[libvirt] [PATCH v4 4/8] qemu_driver: hook up query-cpu-model-baseline

Jiri Denemark jdenemar at redhat.com
Tue Aug 20 13:58:48 UTC 2019


On Wed, Jul 17, 2019 at 10:03:25 -0400, Collin Walling wrote:
> This command is hooked into the virsh hypervisor-cpu-baseline command.
> As such, the CPU models provided in the XML sent to the command will be
> baselined with the CPU contained in the QEMU capabilities file for the
> appropriate QEMU binary (for s390x, this CPU definition can be observed
> via virsh domcapabilities).

This is not how the baseline API works. If a user wants the current host
CPU model to be taken in the baseline computation, they need to provide
it in the array of input CPUs by themselves.

> 
> Signed-off-by: Collin Walling <walling at linux.ibm.com>
> Reviewed-by: Daniel Henrique Barboza <danielh413 at gmail.com>
> ---
>  src/qemu/qemu_capabilities.c | 84 ++++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_capabilities.h |  7 ++++
>  src/qemu/qemu_driver.c       | 27 ++++++++++++++
>  3 files changed, 118 insertions(+)
> 
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index b898113..ab337fa 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -5574,3 +5574,87 @@ virQEMUCapsStripMachineAliases(virQEMUCapsPtr qemuCaps)
>      for (i = 0; i < qemuCaps->nmachineTypes; i++)
>          VIR_FREE(qemuCaps->machineTypes[i].alias);
>  }
> +
> +
> +static int
> +virQEMUCapsStealCPUModelFromInfo(virCPUDefPtr dst,
> +                                 qemuMonitorCPUModelInfoPtr *src)
> +{
> +    qemuMonitorCPUModelInfoPtr info = *src;
> +    size_t i;
> +
> +    virCPUDefFreeModel(dst);
> +
> +    VIR_STEAL_PTR(dst->model, info->name);
> +
> +    for (i = 0; i < info->nprops; i++) {
> +        char *name = info->props[i].name;
> +        int policy = VIR_CPU_FEATURE_REQUIRE;
> +
> +        if (info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_BOOLEAN &&
> +            !info->props[i].value.boolean)
> +            policy = VIR_CPU_FEATURE_DISABLE;
> +
> +        if (virCPUDefAddFeature(dst, name, policy) < 0)
> +            goto error;
> +    }
> +
> +    qemuMonitorCPUModelInfoFree(info);
> +    *src = NULL;
> +    return 0;
> +
> + error:
> +    virCPUDefFree(dst);
> +    return -1;
> +}
> +
> +
> +virCPUDefPtr
> +virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
> +                            const char *libDir,
> +                            uid_t runUid,
> +                            gid_t runGid,
> +                            int ncpus,
> +                            virCPUDefPtr *cpus)

This function does not belong to qemu_capabilities.c, it should be in
qemu_driver.c and with a different prefix, of course. And this applies
to the helper above too.

> +{
> +    qemuMonitorCPUModelInfoPtr result = NULL;
> +    qemuProcessQMPPtr proc = NULL;
> +    virCPUDefPtr cpu = NULL;
> +    virCPUDefPtr baseline = NULL;
> +    size_t i;
> +
> +    if (VIR_ALLOC(cpu) < 0)
> +        goto cleanup;
> +
> +    if (virCPUDefCopyModel(cpu, cpus[0], false))
> +        goto cleanup;
> +
> +    if (!(proc = qemuProcessQMPNew(qemuCaps->binary, libDir,
> +                                   runUid, runGid, false)))
> +        goto cleanup;
> +
> +    if (qemuProcessQMPStart(proc) < 0)
> +        goto cleanup;
> +
> +    for (i = 1; i < ncpus; i++) {
> +        if (qemuMonitorGetCPUModelBaseline(proc->mon, cpu->model,
> +                                           cpu->nfeatures, cpu->features,
> +                                           cpus[i]->model, cpus[i]->nfeatures,
> +                                           cpus[i]->features, &result) < 0)

See my comment to 2/8. Wouldn't this be much better as

            if (qemuMonitorGetCPUModelBaseline(proc->mon, cpu, cpus[i],
                                               &result) < 0)

> +            goto cleanup;
> +
> +        if (virQEMUCapsStealCPUModelFromInfo(cpu, &result) < 0)
> +            goto cleanup;
> +    }
> +
> +    VIR_STEAL_PTR(baseline, cpu);
> +
> + cleanup:
> +    if (!baseline)
> +        virQEMUCapsLogProbeFailure(qemuCaps->binary);

There's no probing here. It's just an implementation of the API invoked
by libvirt client. No need to log anything here.

> +
> +    qemuMonitorCPUModelInfoFree(result);

As Boris already noticed, result cannot be non-NULL here. In fact, you
could even make the result variable local to the for loop.

> +    qemuProcessQMPFree(proc);
> +    virCPUDefFree(cpu);
> +    return baseline;
> +}
> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
> index 8dde759..b49c0b9 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -665,3 +665,10 @@ virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
>  
>  virArch virQEMUCapsArchFromString(const char *arch);
>  const char *virQEMUCapsArchToString(virArch arch);
> +
> +virCPUDefPtr virQEMUCapsCPUModelBaseline(virQEMUCapsPtr qemuCaps,
> +                                        const char *libDir,
> +                                        uid_t runUid,
> +                                        gid_t runGid,
> +                                        int ncpus,
> +                                        virCPUDefPtr *cpus);
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index d3a144a..37b9c75 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -13553,6 +13553,7 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>                                   unsigned int flags)
>  {
>      virQEMUDriverPtr driver = conn->privateData;
> +    virQEMUDriverConfigPtr config = driver->config;

You should use

       VIR_AUTOUNREF(virQEMUDriverConfigPtr) cfg = virQEMUDriverGetConfig(driver);

instead.

>      virCPUDefPtr *cpus = NULL;
>      virQEMUCapsPtr qemuCaps = NULL;
>      virArch arch;
> @@ -13607,6 +13608,32 @@ 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)) {
> +        /* Add a copy of the hypervisor CPU to the list */
> +        virCPUDefPtr hvCPU, tmp;
> +        size_t allocated = ncpus + 1;
> +
> +        hvCPU = virQEMUCapsGetHostModel(qemuCaps, virttype,
> +                                        VIR_QEMU_CAPS_HOST_CPU_REPORTED);
> +        if (VIR_ALLOC(tmp) < 0)
> +             goto cleanup;
> +
> +        if (virCPUDefCopyModel(tmp, hvCPU, false))
> +             goto cleanup;
> +
> +        if (VIR_INSERT_ELEMENT(cpus, ncpus, allocated, tmp) < 0)
> +             goto cleanup;
> +
> +        ncpus++;

All the code in this if statement down to here should go away.

> +
> +        if (!(cpu = virQEMUCapsCPUModelBaseline(qemuCaps, config->libDir,
> +                                                config->user, config->group,
> +                                                ncpus, cpus)))
> +            goto cleanup;
> +
> +        if (!(flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES))
> +            virCPUDefFreeFeatures(cpu);

This seems to be wrong.

>      } else {
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("computing baseline hypervisor CPU is not supported "

Jirka




More information about the libvir-list mailing list