Skip to content

Commit 7800eac

Browse files
adam900710kdave
authored andcommitted
btrfs: introduce new "rescue=ignoremetacsums" mount option
Introduce "rescue=ignoremetacsums" to ignore metadata csums, all the other metadata sanity checks are still kept as is. This new mount option is mostly to allow the kernel to mount an interrupted checksum conversion (at the metadata csum overwrite stage). And since the main part of metadata sanity checks is inside tree-checker, we shouldn't lose much safety, and the new mount option is rescue mount option it requires full read-only mount. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent a048dde commit 7800eac

File tree

8 files changed

+34
-12
lines changed

8 files changed

+34
-12
lines changed

fs/btrfs/bio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
732732
* point, so they are handled as part of the no-checksum case.
733733
*/
734734
if (inode && !(inode->flags & BTRFS_INODE_NODATASUM) &&
735-
!test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state) &&
735+
!test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state) &&
736736
!btrfs_is_data_reloc_root(inode->root)) {
737737
if (should_async_write(bbio) &&
738738
btrfs_wq_submit_bio(bbio, bioc, &smap, mirror_num))

fs/btrfs/disk-io.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ int btrfs_validate_extent_buffer(struct extent_buffer *eb,
367367
u8 result[BTRFS_CSUM_SIZE];
368368
const u8 *header_csum;
369369
int ret = 0;
370+
const bool ignore_csum = btrfs_test_opt(fs_info, IGNOREMETACSUMS);
370371

371372
ASSERT(check);
372373

@@ -399,13 +400,16 @@ int btrfs_validate_extent_buffer(struct extent_buffer *eb,
399400

400401
if (memcmp(result, header_csum, csum_size) != 0) {
401402
btrfs_warn_rl(fs_info,
402-
"checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d",
403+
"checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d%s",
403404
eb->start, eb->read_mirror,
404405
CSUM_FMT_VALUE(csum_size, header_csum),
405406
CSUM_FMT_VALUE(csum_size, result),
406-
btrfs_header_level(eb));
407-
ret = -EUCLEAN;
408-
goto out;
407+
btrfs_header_level(eb),
408+
ignore_csum ? ", ignored" : "");
409+
if (!ignore_csum) {
410+
ret = -EUCLEAN;
411+
goto out;
412+
}
409413
}
410414

411415
if (found_level != check->level) {
@@ -2131,7 +2135,7 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
21312135
/* If we have IGNOREDATACSUMS skip loading these roots. */
21322136
if (objectid == BTRFS_CSUM_TREE_OBJECTID &&
21332137
btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
2134-
set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
2138+
set_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state);
21352139
return 0;
21362140
}
21372141

@@ -2184,7 +2188,7 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
21842188

21852189
if (!found || ret) {
21862190
if (objectid == BTRFS_CSUM_TREE_OBJECTID)
2187-
set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
2191+
set_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state);
21882192

21892193
if (!btrfs_test_opt(fs_info, IGNOREBADROOTS))
21902194
ret = ret ? ret : -ENOENT;
@@ -2865,6 +2869,8 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
28652869

28662870
if (sb_rdonly(sb))
28672871
set_bit(BTRFS_FS_STATE_RO, &fs_info->fs_state);
2872+
if (btrfs_test_opt(fs_info, IGNOREMETACSUMS))
2873+
set_bit(BTRFS_FS_STATE_SKIP_META_CSUMS, &fs_info->fs_state);
28682874

28692875
return btrfs_alloc_stripe_hash_table(fs_info);
28702876
}

fs/btrfs/file-item.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ blk_status_t btrfs_lookup_bio_sums(struct btrfs_bio *bbio)
353353
u32 bio_offset = 0;
354354

355355
if ((inode->flags & BTRFS_INODE_NODATASUM) ||
356-
test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
356+
test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state))
357357
return BLK_STS_OK;
358358

359359
/*

fs/btrfs/fs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ enum {
9898
/* The btrfs_fs_info created for self-tests */
9999
BTRFS_FS_STATE_DUMMY_FS_INFO,
100100

101-
BTRFS_FS_STATE_NO_CSUMS,
101+
/* Checksum errors are ignored. */
102+
BTRFS_FS_STATE_NO_DATA_CSUMS,
103+
BTRFS_FS_STATE_SKIP_META_CSUMS,
102104

103105
/* Indicates there was an error cleaning up a log tree. */
104106
BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
@@ -224,6 +226,7 @@ enum {
224226
BTRFS_MOUNT_IGNOREDATACSUMS = (1UL << 28),
225227
BTRFS_MOUNT_NODISCARD = (1UL << 29),
226228
BTRFS_MOUNT_NOSPACECACHE = (1UL << 30),
229+
BTRFS_MOUNT_IGNOREMETACSUMS = (1UL << 31),
227230
};
228231

