Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1344361 > unrolled thread
| Started by | Ming Lei <ming.lei@canonical.com> |
|---|---|
| First post | 2016-02-26 16:50 +0100 |
| Last post | 2016-02-28 11:00 +0100 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v2 0/4] block: fix bio_will_gap() Ming Lei <ming.lei@canonical.com> - 2016-02-26 16:50 +0100
[PATCH v2 4/4] block: merge: get the 1st and last bvec via helpers Ming Lei <ming.lei@canonical.com> - 2016-02-26 16:50 +0100
[PATCH v2 2/4] block: check virt boundary in bio_will_gap() Ming Lei <ming.lei@canonical.com> - 2016-02-26 16:50 +0100
Re: [PATCH v2 0/4] block: fix bio_will_gap() Sagi Grimberg <sagig@dev.mellanox.co.il> - 2016-02-28 11:00 +0100
| From | Ming Lei <ming.lei@canonical.com> |
|---|---|
| Date | 2016-02-26 16:50 +0100 |
| Subject | [PATCH v2 0/4] block: fix bio_will_gap() |
| Message-ID | <r6sOt-5pp-9@gated-at.bofh.it> |
Hi Guys, The bio passed to bio_will_gap() may be fast cloned from upper layer(dm, md, bcache, fs, ...), or from bio splitting in block core. Unfortunately bio_will_gap() just figures out the last bvec via 'bi_io_vec[prev->bi_vcnt - 1]' directly, and this way is obviously wrong in case of fast-cloned bio. It is observed that lots of BIOs are still merged even if the virt boundary limit is violated by the merge, and the issue was reported from Sagi Grimberg. This patch introduces two helpers for getting the first and last bvec of one bio and applys them to fix the issue. Sagi has confirmed the fix. Thanks for Sagi and Christoph's review. V2: - remove unnecessary comment - add reviewed-by V1: - get bvec directly for non-cloned bio - implement bio_get_last_bvec() with single bio_advance_iter(), and avoid to use bio_for_each_segment() which looks a bit inefficient - avoid to double check queue_virt_boundary() in bio_will_gap() block/blk-merge.c | 8 ++------ include/linux/bio.h | 37 +++++++++++++++++++++++++++++++++++++ include/linux/blkdev.h | 23 +++++++++++++++++------ 3 files changed, 56 insertions(+), 12 deletions(-) Thanks, Ming
[toc] | [next] | [standalone]
| From | Ming Lei <ming.lei@canonical.com> |
|---|---|
| Date | 2016-02-26 16:50 +0100 |
| Subject | [PATCH v2 4/4] block: merge: get the 1st and last bvec via helpers |
| Message-ID | <r6sOu-5pp-37@gated-at.bofh.it> |
| In reply to | #1344361 |
This patch applies the two introduced helpers to
figure out the 1st and last bvec.
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
block/blk-merge.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 888a7fe..2613531 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -304,7 +304,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
struct bio *nxt)
{
struct bio_vec end_bv = { NULL }, nxt_bv;
- struct bvec_iter iter;
if (!blk_queue_cluster(q))
return 0;
@@ -316,11 +315,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
if (!bio_has_data(bio))
return 1;
- bio_for_each_segment(end_bv, bio, iter)
- if (end_bv.bv_len == iter.bi_size)
- break;
-
- nxt_bv = bio_iovec(nxt);
+ bio_get_last_bvec(bio, &end_bv);
+ bio_get_first_bvec(nxt, &nxt_bv);
if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv))
return 0;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Ming Lei <ming.lei@canonical.com> |
|---|---|
| Date | 2016-02-26 16:50 +0100 |
| Subject | [PATCH v2 2/4] block: check virt boundary in bio_will_gap() |
| Message-ID | <r6sOv-5pp-49@gated-at.bofh.it> |
| In reply to | #1344361 |
In the following patch, the way for figuring out
the last bvec will be changed with a bit cost introduced,
so return immediately if the queue doesn't have virt
boundary limit. Actually most of devices have not
this limit.
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
include/linux/blkdev.h | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4571ef1..cd06a41 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1372,6 +1372,13 @@ static inline void put_dev_sector(Sector p)
page_cache_release(p.v);
}
+static inline bool __bvec_gap_to_prev(struct request_queue *q,
+ struct bio_vec *bprv, unsigned int offset)
+{
+ return offset ||
+ ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+}
+
/*
* Check if adding a bio_vec after bprv with offset would create a gap in
* the SG list. Most drivers don't care about this, but some do.
@@ -1381,18 +1388,17 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
{
if (!queue_virt_boundary(q))
return false;
- return offset ||
- ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+ return __bvec_gap_to_prev(q, bprv, offset);
}
static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
struct bio *next)
{
- if (!bio_has_data(prev))
+ if (!bio_has_data(prev) || !queue_virt_boundary(q))
return false;
- return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
- next->bi_io_vec[0].bv_offset);
+ return __bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
+ next->bi_io_vec[0].bv_offset);
}
static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Sagi Grimberg <sagig@dev.mellanox.co.il> |
|---|---|
| Date | 2016-02-28 11:00 +0100 |
| Message-ID | <r76iS-q5-7@gated-at.bofh.it> |
| In reply to | #1344361 |
Still looks good, still want it for 4.5 :)
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web