From: Jan Vesely <jvesely@xxxxxxxxxx> Export the function so it can be used to predict segment counts without calling the recalc function. This will be used in the next patch. Signed-off-by: Jan Vesely <jvesely@xxxxxxxxxx> CC: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> CC: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> CC: Jens Axboe <axboe@xxxxxxxxx> CC: Kent Overstreet <koverstreet@xxxxxxxxxx> CC: Rob Evers <revers@xxxxxxxxxx> CC: Tomas Henzl <thenzl@xxxxxxxxxx> CC: Nikola Pajkovsky <npajkovs@xxxxxxxxxx> CC: Kai Makisara <Kai.Makisara@xxxxxxxxxxx> CC: linux-scsi@xxxxxxxxxxxxxxx CC: linux-fsdevel@xxxxxxxxxxxxxxx --- block/blk-merge.c | 52 +++++++++++++++++++++++++++++++--------------------- include/linux/bio.h | 3 +++ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 5f24482..f1ef657 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -9,11 +9,39 @@ #include "blk.h" +bool bvec_mergeable(struct request_queue *q, struct bio_vec *lastbv, + struct bio_vec *newbv, unsigned int seg_size) +{ + unsigned long limit = queue_bounce_pfn(q); + + if (!blk_queue_cluster(q)) + return false; + + /* + * the trick here is to make sure that a high page is + * never considered part of another segment, since that + * might change with the bounce page. + */ + if ((page_to_pfn(lastbv->bv_page) > limit) + || (page_to_pfn(newbv->bv_page) > limit)) + return false; + + if (seg_size + newbv->bv_len > queue_max_segment_size(q)) + return false; + + if (!BIOVEC_PHYS_MERGEABLE(lastbv, newbv)) + return false; + if (!BIOVEC_SEG_BOUNDARY(q, lastbv, newbv)) + return false; + return true; +} + + static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio *bio) { struct bio_vec *bv, *bvprv = NULL; - int cluster, i, high, highprv = 1; + int i; unsigned int seg_size, nr_phys_segs; struct bio *fbio, *bbio; @@ -21,33 +49,16 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, return 0; fbio = bio; - cluster = blk_queue_cluster(q); seg_size = 0; nr_phys_segs = 0; for_each_bio(bio) { bio_for_each_segment(bv, bio, i) { - /* - * the trick here is making sure that a high page is - * never considered part of another segment, since that - * might change with the bounce page. - */ - high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q); - if (high || highprv) - goto new_segment; - if (cluster) { - if (seg_size + bv->bv_len - > queue_max_segment_size(q)) - goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) - goto new_segment; - + if (bvprv && bvec_mergeable(q, bvprv, bv, seg_size)) { seg_size += bv->bv_len; bvprv = bv; continue; } -new_segment: + /* new segment */ if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) fbio->bi_seg_front_size = seg_size; @@ -55,7 +66,6 @@ new_segment: nr_phys_segs++; bvprv = bv; seg_size = bv->bv_len; - highprv = high; } bbio = bio; } diff --git a/include/linux/bio.h b/include/linux/bio.h index ef24466..3af0e36 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -307,6 +307,9 @@ extern struct bio_vec *bvec_alloc(gfp_t, int, unsigned long *, mempool_t *); extern void bvec_free(mempool_t *, struct bio_vec *, unsigned int); extern unsigned int bvec_nr_vecs(unsigned short idx); +extern bool bvec_mergeable(struct request_queue *q, struct bio_vec *lastbv, + struct bio_vec *newbv, unsigned int seg_size); + #ifdef CONFIG_BLK_CGROUP int bio_associate_current(struct bio *bio); void bio_disassociate_task(struct bio *bio); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html