io_uring: split out filesystem related operations
authorJens Axboe <axboe@kernel.dk>
Wed, 25 May 2022 03:13:00 +0000 (21:13 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 25 Jul 2022 00:39:11 +0000 (18:39 -0600)
This splits out renameat, unlinkat, mkdirat, symlinkat, and linkat.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/Makefile
io_uring/fs.c [new file with mode: 0644]
io_uring/fs.h [new file with mode: 0644]
io_uring/io_uring.c

index 32c02a3..50e68c9 100644 (file)
@@ -2,5 +2,5 @@
 #
 # Makefile for io_uring
 
-obj-$(CONFIG_IO_URING)         += io_uring.o xattr.o nop.o
+obj-$(CONFIG_IO_URING)         += io_uring.o xattr.o nop.o fs.o
 obj-$(CONFIG_IO_WQ)            += io-wq.o
diff --git a/io_uring/fs.c b/io_uring/fs.c
new file mode 100644 (file)
index 0000000..aac1bc5
--- /dev/null
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include <linux/io_uring.h>
+
+#include <uapi/linux/io_uring.h>
+
+#include "../fs/internal.h"
+
+#include "io_uring_types.h"
+#include "io_uring.h"
+#include "fs.h"
+
+struct io_rename {
+       struct file                     *file;
+       int                             old_dfd;
+       int                             new_dfd;
+       struct filename                 *oldpath;
+       struct filename                 *newpath;
+       int                             flags;
+};
+
+struct io_unlink {
+       struct file                     *file;
+       int                             dfd;
+       int                             flags;
+       struct filename                 *filename;
+};
+
+struct io_mkdir {
+       struct file                     *file;
+       int                             dfd;
+       umode_t                         mode;
+       struct filename                 *filename;
+};
+
+struct io_link {
+       struct file                     *file;
+       int                             old_dfd;
+       int                             new_dfd;
+       struct filename                 *oldpath;
+       struct filename                 *newpath;
+       int                             flags;
+};
+
+int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+       struct io_rename *ren = io_kiocb_to_cmd(req);
+       const char __user *oldf, *newf;
+
+       if (sqe->buf_index || sqe->splice_fd_in)
+               return -EINVAL;
+       if (unlikely(req->flags & REQ_F_FIXED_FILE))
+               return -EBADF;
+
+       ren->old_dfd = READ_ONCE(sqe->fd);
+       oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+       ren->new_dfd = READ_ONCE(sqe->len);
+       ren->flags = READ_ONCE(sqe->rename_flags);
+
+       ren->oldpath = getname(oldf);
+       if (IS_ERR(ren->oldpath))
+               return PTR_ERR(ren->oldpath);
+
+       ren->newpath = getname(newf);
+       if (IS_ERR(ren->newpath)) {
+               putname(ren->oldpath);
+               return PTR_ERR(ren->newpath);
+       }
+
+       req->flags |= REQ_F_NEED_CLEANUP;
+       return 0;
+}
+
+int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_rename *ren = io_kiocb_to_cmd(req);
+       int ret;
+
+       if (issue_flags & IO_URING_F_NONBLOCK)
+               return -EAGAIN;
+
+       ret = do_renameat2(ren->old_dfd, ren->oldpath, ren->new_dfd,
+                               ren->newpath, ren->flags);
+
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
+void io_renameat_cleanup(struct io_kiocb *req)
+{
+       struct io_rename *ren = io_kiocb_to_cmd(req);
+
+       putname(ren->oldpath);
+       putname(ren->newpath);
+}
+
+int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+       struct io_unlink *un = io_kiocb_to_cmd(req);
+       const char __user *fname;
+
+       if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in)
+               return -EINVAL;
+       if (unlikely(req->flags & REQ_F_FIXED_FILE))
+               return -EBADF;
+
+       un->dfd = READ_ONCE(sqe->fd);
+
+       un->flags = READ_ONCE(sqe->unlink_flags);
+       if (un->flags & ~AT_REMOVEDIR)
+               return -EINVAL;
+
+       fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       un->filename = getname(fname);
+       if (IS_ERR(un->filename))
+               return PTR_ERR(un->filename);
+
+       req->flags |= REQ_F_NEED_CLEANUP;
+       return 0;
+}
+
+int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_unlink *un = io_kiocb_to_cmd(req);
+       int ret;
+
+       if (issue_flags & IO_URING_F_NONBLOCK)
+               return -EAGAIN;
+
+       if (un->flags & AT_REMOVEDIR)
+               ret = do_rmdir(un->dfd, un->filename);
+       else
+               ret = do_unlinkat(un->dfd, un->filename);
+
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
+void io_unlinkat_cleanup(struct io_kiocb *req)
+{
+       struct io_unlink *ul = io_kiocb_to_cmd(req);
+
+       putname(ul->filename);
+}
+
+int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+       struct io_mkdir *mkd = io_kiocb_to_cmd(req);
+       const char __user *fname;
+
+       if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
+               return -EINVAL;
+       if (unlikely(req->flags & REQ_F_FIXED_FILE))
+               return -EBADF;
+
+       mkd->dfd = READ_ONCE(sqe->fd);
+       mkd->mode = READ_ONCE(sqe->len);
+
+       fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       mkd->filename = getname(fname);
+       if (IS_ERR(mkd->filename))
+               return PTR_ERR(mkd->filename);
+
+       req->flags |= REQ_F_NEED_CLEANUP;
+       return 0;
+}
+
+int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_mkdir *mkd = io_kiocb_to_cmd(req);
+       int ret;
+
+       if (issue_flags & IO_URING_F_NONBLOCK)
+               return -EAGAIN;
+
+       ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode);
+
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
+void io_mkdirat_cleanup(struct io_kiocb *req)
+{
+       struct io_mkdir *md = io_kiocb_to_cmd(req);
+
+       putname(md->filename);
+}
+
+int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+       struct io_link *sl = io_kiocb_to_cmd(req);
+       const char __user *oldpath, *newpath;
+
+       if (sqe->len || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
+               return -EINVAL;
+       if (unlikely(req->flags & REQ_F_FIXED_FILE))
+               return -EBADF;
+
+       sl->new_dfd = READ_ONCE(sqe->fd);
+       oldpath = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       newpath = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+
+       sl->oldpath = getname(oldpath);
+       if (IS_ERR(sl->oldpath))
+               return PTR_ERR(sl->oldpath);
+
+       sl->newpath = getname(newpath);
+       if (IS_ERR(sl->newpath)) {
+               putname(sl->oldpath);
+               return PTR_ERR(sl->newpath);
+       }
+
+       req->flags |= REQ_F_NEED_CLEANUP;
+       return 0;
+}
+
+int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_link *sl = io_kiocb_to_cmd(req);
+       int ret;
+
+       if (issue_flags & IO_URING_F_NONBLOCK)
+               return -EAGAIN;
+
+       ret = do_symlinkat(sl->oldpath, sl->new_dfd, sl->newpath);
+
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
+int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+       struct io_link *lnk = io_kiocb_to_cmd(req);
+       const char __user *oldf, *newf;
+
+       if (sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
+               return -EINVAL;
+       if (unlikely(req->flags & REQ_F_FIXED_FILE))
+               return -EBADF;
+
+       lnk->old_dfd = READ_ONCE(sqe->fd);
+       lnk->new_dfd = READ_ONCE(sqe->len);
+       oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+       lnk->flags = READ_ONCE(sqe->hardlink_flags);
+
+       lnk->oldpath = getname(oldf);
+       if (IS_ERR(lnk->oldpath))
+               return PTR_ERR(lnk->oldpath);
+
+       lnk->newpath = getname(newf);
+       if (IS_ERR(lnk->newpath)) {
+               putname(lnk->oldpath);
+               return PTR_ERR(lnk->newpath);
+       }
+
+       req->flags |= REQ_F_NEED_CLEANUP;
+       return 0;
+}
+
+int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
+{
+       struct io_link *lnk = io_kiocb_to_cmd(req);
+       int ret;
+
+       if (issue_flags & IO_URING_F_NONBLOCK)
+               return -EAGAIN;
+
+       ret = do_linkat(lnk->old_dfd, lnk->oldpath, lnk->new_dfd,
+                               lnk->newpath, lnk->flags);
+
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       io_req_set_res(req, ret, 0);
+       return IOU_OK;
+}
+
+void io_link_cleanup(struct io_kiocb *req)
+{
+       struct io_link *sl = io_kiocb_to_cmd(req);
+
+       putname(sl->oldpath);
+       putname(sl->newpath);
+}
diff --git a/io_uring/fs.h b/io_uring/fs.h
new file mode 100644 (file)
index 0000000..0bb5efe
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+
+int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_renameat(struct io_kiocb *req, unsigned int issue_flags);
+void io_renameat_cleanup(struct io_kiocb *req);
+
+int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags);
+void io_unlinkat_cleanup(struct io_kiocb *req);
+
+int io_mkdirat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags);
+void io_mkdirat_cleanup(struct io_kiocb *req);
+
+int io_symlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags);
+
+int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_linkat(struct io_kiocb *req, unsigned int issue_flags);
+void io_link_cleanup(struct io_kiocb *req);
index 3e74925..5b1e67f 100644 (file)
@@ -94,6 +94,7 @@
 
 #include "xattr.h"
 #include "nop.h"
