summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/cgroup.c8
-rw-r--r--src/core/execute.c4
-rw-r--r--src/core/mount.c2
-rw-r--r--src/core/scope.c2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/socket.c2
-rw-r--r--src/core/swap.c2
-rw-r--r--src/shared/cgroup-util.c154
-rw-r--r--src/shared/cgroup-util.h12
9 files changed, 118 insertions, 70 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index e66b8f4851..8bf4d896de 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -397,13 +397,13 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
}
/* First, create our own group */
- r = cg_create_with_mask(mask, path);
+ r = cg_create_everywhere(u->manager->cgroup_supported, mask, path);
if (r < 0)
log_error("Failed to create cgroup %s: %s", path, strerror(-r));
/* Then, possibly move things over */
- if (u->cgroup_path && !streq(path, u->cgroup_path)) {
- r = cg_migrate_with_mask(mask, u->cgroup_path, path);
+ if (u->cgroup_path) {
+ r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path);
if (r < 0)
log_error("Failed to migrate cgroup %s: %s", path, strerror(-r));
}
@@ -537,7 +537,7 @@ void unit_destroy_cgroup(Unit *u) {
if (!u->cgroup_path)
return;
- r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
+ r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
if (r < 0)
log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
diff --git a/src/core/execute.c b/src/core/execute.c
index f840642d14..0bfa41836a 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1017,7 +1017,7 @@ int exec_spawn(ExecCommand *command,
bool apply_chroot,
bool apply_tty_stdin,
bool confirm_spawn,
- CGroupControllerMask cgroup_mask,
+ CGroupControllerMask cgroup_supported,
const char *cgroup_path,
const char *unit_id,
int idle_pipe[4],
@@ -1198,7 +1198,7 @@ int exec_spawn(ExecCommand *command,
}
if (cgroup_path) {
- err = cg_attach_with_mask(cgroup_mask, cgroup_path, 0);
+ err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
if (err < 0) {
r = EXIT_CGROUP;
goto fail_child;
diff --git a/src/core/mount.c b/src/core/mount.c
index 5c18d4e463..78c5c1e6d6 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -888,7 +888,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
true,
true,
UNIT(m)->manager->confirm_spawn,
- UNIT(m)->cgroup_mask,
+ UNIT(m)->manager->cgroup_supported,
UNIT(m)->cgroup_path,
UNIT(m)->id,
NULL,
diff --git a/src/core/scope.c b/src/core/scope.c
index b94f3ff7ba..50e5dbacb4 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -257,7 +257,7 @@ static int scope_start(Unit *u) {
return r;
}
- r = cg_attach_many_with_mask(u->cgroup_mask, u->cgroup_path, s->pids);
+ r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
if (r < 0)
return r;
diff --git a/src/core/service.c b/src/core/service.c
index cc61b546fc..24b7bef287 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1820,7 +1820,7 @@ static int service_spawn(
apply_chroot,
apply_tty_stdin,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_mask,
+ UNIT(s)->manager->cgroup_supported,
path,
UNIT(s)->id,
s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
diff --git a/src/core/socket.c b/src/core/socket.c
index 46a73e0108..190b36c3ca 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1239,7 +1239,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
true,
true,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_mask,
+ UNIT(s)->manager->cgroup_supported,
UNIT(s)->cgroup_path,
UNIT(s)->id,
NULL,
diff --git a/src/core/swap.c b/src/core/swap.c
index 82bfad187e..dc6731ab30 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -625,7 +625,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
true,
true,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_mask,
+ UNIT(s)->manager->cgroup_supported,
UNIT(s)->cgroup_path,
UNIT(s)->id,
NULL,
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 0bffebdac8..2e630d4708 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -435,6 +435,46 @@ int cg_migrate_recursive(
return ret;
}
+int cg_migrate_recursive_fallback(
+ const char *cfrom,
+ const char *pfrom,
+ const char *cto,
+ const char *pto,
+ bool ignore_self,
+ bool rem) {
+
+ int r;
+
+ assert(cfrom);
+ assert(pfrom);
+ assert(cto);
+ assert(pto);
+
+ r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
+ if (r < 0) {
+ char prefix[strlen(pto) + 1];
+
+ /* This didn't work? Then let's try all prefixes of the destination */
+
+ strcpy(prefix, pto);
+ for (;;) {
+ char *slash;
+
+ slash = strrchr(prefix, '/');
+ if (!slash)
+ break;
+
+ *slash = 0;
+
+ r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
+ if (r >= 0)
+ break;
+ }
+ }
+
+ return r;
+}
+
static const char *normalize_controller(const char *controller) {
assert(controller);
@@ -607,6 +647,39 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
return write_string_file(fs, c);
}
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
+ int r;
+
+ assert(controller);
+ assert(path);
+ assert(pid >= 0);
+
+ r = cg_attach(controller, path, pid);
+ if (r < 0) {
+ char prefix[strlen(path) + 1];
+
+ /* This didn't work? Then let's try all prefixes of
+ * the destination */
+
+ strcpy(prefix, path);
+ for (;;) {
+ char *slash;
+
+ slash = strrchr(prefix, '/');
+ if (!slash)
+ break;
+
+ *slash = 0;
+
+ r = cg_attach(controller, prefix, pid);
+ if (r >= 0)
+ break;
+ }
+ }
+
+ return r;
+}
+
int cg_set_group_access(
const char *controller,
const char *path,
@@ -1607,7 +1680,7 @@ static const char mask_names[] =
"memory\0"
"devices\0";
-int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
CGroupControllerMask bit = 1;
const char *n;
int r;
@@ -1623,102 +1696,75 @@ int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
/* Then, do the same in the other hierarchies */
NULSTR_FOREACH(n, mask_names) {
- if (bit & mask)
+ if (mask & bit)
cg_create(n, path);
- else
+ else if (supported & bit)
cg_trim(n, path, true);
bit <<= 1;
}
- return r;
+ return 0;
}
-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) {
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
CGroupControllerMask bit = 1;
const char *n;
int r;
r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
+ if (r < 0)
+ return r;
NULSTR_FOREACH(n, mask_names) {
- if (bit & mask)
- cg_attach(n, path, pid);
- else {
- char prefix[strlen(path) + 1], *slash;
-
- /* OK, this one is a bit harder... Now we need
- * to add to the closest parent cgroup we
- * can find */
- strcpy(prefix, path);
- while ((slash = strrchr(prefix, '/'))) {
- int q;
- *slash = 0;
-
- q = cg_attach(n, prefix, pid);
- if (q >= 0)
- break;
- }
- }
+ if (supported & bit)
+ cg_attach_fallback(n, path, pid);
bit <<= 1;
}
- return r;
+ return 0;
}
-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids) {
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
Iterator i;
void *pidp;
int r = 0;
SET_FOREACH(pidp, pids, i) {
pid_t pid = PTR_TO_LONG(pidp);
- int k;
+ int q;
- k = cg_attach_with_mask(mask, path, pid);
- if (k < 0)
- r = k;
+ q = cg_attach_everywhere(supported, path, pid);
+ if (q < 0)
+ r = q;
}
return r;
}
-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) {
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
CGroupControllerMask bit = 1;
const char *n;
int r;
- if (path_equal(from, to))
- return 0;
-
- r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+ if (!path_equal(from, to)) {
+ r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+ if (r < 0)
+ return r;
+ }
NULSTR_FOREACH(n, mask_names) {
- if (bit & mask)
- cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
- else {
- char prefix[strlen(to) + 1], *slash;
-
- strcpy(prefix, to);
- while ((slash = strrchr(prefix, '/'))) {
- int q;
-
- *slash = 0;
-
- q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false);
- if (q >= 0)
- break;
- }
- }
+ if (supported & bit)
+ cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
bit <<= 1;
}
- return r;
+ return 0;
}
-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) {
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
CGroupControllerMask bit = 1;
const char *n;
int r;
@@ -1728,13 +1774,13 @@ int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_r
return r;
NULSTR_FOREACH(n, mask_names) {
- if (bit & mask)
+ if (supported & bit)
cg_trim(n, path, delete_root);
bit <<= 1;
}
- return r;
+ return 0;
}
CGroupControllerMask cg_mask_supported(void) {
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
index 0fc93c12c8..0963450b08 100644
--- a/src/shared/cgroup-util.h
+++ b/src/shared/cgroup-util.h
@@ -64,6 +64,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
+int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem);
int cg_split_spec(const char *spec, char **controller, char **path);
int cg_join_spec(const char *controller, const char *path, char **spec);
@@ -81,6 +82,7 @@ int cg_delete(const char *controller, const char *path);
int cg_create(const char *controller, const char *path);
int cg_attach(const char *controller, const char *path, pid_t pid);
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
@@ -126,10 +128,10 @@ bool cg_controller_is_valid(const char *p, bool allow_named);
int cg_slice_to_path(const char *unit, char **ret);
-int cg_create_with_mask(CGroupControllerMask mask, const char *path);
-int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid);
-int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids);
-int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to);
-int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root);
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path);
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid);
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids);
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to);
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root);
CGroupControllerMask cg_mask_supported(void);