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 } 111