[libvirt] [PATCH] Add persistence of PCI addresses to QEMU
Daniel Veillard
veillard at redhat.com
Fri Feb 12 11:05:39 UTC 2010
On Thu, Feb 11, 2010 at 04:40:43PM +0000, Daniel P. Berrange wrote:
> 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 */
But where would we store them ? It sounds a bit strange, it's emulator
properties, not really domain ones, and I think we sound only store in
the domain what specific flags might be needed from the emulator, not
the full set (and this could change over time as a domain is being
modified).
> + 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;
> + }
do we really need to update that every time ? We can't cache forever
but it's not like the emulator is changing every second. Maybe we need
to put a watch on the emulator at the driver level and keep this in
the driver.
> + 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))) {
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