diff options
| author | Alex Williamson <alex.williamson@redhat.com> | 2014-09-29 19:18:39 -0400 |
|---|---|---|
| committer | Alex Williamson <alex.williamson@redhat.com> | 2014-09-29 19:18:39 -0400 |
| commit | 93899a679fd6b2534b5c297d9316bae039ebcbe1 (patch) | |
| tree | 99679fe7f8afc70254c5ff9f0d202028911ccad4 /drivers/vfio | |
| parent | 0f905ce2b59c666ad48f240bfa2ab28b77f7f936 (diff) | |
vfio-pci: Fix remove path locking
Locking both the remove() and release() path results in a deadlock
that should have been obvious. To fix this we can get and hold the
vfio_device reference as we evaluate whether to do a bus/slot reset.
This will automatically block any remove() calls, allowing us to
remove the explict lock. Fixes 61d792562b53.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: stable@vger.kernel.org [3.17]
Diffstat (limited to 'drivers/vfio')
| -rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 136 |
1 files changed, 57 insertions, 79 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index f7825332a325..9558da3f06a0 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -876,15 +876,11 @@ static void vfio_pci_remove(struct pci_dev *pdev) | |||
| 876 | { | 876 | { |
| 877 | struct vfio_pci_device *vdev; | 877 | struct vfio_pci_device *vdev; |
| 878 | 878 | ||
| 879 | mutex_lock(&driver_lock); | ||
| 880 | |||
| 881 | vdev = vfio_del_group_dev(&pdev->dev); | 879 | vdev = vfio_del_group_dev(&pdev->dev); |
| 882 | if (vdev) { | 880 | if (vdev) { |
| 883 | iommu_group_put(pdev->dev.iommu_group); | 881 | iommu_group_put(pdev->dev.iommu_group); |
| 884 | kfree(vdev); | 882 | kfree(vdev); |
| 885 | } | 883 | } |
| 886 | |||
| 887 | mutex_unlock(&driver_lock); | ||
| 888 | } | 884 | } |
| 889 | 885 | ||
| 890 | static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, | 886 | static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, |
| @@ -927,108 +923,90 @@ static struct pci_driver vfio_pci_driver = { | |||
| 927 | .err_handler = &vfio_err_handlers, | 923 | .err_handler = &vfio_err_handlers, |
| 928 | }; | 924 | }; |
| 929 | 925 | ||
| 930 | /* | 926 | struct vfio_devices { |
| 931 | * Test whether a reset is necessary and possible. We mark devices as | 927 | struct vfio_device **devices; |
| 932 | * needs_reset when they are released, but don't have a function-local reset | 928 | int cur_index; |
| 933 | * available. If any of these exist in the affected devices, we want to do | 929 | int max_index; |
| 934 | * a bus/slot reset. We also need all of the affected devices to be unused, | 930 | }; |
| 935 | * so we abort if any device has a non-zero refcnt. driver_lock prevents a | ||
| 936 | * device from being opened during the scan or unbound from vfio-pci. | ||
| 937 | */ | ||
| 938 | static int vfio_pci_test_bus_reset(struct pci_dev *pdev, void *data) | ||
| 939 | { | ||
| 940 | bool *needs_reset = data; | ||
| 941 | struct pci_driver *pci_drv = ACCESS_ONCE(pdev->driver); | ||
| 942 | int ret = -EBUSY; | ||
| 943 | |||
| 944 | if (pci_drv == &vfio_pci_driver) { | ||
| 945 | struct vfio_device *device; | ||
| 946 | struct vfio_pci_device *vdev; | ||
| 947 | |||
| 948 | device = vfio_device_get_from_dev(&pdev->dev); | ||
| 949 | if (!device) | ||
| 950 | return ret; | ||
| 951 | |||
| 952 | vdev = vfio_device_data(device); | ||
| 953 | if (vdev) { | ||
| 954 | if (vdev->needs_reset) | ||
| 955 | *needs_reset = true; | ||
| 956 | |||
| 957 | if (!vdev->refcnt) | ||
| 958 | ret = 0; | ||
| 959 | } | ||
| 960 | |||
| 961 | vfio_device_put(device); | ||
| 962 | } | ||
| 963 | |||
| 964 | /* | ||
| 965 | * TODO: vfio-core considers groups to be viable even if some devices | ||
| 966 | * are attached to known drivers, like pci-stub or pcieport. We can't | ||
| 967 | * freeze devices from being unbound to those drivers like we can | ||
| 968 | * here though, so it would be racy to test for them. We also can't | ||
| 969 | * use device_lock() to prevent changes as that would interfere with | ||
| 970 | * PCI-core taking device_lock during bus reset. For now, we require | ||
| 971 | * devices to be bound to vfio-pci to get a bus/slot reset on release. | ||
| 972 | */ | ||
| 973 | |||
| 974 | return ret; | ||
| 975 | } | ||
| 976 | 931 | ||
| 977 | /* Clear needs_reset on all affected devices after successful bus/slot reset */ | 932 | static int vfio_pci_get_devs(struct pci_dev *pdev, void *data) |
| 978 | static int vfio_pci_clear_needs_reset(struct pci_dev *pdev, void *data) | ||
| 979 | { | 933 | { |
| 934 | struct vfio_devices *devs = data; | ||
| 980 | struct pci_driver *pci_drv = ACCESS_ONCE(pdev->driver); | 935 | struct pci_driver *pci_drv = ACCESS_ONCE(pdev->driver); |
| 981 | 936 | ||
| 982 | if (pci_drv == &vfio_pci_driver) { | 937 | if (pci_drv != &vfio_pci_driver) |
| 983 | struct vfio_device *device; | 938 | return -EBUSY; |
| 984 | struct vfio_pci_device *vdev; | ||
| 985 | 939 | ||
| 986 | device = vfio_device_get_from_dev(&pdev->dev); | 940 | if (devs->cur_index == devs->max_index) |
| 987 | if (!device) | 941 | return -ENOSPC; |
| 988 | return 0; | ||
| 989 | 942 | ||
| 990 | vdev = vfio_device_data(device); | 943 | devs->devices[devs->cur_index] = vfio_device_get_from_dev(&pdev->dev); |
| 991 | if (vdev) | 944 | if (!devs->devices[devs->cur_index]) |
| 992 | vdev->needs_reset = false; | 945 | return -EINVAL; |
| 993 | |||
| 994 | vfio_device_put(device); | ||
| 995 | } | ||
| 996 | 946 | ||
| 947 | devs->cur_index++; | ||
| 997 | return 0; | 948 | return 0; |
| 998 | } | 949 | } |
| 999 | 950 | ||
| 1000 | /* | 951 | /* |
| 1001 | * Attempt to do a bus/slot reset if there are devices affected by a reset for | 952 | * Attempt to do a bus/slot reset if there are devices affected by a reset for |
| 1002 | * this device that are needs_reset and all of the affected devices are unused | 953 | * this device that are needs_reset and all of the affected devices are unused |
| 1003 | * (!refcnt). Callers of this function are required to hold driver_lock such | 954 | * (!refcnt). Callers are required to hold driver_lock when calling this to |
| 1004 | * that devices can not be unbound from vfio-pci or opened by a user while we | 955 | * prevent device opens and concurrent bus reset attempts. We prevent device |
| 1005 | * test for and perform a bus/slot reset. | 956 | * unbinds by acquiring and holding a reference to the vfio_device. |
| 957 | * | ||
| 958 | * NB: vfio-core considers a group to be viable even if some devices are | ||
| 959 | * bound to drivers like pci-stub or pcieport. Here we require all devices | ||
| 960 | * to be bound to vfio_pci since that's the only way we can be sure they | ||
| 961 | * stay put. | ||
| 1006 | */ | 962 | */ |
| 1007 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev) | 963 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev) |
| 1008 | { | 964 | { |
| 965 | struct vfio_devices devs = { .cur_index = 0 }; | ||
| 966 | int i = 0, ret = -EINVAL; | ||
| 1009 | bool needs_reset = false, slot = false; | 967 | bool needs_reset = false, slot = false; |
| 1010 | int ret; | 968 | struct vfio_pci_device *tmp; |
| 1011 | 969 | ||
| 1012 | if (!pci_probe_reset_slot(vdev->pdev->slot)) | 970 | if (!pci_probe_reset_slot(vdev->pdev->slot)) |
| 1013 | slot = true; | 971 | slot = true; |
| 1014 | else if (pci_probe_reset_bus(vdev->pdev->bus)) | 972 | else if (pci_probe_reset_bus(vdev->pdev->bus)) |
| 1015 | return; | 973 | return; |
| 1016 | 974 | ||
| 1017 | if (vfio_pci_for_each_slot_or_bus(vdev->pdev, | 975 | if (vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_count_devs, |
| 1018 | vfio_pci_test_bus_reset, | 976 | &i, slot) || !i) |
| 1019 | &needs_reset, slot) || !needs_reset) | ||
| 1020 | return; | 977 | return; |
| 1021 | 978 | ||
| 1022 | if (slot) | 979 | devs.max_index = i; |
| 1023 | ret = pci_try_reset_slot(vdev->pdev->slot); | 980 | devs.devices = kcalloc(i, sizeof(struct vfio_device *), GFP_KERNEL); |
| 1024 | else | 981 | if (!devs.devices) |
| 1025 | ret = pci_try_reset_bus(vdev->pdev->bus); | ||
| 1026 | |||
| 1027 | if (ret) | ||
| 1028 | return; | 982 | return; |
| 1029 | 983 | ||
| 1030 | vfio_pci_for_each_slot_or_bus(vdev->pdev, | 984 | if (vfio_pci_for_each_slot_or_bus(vdev->pdev, |
| 1031 | vfio_pci_clear_needs_reset, NULL, slot); | 985 | vfio_pci_get_devs, &devs, slot)) |
| 986 | goto put_devs; | ||
| 987 | |||
| 988 | for (i = 0; i < devs.cur_index; i++) { | ||
| 989 | tmp = vfio_device_data(devs.devices[i]); | ||
| 990 | if (tmp->needs_reset) | ||
| 991 | needs_reset = true; | ||
| 992 | if (tmp->refcnt) | ||
| 993 | goto put_devs; | ||
| 994 | } | ||
| 995 | |||
| 996 | if (needs_reset) | ||
| 997 | ret = slot ? pci_try_reset_slot(vdev->pdev->slot) : | ||
| 998 | pci_try_reset_bus(vdev->pdev->bus); | ||
| 999 | |||
| 1000 | put_devs: | ||
| 1001 | for (i = 0; i < devs.cur_index; i++) { | ||
| 1002 | if (!ret) { | ||
| 1003 | tmp = vfio_device_data(devs.devices[i]); | ||
| 1004 | tmp->needs_reset = false; | ||
| 1005 | } | ||
| 1006 | vfio_device_put(devs.devices[i]); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | kfree(devs.devices); | ||
| 1032 | } | 1010 | } |
| 1033 | 1011 | ||
| 1034 | static void __exit vfio_pci_cleanup(void) | 1012 | static void __exit vfio_pci_cleanup(void) |
