[PATCH RFC 4/5] mm: selftests: Update hugepage-mmap to support hugetlbfs mount

From: Ackerley Tng via B4 Relay

Date: Mon May 18 2026 - 14:23:25 EST


From: Ackerley Tng <ackerleytng@xxxxxxxxxx>

Run the same write/read test for a file on a hugetlbfs mount, in addition
to a memfd.

Use FIXTURE_VARIANT for parametrized testing. Use an unlinked fd to make
save cleanup steps later.

Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
tools/testing/selftests/mm/hugepage-mmap.c | 85 ++++++++++++++++++++++++++++--
1 file changed, 80 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/mm/hugepage-mmap.c b/tools/testing/selftests/mm/hugepage-mmap.c
index 9c8a0638d04b8..dd9fccb209b10 100644
--- a/tools/testing/selftests/mm/hugepage-mmap.c
+++ b/tools/testing/selftests/mm/hugepage-mmap.c
@@ -15,36 +15,111 @@
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <limits.h>
#include "kselftest_harness.h"

+static int hugetlbfs_unlinked_fd(const char *mount)
+{
+ char path[PATH_MAX];
+ int fd;
+
+ snprintf(path, sizeof(path), "%s/hugepage-mmap-XXXXXX", mount);
+ fd = mkstemp(path);
+ if (fd < 0)
+ return fd;
+
+ unlink(path);
+ return fd;
+}
+
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)

+enum fd_kind {
+ MEMFD,
+ HUGETLBFS_FD,
+};
+
FIXTURE(hugepage_mmap)
{
int fd;
char *addr;
+ char mount_dir[PATH_MAX];
+};
+
+static int fd_create(struct __test_metadata *_metadata,
+ FIXTURE_DATA(hugepage_mmap) *self, enum fd_kind fd_kind)
+{
+ switch (fd_kind) {
+ case MEMFD:
+ return memfd_create("hugepage-mmap", MFD_HUGETLB);
+ case HUGETLBFS_FD: {
+ snprintf(self->mount_dir, sizeof(self->mount_dir),
+ "/tmp/hugepage-mmap-XXXXXX");
+ ASSERT_NE(NULL, mkdtemp(self->mount_dir))
+ {
+ TH_LOG("mkdtemp() failed: %s", strerror(errno));
+ }
+ ASSERT_EQ(0, mount("none", self->mount_dir, "hugetlbfs", 0,
+ "pagesize=2M"))
+ {
+ TH_LOG("mount() failed: %s", strerror(errno));
+ }
+ return hugetlbfs_unlinked_fd(self->mount_dir);
+ }
+ default:
+ return -1;
+ };
+}
+
+FIXTURE_VARIANT(hugepage_mmap)
+{
+ enum fd_kind fd_kind;
+};
+
+FIXTURE_VARIANT_ADD(hugepage_mmap, memfd)
+{
+ .fd_kind = MEMFD,
+};
+
+FIXTURE_VARIANT_ADD(hugepage_mmap, hugetlbfs_fd)
+{
+ .fd_kind = HUGETLBFS_FD,
};

FIXTURE_SETUP(hugepage_mmap)
{
- self->fd = memfd_create("hugepage-mmap", MFD_HUGETLB);
+ self->fd = -1;
+ self->addr = MAP_FAILED;
+ self->mount_dir[0] = '\0';
+ /* Enable teardown to cleanup on any assertions in FIXTURE_SETUP(). */
+ *_metadata->no_teardown = false;
+
+ self->fd = fd_create(_metadata, self, variant->fd_kind);
ASSERT_GE(self->fd, 0) {
- TH_LOG("memfd_create() failed: %s", strerror(errno));
+ TH_LOG("fd creation failed: %s", strerror(errno));
}

self->addr = mmap(NULL, LENGTH, PROTECTION, MAP_SHARED, self->fd, 0);
ASSERT_NE(MAP_FAILED, self->addr) {
TH_LOG("mmap(): %s", strerror(errno));
- close(self->fd);
}
TH_LOG("Returned address is %p", self->addr);
}

FIXTURE_TEARDOWN(hugepage_mmap)
{
- munmap(self->addr, LENGTH);
- close(self->fd);
+ if (self->addr != MAP_FAILED)
+ munmap(self->addr, LENGTH);
+ if (self->fd >= 0)
+ close(self->fd);
+
+ if (variant->fd_kind == HUGETLBFS_FD && self->mount_dir[0]) {
+ umount(self->mount_dir);
+ rmdir(self->mount_dir);
+ }
}

TEST_F(hugepage_mmap, read_write)

--
2.54.0.563.g4f69b47b94-goog