* [LTP] [PATCH v7 1/4] Hugetlb: Add new tst_test options for hugeltb test support
2022-11-04 6:27 [LTP] [PATCH v7 0/4] Hugetlb:Migrating the libhugetlbfs tests Tarun Sahu
@ 2022-11-04 6:27 ` Tarun Sahu
2022-11-04 6:27 ` [LTP] [PATCH v7 2/4] Hugetlb: Migrating libhugetlbfs brk_near_huge Tarun Sahu
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Tarun Sahu @ 2022-11-04 6:27 UTC (permalink / raw)
To: ltp; +Cc: geetika, sbhat, aneesh.kumar, vaibhav, rpalethorpe
Most of libhugetlbfs test require mounted hugetlbfs.
Here, this patch adds a new field in tst_test struct(include/tst_test.h)
which user can set if the test requires mounted hugetlbfs. Also, this
patch added support to create the unlinked file in the provided dirpath.
Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
Reviewed-by: Li Wang <liwang@redhat.com>
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
---
include/tst_hugepage.h | 7 +++++++
include/tst_test.h | 10 ++++++++++
lib/tst_test.c | 32 +++++++++++++++++++++++++++++---
3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/include/tst_hugepage.h b/include/tst_hugepage.h
index 7fba02c40..46327c79a 100644
--- a/include/tst_hugepage.h
+++ b/include/tst_hugepage.h
@@ -8,6 +8,13 @@
#define PATH_HUGEPAGES "/sys/kernel/mm/hugepages/"
#define PATH_NR_HPAGES "/proc/sys/vm/nr_hugepages"
+#define PATH_OC_HPAGES "/proc/sys/vm/nr_overcommit_hugepages"
+
+#define MEMINFO_HPAGE_TOTAL "HugePages_Total:"
+#define MEMINFO_HPAGE_FREE "HugePages_Free:"
+#define MEMINFO_HPAGE_RSVD "HugePages_Rsvd:"
+#define MEMINFO_HPAGE_SURP "HugePages_Surp:"
+#define MEMINFO_HPAGE_SIZE "Hugepagesize:"
extern char *nr_opt; /* -s num Set the number of the been allocated hugepages */
extern char *Hopt; /* -H /.. Location of hugetlbfs, i.e. -H /var/hugetlbfs */
diff --git a/include/tst_test.h b/include/tst_test.h
index a69965b95..acf2421de 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -176,6 +176,10 @@ struct tst_test {
int all_filesystems:1;
int skip_in_lockdown:1;
int skip_in_compat:1;
+ /*
+ * If set, the hugetlbfs will be mounted at .mntpoint.
+ */
+ int needs_hugetlbfs:1;
/*
* The skip_filesystems is a NULL terminated list of filesystems the
@@ -357,6 +361,12 @@ unsigned int tst_remaining_runtime(void);
*/
void tst_set_max_runtime(int max_runtime);
+/*
+ * Create and open a random file inside the given dir path.
+ * It unlinks the file after opening and return file descriptor.
+ */
+int tst_creat_unlinked(const char *path);
+
/*
* Returns path to the test temporary directory in a newly allocated buffer.
*/
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 8ccde1629..b225ba082 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -1021,6 +1021,28 @@ static void prepare_and_mount_dev_fs(const char *mntpoint)
}
}
+static void prepare_and_mount_hugetlb_fs(void)
+{
+ SAFE_MOUNT("none", tst_test->mntpoint, "hugetlbfs", 0, NULL);
+ mntpoint_mounted = 1;
+}
+
+int tst_creat_unlinked(const char *path)
+{
+ char template[PATH_MAX];
+ int fd;
+
+ snprintf(template, PATH_MAX, "%s/ltp_%.3sXXXXXX",
+ path, tid);
+
+ fd = mkstemp(template);
+ if (fd < 0)
+ tst_brk(TBROK | TERRNO, "mkstemp(%s) failed", template);
+
+ SAFE_UNLINK(template);
+ return fd;
+}
+
static const char *limit_tmpfs_mount_size(const char *mnt_data,
char *buf, size_t buf_size, const char *fs_type)
{
@@ -1191,15 +1213,16 @@ static void do_setup(int argc, char *argv[])
SAFE_MKDIR(tst_test->mntpoint, 0777);
if ((tst_test->needs_devfs || tst_test->needs_rofs ||
- tst_test->mount_device || tst_test->all_filesystems) &&
+ tst_test->mount_device || tst_test->all_filesystems ||
+ tst_test->needs_hugetlbfs) &&
!tst_test->mntpoint) {
tst_brk(TBROK, "tst_test->mntpoint must be set!");
}
if (!!tst_test->needs_rofs + !!tst_test->needs_devfs +
- !!tst_test->needs_device > 1) {
+ !!tst_test->needs_device + !!tst_test->needs_hugetlbfs > 1) {
tst_brk(TBROK,
- "Two or more of needs_{rofs, devfs, device} are set");
+ "Two or more of needs_{rofs, devfs, device, hugetlbfs} are set");
}
if (tst_test->needs_devfs)
@@ -1217,6 +1240,9 @@ static void do_setup(int argc, char *argv[])
}
}
+ if (tst_test->needs_hugetlbfs)
+ prepare_and_mount_hugetlb_fs();
+
if (tst_test->needs_device && !mntpoint_mounted) {
tdev.dev = tst_acquire_device_(NULL, tst_test->dev_min_size);
--
2.31.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread* [LTP] [PATCH v7 2/4] Hugetlb: Migrating libhugetlbfs brk_near_huge
2022-11-04 6:27 [LTP] [PATCH v7 0/4] Hugetlb:Migrating the libhugetlbfs tests Tarun Sahu
2022-11-04 6:27 ` [LTP] [PATCH v7 1/4] Hugetlb: Add new tst_test options for hugeltb test support Tarun Sahu
@ 2022-11-04 6:27 ` Tarun Sahu
2022-11-04 9:21 ` Cyril Hrubis
2022-11-04 6:27 ` [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit Tarun Sahu
2022-11-04 6:27 ` [LTP] [PATCH v7 4/4] Hugetlb: Migrating libhugetlbfs corrupt-by-cow-opt Tarun Sahu
3 siblings, 1 reply; 10+ messages in thread
From: Tarun Sahu @ 2022-11-04 6:27 UTC (permalink / raw)
To: ltp; +Cc: geetika, sbhat, aneesh.kumar, vaibhav, rpalethorpe
Migrating the libhugetlbfs/testcases/brk_near_huge.c test
Test Description:
Certain kernels have a bug where brk() does not perform the same
checks that a MAP_FIXED mmap() will, allowing brk() to create a
normal page VMA in a hugepage only address region. This can lead
to oopses or other badness.
Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
---
runtest/hugetlb | 1 +
testcases/kernel/mem/.gitignore | 1 +
.../kernel/mem/hugetlb/hugemmap/hugemmap07.c | 140 ++++++++++++++++++
testcases/kernel/mem/hugetlb/lib/hugetlb.h | 2 +
4 files changed, 144 insertions(+)
create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
diff --git a/runtest/hugetlb b/runtest/hugetlb
index f719217ab..f7ff81cb3 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -3,6 +3,7 @@ hugemmap02 hugemmap02
hugemmap04 hugemmap04
hugemmap05 hugemmap05
hugemmap06 hugemmap06
+hugemmap07 hugemmap07
hugemmap05_1 hugemmap05 -m
hugemmap05_2 hugemmap05 -s
hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index ff2910533..df5256ec8 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -4,6 +4,7 @@
/hugetlb/hugemmap/hugemmap04
/hugetlb/hugemmap/hugemmap05
/hugetlb/hugemmap/hugemmap06
+/hugetlb/hugemmap/hugemmap07
/hugetlb/hugeshmat/hugeshmat01
/hugetlb/hugeshmat/hugeshmat02
/hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
new file mode 100644
index 000000000..b754d9a30
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap07.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Author: David Gibson & Adam Litke
+ */
+
+/*\
+ *
+ * [Description]
+ *
+ * Certain kernels have a bug where brk() does not perform the same
+ * checks that a MAP_FIXED mmap() will, allowing brk() to create a
+ * normal page VMA in a hugepage only address region. This can lead
+ * to oopses or other badness.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "hugetlb.h"
+#include "tst_safe_stdio.h"
+
+#define MNTPOINT "hugetlbfs/"
+static long hpage_size;
+static int huge_fd = -1;
+
+#ifdef __powerpc64__
+static int arch_has_slice_support(void)
+{
+ char mmu_type[16];
+ FILE *fp;
+ int ret;
+
+ fp = SAFE_POPEN("cat /proc/cpuinfo | grep MMU | awk '{ print $3}'", "r");
+ ret = fscanf(fp, "%s", mmu_type);
+ pclose(fp);
+
+ if (ret < 0)
+ tst_brk(TBROK, "Failed to determine MMU type");
+
+ return strcmp(mmu_type, "Hash") == 0;
+}
+
+static void *next_chunk(void *addr)
+{
+ if (!arch_has_slice_support())
+ return PALIGN(addr, hpage_size);
+
+ if ((unsigned long)addr < 0x100000000UL)
+ /* 256M segments below 4G */
+ return PALIGN(addr, 0x10000000UL);
+ /* 1TB segments above */
+ return PALIGN(addr, 0x10000000000UL);
+}
+#elif defined(__powerpc__)
+static void *next_chunk(void *addr)
+{
+ if (tst_kernel_bits() == 32)
+ return PALIGN(addr, hpage_size);
+ else
+ return PALIGN(addr, 0x10000000UL);
+}
+#elif defined(__ia64__)
+static void *next_chunk(void *addr)
+{
+ return PALIGN(addr, 0x8000000000000000UL);
+}
+#else
+static void *next_chunk(void *addr)
+{
+ return PALIGN(addr, hpage_size);
+}
+#endif
+
+static void run_test(void)
+{
+ void *brk0, *hugemap_addr, *newbrk;
+ char *p;
+ int err;
+
+ brk0 = sbrk(0);
+ tst_res(TINFO, "Initial break at %p", brk0);
+
+ hugemap_addr = next_chunk(brk0) + hpage_size;
+
+ p = SAFE_MMAP(hugemap_addr, hpage_size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_FIXED, huge_fd, 0);
+ if (p != hugemap_addr) {
+ tst_res(TFAIL, "mmap() at unexpected address %p instead of %p\n", p,
+ hugemap_addr);
+ goto cleanup;
+ }
+
+ newbrk = next_chunk(brk0) + getpagesize();
+ err = brk((void *)newbrk);
+ if (err == -1) {
+ /* Failing the brk() is an acceptable kernel response */
+ tst_res(TPASS, "Failing the brk is an acceptable response");
+ } else {
+ /* Suceeding the brk() is acceptable if the new memory is
+ * properly accesible and we don't have a kernel blow up when
+ * we touch it.
+ */
+ tst_res(TINFO, "New break at %p", newbrk);
+ memset(brk0, 0, newbrk-brk0);
+ tst_res(TPASS, "memory is accessible, hence successful brk() is "
+ "an acceptable response");
+ }
+cleanup:
+ SAFE_MUNMAP(p, hpage_size);
+ err = brk(brk0);
+ if (err == -1)
+ tst_brk(TBROK, "Failed to set break at the original position");
+}
+
+static void setup(void)
+{
+ hpage_size = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SIZE)*1024;
+ huge_fd = tst_creat_unlinked(MNTPOINT);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(huge_fd);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .needs_hugetlbfs = 1,
+ .taint_check = TST_TAINT_D | TST_TAINT_W,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run_test,
+ .hugepages = {1, TST_NEEDS},
+};
diff --git a/testcases/kernel/mem/hugetlb/lib/hugetlb.h b/testcases/kernel/mem/hugetlb/lib/hugetlb.h
index f75109f3e..a4300f40f 100644
--- a/testcases/kernel/mem/hugetlb/lib/hugetlb.h
+++ b/testcases/kernel/mem/hugetlb/lib/hugetlb.h
@@ -20,6 +20,8 @@
#include "old_tmpdir.h"
#include "mem.h"
+#define PALIGN(p, a) ((void *)LTP_ALIGN((unsigned long)(p), (a)))
+
#define SHM_RD 0400
#define SHM_WR 0200
#define SHM_RW (SHM_RD|SHM_WR)
--
2.31.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [LTP] [PATCH v7 2/4] Hugetlb: Migrating libhugetlbfs brk_near_huge
2022-11-04 6:27 ` [LTP] [PATCH v7 2/4] Hugetlb: Migrating libhugetlbfs brk_near_huge Tarun Sahu
@ 2022-11-04 9:21 ` Cyril Hrubis
0 siblings, 0 replies; 10+ messages in thread
From: Cyril Hrubis @ 2022-11-04 9:21 UTC (permalink / raw)
To: Tarun Sahu; +Cc: sbhat, aneesh.kumar, geetika, vaibhav, rpalethorpe, ltp
Hi!
> +#ifdef __powerpc64__
> +static int arch_has_slice_support(void)
> +{
> + char mmu_type[16];
> + FILE *fp;
> + int ret;
> +
> + fp = SAFE_POPEN("cat /proc/cpuinfo | grep MMU | awk '{ print $3}'", "r");
> + ret = fscanf(fp, "%s", mmu_type);
> + pclose(fp);
> +
> + if (ret < 0)
> + tst_brk(TBROK, "Failed to determine MMU type");
We do have SAFE_FILE_LINES_SCANF() that simplifies all this to a single line;
SAFE_FILE_LINES_SCANF("/proc/cpuinfo", "MMU : %16s", mmu_type);
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit
2022-11-04 6:27 [LTP] [PATCH v7 0/4] Hugetlb:Migrating the libhugetlbfs tests Tarun Sahu
2022-11-04 6:27 ` [LTP] [PATCH v7 1/4] Hugetlb: Add new tst_test options for hugeltb test support Tarun Sahu
2022-11-04 6:27 ` [LTP] [PATCH v7 2/4] Hugetlb: Migrating libhugetlbfs brk_near_huge Tarun Sahu
@ 2022-11-04 6:27 ` Tarun Sahu
2022-11-04 9:36 ` Cyril Hrubis
2022-11-04 6:27 ` [LTP] [PATCH v7 4/4] Hugetlb: Migrating libhugetlbfs corrupt-by-cow-opt Tarun Sahu
3 siblings, 1 reply; 10+ messages in thread
From: Tarun Sahu @ 2022-11-04 6:27 UTC (permalink / raw)
To: ltp; +Cc: geetika, sbhat, aneesh.kumar, vaibhav, rpalethorpe
Migrating the libhugetlbfs/testcases/chunk-overcommit.c test
Test Description: Some kernel versions after hugepage demand allocation was
added used a dubious heuristic to check if there was enough hugepage space
available for a given mapping. The number of not-already-instantiated
pages in the mapping was compared against the total hugepage free pool. It
was very easy to confuse this heuristic into overcommitting by allocating
hugepage memory in chunks, each less than the total available pool size but
together more than available. This would generally lead to OOM SIGKILLs of
one process or another when it tried to instantiate pages beyond the
available pool.
Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
---
runtest/hugetlb | 1 +
testcases/kernel/mem/.gitignore | 1 +
.../kernel/mem/hugetlb/hugemmap/hugemmap08.c | 146 ++++++++++++++++++
3 files changed, 148 insertions(+)
create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
diff --git a/runtest/hugetlb b/runtest/hugetlb
index f7ff81cb3..664f18827 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -4,6 +4,7 @@ hugemmap04 hugemmap04
hugemmap05 hugemmap05
hugemmap06 hugemmap06
hugemmap07 hugemmap07
+hugemmap08 hugemmap08
hugemmap05_1 hugemmap05 -m
hugemmap05_2 hugemmap05 -s
hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index df5256ec8..003ce422b 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -5,6 +5,7 @@
/hugetlb/hugemmap/hugemmap05
/hugetlb/hugemmap/hugemmap06
/hugetlb/hugemmap/hugemmap07
+/hugetlb/hugemmap/hugemmap08
/hugetlb/hugeshmat/hugeshmat01
/hugetlb/hugeshmat/hugeshmat02
/hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
new file mode 100644
index 000000000..3efabc4aa
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
+ * Author: David Gibson & Adam Litke
+ */
+
+/*\
+ * [Description]
+ *
+ * Some kernel versions after hugepage demand allocation was added used a
+ * dubious heuristic to check if there was enough hugepage space available
+ * for a given mapping. The number of not-already-instantiated pages in
+ * the mapping was compared against the total hugepage free pool. It was
+ * very easy to confuse this heuristic into overcommitting by allocating
+ * hugepage memory in chunks, each less than the total available pool size
+ * but together more than available. This would generally lead to OOM
+ * SIGKILLs of one process or another when it tried to instantiate pages
+ * beyond the available pool.
+ *
+ * HISTORY
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include "hugetlb.h"
+
+#define MNTPOINT "hugetlbfs/"
+#define WITH_OVERCOMMIT 0
+#define WITHOUT_OVERCOMMIT 1
+
+static long hpage_size;
+static int huge_fd = -1;
+
+static void test_chunk_overcommit(void)
+{
+ unsigned long totpages, chunk1, chunk2;
+ void *p, *q;
+ pid_t child;
+ int status;
+
+ totpages = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
+
+ chunk1 = (totpages / 2) + 1;
+ chunk2 = totpages - chunk1 + 1;
+
+ tst_res(TINFO, "Free: %ld hugepages available: "
+ "chunk1=%ld chunk2=%ld", totpages, chunk1, chunk2);
+
+ p = SAFE_MMAP(NULL, chunk1*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ huge_fd, 0);
+
+ q = mmap(NULL, chunk2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ huge_fd, chunk1*hpage_size);
+ if (q == MAP_FAILED) {
+ if (errno != ENOMEM) {
+ tst_res(TFAIL | TERRNO, "mmap() chunk2");
+ goto cleanup1;
+ } else {
+ tst_res(TPASS, "Successful without overcommit pages");
+ goto cleanup1;
+ }
+ }
+
+ tst_res(TINFO, "Looks like we've overcommitted, testing...");
+ /* Looks like we're overcommited, but we need to confirm that
+ * this is bad. We touch it all in a child process because an
+ * overcommit will generally lead to a SIGKILL which we can't
+ * handle, of course.
+ */
+ child = SAFE_FORK();
+
+ if (child == 0) {
+ memset(p, 0, chunk1*hpage_size);
+ memset(q, 0, chunk2*hpage_size);
+ exit(0);
+ }
+
+ SAFE_WAITPID(child, &status, 0);
+
+ if (WIFSIGNALED(status)) {
+ tst_res(TFAIL, "Killed by signal '%s' due to overcommit",
+ tst_strsig(WTERMSIG(status)));
+ goto cleanup2;
+ }
+
+ tst_res(TPASS, "Successful with overcommit pages");
+
+cleanup2:
+ SAFE_MUNMAP(q, chunk2*hpage_size);
+
+cleanup1:
+ SAFE_MUNMAP(p, chunk1*hpage_size);
+ SAFE_FTRUNCATE(huge_fd, 0);
+}
+
+static void run_test(unsigned int test_type)
+{
+ switch (test_type) {
+ case WITHOUT_OVERCOMMIT:
+ tst_res(TINFO, "Without overcommit testing...");
+ SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 0);
+ break;
+ case WITH_OVERCOMMIT:
+ tst_res(TINFO, "With overcommit testing...");
+ SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 2);
+ break;
+ }
+ test_chunk_overcommit();
+}
+
+static void setup(void)
+{
+ hpage_size = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SIZE)*1024;
+ huge_fd = tst_creat_unlinked(MNTPOINT);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(huge_fd);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .needs_hugetlbfs = 1,
+ .forks_child = 1,
+ .save_restore = (const struct tst_path_val[]) {
+ {PATH_OC_HPAGES, NULL},
+ {}
+ },
+ .tcnt = 2,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = run_test,
+ .hugepages = {3, TST_NEEDS},
+};
+
--
2.31.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit
2022-11-04 6:27 ` [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit Tarun Sahu
@ 2022-11-04 9:36 ` Cyril Hrubis
2022-11-04 13:16 ` Tarun Sahu
0 siblings, 1 reply; 10+ messages in thread
From: Cyril Hrubis @ 2022-11-04 9:36 UTC (permalink / raw)
To: Tarun Sahu; +Cc: sbhat, aneesh.kumar, geetika, vaibhav, rpalethorpe, ltp
Hi!
> diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
> new file mode 100644
> index 000000000..3efabc4aa
> --- /dev/null
> +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
> @@ -0,0 +1,146 @@
> +// SPDX-License-Identifier: LGPL-2.1-or-later
> +/*
> + * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
> + * Author: David Gibson & Adam Litke
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Some kernel versions after hugepage demand allocation was added used a
> + * dubious heuristic to check if there was enough hugepage space available
> + * for a given mapping. The number of not-already-instantiated pages in
> + * the mapping was compared against the total hugepage free pool. It was
> + * very easy to confuse this heuristic into overcommitting by allocating
> + * hugepage memory in chunks, each less than the total available pool size
> + * but together more than available. This would generally lead to OOM
> + * SIGKILLs of one process or another when it tried to instantiate pages
> + * beyond the available pool.
> + *
> + * HISTORY
This looks like a leftover.
> + *
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/mount.h>
> +#include <limits.h>
> +#include <sys/param.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <signal.h>
> +
> +#include "hugetlb.h"
> +
> +#define MNTPOINT "hugetlbfs/"
> +#define WITH_OVERCOMMIT 0
> +#define WITHOUT_OVERCOMMIT 1
> +
> +static long hpage_size;
> +static int huge_fd = -1;
> +
> +static void test_chunk_overcommit(void)
> +{
> + unsigned long totpages, chunk1, chunk2;
> + void *p, *q;
> + pid_t child;
> + int status;
> +
> + totpages = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
> +
> + chunk1 = (totpages / 2) + 1;
> + chunk2 = totpages - chunk1 + 1;
> +
> + tst_res(TINFO, "Free: %ld hugepages available: "
> + "chunk1=%ld chunk2=%ld", totpages, chunk1, chunk2);
> +
> + p = SAFE_MMAP(NULL, chunk1*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
> + huge_fd, 0);
> +
> + q = mmap(NULL, chunk2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
> + huge_fd, chunk1*hpage_size);
> + if (q == MAP_FAILED) {
> + if (errno != ENOMEM) {
> + tst_res(TFAIL | TERRNO, "mmap() chunk2");
> + goto cleanup1;
> + } else {
> + tst_res(TPASS, "Successful without overcommit pages");
> + goto cleanup1;
> + }
> + }
> +
> + tst_res(TINFO, "Looks like we've overcommitted, testing...");
> + /* Looks like we're overcommited, but we need to confirm that
> + * this is bad. We touch it all in a child process because an
> + * overcommit will generally lead to a SIGKILL which we can't
> + * handle, of course.
> + */
> + child = SAFE_FORK();
> +
> + if (child == 0) {
> + memset(p, 0, chunk1*hpage_size);
> + memset(q, 0, chunk2*hpage_size);
> + exit(0);
> + }
> +
> + SAFE_WAITPID(child, &status, 0);
> +
> + if (WIFSIGNALED(status)) {
> + tst_res(TFAIL, "Killed by signal '%s' due to overcommit",
> + tst_strsig(WTERMSIG(status)));
> + goto cleanup2;
> + }
> +
> + tst_res(TPASS, "Successful with overcommit pages");
> +
> +cleanup2:
> + SAFE_MUNMAP(q, chunk2*hpage_size);
> +
> +cleanup1:
> + SAFE_MUNMAP(p, chunk1*hpage_size);
> + SAFE_FTRUNCATE(huge_fd, 0);
> +}
> +
> +static void run_test(unsigned int test_type)
> +{
> + switch (test_type) {
> + case WITHOUT_OVERCOMMIT:
> + tst_res(TINFO, "Without overcommit testing...");
> + SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 0);
> + break;
> + case WITH_OVERCOMMIT:
> + tst_res(TINFO, "With overcommit testing...");
> + SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 2);
> + break;
> + }
> + test_chunk_overcommit();
> +}
> +
> +static void setup(void)
> +{
> + hpage_size = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SIZE)*1024;
> + huge_fd = tst_creat_unlinked(MNTPOINT);
Shouldn't we open a file under the MNTPOINT?
Something as:
#define HUGEFILE MNTPOINT "hugefile"
...
huge_fd = tst_creat_unlinked(HUGEFILE);
...
The rest looks good to me.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit
2022-11-04 9:36 ` Cyril Hrubis
@ 2022-11-04 13:16 ` Tarun Sahu
2022-11-04 13:19 ` Cyril Hrubis
0 siblings, 1 reply; 10+ messages in thread
From: Tarun Sahu @ 2022-11-04 13:16 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: sbhat, aneesh.kumar, geetika, vaibhav, rpalethorpe, ltp
On Nov 04 2022, Cyril Hrubis wrote:
> Hi!
> > diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
> > new file mode 100644
> > index 000000000..3efabc4aa
> > --- /dev/null
> > +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap08.c
> > @@ -0,0 +1,146 @@
> > +// SPDX-License-Identifier: LGPL-2.1-or-later
> > +/*
> > + * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation.
> > + * Author: David Gibson & Adam Litke
> > + */
> > +
> > +/*\
> > + * [Description]
> > + *
> > + * Some kernel versions after hugepage demand allocation was added used a
> > + * dubious heuristic to check if there was enough hugepage space available
> > + * for a given mapping. The number of not-already-instantiated pages in
> > + * the mapping was compared against the total hugepage free pool. It was
> > + * very easy to confuse this heuristic into overcommitting by allocating
> > + * hugepage memory in chunks, each less than the total available pool size
> > + * but together more than available. This would generally lead to OOM
> > + * SIGKILLs of one process or another when it tried to instantiate pages
> > + * beyond the available pool.
> > + *
> > + * HISTORY
>
> This looks like a leftover.
Ok.
>
> > + *
> > + */
> > +
> > +#define _GNU_SOURCE
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <sys/mount.h>
> > +#include <limits.h>
> > +#include <sys/param.h>
> > +#include <sys/types.h>
> > +#include <sys/wait.h>
> > +#include <signal.h>
> > +
> > +#include "hugetlb.h"
> > +
> > +#define MNTPOINT "hugetlbfs/"
> > +#define WITH_OVERCOMMIT 0
> > +#define WITHOUT_OVERCOMMIT 1
> > +
> > +static long hpage_size;
> > +static int huge_fd = -1;
> > +
> > +static void test_chunk_overcommit(void)
> > +{
> > + unsigned long totpages, chunk1, chunk2;
> > + void *p, *q;
> > + pid_t child;
> > + int status;
> > +
> > + totpages = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
> > +
> > + chunk1 = (totpages / 2) + 1;
> > + chunk2 = totpages - chunk1 + 1;
> > +
> > + tst_res(TINFO, "Free: %ld hugepages available: "
> > + "chunk1=%ld chunk2=%ld", totpages, chunk1, chunk2);
> > +
> > + p = SAFE_MMAP(NULL, chunk1*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
> > + huge_fd, 0);
> > +
> > + q = mmap(NULL, chunk2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
> > + huge_fd, chunk1*hpage_size);
> > + if (q == MAP_FAILED) {
> > + if (errno != ENOMEM) {
> > + tst_res(TFAIL | TERRNO, "mmap() chunk2");
> > + goto cleanup1;
> > + } else {
> > + tst_res(TPASS, "Successful without overcommit pages");
> > + goto cleanup1;
> > + }
> > + }
> > +
> > + tst_res(TINFO, "Looks like we've overcommitted, testing...");
> > + /* Looks like we're overcommited, but we need to confirm that
> > + * this is bad. We touch it all in a child process because an
> > + * overcommit will generally lead to a SIGKILL which we can't
> > + * handle, of course.
> > + */
> > + child = SAFE_FORK();
> > +
> > + if (child == 0) {
> > + memset(p, 0, chunk1*hpage_size);
> > + memset(q, 0, chunk2*hpage_size);
> > + exit(0);
> > + }
> > +
> > + SAFE_WAITPID(child, &status, 0);
> > +
> > + if (WIFSIGNALED(status)) {
> > + tst_res(TFAIL, "Killed by signal '%s' due to overcommit",
> > + tst_strsig(WTERMSIG(status)));
> > + goto cleanup2;
> > + }
> > +
> > + tst_res(TPASS, "Successful with overcommit pages");
> > +
> > +cleanup2:
> > + SAFE_MUNMAP(q, chunk2*hpage_size);
> > +
> > +cleanup1:
> > + SAFE_MUNMAP(p, chunk1*hpage_size);
> > + SAFE_FTRUNCATE(huge_fd, 0);
> > +}
> > +
> > +static void run_test(unsigned int test_type)
> > +{
> > + switch (test_type) {
> > + case WITHOUT_OVERCOMMIT:
> > + tst_res(TINFO, "Without overcommit testing...");
> > + SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 0);
> > + break;
> > + case WITH_OVERCOMMIT:
> > + tst_res(TINFO, "With overcommit testing...");
> > + SAFE_FILE_PRINTF(PATH_OC_HPAGES, "%d", 2);
> > + break;
> > + }
> > + test_chunk_overcommit();
> > +}
> > +
> > +static void setup(void)
> > +{
> > + hpage_size = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SIZE)*1024;
> > + huge_fd = tst_creat_unlinked(MNTPOINT);
>
> Shouldn't we open a file under the MNTPOINT?
>
> Something as:
>
> #define HUGEFILE MNTPOINT "hugefile"
>
> ...
> huge_fd = tst_creat_unlinked(HUGEFILE);
> ...
>
This function creat a file with random name, so that one test
can call this function multiple times to creat multple files
whenever required. So it will just take the path inside which it will creat
all these files. To keep hugetlb test file with ditinguisable name, the path
is sufficient, no need to take hugefile as argument.
So file is: hugetlbfs/ltp_xxxxxx_<tid>
>
> The rest looks good to me.
>
> --
> Cyril Hrubis
> chrubis@suse.cz
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit
2022-11-04 13:16 ` Tarun Sahu
@ 2022-11-04 13:19 ` Cyril Hrubis
0 siblings, 0 replies; 10+ messages in thread
From: Cyril Hrubis @ 2022-11-04 13:19 UTC (permalink / raw)
To: Tarun Sahu; +Cc: sbhat, aneesh.kumar, geetika, vaibhav, rpalethorpe, ltp
Hi!
> > #define HUGEFILE MNTPOINT "hugefile"
> >
> > ...
> > huge_fd = tst_creat_unlinked(HUGEFILE);
> > ...
> >
> This function creat a file with random name, so that one test
> can call this function multiple times to creat multple files
> whenever required. So it will just take the path inside which it will creat
> all these files. To keep hugetlb test file with ditinguisable name, the path
> is sufficient, no need to take hugefile as argument.
>
> So file is: hugetlbfs/ltp_xxxxxx_<tid>
Sorry, I got somehow confused in the morning, of course the code is
correct.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v7 4/4] Hugetlb: Migrating libhugetlbfs corrupt-by-cow-opt
2022-11-04 6:27 [LTP] [PATCH v7 0/4] Hugetlb:Migrating the libhugetlbfs tests Tarun Sahu
` (2 preceding siblings ...)
2022-11-04 6:27 ` [LTP] [PATCH v7 3/4] Hugetlb: Migrating libhugetlbfs chunk-overcommit Tarun Sahu
@ 2022-11-04 6:27 ` Tarun Sahu
2022-11-04 9:51 ` Cyril Hrubis
3 siblings, 1 reply; 10+ messages in thread
From: Tarun Sahu @ 2022-11-04 6:27 UTC (permalink / raw)
To: ltp; +Cc: geetika, sbhat, aneesh.kumar, vaibhav, rpalethorpe
Migrating the libhugetlbfs/testcases/corrupt-by-cow-opt.c test
Test Description: Test sanity of cow optimization on page cache. If a page
in page cache has only 1 ref count, it is mapped for a private mapping
directly and is overwritten freely, so next time we access the page, we
can see corrupt data.
Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
---
runtest/hugetlb | 1 +
testcases/kernel/mem/.gitignore | 1 +
.../kernel/mem/hugetlb/hugemmap/hugemmap09.c | 79 +++++++++++++++++++
3 files changed, 81 insertions(+)
create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap09.c
diff --git a/runtest/hugetlb b/runtest/hugetlb
index 664f18827..e2ada7a97 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -5,6 +5,7 @@ hugemmap05 hugemmap05
hugemmap06 hugemmap06
hugemmap07 hugemmap07
hugemmap08 hugemmap08
+hugemmap09 hugemmap09
hugemmap05_1 hugemmap05 -m
hugemmap05_2 hugemmap05 -s
hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 003ce422b..1a242ffe0 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -6,6 +6,7 @@
/hugetlb/hugemmap/hugemmap06
/hugetlb/hugemmap/hugemmap07
/hugetlb/hugemmap/hugemmap08
+/hugetlb/hugemmap/hugemmap09
/hugetlb/hugeshmat/hugeshmat01
/hugetlb/hugeshmat/hugeshmat02
/hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap09.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap09.c
new file mode 100644
index 000000000..1008395a4
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap09.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2013 Joonsoo Kim, LG Electronics.
+ * Author: Joonsoo Kim
+ */
+
+/*\
+ * [Description]
+ *
+ * Test sanity of cow optimization on page cache. If a page in page cache
+ * has only 1 ref count, it is mapped for a private mapping directly and
+ * is overwritten freely, so next time we access the page, we can see
+ * corrupt data.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "hugetlb.h"
+
+#define MNTPOINT "hugetlbfs/"
+static long hpage_size;
+static int huge_fd = -1;
+
+static void run_test(void)
+{
+ char *p;
+ char c;
+
+ p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ huge_fd, 0);
+ *p = 's';
+ tst_res(TINFO, "Write %c to %p via shared mapping", *p, p);
+ SAFE_MUNMAP(p, hpage_size);
+
+ p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+ huge_fd, 0);
+ *p = 'p';
+ tst_res(TINFO, "Write %c to %p via private mapping", *p, p);
+ SAFE_MUNMAP(p, hpage_size);
+
+ p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ huge_fd, 0);
+ c = *p;
+ tst_res(TINFO, "Read %c from %p via shared mapping", *p, p);
+ SAFE_MUNMAP(p, hpage_size);
+
+ /* Direct write from huge page */
+ if (c != 's')
+ tst_res(TFAIL, "Data got corrupted.");
+ else
+ tst_res(TPASS, "Successful");
+}
+
+static void setup(void)
+{
+ hpage_size = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SIZE)*1024;
+ huge_fd = tst_creat_unlinked(MNTPOINT);
+}
+
+static void cleanup(void)
+{
+ SAFE_CLOSE(huge_fd);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .needs_hugetlbfs = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run_test,
+ .hugepages = {2, TST_NEEDS},
+};
--
2.31.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread