]> 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>
Wed, 16 Sep 2026 21:39:59 +0000 (17:39 -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 36fe731e1f674dfb39ec0749f80fa8503eba05f8..08e78c19d53bebca4e9eed6afb699308a3138794 100644 (file)
@@ -1831,6 +1831,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.