summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbd-Alrhman Masalkhi <abd.masalkhi@gmail.com>2026-07-10 10:15:17 +0000
committerYu Kuai <yukuai@fygo.io>2026-07-30 23:32:44 +0800
commit3409bf2f9678d769a4c33bd232a3571c51fac481 (patch)
treea7073b304dfbeb7a9ad25c45947ed8ddb522cf7a
parent86d801e895b853667a886918998e1628fcc3174e (diff)
downloadlinux-3409bf2f9678d769a4c33bd232a3571c51fac481.tar.gz
linux-3409bf2f9678d769a4c33bd232a3571c51fac481.zip
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 <abd.masalkhi@gmail.com> Reviewed-by: Yu Kuai <yukuai@fygo.io> Reviewed-by: John Garry <john.g.garry@oracle.com> Link: https://patch.msgid.link/20260710101521.1714-4-abd.masalkhi@gmail.com Signed-off-by: Yu Kuai <yukuai@fygo.io>
-rw-r--r--drivers/md/raid10.c14
1 files 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);