Commit 17f2fe35 authored by Jens Axboe's avatar Jens Axboe
Browse files

io_uring: add support for IORING_OP_ACCEPT



This allows an application to call accept4() in an async fashion. Like
other opcodes, we first try a non-blocking accept, then punt to async
context if we have to.

Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent de2ea4b6
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -1686,6 +1686,40 @@ static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
#endif
}

static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe,
		     struct io_kiocb **nxt, bool force_nonblock)
{
#if defined(CONFIG_NET)
	struct sockaddr __user *addr;
	int __user *addr_len;
	unsigned file_flags;
	int flags, ret;

	if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
		return -EINVAL;
	if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index)
		return -EINVAL;

	addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
	addr_len = (int __user *) (unsigned long) READ_ONCE(sqe->addr2);
	flags = READ_ONCE(sqe->accept_flags);
	file_flags = force_nonblock ? O_NONBLOCK : 0;

	ret = __sys_accept4_file(req->file, file_flags, addr, addr_len, flags);
	if (ret == -EAGAIN && force_nonblock) {
		req->work.flags |= IO_WQ_WORK_NEEDS_FILES;
		return -EAGAIN;
	}
	if (ret < 0 && (req->flags & REQ_F_LINK))
		req->flags |= REQ_F_FAIL_LINK;
	io_cqring_add_event(req->ctx, sqe->user_data, ret);
	io_put_req(req, nxt);
	return 0;
#else
	return -EOPNOTSUPP;
#endif
}

static void io_poll_remove_one(struct io_kiocb *req)
{
	struct io_poll_iocb *poll = &req->poll;
@@ -2173,6 +2207,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
	case IORING_OP_TIMEOUT_REMOVE:
		ret = io_timeout_remove(req, s->sqe);
		break;
	case IORING_OP_ACCEPT:
		ret = io_accept(req, s->sqe, nxt, force_nonblock);
		break;
	default:
		ret = -EINVAL;
		break;
+6 −1
Original line number Diff line number Diff line
@@ -19,7 +19,10 @@ struct io_uring_sqe {
	__u8	flags;		/* IOSQE_ flags */
	__u16	ioprio;		/* ioprio for the request */
	__s32	fd;		/* file descriptor to do IO on */
	union {
		__u64	off;	/* offset into file */
		__u64	addr2;
	};
	__u64	addr;		/* pointer to buffer or iovecs */
	__u32	len;		/* buffer size or number of iovecs */
	union {
@@ -29,6 +32,7 @@ struct io_uring_sqe {
		__u32		sync_range_flags;
		__u32		msg_flags;
		__u32		timeout_flags;
		__u32		accept_flags;
	};
	__u64	user_data;	/* data to be passed back at completion time */
	union {
@@ -65,6 +69,7 @@ struct io_uring_sqe {
#define IORING_OP_RECVMSG	10
#define IORING_OP_TIMEOUT	11
#define IORING_OP_TIMEOUT_REMOVE	12
#define IORING_OP_ACCEPT	13

/*
 * sqe->fsync_flags