]> www.infradead.org Git - users/hch/block.git/commitdiff
io_uring: hand code io_accept() fd installing
authorPavel Begunkov <asml.silence@gmail.com>
Sat, 21 Aug 2021 15:52:39 +0000 (16:52 +0100)
committerJens Axboe <axboe@kernel.dk>
Mon, 23 Aug 2021 19:41:56 +0000 (13:41 -0600)
Make io_accept() to handle file descriptor allocations and installation.
A preparation patch for bypassing file tables.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/8ac4c960937ee595545344c28b73c3ec9b1e8639.1629559905.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index d6375bf598236aabac8f3b6b4b3d976222b3b32a..d7e395729aa975f079e26607293b5fa12049d681 100644 (file)
@@ -4814,6 +4814,11 @@ static 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);
+
+       if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+               return -EINVAL;
+       if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK))
+               accept->flags = (accept->flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
        return 0;
 }
 
@@ -4822,20 +4827,28 @@ 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;
-       int ret;
+       struct file *file;
+       int ret, fd;
 
        if (req->file->f_flags & O_NONBLOCK)
                req->flags |= REQ_F_NOWAIT;
 
-       ret = __sys_accept4_file(req->file, file_flags, accept->addr,
-                                       accept->addr_len, accept->flags,
-                                       accept->nofile);
-       if (ret == -EAGAIN && force_nonblock)
-               return -EAGAIN;
-       if (ret < 0) {
+       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)) {
+               ret = PTR_ERR(file);
+               if (ret == -EAGAIN && force_nonblock)
+                       return -EAGAIN;
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
                req_set_fail(req);
+       } else {
+               fd_install(fd, file);
+               ret = fd;
        }
        __io_req_complete(req, issue_flags, ret, 0);
        return 0;