* [PATCH v1 1/4] block: bio: introduce helpers to get the 1st and last bvec
[not found] <1455852022-14188-1-git-send-email-ming.lei@canonical.com>
@ 2016-02-19 3:20 ` Ming Lei
2016-02-21 9:38 ` Sagi Grimberg
2016-02-22 8:59 ` Christoph Hellwig
2016-02-19 3:20 ` [PATCH v1 3/4] block: get the 1st and last bvec via helpers Ming Lei
1 sibling, 2 replies; 6+ messages in thread
From: Ming Lei @ 2016-02-19 3:20 UTC (permalink / raw)
To: Jens Axboe, linux-kernel
Cc: linux-block, Christoph Hellwig, Sagi Grimberg, Kent Overstreet,
Keith Busch, Elliott Robert, Ming Lei, stable
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.
This patch introduces two helpers for getting the first and last
bvec of one bio for fixing the issue.
Cc: stable@vger.kernel.org
Reported-by: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
include/linux/bio.h | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 5349e68..3ce2e45 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -310,6 +310,47 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
bio->bi_flags &= ~(1U << bit);
}
+static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
+{
+ *bv = bio_iovec(bio);
+}
+
+/*
+ * bio_get_last_bvec() is introduced to get the last bvec of one
+ * bio for bio_will_gap().
+ */
+static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
+{
+ struct bvec_iter iter = bio->bi_iter;
+ int idx;
+
+ if (!bio_flagged(bio, BIO_CLONED)) {
+ *bv = bio->bi_io_vec[bio->bi_vcnt - 1];
+ return;
+ }
+
+ if (unlikely(!bio_multiple_segments(bio))) {
+ *bv = bio_iovec(bio);
+ return;
+ }
+
+ bio_advance_iter(bio, &iter, iter.bi_size);
+
+ if (!iter.bi_bvec_done)
+ idx = iter.bi_idx - 1;
+ else /* in the middle of bvec */
+ idx = iter.bi_idx;
+
+ *bv = bio->bi_io_vec[idx];
+
+ /*
+ * iter.bi_bvec_done records actual length of the last bvec
+ * if this bio ends in the middle of one io vector
+ */
+ if (iter.bi_bvec_done)
+ bv->bv_len = iter.bi_bvec_done;
+}
+
enum bip_flags {
BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v1 3/4] block: get the 1st and last bvec via helpers
[not found] <1455852022-14188-1-git-send-email-ming.lei@canonical.com>
2016-02-19 3:20 ` [PATCH v1 1/4] block: bio: introduce helpers to get the 1st and last bvec Ming Lei
@ 2016-02-19 3:20 ` Ming Lei
2016-02-21 9:39 ` Sagi Grimberg
2016-02-22 9:01 ` Christoph Hellwig
1 sibling, 2 replies; 6+ messages in thread
From: Ming Lei @ 2016-02-19 3:20 UTC (permalink / raw)
To: Jens Axboe, linux-kernel
Cc: linux-block, Christoph Hellwig, Sagi Grimberg, Kent Overstreet,
Keith Busch, Elliott Robert, Ming Lei, stable
This patch applies the two introduced helpers to
figure out the 1st and last bvec, and fixes the
original way after bio splitting.
Cc: stable@vger.kernel.org
Reported-by: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
include/linux/blkdev.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 5023401..de4fc002 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1394,11 +1394,16 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
struct bio *next)
{
- if (!bio_has_data(prev) || !queue_virt_boundary(q))
+ if (!bio_has_data(prev) || !queue_virt_boundary(q)) {
return false;
+ } else {
+ struct bio_vec pb, nb;
- return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
- next->bi_io_vec[0].bv_offset);
+ bio_get_last_bvec(prev, &pb);
+ bio_get_first_bvec(next, &nb);
+
+ return __bvec_gap_to_prev(q, &pb, nb.bv_offset);
+ }
}
static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread