VFIO fixes for v4.2
- Fix a lockdep reported deadlock in device open error path (Alex Williamson) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVuPowAAoJECObm247sIsii7gP/0Lw9csfXBuZSBVEQzp6okYD 1BJoL9c1bfR2f+CKFfnc5JDCgdKGIATWYdZ04M6UGDbRTIRfgd11W46kjneNZS/c FV6NjuabY2YGpj6ckIqi/FzJna93ZucLnaGaCGKyLYdy1Yc50thBQZp/zFvPLhZi fEWz7toOB0sG0/1HTqZN8Mg5qjwXR79+M6qQIOUZSmIfKJFXWcDlUffraS6Ls2Rx O7MlNNUthRf9FI9wX1RnYeRvotzuy1pwQpeSkUi2CPWn7/m/+ynIz4qkakOGnerX 5QwjQd4Ww3BgrAyJ7js9JyfvhQK5He/GZVmQWRuAC0hEDu2JK4AlpOneUc63SaP9 ap+B87pxynmomRAKrgaB5bqh5zzrMPaXooowc3eQ613a5ThVFNWRw8PaK0/yQepX HipvNkR0GVM6aJuXCYTiSyOrL/T8kaSlkn8NXNbMMwZZZiVQLtTlIoCU717iKqbb Ig5Ut9h8OJcNljeIhdeEXJGwCy24BTo5AnABuCUnpZKv9fGryruGQHa5buiirhvR 6Rbdi8HIAvg/KzRtjTgDtHMK1p0DDbQVTh8rAAivHRewg5wkNosILKyvQwbeVc2U 1/L3ewqyRYQuHzS1/MB8M+CYFF3HSQyJnVUzJ94dqrWNHzPjGSb3E0iQfPRhcydM rfwPgM7vpIehTnCMTqlx =e/+g -----END PGP SIGNATURE----- Merge tag 'vfio-v4.2-rc5' of git://github.com/awilliam/linux-vfio Pull VFIO fix from Alex Williamson: "Fix a lockdep reported deadlock in device open error path" * tag 'vfio-v4.2-rc5' of git://github.com/awilliam/linux-vfio: vfio: Fix lockdep issue
This commit is contained in:
commit
d9065f44be
1 changed files with 57 additions and 40 deletions
|
@ -689,6 +689,23 @@ struct vfio_device *vfio_device_get_from_dev(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
|
EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
|
||||||
|
|
||||||
|
static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct vfio_device *device;
|
||||||
|
|
||||||
|
mutex_lock(&group->device_lock);
|
||||||
|
list_for_each_entry(device, &group->device_list, group_next) {
|
||||||
|
if (!strcmp(dev_name(device->dev), buf)) {
|
||||||
|
vfio_device_get(device);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&group->device_lock);
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Caller must hold a reference to the vfio_device
|
* Caller must hold a reference to the vfio_device
|
||||||
*/
|
*/
|
||||||
|
@ -1198,53 +1215,53 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
|
||||||
{
|
{
|
||||||
struct vfio_device *device;
|
struct vfio_device *device;
|
||||||
struct file *filep;
|
struct file *filep;
|
||||||
int ret = -ENODEV;
|
int ret;
|
||||||
|
|
||||||
if (0 == atomic_read(&group->container_users) ||
|
if (0 == atomic_read(&group->container_users) ||
|
||||||
!group->container->iommu_driver || !vfio_group_viable(group))
|
!group->container->iommu_driver || !vfio_group_viable(group))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&group->device_lock);
|
device = vfio_device_get_from_name(group, buf);
|
||||||
list_for_each_entry(device, &group->device_list, group_next) {
|
if (!device)
|
||||||
if (strcmp(dev_name(device->dev), buf))
|
return -ENODEV;
|
||||||
continue;
|
|
||||||
|
|
||||||
ret = device->ops->open(device->device_data);
|
ret = device->ops->open(device->device_data);
|
||||||
if (ret)
|
if (ret) {
|
||||||
break;
|
vfio_device_put(device);
|
||||||
/*
|
return ret;
|
||||||
* We can't use anon_inode_getfd() because we need to modify
|
|
||||||
* the f_mode flags directly to allow more than just ioctls
|
|
||||||
*/
|
|
||||||
ret = get_unused_fd_flags(O_CLOEXEC);
|
|
||||||
if (ret < 0) {
|
|
||||||
device->ops->release(device->device_data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
|
|
||||||
device, O_RDWR);
|
|
||||||
if (IS_ERR(filep)) {
|
|
||||||
put_unused_fd(ret);
|
|
||||||
ret = PTR_ERR(filep);
|
|
||||||
device->ops->release(device->device_data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: add an anon_inode interface to do this.
|
|
||||||
* Appears to be missing by lack of need rather than
|
|
||||||
* explicitly prevented. Now there's need.
|
|
||||||
*/
|
|
||||||
filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
|
||||||
|
|
||||||
vfio_device_get(device);
|
|
||||||
atomic_inc(&group->container_users);
|
|
||||||
|
|
||||||
fd_install(ret, filep);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&group->device_lock);
|
|
||||||
|
/*
|
||||||
|
* We can't use anon_inode_getfd() because we need to modify
|
||||||
|
* the f_mode flags directly to allow more than just ioctls
|
||||||
|
*/
|
||||||
|
ret = get_unused_fd_flags(O_CLOEXEC);
|
||||||
|
if (ret < 0) {
|
||||||
|
device->ops->release(device->device_data);
|
||||||
|
vfio_device_put(device);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
|
||||||
|
device, O_RDWR);
|
||||||
|
if (IS_ERR(filep)) {
|
||||||
|
put_unused_fd(ret);
|
||||||
|
ret = PTR_ERR(filep);
|
||||||
|
device->ops->release(device->device_data);
|
||||||
|
vfio_device_put(device);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: add an anon_inode interface to do this.
|
||||||
|
* Appears to be missing by lack of need rather than
|
||||||
|
* explicitly prevented. Now there's need.
|
||||||
|
*/
|
||||||
|
filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
||||||
|
|
||||||
|
atomic_inc(&group->container_users);
|
||||||
|
|
||||||
|
fd_install(ret, filep);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue