From: Di Wang wangdi44@huawei.com
driver inclusion category: bugfix bugzilla: NA Link: https://gitee.com/openeuler/kernel/issues/I1WGZE
--------------------------------
It will cost a lot of time when synchronize_rcu() is called for every namspace in nvme_stop_queues().
Reviewed-by: Chao Leng lengchao@huawei.com Reviewed-by: Jike Cheng chengjike.cheng@huawei.com Signed-off-by: Di Wang wangdi44@huawei.com Signed-off-by: Lijie lijie34@huawei.com Acked-by: Hanjun Guo guohanjun@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- block/blk-mq.c | 18 ++++++++++++++++++ drivers/nvme/host/core.c | 6 +++++- include/linux/blk-mq.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c index 7096f23b18da..41e92dbff821 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -242,6 +242,24 @@ void blk_mq_quiesce_queue(struct request_queue *q) } EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
+bool blk_mq_quiesce_queue_without_rcu(struct request_queue *q) +{ + struct blk_mq_hw_ctx *hctx; + unsigned int i; + bool rcu = false; + + blk_mq_quiesce_queue_nowait(q); + + queue_for_each_hw_ctx(q, hctx, i) { + if (hctx->flags & BLK_MQ_F_BLOCKING) + synchronize_srcu(hctx->srcu); + else + rcu = true; + } + return rcu; +} +EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_without_rcu); + /* * blk_mq_unquiesce_queue() - counterpart of blk_mq_quiesce_queue() * @q: request queue. diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 8443c6c5c5af..c9faa824de26 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3904,11 +3904,15 @@ EXPORT_SYMBOL_GPL(nvme_start_freeze); void nvme_stop_queues(struct nvme_ctrl *ctrl) { struct nvme_ns *ns; + bool rcu = false;
down_read(&ctrl->namespaces_rwsem); list_for_each_entry(ns, &ctrl->namespaces, list) - blk_mq_quiesce_queue(ns->queue); + rcu = (blk_mq_quiesce_queue_without_rcu(ns->queue) || rcu); up_read(&ctrl->namespaces_rwsem); + + if (rcu) + synchronize_rcu(); } EXPORT_SYMBOL_GPL(nvme_stop_queues);
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index d26edab21d5c..730de600075b 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -309,6 +309,7 @@ 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); +bool blk_mq_quiesce_queue_without_rcu(struct request_queue *q); 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); bool blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);