>From b55341d7c9516a531dafa7396d60cb86af5c3255 Mon Sep 17 00:00:00 2001
From: John Ferlan <jferlan@redhat.com>
Date: Fri, 23 Nov 2018 12:26:49 -0500
Subject: [PATCH] Fixes to CMT v9

-> Introduced virResctrlMonitorFreeStats to be the corollary of the
   virResctrlMonitorGetStats

-> Altered _virQEMUResctrlMonData to follow similar definitions that
   use VIR_APPEND_ELEMENT and then need to free each entry in a loop.

-> Altered qemuDomainGetResctrlMonData to build up @resdata on the fly
   using VIR_APPEND_ELEMENT

-> Added qemuDomainFreeResctrlMonData to undo

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_driver.c   | 86 +++++++++++++++++++++-------------------
 src/util/virresctrl.c    | 13 ++++++
 src/util/virresctrl.h    |  4 ++
 4 files changed, 63 insertions(+), 41 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8889aaa379..5018a13e9c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2692,6 +2692,7 @@ virResctrlInfoNew;
 virResctrlMonitorAddPID;
 virResctrlMonitorCreate;
 virResctrlMonitorDeterminePath;
+virResctrlMonitorFreeStats;
 virResctrlMonitorGetCacheOccupancy;
 virResctrlMonitorGetID;
 virResctrlMonitorNew;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d9e216ccf4..a8e0480ae1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19934,19 +19934,20 @@ typedef virQEMUResctrlMonData *virQEMUResctrlMonDataPtr;
 struct _virQEMUResctrlMonData {
     const char *name;
     char *vcpus;
-    virResctrlMonitorStatsPtr stats;
+    virResctrlMonitorStatsPtr *stats;
     size_t nstats;
 };
 
 
 static int
 qemuDomainGetResctrlMonData(virDomainObjPtr dom,
-                            virQEMUResctrlMonDataPtr resdata)
+                            virQEMUResctrlMonDataPtr *ret_resdata,
+                            size_t *nresdata)
 {
+    virQEMUResctrlMonDataPtr resdata;
     virDomainResctrlDefPtr resctrl = NULL;
     size_t i = 0;
     size_t j = 0;
-    size_t k = 0;
 
     for (i = 0; i < dom->def->nresctrls; i++) {
         resctrl = dom->def->resctrls[i];
@@ -19961,29 +19962,50 @@ qemuDomainGetResctrlMonData(virDomainObjPtr dom,
             if (domresmon->tag != VIR_RESCTRL_MONITOR_TYPE_CACHE)
                 continue;
 
+            if (VIR_ALLOC(resdata) < 0)
+                return -1;
+
             /* If virBitmapFormat successfully returns an vcpu string, then
-             * resdata[k].vcpus is assigned with an memory space holding it,
+             * resdata->vcpus is assigned with an memory space holding it,
              * let this newly allocated memory buffer to be freed along with
              * the free of 'resdata' */
-            if (!(resdata[k].vcpus = virBitmapFormat(domresmon->vcpus)))
-                return -1;
+            if (!(resdata->vcpus = virBitmapFormat(domresmon->vcpus)))
+                goto error;
 
-            if (!(resdata[k].name = virResctrlMonitorGetID(monitor))) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Could not get monitor ID"));
-                return -1;
-            }
+            resdata->name = virResctrlMonitorGetID(monitor);
 
-            if (virResctrlMonitorGetCacheOccupancy(monitor,
-                                                   &resdata[k].stats,
-                                                   &resdata[k].nstats) < 0)
-                return -1;
+            if (virResctrlMonitorGetCacheOccupancy(monitor, resdata->stats,
+                                                   &resdata->nstats) < 0)
+                goto error;
 
-            k++;
+            if (VIR_APPEND_ELEMENT(ret_resdata, *nresdata, resdata) < 0)
+                goto error;
         }
     }
 
     return 0;
