Commit 9f478035 authored by Alex Williamson's avatar Alex Williamson

vfio/pci: Use pci_try_reset_function() on initial open

Device lock bites again; if a device .remove() callback races a user
calling ioctl(VFIO_GROUP_GET_DEVICE_FD), the unbind request will hold
the device lock, but the user ioctl may have already taken a vfio_device
reference.  In the case of a PCI device, the initial open will attempt
to reset the device, which again attempts to get the device lock,
resulting in deadlock.  Use the trylock PCI reset interface and return
error on the open path if reset fails due to lock contention.

Link: https://lkml.org/lkml/2017/7/25/381Reported-by: default avatarWen Congyang <wencongyang2@huawei.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent bb67b496
......@@ -226,7 +226,14 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
if (ret)
return ret;
vdev->reset_works = (pci_reset_function(pdev) == 0);
/* If reset fails because of the device lock, fail this path entirely */
ret = pci_try_reset_function(pdev);
if (ret == -EAGAIN) {
pci_disable_device(pdev);
return ret;
}
vdev->reset_works = !ret;
pci_save_state(pdev);
vdev->pci_saved_state = pci_store_saved_state(pdev);
if (!vdev->pci_saved_state)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment