[libvirt] [V3 PATCH] RFC: Reimplement cache allocation for a VM

Eli Qiao posted 1 patch 6 years, 10 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/1496397120-14360-1-git-send-email-qiaoliyong@gmail.com
include/libvirt/virterror.h               |   1 +
src/Makefile.am                           |   1 +
src/libvirt_private.syms                  |   7 +
src/util/virerror.c                       |   1 +
src/util/virresctrl.c                     | 390 ++++++++++++++++++++++++++++++
src/util/virresctrl.h                     |  72 ++++++
tests/Makefile.am                         |   8 +-
tests/virresctrldata/L3-free.schemata     |   1 +
tests/virresctrldata/L3CODE-free.schemata |   1 +
tests/virresctrldata/L3DATA-free.schemata |   1 +
tests/virresctrldata/linux-resctrl        |   1 +
tests/virresctrldata/linux-resctrl-cdp    |   1 +
tests/virresctrltest.c                    | 119 +++++++++
13 files changed, 603 insertions(+), 1 deletion(-)
create mode 100644 src/util/virresctrl.c
create mode 100644 src/util/virresctrl.h
create mode 100644 tests/virresctrldata/L3-free.schemata
create mode 100644 tests/virresctrldata/L3CODE-free.schemata
create mode 100644 tests/virresctrldata/L3DATA-free.schemata
create mode 120000 tests/virresctrldata/linux-resctrl
create mode 120000 tests/virresctrldata/linux-resctrl-cdp
create mode 100644 tests/virresctrltest.c
[libvirt] [V3 PATCH] RFC: Reimplement cache allocation for a VM
Posted by Eli Qiao 6 years, 10 months ago
From: Eli Qiao <liyong.qiao@intel.com>

This is a RFC patch for the reimplement of `support cache tune(CAT) in
libvirt`[1].

This patch defines some structs to represent data struct in linux
resctrl fs which will be used later to do cache allocation.

The patch expose a private interface `virResctrlFreeSchemata`, which
will be used to query the cache allocation on the host.

Also added unit test cases to test this interface can works well.

There are already patch sets[2] to address it, and functional
works, but people doesn't like it cause it has global variable, and
missing unit test case for new added capabilites, etc.

Martin has proposed a test infra to do vircaps2xmltest, and I extened it
on top of it to extend resctrl control[3], this is kinds of new desiged
apart from [2], so I propose this RFC patch to do some rework on it.

[1] https://www.redhat.com/archives/libvir-list/2017-January/msg00683.html
[2] https://www.redhat.com/archives/libvir-list/2017-March/msg00181.html
[3] https://www.redhat.com/archives/libvir-list/2017-April/msg00516.html
---
 include/libvirt/virterror.h               |   1 +
 src/Makefile.am                           |   1 +
 src/libvirt_private.syms                  |   7 +
 src/util/virerror.c                       |   1 +
 src/util/virresctrl.c                     | 390 ++++++++++++++++++++++++++++++
 src/util/virresctrl.h                     |  72 ++++++
 tests/Makefile.am                         |   8 +-
 tests/virresctrldata/L3-free.schemata     |   1 +
 tests/virresctrldata/L3CODE-free.schemata |   1 +
 tests/virresctrldata/L3DATA-free.schemata |   1 +
 tests/virresctrldata/linux-resctrl        |   1 +
 tests/virresctrldata/linux-resctrl-cdp    |   1 +
 tests/virresctrltest.c                    | 119 +++++++++
 13 files changed, 603 insertions(+), 1 deletion(-)
 create mode 100644 src/util/virresctrl.c
 create mode 100644 src/util/virresctrl.h
 create mode 100644 tests/virresctrldata/L3-free.schemata
 create mode 100644 tests/virresctrldata/L3CODE-free.schemata
 create mode 100644 tests/virresctrldata/L3DATA-free.schemata
 create mode 120000 tests/virresctrldata/linux-resctrl
 create mode 120000 tests/virresctrldata/linux-resctrl-cdp
 create mode 100644 tests/virresctrltest.c

diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 2efee8f..4bc0c74 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -132,6 +132,7 @@ typedef enum {
 
     VIR_FROM_PERF = 65,         /* Error from perf */
     VIR_FROM_LIBSSH = 66,       /* Error from libssh connection transport */
+    VIR_FROM_RESCTRL = 67,      /* Error from resctrl */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_ERR_DOMAIN_LAST
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b7cfc8..08ad5b4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -167,6 +167,7 @@ UTIL_SOURCES =							\
 		util/virprocess.c util/virprocess.h		\
 		util/virqemu.c util/virqemu.h			\
 		util/virrandom.h util/virrandom.c		\
+		util/virresctrl.h util/virresctrl.c		\
 		util/virrotatingfile.h util/virrotatingfile.c   \
 		util/virscsi.c util/virscsi.h			\
 		util/virscsihost.c util/virscsihost.h		\
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 429b095..cdd3467 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2424,6 +2424,13 @@ virRandomGenerateWWN;
 virRandomInt;
 
 
+# util/virresctrl.h
+virResctrlBitmap2String;
+virResctrlFreeSchemata;
+virResctrlGetFreeCache;
+virResctrlTypeToString;
+
+
 # util/virrotatingfile.h
 virRotatingFileReaderConsume;
 virRotatingFileReaderFree;
diff --git a/src/util/virerror.c b/src/util/virerror.c
index ef17fb5..02fabcc 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -139,6 +139,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
 
               "Perf", /* 65 */
               "Libssh transport layer",
+              "Resource Control",
     )
 
 
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
new file mode 100644
index 0000000..d3822ed
--- /dev/null
+++ b/src/util/virresctrl.c
@@ -0,0 +1,390 @@
+/*
+ * virresctrl.c: methods for managing resource control
+ *
+ * Copyright (C) 2017 Intel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Eli Qiao <liyong.qiao@intel.com>
+ */
+
+#include <config.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "virresctrl.h"
+#include "virerror.h"
+#include "virlog.h"
+#include "viralloc.h"
+#include "virstring.h"
+#include "virfile.h"
+
+VIR_LOG_INIT("util.resctrl");
+
+#define VIR_FROM_THIS VIR_FROM_RESCTRL
+#define SYSFS_RESCTRL_PATH "/sys/fs/resctrl"
+#define MAX_CBM_LEN 20
+
+VIR_ENUM_IMPL(virResctrl, VIR_RESCTRL_TYPE_LAST,
+              "L3",
+              "L3CODE",
+              "L3DATA")
+
+/**
+ * a virResctrlGroup represents a resource control group, it's a directory
+ * under /sys/fs/resctrl.
+ * e.g. /sys/fs/resctrl/CG1
+ * |-- cpus
+ * |-- schemata
+ * `-- tasks
+ * # cat schemata
+ * L3DATA:0=fffff;1=fffff
+ * L3CODE:0=fffff;1=fffff
+ *
+ * Besides, it can also represent the default resource control group of the
+ * host.
+ */
+
+typedef struct _virResctrlGroup virResctrlGroup;
+typedef virResctrlGroup *virResctrlGroupPtr;
+struct _virResctrlGroup {
+    char *name; /* resource group name, NULL for default host group */
+    size_t n_tasks; /* number of tasks assigned to the resource group */
+    char **tasks; /* task id list */
+
+    virResctrlSchemataPtr schemata[VIR_RESCTRL_TYPE_LAST]; /* Array for schemata */
+};
+
+/* All resource control groups on this host, including default resource group */
+typedef struct _virResctrlHost virResctrlHost;
+typedef virResctrlHost *virResctrlHostPtr;
+struct _virResctrlHost {
+    size_t n_groups; /* number of resource control group */
+    virResctrlGroupPtr *groups; /* list of resource control group */
+};
+
+void
+virResctrlFreeSchemata(virResctrlSchemataPtr ptr)
+{
+    size_t i;
+
+    if (!ptr)
+        return;
+    for (i = 0; i < ptr->n_masks; i++) {
+        virBitmapFree(ptr->masks[i]->mask);
+        VIR_FREE(ptr->masks[i]);
+    }
+
+    VIR_FREE(ptr->masks);
+    VIR_FREE(ptr);
+    ptr = NULL;
+}
+
+static void
+virResctrlFreeGroup(virResctrlGroupPtr ptr)
+{
+    size_t i;
+
+    if (!ptr)
+        return;
+
+
+    virStringListFree(ptr->tasks);
+    VIR_FREE(ptr->name);
+
+    for (i = 0; i < VIR_RESCTRL_TYPE_LAST; i++)
+        virResctrlFreeSchemata(ptr->schemata[i]);
+
+    VIR_FREE(ptr);
+    ptr = NULL;
+}
+
+/* Return specify type of schemata string from schematalval.
+   e.g., 0=f;1=f */
+static int
+virResctrlGetSchemataString(virResctrlType type,
+                            const char *schemataval,
+                            char **schematastr)
+{
+    int rc = -1;
+    char *prefix = NULL;
+    char **lines = NULL;
+
+    if (virAsprintf(&prefix,
+                    "%s:",
+                    virResctrlTypeToString(type)) < 0)
+        return -1;
+
+    lines = virStringSplit(schemataval, "\n", 0);
+
+    if (VIR_STRDUP(*schematastr,
+                   virStringListGetFirstWithPrefix(lines, prefix)) < 0)
+        goto cleanup;
+
+    if (*schematastr == NULL)
+        rc = -1;
+    else
+        rc = 0;
+
+ cleanup:
+    VIR_FREE(prefix);
+    virStringListFree(lines);
+    return rc;
+}
+
+static
+virBitmapPtr virResctrlMask2Bitmap(const char *mask)
+{
+    virBitmapPtr bitmap;
+    unsigned int tmp;
+    size_t i;
+
+    if (virStrToLong_ui(mask, NULL, 16, &tmp) < 0)
+        return NULL;
+
+    bitmap = virBitmapNewQuiet(MAX_CBM_LEN);
+
+    for (i = 0; i < MAX_CBM_LEN; i++) {
+        if (((tmp & 0x1) == 0x1) &&
+                (virBitmapSetBit(bitmap, i) < 0))
+            goto error;
+        tmp = tmp >> 1;
+    }
+
+    return bitmap;
+
+ error:
+    virBitmapFree(bitmap);
+    return NULL;
+}
+
+char *virResctrlBitmap2String(virBitmapPtr bitmap)
+{
+    char *tmp;
+    char *ret = NULL;
+    char *p;
+    tmp = virBitmapString(bitmap);
+    // skip "0x"
+    p = tmp + 2;
+
+    // find first non-0 position
+    while (*++p == '0');
+
+    if (VIR_STRDUP(ret, p) < 0)
+        ret = NULL;
+
+    VIR_FREE(tmp);
+    return ret;
+}
+
+static int
+virResctrlParseSchemata(const char* schemata_str,
+                        virResctrlSchemataPtr schemata)
+{
+    VIR_DEBUG("schemata_str=%s, schemata=%p", schemata_str, schemata);
+
+    int ret = -1;
+    size_t i;
+    virResctrlMaskPtr mask;
+    char **schemata_list;
+    char *mask_str;
+
+    /* parse 0=fffff;1=f */
+    schemata_list = virStringSplit(schemata_str, ";", 0);
+
+    if (!schemata_list)
+        goto cleanup;
+
+    for (i = 0; schemata_list[i] != NULL; i++) {
+        /* parse 0=fffff */
+        mask_str = strchr(schemata_list[i], '=');
+
+        if (!mask_str)
+            goto cleanup;
+
+        if (VIR_ALLOC(mask) < 0)
+            goto cleanup;
+
+        mask->cache_id = i;
+        mask->mask = virResctrlMask2Bitmap(mask_str + 1);
+
+        if (VIR_APPEND_ELEMENT(schemata->masks,
+                               schemata->n_masks,
+                               mask) < 0) {
+            VIR_FREE(mask);
+            goto cleanup;
+        }
+
+    }
+    ret = 0;
+
+ cleanup:
+    virStringListFree(schemata_list);
+    return ret;
+}
+
+static int
+virResctrlLoadGroup(const char *name,
+                    virResctrlHostPtr host)
+{
+    VIR_DEBUG("name=%s, host=%p\n", name, host);
+
+    int ret = -1;
+    char *schemataval = NULL;
+    char *schemata_str = NULL;
+    virResctrlType i;
+    int rv;
+    virResctrlGroupPtr grp;
+    virResctrlSchemataPtr schemata;
+
+    rv = virFileReadValueString(&schemataval,
+                                SYSFS_RESCTRL_PATH "/%s/schemata",
+                                name ? name : "");
+
+    if (rv < 0)
+        return -1;
+
+    if (VIR_ALLOC(grp) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(grp->name, name) < 0)
+        goto cleanup;
+
+    for (i = 0; i < VIR_RESCTRL_TYPE_LAST; i++) {
+        rv = virResctrlGetSchemataString(i, schemataval, &schemata_str);
+
+        if (rv < 0)
+            continue;
+
+        if (VIR_ALLOC(schemata) < 0)
+            goto cleanup;
+
+        schemata->type = i;
+
+        if (virResctrlParseSchemata(schemata_str, schemata) < 0) {
+            VIR_FREE(schemata);
+            VIR_FREE(schemata_str);
+            goto cleanup;
+        }
+
+        grp->schemata[i] = schemata;
+        VIR_FREE(schemata_str);
+    }
+
+    if (VIR_APPEND_ELEMENT(host->groups,
+                           host->n_groups,
+                           grp) < 0) {
+        virResctrlFreeGroup(grp);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(schemataval);
+    return ret;
+}
+
+static int
+virResctrlLoadHost(virResctrlHostPtr host)
+{
+    int ret = -1;
+    int rv = -1;
+    DIR *dirp = NULL;
+    char *path = NULL;
+    struct dirent *ent;
+
+    VIR_DEBUG("host=%p\n", host);
+
+    rv = virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH);
+
+    if (rv < 0)
+        goto cleanup;
+
+    /* load default group first */
+    if (virResctrlLoadGroup(NULL, host) < 0)
+        goto cleanup;
+
+    while ((rv = virDirRead(dirp, &ent, path)) > 0) {
+        /* resctrl is not hierarchical, only read directory under
+           /sys/fs/resctrl */
+        if ((ent->d_type != DT_DIR) || STREQ(ent->d_name, "info"))
+            continue;
+
+        if (virResctrlLoadGroup(ent->d_name, host) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virDirClose(&dirp);
+    return ret;
+}
+
+static void
+virResctrlRefreshHost(virResctrlHostPtr host)
+{
+    virResctrlGroupPtr default_grp = NULL;
+    virResctrlGroupPtr grp = NULL;
+    virResctrlSchemataPtr schemata = NULL;
+    size_t i, j;
+    virResctrlType t;
+
+    default_grp = host->groups[0];
+
+    /* Loop each other resource group except default group */
+    for (i = 1; i < host->n_groups; i++) {
+        grp = host->groups[i];
+        for (t = 0; t < VIR_RESCTRL_TYPE_LAST; t++) {
+            schemata = grp->schemata[t];
+            if (schemata != NULL) {
+                for (j = 0; j < schemata->n_masks; j++)
+                    virBitmapSubtract(default_grp->schemata[t]->masks[j]->mask,
+                                      schemata->masks[j]->mask);
+            }
+        }
+    }
+}
+
+virResctrlSchemataPtr
+virResctrlGetFreeCache(virResctrlType type)
+{
+    VIR_DEBUG("type=%d", type);
+    virResctrlHostPtr host = NULL;
+    virResctrlSchemataPtr schemata = NULL;
+    size_t i;
+
+    if (VIR_ALLOC(host) < 0)
+        return NULL;
+
+    if (virResctrlLoadHost(host) < 0)
+        return NULL;
+
+    /* default group come the first one */
+    virResctrlRefreshHost(host);
+
+    schemata = host->groups[0]->schemata[type];
+
+    for (i = 1; i < host->n_groups; i++)
+        virResctrlFreeGroup(host->groups[i]);
+    VIR_FREE(host->groups);
+    host = NULL;
+
+    return schemata;
+}
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
new file mode 100644
index 0000000..7c9a1b7
--- /dev/null
+++ b/src/util/virresctrl.h
@@ -0,0 +1,72 @@
+/*
+ * virresctrl.h: header for managing resctrl control
+ *
+ * Copyright (C) 2017 Intel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Eli Qiao <liyong.qiao@intel.com>
+ */
+
+#ifndef __VIR_RESCTRL_H__
+# define __VIR_RESCTRL_H__
+
+#include "virutil.h"
+#include "virbitmap.h"
+
+typedef enum {
+    VIR_RESCTRL_TYPE_L3,
+    VIR_RESCTRL_TYPE_L3_CODE,
+    VIR_RESCTRL_TYPE_L3_DATA,
+
+    VIR_RESCTRL_TYPE_LAST
+} virResctrlType;
+
+VIR_ENUM_DECL(virResctrl);
+
+/*
+ * a virResctrlMask represents one of mask object in a
+ * resource control group.
+ * e.g., 0=f
+ */
+typedef struct _virResctrlMask virResctrlMask;
+typedef virResctrlMask *virResctrlMaskPtr;
+struct _virResctrlMask {
+    unsigned int cache_id; /* cache resource id */
+    virBitmapPtr mask; /* the cbm mask */
+};
+
+/*
+ * a virResctrlSchemata represents schemata objects of specific type of
+ * resource in a resource control group.
+ * eg: L3:0=f,1=ff
+ */
+typedef struct _virResctrlSchemata virResctrlSchemata;
+typedef virResctrlSchemata *virResctrlSchemataPtr;
+struct _virResctrlSchemata {
+    virResctrlType type; /* resource control type, e.g., L3 */
+    size_t n_masks; /* number of masks */
+    virResctrlMaskPtr *masks; /* list of mask */
+};
+
+/* Get free cache of the host, result saved in schemata */
+virResctrlSchemataPtr virResctrlGetFreeCache(virResctrlType type);
+
+/* Get mask string from Bitmap */
+char *virResctrlBitmap2String(virBitmapPtr bitmap);
+
+void virResctrlFreeSchemata(virResctrlSchemataPtr ptr);
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7673329..0dcef4f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -229,6 +229,7 @@ if WITH_LINUX
 test_programs += fchosttest
 test_programs += scsihosttest
 test_programs += vircaps2xmltest
+test_programs += virresctrltest
 test_libraries += virusbmock.la \
 	virnetdevbandwidthmock.la \
 	virnumamock.la \
@@ -1156,8 +1157,13 @@ virnumamock_la_CFLAGS = $(AM_CFLAGS)
 virnumamock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
 virnumamock_la_LIBADD = $(MOCKLIBS_LIBS)
 
+virresctrltest_SOURCES = \
+	virresctrltest.c testutils.h testutils.c virfilewrapper.h virfilewrapper.c
+virresctrltest_LDADD = $(LDADDS)
+
 else ! WITH_LINUX
-EXTRA_DIST += vircaps2xmltest.c virnumamock.c virfilewrapper.c virfilewrapper.h
+EXTRA_DIST += vircaps2xmltest.c virnumamock.c virfilewrapper.c \
+			  virfilewrapper.h virresctrltest.c
 endif ! WITH_LINUX
 
 if WITH_NSS
diff --git a/tests/virresctrldata/L3-free.schemata b/tests/virresctrldata/L3-free.schemata
new file mode 100644
index 0000000..9b47d25
--- /dev/null
+++ b/tests/virresctrldata/L3-free.schemata
@@ -0,0 +1 @@
+L3:0=1ffff;1=1ffff
diff --git a/tests/virresctrldata/L3CODE-free.schemata b/tests/virresctrldata/L3CODE-free.schemata
new file mode 100644
index 0000000..7039c45
--- /dev/null
+++ b/tests/virresctrldata/L3CODE-free.schemata
@@ -0,0 +1 @@
+L3CODE:0=cffff;1=cffff
diff --git a/tests/virresctrldata/L3DATA-free.schemata b/tests/virresctrldata/L3DATA-free.schemata
new file mode 100644
index 0000000..30f1cbd
--- /dev/null
+++ b/tests/virresctrldata/L3DATA-free.schemata
@@ -0,0 +1 @@
+L3DATA:0=3ffff;1=3ffff
diff --git a/tests/virresctrldata/linux-resctrl b/tests/virresctrldata/linux-resctrl
new file mode 120000
index 0000000..069dfb2
--- /dev/null
+++ b/tests/virresctrldata/linux-resctrl
@@ -0,0 +1 @@
+../vircaps2xmldata/linux-resctrl
\ No newline at end of file
diff --git a/tests/virresctrldata/linux-resctrl-cdp b/tests/virresctrldata/linux-resctrl-cdp
new file mode 120000
index 0000000..c5a973f
--- /dev/null
+++ b/tests/virresctrldata/linux-resctrl-cdp
@@ -0,0 +1 @@
+../vircaps2xmldata/linux-resctrl-cdp
\ No newline at end of file
diff --git a/tests/virresctrltest.c b/tests/virresctrltest.c
new file mode 100644
index 0000000..4eaa925
--- /dev/null
+++ b/tests/virresctrltest.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) Intel, Inc. 2017
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Eli Qiao <liyong.qiao@intel.com>
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "testutils.h"
+#include "virbitmap.h"
+#include "virfilewrapper.h"
+#include "virresctrl.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+struct virResctrlData {
+    const char *filename;
+    virResctrlType type;
+};
+
+static void
+GetSchemataStr(virResctrlSchemataPtr schemata, char **str)
+{
+    size_t i;
+
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virBufferAsprintf(&buf, "%s:%u=%s",
+                            virResctrlTypeToString(schemata->type),
+                            schemata->masks[0]->cache_id,
+                            virResctrlBitmap2String(schemata->masks[0]->mask));
+
+    for (i = 1; i < schemata->n_masks; i ++)
+        virBufferAsprintf(&buf, ";%u=%s",
+                                schemata->masks[i]->cache_id,
+                                virResctrlBitmap2String(schemata->masks[i]->mask));
+
+    *str = virBufferContentAndReset(&buf);
+}
+
+static int
+test_virResctrl(const void *opaque)
+{
+    struct virResctrlData *data = (struct virResctrlData *) opaque;
+    char *dir = NULL;
+    char *resctrl = NULL;
+    int ret = -1;
+    virResctrlSchemataPtr schemata = NULL;
+    char *schemata_str = NULL;
+    char *schemata_file;
+
+    if (virAsprintf(&resctrl, "%s/virresctrldata/linux-%s/resctrl",
+                    abs_srcdir, data->filename) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&schemata_file, "%s/virresctrldata/%s-free.schemata",
+                    abs_srcdir, virResctrlTypeToString(data->type)) < 0)
+        goto cleanup;
+
+    if (virFileWrapperAddPrefix("/sys/fs/resctrl", resctrl) < 0)
+        goto cleanup;
+
+    if ((schemata = virResctrlGetFreeCache(data->type)) == NULL)
+        goto cleanup;
+
+    virFileWrapperClearPrefixes();
+
+    GetSchemataStr(schemata, &schemata_str);
+
+    if (virTestCompareToFile(schemata_str, schemata_file) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(dir);
+    VIR_FREE(resctrl);
+    //VIR_FREE(schemata_str);
+    virResctrlFreeSchemata(schemata);
+    return ret;
+}
+
+static int
+mymain(void)
+{
+    int ret = 0;
+
+#define DO_TEST_FULL(filename, type) \
+    do {                                                                \
+        struct virResctrlData data = {filename,                         \
+                                      type};                            \
+        if (virTestRun(filename, test_virResctrl, &data) < 0)           \
+            ret = -1;                                                   \
+    } while (0)
+
+    DO_TEST_FULL("resctrl", VIR_RESCTRL_TYPE_L3);
+    DO_TEST_FULL("resctrl-cdp", VIR_RESCTRL_TYPE_L3_CODE);
+    DO_TEST_FULL("resctrl-cdp", VIR_RESCTRL_TYPE_L3_DATA);
+
+    return ret;
+}
+
+VIR_TEST_MAIN(mymain)
-- 
1.9.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list