]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
NVMe: Short-cut removal on surprise hot-unplug
authorKeith Busch <keith.busch@intel.com>
Thu, 12 May 2016 14:37:14 +0000 (08:37 -0600)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 1 Jun 2017 20:41:25 +0000 (13:41 -0700)
This patch adds a new state that when set has the core automatically
kill request queues prior to removing namespaces.

If PCI device is not present at the time the nvme driver's remove is
called, we can kill all IO queues immediately instead of waiting for
the watchdog thread to do that at its polling interval. This improves
scenarios where multiple hot plug events occur at the same time since
it doesn't block the pci enumeration for as long.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
(cherry picked from commit 0ff9d4e1a284a9282a049bf064f123e27f838907)

Orabug: 25130845

Signed-off-by: Ashok Vairavan <ashok.vairavan@oracle.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c

index a2ec783fcec8aabb3330f06ffe90d6e6f2f2df8a..542eb2ccb46660733ac51119b173deb2dcac0a4d 100644 (file)
@@ -95,6 +95,15 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
                        break;
                }
                break;
+       case NVME_CTRL_DEAD:
+               switch (old_state) {
+               case NVME_CTRL_DELETING:
+                       changed = true;
+                       /* FALLTHRU */
+               default:
+                       break;
+               }
+               break;
        default:
                break;
        }
@@ -1492,6 +1501,15 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns, *next;
 
+       /*
+        * The dead states indicates the controller was not gracefully
+        * disconnected. In that case, we won't be able to flush any data while
+        * removing the namespaces' disks; fail all the queues now to avoid
+        * potentially having to clean up the failed sync later.
+        */
+       if (ctrl->state == NVME_CTRL_DEAD)
+               nvme_kill_queues(ctrl);
+
        mutex_lock(&ctrl->namespaces_mutex);
        list_for_each_entry_safe(ns, next, &ctrl->namespaces, list)
                nvme_ns_remove(ns);
index 70dbc7eb65116eb8f86214a84a985f8b7042e53f..cdaff0e6c6027b3fdaa23ba7e5e56a52ec88402b 100644 (file)
@@ -60,6 +60,7 @@ enum nvme_ctrl_state {
        NVME_CTRL_LIVE,
        NVME_CTRL_RESETTING,
        NVME_CTRL_DELETING,
+       NVME_CTRL_DEAD,
 };
 
 struct nvme_ctrl {
index a2c2aa1bb8dfb345f1b13b527f6903501115f47e..892fc688e0f9dc92c5454aefbafcded2dde4277d 100644 (file)
@@ -2034,6 +2034,10 @@ static void nvme_remove(struct pci_dev *pdev)
        nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
 
        pci_set_drvdata(pdev, NULL);
+
+       if (!pci_device_is_present(pdev))
+               nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD);
+
        flush_work(&dev->reset_work);
        nvme_uninit_ctrl(&dev->ctrl);
        nvme_dev_disable(dev, true);