aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/blkdev.h
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2016-12-17 05:49:09 -0500
committerJens Axboe <axboe@fb.com>2017-01-11 22:47:08 -0500
commit729204ef49ec00b788ce23deb9eb922a5769f55d (patch)
treeab5cc3c0aa17fa8b988ed7dfefe888000fac0be3 /include/linux/blkdev.h
parent1661f2e21c8bbf922dcb76faf2126a33ffe4cddb (diff)
block: relax check on sg gap
If the last bvec of the 1st bio and the 1st bvec of the next bio are physically contigious, and the latter can be merged to last segment of the 1st bio, we should think they don't violate sg gap(or virt boundary) limit. Both Vitaly and Dexuan reported lots of unmergeable small bios are observed when running mkfs on Hyper-V virtual storage, and performance becomes quite low. This patch fixes that performance issue. The same issue should exist on NVMe, since it sets virt boundary too. Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com> Reported-by: Dexuan Cui <decui@microsoft.com> Tested-by: Dexuan Cui <decui@microsoft.com> Cc: Keith Busch <keith.busch@intel.com> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'include/linux/blkdev.h')
-rw-r--r--include/linux/blkdev.h22
1 files changed, 21 insertions, 1 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 83695641bd5e..b20da8dfa7ec 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1607,6 +1607,25 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
1607 return __bvec_gap_to_prev(q, bprv, offset); 1607 return __bvec_gap_to_prev(q, bprv, offset);
1608} 1608}
1609 1609
1610/*
1611 * Check if the two bvecs from two bios can be merged to one segment.
1612 * If yes, no need to check gap between the two bios since the 1st bio
1613 * and the 1st bvec in the 2nd bio can be handled in one segment.
1614 */
1615static inline bool bios_segs_mergeable(struct request_queue *q,
1616 struct bio *prev, struct bio_vec *prev_last_bv,
1617 struct bio_vec *next_first_bv)
1618{
1619 if (!BIOVEC_PHYS_MERGEABLE(prev_last_bv, next_first_bv))
1620 return false;
1621 if (!BIOVEC_SEG_BOUNDARY(q, prev_last_bv, next_first_bv))
1622 return false;
1623 if (prev->bi_seg_back_size + next_first_bv->bv_len >
1624 queue_max_segment_size(q))
1625 return false;
1626 return true;
1627}
1628
1610static inline bool bio_will_gap(struct request_queue *q, struct bio *prev, 1629static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
1611 struct bio *next) 1630 struct bio *next)
1612{ 1631{
@@ -1616,7 +1635,8 @@ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
1616 bio_get_last_bvec(prev, &pb); 1635 bio_get_last_bvec(prev, &pb);
1617 bio_get_first_bvec(next, &nb); 1636 bio_get_first_bvec(next, &nb);
1618 1637
1619 return __bvec_gap_to_prev(q, &pb, nb.bv_offset); 1638 if (!bios_segs_mergeable(q, prev, &pb, &nb))
1639 return __bvec_gap_to_prev(q, &pb, nb.bv_offset);
1620 } 1640 }
1621 1641
1622 return false; 1642 return false;