All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/3] reduce CPU usage on exit for IOPOLL
@ 2020-07-07 13:36 Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 1/3] io_uring: partially inline io_iopoll_getevents() Pavel Begunkov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Pavel Begunkov @ 2020-07-07 13:36 UTC (permalink / raw)
  To: Jens Axboe, io-uring

[1,2] are small preps for the future that should change
nothing functionally.

[3] helps to reduce CPU usage on exit. We don't care about latency
and CQEs when io_uring is going away, so checking it every HZ/20
should be enough
Please, check the assumptions, because I hope that nobody expects
 ->iopoll() to do real work but not just completing.

Pavel Begunkov (3):
  io_uring: partially inline io_iopoll_getevents()
  io_uring: remove nr_events arg from iopoll_check()
  io_uring: don't burn CPU for iopoll on exit

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

-- 
2.24.0


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

* [PATCH 1/3] io_uring: partially inline io_iopoll_getevents()
  2020-07-07 13:36 [RFC 0/3] reduce CPU usage on exit for IOPOLL Pavel Begunkov
@ 2020-07-07 13:36 ` Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 2/3] io_uring: remove nr_events arg from iopoll_check() Pavel Begunkov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Pavel Begunkov @ 2020-07-07 13:36 UTC (permalink / raw)
  To: Jens Axboe, io-uring

io_iopoll_reap_events() doesn't care about returned valued of
io_iopoll_getevents() and does the same checks for list emptiness
and need_resched(). Just use io_do_iopoll().

io_sq_thread() doesn't check return value as well. It also passes min=0,
so there never be the second iteration inside io_poll_getevents().
Inline it there too.

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

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 54756ae94bcd..db8dd2cdd2cb 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2057,7 +2057,7 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
 	while (!list_empty(&ctx->poll_list)) {
 		unsigned int nr_events = 0;
 
-		io_iopoll_getevents(ctx, &nr_events, 1);
+		io_do_iopoll(ctx, &nr_events, 1);
 
 		/*
 		 * Ensure we allow local-to-the-cpu processing to take place,
@@ -6311,8 +6311,8 @@ static int io_sq_thread(void *data)
 			unsigned nr_events = 0;
 
 			mutex_lock(&ctx->uring_lock);
-			if (!list_empty(&ctx->poll_list))
-				io_iopoll_getevents(ctx, &nr_events, 0);
+			if (!list_empty(&ctx->poll_list) && !need_resched())
+				io_do_iopoll(ctx, &nr_events, 0);
 			else
 				timeout = jiffies + ctx->sq_thread_idle;
 			mutex_unlock(&ctx->uring_lock);
-- 
2.24.0


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

* [PATCH 2/3] io_uring: remove nr_events arg from iopoll_check()
  2020-07-07 13:36 [RFC 0/3] reduce CPU usage on exit for IOPOLL Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 1/3] io_uring: partially inline io_iopoll_getevents() Pavel Begunkov
@ 2020-07-07 13:36 ` Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 3/3] io_uring: don't burn CPU for iopoll on exit Pavel Begunkov
  2020-07-07 19:00 ` [RFC 0/3] reduce CPU usage on exit for IOPOLL Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Pavel Begunkov @ 2020-07-07 13:36 UTC (permalink / raw)
  To: Jens Axboe, io-uring

Nobody checks io_iopoll_check()'s output parameter @nr_events.
Remove the parameter and declare it further down the stack.

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

diff --git a/fs/io_uring.c b/fs/io_uring.c
index db8dd2cdd2cb..9c3f9ccb850d 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2073,9 +2073,9 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
 	mutex_unlock(&ctx->uring_lock);
 }
 
-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-			   long min)
+static int io_iopoll_check(struct io_ring_ctx *ctx, long min)
 {
+	unsigned int nr_events = 0;
 	int iters = 0, ret = 0;
 
 	/*
@@ -2109,11 +2109,11 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
 			mutex_lock(&ctx->uring_lock);
 		}
 
-		ret = io_iopoll_getevents(ctx, nr_events, min);
+		ret = io_iopoll_getevents(ctx, &nr_events, min);
 		if (ret <= 0)
 			break;
 		ret = 0;
-	} while (min && !*nr_events && !need_resched());
+	} while (min && !nr_events && !need_resched());
 
 	mutex_unlock(&ctx->uring_lock);
 	return ret;
@@ -7963,8 +7963,6 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
 			goto out;
 	}
 	if (flags & IORING_ENTER_GETEVENTS) {
-		unsigned nr_events = 0;
-
 		min_complete = min(min_complete, ctx->cq_entries);
 
 		/*
@@ -7975,7 +7973,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
 		 */
 		if (ctx->flags & IORING_SETUP_IOPOLL &&
 		    !(ctx->flags & IORING_SETUP_SQPOLL)) {
-			ret = io_iopoll_check(ctx, &nr_events, min_complete);
+			ret = io_iopoll_check(ctx, min_complete);
 		} else {
 			ret = io_cqring_wait(ctx, min_complete, sig, sigsz);
 		}
-- 
2.24.0


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

* [PATCH 3/3] io_uring: don't burn CPU for iopoll on exit
  2020-07-07 13:36 [RFC 0/3] reduce CPU usage on exit for IOPOLL Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 1/3] io_uring: partially inline io_iopoll_getevents() Pavel Begunkov
  2020-07-07 13:36 ` [PATCH 2/3] io_uring: remove nr_events arg from iopoll_check() Pavel Begunkov
