Adds support for doing chmod through io_uring. IORING_OP_FCHMOD behaves like fchmod(2) and takes the same arguments. Signed-off-by: Li Zetao <lizetao1@xxxxxxxxxx> --- include/uapi/linux/io_uring.h | 1 + io_uring/fs.c | 32 ++++++++++++++++++++++++++++++++ io_uring/fs.h | 3 +++ io_uring/opdef.c | 8 ++++++++ 4 files changed, 44 insertions(+) diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 5d08435b95a8..de5cce11f937 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -262,6 +262,7 @@ enum io_uring_op { IORING_OP_FTRUNCATE, IORING_OP_BIND, IORING_OP_LISTEN, + IORING_OP_FCHMOD, /* this goes last, obviously */ IORING_OP_LAST, diff --git a/io_uring/fs.c b/io_uring/fs.c index eccea851dd5a..835f66fb75ff 100644 --- a/io_uring/fs.c +++ b/io_uring/fs.c @@ -47,6 +47,11 @@ struct io_link { int flags; }; +struct io_fchmod { + struct file *file; + umode_t mode; +}; + int io_renameat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_rename *ren = io_kiocb_to_cmd(req, struct io_rename); @@ -291,3 +296,30 @@ void io_link_cleanup(struct io_kiocb *req) putname(sl->oldpath); putname(sl->newpath); } + +int io_fchmod_prep(struct io_kiocb *req, const struct io_uring_sqe +*sqe) { + struct io_fchmod *fc = io_kiocb_to_cmd(req, struct io_fchmod); + + if (unlikely(sqe->off || sqe->addr || sqe->rw_flags || + sqe->buf_index || sqe->splice_fd_in)) + return -EINVAL; + if (unlikely(req->flags & REQ_F_FIXED_FILE)) + return -EBADF; + + fc->mode = READ_ONCE(sqe->len); + req->flags |= REQ_F_FORCE_ASYNC; + return 0; +} + +int io_fchmod(struct io_kiocb *req, unsigned int issue_flags) { + struct io_fchmod *fc = io_kiocb_to_cmd(req, struct io_fchmod); + int ret; + + WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); + + ret = vfs_fchmod(req->file, fc->mode); + io_req_set_res(req, ret, 0); + return IOU_OK; +} diff --git a/io_uring/fs.h b/io_uring/fs.h index 0bb5efe3d6bb..bc7d95e77b2f 100644 --- a/io_uring/fs.h +++ b/io_uring/fs.h @@ -18,3 +18,6 @@ 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); + +int io_fchmod_prep(struct io_kiocb *req, const struct io_uring_sqe +*sqe); int io_fchmod(struct io_kiocb *req, unsigned int issue_flags); diff --git a/io_uring/opdef.c b/io_uring/opdef.c index 3de75eca1c92..eb5bf831513c 100644 --- a/io_uring/opdef.c +++ b/io_uring/opdef.c @@ -515,6 +515,11 @@ const struct io_issue_def io_issue_defs[] = { .prep = io_eopnotsupp_prep, #endif }, + [IORING_OP_FCHMOD] = { + .needs_file = 1, + .prep = io_fchmod_prep, + .issue = io_fchmod, + }, }; const struct io_cold_def io_cold_defs[] = { @@ -744,6 +749,9 @@ const struct io_cold_def io_cold_defs[] = { [IORING_OP_LISTEN] = { .name = "LISTEN", }, + [IORING_OP_FCHMOD] = { + .name = "FCHMOD", + }, }; const char *io_uring_get_opcode(u8 opcode) -- 2.34.1