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