diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c71b4dcf44..b0e51eeca7 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, "%s\n",
virArchToString(qemuCaps->arch));
- for (i = 0; i < qemuCaps->ncpuDefinitions; i++) {
- virBufferEscapeString(&buf, "\n",
- qemuCaps->cpuDefinitions[i]);
+ if (qemuCaps->cpuDefinitions) {
+ for (i = 0; i < qemuCaps->cpuDefinitions->nmodels; i++) {
+ virDomainCapsCPUModelPtr cpu = qemuCaps->cpuDefinitions->models + i;
+ virBufferEscapeString(&buf, "\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 26ac1fa6c3..e31c51c8a0 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 2130a7e2e8..e611c7f255 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6566,9 +6566,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;
@@ -6722,6 +6723,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 b9e2910493..8083a36e99 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 615ab3e940..7d78e5b0fb 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 de746f172e..e1494df8f6 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 0eab96ff9e..6a5eb3b8b5 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 9e195d743c..cbc39c67dc 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 e8540779a4..0b378a7bde 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;
}