IORING_OP_UNLINKAT behaves like unlinkat(2) and takes the same flags and arguments.
Unified · Split
| @@ -555,6 +555,13 @@ struct io_rename { · 554 unmodified lines | |||
| 555 | int flags; | 555 | int flags; |
| 556 | }; | 556 | }; |
| 557 | 557 | ||
| 558 | struct io_unlink { | ||
| 559 | struct file *file; | ||
| 560 | int dfd; | ||
| 561 | int flags; | ||
| 562 | struct filename *filename; | ||
| 563 | }; | ||
| 564 | |||
| 558 | struct io_completion { | 565 | struct io_completion { |
| 559 | struct file *file; | 566 | struct file *file; |
| 560 | struct list_head list; | 567 | struct list_head list; |
| @@ -683,6 +690,7 @@ struct io_kiocb { · 122 unmodified lines | |||
| 683 | struct io_statx statx; | 690 | struct io_statx statx; |
| 684 | struct io_shutdown shutdown; | 691 | struct io_shutdown shutdown; |
| 685 | struct io_rename rename; | 692 | struct io_rename rename; |
| 693 | struct io_unlink unlink; | ||
| 686 | /* use only after cleaning per-op data, see io_clean_op() */ | 694 | /* use only after cleaning per-op data, see io_clean_op() */ |
| 687 | struct io_completion compl; | 695 | struct io_completion compl; |
| 688 | }; | 696 | }; |
| @@ -957,6 +965,10 @@ static const struct io_op_def io_op_defs[] = { · 268 unmodified lines | |||
| 957 | .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | | 965 | .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | |
| 958 | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, | 966 | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, |
| 959 | }, | 967 | }, |
| 968 | [IORING_OP_UNLINKAT] = { | ||
| 969 | .work_flags = IO_WQ_WORK_MM | IO_WQ_WORK_FILES | | ||
| 970 | IO_WQ_WORK_FS | IO_WQ_WORK_BLKCG, | ||
| 971 | }, | ||
| 960 | }; | 972 | }; |
| 961 | 973 | ||
| 962 | enum io_mem_account { | 974 | enum io_mem_account { |
| @@ -3706,6 +3718,50 @@ static int io_renameat(struct io_kiocb *req, bool force_nonblock) · 2743 unmodified lines | |||
| 3706 | return 0; | 3718 | return 0; |
| 3707 | } | 3719 | } |
| 3708 | 3720 | ||
| 3721 | static int io_unlinkat_prep(struct io_kiocb *req, | ||
| 3722 | const struct io_uring_sqe *sqe) | ||
| 3723 | { | ||
| 3724 | struct io_unlink *un = &req->unlink; | ||
| 3725 | const char __user *fname; | ||
| 3726 | |||
| 3727 | if (unlikely(req->flags & REQ_F_FIXED_FILE)) | ||
| 3728 | return -EBADF; | ||
| 3729 | |||
| 3730 | un->dfd = READ_ONCE(sqe->fd); | ||
| 3731 | |||
| 3732 | un->flags = READ_ONCE(sqe->unlink_flags); | ||
| 3733 | if (un->flags & ~AT_REMOVEDIR) | ||
| 3734 | return -EINVAL; | ||
| 3735 | |||
| 3736 | fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); | ||
| 3737 | un->filename = getname(fname); | ||
| 3738 | if (IS_ERR(un->filename)) | ||
| 3739 | return PTR_ERR(un->filename); | ||
| 3740 | |||
| 3741 | req->flags |= REQ_F_NEED_CLEANUP; | ||
| 3742 | return 0; | ||
| 3743 | } | ||
| 3744 | |||
| 3745 | static int io_unlinkat(struct io_kiocb *req, bool force_nonblock) | ||
| 3746 | { | ||
| 3747 | struct io_unlink *un = &req->unlink; | ||
| 3748 | int ret; | ||
| 3749 | |||
| 3750 | if (force_nonblock) | ||
| 3751 | return -EAGAIN; | ||
| 3752 | |||
| 3753 | if (un->flags & AT_REMOVEDIR) | ||
| 3754 | ret = do_rmdir(un->dfd, un->filename); | ||
| 3755 | else | ||
| 3756 | ret = do_unlinkat(un->dfd, un->filename); | ||
| 3757 | |||
| 3758 | req->flags &= ~REQ_F_NEED_CLEANUP; | ||
| 3759 | if (ret < 0) | ||
| 3760 | req_set_fail_links(req); | ||
| 3761 | io_req_complete(req, ret); | ||
| 3762 | return 0; | ||
| 3763 | } | ||
| 3764 | |||
| 3709 | static int io_shutdown_prep(struct io_kiocb *req, | 3765 | static int io_shutdown_prep(struct io_kiocb *req, |
| 3710 | const struct io_uring_sqe *sqe) | 3766 | const struct io_uring_sqe *sqe) |
| 3711 | { | 3767 | { |
| @@ -5932,6 +5988,8 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 2220 unmodified lines | |||
| 5932 | return io_shutdown_prep(req, sqe); | 5988 | return io_shutdown_prep(req, sqe); |
| 5933 | case IORING_OP_RENAMEAT: | 5989 | case IORING_OP_RENAMEAT: |
| 5934 | return io_renameat_prep(req, sqe); | 5990 | return io_renameat_prep(req, sqe); |
| 5991 | case IORING_OP_UNLINKAT: | ||
| 5992 | return io_unlinkat_prep(req, sqe); | ||
| 5935 | } | 5993 | } |
| 5936 | 5994 | ||
| 5937 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", | 5995 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", |
| @@ -6073,6 +6131,9 @@ static void __io_clean_op(struct io_kiocb *req) · 135 unmodified lines | |||
| 6073 | putname(req->rename.oldpath); | 6131 | putname(req->rename.oldpath); |
| 6074 | putname(req->rename.newpath); | 6132 | putname(req->rename.newpath); |
| 6075 | break; | 6133 | break; |
| 6134 | case IORING_OP_UNLINKAT: | ||
| 6135 | putname(req->unlink.filename); | ||
| 6136 | break; | ||
| 6076 | } | 6137 | } |
| 6077 | req->flags &= ~REQ_F_NEED_CLEANUP; | 6138 | req->flags &= ~REQ_F_NEED_CLEANUP; |
| 6078 | } | 6139 | } |
| @@ -6185,6 +6246,9 @@ static int io_issue_sqe(struct io_kiocb *req, bool force_nonblock, · 106 unmodified lines | |||
| 6185 | case IORING_OP_RENAMEAT: | 6246 | case IORING_OP_RENAMEAT: |
| 6186 | ret = io_renameat(req, force_nonblock); | 6247 | ret = io_renameat(req, force_nonblock); |
| 6187 | break; | 6248 | break; |
| 6249 | case IORING_OP_UNLINKAT: | ||
| 6250 | ret = io_unlinkat(req, force_nonblock); | ||
| 6251 | break; | ||
| 6188 | default: | 6252 | default: |
| 6189 | ret = -EINVAL; | 6253 | ret = -EINVAL; |
| 6190 | break; | 6254 | break; |
| @@ -43,6 +43,7 @@ struct io_uring_sqe { · 42 unmodified lines | |||
| 43 | __u32 fadvise_advice; | 43 | __u32 fadvise_advice; |
| 44 | __u32 splice_flags; | 44 | __u32 splice_flags; |
| 45 | __u32 rename_flags; | 45 | __u32 rename_flags; |
| 46 | __u32 unlink_flags; | ||
| 46 | }; | 47 | }; |
| 47 | __u64 user_data; /* data to be passed back at completion time */ | 48 | __u64 user_data; /* data to be passed back at completion time */ |
| 48 | union { | 49 | union { |
| @@ -135,6 +136,7 @@ enum { · 86 unmodified lines | |||
| 135 | IORING_OP_TEE, | 136 | IORING_OP_TEE, |
| 136 | IORING_OP_SHUTDOWN, | 137 | IORING_OP_SHUTDOWN, |
| 137 | IORING_OP_RENAMEAT, | 138 | IORING_OP_RENAMEAT, |
| 139 | IORING_OP_UNLINKAT, | ||
| 138 | 140 | ||
| 139 | /* this goes last, obviously */ | 141 | /* this goes last, obviously */ |
| 140 | IORING_OP_LAST, | 142 | IORING_OP_LAST, |