1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE 3 4 #include <linux/limits.h> 5 #include <unistd.h> 6 #include <stdio.h> 7 #include <signal.h> 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <sys/sysinfo.h> 11 #include <string.h> 12 #include <sys/wait.h> 13 #include <sys/mman.h> 14 #include <sys/random.h> 15 16 #include "kselftest.h" 17 #include "cgroup_util.h" 18 19 static int page_size; 20 21 #define PATH_ZSWAP "/sys/module/zswap" 22 #define PATH_ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled" 23 24 static int read_int(const char *path, size_t *value) 25 { 26 FILE *file; 27 int ret = 0; 28 29 file = fopen(path, "r"); 30 if (!file) 31 return -1; 32 if (fscanf(file, "%ld", value) != 1) 33 ret = -1; 34 fclose(file); 35 return ret; 36 } 37 38 static int set_min_free_kb(size_t value) 39 { 40 FILE *file; 41 int ret; 42 43 file = fopen("/proc/sys/vm/min_free_kbytes", "w"); 44 if (!file) 45 return -1; 46 ret = fprintf(file, "%ld\n", value); 47 fclose(file); 48 return ret; 49 } 50 51 static int read_min_free_kb(size_t *value) 52 { 53 return read_int("/proc/sys/vm/min_free_kbytes", value); 54 } 55 56 static int get_zswap_stored_pages(size_t *value) 57 { 58 return read_int("/sys/kernel/debug/zswap/stored_pages", value); 59 } 60 61 static long get_cg_wb_count(const char *cg) 62 { 63 return cg_read_key_long(cg, "memory.stat", "zswpwb"); 64 } 65 66 static long get_zswpout(const char *cgroup) 67 { 68 return cg_read_key_long(cgroup, "memory.stat", "zswpout "); 69 } 70 71 static int allocate_and_read_bytes(const char *cgroup, void *arg) 72 { 73 size_t size = (size_t)arg; 74 char *mem = (char *)malloc(size); 75 int ret = 0; 76 77 if (!mem) 78 return -1; 79 for (int i = 0; i < size; i += page_size) 80 mem[i] = 'a'; 81 82 /* Go through the allocated memory to (z)swap in and out pages */ 83 for (int i = 0; i < size; i += page_size) { 84 if (mem[i] != 'a') 85 ret = -1; 86 } 87 88 free(mem); 89 return ret; 90 } 91 92 static int allocate_bytes(const char *cgroup, void *arg) 93 { 94 size_t size = (size_t)arg; 95 char *mem = (char *)malloc(size); 96 97 if (!mem) 98 return -1; 99 for (int i = 0; i < size; i += page_size) 100 mem[i] = 'a'; 101 free(mem); 102 return 0; 103 } 104 105 static char *setup_test_group_1M(const char *root, const char *name) 106 { 107 char *group_name = cg_name(root, name); 108 109 if (!group_name) 110 return NULL; 111 if (cg_create(group_name)) 112 goto fail; 113 if (cg_write(group_name, "memory.max", "1M")) { 114 cg_destroy(group_name); 115 goto fail; 116 } 117 return group_name; 118 fail: 119 free(group_name); 120 return NULL; 121 } 122 123 /* 124 * Writeback is asynchronous; poll until at least one writeback has 125 * been recorded for @cg, or until @timeout_ms has elapsed. 126 */ 127 static long wait_for_writeback(const char *cg, int timeout_ms) 128 { 129 long elapsed, count; 130 for (elapsed = 0; elapsed < timeout_ms; elapsed += 100) { 131 count = get_cg_wb_count(cg); 132 133 if (count < 0) 134 return -1; 135 if (count > 0) 136 return count; 137 138 usleep(100000); 139 } 140 141 return 0; 142 } 143 144 /* 145 * Sanity test to check that pages are written into zswap. 146 */ 147 static int test_zswap_usage(const char *root) 148 { 149 long zswpout_before, zswpout_after; 150 int ret = KSFT_FAIL; 151 char *test_group; 152 153 test_group = cg_name(root, "no_shrink_test"); 154 if (!test_group) 155 goto out; 156 if (cg_create(test_group)) 157 goto out; 158 if (cg_write(test_group, "memory.max", "1M")) 159 goto out; 160 161 zswpout_before = get_zswpout(test_group); 162 if (zswpout_before < 0) { 163 ksft_print_msg("Failed to get zswpout\n"); 164 goto out; 165 } 166 167 /* Allocate more than memory.max to push memory into zswap */ 168 if (cg_run(test_group, allocate_bytes, (void *)MB(4))) 169 goto out; 170 171 /* Verify that pages come into zswap */ 172 zswpout_after = get_zswpout(test_group); 173 if (zswpout_after <= zswpout_before) { 174 ksft_print_msg("zswpout does not increase after test program\n"); 175 goto out; 176 } 177 ret = KSFT_PASS; 178 179 out: 180 cg_destroy(test_group); 181 free(test_group); 182 return ret; 183 } 184 185 /* 186 * Check that when memory.zswap.max = 0, no pages can go to the zswap pool for 187 * the cgroup. 188 */ 189 static int test_swapin_nozswap(const char *root) 190 { 191 int ret = KSFT_FAIL; 192 char *test_group, mem_max_buf[32]; 193 long swap_peak, zswpout, min_swap; 194 size_t allocation_size = page_size * 512; 195 196 min_swap = allocation_size / 4; 197 snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", allocation_size * 3/4); 198 199 test_group = cg_name(root, "no_zswap_test"); 200 if (!test_group) 201 goto out; 202 if (cg_create(test_group)) 203 goto out; 204 if (cg_write(test_group, "memory.max", mem_max_buf)) 205 goto out; 206 if (cg_write(test_group, "memory.zswap.max", "0")) 207 goto out; 208 209 /* Allocate and read more than memory.max to trigger swapin */ 210 if (cg_run(test_group, allocate_and_read_bytes, (void *)allocation_size)) 211 goto out; 212 213 /* Verify that pages are swapped out, but no zswap happened */ 214 swap_peak = cg_read_long(test_group, "memory.swap.peak"); 215 if (swap_peak < 0) { 216 ksft_print_msg("failed to get cgroup's swap_peak\n"); 217 goto out; 218 } 219 220 if (swap_peak < min_swap) { 221 ksft_print_msg("at least %ldKB of memory should be swapped out\n", 222 min_swap / 1024); 223 goto out; 224 } 225 226 zswpout = get_zswpout(test_group); 227 if (zswpout < 0) { 228 ksft_print_msg("failed to get zswpout\n"); 229 goto out; 230 } 231 232 if (zswpout > 0) { 233 ksft_print_msg("zswapout > 0 when memory.zswap.max = 0\n"); 234 goto out; 235 } 236 237 ret = KSFT_PASS; 238 239 out: 240 cg_destroy(test_group); 241 free(test_group); 242 return ret; 243 } 244 245 /* Simple test to verify the (z)swapin code paths */ 246 static int test_zswapin(const char *root) 247 { 248 int ret = KSFT_FAIL; 249 char *test_group; 250 long zswpin; 251 252 test_group = cg_name(root, "zswapin_test"); 253 if (!test_group) 254 goto out; 255 if (cg_create(test_group)) 256 goto out; 257 if (cg_write(test_group, "memory.max", "8M")) 258 goto out; 259 if (cg_write(test_group, "memory.zswap.max", "max")) 260 goto out; 261 262 /* Allocate and read more than memory.max to trigger (z)swap in */ 263 if (cg_run(test_group, allocate_and_read_bytes, (void *)MB(32))) 264 goto out; 265 266 zswpin = cg_read_key_long(test_group, "memory.stat", "zswpin "); 267 if (zswpin < 0) { 268 ksft_print_msg("failed to get zswpin\n"); 269 goto out; 270 } 271 272 if (zswpin < MB(24) / page_size) { 273 ksft_print_msg("at least 24MB should be brought back from zswap\n"); 274 goto out; 275 } 276 277 ret = KSFT_PASS; 278 279 out: 280 cg_destroy(test_group); 281 free(test_group); 282 return ret; 283 } 284 285 /* 286 * Attempt writeback with the following steps: 287 * 1. Allocate memory. 288 * 2. Reclaim memory equal to the amount that was allocated in step 1. 289 This will move it into zswap. 290 * 3. Save current zswap usage. 291 * 4. Move the memory allocated in step 1 back in from zswap. 292 * 5. Set zswap.max to 1/4 of the amount that was recorded in step 3. 293 * 6. Attempt to reclaim memory equal to the amount that was allocated, 294 this will either trigger writeback if it's enabled, or reclamation 295 will fail if writeback is disabled as there isn't enough zswap space. 296 */ 297 static int attempt_writeback(const char *cgroup, void *arg) 298 { 299 size_t memsize = page_size * 1024; 300 char buf[page_size]; 301 long zswap_usage; 302 bool wb_enabled = *(bool *) arg; 303 int ret = -1; 304 char *mem; 305 306 mem = (char *)malloc(memsize); 307 if (!mem) 308 return ret; 309 310 /* 311 * Fill half of each page with increasing data, and keep other 312 * half empty, this will result in data that is still compressible 313 * and ends up in zswap, with material zswap usage. 314 */ 315 for (int i = 0; i < page_size; i++) 316 buf[i] = i < page_size/2 ? (char) i : 0; 317 318 for (int i = 0; i < memsize; i += page_size) 319 memcpy(&mem[i], buf, page_size); 320 321 /* Try and reclaim allocated memory */ 322 if (cg_write_numeric(cgroup, "memory.reclaim", memsize)) { 323 ksft_print_msg("Failed to reclaim all of the requested memory\n"); 324 goto out; 325 } 326 327 zswap_usage = cg_read_long(cgroup, "memory.zswap.current"); 328 329 /* zswpin */ 330 for (int i = 0; i < memsize; i += page_size) { 331 if (memcmp(&mem[i], buf, page_size)) { 332 ksft_print_msg("invalid memory\n"); 333 goto out; 334 } 335 } 336 337 if (cg_write_numeric(cgroup, "memory.zswap.max", zswap_usage/4)) 338 goto out; 339 340 /* 341 * If writeback is enabled, trying to reclaim memory now will trigger a 342 * writeback as zswap.max is 1/4 of what was needed when reclaim ran the first time. 343 * If writeback is disabled, memory reclaim will fail as zswap is limited and 344 * it can't writeback to swap. 345 */ 346 ret = cg_write_numeric(cgroup, "memory.reclaim", memsize); 347 if (!wb_enabled) 348 ret = (ret == -EAGAIN) ? 0 : -1; 349 350 out: 351 free(mem); 352 return ret; 353 } 354 355 static int test_zswap_writeback_one(const char *cgroup, bool wb) 356 { 357 long zswpwb_before, zswpwb_after; 358 359 zswpwb_before = get_cg_wb_count(cgroup); 360 if (zswpwb_before != 0) { 361 ksft_print_msg("zswpwb_before = %ld instead of 0\n", zswpwb_before); 362 return -1; 363 } 364 365 if (cg_run(cgroup, attempt_writeback, (void *) &wb)) 366 return -1; 367 368 /* Verify that zswap writeback occurred only if writeback was enabled */ 369 if (wb) 370 zswpwb_after = wait_for_writeback(cgroup, 5000); 371 else 372 zswpwb_after = get_cg_wb_count(cgroup); 373 if (zswpwb_after < 0) 374 return -1; 375 376 if (wb != !!zswpwb_after) { 377 ksft_print_msg("zswpwb_after is %ld while wb is %s\n", 378 zswpwb_after, wb ? "enabled" : "disabled"); 379 return -1; 380 } 381 382 return 0; 383 } 384 385 /* Test to verify the zswap writeback path */ 386 static int test_zswap_writeback(const char *root, bool wb) 387 { 388 int ret = KSFT_FAIL; 389 char *test_group, *test_group_child = NULL; 390 391 if (cg_read_strcmp(root, "memory.zswap.writeback", "1")) 392 return KSFT_SKIP; 393 394 test_group = cg_name(root, "zswap_writeback_test"); 395 if (!test_group) 396 goto out; 397 if (cg_create(test_group)) 398 goto out; 399 if (cg_write(test_group, "memory.zswap.writeback", wb ? "1" : "0")) 400 goto out; 401 402 if (test_zswap_writeback_one(test_group, wb)) 403 goto out; 404 405 /* Reset memory.zswap.max to max (modified by attempt_writeback), and 406 * set up child cgroup, whose memory.zswap.writeback is hardcoded to 1. 407 * Thus, the parent's setting shall be what's in effect. */ 408 if (cg_write(test_group, "memory.zswap.max", "max")) 409 goto out; 410 if (cg_write(test_group, "cgroup.subtree_control", "+memory")) 411 goto out; 412 413 test_group_child = cg_name(test_group, "zswap_writeback_test_child"); 414 if (!test_group_child) 415 goto out; 416 if (cg_create(test_group_child)) 417 goto out; 418 if (cg_write(test_group_child, "memory.zswap.writeback", "1")) 419 goto out; 420 421 if (test_zswap_writeback_one(test_group_child, wb)) 422 goto out; 423 424 ret = KSFT_PASS; 425 426 out: 427 if (test_group_child) { 428 cg_destroy(test_group_child); 429 free(test_group_child); 430 } 431 cg_destroy(test_group); 432 free(test_group); 433 return ret; 434 } 435 436 static int test_zswap_writeback_enabled(const char *root) 437 { 438 return test_zswap_writeback(root, true); 439 } 440 441 static int test_zswap_writeback_disabled(const char *root) 442 { 443 return test_zswap_writeback(root, false); 444 } 445 446 /* 447 * When trying to store a memcg page in zswap, if the memcg hits its memory 448 * limit in zswap, writeback should affect only the zswapped pages of that 449 * memcg. 450 */ 451 static int test_no_invasive_cgroup_shrink(const char *root) 452 { 453 int ret = KSFT_FAIL; 454 unsigned int off; 455 size_t allocation_size = page_size * 1024; 456 unsigned int nr_pages = allocation_size / page_size; 457 char zswap_max_buf[32], mem_max_buf[32]; 458 char *zw_allocation = NULL, *wb_allocation = NULL; 459 char *zw_group = NULL, *wb_group = NULL; 460 461 snprintf(zswap_max_buf, sizeof(zswap_max_buf), "%d", page_size); 462 snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", allocation_size / 2); 463 464 wb_group = setup_test_group_1M(root, "per_memcg_wb_test1"); 465 if (!wb_group) 466 return KSFT_FAIL; 467 if (cg_write(wb_group, "memory.zswap.max", zswap_max_buf)) 468 goto out; 469 if (cg_write(wb_group, "memory.max", mem_max_buf)) 470 goto out; 471 472 zw_group = setup_test_group_1M(root, "per_memcg_wb_test2"); 473 if (!zw_group) 474 goto out; 475 if (cg_write(zw_group, "memory.max", mem_max_buf)) 476 goto out; 477 478 /* Push some zw_group memory into zswap (simple data, easy to compress) */ 479 if (cg_enter_current(zw_group)) 480 goto out; 481 zw_allocation = malloc(allocation_size); 482 for (int i = 0; i < nr_pages; i++) { 483 off = (unsigned long)i * page_size; 484 memset(&zw_allocation[off], 0, page_size); 485 memset(&zw_allocation[off], 'a', page_size/4); 486 } 487 if (cg_read_key_long(zw_group, "memory.stat", "zswapped") < 1) 488 goto out; 489 490 /* Push wb_group memory into zswap with hard-to-compress data to trigger wb */ 491 if (cg_enter_current(wb_group)) 492 goto out; 493 wb_allocation = malloc(allocation_size); 494 if (!wb_allocation) 495 goto out; 496 for (int i = 0; i < nr_pages; i++) { 497 off = (unsigned long)i * page_size; 498 memset(&wb_allocation[off], 0, page_size); 499 getrandom(&wb_allocation[off], page_size/4, 0); 500 } 501 502 /* Verify that only zswapped memory from gwb_group has been written back */ 503 if (wait_for_writeback(wb_group, 5000) > 0 && get_cg_wb_count(zw_group) == 0) 504 ret = KSFT_PASS; 505 out: 506 cg_enter_current(root); 507 if (zw_group) { 508 cg_destroy(zw_group); 509 free(zw_group); 510 } 511 if (wb_group) { 512 cg_destroy(wb_group); 513 free(wb_group); 514 } 515 if (zw_allocation) 516 free(zw_allocation); 517 if (wb_allocation) 518 free(wb_allocation); 519 return ret; 520 } 521 522 struct no_kmem_bypass_child_args { 523 size_t target_alloc_bytes; 524 size_t child_allocated; 525 }; 526 527 static int no_kmem_bypass_child(const char *cgroup, void *arg) 528 { 529 struct no_kmem_bypass_child_args *values = arg; 530 void *allocation; 531 532 allocation = malloc(values->target_alloc_bytes); 533 if (!allocation) { 534 values->child_allocated = true; 535 return -1; 536 } 537 for (long i = 0; i < values->target_alloc_bytes; i += page_size) 538 ((char *)allocation)[i] = 'a'; 539 values->child_allocated = true; 540 pause(); 541 free(allocation); 542 return 0; 543 } 544 545 /* 546 * When pages owned by a memcg are pushed to zswap by kswapd, they should be 547 * charged to that cgroup. This wasn't the case before commit 548 * cd08d80ecdac("mm: correctly charge compressed memory to its memcg"). 549 * 550 * The test first allocates memory in a memcg, then raises min_free_kbytes to 551 * a very high value so that the allocation falls below low wm, then makes 552 * another allocation to trigger kswapd that should push the memcg-owned pages 553 * to zswap and verifies that the zswap pages are correctly charged. 554 * 555 * To be run on a VM with at most 4G of memory. 556 */ 557 static int test_no_kmem_bypass(const char *root) 558 { 559 size_t min_free_kb_high, min_free_kb_low, min_free_kb_original; 560 struct no_kmem_bypass_child_args *values; 561 size_t trigger_allocation_size; 562 int wait_child_iteration = 0; 563 long stored_pages_threshold; 564 struct sysinfo sys_info; 565 int ret = KSFT_FAIL; 566 int child_status; 567 char *test_group = NULL; 568 pid_t child_pid; 569 570 /* Read sys info and compute test values accordingly */ 571 if (sysinfo(&sys_info) != 0) 572 return KSFT_FAIL; 573 if (sys_info.totalram > 5000000000) 574 return KSFT_SKIP; 575 values = mmap(0, sizeof(struct no_kmem_bypass_child_args), PROT_READ | 576 PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 577 if (values == MAP_FAILED) 578 return KSFT_FAIL; 579 if (read_min_free_kb(&min_free_kb_original)) 580 return KSFT_FAIL; 581 min_free_kb_high = sys_info.totalram / 2000; 582 min_free_kb_low = sys_info.totalram / 500000; 583 values->target_alloc_bytes = (sys_info.totalram - min_free_kb_high * 1000) + 584 sys_info.totalram * 5 / 100; 585 stored_pages_threshold = sys_info.totalram / 5 / page_size; 586 trigger_allocation_size = sys_info.totalram / 20; 587 588 /* Set up test memcg */ 589 test_group = cg_name(root, "kmem_bypass_test"); 590 if (!test_group) 591 goto out; 592 593 /* Spawn memcg child and wait for it to allocate */ 594 set_min_free_kb(min_free_kb_low); 595 if (cg_create(test_group)) 596 goto out; 597 values->child_allocated = false; 598 child_pid = cg_run_nowait(test_group, no_kmem_bypass_child, values); 599 if (child_pid < 0) 600 goto out; 601 while (!values->child_allocated && wait_child_iteration++ < 10000) 602 usleep(1000); 603 604 /* Try to wakeup kswapd and let it push child memory to zswap */ 605 set_min_free_kb(min_free_kb_high); 606 for (int i = 0; i < 20; i++) { 607 size_t stored_pages; 608 char *trigger_allocation = malloc(trigger_allocation_size); 609 610 if (!trigger_allocation) 611 break; 612 for (int i = 0; i < trigger_allocation_size; i += page_size) 613 trigger_allocation[i] = 'b'; 614 usleep(100000); 615 free(trigger_allocation); 616 if (get_zswap_stored_pages(&stored_pages)) 617 break; 618 if (stored_pages < 0) 619 break; 620 /* If memory was pushed to zswap, verify it belongs to memcg */ 621 if (stored_pages > stored_pages_threshold) { 622 int zswapped = cg_read_key_long(test_group, "memory.stat", "zswapped "); 623 int delta = stored_pages * page_size - zswapped; 624 int result_ok = delta < stored_pages * page_size / 4; 625 626 ret = result_ok ? KSFT_PASS : KSFT_FAIL; 627 break; 628 } 629 } 630 631 kill(child_pid, SIGTERM); 632 waitpid(child_pid, &child_status, 0); 633 out: 634 set_min_free_kb(min_free_kb_original); 635 cg_destroy(test_group); 636 free(test_group); 637 return ret; 638 } 639 640 struct incomp_child_args { 641 size_t size; 642 int pipefd[2]; 643 int madvise_ret; 644 int madvise_errno; 645 }; 646 647 static int allocate_random_and_wait(const char *cgroup, void *arg) 648 { 649 struct incomp_child_args *values = arg; 650 size_t size = values->size; 651 char *mem; 652 int fd; 653 ssize_t n; 654 655 close(values->pipefd[0]); 656 657 mem = mmap(NULL, size, PROT_READ | PROT_WRITE, 658 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 659 if (mem == MAP_FAILED) 660 return -1; 661 662 /* Fill with random data from /dev/urandom - incompressible */ 663 fd = open("/dev/urandom", O_RDONLY); 664 if (fd < 0) { 665 munmap(mem, size); 666 return -1; 667 } 668 669 for (size_t i = 0; i < size; ) { 670 n = read(fd, mem + i, size - i); 671 if (n <= 0) 672 break; 673 i += n; 674 } 675 close(fd); 676 677 /* Touch all pages to ensure they're faulted in */ 678 for (size_t i = 0; i < size; i += page_size) 679 mem[i] = mem[i]; 680 681 /* Use MADV_PAGEOUT to push pages into zswap */ 682 values->madvise_ret = madvise(mem, size, MADV_PAGEOUT); 683 values->madvise_errno = errno; 684 685 /* Notify parent that allocation and pageout are done */ 686 write(values->pipefd[1], "x", 1); 687 close(values->pipefd[1]); 688 689 /* Keep memory alive for parent to check stats */ 690 pause(); 691 munmap(mem, size); 692 return 0; 693 } 694 695 static long get_zswap_incomp(const char *cgroup) 696 { 697 return cg_read_key_long(cgroup, "memory.stat", "zswap_incomp "); 698 } 699 700 /* 701 * Test that incompressible pages (random data) are tracked by zswap_incomp. 702 * 703 * The child process allocates random data within memory.max, then uses 704 * MADV_PAGEOUT to push pages into zswap. The parent waits on a pipe for 705 * the child to finish, then checks the zswap_incomp stat before the child 706 * exits (zswap_incomp is a gauge that decreases on free). 707 */ 708 static int test_zswap_incompressible(const char *root) 709 { 710 int ret = KSFT_FAIL; 711 struct incomp_child_args *values; 712 char *test_group; 713 long zswap_incomp; 714 pid_t child_pid; 715 int child_status; 716 char buf; 717 718 values = mmap(0, sizeof(struct incomp_child_args), PROT_READ | 719 PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 720 if (values == MAP_FAILED) 721 return KSFT_FAIL; 722 723 if (pipe(values->pipefd)) { 724 munmap(values, sizeof(struct incomp_child_args)); 725 return KSFT_FAIL; 726 } 727 728 test_group = cg_name(root, "zswap_incompressible_test"); 729 if (!test_group) 730 goto out; 731 if (cg_create(test_group)) 732 goto out; 733 if (cg_write(test_group, "memory.max", "32M")) 734 goto out; 735 736 values->size = MB(4); 737 child_pid = cg_run_nowait(test_group, allocate_random_and_wait, values); 738 if (child_pid < 0) 739 goto out; 740 741 close(values->pipefd[1]); 742 743 /* Wait for child to finish allocating and pageout */ 744 read(values->pipefd[0], &buf, 1); 745 close(values->pipefd[0]); 746 747 zswap_incomp = get_zswap_incomp(test_group); 748 if (zswap_incomp <= 0) { 749 long zswpout = get_zswpout(test_group); 750 long zswapped = cg_read_key_long(test_group, "memory.stat", "zswapped "); 751 long zswap_b = cg_read_key_long(test_group, "memory.stat", "zswap "); 752 753 ksft_print_msg("zswap_incomp not increased: %ld\n", zswap_incomp); 754 ksft_print_msg("debug: zswpout=%ld zswapped=%ld zswap_b=%ld\n", 755 zswpout, zswapped, zswap_b); 756 ksft_print_msg("debug: madvise ret=%d errno=%d\n", 757 values->madvise_ret, values->madvise_errno); 758 goto out_kill; 759 } 760 761 ret = KSFT_PASS; 762 763 out_kill: 764 kill(child_pid, SIGTERM); 765 waitpid(child_pid, &child_status, 0); 766 out: 767 cg_destroy(test_group); 768 free(test_group); 769 munmap(values, sizeof(struct incomp_child_args)); 770 return ret; 771 } 772 773 #define T(x) { x, #x } 774 struct zswap_test { 775 int (*fn)(const char *root); 776 const char *name; 777 } tests[] = { 778 T(test_zswap_usage), 779 T(test_swapin_nozswap), 780 T(test_zswapin), 781 T(test_zswap_writeback_enabled), 782 T(test_zswap_writeback_disabled), 783 T(test_no_kmem_bypass), 784 T(test_no_invasive_cgroup_shrink), 785 T(test_zswap_incompressible), 786 }; 787 #undef T 788 789 static void check_zswap_enabled(void) 790 { 791 char value[2]; 792 793 if (access(PATH_ZSWAP, F_OK)) 794 ksft_exit_skip("zswap isn't configured\n"); 795 796 if (read_text(PATH_ZSWAP_ENABLED, value, sizeof(value)) <= 0) 797 ksft_exit_fail_msg("Failed to read " PATH_ZSWAP_ENABLED "\n"); 798 799 if (value[0] == 'N') 800 ksft_exit_skip("zswap is disabled (hint: echo 1 > " PATH_ZSWAP_ENABLED ")\n"); 801 } 802 803 int main(int argc, char **argv) 804 { 805 char root[PATH_MAX]; 806 int i; 807 808 page_size = sysconf(_SC_PAGE_SIZE); 809 if (page_size <= 0) 810 page_size = BUF_SIZE; 811 812 ksft_print_header(); 813 ksft_set_plan(ARRAY_SIZE(tests)); 814 if (cg_find_unified_root(root, sizeof(root), NULL)) 815 ksft_exit_skip("cgroup v2 isn't mounted\n"); 816 817 check_zswap_enabled(); 818 819 /* 820 * Check that memory controller is available: 821 * memory is listed in cgroup.controllers 822 */ 823 if (cg_read_strstr(root, "cgroup.controllers", "memory")) 824 ksft_exit_skip("memory controller isn't available\n"); 825 826 if (cg_read_strstr(root, "cgroup.subtree_control", "memory")) 827 if (cg_write(root, "cgroup.subtree_control", "+memory")) 828 ksft_exit_skip("Failed to set memory controller\n"); 829 830 for (i = 0; i < ARRAY_SIZE(tests); i++) { 831 switch (tests[i].fn(root)) { 832 case KSFT_PASS: 833 ksft_test_result_pass("%s\n", tests[i].name); 834 break; 835 case KSFT_SKIP: 836 ksft_test_result_skip("%s\n", tests[i].name); 837 break; 838 default: 839 ksft_test_result_fail("%s\n", tests[i].name); 840 break; 841 } 842 } 843 844 ksft_finished(); 845 } 846