io-uring.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5 for-next] small for-next optimisations
@ 2021-09-08 15:40 Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 1/5] io_uring: kill off ios_left Pavel Begunkov
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

Small optimisations for 5.16, mostly targeting links

Pavel Begunkov (5):
  io_uring: kill off ios_left
  io_uring: inline io_dismantle_req
  io_uring: inline linked part of io_req_find_next
  io_uring: dedup CQE flushing non-empty checks
  io_uring: kill extra wake_up_process in tw add

 fs/io_uring.c | 78 +++++++++++++++++++++++++--------------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

-- 
2.33.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] io_uring: kill off ios_left
  2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
@ 2021-09-08 15:40 ` Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 2/5] io_uring: inline io_dismantle_req Pavel Begunkov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

->ios_left is only used to decide whether to plug or not, kill it to
avoid this extra accounting, just use the initial submission number.
There is no much difference in regards of enabling plugging, where this
one does it in a few more cases, but all major ones should be covered
well.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 fs/io_uring.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index d816c09c88a5..849e1cb9fba4 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -315,6 +315,7 @@ struct io_submit_state {
 	unsigned int		free_reqs;
 
 	bool			plug_started;
+	bool			need_plug;
 
 	/*
 	 * Batch completion logic
@@ -323,8 +324,6 @@ struct io_submit_state {
 	unsigned int		compl_nr;
 	/* inline/task_work completion list, under ->uring_lock */
 	struct list_head	free_list;
-
-	unsigned int		ios_left;
 };
 
 struct io_ring_ctx {
@@ -7032,10 +7031,10 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
 	 * Plug now if we have more than 1 IO left after this, and the target
 	 * is potentially a read/write to block based storage.
 	 */
-	if (!state->plug_started && state->ios_left > 1 &&
-	    io_op_defs[req->opcode].plug) {
+	if (state->need_plug && io_op_defs[req->opcode].plug) {
 		blk_start_plug(&state->plug);
 		state->plug_started = true;
+		state->need_plug = false;
 	}
 
 	if (io_op_defs[req->opcode].needs_file) {
@@ -7044,8 +7043,6 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
 		if (unlikely(!req->file))
 			ret = -EBADF;
 	}
-
-	state->ios_left--;
 	return ret;
 }
 
@@ -7152,7 +7149,7 @@ static void io_submit_state_start(struct io_submit_state *state,
 				  unsigned int max_ios)
 {
 	state->plug_started = false;
-	state->ios_left = max_ios;
+	state->need_plug = max_ios > 2;
 	/* set only head, no need to init link_last in advance */
 	state->link.head = NULL;
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] io_uring: inline io_dismantle_req
  2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 1/5] io_uring: kill off ios_left Pavel Begunkov
@ 2021-09-08 15:40 ` Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 3/5] io_uring: inline linked part of io_req_find_next Pavel Begunkov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

io_dismantle_req() is hot, and not _too_ huge. Inline it, there are 3
call sites, which hopefully will turn into 2 in the future.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 fs/io_uring.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 849e1cb9fba4..1dc21f7ec666 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1959,7 +1959,7 @@ static inline void io_put_file(struct file *file)
 		fput(file);
 }
 
-static void io_dismantle_req(struct io_kiocb *req)
+static inline void io_dismantle_req(struct io_kiocb *req)
 {
 	unsigned int flags = req->flags;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/5] io_uring: inline linked part of io_req_find_next
  2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 1/5] io_uring: kill off ios_left Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 2/5] io_uring: inline io_dismantle_req Pavel Begunkov
