diff mbox series

blk-mq: don't count completed flush data request as inflight in case of quiesce

Message ID 20231201085605.577730-1-ming.lei@redhat.com (mailing list archive)
State New, archived
Headers show
Series blk-mq: don't count completed flush data request as inflight in case of quiesce | expand

Commit Message

Ming Lei Dec. 1, 2023, 8:56 a.m. UTC
Request queue quiesce may interrupt flush sequence, and the original request
may have been marked as COMPLETE, but can't get finished because of
queue quiesce.

This way is fine from driver viewpoint, because flush sequence is block
layer concept, and it isn't related with driver.

However, driver(such as dm-rq) can call blk_mq_queue_inflight() to count &
drain inflight requests, then the wait & drain never gets done because
the completed & not-finished flush request is counted as inflight.

Fix this issue by not counting completed flush data request as inflight in
case of quiesce.

Cc: Mike Snitzer <snitzer@kernel.org>
Cc: David Jeffery <djeffery@redhat.com>
Cc: John Pittman <jpittman@redhat.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 block/blk-mq.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Comments

Jens Axboe Dec. 1, 2023, 2:34 p.m. UTC | #1
On Fri, 01 Dec 2023 16:56:05 +0800, Ming Lei wrote:
> Request queue quiesce may interrupt flush sequence, and the original request
> may have been marked as COMPLETE, but can't get finished because of
> queue quiesce.
> 
> This way is fine from driver viewpoint, because flush sequence is block
> layer concept, and it isn't related with driver.
> 
> [...]

Applied, thanks!

[1/1] blk-mq: don't count completed flush data request as inflight in case of quiesce
      commit: 0e4237ae8d159e3d28f3cd83146a46f576ffb586

Best regards,
diff mbox series

Patch

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 900c1be1fee1..ac18f802c027 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1512,14 +1512,26 @@  void blk_mq_delay_kick_requeue_list(struct request_queue *q,
 }
 EXPORT_SYMBOL(blk_mq_delay_kick_requeue_list);
 
+static bool blk_is_flush_data_rq(struct request *rq)
+{
+	return (rq->rq_flags & RQF_FLUSH_SEQ) && !is_flush_rq(rq);
+}
+
 static bool blk_mq_rq_inflight(struct request *rq, void *priv)
 {
 	/*
 	 * If we find a request that isn't idle we know the queue is busy
 	 * as it's checked in the iter.
 	 * Return false to stop the iteration.
+	 *
+	 * In case of queue quiesce, if one flush data request is completed,
+	 * don't count it as inflight given the flush sequence is suspended,
+	 * and the original flush data request is invisible to driver, just
+	 * like other pending requests because of quiesce
 	 */
-	if (blk_mq_request_started(rq)) {
+	if (blk_mq_request_started(rq) && !(blk_queue_quiesced(rq->q) &&
+				blk_is_flush_data_rq(rq) &&
+				blk_mq_request_completed(rq))) {
 		bool *busy = priv;
 
 		*busy = true;