[PATCH v2 2/3] blk-mq: introduce async mechanism for quiesce queue

Chao Leng lengchao at huawei.com
Fri Aug 7 05:06:30 EDT 2020


In some scenarios we need quiesce lots of queues together, if quiesce
one by one, may need long time.
Introduce async mechanism for quiesce queue: quiesce queues together
but no wait, and then wait until all queues ongoing dispatches complete.
Thus reduce serial wait time.

Signed-off-by: Chao Leng <lengchao at huawei.com>
---
 block/blk-mq.c         | 28 ++++++++++++++++++++++++++++
 include/linux/blk-mq.h |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index a9aa6d1e44cf..2fc2fd666bda 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -235,6 +235,34 @@ void blk_mq_quiesce_queue(struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
 
+/*
+ * blk_mq_quiesce_queue_async - do not wait until all ongoing dispatches
+ * completed, used for sync lots of queues together to reduce wait time.
+ * Must be used together with blk_mq_quiesce_queue_async_wait.
+ * Caution: do not support concurrent.
+ */
+void blk_mq_quiesce_queue_async(struct request_queue *q, atomic_t *count)
+{
+	struct blk_mq_hw_ctx *hctx;
+	unsigned int i;
+
+	blk_mq_quiesce_queue_nowait(q);
+	queue_for_each_hw_ctx(q, hctx, i) {
+		if (hctx->flags & BLK_MQ_F_BLOCKING)
+			synchronize_srcu_async(hctx->srcu, count);
+	}
+
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_async);
+
+void blk_mq_quiesce_queue_async_wait(atomic_t *count)
+{
+	synchronize_rcu();
+	while (atomic_read(count))
+		schedule();
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_async_wait);
+
 /*
  * blk_mq_unquiesce_queue() - counterpart of blk_mq_quiesce_queue()
  * @q: request queue.
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index d6fcae17da5a..27a713ad73bb 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -515,6 +515,8 @@ void blk_mq_start_hw_queues(struct request_queue *q);
 void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
 void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
 void blk_mq_quiesce_queue(struct request_queue *q);
+void blk_mq_quiesce_queue_async(struct request_queue *q, atomic_t *count);
+void blk_mq_quiesce_queue_async_wait(atomic_t *count);
 void blk_mq_unquiesce_queue(struct request_queue *q);
 void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
 void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
-- 
2.16.4




More information about the Linux-nvme mailing list