[PATCH v6 03/12] md/raid1: serialize non-write-behind writes on CollisionCheck rdevs
Mykola Marzhan <[email protected]> Sun, 26 Jul 2026 13:32:20 +0200
| Newsgroups | org.kernel.vger.linux-raid,org.infradead.lists.linux-nvme,org.kernel.vger.linux-block,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.linux-rdma,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
A write that skips write-behind (full behind queue, a waiting reader, failed behind-bio allocation) races the in-flight behind write it overlaps: nothing orders the two on the write-mostly member, and if the older behind data lands last the member keeps stale data for sectors already acknowledged as rewritten. Serialize on CollisionCheck, which marks exactly the rdevs owning a serial tree: serialize_policy rdevs plus write-mostly members when write-behind arms serialization -- the case the MD_SERIALIZE_POLICY test misses. remove_serial() under the same condition. An rdev hot-added under serialize_policy gets no serial tree at all, because mddev_create_serial_pool() skips one that is not write-behind eligible: the old gate dereferences NULL there, this one skips serialization instead. Martin Wilck's fix repairs that case at the source, after which CollisionCheck is a strict superset of MD_SERIALIZE_POLICY. Link: https://lore.kernel.org/linux-raid/[email protected]/ Fixes: 69df9cfc7042 ("raid1: serialize the overlap write") Cc: [email protected] Assisted-by: Claude:claude-fable-5 Signed-off-by: Mykola Marzhan <[email protected]> --- drivers/md/raid1.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index afe2ca96ad8c..997f79c05db7 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -564,7 +564,7 @@ static void raid1_end_write_request(struct bio *bio) call_bio_endio(r1_bio); } } - } else if (test_bit(MD_SERIALIZE_POLICY, &rdev->mddev->flags)) + } else if (test_bit(CollisionCheck, &rdev->flags)) remove_serial(rdev, lo, hi); if (r1_bio->bios[mirror] == NULL) rdev_dec_pending(rdev, conf->mddev); @@ -1677,7 +1677,11 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio, mbio = bio_alloc_clone(rdev->bdev, bio, GFP_NOIO, &mddev->bio_set); - if (test_bit(MD_SERIALIZE_POLICY, &mddev->flags)) + /* + * CollisionCheck marks every rdev with a serial + * tree; order against in-flight write-behind I/O. + */ + if (test_bit(CollisionCheck, &rdev->flags)) wait_for_serialization(rdev, r1_bio); } -- 2.52.0