Commit c7cafd5b authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe
Browse files

io_uring/poll: fix POLLERR handling



8c8492ca ("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: 8c8492ca ("io_uring/net: don't retry connect operation on EPOLLERR")
Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/3dc89036388d602ebd84c28e5042e457bdfc952b.1752682444.git.asml.silence@gmail.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 08ca1409
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -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,9 +1767,11 @@ 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;
out:
+0 −2
Original line number Diff line number Diff line
@@ -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;