X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Fcore%2Fcgroup.c;h=5065329739d96fae779c0577ced5f145b075c8bd;hb=9444b1f20e311f073864d81e913bd4f32fe95cfd;hp=e07d1ed3c96d2a803c0d49d6fa4147251e936a10;hpb=b59e246565337d6c6967059dd15a52a15277433e;p=elogind.git diff --git a/src/core/cgroup.c b/src/core/cgroup.c index e07d1ed3c..506532973 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -31,6 +31,8 @@ #include "cgroup-util.h" #include "log.h" #include "strv.h" +#include "path-util.h" +#include "special.h" int cgroup_bonding_realize(CGroupBonding *b) { int r; @@ -39,7 +41,7 @@ int cgroup_bonding_realize(CGroupBonding *b) { assert(b->path); assert(b->controller); - r = cg_create(b->controller, b->path); + r = cg_create(b->controller, b->path, NULL); if (r < 0) { log_warning("Failed to create cgroup %s:%s: %s", b->controller, b->path, strerror(-r)); return r; @@ -109,9 +111,8 @@ 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, const char *cgroup_suffix) { - char *p = NULL; + _cleanup_free_ char *p = NULL; const char *path; int r; @@ -119,7 +120,7 @@ int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffi assert(pid >= 0); if (cgroup_suffix) { - p = join(b->path, "/", cgroup_suffix, NULL); + p = strjoin(b->path, "/", cgroup_suffix, NULL); if (!p) return -ENOMEM; @@ -128,8 +129,6 @@ int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffi path = b->path; r = cg_create_and_attach(b->controller, path, pid); - free(p); - if (r < 0) return r; @@ -150,6 +149,34 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgr return 0; } +int cgroup_bonding_migrate(CGroupBonding *b, CGroupBonding *list) { + CGroupBonding *q; + int ret = 0; + + LIST_FOREACH(by_unit, q, list) { + int r; + + if (q == b) + continue; + + if (!q->ours) + continue; + + r = cg_migrate_recursive(q->controller, q->path, b->controller, b->path, true, false); + if (r < 0 && ret == 0) + ret = r; + } + + return ret; +} + +int cgroup_bonding_migrate_to(CGroupBonding *b, const char *target, bool rem) { + assert(b); + assert(target); + + return cg_migrate_recursive(b->controller, b->path, b->controller, target, true, rem); +} + int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) { assert(b); @@ -194,7 +221,7 @@ 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, const char *cgroup_suffix) { +int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) { char *p = NULL; const char *path; int r; @@ -207,7 +234,7 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const c return 0; if (cgroup_suffix) { - p = join(b->path, "/", cgroup_suffix, NULL); + p = strjoin(b->path, "/", cgroup_suffix, NULL); if (!p) return -ENOMEM; @@ -215,13 +242,13 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const c } else path = b->path; - r = cg_kill_recursive(b->controller, path, sig, sigcont, true, false, s); + r = cg_kill_recursive(b->controller, path, sig, sigcont, true, rem, s); free(p); return r; } -int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s, const char *cgroup_suffix) { +int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) { CGroupBonding *b; Set *allocated_set = NULL; int ret = -EAGAIN, r; @@ -234,7 +261,7 @@ int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s return -ENOMEM; LIST_FOREACH(by_unit, b, first) { - r = cgroup_bonding_kill(b, sig, sigcont, s, cgroup_suffix); + r = cgroup_bonding_kill(b, sig, sigcont, rem, s, cgroup_suffix); if (r < 0) { if (r == -EAGAIN || r == -ESRCH) continue; @@ -278,7 +305,8 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) { LIST_FOREACH(by_unit, b, first) { int r; - if ((r = cgroup_bonding_is_empty(b)) < 0) { + r = cgroup_bonding_is_empty(b); + if (r < 0) { /* If this returned -EAGAIN, then we don't know if the * group is empty, so let's see if another group can * tell us */ @@ -293,9 +321,9 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) { } int manager_setup_cgroup(Manager *m) { - char *current = NULL, *path = NULL; + _cleanup_free_ char *path = NULL; int r; - char suffix[32]; + char *e, *a; assert(m); @@ -306,58 +334,54 @@ int manager_setup_cgroup(Manager *m) { } /* 1. Determine hierarchy */ - r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, ¤t); + free(m->cgroup_root); + m->cgroup_root = NULL; + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root); if (r < 0) { log_error("Cannot determine cgroup we are running in: %s", strerror(-r)); - goto finish; + return r; } - if (m->running_as == MANAGER_SYSTEM) - strcpy(suffix, "/system"); - else { - snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid()); - char_array_0(suffix); + /* Already in /system.slice? If so, let's cut this off again */ + if (m->running_as == SYSTEMD_SYSTEM) { + e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); + if (e) + *e = 0; } - free(m->cgroup_hierarchy); - if (endswith(current, suffix)) { - /* We probably got reexecuted and can continue to use our root cgroup */ - m->cgroup_hierarchy = current; - current = NULL; - - } else { - /* We need a new root cgroup */ - m->cgroup_hierarchy = NULL; - if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) { - log_error("Out of memory"); - r = -ENOMEM; - goto finish; - } - } + /* And make sure to store away the root value without trailing + * slash, even for the root dir, so that we can easily prepend + * it everywhere. */ + if (streq(m->cgroup_root, "/")) + m->cgroup_root[0] = 0; /* 2. Show data */ - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path); + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path); if (r < 0) { log_error("Cannot find cgroup mount point: %s", strerror(-r)); - goto finish; + return r; } log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path); /* 3. Install agent */ - 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."); - else - log_debug("Release agent already installed."); - - /* 4. Realize the group */ - r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0); + if (m->running_as == SYSTEMD_SYSTEM) { + 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."); + else + log_debug("Release agent already installed."); + } + + /* 4. Realize the system slice and put us in there */ + a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0); if (r < 0) { log_error("Failed to create root cgroup hierarchy: %s", strerror(-r)); - goto finish; + return r; } /* 5. And pin it, so that it cannot be unmounted */ @@ -367,34 +391,30 @@ int manager_setup_cgroup(Manager *m) { 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; + return -errno; } - log_debug("Created root group."); - + /* 6. Remove non-existing controllers from the default controllers list */ cg_shorten_controllers(m->default_controllers); -finish: - free(current); - free(path); - - return r; + return 0; } void manager_shutdown_cgroup(Manager *m, bool delete) { assert(m); - if (delete && m->cgroup_hierarchy) - cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy); + /* We can't really delete the group, since we are in it. But + * let's trim it. */ + if (delete && m->cgroup_root) + cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false); if (m->pin_cgroupfs_fd >= 0) { close_nointr_nofail(m->pin_cgroupfs_fd); m->pin_cgroupfs_fd = -1; } - free(m->cgroup_hierarchy); - m->cgroup_hierarchy = NULL; + free(m->cgroup_root); + m->cgroup_root = NULL; } int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) { @@ -411,7 +431,7 @@ int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) return 1; } - p = strdup(cgroup); + p = strdupa(cgroup); if (!p) return -ENOMEM; @@ -419,8 +439,7 @@ int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) char *e; e = strrchr(p, '/'); - if (!e || e == p) { - free(p); + if (e == p || !e) { *bonding = NULL; return 0; } @@ -429,7 +448,6 @@ int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) b = hashmap_get(m->cgroup_bondings, p); if (b) { - free(p); *bonding = b; return 1; } @@ -484,7 +502,7 @@ Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) { if (pid <= 1) return NULL; - if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0) + if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0) return NULL; l = hashmap_get(m->cgroup_bondings, group); @@ -520,7 +538,8 @@ Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) { CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) { CGroupBonding *b; - assert(controller); + if (!controller) + controller = SYSTEMD_CGROUP_CONTROLLER; LIST_FOREACH(by_unit, b, first) if (streq(b->controller, controller))