Commit 3ca54708 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Alex Williamson
Browse files

vfio: Change struct vfio_group::container_users to a non-atomic int



Now that everything is fully locked there is no need for container_users
to remain as an atomic, change it to an unsigned int.

Use 'if (group->container)' as the test to determine if the container is
present or not instead of using container_users.

Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Tested-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/6-v2-d035a1842d81+1bf-vfio_group_locking_jgg@nvidia.com


Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent b76c0eed
Loading
Loading
Loading
Loading
+13 −15
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ struct vfio_group {
	struct device 			dev;
	struct cdev			cdev;
	refcount_t			users;
	atomic_t			container_users;
	unsigned int			container_users;
	struct iommu_group		*iommu_group;
	struct vfio_container		*container;
	struct list_head		device_list;
@@ -429,7 +429,7 @@ static void vfio_group_put(struct vfio_group *group)
	 * properly hold the group reference.
	 */
	WARN_ON(!list_empty(&group->device_list));
	WARN_ON(atomic_read(&group->container_users));
	WARN_ON(group->container || group->container_users);
	WARN_ON(group->notifier.head);

	list_del(&group->vfio_next);
@@ -930,6 +930,7 @@ static void __vfio_group_unset_container(struct vfio_group *group)
	iommu_group_release_dma_owner(group->iommu_group);

	group->container = NULL;
	group->container_users = 0;
	list_del(&group->container_next);

	/* Detaching the last group deprivileges a container, remove iommu */
@@ -953,17 +954,13 @@ static void __vfio_group_unset_container(struct vfio_group *group)
 */
static int vfio_group_unset_container(struct vfio_group *group)
{
	int users = atomic_cmpxchg(&group->container_users, 1, 0);

	lockdep_assert_held_write(&group->group_rwsem);

	if (!users)
	if (!group->container)
		return -EINVAL;
	if (users != 1)
	if (group->container_users != 1)
		return -EBUSY;

	__vfio_group_unset_container(group);

	return 0;
}

@@ -976,7 +973,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)

	lockdep_assert_held_write(&group->group_rwsem);

	if (atomic_read(&group->container_users))
	if (group->container || WARN_ON(group->container_users))
		return -EINVAL;

	if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO))
@@ -1020,12 +1017,12 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
	}

	group->container = container;
	group->container_users = 1;
	container->noiommu = (group->type == VFIO_NO_IOMMU);
	list_add(&group->container_next, &container->group_list);

	/* Get a reference on the container and mark a user within the group */
	vfio_container_get(container);
	atomic_inc(&group->container_users);

unlock_out:
	up_write(&container->group_lock);
@@ -1047,22 +1044,23 @@ static int vfio_device_assign_container(struct vfio_device *device)

	lockdep_assert_held_write(&group->group_rwsem);

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

	if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO))
		return -EPERM;

	get_file(group->opened_file);
	atomic_inc(&group->container_users);
	group->container_users++;
	return 0;
}

static void vfio_device_unassign_container(struct vfio_device *device)
{
	down_write(&device->group->group_rwsem);
	atomic_dec(&device->group->container_users);
	WARN_ON(device->group->container_users <= 1);
	device->group->container_users--;
	fput(device->group->opened_file);
	up_write(&device->group->group_rwsem);
}
@@ -1289,7 +1287,7 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
	 */
	WARN_ON(group->notifier.head);
	if (group->container) {
		WARN_ON(atomic_read(&group->container_users) != 1);
		WARN_ON(group->container_users != 1);
		__vfio_group_unset_container(group);
	}
	group->opened_file = NULL;