]> www.infradead.org Git - users/hch/block.git/commitdiff
block: enhance blk_bio_segment_split for Zone Append support zone-append-split
authorChristoph Hellwig <hch@lst.de>
Thu, 7 Jul 2022 06:42:48 +0000 (08:42 +0200)
committerChristoph Hellwig <hch@lst.de>
Wed, 13 Jul 2022 11:40:03 +0000 (13:40 +0200)
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 <hch@lst.de>
block/blk-merge.c
include/linux/blkdev.h

index 5abf5aa5a5f0eaae1334436c05332f07318717a4..bc8f8fdad38861d98747ba75b8fe1b364fac92bd 100644 (file)
@@ -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;
        }
 
index 22c477fadc0f3830416f01a10b765f1529f99d75..6335caa055692e47b980c3737972d15ede8982bd 100644 (file)
@@ -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);