Currently these functions return < 0 on error, and 0 for success.
Change that so that we return < 0 on error, but number of bytes
for success.

Some callers already treat the return value that way, others need a
slight tweak.

Signed-off-by: Jens Axboe <[email protected]>
---
 fs/aio.c            |  9 +++++----
 fs/io_uring.c       | 16 ++++++++--------
 fs/splice.c         |  8 ++++----
 include/linux/uio.h |  4 ++--
 lib/iov_iter.c      | 15 ++++++++-------
 net/compat.c        |  3 ++-
 net/socket.c        |  3 ++-
 7 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index 3490d1fa0e16..41824c710b36 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1479,8 +1479,9 @@ static int aio_prep_rw(struct kiocb *req, const struct 
iocb *iocb)
        return 0;
 }
 
-static int aio_setup_rw(int rw, const struct iocb *iocb, struct iovec **iovec,
-               bool vectored, bool compat, struct iov_iter *iter)
+static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
+               struct iovec **iovec, bool vectored, bool compat,
+               struct iov_iter *iter)
 {
        void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
        size_t len = iocb->aio_nbytes;
@@ -1537,7 +1538,7 @@ static int aio_read(struct kiocb *req, const struct iocb 
*iocb,
                return -EINVAL;
 
        ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
-       if (ret)
+       if (ret < 0)
                return ret;
        ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
        if (!ret)
@@ -1565,7 +1566,7 @@ static int aio_write(struct kiocb *req, const struct iocb 
*iocb,
                return -EINVAL;
 
        ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
-       if (ret)
+       if (ret < 0)
                return ret;
        ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
        if (!ret) {
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 0fbb486a320e..23e08c10f486 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1003,9 +1003,9 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int 
rw,
        return 0;
 }
 
-static int io_import_iovec(struct io_ring_ctx *ctx, int rw,
-                          const struct sqe_submit *s, struct iovec **iovec,
-                          struct iov_iter *iter)
+static ssize_t io_import_iovec(struct io_ring_ctx *ctx, int rw,
+                              const struct sqe_submit *s, struct iovec **iovec,
+                              struct iov_iter *iter)
 {
        const struct io_uring_sqe *sqe = s->sqe;
        void __user *buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
@@ -1023,7 +1023,7 @@ static int io_import_iovec(struct io_ring_ctx *ctx, int 
rw,
        opcode = READ_ONCE(sqe->opcode);
        if (opcode == IORING_OP_READ_FIXED ||
            opcode == IORING_OP_WRITE_FIXED) {
-               int ret = io_import_fixed(ctx, rw, sqe, iter);
+               ssize_t ret = io_import_fixed(ctx, rw, sqe, iter);
                *iovec = NULL;
                return ret;
        }
@@ -1089,7 +1089,7 @@ static int io_read(struct io_kiocb *req, const struct 
sqe_submit *s,
        struct iov_iter iter;
        struct file *file;
        size_t iov_count;
-       int ret;
+       ssize_t ret;
 
        ret = io_prep_rw(req, s, force_nonblock);
        if (ret)
@@ -1102,7 +1102,7 @@ static int io_read(struct io_kiocb *req, const struct 
sqe_submit *s,
                return -EINVAL;
 
        ret = io_import_iovec(req->ctx, READ, s, &iovec, &iter);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        iov_count = iov_iter_count(&iter);
@@ -1136,7 +1136,7 @@ static int io_write(struct io_kiocb *req, const struct 
sqe_submit *s,
        struct iov_iter iter;
        struct file *file;
        size_t iov_count;
-       int ret;
+       ssize_t ret;
 
        ret = io_prep_rw(req, s, force_nonblock);
        if (ret)
@@ -1149,7 +1149,7 @@ static int io_write(struct io_kiocb *req, const struct 
sqe_submit *s,
                return -EINVAL;
 
        ret = io_import_iovec(req->ctx, WRITE, s, &iovec, &iter);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        iov_count = iov_iter_count(&iter);
diff --git a/fs/splice.c b/fs/splice.c
index 14cb602d9a2f..98412721f056 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1356,7 +1356,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, uiov,
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
        struct iov_iter iter;
-       long error;
+       ssize_t error;
        struct fd f;
        int type;
 
@@ -1367,7 +1367,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec 
__user *, uiov,
 
        error = import_iovec(type, uiov, nr_segs,
                             ARRAY_SIZE(iovstack), &iov, &iter);
-       if (!error) {
+       if (error >= 0) {
                error = do_vmsplice(f.file, &iter, flags);
                kfree(iov);
        }
@@ -1382,7 +1382,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct 
compat_iovec __user *, io
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
        struct iov_iter iter;
-       long error;
+       ssize_t error;
        struct fd f;
        int type;
 
@@ -1393,7 +1393,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct 
compat_iovec __user *, io
 
        error = compat_import_iovec(type, iov32, nr_segs,
                             ARRAY_SIZE(iovstack), &iov, &iter);
-       if (!error) {
+       if (error >= 0) {
                error = do_vmsplice(f.file, &iter, flags);
                kfree(iov);
        }
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 2d0131ad4604..a61ceb6575ab 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -279,13 +279,13 @@ bool csum_and_copy_from_iter_full(void *addr, size_t 
bytes, __wsum *csum, struct
 size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
                struct iov_iter *i);
 
-int import_iovec(int type, const struct iovec __user * uvector,
+ssize_t import_iovec(int type, const struct iovec __user * uvector,
                 unsigned nr_segs, unsigned fast_segs,
                 struct iovec **iov, struct iov_iter *i);
 
 #ifdef CONFIG_COMPAT
 struct compat_iovec;
-int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
+ssize_t compat_import_iovec(int type, const struct compat_iovec __user * 
uvector,
                 unsigned nr_segs, unsigned fast_segs,
                 struct iovec **iov, struct iov_iter *i);
 #endif
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f99c41d4eb54..f1e0569b4539 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1634,9 +1634,9 @@ EXPORT_SYMBOL(dup_iter);
  * on-stack array was used or not (and regardless of whether this function
  * returns an error or not).
  *
- * Return: 0 on success or negative error code on error.
+ * Return: Negative error code on error, bytes imported on success
  */
-int import_iovec(int type, const struct iovec __user * uvector,
+ssize_t import_iovec(int type, const struct iovec __user * uvector,
                 unsigned nr_segs, unsigned fast_segs,
                 struct iovec **iov, struct iov_iter *i)
 {
@@ -1652,16 +1652,17 @@ int import_iovec(int type, const struct iovec __user * 
uvector,
        }
        iov_iter_init(i, type, p, nr_segs, n);
        *iov = p == *iov ? NULL : p;
-       return 0;
+       return n;
 }
 EXPORT_SYMBOL(import_iovec);
 
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 
-int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
-                unsigned nr_segs, unsigned fast_segs,
-                struct iovec **iov, struct iov_iter *i)
+ssize_t compat_import_iovec(int type,
+               const struct compat_iovec __user * uvector,
+               unsigned nr_segs, unsigned fast_segs,
+               struct iovec **iov, struct iov_iter *i)
 {
        ssize_t n;
        struct iovec *p;
@@ -1675,7 +1676,7 @@ int compat_import_iovec(int type, const struct 
compat_iovec __user * uvector,
        }
        iov_iter_init(i, type, p, nr_segs, n);
        *iov = p == *iov ? NULL : p;
-       return 0;
+       return n;
 }
 #endif
 
diff --git a/net/compat.c b/net/compat.c
index 3f9ce609397f..0f7ded26059e 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -80,9 +80,10 @@ int get_compat_msghdr(struct msghdr *kmsg,
 
        kmsg->msg_iocb = NULL;
 
-       return compat_import_iovec(save_addr ? READ : WRITE,
+       err = compat_import_iovec(save_addr ? READ : WRITE,
                                   compat_ptr(msg.msg_iov), msg.msg_iovlen,
                                   UIO_FASTIOV, iov, &kmsg->msg_iter);
+       return err < 0 ? err : 0;
 }
 
 /* Bleech... */
diff --git a/net/socket.c b/net/socket.c
index 72372dc5dd70..bffec466b4f1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2208,9 +2208,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
 
        kmsg->msg_iocb = NULL;
 
-       return import_iovec(save_addr ? READ : WRITE,
+       err = import_iovec(save_addr ? READ : WRITE,
                            msg.msg_iov, msg.msg_iovlen,
                            UIO_FASTIOV, iov, &kmsg->msg_iter);
+       return err < 0 ? err : 0;
 }
 
 static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
-- 
2.17.1

Reply via email to