chiark / gitweb /
cgroup: make cg_pid_get_path() work properly for co-mounted controllers and normalize...
authorLennart Poettering <lennart@poettering.net>
Mon, 29 Apr 2013 23:22:36 +0000 (20:22 -0300)
committerLennart Poettering <lennart@poettering.net>
Tue, 30 Apr 2013 11:36:01 +0000 (08:36 -0300)
TODO
src/shared/cgroup-util.c

diff --git a/TODO b/TODO
index 78d168c3600f005bf700dbc1eab00f04e2fc3f1a..eedabd8ba9fbffcbb4d63106512cc20fc9bffb2d 100644 (file)
--- 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
index 016080f65b902b49eae26e2195ff5a8f7d77a159..1366f5865f418f7a89fdfcb0de5b1027c098fc97 100644 (file)
@@ -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;