• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * f2fs_format.c
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5  *             http://www.samsung.com/
6  *
7  * Dual licensed under the GPL or LGPL version 2 licenses.
8  */
9 #define _LARGEFILE64_SOURCE
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <sys/mount.h>
18 #include <time.h>
19 #include <uuid/uuid.h>
20 #include <errno.h>
21 
22 #include "config.h"
23 #ifdef HAVE_LIBBLKID
24 #  include <blkid/blkid.h>
25 #endif
26 
27 #include "f2fs_fs.h"
28 #include "f2fs_format_utils.h"
29 
30 #ifdef WITH_ANDROID
31 #include <sparse/sparse.h>
32 extern struct sparse_file *f2fs_sparse_file;
33 #endif
34 
35 extern struct f2fs_configuration c;
36 static int force_overwrite = 0;
37 
mkfs_usage()38 static void mkfs_usage()
39 {
40 	MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
41 	MSG(0, "[options]:\n");
42 	MSG(0, "  -a heap-based allocation [default:0]\n");
43 	MSG(0, "  -c [device path] up to 7 devices excepts meta device\n");
44 	MSG(0, "  -d debug level [default:0]\n");
45 	MSG(0, "  -e [extension list] e.g. \"mp3,gif,mov\"\n");
46 	MSG(0, "  -f force overwrite the exist filesystem\n");
47 	MSG(0, "  -l label\n");
48 	MSG(0, "  -m support zoned block device [default:0]\n");
49 	MSG(0, "  -o overprovision ratio [default:5]\n");
50 	MSG(0, "  -O [feature list] e.g. \"encrypt\"\n");
51 	MSG(0, "  -q quiet mode\n");
52 	MSG(0, "  -s # of segments per section [default:1]\n");
53 	MSG(0, "  -S sparse mode\n");
54 	MSG(0, "  -t 0: nodiscard, 1: discard [default:1]\n");
55 	MSG(0, "  -z # of sections per zone [default:1]\n");
56 	MSG(0, "sectors: number of sectors. [default: determined by device size]\n");
57 	exit(1);
58 }
59 
f2fs_show_info()60 static void f2fs_show_info()
61 {
62 	MSG(0, "\n\tF2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
63 				F2FS_TOOLS_VERSION,
64 				F2FS_TOOLS_DATE);
65 	if (c.heap == 0)
66 		MSG(0, "Info: Disable heap-based policy\n");
67 
68 	MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
69 	if (c.extension_list)
70 		MSG(0, "Info: Add new extension list\n");
71 
72 	if (c.vol_label)
73 		MSG(0, "Info: Label = %s\n", c.vol_label);
74 	MSG(0, "Info: Trim is %s\n", c.trim ? "enabled": "disabled");
75 }
76 
parse_feature(const char * features)77 static void parse_feature(const char *features)
78 {
79 	while (*features == ' ')
80 		features++;
81 	if (!strcmp(features, "encrypt")) {
82 		c.feature |= cpu_to_le32(F2FS_FEATURE_ENCRYPT);
83 	} else {
84 		MSG(0, "Error: Wrong features\n");
85 		mkfs_usage();
86 	}
87 }
88 
f2fs_parse_options(int argc,char * argv[])89 static void f2fs_parse_options(int argc, char *argv[])
90 {
91 	static const char *option_string = "qa:c:d:e:l:mo:O:s:S:z:t:f";
92 	int32_t option=0;
93 
94 	while ((option = getopt(argc,argv,option_string)) != EOF) {
95 		switch (option) {
96 		case 'q':
97 			c.dbg_lv = -1;
98 			break;
99 		case 'a':
100 			c.heap = atoi(optarg);
101 			break;
102 		case 'c':
103 			if (c.ndevs >= MAX_DEVICES) {
104 				MSG(0, "Error: Too many devices\n");
105 				mkfs_usage();
106 			}
107 
108 			if (strlen(optarg) > MAX_PATH_LEN) {
109 				MSG(0, "Error: device path should be less than "
110 					"%d characters\n", MAX_PATH_LEN);
111 				mkfs_usage();
112 			}
113 			c.devices[c.ndevs++].path = strdup(optarg);
114 			break;
115 		case 'd':
116 			c.dbg_lv = atoi(optarg);
117 			break;
118 		case 'e':
119 			c.extension_list = strdup(optarg);
120 			break;
121 		case 'l':		/*v: volume label */
122 			if (strlen(optarg) > 512) {
123 				MSG(0, "Error: Volume Label should be less than "
124 						"512 characters\n");
125 				mkfs_usage();
126 			}
127 			c.vol_label = optarg;
128 			break;
129 		case 'm':
130 			c.zoned_mode = 1;
131 			break;
132 		case 'o':
133 			c.overprovision = atof(optarg);
134 			break;
135 		case 'O':
136 			parse_feature(optarg);
137 			break;
138 		case 's':
139 			c.segs_per_sec = atoi(optarg);
140 			break;
141 		case 'S':
142 			c.device_size = atoll(optarg);
143 			c.device_size &= (~((u_int64_t)(F2FS_BLKSIZE - 1)));
144 			c.sparse_mode = 1;
145 			break;
146 		case 'z':
147 			c.secs_per_zone = atoi(optarg);
148 			break;
149 		case 't':
150 			c.trim = atoi(optarg);
151 			break;
152 		case 'f':
153 			force_overwrite = 1;
154 			break;
155 		default:
156 			MSG(0, "\tError: Unknown option %c\n",option);
157 			mkfs_usage();
158 			break;
159 		}
160 	}
161 
162 	if (optind >= argc) {
163 		MSG(0, "\tError: Device not specified\n");
164 		mkfs_usage();
165 	}
166 
167 	/* [0] : META, [1 to MAX_DEVICES - 1] : NODE/DATA */
168 	c.devices[0].path = strdup(argv[optind]);
169 
170 	if ((optind + 1) < argc) {
171 		if (c.ndevs > 1) {
172 			MSG(0, "\tError: Not support custom size on multi-devs.\n");
173 			mkfs_usage();
174 		}
175 		c.wanted_total_sectors = atoll(argv[optind+1]);
176 	}
177 
178 	if (c.sparse_mode)
179 		c.trim = 0;
180 
181 	if (c.zoned_mode)
182 		c.feature |= cpu_to_le32(F2FS_FEATURE_BLKZONED);
183 }
184 
185 #ifdef HAVE_LIBBLKID
f2fs_dev_is_overwrite(const char * device)186 static int f2fs_dev_is_overwrite(const char *device)
187 {
188 	const char	*type;
189 	blkid_probe	pr = NULL;
190 	int		ret = -1;
191 
192 	if (!device || !*device)
193 		return 0;
194 
195 	pr = blkid_new_probe_from_filename(device);
196 	if (!pr)
197 		goto out;
198 
199 	ret = blkid_probe_enable_partitions(pr, 1);
200 	if (ret < 0)
201 		goto out;
202 
203 	ret = blkid_do_fullprobe(pr);
204 	if (ret < 0)
205 		goto out;
206 
207 	/*
208 	 * Blkid returns 1 for nothing found and 0 when it finds a signature,
209 	 * but we want the exact opposite, so reverse the return value here.
210 	 *
211 	 * In addition print some useful diagnostics about what actually is
212 	 * on the device.
213 	 */
214 	if (ret) {
215 		ret = 0;
216 		goto out;
217 	}
218 
219 	if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
220 		MSG(0, "\t%s appears to contain an existing filesystem (%s).\n",
221 			device, type);
222 	} else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
223 		MSG(0, "\t%s appears to contain a partition table (%s).\n",
224 			device, type);
225 	} else {
226 		MSG(0, "\t%s appears to contain something weird according to blkid\n",
227 			device);
228 	}
229 	ret = 1;
230 out:
231 	if (pr)
232 		blkid_free_probe(pr);
233 	if (ret == -1)
234 		MSG(0, "\tprobe of %s failed, cannot detect existing filesystem.\n",
235 			device);
236 	return ret;
237 }
238 
f2fs_check_overwrite(void)239 static int f2fs_check_overwrite(void)
240 {
241 	int i;
242 
243 	for (i = 0; i < c.ndevs; i++)
244 		if (f2fs_dev_is_overwrite((char *)c.devices[i].path))
245 			return -1;
246 	return 0;
247 }
248 
249 #else
250 
f2fs_check_overwrite(void)251 static int f2fs_check_overwrite(void)
252 {
253 	return 0;
254 }
255 
256 #endif /* HAVE_LIBBLKID */
257 
main(int argc,char * argv[])258 int main(int argc, char *argv[])
259 {
260 	f2fs_init_configuration();
261 
262 	f2fs_parse_options(argc, argv);
263 
264 	f2fs_show_info();
265 
266 	if (!force_overwrite && f2fs_check_overwrite()) {
267 		MSG(0, "\tUse the -f option to force overwrite.\n");
268 		return -1;
269 	}
270 
271 	if (f2fs_devs_are_umounted() < 0) {
272 		if (errno != EBUSY)
273 			MSG(0, "\tError: Not available on mounted device!\n");
274 		return -1;
275 	}
276 
277 	if (f2fs_get_device_info() < 0)
278 		return -1;
279 
280 	/*
281 	 * Some options are mandatory for host-managed
282 	 * zoned block devices.
283 	 */
284 	if (c.zoned_model == F2FS_ZONED_HM && !c.zoned_mode) {
285 		MSG(0, "\tError: zoned block device feature is required\n");
286 		return -1;
287 	}
288 
289 	if (c.zoned_mode && !c.trim) {
290 		MSG(0, "\tError: Trim is required for zoned block devices\n");
291 		return -1;
292 	}
293 
294 	if (c.sparse_mode) {
295 #ifndef WITH_ANDROID
296 		MSG(0, "\tError: Sparse mode is only supported for android\n");
297 		return -1;
298 #else
299 		if (f2fs_sparse_file)
300 			sparse_file_destroy(f2fs_sparse_file);
301 		f2fs_sparse_file = sparse_file_new(F2FS_BLKSIZE, c.device_size);
302 #endif
303 	}
304 
305 	if (f2fs_format_device() < 0)
306 		return -1;
307 
308 	f2fs_finalize_device();
309 
310 	MSG(0, "Info: format successful\n");
311 
312 	return 0;
313 }
314