[PATCH 4/4] NVMe: Freeze queues on shutdown
Keith Busch
keith.busch at intel.com
Fri Dec 19 16:54:16 PST 2014
We need to prevent entering queues and allocating requests when we are
about to disable a h/w queue.
Signed-off-by: Keith Busch <keith.busch at intel.com>
---
drivers/block/nvme-core.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 9642c83..3063958 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2244,10 +2244,13 @@ static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
fatal_signal_pending(current)) {
set_current_state(TASK_RUNNING);
+ blk_mq_freeze_queue_start(dev->admin_q);
nvme_disable_ctrl(dev, readq(&dev->bar->cap));
nvme_disable_queue(dev, 0);
- send_sig(SIGKILL, dq->worker->task, 1);
+ blk_cleanup_queue(dev->admin_q);
+ blk_mq_unfreeze_queue(dev->admin_q);
+
flush_kthread_worker(dq->worker);
return;
}
@@ -2383,6 +2386,22 @@ static void nvme_dev_list_remove(struct nvme_dev *dev)
kthread_stop(tmp);
}
+static void nvme_freeze_queues(struct nvme_dev *dev)
+{
+ struct nvme_ns *ns;
+
+ list_for_each_entry(ns, &dev->namespaces, list)
+ blk_mq_freeze_queue_start(ns->queue);
+}
+
+static void nvme_unfreeze_queues(struct nvme_dev *dev)
+{
+ struct nvme_ns *ns;
+
+ list_for_each_entry(ns, &dev->namespaces, list)
+ blk_mq_unfreeze_queue(ns->queue);
+}
+
static void nvme_dev_shutdown(struct nvme_dev *dev)
{
int i;
@@ -2391,6 +2410,7 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
dev->initialized = 0;
nvme_dev_list_remove(dev);
+ nvme_freeze_queues(dev);
if (dev->bar)
csts = readl(&dev->bar->csts);
if (csts & NVME_CSTS_CFS || !(csts & NVME_CSTS_RDY)) {
@@ -2646,7 +2666,8 @@ static int nvme_dev_resume(struct nvme_dev *dev)
dev->reset_workfn = nvme_remove_disks;
queue_work(nvme_workq, &dev->reset_work);
spin_unlock(&dev_list_lock);
- }
+ } else
+ nvme_unfreeze_queues(dev);
dev->initialized = 1;
return 0;
}
@@ -2783,8 +2804,8 @@ static void nvme_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
flush_work(&dev->reset_work);
misc_deregister(&dev->miscdev);
- nvme_dev_remove(dev);
nvme_dev_shutdown(dev);
+ nvme_dev_remove(dev);
nvme_dev_remove_admin(dev);
nvme_free_queues(dev, 0);
nvme_free_admin_tags(dev);
--
1.7.10.4
More information about the Linux-nvme
mailing list