Drop remaining CGroup v1 specific code (#38969)

This commit is contained in:
Yu Watanabe
2025-11-17 23:48:29 +09:00
committed by GitHub
47 changed files with 335 additions and 775 deletions
+1 -3
View File
@@ -59,9 +59,7 @@ _systemd_cgtop() {
fi
COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
if [ -d /sys/fs/cgroup/systemd/ ]; then
COMPREPLY+=( $(cd /sys/fs/cgroup/systemd/ && compgen -o nospace -o dirnames "$cur") )
elif [ -d /sys/fs/cgroup/ ]; then
if [ -d /sys/fs/cgroup/ ]; then
COMPREPLY+=( $(cd /sys/fs/cgroup/ && compgen -o nospace -o dirnames "$cur") )
fi
}
+1 -2
View File
@@ -28,8 +28,7 @@ case "$service" in
'(- *)--version[Show package version]' \
'--no-pager[Do not pipe output into a pager]' \
'(-a --all)'{-a,--all}'[Show all groups, including empty]' \
'-k[Include kernel threads in output]' \
':cgroups:(cpuset cpu cpuacct memory devices freezer blkio)'
'-k[Include kernel threads in output]'
;;
systemd-cgtop)
_arguments \
+115 -451
View File
@@ -50,11 +50,24 @@ typedef union {
/* The .f_handle field is not aligned to 64bit on some archs, hence read it via an unaligned accessor */
#define CG_FILE_HANDLE_CGROUPID(fh) unaligned_read_ne64(fh.file_handle.f_handle)
int cg_path_open(const char *controller, const char *path) {
int cg_is_available(void) {
struct statfs fs;
if (statfs("/sys/fs/cgroup/", &fs) < 0) {
if (errno == ENOENT) /* sysfs not mounted? */
return false;
return log_debug_errno(errno, "Failed to statfs /sys/fs/cgroup/: %m");
}
return is_fs_type(&fs, CGROUP2_SUPER_MAGIC);
}
int cg_path_open(const char *path) {
_cleanup_free_ char *fs = NULL;
int r;
r = cg_get_path(controller, path, /* suffix=*/ NULL, &fs);
r = cg_get_path(path, /* suffix= */ NULL, &fs);
if (r < 0)
return r;
@@ -117,14 +130,14 @@ int cg_get_cgroupid_at(int dfd, const char *path, uint64_t *ret) {
return 0;
}
int cg_enumerate_processes(const char *controller, const char *path, FILE **ret) {
int cg_enumerate_processes(const char *path, FILE **ret) {
_cleanup_free_ char *fs = NULL;
FILE *f;
int r;
assert(ret);
r = cg_get_path(controller, path, "cgroup.procs", &fs);
r = cg_get_path(path, "cgroup.procs", &fs);
if (r < 0)
return r;
@@ -209,7 +222,7 @@ bool cg_kill_supported(void) {
if (supported >= 0)
return supported;
if (cg_all_unified() <= 0)
if (cg_is_available() <= 0)
return (supported = false);
if (access("/sys/fs/cgroup/init.scope/cgroup.kill", F_OK) >= 0)
@@ -219,7 +232,7 @@ bool cg_kill_supported(void) {
return (supported = false);
}
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **ret) {
int cg_enumerate_subgroups(const char *path, DIR **ret) {
_cleanup_free_ char *fs = NULL;
DIR *d;
int r;
@@ -228,7 +241,7 @@ int cg_enumerate_subgroups(const char *controller, const char *path, DIR **ret)
/* This is not recursive! */
r = cg_get_path(controller, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -295,7 +308,7 @@ int cg_kill(
done = true;
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
r = cg_enumerate_processes(path, &f);
if (r == -ENOENT)
break;
if (r < 0)
@@ -386,7 +399,7 @@ int cg_kill_recursive(
ret = cg_kill(path, sig, flags, killed_pids, log_kill, userdata);
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
r = cg_enumerate_subgroups(path, &d);
if (r < 0) {
if (r != -ENOENT)
RET_GATHER(ret, log_debug_errno(r, "Failed to enumerate cgroup '%s' subgroups: %m", path));
@@ -431,7 +444,7 @@ int cg_kill_kernel_sigkill(const char *path) {
if (!cg_kill_supported())
return -EOPNOTSUPP;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.kill", &killfile);
r = cg_get_path(path, "cgroup.kill", &killfile);
if (r < 0)
return r;
@@ -442,153 +455,22 @@ int cg_kill_kernel_sigkill(const char *path) {
return 0;
}
static const char *controller_to_dirname(const char *controller) {
assert(controller);
/* Converts a controller name to the directory name below /sys/fs/cgroup/ we want to mount it
* to. Effectively, this just cuts off the name= prefixed used for named hierarchies, if it is
* specified. */
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
if (cg_hybrid_unified() > 0)
controller = SYSTEMD_CGROUP_CONTROLLER_HYBRID;
else
controller = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
}
return startswith(controller, "name=") ?: controller;
}
static int join_path_legacy(const char *controller, const char *path, const char *suffix, char **ret) {
const char *dn;
char *t = NULL;
assert(ret);
assert(controller);
dn = controller_to_dirname(controller);
if (isempty(path) && isempty(suffix))
t = path_join("/sys/fs/cgroup", dn);
else if (isempty(path))
t = path_join("/sys/fs/cgroup", dn, suffix);
else if (isempty(suffix))
t = path_join("/sys/fs/cgroup", dn, path);
else
t = path_join("/sys/fs/cgroup", dn, path, suffix);
if (!t)
return -ENOMEM;
*ret = t;
return 0;
}
static int join_path_unified(const char *path, const char *suffix, char **ret) {
int cg_get_path(const char *path, const char *suffix, char **ret) {
char *t;
assert(ret);
if (isempty(path) && isempty(suffix))
t = strdup("/sys/fs/cgroup");
else if (isempty(path))
t = path_join("/sys/fs/cgroup", suffix);
else if (isempty(suffix))
t = path_join("/sys/fs/cgroup", path);
else
t = path_join("/sys/fs/cgroup", path, suffix);
if (isempty(path))
path = TAKE_PTR(suffix);
t = path_join("/sys/fs/cgroup", path, suffix);
if (!t)
return -ENOMEM;
*ret = t;
*ret = path_simplify(t);
return 0;
}
int cg_get_path(const char *controller, const char *path, const char *suffix, char **ret) {
int r;
assert(ret);
if (!controller) {
char *t;
/* If no controller is specified, we return the path *below* the controllers, without any
* prefix. */
if (isempty(path) && isempty(suffix))
return -EINVAL;
if (isempty(suffix))
t = strdup(path);
else if (isempty(path))
t = strdup(suffix);
else
t = path_join(path, suffix);
if (!t)
return -ENOMEM;
*ret = path_simplify(t);
return 0;
}
if (!cg_controller_is_valid(controller))
return -EINVAL;
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
r = join_path_unified(path, suffix, ret);
else
r = join_path_legacy(controller, path, suffix, ret);
if (r < 0)
return r;
path_simplify(*ret);
return 0;
}
static int controller_is_v1_accessible(const char *root, const char *controller) {
const char *cpath, *dn;
assert(controller);
dn = controller_to_dirname(controller);
/* If root if specified, we check that:
* - possible subcgroup is created at root,
* - we can modify the hierarchy. */
cpath = strjoina("/sys/fs/cgroup/", dn, root, root ? "/cgroup.procs" : NULL);
return access_nofollow(cpath, root ? W_OK : F_OK);
}
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret) {
int r;
assert(controller);
assert(ret);
if (!cg_controller_is_valid(controller))
return -EINVAL;
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
/* In the unified hierarchy all controllers are considered accessible,
* except for the named hierarchies */
if (startswith(controller, "name="))
return -EOPNOTSUPP;
} else {
/* Check if the specified controller is actually accessible */
r = controller_is_v1_accessible(NULL, controller);
if (r < 0)
return r;
}
return cg_get_path(controller, path, suffix, ret);
}
int cg_set_xattr(const char *path, const char *name, const void *value, size_t size, int flags) {
_cleanup_free_ char *fs = NULL;
int r;
@@ -597,7 +479,7 @@ int cg_set_xattr(const char *path, const char *name, const void *value, size_t s
assert(name);
assert(value || size <= 0);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -611,7 +493,7 @@ int cg_get_xattr(const char *path, const char *name, char **ret, size_t *ret_siz
assert(path);
assert(name);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -625,7 +507,7 @@ int cg_get_xattr_bool(const char *path, const char *name) {
assert(path);
assert(name);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -639,37 +521,21 @@ int cg_remove_xattr(const char *path, const char *name) {
assert(path);
assert(name);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
return RET_NERRNO(removexattr(fs, name));
}
int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
int cg_pid_get_path(pid_t pid, char **ret_path) {
_cleanup_fclose_ FILE *f = NULL;
const char *fs, *controller_str = NULL; /* avoid false maybe-uninitialized warning */
int unified, r;
const char *fs;
int r;
assert(pid >= 0);
assert(ret_path);
if (controller) {
if (!cg_controller_is_valid(controller))
return -EINVAL;
} else
controller = SYSTEMD_CGROUP_CONTROLLER;
unified = cg_unified_controller(controller);
if (unified < 0)
return unified;
if (unified == 0) {
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
else
controller_str = controller;
}
fs = procfs_file_alloca(pid, "cgroup");
r = fopen_unlocked(fs, "re", &f);
if (r == -ENOENT)
@@ -687,34 +553,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
if (r == 0)
return -ENODATA;
if (unified) {
e = startswith(line, "0:");
if (!e)
continue;
e = startswith(line, "0:");
if (!e)
continue;
e = strchr(e, ':');
if (!e)
continue;
} else {
char *l;
l = strchr(line, ':');
if (!l)
continue;
l++;
e = strchr(l, ':');
if (!e)
continue;
*e = 0;
assert(controller_str);
r = string_contains_word(l, ",", controller_str);
if (r < 0)
return r;
if (r == 0)
continue;
}
e = strchr(e, ':');
if (!e)
continue;
_cleanup_free_ char *path = strdup(e + 1);
if (!path)
@@ -734,7 +579,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
}
}
int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_path) {
int cg_pidref_get_path(const PidRef *pidref, char **ret_path) {
_cleanup_free_ char *path = NULL;
int r;
@@ -749,7 +594,7 @@ int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_
// bit of information from pidfd directly. However, the latter requires privilege and it's
// not entirely clear how to handle cgroups from outer namespace.
r = cg_pid_get_path(controller, pidref->pid, &path);
r = cg_pid_get_path(pidref->pid, &path);
if (r < 0)
return r;
@@ -762,7 +607,7 @@ int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_
return 0;
}
int cg_is_empty(const char *controller, const char *path) {
int cg_is_empty(const char *path) {
_cleanup_free_ char *t = NULL;
int r;
@@ -775,7 +620,7 @@ int cg_is_empty(const char *controller, const char *path) {
if (empty_or_root(path))
return false;
r = cg_get_keyed_attribute(controller, path, "cgroup.events", STRV_MAKE("populated"), &t);
r = cg_get_keyed_attribute(path, "cgroup.events", STRV_MAKE("populated"), &t);
if (r == -ENOENT)
return true;
if (r < 0)
@@ -785,89 +630,74 @@ int cg_is_empty(const char *controller, const char *path) {
}
int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) {
_cleanup_free_ char *controller = NULL, *path = NULL;
_cleanup_free_ char *controller = NULL;
const char *path;
int r;
assert(spec);
if (*spec == '/') {
if (!path_is_normalized(spec))
return -EINVAL;
/* This extracts the path part from the deprecated controller:path spec. The path must be absolute or
* an empty string. No validation is done for the controller part. */
if (ret_path) {
r = path_simplify_alloc(spec, &path);
if (r < 0)
return r;
}
if (isempty(spec) || path_is_absolute(spec)) {
/* Assume this does not contain controller. */
path = spec;
goto finalize;
}
} else {
const char *e;
e = strchr(spec, ':');
if (e) {
controller = strndup(spec, e-spec);
const char *e = strchr(spec, ':');
if (!e) {
/* Controller only. */
if (ret_controller) {
controller = strdup(spec);
if (!controller)
return -ENOMEM;
if (!cg_controller_is_valid(controller))
return -EINVAL;
if (!isempty(e + 1)) {
path = strdup(e+1);
if (!path)
return -ENOMEM;
if (!path_is_normalized(path) ||
!path_is_absolute(path))
return -EINVAL;
path_simplify(path);
}
} else {
if (!cg_controller_is_valid(spec))
return -EINVAL;
if (ret_controller) {
controller = strdup(spec);
if (!controller)
return -ENOMEM;
}
}
path = NULL;
} else {
/* Both controller and path. */
if (ret_controller) {
controller = strndup(spec, e - spec);
if (!controller)
return -ENOMEM;
}
path = e + 1;
}
finalize:
path = empty_to_null(path);
if (path) {
/* Non-empty path must be absolute. */
if (!path_is_absolute(path))
return -EINVAL;
/* Path must not contain dot-dot. */
if (!path_is_safe(path))
return -EINVAL;
}
if (ret_path) {
r = path_simplify_alloc(path, ret_path);
if (r < 0)
return r;
}
if (ret_controller)
*ret_controller = TAKE_PTR(controller);
if (ret_path)
*ret_path = TAKE_PTR(path);
return 0;
}
int cg_mangle_path(const char *path, char **ret) {
_cleanup_free_ char *c = NULL, *p = NULL;
int r;
assert(path);
assert(ret);
/* First, check if it already is a filesystem path */
if (path_startswith(path, "/sys/fs/cgroup"))
return path_simplify_alloc(path, ret);
/* Otherwise, treat it as cg spec */
r = cg_split_spec(path, &c, &p);
if (r < 0)
return r;
return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, ret);
}
int cg_get_root_path(char **ret_path) {
char *p, *e;
int r;
assert(ret_path);
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
r = cg_pid_get_path(1, &p);
if (r < 0)
return r;
@@ -909,7 +739,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **ret_cgroup) {
assert(pid >= 0);
assert(ret_cgroup);
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
r = cg_pid_get_path(pid, &raw);
if (r < 0)
return r;
@@ -1488,36 +1318,6 @@ char* cg_unescape(const char *p) {
return (char*) p;
}
#define CONTROLLER_VALID \
DIGITS LETTERS \
"_"
bool cg_controller_is_valid(const char *p) {
const char *t, *s;
if (!p)
return false;
if (streq(p, SYSTEMD_CGROUP_CONTROLLER))
return true;
s = startswith(p, "name=");
if (s)
p = s;
if (IN_SET(*p, 0, '_'))
return false;
for (t = p; *t; t++)
if (!strchr(CONTROLLER_VALID, *t))
return false;
if (t - p > NAME_MAX)
return false;
return true;
}
int cg_slice_to_path(const char *unit, char **ret) {
_cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
const char *dash;
@@ -1591,7 +1391,7 @@ int cg_is_threaded(const char *path) {
_cleanup_strv_free_ char **v = NULL;
int r;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.type", &fs);
r = cg_get_path(path, "cgroup.type", &fs);
if (r < 0)
return r;
@@ -1610,13 +1410,13 @@ int cg_is_threaded(const char *path) {
return strv_contains(v, "threaded") || strv_contains(v, "invalid");
}
int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
int cg_set_attribute(const char *path, const char *attribute, const char *value) {
_cleanup_free_ char *p = NULL;
int r;
assert(attribute);
r = cg_get_path(controller, path, attribute, &p);
r = cg_get_path(path, attribute, &p);
if (r < 0)
return r;
@@ -1628,27 +1428,27 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
return write_string_file(p, value, WRITE_STRING_FILE_DISABLE_BUFFER|WRITE_STRING_FILE_OPEN_NONBLOCKING);
}
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
int cg_get_attribute(const char *path, const char *attribute, char **ret) {
_cleanup_free_ char *p = NULL;
int r;
assert(attribute);
r = cg_get_path(controller, path, attribute, &p);
r = cg_get_path(path, attribute, &p);
if (r < 0)
return r;
return read_one_line_file(p, ret);
}
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret) {
int cg_get_attribute_as_uint64(const char *path, const char *attribute, uint64_t *ret) {
_cleanup_free_ char *value = NULL;
uint64_t v;
int r;
assert(ret);
r = cg_get_attribute(controller, path, attribute, &value);
r = cg_get_attribute(path, attribute, &value);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -1667,11 +1467,11 @@ int cg_get_attribute_as_uint64(const char *controller, const char *path, const c
return 0;
}
int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute) {
int cg_get_attribute_as_bool(const char *path, const char *attribute) {
_cleanup_free_ char *value = NULL;
int r;
r = cg_get_attribute(controller, path, attribute, &value);
r = cg_get_attribute(path, attribute, &value);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -1687,7 +1487,7 @@ int cg_get_owner(const char *path, uid_t *ret_uid) {
assert(ret_uid);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &f);
r = cg_get_path(path, /* suffix = */ NULL, &f);
if (r < 0)
return r;
@@ -1703,7 +1503,6 @@ int cg_get_owner(const char *path, uid_t *ret_uid) {
}
int cg_get_keyed_attribute(
const char *controller,
const char *path,
const char *attribute,
char * const *keys,
@@ -1722,7 +1521,7 @@ int cg_get_keyed_attribute(
*
* If the attribute file doesn't exist at all returns ENOENT, if any key is not found returns ENXIO. */
r = cg_get_path(controller, path, attribute, &filename);
r = cg_get_path(path, attribute, &filename);
if (r < 0)
return r;
@@ -1865,48 +1664,22 @@ int cg_mask_supported_subtree(const char *root, CGroupMask *ret) {
* are actually accessible. Only covers real controllers, i.e. not the CGROUP_CONTROLLER_BPF_xyz
* pseudo-controllers. */
r = cg_all_unified();
/* We can read the supported and accessible controllers from the top-level cgroup attribute */
_cleanup_free_ char *controllers = NULL, *path = NULL;
r = cg_get_path(root, "cgroup.controllers", &path);
if (r < 0)
return r;
if (r > 0) {
_cleanup_free_ char *controllers = NULL, *path = NULL;
/* In the unified hierarchy we can read the supported and accessible controllers from
* the top-level cgroup attribute */
r = read_one_line_file(path, &controllers);
if (r < 0)
return r;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path);
if (r < 0)
return r;
r = cg_mask_from_string(controllers, &mask);
if (r < 0)
return r;
r = read_one_line_file(path, &controllers);
if (r < 0)
return r;
r = cg_mask_from_string(controllers, &mask);
if (r < 0)
return r;
/* Mask controllers that are not supported in unified hierarchy. */
mask &= CGROUP_MASK_V2;
} else {
CGroupController c;
/* In the legacy hierarchy, we check which hierarchies are accessible. */
mask = 0;
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
const char *n;
if (!FLAGS_SET(CGROUP_MASK_V1, bit))
continue;
n = cgroup_controller_to_string(c);
if (controller_is_v1_accessible(root, n) >= 0)
mask |= bit;
}
}
/* Mask controllers that are not supported in cgroup v2. */
mask &= CGROUP_MASK_V2;
*ret = mask;
return 0;
@@ -1923,115 +1696,6 @@ int cg_mask_supported(CGroupMask *ret) {
return cg_mask_supported_subtree(root, ret);
}
/* The hybrid mode was initially implemented in v232 and simply mounted cgroup2 on
* /sys/fs/cgroup/systemd. This unfortunately broke other tools (such as docker) which expected the v1
* "name=systemd" hierarchy on /sys/fs/cgroup/systemd. From v233 and on, the hybrid mode mounts v2 on
* /sys/fs/cgroup/unified and maintains "name=systemd" hierarchy on /sys/fs/cgroup/systemd for compatibility
* with other tools.
*
* To keep live upgrade working, we detect and support v232 layout. When v232 layout is detected, to keep
* cgroup v2 process management but disable the compat dual layout, we return true on
* cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) and false on cg_hybrid_unified().
*/
static thread_local bool unified_systemd_v232;
int cg_unified_cached(bool flush) {
static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN;
struct statfs fs;
/* Checks if we support the unified hierarchy. Returns an
* error when the cgroup hierarchies aren't mounted yet or we
* have any other trouble determining if the unified hierarchy
* is supported. */
if (flush)
unified_cache = CGROUP_UNIFIED_UNKNOWN;
else if (unified_cache >= CGROUP_UNIFIED_NONE)
return unified_cache;
if (statfs("/sys/fs/cgroup/", &fs) < 0)
return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/\") failed: %m");
if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
log_debug("Found cgroup2 on /sys/fs/cgroup/, full unified hierarchy");
unified_cache = CGROUP_UNIFIED_ALL;
} else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) {
if (statfs("/sys/fs/cgroup/unified/", &fs) == 0 &&
F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
log_debug("Found cgroup2 on /sys/fs/cgroup/unified, unified hierarchy for systemd controller");
unified_cache = CGROUP_UNIFIED_SYSTEMD;
unified_systemd_v232 = false;
} else {
if (statfs("/sys/fs/cgroup/systemd/", &fs) < 0) {
if (errno == ENOENT) {
/* Some other software may have set up /sys/fs/cgroup in a configuration we do not recognize. */
log_debug_errno(errno, "Unsupported cgroupsv1 setup detected: name=systemd hierarchy not found.");
return -ENOMEDIUM;
}
return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/systemd\" failed: %m");
}
if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
log_debug("Found cgroup2 on /sys/fs/cgroup/systemd, unified hierarchy for systemd controller (v232 variant)");
unified_cache = CGROUP_UNIFIED_SYSTEMD;
unified_systemd_v232 = true;
} else if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)) {
log_debug("Found cgroup on /sys/fs/cgroup/systemd, legacy hierarchy");
unified_cache = CGROUP_UNIFIED_NONE;
} else {
log_debug("Unexpected filesystem type %llx mounted on /sys/fs/cgroup/systemd, assuming legacy hierarchy",
(unsigned long long) fs.f_type);
unified_cache = CGROUP_UNIFIED_NONE;
}
}
} else if (F_TYPE_EQUAL(fs.f_type, SYSFS_MAGIC)) {
return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
"No filesystem is currently mounted on /sys/fs/cgroup.");
} else
return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
"Unknown filesystem type %llx mounted on /sys/fs/cgroup.",
(unsigned long long)fs.f_type);
return unified_cache;
}
int cg_unified_controller(const char *controller) {
int r;
r = cg_unified_cached(false);
if (r < 0)
return r;
if (r == CGROUP_UNIFIED_NONE)
return false;
if (r >= CGROUP_UNIFIED_ALL)
return true;
return streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER);
}
int cg_all_unified(void) {
int r;
r = cg_unified_cached(false);
if (r < 0)
return r;
return r >= CGROUP_UNIFIED_ALL;
}
int cg_hybrid_unified(void) {
int r;
r = cg_unified_cached(false);
if (r < 0)
return r;
return r == CGROUP_UNIFIED_SYSTEMD && !unified_systemd_v232;
}
int cg_is_delegated(const char *path) {
int r;
+14 -41
View File
@@ -3,8 +3,6 @@
#include "basic-forward.h"
#define SYSTEMD_CGROUP_CONTROLLER_LEGACY "name=systemd"
#define SYSTEMD_CGROUP_CONTROLLER_HYBRID "name=unified"
#define SYSTEMD_CGROUP_CONTROLLER "_systemd"
/* An enum of well known cgroup controllers */
@@ -113,29 +111,16 @@ static inline uint64_t BFQ_WEIGHT(uint64_t io_weight) {
CGROUP_BFQ_WEIGHT_DEFAULT + (io_weight - CGROUP_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_WEIGHT_MAX - CGROUP_WEIGHT_DEFAULT);
}
typedef enum CGroupUnified {
CGROUP_UNIFIED_UNKNOWN = -1,
CGROUP_UNIFIED_NONE = 0, /* Both systemd and controllers on legacy */
CGROUP_UNIFIED_SYSTEMD = 1, /* Only systemd on unified */
CGROUP_UNIFIED_ALL = 2, /* Both systemd and controllers on unified */
} CGroupUnified;
/*
* General rules:
*
* We accept named hierarchies in the syntax "foo" and "name=foo".
*
* We expect that named hierarchies do not conflict in name with a
* kernel hierarchy, modulo the "name=" prefix.
*
* We always generate "normalized" controller names, i.e. without the
* "name=" prefix.
*
* We require absolute cgroup paths. When returning, we will always
* generate paths with multiple adjacent / removed.
*/
int cg_path_open(const char *controller, const char *path);
int cg_is_available(void);
int cg_path_open(const char *path);
int cg_cgroupid_open(int cgroupfs_fd, uint64_t id);
int cg_path_from_cgroupid(int cgroupfs_fd, uint64_t id, char **ret);
@@ -153,11 +138,11 @@ typedef enum CGroupFlags {
CGROUP_DONT_SKIP_UNMAPPED = 1 << 2,
} CGroupFlags;
int cg_enumerate_processes(const char *controller, const char *path, FILE **ret);
int cg_enumerate_processes(const char *path, FILE **ret);
int cg_read_pid(FILE *f, pid_t *ret, CGroupFlags flags);
int cg_read_pidref(FILE *f, PidRef *ret, CGroupFlags flags);
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **ret);
int cg_enumerate_subgroups(const char *path, DIR **ret);
int cg_read_subgroup(DIR *d, char **ret);
typedef int (*cg_kill_log_func_t)(const PidRef *pid, int sig, void *userdata);
@@ -167,13 +152,11 @@ int cg_kill_kernel_sigkill(const char *path);
int cg_kill_recursive(const char *path, int sig, CGroupFlags flags, Set *killed_pids, cg_kill_log_func_t log_kill, void *userdata);
int cg_split_spec(const char *spec, char **ret_controller, char **ret_path);
int cg_mangle_path(const char *path, char **ret);
int cg_get_path(const char *controller, const char *path, const char *suffix, char **ret);
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret);
int cg_get_path(const char *path, const char *suffix, char **ret);
int cg_pid_get_path(const char *controller, pid_t pid, char **ret);
int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret);
int cg_pid_get_path(pid_t pid, char **ret);
int cg_pidref_get_path(const PidRef *pidref, char **ret);
int cg_is_threaded(const char *path);
@@ -182,12 +165,12 @@ int cg_is_delegated_fd(int fd);
int cg_has_coredump_receive(const char *path);
int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char * const *keys, char **values);
int cg_set_attribute(const char *path, const char *attribute, const char *value);
int cg_get_attribute(const char *path, const char *attribute, char **ret);
int cg_get_attribute_as_uint64(const char *path, const char *attribute, uint64_t *ret);
int cg_get_attribute_as_bool(const char *path, const char *attribute);
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret);
int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute);
int cg_get_keyed_attribute(const char *path, const char *attribute, char * const *keys, char **values);
int cg_get_owner(const char *path, uid_t *ret_uid);
@@ -197,7 +180,7 @@ int cg_get_xattr(const char *path, const char *name, char **ret, size_t *ret_siz
int cg_get_xattr_bool(const char *path, const char *name);
int cg_remove_xattr(const char *path, const char *name);
int cg_is_empty(const char *controller, const char *path);
int cg_is_empty(const char *path);
int cg_get_root_path(char **path);
@@ -249,8 +232,6 @@ bool cg_needs_escape(const char *p) _pure_;
int cg_escape(const char *p, char **ret);
char* cg_unescape(const char *p) _pure_;
bool cg_controller_is_valid(const char *p);
int cg_slice_to_path(const char *unit, char **ret);
int cg_mask_supported(CGroupMask *ret);
@@ -260,14 +241,6 @@ int cg_mask_to_string(CGroupMask mask, char **ret);
bool cg_kill_supported(void);
int cg_all_unified(void);
int cg_hybrid_unified(void);
int cg_unified_controller(const char *controller);
int cg_unified_cached(bool flush);
static inline int cg_unified(void) {
return cg_unified_cached(true);
}
const char* cgroup_controller_to_string(CGroupController c) _const_;
CGroupController cgroup_controller_from_string(const char *s) _pure_;
+10 -23
View File
@@ -36,32 +36,19 @@ uint64_t physical_memory(void) {
return mem;
}
r = cg_all_unified();
r = cg_get_attribute(root, "memory.max", &value);
if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
* complain. (Note that it might exist on our own root though, if we live
* in a cgroup namespace, hence check anyway instead of not even
* trying.) */
return mem;
if (r < 0) {
log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
return mem;
}
if (r > 0) {
r = cg_get_attribute("memory", root, "memory.max", &value);
if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
* complain. (Note that it might exist on our own root though, if we live
* in a cgroup namespace, hence check anyway instead of not even
* trying.) */
return mem;
if (r < 0) {
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
return mem;
}
if (streq(value, "max"))
return mem;
} else {
r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
if (r < 0) {
log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
return mem;
}
}
if (streq(value, "max"))
return mem;
r = safe_atou64(value, &lim);
if (r < 0) {
@@ -159,7 +146,7 @@ uint64_t system_tasks_max(void) {
/* We'll have the "pids.max" attribute on the our root cgroup only if we are in a
* CLONE_NEWCGROUP namespace. On the top-level namespace this attribute is missing, hence
* suppress any message about that */
r = cg_get_attribute_as_uint64("pids", root, "pids.max", &c);
r = cg_get_attribute_as_uint64(root, "pids.max", &c);
if (r < 0 && r != -ENODATA)
log_debug_errno(r, "Failed to read pids.max attribute of root cgroup, ignoring: %m");
}
+1 -5
View File
@@ -2146,11 +2146,7 @@ int posix_spawn_wrapper(
if (cgroup && have_clone_into_cgroup) {
_cleanup_free_ char *resolved_cgroup = NULL;
r = cg_get_path_and_check(
SYSTEMD_CGROUP_CONTROLLER,
cgroup,
/* suffix= */ NULL,
&resolved_cgroup);
r = cg_get_path(cgroup, /* suffix= */ NULL, &resolved_cgroup);
if (r < 0)
return r;
+10 -12
View File
@@ -187,11 +187,7 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
static void show_cg_info(const char *controller, const char *path) {
if (cg_all_unified() == 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
printf("Controller %s; ", controller);
static void show_cg_info(const char *path) {
printf("CGroup %s:\n", empty_to_root(path));
fflush(stdout);
}
@@ -248,7 +244,7 @@ static int run(int argc, char *argv[]) {
printf("Unit %s (%s):\n", unit_name, cgroup);
fflush(stdout);
q = show_cgroup_by_path(cgroup, NULL, 0, arg_output_flags);
q = show_cgroup(cgroup, NULL, 0, arg_output_flags);
} else if (path_startswith(*name, "/sys/fs/cgroup")) {
@@ -258,7 +254,7 @@ static int run(int argc, char *argv[]) {
q = show_cgroup_by_path(*name, NULL, 0, arg_output_flags);
} else {
_cleanup_free_ char *c = NULL, *p = NULL, *j = NULL;
const char *controller, *path;
const char *path;
if (!root) {
/* Query root only if needed, treat error as fatal */
@@ -273,7 +269,9 @@ static int run(int argc, char *argv[]) {
goto failed;
}
controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
if (c && !streq(c, SYSTEMD_CGROUP_CONTROLLER))
log_warning("Legacy cgroup v1 controller '%s' was specified, ignoring.", c);
if (p) {
j = path_join(root, p);
if (!j)
@@ -284,9 +282,9 @@ static int run(int argc, char *argv[]) {
} else
path = root;
show_cg_info(controller, path);
show_cg_info(path);
q = show_cgroup(controller, path, NULL, 0, arg_output_flags);
q = show_cgroup(path, NULL, 0, arg_output_flags);
}
failed:
@@ -320,10 +318,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to list cgroup tree: %m");
show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root);
show_cg_info(root);
printf("-.slice\n");
r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_output_flags);
r = show_cgroup(root, NULL, 0, arg_output_flags);
}
}
if (r < 0)
+6 -6
View File
@@ -172,7 +172,7 @@ static int process_memory(Group *g) {
else {
_cleanup_free_ char *p = NULL, *v = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, g->path, "memory.current", &p);
r = cg_get_path(g->path, "memory.current", &p);
if (r < 0)
return r;
@@ -202,7 +202,7 @@ static int process_io(Group *g, unsigned iteration) {
assert(g);
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, g->path, "io.stat", &p);
r = cg_get_path(g->path, "io.stat", &p);
if (r < 0)
return r;
@@ -288,7 +288,7 @@ static int process_cpu(Group *g, unsigned iteration) {
_cleanup_free_ char *val = NULL;
uint64_t u;
r = cg_get_keyed_attribute(SYSTEMD_CGROUP_CONTROLLER, g->path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
r = cg_get_keyed_attribute(g->path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
if (IN_SET(r, -ENOENT, -ENXIO))
return 0;
if (r < 0)
@@ -367,7 +367,7 @@ static int process(
_cleanup_fclose_ FILE *f = NULL;
pid_t pid;
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
r = cg_enumerate_processes(path, &f);
if (r < 0 && r != -ENOENT)
return r;
if (r >= 0) {
@@ -395,7 +395,7 @@ static int process(
} else {
_cleanup_free_ char *p = NULL, *v = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "pids.current", &p);
r = cg_get_path(path, "pids.current", &p);
if (r < 0)
return r;
@@ -458,7 +458,7 @@ static int refresh(
if (r < 0)
return r;
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
r = cg_enumerate_subgroups(path, &d);
if (r == -ENOENT) {
if (ret)
*ret = NULL;
+1 -1
View File
@@ -236,7 +236,7 @@ int bpf_devices_apply_policy(
if (r < 0)
return log_error_errno(r, "Extending device control BPF program failed: %m");
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, NULL, &controller_path);
r = cg_get_path(cgroup_path, /* suffix = */ NULL, &controller_path);
if (r < 0)
return log_error_errno(r, "Failed to determine cgroup path: %m");
+1 -1
View File
@@ -696,7 +696,7 @@ int bpf_firewall_install(Unit *u) {
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
"bpf-firewall: BPF firewalling not supported, proceeding without.");
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, NULL, &path);
r = cg_get_path(crt->cgroup_path, /* suffix = */ NULL, &path);
if (r < 0)
return log_unit_error_errno(u, r, "bpf-firewall: Failed to determine cgroup path: %m");
+1 -1
View File
@@ -151,7 +151,7 @@ int bpf_foreign_install(Unit *u) {
if (!crt)
return 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, NULL, &cgroup_path);
r = cg_get_path(crt->cgroup_path, /* suffix = */ NULL, &cgroup_path);
if (r < 0)
return log_unit_error_errno(u, r, "bpf-foreign: Failed to get cgroup path: %m");
+1 -1
View File
@@ -115,7 +115,7 @@ static int restrict_ifaces_install_impl(Unit *u) {
if (!crt)
return 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, NULL, &cgroup_path);
r = cg_get_path(crt->cgroup_path, /* suffix = */ NULL, &cgroup_path);
if (r < 0)
return log_unit_error_errno(u, r, "restrict-interfaces: Failed to get cgroup path: %m");
+1 -1
View File
@@ -179,7 +179,7 @@ static int socket_bind_install_impl(Unit *u) {
if (!crt)
return 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, NULL, &cgroup_path);
r = cg_get_path(crt->cgroup_path, /* suffix = */ NULL, &cgroup_path);
if (r < 0)
return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to get cgroup path: %m");
+18 -22
View File
@@ -136,7 +136,7 @@ static int set_attribute_and_warn(Unit *u, const char *attribute, const char *va
if (!crt || !crt->cgroup_path)
return -EOWNERDEAD;
r = cg_set_attribute(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, attribute, value);
r = cg_set_attribute(crt->cgroup_path, attribute, value);
if (r < 0)
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
attribute, empty_to_root(crt->cgroup_path), (int) strcspn(value, NEWLINE), value);
@@ -287,7 +287,7 @@ static int unit_get_kernel_memory_limit(Unit *u, const char *file, uint64_t *ret
if (!crt || !crt->cgroup_path)
return -EOWNERDEAD;
return cg_get_attribute_as_uint64("memory", crt->cgroup_path, file, ret);
return cg_get_attribute_as_uint64(crt->cgroup_path, file, ret);
}
static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_t *ret_unit_value, uint64_t *ret_kernel_value) {
@@ -1139,7 +1139,7 @@ static void cgroup_apply_cpu_idle(Unit *u, uint64_t weight) {
is_idle = weight == CGROUP_WEIGHT_IDLE;
idle_val = one_zero(is_idle);
r = cg_set_attribute("cpu", crt->cgroup_path, "cpu.idle", idle_val);
r = cg_set_attribute(crt->cgroup_path, "cpu.idle", idle_val);
if (r < 0 && (r != -ENOENT || is_idle))
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%s': %m",
"cpu.idle", empty_to_root(crt->cgroup_path), idle_val);
@@ -1211,7 +1211,7 @@ static int set_bfq_weight(Unit *u, dev_t dev, uint64_t io_weight) {
else
xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
r = cg_set_attribute(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, "io.bfq.weight", buf);
r = cg_set_attribute(crt->cgroup_path, "io.bfq.weight", buf);
if (r >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%s=%" PRIu64 " scaled to io.bfq.weight=%" PRIu64,
major(dev) > 0 ? "IODeviceWeight" : "IOWeight",
@@ -1236,7 +1236,7 @@ static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_
r1 = set_bfq_weight(u, dev, io_weight);
xsprintf(buf, DEVNUM_FORMAT_STR " %" PRIu64 "\n", DEVNUM_FORMAT_VAL(dev), io_weight);
r2 = cg_set_attribute("io", crt->cgroup_path, "io.weight", buf);
r2 = cg_set_attribute(crt->cgroup_path, "io.weight", buf);
/* Look at the configured device, when both fail, prefer io.weight errno. */
r = r2 == -EOPNOTSUPP ? r1 : r2;
@@ -1989,7 +1989,7 @@ static int unit_watch_cgroup(Unit *u) {
if (r < 0)
return log_oom();
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, "cgroup.events", &events);
r = cg_get_path(crt->cgroup_path, "cgroup.events", &events);
if (r < 0)
return log_oom();
@@ -2044,7 +2044,7 @@ static int unit_watch_cgroup_memory(Unit *u) {
if (r < 0)
return log_oom();
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, "memory.events", &events);
r = cg_get_path(crt->cgroup_path, "memory.events", &events);
if (r < 0)
return log_oom();
@@ -2103,7 +2103,7 @@ static int unit_update_cgroup(
CGroupRuntime *crt = ASSERT_PTR(unit_get_cgroup_runtime(u));
uint64_t cgroup_id = 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, NULL, &cgroup_full_path);
r = cg_get_path(crt->cgroup_path, /* suffix = */ NULL, &cgroup_full_path);
if (r == 0) {
r = cg_path_get_cgroupid(cgroup_full_path, &cgroup_id);
if (r < 0)
@@ -2714,7 +2714,7 @@ int unit_cgroup_is_empty(Unit *u) {
if (!crt->cgroup_path)
return -EOWNERDEAD;
r = cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path);
r = cg_is_empty(crt->cgroup_path);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", empty_to_root(crt->cgroup_path));
return r;
@@ -2857,7 +2857,7 @@ int unit_search_main_pid(Unit *u, PidRef *ret) {
if (!crt || !crt->cgroup_path)
return -ENXIO;
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, &f);
r = cg_enumerate_processes(crt->cgroup_path, &f);
if (r < 0)
return r;
@@ -3033,7 +3033,6 @@ int unit_check_oom(Unit *u) {
if (ctx->memory_oom_group) {
r = cg_get_keyed_attribute(
"memory",
crt->cgroup_path,
"memory.events.local",
STRV_MAKE("oom_group_kill"),
@@ -3044,7 +3043,6 @@ int unit_check_oom(Unit *u) {
if (isempty(oom_kill)) {
r = cg_get_keyed_attribute(
"memory",
crt->cgroup_path,
"memory.events",
STRV_MAKE("oom_kill"),
@@ -3156,7 +3154,6 @@ static int unit_check_cgroup_events(Unit *u) {
return 0;
r = cg_get_keyed_attribute(
SYSTEMD_CGROUP_CONTROLLER,
crt->cgroup_path,
"cgroup.events",
STRV_MAKE("populated", "frozen"),
@@ -3260,7 +3257,7 @@ int manager_setup_cgroup(Manager *m) {
/* 1. Determine hierarchy */
m->cgroup_root = mfree(m->cgroup_root);
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
r = cg_pid_get_path(0, &m->cgroup_root);
if (r < 0)
return log_error_errno(r, "Cannot determine cgroup we are running in: %m");
@@ -3404,7 +3401,7 @@ Unit* manager_get_unit_by_pidref_cgroup(Manager *m, const PidRef *pid) {
assert(m);
if (cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0)
if (cg_pidref_get_path(pid, &cgroup) < 0)
return NULL;
return manager_get_unit_by_cgroup(m, cgroup);
@@ -3538,7 +3535,7 @@ int unit_get_memory_accounting(Unit *u, CGroupMemoryAccountingMetric metric, uin
if (!FLAGS_SET(crt->cgroup_realized_mask, CGROUP_MASK_MEMORY))
return -ENODATA;
r = cg_get_attribute_as_uint64("memory", crt->cgroup_path, attributes_table[metric], &bytes);
r = cg_get_attribute_as_uint64(crt->cgroup_path, attributes_table[metric], &bytes);
if (r < 0 && r != -ENODATA)
return r;
updated = r >= 0;
@@ -3581,7 +3578,7 @@ int unit_get_tasks_current(Unit *u, uint64_t *ret) {
if ((crt->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
return -ENODATA;
return cg_get_attribute_as_uint64("pids", crt->cgroup_path, "pids.current", ret);
return cg_get_attribute_as_uint64(crt->cgroup_path, "pids.current", ret);
}
static int unit_get_cpu_usage_raw(const Unit *u, const CGroupRuntime *crt, nsec_t *ret) {
@@ -3601,7 +3598,7 @@ static int unit_get_cpu_usage_raw(const Unit *u, const CGroupRuntime *crt, nsec_
_cleanup_free_ char *val = NULL;
uint64_t us;
r = cg_get_keyed_attribute("cpu", crt->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
r = cg_get_keyed_attribute(crt->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
if (r < 0)
return r;
@@ -3772,7 +3769,7 @@ static int unit_get_io_accounting_raw(
if (!FLAGS_SET(crt->cgroup_realized_mask, CGROUP_MASK_IO))
return -ENODATA;
r = cg_get_path("io", crt->cgroup_path, "io.stat", &path);
r = cg_get_path(crt->cgroup_path, "io.stat", &path);
if (r < 0)
return r;
@@ -4037,7 +4034,6 @@ static int unit_cgroup_freezer_kernel_state(Unit *u, FreezerState *ret) {
return -EOWNERDEAD;
r = cg_get_keyed_attribute(
SYSTEMD_CGROUP_CONTROLLER,
crt->cgroup_path,
"cgroup.events",
STRV_MAKE("frozen"),
@@ -4111,7 +4107,7 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
assert_not_reached();
}
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, "cgroup.freeze", &path);
r = cg_get_path(crt->cgroup_path, "cgroup.freeze", &path);
if (r < 0)
return r;
@@ -4142,7 +4138,7 @@ int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
if ((crt->cgroup_realized_mask & CGROUP_MASK_CPUSET) == 0)
return -ENODATA;
r = cg_get_attribute("cpuset", crt->cgroup_path, name, &v);
r = cg_get_attribute(crt->cgroup_path, name, &v);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
+3 -3
View File
@@ -1345,7 +1345,7 @@ static int append_process(sd_bus_message *reply, const char *p, PidRef *pid, Set
return r;
if (!p) {
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
r = cg_pidref_get_path(pid, &buf);
if (r == -ESRCH)
return 0;
if (r < 0)
@@ -1375,7 +1375,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
assert(reply);
assert(p);
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
r = cg_enumerate_processes(p, &f);
if (r == -ENOENT)
return 0;
if (r < 0)
@@ -1411,7 +1411,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
return r;
}
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
r = cg_enumerate_subgroups(p, &d);
if (r == -ENOENT)
return 0;
if (r < 0)
+2 -2
View File
@@ -5579,7 +5579,7 @@ int exec_invoke(
if (is_pressure_supported() > 0) {
if (cgroup_context_want_memory_pressure(cgroup_context)) {
r = cg_get_path("memory", params->cgroup_path, "memory.pressure", &memory_pressure_path);
r = cg_get_path(params->cgroup_path, "memory.pressure", &memory_pressure_path);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
@@ -5597,7 +5597,7 @@ int exec_invoke(
* memory_pressure_path != NULL in the conditional below. */
if (memory_pressure_path && needs_sandboxing && exec_needs_cgroup_namespace(context)) {
memory_pressure_path = mfree(memory_pressure_path);
r = cg_get_path("memory", "/", "memory.pressure", &memory_pressure_path);
r = cg_get_path("/", "memory.pressure", &memory_pressure_path);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
+1 -1
View File
@@ -2015,7 +2015,7 @@ static int cgroup_good(Service *s) {
if (!s->cgroup_runtime || !s->cgroup_runtime->cgroup_path)
return 0;
r = cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_runtime->cgroup_path);
r = cg_is_empty(s->cgroup_runtime->cgroup_path);
if (r < 0)
return r;
+1 -1
View File
@@ -132,7 +132,7 @@ static int can_forward_coredump(PidRef *pidref, PidRef *leader) {
}
_cleanup_free_ char *cgroup = NULL;
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, leader, &cgroup);
r = cg_pidref_get_path(leader, &cgroup);
if (r < 0)
return log_debug_errno(r, "Failed to get cgroup of the leader process, ignoring: %m");
+1 -1
View File
@@ -1096,7 +1096,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid
if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
if (!c->cgroup) {
r = cg_pid_get_path(NULL, pidref->pid, &c->cgroup);
r = cg_pid_get_path(pidref->pid, &c->cgroup);
if (r < 0 && !ERRNO_IS_NEG_PRIVILEGE(r))
return r;
}
+2 -2
View File
@@ -13,8 +13,8 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
if (IN_SET(cg_unified(), -ENOMEDIUM, -ENOENT))
return log_tests_skipped("/sys/fs/cgroup/ not available");
if (cg_is_available() <= 0)
return log_tests_skipped("cgroupfs v2 is not mounted");
r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
+1 -1
View File
@@ -1972,7 +1972,7 @@ _public_ int sd_event_add_memory_pressure(
* not delegated to us, or PSI simply not available in the kernel). */
_cleanup_free_ char *cg = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cg);
r = cg_pid_get_path(0, &cg);
if (r < 0)
return r;
+2 -2
View File
@@ -105,7 +105,7 @@ _public_ int sd_pid_get_cgroup(pid_t pid, char **ret_cgroup) {
assert_return(pid >= 0, -EINVAL);
_cleanup_free_ char *c = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c);
r = cg_pid_get_path(pid, &c);
if (r < 0)
return r;
@@ -418,7 +418,7 @@ _public_ int sd_peer_get_cgroup(int fd, char **ret_cgroup) {
return r;
_cleanup_free_ char *c = NULL;
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, &pidref, &c);
r = cg_pidref_get_path(&pidref, &c);
if (r < 0)
return r;
+2 -2
View File
@@ -327,8 +327,8 @@ TEST(monitor) {
}
static int intro(void) {
if (IN_SET(cg_unified(), -ENOENT, -ENOMEDIUM))
return log_tests_skipped("cgroupfs is not mounted");
if (cg_is_available() <= 0)
return log_tests_skipped("cgroupfs v2 is not mounted");
log_info("/* Information printed is from the live system */");
return EXIT_SUCCESS;
+2 -2
View File
@@ -457,10 +457,10 @@ static int show_unit_cgroup(
/* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
if (cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
if (cg_is_empty(cgroup) != 0 && leader <= 0)
return 0;
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, prefix, c, &leader, leader > 0, get_output_flags());
show_cgroup_and_extra(cgroup, prefix, c, &leader, leader > 0, get_output_flags());
} else if (r < 0)
return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r));
+3 -3
View File
@@ -596,7 +596,7 @@ static int machine_dispatch_cgroup_empty(sd_event_source *s, const struct inotif
assert(m->cgroup);
r = cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, m->cgroup);
r = cg_is_empty(m->cgroup);
if (r < 0)
return log_error_errno(r, "Failed to determine if cgroup '%s' is empty: %m", m->cgroup);
@@ -616,7 +616,7 @@ static int machine_watch_cgroup(Machine *m) {
return 0;
_cleanup_free_ char *p = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup, "cgroup.events", &p);
r = cg_get_path(m->cgroup, "cgroup.events", &p);
if (r < 0)
return log_error_errno(r, "Failed to get cgroup path for cgroup '%s': %m", m->cgroup);
@@ -782,7 +782,7 @@ bool machine_may_gc(Machine *m, bool drop_not_started) {
}
if (m->cgroup) {
r = cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, m->cgroup);
r = cg_is_empty(m->cgroup);
if (IN_SET(r, 0, -ENOENT))
return true;
if (r < 0)
+2 -2
View File
@@ -452,10 +452,10 @@ static int show_unit_cgroup(
/* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
if (cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
if (cg_is_empty(cgroup) != 0 && leader <= 0)
return 0;
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags());
show_cgroup_and_extra(cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags());
} else if (r < 0)
return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r));
+1 -1
View File
@@ -722,7 +722,7 @@ static int method_register_machine(sd_bus_message *message, void *userdata, sd_b
/* If this is not a top-level cgroup, then we need the cgroup path to be able to watch when
* it empties */
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, &m->leader, &m->cgroup);
r = cg_pidref_get_path(&m->leader, &m->cgroup);
if (r < 0) {
r = sd_bus_error_set_errnof(error, r,
"Failed to determine cgroup of process "PID_FMT" : %m",
+3 -3
View File
@@ -109,11 +109,11 @@ int manager_install_sysctl_monitor(Manager *manager) {
if (r < 0)
return log_warning_errno(r, "Failed to load libbpf, not installing sysctl monitor: %m");
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
r = cg_pid_get_path(0, &cgroup);
if (r < 0)
return log_warning_errno(r, "Failed to get cgroup path, ignoring: %m.");
root_cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
root_cgroup_fd = cg_path_open("/");
if (root_cgroup_fd < 0)
return log_warning_errno(root_cgroup_fd, "Failed to open cgroup, ignoring: %m");
@@ -122,7 +122,7 @@ int manager_install_sysctl_monitor(Manager *manager) {
return log_full_errno(errno == EINVAL ? LOG_DEBUG : LOG_INFO, errno,
"Unable to load sysctl monitor BPF program, ignoring: %m");
cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, cgroup);
cgroup_fd = cg_path_open(cgroup);
if (cgroup_fd < 0)
return log_warning_errno(cgroup_fd, "Failed to open cgroup: %m");
+5 -5
View File
@@ -75,9 +75,9 @@ int create_subcgroup(
return log_error_errno(r, "Failed to determine supported controllers: %m");
if (keep_unit)
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
r = cg_pid_get_path(0, &cgroup);
else
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
r = cg_pidref_get_path(pid, &cgroup);
if (r < 0)
return log_error_errno(r, "Failed to get our control group: %m");
@@ -100,7 +100,7 @@ int create_subcgroup(
if (userns_mode == USER_NAMESPACE_MANAGED) {
_cleanup_close_ int cgroup_fd = -EBADF;
cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, payload);
cgroup_fd = cg_path_open(payload);
if (cgroup_fd < 0)
return log_error_errno(cgroup_fd, "Failed to open cgroup %s: %m", payload);
@@ -113,7 +113,7 @@ int create_subcgroup(
return log_error_errno(r, "Failed to add cgroup %s to userns: %m", payload);
} else {
_cleanup_free_ char *fs = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, payload, NULL, &fs);
r = cg_get_path(payload, /* suffix = */ NULL, &fs);
if (r < 0)
return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
@@ -172,7 +172,7 @@ int bind_mount_cgroup_hierarchy(void) {
/* NB: This must be called from the inner child, with /sys/fs/cgroup/ being a bind mount in mountns! */
r = cg_pid_get_path(NULL, 0, &own_cgroup_path);
r = cg_pid_get_path(0, &own_cgroup_path);
if (r < 0)
return log_error_errno(r, "Failed to determine our own cgroup path: %m");
+2 -2
View File
@@ -210,7 +210,7 @@ static int recursively_get_cgroup_context(Hashmap *new_h, const char *path) {
assert(new_h);
assert(path);
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
r = cg_enumerate_subgroups(path, &d);
if (r < 0)
return r;
@@ -235,7 +235,7 @@ static int recursively_get_cgroup_context(Hashmap *new_h, const char *path) {
subpath = mfree(subpath);
r = cg_get_attribute_as_bool("memory", cg_path, "memory.oom.group");
r = cg_get_attribute_as_bool(cg_path, "memory.oom.group");
/* The cgroup might be gone. Skip it as a candidate since we can't get information on it. */
if (r == -ENOMEM)
return r;
+7 -7
View File
@@ -240,7 +240,7 @@ int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run) {
if (dry_run) {
_cleanup_free_ char *cg_path = NULL;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &cg_path);
r = cg_get_path(path, /* suffix = */ NULL, &cg_path);
if (r < 0)
return r;
@@ -418,7 +418,7 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
is_root = empty_or_root(path);
ctx->preference = MANAGED_OOM_PREFERENCE_NONE;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "memory.pressure", &p);
r = cg_get_path(path, "memory.pressure", &p);
if (r < 0)
return log_debug_errno(r, "Error getting cgroup memory pressure path from %s: %m", path);
@@ -431,19 +431,19 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
if (r < 0)
return log_debug_errno(r, "Error getting memory used from procfs: %m");
} else {
r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.current", &ctx->current_memory_usage);
r = cg_get_attribute_as_uint64(path, "memory.current", &ctx->current_memory_usage);
if (r < 0)
return log_debug_errno(r, "Error getting memory.current from %s: %m", path);
r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.min", &ctx->memory_min);
r = cg_get_attribute_as_uint64(path, "memory.min", &ctx->memory_min);
if (r < 0)
return log_debug_errno(r, "Error getting memory.min from %s: %m", path);
r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.low", &ctx->memory_low);
r = cg_get_attribute_as_uint64(path, "memory.low", &ctx->memory_low);
if (r < 0)
return log_debug_errno(r, "Error getting memory.low from %s: %m", path);
r = cg_get_attribute_as_uint64(SYSTEMD_CGROUP_CONTROLLER, path, "memory.swap.current", &ctx->swap_usage);
r = cg_get_attribute_as_uint64(path, "memory.swap.current", &ctx->swap_usage);
if (r == -ENODATA)
/* The kernel can be compiled without support for memory.swap.* files,
* or it can be disabled with boot param 'swapaccount=0' */
@@ -451,7 +451,7 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
else if (r < 0)
return log_debug_errno(r, "Error getting memory.swap.current from %s: %m", path);
r = cg_get_keyed_attribute(SYSTEMD_CGROUP_CONTROLLER, path, "memory.stat", STRV_MAKE("pgscan"), &val);
r = cg_get_keyed_attribute(path, "memory.stat", STRV_MAKE("pgscan"), &val);
if (r < 0)
return log_debug_errno(r, "Error getting pgscan from memory.stat under %s: %m", path);
+1 -1
View File
@@ -97,7 +97,7 @@ TEST(oomd_cgroup_kill) {
bool empty = false;
for (size_t t = 0; t < 100; t++) {
usleep_safe(100 * USEC_PER_MSEC);
ASSERT_OK(r = cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, subcgroup));
ASSERT_OK(r = cg_is_empty(subcgroup));
if (r > 0) {
empty = true;
break;
+7 -7
View File
@@ -78,7 +78,7 @@ int cg_trim(const char *path, bool delete_root) {
_cleanup_free_ char *fs = NULL;
int r;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -115,7 +115,7 @@ int cg_create(const char *path) {
_cleanup_free_ char *fs = NULL;
int r;
r = cg_get_path_and_check(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -140,7 +140,7 @@ int cg_attach(const char *path, pid_t pid) {
assert(path);
assert(pid >= 0);
r = cg_get_path_and_check(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.procs", &fs);
r = cg_get_path(path, "cgroup.procs", &fs);
if (r < 0)
return r;
@@ -216,7 +216,7 @@ int cg_set_access(
return 0;
/* Configure access to the cgroup itself */
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -289,7 +289,7 @@ int cg_set_access_recursive(
if (!uid_is_valid(uid) && !gid_is_valid(gid))
return 0;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
r = cg_get_path(path, /* suffix = */ NULL, &fs);
if (r < 0)
return r;
@@ -334,7 +334,7 @@ int cg_migrate(
done = true;
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, from, &f);
r = cg_enumerate_processes(from, &f);
if (r < 0)
return RET_GATHER(ret, r);
@@ -396,7 +396,7 @@ int cg_enable(
return 0;
}
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs);
r = cg_get_path(p, "cgroup.subtree_control", &fs);
if (r < 0)
return r;
+12 -21
View File
@@ -87,16 +87,13 @@ static int show_cgroup_one_by_path(
_cleanup_free_ pid_t *pids = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
size_t n = 0;
char *fn;
int r;
r = cg_mangle_path(path, &p);
if (r < 0)
return r;
assert(path);
fn = strjoina(p, "/cgroup.procs");
fn = strjoina(path, "/cgroup.procs");
f = fopen(fn, "re");
if (!f)
return -errno;
@@ -225,7 +222,7 @@ int show_cgroup_by_path(
size_t n_columns,
OutputFlags flags) {
_cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
_cleanup_free_ char *p1 = NULL, *last = NULL, *p2 = NULL;
_cleanup_closedir_ DIR *d = NULL;
bool shown_pids = false;
char *gn = NULL;
@@ -238,23 +235,19 @@ int show_cgroup_by_path(
prefix = strempty(prefix);
r = cg_mangle_path(path, &fn);
if (r < 0)
return r;
d = opendir(fn);
d = opendir(path);
if (!d)
return -errno;
while ((r = cg_read_subgroup(d, &gn)) > 0) {
_cleanup_free_ char *k = NULL;
k = path_join(fn, gn);
k = path_join(path, gn);
free(gn);
if (!k)
return -ENOMEM;
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty(NULL, k) > 0)
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty(path_startswith(k, "/sys/fs/cgroup/")) > 0)
continue;
if (!shown_pids) {
@@ -303,17 +296,17 @@ int show_cgroup_by_path(
return 0;
}
int show_cgroup(const char *controller,
const char *path,
int show_cgroup(const char *path,
const char *prefix,
size_t n_columns,
OutputFlags flags) {
_cleanup_free_ char *p = NULL;
int r;
assert(path);
r = cg_get_path(controller, path, NULL, &p);
r = cg_get_path(path, /* suffix = */ NULL, &p);
if (r < 0)
return r;
@@ -321,7 +314,6 @@ int show_cgroup(const char *controller,
}
static int show_extra_pids(
const char *controller,
const char *path,
const char *prefix,
size_t n_columns,
@@ -350,7 +342,7 @@ static int show_extra_pids(
for (i = 0, j = 0; i < n_pids; i++) {
_cleanup_free_ char *k = NULL;
r = cg_pid_get_path(controller, pids[i], &k);
r = cg_pid_get_path(pids[i], &k);
if (r < 0)
return r;
@@ -366,7 +358,6 @@ static int show_extra_pids(
}
int show_cgroup_and_extra(
const char *controller,
const char *path,
const char *prefix,
size_t n_columns,
@@ -378,11 +369,11 @@ int show_cgroup_and_extra(
assert(path);
r = show_cgroup(controller, path, prefix, n_columns, flags);
r = show_cgroup(path, prefix, n_columns, flags);
if (r < 0)
return r;
return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
return show_extra_pids(path, prefix, n_columns, extra_pids, n_extra_pids, flags);
}
int show_cgroup_get_unit_path_and_warn(
+8 -3
View File
@@ -4,9 +4,14 @@
#include "shared-forward.h"
int show_cgroup_by_path(const char *path, const char *prefix, size_t n_columns, OutputFlags flags);
int show_cgroup(const char *controller, const char *path, const char *prefix, size_t n_columns, OutputFlags flags);
int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, size_t n_columns, const pid_t extra_pids[], size_t n_extra_pids, OutputFlags flags);
int show_cgroup(const char *path, const char *prefix, size_t n_columns, OutputFlags flags);
int show_cgroup_and_extra(
const char *path,
const char *prefix,
size_t n_columns,
const pid_t extra_pids[],
size_t n_extra_pids,
OutputFlags flags);
int show_cgroup_get_unit_path_and_warn(
sd_bus *bus,
+2 -2
View File
@@ -1091,7 +1091,7 @@ static int condition_test_psi(Condition *c, char **env) {
return log_debug_errno(r, "Cannot determine slice \"%s\" cgroup path: %m", slice);
/* We might be running under the user manager, so get the root path and prefix it accordingly. */
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &root_scope);
r = cg_pid_get_path(getpid_cached(), &root_scope);
if (r < 0)
return log_debug_errno(r, "Failed to get root cgroup path: %m");
@@ -1110,7 +1110,7 @@ static int condition_test_psi(Condition *c, char **env) {
free_and_replace(slice_path, slice_joined);
}
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, slice_path, controller, &pressure_path);
r = cg_get_path(slice_path, controller, &pressure_path);
if (r < 0)
return log_debug_errno(r, "Error getting cgroup pressure path from %s: %m", slice_path);
+1 -1
View File
@@ -53,7 +53,7 @@ static bool is_in_survivor_cgroup(const PidRef *pid) {
assert(pidref_is_set(pid));
r = cg_pidref_get_path(/* controller= */ NULL, pid, &cgroup_path);
r = cg_pidref_get_path(pid, &cgroup_path);
if (r == -EUNATCH) {
log_warning_errno(r, "Process " PID_FMT " appears to originate in foreign namespace, ignoring.", pid->pid);
return true;
+9 -3
View File
@@ -213,7 +213,7 @@ static int allocate_scope(void) {
/* Let's try to run this test in a scope of its own, with delegation turned on, so that PID 1 doesn't
* interfere with our cgroup management. */
if (cg_pid_get_path(NULL, 0, &cgroup_root) >= 0 && cg_is_delegated(cgroup_root) && stderr_is_journal()) {
if (cg_pid_get_path(0, &cgroup_root) >= 0 && cg_is_delegated(cgroup_root) && stderr_is_journal()) {
log_debug("Already running as a unit with delegated cgroup, not allocating a cgroup subroot.");
return 0;
}
@@ -287,13 +287,19 @@ static int enter_cgroup(char **ret_cgroup, bool enter_subroot) {
CGroupMask supported;
int r;
r = cg_is_available();
if (r < 0)
return r;
if (r == 0)
return log_warning_errno(SYNTHETIC_ERRNO(ENOMEDIUM), "cgroupfs v2 is not mounted.");
r = allocate_scope();
if (r < 0)
log_warning_errno(r, "Couldn't allocate a scope unit for this test, proceeding without.");
r = cg_pid_get_path(NULL, 0, &cgroup_root);
r = cg_pid_get_path(0, &cgroup_root);
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return log_warning_errno(r, "cg_pid_get_path(NULL, 0, ...) failed: %m");
return log_warning_errno(r, "cg_pid_get_path(0, ...) failed: %m");
ASSERT_OK(r);
if (enter_subroot)
+2 -2
View File
@@ -929,7 +929,7 @@ static void print_status_info(
if (i->control_pid > 0)
extra[k++] = i->control_pid;
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
show_cgroup_and_extra(i->control_group, prefix, c, extra, k, get_output_flags());
} else if (r < 0)
log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
i->id, bus_error_message(&error, r));
@@ -2482,7 +2482,7 @@ static int show_system_status(sd_bus *bus) {
r = unit_show_processes(bus, SPECIAL_ROOT_SLICE, mi.control_group, prefix, c, get_output_flags(), &error);
if (r == -EBADR && arg_transport == BUS_TRANSPORT_LOCAL) /* Compatibility for really old systemd versions */
show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
show_cgroup(strempty(mi.control_group), prefix, c, get_output_flags());
else if (r < 0)
log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
arg_host ?: hn, bus_error_message(&error, r));
+1 -5
View File
@@ -266,10 +266,6 @@ int main(int argc, char *argv[]) {
rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE);
(void) setrlimit(RLIMIT_MEMLOCK, &rl);
r = cg_all_unified();
if (r <= 0)
return log_tests_skipped("We don't seem to be running with unified cgroup hierarchy");
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
@@ -279,7 +275,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
return log_tests_skipped_errno(r, "Failed to prepare cgroup subtree");
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup, NULL, &controller_path);
r = cg_get_path(cgroup, /* suffix = */ NULL, &controller_path);
ASSERT_OK(r);
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
+2 -3
View File
@@ -49,10 +49,9 @@ int main(int argc, char *argv[]) {
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
_cleanup_free_ char *cgroup_path = NULL;
r = enter_cgroup_subroot(&cgroup_path);
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
return log_tests_skipped("cgroupfs v2 is not mounted");
r = find_executable("ping", NULL);
if (r < 0)
-4
View File
@@ -294,10 +294,6 @@ int main(int argc, char *argv[]) {
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
r = cg_all_unified();
if (r <= 0)
return log_tests_skipped("Unified hierarchy is required");
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
+15 -22
View File
@@ -11,11 +11,6 @@
TEST(cg_create) {
int r;
r = cg_unified_cached(false);
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
ASSERT_OK(r);
_cleanup_free_ char *here = NULL;
ASSERT_OK(cg_pid_get_path_shifted(0, NULL, &here));
@@ -43,38 +38,29 @@ TEST(cg_create) {
ASSERT_OK_EQ(cg_create(test_c), 1);
ASSERT_OK_ZERO(cg_create_and_attach(test_b, 0));
ASSERT_OK_ZERO(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path));
ASSERT_OK_ZERO(cg_pid_get_path(getpid_cached(), &path));
ASSERT_STREQ(path, test_b);
free(path);
ASSERT_OK_ZERO(cg_attach(test_a, 0));
ASSERT_OK_ZERO(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path));
ASSERT_OK_ZERO(cg_pid_get_path(getpid_cached(), &path));
ASSERT_TRUE(path_equal(path, test_a));
free(path);
ASSERT_OK_EQ(cg_create_and_attach(test_d, 0), 1);
ASSERT_OK_ZERO(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path));
ASSERT_OK_ZERO(cg_pid_get_path(getpid_cached(), &path));
ASSERT_TRUE(path_equal(path, test_d));
free(path);
ASSERT_OK_ZERO(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, test_d, NULL, &path));
ASSERT_OK_ZERO(cg_get_path(test_d, /* suffix = */ NULL, &path));
log_debug("test_d: %s", path);
const char *full_d;
if (cg_all_unified())
full_d = strjoina("/sys/fs/cgroup", test_d);
else if (cg_hybrid_unified())
full_d = strjoina("/sys/fs/cgroup/unified", test_d);
else
full_d = strjoina("/sys/fs/cgroup/systemd", test_d);
ASSERT_TRUE(path_equal(path, full_d));
ASSERT_TRUE(path_equal(path, strjoina("/sys/fs/cgroup", test_d)));
free(path);
ASSERT_OK_POSITIVE(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, test_a));
ASSERT_OK_ZERO(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, test_b));
ASSERT_OK_POSITIVE(cg_is_empty(NULL, test_a));
ASSERT_OK_POSITIVE(cg_is_empty(NULL, test_b));
ASSERT_OK_POSITIVE(cg_is_empty(test_a));
ASSERT_OK_ZERO(cg_is_empty(test_b));
ASSERT_OK_ZERO(cg_kill_recursive(test_a, 0, 0, NULL, NULL, NULL));
ASSERT_OK_POSITIVE(cg_kill_recursive(test_b, 0, 0, NULL, NULL, NULL));
@@ -86,4 +72,11 @@ TEST(cg_create) {
ASSERT_OK(cg_trim(test_b, true));
}
DEFINE_TEST_MAIN(LOG_DEBUG);
static int intro(void) {
if (cg_is_available() <= 0)
return log_tests_skipped("cgroupfs v2 is not mounted");
return 0;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);
+47 -77
View File
@@ -252,7 +252,7 @@ TEST(proc, .sd_booted = true) {
if (pidref_is_kernel_thread(&pid) != 0)
continue;
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, &pid, &path);
r = cg_pidref_get_path(&pid, &path);
if (r == -ESRCH)
continue;
ASSERT_OK(r);
@@ -322,47 +322,52 @@ TEST(escape, .sd_booted = true) {
test_escape_one(".", "_.");
}
TEST(controller_is_valid) {
assert_se(cg_controller_is_valid("foobar"));
assert_se(cg_controller_is_valid("foo_bar"));
assert_se(cg_controller_is_valid("name=foo"));
assert_se(!cg_controller_is_valid(""));
assert_se(!cg_controller_is_valid("name="));
assert_se(!cg_controller_is_valid("="));
assert_se(!cg_controller_is_valid("cpu,cpuacct"));
assert_se(!cg_controller_is_valid("_"));
assert_se(!cg_controller_is_valid("_foobar"));
assert_se(!cg_controller_is_valid("tatü"));
}
TEST(cg_split_spec) {
char *c, *p;
ASSERT_OK_ZERO(cg_split_spec("foobar:/", &c, &p));
ASSERT_OK(cg_split_spec("foobar:/", &c, &p));
ASSERT_STREQ(c, "foobar");
ASSERT_STREQ(p, "/");
c = mfree(c);
p = mfree(p);
ASSERT_OK_ZERO(cg_split_spec("foobar:", &c, &p));
ASSERT_OK(cg_split_spec("foobar:", &c, &p));
ASSERT_STREQ(c, "foobar");
ASSERT_NULL(p);
c = mfree(c);
ASSERT_OK(cg_split_spec("foobar", &c, &p));
ASSERT_STREQ(c, "foobar");
ASSERT_NULL(p);
c = mfree(c);
ASSERT_OK(cg_split_spec(":///", &c, &p));
ASSERT_STREQ(c, "");
ASSERT_STREQ(p, "/");
c = mfree(c);
p = mfree(p);
ASSERT_FAIL(cg_split_spec("foobar:asdfd", &c, &p));
ASSERT_FAIL(cg_split_spec(":///", &c, &p));
ASSERT_FAIL(cg_split_spec(":", &c, &p));
ASSERT_FAIL(cg_split_spec("", &c, &p));
ASSERT_FAIL(cg_split_spec("fo/obar:/", &c, &p));
ASSERT_OK(cg_split_spec(":", &c, &p));
ASSERT_STREQ(c, "");
ASSERT_NULL(p);
c = mfree(c);
ASSERT_OK(cg_split_spec("", &c, &p));
ASSERT_NULL(c);
ASSERT_NULL(p);
ASSERT_OK(cg_split_spec("fo/obar:/", &c, &p));
ASSERT_STREQ(c, "fo/obar");
ASSERT_STREQ(p, "/");
c = mfree(c);
p = mfree(p);
ASSERT_ERROR(cg_split_spec("foobar:asdfd", &c, &p), EINVAL);
ASSERT_OK(cg_split_spec("/", &c, &p));
ASSERT_NULL(c);
ASSERT_STREQ(p, "/");
p = mfree(p);
ASSERT_OK(cg_split_spec("foo", &c, &p));
ASSERT_STREQ(c, "foo");
ASSERT_NULL(p);
c = mfree(c);
}
static void test_slice_to_path_one(const char *unit, const char *path, int error) {
@@ -428,68 +433,38 @@ TEST(mask_supported, .sd_booted = true) {
yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
}
TEST(cg_tests) {
int all, hybrid, systemd, r;
r = cg_unified();
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
return (void) log_tests_skipped("cgroup not mounted");
assert_se(r >= 0);
all = cg_all_unified();
assert_se(IN_SET(all, 0, 1));
hybrid = cg_hybrid_unified();
assert_se(IN_SET(hybrid, 0, 1));
systemd = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
assert_se(IN_SET(systemd, 0, 1));
if (all) {
assert_se(systemd);
assert_se(!hybrid);
} else if (hybrid) {
assert_se(systemd);
assert_se(!all);
} else
assert_se(!systemd);
}
TEST(cg_get_keyed_attribute) {
_cleanup_free_ char *val = NULL;
char *vals3[3] = {}, *vals3a[3] = {};
int r;
r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val);
if (r == -ENOMEDIUM || ERRNO_IS_PRIVILEGE(r)) {
log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__);
return;
}
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
r = cg_get_keyed_attribute("/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val);
if (ERRNO_IS_PRIVILEGE(r))
return (void) log_tests_skipped_errno(r, "/sys/fs/cgroup not accessible");
assert_se(r == -ENOENT);
ASSERT_NULL(val);
if (access("/sys/fs/cgroup/init.scope/cpu.stat", R_OK) < 0) {
log_info_errno(errno, "Skipping most of %s, /init.scope/cpu.stat not accessible: %m", __func__);
return;
}
if (access("/sys/fs/cgroup/init.scope/cpu.stat", R_OK) < 0)
return (void) log_tests_skipped_errno(errno, "/init.scope/cpu.stat not accessible");
assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO);
assert_se(cg_get_keyed_attribute("/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO);
ASSERT_NULL(val);
assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0);
assert_se(cg_get_keyed_attribute("/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0);
val = mfree(val);
assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO);
assert_se(cg_get_keyed_attribute("/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO);
assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
assert_se(cg_get_keyed_attribute("/init.scope", "cpu.stat",
STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0);
for (size_t i = 0; i < 3; i++)
free(vals3[i]);
assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
assert_se(cg_get_keyed_attribute("/init.scope", "cpu.stat",
STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0);
for (size_t i = 0; i < 3; i++)
free(vals3a[i]);
@@ -508,16 +483,11 @@ TEST(cgroupid) {
_cleanup_free_ char *p = NULL, *p2 = NULL;
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
uint64_t id, id2;
int r;
r = cg_all_unified();
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
if (r == 0)
return (void) log_tests_skipped("skipping cgroupid test, not running in unified mode");
ASSERT_OK_POSITIVE(r);
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
fd = cg_path_open("/");
ASSERT_OK(fd);
ASSERT_OK(fd_get_path(fd, &p));
+4 -11
View File
@@ -131,12 +131,9 @@ TEST(condition_test_control_group_controller) {
Condition *condition;
CGroupMask system_mask;
_cleanup_free_ char *controller_name = NULL;
int r;
r = cg_unified();
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
ASSERT_OK(r);
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
/* Invalid controllers are ignored */
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false)));
@@ -1341,7 +1338,6 @@ TEST(condition_test_os_release) {
TEST(condition_test_psi) {
Condition *condition;
CGroupMask mask;
int r;
if (!is_pressure_supported())
return (void) log_notice("Pressure Stall Information (PSI) is not supported, skipping %s", __func__);
@@ -1426,11 +1422,8 @@ TEST(condition_test_psi) {
ASSERT_OK(condition_test(condition, environ));
condition_free(condition);
r = cg_all_unified();
if (r < 0)
return (void) log_notice("Failed to determine whether the unified cgroups hierarchy is used, skipping %s", __func__);
if (r == 0)
return (void) log_notice("Requires the unified cgroups hierarchy, skipping %s", __func__);
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
if (cg_mask_supported(&mask) < 0)
return (void) log_notice("Failed to get supported cgroup controllers, skipping %s", __func__);
+2 -2
View File
@@ -222,13 +222,13 @@ static int apply_solution_for_path(const char *path, const char *name) {
"\tio.cost.model: %s\n",
path, name, qos, model);
r = cg_set_attribute("io", NULL, "io.cost.qos", qos);
r = cg_set_attribute(/* path = */ NULL, "io.cost.qos", qos);
if (r < 0) {
log_device_full_errno(device, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to set io.cost.qos: %m");
return r == -ENOENT ? 0 : r;
}
r = cg_set_attribute("io", NULL, "io.cost.model", model);
r = cg_set_attribute(/* path = */ NULL, "io.cost.model", model);
if (r < 0) {
log_device_full_errno(device, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to set io.cost.model: %m");
return r == -ENOENT ? 0 : r;
+1 -1
View File
@@ -1452,7 +1452,7 @@ int manager_main(Manager *manager) {
assert(manager);
_cleanup_free_ char *cgroup = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
r = cg_pid_get_path(0, &cgroup);
if (r < 0)
log_debug_errno(r, "Failed to get cgroup, ignoring: %m");
else if (endswith(cgroup, "/udev")) { /* If we are in a subcgroup /udev/ we assume it was delegated to us */