Add .mq_quiesce_mutext to request queue, so that queue quiesce and unquiesce can be serialized. Meantime we can avoid unnecessary synchronize_rcu() in case that queue has been quiesced already. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> Cc: Sagi Grimberg <sagi@xxxxxxxxxxx> Cc: Bart Van Assche <bvanassche@xxxxxxx> Cc: Johannes Thumshirn <Johannes.Thumshirn@xxxxxxx> Cc: Chao Leng <lengchao@xxxxxxxxxx> --- block/blk-core.c | 2 ++ block/blk-mq.c | 11 +++++++++++ include/linux/blkdev.h | 2 ++ 3 files changed, 15 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index d9d632639bd1..ffc57df70064 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -561,6 +561,8 @@ struct request_queue *blk_alloc_queue(int node_id) init_waitqueue_head(&q->mq_freeze_wq); mutex_init(&q->mq_freeze_lock); + mutex_init(&q->mq_quiesce_lock); + /* * Init percpu_ref in atomic mode so that it's faster to shutdown. * See blk_register_queue() for details. diff --git a/block/blk-mq.c b/block/blk-mq.c index b3d2785eefe9..817e016ef886 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -224,6 +224,11 @@ void blk_mq_quiesce_queue(struct request_queue *q) unsigned int i; bool rcu = false; + mutex_lock(&q->mq_quiesce_lock); + + if (blk_queue_quiesced(q)) + goto exit; + blk_mq_quiesce_queue_nowait(q); queue_for_each_hw_ctx(q, hctx, i) { @@ -234,6 +239,8 @@ void blk_mq_quiesce_queue(struct request_queue *q) } if (rcu) synchronize_rcu(); + exit: + mutex_unlock(&q->mq_quiesce_lock); } EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue); @@ -246,10 +253,14 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue); */ void blk_mq_unquiesce_queue(struct request_queue *q) { + mutex_lock(&q->mq_quiesce_lock); + blk_queue_flag_clear(QUEUE_FLAG_QUIESCED, q); /* dispatch requests which are inserted during quiescing */ blk_mq_run_hw_queues(q, true); + + mutex_unlock(&q->mq_quiesce_lock); } EXPORT_SYMBOL_GPL(blk_mq_unquiesce_queue); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d8dba550ecac..5ed03066b33e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -569,6 +569,8 @@ struct request_queue { */ struct mutex mq_freeze_lock; + struct mutex mq_quiesce_lock; + struct blk_mq_tag_set *tag_set; struct list_head tag_set_list; struct bio_set bio_split; -- 2.25.2