Current PCI addresses are allocated at time of VM startup. To make them truely persistent, it is neccessary to do this at time of virDomainDefine/virDomainCreate. The code in qemuStartVMDaemon still remains in order to cope with upgrades from older libvirt releases * src/qemu/qemu_driver.c: Rename existing qemuAssignPCIAddresses to qemuDetectPCIAddresses. Add new qemuAssignPCIAddresses which does auto-allocation upfront. Call qemuAssignPCIAddresses from qemuDomainDefine and qemuDomainCreate to assign PCI addresses that can then be persisted. Don't clear PCI addresses at shutdown if they are intended to be persistent --- src/qemu/qemu_driver.c | 84 +++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 03d0f5f..69187fc 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -95,6 +95,7 @@ struct _qemuDomainObjPrivate { int *vcpupids; qemuDomainPCIAddressSetPtr pciaddrs; + int persistentAddrs; }; static int qemudShutdown(void); @@ -857,6 +858,7 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq virDomainObjPtr obj = payload; struct qemud_driver *driver = opaque; qemuDomainObjPrivatePtr priv; + unsigned long long qemuCmdFlags; virDomainObjLock(obj); @@ -872,6 +874,15 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq goto error; } + /* XXX we should be persisting the original flags in the XML + * not re-detecting them, since the binary may have changed + * since launch time */ + if (qemudExtractVersionInfo(obj->def->emulator, + NULL, + &qemuCmdFlags) >= 0 && + (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) + priv->persistentAddrs = 1; + if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(obj->def))) goto error; @@ -1976,7 +1987,7 @@ qemuGetPCIWatchdogVendorProduct(virDomainWatchdogDefPtr def, * some static addrs on CLI. Have to check that... */ static int -qemuAssignPCIAddresses(virDomainObjPtr vm, +qemuDetectPCIAddresses(virDomainObjPtr vm, qemuMonitorPCIAddress *addrs, int naddrs) { @@ -2098,7 +2109,7 @@ qemuInitPCIAddresses(struct qemud_driver *driver, &addrs); qemuDomainObjExitMonitorWithDriver(driver, vm); - ret = qemuAssignPCIAddresses(vm, addrs, naddrs); + ret = qemuDetectPCIAddresses(vm, addrs, naddrs); VIR_FREE(addrs); @@ -2141,6 +2152,44 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) { return -1; } + +static int +qemuAssignPCIAddresses(virDomainDefPtr def) +{ + int ret = -1; + unsigned long long qemuCmdFlags = 0; + qemuDomainPCIAddressSetPtr addrs = NULL; + struct stat sb; + + if (stat(def->emulator, &sb) < 0) { + virReportSystemError(errno, + _("Cannot find QEMU binary %s"), + def->emulator); + goto cleanup; + } + + if (qemudExtractVersionInfo(def->emulator, + NULL, + &qemuCmdFlags) < 0) + goto cleanup; + + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { + if (!(addrs = qemuDomainPCIAddressSetCreate(def))) + goto cleanup; + + if (qemuAssignDevicePCISlots(def, addrs) < 0) + goto cleanup; + } + + ret = 0; + +cleanup: + qemuDomainPCIAddressSetFree(addrs); + + return ret; +} + + static pciDeviceList * qemuGetPciHostDeviceList(virDomainDefPtr def) { @@ -2662,7 +2711,15 @@ static int qemudStartVMDaemon(virConnectPtr conn, goto cleanup; } + /* + * Normally PCI addresses are assigned inhe virDomainCreate + * or virDomainDefine methods. We might still need to assign + * some here to cope with the question of upgrades. Regardless + * we also need to populate the PCi address set cache for later + * use in hotplug + */ if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { + /* Populate cache with current addresses */ if (priv->pciaddrs) { qemuDomainPCIAddressSetFree(priv->pciaddrs); priv->pciaddrs = NULL; @@ -2670,8 +2727,14 @@ static int qemudStartVMDaemon(virConnectPtr conn, if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(vm->def))) goto cleanup; + + /* Assign any remaining addresses */ if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs) < 0) goto cleanup; + + priv->persistentAddrs = 1; + } else { + priv->persistentAddrs = 0; } vm->def->id = driver->nextvmid++; @@ -2903,10 +2966,12 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, VIR_FREE(vm->def->seclabel.imagelabel); } - virDomainDefClearPCIAddresses(vm->def); virDomainDefClearDeviceAliases(vm->def); - qemuDomainPCIAddressSetFree(priv->pciaddrs); - priv->pciaddrs = NULL; + if (!priv->persistentAddrs) { + virDomainDefClearPCIAddresses(vm->def); + qemuDomainPCIAddressSetFree(priv->pciaddrs); + priv->pciaddrs = NULL; + } qemuDomainReAttachHostDevices(driver, vm->def); @@ -3352,6 +3417,12 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) goto cleanup; + if (qemudCanonicalizeMachine(driver, def) < 0) + goto cleanup; + + if (qemuAssignPCIAddresses(def) < 0) + goto cleanup; + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def))) @@ -5049,6 +5120,9 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { if (qemudCanonicalizeMachine(driver, def) < 0) goto cleanup; + if (qemuAssignPCIAddresses(def) < 0) + goto cleanup; + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def))) { -- 1.6.5.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list