+
+ error:
+    VIR_FREE(resdata->vcpus);
+    VIR_FREE(resdata);
+    return -1;
+}
+
+
+static void
+qemuDomainFreeResctrlMonData(virQEMUResctrlMonDataPtr resdata,
+                            unsigned int nresdata)
+{
+    size_t i;
+
+    if (!resdata)
+        return;
+
+    for (i = 0; i < nresdata; i++) {
+        VIR_FREE(resdata[i].vcpus);
+        virResctrlMonitorFreeStats(resdata[i].stats, resdata[i].nstats);
+    }
+    VIR_FREE(resdata);
 }
 
 
@@ -19994,9 +20016,7 @@ qemuDomainGetStatsCpuCache(virDomainObjPtr dom,
 {
     char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
     virQEMUResctrlMonDataPtr resdata = NULL;
-    virDomainResctrlDefPtr resctrl = NULL;
-    virDomainResctrlMonDefPtr domresmon = NULL;
-    unsigned int nresdata = 0;
+    size_t nresdata = 0;
     size_t i = 0;
     size_t j = 0;
     int ret = -1;
@@ -20004,24 +20024,12 @@ qemuDomainGetStatsCpuCache(virDomainObjPtr dom,
     if (!virDomainObjIsActive(dom))
         return 0;
 
-    for (i = 0; i < dom->def->nresctrls; i++) {
-        resctrl = dom->def->resctrls[i];
-        for (j = 0; j < resctrl->nmonitors; j++) {
-            domresmon = resctrl->monitors[j];
-            if (domresmon->tag == VIR_RESCTRL_MONITOR_TYPE_CACHE)
-                nresdata++;
-        }
-    }
+    if (qemuDomainGetResctrlMonData(dom, &resdata, &nresdata) < 0)
+        goto cleanup;
 
     if (nresdata == 0)
         return 0;
 
-    if (VIR_ALLOC_N(resdata, nresdata) < 0)
-        return -1;
-
-    if (qemuDomainGetResctrlMonData(dom, resdata) < 0)
-        goto cleanup;
-
     snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
              "cpu.cache.monitor.count");
     if (virTypedParamsAddUInt(&record->params, &record->nparams,
@@ -20057,26 +20065,22 @@ qemuDomainGetStatsCpuCache(virDomainObjPtr dom,
                      "cpu.cache.monitor.%zu.bank.%zu.id", i, j);
             if (virTypedParamsAddUInt(&record->params, &record->nparams,
                                       maxparams, param_name,
-                                      resdata[i].stats[j].id) < 0)
+                                      resdata[i].stats[j]->id) < 0)
                 goto cleanup;
 
             snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
                      "cpu.cache.monitor.%zu.bank.%zu.bytes", i, j);
             if (virTypedParamsAddUInt(&record->params, &record->nparams,
                                       maxparams, param_name,
-                                      resdata[i].stats[j].val) < 0)
+                                      resdata[i].stats[j]->val) < 0)
                 goto cleanup;
         }
     }
 
     ret = 0;
- cleanup:
-    for (i = 0; i < nresdata; i++) {
-        VIR_FREE(resdata[i].vcpus);
-        VIR_FREE(resdata[i].stats);
-    }
-    VIR_FREE(resdata);
 
+ cleanup:
+    qemuDomainFreeResctrlMonData(resdata, nresdata);
     return ret;
 }
 
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index b32eedc3b1..3319aa6b2d 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -2747,6 +2747,19 @@ virResctrlMonitorGetStats(virResctrlMonitorPtr monitor,
 }
 
 
+void
+virResctrlMonitorFreeStats(virResctrlMonitorStatsPtr *stats,
+                           size_t nstats)
+{
+    size_t i;
+
+    for (i = 0; i < nstats; i++)
+        VIR_FREE(stats[i]);
+
+    VIR_FREE(stats);
+}
+
+
 /*
  * virResctrlMonitorGetCacheOccupancy
  *
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index 45ec967630..d75ea8e823 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -227,6 +227,10 @@ virResctrlMonitorSetAlloc(virResctrlMonitorPtr monitor,
 int
 virResctrlMonitorRemove(virResctrlMonitorPtr monitor);
 
+void
+virResctrlMonitorFreeStats(virResctrlMonitorStatsPtr *stats,
+                           size_t nstats);
+
 int
 virResctrlMonitorGetCacheOccupancy(virResctrlMonitorPtr monitor,
                                    virResctrlMonitorStatsPtr *caches,
-- 
2.17.2

