public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
@ 2026-03-13  4:35 Li Wang
  2026-03-13  4:35 ` [PATCH v3 2/7] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt

test_zswap currently only checks whether zswap is present by testing
/sys/module/zswap. This misses the runtime global state exposed in
/sys/module/zswap/parameters/enabled.

When zswap is built/loaded but globally disabled, the zswap cgroup
selftests run in an invalid environment and may fail spuriously.

Check the runtime enabled state before running the tests:
  - skip if zswap is not configured,
  - fail if the enabled knob cannot be read,
  - skip if zswap is globally disabled.

Also print a hint in the skip message on how to enable zswap.

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Yosry Ahmed <yosryahmed@google.com>
---

Notes:
    v3:
    	- Replace tri-state zswap_enabled() with check_zswap_enabled() for clearer flow.
    	- Move skip/fail decisions into the helper instead of branching in main().
    	- Make read failure reporting more explicit by naming
    	  `/sys/module/zswap/parameters/enabled`.
    	- Keep skip hint for enabling zswap:
    	  `echo 1 > /sys/module/zswap/parameters/enabled`.
    
    v2:
    	- remove enable/disable_zswap functions
    	- skip the test if zswap is not enabled
    	- reporting fail when zswap_enabled return -1

 tools/testing/selftests/cgroup/test_zswap.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index 64ebc3f3f203..e69d845d3592 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -589,9 +589,21 @@ struct zswap_test {
 };
 #undef T
 
-static bool zswap_configured(void)
+static void check_zswap_enabled(void)
 {
-	return access("/sys/module/zswap", F_OK) == 0;
+	char value[2];
+
+	if (access("/sys/module/zswap", F_OK))
+		ksft_exit_skip("zswap isn't configured\n");
+
+	if (read_text("/sys/module/zswap/parameters/enabled", value,
+						sizeof(value)) <= 0)
+		ksft_exit_fail_msg("Failed to read "
+				"/sys/module/zswap/parameters/enabled\n");
+
+	if (value[0] == 'N')
+		ksft_exit_skip("zswap is disabled (hint: echo 1 > "
+				"/sys/module/zswap/parameters/enabled)\n");
 }
 
 int main(int argc, char **argv)
@@ -604,8 +616,7 @@ int main(int argc, char **argv)
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
-	if (!zswap_configured())
-		ksft_exit_skip("zswap isn't configured\n");
+	check_zswap_enabled();
 
 	/*
 	 * Check that memory controller is available:
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 2/7] selftests/cgroup: avoid OOM in test_swapin_nozswap
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  4:35 ` [PATCH v3 3/7] selftests/cgroup: use runtime page size for zswpin check Li Wang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt, Yosry Ahmed

test_swapin_nozswap can hit OOM before reaching its assertions on some
setups. The test currently sets memory.max=8M and then allocates/reads
32M with memory.zswap.max=0, which may over-constrain reclaim and kill
the workload process.

Replace hardcoded sizes with PAGE_SIZE-based values:
  - control_allocation_size = PAGE_SIZE * 512
  - memory.max = control_allocation_size * 3 / 4
  - minimum expected swap = control_allocation_size / 4

This keeps the test pressure model intact (allocate/read beyond memory.max to
force swap-in/out) while making it more robust across different environments.

The test intent is unchanged: confirm that swapping occurs while zswap remains
unused when memory.zswap.max=0.

=== Error Logs ===

  # ./test_zswap
  TAP version 13
  1..7
  ok 1 test_zswap_usage
  not ok 2 test_swapin_nozswap
  ...

  # dmesg
  [271641.879153] test_zswap invoked oom-killer: gfp_mask=0xcc0(GFP_KERNEL), order=0, oom_score_adj=0
  [271641.879168] CPU: 1 UID: 0 PID: 177372 Comm: test_zswap Kdump: loaded Not tainted 6.12.0-211.el10.ppc64le #1 VOLUNTARY
  [271641.879171] Hardware name: IBM,9009-41A POWER9 (architected) 0x4e0202 0xf000005 of:IBM,FW940.02 (UL940_041) hv:phyp pSeries
  [271641.879173] Call Trace:
  [271641.879174] [c00000037540f730] [c00000000127ec44] dump_stack_lvl+0x88/0xc4 (unreliable)
  [271641.879184] [c00000037540f760] [c0000000005cc594] dump_header+0x5c/0x1e4
  [271641.879188] [c00000037540f7e0] [c0000000005cb464] oom_kill_process+0x324/0x3b0
  [271641.879192] [c00000037540f860] [c0000000005cbe48] out_of_memory+0x118/0x420
  [271641.879196] [c00000037540f8f0] [c00000000070d8ec] mem_cgroup_out_of_memory+0x18c/0x1b0
  [271641.879200] [c00000037540f990] [c000000000713888] try_charge_memcg+0x598/0x890
  [271641.879204] [c00000037540fa70] [c000000000713dbc] charge_memcg+0x5c/0x110
  [271641.879207] [c00000037540faa0] [c0000000007159f8] __mem_cgroup_charge+0x48/0x120
  [271641.879211] [c00000037540fae0] [c000000000641914] alloc_anon_folio+0x2b4/0x5a0
  [271641.879215] [c00000037540fb60] [c000000000641d58] do_anonymous_page+0x158/0x6b0
  [271641.879218] [c00000037540fbd0] [c000000000642f8c] __handle_mm_fault+0x4bc/0x910
  [271641.879221] [c00000037540fcf0] [c000000000643500] handle_mm_fault+0x120/0x3c0
  [271641.879224] [c00000037540fd40] [c00000000014bba0] ___do_page_fault+0x1c0/0x980
  [271641.879228] [c00000037540fdf0] [c00000000014c44c] hash__do_page_fault+0x2c/0xc0
  [271641.879232] [c00000037540fe20] [c0000000001565d8] do_hash_fault+0x128/0x1d0
  [271641.879236] [c00000037540fe50] [c000000000008be0] data_access_common_virt+0x210/0x220
  [271641.879548] Tasks state (memory values in pages):
  ...
  [271641.879550] [  pid  ]   uid  tgid total_vm      rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name
  [271641.879555] [ 177372]     0 177372      571        0        0        0         0    51200       96             0 test_zswap
  [271641.879562] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=/,mems_allowed=0,oom_memcg=/no_zswap_test,task_memcg=/no_zswap_test,task=test_zswap,pid=177372,uid=0
  [271641.879578] Memory cgroup out of memory: Killed process 177372 (test_zswap) total-vm:36544kB, anon-rss:0kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:50kB oom_score_adj:0

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Yosry Ahmed <yosry@kernel.org>
---

