diff options
| -rw-r--r-- | block/blk-merge.c | 28 | ||||
| -rw-r--r-- | block/blk-mq.c | 3 | ||||
| -rw-r--r-- | include/linux/blk-mq.h | 1 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 |
4 files changed, 26 insertions, 7 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index 6c583f9c5b65..b3bf0df0f4c2 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
| @@ -13,7 +13,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, | |||
| 13 | struct bio *bio) | 13 | struct bio *bio) |
| 14 | { | 14 | { |
| 15 | struct bio_vec bv, bvprv = { NULL }; | 15 | struct bio_vec bv, bvprv = { NULL }; |
| 16 | int cluster, high, highprv = 1; | 16 | int cluster, high, highprv = 1, no_sg_merge; |
| 17 | unsigned int seg_size, nr_phys_segs; | 17 | unsigned int seg_size, nr_phys_segs; |
| 18 | struct bio *fbio, *bbio; | 18 | struct bio *fbio, *bbio; |
| 19 | struct bvec_iter iter; | 19 | struct bvec_iter iter; |
| @@ -35,12 +35,21 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, | |||
| 35 | cluster = blk_queue_cluster(q); | 35 | cluster = blk_queue_cluster(q); |
| 36 | seg_size = 0; | 36 | seg_size = 0; |
| 37 | nr_phys_segs = 0; | 37 | nr_phys_segs = 0; |
| 38 | no_sg_merge = test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags); | ||
| 39 | high = 0; | ||
| 38 | for_each_bio(bio) { | 40 | for_each_bio(bio) { |
| 39 | bio_for_each_segment(bv, bio, iter) { | 41 | bio_for_each_segment(bv, bio, iter) { |
| 40 | /* | 42 | /* |
| 43 | * If SG merging is disabled, each bio vector is | ||
| 44 | * a segment | ||
| 45 | */ | ||
| 46 | if (no_sg_merge) | ||
| 47 | goto new_segment; | ||
| 48 | |||
| 49 | /* | ||
| 41 | * the trick here is making sure that a high page is | 50 | * the trick here is making sure that a high page is |
| 42 | * never considered part of another segment, since that | 51 | * never considered part of another segment, since |
| 43 | * might change with the bounce page. | 52 | * that might change with the bounce page. |
| 44 | */ | 53 | */ |
| 45 | high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q); | 54 | high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q); |
| 46 | if (!high && !highprv && cluster) { | 55 | if (!high && !highprv && cluster) { |
| @@ -84,11 +93,16 @@ void blk_recalc_rq_segments(struct request *rq) | |||
| 84 | 93 | ||
| 85 | void blk_recount_segments(struct request_queue *q, struct bio *bio) | 94 | void blk_recount_segments(struct request_queue *q, struct bio *bio) |
| 86 | { | 95 | { |
| 87 | struct bio *nxt = bio->bi_next; | 96 | if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags)) |
| 97 | bio->bi_phys_segments = bio->bi_vcnt; | ||
| 98 | else { | ||
| 99 | struct bio *nxt = bio->bi_next; | ||
| 100 | |||
| 101 | bio->bi_next = NULL; | ||
| 102 | bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio); | ||
| 103 | bio->bi_next = nxt; | ||
| 104 | } | ||
| 88 | 105 | ||
| 89 | bio->bi_next = NULL; | ||
| 90 | bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio); | ||
| 91 | bio->bi_next = nxt; | ||
| 92 | bio->bi_flags |= (1 << BIO_SEG_VALID); | 106 | bio->bi_flags |= (1 << BIO_SEG_VALID); |
| 93 | } | 107 | } |
| 94 | EXPORT_SYMBOL(blk_recount_segments); | 108 | EXPORT_SYMBOL(blk_recount_segments); |
diff --git a/block/blk-mq.c b/block/blk-mq.c index f27fe44230c2..f98d977fd150 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -1829,6 +1829,9 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set) | |||
| 1829 | q->mq_ops = set->ops; | 1829 | q->mq_ops = set->ops; |
| 1830 | q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; | 1830 | q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; |
| 1831 | 1831 | ||
| 1832 | if (!(set->flags & BLK_MQ_F_SG_MERGE)) | ||
| 1833 | q->queue_flags |= 1 << QUEUE_FLAG_NO_SG_MERGE; | ||
| 1834 | |||
| 1832 | q->sg_reserved_size = INT_MAX; | 1835 | q->sg_reserved_size = INT_MAX; |
| 1833 | 1836 | ||
| 1834 | INIT_WORK(&q->requeue_work, blk_mq_requeue_work); | 1837 | INIT_WORK(&q->requeue_work, blk_mq_requeue_work); |
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 91dfb75ce39f..95de239444d2 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h | |||
| @@ -129,6 +129,7 @@ enum { | |||
| 129 | BLK_MQ_F_SHOULD_MERGE = 1 << 0, | 129 | BLK_MQ_F_SHOULD_MERGE = 1 << 0, |
| 130 | BLK_MQ_F_SHOULD_SORT = 1 << 1, | 130 | BLK_MQ_F_SHOULD_SORT = 1 << 1, |
| 131 | BLK_MQ_F_TAG_SHARED = 1 << 2, | 131 | BLK_MQ_F_TAG_SHARED = 1 << 2, |
| 132 | BLK_MQ_F_SG_MERGE = 1 << 3, | ||
| 132 | 133 | ||
| 133 | BLK_MQ_S_STOPPED = 0, | 134 | BLK_MQ_S_STOPPED = 0, |
| 134 | BLK_MQ_S_TAG_ACTIVE = 1, | 135 | BLK_MQ_S_TAG_ACTIVE = 1, |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 098304576d51..695b9fd41efe 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -510,6 +510,7 @@ struct request_queue { | |||
| 510 | #define QUEUE_FLAG_SAME_FORCE 18 /* force complete on same CPU */ | 510 | #define QUEUE_FLAG_SAME_FORCE 18 /* force complete on same CPU */ |
| 511 | #define QUEUE_FLAG_DEAD 19 /* queue tear-down finished */ | 511 | #define QUEUE_FLAG_DEAD 19 /* queue tear-down finished */ |
| 512 | #define QUEUE_FLAG_INIT_DONE 20 /* queue is initialized */ | 512 | #define QUEUE_FLAG_INIT_DONE 20 /* queue is initialized */ |
| 513 | #define QUEUE_FLAG_NO_SG_MERGE 21 /* don't attempt to merge SG segments*/ | ||
| 513 | 514 | ||
| 514 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ | 515 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ |
| 515 | (1 << QUEUE_FLAG_STACKABLE) | \ | 516 | (1 << QUEUE_FLAG_STACKABLE) | \ |
