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.
This commit is contained in:
Yu Watanabe
2025-11-17 21:29:51 +09:00
parent bc154d4c3e
commit 4365351b93
11 changed files with 49 additions and 55 deletions
+13
View File
@@ -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;
+2
View File
@@ -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);
+2 -2
View File
@@ -13,8 +13,8 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
if (IN_SET(cg_unified(), -ENOMEDIUM, -ENOENT))
return log_tests_skipped("/sys/fs/cgroup/ not available");
if (cg_is_available() <= 0)
return log_tests_skipped("cgroupfs v2 is not mounted");
r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
+2 -2
View File
@@ -327,8 +327,8 @@ TEST(monitor) {
}
static int intro(void) {
if (IN_SET(cg_unified(), -ENOENT, -ENOMEDIUM))
return log_tests_skipped("cgroupfs is not mounted");
if (cg_is_available() <= 0)
return log_tests_skipped("cgroupfs v2 is not mounted");
log_info("/* Information printed is from the live system */");
return EXIT_SUCCESS;
+6
View File
@@ -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.");
-4
View File
@@ -266,10 +266,6 @@ int main(int argc, char *argv[]) {
rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE);
(void) setrlimit(RLIMIT_MEMLOCK, &rl);
r = cg_all_unified();
if (r <= 0)
return log_tests_skipped("We don't seem to be running with unified cgroup hierarchy");
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
+2 -3
View File
@@ -49,10 +49,9 @@ int main(int argc, char *argv[]) {
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
_cleanup_free_ char *cgroup_path = NULL;
r = enter_cgroup_subroot(&cgroup_path);
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
return log_tests_skipped("cgroupfs v2 is not mounted");
r = find_executable("ping", NULL);
if (r < 0)
-4
View File
@@ -294,10 +294,6 @@ int main(int argc, char *argv[]) {
if (!can_memlock())
return log_tests_skipped("Can't use mlock()");
r = cg_all_unified();
if (r <= 0)
return log_tests_skipped("Unified hierarchy is required");
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
+9 -14
View File
@@ -11,11 +11,6 @@
TEST(cg_create) {
int r;
r = cg_unified_cached(false);
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
ASSERT_OK(r);
_cleanup_free_ char *here = NULL;
ASSERT_OK(cg_pid_get_path_shifted(0, NULL, &here));
@@ -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);
+9 -15
View File
@@ -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);
+4 -11
View File
@@ -131,12 +131,9 @@ TEST(condition_test_control_group_controller) {
Condition *condition;
CGroupMask system_mask;
_cleanup_free_ char *controller_name = NULL;
int r;
r = cg_unified();
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
ASSERT_OK(r);
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
/* Invalid controllers are ignored */
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false)));
@@ -1341,7 +1338,6 @@ TEST(condition_test_os_release) {
TEST(condition_test_psi) {
Condition *condition;
CGroupMask mask;
int r;
if (!is_pressure_supported())
return (void) log_notice("Pressure Stall Information (PSI) is not supported, skipping %s", __func__);
@@ -1426,11 +1422,8 @@ TEST(condition_test_psi) {
ASSERT_OK(condition_test(condition, environ));
condition_free(condition);
r = cg_all_unified();
if (r < 0)
return (void) log_notice("Failed to determine whether the unified cgroups hierarchy is used, skipping %s", __func__);
if (r == 0)
return (void) log_notice("Requires the unified cgroups hierarchy, skipping %s", __func__);
if (cg_is_available() <= 0)
return (void) log_tests_skipped("cgroupfs v2 is not mounted");
if (cg_mask_supported(&mask) < 0)
return (void) log_notice("Failed to get supported cgroup controllers, skipping %s", __func__);