* [PATCH v4 00/55] make MM selftests more CI friendly
@ 2026-05-11 16:27 Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 01/55] selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler Mike Rapoport
` (55 more replies)
0 siblings, 56 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Hi,
There's a lot of dancing around HugeTLB settings in run_vmtests.sh.
Some test need just a few default huge pages, some require at least 256 MB, and
some just skip lots of tests if huge pages of all supported sizes are not
available.
The goal of this set is to make tests deal with HugeTLB setup and teardown.
There are already convenient helpers that allow easy reading and writing of
/proc and /sysfs, so adding a few APIs that will detect and update HugeTLB
settings shouldn't be a big deal. But these nice helpers use kselftest
framework, and many of HugeTLB (and even THP) test don't, so as a result this
patchset also includes a lot of churn for conversion of those tests to
kselftest framework (patches 7-19).
The series break out:
patches 1-5: small fixes
patch 6: merge of hugetlb mmap tests
patch 7: renaming of hugepage-* to hugetlb-*
patches 8-21: mechanical conversion to kselftest framework
patches 22-28: extension of thp_settings to hugepage_settings to also include
HugeTLB helpers
patches 29-30: add helpers for setting up SHM limits in hugetlb-shm and
thuge-gen tests
patches 31-53: integrate the new APIs in all the tests that use HugeTLB
patches 54-55: drop HugeTLB setup from run_vmtests.sh
--
@Andrew, I think it's good to go now.
I'm sure Sashiko will still have somehting to say, but there is really a lot of
room for imporvement in our selftests and with Sashiko being overly pedantic
we'd be stuck forever.
v4 changes:
* rework fork()ed process cleanup in migration test to be more robust
* rework HugeTLB setup to use free pages before allocating new ones,
add hugetlb_setup_default_exact() for compaction test
* guard against double save/restore of THP and HugeTLB settings
* convert uffd error macros to use ksft reporting
* fix ksft reporting in several tests
* gracefully bail out if default huge page size is 0 in several tests
and gup_test
* add more tags, thanks everyone!
v3: https://lore.kernel.org/all/20260428204240.1924129-1-rppt@kernel.org
* add patches that fix cleanup of fork()ed processes in migration test
* drop MADV_REMOVE changes to khugepage test
* properly setup memfd for non-default hugepages in hugetlb-mmap test
* add forgotten hugetlb_save_settings() to hugetlb_setup()
* fixes for ksft reporting
* rebase on v7.1-rc1
* add more tags, thanks everyone!
v2: https://lore.kernel.org/all/20260418105539.1261536-1-rppt@kernel.org
* fix hugetlb mmap tests to actually test file mappings
* increase maximal tests number in khugepaged
* add tags, thanks everyone!
v1: https://lore.kernel.org/all/20260406141735.2179309-1-rppt@kernel.org
Mike Rapoport (Microsoft) (55):
selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler
selftests/mm: migration: don't assume huge page is TWOMEG
selftests/mm: migration: make nthreads represent number of working threads
selftests/mm: migration: properly cleanup fork()ed processes
selftests/mm: run_vmtests.sh: don't gate THP and KSM tests on HAVE_HUGEPAGES
selftests/mm: merge map_hugetlb into hugepage-mmap
selftests/mm: rename hugepage-* tests to hugetlb-*
selftests/mm: hugetlb-shm: use kselftest framework
selftests/mm: hugetlb-vmemmap: use kselftest framework
selftests/mm: hugetlb-madvise: use kselftest framework
selftests/mm: hugetlb_madv_vs_map: use kselftest framework
selftests/mm: hugetlb-read-hwpoison: use kselftest framework
selftests/mm: khugepaged: group tests in an array
selftests/mm: khugepaged: use ksefltest framework
selftests/mm: ksm_tests: use kselftest framework
selftests/mm: protection_keys: use descriptive test names in the output
selftests/mm: protection_keys: use kselftest framework
selftests/mm: uffd-common: use kselftest framework
selftests/mm: uffd-stress: use kselftest framework
selftests/mm: uffd-unit-tests: use kselftest framework
selftests/mm: va_high_addr_switch: use kselftest framework
selftests/mm: add atexit() and signal handlers to thp_settings
selftests/mm: rename thp_settings.[ch] to hugepage_settings.[ch]
selftests/mm: move HugeTLB helpers to hugepage_settings
selftests/mm: hugepage_settings: use unsigned long in detect_hugetlb_page_size
selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages
selftests/mm: hugepage_settings: rename and rework get_free_hugepages()
selftests/mm: hugepage_settings: add APIs for HugeTLB setup and teardown
selftests/mm: move read_file(), read_num() and write_num() to vm_util
selftests/mm: vm_util: add helpers to set and restore shm limits
selftests/mm: compaction_test: use HugeTLB helpers ...
selftests/mm: cow: add setup of HugeTLB pages
selftests/mm: gup_longterm: add setup of HugeTLB pages
selftests/mm: gup_test: add setup of HugeTLB pages
selftests/mm: hmm-tests: add setup of HugeTLB pages
selftests/mm: hugepage_dio: add setup of HugeTLB pages
selftests/mm: hugetlb_fault_after_madv: add setup of HugeTLB pages
selftests/mm: hugetlb-madvise: add setup of HugeTLB pages
selftests/mm: hugetlb_madv_vs_map: add setup of HugeTLB pages
selftests/mm: hugetlb-mmap: add setup of HugeTLB pages
selftests/mm: hugetlb-mremap: add setup of HugeTLB pages
selftests/mm: hugetlb-shm: add setup of HugeTLB pages
selftests/mm: hugetlb-soft-offline: add setup of HugeTLB pages
selftests/mm: hugetlb-vmemmap: add setup of HugeTLB pages
selftests/mm: migration: add setup of HugeTLB pages
selftests/mm: pagemap_ioctl: add setup of HugeTLB pages
selftests/mm: protection_keys: use library code for HugeTLB setup
selftests/mm: thuge-gen: add setup of HugeTLB pages
selftests/mm: uffd-stress: use hugetlb_save and alloc huge pages
selftests/mm: uffd-unit-tests: add setup of HugeTLB pages
selftests/mm: uffd-wp-mremap: add setup of HugeTLB pages
selftests/mm: va_high_addr_switch: add setup of HugeTLB pages
selftests/mm: va_high_addr_switch.sh: drop huge pages setup
selftests/mm: run_vmtests.sh: free memory if available memory is low
selftests/mm: run_vmtests.sh: drop detection and setup of HugeTLB
Documentation/admin-guide/mm/hugetlbpage.rst | 15 +-
tools/testing/selftests/mm/.gitignore | 4 +
tools/testing/selftests/mm/Makefile | 13 +-
tools/testing/selftests/mm/compaction_test.c | 115 +-----
tools/testing/selftests/mm/cow.c | 31 +-
.../selftests/mm/folio_split_race_test.c | 25 +-
tools/testing/selftests/mm/guard-regions.c | 2 +-
tools/testing/selftests/mm/gup_longterm.c | 5 +-
tools/testing/selftests/mm/gup_test.c | 15 +
tools/testing/selftests/mm/hmm-tests.c | 24 +-
tools/testing/selftests/mm/hugepage-mmap.c | 78 ----
.../{thp_settings.c => hugepage_settings.c} | 316 +++++++++++++--
.../{thp_settings.h => hugepage_settings.h} | 82 +++-
tools/testing/selftests/mm/hugetlb-madvise.c | 215 ++++------
tools/testing/selftests/mm/hugetlb-mmap.c | 143 +++++++
.../{hugepage-mremap.c => hugetlb-mremap.c} | 15 +-
.../selftests/mm/hugetlb-read-hwpoison.c | 121 +++---
.../mm/{hugepage-shm.c => hugetlb-shm.c} | 69 ++--
.../selftests/mm/hugetlb-soft-offline.c | 45 +--
.../{hugepage-vmemmap.c => hugetlb-vmemmap.c} | 46 +--
tools/testing/selftests/mm/hugetlb_dio.c | 15 +-
.../selftests/mm/hugetlb_fault_after_madv.c | 9 +-
.../selftests/mm/hugetlb_madv_vs_map.c | 22 +-
tools/testing/selftests/mm/khugepaged.c | 380 ++++++++----------
tools/testing/selftests/mm/ksm_tests.c | 182 ++++-----
tools/testing/selftests/mm/map_hugetlb.c | 88 ----
tools/testing/selftests/mm/migration.c | 147 ++++---
tools/testing/selftests/mm/pagemap_ioctl.c | 13 +-
tools/testing/selftests/mm/pkey-helpers.h | 15 +-
.../testing/selftests/mm/prctl_thp_disable.c | 2 +-
tools/testing/selftests/mm/protection_keys.c | 130 +++---
tools/testing/selftests/mm/run_vmtests.sh | 174 ++------
tools/testing/selftests/mm/soft-dirty.c | 2 +-
.../selftests/mm/split_huge_page_test.c | 2 +-
tools/testing/selftests/mm/thuge-gen.c | 96 +----
tools/testing/selftests/mm/transhuge-stress.c | 2 +-
tools/testing/selftests/mm/uffd-common.h | 18 +-
tools/testing/selftests/mm/uffd-stress.c | 43 +-
tools/testing/selftests/mm/uffd-unit-tests.c | 138 ++++---
tools/testing/selftests/mm/uffd-wp-mremap.c | 20 +-
.../selftests/mm/va_high_addr_switch.c | 42 +-
.../selftests/mm/va_high_addr_switch.sh | 41 +-
tools/testing/selftests/mm/vm_util.c | 134 +++---
tools/testing/selftests/mm/vm_util.h | 15 +-
44 files changed, 1500 insertions(+), 1609 deletions(-)
delete mode 100644 tools/testing/selftests/mm/hugepage-mmap.c
rename tools/testing/selftests/mm/{thp_settings.c => hugepage_settings.c} (58%)
rename tools/testing/selftests/mm/{thp_settings.h => hugepage_settings.h} (51%)
create mode 100644 tools/testing/selftests/mm/hugetlb-mmap.c
rename tools/testing/selftests/mm/{hugepage-mremap.c => hugetlb-mremap.c} (92%)
rename tools/testing/selftests/mm/{hugepage-shm.c => hugetlb-shm.c} (55%)
rename tools/testing/selftests/mm/{hugepage-vmemmap.c => hugetlb-vmemmap.c} (76%)
delete mode 100644 tools/testing/selftests/mm/map_hugetlb.c
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
--
2.53.0
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v4 01/55] selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 02/55] selftests/mm: migration: don't assume huge page is TWOMEG Mike Rapoport
` (54 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Injection of a memory error with madvise() causes SIGBUS, which terminates
the hugetlb-read-hwpoison test prematurely.
Add a dummy SIGBUS handler to allow the test to continue regardless of
SIGBUS.
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Li Wang <li.wang@linux.dev>
Reviewed-by: Li Wang <li.wang@linux.dev>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-read-hwpoison.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tools/testing/selftests/mm/hugetlb-read-hwpoison.c b/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
index 46230462ad48..ad3198b444ce 100644
--- a/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
+++ b/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
@@ -10,6 +10,7 @@
#include <sys/statfs.h>
#include <errno.h>
#include <stdbool.h>
+#include <signal.h>
#include "kselftest.h"
@@ -261,6 +262,10 @@ static int create_hugetlbfs_file(struct statfs *file_stat)
return -1;
}
+static void sigbus_handler(int sig)
+{
+}
+
int main(void)
{
int fd;
@@ -273,6 +278,7 @@ int main(void)
};
size_t i;
+ signal(SIGBUS, sigbus_handler);
for (i = 0; i < ARRAY_SIZE(wr_chunk_sizes); ++i) {
printf("Write/read chunk size=0x%lx\n",
wr_chunk_sizes[i]);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 02/55] selftests/mm: migration: don't assume huge page is TWOMEG
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 01/55] selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 03/55] selftests/mm: migration: make nthreads represent number of working threads Mike Rapoport
` (53 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
migration tests presume that both THP and HugeTLB huge pages are 2MB.
Add dynamic detection of huge page size with read_pmd_pagesize() for THP
and with default_huge_page_size() for HugeTLB.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/migration.c | 44 +++++++++++++++++++-------
1 file changed, 32 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index 60e78bbfc0e3..0f5a4ddac529 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -184,22 +184,27 @@ TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
*/
TEST_F_TIMEOUT(migration, private_anon_thp, 2*RUNTIME)
{
+ uint64_t pmdsize;
uint64_t *ptr;
int i;
if (!thp_is_enabled())
SKIP(return, "Transparent Hugepages not available");
+ pmdsize = read_pmd_pagesize();
+ if (!pmdsize)
+ SKIP(return, "Reading PMD pagesize failed");
+
if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
SKIP(return, "Not enough threads or NUMA nodes available");
- ptr = mmap(NULL, 2*TWOMEG, PROT_READ | PROT_WRITE,
+ ptr = mmap(NULL, 2 * pmdsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
- ptr = (uint64_t *) ALIGN((uintptr_t) ptr, TWOMEG);
- ASSERT_EQ(madvise(ptr, TWOMEG, MADV_HUGEPAGE), 0);
- memset(ptr, 0xde, TWOMEG);
+ ptr = (uint64_t *) ALIGN((uintptr_t) ptr, pmdsize);
+ ASSERT_EQ(madvise(ptr, pmdsize, MADV_HUGEPAGE), 0);
+ memset(ptr, 0xde, pmdsize);
for (i = 0; i < self->nthreads - 1; i++)
if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
perror("Couldn't create thread");
@@ -215,6 +220,7 @@ TEST_F_TIMEOUT(migration, private_anon_thp, 2*RUNTIME)
TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
{
+ uint64_t pmdsize;
pid_t pid;
uint64_t *ptr;
int i;
@@ -222,17 +228,21 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
if (!thp_is_enabled())
SKIP(return, "Transparent Hugepages not available");
+ pmdsize = read_pmd_pagesize();
+ if (!pmdsize)
+ SKIP(return, "Reading PMD pagesize failed");
+
if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
SKIP(return, "Not enough threads or NUMA nodes available");
- ptr = mmap(NULL, 2 * TWOMEG, PROT_READ | PROT_WRITE,
+ ptr = mmap(NULL, 2 * pmdsize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
- ptr = (uint64_t *) ALIGN((uintptr_t) ptr, TWOMEG);
- ASSERT_EQ(madvise(ptr, TWOMEG, MADV_HUGEPAGE), 0);
+ ptr = (uint64_t *) ALIGN((uintptr_t) ptr, pmdsize);
+ ASSERT_EQ(madvise(ptr, pmdsize, MADV_HUGEPAGE), 0);
- memset(ptr, 0xde, TWOMEG);
+ memset(ptr, 0xde, pmdsize);
for (i = 0; i < self->nthreads - 1; i++) {
pid = fork();
if (!pid) {
@@ -256,17 +266,22 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
*/
TEST_F_TIMEOUT(migration, private_anon_htlb, 2*RUNTIME)
{
+ unsigned long hugepage_size;
uint64_t *ptr;
int i;
if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
SKIP(return, "Not enough threads or NUMA nodes available");
- ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
+ hugepage_size = default_huge_page_size();
+ if (!hugepage_size)
+ SKIP(return, "Reading HugeTLB pagesize failed");
+
+ ptr = mmap(NULL, hugepage_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
- memset(ptr, 0xde, TWOMEG);
+ memset(ptr, 0xde, hugepage_size);
for (i = 0; i < self->nthreads - 1; i++)
if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
perror("Couldn't create thread");
@@ -281,6 +296,7 @@ TEST_F_TIMEOUT(migration, private_anon_htlb, 2*RUNTIME)
*/
TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
{
+ unsigned long hugepage_size;
pid_t pid;
uint64_t *ptr;
int i;
@@ -288,11 +304,15 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
SKIP(return, "Not enough threads or NUMA nodes available");
- ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
+ hugepage_size = default_huge_page_size();
+ if (!hugepage_size)
+ SKIP(return, "Reading HugeTLB pagesize failed");
+
+ ptr = mmap(NULL, hugepage_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
- memset(ptr, 0xde, TWOMEG);
+ memset(ptr, 0xde, hugepage_size);
for (i = 0; i < self->nthreads - 1; i++) {
pid = fork();
if (!pid) {
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 03/55] selftests/mm: migration: make nthreads represent number of working threads
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 01/55] selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 02/55] selftests/mm: migration: don't assume huge page is TWOMEG Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 04/55] selftests/mm: migration: properly cleanup fork()ed processes Mike Rapoport
` (52 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Fixture setup sets self->nthreads to number of available CPUs minus 1
and then each test creates 'self->nthreads - 1' threads or processes, so
essentially nthreads counts the worker tasks and the main task.
Make nthreads represent the number of spawned tasks to simplify
thread/process creation and teardown.
While on it, make the fixture setup skip the tests if there are not
enough CPUs or NUMA nodes instead of checking this in each test.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/migration.c | 47 +++++++++-----------------
1 file changed, 16 insertions(+), 31 deletions(-)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index 0f5a4ddac529..16ffd3c55ee0 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -38,7 +38,7 @@ FIXTURE_SETUP(migration)
if (numa_available() < 0)
SKIP(return, "NUMA not available");
- self->nthreads = numa_num_task_cpus() - 1;
+ self->nthreads = numa_num_task_cpus() - 2;
self->n1 = -1;
self->n2 = -1;
@@ -52,6 +52,9 @@ FIXTURE_SETUP(migration)
}
}
+ if (self->nthreads < 1 || self->n1 < 0 || self->n2 < 0)
+ SKIP(return, "Not enough threads or NUMA nodes available");
+
self->threads = malloc(self->nthreads * sizeof(*self->threads));
ASSERT_NE(self->threads, NULL);
self->pids = malloc(self->nthreads * sizeof(*self->pids));
@@ -127,20 +130,17 @@ TEST_F_TIMEOUT(migration, private_anon, 2*RUNTIME)
uint64_t *ptr;
int i;
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
memset(ptr, 0xde, TWOMEG);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
perror("Couldn't create thread");
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(pthread_cancel(self->threads[i]), 0);
}
@@ -153,15 +153,12 @@ TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
uint64_t *ptr;
int i;
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
memset(ptr, 0xde, TWOMEG);
- for (i = 0; i < self->nthreads - 1; i++) {
+ for (i = 0; i < self->nthreads; i++) {
pid = fork();
if (!pid) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
@@ -175,7 +172,7 @@ TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
}
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
}
@@ -195,9 +192,6 @@ TEST_F_TIMEOUT(migration, private_anon_thp, 2*RUNTIME)
if (!pmdsize)
SKIP(return, "Reading PMD pagesize failed");
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
ptr = mmap(NULL, 2 * pmdsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
@@ -205,12 +199,12 @@ TEST_F_TIMEOUT(migration, private_anon_thp, 2*RUNTIME)
ptr = (uint64_t *) ALIGN((uintptr_t) ptr, pmdsize);
ASSERT_EQ(madvise(ptr, pmdsize, MADV_HUGEPAGE), 0);
memset(ptr, 0xde, pmdsize);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
perror("Couldn't create thread");
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(pthread_cancel(self->threads[i]), 0);
}
@@ -232,9 +226,6 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
if (!pmdsize)
SKIP(return, "Reading PMD pagesize failed");
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
ptr = mmap(NULL, 2 * pmdsize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
@@ -243,7 +234,7 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
ASSERT_EQ(madvise(ptr, pmdsize, MADV_HUGEPAGE), 0);
memset(ptr, 0xde, pmdsize);
- for (i = 0; i < self->nthreads - 1; i++) {
+ for (i = 0; i < self->nthreads; i++) {
pid = fork();
if (!pid) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
@@ -257,7 +248,7 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
}
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
}
@@ -270,9 +261,6 @@ TEST_F_TIMEOUT(migration, private_anon_htlb, 2*RUNTIME)
uint64_t *ptr;
int i;
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
hugepage_size = default_huge_page_size();
if (!hugepage_size)
SKIP(return, "Reading HugeTLB pagesize failed");
@@ -282,12 +270,12 @@ TEST_F_TIMEOUT(migration, private_anon_htlb, 2*RUNTIME)
ASSERT_NE(ptr, MAP_FAILED);
memset(ptr, 0xde, hugepage_size);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
if (pthread_create(&self->threads[i], NULL, access_mem, ptr))
perror("Couldn't create thread");
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(pthread_cancel(self->threads[i]), 0);
}
@@ -301,9 +289,6 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
uint64_t *ptr;
int i;
- if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
- SKIP(return, "Not enough threads or NUMA nodes available");
-
hugepage_size = default_huge_page_size();
if (!hugepage_size)
SKIP(return, "Reading HugeTLB pagesize failed");
@@ -313,7 +298,7 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
ASSERT_NE(ptr, MAP_FAILED);
memset(ptr, 0xde, hugepage_size);
- for (i = 0; i < self->nthreads - 1; i++) {
+ for (i = 0; i < self->nthreads; i++) {
pid = fork();
if (!pid) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
@@ -327,7 +312,7 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
}
ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads - 1; i++)
+ for (i = 0; i < self->nthreads; i++)
ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 04/55] selftests/mm: migration: properly cleanup fork()ed processes
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (2 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 03/55] selftests/mm: migration: make nthreads represent number of working threads Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 05/55] selftests/mm: run_vmtests.sh: don't gate THP and KSM tests on HAVE_HUGEPAGES Mike Rapoport
` (51 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Several migration test use fork() to create worker processes. These
processes are later killed, but nothing collects their exit status and they
remain as zombies in the system.
Add a helper function that kills the worker processes, waitpid()s for
them and verifies the exit status.
Replace the loops that call kill() for each process with a call to that
helper.
Reported-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/migration.c | 47 +++++++++++++++++++-------
1 file changed, 35 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index 16ffd3c55ee0..e504829df6b6 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -67,6 +67,29 @@ FIXTURE_TEARDOWN(migration)
free(self->pids);
}
+static bool kill_children(FIXTURE_DATA(migration) * self)
+{
+ bool err = false;
+ pid_t pid;
+ int i;
+
+ for (i = 0; i < self->nthreads; i++) {
+ int status = 0;
+
+ pid = self->pids[i];
+ if (pid < 0)
+ continue;
+ if (kill(pid, SIGTERM))
+ err = true;
+ if (pid != waitpid(pid, &status, 0))
+ err = true;
+ if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGTERM)
+ err = true;
+ }
+
+ return !err;
+}
+
int migrate(uint64_t *ptr, int n1, int n2)
{
int ret, tmp;
@@ -151,7 +174,7 @@ TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
{
pid_t pid;
uint64_t *ptr;
- int i;
+ int i, err;
ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
@@ -171,9 +194,9 @@ TEST_F_TIMEOUT(migration, shared_anon, 2*RUNTIME)
}
}
- ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads; i++)
- ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
+ err = migrate(ptr, self->n1, self->n2);
+ ASSERT_EQ(kill_children(self), true);
+ ASSERT_EQ(err, 0);
}
/*
@@ -217,7 +240,7 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
uint64_t pmdsize;
pid_t pid;
uint64_t *ptr;
- int i;
+ int i, err;
if (!thp_is_enabled())
SKIP(return, "Transparent Hugepages not available");
@@ -247,9 +270,9 @@ TEST_F_TIMEOUT(migration, shared_anon_thp, 2*RUNTIME)
}
}
- ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads; i++)
- ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
+ err = migrate(ptr, self->n1, self->n2);
+ ASSERT_EQ(kill_children(self), true);
+ ASSERT_EQ(err, 0);
}
/*
@@ -287,7 +310,7 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
unsigned long hugepage_size;
pid_t pid;
uint64_t *ptr;
- int i;
+ int i, err;
hugepage_size = default_huge_page_size();
if (!hugepage_size)
@@ -311,9 +334,9 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
}
}
- ASSERT_EQ(migrate(ptr, self->n1, self->n2), 0);
- for (i = 0; i < self->nthreads; i++)
- ASSERT_EQ(kill(self->pids[i], SIGTERM), 0);
+ err = migrate(ptr, self->n1, self->n2);
+ ASSERT_EQ(kill_children(self), true);
+ ASSERT_EQ(err, 0);
}
TEST_HARNESS_MAIN
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 05/55] selftests/mm: run_vmtests.sh: don't gate THP and KSM tests on HAVE_HUGEPAGES
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (3 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 04/55] selftests/mm: migration: properly cleanup fork()ed processes Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 06/55] selftests/mm: merge map_hugetlb into hugepage-mmap Mike Rapoport
` (50 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
HAVE_HUGEPAGES indicates availability of free HugeTLB pages. It should not
be used to gate KSM test that merges transparent huge pages or
split_huge_page_test.
Remove check for HAVE_HUGEPAGES when running these tests.
Tested-by: Li Wang <li.wang@linux.dev>
Reviewed-by: Li Wang <li.wang@linux.dev>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/run_vmtests.sh | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index d8468451b3a3..e2dc9ac87bfc 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -436,9 +436,7 @@ CATEGORY="memfd_secret" run_test ./memfd_secret
fi
# KSM KSM_MERGE_TIME_HUGE_PAGES test with size of 100
-if [ "${HAVE_HUGEPAGES}" = "1" ]; then
- CATEGORY="ksm" run_test ./ksm_tests -H -s 100
-fi
+CATEGORY="ksm" run_test ./ksm_tests -H -s 100
# KSM KSM_MERGE_TIME test with size of 100
CATEGORY="ksm" run_test ./ksm_tests -P -s 100
# KSM MADV_MERGEABLE test with 10 identical pages
@@ -493,16 +491,14 @@ CATEGORY="thp" run_test ./transhuge-stress -d 20
# Try to create XFS if not provided
if [ -z "${SPLIT_HUGE_PAGE_TEST_XFS_PATH}" ]; then
- if [ "${HAVE_HUGEPAGES}" = "1" ]; then
- if test_selected "thp"; then
- if grep xfs /proc/filesystems &>/dev/null; then
- XFS_IMG=$(mktemp /tmp/xfs_img_XXXXXX)
- SPLIT_HUGE_PAGE_TEST_XFS_PATH=$(mktemp -d /tmp/xfs_dir_XXXXXX)
- truncate -s 314572800 ${XFS_IMG}
- mkfs.xfs -q ${XFS_IMG}
- mount -o loop ${XFS_IMG} ${SPLIT_HUGE_PAGE_TEST_XFS_PATH}
- MOUNTED_XFS=1
- fi
+ if test_selected "thp"; then
+ if grep xfs /proc/filesystems &>/dev/null; then
+ XFS_IMG=$(mktemp /tmp/xfs_img_XXXXXX)
+ SPLIT_HUGE_PAGE_TEST_XFS_PATH=$(mktemp -d /tmp/xfs_dir_XXXXXX)
+ truncate -s 314572800 ${XFS_IMG}
+ mkfs.xfs -q ${XFS_IMG}
+ mount -o loop ${XFS_IMG} ${SPLIT_HUGE_PAGE_TEST_XFS_PATH}
+ MOUNTED_XFS=1
fi
fi
fi
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 06/55] selftests/mm: merge map_hugetlb into hugepage-mmap
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (4 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 05/55] selftests/mm: run_vmtests.sh: don't gate THP and KSM tests on HAVE_HUGEPAGES Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 07/55] selftests/mm: rename hugepage-* tests to hugetlb-* Mike Rapoport
` (49 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Both tests create a hugettlb mapping, fill it with data and verify the
data, the only difference is that one uses file-backed memory and another
one uses anonymous memory.
Merge both tests into a single file.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 7 +-
tools/testing/selftests/mm/Makefile | 1 -
tools/testing/selftests/mm/hugepage-mmap.c | 107 ++++++++++++++-----
tools/testing/selftests/mm/map_hugetlb.c | 88 ---------------
tools/testing/selftests/mm/run_vmtests.sh | 1 -
5 files changed, 84 insertions(+), 120 deletions(-)
delete mode 100644 tools/testing/selftests/mm/map_hugetlb.c
diff --git a/Documentation/admin-guide/mm/hugetlbpage.rst b/Documentation/admin-guide/mm/hugetlbpage.rst
index 67a941903fd2..2dea8c636641 100644
--- a/Documentation/admin-guide/mm/hugetlbpage.rst
+++ b/Documentation/admin-guide/mm/hugetlbpage.rst
@@ -455,7 +455,7 @@ used to change the file attributes on hugetlbfs.
Also, it is important to note that no such mount command is required if
applications are going to use only shmat/shmget system calls or mmap with
MAP_HUGETLB. For an example of how to use mmap with MAP_HUGETLB see
-:ref:`map_hugetlb <map_hugetlb>` below.
+:ref:`examples <examples>` below.
Users who wish to use hugetlb memory via shared memory segment should be
members of a supplementary group and system admin needs to configure that gid
@@ -473,10 +473,7 @@ a hugetlb page and the length is smaller than the hugepage size.
Examples
========
-.. _map_hugetlb:
-
-``map_hugetlb``
- see tools/testing/selftests/mm/map_hugetlb.c
+.. _examples:
``hugepage-shm``
see tools/testing/selftests/mm/hugepage-shm.c
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index cd24596cdd27..cbda989f6b6a 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -70,7 +70,6 @@ TEST_GEN_FILES += hugepage-vmemmap
TEST_GEN_FILES += khugepaged
TEST_GEN_FILES += madv_populate
TEST_GEN_FILES += map_fixed_noreplace
-TEST_GEN_FILES += map_hugetlb
TEST_GEN_FILES += map_populate
ifneq (,$(filter $(ARCH),arm64 riscv riscv64 x86 x86_64 loongarch32 loongarch64))
TEST_GEN_FILES += memfd_secret
diff --git a/tools/testing/selftests/mm/hugepage-mmap.c b/tools/testing/selftests/mm/hugepage-mmap.c
index d543419de040..66cf74b73dea 100644
--- a/tools/testing/selftests/mm/hugepage-mmap.c
+++ b/tools/testing/selftests/mm/hugepage-mmap.c
@@ -15,6 +15,8 @@
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
+#include <linux/memfd.h>
+#include "vm_util.h"
#include "kselftest.h"
#define LENGTH (256UL*1024*1024)
@@ -25,54 +27,109 @@ static void check_bytes(char *addr)
ksft_print_msg("First hex is %x\n", *((unsigned int *)addr));
}
-static void write_bytes(char *addr)
+static void write_bytes(char *addr, size_t length)
{
unsigned long i;
- for (i = 0; i < LENGTH; i++)
+ for (i = 0; i < length; i++)
*(addr + i) = (char)i;
}
-static int read_bytes(char *addr)
+static bool verify_bytes(char *addr, size_t length)
{
unsigned long i;
check_bytes(addr);
- for (i = 0; i < LENGTH; i++)
+ for (i = 0; i < length; i++)
if (*(addr + i) != (char)i) {
- ksft_print_msg("Error: Mismatch at %lu\n", i);
- return 1;
+ ksft_print_msg("Error: Mismatch at %lu(%p)\n", i, addr);
+ return false;
}
- return 0;
+
+ return true;
}
-int main(void)
+static void test_mmap(size_t length, int mmap_flags, int fd,
+ const char *test_name)
{
+ bool passed = true;
void *addr;
- int fd, ret;
- ksft_print_header();
- ksft_set_plan(1);
+ addr = mmap(NULL, length, PROTECTION, mmap_flags, fd, 0);
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
+
+ ksft_print_msg("Returned address is %p\n", addr);
+ check_bytes(addr);
+ write_bytes(addr, length);
+ if (!verify_bytes(addr, length))
+ passed = false;
+
+ /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
+ if (munmap(addr, length))
+ ksft_exit_fail_perror("munmap");
+
+ ksft_test_result(passed, "%s\n", test_name);
+}
+
+static void test_anon_mmap(size_t length, int shift)
+{
+ const char *test_name = "hugetlb anonymous mmap";
+ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB;
+
+ if (shift)
+ mmap_flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
- fd = memfd_create("hugepage-mmap", MFD_HUGETLB);
+ test_mmap(length, mmap_flags, -1, test_name);
+}
+
+static void test_file_mmap(size_t length, int shift)
+{
+ const char *test_name = "hugetlb file mmap";
+ int mfd_flags = MFD_HUGETLB;
+ int fd;
+
+ if (shift)
+ mfd_flags |= (shift & MFD_HUGE_MASK) << MFD_HUGE_SHIFT;
+
+ fd = memfd_create("hugetlb-mmap", mfd_flags);
if (fd < 0)
- ksft_exit_fail_msg("memfd_create() failed: %s\n", strerror(errno));
+ ksft_exit_fail_perror("memfd_create");
+
+ test_mmap(length, MAP_SHARED, fd, test_name);
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ size_t hugepage_size;
+ size_t length = LENGTH;
+ int shift = 0;
- addr = mmap(NULL, LENGTH, PROTECTION, MAP_SHARED, fd, 0);
- if (addr == MAP_FAILED) {
- close(fd);
- ksft_exit_fail_msg("mmap(): %s\n", strerror(errno));
+ ksft_print_header();
+ ksft_set_plan(2);
+
+ if (argc > 1)
+ length = atol(argv[1]) << 20;
+ if (argc > 2)
+ shift = atoi(argv[2]);
+
+ if (shift) {
+ hugepage_size = (1UL << shift);
+ ksft_print_msg("%lu kB hugepages\n", 1UL << (shift - 10));
+ } else {
+ hugepage_size = default_huge_page_size();
+ ksft_print_msg("Default size hugepages (%lu kB)\n", hugepage_size >> 10);
}
- ksft_print_msg("Returned address is %p\n", addr);
- check_bytes(addr);
- write_bytes(addr);
- ret = read_bytes(addr);
+ /* munmap will fail if the length is not page aligned */
+ if (hugepage_size > length)
+ length = hugepage_size;
- munmap(addr, LENGTH);
- close(fd);
+ ksft_print_msg("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
- ksft_test_result(!ret, "Read same data\n");
+ test_anon_mmap(length, shift);
+ test_file_mmap(length, shift);
- ksft_exit(!ret);
+ ksft_finished();
}
diff --git a/tools/testing/selftests/mm/map_hugetlb.c b/tools/testing/selftests/mm/map_hugetlb.c
deleted file mode 100644
index aa409107611b..000000000000
--- a/tools/testing/selftests/mm/map_hugetlb.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Example of using hugepage memory in a user application using the mmap
- * system call with MAP_HUGETLB flag. Before running this program make
- * sure the administrator has allocated enough default sized huge pages
- * to cover the 256 MB allocation.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include "vm_util.h"
-#include "kselftest.h"
-
-#define LENGTH (256UL*1024*1024)
-#define PROTECTION (PROT_READ | PROT_WRITE)
-
-static void check_bytes(char *addr)
-{
- ksft_print_msg("First hex is %x\n", *((unsigned int *)addr));
-}
-
-static void write_bytes(char *addr, size_t length)
-{
- unsigned long i;
-
- for (i = 0; i < length; i++)
- *(addr + i) = (char)i;
-}
-
-static void read_bytes(char *addr, size_t length)
-{
- unsigned long i;
-
- check_bytes(addr);
- for (i = 0; i < length; i++)
- if (*(addr + i) != (char)i)
- ksft_exit_fail_msg("Mismatch at %lu\n", i);
-
- ksft_test_result_pass("Read correct data\n");
-}
-
-int main(int argc, char **argv)
-{
- void *addr;
- size_t hugepage_size;
- size_t length = LENGTH;
- int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB;
- int shift = 0;
-
- hugepage_size = default_huge_page_size();
- /* munmap with fail if the length is not page aligned */
- if (hugepage_size > length)
- length = hugepage_size;
-
- ksft_print_header();
- ksft_set_plan(1);
-
- if (argc > 1)
- length = atol(argv[1]) << 20;
- if (argc > 2) {
- shift = atoi(argv[2]);
- if (shift)
- flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
- }
-
- if (shift)
- ksft_print_msg("%u kB hugepages\n", 1 << (shift - 10));
- else
- ksft_print_msg("Default size hugepages\n");
- ksft_print_msg("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
-
- addr = mmap(NULL, length, PROTECTION, flags, -1, 0);
- if (addr == MAP_FAILED)
- ksft_exit_fail_msg("mmap: %s\n", strerror(errno));
-
- ksft_print_msg("Returned address is %p\n", addr);
- check_bytes(addr);
- write_bytes(addr, length);
- read_bytes(addr, length);
-
- /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
- if (munmap(addr, length))
- ksft_exit_fail_msg("munmap: %s\n", strerror(errno));
-
- ksft_finished();
-}
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index e2dc9ac87bfc..61b450032af8 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -292,7 +292,6 @@ CATEGORY="hugetlb" run_test ./hugepage-shm
echo "$shmmax" > /proc/sys/kernel/shmmax
echo "$shmall" > /proc/sys/kernel/shmall
-CATEGORY="hugetlb" run_test ./map_hugetlb
CATEGORY="hugetlb" run_test ./hugepage-mremap
CATEGORY="hugetlb" run_test ./hugepage-vmemmap
CATEGORY="hugetlb" run_test ./hugetlb-madvise
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 07/55] selftests/mm: rename hugepage-* tests to hugetlb-*
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (5 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 06/55] selftests/mm: merge map_hugetlb into hugepage-mmap Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 08/55] selftests/mm: hugetlb-shm: use kselftest framework Mike Rapoport
` (48 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugepage could mean both THP and HugeTLB these days.
Rename hugepage-* tests for HugeTLB to hugetlb-* to avoid confusion.
Make sure that Makefile update keeps alphabetical ordering of the
TEST_GEN_FILES entries.
Keep old binary names in .gitignore because Linus prefers it this way.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Li Wang <li.wang@linux.dev>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 8 ++++----
tools/testing/selftests/mm/.gitignore | 4 ++++
tools/testing/selftests/mm/Makefile | 8 ++++----
tools/testing/selftests/mm/hugetlb-madvise.c | 2 +-
.../selftests/mm/{hugepage-mmap.c => hugetlb-mmap.c} | 2 +-
.../selftests/mm/{hugepage-mremap.c => hugetlb-mremap.c} | 2 +-
.../selftests/mm/{hugepage-shm.c => hugetlb-shm.c} | 2 +-
.../mm/{hugepage-vmemmap.c => hugetlb-vmemmap.c} | 0
tools/testing/selftests/mm/run_vmtests.sh | 8 ++++----
9 files changed, 20 insertions(+), 16 deletions(-)
rename tools/testing/selftests/mm/{hugepage-mmap.c => hugetlb-mmap.c} (99%)
rename tools/testing/selftests/mm/{hugepage-mremap.c => hugetlb-mremap.c} (99%)
rename tools/testing/selftests/mm/{hugepage-shm.c => hugetlb-shm.c} (99%)
rename tools/testing/selftests/mm/{hugepage-vmemmap.c => hugetlb-vmemmap.c} (100%)
diff --git a/Documentation/admin-guide/mm/hugetlbpage.rst b/Documentation/admin-guide/mm/hugetlbpage.rst
index 2dea8c636641..3cc15d800be1 100644
--- a/Documentation/admin-guide/mm/hugetlbpage.rst
+++ b/Documentation/admin-guide/mm/hugetlbpage.rst
@@ -475,11 +475,11 @@ Examples
.. _examples:
-``hugepage-shm``
- see tools/testing/selftests/mm/hugepage-shm.c
+``hugetlb-shm``
+ see tools/testing/selftests/mm/hugetlb-shm.c
-``hugepage-mmap``
- see tools/testing/selftests/mm/hugepage-mmap.c
+``hugetlb-mmap``
+ see tools/testing/selftests/mm/hugetlb-mmap.c
The `libhugetlbfs`_ library provides a wide range of userspace tools
to help with huge page usability, environment setup, and control.
diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore
index b0c30c5ee9e3..9ccd9e1447e6 100644
--- a/tools/testing/selftests/mm/.gitignore
+++ b/tools/testing/selftests/mm/.gitignore
@@ -4,6 +4,10 @@ hugepage-mmap
hugepage-mremap
hugepage-shm
hugepage-vmemmap
+hugetlb-mmap
+hugetlb-mremap
+hugetlb-shm
+hugetlb-vmemmap
hugetlb-madvise
hugetlb-read-hwpoison
hugetlb-soft-offline
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index cbda989f6b6a..d9ecfb02e05c 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -61,12 +61,12 @@ TEST_GEN_FILES += gup_longterm
TEST_GEN_FILES += gup_test
TEST_GEN_FILES += hmm-tests
TEST_GEN_FILES += hugetlb-madvise
+TEST_GEN_FILES += hugetlb-mmap
+TEST_GEN_FILES += hugetlb-mremap
TEST_GEN_FILES += hugetlb-read-hwpoison
+TEST_GEN_FILES += hugetlb-shm
TEST_GEN_FILES += hugetlb-soft-offline
-TEST_GEN_FILES += hugepage-mmap
-TEST_GEN_FILES += hugepage-mremap
-TEST_GEN_FILES += hugepage-shm
-TEST_GEN_FILES += hugepage-vmemmap
+TEST_GEN_FILES += hugetlb-vmemmap
TEST_GEN_FILES += khugepaged
TEST_GEN_FILES += madv_populate
TEST_GEN_FILES += map_fixed_noreplace
diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
index 5b12041fa310..898cc90b314f 100644
--- a/tools/testing/selftests/mm/hugetlb-madvise.c
+++ b/tools/testing/selftests/mm/hugetlb-madvise.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * hugepage-madvise:
+ * hugetlb-madvise:
*
* Basic functional testing of madvise MADV_DONTNEED and MADV_REMOVE
* on hugetlb mappings.
diff --git a/tools/testing/selftests/mm/hugepage-mmap.c b/tools/testing/selftests/mm/hugetlb-mmap.c
similarity index 99%
rename from tools/testing/selftests/mm/hugepage-mmap.c
rename to tools/testing/selftests/mm/hugetlb-mmap.c
index 66cf74b73dea..a327d90d7a79 100644
--- a/tools/testing/selftests/mm/hugepage-mmap.c
+++ b/tools/testing/selftests/mm/hugetlb-mmap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * hugepage-mmap:
+ * hugetlb-mmap:
*
* Example of using huge page memory in a user application using the mmap
* system call. Before running this application, make sure that the
diff --git a/tools/testing/selftests/mm/hugepage-mremap.c b/tools/testing/selftests/mm/hugetlb-mremap.c
similarity index 99%
rename from tools/testing/selftests/mm/hugepage-mremap.c
rename to tools/testing/selftests/mm/hugetlb-mremap.c
index b8f7d92e5a35..1c87c39780c5 100644
--- a/tools/testing/selftests/mm/hugepage-mremap.c
+++ b/tools/testing/selftests/mm/hugetlb-mremap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * hugepage-mremap:
+ * hugetlb-mremap:
*
* Example of remapping huge page memory in a user application using the
* mremap system call. The path to a file in a hugetlbfs filesystem must
diff --git a/tools/testing/selftests/mm/hugepage-shm.c b/tools/testing/selftests/mm/hugetlb-shm.c
similarity index 99%
rename from tools/testing/selftests/mm/hugepage-shm.c
rename to tools/testing/selftests/mm/hugetlb-shm.c
index ef06260802b5..de8f5d523084 100644
--- a/tools/testing/selftests/mm/hugepage-shm.c
+++ b/tools/testing/selftests/mm/hugetlb-shm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * hugepage-shm:
+ * hugetlb-shm:
*
* Example of using huge page memory in a user application using Sys V shared
* memory system calls. In this example the app is requesting 256MB of
diff --git a/tools/testing/selftests/mm/hugepage-vmemmap.c b/tools/testing/selftests/mm/hugetlb-vmemmap.c
similarity index 100%
rename from tools/testing/selftests/mm/hugepage-vmemmap.c
rename to tools/testing/selftests/mm/hugetlb-vmemmap.c
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index 61b450032af8..b9e520194634 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -282,18 +282,18 @@ run_test() {
echo "TAP version 13" | tap_output
-CATEGORY="hugetlb" run_test ./hugepage-mmap
+CATEGORY="hugetlb" run_test ./hugetlb-mmap
shmmax=$(cat /proc/sys/kernel/shmmax)
shmall=$(cat /proc/sys/kernel/shmall)
echo 268435456 > /proc/sys/kernel/shmmax
echo 4194304 > /proc/sys/kernel/shmall
-CATEGORY="hugetlb" run_test ./hugepage-shm
+CATEGORY="hugetlb" run_test ./hugetlb-shm
echo "$shmmax" > /proc/sys/kernel/shmmax
echo "$shmall" > /proc/sys/kernel/shmall
-CATEGORY="hugetlb" run_test ./hugepage-mremap
-CATEGORY="hugetlb" run_test ./hugepage-vmemmap
+CATEGORY="hugetlb" run_test ./hugetlb-mremap
+CATEGORY="hugetlb" run_test ./hugetlb-vmemmap
CATEGORY="hugetlb" run_test ./hugetlb-madvise
CATEGORY="hugetlb" run_test ./hugetlb_dio
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 08/55] selftests/mm: hugetlb-shm: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (6 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 07/55] selftests/mm: rename hugepage-* tests to hugetlb-* Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 09/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
` (47 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert hugetlb-shm test to use kselftest framework for reporting and
tracking successful and failing runs.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-shm.c | 47 +++++++++++-------------
1 file changed, 22 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-shm.c b/tools/testing/selftests/mm/hugetlb-shm.c
index de8f5d523084..c2c7aee85b96 100644
--- a/tools/testing/selftests/mm/hugetlb-shm.c
+++ b/tools/testing/selftests/mm/hugetlb-shm.c
@@ -28,9 +28,9 @@
#include <sys/shm.h>
#include <sys/mman.h>
-#define LENGTH (256UL*1024*1024)
+#include "vm_util.h"
-#define dprintf(x) printf(x)
+#define LENGTH (256UL*1024*1024)
int main(void)
{
@@ -38,44 +38,41 @@ int main(void)
unsigned long i;
char *shmaddr;
+ ksft_print_header();
+ ksft_set_plan(1);
+
shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
- if (shmid < 0) {
- perror("shmget");
- exit(1);
- }
- printf("shmid: 0x%x\n", shmid);
+ if (shmid < 0)
+ ksft_exit_fail_perror("shmget");
+
+ ksft_print_msg("shmid: 0x%x\n", shmid);
shmaddr = shmat(shmid, NULL, 0);
if (shmaddr == (char *)-1) {
- perror("Shared memory attach failure");
+ ksft_perror("Shared memory attach failure");
shmctl(shmid, IPC_RMID, NULL);
- exit(2);
+ ksft_exit_fail();
}
- printf("shmaddr: %p\n", shmaddr);
+ ksft_print_msg("shmaddr: %p\n", shmaddr);
- dprintf("Starting the writes:\n");
- for (i = 0; i < LENGTH; i++) {
+ ksft_print_msg("Starting the writes:\n");
+ for (i = 0; i < LENGTH; i++)
shmaddr[i] = (char)(i);
- if (!(i % (1024 * 1024)))
- dprintf(".");
- }
- dprintf("\n");
- dprintf("Starting the Check...");
+ ksft_print_msg("Starting the Check...");
for (i = 0; i < LENGTH; i++)
- if (shmaddr[i] != (char)i) {
- printf("\nIndex %lu mismatched\n", i);
- exit(3);
- }
- dprintf("Done.\n");
+ if (shmaddr[i] != (char)i)
+ ksft_exit_fail_msg("Data mismatch at index %lu\n", i);
+ ksft_print_msg("Done.\n");
if (shmdt((const void *)shmaddr) != 0) {
- perror("Detach failure");
+ ksft_perror("Detach failure");
shmctl(shmid, IPC_RMID, NULL);
- exit(4);
+ ksft_exit_fail();
}
shmctl(shmid, IPC_RMID, NULL);
- return 0;
+ ksft_test_result_pass("hugepage using SysV shmget/shmat\n");
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 09/55] selftests/mm: hugetlb-vmemmap: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (7 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 08/55] selftests/mm: hugetlb-shm: use kselftest framework Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 10/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
` (46 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert hugetlb-vmemmap test to use kselftest framework for reporting
and tracking successful and failing runs.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-vmemmap.c | 42 +++++++++-----------
1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-vmemmap.c b/tools/testing/selftests/mm/hugetlb-vmemmap.c
index df366a4d1b92..485a6978b40f 100644
--- a/tools/testing/selftests/mm/hugetlb-vmemmap.c
+++ b/tools/testing/selftests/mm/hugetlb-vmemmap.c
@@ -63,7 +63,7 @@ static int check_page_flags(unsigned long pfn)
read(fd, &pageflags, sizeof(pageflags));
if ((pageflags & HEAD_PAGE_FLAGS) != HEAD_PAGE_FLAGS) {
close(fd);
- printf("Head page flags (%lx) is invalid\n", pageflags);
+ ksft_print_msg("Head page flags (%lx) is invalid\n", pageflags);
return -1;
}
@@ -77,7 +77,7 @@ static int check_page_flags(unsigned long pfn)
if ((pageflags & TAIL_PAGE_FLAGS) != TAIL_PAGE_FLAGS ||
(pageflags & HEAD_PAGE_FLAGS) == HEAD_PAGE_FLAGS) {
close(fd);
- printf("Tail page flags (%lx) is invalid\n", pageflags);
+ ksft_print_msg("Tail page flags (%lx) is invalid\n", pageflags);
return -1;
}
}
@@ -91,44 +91,38 @@ int main(int argc, char **argv)
{
void *addr;
unsigned long pfn;
+ int ret;
+
+ ksft_print_header();
+ ksft_set_plan(1);
pagesize = psize();
maplength = default_huge_page_size();
- if (!maplength) {
- printf("Unable to determine huge page size\n");
- exit(1);
- }
+ if (!maplength)
+ ksft_exit_skip("Unable to determine huge page size\n");
addr = mmap(NULL, maplength, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
/* Trigger allocation of HugeTLB page. */
write_bytes(addr, maplength);
pfn = virt_to_pfn(addr);
if (pfn == -1UL) {
+ ksft_perror("virt_to_pfn");
munmap(addr, maplength);
- perror("virt_to_pfn");
- exit(1);
+ ksft_exit_fail();
}
- printf("Returned address is %p whose pfn is %lx\n", addr, pfn);
+ ksft_print_msg("Returned address is %p whose pfn is %lx\n", addr, pfn);
- if (check_page_flags(pfn) < 0) {
- munmap(addr, maplength);
- perror("check_page_flags");
- exit(1);
- }
+ ret = check_page_flags(pfn);
- /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
- if (munmap(addr, maplength)) {
- perror("munmap");
- exit(1);
- }
+ if (munmap(addr, maplength))
+ ksft_exit_fail_perror("munmap");
- return 0;
+ ksft_test_result(!ret, "HugeTLB vmemmap page flags\n");
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 10/55] selftests/mm: hugetlb-madvise: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (8 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 09/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 11/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
` (45 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert hugetlb-madvise test to use kselftest framework for reporting
and tracking successful and failing runs.
While on it fix the check for base page size detection to actually use
base_page_size.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-madvise.c | 204 ++++++++-----------
1 file changed, 82 insertions(+), 122 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
index 898cc90b314f..e7dd8d06d986 100644
--- a/tools/testing/selftests/mm/hugetlb-madvise.c
+++ b/tools/testing/selftests/mm/hugetlb-madvise.c
@@ -26,12 +26,11 @@
#define validate_free_pages(exp_free) \
do { \
- int fhp = get_free_hugepages(); \
- if (fhp != (exp_free)) { \
- printf("Unexpected number of free huge " \
- "pages line %d\n", __LINE__); \
- exit(1); \
- } \
+ unsigned long fhp = get_free_hugepages(); \
+ if (fhp != (exp_free)) \
+ ksft_exit_fail_msg("Unexpected number of free " \
+ "huge pages %lu, expected %lu line %d\n", \
+ fhp, (exp_free), __LINE__); \
} while (0)
unsigned long huge_page_size;
@@ -57,28 +56,24 @@ int main(int argc, char **argv)
int fd;
int ret;
+ ksft_print_header();
+ ksft_set_plan(1);
+
huge_page_size = default_huge_page_size();
- if (!huge_page_size) {
- printf("Unable to determine huge page size, exiting!\n");
- exit(1);
- }
+ if (!huge_page_size)
+ ksft_exit_skip("Unable to determine huge page size\n");
+
base_page_size = sysconf(_SC_PAGE_SIZE);
- if (!huge_page_size) {
- printf("Unable to determine base page size, exiting!\n");
- exit(1);
- }
+ if (!base_page_size)
+ ksft_exit_fail_msg("Unable to determine base page size\n");
free_hugepages = get_free_hugepages();
- if (free_hugepages < MIN_FREE_PAGES) {
- printf("Not enough free huge pages to test, exiting!\n");
- exit(KSFT_SKIP);
- }
+ if (free_hugepages < MIN_FREE_PAGES)
+ ksft_exit_skip("Not enough free huge pages (have %lu, need %d)\n", free_hugepages, MIN_FREE_PAGES);
fd = memfd_create(argv[0], MFD_HUGETLB);
- if (fd < 0) {
- perror("memfd_create() failed");
- exit(1);
- }
+ if (fd < 0)
+ ksft_exit_fail_perror("memfd_create");
/*
* Test validity of MADV_DONTNEED addr and length arguments. mmap
@@ -90,16 +85,13 @@ int main(int argc, char **argv)
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
-1, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
+
if (munmap(addr, huge_page_size) ||
munmap(addr + (NR_HUGE_PAGES + 1) * huge_page_size,
- huge_page_size)) {
- perror("munmap");
- exit(1);
- }
+ huge_page_size))
+ ksft_exit_fail_perror("munmap");
addr = addr + huge_page_size;
write_fault_pages(addr, NR_HUGE_PAGES);
@@ -108,20 +100,14 @@ int main(int argc, char **argv)
/* addr before mapping should fail */
ret = madvise(addr - base_page_size, NR_HUGE_PAGES * huge_page_size,
MADV_DONTNEED);
- if (!ret) {
- printf("Unexpected success of madvise call with invalid addr line %d\n",
- __LINE__);
- exit(1);
- }
+ if (!ret)
+ ksft_exit_fail_msg("madvise with invalid addr unexpectedly succeeded line %d\n", __LINE__);
/* addr + length after mapping should fail */
ret = madvise(addr, (NR_HUGE_PAGES * huge_page_size) + base_page_size,
MADV_DONTNEED);
- if (!ret) {
- printf("Unexpected success of madvise call with invalid length line %d\n",
- __LINE__);
- exit(1);
- }
+ if (!ret)
+ ksft_exit_fail_msg("madvise with invalid length unexpectedly succeeded line %d\n", __LINE__);
(void)munmap(addr, NR_HUGE_PAGES * huge_page_size);
@@ -132,10 +118,9 @@ int main(int argc, char **argv)
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
-1, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
+
write_fault_pages(addr, NR_HUGE_PAGES);
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
@@ -143,19 +128,14 @@ int main(int argc, char **argv)
ret = madvise(addr + base_page_size,
NR_HUGE_PAGES * huge_page_size - base_page_size,
MADV_DONTNEED);
- if (!ret) {
- printf("Unexpected success of madvise call with unaligned start address %d\n",
- __LINE__);
- exit(1);
- }
+ if (!ret)
+ ksft_exit_fail_msg("madvise with unaligned start unexpectedly succeeded line %d\n", __LINE__);
/* addr + length should be aligned down to huge page size */
if (madvise(addr,
((NR_HUGE_PAGES - 1) * huge_page_size) + base_page_size,
- MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
/* should free all but last page in mapping */
validate_free_pages(free_hugepages - 1);
@@ -170,17 +150,14 @@ int main(int argc, char **argv)
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
-1, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
+
write_fault_pages(addr, NR_HUGE_PAGES);
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
/* should free all pages in mapping */
validate_free_pages(free_hugepages);
@@ -190,29 +167,25 @@ int main(int argc, char **argv)
/*
* Test MADV_DONTNEED on private mapping of hugetlb file
*/
- if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) {
- perror("fallocate");
- exit(1);
- }
+ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size))
+ ksft_exit_fail_perror("fallocate");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
/* read should not consume any pages */
read_fault_pages(addr, NR_HUGE_PAGES);
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/* madvise should not free any pages */
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/* writes should allocate private pages */
@@ -220,10 +193,9 @@ int main(int argc, char **argv)
validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES));
/* madvise should free private pages */
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/* writes should allocate private pages */
@@ -238,10 +210,9 @@ int main(int argc, char **argv)
* implementation.
*/
if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- 0, NR_HUGE_PAGES * huge_page_size)) {
- perror("fallocate");
- exit(1);
- }
+ 0, NR_HUGE_PAGES * huge_page_size))
+ ksft_exit_fail_perror("fallocate");
+
validate_free_pages(free_hugepages);
(void)munmap(addr, NR_HUGE_PAGES * huge_page_size);
@@ -249,29 +220,25 @@ int main(int argc, char **argv)
/*
* Test MADV_DONTNEED on shared mapping of hugetlb file
*/
- if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) {
- perror("fallocate");
- exit(1);
- }
+ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size))
+ ksft_exit_fail_perror("fallocate");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
/* write should not consume any pages */
write_fault_pages(addr, NR_HUGE_PAGES);
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/* madvise should not free any pages */
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/*
@@ -279,29 +246,25 @@ int main(int argc, char **argv)
*
* madvise is same as hole punch and should free all pages.
*/
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages);
(void)munmap(addr, NR_HUGE_PAGES * huge_page_size);
/*
* Test MADV_REMOVE on shared and private mapping of hugetlb file
*/
- if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) {
- perror("fallocate");
- exit(1);
- }
+ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size))
+ ksft_exit_fail_perror("fallocate");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
- if (addr == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
/* shared write should not consume any additional pages */
write_fault_pages(addr, NR_HUGE_PAGES);
@@ -310,10 +273,8 @@ int main(int argc, char **argv)
addr2 = mmap(NULL, NR_HUGE_PAGES * huge_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
- if (addr2 == MAP_FAILED) {
- perror("mmap");
- exit(1);
- }
+ if (addr2 == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
/* private read should not consume any pages */
read_fault_pages(addr2, NR_HUGE_PAGES);
@@ -324,17 +285,15 @@ int main(int argc, char **argv)
validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES));
/* madvise of shared mapping should not free any pages */
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES));
/* madvise of private mapping should free private pages */
- if (madvise(addr2, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr2, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages - NR_HUGE_PAGES);
/* private write should consume additional pages again */
@@ -346,15 +305,16 @@ int main(int argc, char **argv)
* not correct. private pages should not be freed, but this is
* expected. See comment associated with FALLOC_FL_PUNCH_HOLE call.
*/
- if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE)) {
- perror("madvise");
- exit(1);
- }
+ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE))
+ ksft_exit_fail_perror("madvise");
+
validate_free_pages(free_hugepages);
(void)munmap(addr, NR_HUGE_PAGES * huge_page_size);
(void)munmap(addr2, NR_HUGE_PAGES * huge_page_size);
close(fd);
- return 0;
+
+ ksft_test_result_pass("MADV_DONTNEED and MADV_REMOVE on hugetlb\n");
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 11/55] selftests/mm: hugetlb_madv_vs_map: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (9 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 10/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 12/55] selftests/mm: hugetlb-read-hwpoison: " Mike Rapoport
` (44 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert hugetlb_madv_vs_map test to use kselftest framework for
reporting and tracking successful and failing runs.
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../testing/selftests/mm/hugetlb_madv_vs_map.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
index efd774b41389..c7105c6d319b 100644
--- a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
+++ b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
@@ -25,7 +25,6 @@
#include <unistd.h>
#include "vm_util.h"
-#include "kselftest.h"
#define INLOOP_ITER 100
@@ -86,12 +85,14 @@ int main(void)
*/
int max = 10;
+ ksft_print_header();
+ ksft_set_plan(1);
+
free_hugepages = get_free_hugepages();
- if (free_hugepages != 1) {
+ if (free_hugepages != 1)
ksft_exit_skip("This test needs one and only one page to execute. Got %lu\n",
free_hugepages);
- }
mmap_size = default_huge_page_size();
@@ -100,10 +101,8 @@ int main(void)
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
-1, 0);
- if ((unsigned long)huge_ptr == -1) {
- ksft_test_result_fail("Failed to allocate huge page\n");
- return KSFT_FAIL;
- }
+ if ((unsigned long)huge_ptr == -1)
+ ksft_exit_fail_msg("Failed to allocate huge page\n");
pthread_create(&thread1, NULL, madv, NULL);
pthread_create(&thread2, NULL, touch, NULL);
@@ -115,12 +114,13 @@ int main(void)
if (ret) {
ksft_test_result_fail("Unexpected huge page allocation\n");
- return KSFT_FAIL;
+ ksft_finished();
}
/* Unmap and restart */
munmap(huge_ptr, mmap_size);
}
- return KSFT_PASS;
+ ksft_test_result_pass("No unexpected huge page allocations\n");
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 12/55] selftests/mm: hugetlb-read-hwpoison: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (10 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 11/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 13/55] selftests/mm: khugepaged: group tests in an array Mike Rapoport
` (43 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert hugetlb-read-hwpoison test to use kselftest framework for
reporting and tracking successful and failing runs.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Li Wang <li.wang@linux.dev>
Reviewed-by: Li Wang <li.wang@linux.dev>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../selftests/mm/hugetlb-read-hwpoison.c | 115 +++++++++---------
1 file changed, 55 insertions(+), 60 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-read-hwpoison.c b/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
index ad3198b444ce..70b24e3660c4 100644
--- a/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
+++ b/tools/testing/selftests/mm/hugetlb-read-hwpoison.c
@@ -14,9 +14,6 @@
#include "kselftest.h"
-#define PREFIX " ... "
-#define ERROR_PREFIX " !!! "
-
#define MAX_WRITE_READ_CHUNK_SIZE (getpagesize() * 16)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
@@ -26,17 +23,22 @@ enum test_status {
TEST_SKIPPED = 2,
};
-static char *status_to_str(enum test_status status)
+static void report_status(enum test_status status, const char *test_name,
+ size_t chunk_size)
{
switch (status) {
case TEST_PASSED:
- return "TEST_PASSED";
+ ksft_test_result_pass("%s chunk_size=0x%lx\n",
+ test_name, chunk_size);
+ break;
case TEST_FAILED:
- return "TEST_FAILED";
+ ksft_test_result_fail("%s chunk_size=0x%lx\n",
+ test_name, chunk_size);
+ break;
case TEST_SKIPPED:
- return "TEST_SKIPPED";
- default:
- return "TEST_???";
+ ksft_test_result_skip("%s chunk_size=0x%lx\n",
+ test_name, chunk_size);
+ break;
}
}
@@ -59,8 +61,8 @@ static bool verify_chunk(char *buf, size_t len, char val)
for (i = 0; i < len; ++i) {
if (buf[i] != val) {
- printf(PREFIX ERROR_PREFIX "check fail: buf[%lu] = %u != %u\n",
- i, buf[i], val);
+ ksft_print_msg("check fail: buf[%lu] = %u != %u\n",
+ i, buf[i], val);
return false;
}
}
@@ -76,21 +78,21 @@ static bool seek_read_hugepage_filemap(int fd, size_t len, size_t wr_chunk_size,
ssize_t total_ret_count = 0;
char val = offset / wr_chunk_size + offset % wr_chunk_size;
- printf(PREFIX PREFIX "init val=%u with offset=0x%lx\n", val, offset);
- printf(PREFIX PREFIX "expect to read 0x%lx bytes of data in total\n",
- expected);
+ ksft_print_msg("init val=%u with offset=0x%lx\n", val, offset);
+ ksft_print_msg("expect to read 0x%lx bytes of data in total\n",
+ expected);
if (lseek(fd, offset, SEEK_SET) < 0) {
- perror(PREFIX ERROR_PREFIX "seek failed");
+ ksft_perror("seek failed");
return false;
}
while (offset + total_ret_count < len) {
ret_count = read(fd, buf, wr_chunk_size);
if (ret_count == 0) {
- printf(PREFIX PREFIX "read reach end of the file\n");
+ ksft_print_msg("read reach end of the file\n");
break;
} else if (ret_count < 0) {
- perror(PREFIX ERROR_PREFIX "read failed");
+ ksft_perror("read failed");
break;
}
++val;
@@ -99,8 +101,8 @@ static bool seek_read_hugepage_filemap(int fd, size_t len, size_t wr_chunk_size,
total_ret_count += ret_count;
}
- printf(PREFIX PREFIX "actually read 0x%lx bytes of data in total\n",
- total_ret_count);
+ ksft_print_msg("actually read 0x%lx bytes of data in total\n",
+ total_ret_count);
return total_ret_count == expected;
}
@@ -113,15 +115,15 @@ static bool read_hugepage_filemap(int fd, size_t len,
ssize_t total_ret_count = 0;
char val = 0;
- printf(PREFIX PREFIX "expect to read 0x%lx bytes of data in total\n",
- expected);
+ ksft_print_msg("expect to read 0x%lx bytes of data in total\n",
+ expected);
while (total_ret_count < len) {
ret_count = read(fd, buf, wr_chunk_size);
if (ret_count == 0) {
- printf(PREFIX PREFIX "read reach end of the file\n");
+ ksft_print_msg("read reach end of the file\n");
break;
} else if (ret_count < 0) {
- perror(PREFIX ERROR_PREFIX "read failed");
+ ksft_perror("read failed");
break;
}
++val;
@@ -130,8 +132,8 @@ static bool read_hugepage_filemap(int fd, size_t len,
total_ret_count += ret_count;
}
- printf(PREFIX PREFIX "actually read 0x%lx bytes of data in total\n",
- total_ret_count);
+ ksft_print_msg("actually read 0x%lx bytes of data in total\n",
+ total_ret_count);
return total_ret_count == expected;
}
@@ -143,14 +145,14 @@ test_hugetlb_read(int fd, size_t len, size_t wr_chunk_size)
char *filemap = NULL;
if (ftruncate(fd, len) < 0) {
- perror(PREFIX ERROR_PREFIX "ftruncate failed");
+ ksft_perror("ftruncate failed");
return status;
}
filemap = mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0);
if (filemap == MAP_FAILED) {
- perror(PREFIX ERROR_PREFIX "mmap for primary mapping failed");
+ ksft_perror("mmap for primary mapping failed");
goto done;
}
@@ -163,7 +165,7 @@ test_hugetlb_read(int fd, size_t len, size_t wr_chunk_size)
munmap(filemap, len);
done:
if (ftruncate(fd, 0) < 0) {
- perror(PREFIX ERROR_PREFIX "ftruncate back to 0 failed");
+ ksft_perror("ftruncate back to 0 failed");
status = TEST_FAILED;
}
@@ -180,14 +182,14 @@ test_hugetlb_read_hwpoison(int fd, size_t len, size_t wr_chunk_size,
const unsigned long pagesize = getpagesize();
if (ftruncate(fd, len) < 0) {
- perror(PREFIX ERROR_PREFIX "ftruncate failed");
+ ksft_perror("ftruncate failed");
return status;
}
filemap = mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0);
if (filemap == MAP_FAILED) {
- perror(PREFIX ERROR_PREFIX "mmap for primary mapping failed");
+ ksft_perror("mmap for primary mapping failed");
goto done;
}
@@ -202,7 +204,7 @@ test_hugetlb_read_hwpoison(int fd, size_t len, size_t wr_chunk_size,
*/
hwp_addr = filemap + len / 2 + pagesize;
if (madvise(hwp_addr, pagesize, MADV_HWPOISON) < 0) {
- perror(PREFIX ERROR_PREFIX "MADV_HWPOISON failed");
+ ksft_perror("MADV_HWPOISON failed");
goto unmap;
}
@@ -229,7 +231,7 @@ test_hugetlb_read_hwpoison(int fd, size_t len, size_t wr_chunk_size,
munmap(filemap, len);
done:
if (ftruncate(fd, 0) < 0) {
- perror(PREFIX ERROR_PREFIX "ftruncate back to 0 failed");
+ ksft_perror("ftruncate back to 0 failed");
status = TEST_FAILED;
}
@@ -242,17 +244,17 @@ static int create_hugetlbfs_file(struct statfs *file_stat)
fd = memfd_create("hugetlb_tmp", MFD_HUGETLB);
if (fd < 0) {
- perror(PREFIX ERROR_PREFIX "could not open hugetlbfs file");
+ ksft_perror("could not open hugetlbfs file");
return -1;
}
memset(file_stat, 0, sizeof(*file_stat));
if (fstatfs(fd, file_stat)) {
- perror(PREFIX ERROR_PREFIX "fstatfs failed");
+ ksft_perror("fstatfs failed");
goto close;
}
if (file_stat->f_type != HUGETLBFS_MAGIC) {
- printf(PREFIX ERROR_PREFIX "not hugetlbfs file\n");
+ ksft_print_msg("not hugetlbfs file\n");
goto close;
}
@@ -278,51 +280,44 @@ int main(void)
};
size_t i;
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(wr_chunk_sizes) * 3);
+
signal(SIGBUS, sigbus_handler);
for (i = 0; i < ARRAY_SIZE(wr_chunk_sizes); ++i) {
- printf("Write/read chunk size=0x%lx\n",
- wr_chunk_sizes[i]);
+ ksft_print_msg("Write/read chunk size=0x%lx\n",
+ wr_chunk_sizes[i]);
fd = create_hugetlbfs_file(&file_stat);
if (fd < 0)
- goto create_failure;
- printf(PREFIX "HugeTLB read regression test...\n");
+ ksft_exit_fail_msg("Failed to create hugetlbfs file\n");
+
status = test_hugetlb_read(fd, file_stat.f_bsize,
wr_chunk_sizes[i]);
- printf(PREFIX "HugeTLB read regression test...%s\n",
- status_to_str(status));
close(fd);
- if (status == TEST_FAILED)
- return -1;
+ report_status(status, "HugeTLB read regression",
+ wr_chunk_sizes[i]);
fd = create_hugetlbfs_file(&file_stat);
if (fd < 0)
- goto create_failure;
- printf(PREFIX "HugeTLB read HWPOISON test...\n");
+ ksft_exit_fail_msg("Failed to create hugetlbfs file\n");
+
status = test_hugetlb_read_hwpoison(fd, file_stat.f_bsize,
wr_chunk_sizes[i], false);
- printf(PREFIX "HugeTLB read HWPOISON test...%s\n",
- status_to_str(status));
close(fd);
- if (status == TEST_FAILED)
- return -1;
+ report_status(status, "HugeTLB read HWPOISON",
+ wr_chunk_sizes[i]);
fd = create_hugetlbfs_file(&file_stat);
if (fd < 0)
- goto create_failure;
- printf(PREFIX "HugeTLB seek then read HWPOISON test...\n");
+ ksft_exit_fail_msg("Failed to create hugetlbfs file\n");
+
status = test_hugetlb_read_hwpoison(fd, file_stat.f_bsize,
wr_chunk_sizes[i], true);
- printf(PREFIX "HugeTLB seek then read HWPOISON test...%s\n",
- status_to_str(status));
close(fd);
- if (status == TEST_FAILED)
- return -1;
+ report_status(status, "HugeTLB seek then read HWPOISON",
+ wr_chunk_sizes[i]);
}
- return 0;
-
-create_failure:
- printf(ERROR_PREFIX "Abort test: failed to create hugetlbfs file\n");
- return -1;
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 13/55] selftests/mm: khugepaged: group tests in an array
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (11 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 12/55] selftests/mm: hugetlb-read-hwpoison: " Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 14/55] selftests/mm: khugepaged: use ksefltest framework Mike Rapoport
` (42 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Currently khugepaged decides if a test can run using TEST() macro that
checks what mem_ops and collapse_context are set by the command line
arguments.
For better compatibility with ksefltest framework, add an array of 'struct
test_case's and redefine TEST() macro to conditionally add enabled tests to
that array.
Then execute the enabled test by looping the test_case's array.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/khugepaged.c | 43 +++++++++++++++++++++----
1 file changed, 36 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 3fe7ef04ac62..4e3f6bd3b933 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -1165,6 +1165,34 @@ static void parse_test_type(int argc, char **argv)
get_finfo(argv[1]);
}
+typedef void (*test_fn)(struct collapse_context *c, struct mem_ops *ops);
+
+struct test_case {
+ struct collapse_context *ctx;
+ struct mem_ops *ops;
+ const char *desc;
+ test_fn fn;
+};
+
+#define MAX_TEST_CASES 64
+static struct test_case test_cases[MAX_TEST_CASES];
+static int nr_test_cases;
+
+#define TEST(t, c, o) do { \
+ if (c && o) { \
+ if (nr_test_cases >= MAX_TEST_CASES) { \
+ printf("MAX_TEST_CASES is too small\n"); \
+ exit(EXIT_FAILURE); \
+ } \
+ test_cases[nr_test_cases++] = (struct test_case){ \
+ .ctx = c, \
+ .ops = o, \
+ .desc = #t, \
+ .fn = t, \
+ }; \
+ } \
+ } while (0)
+
int main(int argc, char **argv)
{
int hpage_pmd_order;
@@ -1220,13 +1248,6 @@ int main(int argc, char **argv)
alloc_at_fault();
-#define TEST(t, c, o) do { \
- if (c && o) { \
- printf("\nRun test: " #t " (%s:%s)\n", c->name, o->name); \
- t(c, o); \
- } \
- } while (0)
-
TEST(collapse_full, khugepaged_context, anon_ops);
TEST(collapse_full, khugepaged_context, file_ops);
TEST(collapse_full, khugepaged_context, shmem_ops);
@@ -1286,5 +1307,13 @@ int main(int argc, char **argv)
TEST(madvise_retracted_page_tables, madvise_context, file_ops);
TEST(madvise_retracted_page_tables, madvise_context, shmem_ops);
+ exit_status = KSFT_PASS;
+ for (int i = 0; i < nr_test_cases; i++) {
+ struct test_case *t = &test_cases[i];
+
+ printf("\nRun test: %s (%s:%s)\n", t->desc, t->ctx->name, t->ops->name);
+ t->fn(t->ctx, t->ops);
+ }
+
restore_settings(0);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 14/55] selftests/mm: khugepaged: use ksefltest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (12 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 13/55] selftests/mm: khugepaged: group tests in an array Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 15/55] selftests/mm: ksm_tests: use kselftest framework Mike Rapoport
` (41 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert khugepaged tests to use kselftest framework for reporting and
tracking successful and failing runs.
The conversion is mostly about replacing printf()/perror() + exit() pairs
with their ksft_ counterparts.
The nice colored success and failure indications are left intact.
Replace the progress report in collapse_compound_extreme() with a single
ksft_print_msg() to avoid headache with formatting and make the test output
more concise.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/khugepaged.c | 314 ++++++++++--------------
1 file changed, 130 insertions(+), 184 deletions(-)
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 4e3f6bd3b933..3fd0693cc45d 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -78,17 +78,19 @@ static int exit_status;
static void success(const char *msg)
{
printf(" \e[32m%s\e[0m\n", msg);
+ exit_status = KSFT_PASS;
}
static void fail(const char *msg)
{
printf(" \e[31m%s\e[0m\n", msg);
- exit_status++;
+ exit_status = KSFT_FAIL;
}
static void skip(const char *msg)
{
printf(" \e[33m%s\e[0m\n", msg);
+ exit_status = KSFT_SKIP;
}
static void restore_settings_atexit(void)
@@ -96,22 +98,24 @@ static void restore_settings_atexit(void)
if (skip_settings_restore)
return;
- printf("Restore THP and khugepaged settings...");
+ ksft_print_msg("Restore THP and khugepaged settings...");
thp_restore_settings();
success("OK");
skip_settings_restore = true;
+ ksft_print_cnts();
+ exit(exit_status);
}
static void restore_settings(int sig)
{
/* exit() will invoke the restore_settings_atexit handler. */
- exit(sig ? EXIT_FAILURE : exit_status);
+ exit(sig ? KSFT_FAIL : exit_status);
}
static void save_settings(void)
{
- printf("Save THP and khugepaged settings...");
+ ksft_print_msg("Save THP and khugepaged settings...");
if (file_ops && finfo.type == VMA_FILE)
thp_set_read_ahead_path(finfo.dev_queue_read_ahead_path);
thp_save_settings();
@@ -135,19 +139,13 @@ static void get_finfo(const char *dir)
finfo.dir = dir;
stat(finfo.dir, &path_stat);
- if (!S_ISDIR(path_stat.st_mode)) {
- printf("%s: Not a directory (%s)\n", __func__, finfo.dir);
- exit(EXIT_FAILURE);
- }
+ if (!S_ISDIR(path_stat.st_mode))
+ ksft_exit_fail_msg("%s: Not a directory (%s)\n", __func__, finfo.dir);
if (snprintf(finfo.path, sizeof(finfo.path), "%s/" TEST_FILE,
- finfo.dir) >= sizeof(finfo.path)) {
- printf("%s: Pathname is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
- if (statfs(finfo.dir, &fs)) {
- perror("statfs()");
- exit(EXIT_FAILURE);
- }
+ finfo.dir) >= sizeof(finfo.path))
+ ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
+ if (statfs(finfo.dir, &fs))
+ ksft_exit_fail_perror("statfs()");
finfo.type = fs.f_type == TMPFS_MAGIC ? VMA_SHMEM : VMA_FILE;
if (finfo.type == VMA_SHMEM)
return;
@@ -155,40 +153,30 @@ static void get_finfo(const char *dir)
/* Find owning device's queue/read_ahead_kb control */
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/uevent",
major(path_stat.st_dev), minor(path_stat.st_dev))
- >= sizeof(path)) {
- printf("%s: Pathname is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
- if (read_file(path, buf, sizeof(buf)) < 0) {
- perror("read_file(read_num)");
- exit(EXIT_FAILURE);
- }
+ >= sizeof(path))
+ ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
+ if (read_file(path, buf, sizeof(buf)) < 0)
+ ksft_exit_fail_perror("read_file(read_num)");
if (strstr(buf, "DEVTYPE=disk")) {
/* Found it */
if (snprintf(finfo.dev_queue_read_ahead_path,
sizeof(finfo.dev_queue_read_ahead_path),
"/sys/dev/block/%d:%d/queue/read_ahead_kb",
major(path_stat.st_dev), minor(path_stat.st_dev))
- >= sizeof(finfo.dev_queue_read_ahead_path)) {
- printf("%s: Pathname is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
+ >= sizeof(finfo.dev_queue_read_ahead_path))
+ ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
return;
}
- if (!strstr(buf, "DEVTYPE=partition")) {
- printf("%s: Unknown device type: %s\n", __func__, path);
- exit(EXIT_FAILURE);
- }
+ if (!strstr(buf, "DEVTYPE=partition"))
+ ksft_exit_fail_msg("%s: Unknown device type: %s\n", __func__, path);
/*
* Partition of block device - need to find actual device.
* Using naming convention that devnameN is partition of
* device devname.
*/
str = strstr(buf, "DEVNAME=");
- if (!str) {
- printf("%s: Could not read: %s", __func__, path);
- exit(EXIT_FAILURE);
- }
+ if (!str)
+ ksft_exit_fail_msg("%s: Could not read: %s", __func__, path);
str += 8;
end = str;
while (*end) {
@@ -197,16 +185,13 @@ static void get_finfo(const char *dir)
if (snprintf(finfo.dev_queue_read_ahead_path,
sizeof(finfo.dev_queue_read_ahead_path),
"/sys/block/%s/queue/read_ahead_kb",
- str) >= sizeof(finfo.dev_queue_read_ahead_path)) {
- printf("%s: Pathname is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
+ str) >= sizeof(finfo.dev_queue_read_ahead_path))
+ ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
return;
}
++end;
}
- printf("%s: Could not read: %s\n", __func__, path);
- exit(EXIT_FAILURE);
+ ksft_exit_fail_msg("%s: Could not read: %s\n", __func__, path);
}
static bool check_swap(void *addr, unsigned long size)
@@ -219,26 +204,19 @@ static bool check_swap(void *addr, unsigned long size)
ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "%08lx-",
(unsigned long) addr);
- if (ret >= MAX_LINE_LENGTH) {
- printf("%s: Pattern is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
-
+ if (ret >= MAX_LINE_LENGTH)
+ ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
fp = fopen(PID_SMAPS, "r");
- if (!fp) {
- printf("%s: Failed to open file %s\n", __func__, PID_SMAPS);
- exit(EXIT_FAILURE);
- }
+ if (!fp)
+ ksft_exit_fail_msg("%s: Failed to open file %s\n", __func__, PID_SMAPS);
if (!check_for_pattern(fp, addr_pattern, buffer, sizeof(buffer)))
goto err_out;
ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "Swap:%19ld kB",
size >> 10);
- if (ret >= MAX_LINE_LENGTH) {
- printf("%s: Pattern is too long\n", __func__);
- exit(EXIT_FAILURE);
- }
+ if (ret >= MAX_LINE_LENGTH)
+ ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
/*
* Fetch the Swap: in the same block and check whether it got
* the expected number of hugeepages next.
@@ -261,10 +239,8 @@ static void *alloc_mapping(int nr)
p = mmap(BASE_ADDR, nr * hpage_pmd_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- if (p != BASE_ADDR) {
- printf("Failed to allocate VMA at %p\n", BASE_ADDR);
- exit(EXIT_FAILURE);
- }
+ if (p != BASE_ADDR)
+ ksft_exit_fail_msg("Failed to allocate VMA at %p\n", BASE_ADDR);
return p;
}
@@ -314,19 +290,13 @@ static void *alloc_hpage(struct mem_ops *ops)
* khugepaged on low-load system (like a test machine), which
* would cause MADV_COLLAPSE to fail with EAGAIN.
*/
- printf("Allocate huge page...");
- 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);
- }
+ ksft_print_msg("Allocate huge page...");
+ if (madvise_collapse_retry(p, hpage_pmd_size))
+ ksft_exit_fail_perror("madvise(MADV_COLLAPSE)");
+ if (!ops->check_huge(p, 1))
+ ksft_exit_fail_perror("madvise(MADV_COLLAPSE)");
+ if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE))
+ ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)");
success("OK");
return p;
}
@@ -336,11 +306,9 @@ static void validate_memory(int *p, unsigned long start, unsigned long end)
int i;
for (i = start / page_size; i < end / page_size; i++) {
- if (p[i * page_size / sizeof(*p)] != i + 0xdead0000) {
- printf("Page %d is corrupted: %#x\n",
- i, p[i * page_size / sizeof(*p)]);
- exit(EXIT_FAILURE);
- }
+ if (p[i * page_size / sizeof(*p)] != i + 0xdead0000)
+ ksft_exit_fail_msg("Page %d is corrupted: %#x\n",
+ i, p[i * page_size / sizeof(*p)]);
}
}
@@ -371,14 +339,12 @@ static void *file_setup_area(int nr_hpages)
unsigned long size;
unlink(finfo.path); /* Cleanup from previous failed tests */
- printf("Creating %s for collapse%s...", finfo.path,
- finfo.type == VMA_SHMEM ? " (tmpfs)" : "");
+ ksft_print_msg("Creating %s for collapse%s...", finfo.path,
+ finfo.type == VMA_SHMEM ? " (tmpfs)" : "");
fd = open(finfo.path, O_DSYNC | O_CREAT | O_RDWR | O_TRUNC | O_EXCL,
777);
- if (fd < 0) {
- perror("open()");
- exit(EXIT_FAILURE);
- }
+ if (fd < 0)
+ ksft_exit_fail_perror("open()");
size = nr_hpages * hpage_pmd_size;
p = alloc_mapping(nr_hpages);
@@ -388,18 +354,14 @@ static void *file_setup_area(int nr_hpages)
munmap(p, size);
success("OK");
- printf("Opening %s read only for collapse...", finfo.path);
+ ksft_print_msg("Opening %s read only for collapse...", finfo.path);
finfo.fd = open(finfo.path, O_RDONLY, 777);
- if (finfo.fd < 0) {
- perror("open()");
- exit(EXIT_FAILURE);
- }
+ if (finfo.fd < 0)
+ ksft_exit_fail_perror("open()");
p = mmap(BASE_ADDR, size, PROT_READ,
MAP_PRIVATE, finfo.fd, 0);
- if (p == MAP_FAILED || p != BASE_ADDR) {
- perror("mmap()");
- exit(EXIT_FAILURE);
- }
+ if (p == MAP_FAILED || p != BASE_ADDR)
+ ksft_exit_fail_perror("mmap()");
/* Drop page cache */
write_file("/proc/sys/vm/drop_caches", "3", 2);
@@ -416,10 +378,8 @@ static void file_cleanup_area(void *p, unsigned long size)
static void file_fault(void *p, unsigned long start, unsigned long end)
{
- if (madvise(((char *)p) + start, end - start, MADV_POPULATE_READ)) {
- perror("madvise(MADV_POPULATE_READ");
- exit(EXIT_FAILURE);
- }
+ if (madvise(((char *)p) + start, end - start, MADV_POPULATE_READ))
+ ksft_exit_fail_perror("madvise(MADV_POPULATE_READ");
}
static bool file_check_huge(void *addr, int nr_hpages)
@@ -441,20 +401,14 @@ static void *shmem_setup_area(int nr_hpages)
unsigned long size = nr_hpages * hpage_pmd_size;
finfo.fd = memfd_create("khugepaged-selftest-collapse-shmem", 0);
- if (finfo.fd < 0) {
- perror("memfd_create()");
- exit(EXIT_FAILURE);
- }
- if (ftruncate(finfo.fd, size)) {
- perror("ftruncate()");
- exit(EXIT_FAILURE);
- }
+ if (finfo.fd < 0)
+ ksft_exit_fail_perror("memfd_create()");
+ if (ftruncate(finfo.fd, size))
+ ksft_exit_fail_perror("ftruncate()");
p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE, MAP_SHARED, finfo.fd,
0);
- if (p != BASE_ADDR) {
- perror("mmap()");
- exit(EXIT_FAILURE);
- }
+ if (p != BASE_ADDR)
+ ksft_exit_fail_perror("mmap()");
return p;
}
@@ -499,7 +453,7 @@ static void __madvise_collapse(const char *msg, char *p, int nr_hpages,
int ret;
struct thp_settings settings = *thp_current_settings();
- printf("%s...", msg);
+ ksft_print_msg("%s...", msg);
/*
* Prevent khugepaged interference and tests that MADV_COLLAPSE
@@ -526,10 +480,8 @@ 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);
- }
+ if (!ops->check_huge(p, 0))
+ ksft_exit_fail_msg("Unexpected huge page\n");
__madvise_collapse(msg, p, nr_hpages, ops, expect);
}
@@ -541,17 +493,15 @@ static bool wait_for_scan(const char *msg, char *p, int nr_hpages,
int timeout = 6; /* 3 seconds */
/* Sanity check */
- if (!ops->check_huge(p, 0)) {
- printf("Unexpected huge page\n");
- exit(EXIT_FAILURE);
- }
+ if (!ops->check_huge(p, 0))
+ ksft_exit_fail_msg("Unexpected huge page\n");
madvise(p, nr_hpages * hpage_pmd_size, MADV_HUGEPAGE);
/* Wait until the second full_scan completed */
full_scans = thp_read_num("khugepaged/full_scans") + 2;
- printf("%s...", msg);
+ ksft_print_msg("%s...", msg);
while (timeout--) {
if (ops->check_huge(p, nr_hpages))
break;
@@ -621,7 +571,7 @@ static void alloc_at_fault(void)
p = alloc_mapping(1);
*p = 1;
- printf("Allocate huge page on fault...");
+ ksft_print_msg("Allocate huge page on fault...");
if (check_huge_anon(p, 1, hpage_pmd_size))
success("OK");
else
@@ -630,12 +580,14 @@ static void alloc_at_fault(void)
thp_pop_settings();
madvise(p, page_size, MADV_DONTNEED);
- printf("Split huge PMD on MADV_DONTNEED...");
+ ksft_print_msg("Split huge PMD on MADV_DONTNEED...");
if (check_huge_anon(p, 0, hpage_pmd_size))
success("OK");
else
fail("Fail");
munmap(p, hpage_pmd_size);
+
+ ksft_test_result_report(exit_status, "allocate on fault and split\n");
}
static void collapse_full(struct collapse_context *c, struct mem_ops *ops)
@@ -650,6 +602,8 @@ static void collapse_full(struct collapse_context *c, struct mem_ops *ops)
ops, true);
validate_memory(p, 0, size);
ops->cleanup_area(p, size);
+
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_empty(struct collapse_context *c, struct mem_ops *ops)
@@ -659,6 +613,7 @@ static void collapse_empty(struct collapse_context *c, struct mem_ops *ops)
p = ops->setup_area(1);
c->collapse("Do not collapse empty PTE table", p, 1, ops, false);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_single_pte_entry(struct collapse_context *c, struct mem_ops *ops)
@@ -670,6 +625,7 @@ static void collapse_single_pte_entry(struct collapse_context *c, struct mem_ops
c->collapse("Collapse PTE table with single PTE entry present", p,
1, ops, true);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_max_ptes_none(struct collapse_context *c, struct mem_ops *ops)
@@ -706,6 +662,7 @@ static void collapse_max_ptes_none(struct collapse_context *c, struct mem_ops *o
skip:
ops->cleanup_area(p, hpage_pmd_size);
thp_pop_settings();
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_swapin_single_pte(struct collapse_context *c, struct mem_ops *ops)
@@ -715,11 +672,9 @@ static void collapse_swapin_single_pte(struct collapse_context *c, struct mem_op
p = ops->setup_area(1);
ops->fault(p, 0, hpage_pmd_size);
- printf("Swapout one page...");
- if (madvise(p, page_size, MADV_PAGEOUT)) {
- perror("madvise(MADV_PAGEOUT)");
- exit(EXIT_FAILURE);
- }
+ ksft_print_msg("Swapout one page...");
+ if (madvise(p, page_size, MADV_PAGEOUT))
+ ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
if (check_swap(p, page_size)) {
success("OK");
} else {
@@ -732,6 +687,7 @@ static void collapse_swapin_single_pte(struct collapse_context *c, struct mem_op
validate_memory(p, 0, hpage_pmd_size);
out:
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *ops)
@@ -742,11 +698,9 @@ static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *o
p = ops->setup_area(1);
ops->fault(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)");
- exit(EXIT_FAILURE);
- }
+ ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap + 1, hpage_pmd_nr);
+ if (madvise(p, (max_ptes_swap + 1) * page_size, MADV_PAGEOUT))
+ ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
if (check_swap(p, (max_ptes_swap + 1) * page_size)) {
success("OK");
} else {
@@ -760,12 +714,10 @@ static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *o
if (c->enforce_pte_scan_limits) {
ops->fault(p, 0, hpage_pmd_size);
- printf("Swapout %d of %d pages...", max_ptes_swap,
+ ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap,
hpage_pmd_nr);
- if (madvise(p, max_ptes_swap * page_size, MADV_PAGEOUT)) {
- perror("madvise(MADV_PAGEOUT)");
- exit(EXIT_FAILURE);
- }
+ if (madvise(p, max_ptes_swap * page_size, MADV_PAGEOUT))
+ ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
if (check_swap(p, max_ptes_swap * page_size)) {
success("OK");
} else {
@@ -779,6 +731,7 @@ static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *o
}
out:
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_single_pte_entry_compound(struct collapse_context *c, struct mem_ops *ops)
@@ -795,7 +748,7 @@ static void collapse_single_pte_entry_compound(struct collapse_context *c, struc
}
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
- printf("Split huge page leaving single PTE mapping compound page...");
+ ksft_print_msg("Split huge page leaving single PTE mapping compound page...");
madvise(p + page_size, hpage_pmd_size - page_size, MADV_DONTNEED);
if (ops->check_huge(p, 0))
success("OK");
@@ -807,6 +760,7 @@ static void collapse_single_pte_entry_compound(struct collapse_context *c, struc
validate_memory(p, 0, page_size);
skip:
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_full_of_compound(struct collapse_context *c, struct mem_ops *ops)
@@ -814,7 +768,7 @@ static void collapse_full_of_compound(struct collapse_context *c, struct mem_ops
void *p;
p = alloc_hpage(ops);
- printf("Split huge page leaving single PTE page table full of compound pages...");
+ ksft_print_msg("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 (ops->check_huge(p, 0))
@@ -826,6 +780,7 @@ static void collapse_full_of_compound(struct collapse_context *c, struct mem_ops
true);
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops *ops)
@@ -834,16 +789,12 @@ static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops
int i;
p = ops->setup_area(1);
+ ksft_print_msg("Construct PTE page table full of different PTE-mapped compound pages\n");
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);
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);
- }
+ if (!ops->check_huge(BASE_ADDR, 1))
+ ksft_exit_fail_msg("Failed to allocate huge page\n");
madvise(BASE_ADDR, hpage_pmd_size, MADV_NOHUGEPAGE);
p = mremap(BASE_ADDR - i * page_size,
@@ -851,20 +802,16 @@ static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops
(i + 1) * page_size,
MREMAP_MAYMOVE | MREMAP_FIXED,
BASE_ADDR + 2 * hpage_pmd_size);
- if (p == MAP_FAILED) {
- perror("mremap+unmap");
- exit(EXIT_FAILURE);
- }
+ if (p == MAP_FAILED)
+ ksft_exit_fail_perror("mremap+unmap");
p = mremap(BASE_ADDR + 2 * hpage_pmd_size,
(i + 1) * page_size,
(i + 1) * page_size + hpage_pmd_size,
MREMAP_MAYMOVE | MREMAP_FIXED,
BASE_ADDR - (i + 1) * page_size);
- if (p == MAP_FAILED) {
- perror("mremap+alloc");
- exit(EXIT_FAILURE);
- }
+ if (p == MAP_FAILED)
+ ksft_exit_fail_perror("mremap+alloc");
}
ops->cleanup_area(BASE_ADDR, hpage_pmd_size);
@@ -879,6 +826,7 @@ static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
@@ -888,18 +836,17 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
p = ops->setup_area(1);
- printf("Allocate small page...");
+ ksft_print_msg("Allocate small page...");
ops->fault(p, 0, page_size);
if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
- printf("Share small page over fork()...");
+ ksft_print_msg("Share small page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
skip_settings_restore = true;
- exit_status = 0;
if (ops->check_huge(p, 0))
success("OK");
@@ -916,15 +863,16 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
}
wait(&wstatus);
- exit_status += WEXITSTATUS(wstatus);
+ exit_status = WEXITSTATUS(wstatus);
- printf("Check if parent still has small page...");
+ ksft_print_msg("Check if parent still has small page...");
if (ops->check_huge(p, 0))
success("OK");
else
fail("Fail");
validate_memory(p, 0, page_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *ops)
@@ -933,18 +881,17 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o
void *p;
p = alloc_hpage(ops);
- printf("Share huge page over fork()...");
+ ksft_print_msg("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
skip_settings_restore = true;
- exit_status = 0;
if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
- printf("Split huge page PMD in child process...");
+ ksft_print_msg("Split huge page PMD in child process...");
madvise(p, page_size, MADV_NOHUGEPAGE);
madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
if (ops->check_huge(p, 0))
@@ -965,15 +912,16 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o
}
wait(&wstatus);
- exit_status += WEXITSTATUS(wstatus);
+ exit_status = WEXITSTATUS(wstatus);
- printf("Check if parent still has huge page...");
+ ksft_print_msg("Check if parent still has huge page...");
if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops *ops)
@@ -983,18 +931,17 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops
void *p;
p = alloc_hpage(ops);
- printf("Share huge page over fork()...");
+ ksft_print_msg("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
skip_settings_restore = true;
- exit_status = 0;
if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
- printf("Trigger CoW on page %d of %d...",
+ ksft_print_msg("Trigger CoW on page %d of %d...",
hpage_pmd_nr - max_ptes_shared - 1, hpage_pmd_nr);
ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared - 1) * page_size);
if (ops->check_huge(p, 0))
@@ -1006,7 +953,7 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops
1, ops, !c->enforce_pte_scan_limits);
if (c->enforce_pte_scan_limits) {
- printf("Trigger CoW on page %d of %d...",
+ ksft_print_msg("Trigger CoW on page %d of %d...",
hpage_pmd_nr - max_ptes_shared, hpage_pmd_nr);
ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared) *
page_size);
@@ -1025,15 +972,16 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops
}
wait(&wstatus);
- exit_status += WEXITSTATUS(wstatus);
+ exit_status = WEXITSTATUS(wstatus);
- printf("Check if parent still has huge page...");
+ ksft_print_msg("Check if parent still has huge page...");
if (ops->check_huge(p, 1))
success("OK");
else
fail("Fail");
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void madvise_collapse_existing_thps(struct collapse_context *c,
@@ -1050,6 +998,7 @@ static void madvise_collapse_existing_thps(struct collapse_context *c,
__madvise_collapse("Re-collapse PMD-mapped hugepage", p, 1, ops, true);
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
/*
@@ -1077,6 +1026,7 @@ static void madvise_retracted_page_tables(struct collapse_context *c,
true);
validate_memory(p, 0, size);
ops->cleanup_area(p, size);
+ ksft_test_result_report(exit_status, "%s\n", __func__);
}
static void usage(void)
@@ -1180,10 +1130,8 @@ static int nr_test_cases;
#define TEST(t, c, o) do { \
if (c && o) { \
- if (nr_test_cases >= MAX_TEST_CASES) { \
- printf("MAX_TEST_CASES is too small\n"); \
- exit(EXIT_FAILURE); \
- } \
+ if (nr_test_cases >= MAX_TEST_CASES) \
+ ksft_exit_fail_msg("MAX_TEST_CASES is too small\n"); \
test_cases[nr_test_cases++] = (struct test_case){ \
.ctx = c, \
.ops = o, \
@@ -1216,10 +1164,10 @@ int main(int argc, char **argv)
.read_ahead_kb = 0,
};
- if (!thp_is_enabled()) {
- printf("Transparent Hugepages not available\n");
- return KSFT_SKIP;
- }
+ ksft_print_header();
+
+ if (!thp_is_enabled())
+ ksft_exit_skip("Transparent Hugepages not available\n");
parse_test_type(argc, argv);
@@ -1227,10 +1175,8 @@ int main(int argc, char **argv)
page_size = getpagesize();
hpage_pmd_size = read_pmd_pagesize();
- if (!hpage_pmd_size) {
- printf("Reading PMD pagesize failed");
- exit(EXIT_FAILURE);
- }
+ if (!hpage_pmd_size)
+ ksft_exit_fail_msg("Reading PMD pagesize failed\n");
hpage_pmd_nr = hpage_pmd_size / page_size;
hpage_pmd_order = __builtin_ctz(hpage_pmd_nr);
@@ -1246,8 +1192,6 @@ int main(int argc, char **argv)
save_settings();
thp_push_settings(&default_settings);
- alloc_at_fault();
-
TEST(collapse_full, khugepaged_context, anon_ops);
TEST(collapse_full, khugepaged_context, file_ops);
TEST(collapse_full, khugepaged_context, shmem_ops);
@@ -1307,11 +1251,13 @@ int main(int argc, char **argv)
TEST(madvise_retracted_page_tables, madvise_context, file_ops);
TEST(madvise_retracted_page_tables, madvise_context, shmem_ops);
- exit_status = KSFT_PASS;
+ ksft_set_plan(nr_test_cases + 1);
+
+ alloc_at_fault();
for (int i = 0; i < nr_test_cases; i++) {
struct test_case *t = &test_cases[i];
- printf("\nRun test: %s (%s:%s)\n", t->desc, t->ctx->name, t->ops->name);
+ ksft_print_msg("\nRun test: %s (%s:%s)\n", t->desc, t->ctx->name, t->ops->name);
t->fn(t->ctx, t->ops);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 15/55] selftests/mm: ksm_tests: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (13 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 14/55] selftests/mm: khugepaged: use ksefltest framework Mike Rapoport
@ 2026-05-11 16:27 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 16/55] selftests/mm: protection_keys: use descriptive test names in the output Mike Rapoport
` (40 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:27 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert ksm_tests to use kselftest framework for reporting and tracking
successful and failing runs.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/ksm_tests.c | 180 +++++++++++--------------
1 file changed, 81 insertions(+), 99 deletions(-)
diff --git a/tools/testing/selftests/mm/ksm_tests.c b/tools/testing/selftests/mm/ksm_tests.c
index a0b48b839d54..0a5b38d3281c 100644
--- a/tools/testing/selftests/mm/ksm_tests.c
+++ b/tools/testing/selftests/mm/ksm_tests.c
@@ -175,12 +175,12 @@ static void *allocate_memory(void *ptr, int prot, int mapping, char data, size_
void *map_ptr = mmap(ptr, map_size, PROT_WRITE, mapping, -1, 0);
if (!map_ptr) {
- perror("mmap");
+ ksft_perror("mmap");
return NULL;
}
memset(map_ptr, data, map_size);
if (mprotect(map_ptr, map_size, prot)) {
- perror("mprotect");
+ ksft_perror("mprotect");
munmap(map_ptr, map_size);
return NULL;
}
@@ -201,11 +201,11 @@ static int ksm_do_scan(int scan_count, struct timespec start_time, int timeout)
if (ksm_read_sysfs(KSM_FP("full_scans"), &cur_scan))
return 1;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &cur_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return 1;
}
if ((cur_time.tv_sec - start_time.tv_sec) > timeout) {
- printf("Scan time limit exceeded\n");
+ ksft_print_msg("Scan time limit exceeded\n");
return 1;
}
}
@@ -218,12 +218,12 @@ static int ksm_merge_pages(int merge_type, void *addr, size_t size,
{
if (merge_type == KSM_MERGE_MADVISE) {
if (madvise(addr, size, MADV_MERGEABLE)) {
- perror("madvise");
+ ksft_perror("madvise");
return 1;
}
} else if (merge_type == KSM_MERGE_PRCTL) {
if (prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0)) {
- perror("prctl");
+ ksft_perror("prctl");
return 1;
}
}
@@ -242,7 +242,7 @@ static int ksm_unmerge_pages(void *addr, size_t size,
struct timespec start_time, int timeout)
{
if (madvise(addr, size, MADV_UNMERGEABLE)) {
- perror("madvise");
+ ksft_perror("madvise");
return 1;
}
return 0;
@@ -324,7 +324,7 @@ static int check_ksm_merge(int merge_type, int mapping, int prot,
struct timespec start_time;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
@@ -338,7 +338,6 @@ static int check_ksm_merge(int merge_type, int mapping, int prot,
/* verify that the right number of pages are merged */
if (assert_ksm_pages_count(page_count)) {
- printf("OK\n");
munmap(map_ptr, page_size * page_count);
if (merge_type == KSM_MERGE_PRCTL)
prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0);
@@ -346,7 +345,6 @@ static int check_ksm_merge(int merge_type, int mapping, int prot,
}
err_out:
- printf("Not OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_FAIL;
}
@@ -358,7 +356,7 @@ static int check_ksm_unmerge(int merge_type, int mapping, int prot, int timeout,
int page_count = 2;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
@@ -380,13 +378,11 @@ static int check_ksm_unmerge(int merge_type, int mapping, int prot, int timeout,
/* check that unmerging was successful and 0 pages are currently merged */
if (assert_ksm_pages_count(0)) {
- printf("OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_PASS;
}
err_out:
- printf("Not OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_FAIL;
}
@@ -398,7 +394,7 @@ static int check_ksm_zero_page_merge(int merge_type, int mapping, int prot, long
struct timespec start_time;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
@@ -425,12 +421,10 @@ static int check_ksm_zero_page_merge(int merge_type, int mapping, int prot, long
else if (!use_zero_pages && !assert_ksm_pages_count(page_count))
goto err_out;
- printf("OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_PASS;
err_out:
- printf("Not OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_FAIL;
}
@@ -465,16 +459,16 @@ static int check_ksm_numa_merge(int merge_type, int mapping, int prot, int timeo
int first_node;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
if (numa_available() < 0) {
- perror("NUMA support not enabled");
+ ksft_print_msg("NUMA support not enabled\n");
return KSFT_SKIP;
}
if (numa_num_configured_nodes() <= 1) {
- printf("At least 2 NUMA nodes must be available\n");
+ ksft_print_msg("At least 2 NUMA nodes must be available\n");
return KSFT_SKIP;
}
if (ksm_write_sysfs(KSM_FP("merge_across_nodes"), merge_across_nodes))
@@ -485,7 +479,7 @@ static int check_ksm_numa_merge(int merge_type, int mapping, int prot, int timeo
numa1_map_ptr = numa_alloc_onnode(page_size, first_node);
numa2_map_ptr = numa_alloc_onnode(page_size, get_next_mem_node(first_node));
if (!numa1_map_ptr || !numa2_map_ptr) {
- perror("numa_alloc_onnode");
+ ksft_perror("numa_alloc_onnode");
return KSFT_FAIL;
}
@@ -510,13 +504,11 @@ static int check_ksm_numa_merge(int merge_type, int mapping, int prot, int timeo
numa_free(numa1_map_ptr, page_size);
numa_free(numa2_map_ptr, page_size);
- printf("OK\n");
return KSFT_PASS;
err_out:
numa_free(numa1_map_ptr, page_size);
numa_free(numa2_map_ptr, page_size);
- printf("Not OK\n");
return KSFT_FAIL;
}
@@ -529,7 +521,7 @@ static int ksm_merge_hugepages_time(int merge_type, int mapping, int prot,
int pagemap_fd, n_normal_pages, n_huge_pages;
if (!thp_is_enabled()) {
- printf("Transparent Hugepages not available\n");
+ ksft_print_msg("Transparent Hugepages not available\n");
return KSFT_SKIP;
}
@@ -559,36 +551,35 @@ static int ksm_merge_hugepages_time(int merge_type, int mapping, int prot,
else
n_huge_pages++;
}
- printf("Number of normal pages: %d\n", n_normal_pages);
- printf("Number of huge pages: %d\n", n_huge_pages);
+ ksft_print_msg("Number of normal pages: %d\n", n_normal_pages);
+ ksft_print_msg("Number of huge pages: %d\n", n_huge_pages);
memset(map_ptr, '*', len);
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
if (ksm_merge_pages(merge_type, map_ptr, map_size, start_time, timeout))
goto err_out;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
scan_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
(end_time.tv_nsec - start_time.tv_nsec);
- printf("Total size: %lu MiB\n", map_size / MB);
- printf("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
+ ksft_print_msg("Total size: %lu MiB\n", map_size / MB);
+ ksft_print_msg("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
scan_time_ns % NSEC_PER_SEC);
- printf("Average speed: %.3f MiB/s\n", (map_size / MB) /
+ ksft_print_msg("Average speed: %.3f MiB/s\n", (map_size / MB) /
((double)scan_time_ns / NSEC_PER_SEC));
munmap(map_ptr_orig, len + HPAGE_SIZE);
return KSFT_PASS;
err_out:
- printf("Not OK\n");
munmap(map_ptr_orig, len + HPAGE_SIZE);
return KSFT_FAIL;
}
@@ -606,30 +597,29 @@ static int ksm_merge_time(int merge_type, int mapping, int prot, int timeout, si
return KSFT_FAIL;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
if (ksm_merge_pages(merge_type, map_ptr, map_size, start_time, timeout))
goto err_out;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
scan_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
(end_time.tv_nsec - start_time.tv_nsec);
- printf("Total size: %lu MiB\n", map_size / MB);
- printf("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
+ ksft_print_msg("Total size: %lu MiB\n", map_size / MB);
+ ksft_print_msg("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
scan_time_ns % NSEC_PER_SEC);
- printf("Average speed: %.3f MiB/s\n", (map_size / MB) /
+ ksft_print_msg("Average speed: %.3f MiB/s\n", (map_size / MB) /
((double)scan_time_ns / NSEC_PER_SEC));
munmap(map_ptr, map_size);
return KSFT_PASS;
err_out:
- printf("Not OK\n");
munmap(map_ptr, map_size);
return KSFT_FAIL;
}
@@ -646,37 +636,36 @@ static int ksm_unmerge_time(int merge_type, int mapping, int prot, int timeout,
if (!map_ptr)
return KSFT_FAIL;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
if (ksm_merge_pages(merge_type, map_ptr, map_size, start_time, timeout))
goto err_out;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
if (ksm_unmerge_pages(map_ptr, map_size, start_time, timeout))
goto err_out;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
scan_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
(end_time.tv_nsec - start_time.tv_nsec);
- printf("Total size: %lu MiB\n", map_size / MB);
- printf("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
+ ksft_print_msg("Total size: %lu MiB\n", map_size / MB);
+ ksft_print_msg("Total time: %ld.%09ld s\n", scan_time_ns / NSEC_PER_SEC,
scan_time_ns % NSEC_PER_SEC);
- printf("Average speed: %.3f MiB/s\n", (map_size / MB) /
+ ksft_print_msg("Average speed: %.3f MiB/s\n", (map_size / MB) /
((double)scan_time_ns / NSEC_PER_SEC));
munmap(map_ptr, map_size);
return KSFT_PASS;
err_out:
- printf("Not OK\n");
munmap(map_ptr, map_size);
return KSFT_FAIL;
}
@@ -695,24 +684,24 @@ static int ksm_cow_time(int merge_type, int mapping, int prot, int timeout, size
return KSFT_FAIL;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
for (size_t i = 0; i < page_count - 1; i = i + 2)
memset(map_ptr + page_size * i, '-', 1);
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
return KSFT_FAIL;
}
cow_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
(end_time.tv_nsec - start_time.tv_nsec);
- printf("Total size: %lu MiB\n\n", (page_size * page_count) / MB);
- printf("Not merged pages:\n");
- printf("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
+ ksft_print_msg("Total size: %lu MiB\n\n", (page_size * page_count) / MB);
+ ksft_print_msg("Not merged pages:\n");
+ ksft_print_msg("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
cow_time_ns % NSEC_PER_SEC);
- printf("Average speed: %.3f MiB/s\n\n", ((page_size * (page_count / 2)) / MB) /
+ ksft_print_msg("Average speed: %.3f MiB/s\n\n", ((page_size * (page_count / 2)) / MB) /
((double)cow_time_ns / NSEC_PER_SEC));
/* Create 2000 pairs of duplicate pages */
@@ -724,30 +713,29 @@ static int ksm_cow_time(int merge_type, int mapping, int prot, int timeout, size
goto err_out;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
for (size_t i = 0; i < page_count - 1; i = i + 2)
memset(map_ptr + page_size * i, '-', 1);
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_time)) {
- perror("clock_gettime");
+ ksft_perror("clock_gettime");
goto err_out;
}
cow_time_ns = (end_time.tv_sec - start_time.tv_sec) * NSEC_PER_SEC +
(end_time.tv_nsec - start_time.tv_nsec);
- printf("Merged pages:\n");
- printf("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
+ ksft_print_msg("Merged pages:\n");
+ ksft_print_msg("Total time: %ld.%09ld s\n", cow_time_ns / NSEC_PER_SEC,
cow_time_ns % NSEC_PER_SEC);
- printf("Average speed: %.3f MiB/s\n", ((page_size * (page_count / 2)) / MB) /
+ ksft_print_msg("Average speed: %.3f MiB/s\n", ((page_size * (page_count / 2)) / MB) /
((double)cow_time_ns / NSEC_PER_SEC));
munmap(map_ptr, page_size * page_count);
return KSFT_PASS;
err_out:
- printf("Not OK\n");
munmap(map_ptr, page_size * page_count);
return KSFT_FAIL;
}
@@ -765,6 +753,10 @@ int main(int argc, char *argv[])
bool use_zero_pages = KSM_USE_ZERO_PAGES_DEFAULT;
bool merge_across_nodes = KSM_MERGE_ACROSS_NODES_DEFAULT;
long size_MB = 0;
+ const char *test_descr = "KSM merging";
+
+ ksft_print_header();
+ ksft_set_plan(1);
while ((opt = getopt(argc, argv, "dha:p:l:z:m:s:t:MUZNPCHD")) != -1) {
switch (opt) {
@@ -773,17 +765,13 @@ int main(int argc, char *argv[])
break;
case 'p':
page_count = atol(optarg);
- if (page_count <= 0) {
- printf("The number of pages must be greater than 0\n");
- return KSFT_FAIL;
- }
+ if (page_count <= 0)
+ ksft_exit_fail_msg("The number of pages must be greater than 0\n");
break;
case 'l':
ksm_scan_limit_sec = atoi(optarg);
- if (ksm_scan_limit_sec <= 0) {
- printf("Timeout value must be greater than 0\n");
- return KSFT_FAIL;
- }
+ if (ksm_scan_limit_sec <= 0)
+ ksft_exit_fail_msg("Timeout value must be greater than 0\n");
break;
case 'h':
print_help();
@@ -805,19 +793,15 @@ int main(int argc, char *argv[])
break;
case 's':
size_MB = atoi(optarg);
- if (size_MB <= 0) {
- printf("Size must be greater than 0\n");
- return KSFT_FAIL;
- }
+ if (size_MB <= 0)
+ ksft_exit_fail_msg("Size must be greater than 0\n");
break;
case 't':
{
int tmp = atoi(optarg);
- if (tmp < 0 || tmp > KSM_MERGE_LAST) {
- printf("Invalid merge type\n");
- return KSFT_FAIL;
- }
+ if (tmp < 0 || tmp > KSM_MERGE_LAST)
+ ksft_exit_fail_msg("Invalid merge type\n");
merge_type = tmp;
}
break;
@@ -845,82 +829,80 @@ int main(int argc, char *argv[])
test_name = KSM_COW_TIME;
break;
default:
- return KSFT_FAIL;
+ ksft_exit_fail_msg("Unknown option\n");
}
}
if (prot == 0)
prot = str_to_prot(KSM_PROT_STR_DEFAULT);
- if (access(KSM_SYSFS_PATH, F_OK)) {
- printf("Config KSM not enabled\n");
- return KSFT_SKIP;
- }
+ if (access(KSM_SYSFS_PATH, F_OK))
+ ksft_exit_skip("Config KSM not enabled\n");
- if (ksm_save_def(&ksm_sysfs_old)) {
- printf("Cannot save default tunables\n");
- return KSFT_FAIL;
- }
+ if (ksm_save_def(&ksm_sysfs_old))
+ ksft_exit_fail_msg("Cannot save default tunables\n");
if (ksm_write_sysfs(KSM_FP("run"), 2) ||
ksm_write_sysfs(KSM_FP("sleep_millisecs"), 0) ||
numa_available() ? 0 :
ksm_write_sysfs(KSM_FP("merge_across_nodes"), 1) ||
ksm_write_sysfs(KSM_FP("pages_to_scan"), page_count))
- return KSFT_FAIL;
+ ksft_exit_fail_msg("Cannot set up KSM tunables\n");
switch (test_name) {
case CHECK_KSM_MERGE:
+ test_descr = "KSM merging";
ret = check_ksm_merge(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot, page_count,
ksm_scan_limit_sec, page_size);
break;
case CHECK_KSM_UNMERGE:
+ test_descr = "KSM unmerging";
ret = check_ksm_unmerge(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, page_size);
break;
case CHECK_KSM_ZERO_PAGE_MERGE:
+ test_descr = "KSM zero page merging";
ret = check_ksm_zero_page_merge(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
page_count, ksm_scan_limit_sec, use_zero_pages,
page_size);
break;
case CHECK_KSM_NUMA_MERGE:
+ test_descr = "KSM NUMA merging";
ret = check_ksm_numa_merge(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, merge_across_nodes, page_size);
break;
case KSM_MERGE_TIME:
- if (size_MB == 0) {
- printf("Option '-s' is required.\n");
- return KSFT_FAIL;
- }
+ if (size_MB == 0)
+ ksft_exit_fail_msg("Option '-s' is required\n");
+ test_descr = "KSM merge time";
ret = ksm_merge_time(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, size_MB);
break;
case KSM_MERGE_TIME_HUGE_PAGES:
- if (size_MB == 0) {
- printf("Option '-s' is required.\n");
- return KSFT_FAIL;
- }
+ if (size_MB == 0)
+ ksft_exit_fail_msg("Option '-s' is required\n");
+ test_descr = "KSM merge time with huge pages";
ret = ksm_merge_hugepages_time(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, size_MB);
break;
case KSM_UNMERGE_TIME:
- if (size_MB == 0) {
- printf("Option '-s' is required.\n");
- return KSFT_FAIL;
- }
+ if (size_MB == 0)
+ ksft_exit_fail_msg("Option '-s' is required\n");
+ test_descr = "KSM unmerge time";
ret = ksm_unmerge_time(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, size_MB);
break;
case KSM_COW_TIME:
+ test_descr = "KSM COW time";
ret = ksm_cow_time(merge_type, MAP_PRIVATE | MAP_ANONYMOUS, prot,
ksm_scan_limit_sec, page_size);
break;
}
- if (ksm_restore(&ksm_sysfs_old)) {
- printf("Cannot restore default tunables\n");
- return KSFT_FAIL;
- }
+ if (ksm_restore(&ksm_sysfs_old))
+ ksft_print_msg("Cannot restore default tunables\n");
+
+ ksft_test_result_report(ret, "%s\n", test_descr);
- return ret;
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 16/55] selftests/mm: protection_keys: use descriptive test names in the output
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (14 preceding siblings ...)
2026-05-11 16:27 ` [PATCH v4 15/55] selftests/mm: ksm_tests: use kselftest framework Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 17/55] selftests/mm: protection_keys: use kselftest framework Mike Rapoport
` (39 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Replace the numeric test index in TAP output with the actual test
function name.
Use a structure containing function pointer and its name rather than
only the function pointer in the pkey_tests array.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/protection_keys.c | 55 +++++++++++---------
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index 2085982dba69..80c6124e8378 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -1692,29 +1692,36 @@ static void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
pkey_assert(sret < 0);
}
-static void (*pkey_tests[])(int *ptr, u16 pkey) = {
- test_read_of_write_disabled_region,
- test_read_of_access_disabled_region,
- test_read_of_access_disabled_region_with_page_already_mapped,
- test_write_of_write_disabled_region,
- test_write_of_write_disabled_region_with_page_already_mapped,
- test_write_of_access_disabled_region,
- test_write_of_access_disabled_region_with_page_already_mapped,
- test_kernel_write_of_access_disabled_region,
- test_kernel_write_of_write_disabled_region,
- test_kernel_gup_of_access_disabled_region,
- test_kernel_gup_write_to_write_disabled_region,
- test_executing_on_unreadable_memory,
- test_implicit_mprotect_exec_only_memory,
- test_mprotect_with_pkey_0,
- test_ptrace_of_child,
- test_pkey_init_state,
- test_pkey_syscalls_on_non_allocated_pkey,
- test_pkey_syscalls_bad_args,
- test_pkey_alloc_exhaust,
- test_pkey_alloc_free_attach_pkey0,
+struct pkey_test {
+ void (*func)(int *ptr, u16 pkey);
+ const char *name;
+};
+
+#define PKEY_TEST(fn) { fn, #fn }
+
+static struct pkey_test pkey_tests[] = {
+ PKEY_TEST(test_read_of_write_disabled_region),
+ PKEY_TEST(test_read_of_access_disabled_region),
+ PKEY_TEST(test_read_of_access_disabled_region_with_page_already_mapped),
+ PKEY_TEST(test_write_of_write_disabled_region),
+ PKEY_TEST(test_write_of_write_disabled_region_with_page_already_mapped),
+ PKEY_TEST(test_write_of_access_disabled_region),
+ PKEY_TEST(test_write_of_access_disabled_region_with_page_already_mapped),
+ PKEY_TEST(test_kernel_write_of_access_disabled_region),
+ PKEY_TEST(test_kernel_write_of_write_disabled_region),
+ PKEY_TEST(test_kernel_gup_of_access_disabled_region),
+ PKEY_TEST(test_kernel_gup_write_to_write_disabled_region),
+ PKEY_TEST(test_executing_on_unreadable_memory),
+ PKEY_TEST(test_implicit_mprotect_exec_only_memory),
+ PKEY_TEST(test_mprotect_with_pkey_0),
+ PKEY_TEST(test_ptrace_of_child),
+ PKEY_TEST(test_pkey_init_state),
+ PKEY_TEST(test_pkey_syscalls_on_non_allocated_pkey),
+ PKEY_TEST(test_pkey_syscalls_bad_args),
+ PKEY_TEST(test_pkey_alloc_exhaust),
+ PKEY_TEST(test_pkey_alloc_free_attach_pkey0),
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
- test_ptrace_modifies_pkru,
+ PKEY_TEST(test_ptrace_modifies_pkru),
#endif
};
@@ -1735,7 +1742,7 @@ static void run_tests_once(void)
dprintf1("test %d starting with pkey: %d\n", test_nr, pkey);
ptr = malloc_pkey(PAGE_SIZE, prot, pkey);
dprintf1("test %d starting...\n", test_nr);
- pkey_tests[test_nr](ptr, pkey);
+ pkey_tests[test_nr].func(ptr, pkey);
dprintf1("freeing test memory: %p\n", ptr);
free_pkey_malloc(ptr);
sys_pkey_free(pkey);
@@ -1746,7 +1753,7 @@ static void run_tests_once(void)
tracing_off();
close_test_fds();
- printf("test %2d PASSED (iteration %d)\n", test_nr, iteration_nr);
+ printf("test %s PASSED (iteration %d)\n", pkey_tests[test_nr].name, iteration_nr);
dprintf1("======================\n\n");
}
iteration_nr++;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 17/55] selftests/mm: protection_keys: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (15 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 16/55] selftests/mm: protection_keys: use descriptive test names in the output Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 18/55] selftests/mm: uffd-common: " Mike Rapoport
` (38 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert protection_keys test to use kselftest framework for reporting
and tracking successful and failing runs.
Adjust dprintf0() printouts to use "#" in the beginning of the line for
TAP compatibility.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/pkey-helpers.h | 15 +++++------
tools/testing/selftests/mm/protection_keys.c | 26 +++++++++++---------
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey-helpers.h b/tools/testing/selftests/mm/pkey-helpers.h
index 7c29f075e40b..2c377f4e9df1 100644
--- a/tools/testing/selftests/mm/pkey-helpers.h
+++ b/tools/testing/selftests/mm/pkey-helpers.h
@@ -71,13 +71,14 @@ static inline void sigsafe_printf(const char *format, ...)
extern void abort_hooks(void);
#define pkey_assert(condition) do { \
if (!(condition)) { \
- dprintf0("assert() at %s::%d test_nr: %d iteration: %d\n", \
- __FILE__, __LINE__, \
- test_nr, iteration_nr); \
- dprintf0("errno at assert: %d", errno); \
- abort_hooks(); \
- exit(__LINE__); \
- } \
+ dprintf0("# assert() at %s::%d test_nr: %d iteration: %d\n", \
+ __FILE__, __LINE__, \
+ test_nr, iteration_nr); \
+ dprintf0("# errno at assert: %d\n", errno); \
+ abort_hooks(); \
+ ksft_exit_fail_msg("test %d (iteration %d)\n", \
+ test_nr, iteration_nr); \
+ } \
} while (0)
#define barrier() __asm__ __volatile__("": : :"memory")
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index 80c6124e8378..d617b41dda6b 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -136,6 +136,7 @@ static void tracing_off(void)
void abort_hooks(void)
{
+ fflush(stdout);
fprintf(stderr, "running %s()...\n", __func__);
tracing_off();
#ifdef SLEEP_ON_ABORT
@@ -370,8 +371,8 @@ static void signal_handler(int signum, siginfo_t *si, void *vucontext)
if ((si->si_code == SEGV_MAPERR) ||
(si->si_code == SEGV_ACCERR) ||
(si->si_code == SEGV_BNDERR)) {
- printf("non-PK si_code, exiting...\n");
- exit(4);
+ dprintf0("# non-PK si_code: %d, exiting...\n", si->si_code);
+ exit(1);
}
si_pkey_ptr = siginfo_get_pkey_ptr(si);
@@ -719,7 +720,7 @@ static void setup_hugetlbfs(void)
long hpagesz_mb;
if (geteuid() != 0) {
- fprintf(stderr, "WARNING: not run as root, can not do hugetlb test\n");
+ ksft_print_msg("WARNING: not run as root, can not do hugetlb test\n");
return;
}
@@ -855,7 +856,7 @@ void expected_pkey_fault(int pkey)
#define do_not_expect_pkey_fault(msg) do { \
if (last_pkey_faults != pkey_faults) \
- dprintf0("unexpected PKey fault: %s\n", msg); \
+ dprintf0("# unexpected PKey fault: %s\n", msg); \
pkey_assert(last_pkey_faults == pkey_faults); \
} while (0)
@@ -1753,7 +1754,7 @@ static void run_tests_once(void)
tracing_off();
close_test_fds();
- printf("test %s PASSED (iteration %d)\n", pkey_tests[test_nr].name, iteration_nr);
+ ksft_test_result_pass("test %s (iteration %d)\n", pkey_tests[test_nr].name, iteration_nr);
dprintf1("======================\n\n");
}
iteration_nr++;
@@ -1773,27 +1774,30 @@ int main(void)
setup_handlers();
- printf("has pkeys: %d\n", pkeys_supported);
+ ksft_print_header();
if (!pkeys_supported) {
int size = PAGE_SIZE;
int *ptr;
- printf("running PKEY tests for unsupported CPU/OS\n");
+ ksft_set_plan(1);
+ ksft_print_msg("running PKEY tests for unsupported CPU/OS\n");
ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
assert(ptr != (void *)-1);
test_mprotect_pkey_on_unsupported_cpu(ptr, 1);
- exit(0);
+ ksft_test_result_pass("pkey on unsupported CPU/OS\n");
+ ksft_finished();
}
+ ksft_set_plan(ARRAY_SIZE(pkey_tests) * nr_iterations);
+
pkey_setup_shadow();
- printf("startup pkey_reg: %016llx\n", read_pkey_reg());
+ ksft_print_msg("startup pkey_reg: %016llx\n", read_pkey_reg());
setup_hugetlbfs();
while (nr_iterations-- > 0)
run_tests_once();
- printf("done (all tests OK)\n");
- return 0;
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 18/55] selftests/mm: uffd-common: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (16 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 17/55] selftests/mm: protection_keys: use kselftest framework Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 19/55] selftests/mm: uffd-stress: " Mike Rapoport
` (37 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Update err() and errexit() to use ksft_print_msg() and ksft_exit_fail().
This is preparatory change required to update userfaulfd tests to use
kselftest framework.
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-common.h | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-common.h b/tools/testing/selftests/mm/uffd-common.h
index 844a85ab31eb..0723843a7626 100644
--- a/tools/testing/selftests/mm/uffd-common.h
+++ b/tools/testing/selftests/mm/uffd-common.h
@@ -40,21 +40,20 @@
#define UFFD_FLAGS (O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY)
-#define _err(fmt, ...) \
- do { \
- int ret = errno; \
- fprintf(stderr, "ERROR: " fmt, ##__VA_ARGS__); \
- fprintf(stderr, " (errno=%d, @%s:%d)\n", \
- ret, __FILE__, __LINE__); \
+#define _err(fmt, ...) \
+ do { \
+ int ret = errno; \
+ ksft_print_msg("ERROR: " fmt " (errno=%d, @%s:%d)\n", \
+ ##__VA_ARGS__, ret, __FILE__, __LINE__); \
} while (0)
-#define errexit(exitcode, fmt, ...) \
+#define errexit(fmt, ...) \
do { \
_err(fmt, ##__VA_ARGS__); \
- exit(exitcode); \
+ ksft_exit_fail(); \
} while (0)
-#define err(fmt, ...) errexit(1, fmt, ##__VA_ARGS__)
+#define err(fmt, ...) errexit(fmt, ##__VA_ARGS__)
struct uffd_global_test_opts {
unsigned long nr_parallel, nr_pages, nr_pages_per_cpu, page_size;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 19/55] selftests/mm: uffd-stress: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (17 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 18/55] selftests/mm: uffd-common: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 20/55] selftests/mm: uffd-unit-tests: " Mike Rapoport
` (36 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert uffd-stress test to use kselftest framework for reporting and
tracking successful and failing runs.
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-stress.c | 40 +++++++++++-------------
1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-stress.c b/tools/testing/selftests/mm/uffd-stress.c
index 700fbaa18d44..0ce493dac354 100644
--- a/tools/testing/selftests/mm/uffd-stress.c
+++ b/tools/testing/selftests/mm/uffd-stress.c
@@ -286,18 +286,12 @@ static int userfaultfd_stress(uffd_global_test_opts_t *gopts)
pthread_attr_setstacksize(&attr, 16*1024*1024);
while (bounces--) {
- printf("bounces: %d, mode:", bounces);
- if (bounces & BOUNCE_RANDOM)
- printf(" rnd");
- if (bounces & BOUNCE_RACINGFAULTS)
- printf(" racing");
- if (bounces & BOUNCE_VERIFY)
- printf(" ver");
- if (bounces & BOUNCE_POLL)
- printf(" poll");
- else
- printf(" read");
- printf(", ");
+ ksft_print_msg("bounces: %d, mode:%s%s%s%s, ",
+ bounces,
+ bounces & BOUNCE_RANDOM ? " rnd" : "",
+ bounces & BOUNCE_RACINGFAULTS ? " racing" : "",
+ bounces & BOUNCE_VERIFY ? " ver" : "",
+ bounces & BOUNCE_POLL ? " poll" : " read");
fflush(stdout);
if (bounces & BOUNCE_POLL)
@@ -461,6 +455,9 @@ int main(int argc, char **argv)
if (argc < 4)
usage();
+ ksft_print_header();
+ ksft_set_plan(1);
+
if (signal(SIGALRM, sigalrm) == SIG_ERR)
err("failed to arm SIGALRM");
alarm(ALARM_INTERVAL_SECS);
@@ -484,10 +481,8 @@ int main(int argc, char **argv)
* for racy extra reservation of hugepages.
*/
if (gopts->test_type == TEST_HUGETLB &&
- get_free_hugepages() < 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1) {
- printf("skip: Skipping userfaultfd... not enough hugepages\n");
- return KSFT_SKIP;
- }
+ get_free_hugepages() < 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1)
+ ksft_exit_skip("Skipping userfaultfd... not enough hugepages\n");
gopts->nr_pages_per_cpu = bytes / gopts->page_size / gopts->nr_parallel;
if (!gopts->nr_pages_per_cpu) {
@@ -503,9 +498,12 @@ int main(int argc, char **argv)
}
gopts->nr_pages = gopts->nr_pages_per_cpu * gopts->nr_parallel;
- printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
- gopts->nr_pages, gopts->nr_pages_per_cpu);
- return userfaultfd_stress(gopts);
+ ksft_print_msg("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
+ gopts->nr_pages, gopts->nr_pages_per_cpu);
+
+ ksft_test_result(!userfaultfd_stress(gopts),
+ "uffd-stress %s\n", argv[1]);
+ ksft_finished();
}
#else /* __NR_userfaultfd */
@@ -514,8 +512,8 @@ int main(int argc, char **argv)
int main(void)
{
- printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n");
- return KSFT_SKIP;
+ ksft_print_header();
+ ksft_exit_skip("missing __NR_userfaultfd definition\n");
}
#endif /* __NR_userfaultfd */
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 20/55] selftests/mm: uffd-unit-tests: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (18 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 19/55] selftests/mm: uffd-stress: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 21/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
` (35 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert uffd-unit-tests to use kselftest framework for reporting and
tracking successful and failing runs.
Reviewed-by: Donet Tom <donettom@linux.ibm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-unit-tests.c | 105 +++++++++----------
1 file changed, 52 insertions(+), 53 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c
index 6f5e404a446c..db7c26835487 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -86,47 +86,28 @@ typedef struct {
uffd_test_case_ops_t *test_case_ops;
} uffd_test_case_t;
-static void uffd_test_report(void)
-{
- printf("Userfaults unit tests: pass=%u, skip=%u, fail=%u (total=%u)\n",
- ksft_get_pass_cnt(),
- ksft_get_xskip_cnt(),
- ksft_get_fail_cnt(),
- ksft_test_num());
-}
+static char current_test[256];
static void uffd_test_pass(void)
{
- printf("done\n");
- ksft_inc_pass_cnt();
+ ksft_test_result_pass("%s\n", current_test);
}
#define uffd_test_start(...) do { \
- printf("Testing "); \
- printf(__VA_ARGS__); \
- printf("... "); \
- fflush(stdout); \
+ snprintf(current_test, sizeof(current_test), __VA_ARGS__); \
} while (0)
-#define uffd_test_fail(...) do { \
- printf("failed [reason: "); \
- printf(__VA_ARGS__); \
- printf("]\n"); \
- ksft_inc_fail_cnt(); \
+#define uffd_test_fail(fmt, ...) do { \
+ ksft_print_msg("failed reason: [" fmt "]\n", ##__VA_ARGS__); \
+ ksft_test_result_fail("%s\n", current_test); \
} while (0)
static void uffd_test_skip(const char *message)
{
- printf("skipped [reason: %s]\n", message);
- ksft_inc_xskip_cnt();
+ ksft_test_result_skip("%s (%s)\n", current_test, message);
}
-/*
- * Returns 1 if specific userfaultfd supported, 0 otherwise. Note, we'll
- * return 1 even if some test failed as long as uffd supported, because in
- * that case we still want to proceed with the rest uffd unit tests.
- */
-static int test_uffd_api(bool use_dev)
+static void test_uffd_api(bool use_dev)
{
struct uffdio_api uffdio_api;
int uffd;
@@ -140,7 +121,7 @@ static int test_uffd_api(bool use_dev)
uffd = uffd_open_sys(UFFD_FLAGS);
if (uffd < 0) {
uffd_test_skip("cannot open userfaultfd handle");
- return 0;
+ return;
}
/* Test wrong UFFD_API */
@@ -177,8 +158,6 @@ static int test_uffd_api(bool use_dev)
uffd_test_pass();
out:
close(uffd);
- /* We have a valid uffd handle */
- return 1;
}
@@ -1701,6 +1680,26 @@ static void usage(const char *prog)
exit(KSFT_FAIL);
}
+static int uffd_count_tests(int n_tests, int n_mems, const char *test_filter)
+{
+ uffd_test_case_t *test;
+ int i, j, count = 0;
+
+ if (!test_filter)
+ count += 2; /* test_uffd_api(false) + test_uffd_api(true) */
+
+ for (i = 0; i < n_tests; i++) {
+ test = &uffd_tests[i];
+ if (test_filter && !strstr(test->name, test_filter))
+ continue;
+ for (j = 0; j < n_mems; j++)
+ if (test->mem_targets & mem_types[j].mem_flag)
+ count++;
+ }
+
+ return count;
+}
+
int main(int argc, char *argv[])
{
int n_tests = sizeof(uffd_tests) / sizeof(uffd_test_case_t);
@@ -1711,8 +1710,7 @@ int main(int argc, char *argv[])
mem_type_t *mem_type;
uffd_test_args_t args;
const char *errmsg;
- int has_uffd, opt;
- int i, j;
+ int i, j, opt;
while ((opt = getopt(argc, argv, "f:hl")) != -1) {
switch (opt) {
@@ -1730,24 +1728,28 @@ int main(int argc, char *argv[])
}
}
- if (!test_filter && !list_only) {
- has_uffd = test_uffd_api(false);
- has_uffd |= test_uffd_api(true);
-
- if (!has_uffd) {
- printf("Userfaultfd not supported or unprivileged, skip all tests\n");
- exit(KSFT_SKIP);
+ if (list_only) {
+ for (i = 0; i < n_tests; i++) {
+ test = &uffd_tests[i];
+ if (test_filter && !strstr(test->name, test_filter))
+ continue;
+ printf("%s\n", test->name);
}
+ return KSFT_PASS;
+ }
+
+ ksft_print_header();
+ ksft_set_plan(uffd_count_tests(n_tests, n_mems, test_filter));
+
+ if (!test_filter) {
+ test_uffd_api(false);
+ test_uffd_api(true);
}
for (i = 0; i < n_tests; i++) {
test = &uffd_tests[i];
if (test_filter && !strstr(test->name, test_filter))
continue;
- if (list_only) {
- printf("%s\n", test->name);
- continue;
- }
for (j = 0; j < n_mems; j++) {
mem_type = &mem_types[j];
@@ -1758,6 +1760,10 @@ int main(int argc, char *argv[])
uffd_test_ops = mem_type->mem_ops;
uffd_test_case_ops = test->test_case_ops;
+ if (!(test->mem_targets & mem_type->mem_flag))
+ continue;
+
+ uffd_test_start("%s on %s", test->name, mem_type->name);
if (mem_type->mem_flag & (MEM_HUGETLB_PRIVATE | MEM_HUGETLB)) {
gopts.page_size = default_huge_page_size();
if (gopts.page_size == 0) {
@@ -1777,10 +1783,6 @@ int main(int argc, char *argv[])
/* Initialize test arguments */
args.mem_type = mem_type;
- if (!(test->mem_targets & mem_type->mem_flag))
- continue;
-
- uffd_test_start("%s on %s", test->name, mem_type->name);
if (!uffd_feature_supported(test)) {
uffd_test_skip("feature missing");
continue;
@@ -1794,10 +1796,7 @@ int main(int argc, char *argv[])
}
}
- if (!list_only)
- uffd_test_report();
-
- return ksft_get_fail_cnt() ? KSFT_FAIL : KSFT_PASS;
+ ksft_finished();
}
#else /* __NR_userfaultfd */
@@ -1806,8 +1805,8 @@ int main(int argc, char *argv[])
int main(void)
{
- printf("Skipping %s (missing __NR_userfaultfd)\n", __file__);
- return KSFT_SKIP;
+ ksft_print_header();
+ ksft_exit_skip("missing __NR_userfaultfd definition\n");
}
#endif /* __NR_userfaultfd */
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 21/55] selftests/mm: va_high_addr_switch: use kselftest framework
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (19 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 20/55] selftests/mm: uffd-unit-tests: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 22/55] selftests/mm: add atexit() and signal handlers to thp_settings Mike Rapoport
` (34 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Convert va_high_addr_switch test to use kselftest framework for
reporting and tracking successful and failing runs.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../selftests/mm/va_high_addr_switch.c | 41 +++++++++----------
1 file changed, 20 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/mm/va_high_addr_switch.c b/tools/testing/selftests/mm/va_high_addr_switch.c
index 51401e081b20..5d38735ea60e 100644
--- a/tools/testing/selftests/mm/va_high_addr_switch.c
+++ b/tools/testing/selftests/mm/va_high_addr_switch.c
@@ -257,40 +257,35 @@ void testcases_init(void)
switch_hint = addr_switch_hint;
}
-static int run_test(struct testcase *test, int count)
+static void run_test(struct testcase *test, int count)
{
void *p;
- int i, ret = KSFT_PASS;
+ int i;
for (i = 0; i < count; i++) {
struct testcase *t = test + i;
p = mmap(t->addr, t->size, PROT_READ | PROT_WRITE, t->flags, -1, 0);
-
- printf("%s: %p - ", t->msg, p);
-
if (p == MAP_FAILED) {
- printf("FAILED\n");
- ret = KSFT_FAIL;
+ ksft_perror("MAP_FAILED");
+ ksft_test_result_fail("%s\n", t->msg);
continue;
}
if (t->low_addr_required && p >= (void *)(switch_hint)) {
- printf("FAILED\n");
- ret = KSFT_FAIL;
+ ksft_print_msg("%p not below switch hint\n", p);
+ ksft_test_result_fail("%s\n", t->msg);
} else {
/*
* Do a dereference of the address returned so that we catch
* bugs in page fault handling
*/
memset(p, 0, t->size);
- printf("OK\n");
+ ksft_test_result_pass("%s\n", t->msg);
}
if (!t->keep_mapped)
munmap(p, t->size);
}
-
- return ret;
}
#ifdef __aarch64__
@@ -322,19 +317,23 @@ static int supported_arch(void)
int main(int argc, char **argv)
{
- int ret, hugetlb_ret = KSFT_PASS;
+ bool run_hugetlb = false;
+
+ ksft_print_header();
if (!supported_arch())
- return KSFT_SKIP;
+ ksft_exit_skip("Architecture not supported\n");
+
+ if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
+ run_hugetlb = true;
testcases_init();
- ret = run_test(testcases, sz_testcases);
- if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
- hugetlb_ret = run_test(hugetlb_testcases, sz_hugetlb_testcases);
+ ksft_set_plan(sz_testcases + (run_hugetlb ? sz_hugetlb_testcases : 0));
+
+ run_test(testcases, sz_testcases);
+ if (run_hugetlb)
+ run_test(hugetlb_testcases, sz_hugetlb_testcases);
- if (ret == KSFT_PASS && hugetlb_ret == KSFT_PASS)
- return KSFT_PASS;
- else
- return KSFT_FAIL;
+ ksft_finished();
}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 22/55] selftests/mm: add atexit() and signal handlers to thp_settings
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (20 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 21/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 23/55] selftests/mm: rename thp_settings.[ch] to hugepage_settings.[ch] Mike Rapoport
` (33 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
khugepaged registers atexit() and signal handlers that ensure that THP
settings are restored regardless of how the test exited.
Make these handlers available for all users of thp_settings.
The call to thp_save_settings() installs thp_restore_settings as the
atexit() callback and makes sure that signals that kill a process would
still call exit() and atexit() callback.
Update child process in khugepaged tests using thp_settings to use
_exit() instead of exit() to avoid altering THP settings in the middle
of a test.
Remove redundant THP cleanup from folio_split_race_test.c.
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/cow.c | 21 ++++------
.../selftests/mm/folio_split_race_test.c | 23 -----------
tools/testing/selftests/mm/khugepaged.c | 41 ++-----------------
tools/testing/selftests/mm/thp_settings.c | 27 +++++++++++-
tools/testing/selftests/mm/uffd-wp-mremap.c | 4 --
5 files changed, 38 insertions(+), 78 deletions(-)
diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c
index d9c69c04b67d..6abdcb30aba8 100644
--- a/tools/testing/selftests/mm/cow.c
+++ b/tools/testing/selftests/mm/cow.c
@@ -202,7 +202,7 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect,
log_test_result(KSFT_FAIL);
goto close_comm_pipes;
} else if (!ret) {
- exit(fn(mem, size, &comm_pipes));
+ _exit(fn(mem, size, &comm_pipes));
}
while (read(comm_pipes.child_ready[0], &buf, 1) != 1)
@@ -333,7 +333,7 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,
;
/* Modify page content in the child. */
memset(mem, 0xff, size);
- exit(0);
+ _exit(0);
}
if (!before_fork) {
@@ -480,7 +480,7 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)
write(comm_pipes.child_ready[1], "0", 1);
while (read(comm_pipes.parent_ready[0], &buf, 1) != 1)
;
- exit(0);
+ _exit(0);
}
while (read(comm_pipes.child_ready[0], &buf, 1) != 1)
@@ -645,7 +645,7 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,
write(comm_pipes.child_ready[1], "0", 1);
while (read(comm_pipes.parent_ready[0], &buf, 1) != 1)
;
- exit(0);
+ _exit(0);
}
/* Wait until our child is ready. */
@@ -956,7 +956,7 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)
log_test_result(KSFT_FAIL);
goto munmap;
} else if (!ret) {
- exit(0);
+ _exit(0);
}
wait(&ret);
/* Allow for sharing all pages again. */
@@ -1347,13 +1347,13 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,
switch (test) {
case ANON_THP_COLLAPSE_UNSHARED:
case ANON_THP_COLLAPSE_FULLY_SHARED:
- exit(child_memcmp_fn(mem, size, &comm_pipes));
+ _exit(child_memcmp_fn(mem, size, &comm_pipes));
break;
case ANON_THP_COLLAPSE_LOWER_SHARED:
- exit(child_memcmp_fn(mem, size / 2, &comm_pipes));
+ _exit(child_memcmp_fn(mem, size / 2, &comm_pipes));
break;
case ANON_THP_COLLAPSE_UPPER_SHARED:
- exit(child_memcmp_fn(mem + size / 2, size / 2,
+ _exit(child_memcmp_fn(mem + size / 2, size / 2,
&comm_pipes));
break;
default:
@@ -1911,10 +1911,5 @@ int main(int argc, char **argv)
run_anon_thp_test_cases();
run_non_anon_test_cases();
- if (pmdsize) {
- /* Only if THP is supported. */
- thp_restore_settings();
- }
-
ksft_finished();
}
diff --git a/tools/testing/selftests/mm/folio_split_race_test.c b/tools/testing/selftests/mm/folio_split_race_test.c
index ff026f183ac7..390fd97c1bd9 100644
--- a/tools/testing/selftests/mm/folio_split_race_test.c
+++ b/tools/testing/selftests/mm/folio_split_race_test.c
@@ -226,23 +226,6 @@ static uint64_t run_iteration(void)
return reader_failures;
}
-static void thp_cleanup_handler(int signum)
-{
- thp_restore_settings();
- /*
- * Restore default handler and re-raise the signal to exit.
- * This is to ensure the test process exits with the correct
- * status code corresponding to the signal.
- */
- signal(signum, SIG_DFL);
- raise(signum);
-}
-
-static void thp_settings_cleanup(void)
-{
- thp_restore_settings();
-}
-
int main(void)
{
struct thp_settings current_settings;
@@ -261,12 +244,6 @@ int main(void)
ksft_exit_skip("Please run the test as root\n");
thp_save_settings();
- /* make sure thp settings are restored */
- if (atexit(thp_settings_cleanup) != 0)
- ksft_exit_fail_msg("atexit failed\n");
-
- signal(SIGINT, thp_cleanup_handler);
- signal(SIGTERM, thp_cleanup_handler);
thp_read_settings(¤t_settings);
current_settings.shmem_enabled = SHMEM_ADVISE;
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 3fd0693cc45d..712e8f194b3d 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -72,7 +72,6 @@ struct file_info {
};
static struct file_info finfo;
-static bool skip_settings_restore;
static int exit_status;
static void success(const char *msg)
@@ -93,26 +92,6 @@ static void skip(const char *msg)
exit_status = KSFT_SKIP;
}
-static void restore_settings_atexit(void)
-{
- if (skip_settings_restore)
- return;
-
- ksft_print_msg("Restore THP and khugepaged settings...");
- thp_restore_settings();
- success("OK");
-
- skip_settings_restore = true;
- ksft_print_cnts();
- exit(exit_status);
-}
-
-static void restore_settings(int sig)
-{
- /* exit() will invoke the restore_settings_atexit handler. */
- exit(sig ? KSFT_FAIL : exit_status);
-}
-
static void save_settings(void)
{
ksft_print_msg("Save THP and khugepaged settings...");
@@ -121,12 +100,6 @@ static void save_settings(void)
thp_save_settings();
success("OK");
-
- atexit(restore_settings_atexit);
- signal(SIGTERM, restore_settings);
- signal(SIGINT, restore_settings);
- signal(SIGHUP, restore_settings);
- signal(SIGQUIT, restore_settings);
}
static void get_finfo(const char *dir)
@@ -846,8 +819,6 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
ksft_print_msg("Share small page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
- skip_settings_restore = true;
-
if (ops->check_huge(p, 0))
success("OK");
else
@@ -859,7 +830,7 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
validate_memory(p, 0, page_size);
ops->cleanup_area(p, hpage_pmd_size);
- exit(exit_status);
+ _exit(exit_status);
}
wait(&wstatus);
@@ -884,8 +855,6 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o
ksft_print_msg("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
- skip_settings_restore = true;
-
if (ops->check_huge(p, 1))
success("OK");
else
@@ -908,7 +877,7 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
- exit(exit_status);
+ _exit(exit_status);
}
wait(&wstatus);
@@ -934,8 +903,6 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops
ksft_print_msg("Share huge page over fork()...");
if (!fork()) {
/* Do not touch settings on child exit */
- skip_settings_restore = true;
-
if (ops->check_huge(p, 1))
success("OK");
else
@@ -968,7 +935,7 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops
validate_memory(p, 0, hpage_pmd_size);
ops->cleanup_area(p, hpage_pmd_size);
- exit(exit_status);
+ _exit(exit_status);
}
wait(&wstatus);
@@ -1261,5 +1228,5 @@ int main(int argc, char **argv)
t->fn(t->ctx, t->ops);
}
- restore_settings(0);
+ ksft_finished();
}
diff --git a/tools/testing/selftests/mm/thp_settings.c b/tools/testing/selftests/mm/thp_settings.c
index e748ebfb3d4e..9bfa5dc42624 100644
--- a/tools/testing/selftests/mm/thp_settings.c
+++ b/tools/testing/selftests/mm/thp_settings.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <fcntl.h>
#include <limits.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,6 +16,7 @@ static struct thp_settings settings_stack[MAX_SETTINGS_DEPTH];
static int settings_index;
static struct thp_settings saved_settings;
static char dev_queue_read_ahead_path[PATH_MAX];
+static bool thp_settings_saved;
static const char * const thp_enabled_strings[] = {
"never",
@@ -298,12 +300,35 @@ void thp_pop_settings(void)
void thp_restore_settings(void)
{
- thp_write_settings(&saved_settings);
+ if (thp_settings_saved)
+ thp_write_settings(&saved_settings);
+}
+
+static void thp_restore_settings_atexit(void)
+{
+ thp_restore_settings();
+}
+
+static void thp_restore_settings_sighandler(int sig)
+{
+ /* exit() will invoke the thp_restore_settings_atexit handler. */
+ exit(KSFT_FAIL);
}
void thp_save_settings(void)
{
thp_read_settings(&saved_settings);
+ thp_settings_saved = true;
+
+ /*
+ * setup exit hooks to make sure THP settings are restored on graceful
+ * and error exits and signals
+ */
+ atexit(thp_restore_settings_atexit);
+ signal(SIGTERM, thp_restore_settings_sighandler);
+ signal(SIGINT, thp_restore_settings_sighandler);
+ signal(SIGHUP, thp_restore_settings_sighandler);
+ signal(SIGQUIT, thp_restore_settings_sighandler);
}
void thp_set_read_ahead_path(char *path)
diff --git a/tools/testing/selftests/mm/uffd-wp-mremap.c b/tools/testing/selftests/mm/uffd-wp-mremap.c
index 17186d4a4147..516c35d236e1 100644
--- a/tools/testing/selftests/mm/uffd-wp-mremap.c
+++ b/tools/testing/selftests/mm/uffd-wp-mremap.c
@@ -368,10 +368,6 @@ int main(int argc, char **argv)
tc->swapout, tc->hugetlb);
}
- /* If THP is supported, restore original THP settings. */
- if (nr_thpsizes)
- thp_restore_settings();
-
i = ksft_get_fail_cnt();
if (i)
ksft_exit_fail_msg("%d out of %d tests failed\n",
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 23/55] selftests/mm: rename thp_settings.[ch] to hugepage_settings.[ch]
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (21 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 22/55] selftests/mm: add atexit() and signal handlers to thp_settings Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 24/55] selftests/mm: move HugeTLB helpers to hugepage_settings Mike Rapoport
` (32 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
... for upcoming addition of HugeTLB helpers.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/Makefile | 4 ++--
tools/testing/selftests/mm/cow.c | 2 +-
tools/testing/selftests/mm/folio_split_race_test.c | 2 +-
tools/testing/selftests/mm/guard-regions.c | 2 +-
.../selftests/mm/{thp_settings.c => hugepage_settings.c} | 2 +-
.../selftests/mm/{thp_settings.h => hugepage_settings.h} | 6 +++---
tools/testing/selftests/mm/khugepaged.c | 2 +-
tools/testing/selftests/mm/ksm_tests.c | 2 +-
tools/testing/selftests/mm/migration.c | 2 +-
tools/testing/selftests/mm/prctl_thp_disable.c | 2 +-
tools/testing/selftests/mm/soft-dirty.c | 2 +-
tools/testing/selftests/mm/split_huge_page_test.c | 2 +-
tools/testing/selftests/mm/transhuge-stress.c | 2 +-
tools/testing/selftests/mm/uffd-wp-mremap.c | 2 +-
14 files changed, 17 insertions(+), 17 deletions(-)
rename tools/testing/selftests/mm/{thp_settings.c => hugepage_settings.c} (99%)
rename tools/testing/selftests/mm/{thp_settings.h => hugepage_settings.h} (95%)
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index d9ecfb02e05c..5b98ce5d0d77 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -186,8 +186,8 @@ TEST_FILES += write_hugetlb_memory.sh
include ../lib.mk
-$(TEST_GEN_PROGS): vm_util.c thp_settings.c
-$(TEST_GEN_FILES): vm_util.c thp_settings.c
+$(TEST_GEN_PROGS): vm_util.c hugepage_settings.c
+$(TEST_GEN_FILES): vm_util.c hugepage_settings.c
$(OUTPUT)/uffd-stress: uffd-common.c
$(OUTPUT)/uffd-unit-tests: uffd-common.c
diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c
index 6abdcb30aba8..4321f4208fe3 100644
--- a/tools/testing/selftests/mm/cow.c
+++ b/tools/testing/selftests/mm/cow.c
@@ -29,7 +29,7 @@
#include "../../../../mm/gup_test.h"
#include "kselftest.h"
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
static size_t pagesize;
static int pagemap_fd;
diff --git a/tools/testing/selftests/mm/folio_split_race_test.c b/tools/testing/selftests/mm/folio_split_race_test.c
index 390fd97c1bd9..6329e37fff4c 100644
--- a/tools/testing/selftests/mm/folio_split_race_test.c
+++ b/tools/testing/selftests/mm/folio_split_race_test.c
@@ -25,7 +25,7 @@
#include <unistd.h>
#include "vm_util.h"
#include "kselftest.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
uint64_t page_size;
uint64_t pmd_pagesize;
diff --git a/tools/testing/selftests/mm/guard-regions.c b/tools/testing/selftests/mm/guard-regions.c
index 48e8b1539be3..feb50b415f52 100644
--- a/tools/testing/selftests/mm/guard-regions.c
+++ b/tools/testing/selftests/mm/guard-regions.c
@@ -21,7 +21,7 @@
#include <sys/uio.h>
#include <unistd.h>
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#include "../pidfd/pidfd.h"
diff --git a/tools/testing/selftests/mm/thp_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
similarity index 99%
rename from tools/testing/selftests/mm/thp_settings.c
rename to tools/testing/selftests/mm/hugepage_settings.c
index 9bfa5dc42624..9000864f8aa4 100644
--- a/tools/testing/selftests/mm/thp_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -8,7 +8,7 @@
#include <unistd.h>
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#define THP_SYSFS "/sys/kernel/mm/transparent_hugepage/"
#define MAX_SETTINGS_DEPTH 4
diff --git a/tools/testing/selftests/mm/thp_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
similarity index 95%
rename from tools/testing/selftests/mm/thp_settings.h
rename to tools/testing/selftests/mm/hugepage_settings.h
index 7748a9009191..d81e33e425c2 100644
--- a/tools/testing/selftests/mm/thp_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __THP_SETTINGS_H__
-#define __THP_SETTINGS_H__
+#ifndef __HUGEPAGE_SETTINGS_H__
+#define __HUGEPAGE_SETTINGS_H__
#include <stdbool.h>
#include <stddef.h>
@@ -86,4 +86,4 @@ unsigned long thp_shmem_supported_orders(void);
bool thp_available(void);
bool thp_is_enabled(void);
-#endif /* __THP_SETTINGS_H__ */
+#endif /* __HUGEPAGE_SETTINGS_H__ */
diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 712e8f194b3d..0c4ecbe82cf0 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -22,7 +22,7 @@
#include "linux/magic.h"
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#define BASE_ADDR ((void *)(1UL << 30))
static unsigned long hpage_pmd_size;
diff --git a/tools/testing/selftests/mm/ksm_tests.c b/tools/testing/selftests/mm/ksm_tests.c
index 0a5b38d3281c..64d1c63ae8c0 100644
--- a/tools/testing/selftests/mm/ksm_tests.c
+++ b/tools/testing/selftests/mm/ksm_tests.c
@@ -15,7 +15,7 @@
#include "kselftest.h"
#include <include/vdso/time64.h>
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#define KSM_SYSFS_PATH "/sys/kernel/mm/ksm/"
#define KSM_FP(s) (KSM_SYSFS_PATH s)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index e504829df6b6..7781a59bb9f8 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -5,7 +5,7 @@
*/
#include "kselftest_harness.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#include <strings.h>
#include <pthread.h>
diff --git a/tools/testing/selftests/mm/prctl_thp_disable.c b/tools/testing/selftests/mm/prctl_thp_disable.c
index ca27200596a4..d8d9d1de57b8 100644
--- a/tools/testing/selftests/mm/prctl_thp_disable.c
+++ b/tools/testing/selftests/mm/prctl_thp_disable.c
@@ -14,7 +14,7 @@
#include <sys/wait.h>
#include "kselftest_harness.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#include "vm_util.h"
#ifndef PR_THP_DISABLE_EXCEPT_ADVISED
diff --git a/tools/testing/selftests/mm/soft-dirty.c b/tools/testing/selftests/mm/soft-dirty.c
index bcfcac99b436..c426c4636ef5 100644
--- a/tools/testing/selftests/mm/soft-dirty.c
+++ b/tools/testing/selftests/mm/soft-dirty.c
@@ -9,7 +9,7 @@
#include "kselftest.h"
#include "vm_util.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#define PAGEMAP_FILE_PATH "/proc/self/pagemap"
#define TEST_ITERATIONS 10000
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
index 500d07c4938b..cc99294bdd5a 100644
--- a/tools/testing/selftests/mm/split_huge_page_test.c
+++ b/tools/testing/selftests/mm/split_huge_page_test.c
@@ -21,7 +21,7 @@
#include <time.h>
#include "vm_util.h"
#include "kselftest.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
uint64_t pagesize;
unsigned int pageshift;
diff --git a/tools/testing/selftests/mm/transhuge-stress.c b/tools/testing/selftests/mm/transhuge-stress.c
index 7a9f1035099b..8eb0c5630e7e 100644
--- a/tools/testing/selftests/mm/transhuge-stress.c
+++ b/tools/testing/selftests/mm/transhuge-stress.c
@@ -17,7 +17,7 @@
#include <sys/mman.h>
#include "vm_util.h"
#include "kselftest.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
int backing_fd = -1;
int mmap_flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE;
diff --git a/tools/testing/selftests/mm/uffd-wp-mremap.c b/tools/testing/selftests/mm/uffd-wp-mremap.c
index 516c35d236e1..9d67b11c2f28 100644
--- a/tools/testing/selftests/mm/uffd-wp-mremap.c
+++ b/tools/testing/selftests/mm/uffd-wp-mremap.c
@@ -8,7 +8,7 @@
#include <linux/mman.h>
#include <sys/mman.h>
#include "kselftest.h"
-#include "thp_settings.h"
+#include "hugepage_settings.h"
#include "uffd-common.h"
static int pagemap_fd;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 24/55] selftests/mm: move HugeTLB helpers to hugepage_settings
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (22 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 23/55] selftests/mm: rename thp_settings.[ch] to hugepage_settings.[ch] Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 25/55] selftests/mm: hugepage_settings: use unsigned long in detect_hugetlb_page_size Mike Rapoport
` (31 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Move library functions that abstract HugeTLB /proc and /sysfs access
from vm_util to hugepage_settings.
This will help creating common helpers that save and restore HugeTLB and
THP settings.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/gup_longterm.c | 1 +
tools/testing/selftests/mm/hmm-tests.c | 2 +-
.../testing/selftests/mm/hugepage_settings.c | 68 +++++++++++++++++++
.../testing/selftests/mm/hugepage_settings.h | 8 +++
tools/testing/selftests/mm/hugetlb-madvise.c | 1 +
tools/testing/selftests/mm/hugetlb-mmap.c | 1 +
tools/testing/selftests/mm/hugetlb-vmemmap.c | 1 +
tools/testing/selftests/mm/hugetlb_dio.c | 1 +
.../selftests/mm/hugetlb_fault_after_madv.c | 1 +
.../selftests/mm/hugetlb_madv_vs_map.c | 1 +
tools/testing/selftests/mm/protection_keys.c | 1 +
tools/testing/selftests/mm/thuge-gen.c | 1 +
tools/testing/selftests/mm/uffd-common.h | 1 +
.../selftests/mm/va_high_addr_switch.c | 1 +
tools/testing/selftests/mm/vm_util.c | 67 ------------------
tools/testing/selftests/mm/vm_util.h | 3 -
16 files changed, 88 insertions(+), 71 deletions(-)
diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c
index f61150d28eb2..ab4eaf4feb7c 100644
--- a/tools/testing/selftests/mm/gup_longterm.c
+++ b/tools/testing/selftests/mm/gup_longterm.c
@@ -29,6 +29,7 @@
#include "../../../../mm/gup_test.h"
#include "kselftest.h"
#include "vm_util.h"
+#include "hugepage_settings.h"
static size_t pagesize;
static int nr_hugetlbsizes;
diff --git a/tools/testing/selftests/mm/hmm-tests.c b/tools/testing/selftests/mm/hmm-tests.c
index 788689497e92..409b11cad4bc 100644
--- a/tools/testing/selftests/mm/hmm-tests.c
+++ b/tools/testing/selftests/mm/hmm-tests.c
@@ -11,6 +11,7 @@
*/
#include "kselftest_harness.h"
+#include "hugepage_settings.h"
#include <errno.h>
#include <fcntl.h>
@@ -27,7 +28,6 @@
#include <sys/ioctl.h>
#include <sys/time.h>
-
/*
* This is a private UAPI to the kernel test module so it isn't exported
* in the usual include/uapi/... directory.
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index 9000864f8aa4..3d6e4376de06 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
+#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -395,3 +397,69 @@ bool thp_is_enabled(void)
/* THP is considered enabled if it's either "always" or "madvise" */
return mode == 1 || mode == 3;
}
+
+int detect_hugetlb_page_sizes(size_t sizes[], int max)
+{
+ DIR *dir = opendir("/sys/kernel/mm/hugepages/");
+ int count = 0;
+
+ if (!dir)
+ return 0;
+
+ while (count < max) {
+ struct dirent *entry = readdir(dir);
+ size_t kb;
+
+ if (!entry)
+ break;
+ if (entry->d_type != DT_DIR)
+ continue;
+ if (sscanf(entry->d_name, "hugepages-%zukB", &kb) != 1)
+ continue;
+ sizes[count++] = kb * 1024;
+ ksft_print_msg("[INFO] detected hugetlb page size: %zu KiB\n",
+ kb);
+ }
+ closedir(dir);
+ return count;
+}
+
+unsigned long default_huge_page_size(void)
+{
+ unsigned long hps = 0;
+ char *line = NULL;
+ size_t linelen = 0;
+ FILE *f = fopen("/proc/meminfo", "r");
+
+ if (!f)
+ return 0;
+ while (getline(&line, &linelen, f) > 0) {
+ if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
+ hps <<= 10;
+ break;
+ }
+ }
+
+ free(line);
+ fclose(f);
+ return hps;
+}
+
+unsigned long get_free_hugepages(void)
+{
+ unsigned long fhp = 0;
+ char *line = NULL;
+ size_t linelen = 0;
+ FILE *f = fopen("/proc/meminfo", "r");
+
+ if (!f)
+ return fhp;
+ while (getline(&line, &linelen, f) > 0) {
+ if (sscanf(line, "HugePages_Free: %lu", &fhp) == 1)
+ break;
+ }
+
+ free(line);
+ fclose(f);
+ return fhp;
+}
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index d81e33e425c2..4c51e9219f6a 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -6,6 +6,8 @@
#include <stddef.h>
#include <stdint.h>
+/* Transparent Huge Pages (THP) */
+
enum thp_enabled {
THP_NEVER,
THP_ALWAYS,
@@ -86,4 +88,10 @@ unsigned long thp_shmem_supported_orders(void);
bool thp_available(void);
bool thp_is_enabled(void);
+/* HugeTLB */
+
+int detect_hugetlb_page_sizes(size_t sizes[], int max);
+unsigned long default_huge_page_size(void);
+unsigned long get_free_hugepages(void);
+
#endif /* __HUGEPAGE_SETTINGS_H__ */
diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
index e7dd8d06d986..5dfa2e0097ef 100644
--- a/tools/testing/selftests/mm/hugetlb-madvise.c
+++ b/tools/testing/selftests/mm/hugetlb-madvise.c
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
#define MIN_FREE_PAGES 20
#define NR_HUGE_PAGES 10 /* common number of pages to map/allocate */
diff --git a/tools/testing/selftests/mm/hugetlb-mmap.c b/tools/testing/selftests/mm/hugetlb-mmap.c
index a327d90d7a79..395be5d0dc1a 100644
--- a/tools/testing/selftests/mm/hugetlb-mmap.c
+++ b/tools/testing/selftests/mm/hugetlb-mmap.c
@@ -18,6 +18,7 @@
#include <linux/memfd.h>
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)
diff --git a/tools/testing/selftests/mm/hugetlb-vmemmap.c b/tools/testing/selftests/mm/hugetlb-vmemmap.c
index 485a6978b40f..af5786bebfd1 100644
--- a/tools/testing/selftests/mm/hugetlb-vmemmap.c
+++ b/tools/testing/selftests/mm/hugetlb-vmemmap.c
@@ -11,6 +11,7 @@
#include <sys/mman.h>
#include <fcntl.h>
#include "vm_util.h"
+#include "hugepage_settings.h"
#define PAGE_COMPOUND_HEAD (1UL << 15)
#define PAGE_COMPOUND_TAIL (1UL << 16)
diff --git a/tools/testing/selftests/mm/hugetlb_dio.c b/tools/testing/selftests/mm/hugetlb_dio.c
index 31a054fa8134..81e3f7bc8e76 100644
--- a/tools/testing/selftests/mm/hugetlb_dio.c
+++ b/tools/testing/selftests/mm/hugetlb_dio.c
@@ -20,6 +20,7 @@
#include <sys/syscall.h>
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
#ifndef STATX_DIOALIGN
#define STATX_DIOALIGN 0x00002000U
diff --git a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
index b4b257775b74..abc3904c5268 100644
--- a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
+++ b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
@@ -10,6 +10,7 @@
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
#define INLOOP_ITER 100
diff --git a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
index c7105c6d319b..ac60b4f18784 100644
--- a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
+++ b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include "vm_util.h"
+#include "hugepage_settings.h"
#define INLOOP_ITER 100
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index d617b41dda6b..4e4aa3b326c1 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -46,6 +46,7 @@
#include <sys/ptrace.h>
#include <setjmp.h>
+#include "hugepage_settings.h"
#include "pkey-helpers.h"
int iteration_nr = 1;
diff --git a/tools/testing/selftests/mm/thuge-gen.c b/tools/testing/selftests/mm/thuge-gen.c
index 77813d34dcc2..1007bc8aa57c 100644
--- a/tools/testing/selftests/mm/thuge-gen.c
+++ b/tools/testing/selftests/mm/thuge-gen.c
@@ -28,6 +28,7 @@
#include <string.h>
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
#if !defined(MAP_HUGETLB)
#define MAP_HUGETLB 0x40000
diff --git a/tools/testing/selftests/mm/uffd-common.h b/tools/testing/selftests/mm/uffd-common.h
index 0723843a7626..92a21b97f745 100644
--- a/tools/testing/selftests/mm/uffd-common.h
+++ b/tools/testing/selftests/mm/uffd-common.h
@@ -37,6 +37,7 @@
#include "kselftest.h"
#include "vm_util.h"
+#include "hugepage_settings.h"
#define UFFD_FLAGS (O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY)
diff --git a/tools/testing/selftests/mm/va_high_addr_switch.c b/tools/testing/selftests/mm/va_high_addr_switch.c
index 5d38735ea60e..0b69bd4b901d 100644
--- a/tools/testing/selftests/mm/va_high_addr_switch.c
+++ b/tools/testing/selftests/mm/va_high_addr_switch.c
@@ -11,6 +11,7 @@
#include "vm_util.h"
#include "kselftest.h"
+#include "hugepage_settings.h"
/*
* The hint addr value is used to allocate addresses
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index db94564f4431..412e980cce9a 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -2,7 +2,6 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
-#include <dirent.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <linux/userfaultfd.h>
@@ -291,53 +290,6 @@ int64_t allocate_transhuge(void *ptr, int pagemap_fd)
return -1;
}
-unsigned long default_huge_page_size(void)
-{
- unsigned long hps = 0;
- char *line = NULL;
- size_t linelen = 0;
- FILE *f = fopen("/proc/meminfo", "r");
-
- if (!f)
- return 0;
- while (getline(&line, &linelen, f) > 0) {
- if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
- hps <<= 10;
- break;
- }
- }
-
- free(line);
- fclose(f);
- return hps;
-}
-
-int detect_hugetlb_page_sizes(size_t sizes[], int max)
-{
- DIR *dir = opendir("/sys/kernel/mm/hugepages/");
- int count = 0;
-
- if (!dir)
- return 0;
-
- while (count < max) {
- struct dirent *entry = readdir(dir);
- size_t kb;
-
- if (!entry)
- break;
- if (entry->d_type != DT_DIR)
- continue;
- if (sscanf(entry->d_name, "hugepages-%zukB", &kb) != 1)
- continue;
- sizes[count++] = kb * 1024;
- ksft_print_msg("[INFO] detected hugetlb page size: %zu KiB\n",
- kb);
- }
- closedir(dir);
- return count;
-}
-
int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags)
{
size_t count;
@@ -396,25 +348,6 @@ int uffd_unregister(int uffd, void *addr, uint64_t len)
return ret;
}
-unsigned long get_free_hugepages(void)
-{
- unsigned long fhp = 0;
- char *line = NULL;
- size_t linelen = 0;
- FILE *f = fopen("/proc/meminfo", "r");
-
- if (!f)
- return fhp;
- while (getline(&line, &linelen, f) > 0) {
- if (sscanf(line, "HugePages_Free: %lu", &fhp) == 1)
- break;
- }
-
- free(line);
- fclose(f);
- return fhp;
-}
-
static bool check_vmflag(void *addr, const char *flag)
{
char buffer[MAX_LINE_LENGTH];
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index 1a07305ceff4..195bf2e26792 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -94,8 +94,6 @@ bool check_huge_anon(void *addr, int nr_hpages, uint64_t hpage_size);
bool check_huge_file(void *addr, int nr_hpages, uint64_t hpage_size);
bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size);
int64_t allocate_transhuge(void *ptr, int pagemap_fd);
-unsigned long default_huge_page_size(void);
-int detect_hugetlb_page_sizes(size_t sizes[], int max);
int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags);
int uffd_register(int uffd, void *addr, uint64_t len,
@@ -103,7 +101,6 @@ int uffd_register(int uffd, void *addr, uint64_t len,
int uffd_unregister(int uffd, void *addr, uint64_t len);
int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
bool miss, bool wp, bool minor, uint64_t *ioctls);
-unsigned long get_free_hugepages(void);
bool check_vmflag_io(void *addr);
bool check_vmflag_pfnmap(void *addr);
bool check_vmflag_guard(void *addr);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 25/55] selftests/mm: hugepage_settings: use unsigned long in detect_hugetlb_page_size
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (23 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 24/55] selftests/mm: move HugeTLB helpers to hugepage_settings Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 26/55] selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages Mike Rapoport
` (30 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
... instead of size_t to avoid type mismatch in 32 and 64 bit builds.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/cow.c | 2 +-
tools/testing/selftests/mm/gup_longterm.c | 2 +-
tools/testing/selftests/mm/hugepage_settings.c | 2 +-
tools/testing/selftests/mm/hugepage_settings.h | 2 +-
tools/testing/selftests/mm/uffd-wp-mremap.c | 6 +++---
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c
index 4321f4208fe3..5e571216b8d2 100644
--- a/tools/testing/selftests/mm/cow.c
+++ b/tools/testing/selftests/mm/cow.c
@@ -37,7 +37,7 @@ static size_t pmdsize;
static int nr_thpsizes;
static size_t thpsizes[20];
static int nr_hugetlbsizes;
-static size_t hugetlbsizes[10];
+static unsigned long hugetlbsizes[10];
static int gup_fd;
static bool has_huge_zeropage;
diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c
index ab4eaf4feb7c..96dae0acd11a 100644
--- a/tools/testing/selftests/mm/gup_longterm.c
+++ b/tools/testing/selftests/mm/gup_longterm.c
@@ -33,7 +33,7 @@
static size_t pagesize;
static int nr_hugetlbsizes;
-static size_t hugetlbsizes[10];
+static unsigned long hugetlbsizes[10];
static int gup_fd;
static __fsword_t get_fs_type(int fd)
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index 3d6e4376de06..fa635667aabb 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -398,7 +398,7 @@ bool thp_is_enabled(void)
return mode == 1 || mode == 3;
}
-int detect_hugetlb_page_sizes(size_t sizes[], int max)
+int detect_hugetlb_page_sizes(unsigned long sizes[], int max)
{
DIR *dir = opendir("/sys/kernel/mm/hugepages/");
int count = 0;
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index 4c51e9219f6a..f49bd7fba512 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -90,7 +90,7 @@ bool thp_is_enabled(void);
/* HugeTLB */
-int detect_hugetlb_page_sizes(size_t sizes[], int max);
+int detect_hugetlb_page_sizes(unsigned long sizes[], int max);
unsigned long default_huge_page_size(void);
unsigned long get_free_hugepages(void);
diff --git a/tools/testing/selftests/mm/uffd-wp-mremap.c b/tools/testing/selftests/mm/uffd-wp-mremap.c
index 9d67b11c2f28..b44e02840a5e 100644
--- a/tools/testing/selftests/mm/uffd-wp-mremap.c
+++ b/tools/testing/selftests/mm/uffd-wp-mremap.c
@@ -12,12 +12,12 @@
#include "uffd-common.h"
static int pagemap_fd;
-static size_t pagesize;
static int nr_pagesizes = 1;
+static unsigned long pagesize;
static int nr_thpsizes;
static size_t thpsizes[20];
static int nr_hugetlbsizes;
-static size_t hugetlbsizes[10];
+static unsigned long hugetlbsizes[10];
static int detect_thp_sizes(size_t sizes[], int max)
{
@@ -245,7 +245,7 @@ static void test_one_folio(uffd_global_test_opts_t *gopts, size_t size, bool pri
}
struct testcase {
- size_t *sizes;
+ unsigned long *sizes;
int *nr_sizes;
bool private;
bool swapout;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 26/55] selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (24 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 25/55] selftests/mm: hugepage_settings: use unsigned long in detect_hugetlb_page_size Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 27/55] selftests/mm: hugepage_settings: rename and rework get_free_hugepages() Mike Rapoport
` (29 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Add APIs that allow reading and writing of
/sys/kernel/mm/hugepages/hugepages-NkB/nr_hugepages
to detect and change the amount of HugeTLB pages of different sizes.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../testing/selftests/mm/hugepage_settings.c | 25 +++++++++++++++++++
.../testing/selftests/mm/hugepage_settings.h | 23 +++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index fa635667aabb..99402cfccb6d 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -463,3 +463,28 @@ unsigned long get_free_hugepages(void)
fclose(f);
return fhp;
}
+
+static void hugetlb_sysfs_path(char *buf, size_t buflen,
+ unsigned long size, const char *attr)
+{
+ snprintf(buf, buflen, "/sys/kernel/mm/hugepages/hugepages-%lukB/%s",
+ size / 1024, attr);
+}
+
+unsigned long hugetlb_nr_pages(unsigned long size)
+{
+ char path[PATH_MAX];
+
+ hugetlb_sysfs_path(path, sizeof(path), size, "nr_hugepages");
+
+ return read_num(path);
+}
+
+void hugetlb_set_nr_pages(unsigned long size, unsigned long nr)
+{
+ char path[PATH_MAX];
+
+ hugetlb_sysfs_path(path, sizeof(path), size, "nr_hugepages");
+
+ write_num(path, nr);
+}
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index f49bd7fba512..e66302926377 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -94,4 +94,27 @@ int detect_hugetlb_page_sizes(unsigned long sizes[], int max);
unsigned long default_huge_page_size(void);
unsigned long get_free_hugepages(void);
+unsigned long hugetlb_nr_pages(unsigned long size);
+void hugetlb_set_nr_pages(unsigned long size, unsigned long nr);
+
+static inline unsigned long hugetlb_nr_default_pages(void)
+{
+ unsigned long size = default_huge_page_size();
+
+ if (!size)
+ return 0;
+
+ return hugetlb_nr_pages(size);
+}
+
+static inline void hugetlb_set_nr_default_pages(unsigned long nr)
+{
+ unsigned long size = default_huge_page_size();
+
+ if (!size)
+ return;
+
+ hugetlb_set_nr_pages(size, nr);
+}
+
#endif /* __HUGEPAGE_SETTINGS_H__ */
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 27/55] selftests/mm: hugepage_settings: rename and rework get_free_hugepages()
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (25 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 26/55] selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 28/55] selftests/mm: hugepage_settings: add APIs for HugeTLB setup and teardown Mike Rapoport
` (28 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
... to hugetlb_free_default_pages() for consistency with
hugetlb_nr_default_pages().
Make hugetlb_free_default_pages() use hugetlb_sysfs_path() helper instead
of parsing /proc/meminfo.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../testing/selftests/mm/hugepage_settings.c | 28 ++++++-------------
.../testing/selftests/mm/hugepage_settings.h | 12 +++++++-
tools/testing/selftests/mm/hugetlb-madvise.c | 4 +--
tools/testing/selftests/mm/hugetlb_dio.c | 6 ++--
.../selftests/mm/hugetlb_fault_after_madv.c | 2 +-
.../selftests/mm/hugetlb_madv_vs_map.c | 2 +-
tools/testing/selftests/mm/uffd-stress.c | 2 +-
7 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index 99402cfccb6d..3c944d28d14a 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -445,25 +445,6 @@ unsigned long default_huge_page_size(void)
return hps;
}
-unsigned long get_free_hugepages(void)
-{
- unsigned long fhp = 0;
- char *line = NULL;
- size_t linelen = 0;
- FILE *f = fopen("/proc/meminfo", "r");
-
- if (!f)
- return fhp;
- while (getline(&line, &linelen, f) > 0) {
- if (sscanf(line, "HugePages_Free: %lu", &fhp) == 1)
- break;
- }
-
- free(line);
- fclose(f);
- return fhp;
-}
-
static void hugetlb_sysfs_path(char *buf, size_t buflen,
unsigned long size, const char *attr)
{
@@ -488,3 +469,12 @@ void hugetlb_set_nr_pages(unsigned long size, unsigned long nr)
write_num(path, nr);
}
+
+unsigned long hugetlb_free_pages(unsigned long size)
+{
+ char path[PATH_MAX];
+
+ hugetlb_sysfs_path(path, sizeof(path), size, "free_hugepages");
+
+ return read_num(path);
+}
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index e66302926377..436f4ce02984 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -92,10 +92,10 @@ bool thp_is_enabled(void);
int detect_hugetlb_page_sizes(unsigned long sizes[], int max);
unsigned long default_huge_page_size(void);
-unsigned long get_free_hugepages(void);
unsigned long hugetlb_nr_pages(unsigned long size);
void hugetlb_set_nr_pages(unsigned long size, unsigned long nr);
+unsigned long hugetlb_free_pages(unsigned long size);
static inline unsigned long hugetlb_nr_default_pages(void)
{
@@ -117,4 +117,14 @@ static inline void hugetlb_set_nr_default_pages(unsigned long nr)
hugetlb_set_nr_pages(size, nr);
}
+static inline unsigned long hugetlb_free_default_pages(void)
+{
+ unsigned long size = default_huge_page_size();
+
+ if (!size)
+ return 0;
+
+ return hugetlb_free_pages(size);
+}
+
#endif /* __HUGEPAGE_SETTINGS_H__ */
diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
index 5dfa2e0097ef..8adcd91d078d 100644
--- a/tools/testing/selftests/mm/hugetlb-madvise.c
+++ b/tools/testing/selftests/mm/hugetlb-madvise.c
@@ -27,7 +27,7 @@
#define validate_free_pages(exp_free) \
do { \
- unsigned long fhp = get_free_hugepages(); \
+ unsigned long fhp = hugetlb_free_default_pages(); \
if (fhp != (exp_free)) \
ksft_exit_fail_msg("Unexpected number of free " \
"huge pages %lu, expected %lu line %d\n", \
@@ -68,7 +68,7 @@ int main(int argc, char **argv)
if (!base_page_size)
ksft_exit_fail_msg("Unable to determine base page size\n");
- free_hugepages = get_free_hugepages();
+ free_hugepages = hugetlb_free_default_pages();
if (free_hugepages < MIN_FREE_PAGES)
ksft_exit_skip("Not enough free huge pages (have %lu, need %d)\n", free_hugepages, MIN_FREE_PAGES);
diff --git a/tools/testing/selftests/mm/hugetlb_dio.c b/tools/testing/selftests/mm/hugetlb_dio.c
index 81e3f7bc8e76..47019433ddaf 100644
--- a/tools/testing/selftests/mm/hugetlb_dio.c
+++ b/tools/testing/selftests/mm/hugetlb_dio.c
@@ -93,7 +93,7 @@ static void run_dio_using_hugetlb(int fd, unsigned int start_off,
ksft_exit_fail_perror("lseek failed\n");
/* Get the free huge pages before allocation */
- free_hpage_b = get_free_hugepages();
+ free_hpage_b = hugetlb_free_default_pages();
if (free_hpage_b == 0) {
close(fd);
ksft_exit_skip("No free hugepage, exiting!\n");
@@ -121,7 +121,7 @@ static void run_dio_using_hugetlb(int fd, unsigned int start_off,
munmap(orig_buffer, h_pagesize);
/* Get the free huge pages after unmap*/
- free_hpage_a = get_free_hugepages();
+ free_hpage_a = hugetlb_free_default_pages();
ksft_print_msg("No. Free pages before allocation : %d\n", free_hpage_b);
ksft_print_msg("No. Free pages after munmap : %d\n", free_hpage_a);
@@ -142,7 +142,7 @@ int main(void)
ksft_print_header();
/* Check if huge pages are free */
- if (!get_free_hugepages())
+ if (!hugetlb_free_default_pages())
ksft_exit_skip("No free hugepage, exiting\n");
fd = open("/tmp", O_TMPFILE | O_RDWR | O_DIRECT, 0664);
diff --git a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
index abc3904c5268..c718dd065d53 100644
--- a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
+++ b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
@@ -78,7 +78,7 @@ int main(void)
ksft_print_msg("[INFO] detected default hugetlb page size: %zu KiB\n",
huge_page_size / 1024);
- free_hugepages = get_free_hugepages();
+ free_hugepages = hugetlb_free_default_pages();
if (free_hugepages != 1) {
ksft_exit_skip("This test needs one and only one page to execute. Got %lu\n",
free_hugepages);
diff --git a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
index ac60b4f18784..dfbd71a7f709 100644
--- a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
+++ b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
@@ -89,7 +89,7 @@ int main(void)
ksft_print_header();
ksft_set_plan(1);
- free_hugepages = get_free_hugepages();
+ free_hugepages = hugetlb_free_default_pages();
if (free_hugepages != 1)
ksft_exit_skip("This test needs one and only one page to execute. Got %lu\n",
diff --git a/tools/testing/selftests/mm/uffd-stress.c b/tools/testing/selftests/mm/uffd-stress.c
index 0ce493dac354..7c719d789249 100644
--- a/tools/testing/selftests/mm/uffd-stress.c
+++ b/tools/testing/selftests/mm/uffd-stress.c
@@ -481,7 +481,7 @@ int main(int argc, char **argv)
* for racy extra reservation of hugepages.
*/
if (gopts->test_type == TEST_HUGETLB &&
- get_free_hugepages() < 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1)
+ hugetlb_free_default_pages() < 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1)
ksft_exit_skip("Skipping userfaultfd... not enough hugepages\n");
gopts->nr_pages_per_cpu = bytes / gopts->page_size / gopts->nr_parallel;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 28/55] selftests/mm: hugepage_settings: add APIs for HugeTLB setup and teardown
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (26 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 27/55] selftests/mm: hugepage_settings: rename and rework get_free_hugepages() Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 29/55] selftests/mm: move read_file(), read_num() and write_num() to vm_util Mike Rapoport
` (27 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
A lot of tests require free HugeTLB pages. Some need just a few default
huge pages, some need a certain amount of memory available as HugeTLB, and
some just skip lots of tests if huge pages of all supported sizes are not
available.
This all resulted in a huge mess in run_vmtests.sh that sets up some huge
pages, adjusts them later and restores some of the settings if the stars
align.
Add APIs that allow saving the state of HugeTLB and setting up the desired
amount of HugeTLB pages.
Saving the state also registers atexit() callback and signal handler that
will ensure restoration of HugeTLB state.
Since many tests use both HugeTLB and THP, the atexit() callbacks and
signal handler are restoring both.
For kselftest_harness tests that run fixture setups and test in child
processes add a constructor that will save and restore settings in the main
process.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../testing/selftests/mm/hugepage_settings.c | 205 ++++++++++++++++--
.../testing/selftests/mm/hugepage_settings.h | 31 ++-
2 files changed, 213 insertions(+), 23 deletions(-)
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index 3c944d28d14a..01a557f372d1 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -306,31 +306,16 @@ void thp_restore_settings(void)
thp_write_settings(&saved_settings);
}
-static void thp_restore_settings_atexit(void)
+static void __thp_save_settings(void)
{
- thp_restore_settings();
-}
+ if (!thp_available())
+ return;
-static void thp_restore_settings_sighandler(int sig)
-{
- /* exit() will invoke the thp_restore_settings_atexit handler. */
- exit(KSFT_FAIL);
-}
+ if (thp_settings_saved)
+ return;
-void thp_save_settings(void)
-{
thp_read_settings(&saved_settings);
thp_settings_saved = true;
-
- /*
- * setup exit hooks to make sure THP settings are restored on graceful
- * and error exits and signals
- */
- atexit(thp_restore_settings_atexit);
- signal(SIGTERM, thp_restore_settings_sighandler);
- signal(SIGINT, thp_restore_settings_sighandler);
- signal(SIGHUP, thp_restore_settings_sighandler);
- signal(SIGQUIT, thp_restore_settings_sighandler);
}
void thp_set_read_ahead_path(char *path)
@@ -398,11 +383,32 @@ bool thp_is_enabled(void)
return mode == 1 || mode == 3;
}
+#define HUGETLB_MAX_NR_PAGESIZES 10
+struct hugetlb_settings {
+ unsigned long nr_hugepages[HUGETLB_MAX_NR_PAGESIZES];
+ unsigned long sizes[HUGETLB_MAX_NR_PAGESIZES];
+ unsigned long default_size;
+ int nr_sizes;
+};
+
+static struct hugetlb_settings hugetlb_saved_settings;
+static bool hugetlb_settings_saved;
+
int detect_hugetlb_page_sizes(unsigned long sizes[], int max)
{
- DIR *dir = opendir("/sys/kernel/mm/hugepages/");
+ static struct hugetlb_settings *settings = &hugetlb_saved_settings;
+ DIR *dir;
int count = 0;
+ if (settings->nr_sizes) {
+ if (settings->nr_sizes < max)
+ max = settings->nr_sizes;
+ for (count = 0; count < max; count++)
+ sizes[count] = settings->sizes[count];
+ return count;
+ }
+
+ dir = opendir("/sys/kernel/mm/hugepages/");
if (!dir)
return 0;
@@ -426,11 +432,16 @@ int detect_hugetlb_page_sizes(unsigned long sizes[], int max)
unsigned long default_huge_page_size(void)
{
+ static struct hugetlb_settings *settings = &hugetlb_saved_settings;
unsigned long hps = 0;
char *line = NULL;
size_t linelen = 0;
- FILE *f = fopen("/proc/meminfo", "r");
+ FILE *f;
+
+ if (settings->default_size)
+ return settings->default_size;
+ f = fopen("/proc/meminfo", "r");
if (!f)
return 0;
while (getline(&line, &linelen, f) > 0) {
@@ -478,3 +489,153 @@ unsigned long hugetlb_free_pages(unsigned long size)
return read_num(path);
}
+
+static bool __hugetlb_setup(unsigned long size, unsigned long nr)
+{
+ unsigned long free = hugetlb_free_pages(size);
+ unsigned long total = hugetlb_nr_pages(size);
+
+ if (free >= nr)
+ return true;
+
+ hugetlb_set_nr_pages(size, total + (nr - free));
+
+ return hugetlb_free_pages(size) >= nr;
+}
+
+bool hugetlb_setup_default(unsigned long nr)
+{
+ unsigned long size;
+
+ hugetlb_save_settings();
+ size = default_huge_page_size();
+ if (!size)
+ return false;
+
+ return __hugetlb_setup(size, nr);
+}
+
+bool hugetlb_setup_default_exact(unsigned long nr)
+{
+ unsigned long size;
+
+ hugetlb_save_settings();
+ size = default_huge_page_size();
+ if (!size)
+ return false;
+
+ hugetlb_set_nr_pages(size, nr);
+
+ return hugetlb_free_pages(size) == nr;
+}
+
+unsigned long hugetlb_setup(unsigned long nr, unsigned long sizes[],
+ int max)
+{
+ unsigned long enabled[10];
+ int nr_sizes = 0;
+ int nr_enabled;
+
+ hugetlb_save_settings();
+
+ nr_enabled = detect_hugetlb_page_sizes(enabled, ARRAY_SIZE(enabled));
+ if (!nr_enabled)
+ return 0;
+
+ if (nr_enabled > max) {
+ ksft_print_msg("detected %d huge page sizes, will only test %d\n", nr_enabled, max);
+ nr_enabled = max;
+ }
+
+ /* request nr HugeTLB pages of every size. */
+ for (int i = 0; i < nr_enabled; i++) {
+ if (!__hugetlb_setup(enabled[i], nr))
+ continue;
+ sizes[nr_sizes++] = enabled[i];
+ }
+
+ return nr_sizes;
+}
+
+static void __hugetlb_save_settings(void)
+{
+ struct hugetlb_settings *settings = &hugetlb_saved_settings;
+ int nr_sizes;
+
+ if (hugetlb_settings_saved)
+ return;
+
+ settings->default_size = default_huge_page_size();
+ if (!settings->default_size)
+ return;
+
+ nr_sizes = detect_hugetlb_page_sizes(settings->sizes,
+ HUGETLB_MAX_NR_PAGESIZES);
+ if (!nr_sizes) {
+ settings->default_size = 0;
+ return;
+ }
+
+ for (int i = 0; i < nr_sizes; i++) {
+ unsigned long sz = settings->sizes[i];
+
+ if (!sz)
+ continue;
+ settings->nr_hugepages[i] = hugetlb_nr_pages(sz);
+ }
+
+ settings->nr_sizes = nr_sizes;
+ hugetlb_settings_saved = true;
+}
+
+void hugetlb_restore_settings(void)
+{
+ struct hugetlb_settings *settings = &hugetlb_saved_settings;
+
+ if (!hugetlb_settings_saved || !settings->default_size)
+ return;
+
+ for (int i = 0; i < HUGETLB_MAX_NR_PAGESIZES; i++) {
+ unsigned long sz = settings->sizes[i];
+
+ if (!sz)
+ continue;
+
+ hugetlb_set_nr_pages(sz, settings->nr_hugepages[i]);
+ }
+}
+
+static void hugepage_restore_settings_atexit(void)
+{
+ if (thp_settings_saved)
+ thp_restore_settings();
+ if (hugetlb_settings_saved)
+ hugetlb_restore_settings();
+}
+
+static void hugepage_restore_settings_sighandler(int sig)
+{
+ /* exit() will invoke the hugepage_restore_settings_atexit handler. */
+ exit(KSFT_FAIL);
+}
+
+void hugepage_save_settings(bool thp, bool hugetlb)
+{
+ if (!thp && !hugetlb)
+ return;
+
+ if (thp)
+ __thp_save_settings();
+ if (hugetlb)
+ __hugetlb_save_settings();
+
+ /*
+ * setup exit hooks to make sure THP and HugeTLB settings are
+ * restored on graceful and error exits and signals
+ */
+ atexit(hugepage_restore_settings_atexit);
+ signal(SIGTERM, hugepage_restore_settings_sighandler);
+ signal(SIGINT, hugepage_restore_settings_sighandler);
+ signal(SIGHUP, hugepage_restore_settings_sighandler);
+ signal(SIGQUIT, hugepage_restore_settings_sighandler);
+}
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index 436f4ce02984..c07722b7f102 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -6,6 +6,8 @@
#include <stddef.h>
#include <stdint.h>
+void hugepage_save_settings(bool thp, bool hugetlb);
+
/* Transparent Huge Pages (THP) */
enum thp_enabled {
@@ -79,7 +81,11 @@ struct thp_settings *thp_current_settings(void);
void thp_push_settings(struct thp_settings *settings);
void thp_pop_settings(void);
void thp_restore_settings(void);
-void thp_save_settings(void);
+
+static inline void thp_save_settings(void)
+{
+ hugepage_save_settings(/* thp = */ true, /* hugetlb = */ false);
+}
void thp_set_read_ahead_path(char *path);
unsigned long thp_supported_orders(void);
@@ -97,6 +103,13 @@ unsigned long hugetlb_nr_pages(unsigned long size);
void hugetlb_set_nr_pages(unsigned long size, unsigned long nr);
unsigned long hugetlb_free_pages(unsigned long size);
+static inline void hugetlb_save_settings(void)
+{
+ hugepage_save_settings(/* thp = */ false, /* hugetlb = */ true);
+}
+
+void hugetlb_restore_settings(void);
+
static inline unsigned long hugetlb_nr_default_pages(void)
{
unsigned long size = default_huge_page_size();
@@ -127,4 +140,20 @@ static inline unsigned long hugetlb_free_default_pages(void)
return hugetlb_free_pages(size);
}
+static inline bool hugetlb_available(void)
+{
+ return default_huge_page_size() != 0;
+}
+
+bool hugetlb_setup_default(unsigned long nr);
+bool hugetlb_setup_default_exact(unsigned long nr);
+unsigned long hugetlb_setup(unsigned long nr, unsigned long sizes[],
+ int max);
+
+#define HUGETLB_SETUP_DEFAULT_PAGES(nr_pages) \
+static void __attribute__((constructor)) __hugetlb_setup_default(void) \
+{ \
+ hugetlb_setup_default((nr_pages)); \
+}
+
#endif /* __HUGEPAGE_SETTINGS_H__ */
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 29/55] selftests/mm: move read_file(), read_num() and write_num() to vm_util
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (27 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 28/55] selftests/mm: hugepage_settings: add APIs for HugeTLB setup and teardown Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 30/55] selftests/mm: vm_util: add helpers to set and restore shm limits Mike Rapoport
` (26 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
These are useful helpers for writing and reading sysfs and proc files.
Make them available to the tests that don't use thp_settings.
While on it make write_num() use "%lu" instead of "%ld" to match
'unsigned long num' argument type.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../testing/selftests/mm/hugepage_settings.c | 41 -------------------
.../testing/selftests/mm/hugepage_settings.h | 4 --
tools/testing/selftests/mm/vm_util.c | 39 ++++++++++++++++++
tools/testing/selftests/mm/vm_util.h | 3 ++
4 files changed, 42 insertions(+), 45 deletions(-)
diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
index 01a557f372d1..2eab2110ac6a 100644
--- a/tools/testing/selftests/mm/hugepage_settings.c
+++ b/tools/testing/selftests/mm/hugepage_settings.c
@@ -48,47 +48,6 @@ static const char * const shmem_enabled_strings[] = {
NULL
};
-int read_file(const char *path, char *buf, size_t buflen)
-{
- int fd;
- ssize_t numread;
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
- return 0;
-
- numread = read(fd, buf, buflen - 1);
- if (numread < 1) {
- close(fd);
- return 0;
- }
-
- buf[numread] = '\0';
- close(fd);
-
- return (unsigned int) numread;
-}
-
-unsigned long read_num(const char *path)
-{
- char buf[21];
-
- if (read_file(path, buf, sizeof(buf)) < 0) {
- perror("read_file()");
- exit(EXIT_FAILURE);
- }
-
- return strtoul(buf, NULL, 10);
-}
-
-void write_num(const char *path, unsigned long num)
-{
- char buf[21];
-
- sprintf(buf, "%ld", num);
- write_file(path, buf, strlen(buf) + 1);
-}
-
int thp_read_string(const char *name, const char * const strings[])
{
char path[PATH_MAX];
diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
index c07722b7f102..726c73c43c05 100644
--- a/tools/testing/selftests/mm/hugepage_settings.h
+++ b/tools/testing/selftests/mm/hugepage_settings.h
@@ -66,10 +66,6 @@ struct thp_settings {
struct shmem_hugepages_settings shmem_hugepages[NR_ORDERS];
};
-int read_file(const char *path, char *buf, size_t buflen);
-unsigned long read_num(const char *path);
-void write_num(const char *path, unsigned long num);
-
int thp_read_string(const char *name, const char * const strings[]);
void thp_write_string(const char *name, const char *val);
unsigned long thp_read_num(const char *name);
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 412e980cce9a..9256bbbe38ea 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -698,6 +698,27 @@ int unpoison_memory(unsigned long pfn)
return ret > 0 ? 0 : -errno;
}
+int read_file(const char *path, char *buf, size_t buflen)
+{
+ int fd;
+ ssize_t numread;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return 0;
+
+ numread = read(fd, buf, buflen - 1);
+ if (numread < 1) {
+ close(fd);
+ return 0;
+ }
+
+ buf[numread] = '\0';
+ close(fd);
+
+ return (unsigned int) numread;
+}
+
void write_file(const char *path, const char *buf, size_t buflen)
{
int fd, saved_errno;
@@ -721,3 +742,21 @@ void write_file(const char *path, const char *buf, size_t buflen)
ksft_exit_fail_msg("%s write(%.*s) is truncated, expected %zu bytes, got %zd bytes\n",
path, (int)(buflen - 1), buf, buflen - 1, numwritten);
}
+
+unsigned long read_num(const char *path)
+{
+ char buf[21];
+
+ if (read_file(path, buf, sizeof(buf)) < 0)
+ ksft_exit_fail_perror("read_file()");
+
+ return strtoul(buf, NULL, 10);
+}
+
+void write_num(const char *path, unsigned long num)
+{
+ char buf[21];
+
+ sprintf(buf, "%lu", num);
+ write_file(path, buf, strlen(buf) + 1);
+}
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index 195bf2e26792..5fc9707f6b9a 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -165,3 +165,6 @@ int unpoison_memory(unsigned long pfn);
#define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1))
void write_file(const char *path, const char *buf, size_t buflen);
+int read_file(const char *path, char *buf, size_t buflen);
+unsigned long read_num(const char *path);
+void write_num(const char *path, unsigned long num);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 30/55] selftests/mm: vm_util: add helpers to set and restore shm limits
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (28 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 29/55] selftests/mm: move read_file(), read_num() and write_num() to vm_util Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 31/55] selftests/mm: compaction_test: use HugeTLB helpers Mike Rapoport
` (25 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-shm and thuge-gen tests require that limits defined by
/proc/sys/kernel/{shmmax,shmall} should be higher than certain values.
Add helpers that allow setting these limits and restoring their settings on
a test exit.
They will be used later in hugetlb-shm and thuge-gen.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/vm_util.c | 28 ++++++++++++++++++++++++++++
tools/testing/selftests/mm/vm_util.h | 9 +++++++++
2 files changed, 37 insertions(+)
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 9256bbbe38ea..336a26751d3f 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -760,3 +760,31 @@ void write_num(const char *path, unsigned long num)
sprintf(buf, "%lu", num);
write_file(path, buf, strlen(buf) + 1);
}
+
+static unsigned long shmall, shmmax;
+
+void __shm_limits_restore(void)
+{
+ if (shmmax)
+ write_num("/proc/sys/kernel/shmmax", shmmax);
+ if (shmall)
+ write_num("/proc/sys/kernel/shmall", shmall);
+}
+
+void shm_limits_prepare(unsigned long length)
+{
+ unsigned long nr = length / psize();
+ unsigned long val;
+
+ val = read_num("/proc/sys/kernel/shmmax");
+ if (val < length) {
+ write_num("/proc/sys/kernel/shmmax", length);
+ shmmax = val;
+ }
+
+ val = read_num("/proc/sys/kernel/shmall");
+ if (val < nr) {
+ write_num("/proc/sys/kernel/shmall", nr);
+ shmall = val;
+ }
+}
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index 5fc9707f6b9a..ea8fc8fdf0eb 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -168,3 +168,12 @@ void write_file(const char *path, const char *buf, size_t buflen);
int read_file(const char *path, char *buf, size_t buflen);
unsigned long read_num(const char *path);
void write_num(const char *path, unsigned long num);
+
+void shm_limits_prepare(unsigned long length);
+void __shm_limits_restore(void);
+
+#define SHM_LIMITS_RESTORE() \
+static void __attribute__((destructor)) shm_limits_restore(void) \
+{ \
+ __shm_limits_restore(); \
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 31/55] selftests/mm: compaction_test: use HugeTLB helpers ...
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (29 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 30/55] selftests/mm: vm_util: add helpers to set and restore shm limits Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 32/55] selftests/mm: cow: add setup of HugeTLB pages Mike Rapoport
` (24 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
... instead of open coded access of HugeTLB parameters via /proc.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/compaction_test.c | 115 +++----------------
1 file changed, 17 insertions(+), 98 deletions(-)
diff --git a/tools/testing/selftests/mm/compaction_test.c b/tools/testing/selftests/mm/compaction_test.c
index 30209c40b697..de0633f9a7e5 100644
--- a/tools/testing/selftests/mm/compaction_test.c
+++ b/tools/testing/selftests/mm/compaction_test.c
@@ -17,6 +17,7 @@
#include <string.h>
#include "kselftest.h"
+#include "hugepage_settings.h"
#define MAP_SIZE_MB 100
#define MAP_SIZE (MAP_SIZE_MB * 1024 * 1024)
@@ -82,124 +83,44 @@ int prereq(void)
return -1;
}
-int check_compaction(unsigned long mem_free, unsigned long hugepage_size,
- unsigned long initial_nr_hugepages)
+int check_compaction(unsigned long mem_free, unsigned long hugepage_size)
{
- unsigned long nr_hugepages_ul;
- int fd, ret = -1;
+ unsigned long nr_hugepages;
int compaction_index = 0;
- char nr_hugepages[20] = {0};
- char init_nr_hugepages[24] = {0};
- char target_nr_hugepages[24] = {0};
- int slen;
-
- snprintf(init_nr_hugepages, sizeof(init_nr_hugepages),
- "%lu", initial_nr_hugepages);
+ int ret = -1;
/* We want to test with 80% of available memory. Else, OOM killer comes
in to play */
mem_free = mem_free * 0.8;
- fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
- ret = -1;
- goto out;
- }
-
/*
* Request huge pages for about half of the free memory. The Kernel
* will allocate as much as it can, and we expect it will get at least 1/3
*/
- nr_hugepages_ul = mem_free / hugepage_size / 2;
- snprintf(target_nr_hugepages, sizeof(target_nr_hugepages),
- "%lu", nr_hugepages_ul);
-
- slen = strlen(target_nr_hugepages);
- if (write(fd, target_nr_hugepages, slen) != slen) {
- ksft_print_msg("Failed to write %lu to /proc/sys/vm/nr_hugepages: %s\n",
- nr_hugepages_ul, strerror(errno));
- goto close_fd;
- }
-
- lseek(fd, 0, SEEK_SET);
-
- if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
- ksft_print_msg("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
- goto close_fd;
- }
+ nr_hugepages = mem_free / hugepage_size / 2;
+ hugetlb_set_nr_default_pages(nr_hugepages);
/* We should have been able to request at least 1/3 rd of the memory in
huge pages */
- nr_hugepages_ul = strtoul(nr_hugepages, NULL, 10);
- if (!nr_hugepages_ul) {
+ nr_hugepages = hugetlb_nr_default_pages();
+ if (!nr_hugepages) {
ksft_print_msg("ERROR: No memory is available as huge pages\n");
- goto close_fd;
- }
- compaction_index = mem_free/(nr_hugepages_ul * hugepage_size);
-
- lseek(fd, 0, SEEK_SET);
-
- if (write(fd, init_nr_hugepages, strlen(init_nr_hugepages))
- != strlen(init_nr_hugepages)) {
- ksft_print_msg("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
- goto close_fd;
+ goto out;
}
+ compaction_index = mem_free/(nr_hugepages * hugepage_size);
- ksft_print_msg("Number of huge pages allocated = %lu\n",
- nr_hugepages_ul);
+ ksft_print_msg("Number of huge pages allocated = %lu\n", nr_hugepages);
if (compaction_index > 3) {
ksft_print_msg("ERROR: Less than 1/%d of memory is available\n"
"as huge pages\n", compaction_index);
- goto close_fd;
- }
-
- ret = 0;
-
- close_fd:
- close(fd);
- out:
- ksft_test_result(ret == 0, "check_compaction\n");
- return ret;
-}
-
-int set_zero_hugepages(unsigned long *initial_nr_hugepages)
-{
- int fd, ret = -1;
- char nr_hugepages[20] = {0};
-
- fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
goto out;
}
- if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
- ksft_print_msg("Failed to read from /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
- goto close_fd;
- }
-
- lseek(fd, 0, SEEK_SET);
- /* Start with the initial condition of 0 huge pages */
- if (write(fd, "0", sizeof(char)) != sizeof(char)) {
- ksft_print_msg("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n",
- strerror(errno));
- goto close_fd;
- }
-
- *initial_nr_hugepages = strtoul(nr_hugepages, NULL, 10);
ret = 0;
- close_fd:
- close(fd);
-
out:
+ ksft_test_result(ret == 0, "check_compaction\n");
return ret;
}
@@ -212,18 +133,17 @@ int main(int argc, char **argv)
unsigned long mem_free = 0;
unsigned long hugepage_size = 0;
long mem_fragmentable_MB = 0;
- unsigned long initial_nr_hugepages;
ksft_print_header();
if (prereq() || geteuid())
ksft_exit_skip("Prerequisites unsatisfied\n");
- ksft_set_plan(1);
-
/* Start the test without hugepages reducing mem_free */
- if (set_zero_hugepages(&initial_nr_hugepages))
- ksft_exit_fail();
+ if (!hugetlb_setup_default_exact(0))
+ ksft_exit_skip("Could not reset nr_hugepages\n");
+
+ ksft_set_plan(1);
lim.rlim_cur = RLIM_INFINITY;
lim.rlim_max = RLIM_INFINITY;
@@ -268,8 +188,7 @@ int main(int argc, char **argv)
entry = entry->next;
}
- if (check_compaction(mem_free, hugepage_size,
- initial_nr_hugepages) == 0)
+ if (check_compaction(mem_free, hugepage_size) == 0)
ksft_exit_pass();
ksft_exit_fail();
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 32/55] selftests/mm: cow: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (30 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 31/55] selftests/mm: compaction_test: use HugeTLB helpers Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 33/55] selftests/mm: gup_longterm: " Mike Rapoport
` (23 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
cow tests skips HugeTLB tests if there are no free huge pages prepared
by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/cow.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/mm/cow.c b/tools/testing/selftests/mm/cow.c
index 5e571216b8d2..0c627ea89ff7 100644
--- a/tools/testing/selftests/mm/cow.c
+++ b/tools/testing/selftests/mm/cow.c
@@ -1881,21 +1881,21 @@ int main(int argc, char **argv)
ksft_print_header();
+ thp_save_settings();
+
pagesize = getpagesize();
pmdsize = read_pmd_pagesize();
if (pmdsize) {
/* Only if THP is supported. */
thp_read_settings(&default_settings);
default_settings.hugepages[sz2ord(pmdsize, pagesize)].enabled = THP_INHERIT;
- thp_save_settings();
thp_push_settings(&default_settings);
ksft_print_msg("[INFO] detected PMD size: %zu KiB\n",
pmdsize / 1024);
nr_thpsizes = detect_thp_sizes(thpsizes, ARRAY_SIZE(thpsizes));
}
- nr_hugetlbsizes = detect_hugetlb_page_sizes(hugetlbsizes,
- ARRAY_SIZE(hugetlbsizes));
+ nr_hugetlbsizes = hugetlb_setup(2, hugetlbsizes, ARRAY_SIZE(hugetlbsizes));
has_huge_zeropage = detect_huge_zeropage();
ksft_set_plan(ARRAY_SIZE(anon_test_cases) * tests_per_anon_test_case() +
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 33/55] selftests/mm: gup_longterm: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (31 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 32/55] selftests/mm: cow: add setup of HugeTLB pages Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 34/55] selftests/mm: gup_test: " Mike Rapoport
` (22 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
gup_longterm tests skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/gup_longterm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c
index 96dae0acd11a..eb8963e9d98f 100644
--- a/tools/testing/selftests/mm/gup_longterm.c
+++ b/tools/testing/selftests/mm/gup_longterm.c
@@ -510,7 +510,7 @@ int main(int argc, char **argv)
int i;
pagesize = getpagesize();
- nr_hugetlbsizes = detect_hugetlb_page_sizes(hugetlbsizes,
+ nr_hugetlbsizes = hugetlb_setup(2, hugetlbsizes,
ARRAY_SIZE(hugetlbsizes));
ksft_print_header();
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 34/55] selftests/mm: gup_test: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (32 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 33/55] selftests/mm: gup_longterm: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 35/55] selftests/mm: hmm-tests: " Mike Rapoport
` (21 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
gup_test fails to run HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the
original settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/gup_test.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/tools/testing/selftests/mm/gup_test.c b/tools/testing/selftests/mm/gup_test.c
index fb8f9ae49efa..3f841a96f870 100644
--- a/tools/testing/selftests/mm/gup_test.c
+++ b/tools/testing/selftests/mm/gup_test.c
@@ -14,6 +14,7 @@
#include <mm/gup_test.h>
#include "kselftest.h"
#include "vm_util.h"
+#include "hugepage_settings.h"
#define MB (1UL << 20)
@@ -94,6 +95,7 @@ int main(int argc, char **argv)
int filed, i, opt, nr_pages = 1, thp = -1, write = 1, nthreads = 1, ret;
int flags = MAP_PRIVATE;
char *file = "/dev/zero";
+ bool hugetlb = false;
pthread_t *tid;
char *p;
@@ -168,6 +170,7 @@ int main(int argc, char **argv)
break;
case 'H':
flags |= (MAP_HUGETLB | MAP_ANONYMOUS);
+ hugetlb = true;
break;
default:
ksft_exit_fail_msg("Wrong argument\n");
@@ -199,6 +202,18 @@ int main(int argc, char **argv)
}
ksft_print_header();
+
+ if (hugetlb) {
+ unsigned long hp_size = default_huge_page_size();
+
+ if (!hp_size)
+ ksft_exit_skip("HugeTLB is unavailable\n");
+
+ size = (size + hp_size - 1) & ~(hp_size - 1);
+ if (!hugetlb_setup_default(size / hp_size))
+ ksft_exit_skip("Not enough huge pages\n");
+ }
+
ksft_set_plan(nthreads);
filed = open(file, O_RDWR|O_CREAT, 0664);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 35/55] selftests/mm: hmm-tests: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (33 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 34/55] selftests/mm: gup_test: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 36/55] selftests/mm: hugepage_dio: " Mike Rapoport
` (20 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hmm-tests skips HugeTLB tests if there are no free huge pages prepared by a
wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Since kselftest_harness runs fixture setup and the tests in child
processes, use HUGETLB_SETUP_DEFAULT_PAGES() that defines a constructor
that runs in the main process and add verification that there are enough
free huge pages to the tests that use them.
Replace exit() calls with _exit() to avoid restoring HugeTLB settings in
the middle of test and use SIGKILL to kill a child process in
hmm_cow_in_device test to avoid interference with signal handlers in
hugepage_restore_settings().
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hmm-tests.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/tools/testing/selftests/mm/hmm-tests.c b/tools/testing/selftests/mm/hmm-tests.c
index 409b11cad4bc..4f4912dcfc81 100644
--- a/tools/testing/selftests/mm/hmm-tests.c
+++ b/tools/testing/selftests/mm/hmm-tests.c
@@ -69,6 +69,9 @@ enum {
#ifndef FOLL_LONGTERM
#define FOLL_LONGTERM 0x100 /* mapping lifetime is indefinite */
#endif
+
+HUGETLB_SETUP_DEFAULT_PAGES(1)
+
FIXTURE(hmm)
{
int fd;
@@ -632,7 +635,7 @@ TEST_F(hmm, anon_write_child)
}
close(child_fd);
- exit(0);
+ _exit(0);
}
}
}
@@ -712,7 +715,7 @@ TEST_F(hmm, anon_write_child_shared)
ASSERT_EQ(ptr[i], -i);
close(child_fd);
- exit(0);
+ _exit(0);
}
/*
@@ -784,8 +787,8 @@ TEST_F(hmm, anon_write_hugetlbfs)
int *ptr;
int ret;
- if (!default_hsize)
- SKIP(return, "Huge page size could not be determined");
+ if (!hugetlb_free_default_pages())
+ SKIP(return, "Not enough huge pages");
size = ALIGN(TWOMEG, default_hsize);
npages = size >> self->page_shift;
@@ -1564,9 +1567,8 @@ TEST_F(hmm, compound)
unsigned long i;
/* Skip test if we can't allocate a hugetlbfs page. */
-
- if (!default_hsize)
- SKIP(return, "Huge page size could not be determined");
+ if (!hugetlb_free_default_pages())
+ SKIP(return, "Not enough huge pages");
size = ALIGN(TWOMEG, default_hsize);
npages = size >> self->page_shift;
@@ -2012,7 +2014,7 @@ TEST_F(hmm, hmm_cow_in_device)
if (pid == -1)
ASSERT_EQ(pid, 0);
if (!pid) {
- /* Child process waits for SIGTERM from the parent. */
+ /* Child process waits for SIGKILL from the parent. */
while (1) {
}
/* Should not reach this */
@@ -2025,10 +2027,10 @@ TEST_F(hmm, hmm_cow_in_device)
ptr[i] = i;
/* Terminate child and wait */
- EXPECT_EQ(0, kill(pid, SIGTERM));
+ EXPECT_EQ(0, kill(pid, SIGKILL));
EXPECT_EQ(pid, waitpid(pid, &status, 0));
EXPECT_NE(0, WIFSIGNALED(status));
- EXPECT_EQ(SIGTERM, WTERMSIG(status));
+ EXPECT_EQ(SIGKILL, WTERMSIG(status));
/* Take snapshot to CPU pagetables */
ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 36/55] selftests/mm: hugepage_dio: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (34 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 35/55] selftests/mm: hmm-tests: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 37/55] selftests/mm: hugetlb_fault_after_madv: " Mike Rapoport
` (19 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugepage_dio test fails if there are no free huge pages prepared by a
wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb_dio.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb_dio.c b/tools/testing/selftests/mm/hugetlb_dio.c
index 47019433ddaf..fb4600570e13 100644
--- a/tools/testing/selftests/mm/hugetlb_dio.c
+++ b/tools/testing/selftests/mm/hugetlb_dio.c
@@ -85,8 +85,6 @@ static void run_dio_using_hugetlb(int fd, unsigned int start_off,
/* Get the default huge page size */
h_pagesize = default_huge_page_size();
- if (!h_pagesize)
- ksft_exit_fail_msg("Unable to determine huge page size\n");
/* Reset file position since fd is shared across tests */
if (lseek(fd, 0, SEEK_SET) < 0)
@@ -94,10 +92,6 @@ static void run_dio_using_hugetlb(int fd, unsigned int start_off,
/* Get the free huge pages before allocation */
free_hpage_b = hugetlb_free_default_pages();
- if (free_hpage_b == 0) {
- close(fd);
- ksft_exit_skip("No free hugepage, exiting!\n");
- }
/* Allocate a hugetlb page */
orig_buffer = mmap(NULL, h_pagesize, mmap_prot, mmap_flags, -1, 0);
@@ -141,8 +135,8 @@ int main(void)
ksft_print_header();
- /* Check if huge pages are free */
- if (!hugetlb_free_default_pages())
+ /* request a huge page */
+ if (!hugetlb_setup_default(1))
ksft_exit_skip("No free hugepage, exiting\n");
fd = open("/tmp", O_TMPFILE | O_RDWR | O_DIRECT, 0664);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 37/55] selftests/mm: hugetlb_fault_after_madv: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (35 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 36/55] selftests/mm: hugepage_dio: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 38/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
` (18 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb_fault_after_madv test skips testing if there are no free huge
pages prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb_fault_after_madv.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
index c718dd065d53..2dc158054f66 100644
--- a/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
+++ b/tools/testing/selftests/mm/hugetlb_fault_after_madv.c
@@ -54,7 +54,6 @@ void *madv(void *unused)
int main(void)
{
- unsigned long free_hugepages;
pthread_t thread1, thread2;
/*
* On kernel 6.4, we are able to reproduce the problem with ~1000
@@ -78,11 +77,8 @@ int main(void)
ksft_print_msg("[INFO] detected default hugetlb page size: %zu KiB\n",
huge_page_size / 1024);
- free_hugepages = hugetlb_free_default_pages();
- if (free_hugepages != 1) {
- ksft_exit_skip("This test needs one and only one page to execute. Got %lu\n",
- free_hugepages);
- }
+ if (!hugetlb_setup_default(1))
+ ksft_exit_skip("Not enough HugeTLB pages\n");
while (max--) {
huge_ptr = mmap(NULL, huge_page_size, PROT_READ | PROT_WRITE,
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 38/55] selftests/mm: hugetlb-madvise: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (36 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 37/55] selftests/mm: hugetlb_fault_after_madv: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 39/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
` (17 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-madvise test skips testing if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-madvise.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-madvise.c b/tools/testing/selftests/mm/hugetlb-madvise.c
index 8adcd91d078d..555b4b3d1430 100644
--- a/tools/testing/selftests/mm/hugetlb-madvise.c
+++ b/tools/testing/selftests/mm/hugetlb-madvise.c
@@ -4,12 +4,6 @@
*
* Basic functional testing of madvise MADV_DONTNEED and MADV_REMOVE
* on hugetlb mappings.
- *
- * Before running this test, make sure the administrator has pre-allocated
- * at least MIN_FREE_PAGES hugetlb pages and they are free. In addition,
- * the test takes an argument that is the path to a file in a hugetlbfs
- * filesystem. Therefore, a hugetlbfs filesystem must be mounted on some
- * directory.
*/
#define _GNU_SOURCE
@@ -68,9 +62,9 @@ int main(int argc, char **argv)
if (!base_page_size)
ksft_exit_fail_msg("Unable to determine base page size\n");
+ if (!hugetlb_setup_default(MIN_FREE_PAGES))
+ ksft_exit_skip("Not enough free huge pages (have %lu, need %d)\n", hugetlb_free_default_pages(), MIN_FREE_PAGES);
free_hugepages = hugetlb_free_default_pages();
- if (free_hugepages < MIN_FREE_PAGES)
- ksft_exit_skip("Not enough free huge pages (have %lu, need %d)\n", free_hugepages, MIN_FREE_PAGES);
fd = memfd_create(argv[0], MFD_HUGETLB);
if (fd < 0)
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 39/55] selftests/mm: hugetlb_madv_vs_map: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (37 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 38/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 40/55] selftests/mm: hugetlb-mmap: " Mike Rapoport
` (16 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb_madv_vs_map test skips testing if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb_madv_vs_map.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
index dfbd71a7f709..f94549efcc6f 100644
--- a/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
+++ b/tools/testing/selftests/mm/hugetlb_madv_vs_map.c
@@ -77,7 +77,6 @@ void *map_extra(void *unused)
int main(void)
{
pthread_t thread1, thread2, thread3;
- unsigned long free_hugepages;
void *ret;
/*
@@ -89,11 +88,9 @@ int main(void)
ksft_print_header();
ksft_set_plan(1);
- free_hugepages = hugetlb_free_default_pages();
-
- if (free_hugepages != 1)
+ if (!hugetlb_setup_default_exact(1))
ksft_exit_skip("This test needs one and only one page to execute. Got %lu\n",
- free_hugepages);
+ hugetlb_free_default_pages());
mmap_size = default_huge_page_size();
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 40/55] selftests/mm: hugetlb-mmap: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (38 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 39/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 41/55] selftests/mm: hugetlb-mremap: " Mike Rapoport
` (15 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-mmap test fails if there are no free huge pages prepared by a
wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-mmap.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-mmap.c b/tools/testing/selftests/mm/hugetlb-mmap.c
index 395be5d0dc1a..0f2aad1b7dbd 100644
--- a/tools/testing/selftests/mm/hugetlb-mmap.c
+++ b/tools/testing/selftests/mm/hugetlb-mmap.c
@@ -105,28 +105,35 @@ int main(int argc, char **argv)
{
size_t hugepage_size;
size_t length = LENGTH;
- int shift = 0;
+ int shift = 0, nr;
ksft_print_header();
- ksft_set_plan(2);
if (argc > 1)
length = atol(argv[1]) << 20;
if (argc > 2)
shift = atoi(argv[2]);
+ hugetlb_save_settings();
if (shift) {
hugepage_size = (1UL << shift);
ksft_print_msg("%lu kB hugepages\n", 1UL << (shift - 10));
} else {
hugepage_size = default_huge_page_size();
+ if (!hugepage_size)
+ ksft_exit_skip("Could not detect default hugetlb page size.");
ksft_print_msg("Default size hugepages (%lu kB)\n", hugepage_size >> 10);
}
/* munmap will fail if the length is not page aligned */
- if (hugepage_size > length)
- length = hugepage_size;
+ length = (length + hugepage_size - 1) & ~(hugepage_size - 1);
+ nr = length / hugepage_size;
+
+ hugetlb_set_nr_pages(hugepage_size, nr);
+ if (hugetlb_free_pages(hugepage_size) < nr)
+ ksft_exit_skip("Not enough %lu Kb pages\n", hugepage_size >> 10);
+ ksft_set_plan(2);
ksft_print_msg("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
test_anon_mmap(length, shift);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 41/55] selftests/mm: hugetlb-mremap: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (39 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 40/55] selftests/mm: hugetlb-mmap: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 42/55] selftests/mm: hugetlb-shm: " Mike Rapoport
` (14 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-mremap test fails if there are no free huge pages prepared by a
wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-mremap.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/hugetlb-mremap.c b/tools/testing/selftests/mm/hugetlb-mremap.c
index 1c87c39780c5..d239905790dd 100644
--- a/tools/testing/selftests/mm/hugetlb-mremap.c
+++ b/tools/testing/selftests/mm/hugetlb-mremap.c
@@ -26,6 +26,7 @@
#include <stdbool.h>
#include "kselftest.h"
#include "vm_util.h"
+#include "hugepage_settings.h"
#define DEFAULT_LENGTH_MB 10UL
#define MB_TO_BYTES(x) (x * 1024 * 1024)
@@ -108,8 +109,9 @@ static void register_region_with_uffd(char *addr, size_t len)
int main(int argc, char *argv[])
{
+ unsigned long hugepage_size;
+ int ret = 0, fd, nr;
size_t length = 0;
- int ret = 0, fd;
ksft_print_header();
ksft_set_plan(1);
@@ -125,7 +127,16 @@ int main(int argc, char *argv[])
else
length = DEFAULT_LENGTH_MB;
+ hugepage_size = default_huge_page_size();
+ if (!hugepage_size)
+ ksft_exit_skip("Could not detect default hugetlb page size\n");
length = MB_TO_BYTES(length);
+ length = (length + hugepage_size - 1) & ~(hugepage_size - 1);
+ nr = length / hugepage_size;
+
+ if (!hugetlb_setup_default(nr))
+ ksft_exit_skip("Not enough huge pages\n");
+
fd = memfd_create(argv[0], MFD_HUGETLB);
if (fd < 0)
ksft_exit_fail_msg("Open failed: %s\n", strerror(errno));
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 42/55] selftests/mm: hugetlb-shm: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (40 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 41/55] selftests/mm: hugetlb-mremap: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 43/55] selftests/mm: hugetlb-soft-offline: " Mike Rapoport
` (13 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-shm test fails if there are no free huge pages prepared by a
wrapper script and shm liimts in proc are too low.
Add setup of HugeTLB pages and shm limits to the test and make sure that
the original settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-shm.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/tools/testing/selftests/mm/hugetlb-shm.c b/tools/testing/selftests/mm/hugetlb-shm.c
index c2c7aee85b96..3ff7f062b7eb 100644
--- a/tools/testing/selftests/mm/hugetlb-shm.c
+++ b/tools/testing/selftests/mm/hugetlb-shm.c
@@ -29,9 +29,27 @@
#include <sys/mman.h>
#include "vm_util.h"
+#include "hugepage_settings.h"
#define LENGTH (256UL*1024*1024)
+static void prepare(void)
+{
+ unsigned long length, hugepage_size, nr;
+
+ hugepage_size = default_huge_page_size();
+ if (!hugepage_size)
+ ksft_exit_skip("Unable to determine huge page size\n");
+
+ length = (LENGTH + hugepage_size - 1) & ~(hugepage_size - 1);
+ nr = length / hugepage_size;
+
+ if (!hugetlb_setup_default(nr))
+ ksft_exit_skip("Not enough free huge pages\n");
+
+ shm_limits_prepare(length);
+}
+
int main(void)
{
int shmid;
@@ -41,6 +59,8 @@ int main(void)
ksft_print_header();
ksft_set_plan(1);
+ prepare();
+
shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
if (shmid < 0)
ksft_exit_fail_perror("shmget");
@@ -76,3 +96,5 @@ int main(void)
ksft_test_result_pass("hugepage using SysV shmget/shmat\n");
ksft_finished();
}
+
+SHM_LIMITS_RESTORE()
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 43/55] selftests/mm: hugetlb-soft-offline: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (41 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 42/55] selftests/mm: hugetlb-shm: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 44/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
` (12 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-soft-offline test uses open coded access to /proc to determine
availability of huge pages and fails if there are no enough free huget
pages..
Replace open coded access to /proc with hugepage helpers and add setup
of HugeTLB pages to the test and make sure that the original settings
are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../selftests/mm/hugetlb-soft-offline.c | 45 ++++---------------
1 file changed, 8 insertions(+), 37 deletions(-)
diff --git a/tools/testing/selftests/mm/hugetlb-soft-offline.c b/tools/testing/selftests/mm/hugetlb-soft-offline.c
index a8bc02688085..bc202e4ed2bd 100644
--- a/tools/testing/selftests/mm/hugetlb-soft-offline.c
+++ b/tools/testing/selftests/mm/hugetlb-soft-offline.c
@@ -6,9 +6,7 @@
* - if enable_soft_offline = 1, a hugepage should be dissolved and
* nr_hugepages/free_hugepages should be reduced by 1.
*
- * Before running, make sure more than 2 hugepages of default_hugepagesz
- * are allocated. For example, if /proc/meminfo/Hugepagesize is 2048kB:
- * echo 8 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
+ * The test allocates 8 default hugepages
*/
#define _GNU_SOURCE
@@ -25,6 +23,7 @@
#include <sys/types.h>
#include "kselftest.h"
+#include "hugepage_settings.h"
#ifndef MADV_SOFT_OFFLINE
#define MADV_SOFT_OFFLINE 101
@@ -100,32 +99,6 @@ static int set_enable_soft_offline(int value)
return 0;
}
-static int read_nr_hugepages(unsigned long hugepage_size,
- unsigned long *nr_hugepages)
-{
- char buffer[256] = {0};
- char cmd[256] = {0};
-
- sprintf(cmd, "cat /sys/kernel/mm/hugepages/hugepages-%ldkB/nr_hugepages",
- hugepage_size);
- FILE *cmdfile = popen(cmd, "r");
-
- if (cmdfile == NULL) {
- ksft_perror(EPREFIX "failed to popen nr_hugepages");
- return -1;
- }
-
- if (!fgets(buffer, sizeof(buffer), cmdfile)) {
- ksft_perror(EPREFIX "failed to read nr_hugepages");
- pclose(cmdfile);
- return -1;
- }
-
- *nr_hugepages = atoll(buffer);
- pclose(cmdfile);
- return 0;
-}
-
static int create_hugetlbfs_file(struct statfs *file_stat)
{
int fd;
@@ -177,20 +150,14 @@ static void test_soft_offline_common(int enable_soft_offline)
ksft_exit_fail_msg("Failed to set enable_soft_offline\n");
}
- if (read_nr_hugepages(hugepagesize_kb, &nr_hugepages_before) != 0) {
- close(fd);
- ksft_exit_fail_msg("Failed to read nr_hugepages\n");
- }
+ nr_hugepages_before = hugetlb_nr_default_pages();
ksft_print_msg("Before MADV_SOFT_OFFLINE nr_hugepages=%ld\n",
nr_hugepages_before);
ret = do_soft_offline(fd, 2 * file_stat.f_bsize, expect_errno);
- if (read_nr_hugepages(hugepagesize_kb, &nr_hugepages_after) != 0) {
- close(fd);
- ksft_exit_fail_msg("Failed to read nr_hugepages\n");
- }
+ nr_hugepages_after = hugetlb_nr_default_pages();
ksft_print_msg("After MADV_SOFT_OFFLINE nr_hugepages=%ld\n",
nr_hugepages_after);
@@ -219,6 +186,10 @@ static void test_soft_offline_common(int enable_soft_offline)
int main(int argc, char **argv)
{
ksft_print_header();
+
+ if (!hugetlb_setup_default(8))
+ ksft_exit_skip("not enough hugetlb pages\n");
+
ksft_set_plan(2);
test_soft_offline_common(1);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 44/55] selftests/mm: hugetlb-vmemmap: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (42 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 43/55] selftests/mm: hugetlb-soft-offline: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 45/55] selftests/mm: migration: " Mike Rapoport
` (11 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
hugetlb-vmemmap test fails if there are no free huge pages prepared by a
wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/hugetlb-vmemmap.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/mm/hugetlb-vmemmap.c b/tools/testing/selftests/mm/hugetlb-vmemmap.c
index af5786bebfd1..507df78a158d 100644
--- a/tools/testing/selftests/mm/hugetlb-vmemmap.c
+++ b/tools/testing/selftests/mm/hugetlb-vmemmap.c
@@ -97,6 +97,9 @@ int main(int argc, char **argv)
ksft_print_header();
ksft_set_plan(1);
+ if (!hugetlb_setup_default(1))
+ ksft_exit_skip("Not enough free huge pages\n");
+
pagesize = psize();
maplength = default_huge_page_size();
if (!maplength)
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 45/55] selftests/mm: migration: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (43 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 44/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 46/55] selftests/mm: pagemap_ioctl: " Mike Rapoport
` (10 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
migration skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Since kselftest_harness runs fixture setup and the tests in child
processes, use HUGETLB_SETUP_DEFAULT_PAGES() that defines a constructor
that runs in the main process and add verification that there are enough
free huge pages to the tests that use them.
Reset signal handlers to defaults in FIXTURE_SETUP() so that sending
SIGTERM and SIGHUP during the tests won't cause restoration of HugeTLB
settings.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/migration.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index 7781a59bb9f8..29f7492453d4 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -23,6 +23,8 @@
#define MAX_RETRIES 100
#define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
+HUGETLB_SETUP_DEFAULT_PAGES(1)
+
FIXTURE(migration)
{
pthread_t *threads;
@@ -32,10 +34,23 @@ FIXTURE(migration)
int n2;
};
+static void reset_signals(void)
+{
+ struct sigaction sa = { .sa_handler = SIG_DFL };
+
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+}
+
FIXTURE_SETUP(migration)
{
int n;
+ reset_signals();
+
if (numa_available() < 0)
SKIP(return, "NUMA not available");
self->nthreads = numa_num_task_cpus() - 2;
@@ -288,6 +303,9 @@ TEST_F_TIMEOUT(migration, private_anon_htlb, 2*RUNTIME)
if (!hugepage_size)
SKIP(return, "Reading HugeTLB pagesize failed");
+ if (hugetlb_free_default_pages() < 1)
+ SKIP(return, "Not enough huge pages");
+
ptr = mmap(NULL, hugepage_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
@@ -316,6 +334,9 @@ TEST_F_TIMEOUT(migration, shared_anon_htlb, 2*RUNTIME)
if (!hugepage_size)
SKIP(return, "Reading HugeTLB pagesize failed");
+ if (hugetlb_free_default_pages() < 1)
+ SKIP(return, "Not enough huge pages");
+
ptr = mmap(NULL, hugepage_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 46/55] selftests/mm: pagemap_ioctl: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (44 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 45/55] selftests/mm: migration: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 47/55] selftests/mm: protection_keys: use library code for HugeTLB setup Mike Rapoport
` (9 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
pagemap-ioctl skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/pagemap_ioctl.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
index 7f9428d6062c..762306177ad8 100644
--- a/tools/testing/selftests/mm/pagemap_ioctl.c
+++ b/tools/testing/selftests/mm/pagemap_ioctl.c
@@ -7,8 +7,6 @@
#include <sys/mman.h>
#include <errno.h>
#include <malloc.h>
-#include "vm_util.h"
-#include "kselftest.h"
#include <linux/types.h>
#include <linux/memfd.h>
#include <linux/userfaultfd.h>
@@ -23,6 +21,10 @@
#include <sys/ipc.h>
#include <sys/shm.h>
+#include "vm_util.h"
+#include "kselftest.h"
+#include "hugepage_settings.h"
+
#define PAGEMAP_BITS_ALL (PAGE_IS_WPALLOWED | PAGE_IS_WRITTEN | \
PAGE_IS_FILE | PAGE_IS_PRESENT | \
PAGE_IS_SWAPPED | PAGE_IS_PFNZERO | \
@@ -1554,6 +1556,9 @@ int main(int __attribute__((unused)) argc, char *argv[])
if (init_uffd())
ksft_exit_skip("Failed to initialize userfaultfd\n");
+ if (!hugetlb_setup_default(4))
+ ksft_print_msg("HugeTLB test will be skipped\n");
+
ksft_set_plan(117);
page_size = getpagesize();
@@ -1605,7 +1610,7 @@ int main(int __attribute__((unused)) argc, char *argv[])
}
/* 5. SHM Hugetlb page testing */
- mem_size = 2*1024*1024;
+ mem_size = default_huge_page_size();
mem = gethugetlb_mem(mem_size, &shmid);
if (mem) {
wp_init(mem, mem_size);
@@ -1633,7 +1638,7 @@ int main(int __attribute__((unused)) argc, char *argv[])
}
/* 7. File Hugetlb testing */
- mem_size = 2*1024*1024;
+ mem_size = default_huge_page_size();
fd = memfd_create("uffd-test", MFD_HUGETLB | MFD_NOEXEC_SEAL);
if (fd < 0)
ksft_exit_fail_msg("uffd-test creation failed %d %s\n", errno, strerror(errno));
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 47/55] selftests/mm: protection_keys: use library code for HugeTLB setup
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (45 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 46/55] selftests/mm: pagemap_ioctl: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 48/55] selftests/mm: thuge-gen: add setup of HugeTLB pages Mike Rapoport
` (8 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
protection_keys open codes setup of HugeTLB pages.
Replace it with the library functions from hugepage_setup.
Replace exit() calls with _exit() to avoid restoring HugeTLB settings in
the middle of test.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/protection_keys.c | 50 ++++++--------------
1 file changed, 14 insertions(+), 36 deletions(-)
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index 4e4aa3b326c1..9a6d954ee371 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -62,6 +62,7 @@ noinline int read_ptr(int *ptr)
return *ptr;
}
+#if CONTROL_TRACING > 0
static void cat_into_file(char *str, char *file)
{
int fd = open(file, O_RDWR);
@@ -87,7 +88,6 @@ static void cat_into_file(char *str, char *file)
close(fd);
}
-#if CONTROL_TRACING > 0
static int warned_tracing;
static int tracing_root_ok(void)
{
@@ -710,50 +710,28 @@ static void *malloc_pkey_anon_huge(long size, int prot, u16 pkey)
}
static int hugetlb_setup_ok;
-#define SYSFS_FMT_NR_HUGE_PAGES "/sys/kernel/mm/hugepages/hugepages-%ldkB/nr_hugepages"
#define GET_NR_HUGE_PAGES 10
static void setup_hugetlbfs(void)
{
- int err;
- int fd;
- char buf[256];
- long hpagesz_kb;
- long hpagesz_mb;
+ long hpagesz_mb = HPAGE_SIZE / 1024 / 1024;
+ unsigned long free_pages;
if (geteuid() != 0) {
ksft_print_msg("WARNING: not run as root, can not do hugetlb test\n");
return;
}
- cat_into_file(__stringify(GET_NR_HUGE_PAGES), "/proc/sys/vm/nr_hugepages");
-
/*
- * Now go make sure that we got the pages and that they
+ * Make sure that we got the pages and that they
* are PMD-level pages. Someone might have made PUD-level
* pages the default.
*/
- hpagesz_kb = HPAGE_SIZE / 1024;
- hpagesz_mb = hpagesz_kb / 1024;
- sprintf(buf, SYSFS_FMT_NR_HUGE_PAGES, hpagesz_kb);
- fd = open(buf, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "opening sysfs %ldM hugetlb config: %s\n",
- hpagesz_mb, strerror(errno));
- return;
- }
-
- /* -1 to guarantee leaving the trailing \0 */
- err = read(fd, buf, sizeof(buf)-1);
- close(fd);
- if (err <= 0) {
- fprintf(stderr, "reading sysfs %ldM hugetlb config: %s\n",
- hpagesz_mb, strerror(errno));
- return;
- }
-
- if (atoi(buf) != GET_NR_HUGE_PAGES) {
- fprintf(stderr, "could not confirm %ldM pages, got: '%s' expected %d\n",
- hpagesz_mb, buf, GET_NR_HUGE_PAGES);
+ hugetlb_save_settings();
+ hugetlb_set_nr_pages(HPAGE_SIZE, GET_NR_HUGE_PAGES);
+ free_pages = hugetlb_free_pages(HPAGE_SIZE);
+ if (free_pages < GET_NR_HUGE_PAGES) {
+ ksft_print_msg("could not confirm %ldM pages, got: '%lu' expected %d\n",
+ hpagesz_mb, free_pages, GET_NR_HUGE_PAGES);
return;
}
@@ -1130,7 +1108,7 @@ static void become_child(void)
/* in the child */
return;
}
- exit(0);
+ _exit(0);
}
/* Assumes that all pkeys other than 'pkey' are unallocated */
@@ -1509,18 +1487,18 @@ static void test_ptrace_modifies_pkru(int *ptr, u16 pkey)
* checking
*/
if (__read_pkey_reg() != new_pkru)
- exit(1);
+ _exit(1);
/* Stop and allow the tracer to clear XSTATE_BV for PKRU */
raise(SIGSTOP);
if (__read_pkey_reg() != 0)
- exit(1);
+ _exit(1);
/* Stop and allow the tracer to examine PKRU */
raise(SIGSTOP);
- exit(0);
+ _exit(0);
}
pkey_assert(child == waitpid(child, &status, 0));
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 48/55] selftests/mm: thuge-gen: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (46 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 47/55] selftests/mm: protection_keys: use library code for HugeTLB setup Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 49/55] selftests/mm: uffd-stress: use hugetlb_save and alloc huge pages Mike Rapoport
` (7 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
thuge-gen skips tests if there are no free huge pages prepared by a wrapper
script and shm liimts in proc are too low.
Replace custom detection of huge pages with the library functions and add
setup of HugeTLB pages and shm limits to the test and make sure that the
original settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/thuge-gen.c | 95 ++++----------------------
1 file changed, 12 insertions(+), 83 deletions(-)
diff --git a/tools/testing/selftests/mm/thuge-gen.c b/tools/testing/selftests/mm/thuge-gen.c
index 1007bc8aa57c..22b9c2f1c35d 100644
--- a/tools/testing/selftests/mm/thuge-gen.c
+++ b/tools/testing/selftests/mm/thuge-gen.c
@@ -1,17 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Test selecting other page sizes for mmap/shmget.
-
- Before running this huge pages for each huge page size must have been
- reserved.
- For large pages beyond MAX_PAGE_ORDER (like 1GB on x86) boot options must
- be used. 1GB wouldn't be tested if it isn't available.
- Also shmmax must be increased.
- And you need to run as root to work around some weird permissions in shm.
- And nothing using huge pages should run in parallel.
- When the program aborts you may need to clean up the shm segments with
- ipcrm -m by hand, like this
- sudo ipcs | awk '$1 == "0x00000000" {print $2}' | xargs -n1 sudo ipcrm -m
- (warning this will remove all if someone else uses them) */
+/* Test selecting other page sizes for mmap/shmget. */
#define _GNU_SOURCE
#include <sys/mman.h>
@@ -21,8 +9,6 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
-#include <glob.h>
-#include <assert.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
@@ -38,15 +24,6 @@
#ifndef SHM_HUGE_SHIFT
#define SHM_HUGE_SHIFT 26
#endif
-#ifndef SHM_HUGE_MASK
-#define SHM_HUGE_MASK 0x3f
-#endif
-#ifndef SHM_HUGE_2MB
-#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
-#endif
-#ifndef SHM_HUGE_1GB
-#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
-#endif
#define NUM_PAGESIZES 5
#define NUM_PAGES 4
@@ -64,32 +41,10 @@ int ilog2(unsigned long v)
void show(unsigned long ps)
{
- char buf[100];
-
if (ps == getpagesize())
return;
- ksft_print_msg("%luMB: ", ps >> 20);
-
- fflush(stdout);
- snprintf(buf, sizeof buf,
- "cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
- ps >> 10);
- system(buf);
-}
-
-unsigned long read_free(unsigned long ps)
-{
- unsigned long val = 0;
- char buf[100];
-
- snprintf(buf, sizeof(buf),
- "/sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
- ps >> 10);
- if (read_sysfs(buf, &val) && ps != getpagesize())
- ksft_print_msg("missing %s\n", buf);
-
- return val;
+ ksft_print_msg("%luMB: %lu\n", ps >> 20, hugetlb_free_pages(ps));
}
void test_mmap(unsigned long size, unsigned flags)
@@ -97,14 +52,14 @@ void test_mmap(unsigned long size, unsigned flags)
char *map;
unsigned long before, after;
- before = read_free(size);
+ before = hugetlb_free_pages(size);
map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, -1, 0);
if (map == MAP_FAILED)
ksft_exit_fail_msg("mmap: %s\n", strerror(errno));
memset(map, 0xff, size*NUM_PAGES);
- after = read_free(size);
+ after = hugetlb_free_pages(size);
show(size);
ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
@@ -121,7 +76,7 @@ void test_shmget(unsigned long size, unsigned flags)
struct shm_info i;
char *map;
- before = read_free(size);
+ before = hugetlb_free_pages(size);
id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags);
if (id < 0) {
if (errno == EPERM) {
@@ -142,7 +97,7 @@ void test_shmget(unsigned long size, unsigned flags)
shmctl(id, IPC_RMID, NULL);
memset(map, 0xff, size*NUM_PAGES);
- after = read_free(size);
+ after = hugetlb_free_pages(size);
show(size);
ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
@@ -154,43 +109,15 @@ void test_shmget(unsigned long size, unsigned flags)
void find_pagesizes(void)
{
unsigned long largest = getpagesize();
- unsigned long shmmax_val = 0;
int i;
- glob_t g;
- glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g);
- assert(g.gl_pathc <= NUM_PAGESIZES);
- for (i = 0; (i < g.gl_pathc) && (num_page_sizes < NUM_PAGESIZES); i++) {
- sscanf(g.gl_pathv[i], "/sys/kernel/mm/hugepages/hugepages-%lukB",
- &page_sizes[num_page_sizes]);
- page_sizes[num_page_sizes] <<= 10;
- ksft_print_msg("Found %luMB\n", page_sizes[i] >> 20);
+ num_page_sizes = hugetlb_setup(NUM_PAGES, page_sizes, ARRAY_SIZE(page_sizes));
- if (page_sizes[num_page_sizes] > largest)
+ for (i = 0; i < num_page_sizes; i++)
+ if (page_sizes[i] > largest)
largest = page_sizes[i];
- if (read_free(page_sizes[num_page_sizes]) >= NUM_PAGES)
- num_page_sizes++;
- else
- ksft_print_msg("SKIP for size %lu MB as not enough huge pages, need %u\n",
- page_sizes[num_page_sizes] >> 20, NUM_PAGES);
- }
- globfree(&g);
-
- read_sysfs("/proc/sys/kernel/shmmax", &shmmax_val);
- if (shmmax_val < NUM_PAGES * largest) {
- ksft_print_msg("WARNING: shmmax is too small to run this test.\n");
- ksft_print_msg("Please run the following command to increase shmmax:\n");
- ksft_print_msg("echo %lu > /proc/sys/kernel/shmmax\n", largest * NUM_PAGES);
- ksft_exit_skip("Test skipped due to insufficient shmmax value.\n");
- }
-
-#if defined(__x86_64__)
- if (largest != 1U<<30) {
- ksft_exit_skip("No GB pages available on x86-64\n"
- "Please boot with hugepagesz=1G hugepages=%d\n", NUM_PAGES);
- }
-#endif
+ shm_limits_prepare(NUM_PAGES * largest);
}
int main(void)
@@ -233,3 +160,5 @@ int main(void)
ksft_finished();
}
+
+SHM_LIMITS_RESTORE()
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 49/55] selftests/mm: uffd-stress: use hugetlb_save and alloc huge pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (47 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 48/55] selftests/mm: thuge-gen: add setup of HugeTLB pages Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 50/55] selftests/mm: uffd-unit-tests: add setup of HugeTLB pages Mike Rapoport
` (6 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
uffd-stress skips HugeTLB tests if there are no free huge pages prepared
by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-stress.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-stress.c b/tools/testing/selftests/mm/uffd-stress.c
index 7c719d789249..43cc79590136 100644
--- a/tools/testing/selftests/mm/uffd-stress.c
+++ b/tools/testing/selftests/mm/uffd-stress.c
@@ -480,9 +480,12 @@ int main(int argc, char **argv)
* Ensure nr_parallel - 1 hugepages on top of that to account
* for racy extra reservation of hugepages.
*/
- if (gopts->test_type == TEST_HUGETLB &&
- hugetlb_free_default_pages() < 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1)
- ksft_exit_skip("Skipping userfaultfd... not enough hugepages\n");
+ if (gopts->test_type == TEST_HUGETLB) {
+ unsigned long nr = 2 * (bytes / gopts->page_size) + gopts->nr_parallel - 1;
+
+ if (!hugetlb_setup_default(nr))
+ ksft_exit_skip("Skipping userfaultfd... not enough hugepages\n");
+ }
gopts->nr_pages_per_cpu = bytes / gopts->page_size / gopts->nr_parallel;
if (!gopts->nr_pages_per_cpu) {
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 50/55] selftests/mm: uffd-unit-tests: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (48 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 49/55] selftests/mm: uffd-stress: use hugetlb_save and alloc huge pages Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 51/55] selftests/mm: uffd-wp-mremap: " Mike Rapoport
` (5 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
uffd-unit-tests skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Replace exit() calls with _exit() to avoid restoring HugeTLB settings in
the middle of test.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-unit-tests.c | 33 +++++++++++++++++---
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c
index db7c26835487..a6c14109e818 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -299,7 +299,7 @@ static int pagemap_test_fork(uffd_global_test_opts_t *gopts, bool with_event, bo
if (test_pin)
unpin_pages(&args);
/* Succeed */
- exit(0);
+ _exit(0);
}
waitpid(child, &result, 0);
@@ -767,7 +767,7 @@ static void uffd_sigbus_test_common(uffd_global_test_opts_t *gopts, bool wp)
err("fork");
if (!pid)
- exit(faulting_process(gopts, 2, wp));
+ _exit(faulting_process(gopts, 2, wp));
waitpid(pid, &err, 0);
if (err)
@@ -821,7 +821,7 @@ static void uffd_events_test_common(uffd_global_test_opts_t *gopts, bool wp)
err("fork");
if (!pid)
- exit(faulting_process(gopts, 0, wp));
+ _exit(faulting_process(gopts, 0, wp));
waitpid(pid, &err, 0);
if (err)
@@ -1700,11 +1700,32 @@ static int uffd_count_tests(int n_tests, int n_mems, const char *test_filter)
return count;
}
+static unsigned long uffd_setup_hugetlb(void)
+{
+ unsigned long nr_hugepages, hp_size;
+
+ hugetlb_save_settings();
+ hp_size = default_huge_page_size();
+
+ if (!hp_size)
+ return 0;
+
+ /* need twice UFFD_TEST_MEM_SIZE, one for src area and one for dst */
+ nr_hugepages = 2 * MAX(UFFD_TEST_MEM_SIZE, hp_size * 2) / hp_size;
+ hugetlb_set_nr_default_pages(nr_hugepages);
+
+ if (hugetlb_free_default_pages() < nr_hugepages)
+ return 0;
+
+ return hp_size;
+}
+
int main(int argc, char *argv[])
{
int n_tests = sizeof(uffd_tests) / sizeof(uffd_test_case_t);
int n_mems = sizeof(mem_types) / sizeof(mem_type_t);
const char *test_filter = NULL;
+ unsigned long hugepage_size;
bool list_only = false;
uffd_test_case_t *test;
mem_type_t *mem_type;
@@ -1738,6 +1759,8 @@ int main(int argc, char *argv[])
return KSFT_PASS;
}
+ hugepage_size = uffd_setup_hugetlb();
+
ksft_print_header();
ksft_set_plan(uffd_count_tests(n_tests, n_mems, test_filter));
@@ -1765,9 +1788,9 @@ int main(int argc, char *argv[])
uffd_test_start("%s on %s", test->name, mem_type->name);
if (mem_type->mem_flag & (MEM_HUGETLB_PRIVATE | MEM_HUGETLB)) {
- gopts.page_size = default_huge_page_size();
+ gopts.page_size = hugepage_size;
if (gopts.page_size == 0) {
- uffd_test_skip("huge page size is 0, feature missing?");
+ uffd_test_skip("not enough HugeTLB pages");
continue;
}
} else {
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 51/55] selftests/mm: uffd-wp-mremap: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (49 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 50/55] selftests/mm: uffd-unit-tests: add setup of HugeTLB pages Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 52/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
` (4 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
uffd-wp-remap skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/uffd-wp-mremap.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/mm/uffd-wp-mremap.c b/tools/testing/selftests/mm/uffd-wp-mremap.c
index b44e02840a5e..90ac410c6c6f 100644
--- a/tools/testing/selftests/mm/uffd-wp-mremap.c
+++ b/tools/testing/selftests/mm/uffd-wp-mremap.c
@@ -336,14 +336,14 @@ int main(int argc, char **argv)
struct thp_settings settings;
int i, j, plan = 0;
+ hugepage_save_settings(true, true);
+
pagesize = getpagesize();
nr_thpsizes = detect_thp_sizes(thpsizes, ARRAY_SIZE(thpsizes));
- nr_hugetlbsizes = detect_hugetlb_page_sizes(hugetlbsizes,
- ARRAY_SIZE(hugetlbsizes));
+ nr_hugetlbsizes = hugetlb_setup(1, hugetlbsizes, ARRAY_SIZE(hugetlbsizes));
- /* If THP is supported, save THP settings and initially disable THP. */
+ /* If THP is supported, initially disable THP. */
if (nr_thpsizes) {
- thp_save_settings();
thp_read_settings(&settings);
for (i = 0; i < NR_ORDERS; i++) {
settings.hugepages[i].enabled = THP_NEVER;
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 52/55] selftests/mm: va_high_addr_switch: add setup of HugeTLB pages
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (50 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 51/55] selftests/mm: uffd-wp-mremap: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 53/55] selftests/mm: va_high_addr_switch.sh: drop huge pages setup Mike Rapoport
` (3 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
va_high_addr_switch skips HugeTLB tests if there are no free huge pages
prepared by a wrapper script.
Add setup of HugeTLB pages to the test and make sure that the original
settings are restored on the test exit.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/va_high_addr_switch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/va_high_addr_switch.c b/tools/testing/selftests/mm/va_high_addr_switch.c
index 0b69bd4b901d..e24d7ba00b44 100644
--- a/tools/testing/selftests/mm/va_high_addr_switch.c
+++ b/tools/testing/selftests/mm/va_high_addr_switch.c
@@ -325,7 +325,7 @@ int main(int argc, char **argv)
if (!supported_arch())
ksft_exit_skip("Architecture not supported\n");
- if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
+ if (hugetlb_setup_default(6))
run_hugetlb = true;
testcases_init();
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 53/55] selftests/mm: va_high_addr_switch.sh: drop huge pages setup
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (51 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 52/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 54/55] selftests/mm: run_vmtests.sh: free memory if available memory is low Mike Rapoport
` (2 subsequent siblings)
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Since va_high_addr_switch takes care of setting up huge pages, there is
no need to set them up in the va_high_addr_switch.sh wrapper script.
Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
.../selftests/mm/va_high_addr_switch.sh | 41 +------------------
1 file changed, 1 insertion(+), 40 deletions(-)
diff --git a/tools/testing/selftests/mm/va_high_addr_switch.sh b/tools/testing/selftests/mm/va_high_addr_switch.sh
index 9492c2d72634..01c15fe3c799 100755
--- a/tools/testing/selftests/mm/va_high_addr_switch.sh
+++ b/tools/testing/selftests/mm/va_high_addr_switch.sh
@@ -9,7 +9,6 @@
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
-orig_nr_hugepages=0
skip()
{
@@ -77,43 +76,5 @@ check_test_requirements()
esac
}
-save_nr_hugepages()
-{
- orig_nr_hugepages=$(cat /proc/sys/vm/nr_hugepages)
-}
-
-restore_nr_hugepages()
-{
- echo "$orig_nr_hugepages" > /proc/sys/vm/nr_hugepages
-}
-
-setup_nr_hugepages()
-{
- local needpgs=$1
- while read -r name size unit; do
- if [ "$name" = "HugePages_Free:" ]; then
- freepgs="$size"
- break
- fi
- done < /proc/meminfo
- if [ "$freepgs" -ge "$needpgs" ]; then
- return
- fi
- local hpgs=$((orig_nr_hugepages + needpgs))
- echo $hpgs > /proc/sys/vm/nr_hugepages
-
- local nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
- if [ "$nr_hugepgs" != "$hpgs" ]; then
- restore_nr_hugepages
- skip "$0: no enough hugepages for testing"
- fi
-}
-
check_test_requirements
-save_nr_hugepages
-# The HugeTLB tests require 6 pages
-setup_nr_hugepages 6
-./va_high_addr_switch --run-hugetlb
-retcode=$?
-restore_nr_hugepages
-exit $retcode
+./va_high_addr_switch
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 54/55] selftests/mm: run_vmtests.sh: free memory if available memory is low
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (52 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 53/55] selftests/mm: va_high_addr_switch.sh: drop huge pages setup Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 55/55] selftests/mm: run_vmtests.sh: drop detection and setup of HugeTLB Mike Rapoport
2026-05-11 21:34 ` [PATCH v4 00/55] make MM selftests more CI friendly Andrew Morton
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
Currently when running THP and HugeTLB tests, if HAVE_HUGEPAGES is set
run_test() drops caches, compacts memory and runs the test. But if
HAVE_HUGEPAGES is not set it skips the tests entirely, even if THP tests
have nothing to do with HAVE_HUGEPAGES.
Replace the check if HAVE_HUGEPAGES is set with a check of how much memory
is available. If there is less than 256 MB of available memory, drop caches
and run compaction and then continue to run a test regardless of
HAVE_HUGEPAGES value.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/run_vmtests.sh | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index b9e520194634..45298157b155 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -234,19 +234,17 @@ pretty_name() {
# Usage: run_test [test binary] [arbitrary test arguments...]
run_test() {
if test_selected ${CATEGORY}; then
- local skip=0
-
# On memory constrainted systems some tests can fail to allocate hugepages.
# perform some cleanup before the test for a higher success rate.
if [ ${CATEGORY} == "thp" -o ${CATEGORY} == "hugetlb" ]; then
- if [ "${HAVE_HUGEPAGES}" = "1" ]; then
+ mem_kb=$(awk '/MemAvailable/ {print $2}' /proc/meminfo)
+ mem_Mb=$((mem_kb / 1024))
+
+ if (( $mem_Mb < 256 )); then
echo 3 > /proc/sys/vm/drop_caches
sleep 2
echo 1 > /proc/sys/vm/compact_memory
sleep 2
- else
- echo "hugepages not supported" | tap_prefix
- skip=1
fi
fi
@@ -255,12 +253,8 @@ run_test() {
local sep=$(echo -n "$title" | tr "[:graph:][:space:]" -)
printf "%s\n%s\n%s\n" "$sep" "$title" "$sep" | tap_prefix
- if [ "${skip}" != "1" ]; then
- ("$@" 2>&1) | tap_prefix
- local ret=${PIPESTATUS[0]}
- else
- local ret=$ksft_skip
- fi
+ ("$@" 2>&1) | tap_prefix
+ local ret=${PIPESTATUS[0]}
count_total=$(( count_total + 1 ))
if [ $ret -eq 0 ]; then
count_pass=$(( count_pass + 1 ))
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH v4 55/55] selftests/mm: run_vmtests.sh: drop detection and setup of HugeTLB
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (53 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 54/55] selftests/mm: run_vmtests.sh: free memory if available memory is low Mike Rapoport
@ 2026-05-11 16:28 ` Mike Rapoport
2026-05-11 21:34 ` [PATCH v4 00/55] make MM selftests more CI friendly Andrew Morton
55 siblings, 0 replies; 57+ messages in thread
From: Mike Rapoport @ 2026-05-11 16:28 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Baolin Wang, Barry Song, Dev Jain, Donet Tom, Jason Gunthorpe,
John Hubbard, Liam R. Howlett, Lance Yang, Li Wang,
Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino, Mark Brown,
Michal Hocko, Mike Rapoport, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
All the tests that use HugeTLB can detect and setup HugeTLB pages on
their own.
Drop detection and setup of HugeTLB from run_vmtests.sh.
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
tools/testing/selftests/mm/run_vmtests.sh | 125 ++--------------------
1 file changed, 7 insertions(+), 118 deletions(-)
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index 45298157b155..73f14894790a 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -132,7 +132,7 @@ test_selected() {
run_gup_matrix() {
# -t: thp=on, -T: thp=off, -H: hugetlb=on
- local hugetlb_mb=$(( needmem_KB / 1024 ))
+ local hugetlb_mb=256
for huge in -t -T "-H -m $hugetlb_mb"; do
# -u: gup-fast, -U: gup-basic, -a: pin-fast, -b: pin-basic, -L: pin-longterm
@@ -154,60 +154,6 @@ run_gup_matrix() {
done
}
-# get huge pagesize and freepages from /proc/meminfo
-while read -r name size unit; do
- if [ "$name" = "HugePages_Free:" ]; then
- freepgs="$size"
- fi
- if [ "$name" = "Hugepagesize:" ]; then
- hpgsize_KB="$size"
- fi
-done < /proc/meminfo
-
-# Simple hugetlbfs tests have a hardcoded minimum requirement of
-# huge pages totaling 256MB (262144KB) in size. The userfaultfd
-# hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take
-# both of these requirements into account and attempt to increase
-# number of huge pages available.
-nr_cpus=$(nproc)
-uffd_min_KB=$((hpgsize_KB * nr_cpus * 2))
-hugetlb_min_KB=$((256 * 1024))
-if [[ $uffd_min_KB -gt $hugetlb_min_KB ]]; then
- needmem_KB=$uffd_min_KB
-else
- needmem_KB=$hugetlb_min_KB
-fi
-
-# set proper nr_hugepages
-if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then
- orig_nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
- needpgs=$((needmem_KB / hpgsize_KB))
- tries=2
- while [ "$tries" -gt 0 ] && [ "$freepgs" -lt "$needpgs" ]; do
- lackpgs=$((needpgs - freepgs))
- echo 3 > /proc/sys/vm/drop_caches
- if ! echo $((lackpgs + orig_nr_hugepgs)) > /proc/sys/vm/nr_hugepages; then
- echo "Please run this test as root"
- exit $ksft_skip
- fi
- while read -r name size unit; do
- if [ "$name" = "HugePages_Free:" ]; then
- freepgs=$size
- fi
- done < /proc/meminfo
- tries=$((tries - 1))
- done
- nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
- if [ "$freepgs" -lt "$needpgs" ]; then
- printf "Not enough huge pages available (%d < %d)\n" \
- "$freepgs" "$needpgs"
- fi
- HAVE_HUGEPAGES=1
-else
- echo "no hugetlbfs support in kernel?"
- HAVE_HUGEPAGES=0
-fi
-
# filter 64bit architectures
ARCH64STR="arm64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sparc64 x86_64"
if [ -z "$ARCH" ]; then
@@ -277,29 +223,13 @@ run_test() {
echo "TAP version 13" | tap_output
CATEGORY="hugetlb" run_test ./hugetlb-mmap
-
-shmmax=$(cat /proc/sys/kernel/shmmax)
-shmall=$(cat /proc/sys/kernel/shmall)
-echo 268435456 > /proc/sys/kernel/shmmax
-echo 4194304 > /proc/sys/kernel/shmall
CATEGORY="hugetlb" run_test ./hugetlb-shm
-echo "$shmmax" > /proc/sys/kernel/shmmax
-echo "$shmall" > /proc/sys/kernel/shmall
-
CATEGORY="hugetlb" run_test ./hugetlb-mremap
CATEGORY="hugetlb" run_test ./hugetlb-vmemmap
CATEGORY="hugetlb" run_test ./hugetlb-madvise
CATEGORY="hugetlb" run_test ./hugetlb_dio
-
-if [ "${HAVE_HUGEPAGES}" = "1" ]; then
- nr_hugepages_tmp=$(cat /proc/sys/vm/nr_hugepages)
- # For this test, we need one and just one huge page
- echo 1 > /proc/sys/vm/nr_hugepages
- CATEGORY="hugetlb" run_test ./hugetlb_fault_after_madv
- CATEGORY="hugetlb" run_test ./hugetlb_madv_vs_map
- # Restore the previous number of huge pages, since further tests rely on it
- echo "$nr_hugepages_tmp" > /proc/sys/vm/nr_hugepages
-fi
+CATEGORY="hugetlb" run_test ./hugetlb_fault_after_madv
+CATEGORY="hugetlb" run_test ./hugetlb_madv_vs_map
if test_selected "hugetlb"; then
echo "NOTE: These hugetlb tests provide minimal coverage. Use" | tap_prefix
@@ -326,44 +256,11 @@ CATEGORY="gup_test" run_test ./gup_longterm
CATEGORY="userfaultfd" run_test ./uffd-unit-tests
uffd_stress_bin=./uffd-stress
CATEGORY="userfaultfd" run_test ${uffd_stress_bin} anon 20 16
-# Hugetlb tests require source and destination huge pages. Pass in almost half
-# the size of the free pages we have, which is used for *each*. An adjustment
-# of (nr_parallel - 1) is done (see nr_parallel in uffd-stress.c) to have some
-# extra hugepages - this is done to prevent the test from failing by racily
-# reserving more hugepages than strictly required.
-# uffd-stress expects a region expressed in MiB, so we adjust
-# half_ufd_size_MB accordingly.
-adjustment=$(( (31 < (nr_cpus - 1)) ? 31 : (nr_cpus - 1) ))
-half_ufd_size_MB=$((((freepgs - adjustment) * hpgsize_KB) / 1024 / 2))
-CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb "$half_ufd_size_MB" 32
-CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb-private "$half_ufd_size_MB" 32
+CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb 128 32
+CATEGORY="userfaultfd" run_test ${uffd_stress_bin} hugetlb-private 128 32
CATEGORY="userfaultfd" run_test ${uffd_stress_bin} shmem 20 16
CATEGORY="userfaultfd" run_test ${uffd_stress_bin} shmem-private 20 16
-# uffd-wp-mremap requires at least one page of each size.
-have_all_size_hugepgs=true
-declare -A nr_size_hugepgs
-for f in /sys/kernel/mm/hugepages/**/nr_hugepages; do
- old=$(cat $f)
- nr_size_hugepgs["$f"]="$old"
- if [ "$old" == 0 ]; then
- echo 1 > "$f"
- fi
- if [ $(cat "$f") == 0 ]; then
- have_all_size_hugepgs=false
- break
- fi
-done
-if $have_all_size_hugepgs; then
- CATEGORY="userfaultfd" run_test ./uffd-wp-mremap
-else
- echo "# SKIP ./uffd-wp-mremap"
-fi
-
-#cleanup
-for f in "${!nr_size_hugepgs[@]}"; do
- echo "${nr_size_hugepgs["$f"]}" > "$f"
-done
-echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
+CATEGORY="userfaultfd" run_test ./uffd-wp-mremap
CATEGORY="compaction" run_test ./compaction_test
@@ -387,12 +284,10 @@ CATEGORY="mremap" run_test ./mremap_test
CATEGORY="hugetlb" run_test ./thuge-gen
CATEGORY="hugetlb" run_test ./charge_reserved_hugetlb.sh -cgroup-v2
CATEGORY="hugetlb" run_test ./hugetlb_reparenting_test.sh -cgroup-v2
+
if $RUN_DESTRUCTIVE; then
-nr_hugepages_tmp=$(cat /proc/sys/vm/nr_hugepages)
enable_soft_offline=$(cat /proc/sys/vm/enable_soft_offline)
-echo 8 > /proc/sys/vm/nr_hugepages
CATEGORY="hugetlb" run_test ./hugetlb-soft-offline
-echo "$nr_hugepages_tmp" > /proc/sys/vm/nr_hugepages
echo "$enable_soft_offline" > /proc/sys/vm/enable_soft_offline
CATEGORY="hugetlb" run_test ./hugetlb-read-hwpoison
fi
@@ -448,7 +343,6 @@ CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0
CATEGORY="ksm" run_test ./ksm_functional_tests
# protection_keys tests
-nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
if [ -x ./protection_keys_32 ]
then
CATEGORY="pkey" run_test ./protection_keys_32
@@ -458,7 +352,6 @@ if [ -x ./protection_keys_64 ]
then
CATEGORY="pkey" run_test ./protection_keys_64
fi
-echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
if [ -x ./soft-dirty ]
then
@@ -539,10 +432,6 @@ if [ -n "${LOADED_MOD}" ]; then
modprobe -r hwpoison_inject > /dev/null 2>&1
fi
-if [ "${HAVE_HUGEPAGES}" = 1 ]; then
- echo "$orig_nr_hugepgs" > /proc/sys/vm/nr_hugepages
-fi
-
echo "SUMMARY: PASS=${count_pass} SKIP=${count_skip} FAIL=${count_fail}" | tap_prefix
echo "1..${count_total}" | tap_output
--
2.53.0
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH v4 00/55] make MM selftests more CI friendly
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
` (54 preceding siblings ...)
2026-05-11 16:28 ` [PATCH v4 55/55] selftests/mm: run_vmtests.sh: drop detection and setup of HugeTLB Mike Rapoport
@ 2026-05-11 21:34 ` Andrew Morton
55 siblings, 0 replies; 57+ messages in thread
From: Andrew Morton @ 2026-05-11 21:34 UTC (permalink / raw)
To: Mike Rapoport
Cc: David Hildenbrand, Baolin Wang, Barry Song, Dev Jain, Donet Tom,
Jason Gunthorpe, John Hubbard, Liam R. Howlett, Lance Yang,
Li Wang, Leon Romanovsky, Lorenzo Stoakes, Luiz Capitulino,
Mark Brown, Michal Hocko, Nico Pache, Peter Xu, Ryan Roberts,
Sarthak Sharma, Shuah Khan, Suren Baghdasaryan, Vlastimil Babka,
Zi Yan, linux-kernel, linux-kselftest, linux-mm
On Mon, 11 May 2026 19:27:44 +0300 Mike Rapoport <rppt@kernel.org> wrote:
> From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
>
> Hi,
>
> There's a lot of dancing around HugeTLB settings in run_vmtests.sh.
> Some test need just a few default huge pages, some require at least 256 MB, and
> some just skip lots of tests if huge pages of all supported sizes are not
> available.
>
> The goal of this set is to make tests deal with HugeTLB setup and teardown.
>
> There are already convenient helpers that allow easy reading and writing of
> /proc and /sysfs, so adding a few APIs that will detect and update HugeTLB
> settings shouldn't be a big deal. But these nice helpers use kselftest
> framework, and many of HugeTLB (and even THP) test don't, so as a result this
> patchset also includes a lot of churn for conversion of those tests to
> kselftest framework (patches 7-19).
>
> @Andrew, I think it's good to go now.
OK, thanks, I've added this to mm-new.
> I'm sure Sashiko will still have somehting to say, but there is really a lot of
> room for imporvement in our selftests and with Sashiko being overly pedantic
> we'd be stuck forever.
Fair enough ;)
^ permalink raw reply [flat|nested] 57+ messages in thread
end of thread, other threads:[~2026-05-11 21:34 UTC | newest]
Thread overview: 57+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-11 16:27 [PATCH v4 00/55] make MM selftests more CI friendly Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 01/55] selftests/mm: hugetlb-read-hwpoison: add SIGBUS handler Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 02/55] selftests/mm: migration: don't assume huge page is TWOMEG Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 03/55] selftests/mm: migration: make nthreads represent number of working threads Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 04/55] selftests/mm: migration: properly cleanup fork()ed processes Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 05/55] selftests/mm: run_vmtests.sh: don't gate THP and KSM tests on HAVE_HUGEPAGES Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 06/55] selftests/mm: merge map_hugetlb into hugepage-mmap Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 07/55] selftests/mm: rename hugepage-* tests to hugetlb-* Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 08/55] selftests/mm: hugetlb-shm: use kselftest framework Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 09/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 10/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 11/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 12/55] selftests/mm: hugetlb-read-hwpoison: " Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 13/55] selftests/mm: khugepaged: group tests in an array Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 14/55] selftests/mm: khugepaged: use ksefltest framework Mike Rapoport
2026-05-11 16:27 ` [PATCH v4 15/55] selftests/mm: ksm_tests: use kselftest framework Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 16/55] selftests/mm: protection_keys: use descriptive test names in the output Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 17/55] selftests/mm: protection_keys: use kselftest framework Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 18/55] selftests/mm: uffd-common: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 19/55] selftests/mm: uffd-stress: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 20/55] selftests/mm: uffd-unit-tests: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 21/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 22/55] selftests/mm: add atexit() and signal handlers to thp_settings Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 23/55] selftests/mm: rename thp_settings.[ch] to hugepage_settings.[ch] Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 24/55] selftests/mm: move HugeTLB helpers to hugepage_settings Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 25/55] selftests/mm: hugepage_settings: use unsigned long in detect_hugetlb_page_size Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 26/55] selftests/mm: hugepage_settings: add APIs to get and set nr_hugepages Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 27/55] selftests/mm: hugepage_settings: rename and rework get_free_hugepages() Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 28/55] selftests/mm: hugepage_settings: add APIs for HugeTLB setup and teardown Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 29/55] selftests/mm: move read_file(), read_num() and write_num() to vm_util Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 30/55] selftests/mm: vm_util: add helpers to set and restore shm limits Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 31/55] selftests/mm: compaction_test: use HugeTLB helpers Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 32/55] selftests/mm: cow: add setup of HugeTLB pages Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 33/55] selftests/mm: gup_longterm: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 34/55] selftests/mm: gup_test: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 35/55] selftests/mm: hmm-tests: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 36/55] selftests/mm: hugepage_dio: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 37/55] selftests/mm: hugetlb_fault_after_madv: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 38/55] selftests/mm: hugetlb-madvise: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 39/55] selftests/mm: hugetlb_madv_vs_map: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 40/55] selftests/mm: hugetlb-mmap: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 41/55] selftests/mm: hugetlb-mremap: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 42/55] selftests/mm: hugetlb-shm: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 43/55] selftests/mm: hugetlb-soft-offline: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 44/55] selftests/mm: hugetlb-vmemmap: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 45/55] selftests/mm: migration: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 46/55] selftests/mm: pagemap_ioctl: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 47/55] selftests/mm: protection_keys: use library code for HugeTLB setup Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 48/55] selftests/mm: thuge-gen: add setup of HugeTLB pages Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 49/55] selftests/mm: uffd-stress: use hugetlb_save and alloc huge pages Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 50/55] selftests/mm: uffd-unit-tests: add setup of HugeTLB pages Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 51/55] selftests/mm: uffd-wp-mremap: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 52/55] selftests/mm: va_high_addr_switch: " Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 53/55] selftests/mm: va_high_addr_switch.sh: drop huge pages setup Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 54/55] selftests/mm: run_vmtests.sh: free memory if available memory is low Mike Rapoport
2026-05-11 16:28 ` [PATCH v4 55/55] selftests/mm: run_vmtests.sh: drop detection and setup of HugeTLB Mike Rapoport
2026-05-11 21:34 ` [PATCH v4 00/55] make MM selftests more CI friendly Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox