All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wake Liu via ltp <ltp@lists.linux.it>
To: ltp@lists.linux.it
Cc: kaleshsingh@google.com
Subject: [LTP] [PATCH 1/4] epoll_wait06, fcntl35: Don't assume a pipe buffer is getpagesize()
Date: Wed, 11 Nov 2026 09:31:48 +0000	[thread overview]
Message-ID: <20261111093151.374731-2-wakel@google.com> (raw)
In-Reply-To: <20261111093151.374731-1-wakel@google.com>

A pipe consists of pipe buffers of one kernel page each, but both tests
assume that a pipe buffer is getpagesize() bytes.

epoll_wait06 sets the pipe capacity to getpagesize() and expects the
pipe to consist of a single buffer, so that reading half of the data
does not release a buffer and raise EPOLLOUT. fcntl35 expects the
default capacity of a pipe created by a privileged user, which is 16
pipe buffers (PIPE_DEF_BUFFERS), to be 16 * getpagesize().

Neither holds when the kernel reports a larger page size to userspace
than it uses internally, as with the 16K page size emulation that
Android uses on x86_64. There the pipe of epoll_wait06 consists of four
4K buffers, reading half of the data releases two of them, and the
test fails with:

  TFAIL: SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0) (1) != 0 (0)

fcntl35 gets a default capacity of 65536 bytes instead of the expected
262144.

Get the size of a pipe buffer from the kernel instead, by shrinking a
pipe to its minimum capacity with F_SETPIPE_SZ. The unprivileged case
of fcntl35 needs no change, as setting pipe-max-size to getpagesize()
still caps the capacity at getpagesize() bytes. Nothing changes on
kernels where both page sizes are equal.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../kernel/syscalls/epoll_wait/epoll_wait06.c | 15 +++++++++-----
 testcases/kernel/syscalls/fcntl/fcntl35.c     | 20 ++++++++++++++++++-
 2 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c
index 622830d55..ce4e2d5bc 100644
--- a/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait06.c
@@ -32,13 +32,18 @@ static int epfd;
 
 static void setup(void)
 {
-	write_size = getpagesize();
-	read_size = write_size / 2;
-
 	SAFE_PIPE2(fds, O_NONBLOCK);
 
-	/* EPOLLOUT will be raised when buffer became empty after becoming full */
-	SAFE_FCNTL(fds[1], F_SETPIPE_SZ, write_size);
+	/*
+	 * EPOLLOUT will be raised when buffer became empty after becoming full.
+	 *
+	 * Shrink the pipe to its minimum capacity, which is a single pipe
+	 * buffer, so that reading only half of the data doesn't release any
+	 * buffer. Use the capacity reported by the kernel rather than
+	 * assuming it matches getpagesize().
+	 */
+	write_size = SAFE_FCNTL(fds[1], F_SETPIPE_SZ, 1);
+	read_size = write_size / 2;
 }
 
 static void cleanup(void)
diff --git a/testcases/kernel/syscalls/fcntl/fcntl35.c b/testcases/kernel/syscalls/fcntl/fcntl35.c
index d17812fd0..a240500d4 100644
--- a/testcases/kernel/syscalls/fcntl/fcntl35.c
+++ b/testcases/kernel/syscalls/fcntl/fcntl35.c
@@ -44,10 +44,28 @@ static struct tcase {
 	{&test_max_priv, 0, "a privileged user"}
 };
 
+/*
+ * The pipe capacity is a multiple of the size of a pipe buffer, which is one
+ * page of the kernel. Get it by shrinking a pipe to its minimum capacity,
+ * rather than assuming it matches getpagesize().
+ */
+static int get_pipe_buf_size(void)
+{
+	int fds[2], size;
+
+	SAFE_PIPE(fds);
+	size = SAFE_FCNTL(fds[1], F_SETPIPE_SZ, 1);
+	SAFE_CLOSE(fds[0]);
+	SAFE_CLOSE(fds[1]);
+
+	return size;
+}
+
 static void setup(void)
 {
 	test_max_unpriv = getpagesize();
-	test_max_priv = test_max_unpriv * 16;
+	/* The default capacity is 16 pipe buffers (PIPE_DEF_BUFFERS) */
+	test_max_priv = get_pipe_buf_size() * 16;
 
 	if (!access(PATH_FS_PIPE_MAX_SIZE, F_OK)) {
 		SAFE_FILE_SCANF(PATH_FS_PIPE_MAX_SIZE, "%d", &pipe_max_unpriv);
-- 
2.56.0.567.gdb80ae8cd5-goog


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

  reply	other threads:[~2026-11-11  9:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11  9:31 [LTP] [PATCH 0/4] Don't derive kernel granularities from getpagesize() Wake Liu via ltp
2026-11-11  9:31 ` Wake Liu via ltp [this message]
2026-11-11  9:31 ` [LTP] [PATCH 2/4] memcg, userfaultfd07: Populate whole pages instead of single bytes Wake Liu via ltp
2026-11-11  9:31 ` [LTP] [PATCH 3/4] ioctl10: Compare vma_page_size with KernelPageSize from smaps Wake Liu via ltp
2026-11-11  9:31 ` [LTP] [PATCH 4/4] signal06: Allocate the alternate signal stack with mmap() Wake Liu 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=20261111093151.374731-2-wakel@google.com \
    --to=ltp@lists.linux.it \
    --cc=kaleshsingh@google.com \
    --cc=wakel@google.com \
    /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.