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

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.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent b76c0eed
...@@ -66,7 +66,7 @@ struct vfio_group { ...@@ -66,7 +66,7 @@ struct vfio_group {
struct device dev; struct device dev;
struct cdev cdev; struct cdev cdev;
refcount_t users; refcount_t users;
atomic_t container_users; unsigned int container_users;
struct iommu_group *iommu_group; struct iommu_group *iommu_group;
struct vfio_container *container; struct vfio_container *container;
struct list_head device_list; struct list_head device_list;
...@@ -429,7 +429,7 @@ static void vfio_group_put(struct vfio_group *group) ...@@ -429,7 +429,7 @@ static void vfio_group_put(struct vfio_group *group)
* properly hold the group reference. * properly hold the group reference.
*/ */
WARN_ON(!list_empty(&group->device_list)); 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); WARN_ON(group->notifier.head);
list_del(&group->vfio_next); list_del(&group->vfio_next);
...@@ -930,6 +930,7 @@ static void __vfio_group_unset_container(struct vfio_group *group) ...@@ -930,6 +930,7 @@ static void __vfio_group_unset_container(struct vfio_group *group)
iommu_group_release_dma_owner(group->iommu_group); iommu_group_release_dma_owner(group->iommu_group);
group->container = NULL; group->container = NULL;
group->container_users = 0;
list_del(&group->container_next); list_del(&group->container_next);
/* Detaching the last group deprivileges a container, remove iommu */ /* Detaching the last group deprivileges a container, remove iommu */
...@@ -953,17 +954,13 @@ static void __vfio_group_unset_container(struct vfio_group *group) ...@@ -953,17 +954,13 @@ static void __vfio_group_unset_container(struct vfio_group *group)
*/ */
static int 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); lockdep_assert_held_write(&group->group_rwsem);
if (!users) if (!group->container)
return -EINVAL; return -EINVAL;
if (users != 1) if (group->container_users != 1)
return -EBUSY; return -EBUSY;
__vfio_group_unset_container(group); __vfio_group_unset_container(group);
return 0; return 0;
} }
...@@ -976,7 +973,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) ...@@ -976,7 +973,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
lockdep_assert_held_write(&group->group_rwsem); lockdep_assert_held_write(&group->group_rwsem);
if (atomic_read(&group->container_users)) if (group->container || WARN_ON(group->container_users))
return -EINVAL; return -EINVAL;
if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) 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) ...@@ -1020,12 +1017,12 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
} }
group->container = container; group->container = container;
group->container_users = 1;
container->noiommu = (group->type == VFIO_NO_IOMMU); container->noiommu = (group->type == VFIO_NO_IOMMU);
list_add(&group->container_next, &container->group_list); list_add(&group->container_next, &container->group_list);
/* Get a reference on the container and mark a user within the group */ /* Get a reference on the container and mark a user within the group */
vfio_container_get(container); vfio_container_get(container);
atomic_inc(&group->container_users);
unlock_out: unlock_out:
up_write(&container->group_lock); up_write(&container->group_lock);
...@@ -1047,22 +1044,23 @@ static int vfio_device_assign_container(struct vfio_device *device) ...@@ -1047,22 +1044,23 @@ static int vfio_device_assign_container(struct vfio_device *device)
lockdep_assert_held_write(&group->group_rwsem); lockdep_assert_held_write(&group->group_rwsem);
if (0 == atomic_read(&group->container_users) || if (!group->container || !group->container->iommu_driver ||
!group->container->iommu_driver) WARN_ON(!group->container_users))
return -EINVAL; return -EINVAL;
if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
get_file(group->opened_file); get_file(group->opened_file);
atomic_inc(&group->container_users); group->container_users++;
return 0; return 0;
} }
static void vfio_device_unassign_container(struct vfio_device *device) static void vfio_device_unassign_container(struct vfio_device *device)
{ {
down_write(&device->group->group_rwsem); 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); fput(device->group->opened_file);
up_write(&device->group->group_rwsem); up_write(&device->group->group_rwsem);
} }
...@@ -1289,7 +1287,7 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep) ...@@ -1289,7 +1287,7 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
*/ */
WARN_ON(group->notifier.head); WARN_ON(group->notifier.head);
if (group->container) { if (group->container) {
WARN_ON(atomic_read(&group->container_users) != 1); WARN_ON(group->container_users != 1);
__vfio_group_unset_container(group); __vfio_group_unset_container(group);
} }
group->opened_file = NULL; group->opened_file = NULL;
......
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