aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-06-25 18:06:54 -0400
committerAlex Williamson <alex.williamson@redhat.com>2013-06-25 18:06:54 -0400
commit6d6768c61b39a2184bc11bb0342e4f7f35642bcc (patch)
tree504f88a65c5ad214086ae2e3edff7bd4efcb548f /drivers/vfio/vfio.c
parentf5bfdbf252ad54aa4b6f765cbe89750087fcc155 (diff)
vfio: Limit group opens
vfio_group_fops_open attempts to limit concurrent sessions by disallowing opens once group->container is set. This really doesn't do what we want and allow for inconsistent behavior, for instance a group can be opened twice, then a container set giving the user two file descriptors to the group. But then it won't allow more to be opened. There's not much reason to have the group opened multiple times since most access is through devices or the container, so complete what the original code intended and only allow a single instance. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
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 6d78736563de..d30f44da8762 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;