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,
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;
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}