99cbc7
From c402803b725543f690abd96175df12dbee224c58 Mon Sep 17 00:00:00 2001
99cbc7
Message-Id: <c402803b725543f690abd96175df12dbee224c58@dist-git>
99cbc7
From: Bing Niu <bing.niu@intel.com>
99cbc7
Date: Mon, 15 Apr 2019 17:32:47 +0200
99cbc7
Subject: [PATCH] util: Add MBA capability information query to resctrl
99cbc7
MIME-Version: 1.0
99cbc7
Content-Type: text/plain; charset=UTF-8
99cbc7
Content-Transfer-Encoding: 8bit
99cbc7
99cbc7
Introducing virResctrlInfoMemBW for the information memory bandwidth
99cbc7
allocation information.
99cbc7
99cbc7
Signed-off-by: Bing Niu <bing.niu@intel.com>
99cbc7
Reviewed-by: John Ferlan <jferlan@redhat.com>
99cbc7
(cherry picked from commit a24da791b8d489600807158c45451012ae1a8270)
99cbc7
99cbc7
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650
99cbc7
99cbc7
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
99cbc7
Message-Id: <5bf94bb7ee189420dfd99b19ff423c9650b1e637.1555342313.git.phrdina@redhat.com>
99cbc7
Reviewed-by: Ján Tomko <jtomko@redhat.com>
99cbc7
---
99cbc7
 src/util/virresctrl.c | 84 +++++++++++++++++++++++++++++++++++++++++++
99cbc7
 1 file changed, 84 insertions(+)
99cbc7
99cbc7
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
99cbc7
index a38c9261b6..b12a05cb0f 100644
99cbc7
--- a/src/util/virresctrl.c
99cbc7
+++ b/src/util/virresctrl.c
99cbc7
@@ -80,6 +80,9 @@ typedef virResctrlInfoPerType *virResctrlInfoPerTypePtr;
99cbc7
 typedef struct _virResctrlInfoPerLevel virResctrlInfoPerLevel;
99cbc7
 typedef virResctrlInfoPerLevel *virResctrlInfoPerLevelPtr;
99cbc7
 
99cbc7
+typedef struct _virResctrlInfoMemBW virResctrlInfoMemBW;
99cbc7
+typedef virResctrlInfoMemBW *virResctrlInfoMemBWPtr;
99cbc7
+
99cbc7
 typedef struct _virResctrlAllocPerType virResctrlAllocPerType;
99cbc7
 typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr;
99cbc7
 
99cbc7
@@ -116,11 +119,30 @@ struct _virResctrlInfoPerLevel {
99cbc7
     virResctrlInfoPerTypePtr *types;
99cbc7
 };
99cbc7
 
99cbc7
+/* Information about memory bandwidth allocation */
99cbc7
+struct _virResctrlInfoMemBW {
99cbc7
+    /* minimum memory bandwidth allowed */
99cbc7
+    unsigned int min_bandwidth;
99cbc7
+    /* bandwidth granularity */
99cbc7
+    unsigned int bandwidth_granularity;
99cbc7
+    /* Maximum number of simultaneous allocations */
99cbc7
+    unsigned int max_allocation;
99cbc7
+    /* level number of last level cache */
99cbc7
+    unsigned int last_level_cache;
99cbc7
+    /* max id of last level cache, this is used to track
99cbc7
+     * how many last level cache available in host system,
99cbc7
+     * the number of memory bandwidth allocation controller
99cbc7
+     * is identical with last level cache. */
99cbc7
+    unsigned int max_id;
99cbc7
+};
99cbc7
+
99cbc7
 struct _virResctrlInfo {
99cbc7
     virObject parent;
99cbc7
 
99cbc7
     virResctrlInfoPerLevelPtr *levels;
99cbc7
     size_t nlevels;
99cbc7
+
99cbc7
+    virResctrlInfoMemBWPtr membw_info;
99cbc7
 };
99cbc7
 
99cbc7
 
99cbc7
@@ -146,6 +168,7 @@ virResctrlInfoDispose(void *obj)
99cbc7
         VIR_FREE(level);
99cbc7
     }
99cbc7
 
99cbc7
+    VIR_FREE(resctrl->membw_info);
99cbc7
     VIR_FREE(resctrl->levels);
