|
@@ -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);
|
|
|
|
- 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;
|
|
return ret;
|
|
}
|
|
}
|