Skip to content

Commit c1a82de

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: fix-data-checksum: introduce option -m|--mirror
This option allows "btrfs rescue fix-data-checksum" to use the specified mirror number to update checksum items 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> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent e3b9a9d commit c1a82de

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 errors 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 fewer 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
@@ -382,7 +382,8 @@ static int update_csum_item(struct btrfs_fs_info *fs_info, u64 logical,
382382
}
383383

384384
static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
385-
enum btrfs_fix_data_checksum_mode mode)
385+
enum btrfs_fix_data_checksum_mode mode,
386+
unsigned int mirror)
386387
{
387388
struct corrupted_block *entry;
388389
struct btrfs_path path = { 0 };
@@ -394,7 +395,6 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
394395
}
395396

396397
list_for_each_entry(entry, &corrupted_blocks, list) {
397-
unsigned int mirror;
398398
bool has_printed = false;
399399
int ret;
400400

@@ -427,6 +427,10 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
427427
case BTRFS_FIX_DATA_CSUMS_READONLY:
428428
action = ACTION_IGNORE;
429429
break;
430+
case BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM:
431+
action = ACTION_UPDATE_CSUM;
432+
mirror = mirror % (entry->num_mirrors + 1);
433+
break;
430434
default:
431435
UASSERT(0);
432436
}
@@ -435,6 +439,7 @@ static void report_corrupted_blocks(struct btrfs_fs_info *fs_info,
435439
case ACTION_IGNORE:
436440
break;
437441
case ACTION_UPDATE_CSUM:
442+
UASSERT(mirror > 0 && mirror <= entry->num_mirrors);
438443
ret = update_csum_item(fs_info, entry->logical, mirror);
439444
break;
440445
default:
@@ -455,7 +460,8 @@ static void free_corrupted_blocks(void)
455460
}
456461
}
457462

458-
int btrfs_recover_fix_data_checksum(const char *path, enum btrfs_fix_data_checksum_mode mode)
463+
int btrfs_recover_fix_data_checksum(const char *path, 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, enum btrfs_fix_data_checks
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, enum btrfs_fix_data_checks
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

296299
optind = 0;
@@ -300,10 +303,11 @@ 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
};
305309

306-
c = getopt_long(argc, argv, "ri", long_options, NULL);
310+
c = getopt_long(argc, argv, "rim:", long_options, NULL);
307311
if (c < 0)
308312
break;
309313
switch (c) {
@@ -313,6 +317,14 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
313317
case 'i':
314318
mode = BTRFS_FIX_DATA_CSUMS_INTERACTIVE;
315319
break;
320+
case 'm':
321+
mode = BTRFS_FIX_DATA_CSUMS_UPDATE_CSUM_ITEM;
322+
mirror = arg_strtou64(optarg);
323+
if (mirror == 0) {
324+
error("invalid mirror number %u, must be >= 1", mirror);
325+
return 1;
326+
}
327+
break;
316328
default:
317329
usage_unknown_option(cmd, argv);
318330
}
@@ -321,7 +333,7 @@ static int cmd_rescue_fix_data_checksum(const struct cmd_struct *cmd,
321333
if (check_argc_min(argc - optind, 1))
322334
return 1;
323335

324-
ret = btrfs_recover_fix_data_checksum(argv[optind], mode);
336+
ret = btrfs_recover_fix_data_checksum(argv[optind], mode, mirror);
325337
if (ret < 0) {
326338
errno = -ret;
327339
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,11 +23,13 @@
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);
31-
int btrfs_recover_fix_data_checksum(const char *path, enum btrfs_fix_data_checksum_mode mode);
32+
int btrfs_recover_fix_data_checksum(const char *path, enum btrfs_fix_data_checksum_mode mode,
33+
unsigned int mirror);
3234

3335
#endif

0 commit comments

Comments
 (0)