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(a)redhat.com>
---
src/qemu/qemu_migration.c | 173 +++++++++++++++++++++++---------------
1 file changed, 103 insertions(+), 70 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 170d99d789..d02e8132e4 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -6004,71 +6004,32 @@ qemuMigrationDstFinishFresh(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)
+static virDomainPtr
+qemuMigrationDstFinishActive(virQEMUDriver *driver,
+ virConnectPtr dconn,
+ virDomainObj *vm,
+ int cookie_flags,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
+ unsigned long flags,
+ int retcode,
+ bool v3proto,
+ unsigned long long timeReceived,
+ virErrorPtr *orig_err)
{
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 (flags & VIR_MIGRATE_OFFLINE) {
- if (retcode == 0) {
- dom = qemuMigrationDstFinishOffline(driver, dconn, vm,
- cookie_flags,
- cookiein, cookieinlen,
- cookieout, cookieoutlen);
- }
-
- qemuMigrationJobFinish(vm);
- goto cleanup;
- }
+ VIR_DEBUG("vm=%p, flags=0x%lx, retcode=%d",
+ vm, flags, retcode);
if (!(mig = qemuMigrationCookieParse(driver, vm->def, priv->origname, priv,
cookiein, cookieinlen, cookie_flags)))
@@ -6106,25 +6067,12 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
qemuMigrationJobFinish(vm);
- cleanup:
- virPortAllocatorRelease(port);
- if (priv->mon)
- qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL);
- VIR_FREE(priv->origname);
- virDomainObjEndAPI(&vm);
- virErrorRestore(&orig_err);
-
- /* Set a special error if Finish is expected to return NULL as a result of
- * successful call with retcode != 0
- */
- if (retcode != 0 && !dom && virGetLastErrorCode() == VIR_ERR_OK)
- virReportError(VIR_ERR_MIGRATE_FINISH_OK, NULL);
return dom;
error:
/* Need to save the current error, in case shutting down the process
* overwrites it. */
- virErrorPreserveLast(&orig_err);
+ virErrorPreserveLast(orig_err);
if (virDomainObjIsActive(vm)) {
if (doKill) {
@@ -6155,7 +6103,92 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
if (!virDomainObjIsActive(vm))
qemuDomainRemoveInactive(driver, vm);
- goto cleanup;
+ return NULL;
+}
+
+
+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;
+ virErrorPtr orig_err = NULL;
+ int cookie_flags = 0;
+ qemuDomainObjPrivate *priv = vm->privateData;
+ unsigned short port;
+ unsigned long long timeReceived = 0;
+
+ 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 (flags & VIR_MIGRATE_OFFLINE) {
+ if (retcode == 0) {
+ dom = qemuMigrationDstFinishOffline(driver, dconn, vm,
+ cookie_flags,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen);
+ }
+
+ qemuMigrationJobFinish(vm);
+ goto cleanup;
+ }
+
+ dom = qemuMigrationDstFinishActive(driver, dconn, vm, cookie_flags,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, retcode, v3proto, timeReceived,
+ &orig_err);
+ if (!dom)
+ goto cleanup;
+
+ cleanup:
+ virPortAllocatorRelease(port);
+ if (priv->mon)
+ qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL);
+ VIR_FREE(priv->origname);
+ virDomainObjEndAPI(&vm);
+ virErrorRestore(&orig_err);
+
+ /* Set a special error if Finish is expected to return NULL as a result of
+ * successful call with retcode != 0
+ */
+ if (retcode != 0 && !dom && virGetLastErrorCode() == VIR_ERR_OK)
+ virReportError(VIR_ERR_MIGRATE_FINISH_OK, NULL);
+ return dom;
}
--
2.35.1