diff options
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r-- | drivers/vfio/vfio.c | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 9591e2b509d7..17830c9c7cc6 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -264,6 +264,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
264 | return group; | 264 | return group; |
265 | } | 265 | } |
266 | 266 | ||
267 | /* called with vfio.group_lock held */ | ||
267 | static void vfio_group_release(struct kref *kref) | 268 | static void vfio_group_release(struct kref *kref) |
268 | { | 269 | { |
269 | struct vfio_group *group = container_of(kref, struct vfio_group, kref); | 270 | struct vfio_group *group = container_of(kref, struct vfio_group, kref); |
@@ -287,13 +288,7 @@ static void vfio_group_release(struct kref *kref) | |||
287 | 288 | ||
288 | static void vfio_group_put(struct vfio_group *group) | 289 | static void vfio_group_put(struct vfio_group *group) |
289 | { | 290 | { |
290 | mutex_lock(&vfio.group_lock); | 291 | kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); |
291 | /* | ||
292 | * Release needs to unlock to unregister the notifier, so only | ||
293 | * unlock if not released. | ||
294 | */ | ||
295 | if (!kref_put(&group->kref, vfio_group_release)) | ||
296 | mutex_unlock(&vfio.group_lock); | ||
297 | } | 292 | } |
298 | 293 | ||
299 | /* Assume group_lock or group reference is held */ | 294 | /* Assume group_lock or group reference is held */ |
@@ -401,7 +396,6 @@ static void vfio_device_release(struct kref *kref) | |||
401 | struct vfio_device, kref); | 396 | struct vfio_device, kref); |
402 | struct vfio_group *group = device->group; | 397 | struct vfio_group *group = device->group; |
403 | 398 | ||
404 | mutex_lock(&group->device_lock); | ||
405 | list_del(&device->group_next); | 399 | list_del(&device->group_next); |
406 | mutex_unlock(&group->device_lock); | 400 | mutex_unlock(&group->device_lock); |
407 | 401 | ||
@@ -416,8 +410,9 @@ static void vfio_device_release(struct kref *kref) | |||
416 | /* Device reference always implies a group reference */ | 410 | /* Device reference always implies a group reference */ |
417 | static void vfio_device_put(struct vfio_device *device) | 411 | static void vfio_device_put(struct vfio_device *device) |
418 | { | 412 | { |
419 | kref_put(&device->kref, vfio_device_release); | 413 | struct vfio_group *group = device->group; |
420 | vfio_group_put(device->group); | 414 | kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock); |
415 | vfio_group_put(group); | ||
421 | } | 416 | } |
422 | 417 | ||
423 | static void vfio_device_get(struct vfio_device *device) | 418 | static void vfio_device_get(struct vfio_device *device) |
@@ -1116,10 +1111,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) | |||
1116 | */ | 1111 | */ |
1117 | filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); | 1112 | filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); |
1118 | 1113 | ||
1119 | fd_install(ret, filep); | ||
1120 | |||
1121 | vfio_device_get(device); | 1114 | vfio_device_get(device); |
1122 | atomic_inc(&group->container_users); | 1115 | atomic_inc(&group->container_users); |
1116 | |||
1117 | fd_install(ret, filep); | ||
1123 | break; | 1118 | break; |
1124 | } | 1119 | } |
1125 | mutex_unlock(&group->device_lock); | 1120 | mutex_unlock(&group->device_lock); |