Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring: split out open/close operations

Signed-off-by: Jens Axboe <axboe@kernel.dk>

+345 -298
+2 -1
io_uring/Makefile
··· 3 3 # Makefile for io_uring 4 4 5 5 obj-$(CONFIG_IO_URING) += io_uring.o xattr.o nop.o fs.o splice.o \ 6 - sync.o advise.o filetable.o 6 + sync.o advise.o filetable.o \ 7 + openclose.o 7 8 obj-$(CONFIG_IO_WQ) += io-wq.o
+14 -297
io_uring/io_uring.c
··· 98 98 #include "splice.h" 99 99 #include "sync.h" 100 100 #include "advise.h" 101 + #include "openclose.h" 101 102 102 103 #define IORING_MAX_ENTRIES 32768 103 104 #define IORING_MAX_CQ_ENTRIES (2 * IORING_MAX_ENTRIES) ··· 284 283 bool update_user_data; 285 284 }; 286 285 287 - struct io_close { 288 - struct file *file; 289 - int fd; 290 - u32 file_slot; 291 - }; 292 - 293 286 struct io_timeout_data { 294 287 struct io_kiocb *req; 295 288 struct hrtimer timer; ··· 364 369 size_t len; 365 370 size_t done_io; 366 371 unsigned int flags; 367 - }; 368 - 369 - struct io_open { 370 - struct file *file; 371 - int dfd; 372 - u32 file_slot; 373 - struct filename *filename; 374 - struct open_how how; 375 - unsigned long nofile; 376 372 }; 377 373 378 374 struct io_rsrc_update { ··· 541 555 542 556 static int io_install_fixed_file(struct io_kiocb *req, struct file *file, 543 557 unsigned int issue_flags, u32 slot_index); 544 - static int __io_close_fixed(struct io_kiocb *req, unsigned int issue_flags, 545 - unsigned int offset); 546 - static inline int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags); 547 558 548 559 static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer); 549 560 static void io_eventfd_signal(struct io_ring_ctx *ctx); ··· 653 670 return "INVALID"; 654 671 } 655 672 673 + bool io_is_uring_fops(struct file *file) 674 + { 675 + return file->f_op == &io_uring_fops; 676 + } 677 + 656 678 struct sock *io_uring_get_socket(struct file *file) 657 679 { 658 680 #if defined(CONFIG_UNIX) 659 - if (file->f_op == &io_uring_fops) { 681 + if (io_is_uring_fops(file)) { 660 682 struct io_ring_ctx *ctx = file->private_data; 661 683 662 684 return ctx->ring_sock->sk; ··· 686 698 return false; 687 699 } 688 700 #endif 689 - 690 - static void io_ring_submit_unlock(struct io_ring_ctx *ctx, unsigned issue_flags) 691 - { 692 - lockdep_assert_held(&ctx->uring_lock); 693 - if (issue_flags & IO_URING_F_UNLOCKED) 694 - mutex_unlock(&ctx->uring_lock); 695 - } 696 - 697 - static void io_ring_submit_lock(struct io_ring_ctx *ctx, unsigned issue_flags) 698 - { 699 - /* 700 - * "Normal" inline submissions always hold the uring_lock, since we 701 - * grab it from the system call. Same is true for the SQPOLL offload. 702 - * The only exception is when we've detached the request and issue it 703 - * from an async worker thread, grab the lock for that case. 704 - */ 705 - if (issue_flags & IO_URING_F_UNLOCKED) 706 - mutex_lock(&ctx->uring_lock); 707 - lockdep_assert_held(&ctx->uring_lock); 708 - } 709 701 710 702 static inline void io_tw_lock(struct io_ring_ctx *ctx, bool *locked) 711 703 { ··· 3867 3899 return IOU_OK; 3868 3900 } 3869 3901 3870 - static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 3871 - { 3872 - struct io_open *open = io_kiocb_to_cmd(req); 3873 - const char __user *fname; 3874 - int ret; 3875 - 3876 - if (unlikely(sqe->buf_index)) 3877 - return -EINVAL; 3878 - if (unlikely(req->flags & REQ_F_FIXED_FILE)) 3879 - return -EBADF; 3880 - 3881 - /* open.how should be already initialised */ 3882 - if (!(open->how.flags & O_PATH) && force_o_largefile()) 3883 - open->how.flags |= O_LARGEFILE; 3884 - 3885 - open->dfd = READ_ONCE(sqe->fd); 3886 - fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); 3887 - open->filename = getname(fname); 3888 - if (IS_ERR(open->filename)) { 3889 - ret = PTR_ERR(open->filename); 3890 - open->filename = NULL; 3891 - return ret; 3892 - } 3893 - 3894 - open->file_slot = READ_ONCE(sqe->file_index); 3895 - if (open->file_slot && (open->how.flags & O_CLOEXEC)) 3896 - return -EINVAL; 3897 - 3898 - open->nofile = rlimit(RLIMIT_NOFILE); 3899 - req->flags |= REQ_F_NEED_CLEANUP; 3900 - return 0; 3901 - } 3902 - 3903 - static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 3904 - { 3905 - struct io_open *open = io_kiocb_to_cmd(req); 3906 - u64 mode = READ_ONCE(sqe->len); 3907 - u64 flags = READ_ONCE(sqe->open_flags); 3908 - 3909 - open->how = build_open_how(flags, mode); 3910 - return __io_openat_prep(req, sqe); 3911 - } 3912 - 3913 - static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 3914 - { 3915 - struct io_open *open = io_kiocb_to_cmd(req); 3916 - struct open_how __user *how; 3917 - size_t len; 3918 - int ret; 3919 - 3920 - how = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 3921 - len = READ_ONCE(sqe->len); 3922 - if (len < OPEN_HOW_SIZE_VER0) 3923 - return -EINVAL; 3924 - 3925 - ret = copy_struct_from_user(&open->how, sizeof(open->how), how, len); 3926 - if (ret) 3927 - return ret; 3928 - 3929 - return __io_openat_prep(req, sqe); 3930 - } 3931 - 3932 3902 /* 3933 3903 * Note when io_fixed_fd_install() returns error value, it will ensure 3934 3904 * fput() is called correspondingly. 3935 3905 */ 3936 - static int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags, 3937 - struct file *file, unsigned int file_slot) 3906 + int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags, 3907 + struct file *file, unsigned int file_slot) 3938 3908 { 3939 3909 bool alloc_slot = file_slot == IORING_FILE_INDEX_ALLOC; 3940 3910 struct io_ring_ctx *ctx = req->ctx; ··· 3897 3991 if (unlikely(ret < 0)) 3898 3992 fput(file); 3899 3993 return ret; 3900 - } 3901 - 3902 - static int io_openat2(struct io_kiocb *req, unsigned int issue_flags) 3903 - { 3904 - struct io_open *open = io_kiocb_to_cmd(req); 3905 - struct open_flags op; 3906 - struct file *file; 3907 - bool resolve_nonblock, nonblock_set; 3908 - bool fixed = !!open->file_slot; 3909 - int ret; 3910 - 3911 - ret = build_open_flags(&open->how, &op); 3912 - if (ret) 3913 - goto err; 3914 - nonblock_set = op.open_flag & O_NONBLOCK; 3915 - resolve_nonblock = open->how.resolve & RESOLVE_CACHED; 3916 - if (issue_flags & IO_URING_F_NONBLOCK) { 3917 - /* 3918 - * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open, 3919 - * it'll always -EAGAIN 3920 - */ 3921 - if (open->how.flags & (O_TRUNC | O_CREAT | O_TMPFILE)) 3922 - return -EAGAIN; 3923 - op.lookup_flags |= LOOKUP_CACHED; 3924 - op.open_flag |= O_NONBLOCK; 3925 - } 3926 - 3927 - if (!fixed) { 3928 - ret = __get_unused_fd_flags(open->how.flags, open->nofile); 3929 - if (ret < 0) 3930 - goto err; 3931 - } 3932 - 3933 - file = do_filp_open(open->dfd, open->filename, &op); 3934 - if (IS_ERR(file)) { 3935 - /* 3936 - * We could hang on to this 'fd' on retrying, but seems like 3937 - * marginal gain for something that is now known to be a slower 3938 - * path. So just put it, and we'll get a new one when we retry. 3939 - */ 3940 - if (!fixed) 3941 - put_unused_fd(ret); 3942 - 3943 - ret = PTR_ERR(file); 3944 - /* only retry if RESOLVE_CACHED wasn't already set by application */ 3945 - if (ret == -EAGAIN && 3946 - (!resolve_nonblock && (issue_flags & IO_URING_F_NONBLOCK))) 3947 - return -EAGAIN; 3948 - goto err; 3949 - } 3950 - 3951 - if ((issue_flags & IO_URING_F_NONBLOCK) && !nonblock_set) 3952 - file->f_flags &= ~O_NONBLOCK; 3953 - fsnotify_open(file); 3954 - 3955 - if (!fixed) 3956 - fd_install(ret, file); 3957 - else 3958 - ret = io_fixed_fd_install(req, issue_flags, file, 3959 - open->file_slot); 3960 - err: 3961 - putname(open->filename); 3962 - req->flags &= ~REQ_F_NEED_CLEANUP; 3963 - if (ret < 0) 3964 - req_set_fail(req); 3965 - io_req_set_res(req, ret, 0); 3966 - return IOU_OK; 3967 - } 3968 - 3969 - static int io_openat(struct io_kiocb *req, unsigned int issue_flags) 3970 - { 3971 - return io_openat2(req, issue_flags); 3972 - } 3973 - 3974 - static void io_open_cleanup(struct io_kiocb *req) 3975 - { 3976 - struct io_open *open = io_kiocb_to_cmd(req); 3977 - 3978 - if (open->filename) 3979 - putname(open->filename); 3980 3994 } 3981 3995 3982 3996 static int io_remove_buffers_prep(struct io_kiocb *req, ··· 4248 4422 4249 4423 if (sx->filename) 4250 4424 putname(sx->filename); 4251 - } 4252 - 4253 - static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 4254 - { 4255 - struct io_close *close = io_kiocb_to_cmd(req); 4256 - 4257 - if (sqe->off || sqe->addr || sqe->len || sqe->rw_flags || sqe->buf_index) 4258 - return -EINVAL; 4259 - if (req->flags & REQ_F_FIXED_FILE) 4260 - return -EBADF; 4261 - 4262 - close->fd = READ_ONCE(sqe->fd); 4263 - close->file_slot = READ_ONCE(sqe->file_index); 4264 - if (close->file_slot && close->fd) 4265 - return -EINVAL; 4266 - 4267 - return 0; 4268 - } 4269 - 4270 - static int io_close(struct io_kiocb *req, unsigned int issue_flags) 4271 - { 4272 - struct files_struct *files = current->files; 4273 - struct io_close *close = io_kiocb_to_cmd(req); 4274 - struct fdtable *fdt; 4275 - struct file *file; 4276 - int ret = -EBADF; 4277 - 4278 - if (close->file_slot) { 4279 - ret = io_close_fixed(req, issue_flags); 4280 - goto err; 4281 - } 4282 - 4283 - spin_lock(&files->file_lock); 4284 - fdt = files_fdtable(files); 4285 - if (close->fd >= fdt->max_fds) { 4286 - spin_unlock(&files->file_lock); 4287 - goto err; 4288 - } 4289 - file = rcu_dereference_protected(fdt->fd[close->fd], 4290 - lockdep_is_held(&files->file_lock)); 4291 - if (!file || file->f_op == &io_uring_fops) { 4292 - spin_unlock(&files->file_lock); 4293 - goto err; 4294 - } 4295 - 4296 - /* if the file has a flush method, be safe and punt to async */ 4297 - if (file->f_op->flush && (issue_flags & IO_URING_F_NONBLOCK)) { 4298 - spin_unlock(&files->file_lock); 4299 - return -EAGAIN; 4300 - } 4301 - 4302 - file = __close_fd_get_file(close->fd); 4303 - spin_unlock(&files->file_lock); 4304 - if (!file) 4305 - goto err; 4306 - 4307 - /* No ->flush() or already async, safely close from here */ 4308 - ret = filp_close(file, current->files); 4309 - err: 4310 - if (ret < 0) 4311 - req_set_fail(req); 4312 - io_req_set_res(req, ret, 0); 4313 - return IOU_OK; 4314 4425 } 4315 4426 4316 4427 #if defined(CONFIG_NET) ··· 7507 7744 return ref_node; 7508 7745 } 7509 7746 7510 - static void io_rsrc_node_switch(struct io_ring_ctx *ctx, 7511 - struct io_rsrc_data *data_to_kill) 7747 + void io_rsrc_node_switch(struct io_ring_ctx *ctx, 7748 + struct io_rsrc_data *data_to_kill) 7512 7749 __must_hold(&ctx->uring_lock) 7513 7750 { 7514 7751 WARN_ON_ONCE(!ctx->rsrc_backup_node); ··· 7535 7772 } 7536 7773 } 7537 7774 7538 - static int io_rsrc_node_switch_start(struct io_ring_ctx *ctx) 7775 + int io_rsrc_node_switch_start(struct io_ring_ctx *ctx) 7539 7776 { 7540 7777 if (ctx->rsrc_backup_node) 7541 7778 return 0; ··· 8082 8319 return ret; 8083 8320 } 8084 8321 8085 - static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, 8086 - struct io_rsrc_node *node, void *rsrc) 8322 + int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, 8323 + struct io_rsrc_node *node, void *rsrc) 8087 8324 { 8088 8325 u64 *tag_slot = io_get_tag_slot(data, idx); 8089 8326 struct io_rsrc_put *prsrc; ··· 8147 8384 if (ret) 8148 8385 fput(file); 8149 8386 return ret; 8150 - } 8151 - 8152 - static int __io_close_fixed(struct io_kiocb *req, unsigned int issue_flags, 8153 - unsigned int offset) 8154 - { 8155 - struct io_ring_ctx *ctx = req->ctx; 8156 - struct io_fixed_file *file_slot; 8157 - struct file *file; 8158 - int ret; 8159 - 8160 - io_ring_submit_lock(ctx, issue_flags); 8161 - ret = -ENXIO; 8162 - if (unlikely(!ctx->file_data)) 8163 - goto out; 8164 - ret = -EINVAL; 8165 - if (offset >= ctx->nr_user_files) 8166 - goto out; 8167 - ret = io_rsrc_node_switch_start(ctx); 8168 - if (ret) 8169 - goto out; 8170 - 8171 - offset = array_index_nospec(offset, ctx->nr_user_files); 8172 - file_slot = io_fixed_file_slot(&ctx->file_table, offset); 8173 - ret = -EBADF; 8174 - if (!file_slot->file_ptr) 8175 - goto out; 8176 - 8177 - file = (struct file *)(file_slot->file_ptr & FFS_MASK); 8178 - ret = io_queue_rsrc_removal(ctx->file_data, offset, ctx->rsrc_node, file); 8179 - if (ret) 8180 - goto out; 8181 - 8182 - file_slot->file_ptr = 0; 8183 - io_file_bitmap_clear(&ctx->file_table, offset); 8184 - io_rsrc_node_switch(ctx, ctx->file_data); 8185 - ret = 0; 8186 - out: 8187 - io_ring_submit_unlock(ctx, issue_flags); 8188 - return ret; 8189 - } 8190 - 8191 - static inline int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags) 8192 - { 8193 - struct io_close *close = io_kiocb_to_cmd(req); 8194 - 8195 - return __io_close_fixed(req, issue_flags, close->file_slot - 1); 8196 8387 } 8197 8388 8198 8389 static int __io_sqe_files_update(struct io_ring_ctx *ctx,
+32
io_uring/io_uring.h
··· 2 2 #define IOU_CORE_H 3 3 4 4 #include <linux/errno.h> 5 + #include <linux/lockdep.h> 5 6 #include "io_uring_types.h" 6 7 7 8 enum { ··· 31 30 fput(file); 32 31 } 33 32 33 + static inline void io_ring_submit_unlock(struct io_ring_ctx *ctx, 34 + unsigned issue_flags) 35 + { 36 + lockdep_assert_held(&ctx->uring_lock); 37 + if (issue_flags & IO_URING_F_UNLOCKED) 38 + mutex_unlock(&ctx->uring_lock); 39 + } 40 + 41 + static inline void io_ring_submit_lock(struct io_ring_ctx *ctx, 42 + unsigned issue_flags) 43 + { 44 + /* 45 + * "Normal" inline submissions always hold the uring_lock, since we 46 + * grab it from the system call. Same is true for the SQPOLL offload. 47 + * The only exception is when we've detached the request and issue it 48 + * from an async worker thread, grab the lock for that case. 49 + */ 50 + if (issue_flags & IO_URING_F_UNLOCKED) 51 + mutex_lock(&ctx->uring_lock); 52 + lockdep_assert_held(&ctx->uring_lock); 53 + } 54 + 34 55 struct file *io_file_get_normal(struct io_kiocb *req, int fd); 35 56 struct file *io_file_get_fixed(struct io_kiocb *req, int fd, 36 57 unsigned issue_flags); 58 + int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags, 59 + struct file *file, unsigned int file_slot); 60 + 61 + int io_rsrc_node_switch_start(struct io_ring_ctx *ctx); 62 + int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, 63 + struct io_rsrc_node *node, void *rsrc); 64 + void io_rsrc_node_switch(struct io_ring_ctx *ctx, 65 + struct io_rsrc_data *data_to_kill); 66 + bool io_is_uring_fops(struct file *file); 37 67 38 68 #endif
+283
io_uring/openclose.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/kernel.h> 3 + #include <linux/errno.h> 4 + #include <linux/fs.h> 5 + #include <linux/file.h> 6 + #include <linux/fdtable.h> 7 + #include <linux/fsnotify.h> 8 + #include <linux/namei.h> 9 + #include <linux/io_uring.h> 10 + 11 + #include <uapi/linux/io_uring.h> 12 + 13 + #include "../fs/internal.h" 14 + 15 + #include "io_uring_types.h" 16 + #include "io_uring.h" 17 + #include "openclose.h" 18 + 19 + struct io_open { 20 + struct file *file; 21 + int dfd; 22 + u32 file_slot; 23 + struct filename *filename; 24 + struct open_how how; 25 + unsigned long nofile; 26 + }; 27 + 28 + struct io_close { 29 + struct file *file; 30 + int fd; 31 + u32 file_slot; 32 + }; 33 + 34 + static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 35 + { 36 + struct io_open *open = io_kiocb_to_cmd(req); 37 + const char __user *fname; 38 + int ret; 39 + 40 + if (unlikely(sqe->buf_index)) 41 + return -EINVAL; 42 + if (unlikely(req->flags & REQ_F_FIXED_FILE)) 43 + return -EBADF; 44 + 45 + /* open.how should be already initialised */ 46 + if (!(open->how.flags & O_PATH) && force_o_largefile()) 47 + open->how.flags |= O_LARGEFILE; 48 + 49 + open->dfd = READ_ONCE(sqe->fd); 50 + fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); 51 + open->filename = getname(fname); 52 + if (IS_ERR(open->filename)) { 53 + ret = PTR_ERR(open->filename); 54 + open->filename = NULL; 55 + return ret; 56 + } 57 + 58 + open->file_slot = READ_ONCE(sqe->file_index); 59 + if (open->file_slot && (open->how.flags & O_CLOEXEC)) 60 + return -EINVAL; 61 + 62 + open->nofile = rlimit(RLIMIT_NOFILE); 63 + req->flags |= REQ_F_NEED_CLEANUP; 64 + return 0; 65 + } 66 + 67 + int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 68 + { 69 + struct io_open *open = io_kiocb_to_cmd(req); 70 + u64 mode = READ_ONCE(sqe->len); 71 + u64 flags = READ_ONCE(sqe->open_flags); 72 + 73 + open->how = build_open_how(flags, mode); 74 + return __io_openat_prep(req, sqe); 75 + } 76 + 77 + int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 78 + { 79 + struct io_open *open = io_kiocb_to_cmd(req); 80 + struct open_how __user *how; 81 + size_t len; 82 + int ret; 83 + 84 + how = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 85 + len = READ_ONCE(sqe->len); 86 + if (len < OPEN_HOW_SIZE_VER0) 87 + return -EINVAL; 88 + 89 + ret = copy_struct_from_user(&open->how, sizeof(open->how), how, len); 90 + if (ret) 91 + return ret; 92 + 93 + return __io_openat_prep(req, sqe); 94 + } 95 + 96 + int io_openat2(struct io_kiocb *req, unsigned int issue_flags) 97 + { 98 + struct io_open *open = io_kiocb_to_cmd(req); 99 + struct open_flags op; 100 + struct file *file; 101 + bool resolve_nonblock, nonblock_set; 102 + bool fixed = !!open->file_slot; 103 + int ret; 104 + 105 + ret = build_open_flags(&open->how, &op); 106 + if (ret) 107 + goto err; 108 + nonblock_set = op.open_flag & O_NONBLOCK; 109 + resolve_nonblock = open->how.resolve & RESOLVE_CACHED; 110 + if (issue_flags & IO_URING_F_NONBLOCK) { 111 + /* 112 + * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open, 113 + * it'll always -EAGAIN 114 + */ 115 + if (open->how.flags & (O_TRUNC | O_CREAT | O_TMPFILE)) 116 + return -EAGAIN; 117 + op.lookup_flags |= LOOKUP_CACHED; 118 + op.open_flag |= O_NONBLOCK; 119 + } 120 + 121 + if (!fixed) { 122 + ret = __get_unused_fd_flags(open->how.flags, open->nofile); 123 + if (ret < 0) 124 + goto err; 125 + } 126 + 127 + file = do_filp_open(open->dfd, open->filename, &op); 128 + if (IS_ERR(file)) { 129 + /* 130 + * We could hang on to this 'fd' on retrying, but seems like 131 + * marginal gain for something that is now known to be a slower 132 + * path. So just put it, and we'll get a new one when we retry. 133 + */ 134 + if (!fixed) 135 + put_unused_fd(ret); 136 + 137 + ret = PTR_ERR(file); 138 + /* only retry if RESOLVE_CACHED wasn't already set by application */ 139 + if (ret == -EAGAIN && 140 + (!resolve_nonblock && (issue_flags & IO_URING_F_NONBLOCK))) 141 + return -EAGAIN; 142 + goto err; 143 + } 144 + 145 + if ((issue_flags & IO_URING_F_NONBLOCK) && !nonblock_set) 146 + file->f_flags &= ~O_NONBLOCK; 147 + fsnotify_open(file); 148 + 149 + if (!fixed) 150 + fd_install(ret, file); 151 + else 152 + ret = io_fixed_fd_install(req, issue_flags, file, 153 + open->file_slot); 154 + err: 155 + putname(open->filename); 156 + req->flags &= ~REQ_F_NEED_CLEANUP; 157 + if (ret < 0) 158 + req_set_fail(req); 159 + io_req_set_res(req, ret, 0); 160 + return IOU_OK; 161 + } 162 + 163 + int io_openat(struct io_kiocb *req, unsigned int issue_flags) 164 + { 165 + return io_openat2(req, issue_flags); 166 + } 167 + 168 + void io_open_cleanup(struct io_kiocb *req) 169 + { 170 + struct io_open *open = io_kiocb_to_cmd(req); 171 + 172 + if (open->filename) 173 + putname(open->filename); 174 + } 175 + 176 + int __io_close_fixed(struct io_kiocb *req, unsigned int issue_flags, 177 + unsigned int offset) 178 + { 179 + struct io_ring_ctx *ctx = req->ctx; 180 + struct io_fixed_file *file_slot; 181 + struct file *file; 182 + int ret; 183 + 184 + io_ring_submit_lock(ctx, issue_flags); 185 + ret = -ENXIO; 186 + if (unlikely(!ctx->file_data)) 187 + goto out; 188 + ret = -EINVAL; 189 + if (offset >= ctx->nr_user_files) 190 + goto out; 191 + ret = io_rsrc_node_switch_start(ctx); 192 + if (ret) 193 + goto out; 194 + 195 + offset = array_index_nospec(offset, ctx->nr_user_files); 196 + file_slot = io_fixed_file_slot(&ctx->file_table, offset); 197 + ret = -EBADF; 198 + if (!file_slot->file_ptr) 199 + goto out; 200 + 201 + file = (struct file *)(file_slot->file_ptr & FFS_MASK); 202 + ret = io_queue_rsrc_removal(ctx->file_data, offset, ctx->rsrc_node, file); 203 + if (ret) 204 + goto out; 205 + 206 + file_slot->file_ptr = 0; 207 + io_file_bitmap_clear(&ctx->file_table, offset); 208 + io_rsrc_node_switch(ctx, ctx->file_data); 209 + ret = 0; 210 + out: 211 + io_ring_submit_unlock(ctx, issue_flags); 212 + return ret; 213 + } 214 + 215 + static inline int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags) 216 + { 217 + struct io_close *close = io_kiocb_to_cmd(req); 218 + 219 + return __io_close_fixed(req, issue_flags, close->file_slot - 1); 220 + } 221 + 222 + int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 223 + { 224 + struct io_close *close = io_kiocb_to_cmd(req); 225 + 226 + if (sqe->off || sqe->addr || sqe->len || sqe->rw_flags || sqe->buf_index) 227 + return -EINVAL; 228 + if (req->flags & REQ_F_FIXED_FILE) 229 + return -EBADF; 230 + 231 + close->fd = READ_ONCE(sqe->fd); 232 + close->file_slot = READ_ONCE(sqe->file_index); 233 + if (close->file_slot && close->fd) 234 + return -EINVAL; 235 + 236 + return 0; 237 + } 238 + 239 + int io_close(struct io_kiocb *req, unsigned int issue_flags) 240 + { 241 + struct files_struct *files = current->files; 242 + struct io_close *close = io_kiocb_to_cmd(req); 243 + struct fdtable *fdt; 244 + struct file *file; 245 + int ret = -EBADF; 246 + 247 + if (close->file_slot) { 248 + ret = io_close_fixed(req, issue_flags); 249 + goto err; 250 + } 251 + 252 + spin_lock(&files->file_lock); 253 + fdt = files_fdtable(files); 254 + if (close->fd >= fdt->max_fds) { 255 + spin_unlock(&files->file_lock); 256 + goto err; 257 + } 258 + file = rcu_dereference_protected(fdt->fd[close->fd], 259 + lockdep_is_held(&files->file_lock)); 260 + if (!file || io_is_uring_fops(file)) { 261 + spin_unlock(&files->file_lock); 262 + goto err; 263 + } 264 + 265 + /* if the file has a flush method, be safe and punt to async */ 266 + if (file->f_op->flush && (issue_flags & IO_URING_F_NONBLOCK)) { 267 + spin_unlock(&files->file_lock); 268 + return -EAGAIN; 269 + } 270 + 271 + file = __close_fd_get_file(close->fd); 272 + spin_unlock(&files->file_lock); 273 + if (!file) 274 + goto err; 275 + 276 + /* No ->flush() or already async, safely close from here */ 277 + ret = filp_close(file, current->files); 278 + err: 279 + if (ret < 0) 280 + req_set_fail(req); 281 + io_req_set_res(req, ret, 0); 282 + return IOU_OK; 283 + }
+14
io_uring/openclose.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + int __io_close_fixed(struct io_kiocb *req, unsigned int issue_flags, 4 + unsigned int offset); 5 + 6 + int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 7 + int io_openat(struct io_kiocb *req, unsigned int issue_flags); 8 + void io_open_cleanup(struct io_kiocb *req); 9 + 10 + int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 11 + int io_openat2(struct io_kiocb *req, unsigned int issue_flags); 12 + 13 + int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 14 + int io_close(struct io_kiocb *req, unsigned int issue_flags);