cgroup: change cg_unified() to possibly return errors again

We use our cgroup APIs in various contexts, including from our libraries
sd-login, sd-bus. As we don#t control those environments we can't rely
that the unified cgroup setup logic succeeds, and hence really shouldn't
assert on it.

This more or less reverts 415fc41cea.
This commit is contained in:
Lennart Poettering 2017-02-24 17:52:58 +01:00
parent fc9ae7178e
commit b4cccbc13a
12 changed files with 184 additions and 74 deletions

View File

@ -208,7 +208,13 @@ int cg_rmdir(const char *controller, const char *path) {
if (r < 0 && errno != ENOENT)
return -errno;
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
r = cg_hybrid_unified();
if (r < 0)
return r;
if (r == 0)
return 0;
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
r = cg_rmdir(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path);
if (r < 0)
log_warning_errno(r, "Failed to remove compat systemd cgroup %s: %m", path);
@ -549,7 +555,7 @@ static const char *controller_to_dirname(const char *controller) {
* hierarchies, if it is specified. */
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
if (cg_hybrid_unified())
if (cg_hybrid_unified() > 0)
controller = SYSTEMD_CGROUP_CONTROLLER_HYBRID;
else
controller = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
@ -636,7 +642,10 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (!cg_controller_is_valid(controller))
return -EINVAL;
if (cg_all_unified())
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
r = join_path_unified(path, suffix, fs);
else
r = join_path_legacy(controller, path, suffix, fs);
@ -648,6 +657,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
}
static int controller_is_accessible(const char *controller) {
int r;
assert(controller);
@ -659,7 +669,10 @@ static int controller_is_accessible(const char *controller) {
if (!cg_controller_is_valid(controller))
return -EINVAL;
if (cg_all_unified()) {
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
/* We don't support named hierarchies if we are using
* the unified hierarchy. */
@ -736,7 +749,10 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
return -errno;
}
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
q = cg_hybrid_unified();
if (q < 0)
return q;
if (q > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
q = cg_trim(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, delete_root);
if (q < 0)
log_warning_errno(q, "Failed to trim compat systemd cgroup %s: %m", path);
@ -765,7 +781,11 @@ int cg_create(const char *controller, const char *path) {
return -errno;
}
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
r = cg_hybrid_unified();
if (r < 0)
return r;
if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
r = cg_create(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path);
if (r < 0)
log_warning_errno(r, "Failed to create compat systemd cgroup %s: %m", path);
@ -812,7 +832,11 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
if (r < 0)
return r;
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
r = cg_hybrid_unified();
if (r < 0)
return r;
if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
r = cg_attach(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, pid);
if (r < 0)
log_warning_errno(r, "Failed to attach %d to compat systemd cgroup %s: %m", pid, path);
@ -871,7 +895,10 @@ int cg_set_group_access(
if (r < 0)
return r;
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
r = cg_hybrid_unified();
if (r < 0)
return r;
if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, mode, uid, gid);
if (r < 0)
log_warning_errno(r, "Failed to set group access on compat systemd cgroup %s: %m", path);
@ -906,14 +933,20 @@ int cg_set_task_access(
if (r < 0)
return r;
if (!cg_unified(controller)) {
r = cg_unified(controller);
if (r < 0)
return r;
if (r == 0) {
/* Compatibility, Always keep values for "tasks" in sync with
* "cgroup.procs" */
if (cg_get_path(controller, path, "tasks", &procs) >= 0)
(void) chmod_and_chown(procs, mode, uid, gid);
}
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && cg_hybrid_unified()) {
r = cg_hybrid_unified();
if (r < 0)
return r;
if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, mode, uid, gid);
if (r < 0)
log_warning_errno(r, "Failed to set task access on compat systemd cgroup %s: %m", path);
@ -964,7 +997,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
char line[LINE_MAX];
const char *fs, *controller_str;
size_t cs = 0;
bool unified;
int unified;
assert(path);
assert(pid >= 0);
@ -976,7 +1009,9 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
controller = SYSTEMD_CGROUP_CONTROLLER;
unified = cg_unified(controller);
if (!unified) {
if (unified < 0)
return unified;
if (unified == 0) {
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
else
@ -1048,7 +1083,10 @@ int cg_install_release_agent(const char *controller, const char *agent) {
assert(agent);
if (cg_unified(controller)) /* doesn't apply to unified hierarchy */
r = cg_unified(controller);
if (r < 0)
return r;
if (r > 0) /* doesn't apply to unified hierarchy */
return -EOPNOTSUPP;
r = cg_get_path(controller, NULL, "release_agent", &fs);
@ -1096,7 +1134,10 @@ int cg_uninstall_release_agent(const char *controller) {
_cleanup_free_ char *fs = NULL;
int r;
if (cg_unified(controller)) /* Doesn't apply to unified hierarchy */
r = cg_unified(controller);
if (r < 0)
return r;
if (r > 0) /* Doesn't apply to unified hierarchy */
return -EOPNOTSUPP;
r = cg_get_path(controller, NULL, "notify_on_release", &fs);
@ -1149,7 +1190,10 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
if (controller && (isempty(path) || path_equal(path, "/")))
return false;
if (cg_unified(controller)) {
r = cg_unified(controller);
if (r < 0)
return r;
if (r > 0) {
_cleanup_free_ char *t = NULL;
/* On the unified hierarchy we can check empty state
@ -2034,7 +2078,10 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path
return r;
/* If we are in the unified hierarchy, we are done now */
if (cg_all_unified())
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
return 0;
/* Otherwise, do the same in the other hierarchies */
@ -2061,7 +2108,10 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m
if (r < 0)
return r;
if (cg_all_unified())
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
return 0;
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@ -2102,7 +2152,7 @@ int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids,
int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
CGroupController c;
int r = 0;
int r = 0, q;
if (!path_equal(from, to)) {
r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE);
@ -2110,7 +2160,10 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
return r;
}
if (cg_all_unified())
q = cg_all_unified();
if (q < 0)
return q;
if (q > 0)
return r;
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@ -2134,13 +2187,16 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) {
CGroupController c;
int r;
int r, q;
r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
if (r < 0)
return r;
if (cg_all_unified())
q = cg_all_unified();
if (q < 0)
return q;
if (q > 0)
return r;
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@ -2163,7 +2219,10 @@ int cg_mask_supported(CGroupMask *ret) {
* includes controllers we can make sense of and that are
* actually accessible. */
if (cg_all_unified()) {
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
_cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL;
const char *c;
@ -2336,9 +2395,12 @@ static int cg_update_unified(void) {
return 0;
}
bool cg_unified(const char *controller) {
int cg_unified(const char *controller) {
int r;
assert(cg_update_unified() >= 0);
r = cg_update_unified();
if (r < 0)
return r;
if (unified_cache == CGROUP_UNIFIED_NONE)
return false;
@ -2349,14 +2411,16 @@ bool cg_unified(const char *controller) {
return streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER);
}
bool cg_all_unified(void) {
int cg_all_unified(void) {
return cg_unified(NULL);
}
bool cg_hybrid_unified(void) {
int cg_hybrid_unified(void) {
int r;
assert(cg_update_unified() >= 0);
r = cg_update_unified();
if (r < 0)
return r;
return unified_cache == CGROUP_UNIFIED_SYSTEMD && !unified_systemd_v232;
}
@ -2377,7 +2441,10 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) {
if (supported == 0)
return 0;
if (!cg_all_unified()) /* on the legacy hiearchy there's no joining of controllers defined */
r = cg_all_unified();
if (r < 0)
return r;
if (r == 0) /* on the legacy hiearchy there's no joining of controllers defined */
return 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs);
@ -2420,7 +2487,7 @@ bool cg_is_unified_wanted(void) {
/* If the hierarchy is already mounted, then follow whatever
* was chosen for it. */
if (cg_unified_flush() >= 0)
return (wanted = cg_all_unified());
return (wanted = unified_cache >= CGROUP_UNIFIED_ALL);
/* Otherwise, let's see what the kernel command line has to say.
* Since checking is expensive, cache a non-error result. */

View File

@ -240,9 +240,9 @@ int cg_kernel_controllers(Set *controllers);
bool cg_ns_supported(void);
bool cg_all_unified(void);
bool cg_hybrid_unified(void);
bool cg_unified(const char *controller);
int cg_all_unified(void);
int cg_hybrid_unified(void);
int cg_unified(const char *controller);
int cg_unified_flush(void);
bool cg_is_unified_wanted(void);

View File

@ -158,7 +158,7 @@ static int parse_argv(int argc, char *argv[]) {
static void show_cg_info(const char *controller, const char *path) {
if (!cg_all_unified() && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
if (cg_all_unified() == 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
printf("Controller %s; ", controller);
printf("Control group %s:\n", isempty(path) ? "/" : path);

View File

@ -133,12 +133,16 @@ static int process(
Group **ret) {
Group *g;
int r;
int r, all_unified;
assert(controller);
assert(path);
assert(a);
all_unified = cg_all_unified();
if (all_unified < 0)
return all_unified;
g = hashmap_get(a, path);
if (!g) {
g = hashmap_get(b, path);
@ -214,7 +218,7 @@ static int process(
uint64_t new_usage;
nsec_t timestamp;
if (cg_all_unified()) {
if (all_unified) {
const char *keys[] = { "usage_usec", NULL };
_cleanup_free_ char *val = NULL;
@ -274,10 +278,10 @@ static int process(
} else if (streq(controller, "memory")) {
_cleanup_free_ char *p = NULL, *v = NULL;
if (!cg_all_unified())
r = cg_get_path(controller, path, "memory.usage_in_bytes", &p);
else
if (all_unified)
r = cg_get_path(controller, path, "memory.current", &p);
else
r = cg_get_path(controller, path, "memory.usage_in_bytes", &p);
if (r < 0)
return r;
@ -294,14 +298,14 @@ static int process(
if (g->memory > 0)
g->memory_valid = true;
} else if ((streq(controller, "io") && cg_all_unified()) ||
(streq(controller, "blkio") && !cg_all_unified())) {
} else if ((streq(controller, "io") && all_unified) ||
(streq(controller, "blkio") && !all_unified)) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
uint64_t wr = 0, rd = 0;
nsec_t timestamp;
r = cg_get_path(controller, path, cg_all_unified() ? "io.stat" : "blkio.io_service_bytes", &p);
r = cg_get_path(controller, path, all_unified ? "io.stat" : "blkio.io_service_bytes", &p);
if (r < 0)
return r;
@ -324,7 +328,7 @@ static int process(
l += strcspn(l, WHITESPACE);
l += strspn(l, WHITESPACE);
if (cg_all_unified()) {
if (all_unified) {
while (!isempty(l)) {
if (sscanf(l, "rbytes=%" SCNu64, &k))
rd += k;

View File

@ -678,7 +678,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
bool has_weight = cgroup_context_has_cpu_weight(c);
bool has_shares = cgroup_context_has_cpu_shares(c);
if (cg_all_unified()) {
if (cg_all_unified() > 0) {
uint64_t weight;
if (has_weight)
@ -858,9 +858,8 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
}
if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
if (cg_all_unified()) {
uint64_t max;
uint64_t swap_max = CGROUP_LIMIT_MAX;
if (cg_all_unified() > 0) {
uint64_t max, swap_max = CGROUP_LIMIT_MAX;
if (cgroup_context_has_unified_memory_config(c)) {
max = c->memory_max;
@ -1033,7 +1032,7 @@ CGroupMask unit_get_own_mask(Unit *u) {
e = unit_get_exec_context(u);
if (!e ||
exec_context_maintains_privileges(e) ||
cg_all_unified())
cg_all_unified() > 0)
return _CGROUP_MASK_ALL;
}
@ -1260,7 +1259,10 @@ int unit_watch_cgroup(Unit *u) {
return 0;
/* Only applies to the unified hierarchy */
if (!cg_unified(SYSTEMD_CGROUP_CONTROLLER))
r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m");
if (r == 0)
return 0;
/* Don't watch the root slice, it's pointless. */
@ -1670,6 +1672,8 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
}
int unit_watch_all_pids(Unit *u) {
int r;
assert(u);
/* Adds all PIDs from our cgroup to the set of PIDs we
@ -1680,7 +1684,10 @@ int unit_watch_all_pids(Unit *u) {
if (!u->cgroup_path)
return -ENOENT;
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) /* On unified we can use proper notifications */
r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return r;
if (r > 0) /* On unified we can use proper notifications */
return 0;
return unit_watch_pids_in_path(u, u->cgroup_path);
@ -1753,7 +1760,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
int manager_setup_cgroup(Manager *m) {
_cleanup_free_ char *path = NULL;
CGroupController c;
int r;
int r, all_unified;
char *e;
assert(m);
@ -1794,18 +1801,26 @@ int manager_setup_cgroup(Manager *m) {
if (r < 0)
return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
if (cg_all_unified())
all_unified = cg_all_unified();
if (r < 0)
return log_error_errno(r, "Couldn't determine whether we are in all unified mode: %m");
if (r > 0)
log_debug("Unified cgroup hierarchy is located at %s.", path);
else if (cg_unified(SYSTEMD_CGROUP_CONTROLLER))
log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
else
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
else {
r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_error_errno(r, "Failed to determine whether systemd's own controller is in unified mode: %m");
if (r > 0)
log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
else
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
}
if (!m->test_run) {
const char *scope_path;
/* 3. Install agent */
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) {
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) {
/* In the unified hierarchy we can get
* cgroup empty notifications via inotify. */
@ -1865,7 +1880,7 @@ int manager_setup_cgroup(Manager *m) {
return log_error_errno(errno, "Failed to open pin file: %m");
/* 6. Always enable hierarchical support if it exists... */
if (!cg_all_unified())
if (!all_unified)
(void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
}
@ -1991,10 +2006,13 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
return -ENODATA;
if (!cg_all_unified())
r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
else
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
else
r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@ -2036,7 +2054,10 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
if (!u->cgroup_path)
return -ENODATA;
if (cg_all_unified()) {
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
const char *keys[] = { "usage_usec", NULL };
_cleanup_free_ char *val = NULL;
uint64_t us;

View File

@ -776,7 +776,10 @@ static int manager_setup_cgroups_agent(Manager *m) {
if (!MANAGER_IS_SYSTEM(m))
return 0;
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) /* We don't need this anymore on the unified hierarchy */
r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_error_errno(r, "Failed to determine whether unified cgroups hierarchy is used: %m");
if (r > 0) /* We don't need this anymore on the unified hierarchy */
return 0;
if (m->cgroups_agent_fd < 0) {

View File

@ -475,7 +475,7 @@ static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* If the PID set is empty now, then let's finish this off
(On unified we use proper notifications) */
if (!cg_unified(SYSTEMD_CGROUP_CONTROLLER) && set_isempty(u->pids))
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) == 0 && set_isempty(u->pids))
scope_notify_cgroup_empty_event(u);
}

View File

@ -2938,7 +2938,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* If the PID set is empty now, then let's finish this off
(On unified we use proper notifications) */
if (!cg_unified(SYSTEMD_CGROUP_CONTROLLER) && set_isempty(u->pids))
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) == 0 && set_isempty(u->pids))
service_notify_cgroup_empty_event(u);
}

View File

@ -3897,7 +3897,7 @@ int unit_kill_context(
* there we get proper events. Hence rely on
* them.*/
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) ||
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0 ||
(detect_container() == 0 && !unit_cgroup_delegate(u)))
wait_for_exit = true;

View File

@ -78,9 +78,12 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t arg_uid_shift)
char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1];
bool undo_mount = false;
const char *fn;
int r;
int r, unified_controller;
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD))
unified_controller = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (unified_controller < 0)
return log_error_errno(unified_controller, "Failed to determine whether the systemd hierarchy is unified: %m");
if ((unified_controller > 0) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD))
return 0;
/* When the host uses the legacy cgroup setup, but the
@ -96,7 +99,7 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t arg_uid_shift)
if (!mkdtemp(tree))
return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m");
if (cg_unified(SYSTEMD_CGROUP_CONTROLLER))
if (unified_controller > 0)
r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup",
MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr");
else
@ -150,7 +153,10 @@ int create_subcgroup(pid_t pid, CGroupUnified unified_requested) {
if (unified_requested == CGROUP_UNIFIED_NONE)
return 0;
if (!cg_unified(SYSTEMD_CGROUP_CONTROLLER))
r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_error_errno(r, "Failed to determine whether the systemd controller is unified: %m");
if (r == 0)
return 0;
r = cg_mask_supported(&supported);

View File

@ -991,7 +991,10 @@ static int mount_legacy_cgns_supported(
return r;
}
if (cg_all_unified())
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
goto skip_controllers;
controllers = set_new(&string_hash_ops);
@ -1094,7 +1097,10 @@ static int mount_legacy_cgns_unsupported(
return r;
}
if (cg_all_unified())
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
goto skip_controllers;
controllers = set_new(&string_hash_ops);

View File

@ -333,7 +333,10 @@ static int detect_unified_cgroup_hierarchy(const char *directory) {
}
/* Otherwise inherit the default from the host system */
if (cg_all_unified()) {
r = cg_all_unified();
if (r < 0)
return log_error_errno(r, "Failed to determine whether we are in all unified mode.");
if (r > 0) {
/* Unified cgroup hierarchy support was added in 230. Unfortunately the detection
* routine only detects 231, so we'll have a false negative here for 230. */
r = systemd_installation_has_version(directory, 230);
@ -343,7 +346,7 @@ static int detect_unified_cgroup_hierarchy(const char *directory) {
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL;
else
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE;
} else if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) {
} else if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) {
/* Mixed cgroup hierarchy support was added in 233 */
r = systemd_installation_has_version(directory, 233);
if (r < 0)