* [LTP] [PATCH v3] userfaultfd: Add new test using UFFDIO_CONTINUE
@ 2026-03-31 22:03 Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Ricardo Branco @ 2026-03-31 22:03 UTC (permalink / raw)
To: ltp
Add test to exercise UFFDIO_CONTINUE on a shared-memory mapping with
UFFD_PAGEFAULT_FLAG_MINOR. The test populates a memfd-backed page,
drops only the PTEs with MADV_DONTNEED, verifies that the resulting
fault is reported as MINOR, updates the page cache from the handler
thread, and resumes execution with UFFDIO_CONTINUE.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/userfaultfd.h | 1 +
runtest/syscalls | 1 +
.../kernel/syscalls/userfaultfd/.gitignore | 1 +
.../kernel/syscalls/userfaultfd/Makefile | 1 +
.../syscalls/userfaultfd/userfaultfd07.c | 152 ++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
diff --git a/include/lapi/userfaultfd.h b/include/lapi/userfaultfd.h
index aab3890b7..c05b8dbf5 100644
--- a/include/lapi/userfaultfd.h
+++ b/include/lapi/userfaultfd.h
@@ -171,6 +171,7 @@ struct uffdio_zeropage {
#ifndef UFFD_PAGEFAULT_FLAG_MINOR
#define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
+#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2)
#define _UFFDIO_CONTINUE (0x07)
#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \
diff --git a/runtest/syscalls b/runtest/syscalls
index 6ba0227a8..534140f42 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1780,6 +1780,7 @@ userfaultfd03 userfaultfd03
userfaultfd04 userfaultfd04
userfaultfd05 userfaultfd05
userfaultfd06 userfaultfd06
+userfaultfd07 userfaultfd07
ustat01 ustat01
ustat02 ustat02
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index bc32fdf3b..3478a162e 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -4,3 +4,4 @@
/userfaultfd04
/userfaultfd05
/userfaultfd06
+/userfaultfd07
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 3252e47df..257249e88 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -17,3 +17,4 @@ userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
userfaultfd06: CFLAGS += -pthread
+userfaultfd07: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
new file mode 100644
index 000000000..9d37589e8
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rbranco@suse.com>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different thread testing UFFDIO_CONTINUE.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_prw.h"
+#include "tst_safe_pthread.h"
+#include "lapi/memfd.h"
+#include "lapi/userfaultfd.h"
+#include "lapi/syscalls.h"
+
+static long page_size;
+static char *page;
+static int uffd = -1;
+static int memfd = -1;
+
+static void set_pages(void)
+{
+ char ch = 'A';
+
+ page_size = SAFE_SYSCONF(_SC_PAGE_SIZE);
+
+ memfd = sys_memfd_create("ltp-uffd-continue", MFD_CLOEXEC);
+ if (memfd < 0)
+ tst_brk(TBROK | TERRNO, "memfd_create failed");
+
+ SAFE_FTRUNCATE(memfd, page_size);
+
+ /*
+ * Populate page cache so that after MADV_DONTNEED the next access
+ * can generate a MINOR fault rather than a MISSING fault.
+ */
+ SAFE_PWRITE(1, memfd, &ch, 1, 0);
+
+ page = SAFE_MMAP(NULL, page_size, PROT_READ, MAP_SHARED, memfd, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+
+ if (memfd != -1)
+ memfd = -1;
+
+ if (uffd != -1)
+ SAFE_CLOSE(uffd);
+}
+
+static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ static struct uffd_msg msg;
+ struct uffdio_continue uffdio_continue = {};
+ struct pollfd pollfd;
+ int nready;
+ char z = 'Z';
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR)) {
+ tst_brk(TBROK, "expected MINOR fault, got flags=0x%llx",
+ (unsigned long long)msg.arg.pagefault.flags);
+ }
+
+ /* Update the shmem page in page cache before resuming the fault. */
+ SAFE_PWRITE(1, memfd, &z, 1, 0);
+
+ uffdio_continue.range.start =
+ msg.arg.pagefault.address & ~((unsigned long)page_size - 1);
+ uffdio_continue.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_CONTINUE, &uffdio_continue);
+
+ SAFE_CLOSE(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thr;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, true);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_MINOR_SHMEM;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ if (!(uffdio_api.features & UFFD_FEATURE_MINOR_SHMEM))
+ tst_brk(TCONF, "UFFD_FEATURE_MINOR_SHMEM not supported");
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ /*
+ * Drop PTEs while retaining the cached shmem page so the next access
+ * faults in MINOR mode.
+ */
+ if (madvise(page, page_size, MADV_DONTNEED) < 0)
+ tst_brk(TBROK | TERRNO, "madvise MADV_DONTNEED failed");
+
+ SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
+
+ char c = page[0];
+
+ if (c == 'Z')
+ tst_res(TPASS, "Pagefault handled via UFFDIO_CONTINUE");
+ else
+ tst_res(TFAIL, "pagefault not handled via UFFDIO_CONTINUE, got '%c'", c);
+
+ SAFE_PTHREAD_JOIN(thr, NULL);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ /*
+ * UFFDIO_CONTINUE is available since 5.13 but
+ * UFFD_FEATURE_MINOR_SHMEM appeared in 5.14
+ */
+ .min_kver = "5.14",
+ .cleanup = reset_pages,
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h
2026-03-31 22:03 [LTP] [PATCH v3] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
@ 2026-04-01 21:03 ` Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-09 15:19 ` [LTP] [PATCH v5 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2 siblings, 1 reply; 10+ messages in thread
From: Ricardo Branco @ 2026-04-01 21:03 UTC (permalink / raw)
To: ltp
Add the static inline wrapper to include/lapi/memfd.h and include the
required headers so other tests can reuse it.
Also fix some minor issues detected by make check.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/memfd.h | 8 ++++++++
testcases/kernel/syscalls/memfd_create/memfd_create01.c | 1 -
.../kernel/syscalls/memfd_create/memfd_create_common.c | 5 -----
.../kernel/syscalls/memfd_create/memfd_create_common.h | 2 +-
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/include/lapi/memfd.h b/include/lapi/memfd.h
index 57b6cd83d..46ccb0a3f 100644
--- a/include/lapi/memfd.h
+++ b/include/lapi/memfd.h
@@ -6,6 +6,9 @@
#ifndef LAPI_MEMFD_H__
#define LAPI_MEMFD_H__
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
/* flags for memfd_create(2) (unsigned int) */
#ifndef MFD_CLOEXEC
# define MFD_CLOEXEC 0x0001U
@@ -47,4 +50,9 @@
#define MFD_HUGE_16GB (34 << 26)
#endif
+static inline int sys_memfd_create(const char *name, unsigned int flags)
+{
+ return tst_syscall(__NR_memfd_create, name, flags);
+}
+
#endif /* LAPI_MEMFD_H__ */
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create01.c b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
index 73f6b01e8..28ad04a86 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create01.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
@@ -212,7 +212,6 @@ static void test_share_open(int fd)
SAFE_CLOSE(fd2);
}
-
static const struct tcase {
int flags;
void (*func)(int fd);
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
index a52b02a56..63e8daac5 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
@@ -24,11 +24,6 @@
#include "memfd_create_common.h"
-int sys_memfd_create(const char *name, unsigned int flags)
-{
- return tst_syscall(__NR_memfd_create, name, flags);
-}
-
int check_fallocate(const char *filename, const int lineno, int fd,
int mode, off_t offset, off_t len)
{
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
index 60ad895fe..8e5a3efbd 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
@@ -50,7 +50,7 @@
check_munmap(__FILE__, __LINE__, (p), (length))
#define CHECK_MFD_HAS_SEALS(fd, seals) \
- check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals));
+ check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals))
#define CHECK_MFD_ADD_SEALS(fd, seals) \
({int r = SAFE_FCNTL((fd), F_ADD_SEALS, (seals)); \
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE
2026-04-01 21:03 ` [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
@ 2026-04-01 21:03 ` Ricardo Branco
2026-04-09 14:15 ` Andrea Cervesato via ltp
0 siblings, 1 reply; 10+ messages in thread
From: Ricardo Branco @ 2026-04-01 21:03 UTC (permalink / raw)
To: ltp
Add test to exercise UFFDIO_CONTINUE on a shared-memory mapping with
UFFD_PAGEFAULT_FLAG_MINOR. The test populates a memfd-backed page,
drops only the PTEs with MADV_DONTNEED, verifies that the resulting
fault is reported as MINOR, updates the page cache from the handler
thread, and resumes execution with UFFDIO_CONTINUE.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/userfaultfd.h | 1 +
runtest/syscalls | 1 +
.../kernel/syscalls/userfaultfd/.gitignore | 1 +
.../kernel/syscalls/userfaultfd/Makefile | 1 +
.../syscalls/userfaultfd/userfaultfd07.c | 152 ++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
diff --git a/include/lapi/userfaultfd.h b/include/lapi/userfaultfd.h
index aab3890b7..c05b8dbf5 100644
--- a/include/lapi/userfaultfd.h
+++ b/include/lapi/userfaultfd.h
@@ -171,6 +171,7 @@ struct uffdio_zeropage {
#ifndef UFFD_PAGEFAULT_FLAG_MINOR
#define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
+#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2)
#define _UFFDIO_CONTINUE (0x07)
#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \
diff --git a/runtest/syscalls b/runtest/syscalls
index 6ba0227a8..534140f42 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1780,6 +1780,7 @@ userfaultfd03 userfaultfd03
userfaultfd04 userfaultfd04
userfaultfd05 userfaultfd05
userfaultfd06 userfaultfd06
+userfaultfd07 userfaultfd07
ustat01 ustat01
ustat02 ustat02
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index bc32fdf3b..3478a162e 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -4,3 +4,4 @@
/userfaultfd04
/userfaultfd05
/userfaultfd06
+/userfaultfd07
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 3252e47df..257249e88 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -17,3 +17,4 @@ userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
userfaultfd06: CFLAGS += -pthread
+userfaultfd07: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
new file mode 100644
index 000000000..96b273262
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rbranco@suse.com>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different thread testing UFFDIO_CONTINUE.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_prw.h"
+#include "tst_safe_pthread.h"
+#include "lapi/memfd.h"
+#include "lapi/userfaultfd.h"
+#include "lapi/syscalls.h"
+
+static long page_size;
+static char *page;
+static int uffd = -1;
+static int memfd = -1;
+
+static void set_pages(void)
+{
+ char ch = 'A';
+
+ page_size = SAFE_SYSCONF(_SC_PAGE_SIZE);
+
+ memfd = sys_memfd_create("ltp-uffd-continue", MFD_CLOEXEC);
+ if (memfd < 0)
+ tst_brk(TBROK | TERRNO, "memfd_create failed");
+
+ SAFE_FTRUNCATE(memfd, page_size);
+
+ /*
+ * Populate page cache so that after MADV_DONTNEED the next access
+ * can generate a MINOR fault rather than a MISSING fault.
+ */
+ SAFE_PWRITE(1, memfd, &ch, 1, 0);
+
+ page = SAFE_MMAP(NULL, page_size, PROT_READ, MAP_SHARED, memfd, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+
+ if (memfd != -1)
+ SAFE_CLOSE(memfd);
+
+ if (uffd != -1)
+ SAFE_CLOSE(uffd);
+}
+
+static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ static struct uffd_msg msg;
+ struct uffdio_continue uffdio_continue = {};
+ struct pollfd pollfd;
+ int nready;
+ char z = 'Z';
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR)) {
+ tst_brk(TBROK, "expected MINOR fault, got flags=0x%llx",
+ (unsigned long long)msg.arg.pagefault.flags);
+ }
+
+ /* Update the shmem page in page cache before resuming the fault. */
+ SAFE_PWRITE(1, memfd, &z, 1, 0);
+
+ uffdio_continue.range.start =
+ msg.arg.pagefault.address & ~((unsigned long)page_size - 1);
+ uffdio_continue.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_CONTINUE, &uffdio_continue);
+
+ SAFE_CLOSE(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thr;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, true);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_MINOR_SHMEM;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ if (!(uffdio_api.features & UFFD_FEATURE_MINOR_SHMEM))
+ tst_brk(TCONF, "UFFD_FEATURE_MINOR_SHMEM not supported");
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ /*
+ * Drop PTEs while retaining the cached shmem page so the next access
+ * faults in MINOR mode.
+ */
+ if (madvise(page, page_size, MADV_DONTNEED) < 0)
+ tst_brk(TBROK | TERRNO, "madvise MADV_DONTNEED failed");
+
+ SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
+
+ char c = page[0];
+
+ if (c == 'Z')
+ tst_res(TPASS, "Pagefault handled via UFFDIO_CONTINUE");
+ else
+ tst_res(TFAIL, "pagefault not handled via UFFDIO_CONTINUE, got '%c'", c);
+
+ SAFE_PTHREAD_JOIN(thr, NULL);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ /*
+ * UFFDIO_CONTINUE is available since 5.13 but
+ * UFFD_FEATURE_MINOR_SHMEM appeared in 5.14
+ */
+ .min_kver = "5.14",
+ .cleanup = reset_pages,
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE
2026-04-01 21:03 ` [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
@ 2026-04-09 14:15 ` Andrea Cervesato via ltp
2026-04-09 14:51 ` Andrea Cervesato via ltp
0 siblings, 1 reply; 10+ messages in thread
From: Andrea Cervesato via ltp @ 2026-04-09 14:15 UTC (permalink / raw)
To: Ricardo Branco; +Cc: ltp
Hi Ricardo,
there must be something wrong with the patches you sent. I see v4 (last one
was v2) and patch #2 in a set of 2 patches (but only one is available).
Can you send the correct verion please? I will set the v3 as broken because
LTP is not compiling with that one.
Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE
2026-04-09 14:15 ` Andrea Cervesato via ltp
@ 2026-04-09 14:51 ` Andrea Cervesato via ltp
0 siblings, 0 replies; 10+ messages in thread
From: Andrea Cervesato via ltp @ 2026-04-09 14:51 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: ltp
Hi,
sorry I was confused by the patchwork interface (sigh). All good, I will
review the v4.
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v5 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h
2026-03-31 22:03 [LTP] [PATCH v3] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
@ 2026-04-09 15:19 ` Ricardo Branco
2026-04-09 15:19 ` [LTP] [PATCH v5 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2 siblings, 1 reply; 10+ messages in thread
From: Ricardo Branco @ 2026-04-09 15:19 UTC (permalink / raw)
To: ltp
Add the static inline wrapper to include/lapi/memfd.h and include the
required headers so other tests can reuse it.
Also fix some minor issues detected by make check.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/memfd.h | 8 ++++++++
testcases/kernel/syscalls/memfd_create/memfd_create01.c | 1 -
.../kernel/syscalls/memfd_create/memfd_create_common.c | 5 -----
.../kernel/syscalls/memfd_create/memfd_create_common.h | 4 +---
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/lapi/memfd.h b/include/lapi/memfd.h
index 57b6cd83d..46ccb0a3f 100644
--- a/include/lapi/memfd.h
+++ b/include/lapi/memfd.h
@@ -6,6 +6,9 @@
#ifndef LAPI_MEMFD_H__
#define LAPI_MEMFD_H__
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
/* flags for memfd_create(2) (unsigned int) */
#ifndef MFD_CLOEXEC
# define MFD_CLOEXEC 0x0001U
@@ -47,4 +50,9 @@
#define MFD_HUGE_16GB (34 << 26)
#endif
+static inline int sys_memfd_create(const char *name, unsigned int flags)
+{
+ return tst_syscall(__NR_memfd_create, name, flags);
+}
+
#endif /* LAPI_MEMFD_H__ */
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create01.c b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
index 73f6b01e8..28ad04a86 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create01.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
@@ -212,7 +212,6 @@ static void test_share_open(int fd)
SAFE_CLOSE(fd2);
}
-
static const struct tcase {
int flags;
void (*func)(int fd);
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
index a52b02a56..63e8daac5 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
@@ -24,11 +24,6 @@
#include "memfd_create_common.h"
-int sys_memfd_create(const char *name, unsigned int flags)
-{
- return tst_syscall(__NR_memfd_create, name, flags);
-}
-
int check_fallocate(const char *filename, const int lineno, int fd,
int mode, off_t offset, off_t len)
{
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
index 60ad895fe..df809d6c7 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
@@ -50,7 +50,7 @@
check_munmap(__FILE__, __LINE__, (p), (length))
#define CHECK_MFD_HAS_SEALS(fd, seals) \
- check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals));
+ check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals))
#define CHECK_MFD_ADD_SEALS(fd, seals) \
({int r = SAFE_FCNTL((fd), F_ADD_SEALS, (seals)); \
@@ -101,8 +101,6 @@ int mfd_flags_available(const char *filename, const int lineno,
int get_mfd_all_available_flags(const char *filename, const int lineno);
-int sys_memfd_create(const char *name, unsigned int flags);
-
int check_fallocate(const char *filename, const int lineno, int fd,
int mode, off_t offset, off_t len);
int check_fallocate_fail(const char *filename, const int lineno, int fd,
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [LTP] [PATCH v5 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE
2026-04-09 15:19 ` [LTP] [PATCH v5 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
@ 2026-04-09 15:19 ` Ricardo Branco
0 siblings, 0 replies; 10+ messages in thread
From: Ricardo Branco @ 2026-04-09 15:19 UTC (permalink / raw)
To: ltp
Add test to exercise UFFDIO_CONTINUE on a shared-memory mapping with
UFFD_PAGEFAULT_FLAG_MINOR. The test populates a memfd-backed page,
drops only the PTEs with MADV_DONTNEED, verifies that the resulting
fault is reported as MINOR, updates the page cache from the handler
thread, and resumes execution with UFFDIO_CONTINUE.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/userfaultfd.h | 1 +
runtest/syscalls | 1 +
.../kernel/syscalls/userfaultfd/.gitignore | 1 +
.../kernel/syscalls/userfaultfd/Makefile | 1 +
.../syscalls/userfaultfd/userfaultfd07.c | 152 ++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
diff --git a/include/lapi/userfaultfd.h b/include/lapi/userfaultfd.h
index aab3890b7..c05b8dbf5 100644
--- a/include/lapi/userfaultfd.h
+++ b/include/lapi/userfaultfd.h
@@ -171,6 +171,7 @@ struct uffdio_zeropage {
#ifndef UFFD_PAGEFAULT_FLAG_MINOR
#define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
+#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2)
#define _UFFDIO_CONTINUE (0x07)
#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \
diff --git a/runtest/syscalls b/runtest/syscalls
index 6ba0227a8..534140f42 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1780,6 +1780,7 @@ userfaultfd03 userfaultfd03
userfaultfd04 userfaultfd04
userfaultfd05 userfaultfd05
userfaultfd06 userfaultfd06
+userfaultfd07 userfaultfd07
ustat01 ustat01
ustat02 ustat02
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index bc32fdf3b..3478a162e 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -4,3 +4,4 @@
/userfaultfd04
/userfaultfd05
/userfaultfd06
+/userfaultfd07
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 3252e47df..257249e88 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -17,3 +17,4 @@ userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
userfaultfd06: CFLAGS += -pthread
+userfaultfd07: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
new file mode 100644
index 000000000..96b273262
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rbranco@suse.com>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different thread testing UFFDIO_CONTINUE.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_prw.h"
+#include "tst_safe_pthread.h"
+#include "lapi/memfd.h"
+#include "lapi/userfaultfd.h"
+#include "lapi/syscalls.h"
+
+static long page_size;
+static char *page;
+static int uffd = -1;
+static int memfd = -1;
+
+static void set_pages(void)
+{
+ char ch = 'A';
+
+ page_size = SAFE_SYSCONF(_SC_PAGE_SIZE);
+
+ memfd = sys_memfd_create("ltp-uffd-continue", MFD_CLOEXEC);
+ if (memfd < 0)
+ tst_brk(TBROK | TERRNO, "memfd_create failed");
+
+ SAFE_FTRUNCATE(memfd, page_size);
+
+ /*
+ * Populate page cache so that after MADV_DONTNEED the next access
+ * can generate a MINOR fault rather than a MISSING fault.
+ */
+ SAFE_PWRITE(1, memfd, &ch, 1, 0);
+
+ page = SAFE_MMAP(NULL, page_size, PROT_READ, MAP_SHARED, memfd, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+
+ if (memfd != -1)
+ SAFE_CLOSE(memfd);
+
+ if (uffd != -1)
+ SAFE_CLOSE(uffd);
+}
+
+static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ static struct uffd_msg msg;
+ struct uffdio_continue uffdio_continue = {};
+ struct pollfd pollfd;
+ int nready;
+ char z = 'Z';
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR)) {
+ tst_brk(TBROK, "expected MINOR fault, got flags=0x%llx",
+ (unsigned long long)msg.arg.pagefault.flags);
+ }
+
+ /* Update the shmem page in page cache before resuming the fault. */
+ SAFE_PWRITE(1, memfd, &z, 1, 0);
+
+ uffdio_continue.range.start =
+ msg.arg.pagefault.address & ~((unsigned long)page_size - 1);
+ uffdio_continue.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_CONTINUE, &uffdio_continue);
+
+ SAFE_CLOSE(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thr;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, true);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_MINOR_SHMEM;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ if (!(uffdio_api.features & UFFD_FEATURE_MINOR_SHMEM))
+ tst_brk(TCONF, "UFFD_FEATURE_MINOR_SHMEM not supported");
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ /*
+ * Drop PTEs while retaining the cached shmem page so the next access
+ * faults in MINOR mode.
+ */
+ if (madvise(page, page_size, MADV_DONTNEED) < 0)
+ tst_brk(TBROK | TERRNO, "madvise MADV_DONTNEED failed");
+
+ SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
+
+ char c = page[0];
+
+ if (c == 'Z')
+ tst_res(TPASS, "Pagefault handled via UFFDIO_CONTINUE");
+ else
+ tst_res(TFAIL, "pagefault not handled via UFFDIO_CONTINUE, got '%c'", c);
+
+ SAFE_PTHREAD_JOIN(thr, NULL);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ /*
+ * UFFDIO_CONTINUE is available since 5.13 but
+ * UFFD_FEATURE_MINOR_SHMEM appeared in 5.14
+ */
+ .min_kver = "5.14",
+ .cleanup = reset_pages,
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h
2026-03-31 22:03 [LTP] [PATCH v3] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-09 15:19 ` [LTP] [PATCH v5 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
@ 2026-04-11 9:47 ` Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-11 10:44 ` [LTP] memfd_create: move sys_memfd_create() to lapi/memfd.h acervesato
2 siblings, 2 replies; 10+ messages in thread
From: Ricardo Branco @ 2026-04-11 9:47 UTC (permalink / raw)
To: ltp
Add the static inline wrapper to include/lapi/memfd.h and include the
required headers so other tests can reuse it.
Also fix some minor issues detected by make check.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/memfd.h | 8 ++++++++
testcases/kernel/syscalls/memfd_create/memfd_create01.c | 1 -
.../kernel/syscalls/memfd_create/memfd_create_common.c | 5 -----
.../kernel/syscalls/memfd_create/memfd_create_common.h | 4 +---
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/lapi/memfd.h b/include/lapi/memfd.h
index 57b6cd83d..46ccb0a3f 100644
--- a/include/lapi/memfd.h
+++ b/include/lapi/memfd.h
@@ -6,6 +6,9 @@
#ifndef LAPI_MEMFD_H__
#define LAPI_MEMFD_H__
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+
/* flags for memfd_create(2) (unsigned int) */
#ifndef MFD_CLOEXEC
# define MFD_CLOEXEC 0x0001U
@@ -47,4 +50,9 @@
#define MFD_HUGE_16GB (34 << 26)
#endif
+static inline int sys_memfd_create(const char *name, unsigned int flags)
+{
+ return tst_syscall(__NR_memfd_create, name, flags);
+}
+
#endif /* LAPI_MEMFD_H__ */
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create01.c b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
index 73f6b01e8..28ad04a86 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create01.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create01.c
@@ -212,7 +212,6 @@ static void test_share_open(int fd)
SAFE_CLOSE(fd2);
}
-
static const struct tcase {
int flags;
void (*func)(int fd);
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
index a52b02a56..63e8daac5 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.c
@@ -24,11 +24,6 @@
#include "memfd_create_common.h"
-int sys_memfd_create(const char *name, unsigned int flags)
-{
- return tst_syscall(__NR_memfd_create, name, flags);
-}
-
int check_fallocate(const char *filename, const int lineno, int fd,
int mode, off_t offset, off_t len)
{
diff --git a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
index 60ad895fe..df809d6c7 100644
--- a/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
+++ b/testcases/kernel/syscalls/memfd_create/memfd_create_common.h
@@ -50,7 +50,7 @@
check_munmap(__FILE__, __LINE__, (p), (length))
#define CHECK_MFD_HAS_SEALS(fd, seals) \
- check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals));
+ check_mfd_has_seals(__FILE__, __LINE__, (fd), (seals))
#define CHECK_MFD_ADD_SEALS(fd, seals) \
({int r = SAFE_FCNTL((fd), F_ADD_SEALS, (seals)); \
@@ -101,8 +101,6 @@ int mfd_flags_available(const char *filename, const int lineno,
int get_mfd_all_available_flags(const char *filename, const int lineno);
-int sys_memfd_create(const char *name, unsigned int flags);
-
int check_fallocate(const char *filename, const int lineno, int fd,
int mode, off_t offset, off_t len);
int check_fallocate_fail(const char *filename, const int lineno, int fd,
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [LTP] [PATCH v6 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE
2026-04-11 9:47 ` [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
@ 2026-04-11 9:47 ` Ricardo Branco
2026-04-11 10:44 ` [LTP] memfd_create: move sys_memfd_create() to lapi/memfd.h acervesato
1 sibling, 0 replies; 10+ messages in thread
From: Ricardo Branco @ 2026-04-11 9:47 UTC (permalink / raw)
To: ltp
Add test to exercise UFFDIO_CONTINUE on a shared-memory mapping with
UFFD_PAGEFAULT_FLAG_MINOR. The test populates a memfd-backed page,
drops only the PTEs with MADV_DONTNEED, verifies that the resulting
fault is reported as MINOR, updates the page cache from the handler
thread, and resumes execution with UFFDIO_CONTINUE.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
include/lapi/userfaultfd.h | 1 +
runtest/syscalls | 1 +
.../kernel/syscalls/userfaultfd/.gitignore | 1 +
.../kernel/syscalls/userfaultfd/Makefile | 1 +
.../syscalls/userfaultfd/userfaultfd07.c | 157 ++++++++++++++++++
5 files changed, 161 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
diff --git a/include/lapi/userfaultfd.h b/include/lapi/userfaultfd.h
index aab3890b7..c05b8dbf5 100644
--- a/include/lapi/userfaultfd.h
+++ b/include/lapi/userfaultfd.h
@@ -171,6 +171,7 @@ struct uffdio_zeropage {
#ifndef UFFD_PAGEFAULT_FLAG_MINOR
#define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9)
#define UFFDIO_REGISTER_MODE_MINOR ((__u64)1<<2)
+#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2)
#define _UFFDIO_CONTINUE (0x07)
#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \
diff --git a/runtest/syscalls b/runtest/syscalls
index d72fceb5e..fee8b1a24 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1781,6 +1781,7 @@ userfaultfd03 userfaultfd03
userfaultfd04 userfaultfd04
userfaultfd05 userfaultfd05
userfaultfd06 userfaultfd06
+userfaultfd07 userfaultfd07
ustat01 ustat01
ustat02 ustat02
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index bc32fdf3b..3478a162e 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -4,3 +4,4 @@
/userfaultfd04
/userfaultfd05
/userfaultfd06
+/userfaultfd07
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 3252e47df..257249e88 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -17,3 +17,4 @@ userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
userfaultfd06: CFLAGS += -pthread
+userfaultfd07: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
new file mode 100644
index 000000000..69b6e5335
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rbranco@suse.com>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different thread testing UFFDIO_CONTINUE.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_prw.h"
+#include "tst_safe_pthread.h"
+#include "lapi/memfd.h"
+#include "lapi/userfaultfd.h"
+#include "lapi/syscalls.h"
+
+static long page_size;
+static char *page;
+static int uffd = -1;
+static int memfd = -1;
+
+static void set_pages(void)
+{
+ char ch = 'A';
+
+ page_size = SAFE_SYSCONF(_SC_PAGE_SIZE);
+
+ memfd = sys_memfd_create("ltp-uffd-continue", MFD_CLOEXEC);
+ if (memfd < 0)
+ tst_brk(TBROK | TERRNO, "memfd_create failed");
+
+ SAFE_FTRUNCATE(memfd, page_size);
+
+ /*
+ * Populate page cache so that after MADV_DONTNEED the next access
+ * can generate a MINOR fault rather than a MISSING fault.
+ */
+ SAFE_PWRITE(1, memfd, &ch, 1, 0);
+
+ page = SAFE_MMAP(NULL, page_size, PROT_READ, MAP_SHARED, memfd, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+
+ if (memfd != -1)
+ SAFE_CLOSE(memfd);
+
+ if (uffd != -1)
+ SAFE_CLOSE(uffd);
+}
+
+static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ static struct uffd_msg msg;
+ struct uffdio_continue uffdio_continue = {};
+ struct pollfd pollfd;
+ int nready;
+ char z = 'Z';
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR)) {
+ tst_brk(TBROK, "expected MINOR fault, got flags=0x%llx",
+ (unsigned long long)msg.arg.pagefault.flags);
+ }
+
+ /* Update the shmem page in page cache before resuming the fault. */
+ SAFE_PWRITE(1, memfd, &z, 1, 0);
+
+ uffdio_continue.range.start =
+ msg.arg.pagefault.address & ~((unsigned long)page_size - 1);
+ uffdio_continue.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_CONTINUE, &uffdio_continue);
+
+ SAFE_CLOSE(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thr;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, true);
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = 0;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+ if (!(uffdio_api.features & UFFD_FEATURE_MINOR_SHMEM))
+ tst_brk(TCONF, "UFFD_FEATURE_MINOR_SHMEM not supported");
+ SAFE_CLOSE(uffd);
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_MINOR_SHMEM;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ /*
+ * Drop PTEs while retaining the cached shmem page so the next access
+ * faults in MINOR mode.
+ */
+ if (madvise(page, page_size, MADV_DONTNEED) < 0)
+ tst_brk(TBROK | TERRNO, "madvise MADV_DONTNEED failed");
+
+ SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
+
+ char c = page[0];
+
+ if (c == 'Z')
+ tst_res(TPASS, "Pagefault handled via UFFDIO_CONTINUE");
+ else
+ tst_res(TFAIL, "pagefault not handled via UFFDIO_CONTINUE, got '%c'", c);
+
+ SAFE_PTHREAD_JOIN(thr, NULL);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ /*
+ * UFFDIO_CONTINUE is available since 5.13 but
+ * UFFD_FEATURE_MINOR_SHMEM appeared in 5.14
+ */
+ .min_kver = "5.14",
+ .cleanup = reset_pages,
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] memfd_create: move sys_memfd_create() to lapi/memfd.h
2026-04-11 9:47 ` [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
@ 2026-04-11 10:44 ` acervesato
1 sibling, 0 replies; 10+ messages in thread
From: acervesato @ 2026-04-11 10:44 UTC (permalink / raw)
To: Ricardo Branco; +Cc: ltp
Hi Ricardo,
our agent completed the review of the patch.
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
--- [PATCH 1/2] ---
On Sat, 11 Apr 2026 11:47:22 +0200, Ricardo Branco wrote:
> memfd_create: move sys_memfd_create() to lapi/memfd.h
>
> Add the static inline wrapper to include/lapi/memfd.h and include the
> required headers so other tests can reuse it.
>
> Also fix some minor issues detected by make check.
The commit bundles two logical changes: the main refactoring (moving
sys_memfd_create() to lapi/memfd.h) and unrelated minor fixes (blank
line in memfd_create01.c, trailing semicolon in CHECK_MFD_HAS_SEALS).
Please split them into separate commits.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-04-11 11:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-31 22:03 [LTP] [PATCH v3] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-01 21:03 ` [LTP] [PATCH v4 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-09 14:15 ` Andrea Cervesato via ltp
2026-04-09 14:51 ` Andrea Cervesato via ltp
2026-04-09 15:19 ` [LTP] [PATCH v5 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-09 15:19 ` [LTP] [PATCH v5 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 1/2] memfd_create: move sys_memfd_create() to lapi/memfd.h Ricardo Branco
2026-04-11 9:47 ` [LTP] [PATCH v6 2/2] userfaultfd: Add new test using UFFDIO_CONTINUE Ricardo Branco
2026-04-11 10:44 ` [LTP] memfd_create: move sys_memfd_create() to lapi/memfd.h acervesato
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox