Skip to content

Commit 063c7d8

Browse files
adam900710gregkh
authored andcommitted
btrfs: scrub: improve tree block error reporting
[ Upstream commit 2823290 ] [BUG] When debugging a scrub related metadata error, it turns out that our metadata error reporting is not ideal. The only 3 error messages are: - BTRFS error (device dm-2): bdev /dev/mapper/test-scratch1 errs: wr 0, rd 0, flush 0, corrupt 0, gen 1 Showing we have metadata generation mismatch errors. - BTRFS error (device dm-2): unable to fixup (regular) error at logical 7110656 on dev /dev/mapper/test-scratch1 Showing which tree blocks are corrupted. - BTRFS warning (device dm-2): checksum/header error at logical 24772608 on dev /dev/mapper/test-scratch2, physical 3801088: metadata node (level 1) in tree 5 Showing which physical range the corrupted metadata is at. We have to combine the above 3 to know we have a corrupted metadata with generation mismatch. And this is already the better case, if we have other problems, like fsid mismatch, we can not even know the cause. [CAUSE] The problem is caused by the fact that, scrub_checksum_tree_block() never outputs any error message. It just return two bits for scrub: sblock->header_error, and sblock->generation_error. And later we report error in scrub_print_warning(), but unfortunately we only have two bits, there is not really much thing we can done to print any detailed errors. [FIX] This patch will do the following to enhance the error reporting of metadata scrub: - Add extra warning (ratelimited) for every error we hit This can help us to distinguish the different types of errors. Some errors can help us to know what's going wrong immediately, like bytenr mismatch. - Re-order the checks Currently we check bytenr first, then immediately generation. This can lead to false generation mismatch reports, while the fsid mismatches. Here is the new output for the bug I'm debugging (we forgot to writeback tree blocks for commit roots): BTRFS warning (device dm-2): tree block 24117248 mirror 1 has bad fsid, has b77cd862-f150-4c71-90ec-7baf0544d83f want 17df6abf-23cd-445f-b350-5b3e40bfd2fc BTRFS warning (device dm-2): tree block 24117248 mirror 0 has bad fsid, has b77cd862-f150-4c71-90ec-7baf0544d83f want 17df6abf-23cd-445f-b350-5b3e40bfd2fc Now we can immediately know it's some tree blocks didn't even get written back, other than the original confusing generation mismatch. Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 3036f5f commit 063c7d8

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

fs/btrfs/scrub.c

+40-9
Original file line numberDiff line numberDiff line change
@@ -2036,20 +2036,33 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
20362036
* a) don't have an extent buffer and
20372037
* b) the page is already kmapped
20382038
*/
2039-
if (sblock->logical != btrfs_stack_header_bytenr(h))
2039+
if (sblock->logical != btrfs_stack_header_bytenr(h)) {
20402040
sblock->header_error = 1;
2041-
2042-
if (sector->generation != btrfs_stack_header_generation(h)) {
2043-
sblock->header_error = 1;
2044-
sblock->generation_error = 1;
2041+
btrfs_warn_rl(fs_info,
2042+
"tree block %llu mirror %u has bad bytenr, has %llu want %llu",
2043+
sblock->logical, sblock->mirror_num,
2044+
btrfs_stack_header_bytenr(h),
2045+
sblock->logical);
2046+
goto out;
20452047
}
20462048

2047-
if (!scrub_check_fsid(h->fsid, sector))
2049+
if (!scrub_check_fsid(h->fsid, sector)) {
20482050
sblock->header_error = 1;
2051+
btrfs_warn_rl(fs_info,
2052+
"tree block %llu mirror %u has bad fsid, has %pU want %pU",
2053+
sblock->logical, sblock->mirror_num,
2054+
h->fsid, sblock->dev->fs_devices->fsid);
2055+
goto out;
2056+
}
20492057

2050-
if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid,
2051-
BTRFS_UUID_SIZE))
2058+
if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid, BTRFS_UUID_SIZE)) {
20522059
sblock->header_error = 1;
2060+
btrfs_warn_rl(fs_info,
2061+
"tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU",
2062+
sblock->logical, sblock->mirror_num,
2063+
h->chunk_tree_uuid, fs_info->chunk_tree_uuid);
2064+
goto out;
2065+
}
20532066

20542067
shash->tfm = fs_info->csum_shash;
20552068
crypto_shash_init(shash);
@@ -2062,9 +2075,27 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
20622075
}
20632076

20642077
crypto_shash_final(shash, calculated_csum);
2065-
if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size))
2078+
if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) {
20662079
sblock->checksum_error = 1;
2080+
btrfs_warn_rl(fs_info,
2081+
"tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT,
2082+
sblock->logical, sblock->mirror_num,
2083+
CSUM_FMT_VALUE(fs_info->csum_size, on_disk_csum),
2084+
CSUM_FMT_VALUE(fs_info->csum_size, calculated_csum));
2085+
goto out;
2086+
}
2087+
2088+
if (sector->generation != btrfs_stack_header_generation(h)) {
2089+
sblock->header_error = 1;
2090+
sblock->generation_error = 1;
2091+
btrfs_warn_rl(fs_info,
2092+
"tree block %llu mirror %u has bad generation, has %llu want %llu",
2093+
sblock->logical, sblock->mirror_num,
2094+
btrfs_stack_header_generation(h),
2095+
sector->generation);
2096+
}
20672097

2098+
out:
20682099
return sblock->header_error || sblock->checksum_error;
20692100
}
20702101

0 commit comments

Comments
 (0)