blob: 2af3daf57452460167c9f920d708d820413006f7 [file] [log] [blame]
Changman Lee7f35b542013-07-04 17:11:32 +09001/**
2 * main.c
3 *
4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include "fsck.h"
12#include <libgen.h>
13
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070014struct f2fs_fsck gfsck;
Changman Lee7f35b542013-07-04 17:11:32 +090015
16void fsck_usage()
17{
18 MSG(0, "\nUsage: fsck.f2fs [options] device\n");
19 MSG(0, "[options]:\n");
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -070020 MSG(0, " -a check/fix potential corruption, reported by f2fs\n");
Changman Lee7f35b542013-07-04 17:11:32 +090021 MSG(0, " -d debug level [default:0]\n");
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -070022 MSG(0, " -f check/fix entire partition\n");
23 MSG(0, " -t show directory tree [-d -1]\n");
Changman Lee7f35b542013-07-04 17:11:32 +090024 exit(1);
25}
26
27void dump_usage()
28{
29 MSG(0, "\nUsage: dump.f2fs [options] device\n");
30 MSG(0, "[options]:\n");
31 MSG(0, " -d debug level [default:0]\n");
32 MSG(0, " -i inode no (hex)\n");
33 MSG(0, " -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]\n");
34 MSG(0, " -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]\n");
Changman Lee88435542013-07-18 11:20:05 +090035 MSG(0, " -b blk_addr (in 4KB)\n");
Changman Lee7f35b542013-07-04 17:11:32 +090036
37 exit(1);
38}
39
40void f2fs_parse_options(int argc, char *argv[])
41{
42 int option = 0;
43 char *prog = basename(argv[0]);
44
45 if (!strcmp("fsck.f2fs", prog)) {
Jaegeuk Kimde6c1c72014-09-02 18:07:35 -070046 const char *option_string = "ad:ft";
Changman Lee7f35b542013-07-04 17:11:32 +090047
48 config.func = FSCK;
49 while ((option = getopt(argc, argv, option_string)) != EOF) {
50 switch (option) {
Jaegeuk Kimde6c1c72014-09-02 18:07:35 -070051 case 'a':
52 config.auto_fix = 1;
53 MSG(0, "Info: Fix the reported corruption.\n");
54 break;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070055 case 'd':
56 config.dbg_lv = atoi(optarg);
57 MSG(0, "Info: Debug level = %d\n",
58 config.dbg_lv);
59 break;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070060 case 'f':
61 config.fix_on = 1;
62 MSG(0, "Info: Force to fix corruption\n");
63 break;
Jaegeuk Kimde6c1c72014-09-02 18:07:35 -070064 case 't':
65 config.dbg_lv = -1;
66 break;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070067 default:
68 MSG(0, "\tError: Unknown option %c\n", option);
69 fsck_usage();
70 break;
Changman Lee7f35b542013-07-04 17:11:32 +090071 }
72 }
73 } else if (!strcmp("dump.f2fs", prog)) {
Changman Lee88435542013-07-18 11:20:05 +090074 const char *option_string = "d:i:s:a:b:";
Changman Lee7f35b542013-07-04 17:11:32 +090075 static struct dump_option dump_opt = {
76 .nid = 3, /* default root ino */
77 .start_sit = -1,
78 .end_sit = -1,
79 .start_ssa = -1,
80 .end_ssa = -1,
Changman Lee88435542013-07-18 11:20:05 +090081 .blk_addr = -1,
Changman Lee7f35b542013-07-04 17:11:32 +090082 };
83
84 config.func = DUMP;
85 while ((option = getopt(argc, argv, option_string)) != EOF) {
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070086 int ret = 0;
87
Changman Lee7f35b542013-07-04 17:11:32 +090088 switch (option) {
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -070089 case 'd':
90 config.dbg_lv = atoi(optarg);
91 MSG(0, "Info: Debug level = %d\n",
92 config.dbg_lv);
93 break;
94 case 'i':
95 if (strncmp(optarg, "0x", 2))
96 ret = sscanf(optarg, "%d",
97 &dump_opt.nid);
98 else
99 ret = sscanf(optarg, "%x",
100 &dump_opt.nid);
101 break;
102 case 's':
103 ret = sscanf(optarg, "%d~%d",
104 &dump_opt.start_sit,
105 &dump_opt.end_sit);
106 break;
107 case 'a':
108 ret = sscanf(optarg, "%d~%d",
109 &dump_opt.start_ssa,
110 &dump_opt.end_ssa);
111 break;
112 case 'b':
113 if (strncmp(optarg, "0x", 2))
114 ret = sscanf(optarg, "%d",
115 &dump_opt.blk_addr);
116 else
117 ret = sscanf(optarg, "%x",
118 &dump_opt.blk_addr);
119 break;
120 default:
121 MSG(0, "\tError: Unknown option %c\n", option);
122 dump_usage();
123 break;
Changman Lee7f35b542013-07-04 17:11:32 +0900124 }
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700125 ASSERT(ret >= 0);
Changman Lee7f35b542013-07-04 17:11:32 +0900126 }
127
128 config.private = &dump_opt;
129 }
130
131 if ((optind + 1) != argc) {
132 MSG(0, "\tError: Device not specified\n");
133 if (config.func == FSCK)
134 fsck_usage();
135 else if (config.func == DUMP)
136 dump_usage();
137 }
138 config.device_name = argv[optind];
139}
140
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700141static void do_fsck(struct f2fs_sb_info *sbi)
Changman Lee7f35b542013-07-04 17:11:32 +0900142{
143 u32 blk_cnt;
Changman Lee7f35b542013-07-04 17:11:32 +0900144
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700145 fsck_init(sbi);
Changman Lee7f35b542013-07-04 17:11:32 +0900146
147 fsck_chk_orphan_node(sbi);
148
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700149 /* Traverse all block recursively from root inode */
Changman Lee7f35b542013-07-04 17:11:32 +0900150 blk_cnt = 1;
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700151 fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
152 F2FS_FT_DIR, TYPE_INODE, &blk_cnt);
153 fsck_verify(sbi);
Changman Lee7f35b542013-07-04 17:11:32 +0900154 fsck_free(sbi);
Changman Lee7f35b542013-07-04 17:11:32 +0900155}
156
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700157static void do_dump(struct f2fs_sb_info *sbi)
Changman Lee7f35b542013-07-04 17:11:32 +0900158{
159 struct dump_option *opt = (struct dump_option *)config.private;
Changman Lee88435542013-07-18 11:20:05 +0900160
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700161 fsck_init(sbi);
Changman Lee7f35b542013-07-04 17:11:32 +0900162
163 if (opt->end_sit == -1)
164 opt->end_sit = SM_I(sbi)->main_segments;
165 if (opt->end_ssa == -1)
166 opt->end_ssa = SM_I(sbi)->main_segments;
167 if (opt->start_sit != -1)
168 sit_dump(sbi, opt->start_sit, opt->end_sit);
169 if (opt->start_ssa != -1)
170 ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
Changman Lee88435542013-07-18 11:20:05 +0900171 if (opt->blk_addr != -1) {
172 dump_inode_from_blkaddr(sbi, opt->blk_addr);
173 goto cleanup;
174 }
Changman Lee7f35b542013-07-04 17:11:32 +0900175 dump_node(sbi, opt->nid);
Changman Lee88435542013-07-18 11:20:05 +0900176cleanup:
177 fsck_free(sbi);
Changman Lee7f35b542013-07-04 17:11:32 +0900178}
179
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700180int main(int argc, char **argv)
Changman Lee7f35b542013-07-04 17:11:32 +0900181{
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700182 struct f2fs_sb_info *sbi;
Changman Lee7f35b542013-07-04 17:11:32 +0900183 int ret = 0;
184
185 f2fs_init_configuration(&config);
186
187 f2fs_parse_options(argc, argv);
188
Jaegeuk Kim2c877a82013-08-02 17:03:10 +0900189 if (f2fs_dev_is_umounted(&config) < 0)
Changman Lee7f35b542013-07-04 17:11:32 +0900190 return -1;
191
192 /* Get device */
193 if (f2fs_get_device_info(&config) < 0)
194 return -1;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700195fsck_again:
196 memset(&gfsck, 0, sizeof(gfsck));
197 gfsck.sbi.fsck = &gfsck;
198 sbi = &gfsck.sbi;
Changman Lee7f35b542013-07-04 17:11:32 +0900199
Jaegeuk Kimde6c1c72014-09-02 18:07:35 -0700200 ret = f2fs_do_mount(sbi);
201 if (ret == 1) {
202 free(sbi->ckpt);
203 free(sbi->raw_super);
204 goto out;
205 } else if (ret < 0)
Changman Lee7f35b542013-07-04 17:11:32 +0900206 return -1;
207
208 switch (config.func) {
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700209 case FSCK:
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700210 do_fsck(sbi);
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700211 break;
212 case DUMP:
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700213 do_dump(sbi);
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700214 break;
Changman Lee7f35b542013-07-04 17:11:32 +0900215 }
216
Changman Lee88435542013-07-18 11:20:05 +0900217 f2fs_do_umount(sbi);
Jaegeuk Kimde6c1c72014-09-02 18:07:35 -0700218out:
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700219 if (config.func == FSCK && config.bug_on) {
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -0700220 if (config.fix_on == 0 && config.auto_fix == 0) {
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700221 char ans[255] = {0};
222retry:
223 printf("Do you want to fix this partition? [Y/N] ");
224 ret = scanf("%s", ans);
225 ASSERT(ret >= 0);
226 if (!strcasecmp(ans, "y"))
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -0700227 config.fix_on = 1;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700228 else if (!strcasecmp(ans, "n"))
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -0700229 config.fix_on = 0;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700230 else
231 goto retry;
Jaegeuk Kim73b6e3e2014-09-03 19:41:44 -0700232
233 if (config.fix_on)
234 goto fsck_again;
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700235 }
Jaegeuk Kimf4ef4a12014-08-26 17:26:01 -0700236 }
Jaegeuk Kimc5786962014-06-13 16:51:32 +0900237 f2fs_finalize_device(&config);
238
Changman Lee7f35b542013-07-04 17:11:32 +0900239 printf("\nDone.\n");
Jaegeuk Kim3b4b8262014-08-27 17:06:17 -0700240 return 0;
Changman Lee7f35b542013-07-04 17:11:32 +0900241}