diff options
author | Keith Busch <keith.busch@intel.com> | 2014-07-18 13:40:20 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-11-04 15:17:08 -0500 |
commit | 302c6727e5eb4d0be0e02d077b65feb3e73ea254 (patch) | |
tree | 17f37cd779add019ed67a28cb1508e739ff8278a | |
parent | f435c2825b4cc6453b9a1f91418cabbd6ba08cc0 (diff) |
NVMe: Fix filesystem sync deadlock on removal
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>
-rw-r--r-- | drivers/block/nvme-core.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index d3a025fc1268..48a1be4ab24c 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -2781,8 +2781,8 @@ static void nvme_remove_disks(struct work_struct *ws) | |||
2781 | { | 2781 | { |
2782 | struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); | 2782 | struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work); |
2783 | 2783 | ||
2784 | nvme_dev_remove(dev); | ||
2785 | nvme_free_queues(dev, 1); | 2784 | nvme_free_queues(dev, 1); |
2785 | nvme_dev_remove(dev); | ||
2786 | } | 2786 | } |
2787 | 2787 | ||
2788 | static int nvme_dev_resume(struct nvme_dev *dev) | 2788 | static int nvme_dev_resume(struct nvme_dev *dev) |
@@ -2931,9 +2931,9 @@ static void nvme_remove(struct pci_dev *pdev) | |||
2931 | flush_work(&dev->reset_work); | 2931 | flush_work(&dev->reset_work); |
2932 | flush_work(&dev->cpu_work); | 2932 | flush_work(&dev->cpu_work); |
2933 | misc_deregister(&dev->miscdev); | 2933 | misc_deregister(&dev->miscdev); |
2934 | nvme_dev_remove(dev); | ||
2935 | nvme_dev_shutdown(dev); | 2934 | nvme_dev_shutdown(dev); |
2936 | nvme_free_queues(dev, 0); | 2935 | nvme_free_queues(dev, 0); |
2936 | nvme_dev_remove(dev); | ||
2937 | nvme_release_instance(dev); | 2937 | nvme_release_instance(dev); |
2938 | nvme_release_prp_pools(dev); | 2938 | nvme_release_prp_pools(dev); |
2939 | kref_put(&dev->kref, nvme_free_dev); | 2939 | kref_put(&dev->kref, nvme_free_dev); |