[LTP] [PATCH v2] syscalls/move_page12.c: Add new regression test
Yang Xu
xuyang2018.jy@cn.fujitsu.com
Tue Apr 16 10:48:53 CEST 2019
The bug has been fixed in kernel: 'c9d398fa2378 ("mm, hugetlb:
use pte_present() instead of pmd_present() in follow_huge_pmd()").
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
---
.../kernel/syscalls/move_pages/move_pages12.c | 100 ++++++++++++------
1 file changed, 67 insertions(+), 33 deletions(-)
diff --git a/testcases/kernel/syscalls/move_pages/move_pages12.c b/testcases/kernel/syscalls/move_pages/move_pages12.c
index 04fda8bef..e9035a18e 100644
--- a/testcases/kernel/syscalls/move_pages/move_pages12.c
+++ b/testcases/kernel/syscalls/move_pages/move_pages12.c
@@ -1,35 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2016 Fujitsu Ltd.
* Author: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
* Ported: Guangwen Feng <fenggw-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/>.
+ * Ported: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Ported: Yang Xu <xuyang2018.jy@cn.jujitsu.com>
*/
/*
- * This is a regression test for the race condition between move_pages()
- * and freeing hugepages, where move_pages() calls follow_page(FOLL_GET)
- * for hugepages internally and tries to get its refcount without
- * preventing concurrent freeing.
+ * Description:
*
- * This test can crash the buggy kernel, and the bug was fixed in:
+ * Test #1:
+ * This is a regression test for the race condition between move_pages()
+ * and freeing hugepages, where move_pages() calls follow_page(FOLL_GET)
+ * for hugepages internally and tries to get its refcount without
+ * preventing concurrent freeing.
*
- * commit e66f17ff71772b209eed39de35aaa99ba819c93d
- * Author: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
- * Date: Wed Feb 11 15:25:22 2015 -0800
+ * This test can crash the buggy kernel, and the bug was fixed in:
+ *
+ * commit e66f17ff71772b209eed39de35aaa99ba819c93d
+ * Author: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
+ * Date: Wed Feb 11 15:25:22 2015 -0800
*
- * mm/hugetlb: take page table lock in follow_huge_pmd()
+ * mm/hugetlb: take page table lock in follow_huge_pmd()
+ *
+ * Test #2:
+ * 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>
@@ -49,9 +54,17 @@
#define PATH_MEMINFO "/proc/meminfo"
#define PATH_NR_HUGEPAGES "/proc/sys/vm/nr_hugepages"
#define PATH_HUGEPAGES "/sys/kernel/mm/hugepages/"
-#define TEST_PAGES 2
+#define PATH_PAGEMAP "/proc/self/pagemap"
#define TEST_NODES 2
+static struct tcase {
+ int tpages;
+ int offline;
+} tcases[] = {
+ {2, 0},
+ {2, 1},
+};
+
static int pgsz, hpsz;
static long orig_hugepages = -1;
static char path_hugepages_node1[PATH_MAX];
@@ -61,9 +74,21 @@ static long orig_hugepages_node2 = -1;
static unsigned int node1, node2;
static void *addr;
-static void do_child(void)
+static void do_soft_offline(int tpgs)
{
- int test_pages = TEST_PAGES * hpsz / pgsz;
+ if (madvise(addr, tpgs * hpsz, MADV_SOFT_OFFLINE) == -1) {
+ if (errno == EINVAL) {
+ tst_brk(TCONF,
+ "madvise() didn't support MADV_SOFT_OFFLINE");
+ } else {
+ tst_brk(TBROK | TERRNO, "madvise() failed");
+ }
+ }
+}
+
+static void do_child(int tpgs)
+{
+ int test_pages = tpgs * hpsz / pgsz;
int i, j;
int *nodes, *status;
void **pages;
@@ -96,34 +121,42 @@ static void do_child(void)
exit(0);
}
-static void do_test(void)
+static void do_test(unsigned int n)
{
int i;
pid_t cpid = -1;
int status;
unsigned int twenty_percent = (tst_timeout_remaining() / 5);
- addr = SAFE_MMAP(NULL, TEST_PAGES * hpsz, PROT_READ | PROT_WRITE,
+ if (tcases[n].offline) {
+ if (access(PATH_PAGEMAP, F_OK))
+ tst_brk(TCONF, "pagemap was not supported");
+ }
+
+ addr = SAFE_MMAP(NULL, tcases[n].tpages * hpsz, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
- SAFE_MUNMAP(addr, TEST_PAGES * hpsz);
+ SAFE_MUNMAP(addr, tcases[n].tpages * hpsz);
cpid = SAFE_FORK();
if (cpid == 0)
- do_child();
+ do_child(tcases[n].tpages);
for (i = 0; i < LOOPS; i++) {
void *ptr;
- ptr = SAFE_MMAP(NULL, TEST_PAGES * hpsz,
+ ptr = SAFE_MMAP(NULL, tcases[n].tpages * hpsz,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
if (ptr != addr)
tst_brk(TBROK, "Failed to mmap at desired addr");
- memset(addr, 0, TEST_PAGES * hpsz);
+ memset(addr, 0, tcases[n].tpages * hpsz);
+
+ if (tcases[n].offline)
+ do_soft_offline(tcases[n].tpages);
- SAFE_MUNMAP(addr, TEST_PAGES * hpsz);
+ SAFE_MUNMAP(addr, tcases[n].tpages * hpsz);
if (tst_timeout_remaining() < twenty_percent)
break;
@@ -266,7 +299,8 @@ static struct tst_test test = {
.forks_child = 1,
.setup = setup,
.cleanup = cleanup,
- .test_all = do_test,
+ .test = do_test,
+ .tcnt = ARRAY_SIZE(tcases),
};
#else
--
2.18.1
More information about the ltp
mailing list