aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nvme-core.c
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2014-08-19 21:15:59 -0400
committerJens Axboe <axboe@fb.com>2014-11-04 15:17:09 -0500
commita96d4f5c2da66a0c1537bfd8aaa868b69595476a (patch)
tree59758fc29e667a858e6d072126178ea9d709d7a7 /drivers/block/nvme-core.c
parent062261be4e39e35bdf2fba16a4b2d8a432ae8281 (diff)
NVMe: Reference count pci device
If an nvme device is removed but user space has an open reference, the nvme driver would have been holding an invalid reference to its pci device. You may get a general protection fault on x86 h/w when the driver uses that reference in dma_map_sg(), as is done in nvme_map_user_pages() from the IOCTL interface. This patch fixes the fault by taking a reference on the pci device and holding it even after device removal until all opens on the nvme device are closed. Signed-off-by: Keith Busch <keith.busch@intel.com> Reported-by: Nilesh Choudhury <nilesh.choudhury@oracle.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/nvme-core.c')
-rw-r--r--drivers/block/nvme-core.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index c1e3c1a101b8..955b5699ff96 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2678,6 +2678,7 @@ static void nvme_free_dev(struct kref *kref)
2678{ 2678{
2679 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); 2679 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
2680 2680
2681 pci_dev_put(dev->pci_dev);
2681 nvme_free_namespaces(dev); 2682 nvme_free_namespaces(dev);
2682 free_percpu(dev->io_queue); 2683 free_percpu(dev->io_queue);
2683 kfree(dev->queues); 2684 kfree(dev->queues);
@@ -2853,11 +2854,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2853 dev->reset_workfn = nvme_reset_failed_dev; 2854 dev->reset_workfn = nvme_reset_failed_dev;
2854 INIT_WORK(&dev->reset_work, nvme_reset_workfn); 2855 INIT_WORK(&dev->reset_work, nvme_reset_workfn);
2855 INIT_WORK(&dev->cpu_work, nvme_cpu_workfn); 2856 INIT_WORK(&dev->cpu_work, nvme_cpu_workfn);
2856 dev->pci_dev = pdev; 2857 dev->pci_dev = pci_dev_get(pdev);
2857 pci_set_drvdata(pdev, dev); 2858 pci_set_drvdata(pdev, dev);
2858 result = nvme_set_instance(dev); 2859 result = nvme_set_instance(dev);
2859 if (result) 2860 if (result)
2860 goto free; 2861 goto put_pci;
2861 2862
2862 result = nvme_setup_prp_pools(dev); 2863 result = nvme_setup_prp_pools(dev);
2863 if (result) 2864 if (result)
@@ -2895,6 +2896,8 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2895 nvme_release_prp_pools(dev); 2896 nvme_release_prp_pools(dev);
2896 release: 2897 release:
2897 nvme_release_instance(dev); 2898 nvme_release_instance(dev);
2899 put_pci:
2900 pci_dev_put(dev->pci_dev);
2898 free: 2901 free:
2899 free_percpu(dev->io_queue); 2902 free_percpu(dev->io_queue);
2900 kfree(dev->queues); 2903 kfree(dev->queues);