Notes:
    v3:
    	- Replace fixed 8M/32M sizing with PAGE_SIZE-based sizing in
    	  test_swapin_nozswap.
    	- Set memory.max to 3/4 of workload size to reduce OOM risk while still
    	  forcing reclaim/swap activity.
    	- Derive minimum swap expectation from workload size (1/4) instead of a
    	  fixed 8M threshold.
    v2:
    	- No change.

 tools/testing/selftests/cgroup/test_zswap.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index e69d845d3592..04796b6641b8 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -160,21 +160,25 @@ static int test_zswap_usage(const char *root)
 static int test_swapin_nozswap(const char *root)
 {
 	int ret = KSFT_FAIL;
-	char *test_group;
-	long swap_peak, zswpout;
+	char *test_group, mem_max_buf[32];
+	long swap_peak, zswpout, min_swap;
+	size_t control_allocation_size = sysconf(_SC_PAGESIZE) * 512;
+
+	min_swap = control_allocation_size / 4;
+	snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", control_allocation_size * 3/4);
 
 	test_group = cg_name(root, "no_zswap_test");
 	if (!test_group)
 		goto out;
 	if (cg_create(test_group))
 		goto out;
-	if (cg_write(test_group, "memory.max", "8M"))
+	if (cg_write(test_group, "memory.max", mem_max_buf))
 		goto out;
 	if (cg_write(test_group, "memory.zswap.max", "0"))
 		goto out;
 
 	/* Allocate and read more than memory.max to trigger swapin */
-	if (cg_run(test_group, allocate_and_read_bytes, (void *)MB(32)))
+	if (cg_run(test_group, allocate_and_read_bytes, (void *)control_allocation_size))
 		goto out;
 
 	/* Verify that pages are swapped out, but no zswap happened */
@@ -184,8 +188,9 @@ static int test_swapin_nozswap(const char *root)
 		goto out;
 	}
 
-	if (swap_peak < MB(24)) {
-		ksft_print_msg("at least 24MB of memory should be swapped out\n");
+	if (swap_peak < min_swap) {
+		ksft_print_msg("at least %ldMB of memory should be swapped out\n",
+				min_swap / MB(1));
 		goto out;
 	}
 
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 3/7] selftests/cgroup: use runtime page size for zswpin check
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
  2026-03-13  4:35 ` [PATCH v3 2/7] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  4:35 ` [PATCH v3 4/7] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util Li Wang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt, Yosry Ahmed

test_zswapin compares memory.stat:zswpin (counted in pages) against a
byte threshold converted with PAGE_SIZE. In cgroup selftests, PAGE_SIZE
is hardcoded to 4096, which makes the conversion wrong on systems with
non-4K base pages (e.g. 64K).

As a result, the test requires too many pages to pass and fails
spuriously even when zswap is working.

Use sysconf(_SC_PAGESIZE) for the zswpin threshold conversion so the
check matches the actual system page size.

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Reviewed-by: Yosry Ahmed <yosry@kernel.org>
---
 tools/testing/selftests/cgroup/test_zswap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index 04796b6641b8..74b57331cbf1 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -240,7 +240,7 @@ static int test_zswapin(const char *root)
 		goto out;
 	}
 
