Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cgroup: Add new test_cpu.c test suite in cgroup selftests

The cgroup selftests suite currently contains tests that validate various
aspects of cgroup, such as validating the expected behavior for memory
controllers, the expected behavior of cgroup.procs, etc. There are no tests
that validate the expected behavior of the cgroup cpu controller.

This patch therefore adds a new test_cpu.c file that will contain cpu
controller testcases. The file currently only contains a single testcase
that validates creating nested cgroups with cgroup.subtree_control
including cpu. Future patches will add more sophisticated testcases that
validate functional aspects of the cpu controller.

Signed-off-by: David Vernet <void@manifault.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

David Vernet and committed by
Tejun Heo
820a4f88 281b9d9a

+113
+1
tools/testing/selftests/cgroup/.gitignore
··· 4 4 test_freezer 5 5 test_kmem 6 6 test_kill 7 + test_cpu
+2
tools/testing/selftests/cgroup/Makefile
··· 10 10 TEST_GEN_PROGS += test_core 11 11 TEST_GEN_PROGS += test_freezer 12 12 TEST_GEN_PROGS += test_kill 13 + TEST_GEN_PROGS += test_cpu 13 14 14 15 LOCAL_HDRS += $(selfdir)/clone3/clone3_selftests.h $(selfdir)/pidfd/pidfd.h 15 16 ··· 21 20 $(OUTPUT)/test_core: cgroup_util.c 22 21 $(OUTPUT)/test_freezer: cgroup_util.c 23 22 $(OUTPUT)/test_kill: cgroup_util.c 23 + $(OUTPUT)/test_cpu: cgroup_util.c
+110
tools/testing/selftests/cgroup/test_cpu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE 4 + #include <linux/limits.h> 5 + #include <stdio.h> 6 + 7 + #include "../kselftest.h" 8 + #include "cgroup_util.h" 9 + 10 + /* 11 + * This test creates two nested cgroups with and without enabling 12 + * the cpu controller. 13 + */ 14 + static int test_cpucg_subtree_control(const char *root) 15 + { 16 + char *parent = NULL, *child = NULL, *parent2 = NULL, *child2 = NULL; 17 + int ret = KSFT_FAIL; 18 + 19 + // Create two nested cgroups with the cpu controller enabled. 20 + parent = cg_name(root, "cpucg_test_0"); 21 + if (!parent) 22 + goto cleanup; 23 + 24 + if (cg_create(parent)) 25 + goto cleanup; 26 + 27 + if (cg_write(parent, "cgroup.subtree_control", "+cpu")) 28 + goto cleanup; 29 + 30 + child = cg_name(parent, "cpucg_test_child"); 31 + if (!child) 32 + goto cleanup; 33 + 34 + if (cg_create(child)) 35 + goto cleanup; 36 + 37 + if (cg_read_strstr(child, "cgroup.controllers", "cpu")) 38 + goto cleanup; 39 + 40 + // Create two nested cgroups without enabling the cpu controller. 41 + parent2 = cg_name(root, "cpucg_test_1"); 42 + if (!parent2) 43 + goto cleanup; 44 + 45 + if (cg_create(parent2)) 46 + goto cleanup; 47 + 48 + child2 = cg_name(parent2, "cpucg_test_child"); 49 + if (!child2) 50 + goto cleanup; 51 + 52 + if (cg_create(child2)) 53 + goto cleanup; 54 + 55 + if (!cg_read_strstr(child2, "cgroup.controllers", "cpu")) 56 + goto cleanup; 57 + 58 + ret = KSFT_PASS; 59 + 60 + cleanup: 61 + cg_destroy(child); 62 + free(child); 63 + cg_destroy(child2); 64 + free(child2); 65 + cg_destroy(parent); 66 + free(parent); 67 + cg_destroy(parent2); 68 + free(parent2); 69 + 70 + return ret; 71 + } 72 + 73 + #define T(x) { x, #x } 74 + struct cpucg_test { 75 + int (*fn)(const char *root); 76 + const char *name; 77 + } tests[] = { 78 + T(test_cpucg_subtree_control), 79 + }; 80 + #undef T 81 + 82 + int main(int argc, char *argv[]) 83 + { 84 + char root[PATH_MAX]; 85 + int i, ret = EXIT_SUCCESS; 86 + 87 + if (cg_find_unified_root(root, sizeof(root))) 88 + ksft_exit_skip("cgroup v2 isn't mounted\n"); 89 + 90 + if (cg_read_strstr(root, "cgroup.subtree_control", "cpu")) 91 + if (cg_write(root, "cgroup.subtree_control", "+cpu")) 92 + ksft_exit_skip("Failed to set cpu controller\n"); 93 + 94 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 95 + switch (tests[i].fn(root)) { 96 + case KSFT_PASS: 97 + ksft_test_result_pass("%s\n", tests[i].name); 98 + break; 99 + case KSFT_SKIP: 100 + ksft_test_result_skip("%s\n", tests[i].name); 101 + break; 102 + default: 103 + ret = EXIT_FAILURE; 104 + ksft_test_result_fail("%s\n", tests[i].name); 105 + break; 106 + } 107 + } 108 + 109 + return ret; 110 + }