diff options
author | Christoph Hellwig <hch@lst.de> | 2019-06-26 09:49:28 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-06-29 11:47:32 -0400 |
commit | b620743077e291ae7d0debd21f50413a8c266229 (patch) | |
tree | 965cefe7b283e821cc9f288e9ded8ba0778f6a60 | |
parent | d7c8aa85ed204ccebf0c18f29b941d52b33deae3 (diff) |
block: never take page references for ITER_BVEC
If we pass pages through an iov_iter we always already have a reference
in the caller. Thus remove the ITER_BVEC_FLAG_NO_REF and don't take
reference to pages by default for bvec backed iov_iters.
Reviewed-by: Minwoo Im <minwoo.im.dev@gmail.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | block/bio.c | 14 | ||||
-rw-r--r-- | drivers/block/loop.c | 16 | ||||
-rw-r--r-- | fs/io_uring.c | 3 | ||||
-rw-r--r-- | include/linux/uio.h | 10 |
4 files changed, 6 insertions, 37 deletions
diff --git a/block/bio.c b/block/bio.c index 1cbf2a7c245e..5733b9426231 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -836,15 +836,6 @@ int bio_add_page(struct bio *bio, struct page *page, | |||
836 | } | 836 | } |
837 | EXPORT_SYMBOL(bio_add_page); | 837 | EXPORT_SYMBOL(bio_add_page); |
838 | 838 | ||
839 | static void bio_get_pages(struct bio *bio) | ||
840 | { | ||
841 | struct bvec_iter_all iter_all; | ||
842 | struct bio_vec *bvec; | ||
843 | |||
844 | bio_for_each_segment_all(bvec, bio, iter_all) | ||
845 | get_page(bvec->bv_page); | ||
846 | } | ||
847 | |||
848 | void bio_release_pages(struct bio *bio, bool mark_dirty) | 839 | void bio_release_pages(struct bio *bio, bool mark_dirty) |
849 | { | 840 | { |
850 | struct bvec_iter_all iter_all; | 841 | struct bvec_iter_all iter_all; |
@@ -960,11 +951,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) | |||
960 | ret = __bio_iov_iter_get_pages(bio, iter); | 951 | ret = __bio_iov_iter_get_pages(bio, iter); |
961 | } while (!ret && iov_iter_count(iter) && !bio_full(bio)); | 952 | } while (!ret && iov_iter_count(iter) && !bio_full(bio)); |
962 | 953 | ||
963 | if (iov_iter_bvec_no_ref(iter)) | 954 | if (is_bvec) |
964 | bio_set_flag(bio, BIO_NO_PAGE_REF); | 955 | bio_set_flag(bio, BIO_NO_PAGE_REF); |
965 | else if (is_bvec) | ||
966 | bio_get_pages(bio); | ||
967 | |||
968 | return bio->bi_vcnt ? 0 : ret; | 956 | return bio->bi_vcnt ? 0 : ret; |
969 | } | 957 | } |
970 | 958 | ||
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f11b7dc16e9d..44c9985f352a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -264,20 +264,12 @@ lo_do_transfer(struct loop_device *lo, int cmd, | |||
264 | return ret; | 264 | return ret; |
265 | } | 265 | } |
266 | 266 | ||
267 | static inline void loop_iov_iter_bvec(struct iov_iter *i, | ||
268 | unsigned int direction, const struct bio_vec *bvec, | ||
269 | unsigned long nr_segs, size_t count) | ||
270 | { | ||
271 | iov_iter_bvec(i, direction, bvec, nr_segs, count); | ||
272 | i->type |= ITER_BVEC_FLAG_NO_REF; | ||
273 | } | ||
274 | |||
275 | static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos) | 267 | static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos) |
276 | { | 268 | { |
277 | struct iov_iter i; | 269 | struct iov_iter i; |
278 | ssize_t bw; | 270 | ssize_t bw; |
279 | 271 | ||
280 | loop_iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len); | 272 | iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len); |
281 | 273 | ||
282 | file_start_write(file); | 274 | file_start_write(file); |
283 | bw = vfs_iter_write(file, &i, ppos, 0); | 275 | bw = vfs_iter_write(file, &i, ppos, 0); |
@@ -355,7 +347,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq, | |||
355 | ssize_t len; | 347 | ssize_t len; |
356 | 348 | ||
357 | rq_for_each_segment(bvec, rq, iter) { | 349 | rq_for_each_segment(bvec, rq, iter) { |
358 | loop_iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len); | 350 | iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len); |
359 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); | 351 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
360 | if (len < 0) | 352 | if (len < 0) |
361 | return len; | 353 | return len; |
@@ -396,7 +388,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq, | |||
396 | b.bv_offset = 0; | 388 | b.bv_offset = 0; |
397 | b.bv_len = bvec.bv_len; | 389 | b.bv_len = bvec.bv_len; |
398 | 390 | ||
399 | loop_iov_iter_bvec(&i, READ, &b, 1, b.bv_len); | 391 | iov_iter_bvec(&i, READ, &b, 1, b.bv_len); |
400 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); | 392 | len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0); |
401 | if (len < 0) { | 393 | if (len < 0) { |
402 | ret = len; | 394 | ret = len; |
@@ -563,7 +555,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |||
563 | } | 555 | } |
564 | atomic_set(&cmd->ref, 2); | 556 | atomic_set(&cmd->ref, 2); |
565 | 557 | ||
566 | loop_iov_iter_bvec(&iter, rw, bvec, nr_bvec, blk_rq_bytes(rq)); | 558 | iov_iter_bvec(&iter, rw, bvec, nr_bvec, blk_rq_bytes(rq)); |
567 | iter.iov_offset = offset; | 559 | iter.iov_offset = offset; |
568 | 560 | ||
569 | cmd->iocb.ki_pos = pos; | 561 | cmd->iocb.ki_pos = pos; |
diff --git a/fs/io_uring.c b/fs/io_uring.c index 86a2bd721900..eb6ab1507913 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c | |||
@@ -997,9 +997,6 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw, | |||
997 | iov_iter_bvec(iter, rw, imu->bvec, imu->nr_bvecs, offset + len); | 997 | iov_iter_bvec(iter, rw, imu->bvec, imu->nr_bvecs, offset + len); |
998 | if (offset) | 998 | if (offset) |
999 | iov_iter_advance(iter, offset); | 999 | iov_iter_advance(iter, offset); |
1000 | |||
1001 | /* don't drop a reference to these pages */ | ||
1002 | iter->type |= ITER_BVEC_FLAG_NO_REF; | ||
1003 | return 0; | 1000 | return 0; |
1004 | } | 1001 | } |
1005 | 1002 | ||
diff --git a/include/linux/uio.h b/include/linux/uio.h index 2c90a0842ee8..cea1761c5672 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -19,9 +19,6 @@ struct kvec { | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | enum iter_type { | 21 | enum iter_type { |
22 | /* set if ITER_BVEC doesn't hold a bv_page ref */ | ||
23 | ITER_BVEC_FLAG_NO_REF = 2, | ||
24 | |||
25 | /* iter types */ | 22 | /* iter types */ |
26 | ITER_IOVEC = 4, | 23 | ITER_IOVEC = 4, |
27 | ITER_KVEC = 8, | 24 | ITER_KVEC = 8, |
@@ -56,7 +53,7 @@ struct iov_iter { | |||
56 | 53 | ||
57 | static inline enum iter_type iov_iter_type(const struct iov_iter *i) | 54 | static inline enum iter_type iov_iter_type(const struct iov_iter *i) |
58 | { | 55 | { |
59 | return i->type & ~(READ | WRITE | ITER_BVEC_FLAG_NO_REF); | 56 | return i->type & ~(READ | WRITE); |
60 | } | 57 | } |
61 | 58 | ||
62 | static inline bool iter_is_iovec(const struct iov_iter *i) | 59 | static inline bool iter_is_iovec(const struct iov_iter *i) |
@@ -89,11 +86,6 @@ static inline unsigned char iov_iter_rw(const struct iov_iter *i) | |||
89 | return i->type & (READ | WRITE); | 86 | return i->type & (READ | WRITE); |
90 | } | 87 | } |
91 | 88 | ||
92 | static inline bool iov_iter_bvec_no_ref(const struct iov_iter *i) | ||
93 | { | ||
94 | return (i->type & ITER_BVEC_FLAG_NO_REF) != 0; | ||
95 | } | ||
96 | |||
97 | /* | 89 | /* |
98 | * Total number of bytes covered by an iovec. | 90 | * Total number of bytes covered by an iovec. |
99 | * | 91 | * |