aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-10 17:50:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-10 17:50:08 -0400
commit15a49b9a90c86c6cb7f270a699d2ae7468862c28 (patch)
tree218fc6bf3ae5beb989cddaede2e4ee0c2e679845 /drivers/vfio/vfio.c
parent8d10aae2741ec9ffd53c8d214f7ada6d543b3a46 (diff)
parent8d38ef1948bd415a5cb653a5c0ec16f3402aaca1 (diff)
Merge tag 'vfio-v3.11' of git://github.com/awilliam/linux-vfio
Pull vfio updates from Alex Williamson: "Largely hugepage support for vfio/type1 iommu and surrounding cleanups and fixes" * tag 'vfio-v3.11' of git://github.com/awilliam/linux-vfio: vfio/type1: Fix leak on error path vfio: Limit group opens vfio/type1: Fix missed frees and zero sized removes vfio: fix documentation vfio: Provide module option to disable vfio_iommu_type1 hugepage support vfio: hugepage support for vfio_iommu_type1 vfio: Convert type1 iommu to use rbtree
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r--drivers/vfio/vfio.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 259ad282ae5d..c488da5db7c7 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -76,6 +76,7 @@ struct vfio_group {
76 struct notifier_block nb; 76 struct notifier_block nb;
77 struct list_head vfio_next; 77 struct list_head vfio_next;
78 struct list_head container_next; 78 struct list_head container_next;
79 atomic_t opened;
79}; 80};
80 81
81struct vfio_device { 82struct vfio_device {
@@ -206,6 +207,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
206 INIT_LIST_HEAD(&group->device_list); 207 INIT_LIST_HEAD(&group->device_list);
207 mutex_init(&group->device_lock); 208 mutex_init(&group->device_lock);
208 atomic_set(&group->container_users, 0); 209 atomic_set(&group->container_users, 0);
210 atomic_set(&group->opened, 0);
209 group->iommu_group = iommu_group; 211 group->iommu_group = iommu_group;
210 212
211 group->nb.notifier_call = vfio_iommu_group_notifier; 213 group->nb.notifier_call = vfio_iommu_group_notifier;
@@ -1236,12 +1238,22 @@ static long vfio_group_fops_compat_ioctl(struct file *filep,
1236static int vfio_group_fops_open(struct inode *inode, struct file *filep) 1238static int vfio_group_fops_open(struct inode *inode, struct file *filep)
1237{ 1239{
1238 struct vfio_group *group; 1240 struct vfio_group *group;
1241 int opened;
1239 1242
1240 group = vfio_group_get_from_minor(iminor(inode)); 1243 group = vfio_group_get_from_minor(iminor(inode));
1241 if (!group) 1244 if (!group)
1242 return -ENODEV; 1245 return -ENODEV;
1243 1246
1247 /* Do we need multiple instances of the group open? Seems not. */
1248 opened = atomic_cmpxchg(&group->opened, 0, 1);
1249 if (opened) {
1250 vfio_group_put(group);
1251 return -EBUSY;
1252 }
1253
1254 /* Is something still in use from a previous open? */
1244 if (group->container) { 1255 if (group->container) {
1256 atomic_dec(&group->opened);
1245 vfio_group_put(group); 1257 vfio_group_put(group);
1246 return -EBUSY; 1258 return -EBUSY;
1247 } 1259 }
@@ -1259,6 +1271,8 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
1259 1271
1260 vfio_group_try_dissolve_container(group); 1272 vfio_group_try_dissolve_container(group);
1261 1273
1274 atomic_dec(&group->opened);
1275
1262 vfio_group_put(group); 1276 vfio_group_put(group);
1263 1277
1264 return 0; 1278 return 0;