<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Feb 8, 2022 at 10:04 PM Richard Palethorpe via ltp <<a href="mailto:ltp@lists.linux.it">ltp@lists.linux.it</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">At first glance this test looks the same as memcontrol03. However<br>
there are some significant changes which complicate combining the two.<br>
<br>
Signed-off-by: Richard Palethorpe <<a href="mailto:rpalethorpe@suse.com" target="_blank">rpalethorpe@suse.com</a>><br>
---<br>
 runtest/controllers                           |   1 +<br>
 testcases/kernel/controllers/memcg/.gitignore |   1 +<br>
 .../kernel/controllers/memcg/memcontrol04.c   | 228 ++++++++++++++++++<br>
 3 files changed, 230 insertions(+)<br>
 create mode 100644 testcases/kernel/controllers/memcg/memcontrol04.c<br>
<br>
diff --git a/runtest/controllers b/runtest/controllers<br>
index 4a6f919af..3108a2561 100644<br>
--- a/runtest/controllers<br>
+++ b/runtest/controllers<br>
@@ -20,6 +20,7 @@ memcg_control         memcg_control_test.sh<br>
 memcontrol01 memcontrol01<br>
 memcontrol02 memcontrol02<br>
 memcontrol03 memcontrol03<br>
+memcontrol04 memcontrol04<br>
<br>
 cgroup_fj_function_debug cgroup_fj_function.sh debug<br>
 cgroup_fj_function_cpuset cgroup_fj_function.sh cpuset<br>
diff --git a/testcases/kernel/controllers/memcg/.gitignore b/testcases/kernel/controllers/memcg/.gitignore<br>
index 49df1582c..3883cede6 100644<br>
--- a/testcases/kernel/controllers/memcg/.gitignore<br>
+++ b/testcases/kernel/controllers/memcg/.gitignore<br>
@@ -8,3 +8,4 @@<br>
 memcontrol01<br>
 memcontrol02<br>
 memcontrol03<br>
