[libvirt PATCH v2 30/81] qemu: Introduce qemuMigrationDstFinishFresh

Jiri Denemark jdenemar at redhat.com
Wed Jun 1 12:49:30 UTC 2022


Refactors qemuMigrationDstFinish by moving some parts to a dedicated
function for easier introduction of postcopy resume code without
duplicating common parts of the Finish phase. The goal is to have the
following call graph:

    - qemuMigrationDstFinish
        - qemuMigrationDstFinishOffline
        - qemuMigrationDstFinishActive
            - qemuMigrationDstFinishFresh
            - qemuMigrationDstFinishResume

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
Reviewed-by: Peter Krempa <pkrempa at redhat.com>
Reviewed-by: Pavel Hrdina <phrdina at redhat.com>
---

Notes:
    Version 2:
    - no change

 src/qemu/qemu_migration.c | 234 +++++++++++++++++++++-----------------
 1 file changed, 129 insertions(+), 105 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 10c4f7a470..72f22f09e4 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -5808,111 +5808,38 @@ qemuMigrationDstComplete(virQEMUDriver *driver,
 }
 
 
-virDomainPtr
-qemuMigrationDstFinish(virQEMUDriver *driver,
-                       virConnectPtr dconn,
-                       virDomainObj *vm,
-                       const char *cookiein,
-                       int cookieinlen,
-                       char **cookieout,
-                       int *cookieoutlen,
-                       unsigned long flags,
-                       int retcode,
-                       bool v3proto)
+/*
+ * Perform Finish phase of a fresh (i.e., not recovery) migration of an active
+ * domain.
+ */
+static int
+qemuMigrationDstFinishFresh(virQEMUDriver *driver,
+                            virDomainObj *vm,
+                            qemuMigrationCookie *mig,
+                            unsigned long flags,
+                            bool v3proto,
+                            unsigned long long timeReceived,
+                            bool *doKill,
+                            bool *inPostCopy)
 {
-    virDomainPtr dom = NULL;
-    g_autoptr(qemuMigrationCookie) mig = NULL;
-    virErrorPtr orig_err = NULL;
-    int cookie_flags = 0;
     qemuDomainObjPrivate *priv = vm->privateData;
-    qemuDomainJobPrivate *jobPriv = priv->job.privateData;
-    unsigned short port;
-    unsigned long long timeReceived = 0;
-    virObjectEvent *event;
-    virDomainJobData *jobData = NULL;
-    bool inPostCopy = false;
-    bool doKill = true;
-
-    VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
-              "cookieout=%p, cookieoutlen=%p, flags=0x%lx, retcode=%d",
-              driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
-              cookieout, cookieoutlen, flags, retcode);
-
-    port = priv->migrationPort;
-    priv->migrationPort = 0;
-
-    if (!qemuMigrationJobIsActive(vm, VIR_ASYNC_JOB_MIGRATION_IN)) {
-        qemuMigrationDstErrorReport(driver, vm->def->name);
-        goto cleanup;
-    }
-
-    ignore_value(virTimeMillisNow(&timeReceived));
-
-    qemuMigrationJobStartPhase(vm,
-                               v3proto ? QEMU_MIGRATION_PHASE_FINISH3
-                                       : QEMU_MIGRATION_PHASE_FINISH2);
-
-    qemuDomainCleanupRemove(vm, qemuMigrationDstPrepareCleanup);
-    g_clear_pointer(&priv->job.completed, virDomainJobDataFree);
-
-    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK |
-                   QEMU_MIGRATION_COOKIE_STATS |
-                   QEMU_MIGRATION_COOKIE_NBD;
-    /* Some older versions of libvirt always send persistent XML in the cookie
-     * even though VIR_MIGRATE_PERSIST_DEST was not used. */
-    cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
-
-    if (!(mig = qemuMigrationCookieParse(driver, vm->def, priv->origname, priv,
-                                         cookiein, cookieinlen, cookie_flags)))
-        goto error;
-
-    if (flags & VIR_MIGRATE_OFFLINE) {
-        if (retcode == 0 &&
-            qemuMigrationDstPersist(driver, vm, mig, false) == 0) {
-            dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, -1);
-
-            if (dom &&
-                qemuMigrationCookieFormat(mig, driver, vm,
-                                          QEMU_MIGRATION_DESTINATION,
-                                          cookieout, cookieoutlen,
-                                          QEMU_MIGRATION_COOKIE_STATS) < 0)
-                VIR_WARN("Unable to encode migration cookie");
-        }
-
-        qemuMigrationJobFinish(vm);
-        goto cleanup;
-    }
-
-    if (retcode != 0) {
-        /* Check for a possible error on the monitor in case Finish was called
-         * earlier than monitor EOF handler got a chance to process the error
-         */
-        qemuDomainCheckMonitor(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN);
-        goto error;
-    }
-
-    if (!virDomainObjIsActive(vm)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("guest unexpectedly quit"));
-        qemuMigrationDstErrorReport(driver, vm->def->name);
-        goto error;
-    }
+    g_autoptr(virDomainJobData) jobData = NULL;
 
     if (qemuMigrationDstVPAssociatePortProfiles(vm->def) < 0)
