Skip to content

Commit 9330694

Browse files
zokeefeakpm00
authored andcommitted
selftests/vm: add MADV_COLLAPSE collapse context to selftests
Add madvise collapse context to hugepage collapse selftests. This context is tested with /sys/kernel/mm/transparent_hugepage/enabled set to "never" in order to avoid unwanted interaction with khugepaged during testing. Also, refactor updates to sysfs THP settings using a stack so that the THP settings from nested callers can be restored. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Zach O'Keefe <[email protected]> Cc: Alex Shi <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Axel Rasmussen <[email protected]> Cc: Chris Kennelly <[email protected]> Cc: Chris Zankel <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: David Rientjes <[email protected]> Cc: Helge Deller <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Ivan Kokshaysky <[email protected]> Cc: James Bottomley <[email protected]> Cc: Jens Axboe <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Matt Turner <[email protected]> Cc: Max Filippov <[email protected]> Cc: Miaohe Lin <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Pasha Tatashin <[email protected]> Cc: Pavel Begunkov <[email protected]> Cc: Peter Xu <[email protected]> Cc: Rongwei Wang <[email protected]> Cc: SeongJae Park <[email protected]> Cc: Song Liu <[email protected]> Cc: Thomas Bogendoerfer <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Yang Shi <[email protected]> Cc: Zi Yan <[email protected]> Cc: Dan Carpenter <[email protected]> Cc: "Souptick Joarder (HPE)" <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent be6667b commit 9330694

File tree

1 file changed

+125
-46
lines changed

1 file changed

+125
-46
lines changed

tools/testing/selftests/vm/khugepaged.c

Lines changed: 125 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#ifndef MADV_PAGEOUT
1515
#define MADV_PAGEOUT 21
1616
#endif
17+
#ifndef MADV_COLLAPSE
18+
#define MADV_COLLAPSE 25
19+
#endif
1720

1821
#define BASE_ADDR ((void *)(1UL << 30))
1922
static unsigned long hpage_pmd_size;
@@ -95,18 +98,6 @@ struct settings {
9598
struct khugepaged_settings khugepaged;
9699
};
97100

98-
static struct settings default_settings = {
99-
.thp_enabled = THP_MADVISE,
100-
.thp_defrag = THP_DEFRAG_ALWAYS,
101-
.shmem_enabled = SHMEM_NEVER,
102-
.use_zero_page = 0,
103-
.khugepaged = {
104-
.defrag = 1,
105-
.alloc_sleep_millisecs = 10,
106-
.scan_sleep_millisecs = 10,
107-
},
108-
};
109-
110101
static struct settings saved_settings;
111102
static bool skip_settings_restore;
112103

@@ -284,6 +275,39 @@ static void write_settings(struct settings *settings)
284275
write_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan);
285276
}
286277

278+
#define MAX_SETTINGS_DEPTH 4
279+
static struct settings settings_stack[MAX_SETTINGS_DEPTH];
280+
static int settings_index;
281+
282+
static struct settings *current_settings(void)
283+
{
284+
if (!settings_index) {
285+
printf("Fail: No settings set");
286+
exit(EXIT_FAILURE);
287+
}
288+
return settings_stack + settings_index - 1;
289+
}
290+
291+
static void push_settings(struct settings *settings)
292+
{
293+
if (settings_index >= MAX_SETTINGS_DEPTH) {
294+
printf("Fail: Settings stack exceeded");
295+
exit(EXIT_FAILURE);
296+
}
297+
settings_stack[settings_index++] = *settings;
298+
write_settings(current_settings());
299+
}
300+
301+
static void pop_settings(void)
302+
{
303+
if (settings_index <= 0) {
304+
printf("Fail: Settings stack empty");
305+
exit(EXIT_FAILURE);
306+
}
307+
--settings_index;
308+
write_settings(current_settings());
309+
}
310+
287311
static void restore_settings(int sig)
288312
{
289313
if (skip_settings_restore)
@@ -327,14 +351,6 @@ static void save_settings(void)
327351
signal(SIGQUIT, restore_settings);
328352
}
329353

