[libvirt] [resend v2 3/7] Resctrl: Add new xml element to support cache tune

Eli Qiao liyong.qiao at intel.com
Mon Feb 6 02:23:38 UTC 2017


This patch adds new xml element to support cache tune as:

<cputune>
  ...
  <cachetune id='1' host_id='0' type='l3' size='2816' unit='KiB'/>
  ...
</cputune>

id: any non-minus number
host_id: reference of the host's cache banks id, it's from capabilities
type: cache bank type
size: should be multiples of the min_size of the bank on host.
---
 docs/schemas/domaincommon.rng |  41 +++++++++++++
 src/conf/domain_conf.c        | 134 ++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        |  18 ++++++
 src/libvirt_private.syms      |   3 +
 src/util/virresctrl.c         |  25 ++++++++
 src/util/virresctrl.h         |   3 +-
 6 files changed, 223 insertions(+), 1 deletion(-)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index cc6e0d0..d0f9e54 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -795,6 +795,27 @@
             </attribute>
           </element>
         </zeroOrMore>
+        <zeroOrMore>
+          <element name="cachetune">
+            <attribute name="id">
+              <ref name="cacheid"/>
+            </attribute>
+            <attribute name="host_id">
+              <ref name="hostid"/>
+            </attribute>
+            <attribute name="type">
+              <ref name="cachetype"/>
+            </attribute>
+            <attribute name="size">
+              <ref name="unsignedInt"/>
+            </attribute>
+            <optional>
+              <attribute name="unit">
+                <ref name="cacheunit"/>
+              </attribute>
+            </optional>
+          </element>
+        </zeroOrMore>
         <optional>
           <element name="emulatorpin">
             <attribute name="cpuset">
@@ -5451,6 +5472,26 @@
       <param name="minInclusive">-1</param>
     </data>
   </define>
+  <define name="cacheid">
+    <data type="unsignedShort">
+      <param name="pattern">[0-9]+</param>
+    </data>
+  </define>
+  <define name="hostid">
+    <data type="unsignedShort">
+      <param name="pattern">[0-9]+</param>
+    </data>
+  </define>
+  <define name="cachetype">
+    <data type="string">
+      <param name="pattern">(l3)</param>
+    </data>
+  </define>
+  <define name="cacheunit">
+    <data type="string">
+      <param name="pattern">KiB</param>
+    </data>
+  </define>
   <!-- weight currently is in range [100, 1000] -->
   <define name="weight">
     <data type="unsignedInt">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c06b128..0304b36 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -56,6 +56,7 @@
 #include "virstring.h"
 #include "virnetdev.h"
 #include "virhostdev.h"
+#include "virresctrl.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
 
@@ -15604,6 +15605,116 @@ virDomainVcpuPinDefParseXML(virDomainDefPtr def,
     return ret;
 }
 
+/* Parse the XML definition for cachetune
+ * and a cachetune has the form
+ * <cachetune id='0' host_id='0' type='l3' size='1024' unit='KiB'/>
+ */
+static int
+virDomainCacheTuneDefParseXML(virDomainDefPtr def,
+                              int n,
+                              xmlNodePtr* nodes)
+{
+    char* tmp = NULL;
+    int i;
+    size_t j;
+    int type = -1 ;
+    virDomainCacheBankPtr bank = NULL;
+    virResCtrlPtr resctrl;
+
+    if (VIR_ALLOC_N(bank, n) < 0)
+        goto cleanup;
+
+    for (i = 0; i < n; i++) {
+        if (!(tmp = virXMLPropString(nodes[i], "id"))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s", _("missing id in cache tune"));
+            goto cleanup;
+        }
+        if (virStrToLong_uip(tmp, NULL, 10, &(bank[i].id)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("invalid setting for cache id '%s'"), tmp);
+            goto cleanup;
+        }
+
+        VIR_FREE(tmp);
+        if (!(tmp = virXMLPropString(nodes[i], "host_id"))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s", _("missing host id in cache tune"));
+            goto cleanup;
+        }
+        if (virStrToLong_uip(tmp, NULL, 10, &(bank[i].host_id)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("invalid setting for cache host id '%s'"), tmp);
+            goto cleanup;
+        }
+        VIR_FREE(tmp);
+
+        if (!(tmp = virXMLPropString(nodes[i], "size"))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s", _("missing size in cache tune"));
+            goto cleanup;
+        }
+        if (virStrToLong_ull(tmp, NULL, 10, &(bank[i].size)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("invalid setting for cache size '%s'"), tmp);
+            goto cleanup;
+        }
+        VIR_FREE(tmp);
+
+        if (!(tmp = virXMLPropString(nodes[i], "type"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("missing cache type"));
+            goto cleanup;
+        }
+
+        if ((type = virResCtrlTypeFromString(tmp)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                    _("'unsupported cache type '%s'"), tmp);
+            goto cleanup;
+        }
+
+        resctrl = virResCtrlGet(type);
+
+        if(resctrl == NULL || !resctrl->enabled) {
+            virReportError(VIR_ERR_XML_ERROR,
+                    _("'host doesn't enabled cache type '%s'"), tmp);
+            goto cleanup;
+        }
+
+        bool found_host_id = false;
+        /* Loop for banks to search host_id */
+        for(j = 0; j < resctrl->num_banks; j++) {
+            if (resctrl->cache_banks[j].host_id == bank[i].host_id) {
+                found_host_id = true;
+                break;
+            }
+        }
+
+        if (! found_host_id) {
+            virReportError(VIR_ERR_XML_ERROR,
+                    _("'cache bank's host id %u not found on the host"),
+                    bank[i].host_id);
+            goto cleanup;
+        }
+
+        if (bank[i].size == 0 ||
+                bank[i].size % resctrl->cache_banks[j].cache_min != 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("'the size shoud be multiplies of '%llu'"),
+                           resctrl->cache_banks[j].cache_min);
+            goto cleanup;
+        }
+
+        if (VIR_STRDUP(bank[i].type, tmp) < 0)
+            goto cleanup;
+        def->cachetune.cache_banks = bank;
+    }
+
+    def->cachetune.n_banks = n;
+    return 0;
+
+cleanup:
+    VIR_FREE(bank);
+    VIR_FREE(tmp);
+    return -1;
+}
 
 /* Parse the XML definition for a iothreadpin
  * and an iothreadspin has the form
@@ -16882,6 +16993,13 @@ virDomainDefParseXML(xmlDocPtr xml,
     }
     VIR_FREE(nodes);
 
+    if ((n = virXPathNodeSet("./cputune/cachetune", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (virDomainCacheTuneDefParseXML(def, n ,nodes) < 0)
+        goto error;
+    VIR_FREE(nodes);
+
     if ((n = virXPathNodeSet("./cputune/emulatorpin", ctxt, &nodes)) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("cannot extract emulatorpin nodes"));
@@ -23398,6 +23516,20 @@ virDomainSchedulerFormat(virBufferPtr buf,
 
 }
 
+static void
+virDomainCacheTuneDefFormat(virBufferPtr buf,
+                            virDomainCachetunePtr cache)
+{
+    size_t i;
+    for(i = 0; i < cache->n_banks; i ++) {
+        virBufferAsprintf(buf, "<cachetune id='%u' host_id='%u' "
+                               "type='%s' size='%llu' unit='KiB'/>\n",
+                               cache->cache_banks[i].id,
+                               cache->cache_banks[i].host_id,
+                               cache->cache_banks[i].type,
+                               cache->cache_banks[i].size);
+    }
+}
 
 static int
 virDomainCputuneDefFormat(virBufferPtr buf,
@@ -23461,6 +23593,8 @@ virDomainCputuneDefFormat(virBufferPtr buf,
         VIR_FREE(cpumask);
     }
 
+    virDomainCacheTuneDefFormat(&childrenBuf, &def->cachetune);
+
     if (def->cputune.emulatorpin) {
         char *cpumask;
         virBufferAddLit(&childrenBuf, "<emulatorpin ");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 507ace8..49e01ac 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2132,6 +2132,22 @@ struct _virDomainMemtune {
     unsigned long long swap_hard_limit; /* in kibibytes, limit at off_t bytes */
 };
 
