1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/*\ 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * [Description] 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Conversion of second kself test in cgroup/test_memcontrol.c. 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * Original description: 9f08c3bdfSopenharmony_ci * "This test creates a memory cgroup, allocates some anonymous memory 10f08c3bdfSopenharmony_ci * and some pagecache and check memory.current and some memory.stat 11f08c3bdfSopenharmony_ci * values." 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * Note that the V1 rss and cache counters were renamed to anon and 14f08c3bdfSopenharmony_ci * file in V2. Besides error reporting, this test differs from the 15f08c3bdfSopenharmony_ci * kselftest in the following ways: 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * . It supports V1. 18f08c3bdfSopenharmony_ci * . It writes instead of reads to fill the page cache. Because no 19f08c3bdfSopenharmony_ci * pages were allocated on tmpfs. 20f08c3bdfSopenharmony_ci * . It runs on most filesystems available 21f08c3bdfSopenharmony_ci * . On EXFAT and extN we change the margin of error between all and file 22f08c3bdfSopenharmony_ci * memory to 50%. Because these allocate non-page-cache memory during writes. 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci#define _GNU_SOURCE 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#include "memcontrol_common.h" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic size_t page_size; 29f08c3bdfSopenharmony_cistatic struct tst_cg_group *cg_child; 30f08c3bdfSopenharmony_cistatic int fd; 31f08c3bdfSopenharmony_cistatic int file_to_all_error = 10; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void alloc_anon_50M_check(void) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci const ssize_t size = MB(50); 36f08c3bdfSopenharmony_ci char *buf, *ptr; 37f08c3bdfSopenharmony_ci ssize_t anon, current; 38f08c3bdfSopenharmony_ci const char *const anon_key_fmt = 39f08c3bdfSopenharmony_ci TST_CG_VER_IS_V1(tst_cg, "memory") ? "rss %zd" : "anon %zd"; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci buf = SAFE_MALLOC(size); 42f08c3bdfSopenharmony_ci for (ptr = buf; ptr < buf + size; ptr += page_size) 43f08c3bdfSopenharmony_ci *ptr = 0; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci SAFE_CG_SCANF(cg_child, "memory.current", "%zd", ¤t); 46f08c3bdfSopenharmony_ci TST_EXP_EXPR(current >= size, 47f08c3bdfSopenharmony_ci "(memory.current=%zd) >= (size=%zd)", current, size); 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci SAFE_CG_LINES_SCANF(cg_child, "memory.stat", anon_key_fmt, &anon); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci TST_EXP_EXPR(anon > 0, "(memory.stat.anon=%zd) > 0", anon); 52f08c3bdfSopenharmony_ci TST_EXP_EXPR(values_close(size, anon, 3), 53f08c3bdfSopenharmony_ci "(size=%zd) ~= (memory.stat.anon=%zd)", size, anon); 54f08c3bdfSopenharmony_ci TST_EXP_EXPR(values_close(anon, current, 3), 55f08c3bdfSopenharmony_ci "(memory.current=%zd) ~= (memory.stat.anon=%zd)", 56f08c3bdfSopenharmony_ci current, anon); 57f08c3bdfSopenharmony_ci} 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_cistatic void alloc_pagecache_50M_check(void) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci const size_t size = MB(50); 62f08c3bdfSopenharmony_ci size_t current, file; 63f08c3bdfSopenharmony_ci const char *const file_key_fmt = 64f08c3bdfSopenharmony_ci TST_CG_VER_IS_V1(tst_cg, "memory") ? "cache %zd" : "file %zd"; 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci fd = SAFE_OPEN(TMPDIR"/tmpfile", O_RDWR | O_CREAT, 0600); 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci SAFE_CG_SCANF(cg_child, "memory.current", "%zu", ¤t); 69f08c3bdfSopenharmony_ci tst_res(TINFO, "Created temp file: memory.current=%zu", current); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci alloc_pagecache(fd, size); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci SAFE_CG_SCANF(cg_child, "memory.current", "%zu", ¤t); 74f08c3bdfSopenharmony_ci TST_EXP_EXPR(current >= size, 75f08c3bdfSopenharmony_ci "(memory.current=%zu) >= (size=%zu)", current, size); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci SAFE_CG_LINES_SCANF(cg_child, "memory.stat", file_key_fmt, &file); 78f08c3bdfSopenharmony_ci TST_EXP_EXPR(file > 0, "(memory.stat.file=%zd) > 0", file); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci TST_EXP_EXPR(values_close(file, current, file_to_all_error), 81f08c3bdfSopenharmony_ci "(memory.current=%zd) ~= (memory.stat.file=%zd)", 82f08c3bdfSopenharmony_ci current, file); 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 85f08c3bdfSopenharmony_ci} 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_cistatic void test_memcg_current(unsigned int n) 88f08c3bdfSopenharmony_ci{ 89f08c3bdfSopenharmony_ci size_t current; 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci cg_child = tst_cg_group_mk(tst_cg, "child"); 92f08c3bdfSopenharmony_ci SAFE_CG_SCANF(cg_child, "memory.current", "%zu", ¤t); 93f08c3bdfSopenharmony_ci TST_EXP_EXPR(current == 0, "(current=%zu) == 0", current); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 96f08c3bdfSopenharmony_ci SAFE_CG_PRINTF(cg_child, "cgroup.procs", "%d", getpid()); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci SAFE_CG_SCANF(cg_child, "memory.current", "%zu", ¤t); 99f08c3bdfSopenharmony_ci tst_res(TINFO, "Added proc to memcg: memory.current=%zu", 100f08c3bdfSopenharmony_ci current); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci if (!n) 103f08c3bdfSopenharmony_ci alloc_anon_50M_check(); 104f08c3bdfSopenharmony_ci else 105f08c3bdfSopenharmony_ci alloc_pagecache_50M_check(); 106f08c3bdfSopenharmony_ci } else { 107f08c3bdfSopenharmony_ci tst_reap_children(); 108f08c3bdfSopenharmony_ci cg_child = tst_cg_group_rm(cg_child); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci} 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_cistatic void setup(void) 113f08c3bdfSopenharmony_ci{ 114f08c3bdfSopenharmony_ci page_size = SAFE_SYSCONF(_SC_PAGESIZE); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci switch (tst_fs_type(TMPDIR)) { 117f08c3bdfSopenharmony_ci case TST_VFAT_MAGIC: 118f08c3bdfSopenharmony_ci case TST_EXFAT_MAGIC: 119f08c3bdfSopenharmony_ci case TST_EXT234_MAGIC: 120f08c3bdfSopenharmony_ci file_to_all_error = 50; 121f08c3bdfSopenharmony_ci break; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci} 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_cistatic void cleanup(void) 126f08c3bdfSopenharmony_ci{ 127f08c3bdfSopenharmony_ci if (cg_child) 128f08c3bdfSopenharmony_ci cg_child = tst_cg_group_rm(cg_child); 129f08c3bdfSopenharmony_ci} 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_cistatic struct tst_test test = { 132f08c3bdfSopenharmony_ci .setup = setup, 133f08c3bdfSopenharmony_ci .cleanup = cleanup, 134f08c3bdfSopenharmony_ci .tcnt = 2, 135f08c3bdfSopenharmony_ci .test = test_memcg_current, 136f08c3bdfSopenharmony_ci .mount_device = 1, 137f08c3bdfSopenharmony_ci .dev_min_size = 256, 138f08c3bdfSopenharmony_ci .mntpoint = TMPDIR, 139f08c3bdfSopenharmony_ci .all_filesystems = 1, 140f08c3bdfSopenharmony_ci .forks_child = 1, 141f08c3bdfSopenharmony_ci .needs_root = 1, 142f08c3bdfSopenharmony_ci .needs_cgroup_ctrls = (const char *const []){ "memory", NULL }, 143f08c3bdfSopenharmony_ci}; 144