[libvirt] [PATCHv3 2/2] qemu: improve error reporting during PCI address validation
Doug Goldstein
cardoe at gentoo.org
Tue Aug 6 14:56:30 UTC 2013
On Mon, Aug 5, 2013 at 9:15 PM, Doug Goldstein <cardoe at gentoo.org> wrote:
> On Mon, Aug 5, 2013 at 8:13 PM, Laine Stump <laine at laine.org> wrote:
>> This patch addresses two concerns with the error reporting when an
>> incompatible PCI address is specified for a device:
>>
>> 1) It wasn't always apparent which device had the problem. With this
>> patch applied, any error about an incompatible address will always
>> contain the full address as given in the config, so it will be easier
>> to determine which device's config aused the problem.
>>
>> 2) In some cases when the problem came from bad config, the error
>> message was erroneously classified as VIR_ERR_INTERNAL_ERROR. With
>> this patch applied, the same error message will be changed to indicate
>> either "internal" or "xml" error depending on whether the address came
>> from the config, or was automatically generated by libvirt.
>>
>> Note that in the case of "internal" (due to bad auto-generation)
>> errors, the PCI address won't be of much use in finding the location
>> in config to change (because it was automatically generated). Of
>> course that makes perfect sense, but still the address could provide a
>> clue about a bug in libvirt attempting to use a type of pci bus that
>> doesn't have its flags set correctly (or something similar). In other
>> words, it's not perfect, but it is definitely better.
>> ---
>> src/qemu/qemu_command.c | 224 +++++++++++++++++++++++++++++-------------------
>> 1 file changed, 138 insertions(+), 86 deletions(-)
>>
>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>> index 3d670f9..6060bb0 100644
>> --- a/src/qemu/qemu_command.c
>> +++ b/src/qemu/qemu_command.c
>> @@ -1445,10 +1445,15 @@ struct _qemuDomainPCIAddressSet {
>>
>> static bool
>> qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
>> + char *addrStr,
>
> Slight nitpick. const char maybe?
>
>> qemuDomainPCIConnectFlags busFlags,
>> qemuDomainPCIConnectFlags devFlags,
>> - bool reportError)
>> + bool reportError,
>> + bool fromConfig)
>> {
>> + virErrorNumber errType = (fromConfig
>> + ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
>> +
>> /* If this bus doesn't allow the type of connection (PCI
>> * vs. PCIe) required by the device, or if the device requires
>> * hot-plug and this bus doesn't have it, return false.
>> @@ -1456,24 +1461,24 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
>> if (!(devFlags & busFlags & QEMU_PCI_CONNECT_TYPES_MASK)) {
>> if (reportError) {
>> if (devFlags & QEMU_PCI_CONNECT_TYPE_PCI) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR,
>> - _("PCI bus %.4x:%.2x is not compatible with the "
>> - "device. Device requires a standard PCI slot, "
>> - "which is not provided by this bus"),
>> - addr->domain, addr->bus);
>> + virReportError(errType,
>> + _("PCI bus is not compatible with the device "
>> + "at %s. Device requires a standard PCI slot, "
>> + "which is not provided by bus %.4x:%.2x"),
>> + addrStr, addr->domain, addr->bus);
>> } else if (devFlags & QEMU_PCI_CONNECT_TYPE_PCIE) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR,
>> - _("PCI bus %.4x:%.2x is not compatible with the "
>> - "device. Device requires a PCI Express slot, "
>> - "which is not provided by this bus"),
>> - addr->domain, addr->bus);
>> + virReportError(errType,
>> + _("PCI bus is not compatible with the device "
>> + "at %s. Device requires a PCI Express slot, "
>> + "which is not provided by bus %.4x:%.2x"),
>> + addrStr, addr->domain, addr->bus);
>> } else {
>> /* this should never happen. If it does, there is a
>> * bug in the code that sets the flag bits for devices.
>> */
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("The device information has no PCI "
>> - "connection types listed"));
>> + virReportError(errType,
>> + _("The device information for %s has no PCI "
>> + "connection types listed"), addrStr);
>> }
>> }
>> return false;
>> @@ -1481,11 +1486,11 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
>> if ((devFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE) &&
>> !(busFlags & QEMU_PCI_CONNECT_HOTPLUGGABLE)) {
>> if (reportError) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR,
>> - _("PCI bus %.4x:%.2x is not compatible with the "
>> - "device. Device requires hot-plug capability, "
>> - "which is not provided by the bus"),
>> - addr->domain, addr->bus);
>> + virReportError(errType,
>> + _("PCI bus is not compatible with the device "
>> + "at %s. Device requires hot-plug capability, "
>> + "which is not provided by bus %.4x:%.2x"),
>> + addrStr, addr->domain, addr->bus);
>> }
>> return false;
>> }
>> @@ -1500,23 +1505,30 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
>> static bool
>> qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
>> virDevicePCIAddressPtr addr,
>> - qemuDomainPCIConnectFlags flags)
>> + char *addrStr,
>
> Same here? const char?
>
>> + qemuDomainPCIConnectFlags flags,
>> + bool fromConfig)
>> {
>> qemuDomainPCIAddressBusPtr bus;
>> + virErrorNumber errType = (fromConfig
>> + ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
>>
>> if (addrs->nbuses == 0) {
>> - virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
>> + virReportError(errType, "%s", _("No PCI buses available"));
>> return false;
>> }
>> if (addr->domain != 0) {
>> - virReportError(VIR_ERR_XML_ERROR, "%s",
>> - _("Only PCI domain 0 is available"));
>> + virReportError(errType,
>> + _("Invalid PCI address %s. "
>> + "Only PCI domain 0 is available"),
>> + addrStr);
>> return false;
>> }
>> if (addr->bus >= addrs->nbuses) {
>> - virReportError(VIR_ERR_XML_ERROR,
>> - _("Only PCI buses up to %zu are available"),
>> - addrs->nbuses - 1);
>> + virReportError(errType,
>> + _("Invalid PCI address %s. "
>> + "Only PCI buses up to %zu are available"),
>> + addrStr, addrs->nbuses - 1);
>> return false;
>> }
>>
>> @@ -1525,26 +1537,27 @@ qemuDomainPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs,
>> /* assure that at least one of the requested connection types is
>> * provided by this bus
>> */
>> - if (!qemuDomainPCIAddressFlagsCompatible(addr, bus->flags, flags, true))
>> + if (!qemuDomainPCIAddressFlagsCompatible(addr, addrStr, bus->flags,
>> + flags, true, fromConfig))
>> return false;
>>
>> /* some "buses" are really just a single port */
>> if (bus->minSlot && addr->slot < bus->minSlot) {
>> - virReportError(VIR_ERR_XML_ERROR,
>> - _("Invalid PCI address: slot must be >= %zu"),
>> - bus->minSlot);
>> + virReportError(errType,
>> + _("Invalid PCI address %s. slot must be >= %zu"),
>> + addrStr, bus->minSlot);
>> return false;
>> }
>> if (addr->slot > bus->maxSlot) {
>> - virReportError(VIR_ERR_XML_ERROR,
>> - _("Invalid PCI address: slot must be <= %zu"),
>> - bus->maxSlot);
>> + virReportError(errType,
>> + _("Invalid PCI address %s. slot must be <= %zu"),
>> + addrStr, bus->maxSlot);
>> return false;
>> }
>> if (addr->function > QEMU_PCI_ADDRESS_FUNCTION_LAST) {
>> - virReportError(VIR_ERR_XML_ERROR,
>> - _("Invalid PCI address: function must be <= %u"),
>> - QEMU_PCI_ADDRESS_FUNCTION_LAST);
>> + virReportError(errType,
>> + _("Invalid PCI address %s. function must be <= %u"),
>> + addrStr, QEMU_PCI_ADDRESS_FUNCTION_LAST);
>> return false;
>> }
>> return true;
>> @@ -1953,12 +1966,12 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
>> bool fromConfig)
>> {
>> int ret = -1;
>> - char *str = NULL;
>> + char *addrStr = NULL;
>> qemuDomainPCIAddressBusPtr bus;
>> virErrorNumber errType = (fromConfig
>> ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
>>
>> - if (!(str = qemuDomainPCIAddressAsString(addr)))
>> + if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
>> goto cleanup;
>>
>> /* Add an extra bus if necessary */
>> @@ -1967,7 +1980,7 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
>> /* Check that the requested bus exists, is the correct type, and we
>> * are asking for a valid slot
>> */
>> - if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
>> + if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, fromConfig))
>> goto cleanup;
>>
>> bus = &addrs->buses[addr->bus];
>> @@ -1977,31 +1990,32 @@ qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
>> virReportError(errType,
>> _("Attempted double use of PCI slot %s "
>> "(may need \"multifunction='on'\" for "
>> - "device on function 0)"), str);
>> + "device on function 0)"), addrStr);
>> goto cleanup;
>> }
>> bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
>> - VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", str);
>> + VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", addrStr);
>> } else {
>> if (bus->slots[addr->slot] & (1 << addr->function)) {
>> if (addr->function == 0) {
>> virReportError(errType,
>> - _("Attempted double use of PCI Address %s"), str);
>> + _("Attempted double use of PCI Address %s"),
>> + addrStr);
>> } else {
>> virReportError(errType,
>> _("Attempted double use of PCI Address %s "
>> "(may need \"multifunction='on'\" "
>> - "for device on function 0)"), str);
>> + "for device on function 0)"), addrStr);
>> }
>> goto cleanup;
>> }
>> bus->slots[addr->slot] |= (1 << addr->function);
>> - VIR_DEBUG("Reserving PCI address %s", str);
>> + VIR_DEBUG("Reserving PCI address %s", addrStr);
>> }
>>
>> ret = 0;
>> cleanup:
>> - VIR_FREE(str);
>> + VIR_FREE(addrStr);
>> return ret;
>> }
>>
>> @@ -2017,7 +2031,8 @@ qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
>> int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
>> virDomainDeviceInfoPtr dev)
>> {
>> - int ret = 0;
>> + int ret = -1;
>> + char *addrStr = NULL;
>> /* Flags should be set according to the particular device,
>> * but only the caller knows the type of device. Currently this
>> * function is only used for hot-plug, though, and hot-plug is
>> @@ -2026,6 +2041,9 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
>> qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
>> QEMU_PCI_CONNECT_TYPE_PCI);
>>
>> + if (!(addrStr = qemuDomainPCIAddressAsString(&dev->addr.pci)))
>> + goto cleanup;
>> +
>> if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
>> /* We do not support hotplug multi-function PCI device now, so we should
>> * reserve the whole slot. The function of the PCI device must be 0.
>> @@ -2034,16 +2052,20 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("Only PCI device addresses with function=0"
>> " are supported"));
>> - return -1;
>> + goto cleanup;
>> }
>>
>> - if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci, flags))
>> - return -1;
>> + if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci,
>> + addrStr, flags, true))
>> + goto cleanup;
>>
>> ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
>> } else {
>> ret = qemuDomainPCIAddressReserveNextSlot(addrs, dev, flags);
>> }
>> +
>> +cleanup:
>> + VIR_FREE(addrStr);
>> return ret;
>> }
>>
>> @@ -2063,12 +2085,20 @@ qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs,
>> * already had it, and are giving it back.
>> */
>> qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPES_MASK;
>> + int ret = -1;
>> + char *addrStr = NULL;
>>
>> - if (!qemuDomainPCIAddressValidate(addrs, addr, flags))
>> - return -1;
>> + if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
>> + goto cleanup;
>> +
>> + if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, false))
>> + goto cleanup;
>>
>> addrs->buses[addr->bus].slots[addr->slot] = 0;
>> - return 0;
>> + ret = 0;
>> +cleanup:
>> + VIR_FREE(addrStr);
>> + return ret;
>> }
>>
>> void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
>> @@ -2090,6 +2120,7 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
>> * 0000:00:00.0
>> */
>> virDevicePCIAddress a = { 0, 0, 0, 0, false };
>> + char *addrStr = NULL;
>>
>> /* except if this search is for the exact same type of device as
>> * last time, continue the search from the previous match
>> @@ -2099,13 +2130,17 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
>>
>> if (addrs->nbuses == 0) {
>> virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
>> - return -1;
>> + goto error;
>> }
>>
>> /* Start the search at the last used bus and slot */
>> for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
>> - if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
>> - flags, false)) {
>> + addrStr = NULL;
>> + if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
>> + goto error;
>> + if (!qemuDomainPCIAddressFlagsCompatible(&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);
>> continue;
>> @@ -2124,13 +2159,17 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
>> if (addrs->dryRun) {
>> /* a is already set to the first new bus and slot 1 */
>> if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
>> - return -1;
>> + goto error;
>> goto success;
>> } else if (flags == addrs->lastFlags) {
>> /* Check the buses from 0 up to the last used one */
>> for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
>> - if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
>> - flags, false)) {
>> + addrStr = NULL;
>> + if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
>> + goto error;
>> + if (!qemuDomainPCIAddressFlagsCompatible(&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);
>> continue;
>> @@ -2147,12 +2186,15 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
>>
>> 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;
>> }
>>
>> @@ -2217,10 +2259,12 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> virQEMUCapsPtr qemuCaps,
>> qemuDomainPCIAddressSetPtr addrs)
>> {
>> + int ret = -1;
>> size_t i;
>> virDevicePCIAddress tmp_addr;
>> bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
>> virDevicePCIAddressPtr addrptr;
>> + char *addrStr = NULL;
>> qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
>>
>> /* Verify that first IDE and USB controllers (if any) is on the PIIX3, fn 1 */
>> @@ -2235,7 +2279,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> def->controllers[i]->info.addr.pci.function != 1) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("Primary IDE controller must have PCI address 0:0:1.1"));
>> - goto error;
>> + goto cleanup;
>> }
>> } else {
>> def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
>> @@ -2255,7 +2299,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> def->controllers[i]->info.addr.pci.function != 2) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("PIIX3 USB controller must have PCI address 0:0:1.2"));
>> - goto error;
>> + goto cleanup;
>> }
>> } else {
>> def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
>> @@ -2274,7 +2318,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> memset(&tmp_addr, 0, sizeof(tmp_addr));
>> tmp_addr.slot = 1;
>> if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
>> - goto error;
>> + goto cleanup;
>> }
>>
>> if (def->nvideos > 0) {
>> @@ -2293,8 +2337,11 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> primaryVideo->info.addr.pci.function = 0;
>> addrptr = &primaryVideo->info.addr.pci;
>>
>> - if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
>> - goto error;
>> + if (!(addrStr = qemuDomainPCIAddressAsString(addrptr)))
>> + goto cleanup;
>> + if (!qemuDomainPCIAddressValidate(addrs, addrptr,
>> + addrStr, flags, false))
>> + goto cleanup;
>>
>> if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
>> if (qemuDeviceVideoUsable) {
>> @@ -2302,15 +2349,15 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> if (qemuDomainPCIAddressReserveNextSlot(addrs,
>> &primaryVideo->info,
>> flags) < 0)
>> - goto error;
>> + goto cleanup;
>> } else {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("PCI address 0:0:2.0 is in use, "
>> "QEMU needs it for primary video"));
>> - goto error;
>> + goto cleanup;
>> }
>> } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) {
>> - goto error;
>> + goto cleanup;
>> }
>> } else if (!qemuDeviceVideoUsable) {
>> if (primaryVideo->info.addr.pci.domain != 0 ||
>> @@ -2319,7 +2366,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> primaryVideo->info.addr.pci.function != 0) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("Primary video card must have PCI address 0:0:2.0"));
>> - goto error;
>> + goto cleanup;
>> }
>> /* If TYPE==PCI, then qemuCollectPCIAddress() function
>> * has already reserved the address, so we must skip */
>> @@ -2334,13 +2381,13 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
>> " intervention");
>> virResetLastError();
>> } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
>> - goto error;
>> + goto cleanup;
>> }
>> }
>> - return 0;
>> -
>> -error:
>> - return -1;
>> + ret = 0;
>> +cleanup:
>> + VIR_FREE(addrStr);
>> + return ret;
>> }
>>
>>
>> @@ -2357,10 +2404,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> virQEMUCapsPtr qemuCaps,
>> qemuDomainPCIAddressSetPtr addrs)
>> {
>> + int ret = -1;
>> size_t i;
>> virDevicePCIAddress tmp_addr;
>> bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
>> virDevicePCIAddressPtr addrptr;
>> + char *addrStr = NULL;
>> qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCIE;
>>
>> /* Verify that the first SATA controller is at 00:1F.2 */
>> @@ -2375,7 +2424,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> def->controllers[i]->info.addr.pci.function != 2) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("Primary SATA controller must have PCI address 0:0:1f.2"));
>> - goto error;
>> + goto cleanup;
>> }
>> } else {
>> def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
>> @@ -2399,12 +2448,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> tmp_addr.multi = 1;
>> if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
>> false, false) < 0)
>> - goto error;
>> + goto cleanup;
>> tmp_addr.function = 3;
>> tmp_addr.multi = 0;
>> if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
>> false, false) < 0)
>> - goto error;
>> + goto cleanup;
>> }
>>
>> if (def->nvideos > 0) {
>> @@ -2423,8 +2472,11 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> primaryVideo->info.addr.pci.function = 0;
>> addrptr = &primaryVideo->info.addr.pci;
>>
>> - if (!qemuDomainPCIAddressValidate(addrs, addrptr, flags))
>> - goto error;
>> + if (!(addrStr = qemuDomainPCIAddressAsString(addrptr)))
>> + goto cleanup;
>> + if (!qemuDomainPCIAddressValidate(addrs, addrptr,
>> + addrStr, flags, false))
>> + goto cleanup;
>>
>> if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) {
>> if (qemuDeviceVideoUsable) {
>> @@ -2432,15 +2484,15 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> if (qemuDomainPCIAddressReserveNextSlot(addrs,
>> &primaryVideo->info,
>> flags) < 0)
>> - goto error;
>> + goto cleanup;
>> } else {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("PCI address 0:0:1.0 is in use, "
>> "QEMU needs it for primary video"));
>> - goto error;
>> + goto cleanup;
>> }
>> } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) {
>> - goto error;
>> + goto cleanup;
>> }
>> } else if (!qemuDeviceVideoUsable) {
>> if (primaryVideo->info.addr.pci.domain != 0 ||
>> @@ -2449,7 +2501,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> primaryVideo->info.addr.pci.function != 0) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> _("Primary video card must have PCI address 0:0:1.0"));
>> - goto error;
>> + goto cleanup;
>> }
>> /* If TYPE==PCI, then qemuCollectPCIAddress() function
>> * has already reserved the address, so we must skip */
>> @@ -2464,13 +2516,13 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
>> " intervention");
>> virResetLastError();
>> } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
>> - goto error;
>> + goto cleanup;
>> }
>> }
>> - return 0;
>> -
>> -error:
>> - return -1;
>> + ret = 0;
>> +cleanup:
>> + VIR_FREE(addrStr);
>> + return ret;
>> }
>>
>>
>> --
>> 1.7.11.7
>>
>
> Other than my slight nitpick, visually this looks good. I'll give it a
> whirl with some of my bad configs tonight.
>
> --
> Doug Goldstein
Works as expected.
error: Failed to define domain from error.xml
error: XML error: PCI bus is not compatible with the device at
0000:00:04.0. Device requires a standard PCI slot, which is not
provided by bus 0000:00
--
Doug Goldstein
More information about the libvir-list
mailing list