drm/i915: Refactor setting dma info to a common helper
[linux-2.6-microblaze.git] / fs / io_uring.c
index 08f5204..5190bfb 100644 (file)
@@ -326,6 +326,8 @@ struct io_ring_ctx {
                spinlock_t              inflight_lock;
                struct list_head        inflight_list;
        } ____cacheline_aligned_in_smp;
+
+       struct work_struct              exit_work;
 };
 
 /*
@@ -608,6 +610,7 @@ struct io_kiocb {
        };
 
        struct io_async_ctx             *io;
+       int                             cflags;
        bool                            needs_fixed_file;
        u8                              opcode;
 
@@ -638,7 +641,6 @@ struct io_kiocb {
                        struct callback_head    task_work;
                        struct hlist_node       hash_node;
                        struct async_poll       *apoll;
-                       int                     cflags;
                };
                struct io_wq_work       work;
        };
@@ -1293,8 +1295,8 @@ static struct io_kiocb *io_get_fallback_req(struct io_ring_ctx *ctx)
        return NULL;
 }
 
-static struct io_kiocb *io_get_req(struct io_ring_ctx *ctx,
-                                  struct io_submit_state *state)
+static struct io_kiocb *io_alloc_req(struct io_ring_ctx *ctx,
+                                    struct io_submit_state *state)
 {
        gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
        struct io_kiocb *req;
@@ -1327,22 +1329,9 @@ static struct io_kiocb *io_get_req(struct io_ring_ctx *ctx,
                req = state->reqs[state->free_reqs];
        }
 
-got_it:
-       req->io = NULL;
-       req->file = NULL;
-       req->ctx = ctx;
-       req->flags = 0;
-       /* one is dropped after submission, the other at completion */
-       refcount_set(&req->refs, 2);
-       req->task = NULL;
-       req->result = 0;
-       INIT_IO_WORK(&req->work, io_wq_submit_work);
        return req;
 fallback:
-       req = io_get_fallback_req(ctx);
-       if (req)
-               goto got_it;
-       return NULL;
+       return io_get_fallback_req(ctx);
 }
 
 static inline void io_put_file(struct io_kiocb *req, struct file *file,
@@ -1354,14 +1343,6 @@ static inline void io_put_file(struct io_kiocb *req, struct file *file,
                fput(file);
 }
 
-static void __io_req_do_free(struct io_kiocb *req)
-{
-       if (likely(!io_is_fallback_req(req)))
-               kmem_cache_free(req_cachep, req);
-       else
-               clear_bit_unlock(0, (unsigned long *) req->ctx->fallback_req);
-}
-
 static void __io_req_aux_free(struct io_kiocb *req)
 {
        if (req->flags & REQ_F_NEED_CLEANUP)
@@ -1392,7 +1373,10 @@ static void __io_free_req(struct io_kiocb *req)
        }
 
        percpu_ref_put(&req->ctx->refs);
-       __io_req_do_free(req);
+       if (likely(!io_is_fallback_req(req)))
+               kmem_cache_free(req_cachep, req);
+       else
+               clear_bit_unlock(0, (unsigned long *) req->ctx->fallback_req);
 }
 
 struct req_batch {
@@ -2949,7 +2933,7 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        if (sqe->ioprio || sqe->buf_index)
                return -EINVAL;
-       if (sqe->flags & IOSQE_FIXED_FILE)
+       if (req->flags & REQ_F_FIXED_FILE)
                return -EBADF;
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
@@ -2982,7 +2966,7 @@ static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        if (sqe->ioprio || sqe->buf_index)
                return -EINVAL;
-       if (sqe->flags & IOSQE_FIXED_FILE)
+       if (req->flags & REQ_F_FIXED_FILE)
                return -EBADF;
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
@@ -3336,7 +3320,7 @@ static int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        if (sqe->ioprio || sqe->buf_index)
                return -EINVAL;
-       if (sqe->flags & IOSQE_FIXED_FILE)
+       if (req->flags & REQ_F_FIXED_FILE)
                return -EBADF;
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
@@ -3413,7 +3397,7 @@ static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (sqe->ioprio || sqe->off || sqe->addr || sqe->len ||
            sqe->rw_flags || sqe->buf_index)
                return -EINVAL;
-       if (sqe->flags & IOSQE_FIXED_FILE)
+       if (req->flags & REQ_F_FIXED_FILE)
                return -EBADF;
 
        req->close.fd = READ_ONCE(sqe->fd);
@@ -5384,15 +5368,10 @@ static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
 }
 
 static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
