aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-22 12:56:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-22 12:56:06 -0400
commit467e9e51d07d43d32a1dd8b6ead2351e28fff084 (patch)
treed925caa3c94036ba2457f0de64b6e6c40236ca46 /drivers
parent23dcfa61bac244e1200ff9ad19c6e9144dcb6bb5 (diff)
parent88ec2789d856056344161aa20420dd37e893b0fe (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull assorted fixes - mostly vfs - from Al Viro: "Assorted fixes, with an unexpected detour into vfio refcounting logics (fell out when digging in an analog of eventpoll race in there)." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: task_work: add a scheduling point in task_work_run() fs: fix fs/namei.c kernel-doc warnings eventpoll: use-after-possible-free in epoll_create1() vfio: grab vfio_device reference *before* exposing the sucker via fd_install() vfio: get rid of vfio_device_put()/vfio_group_get_device* races vfio: get rid of open-coding kref_put_mutex introduce kref_put_mutex() vfio: don't dereference after kfree... mqueue: lift mnt_want_write() outside ->i_mutex, clean up a bit
Diffstat (limited to 'drivers')
-rw-r--r--drivers/vfio/vfio.c19
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 */
267static void vfio_group_release(struct kref *kref) 268static 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
288static void vfio_group_put(struct vfio_group *group) 289static 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 */
417static void vfio_device_put(struct vfio_device *device) 411static 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
423static void vfio_device_get(struct vfio_device *device) 418static 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);