[libvirt] [PATCH v5 09/15] qemu_driver: hook up query-cpu-model-baseline
Jiri Denemark
jdenemar at redhat.com
Wed Oct 2 13:52:15 UTC 2019
On Thu, Sep 19, 2019 at 16:25:00 -0400, Collin Walling wrote:
> This command is hooked into the virsh hypervisor-cpu-baseline command.
> The CPU models provided in the XML sent to the command will be baselined
> via the query-cpu-model-baseline QMP command. The resulting CPU model
> will be reported.
>
> Signed-off-by: Collin Walling <walling at linux.ibm.com>
> Reviewed-by: Daniel Henrique Barboza <danielh413 at gmail.com>
> ---
> src/qemu/qemu_driver.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 88 insertions(+)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 1e041a8..2a5a3ca 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -13810,6 +13810,83 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
> }
>
>
> +static int
> +qemuConnectStealCPUModelFromInfo(virCPUDefPtr dst,
> + qemuMonitorCPUModelInfoPtr *src)
> +{
> + qemuMonitorCPUModelInfoPtr info = *src;
> + size_t i;
> + int ret = 0;
We usually initialize ret to -1 and set it to zero at the very end when
everything is done rather than changing it to -1 on each error path.
> +
> + virCPUDefFreeModel(dst);
> +
> + VIR_STEAL_PTR(dst->model, info->name);
> +
> + for (i = 0; i < info->nprops; i++) {
> + char *name = info->props[i].name;
> +
> + if (info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_BOOLEAN &&
> + info->props[i].value.boolean &&
> + virCPUDefAddFeature(dst, name, VIR_CPU_FEATURE_REQUIRE) < 0) {
> + virCPUDefFree(dst);
This would cause double free in the caller.
> + ret = -1;
> + break;
> + }
> + }
> +
Adding cleanup label here would be better.
> + qemuMonitorCPUModelInfoFree(info);
> + *src = NULL;
You can avoid this by using VIR_STEAL_PTR(info, *src) at the beginning.
> + return ret;
> +}
> +
> +
> +static virCPUDefPtr
> +qemuConnectCPUModelBaseline(virQEMUCapsPtr qemuCaps,
> + const char *libDir,
> + uid_t runUid,
> + gid_t runGid,
> + int ncpus,
> + virCPUDefPtr *cpus)
I think I mentioned in my previous review (probably not in this exact
context, though) we usually pass an array followed by the number of
elements.
> +{
> + qemuProcessQMPPtr proc;
> + virCPUDefPtr baseline = NULL;
> + qemuMonitorCPUModelInfoPtr result = NULL;
> + size_t i;
> +
> + if (!(proc = qemuProcessQMPNew(virQEMUCapsGetBinary(qemuCaps),
> + libDir, runUid, runGid, false)))
> + goto cleanup;
> +
> + if (qemuProcessQMPStart(proc) < 0)
> + goto cleanup;
> +
> + if (VIR_ALLOC(baseline) < 0)
> + goto error;
> +
> + if (virCPUDefCopyModel(baseline, cpus[0], false))
> + goto error;
> +
> + for (i = 1; i < ncpus; i++) {
> +
Extra empty line.
> + if (qemuMonitorGetCPUModelBaseline(proc->mon, baseline,
> + cpus[i], &result) < 0)
> + goto error;
> +
> + /* result is freed regardless of this function's success */
I think this comment would be better placed as a documentation of the
new function.
> + if (qemuConnectStealCPUModelFromInfo(baseline, &result) < 0)
> + goto error;
> + }
> +
You could steal from baseline to ret, free baseline unconditionally and
return ret to get rid of the error label.
> + cleanup:
> + qemuProcessQMPFree(proc);
> + return baseline;
> +
> + error:
> + virCPUDefFree(baseline);
> + goto cleanup;
> +}
> +
> +
> static char *
> qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
> const char *emulator,
> @@ -13821,6 +13898,7 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
> unsigned int flags)
> {
> virQEMUDriverPtr driver = conn->privateData;
> + VIR_AUTOUNREF(virQEMUDriverConfigPtr) cfg = virQEMUDriverGetConfig(driver);
> virCPUDefPtr *cpus = NULL;
> virQEMUCapsPtr qemuCaps = NULL;
> virArch arch;
> @@ -13875,6 +13953,16 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
> if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
> (const char **)features, migratable)))
> goto cleanup;
> +
> + } else if (ARCH_IS_S390(arch) &&
> + virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_BASELINE)) {
> +
> + if (!(cpu = qemuConnectCPUModelBaseline(qemuCaps, cfg->libDir,
> + cfg->user, cfg->group,
> + ncpus,
> + cpus)))
> + goto cleanup;
> +
Three extra empty lines in this hunk.
> } else {
> virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
> _("computing baseline hypervisor CPU is not supported "
With the following patch squashed in
Reviewed-by: Jiri Denemark <jdenemar at redhat.com>
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b25e554358..b772a920e3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13739,32 +13739,41 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
}
+/**
+ * qemuConnectStealCPUModelFromInfo:
+ *
+ * Consumes @src and replaces the content of @dst with CPU model name and
+ * features from @src. When this function returns (both with success or
+ * failure), @src is freed.
+ */
static int
qemuConnectStealCPUModelFromInfo(virCPUDefPtr dst,
qemuMonitorCPUModelInfoPtr *src)
{
- qemuMonitorCPUModelInfoPtr info = *src;
+ qemuMonitorCPUModelInfoPtr info;
size_t i;
- int ret = 0;
+ int ret = -1;
virCPUDefFreeModel(dst);
+ VIR_STEAL_PTR(info, *src);
VIR_STEAL_PTR(dst->model, info->name);
for (i = 0; i < info->nprops; i++) {
char *name = info->props[i].name;
- if (info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_BOOLEAN &&
- info->props[i].value.boolean &&
- virCPUDefAddFeature(dst, name, VIR_CPU_FEATURE_REQUIRE) < 0) {
- virCPUDefFree(dst);
- ret = -1;
- break;
- }
+ if (info->props[i].type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN ||
+ !info->props[i].value.boolean)
+ continue;
+
+ if (virCPUDefAddFeature(dst, name, VIR_CPU_FEATURE_REQUIRE) < 0)
+ goto cleanup;
}
+ ret = 0;
+
+ cleanup:
qemuMonitorCPUModelInfoFree(info);
- *src = NULL;
return ret;
}
@@ -13774,10 +13783,11 @@ qemuConnectCPUModelBaseline(virQEMUCapsPtr qemuCaps,
const char *libDir,
uid_t runUid,
gid_t runGid,
- int ncpus,
- virCPUDefPtr *cpus)
+ virCPUDefPtr *cpus,
+ int ncpus)
{
qemuProcessQMPPtr proc;
+ virCPUDefPtr ret = NULL;
virCPUDefPtr baseline = NULL;
qemuMonitorCPUModelInfoPtr result = NULL;
size_t i;
@@ -13790,29 +13800,26 @@ qemuConnectCPUModelBaseline(virQEMUCapsPtr qemuCaps,
goto cleanup;
if (VIR_ALLOC(baseline) < 0)
- goto error;
+ goto cleanup;
if (virCPUDefCopyModel(baseline, cpus[0], false))
- goto error;
+ goto cleanup;
for (i = 1; i < ncpus; i++) {
-
if (qemuMonitorGetCPUModelBaseline(proc->mon, baseline,
cpus[i], &result) < 0)
- goto error;
+ goto cleanup;
- /* result is freed regardless of this function's success */
if (qemuConnectStealCPUModelFromInfo(baseline, &result) < 0)
- goto error;
+ goto cleanup;
}
+ VIR_STEAL_PTR(ret, baseline);
+
cleanup:
qemuProcessQMPFree(proc);
- return baseline;
-
- error:
virCPUDefFree(baseline);
- goto cleanup;
+ return ret;
}
@@ -13882,16 +13889,12 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
(const char **)features, migratable)))
goto cleanup;
-
} else if (ARCH_IS_S390(arch) &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_BASELINE)) {
-
if (!(cpu = qemuConnectCPUModelBaseline(qemuCaps, cfg->libDir,
cfg->user, cfg->group,
- ncpus,
- cpus)))
+ cpus, ncpus)))
goto cleanup;
-
} else {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("computing baseline hypervisor CPU is not supported "
More information about the libvir-list
mailing list