+typedef struct _virDomainCacheBank virDomainCacheBank;
+typedef virDomainCacheBank *virDomainCacheBankPtr;
+struct _virDomainCacheBank {
+    unsigned int id;
+    unsigned int host_id;
+    unsigned long long size;
+    char* type;
+};
+
+typedef struct _virDomainCachetune virDomainCachetune;
+typedef virDomainCachetune *virDomainCachetunePtr;
+struct _virDomainCachetune {
+    size_t n_banks;
+    virDomainCacheBankPtr cache_banks;
+};
+
 typedef struct _virDomainPowerManagement virDomainPowerManagement;
 typedef virDomainPowerManagement *virDomainPowerManagementPtr;
 
@@ -2196,6 +2212,8 @@ struct _virDomainDef {
 
     virDomainCputune cputune;
 
+    virDomainCachetune cachetune;
+
     virDomainNumaPtr numa;
     virDomainResourceDefPtr resource;
     virDomainIdMapDef idmap;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d93b775..08a0bc4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2317,6 +2317,9 @@ virRandomInt;
 virResCtrlAvailable;
 virResCtrlInit;
 virResCtrlGet;
+virResCtrlTypeFromString;
+virResCtrlTypeToString;
+
 
 # util/virrotatingfile.h
 virRotatingFileReaderConsume;
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index 63bc808..76d4ab8 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -41,6 +41,31 @@ VIR_LOG_INIT("util.resctrl");
 
 #define VIR_FROM_THIS VIR_FROM_RESCTRL
 
+VIR_ENUM_IMPL(virResCtrl, RDT_NUM_RESOURCES,
+              "l3", "l3data", "l3code", "l2");
+
+#define CONSTRUCT_RESCTRL_PATH(domain_name, item_name) \
+do { \
+    if (NULL == domain_name) { \
+        if (asprintf(&path, "%s/%s", RESCTRL_DIR, item_name) < 0)\
+            return -1; \
+    } \
+    else { \
+        if (asprintf(&path, "%s/%s/%s", RESCTRL_DIR, \
+                                        domain_name, \
+                                        item_name) < 0) \
+            return -1;  \
+    } \
+} while(0)
+
+#define VIR_RESCTRL_ENABLED(type) \
+    ResCtrlAll[type].enabled
+
+#define VIR_RESCTRL_GET_SCHEMATA(count) ((1 << count) - 1)
+
+#define VIR_RESCTRL_SET_SCHEMATA(p, type, pos, val) \
+    p->schematas[type]->schemata_items[pos] = val
+
 static unsigned int host_id = 0;
 
 static virResCtrl ResCtrlAll[] = {
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index f713e66..3cc41da 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -42,9 +42,10 @@ enum {
     RDT_RESOURCE_L3CODE,
     RDT_RESOURCE_L2,
     /* Must be the last */
-    RDT_NUM_RESOURCES,
+    RDT_NUM_RESOURCES
 };
 
+VIR_ENUM_DECL(virResCtrl);
 
 typedef struct _virResCacheBank virResCacheBank;
 typedef virResCacheBank *virResCacheBankPtr;
-- 
1.9.1




More information about the libvir-list mailing list