Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / cgroup / test_pids.c
blob9ecb83c6cc5cbf4d2b26d02fa921700d5c1ada23
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <linux/limits.h>
6 #include <signal.h>
7 #include <string.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
12 #include "../kselftest.h"
13 #include "cgroup_util.h"
15 static int run_success(const char *cgroup, void *arg)
17 return 0;
20 static int run_pause(const char *cgroup, void *arg)
22 return pause();
26 * This test checks that pids.max prevents forking new children above the
27 * specified limit in the cgroup.
29 static int test_pids_max(const char *root)
31 int ret = KSFT_FAIL;
32 char *cg_pids;
33 int pid;
35 cg_pids = cg_name(root, "pids_test");
36 if (!cg_pids)
37 goto cleanup;
39 if (cg_create(cg_pids))
40 goto cleanup;
42 if (cg_read_strcmp(cg_pids, "pids.max", "max\n"))
43 goto cleanup;
45 if (cg_write(cg_pids, "pids.max", "2"))
46 goto cleanup;
48 if (cg_enter_current(cg_pids))
49 goto cleanup;
51 pid = cg_run_nowait(cg_pids, run_pause, NULL);
52 if (pid < 0)
53 goto cleanup;
55 if (cg_run_nowait(cg_pids, run_success, NULL) != -1 || errno != EAGAIN)
56 goto cleanup;
58 if (kill(pid, SIGINT))
59 goto cleanup;
61 ret = KSFT_PASS;
63 cleanup:
64 cg_enter_current(root);
65 cg_destroy(cg_pids);
66 free(cg_pids);
68 return ret;
72 * This test checks that pids.events are counted in cgroup associated with pids.max
74 static int test_pids_events(const char *root)
76 int ret = KSFT_FAIL;
77 char *cg_parent = NULL, *cg_child = NULL;
78 int pid;
80 cg_parent = cg_name(root, "pids_parent");
81 cg_child = cg_name(cg_parent, "pids_child");
82 if (!cg_parent || !cg_child)
83 goto cleanup;
85 if (cg_create(cg_parent))
86 goto cleanup;
87 if (cg_write(cg_parent, "cgroup.subtree_control", "+pids"))
88 goto cleanup;
89 if (cg_create(cg_child))
90 goto cleanup;
92 if (cg_write(cg_parent, "pids.max", "2"))
93 goto cleanup;
95 if (cg_read_strcmp(cg_child, "pids.max", "max\n"))
96 goto cleanup;
98 if (cg_enter_current(cg_child))
99 goto cleanup;
101 pid = cg_run_nowait(cg_child, run_pause, NULL);
102 if (pid < 0)
103 goto cleanup;
105 if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)
106 goto cleanup;
108 if (kill(pid, SIGINT))
109 goto cleanup;
111 if (cg_read_key_long(cg_child, "pids.events", "max ") != 0)
112 goto cleanup;
113 if (cg_read_key_long(cg_parent, "pids.events", "max ") != 1)
114 goto cleanup;
117 ret = KSFT_PASS;
119 cleanup:
120 cg_enter_current(root);
121 if (cg_child)
122 cg_destroy(cg_child);
123 if (cg_parent)
124 cg_destroy(cg_parent);
125 free(cg_child);
126 free(cg_parent);
128 return ret;
133 #define T(x) { x, #x }
134 struct pids_test {
135 int (*fn)(const char *root);
136 const char *name;
137 } tests[] = {
138 T(test_pids_max),
139 T(test_pids_events),
141 #undef T
143 int main(int argc, char **argv)
145 char root[PATH_MAX];
147 ksft_print_header();
148 ksft_set_plan(ARRAY_SIZE(tests));
149 if (cg_find_unified_root(root, sizeof(root), NULL))
150 ksft_exit_skip("cgroup v2 isn't mounted\n");
153 * Check that pids controller is available:
154 * pids is listed in cgroup.controllers
156 if (cg_read_strstr(root, "cgroup.controllers", "pids"))
157 ksft_exit_skip("pids controller isn't available\n");
159 if (cg_read_strstr(root, "cgroup.subtree_control", "pids"))
160 if (cg_write(root, "cgroup.subtree_control", "+pids"))
161 ksft_exit_skip("Failed to set pids controller\n");
163 for (int i = 0; i < ARRAY_SIZE(tests); i++) {
164 switch (tests[i].fn(root)) {
165 case KSFT_PASS:
166 ksft_test_result_pass("%s\n", tests[i].name);
167 break;
168 case KSFT_SKIP:
169 ksft_test_result_skip("%s\n", tests[i].name);
170 break;
171 default:
172 ksft_test_result_fail("%s\n", tests[i].name);
173 break;
177 ksft_finished();