[libvirt] [PATCH 4/9] util: Add MBA capability information query to resctrl

bing.niu at intel.com bing.niu at intel.com
Wed Jul 18 07:57:54 UTC 2018


From: Bing Niu <bing.niu at intel.com>

Introducing virResctrlInfoMemBW for the information memory bandwidth
allocation information. Those information is used for memory
bandwidth allocating.

Signed-off-by: Bing Niu <bing.niu at intel.com>
---
 src/util/virresctrl.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index 1515de2..06e2702 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -80,6 +80,9 @@ typedef virResctrlInfoPerType *virResctrlInfoPerTypePtr;
 typedef struct _virResctrlInfoPerLevel virResctrlInfoPerLevel;
 typedef virResctrlInfoPerLevel *virResctrlInfoPerLevelPtr;
 
+typedef struct _virResctrlInfoMemBW virResctrlInfoMemBW;
+typedef virResctrlInfoMemBW *virResctrlInfoMemBWPtr;
+
 typedef struct _virResctrlAllocPerType virResctrlAllocPerType;
 typedef virResctrlAllocPerType *virResctrlAllocPerTypePtr;
 
@@ -116,11 +119,31 @@ struct _virResctrlInfoPerLevel {
     virResctrlInfoPerTypePtr *types;
 };
 
+/* Information about memory bandwidth allocation */
+struct _virResctrlInfoMemBW {
+    /* minimum memory bandwidth allowed */
+    unsigned int min_bandwidth;
+    /* bandwidth granularity */
+    unsigned int bandwidth_granularity;
+    /* Maximum number of simultaneous allocations */
+    unsigned int max_allocation;
+    /* level number of last level cache */
+    unsigned int last_level_cache;
+    /* max id of last level cache, this is used to track
+     * how many last level cache available in host system,
+     * the number of memory bandwidth allocation controller
+     * is identical with last level cache.
+     */
+    unsigned int max_id;
+};
+
 struct _virResctrlInfo {
     virObject parent;
 
     virResctrlInfoPerLevelPtr *levels;
     size_t nlevels;
+
+    virResctrlInfoMemBWPtr membw_info;
 };
 
 
@@ -146,6 +169,7 @@ virResctrlInfoDispose(void *obj)
         VIR_FREE(level);
     }
 
+    VIR_FREE(resctrl->membw_info);
     VIR_FREE(resctrl->levels);
 }
 
@@ -442,6 +466,65 @@ virResctrlGetCacheInfo(virResctrlInfoPtr resctrl, DIR *dirp)
 
 
 static int
+virResctrlGetMemoryBandwidthInfo(virResctrlInfoPtr resctrl)
+{
+    int ret = -1;
+    int rv = -1;
+    virResctrlInfoMemBWPtr i_membw = NULL;
+
+    /* query memory bandwidth allocation info */
+    if (VIR_ALLOC(i_membw) < 0)
+        goto cleanup;
+    rv = virFileReadValueUint(&i_membw->bandwidth_granularity,
+                              SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran");
+    if (rv == -2) {
+        /* The file doesn't exist, so it's unusable for us,
+         *  properly mba unsupported */
+        VIR_INFO("The path '" SYSFS_RESCTRL_PATH "/info/MB/bandwidth_gran'"
+                 "does not exist");
+        ret = 0;
+        goto cleanup;
+    } else if (rv < 0) {
+        /* Other failures are fatal, so just quit */
+        goto cleanup;
+    }
+
+    rv = virFileReadValueUint(&i_membw->min_bandwidth,
+                              SYSFS_RESCTRL_PATH "/info/MB/min_bandwidth");
+    if (rv == -2) {
+        /* If the previous file exists, so should this one.  Hence -2 is
+         * fatal in this case (errors out in next condition) - the
+         * kernel interface might've changed too much or something else is
+         * wrong. */
+
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Cannot get min bandwidth from resctrl memory info"));
+    }
+    if (rv < 0)
+        goto cleanup;
+
+    rv = virFileReadValueUint(&i_membw->max_allocation,
+                              SYSFS_RESCTRL_PATH "/info/MB/num_closids");
+    if (rv == -2) {
+        /* If the previous file exists, so should this one.  Hence -2 is
+         * fatal in this case as well (errors out in next condition) - the
+         * kernel interface might've changed too much or something else is
+         * wrong. */
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Cannot get max allocation from resctrl memory info"));
+    }
+    if (rv < 0)
+        goto cleanup;
+
+    VIR_STEAL_PTR(resctrl->membw_info, i_membw);
+    ret = 0;
+ cleanup:
+    VIR_FREE(i_membw);
+    return ret;
+}
+
+
+static int
 virResctrlGetInfo(virResctrlInfoPtr resctrl)
 {
     DIR *dirp = NULL;
@@ -451,6 +534,10 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl)
     if (ret <= 0)
         goto cleanup;
 
+    ret = virResctrlGetMemoryBandwidthInfo(resctrl);
+    if (ret < 0)
+        goto cleanup;
+
     ret = virResctrlGetCacheInfo(resctrl, dirp);
     if (ret < 0)
         goto cleanup;
@@ -492,6 +579,9 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl)
     if (!resctrl)
         return true;
 
+    if (resctrl->membw_info)
+        return false;
+
     for (i = 0; i < resctrl->nlevels; i++) {
         virResctrlInfoPerLevelPtr i_level = resctrl->levels[i];
 
@@ -517,12 +607,26 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
 {
     virResctrlInfoPerLevelPtr i_level = NULL;
     virResctrlInfoPerTypePtr i_type = NULL;
+    virResctrlInfoMemBWPtr membw_info = NULL;
     size_t i = 0;
     int ret = -1;
 
     if (virResctrlInfoIsEmpty(resctrl))
         return 0;
 
+    /* Let's take the opportunity to update the number of last level
+     * cache. This number of memory bandwidth controller is same with
+     * last level cache */
+    if (resctrl->membw_info) {
+        membw_info = resctrl->membw_info;
+        if (level > membw_info->last_level_cache) {
+            membw_info->last_level_cache = level;
+            membw_info->max_id = 0;
+        } else if (membw_info->last_level_cache == level) {
+            membw_info->max_id++;
+        }
+    }
+
     if (level >= resctrl->nlevels)
         return 0;
 
-- 
2.7.4




More information about the libvir-list mailing list