<div>Ping</div><div><br></div><div>Please let me know which is the direction.</div><div><br></div><div>Thx.</div><div>
</div>
<div></div>
<p style="color: #A0A0A8;">On Friday, 14 April 2017 at 6:01 PM, Eli Qiao wrote:</p>
<blockquote type="cite" style="border-left-style:solid;border-width:1px;margin-left:0px;padding-left:10px;">
<span><div><div><div>This is a RFC patch for the reimplement of `support cache tune(CAT) in</div><div>libvirt`[1].</div><div><br></div><div>This patch defines some structs to represent data struct in linux</div><div>resctrl fs which will be used later to do cache allocation.</div><div><br></div><div>The patch expose a private interface `virResctrlFreeSchemata`, which</div><div>will be used to query the cache allocation on the host.</div><div><br></div><div>Also added unit test cases to test this interface can works well.</div><div><br></div><div>There are already patch sets[2] to address it, and functional</div><div>works, but people doesn't like it cause it has global variable, and</div><div>missing unit test case for new added capabilites, etc.</div><div><br></div><div>Martin has proposed a test infra to do vircaps2xmltest, and I extened it</div><div>on top of it to extend resctrl control[3], this is kinds of new desiged</div><div>apart from [2], so I propose this RFC patch to do some rework on it.</div><div><br></div><div>[1] <a href="https://www.redhat.com/archives/libvir-list/2017-January/msg00683.html">https://www.redhat.com/archives/libvir-list/2017-January/msg00683.html</a></div><div>[2] <a href="https://www.redhat.com/archives/libvir-list/2017-March/msg00181.html">https://www.redhat.com/archives/libvir-list/2017-March/msg00181.html</a></div><div>[3] <a href="https://www.redhat.com/archives/libvir-list/2017-April/msg00516.html">https://www.redhat.com/archives/libvir-list/2017-April/msg00516.html</a></div><div>---</div><div> include/libvirt/virterror.h | 1 +</div><div> src/<a href="http://Makefile.am">Makefile.am</a> | 1 +</div><div> src/libvirt_private.syms | 6 +</div><div> src/util/virerror.c | 1 +</div><div> src/util/virresctrl.c | 423 ++++++++++++++++++++++++++++++</div><div> src/util/virresctrl.h | 86 ++++++</div><div> tests/<a href="http://Makefile.am">Makefile.am</a> | 7 +-</div><div> tests/virresctrldata/L3-free.schemata | 1 +</div><div> tests/virresctrldata/L3CODE-free.schemata | 1 +</div><div> tests/virresctrldata/L3DATA-free.schemata | 1 +</div><div> tests/virresctrltest.c | 117 +++++++++</div><div> 11 files changed, 644 insertions(+), 1 deletion(-)</div><div> create mode 100644 src/util/virresctrl.c</div><div> create mode 100644 src/util/virresctrl.h</div><div> create mode 100644 tests/virresctrldata/L3-free.schemata</div><div> create mode 100644 tests/virresctrldata/L3CODE-free.schemata</div><div> create mode 100644 tests/virresctrldata/L3DATA-free.schemata</div><div> create mode 100644 tests/virresctrltest.c</div><div><br></div><div>diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h</div><div>index 2efee8f..4bc0c74 100644</div><div>--- a/include/libvirt/virterror.h</div><div>+++ b/include/libvirt/virterror.h</div><div>@@ -132,6 +132,7 @@ typedef enum {</div><div><br></div><div> VIR_FROM_PERF = 65, /* Error from perf */</div><div> VIR_FROM_LIBSSH = 66, /* Error from libssh connection transport */</div><div>+ VIR_FROM_RESCTRL = 67, /* Error from resctrl */</div><div><br></div><div> # ifdef VIR_ENUM_SENTINELS</div><div> VIR_ERR_DOMAIN_LAST</div><div>diff --git a/src/<a href="http://Makefile.am">Makefile.am</a> b/src/<a href="http://Makefile.am">Makefile.am</a></div><div>index 60eba37..0ae2af5 100644</div><div>--- a/src/<a href="http://Makefile.am">Makefile.am</a></div><div>+++ b/src/<a href="http://Makefile.am">Makefile.am</a></div><div>@@ -165,6 +165,7 @@ UTIL_SOURCES = \</div><div> util/virprocess.c util/virprocess.h \</div><div> util/virqemu.c util/virqemu.h \</div><div> util/virrandom.h util/virrandom.c \</div><div>+ util/virresctrl.h util/virresctrl.c \</div><div> util/virrotatingfile.h util/virrotatingfile.c \</div><div> util/virscsi.c util/virscsi.h \</div><div> util/virscsihost.c util/virscsihost.h \</div><div>diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms</div><div>index 9d7760d..b7225fe 100644</div><div>--- a/src/libvirt_private.syms</div><div>+++ b/src/libvirt_private.syms</div><div>@@ -2396,6 +2396,12 @@ virRandomGenerateWWN;</div><div> virRandomInt;</div><div><br></div><div><br></div><div>+# util/virresctrl.h</div><div>+virResctrlFreeSchemata;</div><div>+virResctrlGetFreeCache;</div><div>+virResctrlTypeToString;</div><div>+</div><div>+</div><div> # util/virrotatingfile.h</div><div> virRotatingFileReaderConsume;</div><div> virRotatingFileReaderFree;</div><div>diff --git a/src/util/virerror.c b/src/util/virerror.c</div><div>index ef17fb5..02fabcc 100644</div><div>--- a/src/util/virerror.c</div><div>+++ b/src/util/virerror.c</div><div>@@ -139,6 +139,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,</div><div><br></div><div> "Perf", /* 65 */</div><div> "Libssh transport layer",</div><div>+ "Resource Control",</div><div> )</div><div><br></div><div><br></div><div>diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c</div><div>new file mode 100644</div><div>index 0000000..778c2ec</div><div>--- /dev/null</div><div>+++ b/src/util/virresctrl.c</div><div>@@ -0,0 +1,423 @@</div><div>+/*</div><div>+ * virresctrl.c: methods for managing resource control</div><div>+ *</div><div>+ * Copyright (C) 2017 Intel, Inc.</div><div>+ *</div><div>+ * This library is free software; you can redistribute it and/or</div><div>+ * modify it under the terms of the GNU Lesser General Public</div><div>+ * License as published by the Free Software Foundation; either</div><div>+ * version 2.1 of the License, or (at your option) any later version.</div><div>+ *</div><div>+ * This library is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</div><div>+ * Lesser General Public License for more details.</div><div>+ *</div><div>+ * You should have received a copy of the GNU Lesser General Public</div><div>+ * License along with this library. If not, see</div><div>+ * <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.</div><div>+ *</div><div>+ * Authors:</div><div>+ * Eli Qiao <<a href="mailto:liyong.qiao@intel.com">liyong.qiao@intel.com</a>></div><div>+ */</div><div>+</div><div>+#include <config.h></div><div>+#include <fcntl.h></div><div>+#include <sys/file.h></div><div>+#include <sys/stat.h></div><div>+#include <sys/types.h></div><div>+</div><div>+#include "virresctrl.h"</div><div>+#include "virerror.h"</div><div>+#include "virlog.h"</div><div>+#include "viralloc.h"</div><div>+#include "virstring.h"</div><div>+#include "virfile.h"</div><div>+</div><div>+VIR_LOG_INIT("util.resctrl");</div><div>+</div><div>+#define VIR_FROM_THIS VIR_FROM_RESCTRL</div><div>+#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl/"</div><div>+</div><div>+VIR_ENUM_IMPL(virResctrl, VIR_RESCTRL_TYPE_LAST,</div><div>+ "L3",</div><div>+ "L3CODE",</div><div>+ "L3DATA",</div><div>+ "L2")</div><div>+</div><div>+/**</div><div>+ * a virResctrlDomain represents a resource control group, it's a directory</div><div>+ * under /sys/fs/resctrl.</div><div>+ * eg: /sys/fs/resctrl/CG1</div><div>+ * |-- cpus</div><div>+ * |-- schemata</div><div>+ * `-- tasks</div><div>+ * # cat schemata</div><div>+ * L3DATA:0=fffff;1=fffff</div><div>+ * L3CODE:0=fffff;1=fffff</div><div>+ *</div><div>+ * Besides, it can also represent the default resource control group of the</div><div>+ * host.</div><div>+ */</div><div>+</div><div>+typedef struct _virResctrlGroup virResctrlGroup;</div><div>+typedef virResctrlGroup *virResctrlGroupPtr;</div><div>+struct _virResctrlGroup {</div><div>+ char *name; /* resource group name, eg: CG1. If it represent host's</div><div>+ default resource group name, should be a NULL pointer */</div><div>+ size_t n_tasks; /* number of task assigned to the resource group */</div><div>+ char **tasks; /* task list which contains task id eg: 77454 */</div><div>+</div><div>+ size_t n_schematas; /* number of schemata the resource group contains,</div><div>+ eg: 2 */</div><div>+ virResctrlSchemataPtr *schematas; /* scheamta list */</div><div>+};</div><div>+</div><div>+/* All resource control groups on this host, including default resource group */</div><div>+typedef struct _virResctrlDomain virResctrlDomain;</div><div>+typedef virResctrlDomain *virResctrlDomainPtr;</div><div>+struct _virResctrlDomain {</div><div>+ size_t n_groups; /* number of resource control group */</div><div>+ virResctrlGroupPtr *groups; /* list of resource control group */</div><div>+};</div><div>+</div><div>+void</div><div>+virResctrlFreeSchemata(virResctrlSchemataPtr ptr)</div><div>+{</div><div>+ size_t i;</div><div>+</div><div>+ if (!ptr)</div><div>+ return;</div><div>+</div><div>+ for (i = 0; i < ptr->n_schemata_items; i++)</div><div>+ VIR_FREE(ptr->schemata_items[i]);</div><div>+}</div><div>+</div><div>+static void</div><div>+virResctrlFreeGroup(virResctrlGroupPtr ptr)</div><div>+{</div><div>+ size_t i;</div><div>+</div><div>+ if (!ptr)</div><div>+ return;</div><div>+</div><div>+ for (i = 0; i < ptr->n_tasks; i++)</div><div>+ VIR_FREE(ptr->tasks[i]);</div><div>+</div><div>+ for (i = 0; i < ptr->n_schematas; i++) {</div><div>+ virResctrlFreeSchemata(ptr->schematas[i]);</div><div>+ VIR_FREE(ptr->schematas[i]);</div><div>+ }</div><div>+}</div><div>+</div><div>+static void</div><div>+virResctrlFreeDomain(virResctrlDomainPtr ptr)</div><div>+{</div><div>+ size_t i;</div><div>+</div><div>+ if (!ptr)</div><div>+ return;</div><div>+</div><div>+ for (i = 0; i < ptr->n_groups; i++) {</div><div>+ virResctrlFreeGroup(ptr->groups[i]);</div><div>+ VIR_FREE(ptr->groups[i]);</div><div>+ }</div><div>+}</div><div>+</div><div>+static int</div><div>+virResctrlCopySchemata(virResctrlSchemataPtr src,</div><div>+ virResctrlSchemataPtr *dst)</div><div>+{</div><div>+ size_t i;</div><div>+ virResctrlSchemataItemPtr schemataitem;</div><div>+ virResctrlSchemataPtr schemata;</div><div>+</div><div>+ if (VIR_ALLOC(schemata) < 0)</div><div>+ return -1;</div><div>+</div><div>+ schemata->type = src->type;</div><div>+</div><div>+ for (i = 0; i < src->n_schemata_items; i++) {</div><div>+ if (VIR_ALLOC(schemataitem) < 0)</div><div>+ goto error;</div><div>+</div><div>+ schemataitem->cache_id = src->schemata_items[i]->cache_id;</div><div>+ schemataitem->continuous_schemata = src->schemata_items[i]->continuous_schemata;</div><div>+ schemataitem->schemata = src->schemata_items[i]->schemata;</div><div>+ schemataitem->size = src->schemata_items[i]->size;</div><div>+</div><div>+ if (VIR_APPEND_ELEMENT(schemata->schemata_items,</div><div>+ schemata->n_schemata_items,</div><div>+ schemataitem) < 0)</div><div>+ goto error;</div><div>+ }</div><div>+</div><div>+ *dst = schemata;</div><div>+</div><div>+ return 0;</div><div>+</div><div>+ error:</div><div>+ virResctrlFreeSchemata(schemata);</div><div>+ return -1;</div><div>+}</div><div>+</div><div>+static int</div><div>+virResctrlGetSchemataString(virResctrlType type,</div><div>+ const char *name,</div><div>+ char **schemata)</div><div>+{</div><div>+ int rc = -1;</div><div>+ char *tmp = NULL;</div><div>+ char *end = NULL;</div><div>+ char *buf = NULL;</div><div>+ char *type_suffix = NULL;</div><div>+</div><div>+ if (virFileReadValueString(&buf,</div><div>+ SYSFS_RESCTRL_PATH "%s/schemata",</div><div>+ name ? name : "") < 0)</div><div>+ return -1;</div><div>+</div><div>+ if (virAsprintf(&type_suffix,</div><div>+ "%s:",</div><div>+ virResctrlTypeToString(type)) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ tmp = strstr(buf, type_suffix);</div><div>+</div><div>+ if (!tmp)</div><div>+ goto cleanup;</div><div>+</div><div>+ end = strchr(tmp, '\n');</div><div>+ if (end != NULL)</div><div>+ *end = '\0';</div><div>+</div><div>+ if (VIR_STRDUP(*schemata, tmp) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ rc = 0;</div><div>+</div><div>+ cleanup:</div><div>+ VIR_FREE(buf);</div><div>+ VIR_FREE(type_suffix);</div><div>+ return rc;</div><div>+}</div><div>+</div><div>+static int</div><div>+virResctrlLoadSchemata(const char* schemata_str,</div><div>+ virResctrlSchemataPtr schemata)</div><div>+{</div><div>+ VIR_DEBUG("%s, %p\n", schemata_str, schemata);</div><div>+</div><div>+ int ret = -1;</div><div>+ char **lists = NULL;</div><div>+ char **sms = NULL;</div><div>+ char **sis = NULL;</div><div>+ size_t i;</div><div>+ virResctrlSchemataItemPtr si;</div><div>+</div><div>+ /* parse L3:0=fffff;1=f */</div><div>+ lists = virStringSplit(schemata_str, ":", 2);</div><div>+</div><div>+ if ((!lists) || (!lists[1]))</div><div>+ goto cleanup;</div><div>+</div><div>+ /* parse 0=fffff;1=f */</div><div>+ sms = virStringSplit(lists[1], ";", 0);</div><div>+ if (!sms)</div><div>+ goto cleanup;</div><div>+</div><div>+ for (i = 0; sms[i] != NULL; i++) {</div><div>+ /* parse 0=fffff */</div><div>+ sis = virStringSplit(sms[i], "=", 2);</div><div>+ if (!sis)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (VIR_ALLOC(si) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (virStrToLong_ui(sis[0], NULL, 10, &si->cache_id) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (virStrToLong_ui(sis[1], NULL, 16, &si->continuous_schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ si->schemata = si->continuous_schemata;</div><div>+</div><div>+ if (VIR_APPEND_ELEMENT(schemata->schemata_items,</div><div>+ schemata->n_schemata_items,</div><div>+ si) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ }</div><div>+</div><div>+ ret = 0;</div><div>+</div><div>+ cleanup:</div><div>+ VIR_FREE(si);</div><div>+ virStringListFree(lists);</div><div>+ virStringListFree(sms);</div><div>+ virStringListFree(sis);</div><div>+ return ret;</div><div>+}</div><div>+</div><div>+static int</div><div>+virResctrlLoadGroup(const char *name,</div><div>+ virResctrlDomainPtr dom)</div><div>+{</div><div>+ VIR_DEBUG("%s, %p\n", name, dom);</div><div>+</div><div>+ int ret = -1;</div><div>+ char *path = NULL;</div><div>+ char *schemata_str;</div><div>+ virResctrlType i;</div><div>+ int rv;</div><div>+ virResctrlGroupPtr grp;</div><div>+ virResctrlSchemataPtr schemata;</div><div>+</div><div>+ if ((virAsprintf(&path, "%s/%s", SYSFS_RESCTRL_PATH, name)) < 0)</div><div>+ return -1;</div><div>+</div><div>+ if (!virFileExists(path))</div><div>+ goto cleanup;</div><div>+</div><div>+ if (VIR_ALLOC(grp) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (VIR_STRDUP(grp->name, name) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ for (i = 0; i < VIR_RESCTRL_TYPE_LAST; i++) {</div><div>+ rv = virResctrlGetSchemataString(i, name, &schemata_str);</div><div>+ if (rv < 0)</div><div>+ continue;</div><div>+</div><div>+ if (VIR_ALLOC(schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ schemata->type = i;</div><div>+</div><div>+ if (virResctrlLoadSchemata(schemata_str, schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ VIR_FREE(schemata_str);</div><div>+</div><div>+ if (VIR_APPEND_ELEMENT(grp->schematas,</div><div>+ grp->n_schematas,</div><div>+ schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ virResctrlFreeSchemata(schemata);</div><div>+ }</div><div>+</div><div>+ if (VIR_APPEND_ELEMENT(dom->groups,</div><div>+ dom->n_groups,</div><div>+ grp) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ ret = 0;</div><div>+</div><div>+ cleanup:</div><div>+ VIR_FREE(path);</div><div>+ virResctrlFreeGroup(grp);</div><div>+ return ret;</div><div>+}</div><div>+</div><div>+static int</div><div>+virResctrlLoadDomain(virResctrlDomainPtr dom)</div><div>+{</div><div>+ int ret = -1;</div><div>+ int rv = -1;</div><div>+ DIR *dirp = NULL;</div><div>+ char *path = NULL;</div><div>+ struct dirent *ent;</div><div>+</div><div>+ VIR_DEBUG("%s, %p\n", "", dom);</div><div>+</div><div>+ rv = virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH);</div><div>+</div><div>+ if (rv < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ /* load default resctrl group */</div><div>+ if (virResctrlLoadGroup("", dom) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ while ((rv = virDirRead(dirp, &ent, path)) > 0) {</div><div>+ /* only read directory in resctrl */</div><div>+ if ((ent->d_type != DT_DIR) || STREQ(ent->d_name, "info"))</div><div>+ continue;</div><div>+</div><div>+ if (virResctrlLoadGroup(ent->d_name, dom) < 0)</div><div>+ goto cleanup;</div><div>+ }</div><div>+</div><div>+ ret = 0;</div><div>+</div><div>+ cleanup:</div><div>+ virDirClose(&dirp);</div><div>+ return ret;</div><div>+}</div><div>+</div><div>+static void</div><div>+virResctrlRefreshDom(virResctrlDomainPtr dom, virResctrlType type)</div><div>+{</div><div>+ size_t i;</div><div>+ size_t j;</div><div>+ size_t k;</div><div>+</div><div>+ virResctrlGroupPtr default_grp = NULL;</div><div>+ virResctrlGroupPtr grp = NULL;</div><div>+ virResctrlSchemataPtr schemata = NULL;</div><div>+ virResctrlSchemataItemPtr schemataitem = NULL;</div><div>+</div><div>+ default_grp = dom->groups[0];</div><div>+</div><div>+ /* We are sure that the first group is the default one */</div><div>+ for (i = 1; i < dom->n_groups; i++) {</div><div>+ grp = dom->groups[i];</div><div>+ for (j = 0; j < grp->n_schematas; j++) {</div><div>+ schemata = grp->schematas[j];</div><div>+ /* we can only calculate one type of schemata */</div><div>+ if (schemata->type != type)</div><div>+ continue;</div><div>+ for (k = 0; k < schemata->n_schemata_items; k++) {</div><div>+ schemataitem = schemata->schemata_items[k];</div><div>+ /* if the schemata = 1, ignore it */</div><div>+ if (schemataitem->continuous_schemata > 1)</div><div>+ /* calculate default schemata, it can be non-continuous */</div><div>+ default_grp->schematas[j]->schemata_items[k]->schemata &= ~(schemataitem->continuous_schemata);</div><div>+ }</div><div>+ }</div><div>+ }</div><div>+}</div><div>+</div><div>+int virResctrlGetFreeCache(virResctrlType type,</div><div>+ virResctrlSchemataPtr *schemata)</div><div>+{</div><div>+ VIR_DEBUG("%d, %p\n", type, schemata);</div><div>+ int ret = -1;</div><div>+ size_t i;</div><div>+ virResctrlDomainPtr dom = NULL;</div><div>+ virResctrlGroupPtr grp = NULL;</div><div>+</div><div>+ if (VIR_ALLOC(dom) < 0)</div><div>+ return -1;</div><div>+</div><div>+ if (virResctrlLoadDomain(dom) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ virResctrlRefreshDom(dom, type);</div><div>+ grp = dom->groups[0];</div><div>+</div><div>+ for (i = 0; i < grp->n_schematas; i ++)</div><div>+ if (grp->schematas[i]->type == type)</div><div>+ if (virResctrlCopySchemata(grp->schematas[i], schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (schemata != NULL)</div><div>+ ret = 0;</div><div>+</div><div>+ cleanup:</div><div>+ virResctrlFreeDomain(dom);</div><div>+ return ret;</div><div>+}</div><div>diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h</div><div>new file mode 100644</div><div>index 0000000..1b040d4</div><div>--- /dev/null</div><div>+++ b/src/util/virresctrl.h</div><div>@@ -0,0 +1,86 @@</div><div>+/*</div><div>+ * virresctrl.h: header for managing resctrl control</div><div>+ *</div><div>+ * Copyright (C) 2017 Intel, Inc.</div><div>+ *</div><div>+ * This library is free software; you can redistribute it and/or</div><div>+ * modify it under the terms of the GNU Lesser General Public</div><div>+ * License as published by the Free Software Foundation; either</div><div>+ * version 2.1 of the License, or (at your option) any later version.</div><div>+ *</div><div>+ * This library is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</div><div>+ * Lesser General Public License for more details.</div><div>+ *</div><div>+ * You should have received a copy of the GNU Lesser General Public</div><div>+ * License along with this library. If not, see</div><div>+ * <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.</div><div>+ *</div><div>+ * Authors:</div><div>+ * Eli Qiao <<a href="mailto:liyong.qiao@intel.com">liyong.qiao@intel.com</a>></div><div>+ */</div><div>+</div><div>+#ifndef __VIR_RESCTRL_H__</div><div>+# define __VIR_RESCTRL_H__</div><div>+</div><div>+#include "virutil.h"</div><div>+</div><div>+typedef enum {</div><div>+ VIR_RESCTRL_TYPE_L3,</div><div>+ VIR_RESCTRL_TYPE_L3_CODE,</div><div>+ VIR_RESCTRL_TYPE_L3_DATA,</div><div>+ VIR_RESCTRL_TYPE_L2,</div><div>+</div><div>+ VIR_RESCTRL_TYPE_LAST</div><div>+} virResctrlType;</div><div>+</div><div>+VIR_ENUM_DECL(virResctrl);</div><div>+</div><div>+/*</div><div>+ * a virResctrlSchemataItem represents one of schemata object in a</div><div>+ * resource control group.</div><div>+ * eg: 0=f</div><div>+ */</div><div>+typedef struct _virResctrlSchemataItem virResctrlSchemataItem;</div><div>+typedef virResctrlSchemataItem *virResctrlSchemataItemPtr;</div><div>+struct _virResctrlSchemataItem {</div><div>+ unsigned int cache_id; /* cache resource id, eg: 0 */</div><div>+ unsigned int continuous_schemata; /* schemata, should be a continuous bits,</div><div>+ eg: f, this schemata can be persisted</div><div>+ to sysfs */</div><div>+ unsigned int schemata; /* schemata eg: f0f, a schemata which is calculated</div><div>+ at running time */</div><div>+ unsigned long long size; /* the cache size schemata represented in B,</div><div>+ eg: (min * bits of continuous_schemata) */</div><div>+};</div><div>+</div><div>+/*</div><div>+ * a virResctrlSchemata represents schemata objects of specific type of</div><div>+ * resource in a resource control group.</div><div>+ * eg: L3:0=f,1=ff</div><div>+ */</div><div>+typedef struct _virResctrlSchemata virResctrlSchemata;</div><div>+typedef virResctrlSchemata *virResctrlSchemataPtr;</div><div>+struct _virResctrlSchemata {</div><div>+ virResctrlType type; /* resource control type, eg: L3 */</div><div>+ size_t n_schemata_items; /* number of schemata item, eg: 2 */</div><div>+ virResctrlSchemataItemPtr *schemata_items; /* pointer list of schemata item */</div><div>+};</div><div>+</div><div>+/* Get free cache of the host, result saved in schemata */</div><div>+int virResctrlGetFreeCache(virResctrlType type,</div><div>+ virResctrlSchemataPtr *schemata);</div><div>+</div><div>+</div><div>+/* TODO Need to first define virDomainCachetunePtr */</div><div>+/* Set cache allocation for a VM domain */</div><div>+// int virResctrlSetCacheBanks(virDomainCachetunePtr cachetune,</div><div>+// unsigned char *group_name,</div><div>+// size_t n_pids,</div><div>+// pid_t *pids);</div><div>+//</div><div>+/* remove cache allocation for a VM domain */</div><div>+// int virResctrlRemoveCacheBanks(unsigned char *group_name);</div><div>+void virResctrlFreeSchemata(virResctrlSchemataPtr ptr);</div><div>+#endif</div><div>diff --git a/tests/<a href="http://Makefile.am">Makefile.am</a> b/tests/<a href="http://Makefile.am">Makefile.am</a></div><div>index 3cc828d..0e09e43 100644</div><div>--- a/tests/<a href="http://Makefile.am">Makefile.am</a></div><div>+++ b/tests/<a href="http://Makefile.am">Makefile.am</a></div><div>@@ -229,6 +229,7 @@ if WITH_LINUX</div><div> test_programs += fchosttest</div><div> test_programs += scsihosttest</div><div> test_programs += vircaps2xmltest</div><div>+test_programs += virresctrltest</div><div> test_libraries += <a href="http://virusbmock.la">virusbmock.la</a> \</div><div> <a href="http://virnetdevbandwidthmock.la">virnetdevbandwidthmock.la</a> \</div><div> <a href="http://virnumamock.la">virnumamock.la</a> \</div><div>@@ -1150,6 +1151,10 @@ vircaps2xmltest_SOURCES = \</div><div> vircaps2xmltest.c testutils.h testutils.c virfilemock.c</div><div> vircaps2xmltest_LDADD = $(LDADDS)</div><div><br></div><div>+virresctrltest_SOURCES = \</div><div>+ virresctrltest.c testutils.h testutils.c virfilemock.c</div><div>+virresctrltest_LDADD = $(LDADDS)</div><div>+</div><div> virnumamock_la_SOURCES = \</div><div> virnumamock.c</div><div> virnumamock_la_CFLAGS = $(AM_CFLAGS)</div><div>@@ -1157,7 +1162,7 @@ virnumamock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)</div><div> virnumamock_la_LIBADD = $(MOCKLIBS_LIBS)</div><div><br></div><div> else ! WITH_LINUX</div><div>-EXTRA_DIST += vircaps2xmltest.c virnumamock.c</div><div>+EXTRA_DIST += vircaps2xmltest.c virresctrltest.c virnumamock.c</div><div> endif ! WITH_LINUX</div><div><br></div><div> if WITH_NSS</div><div>diff --git a/tests/virresctrldata/L3-free.schemata b/tests/virresctrldata/L3-free.schemata</div><div>new file mode 100644</div><div>index 0000000..9b47d25</div><div>--- /dev/null</div><div>+++ b/tests/virresctrldata/L3-free.schemata</div><div>@@ -0,0 +1 @@</div><div>+L3:0=1ffff;1=1ffff</div><div>diff --git a/tests/virresctrldata/L3CODE-free.schemata b/tests/virresctrldata/L3CODE-free.schemata</div><div>new file mode 100644</div><div>index 0000000..7039c45</div><div>--- /dev/null</div><div>+++ b/tests/virresctrldata/L3CODE-free.schemata</div><div>@@ -0,0 +1 @@</div><div>+L3CODE:0=cffff;1=cffff</div><div>diff --git a/tests/virresctrldata/L3DATA-free.schemata b/tests/virresctrldata/L3DATA-free.schemata</div><div>new file mode 100644</div><div>index 0000000..30f1cbd</div><div>--- /dev/null</div><div>+++ b/tests/virresctrldata/L3DATA-free.schemata</div><div>@@ -0,0 +1 @@</div><div>+L3DATA:0=3ffff;1=3ffff</div><div>diff --git a/tests/virresctrltest.c b/tests/virresctrltest.c</div><div>new file mode 100644</div><div>index 0000000..4926468</div><div>--- /dev/null</div><div>+++ b/tests/virresctrltest.c</div><div>@@ -0,0 +1,117 @@</div><div>+/*</div><div>+ * Copyright (C) Intel, Inc. 2017</div><div>+ *</div><div>+ * This library is free software; you can redistribute it and/or</div><div>+ * modify it under the terms of the GNU Lesser General Public</div><div>+ * License as published by the Free Software Foundation; either</div><div>+ * version 2.1 of the License, or (at your option) any later version.</div><div>+ *</div><div>+ * This library is distributed in the hope that it will be useful,</div><div>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</div><div>+ * Lesser General Public License for more details.</div><div>+ *</div><div>+ * You should have received a copy of the GNU Lesser General Public</div><div>+ * License along with this library. If not, see</div><div>+ * <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.</div><div>+ *</div><div>+ * Authors:</div><div>+ * Eli Qiao <<a href="mailto:liyong.qiao@intel.com">liyong.qiao@intel.com</a>></div><div>+ */</div><div>+</div><div>+#include <config.h></div><div>+#include <stdlib.h></div><div>+</div><div>+#include "testutils.h"</div><div>+#include "virbitmap.h"</div><div>+#include "virfilemock.h"</div><div>+#include "virresctrl.h"</div><div>+</div><div>+</div><div>+#define VIR_FROM_THIS VIR_FROM_NONE</div><div>+</div><div>+struct virResctrlData {</div><div>+ const char *filename;</div><div>+ virResctrlType type;</div><div>+};</div><div>+</div><div>+static void</div><div>+GetSchemataStr(virResctrlSchemataPtr schemata, char **str)</div><div>+{</div><div>+ size_t i;</div><div>+ virBuffer buf = VIR_BUFFER_INITIALIZER;</div><div>+ virBufferAsprintf(&buf, "%s:%u=%x",</div><div>+ virResctrlTypeToString(schemata->type),</div><div>+ schemata->schemata_items[0]->cache_id,</div><div>+ schemata->schemata_items[0]->schemata);</div><div>+</div><div>+ for (i = 1; i < schemata->n_schemata_items; i ++)</div><div>+ virBufferAsprintf(&buf, ";%u=%x",</div><div>+ schemata->schemata_items[i]->cache_id,</div><div>+ schemata->schemata_items[i]->schemata);</div><div>+</div><div>+ *str = virBufferContentAndReset(&buf);</div><div>+}</div><div>+</div><div>+static int</div><div>+test_virResctrl(const void *opaque)</div><div>+{</div><div>+ struct virResctrlData *data = (struct virResctrlData *) opaque;</div><div>+ char *dir = NULL;</div><div>+ char *resctrl = NULL;</div><div>+ int ret = -1;</div><div>+ virResctrlSchemataPtr schemata = NULL;</div><div>+ char *schemata_str;</div><div>+ char *schemata_file;</div><div>+</div><div>+ if (virAsprintf(&resctrl, "%s/virresctrldata/linux-%s/resctrl",</div><div>+ abs_srcdir, data->filename) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ if (virAsprintf(&schemata_file, "%s/virresctrldata/%s-free.schemata",</div><div>+ abs_srcdir, virResctrlTypeToString(data->type)) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ virFileMockAddPrefix("/sys/fs/resctrl", resctrl);</div><div>+</div><div>+ if (virResctrlGetFreeCache(data->type, &schemata) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ GetSchemataStr(schemata, &schemata_str);</div><div>+</div><div>+ if (virTestCompareToFile(schemata_str, schemata_file) < 0)</div><div>+ goto cleanup;</div><div>+</div><div>+ virFileMockClearPrefixes();</div><div>+</div><div>+ ret = 0;</div><div>+</div><div>+ cleanup:</div><div>+ VIR_FREE(dir);</div><div>+ VIR_FREE(resctrl);</div><div>+ VIR_FREE(schemata_str);</div><div>+ virResctrlFreeSchemata(schemata);</div><div>+ return ret;</div><div>+}</div><div>+</div><div>+static int</div><div>+mymain(void)</div><div>+{</div><div>+ int ret = 0;</div><div>+</div><div>+#define DO_TEST_FULL(filename, type) \</div><div>+ do { \</div><div>+ struct virResctrlData data = {filename, \</div><div>+ type}; \</div><div>+ if (virTestRun(filename, test_virResctrl, &data) < 0) \</div><div>+ ret = -1; \</div><div>+ } while (0)</div><div>+</div><div>+ DO_TEST_FULL("resctrl", VIR_RESCTRL_TYPE_L3);</div><div>+ DO_TEST_FULL("resctrl-cdp", VIR_RESCTRL_TYPE_L3_CODE);</div><div>+ DO_TEST_FULL("resctrl-cdp", VIR_RESCTRL_TYPE_L3_DATA);</div><div>+</div><div>+ return ret;</div><div>+}</div><div>+</div><div>+VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virnumamock.so")</div><div>--</div><div>1.9.1</div><div><br></div><div>--</div><div>libvir-list mailing list</div><div><a href="mailto:libvir-list@redhat.com">libvir-list@redhat.com</a></div><div><a href="https://www.redhat.com/mailman/listinfo/libvir-list">https://www.redhat.com/mailman/listinfo/libvir-list</a></div></div></div></span>
</blockquote>
<div>
<br>
</div>