+memcontrol04<br>
diff --git a/testcases/kernel/controllers/memcg/memcontrol04.c b/testcases/kernel/controllers/memcg/memcontrol04.c<br>
new file mode 100644<br>
index 000000000..cdfeff4a4<br>
--- /dev/null<br>
+++ b/testcases/kernel/controllers/memcg/memcontrol04.c<br>
@@ -0,0 +1,228 @@<br>
+// SPDX-License-Identifier: GPL-2.0<br>
+/*\<br>
+ *<br>
+ * [Description]<br>
+ *<br>
+ * Conversion of the forth kself test in cgroup/test_memcontrol.c.<br>
+ *<br>
+ * Original description:<br>
+ * "First, this test creates the following hierarchy:<br>
+ * A       memory.low = 50M,  memory.max = 200M<br>
+ * A/B     memory.low = 50M,  memory.current = 50M<br>
+ * A/B/C   memory.low = 75M,  memory.current = 50M<br>
+ * A/B/D   memory.low = 25M,  memory.current = 50M<br>
+ * A/B/E   memory.low = 500M, memory.current = 0<br>
+ * A/B/F   memory.low = 0,    memory.current = 50M<br>
+ *<br>
+ * Usages are pagecache<br>
+ * Then it creates A/G and creates a significant<br>
+ * memory pressure in it.<br>
+ *<br>
+ * A/B    memory.current ~= 50M<br>
+ * A/B/C  memory.current ~= 33M<br>
+ * A/B/D  memory.current ~= 17M<br>
+ * A/B/E  memory.current ~= 0<br>
+ *<br>
+ * After that it tries to allocate more than there is unprotected<br>
+ * memory in A available, and checks that memory.low protects<br>
+ * pagecache even in this case."<br>
+ *<br>
+ * The closest thing to memory.low on V1 is soft_limit_in_bytes which<br>
+ * uses a different mechanism and has different semantics. So we only<br>
+ * test on V2 like the selftest. We do test on more file systems, but<br>
+ * not tempfs becaue it can't evict the page cache without swap. Also<br>
+ * we avoid filesystems which allocate extra memory for buffer heads.<br>
+ *<br>
+ * The tolerances have been increased from the self tests.<br>
+ */<br>
+<br>
+#define _GNU_SOURCE<br>
+<br>
+#include <inttypes.h><br>
+<br>
+#include "memcontrol_common.h"<br>
+<br>
+#define TMPDIR "mntdir"<br>
+<br>
+static struct tst_cg_group *trunk_cg[3];<br>
+static struct tst_cg_group *leaf_cg[4];<br>
+static int fd = -1;<br>
+<br>
+enum checkpoints {<br>
+       CHILD_IDLE<br>
+};<br>
+<br>
+enum trunk_cg {<br>
+       A,<br>
+       B,<br>
+       G<br>
+};<br>
+<br>
+enum leaf_cg {<br>
+       C,<br>
+       D,<br>
+       E,<br>
+       F<br>
+};<br>
+<br>
+static void cleanup_sub_groups(void)<br>
+{<br>
+       size_t i;<br>
+<br>
+       for (i = ARRAY_SIZE(leaf_cg); i > 0; i--) {<br>
+               if (!leaf_cg[i - 1])<br>
+                       continue;<br>
+<br>
+               leaf_cg[i - 1] = tst_cg_group_rm(leaf_cg[i - 1]);<br>
+       }<br>
+<br>
+       for (i = ARRAY_SIZE(trunk_cg); i > 0; i--) {<br>
+               if (!trunk_cg[i - 1])<br>
+                       continue;<br>
+<br>
+               trunk_cg[i - 1] = tst_cg_group_rm(trunk_cg[i - 1]);<br>
+       }<br>
+}<br>
+<br>
+static void alloc_anon_in_child(const struct tst_cg_group *const cg,<br>
+                               const size_t size)<br>
+{<br>
+       const pid_t pid = SAFE_FORK();<br>
+<br>
+       if (pid) {<br>
+               tst_reap_children();<br>
+               return;<br>
+       }<br>
+<br>
+       SAFE_CG_PRINTF(cg, "cgroup.procs", "%d", getpid());<br>
+<br>
+       tst_res(TINFO, "Child %d in %s: Allocating anon: %"PRIdPTR,<br>
+               getpid(), tst_cg_group_name(cg), size);<br>
+       alloc_anon(size);<br>
+<br>
+       exit(0);<br>
+}<br>
+<br>
+static void alloc_pagecache_in_child(const struct tst_cg_group *const cg,<br>
+                                    const size_t size)<br>
+{<br>
+       const pid_t pid = SAFE_FORK();<br>
+<br>
+       if (pid) {<br>
+               tst_reap_children();<br>
+               return;<br>
+       }<br>
+<br>
+       SAFE_CG_PRINTF(cg, "cgroup.procs", "%d", getpid());<br>
+<br>
+       tst_res(TINFO, "Child %d in %s: Allocating pagecache: %"PRIdPTR,<br>
+               getpid(), tst_cg_group_name(cg), size);<br>
+       alloc_pagecache(fd, size);<br>
+<br>
+       exit(0);<br>
+}<br>
+<br>
+static void test_memcg_min(void)<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">test_memcg_low() ^</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+{<br>
+       long c[4];<br>
+       unsigned int i;<br>
+<br>
+       fd = SAFE_OPEN(TMPDIR"/tmpfile", O_RDWR | O_CREAT, 0600);<br>
+       trunk_cg[A] = tst_cg_group_mk(tst_cg, "trunk_A");<br>
+<br>
+       SAFE_CG_SCANF(trunk_cg[A], "memory.low", "%ld", c);<br>
+       if (c[0]) {<br>
+               tst_brk(TCONF,<br>
+                       "memory.low already set to %ld on parent group", c[0]);<br>
+       }<br>
+<br>
+       SAFE_CG_PRINT(trunk_cg[A], "cgroup.subtree_control", "+memory");<br>
+<br>
+       SAFE_CG_PRINT(trunk_cg[A], "memory.max", "200M");<br>
+       SAFE_CG_PRINT(trunk_cg[A], "memory.swap.max", "0");<br>
+<br>
+       trunk_cg[B] = tst_cg_group_mk(trunk_cg[A], "trunk_B");<br>
+<br>
+       SAFE_CG_PRINT(trunk_cg[B], "cgroup.subtree_control", "+memory");<br>
+<br>
+       trunk_cg[G] = tst_cg_group_mk(trunk_cg[A], "trunk_G");<br>
+<br>
+       for (i = 0; i < ARRAY_SIZE(leaf_cg); i++) {<br>
+               leaf_cg[i] = tst_cg_group_mk(trunk_cg[B],<br>
+                                                "leaf_%c", 'C' + i);<br>
+<br>
+               if (i == E)<br>
+                       continue;<br>
+<br>
+               alloc_pagecache_in_child(leaf_cg[i], MB(50));<br>
+       }<br>
+<br>
+       SAFE_CG_PRINT(trunk_cg[A], "memory.low", "50M");<br>
+       SAFE_CG_PRINT(trunk_cg[B], "memory.low", "50M");<br>
+       SAFE_CG_PRINT(leaf_cg[C], "memory.low", "75M");<br>
+       SAFE_CG_PRINT(leaf_cg[D], "memory.low", "25M");<br>
+       SAFE_CG_PRINT(leaf_cg[E], "memory.low", "500M");<br>
+       SAFE_CG_PRINT(leaf_cg[F], "memory.low", "0");<br>
+<br>
+       alloc_anon_in_child(trunk_cg[G], MB(148));<br>
+<br>
+       SAFE_CG_SCANF(trunk_cg[B], "memory.current", "%ld", c);<br>
+       TST_EXP_EXPR(values_close(c[0], MB(50), 5),<br>
+                    "(A/B memory.current=%ld) ~= %d", c[0], MB(50));<br>
+<br>
+       for (i = 0; i < ARRAY_SIZE(leaf_cg); i++)<br>
+               SAFE_CG_SCANF(leaf_cg[i], "memory.current", "%ld", c + i);<br>
+<br>
+       TST_EXP_EXPR(values_close(c[0], MB(33), 20),<br>
+                    "(A/B/C memory.current=%ld) ~= %d", c[0], MB(33));<br>
+       TST_EXP_EXPR(values_close(c[1], MB(17), 20),<br>
+                    "(A/B/D memory.current=%ld) ~= %d", c[1], MB(17));<br>
+       TST_EXP_EXPR(values_close(c[2], 0, 1),<br>
+                    "(A/B/E memory.current=%ld) ~= 0", c[2]);<br>
+<br>
+       alloc_anon_in_child(trunk_cg[G], MB(166));<br>
+<br>
+       for (i = 0; i < ARRAY_SIZE(leaf_cg); i++) {<br>
+               long low, oom;<br>
+<br>
+               SAFE_CG_LINES_SCANF(leaf_cg[i], "memory.events",<br>
+                                       "low %ld", &low);<br>
+               SAFE_CG_LINES_SCANF(leaf_cg[i], "memory.events",<br>
+                                       "oom %ld", &oom);<br>
+<br>
+               TST_EXP_EXPR(oom == 0, "(oom events=%ld) == 0", oom);<br>
+<br>
+               if (i < E)<br>
+                       TST_EXP_EXPR(low > 0, "(low events=%ld) > 0", low)<br>
+               else<br>
+                       TST_EXP_EXPR(low == 0, "(low events=%ld) == 0", low);<br>
+       }<br>
+<br>
+       cleanup_sub_groups();<br>
+       SAFE_CLOSE(fd);<br>
+       SAFE_UNLINK(TMPDIR"/tmpfile");<br>
+}<br>
+<br>
+static void cleanup(void)<br>
+{<br>
+       cleanup_sub_groups();<br>
+       if (fd > -1)<br>
+               SAFE_CLOSE(fd);<br>
+}<br>
+<br>
+static struct tst_test test = {<br>
+       .cleanup = cleanup,<br>
+       .test_all = test_memcg_min,<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">test_memcg_low  ^</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+       .mount_device = 1,<br>
+       .dev_min_size = 256,<br>
+       .mntpoint = TMPDIR,<br>
+       .all_filesystems = 1,<br>
+       .skip_filesystems = (const char *const[]){<br>
+               "exfat", "vfat", "fuse", "ntfs", "tmpfs", NULL<br>
+       },<br>
+       .forks_child = 1,<br>
+       .needs_root = 1,<br>
+       .needs_checkpoints = 1,<br>
+       .needs_cgroup_ver = TST_CG_V2,<br>
+       .needs_cgroup_ctrls = (const char *const[]){ "memory", NULL },<br>
+};<br></blockquote><div><br></div><div><br></div><div class="gmail_default" style="font-size:small">Apart from the tiny issues and controversy on renaming in patch2/3. </div><div class="gmail_default" style="font-size:small">The test itself looks good if we decide to go separate with memcontrol03.c</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">Btw, there are some TFAILs from my manual run. </div><div class="gmail_default" style="font-size:small">(I will look into that try to figure it out tomorrow)</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">tst_test.c:1521: TINFO: Testing on ext4<br>tst_test.c:996: TINFO: Formatting /dev/loop0 with ext4 opts='' extra opts=''<br>mke2fs 1.46.5 (30-Dec-2021)<br>tst_test.c:1452: TINFO: Timeout per run is 0h 05m 00s<br>memcontrol04.c:118: TINFO: Child 242775 in leaf_C: Allocating pagecache: 52428800<br>memcontrol04.c:118: TINFO: Child 242776 in leaf_D: Allocating pagecache: 52428800<br>memcontrol04.c:118: TINFO: Child 242777 in leaf_F: Allocating pagecache: 52428800<br>memcontrol04.c:99: TINFO: Child 242778 in trunk_G: Allocating anon: 155189248<br>memcontrol04.c:170: TPASS: Expect: (A/B memory.current=54181888) ~= 52428800<br>memcontrol04.c:176: TPASS: Expect: (A/B/C memory.current=30957568) ~= 34603008<br>memcontrol04.c:178: TPASS: Expect: (A/B/D memory.current=22282240) ~= 17825792<br>memcontrol04.c:180: TPASS: Expect: (A/B/E memory.current=0) ~= 0<br>memcontrol04.c:99: TINFO: Child 242779 in trunk_G: Allocating anon: 174063616<br>memcontrol04.c:193: TPASS: Expect: (oom events=0) == 0<br>memcontrol04.c:196: TPASS: Expect: (low events=373) > 0<br>memcontrol04.c:193: TPASS: Expect: (oom events=0) == 0<br>memcontrol04.c:196: TPASS: Expect: (low events=373) > 0<br>memcontrol04.c:193: TPASS: Expect: (oom events=0) == 0<br>memcontrol04.c:198: TPASS: Expect: (low events=0) == 0<br>memcontrol04.c:193: TPASS: Expect: (oom events=0) == 0<br>memcontrol04.c:198: TFAIL: Expect: (low events=370) == 0<br></div><div class="gmail_default" style="font-size:small"><br></div></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>