Loading fs/io_uring.c +64 −0 Original line number Diff line number Diff line Loading @@ -555,6 +555,13 @@ struct io_rename { int flags; }; struct io_unlink { struct file *file; int dfd; int flags; struct filename *filename; }; struct io_completion { struct file *file; struct list_head list; Loading Loading @@ -683,6 +690,7 @@ struct io_kiocb { struct io_statx statx; struct io_shutdown shutdown; struct io_rename rename; struct io_unlink unlink; /* use only after cleaning per-op data, see io_clean_op() */ struct io_completion compl; }; Loading Loading @@ -957,6 +965,10 @@ static const struct io_op_def io_op_defs[] = { .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, }, [IORING_OP_UNLINKAT] = { .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, }, }; enum io_mem_account { Loading Loading @@ -3706,6 +3718,50 @@ static int io_renameat(struct io_kiocb *req, bool force_nonblock) return 0; } static int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_unlink *un = &req->unlink; const char __user *fname; 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, bool force_nonblock) { struct io_unlink *un = &req->unlink; int ret; if (force_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; if (ret < 0) req_set_fail_links(req); io_req_complete(req, ret); return 0; } static int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { Loading Loading @@ -5932,6 +5988,8 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return io_shutdown_prep(req, sqe); case IORING_OP_RENAMEAT: return io_renameat_prep(req, sqe); case IORING_OP_UNLINKAT: return io_unlinkat_prep(req, sqe); } printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", Loading Loading @@ -6073,6 +6131,9 @@ static void __io_clean_op(struct io_kiocb *req) putname(req->rename.oldpath); putname(req->rename.newpath); break; case IORING_OP_UNLINKAT: putname(req->unlink.filename); break; } req->flags &= ~REQ_F_NEED_CLEANUP; } Loading Loading @@ -6185,6 +6246,9 @@ static int io_issue_sqe(struct io_kiocb *req, bool force_nonblock, case IORING_OP_RENAMEAT: ret = io_renameat(req, force_nonblock); break; case IORING_OP_UNLINKAT: ret = io_unlinkat(req, force_nonblock); break; default: ret = -EINVAL; break; Loading include/uapi/linux/io_uring.h +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ struct io_uring_sqe { __u32 fadvise_advice; __u32 splice_flags; __u32 rename_flags; __u32 unlink_flags; }; __u64 user_data; /* data to be passed back at completion time */ union { Loading Loading @@ -135,6 +136,7 @@ enum { IORING_OP_TEE, IORING_OP_SHUTDOWN, IORING_OP_RENAMEAT, IORING_OP_UNLINKAT, /* this goes last, obviously */ IORING_OP_LAST, Loading Loading
fs/io_uring.c +64 −0 Original line number Diff line number Diff line Loading @@ -555,6 +555,13 @@ struct io_rename { int flags; }; struct io_unlink { struct file *file; int dfd; int flags; struct filename *filename; }; struct io_completion { struct file *file; struct list_head list; Loading Loading @@ -683,6 +690,7 @@ struct io_kiocb { struct io_statx statx; struct io_shutdown shutdown; struct io_rename rename; struct io_unlink unlink; /* use only after cleaning per-op data, see io_clean_op() */ struct io_completion compl; }; Loading Loading @@ -957,6 +965,10 @@ static const struct io_op_def io_op_defs[] = { .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, }, [IORING_OP_UNLINKAT] = { .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, }, }; enum io_mem_account { Loading Loading @@ -3706,6 +3718,50 @@ static int io_renameat(struct io_kiocb *req, bool force_nonblock) return 0; } static int io_unlinkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_unlink *un = &req->unlink; const char __user *fname; 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, bool force_nonblock) { struct io_unlink *un = &req->unlink; int ret; if (force_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; if (ret < 0) req_set_fail_links(req); io_req_complete(req, ret); return 0; } static int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { Loading Loading @@ -5932,6 +5988,8 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return io_shutdown_prep(req, sqe); case IORING_OP_RENAMEAT: return io_renameat_prep(req, sqe); case IORING_OP_UNLINKAT: return io_unlinkat_prep(req, sqe); } printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", Loading Loading @@ -6073,6 +6131,9 @@ static void __io_clean_op(struct io_kiocb *req) putname(req->rename.oldpath); putname(req->rename.newpath); break; case IORING_OP_UNLINKAT: putname(req->unlink.filename); break; } req->flags &= ~REQ_F_NEED_CLEANUP; } Loading Loading @@ -6185,6 +6246,9 @@ static int io_issue_sqe(struct io_kiocb *req, bool force_nonblock, case IORING_OP_RENAMEAT: ret = io_renameat(req, force_nonblock); break; case IORING_OP_UNLINKAT: ret = io_unlinkat(req, force_nonblock); break; default: ret = -EINVAL; break; Loading
include/uapi/linux/io_uring.h +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ struct io_uring_sqe { __u32 fadvise_advice; __u32 splice_flags; __u32 rename_flags; __u32 unlink_flags; }; __u64 user_data; /* data to be passed back at completion time */ union { Loading Loading @@ -135,6 +136,7 @@ enum { IORING_OP_TEE, IORING_OP_SHUTDOWN, IORING_OP_RENAMEAT, IORING_OP_UNLINKAT, /* this goes last, obviously */ IORING_OP_LAST, Loading