Skip to content

Commit 2c8f5c7

Browse files
committed
btrfs-progs: fix-data-checksum: introduce -m|--mirror option
This option allows "btrfs rescue fix-data-checksum" to use the specified mirror number to update checksum item for all corrupted mirrors. If the specified number is larger than the max number of mirrors, the real mirror number will be `num % (num_mirrors + 1)`. Signed-off-by: Qu Wenruo <wqu@suse.com>
1 parent 535b321 commit 2c8f5c7

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

Documentation/btrfs-rescue.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ fix-data-checksum <device>
7272
-i|--interactive
7373
interactive mode, ask for how to repair, ignore the error by default
7474

75+
-m|--mirror <num>
76+
use specified mirror to update the checksum item for all corrupted blocks.
77+
78+
The value must be >= 1, and if the corrupted block has less mirrors than
79+
the value, the mirror number will be `num % (num_mirrors + 1)`.
80+
7581
.. _man-rescue-clear-ino-cache:
7682

7783
clear-ino-cache <device>

cmds/rescue-fix-data-checksum.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,8 @@ static int update_csum_item(struct btrfs_fs_info *fs_info, u64 logical,
381381
}
382382

383383
static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
384-
enum btrfs_fix_data_checksum_mode mode)
384+
enum btrfs_fix_data_checksum_mode mode,
385+
unsigned int mirror)
385386
{
386387
struct corrupted_block *entry;
387388
struct btrfs_path path = { 0 };
@@ -393,7 +394,6 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
393394
}
394395

395396
list_for_each_entry(entry, &corrupted_blocks, list) {
396-
unsigned int mirror;
397397
bool has_printed = false;
398398
int ret;
399399

@@ -426,6 +426,10 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
426426
case BTRFS_FIX_DATA_CSUMS_READONLY:
427427
action = ACTION_IGNORE;
428428
break;
429+
case BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM:
430+
action = ACTION_UPDATE_CSUM;
431+
mirror = mirror % (entry->num_mirrors + 1);
432+
break;
429433
default:
430434
UASSERT(0);
431435
}
@@ -434,6 +438,7 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
434438
case ACTION_IGNORE:
435439
break;
436440
case ACTION_UPDATE_CSUM:
441+
UASSERT(mirror > 0 && mirror <= entry->num_mirrors);
437442
ret = update_csum_item(fs_info, entry->logical, mirror);
438443
break;
439444
default:
@@ -455,7 +460,8 @@ static void free_corrupted_blocks(void)
455460
}
456461

457462
int btrfs_recover_fix_data_checksum(const char *path,
458-
enum btrfs_fix_data_checksum_mode mode)
463+
enum btrfs_fix_data_checksum_mode mode,
464+
unsigned int mirror)
459465
{
460466
struct btrfs_fs_info *fs_info;
461467
struct btrfs_root *csum_root;
@@ -465,6 +471,8 @@ int btrfs_recover_fix_data_checksum(const char *path,
465471
if (mode >= BTRFS_FIX_DATA_CSUMS_LAST)
466472
return -EINVAL;
467473

474+
if (mode == BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM)
475+
UASSERT(mirror > 0);
468476
ret = check_mounted(path);
469477
if (ret < 0) {
470478
errno = -ret;
@@ -495,7 +503,7 @@ int btrfs_recover_fix_data_checksum(const char *path,
495503
errno = -ret;
496504
error("failed to iterate csum tree: %m");
497505
}
498-
report_corrupted_blocks(fs_info, mode);
506+
report_corrupted_blocks(fs_info, mode, mirror);
499507
out_close:
500508
free_corrupted_blocks();
501509
close_ctree_fs_info(fs_info);

cmds/rescue.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "kernel-shared/extent_io.h"
3232
#include "kernel-shared/accessors.h"
3333
#include "kernel-shared/uapi/btrfs_tree.h"
34+
#include "common/string-utils.h"
3435
#include "common/messages.h"
3536
#include "common/utils.h"
3637
#include "common/help.h"
@@ -282,6 +283,7 @@ static const char * const cmd_rescue_fix_data_checksum_usage[] = {
282283
"",
283284
OPTLINE("-r|--readonly", "readonly mode, only report errors without repair"),
284285
OPTLINE("-i|--interactive", "interactive mode, ignore the error by default."),
286+
OPTLINE("-m|--mirror <mirror>", "update csum item using specified mirror"),
285287
HELPINFO_INSERT_GLOBALS,
286288
HELPINFO_INSERT_VERBOSE,
287289
NULL
@@ -291,6 +293,7 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
291293
int argc, char **argv)
292294
{
293295
enum btrfs_fix_data_checksum_mode mode = BTRFS_FIX_DATA_CSUMS_READONLY;
296+
unsigned int mirror = 0;
294297
int ret;
295298
optind = 0;
296299

@@ -300,9 +303,10 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
300303
static const struct option long_options [] = {
301304
{"readonly", no_argument, NULL, 'r'},
302305
{"interactive", no_argument, NULL, 'i'},
306+
{"mirror", required_argument, NULL, 'm'},
303307
{"NULL", 0, NULL, 0},
304308
};
305-
c = getopt_long(argc, argv, "ri", long_options, NULL);
309+
c = getopt_long(argc, argv, "rim:", long_options, NULL);
306310
if (c < 0)
307311
break;
308312
switch (c) {
@@ -312,13 +316,21 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
312316
case 'i':
313317
mode = BTRFS_FIX_DATA_CSUMS_INTERACTIVE;
314318
break;
319+
case 'm':
320+
mode = BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM;
321+
mirror = arg_strtou64(optarg);
322+
if (mirror == 0) {
323+
error("invalid mirror number %u, must be >= 1", mirror);
324+
return 1;
325+
}
326+
break;
315327
default:
316328
usage_unknown_option(cmd, argv);
317329
}
318330
}
319331
if (check_argc_min(argc - optind, 1))
320332
return 1;
321-
ret = btrfs_recover_fix_data_checksum(argv[optind], mode);
333+
ret = btrfs_recover_fix_data_checksum(argv[optind], mode, mirror);
322334
if (ret < 0) {
323335
errno = -ret;
324336
error("failed to fix data checksums: %m");

cmds/rescue.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
enum btrfs_fix_data_checksum_mode {
2424
BTRFS_FIX_DATA_CSUMS_READONLY,
2525
BTRFS_FIX_DATA_CSUMS_INTERACTIVE,
26+
BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM,
2627
BTRFS_FIX_DATA_CSUMS_LAST,
2728
};
2829

2930
int btrfs_recover_superblocks(const char *path, int yes);
3031
int btrfs_recover_chunk_tree(const char *path, int yes);
3132
int btrfs_recover_fix_data_checksum(const char *path,
32-
enum btrfs_fix_data_checksum_mode mode);
33+
enum btrfs_fix_data_checksum_mode mode,
34+
unsigned int mirror);
3335

3436
#endif

0 commit comments

Comments
 (0)