@@ -14,6 +14,9 @@
#ifndef MADV_PAGEOUT
#define MADV_PAGEOUT 21
#endif
+#ifndef MADV_COLLAPSE
+#define MADV_COLLAPSE 25
+#endif
#define BASE_ADDR ((void *)(1UL << 30))
static unsigned long hpage_pmd_size;
@@ -108,6 +111,7 @@ static struct settings default_settings = {
};
static struct settings saved_settings;
+static struct settings current_settings;
static bool skip_settings_restore;
static int exit_status;
@@ -282,6 +286,8 @@ static void write_settings(struct settings *settings)
write_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap);
write_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared);
write_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan);
+
+ current_settings = *settings;
}
static void restore_settings(int sig)
@@ -912,6 +918,38 @@ static void collapse_max_ptes_shared(struct collapse_context *c)
munmap(p, hpage_pmd_size);
}
+static void madvise_collapse(const char *msg, char *p, bool expect)
+{
+ int ret;
+ struct settings old_settings = current_settings;
+ struct settings settings = old_settings;
+
+ printf("%s...", msg);
+ /* Sanity check */
+ if (check_huge(p)) {
+ printf("Unexpected huge page\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Prevent khugepaged interference and tests that MADV_COLLAPSE
+ * ignores /sys/kernel/mm/transparent_hugepage/enabled
+ */
+ settings.thp_enabled = THP_NEVER;
+ write_settings(&settings);
+
+ madvise(p, hpage_pmd_size, MADV_HUGEPAGE);
+ ret = madvise(p, hpage_pmd_size, MADV_COLLAPSE);
+ if (((bool)ret) == expect)
+ fail("Fail: Bad return value");
+ else if (check_huge(p) != expect)
+ fail("Fail: check_huge()");
+ else
+ success("OK");
+
+ write_settings(&old_settings);
+}
+
#define TICK 500000
static bool wait_for_scan(const char *msg, char *p)
{
@@ -996,5 +1034,22 @@ int main(void)
collapse_fork_compound(&c);
collapse_max_ptes_shared(&c);
+ 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);
+
restore_settings(0);
}
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. Signed-off-by: Zach O'Keefe <zokeefe@google.com> --- tools/testing/selftests/vm/khugepaged.c | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+)