From: Petr Vorel <pvorel@suse.cz>
To: Martin Cermak <mcermak@redhat.com>
Cc: valgrind-developers@lists.sourceforge.net, ltp@lists.linux.it
Subject: Re: [LTP] [Valgrind-developers] [PATCH] Make userfaultfd0{1, 3, 4} LTP tests valgrind compatible
Date: Wed, 22 Apr 2026 07:37:12 +0200 [thread overview]
Message-ID: <20260422053712.GB392764@pevik> (raw)
In-Reply-To: <20260421152349.1673057-1-mcermak@redhat.com>
Hi Martin,
[ Cc Ricardo ]
> Historically a page fault is handled in the linux kernel. The
> userfaultfd mechanism [1] was introduced in Linux 4.3 (2015) to allow
> custom handling page faults in userspace. It allows for custom page
> fault handling strategies such as lazy loading, live migration of qemu
> VMs, etc. With userfaultfd, kernel communicates with userspace via a
> file descriptor (userfaultfd). Userfaultfd LTP tests cover this.
> These tests set up a main thread and a page fault handler thread. Once
> a page fault happens in the main thread, kernel stops it, and let's the
> handler take care of the page fault.
> This is a problem for Valgrind, because it serializes the threads
> execution (using one "big mutex", VG_(acquire_BigLock)). Once kernel
> stops the main thread, under valgrind, the handler thread doesn't have
> a chance to handle the page fault. Valgrind stalls till the timeout
> (adjustable via LTP_TIMEOUT_MUL ;)
> However, some of the testcases can be easily changed to use forked
> processes instead of threads. That's what this patch does. When
> client program forks, Valgrind forks too, and that allows for the needed
> parallelism to handle the page fault.
You understand process vs. threads more than me. But shouldn't mmap() use
MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd?
> This redesign can't be easily done with some of the tests, such as e.g.
> userfaultfd02 where both the main thread and the handler thread need to
> share the address space. That could be done via clone() and is proven
What is the difference with userfaultfd02 then?
> to work. But unfortunately there is another Valgrind limitation in clone
> flags it supports, so this also isn't a practical way to go.
> That said, this update tweaks userfaultfd01, userfaultfd03, and
> userfaultfd04 in a way that they become "compatible" with Valgrind.
> It's a test coverage improvement.
Also doc should be updated (mentions thread).
Please don't forget to add it next time:
Signed-off-by: Martin Cermak <mcermak@redhat.com>
> [1] https://www.kernel.org/doc/html/latest/admin-guide/mm/userfaultfd.html
> ---
> .../kernel/syscalls/userfaultfd/userfaultfd01.c | 13 +++++++++----
> .../kernel/syscalls/userfaultfd/userfaultfd03.c | 15 ++++++++++-----
> .../kernel/syscalls/userfaultfd/userfaultfd04.c | 13 +++++++++----
> 3 files changed, 28 insertions(+), 13 deletions(-)
> diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c
> index 7368d3863..c927cda95 100644
> --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c
> +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c
> @@ -57,7 +57,7 @@ static void reset_pages(void)
> SAFE_MUNMAP(copy_page, page_size);
> }
> -static void *handle_thread(void)
> +static void *pagefault_handler(void)
> {
> static struct uffd_msg msg;
> struct uffdio_copy uffdio_copy = {};
> @@ -91,7 +91,7 @@ static void *handle_thread(void)
> static void run(unsigned int i)
> {
> - pthread_t thr;
> + pid_t pid;
> struct uffdio_api uffdio_api = {};
> struct uffdio_register uffdio_register;
> struct tcase *tc = &tcases[i];
> @@ -112,7 +112,11 @@ static void run(unsigned int i)
> SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
> - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
> + pid = SAFE_FORK();
> + if (pid == 0) {
> + pagefault_handler();
> + _exit(0);
> + }
> char c = page[0xf];
> @@ -121,7 +125,7 @@ static void run(unsigned int i)
> else
> tst_res(TFAIL, "Pagefault not handled!");
> - SAFE_PTHREAD_JOIN(thr, NULL);
> + SAFE_WAITPID(pid, NULL, 0);
> reset_pages();
> }
> @@ -129,4 +133,5 @@ static struct tst_test test = {
> .setup = setup,
> .test = run,
> .tcnt = ARRAY_SIZE(tcases),
> + .forks_child = 1,
> };
> diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c
> index b65f39eca..f5d3be1ae 100644
> --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c
> +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c
> @@ -61,7 +61,7 @@ static void reset_pages(void)
> SAFE_MUNMAP(copy_page, page_size);
> }
> -static void *handle_thread(void)
> +static void *pagefault_handler(void)
> {
> static struct uffd_msg msg;
> struct uffdio_copy uffdio_copy = {};
> @@ -95,7 +95,7 @@ static void *handle_thread(void)
> static void run(void)
> {
> - pthread_t thr;
> + pid_t pid;
> struct uffdio_api uffdio_api = {};
> struct uffdio_register uffdio_register;
> @@ -112,7 +112,11 @@ static void run(void)
> SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
> - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
> + pid = SAFE_FORK();
> + if (pid == 0) {
> + pagefault_handler();
> + _exit(0);
> + }
> char c = page[0xf];
> @@ -121,7 +125,7 @@ static void run(void)
> else
> tst_res(TFAIL, "Pagefault not handled via /dev/userfaultfd");
> - SAFE_PTHREAD_JOIN(thr, NULL);
> + SAFE_WAITPID(pid, NULL, 0);
> reset_pages();
> }
> @@ -132,5 +136,6 @@ static struct tst_test test = {
> .needs_kconfigs = (const char *[]) {
> "CONFIG_USERFAULTFD=y",
> NULL
> - }
> + },
> + .forks_child = 1,
> };
> diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c
> index 4eb811e45..13883a711 100644
> --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c
> +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c
> @@ -33,7 +33,7 @@ static void reset_pages(void)
> SAFE_MUNMAP(page, page_size);
> }
> -static void *handle_thread(void)
> +static void *pagefault_handler(void)
> {
> static struct uffd_msg msg;
> struct uffdio_zeropage uffdio_zeropage = {};
> @@ -64,7 +64,7 @@ static void *handle_thread(void)
> static void run(void)
> {
> - pthread_t thr;
> + pid_t pid;
> struct uffdio_api uffdio_api = {};
> struct uffdio_register uffdio_register;
> @@ -81,7 +81,11 @@ static void run(void)
> SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
> - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
> + pid = SAFE_FORK();
> + if (pid == 0) {
> + pagefault_handler();
> + _exit(0);
> + }
> for (int i = 0; i < page_size; i++) {
> if (page[i] != 0) {
> @@ -92,10 +96,11 @@ static void run(void)
> tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE");
> - SAFE_PTHREAD_JOIN(thr, NULL);
> + SAFE_WAITPID(pid, NULL, 0);
> reset_pages();
> }
> static struct tst_test test = {
> .test_all = run,
> + .forks_child = 1,
> };
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2026-04-22 5:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-21 15:23 [LTP] [PATCH] Make userfaultfd0{1, 3, 4} LTP tests valgrind compatible Martin Cermak via ltp
2026-04-21 17:06 ` [LTP] " linuxtestproject.agent
2026-04-22 5:37 ` Petr Vorel [this message]
2026-04-22 7:54 ` [LTP] [Valgrind-developers] [PATCH] " Ricardo Branco
2026-04-22 12:17 ` Petr Vorel
2026-04-22 12:42 ` Ricardo Branco
2026-04-22 13:08 ` Martin Cermak via ltp
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=20260422053712.GB392764@pevik \
--to=pvorel@suse.cz \
--cc=ltp@lists.linux.it \
--cc=mcermak@redhat.com \
--cc=valgrind-developers@lists.sourceforge.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox