Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9065f44 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+54 −37
Original line number Diff line number Diff line
@@ -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
 */
@@ -1198,20 +1215,22 @@ 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;
	if (ret) {
		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
@@ -1219,7 +1238,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
	ret = get_unused_fd_flags(O_CLOEXEC);
	if (ret < 0) {
		device->ops->release(device->device_data);
			break;
		vfio_device_put(device);
		return ret;
	}

	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)
		put_unused_fd(ret);
		ret = PTR_ERR(filep);
		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)
	 */
	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);

	return ret;
}