Commit d9065f44 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 733db573 4bc94d5d
...@@ -689,6 +689,23 @@ struct vfio_device *vfio_device_get_from_dev(struct device *dev) ...@@ -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,20 +1215,22 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) ...@@ -1198,20 +1215,22 @@ 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 * We can't use anon_inode_getfd() because we need to modify
* the f_mode flags directly to allow more than just ioctls * the f_mode flags directly to allow more than just ioctls
...@@ -1219,7 +1238,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) ...@@ -1219,7 +1238,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
ret = get_unused_fd_flags(O_CLOEXEC); ret = get_unused_fd_flags(O_CLOEXEC);
if (ret < 0) { if (ret < 0) {
device->ops->release(device->device_data); device->ops->release(device->device_data);
break; vfio_device_put(device);
return ret;
} }
filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops, filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
...@@ -1228,7 +1248,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) ...@@ -1228,7 +1248,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
put_unused_fd(ret); put_unused_fd(ret);
ret = PTR_ERR(filep); ret = PTR_ERR(filep);
device->ops->release(device->device_data); device->ops->release(device->device_data);
break; vfio_device_put(device);
return ret;
} }
/* /*
...@@ -1238,13 +1259,9 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) ...@@ -1238,13 +1259,9 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
*/ */
filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
vfio_device_get(device);
atomic_inc(&group->container_users); atomic_inc(&group->container_users);
fd_install(ret, filep); fd_install(ret, filep);
break;
}
mutex_unlock(&group->device_lock);
return ret; return ret;
} }
......
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