[libvirt] [PATCH v2 03/45] qemu: Use virDomainCapsCPUModels for cpuDefinitions

Jiri Denemark jdenemar at redhat.com
Mon Sep 19 13:30:12 UTC 2016


The list of supported CPU models in domain capabilities is stored in
virDomainCapsCPUModels. Let's use the same object for storing CPU models
in QEMU capabilities.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---

Notes:
    Version 2:
    - removed superfluous ret < 0
    - adapted to changes in previous patches

 src/qemu/qemu_capabilities.c | 162 +++++++++++++++++++++++++++----------------
 src/qemu/qemu_capabilities.h |  10 +--
 src/qemu/qemu_command.c      |   8 ++-
 src/qemu/qemu_monitor.c      |  12 +++-
 src/qemu/qemu_monitor.h      |  10 ++-
 src/qemu/qemu_monitor_json.c |  24 +++++--
 src/qemu/qemu_monitor_json.h |   2 +-
 tests/qemumonitorjsontest.c  |   8 +--
 tests/qemuxml2argvtest.c     |  18 ++---
 9 files changed, 164 insertions(+), 90 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c71b4dc..b0e51ee 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -378,8 +378,7 @@ struct _virQEMUCaps {
 
     virArch arch;
 
-    size_t ncpuDefinitions;
-    char **cpuDefinitions;
+    virDomainCapsCPUModelsPtr cpuDefinitions;
 
     size_t nmachineTypes;
     struct virQEMUCapsMachineType *machineTypes;
@@ -618,7 +617,10 @@ virQEMUCapsParseX86Models(const char *output,
 {
     const char *p = output;
     const char *next;
-    int ret = -1;
+    virDomainCapsCPUModelsPtr cpus;
+
+    if (!(cpus = virDomainCapsCPUModelsNew(0)))
+        return -1;
 
     do {
         const char *t;
@@ -640,9 +642,6 @@ virQEMUCapsParseX86Models(const char *output,
         if (*p == '\0' || *p == '\n')
             continue;
 
-        if (VIR_EXPAND_N(qemuCaps->cpuDefinitions, qemuCaps->ncpuDefinitions, 1) < 0)
-            goto cleanup;
-
         if (next)
             len = next - p - 1;
         else
@@ -653,14 +652,16 @@ virQEMUCapsParseX86Models(const char *output,
             len -= 2;
         }
 
-        if (VIR_STRNDUP(qemuCaps->cpuDefinitions[qemuCaps->ncpuDefinitions - 1], p, len) < 0)
-            goto cleanup;
+        if (virDomainCapsCPUModelsAdd(cpus, p, len) < 0)
+            goto error;
     } while ((p = next));
 
-    ret = 0;
+    qemuCaps->cpuDefinitions = cpus;
+    return 0;
 
- cleanup:
-    return ret;
+ error:
+    virObjectUnref(cpus);
+    return -1;
 }
 
 /* ppc64 parser.
@@ -672,11 +673,13 @@ virQEMUCapsParsePPCModels(const char *output,
 {
     const char *p = output;
     const char *next;
-    int ret = -1;
+    virDomainCapsCPUModelsPtr cpus;
+
+    if (!(cpus = virDomainCapsCPUModelsNew(0)))
+        return -1;
 
     do {
         const char *t;
-        size_t len;
 
         if ((next = strchr(p, '\n')))
             next++;
@@ -697,19 +700,16 @@ virQEMUCapsParsePPCModels(const char *output,
         if (*p == '\n')
             continue;
 
-        if (VIR_EXPAND_N(qemuCaps->cpuDefinitions, qemuCaps->ncpuDefinitions, 1) < 0)
-            goto cleanup;
-
-        len = t - p - 1;
-
-        if (VIR_STRNDUP(qemuCaps->cpuDefinitions[qemuCaps->ncpuDefinitions - 1], p, len) < 0)
-            goto cleanup;
+        if (virDomainCapsCPUModelsAdd(cpus, p, t - p - 1) < 0)
+            goto error;
     } while ((p = next));
 
-    ret = 0;
+    qemuCaps->cpuDefinitions = cpus;
+    return 0;
 
- cleanup:
-    return ret;
+ error:
+    virObjectUnref(cpus);
+    return -1;
 }
 
 static int
@@ -2094,11 +2094,9 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
 
     ret->arch = qemuCaps->arch;
 
-    if (VIR_ALLOC_N(ret->cpuDefinitions, qemuCaps->ncpuDefinitions) < 0)
-        goto error;
-    ret->ncpuDefinitions = qemuCaps->ncpuDefinitions;
-    for (i = 0; i < qemuCaps->ncpuDefinitions; i++) {
-        if (VIR_STRDUP(ret->cpuDefinitions[i], qemuCaps->cpuDefinitions[i]) < 0)
+    if (qemuCaps->cpuDefinitions) {
+        ret->cpuDefinitions = virDomainCapsCPUModelsCopy(qemuCaps->cpuDefinitions);
+        if (!ret->cpuDefinitions)
             goto error;
     }
 
@@ -2138,9 +2136,7 @@ void virQEMUCapsDispose(void *obj)
     }
     VIR_FREE(qemuCaps->machineTypes);
 
-    for (i = 0; i < qemuCaps->ncpuDefinitions; i++)
-        VIR_FREE(qemuCaps->cpuDefinitions[i]);
-    VIR_FREE(qemuCaps->cpuDefinitions);
+    virObjectUnref(qemuCaps->cpuDefinitions);
 
     virBitmapFree(qemuCaps->flags);
 
@@ -2278,28 +2274,58 @@ const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps)
 }
 
 
-int virQEMUCapsAddCPUDefinition(virQEMUCapsPtr qemuCaps,
-                                const char *name)
+int
+virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
+                             const char **name,
+                             size_t count)
 {
-    char *tmp;
+    size_t i;
 
-    if (VIR_STRDUP(tmp, name) < 0)
-        return -1;
-    if (VIR_EXPAND_N(qemuCaps->cpuDefinitions, qemuCaps->ncpuDefinitions, 1) < 0) {
-        VIR_FREE(tmp);
+    if (!qemuCaps->cpuDefinitions &&
+        !(qemuCaps->cpuDefinitions = virDomainCapsCPUModelsNew(count)))
         return -1;
+
+    for (i = 0; i < count; i++) {
+        if (virDomainCapsCPUModelsAdd(qemuCaps->cpuDefinitions, name[i], -1) < 0)
+            return -1;
     }
-    qemuCaps->cpuDefinitions[qemuCaps->ncpuDefinitions-1] = tmp;
+
     return 0;
 }
 
 
-size_t virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
-                                    char ***names)
+int
+virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
+                             char ***names,
+                             size_t *count)
 {
+    size_t i;
+    char **models = NULL;
+
+    *count = 0;
     if (names)
-        *names = qemuCaps->cpuDefinitions;
-    return qemuCaps->ncpuDefinitions;
+        *names = NULL;
+
+    if (!qemuCaps->cpuDefinitions)
+        return 0;
+
+    if (names && VIR_ALLOC_N(models, qemuCaps->cpuDefinitions->nmodels) < 0)
+        return -1;
+
+    for (i = 0; i < qemuCaps->cpuDefinitions->nmodels; i++) {
+        virDomainCapsCPUModelPtr cpu = qemuCaps->cpuDefinitions->models + i;
+        if (models && VIR_STRDUP(models[i], cpu->name) < 0)
+            goto error;
+    }
+
+    if (names)
+        *names = models;
+    *count = qemuCaps->cpuDefinitions->nmodels;
+    return 0;
+
+ error:
+    virStringFreeListCount(models, i);
+    return -1;
 }
 
 
@@ -2615,16 +2641,30 @@ static int
 virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
                                   qemuMonitorPtr mon)
 {
-    int ncpuDefinitions;
-    char **cpuDefinitions;
+    qemuMonitorCPUDefInfoPtr *cpus;
+    int ncpus;
+    int ret = -1;
+    size_t i;
 
-    if ((ncpuDefinitions = qemuMonitorGetCPUDefinitions(mon, &cpuDefinitions)) < 0)
+    if ((ncpus = qemuMonitorGetCPUDefinitions(mon, &cpus)) < 0)
         return -1;
 
-    qemuCaps->ncpuDefinitions = ncpuDefinitions;
-    qemuCaps->cpuDefinitions = cpuDefinitions;
+    if (!(qemuCaps->cpuDefinitions = virDomainCapsCPUModelsNew(ncpus)))
+        goto cleanup;
 
-    return 0;
+    for (i = 0; i < ncpus; i++) {
+        if (virDomainCapsCPUModelsAddSteal(qemuCaps->cpuDefinitions,
+                                           &cpus[i]->name) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    for (i = 0; i < ncpus; i++)
+        qemuMonitorCPUDefInfoFree(cpus[i]);
+    VIR_FREE(cpus);
+    return ret;
 }
 
 struct tpmTypeToCaps {
@@ -2970,17 +3010,19 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename,
         goto cleanup;
     }
     if (n > 0) {
-        qemuCaps->ncpuDefinitions = n;
-        if (VIR_ALLOC_N(qemuCaps->cpuDefinitions,
-                        qemuCaps->ncpuDefinitions) < 0)
+        if (!(qemuCaps->cpuDefinitions = virDomainCapsCPUModelsNew(n)))
             goto cleanup;
 
         for (i = 0; i < n; i++) {
-            if (!(qemuCaps->cpuDefinitions[i] = virXMLPropString(nodes[i], "name"))) {
+            if (!(str = virXMLPropString(nodes[i], "name"))) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("missing cpu name in QEMU capabilities cache"));
                 goto cleanup;
             }
+
+            if (virDomainCapsCPUModelsAddSteal(qemuCaps->cpuDefinitions,
+                                               &str) < 0)
+                goto cleanup;
         }
     }
     VIR_FREE(nodes);
@@ -3139,9 +3181,11 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps,
     virBufferAsprintf(&buf, "<arch>%s</arch>\n",
                       virArchToString(qemuCaps->arch));
 
-    for (i = 0; i < qemuCaps->ncpuDefinitions; i++) {
-        virBufferEscapeString(&buf, "<cpu name='%s'/>\n",
-                              qemuCaps->cpuDefinitions[i]);
+    if (qemuCaps->cpuDefinitions) {
+        for (i = 0; i < qemuCaps->cpuDefinitions->nmodels; i++) {
+            virDomainCapsCPUModelPtr cpu = qemuCaps->cpuDefinitions->models + i;
+            virBufferEscapeString(&buf, "<cpu name='%s'/>\n", cpu->name);
+        }
     }
 
     for (i = 0; i < qemuCaps->nmachineTypes; i++) {
@@ -3259,10 +3303,8 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps)
     qemuCaps->arch = VIR_ARCH_NONE;
     qemuCaps->usedQMP = false;
 
-    for (i = 0; i < qemuCaps->ncpuDefinitions; i++)
-        VIR_FREE(qemuCaps->cpuDefinitions[i]);
-    VIR_FREE(qemuCaps->cpuDefinitions);
-    qemuCaps->ncpuDefinitions = 0;
+    virObjectUnref(qemuCaps->cpuDefinitions);
+    qemuCaps->cpuDefinitions = NULL;
 
     for (i = 0; i < qemuCaps->nmachineTypes; i++) {
         VIR_FREE(qemuCaps->machineTypes[i].name);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 26ac1fa..e31c51c 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -423,10 +423,12 @@ virArch virQEMUCapsGetArch(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetVersion(virQEMUCapsPtr qemuCaps);
 const char *virQEMUCapsGetPackage(virQEMUCapsPtr qemuCaps);
 unsigned int virQEMUCapsGetKVMVersion(virQEMUCapsPtr qemuCaps);
-int virQEMUCapsAddCPUDefinition(virQEMUCapsPtr qemuCaps,
-                                const char *name);
-size_t virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
-                                    char ***names);
+int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps,
+                                 const char **name,
+                                 size_t count);
+int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
+                                 char ***names,
+                                 size_t *count);
 const char *virQEMUCapsGetCanonicalMachine(virQEMUCapsPtr qemuCaps,
                                            const char *name);
 int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps,
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 038c38f..c657354 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6586,9 +6586,10 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
 
     host = caps->host.cpu;
 
-    if (!host ||
-        !host->model ||
-        (ncpus = virQEMUCapsGetCPUDefinitions(qemuCaps, &cpus)) == 0) {
+    if (virQEMUCapsGetCPUDefinitions(qemuCaps, &cpus, &ncpus) < 0)
+        goto cleanup;
+
+    if (!host || !host->model || ncpus == 0) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("CPU specification not supported by hypervisor"));
         goto cleanup;
@@ -6742,6 +6743,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
     cpuDataFree(hostData);
     virCPUDefFree(guest);
     virCPUDefFree(cpu);
+    virStringFreeListCount(cpus, ncpus);
     return ret;
 }
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b9e2910..8083a36 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3587,7 +3587,7 @@ qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine)
 
 int
 qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
-                             char ***cpus)
+                             qemuMonitorCPUDefInfoPtr **cpus)
 {
     VIR_DEBUG("cpus=%p", cpus);
 
@@ -3597,6 +3597,16 @@ qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
 }
 
 
+void
+qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu)
+{
+    if (!cpu)
+        return;
+    VIR_FREE(cpu->name);
+    VIR_FREE(cpu);
+}
+
+
 int
 qemuMonitorGetCommands(qemuMonitorPtr mon,
                        char ***commands)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 615ab3e..7d78e5b 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -905,8 +905,16 @@ int qemuMonitorGetMachines(qemuMonitorPtr mon,
 
 void qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine);
 
+typedef struct _qemuMonitorCPUDefInfo qemuMonitorCPUDefInfo;
+typedef qemuMonitorCPUDefInfo *qemuMonitorCPUDefInfoPtr;
+
+struct _qemuMonitorCPUDefInfo {
+    char *name;
+};
+
 int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
-                                 char ***cpus);
+                                 qemuMonitorCPUDefInfoPtr **cpus);
+void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu);
 
 int qemuMonitorGetCommands(qemuMonitorPtr mon,
                            char ***commands);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index de746f1..e1494df 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4873,14 +4873,15 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
 }
 
 
-int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
-                                     char ***cpus)
+int
+qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
+                                 qemuMonitorCPUDefInfoPtr **cpus)
 {
     int ret = -1;
     virJSONValuePtr cmd;
     virJSONValuePtr reply = NULL;
     virJSONValuePtr data;
-    char **cpulist = NULL;
+    qemuMonitorCPUDefInfoPtr *cpulist = NULL;
     int n = 0;
     size_t i;
 
@@ -4916,13 +4917,18 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
         goto cleanup;
     }
 
-    /* null-terminated list */
-    if (VIR_ALLOC_N(cpulist, n + 1) < 0)
+    if (VIR_ALLOC_N(cpulist, n) < 0)
         goto cleanup;
 
     for (i = 0; i < n; i++) {
         virJSONValuePtr child = virJSONValueArrayGet(data, i);
         const char *tmp;
+        qemuMonitorCPUDefInfoPtr cpu;
+
+        if (VIR_ALLOC(cpu) < 0)
+            goto cleanup;
+
+        cpulist[i] = cpu;
 
         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -4930,7 +4936,7 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
             goto cleanup;
         }
 
-        if (VIR_STRDUP(cpulist[i], tmp) < 0)
+        if (VIR_STRDUP(cpu->name, tmp) < 0)
             goto cleanup;
     }
 
@@ -4939,7 +4945,11 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
     cpulist = NULL;
 
  cleanup:
-    virStringFreeList(cpulist);
+    if (cpulist) {
+        for (i = 0; i < n; i++)
+            qemuMonitorCPUDefInfoFree(cpulist[i]);
+        VIR_FREE(cpulist);
+    }
     virJSONValueFree(cmd);
     virJSONValueFree(reply);
     return ret;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 0eab96f..6a5eb3b 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -347,7 +347,7 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
     ATTRIBUTE_NONNULL(2);
 
 int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
-                                     char ***cpus)
+                                     qemuMonitorCPUDefInfoPtr **cpus)
     ATTRIBUTE_NONNULL(2);
 
 int qemuMonitorJSONGetCommands(qemuMonitorPtr mon,
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 9e195d7..cbc39c6 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -412,7 +412,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data)
     virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
     qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
     int ret = -1;
