From: Pavithra <pavrampu@linux.ibm.com>
To: ltp@lists.linux.it
Cc: pavrampu@linux.ibm.com
Subject: [LTP] [PATCH v10] hugetlb/hugefallocate: Add hugefallocate03 to stress test fallocate on hugetlbfs
Date: Sat, 7 Nov 2026 11:58:11 +0530 [thread overview]
Message-ID: <20261107062811.79329-1-pavrampu@linux.ibm.com> (raw)
Stress test fallocate() on hugetlbfs with three concurrent threads:
one continuously punches and fills holes, one faults in hugepages,
and one continuously mmaps and munmaps the same file range.
Verify no hugepage leak occurs after the stress run.
Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v9 -> v10:
- Save the original SIGBUS handler in thread_fault() and restore it before
the thread exits.
- Replace pthread_cancel()/pthread_testcancel() and the cleanup handler with
a volatile "run" flag.
- Drop the unused thread return value variables and the global
fault_mmap_addr.
Link to v9: https://lore.kernel.org/ltp/20260923080150.44934-1-pavrampu@linux.ibm.com/
---
runtest/hugetlb | 1 +
testcases/kernel/mem/.gitignore | 1 +
.../hugetlb/hugefallocate/hugefallocate03.c | 200 ++++++++++++++++++
3 files changed, 202 insertions(+)
create mode 100644 testcases/kernel/mem/hugetlb/hugefallocate/hugefallocate03.c
diff --git a/runtest/hugetlb b/runtest/hugetlb
index fd687a14e..2e7bd1779 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -1,5 +1,6 @@
hugefallocate01 hugefallocate01
hugefallocate02 hugefallocate02
+hugefallocate03 hugefallocate03
hugefork01 hugefork01
hugefork02 hugefork02
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 763f134dd..f4d5a6dae 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -2,6 +2,7 @@
/cpuset/cpuset02
/hugetlb/hugefallocate/hugefallocate01
/hugetlb/hugefallocate/hugefallocate02
+/hugetlb/hugefallocate/hugefallocate03
/hugetlb/hugefork/hugefork01
/hugetlb/hugefork/hugefork02
/hugetlb/hugemmap/hugemmap01
diff --git a/testcases/kernel/mem/hugetlb/hugefallocate/hugefallocate03.c b/testcases/kernel/mem/hugetlb/hugefallocate/hugefallocate03.c
new file mode 100644
index 000000000..a63fa2f8f
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugefallocate/hugefallocate03.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Pavithra <pavrampu@linux.ibm.com>
+ */
+
+/*\
+ * Stress test :manpage:`fallocate(2)`. This test starts three threads:
+ *
+ * - Thread one will continually punch/fill holes via :manpage:`fallocate(2)`.
+ * - Thread two will continually fault in those same pages.
+ * - Thread three will continually :manpage:`mmap(2)` / :manpage:`munmap(2)` that page range.
+ *
+ * Requires root to mount hugetlbfs.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <time.h>
+
+#include "hugetlb.h"
+#include "lapi/fallocate.h"
+#include "tst_safe_pthread.h"
+
+#define MNTPOINT "hugetlbfs/"
+#define MAX_PAGES_TO_USE 100
+#define FALLOCATE_ITERATIONS 100000
+
+static int fd = -1;
+static unsigned long max_hpages;
+static long hpage_size;
+static void *thread_fallocate(void *arg)
+{
+ int i, err;
+ long tpage;
+
+ (void)arg;
+
+ for (i = 0; i < FALLOCATE_ITERATIONS; i++) {
+ tpage = ((long long)random()) % (max_hpages);
+ err = fallocate(fd,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ tpage * hpage_size, hpage_size);
+ if (err) {
+ tst_res(TFAIL | TERRNO, "fallocate(PUNCH_HOLE) failed at page %ld", tpage);
+ return NULL;
+ }
+ err = fallocate(fd, 0, tpage * hpage_size, hpage_size);
+ if (err) {
+ tst_res(TFAIL | TERRNO, "fallocate(fill) failed at page %ld", tpage);
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+static volatile int run;
+static sigjmp_buf fault_jmp;
+
+static void sigbus_handler(int signum LTP_ATTRIBUTE_UNUSED)
+{
+ siglongjmp(fault_jmp, 1);
+}
+
+static void *thread_fault(void *arg)
+{
+ long tpage;
+ char foo;
+ void *addr;
+ struct sigaction sa = {
+ .sa_handler = sigbus_handler,
+ };
+ struct sigaction old_sa;
+
+ (void)arg;
+
+ SAFE_SIGACTION(SIGBUS, &sa, &old_sa);
+
+ addr = SAFE_MMAP(NULL, max_hpages * hpage_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+
+ while (run) {
+ tpage = ((long long)random()) % (max_hpages);
+
+ if (sigsetjmp(fault_jmp, 1) == 0) {
+ foo = *((char *)(addr + (tpage * hpage_size)));
+ *((volatile char *)(addr + (tpage * hpage_size))) = foo;
+ }
+ }
+
+ SAFE_MUNMAP(addr, max_hpages * hpage_size);
+
+ /* fault_jmp is no longer valid once this thread exits */
+ SAFE_SIGACTION(SIGBUS, &old_sa, NULL);
+
+ return NULL;
+}
+
+static void *thread_mmap_munmap(void *arg)
+{
+ void *addr;
+
+ (void)arg;
+
+ while (run) {
+ addr = mmap(NULL, max_hpages * hpage_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (addr != MAP_FAILED)
+ SAFE_MUNMAP(addr, max_hpages * hpage_size);
+ }
+
+ return NULL;
+}
+
+static void run_test(void)
+{
+ int err;
+ long nr_hpages_free;
+ unsigned long free_before, free_after;
+ unsigned long rsvd_before, rsvd_after;
+ pthread_t falloc_th, fault_th, mmap_munmap_th;
+
+ fd = tst_creat_unlinked(MNTPOINT, 0, 0600);
+
+ unsigned int seed = (unsigned int)getpid() * time(NULL);
+
+ srandom(seed);
+ tst_res(TINFO, "Seed = %u", seed);
+ nr_hpages_free = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
+ max_hpages = MIN(nr_hpages_free, MAX_PAGES_TO_USE);
+ free_before = nr_hpages_free;
+ rsvd_before = SAFE_READ_MEMINFO(MEMINFO_HPAGE_RSVD);
+
+ /* First preallocate file with max_hpages pages */
+ err = fallocate(fd, 0, 0, hpage_size * max_hpages);
+ if (err) {
+ if (errno == EOPNOTSUPP)
+ tst_brk(TCONF, "fallocate() Operation is not supported");
+ tst_brk(TBROK | TERRNO, "fallocate() failed to preallocate");
+ }
+
+ free_after = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
+ if (free_before - free_after != max_hpages) {
+ tst_brk(TBROK, "fallocate did not preallocate %lu huge pages",
+ max_hpages);
+ }
+
+ run = 1;
+
+ SAFE_PTHREAD_CREATE(&falloc_th, NULL, thread_fallocate, NULL);
+
+ SAFE_PTHREAD_CREATE(&fault_th, NULL, thread_fault, NULL);
+
+ SAFE_PTHREAD_CREATE(&mmap_munmap_th, NULL, thread_mmap_munmap, NULL);
+
+ SAFE_PTHREAD_JOIN(falloc_th, NULL);
+
+ run = 0;
+
+ SAFE_PTHREAD_JOIN(fault_th, NULL);
+
+ SAFE_PTHREAD_JOIN(mmap_munmap_th, NULL);
+
+ SAFE_CLOSE(fd);
+
+ free_after = SAFE_READ_MEMINFO(MEMINFO_HPAGE_FREE);
+ rsvd_after = SAFE_READ_MEMINFO(MEMINFO_HPAGE_RSVD);
+
+ TST_EXP_EQ_LU(free_after, free_before);
+ TST_EXP_EQ_LU(rsvd_after, rsvd_before);
+}
+
+static void setup(void)
+{
+ hpage_size = tst_get_hugepage_size();
+}
+
+static void cleanup(void)
+{
+ if (fd != -1)
+ SAFE_CLOSE(fd);
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .mntpoint = MNTPOINT,
+ .needs_hugetlbfs = 1,
+ .needs_tmpdir = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run_test,
+ .hugepages = {MAX_PAGES_TO_USE, TST_REQUEST},
+};
--
2.56.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next reply other threads:[~2026-11-07 6:28 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 6:28 Pavithra [this message]
2026-11-07 10:51 ` [LTP] hugetlb/hugefallocate: Add hugefallocate03 to stress test fallocate on hugetlbfs linuxtestproject.agent
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261107062811.79329-1-pavrampu@linux.ibm.com \
--to=pavrampu@linux.ibm.com \
--cc=ltp@lists.linux.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.