drm/edid/firmware: Add built-in edid/1280x720.bin firmware
[platform/kernel/linux-starfive.git] / io_uring / net.c
index ab83da7..2b44126 100644 (file)
@@ -47,6 +47,7 @@ struct io_connect {
        struct sockaddr __user          *addr;
        int                             addr_len;
        bool                            in_progress;
+       bool                            seen_econnaborted;
 };
 
 struct io_sr_msg {
@@ -62,7 +63,9 @@ struct io_sr_msg {
        u16                             flags;
        /* initialised and used only by !msg send variants */
        u16                             addr_len;
+       u16                             buf_group;
        void __user                     *addr;
+       void __user                     *msg_control;
        /* used only for send zerocopy */
        struct io_kiocb                 *notif;
 };
@@ -125,13 +128,15 @@ static struct io_async_msghdr *io_msg_alloc_async(struct io_kiocb *req,
        struct io_cache_entry *entry;
        struct io_async_msghdr *hdr;
 
-       if (!(issue_flags & IO_URING_F_UNLOCKED) &&
-           (entry = io_alloc_cache_get(&ctx->netmsg_cache)) != NULL) {
-               hdr = container_of(entry, struct io_async_msghdr, cache);
-               hdr->free_iov = NULL;
-               req->flags |= REQ_F_ASYNC_DATA;
-               req->async_data = hdr;
-               return hdr;
+       if (!(issue_flags & IO_URING_F_UNLOCKED)) {
+               entry = io_alloc_cache_get(&ctx->netmsg_cache);
+               if (entry) {
+                       hdr = container_of(entry, struct io_async_msghdr, cache);
+                       hdr->free_iov = NULL;
+                       req->flags |= REQ_F_ASYNC_DATA;
+                       req->async_data = hdr;
+                       return hdr;
+               }
        }
 
        if (!io_alloc_async_data(req)) {
@@ -178,11 +183,15 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
                               struct io_async_msghdr *iomsg)
 {
        struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+       int ret;
 
        iomsg->msg.msg_name = &iomsg->addr;
        iomsg->free_iov = iomsg->fast_iov;
-       return sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
+       ret = sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
                                        &iomsg->free_iov);
+       /* save msg_control as sys_sendmsg() overwrites it */
+       sr->msg_control = iomsg->msg.msg_control_user;
+       return ret;
 }
 
 int io_send_prep_async(struct io_kiocb *req)
@@ -280,6 +289,7 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
 
        if (req_has_async_data(req)) {
                kmsg = req->async_data;
+               kmsg->msg.msg_control_user = sr->msg_control;
        } else {
                ret = io_sendmsg_copy_hdr(req, &iomsg);
                if (ret)
@@ -303,6 +313,8 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
                if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
                        return io_setup_async_msg(req, kmsg, issue_flags);
                if (ret > 0 && io_net_retry(sock, flags)) {
+                       kmsg->msg.msg_controllen = 0;
+                       kmsg->msg.msg_control = NULL;
                        sr->done_io += ret;
                        req->flags |= REQ_F_PARTIAL_IO;
                        return io_setup_async_msg(req, kmsg, issue_flags);
@@ -363,7 +375,7 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
        if (unlikely(!sock))
                return -ENOTSOCK;
 
-       ret = import_single_range(WRITE, sr->buf, sr->len, &iov, &msg.msg_iter);
+       ret = import_single_range(ITER_SOURCE, sr->buf, sr->len, &iov, &msg.msg_iter);
        if (unlikely(ret))
                return ret;
 
@@ -449,7 +461,7 @@ static int __io_recvmsg_copy_hdr(struct io_kiocb *req,
                }
        } else {
                iomsg->free_iov = iomsg->fast_iov;
-               ret = __import_iovec(READ, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV,
+               ret = __import_iovec(ITER_DEST, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV,
                                     &iomsg->free_iov, &iomsg->msg.msg_iter,
                                     false);
                if (ret > 0)
@@ -479,6 +491,7 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
        if (req->flags & REQ_F_BUFFER_SELECT) {
                compat_ssize_t clen;
 
+               iomsg->free_iov = NULL;
                if (msg.msg_iovlen == 0) {
                        sr->len = 0;
                } else if (msg.msg_iovlen > 1) {
@@ -501,7 +514,7 @@ static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
                }
        } else {
                iomsg->free_iov = iomsg->fast_iov;
-               ret = __import_iovec(READ, (struct iovec __user *)uiov, msg.msg_iovlen,
+               ret = __import_iovec(ITER_DEST, (struct iovec __user *)uiov, msg.msg_iovlen,
                                   UIO_FASTIOV, &iomsg->free_iov,
                                   &iomsg->msg.msg_iter, true);
                if (ret < 0)
@@ -551,7 +564,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        sr->flags = READ_ONCE(sqe->ioprio);
        if (sr->flags & ~(RECVMSG_FLAGS))
                return -EINVAL;
-       sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
+       sr->msg_flags = READ_ONCE(sqe->msg_flags);
        if (sr->msg_flags & MSG_DONTWAIT)
                req->flags |= REQ_F_NOWAIT;
        if (sr->msg_flags & MSG_ERRQUEUE)
@@ -564,6 +577,15 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                if (req->opcode == IORING_OP_RECV && sr->len)
                        return -EINVAL;
                req->flags |= REQ_F_APOLL_MULTISHOT;
+               /*
+                * Store the buffer group for this multishot receive separately,
+                * as if we end up doing an io-wq based issue that selects a
+                * buffer, it has to be committed immediately and that will
+                * clear ->buf_list. This means we lose the link to the buffer
+                * list, and the eventual buffer put on completion then cannot
+                * restore it.
+                */
+               sr->buf_group = req->buf_index;
        }
 
 #ifdef CONFIG_COMPAT
@@ -580,6 +602,7 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
 
        sr->done_io = 0;
        sr->len = 0; /* get from the provided buffer */
+       req->buf_index = sr->buf_group;
 }
 
 /*
@@ -751,23 +774,26 @@ retry_multishot:
 
                kmsg->fast_iov[0].iov_base = buf;
                kmsg->fast_iov[0].iov_len = len;
-               iov_iter_init(&kmsg->msg.msg_iter, READ, kmsg->fast_iov, 1,
+               iov_iter_init(&kmsg->msg.msg_iter, ITER_DEST, kmsg->fast_iov, 1,
                                len);
        }
 
        flags = sr->msg_flags;
        if (force_nonblock)
                flags |= MSG_DONTWAIT;
-       if (flags & MSG_WAITALL)
-               min_ret = iov_iter_count(&kmsg->msg.msg_iter);
 
        kmsg->msg.msg_get_inq = 1;
-       if (req->flags & REQ_F_APOLL_MULTISHOT)
+       if (req->flags & REQ_F_APOLL_MULTISHOT) {
                ret = io_recvmsg_multishot(sock, sr, kmsg, flags,
                                           &mshot_finished);
-       else
+       } else {
+               /* disable partial retry for recvmsg with cmsg attached */
+               if (flags & MSG_WAITALL && !kmsg->msg.msg_controllen)
+                       min_ret = iov_iter_count(&kmsg->msg.msg_iter);
+
                ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
                                         kmsg->uaddr, flags);
+       }
 
        if (ret < min_ret) {
                if (ret == -EAGAIN && force_nonblock) {
@@ -805,10 +831,10 @@ retry_multishot:
                goto retry_multishot;
 
        if (mshot_finished) {
-               io_netmsg_recycle(req, issue_flags);
                /* fast path, check for non-NULL to avoid function call */
                if (kmsg->free_iov)
                        kfree(kmsg->free_iov);
+               io_netmsg_recycle(req, issue_flags);
                req->flags &= ~REQ_F_NEED_CLEANUP;
        }
 
@@ -845,7 +871,7 @@ retry_multishot:
                sr->buf = buf;
        }
 
-       ret = import_single_range(READ, sr->buf, len, &iov, &msg.msg_iter);
+       ret = import_single_range(ITER_DEST, sr->buf, len, &iov, &msg.msg_iter);
        if (unlikely(ret))
                goto out_free;
 
@@ -937,7 +963,8 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        zc->flags = READ_ONCE(sqe->ioprio);
        if (zc->flags & ~(IORING_RECVSEND_POLL_FIRST |
-                         IORING_RECVSEND_FIXED_BUF))
+                         IORING_RECVSEND_FIXED_BUF |
+                         IORING_SEND_ZC_REPORT_USAGE))
                return -EINVAL;
        notif = zc->notif = io_alloc_notif(ctx);
        if (!notif)
@@ -955,6 +982,9 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                req->imu = READ_ONCE(ctx->user_bufs[idx]);
                io_req_set_rsrc_node(notif, ctx, 0);
        }
+       if (zc->flags & IORING_SEND_ZC_REPORT_USAGE) {
+               io_notif_to_data(notif)->zc_report = true;
+       }
 
        if (req->opcode == IORING_OP_SEND_ZC) {
                if (READ_ONCE(sqe->__pad3[0]))
@@ -1081,13 +1111,13 @@ int io_send_zc(struct io_kiocb *req, unsigned int issue_flags)
                return io_setup_async_addr(req, &__address, issue_flags);
 
        if (zc->flags & IORING_RECVSEND_FIXED_BUF) {
-               ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu,
+               ret = io_import_fixed(ITER_SOURCE, &msg.msg_iter, req->imu,
                                        (u64)(uintptr_t)zc->buf, zc->len);
                if (unlikely(ret))
                        return ret;
                msg.sg_from_iter = io_sg_from_iter;
        } else {
-               ret = import_single_range(WRITE, zc->buf, zc->len, &iov,
+               ret = import_single_range(ITER_SOURCE, zc->buf, zc->len, &iov,
                                          &msg.msg_iter);
                if (unlikely(ret))
                        return ret;
@@ -1386,7 +1416,7 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
        conn->addr_len =  READ_ONCE(sqe->addr2);
-       conn->in_progress = false;
+       conn->in_progress = conn->seen_econnaborted = false;
        return 0;
 }
 
@@ -1423,18 +1453,24 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 
        ret = __sys_connect_file(req->file, &io->address,
                                        connect->addr_len, file_flags);
-       if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
+       if ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
+           && force_nonblock) {
                if (ret == -EINPROGRESS) {
                        connect->in_progress = true;
-               } else {
-                       if (req_has_async_data(req))
-                               return -EAGAIN;
-                       if (io_alloc_async_data(req)) {
-                               ret = -ENOMEM;
+                       return -EAGAIN;
+               }
+               if (ret == -ECONNABORTED) {
+                       if (connect->seen_econnaborted)
                                goto out;
-                       }
-                       memcpy(req->async_data, &__io, sizeof(__io));
+                       connect->seen_econnaborted = true;
+               }
+               if (req_has_async_data(req))
+                       return -EAGAIN;
+               if (io_alloc_async_data(req)) {
+                       ret = -ENOMEM;
+                       goto out;
                }
+               memcpy(req->async_data, &__io, sizeof(__io));
                return -EAGAIN;
        }
        if (ret == -ERESTARTSYS)