[libvirt] [PATCH 5/8] conf: new function virDomainPCIAddressIsMulti()

Laine Stump laine at laine.org
Mon Oct 24 19:50:26 UTC 2016


This function iterates through all the devices in a domain to
determine if the address it has been given is part of a "multifunction
device" (i.e. multiple devices connected to different functions of the
same slot).

This implementation may seem a bit inefficient because it has to
iterate through all the devices for each device that needs checking,
but this really is our only option since the address allocation set
isn't always available (and maybe not even exist at the time it's
needed).
---
 src/conf/domain_addr.c   | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_addr.h   |  5 ++++
 src/libvirt_private.syms |  1 +
 3 files changed, 66 insertions(+)

diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 2ac740f..dcd384a 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -809,6 +809,66 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
 }
 
 
+typedef struct {
+    virPCIDeviceAddressPtr addr;
+    bool isMulti;
+} virDomainPCIAddressIsMultiIterData;
+
+
+static int
+virDomainPCIAddressIsMultiIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                               virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                               virDomainDeviceInfoPtr info,
+                               void *data)
+{
+    virDomainPCIAddressIsMultiIterData *context = data;
+    virPCIDeviceAddressPtr testAddr = context->addr;
+    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 != testAddr->function) {
+        context->isMulti = true;
+        return -1; /* finish early, *NOT* an error */
+    }
+
+    return 0;
+}
+
+
+/**
+ * virDomainPCIAddressIsMulti():
+ *
+ * @def: the domain definition whose devices need adjusting
+ * @addr: the address to check
+ *
+ * See if there is any PCI device in the domain with the same
+ * domain/bus/slot but different function. If so, then this address is
+ * used by a multifunction device.
+ *
+ * Returns true if the address is being used by multiple devices, else
+ * false.
+ */
+bool
+virDomainPCIAddressIsMulti(const virDomainDef *def,
+                           virPCIDeviceAddressPtr addr)
+{
+    virDomainPCIAddressIsMultiIterData data = { .addr = addr,
+                                                .isMulti = false };
+
+    ignore_value(virDomainDeviceInfoIterate((virDomainDefPtr)def,
+                                            virDomainPCIAddressIsMultiIter,
+                                            &data));
+    return data.isMulti;
+}
+
+
 static char*
 virDomainCCWAddressAsString(virDomainDeviceCCWAddressPtr addr)
 {
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 0a571ca..1b36877 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -173,6 +173,11 @@ int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
                                        virDomainPCIConnectFlags flags)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
+bool
+virDomainPCIAddressIsMulti(const virDomainDef *def,
+                           virPCIDeviceAddressPtr addr)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
 struct _virDomainCCWAddressSet {
     virHashTablePtr defined;
     virDomainDeviceCCWAddress next;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b4210f4..104d43e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -99,6 +99,7 @@ virDomainPCIAddressAsString;
 virDomainPCIAddressBusSetModel;
 virDomainPCIAddressEnsureAddr;
 virDomainPCIAddressFlagsCompatible;
+virDomainPCIAddressIsMulti;
 virDomainPCIAddressReleaseSlot;
 virDomainPCIAddressReserveAddr;
 virDomainPCIAddressReserveNextAddr;
-- 
2.7.4




More information about the libvir-list mailing list