summaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@nvidia.com>2021-10-15 13:40:53 +0200
committerAlex Williamson <alex.williamson@redhat.com>2021-10-15 21:58:20 +0200
commit2b678aa2f0990a25e15cdef66256a131566ecd2e (patch)
tree96c10c15697f3d0e3f9db7ed695e12193024fb30 /drivers/vfio
parentvfio: Don't leak a group reference if the group already exists (diff)
downloadlinux-2b678aa2f0990a25e15cdef66256a131566ecd2e.tar.xz
linux-2b678aa2f0990a25e15cdef66256a131566ecd2e.zip
vfio: Use a refcount_t instead of a kref in the vfio_group
The next patch adds a struct device to the struct vfio_group, and it is confusing/bad practice to have two krefs in the same struct. This kref is controlling the period when the vfio_group is registered in sysfs, and visible in the internal lookup. Switch it to a refcount_t instead. The refcount_dec_and_mutex_lock() is still required because we need atomicity of the list searches and sysfs presence. Reviewed-by: Liu Yi L <yi.l.liu@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/4-v3-2fdfe4ca2cc6+18c-vfio_group_cdev_jgg@nvidia.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 4abb2e5e1965..e313fa030b91 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -69,7 +69,7 @@ struct vfio_unbound_dev {
};
struct vfio_group {
- struct kref kref;
+ refcount_t users;
int minor;
atomic_t container_users;
struct iommu_group *iommu_group;
@@ -377,7 +377,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
if (!group)
return ERR_PTR(-ENOMEM);
- kref_init(&group->kref);
+ refcount_set(&group->users, 1);
INIT_LIST_HEAD(&group->device_list);
mutex_init(&group->device_lock);
INIT_LIST_HEAD(&group->unbound_list);
@@ -433,10 +433,10 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
return group;
}
-/* called with vfio.group_lock held */
-static void vfio_group_release(struct kref *kref)
+static void vfio_group_put(struct vfio_group *group)
{
- struct vfio_group *group = container_of(kref, struct vfio_group, kref);
+ if (!refcount_dec_and_mutex_lock(&group->users, &vfio.group_lock))
+ return;
/*
* These data structures all have paired operations that can only be
@@ -454,15 +454,9 @@ static void vfio_group_release(struct kref *kref)
vfio_group_unlock_and_free(group);
}
-static void vfio_group_put(struct vfio_group *group)
-{
- kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock);
-}
-
-/* Assume group_lock or group reference is held */
static void vfio_group_get(struct vfio_group *group)
{
- kref_get(&group->kref);
+ refcount_inc(&group->users);
}
static struct vfio_group *vfio_group_get_from_minor(int minor)
@@ -1657,6 +1651,9 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
if (ret)
return ERR_PTR(ret);
+ /*
+ * Since the caller holds the fget on the file group->users must be >= 1
+ */
vfio_group_get(group);
return group;