diff options
Diffstat (limited to 'src/shared/cgroup-setup.c')
-rw-r--r-- | src/shared/cgroup-setup.c | 122 |
1 files changed, 65 insertions, 57 deletions
diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index 934a16e..093b6d0 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -51,7 +51,7 @@ static int cg_any_controller_used_for_v1(void) { continue; const char *p = *line; - r = extract_many_words(&p, NULL, 0, &name, &hierarchy_id, &num, &enabled, NULL); + r = extract_many_words(&p, NULL, 0, &name, &hierarchy_id, &num, &enabled); if (r < 0) return log_debug_errno(r, "Error parsing /proc/cgroups line, ignoring: %m"); else if (r < 4) { @@ -81,9 +81,6 @@ static int cg_any_controller_used_for_v1(void) { bool cg_is_unified_wanted(void) { static thread_local int wanted = -1; - bool b; - const bool is_default = DEFAULT_HIERARCHY == CGROUP_UNIFIED_ALL; - _cleanup_free_ char *c = NULL; int r; /* If we have a cached value, return that. */ @@ -96,21 +93,20 @@ bool cg_is_unified_wanted(void) { return (wanted = r >= CGROUP_UNIFIED_ALL); /* If we were explicitly passed systemd.unified_cgroup_hierarchy, respect that. */ + bool b; r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", /* flags = */ 0, &b); if (r > 0) return (wanted = b); /* If we passed cgroup_no_v1=all with no other instructions, it seems highly unlikely that we want to * use hybrid or legacy hierarchy. */ + _cleanup_free_ char *c = NULL; r = proc_cmdline_get_key("cgroup_no_v1", 0, &c); if (r > 0 && streq_ptr(c, "all")) return (wanted = true); /* If any controller is in use as v1, don't use unified. */ - if (cg_any_controller_used_for_v1() > 0) - return (wanted = false); - - return (wanted = is_default); + return (wanted = (cg_any_controller_used_for_v1() <= 0)); } bool cg_is_legacy_wanted(void) { @@ -132,10 +128,6 @@ bool cg_is_legacy_wanted(void) { bool cg_is_hybrid_wanted(void) { static thread_local int wanted = -1; int r; - bool b; - const bool is_default = DEFAULT_HIERARCHY >= CGROUP_UNIFIED_SYSTEMD; - /* We default to true if the default is "hybrid", obviously, but also when the default is "unified", - * because if we get called, it means that unified hierarchy was not mounted. */ /* If we have a cached value, return that. */ if (wanted >= 0) @@ -146,12 +138,33 @@ bool cg_is_hybrid_wanted(void) { return (wanted = false); /* Otherwise, let's see what the kernel command line has to say. Since checking is expensive, cache - * a non-error result. */ + * a non-error result. + * The meaning of the kernel option is reversed wrt. to the return value of this function, hence the + * negation. */ + bool b; r = proc_cmdline_get_bool("systemd.legacy_systemd_cgroup_controller", /* flags = */ 0, &b); + if (r > 0) + return (wanted = !b); - /* The meaning of the kernel option is reversed wrt. to the return value of this function, hence the - * negation. */ - return (wanted = r > 0 ? !b : is_default); + /* The default hierarchy is "unified". But if this is reached, it means that unified hierarchy was + * not mounted, so return true too. */ + return (wanted = true); +} + +bool cg_is_legacy_force_enabled(void) { + bool force; + + if (!cg_is_legacy_wanted()) + return false; + + /* If in container, we have to follow host's cgroup hierarchy. */ + if (detect_container() > 0) + return true; + + if (proc_cmdline_get_bool("SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE", /* flags = */ 0, &force) < 0) + return false; + + return force; } int cg_weight_parse(const char *s, uint64_t *ret) { @@ -371,6 +384,20 @@ int cg_attach(const char *controller, const char *path, pid_t pid) { return 0; } +int cg_fd_attach(int fd, pid_t pid) { + char c[DECIMAL_STR_MAX(pid_t) + 2]; + + assert(fd >= 0); + assert(pid >= 0); + + if (pid == 0) + pid = getpid_cached(); + + xsprintf(c, PID_FMT "\n", pid); + + return write_string_file_at(fd, "cgroup.procs", c, WRITE_STRING_FILE_DISABLE_BUFFER); +} + int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { int r; @@ -571,75 +598,56 @@ int cg_migrate( bool done = false; _cleanup_set_free_ Set *s = NULL; int r, ret = 0; - pid_t my_pid; assert(cfrom); assert(pfrom); assert(cto); assert(pto); - s = set_new(NULL); - if (!s) - return -ENOMEM; - - my_pid = getpid_cached(); - do { _cleanup_fclose_ FILE *f = NULL; - pid_t pid = 0; + pid_t pid; + done = true; r = cg_enumerate_processes(cfrom, pfrom, &f); - if (r < 0) { - if (ret >= 0 && r != -ENOENT) - return r; - - return ret; - } + if (r < 0) + return RET_GATHER(ret, r); - while ((r = cg_read_pid(f, &pid)) > 0) { + while ((r = cg_read_pid(f, &pid, flags)) > 0) { + /* Throw an error if unmappable PIDs are in output, we can't migrate those. */ + if (pid == 0) + return -EREMOTE; - /* This might do weird stuff if we aren't a - * single-threaded program. However, we - * luckily know we are not */ - if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) + /* This might do weird stuff if we aren't a single-threaded program. However, we + * luckily know we are. */ + if (FLAGS_SET(flags, CGROUP_IGNORE_SELF) && pid == getpid_cached()) continue; - if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) + if (set_contains(s, PID_TO_PTR(pid))) continue; - /* Ignore kernel threads. Since they can only - * exist in the root cgroup, we only check for - * them there. */ - if (cfrom && - empty_or_root(pfrom) && + /* Ignore kernel threads. Since they can only exist in the root cgroup, we only + * check for them there. */ + if (cfrom && empty_or_root(pfrom) && pid_is_kernel_thread(pid) > 0) continue; r = cg_attach(cto, pto, pid); if (r < 0) { - if (ret >= 0 && r != -ESRCH) - ret = r; + if (r != -ESRCH) + RET_GATHER(ret, r); } else if (ret == 0) ret = 1; done = false; - r = set_put(s, PID_TO_PTR(pid)); - if (r < 0) { - if (ret >= 0) - return r; - - return ret; - } - } - - if (r < 0) { - if (ret >= 0) - return r; - - return ret; + r = set_ensure_put(&s, /* hash_ops = */ NULL, PID_TO_PTR(pid)); + if (r < 0) + return RET_GATHER(ret, r); } + if (r < 0) + return RET_GATHER(ret, r); } while (!done); return ret; |