[libvirt] [PATCH 4/6] qemu: add architecture-specific CPU info handling
Peter Krempa
pkrempa at redhat.com
Fri Mar 2 11:42:31 UTC 2018
On Fri, Mar 02, 2018 at 10:29:09 +0100, Viktor Mihajlovski wrote:
> Extract architecture specific data from query-cpus[-fast] if
> available. A new function qemuMonitorJSONExtractCPUArchInfo()
> uses a call-back table to find and call architecture-specific
> extraction handlers.
>
> Initially, there's a handler for s390 cpu info to
> set the halted property depending on the s390 cpu state
> returned by QEMU. With this it's still possible to report
> the halted condition even when using query-cpus-fast.
>
> Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
> Reviewed-by: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> ---
> src/qemu/qemu_monitor.c | 6 ++-
> src/qemu/qemu_monitor_json.c | 123 ++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 126 insertions(+), 3 deletions(-)
>
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index dad1383..5a0e8a7 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -2083,12 +2083,16 @@ qemuMonitorGetCpuHalted(qemuMonitorPtr mon,
> size_t i;
> int rc;
> virBitmapPtr ret = NULL;
> + bool fast;
>
> QEMU_CHECK_MONITOR_NULL(mon);
>
> + fast = virQEMUCapsGet(QEMU_DOMAIN_PRIVATE(mon->vm)->qemuCaps,
As said, mon->vm should not be used here.
> + QEMU_CAPS_QUERY_CPUS_FAST);
> +
> if (mon->json)
> rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, false,
> - false);
> + fast);
> else
> rc = qemuMonitorTextQueryCPUs(mon, &cpuentries, &ncpuentries);
>
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 2ecdf0a..a408cfd 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -1451,15 +1451,128 @@ int qemuMonitorJSONSystemReset(qemuMonitorPtr mon)
> }
>
>
> -/*
> +typedef struct {
> + const char *state;
> + bool halted;
> +} s390CpuStateMap;
> +
> +/**
> + * qemuMonitorJSONExtractCPUS390Info:
> + * @jsoncpu: pointer to a single JSON cpu entry
> + * @cpu: pointer to a single cpu entry
> + *
> + * Derive the legacy cpu info 'halted' information
> + * from the more accurate s390 cpu state. @cpu is
> + * modified only on success.
> + *
> + * Note: the 'uninitialized' s390 cpu state can't be
> + * mapped to halted yes/no.
> + *
> + * A s390 cpu entry could look like this
> + * { "arch": "s390",
> + * "cpu-index": 0,
> + * "qom-path": "/machine/unattached/device[0]",
> + * "thread_id": 3081,
> + * "cpu-state": "operating" }
> + *
> + * Returns 0 on success, and -2 if no cpu-state field was
> + * found or the state value is unknown.
> + */
> +static int
> +qemuMonitorJSONExtractCPUS390Info(virJSONValuePtr jsoncpu,
> + struct qemuMonitorQueryCpusEntry *cpu)
> +{
> + const char *cpu_state;
> + s390CpuStateMap states[] = {
> + { "operating", false},
> + { "load", false},
> + { "stopped", true},
> + { "check-stop", true},
> + };
> + size_t i;
> +
> + if ((cpu_state = virJSONValueObjectGetString(jsoncpu, "cpu-state"))) {
> + for (i = 0; i < ARRAY_CARDINALITY(states); i++) {
> + if (STREQ(states[i].state, cpu_state)) {
> + cpu->halted = states[i].halted;
> + return 0;
> + }
> + }
> + }
> +
> + return -2;
> +}
> +
> +typedef struct {
> + const char *arch;
> + int (*extract)(virJSONValuePtr jsoncpu,
> + struct qemuMonitorQueryCpusEntry *cpu);
> +} qemuCpuArchInfoHandler;
> +
> +
> +/**
> + * qemuMonitorJSONExtractCPUArchInfo:
> + * @arch: virtual CPU's architecture
> + * @jsoncpu: pointer to a single JSON cpu entry
> + * @cpu: pointer to a single cpu entry
> + *
> + * Extracts architecure specific virtual CPU data for a single
> + * CPU from the QAPI response using an architecture specific
> + * callback.
> *
> + * To add a support for a new architecture, extend the array
> + * 'handlers' with a line like
> + * ...
> + * { "newarch", qemuMonitorJSONExtractCPUNewarch },
This should be obvious from the code.
> + * ...
> + * and implement the extraction callback.
> + * Check the QEMU QAPI schema for valid architecture names.
> + *
> + * Returns the called handler's return value or 0, if no handler
> + * was called.
> + */
> +static int
> +qemuMonitorJSONExtractCPUArchInfo(const char *arch, virJSONValuePtr jsoncpu,
> + struct qemuMonitorQueryCpusEntry *cpu)
Please don't mix header alignment styles.
> +{
> + qemuCpuArchInfoHandler handlers[] = {
> + { "s390", qemuMonitorJSONExtractCPUS390Info },
> + };
> + size_t i;
> +
> + for (i = 0; i < ARRAY_CARDINALITY(handlers); i++) {
> + if (STREQ(handlers[i].arch, arch))
> + return handlers[i].extract(jsoncpu, cpu);
You can remove the callback topology and hard-code the STREQs. It will
result in the same execution complexity, but be clearer to understand
than the callback-topology.
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * qemuMonitorJSONExtractCPUArchInfo:
> + * @data: JSON response data
> + * @entries: filled with detected cpu entries on success
> + * @nentries: number of entries returned
> + * @fast: true if this is a response from query-cpus-fast
> + *
> + * The JSON response @data will have the following format
> + * in case @fast == false
> * [{ "arch": "x86",
> * "current": true,
> * "CPU": 0,
> * "qom_path": "/machine/unattached/device[0]",
> * "pc": -2130415978,
> * "halted": true,
> - * "thread_id": 2631237},
> + * "thread_id": 2631237,
> + * ...},
> + * {...}
> + * ]
> + * and for @fast == true
> + * [{ "arch": "x86",
> + * "cpu-index": 0,
> + * "qom-path": "/machine/unattached/device[0]",
> + * "thread_id": 2631237,
> + * ...},
> * {...}
> * ]
> */
> @@ -1486,6 +1599,7 @@ qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
> int thread = 0;
> bool halted = false;
> const char *qom_path;
> + const char *arch;
> if (!entry) {
> ret = -2;
> goto cleanup;
> @@ -1505,6 +1619,11 @@ qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
> cpus[i].halted = halted;
> if (VIR_STRDUP(cpus[i].qom_path, qom_path) < 0)
> goto cleanup;
> +
> + /* process optional architecture-specific data */
> + if ((arch = virJSONValueObjectGetString(entry, "arch")))
> + ignore_value(qemuMonitorJSONExtractCPUArchInfo(arch, entry,
> + cpus + i));
So why does this function try to return something if the only caller
does not care?
> }
>
> VIR_STEAL_PTR(*entries, cpus);
> --
> 1.9.1
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20180302/0353e892/attachment-0001.sig>
More information about the libvir-list
mailing list