Skip to content

Commit e99cae2

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: fix-data-checksum: introduce interactive mode
This mode will ask user for how to fix each block. User input can match the first letter or the whole action name to specify given action, the input is verified case insensitive. If no user input is provided, the default action is to ignore the corrupted block. If the input matches no action, a warning is outputted and user must retry until a valid input is provided. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent cdf3c10 commit e99cae2

File tree

4 files changed

+78
-4
lines changed

4 files changed

+78
-4
lines changed

Documentation/btrfs-rescue.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ fix-data-checksum <device>
6969
readonly mode, only scan for and report data checksum mismatches,
7070
do not repair
7171

72+
-i|--interactive
73+
interactive mode, ask for how to repair, ignore the errors by default
74+
7275
.. _man-rescue-clear-ino-cache:
7376

7477
clear-ino-cache <device>

cmds/rescue-fix-data-checksum.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include "kerncompat.h"
18+
#include <ctype.h>
1819
#include "kernel-shared/disk-io.h"
1920
#include "kernel-shared/ctree.h"
2021
#include "kernel-shared/volumes.h"
@@ -45,6 +46,21 @@ struct corrupted_block {
4546
unsigned long *error_mirror_bitmap;
4647
};
4748

49+
enum fix_data_checksum_action_value {
50+
ACTION_IGNORE,
51+
ACTION_LAST,
52+
};
53+
54+
static const struct fix_data_checksum_action {
55+
enum fix_data_checksum_action_value value;
56+
const char *string;
57+
} actions[] = {
58+
[ACTION_IGNORE] = {
59+
.value = ACTION_IGNORE,
60+
.string = "ignore"
61+
},
62+
};
63+
4864
static int global_repair_mode;
4965
LIST_HEAD(corrupted_blocks);
5066

@@ -243,10 +259,49 @@ static int iterate_csum_root(struct btrfs_fs_info *fs_info, struct btrfs_root *c
243259
return ret;
244260
}
245261

246-
static void report_corrupted_blocks(struct btrfs_fs_info *fs_info)
262+
#define ASK_ACTION_BUFSIZE (32)
263+
static enum fix_data_checksum_action_value ask_action(void)
264+
{
265+
char buf[ASK_ACTION_BUFSIZE] = { 0 };
266+
bool printed;
267+
268+
again:
269+
printed = false;
270+
for (int i = 0; i < ACTION_LAST; i++) {
271+
if (printed)
272+
pr_verbose(LOG_DEFAULT, "/");
273+
/* Mark Ignore as default. */
274+
if (i == ACTION_IGNORE)
275+
pr_verbose(LOG_DEFAULT, "<<%c>>%s", toupper(actions[i].string[0]),
276+
actions[i].string + 1);
277+
else
278+
pr_verbose(LOG_DEFAULT, "<%c>%s", toupper(actions[i].string[0]),
279+
actions[i].string + 1);
280+
}
281+
pr_verbose(LOG_DEFAULT, ":");
282+
fflush(stdout);
283+
/* Default to Ignore if no action provided. */
284+
if (fgets(buf, sizeof(buf) - 1, stdin) == 0)
285+
return ACTION_IGNORE;
286+
if (buf[0] == '\n')
287+
return ACTION_IGNORE;
288+
/* Check exact match or matching the initial letter. */
289+
for (int i = 0; i < ACTION_LAST; i++) {
290+
if (strncasecmp(buf, actions[i].string, 1) == 0 ||
291+
strncasecmp(buf, actions[i].string, ASK_ACTION_BUFSIZE) == 0)
292+
return actions[i].value;
293+
}
294+
/* No valid action found, retry. */
295+
warning("invalid action, please retry");
296+
goto again;
297+
}
298+
299+
static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
300+
enum btrfs_fix_data_checksum_mode mode)
247301
{
248302
struct corrupted_block *entry;
249303
struct btrfs_path path = { 0 };
304+
enum fix_data_checksum_action_value action;
250305

251306
if (list_empty(&corrupted_blocks)) {
252307
pr_verbose(LOG_DEFAULT, "no data checksum mismatch found\n");
@@ -279,6 +334,16 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info)
279334
error("failed to iterate involved files: %m");
280335
break;
281336
}
337+
switch (mode) {
338+
case BTRFS_FIX_DATA_CSUMS_INTERACTIVE:
339+
action = ask_action();
340+
UASSERT(action == ACTION_IGNORE);
341+
fallthrough;
342+
case BTRFS_FIX_DATA_CSUMS_READONLY:
343+
break;
344+
default:
345+
UASSERT(0);
346+
}
282347
}
283348
}
284349

@@ -334,7 +399,7 @@ int btrfs_recover_fix_data_checksum(const char *path, enum btrfs_fix_data_checks
334399
errno = -ret;
335400
error("failed to iterate csum tree: %m");
336401
}
337-
report_corrupted_blocks(fs_info);
402+
report_corrupted_blocks(fs_info, mode);
338403
out_close:
339404
free_corrupted_blocks();
340405
close_ctree_fs_info(fs_info);

cmds/rescue.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ static const char * const cmd_rescue_fix_data_checksum_usage[] = {
280280
"btrfs rescue fix-data-checksum <device>",
281281
"Fix data checksum mismatches.",
282282
"",
283-
OPTLINE("-r", "readonly mode, only report errors without repair"),
283+
OPTLINE("-r|--readonly", "readonly mode, only report errors without repair"),
284+
OPTLINE("-i|--interactive", "interactive mode, ignore the error by default."),
284285
HELPINFO_INSERT_GLOBALS,
285286
HELPINFO_INSERT_VERBOSE,
286287
NULL
@@ -298,16 +299,20 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
298299
enum { GETOPT_VAL_DRYRUN = GETOPT_VAL_FIRST };
299300
static const struct option long_options [] = {
300301
{"readonly", no_argument, NULL, 'r'},
302+
{"interactive", no_argument, NULL, 'i'},
301303
{"NULL", 0, NULL, 0},
302304
};
303305

304-
c = getopt_long(argc, argv, "r", long_options, NULL);
306+
c = getopt_long(argc, argv, "ri", long_options, NULL);
305307
if (c < 0)
306308
break;
307309
switch (c) {
308310
case 'r':
309311
mode = BTRFS_FIX_DATA_CSUMS_READONLY;
310312
break;
313+
case 'i':
314+
mode = BTRFS_FIX_DATA_CSUMS_INTERACTIVE;
315+
break;
311316
default:
312317
usage_unknown_option(cmd, argv);
313318
}

cmds/rescue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
enum btrfs_fix_data_checksum_mode {
2424
BTRFS_FIX_DATA_CSUMS_READONLY,
25+
BTRFS_FIX_DATA_CSUMS_INTERACTIVE,
2526
BTRFS_FIX_DATA_CSUMS_LAST,
2627
};
2728

0 commit comments

Comments
 (0)