From 4365351b938bd35420e82fb1433d0fcf72063e9a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 07:32:49 +0900 Subject: [PATCH 01/21] cgroup-util: introduce cg_is_available() and check it in tests Now most of our code does not support cgroup v1. Let's skip test cases if we are running on cgroup v1. --- src/basic/cgroup-util.c | 13 +++++++++++++ src/basic/cgroup-util.h | 2 ++ src/libsystemd/sd-bus/test-bus-creds.c | 4 ++-- src/libsystemd/sd-login/test-login.c | 4 ++-- src/shared/tests.c | 6 ++++++ src/test/test-bpf-devices.c | 4 ---- src/test/test-bpf-firewall.c | 5 ++--- src/test/test-bpf-foreign-programs.c | 4 ---- src/test/test-cgroup-setup.c | 23 +++++++++-------------- src/test/test-cgroup-util.c | 24 +++++++++--------------- src/test/test-condition.c | 15 ++++----------- 11 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 97f0bc741f..1251538f0f 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -50,6 +50,19 @@ 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_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 *controller, const char *path) { _cleanup_free_ char *fs = NULL; int r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 8ed8d7704c..fae3709f79 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -135,6 +135,8 @@ typedef enum CGroupUnified { * generate paths with multiple adjacent / removed. */ +int cg_is_available(void); + int cg_path_open(const char *controller, const char *path); int cg_cgroupid_open(int cgroupfs_fd, uint64_t id); diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index 7eb7a38c39..3fa1e66b0a 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -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"); diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c index 98846d1011..7c2b68a5c7 100644 --- a/src/libsystemd/sd-login/test-login.c +++ b/src/libsystemd/sd-login/test-login.c @@ -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; diff --git a/src/shared/tests.c b/src/shared/tests.c index 4eb07b11ff..eed6ea6249 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -287,6 +287,12 @@ 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."); diff --git a/src/test/test-bpf-devices.c b/src/test/test-bpf-devices.c index 74e58fd41d..fb8155c45d 100644 --- a/src/test/test-bpf-devices.c +++ b/src/test/test-bpf-devices.c @@ -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()"); diff --git a/src/test/test-bpf-firewall.c b/src/test/test-bpf-firewall.c index 7f06589907..c3d8e7d5d5 100644 --- a/src/test/test-bpf-firewall.c +++ b/src/test/test-bpf-firewall.c @@ -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) diff --git a/src/test/test-bpf-foreign-programs.c b/src/test/test-bpf-foreign-programs.c index 6ebd807326..bf56451d25 100644 --- a/src/test/test-bpf-foreign-programs.c +++ b/src/test/test-bpf-foreign-programs.c @@ -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"); diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c index ce20c956d2..9f0cee9224 100644 --- a/src/test/test-cgroup-setup.c +++ b/src/test/test-cgroup-setup.c @@ -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)); @@ -61,14 +56,7 @@ TEST(cg_create) { ASSERT_OK_ZERO(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, test_d, 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)); @@ -86,4 +74,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); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 997bcf2215..764e0fb553 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -462,19 +462,18 @@ TEST(cg_get_keyed_attribute) { char *vals3[3] = {}, *vals3a[3] = {}; int r; + if (cg_is_available() <= 0) + return (void) log_tests_skipped("cgroupfs v2 is not mounted"); + 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 (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_NULL(val); @@ -508,14 +507,9 @@ 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, "/"); ASSERT_OK(fd); diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 1bae2e3dd8..efebf6b49a 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -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__); From 5169b1c5a702925b4b6fc86d6a3c7c9bcc223a99 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 05:06:28 +0900 Subject: [PATCH 02/21] cgroup-show: drop 'controller' argument from show_cgroup() and show_cgroup_and_extra() Nowadays these always take SYSTEMD_CGROUP_CONTROLLER as controller. Let's drop it. No functional change, just refactoring. --- src/cgls/cgls.c | 4 ++-- src/login/loginctl.c | 2 +- src/machine/machinectl.c | 2 +- src/shared/cgroup-show.c | 14 ++++++-------- src/shared/cgroup-show.h | 11 ++++++++--- src/systemctl/systemctl-show.c | 4 ++-- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 9e023af031..339f7d5ce4 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -286,7 +286,7 @@ static int run(int argc, char *argv[]) { show_cg_info(controller, path); - q = show_cgroup(controller, path, NULL, 0, arg_output_flags); + q = show_cgroup(path, NULL, 0, arg_output_flags); } failed: @@ -323,7 +323,7 @@ static int run(int argc, char *argv[]) { show_cg_info(SYSTEMD_CGROUP_CONTROLLER, 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) diff --git a/src/login/loginctl.c b/src/login/loginctl.c index c86f694c2b..1a5cbb45e1 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -460,7 +460,7 @@ static int show_unit_cgroup( if (cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, 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)); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 487a50813e..1318f3c6f2 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -455,7 +455,7 @@ static int show_unit_cgroup( if (cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, 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)); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index b97edbdba7..e60cfec854 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -303,17 +303,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(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &p); if (r < 0) return r; @@ -321,7 +321,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 +349,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(SYSTEMD_CGROUP_CONTROLLER, pids[i], &k); if (r < 0) return r; @@ -366,7 +365,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 +376,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( diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index ecff0298ae..27fc878c93 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -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, diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index 2e7d3ffe75..97137ef170 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -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)); From f8de2107a7df00e12be9c1ebce7d520fcdd2df97 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 05:18:55 +0900 Subject: [PATCH 03/21] cgroup-util: drop 'controller' argument from cg_enumerate_processes() Nowadays it always takes SYSTEMD_CGROUP_CONTROLLER as controller. Let's drop it. No functional change, just refactoring. --- src/basic/cgroup-util.c | 6 +++--- src/basic/cgroup-util.h | 2 +- src/cgtop/cgtop.c | 2 +- src/core/cgroup.c | 2 +- src/core/dbus-unit.c | 2 +- src/shared/cgroup-setup.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 1251538f0f..4f8803f732 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -130,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(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.procs", &fs); if (r < 0) return r; @@ -308,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) diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index fae3709f79..621331db06 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -155,7 +155,7 @@ 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); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 19ad6f68a9..78f1968d79 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -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) { diff --git a/src/core/cgroup.c b/src/core/cgroup.c index ce9056ddaf..30e6a4cc77 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index a524cfad22..45dc2fae62 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -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) diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index 323204725f..43962206d2 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -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); From 4d1badbbc4402f3d5b774c35c108df90be2f4cbb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 05:22:21 +0900 Subject: [PATCH 04/21] cgroup-util: drop 'controller' argument from cg_enumerate_subgroups() Nowadays it always takes SYSTEMD_CGROUP_CONTROLLER as controller. Let's drop it. No functional change, just refactoring. --- src/basic/cgroup-util.c | 6 +++--- src/basic/cgroup-util.h | 2 +- src/cgtop/cgtop.c | 2 +- src/core/dbus-unit.c | 2 +- src/oom/oomd-manager.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 4f8803f732..d9b6d68bf7 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -232,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; @@ -241,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(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); if (r < 0) return r; @@ -399,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)); diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 621331db06..206d7ede3f 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -159,7 +159,7 @@ 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); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 78f1968d79..9a3f1a811b 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -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; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 45dc2fae62..493315cf3b 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -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) diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c index 7ff245c437..52ecb17580 100644 --- a/src/oom/oomd-manager.c +++ b/src/oom/oomd-manager.c @@ -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; From 4dbf06bd85804e6564b4ec3f50cd061fad10bc61 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 05:36:21 +0900 Subject: [PATCH 05/21] cgroup-util: drop 'controller' argument from cg_set_attribute(), cg_get_attribute() and friends Non-null controller arguments are always ignored when running on cgroup v2. Let's drop the argument. No functional change, just refactoring. --- src/basic/cgroup-util.c | 16 ++++++++-------- src/basic/cgroup-util.h | 10 +++++----- src/basic/limits-util.c | 6 +++--- src/core/cgroup.c | 16 ++++++++-------- src/oom/oomd-manager.c | 2 +- src/oom/oomd-util.c | 8 ++++---- src/udev/iocost/iocost.c | 4 ++-- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index d9b6d68bf7..1e36b1486a 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1623,13 +1623,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(SYSTEMD_CGROUP_CONTROLLER, path, attribute, &p); if (r < 0) return r; @@ -1641,27 +1641,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(SYSTEMD_CGROUP_CONTROLLER, 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) @@ -1680,11 +1680,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) diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 206d7ede3f..a7fc9d2ba2 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -184,12 +184,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 *controller, const char *path, const char *attribute, char * const *keys, char **values); int cg_get_owner(const char *path, uid_t *ret_uid); diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c index ffa89b0446..0b5dff3946 100644 --- a/src/basic/limits-util.c +++ b/src/basic/limits-util.c @@ -42,7 +42,7 @@ uint64_t physical_memory(void) { return mem; } if (r > 0) { - r = cg_get_attribute("memory", root, "memory.max", &value); + 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 @@ -56,7 +56,7 @@ uint64_t physical_memory(void) { if (streq(value, "max")) return mem; } else { - r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value); + r = cg_get_attribute(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; @@ -159,7 +159,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"); } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 30e6a4cc77..5e81387266 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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; @@ -3538,7 +3538,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 +3581,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) { @@ -4142,7 +4142,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) diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c index 52ecb17580..49c2241bdd 100644 --- a/src/oom/oomd-manager.c +++ b/src/oom/oomd-manager.c @@ -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; diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index 4f9808e5c3..b3cf917fcd 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -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' */ diff --git a/src/udev/iocost/iocost.c b/src/udev/iocost/iocost.c index 7558160d7b..8e2fabbe2c 100644 --- a/src/udev/iocost/iocost.c +++ b/src/udev/iocost/iocost.c @@ -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; From 6475926a59e9d3fee35366df54ce1597af4857fa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 05:43:31 +0900 Subject: [PATCH 06/21] cgroup-util: drop 'controller' argument from cg_path_open() Nowadays it always takes SYSTEMD_CGROUP_CONTROLLER as controller. Let's drop it. No functional change, just refactoring. --- src/basic/cgroup-util.c | 4 ++-- src/basic/cgroup-util.h | 2 +- src/network/networkd-sysctl.c | 4 ++-- src/nspawn/nspawn-cgroup.c | 2 +- src/test/test-cgroup-util.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 1e36b1486a..572ea8c048 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -63,11 +63,11 @@ int cg_is_available(void) { return is_fs_type(&fs, CGROUP2_SUPER_MAGIC); } -int cg_path_open(const char *controller, const char *path) { +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(SYSTEMD_CGROUP_CONTROLLER, path, /* suffix= */ NULL, &fs); if (r < 0) return r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index a7fc9d2ba2..3731b85627 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -137,7 +137,7 @@ typedef enum CGroupUnified { int cg_is_available(void); -int cg_path_open(const char *controller, const char *path); +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); diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index b29d49d79d..9a49335750 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -113,7 +113,7 @@ int manager_install_sysctl_monitor(Manager *manager) { 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"); diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index 7cef863c93..de58ffb6a0 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -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); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 764e0fb553..839bf412dd 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -511,7 +511,7 @@ TEST(cgroupid) { 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)); From b525a72f7bd10c27c672fd8d78322a3e40255842 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 06:32:56 +0900 Subject: [PATCH 07/21] cgroup-util: drop cgroup v1 support from cg_pid_get_path() We have dropped cgroup v1 support in v258. Let's drop legacy code. Then, we can drop 'controller' argument from cg_pid_get_path() and cg_pidref_get_path(). --- src/basic/cgroup-util.c | 63 ++++++------------------------ src/basic/cgroup-util.h | 4 +- src/core/cgroup.c | 4 +- src/core/dbus-unit.c | 2 +- src/coredump/coredump-send.c | 2 +- src/libsystemd/sd-bus/bus-creds.c | 2 +- src/libsystemd/sd-event/sd-event.c | 2 +- src/libsystemd/sd-login/sd-login.c | 4 +- src/machine/machined-dbus.c | 2 +- src/network/networkd-sysctl.c | 2 +- src/nspawn/nspawn-cgroup.c | 6 +-- src/shared/cgroup-show.c | 2 +- src/shared/condition.c | 2 +- src/shared/killall.c | 2 +- src/shared/tests.c | 6 +-- src/test/test-cgroup-setup.c | 6 +-- src/test/test-cgroup-util.c | 2 +- src/udev/udev-manager.c | 2 +- 18 files changed, 39 insertions(+), 76 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 572ea8c048..a4e7c069b3 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -659,30 +659,14 @@ int cg_remove_xattr(const char *path, const char *name) { 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) @@ -700,34 +684,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) @@ -747,7 +710,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; @@ -762,7 +725,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; @@ -880,7 +843,7 @@ int cg_get_root_path(char **ret_path) { 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; @@ -922,7 +885,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; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 3731b85627..6f36194403 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -174,8 +174,8 @@ 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_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); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 5e81387266..7279682b63 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -3260,7 +3260,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 +3404,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); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 493315cf3b..ed4646f75a 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -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) diff --git a/src/coredump/coredump-send.c b/src/coredump/coredump-send.c index 6316511bad..eadec5f0f5 100644 --- a/src/coredump/coredump-send.c +++ b/src/coredump/coredump-send.c @@ -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"); diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 86f1b70f95..2bbbd0f484 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -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; } diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 044cdf246d..c9d14ebf17 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -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; diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 133e97b432..b559b4576b 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -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; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 1619d3fd6b..0f1ac1776a 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -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", diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 9a49335750..8131658829 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -109,7 +109,7 @@ 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."); diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index de58ffb6a0..caa55186ef 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -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"); @@ -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"); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index e60cfec854..ea419fd5d0 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -349,7 +349,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(SYSTEMD_CGROUP_CONTROLLER, pids[i], &k); + r = cg_pid_get_path(pids[i], &k); if (r < 0) return r; diff --git a/src/shared/condition.c b/src/shared/condition.c index b09eff1bfb..a998c049cc 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -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"); diff --git a/src/shared/killall.c b/src/shared/killall.c index 0a41d251ef..729e0e2480 100644 --- a/src/shared/killall.c +++ b/src/shared/killall.c @@ -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; diff --git a/src/shared/tests.c b/src/shared/tests.c index eed6ea6249..53dda342a4 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -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; } @@ -297,9 +297,9 @@ static int enter_cgroup(char **ret_cgroup, bool enter_subroot) { 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) diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c index 9f0cee9224..195677bf0e 100644 --- a/src/test/test-cgroup-setup.c +++ b/src/test/test-cgroup-setup.c @@ -38,19 +38,19 @@ 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); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 839bf412dd..6f84f9300b 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -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); diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index a7118055d1..0dac43a3fb 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -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 */ From 0ab90015e06d299afaff5474fb71c61f5f150bf6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 06:38:14 +0900 Subject: [PATCH 08/21] tree-wide: replace cg_get_path_and_check() with cg_get_path() We have dropped cgroup v1 support in v258. When running on cgroup v2, cg_get_path_and_check() with SYSTEMD_CGROUP_CONTROLLER as controller is equivalent with checking if we are running on cgroup v2 and then cg_get_path(). As we can assume we are running on cgroup v2, then the check is not necessary anymore, thus we can replace cg_get_path_and_check() with cg_get_path(). --- src/basic/cgroup-util.c | 27 --------------------------- src/basic/cgroup-util.h | 1 - src/basic/process-util.c | 6 +----- src/shared/cgroup-setup.c | 4 ++-- 4 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index a4e7c069b3..91c230208d 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -575,33 +575,6 @@ static int controller_is_v1_accessible(const char *root, const char *controller) 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; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 6f36194403..27fa4cd2d7 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -172,7 +172,6 @@ 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_pid_get_path(pid_t pid, char **ret); int cg_pidref_get_path(const PidRef *pidref, char **ret); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 35d3f8bfd9..900e885bfa 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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(SYSTEMD_CGROUP_CONTROLLER, cgroup, /* suffix= */ NULL, &resolved_cgroup); if (r < 0) return r; diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index 43962206d2..e0fddd7973 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -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(SYSTEMD_CGROUP_CONTROLLER, path, 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(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.procs", &fs); if (r < 0) return r; From 57c16d344b6fcdf34de1141f3fbb9dcfa3bfd3ee Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 06:57:13 +0900 Subject: [PATCH 09/21] cgroup-util: drop cgroup v1 support from cg_mask_supported_subtree() We have dropped cgroup v1 support in v258. Let's drop unused legacy code. --- src/basic/cgroup-util.c | 63 +++++++---------------------------------- 1 file changed, 11 insertions(+), 52 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 91c230208d..f811be5a91 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -560,21 +560,6 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch 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_set_xattr(const char *path, const char *name, const void *value, size_t size, int flags) { _cleanup_free_ char *fs = NULL; int r; @@ -1814,48 +1799,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(SYSTEMD_CGROUP_CONTROLLER, 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; From f5a48af34b508ec52b1a1da2663aefc29921d121 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 06:59:58 +0900 Subject: [PATCH 10/21] cgroup-util: use cg_is_available() in cg_kill_supported() --- src/basic/cgroup-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index f811be5a91..16a963843b 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -222,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) From 2d6dd692beb67b9167d8f7eff91c83d8c9fcdc4e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 07:03:03 +0900 Subject: [PATCH 11/21] cgroup-util: drop cgroup v1 support in cg_get_path() We have dropped cgroup v1 support in v258. Let's assume we are running on cgroup v2 and drop unused legacy code. --- src/basic/cgroup-util.c | 102 ++++------------------------------------ 1 file changed, 8 insertions(+), 94 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 16a963843b..ad130a5334 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -455,108 +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 *controller, 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 + if (isempty(path)) + path = TAKE_PTR(suffix); + + if (controller) t = path_join("/sys/fs/cgroup", path, suffix); + else + t = path_join(path, suffix); if (!t) return -ENOMEM; - *ret = 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); + *ret = path_simplify(t); return 0; } From 2fe89e3b0f760eac73d7b27e27bf0746ccc3a5a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 07:16:09 +0900 Subject: [PATCH 12/21] limits-util: drop cgroup v1 support from physical_memory() --- src/basic/limits-util.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c index 0b5dff3946..d48d67dbf7 100644 --- a/src/basic/limits-util.c +++ b/src/basic/limits-util.c @@ -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(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(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) { From 90ee92b073f4572c6a08fbcbad10238f12b3a41b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 07:51:06 +0900 Subject: [PATCH 13/21] cgls: drop cgroup v1 support and warn when cgroup v1 controller is specified --- src/cgls/cgls.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 339f7d5ce4..17c29d38c1 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -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); } @@ -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,7 +282,7 @@ static int run(int argc, char *argv[]) { } else path = root; - show_cg_info(controller, path); + show_cg_info(path); q = show_cgroup(path, NULL, 0, arg_output_flags); } @@ -320,7 +318,7 @@ 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(root, NULL, 0, arg_output_flags); From 3454b160e4b11aa96a8adef89346af2a45dbf1e8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 07:54:19 +0900 Subject: [PATCH 14/21] cgroup-util: drop unused cg_unified() and friends --- src/basic/cgroup-util.c | 109 ------------------------------------ src/basic/cgroup-util.h | 15 ----- src/test/test-cgroup-util.c | 29 ---------- 3 files changed, 153 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index ad130a5334..c31f2a1b05 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1745,115 +1745,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; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 27fa4cd2d7..ac02d68dcd 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -113,13 +113,6 @@ 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: * @@ -261,14 +254,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_; diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 6f84f9300b..823a4d403b 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -428,35 +428,6 @@ 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] = {}; From 5d397dc7f48edbc463cdd021d12ebce910713a11 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 08:29:37 +0900 Subject: [PATCH 15/21] cgroup-util: drop 'controller' argument from cg_get_keyed_attribute() and cg_is_empty() The argument is completely unused. Let's drop it. --- src/basic/cgroup-util.c | 7 +++---- src/basic/cgroup-util.h | 4 ++-- src/cgtop/cgtop.c | 2 +- src/core/cgroup.c | 8 ++------ src/core/service.c | 2 +- src/login/loginctl.c | 2 +- src/machine/machine.c | 4 ++-- src/machine/machinectl.c | 2 +- src/oom/oomd-util.c | 2 +- src/oom/test-oomd-util.c | 2 +- src/shared/cgroup-show.c | 2 +- src/test/test-cgroup-setup.c | 6 ++---- src/test/test-cgroup-util.c | 12 ++++++------ 13 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index c31f2a1b05..b01b7b6a3f 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -610,7 +610,7 @@ int cg_pidref_get_path(const PidRef *pidref, char **ret_path) { 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; @@ -623,7 +623,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) @@ -1551,7 +1551,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, @@ -1570,7 +1569,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(SYSTEMD_CGROUP_CONTROLLER, path, attribute, &filename); if (r < 0) return r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index ac02d68dcd..9c534ac594 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -181,7 +181,7 @@ 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_keyed_attribute(const char *controller, const char *path, const char *attribute, char * const *keys, char **values); +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); @@ -191,7 +191,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); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 9a3f1a811b..99f1fe22ae 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -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) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7279682b63..6f3e61ea3a 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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; @@ -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"), @@ -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; @@ -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"), diff --git a/src/core/service.c b/src/core/service.c index c92fb45085..59a81028e6 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -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; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 1a5cbb45e1..fa406cfd74 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -457,7 +457,7 @@ 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(cgroup, prefix, c, &leader, leader > 0, get_output_flags()); diff --git a/src/machine/machine.c b/src/machine/machine.c index f097bfe380..0eb854f4ab 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -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); @@ -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) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 1318f3c6f2..cf8f7d48b9 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -452,7 +452,7 @@ 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(cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags()); diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index b3cf917fcd..fcd00f8c16 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -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); diff --git a/src/oom/test-oomd-util.c b/src/oom/test-oomd-util.c index abb5c2ccd8..7e68525ba0 100644 --- a/src/oom/test-oomd-util.c +++ b/src/oom/test-oomd-util.c @@ -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; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index ea419fd5d0..6a591d7192 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -254,7 +254,7 @@ int show_cgroup_by_path( 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) { diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c index 195677bf0e..5c162bbbf3 100644 --- a/src/test/test-cgroup-setup.c +++ b/src/test/test-cgroup-setup.c @@ -59,10 +59,8 @@ TEST(cg_create) { 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)); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 823a4d403b..bdc85adc89 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -436,7 +436,7 @@ TEST(cg_get_keyed_attribute) { if (cg_is_available() <= 0) return (void) log_tests_skipped("cgroupfs v2 is not mounted"); - r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val); + 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"); @@ -446,20 +446,20 @@ TEST(cg_get_keyed_attribute) { 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]); From a8156588fa1bc2e0f954ff2ecca562b308c3383c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 08:38:59 +0900 Subject: [PATCH 16/21] cgroup-util: drop 'controller' argument from cg_get_path() The argument is not used anymore. Let's drop it. --- src/basic/cgroup-util.c | 41 ++++++++++++++++------------------ src/basic/cgroup-util.h | 2 +- src/basic/process-util.c | 2 +- src/cgtop/cgtop.c | 6 ++--- src/core/bpf-devices.c | 2 +- src/core/bpf-firewall.c | 2 +- src/core/bpf-foreign.c | 2 +- src/core/bpf-restrict-ifaces.c | 2 +- src/core/bpf-socket-bind.c | 2 +- src/core/cgroup.c | 10 ++++----- src/core/exec-invoke.c | 4 ++-- src/machine/machine.c | 2 +- src/nspawn/nspawn-cgroup.c | 2 +- src/oom/oomd-util.c | 4 ++-- src/shared/cgroup-setup.c | 12 +++++----- src/shared/cgroup-show.c | 2 +- src/shared/condition.c | 2 +- src/test/test-bpf-devices.c | 2 +- src/test/test-cgroup-setup.c | 2 +- 19 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index b01b7b6a3f..2dfc9188fe 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -67,7 +67,7 @@ int cg_path_open(const char *path) { _cleanup_free_ char *fs = NULL; int r; - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, /* suffix= */ NULL, &fs); + r = cg_get_path(path, /* suffix= */ NULL, &fs); if (r < 0) return r; @@ -137,7 +137,7 @@ int cg_enumerate_processes(const char *path, FILE **ret) { assert(ret); - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, "cgroup.procs", &fs); + r = cg_get_path(path, "cgroup.procs", &fs); if (r < 0) return r; @@ -241,7 +241,7 @@ int cg_enumerate_subgroups(const char *path, DIR **ret) { /* This is not recursive! */ - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); + r = cg_get_path(path, /* suffix = */ NULL, &fs); if (r < 0) return r; @@ -444,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; @@ -455,7 +455,7 @@ int cg_kill_kernel_sigkill(const char *path) { return 0; } -int cg_get_path(const char *controller, const char *path, const char *suffix, char **ret) { +int cg_get_path(const char *path, const char *suffix, char **ret) { char *t; assert(ret); @@ -463,10 +463,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (isempty(path)) path = TAKE_PTR(suffix); - if (controller) - t = path_join("/sys/fs/cgroup", path, suffix); - else - t = path_join(path, suffix); + t = path_join("/sys/fs/cgroup", path, suffix); if (!t) return -ENOMEM; @@ -482,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; @@ -496,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; @@ -510,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; @@ -524,7 +521,7 @@ 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; @@ -691,7 +688,7 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { } int cg_mangle_path(const char *path, char **ret) { - _cleanup_free_ char *c = NULL, *p = NULL; + _cleanup_free_ char *p = NULL; int r; assert(path); @@ -702,11 +699,11 @@ int cg_mangle_path(const char *path, char **ret) { return path_simplify_alloc(path, ret); /* Otherwise, treat it as cg spec */ - r = cg_split_spec(path, &c, &p); + r = cg_split_spec(path, /* ret_controller = */ NULL, &p); if (r < 0) return r; - return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, ret); + return cg_get_path(p, /* suffix = */ NULL, ret); } int cg_get_root_path(char **ret_path) { @@ -1439,7 +1436,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; @@ -1464,7 +1461,7 @@ int cg_set_attribute(const char *path, const char *attribute, const char *value) assert(attribute); - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, attribute, &p); + r = cg_get_path(path, attribute, &p); if (r < 0) return r; @@ -1482,7 +1479,7 @@ int cg_get_attribute(const char *path, const char *attribute, char **ret) { assert(attribute); - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, attribute, &p); + r = cg_get_path(path, attribute, &p); if (r < 0) return r; @@ -1535,7 +1532,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; @@ -1569,7 +1566,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(SYSTEMD_CGROUP_CONTROLLER, path, attribute, &filename); + r = cg_get_path(path, attribute, &filename); if (r < 0) return r; @@ -1714,7 +1711,7 @@ int cg_mask_supported_subtree(const char *root, CGroupMask *ret) { /* 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(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path); + r = cg_get_path(root, "cgroup.controllers", &path); if (r < 0) return r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 9c534ac594..b25660c086 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -164,7 +164,7 @@ int cg_kill_recursive(const char *path, int sig, CGroupFlags flags, Set *killed_ 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(const char *path, const char *suffix, char **ret); int cg_pid_get_path(pid_t pid, char **ret); int cg_pidref_get_path(const PidRef *pidref, char **ret); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 900e885bfa..5759de38f4 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -2146,7 +2146,7 @@ int posix_spawn_wrapper( if (cgroup && have_clone_into_cgroup) { _cleanup_free_ char *resolved_cgroup = NULL; - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup, /* suffix= */ NULL, &resolved_cgroup); + r = cg_get_path(cgroup, /* suffix= */ NULL, &resolved_cgroup); if (r < 0) return r; diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 99f1fe22ae..87806caeba 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -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; @@ -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; diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c index ef8ba3d572..71ffd04898 100644 --- a/src/core/bpf-devices.c +++ b/src/core/bpf-devices.c @@ -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"); diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index fce885da87..b2a4cd6e27 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -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"); diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 2e8c07978c..1da16a7b8d 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -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"); diff --git a/src/core/bpf-restrict-ifaces.c b/src/core/bpf-restrict-ifaces.c index 0c66ae0630..a0ed94ce3a 100644 --- a/src/core/bpf-restrict-ifaces.c +++ b/src/core/bpf-restrict-ifaces.c @@ -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"); diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 1fc73c19ab..1cba47306d 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -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"); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 6f3e61ea3a..7242734e5a 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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) @@ -3769,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; @@ -4107,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; diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 88178a82f9..97a7107384 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -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(); diff --git a/src/machine/machine.c b/src/machine/machine.c index 0eb854f4ab..5cbe076506 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -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); diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index caa55186ef..db99b7d846 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -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"); diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index fcd00f8c16..e463ce01f2 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -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); diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index e0fddd7973..a334805871 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -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(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(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; @@ -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; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 6a591d7192..47ffaf725f 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -313,7 +313,7 @@ int show_cgroup(const char *path, assert(path); - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &p); + r = cg_get_path(path, /* suffix = */ NULL, &p); if (r < 0) return r; diff --git a/src/shared/condition.c b/src/shared/condition.c index a998c049cc..186f0b6c4a 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -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); diff --git a/src/test/test-bpf-devices.c b/src/test/test-bpf-devices.c index fb8155c45d..78e7487655 100644 --- a/src/test/test-bpf-devices.c +++ b/src/test/test-bpf-devices.c @@ -275,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; diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c index 5c162bbbf3..ae33e1fcd1 100644 --- a/src/test/test-cgroup-setup.c +++ b/src/test/test-cgroup-setup.c @@ -54,7 +54,7 @@ TEST(cg_create) { 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); ASSERT_TRUE(path_equal(path, strjoina("/sys/fs/cgroup", test_d))); free(path); From 6a8ab5f062ca8ee81fbfe6e89c67b789852e9dff Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 09:52:14 +0900 Subject: [PATCH 17/21] cgroup-show: drop unnecessary call of cg_mangle_path() As the caller already dropped controller part. --- src/basic/cgroup-util.c | 19 ------------------- src/basic/cgroup-util.h | 1 - src/cgls/cgls.c | 2 +- src/shared/cgroup-show.c | 17 +++++------------ 4 files changed, 6 insertions(+), 33 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 2dfc9188fe..90069684c4 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -687,25 +687,6 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { return 0; } -int cg_mangle_path(const char *path, char **ret) { - _cleanup_free_ char *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, /* ret_controller = */ NULL, &p); - if (r < 0) - return r; - - return cg_get_path(p, /* suffix = */ NULL, ret); -} - int cg_get_root_path(char **ret_path) { char *p, *e; int r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index b25660c086..59f27a7248 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -162,7 +162,6 @@ 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 *path, const char *suffix, char **ret); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 17c29d38c1..c224a892e4 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -244,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")) { diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 47ffaf725f..94b8d15bec 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -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,18 +235,14 @@ 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; From b9e612e070fd766c63b933c2a17c49b053c16111 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 22:25:22 +0900 Subject: [PATCH 18/21] cgroup-util: do not check validity of controller in cg_split_spec() Now the controller part is always ignored, hence let's skip check for the controller part of the spec. This also make it acceppt unnormalized path. Previously paths were checked by path_is_normalized(), but now checked by path_is_safe(). Also, now this mapps an empty path to NULL. --- src/basic/cgroup-util.c | 116 ++++++++++++++---------------------- src/basic/cgroup-util.h | 2 - src/test/test-cgroup-util.c | 55 +++++++++-------- 3 files changed, 75 insertions(+), 98 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 90069684c4..207f5428b7 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -630,60 +630,64 @@ int cg_is_empty(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; } @@ -1314,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; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 59f27a7248..7be0de18bf 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -242,8 +242,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); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index bdc85adc89..0fd81284e8 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -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) { From 4434fd76f124f48d351ed2a46b3a2ad07a42af70 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 22:28:33 +0900 Subject: [PATCH 19/21] cgroup-util: drop unused SYSTEMD_CGROUP_CONTROLLER_{LEGACY,HYBRID} --- src/basic/cgroup-util.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 7be0de18bf..3e9c714c69 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -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 */ From 44440ea65821192e661f0458ffa2ff4b92f43d69 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 30 Aug 2025 10:26:10 +0900 Subject: [PATCH 20/21] cgroup-util: drop outdated comments --- src/basic/cgroup-util.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 3e9c714c69..f494617ffa 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -114,14 +114,6 @@ static inline uint64_t BFQ_WEIGHT(uint64_t io_weight) { /* * 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. */ From d32ec012232e830c54c7a79e054da19d27ebacef Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 16 Nov 2025 04:39:13 +0900 Subject: [PATCH 21/21] shell-completion: drop deprecated cgroup controller suggestion --- shell-completion/bash/systemd-cgtop | 4 +--- shell-completion/zsh/_systemd | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/shell-completion/bash/systemd-cgtop b/shell-completion/bash/systemd-cgtop index a444b65064..325aa60de7 100644 --- a/shell-completion/bash/systemd-cgtop +++ b/shell-completion/bash/systemd-cgtop @@ -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 } diff --git a/shell-completion/zsh/_systemd b/shell-completion/zsh/_systemd index 4d9ec7f032..f555abd06b 100644 --- a/shell-completion/zsh/_systemd +++ b/shell-completion/zsh/_systemd @@ -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 \