Skip to content

Commit 8bb9d14

Browse files
committed
io_uring: fix task_work cap overshooting
JIRA: https://issues.redhat.com/browse/RHEL-105612 commit 49c5c63 Author: Jens Axboe <axboe@kernel.dk> Date: Tue Nov 26 13:42:27 2024 -0700 io_uring: fix task_work cap overshooting A previous commit fixed task_work overrunning by a lot more than what the user asked for, by adding a retry list. However, it didn't cap the overall count, hence for multiple task_work runs inside the same wait loop, it'd still overshoot the target by potentially a large amount. Cap it generally inside the wait path. Note that this will still overshoot the default limit of 20, but should overshoot by no more than limit-1 in addition to the limit. That still provides a ceiling over how much task_work will be run, rather than still having gaps where it was uncapped essentially. Fixes: f46b9cd ("io_uring: limit local tw done") Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
1 parent 9a8b302 commit 8bb9d14

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

io_uring/io_uring.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,8 @@ static int __io_run_local_work_loop(struct llist_node **node,
12911291
struct io_tw_state *ts,
12921292
int events)
12931293
{
1294+
int ret = 0;
1295+
12941296
while (*node) {
12951297
struct llist_node *next = (*node)->next;
12961298
struct io_kiocb *req = container_of(*node, struct io_kiocb,
@@ -1299,27 +1301,27 @@ static int __io_run_local_work_loop(struct llist_node **node,
12991301
io_poll_task_func, io_req_rw_complete,
13001302
req, ts);
13011303
*node = next;
1302-
if (--events <= 0)
1304+
if (++ret >= events)
13031305
break;
13041306
}
13051307

1306-
return events;
1308+
return ret;
13071309
}
13081310

13091311
static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
1310-
int min_events)
1312+
int min_events, int max_events)
13111313
{
13121314
struct llist_node *node;
13131315
unsigned int loops = 0;
1314-
int ret, limit;
1316+
int ret = 0;
13151317

13161318
if (WARN_ON_ONCE(ctx->submitter_task != current))
13171319
return -EEXIST;
13181320
if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
13191321
atomic_andnot(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
1320-
limit = max(IO_LOCAL_TW_DEFAULT_MAX, min_events);
13211322
again:
1322-
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, limit);
1323+
min_events -= ret;
1324+
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, max_events);
13231325
if (ctx->retry_llist.first)
13241326
goto retry_done;
13251327

@@ -1328,11 +1330,10 @@ static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
13281330
* running the pending items.
13291331
*/
13301332
node = llist_reverse_order(llist_del_all(&ctx->work_llist));
1331-
ret = __io_run_local_work_loop(&node, ts, ret);
1333+
ret += __io_run_local_work_loop(&node, ts, max_events - ret);
13321334
ctx->retry_llist.first = node;
13331335
loops++;
13341336

1335-
ret = limit - ret;
13361337
if (io_run_local_work_continue(ctx, ret, min_events))
13371338
goto again;
13381339
retry_done:
@@ -1351,16 +1352,18 @@ static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
13511352

13521353
if (!io_local_work_pending(ctx))
13531354
return 0;
1354-
return __io_run_local_work(ctx, &ts, min_events);
1355+
return __io_run_local_work(ctx, &ts, min_events,
1356+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
13551357
}
13561358

1357-
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
1359+
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events,
1360+
int max_events)
13581361
{
13591362
struct io_tw_state ts = {};
13601363
int ret;
13611364

13621365
mutex_lock(&ctx->uring_lock);
1363-
ret = __io_run_local_work(ctx, &ts, min_events);
1366+
ret = __io_run_local_work(ctx, &ts, min_events, max_events);
13641367
mutex_unlock(&ctx->uring_lock);
13651368
return ret;
13661369
}
@@ -2368,7 +2371,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
23682371
{
23692372
if (io_local_work_pending(ctx)) {
23702373
__set_current_state(TASK_RUNNING);
2371-
if (io_run_local_work(ctx, INT_MAX) > 0)
2374+
if (io_run_local_work(ctx, INT_MAX, IO_LOCAL_TW_DEFAULT_MAX) > 0)
23722375
return 0;
23732376
}
23742377
if (io_run_task_work() > 0)
@@ -2531,7 +2534,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
25312534
if (!io_allowed_run_tw(ctx))
25322535
return -EEXIST;
25332536
if (io_local_work_pending(ctx))
2534-
io_run_local_work(ctx, min_events);
2537+
io_run_local_work(ctx, min_events,
2538+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
25352539
io_run_task_work();
25362540

25372541
if (unlikely(test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)))
@@ -2602,7 +2606,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
26022606
* now rather than let the caller do another wait loop.
26032607
*/
26042608
if (io_local_work_pending(ctx))
2605-
io_run_local_work(ctx, nr_wait);
2609+
io_run_local_work(ctx, nr_wait, nr_wait);
26062610
io_run_task_work();
26072611

26082612
/*
@@ -3114,7 +3118,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
31143118

31153119
if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) &&
31163120
io_allowed_defer_tw_run(ctx))
3117-
ret |= io_run_local_work(ctx, INT_MAX) > 0;
3121+
ret |= io_run_local_work(ctx, INT_MAX, INT_MAX) > 0;
31183122
ret |= io_cancel_defer_files(ctx, tctx, cancel_all);
31193123
mutex_lock(&ctx->uring_lock);
31203124
ret |= io_poll_remove_all(ctx, tctx, cancel_all);

0 commit comments

Comments
 (0)