IORING_OP_MKDIRAT behaves like mkdirat(2) and takes the same flags and arguments.
Unified · Split
| @@ -662,6 +662,13 @@ struct io_unlink { · 661 unmodified lines | |||
| 662 | struct filename *filename; | 662 | struct filename *filename; |
| 663 | }; | 663 | }; |
| 664 | 664 | ||
| 665 | struct io_mkdir { | ||
| 666 | struct file *file; | ||
| 667 | int dfd; | ||
| 668 | umode_t mode; | ||
| 669 | struct filename *filename; | ||
| 670 | }; | ||
| 671 | |||
| 665 | struct io_completion { | 672 | struct io_completion { |
| 666 | struct file *file; | 673 | struct file *file; |
| 667 | u32 cflags; | 674 | u32 cflags; |
| @@ -821,6 +828,7 @@ struct io_kiocb { · 153 unmodified lines | |||
| 821 | struct io_shutdown shutdown; | 828 | struct io_shutdown shutdown; |
| 822 | struct io_rename rename; | 829 | struct io_rename rename; |
| 823 | struct io_unlink unlink; | 830 | struct io_unlink unlink; |
| 831 | struct io_mkdir mkdir; | ||
| 824 | /* use only after cleaning per-op data, see io_clean_op() */ | 832 | /* use only after cleaning per-op data, see io_clean_op() */ |
| 825 | struct io_completion compl; | 833 | struct io_completion compl; |
| 826 | }; | 834 | }; |
| @@ -1032,6 +1040,7 @@ static const struct io_op_def io_op_defs[] = { · 205 unmodified lines | |||
| 1032 | }, | 1040 | }, |
| 1033 | [IORING_OP_RENAMEAT] = {}, | 1041 | [IORING_OP_RENAMEAT] = {}, |
| 1034 | [IORING_OP_UNLINKAT] = {}, | 1042 | [IORING_OP_UNLINKAT] = {}, |
| 1043 | [IORING_OP_MKDIRAT] = {}, | ||
| 1035 | }; | 1044 | }; |
| 1036 | 1045 | ||
| 1037 | /* requests with any of those set should undergo io_disarm_next() */ | 1046 | /* requests with any of those set should undergo io_disarm_next() */ |
| @@ -3603,6 +3612,49 @@ static int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags) · 2565 unmodified lines | |||
| 3603 | return 0; | 3612 | return 0; |
| 3604 | } | 3613 | } |
| 3605 | 3614 | ||
| 3615 | static int io_mkdirat_prep(struct io_kiocb *req, | ||
| 3616 | const struct io_uring_sqe *sqe) | ||
| 3617 | { | ||
| 3618 | struct io_mkdir *mkd = &req->mkdir; | ||
| 3619 | const char __user *fname; | ||
| 3620 | |||
| 3621 | if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) | ||
| 3622 | return -EINVAL; | ||
| 3623 | if (sqe->ioprio || sqe->off || sqe->rw_flags || sqe->buf_index || | ||
| 3624 | sqe->splice_fd_in) | ||
| 3625 | return -EINVAL; | ||
| 3626 | if (unlikely(req->flags & REQ_F_FIXED_FILE)) | ||
| 3627 | return -EBADF; | ||
| 3628 | |||
| 3629 | mkd->dfd = READ_ONCE(sqe->fd); | ||
| 3630 | mkd->mode = READ_ONCE(sqe->len); | ||
| 3631 | |||
| 3632 | fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); | ||
| 3633 | mkd->filename = getname(fname); | ||
| 3634 | if (IS_ERR(mkd->filename)) | ||
| 3635 | return PTR_ERR(mkd->filename); | ||
| 3636 | |||
| 3637 | req->flags |= REQ_F_NEED_CLEANUP; | ||
| 3638 | return 0; | ||
| 3639 | } | ||
| 3640 | |||
| 3641 | static int io_mkdirat(struct io_kiocb *req, int issue_flags) | ||
| 3642 | { | ||
| 3643 | struct io_mkdir *mkd = &req->mkdir; | ||
| 3644 | int ret; | ||
| 3645 | |||
| 3646 | if (issue_flags & IO_URING_F_NONBLOCK) | ||
| 3647 | return -EAGAIN; | ||
| 3648 | |||
| 3649 | ret = do_mkdirat(mkd->dfd, mkd->filename, mkd->mode); | ||
| 3650 | |||
| 3651 | req->flags &= ~REQ_F_NEED_CLEANUP; | ||
| 3652 | if (ret < 0) | ||
| 3653 | req_set_fail(req); | ||
| 3654 | io_req_complete(req, ret); | ||
| 3655 | return 0; | ||
| 3656 | } | ||
| 3657 | |||
| 3606 | static int io_shutdown_prep(struct io_kiocb *req, | 3658 | static int io_shutdown_prep(struct io_kiocb *req, |
| 3607 | const struct io_uring_sqe *sqe) | 3659 | const struct io_uring_sqe *sqe) |
| 3608 | { | 3660 | { |
| @@ -6000,6 +6052,8 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 2391 unmodified lines | |||
| 6000 | return io_renameat_prep(req, sqe); | 6052 | return io_renameat_prep(req, sqe); |
| 6001 | case IORING_OP_UNLINKAT: | 6053 | case IORING_OP_UNLINKAT: |
| 6002 | return io_unlinkat_prep(req, sqe); | 6054 | return io_unlinkat_prep(req, sqe); |
| 6055 | case IORING_OP_MKDIRAT: | ||
| 6056 | return io_mkdirat_prep(req, sqe); | ||
| 6003 | } | 6057 | } |
| 6004 | 6058 | ||
| 6005 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", | 6059 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", |
| @@ -6163,6 +6217,9 @@ static void io_clean_op(struct io_kiocb *req) · 157 unmodified lines | |||
| 6163 | case IORING_OP_UNLINKAT: | 6217 | case IORING_OP_UNLINKAT: |
| 6164 | putname(req->unlink.filename); | 6218 | putname(req->unlink.filename); |
| 6165 | break; | 6219 | break; |
| 6220 | case IORING_OP_MKDIRAT: | ||
| 6221 | putname(req->mkdir.filename); | ||
| 6222 | break; | ||
| 6166 | } | 6223 | } |
| 6167 | } | 6224 | } |
| 6168 | if ((req->flags & REQ_F_POLLED) && req->apoll) { | 6225 | if ((req->flags & REQ_F_POLLED) && req->apoll) { |
| @@ -6291,6 +6348,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) · 122 unmodified lines | |||
| 6291 | case IORING_OP_UNLINKAT: | 6348 | case IORING_OP_UNLINKAT: |
| 6292 | ret = io_unlinkat(req, issue_flags); | 6349 | ret = io_unlinkat(req, issue_flags); |
| 6293 | break; | 6350 | break; |
| 6351 | case IORING_OP_MKDIRAT: | ||
| 6352 | ret = io_mkdirat(req, issue_flags); | ||
| 6353 | break; | ||
| 6294 | default: | 6354 | default: |
| 6295 | ret = -EINVAL; | 6355 | ret = -EINVAL; |
| 6296 | break; | 6356 | break; |
| @@ -133,6 +133,7 @@ enum { · 132 unmodified lines | |||
| 133 | IORING_OP_SHUTDOWN, | 133 | IORING_OP_SHUTDOWN, |
| 134 | IORING_OP_RENAMEAT, | 134 | IORING_OP_RENAMEAT, |
| 135 | IORING_OP_UNLINKAT, | 135 | IORING_OP_UNLINKAT, |
| 136 | IORING_OP_MKDIRAT, | ||
| 136 | 137 | ||
| 137 | /* this goes last, obviously */ | 138 | /* this goes last, obviously */ |
| 138 | IORING_OP_LAST, | 139 | IORING_OP_LAST, |