summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorMing Lei <ming.lei@redhat.com>2019-02-21 23:43:36 +0800
committerJens Axboe <axboe@kernel.dk>2019-02-21 10:58:44 -0700
commit8f4e80da764ec1ca44c83f3e17dbc9bf0209bccc (patch)
tree15a75d174ed2de167fc9d8ef8802f2545be8b580 /block
parent037b2625d898844da99c29362121131161f365a5 (diff)
downloadlinux-stable-8f4e80da764ec1ca44c83f3e17dbc9bf0209bccc.tar.gz
linux-stable-8f4e80da764ec1ca44c83f3e17dbc9bf0209bccc.tar.bz2
linux-stable-8f4e80da764ec1ca44c83f3e17dbc9bf0209bccc.zip
block: bounce: make sure that bvec table is updated
Block bounce needs to allocate new page for doing IO, and the new page has to be updated to bvec table. Commit 6dc4f100c switches __blk_queue_bounce() to use the new bio_for_each_segment_all() interface. Unfortunately the new bio_for_each_segment_all() can't be used to update bvec table. This patch fixes this issue by retrieving bvec from the table directly, then the new allocated page can be updated to the bio. This way is safe because the cloned bio is single page bvec. Fixes: 6dc4f100c ("block: allow bio_for_each_segment_all() to iterate over multi-page bvec") Cc: Christoph Hellwig <hch@lst.de> Cc: Omar Sandoval <osandov@fb.com> Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/bounce.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/block/bounce.c b/block/bounce.c
index add085e28b1d..47eb7e936e22 100644
--- a/block/bounce.c
+++ b/block/bounce.c
@@ -295,7 +295,6 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
bool bounce = false;
int sectors = 0;
bool passthrough = bio_is_passthrough(*bio_orig);
- struct bvec_iter_all iter_all;
bio_for_each_segment(from, *bio_orig, iter) {
if (i++ < BIO_MAX_PAGES)
@@ -315,7 +314,12 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
bio = bounce_clone_bio(*bio_orig, GFP_NOIO, passthrough ? NULL :
&bounce_bio_set);
- bio_for_each_segment_all(to, bio, i, iter_all) {
+ /*
+ * Bvec table can't be updated by bio_for_each_segment_all(),
+ * so retrieve bvec from the table directly. This way is safe
+ * because the 'bio' is single-page bvec.
+ */
+ for (i = 0, to = bio->bi_io_vec; i < bio->bi_vcnt; to++, i++) {
struct page *page = to->bv_page;
if (page_to_pfn(page) <= q->limits.bounce_pfn)