Ping
Please let me know which is the direction.
Thx.
On Friday, 14 April 2017 at 6:01 PM, Eli Qiao wrote:
This is a RFC patch for the reimplement of `support cache tune(CAT) inlibvirt`[1].This patch defines some structs to represent data struct in linuxresctrl fs which will be used later to do cache allocation.The patch expose a private interface `virResctrlFreeSchemata`, whichwill 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 functionalworks, but people doesn't like it cause it has global variable, andmissing unit test case for new added capabilites, etc.Martin has proposed a test infra to do vircaps2xmltest, and I extened iton top of it to extend resctrl control[3], this is kinds of new desigedapart from [2], so I propose this RFC patch to do some rework on it.---include/libvirt/virterror.h | 1 +src/Makefile.am | 1 +src/libvirt_private.syms | 6 +src/util/virerror.c | 1 +src/util/virresctrl.c | 423 ++++++++++++++++++++++++++++++src/util/virresctrl.h | 86 ++++++tests/Makefile.am | 7 +-tests/virresctrldata/L3-free.schemata | 1 +tests/virresctrldata/L3CODE-free.schemata | 1 +tests/virresctrldata/L3DATA-free.schemata | 1 +tests/virresctrltest.c | 117 +++++++++11 files changed, 644 insertions(+), 1 deletion(-)create mode 100644 src/util/virresctrl.ccreate mode 100644 src/util/virresctrl.hcreate mode 100644 tests/virresctrldata/L3-free.schematacreate mode 100644 tests/virresctrldata/L3CODE-free.schematacreate mode 100644 tests/virresctrldata/L3DATA-free.schematacreate mode 100644 tests/virresctrltest.cdiff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.hindex 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_SENTINELSVIR_ERR_DOMAIN_LASTdiff --git a/src/Makefile.am b/src/Makefile.amindex 60eba37..0ae2af5 100644--- a/src/Makefile.am+++ b/src/Makefile.am@@ -165,6 +165,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.symsindex 9d7760d..b7225fe 100644--- a/src/libvirt_private.syms+++ b/src/libvirt_private.syms@@ -2396,6 +2396,12 @@ virRandomGenerateWWN;virRandomInt;+# util/virresctrl.h+virResctrlFreeSchemata;+virResctrlGetFreeCache;+virResctrlTypeToString;++# util/virrotatingfile.hvirRotatingFileReaderConsume;virRotatingFileReaderFree;diff --git a/src/util/virerror.c b/src/util/virerror.cindex 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.cnew file mode 100644index 0000000..778c2ec--- /dev/null+++ b/src/util/virresctrl.c@@ -0,0 +1,423 @@+/*+ * 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@xxxxxxxxx>+ */++#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/"++VIR_ENUM_IMPL(virResctrl, VIR_RESCTRL_TYPE_LAST,+ "L3",+ "L3CODE",+ "L3DATA",+ "L2")++/**+ * a virResctrlDomain represents a resource control group, it's a directory+ * under /sys/fs/resctrl.+ * eg: /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, eg: CG1. If it represent host's+ default resource group name, should be a NULL pointer */+ size_t n_tasks; /* number of task assigned to the resource group */+ char **tasks; /* task list which contains task id eg: 77454 */++ size_t n_schematas; /* number of schemata the resource group contains,+ eg: 2 */+ virResctrlSchemataPtr *schematas; /* scheamta list */+};++/* All resource control groups on this host, including default resource group */+typedef struct _virResctrlDomain virResctrlDomain;+typedef virResctrlDomain *virResctrlDomainPtr;+struct _virResctrlDomain {+ 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_schemata_items; i++)+ VIR_FREE(ptr->schemata_items[i]);+}++static void+virResctrlFreeGroup(virResctrlGroupPtr ptr)+{+ size_t i;++ if (!ptr)+ return;++ for (i = 0; i < ptr->n_tasks; i++)+ VIR_FREE(ptr->tasks[i]);++ for (i = 0; i < ptr->n_schematas; i++) {+ virResctrlFreeSchemata(ptr->schematas[i]);+ VIR_FREE(ptr->schematas[i]);+ }+}++static void+virResctrlFreeDomain(virResctrlDomainPtr ptr)+{+ size_t i;++ if (!ptr)+ return;++ for (i = 0; i < ptr->n_groups; i++) {+ virResctrlFreeGroup(ptr->groups[i]);+ VIR_FREE(ptr->groups[i]);+ }+}++static int+virResctrlCopySchemata(virResctrlSchemataPtr src,+ virResctrlSchemataPtr *dst)+{+ size_t i;+ virResctrlSchemataItemPtr schemataitem;+ virResctrlSchemataPtr schemata;++ if (VIR_ALLOC(schemata) < 0)+ return -1;++ schemata->type = src->type;++ for (i = 0; i < src->n_schemata_items; i++) {+ if (VIR_ALLOC(schemataitem) < 0)+ goto error;++ schemataitem->cache_id = src->schemata_items[i]->cache_id;+ schemataitem->continuous_schemata = src->schemata_items[i]->continuous_schemata;+ schemataitem->schemata = src->schemata_items[i]->schemata;+ schemataitem->size = src->schemata_items[i]->size;++ if (VIR_APPEND_ELEMENT(schemata->schemata_items,+ schemata->n_schemata_items,+ schemataitem) < 0)+ goto error;+ }++ *dst = schemata;++ return 0;++ error:+ virResctrlFreeSchemata(schemata);+ return -1;+}++static int+virResctrlGetSchemataString(virResctrlType type,+ const char *name,+ char **schemata)+{+ int rc = -1;+ char *tmp = NULL;+ char *end = NULL;+ char *buf = NULL;+ char *type_suffix = NULL;++ if (virFileReadValueString(&buf,+ SYSFS_RESCTRL_PATH "%s/schemata",+ name ? name : "") < 0)+ return -1;++ if (virAsprintf(&type_suffix,+ "%s:",+ virResctrlTypeToString(type)) < 0)+ goto cleanup;++ tmp = strstr(buf, type_suffix);++ if (!tmp)+ goto cleanup;++ end = strchr(tmp, '\n');+ if (end != NULL)+ *end = '\0';++ if (VIR_STRDUP(*schemata, tmp) < 0)+ goto cleanup;++ rc = 0;++ cleanup:+ VIR_FREE(buf);+ VIR_FREE(type_suffix);+ return rc;+}++static int+virResctrlLoadSchemata(const char* schemata_str,+ virResctrlSchemataPtr schemata)+{+ VIR_DEBUG("%s, %p\n", schemata_str, schemata);++ int ret = -1;+ char **lists = NULL;+ char **sms = NULL;+ char **sis = NULL;+ size_t i;+ virResctrlSchemataItemPtr si;++ /* parse L3:0=fffff;1=f */+ lists = virStringSplit(schemata_str, ":", 2);++ if ((!lists) || (!lists[1]))+ goto cleanup;++ /* parse 0=fffff;1=f */+ sms = virStringSplit(lists[1], ";", 0);+ if (!sms)+ goto cleanup;++ for (i = 0; sms[i] != NULL; i++) {+ /* parse 0=fffff */+ sis = virStringSplit(sms[i], "=", 2);+ if (!sis)+ goto cleanup;++ if (VIR_ALLOC(si) < 0)+ goto cleanup;++ if (virStrToLong_ui(sis[0], NULL, 10, &si->cache_id) < 0)+ goto cleanup;++ if (virStrToLong_ui(sis[1], NULL, 16, &si->continuous_schemata) < 0)+ goto cleanup;++ si->schemata = si->continuous_schemata;++ if (VIR_APPEND_ELEMENT(schemata->schemata_items,+ schemata->n_schemata_items,+ si) < 0)+ goto cleanup;++ }++ ret = 0;++ cleanup:+ VIR_FREE(si);+ virStringListFree(lists);+ virStringListFree(sms);+ virStringListFree(sis);+ return ret;+}++static int+virResctrlLoadGroup(const char *name,+ virResctrlDomainPtr dom)+{+ VIR_DEBUG("%s, %p\n", name, dom);++ int ret = -1;+ char *path = NULL;+ char *schemata_str;+ virResctrlType i;+ int rv;+ virResctrlGroupPtr grp;+ virResctrlSchemataPtr schemata;++ if ((virAsprintf(&path, "%s/%s", SYSFS_RESCTRL_PATH, name)) < 0)+ return -1;++ if (!virFileExists(path))+ goto cleanup;++ 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, name, &schemata_str);+ if (rv < 0)+ continue;++ if (VIR_ALLOC(schemata) < 0)+ goto cleanup;++ schemata->type = i;++ if (virResctrlLoadSchemata(schemata_str, schemata) < 0)+ goto cleanup;++ VIR_FREE(schemata_str);++ if (VIR_APPEND_ELEMENT(grp->schematas,+ grp->n_schematas,+ schemata) < 0)+ goto cleanup;++ virResctrlFreeSchemata(schemata);+ }++ if (VIR_APPEND_ELEMENT(dom->groups,+ dom->n_groups,+ grp) < 0)+ goto cleanup;++ ret = 0;++ cleanup:+ VIR_FREE(path);+ virResctrlFreeGroup(grp);+ return ret;+}++static int+virResctrlLoadDomain(virResctrlDomainPtr dom)+{+ int ret = -1;+ int rv = -1;+ DIR *dirp = NULL;+ char *path = NULL;+ struct dirent *ent;++ VIR_DEBUG("%s, %p\n", "", dom);++ rv = virDirOpenIfExists(&dirp, SYSFS_RESCTRL_PATH);++ if (rv < 0)+ goto cleanup;++ /* load default resctrl group */+ if (virResctrlLoadGroup("", dom) < 0)+ goto cleanup;++ while ((rv = virDirRead(dirp, &ent, path)) > 0) {+ /* only read directory in resctrl */+ if ((ent->d_type != DT_DIR) || STREQ(ent->d_name, "info"))+ continue;++ if (virResctrlLoadGroup(ent->d_name, dom) < 0)+ goto cleanup;+ }++ ret = 0;++ cleanup:+ virDirClose(&dirp);+ return ret;+}++static void+virResctrlRefreshDom(virResctrlDomainPtr dom, virResctrlType type)+{+ size_t i;+ size_t j;+ size_t k;++ virResctrlGroupPtr default_grp = NULL;+ virResctrlGroupPtr grp = NULL;+ virResctrlSchemataPtr schemata = NULL;+ virResctrlSchemataItemPtr schemataitem = NULL;++ default_grp = dom->groups[0];++ /* We are sure that the first group is the default one */+ for (i = 1; i < dom->n_groups; i++) {+ grp = dom->groups[i];+ for (j = 0; j < grp->n_schematas; j++) {+ schemata = grp->schematas[j];+ /* we can only calculate one type of schemata */+ if (schemata->type != type)+ continue;+ for (k = 0; k < schemata->n_schemata_items; k++) {+ schemataitem = schemata->schemata_items[k];+ /* if the schemata = 1, ignore it */+ if (schemataitem->continuous_schemata > 1)+ /* calculate default schemata, it can be non-continuous */+ default_grp->schematas[j]->schemata_items[k]->schemata &= ~(schemataitem->continuous_schemata);+ }+ }+ }+}++int virResctrlGetFreeCache(virResctrlType type,+ virResctrlSchemataPtr *schemata)+{+ VIR_DEBUG("%d, %p\n", type, schemata);+ int ret = -1;+ size_t i;+ virResctrlDomainPtr dom = NULL;+ virResctrlGroupPtr grp = NULL;++ if (VIR_ALLOC(dom) < 0)+ return -1;++ if (virResctrlLoadDomain(dom) < 0)+ goto cleanup;++ virResctrlRefreshDom(dom, type);+ grp = dom->groups[0];++ for (i = 0; i < grp->n_schematas; i ++)+ if (grp->schematas[i]->type == type)+ if (virResctrlCopySchemata(grp->schematas[i], schemata) < 0)+ goto cleanup;++ if (schemata != NULL)+ ret = 0;++ cleanup:+ virResctrlFreeDomain(dom);+ return ret;+}diff --git a/src/util/virresctrl.h b/src/util/virresctrl.hnew file mode 100644index 0000000..1b040d4--- /dev/null+++ b/src/util/virresctrl.h@@ -0,0 +1,86 @@+/*+ * 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@xxxxxxxxx>+ */++#ifndef __VIR_RESCTRL_H__+# define __VIR_RESCTRL_H__++#include "virutil.h"++typedef enum {+ VIR_RESCTRL_TYPE_L3,+ VIR_RESCTRL_TYPE_L3_CODE,+ VIR_RESCTRL_TYPE_L3_DATA,+ VIR_RESCTRL_TYPE_L2,++ VIR_RESCTRL_TYPE_LAST+} virResctrlType;++VIR_ENUM_DECL(virResctrl);++/*+ * a virResctrlSchemataItem represents one of schemata object in a+ * resource control group.+ * eg: 0=f+ */+typedef struct _virResctrlSchemataItem virResctrlSchemataItem;+typedef virResctrlSchemataItem *virResctrlSchemataItemPtr;+struct _virResctrlSchemataItem {+ unsigned int cache_id; /* cache resource id, eg: 0 */+ unsigned int continuous_schemata; /* schemata, should be a continuous bits,+ eg: f, this schemata can be persisted+ to sysfs */+ unsigned int schemata; /* schemata eg: f0f, a schemata which is calculated+ at running time */+ unsigned long long size; /* the cache size schemata represented in B,+ eg: (min * bits of continuous_schemata) */+};++/*+ * 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, eg: L3 */+ size_t n_schemata_items; /* number of schemata item, eg: 2 */+ virResctrlSchemataItemPtr *schemata_items; /* pointer list of schemata item */+};++/* Get free cache of the host, result saved in schemata */+int virResctrlGetFreeCache(virResctrlType type,+ virResctrlSchemataPtr *schemata);+++/* TODO Need to first define virDomainCachetunePtr */+/* Set cache allocation for a VM domain */+// int virResctrlSetCacheBanks(virDomainCachetunePtr cachetune,+// unsigned char *group_name,+// size_t n_pids,+// pid_t *pids);+//+/* remove cache allocation for a VM domain */+// int virResctrlRemoveCacheBanks(unsigned char *group_name);+void virResctrlFreeSchemata(virResctrlSchemataPtr ptr);+#endifdiff --git a/tests/Makefile.am b/tests/Makefile.amindex 3cc828d..0e09e43 100644--- a/tests/Makefile.am+++ b/tests/Makefile.am@@ -229,6 +229,7 @@ if WITH_LINUXtest_programs += fchosttesttest_programs += scsihosttesttest_programs += vircaps2xmltest+test_programs += virresctrltesttest_libraries += virusbmock.la \@@ -1150,6 +1151,10 @@ vircaps2xmltest_SOURCES = \vircaps2xmltest.c testutils.h testutils.c virfilemock.cvircaps2xmltest_LDADD = $(LDADDS)+virresctrltest_SOURCES = \+ virresctrltest.c testutils.h testutils.c virfilemock.c+virresctrltest_LDADD = $(LDADDS)+virnumamock_la_SOURCES = \virnumamock.cvirnumamock_la_CFLAGS = $(AM_CFLAGS)@@ -1157,7 +1162,7 @@ virnumamock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)virnumamock_la_LIBADD = $(MOCKLIBS_LIBS)else ! WITH_LINUX-EXTRA_DIST += vircaps2xmltest.c virnumamock.c+EXTRA_DIST += vircaps2xmltest.c virresctrltest.c virnumamock.cendif ! WITH_LINUXif WITH_NSSdiff --git a/tests/virresctrldata/L3-free.schemata b/tests/virresctrldata/L3-free.schematanew file mode 100644index 0000000..9b47d25--- /dev/null+++ b/tests/virresctrldata/L3-free.schemata@@ -0,0 +1 @@+L3:0=1ffff;1=1ffffdiff --git a/tests/virresctrldata/L3CODE-free.schemata b/tests/virresctrldata/L3CODE-free.schematanew file mode 100644index 0000000..7039c45--- /dev/null+++ b/tests/virresctrldata/L3CODE-free.schemata@@ -0,0 +1 @@+L3CODE:0=cffff;1=cffffdiff --git a/tests/virresctrldata/L3DATA-free.schemata b/tests/virresctrldata/L3DATA-free.schematanew file mode 100644index 0000000..30f1cbd--- /dev/null+++ b/tests/virresctrldata/L3DATA-free.schemata@@ -0,0 +1 @@+L3DATA:0=3ffff;1=3ffffdiff --git a/tests/virresctrltest.c b/tests/virresctrltest.cnew file mode 100644index 0000000..4926468--- /dev/null+++ b/tests/virresctrltest.c@@ -0,0 +1,117 @@+/*+ * 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@xxxxxxxxx>+ */++#include <config.h>+#include <stdlib.h>++#include "testutils.h"+#include "virbitmap.h"+#include "virfilemock.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=%x",+ virResctrlTypeToString(schemata->type),+ schemata->schemata_items[0]->cache_id,+ schemata->schemata_items[0]->schemata);++ for (i = 1; i < schemata->n_schemata_items; i ++)+ virBufferAsprintf(&buf, ";%u=%x",+ schemata->schemata_items[i]->cache_id,+ schemata->schemata_items[i]->schemata);++ *str = virBufferContentAndReset(&buf);+}++static int+test_virResctrl(const void *opaque)+{+ struct virResctrlData *data = "" virResctrlData *) opaque;+ char *dir = NULL;+ char *resctrl = NULL;+ int ret = -1;+ virResctrlSchemataPtr schemata = NULL;+ char *schemata_str;+ 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;++ virFileMockAddPrefix("/sys/fs/resctrl", resctrl);++ if (virResctrlGetFreeCache(data->type, &schemata) < 0)+ goto cleanup;++ GetSchemataStr(schemata, &schemata_str);++ if (virTestCompareToFile(schemata_str, schemata_file) < 0)+ goto cleanup;++ virFileMockClearPrefixes();++ 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 = "" \+ 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_PRELOAD(mymain, abs_builddir "/.libs/virnumamock.so")--1.9.1--libvir-list mailing list
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list