From: Andrew Morton <akpm@linux-foundation.org>
To: mm-commits@vger.kernel.org, willy@infradead.org, vbabka@suse.cz,
songliubraving@fb.com, sj@kernel.org, shy828301@gmail.com,
rongwei.wang@linux.alibaba.com, rientjes@google.com,
peterx@redhat.com, pasha.tatashin@soleen.com, minchan@kernel.org,
linmiaohe@huawei.com, kirill.shutemov@linux.intel.com,
jthoughton@google.com, hughd@google.com, david@redhat.com,
ckennelly@google.com, axelrasmussen@google.com,
zokeefe@google.com, akpm@linux-foundation.org
Subject: + selftests-vm-modularize-thp-collapse-memory-operations.patch added to mm-unstable branch
Date: Sun, 25 Sep 2022 12:13:41 -0700 [thread overview]
Message-ID: <20220925191342.6D89DC433D6@smtp.kernel.org> (raw)
The patch titled
Subject: selftests/vm: modularize thp collapse memory operations
has been added to the -mm mm-unstable branch. Its filename is
selftests-vm-modularize-thp-collapse-memory-operations.patch
This patch will shortly appear at
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/selftests-vm-modularize-thp-collapse-memory-operations.patch
This patch will later appear in the mm-unstable branch at
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
The -mm tree is included into linux-next via the mm-everything
branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
and is updated there every 2-3 working days
------------------------------------------------------
From: "Zach O'Keefe" <zokeefe@google.com>
Subject: selftests/vm: modularize thp collapse memory operations
Date: Thu, 22 Sep 2022 15:40:42 -0700
Modularize operations to setup, cleanup, fault, and check for huge pages,
for a given memory type. This allows reusing existing tests with
additional memory types by defining new memory operations. Following
patches will add file and shmem memory types.
Link: https://lkml.kernel.org/r/20220907144521.3115321-7-zokeefe@google.com
Link: https://lkml.kernel.org/r/20220922224046.1143204-7-zokeefe@google.com
Signed-off-by: Zach O'Keefe <zokeefe@google.com>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Chris Kennelly <ckennelly@google.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: James Houghton <jthoughton@google.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Rongwei Wang <rongwei.wang@linux.alibaba.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Yang Shi <shy828301@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
--- a/tools/testing/selftests/vm/khugepaged.c~selftests-vm-modularize-thp-collapse-memory-operations
+++ a/tools/testing/selftests/vm/khugepaged.c
@@ -29,8 +29,16 @@ static int hpage_pmd_nr;
#define THP_SYSFS "/sys/kernel/mm/transparent_hugepage/"
#define PID_SMAPS "/proc/self/smaps"
+struct mem_ops {
+ void *(*setup_area)(int nr_hpages);
+ void (*cleanup_area)(void *p, unsigned long size);
+ void (*fault)(void *p, unsigned long start, unsigned long end);
+ bool (*check_huge)(void *addr, int nr_hpages);
+};
+
struct collapse_context {
- void (*collapse)(const char *msg, char *p, int nr_hpages, bool expect);
+ void (*collapse)(const char *msg, char *p, int nr_hpages,
+ struct mem_ops *ops, bool expect);
bool enforce_pte_scan_limits;
};
@@ -354,11 +362,6 @@ static void save_settings(void)
signal(SIGQUIT, restore_settings);
}
-static bool check_huge(void *addr, int nr_hpages)
-{
- return check_huge_anon(addr, nr_hpages, hpage_pmd_size);
-}
-
#define MAX_LINE_LENGTH 500
static bool check_swap(void *addr, unsigned long size)
{
@@ -452,18 +455,33 @@ retry:
* Returns pmd-mapped hugepage in VMA marked VM_HUGEPAGE, filled with
* validate_memory()'able contents.
*/
-static void *alloc_hpage(void)
+static void *alloc_hpage(struct mem_ops *ops)
{
- void *p;
+ void *p = ops->setup_area(1);
- p = alloc_mapping(1);
+ ops->fault(p, 0, hpage_pmd_size);
+
+ /*
+ * VMA should be neither VM_HUGEPAGE nor VM_NOHUGEPAGE.
+ * The latter is ineligible for collapse by MADV_COLLAPSE
+ * while the former might cause MADV_COLLAPSE to race with
+ * khugepaged on low-load system (like a test machine), which
+ * would cause MADV_COLLAPSE to fail with EAGAIN.
+ */
printf("Allocate huge page...");
- madvise(p, hpage_pmd_size, MADV_HUGEPAGE);
- fill_memory(p, 0, hpage_pmd_size);
- if (check_huge(p, 1))
- success("OK");
- else
- fail("Fail");
+ if (madvise_collapse_retry(p, hpage_pmd_size)) {
+ perror("madvise(MADV_COLLAPSE)");
+ exit(EXIT_FAILURE);
+ }
+ if (!ops->check_huge(p, 1)) {
+ perror("madvise(MADV_COLLAPSE)");
+ exit(EXIT_FAILURE);
+ }
+ if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) {
+ perror("madvise(MADV_HUGEPAGE)");
+ exit(EXIT_FAILURE);
+ }
+ success("OK");
return p;
}
@@ -480,18 +498,40 @@ static void validate_memory(int *p, unsi
}
}
-static void madvise_collapse(const char *msg, char *p, int nr_hpages,
- bool expect)
+static void *anon_setup_area(int nr_hpages)
+{
+ return alloc_mapping(nr_hpages);
+}
+
+static void anon_cleanup_area(void *p, unsigned long size)
+{
+ munmap(p, size);
+}
+
+static void anon_fault(void *p, unsigned long start, unsigned long end)
+{
+ fill_memory(p, start, end);
+}
+
+static bool anon_check_huge(void *addr, int nr_hpages)
+{
+ return check_huge_anon(addr, nr_hpages, hpage_pmd_size);
+}
+
+static struct mem_ops anon_ops = {
+ .setup_area = &anon_setup_area,
+ .cleanup_area = &anon_cleanup_area,
+ .fault = &anon_fault,
+ .check_huge = &anon_check_huge,
+};
+
+static void __madvise_collapse(const char *msg, char *p, int nr_hpages,
+ struct mem_ops *ops, bool expect)
{
int ret;
struct settings settings = *current_settings();
printf("%s...", msg);
- /* Sanity check */
- if (!check_huge(p, 0)) {
- printf("Unexpected huge page\n");
- exit(EXIT_FAILURE);
- }
/*
* Prevent khugepaged interference and tests that MADV_COLLAPSE
@@ -505,7 +545,7 @@ static void madvise_collapse(const char
ret = madvise_collapse_retry(p, nr_hpages * hpage_pmd_size);
if (((bool)ret) == expect)
fail("Fail: Bad return value");
- else if (check_huge(p, nr_hpages) != expect)
+ else if (!ops->check_huge(p, expect ? nr_hpages : 0))
fail("Fail: check_huge()");
else
success("OK");
@@ -513,14 +553,26 @@ static void madvise_collapse(const char
pop_settings();
}
+static void madvise_collapse(const char *msg, char *p, int nr_hpages,
+ struct mem_ops *ops, bool expect)
+{
+ /* Sanity check */
+ if (!ops->check_huge(p, 0)) {
+ printf("Unexpected huge page\n");
+ exit(EXIT_FAILURE);
+ }
+ __madvise_collapse(msg, p, nr_hpages, ops, expect);
+}
+
#define TICK 500000
-static bool wait_for_scan(const char *msg, char *p, int nr_hpages)
+static bool wait_for_scan(const char *msg, char *p, int nr_hpages,
+ struct mem_ops *ops)
{
int full_scans;
int timeout = 6; /* 3 seconds */
/* Sanity check */
- if (!check_huge(p, 0)) {
+ if (!ops->check_huge(p, 0)) {
printf("Unexpected huge page\n");
exit(EXIT_FAILURE);
}
@@ -532,7 +584,7 @@ static bool wait_for_scan(const char *ms
printf("%s...", msg);
while (timeout--) {
- if (check_huge(p, nr_hpages))
+ if (ops->check_huge(p, nr_hpages))
break;
if (read_num("khugepaged/full_scans") >= full_scans)
break;
@@ -546,19 +598,20 @@ static bool wait_for_scan(const char *ms
}
static void khugepaged_collapse(const char *msg, char *p, int nr_hpages,
- bool expect)
+ struct mem_ops *ops, bool expect)
{
- if (wait_for_scan(msg, p, nr_hpages)) {
+ if (wait_for_scan(msg, p, nr_hpages, ops)) {
if (expect)
fail("Timeout");
else
success("OK");
return;
- } else if (check_huge(p, nr_hpages) == expect) {
+ }
+
+ if (ops->check_huge(p, expect ? nr_hpages : 0))
success("OK");
- } else {
+ else
fail("Fail");
- }
}
static void alloc_at_fault(void)
@@ -572,7 +625,7 @@ static void alloc_at_fault(void)
p = alloc_mapping(1);
*p = 1;
printf("Allocate huge page on fault...");
- if (check_huge(p, 1))
+ if (check_huge_anon(p, 1, hpage_pmd_size))
success("OK");
else
fail("Fail");
@@ -581,49 +634,48 @@ static void alloc_at_fault(void)
madvise(p, page_size, MADV_DONTNEED);
printf("Split huge PMD on MADV_DONTNEED...");
- if (check_huge(p, 0))
+ if (check_huge_anon(p, 0, hpage_pmd_size))
success("OK");
else
fail("Fail");
munmap(p, hpage_pmd_size);
}
-static void collapse_full(struct collapse_context *c)
+static void collapse_full(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
int nr_hpages = 4;
unsigned long size = nr_hpages * hpage_pmd_size;
- p = alloc_mapping(nr_hpages);
- fill_memory(p, 0, size);
+ p = ops->setup_area(nr_hpages);
+ ops->fault(p, 0, size);
c->collapse("Collapse multiple fully populated PTE table", p, nr_hpages,
- true);
+ ops, true);
validate_memory(p, 0, size);
- munmap(p, size);
+ ops->cleanup_area(p, size);
}
-static void collapse_empty(struct collapse_context *c)
+static void collapse_empty(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
- p = alloc_mapping(1);
- c->collapse("Do not collapse empty PTE table", p, 1, false);
- munmap(p, hpage_pmd_size);
+ p = ops->setup_area(1);
+ c->collapse("Do not collapse empty PTE table", p, 1, ops, false);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_single_pte_entry(struct collapse_context *c)
+static void collapse_single_pte_entry(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
- p = alloc_mapping(1);
- fill_memory(p, 0, page_size);
+ p = ops->setup_area(1);
+ ops->fault(p, 0, page_size);
c->collapse("Collapse PTE table with single PTE entry present", p,
- 1, true);
- validate_memory(p, 0, page_size);
- munmap(p, hpage_pmd_size);
+ 1, ops, true);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_max_ptes_none(struct collapse_context *c)
+static void collapse_max_ptes_none(struct collapse_context *c, struct mem_ops *ops)
{
int max_ptes_none = hpage_pmd_nr / 2;
struct settings settings = *current_settings();
@@ -632,30 +684,30 @@ static void collapse_max_ptes_none(struc
settings.khugepaged.max_ptes_none = max_ptes_none;
push_settings(&settings);
- p = alloc_mapping(1);
+ p = ops->setup_area(1);
- fill_memory(p, 0, (hpage_pmd_nr - max_ptes_none - 1) * page_size);
+ ops->fault(p, 0, (hpage_pmd_nr - max_ptes_none - 1) * page_size);
c->collapse("Maybe collapse with max_ptes_none exceeded", p, 1,
- !c->enforce_pte_scan_limits);
+ ops, !c->enforce_pte_scan_limits);
validate_memory(p, 0, (hpage_pmd_nr - max_ptes_none - 1) * page_size);
if (c->enforce_pte_scan_limits) {
- fill_memory(p, 0, (hpage_pmd_nr - max_ptes_none) * page_size);
- c->collapse("Collapse with max_ptes_none PTEs empty", p, 1,
+ ops->fault(p, 0, (hpage_pmd_nr - max_ptes_none) * page_size);
+ c->collapse("Collapse with max_ptes_none PTEs empty", p, 1, ops,
true);
validate_memory(p, 0,
(hpage_pmd_nr - max_ptes_none) * page_size);
}
-
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
pop_settings();
}
-static void collapse_swapin_single_pte(struct collapse_context *c)
+static void collapse_swapin_single_pte(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
- p = alloc_mapping(1);
- fill_memory(p, 0, hpage_pmd_size);
+
+ p = ops->setup_area(1);
+ ops->fault(p, 0, hpage_pmd_size);
printf("Swapout one page...");
if (madvise(p, page_size, MADV_PAGEOUT)) {
@@ -669,20 +721,21 @@ static void collapse_swapin_single_pte(s
goto out;
}
- c->collapse("Collapse with swapping in single PTE entry", p, 1, true);
+ c->collapse("Collapse with swapping in single PTE entry", p, 1, ops,
+ true);
validate_memory(p, 0, hpage_pmd_size);
out:
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_max_ptes_swap(struct collapse_context *c)
+static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *ops)
{
int max_ptes_swap = read_num("khugepaged/max_ptes_swap");
void *p;
- p = alloc_mapping(1);
+ p = ops->setup_area(1);
+ ops->fault(p, 0, hpage_pmd_size);
- fill_memory(p, 0, hpage_pmd_size);
printf("Swapout %d of %d pages...", max_ptes_swap + 1, hpage_pmd_nr);
if (madvise(p, (max_ptes_swap + 1) * page_size, MADV_PAGEOUT)) {
perror("madvise(MADV_PAGEOUT)");
@@ -695,12 +748,12 @@ static void collapse_max_ptes_swap(struc
goto out;
}
- c->collapse("Maybe collapse with max_ptes_swap exceeded", p, 1,
+ c->collapse("Maybe collapse with max_ptes_swap exceeded", p, 1, ops,
!c->enforce_pte_scan_limits);
validate_memory(p, 0, hpage_pmd_size);
if (c->enforce_pte_scan_limits) {
- fill_memory(p, 0, hpage_pmd_size);
+ ops->fault(p, 0, hpage_pmd_size);
printf("Swapout %d of %d pages...", max_ptes_swap,
hpage_pmd_nr);
if (madvise(p, max_ptes_swap * page_size, MADV_PAGEOUT)) {
@@ -715,63 +768,65 @@ static void collapse_max_ptes_swap(struc
}
c->collapse("Collapse with max_ptes_swap pages swapped out", p,
- 1, true);
+ 1, ops, true);
validate_memory(p, 0, hpage_pmd_size);
}
out:
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_single_pte_entry_compound(struct collapse_context *c)
+static void collapse_single_pte_entry_compound(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
- p = alloc_hpage();
+ p = alloc_hpage(ops);
+
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
printf("Split huge page leaving single PTE mapping compound page...");
madvise(p + page_size, hpage_pmd_size - page_size, MADV_DONTNEED);
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
c->collapse("Collapse PTE table with single PTE mapping compound page",
- p, 1, true);
+ p, 1, ops, true);
validate_memory(p, 0, page_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_full_of_compound(struct collapse_context *c)
+static void collapse_full_of_compound(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
- p = alloc_hpage();
+ p = alloc_hpage(ops);
printf("Split huge page leaving single PTE page table full of compound pages...");
madvise(p, page_size, MADV_NOHUGEPAGE);
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
- c->collapse("Collapse PTE table full of compound pages", p, 1, true);
+ c->collapse("Collapse PTE table full of compound pages", p, 1, ops,
+ true);
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_compound_extreme(struct collapse_context *c)
+static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops *ops)
{
void *p;
int i;
- p = alloc_mapping(1);
+ p = ops->setup_area(1);
for (i = 0; i < hpage_pmd_nr; i++) {
printf("\rConstruct PTE page table full of different PTE-mapped compound pages %3d/%d...",
i + 1, hpage_pmd_nr);
madvise(BASE_ADDR, hpage_pmd_size, MADV_HUGEPAGE);
- fill_memory(BASE_ADDR, 0, hpage_pmd_size);
- if (!check_huge(BASE_ADDR, 1)) {
+ ops->fault(BASE_ADDR, 0, hpage_pmd_size);
+ if (!ops->check_huge(BASE_ADDR, 1)) {
printf("Failed to allocate huge page\n");
exit(EXIT_FAILURE);
}
@@ -798,30 +853,30 @@ static void collapse_compound_extreme(st
}
}
- munmap(BASE_ADDR, hpage_pmd_size);
- fill_memory(p, 0, hpage_pmd_size);
- if (check_huge(p, 0))
+ ops->cleanup_area(BASE_ADDR, hpage_pmd_size);
+ ops->fault(p, 0, hpage_pmd_size);
+ if (!ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
c->collapse("Collapse PTE table full of different compound pages", p, 1,
- true);
+ ops, true);
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_fork(struct collapse_context *c)
+static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
{
int wstatus;
void *p;
- p = alloc_mapping(1);
+ p = ops->setup_area(1);
printf("Allocate small page...");
- fill_memory(p, 0, page_size);
- if (check_huge(p, 0))
+ ops->fault(p, 0, page_size);
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
@@ -832,17 +887,17 @@ static void collapse_fork(struct collaps
skip_settings_restore = true;
exit_status = 0;
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
- fill_memory(p, page_size, 2 * page_size);
+ ops->fault(p, page_size, 2 * page_size);
c->collapse("Collapse PTE table with single page shared with parent process",
- p, 1, true);
+ p, 1, ops, true);
validate_memory(p, 0, page_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
exit(exit_status);
}
@@ -850,27 +905,27 @@ static void collapse_fork(struct collaps
exit_status += WEXITSTATUS(wstatus);
printf("Check if parent still has small page...");
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
validate_memory(p, 0, page_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_fork_compound(struct collapse_context *c)
+static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *ops)
{
int wstatus;
void *p;
- p = alloc_hpage();
+ p = alloc_hpage(ops);
printf("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
skip_settings_restore = true;
exit_status = 0;
- if (check_huge(p, 1))
+ if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
@@ -878,20 +933,20 @@ static void collapse_fork_compound(struc
printf("Split huge page PMD in child process...");
madvise(p, page_size, MADV_NOHUGEPAGE);
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
- fill_memory(p, 0, page_size);
+ ops->fault(p, 0, page_size);
write_num("khugepaged/max_ptes_shared", hpage_pmd_nr - 1);
c->collapse("Collapse PTE table full of compound pages in child",
- p, 1, true);
+ p, 1, ops, true);
write_num("khugepaged/max_ptes_shared",
current_settings()->khugepaged.max_ptes_shared);
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
exit(exit_status);
}
@@ -899,59 +954,59 @@ static void collapse_fork_compound(struc
exit_status += WEXITSTATUS(wstatus);
printf("Check if parent still has huge page...");
- if (check_huge(p, 1))
+ if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void collapse_max_ptes_shared(struct collapse_context *c)
+static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops *ops)
{
int max_ptes_shared = read_num("khugepaged/max_ptes_shared");
int wstatus;
void *p;
- p = alloc_hpage();
+ p = alloc_hpage(ops);
printf("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
skip_settings_restore = true;
exit_status = 0;
- if (check_huge(p, 1))
+ if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
printf("Trigger CoW on page %d of %d...",
hpage_pmd_nr - max_ptes_shared - 1, hpage_pmd_nr);
- fill_memory(p, 0, (hpage_pmd_nr - max_ptes_shared - 1) * page_size);
- if (check_huge(p, 0))
+ ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared - 1) * page_size);
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
c->collapse("Maybe collapse with max_ptes_shared exceeded", p,
- 1, !c->enforce_pte_scan_limits);
+ 1, ops, !c->enforce_pte_scan_limits);
if (c->enforce_pte_scan_limits) {
printf("Trigger CoW on page %d of %d...",
hpage_pmd_nr - max_ptes_shared, hpage_pmd_nr);
- fill_memory(p, 0, (hpage_pmd_nr - max_ptes_shared) *
+ ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared) *
page_size);
- if (check_huge(p, 0))
+ if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
c->collapse("Collapse with max_ptes_shared PTEs shared",
- p, 1, true);
+ p, 1, ops, true);
}
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
exit(exit_status);
}
@@ -959,42 +1014,28 @@ static void collapse_max_ptes_shared(str
exit_status += WEXITSTATUS(wstatus);
printf("Check if parent still has huge page...");
- if (check_huge(p, 1))
+ if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
-static void madvise_collapse_existing_thps(void)
+static void madvise_collapse_existing_thps(struct collapse_context *c,
+ struct mem_ops *ops)
{
void *p;
- int err;
- p = alloc_mapping(1);
- fill_memory(p, 0, hpage_pmd_size);
+ p = ops->setup_area(1);
+ ops->fault(p, 0, hpage_pmd_size);
+ c->collapse("Collapse fully populated PTE table...", p, 1, ops, true);
+ validate_memory(p, 0, hpage_pmd_size);
- printf("Collapse fully populated PTE table...");
- /*
- * Note that we don't set MADV_HUGEPAGE here, which
- * also tests that VM_HUGEPAGE isn't required for
- * MADV_COLLAPSE in "madvise" mode.
- */
- err = madvise(p, hpage_pmd_size, MADV_COLLAPSE);
- if (err == 0 && check_huge(p, 1)) {
- success("OK");
- printf("Re-collapse PMD-mapped hugepage");
- err = madvise(p, hpage_pmd_size, MADV_COLLAPSE);
- if (err == 0 && check_huge(p, 1))
- success("OK");
- else
- fail("Fail");
- } else {
- fail("Fail");
- }
+ /* c->collapse() will find a hugepage and complain - call directly. */
+ __madvise_collapse("Re-collapse PMD-mapped hugepage", p, 1, ops, true);
validate_memory(p, 0, hpage_pmd_size);
- munmap(p, hpage_pmd_size);
+ ops->cleanup_area(p, hpage_pmd_size);
}
int main(int argc, const char **argv)
@@ -1034,37 +1075,37 @@ int main(int argc, const char **argv)
c.collapse = &khugepaged_collapse;
c.enforce_pte_scan_limits = true;
- collapse_full(&c);
- collapse_empty(&c);
- collapse_single_pte_entry(&c);
- collapse_max_ptes_none(&c);
- collapse_swapin_single_pte(&c);
- collapse_max_ptes_swap(&c);
- collapse_single_pte_entry_compound(&c);
- collapse_full_of_compound(&c);
- collapse_compound_extreme(&c);
- collapse_fork(&c);
- collapse_fork_compound(&c);
- collapse_max_ptes_shared(&c);
+ collapse_full(&c, &anon_ops);
+ collapse_empty(&c, &anon_ops);
+ collapse_single_pte_entry(&c, &anon_ops);
+ collapse_max_ptes_none(&c, &anon_ops);
+ collapse_swapin_single_pte(&c, &anon_ops);
+ collapse_max_ptes_swap(&c, &anon_ops);
+ collapse_single_pte_entry_compound(&c, &anon_ops);
+ collapse_full_of_compound(&c, &anon_ops);
+ collapse_compound_extreme(&c, &anon_ops);
+ collapse_fork(&c, &anon_ops);
+ collapse_fork_compound(&c, &anon_ops);
+ collapse_max_ptes_shared(&c, &anon_ops);
}
if (!strcmp(tests, "madvise") || !strcmp(tests, "all")) {
printf("\n*** Testing context: madvise ***\n");
c.collapse = &madvise_collapse;
c.enforce_pte_scan_limits = false;
- collapse_full(&c);
- collapse_empty(&c);
- collapse_single_pte_entry(&c);
- collapse_max_ptes_none(&c);
- collapse_swapin_single_pte(&c);
- collapse_max_ptes_swap(&c);
- collapse_single_pte_entry_compound(&c);
- collapse_full_of_compound(&c);
- collapse_compound_extreme(&c);
- collapse_fork(&c);
- collapse_fork_compound(&c);
- collapse_max_ptes_shared(&c);
- madvise_collapse_existing_thps();
+ collapse_full(&c, &anon_ops);
+ collapse_empty(&c, &anon_ops);
+ collapse_single_pte_entry(&c, &anon_ops);
+ collapse_max_ptes_none(&c, &anon_ops);
+ collapse_swapin_single_pte(&c, &anon_ops);
+ collapse_max_ptes_swap(&c, &anon_ops);
+ collapse_single_pte_entry_compound(&c, &anon_ops);
+ collapse_full_of_compound(&c, &anon_ops);
+ collapse_compound_extreme(&c, &anon_ops);
+ collapse_fork(&c, &anon_ops);
+ collapse_fork_compound(&c, &anon_ops);
+ collapse_max_ptes_shared(&c, &anon_ops);
+ madvise_collapse_existing_thps(&c, &anon_ops);
}
restore_settings(0);
_
Patches currently in -mm which might be from zokeefe@google.com are
mm-khugepaged-check-compound_order-in-collapse_pte_mapped_thp.patch
mm-madvise-madv_collapse-return-eagain-when-page-cannot-be-isolated.patch
selftests-vm-retry-on-eagain-for-madv_collapse-selftest.patch
mm-shmem-add-flag-to-enforce-shmem-thp-in-hugepage_vma_check.patch
mm-khugepaged-attempt-to-map-file-shmem-backed-pte-mapped-thps-by-pmds.patch
mm-madvise-add-file-and-shmem-support-to-madv_collapse.patch
mm-khugepaged-add-tracepoint-to-hpage_collapse_scan_file.patch
selftests-vm-dedup-thp-helpers.patch
selftests-vm-modularize-thp-collapse-memory-operations.patch
selftests-vm-add-thp-collapse-file-and-tmpfs-testing.patch
selftests-vm-add-thp-collapse-shmem-testing.patch
selftests-vm-add-file-shmem-madv_collapse-selftest-for-cleared-pmd.patch
selftests-vm-add-selftest-for-madv_collapse-of-uffd-minor-memory.patch
next reply other threads:[~2022-09-25 19:14 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-25 19:13 Andrew Morton [this message]
-- strict thread matches above, loose matches on Subject: below --
2022-09-07 22:20 + selftests-vm-modularize-thp-collapse-memory-operations.patch added to mm-unstable branch Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220925191342.6D89DC433D6@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=ckennelly@google.com \
--cc=david@redhat.com \
--cc=hughd@google.com \
--cc=jthoughton@google.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=linmiaohe@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=minchan@kernel.org \
--cc=mm-commits@vger.kernel.org \
--cc=pasha.tatashin@soleen.com \
--cc=peterx@redhat.com \
--cc=rientjes@google.com \
--cc=rongwei.wang@linux.alibaba.com \
--cc=shy828301@gmail.com \
--cc=sj@kernel.org \
--cc=songliubraving@fb.com \
--cc=vbabka@suse.cz \
--cc=willy@infradead.org \
--cc=zokeefe@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.