1 /* SPDX-License-Identifier: GPL-2.0 */
4 #include <linux/limits.h>
10 #include <sys/types.h>
13 #include "../kselftest.h"
14 #include "cgroup_util.h"
17 * This test creates two nested cgroups with and without enabling
18 * the memory controller.
20 static int test_memcg_subtree_control(const char *root)
22 char *parent, *child, *parent2, *child2;
26 /* Create two nested cgroups with the memory controller enabled */
27 parent = cg_name(root, "memcg_test_0");
28 child = cg_name(root, "memcg_test_0/memcg_test_1");
29 if (!parent || !child)
32 if (cg_create(parent))
35 if (cg_write(parent, "cgroup.subtree_control", "+memory"))
41 if (cg_read_strstr(child, "cgroup.controllers", "memory"))
44 /* Create two nested cgroups without enabling memory controller */
45 parent2 = cg_name(root, "memcg_test_1");
46 child2 = cg_name(root, "memcg_test_1/memcg_test_1");
47 if (!parent2 || !child2)
50 if (cg_create(parent2))
53 if (cg_create(child2))
56 if (cg_read(child2, "cgroup.controllers", buf, sizeof(buf)))
59 if (!cg_read_strstr(child2, "cgroup.controllers", "memory"))
78 static int alloc_anon_50M_check(const char *cgroup, void *arg)
86 for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
89 current = cg_read_long(cgroup, "memory.current");
93 if (!values_close(size, current, 3))
96 anon = cg_read_key_long(cgroup, "memory.stat", "anon ");
100 if (!values_close(anon, current, 3))
109 static int alloc_pagecache_50M_check(const char *cgroup, void *arg)
111 size_t size = MB(50);
120 if (alloc_pagecache(fd, size))
123 current = cg_read_long(cgroup, "memory.current");
127 file = cg_read_key_long(cgroup, "memory.stat", "file ");
131 if (!values_close(file, current, 10))
142 * This test create a memory cgroup, allocates
143 * some anonymous memory and some pagecache
144 * and check memory.current and some memory.stat values.
146 static int test_memcg_current(const char *root)
152 memcg = cg_name(root, "memcg_test");
156 if (cg_create(memcg))
159 current = cg_read_long(memcg, "memory.current");
163 if (cg_run(memcg, alloc_anon_50M_check, NULL))
166 if (cg_run(memcg, alloc_pagecache_50M_check, NULL))
178 static int alloc_pagecache_50M(const char *cgroup, void *arg)
182 return alloc_pagecache(fd, MB(50));
185 static int alloc_pagecache_50M_noexit(const char *cgroup, void *arg)
188 int ppid = getppid();
190 if (alloc_pagecache(fd, MB(50)))
193 while (getppid() == ppid)
200 * First, this test creates the following hierarchy:
201 * A memory.min = 50M, memory.max = 200M
202 * A/B memory.min = 50M, memory.current = 50M
203 * A/B/C memory.min = 75M, memory.current = 50M
204 * A/B/D memory.min = 25M, memory.current = 50M
205 * A/B/E memory.min = 500M, memory.current = 0
206 * A/B/F memory.min = 0, memory.current = 50M
208 * Usages are pagecache, but the test keeps a running
209 * process in every leaf cgroup.
210 * Then it creates A/G and creates a significant
211 * memory pressure in it.
213 * A/B memory.current ~= 50M
214 * A/B/C memory.current ~= 33M
215 * A/B/D memory.current ~= 17M
216 * A/B/E memory.current ~= 0
218 * After that it tries to allocate more than there is
219 * unprotected memory in A available, and checks
220 * checks that memory.min protects pagecache even
223 static int test_memcg_min(const char *root)
226 char *parent[3] = {NULL};
227 char *children[4] = {NULL};
236 parent[0] = cg_name(root, "memcg_test_0");
240 parent[1] = cg_name(parent[0], "memcg_test_1");
244 parent[2] = cg_name(parent[0], "memcg_test_2");
248 if (cg_create(parent[0]))
251 if (cg_read_long(parent[0], "memory.min")) {
256 if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
259 if (cg_write(parent[0], "memory.max", "200M"))
262 if (cg_write(parent[0], "memory.swap.max", "0"))
265 if (cg_create(parent[1]))
268 if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
271 if (cg_create(parent[2]))
274 for (i = 0; i < ARRAY_SIZE(children); i++) {
275 children[i] = cg_name_indexed(parent[1], "child_memcg", i);
279 if (cg_create(children[i]))
285 cg_run_nowait(children[i], alloc_pagecache_50M_noexit,
289 if (cg_write(parent[0], "memory.min", "50M"))
291 if (cg_write(parent[1], "memory.min", "50M"))
293 if (cg_write(children[0], "memory.min", "75M"))
295 if (cg_write(children[1], "memory.min", "25M"))
297 if (cg_write(children[2], "memory.min", "500M"))
299 if (cg_write(children[3], "memory.min", "0"))
303 while (!values_close(cg_read_long(parent[1], "memory.current"),
310 if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
313 if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
316 for (i = 0; i < ARRAY_SIZE(children); i++)
317 c[i] = cg_read_long(children[i], "memory.current");
319 if (!values_close(c[0], MB(33), 10))
322 if (!values_close(c[1], MB(17), 10))
325 if (!values_close(c[2], 0, 1))
328 if (!cg_run(parent[2], alloc_anon, (void *)MB(170)))
331 if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
337 for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
341 cg_destroy(children[i]);
345 for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
349 cg_destroy(parent[i]);
357 * First, this test creates the following hierarchy:
358 * A memory.low = 50M, memory.max = 200M
359 * A/B memory.low = 50M, memory.current = 50M
360 * A/B/C memory.low = 75M, memory.current = 50M
361 * A/B/D memory.low = 25M, memory.current = 50M
362 * A/B/E memory.low = 500M, memory.current = 0
363 * A/B/F memory.low = 0, memory.current = 50M
365 * Usages are pagecache.
366 * Then it creates A/G an creates a significant
367 * memory pressure in it.
369 * Then it checks actual memory usages and expects that:
370 * A/B memory.current ~= 50M
371 * A/B/ memory.current ~= 33M
372 * A/B/D memory.current ~= 17M
373 * A/B/E memory.current ~= 0
375 * After that it tries to allocate more than there is
376 * unprotected memory in A available,
377 * and checks low and oom events in memory.events.
379 static int test_memcg_low(const char *root)
382 char *parent[3] = {NULL};
383 char *children[4] = {NULL};
393 parent[0] = cg_name(root, "memcg_test_0");
397 parent[1] = cg_name(parent[0], "memcg_test_1");
401 parent[2] = cg_name(parent[0], "memcg_test_2");
405 if (cg_create(parent[0]))
408 if (cg_read_long(parent[0], "memory.low"))
411 if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
414 if (cg_write(parent[0], "memory.max", "200M"))
417 if (cg_write(parent[0], "memory.swap.max", "0"))
420 if (cg_create(parent[1]))
423 if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
426 if (cg_create(parent[2]))
429 for (i = 0; i < ARRAY_SIZE(children); i++) {
430 children[i] = cg_name_indexed(parent[1], "child_memcg", i);
434 if (cg_create(children[i]))
440 if (cg_run(children[i], alloc_pagecache_50M, (void *)(long)fd))
444 if (cg_write(parent[0], "memory.low", "50M"))
446 if (cg_write(parent[1], "memory.low", "50M"))
448 if (cg_write(children[0], "memory.low", "75M"))
450 if (cg_write(children[1], "memory.low", "25M"))
452 if (cg_write(children[2], "memory.low", "500M"))
454 if (cg_write(children[3], "memory.low", "0"))
457 if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
460 if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
463 for (i = 0; i < ARRAY_SIZE(children); i++)
464 c[i] = cg_read_long(children[i], "memory.current");
466 if (!values_close(c[0], MB(33), 10))
469 if (!values_close(c[1], MB(17), 10))
472 if (!values_close(c[2], 0, 1))
475 if (cg_run(parent[2], alloc_anon, (void *)MB(166))) {
477 "memory.low prevents from allocating anon memory\n");
481 for (i = 0; i < ARRAY_SIZE(children); i++) {
482 oom = cg_read_key_long(children[i], "memory.events", "oom ");
483 low = cg_read_key_long(children[i], "memory.events", "low ");
487 if (i < 2 && low <= 0)
496 for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
500 cg_destroy(children[i]);
504 for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
508 cg_destroy(parent[i]);
515 static int alloc_pagecache_max_30M(const char *cgroup, void *arg)
517 size_t size = MB(50);
526 if (alloc_pagecache(fd, size))
529 current = cg_read_long(cgroup, "memory.current");
530 if (current <= MB(29) || current > MB(30))
542 * This test checks that memory.high limits the amount of
543 * memory which can be consumed by either anonymous memory
546 static int test_memcg_high(const char *root)
552 memcg = cg_name(root, "memcg_test");
556 if (cg_create(memcg))
559 if (cg_read_strcmp(memcg, "memory.high", "max\n"))
562 if (cg_write(memcg, "memory.swap.max", "0"))
565 if (cg_write(memcg, "memory.high", "30M"))
568 if (cg_run(memcg, alloc_anon, (void *)MB(100)))
571 if (!cg_run(memcg, alloc_pagecache_50M_check, NULL))
574 if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
577 high = cg_read_key_long(memcg, "memory.events", "high ");
591 * This test checks that memory.max limits the amount of
592 * memory which can be consumed by either anonymous memory
595 static int test_memcg_max(const char *root)
601 memcg = cg_name(root, "memcg_test");
605 if (cg_create(memcg))
608 if (cg_read_strcmp(memcg, "memory.max", "max\n"))
611 if (cg_write(memcg, "memory.swap.max", "0"))
614 if (cg_write(memcg, "memory.max", "30M"))
617 /* Should be killed by OOM killer */
618 if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
621 if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
624 current = cg_read_long(memcg, "memory.current");
625 if (current > MB(30) || !current)
628 max = cg_read_key_long(memcg, "memory.events", "max ");
642 * This test disables swapping and tries to allocate anonymous memory
643 * up to OOM. Then it checks for oom and oom_kill events in
646 static int test_memcg_oom_events(const char *root)
651 memcg = cg_name(root, "memcg_test");
655 if (cg_create(memcg))
658 if (cg_write(memcg, "memory.max", "30M"))
661 if (cg_write(memcg, "memory.swap.max", "0"))
664 if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
667 if (cg_read_strcmp(memcg, "cgroup.procs", ""))
670 if (cg_read_key_long(memcg, "memory.events", "oom ") != 1)
673 if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 1)
685 #define T(x) { x, #x }
687 int (*fn)(const char *root);
690 T(test_memcg_subtree_control),
691 T(test_memcg_current),
696 T(test_memcg_oom_events),
700 int main(int argc, char **argv)
703 int i, ret = EXIT_SUCCESS;
705 if (cg_find_unified_root(root, sizeof(root)))
706 ksft_exit_skip("cgroup v2 isn't mounted\n");
709 * Check that memory controller is available:
710 * memory is listed in cgroup.controllers
712 if (cg_read_strstr(root, "cgroup.controllers", "memory"))
713 ksft_exit_skip("memory controller isn't available\n");
715 for (i = 0; i < ARRAY_SIZE(tests); i++) {
716 switch (tests[i].fn(root)) {
718 ksft_test_result_pass("%s\n", tests[i].name);
721 ksft_test_result_skip("%s\n", tests[i].name);
725 ksft_test_result_fail("%s\n", tests[i].name);