Skip to content

Commit 7adf4ea

Browse files
committed
io_uring: fix sequence logic for timeout requests
We have two ways a request can be deferred: 1) It's a regular request that depends on another one 2) It's a timeout that tracks completions We have a shared helper to determine whether to defer, and that attempts to make the right decision based on the request. But we only have some of this information in the caller. Un-share the two timeout/defer helpers so the caller can use the right one. Fixes: 5262f56 ("io_uring: IORING_OP_TIMEOUT support") Reported-by: yangerkun <[email protected]> Reviewed-by: Jackie Liu <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 8624881 commit 7adf4ea

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

fs/io_uring.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -415,42 +415,45 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
415415
return ctx;
416416
}
417417

418+
static inline bool __io_sequence_defer(struct io_ring_ctx *ctx,
419+
struct io_kiocb *req)
420+
{
421+
return req->sequence != ctx->cached_cq_tail + ctx->rings->sq_dropped;
422+
}
423+
418424
static inline bool io_sequence_defer(struct io_ring_ctx *ctx,
419425
struct io_kiocb *req)
420426
{
421-
/* timeout requests always honor sequence */
422-
if (!(req->flags & REQ_F_TIMEOUT) &&
423-
(req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
427+
if ((req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
424428
return false;
425429

426-
return req->sequence != ctx->cached_cq_tail + ctx->rings->sq_dropped;
430+
return __io_sequence_defer(ctx, req);
427431
}
428432

429-
static struct io_kiocb *__io_get_deferred_req(struct io_ring_ctx *ctx,
430-
struct list_head *list)
433+
static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
431434
{
432435
struct io_kiocb *req;
433436

434-
if (list_empty(list))
435-
return NULL;
436-
437-
req = list_first_entry(list, struct io_kiocb, list);
438-
if (!io_sequence_defer(ctx, req)) {
437+
req = list_first_entry_or_null(&ctx->defer_list, struct io_kiocb, list);
438+
if (req && !io_sequence_defer(ctx, req)) {
439439
list_del_init(&req->list);
440440
return req;
441441
}
442442

443443
return NULL;
444444
}
445445

446-
static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
447-
{
448-
return __io_get_deferred_req(ctx, &ctx->defer_list);
449-
}
450-
451446
static struct io_kiocb *io_get_timeout_req(struct io_ring_ctx *ctx)
452447
{
453-
return __io_get_deferred_req(ctx, &ctx->timeout_list);
448+
struct io_kiocb *req;
449+
450+
req = list_first_entry_or_null(&ctx->timeout_list, struct io_kiocb, list);
451+
if (req && !__io_sequence_defer(ctx, req)) {
452+
list_del_init(&req->list);
453+
return req;
454+
}
455+
456+
return NULL;
454457
}
455458

456459
static void __io_commit_cqring(struct io_ring_ctx *ctx)

0 commit comments

Comments
 (0)