[libvirt] [PATCH 3/5] qemu: Fix auto-adding PCI bridge when all slots are reserved

Erik Skultety eskultet at redhat.com
Fri Jan 23 12:04:01 UTC 2015



On 01/22/2015 05:00 PM, Ján Tomko wrote:
> On 01/21/2015 05:50 PM, Erik Skultety wrote:
>> 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(-)
>>
> 
> This breaks the pci-many test case you added before.
> 
>> 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;
>> +
> 
> If you set this to true by default...
> 
>>          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;
> 
> you can do:
> if (!fullyReserved(buses[i]))
>   buses_reserved = false;
> 

Yeah, that one looks better, thanks.

> Or just rename the bool to something like 'addExtraEmptySlot' and invert the
> condition below. (To stay more positive :))
> 
>> +            }
>> +            buses_reserved = (resflags && ~((~0) << nbuses));
>> +

Not to mention this one should have been bitwise AND instead of logical
one anyway.

>>              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;
>> +            }
>> +        }
> 
> This should IMHO be a separate commit, as it does not fix the case where the
> devices exactly fill the buses, but when there are too many.
> 

You're probably right, coming in v2 series.

> Also, maybe the error message could say something about 'too many devices with
> fixed addressess'?
> 
> Jan
> 
> 
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
> 
Erik




More information about the libvir-list mailing list