[RFC PATCH 2/7] iommu: Add checked group device update helper
Zhanpeng Zhang
zhangzhanpeng.jasper at bytedance.com
Tue Jul 14 06:06:52 PDT 2026
Some group-wide operations must validate every member before changing
any device. Separate iommu_group_for_each_dev() calls cannot provide
that guarantee because group membership may change between traversals.
Add iommu_group_update_devices() to keep the group membership mutex held
across a validation pass and a non-failing update pass. This provides
all-or-none validation without exposing IOMMU group internals to
callers.
Signed-off-by: Zhanpeng Zhang <zhangzhanpeng.jasper at bytedance.com>
---
drivers/iommu/iommu.c | 33 +++++++++++++++++++++++++++++++++
include/linux/iommu.h | 13 +++++++++++++
2 files changed, 46 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index da269d10f6bf..9a6c4a7e7df6 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1436,6 +1436,39 @@ int iommu_group_for_each_dev(struct iommu_group *group, void *data,
}
EXPORT_SYMBOL_GPL(iommu_group_for_each_dev);
+/**
+ * iommu_group_update_devices - Check and update every device in a group
+ * @group: the group
+ * @data: caller data passed to both callbacks
+ * @check: validates whether one device can be updated
+ * @update: updates one device after every check has succeeded
+ *
+ * Keep group membership stable while first checking every device and then
+ * applying an update which cannot fail. No device is updated if a check fails.
+ */
+int iommu_group_update_devices(struct iommu_group *group, void *data,
+ int (*check)(struct device *, void *),
+ void (*update)(struct device *, void *))
+{
+ struct group_device *device;
+ int ret = 0;
+
+ mutex_lock(&group->mutex);
+ for_each_group_device(group, device) {
+ ret = check(device->dev, data);
+ if (ret)
+ goto unlock;
+ }
+
+ for_each_group_device(group, device)
+ update(device->dev, data);
+
+unlock:
+ mutex_unlock(&group->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_group_update_devices);
+
/**
* iommu_group_get - Return the group for a device and increment reference
* @dev: get the group that this device belongs to
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index e771b4a92f5b..befba0683e06 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -988,6 +988,9 @@ extern int iommu_group_add_device(struct iommu_group *group,
extern void iommu_group_remove_device(struct device *dev);
extern int iommu_group_for_each_dev(struct iommu_group *group, void *data,
int (*fn)(struct device *, void *));
+int iommu_group_update_devices(struct iommu_group *group, void *data,
+ int (*check)(struct device *, void *),
+ void (*update)(struct device *, void *));
extern struct iommu_group *iommu_group_get(struct device *dev);
struct iommu_group *iommu_group_get_by_id(int id);
void iommu_group_put_by_id(struct iommu_group *group);
@@ -1399,6 +1402,16 @@ static inline int iommu_group_for_each_dev(struct iommu_group *group,
return -ENODEV;
}
+static inline int iommu_group_update_devices(struct iommu_group *group,
+ void *data,
+ int (*check)(struct device *,
+ void *),
+ void (*update)(struct device *,
+ void *))
+{
+ return -ENODEV;
+}
+
static inline struct iommu_group *iommu_group_get(struct device *dev)
{
return NULL;
--
2.50.1 (Apple Git-155)
More information about the linux-riscv
mailing list