<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 Sat, Oct 29, 2022 at 3:14 PM Tarun Sahu <<a href="mailto:tsahu@linux.ibm.com">tsahu@linux.ibm.com</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">Migrating the libhugetlbfs/testcases/chunk-overcommit.c test<br>
<br>
Test Description: Some kernel versions after hugepage demand allocation was<br>
added used a dubious heuristic to check if there was enough hugepage space<br>
available for a given mapping.  The number of not-already-instantiated<br>
pages in the mapping was compared against the total hugepage free pool. It<br>
was very easy to confuse this heuristic into overcommitting by allocating<br>
hugepage memory in chunks, each less than the total available pool size but<br>
together more than available.  This would generally lead to OOM SIGKILLs of<br>
one process or another when it tried to instantiate pages beyond the<br>
available pool.<br>
<br>
Signed-off-by: Tarun Sahu <<a href="mailto:tsahu@linux.ibm.com" target="_blank">tsahu@linux.ibm.com</a>><br>
---<br>
 runtest/hugetlb                               |   1 +<br>
 testcases/kernel/mem/.gitignore               |   1 +<br>
 .../kernel/mem/hugetlb/hugemmap/hugemmap08.c  | 144 ++++++++++++++++++<br>
 3 files changed, 146 insertions(+)<br>
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c<br>
<br>
diff --git a/runtest/hugetlb b/runtest/hugetlb<br>
index f7ff81cb3..664f18827 100644<br>
--- a/runtest/hugetlb<br>
+++ b/runtest/hugetlb<br>
@@ -4,6 +4,7 @@ hugemmap04 hugemmap04<br>
 hugemmap05 hugemmap05<br>
 hugemmap06 hugemmap06<br>
 hugemmap07 hugemmap07<br>
+hugemmap08 hugemmap08<br>
 hugemmap05_1 hugemmap05 -m<br>
 hugemmap05_2 hugemmap05 -s<br>
 hugemmap05_3 hugemmap05 -s -m<br>
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore<br>
index df5256ec8..003ce422b 100644<br>
--- a/testcases/kernel/mem/.gitignore<br>
+++ b/testcases/kernel/mem/.gitignore<br>
@@ -5,6 +5,7 @@<br>
 /hugetlb/hugemmap/hugemmap05<br>
 /hugetlb/hugemmap/hugemmap06<br>
 /hugetlb/hugemmap/hugemmap07<br>
