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 | 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 | 672 | struct io_completion { |
| 666 | 673 | struct file *file; |
| 667 | 674 | u32 cflags; |
| @@ -821,6 +828,7 @@ struct io_kiocb { · 153 unmodified lines | ||
| 821 | 828 | struct io_shutdown shutdown; |
| 822 | 829 | struct io_rename rename; |
| 823 | 830 | struct io_unlink unlink; |
| 831 | + struct io_mkdir mkdir; | |
| 824 | 832 | /* use only after cleaning per-op data, see io_clean_op() */ |
| 825 | 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 | 1041 | [IORING_OP_RENAMEAT] = {}, |
| 1034 | 1042 | [IORING_OP_UNLINKAT] = {}, |
| 1043 | + [IORING_OP_MKDIRAT] = {}, | |
| 1035 | 1044 | }; |
| 1036 | 1045 | |
| 1037 | 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 | 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 | 3658 | static int io_shutdown_prep(struct io_kiocb *req, |
| 3607 | 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 | 6052 | return io_renameat_prep(req, sqe); |
| 6001 | 6053 | case IORING_OP_UNLINKAT: |
| 6002 | 6054 | return io_unlinkat_prep(req, sqe); |
| 6055 | + case IORING_OP_MKDIRAT: | |
| 6056 | + return io_mkdirat_prep(req, sqe); | |
| 6003 | 6057 | } |
| 6004 | 6058 | |
| 6005 | 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 | 6217 | case IORING_OP_UNLINKAT: |
| 6164 | 6218 | putname(req->unlink.filename); |
| 6165 | 6219 | break; |
| 6220 | + case IORING_OP_MKDIRAT: | |
| 6221 | + putname(req->mkdir.filename); | |
| 6222 | + break; | |
| 6166 | 6223 | } |
| 6167 | 6224 | } |
| 6168 | 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 | 6348 | case IORING_OP_UNLINKAT: |
| 6292 | 6349 | ret = io_unlinkat(req, issue_flags); |
| 6293 | 6350 | break; |
| 6351 | + case IORING_OP_MKDIRAT: | |
| 6352 | + ret = io_mkdirat(req, issue_flags); | |
| 6353 | + break; | |
| 6294 | 6354 | default: |
| 6295 | 6355 | ret = -EINVAL; |
| 6296 | 6356 | break; |
| @@ -133,6 +133,7 @@ enum { · 132 unmodified lines | ||
| 133 | 133 | IORING_OP_SHUTDOWN, |
| 134 | 134 | IORING_OP_RENAMEAT, |
| 135 | 135 | IORING_OP_UNLINKAT, |
| 136 | + IORING_OP_MKDIRAT, | |
| 136 | 137 | |
| 137 | 138 | /* this goes last, obviously */ |
| 138 | 139 | IORING_OP_LAST, |