[LTP] [PATCH 2/2] syscalls/move_pages13.c: Add new regression test
Xiao Yang
yangx.jy@cn.fujitsu.com
Fri Dec 1 04:48:28 CET 2017
The bug has been fixed in kernel:
'c9d398fa2378("mm, hugetlb: use pte_present() instead
of pmd_present() in follow_huge_pmd()")'
It is easily for RHEL7.4GA to trigger the bug, but hardly
for upstream kernel.
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
Signed-off-by: Jie Fei <feij.fnst@cn.fujitsu.com>
---
runtest/numa | 1 +
runtest/syscalls | 1 +
testcases/kernel/syscalls/.gitignore | 1 +
.../kernel/syscalls/move_pages/move_pages13.c | 158 +++++++++++++++++++++
4 files changed, 161 insertions(+)
create mode 100644 testcases/kernel/syscalls/move_pages/move_pages13.c
diff --git a/runtest/numa b/runtest/numa
index dcf4948..7757874 100644
--- a/runtest/numa
+++ b/runtest/numa
@@ -11,3 +11,4 @@ move_pages09 move_pages.sh 09
move_pages10 move_pages.sh 10
move_pages11 cd $LTPROOT/testcases/bin && chown root move_pages11 && chmod 04755 move_pages11 && move_pages.sh 11
move_pages12 move_pages12
+move_pages13 move_pages13
diff --git a/runtest/syscalls b/runtest/syscalls
index 14089ac..904333a 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -665,6 +665,7 @@ move_pages09 move_pages.sh 09
move_pages10 move_pages.sh 10
move_pages11 cd $LTPROOT/testcases/bin && chown root move_pages11 && chmod 04755 move_pages11 && move_pages.sh 11
move_pages12 move_pages12
+move_pages13 move_pages13
mprotect01 mprotect01
mprotect02 mprotect02
diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore
index 12a136e..bf99657 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -606,6 +606,7 @@
/move_pages/move_pages10
/move_pages/move_pages11
/move_pages/move_pages12
+/move_pages/move_pages13
/mprotect/mprotect01
/mprotect/mprotect02
/mprotect/mprotect03
diff --git a/testcases/kernel/syscalls/move_pages/move_pages13.c b/testcases/kernel/syscalls/move_pages/move_pages13.c
new file mode 100644
index 0000000..2f1554b
--- /dev/null
+++ b/testcases/kernel/syscalls/move_pages/move_pages13.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved.
+ * Author(s): Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Jie Fei <feij.fnst@cn.fujitsu.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program, if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Description:
+ * This is a regression test for the race condition, where move_pages()
+ * and soft offline are called on a single hugetlb page concurrently.
+ *
+ * This bug can crash the buggy kernel, and was fixed by:
+ *
+ * commit c9d398fa237882ea07167e23bcfc5e6847066518
+ * Author: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
+ * Date: Fri Mar 31 15:11:55 2017 -0700
+ *
+ * mm, hugetlb: use pte_present() instead of pmd_present() in follow_huge_pmd()
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "move_pages_support.h"
+#include "move_hugepages_support.h"
+#include "lapi/mmap.h"
+
+#ifdef HAVE_NUMA_V2
+
+#define LOOPS 2000
+#define TEST_PAGES 2
+#define TEST_NODES 2
+
+static int pgsz, hpsz;
+static long orig_hugepages = -1;
+static char path_hugepages_node1[PATH_MAX];
+static char path_hugepages_node2[PATH_MAX];
+static long orig_hugepages_node1 = -1;
+static long orig_hugepages_node2 = -1;
+static unsigned int node1, node2;
+static void *addr;
+
+static void do_test(void)
+{
+ int i, status;
+ void *test_addr;
+ pid_t pid = -1;
+
+ addr = SAFE_MMAP(NULL, TEST_PAGES * hpsz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
+
+ SAFE_MUNMAP(addr, TEST_PAGES * hpsz);
+
+ pid = SAFE_FORK();
+ if (pid == 0)
+ do_hugepages_move(TEST_PAGES, hpsz, pgsz, addr, node1, node2);
+
+ for (i = 0; i < LOOPS; i++) {
+ test_addr = SAFE_MMAP(NULL, TEST_PAGES * hpsz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
+ if (test_addr != addr)
+ tst_brk(TBROK, "Failed to mmap at desired addr");
+
+ memset(test_addr, 0, TEST_PAGES * hpsz);
+
+ if (madvise(test_addr, TEST_PAGES * hpsz, MADV_SOFT_OFFLINE)) {
+ if (errno == EINVAL) {
+ tst_brk(TCONF, "madvise() didn't support "
+ "MADV_SOFT_OFFLINE");
+ }
+ }
+
+ SAFE_MUNMAP(test_addr, TEST_PAGES * hpsz);
+ }
+
+ if (i == LOOPS) {
+ SAFE_KILL(pid, SIGKILL);
+ SAFE_WAITPID(pid, &status, 0);
+ if (!WIFEXITED(status))
+ tst_res(TPASS, "Bug not reproduced");
+ }
+}
+
+static void setup(void)
+{
+ int memfree, ret;
+
+ check_config(TEST_NODES);
+
+ if (access(PATH_HUGEPAGES, F_OK))
+ tst_brk(TCONF, "Huge page not supported");
+
+ ret = get_allowed_nodes(NH_MEMS, TEST_NODES, &node1, &node2);
+ if (ret < 0)
+ tst_brk(TBROK | TERRNO, "get_allowed_nodes: %d", ret);
+
+ pgsz = (int)get_page_size();
+ SAFE_FILE_LINES_SCANF(PATH_MEMINFO, "Hugepagesize: %d", &hpsz);
+
+ SAFE_FILE_LINES_SCANF(PATH_MEMINFO, "MemFree: %d", &memfree);
+ tst_res(TINFO, "Free RAM %d kB", memfree);
+
+ if (4 * hpsz > memfree)
+ tst_brk(TBROK, "Not enough free RAM");
+
+ orig_hugepages_node1 = modify_node_nr_hgpgs(path_hugepages_node1, sizeof(path_hugepages_node1), node1, hpsz, 4);
+ orig_hugepages_node2 = modify_node_nr_hgpgs(path_hugepages_node2, sizeof(path_hugepages_node2), node2, hpsz, 4);
+
+ hpsz *= 1024;
+
+ if (orig_hugepages_node1 == -1 || orig_hugepages_node2 == -1) {
+ SAFE_FILE_SCANF(PATH_NR_HUGEPAGES, "%ld", &orig_hugepages);
+ tst_res(TINFO, "Increasing global hugepages pool to %ld",
+ orig_hugepages + 8);
+ SAFE_FILE_PRINTF(PATH_NR_HUGEPAGES, "%ld", orig_hugepages + 8);
+ }
+
+ alloc_free_huge_on_node(node1, 4L * hpsz, hpsz);
+ alloc_free_huge_on_node(node2, 4L * hpsz, hpsz);
+}
+
+static void cleanup(void)
+{
+ restore_orig_hgpgs_value(PATH_NR_HUGEPAGES, orig_hugepages);
+ restore_orig_hgpgs_value(path_hugepages_node1, orig_hugepages_node1);
+ restore_orig_hgpgs_value(path_hugepages_node2, orig_hugepages_node2);
+}
+
+static struct tst_test test = {
+ .min_kver = "2.6.33",
+ .needs_root = 1,
+ .forks_child = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = do_test,
+};
+
+#else
+ TST_TEST_TCONF("test requires libnuma >= 2 and it's development packages");
+#endif
--
1.8.3.1
More information about the ltp
mailing list