aboutsummaryrefslogtreecommitdiffstats
path: root/fsck/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fsck/main.c')
-rw-r--r--fsck/main.c203
1 files changed, 120 insertions, 83 deletions
diff --git a/fsck/main.c b/fsck/main.c
index 87f009c..31eeeed 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -11,15 +11,16 @@
#include "fsck.h"
#include <libgen.h>
-struct f2fs_fsck gfsck = {
- .sbi.fsck = &gfsck,
-};
+struct f2fs_fsck gfsck;
void fsck_usage()
{
MSG(0, "\nUsage: fsck.f2fs [options] device\n");
MSG(0, "[options]:\n");
+ MSG(0, " -a check/fix potential corruption, reported by f2fs\n");
MSG(0, " -d debug level [default:0]\n");
+ MSG(0, " -f check/fix entire partition\n");
+ MSG(0, " -t show directory tree [-d -1]\n");
exit(1);
}
@@ -42,24 +43,33 @@ void f2fs_parse_options(int argc, char *argv[])
char *prog = basename(argv[0]);
if (!strcmp("fsck.f2fs", prog)) {
- const char *option_string = "d:t";
+ const char *option_string = "ad:ft";
MSG(0, "\n\tF2FS-tools: fsck.f2fs Ver: %s (%s)\n\n",
- F2FS_TOOLS_VERSION,
- F2FS_TOOLS_DATE);
+ F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE);
+
config.func = FSCK;
while ((option = getopt(argc, argv, option_string)) != EOF) {
switch (option) {
- case 'd':
- config.dbg_lv = atoi(optarg);
- MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
- break;
- case 't':
- config.dbg_lv = -1;
- break;
- default:
- fsck_usage();
- break;
+ case 'a':
+ config.auto_fix = 1;
+ MSG(0, "Info: Fix the reported corruption.\n");
+ break;
+ case 'd':
+ config.dbg_lv = atoi(optarg);
+ MSG(0, "Info: Debug level = %d\n",
+ config.dbg_lv);
+ break;
+ case 'f':
+ config.fix_on = 1;
+ MSG(0, "Info: Force to fix corruption\n");
+ break;
+ case 't':
+ config.dbg_lv = -1;
+ break;
+ default:
+ fsck_usage();
+ break;
}
}
} else if (!strcmp("dump.f2fs", prog)) {
@@ -74,37 +84,49 @@ void f2fs_parse_options(int argc, char *argv[])
};
MSG(0, "\n\tF2FS-tools: dump.f2fs Ver: %s (%s)\n\n",
- F2FS_TOOLS_VERSION,
- F2FS_TOOLS_DATE);
+ F2FS_TOOLS_VERSION, F2FS_TOOLS_DATE);
+
config.func = DUMP;
while ((option = getopt(argc, argv, option_string)) != EOF) {
+ int ret = 0;
+
switch (option) {
- case 'd':
- config.dbg_lv = atoi(optarg);
- MSG(0, "Info: Debug level = %d\n", config.dbg_lv);
- break;
- case 'i':
- if (strncmp(optarg, "0x", 2))
- sscanf(optarg, "%d", &dump_opt.nid);
- else
- sscanf(optarg, "%x", &dump_opt.nid);
- break;
- case 's':
- sscanf(optarg, "%d~%d", &dump_opt.start_sit, &dump_opt.end_sit);
- break;
- case 'a':
- sscanf(optarg, "%d~%d", &dump_opt.start_ssa, &dump_opt.end_ssa);
- break;
- case 'b':
- if (strncmp(optarg, "0x", 2))
- sscanf(optarg, "%d", &dump_opt.blk_addr);
- else
- sscanf(optarg, "%x", &dump_opt.blk_addr);
- break;
- default:
- dump_usage();
- break;
+ case 'd':
+ config.dbg_lv = atoi(optarg);
+ MSG(0, "Info: Debug level = %d\n",
+ config.dbg_lv);
+ break;
+ case 'i':
+ if (strncmp(optarg, "0x", 2))
+ ret = sscanf(optarg, "%d",
+ &dump_opt.nid);
+ else
+ ret = sscanf(optarg, "%x",
+ &dump_opt.nid);
+ break;
+ case 's':
+ ret = sscanf(optarg, "%d~%d",
+ &dump_opt.start_sit,
+ &dump_opt.end_sit);
+ break;
+ case 'a':
+ ret = sscanf(optarg, "%d~%d",
+ &dump_opt.start_ssa,
+ &dump_opt.end_ssa);
+ break;
+ case 'b':
+ if (strncmp(optarg, "0x", 2))
+ ret = sscanf(optarg, "%d",
+ &dump_opt.blk_addr);
+ else
+ ret = sscanf(optarg, "%x",
+ &dump_opt.blk_addr);
+ break;
+ default:
+ dump_usage();
+ break;
}
+ ASSERT(ret >= 0);
}
config.private = &dump_opt;
@@ -120,43 +142,27 @@ void f2fs_parse_options(int argc, char *argv[])
config.device_name = argv[optind];
}
-int do_fsck(struct f2fs_sb_info *sbi)
+static void do_fsck(struct f2fs_sb_info *sbi)
{
u32 blk_cnt;
- int ret;
- ret = fsck_init(sbi);
- if (ret < 0)
- return ret;
+ fsck_init(sbi);
fsck_chk_orphan_node(sbi);
- /* Travses all block recursively from root inode */
+ /* Traverse all block recursively from root inode */
blk_cnt = 1;
- ret = fsck_chk_node_blk(sbi,
- NULL,
- sbi->root_ino_num,
- F2FS_FT_DIR,
- TYPE_INODE,
- &blk_cnt);
- if (ret < 0)
- goto out1;
-
- ret = fsck_verify(sbi);
-
-out1:
+ fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
+ F2FS_FT_DIR, TYPE_INODE, &blk_cnt);
+ fsck_verify(sbi);
fsck_free(sbi);
- return ret;
}
-int do_dump(struct f2fs_sb_info *sbi)
+static void do_dump(struct f2fs_sb_info *sbi)
{
struct dump_option *opt = (struct dump_option *)config.private;
- int ret;
- ret = fsck_init(sbi);
- if (ret < 0)
- return ret;
+ fsck_init(sbi);
if (opt->end_sit == -1)
opt->end_sit = SM_I(sbi)->main_segments;
@@ -170,45 +176,76 @@ int do_dump(struct f2fs_sb_info *sbi)
dump_inode_from_blkaddr(sbi, opt->blk_addr);
goto cleanup;
}
-
dump_node(sbi, opt->nid);
-
cleanup:
fsck_free(sbi);
- return 0;
}
-int fsck_f2fs_main (int argc, char **argv)
+#ifndef ANDROID
+int main(int argc, char **argv)
+#else
+int fsck_f2fs_main(int argc, char **argv)
+#endif
{
- struct f2fs_sb_info *sbi = &gfsck.sbi;
+ struct f2fs_sb_info *sbi;
int ret = 0;
f2fs_init_configuration(&config);
f2fs_parse_options(argc, argv);
- /*
+#ifndef ANDROID
if (f2fs_dev_is_umounted(&config) < 0)
return -1;
- */
+#endif
/* Get device */
if (f2fs_get_device_info(&config) < 0)
return -1;
-
- if (f2fs_do_mount(sbi) < 0)
+fsck_again:
+ memset(&gfsck, 0, sizeof(gfsck));
+ gfsck.sbi.fsck = &gfsck;
+ sbi = &gfsck.sbi;
+
+ ret = f2fs_do_mount(sbi);
+ if (ret == 1) {
+ free(sbi->ckpt);
+ free(sbi->raw_super);
+ goto out;
+ } else if (ret < 0)
return -1;
switch (config.func) {
- case FSCK:
- ret = do_fsck(sbi);
- break;
- case DUMP:
- ret = do_dump(sbi);
- break;
+ case FSCK:
+ do_fsck(sbi);
+ break;
+ case DUMP:
+ do_dump(sbi);
+ break;
}
f2fs_do_umount(sbi);
+out:
+ if (config.func == FSCK && config.bug_on) {
+ if (config.fix_on == 0 && config.auto_fix == 0) {
+ char ans[255] = {0};
+retry:
+ printf("Do you want to fix this partition? [Y/N] ");
+ ret = scanf("%s", ans);
+ ASSERT(ret >= 0);
+ if (!strcasecmp(ans, "y"))
+ config.fix_on = 1;
+ else if (!strcasecmp(ans, "n"))
+ config.fix_on = 0;
+ else
+ goto retry;
+
+ if (config.fix_on)
+ goto fsck_again;
+ }
+ }
+ f2fs_finalize_device(&config);
+
printf("\nDone.\n");
- return ret;
+ return 0;
}