229232
/*

fs/btrfs/messages.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ static const char fs_state_chars[] = {
2020
[BTRFS_FS_STATE_TRANS_ABORTED] = 'A',
2121
[BTRFS_FS_STATE_DEV_REPLACING] = 'R',
2222
[BTRFS_FS_STATE_DUMMY_FS_INFO] = 0,
23-
[BTRFS_FS_STATE_NO_CSUMS] = 'C',
23+
[BTRFS_FS_STATE_NO_DATA_CSUMS] = 'C',
24+
[BTRFS_FS_STATE_SKIP_META_CSUMS] = 'S',
2425
[BTRFS_FS_STATE_LOG_CLEANUP_ERROR] = 'L',
2526
};
2627

fs/btrfs/super.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ enum {
176176
Opt_rescue_nologreplay,
177177
Opt_rescue_ignorebadroots,
178178
Opt_rescue_ignoredatacsums,
179+
Opt_rescue_ignoremetacsums,
179180
Opt_rescue_parameter_all,
180181
};
181182

@@ -185,7 +186,9 @@ static const struct constant_table btrfs_parameter_rescue[] = {
185186
{ "ignorebadroots", Opt_rescue_ignorebadroots },
186187
{ "ibadroots", Opt_rescue_ignorebadroots },
187188
{ "ignoredatacsums", Opt_rescue_ignoredatacsums },
189+
{ "ignoremetacsums", Opt_rescue_ignoremetacsums},
188190
{ "idatacsums", Opt_rescue_ignoredatacsums },
191+
{ "imetacsums", Opt_rescue_ignoremetacsums},
189192
{ "all", Opt_rescue_parameter_all },
190193
{}
191194
};
@@ -571,8 +574,12 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
571574
case Opt_rescue_ignoredatacsums:
572575
btrfs_set_opt(ctx->mount_opt, IGNOREDATACSUMS);
573576
break;
577+
case Opt_rescue_ignoremetacsums:
578+
btrfs_set_opt(ctx->mount_opt, IGNOREMETACSUMS);
579+
break;
574580
case Opt_rescue_parameter_all:
575581
btrfs_set_opt(ctx->mount_opt, IGNOREDATACSUMS);
582+
btrfs_set_opt(ctx->mount_opt, IGNOREMETACSUMS);
576583
btrfs_set_opt(ctx->mount_opt, IGNOREBADROOTS);
577584
btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY);
578585
break;
@@ -647,7 +654,8 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, unsigned long *mount_
647654
if (!(flags & SB_RDONLY) &&
648655
(check_ro_option(info, *mount_opt, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") ||
649656
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots") ||
650-
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums")))
657+
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums") ||
658+
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREMETACSUMS, "ignoremetacsums")))
651659
ret = false;
652660

653661
if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) &&
@@ -1063,6 +1071,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
10631071
print_rescue_option(seq, "ignorebadroots", &printed);
10641072
if (btrfs_test_opt(info, IGNOREDATACSUMS))
10651073
print_rescue_option(seq, "ignoredatacsums", &printed);
1074+
if (btrfs_test_opt(info, IGNOREMETACSUMS))
1075+
print_rescue_option(seq, "ignoremetacsums", &printed);
10661076
if (btrfs_test_opt(info, FLUSHONCOMMIT))
10671077
seq_puts(seq, ",flushoncommit");
10681078
if (btrfs_test_opt(info, DISCARD_SYNC))
@@ -1420,6 +1430,7 @@ static void btrfs_emit_options(struct btrfs_fs_info *info,
14201430
btrfs_info_if_set(info, old, USEBACKUPROOT, "trying to use backup root at mount time");
14211431
btrfs_info_if_set(info, old, IGNOREBADROOTS, "ignoring bad roots");
14221432
btrfs_info_if_set(info, old, IGNOREDATACSUMS, "ignoring data csums");
1433+
btrfs_info_if_set(info, old, IGNOREMETACSUMS, "ignoring meta csums");
14231434

14241435
btrfs_info_if_unset(info, old, NODATACOW, "setting datacow");
14251436
btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations");

fs/btrfs/sysfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ static const char *rescue_opts[] = {
385385
"nologreplay",
386386
"ignorebadroots",
387387
"ignoredatacsums",
388+
"ignoremetacsums",
388389
"all",
389390
};
390391

fs/btrfs/zoned.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1844,7 +1844,7 @@ void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered)
18441844
* here so that we don't attempt to log the csums later.
18451845
*/
18461846
if ((inode->flags & BTRFS_INODE_NODATASUM) ||
1847-
test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state)) {
1847+
test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state)) {
18481848
while ((sum = list_first_entry_or_null(&ordered->list,
18491849
typeof(*sum), list))) {
18501850
list_del(&sum->list);

0 commit comments

Comments
 (0)