4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
7 * : implement defrag.f2fs
8 * Copyright (C) 2015 Huawei Ltd.
9 * Hou Pengyang <houpengyang@huawei.com>
10 * Liu Shuoran <liushuoran@huawei.com>
11 * Jaegeuk Kim <jaegeuk@kernel.org>
13 * Copyright (c) 2019 Google Inc.
14 * Robin Hsu <robinhsu@google.com>
16 * Copyright (c) 2020 Google Inc.
17 * Robin Hsu <robinhsu@google.com>
18 * : add sload compression support
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2 as
22 * published by the Free Software Foundation.
33 struct f2fs_fsck gfsck;
38 static char *absolute_path(const char *file)
44 if (getcwd(cwd, PATH_MAX) == NULL) {
45 fprintf(stderr, "Failed to getcwd\n");
48 ret = malloc(strlen(cwd) + 1 + strlen(file) + 1);
50 sprintf(ret, "%s/%s", cwd, file);
59 MSG(0, "\nUsage: fsck.f2fs [options] device\n");
60 MSG(0, "[options]:\n");
61 MSG(0, " -a check/fix potential corruption, reported by f2fs\n");
62 MSG(0, " -c <num-cache-entry> set number of cache entries"
64 MSG(0, " -m <max-hash-collision> set max cache hash collision"
66 MSG(0, " -C encoding[:flag1,flag2] Set options for enabling"
68 MSG(0, " -d debug level [default:0]\n");
69 MSG(0, " -f check/fix entire partition\n");
70 MSG(0, " -g add default options\n");
71 MSG(0, " -l show superblock/checkpoint\n");
72 MSG(0, " -M show a file map\n");
73 MSG(0, " -O feature1[feature2,feature3,...] e.g. \"encrypt\"\n");
74 MSG(0, " -p preen mode [default:0 the same as -a [0|1|2]]\n");
75 MSG(0, " -S sparse_mode\n");
76 MSG(0, " -t show directory tree\n");
77 MSG(0, " -q preserve quota limits\n");
78 MSG(0, " -y fix all the time\n");
79 MSG(0, " -V print the version number and exit\n");
80 MSG(0, " --dry-run do not really fix corruptions\n");
81 MSG(0, " --no-kernel-check skips detecting kernel change\n");
82 MSG(0, " --kernel-check checks kernel change\n");
83 MSG(0, " --debug-cache to debug cache when -c is used\n");
89 MSG(0, "\nUsage: dump.f2fs [options] device\n");
90 MSG(0, "[options]:\n");
91 MSG(0, " -d debug level [default:0]\n");
92 MSG(0, " -i inode no (hex)\n");
93 MSG(0, " -I inode no (hex) scan full disk\n");
94 MSG(0, " -n [NAT dump nid from #1~#2 (decimal), for all 0~-1]\n");
95 MSG(0, " -M show a block map\n");
96 MSG(0, " -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]\n");
97 MSG(0, " -S sparse_mode\n");
98 MSG(0, " -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]\n");
99 MSG(0, " -b blk_addr (in 4KB)\n");
100 MSG(0, " -V print the version number and exit\n");
107 MSG(0, "\nUsage: defrag.f2fs [options] device\n");
108 MSG(0, "[options]:\n");
109 MSG(0, " -d debug level [default:0]\n");
110 MSG(0, " -s start block address [default: main_blkaddr]\n");
111 MSG(0, " -S sparse_mode\n");
112 MSG(0, " -l length [default:512 (2MB)]\n");
113 MSG(0, " -t target block address [default: main_blkaddr + 2MB]\n");
114 MSG(0, " -i set direction as shrink [default: expand]\n");
115 MSG(0, " -V print the version number and exit\n");
121 MSG(0, "\nUsage: resize.f2fs [options] device\n");
122 MSG(0, "[options]:\n");
123 MSG(0, " -d debug level [default:0]\n");
124 MSG(0, " -i extended node bitmap, node ratio is 20%% by default\n");
125 MSG(0, " -o overprovision percentage [default:auto]\n");
126 MSG(0, " -s safe resize (Does not resize metadata)\n");
127 MSG(0, " -t target sectors [default: device size]\n");
128 MSG(0, " -V print the version number and exit\n");
134 MSG(0, "\nUsage: sload.f2fs [options] device\n");
135 MSG(0, "[options]:\n");
136 MSG(0, " -C fs_config\n");
137 MSG(0, " -f source directory [path of the source directory]\n");
138 MSG(0, " -p product out directory\n");
139 MSG(0, " -s file_contexts\n");
140 MSG(0, " -S sparse_mode\n");
141 MSG(0, " -t mount point [prefix of target fs path, default:/]\n");
142 MSG(0, " -T timestamp\n");
143 MSG(0, " -P preserve owner: user and group\n");
144 MSG(0, " -c enable compression (default allow policy)\n");
145 MSG(0, " ------------ Compression sub-options -----------------\n");
146 MSG(0, " -L <log-of-blocks-per-cluster>, default 2\n");
147 MSG(0, " -a <algorithm> compression algorithm, default LZ4\n");
148 MSG(0, " -x <ext> compress files except for these extensions.\n");
149 MSG(0, " -i <ext> compress files with these extensions only.\n");
150 MSG(0, " * -i or -x: use it many times for multiple extensions.\n");
151 MSG(0, " * -i and -x cannot be used together..\n");
152 MSG(0, " -m <num> min compressed blocks per cluster\n");
153 MSG(0, " -r read only (to release unused blocks) for compressed "
155 MSG(0, " ------------------------------------------------------\n");
156 MSG(0, " -d debug level [default:0]\n");
157 MSG(0, " -V print the version number and exit\n");
163 MSG(0, "\nUsage: f2fslabel [options] device [volume-label]\n");
164 MSG(0, "[options]:\n");
165 MSG(0, " -V print the version number and exit\n");
169 static int is_digits(char *optarg)
173 for (i = 0; i < strlen(optarg); i++)
174 if (!isdigit(optarg[i]))
176 return i == strlen(optarg);
179 static void error_out(char *prog)
181 if (!strcmp("fsck.f2fs", prog))
183 else if (!strcmp("dump.f2fs", prog))
185 else if (!strcmp("defrag.f2fs", prog))
187 else if (!strcmp("resize.f2fs", prog))
189 else if (!strcmp("sload.f2fs", prog))
191 else if (!strcmp("f2fslabel", prog))
194 MSG(0, "\nWrong program.\n");
197 static void __add_fsck_options(void)
203 static void add_default_options(void)
207 __add_fsck_options();
212 void f2fs_parse_options(int argc, char *argv[])
215 char *prog = basename(argv[0]);
220 /* Allow prog names (e.g, sload_f2fs, fsck_f2fs, etc) */
221 for (i = 0; i < strlen(prog); i++) {
227 MSG(0, "\tError: Device not specified\n");
231 if (!strcmp("fsck.f2fs", prog)) {
232 const char *option_string = ":aC:c:m:Md:fg:lO:p:q:StyV";
235 struct option long_opt[] = {
236 {"dry-run", no_argument, 0, 1},
237 {"no-kernel-check", no_argument, 0, 2},
238 {"kernel-check", no_argument, 0, 3},
239 {"debug-cache", no_argument, 0, 4},
244 c.cache_config.max_hash_collision = 16;
245 c.cache_config.dbg_en = false;
246 while ((option = getopt_long(argc, argv, option_string,
247 long_opt, &opt)) != EOF) {
251 MSG(0, "Info: Dry run\n");
254 c.no_kernel_check = 1;
255 MSG(0, "Info: No Kernel Check\n");
258 c.no_kernel_check = 0;
259 MSG(0, "Info: Do Kernel Check\n");
262 c.cache_config.dbg_en = true;
266 MSG(0, "Info: Fix the reported corruption.\n");
269 c.cache_config.num_cache_entry = atoi(optarg);
272 c.cache_config.max_hash_collision =
276 if (!strcmp(optarg, "android")) {
277 c.defset = CONF_ANDROID;
278 MSG(0, "Info: Set conf for android\n");
288 if (parse_feature(feature_table, optarg))
292 /* preen mode has different levels:
293 * 0: default level, the same as -a
295 * 2: same as 0, but will skip some
296 * check for old kernel
298 if (optarg[0] == '-' || !is_digits(optarg) ||
300 MSG(0, "Info: Use default preen mode\n");
301 c.preen_mode = PREEN_MODE_0;
306 c.preen_mode = atoi(optarg);
307 if (c.preen_mode < 0)
308 c.preen_mode = PREEN_MODE_0;
309 else if (c.preen_mode >= PREEN_MODE_MAX)
310 c.preen_mode = PREEN_MODE_MAX - 1;
311 if (c.preen_mode == PREEN_MODE_0 ||
312 c.preen_mode == PREEN_MODE_2)
314 MSG(0, "Info: Fix the reported corruption in "
315 "preen mode %d\n", c.preen_mode);
318 if (optarg[0] == '-') {
321 } else if (!is_digits(optarg)) {
325 c.dbg_lv = atoi(optarg);
326 MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
332 MSG(0, "Info: Force to fix corruption\n");
335 c.preserve_limits = atoi(optarg);
336 MSG(0, "Info: Preserve quota limits = %d\n",
347 MSG(0, "Info: Use default preen mode\n");
348 c.preen_mode = PREEN_MODE_0;
357 token = strtok(optarg, ":");
358 val = f2fs_str2encoding(token);
360 MSG(0, "\tError: Unknown encoding %s\n", token);
364 token = strtok(NULL, "");
365 val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags);
367 MSG(0, "\tError: Unknown flag %s\n", token);
370 c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
385 } else if (!strcmp("dump.f2fs", prog)) {
387 const char *option_string = "d:i:I:n:Ms:Sa:b:V";
388 static struct dump_option dump_opt = {
389 .nid = 0, /* default root ino */
401 while ((option = getopt(argc, argv, option_string)) != EOF) {
406 if (!is_digits(optarg)) {
410 c.dbg_lv = atoi(optarg);
411 MSG(0, "Info: Debug level = %d\n",
415 if (strncmp(optarg, "0x", 2))
416 ret = sscanf(optarg, "%d",
419 ret = sscanf(optarg, "%x",
423 if (strncmp(optarg, "0x", 2))
424 ret = sscanf(optarg, "%d",
427 ret = sscanf(optarg, "%x",
431 ret = sscanf(optarg, "%d~%d",
439 ret = sscanf(optarg, "%d~%d",
447 ret = sscanf(optarg, "%d~%d",
452 if (strncmp(optarg, "0x", 2))
453 ret = sscanf(optarg, "%d",
456 ret = sscanf(optarg, "%x",
471 c.private = &dump_opt;
473 } else if (!strcmp("defrag.f2fs", prog)) {
475 const char *option_string = "d:s:Sl:t:iV";
478 while ((option = getopt(argc, argv, option_string)) != EOF) {
483 if (!is_digits(optarg)) {
487 c.dbg_lv = atoi(optarg);
488 MSG(0, "Info: Debug level = %d\n",
492 if (strncmp(optarg, "0x", 2))
493 ret = sscanf(optarg, "%"PRIu64"",
496 ret = sscanf(optarg, "%"PRIx64"",
503 if (strncmp(optarg, "0x", 2))
504 ret = sscanf(optarg, "%"PRIu64"",
507 ret = sscanf(optarg, "%"PRIx64"",
511 if (strncmp(optarg, "0x", 2))
512 ret = sscanf(optarg, "%"PRIu64"",
515 ret = sscanf(optarg, "%"PRIx64"",
533 } else if (!strcmp("resize.f2fs", prog)) {
535 const char *option_string = "d:fst:io:V";
538 while ((option = getopt(argc, argv, option_string)) != EOF) {
543 if (!is_digits(optarg)) {
547 c.dbg_lv = atoi(optarg);
548 MSG(0, "Info: Debug level = %d\n",
553 MSG(0, "Info: Force to resize\n");
559 if (strncmp(optarg, "0x", 2))
560 ret = sscanf(optarg, "%"PRIu64"",
563 ret = sscanf(optarg, "%"PRIx64"",
567 c.large_nat_bitmap = 1;
570 c.new_overprovision = atof(optarg);
584 } else if (!strcmp("sload.f2fs", prog)) {
586 const char *option_string = "cL:a:i:x:m:rC:d:f:p:s:St:T:VP";
587 #ifdef HAVE_LIBSELINUX
588 int max_nr_opt = (int)sizeof(c.seopt_file) /
589 sizeof(c.seopt_file[0]);
595 c.compress.cc.log_cluster_size = 2;
596 c.compress.alg = COMPR_LZ4;
597 c.compress.min_blocks = 1;
598 c.compress.filter_ops = &ext_filter;
599 while ((option = getopt(argc, argv, option_string)) != EOF) {
604 case 'c': /* compression support */
605 c.compress.enabled = true;
607 case 'L': /* compression: log of blocks-per-cluster */
608 c.compress.required = true;
610 if (val < MIN_COMPRESS_LOG_SIZE ||
611 val > MAX_COMPRESS_LOG_SIZE) {
612 MSG(0, "\tError: log of blocks per"
613 " cluster must be in the range"
615 MIN_COMPRESS_LOG_SIZE,
616 MAX_COMPRESS_LOG_SIZE);
619 c.compress.cc.log_cluster_size = val;
621 case 'a': /* compression: choose algorithm */
622 c.compress.required = true;
623 c.compress.alg = MAX_COMPRESS_ALGS;
624 for (i = 0; i < MAX_COMPRESS_ALGS; i++) {
625 if (!strcmp(supported_comp_names[i],
631 if (c.compress.alg == MAX_COMPRESS_ALGS) {
632 MSG(0, "\tError: Unknown compression"
633 " algorithm %s\n", optarg);
637 case 'i': /* compress only these extensions */
638 c.compress.required = true;
639 if (c.compress.filter == COMPR_FILTER_ALLOW) {
640 MSG(0, "\tError: could not mix option"
644 c.compress.filter = COMPR_FILTER_DENY;
645 c.compress.filter_ops->add(optarg);
647 case 'x': /* compress except for these extensions */
648 c.compress.required = true;
649 if (c.compress.filter == COMPR_FILTER_DENY) {
650 MSG(0, "\tError: could not mix option"
654 c.compress.filter = COMPR_FILTER_ALLOW;
655 c.compress.filter_ops->add(optarg);
657 case 'm': /* minimum compressed blocks per cluster */
658 c.compress.required = true;
661 MSG(0, "\tError: minimum compressed"
662 " blocks per cluster must be"
666 c.compress.min_blocks = val;
668 case 'r': /* for setting FI_COMPRESS_RELEASED */
669 c.compress.required = true;
670 c.compress.readonly = true;
673 c.fs_config_file = absolute_path(optarg);
676 if (!is_digits(optarg)) {
680 c.dbg_lv = atoi(optarg);
681 MSG(0, "Info: Debug level = %d\n",
685 c.from_dir = absolute_path(optarg);
688 c.target_out_dir = absolute_path(optarg);
691 #ifdef HAVE_LIBSELINUX
692 token = strtok(optarg, ",");
694 if (c.nr_opt == max_nr_opt) {
695 MSG(0, "\tError: Expected at most %d selinux opts\n",
699 c.seopt_file[c.nr_opt].type =
701 c.seopt_file[c.nr_opt].value =
702 absolute_path(token);
704 token = strtok(NULL, ",");
707 MSG(0, "Info: Not support selinux opts\n");
714 c.mount_point = (char *)optarg;
717 c.fixed_time = strtoul(optarg, &p, 0);
723 c.preserve_perms = 1;
732 if (c.compress.required && !c.compress.enabled) {
733 MSG(0, "\tError: compression sub-options are used"
734 " without the compression enable (-c) option\n"
738 if (err == NOERROR && c.compress.enabled) {
739 c.compress.cc.cluster_size = 1
740 << c.compress.cc.log_cluster_size;
741 if (c.compress.filter == COMPR_FILTER_UNASSIGNED)
742 c.compress.filter = COMPR_FILTER_ALLOW;
743 if (c.compress.min_blocks >=
744 c.compress.cc.cluster_size) {
745 MSG(0, "\tError: minimum reduced blocks by"
746 " compression per cluster must be at"
747 " most one less than blocks per"
748 " cluster, i.e. %d\n",
749 c.compress.cc.cluster_size - 1);
753 #endif /* WITH_SLOAD */
754 } else if (!strcmp("f2fslabel", prog)) {
756 const char *option_string = "V";
759 while ((option = getopt(argc, argv, option_string)) != EOF) {
772 if (argc > (optind + 2)) { /* unknown argument(s) is(are) passed */
775 } else if (argc == (optind + 2)) { /* change label */
776 c.vol_label = argv[optind + 1];
778 } else { /* print label */
780 * Since vol_label was initialized as "", in order to
781 * distinguish between clear label and print, set
782 * vol_label as NULL for print case
786 #endif /* WITH_LABEL */
789 if (err == NOERROR) {
790 add_default_options();
792 if (optind >= argc) {
793 MSG(0, "\tError: Device not specified\n");
797 c.devices[0].path = strdup(argv[optind]);
798 if (argc > (optind + 1)) {
806 /* print out error */
809 MSG(0, "\tError: Wrong option -%c %s\n", option, optarg);
812 MSG(0, "\tError: Need argument for -%c\n", option);
815 MSG(0, "\tError: Unknown option %c\n", option);
818 MSG(0, "\tError: Unknown argument %s\n", argv[optind]);
824 static int do_fsck(struct f2fs_sb_info *sbi)
826 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
827 u32 flag = le32_to_cpu(ckpt->ckpt_flags);
829 struct f2fs_compr_blk_cnt cbc;
834 print_cp_state(flag);
836 fsck_chk_and_fix_write_pointers(sbi);
838 fsck_chk_curseg_info(sbi);
840 if (!c.fix_on && !c.bug_on) {
841 switch (c.preen_mode) {
843 if (fsck_chk_meta(sbi)) {
844 MSG(0, "[FSCK] F2FS metadata [Fail]");
845 MSG(0, "\tError: meta does not match, "
846 "force check all\n");
848 MSG(0, "[FSCK] F2FS metadata [Ok..]");
857 } else if (c.preen_mode) {
859 * we can hit this in 3 situations:
860 * 1. fsck -f, fix_on has already been set to 1 when
862 * 2. fsck -a && CP_FSCK_FLAG is set, fix_on has already
863 * been set to 1 when checking CP_FSCK_FLAG;
864 * 3. fsck -p 1 && error is detected, then bug_on is set,
865 * we set fix_on = 1 here, so that fsck can fix errors
871 fsck_chk_checkpoint(sbi);
873 fsck_chk_quota_node(sbi);
875 /* Traverse all block recursively from root inode */
878 cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
880 if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO)) {
881 ret = quota_init_context(sbi);
883 ASSERT_MSG("quota_init_context failure: %d", ret);
884 return FSCK_OPERATIONAL_ERROR;
887 fsck_chk_orphan_node(sbi);
889 if (fsck_sanity_check_nat(sbi, sbi->root_ino_num))
890 fsck_chk_root_inode(sbi);
892 fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
893 F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, NULL);
894 fsck_chk_quota_files(sbi);
896 ret = fsck_verify(sbi);
902 return FSCK_ERROR_CORRECTED;
903 return FSCK_ERRORS_LEFT_UNCORRECTED;
907 static void do_dump(struct f2fs_sb_info *sbi)
909 struct dump_option *opt = (struct dump_option *)c.private;
910 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
911 u32 flag = le32_to_cpu(ckpt->ckpt_flags);
913 if (opt->end_nat == -1)
914 opt->end_nat = NM_I(sbi)->max_nid;
915 if (opt->end_sit == -1)
916 opt->end_sit = SM_I(sbi)->main_segments;
917 if (opt->end_ssa == -1)
918 opt->end_ssa = SM_I(sbi)->main_segments;
919 if (opt->start_nat != -1)
920 nat_dump(sbi, opt->start_nat, opt->end_nat);
921 if (opt->start_sit != -1)
922 sit_dump(sbi, opt->start_sit, opt->end_sit);
923 if (opt->start_ssa != -1)
924 ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
925 if (opt->blk_addr != -1)
926 dump_info_from_blkaddr(sbi, opt->blk_addr);
928 dump_node(sbi, opt->nid, 0);
930 dump_node_scan_disk(sbi, opt->scan_nid);
932 print_cp_state(flag);
938 static int do_defrag(struct f2fs_sb_info *sbi)
940 struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
942 if (get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) {
943 MSG(0, "Not support on readonly image.\n");
947 if (c.defrag_start > get_sb(block_count))
949 if (c.defrag_start < SM_I(sbi)->main_blkaddr)
950 c.defrag_start = SM_I(sbi)->main_blkaddr;
952 if (c.defrag_len == 0)
953 c.defrag_len = sbi->blocks_per_seg;
955 if (c.defrag_start + c.defrag_len > get_sb(block_count))
956 c.defrag_len = get_sb(block_count) - c.defrag_start;
958 if (c.defrag_target == 0) {
959 c.defrag_target = c.defrag_start - 1;
960 if (!c.defrag_shrink)
961 c.defrag_target += c.defrag_len + 1;
964 if (c.defrag_target < SM_I(sbi)->main_blkaddr ||
965 c.defrag_target > get_sb(block_count))
967 if (c.defrag_target >= c.defrag_start &&
968 c.defrag_target < c.defrag_start + c.defrag_len)
971 if (c.defrag_start > c.defrag_target)
972 MSG(0, "Info: Move 0x%"PRIx64" <- [0x%"PRIx64"-0x%"PRIx64"]\n",
975 c.defrag_start + c.defrag_len - 1);
977 MSG(0, "Info: Move [0x%"PRIx64"-0x%"PRIx64"] -> 0x%"PRIx64"\n",
979 c.defrag_start + c.defrag_len - 1,
982 return f2fs_defragment(sbi, c.defrag_start, c.defrag_len,
983 c.defrag_target, c.defrag_shrink);
985 ASSERT_MSG("Out-of-range [0x%"PRIx64" ~ 0x%"PRIx64"] to 0x%"PRIx64"",
987 c.defrag_start + c.defrag_len - 1,
994 static int do_resize(struct f2fs_sb_info *sbi)
996 if (!c.target_sectors)
997 c.target_sectors = c.total_sectors;
999 if (c.target_sectors > c.total_sectors) {
1000 ASSERT_MSG("Out-of-range Target=0x%"PRIx64" / 0x%"PRIx64"",
1001 c.target_sectors, c.total_sectors);
1005 return f2fs_resize(sbi);
1010 static int init_compr(struct f2fs_sb_info *sbi)
1012 if (!c.compress.enabled)
1015 if (!(sbi->raw_super->feature
1016 & cpu_to_le32(F2FS_FEATURE_COMPRESSION))) {
1017 MSG(0, "Error: Compression (-c) was requested "
1018 "but the file system is not created "
1019 "with such feature.\n");
1022 if (!supported_comp_ops[c.compress.alg].init) {
1023 MSG(0, "Error: The selected compression algorithm is not"
1027 c.compress.ops = supported_comp_ops + c.compress.alg;
1028 c.compress.ops->init(&c.compress.cc);
1029 c.compress.ops->reset(&c.compress.cc);
1030 c.compress.cc.rlen = c.compress.cc.cluster_size * F2FS_BLKSIZE;
1034 static int do_sload(struct f2fs_sb_info *sbi)
1037 MSG(0, "Info: No source directory, but it's okay.\n");
1041 c.mount_point = "/";
1043 if (init_compr(sbi))
1046 return f2fs_sload(sbi);
1051 static int do_label(struct f2fs_sb_info *sbi)
1053 struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
1056 char label[MAX_VOLUME_NAME];
1058 utf16_to_utf8(label, (const char *)sb->volume_name,
1059 MAX_VOLUME_NAME, MAX_VOLUME_NAME);
1060 MSG(0, "Info: volume label = %s\n", label);
1064 if (strlen(c.vol_label) > MAX_VOLUME_NAME) {
1065 ERR_MSG("Label should not exceed %d characters\n", MAX_VOLUME_NAME);
1069 utf8_to_utf16((char *)sb->volume_name, (const char *)c.vol_label,
1070 MAX_VOLUME_NAME, strlen(c.vol_label));
1072 update_superblock(sb, SB_MASK_ALL);
1074 MSG(0, "Info: volume label is changed to %s\n", c.vol_label);
1080 #ifdef HAVE_MACH_TIME_H
1081 static u64 get_boottime_ns()
1083 return mach_absolute_time();
1085 #elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_BOOTTIME)
1086 static u64 get_boottime_ns()
1089 t.tv_sec = t.tv_nsec = 0;
1090 clock_gettime(CLOCK_BOOTTIME, &t);
1091 return (u64)t.tv_sec * 1000000000LL + t.tv_nsec;
1094 static u64 get_boottime_ns()
1100 int main(int argc, char **argv)
1102 struct f2fs_sb_info *sbi;
1104 u64 start = get_boottime_ns();
1106 f2fs_init_configuration();
1108 f2fs_parse_options(argc, argv);
1110 if (c.func != DUMP && f2fs_devs_are_umounted() < 0) {
1111 if (errno == EBUSY) {
1114 ret = FSCK_OPERATIONAL_ERROR;
1117 if (!c.ro || c.func == DEFRAG) {
1118 MSG(0, "\tError: Not available on mounted device!\n");
1121 ret = FSCK_OPERATIONAL_ERROR;
1125 /* allow ro-mounted partition */
1127 MSG(0, "Info: Force to check/repair FS on RO mounted device\n");
1129 MSG(0, "Info: Check FS only on RO mounted device\n");
1136 if (f2fs_get_device_info() < 0 || f2fs_get_f2fs_info() < 0) {
1139 ret = FSCK_OPERATIONAL_ERROR;
1144 memset(&gfsck, 0, sizeof(gfsck));
1145 gfsck.sbi.fsck = &gfsck;
1148 ret = f2fs_do_mount(sbi);
1151 MSG(0, "Info: No error was reported\n");
1168 ret = do_defrag(sbi);
1184 ret = f2fs_sparse_initialize_meta(sbi);
1188 f2fs_do_umount(sbi);
1190 /* fsck to fix missing quota */
1202 ERR_MSG("Wrong program name\n");
1206 f2fs_do_umount(sbi);
1208 if (c.func == FSCK && c.bug_on) {
1209 if (!c.ro && c.fix_on == 0 && c.auto_fix == 0 && !c.dry_run) {
1210 char ans[255] = {0};
1212 printf("Do you want to fix this partition? [Y/N] ");
1213 ret2 = scanf("%s", ans);
1215 if (!strcasecmp(ans, "y"))
1217 else if (!strcasecmp(ans, "n"))
1226 ret2 = f2fs_finalize_device();
1229 return FSCK_OPERATIONAL_ERROR;
1233 if (c.func == SLOAD)
1234 c.compress.filter_ops->destroy();
1236 if (!c.show_file_map)
1237 printf("\nDone: %lf secs\n", (get_boottime_ns() - start) / 1000000000.0);
1244 free(sbi->raw_super);
1246 f2fs_release_sparse_resource();