Commit 93c8ca tried to fix the issue with auto-adding of a PCI bridge controller, it worked well when the slots were reserved by devices with user defined addresses without any other devices with unspecified PCI addresses present in the XML. However, if another device with unspecified PCI addresses appeared in the domain's XML, the same problem occurred as the BZ below references. This patch fixes the issue by not creating any additional bridges when not necessary. Now let's say all the buses corresponding to the number of PCI controllers present in the domain's XML got fully reserved by devices with user defined addresses. If there are no other devices present in the XML, no need to create both an additional PCI bus and a bridge controller. If however there are still some PCI devices waiting to get a slot assigned by qemuAssignDevicePCISlots, this means an additional bus needs to be created along with a corresponding bridge controller. This scenario now results in an reasonable error instead of generating wrong qemu command line. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1132900 --- src/qemu/qemu_command.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index cdf02a6..99b06ee 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1472,6 +1472,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, int nbuses = 0; size_t i; int rv; + int resflags = 0; + bool buses_reserved = false; + virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI; for (i = 0; i < def->ncontrollers; i++) { @@ -1490,17 +1493,22 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, /* 1st pass to figure out how many PCI bridges we need */ if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) goto cleanup; + + for (i = 0; i < nbuses; i++) { + if (qemuDomainPCIBusFullyReserved(&addrs->buses[i])) + resflags |= 1 << i; + } + buses_reserved = (resflags && ~((~0) << nbuses)); + if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0) goto cleanup; - for (i = 0; i < addrs->nbuses; i++) { - if (!qemuDomainPCIBusFullyReserved(&addrs->buses[i])) { - - /* Reserve 1 extra slot for a (potential) bridge */ - if (virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) - goto cleanup; - } - } + /* Reserve 1 extra slot for a (potential) bridge only if buses + * are not fully reserved yet + */ + if (!buses_reserved && + virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) + goto cleanup; for (i = 1; i < addrs->nbuses; i++) { virDomainPCIAddressBusPtr bus = &addrs->buses[i]; @@ -1532,6 +1540,24 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0) goto cleanup; } + + for (i = 0; i < def->ncontrollers; i++) { + /* check if every PCI bridge controller's ID is greater than + * the bus it is placed onto + */ + virDomainControllerDefPtr cont = def->controllers[i]; + int idx = cont->idx; + int bus = cont->info.addr.pci.bus; + if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE && + idx <= bus) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("failed to create PCI bridge " + "on bus %d: bus is fully reserved"), + bus); + goto cleanup; + } + } } if (obj && obj->privateData) { -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list