|
|
6ae9ed |
From 4da15317e206ea8dede92b8b6e37805473df5a2f Mon Sep 17 00:00:00 2001
|
|
|
6ae9ed |
Message-Id: <4da15317e206ea8dede92b8b6e37805473df5a2f@dist-git>
|
|
|
6ae9ed |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
6ae9ed |
Date: Wed, 24 Aug 2016 16:11:23 -0400
|
|
|
6ae9ed |
Subject: [PATCH] qemu: monitor: Add support for calling
|
|
|
6ae9ed |
query-hotpluggable-cpus
|
|
|
6ae9ed |
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1097930
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1224341
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Add support for retrieving information regarding hotpluggable cpu units
|
|
|
6ae9ed |
supported by qemu. Data returned by the command carries information
|
|
|
6ae9ed |
needed to figure out the granularity of hotplug, the necessary cpu type
|
|
|
6ae9ed |
name and the topology information.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Note that qemu doesn't specify any particular order of the entries thus
|
|
|
6ae9ed |
it's necessary sort them by socket_id, core_id and thread_id to the
|
|
|
6ae9ed |
order libvirt expects.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
(cherry picked from commit 1213f0f8a50d9d3b782e3c336e3373c35c652a55)
|
|
|
6ae9ed |
---
|
|
|
6ae9ed |
src/qemu/qemu_monitor.h | 16 ++++
|
|
|
6ae9ed |
src/qemu/qemu_monitor_json.c | 170 +++++++++++++++++++++++++++++++++++++++++++
|
|
|
6ae9ed |
src/qemu/qemu_monitor_json.h | 5 ++
|
|
|
6ae9ed |
3 files changed, 191 insertions(+)
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
|
|
6ae9ed |
index 83396a4..027a7a9 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_monitor.h
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_monitor.h
|
|
|
6ae9ed |
@@ -398,6 +398,22 @@ void qemuMonitorQueryCpusFree(struct qemuMonitorQueryCpusEntry *entries,
|
|
|
6ae9ed |
size_t nentries);
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+struct qemuMonitorQueryHotpluggableCpusEntry {
|
|
|
6ae9ed |
+ char *type; /* name of the cpu to use with device_add */
|
|
|
6ae9ed |
+ unsigned int vcpus; /* count of virtual cpus in the guest this entry adds */
|
|
|
6ae9ed |
+ char *qom_path; /* full device qom path only present for online cpus */
|
|
|
6ae9ed |
+ char *alias; /* device alias, may be NULL for non-hotpluggable entities */
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* topology information -1 if qemu didn't report given parameter */
|
|
|
6ae9ed |
+ int node_id;
|
|
|
6ae9ed |
+ int socket_id;
|
|
|
6ae9ed |
+ int core_id;
|
|
|
6ae9ed |
+ int thread_id;
|
|
|
6ae9ed |
+};
|
|
|
6ae9ed |
+void qemuMonitorQueryHotpluggableCpusFree(struct qemuMonitorQueryHotpluggableCpusEntry *entries,
|
|
|
6ae9ed |
+ size_t nentries);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
struct _qemuMonitorCPUInfo {
|
|
|
6ae9ed |
pid_t tid;
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
|
|
6ae9ed |
index a59b195..1871723 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_monitor_json.c
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_monitor_json.c
|
|
|
6ae9ed |
@@ -7209,3 +7209,173 @@ qemuMonitorJSONGetRTCTime(qemuMonitorPtr mon,
|
|
|
6ae9ed |
virJSONValueFree(reply);
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+void
|
|
|
6ae9ed |
+qemuMonitorQueryHotpluggableCpusFree(struct qemuMonitorQueryHotpluggableCpusEntry *entries,
|
|
|
6ae9ed |
+ size_t nentries)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ struct qemuMonitorQueryHotpluggableCpusEntry *entry;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!entries)
|
|
|
6ae9ed |
+ return;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < nentries; i++) {
|
|
|
6ae9ed |
+ entry = entries + i;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ VIR_FREE(entry->type);
|
|
|
6ae9ed |
+ VIR_FREE(entry->qom_path);
|
|
|
6ae9ed |
+ VIR_FREE(entry->alias);
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ VIR_FREE(entries);
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+/**
|
|
|
6ae9ed |
+ * [{
|
|
|
6ae9ed |
+ * "props": {
|
|
|
6ae9ed |
+ * "core-id": 0,
|
|
|
6ae9ed |
+ * "thread-id": 0,
|
|
|
6ae9ed |
+ * "socket-id": 0
|
|
|
6ae9ed |
+ * },
|
|
|
6ae9ed |
+ * "vcpus-count": 1,
|
|
|
6ae9ed |
+ * "qom-path": "/machine/unattached/device[0]",
|
|
|
6ae9ed |
+ * "type": "qemu64-x86_64-cpu"
|
|
|
6ae9ed |
+ * },
|
|
|
6ae9ed |
+ * {...}
|
|
|
6ae9ed |
+ * ]
|
|
|
6ae9ed |
+ */
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuMonitorJSONProcessHotpluggableCpusReply(virJSONValuePtr vcpu,
|
|
|
6ae9ed |
+ struct qemuMonitorQueryHotpluggableCpusEntry *entry)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virJSONValuePtr props;
|
|
|
6ae9ed |
+ const char *tmp;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(tmp = virJSONValueObjectGetString(vcpu, "type"))) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("query-hotpluggable-cpus didn't return device type"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (VIR_STRDUP(entry->type, tmp) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virJSONValueObjectGetNumberUint(vcpu, "vcpus-count", &entry->vcpus) < 0) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("query-hotpluggable-cpus didn't return vcpus-count"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(props = virJSONValueObjectGetObject(vcpu, "props"))) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("query-hotpluggable-cpus didn't return device props"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ entry->node_id = -1;
|
|
|
6ae9ed |
+ entry->socket_id = -1;
|
|
|
6ae9ed |
+ entry->core_id = -1;
|
|
|
6ae9ed |
+ entry->thread_id = -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ignore_value(virJSONValueObjectGetNumberInt(props, "node-id", &entry->node_id));
|
|
|
6ae9ed |
+ ignore_value(virJSONValueObjectGetNumberInt(props, "socket-id", &entry->socket_id));
|
|
|
6ae9ed |
+ ignore_value(virJSONValueObjectGetNumberInt(props, "core-id", &entry->core_id));
|
|
|
6ae9ed |
+ ignore_value(virJSONValueObjectGetNumberInt(props, "thread-id", &entry->thread_id));
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (entry->node_id == -1 && entry->socket_id == -1 &&
|
|
|
6ae9ed |
+ entry->core_id == -1 && entry->thread_id == -1) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("query-hotpluggable-cpus entry doesn't report "
|
|
|
6ae9ed |
+ "topology information"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* qom path is not present unless the vCPU is online */
|
|
|
6ae9ed |
+ if ((tmp = virJSONValueObjectGetString(vcpu, "qom-path"))) {
|
|
|
6ae9ed |
+ if (VIR_STRDUP(entry->qom_path, tmp) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ /* alias is the part after last slash having a "vcpu" prefix */
|
|
|
6ae9ed |
+ if ((tmp = strrchr(tmp, '/')) && STRPREFIX(tmp + 1, "vcpu")) {
|
|
|
6ae9ed |
+ if (VIR_STRDUP(entry->alias, tmp + 1) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+qemuMonitorQueryHotpluggableCpusEntrySort(const void *p1,
|
|
|
6ae9ed |
+ const void *p2)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ const struct qemuMonitorQueryHotpluggableCpusEntry *a = p1;
|
|
|
6ae9ed |
+ const struct qemuMonitorQueryHotpluggableCpusEntry *b = p2;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (a->socket_id != b->socket_id)
|
|
|
6ae9ed |
+ return a->socket_id - b->socket_id;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (a->core_id != b->core_id)
|
|
|
6ae9ed |
+ return a->core_id - b->core_id;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return a->thread_id - b->thread_id;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+int
|
|
|
6ae9ed |
+qemuMonitorJSONGetHotpluggableCPUs(qemuMonitorPtr mon,
|
|
|
6ae9ed |
+ struct qemuMonitorQueryHotpluggableCpusEntry **entries,
|
|
|
6ae9ed |
+ size_t *nentries)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ struct qemuMonitorQueryHotpluggableCpusEntry *info = NULL;
|
|
|
6ae9ed |
+ ssize_t ninfo = 0;
|
|
|
6ae9ed |
+ int ret = -1;
|
|
|
6ae9ed |
+ size_t i;
|
|
|
6ae9ed |
+ virJSONValuePtr data;
|
|
|
6ae9ed |
+ virJSONValuePtr cmd;
|
|
|
6ae9ed |
+ virJSONValuePtr reply = NULL;
|
|
|
6ae9ed |
+ virJSONValuePtr vcpu;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(cmd = qemuMonitorJSONMakeCommand("query-hotpluggable-cpus", NULL)))
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ data = virJSONValueObjectGet(reply, "return");
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((ninfo = virJSONValueArraySize(data)) < 0) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
6ae9ed |
+ _("query-hotpluggable-cpus reply is not an array"));
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (VIR_ALLOC_N(info, ninfo) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ for (i = 0; i < ninfo; i++) {
|
|
|
6ae9ed |
+ vcpu = virJSONValueArrayGet(data, i);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (qemuMonitorJSONProcessHotpluggableCpusReply(vcpu, info + i) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ qsort(info, ninfo, sizeof(*info), qemuMonitorQueryHotpluggableCpusEntrySort);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ VIR_STEAL_PTR(*entries, info);
|
|
|
6ae9ed |
+ *nentries = ninfo;
|
|
|
6ae9ed |
+ ret = 0;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ cleanup:
|
|
|
6ae9ed |
+ qemuMonitorQueryHotpluggableCpusFree(info, ninfo);
|
|
|
6ae9ed |
+ virJSONValueFree(cmd);
|
|
|
6ae9ed |
+ virJSONValueFree(reply);
|
|
|
6ae9ed |
+ return ret;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
|
|
|
6ae9ed |
index 2a439da..4db6067 100644
|
|
|
6ae9ed |
--- a/src/qemu/qemu_monitor_json.h
|
|
|
6ae9ed |
+++ b/src/qemu/qemu_monitor_json.h
|
|
|
6ae9ed |
@@ -504,4 +504,9 @@ int qemuMonitorJSONMigrateStartPostCopy(qemuMonitorPtr mon)
|
|
|
6ae9ed |
int qemuMonitorJSONGetRTCTime(qemuMonitorPtr mon,
|
|
|
6ae9ed |
struct tm *tm)
|
|
|
6ae9ed |
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+int qemuMonitorJSONGetHotpluggableCPUs(qemuMonitorPtr mon,
|
|
|
6ae9ed |
+ struct qemuMonitorQueryHotpluggableCpusEntry **entries,
|
|
|
6ae9ed |
+ size_t *nentries)
|
|
|
6ae9ed |
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
|
|
6ae9ed |
#endif /* QEMU_MONITOR_JSON_H */
|
|
|
6ae9ed |
--
|
|
|
6ae9ed |
2.10.0
|
|
|
6ae9ed |
|