diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 83678e6e03..35b862d5c2 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -605,7 +605,6 @@ static const char *migrate_callback(CGroupControllerMask mask, void *userdata) { } static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { - _cleanup_free_ char *path = NULL; CGroupContext *c; int r; @@ -615,18 +614,22 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { if (!c) return 0; - path = unit_default_cgroup_path(u); - if (!path) - return log_oom(); + if (!u->cgroup_path) { + _cleanup_free_ char *path = NULL; - r = hashmap_put(u->manager->cgroup_unit, path, u); - if (r < 0) { - log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r)); - return r; - } - if (r > 0) { - u->cgroup_path = path; - path = NULL; + path = unit_default_cgroup_path(u); + if (!path) + return log_oom(); + + r = hashmap_put(u->manager->cgroup_unit, path, u); + if (r < 0) { + log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r)); + return r; + } + if (r > 0) { + u->cgroup_path = path; + path = NULL; + } } /* First, create our own group */ @@ -651,6 +654,21 @@ static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) { return 0; } +int unit_attach_pids_to_cgroup(Unit *u) { + int r; + assert(u); + + r = unit_realize_cgroup(u); + if (r < 0) + return r; + + r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->pids, migrate_callback, u); + if (r < 0) + return r; + + return 0; +} + static bool unit_has_mask_realized(Unit *u, CGroupControllerMask mask) { assert(u); diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 16d661357b..7150e5e7e2 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -110,6 +110,7 @@ CGroupControllerMask unit_get_target_mask(Unit *u); void unit_update_cgroup_members_masks(Unit *u); int unit_realize_cgroup(Unit *u); void unit_destroy_cgroup_if_empty(Unit *u); +int unit_attach_pids_to_cgroup(Unit *u); int manager_setup_cgroup(Manager *m); void manager_shutdown_cgroup(Manager *m, bool delete); diff --git a/src/core/execute.c b/src/core/execute.c index 955090c446..5e4135e030 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1351,7 +1351,7 @@ static int exec_child(ExecCommand *command, } if (params->cgroup_path) { - err = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0); + err = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL); if (err < 0) { *error = EXIT_CGROUP; return err; diff --git a/src/core/scope.c b/src/core/scope.c index f0efec0516..e0da6e4db7 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -288,11 +288,7 @@ static int scope_start(Unit *u) { if (!u->transient && UNIT(s)->manager->n_reloading <= 0) return -ENOENT; - r = unit_realize_cgroup(u); - if (r < 0) - return log_error_errno(r, "Failed to realize cgroup: %m"); - - r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids); + r = unit_attach_pids_to_cgroup(u); if (r < 0) return r; diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index e595d895d2..1bcba01887 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -1624,7 +1624,7 @@ int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask ma return 0; } -int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) { +int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) { CGroupControllerMask bit = 1; const char *n; int r; @@ -1634,8 +1634,18 @@ int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t return r; NULSTR_FOREACH(n, mask_names) { - if (supported & bit) + + if (supported & bit) { + const char *p = NULL; + + if (path_callback) + p = path_callback(bit, userdata); + + if (!p) + p = path; + cg_attach_fallback(n, path, pid); + } bit <<= 1; } @@ -1643,7 +1653,7 @@ int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t return 0; } -int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) { +int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) { Iterator i; void *pidp; int r = 0; @@ -1652,7 +1662,7 @@ int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, pid_t pid = PTR_TO_LONG(pidp); int q; - q = cg_attach_everywhere(supported, path, pid); + q = cg_attach_everywhere(supported, path, pid, path_callback, userdata); if (q < 0) r = q; } diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index a65f515b45..5e1e445c33 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -126,8 +126,8 @@ 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_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid, cg_migrate_callback_t callback, void *userdata); +int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids, cg_migrate_callback_t callback, void *userdata); 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);