diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index ffd9e6c2ffc1..9b65509424dc 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -643,14 +643,12 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, size_t offset; unsigned int npages = 0; - bytes = iov_iter_get_pages(iter, pages, LONG_MAX, + bytes = iov_iter_get_pages2(iter, pages, LONG_MAX, VHOST_SCSI_PREALLOC_UPAGES, &offset); /* No pages were pinned */ if (bytes <= 0) return bytes < 0 ? bytes : -EFAULT; - iov_iter_advance(iter, bytes); - while (bytes) { unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes); sg_set_page(sg++, pages[npages++], n, offset); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index c535de5852bf..8fab5db16c73 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -95,12 +95,11 @@ static ssize_t __iter_get_bvecs(struct iov_iter *iter, size_t maxsize, size_t start; int idx = 0; - bytes = iov_iter_get_pages(iter, pages, maxsize - size, + bytes = iov_iter_get_pages2(iter, pages, maxsize - size, ITER_GET_BVECS_PAGES, &start); if (bytes < 0) return size ?: bytes; - iov_iter_advance(iter, bytes); size += bytes; for ( ; bytes; idx++, bvec_idx++) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e1e05b253daa..3ba013e2987f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -3022,7 +3022,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, if (ctx->direct_io) { ssize_t result; - result = iov_iter_get_pages_alloc( + result = iov_iter_get_pages_alloc2( from, &pagevec, cur_len, &start); if (result < 0) { cifs_dbg(VFS, @@ -3036,7 +3036,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, break; } cur_len = (size_t)result; - iov_iter_advance(from, cur_len); nr_pages = (cur_len + start + PAGE_SIZE - 1) / PAGE_SIZE; @@ -3758,7 +3757,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, if (ctx->direct_io) { ssize_t result; - result = iov_iter_get_pages_alloc( + result = iov_iter_get_pages_alloc2( &direct_iov, &pagevec, cur_len, &start); if (result < 0) { @@ -3774,7 +3773,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, break; } cur_len = (size_t)result; - iov_iter_advance(&direct_iov, cur_len); rdata = cifs_readdata_direct_alloc( pagevec, cifs_uncached_readv_complete); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 0e84e6fcf8ab..f833953bab61 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1029,7 +1029,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) saved_len = count; while (count && npages < max_pages) { - rc = iov_iter_get_pages(iter, pages, count, max_pages, &start); + rc = iov_iter_get_pages2(iter, pages, count, max_pages, &start); if (rc < 0) { cifs_dbg(VFS, "Couldn't get user pages (rc=%zd)\n", rc); break; @@ -1041,7 +1041,6 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) break; } - iov_iter_advance(iter, rc); count -= rc; rc += start; cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE); diff --git a/fs/direct-io.c b/fs/direct-io.c index c7fc01c2d509..f669163d5860 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -169,7 +169,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio) const enum req_op dio_op = dio->opf & REQ_OP_MASK; ssize_t ret; - ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES, + ret = iov_iter_get_pages2(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES, &sdio->from); if (ret < 0 && sdio->blocks_available && dio_op == REQ_OP_WRITE) { @@ -191,7 +191,6 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio) } if (ret >= 0) { - iov_iter_advance(sdio->iter, ret); ret += sdio->from; sdio->head = 0; sdio->tail = (ret + PAGE_SIZE - 1) / PAGE_SIZE; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8d657c2cd6f7..51897427a534 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -730,14 +730,13 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) } } else { size_t off; - err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off); + err = iov_iter_get_pages2(cs->iter, &page, PAGE_SIZE, 1, &off); if (err < 0) return err; BUG_ON(!err); cs->len = err; cs->offset = off; cs->pg = page; - iov_iter_advance(cs->iter, err); } return lock_request(cs->req); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c982e3afe3b4..69e19fc0afc1 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1401,14 +1401,13 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, while (nbytes < *nbytesp && ap->num_pages < max_pages) { unsigned npages; size_t start; - ret = iov_iter_get_pages(ii, &ap->pages[ap->num_pages], + ret = iov_iter_get_pages2(ii, &ap->pages[ap->num_pages], *nbytesp - nbytes, max_pages - ap->num_pages, &start); if (ret < 0) break; - iov_iter_advance(ii, ret); nbytes += ret; ret += start; diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 022e1ce63e62..c275c83f0aef 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -364,13 +364,12 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, size_t pgbase; unsigned npages, i; - result = iov_iter_get_pages_alloc(iter, &pagevec, + result = iov_iter_get_pages_alloc2(iter, &pagevec, rsize, &pgbase); if (result < 0) break; bytes = result; - iov_iter_advance(iter, bytes); npages = (result + pgbase + PAGE_SIZE - 1) / PAGE_SIZE; for (i = 0; i < npages; i++) { struct nfs_page *req; @@ -812,13 +811,12 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, size_t pgbase; unsigned npages, i; - result = iov_iter_get_pages_alloc(iter, &pagevec, + result = iov_iter_get_pages_alloc2(iter, &pagevec, wsize, &pgbase); if (result < 0) break; bytes = result; - iov_iter_advance(iter, bytes); npages = (result + pgbase + PAGE_SIZE - 1) / PAGE_SIZE; for (i = 0; i < npages; i++) { struct nfs_page *req; diff --git a/include/linux/uio.h b/include/linux/uio.h index e7fc29b5ad19..b70d28693400 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -351,4 +351,24 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction, }; } +static inline ssize_t iov_iter_get_pages2(struct iov_iter *i, struct page **pages, + size_t maxsize, unsigned maxpages, size_t *start) +{ + ssize_t res = iov_iter_get_pages(i, pages, maxsize, maxpages, start); + + if (res >= 0) + iov_iter_advance(i, res); + return res; +} + +static inline ssize_t iov_iter_get_pages_alloc2(struct iov_iter *i, struct page ***pages, + size_t maxsize, size_t *start) +{ + ssize_t res = iov_iter_get_pages_alloc(i, pages, maxsize, start); + + if (res >= 0) + iov_iter_advance(i, res); + return res; +} + #endif diff --git a/net/core/datagram.c b/net/core/datagram.c index f3988ef8e9af..7255531f63ae 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -632,12 +632,11 @@ int __zerocopy_sg_from_iter(struct msghdr *msg, struct sock *sk, if (frag == MAX_SKB_FRAGS) return -EMSGSIZE; - copied = iov_iter_get_pages(from, pages, length, + copied = iov_iter_get_pages2(from, pages, length, MAX_SKB_FRAGS - frag, &start); if (copied < 0) return -EFAULT; - iov_iter_advance(from, copied); length -= copied; truesize = PAGE_ALIGN(copied + start); diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 81627892bdd4..cf3c24c8610d 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -324,14 +324,13 @@ int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from, goto out; } - copied = iov_iter_get_pages(from, pages, bytes, maxpages, + copied = iov_iter_get_pages2(from, pages, bytes, maxpages, &offset); if (copied <= 0) { ret = -EFAULT; goto out; } - iov_iter_advance(from, copied); bytes -= copied; msg->sg.size += copied; diff --git a/net/rds/message.c b/net/rds/message.c index 799034e0f513..d74be4e3f3fa 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -391,7 +391,7 @@ static int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter * size_t start; ssize_t copied; - copied = iov_iter_get_pages(from, &pages, PAGE_SIZE, + copied = iov_iter_get_pages2(from, &pages, PAGE_SIZE, 1, &start); if (copied < 0) { struct mmpin *mmp; @@ -405,7 +405,6 @@ static int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter * goto err; } total_copied += copied; - iov_iter_advance(from, copied); length -= copied; sg_set_page(sg, pages, copied, start); rm->data.op_nents++; diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 17db8c8811fa..f76119f62f1b 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1352,7 +1352,7 @@ static int tls_setup_from_iter(struct iov_iter *from, rc = -EFAULT; goto out; } - copied = iov_iter_get_pages(from, pages, + copied = iov_iter_get_pages2(from, pages, length, maxpages, &offset); if (copied <= 0) { @@ -1360,8 +1360,6 @@ static int tls_setup_from_iter(struct iov_iter *from, goto out; } - iov_iter_advance(from, copied); - length -= copied; size += copied; while (copied) {