qemu: Introduce qemuMonitorCPUDefs struct

It is a container for a CPU models list (qemuMonitorCPUDefInfo) and a
number of elements in this list.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Jiri Denemark 2019-09-24 13:42:00 +02:00
parent a94f67ee69
commit 3aa53dcf01
6 changed files with 88 additions and 84 deletions

View File

@ -2446,18 +2446,17 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon,
virArch arch, virArch arch,
virDomainCapsCPUModelsPtr *cpuModels) virDomainCapsCPUModelsPtr *cpuModels)
{ {
g_autoptr(qemuMonitorCPUDefs) defs = NULL;
virDomainCapsCPUModelsPtr models = NULL; virDomainCapsCPUModelsPtr models = NULL;
qemuMonitorCPUDefInfoPtr *cpus = NULL;
int ncpus = 0;
size_t i; size_t i;
int ret = -1; int ret = -1;
*cpuModels = NULL; *cpuModels = NULL;
if ((ncpus = qemuMonitorGetCPUDefinitions(mon, &cpus)) < 0) if (qemuMonitorGetCPUDefinitions(mon, &defs) < 0)
return -1; return -1;
if (ncpus == 0) { if (!defs) {
ret = 0; ret = 0;
goto cleanup; goto cleanup;
} }
@ -2472,29 +2471,29 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon,
goto cleanup; goto cleanup;
for (name = libvirtModels; name && *name; name++) { for (name = libvirtModels; name && *name; name++) {
for (i = 0; i < ncpus; i++) { for (i = 0; i < defs->ncpus; i++) {
if (STRCASENEQ(cpus[i]->name, *name)) if (STRCASENEQ(defs->cpus[i]->name, *name))
continue; continue;
VIR_FREE(cpus[i]->name); VIR_FREE(defs->cpus[i]->name);
cpus[i]->name = g_strdup(*name); defs->cpus[i]->name = g_strdup(*name);
} }
} }
} }
if (!(models = virDomainCapsCPUModelsNew(ncpus))) if (!(models = virDomainCapsCPUModelsNew(defs->ncpus)))
goto cleanup; goto cleanup;
for (i = 0; i < ncpus; i++) { for (i = 0; i < defs->ncpus; i++) {
virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; 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; 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; usable = VIR_DOMCAPS_CPU_USABLE_NO;
if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable, if (virDomainCapsCPUModelsAddSteal(models, &defs->cpus[i]->name, usable,
&cpus[i]->blockers) < 0) &defs->cpus[i]->blockers) < 0)
goto cleanup; goto cleanup;
} }
@ -2502,9 +2501,6 @@ virQEMUCapsFetchCPUDefinitions(qemuMonitorPtr mon,
ret = 0; ret = 0;
cleanup: cleanup:
for (i = 0; i < ncpus; i++)
qemuMonitorCPUDefInfoFree(cpus[i]);
VIR_FREE(cpus);
virObjectUnref(models); virObjectUnref(models);
return ret; return ret;
} }

View File

@ -3550,25 +3550,45 @@ qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine)
int int
qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus) qemuMonitorCPUDefsPtr *cpuDefs)
{ {
VIR_DEBUG("cpus=%p", cpus); VIR_DEBUG("cpuDefs=%p", cpuDefs);
QEMU_CHECK_MONITOR(mon); QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONGetCPUDefinitions(mon, cpus); return qemuMonitorJSONGetCPUDefinitions(mon, cpuDefs);
} }
void void
qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu) qemuMonitorCPUDefsFree(qemuMonitorCPUDefsPtr defs)
{ {
if (!cpu) size_t i;
if (!defs)
return; return;
virStringListFree(cpu->blockers); for (i = 0; i < defs->ncpus; i++) {
VIR_FREE(cpu->name); g_strfreev(defs->cpus[i]->blockers);
VIR_FREE(cpu); 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);
} }

View File