@ 2021-09-08 15:40 ` Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 4/5] io_uring: dedup CQE flushing non-empty checks Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 5/5] io_uring: kill extra wake_up_process in tw add Pavel Begunkov
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

Inline part of __io_req_find_next() that returns a request but doesn't
need io_disarm_next(). It's just two places, but makes links a bit
faster.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 fs/io_uring.c | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 1dc21f7ec666..45e9cd1af97a 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2073,40 +2073,39 @@ static bool io_disarm_next(struct io_kiocb *req)
 	return posted;
 }
 
-static struct io_kiocb *__io_req_find_next(struct io_kiocb *req)
+static void __io_req_find_next_prep(struct io_kiocb *req)
+{
+	struct io_ring_ctx *ctx = req->ctx;
+	bool posted;
+
+	spin_lock(&ctx->completion_lock);
+	posted = io_disarm_next(req);
+	if (posted)
+		io_commit_cqring(req->ctx);
+	spin_unlock(&ctx->completion_lock);
+	if (posted)
+		io_cqring_ev_posted(ctx);
+}
+
+static inline struct io_kiocb *io_req_find_next(struct io_kiocb *req)
 {
 	struct io_kiocb *nxt;
 
+	if (likely(!(req->flags & (REQ_F_LINK|REQ_F_HARDLINK))))
+		return NULL;
 	/*
 	 * If LINK is set, we have dependent requests in this chain. If we
 	 * didn't fail this request, queue the first one up, moving any other
 	 * dependencies to the next request. In case of failure, fail the rest
 	 * of the chain.
 	 */
-	if (req->flags & IO_DISARM_MASK) {
-		struct io_ring_ctx *ctx = req->ctx;
-		bool posted;
-
-		spin_lock(&ctx->completion_lock);
-		posted = io_disarm_next(req);
-		if (posted)
-			io_commit_cqring(req->ctx);
-		spin_unlock(&ctx->completion_lock);
-		if (posted)
-			io_cqring_ev_posted(ctx);
-	}
+	if (unlikely(req->flags & IO_DISARM_MASK))
+		__io_req_find_next_prep(req);
 	nxt = req->link;
 	req->link = NULL;
 	return nxt;
 }
 
-static inline struct io_kiocb *io_req_find_next(struct io_kiocb *req)
-{
-	if (likely(!(req->flags & (REQ_F_LINK|REQ_F_HARDLINK))))
-		return NULL;
-	return __io_req_find_next(req);
-}
-
 static void ctx_flush_and_put(struct io_ring_ctx *ctx, bool *locked)
 {
 	if (!ctx)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/5] io_uring: dedup CQE flushing non-empty checks
  2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
                   ` (2 preceding siblings ...)
  2021-09-08 15:40 ` [PATCH 3/5] io_uring: inline linked part of io_req_find_next Pavel Begunkov
@ 2021-09-08 15:40 ` Pavel Begunkov
  2021-09-08 15:40 ` [PATCH 5/5] io_uring: kill extra wake_up_process in tw add Pavel Begunkov
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

We don't do io_submit_flush_completions() when there is no requests
enqueued, and every single caller checks for it. Hide that check into
the function not forgetting about inlining. That will make it much
easier for changing the empty check condition in the future.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 fs/io_uring.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 45e9cd1af97a..3d911f8808bf 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1094,7 +1094,7 @@ static void __io_queue_sqe(struct io_kiocb *req);
 static void io_rsrc_put_work(struct work_struct *work);
 
 static void io_req_task_queue(struct io_kiocb *req);
-static void io_submit_flush_completions(struct io_ring_ctx *ctx);
+static void __io_submit_flush_completions(struct io_ring_ctx *ctx);
 static int io_req_prep_async(struct io_kiocb *req);
 
 static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
@@ -1164,6 +1164,12 @@ static inline void req_ref_get(struct io_kiocb *req)
 	atomic_inc(&req->refs);
 }
 
+static inline void io_submit_flush_completions(struct io_ring_ctx *ctx)
+{
+	if (ctx->submit_state.compl_nr)
+		__io_submit_flush_completions(ctx);
+}
+
 static inline void __io_req_set_refcount(struct io_kiocb *req, int nr)
 {
 	if (!(req->flags & REQ_F_REFCOUNT)) {
@@ -1252,8 +1258,7 @@ static void io_fallback_req_func(struct work_struct *work)
 		req->io_task_work.func(req, &locked);
 
 	if (locked) {
-		if (ctx->submit_state.compl_nr)
-			io_submit_flush_completions(ctx);
+		io_submit_flush_completions(ctx);
 		mutex_unlock(&ctx->uring_lock);
 	}
 	percpu_ref_put(&ctx->refs);
@@ -2111,8 +2116,7 @@ static void ctx_flush_and_put(struct io_ring_ctx *ctx, bool *locked)
 	if (!ctx)
 		return;
 	if (*locked) {
-		if (ctx->submit_state.compl_nr)
-			io_submit_flush_completions(ctx);
+		io_submit_flush_completions(ctx);
 		mutex_unlock(&ctx->uring_lock);
 		*locked = false;
 	}
@@ -2129,7 +2133,7 @@ static void tctx_task_work(struct callback_head *cb)
 	while (1) {
 		struct io_wq_work_node *node;
 
-		if (!tctx->task_list.first && locked && ctx->submit_state.compl_nr)
+		if (!tctx->task_list.first && locked)
 			io_submit_flush_completions(ctx);
 
 		spin_lock_irq(&tctx->task_lock);
@@ -2314,7 +2318,7 @@ static void io_req_free_batch(struct req_batch *rb, struct io_kiocb *req,
 		list_add(&req->inflight_entry, &state->free_list);
 }
 
-static void io_submit_flush_completions(struct io_ring_ctx *ctx)
+static void __io_submit_flush_completions(struct io_ring_ctx *ctx)
 	__must_hold(&ctx->uring_lock)
 {
 	struct io_submit_state *state = &ctx->submit_state;
@@ -7135,8 +7139,7 @@ static void io_submit_state_end(struct io_submit_state *state,
 {
 	if (state->link.head)
 		io_queue_sqe(state->link.head);
-	if (state->compl_nr)
-		io_submit_flush_completions(ctx);
+	io_submit_flush_completions(ctx);
 	if (state->plug_started)
 		blk_finish_plug(&state->plug);
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/5] io_uring: kill extra wake_up_process in tw add
  2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
                   ` (3 preceding siblings ...)
  2021-09-08 15:40 ` [PATCH 4/5] io_uring: dedup CQE flushing non-empty checks Pavel Begunkov
@ 2021-09-08 15:40 ` Pavel Begunkov
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2021-09-08 15:40 UTC (permalink / raw)
  To: Jens Axboe, io-uring

