Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/cgroup/test_pids.c
29270 views
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
if (cgroup_feature("pids_localevents") <= 0)
81
return KSFT_SKIP;
82
83
cg_parent = cg_name(root, "pids_parent");
84
cg_child = cg_name(cg_parent, "pids_child");
85
if (!cg_parent || !cg_child)
86
goto cleanup;
87
88
if (cg_create(cg_parent))
89
goto cleanup;
90
if (cg_write(cg_parent, "cgroup.subtree_control", "+pids"))
91
goto cleanup;
92
if (cg_create(cg_child))
93
goto cleanup;
94
95
if (cg_write(cg_parent, "pids.max", "2"))
96
goto cleanup;
97
98
if (cg_read_strcmp(cg_child, "pids.max", "max\n"))
99
goto cleanup;
100
101
if (cg_enter_current(cg_child))
102
goto cleanup;
103
104
pid = cg_run_nowait(cg_child, run_pause, NULL);
105
if (pid < 0)
106
goto cleanup;
107
108
if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)
109
goto cleanup;
110
111
if (kill(pid, SIGINT))
112
goto cleanup;
113
114
if (cg_read_key_long(cg_child, "pids.events", "max ") != 0)
115
goto cleanup;
116
if (cg_read_key_long(cg_parent, "pids.events", "max ") != 1)
117
goto cleanup;
118
119
120
ret = KSFT_PASS;
121
122
cleanup:
123
cg_enter_current(root);
124
if (cg_child)
125
cg_destroy(cg_child);
126
if (cg_parent)
127
cg_destroy(cg_parent);
128
free(cg_child);
129
free(cg_parent);
130
131
return ret;
132
}
133
134
135
136
#define T(x) { x, #x }
137
struct pids_test {
138
int (*fn)(const char *root);
139
const char *name;
140
} tests[] = {
141
T(test_pids_max),
142
T(test_pids_events),
143
};
144
#undef T
145
146
int main(int argc, char **argv)
147
{
148
char root[PATH_MAX];
149
150
ksft_print_header();
151
ksft_set_plan(ARRAY_SIZE(tests));
152
if (cg_find_unified_root(root, sizeof(root), NULL))
153
ksft_exit_skip("cgroup v2 isn't mounted\n");
154
155
/*
156
* Check that pids controller is available:
157
* pids is listed in cgroup.controllers
158
*/
159
if (cg_read_strstr(root, "cgroup.controllers", "pids"))
160
ksft_exit_skip("pids controller isn't available\n");
161
162
if (cg_read_strstr(root, "cgroup.subtree_control", "pids"))
163
if (cg_write(root, "cgroup.subtree_control", "+pids"))
164
ksft_exit_skip("Failed to set pids controller\n");
165
166
for (int i = 0; i < ARRAY_SIZE(tests); i++) {
167
switch (tests[i].fn(root)) {
168
case KSFT_PASS:
169
ksft_test_result_pass("%s\n", tests[i].name);
170
break;
171
case KSFT_SKIP:
172
ksft_test_result_skip("%s\n", tests[i].name);
173
break;
174
default:
175
ksft_test_result_fail("%s\n", tests[i].name);
176
break;
177
}
178
}
179
180
ksft_finished();
181
}
182
183