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<zhengchuan@xxxxxxxxxx> Signed-off-by: Jiang Jiacheng <jiangjiacheng@xxxxxxxxxx> --- 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