Skip to content

Commit 4899244

Browse files
author
Ming Lei
committed
io_uring: fix task_work cap overshooting
JIRA: https://issues.redhat.com/browse/RHEL-106845 commit 49c5c63 Author: Jens Axboe <[email protected]> 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 <[email protected]> Signed-off-by: Ming Lei <[email protected]>
1 parent 298d94d commit 4899244

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
@@ -1285,6 +1285,8 @@ static int __io_run_local_work_loop(struct llist_node **node,
12851285
struct io_tw_state *ts,
12861286
int events)
12871287
{
1288+
int ret = 0;
1289+
12881290
while (*node) {
12891291
struct llist_node *next = (*node)->next;
12901292
struct io_kiocb *req = container_of(*node, struct io_kiocb,
@@ -1293,27 +1295,27 @@ static int __io_run_local_work_loop(struct llist_node **node,
12931295
io_poll_task_func, io_req_rw_complete,
12941296
req, ts);
12951297
*node = next;
1296-
if (--events <= 0)
1298+
if (++ret >= events)
12971299
break;
12981300
}
12991301

1300-
return events;
1302+
return ret;
13011303
}
13021304

13031305
static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
1304-
int min_events)
1306+
int min_events, int max_events)
13051307
{
13061308
struct llist_node *node;
13071309
unsigned int loops = 0;
1308-
int ret, limit;
1310+
int ret = 0;
13091311

13101312
if (WARN_ON_ONCE(ctx->submitter_task != current))
13111313
return -EEXIST;
13121314
if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
13131315
atomic_andnot(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
1314-
limit = max(IO_LOCAL_TW_DEFAULT_MAX, min_events);
13151316
again:
1316-
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, limit);
1317+
min_events -= ret;
1318+
ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, max_events);
13171319
if (ctx->retry_llist.first)
13181320
goto retry_done;
13191321

@@ -1322,11 +1324,10 @@ static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
13221324
* running the pending items.
13231325
*/
13241326
node = llist_reverse_order(llist_del_all(&ctx->work_llist));
1325-
ret = __io_run_local_work_loop(&node, ts, ret);
1327+
ret += __io_run_local_work_loop(&node, ts, max_events - ret);
13261328
ctx->retry_llist.first = node;
13271329
loops++;
13281330

1329-
ret = limit - ret;
13301331
if (io_run_local_work_continue(ctx, ret, min_events))
13311332
goto again;
13321333
retry_done:
@@ -1345,16 +1346,18 @@ static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
13451346

13461347
if (!io_local_work_pending(ctx))
13471348
return 0;
1348-
return __io_run_local_work(ctx, &ts, min_events);
1349+
return __io_run_local_work(ctx, &ts, min_events,
1350+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
13491351
}
13501352

1351-
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
1353+
static int io_run_local_work(struct io_ring_ctx *ctx, int min_events,
1354+
int max_events)
13521355
{
13531356
struct io_tw_state ts = {};
13541357
int ret;
13551358

13561359
mutex_lock(&ctx->uring_lock);
1357-
ret = __io_run_local_work(ctx, &ts, min_events);
1360+
ret = __io_run_local_work(ctx, &ts, min_events, max_events);
13581361
mutex_unlock(&ctx->uring_lock);
13591362
return ret;
13601363
}
@@ -2362,7 +2365,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
23622365
{
23632366
if (io_local_work_pending(ctx)) {
23642367
__set_current_state(TASK_RUNNING);
2365-
if (io_run_local_work(ctx, INT_MAX) > 0)
2368+
if (io_run_local_work(ctx, INT_MAX, IO_LOCAL_TW_DEFAULT_MAX) > 0)
23662369
return 0;
23672370
}
23682371
if (io_run_task_work() > 0)
@@ -2526,7 +2529,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
25262529
if (!io_allowed_run_tw(ctx))
25272530
return -EEXIST;
25282531
if (io_local_work_pending(ctx))
2529-
io_run_local_work(ctx, min_events);
2532+
io_run_local_work(ctx, min_events,
2533+
max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
25302534
io_run_task_work();
25312535

25322536
if (unlikely(test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)))
@@ -2597,7 +2601,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
25972601
* now rather than let the caller do another wait loop.
25982602
*/
25992603
if (io_local_work_pending(ctx))
2600-
io_run_local_work(ctx, nr_wait);
2604+
io_run_local_work(ctx, nr_wait, nr_wait);
26012605
io_run_task_work();
26022606

26032607
/*
@@ -3109,7 +3113,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
31093113

31103114
if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) &&
31113115
io_allowed_defer_tw_run(ctx))
3112-
ret |= io_run_local_work(ctx, INT_MAX) > 0;
3116+
ret |= io_run_local_work(ctx, INT_MAX, INT_MAX) > 0;
31133117
ret |= io_cancel_defer_files(ctx, tctx, cancel_all);
31143118
mutex_lock(&ctx->uring_lock);
31153119
ret |= io_poll_remove_all(ctx, tctx, cancel_all);

0 commit comments

Comments
 (0)