[libvirt] [PATCH v2 8/8] qemu: Fix some corner cases in persistent migration
John Ferlan
jferlan at redhat.com
Thu Sep 17 22:40:59 UTC 2015
On 09/11/2015 09:26 AM, Jiri Denemark wrote:
> When persistently migrating a domain to a destination host where the
> same domain already exists (i.e., it is persistent and shutdown at the
> destination), we would happily through away the original persistent
s/through/throw
> definition without properly freeing it. And when updating the definition
> fails for some reason we don't properly revert to the original state
> leaving the domain broken.
>
> In addition to fixing these issues, the patch also makes sure the domain
> definition parsed from a migration cookie is either used or freed.
>
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
>
> Notes:
> Version 2:
> - new patch
>
> src/qemu/qemu_migration.c | 56 +++++++++++++++++++++++++++++++----------------
> 1 file changed, 37 insertions(+), 19 deletions(-)
>
Ran using my Coverity checker...
One issue - in qemuMigrationPersist can get to 'cleanup:' calling
qemuMigrationCookieGetPersistent when 'mig == NULL' from either the goto
in the "if (!qemuMigrationJobIsActive(vm...)" or "if (!(mig =
qemuMigrationEatCookie(driver, ..." paths
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index c761657..1d556eb 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -525,6 +525,19 @@ qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig,
> }
>
>
> +static virDomainDefPtr
> +qemuMigrationCookieGetPersistent(qemuMigrationCookiePtr mig)
> +{
> + virDomainDefPtr def = mig->persistent;
> +
> + mig->persistent = NULL;
> + mig->flags &= ~QEMU_MIGRATION_COOKIE_PERSISTENT;
> + mig->flagsMandatory &= ~QEMU_MIGRATION_COOKIE_PERSISTENT;
> +
> + return def;
> +}
> +
> +
> static int
> qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
> virQEMUDriverPtr driver,
> @@ -5554,47 +5567,51 @@ qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def)
> static int
> qemuMigrationPersist(virQEMUDriverPtr driver,
> virDomainObjPtr vm,
> - qemuMigrationCookiePtr mig)
> + qemuMigrationCookiePtr mig,
> + bool ignoreSaveError)
> {
> virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
> virCapsPtr caps = NULL;
> virDomainDefPtr vmdef;
> + virDomainDefPtr oldDef = NULL;
> + unsigned int oldPersist = vm->persistent;
> virObjectEventPtr event;
> - bool newVM;
> int ret = -1;
>
> if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
> goto cleanup;
>
> - newVM = !vm->persistent;
> vm->persistent = 1;
> + oldDef = vm->newDef;
> + vm->newDef = qemuMigrationCookieGetPersistent(mig);
>
> - if (mig->persistent)
> - vm->newDef = mig->persistent;
> + if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm)))
> + goto error;
>
> - vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm);
> - if (!vmdef) {
> - if (newVM)
> - vm->persistent = 0;
> - goto cleanup;
> - }
> -
> - if (virDomainSaveConfig(cfg->configDir, vmdef) < 0)
> - goto cleanup;
> + if (virDomainSaveConfig(cfg->configDir, vmdef) < 0 && !ignoreSaveError)
> + goto error;
>
> event = virDomainEventLifecycleNewFromObj(vm,
> VIR_DOMAIN_EVENT_DEFINED,
> - newVM ?
> - VIR_DOMAIN_EVENT_DEFINED_ADDED :
> - VIR_DOMAIN_EVENT_DEFINED_UPDATED);
> + oldPersist ?
> + VIR_DOMAIN_EVENT_DEFINED_UPDATED :
> + VIR_DOMAIN_EVENT_DEFINED_ADDED);
> qemuDomainEventQueue(driver, event);
>
> ret = 0;
>
> cleanup:
> + virDomainDefFree(oldDef);
> virObjectUnref(caps);
> virObjectUnref(cfg);
> return ret;
> +
> + error:
> + virDomainDefFree(vm->newDef);
> + vm->persistent = oldPersist;
This set of changes resolves what I pointed out in patch 1 regarding
setting vm->persistent
> + vm->newDef = oldDef;
> + oldDef = NULL;
> + goto cleanup;
> }
>
>
> @@ -5653,7 +5670,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> */
> if (flags & VIR_MIGRATE_OFFLINE) {
> if (retcode != 0 ||
> - qemuMigrationPersist(driver, vm, mig) < 0)
> + qemuMigrationPersist(driver, vm, mig, false) < 0)
> goto endjob;
>
> dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
> @@ -5685,7 +5702,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> goto endjob;
>
> if (flags & VIR_MIGRATE_PERSIST_DEST) {
> - if (qemuMigrationPersist(driver, vm, mig) < 0) {
> + if (qemuMigrationPersist(driver, vm, mig, !v3proto) < 0) {
> /* Hmpf. Migration was successful, but making it persistent
> * was not. If we report successful, then when this domain
> * shuts down, management tools are in for a surprise. On the
> @@ -5796,6 +5813,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> qemuMonitorSetDomainLog(priv->mon, -1);
> VIR_FREE(priv->origname);
> virDomainObjEndAPI(&vm);
> + virDomainDefFree(qemuMigrationCookieGetPersistent(mig));
If this has a "if (mig)", then Coverity is happy.
ACK with the adjustment
John
> qemuMigrationCookieFree(mig);
> if (orig_err) {
> virSetError(orig_err);
>
More information about the libvir-list
mailing list