-                          const struct io_uring_sqe *sqe)
+                          int fd, unsigned int flags)
 {
-       unsigned flags;
-       int fd;
        bool fixed;
 
-       flags = READ_ONCE(sqe->flags);
-       fd = READ_ONCE(sqe->fd);
-
        if (!io_req_needs_file(req, fd))
                return 0;
 
@@ -5634,7 +5613,7 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 {
        struct io_ring_ctx *ctx = req->ctx;
        unsigned int sqe_flags;
-       int ret, id;
+       int ret, id, fd;
 
        sqe_flags = READ_ONCE(sqe->flags);
 
@@ -5665,7 +5644,8 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                                        IOSQE_ASYNC | IOSQE_FIXED_FILE |
                                        IOSQE_BUFFER_SELECT);
 
-       ret = io_req_set_file(state, req, sqe);
+       fd = READ_ONCE(sqe->fd);
+       ret = io_req_set_file(state, req, fd, sqe_flags);
        if (unlikely(ret)) {
 err_req:
                io_cqring_add_event(req, ret);
@@ -5809,6 +5789,28 @@ static inline void io_consume_sqe(struct io_ring_ctx *ctx)
        ctx->cached_sq_head++;
 }
 
+static void io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+                       const struct io_uring_sqe *sqe)
+{
+       /*
+        * All io need record the previous position, if LINK vs DARIN,
+        * it can be used to mark the position of the first IO in the
+        * link list.
+        */
+       req->sequence = ctx->cached_sq_head;
+       req->opcode = READ_ONCE(sqe->opcode);
+       req->user_data = READ_ONCE(sqe->user_data);
+       req->io = NULL;
+       req->file = NULL;
+       req->ctx = ctx;
+       req->flags = 0;
+       /* one is dropped after submission, the other at completion */
+       refcount_set(&req->refs, 2);
+       req->task = NULL;
+       req->result = 0;
+       INIT_IO_WORK(&req->work, io_wq_submit_work);
+}
+
 static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                          struct file *ring_file, int ring_fd,
                          struct mm_struct **mm, bool async)
@@ -5844,29 +5846,20 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                struct io_kiocb *req;
                int err;
 
-               req = io_get_req(ctx, statep);
+               sqe = io_get_sqe(ctx);
+               if (unlikely(!sqe)) {
+                       io_consume_sqe(ctx);
+                       break;
+               }
+               req = io_alloc_req(ctx, statep);
                if (unlikely(!req)) {
                        if (!submitted)
                                submitted = -EAGAIN;
                        break;
                }
-               sqe = io_get_sqe(ctx);
-               if (!sqe) {
-                       __io_req_do_free(req);
-                       io_consume_sqe(ctx);
-                       break;
-               }
 
-               /*
-                * All io need record the previous position, if LINK vs DARIN,
-                * it can be used to mark the position of the first IO in the
-                * link list.
-                */
-               req->sequence = ctx->cached_sq_head;
-               req->opcode = READ_ONCE(sqe->opcode);
-               req->user_data = READ_ONCE(sqe->user_data);
+               io_init_req(ctx, req, sqe);
                io_consume_sqe(ctx);
-
                /* will complete beyond this point, count as submitted */
                submitted++;
 
@@ -7280,6 +7273,18 @@ static int io_remove_personalities(int id, void *p, void *data)
        return 0;
 }
 
+static void io_ring_exit_work(struct work_struct *work)
+{
+       struct io_ring_ctx *ctx;
+
+       ctx = container_of(work, struct io_ring_ctx, exit_work);
+       if (ctx->rings)
+               io_cqring_overflow_flush(ctx, true);
+
+       wait_for_completion(&ctx->completions[0]);
+       io_ring_ctx_free(ctx);
+}
+
 static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
 {
        mutex_lock(&ctx->uring_lock);
@@ -7307,8 +7312,8 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
        if (ctx->rings)
                io_cqring_overflow_flush(ctx, true);
        idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
-       wait_for_completion(&ctx->completions[0]);
-       io_ring_ctx_free(ctx);
+       INIT_WORK(&ctx->exit_work, io_ring_exit_work);
+       queue_work(system_wq, &ctx->exit_work);
 }
 
 static int io_uring_release(struct inode *inode, struct file *file)