Skip to content

Commit 49c5c63

Browse files
committed
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>
1 parent 0c0a4ea commit 49c5c63

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
@@ -1277,6 +1277,8 @@ static int __io_run_local_work_loop(struct llist_node **node,
12771277
struct io_tw_state *ts,
12781278
int events)
12791279
{
1280+
int ret = 0;
1281+
12801282
while (*node) {
12811283
struct llist_node *next = (*node)->next;
12821284
struct io_kiocb *req = container_of(*node, struct io_kiocb,
@@ -1285,27 +1287,27 @@ static int __io_run_local_work_loop(struct llist_node **node,
12851287
io_poll_task_func, io_req_rw_complete,
12861288
req, ts);
12871289
*node = next;
1288-
if (--events <= 0)
1290+
if (++ret >= events)
12891291
break;
12901292
}
12911293

1292-
return events;
1294+
return ret;
12931295
}
12941296

12951297
static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
1296-
int min_events)
1298+
int min_events, int max_events)
12971299
{
12981300
struct llist_node *node;
12991301
unsigned int loops = 0;
1300-
int ret, limit;
1302+
int ret = 0;
13011303

13021304
if (WARN_ON_ONCE(ctx->submitter_task != current))
13031305
return -EEXIST;
13041306
if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
13051307
atomic_andnot(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
1306-
limit = max(IO_LOCAL_TW_DEFAULT_MAX, min_events);
13071308
again:
1308-
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, limit);
1309+
min_events -= ret;
1310+
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, max_events);
13091311
if (ctx->retry_llist.first)
13101312
goto retry_done;
13111313

@@ -1314,11 +1316,10 @@ static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
13141316
* running the pending items.
13151317
*/
13161318
node = llist_reverse_order(llist_del_all(&ctx->work_llist));
1317-
ret = __io_run_local_work_loop(&node, ts, ret);
1319+
ret += __io_run_local_work_loop(&node, ts, max_events - ret);
13181320
ctx->retry_llist.first = node;
13191321
loops++;
13201322

1321-
ret = limit - ret;
13221323
if (io_run_local_work_continue(ctx, ret, min_events))
13231324
goto again;
13241325
retry_done:
@@ -1337,16 +1338,18 @@ static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
13371338

13381339
if (!io_local_work_pending(ctx))
13391340
return 0;
1340-
return __io_run_local_work(ctx, &ts, min_events);
1341+
return __io_run_local_work(ctx, &ts, min_events,
1342+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
13411343
}
13421344

1343-
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
1345+
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events,
1346+
int max_events)
13441347
{
13451348
struct io_tw_state ts = {};
13461349
int ret;
13471350

13481351
mutex_lock(&ctx->uring_lock);
1349-
ret = __io_run_local_work(ctx, &ts, min_events);
1352+
ret = __io_run_local_work(ctx, &ts, min_events, max_events);
13501353
mutex_unlock(&ctx->uring_lock);
13511354
return ret;
13521355
}
@@ -2352,7 +2355,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
23522355
{
23532356
if (io_local_work_pending(ctx)) {
23542357
__set_current_state(TASK_RUNNING);
2355-
if (io_run_local_work(ctx, INT_MAX) > 0)
2358+
if (io_run_local_work(ctx, INT_MAX, IO_LOCAL_TW_DEFAULT_MAX) > 0)
23562359
return 0;
23572360
}
23582361
if (io_run_task_work() > 0)
@@ -2515,7 +2518,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
25152518
if (!io_allowed_run_tw(ctx))
25162519
return -EEXIST;
25172520
if (io_local_work_pending(ctx))
2518-
io_run_local_work(ctx, min_events);
2521+
io_run_local_work(ctx, min_events,
2522+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
25192523
io_run_task_work();
25202524

25212525
if (unlikely(test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)))
@@ -2586,7 +2590,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
25862590
* now rather than let the caller do another wait loop.
25872591
*/
25882592
if (io_local_work_pending(ctx))
2589-
io_run_local_work(ctx, nr_wait);
2593+
io_run_local_work(ctx, nr_wait, nr_wait);
25902594
io_run_task_work();
25912595

25922596
/*
@@ -3098,7 +3102,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
30983102

30993103
if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) &&
31003104
io_allowed_defer_tw_run(ctx))
3101-
ret |= io_run_local_work(ctx, INT_MAX) > 0;
3105+
ret |= io_run_local_work(ctx, INT_MAX, INT_MAX) > 0;
31023106
ret |= io_cancel_defer_files(ctx, tctx, cancel_all);
31033107
mutex_lock(&ctx->uring_lock);
31043108
ret |= io_poll_remove_all(ctx, tctx, cancel_all);

0 commit comments

Comments
 (0)