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(a)redhat.com>
---
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 43e3ea7..1dcc970 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -373,8 +373,7 @@ struct _virQEMUCaps {
virArch arch;
- size_t ncpuDefinitions;
- char **cpuDefinitions;
+ virDomainCapsCPUModelsPtr cpuDefinitions;
size_t nmachineTypes;
struct virQEMUCapsMachineType *machineTypes;
@@ -612,7 +611,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;
@@ -634,9 +636,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
@@ -647,14 +646,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.
@@ -666,11 +667,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++;
@@ -691,19 +694,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
@@ -2033,11 +2033,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;
}
@@ -2076,9 +2074,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);
@@ -2216,28 +2212,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->count) <
0)
+ return -1;
+
+ for (i = 0; i < qemuCaps->cpuDefinitions->count; 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->count;
+ return 0;
+
+ error:
+ virStringFreeListCount(models, i);
+ return -1;
}
@@ -2534,16 +2560,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 {
@@ -2889,17 +2929,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);
@@ -3053,9 +3095,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->count; i++) {
+ virDomainCapsCPUModelPtr cpu = qemuCaps->cpuDefinitions->models + i;
+ virBufferEscapeString(&buf, "<cpu name='%s'/>\n",
cpu->name);
+ }
}
for (i = 0; i < qemuCaps->nmachineTypes; i++) {
@@ -3171,10 +3215,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 d249e2e..0767a87 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -418,10 +418,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 55df23d..3f542bc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6459,9 +6459,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;
@@ -6615,6 +6616,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 83e1272..4687660 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3317,7 +3317,7 @@ qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine)
int
qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
- char ***cpus)
+ qemuMonitorCPUDefInfoPtr **cpus)
{
VIR_DEBUG("cpus=%p", cpus);
@@ -3327,6 +3327,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 591d3ed..9e431ed 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -844,8 +844,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 d455adf..39ff24a 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4855,14 +4855,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;
@@ -4898,13 +4899,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",
@@ -4912,7 +4918,7 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
goto cleanup;
}
- if (VIR_STRDUP(cpulist[i], tmp) < 0)
+ if (VIR_STRDUP(cpu->name, tmp) < 0)
goto cleanup;
}
@@ -4921,7 +4927,11 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
cpulist = NULL;
cleanup:
- virStringFreeList(cpulist);
+ if (ret < 0 && 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 174f0ef..feb061f 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -346,7 +346,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 544b569..dab447b 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 ad0693f..a457c69 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.9.2