drm/amd/display: Implement bounds check for stream encoder creation in DCN301
[platform/kernel/linux-rpi.git] / io_uring / io_uring.c
index efd5331..ea772a0 100644 (file)
@@ -269,6 +269,7 @@ static __cold void io_fallback_req_func(struct work_struct *work)
        struct io_kiocb *req, *tmp;
        struct io_tw_state ts = { .locked = true, };
 
+       percpu_ref_get(&ctx->refs);
        mutex_lock(&ctx->uring_lock);
        llist_for_each_entry_safe(req, tmp, node, io_task_work.node)
                req->io_task_work.func(req, &ts);
@@ -276,6 +277,7 @@ static __cold void io_fallback_req_func(struct work_struct *work)
                return;
        io_submit_flush_completions(ctx);
        mutex_unlock(&ctx->uring_lock);
+       percpu_ref_put(&ctx->refs);
 }
 
 static int io_alloc_hash_table(struct io_hash_table *table, unsigned bits)
@@ -323,6 +325,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
        INIT_LIST_HEAD(&ctx->sqd_list);
        INIT_LIST_HEAD(&ctx->cq_overflow_list);
        INIT_LIST_HEAD(&ctx->io_buffers_cache);
+       INIT_HLIST_HEAD(&ctx->io_buf_list);
        io_alloc_cache_init(&ctx->rsrc_node_cache, IO_NODE_ALLOC_CACHE_MAX,
                            sizeof(struct io_rsrc_node));
        io_alloc_cache_init(&ctx->apoll_cache, IO_ALLOC_CACHE_MAX,
@@ -1336,7 +1339,7 @@ static inline void io_req_local_work_add(struct io_kiocb *req, unsigned flags)
                nr_tw = nr_tw_prev + 1;
                /* Large enough to fail the nr_wait comparison below */
                if (!(flags & IOU_F_TWQ_LAZY_WAKE))
-                       nr_tw = -1U;
+                       nr_tw = INT_MAX;
 
                req->nr_tw = nr_tw;
                req->io_task_work.node.next = first;
@@ -1888,7 +1891,11 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
                        io_req_complete_defer(req);
                else
                        io_req_complete_post(req, issue_flags);
-       } else if (ret != IOU_ISSUE_SKIP_COMPLETE)
+
+               return 0;
+       }
+
+       if (ret != IOU_ISSUE_SKIP_COMPLETE)
                return ret;
 
        /* If the op doesn't have a file, we're not polling for it */
@@ -2623,8 +2630,6 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
                __set_current_state(TASK_RUNNING);
                atomic_set(&ctx->cq_wait_nr, 0);
 
-               if (ret < 0)
-                       break;
                /*
                 * Run task_work after scheduling and before io_should_wake().
                 * If we got woken because of task_work being processed, run it
@@ -2634,6 +2639,18 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
                if (!llist_empty(&ctx->work_llist))
                        io_run_local_work(ctx);
 
+               /*
+                * Non-local task_work will be run on exit to userspace, but
+                * if we're using DEFER_TASKRUN, then we could have waited
+                * with a timeout for a number of requests. If the timeout
+                * hits, we could have some requests ready to process. Ensure
+                * this break is _after_ we have run task_work, to avoid
+                * deferring running potentially pending requests until the
+                * next time we wait for events.
+                */
+               if (ret < 0)
+                       break;
+
                check_cq = READ_ONCE(ctx->check_cq);
                if (unlikely(check_cq)) {
                        /* let the caller flush overflows, retry */
@@ -2659,7 +2676,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
        return READ_ONCE(rings->cq.head) == READ_ONCE(rings->cq.tail) ? ret : 0;
 }
 
-static void io_mem_free(void *ptr)
+void io_mem_free(void *ptr)
 {
        if (!ptr)
                return;
@@ -2771,7 +2788,7 @@ static void io_rings_free(struct io_ring_ctx *ctx)
        }
 }
 
-static void *io_mem_alloc(size_t size)
+void *io_mem_alloc(size_t size)
 {
        gfp_t gfp = GFP_KERNEL_ACCOUNT | __GFP_ZERO | __GFP_NOWARN | __GFP_COMP;
        void *ret;
@@ -2942,6 +2959,7 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
                ctx->mm_account = NULL;
        }
        io_rings_free(ctx);
+       io_kbuf_mmap_list_free(ctx);
 
        percpu_ref_exit(&ctx->refs);
        free_uid(ctx->user);
@@ -3136,12 +3154,7 @@ static __cold void io_ring_exit_work(struct work_struct *work)
        init_completion(&exit.completion);
        init_task_work(&exit.task_work, io_tctx_exit_cb);
        exit.ctx = ctx;