330-
static void adjust_settings(void)
331-
{
332-
333-
printf("Adjust settings...");
334-
write_settings(&default_settings);
335-
success("OK");
336-
}
337-
338354
#define MAX_LINE_LENGTH 500
339355

340356
static bool check_for_pattern(FILE *fp, char *pattern, char *buf)
@@ -493,6 +509,38 @@ static void validate_memory(int *p, unsigned long start, unsigned long end)
493509
}
494510
}
495511

512+
static void madvise_collapse(const char *msg, char *p, bool expect)
513+
{
514+
int ret;
515+
struct settings settings = *current_settings();
516+
517+
printf("%s...", msg);
518+
/* Sanity check */
519+
if (check_huge(p)) {
520+
printf("Unexpected huge page\n");
521+
exit(EXIT_FAILURE);
522+
}
523+
524+
/*
525+
* Prevent khugepaged interference and tests that MADV_COLLAPSE
526+
* ignores /sys/kernel/mm/transparent_hugepage/enabled
527+
*/
528+
settings.thp_enabled = THP_NEVER;
529+
push_settings(&settings);
530+
531+
/* Clear VM_NOHUGEPAGE */
532+
madvise(p, hpage_pmd_size, MADV_HUGEPAGE);
533+
ret = madvise(p, hpage_pmd_size, MADV_COLLAPSE);
534+
if (((bool)ret) == expect)
535+
fail("Fail: Bad return value");
536+
else if (check_huge(p) != expect)
537+
fail("Fail: check_huge()");
538+
else
539+
success("OK");
540+
541+
pop_settings();
542+
}
543+
496544
#define TICK 500000
497545
static bool wait_for_scan(const char *msg, char *p)
498546
{
@@ -542,11 +590,11 @@ static void khugepaged_collapse(const char *msg, char *p, bool expect)
542590

543591
static void alloc_at_fault(void)
544592
{
545-
struct settings settings = default_settings;
593+
struct settings settings = *current_settings();
546594
char *p;
547595

548596
settings.thp_enabled = THP_ALWAYS;
549-
write_settings(&settings);
597+
push_settings(&settings);
550598

551599
p = alloc_mapping();
552600
*p = 1;
@@ -556,7 +604,7 @@ static void alloc_at_fault(void)
556604
else
557605
fail("Fail");
558606

559-
write_settings(&default_settings);
607+
pop_settings();
560608

561609
madvise(p, page_size, MADV_DONTNEED);
562610
printf("Split huge PMD on MADV_DONTNEED...");
@@ -602,11 +650,11 @@ static void collapse_single_pte_entry(struct collapse_context *c)
602650
static void collapse_max_ptes_none(struct collapse_context *c)
603651
{
604652
int max_ptes_none = hpage_pmd_nr / 2;
605-
struct settings settings = default_settings;
653+
struct settings settings = *current_settings();
606654
void *p;
607655

608656
settings.khugepaged.max_ptes_none = max_ptes_none;
609-
write_settings(&settings);
657+
push_settings(&settings);
610658

611659
p = alloc_mapping();
612660

@@ -623,7 +671,7 @@ static void collapse_max_ptes_none(struct collapse_context *c)
623671
}
624672

625673
munmap(p, hpage_pmd_size);
626-
write_settings(&default_settings);
674+
pop_settings();
627675
}
628676

629677
static void collapse_swapin_single_pte(struct collapse_context *c)
@@ -703,7 +751,6 @@ static void collapse_single_pte_entry_compound(struct collapse_context *c)
703751

704752
p = alloc_hpage();
705753
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
706-
707754
printf("Split huge page leaving single PTE mapping compound page...");
708755
madvise(p + page_size, hpage_pmd_size - page_size, MADV_DONTNEED);
709756
if (!check_huge(p))
@@ -864,7 +911,7 @@ static void collapse_fork_compound(struct collapse_context *c)
864911
c->collapse("Collapse PTE table full of compound pages in child",
865912
p, true);
866913
write_num("khugepaged/max_ptes_shared",
867-
default_settings.khugepaged.max_ptes_shared);
914+
current_settings()->khugepaged.max_ptes_shared);
868915

