This patch adds new xml element to support cache tune as:
<cputune>
...
<cachetune id='1' host_id='0' type='l3' size='2816'
unit='KiB'
vcpus='1,2'/>
...
</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.
vcpus: cache allocation on vcpu set, if empty, will apply the allocation
on all vcpus
---
docs/schemas/domaincommon.rng | 46 +++++++++++++
src/conf/domain_conf.c | 152 ++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 19 ++++++
src/util/virresctrl.c | 32 +++++++--
src/util/virresctrl.h | 1 +
5 files changed, 245 insertions(+), 5 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index cc6e0d0..edb2888 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -795,6 +795,32 @@
</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>
+ <optional>
+ <attribute name="vcpus">
+ <ref name="cpuset"/>
+ </attribute>
+ </optional>
+ </element>
+ </zeroOrMore>
<optional>
<element name="emulatorpin">
<attribute name="cpuset">
@@ -5451,6 +5477,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..6ce819d 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,127 @@ 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;
+ size_t i, 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;
+
+ if ((tmp = virXMLPropString(nodes[i], "vcpus"))) {
+ if (virBitmapParse(tmp, &bank[i].vcpus,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ goto cleanup;
+
+ if (virBitmapIsAllClear(bank[i].vcpus)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid value of 'vcpus': %s"), tmp);
+ 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 +17004,14 @@ 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 +23528,26 @@ 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'",
+ cache->cache_banks[i].id,
+ cache->cache_banks[i].host_id,
+ cache->cache_banks[i].type,
+ cache->cache_banks[i].size);
+
+ if (cache->cache_banks[i].vcpus)
+ virBufferAsprintf(buf, " vcpus='%s'/>\n",
+ virBitmapFormat(cache->cache_banks[i].vcpus));
+ else
+ virBufferAddLit(buf, "/>\n");
+ }
+}
static int
virDomainCputuneDefFormat(virBufferPtr buf,
@@ -23461,6 +23611,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..fa47fe4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2132,6 +2132,23 @@ 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;
+ virBitmapPtr vcpus;
+};
+
+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 +2213,8 @@ struct _virDomainDef {
virDomainCputune cputune;
+ virDomainCachetune cachetune;
+
virDomainNumaPtr numa;
virDomainResourceDefPtr resource;
virDomainIdMapDef idmap;
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index 80481bc..b49e965 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -40,15 +40,37 @@
VIR_LOG_INIT("util.resctrl");
#define VIR_FROM_THIS VIR_FROM_RESCTRL
-
-#define RESCTRL_DIR "/sys/fs/resctrl"
-#define RESCTRL_INFO_DIR "/sys/fs/resctrl/info"
-#define SYSFS_SYSTEM_PATH "/sys/devices/system"
-
#define MAX_CPU_SOCKET_NUM 8
#define MAX_CBM_BIT_LEN 32
#define MAX_SCHEMATA_LEN 1024
#define MAX_FILE_LEN ( 10 * 1024 * 1024)
+#define RESCTRL_DIR "/sys/fs/resctrl"
+#define RESCTRL_INFO_DIR "/sys/fs/resctrl/info"
+#define SYSFS_SYSTEM_PATH "/sys/devices/system"
+
+VIR_ENUM_IMPL(virResCtrl, VIR_RDT_RESOURCE_LAST,
+ "l3", "l3data", "l3code", "l2");
+
+#define CONSTRUCT_RESCTRL_PATH(domain_name, item_name) \
+do { \
+ if (NULL == domain_name) { \
+ if (virAsprintf(&path, "%s/%s", RESCTRL_DIR, item_name) < 0)\
+ return -1; \
+ } else { \
+ if (virAsprintf(&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;
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index aa113f4..3f6fcae 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -36,6 +36,7 @@ enum {
VIR_RDT_RESOURCE_LAST,
};
+VIR_ENUM_DECL(virResCtrl);
typedef struct _virResCacheBank virResCacheBank;
typedef virResCacheBank *virResCacheBankPtr;
--
1.9.1