Thread (19 messages) 19 messages, 6 authors, 2020-04-23

Re: [PATCH] block: Limit number of items taken from the I/O scheduler in one go

From: Salman Qazi <hidden>
Date: 2020-02-04 18:26:44
Also in: lkml

On Tue, Feb 4, 2020 at 1:20 AM Ming Lei [off-list ref] wrote:
On Mon, Feb 03, 2020 at 12:59:50PM -0800, Salman Qazi wrote:
quoted
We observed that it is possible for a flush to bypass the I/O
scheduler and get added to hctx->dispatch in blk_mq_sched_bypass_insert.
We always bypass io scheduler for flush request.
quoted
This can happen while a kworker is running blk_mq_do_dispatch_sched call
in blk_mq_sched_dispatch_requests.

However, the blk_mq_do_dispatch_sched call doesn't end in bounded time.
As a result, the flush can sit there indefinitely, as the I/O scheduler
feeds an arbitrary number of requests to the hardware.
blk-mq supposes to handle requests in hctx->dispatch with higher
priority, see blk_mq_sched_dispatch_requests().

However, there is single hctx->run_work, so async run queue for dispatching
flush request can only be run until another async run queue from scheduler
is done.
quoted
The solution is to periodically poll hctx->dispatch in
blk_mq_do_dispatch_sched, to put a bound on the latency of the commands
sitting there.

Signed-off-by: Salman Qazi <redacted>
---
 block/blk-mq-sched.c   |  6 ++++++
 block/blk-mq.c         |  4 ++++
 block/blk-sysfs.c      | 33 +++++++++++++++++++++++++++++++++
 include/linux/blkdev.h |  2 ++
 4 files changed, 45 insertions(+)
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index ca22afd47b3d..75cdec64b9c7 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -90,6 +90,7 @@ static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
      struct request_queue *q = hctx->queue;
      struct elevator_queue *e = q->elevator;
      LIST_HEAD(rq_list);
+     int count = 0;

      do {
              struct request *rq;
@@ -97,6 +98,10 @@ static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
              if (e->type->ops.has_work && !e->type->ops.has_work(hctx))
                      break;

+             if (count > 0 && count % q->max_sched_batch == 0 &&
+                 !list_empty_careful(&hctx->dispatch))
+                     break;
q->max_sched_batch may not be needed, and it is reasonable to always
disaptch requests in hctx->dispatch first.

Also such trick is missed in dispatch from sw queue.
I will update the commit message, drop max_sched_batch and just turn
it into a simple check and add the same
thing to the dispatch from the sw queue.

Thanks,
Ming
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help