[PATCH v3 3/7] selftests/mm: check that MADV_COLD and MADV_PAGEOUT reject hugetlb
From: Gregory Price (Meta)
Date: Mon Oct 19 2026 - 16:07:36 EST
Neither hint may be applied to hugetlb memory, so madvise(2) must fail
with EINVAL for a hugetlb VMA. Locked VMAs are already checked here and
PFNMAP VMAs by the pfnmap test.
Check the hugetlb case for both hints. run_vmtests.sh does not reserve
hugetlb pages, so when run as root main() reserves the one page the test
needs, and restores the pool on exit. Otherwise the test skips if no
page is free.
Signed-off-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
Reviewed-by: Sarthak Sharma <sarthak.sharma@xxxxxxx>
---
v3: Kept Sarthak's Reviewed-by, but only a couple minor changes,
e.g. the hugetlb reservations / skips.
---
.../testing/selftests/mm/madv_cold_pageout.c | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tools/testing/selftests/mm/madv_cold_pageout.c b/tools/testing/selftests/mm/madv_cold_pageout.c
index 8cbbfd4c24c4..0874726ec141 100644
--- a/tools/testing/selftests/mm/madv_cold_pageout.c
+++ b/tools/testing/selftests/mm/madv_cold_pageout.c
@@ -141,6 +141,29 @@ TEST_F(madv_cold_pageout, locked_vma_is_rejected)
ASSERT_EQ(munmap(mapping, page_size), 0);
}
+/* Neither hint may be applied to hugetlb memory. */
+TEST_F(madv_cold_pageout, hugetlb_vma_is_rejected)
+{
+ size_t size = default_huge_page_size();
+ char *mapping;
+
+ if (!size)
+ SKIP(return, "hugetlb is not supported");
+ mapping = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
+ if (mapping == MAP_FAILED)
+ SKIP(return, "no hugetlb pages are available");
+ mapping[0] = 1;
+
+ ASSERT_EQ(madvise(mapping, size, MADV_COLD), -1);
+ ASSERT_EQ(errno, EINVAL);
+ ASSERT_EQ(madvise(mapping, size, MADV_PAGEOUT), -1);
+ ASSERT_EQ(errno, EINVAL);
+ ASSERT_EQ(mapping[0], 1);
+
+ ASSERT_EQ(munmap(mapping, size), 0);
+}
+
/* A zero-length range is accepted. */
TEST_F(madv_cold_pageout, zero_length_is_accepted)
{
@@ -276,6 +299,9 @@ int main(int argc, char **argv)
page_size = getpagesize();
/* The harness forks each test, which inherits this. */
pin_to_current_cpu();
+ /* Only root can reserve the page that hugetlb_vma_is_rejected maps. */
+ if (!geteuid())
+ hugetlb_setup_default(1);
pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
if (pagemap_fd < 0)
--
2.56.0