<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>