diff options
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r-- | fs/io_uring.c | 178 |
1 files changed, 16 insertions, 162 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index e73969fa96bc..2c793e4ccf09 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -63,7 +63,6 @@ #include <linux/net.h> #include <net/sock.h> #include <net/af_unix.h> -#include <net/scm.h> #include <linux/anon_inodes.h> #include <linux/sched/mm.h> #include <linux/uaccess.h> @@ -264,10 +263,6 @@ struct io_ring_ctx { struct async_list pending_async[2]; -#if defined(CONFIG_UNIX) - struct socket *ring_sock; -#endif - struct list_head task_list; spinlock_t task_lock; }; @@ -381,19 +376,6 @@ static struct kmem_cache *req_cachep; static const struct file_operations io_uring_fops; -struct sock *io_uring_get_socket(struct file *file) -{ -#if defined(CONFIG_UNIX) - if (file->f_op == &io_uring_fops) { - struct io_ring_ctx *ctx = file->private_data; - - return ctx->ring_sock->sk; - } -#endif - return NULL; -} -EXPORT_SYMBOL(io_uring_get_socket); - static void io_ring_ctx_ref_free(struct percpu_ref *ref) { struct io_ring_ctx *ctx = container_of(ref, struct io_ring_ctx, refs); @@ -551,7 +533,8 @@ static void io_kill_timeout(struct io_kiocb *req) atomic_inc(&req->ctx->cq_timeouts); list_del(&req->list); io_cqring_fill_event(req->ctx, req->user_data, 0); - __io_free_req(req); + if (refcount_dec_and_test(&req->refs)) + __io_free_req(req); } } @@ -1255,7 +1238,7 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw, */ const struct bio_vec *bvec = imu->bvec; - if (offset <= bvec->bv_len) { + if (offset < bvec->bv_len) { iov_iter_advance(iter, offset); } else { unsigned long seg_skip; @@ -1908,6 +1891,9 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe) __poll_t mask; u16 events; + if (req->file->f_op->may_pollfree) + return -EOPNOTSUPP; + if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; if (sqe->addr || sqe->ioprio || sqe->off || sqe->len || sqe->buf_index) @@ -2076,12 +2062,12 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe) req->sequence -= span; add: list_add(&req->list, entry); - spin_unlock_irq(&ctx->completion_lock); hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); req->timeout.timer.function = io_timeout_fn; hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts), HRTIMER_MODE_REL); + spin_unlock_irq(&ctx->completion_lock); return 0; } @@ -3076,20 +3062,10 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, static void __io_sqe_files_unregister(struct io_ring_ctx *ctx) { -#if defined(CONFIG_UNIX) - if (ctx->ring_sock) { - struct sock *sock = ctx->ring_sock->sk; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sock->sk_receive_queue)) != NULL) - kfree_skb(skb); - } -#else int i; for (i = 0; i < ctx->nr_user_files; i++) fput(ctx->user_files[i]); -#endif } static int io_sqe_files_unregister(struct io_ring_ctx *ctx) @@ -3133,100 +3109,6 @@ static void io_finish_async(struct io_ring_ctx *ctx) } } -#if defined(CONFIG_UNIX) -static void io_destruct_skb(struct sk_buff *skb) -{ - struct io_ring_ctx *ctx = skb->sk->sk_user_data; - int i; - - for (i = 0; i < ARRAY_SIZE(ctx->sqo_wq); i++) - if (ctx->sqo_wq[i]) - flush_workqueue(ctx->sqo_wq[i]); - - unix_destruct_scm(skb); -} - -/* - * Ensure the UNIX gc is aware of our file set, so we are certain that - * the io_uring can be safely unregistered on process exit, even if we have - * loops in the file referencing. - */ -static int __io_sqe_files_scm(struct io_ring_ctx *ctx, int nr, int offset) -{ - struct sock *sk = ctx->ring_sock->sk; - struct scm_fp_list *fpl; - struct sk_buff *skb; - int i; - - fpl = kzalloc(sizeof(*fpl), GFP_KERNEL); - if (!fpl) - return -ENOMEM; - - skb = alloc_skb(0, GFP_KERNEL); - if (!skb) { - kfree(fpl); - return -ENOMEM; - } - - skb->sk = sk; - skb->destructor = io_destruct_skb; - - fpl->user = get_uid(ctx->user); - for (i = 0; i < nr; i++) { - fpl->fp[i] = get_file(ctx->user_files[i + offset]); - unix_inflight(fpl->user, fpl->fp[i]); - } - - fpl->max = fpl->count = nr; - UNIXCB(skb).fp = fpl; - refcount_add(skb->truesize, &sk->sk_wmem_alloc); - skb_queue_head(&sk->sk_receive_queue, skb); - - for (i = 0; i < nr; i++) - fput(fpl->fp[i]); - - return 0; -} - -/* - * If UNIX sockets are enabled, fd passing can cause a reference cycle which - * causes regular reference counting to break down. We rely on the UNIX - * garbage collection to take care of this problem for us. - */ -static int io_sqe_files_scm(struct io_ring_ctx *ctx) -{ - unsigned left, total; - int ret = 0; - - total = 0; - left = ctx->nr_user_files; - while (left) { - unsigned this_files = min_t(unsigned, left, SCM_MAX_FD); - - ret = __io_sqe_files_scm(ctx, this_files, total); - if (ret) - break; - left -= this_files; - total += this_files; - } - - if (!ret) - return 0; - - while (total < ctx->nr_user_files) { - fput(ctx->user_files[total]); - total++; - } - - return ret; -} -#else -static int io_sqe_files_scm(struct io_ring_ctx *ctx) -{ - return 0; -} -#endif - static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, unsigned nr_args) { @@ -3280,11 +3162,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, return ret; } - ret = io_sqe_files_scm(ctx); - if (ret) - io_sqe_files_unregister(ctx); - - return ret; + return 0; } static int io_sq_offload_start(struct io_ring_ctx *ctx, @@ -3682,13 +3560,6 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx) io_sqe_files_unregister(ctx); io_eventfd_unregister(ctx); -#if defined(CONFIG_UNIX) - if (ctx->ring_sock) { - ctx->ring_sock->file = NULL; /* so that iput() is called */ - sock_release(ctx->ring_sock); - } -#endif - io_mem_free(ctx->rings); io_mem_free(ctx->sq_sqes); @@ -3734,9 +3605,6 @@ static void io_cancel_async_work(struct io_ring_ctx *ctx, { struct io_kiocb *req; - if (list_empty(&ctx->task_list)) - return; - spin_lock_irq(&ctx->task_lock); list_for_each_entry(req, &ctx->task_list, task_list) { @@ -3891,6 +3759,11 @@ static const struct file_operations io_uring_fops = { .fasync = io_uring_fasync, }; +bool io_is_uring_fops(struct file *file) +{ + return file->f_op == &io_uring_fops; +} + static int io_allocate_scq_urings(struct io_ring_ctx *ctx, struct io_uring_params *p) { @@ -3938,45 +3811,26 @@ static int io_allocate_scq_urings(struct io_ring_ctx *ctx, /* * Allocate an anonymous fd, this is what constitutes the application * visible backing of an io_uring instance. The application mmaps this - * fd to gain access to the SQ/CQ ring details. If UNIX sockets are enabled, - * we have to tie this fd to a socket for file garbage collection purposes. + * fd to gain access to the SQ/CQ ring details. */ static int io_uring_get_fd(struct io_ring_ctx *ctx) { struct file *file; int ret; -#if defined(CONFIG_UNIX) - ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP, - &ctx->ring_sock); - if (ret) - return ret; -#endif - ret = get_unused_fd_flags(O_RDWR | O_CLOEXEC); if (ret < 0) - goto err; + return ret; file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx, O_RDWR | O_CLOEXEC); if (IS_ERR(file)) { put_unused_fd(ret); - ret = PTR_ERR(file); - goto err; + return PTR_ERR(file); } -#if defined(CONFIG_UNIX) - ctx->ring_sock->file = file; - ctx->ring_sock->sk->sk_user_data = ctx; -#endif fd_install(ret, file); return ret; -err: -#if defined(CONFIG_UNIX) - sock_release(ctx->ring_sock); - ctx->ring_sock = NULL; -#endif - return ret; } static int io_uring_create(unsigned entries, struct io_uring_params *p) |