TWA_SIGNAL already wakes the thread, no need in wake_up_process() after
it.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 fs/io_uring.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 3d911f8808bf..9dfc243ade9e 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2196,8 +2196,9 @@ static void io_req_task_work_add(struct io_kiocb *req)
 	 * will do the job.
 	 */
 	notify = (req->ctx->flags & IORING_SETUP_SQPOLL) ? TWA_NONE : TWA_SIGNAL;
-	if (!task_work_add(tsk, &tctx->task_work, notify)) {
-		wake_up_process(tsk);
+	if (likely(!task_work_add(tsk, &tctx->task_work, notify))) {
+		if (notify == TWA_NONE)
+			wake_up_process(tsk);
 		return;
 	}
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-09-08 15:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-08 15:40 [PATCH 0/5 for-next] small for-next optimisations Pavel Begunkov
2021-09-08 15:40 ` [PATCH 1/5] io_uring: kill off ios_left Pavel Begunkov
2021-09-08 15:40 ` [PATCH 2/5] io_uring: inline io_dismantle_req Pavel Begunkov
2021-09-08 15:40 ` [PATCH 3/5] io_uring: inline linked part of io_req_find_next Pavel Begunkov
2021-09-08 15:40 ` [PATCH 4/5] io_uring: dedup CQE flushing non-empty checks Pavel Begunkov
2021-09-08 15:40 ` [PATCH 5/5] io_uring: kill extra wake_up_process in tw add Pavel Begunkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).