Blob Blame History Raw
From 69f7fb4615fb51ea9913650552b9d4937f2ad12b Mon Sep 17 00:00:00 2001
Message-Id: <69f7fb4615fb51ea9913650552b9d4937f2ad12b@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 24 Aug 2016 16:11:17 -0400
Subject: [PATCH] qemu: monitor: Return structures from qemuMonitorGetCPUInfo

https://bugzilla.redhat.com/show_bug.cgi?id=1097930
https://bugzilla.redhat.com/show_bug.cgi?id=1224341

The function will gradually add more returned data. Return a struct for
every vCPU containing the data.

(cherry picked from commit 5b5f494a1bc5af7d162ca23cdb6527d15620e851)
---
 src/qemu/qemu_domain.c  | 25 +++++++++-------------
 src/qemu/qemu_monitor.c | 57 +++++++++++++++++++++++++++++++++++++++++++------
 src/qemu/qemu_monitor.h | 13 ++++++++++-
 3 files changed, 72 insertions(+), 23 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 9cbf938..52e9c1e 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5687,10 +5687,11 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
                           int asyncJob)
 {
     virDomainVcpuDefPtr vcpu;
+    qemuDomainVcpuPrivatePtr vcpupriv;
+    qemuMonitorCPUInfoPtr info = NULL;
     size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
-    pid_t *cpupids = NULL;
-    int ncpupids;
     size_t i;
+    int rc;
     int ret = -1;
 
     /*
@@ -5726,32 +5727,26 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
         return -1;
-    ncpupids = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &cpupids);
+
+    rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus);
+
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
-    /* failure to get the VCPU <-> PID mapping or to execute the query
-     * command will not be treated fatal as some versions of qemu don't
-     * support this command */
-    if (ncpupids <= 0) {
-        virResetLastError();
-        ret = 0;
+    if (rc < 0)
         goto cleanup;
-    }
 
     for (i = 0; i < maxvcpus; i++) {
         vcpu = virDomainDefGetVcpu(vm->def, i);
+        vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
 
-        if (i < ncpupids)
-            QEMU_DOMAIN_VCPU_PRIVATE(vcpu)->tid = cpupids[i];
-        else
-            QEMU_DOMAIN_VCPU_PRIVATE(vcpu)->tid = 0;
+        vcpupriv->tid = info[i].tid;
     }
 
     ret = 0;
 
  cleanup:
-    VIR_FREE(cpupids);
+    qemuMonitorCPUInfoFree(info, maxvcpus);
     return ret;
 }
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 8a558ca..c3b9f41 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1651,25 +1651,68 @@ qemuMonitorSystemReset(qemuMonitorPtr mon)
 }
 
 
+void
+qemuMonitorCPUInfoFree(qemuMonitorCPUInfoPtr cpus,
+                       size_t ncpus ATTRIBUTE_UNUSED)
+{
+    if (!cpus)
+        return;
+
+    VIR_FREE(cpus);
+}
+
+
 /**
  * qemuMonitorGetCPUInfo:
  * @mon: monitor
- * @pids: returned array of thread ids corresponding to the vCPUs
+ * @vcpus: pointer filled by array of qemuMonitorCPUInfo structures
+ * @maxvcpus: total possible number of vcpus
  *
- * Detects the vCPU thread ids. Returns count of detected vCPUs on success,
- * 0 if qemu didn't report thread ids (does not report libvirt error),
- * -1 on error (reports libvirt error).
+ * Detects VCPU information. If qemu doesn't support or fails reporting
+ * information this function will return success as other parts of libvirt
+ * are able to cope with that.
+ *
+ * Returns 0 on success (including if qemu didn't report any data) and
+ *  -1 on error (reports libvirt error).
  */
 int
 qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
-                      int **pids)
+                      qemuMonitorCPUInfoPtr *vcpus,
+                      size_t maxvcpus)
 {
+    qemuMonitorCPUInfoPtr info = NULL;
+    int *pids = NULL;
+    size_t i;
+    int ret = -1;
+    int rc;
+
     QEMU_CHECK_MONITOR(mon);
 
+    if (VIR_ALLOC_N(info, maxvcpus) < 0)
+        return -1;
+
     if (mon->json)
-        return qemuMonitorJSONQueryCPUs(mon, pids);
+        rc = qemuMonitorJSONQueryCPUs(mon, &pids);
     else
-        return qemuMonitorTextQueryCPUs(mon, pids);
+        rc = qemuMonitorTextQueryCPUs(mon, &pids);
+
+    if (rc < 0) {
+        virResetLastError();
+        VIR_STEAL_PTR(*vcpus, info);
+        ret = 0;
+        goto cleanup;
+    }
+
+    for (i = 0; i < rc; i++)
+        info[i].tid = pids[i];
+
+    VIR_STEAL_PTR(*vcpus, info);
+    ret = 0;
+
+ cleanup:
+    qemuMonitorCPUInfoFree(info, maxvcpus);
+    VIR_FREE(pids);
+    return ret;
 }
 
 
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b2f20e9..3ab3f08 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -390,8 +390,19 @@ int qemuMonitorGetStatus(qemuMonitorPtr mon,
 int qemuMonitorSystemReset(qemuMonitorPtr mon);
 int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
 
+
+struct _qemuMonitorCPUInfo {
+    pid_t tid;
+};
+typedef struct _qemuMonitorCPUInfo qemuMonitorCPUInfo;
+typedef qemuMonitorCPUInfo *qemuMonitorCPUInfoPtr;
+
+void qemuMonitorCPUInfoFree(qemuMonitorCPUInfoPtr list,
+                            size_t nitems);
 int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
-                          int **pids);
+                          qemuMonitorCPUInfoPtr *vcpus,
+                          size_t maxvcpus);
+
 int qemuMonitorGetVirtType(qemuMonitorPtr mon,
                            virDomainVirtType *virtType);
 int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
-- 
2.10.0