summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérôme Glisse <jglisse@redhat.com>2019-04-17 12:56:35 -0400
committerJérôme Glisse <jglisse@redhat.com>2019-05-22 17:19:11 -0400
commit25fc9276bdd4d6fec1067af01c99cf18e96f94ad (patch)
tree321db420d14fed077aa21444b69e68c2836b0335
parente7fe07f1dd5909e16ce6219c45704b07fa15d0ac (diff)
block/iomap: differentiate GUPed pages from iov_iter_get_pages*()
We want to handle differently pages that are coming from GUP (get_user_pages*()) as they will need to be release through new put_user_page() function and not with put_page(). Signed-off-by: Jérôme Glisse <jglisse@redhat.com> Cc: linux-fsdevel@vger.kernel.org Cc: linux-block@vger.kernel.org Cc: linux-xfs@vger.kernel.org Cc: linux-mm@kvack.org Cc: John Hubbard <jhubbard@nvidia.com> Cc: Jan Kara <jack@suse.cz> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Johannes Thumshirn <jthumshirn@suse.de> Cc: Christoph Hellwig <hch@lst.de> Cc: Jens Axboe <axboe@kernel.dk> Cc: Ming Lei <ming.lei@redhat.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: Matthew Wilcox <willy@infradead.org> Cc: Boaz Harrosh <boaz@plexistor.com> Cc: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/iomap.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/iomap.c b/fs/iomap.c
index 071880fee018..596a10f09cde 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -1569,7 +1569,7 @@ static inline void iomap_dio_set_error(struct iomap_dio *dio, int ret)
cmpxchg(&dio->error, 0, ret);
}
-static void iomap_dio_bio_end_io(struct bio *bio)
+static void _iomap_dio_bio_end_io(struct bio *bio, bool from_gup)
{
struct iomap_dio *dio = bio->bi_private;
bool should_dirty = (dio->flags & IOMAP_DIO_DIRTY);
@@ -1593,19 +1593,24 @@ static void iomap_dio_bio_end_io(struct bio *bio)
}
if (should_dirty) {
- bio_check_pages_dirty(bio, false);
+ bio_check_pages_dirty(bio, from_gup);
} else {
- if (!bio_flagged(bio, BIO_NO_PAGE_REF)) {
- struct bvec_iter_all iter_all;
- struct bio_vec *bvec;
-
- bio_for_each_segment_all(bvec, bio, iter_all)
- put_page(bvec->bv_page);
- }
+ if (!bio_flagged(bio, BIO_NO_PAGE_REF))
+ bio_release_pages(bio, from_gup);
bio_put(bio);
}
}
+static void iomap_dio_bio_end_io(struct bio *bio)
+{
+ _iomap_dio_bio_end_io(bio, false);
+}
+
+static void iomap_dio_gup_bio_end_io(struct bio *bio)
+{
+ _iomap_dio_bio_end_io(bio, true);
+}
+
static void
iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
unsigned len)
@@ -1698,7 +1703,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
bio->bi_write_hint = dio->iocb->ki_hint;
bio->bi_ioprio = dio->iocb->ki_ioprio;
bio->bi_private = dio;
- bio->bi_end_io = iomap_dio_bio_end_io;
+ bio->bi_end_io = iov_iter_get_pages_use_gup(&iter) ?
+ iomap_dio_gup_bio_end_io :
+ iomap_dio_bio_end_io;
ret = bio_iov_iter_get_pages(bio, &iter);
if (unlikely(ret)) {