From 66a7f857f31309f02e7ded96ee7a9c896fa065a5 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 19 Jul 2013 11:13:05 +0100 Subject: [PATCH] Add a virCgroupNewDetect API for finding cgroup placement Add a virCgroupNewDetect API which is used to initialize a cgroup object with the placement of an arbitrary process. Signed-off-by: Daniel P. Berrange --- src/libvirt_private.syms | 1 + src/util/vircgroup.c | 81 ++++++++++++++++++++++++++-------------- src/util/vircgroup.h | 3 ++ 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 76873ad058..49b9f9d943 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1186,6 +1186,7 @@ virCgroupKill; virCgroupKillPainfully; virCgroupKillRecursive; virCgroupMoveTask; +virCgroupNewDetect; virCgroupNewDomainDriver; virCgroupNewDomainPartition; virCgroupNewDriver; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 525161181f..94d19e00f5 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -306,18 +306,30 @@ static int virCgroupCopyPlacement(virCgroupPtr group, * It then appends @path to each detected path. */ static int virCgroupDetectPlacement(virCgroupPtr group, + pid_t pid, const char *path) { size_t i; FILE *mapping = NULL; char line[1024]; int ret = -1; + char *procfile; - mapping = fopen("/proc/self/cgroup", "r"); + if (pid == -1) { + if (VIR_STRDUP(procfile, "/proc/self/cgroup") < 0) + goto cleanup; + } else { + if (virAsprintf(&procfile, "/proc/%llu/cgroup", + (unsigned long long)pid) < 0) + goto cleanup; + } + + mapping = fopen(procfile, "r"); if (mapping == NULL) { - virReportSystemError(errno, "%s", - _("Unable to open /proc/self/cgroup")); - return -1; + virReportSystemError(errno, + _("Unable to open '%s'"), + procfile); + goto cleanup; } while (fgets(line, sizeof(line), mapping) != NULL) { @@ -371,12 +383,14 @@ static int virCgroupDetectPlacement(virCgroupPtr group, ret = 0; cleanup: + VIR_FREE(procfile); VIR_FORCE_FCLOSE(mapping); return ret; } static int virCgroupDetect(virCgroupPtr group, + pid_t pid, int controllers, const char *path, virCgroupPtr parent) @@ -453,7 +467,7 @@ static int virCgroupDetect(virCgroupPtr group, if (virCgroupCopyPlacement(group, path, parent) < 0) return -1; } else { - if (virCgroupDetectPlacement(group, path) < 0) + if (virCgroupDetectPlacement(group, pid, path) < 0) return -1; } @@ -470,10 +484,11 @@ static int virCgroupDetect(virCgroupPtr group, return -1; } - VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s", i, + VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %llu", i, virCgroupControllerTypeToString(i), group->controllers[i].mountPoint, - group->controllers[i].placement); + group->controllers[i].placement, + (unsigned long long)pid); } return 0; @@ -826,7 +841,8 @@ cleanup: * * Returns 0 on success, -1 on error */ -static int virCgroupNew(const char *path, +static int virCgroupNew(pid_t pid, + const char *path, virCgroupPtr parent, int controllers, virCgroupPtr *group) @@ -849,7 +865,7 @@ static int virCgroupNew(const char *path, goto error; } - if (virCgroupDetect(*group, controllers, path, parent) < 0) + if (virCgroupDetect(*group, pid, controllers, path, parent) < 0) goto error; return 0; @@ -871,7 +887,7 @@ static int virCgroupAppRoot(virCgroupPtr *group, if (virCgroupNewSelf(&selfgrp) < 0) return -1; - if (virCgroupNew("libvirt", selfgrp, controllers, group) < 0) + if (virCgroupNew(-1, "libvirt", selfgrp, controllers, group) < 0) goto cleanup; if (virCgroupMakeGroup(selfgrp, *group, create, VIR_CGROUP_NONE) < 0) @@ -1287,7 +1303,7 @@ int virCgroupNewPartition(const char *path, if (virCgroupSetPartitionSuffix(path, &newpath) < 0) goto cleanup; - if (virCgroupNew(newpath, NULL, controllers, group) < 0) + if (virCgroupNew(-1, newpath, NULL, controllers, group) < 0) goto cleanup; if (STRNEQ(newpath, "/")) { @@ -1299,7 +1315,7 @@ int virCgroupNewPartition(const char *path, tmp++; *tmp = '\0'; - if (virCgroupNew(parentPath, NULL, controllers, &parent) < 0) + if (virCgroupNew(-1, parentPath, NULL, controllers, &parent) < 0) goto cleanup; if (virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE) < 0) { @@ -1350,7 +1366,7 @@ int virCgroupNewDriver(const char *name, create, controllers) < 0) goto cleanup; - if (virCgroupNew(name, rootgrp, -1, group) < 0) + if (virCgroupNew(-1, name, rootgrp, -1, group) < 0) goto cleanup; if (virCgroupMakeGroup(rootgrp, *group, create, VIR_CGROUP_NONE) < 0) { @@ -1387,19 +1403,11 @@ int virCgroupNewDriver(const char *name ATTRIBUTE_UNUSED, * * Returns 0 on success, or -1 on error */ -#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R int virCgroupNewSelf(virCgroupPtr *group) { - return virCgroupNew("", NULL, -1, group); + return virCgroupNewDetect(-1, group); } -#else -int virCgroupNewSelf(virCgroupPtr *group ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENXIO, "%s", - _("Control groups not supported on this platform")); - return -1; -} -#endif + /** * virCgroupNewDomainDriver: @@ -1418,7 +1426,7 @@ int virCgroupNewDomainDriver(virCgroupPtr driver, { int ret = -1; - if (virCgroupNew(name, driver, -1, group) < 0) + if (virCgroupNew(-1, name, driver, -1, group) < 0) goto cleanup; /* @@ -1480,7 +1488,7 @@ int virCgroupNewDomainPartition(virCgroupPtr partition, if (virCgroupPartitionEscape(&grpname) < 0) goto cleanup; - if (virCgroupNew(grpname, partition, -1, group) < 0) + if (virCgroupNew(-1, grpname, partition, -1, group) < 0) goto cleanup; /* @@ -1545,7 +1553,7 @@ int virCgroupNewVcpu(virCgroupPtr domain, (1 << VIR_CGROUP_CONTROLLER_CPUACCT) | (1 << VIR_CGROUP_CONTROLLER_CPUSET)); - if (virCgroupNew(name, domain, controllers, group) < 0) + if (virCgroupNew(-1, name, domain, controllers, group) < 0) goto cleanup; if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) { @@ -1592,7 +1600,7 @@ int virCgroupNewEmulator(virCgroupPtr domain, (1 << VIR_CGROUP_CONTROLLER_CPUACCT) | (1 << VIR_CGROUP_CONTROLLER_CPUSET)); - if (virCgroupNew("emulator", domain, controllers, group) < 0) + if (virCgroupNew(-1, "emulator", domain, controllers, group) < 0) goto cleanup; if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) { @@ -1617,6 +1625,23 @@ int virCgroupNewEmulator(virCgroupPtr domain ATTRIBUTE_UNUSED, #endif + +#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R +int virCgroupNewDetect(pid_t pid, + virCgroupPtr *group) +{ + return virCgroupNew(pid, "", NULL, -1, group); +} +#else +int virCgroupNewDetect(pid_t pid ATTRIBUTE_UNUSED, + virCgroupPtr *group ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENXIO, "%s", + _("Control groups not supported on this platform")); + return -1; +} +#endif + bool virCgroupNewIgnoreError(void) { if (virLastErrorIsSystemErrno(ENXIO) || @@ -2573,7 +2598,7 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas VIR_DEBUG("Process subdir %s", ent->d_name); - if (virCgroupNew(ent->d_name, group, -1, &subgroup) < 0) + if (virCgroupNew(-1, ent->d_name, group, -1, &subgroup) < 0) goto cleanup; if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids, true)) < 0) diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index 0ec8b67f59..602d4ff7e9 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -86,6 +86,9 @@ int virCgroupNewEmulator(virCgroupPtr domain, virCgroupPtr *group) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); +int virCgroupNewDetect(pid_t pid, + virCgroupPtr *group); + bool virCgroupNewIgnoreError(void); int virCgroupPathOfController(virCgroupPtr group,