]> Git Repo - J-linux.git/blob - tools/testing/selftests/cgroup/test_pids.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / cgroup / test_pids.c
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3
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>
11
12 #include "../kselftest.h"
13 #include "cgroup_util.h"
14
15 static int run_success(const char *cgroup, void *arg)
16 {
17         return 0;
18 }
19
20 static int run_pause(const char *cgroup, void *arg)
21 {
22         return pause();
23 }
24
25 /*
26  * This test checks that pids.max prevents forking new children above the
27  * specified limit in the cgroup.
28  */
29 static int test_pids_max(const char *root)
30 {
31         int ret = KSFT_FAIL;
32         char *cg_pids;
33         int pid;
34
35         cg_pids = cg_name(root, "pids_test");
36         if (!cg_pids)
37                 goto cleanup;
38
39         if (cg_create(cg_pids))
40                 goto cleanup;
41
42         if (cg_read_strcmp(cg_pids, "pids.max", "max\n"))
43                 goto cleanup;
44
45         if (cg_write(cg_pids, "pids.max", "2"))
46                 goto cleanup;
47
48         if (cg_enter_current(cg_pids))
49                 goto cleanup;
50
51         pid = cg_run_nowait(cg_pids, run_pause, NULL);
52         if (pid < 0)
53                 goto cleanup;
54
55         if (cg_run_nowait(cg_pids, run_success, NULL) != -1 || errno != EAGAIN)
56                 goto cleanup;
57
58         if (kill(pid, SIGINT))
59                 goto cleanup;
60
61         ret = KSFT_PASS;
62
63 cleanup:
64         cg_enter_current(root);
65         cg_destroy(cg_pids);
66         free(cg_pids);
67
68         return ret;
69 }
70
71 /*
72  * This test checks that pids.events are counted in cgroup associated with pids.max
73  */
74 static int test_pids_events(const char *root)
75 {
76         int ret = KSFT_FAIL;
77         char *cg_parent = NULL, *cg_child = NULL;
78         int pid;
79
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;
84
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;
91
92         if (cg_write(cg_parent, "pids.max", "2"))
93                 goto cleanup;
94
95         if (cg_read_strcmp(cg_child, "pids.max", "max\n"))
96                 goto cleanup;
97
98         if (cg_enter_current(cg_child))
99                 goto cleanup;
100
101         pid = cg_run_nowait(cg_child, run_pause, NULL);
102         if (pid < 0)
103                 goto cleanup;
104
105         if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)
106                 goto cleanup;
107
108         if (kill(pid, SIGINT))
109                 goto cleanup;
110
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;
115
116
117         ret = KSFT_PASS;
118
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);
127
128         return ret;
129 }
130
131
132
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),
140 };
141 #undef T
142
143 int main(int argc, char **argv)
144 {
145         char root[PATH_MAX];
146
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");
151
152         /*
153          * Check that pids controller is available:
154          * pids is listed in cgroup.controllers
155          */
156         if (cg_read_strstr(root, "cgroup.controllers", "pids"))
157                 ksft_exit_skip("pids controller isn't available\n");
158
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");
162
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;
174                 }
175         }
176
177         ksft_finished();
178 }
This page took 0.035676 seconds and 4 git commands to generate.