From 3409bf2f9678d769a4c33bd232a3571c51fac481 Mon Sep 17 00:00:00 2001 From: Abd-Alrhman Masalkhi Date: Fri, 10 Jul 2026 10:15:17 +0000 Subject: [PATCH] md/raid10: consistently fail atomic writes that require splitting RAID10 currently handles one badblock path explicitly by failing atomic writes with EIO. However, another badblock path can also reduce the writable range and force the bio through bio_submit_split_bioset(), which implicitly completes the bio with EINVAL. Fix this by handling atomic writes in the common split check. If RAID10 determines that an atomic write would require splitting, complete the bio with EIO. Fixes: a1d9b4fd42d9 ("md/raid10: Atomic write support") Signed-off-by: Abd-Alrhman Masalkhi Reviewed-by: Yu Kuai Reviewed-by: John Garry Link: https://patch.msgid.link/20260710101521.1714-4-abd.masalkhi@gmail.com Signed-off-by: Yu Kuai --- drivers/md/raid10.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4b702e832f06..d08a4ad76115 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1333,6 +1333,7 @@ static bool raid10_write_request(struct mddev *mddev, struct bio *bio, int i, k; sector_t sectors; int max_sectors; + bool atomic = bio->bi_opf & REQ_ATOMIC; if ((mddev_is_clustered(mddev) && mddev->cluster_ops->area_resyncing(mddev, WRITE, @@ -1420,16 +1421,6 @@ static bool raid10_write_request(struct mddev *mddev, struct bio *bio, if (is_bad) { int good_sectors; - /* - * We cannot atomically write this, so just - * error in that case. It could be possible to - * atomically write other mirrors, but the - * complexity of supporting that is not worth - * the benefit. - */ - if (bio->bi_opf & REQ_ATOMIC) - goto err_handle; - good_sectors = first_bad - dev_sector; if (good_sectors < max_sectors) max_sectors = good_sectors; @@ -1449,6 +1440,9 @@ static bool raid10_write_request(struct mddev *mddev, struct bio *bio, r10_bio->sectors = max_sectors; if (r10_bio->sectors < bio_sectors(bio)) { + if (atomic) + goto err_handle; + allow_barrier(conf); bio = bio_submit_split_bioset(bio, r10_bio->sectors, &conf->bio_split);