linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core
@ 2025-06-17 13:36 Michal Koutný
  2025-06-17 13:36 ` [PATCH 1/4] selftests: cgroup_util: Add helpers for testing named v1 hierarchies Michal Koutný
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Michal Koutný @ 2025-06-17 13:36 UTC (permalink / raw)
  To: linux-kernel, cgroups, linux-kselftest
  Cc: Michal Koutný, Johannes Weiner, Tejun Heo, Shuah Khan

This comes useful when using selftests from mainline on older
kernels/setups that still rely on cgroup v1 while maintains single
variant of selftests.
The core tests that rely on v2 specific features are skipped, the
remaining ones are adjusted to work with a v1 hierarchy.

The expected output on v1 system:
    ok 1 # SKIP test_cgcore_internal_process_constraint
    ok 2 # SKIP test_cgcore_top_down_constraint_enable
    ok 3 # SKIP test_cgcore_top_down_constraint_disable
    ok 4 # SKIP test_cgcore_no_internal_process_constraint_on_threads
    ok 5 # SKIP test_cgcore_parent_becomes_threaded
    ok 6 # SKIP test_cgcore_invalid_domain
    ok 7 # SKIP test_cgcore_populated
    ok 8 test_cgcore_proc_migration
    ok 9 test_cgcore_thread_migration
    ok 10 test_cgcore_destroy
    ok 11 test_cgcore_lesser_euid_open
    ok 12 # SKIP test_cgcore_lesser_ns_open

Michal Koutný (4):
  selftests: cgroup_util: Add helpers for testing named v1 hierarchies
  selftests: cgroup: Add support for named v1 hierarchies in test_core
  selftests: cgroup: Optionally set up v1 environment
  selftests: cgroup: Fix compilation on pre-cgroupns kernels

 .../selftests/cgroup/lib/cgroup_util.c        |  4 +-
 .../cgroup/lib/include/cgroup_util.h          |  5 ++
 tools/testing/selftests/cgroup/test_core.c    | 84 ++++++++++++++++---
 3 files changed, 82 insertions(+), 11 deletions(-)


base-commit: 9afe652958c3ee88f24df1e4a97f298afce89407
-- 
2.49.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] selftests: cgroup_util: Add helpers for testing named v1 hierarchies
  2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
@ 2025-06-17 13:36 ` Michal Koutný
  2025-06-17 13:36 ` [PATCH 2/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Michal Koutný @ 2025-06-17 13:36 UTC (permalink / raw)
  To: cgroups, linux-kselftest, linux-kernel
  Cc: Michal Koutný, Tejun Heo, Johannes Weiner, Shuah Khan

Non-functional change, the control variable will be wired in a separate
commit.

Signed-off-by: Michal Koutný <mkoutny@suse.com>
---
 tools/testing/selftests/cgroup/lib/cgroup_util.c         | 4 +++-
 tools/testing/selftests/cgroup/lib/include/cgroup_util.h | 5 +++++
 tools/testing/selftests/cgroup/test_core.c               | 6 +++---
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/cgroup/lib/cgroup_util.c b/tools/testing/selftests/cgroup/lib/cgroup_util.c
index 8832f3d1cb614..0e89fcff4d05d 100644
--- a/tools/testing/selftests/cgroup/lib/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/lib/cgroup_util.c
@@ -19,6 +19,8 @@
 #include "cgroup_util.h"
 #include "../../clone3/clone3_selftests.h"
 
+bool cg_test_v1_named;
+
 /* Returns read len on success, or -errno on failure. */
 ssize_t read_text(const char *path, char *buf, size_t max_len)
 {
@@ -361,7 +363,7 @@ int cg_enter_current(const char *cgroup)
 
 int cg_enter_current_thread(const char *cgroup)
 {
-	return cg_write(cgroup, "cgroup.threads", "0");
+	return cg_write(cgroup, CG_THREADS_FILE, "0");
 }
 
 int cg_run(const char *cgroup,
diff --git a/tools/testing/selftests/cgroup/lib/include/cgroup_util.h b/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
index adb2bc1931839..c69cab66254b4 100644
--- a/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
+++ b/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
@@ -13,6 +13,10 @@
 
 #define TEST_UID	65534 /* usually nobody, any !root is fine */
 
+#define CG_THREADS_FILE (!cg_test_v1_named ? "cgroup.threads" : "tasks")
+#define CG_NAMED_NAME "selftest"
+#define CG_PATH_FORMAT (!cg_test_v1_named ? "0::%s" : (":name=" CG_NAMED_NAME ":%s"))
+
 /*
  * Checks if two given values differ by less than err% of their sum.
  */
@@ -65,3 +69,4 @@ extern int dirfd_open_opath(const char *dir);
 extern int cg_prepare_for_wait(const char *cgroup);
 extern int memcg_prepare_for_wait(const char *cgroup);
 extern int cg_wait_for(int fd);
+extern bool cg_test_v1_named;
diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index a5672a91d273c..0c4cc4e5fc8c2 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -573,7 +573,7 @@ static int test_cgcore_proc_migration(const char *root)
 	}
 
 	cg_enter_current(dst);
-	if (cg_read_lc(dst, "cgroup.threads") != n_threads + 1)
+	if (cg_read_lc(dst, CG_THREADS_FILE) != n_threads + 1)
 		goto cleanup;
 
 	ret = KSFT_PASS;
@@ -605,7 +605,7 @@ static void *migrating_thread_fn(void *arg)
 	char lines[3][PATH_MAX];
 
 	for (g = 1; g < 3; ++g)
-		snprintf(lines[g], sizeof(lines[g]), "0::%s", grps[g] + strlen(grps[0]));
+		snprintf(lines[g], sizeof(lines[g]), CG_PATH_FORMAT, grps[g] + strlen(grps[0]));
 
 	for (i = 0; i < n_iterations; ++i) {
 		cg_enter_current_thread(grps[(i % 2) + 1]);
@@ -659,7 +659,7 @@ static int test_cgcore_thread_migration(const char *root)
 	if (retval)
 		goto cleanup;
 
-	snprintf(line, sizeof(line), "0::%s", grps[1] + strlen(grps[0]));
+	snprintf(line, sizeof(line), CG_PATH_FORMAT, grps[1] + strlen(grps[0]));
 	if (proc_read_strstr(0, 1, "cgroup", line))
 		goto cleanup;
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] selftests: cgroup: Add support for named v1 hierarchies in test_core
  2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
  2025-06-17 13:36 ` [PATCH 1/4] selftests: cgroup_util: Add helpers for testing named v1 hierarchies Michal Koutný
