File Index
Files and directories
Sign in
FILE

test_pids.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/cgroup/test_pids.c 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
 15static int run_success(const char *cgroup, void *arg)
 16{
 17	return 0;
 18}
 19
 20static 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 */
 29static 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
 63cleanup:
 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 */
 74static 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
122cleanup:
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 }
137struct 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
146int 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}
~/ Read-only file preview.