]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/net: Avoid msghdr on op_connect/op_bind async data
authorGabriel Krisman Bertazi <krisman@suse.de>
Tue, 2 Jun 2026 21:53:24 +0000 (17:53 -0400)
committerJens Axboe <axboe@kernel.dk>
Tue, 2 Jun 2026 23:43:06 +0000 (17:43 -0600)
Both IORING_OP_CONNECT and IORING_OP_BIND reuse the msghdr object just
to store the sockaddr. Beyond allocating a much larger object than
needed, msghdr can also wrap an iovec, which will be recycled
unnecessarily. This uses the sockaddr directly.

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Link: https://patch.msgid.link/20260602215327.1885109-2-krisman@suse.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/net.c
io_uring/opdef.c

index cceb5c1409ca8c25db66d785ee246be12083ff2b..7ff5975e118bb2ee4f507f5868f533bbf486efc9 100644 (file)
@@ -1677,8 +1677,7 @@ void io_socket_bpf_populate(struct io_uring_bpf_ctx *bctx, struct io_kiocb *req)
 void io_connect_bpf_populate(struct io_uring_bpf_ctx *bctx, struct io_kiocb *req)
 {
        struct io_connect *conn = io_kiocb_to_cmd(req, struct io_connect);
-       struct io_async_msghdr *iomsg = req->async_data;
-       struct sockaddr_storage *ss = &iomsg->addr;
+       struct sockaddr_storage *ss = req->async_data;
 
        /*
         * move_addr_to_kernel() skips the copy for addr_len == 0, so
@@ -1772,7 +1771,7 @@ int io_socket(struct io_kiocb *req, unsigned int issue_flags)
 int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_connect *conn = io_kiocb_to_cmd(req, struct io_connect);
-       struct io_async_msghdr *io;
+       struct sockaddr_storage *addr;
 
        if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
                return -EINVAL;
@@ -1781,17 +1780,17 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        conn->addr_len =  READ_ONCE(sqe->addr2);
        conn->in_progress = conn->seen_econnaborted = false;
 
-       io = io_msg_alloc_async(req);
-       if (unlikely(!io))
+       addr = io_uring_alloc_async_data(NULL, req);
+       if (unlikely(!addr))
                return -ENOMEM;
 
-       return move_addr_to_kernel(conn->addr, conn->addr_len, &io->addr);
+       return move_addr_to_kernel(conn->addr, conn->addr_len, addr);
 }
 
 int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_connect *connect = io_kiocb_to_cmd(req, struct io_connect);
-       struct io_async_msghdr *io = req->async_data;
+       struct sockaddr_storage *addr = req->async_data;
        unsigned file_flags;
        int ret;
        bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
@@ -1805,8 +1804,7 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 
        file_flags = force_nonblock ? O_NONBLOCK : 0;
 
-       ret = __sys_connect_file(req->file, &io->addr, connect->addr_len,
-                                file_flags);
+       ret = __sys_connect_file(req->file, addr, connect->addr_len, file_flags);
        if ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
            && force_nonblock) {
                if (ret == -EINPROGRESS) {
@@ -1835,7 +1833,6 @@ get_sock_err:
 out:
        if (ret < 0)
                req_set_fail(req);
-       io_req_msg_cleanup(req, issue_flags);
        io_req_set_res(req, ret, 0);
        return IOU_COMPLETE;
 }
@@ -1844,7 +1841,7 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
        struct sockaddr __user *uaddr;
-       struct io_async_msghdr *io;
+       struct sockaddr_storage *addr;
 
        if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
                return -EINVAL;
@@ -1852,16 +1849,17 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        uaddr = u64_to_user_ptr(READ_ONCE(sqe->addr));
        bind->addr_len =  READ_ONCE(sqe->addr2);
 
-       io = io_msg_alloc_async(req);
-       if (unlikely(!io))
+       addr = io_uring_alloc_async_data(NULL, req);
+       if (unlikely(!addr))
                return -ENOMEM;
-       return move_addr_to_kernel(uaddr, bind->addr_len, &io->addr);
+       return move_addr_to_kernel(uaddr, bind->addr_len, addr);
 }
 
+
 int io_bind(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
-       struct io_async_msghdr *io = req->async_data;
+       struct sockaddr_storage *addr = req->async_data;
        struct socket *sock;
        int ret;
 
@@ -1869,7 +1867,7 @@ int io_bind(struct io_kiocb *req, unsigned int issue_flags)
        if (unlikely(!sock))
                return -ENOTSOCK;
 
-       ret = __sys_bind_socket(sock, &io->addr, bind->addr_len);
+       ret = __sys_bind_socket(sock, addr, bind->addr_len);
        if (ret < 0)
                req_set_fail(req);
        io_req_set_res(req, ret, 0);
index 8ea6bd274607ae8b6a8e2abccf95f1767ca6b891..517bad015505de04b96c1c44c7c32364a974c4a2 100644 (file)
@@ -204,7 +204,7 @@ const struct io_issue_def io_issue_defs[] = {
                .pollout                = 1,
 #if defined(CONFIG_NET)
                .filter_pdu_size        = sizeof_field(struct io_uring_bpf_ctx, connect),
-               .async_size             = sizeof(struct io_async_msghdr),
+               .async_size             = sizeof(struct sockaddr_storage),
                .prep                   = io_connect_prep,
                .issue                  = io_connect,
                .filter_populate        = io_connect_bpf_populate,
@@ -505,7 +505,7 @@ const struct io_issue_def io_issue_defs[] = {
                .needs_file             = 1,
                .prep                   = io_bind_prep,
                .issue                  = io_bind,
-               .async_size             = sizeof(struct io_async_msghdr),
+               .async_size             = sizeof(struct sockaddr_storage),
 #else
                .prep                   = io_eopnotsupp_prep,
 #endif