[libvirt] [PATCH] Fix restore of QEMU guests with PCI device reservation
Daniel Veillard
veillard at redhat.com
Wed Feb 3 16:43:42 UTC 2010
On Wed, Feb 03, 2010 at 04:32:47PM +0000, Daniel P. Berrange wrote:
> When restoring from a saved guest image, the XML would already
> contain the PCI slot ID of the IDE controller & video card.
> The attempt to explicitly reserve this upfront would thus fail
> everytime.
>
> slot at time of need, rather than upfront
> ---
> src/qemu/qemu_conf.c | 83 ++++++++++++++++++++++++++++++++++++++------------
> 1 files changed, 63 insertions(+), 20 deletions(-)
>
> diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
> index 389db7b..3d83a8f 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -1797,6 +1797,13 @@ static char *qemuPCIAddressAsString(virDomainDeviceInfoPtr dev)
> {
> char *addr;
>
> + if (dev->addr.pci.domain != 0 ||
> + dev->addr.pci.bus != 0) {
> + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Only PCI domain 0 and bus 0 are available"));
> + return NULL;
> + }
> +
> if (virAsprintf(&addr, "%d:%d:%d",
> dev->addr.pci.domain,
> dev->addr.pci.bus,
> @@ -1817,6 +1824,8 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
> if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> char *addr = qemuPCIAddressAsString(dev);
>
> + VIR_DEBUG("Remembering PCI addr %s", addr);
> +
> if (virHashAddEntry(addrs->used, addr, addr) < 0) {
> VIR_FREE(addr);
> return -1;
> @@ -1858,6 +1867,8 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
> if (!addr)
> return -1;
>
> + VIR_DEBUG("Reserving PCI addr %s", addr);
> +
> if (virHashLookup(addrs->used, addr)) {
> qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> _("unable to reserve PCI address %s"), addr);
> @@ -1870,6 +1881,9 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
> return -1;
> }
>
> + if (dev->addr.pci.slot > addrs->nextslot)
> + addrs->nextslot = dev->addr.pci.slot + 1;
> +
> return 0;
> }
>
> @@ -1947,6 +1961,8 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
>
> addr = qemuPCIAddressAsString(&maybe);
>
> + VIR_DEBUG("Allocating PCI addr %s", addr);
> +
> if (virHashLookup(addrs->used, addr)) {
> VIR_FREE(addr);
> continue;
> @@ -1981,12 +1997,13 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
> /* Host bridge */
> if (qemuDomainPCIAddressReserveSlot(addrs, 0) < 0)
> goto error;
> - /* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller) */
> - if (qemuDomainPCIAddressReserveSlot(addrs, 1) < 0)
> - goto error;
> - /* VGA */
> - if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0)
> - goto error;
> +
> + /* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller)
> + * at slot 1....reserve it later
> + */
> +
> + /* VGA at slot 2.... reserve it later */
> +
> /* VirtIO Balloon */
> if (qemuDomainPCIAddressReserveSlot(addrs, 3) < 0)
> goto error;
> @@ -2033,23 +2050,34 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
> goto error;
> }
> for (i = 0; i < def->nvideos ; i++) {
> - if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> - continue;
> /* First VGA is hardcoded slot=2 */
> if (i == 0) {
> - def->videos[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
> - def->videos[i]->info.addr.pci.domain = 0;
> - def->videos[i]->info.addr.pci.bus = 0;
> - def->videos[i]->info.addr.pci.slot = 2;
> - def->videos[i]->info.addr.pci.function = 0;
> + if (def->videos[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> + if (def->videos[i]->info.addr.pci.domain != 0 ||
> + def->videos[i]->info.addr.pci.bus != 0 ||
> + def->videos[i]->info.addr.pci.slot != 2 ||
> + def->videos[i]->info.addr.pci.function != 0) {
> + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Primary video card must have PCI address 0:0:2.0"));
> + goto error;
> + }
> + } else {
> + def->videos[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
> + def->videos[i]->info.addr.pci.domain = 0;
> + def->videos[i]->info.addr.pci.bus = 0;
> + def->videos[i]->info.addr.pci.slot = 2;
> + def->videos[i]->info.addr.pci.function = 0;
> + if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0)
> + goto error;
> + }
Ah, okay, understood ...
> } else {
> + if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> + continue;
> if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info) < 0)
> goto error;
> }
> }
> for (i = 0; i < def->ncontrollers ; i++) {
> - if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> - continue;
> /* FDC lives behind the ISA bridge */
> if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC)
> continue;
> @@ -2057,12 +2085,27 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
> /* First IDE controller lives on the PIIX3 at slot=1, function=1 */
> if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
> def->controllers[i]->idx == 0) {
> - def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
> - def->controllers[i]->info.addr.pci.domain = 0;
> - def->controllers[i]->info.addr.pci.bus = 0;
> - def->controllers[i]->info.addr.pci.slot = 1;
> - def->controllers[i]->info.addr.pci.function = 1;
> + if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> + if (def->videos[i]->info.addr.pci.domain != 0 ||
> + def->videos[i]->info.addr.pci.bus != 0 ||
> + def->videos[i]->info.addr.pci.slot != 2 ||
> + def->videos[i]->info.addr.pci.function != 0) {
> + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Primary IDE controller must have PCI address 0:0:1.1"));
> + goto error;
> + }
> + } else {
> + def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
> + def->controllers[i]->info.addr.pci.domain = 0;
> + def->controllers[i]->info.addr.pci.bus = 0;
> + def->controllers[i]->info.addr.pci.slot = 1;
> + def->controllers[i]->info.addr.pci.function = 1;
> + if (qemuDomainPCIAddressReserveSlot(addrs, 1) < 0)
> + goto error;
> + }
> } else {
> + if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> + continue;
> if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0)
> goto error;
> }
Okay, ACK !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list