Linux Test Project
 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 2/4] memcg, userfaultfd07: Populate whole pages instead of single bytes
Date: Wed, 11 Nov 2026 09:31:49 +0000	[thread overview]
Message-ID: <20261111093151.374731-3-wakel@google.com> (raw)
In-Reply-To: <20261111093151.374731-1-wakel@google.com>

memcontrol02 and mem_process, the helper of memcg_control_test.sh,
fault in their memory by writing one byte per getpagesize() bytes, and
userfaultfd07 populates the page cache of its memfd by writing a single
byte. All of them assume that this populates whole pages of
getpagesize() bytes.

That is not the case when the kernel faults in and caches memory in
smaller units than the page size it reports to userspace, as with the
16K page size emulation that Android uses on x86_64. Only one in four
4K pages gets populated there, so memcontrol02 sees only about a
quarter of the expected 50M in memory.current, mem_process stays below
the memory limit it is supposed to exceed, and UFFDIO_CONTINUE in
userfaultfd07 fails for the part of the page that is not in the page
cache:

  TBROK: ioctl(4,UFFDIO_CONTINUE,...) failed: EAGAIN/EWOULDBLOCK (11)

Write the whole buffers instead. Nothing changes on kernels where both
page sizes are equal.

Signed-off-by: Wake Liu <wakel@google.com>
---

Notes:
    alloc_anon() in memcontrol_common.h, used by memcontrol03 and
    memcontrol04, writes one byte per page as well. It frees the buffer
    right away, so GCC and Clang would drop a plain memset() there as a
    dead store and it needs a different fix. I will look at it
    separately.

 .../kernel/controllers/memcg/control/mem_process.c  | 11 ++++++-----
 testcases/kernel/controllers/memcg/memcontrol02.c   | 13 +++++++------
 .../kernel/syscalls/userfaultfd/userfaultfd07.c     | 11 +++++++++--
 3 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/testcases/kernel/controllers/memcg/control/mem_process.c b/testcases/kernel/controllers/memcg/control/mem_process.c
index 8ecabb272..f32189cc2 100644
--- a/testcases/kernel/controllers/memcg/control/mem_process.c
+++ b/testcases/kernel/controllers/memcg/control/mem_process.c
@@ -10,6 +10,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 /*
@@ -49,14 +50,14 @@ void process_options(int argc, char **argv)
 
 /*
  * touch_memory: force physical memory allocation
+ *
+ * Write the whole area rather than one byte per getpagesize(), so that it
+ * gets fully populated regardless of the granularity the kernel faults in
+ * memory with.
  */
 void touch_memory(char *p)
 {
-	int i;
-	int pagesize = getpagesize();
-
-	for (i = 0; i < (int)memsize; i += pagesize)
-		p[i] = 0xef;
+	memset(p, 0xef, memsize);
 }
 
 void mem_map(void)
diff --git a/testcases/kernel/controllers/memcg/memcontrol02.c b/testcases/kernel/controllers/memcg/memcontrol02.c
index 52096f697..6687c6e84 100644
--- a/testcases/kernel/controllers/memcg/memcontrol02.c
+++ b/testcases/kernel/controllers/memcg/memcontrol02.c
@@ -27,7 +27,6 @@
 #define _GNU_SOURCE
 #include "memcontrol_common.h"
 
-static size_t page_size;
 static struct tst_cg_group *cg_child;
 static int fd = -1;
 static int file_to_all_error = 10;
@@ -35,14 +34,18 @@ static int file_to_all_error = 10;
 static void alloc_anon_50M_check(void)
 {
 	const ssize_t size = MB(50);
-	char *buf, *ptr;
+	char *buf;
 	ssize_t anon, current;
 	const char *const anon_key_fmt =
 		TST_CG_VER_IS_V1(tst_cg, "memory") ? "rss %zd" : "anon %zd";
 
 	buf = SAFE_MALLOC(size);
-	for (ptr = buf; ptr < buf + size; ptr += page_size)
-		*ptr = 0;
+	/*
+	 * Write the whole buffer rather than one byte per getpagesize(), so
+	 * that it gets fully populated regardless of the granularity the
+	 * kernel faults in memory with.
+	 */
+	memset(buf, 1, size);
 
 	SAFE_CG_SCANF(cg_child, "memory.current", "%zd", &current);
 	TST_EXP_EXPR(current >= size,
@@ -113,8 +116,6 @@ static void test_memcg_current(unsigned int n)
 
 static void setup(void)
 {
-	page_size = SAFE_SYSCONF(_SC_PAGESIZE);
-
 	switch (tst_fs_type(TMPDIR)) {
 	case TST_VFAT_MAGIC:
 	case TST_EXFAT_MAGIC:
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
index e0a1b0d23..dce6d8827 100644
--- a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -32,7 +32,7 @@ static void setup(void)
 
 static void set_pages(void)
 {
-	char ch = 'A';
+	char *buf;
 
 	page_size = SAFE_SYSCONF(_SC_PAGE_SIZE);
 
@@ -45,8 +45,15 @@ static void set_pages(void)
 	/*
 	 * Populate page cache so that after MADV_DONTNEED the next access
 	 * can generate a MINOR fault rather than a MISSING fault.
+	 *
+	 * Write the whole page, as UFFDIO_CONTINUE needs the page cache to
+	 * cover the whole range and the kernel may cache memory in units
+	 * smaller than getpagesize().
 	 */
-	SAFE_PWRITE(1, memfd, &ch, 1, 0);
+	buf = SAFE_MALLOC(page_size);
+	memset(buf, 'A', page_size);
+	SAFE_PWRITE(1, memfd, buf, page_size, 0);
+	free(buf);
 
 	page = SAFE_MMAP(NULL, page_size, PROT_READ, MAP_SHARED, memfd, 0);
 }
-- 
2.56.0.567.gdb80ae8cd5-goog


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

  parent reply	other threads:[~2026-11-11  9:32 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 ` [LTP] [PATCH 1/4] epoll_wait06, fcntl35: Don't assume a pipe buffer is getpagesize() Wake Liu via ltp
2026-11-11  9:31 ` Wake Liu via ltp [this message]
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-3-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox