]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/mm: thuge-gen: add setup of HugeTLB pages
authorMike Rapoport (Microsoft) <rppt@kernel.org>
Mon, 11 May 2026 16:28:32 +0000 (19:28 +0300)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 21 Jun 2026 18:37:29 +0000 (11:37 -0700)
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.

Link: https://lore.kernel.org/20260511162840.375890-49-rppt@kernel.org
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Tested-by: Luiz Capitulino <luizcap@redhat.com>
Tested-by: Sarthak Sharma <sarthak.sharma@arm.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Donet Tom <donettom@linux.ibm.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Liam Howlett <liam@infradead.org>
Cc: Li Wang <li.wang@linux.dev>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
tools/testing/selftests/mm/thuge-gen.c

index 1007bc8aa57c015c292b8a26c0a7c635b5247e3a..22b9c2f1c35d23735afa3c7471d5f2fcd7cd32d6 100644 (file)
@@ -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>
 #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()