869916
validate_memory(p, 0, hpage_pmd_size);
870917
munmap(p, hpage_pmd_size);
@@ -943,9 +990,21 @@ static void collapse_max_ptes_shared(struct collapse_context *c)
943990
munmap(p, hpage_pmd_size);
944991
}
945992

946-
int main(void)
993+
int main(int argc, const char **argv)
947994
{
948995
struct collapse_context c;
996+
struct settings default_settings = {
997+
.thp_enabled = THP_MADVISE,
998+
.thp_defrag = THP_DEFRAG_ALWAYS,
999+
.shmem_enabled = SHMEM_NEVER,
1000+
.use_zero_page = 0,
1001+
.khugepaged = {
1002+
.defrag = 1,
1003+
.alloc_sleep_millisecs = 10,
1004+
.scan_sleep_millisecs = 10,
1005+
},
1006+
};
1007+
const char *tests = argc == 1 ? "all" : argv[1];
9491008

9501009
setbuf(stdout, NULL);
9511010

@@ -959,26 +1018,46 @@ int main(void)
9591018
default_settings.khugepaged.pages_to_scan = hpage_pmd_nr * 8;
9601019

9611020
save_settings();
962-
adjust_settings();
1021+
push_settings(&default_settings);
9631022

9641023
alloc_at_fault();
9651024

966-
printf("\n*** Testing context: khugepaged ***\n");
967-
c.collapse = &khugepaged_collapse;
968-
c.enforce_pte_scan_limits = true;
969-
970-
collapse_full(&c);
971-
collapse_empty(&c);
972-
collapse_single_pte_entry(&c);
973-
collapse_max_ptes_none(&c);
974-
collapse_swapin_single_pte(&c);
975-
collapse_max_ptes_swap(&c);
976-
collapse_single_pte_entry_compound(&c);
977-
collapse_full_of_compound(&c);
978-
collapse_compound_extreme(&c);
979-
collapse_fork(&c);
980-
collapse_fork_compound(&c);
981-
collapse_max_ptes_shared(&c);
1025+
if (!strcmp(tests, "khugepaged") || !strcmp(tests, "all")) {
1026+
printf("\n*** Testing context: khugepaged ***\n");
1027+
c.collapse = &khugepaged_collapse;
1028+
c.enforce_pte_scan_limits = true;
1029+
1030+
collapse_full(&c);
1031+
collapse_empty(&c);
1032+
collapse_single_pte_entry(&c);
1033+
collapse_max_ptes_none(&c);
1034+
collapse_swapin_single_pte(&c);
1035+
collapse_max_ptes_swap(&c);
1036+
collapse_single_pte_entry_compound(&c);
1037+
collapse_full_of_compound(&c);
1038+
collapse_compound_extreme(&c);
1039+
collapse_fork(&c);
1040+
collapse_fork_compound(&c);
1041+
collapse_max_ptes_shared(&c);
1042+
}
1043+
if (!strcmp(tests, "madvise") || !strcmp(tests, "all")) {
1044+
printf("\n*** Testing context: madvise ***\n");
1045+
c.collapse = &madvise_collapse;
1046+
c.enforce_pte_scan_limits = false;
1047+
1048+
collapse_full(&c);
1049+
collapse_empty(&c);
1050+
collapse_single_pte_entry(&c);
1051+
collapse_max_ptes_none(&c);
1052+
collapse_swapin_single_pte(&c);
1053+
collapse_max_ptes_swap(&c);
1054+
collapse_single_pte_entry_compound(&c);
1055+
collapse_full_of_compound(&c);
1056+
collapse_compound_extreme(&c);
1057+
collapse_fork(&c);
1058+
collapse_fork_compound(&c);
1059+
collapse_max_ptes_shared(&c);
1060+
}
9821061

9831062
restore_settings(0);
9841063
}

0 commit comments

Comments
 (0)