Skip to content

Commit

Permalink
io_uring: fix sequence logic for timeout requests
Browse files Browse the repository at this point in the history
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 <yangerkun@huawei.com>
Reviewed-by: Jackie Liu <liuyun01@kylinos.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Jens Axboe committed Oct 11, 2019
1 parent 8624881 commit 7adf4ea
Showing 1 changed file with 20 additions and 17 deletions.
37 changes: 20 additions & 17 deletions fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,42 +415,45 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
return ctx;
}

static inline bool __io_sequence_defer(struct io_ring_ctx *ctx,
struct io_kiocb *req)
{
return req->sequence != ctx->cached_cq_tail + ctx->rings->sq_dropped;
}

static inline bool io_sequence_defer(struct io_ring_ctx *ctx,
struct io_kiocb *req)
{
/* timeout requests always honor sequence */
if (!(req->flags & REQ_F_TIMEOUT) &&
(req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
if ((req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
return false;

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

static struct io_kiocb *__io_get_deferred_req(struct io_ring_ctx *ctx,
struct list_head *list)
static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
{
struct io_kiocb *req;

if (list_empty(list))
return NULL;

req = list_first_entry(list, struct io_kiocb, list);
if (!io_sequence_defer(ctx, req)) {
req = list_first_entry_or_null(&ctx->defer_list, struct io_kiocb, list);
if (req && !io_sequence_defer(ctx, req)) {
list_del_init(&req->list);
return req;
}

return NULL;
}

static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
{
return __io_get_deferred_req(ctx, &ctx->defer_list);
}

static struct io_kiocb *io_get_timeout_req(struct io_ring_ctx *ctx)
{
return __io_get_deferred_req(ctx, &ctx->timeout_list);
struct io_kiocb *req;

req = list_first_entry_or_null(&ctx->timeout_list, struct io_kiocb, list);
if (req && !__io_sequence_defer(ctx, req)) {
list_del_init(&req->list);
return req;
}

return NULL;
}

static void __io_commit_cqring(struct io_ring_ctx *ctx)
Expand Down

0 comments on commit 7adf4ea

Please sign in to comment.