@ 2020-07-07 13:36 ` Pavel Begunkov
  2020-07-07 19:00 ` [RFC 0/3] reduce CPU usage on exit for IOPOLL Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Pavel Begunkov @ 2020-07-07 13:36 UTC (permalink / raw)
  To: Jens Axboe, io-uring

First of all don't spin in io_ring_ctx_wait_and_kill() on iopoll.
Requests won't complete faster because of that, but only lengthen
io_uring_release().

The same goes for offloaded cleanup in io_ring_exit_work() -- it
already has waiting loop, don't do blocking active spinning.

For that, pass min=0 into io_iopoll_[try_]reap_events(), so it won't
actively spin. Leave the function if io_do_iopoll() there can't
complete a request to sleep in io_ring_exit_work().

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

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 9c3f9ccb850d..bcf6bf799a61 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2048,7 +2048,7 @@ static int io_iopoll_getevents(struct io_ring_ctx *ctx, unsigned int *nr_events,
  * We can't just wait for polled events to come to us, we have to actively
  * find and complete them.
  */
-static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
+static void io_iopoll_try_reap_events(struct io_ring_ctx *ctx)
 {
 	if (!(ctx->flags & IORING_SETUP_IOPOLL))
 		return;
@@ -2057,8 +2057,11 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
 	while (!list_empty(&ctx->poll_list)) {
 		unsigned int nr_events = 0;
 
-		io_do_iopoll(ctx, &nr_events, 1);
+		io_do_iopoll(ctx, &nr_events, 0);
 
+		/* let it sleep and repeat later if can't complete a request */
+		if (nr_events == 0)
+			break;
 		/*
 		 * Ensure we allow local-to-the-cpu processing to take place,
 		 * in this case we need to ensure that we reap all events.
@@ -7634,7 +7637,6 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
 		ctx->sqo_mm = NULL;
 	}
 
-	io_iopoll_reap_events(ctx);
 	io_sqe_buffer_unregister(ctx);
 	io_sqe_files_unregister(ctx);
 	io_eventfd_unregister(ctx);
@@ -7701,11 +7703,8 @@ static int io_remove_personalities(int id, void *p, void *data)
 
 static void io_ring_exit_work(struct work_struct *work)
 {
-	struct io_ring_ctx *ctx;
-
-	ctx = container_of(work, struct io_ring_ctx, exit_work);
-	if (ctx->rings)
-		io_cqring_overflow_flush(ctx, true);
+	struct io_ring_ctx *ctx = container_of(work, struct io_ring_ctx,
+					       exit_work);
 
 	/*
 	 * If we're doing polled IO and end up having requests being
@@ -7713,11 +7712,11 @@ static void io_ring_exit_work(struct work_struct *work)
 	 * we're waiting for refs to drop. We need to reap these manually,
 	 * as nobody else will be looking for them.
 	 */
-	while (!wait_for_completion_timeout(&ctx->ref_comp, HZ/20)) {
-		io_iopoll_reap_events(ctx);
+	do {
 		if (ctx->rings)
 			io_cqring_overflow_flush(ctx, true);
-	}
+		io_iopoll_try_reap_events(ctx);
+	} while (!wait_for_completion_timeout(&ctx->ref_comp, HZ/20));
 	io_ring_ctx_free(ctx);
 }
 
@@ -7733,10 +7732,10 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
 	if (ctx->io_wq)
 		io_wq_cancel_all(ctx->io_wq);
 
-	io_iopoll_reap_events(ctx);
 	/* if we failed setting up the ctx, we might not have any rings */
 	if (ctx->rings)
 		io_cqring_overflow_flush(ctx, true);
+	io_iopoll_try_reap_events(ctx);
 	idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
 	INIT_WORK(&ctx->exit_work, io_ring_exit_work);
 	queue_work(system_wq, &ctx->exit_work);
-- 
2.24.0


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

* Re: [RFC 0/3] reduce CPU usage on exit for IOPOLL
  2020-07-07 13:36 [RFC 0/3] reduce CPU usage on exit for IOPOLL Pavel Begunkov
                   ` (2 preceding siblings ...)
  2020-07-07 13:36 ` [PATCH 3/3] io_uring: don't burn CPU for iopoll on exit Pavel Begunkov
@ 2020-07-07 19:00 ` Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Jens Axboe @ 2020-07-07 19:00 UTC (permalink / raw)
  To: Pavel Begunkov, io-uring

On 7/7/20 7:36 AM, Pavel Begunkov wrote:
> [1,2] are small preps for the future that should change
> nothing functionally.
> 
> [3] helps to reduce CPU usage on exit. We don't care about latency
> and CQEs when io_uring is going away, so checking it every HZ/20
> should be enough
> Please, check the assumptions, because I hope that nobody expects
>  ->iopoll() to do real work but not just completing.

I think it's fine to do it in 1/20th second intervals, if you exit
with pending poll requests.

Hence it looks good to me, I've applied it.

-- 
Jens Axboe


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

end of thread, other threads:[~2020-07-07 19:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-07 13:36 [RFC 0/3] reduce CPU usage on exit for IOPOLL Pavel Begunkov
2020-07-07 13:36 ` [PATCH 1/3] io_uring: partially inline io_iopoll_getevents() Pavel Begunkov
2020-07-07 13:36 ` [PATCH 2/3] io_uring: remove nr_events arg from iopoll_check() Pavel Begunkov
2020-07-07 13:36 ` [PATCH 3/3] io_uring: don't burn CPU for iopoll on exit Pavel Begunkov
2020-07-07 19:00 ` [RFC 0/3] reduce CPU usage on exit for IOPOLL Jens Axboe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.