+#include "fs.h"
 
 #define IORING_MAX_ENTRIES     32768
 #define IORING_MAX_CQ_ENTRIES  (2 * IORING_MAX_ENTRIES)
@@ -467,38 +468,6 @@ struct io_shutdown {
        int                             how;
 };
 
-struct io_rename {
-       struct file                     *file;
-       int                             old_dfd;
-       int                             new_dfd;
-       struct filename                 *oldpath;
-       struct filename                 *newpath;
-       int                             flags;
-};
-
-struct io_unlink {
-       struct file                     *file;
-       int                             dfd;
-       int                             flags;
-       struct filename                 *filename;
-};
-
-struct io_mkdir {
-       struct file                     *file;
-       int                             dfd;
-       umode_t                         mode;
-       struct filename                 *filename;
-};
-
-struct io_link {
-       struct file                     *file;
-       int                             old_dfd;
-       int                             new_dfd;
-       struct filename                 *oldpath;
-       struct filename                 *newpath;
-       int                             flags;
-};
-
 struct io_msg {
        struct file                     *file;
        u64 user_data;
@@ -3845,256 +3814,6 @@ out_free:
        return ret;
 }
 
-static int io_renameat_prep(struct io_kiocb *req,
-                           const struct io_uring_sqe *sqe)
-{
-       struct io_rename *ren = io_kiocb_to_cmd(req);
-       const char __user *oldf, *newf;
-
-       if (sqe->buf_index || sqe->splice_fd_in)
-               return -EINVAL;
-       if (unlikely(req->flags & REQ_F_FIXED_FILE))
-               return -EBADF;
-
-       ren->old_dfd = READ_ONCE(sqe->fd);
-       oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
-       ren->new_dfd = READ_ONCE(sqe->len);
-       ren->flags = READ_ONCE(sqe->rename_flags);
-
-       ren->oldpath = getname(oldf);
-       if (IS_ERR(ren->oldpath))
-               return PTR_ERR(ren->oldpath);
-
-       ren->newpath = getname(newf);
-       if (IS_ERR(ren->newpath)) {
-               putname(ren->oldpath);
-               return PTR_ERR(ren->newpath);
-       }
-
-       req->flags |= REQ_F_NEED_CLEANUP;
-       return 0;
-}
-
-static int io_renameat(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_rename *ren = io_kiocb_to_cmd(req);
-       int ret;
-
-       if (issue_flags & IO_URING_F_NONBLOCK)
-               return -EAGAIN;
-
-       ret = do_renameat2(ren->old_dfd, ren->oldpath, ren->new_dfd,
-                               ren->newpath, ren->flags);
-
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-static void io_renameat_cleanup(struct io_kiocb *req)
-{
-       struct io_rename *ren = io_kiocb_to_cmd(req);
-
-       putname(ren->oldpath);
-       putname(ren->newpath);
-}
-
-static int io_unlinkat_prep(struct io_kiocb *req,
-                           const struct io_uring_sqe *sqe)
-{
-       struct io_unlink *un = io_kiocb_to_cmd(req);
-       const char __user *fname;
-
-       if (sqe->off || sqe->len || sqe->buf_index || sqe->splice_fd_in)
-               return -EINVAL;
-       if (unlikely(req->flags & REQ_F_FIXED_FILE))
-               return -EBADF;
-
-       un->dfd = READ_ONCE(sqe->fd);
-
-       un->flags = READ_ONCE(sqe->unlink_flags);
-       if (un->flags & ~AT_REMOVEDIR)
-               return -EINVAL;
-
-       fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       un->filename = getname(fname);
-       if (IS_ERR(un->filename))
-               return PTR_ERR(un->filename);
-
-       req->flags |= REQ_F_NEED_CLEANUP;
-       return 0;
-}
-
-static int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_unlink *un = io_kiocb_to_cmd(req);
-       int ret;
-
-       if (issue_flags & IO_URING_F_NONBLOCK)
-               return -EAGAIN;
-
-       if (un->flags & AT_REMOVEDIR)
-               ret = do_rmdir(un->dfd, un->filename);
-       else
-               ret = do_unlinkat(un->dfd, un->filename);
-
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-static void io_unlinkat_cleanup(struct io_kiocb *req)
-{
-       struct io_unlink *ul = io_kiocb_to_cmd(req);
-
-       putname(ul->filename);
-}
-
-static int io_mkdirat_prep(struct io_kiocb *req,
-                           const struct io_uring_sqe *sqe)
-{
-       struct io_mkdir *mkd = io_kiocb_to_cmd(req);
-       const char __user *fname;
-
-       if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
-               return -EINVAL;
-       if (unlikely(req->flags & REQ_F_FIXED_FILE))
-               return -EBADF;
-
-       mkd->dfd = READ_ONCE(sqe->fd);
-       mkd->mode = READ_ONCE(sqe->len);
-
-       fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       mkd->filename = getname(fname);
-       if (IS_ERR(mkd->filename))
-               return PTR_ERR(mkd->filename);
-
-       req->flags |= REQ_F_NEED_CLEANUP;
-       return 0;
-}
-
-static int io_mkdirat(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_mkdir *mkd = io_kiocb_to_cmd(req);
-       int ret;
-
-       if (issue_flags & IO_URING_F_NONBLOCK)
-               return -EAGAIN;
-
-       ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode);
-
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-static void io_mkdirat_cleanup(struct io_kiocb *req)
-{
-       struct io_mkdir *md = io_kiocb_to_cmd(req);
-
-       putname(md->filename);
-}
-
-static int io_symlinkat_prep(struct io_kiocb *req,
-                           const struct io_uring_sqe *sqe)
-{
-       struct io_link *sl = io_kiocb_to_cmd(req);
-       const char __user *oldpath, *newpath;
-
-       if (sqe->len || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
-               return -EINVAL;
-       if (unlikely(req->flags & REQ_F_FIXED_FILE))
-               return -EBADF;
-
-       sl->new_dfd = READ_ONCE(sqe->fd);
-       oldpath = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       newpath = u64_to_user_ptr(READ_ONCE(sqe->addr2));
-
-       sl->oldpath = getname(oldpath);
-       if (IS_ERR(sl->oldpath))
-               return PTR_ERR(sl->oldpath);
-
-       sl->newpath = getname(newpath);
-       if (IS_ERR(sl->newpath)) {
-               putname(sl->oldpath);
-               return PTR_ERR(sl->newpath);
-       }
-
-       req->flags |= REQ_F_NEED_CLEANUP;
-       return 0;
-}
-
-static int io_symlinkat(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_link *sl = io_kiocb_to_cmd(req);
-       int ret;
-
-       if (issue_flags & IO_URING_F_NONBLOCK)
-               return -EAGAIN;
-
-       ret = do_symlinkat(sl->oldpath, sl->new_dfd, sl->newpath);
-
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-static int io_linkat_prep(struct io_kiocb *req,
-                           const struct io_uring_sqe *sqe)
-{
-       struct io_link *lnk = io_kiocb_to_cmd(req);
-       const char __user *oldf, *newf;
-
-       if (sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
-               return -EINVAL;
-       if (unlikely(req->flags & REQ_F_FIXED_FILE))
-               return -EBADF;
-
-       lnk->old_dfd = READ_ONCE(sqe->fd);
-       lnk->new_dfd = READ_ONCE(sqe->len);
-       oldf = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
-       lnk->flags = READ_ONCE(sqe->hardlink_flags);
-
-       lnk->oldpath = getname(oldf);
-       if (IS_ERR(lnk->oldpath))
-               return PTR_ERR(lnk->oldpath);
-
-       lnk->newpath = getname(newf);
-       if (IS_ERR(lnk->newpath)) {
-               putname(lnk->oldpath);
-               return PTR_ERR(lnk->newpath);
-       }
-
-       req->flags |= REQ_F_NEED_CLEANUP;
-       return 0;
-}
-
-static int io_linkat(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_link *lnk = io_kiocb_to_cmd(req);
-       int ret;
-
-       if (issue_flags & IO_URING_F_NONBLOCK)
-               return -EAGAIN;
-
-       ret = do_linkat(lnk->old_dfd, lnk->oldpath, lnk->new_dfd,
-                               lnk->newpath, lnk->flags);
-
-       req->flags &= ~REQ_F_NEED_CLEANUP;
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-static void io_link_cleanup(struct io_kiocb *req)
-{
-       struct io_link *sl = io_kiocb_to_cmd(req);
-
-       putname(sl->oldpath);
-       putname(sl->newpath);
-}
-
 static void io_uring_cmd_work(struct io_kiocb *req, bool *locked)
 {
        struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req);