From 739cbb29f96da39409ac41982ad9cdebbf9631d0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 7 Jul 2022 08:42:48 +0200 Subject: [PATCH] block: enhance blk_bio_segment_split for Zone Append support To allow splitting a single write bio into multiple zone append bios in stacking drivers, export blk_bio_segment_split and allow the driver to pass an individual max_size limit (i.e. the max zone append size). Signed-off-by: Christoph Hellwig --- block/blk-merge.c | 18 +++++++++--------- include/linux/blkdev.h | 2 ++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 5abf5aa5a5f0..bc8f8fdad388 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -199,7 +199,7 @@ static inline unsigned get_max_segment_size(const struct request_queue *q, /** * bvec_split_segs - verify whether or not a bvec should be split in the middle - * @q: [in] request queue associated with the bio associated with @bv + * @q: [in] request queue the I/O will be submitted to * @bv: [in] bvec to examine * @nsegs: [in,out] Number of segments in the bio being built. Incremented * by the number of segments from @bv that may be appended to that @@ -248,15 +248,16 @@ static bool bvec_split_segs(const struct request_queue *q, /** * blk_bio_segment_split - split a bio in two bios - * @q: [in] request queue pointer + * @q: [in] request queue the I/O will be submitted to * @bio: [in] bio to be split * @bs: [in] bio set to allocate the clone from * @segs: [out] number of segments in the bio with the first half of the sectors + * @max_bytes: [in] maximum number of bytes per bio * * Clone @bio, update the bi_iter of the clone to represent the first sectors * of @bio and update @bio->bi_iter to represent the remaining sectors. The * following is guaranteed for the cloned bio: - * - That it has at most get_max_io_size(@q, @bio) sectors. + * - That it has at most @max_bytes worth of data * - That it has at most queue_max_segments(@q) segments. * * Except for discard requests the cloned bio will point at the bi_io_vec of @@ -265,15 +266,12 @@ static bool bvec_split_segs(const struct request_queue *q, * responsible for ensuring that @bs is only destroyed after processing of the * split bio has finished. */ -static struct bio *blk_bio_segment_split(struct request_queue *q, - struct bio *bio, - struct bio_set *bs, - unsigned *segs) +struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *bio, + struct bio_set *bs, unsigned *segs, unsigned max_bytes) { struct bio_vec bv, bvprv, *bvprvp = NULL; struct bvec_iter iter; unsigned nsegs = 0, bytes = 0; - const unsigned max_bytes = get_max_io_size(q, bio) << 9; const unsigned max_segs = queue_max_segments(q); bio_for_each_bvec(bv, bio, iter) { @@ -318,6 +316,7 @@ split: bio_clear_polled(bio); return bio_split(bio, bytes >> SECTOR_SHIFT, GFP_NOIO, bs); } +EXPORT_SYMBOL_GPL(blk_bio_segment_split); /** * __blk_queue_split - split a bio and submit the second half @@ -347,7 +346,8 @@ void __blk_queue_split(struct request_queue *q, struct bio **bio, nr_segs); break; default: - split = blk_bio_segment_split(q, *bio, &q->bio_split, nr_segs); + split = blk_bio_segment_split(q, *bio, &q->bio_split, nr_segs, + get_max_io_size(q, *bio) << SECTOR_SHIFT); break; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 22c477fadc0f..6335caa05569 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -867,6 +867,8 @@ void submit_bio_noacct(struct bio *bio); extern int blk_lld_busy(struct request_queue *q); extern void blk_queue_split(struct bio **); +struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *bio, + struct bio_set *bs, unsigned *segs, unsigned max_bytes); extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags); extern void blk_queue_exit(struct request_queue *q); extern void blk_sync_queue(struct request_queue *q); -- 2.51.0