]> git.hungrycats.org Git - linux/commitdiff
btrfs: raid56: only verify recovered sectors that have a checksum
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 1 Aug 2026 22:31:19 +0000 (18:31 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 1 Aug 2026 23:38:26 +0000 (19:38 -0400)
verify_one_sector() checks that the rbio has a csum_buf/csum_bitmap at
all, but never tests the bitmap bit for the sector it is about to
verify.  A recovered sector that has no csum -- free space, or a sector
whose ordered extent has not yet committed its csums, including the
very sector a sub-stripe write is replacing -- is then compared against
an all-zero csum_buf slot and fails with EIO.

The visible symptom: sub-stripe writes to a degraded raid5/6 fail with
EIO whenever the missing device's column in the target stripe is only
partially covered by csums.  The RMW read phase marks every sector of
the missing device as an error, recover_sectors() rebuilds the column
and verifies each rebuilt sector, and the first csum-less sector kills
the write:

  BTRFS error (device loop3): dropping unwritten extent at root 5
    ino 1061 offset [0,4095] disk bytenr 638771200 length 4096

with no underlying device error and no corruption counted anywhere.
Writing new data into partially filled stripes is exactly what a
degraded array must do to keep operating, so this makes a degraded
raid56 filesystem effectively read-only for small writes, and each
failure drops the unwritten extent (detectable data loss).

fill_data_csums() only covers sectors that have csum items, and its
sibling loop verify_bio_data_sectors() already skips sectors whose
bitmap bit is clear.  Do the same here.

Fixes: 7a3150723061 ("btrfs: raid56: do data csum verification during RMW cycle")
CC: stable@vger.kernel.org # 6.2+
Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
Assisted-by: Claude:claude-fable-5
fs/btrfs/raid56.c

index fa2673f50e772cd9f368a554386fc6f482cfc028..f84b88ec92d0da7dfc55c4b8a0bf237b37b06965 100644 (file)
@@ -1926,6 +1926,12 @@ static int verify_one_sector(struct btrfs_raid_bio *rbio,
        /* No way to verify P/Q as they are not covered by data csum. */
        if (stripe_nr >= rbio->nr_data)
                return 0;
+
+       /* No csum for this sector, nothing to verify against. */
+       if (!test_bit(stripe_nr * rbio->stripe_nsectors + sector_nr,
+                     rbio->csum_bitmap))
+               return 0;
+
        /*
         * If we're rebuilding a read, we have to use pages from the
         * bio list if possible.