-	if (zswpin < MB(24) / PAGE_SIZE) {
+	if (zswpin < MB(24) / sysconf(_SC_PAGESIZE)) {
 		ksft_print_msg("at least 24MB should be brought back from zswap\n");
 		goto out;
 	}
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 4/7] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
  2026-03-13  4:35 ` [PATCH v3 2/7] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
  2026-03-13  4:35 ` [PATCH v3 3/7] selftests/cgroup: use runtime page size for zswpin check Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  4:35 ` [PATCH v3 5/7] selftests/cgroup: replace hardcoded page size values in test_zswap Li Wang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt

The cgroup utility code defines a local PAGE_SIZE macro hardcoded to
4096, which is used solely as a generic buffer size for reading cgroup
and proc files. This is misleading because the value has nothing to do
with the actual page size of the system, and on architectures with
larger pages (e.g., 64K on arm64 or ppc64) the name suggests a
relationship that does not exist.

Additionally, the name can shadow or conflict with the PAGE_SIZE
definition from system headers, leading to confusion or subtle bugs.

Rename it to BUF_SIZE to accurately reflect its purpose as a general
I/O buffer size. No functional change.

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Yosry Ahmed <yosryahmed@google.com>
---
 .../testing/selftests/cgroup/lib/cgroup_util.c | 18 +++++++++---------
 .../selftests/cgroup/lib/include/cgroup_util.h |  4 ++--
 tools/testing/selftests/cgroup/test_core.c     |  2 +-
 tools/testing/selftests/cgroup/test_freezer.c  |  2 +-
 .../testing/selftests/cgroup/test_memcontrol.c | 14 +++++++-------
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/testing/selftests/cgroup/lib/cgroup_util.c b/tools/testing/selftests/cgroup/lib/cgroup_util.c
index ce6c2642fd9b..0be525ed11db 100644
--- a/tools/testing/selftests/cgroup/lib/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/lib/cgroup_util.c
@@ -125,7 +125,7 @@ int cg_read_strcmp(const char *cgroup, const char *control,
 
 int cg_read_strstr(const char *cgroup, const char *control, const char *needle)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 
 	if (cg_read(cgroup, control, buf, sizeof(buf)))
 		return -1;
@@ -155,7 +155,7 @@ long cg_read_long_fd(int fd)
 
 long cg_read_key_long(const char *cgroup, const char *control, const char *key)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	char *ptr;
 
 	if (cg_read(cgroup, control, buf, sizeof(buf)))
@@ -191,7 +191,7 @@ long cg_read_key_long_poll(const char *cgroup, const char *control,
 
 long cg_read_lc(const char *cgroup, const char *control)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	const char delim[] = "\n";
 	char *line;
 	long cnt = 0;
@@ -243,7 +243,7 @@ int cg_write_numeric(const char *cgroup, const char *control, long value)
 static int cg_find_root(char *root, size_t len, const char *controller,
 			bool *nsdelegate)
 {
-	char buf[10 * PAGE_SIZE];
+	char buf[10 * BUF_SIZE];
 	char *fs, *mount, *type, *options;
 	const char delim[] = "\n\t ";
 
@@ -298,7 +298,7 @@ int cg_create(const char *cgroup)
 
 int cg_wait_for_proc_count(const char *cgroup, int count)
 {
-	char buf[10 * PAGE_SIZE] = {0};
+	char buf[10 * BUF_SIZE] = {0};
 	int attempts;
 	char *ptr;
 
@@ -323,7 +323,7 @@ int cg_wait_for_proc_count(const char *cgroup, int count)
 
 int cg_killall(const char *cgroup)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	char *ptr = buf;
 
 	/* If cgroup.kill exists use it. */
@@ -533,7 +533,7 @@ int cg_run_nowait(const char *cgroup,
 
 int proc_mount_contains(const char *option)
 {
-	char buf[4 * PAGE_SIZE];
+	char buf[4 * BUF_SIZE];
 	ssize_t read;
 
 	read = read_text("/proc/mounts", buf, sizeof(buf));
@@ -545,7 +545,7 @@ int proc_mount_contains(const char *option)
 
 int cgroup_feature(const char *feature)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	ssize_t read;
 
 	read = read_text("/sys/kernel/cgroup/features", buf, sizeof(buf));
@@ -572,7 +572,7 @@ ssize_t proc_read_text(int pid, bool thread, const char *item, char *buf, size_t
 
 int proc_read_strstr(int pid, bool thread, const char *item, const char *needle)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 
 	if (proc_read_text(pid, thread, item, buf, sizeof(buf)) < 0)
 		return -1;
diff --git a/tools/testing/selftests/cgroup/lib/include/cgroup_util.h b/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
index 77f386dab5e8..ca4a161c17a4 100644
--- a/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
+++ b/tools/testing/selftests/cgroup/lib/include/cgroup_util.h
@@ -2,8 +2,8 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
+#ifndef BUF_SIZE
+#define BUF_SIZE 4096
 #endif
 
 #define MB(x) (x << 20)
diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index 102262555a59..df7fac7e5554 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -87,7 +87,7 @@ static int test_cgcore_destroy(const char *root)
 	int ret = KSFT_FAIL;
 	char *cg_test = NULL;
 	int child_pid;
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 
 	cg_test = cg_name(root, "cg_test");
 
diff --git a/tools/testing/selftests/cgroup/test_freezer.c b/tools/testing/selftests/cgroup/test_freezer.c
index 97fae92c8387..160a9e6ad277 100644
--- a/tools/testing/selftests/cgroup/test_freezer.c
+++ b/tools/testing/selftests/cgroup/test_freezer.c
@@ -642,7 +642,7 @@ static int test_cgfreezer_ptrace(const char *root)
  */
 static int proc_check_stopped(int pid)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	int len;
 
 	len = proc_read_text(pid, 0, "stat", buf, sizeof(buf));
diff --git a/tools/testing/selftests/cgroup/test_memcontrol.c b/tools/testing/selftests/cgroup/test_memcontrol.c
index 2fb096a2a9f9..c01e60b497aa 100644
--- a/tools/testing/selftests/cgroup/test_memcontrol.c
+++ b/tools/testing/selftests/cgroup/test_memcontrol.c
@@ -33,7 +33,7 @@ int get_temp_fd(void)
 
 int alloc_pagecache(int fd, size_t size)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	struct stat st;
 	int i;
 
@@ -60,7 +60,7 @@ int alloc_anon(const char *cgroup, void *arg)
 	char *buf, *ptr;
 
 	buf = malloc(size);
-	for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
+	for (ptr = buf; ptr < buf + size; ptr += BUF_SIZE)
 		*ptr = 0;
 
 	free(buf);
@@ -69,7 +69,7 @@ int alloc_anon(const char *cgroup, void *arg)
 
 int is_swap_enabled(void)
 {
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 	const char delim[] = "\n";
 	int cnt = 0;
 	char *line;
@@ -112,7 +112,7 @@ static int test_memcg_subtree_control(const char *root)
 {
 	char *parent, *child, *parent2 = NULL, *child2 = NULL;
 	int ret = KSFT_FAIL;
-	char buf[PAGE_SIZE];
+	char buf[BUF_SIZE];
 
 	/* Create two nested cgroups with the memory controller enabled */
 	parent = cg_name(root, "memcg_test_0");
@@ -183,7 +183,7 @@ static int alloc_anon_50M_check(const char *cgroup, void *arg)
 		return -1;
 	}
 
-	for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
+	for (ptr = buf; ptr < buf + size; ptr += BUF_SIZE)
 		*ptr = 0;
 
 	current = cg_read_long(cgroup, "memory.current");
@@ -413,7 +413,7 @@ static int alloc_anon_noexit(const char *cgroup, void *arg)
 		return -1;
 	}
 
-	for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
+	for (ptr = buf; ptr < buf + size; ptr += BUF_SIZE)
 		*ptr = 0;
 
 	while (getppid() == ppid)
@@ -999,7 +999,7 @@ static int alloc_anon_50M_check_swap(const char *cgroup, void *arg)
 		return -1;
 	}
 
-	for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
+	for (ptr = buf; ptr < buf + size; ptr += BUF_SIZE)
 		*ptr = 0;
 
 	mem_current = cg_read_long(cgroup, "memory.current");
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 5/7] selftests/cgroup: replace hardcoded page size values in test_zswap
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
                   ` (2 preceding siblings ...)
  2026-03-13  4:35 ` [PATCH v3 4/7] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  4:35 ` [PATCH v3 6/7] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system Li Wang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt

