[PATCH v4 25/25] md/raid5: split reshape bios before bitmap accounting
From: Yu Kuai
Date: Sat Aug 01 2026 - 13:33:00 EST
From: Yu Kuai <yukuai@xxxxxxx>
RAID5 maps array sectors through different geometries before and after the
reshape position. During llbitmap reshape, md core cannot account one bio
against both geometries as a single bitmap range, because the old and new
bitmap mappings can cover different chunks.
Split bios that cross reshape_position before md_account_bio(), so the
bitmap only sees ranges that belong to one side of the reshape boundary.
mddev_bio_split_at_reshape_offset() uses bio_submit_split_bioset(), which
submits the remainder immediately and returns the front split bio. If that
front bio later has to wait for reshape, md_handle_request() must not retry
the original bio pointer, because after the split that pointer is the
already-submitted remainder. Track whether the split happened, clear the
temporary BLK_STS_RESOURCE status after the internal clone completion, and
resubmit the front bio directly after the reshape wait. Keep the old
return-false retry path for unsplit bios, where md_handle_request() still
owns the same bio.
Signed-off-by: Yu Kuai <yukuai@xxxxxxx>
---
drivers/md/raid5.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 896aa522f446..9b47d9a277f9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6148,9 +6148,11 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
struct r5conf *conf = mddev->private;
const int rw = bio_data_dir(bi);
struct stripe_request_ctx *ctx;
+ struct bio *front_bio;
sector_t logical_sector;
enum stripe_result res;
int s, stripe_cnt;
+ bool split = false;
bool on_wq;
if (unlikely(bi->bi_opf & REQ_PREFLUSH)) {
@@ -6184,6 +6186,18 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
return true;
}
+ front_bio = bi;
+ bi = mddev_bio_split_at_reshape_offset(mddev, bi, NULL,
+ &conf->bio_split);
+ if (!bi) {
+ if (rw == WRITE)
+ md_write_end(mddev);
+ return true;
+ }
+ if (bi != front_bio)
+ split = true;
+ front_bio = bi;
+
logical_sector = bi->bi_iter.bi_sector & ~((sector_t)RAID5_STRIPE_SECTORS(conf)-1);
bi->bi_next = NULL;
@@ -6284,6 +6298,11 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
bio_endio(bi);
wait_for_completion(&done);
+ front_bio->bi_status = BLK_STS_OK;
+ if (split) {
+ submit_bio_noacct(front_bio);
+ return true;
+ }
return false;
}
--
2.51.0