Commit c6f4860e authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Alex Williamson

vfio: Change struct vfio_group::opened from an atomic to bool

This is not a performance path, just use the group_rwsem to protect the
value.
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/2-v2-d035a1842d81+1bf-vfio_group_locking_jgg@nvidia.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent be8d3ada
...@@ -73,7 +73,7 @@ struct vfio_group { ...@@ -73,7 +73,7 @@ struct vfio_group {
struct mutex device_lock; struct mutex device_lock;
struct list_head vfio_next; struct list_head vfio_next;
struct list_head container_next; struct list_head container_next;
atomic_t opened; bool opened;
enum vfio_group_type type; enum vfio_group_type type;
unsigned int dev_counter; unsigned int dev_counter;
struct rw_semaphore group_rwsem; struct rw_semaphore group_rwsem;
...@@ -1213,30 +1213,30 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep) ...@@ -1213,30 +1213,30 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
{ {
struct vfio_group *group = struct vfio_group *group =
container_of(inode->i_cdev, struct vfio_group, cdev); container_of(inode->i_cdev, struct vfio_group, cdev);
int opened; int ret;
/* users can be zero if this races with vfio_group_put() */ down_write(&group->group_rwsem);
if (!refcount_inc_not_zero(&group->users))
return -ENODEV;
if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) { /* users can be zero if this races with vfio_group_put() */
vfio_group_put(group); if (!refcount_inc_not_zero(&group->users)) {
return -EPERM; ret = -ENODEV;
goto err_unlock;
} }
/* Do we need multiple instances of the group open? Seems not. */ if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) {
opened = atomic_cmpxchg(&group->opened, 0, 1); ret = -EPERM;
if (opened) { goto err_put;
vfio_group_put(group);
return -EBUSY;
} }
/* Is something still in use from a previous open? */ /*
if (group->container) { * Do we need multiple instances of the group open? Seems not.
atomic_dec(&group->opened); * Is something still in use from a previous open?
vfio_group_put(group); */
return -EBUSY; if (group->opened || group->container) {
ret = -EBUSY;
goto err_put;
} }
group->opened = true;
/* Warn if previous user didn't cleanup and re-init to drop them */ /* Warn if previous user didn't cleanup and re-init to drop them */
if (WARN_ON(group->notifier.head)) if (WARN_ON(group->notifier.head))
...@@ -1244,7 +1244,13 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep) ...@@ -1244,7 +1244,13 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
filep->private_data = group; filep->private_data = group;
up_write(&group->group_rwsem);
return 0; return 0;
err_put:
vfio_group_put(group);
err_unlock:
up_write(&group->group_rwsem);
return ret;
} }
static int vfio_group_fops_release(struct inode *inode, struct file *filep) static int vfio_group_fops_release(struct inode *inode, struct file *filep)
...@@ -1255,7 +1261,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep) ...@@ -1255,7 +1261,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
vfio_group_try_dissolve_container(group); vfio_group_try_dissolve_container(group);
atomic_dec(&group->opened); down_write(&group->group_rwsem);
group->opened = false;
up_write(&group->group_rwsem);
vfio_group_put(group); vfio_group_put(group);
......
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