From: Lennart Poettering Date: Mon, 17 Feb 2014 01:06:32 +0000 (+0100) Subject: core: find the closest parent slice that has a specfic cgroup controller enabled... X-Git-Tag: v209~99 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=03b90d4bade317c601bc22ccc700396ca6ba5a8e;ds=sidebyside core: find the closest parent slice that has a specfic cgroup controller enabled when enabling/disabling cgroup controllers for units --- diff --git a/src/core/cgroup.c b/src/core/cgroup.c index f0420ebc0..24d6ff648 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; } diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 9692a07f5..1aa81c2cd 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -1668,7 +1668,7 @@ int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, return r; } -int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) { +int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { CGroupControllerMask bit = 1; const char *n; int r; @@ -1680,8 +1680,17 @@ int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, cons } NULSTR_FOREACH(n, mask_names) { - if (supported & bit) - cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false); + if (supported & bit) { + const char *p = NULL; + + if (to_callback) + p = to_callback(bit, userdata); + + if (!p) + p = to; + + cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, p, false, false); + } bit <<= 1; } diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index 743d902e2..aca4e44c4 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -122,10 +122,12 @@ bool cg_controller_is_valid(const char *p, bool allow_named); int cg_slice_to_path(const char *unit, char **ret); +typedef const char* (*cg_migrate_callback_t)(CGroupControllerMask mask, void *userdata); + 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_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t callback, void *userdata); int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root); CGroupControllerMask cg_mask_supported(void);