This utility function iterates through all devices looking for any
with a PCI address that has function != 0 (which implies that multiple
functions are in use on that slot), then uses an inner iterator to
find the device that's on function 0 of that same slot and sets the
"multi" in its virDomainDeviceInfo (as long as it hasn't already been
set explicitly by someone who presumably has better information than
we do).
It isn't yet called from anywhere, so will have no functional effect.
---
Change from V1: implement as two nested deviceinfo iterators as
suggested by Andrea.
src/conf/domain_addr.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_addr.h | 3 ++
src/libvirt_private.syms | 1 +
3 files changed, 86 insertions(+)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 4d14ac4..453f287 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -867,6 +867,88 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
}
+static int
+virDomainPCIAddressSetMultiIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr info,
+ void *data)
+{
+ virPCIDeviceAddressPtr testAddr = data;
+ virPCIDeviceAddressPtr thisAddr;
+
+ if (!info || info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
+ return 0;
+
+ thisAddr = &info->addr.pci;
+
+ if (thisAddr->domain == testAddr->domain &&
+ thisAddr->bus == testAddr->bus &&
+ thisAddr->slot == testAddr->slot &&
+ thisAddr->function == 0) {
+
+ /* only set to ON if it wasn't previously set
+ * (assuming that the user must have better information
+ * than us if they explicitly set it OFF)
+ */
+ if (thisAddr->multi == VIR_TRISTATE_SWITCH_ABSENT)
+ thisAddr->multi = VIR_TRISTATE_SWITCH_ON;
+
+ return -1; /* finish early, *NOT* an error */
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainPCIAddressSetAllMultiIter(virDomainDefPtr def,
+ virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr info,
+ void *data ATTRIBUTE_UNUSED)
+{
+ virPCIDeviceAddressPtr testAddr;
+
+ if (!info || info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
+ return 0;
+
+ testAddr = &info->addr.pci;
+ if (testAddr->function != 0) {
+ ignore_value(virDomainDeviceInfoIterate(def,
+ virDomainPCIAddressSetMultiIter,
+ testAddr));
+ }
+
+ return 0;
+}
+
+
+/**
+ * virDomainPCIAddressSetAllMulti():
+ *
+ * @def: the domain definition whose devices may need adjusting
+ * @addrs: address set keeping track of all addresses in use.
+ *
+ * Look for any PCI slots that have multiple functions assigned, and
+ * set multi to ON in the address for the device at function 0
+ * (unless it has been explicitly set to OFF).
+ *
+ * No return code, since there is no possibility of failure.
+ */
+void
+virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
+{
+ /* Use nested iterators over all the devices - the outer iterator
+ * scans through all the devices looking for those whose address
+ * has a non-0 function; when one is found, the inner iterator looks
+ * for the device that uses function 0 on the same slot and marks
+ * it as multi = ON
+ */
+ ignore_value(virDomainDeviceInfoIterate(def,
+ virDomainPCIAddressSetAllMultiIter,
+ NULL));
+}
+
+
static char*
virDomainCCWAddressAsString(virDomainDeviceCCWAddressPtr addr)
{
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 5f0924e..c728c00 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -173,6 +173,9 @@ int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr
addrs,
virDomainPCIConnectFlags flags)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+void virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
+ ATTRIBUTE_NONNULL(1);
+
struct _virDomainCCWAddressSet {
virHashTablePtr defined;
virDomainDeviceCCWAddress next;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 82adf7e..bdc0272 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -104,6 +104,7 @@ virDomainPCIAddressReserveAddr;
virDomainPCIAddressReserveNextAddr;
virDomainPCIAddressReserveNextSlot;
virDomainPCIAddressReserveSlot;
+virDomainPCIAddressSetAllMulti;
virDomainPCIAddressSetAlloc;
virDomainPCIAddressSetFree;
virDomainPCIAddressSetGrow;
--
2.7.4