-        goto error;
+        return -1;
 
     if (mig->network && qemuMigrationDstOPDRelocate(driver, vm, mig) < 0)
         VIR_WARN("unable to provide network data for relocation");
 
     if (qemuMigrationDstStopNBDServer(driver, vm, mig) < 0)
-        goto error;
+        return -1;
 
     if (qemuRefreshVirtioChannelState(driver, vm,
                                       VIR_ASYNC_JOB_MIGRATION_IN) < 0)
-        goto error;
+        return -1;
 
     if (qemuConnectAgent(driver, vm) < 0)
-        goto error;
+        return -1;
 
     if (flags & VIR_MIGRATE_PERSIST_DEST) {
         if (qemuMigrationDstPersist(driver, vm, mig, !v3proto) < 0) {
@@ -5929,7 +5856,7 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
              * to restart during confirm() step, so we kill it off now.
              */
             if (v3proto)
-                goto error;
+                return -1;
         }
     }
 
@@ -5943,7 +5870,7 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
          * original domain on the source host is already gone.
          */
         if (v3proto)
-            goto error;
+            return -1;
     }
 
     /* Now that the state data was transferred we can refresh the actual state
@@ -5952,16 +5879,16 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
         /* Similarly to the case above v2 protocol will not be able to recover
          * from this. Let's ignore this and perhaps stuff will not break. */
         if (v3proto)
-            goto error;
+            return -1;
     }
 
     if (priv->job.current->status == VIR_DOMAIN_JOB_STATUS_POSTCOPY)
-        inPostCopy = true;
+        *inPostCopy = true;
 
     if (!(flags & VIR_MIGRATE_PAUSED)) {
         if (qemuProcessStartCPUs(driver, vm,
-                                 inPostCopy ? VIR_DOMAIN_RUNNING_POSTCOPY
-                                            : VIR_DOMAIN_RUNNING_MIGRATED,
+                                 *inPostCopy ? VIR_DOMAIN_RUNNING_POSTCOPY
+                                             : VIR_DOMAIN_RUNNING_MIGRATED,
                                  VIR_ASYNC_JOB_MIGRATION_IN) < 0) {
             if (virGetLastErrorCode() == VIR_ERR_OK)
                 virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5975,11 +5902,11 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
              * things up.
              */
             if (v3proto)
-                goto error;
+                return -1;
         }
 
-        if (inPostCopy)
-            doKill = false;
+        if (*inPostCopy)
+            *doKill = false;
     }
 
     if (mig->jobData) {
@@ -5994,11 +5921,11 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
         qemuDomainJobDataUpdateDowntime(jobData);
     }
 
-    if (inPostCopy &&
+    if (*inPostCopy &&
         qemuMigrationDstWaitForCompletion(driver, vm,
                                           VIR_ASYNC_JOB_MIGRATION_IN,
                                           false) < 0) {
-        goto error;
+        return -1;
     }
 
     if (jobData) {
@@ -6008,6 +5935,106 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
                                   QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION);
     }
 
