If pcpumap is set before migration, pin migration thread
to expected cpulist immediately after get thread info during
migration. Add 'qemuProcessGetPcpumap' to get pcpumap, try
get the result of 'virsh migratepin' first, and if it's not set,
try to get the pcpumap from migration parameter.

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

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1fb091255f..30f41e8d25 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2003,6 +2003,23 @@ qemuMigrationAnyCompleted(virDomainObj *vm,
     return -1;
 }
 
+
+static void
+qemuMigrationSrcThreadPin(virDomainObj *vm,
+                          virBitmap *pcpumap,
+                          int nmigthreads)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuDomainMigThreadInfo **migthreads = priv->migThreadsInfo;
+    size_t i;
+
+
+    for (i = 0; i < nmigthreads; i++) {
+        qemuProcessSetMigThreadAffinity(priv, vm, migthreads[i]->thread_id, 
pcpumap);
+    }
+}
+
+
 /* Returns 0 on get migration thread info success,
  * -1 on unexpected failure
  */
@@ -2018,6 +2035,7 @@ qemuMigrationSrcWaitForThreadInfo(virDomainObj *vm,
     qemuDomainObjPrivate *priv = vm->privateData;
     qemuMonitorMigThreadInfo **infolist = NULL;
     qemuDomainMigThreadInfo **migthreads = NULL;
+    virBitmap *pcpumap = NULL;
     int nmigthreads = 0;
     int rc;
     size_t i;
@@ -2065,7 +2083,17 @@ qemuMigrationSrcWaitForThreadInfo(virDomainObj *vm,
     priv->migThreadsInfo = migthreads;
     ret = 0;
 
+    /* Try get pcpumap for migration thread pin,
+     * but thread pin failed shouldn't effect migration */
+    if (!(pcpumap = qemuProcessGetPcpumap(priv)))
+        goto cleanup;
+
+    qemuMigrationSrcThreadPin(vm, pcpumap, nmigthreads);
+
  cleanup:
+    if (pcpumap != priv->pcpumap)
+        virBitmapFree(pcpumap);
+
     if (migthreads && (ret < 0)) {
         qemuDomainMigThreadsInfoFree(migthreads, priv->migThreadCount);
         priv->migThreadCount = 0;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 946aeb81b1..e787db8b24 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -9608,3 +9608,84 @@ qemuProcessSetMigThreadAffinity(qemuDomainObjPrivate 
*priv,
     virDomainMigrationIDDefFree(migration);
     return;
 }
+
+
+static unsigned char *
+virParseCPUList(int *cpumaplen, const char *cpulist, int maxcpu)
+{
+    int lastcpu;
+    unsigned char *cpumap = NULL;
+    virBitmap *map = NULL;
+
+    if (cpulist[0] == 'r') {
+        map = virBitmapNew(maxcpu);
+        if (!map)
+            return NULL;
+        virBitmapSetAll(map);
+    } else {
+        if (virBitmapParse(cpulist, &map, 1024) < 0 ||
+            virBitmapIsAllClear(map)) {
+            goto cleanup;
+        }
+
+        lastcpu = virBitmapLastSetBit(map);
+        if (lastcpu >= maxcpu)
+            goto cleanup;
+    }
+
+    if (virBitmapToData(map, &cpumap, cpumaplen) < 0)
+        VIR_ERROR(_("Bitmap to data failure"));
+
+ cleanup:
+    virBitmapFree(map);
+    return cpumap;
+}
+
+
+/*
+ * The value of "virsh migrationpin" is saved to priv->pcpumap
+ * If priv->pcpumap is NULL, it means migrationpin command is not called,
+ * otherwise we set the affinity of migration thread by migrationpin
+ */
+virBitmap*
+qemuProcessGetPcpumap(qemuDomainObjPrivate *priv)
+{
+    int cpumaplen = 0;
+    int maxcpu = 0;
+    virBitmap *pcpumap = NULL;
+    g_autofree unsigned char *cpumap = NULL;
+
+    /* priv->pcpumap = NULL means migrationpin is not set, try to get pcpumap
+     * from migration parameter. */
+    if (priv->pcpumap)
+        return priv->pcpumap;
+
+    if (!(priv->migrationThreadPinList) || STREQ(priv->migrationThreadPinList, 
"")) {
+        VIR_ERROR(_("didn't set the migratin thread pin"));
+        return NULL;
+    }
+
+    /* judge whether set_migration_pin is default value or not */
+    if (STREQ(priv->migrationThreadPinList, "none"))
+        return NULL;
+
+    maxcpu = virHostCPUGetCount();
+    if (maxcpu < 0) {
+        VIR_ERROR(_("get the cpu count of host failure"));
+        return NULL;
+    }
+
+    cpumap = virParseCPUList(&cpumaplen, priv->migrationThreadPinList, maxcpu);
+    if (!cpumap) {
+        VIR_ERROR(_("parse migration.pin param failure : migration.pin = %s"),
+                  priv->migrationThreadPinList);
+        return NULL;
+    }
+
+    if (!(pcpumap = virBitmapNewData(cpumap, cpumaplen))) {
+        VIR_ERROR(_("Bitmap data failure"));
+        return NULL;
+    }
+
+    return pcpumap;
+}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 2af1e2ee87..74e96ccb07 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -245,3 +245,6 @@ qemuProcessSetMigThreadAffinity(qemuDomainObjPrivate *priv,
                                 virDomainObj *vm,
                                 int mpid,
                                 virBitmap *pcpumap);
+
+virBitmap*
+qemuProcessGetPcpumap(qemuDomainObjPrivate *priv);
-- 
2.33.0

Reply via email to