public inbox for [email protected]
 help / color / mirror / Atom feed
* [PATCH v2] io_uring/net: handle -EINPROGRESS correct for IORING_OP_CONNECT
@ 2022-10-05  2:43 Jens Axboe
  0 siblings, 0 replies; only message in thread
From: Jens Axboe @ 2022-10-05  2:43 UTC (permalink / raw)
  To: io-uring

We treat EINPROGRESS like EAGAIN, but if we're retrying post getting
EINPROGRESS, then we just need to check the socket for errors and
terminate the request.

This was exposed on a bluetooth connection request which ends up
taking a while and hitting EINPROGRESS, and yields a CQE result of
-EBADFD because we're retrying a connect on a socket that is now
connected.

Cc: [email protected]
Fixes: 87f80d623c6c ("io_uring: handle connect -EINPROGRESS like -EAGAIN")
Link: https://github.com/axboe/liburing/issues/671
Signed-off-by: Jens Axboe <[email protected]>

---

Since v1:

- Send out the right version of the patch, there's no need to
  setup async data for the EINPROGRESS retry.

diff --git a/io_uring/net.c b/io_uring/net.c
index 6b69eff6887e..c2fbe8f083fb 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -46,6 +46,7 @@ struct io_connect {
 	struct file			*file;
 	struct sockaddr __user		*addr;
 	int				addr_len;
+	bool				in_progress;
 };
 
 struct io_sr_msg {
@@ -1382,6 +1383,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;
 	return 0;
 }
 
@@ -1393,6 +1395,18 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 	int ret;
 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
 
+	if (connect->in_progress) {
+		struct socket *socket;
+
+		socket = sock_from_file(req->file);
+		if (unlikely(!socket)) {
+			ret = -EBADF;
+			goto out;
+		}
+		ret = sock_error(socket->sk);
+		goto out;
+	}
+
 	if (req_has_async_data(req)) {
 		io = req->async_data;
 	} else {
@@ -1409,13 +1423,17 @@ 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 (req_has_async_data(req))
-			return -EAGAIN;
-		if (io_alloc_async_data(req)) {
-			ret = -ENOMEM;
-			goto out;
+		if (ret == -EINPROGRESS) {
+			connect->in_progress = true;
+		} else {
+			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));
 		}
-		memcpy(req->async_data, &__io, sizeof(__io));
 		return -EAGAIN;
 	}
 	if (ret == -ERESTARTSYS)

-- 
Jens Axboe

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-05  2:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-05  2:43 [PATCH v2] io_uring/net: handle -EINPROGRESS correct for IORING_OP_CONNECT Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox