]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/poll: fix POLLERR handling
authorPavel Begunkov <asml.silence@gmail.com>
Wed, 16 Jul 2025 16:20:17 +0000 (17:20 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 16 Jul 2025 16:28:28 +0000 (10:28 -0600)
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>
io_uring/net.c
io_uring/poll.c

index 43a43522f406b19a28582a2ac01e4d5d195c9c10..bec8c6ed0a93f9dadbd11dbcb93eca463242d4c9 100644 (file)
@@ -1738,9 +1738,11 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
        int ret;
        bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
 
-       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;
@@ -1765,8 +1767,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;
index 0526062e2f8137a78a4fd8de55cf765b2ddbd03f..20e9b46a4adfd5d9259e825249a4101cc04213f5 100644 (file)
@@ -273,8 +273,6 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw)
                                return IOU_POLL_REISSUE;
                        }
                }
-               if (unlikely(req->cqe.res & EPOLLERR))
-                       req_set_fail(req);
                if (req->apoll_events & EPOLLONESHOT)
                        return IOU_POLL_DONE;