Message ID | 20230401151833.124749-10-yi.l.liu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add vfio_device cdev for iommufd support | expand |
Hi Yi, On 4/1/23 17:18, Yi Liu wrote: > for counting the devices that are opened via the cdev path. This count > is increased and decreased by the cdev path. The group path checks it > to achieve exclusion with the cdev path. With this, only one path (group > path or cdev path) will claim DMA ownership. This avoids scenarios in > which devices within the same group may be opened via different paths. > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> > Tested-by: Terrence Xu <terrence.xu@intel.com> > Tested-by: Nicolin Chen <nicolinc@nvidia.com> > Tested-by: Matthew Rosato <mjrosato@linux.ibm.com> > Tested-by: Yanting Jiang <yanting.jiang@intel.com> > Signed-off-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Thanks Eric > --- > drivers/vfio/group.c | 33 +++++++++++++++++++++++++++++++++ > drivers/vfio/vfio.h | 3 +++ > 2 files changed, 36 insertions(+) > > diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c > index 71f0a9a4016e..d55ce3ca44b7 100644 > --- a/drivers/vfio/group.c > +++ b/drivers/vfio/group.c > @@ -383,6 +383,33 @@ static long vfio_group_fops_unl_ioctl(struct file *filep, > } > } > > +int vfio_device_block_group(struct vfio_device *device) > +{ > + struct vfio_group *group = device->group; > + int ret = 0; > + > + mutex_lock(&group->group_lock); > + if (group->opened_file) { > + ret = -EBUSY; > + goto out_unlock; > + } > + > + group->cdev_device_open_cnt++; > + > +out_unlock: > + mutex_unlock(&group->group_lock); > + return ret; > +} > + > +void vfio_device_unblock_group(struct vfio_device *device) > +{ > + struct vfio_group *group = device->group; > + > + mutex_lock(&group->group_lock); > + group->cdev_device_open_cnt--; > + mutex_unlock(&group->group_lock); > +} > + > static int vfio_group_fops_open(struct inode *inode, struct file *filep) > { > struct vfio_group *group = > @@ -405,6 +432,11 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep) > goto out_unlock; > } > > + if (group->cdev_device_open_cnt) { > + ret = -EBUSY; > + goto out_unlock; > + } > + > /* > * Do we need multiple instances of the group open? Seems not. > */ > @@ -479,6 +511,7 @@ static void vfio_group_release(struct device *dev) > mutex_destroy(&group->device_lock); > mutex_destroy(&group->group_lock); > WARN_ON(group->iommu_group); > + WARN_ON(group->cdev_device_open_cnt); > ida_free(&vfio.group_ida, MINOR(group->dev.devt)); > kfree(group); > } > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index 854f2c97cb9a..b2f20b78a707 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -83,8 +83,11 @@ struct vfio_group { > struct blocking_notifier_head notifier; > struct iommufd_ctx *iommufd; > spinlock_t kvm_ref_lock; > + unsigned int cdev_device_open_cnt; > }; > > +int vfio_device_block_group(struct vfio_device *device); > +void vfio_device_unblock_group(struct vfio_device *device); > int vfio_device_set_group(struct vfio_device *device, > enum vfio_group_type type); > void vfio_device_remove_group(struct vfio_device *device);
diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c index 71f0a9a4016e..d55ce3ca44b7 100644 --- a/drivers/vfio/group.c +++ b/drivers/vfio/group.c @@ -383,6 +383,33 @@ static long vfio_group_fops_unl_ioctl(struct file *filep, } } +int vfio_device_block_group(struct vfio_device *device) +{ + struct vfio_group *group = device->group; + int ret = 0; + + mutex_lock(&group->group_lock); + if (group->opened_file) { + ret = -EBUSY; + goto out_unlock; + } + + group->cdev_device_open_cnt++; + +out_unlock: + mutex_unlock(&group->group_lock); + return ret; +} + +void vfio_device_unblock_group(struct vfio_device *device) +{ + struct vfio_group *group = device->group; + + mutex_lock(&group->group_lock); + group->cdev_device_open_cnt--; + mutex_unlock(&group->group_lock); +} + static int vfio_group_fops_open(struct inode *inode, struct file *filep) { struct vfio_group *group = @@ -405,6 +432,11 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep) goto out_unlock; } + if (group->cdev_device_open_cnt) { + ret = -EBUSY; + goto out_unlock; + } + /* * Do we need multiple instances of the group open? Seems not. */ @@ -479,6 +511,7 @@ static void vfio_group_release(struct device *dev) mutex_destroy(&group->device_lock); mutex_destroy(&group->group_lock); WARN_ON(group->iommu_group); + WARN_ON(group->cdev_device_open_cnt); ida_free(&vfio.group_ida, MINOR(group->dev.devt)); kfree(group); } diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index 854f2c97cb9a..b2f20b78a707 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -83,8 +83,11 @@ struct vfio_group { struct blocking_notifier_head notifier; struct iommufd_ctx *iommufd; spinlock_t kvm_ref_lock; + unsigned int cdev_device_open_cnt; }; +int vfio_device_block_group(struct vfio_device *device); +void vfio_device_unblock_group(struct vfio_device *device); int vfio_device_set_group(struct vfio_device *device, enum vfio_group_type type); void vfio_device_remove_group(struct vfio_device *device);