This prepares for using vfio device cdev as no group fd will be opened in device cdev usage. vfio_file_is_device_opened() is added for checking a given vfio file is able to be a proof for the device ownership or not. The reason is that the cdev path has the device opened in an in-between state, in which the device is not fully opened. But to be proof of ownership, device should be fully opened. This also updates some comments as it also accepts device fd passed by user. The uapi has no change, but user can specify a set of device fds in the struct vfio_pci_hot_reset::group_fds field. Signed-off-by: Yi Liu <yi.l.liu@xxxxxxxxx> --- drivers/vfio/pci/vfio_pci_core.c | 11 ++++++----- drivers/vfio/vfio_main.c | 19 +++++++++++++++++++ include/linux/vfio.h | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 827524510f3f..09086fefd515 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -1280,8 +1280,9 @@ static int vfio_pci_ioctl_pci_hot_reset(struct vfio_pci_core_device *vdev, /* * We can't let userspace give us an arbitrarily large buffer to copy, - * so verify how many we think there could be. Note groups can have - * multiple devices so one group per device is the max. + * so verify how many we think there could be. Note user may provide + * a set of groups, group can have multiple devices so one group per + * device is the max. */ ret = vfio_pci_for_each_slot_or_bus(vdev->pdev, vfio_pci_count_devs, &count, slot); @@ -1308,7 +1309,7 @@ static int vfio_pci_ioctl_pci_hot_reset(struct vfio_pci_core_device *vdev, } /* - * For each group_fd, get the group file, this ensures the group + * For each fd, get the file, this ensures the group or device * is held across the reset. */ for (file_idx = 0; file_idx < hdr.count; file_idx++) { @@ -1320,7 +1321,7 @@ static int vfio_pci_ioctl_pci_hot_reset(struct vfio_pci_core_device *vdev, } /* Ensure the FD is a vfio FD.*/ - if (!vfio_file_is_valid(file)) { + if (!vfio_file_is_device_opened(file)) { fput(file); ret = -EINVAL; break; @@ -2430,7 +2431,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, list_for_each_entry(cur_vma, &dev_set->device_list, vdev.dev_set_list) { /* * Test whether all the affected devices are contained by the - * set of groups provided by the user. + * set of files provided by the user. */ if (!vfio_dev_in_groups(cur_vma, groups)) { ret = -EINVAL; diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 91c8f25393db..2c851e172586 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -1209,6 +1209,25 @@ bool vfio_file_is_valid(struct file *file) } EXPORT_SYMBOL_GPL(vfio_file_is_valid); +/** + * vfio_file_is_device_opened - True if the file is fully opened + * @file: VFIO group file or VFIO device file + */ +bool vfio_file_is_device_opened(struct file *file) +{ + struct vfio_device *device; + + if (vfio_group_from_file(file)) + return true; + + device = vfio_device_from_file(file); + if (device) + return READ_ONCE(device->open_count); + + return false; +} +EXPORT_SYMBOL_GPL(vfio_file_is_device_opened); + /** * vfio_file_enforced_coherent - True if the DMA associated with the VFIO file * is always CPU cache coherent diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 6a07e1c6c38e..615f8a081a41 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -249,6 +249,7 @@ bool vfio_file_is_valid(struct file *file); bool vfio_file_enforced_coherent(struct file *file); void vfio_file_set_kvm(struct file *file, struct kvm *kvm); bool vfio_file_has_dev(struct file *file, struct vfio_device *device); +bool vfio_file_is_device_opened(struct file *file); #define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long)) -- 2.34.1