[PATCH v2 03/20] md: add helper to split bios at reshape offset

From: Yu Kuai

Date: Wed Jun 24 2026 - 02:45:44 EST


From: Yu Kuai <yukuai@xxxxxxx>

Add mddev_bio_split_at_reshape_offset() so personalities can share
reshape-offset bio splitting instead of open-coding the same helper in
multiple places.

Signed-off-by: Yu Kuai <yukuai@xxxxxxx>
---
drivers/md/md.c | 39 +++++++++++++++++++++++++++++++++++++++
drivers/md/md.h | 4 ++++
2 files changed, 43 insertions(+)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 0b59c676f7c0..c18a7f3c27e6 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9361,6 +9361,45 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
}
EXPORT_SYMBOL_GPL(md_submit_discard_bio);

+struct bio *mddev_bio_split_at_reshape_offset(struct mddev *mddev,
+ struct bio *bio,
+ unsigned int *max_sectors,
+ struct bio_set *bs)
+{
+ sector_t boundary;
+ sector_t start;
+ sector_t end;
+ unsigned int split_sectors;
+
+ split_sectors = bio_sectors(bio);
+ if (max_sectors && *max_sectors && *max_sectors < split_sectors)
+ split_sectors = *max_sectors;
+
+ if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ goto split;
+
+ boundary = mddev->reshape_position;
+ start = bio->bi_iter.bi_sector;
+ end = bio_end_sector(bio);
+ if (start >= boundary || end <= boundary)
+ goto split;
+
+ if (boundary - start < split_sectors)
+ split_sectors = boundary - start;
+
+split:
+ if (max_sectors)
+ *max_sectors = split_sectors;
+ if (split_sectors < bio_sectors(bio)) {
+ bio = bio_submit_split_bioset(bio, split_sectors, bs);
+ if (bio)
+ bio->bi_opf |= REQ_NOMERGE;
+ }
+
+ return bio;
+}
+EXPORT_SYMBOL_GPL(mddev_bio_split_at_reshape_offset);
+
static void md_bitmap_prepare_range(struct mddev *mddev, sector_t *offset,
unsigned long *sectors)
{
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 110cf0f8b107..ebfc6da83161 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -925,6 +925,10 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
extern void md_finish_reshape(struct mddev *mddev);
void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
struct bio *bio, sector_t start, sector_t size);
+struct bio *mddev_bio_split_at_reshape_offset(struct mddev *mddev,
+ struct bio *bio,
+ unsigned int *max_sectors,
+ struct bio_set *bs);
void md_account_bio(struct mddev *mddev, struct bio **bio);

extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
--
2.51.0