07995b350a7046ce07153f6a85d6cb42ee2d756c
[platform/upstream/f2fs-tools.git] / mkfs / f2fs_format_main.c
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 <stdbool.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #ifdef HAVE_SYS_MOUNT_H
19 #include <sys/mount.h>
20 #endif
21 #include <time.h>
22 #include <errno.h>
23 #include <getopt.h>
24
25 #include <f2fs_fs.h>
26
27 #ifdef HAVE_LIBBLKID
28 #include <blkid/blkid.h>
29 #endif
30 #ifdef HAVE_UUID_UUID_H
31 #include <uuid/uuid.h>
32 #endif
33
34 #include "quota.h"
35 #include "f2fs_format_utils.h"
36
37 #ifdef HAVE_SYS_UTSNAME_H
38 #include <sys/utsname.h>
39 #endif
40 #ifdef HAVE_SPARSE_SPARSE_H
41 #include <sparse/sparse.h>
42 extern struct sparse_file *f2fs_sparse_file;
43 #endif
44
45 extern struct f2fs_configuration c;
46 static int force_overwrite = 0;
47
48 INIT_FEATURE_TABLE;
49
50 static void mkfs_usage()
51 {
52         MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
53         MSG(0, "[options]:\n");
54         MSG(0, "  -a heap-based allocation [default:0]\n");
55         MSG(0, "  -c device1[,device2,...] up to 7 additional devices, except meta device\n");
56         MSG(0, "  -d debug level [default:0]\n");
57         MSG(0, "  -e [cold file ext list] e.g. \"mp3,gif,mov\"\n");
58         MSG(0, "  -E [hot file ext list] e.g. \"db\"\n");
59         MSG(0, "  -f force overwrite of the existing filesystem\n");
60         MSG(0, "  -g add default options\n");
61         MSG(0, "  -i extended node bitmap, node ratio is 20%% by default\n");
62         MSG(0, "  -l label\n");
63         MSG(0, "  -U uuid\n");
64         MSG(0, "  -m support zoned block device [default:0]\n");
65         MSG(0, "  -o overprovision percentage [default:auto]\n");
66         MSG(0, "  -O feature1[,feature2,...] e.g. \"encrypt\"\n");
67         MSG(0, "  -C [encoding[:flag1,...]] Support casefolding with optional flags\n");
68         MSG(0, "  -q quiet mode\n");
69         MSG(0, "  -r set checkpointing seed (srand()) to 0\n");
70         MSG(0, "  -R root_owner [default: 0:0]\n");
71         MSG(0, "  -s # of segments per section [default:1]\n");
72         MSG(0, "  -S sparse mode\n");
73         MSG(0, "  -t 0: nodiscard, 1: discard [default:1]\n");
74         MSG(0, "  -T timestamps\n");
75         MSG(0, "  -w wanted sector size\n");
76         MSG(0, "  -z # of sections per zone [default:1]\n");
77         MSG(0, "  -V print the version number and exit\n");
78         MSG(0, "  -Z # of reserved sections [default:auto]\n");
79         MSG(0, "sectors: number of sectors [default: determined by device size]\n");
80         exit(1);
81 }
82
83 static void f2fs_show_info()
84 {
85         MSG(0, "\n    F2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
86                                 F2FS_TOOLS_VERSION,
87                                 F2FS_TOOLS_DATE);
88         if (c.heap == 0)
89                 MSG(0, "Info: Disable heap-based policy\n");
90
91         MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
92         if (c.extension_list[0])
93                 MSG(0, "Info: Add new cold file extension list\n");
94         if (c.extension_list[1])
95                 MSG(0, "Info: Add new hot file extension list\n");
96
97         if (strlen(c.vol_label))
98                 MSG(0, "Info: Label = %s\n", c.vol_label);
99         MSG(0, "Info: Trim is %s\n", c.trim ? "enabled": "disabled");
100
101         if (c.defset == CONF_ANDROID)
102                 MSG(0, "Info: Set conf for android\n");
103
104         if (c.feature & le32_to_cpu(F2FS_FEATURE_CASEFOLD))
105                 MSG(0, "Info: Enable %s with casefolding\n",
106                                         f2fs_encoding2str(c.s_encoding));
107         if (c.feature & le32_to_cpu(F2FS_FEATURE_PRJQUOTA))
108                 MSG(0, "Info: Enable Project quota\n");
109
110         if (c.feature & le32_to_cpu(F2FS_FEATURE_COMPRESSION))
111                 MSG(0, "Info: Enable Compression\n");
112 }
113
114 #if defined(ANDROID_TARGET) && defined(HAVE_SYS_UTSNAME_H)
115 static bool kernel_version_over(unsigned int min_major, unsigned int min_minor)
116 {
117         unsigned int major, minor;
118         struct utsname uts;
119
120         if ((uname(&uts) != 0) ||
121                         (sscanf(uts.release, "%u.%u", &major, &minor) != 2))
122                 return false;
123         if (major > min_major)
124                 return true;
125         if (major == min_major && minor >= min_minor)
126                 return true;
127         return false;
128 }
129 #else
130 static bool kernel_version_over(unsigned int UNUSED(min_major),
131                                 unsigned int UNUSED(min_minor))
132 {
133         return false;
134 }
135 #endif
136
137 static void add_default_options(void)
138 {
139         switch (c.defset) {
140         case CONF_ANDROID:
141                 /* -d1 -f -w 4096 -R 0:0 */
142                 c.dbg_lv = 1;
143                 force_overwrite = 1;
144                 c.wanted_sector_size = 4096;
145                 c.root_uid = c.root_gid = 0;
146
147                 /* RO doesn't need any other features */
148                 if (c.feature & cpu_to_le32(F2FS_FEATURE_RO))
149                         return;
150
151                 /* -O encrypt -O project_quota,extra_attr,{quota} -O verity */
152                 c.feature |= cpu_to_le32(F2FS_FEATURE_ENCRYPT);
153                 if (!kernel_version_over(4, 14))
154                         c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
155                 c.feature |= cpu_to_le32(F2FS_FEATURE_PRJQUOTA);
156                 c.feature |= cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR);
157                 c.feature |= cpu_to_le32(F2FS_FEATURE_VERITY);
158                 break;
159         }
160 #ifdef CONF_CASEFOLD
161         c.s_encoding = F2FS_ENC_UTF8_12_1;
162         c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
163 #endif
164 #ifdef CONF_PROJID
165         c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
166         c.feature |= cpu_to_le32(F2FS_FEATURE_PRJQUOTA);
167         c.feature |= cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR);
168 #endif
169
170         if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO))
171                 c.quota_bits = QUOTA_USR_BIT | QUOTA_GRP_BIT;
172         if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) {
173                 c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
174                 c.quota_bits |= QUOTA_PRJ_BIT;
175         }
176 }
177
178 static void f2fs_parse_options(int argc, char *argv[])
179 {
180         static const char *option_string = "qa:c:C:d:e:E:g:hil:mo:O:rR:s:S:z:t:T:U:Vfw:Z:";
181         static const struct option long_opts[] = {
182                 { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
183                 { .name = NULL, .has_arg = 0, .flag = NULL, .val = 0 }
184         };
185         int32_t option=0;
186         int val;
187         char *token;
188
189         while ((option = getopt_long(argc,argv,option_string,long_opts,NULL)) != EOF) {
190                 switch (option) {
191                 case 'q':
192                         c.dbg_lv = -1;
193                         break;
194                 case 'a':
195                         c.heap = atoi(optarg);
196                         break;
197                 case 'c':
198                         if (c.ndevs >= MAX_DEVICES) {
199                                 MSG(0, "Error: Too many devices\n");
200                                 mkfs_usage();
201                         }
202
203                         if (strlen(optarg) > MAX_PATH_LEN) {
204                                 MSG(0, "Error: device path should be less than "
205                                         "%d characters\n", MAX_PATH_LEN);
206                                 mkfs_usage();
207                         }
208                         c.devices[c.ndevs++].path = strdup(optarg);
209                         break;
210                 case 'd':
211                         c.dbg_lv = atoi(optarg);
212                         break;
213                 case 'e':
214                         c.extension_list[0] = strdup(optarg);
215                         break;
216                 case 'E':
217                         c.extension_list[1] = strdup(optarg);
218                         break;
219                 case 'g':
220                         if (!strcmp(optarg, "android"))
221                                 c.defset = CONF_ANDROID;
222                         break;
223                 case 'h':
224                         mkfs_usage();
225                         break;
226                 case 'i':
227                         c.large_nat_bitmap = 1;
228                         break;
229                 case 'l':               /*v: volume label */
230                         if (strlen(optarg) > 512) {
231                                 MSG(0, "Error: Volume Label should be less than "
232                                                 "512 characters\n");
233                                 mkfs_usage();
234                         }
235                         c.vol_label = optarg;
236                         break;
237                 case 'm':
238                         c.zoned_mode = 1;
239                         break;
240                 case 'o':
241                         c.overprovision = atof(optarg);
242                         break;
243                 case 'O':
244                         if (parse_feature(feature_table, optarg))
245                                 mkfs_usage();
246                         break;
247                 case 'r':
248                         c.fake_seed = 1;
249                         break;
250                 case 'R':
251                         if (parse_root_owner(optarg, &c.root_uid, &c.root_gid))
252                                 mkfs_usage();
253                         break;
254                 case 's':
255                         c.segs_per_sec = atoi(optarg);
256                         break;
257                 case 'S':
258                         c.device_size = atoll(optarg);
259                         c.device_size &= (~((uint64_t)(F2FS_BLKSIZE - 1)));
260                         c.sparse_mode = 1;
261                         break;
262                 case 'z':
263                         c.secs_per_zone = atoi(optarg);
264                         break;
265                 case 't':
266                         c.trim = atoi(optarg);
267                         break;
268                 case 'T':
269                         c.fixed_time = strtoul(optarg, NULL, 0);
270                         break;
271                 case 'U':
272                         c.vol_uuid = strdup(optarg);
273                         break;
274                 case 'f':
275                         force_overwrite = 1;
276                         break;
277                 case 'w':
278                         c.wanted_sector_size = atoi(optarg);
279                         break;
280                 case 'V':
281                         show_version("mkfs.f2fs");
282                         exit(0);
283                 case 'C':
284                         token = strtok(optarg, ":");
285                         val = f2fs_str2encoding(token);
286                         if (val < 0) {
287                                 MSG(0, "\tError: Unknown encoding %s\n", token);
288                                 mkfs_usage();
289                         }
290                         c.s_encoding = val;
291                         token = strtok(NULL, "");
292                         val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags);
293                         if (val) {
294                                 MSG(0, "\tError: Unknown flag %s\n",token);
295                                 mkfs_usage();
296                         }
297                         c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
298                         break;
299                 case 'Z':
300                         c.conf_reserved_sections = atoi(optarg);
301                         break;
302                 default:
303                         MSG(0, "\tError: Unknown option %c\n",option);
304                         mkfs_usage();
305                         break;
306                 }
307         }
308
309         add_default_options();
310
311         if (!(c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR))) {
312                 if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) {
313                         MSG(0, "\tInfo: project quota feature should always be "
314                                 "enabled with extra attr feature\n");
315                         exit(1);
316                 }
317                 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) {
318                         MSG(0, "\tInfo: inode checksum feature should always be "
319                                 "enabled with extra attr feature\n");
320                         exit(1);
321                 }
322                 if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)) {
323                         MSG(0, "\tInfo: flexible inline xattr feature should always be "
324                                 "enabled with extra attr feature\n");
325                         exit(1);
326                 }
327                 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
328                         MSG(0, "\tInfo: inode crtime feature should always be "
329                                 "enabled with extra attr feature\n");
330                         exit(1);
331                 }
332                 if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION)) {
333                         MSG(0, "\tInfo: compression feature should always be "
334                                 "enabled with extra attr feature\n");
335                         exit(1);
336                 }
337         }
338
339         if (optind >= argc) {
340                 MSG(0, "\tError: Device not specified\n");
341                 mkfs_usage();
342         }
343
344         /* [0] : META, [1 to MAX_DEVICES - 1] : NODE/DATA */
345         c.devices[0].path = strdup(argv[optind]);
346
347         if ((optind + 1) < argc) {
348                 if (c.ndevs > 1) {
349                         MSG(0, "\tError: Not support custom size on multi-devs.\n");
350                         mkfs_usage();
351                 }
352                 c.wanted_total_sectors = atoll(argv[optind+1]);
353         }
354
355         if (c.sparse_mode)
356                 c.trim = 0;
357
358         if (c.zoned_mode)
359                 c.feature |= cpu_to_le32(F2FS_FEATURE_BLKZONED);
360 }
361
362 #ifdef HAVE_LIBBLKID
363 static int f2fs_dev_is_overwrite(const char *device)
364 {
365         const char      *type;
366         blkid_probe     pr = NULL;
367         int             ret = -1;
368
369         if (!device || !*device)
370                 return 0;
371
372         pr = blkid_new_probe_from_filename(device);
373         if (!pr)
374                 goto out;
375
376         ret = blkid_probe_enable_partitions(pr, 1);
377         if (ret < 0)
378                 goto out;
379
380         ret = blkid_do_fullprobe(pr);
381         if (ret < 0)
382                 goto out;
383
384         /*
385          * Blkid returns 1 for nothing found and 0 when it finds a signature,
386          * but we want the exact opposite, so reverse the return value here.
387          *
388          * In addition print some useful diagnostics about what actually is
389          * on the device.
390          */
391         if (ret) {
392                 ret = 0;
393                 goto out;
394         }
395
396         if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
397                 MSG(0, "\t%s appears to contain an existing filesystem (%s).\n",
398                         device, type);
399         } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
400                 MSG(0, "\t%s appears to contain a partition table (%s).\n",
401                         device, type);
402         } else {
403                 MSG(0, "\t%s appears to contain something weird according to blkid\n",
404                         device);
405         }
406         ret = 1;
407 out:
408         if (pr)
409                 blkid_free_probe(pr);
410         if (ret == -1)
411                 MSG(0, "\tprobe of %s failed, cannot detect existing filesystem.\n",
412                         device);
413         return ret;
414 }
415
416 static int f2fs_check_overwrite(void)
417 {
418         int i;
419
420         for (i = 0; i < c.ndevs; i++)
421                 if (f2fs_dev_is_overwrite((char *)c.devices[i].path))
422                         return -1;
423         return 0;
424 }
425
426 #else
427
428 static int f2fs_check_overwrite(void)
429 {
430         return 0;
431 }
432
433 #endif /* HAVE_LIBBLKID */
434
435 int main(int argc, char *argv[])
436 {
437         f2fs_init_configuration();
438
439         f2fs_parse_options(argc, argv);
440
441         f2fs_show_info();
442
443         c.func = MKFS;
444
445         if (f2fs_devs_are_umounted() < 0) {
446                 if (errno != EBUSY)
447                         MSG(0, "\tError: Not available on mounted device!\n");
448                 goto err_format;
449         }
450
451         if (f2fs_get_device_info() < 0)
452                 return -1;
453
454         if (f2fs_check_overwrite()) {
455                 char *zero_buf = NULL;
456                 int i;
457
458                 if (!force_overwrite) {
459                         MSG(0, "\tUse the -f option to force overwrite.\n");
460                         goto err_format;
461                 }
462                 zero_buf = calloc(F2FS_BLKSIZE, 1);
463                 if (!zero_buf) {
464                         MSG(0, "\tError: Fail to allocate zero buffer.\n");
465                         goto err_format;
466                 }
467                 /* wipe out other FS magics mostly first 4MB space */
468                 for (i = 0; i < 1024; i++)
469                         if (dev_fill_block(zero_buf, i))
470                                 break;
471                 free(zero_buf);
472                 if (i != 1024) {
473                         MSG(0, "\tError: Fail to fill zeros till %d.\n", i);
474                         goto err_format;
475                 }
476                 if (f2fs_fsync_device())
477                         goto err_format;
478         }
479
480         if (f2fs_get_f2fs_info() < 0)
481                 goto err_format;
482
483         /*
484          * Some options are mandatory for host-managed
485          * zoned block devices.
486          */
487         if (c.zoned_model != F2FS_ZONED_NONE && !c.zoned_mode) {
488                 MSG(0, "\tError: zoned block device feature is required\n");
489                 goto err_format;
490         }
491
492         if (c.zoned_mode && !c.trim) {
493                 MSG(0, "\tError: Trim is required for zoned block devices\n");
494                 goto err_format;
495         }
496
497         if (c.conf_reserved_sections && !c.zoned_mode) {
498                 MSG(0, "\tError: Reserved area can't be specified on non zoned device\n");
499                 goto err_format;
500         }
501
502         if (f2fs_format_device() < 0)
503                 goto err_format;
504
505         if (f2fs_finalize_device() < 0)
506                 goto err_format;
507
508         MSG(0, "Info: format successful\n");
509
510         return 0;
511
512 err_format:
513         f2fs_release_sparse_resource();
514         return -1;
515 }