summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-17 02:06:32 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-17 15:49:21 +0100
commit03b90d4bade317c601bc22ccc700396ca6ba5a8e (patch)
tree558bcb521e25a5b26554be828d9c0be29a06ae41 /src/core
parent6d2357247b198314d972932415d65a42f83a9b6e (diff)
core: find the closest parent slice that has a specfic cgroup controller enabled when enabling/disabling cgroup controllers for units
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index f0420ebc09..24d6ff6482 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -448,9 +448,26 @@ void unit_update_cgroup_members_masks(Unit *u) {
}
}
+static const char *migrate_callback(CGroupControllerMask mask, void *userdata) {
+ Unit *u = userdata;
+
+ assert(mask != 0);
+ assert(u);
+
+ while (u) {
+ if (u->cgroup_path &&
+ u->cgroup_realized &&
+ (u->cgroup_realized_mask & mask) == mask)
+ return u->cgroup_path;
+
+ u = UNIT_DEREF(u->slice);
+ }
+
+ return NULL;
+}
+
static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
- _cleanup_free_ char *path;
- bool was_in_hash = false;
+ _cleanup_free_ char *path = NULL;
int r;
assert(u);
@@ -460,38 +477,31 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
return log_oom();
r = hashmap_put(u->manager->cgroup_unit, path, u);
- if (r == 0)
- was_in_hash = true;
- else if (r < 0) {
- log_error(r == -EEXIST ?
- "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s",
- path, strerror(-r));
+ if (r < 0) {
+ log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r));
return r;
}
-
- /* First, create our own group */
- 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) {
- r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path);
- if (r < 0)
- log_error("Failed to migrate cgroup from %s to %s: %s",
- u->cgroup_path, path, strerror(-r));
- }
-
- if (!was_in_hash) {
- /* Remember the new data */
- free(u->cgroup_path);
+ if (r > 0) {
u->cgroup_path = path;
path = NULL;
}
+ /* First, create our own group */
+ r = cg_create_everywhere(u->manager->cgroup_supported, mask, u->cgroup_path);
+ if (r < 0) {
+ log_error("Failed to create cgroup %s: %s", u->cgroup_path, strerror(-r));
+ return r;
+ }
+
+ /* Keep track that this is now realized */
u->cgroup_realized = true;
u->cgroup_realized_mask = mask;
+ /* Then, possibly move things over */
+ r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
+ if (r < 0)
+ log_warning("Failed to migrate cgroup from to %s: %s", u->cgroup_path, strerror(-r));
+
return 0;
}