1f9ead18cSJens Axboe // SPDX-License-Identifier: GPL-2.0 2f9ead18cSJens Axboe #include <linux/kernel.h> 3f9ead18cSJens Axboe #include <linux/errno.h> 4f9ead18cSJens Axboe #include <linux/file.h> 5f9ead18cSJens Axboe #include <linux/slab.h> 6f9ead18cSJens Axboe #include <linux/net.h> 7f9ead18cSJens Axboe #include <linux/compat.h> 8f9ead18cSJens Axboe #include <net/compat.h> 9f9ead18cSJens Axboe #include <linux/io_uring.h> 10f9ead18cSJens Axboe 11f9ead18cSJens Axboe #include <uapi/linux/io_uring.h> 12f9ead18cSJens Axboe 13f9ead18cSJens Axboe #include "io_uring.h" 143b77495aSJens Axboe #include "kbuf.h" 15f9ead18cSJens Axboe #include "net.h" 16f9ead18cSJens Axboe 17f9ead18cSJens Axboe #if defined(CONFIG_NET) 18f9ead18cSJens Axboe struct io_shutdown { 19f9ead18cSJens Axboe struct file *file; 20f9ead18cSJens Axboe int how; 21f9ead18cSJens Axboe }; 22f9ead18cSJens Axboe 23f9ead18cSJens Axboe struct io_accept { 24f9ead18cSJens Axboe struct file *file; 25f9ead18cSJens Axboe struct sockaddr __user *addr; 26f9ead18cSJens Axboe int __user *addr_len; 27f9ead18cSJens Axboe int flags; 28f9ead18cSJens Axboe u32 file_slot; 29f9ead18cSJens Axboe unsigned long nofile; 30f9ead18cSJens Axboe }; 31f9ead18cSJens Axboe 32f9ead18cSJens Axboe struct io_socket { 33f9ead18cSJens Axboe struct file *file; 34f9ead18cSJens Axboe int domain; 35f9ead18cSJens Axboe int type; 36f9ead18cSJens Axboe int protocol; 37f9ead18cSJens Axboe int flags; 38f9ead18cSJens Axboe u32 file_slot; 39f9ead18cSJens Axboe unsigned long nofile; 40f9ead18cSJens Axboe }; 41f9ead18cSJens Axboe 42f9ead18cSJens Axboe struct io_connect { 43f9ead18cSJens Axboe struct file *file; 44f9ead18cSJens Axboe struct sockaddr __user *addr; 45f9ead18cSJens Axboe int addr_len; 46f9ead18cSJens Axboe }; 47f9ead18cSJens Axboe 48f9ead18cSJens Axboe struct io_sr_msg { 49f9ead18cSJens Axboe struct file *file; 50f9ead18cSJens Axboe union { 51f9ead18cSJens Axboe struct compat_msghdr __user *umsg_compat; 52f9ead18cSJens Axboe struct user_msghdr __user *umsg; 53f9ead18cSJens Axboe void __user *buf; 54f9ead18cSJens Axboe }; 55f9ead18cSJens Axboe int msg_flags; 56f9ead18cSJens Axboe size_t len; 57f9ead18cSJens Axboe size_t done_io; 58f9ead18cSJens Axboe unsigned int flags; 59f9ead18cSJens Axboe }; 60f9ead18cSJens Axboe 61f9ead18cSJens Axboe #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED) 62f9ead18cSJens Axboe 63f9ead18cSJens Axboe int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 64f9ead18cSJens Axboe { 65f9ead18cSJens Axboe struct io_shutdown *shutdown = io_kiocb_to_cmd(req); 66f9ead18cSJens Axboe 67f9ead18cSJens Axboe if (unlikely(sqe->off || sqe->addr || sqe->rw_flags || 68f9ead18cSJens Axboe sqe->buf_index || sqe->splice_fd_in)) 69f9ead18cSJens Axboe return -EINVAL; 70f9ead18cSJens Axboe 71f9ead18cSJens Axboe shutdown->how = READ_ONCE(sqe->len); 72f9ead18cSJens Axboe return 0; 73f9ead18cSJens Axboe } 74f9ead18cSJens Axboe 75f9ead18cSJens Axboe int io_shutdown(struct io_kiocb *req, unsigned int issue_flags) 76f9ead18cSJens Axboe { 77f9ead18cSJens Axboe struct io_shutdown *shutdown = io_kiocb_to_cmd(req); 78f9ead18cSJens Axboe struct socket *sock; 79f9ead18cSJens Axboe int ret; 80f9ead18cSJens Axboe 81f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 82f9ead18cSJens Axboe return -EAGAIN; 83f9ead18cSJens Axboe 84f9ead18cSJens Axboe sock = sock_from_file(req->file); 85f9ead18cSJens Axboe if (unlikely(!sock)) 86f9ead18cSJens Axboe return -ENOTSOCK; 87f9ead18cSJens Axboe 88f9ead18cSJens Axboe ret = __sys_shutdown_sock(sock, shutdown->how); 89f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 90f9ead18cSJens Axboe return IOU_OK; 91f9ead18cSJens Axboe } 92f9ead18cSJens Axboe 93f9ead18cSJens Axboe static bool io_net_retry(struct socket *sock, int flags) 94f9ead18cSJens Axboe { 95f9ead18cSJens Axboe if (!(flags & MSG_WAITALL)) 96f9ead18cSJens Axboe return false; 97f9ead18cSJens Axboe return sock->type == SOCK_STREAM || sock->type == SOCK_SEQPACKET; 98f9ead18cSJens Axboe } 99f9ead18cSJens Axboe 100f9ead18cSJens Axboe static int io_setup_async_msg(struct io_kiocb *req, 101f9ead18cSJens Axboe struct io_async_msghdr *kmsg) 102f9ead18cSJens Axboe { 103f9ead18cSJens Axboe struct io_async_msghdr *async_msg = req->async_data; 104f9ead18cSJens Axboe 105f9ead18cSJens Axboe if (async_msg) 106f9ead18cSJens Axboe return -EAGAIN; 107f9ead18cSJens Axboe if (io_alloc_async_data(req)) { 108f9ead18cSJens Axboe kfree(kmsg->free_iov); 109f9ead18cSJens Axboe return -ENOMEM; 110f9ead18cSJens Axboe } 111f9ead18cSJens Axboe async_msg = req->async_data; 112f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 113f9ead18cSJens Axboe memcpy(async_msg, kmsg, sizeof(*kmsg)); 114f9ead18cSJens Axboe async_msg->msg.msg_name = &async_msg->addr; 115f9ead18cSJens Axboe /* if were using fast_iov, set it to the new one */ 116f9ead18cSJens Axboe if (!async_msg->free_iov) 117f9ead18cSJens Axboe async_msg->msg.msg_iter.iov = async_msg->fast_iov; 118f9ead18cSJens Axboe 119f9ead18cSJens Axboe return -EAGAIN; 120f9ead18cSJens Axboe } 121f9ead18cSJens Axboe 122f9ead18cSJens Axboe static int io_sendmsg_copy_hdr(struct io_kiocb *req, 123f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 124f9ead18cSJens Axboe { 125f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 126f9ead18cSJens Axboe 127f9ead18cSJens Axboe iomsg->msg.msg_name = &iomsg->addr; 128f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 129f9ead18cSJens Axboe return sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags, 130f9ead18cSJens Axboe &iomsg->free_iov); 131f9ead18cSJens Axboe } 132f9ead18cSJens Axboe 133f9ead18cSJens Axboe int io_sendmsg_prep_async(struct io_kiocb *req) 134f9ead18cSJens Axboe { 135f9ead18cSJens Axboe int ret; 136f9ead18cSJens Axboe 137f9ead18cSJens Axboe ret = io_sendmsg_copy_hdr(req, req->async_data); 138f9ead18cSJens Axboe if (!ret) 139f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 140f9ead18cSJens Axboe return ret; 141f9ead18cSJens Axboe } 142f9ead18cSJens Axboe 143f9ead18cSJens Axboe void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req) 144f9ead18cSJens Axboe { 145f9ead18cSJens Axboe struct io_async_msghdr *io = req->async_data; 146f9ead18cSJens Axboe 147f9ead18cSJens Axboe kfree(io->free_iov); 148f9ead18cSJens Axboe } 149f9ead18cSJens Axboe 150f9ead18cSJens Axboe int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 151f9ead18cSJens Axboe { 152f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 153f9ead18cSJens Axboe 154f9ead18cSJens Axboe if (unlikely(sqe->file_index || sqe->addr2)) 155f9ead18cSJens Axboe return -EINVAL; 156f9ead18cSJens Axboe 157f9ead18cSJens Axboe sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); 158f9ead18cSJens Axboe sr->len = READ_ONCE(sqe->len); 159f9ead18cSJens Axboe sr->flags = READ_ONCE(sqe->ioprio); 160f9ead18cSJens Axboe if (sr->flags & ~IORING_RECVSEND_POLL_FIRST) 161f9ead18cSJens Axboe return -EINVAL; 162f9ead18cSJens Axboe sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL; 163f9ead18cSJens Axboe if (sr->msg_flags & MSG_DONTWAIT) 164f9ead18cSJens Axboe req->flags |= REQ_F_NOWAIT; 165f9ead18cSJens Axboe 166f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 167f9ead18cSJens Axboe if (req->ctx->compat) 168f9ead18cSJens Axboe sr->msg_flags |= MSG_CMSG_COMPAT; 169f9ead18cSJens Axboe #endif 170f9ead18cSJens Axboe sr->done_io = 0; 171f9ead18cSJens Axboe return 0; 172f9ead18cSJens Axboe } 173f9ead18cSJens Axboe 174f9ead18cSJens Axboe int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags) 175f9ead18cSJens Axboe { 176f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 177f9ead18cSJens Axboe struct io_async_msghdr iomsg, *kmsg; 178f9ead18cSJens Axboe struct socket *sock; 179f9ead18cSJens Axboe unsigned flags; 180f9ead18cSJens Axboe int min_ret = 0; 181f9ead18cSJens Axboe int ret; 182f9ead18cSJens Axboe 183f9ead18cSJens Axboe sock = sock_from_file(req->file); 184f9ead18cSJens Axboe if (unlikely(!sock)) 185f9ead18cSJens Axboe return -ENOTSOCK; 186f9ead18cSJens Axboe 187f9ead18cSJens Axboe if (req_has_async_data(req)) { 188f9ead18cSJens Axboe kmsg = req->async_data; 189f9ead18cSJens Axboe } else { 190f9ead18cSJens Axboe ret = io_sendmsg_copy_hdr(req, &iomsg); 191f9ead18cSJens Axboe if (ret) 192f9ead18cSJens Axboe return ret; 193f9ead18cSJens Axboe kmsg = &iomsg; 194f9ead18cSJens Axboe } 195f9ead18cSJens Axboe 196f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 197f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 198f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 199f9ead18cSJens Axboe 200f9ead18cSJens Axboe flags = sr->msg_flags; 201f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 202f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 203f9ead18cSJens Axboe if (flags & MSG_WAITALL) 204f9ead18cSJens Axboe min_ret = iov_iter_count(&kmsg->msg.msg_iter); 205f9ead18cSJens Axboe 206f9ead18cSJens Axboe ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags); 207f9ead18cSJens Axboe 208f9ead18cSJens Axboe if (ret < min_ret) { 209f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 210f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 211f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 212f9ead18cSJens Axboe ret = -EINTR; 213f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 214f9ead18cSJens Axboe sr->done_io += ret; 215f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 216f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 217f9ead18cSJens Axboe } 218f9ead18cSJens Axboe req_set_fail(req); 219f9ead18cSJens Axboe } 220f9ead18cSJens Axboe /* fast path, check for non-NULL to avoid function call */ 221f9ead18cSJens Axboe if (kmsg->free_iov) 222f9ead18cSJens Axboe kfree(kmsg->free_iov); 223f9ead18cSJens Axboe req->flags &= ~REQ_F_NEED_CLEANUP; 224f9ead18cSJens Axboe if (ret >= 0) 225f9ead18cSJens Axboe ret += sr->done_io; 226f9ead18cSJens Axboe else if (sr->done_io) 227f9ead18cSJens Axboe ret = sr->done_io; 228f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 229f9ead18cSJens Axboe return IOU_OK; 230f9ead18cSJens Axboe } 231f9ead18cSJens Axboe 232f9ead18cSJens Axboe int io_send(struct io_kiocb *req, unsigned int issue_flags) 233f9ead18cSJens Axboe { 234f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 235f9ead18cSJens Axboe struct msghdr msg; 236f9ead18cSJens Axboe struct iovec iov; 237f9ead18cSJens Axboe struct socket *sock; 238f9ead18cSJens Axboe unsigned flags; 239f9ead18cSJens Axboe int min_ret = 0; 240f9ead18cSJens Axboe int ret; 241f9ead18cSJens Axboe 242f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 243f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 244f9ead18cSJens Axboe return -EAGAIN; 245f9ead18cSJens Axboe 246f9ead18cSJens Axboe sock = sock_from_file(req->file); 247f9ead18cSJens Axboe if (unlikely(!sock)) 248f9ead18cSJens Axboe return -ENOTSOCK; 249f9ead18cSJens Axboe 250f9ead18cSJens Axboe ret = import_single_range(WRITE, sr->buf, sr->len, &iov, &msg.msg_iter); 251f9ead18cSJens Axboe if (unlikely(ret)) 252f9ead18cSJens Axboe return ret; 253f9ead18cSJens Axboe 254f9ead18cSJens Axboe msg.msg_name = NULL; 255f9ead18cSJens Axboe msg.msg_control = NULL; 256f9ead18cSJens Axboe msg.msg_controllen = 0; 257f9ead18cSJens Axboe msg.msg_namelen = 0; 258f9ead18cSJens Axboe 259f9ead18cSJens Axboe flags = sr->msg_flags; 260f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 261f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 262f9ead18cSJens Axboe if (flags & MSG_WAITALL) 263f9ead18cSJens Axboe min_ret = iov_iter_count(&msg.msg_iter); 264f9ead18cSJens Axboe 265f9ead18cSJens Axboe msg.msg_flags = flags; 266f9ead18cSJens Axboe ret = sock_sendmsg(sock, &msg); 267f9ead18cSJens Axboe if (ret < min_ret) { 268f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 269f9ead18cSJens Axboe return -EAGAIN; 270f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 271f9ead18cSJens Axboe ret = -EINTR; 272f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 273f9ead18cSJens Axboe sr->len -= ret; 274f9ead18cSJens Axboe sr->buf += ret; 275f9ead18cSJens Axboe sr->done_io += ret; 276f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 277f9ead18cSJens Axboe return -EAGAIN; 278f9ead18cSJens Axboe } 279f9ead18cSJens Axboe req_set_fail(req); 280f9ead18cSJens Axboe } 281f9ead18cSJens Axboe if (ret >= 0) 282f9ead18cSJens Axboe ret += sr->done_io; 283f9ead18cSJens Axboe else if (sr->done_io) 284f9ead18cSJens Axboe ret = sr->done_io; 285f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 286f9ead18cSJens Axboe return IOU_OK; 287f9ead18cSJens Axboe } 288f9ead18cSJens Axboe 289f9ead18cSJens Axboe static int __io_recvmsg_copy_hdr(struct io_kiocb *req, 290f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 291f9ead18cSJens Axboe { 292f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 293f9ead18cSJens Axboe struct iovec __user *uiov; 294f9ead18cSJens Axboe size_t iov_len; 295f9ead18cSJens Axboe int ret; 296f9ead18cSJens Axboe 297f9ead18cSJens Axboe ret = __copy_msghdr_from_user(&iomsg->msg, sr->umsg, 298f9ead18cSJens Axboe &iomsg->uaddr, &uiov, &iov_len); 299f9ead18cSJens Axboe if (ret) 300f9ead18cSJens Axboe return ret; 301f9ead18cSJens Axboe 302f9ead18cSJens Axboe if (req->flags & REQ_F_BUFFER_SELECT) { 3035702196eSDylan Yudaken if (iov_len == 0) { 3045702196eSDylan Yudaken sr->len = iomsg->fast_iov[0].iov_len = 0; 3055702196eSDylan Yudaken iomsg->fast_iov[0].iov_base = NULL; 3065702196eSDylan Yudaken iomsg->free_iov = NULL; 3075702196eSDylan Yudaken } else if (iov_len > 1) { 308f9ead18cSJens Axboe return -EINVAL; 3095702196eSDylan Yudaken } else { 310f9ead18cSJens Axboe if (copy_from_user(iomsg->fast_iov, uiov, sizeof(*uiov))) 311f9ead18cSJens Axboe return -EFAULT; 312f9ead18cSJens Axboe sr->len = iomsg->fast_iov[0].iov_len; 313f9ead18cSJens Axboe iomsg->free_iov = NULL; 3145702196eSDylan Yudaken } 315f9ead18cSJens Axboe } else { 316f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 317f9ead18cSJens Axboe ret = __import_iovec(READ, uiov, iov_len, UIO_FASTIOV, 318f9ead18cSJens Axboe &iomsg->free_iov, &iomsg->msg.msg_iter, 319f9ead18cSJens Axboe false); 320f9ead18cSJens Axboe if (ret > 0) 321f9ead18cSJens Axboe ret = 0; 322f9ead18cSJens Axboe } 323f9ead18cSJens Axboe 324f9ead18cSJens Axboe return ret; 325f9ead18cSJens Axboe } 326f9ead18cSJens Axboe 327f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 328f9ead18cSJens Axboe static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req, 329f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 330f9ead18cSJens Axboe { 331f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 332f9ead18cSJens Axboe struct compat_iovec __user *uiov; 333f9ead18cSJens Axboe compat_uptr_t ptr; 334f9ead18cSJens Axboe compat_size_t len; 335f9ead18cSJens Axboe int ret; 336f9ead18cSJens Axboe 337f9ead18cSJens Axboe ret = __get_compat_msghdr(&iomsg->msg, sr->umsg_compat, &iomsg->uaddr, 338f9ead18cSJens Axboe &ptr, &len); 339f9ead18cSJens Axboe if (ret) 340f9ead18cSJens Axboe return ret; 341f9ead18cSJens Axboe 342f9ead18cSJens Axboe uiov = compat_ptr(ptr); 343f9ead18cSJens Axboe if (req->flags & REQ_F_BUFFER_SELECT) { 344f9ead18cSJens Axboe compat_ssize_t clen; 345f9ead18cSJens Axboe 346f9ead18cSJens Axboe if (len > 1) 347f9ead18cSJens Axboe return -EINVAL; 348f9ead18cSJens Axboe if (!access_ok(uiov, sizeof(*uiov))) 349f9ead18cSJens Axboe return -EFAULT; 350f9ead18cSJens Axboe if (__get_user(clen, &uiov->iov_len)) 351f9ead18cSJens Axboe return -EFAULT; 352f9ead18cSJens Axboe if (clen < 0) 353f9ead18cSJens Axboe return -EINVAL; 354f9ead18cSJens Axboe sr->len = clen; 355f9ead18cSJens Axboe iomsg->free_iov = NULL; 356f9ead18cSJens Axboe } else { 357f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 358f9ead18cSJens Axboe ret = __import_iovec(READ, (struct iovec __user *)uiov, len, 359f9ead18cSJens Axboe UIO_FASTIOV, &iomsg->free_iov, 360f9ead18cSJens Axboe &iomsg->msg.msg_iter, true); 361f9ead18cSJens Axboe if (ret < 0) 362f9ead18cSJens Axboe return ret; 363f9ead18cSJens Axboe } 364f9ead18cSJens Axboe 365f9ead18cSJens Axboe return 0; 366f9ead18cSJens Axboe } 367f9ead18cSJens Axboe #endif 368f9ead18cSJens Axboe 369f9ead18cSJens Axboe static int io_recvmsg_copy_hdr(struct io_kiocb *req, 370f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 371f9ead18cSJens Axboe { 372f9ead18cSJens Axboe iomsg->msg.msg_name = &iomsg->addr; 373f9ead18cSJens Axboe 374f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 375f9ead18cSJens Axboe if (req->ctx->compat) 376f9ead18cSJens Axboe return __io_compat_recvmsg_copy_hdr(req, iomsg); 377f9ead18cSJens Axboe #endif 378f9ead18cSJens Axboe 379f9ead18cSJens Axboe return __io_recvmsg_copy_hdr(req, iomsg); 380f9ead18cSJens Axboe } 381f9ead18cSJens Axboe 382f9ead18cSJens Axboe int io_recvmsg_prep_async(struct io_kiocb *req) 383f9ead18cSJens Axboe { 384f9ead18cSJens Axboe int ret; 385f9ead18cSJens Axboe 386f9ead18cSJens Axboe ret = io_recvmsg_copy_hdr(req, req->async_data); 387f9ead18cSJens Axboe if (!ret) 388f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 389f9ead18cSJens Axboe return ret; 390f9ead18cSJens Axboe } 391f9ead18cSJens Axboe 392f9ead18cSJens Axboe int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 393f9ead18cSJens Axboe { 394f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 395f9ead18cSJens Axboe 396f9ead18cSJens Axboe if (unlikely(sqe->file_index || sqe->addr2)) 397f9ead18cSJens Axboe return -EINVAL; 398f9ead18cSJens Axboe 399f9ead18cSJens Axboe sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); 400f9ead18cSJens Axboe sr->len = READ_ONCE(sqe->len); 401f9ead18cSJens Axboe sr->flags = READ_ONCE(sqe->ioprio); 402f9ead18cSJens Axboe if (sr->flags & ~IORING_RECVSEND_POLL_FIRST) 403f9ead18cSJens Axboe return -EINVAL; 404f9ead18cSJens Axboe sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL; 405f9ead18cSJens Axboe if (sr->msg_flags & MSG_DONTWAIT) 406f9ead18cSJens Axboe req->flags |= REQ_F_NOWAIT; 407f9ead18cSJens Axboe if (sr->msg_flags & MSG_ERRQUEUE) 408f9ead18cSJens Axboe req->flags |= REQ_F_CLEAR_POLLIN; 409f9ead18cSJens Axboe 410f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 411f9ead18cSJens Axboe if (req->ctx->compat) 412f9ead18cSJens Axboe sr->msg_flags |= MSG_CMSG_COMPAT; 413f9ead18cSJens Axboe #endif 414f9ead18cSJens Axboe sr->done_io = 0; 415f9ead18cSJens Axboe return 0; 416f9ead18cSJens Axboe } 417f9ead18cSJens Axboe 418f9ead18cSJens Axboe int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags) 419f9ead18cSJens Axboe { 420f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 421f9ead18cSJens Axboe struct io_async_msghdr iomsg, *kmsg; 422f9ead18cSJens Axboe struct socket *sock; 423f9ead18cSJens Axboe unsigned int cflags; 424f9ead18cSJens Axboe unsigned flags; 425f9ead18cSJens Axboe int ret, min_ret = 0; 426f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 427f9ead18cSJens Axboe 428f9ead18cSJens Axboe sock = sock_from_file(req->file); 429f9ead18cSJens Axboe if (unlikely(!sock)) 430f9ead18cSJens Axboe return -ENOTSOCK; 431f9ead18cSJens Axboe 432f9ead18cSJens Axboe if (req_has_async_data(req)) { 433f9ead18cSJens Axboe kmsg = req->async_data; 434f9ead18cSJens Axboe } else { 435f9ead18cSJens Axboe ret = io_recvmsg_copy_hdr(req, &iomsg); 436f9ead18cSJens Axboe if (ret) 437f9ead18cSJens Axboe return ret; 438f9ead18cSJens Axboe kmsg = &iomsg; 439f9ead18cSJens Axboe } 440f9ead18cSJens Axboe 441f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 442f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 443f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 444f9ead18cSJens Axboe 445f9ead18cSJens Axboe if (io_do_buffer_select(req)) { 446f9ead18cSJens Axboe void __user *buf; 447f9ead18cSJens Axboe 448f9ead18cSJens Axboe buf = io_buffer_select(req, &sr->len, issue_flags); 449f9ead18cSJens Axboe if (!buf) 450f9ead18cSJens Axboe return -ENOBUFS; 451f9ead18cSJens Axboe kmsg->fast_iov[0].iov_base = buf; 452f9ead18cSJens Axboe kmsg->fast_iov[0].iov_len = sr->len; 453f9ead18cSJens Axboe iov_iter_init(&kmsg->msg.msg_iter, READ, kmsg->fast_iov, 1, 454f9ead18cSJens Axboe sr->len); 455f9ead18cSJens Axboe } 456f9ead18cSJens Axboe 457f9ead18cSJens Axboe flags = sr->msg_flags; 458f9ead18cSJens Axboe if (force_nonblock) 459f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 460f9ead18cSJens Axboe if (flags & MSG_WAITALL) 461f9ead18cSJens Axboe min_ret = iov_iter_count(&kmsg->msg.msg_iter); 462f9ead18cSJens Axboe 463f9ead18cSJens Axboe kmsg->msg.msg_get_inq = 1; 464f9ead18cSJens Axboe ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg, kmsg->uaddr, flags); 465f9ead18cSJens Axboe if (ret < min_ret) { 466f9ead18cSJens Axboe if (ret == -EAGAIN && force_nonblock) 467f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 468f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 469f9ead18cSJens Axboe ret = -EINTR; 470f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 471f9ead18cSJens Axboe sr->done_io += ret; 472f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 473f9ead18cSJens Axboe return io_setup_async_msg(req, kmsg); 474f9ead18cSJens Axboe } 475f9ead18cSJens Axboe req_set_fail(req); 476f9ead18cSJens Axboe } else if ((flags & MSG_WAITALL) && (kmsg->msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { 477f9ead18cSJens Axboe req_set_fail(req); 478f9ead18cSJens Axboe } 479f9ead18cSJens Axboe 480f9ead18cSJens Axboe /* fast path, check for non-NULL to avoid function call */ 481f9ead18cSJens Axboe if (kmsg->free_iov) 482f9ead18cSJens Axboe kfree(kmsg->free_iov); 483f9ead18cSJens Axboe req->flags &= ~REQ_F_NEED_CLEANUP; 484*d4e097daSDylan Yudaken if (ret > 0) 485f9ead18cSJens Axboe ret += sr->done_io; 486f9ead18cSJens Axboe else if (sr->done_io) 487f9ead18cSJens Axboe ret = sr->done_io; 488*d4e097daSDylan Yudaken else 489*d4e097daSDylan Yudaken io_kbuf_recycle(req, issue_flags); 490*d4e097daSDylan Yudaken 491f9ead18cSJens Axboe cflags = io_put_kbuf(req, issue_flags); 492f9ead18cSJens Axboe if (kmsg->msg.msg_inq) 493f9ead18cSJens Axboe cflags |= IORING_CQE_F_SOCK_NONEMPTY; 494f9ead18cSJens Axboe io_req_set_res(req, ret, cflags); 495f9ead18cSJens Axboe return IOU_OK; 496f9ead18cSJens Axboe } 497f9ead18cSJens Axboe 498f9ead18cSJens Axboe int io_recv(struct io_kiocb *req, unsigned int issue_flags) 499f9ead18cSJens Axboe { 500f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 501f9ead18cSJens Axboe struct msghdr msg; 502f9ead18cSJens Axboe struct socket *sock; 503f9ead18cSJens Axboe struct iovec iov; 504f9ead18cSJens Axboe unsigned int cflags; 505f9ead18cSJens Axboe unsigned flags; 506f9ead18cSJens Axboe int ret, min_ret = 0; 507f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 508f9ead18cSJens Axboe 509f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 510f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 511f9ead18cSJens Axboe return -EAGAIN; 512f9ead18cSJens Axboe 513f9ead18cSJens Axboe sock = sock_from_file(req->file); 514f9ead18cSJens Axboe if (unlikely(!sock)) 515f9ead18cSJens Axboe return -ENOTSOCK; 516f9ead18cSJens Axboe 517f9ead18cSJens Axboe if (io_do_buffer_select(req)) { 518f9ead18cSJens Axboe void __user *buf; 519f9ead18cSJens Axboe 520f9ead18cSJens Axboe buf = io_buffer_select(req, &sr->len, issue_flags); 521f9ead18cSJens Axboe if (!buf) 522f9ead18cSJens Axboe return -ENOBUFS; 523f9ead18cSJens Axboe sr->buf = buf; 524f9ead18cSJens Axboe } 525f9ead18cSJens Axboe 526f9ead18cSJens Axboe ret = import_single_range(READ, sr->buf, sr->len, &iov, &msg.msg_iter); 527f9ead18cSJens Axboe if (unlikely(ret)) 528f9ead18cSJens Axboe goto out_free; 529f9ead18cSJens Axboe 530f9ead18cSJens Axboe msg.msg_name = NULL; 531f9ead18cSJens Axboe msg.msg_namelen = 0; 532f9ead18cSJens Axboe msg.msg_control = NULL; 533f9ead18cSJens Axboe msg.msg_get_inq = 1; 534f9ead18cSJens Axboe msg.msg_flags = 0; 535f9ead18cSJens Axboe msg.msg_controllen = 0; 536f9ead18cSJens Axboe msg.msg_iocb = NULL; 537f9ead18cSJens Axboe 538f9ead18cSJens Axboe flags = sr->msg_flags; 539f9ead18cSJens Axboe if (force_nonblock) 540f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 541f9ead18cSJens Axboe if (flags & MSG_WAITALL) 542f9ead18cSJens Axboe min_ret = iov_iter_count(&msg.msg_iter); 543f9ead18cSJens Axboe 544f9ead18cSJens Axboe ret = sock_recvmsg(sock, &msg, flags); 545f9ead18cSJens Axboe if (ret < min_ret) { 546f9ead18cSJens Axboe if (ret == -EAGAIN && force_nonblock) 547f9ead18cSJens Axboe return -EAGAIN; 548f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 549f9ead18cSJens Axboe ret = -EINTR; 550f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 551f9ead18cSJens Axboe sr->len -= ret; 552f9ead18cSJens Axboe sr->buf += ret; 553f9ead18cSJens Axboe sr->done_io += ret; 554f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 555f9ead18cSJens Axboe return -EAGAIN; 556f9ead18cSJens Axboe } 557f9ead18cSJens Axboe req_set_fail(req); 558f9ead18cSJens Axboe } else if ((flags & MSG_WAITALL) && (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { 559f9ead18cSJens Axboe out_free: 560f9ead18cSJens Axboe req_set_fail(req); 561f9ead18cSJens Axboe } 562f9ead18cSJens Axboe 563*d4e097daSDylan Yudaken if (ret > 0) 564f9ead18cSJens Axboe ret += sr->done_io; 565f9ead18cSJens Axboe else if (sr->done_io) 566f9ead18cSJens Axboe ret = sr->done_io; 567*d4e097daSDylan Yudaken else 568*d4e097daSDylan Yudaken io_kbuf_recycle(req, issue_flags); 569*d4e097daSDylan Yudaken 570f9ead18cSJens Axboe cflags = io_put_kbuf(req, issue_flags); 571f9ead18cSJens Axboe if (msg.msg_inq) 572f9ead18cSJens Axboe cflags |= IORING_CQE_F_SOCK_NONEMPTY; 573f9ead18cSJens Axboe io_req_set_res(req, ret, cflags); 574f9ead18cSJens Axboe return IOU_OK; 575f9ead18cSJens Axboe } 576f9ead18cSJens Axboe 577f9ead18cSJens Axboe int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 578f9ead18cSJens Axboe { 579f9ead18cSJens Axboe struct io_accept *accept = io_kiocb_to_cmd(req); 580f9ead18cSJens Axboe unsigned flags; 581f9ead18cSJens Axboe 582f9ead18cSJens Axboe if (sqe->len || sqe->buf_index) 583f9ead18cSJens Axboe return -EINVAL; 584f9ead18cSJens Axboe 585f9ead18cSJens Axboe accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr)); 586f9ead18cSJens Axboe accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 587f9ead18cSJens Axboe accept->flags = READ_ONCE(sqe->accept_flags); 588f9ead18cSJens Axboe accept->nofile = rlimit(RLIMIT_NOFILE); 589f9ead18cSJens Axboe flags = READ_ONCE(sqe->ioprio); 590f9ead18cSJens Axboe if (flags & ~IORING_ACCEPT_MULTISHOT) 591f9ead18cSJens Axboe return -EINVAL; 592f9ead18cSJens Axboe 593f9ead18cSJens Axboe accept->file_slot = READ_ONCE(sqe->file_index); 594f9ead18cSJens Axboe if (accept->file_slot) { 595f9ead18cSJens Axboe if (accept->flags & SOCK_CLOEXEC) 596f9ead18cSJens Axboe return -EINVAL; 597f9ead18cSJens Axboe if (flags & IORING_ACCEPT_MULTISHOT && 598f9ead18cSJens Axboe accept->file_slot != IORING_FILE_INDEX_ALLOC) 599f9ead18cSJens Axboe return -EINVAL; 600f9ead18cSJens Axboe } 601f9ead18cSJens Axboe if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 602f9ead18cSJens Axboe return -EINVAL; 603f9ead18cSJens Axboe if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK)) 604f9ead18cSJens Axboe accept->flags = (accept->flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 605f9ead18cSJens Axboe if (flags & IORING_ACCEPT_MULTISHOT) 606f9ead18cSJens Axboe req->flags |= REQ_F_APOLL_MULTISHOT; 607f9ead18cSJens Axboe return 0; 608f9ead18cSJens Axboe } 609f9ead18cSJens Axboe 610f9ead18cSJens Axboe int io_accept(struct io_kiocb *req, unsigned int issue_flags) 611f9ead18cSJens Axboe { 612f9ead18cSJens Axboe struct io_ring_ctx *ctx = req->ctx; 613f9ead18cSJens Axboe struct io_accept *accept = io_kiocb_to_cmd(req); 614f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 615f9ead18cSJens Axboe unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0; 616f9ead18cSJens Axboe bool fixed = !!accept->file_slot; 617f9ead18cSJens Axboe struct file *file; 618f9ead18cSJens Axboe int ret, fd; 619f9ead18cSJens Axboe 620f9ead18cSJens Axboe retry: 621f9ead18cSJens Axboe if (!fixed) { 622f9ead18cSJens Axboe fd = __get_unused_fd_flags(accept->flags, accept->nofile); 623f9ead18cSJens Axboe if (unlikely(fd < 0)) 624f9ead18cSJens Axboe return fd; 625f9ead18cSJens Axboe } 626f9ead18cSJens Axboe file = do_accept(req->file, file_flags, accept->addr, accept->addr_len, 627f9ead18cSJens Axboe accept->flags); 628f9ead18cSJens Axboe if (IS_ERR(file)) { 629f9ead18cSJens Axboe if (!fixed) 630f9ead18cSJens Axboe put_unused_fd(fd); 631f9ead18cSJens Axboe ret = PTR_ERR(file); 632f9ead18cSJens Axboe if (ret == -EAGAIN && force_nonblock) { 633f9ead18cSJens Axboe /* 634f9ead18cSJens Axboe * if it's multishot and polled, we don't need to 635f9ead18cSJens Axboe * return EAGAIN to arm the poll infra since it 636f9ead18cSJens Axboe * has already been done 637f9ead18cSJens Axboe */ 638f9ead18cSJens Axboe if ((req->flags & IO_APOLL_MULTI_POLLED) == 639f9ead18cSJens Axboe IO_APOLL_MULTI_POLLED) 640f9ead18cSJens Axboe ret = IOU_ISSUE_SKIP_COMPLETE; 641f9ead18cSJens Axboe return ret; 642f9ead18cSJens Axboe } 643f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 644f9ead18cSJens Axboe ret = -EINTR; 645f9ead18cSJens Axboe req_set_fail(req); 646f9ead18cSJens Axboe } else if (!fixed) { 647f9ead18cSJens Axboe fd_install(fd, file); 648f9ead18cSJens Axboe ret = fd; 649f9ead18cSJens Axboe } else { 650f9ead18cSJens Axboe ret = io_fixed_fd_install(req, issue_flags, file, 651f9ead18cSJens Axboe accept->file_slot); 652f9ead18cSJens Axboe } 653f9ead18cSJens Axboe 654f9ead18cSJens Axboe if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { 655f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 656f9ead18cSJens Axboe return IOU_OK; 657f9ead18cSJens Axboe } 658f9ead18cSJens Axboe 659d245bca6SPavel Begunkov if (ret < 0) 660f9ead18cSJens Axboe return ret; 661d245bca6SPavel Begunkov if (io_post_aux_cqe(ctx, req->cqe.user_data, ret, IORING_CQE_F_MORE)) 662d245bca6SPavel Begunkov goto retry; 663d245bca6SPavel Begunkov return -ECANCELED; 664f9ead18cSJens Axboe } 665f9ead18cSJens Axboe 666f9ead18cSJens Axboe int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 667f9ead18cSJens Axboe { 668f9ead18cSJens Axboe struct io_socket *sock = io_kiocb_to_cmd(req); 669f9ead18cSJens Axboe 670f9ead18cSJens Axboe if (sqe->addr || sqe->rw_flags || sqe->buf_index) 671f9ead18cSJens Axboe return -EINVAL; 672f9ead18cSJens Axboe 673f9ead18cSJens Axboe sock->domain = READ_ONCE(sqe->fd); 674f9ead18cSJens Axboe sock->type = READ_ONCE(sqe->off); 675f9ead18cSJens Axboe sock->protocol = READ_ONCE(sqe->len); 676f9ead18cSJens Axboe sock->file_slot = READ_ONCE(sqe->file_index); 677f9ead18cSJens Axboe sock->nofile = rlimit(RLIMIT_NOFILE); 678f9ead18cSJens Axboe 679f9ead18cSJens Axboe sock->flags = sock->type & ~SOCK_TYPE_MASK; 680f9ead18cSJens Axboe if (sock->file_slot && (sock->flags & SOCK_CLOEXEC)) 681f9ead18cSJens Axboe return -EINVAL; 682f9ead18cSJens Axboe if (sock->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 683f9ead18cSJens Axboe return -EINVAL; 684f9ead18cSJens Axboe return 0; 685f9ead18cSJens Axboe } 686f9ead18cSJens Axboe 687f9ead18cSJens Axboe int io_socket(struct io_kiocb *req, unsigned int issue_flags) 688f9ead18cSJens Axboe { 689f9ead18cSJens Axboe struct io_socket *sock = io_kiocb_to_cmd(req); 690f9ead18cSJens Axboe bool fixed = !!sock->file_slot; 691f9ead18cSJens Axboe struct file *file; 692f9ead18cSJens Axboe int ret, fd; 693f9ead18cSJens Axboe 694f9ead18cSJens Axboe if (!fixed) { 695f9ead18cSJens Axboe fd = __get_unused_fd_flags(sock->flags, sock->nofile); 696f9ead18cSJens Axboe if (unlikely(fd < 0)) 697f9ead18cSJens Axboe return fd; 698f9ead18cSJens Axboe } 699f9ead18cSJens Axboe file = __sys_socket_file(sock->domain, sock->type, sock->protocol); 700f9ead18cSJens Axboe if (IS_ERR(file)) { 701f9ead18cSJens Axboe if (!fixed) 702f9ead18cSJens Axboe put_unused_fd(fd); 703f9ead18cSJens Axboe ret = PTR_ERR(file); 704f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 705f9ead18cSJens Axboe return -EAGAIN; 706f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 707f9ead18cSJens Axboe ret = -EINTR; 708f9ead18cSJens Axboe req_set_fail(req); 709f9ead18cSJens Axboe } else if (!fixed) { 710f9ead18cSJens Axboe fd_install(fd, file); 711f9ead18cSJens Axboe ret = fd; 712f9ead18cSJens Axboe } else { 713f9ead18cSJens Axboe ret = io_fixed_fd_install(req, issue_flags, file, 714f9ead18cSJens Axboe sock->file_slot); 715f9ead18cSJens Axboe } 716f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 717f9ead18cSJens Axboe return IOU_OK; 718f9ead18cSJens Axboe } 719f9ead18cSJens Axboe 720f9ead18cSJens Axboe int io_connect_prep_async(struct io_kiocb *req) 721f9ead18cSJens Axboe { 722f9ead18cSJens Axboe struct io_async_connect *io = req->async_data; 723f9ead18cSJens Axboe struct io_connect *conn = io_kiocb_to_cmd(req); 724f9ead18cSJens Axboe 725f9ead18cSJens Axboe return move_addr_to_kernel(conn->addr, conn->addr_len, &io->address); 726f9ead18cSJens Axboe } 727f9ead18cSJens Axboe 728f9ead18cSJens Axboe int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 729f9ead18cSJens Axboe { 730f9ead18cSJens Axboe struct io_connect *conn = io_kiocb_to_cmd(req); 731f9ead18cSJens Axboe 732f9ead18cSJens Axboe if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in) 733f9ead18cSJens Axboe return -EINVAL; 734f9ead18cSJens Axboe 735f9ead18cSJens Axboe conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr)); 736f9ead18cSJens Axboe conn->addr_len = READ_ONCE(sqe->addr2); 737f9ead18cSJens Axboe return 0; 738f9ead18cSJens Axboe } 739f9ead18cSJens Axboe 740f9ead18cSJens Axboe int io_connect(struct io_kiocb *req, unsigned int issue_flags) 741f9ead18cSJens Axboe { 742f9ead18cSJens Axboe struct io_connect *connect = io_kiocb_to_cmd(req); 743f9ead18cSJens Axboe struct io_async_connect __io, *io; 744f9ead18cSJens Axboe unsigned file_flags; 745f9ead18cSJens Axboe int ret; 746f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 747f9ead18cSJens Axboe 748f9ead18cSJens Axboe if (req_has_async_data(req)) { 749f9ead18cSJens Axboe io = req->async_data; 750f9ead18cSJens Axboe } else { 751f9ead18cSJens Axboe ret = move_addr_to_kernel(connect->addr, 752f9ead18cSJens Axboe connect->addr_len, 753f9ead18cSJens Axboe &__io.address); 754f9ead18cSJens Axboe if (ret) 755f9ead18cSJens Axboe goto out; 756f9ead18cSJens Axboe io = &__io; 757f9ead18cSJens Axboe } 758f9ead18cSJens Axboe 759f9ead18cSJens Axboe file_flags = force_nonblock ? O_NONBLOCK : 0; 760f9ead18cSJens Axboe 761f9ead18cSJens Axboe ret = __sys_connect_file(req->file, &io->address, 762f9ead18cSJens Axboe connect->addr_len, file_flags); 763f9ead18cSJens Axboe if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) { 764f9ead18cSJens Axboe if (req_has_async_data(req)) 765f9ead18cSJens Axboe return -EAGAIN; 766f9ead18cSJens Axboe if (io_alloc_async_data(req)) { 767f9ead18cSJens Axboe ret = -ENOMEM; 768f9ead18cSJens Axboe goto out; 769f9ead18cSJens Axboe } 770f9ead18cSJens Axboe memcpy(req->async_data, &__io, sizeof(__io)); 771f9ead18cSJens Axboe return -EAGAIN; 772f9ead18cSJens Axboe } 773f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 774f9ead18cSJens Axboe ret = -EINTR; 775f9ead18cSJens Axboe out: 776f9ead18cSJens Axboe if (ret < 0) 777f9ead18cSJens Axboe req_set_fail(req); 778f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 779f9ead18cSJens Axboe return IOU_OK; 780f9ead18cSJens Axboe } 781f9ead18cSJens Axboe #endif 782