chiark / gitweb /
logind: hook up inhibit logic with idle hint logic
[elogind.git] / src / core / cgroup.c
index ef9b02f4639000039d0e19346049d178ce7b03c6..b1e22e0ac3e48c49e08b69deade23a66c5031cf3 100644 (file)
@@ -30,6 +30,7 @@
 #include "cgroup.h"
 #include "cgroup-util.h"
 #include "log.h"
+#include "strv.h"
 
 int cgroup_bonding_realize(CGroupBonding *b) {
         int r;
@@ -108,26 +109,43 @@ void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
                 cgroup_bonding_trim(b, delete_root);
 }
 
-int cgroup_bonding_install(CGroupBonding *b, pid_t pid) {
+
+int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffix) {
+        char *p = NULL;
+        const char *path;
         int r;
 
         assert(b);
         assert(pid >= 0);
 
-        if ((r = cg_create_and_attach(b->controller, b->path, pid)) < 0)
+        if (cgroup_suffix) {
+                p = join(b->path, "/", cgroup_suffix, NULL);
+                if (!p)
+                        return -ENOMEM;
+
+                path = p;
+        } else
+                path = b->path;
+
+        r = cg_create_and_attach(b->controller, path, pid);
+        free(p);
+
+        if (r < 0)
                 return r;
 
         b->realized = true;
         return 0;
 }
 
-int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid) {
+int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgroup_suffix) {
         CGroupBonding *b;
         int r;
 
-        LIST_FOREACH(by_unit, b, first)
-                if ((r = cgroup_bonding_install(b, pid)) < 0 && b->essential)
+        LIST_FOREACH(by_unit, b, first) {
+                r = cgroup_bonding_install(b, pid, cgroup_suffix);
+                if (r < 0 && b->essential)
                         return r;
+        }
 
         return 0;
 }
@@ -176,7 +194,11 @@ int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t
         return 0;
 }
 
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s) {
+int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
+        char *p = NULL;
+        const char *path;
+        int r;
+
         assert(b);
         assert(sig >= 0);
 
@@ -184,10 +206,22 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s) {
         if (!b->ours)
                 return 0;
 
-        return cg_kill_recursive(b->controller, b->path, sig, sigcont, true, false, s);
+        if (cgroup_suffix) {
+                p = join(b->path, "/", cgroup_suffix, NULL);
+                if (!p)
+                        return -ENOMEM;
+
+                path = p;
+        } else
+                path = b->path;
+
+        r = cg_kill_recursive(b->controller, path, sig, sigcont, true, false, s);
+        free(p);
+
+        return r;
 }
 
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s) {
+int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
         CGroupBonding *b;
         Set *allocated_set = NULL;
         int ret = -EAGAIN, r;
@@ -200,7 +234,8 @@ int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s
                         return -ENOMEM;
 
         LIST_FOREACH(by_unit, b, first) {
-                if ((r = cgroup_bonding_kill(b, sig, sigcont, s)) < 0) {
+                r = cgroup_bonding_kill(b, sig, sigcont, s, cgroup_suffix);
+                if (r < 0) {
                         if (r == -EAGAIN || r == -ESRCH)
                                 continue;
 
@@ -271,7 +306,8 @@ int manager_setup_cgroup(Manager *m) {
         }
 
         /* 1. Determine hierarchy */
-        if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0) {
+        r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current);
+        if (r < 0) {
                 log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
                 goto finish;
         }
@@ -300,7 +336,8 @@ int manager_setup_cgroup(Manager *m) {
         }
 
         /* 2. Show data */
-        if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0) {
+        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
+        if (r < 0) {
                 log_error("Cannot find cgroup mount point: %s", strerror(-r));
                 goto finish;
         }
@@ -308,7 +345,8 @@ int manager_setup_cgroup(Manager *m) {
         log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
 
         /* 3. Install agent */
-        if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH)) < 0)
+        r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
+        if (r < 0)
                 log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
         else if (r > 0)
                 log_debug("Installed release agent.");
@@ -316,7 +354,8 @@ int manager_setup_cgroup(Manager *m) {
                 log_debug("Release agent already installed.");
 
         /* 4. Realize the group */
-        if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0) {
+        r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0);
+        if (r < 0) {
                 log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
                 goto finish;
         }
@@ -325,7 +364,8 @@ int manager_setup_cgroup(Manager *m) {
         if (m->pin_cgroupfs_fd >= 0)
                 close_nointr_nofail(m->pin_cgroupfs_fd);
 
-        if ((m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK)) < 0) {
+        m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
+        if (r < 0) {
                 log_error("Failed to open pin file: %m");
                 r = -errno;
                 goto finish;
@@ -333,6 +373,8 @@ int manager_setup_cgroup(Manager *m) {
 
         log_debug("Created root group.");
 
+        manager_shorten_default_controllers(m);
+
 finish:
         free(current);
         free(path);
@@ -355,6 +397,35 @@ void manager_shutdown_cgroup(Manager *m, bool delete) {
         m->cgroup_hierarchy = NULL;
 }
 
+void manager_shorten_default_controllers(Manager *m) {
+        char **f, **t;
+
+        strv_uniq(m->default_controllers);
+
+        if (!m->default_controllers)
+                return;
+
+        for (f = m->default_controllers, t = m->default_controllers; *f; f++) {
+
+                if (!streq(*f, "systemd") && !streq(*f, "name=systemd")) {
+                        char *cc;
+
+                        cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(*f));
+                        strcpy(stpcpy(cc, "/sys/fs/cgroup/"), *f);
+
+                        if (access(cc, F_OK) >= 0) {
+                                *(t++) = *f;
+                                continue;
+                        }
+                }
+
+                log_debug("Controller %s not available or redundant, removing from default controllers list.", *f);
+                free(*f);
+        }
+
+        *t = NULL;
+}
+
 int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) {
         CGroupBonding *b;
         char *p;