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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list