struct vfio_container *container = group->container;
struct vfio_iommu_driver *driver;
+ lockdep_assert_held_write(&group->group_rwsem);
+
down_write(&container->group_lock);
driver = container->iommu_driver;
{
int users = atomic_cmpxchg(&group->container_users, 1, 0);
+ lockdep_assert_held_write(&group->group_rwsem);
+
if (!users)
return -EINVAL;
if (users != 1)
*/
static void vfio_group_try_dissolve_container(struct vfio_group *group)
{
+ down_write(&group->group_rwsem);
if (0 == atomic_dec_if_positive(&group->container_users))
__vfio_group_unset_container(group);
+ up_write(&group->group_rwsem);
}
static int vfio_group_set_container(struct vfio_group *group, int container_fd)
struct vfio_iommu_driver *driver;
int ret = 0;
+ lockdep_assert_held_write(&group->group_rwsem);
+
if (atomic_read(&group->container_users))
return -EINVAL;
return ret;
}
-static int vfio_group_add_container_user(struct vfio_group *group)
-{
- if (!atomic_inc_not_zero(&group->container_users))
- return -EINVAL;
-
- if (group->type == VFIO_NO_IOMMU) {
- atomic_dec(&group->container_users);
- return -EPERM;
- }
- if (!group->container->iommu_driver) {
- atomic_dec(&group->container_users);
- return -EINVAL;
- }
-
- return 0;
-}
-
static const struct file_operations vfio_device_fops;
/* true if the vfio_device has open_device() called but not close_device() */
{
struct vfio_group *group = device->group;
+ lockdep_assert_held_write(&group->group_rwsem);
+
if (0 == atomic_read(&group->container_users) ||
!group->container->iommu_driver)
return -EINVAL;
struct file *filep;
int ret;
+ down_write(&device->group->group_rwsem);
ret = vfio_device_assign_container(device);
+ up_write(&device->group->group_rwsem);
if (ret)
return ERR_PTR(ret);
status.flags = 0;
+ down_read(&group->group_rwsem);
if (group->container)
status.flags |= VFIO_GROUP_FLAGS_CONTAINER_SET |
VFIO_GROUP_FLAGS_VIABLE;
else if (!iommu_group_dma_owner_claimed(group->iommu_group))
status.flags |= VFIO_GROUP_FLAGS_VIABLE;
+ up_read(&group->group_rwsem);
if (copy_to_user((void __user *)arg, &status, minsz))
return -EFAULT;
if (fd < 0)
return -EINVAL;
+ down_write(&group->group_rwsem);
ret = vfio_group_set_container(group, fd);
+ up_write(&group->group_rwsem);
break;
}
case VFIO_GROUP_UNSET_CONTAINER:
+ down_write(&group->group_rwsem);
ret = vfio_group_unset_container(group);
+ up_write(&group->group_rwsem);
break;
case VFIO_GROUP_GET_DEVICE_FD:
{
if (file->f_op != &vfio_group_fops)
return true;
- /*
- * Since the coherency state is determined only once a container is
- * attached the user must do so before they can prove they have
- * permission.
- */
- if (vfio_group_add_container_user(group))
- return true;
- ret = vfio_ioctl_check_extension(group->container, VFIO_DMA_CC_IOMMU);
- vfio_group_try_dissolve_container(group);
+ down_read(&group->group_rwsem);
+ if (group->container) {
+ ret = vfio_ioctl_check_extension(group->container,
+ VFIO_DMA_CC_IOMMU);
+ } else {
+ /*
+ * Since the coherency state is determined only once a container
+ * is attached the user must do so before they can prove they
+ * have permission.
+ */
+ ret = true;
+ }
+ up_read(&group->group_rwsem);
return ret;
}
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
if (group->dev_counter > 1)
return -EINVAL;
+ /* group->container cannot change while a vfio device is open */
container = group->container;
driver = container->iommu_driver;
if (likely(driver && driver->ops->pin_pages))
if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
return -E2BIG;
+ /* group->container cannot change while a vfio device is open */
container = device->group->container;
driver = container->iommu_driver;
if (likely(driver && driver->ops->unpin_pages))
if (!data || len <= 0 || !vfio_assert_device_open(device))
return -EINVAL;
+ /* group->container cannot change while a vfio device is open */
container = device->group->container;
driver = container->iommu_driver;
struct vfio_iommu_driver *driver;
int ret;
+ down_read(&group->group_rwsem);
container = group->container;
driver = container->iommu_driver;
if (likely(driver && driver->ops->register_notifier))
events, nb);
else
ret = -ENOTTY;
+ up_read(&group->group_rwsem);
+
return ret;
}
struct vfio_iommu_driver *driver;
int ret;
+ down_read(&group->group_rwsem);
container = group->container;
driver = container->iommu_driver;
if (likely(driver && driver->ops->unregister_notifier))
nb);
else
ret = -ENOTTY;
+ up_read(&group->group_rwsem);
+
return ret;
}