diff options
author | Jens Axboe <axboe@kernel.dk> | 2023-03-20 11:13:49 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-03-30 12:49:25 +0200 |
commit | 87f2d329f4cb1a3b5025d49f98379a3ae89b9fd2 (patch) | |
tree | 93ffcf498923868487555d789f725b1c37c2e944 /io_uring | |
parent | 1c00030a59a9a829b1be04c83dbe66994c0e4826 (diff) | |
download | linux-stable-87f2d329f4cb1a3b5025d49f98379a3ae89b9fd2.tar.gz linux-stable-87f2d329f4cb1a3b5025d49f98379a3ae89b9fd2.tar.bz2 linux-stable-87f2d329f4cb1a3b5025d49f98379a3ae89b9fd2.zip |
io_uring/net: avoid sending -ECONNABORTED on repeated connection requests
commit 74e2e17ee1f8d8a0928b90434ad7e2df70f8483e upstream.
Since io_uring does nonblocking connect requests, if we do two repeated
ones without having a listener, the second will get -ECONNABORTED rather
than the expected -ECONNREFUSED. Treat -ECONNABORTED like a normal retry
condition if we're nonblocking, if we haven't already seen it.
Cc: stable@vger.kernel.org
Fixes: 3fb1bd688172 ("io_uring/net: handle -EINPROGRESS correct for IORING_OP_CONNECT")
Link: https://github.com/axboe/liburing/issues/828
Reported-by: Hui, Chunyang <sanqian.hcy@antgroup.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'io_uring')
-rw-r--r-- | io_uring/net.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/io_uring/net.c b/io_uring/net.c index 4fdc2770bbe4..f6d8b02387a9 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -47,6 +47,7 @@ struct io_connect { struct sockaddr __user *addr; int addr_len; bool in_progress; + bool seen_econnaborted; }; struct io_sr_msg { @@ -1404,7 +1405,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; } @@ -1441,18 +1442,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) |