+    return 0;
+}
+
+
+virDomainPtr
+qemuMigrationDstFinish(virQEMUDriver *driver,
+                       virConnectPtr dconn,
+                       virDomainObj *vm,
+                       const char *cookiein,
+                       int cookieinlen,
+                       char **cookieout,
+                       int *cookieoutlen,
+                       unsigned long flags,
+                       int retcode,
+                       bool v3proto)
+{
+    virDomainPtr dom = NULL;
+    g_autoptr(qemuMigrationCookie) mig = NULL;
+    virErrorPtr orig_err = NULL;
+    int cookie_flags = 0;
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuDomainJobPrivate *jobPriv = priv->job.privateData;
+    unsigned short port;
+    unsigned long long timeReceived = 0;
+    virObjectEvent *event;
+    bool inPostCopy = false;
+    bool doKill = true;
+    int rc;
+
+    VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
+              "cookieout=%p, cookieoutlen=%p, flags=0x%lx, retcode=%d",
+              driver, dconn, vm, NULLSTR(cookiein), cookieinlen,
+              cookieout, cookieoutlen, flags, retcode);
+
+    port = priv->migrationPort;
+    priv->migrationPort = 0;
+
+    if (!qemuMigrationJobIsActive(vm, VIR_ASYNC_JOB_MIGRATION_IN)) {
+        qemuMigrationDstErrorReport(driver, vm->def->name);
+        goto cleanup;
+    }
+
+    ignore_value(virTimeMillisNow(&timeReceived));
+
+    qemuMigrationJobStartPhase(vm,
+                               v3proto ? QEMU_MIGRATION_PHASE_FINISH3
+                                       : QEMU_MIGRATION_PHASE_FINISH2);
+
+    qemuDomainCleanupRemove(vm, qemuMigrationDstPrepareCleanup);
+    g_clear_pointer(&priv->job.completed, virDomainJobDataFree);
+
+    cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK |
+                   QEMU_MIGRATION_COOKIE_STATS |
+                   QEMU_MIGRATION_COOKIE_NBD;
+    /* Some older versions of libvirt always send persistent XML in the cookie
+     * even though VIR_MIGRATE_PERSIST_DEST was not used. */
+    cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
+
+    if (!(mig = qemuMigrationCookieParse(driver, vm->def, priv->origname, priv,
+                                         cookiein, cookieinlen, cookie_flags)))
+        goto error;
+
+    if (flags & VIR_MIGRATE_OFFLINE) {
+        if (retcode == 0 &&
+            qemuMigrationDstPersist(driver, vm, mig, false) == 0) {
+            dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, -1);
+
+            if (dom &&
+                qemuMigrationCookieFormat(mig, driver, vm,
+                                          QEMU_MIGRATION_DESTINATION,
+                                          cookieout, cookieoutlen,
+                                          QEMU_MIGRATION_COOKIE_STATS) < 0)
+                VIR_WARN("Unable to encode migration cookie");
+        }
+
+        qemuMigrationJobFinish(vm);
+        goto cleanup;
+    }
+
+    if (retcode != 0) {
+        /* Check for a possible error on the monitor in case Finish was called
+         * earlier than monitor EOF handler got a chance to process the error
+         */
+        qemuDomainCheckMonitor(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN);
+        goto error;
+    }
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("guest unexpectedly quit"));
+        qemuMigrationDstErrorReport(driver, vm->def->name);
+        goto error;
+    }
+
+    rc = qemuMigrationDstFinishFresh(driver, vm, mig, flags, v3proto,
+                                     timeReceived, &doKill, &inPostCopy);
+    if (rc < 0 ||
+        !(dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, vm->def->id)))
+        goto error;
+
     if (qemuMigrationCookieFormat(mig, driver, vm,
                                   QEMU_MIGRATION_DESTINATION,
                                   cookieout, cookieoutlen,
@@ -6017,12 +6044,9 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
     qemuMigrationDstComplete(driver, vm, inPostCopy,
                              VIR_ASYNC_JOB_MIGRATION_IN);
 
-    dom = virGetDomain(dconn, vm->def->name, vm->def->uuid, vm->def->id);
-
     qemuMigrationJobFinish(vm);
 
  cleanup:
-    g_clear_pointer(&jobData, virDomainJobDataFree);
     virPortAllocatorRelease(port);
     if (priv->mon)
         qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL);
-- 
2.35.1



More information about the libvir-list mailing list