From: Yu Watanabe Date: Fri, 29 Aug 2025 22:32:49 +0000 (+0900) Subject: cgroup-util: introduce cg_is_available() and check it in tests X-Git-Tag: v259-rc1~18^2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4365351b938bd35420e82fb1433d0fcf72063e9a;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 97f0bc741fd..1251538f0f7 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 8ed8d7704cd..fae3709f79a 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 7eb7a38c39d..3fa1e66b0a0 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 98846d1011e..7c2b68a5c78 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 4eb07b11ff7..eed6ea62493 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 74e58fd41dd..fb8155c45db 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 7f065899075..c3d8e7d5d54 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 6ebd807326a..bf56451d250 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 ce20c956d2f..9f0cee9224e 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 997bcf22155..764e0fb5533 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 1bae2e3dd83..efebf6b49af 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__);