aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r--drivers/vfio/vfio.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 56097c6d072d..3b7fa7967221 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container)
191 kref_put(&container->kref, vfio_container_release); 191 kref_put(&container->kref, vfio_container_release);
192} 192}
193 193
194static void vfio_group_unlock_and_free(struct vfio_group *group)
195{
196 mutex_unlock(&vfio.group_lock);
197 /*
198 * Unregister outside of lock. A spurious callback is harmless now
199 * that the group is no longer in vfio.group_list.
200 */
201 iommu_group_unregister_notifier(group->iommu_group, &group->nb);
202 kfree(group);
203}
204
194/** 205/**
195 * Group objects - create, release, get, put, search 206 * Group objects - create, release, get, put, search
196 */ 207 */
@@ -229,8 +240,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
229 240
230 minor = vfio_alloc_group_minor(group); 241 minor = vfio_alloc_group_minor(group);
231 if (minor < 0) { 242 if (minor < 0) {
232 mutex_unlock(&vfio.group_lock); 243 vfio_group_unlock_and_free(group);
233 kfree(group);
234 return ERR_PTR(minor); 244 return ERR_PTR(minor);
235 } 245 }
236 246
@@ -239,8 +249,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
239 if (tmp->iommu_group == iommu_group) { 249 if (tmp->iommu_group == iommu_group) {
240 vfio_group_get(tmp); 250 vfio_group_get(tmp);
241 vfio_free_group_minor(minor); 251 vfio_free_group_minor(minor);
242 mutex_unlock(&vfio.group_lock); 252 vfio_group_unlock_and_free(group);
243 kfree(group);
244 return tmp; 253 return tmp;
245 } 254 }
246 } 255 }
@@ -249,8 +258,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
249 group, "%d", iommu_group_id(iommu_group)); 258 group, "%d", iommu_group_id(iommu_group));
250 if (IS_ERR(dev)) { 259 if (IS_ERR(dev)) {
251 vfio_free_group_minor(minor); 260 vfio_free_group_minor(minor);
252 mutex_unlock(&vfio.group_lock); 261 vfio_group_unlock_and_free(group);
253 kfree(group);
254 return (struct vfio_group *)dev; /* ERR_PTR */ 262 return (struct vfio_group *)dev; /* ERR_PTR */
255 } 263 }
256 264
@@ -274,16 +282,7 @@ static void vfio_group_release(struct kref *kref)
274 device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); 282 device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor));
275 list_del(&group->vfio_next); 283 list_del(&group->vfio_next);
276 vfio_free_group_minor(group->minor); 284 vfio_free_group_minor(group->minor);
277 285 vfio_group_unlock_and_free(group);
278 mutex_unlock(&vfio.group_lock);
279
280 /*
281 * Unregister outside of lock. A spurious callback is harmless now
282 * that the group is no longer in vfio.group_list.
283 */
284 iommu_group_unregister_notifier(group->iommu_group, &group->nb);
285
286 kfree(group);
287} 286}
288 287
289static void vfio_group_put(struct vfio_group *group) 288static void vfio_group_put(struct vfio_group *group)