virDomainPCIAddressGetNextSlot() starts searching from the last
allocated address and goes to the end of all the buses, then goes back
to the first bus and searchs from there up to the starting point (in
case any address has been freed since the last time an address was
allocated. The loops for these two are almost, but not exactly, the
same, so they have remained as separate loops with the same code
inside the loop. To lessen maintenance headaches, the identical code
has been moved out into the function
virDomainPCIAddressFindUnusedFunctionOnBus(), which is called in place
of the loop contents.
---
src/conf/domain_addr.c | 92 ++++++++++++++++++++++++++++++--------------------
1 file changed, 56 insertions(+), 36 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 2db6250..cd070e5 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -633,6 +633,45 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
}
+static int
+virDomainPCIAddressFindUnusedFunctionOnBus(virDomainPCIAddressBusPtr bus,
+ virPCIDeviceAddressPtr searchAddr,
+ int function ATTRIBUTE_UNUSED,
+ virDomainPCIConnectFlags flags,
+ bool *found)
+{
+ int ret = -1;
+ char *addrStr = NULL;
+
+ *found = false;
+
+ if (!(addrStr = virDomainPCIAddressAsString(searchAddr)))
+ goto cleanup;
+
+ if (!virDomainPCIAddressFlagsCompatible(searchAddr, addrStr, bus->flags,
+ flags, false, false)) {
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
+ searchAddr->domain, searchAddr->bus);
+ } else {
+ while (searchAddr->slot <= bus->maxSlot) {
+ if (bus->slot[searchAddr->slot].functions == 0) {
+ *found = true;
+ break;
+ }
+
+ VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
+ searchAddr->domain, searchAddr->bus, searchAddr->slot);
+ searchAddr->slot++;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(addrStr);
+ return ret;
+}
+
+
static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr next_addr,
@@ -642,8 +681,8 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
/* default to starting the search for a free slot from
* the first slot of domain 0 bus 0...
*/
- virPCIDeviceAddress a = {0};
- char *addrStr = NULL;
+ virPCIDeviceAddress a = { 0 };
+ bool found = false;
if (addrs->nbuses == 0) {
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses
available"));
@@ -671,24 +710,16 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
a.function = function;
while (a.bus < addrs->nbuses) {
- VIR_FREE(addrStr);
- if (!(addrStr = virDomainPCIAddressAsString(&a)))
+ if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus],
+ &a, function,
+ flags, &found) < 0) {
goto error;
- if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
- addrs->buses[a.bus].flags,
- flags, false, false)) {
- VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
- a.domain, a.bus);
- } else {
- while (a.slot <= addrs->buses[a.bus].maxSlot) {
- if (!virDomainPCIAddressSlotInUse(addrs, &a))
- goto success;
-
- VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
- a.domain, a.bus, a.slot);
- a.slot++;
- }
}
+
+ if (found)
+ goto success;
+
+ /* nothing on this bus, go to the next bus */
if (++a.bus < addrs->nbuses)
a.slot = addrs->buses[a.bus].minSlot;
}
@@ -705,38 +736,27 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
/* Check the buses from 0 up to the last used one */
for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
a.slot = addrs->buses[a.bus].minSlot;
- VIR_FREE(addrStr);
- if (!(addrStr = virDomainPCIAddressAsString(&a)))
+
+ if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus],
+ &a, function,
+ flags, &found) < 0) {
goto error;
- if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
- addrs->buses[a.bus].flags,
- flags, false, false)) {
- VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the
device",
- a.domain, a.bus);
- } else {
- while (a.slot <= addrs->buses[a.bus].maxSlot) {
- if (!virDomainPCIAddressSlotInUse(addrs, &a))
- goto success;
-
- VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
- a.domain, a.bus, a.slot);
- a.slot++;
- }
}
+
+ if (found)
+ goto success;
}
}
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("No more available PCI slots"));
error:
- VIR_FREE(addrStr);
return -1;
success:
VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x",
a.domain, a.bus, a.slot);
*next_addr = a;
- VIR_FREE(addrStr);
return 0;
}
--
2.7.4