[LTP] [PATCH 5/8] syscall: Add epoll_wait10
Cyril Hrubis
chrubis@suse.cz
Thu Apr 23 11:58:31 CEST 2026
Functional test for EPOLLPRI using /proc/mounts that produces POLLPRI
when a filesystem is mounted/umounted.
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
runtest/syscalls | 1 +
.../kernel/syscalls/epoll_wait/.gitignore | 1 +
.../kernel/syscalls/epoll_wait/epoll_wait10.c | 107 ++++++++++++++++++
3 files changed, 109 insertions(+)
create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait10.c
diff --git a/runtest/syscalls b/runtest/syscalls
index 148a4dd0e..06948d8ad 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -197,6 +197,7 @@ epoll_wait05 epoll_wait05
epoll_wait06 epoll_wait06
epoll_wait07 epoll_wait07
epoll_wait09 epoll_wait09
+epoll_wait10 epoll_wait10
epoll_pwait01 epoll_pwait01
epoll_pwait02 epoll_pwait02
diff --git a/testcases/kernel/syscalls/epoll_wait/.gitignore b/testcases/kernel/syscalls/epoll_wait/.gitignore
index f32ec535b..30139375d 100644
--- a/testcases/kernel/syscalls/epoll_wait/.gitignore
+++ b/testcases/kernel/syscalls/epoll_wait/.gitignore
@@ -7,3 +7,4 @@ epoll_wait06
epoll_wait07
epoll_wait08
epoll_wait09
+epoll_wait10
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait10.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait10.c
new file mode 100644
index 000000000..82cd8b15e
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait10.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * Verify that epoll_wait with EPOLLPRI detects changes to /proc/mounts.
+ *
+ * The kernel generates a poll notification (POLLPRI/EPOLLERR) on
+ * /proc/mounts whenever the mount namespace changes. This test verifies
+ * that epoll can observe these notifications.
+ *
+ * [Algorithm]
+ *
+ * - Open /proc/mounts and register it with an epoll instance for EPOLLPRI.
+ * - Fork a child that mounts and then unmounts a tmpfs filesystem, using
+ * checkpoints to synchronize with the parent.
+ * - After each mount namespace change the parent calls epoll_wait and verifies
+ * it returns an event.
+ *
+ * Needs root to call mount/umount.
+ */
+
+#include <sys/epoll.h>
+
+#include "tst_test.h"
+#include "tst_epoll.h"
+
+#define MNTPOINT "mnt_epoll"
+
+static int efd = -1, mnt_fd = -1;
+
+static void setup(void)
+{
+ SAFE_MKDIR(MNTPOINT, 0777);
+
+ mnt_fd = SAFE_OPEN("/proc/mounts", O_RDONLY);
+
+ efd = SAFE_EPOLL_CREATE1(0);
+
+ struct epoll_event ev = {
+ .events = EPOLLPRI,
+ .data.fd = mnt_fd,
+ };
+
+ SAFE_EPOLL_CTL(efd, EPOLL_CTL_ADD, mnt_fd, &ev);
+}
+
+static void check_epoll_event(const char *desc)
+{
+ struct epoll_event ret_ev;
+ char buf[1024];
+
+ TEST(epoll_wait(efd, &ret_ev, 1, 1000));
+ if (TST_RET < 1) {
+ tst_res(TFAIL | TTERRNO,
+ "epoll_wait() after %s returned %li", desc, TST_RET);
+ } else if (!(ret_ev.events & (EPOLLPRI | EPOLLERR))) {
+ tst_res(TFAIL,
+ "after %s: events %x, expected EPOLLPRI or EPOLLERR",
+ desc, ret_ev.events);
+ } else {
+ tst_res(TPASS,
+ "epoll_wait() reported event after %s", desc);
+ }
+
+ /* Re-read /proc/self/mounts to clear the notification */
+ SAFE_LSEEK(mnt_fd, 0, SEEK_SET);
+ while (SAFE_READ(0, mnt_fd, buf, sizeof(buf)) > 0)
+ ;
+}
+
+static void run(void)
+{
+ if (!SAFE_FORK()) {
+ SAFE_MOUNT("none", MNTPOINT, "tmpfs", 0, NULL);
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+ SAFE_UMOUNT(MNTPOINT);
+ TST_CHECKPOINT_WAKE(0);
+ exit(0);
+ }
+
+ TST_CHECKPOINT_WAIT(0);
+ check_epoll_event("mount");
+
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+ check_epoll_event("umount");
+}
+
+static void cleanup(void)
+{
+ if (efd != -1)
+ SAFE_CLOSE(efd);
+
+ if (mnt_fd != -1)
+ SAFE_CLOSE(mnt_fd);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = cleanup,
+ .needs_root = 1,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+ .needs_tmpdir = 1,
+};
--
2.52.0
More information about the ltp
mailing list