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