First, we need get migration thread info, implement the related
interface to obtain migration threadinfo from qemu using qmp command.

Implementation of the Interface for Obtaining Thread Information

Signed-off-by: zhengchuan<zhengch...@huawei.com>
Signed-off-by: Jiang Jiacheng <jiangjiach...@huawei.com>
---
 src/qemu/qemu_domain.c       | 24 ++++++++++++++
 src/qemu/qemu_domain.h       | 11 +++++++
 src/qemu/qemu_monitor.c      | 25 +++++++++++++++
 src/qemu/qemu_monitor.h      | 11 +++++++
 src/qemu/qemu_monitor_json.c | 62 ++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  5 +++
 6 files changed, 138 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index aa567f652a..ba8d1055ae 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -797,6 +797,28 @@ qemuDomainSecretInfoDestroy(qemuDomainSecretInfo *secinfo)
     qemuDomainSecretInfoClear(secinfo, true);
 }
 
+static void
+qemuDomainMigThreadInfoFree(qemuDomainMigThreadInfo *migthread)
+{
+    if (!migthread)
+        return;
+
+    g_free(migthread->thread_name);
+}
+
+void
+qemuDomainMigThreadsInfoFree(qemuDomainMigThreadInfo **migthreads,
+                             int nmigthreads)
+{
+    size_t i;
+    if (!migthreads)
+        return;
+
+    for (i = 0; i < nmigthreads; i++) {
+        g_clear_pointer(&migthreads[i], qemuDomainMigThreadInfoFree);
+    }
+    g_free(migthreads);
+}
 
 static virClass *qemuDomainDiskPrivateClass;
 static void qemuDomainDiskPrivateDispose(void *obj);
@@ -1842,6 +1864,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *priv)
     priv->allowReboot = VIR_TRISTATE_BOOL_ABSENT;
 
     g_clear_pointer(&priv->migrationCaps, virBitmapFree);
+    qemuDomainMigThreadsInfoFree(priv->migThreadsInfo, priv->migThreadCount);
+    priv->migThreadCount = 0;
 
     virHashRemoveAll(priv->blockjobs);
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 550397ee50..42115a20ef 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -97,6 +97,12 @@ struct _qemuDomainSecretInfo {
     char *ciphertext; /* encoded/encrypted secret */
 };
 