-       /*
-        * Some may use context even when all refs and requests have been put,
-        * and they are free to do so while still holding uring_lock or
-        * completion_lock, see io_req_task_submit(). Apart from other work,
-        * this lock/unlock section also waits them to finish.
-        */
+
        mutex_lock(&ctx->uring_lock);
        while (!list_empty(&ctx->tctx_list)) {
                WARN_ON_ONCE(time_after(jiffies, timeout));
@@ -3436,16 +3449,18 @@ static void *io_uring_validate_mmap_request(struct file *file,
        struct page *page;
        void *ptr;
 
-       /* Don't allow mmap if the ring was setup without it */
-       if (ctx->flags & IORING_SETUP_NO_MMAP)
-               return ERR_PTR(-EINVAL);
-
        switch (offset & IORING_OFF_MMAP_MASK) {
        case IORING_OFF_SQ_RING:
        case IORING_OFF_CQ_RING:
+               /* Don't allow mmap if the ring was setup without it */
+               if (ctx->flags & IORING_SETUP_NO_MMAP)
+                       return ERR_PTR(-EINVAL);
                ptr = ctx->rings;
                break;
        case IORING_OFF_SQES:
+               /* Don't allow mmap if the ring was setup without it */
+               if (ctx->flags & IORING_SETUP_NO_MMAP)
+                       return ERR_PTR(-EINVAL);
                ptr = ctx->sq_sqes;
                break;
        case IORING_OFF_PBUF_RING: {
@@ -3606,7 +3621,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                size_t, argsz)
 {
        struct io_ring_ctx *ctx;
-       struct fd f;
+       struct file *file;
        long ret;
 
        if (unlikely(flags & ~(IORING_ENTER_GETEVENTS | IORING_ENTER_SQ_WAKEUP |
@@ -3624,20 +3639,19 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                if (unlikely(!tctx || fd >= IO_RINGFD_REG_MAX))
                        return -EINVAL;
                fd = array_index_nospec(fd, IO_RINGFD_REG_MAX);
-               f.file = tctx->registered_rings[fd];
-               f.flags = 0;
-               if (unlikely(!f.file))
+               file = tctx->registered_rings[fd];
+               if (unlikely(!file))
                        return -EBADF;
        } else {
-               f = fdget(fd);
-               if (unlikely(!f.file))
+               file = fget(fd);
+               if (unlikely(!file))
                        return -EBADF;
                ret = -EOPNOTSUPP;
-               if (unlikely(!io_is_uring_fops(f.file)))
+               if (unlikely(!io_is_uring_fops(file)))
                        goto out;
        }
 
-       ctx = f.file->private_data;
+       ctx = file->private_data;
        ret = -EBADFD;
        if (unlikely(ctx->flags & IORING_SETUP_R_DISABLED))
                goto out;
@@ -3731,7 +3745,8 @@ iopoll_locked:
                }
        }
 out:
-       fdput(f);
+       if (!(flags & IORING_ENTER_REGISTERED_RING))
+               fput(file);
        return ret;
 }
 
@@ -4572,7 +4587,7 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode,
 {
        struct io_ring_ctx *ctx;
        long ret = -EBADF;
-       struct fd f;
+       struct file *file;
        bool use_registered_ring;
 
        use_registered_ring = !!(opcode & IORING_REGISTER_USE_REGISTERED_RING);
@@ -4591,27 +4606,27 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode,
                if (unlikely(!tctx || fd >= IO_RINGFD_REG_MAX))
                        return -EINVAL;
                fd = array_index_nospec(fd, IO_RINGFD_REG_MAX);
-               f.file = tctx->registered_rings[fd];
-               f.flags = 0;
-               if (unlikely(!f.file))
+               file = tctx->registered_rings[fd];
+               if (unlikely(!file))
                        return -EBADF;
        } else {
-               f = fdget(fd);
-               if (unlikely(!f.file))
+               file = fget(fd);
+               if (unlikely(!file))
                        return -EBADF;
                ret = -EOPNOTSUPP;
-               if (!io_is_uring_fops(f.file))
+               if (!io_is_uring_fops(file))
                        goto out_fput;
        }
 
-       ctx = f.file->private_data;
+       ctx = file->private_data;
 
        mutex_lock(&ctx->uring_lock);
        ret = __io_uring_register(ctx, opcode, arg, nr_args);
        mutex_unlock(&ctx->uring_lock);
        trace_io_uring_register(ctx, opcode, ctx->nr_user_files, ctx->nr_user_bufs, ret);
 out_fput:
-       fdput(f);
+       if (!use_registered_ring)
+               fput(file);
        return ret;
 }