Skip to content

Commit

Permalink
io_uring: accept directly into fixed file table
Browse files Browse the repository at this point in the history
As done with open opcodes, allow accept to skip installing fd into
processes' file tables and put it directly into io_uring's fixed file
table. Same restrictions and design as for open.

Suggested-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Link: https://lore.kernel.org/r/6d16163f376fac7ac26a656de6b42199143e9721.1629888991.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Pavel Begunkov authored and Jens Axboe committed Aug 25, 2021
1 parent a7083ad commit aaa4db1
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ struct io_accept {
struct sockaddr __user *addr;
int __user *addr_len;
int flags;
u32 file_slot;
unsigned long nofile;
};

Expand Down Expand Up @@ -4803,14 +4804,18 @@ static int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)

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

accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2));
accept->flags = READ_ONCE(sqe->accept_flags);
accept->nofile = rlimit(RLIMIT_NOFILE);

accept->file_slot = READ_ONCE(sqe->file_index);
if (accept->file_slot && ((req->open.how.flags & O_CLOEXEC) ||
(accept->flags & SOCK_CLOEXEC)))
return -EINVAL;
if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
return -EINVAL;
if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK))
Expand All @@ -4823,28 +4828,35 @@ static int io_accept(struct io_kiocb *req, unsigned int issue_flags)
struct io_accept *accept = &req->accept;
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0;
bool fixed = !!accept->file_slot;
struct file *file;
int ret, fd;

if (req->file->f_flags & O_NONBLOCK)
req->flags |= REQ_F_NOWAIT;

fd = __get_unused_fd_flags(accept->flags, accept->nofile);
if (unlikely(fd < 0))
return fd;

if (!fixed) {
fd = __get_unused_fd_flags(accept->flags, accept->nofile);
if (unlikely(fd < 0))
return fd;
}
file = do_accept(req->file, file_flags, accept->addr, accept->addr_len,
accept->flags);
if (IS_ERR(file)) {
if (!fixed)
put_unused_fd(fd);
ret = PTR_ERR(file);
if (ret == -EAGAIN && force_nonblock)
return -EAGAIN;
if (ret == -ERESTARTSYS)
ret = -EINTR;
req_set_fail(req);
} else {
} else if (!fixed) {
fd_install(fd, file);
ret = fd;
} else {
ret = io_install_fixed_file(req, file, issue_flags,
accept->file_slot - 1);
}
__io_req_complete(req, issue_flags, ret, 0);
return 0;
Expand Down

0 comments on commit aaa4db1

Please sign in to comment.