Add RDT/CMT feature (Intel x86) by interacting with kernel resctrl file system. Integrate code into util/resctrl.
---
src/libvirt_private.syms | 9 ++
src/util/virresctrl.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++-
src/util/virresctrl.h | 44 +++++++
3 files changed, 367 insertions(+), 2 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b4ab1f3..e16c3e0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2634,6 +2634,15 @@ virResctrlAllocSetSize;
virResctrlGetInfo;
virResctrlInfoGetCache;
virResctrlInfoNew;
+virResctrlMonNew;
+virResctrlMonSetID;
+virResctrlMonGetID;
+virResctrlMonDeterminePath;
+virResctrlMonAddPID;
+virResctrlMonCreate;
+virResctrlMonRemove;
+virResctrlMonIsRunning;
+virResctrlMonGetCacheOccupancy;
# util/virrotatingfile.h
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index fc11635..e5f5caf 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -224,6 +224,22 @@ struct _virResctrlAlloc {
static virClassPtr virResctrlAllocClass;
+struct _virResctrlMon {
+ virObject parent;
+
+ /* pairedalloc: pointer to a resctrl allocaion it paried with.
+ * NULL for a resctrl monitoring group not associated with
+ * any allocation. */
+ virResctrlAllocPtr pairedalloc;
+ /* The identifier (any unique string for now) */
+ char *id;
+ /* libvirt-generated path, may be identical to alloction path
+ * may not if allocation is ready */
+ char *path;
+};
+
+static virClassPtr virResctrlMonClass;
+
static void
virResctrlAllocDispose(void *obj)
{
@@ -275,7 +291,28 @@ virResctrlAllocOnceInit(void)
}
+static void
+virResctrlMonDispose(void *obj)
+{
+ virResctrlMonPtr resctrlMon = obj;
+
+ VIR_FREE(resctrlMon->id);
+ VIR_FREE(resctrlMon->path);
+}
+
+
+static int
+virResctrlMonOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(virResctrlMon, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+
VIR_ONCE_GLOBAL_INIT(virResctrlAlloc)
+VIR_ONCE_GLOBAL_INIT(virResctrlMon)
virResctrlAllocPtr
@@ -288,6 +325,16 @@ virResctrlAllocNew(void)
}
+virResctrlMonPtr
+virResctrlMonNew(void)
+{
+ if (virResctrlMonInitialize() < 0)
+ return NULL;
+
+ return virObjectNew(virResctrlMonClass);
+}
+
+
/* Common functions */
#ifdef __linux__
static int
@@ -329,8 +376,6 @@ virResctrlLockWrite(void)
#endif
-
-
static int
virResctrlUnlock(int fd)
{
@@ -1646,3 +1691,270 @@ virResctrlAllocRemove(virResctrlAllocPtr alloc)
return ret;
}
+
+
+int
+virResctrlMonSetID(virResctrlMonPtr mon,
+ const char *id)
+{
+ if (!id) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Resctrl mon group 'id' cannot be NULL"));
+ return -1;
+ }
+
+ return VIR_STRDUP(mon->id, id);
+}
+
+
+const char *
+virResctrlMonGetID(virResctrlMonPtr mon)
+{
+ return mon->id;
+}
+
+
+int
+virResctrlMonDeterminePath(virResctrlMonPtr mon,
+ const char *machinename)
+{
+
+ VIR_DEBUG("mon group, mon->path=%s\n", mon->path);
+ if (!mon->id) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Resctrl mon group id must be set before creation"));
+ return -1;
+ }
+
+ if (mon->path)
+ return -1;
+
+ if(mon->pairedalloc)
+ {
+ if (virAsprintf(&mon->path, "%s/%s-%s",
+ SYSFS_RESCTRL_PATH, machinename, mon->id) < 0)
+ return -1;
+ }
+ else
+ {
+ if (virAsprintf(&mon->path, "%s/mon_groups/%s-%s",
+ SYSFS_RESCTRL_PATH, machinename, mon->id) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+virResctrlMonAddPID(virResctrlMonPtr mon,
+ pid_t pid)
+{
+ char *tasks = NULL;
+ char *pidstr = NULL;
+ int ret = 0;
+
+ if (!mon->path) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot add pid to non-existing resctrl mon group"));
+ return -1;
+ }
+
+ VIR_DEBUG("Add PID %d to domain %s\n",
+ pid, mon->path);
+
+ if (virAsprintf(&tasks, "%s/tasks", mon->path) < 0)
+ return -1;
+
+ if (virAsprintf(&pidstr, "%lld", (long long int) pid) < 0)
+ goto cleanup;
+
+ if (virFileWriteStr(tasks, pidstr, 0) < 0) {
+ virReportSystemError(errno,
+ _("Cannot write pid in tasks file '%s'"),
+ tasks);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FREE(tasks);
+ VIR_FREE(pidstr);
+ return ret;
+}
+
+
+int
+virResctrlMonCreate(virResctrlAllocPtr pairedalloc,
+ virResctrlMonPtr mon,
+ const char *machinename)
+{
+ int ret = -1;
+ int lockfd = -1;
+
+ if (!mon)
+ return 0;
+
+
+ if (pairedalloc)
+ {
+ if (!virFileExists(pairedalloc->path)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("For paired mon group, the resctrl allocation "
+ "must be created first"));
+ goto cleanup;
+ }
+ mon->pairedalloc = pairedalloc;
+
+ if (virResctrlMonDeterminePath(mon, machinename) < 0)
+ return -1;
+ }
+ else
+ {
+ mon->pairedalloc = NULL;
+
+ /* resctrl mon group object may use for multiple purpose,
+ * free mon group path information*/
+ VIR_FREE(mon->path);
+
+ if (virResctrlMonDeterminePath(mon, machinename) < 0)
+ return -1;
+
+ lockfd = virResctrlLockWrite();
+ if (lockfd < 0)
+ goto cleanup;
+
+ if (virFileExists(mon->path))
+ {
+ VIR_DEBUG("Removing resctrl mon group %s", mon->path);
+ if (rmdir(mon->path) != 0 && errno != ENOENT) {
+ ret = -errno;
+ VIR_ERROR(_("Unable to remove %s (%d)"), mon->path, errno);
+ goto cleanup;
+ }
+ }
+
+ if (virFileMakePath(mon->path) < 0) {
+ virReportSystemError(errno,
+ _("Cannot create resctrl directory '%s'"),
+ mon->path);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+cleanup:
+ virResctrlUnlock(lockfd);
+ return ret;
+}
+
+
+int
+virResctrlMonRemove(virResctrlMonPtr mon)
+{
+ int ret = 0;
+
+ if (!mon->path)
+ return 0;
+
+ VIR_DEBUG("Removing resctrl mon group %s", mon->path);
+ if (rmdir(mon->path) != 0 && errno != ENOENT) {
+ ret = -errno;
+ VIR_ERROR(_("Unable to remove %s (%d)"), mon->path, errno);
+ }
+
+ return ret;
+}
+
+
+bool
+virResctrlMonIsRunning(virResctrlMonPtr mon)
+{
+ bool ret = false;
+ char *tasks = NULL;
+
+ if (mon && virFileExists(mon->path)) {
+ ret = virFileReadValueString(&tasks, "%s/tasks", mon->path);
+ if (ret < 0)
+ goto cleanup;
+
+ if (!tasks || !tasks[0])
+ goto cleanup;
+
+ ret = true;
+ }
+
+cleanup:
+ VIR_FREE(tasks);
+
+ return ret;
+}
+
+
+int
+virResctrlMonGetCacheOccupancy(virResctrlMonPtr mon,
+ unsigned int * cacheoccu)
+{
+ DIR *dirp = NULL;
+ int ret = -1;
+ int rv = -1;
+ struct dirent *ent = NULL;
+ unsigned int cachetotal = 0;
+ unsigned int cacheoccyperblock = 0;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *pathmondata = NULL;
+
+ if (!mon->path)
+ goto cleanup;
+
+ rv = virDirOpenIfExists(&dirp,mon->path);
+ if (rv <= 0) {
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buf, "%s/mon_data",
+ mon->path);
+ pathmondata = virBufferContentAndReset(&buf);
+ if (!pathmondata)
+ goto cleanup;
+
+ VIR_DEBUG("Seek llc_occupancy file from root: %s ",
+ pathmondata);
+
+ if (virDirOpen(&dirp, pathmondata) < 0)
+ goto cleanup;
+
+ while ((rv = virDirRead(dirp, &ent, pathmondata)) > 0) {
+ VIR_DEBUG("Parsing file '%s'", ent->d_name);
+ if (ent->d_type != DT_DIR)
+ continue;
+
+ if (STRNEQLEN(ent->d_name, "mon_L", 5))
+ continue;
+
+ rv = virFileReadValueUint(&cacheoccyperblock,
+ "%s/%s/llc_occupancy",
+ pathmondata, ent->d_name);
+ if (rv == -2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "file %s/%s/llc_occupancy does not exist",
+ pathmondata, ent->d_name);
+ goto cleanup;
+ } else if (rv < 0) {
+ goto cleanup;
+ }
+
+ VIR_DEBUG("%s/%s/llc_occupancy: occupancy %d bytes",
+ pathmondata, ent->d_name, cacheoccyperblock);
+
+ cachetotal += cacheoccyperblock;
+ }
+
+ *cacheoccu = cachetotal;
+
+ ret = 0;
+cleanup:
+ VIR_FREE(pathmondata);
+ VIR_DIR_CLOSE(dirp);
+ return ret;
+}
diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h
index 5368ba2..a23c425 100644
--- a/src/util/virresctrl.h
+++ b/src/util/virresctrl.h
@@ -35,6 +35,12 @@ typedef enum {
VIR_ENUM_DECL(virCache);
+typedef enum {
+ VIR_RESCTRL_MONACT_NONE,
+ VIR_RESCTRL_MONACT_ENABLE,
+ VIR_RESCTRL_MONACT_DISABLE
+} virResctrlMonAct;
+
typedef struct _virResctrlInfoPerCache virResctrlInfoPerCache;
typedef virResctrlInfoPerCache *virResctrlInfoPerCachePtr;
@@ -118,4 +124,42 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc,
int
virResctrlAllocRemove(virResctrlAllocPtr alloc);
+
+/* Monitoring-related things */
+typedef struct _virResctrlMon virResctrlMon;
+typedef virResctrlMon *virResctrlMonPtr;
+
+virResctrlMonPtr
+virResctrlMonNew(void);
+
+int
+virResctrlMonSetID(virResctrlMonPtr mon,
+ const char *id);
+
+const char *
+virResctrlMonGetID(virResctrlMonPtr mon);
+
+int
+virResctrlMonDeterminePath(virResctrlMonPtr mon,
+ const char *machinename);
+
+int
+virResctrlMonAddPID(virResctrlMonPtr alloc,
+ pid_t pid);
+
+int
+virResctrlMonCreate(virResctrlAllocPtr pairedalloc,
+ virResctrlMonPtr mon,
+ const char *machinename);
+
+int
+virResctrlMonRemove(virResctrlMonPtr mon);
+
+bool
+virResctrlMonIsRunning(virResctrlMonPtr mon);
+
+int
+virResctrlMonGetCacheOccupancy(virResctrlMonPtr mon,
+ unsigned int * cacheoccu);
+
#endif /* __VIR_RESCTRL_H__ */
--
2.7.4
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Fri, Jun 08, 2018 at 05:02:17PM +0800, Wang Huaqiang wrote: >Add RDT/CMT feature (Intel x86) by interacting with kernel resctrl file system. Integrate code into util/resctrl. >--- > src/libvirt_private.syms | 9 ++ > src/util/virresctrl.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++- > src/util/virresctrl.h | 44 +++++++ > 3 files changed, 367 insertions(+), 2 deletions(-) > This will not merge after some of the cleanups I made. There is one more patch that didn't get in and you clould look there for some inspiration as well, but it's just about keeping the data in another part of the code. Anyway the conflict is very easy to fix now. Why isn't it just a matter of setting a boolean? Aling the code and run the checks before posting to the list. For more info see contribution guidelines: https://libvirt.org/hacking.html-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
See my update inline. > -----Original Message----- > From: Martin Kletzander [mailto:mkletzan@redhat.com] > Sent: Monday, June 11, 2018 4:40 PM > To: Wang, Huaqiang <huaqiang.wang@intel.com> > Cc: libvir-list@redhat.com; Feng, Shaohe <shaohe.feng@intel.com>; Niu, Bing > <bing.niu@intel.com>; Ding, Jian-feng <jian-feng.ding@intel.com>; Zang, Rui > <rui.zang@intel.com> > Subject: Re: [libvirt] [PATCH 1/3] util: add Intel x86 RDT/CMT support > > On Fri, Jun 08, 2018 at 05:02:17PM +0800, Wang Huaqiang wrote: > >Add RDT/CMT feature (Intel x86) by interacting with kernel resctrl file system. > Integrate code into util/resctrl. > >--- > > src/libvirt_private.syms | 9 ++ > > src/util/virresctrl.c | 316 > ++++++++++++++++++++++++++++++++++++++++++++++- > > src/util/virresctrl.h | 44 +++++++ > > 3 files changed, 367 insertions(+), 2 deletions(-) > > > > This will not merge after some of the cleanups I made. There is one more patch > that didn't get in and you clould look there for some inspiration as well, but it's > just about keeping the data in another part of the code. > > Anyway the conflict is very easy to fix now. > > Why isn't it just a matter of setting a boolean? > > Aling the code and run the checks before posting to the list. For more info see > contribution guidelines: > > https://libvirt.org/hacking.html Yes, noticed your patch. I'd like to make changes accordingly. Will follow the rules listed in "https://libvirt.org/hacking.html" and take care the coding style. Thanks very much. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.