Re: [PATCH v2] btrfs: scrub: report the failing sector's address, not the stripe base
Qu Wenruo <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
在 2026/8/16 01:04, James C. Owens 写道:
> scrub_stripe_report_errors() iterates over the sectors of a stripe, but
> every message it emits passes stripe->logical, the address of the first
> sector of the 64KiB stripe, rather than the address of the sector being
> reported. The physical address is likewise computed once, before the
> loop, from stripe->logical.
>
> This matters because scrub_print_common_warning() uses that logical
> address for the backref walk which produces the "root %llu inode %llu
> offset %llu ... (path: ...)" part of the message. As the address is
> always the stripe base, the reported root/inode/offset/path can identify
> a different file from the one whose sector actually failed.
>
> A 64KiB stripe routinely spans several extents belonging to unrelated
> files. On the machine where this was found, the stripe at logical
> 0x17D9380000 holds four sectors of /usr/share/plasma/emoji/bg.dict, then
> a file inside a docker volume, then sectors referenced only by
> snapshots. Every error anywhere in that stripe is attributed to bg.dict.
>
> The effect is visible statistically: across ten months and four kernel
> series that machine logged 81 distinct flagged logical addresses, and
> every one of them is exactly 64KiB aligned. Since BTRFS_STRIPE_LEN is
> 64KiB and stripe->logical is stripe aligned by construction, real
> failures distributed across sectors could not produce that.
>
> Report the address of the sector actually being examined. Adding the
> sector offset to the physical address is valid because BTRFS_STRIPE_LEN
> is the unit contiguous on a single device for every profile, so a stripe
> never crosses a device boundary.
>
> Fixes: 0096580713ff ("btrfs: scrub: introduce error reporting functionality for scrub_stripe")
> Signed-off-by: James C. Owens <[email protected]>
> Reviewed-by: Qu Wenruo <[email protected]>
> ---
> v2:
> - Regenerate the patch with git format-patch. v1 was produced with plain
> diff(1) and so lacked the diffstat, the "diff --git" header, the index
> line and the function context in the hunk headers. Thanks Qu for catching
> it; no code change.
Great that the mystery got solved!
The v1 version is already pushed to for-next with involved tags added.
So nothing to worry about.
Thanks,
Qu
> - Add the Fixes: tag Qu supplied.
> - Carry Qu's Reviewed-by.
>
> fs/btrfs/scrub.c | 24 ++++++++++++++----------
> 1 file changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
> index d2f7ac5b6e96..09b6003d3019 100644
> --- a/fs/btrfs/scrub.c
> +++ b/fs/btrfs/scrub.c
> @@ -1041,6 +1041,10 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
>
> skip:
> for_each_set_bit(sector_nr, &extent_bitmap, stripe->nr_sectors) {
> + const u64 sector_logical = stripe->logical +
> + ((u64)sector_nr << fs_info->sectorsize_bits);
> + const u64 sector_physical = physical +
> + ((u64)sector_nr << fs_info->sectorsize_bits);
> bool repaired = false;
>
> if (scrub_bitmap_test_bit_is_metadata(stripe, sector_nr)) {
> @@ -1069,12 +1073,12 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
> if (dev) {
> btrfs_err_rl(fs_info,
> "scrub: fixed up error at logical %llu on dev %s physical %llu",
> - stripe->logical, btrfs_dev_name(dev),
> - physical);
> + sector_logical, btrfs_dev_name(dev),
> + sector_physical);
> } else {
> btrfs_err_rl(fs_info,
> "scrub: fixed up error at logical %llu on mirror %u",
> - stripe->logical, stripe->mirror_num);
> + sector_logical, stripe->mirror_num);
> }
> continue;
> }
> @@ -1083,30 +1087,30 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
> if (dev) {
> btrfs_err_rl(fs_info,
> "scrub: unable to fixup (regular) error at logical %llu on dev %s physical %llu",
> - stripe->logical, btrfs_dev_name(dev),
> - physical);
> + sector_logical, btrfs_dev_name(dev),
> + sector_physical);
> } else {
> btrfs_err_rl(fs_info,
> "scrub: unable to fixup (regular) error at logical %llu on mirror %u",
> - stripe->logical, stripe->mirror_num);
> + sector_logical, stripe->mirror_num);
> }
>
> if (scrub_bitmap_test_bit_io_error(stripe, sector_nr))
> if (__ratelimit(&rs) && dev)
> scrub_print_common_warning("i/o error", dev, false,
> - stripe->logical, physical);
> + sector_logical, sector_physical);
> if (scrub_bitmap_test_bit_csum_error(stripe, sector_nr))
> if (__ratelimit(&rs) && dev)
> scrub_print_common_warning("checksum error", dev, false,
> - stripe->logical, physical);
> + sector_logical, sector_physical);
> if (scrub_bitmap_test_bit_meta_error(stripe, sector_nr))
> if (__ratelimit(&rs) && dev)
> scrub_print_common_warning("header error", dev, false,
> - stripe->logical, physical);
> + sector_logical, sector_physical);
> if (scrub_bitmap_test_bit_meta_gen_error(stripe, sector_nr))
> if (__ratelimit(&rs) && dev)
> scrub_print_common_warning("generation error", dev, false,
> - stripe->logical, physical);
> + sector_logical, sector_physical);
> }
>
> /* Update the device stats. */
>
> base-commit: 15ef2f78c49d20d53ec7c0f1c9b40b02e089f2d6