io_uring: remove struct io_tw_state::locked
authorPavel Begunkov <asml.silence@gmail.com>
Mon, 18 Mar 2024 22:00:30 +0000 (22:00 +0000)
committerJens Axboe <axboe@kernel.dk>
Mon, 15 Apr 2024 14:10:24 +0000 (08:10 -0600)
ctx is always locked for task_work now, so get rid of struct
io_tw_state::locked. Note I'm stopping one step before removing
io_tw_state altogether, which is not empty, because it still serves the
purpose of indicating which function is a tw callback and forcing users
not to invoke them carelessly out of a wrong context. The removal can
always be done later.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Tested-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/e95e1ea116d0bfa54b656076e6a977bc221392a4.1710799188.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/io_uring_types.h
io_uring/io_uring.c
io_uring/io_uring.h
io_uring/poll.c
io_uring/rw.c
io_uring/timeout.c
io_uring/uring_cmd.c
io_uring/waitid.c

index ac333ea81d319526d5fde59bf9f64b5510f94e41..90e5af401800849b06324a759d86e042f6d7b858 100644 (file)
@@ -438,8 +438,6 @@ struct io_ring_ctx {
 };
 
 struct io_tw_state {
-       /* ->uring_lock is taken, callbacks can use io_tw_lock to lock it */
-       bool locked;
 };
 
 enum {
index 13fb5958454fc5a71dc1152a820200cf90afae67..ecb59bb2418b7c5aaeb4a17a683726ece068d79e 100644 (file)
@@ -247,14 +247,12 @@ static __cold void io_fallback_req_func(struct work_struct *work)
                                                fallback_work.work);
        struct llist_node *node = llist_del_all(&ctx->fallback_llist);
        struct io_kiocb *req, *tmp;
-       struct io_tw_state ts = { .locked = true, };
+       struct io_tw_state ts = {};
 
        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);
-       if (WARN_ON_ONCE(!ts.locked))
-               return;
        io_submit_flush_completions(ctx);
        mutex_unlock(&ctx->uring_lock);
        percpu_ref_put(&ctx->refs);
@@ -1157,11 +1155,9 @@ static void ctx_flush_and_put(struct io_ring_ctx *ctx, struct io_tw_state *ts)
                return;
        if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
                atomic_andnot(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
-       if (ts->locked) {
-               io_submit_flush_completions(ctx);
-               mutex_unlock(&ctx->uring_lock);
-               ts->locked = false;
-       }
+
+       io_submit_flush_completions(ctx);
+       mutex_unlock(&ctx->uring_lock);
        percpu_ref_put(&ctx->refs);
 }
 