test_zswap uses hardcoded values of 4095 and 4096 throughout as page
stride and page size, which are only correct on systems with a 4K page
size. On architectures with larger pages (e.g., 64K on arm64 or ppc64),
these constants cause memory to be touched at sub-page granularity,
leading to inefficient access patterns and incorrect page count
calculations, which can cause test failures.

Replace all hardcoded 4095 and 4096 values with a global pagesize
variable initialized from sysconf(_SC_PAGESIZE) at startup, and remove
the redundant local sysconf() calls scattered across individual
functions. No functional change on 4K page size systems.

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Yosry Ahmed <yosryahmed@google.com>
---
 tools/testing/selftests/cgroup/test_zswap.c | 22 +++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index 74b57331cbf1..cf5b1531c827 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -13,6 +13,8 @@
 #include "kselftest.h"
 #include "cgroup_util.h"
 
+static size_t pagesize;
+
 static int read_int(const char *path, size_t *value)
 {
 	FILE *file;
@@ -68,11 +70,11 @@ static int allocate_and_read_bytes(const char *cgroup, void *arg)
 
 	if (!mem)
 		return -1;
-	for (int i = 0; i < size; i += 4095)
+	for (int i = 0; i < size; i += pagesize)
 		mem[i] = 'a';
 
 	/* Go through the allocated memory to (z)swap in and out pages */
-	for (int i = 0; i < size; i += 4095) {
+	for (int i = 0; i < size; i += pagesize) {
 		if (mem[i] != 'a')
 			ret = -1;
 	}
@@ -88,7 +90,7 @@ static int allocate_bytes(const char *cgroup, void *arg)
 
 	if (!mem)
 		return -1;
-	for (int i = 0; i < size; i += 4095)
+	for (int i = 0; i < size; i += pagesize)
 		mem[i] = 'a';
 	free(mem);
 	return 0;
@@ -267,7 +269,6 @@ static int test_zswapin(const char *root)
  */
 static int attempt_writeback(const char *cgroup, void *arg)
 {
-	long pagesize = sysconf(_SC_PAGESIZE);
 	size_t memsize = MB(4);
 	char buf[pagesize];
 	long zswap_usage;
@@ -436,7 +437,7 @@ static int test_no_invasive_cgroup_shrink(const char *root)
 	if (cg_enter_current(control_group))
 		goto out;
 	control_allocation = malloc(control_allocation_size);
-	for (int i = 0; i < control_allocation_size; i += 4095)
+	for (int i = 0; i < control_allocation_size; i += pagesize)
 		control_allocation[i] = 'a';
 	if (cg_read_key_long(control_group, "memory.stat", "zswapped") < 1)
 		goto out;
@@ -476,7 +477,7 @@ static int no_kmem_bypass_child(const char *cgroup, void *arg)
 		values->child_allocated = true;
 		return -1;
 	}
-	for (long i = 0; i < values->target_alloc_bytes; i += 4095)
+	for (long i = 0; i < values->target_alloc_bytes; i += pagesize)
 		((char *)allocation)[i] = 'a';
 	values->child_allocated = true;
 	pause();
@@ -524,7 +525,7 @@ static int test_no_kmem_bypass(const char *root)
 	min_free_kb_low = sys_info.totalram / 500000;
 	values->target_alloc_bytes = (sys_info.totalram - min_free_kb_high * 1000) +
 		sys_info.totalram * 5 / 100;
-	stored_pages_threshold = sys_info.totalram / 5 / 4096;
+	stored_pages_threshold = sys_info.totalram / 5 / pagesize;
 	trigger_allocation_size = sys_info.totalram / 20;
 
 	/* Set up test memcg */
@@ -551,7 +552,7 @@ static int test_no_kmem_bypass(const char *root)
 
 		if (!trigger_allocation)
 			break;
-		for (int i = 0; i < trigger_allocation_size; i += 4095)
+		for (int i = 0; i < trigger_allocation_size; i += pagesize)
 			trigger_allocation[i] = 'b';
 		usleep(100000);
 		free(trigger_allocation);
@@ -562,8 +563,8 @@ static int test_no_kmem_bypass(const char *root)
 		/* If memory was pushed to zswap, verify it belongs to memcg */
 		if (stored_pages > stored_pages_threshold) {
 			int zswapped = cg_read_key_long(test_group, "memory.stat", "zswapped ");
-			int delta = stored_pages * 4096 - zswapped;
-			int result_ok = delta < stored_pages * 4096 / 4;
+			int delta = stored_pages * pagesize - zswapped;
+			int result_ok = delta < stored_pages * pagesize / 4;
 
 			ret = result_ok ? KSFT_PASS : KSFT_FAIL;
 			break;
@@ -616,6 +617,7 @@ int main(int argc, char **argv)
 	char root[PATH_MAX];
 	int i;
 
+	pagesize = sysconf(_SC_PAGESIZE);
 	ksft_print_header();
 	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 6/7] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
                   ` (3 preceding siblings ...)
  2026-03-13  4:35 ` [PATCH v3 5/7] selftests/cgroup: replace hardcoded page size values in test_zswap Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  4:35 ` [PATCH v3 7/7] selftest/cgroup: fix zswap attempt_writeback() on 64K " Li Wang
  2026-03-13  6:34 ` [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Yosry Ahmed
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt

test_no_invasive_cgroup_shrink uses fixed zswap/memory limits and
allocation sizes that are too small on systems with large PAGE_SIZE
(e.g. 64K). In that case, the test may fail to build enough pressure
to trigger zswap writeback reliably, leading to false failures.

Make the test size parameters PAGE_SIZE-aware and consistent:
  - set control_allocation_size to PAGE_SIZE * 1024,
  - set memory.zswap.max to PAGE_SIZE,
  - set memory.max of both cgroups to control_allocation_size / 2,
  - allocate control_allocation_size in wb_group (2x memory.max).

This keeps the test behavior stable across 4K and 64K PAGE_SIZE
configurations and avoids spurious failures in
test_no_invasive_cgroup_shrink.

=== Error Log ===
 # getconf PAGESIZE
 65536

 # ./test_zswap
 TAP version 13
 ...
 ok 5 test_zswap_writeback_disabled
 ok 6 # SKIP test_no_kmem_bypass
 not ok 7 test_no_invasive_cgroup_shrink

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Yosry Ahmed <yosryahmed@google.com>
---

Notes:
    v3:
    	- Make PAGE_SIZE aware instead of using fixed sizing.
    	- Set memory.max for  wb_group/control_group to control_allocation_size/2.
    	- Update wb_group pressure allocation to control_allocation_size.
    	- Clarify commit message to focus on this test's sizing issue.
    v2:
    	- No change.

 tools/testing/selftests/cgroup/test_zswap.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index cf5b1531c827..f84e84c3e7c8 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -421,17 +421,26 @@ static int test_zswap_writeback_disabled(const char *root)
 static int test_no_invasive_cgroup_shrink(const char *root)
 {
 	int ret = KSFT_FAIL;
-	size_t control_allocation_size = MB(10);
+	size_t control_allocation_size = pagesize * 1024;
+	char zswap_max_buf[32], mem_max_buf[32];
 	char *control_allocation = NULL, *wb_group = NULL, *control_group = NULL;
 
+	snprintf(zswap_max_buf, sizeof(zswap_max_buf), "%ld", pagesize);
+	snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", control_allocation_size / 2);
+
 	wb_group = setup_test_group_1M(root, "per_memcg_wb_test1");
 	if (!wb_group)
 		return KSFT_FAIL;
-	if (cg_write(wb_group, "memory.zswap.max", "10K"))
+	if (cg_write(wb_group, "memory.zswap.max", zswap_max_buf))
+		goto out;
+	if (cg_write(wb_group, "memory.max", mem_max_buf))
 		goto out;
+
 	control_group = setup_test_group_1M(root, "per_memcg_wb_test2");
 	if (!control_group)
 		goto out;
+	if (cg_write(control_group, "memory.max", mem_max_buf))
+		goto out;
 
 	/* Push some test_group2 memory into zswap */
 	if (cg_enter_current(control_group))
@@ -442,8 +451,8 @@ static int test_no_invasive_cgroup_shrink(const char *root)
 	if (cg_read_key_long(control_group, "memory.stat", "zswapped") < 1)
 		goto out;
 
-	/* Allocate 10x memory.max to push wb_group memory into zswap and trigger wb */
-	if (cg_run(wb_group, allocate_bytes, (void *)MB(10)))
+	/* Allocate 2x memory.max to push wb_group memory into zswap and trigger wb */
+	if (cg_run(wb_group, allocate_bytes, (void *)control_allocation_size))
 		goto out;
 
 	/* Verify that only zswapped memory from gwb_group has been written back */
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 7/7] selftest/cgroup: fix zswap attempt_writeback() on 64K pagesize system
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
                   ` (4 preceding siblings ...)
  2026-03-13  4:35 ` [PATCH v3 6/7] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system Li Wang
@ 2026-03-13  4:35 ` Li Wang
  2026-03-13  6:34 ` [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Yosry Ahmed
  6 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-13  4:35 UTC (permalink / raw)
  To: yosryahmed, nphamcs
  Cc: linux-kselftest, linux-kernel, linux-mm, Johannes Weiner,
	Michal Hocko, Michal Koutný, Muchun Song, Tejun Heo,
	Roman Gushchin, Shakeel Butt, Yosry Ahmed

In attempt_writeback(), a memsize of 4M only covers 64 pages on 64K
page size systems. When memory.reclaim is called, the kernel prefers
reclaiming clean file pages (binary, libc, linker, etc.) over swapping
anonymous pages. With only 64 pages of anonymous memory, the reclaim
target can be largely or entirely satisfied by dropping file pages,
resulting in very few or zero anonymous pages being pushed into zswap.

This causes zswap_usage to be extremely small or zero, making
zswap_usage/2 insufficient to create meaningful writeback pressure.
The test then fails because no writeback is triggered.

On 4K page size systems this is not an issue because 4M covers 1024
pages, and file pages are a small fraction of the reclaim target.

Fix this by always allocating 1024 pages regardless of page size.
This ensures enough anonymous pages to reliably populate zswap and
trigger writeback, while keeping the original 4M allocation on 4K
page size systems.

=== Error Log ===
  # uname -rm
  6.12.0-211.el10.ppc64le ppc64le

  # getconf PAGESIZE
  65536

  # ./test_zswap
  TAP version 13
  1..7
  ok 1 test_zswap_usage
  ok 2 test_swapin_nozswap
  ok 3 test_zswapin
  not ok 4 test_zswap_writeback_enabled
  ...

Signed-off-by: Li Wang <liwang@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Yosry Ahmed <yosry@kernel.org>
---

Notes:
    v3:
    	- No changes.
    v2:
    	- use pagesize * 1024 which clearly shows the page numbers.

 tools/testing/selftests/cgroup/test_zswap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index f84e84c3e7c8..d7a862a414e5 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -269,7 +269,7 @@ static int test_zswapin(const char *root)
  */
 static int attempt_writeback(const char *cgroup, void *arg)
 {
-	size_t memsize = MB(4);
+	size_t memsize = pagesize * 1024;
 	char buf[pagesize];
 	long zswap_usage;
 	bool wb_enabled = *(bool *) arg;
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
                   ` (5 preceding siblings ...)
  2026-03-13  4:35 ` [PATCH v3 7/7] selftest/cgroup: fix zswap attempt_writeback() on 64K " Li Wang
@ 2026-03-13  6:34 ` Yosry Ahmed
  2026-03-13  8:00   ` Li Wang
  6 siblings, 1 reply; 13+ messages in thread
From: Yosry Ahmed @ 2026-03-13  6:34 UTC (permalink / raw)
  To: Li Wang
  Cc: yosryahmed, nphamcs, linux-kselftest, linux-kernel, linux-mm,
	Johannes Weiner, Michal Hocko, Michal Koutný, Muchun Song,
	Tejun Heo, Roman Gushchin, Shakeel Butt

> diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
> index 64ebc3f3f203..e69d845d3592 100644
> --- a/tools/testing/selftests/cgroup/test_zswap.c
> +++ b/tools/testing/selftests/cgroup/test_zswap.c
> @@ -589,9 +589,21 @@ struct zswap_test {
>  };
>  #undef T
>
> -static bool zswap_configured(void)
> +static void check_zswap_enabled(void)
>  {
> -       return access("/sys/module/zswap", F_OK) == 0;
> +       char value[2];

Please wait for discussions on the previous version to conclude and
give people a little bit of time to respond before sending the next
version.

I think this can just be be:

    char value;
    ...

    if (read_text(.., &value, sizeof(value)) < 0)

> +
> +       if (access("/sys/module/zswap", F_OK))
> +               ksft_exit_skip("zswap isn't configured\n");
> +
> +       if (read_text("/sys/module/zswap/parameters/enabled", value,
> +                                               sizeof(value)) <= 0)
> +               ksft_exit_fail_msg("Failed to read "
> +                               "/sys/module/zswap/parameters/enabled\n");
> +
> +       if (value[0] == 'N')
> +               ksft_exit_skip("zswap is disabled (hint: echo 1 > "
> +                               "/sys/module/zswap/parameters/enabled)\n");
>  }
>
>  int main(int argc, char **argv)
> @@ -604,8 +616,7 @@ int main(int argc, char **argv)
>         if (cg_find_unified_root(root, sizeof(root), NULL))
>                 ksft_exit_skip("cgroup v2 isn't mounted\n");
>
> -       if (!zswap_configured())
> -               ksft_exit_skip("zswap isn't configured\n");
> +       check_zswap_enabled();
>
>         /*
>          * Check that memory controller is available:
> --
> 2.53.0
>
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-13  6:34 ` [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Yosry Ahmed
@ 2026-03-13  8:00   ` Li Wang
  2026-03-13 17:35     ` Yosry Ahmed
  0 siblings, 1 reply; 13+ messages in thread
From: Li Wang @ 2026-03-13  8:00 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: yosryahmed, nphamcs, linux-kselftest, linux-kernel, linux-mm,
	Johannes Weiner, Michal Hocko, Michal Koutný, Muchun Song,
	Tejun Heo, Roman Gushchin, Shakeel Butt

On Thu, Mar 12, 2026 at 11:34:41PM -0700, Yosry Ahmed wrote:
> > diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
> > index 64ebc3f3f203..e69d845d3592 100644
> > --- a/tools/testing/selftests/cgroup/test_zswap.c
> > +++ b/tools/testing/selftests/cgroup/test_zswap.c
> > @@ -589,9 +589,21 @@ struct zswap_test {
> >  };
> >  #undef T
> >
> > -static bool zswap_configured(void)
> > +static void check_zswap_enabled(void)
> >  {
> > -       return access("/sys/module/zswap", F_OK) == 0;
> > +       char value[2];
> 
> Please wait for discussions on the previous version to conclude and
> give people a little bit of time to respond before sending the next
> version.

Sorry for the rush. I thought that I had clarified the issue there.

> I think this can just be be:
> 
>     char value;
>     ...
> 
>     if (read_text(.., &value, sizeof(value)) < 0)

This actuall introduce a problem to the code, as in read_text()
that achivement is:

  len = read(fd, buf, max_len - 1);

When 'sizeof(value) == 1' pass in that makes read(fd, &value, 0);
read zero, after that, the value is set to '\0'.

With your < 0 check, this is treated as success, then value == 'N' is false,
the check_zswap_enabled will report wrong status (enabled) on disabled.

-- 
Regards,
Li Wang



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-13  8:00   ` Li Wang
@ 2026-03-13 17:35     ` Yosry Ahmed
  2026-03-20  1:25       ` Li Wang
  0 siblings, 1 reply; 13+ messages in thread
From: Yosry Ahmed @ 2026-03-13 17:35 UTC (permalink / raw)
  To: Li Wang
  Cc: yosryahmed, nphamcs, linux-kselftest, linux-kernel, linux-mm,
	Johannes Weiner, Michal Hocko, Michal Koutný, Muchun Song,
	Tejun Heo, Roman Gushchin, Shakeel Butt

On Fri, Mar 13, 2026 at 1:00 AM Li Wang <liwang@redhat.com> wrote:
>
> On Thu, Mar 12, 2026 at 11:34:41PM -0700, Yosry Ahmed wrote:
> > > diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
> > > index 64ebc3f3f203..e69d845d3592 100644
> > > --- a/tools/testing/selftests/cgroup/test_zswap.c
> > > +++ b/tools/testing/selftests/cgroup/test_zswap.c
> > > @@ -589,9 +589,21 @@ struct zswap_test {
> > >  };
> > >  #undef T
> > >
> > > -static bool zswap_configured(void)
> > > +static void check_zswap_enabled(void)
> > >  {
> > > -       return access("/sys/module/zswap", F_OK) == 0;
> > > +       char value[2];
> >
> > Please wait for discussions on the previous version to conclude and
> > give people a little bit of time to respond before sending the next
> > version.
>
> Sorry for the rush. I thought that I had clarified the issue there.
>
> > I think this can just be be:
> >
> >     char value;
> >     ...
> >
> >     if (read_text(.., &value, sizeof(value)) < 0)
>
> This actuall introduce a problem to the code, as in read_text()
> that achivement is:
>
>   len = read(fd, buf, max_len - 1);
>
> When 'sizeof(value) == 1' pass in that makes read(fd, &value, 0);
> read zero, after that, the value is set to '\0'.

I see, I missed that, thanks for clarifying. If you do send a new
version, put the path of the module parameter in a macro or variable
to make the lines in check_zswap_enabled() shorter and hopefully have
everything fit in one line. Anyway:

Acked-by: Yosry Ahmed <yosry@kernel.org>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-13 17:35     ` Yosry Ahmed
@ 2026-03-20  1:25       ` Li Wang
  2026-03-20 19:35         ` Andrew Morton
  0 siblings, 1 reply; 13+ messages in thread
From: Li Wang @ 2026-03-20  1:25 UTC (permalink / raw)
  To: Yosry Ahmed, Andrew Morton
  Cc: yosryahmed, nphamcs, linux-kselftest, linux-kernel, linux-mm,
	Johannes Weiner, Michal Hocko, Michal Koutný, Muchun Song,
	Tejun Heo, Roman Gushchin, Shakeel Butt

[-- Attachment #1: Type: text/plain, Size: 1922 bytes --]

Hi Yosry,

Do you know who will help merge this patchset?
Should I wait or ping someone to move on the process?


On Sat, Mar 14, 2026 at 1:35 AM Yosry Ahmed <yosry@kernel.org> wrote:

> On Fri, Mar 13, 2026 at 1:00 AM Li Wang <liwang@redhat.com> wrote:
> >
> > On Thu, Mar 12, 2026 at 11:34:41PM -0700, Yosry Ahmed wrote:
> > > > diff --git a/tools/testing/selftests/cgroup/test_zswap.c
> b/tools/testing/selftests/cgroup/test_zswap.c
> > > > index 64ebc3f3f203..e69d845d3592 100644
> > > > --- a/tools/testing/selftests/cgroup/test_zswap.c
> > > > +++ b/tools/testing/selftests/cgroup/test_zswap.c
> > > > @@ -589,9 +589,21 @@ struct zswap_test {
> > > >  };
> > > >  #undef T
> > > >
> > > > -static bool zswap_configured(void)
> > > > +static void check_zswap_enabled(void)
> > > >  {
> > > > -       return access("/sys/module/zswap", F_OK) == 0;
> > > > +       char value[2];
> > >
> > > Please wait for discussions on the previous version to conclude and
> > > give people a little bit of time to respond before sending the next
> > > version.
> >
> > Sorry for the rush. I thought that I had clarified the issue there.
> >
> > > I think this can just be be:
> > >
> > >     char value;
> > >     ...
> > >
> > >     if (read_text(.., &value, sizeof(value)) < 0)
> >
> > This actuall introduce a problem to the code, as in read_text()
> > that achivement is:
> >
> >   len = read(fd, buf, max_len - 1);
> >
> > When 'sizeof(value) == 1' pass in that makes read(fd, &value, 0);
> > read zero, after that, the value is set to '\0'.
>
> I see, I missed that, thanks for clarifying. If you do send a new
> version, put the path of the module parameter in a macro or variable
> to make the lines in check_zswap_enabled() shorter and hopefully have
> everything fit in one line. Anyway:
>
> Acked-by: Yosry Ahmed <yosry@kernel.org>
>


-- 
Regards,
Li Wang

[-- Attachment #2: Type: text/html, Size: 3175 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-20  1:25       ` Li Wang
@ 2026-03-20 19:35         ` Andrew Morton
  2026-03-22  3:08           ` Li Wang
  0 siblings, 1 reply; 13+ messages in thread
From: Andrew Morton @ 2026-03-20 19:35 UTC (permalink / raw)
  To: Li Wang
  Cc: Yosry Ahmed, yosryahmed, nphamcs, linux-kselftest, linux-kernel,
	linux-mm, Johannes Weiner, Michal Hocko, Michal Koutný,
	Muchun Song, Tejun Heo, Roman Gushchin, Shakeel Butt

On Fri, 20 Mar 2026 09:25:10 +0800 Li Wang <liwang@redhat.com> wrote:

> Hi Yosry,
> 
> Do you know who will help merge this patchset?

That would be me.

> Should I wait or ping someone to move on the process?

A few more reviewed-by's would be nice.

Meanwhile, AI review has a lot of things to say:
	https://sashiko.dev/#/patchset/20260313043532.103987-1-liwang@redhat.com


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled
  2026-03-20 19:35         ` Andrew Morton
@ 2026-03-22  3:08           ` Li Wang
  0 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-22  3:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Yosry Ahmed, yosryahmed, nphamcs, linux-kselftest, linux-kernel,
	linux-mm, Johannes Weiner, Michal Hocko, Michal Koutný,
	Muchun Song, Tejun Heo, Roman Gushchin, Shakeel Butt

Andrew Morton wrote:

> Meanwhile, AI review has a lot of things to say:
> 	https://sashiko.dev/#/patchset/20260313043532.103987-1-liwang@redhat.com

> [Sashiko comment in patch 2/7]
> ...
> Could this diagnostic message be updated to print the expected swap amount
> in KB or bytes to avoid confusion?

Yes, good point, will modify it in v4.

> [Sashiko comments in patch 4/7]
> ...
> Is this description accurate?
> Looking at tools/testing/selftests/cgroup/test_memcontrol.c, the macro is
> also used as a memory stride to trigger page faults:
>     for (ptr = buf; ptr < buf + size; ptr += BUF_SIZE)
>         *ptr = 0;
> Could renaming this to BUF_SIZE obscure the original intent of touching
> each memory page once to force it to be resident?

Well, maybe yes, we can use page_size for this one.

> Could this lead to truncation of /proc/self/mounts on architectures like
> arm64?
> Since BUF_SIZE is strictly 4096, this reduces the buffer size from 640KB
> (when PAGE_SIZE was 64K from system headers) to 40KB. If the mounts file
> exceeds this limit, the buffer is cleanly null-terminated but the last line
> is truncated.
> Later in this function, strtok() extracts tokens without checking for NULL:
>     type = strtok(NULL, delim);
>     options = strtok(NULL, delim);
>     ...
>     if (strcmp(type, "cgroup") == 0) {
>         if (!controller || !strstr(options, controller))
> Will passing a NULL type or options pointer directly to string comparison
> functions cause a segmentation fault?

Theoretically, you're right. But in real situation we haven't observe such
failure so we can just add NULL checks on the strtok() return values.

    options = strtok(NULL, delim);
    if (!type || !options)
        continue;

> Does this code evaluate its exit condition correctly when waiting for a
> cgroup to become empty?
> When test code wants to wait for a cgroup to become empty by passing count
> = 0 (e.g., in test_cgfreezer_forkbomb()), the loop exit condition is:
>     if (nr >= count)
>         return 0;
> Doesn't nr >= 0 evaluate to true on the very first iteration, returning
> immediately and bypassing the intended wait intervals? Could this cause
> subsequent cg_destroy() calls to fail with EBUSY because the processes have
> not yet fully terminated?

Okay, this smeems a problem, but not blong to this patchset.
I would sugguest fixing it in another series.

> Is it safe to ignore the return value of read() here?
> If the read() fails, the loop will continue incrementing the offset without
> instantiating the data into the page cache:
>     for (i = 0; i < size; i += sizeof(buf))
>         read(fd, buf, sizeof(buf));
> Can this silently fail to establish the required memory conditions for the
> tests?

This also can be improved in another series. Shouldn't resolve in
this one.

> Can this dereference a NULL pointer under memory pressure?

Theoretically, you're right. But I think NULL pointer checks can
be added in another series.

> [Sashiko comments in patch 5/7]
> ...
> If malloc() fails and returns NULL, does this loop dereference a NULL pointer
> when writing to control_allocation[i]? Other allocations in this file seem to
> check for NULL before proceeding.

Theoretically, you're right. But I think NULL pointer checks can
be added in another series.

> [Sashiko comment in patch 6/7]
> ...
> Does this larger allocation size require a NULL check on the malloc return
> value later in this function?

Theoretically, you're right. But I think NULL pointer checks can
be added in another series.

>> +	snprintf(zswap_max_buf, sizeof(zswap_max_buf), "%ld", pagesize);
> This isn't a bug, but since pagesize is a size_t, should this use the %zu
> format specifier instead of %ld to avoid compiler warnings on 32-bit
> platforms where size_t is an unsigned int?

Good point, let's use %zu in patch v4.

> Will this new limit consistently trigger zswap writeback on systems with
> efficient memory compression?

At least based on my testing, (whether on 4k or 64k systems), everything
runs smoothly; this change has indeed reduced instances of false failures
in real-world.

-- 
Regards,
Li Wang



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-03-22  3:08 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-13  4:35 [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
2026-03-13  4:35 ` [PATCH v3 2/7] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
2026-03-13  4:35 ` [PATCH v3 3/7] selftests/cgroup: use runtime page size for zswpin check Li Wang
2026-03-13  4:35 ` [PATCH v3 4/7] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util Li Wang
2026-03-13  4:35 ` [PATCH v3 5/7] selftests/cgroup: replace hardcoded page size values in test_zswap Li Wang
2026-03-13  4:35 ` [PATCH v3 6/7] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system Li Wang
2026-03-13  4:35 ` [PATCH v3 7/7] selftest/cgroup: fix zswap attempt_writeback() on 64K " Li Wang
2026-03-13  6:34 ` [PATCH v3 1/7] selftests/cgroup: skip test_zswap if zswap is globally disabled Yosry Ahmed
2026-03-13  8:00   ` Li Wang
2026-03-13 17:35     ` Yosry Ahmed
2026-03-20  1:25       ` Li Wang
2026-03-20 19:35         ` Andrew Morton
2026-03-22  3:08           ` Li Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox