diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 17:50:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 17:50:08 -0400 |
commit | 15a49b9a90c86c6cb7f270a699d2ae7468862c28 (patch) | |
tree | 218fc6bf3ae5beb989cddaede2e4ee0c2e679845 /drivers/vfio/vfio.c | |
parent | 8d10aae2741ec9ffd53c8d214f7ada6d543b3a46 (diff) | |
parent | 8d38ef1948bd415a5cb653a5c0ec16f3402aaca1 (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.c | 14 |
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 | ||
81 | struct vfio_device { | 82 | struct 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, | |||
1236 | static int vfio_group_fops_open(struct inode *inode, struct file *filep) | 1238 | static 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; |