Skip to content

Commit ec26c22

Browse files
isilenceaxboe
authored andcommitted
io_uring: merge iopoll and normal completion paths
io_do_iopoll() and io_submit_flush_completions() are pretty similar, both filling CQEs and then free a list of requests. Don't duplicate it and make iopoll use __io_submit_flush_completions(), which also helps with inlining and other optimisations. For that, we need to first find all completed iopoll requests and splice them from the iopoll list and then pass it down. This adds one extra list traversal, which should be fine as requests will stay hot in cache. CQ locking is already conditional, introduce ->lockless_cq and skip locking for IOPOLL as it's protected by ->uring_lock. We also add a wakeup optimisation for IOPOLL to __io_cq_unlock_post(), so it works just like io_cqring_ev_posted_iopoll(). Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/3840473f5e8a960de35b77292026691880f6bdbc.1692916914.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 54927ba commit ec26c22

File tree

4 files changed

+19
-26
lines changed

4 files changed

+19
-26
lines changed

include/linux/io_uring_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ struct io_ring_ctx {
205205
unsigned int has_evfd: 1;
206206
/* all CQEs should be posted only by the submitter task */
207207
unsigned int task_complete: 1;
208+
unsigned int lockless_cq: 1;
208209
unsigned int syscall_iopoll: 1;
209210
unsigned int poll_activated: 1;
210211
unsigned int drain_disabled: 1;

io_uring/io_uring.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ static bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
147147
bool cancel_all);
148148

149149
static void io_queue_sqe(struct io_kiocb *req);
150-
static void __io_submit_flush_completions(struct io_ring_ctx *ctx);
151150

152151
struct kmem_cache *req_cachep;
153152

@@ -616,7 +615,7 @@ void __io_commit_cqring_flush(struct io_ring_ctx *ctx)
616615

617616
static inline void __io_cq_lock(struct io_ring_ctx *ctx)
618617
{
619-
if (!ctx->task_complete)
618+
if (!ctx->lockless_cq)
620619
spin_lock(&ctx->completion_lock);
621620
}
622621

@@ -630,8 +629,11 @@ static inline void __io_cq_unlock_post(struct io_ring_ctx *ctx)
630629
{
631630
io_commit_cqring(ctx);
632631
if (!ctx->task_complete) {
633-
spin_unlock(&ctx->completion_lock);
634-
io_cqring_wake(ctx);
632+
if (!ctx->lockless_cq)
633+
spin_unlock(&ctx->completion_lock);
634+
/* IOPOLL rings only need to wake up if it's also SQPOLL */
635+
if (!ctx->syscall_iopoll)
636+
io_cqring_wake(ctx);
635637
}
636638
io_commit_cqring_flush(ctx);
637639
}
@@ -1485,7 +1487,8 @@ void io_queue_next(struct io_kiocb *req)
14851487
io_req_task_queue(nxt);
14861488
}
14871489

1488-
void io_free_batch_list(struct io_ring_ctx *ctx, struct io_wq_work_node *node)
1490+
static void io_free_batch_list(struct io_ring_ctx *ctx,
1491+
struct io_wq_work_node *node)
14891492
__must_hold(&ctx->uring_lock)
14901493
{
14911494
do {
@@ -1522,7 +1525,7 @@ void io_free_batch_list(struct io_ring_ctx *ctx, struct io_wq_work_node *node)
15221525
} while (node);
15231526
}
15241527

1525-
static void __io_submit_flush_completions(struct io_ring_ctx *ctx)
1528+
void __io_submit_flush_completions(struct io_ring_ctx *ctx)
15261529
__must_hold(&ctx->uring_lock)
15271530
{
15281531
struct io_submit_state *state = &ctx->submit_state;
@@ -3836,6 +3839,9 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
38363839
!(ctx->flags & IORING_SETUP_SQPOLL))
38373840
ctx->task_complete = true;
38383841

3842+
if (ctx->task_complete || (ctx->flags & IORING_SETUP_IOPOLL))
3843+
ctx->lockless_cq = true;
3844+
38393845
/*
38403846
* lazy poll_wq activation relies on ->task_complete for synchronisation
38413847
* purposes, see io_activate_pollwq()

io_uring/io_uring.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file,
7272
int io_poll_issue(struct io_kiocb *req, struct io_tw_state *ts);
7373
int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr);
7474
int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin);
75-
void io_free_batch_list(struct io_ring_ctx *ctx, struct io_wq_work_node *node);
75+
void __io_submit_flush_completions(struct io_ring_ctx *ctx);
7676
int io_req_prep_async(struct io_kiocb *req);
7777

7878
struct io_wq_work *io_wq_free_work(struct io_wq_work *work);

io_uring/rw.c

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -983,13 +983,6 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
983983
return ret;
984984
}
985985

986-
static void io_cqring_ev_posted_iopoll(struct io_ring_ctx *ctx)
987-
{
988-
if (ctx->flags & IORING_SETUP_SQPOLL)
989-
io_cqring_wake(ctx);
990-
io_commit_cqring_flush(ctx);
991-
}
992-
993986
void io_rw_fail(struct io_kiocb *req)
994987
{
995988
int res;
@@ -1060,24 +1053,17 @@ int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin)
10601053
if (!smp_load_acquire(&req->iopoll_completed))
10611054
break;
10621055
nr_events++;
1063-
if (unlikely(req->flags & REQ_F_CQE_SKIP))
1064-
continue;
1065-
10661056
req->cqe.flags = io_put_kbuf(req, 0);
1067-
if (unlikely(!io_fill_cqe_req(ctx, req))) {
1068-
spin_lock(&ctx->completion_lock);
1069-
io_req_cqe_overflow(req);
1070-
spin_unlock(&ctx->completion_lock);
1071-
}
10721057
}
1073-
10741058
if (unlikely(!nr_events))
10751059
return 0;
10761060

1077-
io_commit_cqring(ctx);
1078-
io_cqring_ev_posted_iopoll(ctx);
10791061
pos = start ? start->next : ctx->iopoll_list.first;
10801062
wq_list_cut(&ctx->iopoll_list, prev, start);
1081-
io_free_batch_list(ctx, pos);
1063+
1064+
if (WARN_ON_ONCE(!wq_list_empty(&ctx->submit_state.compl_reqs)))
1065+
return 0;
1066+
ctx->submit_state.compl_reqs.first = pos;
1067+
__io_submit_flush_completions(ctx);
10821068
return nr_events;
10831069
}

0 commit comments

Comments
 (0)