summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2019-06-26 09:49:28 -0400
committerJens Axboe <axboe@kernel.dk>2019-06-29 11:47:32 -0400
commitb620743077e291ae7d0debd21f50413a8c266229 (patch)
tree965cefe7b283e821cc9f288e9ded8ba0778f6a60
parentd7c8aa85ed204ccebf0c18f29b941d52b33deae3 (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.c14
-rw-r--r--drivers/block/loop.c16
-rw-r--r--fs/io_uring.c3
-rw-r--r--include/linux/uio.h10
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}
837EXPORT_SYMBOL(bio_add_page); 837EXPORT_SYMBOL(bio_add_page);
838 838
839static 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
848void bio_release_pages(struct bio *bio, bool mark_dirty) 839void 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
267static 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
275static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos) 267static 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
21enum iter_type { 21enum 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
57static inline enum iter_type iov_iter_type(const struct iov_iter *i) 54static 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
62static inline bool iter_is_iovec(const struct iov_iter *i) 59static 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
92static 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 *