summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-04-29 20:22:36 -0300
committerLennart Poettering <lennart@poettering.net>2013-04-30 08:36:01 -0300
commit8af8afd6b3a34d1218826f55ada8ece8b4e36fed (patch)
tree2158894c31fed3ad2543623beedce46451a44b52
parent5f1dac6bf605871615b35891a3966fa474db5b20 (diff)
cgroup: make cg_pid_get_path() work properly for co-mounted controllers and normalized named hierarchies
-rw-r--r--TODO4
-rw-r--r--src/shared/cgroup-util.c44
2 files changed, 34 insertions, 14 deletions
diff --git a/TODO b/TODO
index 78d168c36..eedabd8ba 100644
--- a/TODO
+++ b/TODO
@@ -26,8 +26,6 @@ Fedora 19:
Features:
-* handle named vs controller hierarchies correctly in cg_pid_get_path()
-
* add nspawn@.service
* investigate endianess issues of UUID vs. GUID
@@ -59,8 +57,6 @@ Features:
* cgtop: make cgtop useful in a container
-* make sure cg_pid_get_path() works properly for co-mounted controllers
-
* test/:
- add 'set -e' to scripts in test/
- make stuff in test/ work with separate output dir
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 016080f65..1366f5865 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -736,24 +736,27 @@ int cg_set_task_access(
}
int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
- char fs[sizeof("/proc/") - 1 + DECIMAL_STR_MAX(pid_t) + sizeof("/cgroup")];
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
+ const char *fs;
size_t cs;
assert(path);
assert(pid >= 0);
- if (controller && !cg_controller_is_valid(controller, true))
- return -EINVAL;
+ if (controller) {
+ if (!cg_controller_is_valid(controller, true))
+ return -EINVAL;
- if (!controller)
+ controller = normalize_controller(controller);
+ } else
controller = SYSTEMD_CGROUP_CONTROLLER;
if (pid == 0)
- pid = getpid();
+ fs = "/proc/self/cgroup";
+ else
+ fs = procfs_file_alloca(pid, "cgroup");
- sprintf(fs, "/proc/%lu/cgroup", (unsigned long) pid);
f = fopen(fs, "re");
if (!f)
return errno == ENOENT ? -ESRCH : -errno;
@@ -761,7 +764,10 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
cs = strlen(controller);
FOREACH_LINE(line, f, return -errno) {
- char *l, *p;
+ char *l, *p, *w, *e;
+ size_t k;
+ char *state;
+ bool found = false;
truncate_nl(line);
@@ -770,13 +776,31 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
continue;
l++;
- if (!strneq(l, controller, cs))
+ e = strchr(l, ':');
+ if (!e)
continue;
- if (l[cs] != ':')
+ *e = 0;
+
+ FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
+
+ if (k == cs && memcmp(w, controller, cs) == 0) {
+ found = true;
+ break;
+ }
+
+ if (k == 5 + cs &&
+ memcmp(w, "name=", 5) == 0 &&
+ memcmp(w+5, controller, cs) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
continue;
- p = strdup(l + cs + 1);
+ p = strdup(e + 1);
if (!p)
return -ENOMEM;