+/hugetlb/hugemmap/hugemmap08<br>
 /hugetlb/hugeshmat/hugeshmat01<br>
 /hugetlb/hugeshmat/hugeshmat02<br>
 /hugetlb/hugeshmat/hugeshmat03<br>
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c<br>
new file mode 100644<br>
index 000000000..61db030d5<br>
--- /dev/null<br>
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c<br>
@@ -0,0 +1,144 @@<br>
+// SPDX-License-Identifier: LGPL-2.1-or-later<br>
+/*<br>
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.<br>
+ * Author: David Gibson & Adam Litke<br>
+ */<br>
+<br>
+/*\<br>
+ * [Description]<br>
+ *<br>
+ * Chunk Overcommit:<br>
+ * Some kernel versions after hugepage demand allocation was added used a<br>
+ * dubious heuristic to check if there was enough hugepage space available<br>
+ * for a given mapping.  The number of not-already-instantiated pages in<br>
+ * the mapping was compared against the total hugepage free pool. It was<br>
+ * very easy to confuse this heuristic into overcommitting by allocating<br>
+ * hugepage memory in chunks, each less than the total available pool size<br>
+ * but together more than available.  This would generally lead to OOM<br>
+ * SIGKILLs of one process or another when it tried to instantiate pages<br>
+ * beyond the available pool.<br>
+ *<br>
+ * HISTORY<br>
+ *<br>
+ */<br>
+<br>
+#define _GNU_SOURCE<br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+#include <sys/mount.h><br>
+#include <limits.h><br>
+#include <sys/param.h><br>
+#include <sys/types.h><br>
+#include <sys/wait.h><br>
+#include <signal.h><br>
+<br>
+#include "hugetlb.h"<br>
+<br>
+#define PROC_OVERCOMMIT "/proc/sys/vm/nr_overcommit_hugepages"<br>
+#define WITH_OVERCOMMIT 0<br>
+#define WITHOUT_OVERCOMMIT 1<br>
+<br>
+static long hpage_size;<br>
+<br>
+static void test_chunk_overcommit(void)<br>
+{<br>
+       unsigned long totpages, chunk1, chunk2;<br>
+       void *p, *q;<br>
+       pid_t child;<br>
+       int status;<br>
+<br>
+       totpages = SAFE_READ_MEMINFO("HugePages_Free:");<br>
+<br>
+       chunk1 = (totpages / 2) + 1;<br>
+       chunk2 = totpages - chunk1 + 1;<br>
+<br>
+       tst_res(TINFO, "Free: %ld hugepages available: "<br>
+              "chunk1=%ld chunk2=%ld", totpages, chunk1, chunk2);<br>
+<br>
+       p = SAFE_MMAP(NULL, chunk1*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,<br>
+                tst_hugetlb_fd, 0);<br>
+<br>
+       q = mmap(NULL, chunk2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,<br>
+                tst_hugetlb_fd, chunk1*hpage_size);<br>
+       if (q == MAP_FAILED) {<br>
+               if (errno != ENOMEM) {<br>
+                       tst_res(TFAIL | TERRNO, "mmap() chunk2");<br>
+                       goto cleanup1;<br>
+               } else {<br>
+                       tst_res(TPASS, "Successful without overcommit pages");<br>
+                       goto cleanup1;<br>
+               }<br>
+       }<br>
+<br>
+       tst_res(TINFO, "Looks like we've overcommitted, testing...");<br>
+       /* Looks like we're overcommited, but we need to confirm that<br>
+        * this is bad.  We touch it all in a child process because an<br>
+        * overcommit will generally lead to a SIGKILL which we can't<br>
+        * handle, of course.<br>
+        */<br>
+       child = SAFE_FORK();<br>
+<br>
+       if (child == 0) {<br>
+               memset(p, 0, chunk1*hpage_size);<br>
+               memset(q, 0, chunk2*hpage_size);<br>
+               exit(0);<br>
+       }<br>
+<br>
+       SAFE_WAITPID(child, &status, 0);<br>
+<br>
+       if (WIFSIGNALED(status)) {<br>
+               tst_res(TFAIL, "Killed by signal '%s' due to overcommit",<br>
+                    tst_strsig(WTERMSIG(status)));<br>
+               goto cleanup2;<br>
+       }<br>
+<br>
+       tst_res(TPASS, "Successful with overcommit pages");<br>
+<br>
+cleanup2:<br>
+       SAFE_MUNMAP(q, chunk2*hpage_size);<br>
+<br>
+cleanup1:<br>
+       SAFE_MUNMAP(p, chunk1*hpage_size);<br>
+       SAFE_FTRUNCATE(tst_hugetlb_fd, 0);<br>
+}<br>
+<br>
+static void run_test(unsigned int test_type)<br>
+{<br>
+       unsigned long saved_oc_hugepages;<br>
+<br>
+       SAFE_FILE_SCANF(PROC_OVERCOMMIT, "%ld", &saved_oc_hugepages);<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">There is unnecessary to read PROC_OVERCOMMIT value again,</div><div class="gmail_default" style="font-size:small">we already save/restore it in struct tst_path_val[], so here we</div><div class="gmail_default" style="font-size:small">can set it directly to what we expected no matter if the original is 0 or 2.</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">static void run_test(unsigned int test_type)<br>{<br>        switch (test_type) {<br>        case WITHOUT_OVERCOMMIT:<br>                tst_res(TINFO, "Without overcommit testing...");<br>                SAFE_FILE_PRINTF(PROC_OVERCOMMIT, "%d", 0);<br>                break;<br>        case WITH_OVERCOMMIT:<br>                tst_res(TINFO, "With overcommit testing...");<br>                SAFE_FILE_PRINTF(PROC_OVERCOMMIT, "%d", 2);<br>                break;<br>    }<br>    test_chunk_overcommit();<br>}<br></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">
+       switch (test_type) {<br>
+       case WITHOUT_OVERCOMMIT:<br>
+               tst_res(TINFO, "Without overcommit testing...");<br>
+               if (saved_oc_hugepages > 0)<br>
+                       SAFE_FILE_PRINTF(PROC_OVERCOMMIT, "%d", 0);<br>
+               break;<br>
+       case WITH_OVERCOMMIT:<br>
+               tst_res(TINFO, "With overcommit testing...");<br>
+               if (saved_oc_hugepages == 0)<br>
+                       SAFE_FILE_PRINTF(PROC_OVERCOMMIT, "%d", 2);<br>
+               break;<br>
+       }<br>
+       test_chunk_overcommit();<br>
+}<br>
+<br>
+static void setup(void)<br>
+{<br>
+       hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024;<br>
+}<br>
+<br>
+static struct tst_test test = {<br>
+       .needs_root = 1,<br>
+       .needs_hugetlbfs = 1,<br>
+       .needs_unlinked_hugetlb_file = 1,<br>
+       .forks_child = 1,<br>
+       .save_restore = (const struct tst_path_val[]) {<br>
+               {PROC_OVERCOMMIT, NULL},<br>
+               {}<br>
+       },<br>
+       .tcnt = 2,<br>
+       .setup = setup,<br>
+       .test = run_test,<br>
+       .hugepages = {3, TST_NEEDS},<br>
+};<br>
+<br>
-- <br>
2.31.1<br>
<br>
<br>
-- <br>
Mailing list info: <a href="https://lists.linux.it/listinfo/ltp" rel="noreferrer" target="_blank">https://lists.linux.it/listinfo/ltp</a><br>
<br>
</blockquote></div><br clear="all"><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>