[PATCH v6 06/27] vfio: Add helpers to identify device files that can be preserved
From: Vipin Sharma
Date: Mon Nov 02 2026 - 13:13:45 EST
Add two helpers needed by vfio-pci Live Update support:
1. vfio_file_is_bound_cdev(): checks whether a specific file is a VFIO
cdev device file that has been bound to an iommufd. Only the bound
cdev file keeps the device open; the device-level cdev_opened flag
cannot distinguish between the bound cdev file and a second, unbound
cdev file opened for the same device.
2. vfio_device_is_noiommu(): move the existing helper out of line and
export it so vfio-pci can enforce that only devices in no-IOMMU mode
are preserved across Live Update.
No functional change intended for existing callers.
Signed-off-by: Vipin Sharma <vipinsh@xxxxxxxxxx>
---
drivers/vfio/device_cdev.c | 20 ++++++++++++++++++++
drivers/vfio/vfio.h | 10 ----------
drivers/vfio/vfio_main.c | 18 ++++++++++++++++++
include/linux/vfio.h | 10 ++++++++++
4 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
index 1d9515c967b0..23b229468151 100644
--- a/drivers/vfio/device_cdev.c
+++ b/drivers/vfio/device_cdev.c
@@ -200,6 +200,26 @@ void vfio_df_unbind_iommufd(struct vfio_device_file *df)
vfio_device_unblock_group(device);
}
+/**
+ * vfio_file_is_bound_cdev - True if the file is a VFIO cdev file bound to an
+ * iommufd
+ * @file: File to check
+ *
+ * Return: True if @file is a VFIO cdev device file on which
+ * VFIO_DEVICE_BIND_IOMMUFD has succeeded, false otherwise.
+ */
+bool vfio_file_is_bound_cdev(struct file *file)
+{
+ struct vfio_device_file *df = file->private_data;
+
+ if (file->f_op != &vfio_device_fops)
+ return false;
+
+ /* Paired with smp_store_release() in vfio_df_ioctl_bind_iommufd() */
+ return !df->group && smp_load_acquire(&df->access_granted);
+}
+EXPORT_SYMBOL_GPL(vfio_file_is_bound_cdev);
+
int vfio_df_ioctl_attach_pt(struct vfio_device_file *df,
struct vfio_device_attach_iommufd_pt __user *arg)
{
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 7728bc99b63d..12557d45dfee 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -185,16 +185,6 @@ static inline void vfio_group_cleanup(void)
#endif /* CONFIG_VFIO_GROUP */
-static inline bool vfio_device_is_noiommu(struct vfio_device *vdev)
-{
-#if IS_ENABLED(CONFIG_VFIO_GROUP)
- if (vdev->group && vdev->group->type == VFIO_NO_IOMMU)
- return true;
-#endif
-
- return IS_ENABLED(CONFIG_IOMMUFD_NOIOMMU) && vdev->noiommu;
-}
-
#if IS_ENABLED(CONFIG_VFIO_CONTAINER)
/**
* struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 73a5c4f3751c..291460102cd1 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1507,6 +1507,24 @@ struct vfio_device *vfio_device_from_file(struct file *file)
}
EXPORT_SYMBOL_GPL(vfio_device_from_file);
+/**
+ * vfio_device_is_noiommu - True if the VFIO device is registered in no-IOMMU
+ * mode
+ * @vdev: The VFIO device to check
+ *
+ * Return: True if @vdev is registered in no-IOMMU mode, false otherwise.
+ */
+bool vfio_device_is_noiommu(struct vfio_device *vdev)
+{
+#if IS_ENABLED(CONFIG_VFIO_GROUP)
+ if (vdev->group && vdev->group->type == VFIO_NO_IOMMU)
+ return true;
+#endif
+
+ return IS_ENABLED(CONFIG_IOMMUFD_NOIOMMU) && vdev->noiommu;
+}
+EXPORT_SYMBOL_GPL(vfio_device_is_noiommu);
+
/**
* vfio_file_is_valid - True if the file is valid vfio file
* @file: VFIO group file or VFIO device file
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index de3fa6e6bf2a..3cfbf1d73479 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -380,6 +380,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);
struct vfio_device *vfio_device_from_file(struct file *file);
+bool vfio_device_is_noiommu(struct vfio_device *vdev);
#define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long))
@@ -431,4 +432,13 @@ int vfio_virqfd_enable(void *opaque, int (*handler)(void *, void *),
void vfio_virqfd_disable(struct virqfd **pvirqfd);
void vfio_virqfd_flush_thread(struct virqfd **pvirqfd);
+#if IS_ENABLED(CONFIG_VFIO_DEVICE_CDEV)
+bool vfio_file_is_bound_cdev(struct file *file);
+#else
+static inline bool vfio_file_is_bound_cdev(struct file *file)
+{
+ return false;
+}
+#endif /* IS_ENABLED(CONFIG_VFIO_DEVICE_CDEV) */
+
#endif /* VFIO_H */
--
2.56.0.317.g454f8302e1-goog