@@ -1185,8 +1181,6 @@ struct llist_node *io_handle_tw_list(struct llist_node *node,
                if (req->ctx != ctx) {
                        ctx_flush_and_put(ctx, &ts);
                        ctx = req->ctx;
-
-                       ts.locked = true;
                        mutex_lock(&ctx->uring_lock);
                        percpu_ref_get(&ctx->refs);
                }
@@ -1459,22 +1453,16 @@ again:
 static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
                                           int min_events)
 {
-       struct io_tw_state ts = { .locked = true, };
-       int ret;
+       struct io_tw_state ts = {};
 
        if (llist_empty(&ctx->work_llist))
                return 0;
-
-       ret = __io_run_local_work(ctx, &ts, min_events);
-       /* shouldn't happen! */
-       if (WARN_ON_ONCE(!ts.locked))
-               mutex_lock(&ctx->uring_lock);
-       return ret;
+       return __io_run_local_work(ctx, &ts, min_events);
 }
 
 static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
 {
-       struct io_tw_state ts = { .locked = true };
+       struct io_tw_state ts = {};
        int ret;
 
        mutex_lock(&ctx->uring_lock);
@@ -1702,10 +1690,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, long min)
 
 void io_req_task_complete(struct io_kiocb *req, struct io_tw_state *ts)
 {
-       if (ts->locked)
-               io_req_complete_defer(req);
-       else
-               io_req_complete_post(req, IO_URING_F_UNLOCKED);
+       io_req_complete_defer(req);
 }
 
 /*
index 0861d49e83de031035a7ffd9dc46a93fb7001139..7f921daae9c39b00cfd6b2f7856385d8869e32fe 100644 (file)
@@ -351,10 +351,7 @@ static inline bool io_task_work_pending(struct io_ring_ctx *ctx)
 
 static inline void io_tw_lock(struct io_ring_ctx *ctx, struct io_tw_state *ts)
 {
-       if (!ts->locked) {
-               mutex_lock(&ctx->uring_lock);
-               ts->locked = true;
-       }
+       lockdep_assert_held(&ctx->uring_lock);
 }
 
 /*
index 6db1dcb2c7977662dc62127803d6bd1ef5d0b517..8901dd118e500cda6d502a5cfd32ecdcab5ac5a3 100644 (file)
@@ -322,7 +322,7 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts)
                        __poll_t mask = mangle_poll(req->cqe.res &
                                                    req->apoll_events);
 
-                       if (!io_fill_cqe_req_aux(req, ts->locked, mask,
+                       if (!io_fill_cqe_req_aux(req, true, mask,
                                                 IORING_CQE_F_MORE)) {
                                io_req_set_res(req, mask, 0);
                                return IOU_POLL_REMOVE_POLL_USE_RES;
index 0afe4f9e0e3f7a5e7fa82ea2e764dfd1afea32f6..674581bda8d74de64899841e24650dfa192bdabf 100644 (file)
@@ -305,11 +305,9 @@ void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts)
 
        io_req_io_end(req);
 
-       if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)) {
-               unsigned issue_flags = ts->locked ? 0 : IO_URING_F_UNLOCKED;
+       if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING))
+               req->cqe.flags |= io_put_kbuf(req, 0);
 
-               req->cqe.flags |= io_put_kbuf(req, issue_flags);
-       }
        io_req_task_complete(req, ts);
 }
 
index 7fd7dbb211d64295072782b8840e6de77ef6c9be..0a48e6acd0b213accc53ae78bdcd651459ae1c55 100644 (file)
@@ -72,10 +72,7 @@ static void io_timeout_complete(struct io_kiocb *req, struct io_tw_state *ts)
        struct io_ring_ctx *ctx = req->ctx;
 
        if (!io_timeout_finish(timeout, data)) {
-               bool filled;
-               filled = io_fill_cqe_req_aux(req, ts->locked, -ETIME,
-                                            IORING_CQE_F_MORE);
-               if (filled) {
+               if (io_fill_cqe_req_aux(req, true, -ETIME, IORING_CQE_F_MORE)) {
                        /* re-arm timer */
                        spin_lock_irq(&ctx->timeout_lock);
                        list_add(&timeout->list, ctx->timeout_list.prev);
@@ -301,7 +298,6 @@ int io_timeout_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd)
 
 static void io_req_task_link_timeout(struct io_kiocb *req, struct io_tw_state *ts)
 {
-       unsigned issue_flags = ts->locked ? 0 : IO_URING_F_UNLOCKED;
        struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
        struct io_kiocb *prev = timeout->prev;
        int ret = -ENOENT;
@@ -313,7 +309,7 @@ static void io_req_task_link_timeout(struct io_kiocb *req, struct io_tw_state *t
                                .data           = prev->cqe.user_data,
                        };
 
-                       ret = io_try_cancel(req->task->io_uring, &cd, issue_flags);
+                       ret = io_try_cancel(req->task->io_uring, &cd, 0);
                }
                io_req_set_res(req, ret ?: -ETIME, 0);
                io_req_task_complete(req, ts);
index 759f919b14a9905852c045a8fd709123ea4dec8a..4614ce734fee0684828edc03d7484d3a33ff0556 100644 (file)
@@ -87,13 +87,9 @@ EXPORT_SYMBOL_GPL(io_uring_cmd_mark_cancelable);
 static void io_uring_cmd_work(struct io_kiocb *req, struct io_tw_state *ts)
 {
        struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
-       unsigned issue_flags = IO_URING_F_UNLOCKED;
 
-       /* locked task_work executor checks the deffered list completion */
-       if (ts->locked)
-               issue_flags = IO_URING_F_COMPLETE_DEFER;
-
-       ioucmd->task_work_cb(ioucmd, issue_flags);
+       /* task_work executor checks the deffered list completion */
+       ioucmd->task_work_cb(ioucmd, IO_URING_F_COMPLETE_DEFER);
 }
 
 void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
index 77d340666cb95b61a98ccd4717e033f35ec2f9f8..6362ec20abc0cf022a12ac7a83a8dd8bb073804f 100644 (file)
@@ -118,7 +118,7 @@ static int io_waitid_finish(struct io_kiocb *req, int ret)
 static void io_waitid_complete(struct io_kiocb *req, int ret)
 {
        struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid);
-       struct io_tw_state ts = { .locked = true };
+       struct io_tw_state ts = {};
 
        /* anyone completing better be holding a reference */
        WARN_ON_ONCE(!(atomic_read(&iw->refs) & IO_WAITID_REF_MASK));