#include "log.h"
#include "strv.h"
#include "path-util.h"
+#include "special.h"
int cgroup_bonding_realize(CGroupBonding *b) {
int r;
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;
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;
assert(pid >= 0);
if (cgroup_suffix) {
- p = join(b->path, "/", cgroup_suffix, NULL);
+ p = strjoin(b->path, "/", cgroup_suffix, NULL);
if (!p)
return -ENOMEM;
path = b->path;
r = cg_create_and_attach(b->controller, path, pid);
- free(p);
-
if (r < 0)
return r;
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);
return 0;
if (cgroup_suffix) {
- p = join(b->path, "/", cgroup_suffix, NULL);
+ p = strjoin(b->path, "/", cgroup_suffix, NULL);
if (!p)
return -ENOMEM;
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 */
}
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);
}
/* 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 */
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) {
return 1;
}
- p = strdup(cgroup);
+ p = strdupa(cgroup);
if (!p)
return -ENOMEM;
char *e;
e = strrchr(p, '/');
- if (!e || e == p) {
- free(p);
+ if (e == p || !e) {
*bonding = NULL;
return 0;
}
b = hashmap_get(m->cgroup_bondings, p);
if (b) {
- free(p);
*bonding = b;
return 1;
}
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);
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))