vfio: Change struct vfio_group::container_users to a non-atomic int
authorJason Gunthorpe <jgg@nvidia.com>
Mon, 16 May 2022 23:41:22 +0000 (20:41 -0300)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 17 May 2022 19:07:09 +0000 (13:07 -0600)
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: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/6-v2-d035a1842d81+1bf-vfio_group_locking_jgg@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/vfio.c

index 149c258..cfcff77 100644 (file)
@@ -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;