edecca
From 91a37e3641afbd29067cd945ca14a6572e4d4897 Mon Sep 17 00:00:00 2001
edecca
Message-Id: <91a37e3641afbd29067cd945ca14a6572e4d4897@dist-git>
edecca
From: Jiri Denemark <jdenemar@redhat.com>
edecca
Date: Thu, 15 Nov 2018 11:16:43 +0100
edecca
Subject: [PATCH] qemu: Fix post-copy migration on the source
edecca
MIME-Version: 1.0
edecca
Content-Type: text/plain; charset=UTF-8
edecca
Content-Transfer-Encoding: 8bit
edecca
edecca
Post-copy migration has been broken on the source since commit
edecca
v3.8.0-245-g32c29f10db which implemented support for
edecca
pause-before-switchover QEMU migration capability.
edecca
edecca
Even though the migration itself went well, the source did not really
edecca
know when it switched to the post-copy mode despite the messages logged
edecca
by MIGRATION event handler. As a result of this, the events emitted by
edecca
source libvirtd were not accurate and statistics of the completed
edecca
migration would cover only the pre-copy part of migration. Moreover, if
edecca
migration failed during the post-copy phase for some reason, the source
edecca
libvirtd would just happily resume the domain, which could lead to disk
edecca
corruption.
edecca
edecca
With the pause-before-switchover capability enabled, the order of events
edecca
emitted by QEMU changed:
edecca
edecca
                    pause-before-switchover
edecca
           disabled                        enabled
edecca
    MIGRATION, postcopy-active      STOP
edecca
    STOP                            MIGRATION, pre-switchover
edecca
                                    MIGRATION, postcopy-active
edecca
edecca
The STOP even handler checks the migration status (postcopy-active) and
edecca
sets the domain state accordingly. Which is sufficient when
edecca
pause-before-switchover is disabled, but once we enable it, the
edecca
migration status is still active when we get STOP from QEMU. Thus the
edecca
domain state set in the STOP handler has to be corrected once we are
edecca
notified that migration changed to postcopy-active.
edecca
edecca
This results in two SUSPENDED events to be emitted by the source
edecca
libvirtd during post-copy migration. The first one with
edecca
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED detail, while the second one reports
edecca
the corrected VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY detail. This is
edecca
inevitable because we don't know whether migration will eventually
edecca
switch to post-copy at the time we emit the first event.
edecca
edecca
https://bugzilla.redhat.com/show_bug.cgi?id=1647365
edecca
edecca
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
edecca
Reviewed-by: Ján Tomko <jtomko@redhat.com>
edecca
(cherry picked from commit eca9d21e6cc8129ec4426fbf1ace30e215b9cfbc)
edecca
edecca
https://bugzilla.redhat.com/show_bug.cgi?id=1649169
edecca
https://bugzilla.redhat.com/show_bug.cgi?id=1654732
edecca
edecca
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
edecca
---
edecca
 src/qemu/qemu_process.c | 26 +++++++++++++++++++++++++-
edecca
 1 file changed, 25 insertions(+), 1 deletion(-)
edecca
edecca
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
edecca
index 4b99fbd835..2d2954ba18 100644
edecca
--- a/src/qemu/qemu_process.c
edecca
+++ b/src/qemu/qemu_process.c
edecca
@@ -1522,9 +1522,13 @@ static int
edecca
 qemuProcessHandleMigrationStatus(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
edecca
                                  virDomainObjPtr vm,
edecca
                                  int status,
edecca
-                                 void *opaque ATTRIBUTE_UNUSED)
edecca
+                                 void *opaque)
edecca
 {
edecca
     qemuDomainObjPrivatePtr priv;
edecca
+    virQEMUDriverPtr driver = opaque;
edecca
+    virObjectEventPtr event = NULL;
edecca
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
edecca
+    int reason;
edecca
 
edecca
     virObjectLock(vm);
edecca
 
edecca
@@ -1541,8 +1545,28 @@ qemuProcessHandleMigrationStatus(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
edecca
     priv->job.current->stats.mig.status = status;
edecca
     virDomainObjBroadcast(vm);
edecca
 
edecca
+    if (status == QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY &&
edecca
+        virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
edecca
+        reason == VIR_DOMAIN_PAUSED_MIGRATION) {
edecca
+        VIR_DEBUG("Correcting paused state reason for domain %s to %s",
edecca
+                  vm->def->name,
edecca
+                  virDomainPausedReasonTypeToString(VIR_DOMAIN_PAUSED_POSTCOPY));
edecca
+
edecca
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_POSTCOPY);
edecca
+        event = virDomainEventLifecycleNewFromObj(vm,
edecca
+                                                  VIR_DOMAIN_EVENT_SUSPENDED,
edecca
+                                                  VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY);
edecca
+
edecca
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
edecca
+            VIR_WARN("Unable to save status on vm %s after state change",
edecca
+                     vm->def->name);
edecca
+        }
edecca
+    }
edecca
+
edecca
  cleanup:
edecca
     virObjectUnlock(vm);
edecca
+    virObjectEventStateQueue(driver->domainEventState, event);
edecca
+    virObjectUnref(cfg);
edecca
     return 0;
edecca
 }
edecca
 
edecca
-- 
edecca
2.19.2
edecca