NVMe: Fix filesystem sync deadlock on removal
authorKeith Busch <keith.busch@intel.com>
Fri, 18 Jul 2014 17:40:20 +0000 (11:40 -0600)
committerJens Axboe <axboe@fb.com>
Tue, 4 Nov 2014 20:17:08 +0000 (13:17 -0700)
This changes the order of deleting the gendisks so it happens after the
nvme IO queues are freed. If a device is removed while a filesystem has
associated dirty data, the removal will wait on these to complete before
proceeding from del_gendisk, which could have caused deadlock before.

The implication of this is that an orderly removal of a responsive
device won't necessarily wait for dirty data to be written, but we are
not guaranteed the device is even going to respond at this point either.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/nvme-core.c

index d3a025f..48a1be4 100644 (file)
@@ -2781,8 +2781,8 @@ static void nvme_remove_disks(struct work_struct *ws)
 {
        struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
 
-       nvme_dev_remove(dev);
        nvme_free_queues(dev, 1);
+       nvme_dev_remove(dev);
 }
 
 static int nvme_dev_resume(struct nvme_dev *dev)
@@ -2931,9 +2931,9 @@ static void nvme_remove(struct pci_dev *pdev)
        flush_work(&dev->reset_work);
        flush_work(&dev->cpu_work);
        misc_deregister(&dev->miscdev);
-       nvme_dev_remove(dev);
        nvme_dev_shutdown(dev);
        nvme_free_queues(dev, 0);
+       nvme_dev_remove(dev);
        nvme_release_instance(dev);
        nvme_release_prp_pools(dev);
        kref_put(&dev->kref, nvme_free_dev);