@ 2025-06-17 13:36 ` Michal Koutný
  2025-06-17 13:36 ` [PATCH 3/4] selftests: cgroup: Optionally set up v1 environment Michal Koutný
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Michal Koutný @ 2025-06-17 13:36 UTC (permalink / raw)
  To: cgroups, linux-kselftest, linux-kernel
  Cc: Michal Koutný, Tejun Heo, Johannes Weiner, Shuah Khan

This comes useful when using selftests from mainline on older
kernels/setups that still rely on cgroup v1.
The core tests that rely on v2 specific features are skipped, the
remaining ones are adjusted to work with a v1 hierarchy.

The expected output on v1 system:
	ok 1 # SKIP test_cgcore_internal_process_constraint
	ok 2 # SKIP test_cgcore_top_down_constraint_enable
	ok 3 # SKIP test_cgcore_top_down_constraint_disable
	ok 4 # SKIP test_cgcore_no_internal_process_constraint_on_threads
	ok 5 # SKIP test_cgcore_parent_becomes_threaded
	ok 6 # SKIP test_cgcore_invalid_domain
	ok 7 # SKIP test_cgcore_populated
	ok 8 test_cgcore_proc_migration
	ok 9 test_cgcore_thread_migration
	ok 10 test_cgcore_destroy
	ok 11 test_cgcore_lesser_euid_open
	ok 12 # SKIP test_cgcore_lesser_ns_open

Signed-off-by: Michal Koutný <mkoutny@suse.com>
---
 tools/testing/selftests/cgroup/test_core.c | 31 ++++++++++++++++++----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index 0c4cc4e5fc8c2..338e276aae5da 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -148,6 +148,9 @@ static int test_cgcore_populated(const char *root)
 	int cgroup_fd = -EBADF;
 	pid_t pid;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	cg_test_a = cg_name(root, "cg_test_a");
 	cg_test_b = cg_name(root, "cg_test_a/cg_test_b");
 	cg_test_c = cg_name(root, "cg_test_a/cg_test_b/cg_test_c");
@@ -277,6 +280,9 @@ static int test_cgcore_invalid_domain(const char *root)
 	int ret = KSFT_FAIL;
 	char *grandparent = NULL, *parent = NULL, *child = NULL;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	grandparent = cg_name(root, "cg_test_grandparent");
 	parent = cg_name(root, "cg_test_grandparent/cg_test_parent");
 	child = cg_name(root, "cg_test_grandparent/cg_test_parent/cg_test_child");
