[libvirt] [PATCH 6/9] qemu: Pass migratable host CPU model to virCPUUpdate

Jiri Denemark jdenemar at redhat.com
Thu Apr 13 13:32:55 UTC 2017


We already know from QEMU which CPU features will block migration. Let's
use this information to make a migratable copy of the host CPU model and
use it for updating guest CPU specification. This will allow us to drop
feature filtering from virCPUUpdate where it was just a hack.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++-------
 src/qemu/qemu_capabilities.h |  2 ++
 src/qemu/qemu_process.c      |  2 +-
 tests/cputest.c              |  7 +++++-
 4 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 3bfc79c09..1d95e67b3 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -384,6 +384,8 @@ struct _virQEMUCapsHostCPUData {
     qemuMonitorCPUModelInfoPtr info;
     /* Host CPU definition reported in domain capabilities. */
     virCPUDefPtr reported;
+    /* Migratable host CPU definition used for updating guest CPU. */
+    virCPUDefPtr migratable;
 };
 
 /*
@@ -2136,6 +2138,10 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst,
         !(dst->reported = virCPUDefCopy(src->reported)))
         return -1;
 
+    if (src->migratable &&
+        !(dst->migratable = virCPUDefCopy(src->migratable)))
+        return -1;
+
     return 0;
 }
 
@@ -2145,6 +2151,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData)
 {
     qemuMonitorCPUModelInfoFree(cpuData->info);
     virCPUDefFree(cpuData->reported);
+    virCPUDefFree(cpuData->migratable);
 
     memset(cpuData, '\0', sizeof(*cpuData));
 }
@@ -2483,6 +2490,9 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
     switch (cpuType) {
     case VIR_QEMU_CAPS_HOST_CPU_REPORTED:
         return cpuData->reported;
+
+    case VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE:
+        return cpuData->migratable;
     }
 
     return NULL;
@@ -2492,11 +2502,13 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
 static void
 virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps,
                         virDomainVirtType type,
-                        virCPUDefPtr cpu)
+                        virCPUDefPtr reported,
+                        virCPUDefPtr migratable)
 {
     virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
 
-    cpuData->reported = cpu;
+    cpuData->reported = reported;
+    cpuData->migratable = migratable;
 }
 
 
@@ -3348,26 +3360,39 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
 }
 
 
+static virCPUDefPtr
+virQEMUCapsNewHostCPUModel(void)
+{
+    virCPUDefPtr cpu;
+
+    if (VIR_ALLOC(cpu) < 0)
+        return NULL;
+
+    cpu->type = VIR_CPU_TYPE_GUEST;
+    cpu->mode = VIR_CPU_MODE_CUSTOM;
+    cpu->match = VIR_CPU_MATCH_EXACT;
+    cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
+
+    return cpu;
+}
+
+
 void
 virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
                             virCapsPtr caps,
                             virDomainVirtType type)
 {
     virCPUDefPtr cpu = NULL;
+    virCPUDefPtr migCPU = NULL;
     virCPUDefPtr hostCPU = NULL;
     int rc;
 
     if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
         return;
 
-    if (VIR_ALLOC(cpu) < 0)
+    if (!(cpu = virQEMUCapsNewHostCPUModel()))
         goto error;
 
-    cpu->type = VIR_CPU_TYPE_GUEST;
-    cpu->mode = VIR_CPU_MODE_CUSTOM;
-    cpu->match = VIR_CPU_MATCH_EXACT;
-    cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
-
     if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu, false)) < 0) {
         goto error;
     } else if (rc == 1) {
@@ -3381,7 +3406,20 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
             goto error;
     }
 
-    virQEMUCapsSetHostModel(qemuCaps, type, cpu);
+    if (!(migCPU = virQEMUCapsNewHostCPUModel()))
+        goto error;
+
+    if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, migCPU, true)) < 0) {
+        goto error;
+    } else if (rc == 1) {
+        VIR_DEBUG("CPU migratability not provided by QEMU");
+
+        virCPUDefFree(migCPU);
+        if (!(migCPU = virCPUCopyMigratable(qemuCaps->arch, cpu)))
+            goto error;
+    }
+
+    virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU);
 
  cleanup:
     virCPUDefFree(hostCPU);
@@ -3389,6 +3427,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
 
  error:
     virCPUDefFree(cpu);
+    virCPUDefFree(migCPU);
     virResetLastError();
     goto cleanup;
 }
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index bd147c009..f04f74060 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -453,6 +453,8 @@ int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
 typedef enum {
     /* Host CPU definition reported in domain capabilities. */
     VIR_QEMU_CAPS_HOST_CPU_REPORTED,
+    /* Migratable host CPU definition used for updating guest CPU. */
+    VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE,
 } virQEMUCapsHostCPUType;
 
 virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c05cd9e7a..6b77a3969 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5311,7 +5311,7 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def,
 
     if (virCPUUpdate(def->os.arch, def->cpu,
                      virQEMUCapsGetHostModel(qemuCaps, def->virtType,
-                                             VIR_QEMU_CAPS_HOST_CPU_REPORTED)) < 0)
+                                             VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) < 0)
         goto cleanup;
 
     if (virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType,
diff --git a/tests/cputest.c b/tests/cputest.c
index 528030754..d5e023c40 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -393,6 +393,7 @@ cpuTestUpdate(const void *arg)
     const struct data *data = arg;
     int ret = -1;
     virCPUDefPtr host = NULL;
+    virCPUDefPtr migHost = NULL;
     virCPUDefPtr cpu = NULL;
     char *result = NULL;
 
@@ -400,7 +401,10 @@ cpuTestUpdate(const void *arg)
         !(cpu = cpuTestLoadXML(data->arch, data->name)))
         goto cleanup;
 
-    if (virCPUUpdate(host->arch, cpu, host) < 0)
+    if (!(migHost = virCPUCopyMigratable(data->arch, host)))
+        goto cleanup;
+
+    if (virCPUUpdate(host->arch, cpu, migHost) < 0)
         goto cleanup;
 
     if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0)
@@ -411,6 +415,7 @@ cpuTestUpdate(const void *arg)
  cleanup:
     virCPUDefFree(host);
     virCPUDefFree(cpu);
+    virCPUDefFree(migHost);
     VIR_FREE(result);
     return ret;
 }
-- 
2.12.2




More information about the libvir-list mailing list