* [PATCH v5 1/8] selftests/cgroup: skip test_zswap if zswap is globally disabled
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 2/8] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm,
Yosry Ahmed
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>
Acked-by: Yosry Ahmed <yosry@kernel.org>
---
Notes:
v5:
- Defined PATH_ZSWAP and PATH_ZSWAP_ENABLED macros to avoid line breaks
v4:
- No changes.
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..44fa81ef6157 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -13,6 +13,9 @@
#include "kselftest.h"
#include "cgroup_util.h"
+#define PATH_ZSWAP "/sys/module/zswap"
+#define PATH_ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled"
+
static int read_int(const char *path, size_t *value)
{
FILE *file;
@@ -589,9 +592,18 @@ 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(PATH_ZSWAP, F_OK))
+ ksft_exit_skip("zswap isn't configured\n");
+
+ if (read_text(PATH_ZSWAP_ENABLED, value, sizeof(value)) <= 0)
+ ksft_exit_fail_msg("Failed to read " PATH_ZSWAP_ENABLED "\n");
+
+ if (value[0] == 'N')
+ ksft_exit_skip("zswap is disabled (hint: echo 1 > " PATH_ZSWAP_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 v5 2/8] selftests/cgroup: avoid OOM in test_swapin_nozswap
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
2026-03-26 3:26 ` [PATCH v5 1/8] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 3/8] selftests/cgroup: use runtime page size for zswpin check Li Wang
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm
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:
v4:
- print the expected swap amount in KB but not MB.
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 44fa81ef6157..ed257d464bd6 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -163,21 +163,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 allocation_size = sysconf(_SC_PAGESIZE) * 512;
+
+ min_swap = allocation_size / 4;
+ snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", 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 *)allocation_size))
goto out;
/* Verify that pages are swapped out, but no zswap happened */
@@ -187,8 +191,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 %ldKB of memory should be swapped out\n",
+ min_swap / 1024);
goto out;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 3/8] selftests/cgroup: use runtime page size for zswpin check
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
2026-03-26 3:26 ` [PATCH v5 1/8] selftests/cgroup: skip test_zswap if zswap is globally disabled Li Wang
2026-03-26 3:26 ` [PATCH v5 2/8] selftests/cgroup: avoid OOM in test_swapin_nozswap Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 4/8] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util Li Wang
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm
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 ed257d464bd6..516da5d52bfd 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -243,7 +243,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 v5 4/8] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (2 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 3/8] selftests/cgroup: use runtime page size for zswpin check Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 5/8] selftests/cgroup: replace hardcoded page size values in test_zswap Li Wang
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm,
Yosry Ahmed
The cgroup utility code defines a local PAGE_SIZE macro hardcoded to
4096, which is used primarily as a generic buffer size for reading cgroup
and proc files. This naming is misleading because the value has nothing
to do with the actual page size of the system. 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 PAGE_SIZE
definitions from system headers, leading to confusion or subtle bugs.
To resolve this, rename the macro to BUF_SIZE to accurately reflect its
purpose as a general I/O buffer size.
Furthermore, test_memcontrol currently relies on this hardcoded 4K value
to stride through memory and trigger page faults. Update this logic to
use the actual system page size dynamically. This micro-optimizes the
memory faulting process by ensuring it iterates correctly and efficiently
based on the underlying architecture's true page size. (This part from Waiman)
Signed-off-by: Li Wang <liwang@redhat.com>
Signed-off-by: Waiman Long <longman@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:
v5:
- Merge Waiman's work into this patch (use page_size)
v4:
- Use page_size instead of BUF_SIZE in test_memcontrol.c
v3, v2, v1:
- No changes.
.../selftests/cgroup/lib/cgroup_util.c | 18 +++++++++---------
.../cgroup/lib/include/cgroup_util.h | 4 ++--
tools/testing/selftests/cgroup/test_core.c | 2 +-
tools/testing/selftests/cgroup/test_freezer.c | 2 +-
.../selftests/cgroup/test_memcontrol.c | 19 ++++++++++++-------
5 files changed, 25 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..94d7b9de978c 100644
--- a/tools/testing/selftests/cgroup/test_memcontrol.c
+++ b/tools/testing/selftests/cgroup/test_memcontrol.c
@@ -25,6 +25,7 @@
static bool has_localevents;
static bool has_recursiveprot;
+static size_t page_size;
int get_temp_fd(void)
{
@@ -33,7 +34,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 +61,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 +70,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 +113,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 +184,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 += page_size)
*ptr = 0;
current = cg_read_long(cgroup, "memory.current");
@@ -413,7 +414,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 += page_size)
*ptr = 0;
while (getppid() == ppid)
@@ -999,7 +1000,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 += page_size)
*ptr = 0;
mem_current = cg_read_long(cgroup, "memory.current");
@@ -1670,6 +1671,10 @@ int main(int argc, char **argv)
char root[PATH_MAX];
int i, proc_status;
+ page_size = sysconf(_SC_PAGE_SIZE);
+ if (page_size <= 0)
+ page_size = BUF_SIZE;
+
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 v5 5/8] selftests/cgroup: replace hardcoded page size values in test_zswap
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (3 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 4/8] selftests/cgroup: rename PAGE_SIZE to BUF_SIZE in cgroup_util Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 6/8] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system Li Wang
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm
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>
Acked-by: Yosry Ahmed <yosry@kernel.org>
---
Notes:
v5:
- Change pagesize by the global page_size.
v1-4:
- No changes.
tools/testing/selftests/cgroup/test_zswap.c | 39 ++++++++++++---------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index 516da5d52bfd..fc7a9aa27e27 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 page_size;
+
#define PATH_ZSWAP "/sys/module/zswap"
#define PATH_ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled"
@@ -71,11 +73,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 += page_size)
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 += page_size) {
if (mem[i] != 'a')
ret = -1;
}
@@ -91,7 +93,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 += page_size)
mem[i] = 'a';
free(mem);
return 0;
@@ -270,9 +272,8 @@ 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];
+ char buf[page_size];
long zswap_usage;
bool wb_enabled = *(bool *) arg;
int ret = -1;
@@ -287,11 +288,11 @@ static int attempt_writeback(const char *cgroup, void *arg)
* half empty, this will result in data that is still compressible
* and ends up in zswap, with material zswap usage.
*/
- for (int i = 0; i < pagesize; i++)
- buf[i] = i < pagesize/2 ? (char) i : 0;
+ for (int i = 0; i < page_size; i++)
+ buf[i] = i < page_size/2 ? (char) i : 0;
- for (int i = 0; i < memsize; i += pagesize)
- memcpy(&mem[i], buf, pagesize);
+ for (int i = 0; i < memsize; i += page_size)
+ memcpy(&mem[i], buf, page_size);
/* Try and reclaim allocated memory */
if (cg_write_numeric(cgroup, "memory.reclaim", memsize)) {
@@ -302,8 +303,8 @@ static int attempt_writeback(const char *cgroup, void *arg)
zswap_usage = cg_read_long(cgroup, "memory.zswap.current");
/* zswpin */
- for (int i = 0; i < memsize; i += pagesize) {
- if (memcmp(&mem[i], buf, pagesize)) {
+ for (int i = 0; i < memsize; i += page_size) {
+ if (memcmp(&mem[i], buf, page_size)) {
ksft_print_msg("invalid memory\n");
goto out;
}
@@ -439,7 +440,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 += page_size)
control_allocation[i] = 'a';
if (cg_read_key_long(control_group, "memory.stat", "zswapped") < 1)
goto out;
@@ -479,7 +480,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 += page_size)
((char *)allocation)[i] = 'a';
values->child_allocated = true;
pause();
@@ -527,7 +528,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 / page_size;
trigger_allocation_size = sys_info.totalram / 20;
/* Set up test memcg */
@@ -554,7 +555,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 += page_size)
trigger_allocation[i] = 'b';
usleep(100000);
free(trigger_allocation);
@@ -565,8 +566,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 * page_size - zswapped;
+ int result_ok = delta < stored_pages * page_size / 4;
ret = result_ok ? KSFT_PASS : KSFT_FAIL;
break;
@@ -616,6 +617,10 @@ int main(int argc, char **argv)
char root[PATH_MAX];
int i;
+ page_size = sysconf(_SC_PAGE_SIZE);
+ if (page_size <= 0)
+ page_size = BUF_SIZE;
+
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 v5 6/8] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (4 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 5/8] selftests/cgroup: replace hardcoded page size values in test_zswap Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 7/8] selftest/cgroup: fix zswap attempt_writeback() on 64K " Li Wang
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm,
Yosry Ahmed
test_no_invasive_cgroup_shrink sets up two cgroups: wb_group, which is
expected to trigger zswap writeback, and a control group (renamed to
zw_group), which should only have pages sitting in zswap without any
writeback.
There are two problems with the current test:
1) The data patterns are reversed. wb_group uses allocate_bytes(), which
writes only a single byte per page — trivially compressible,
especially by zstd — so compressed pages fit within zswap.max and
writeback is never triggered. Meanwhile, the control group uses
getrandom() to produce hard-to-compress data, but it is the group
that does *not* need writeback.
2) The test uses fixed sizes (10K zswap.max, 10MB allocation) that are
too small on systems with large PAGE_SIZE (e.g. 64K), failing to
build enough memory pressure to trigger writeback reliably.
Fix both issues by:
- Swapping the data patterns: fill wb_group pages with partially
random data (getrandom for page_size/4 bytes) to resist compression
and trigger writeback, and fill zw_group pages with simple repeated
data to stay compressed in zswap.
- Making all size parameters PAGE_SIZE-aware: set allocation size to
PAGE_SIZE * 1024, memory.zswap.max to PAGE_SIZE, and memory.max to
allocation_size / 2 for both cgroups.
- Allocating memory inline instead of via cg_run() so the pages
remain resident throughout the test.
=== 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:
v5:
- Swap data patterns: use getrandom() for wb_group and simple
memset for zw_group to fix the reversed allocation logic.
- Rename control_group to zw_group for clarity.
- Allocate memory inline instead of via cg_run() so pages remain
resident throughout the test.
tools/testing/selftests/cgroup/test_zswap.c | 69 ++++++++++++++-------
1 file changed, 48 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index fc7a9aa27e27..72082e5d4725 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -9,6 +9,7 @@
#include <string.h>
#include <sys/wait.h>
#include <sys/mman.h>
+#include <sys/random.h>
#include "kselftest.h"
#include "cgroup_util.h"
@@ -424,44 +425,70 @@ 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);
- char *control_allocation = NULL, *wb_group = NULL, *control_group = NULL;
+ unsigned int off;
+ size_t allocation_size = page_size * 1024;
+ unsigned int nr_pages = allocation_size / page_size;
+ char zswap_max_buf[32], mem_max_buf[32];
+ char *zw_allocation = NULL, *wb_allocation = NULL;
+ char *zw_group = NULL, *wb_group = NULL;
+
+ snprintf(zswap_max_buf, sizeof(zswap_max_buf), "%zu", page_size);
+ snprintf(mem_max_buf, sizeof(mem_max_buf), "%zu", 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;
+
+ zw_group = setup_test_group_1M(root, "per_memcg_wb_test2");
+ if (!zw_group)
goto out;
- control_group = setup_test_group_1M(root, "per_memcg_wb_test2");
- if (!control_group)
+ if (cg_write(zw_group, "memory.max", mem_max_buf))
goto out;
- /* Push some test_group2 memory into zswap */
- if (cg_enter_current(control_group))
+ /* Push some zw_group memory into zswap (simple data, easy to compress) */
+ if (cg_enter_current(zw_group))
goto out;
- control_allocation = malloc(control_allocation_size);
- for (int i = 0; i < control_allocation_size; i += page_size)
- control_allocation[i] = 'a';
- if (cg_read_key_long(control_group, "memory.stat", "zswapped") < 1)
+ zw_allocation = malloc(allocation_size);
+ for (int i = 0; i < nr_pages; i++) {
+ off = (unsigned long)i * page_size;
+ memset(&zw_allocation[off], 'a', page_size/4);
+ }
+ if (cg_read_key_long(zw_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)))
+ /* Push wb_group memory into zswap with hard-to-compress data to trigger wb */
+ if (cg_enter_current(wb_group))
+ goto out;
+ wb_allocation = malloc(allocation_size);
+ if (!wb_allocation)
goto out;
+ for (int i = 0; i < nr_pages; i++) {
+ off = (unsigned long)i * page_size;
+ memset(&wb_allocation[off], 0, page_size);
+ getrandom(&wb_allocation[off], page_size/4, 0);
+ }
/* Verify that only zswapped memory from gwb_group has been written back */
- if (get_cg_wb_count(wb_group) > 0 && get_cg_wb_count(control_group) == 0)
+ if (get_cg_wb_count(wb_group) > 0 && get_cg_wb_count(zw_group) == 0)
ret = KSFT_PASS;
out:
cg_enter_current(root);
- if (control_group) {
- cg_destroy(control_group);
- free(control_group);
+ if (zw_group) {
+ cg_destroy(zw_group);
+ free(zw_group);
+ }
+ if (wb_group) {
+ cg_destroy(wb_group);
+ free(wb_group);
}
- cg_destroy(wb_group);
- free(wb_group);
- if (control_allocation)
- free(control_allocation);
+ if (zw_allocation)
+ free(zw_allocation);
+ if (wb_allocation)
+ free(wb_allocation);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 7/8] selftest/cgroup: fix zswap attempt_writeback() on 64K pagesize system
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (5 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 6/8] selftest/cgroup: fix zswap test_no_invasive_cgroup_shrink on large pagesize system Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 3:26 ` [PATCH v5 8/8] selftests/cgroup: test_zswap: wait for asynchronous writeback Li Wang
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm
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 systems.
- Setting zswap.max to zswap_usage/4 instead of zswap_usage/2 to
create stronger writeback pressure, ensuring reclaim reliably
triggers writeback even on large 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:
v5:
- Setting zswap.max to zswap_usage/4 to create stronger writeback pressure.
v3-4:
- No changes.
v2:
- use pagesize * 1024 which clearly shows the page numbers.
tools/testing/selftests/cgroup/test_zswap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index 72082e5d4725..e96e316f7c47 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -273,7 +273,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 = page_size * 1024;
char buf[page_size];
long zswap_usage;
bool wb_enabled = *(bool *) arg;
@@ -311,7 +311,7 @@ static int attempt_writeback(const char *cgroup, void *arg)
}
}
- if (cg_write_numeric(cgroup, "memory.zswap.max", zswap_usage/2))
+ if (cg_write_numeric(cgroup, "memory.zswap.max", zswap_usage/4))
goto out;
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v5 8/8] selftests/cgroup: test_zswap: wait for asynchronous writeback
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (6 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 7/8] selftest/cgroup: fix zswap attempt_writeback() on 64K " Li Wang
@ 2026-03-26 3:26 ` Li Wang
2026-03-26 6:29 ` [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
2026-03-26 23:01 ` Andrew Morton
9 siblings, 0 replies; 13+ messages in thread
From: Li Wang @ 2026-03-26 3:26 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, liwang, linux-kselftest, linux-kernel, linux-mm,
Yosry Ahmed
zswap writeback is asynchronous, but test_zswap.c checks writeback
counters immediately after reclaim/trigger paths. On some platforms
(e.g. ppc64le), this can race with background writeback and cause
spurious failures even when behavior is correct.
Add wait_for_writeback() to poll get_cg_wb_count() with a bounded
timeout, and use it in:
test_zswap_writeback_one() when writeback is expected
test_no_invasive_cgroup_shrink() for the wb_group check
This keeps the original before/after assertion style while making the
tests robust against writeback completion latency.
No test behavior change, selftest stability improvement only.
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 | 28 +++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
index e96e316f7c47..e7d5dbc1ef7f 100644
--- a/tools/testing/selftests/cgroup/test_zswap.c
+++ b/tools/testing/selftests/cgroup/test_zswap.c
@@ -118,6 +118,27 @@ static char *setup_test_group_1M(const char *root, const char *name)
return NULL;
}
+/*
+ * Writeback is asynchronous; poll until at least one writeback has
+ * been recorded for @cg, or until @timeout_ms has elapsed.
+ */
+static long wait_for_writeback(const char *cg, int timeout_ms)
+{
+ int elapsed, count;
+ for (elapsed = 0; elapsed < timeout_ms; elapsed += 100) {
+ count = get_cg_wb_count(cg);
+
+ if (count < 0)
+ return -1;
+ if (count > 0)
+ return count;
+
+ usleep(100000);
+ }
+
+ return 0;
+}
+
/*
* Sanity test to check that pages are written into zswap.
*/
@@ -343,7 +364,10 @@ static int test_zswap_writeback_one(const char *cgroup, bool wb)
return -1;
/* Verify that zswap writeback occurred only if writeback was enabled */
- zswpwb_after = get_cg_wb_count(cgroup);
+ if (wb)
+ zswpwb_after = wait_for_writeback(cgroup, 5000);
+ else
+ zswpwb_after = get_cg_wb_count(cgroup);
if (zswpwb_after < 0)
return -1;
@@ -473,7 +497,7 @@ static int test_no_invasive_cgroup_shrink(const char *root)
}
/* Verify that only zswapped memory from gwb_group has been written back */
- if (get_cg_wb_count(wb_group) > 0 && get_cg_wb_count(zw_group) == 0)
+ if (wait_for_writeback(wb_group, 5000) > 0 && get_cg_wb_count(zw_group) == 0)
ret = KSFT_PASS;
out:
cg_enter_current(root);
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (7 preceding siblings ...)
2026-03-26 3:26 ` [PATCH v5 8/8] selftests/cgroup: test_zswap: wait for asynchronous writeback Li Wang
@ 2026-03-26 6:29 ` Li Wang
2026-03-26 23:06 ` Andrew Morton
2026-03-26 23:01 ` Andrew Morton
9 siblings, 1 reply; 13+ messages in thread
From: Li Wang @ 2026-03-26 6:29 UTC (permalink / raw)
To: akpm, yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt
Cc: longman, linux-kselftest, linux-kernel, linux-mm
On Thu, Mar 26, 2026 at 11:26:50AM +0800, Li Wang wrote:
> This patchset aims to fix various spurious failures and improve the overall
> robustness of the cgroup zswap selftests.
>
> The primary motivation is to make the tests compatible with architectures
> that use non-4K page sizes (such as 64K on ppc64le and arm64). Currently,
> the tests rely heavily on hardcoded 4K page sizes and fixed memory limits.
> On 64K page size systems, these hardcoded values lead to sub-page granularity
> accesses, incorrect page count calculations, and insufficient memory pressure
> to trigger zswap writeback, ultimately causing the tests to fail.
>
> Additionally, this series addresses OOM kills occurring in test_swapin_nozswap
> by dynamically scaling memory limits, and prevents spurious test failures
> when zswap is built into the kernel but globally disabled.
>
> Changes in v5:
> Patch 1/8: Defined PATH_ZSWAP and PATH_ZSWAP_ENABLED macros.
> Patch 4/8: Merge Waiman's work into this patch (use page_size).
> Patch 5/8: Change pagesize by the global page_size.
> Patch 6/8: Swap data patterns: use getrandom() for wb_group and simple
> memset for zw_group to fix the reversed allocation logic.
> Patch 7/8: Setting zswap.max to zswap_usage/4 to increase writeback pressure.
> Patch 8/8: New added. Just add loops for read zswpwb more times.
>
> Test all passed on:
> x86_64(4k), aarch64(4K, 64K), ppc64le(64K).
Hi Andrew, All,
I see that Sashiko still points out minor issues in this patchset,
That seems very tiny in selftest programming.
I can correct all that in a new version if you'd like a perfect patchset.
Sashiko comments:
https://sashiko.dev/#/patchset/20260326032658.96819-1-liwang%40redhat.com
--
Regards,
Li Wang
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes
2026-03-26 6:29 ` [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
@ 2026-03-26 23:06 ` Andrew Morton
2026-03-26 23:10 ` Yosry Ahmed
0 siblings, 1 reply; 13+ messages in thread
From: Andrew Morton @ 2026-03-26 23:06 UTC (permalink / raw)
To: Li Wang
Cc: yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt, longman, linux-kselftest,
linux-kernel, linux-mm
On Thu, 26 Mar 2026 14:29:20 +0800 Li Wang <liwang@redhat.com> wrote:
> > Test all passed on:
> > x86_64(4k), aarch64(4K, 64K), ppc64le(64K).
>
> Hi Andrew, All,
>
> I see that Sashiko still points out minor issues in this patchset,
> That seems very tiny in selftest programming.
>
> I can correct all that in a new version if you'd like a perfect patchset.
>
> Sashiko comments:
> https://sashiko.dev/#/patchset/20260326032658.96819-1-liwang%40redhat.com
Ah, OK, you already looked.
If you say they're too minor then I'm OK with that. If there are any
you feel you'd like to address then go for it. That's my opinion,
others might differ!
I suggest you leave things as-is for a while (a week?), give the memcg
maintainers time to take a look (please).
Thanks.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes
2026-03-26 23:06 ` Andrew Morton
@ 2026-03-26 23:10 ` Yosry Ahmed
0 siblings, 0 replies; 13+ messages in thread
From: Yosry Ahmed @ 2026-03-26 23:10 UTC (permalink / raw)
To: Andrew Morton
Cc: Li Wang, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt, longman, linux-kselftest,
linux-kernel, linux-mm
On Thu, Mar 26, 2026 at 4:06 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu, 26 Mar 2026 14:29:20 +0800 Li Wang <liwang@redhat.com> wrote:
>
> > > Test all passed on:
> > > x86_64(4k), aarch64(4K, 64K), ppc64le(64K).
> >
> > Hi Andrew, All,
> >
> > I see that Sashiko still points out minor issues in this patchset,
> > That seems very tiny in selftest programming.
> >
> > I can correct all that in a new version if you'd like a perfect patchset.
> >
> > Sashiko comments:
> > https://sashiko.dev/#/patchset/20260326032658.96819-1-liwang%40redhat.com
>
> Ah, OK, you already looked.
>
> If you say they're too minor then I'm OK with that. If there are any
> you feel you'd like to address then go for it. That's my opinion,
> others might differ!
>
> I suggest you leave things as-is for a while (a week?), give the memcg
> maintainers time to take a look (please).
I think some of the comments are worth addressing, especially:
Patch 4:
Using BUF_SIZE in the allocation helpers is wrong, we should use the
actual page size.
Patch 6:
Zero initialization of zw_allocation.
But yeah as Andrew said, it may be worth waiting for memcg maintainers
to take a look before sending a new version.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes
2026-03-26 3:26 [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
` (8 preceding siblings ...)
2026-03-26 6:29 ` [PATCH v5 0/8] selftests/cgroup: improve zswap tests robustness and support large page sizes Li Wang
@ 2026-03-26 23:01 ` Andrew Morton
9 siblings, 0 replies; 13+ messages in thread
From: Andrew Morton @ 2026-03-26 23:01 UTC (permalink / raw)
To: Li Wang
Cc: yosry, nphamcs, hannes, mhocko, mkoutny, muchun.song, tj,
roman.gushchin, shakeel.butt, longman, linux-kselftest,
linux-kernel, linux-mm
On Thu, 26 Mar 2026 11:26:50 +0800 Li Wang <liwang@redhat.com> wrote:
> This patchset aims to fix various spurious failures and improve the overall
> robustness of the cgroup zswap selftests.
>
> The primary motivation is to make the tests compatible with architectures
> that use non-4K page sizes (such as 64K on ppc64le and arm64). Currently,
> the tests rely heavily on hardcoded 4K page sizes and fixed memory limits.
> On 64K page size systems, these hardcoded values lead to sub-page granularity
> accesses, incorrect page count calculations, and insufficient memory pressure
> to trigger zswap writeback, ultimately causing the tests to fail.
>
> Additionally, this series addresses OOM kills occurring in test_swapin_nozswap
> by dynamically scaling memory limits, and prevents spurious test failures
> when zswap is built into the kernel but globally disabled.
Thanks. AI review flagged a few potential issues.
https://sashiko.dev/#/patchset/20260326032658.96819-1-liwang%40redhat.com
Please take a look - I'm interested in learning how may of these you
feel are worth addressing.
The sysconf retval one is real, pretty minor.
I'd be inclined to ignore the unchecked-malloc-return one. It's
userspace, it's selftests. If a malloc() fails then gee, fix your
machine and run it again.
Plese understand that I'm serious trying to slow things down now
(https://lkml.kernel.org/r/20260323202941.08ddf2b0411501cae801ab4c@linux-foundation.org).
Maybe we can weasel out of that for selftests but I'd rather not.
That means post-7.1-r1 for this patchset, so please plan to resend at
that time.
If memcg maintainers decide that this material should target the
upcoming merge window then OK,
^ permalink raw reply [flat|nested] 13+ messages in thread