diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 61ccb62a14..6a2fdc8939 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2446,18 +2446,17 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon, virArch arch, virDomainCapsCPUModelsPtr *cpuModels) { + g_autoptr(qemuMonitorCPUDefs) defs = NULL; virDomainCapsCPUModelsPtr models = NULL; - qemuMonitorCPUDefInfoPtr *cpus = NULL; - int ncpus = 0; size_t i; int ret = -1; *cpuModels = NULL; - if ((ncpus = qemuMonitorGetCPUDefinitions(mon, &cpus)) < 0) + if (qemuMonitorGetCPUDefinitions(mon, &defs) < 0) return -1; - if (ncpus == 0) { + if (!defs) { ret = 0; goto cleanup; } @@ -2472,29 +2471,29 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon, goto cleanup; for (name = libvirtModels; name && *name; name++) { - for (i = 0; i < ncpus; i++) { - if (STRCASENEQ(cpus[i]->name, *name)) + for (i = 0; i < defs->ncpus; i++) { + if (STRCASENEQ(defs->cpus[i]->name, *name)) continue; - VIR_FREE(cpus[i]->name); - cpus[i]->name = g_strdup(*name); + VIR_FREE(defs->cpus[i]->name); + defs->cpus[i]->name = g_strdup(*name); } } } - if (!(models = virDomainCapsCPUModelsNew(ncpus))) + if (!(models = virDomainCapsCPUModelsNew(defs->ncpus))) goto cleanup; - for (i = 0; i < ncpus; i++) { + for (i = 0; i < defs->ncpus; i++) { virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; - if (cpus[i]->usable == VIR_TRISTATE_BOOL_YES) + if (defs->cpus[i]->usable == VIR_TRISTATE_BOOL_YES) usable = VIR_DOMCAPS_CPU_USABLE_YES; - else if (cpus[i]->usable == VIR_TRISTATE_BOOL_NO) + else if (defs->cpus[i]->usable == VIR_TRISTATE_BOOL_NO) usable = VIR_DOMCAPS_CPU_USABLE_NO; - if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable, - &cpus[i]->blockers) < 0) + if (virDomainCapsCPUModelsAddSteal(models, &defs->cpus[i]->name, usable, + &defs->cpus[i]->blockers) < 0) goto cleanup; } @@ -2502,9 +2501,6 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon, ret = 0; cleanup: - for (i = 0; i < ncpus; i++) - qemuMonitorCPUDefInfoFree(cpus[i]); - VIR_FREE(cpus); virObjectUnref(models); return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index cdad5c955d..2ee166592c 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3550,25 +3550,45 @@ qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine) int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, - qemuMonitorCPUDefInfoPtr **cpus) + qemuMonitorCPUDefsPtr *cpuDefs) { - VIR_DEBUG("cpus=%p", cpus); + VIR_DEBUG("cpuDefs=%p", cpuDefs); QEMU_CHECK_MONITOR(mon); - return qemuMonitorJSONGetCPUDefinitions(mon, cpus); + return qemuMonitorJSONGetCPUDefinitions(mon, cpuDefs); } void -qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu) +qemuMonitorCPUDefsFree(qemuMonitorCPUDefsPtr defs) { - if (!cpu) + size_t i; + + if (!defs) return; - virStringListFree(cpu->blockers); - VIR_FREE(cpu->name); - VIR_FREE(cpu); + for (i = 0; i < defs->ncpus; i++) { + g_strfreev(defs->cpus[i]->blockers); + g_free(defs->cpus[i]->name); + g_free(defs->cpus[i]); + } + + g_free(defs->cpus); + g_free(defs); +} + + +qemuMonitorCPUDefsPtr +qemuMonitorCPUDefsNew(size_t count) +{ + g_autoptr(qemuMonitorCPUDefs) defs = NULL; + + defs = g_new0(qemuMonitorCPUDefs, 1); + defs->cpus = g_new0(qemuMonitorCPUDefInfoPtr, count); + defs->ncpus = count; + + return g_steal_pointer(&defs); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a1c980e40e..058656e75e 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1093,9 +1093,19 @@ struct _qemuMonitorCPUDefInfo { char **blockers; /* NULL-terminated string list */ }; +typedef struct _qemuMonitorCPUDefs qemuMonitorCPUDefs; +typedef qemuMonitorCPUDefs *qemuMonitorCPUDefsPtr; +struct _qemuMonitorCPUDefs { + size_t ncpus; + qemuMonitorCPUDefInfoPtr *cpus; +}; + int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, - qemuMonitorCPUDefInfoPtr **cpus); -void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu); + qemuMonitorCPUDefsPtr *cpuDefs); +qemuMonitorCPUDefsPtr qemuMonitorCPUDefsNew(size_t count); +void qemuMonitorCPUDefsFree(qemuMonitorCPUDefsPtr defs); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorCPUDefs, qemuMonitorCPUDefsFree); + typedef enum { QEMU_MONITOR_CPU_PROPERTY_BOOLEAN, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index ae676f13d2..2a4c70ef26 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5571,56 +5571,53 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon, int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, - qemuMonitorCPUDefInfoPtr **cpus) + qemuMonitorCPUDefsPtr *cpuDefs) { - int ret = -1; + g_autoptr(qemuMonitorCPUDefs) defs = NULL; g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; virJSONValuePtr data; - qemuMonitorCPUDefInfoPtr *cpulist = NULL; - size_t n = 0; + size_t ncpus; size_t i; - *cpus = NULL; + *cpuDefs = NULL; if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-definitions", NULL))) return -1; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) - goto cleanup; + return -1; /* Urgh, some QEMU architectures have the query-cpu-definitions * command, but return 'GenericError' with string "Not supported", * instead of simply omitting the command entirely :-( */ - if (qemuMonitorJSONHasError(reply, "GenericError")) { - ret = 0; - goto cleanup; - } + if (qemuMonitorJSONHasError(reply, "GenericError")) + return 0; if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) - goto cleanup; + return -1; data = virJSONValueObjectGetArray(reply, "return"); - n = virJSONValueArraySize(data); + ncpus = virJSONValueArraySize(data); - if (VIR_ALLOC_N(cpulist, n) < 0) - goto cleanup; + if (!(defs = qemuMonitorCPUDefsNew(ncpus))) + return -1; - for (i = 0; i < n; i++) { + for (i = 0; i < defs->ncpus; i++) { virJSONValuePtr child = virJSONValueArrayGet(data, i); const char *tmp; qemuMonitorCPUDefInfoPtr cpu; if (VIR_ALLOC(cpu) < 0) - goto cleanup; + return -1; - cpulist[i] = cpu; + defs->cpus[i] = cpu; if (!(tmp = virJSONValueObjectGetString(child, "name"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("query-cpu-definitions reply data was missing 'name'")); - goto cleanup; + return -1; } cpu->name = g_strdup(tmp); @@ -5636,7 +5633,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("unavailable-features in query-cpu-definitions " "reply data was not an array")); - goto cleanup; + return -1; } len = virJSONValueArraySize(blockers); @@ -5648,7 +5645,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, cpu->usable = VIR_TRISTATE_BOOL_NO; if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0) - goto cleanup; + return -1; for (j = 0; j < len; j++) { virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); @@ -5657,7 +5654,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("unexpected value in unavailable-features " "array")); - goto cleanup; + return -1; } cpu->blockers[j] = g_strdup(virJSONValueGetString(blocker)); @@ -5665,17 +5662,8 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, } } - ret = n; - *cpus = cpulist; - cpulist = NULL; - - cleanup: - if (cpulist) { - for (i = 0; i < n; i++) - qemuMonitorCPUDefInfoFree(cpulist[i]); - VIR_FREE(cpulist); - } - return ret; + *cpuDefs = g_steal_pointer(&defs); + return 0; } diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 6617783797..25b568d6b0 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -379,7 +379,7 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon, ATTRIBUTE_NONNULL(2); int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, - qemuMonitorCPUDefInfoPtr **cpus) + qemuMonitorCPUDefsPtr *cpuDefs) ATTRIBUTE_NONNULL(2); int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 3977f2fcf8..ec5ce5b7db 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -428,10 +428,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque) { const testGenericData *data = opaque; virDomainXMLOptionPtr xmlopt = data->xmlopt; - int ret = -1; - qemuMonitorCPUDefInfoPtr *cpus = NULL; - int ncpus = 0; - size_t i; + g_autoptr(qemuMonitorCPUDefs) defs = NULL; g_autoptr(qemuMonitorTest) test = NULL; if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema))) @@ -453,31 +450,30 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque) " } " " ]" "}") < 0) - goto cleanup; + return -1; - if ((ncpus = qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test), - &cpus)) < 0) - goto cleanup; + if (qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test), &defs) < 0) + return -1; - if (ncpus != 3) { + if (defs->ncpus != 3) { virReportError(VIR_ERR_INTERNAL_ERROR, - "ncpus %d is not 3", ncpus); - goto cleanup; + "ncpus %zu is not 3", defs->ncpus); + return -1; } #define CHECK_FULL(i, wantname, Usable) \ do { \ - if (STRNEQ(cpus[i]->name, (wantname))) { \ + if (STRNEQ(defs->cpus[i]->name, (wantname))) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "name %s is not %s", \ - cpus[i]->name, (wantname)); \ - goto cleanup; \ + defs->cpus[i]->name, (wantname)); \ + return -1; \ } \ - if (cpus[i]->usable != (Usable)) { \ + if (defs->cpus[i]->usable != (Usable)) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "%s: expecting usable flag %d, got %d", \ - cpus[i]->name, Usable, cpus[i]->usable); \ - goto cleanup; \ + defs->cpus[i]->name, Usable, defs->cpus[i]->usable); \ + return -1; \ } \ } while (0) @@ -496,13 +492,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque) #undef CHECK_USABLE #undef CHECK_FULL - ret = 0; - - cleanup: - for (i = 0; i < ncpus; i++) - qemuMonitorCPUDefInfoFree(cpus[i]); - VIR_FREE(cpus); - return ret; + return 0; }