-    char **cpus = NULL;
+    qemuMonitorCPUDefInfoPtr *cpus = NULL;
     int ncpus = 0;
     size_t i;
 
@@ -447,10 +447,10 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data)
 
 #define CHECK(i, wantname)                                              \
     do {                                                                \
-        if (STRNEQ(cpus[i], (wantname))) {                              \
+        if (STRNEQ(cpus[i]->name, (wantname))) {                        \
             virReportError(VIR_ERR_INTERNAL_ERROR,                      \
                            "name %s is not %s",                         \
-                           cpus[i], (wantname));                        \
+                           cpus[i]->name, (wantname));                  \
             goto cleanup;                                               \
         }                                                               \
     } while (0)
@@ -466,7 +466,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data)
  cleanup:
     qemuMonitorTestFree(test);
     for (i = 0; i < ncpus; i++)
-        VIR_FREE(cpus[i]);
+        qemuMonitorCPUDefInfoFree(cpus[i]);
     VIR_FREE(cpus);
     return ret;
 }
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index e854077..0b378a7 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -452,18 +452,18 @@ testAddCPUModels(virQEMUCapsPtr caps, bool skipLegacy)
         "486", "coreduo", "kvm32", "qemu32", "kvm64",
         "core2duo", "phenom", "qemu64",
     };
-    size_t i;
 
-    for (i = 0; i < ARRAY_CARDINALITY(newModels); i++) {
-        if (virQEMUCapsAddCPUDefinition(caps, newModels[i]) < 0)
-            return -1;
-    }
+    if (virQEMUCapsAddCPUDefinitions(caps, newModels,
+                                     ARRAY_CARDINALITY(newModels)) < 0)
+        return -1;
+
     if (skipLegacy)
         return 0;
-    for (i = 0; i < ARRAY_CARDINALITY(legacyModels); i++) {
-        if (virQEMUCapsAddCPUDefinition(caps, legacyModels[i]) < 0)
-            return -1;
-    }
+
+    if (virQEMUCapsAddCPUDefinitions(caps, legacyModels,
+                                     ARRAY_CARDINALITY(legacyModels)) < 0)
+        return -1;
+
     return 0;
 }
 
-- 
2.10.0




More information about the libvir-list mailing list