From 533abda062b605f8a049ac8bcc1280fa3a81a5ca Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 17 Sep 2015 09:58:38 -0600 Subject: [PATCH] block: blk-merge: fast-clone bio when splitting rw bios biovecs has become immutable since v3.13, so it isn't necessary to allocate biovecs for the new cloned bios, then we can save one extra biovecs allocation/copy, and the allocation is often not fixed-length and a bit more expensive. For example, if the 'max_sectors_kb' of null blk's queue is set as 16(32 sectors) via sysfs just for making more splits, this patch can increase throught about ~70% in the sequential read test over null_blk(direct io, bs: 1M). Cc: Christoph Hellwig Cc: Kent Overstreet Cc: Ming Lin Cc: Dongsu Park Signed-off-by: Ming Lei This fixes a performance regression introduced by commit fbe004c303, and allows us to take full advantage of the fact that we have immutable bio_vecs. Hand applied, as it rejected violently with commit 24da4cf775ea. Signed-off-by: Jens Axboe --- block/blk-merge.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 574ea7c0468ff..c4e9c37f3e381 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -66,15 +66,12 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *bio, struct bio_set *bs) { - struct bio *split; struct bio_vec bv, bvprv, *bvprvp = NULL; struct bvec_iter iter; unsigned seg_size = 0, nsegs = 0, sectors = 0; bio_for_each_segment(bv, bio, iter) { - sectors += bv.bv_len >> 9; - - if (sectors > queue_max_sectors(q)) + if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q)) goto split; /* @@ -95,6 +92,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, seg_size += bv.bv_len; bvprv = bv; bvprvp = &bv; + sectors += bv.bv_len >> 9; continue; } new_segment: @@ -105,21 +103,12 @@ new_segment: bvprv = bv; bvprvp = &bv; seg_size = bv.bv_len; + sectors += bv.bv_len >> 9; } return NULL; split: - split = bio_clone_bioset(bio, GFP_NOIO, bs); - - split->bi_iter.bi_size -= iter.bi_size; - bio->bi_iter = iter; - - if (bio_integrity(bio)) { - bio_integrity_advance(bio, split->bi_iter.bi_size); - bio_integrity_trim(split, 0, bio_sectors(split)); - } - - return split; + return bio_split(bio, sectors, GFP_NOIO, bs); } void blk_queue_split(struct request_queue *q, struct bio **bio, -- 2.39.5