[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200901150938.597429566@linuxfoundation.org>
Date: Tue, 1 Sep 2020 17:10:37 +0200
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, kernel test robot <rong.a.chen@...el.com>,
Ming Lei <ming.lei@...hat.com>, Christoph Hellwig <hch@....de>,
Bart Van Assche <bvanassche@....org>,
David Jeffery <djeffery@...hat.com>,
Jens Axboe <axboe@...nel.dk>
Subject: [PATCH 4.19 082/125] blk-mq: order adding requests to hctx->dispatch and checking SCHED_RESTART
From: Ming Lei <ming.lei@...hat.com>
commit d7d8535f377e9ba87edbf7fbbd634ac942f3f54f upstream.
SCHED_RESTART code path is relied to re-run queue for dispatch requests
in hctx->dispatch. Meantime the SCHED_RSTART flag is checked when adding
requests to hctx->dispatch.
memory barriers have to be used for ordering the following two pair of OPs:
1) adding requests to hctx->dispatch and checking SCHED_RESTART in
blk_mq_dispatch_rq_list()
2) clearing SCHED_RESTART and checking if there is request in hctx->dispatch
in blk_mq_sched_restart().
Without the added memory barrier, either:
1) blk_mq_sched_restart() may miss requests added to hctx->dispatch meantime
blk_mq_dispatch_rq_list() observes SCHED_RESTART, and not run queue in
dispatch side
or
2) blk_mq_dispatch_rq_list still sees SCHED_RESTART, and not run queue
in dispatch side, meantime checking if there is request in
hctx->dispatch from blk_mq_sched_restart() is missed.
IO hang in ltp/fs_fill test is reported by kernel test robot:
https://lkml.org/lkml/2020/7/26/77
Turns out it is caused by the above out-of-order OPs. And the IO hang
can't be observed any more after applying this patch.
Fixes: bd166ef183c2 ("blk-mq-sched: add framework for MQ capable IO schedulers")
Reported-by: kernel test robot <rong.a.chen@...el.com>
Signed-off-by: Ming Lei <ming.lei@...hat.com>
Reviewed-by: Christoph Hellwig <hch@....de>
Cc: Bart Van Assche <bvanassche@....org>
Cc: Christoph Hellwig <hch@....de>
Cc: David Jeffery <djeffery@...hat.com>
Cc: <stable@...r.kernel.org>
Signed-off-by: Jens Axboe <axboe@...nel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
block/blk-mq-sched.c | 9 +++++++++
block/blk-mq.c | 9 +++++++++
2 files changed, 18 insertions(+)
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -69,6 +69,15 @@ void blk_mq_sched_restart(struct blk_mq_
return;
clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
+ /*
+ * Order clearing SCHED_RESTART and list_empty_careful(&hctx->dispatch)
+ * in blk_mq_run_hw_queue(). Its pair is the barrier in
+ * blk_mq_dispatch_rq_list(). So dispatch code won't see SCHED_RESTART,
+ * meantime new request added to hctx->dispatch is missed to check in
+ * blk_mq_run_hw_queue().
+ */
+ smp_mb();
+
blk_mq_run_hw_queue(hctx, true);
}
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1222,6 +1222,15 @@ bool blk_mq_dispatch_rq_list(struct requ
spin_unlock(&hctx->lock);
/*
+ * Order adding requests to hctx->dispatch and checking
+ * SCHED_RESTART flag. The pair of this smp_mb() is the one
+ * in blk_mq_sched_restart(). Avoid restart code path to
+ * miss the new added requests to hctx->dispatch, meantime
+ * SCHED_RESTART is observed here.
+ */
+ smp_mb();
+
+ /*
* If SCHED_RESTART was set by the caller of this function and
* it is no longer set that means that it was cleared by another
* thread and hence that a queue rerun is needed.
Powered by blists - more mailing lists