From 3c1a0fc27d271590818c672fab4dc935c6d2f21d Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Tue, 10 Jan 2017 00:02:40 -0500 Subject: [PATCH] conf: new function virDomainPCIAddressSetAllMulti() 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. --- src/conf/domain_addr.c | 83 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 3 ++ src/libvirt_private.syms | 1 + 3 files changed, 87 insertions(+) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 4d14ac4953..1f6ff7a26a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -867,6 +867,89 @@ 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 5f0924e418..c728c009b9 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 4d16620b4e..4d2f85cc3d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -104,6 +104,7 @@ virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextAddr; virDomainPCIAddressReserveNextSlot; virDomainPCIAddressReserveSlot; +virDomainPCIAddressSetAllMulti; virDomainPCIAddressSetAlloc; virDomainPCIAddressSetFree; virDomainPCIAddressSetGrow;