+typedef struct _qemuDomainMigThreadInfo qemuDomainMigThreadInfo;
+struct _qemuDomainMigThreadInfo {
+    char *thread_name;
+    int thread_id;
+};
+
 typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
 struct _qemuDomainObjPrivate {
     virQEMUDriver *driver;
@@ -138,6 +144,8 @@ struct _qemuDomainObjPrivate {
     unsigned long migMaxBandwidth;
     char *origname;
     int nbdPort; /* Port used for migration with NBD */
+    int migThreadCount;
+    qemuDomainMigThreadInfo **migThreadsInfo;
     unsigned short migrationPort;
     int preMigrationState;
     unsigned long long preMigrationMemlock; /* Original RLIMIT_MEMLOCK in case
@@ -925,6 +933,9 @@ int qemuDomainSecretChardevPrepare(virQEMUDriverConfig *cfg,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(4);
 
+void qemuDomainMigThreadsInfoFree(qemuDomainMigThreadInfo **migthreads,
+                                  int nmigthreads);
+
 void qemuDomainCleanupStorageSourceFD(virStorageSource *src);
 
 void qemuDomainStartupCleanup(virDomainObj *vm);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 1fa35f03cc..ad35034db2 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2222,6 +2222,31 @@ qemuMonitorGetMigrationStats(qemuMonitor *mon,
     return qemuMonitorJSONGetMigrationStats(mon, stats, error);
 }
 
+void qemuMonitorMigThreadsInfoFree(qemuMonitorMigThreadInfo **migthreads,
+                                   int nmigthreads)
+{
+    size_t i;
+
+    if (!migthreads)
+        return;
+
+    for (i = 0; i < nmigthreads; i++) {
+        g_free(migthreads[i]->thread_name);
+        g_free(migthreads[i]);
+    }
+
+    g_free(migthreads);
+}
+
+int
+qemuMonitorGetMigThreadsInfo(qemuMonitor *mon,
+                             qemuMonitorMigThreadInfo ***migthreads,
+                             int *nmigthreads)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetMigThreadsInfo(mon, migthreads, nmigthreads);
+}
 
 int
 qemuMonitorMigrateToFd(qemuMonitor *mon,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 72db0c0838..076e32bdd3 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -823,6 +823,17 @@ int qemuMonitorGetMigrationCapabilities(qemuMonitor *mon,
 int qemuMonitorSetMigrationCapabilities(qemuMonitor *mon,
                                         virJSONValue **caps);
 
+typedef struct _qemuMonitorMigThreadInfo qemuMonitorMigThreadInfo;
+struct _qemuMonitorMigThreadInfo {
+    char *thread_name;
+    int thread_id;
+};
+int qemuMonitorGetMigThreadsInfo(qemuMonitor *mon,
+                                 qemuMonitorMigThreadInfo ***migthreads,
+                                 int *nmigthreads);
+void qemuMonitorMigThreadsInfoFree(qemuMonitorMigThreadInfo **migthreads,
+                                   int nmigthreads);
+
 int qemuMonitorGetGICCapabilities(qemuMonitor *mon,
                                   virGICCapability **capabilities);
 
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ee2ea68acb..4fd381859f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3124,6 +3124,68 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitor *mon,
     return 0;
 }
 
+int
+qemuMonitorJSONGetMigThreadsInfo(qemuMonitor *mon,
+                                 qemuMonitorMigThreadInfo ***migthreads,
+                                 int *nmigthreads)
+{
+    int ret = -1;
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    virJSONValue *data = NULL;
+    qemuMonitorMigThreadInfo **infolist = NULL;
+    size_t n = 0;
+    size_t i;
+
+    *migthreads = NULL;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-migrationthreads", NULL)))
+        return ret;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
+        goto cleanup;
+
+    data = virJSONValueObjectGetArray(reply, "return");
+    n = virJSONValueArraySize(data);
+
+    infolist = g_new0(qemuMonitorMigThreadInfo *, n + 1);
+
+    for (i = 0; i < n; i++) {
+        virJSONValue *child = virJSONValueArrayGet(data, i);
+        const char *tmp;
+        qemuMonitorMigThreadInfo *info;
+
+        info = g_new0(qemuMonitorMigThreadInfo, 1);
+
+        infolist[i] = info;
+
+        if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("query-migrationthreads reply data was missing 
'name'"));
+             goto cleanup;
+        }
+        info->thread_name = g_strdup(tmp);
+
+        if (virJSONValueObjectGetNumberInt(child, "thread-id",
+                                           &info->thread_id) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("query-migrationthreads reply has malformed "
+                             "'thread-id' data"));
+            goto cleanup;
+        }
+    }
+
+    *nmigthreads = n;
+    *migthreads = g_steal_pointer(&infolist);
+    ret = 0;
+
+ cleanup:
+    qemuMonitorMigThreadsInfoFree(infolist, n);
+    return ret;
+}
 
 int qemuMonitorJSONMigrate(qemuMonitor *mon,
                            unsigned int flags,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 6f376cf9b7..1a0875bd2c 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -156,6 +156,11 @@ int
 qemuMonitorJSONSetMigrationCapabilities(qemuMonitor *mon,
                                         virJSONValue **caps);
 
+int
+qemuMonitorJSONGetMigThreadsInfo(qemuMonitor *mon,
+                                 qemuMonitorMigThreadInfo ***migthreads,
+                                 int *nmigthreads);
+
 int
 qemuMonitorJSONGetGICCapabilities(qemuMonitor *mon,
                                   virGICCapability **capabilities);
-- 
2.33.0

Reply via email to