Second, query migration thread information during migration
process proactively. Migration should start after all thread
be created, so querying the migration thread infomation before
wating for completion and terminate the query in any abnormal
situation.

Signed-off-by: zhengchuan<zhengch...@huawei.com>
Signed-off-by: Jiang Jiacheng <jiangjiach...@huawei.com>
---
 src/qemu/qemu_migration.c        | 81 ++++++++++++++++++++++++++++++++
 src/qemu/qemu_migration_params.c | 19 ++++++++
 src/qemu/qemu_migration_params.h |  4 ++
 3 files changed, 104 insertions(+)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 2720f0b083..0cea055eec 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2003,6 +2003,81 @@ qemuMigrationAnyCompleted(virDomainObj *vm,
     return -1;
 }
 
+/* Returns 0 on get migration thread info success,
+ * -1 on unexpected failure
+ */
+static int
+qemuMigrationSrcWaitForThreadInfo(virDomainObj *vm,
+                                  qemuMigrationParams *migParams,
+                                  unsigned long migflags,
+                                  virDomainAsyncJob asyncJob,
+                                  virConnectPtr dconn,
+                                  unsigned int flags)
+{
+    int ret = -1;
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuMonitorMigThreadInfo **infolist = NULL;
+    qemuDomainMigThreadInfo **migthreads = NULL;
+    int nmigthreads = 0;
+    int rc;
+    size_t i;
+
+    /* migrationThreadCount = live_migration + multifd channels */
+    priv->migThreadCount = qemuMigrationParamsGetMigThreadCount(migParams,
+                                                                migflags);
+    while ((rc = qemuMigrationAnyCompleted(vm, asyncJob,
+                                           dconn, flags)) != 1) {
+        if (rc < 0)
+            return rc;
+
+        if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
+            return ret;
+        rc = qemuMonitorGetMigThreadsInfo(priv->mon, &infolist, &nmigthreads);
+        qemuDomainObjExitMonitor(vm);
+        if (rc < 0)
+            goto cleanup;
+
+        if (nmigthreads == priv->migThreadCount) {
+            break;
+        } else if (nmigthreads > priv->migThreadCount) {
+            VIR_WARN("migration threads is more than expected");
+            goto cleanup;
+        } else {
+            struct timespec ts = { .tv_sec = 0, .tv_nsec = 10 * 1000 * 1000ull 
};
+            virObjectUnlock(vm);
+            nanosleep(&ts, NULL);
+            virObjectLock(vm);
+        }
+    }
+
+    migthreads = g_new0(qemuDomainMigThreadInfo *, nmigthreads + 1);
+
+    for (i = 0; i < nmigthreads; i++) {
+        qemuDomainMigThreadInfo *migthread;
+        migthread = g_new0(qemuDomainMigThreadInfo, nmigthreads + 1);
+
+        migthread->thread_name = g_strdup(infolist[i]->thread_name);
+        migthread->thread_id = infolist[i]->thread_id;
+
+        migthreads[i] = migthread;
+    }
+
+    priv->migThreadsInfo = migthreads;
+    ret = 0;
+
+ cleanup:
+    if (migthreads && (ret < 0)) {
+        qemuDomainMigThreadsInfoFree(migthreads, priv->migThreadCount);
+        priv->migThreadCount = 0;
+    }
+
+    if (infolist) {
+        qemuMonitorMigThreadsInfoFree(infolist, nmigthreads);
+    }
+
+    return ret;
+}
+
 
 /* Returns 0 on success, -2 when migration needs to be cancelled, or -1 when
  * QEMU reports failed migration.
@@ -4917,6 +4992,12 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
     if (flags & VIR_MIGRATE_POSTCOPY)
         waitFlags |= QEMU_MIGRATION_COMPLETED_POSTCOPY;
 
+    rc = qemuMigrationSrcWaitForThreadInfo(vm, migParams, flags,
+                                           VIR_ASYNC_JOB_MIGRATION_OUT,
+                                           dconn, waitFlags);
+    if (rc == -1)
+        goto error;
+
     rc = qemuMigrationSrcWaitForCompletion(vm, VIR_ASYNC_JOB_MIGRATION_OUT,
                                            dconn, waitFlags);
     if (rc == -2)
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index bd09dcfb23..43bed2e618 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -1540,3 +1540,22 @@ qemuMigrationParamsGetTLSHostname(qemuMigrationParams 
*migParams)
 
     return migParams->params[QEMU_MIGRATION_PARAM_TLS_HOSTNAME].value.s;
 }
+
+
+int
+qemuMigrationParamsGetMigThreadCount(qemuMigrationParams *migParams,
+                                     unsigned long migflags)
+{
+    int nmigthreads = 1; /* live_migtion */
+
+    if (!(migflags & VIR_MIGRATE_PARALLEL)) {
+        return nmigthreads;
+    } else {
+        if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].set)
+            nmigthreads += 
migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].value.i;
+        else
+            nmigthreads += 2; /* default multifd channel is 2 */
+    }
+
+    return nmigthreads;
+}
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index e7c65f6a21..975b6691d4 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -166,3 +166,7 @@ qemuMigrationCapsGet(virDomainObj *vm,
 
 const char *
 qemuMigrationParamsGetTLSHostname(qemuMigrationParams *migParams);
+
+int
+qemuMigrationParamsGetMigThreadCount(qemuMigrationParams *migParams,
+                                     unsigned long migflags);
-- 
2.33.0

Reply via email to