History

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.

Ming Lei committed 9 years ago

Commit 729204e1 parent 1661f2e1 file · +21 −1Browse files

Unified · Split

include/linux/blkdev.h+21−1
@@ -1607,6 +1607,25 @@ static inline bool bvec_gap_to_prev(struct request_queue *q, · 1606 unmodified lines
16071607 return __bvec_gap_to_prev(q, bprv, offset);
16081608 }
16091609
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+ */
1615+static 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+
16101629 static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
16111630 struct bio *next)
16121631 {
@@ -1616,7 +1635,8 @@ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev, · 3 unmodified lines
16161635 bio_get_last_bvec(prev, &pb);
16171636 bio_get_first_bvec(next, &nb);
16181637
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);
16201640 }
16211641
16221642 return false;