io_uring: make io_buffer_select() return the user address directly
authorJens Axboe <axboe@kernel.dk>
Thu, 28 Apr 2022 19:57:23 +0000 (13:57 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 9 May 2022 12:29:02 +0000 (06:29 -0600)
There's no point in having callers provide a kbuf, we're just returning
the address anyway.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index 3dbf096..2b87c89 100644 (file)
@@ -3458,15 +3458,15 @@ static void io_buffer_add_list(struct io_ring_ctx *ctx,
        list_add(&bl->list, list);
 }
 
-static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,
-                                         int bgid, unsigned int issue_flags)
+static void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
+                                    int bgid, unsigned int issue_flags)
 {
        struct io_buffer *kbuf = req->kbuf;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_buffer_list *bl;
 
        if (req->flags & REQ_F_BUFFER_SELECTED)
-               return kbuf;
+               return u64_to_user_ptr(kbuf->addr);
 
        io_ring_submit_lock(req->ctx, issue_flags);
 
@@ -3478,25 +3478,18 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,
                        *len = kbuf->len;
                req->flags |= REQ_F_BUFFER_SELECTED;
                req->kbuf = kbuf;
-       } else {
-               kbuf = ERR_PTR(-ENOBUFS);
+               io_ring_submit_unlock(req->ctx, issue_flags);
+               return u64_to_user_ptr(kbuf->addr);
        }
 
        io_ring_submit_unlock(req->ctx, issue_flags);
-       return kbuf;
+       return ERR_PTR(-ENOBUFS);
 }
 
 static void __user *io_rw_buffer_select(struct io_kiocb *req, size_t *len,
                                        unsigned int issue_flags)
 {
-       struct io_buffer *kbuf;
-       u16 bgid;
-
-       bgid = req->buf_index;
-       kbuf = io_buffer_select(req, len, bgid, issue_flags);
-       if (IS_ERR(kbuf))
-               return kbuf;
-       return u64_to_user_ptr(kbuf->addr);
+       return io_buffer_select(req, len, req->buf_index, issue_flags);
 }
 
 #ifdef CONFIG_COMPAT
@@ -5535,7 +5528,6 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
        struct io_async_msghdr iomsg, *kmsg;
        struct io_sr_msg *sr = &req->sr_msg;
        struct socket *sock;
-       struct io_buffer *kbuf;
        unsigned flags;
        int ret, min_ret = 0;
        bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
@@ -5558,10 +5550,12 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
                return io_setup_async_msg(req, kmsg);
 
        if (req->flags & REQ_F_BUFFER_SELECT) {
-               kbuf = io_buffer_select(req, &sr->len, sr->bgid, issue_flags);
-               if (IS_ERR(kbuf))
-                       return PTR_ERR(kbuf);
-               kmsg->fast_iov[0].iov_base = u64_to_user_ptr(kbuf->addr);
+               void __user *buf;
+
+               buf = io_buffer_select(req, &sr->len, sr->bgid, issue_flags);
+               if (IS_ERR(buf))
+                       return PTR_ERR(buf);
+               kmsg->fast_iov[0].iov_base = buf;
                kmsg->fast_iov[0].iov_len = sr->len;
                iov_iter_init(&kmsg->msg.msg_iter, READ, kmsg->fast_iov, 1,
                                sr->len);
@@ -5603,10 +5597,8 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
 
 static int io_recv(struct io_kiocb *req, unsigned int issue_flags)
 {
-       struct io_buffer *kbuf;
        struct io_sr_msg *sr = &req->sr_msg;
        struct msghdr msg;
-       void __user *buf = sr->buf;
        struct socket *sock;
        struct iovec iov;
        unsigned flags;
@@ -5622,13 +5614,15 @@ static int io_recv(struct io_kiocb *req, unsigned int issue_flags)
                return -ENOTSOCK;
 
        if (req->flags & REQ_F_BUFFER_SELECT) {
-               kbuf = io_buffer_select(req, &sr->len, sr->bgid, issue_flags);
-               if (IS_ERR(kbuf))
-                       return PTR_ERR(kbuf);
-               buf = u64_to_user_ptr(kbuf->addr);
+               void __user *buf;
+
+               buf = io_buffer_select(req, &sr->len, sr->bgid, issue_flags);
+               if (IS_ERR(buf))
+                       return PTR_ERR(buf);
+               sr->buf = buf;
        }
 
-       ret = import_single_range(READ, buf, sr->len, &iov, &msg.msg_iter);
+       ret = import_single_range(READ, sr->buf, sr->len, &iov, &msg.msg_iter);
        if (unlikely(ret))
                goto out_free;