Merge tag 'kvm-x86-mmu-6.5' of https://github.com/kvm-x86/linux into HEAD
[linux-block.git] / io_uring / net.c
index 89e839013837ffd34947076ae7e9be54e1b1cfc7..c8a4b2ac00f7801a3575fe7b9f5b4ab6555bd05b 100644 (file)
@@ -65,6 +65,7 @@ struct io_sr_msg {
        u16                             addr_len;
        u16                             buf_group;
        void __user                     *addr;
+       void __user                     *msg_control;
        /* used only for send zerocopy */
        struct io_kiocb                 *notif;
 };
@@ -195,11 +196,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)
@@ -297,6 +302,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)
@@ -320,6 +326,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);
@@ -781,16 +789,19 @@ retry_multishot:
        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) {