@ -1093,9 +1093,19 @@ struct _qemuMonitorCPUDefInfo {
char **blockers; /* NULL-terminated string list */ char **blockers; /* NULL-terminated string list */
}; };
typedef struct _qemuMonitorCPUDefs qemuMonitorCPUDefs;
typedef qemuMonitorCPUDefs *qemuMonitorCPUDefsPtr;
struct _qemuMonitorCPUDefs {
size_t ncpus;
qemuMonitorCPUDefInfoPtr *cpus;
};
int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus); qemuMonitorCPUDefsPtr *cpuDefs);
void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu); qemuMonitorCPUDefsPtr qemuMonitorCPUDefsNew(size_t count);
void qemuMonitorCPUDefsFree(qemuMonitorCPUDefsPtr defs);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorCPUDefs, qemuMonitorCPUDefsFree);
typedef enum { typedef enum {
QEMU_MONITOR_CPU_PROPERTY_BOOLEAN, QEMU_MONITOR_CPU_PROPERTY_BOOLEAN,

View File

@ -5571,56 +5571,53 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
int int
qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus) qemuMonitorCPUDefsPtr *cpuDefs)
{ {
int ret = -1; g_autoptr(qemuMonitorCPUDefs) defs = NULL;
g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) cmd = NULL;
g_autoptr(virJSONValue) reply = NULL; g_autoptr(virJSONValue) reply = NULL;
virJSONValuePtr data; virJSONValuePtr data;
qemuMonitorCPUDefInfoPtr *cpulist = NULL; size_t ncpus;
size_t n = 0;
size_t i; size_t i;
*cpus = NULL; *cpuDefs = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-definitions", NULL))) if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-definitions", NULL)))
return -1; return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup; return -1;
/* Urgh, some QEMU architectures have the query-cpu-definitions /* Urgh, some QEMU architectures have the query-cpu-definitions
* command, but return 'GenericError' with string "Not supported", * command, but return 'GenericError' with string "Not supported",
* instead of simply omitting the command entirely :-( * instead of simply omitting the command entirely :-(
*/ */
if (qemuMonitorJSONHasError(reply, "GenericError")) { if (qemuMonitorJSONHasError(reply, "GenericError"))
ret = 0; return 0;
goto cleanup;
}
if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
goto cleanup; return -1;
data = virJSONValueObjectGetArray(reply, "return"); data = virJSONValueObjectGetArray(reply, "return");
n = virJSONValueArraySize(data); ncpus = virJSONValueArraySize(data);
if (VIR_ALLOC_N(cpulist, n) < 0) if (!(defs = qemuMonitorCPUDefsNew(ncpus)))
goto cleanup; return -1;
for (i = 0; i < n; i++) { for (i = 0; i < defs->ncpus; i++) {
virJSONValuePtr child = virJSONValueArrayGet(data, i); virJSONValuePtr child = virJSONValueArrayGet(data, i);
const char *tmp; const char *tmp;
qemuMonitorCPUDefInfoPtr cpu; qemuMonitorCPUDefInfoPtr cpu;
if (VIR_ALLOC(cpu) < 0) if (VIR_ALLOC(cpu) < 0)
goto cleanup; return -1;
cpulist[i] = cpu; defs->cpus[i] = cpu;
if (!(tmp = virJSONValueObjectGetString(child, "name"))) { if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("query-cpu-definitions reply data was missing 'name'")); _("query-cpu-definitions reply data was missing 'name'"));
goto cleanup; return -1;
} }
cpu->name = g_strdup(tmp); cpu->name = g_strdup(tmp);
@ -5636,7 +5633,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unavailable-features in query-cpu-definitions " _("unavailable-features in query-cpu-definitions "
"reply data was not an array")); "reply data was not an array"));
goto cleanup; return -1;
} }
len = virJSONValueArraySize(blockers); len = virJSONValueArraySize(blockers);
@ -5648,7 +5645,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
cpu->usable = VIR_TRISTATE_BOOL_NO; cpu->usable = VIR_TRISTATE_BOOL_NO;
if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0) if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0)
goto cleanup; return -1;
for (j = 0; j < len; j++) { for (j = 0; j < len; j++) {
virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j);
@ -5657,7 +5654,7 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unexpected value in unavailable-features " _("unexpected value in unavailable-features "
"array")); "array"));
goto cleanup; return -1;
} }
cpu->blockers[j] = g_strdup(virJSONValueGetString(blocker)); cpu->blockers[j] = g_strdup(virJSONValueGetString(blocker));
@ -5665,17 +5662,8 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
} }
} }
ret = n; *cpuDefs = g_steal_pointer(&defs);
*cpus = cpulist; return 0;
cpulist = NULL;
cleanup:
if (cpulist) {
for (i = 0; i < n; i++)
qemuMonitorCPUDefInfoFree(cpulist[i]);
VIR_FREE(cpulist);
}
return ret;
} }

View File

@ -379,7 +379,7 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
qemuMonitorCPUDefInfoPtr **cpus) qemuMonitorCPUDefsPtr *cpuDefs)
ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon, int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,

View File

@ -428,10 +428,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque)
{ {
const testGenericData *data = opaque; const testGenericData *data = opaque;
virDomainXMLOptionPtr xmlopt = data->xmlopt; virDomainXMLOptionPtr xmlopt = data->xmlopt;
int ret = -1; g_autoptr(qemuMonitorCPUDefs) defs = NULL;
qemuMonitorCPUDefInfoPtr *cpus = NULL;
int ncpus = 0;
size_t i;
g_autoptr(qemuMonitorTest) test = NULL; g_autoptr(qemuMonitorTest) test = NULL;
if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema))) if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
@ -453,31 +450,30 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque)
" } " " } "
" ]" " ]"
"}") < 0) "}") < 0)
goto cleanup; return -1;
if ((ncpus = qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test), if (qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test), &defs) < 0)
&cpus)) < 0) return -1;
goto cleanup;
if (ncpus != 3) { if (defs->ncpus != 3) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
"ncpus %d is not 3", ncpus); "ncpus %zu is not 3", defs->ncpus);
goto cleanup; return -1;
} }
#define CHECK_FULL(i, wantname, Usable) \ #define CHECK_FULL(i, wantname, Usable) \
do { \ do { \
if (STRNEQ(cpus[i]->name, (wantname))) { \ if (STRNEQ(defs->cpus[i]->name, (wantname))) { \
virReportError(VIR_ERR_INTERNAL_ERROR, \ virReportError(VIR_ERR_INTERNAL_ERROR, \
"name %s is not %s", \ "name %s is not %s", \
cpus[i]->name, (wantname)); \ defs->cpus[i]->name, (wantname)); \
goto cleanup; \ return -1; \
} \ } \
if (cpus[i]->usable != (Usable)) { \ if (defs->cpus[i]->usable != (Usable)) { \
virReportError(VIR_ERR_INTERNAL_ERROR, \ virReportError(VIR_ERR_INTERNAL_ERROR, \
"%s: expecting usable flag %d, got %d", \ "%s: expecting usable flag %d, got %d", \
cpus[i]->name, Usable, cpus[i]->usable); \ defs->cpus[i]->name, Usable, defs->cpus[i]->usable); \
goto cleanup; \ return -1; \
} \ } \
} while (0) } while (0)
@ -496,13 +492,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *opaque)
#undef CHECK_USABLE #undef CHECK_USABLE
#undef CHECK_FULL #undef CHECK_FULL
ret = 0; return 0;
cleanup:
for (i = 0; i < ncpus; i++)
qemuMonitorCPUDefInfoFree(cpus[i]);
VIR_FREE(cpus);
return ret;
} }