<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>