99cbc7
 }
99cbc7
 
99cbc7
@@ -442,6 +465,60 @@ virResctrlGetCacheInfo(virResctrlInfoPtr resctrl,
99cbc7
 }
99cbc7
 
99cbc7
 
99cbc7
+static int
99cbc7
+virResctrlGetMemoryBandwidthInfo(virResctrlInfoPtr resctrl)
99cbc7
+{
99cbc7
+    int ret = -1;
99cbc7
+    int rv = -1;
99cbc7
+    virResctrlInfoMemBWPtr i_membw = NULL;
99cbc7
+
99cbc7
+    /* query memory bandwidth allocation info */
99cbc7
+    if (VIR_ALLOC(i_membw) < 0)
99cbc7
+        goto cleanup;
99cbc7
+    rv = virFileReadValueUint(&i_membw->bandwidth_granularity,
99cbc7
+                              SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran");
99cbc7
+    if (rv == -2) {
99cbc7
+        /* The file doesn't exist, so it's unusable for us,
99cbc7
+         * probably memory bandwidth allocation unsupported */
99cbc7
+        VIR_INFO("The path '" SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran'"
99cbc7
+                 "does not exist");
99cbc7
+        ret = 0;
99cbc7
+        goto cleanup;
99cbc7
+    } else if (rv < 0) {
99cbc7
+        /* Other failures are fatal, so just quit */
99cbc7
+        goto cleanup;
99cbc7
+    }
99cbc7
+
99cbc7
+    rv = virFileReadValueUint(&i_membw->min_bandwidth,
99cbc7
+                              SYSFS_RESCTRL_PATH "/info/MB/min_bandwidth");
99cbc7
+    if (rv == -2) {
99cbc7
+        /* If the previous file exists, so should this one. Hence -2 is
99cbc7
+         * fatal in this case (errors out in next condition) - the kernel
99cbc7
+         * interface might've changed too much or something else is wrong. */
99cbc7
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
99cbc7
+                       _("Cannot get min bandwidth from resctrl memory info"));
99cbc7
+    }
99cbc7
+    if (rv < 0)
99cbc7
+        goto cleanup;
99cbc7
+
99cbc7
+    rv = virFileReadValueUint(&i_membw->max_allocation,
99cbc7
+                              SYSFS_RESCTRL_PATH "/info/MB/num_closids");
99cbc7
+    if (rv == -2) {
99cbc7
+         /* Similar reasoning to min_bandwidth above. */
99cbc7
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
99cbc7
+                       _("Cannot get max allocation from resctrl memory info"));
99cbc7
+    }
99cbc7
+    if (rv < 0)
99cbc7
+        goto cleanup;
99cbc7
+
99cbc7
+    VIR_STEAL_PTR(resctrl->membw_info, i_membw);
99cbc7
+    ret = 0;
99cbc7
+ cleanup:
99cbc7
+    VIR_FREE(i_membw);
99cbc7
+    return ret;
99cbc7
+}
99cbc7
+
99cbc7
+
99cbc7
 static int
99cbc7
 virResctrlGetInfo(virResctrlInfoPtr resctrl)
99cbc7
 {
99cbc7
@@ -452,6 +529,10 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl)
99cbc7
     if (ret <= 0)
99cbc7
         goto cleanup;
99cbc7
 
99cbc7
+    ret = virResctrlGetMemoryBandwidthInfo(resctrl);
99cbc7
+    if (ret < 0)
99cbc7
+        goto cleanup;
99cbc7
+
99cbc7
     ret = virResctrlGetCacheInfo(resctrl, dirp);
99cbc7
     if (ret < 0)
99cbc7
         goto cleanup;
99cbc7
@@ -493,6 +574,9 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl)
99cbc7
     if (!resctrl)
99cbc7
         return true;
99cbc7
 
99cbc7
+    if (resctrl->membw_info)
99cbc7
+        return false;
99cbc7
+
99cbc7
     for (i = 0; i < resctrl->nlevels; i++) {
99cbc7
         virResctrlInfoPerLevelPtr i_level = resctrl->levels[i];
99cbc7
 
99cbc7
-- 
99cbc7
2.21.0
99cbc7