root/tools/testing/selftests/cgroup/test_memcontrol.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_memcg_subtree_control
  2. alloc_anon_50M_check
  3. alloc_pagecache_50M_check
  4. test_memcg_current
  5. alloc_pagecache_50M
  6. alloc_pagecache_50M_noexit
  7. alloc_anon_noexit
  8. cg_test_proc_killed
  9. test_memcg_min
  10. test_memcg_low
  11. alloc_pagecache_max_30M
  12. test_memcg_high
  13. test_memcg_max
  14. alloc_anon_50M_check_swap
  15. test_memcg_swap_max
  16. test_memcg_oom_events
  17. tcp_server
  18. tcp_client
  19. test_memcg_sock
  20. test_memcg_oom_group_leaf_events
  21. test_memcg_oom_group_parent_events
  22. test_memcg_oom_group_score_events
  23. main

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #define _GNU_SOURCE
   3 
   4 #include <linux/limits.h>
   5 #include <linux/oom.h>
   6 #include <fcntl.h>
   7 #include <stdio.h>
   8 #include <stdlib.h>
   9 #include <string.h>
  10 #include <sys/stat.h>
  11 #include <sys/types.h>
  12 #include <unistd.h>
  13 #include <sys/socket.h>
  14 #include <sys/wait.h>
  15 #include <arpa/inet.h>
  16 #include <netinet/in.h>
  17 #include <netdb.h>
  18 #include <errno.h>
  19 
  20 #include "../kselftest.h"
  21 #include "cgroup_util.h"
  22 
  23 /*
  24  * This test creates two nested cgroups with and without enabling
  25  * the memory controller.
  26  */
  27 static int test_memcg_subtree_control(const char *root)
  28 {
  29         char *parent, *child, *parent2 = NULL, *child2 = NULL;
  30         int ret = KSFT_FAIL;
  31         char buf[PAGE_SIZE];
  32 
  33         /* Create two nested cgroups with the memory controller enabled */
  34         parent = cg_name(root, "memcg_test_0");
  35         child = cg_name(root, "memcg_test_0/memcg_test_1");
  36         if (!parent || !child)
  37                 goto cleanup_free;
  38 
  39         if (cg_create(parent))
  40                 goto cleanup_free;
  41 
  42         if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  43                 goto cleanup_parent;
  44 
  45         if (cg_create(child))
  46                 goto cleanup_parent;
  47 
  48         if (cg_read_strstr(child, "cgroup.controllers", "memory"))
  49                 goto cleanup_child;
  50 
  51         /* Create two nested cgroups without enabling memory controller */
  52         parent2 = cg_name(root, "memcg_test_1");
  53         child2 = cg_name(root, "memcg_test_1/memcg_test_1");
  54         if (!parent2 || !child2)
  55                 goto cleanup_free2;
  56 
  57         if (cg_create(parent2))
  58                 goto cleanup_free2;
  59 
  60         if (cg_create(child2))
  61                 goto cleanup_parent2;
  62 
  63         if (cg_read(child2, "cgroup.controllers", buf, sizeof(buf)))
  64                 goto cleanup_all;
  65 
  66         if (!cg_read_strstr(child2, "cgroup.controllers", "memory"))
  67                 goto cleanup_all;
  68 
  69         ret = KSFT_PASS;
  70 
  71 cleanup_all:
  72         cg_destroy(child2);
  73 cleanup_parent2:
  74         cg_destroy(parent2);
  75 cleanup_free2:
  76         free(parent2);
  77         free(child2);
  78 cleanup_child:
  79         cg_destroy(child);
  80 cleanup_parent:
  81         cg_destroy(parent);
  82 cleanup_free:
  83         free(parent);
  84         free(child);
  85 
  86         return ret;
  87 }
  88 
  89 static int alloc_anon_50M_check(const char *cgroup, void *arg)
  90 {
  91         size_t size = MB(50);
  92         char *buf, *ptr;
  93         long anon, current;
  94         int ret = -1;
  95 
  96         buf = malloc(size);
  97         for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
  98                 *ptr = 0;
  99 
 100         current = cg_read_long(cgroup, "memory.current");
 101         if (current < size)
 102                 goto cleanup;
 103 
 104         if (!values_close(size, current, 3))
 105                 goto cleanup;
 106 
 107         anon = cg_read_key_long(cgroup, "memory.stat", "anon ");
 108         if (anon < 0)
 109                 goto cleanup;
 110 
 111         if (!values_close(anon, current, 3))
 112                 goto cleanup;
 113 
 114         ret = 0;
 115 cleanup:
 116         free(buf);
 117         return ret;
 118 }
 119 
 120 static int alloc_pagecache_50M_check(const char *cgroup, void *arg)
 121 {
 122         size_t size = MB(50);
 123         int ret = -1;
 124         long current, file;
 125         int fd;
 126 
 127         fd = get_temp_fd();
 128         if (fd < 0)
 129                 return -1;
 130 
 131         if (alloc_pagecache(fd, size))
 132                 goto cleanup;
 133 
 134         current = cg_read_long(cgroup, "memory.current");
 135         if (current < size)
 136                 goto cleanup;
 137 
 138         file = cg_read_key_long(cgroup, "memory.stat", "file ");
 139         if (file < 0)
 140                 goto cleanup;
 141 
 142         if (!values_close(file, current, 10))
 143                 goto cleanup;
 144 
 145         ret = 0;
 146 
 147 cleanup:
 148         close(fd);
 149         return ret;
 150 }
 151 
 152 /*
 153  * This test create a memory cgroup, allocates
 154  * some anonymous memory and some pagecache
 155  * and check memory.current and some memory.stat values.
 156  */
 157 static int test_memcg_current(const char *root)
 158 {
 159         int ret = KSFT_FAIL;
 160         long current;
 161         char *memcg;
 162 
 163         memcg = cg_name(root, "memcg_test");
 164         if (!memcg)
 165                 goto cleanup;
 166 
 167         if (cg_create(memcg))
 168                 goto cleanup;
 169 
 170         current = cg_read_long(memcg, "memory.current");
 171         if (current != 0)
 172                 goto cleanup;
 173 
 174         if (cg_run(memcg, alloc_anon_50M_check, NULL))
 175                 goto cleanup;
 176 
 177         if (cg_run(memcg, alloc_pagecache_50M_check, NULL))
 178                 goto cleanup;
 179 
 180         ret = KSFT_PASS;
 181 
 182 cleanup:
 183         cg_destroy(memcg);
 184         free(memcg);
 185 
 186         return ret;
 187 }
 188 
 189 static int alloc_pagecache_50M(const char *cgroup, void *arg)
 190 {
 191         int fd = (long)arg;
 192 
 193         return alloc_pagecache(fd, MB(50));
 194 }
 195 
 196 static int alloc_pagecache_50M_noexit(const char *cgroup, void *arg)
 197 {
 198         int fd = (long)arg;
 199         int ppid = getppid();
 200 
 201         if (alloc_pagecache(fd, MB(50)))
 202                 return -1;
 203 
 204         while (getppid() == ppid)
 205                 sleep(1);
 206 
 207         return 0;
 208 }
 209 
 210 static int alloc_anon_noexit(const char *cgroup, void *arg)
 211 {
 212         int ppid = getppid();
 213 
 214         if (alloc_anon(cgroup, arg))
 215                 return -1;
 216 
 217         while (getppid() == ppid)
 218                 sleep(1);
 219 
 220         return 0;
 221 }
 222 
 223 /*
 224  * Wait until processes are killed asynchronously by the OOM killer
 225  * If we exceed a timeout, fail.
 226  */
 227 static int cg_test_proc_killed(const char *cgroup)
 228 {
 229         int limit;
 230 
 231         for (limit = 10; limit > 0; limit--) {
 232                 if (cg_read_strcmp(cgroup, "cgroup.procs", "") == 0)
 233                         return 0;
 234 
 235                 usleep(100000);
 236         }
 237         return -1;
 238 }
 239 
 240 /*
 241  * First, this test creates the following hierarchy:
 242  * A       memory.min = 50M,  memory.max = 200M
 243  * A/B     memory.min = 50M,  memory.current = 50M
 244  * A/B/C   memory.min = 75M,  memory.current = 50M
 245  * A/B/D   memory.min = 25M,  memory.current = 50M
 246  * A/B/E   memory.min = 500M, memory.current = 0
 247  * A/B/F   memory.min = 0,    memory.current = 50M
 248  *
 249  * Usages are pagecache, but the test keeps a running
 250  * process in every leaf cgroup.
 251  * Then it creates A/G and creates a significant
 252  * memory pressure in it.
 253  *
 254  * A/B    memory.current ~= 50M
 255  * A/B/C  memory.current ~= 33M
 256  * A/B/D  memory.current ~= 17M
 257  * A/B/E  memory.current ~= 0
 258  *
 259  * After that it tries to allocate more than there is
 260  * unprotected memory in A available, and checks
 261  * checks that memory.min protects pagecache even
 262  * in this case.
 263  */
 264 static int test_memcg_min(const char *root)
 265 {
 266         int ret = KSFT_FAIL;
 267         char *parent[3] = {NULL};
 268         char *children[4] = {NULL};
 269         long c[4];
 270         int i, attempts;
 271         int fd;
 272 
 273         fd = get_temp_fd();
 274         if (fd < 0)
 275                 goto cleanup;
 276 
 277         parent[0] = cg_name(root, "memcg_test_0");
 278         if (!parent[0])
 279                 goto cleanup;
 280 
 281         parent[1] = cg_name(parent[0], "memcg_test_1");
 282         if (!parent[1])
 283                 goto cleanup;
 284 
 285         parent[2] = cg_name(parent[0], "memcg_test_2");
 286         if (!parent[2])
 287                 goto cleanup;
 288 
 289         if (cg_create(parent[0]))
 290                 goto cleanup;
 291 
 292         if (cg_read_long(parent[0], "memory.min")) {
 293                 ret = KSFT_SKIP;
 294                 goto cleanup;
 295         }
 296 
 297         if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
 298                 goto cleanup;
 299 
 300         if (cg_write(parent[0], "memory.max", "200M"))
 301                 goto cleanup;
 302 
 303         if (cg_write(parent[0], "memory.swap.max", "0"))
 304                 goto cleanup;
 305 
 306         if (cg_create(parent[1]))
 307                 goto cleanup;
 308 
 309         if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
 310                 goto cleanup;
 311 
 312         if (cg_create(parent[2]))
 313                 goto cleanup;
 314 
 315         for (i = 0; i < ARRAY_SIZE(children); i++) {
 316                 children[i] = cg_name_indexed(parent[1], "child_memcg", i);
 317                 if (!children[i])
 318                         goto cleanup;
 319 
 320                 if (cg_create(children[i]))
 321                         goto cleanup;
 322 
 323                 if (i == 2)
 324                         continue;
 325 
 326                 cg_run_nowait(children[i], alloc_pagecache_50M_noexit,
 327                               (void *)(long)fd);
 328         }
 329 
 330         if (cg_write(parent[0], "memory.min", "50M"))
 331                 goto cleanup;
 332         if (cg_write(parent[1], "memory.min", "50M"))
 333                 goto cleanup;
 334         if (cg_write(children[0], "memory.min", "75M"))
 335                 goto cleanup;
 336         if (cg_write(children[1], "memory.min", "25M"))
 337                 goto cleanup;
 338         if (cg_write(children[2], "memory.min", "500M"))
 339                 goto cleanup;
 340         if (cg_write(children[3], "memory.min", "0"))
 341                 goto cleanup;
 342 
 343         attempts = 0;
 344         while (!values_close(cg_read_long(parent[1], "memory.current"),
 345                              MB(150), 3)) {
 346                 if (attempts++ > 5)
 347                         break;
 348                 sleep(1);
 349         }
 350 
 351         if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
 352                 goto cleanup;
 353 
 354         if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
 355                 goto cleanup;
 356 
 357         for (i = 0; i < ARRAY_SIZE(children); i++)
 358                 c[i] = cg_read_long(children[i], "memory.current");
 359 
 360         if (!values_close(c[0], MB(33), 10))
 361                 goto cleanup;
 362 
 363         if (!values_close(c[1], MB(17), 10))
 364                 goto cleanup;
 365 
 366         if (!values_close(c[2], 0, 1))
 367                 goto cleanup;
 368 
 369         if (!cg_run(parent[2], alloc_anon, (void *)MB(170)))
 370                 goto cleanup;
 371 
 372         if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
 373                 goto cleanup;
 374 
 375         ret = KSFT_PASS;
 376 
 377 cleanup:
 378         for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
 379                 if (!children[i])
 380                         continue;
 381 
 382                 cg_destroy(children[i]);
 383                 free(children[i]);
 384         }
 385 
 386         for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
 387                 if (!parent[i])
 388                         continue;
 389 
 390                 cg_destroy(parent[i]);
 391                 free(parent[i]);
 392         }
 393         close(fd);
 394         return ret;
 395 }
 396 
 397 /*
 398  * First, this test creates the following hierarchy:
 399  * A       memory.low = 50M,  memory.max = 200M
 400  * A/B     memory.low = 50M,  memory.current = 50M
 401  * A/B/C   memory.low = 75M,  memory.current = 50M
 402  * A/B/D   memory.low = 25M,  memory.current = 50M
 403  * A/B/E   memory.low = 500M, memory.current = 0
 404  * A/B/F   memory.low = 0,    memory.current = 50M
 405  *
 406  * Usages are pagecache.
 407  * Then it creates A/G an creates a significant
 408  * memory pressure in it.
 409  *
 410  * Then it checks actual memory usages and expects that:
 411  * A/B    memory.current ~= 50M
 412  * A/B/   memory.current ~= 33M
 413  * A/B/D  memory.current ~= 17M
 414  * A/B/E  memory.current ~= 0
 415  *
 416  * After that it tries to allocate more than there is
 417  * unprotected memory in A available,
 418  * and checks low and oom events in memory.events.
 419  */
 420 static int test_memcg_low(const char *root)
 421 {
 422         int ret = KSFT_FAIL;
 423         char *parent[3] = {NULL};
 424         char *children[4] = {NULL};
 425         long low, oom;
 426         long c[4];
 427         int i;
 428         int fd;
 429 
 430         fd = get_temp_fd();
 431         if (fd < 0)
 432                 goto cleanup;
 433 
 434         parent[0] = cg_name(root, "memcg_test_0");
 435         if (!parent[0])
 436                 goto cleanup;
 437 
 438         parent[1] = cg_name(parent[0], "memcg_test_1");
 439         if (!parent[1])
 440                 goto cleanup;
 441 
 442         parent[2] = cg_name(parent[0], "memcg_test_2");
 443         if (!parent[2])
 444                 goto cleanup;
 445 
 446         if (cg_create(parent[0]))
 447                 goto cleanup;
 448 
 449         if (cg_read_long(parent[0], "memory.low"))
 450                 goto cleanup;
 451 
 452         if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
 453                 goto cleanup;
 454 
 455         if (cg_write(parent[0], "memory.max", "200M"))
 456                 goto cleanup;
 457 
 458         if (cg_write(parent[0], "memory.swap.max", "0"))
 459                 goto cleanup;
 460 
 461         if (cg_create(parent[1]))
 462                 goto cleanup;
 463 
 464         if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
 465                 goto cleanup;
 466 
 467         if (cg_create(parent[2]))
 468                 goto cleanup;
 469 
 470         for (i = 0; i < ARRAY_SIZE(children); i++) {
 471                 children[i] = cg_name_indexed(parent[1], "child_memcg", i);
 472                 if (!children[i])
 473                         goto cleanup;
 474 
 475                 if (cg_create(children[i]))
 476                         goto cleanup;
 477 
 478                 if (i == 2)
 479                         continue;
 480 
 481                 if (cg_run(children[i], alloc_pagecache_50M, (void *)(long)fd))
 482                         goto cleanup;
 483         }
 484 
 485         if (cg_write(parent[0], "memory.low", "50M"))
 486                 goto cleanup;
 487         if (cg_write(parent[1], "memory.low", "50M"))
 488                 goto cleanup;
 489         if (cg_write(children[0], "memory.low", "75M"))
 490                 goto cleanup;
 491         if (cg_write(children[1], "memory.low", "25M"))
 492                 goto cleanup;
 493         if (cg_write(children[2], "memory.low", "500M"))
 494                 goto cleanup;
 495         if (cg_write(children[3], "memory.low", "0"))
 496                 goto cleanup;
 497 
 498         if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
 499                 goto cleanup;
 500 
 501         if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
 502                 goto cleanup;
 503 
 504         for (i = 0; i < ARRAY_SIZE(children); i++)
 505                 c[i] = cg_read_long(children[i], "memory.current");
 506 
 507         if (!values_close(c[0], MB(33), 10))
 508                 goto cleanup;
 509 
 510         if (!values_close(c[1], MB(17), 10))
 511                 goto cleanup;
 512 
 513         if (!values_close(c[2], 0, 1))
 514                 goto cleanup;
 515 
 516         if (cg_run(parent[2], alloc_anon, (void *)MB(166))) {
 517                 fprintf(stderr,
 518                         "memory.low prevents from allocating anon memory\n");
 519                 goto cleanup;
 520         }
 521 
 522         for (i = 0; i < ARRAY_SIZE(children); i++) {
 523                 oom = cg_read_key_long(children[i], "memory.events", "oom ");
 524                 low = cg_read_key_long(children[i], "memory.events", "low ");
 525 
 526                 if (oom)
 527                         goto cleanup;
 528                 if (i < 2 && low <= 0)
 529                         goto cleanup;
 530                 if (i >= 2 && low)
 531                         goto cleanup;
 532         }
 533 
 534         ret = KSFT_PASS;
 535 
 536 cleanup:
 537         for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
 538                 if (!children[i])
 539                         continue;
 540 
 541                 cg_destroy(children[i]);
 542                 free(children[i]);
 543         }
 544 
 545         for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
 546                 if (!parent[i])
 547                         continue;
 548 
 549                 cg_destroy(parent[i]);
 550                 free(parent[i]);
 551         }
 552         close(fd);
 553         return ret;
 554 }
 555 
 556 static int alloc_pagecache_max_30M(const char *cgroup, void *arg)
 557 {
 558         size_t size = MB(50);
 559         int ret = -1;
 560         long current;
 561         int fd;
 562 
 563         fd = get_temp_fd();
 564         if (fd < 0)
 565                 return -1;
 566 
 567         if (alloc_pagecache(fd, size))
 568                 goto cleanup;
 569 
 570         current = cg_read_long(cgroup, "memory.current");
 571         if (current <= MB(29) || current > MB(30))
 572                 goto cleanup;
 573 
 574         ret = 0;
 575 
 576 cleanup:
 577         close(fd);
 578         return ret;
 579 
 580 }
 581 
 582 /*
 583  * This test checks that memory.high limits the amount of
 584  * memory which can be consumed by either anonymous memory
 585  * or pagecache.
 586  */
 587 static int test_memcg_high(const char *root)
 588 {
 589         int ret = KSFT_FAIL;
 590         char *memcg;
 591         long high;
 592 
 593         memcg = cg_name(root, "memcg_test");
 594         if (!memcg)
 595                 goto cleanup;
 596 
 597         if (cg_create(memcg))
 598                 goto cleanup;
 599 
 600         if (cg_read_strcmp(memcg, "memory.high", "max\n"))
 601                 goto cleanup;
 602 
 603         if (cg_write(memcg, "memory.swap.max", "0"))
 604                 goto cleanup;
 605 
 606         if (cg_write(memcg, "memory.high", "30M"))
 607                 goto cleanup;
 608 
 609         if (cg_run(memcg, alloc_anon, (void *)MB(100)))
 610                 goto cleanup;
 611 
 612         if (!cg_run(memcg, alloc_pagecache_50M_check, NULL))
 613                 goto cleanup;
 614 
 615         if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
 616                 goto cleanup;
 617 
 618         high = cg_read_key_long(memcg, "memory.events", "high ");
 619         if (high <= 0)
 620                 goto cleanup;
 621 
 622         ret = KSFT_PASS;
 623 
 624 cleanup:
 625         cg_destroy(memcg);
 626         free(memcg);
 627 
 628         return ret;
 629 }
 630 
 631 /*
 632  * This test checks that memory.max limits the amount of
 633  * memory which can be consumed by either anonymous memory
 634  * or pagecache.
 635  */
 636 static int test_memcg_max(const char *root)
 637 {
 638         int ret = KSFT_FAIL;
 639         char *memcg;
 640         long current, max;
 641 
 642         memcg = cg_name(root, "memcg_test");
 643         if (!memcg)
 644                 goto cleanup;
 645 
 646         if (cg_create(memcg))
 647                 goto cleanup;
 648 
 649         if (cg_read_strcmp(memcg, "memory.max", "max\n"))
 650                 goto cleanup;
 651 
 652         if (cg_write(memcg, "memory.swap.max", "0"))
 653                 goto cleanup;
 654 
 655         if (cg_write(memcg, "memory.max", "30M"))
 656                 goto cleanup;
 657 
 658         /* Should be killed by OOM killer */
 659         if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
 660                 goto cleanup;
 661 
 662         if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
 663                 goto cleanup;
 664 
 665         current = cg_read_long(memcg, "memory.current");
 666         if (current > MB(30) || !current)
 667                 goto cleanup;
 668 
 669         max = cg_read_key_long(memcg, "memory.events", "max ");
 670         if (max <= 0)
 671                 goto cleanup;
 672 
 673         ret = KSFT_PASS;
 674 
 675 cleanup:
 676         cg_destroy(memcg);
 677         free(memcg);
 678 
 679         return ret;
 680 }
 681 
 682 static int alloc_anon_50M_check_swap(const char *cgroup, void *arg)
 683 {
 684         long mem_max = (long)arg;
 685         size_t size = MB(50);
 686         char *buf, *ptr;
 687         long mem_current, swap_current;
 688         int ret = -1;
 689 
 690         buf = malloc(size);
 691         for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
 692                 *ptr = 0;
 693 
 694         mem_current = cg_read_long(cgroup, "memory.current");
 695         if (!mem_current || !values_close(mem_current, mem_max, 3))
 696                 goto cleanup;
 697 
 698         swap_current = cg_read_long(cgroup, "memory.swap.current");
 699         if (!swap_current ||
 700             !values_close(mem_current + swap_current, size, 3))
 701                 goto cleanup;
 702 
 703         ret = 0;
 704 cleanup:
 705         free(buf);
 706         return ret;
 707 }
 708 
 709 /*
 710  * This test checks that memory.swap.max limits the amount of
 711  * anonymous memory which can be swapped out.
 712  */
 713 static int test_memcg_swap_max(const char *root)
 714 {
 715         int ret = KSFT_FAIL;
 716         char *memcg;
 717         long max;
 718 
 719         if (!is_swap_enabled())
 720                 return KSFT_SKIP;
 721 
 722         memcg = cg_name(root, "memcg_test");
 723         if (!memcg)
 724                 goto cleanup;
 725 
 726         if (cg_create(memcg))
 727                 goto cleanup;
 728 
 729         if (cg_read_long(memcg, "memory.swap.current")) {
 730                 ret = KSFT_SKIP;
 731                 goto cleanup;
 732         }
 733 
 734         if (cg_read_strcmp(memcg, "memory.max", "max\n"))
 735                 goto cleanup;
 736 
 737         if (cg_read_strcmp(memcg, "memory.swap.max", "max\n"))
 738                 goto cleanup;
 739 
 740         if (cg_write(memcg, "memory.swap.max", "30M"))
 741                 goto cleanup;
 742 
 743         if (cg_write(memcg, "memory.max", "30M"))
 744                 goto cleanup;
 745 
 746         /* Should be killed by OOM killer */
 747         if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
 748                 goto cleanup;
 749 
 750         if (cg_read_key_long(memcg, "memory.events", "oom ") != 1)
 751                 goto cleanup;
 752 
 753         if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 1)
 754                 goto cleanup;
 755 
 756         if (cg_run(memcg, alloc_anon_50M_check_swap, (void *)MB(30)))
 757                 goto cleanup;
 758 
 759         max = cg_read_key_long(memcg, "memory.events", "max ");
 760         if (max <= 0)
 761                 goto cleanup;
 762 
 763         ret = KSFT_PASS;
 764 
 765 cleanup:
 766         cg_destroy(memcg);
 767         free(memcg);
 768 
 769         return ret;
 770 }
 771 
 772 /*
 773  * This test disables swapping and tries to allocate anonymous memory
 774  * up to OOM. Then it checks for oom and oom_kill events in
 775  * memory.events.
 776  */
 777 static int test_memcg_oom_events(const char *root)
 778 {
 779         int ret = KSFT_FAIL;
 780         char *memcg;
 781 
 782         memcg = cg_name(root, "memcg_test");
 783         if (!memcg)
 784                 goto cleanup;
 785 
 786         if (cg_create(memcg))
 787                 goto cleanup;
 788 
 789         if (cg_write(memcg, "memory.max", "30M"))
 790                 goto cleanup;
 791 
 792         if (cg_write(memcg, "memory.swap.max", "0"))
 793                 goto cleanup;
 794 
 795         if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
 796                 goto cleanup;
 797 
 798         if (cg_read_strcmp(memcg, "cgroup.procs", ""))
 799                 goto cleanup;
 800 
 801         if (cg_read_key_long(memcg, "memory.events", "oom ") != 1)
 802                 goto cleanup;
 803 
 804         if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 1)
 805                 goto cleanup;
 806 
 807         ret = KSFT_PASS;
 808 
 809 cleanup:
 810         cg_destroy(memcg);
 811         free(memcg);
 812 
 813         return ret;
 814 }
 815 
 816 struct tcp_server_args {
 817         unsigned short port;
 818         int ctl[2];
 819 };
 820 
 821 static int tcp_server(const char *cgroup, void *arg)
 822 {
 823         struct tcp_server_args *srv_args = arg;
 824         struct sockaddr_in6 saddr = { 0 };
 825         socklen_t slen = sizeof(saddr);
 826         int sk, client_sk, ctl_fd, yes = 1, ret = -1;
 827 
 828         close(srv_args->ctl[0]);
 829         ctl_fd = srv_args->ctl[1];
 830 
 831         saddr.sin6_family = AF_INET6;
 832         saddr.sin6_addr = in6addr_any;
 833         saddr.sin6_port = htons(srv_args->port);
 834 
 835         sk = socket(AF_INET6, SOCK_STREAM, 0);
 836         if (sk < 0)
 837                 return ret;
 838 
 839         if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
 840                 goto cleanup;
 841 
 842         if (bind(sk, (struct sockaddr *)&saddr, slen)) {
 843                 write(ctl_fd, &errno, sizeof(errno));
 844                 goto cleanup;
 845         }
 846 
 847         if (listen(sk, 1))
 848                 goto cleanup;
 849 
 850         ret = 0;
 851         if (write(ctl_fd, &ret, sizeof(ret)) != sizeof(ret)) {
 852                 ret = -1;
 853                 goto cleanup;
 854         }
 855 
 856         client_sk = accept(sk, NULL, NULL);
 857         if (client_sk < 0)
 858                 goto cleanup;
 859 
 860         ret = -1;
 861         for (;;) {
 862                 uint8_t buf[0x100000];
 863 
 864                 if (write(client_sk, buf, sizeof(buf)) <= 0) {
 865                         if (errno == ECONNRESET)
 866                                 ret = 0;
 867                         break;
 868                 }
 869         }
 870 
 871         close(client_sk);
 872 
 873 cleanup:
 874         close(sk);
 875         return ret;
 876 }
 877 
 878 static int tcp_client(const char *cgroup, unsigned short port)
 879 {
 880         const char server[] = "localhost";
 881         struct addrinfo *ai;
 882         char servport[6];
 883         int retries = 0x10; /* nice round number */
 884         int sk, ret;
 885 
 886         snprintf(servport, sizeof(servport), "%hd", port);
 887         ret = getaddrinfo(server, servport, NULL, &ai);
 888         if (ret)
 889                 return ret;
 890 
 891         sk = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 892         if (sk < 0)
 893                 goto free_ainfo;
 894 
 895         ret = connect(sk, ai->ai_addr, ai->ai_addrlen);
 896         if (ret < 0)
 897                 goto close_sk;
 898 
 899         ret = KSFT_FAIL;
 900         while (retries--) {
 901                 uint8_t buf[0x100000];
 902                 long current, sock;
 903 
 904                 if (read(sk, buf, sizeof(buf)) <= 0)
 905                         goto close_sk;
 906 
 907                 current = cg_read_long(cgroup, "memory.current");
 908                 sock = cg_read_key_long(cgroup, "memory.stat", "sock ");
 909 
 910                 if (current < 0 || sock < 0)
 911                         goto close_sk;
 912 
 913                 if (current < sock)
 914                         goto close_sk;
 915 
 916                 if (values_close(current, sock, 10)) {
 917                         ret = KSFT_PASS;
 918                         break;
 919                 }
 920         }
 921 
 922 close_sk:
 923         close(sk);
 924 free_ainfo:
 925         freeaddrinfo(ai);
 926         return ret;
 927 }
 928 
 929 /*
 930  * This test checks socket memory accounting.
 931  * The test forks a TCP server listens on a random port between 1000
 932  * and 61000. Once it gets a client connection, it starts writing to
 933  * its socket.
 934  * The TCP client interleaves reads from the socket with check whether
 935  * memory.current and memory.stat.sock are similar.
 936  */
 937 static int test_memcg_sock(const char *root)
 938 {
 939         int bind_retries = 5, ret = KSFT_FAIL, pid, err;
 940         unsigned short port;
 941         char *memcg;
 942 
 943         memcg = cg_name(root, "memcg_test");
 944         if (!memcg)
 945                 goto cleanup;
 946 
 947         if (cg_create(memcg))
 948                 goto cleanup;
 949 
 950         while (bind_retries--) {
 951                 struct tcp_server_args args;
 952 
 953                 if (pipe(args.ctl))
 954                         goto cleanup;
 955 
 956                 port = args.port = 1000 + rand() % 60000;
 957 
 958                 pid = cg_run_nowait(memcg, tcp_server, &args);
 959                 if (pid < 0)
 960                         goto cleanup;
 961 
 962                 close(args.ctl[1]);
 963                 if (read(args.ctl[0], &err, sizeof(err)) != sizeof(err))
 964                         goto cleanup;
 965                 close(args.ctl[0]);
 966 
 967                 if (!err)
 968                         break;
 969                 if (err != EADDRINUSE)
 970                         goto cleanup;
 971 
 972                 waitpid(pid, NULL, 0);
 973         }
 974 
 975         if (err == EADDRINUSE) {
 976                 ret = KSFT_SKIP;
 977                 goto cleanup;
 978         }
 979 
 980         if (tcp_client(memcg, port) != KSFT_PASS)
 981                 goto cleanup;
 982 
 983         waitpid(pid, &err, 0);
 984         if (WEXITSTATUS(err))
 985                 goto cleanup;
 986 
 987         if (cg_read_long(memcg, "memory.current") < 0)
 988                 goto cleanup;
 989 
 990         if (cg_read_key_long(memcg, "memory.stat", "sock "))
 991                 goto cleanup;
 992 
 993         ret = KSFT_PASS;
 994 
 995 cleanup:
 996         cg_destroy(memcg);
 997         free(memcg);
 998 
 999         return ret;
1000 }
1001 
1002 /*
1003  * This test disables swapping and tries to allocate anonymous memory
1004  * up to OOM with memory.group.oom set. Then it checks that all
1005  * processes in the leaf (but not the parent) were killed.
1006  */
1007 static int test_memcg_oom_group_leaf_events(const char *root)
1008 {
1009         int ret = KSFT_FAIL;
1010         char *parent, *child;
1011 
1012         parent = cg_name(root, "memcg_test_0");
1013         child = cg_name(root, "memcg_test_0/memcg_test_1");
1014 
1015         if (!parent || !child)
1016                 goto cleanup;
1017 
1018         if (cg_create(parent))
1019                 goto cleanup;
1020 
1021         if (cg_create(child))
1022                 goto cleanup;
1023 
1024         if (cg_write(parent, "cgroup.subtree_control", "+memory"))
1025                 goto cleanup;
1026 
1027         if (cg_write(child, "memory.max", "50M"))
1028                 goto cleanup;
1029 
1030         if (cg_write(child, "memory.swap.max", "0"))
1031                 goto cleanup;
1032 
1033         if (cg_write(child, "memory.oom.group", "1"))
1034                 goto cleanup;
1035 
1036         cg_run_nowait(parent, alloc_anon_noexit, (void *) MB(60));
1037         cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
1038         cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
1039         if (!cg_run(child, alloc_anon, (void *)MB(100)))
1040                 goto cleanup;
1041 
1042         if (cg_test_proc_killed(child))
1043                 goto cleanup;
1044 
1045         if (cg_read_key_long(child, "memory.events", "oom_kill ") <= 0)
1046                 goto cleanup;
1047 
1048         if (cg_read_key_long(parent, "memory.events", "oom_kill ") != 0)
1049                 goto cleanup;
1050 
1051         ret = KSFT_PASS;
1052 
1053 cleanup:
1054         if (child)
1055                 cg_destroy(child);
1056         if (parent)
1057                 cg_destroy(parent);
1058         free(child);
1059         free(parent);
1060 
1061         return ret;
1062 }
1063 
1064 /*
1065  * This test disables swapping and tries to allocate anonymous memory
1066  * up to OOM with memory.group.oom set. Then it checks that all
1067  * processes in the parent and leaf were killed.
1068  */
1069 static int test_memcg_oom_group_parent_events(const char *root)
1070 {
1071         int ret = KSFT_FAIL;
1072         char *parent, *child;
1073 
1074         parent = cg_name(root, "memcg_test_0");
1075         child = cg_name(root, "memcg_test_0/memcg_test_1");
1076 
1077         if (!parent || !child)
1078                 goto cleanup;
1079 
1080         if (cg_create(parent))
1081                 goto cleanup;
1082 
1083         if (cg_create(child))
1084                 goto cleanup;
1085 
1086         if (cg_write(parent, "memory.max", "80M"))
1087                 goto cleanup;
1088 
1089         if (cg_write(parent, "memory.swap.max", "0"))
1090                 goto cleanup;
1091 
1092         if (cg_write(parent, "memory.oom.group", "1"))
1093                 goto cleanup;
1094 
1095         cg_run_nowait(parent, alloc_anon_noexit, (void *) MB(60));
1096         cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
1097         cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
1098 
1099         if (!cg_run(child, alloc_anon, (void *)MB(100)))
1100                 goto cleanup;
1101 
1102         if (cg_test_proc_killed(child))
1103                 goto cleanup;
1104         if (cg_test_proc_killed(parent))
1105                 goto cleanup;
1106 
1107         ret = KSFT_PASS;
1108 
1109 cleanup:
1110         if (child)
1111                 cg_destroy(child);
1112         if (parent)
1113                 cg_destroy(parent);
1114         free(child);
1115         free(parent);
1116 
1117         return ret;
1118 }
1119 
1120 /*
1121  * This test disables swapping and tries to allocate anonymous memory
1122  * up to OOM with memory.group.oom set. Then it checks that all
1123  * processes were killed except those set with OOM_SCORE_ADJ_MIN
1124  */
1125 static int test_memcg_oom_group_score_events(const char *root)
1126 {
1127         int ret = KSFT_FAIL;
1128         char *memcg;
1129         int safe_pid;
1130 
1131         memcg = cg_name(root, "memcg_test_0");
1132 
1133         if (!memcg)
1134                 goto cleanup;
1135 
1136         if (cg_create(memcg))
1137                 goto cleanup;
1138 
1139         if (cg_write(memcg, "memory.max", "50M"))
1140                 goto cleanup;
1141 
1142         if (cg_write(memcg, "memory.swap.max", "0"))
1143                 goto cleanup;
1144 
1145         if (cg_write(memcg, "memory.oom.group", "1"))
1146                 goto cleanup;
1147 
1148         safe_pid = cg_run_nowait(memcg, alloc_anon_noexit, (void *) MB(1));
1149         if (set_oom_adj_score(safe_pid, OOM_SCORE_ADJ_MIN))
1150                 goto cleanup;
1151 
1152         cg_run_nowait(memcg, alloc_anon_noexit, (void *) MB(1));
1153         if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
1154                 goto cleanup;
1155 
1156         if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 3)
1157                 goto cleanup;
1158 
1159         if (kill(safe_pid, SIGKILL))
1160                 goto cleanup;
1161 
1162         ret = KSFT_PASS;
1163 
1164 cleanup:
1165         if (memcg)
1166                 cg_destroy(memcg);
1167         free(memcg);
1168 
1169         return ret;
1170 }
1171 
1172 
1173 #define T(x) { x, #x }
1174 struct memcg_test {
1175         int (*fn)(const char *root);
1176         const char *name;
1177 } tests[] = {
1178         T(test_memcg_subtree_control),
1179         T(test_memcg_current),
1180         T(test_memcg_min),
1181         T(test_memcg_low),
1182         T(test_memcg_high),
1183         T(test_memcg_max),
1184         T(test_memcg_oom_events),
1185         T(test_memcg_swap_max),
1186         T(test_memcg_sock),
1187         T(test_memcg_oom_group_leaf_events),
1188         T(test_memcg_oom_group_parent_events),
1189         T(test_memcg_oom_group_score_events),
1190 };
1191 #undef T
1192 
1193 int main(int argc, char **argv)
1194 {
1195         char root[PATH_MAX];
1196         int i, ret = EXIT_SUCCESS;
1197 
1198         if (cg_find_unified_root(root, sizeof(root)))
1199                 ksft_exit_skip("cgroup v2 isn't mounted\n");
1200 
1201         /*
1202          * Check that memory controller is available:
1203          * memory is listed in cgroup.controllers
1204          */
1205         if (cg_read_strstr(root, "cgroup.controllers", "memory"))
1206                 ksft_exit_skip("memory controller isn't available\n");
1207 
1208         if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
1209                 if (cg_write(root, "cgroup.subtree_control", "+memory"))
1210                         ksft_exit_skip("Failed to set memory controller\n");
1211 
1212         for (i = 0; i < ARRAY_SIZE(tests); i++) {
1213                 switch (tests[i].fn(root)) {
1214                 case KSFT_PASS:
1215                         ksft_test_result_pass("%s\n", tests[i].name);
1216                         break;
1217                 case KSFT_SKIP:
1218                         ksft_test_result_skip("%s\n", tests[i].name);
1219                         break;
1220                 default:
1221                         ret = EXIT_FAILURE;
1222                         ksft_test_result_fail("%s\n", tests[i].name);
1223                         break;
1224                 }
1225         }
1226 
1227         return ret;
1228 }

/* [<][>][^][v][top][bottom][index][help] */