Skip to content

Commit e69bf81

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: properly report super block errors in system log
[PROBLEM] Unlike data/metadata corruption, if scrub detected some error in the super block, the only error message is from the updated device status: BTRFS info (device dm-1): scrub: started on devid 2 BTRFS error (device dm-1): bdev /dev/mapper/test-scratch2 errs: wr 0, rd 0, flush 0, corrupt 1, gen 0 BTRFS info (device dm-1): scrub: finished on devid 2 with status: 0 This is not helpful at all. [CAUSE] Unlike data/metadata error reporting, there is no visible report in kernel dmesg to report supper block errors. In fact, return value of scrub_checksum_super() is intentionally skipped, thus scrub_handle_errored_block() will never be called for super blocks. [FIX] Make super block errors to output an error message, now the full dmesg would looks like this: BTRFS info (device dm-1): scrub: started on devid 2 BTRFS warning (device dm-1): super block error on device /dev/mapper/test-scratch2, physical 67108864 BTRFS error (device dm-1): bdev /dev/mapper/test-scratch2 errs: wr 0, rd 0, flush 0, corrupt 1, gen 0 BTRFS info (device dm-1): scrub: finished on devid 2 with status: 0 BTRFS info (device dm-1): scrub: started on devid 2 This fix involves: - Move the super_errors reporting to scrub_handle_errored_block() This allows the device status message to show after the super block error message. But now we no longer distinguish super block corruption and generation mismatch, now all counted as corruption. - Properly check the return value from scrub_checksum_super() - Add extra super block error reporting for scrub_print_warning(). Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent b0c5822 commit e69bf81

File tree

1 file changed

+12
-21
lines changed

1 file changed

+12
-21
lines changed

fs/btrfs/scrub.c

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,13 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
729729
dev = sblock->sectors[0]->dev;
730730
fs_info = sblock->sctx->fs_info;
731731

732+
/* Super block error, no need to search extent tree. */
733+
if (sblock->sectors[0]->flags & BTRFS_EXTENT_FLAG_SUPER) {
734+
btrfs_warn_in_rcu(fs_info, "%s on device %s, physical %llu",
735+
errstr, rcu_str_deref(dev->name),
736+
sblock->sectors[0]->physical);
737+
return;
738+
}
732739
path = btrfs_alloc_path();
733740
if (!path)
734741
return;
@@ -804,7 +811,7 @@ static inline void scrub_put_recover(struct btrfs_fs_info *fs_info,
804811
static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
805812
{
806813
struct scrub_ctx *sctx = sblock_to_check->sctx;
807-
struct btrfs_device *dev;
814+
struct btrfs_device *dev = sblock_to_check->sectors[0]->dev;
808815
struct btrfs_fs_info *fs_info;
809816
u64 logical;
810817
unsigned int failed_mirror_index;
@@ -825,13 +832,15 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
825832
fs_info = sctx->fs_info;
826833
if (sblock_to_check->sectors[0]->flags & BTRFS_EXTENT_FLAG_SUPER) {
827834
/*
828-
* if we find an error in a super block, we just report it.
835+
* If we find an error in a super block, we just report it.
829836
* They will get written with the next transaction commit
830837
* anyway
831838
*/
839+
scrub_print_warning("super block error", sblock_to_check);
832840
spin_lock(&sctx->stat_lock);
833841
++sctx->stat.super_errors;
834842
spin_unlock(&sctx->stat_lock);
843+
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_CORRUPTION_ERRS);
835844
return 0;
836845
}
837846
logical = sblock_to_check->sectors[0]->logical;
@@ -840,7 +849,6 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
840849
is_metadata = !(sblock_to_check->sectors[0]->flags &
841850
BTRFS_EXTENT_FLAG_DATA);
842851
have_csum = sblock_to_check->sectors[0]->have_csum;
843-
dev = sblock_to_check->sectors[0]->dev;
844852

845853
if (!sctx->is_dev_replace && btrfs_repair_one_zone(fs_info, logical))
846854
return 0;
@@ -1762,7 +1770,7 @@ static int scrub_checksum(struct scrub_block *sblock)
17621770
else if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
17631771
ret = scrub_checksum_tree_block(sblock);
17641772
else if (flags & BTRFS_EXTENT_FLAG_SUPER)
1765-
(void)scrub_checksum_super(sblock);
1773+
ret = scrub_checksum_super(sblock);
17661774
else
17671775
WARN_ON(1);
17681776
if (ret)
@@ -1901,23 +1909,6 @@ static int scrub_checksum_super(struct scrub_block *sblock)
19011909
if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size))
19021910
++fail_cor;
19031911

1904-
if (fail_cor + fail_gen) {
1905-
/*
1906-
* if we find an error in a super block, we just report it.
1907-
* They will get written with the next transaction commit
1908-
* anyway
1909-
*/
1910-
spin_lock(&sctx->stat_lock);
1911-
++sctx->stat.super_errors;
1912-
spin_unlock(&sctx->stat_lock);
1913-
if (fail_cor)
1914-
btrfs_dev_stat_inc_and_print(sector->dev,
1915-
BTRFS_DEV_STAT_CORRUPTION_ERRS);
1916-
else
1917-
btrfs_dev_stat_inc_and_print(sector->dev,
1918-
BTRFS_DEV_STAT_GENERATION_ERRS);
1919-
}
1920-
19211912
return fail_cor + fail_gen;
19221913
}
19231914

0 commit comments

Comments
 (0)