Commit 7dcc758c authored by Jens Axboe's avatar Jens Axboe
Browse files

io_uring/net: add IORING_ACCEPT_DONTWAIT flag



This allows the caller to perform a non-blocking attempt, similarly to
how recvmsg has MSG_DONTWAIT. If set, and we get -EAGAIN on a connection
attempt, propagate the result to userspace rather than arm poll and
wait for a retry.

Suggested-by: default avatarNorman Maurer <norman_maurer@apple.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 340f634a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -379,6 +379,7 @@ enum io_uring_op {
 * accept flags stored in sqe->ioprio
 */
#define IORING_ACCEPT_MULTISHOT	(1U << 0)
#define IORING_ACCEPT_DONTWAIT	(1U << 1)

/*
 * IORING_OP_MSG_RING command types, stored in sqe->addr
+9 −6
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ struct io_accept {
	struct sockaddr __user		*addr;
	int __user			*addr_len;
	int				flags;
	int				iou_flags;
	u32				file_slot;
	unsigned long			nofile;
};
@@ -1489,7 +1490,6 @@ void io_sendrecv_fail(struct io_kiocb *req)
int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
	struct io_accept *accept = io_kiocb_to_cmd(req, struct io_accept);
	unsigned flags;

	if (sqe->len || sqe->buf_index)
		return -EINVAL;
@@ -1498,15 +1498,15 @@ int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
	accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2));
	accept->flags = READ_ONCE(sqe->accept_flags);
	accept->nofile = rlimit(RLIMIT_NOFILE);
	flags = READ_ONCE(sqe->ioprio);
	if (flags & ~IORING_ACCEPT_MULTISHOT)
	accept->iou_flags = READ_ONCE(sqe->ioprio);
	if (accept->iou_flags & ~(IORING_ACCEPT_MULTISHOT | IORING_ACCEPT_DONTWAIT))
		return -EINVAL;

	accept->file_slot = READ_ONCE(sqe->file_index);
	if (accept->file_slot) {
		if (accept->flags & SOCK_CLOEXEC)
			return -EINVAL;
		if (flags & IORING_ACCEPT_MULTISHOT &&
		if (accept->iou_flags & IORING_ACCEPT_MULTISHOT &&
		    accept->file_slot != IORING_FILE_INDEX_ALLOC)
			return -EINVAL;
	}
@@ -1514,8 +1514,10 @@ int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
		return -EINVAL;
	if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK))
		accept->flags = (accept->flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
	if (flags & IORING_ACCEPT_MULTISHOT)
	if (accept->iou_flags & IORING_ACCEPT_MULTISHOT)
		req->flags |= REQ_F_APOLL_MULTISHOT;
	if (accept->iou_flags & IORING_ACCEPT_DONTWAIT)
		req->flags |= REQ_F_NOWAIT;
	return 0;
}

@@ -1540,7 +1542,8 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
		if (!fixed)
			put_unused_fd(fd);
		ret = PTR_ERR(file);
		if (ret == -EAGAIN && force_nonblock) {
		if (ret == -EAGAIN && force_nonblock &&
		    !(accept->iou_flags & IORING_ACCEPT_DONTWAIT)) {
			/*
			 * if it's multishot and polled, we don't need to
			 * return EAGAIN to arm the poll infra since it