Skip to content

Commit b302676

Browse files
Dylan Yudakenaxboe
authored andcommitted
io_uring: unlock if __io_run_local_work locked inside
It is possible for tw to lock the ring, and this was not propogated out to io_run_local_work. This can cause an unlock to be missed. Instead pass a pointer to locked into __io_run_local_work. Fixes: 8ac5d85 ("io_uring: add local task_work run helper that is entered locked") Signed-off-by: Dylan Yudaken <[email protected]> Link: https://lore.kernel.org/r/[email protected] [axboe: WARN_ON() -> WARN_ON_ONCE() and add a minor comment] Signed-off-by: Jens Axboe <[email protected]>
1 parent 8de11cd commit b302676

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

io_uring/io_uring.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ static void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx)
11731173
}
11741174
}
11751175

1176-
int __io_run_local_work(struct io_ring_ctx *ctx, bool locked)
1176+
int __io_run_local_work(struct io_ring_ctx *ctx, bool *locked)
11771177
{
11781178
struct llist_node *node;
11791179
struct llist_node fake;
@@ -1192,7 +1192,7 @@ int __io_run_local_work(struct io_ring_ctx *ctx, bool locked)
11921192
struct io_kiocb *req = container_of(node, struct io_kiocb,
11931193
io_task_work.node);
11941194
prefetch(container_of(next, struct io_kiocb, io_task_work.node));
1195-
req->io_task_work.func(req, &locked);
1195+
req->io_task_work.func(req, locked);
11961196
ret++;
11971197
node = next;
11981198
}
@@ -1208,7 +1208,7 @@ int __io_run_local_work(struct io_ring_ctx *ctx, bool locked)
12081208
goto again;
12091209
}
12101210

1211-
if (locked)
1211+
if (*locked)
12121212
io_submit_flush_completions(ctx);
12131213
trace_io_uring_local_work_run(ctx, ret, loops);
12141214
return ret;
@@ -1225,7 +1225,7 @@ int io_run_local_work(struct io_ring_ctx *ctx)
12251225

12261226
__set_current_state(TASK_RUNNING);
12271227
locked = mutex_trylock(&ctx->uring_lock);
1228-
ret = __io_run_local_work(ctx, locked);
1228+
ret = __io_run_local_work(ctx, &locked);
12291229
if (locked)
12301230
mutex_unlock(&ctx->uring_lock);
12311231

io_uring/io_uring.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ enum {
2727
struct io_uring_cqe *__io_get_cqe(struct io_ring_ctx *ctx, bool overflow);
2828
bool io_req_cqe_overflow(struct io_kiocb *req);
2929
int io_run_task_work_sig(struct io_ring_ctx *ctx);
30-
int __io_run_local_work(struct io_ring_ctx *ctx, bool locked);
30+
int __io_run_local_work(struct io_ring_ctx *ctx, bool *locked);
3131
int io_run_local_work(struct io_ring_ctx *ctx);
3232
void io_req_complete_failed(struct io_kiocb *req, s32 res);
3333
void __io_req_complete(struct io_kiocb *req, unsigned issue_flags);
@@ -277,9 +277,18 @@ static inline int io_run_task_work_ctx(struct io_ring_ctx *ctx)
277277

278278
static inline int io_run_local_work_locked(struct io_ring_ctx *ctx)
279279
{
280+
bool locked;
281+
int ret;
282+
280283
if (llist_empty(&ctx->work_llist))
281284
return 0;
282-
return __io_run_local_work(ctx, true);
285+
286+
locked = true;
287+
ret = __io_run_local_work(ctx, &locked);
288+
/* shouldn't happen! */
289+
if (WARN_ON_ONCE(!locked))
290+
mutex_lock(&ctx->uring_lock);
291+
return ret;
283292
}
284293

285294
static inline void io_tw_lock(struct io_ring_ctx *ctx, bool *locked)

0 commit comments

Comments
 (0)