Skip to content

Commit

Permalink
Merge tag 'vfio-v4.2-rc5' of git://github.com/awilliam/linux-vfio
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Jul 29, 2015
2 parents 733db57 + 4bc94d5 commit d9065f4
Showing 1 changed file with 54 additions and 37 deletions.
91 changes: 54 additions & 37 deletions drivers/vfio/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,23 @@ struct vfio_device *vfio_device_get_from_dev(struct device *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
*/
Expand Down Expand Up @@ -1198,53 +1215,53 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
{
struct vfio_device *device;
struct file *filep;
int ret = -ENODEV;
int ret;

if (0 == atomic_read(&group->container_users) ||
!group->container->iommu_driver || !vfio_group_viable(group))
return -EINVAL;

mutex_lock(&group->device_lock);
list_for_each_entry(device, &group->device_list, group_next) {
if (strcmp(dev_name(device->dev), buf))
continue;
device = vfio_device_get_from_name(group, buf);
if (!device)
return -ENODEV;

ret = device->ops->open(device->device_data);
if (ret)
break;
/*
* 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;
}
ret = device->ops->open(device->device_data);
if (ret) {
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);
break;
}
/*
* 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;
}

/*
* 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);
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);

vfio_device_get(device);
atomic_inc(&group->container_users);
atomic_inc(&group->container_users);

fd_install(ret, filep);
break;
}
mutex_unlock(&group->device_lock);
fd_install(ret, filep);

return ret;
}
Expand Down

0 comments on commit d9065f4

Please sign in to comment.