@@ -339,6 +345,9 @@ static int test_cgcore_parent_becomes_threaded(const char *root)
 	int ret = KSFT_FAIL;
 	char *parent = NULL, *child = NULL;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	parent = cg_name(root, "cg_test_parent");
 	child = cg_name(root, "cg_test_parent/cg_test_child");
 	if (!parent || !child)
@@ -378,7 +387,8 @@ static int test_cgcore_no_internal_process_constraint_on_threads(const char *roo
 	int ret = KSFT_FAIL;
 	char *parent = NULL, *child = NULL;
 
-	if (cg_read_strstr(root, "cgroup.controllers", "cpu") ||
+	if (cg_test_v1_named ||
+	    cg_read_strstr(root, "cgroup.controllers", "cpu") ||
 	    cg_write(root, "cgroup.subtree_control", "+cpu")) {
 		ret = KSFT_SKIP;
 		goto cleanup;
@@ -430,6 +440,9 @@ static int test_cgcore_top_down_constraint_enable(const char *root)
 	int ret = KSFT_FAIL;
 	char *parent = NULL, *child = NULL;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	parent = cg_name(root, "cg_test_parent");
 	child = cg_name(root, "cg_test_parent/cg_test_child");
 	if (!parent || !child)
@@ -465,6 +478,9 @@ static int test_cgcore_top_down_constraint_disable(const char *root)
 	int ret = KSFT_FAIL;
 	char *parent = NULL, *child = NULL;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	parent = cg_name(root, "cg_test_parent");
 	child = cg_name(root, "cg_test_parent/cg_test_child");
 	if (!parent || !child)
@@ -506,6 +522,9 @@ static int test_cgcore_internal_process_constraint(const char *root)
 	int ret = KSFT_FAIL;
 	char *parent = NULL, *child = NULL;
 
+	if (cg_test_v1_named)
+		return KSFT_SKIP;
+
 	parent = cg_name(root, "cg_test_parent");
 	child = cg_name(root, "cg_test_parent/cg_test_child");
 	if (!parent || !child)
@@ -642,10 +661,12 @@ static int test_cgcore_thread_migration(const char *root)
 	if (cg_create(grps[2]))
 		goto cleanup;
 
-	if (cg_write(grps[1], "cgroup.type", "threaded"))
-		goto cleanup;
-	if (cg_write(grps[2], "cgroup.type", "threaded"))
-		goto cleanup;
+	if (!cg_test_v1_named) {
+		if (cg_write(grps[1], "cgroup.type", "threaded"))
+			goto cleanup;
+		if (cg_write(grps[2], "cgroup.type", "threaded"))
+			goto cleanup;
+	}
 
 	if (cg_enter_current(grps[1]))
 		goto cleanup;
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] selftests: cgroup: Optionally set up v1 environment
  2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
  2025-06-17 13:36 ` [PATCH 1/4] selftests: cgroup_util: Add helpers for testing named v1 hierarchies Michal Koutný
  2025-06-17 13:36 ` [PATCH 2/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
@ 2025-06-17 13:36 ` Michal Koutný
  2025-06-17 13:36 ` [PATCH 4/4] selftests: cgroup: Fix compilation on pre-cgroupns kernels Michal Koutný
  2025-06-17 18:13 ` [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Tejun Heo
  4 siblings, 0 replies; 6+ messages in thread
From: Michal Koutný @ 2025-06-17 13:36 UTC (permalink / raw)
  To: cgroups, linux-kselftest, linux-kernel
  Cc: Michal Koutný, Tejun Heo, Johannes Weiner, Shuah Khan

Use the missing mount of the unifier hierarchy as a hint of legacy
system and prepare our own named v1 hierarchy for tests.

The code is only in test_core.c and not cgroup_util.c because other
selftests are related to controllers which will be exposed on v2
hierarchy but named hierarchies are only v1 thing.

Signed-off-by: Michal Koutný <mkoutny@suse.com>
---
 tools/testing/selftests/cgroup/test_core.c | 44 +++++++++++++++++++++-
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index 338e276aae5da..452c2abf9794e 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -5,6 +5,8 @@
 #include <linux/sched.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -863,6 +865,38 @@ static int test_cgcore_lesser_ns_open(const char *root)
 	return ret;
 }
 
+static int setup_named_v1_root(char *root, size_t len, const char *name)
+{
+	char options[PATH_MAX];
+	int r;
+
+	r = snprintf(root, len, "/mnt/cg_selftest");
+	if (r < 0)
+		return r;
+
+	r = snprintf(options, sizeof(options), "none,name=%s", name);
+	if (r < 0)
+		return r;
+
+	r = mkdir(root, 0755);
+	if (r < 0 && errno != EEXIST)
+		return r;
+
+	r = mount("none", root, "cgroup", 0, options);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+static void cleanup_named_v1_root(char *root)
+{
+	if (!cg_test_v1_named)
+		return;
+	umount(root);
+	rmdir(root);
+}
+
 #define T(x) { x, #x }
 struct corecg_test {
 	int (*fn)(const char *root);
@@ -888,13 +922,18 @@ int main(int argc, char *argv[])
 	char root[PATH_MAX];
 	int i, ret = EXIT_SUCCESS;
 
-	if (cg_find_unified_root(root, sizeof(root), &nsdelegate))
-		ksft_exit_skip("cgroup v2 isn't mounted\n");
+	if (cg_find_unified_root(root, sizeof(root), &nsdelegate)) {
+		if (setup_named_v1_root(root, sizeof(root), CG_NAMED_NAME))
+			ksft_exit_skip("cgroup v2 isn't mounted and could not setup named v1 hierarchy\n");
+		cg_test_v1_named = true;
+		goto post_v2_setup;
+	}
 
 	if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
 		if (cg_write(root, "cgroup.subtree_control", "+memory"))
 			ksft_exit_skip("Failed to set memory controller\n");
 
+post_v2_setup:
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
@@ -910,5 +949,6 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	cleanup_named_v1_root(root);
 	return ret;
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] selftests: cgroup: Fix compilation on pre-cgroupns kernels
  2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
                   ` (2 preceding siblings ...)
  2025-06-17 13:36 ` [PATCH 3/4] selftests: cgroup: Optionally set up v1 environment Michal Koutný
@ 2025-06-17 13:36 ` Michal Koutný
  2025-06-17 18:13 ` [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Tejun Heo
  4 siblings, 0 replies; 6+ messages in thread
From: Michal Koutný @ 2025-06-17 13:36 UTC (permalink / raw)
  To: cgroups, linux-kselftest, linux-kernel
  Cc: Michal Koutný, Tejun Heo, Johannes Weiner, Shuah Khan

The test would be skipped because of nsdelegate, so the defined value is
not used (0 is always acceptable).

Signed-off-by: Michal Koutný <mkoutny@suse.com>
---
 tools/testing/selftests/cgroup/test_core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index 452c2abf9794e..a360e2eb2eefd 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -21,6 +21,9 @@
 #include "cgroup_util.h"
 
 static bool nsdelegate;
+#ifndef CLONE_NEWCGROUP
+#define CLONE_NEWCGROUP 0
+#endif
 
 static int touch_anon(char *buf, size_t size)
 {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core
  2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
                   ` (3 preceding siblings ...)
  2025-06-17 13:36 ` [PATCH 4/4] selftests: cgroup: Fix compilation on pre-cgroupns kernels Michal Koutný
@ 2025-06-17 18:13 ` Tejun Heo
  4 siblings, 0 replies; 6+ messages in thread
From: Tejun Heo @ 2025-06-17 18:13 UTC (permalink / raw)
  To: Michal Koutný
  Cc: linux-kernel, cgroups, linux-kselftest, Johannes Weiner,
	Shuah Khan

On Tue, Jun 17, 2025 at 03:36:52PM +0200, Michal Koutný wrote:
> Michal Koutný (4):
>   selftests: cgroup_util: Add helpers for testing named v1 hierarchies
>   selftests: cgroup: Add support for named v1 hierarchies in test_core
>   selftests: cgroup: Optionally set up v1 environment
>   selftests: cgroup: Fix compilation on pre-cgroupns kernels

Applied to cgroup/for-6.17.

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-06-17 18:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-17 13:36 [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
2025-06-17 13:36 ` [PATCH 1/4] selftests: cgroup_util: Add helpers for testing named v1 hierarchies Michal Koutný
2025-06-17 13:36 ` [PATCH 2/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Michal Koutný
2025-06-17 13:36 ` [PATCH 3/4] selftests: cgroup: Optionally set up v1 environment Michal Koutný
2025-06-17 13:36 ` [PATCH 4/4] selftests: cgroup: Fix compilation on pre-cgroupns kernels Michal Koutný
2025-06-17 18:13 ` [PATCH 0/4] selftests: cgroup: Add support for named v1 hierarchies in test_core Tejun Heo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).