diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-02-17 02:06:32 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-02-17 15:49:21 +0100 |
commit | 03b90d4bade317c601bc22ccc700396ca6ba5a8e (patch) | |
tree | 558bcb521e25a5b26554be828d9c0be29a06ae41 /src/core | |
parent | 6d2357247b198314d972932415d65a42f83a9b6e (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.c | 60 |
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; } |