|
|
5ff110 |
From f01aeffaa7dbb4e9efe61f9826deed14c4cb3b41 Mon Sep 17 00:00:00 2001
|
|
|
5ff110 |
Message-Id: <f01aeffaa7dbb4e9efe61f9826deed14c4cb3b41@dist-git>
|
|
|
5ff110 |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
5ff110 |
Date: Wed, 12 Sep 2018 14:34:33 +0200
|
|
|
5ff110 |
Subject: [PATCH] qemu: Avoid duplicate resume events and state changes
|
|
|
5ff110 |
MIME-Version: 1.0
|
|
|
5ff110 |
Content-Type: text/plain; charset=UTF-8
|
|
|
5ff110 |
Content-Transfer-Encoding: 8bit
|
|
|
5ff110 |
|
|
|
5ff110 |
The only place where VIR_DOMAIN_EVENT_RESUMED should be generated is the
|
|
|
5ff110 |
RESUME event handler to make sure we don't generate duplicate events or
|
|
|
5ff110 |
state changes. In the worse case the duplicity can revert or cover
|
|
|
5ff110 |
changes done by other event handlers.
|
|
|
5ff110 |
|
|
|
5ff110 |
For example, after QEMU sent RESUME, BLOCK_IO_ERROR, and STOP events
|
|
|
5ff110 |
we could happily mark the domain as running and report
|
|
|
5ff110 |
VIR_DOMAIN_EVENT_RESUMED to registered clients.
|
|
|
5ff110 |
|
|
|
5ff110 |
https://bugzilla.redhat.com/show_bug.cgi?id=1612943
|
|
|
5ff110 |
|
|
|
5ff110 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
5ff110 |
Reviewed-by: John Ferlan <jferlan@redhat.com>
|
|
|
5ff110 |
(cherry picked from commit e6d77a75c4bf0c017d62b717b75e4bb6aa7a456b)
|
|
|
5ff110 |
|
|
|
5ff110 |
https://bugzilla.redhat.com/show_bug.cgi?id=1634758
|
|
|
5ff110 |
https://bugzilla.redhat.com/show_bug.cgi?id=1634759
|
|
|
5ff110 |
|
|
|
5ff110 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
5ff110 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
5ff110 |
---
|
|
|
5ff110 |
src/qemu/qemu_driver.c | 13 -----------
|
|
|
5ff110 |
src/qemu/qemu_migration.c | 49 ++++++++++++++++-----------------------
|
|
|
5ff110 |
src/qemu/qemu_process.c | 10 ++++----
|
|
|
5ff110 |
3 files changed, 24 insertions(+), 48 deletions(-)
|
|
|
5ff110 |
|
|
|
5ff110 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
5ff110 |
index 26aa557d9f..295613ba3c 100644
|
|
|
5ff110 |
--- a/src/qemu/qemu_driver.c
|
|
|
5ff110 |
+++ b/src/qemu/qemu_driver.c
|
|
|
5ff110 |
@@ -1863,7 +1863,6 @@ static int qemuDomainResume(virDomainPtr dom)
|
|
|
5ff110 |
virQEMUDriverPtr driver = dom->conn->privateData;
|
|
|
5ff110 |
virDomainObjPtr vm;
|
|
|
5ff110 |
int ret = -1;
|
|
|
5ff110 |
- virObjectEventPtr event = NULL;
|
|
|
5ff110 |
int state;
|
|
|
5ff110 |
int reason;
|
|
|
5ff110 |
virQEMUDriverConfigPtr cfg = NULL;
|
|
|
5ff110 |
@@ -1902,9 +1901,6 @@ static int qemuDomainResume(virDomainPtr dom)
|
|
|
5ff110 |
"%s", _("resume operation failed"));
|
|
|
5ff110 |
goto endjob;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
5ff110 |
}
|
|
|
5ff110 |
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
|
|
5ff110 |
goto endjob;
|
|
|
5ff110 |
@@ -1915,7 +1911,6 @@ static int qemuDomainResume(virDomainPtr dom)
|
|
|
5ff110 |
|
|
|
5ff110 |
cleanup:
|
|
|
5ff110 |
virDomainObjEndAPI(&vm;;
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
virObjectUnref(cfg);
|
|
|
5ff110 |
return ret;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
@@ -16031,7 +16026,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
5ff110 |
virDomainDefPtr config = NULL;
|
|
|
5ff110 |
virQEMUDriverConfigPtr cfg = NULL;
|
|
|
5ff110 |
virCapsPtr caps = NULL;
|
|
|
5ff110 |
- bool was_running = false;
|
|
|
5ff110 |
bool was_stopped = false;
|
|
|
5ff110 |
qemuDomainSaveCookiePtr cookie;
|
|
|
5ff110 |
virCPUDefPtr origCPU = NULL;
|
|
|
5ff110 |
@@ -16222,7 +16216,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
5ff110 |
priv = vm->privateData;
|
|
|
5ff110 |
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
|
|
5ff110 |
/* Transitions 5, 6 */
|
|
|
5ff110 |
- was_running = true;
|
|
|
5ff110 |
if (qemuProcessStopCPUs(driver, vm,
|
|
|
5ff110 |
VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
|
|
|
5ff110 |
QEMU_ASYNC_JOB_START) < 0)
|
|
|
5ff110 |
@@ -16319,12 +16312,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
|
|
|
5ff110 |
event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
VIR_DOMAIN_EVENT_STARTED,
|
|
|
5ff110 |
detail);
|
|
|
5ff110 |
- } else if (!was_running) {
|
|
|
5ff110 |
- /* Transition 8 */
|
|
|
5ff110 |
- detail = VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT;
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- detail);
|
|
|
5ff110 |
}
|
|
|
5ff110 |
}
|
|
|
5ff110 |
break;
|
|
|
5ff110 |
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
|
|
5ff110 |
index 825a9d399b..67940330aa 100644
|
|
|
5ff110 |
--- a/src/qemu/qemu_migration.c
|
|
|
5ff110 |
+++ b/src/qemu/qemu_migration.c
|
|
|
5ff110 |
@@ -2982,14 +2982,10 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver,
|
|
|
5ff110 |
virFreeError(orig_err);
|
|
|
5ff110 |
|
|
|
5ff110 |
if (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
|
|
|
5ff110 |
- reason == VIR_DOMAIN_PAUSED_POSTCOPY) {
|
|
|
5ff110 |
+ reason == VIR_DOMAIN_PAUSED_POSTCOPY)
|
|
|
5ff110 |
qemuMigrationAnyPostcopyFailed(driver, vm);
|
|
|
5ff110 |
- } else if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
- }
|
|
|
5ff110 |
+ else
|
|
|
5ff110 |
+ qemuMigrationSrcRestoreDomainState(driver, vm);
|
|
|
5ff110 |
|
|
|
5ff110 |
qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
|
|
|
5ff110 |
priv->job.migParams, priv->job.apiFlags);
|
|
|
5ff110 |
@@ -4624,11 +4620,7 @@ qemuMigrationSrcPerformJob(virQEMUDriverPtr driver,
|
|
|
5ff110 |
qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
|
|
|
5ff110 |
priv->job.migParams, priv->job.apiFlags);
|
|
|
5ff110 |
|
|
|
5ff110 |
- if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
|
|
5ff110 |
- }
|
|
|
5ff110 |
+ qemuMigrationSrcRestoreDomainState(driver, vm);
|
|
|
5ff110 |
|
|
|
5ff110 |
qemuMigrationJobFinish(driver, vm);
|
|
|
5ff110 |
if (!virDomainObjIsActive(vm) && ret == 0) {
|
|
|
5ff110 |
@@ -4672,7 +4664,6 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
|
|
|
5ff110 |
unsigned long resource)
|
|
|
5ff110 |
{
|
|
|
5ff110 |
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
5ff110 |
- virObjectEventPtr event = NULL;
|
|
|
5ff110 |
int ret = -1;
|
|
|
5ff110 |
|
|
|
5ff110 |
/* If we didn't start the job in the begin phase, start it now. */
|
|
|
5ff110 |
@@ -4694,11 +4685,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
|
|
|
5ff110 |
nmigrate_disks, migrate_disks, migParams);
|
|
|
5ff110 |
|
|
|
5ff110 |
if (ret < 0) {
|
|
|
5ff110 |
- if (qemuMigrationSrcRestoreDomainState(driver, vm)) {
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
|
|
5ff110 |
- }
|
|
|
5ff110 |
+ qemuMigrationSrcRestoreDomainState(driver, vm);
|
|
|
5ff110 |
goto endjob;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
|
|
|
5ff110 |
@@ -4722,7 +4709,6 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver,
|
|
|
5ff110 |
|
|
|
5ff110 |
cleanup:
|
|
|
5ff110 |
virDomainObjEndAPI(&vm;;
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
return ret;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
|
|
|
5ff110 |
@@ -5074,13 +5060,8 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
|
|
|
5ff110 |
goto endjob;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
|
|
|
5ff110 |
- if (inPostCopy) {
|
|
|
5ff110 |
+ if (inPostCopy)
|
|
|
5ff110 |
doKill = false;
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_POSTCOPY);
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
- }
|
|
|
5ff110 |
}
|
|
|
5ff110 |
|
|
|
5ff110 |
if (mig->jobInfo) {
|
|
|
5ff110 |
@@ -5111,10 +5092,20 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
|
|
|
5ff110 |
|
|
|
5ff110 |
dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, vm->def->id);
|
|
|
5ff110 |
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
+ if (inPostCopy) {
|
|
|
5ff110 |
+ /* The only RESUME event during post-copy migration is triggered by
|
|
|
5ff110 |
+ * QEMU when the running domain moves from the source to the
|
|
|
5ff110 |
+ * destination host, but then the migration keeps running until all
|
|
|
5ff110 |
+ * modified memory is transferred from the source host. This will
|
|
|
5ff110 |
+ * result in VIR_DOMAIN_EVENT_RESUMED with RESUMED_POSTCOPY detail.
|
|
|
5ff110 |
+ * However, our API documentation says we need to fire another RESUMED
|
|
|
5ff110 |
+ * event at the very end of migration with RESUMED_MIGRATED detail.
|
|
|
5ff110 |
+ */
|
|
|
5ff110 |
+ event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
+ VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
+ VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
|
|
5ff110 |
+ virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
+ }
|
|
|
5ff110 |
|
|
|
5ff110 |
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
|
|
5ff110 |
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
|
|
5ff110 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
5ff110 |
index 37568165b7..2d51c0fa25 100644
|
|
|
5ff110 |
--- a/src/qemu/qemu_process.c
|
|
|
5ff110 |
+++ b/src/qemu/qemu_process.c
|
|
|
5ff110 |
@@ -436,7 +436,6 @@ qemuProcessFakeReboot(void *opaque)
|
|
|
5ff110 |
virDomainObjPtr vm = opaque;
|
|
|
5ff110 |
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
5ff110 |
virQEMUDriverPtr driver = priv->driver;
|
|
|
5ff110 |
- virObjectEventPtr event = NULL;
|
|
|
5ff110 |
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
|
|
5ff110 |
virDomainRunningReason reason = VIR_DOMAIN_RUNNING_BOOTED;
|
|
|
5ff110 |
int ret = -1, rc;
|
|
|
5ff110 |
@@ -473,9 +472,6 @@ qemuProcessFakeReboot(void *opaque)
|
|
|
5ff110 |
goto endjob;
|
|
|
5ff110 |
}
|
|
|
5ff110 |
priv->gotShutdown = false;
|
|
|
5ff110 |
- event = virDomainEventLifecycleNewFromObj(vm,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED,
|
|
|
5ff110 |
- VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
5ff110 |
|
|
|
5ff110 |
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
|
|
|
5ff110 |
VIR_WARN("Unable to save status on vm %s after state change",
|
|
|
5ff110 |
@@ -491,7 +487,6 @@ qemuProcessFakeReboot(void *opaque)
|
|
|
5ff110 |
if (ret == -1)
|
|
|
5ff110 |
ignore_value(qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE));
|
|
|
5ff110 |
virDomainObjEndAPI(&vm;;
|
|
|
5ff110 |
- virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
5ff110 |
virObjectUnref(cfg);
|
|
|
5ff110 |
}
|
|
|
5ff110 |
|
|
|
5ff110 |
@@ -3073,7 +3068,10 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
|
|
|
5ff110 |
if (ret < 0)
|
|
|
5ff110 |
goto release;
|
|
|
5ff110 |
|
|
|
5ff110 |
- virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
|
|
|
5ff110 |
+ /* The RESUME event handler will change the domain state with the reason
|
|
|
5ff110 |
+ * saved in priv->runningReason and it will also emit corresponding domain
|
|
|
5ff110 |
+ * lifecycle event.
|
|
|
5ff110 |
+ */
|
|
|
5ff110 |
|
|
|
5ff110 |
cleanup:
|
|
|
5ff110 |
virObjectUnref(cfg);
|
|
|
5ff110 |
--
|
|
|
5ff110 |
2.19.1
|
|
|
5ff110 |
|