summaryrefslogtreecommitdiff
path: root/io_uring
diff options
context:
space:
mode:
authorPavel Begunkov <asml.silence@gmail.com>2025-07-16 17:20:17 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-07-24 08:51:48 +0200
commit283bace0409504e3f60df72eeaef53d014f573ee (patch)
treef5d687db18f5e3c338da68cdb6e14a0ce3bf911c /io_uring
parent7803b28c9aa8d8bd4e19ebcf5f0db9612b0f333b (diff)
io_uring/poll: fix POLLERR handling
commit c7cafd5b81cc07fb402e3068d134c21e60ea688c upstream. 8c8492ca64e7 ("io_uring/net: don't retry connect operation on EPOLLERR") is a little dirty hack that 1) wrongfully assumes that POLLERR equals to a failed request, which breaks all POLLERR users, e.g. all error queue recv interfaces. 2) deviates the connection request behaviour from connect(2), and 3) racy and solved at a wrong level. Nothing can be done with 2) now, and 3) is beyond the scope of the patch. At least solve 1) by moving the hack out of generic poll handling into io_connect(). Cc: stable@vger.kernel.org Fixes: 8c8492ca64e79 ("io_uring/net: don't retry connect operation on EPOLLERR") Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/3dc89036388d602ebd84c28e5042e457bdfc952b.1752682444.git.asml.silence@gmail.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.c12
-rw-r--r--io_uring/poll.c2
2 files changed, 8 insertions, 6 deletions
diff --git a/io_uring/net.c b/io_uring/net.c
index 898990e71367..cc25cbb27e5d 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -1490,9 +1490,11 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
io = &__io;
}
- if (unlikely(req->flags & REQ_F_FAIL)) {
- ret = -ECONNRESET;
- goto out;
+ if (connect->in_progress) {
+ struct poll_table_struct pt = { ._key = EPOLLERR };
+
+ if (vfs_poll(req->file, &pt) & EPOLLERR)
+ goto get_sock_err;
}
file_flags = force_nonblock ? O_NONBLOCK : 0;
@@ -1524,8 +1526,10 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
* which means the previous result is good. For both of these,
* grab the sock_error() and use that for the completion.
*/
- if (ret == -EBADFD || ret == -EISCONN)
+ if (ret == -EBADFD || ret == -EISCONN) {
+get_sock_err:
ret = sock_error(sock_from_file(req->file)->sk);
+ }
}
if (ret == -ERESTARTSYS)
ret = -EINTR;
diff --git a/io_uring/poll.c b/io_uring/poll.c
index bbdc9a7624a1..ab27a627fd4c 100644
--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -288,8 +288,6 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
return IOU_POLL_REISSUE;
}
}
- if (unlikely(req->cqe.res & EPOLLERR))
- req_set_fail(req);
if (req->apoll_events & EPOLLONESHOT)
return IOU_POLL_DONE;
if (io_is_uring_fops(req->file))