Skip to content

Commit 6479b29

Browse files
nhatsmrtakpm00
authored andcommitted
selftests: add a sanity check for zswap
We recently encountered a bug that makes all zswap store attempt fail. Specifically, after: "141fdeececb3 mm/zswap: delay the initialization of zswap" if we build a kernel with zswap disabled by default, then enabled after the swapfile is set up, the zswap tree will not be initialized. As a result, all zswap store calls will be short-circuited. We have to perform another swapon to get zswap working properly again. Fortunately, this issue has since been fixed by the patch that kills frontswap: "42c06a0e8ebe mm: kill frontswap" which performs zswap_swapon() unconditionally, i.e always initializing the zswap tree. This test add a sanity check that ensure zswap storing works as intended. Link: https://lkml.kernel.org/r/20231020222009.2358953-1-nphamcs@gmail.com Signed-off-by: Nhat Pham <nphamcs@gmail.com> Acked-by: Rik van Riel <riel@surriel.com> Cc: Domenico Cerasuolo <cerasuolodomenico@gmail.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Tejun Heo <tj@kernel.org> Cc: Zefan Li <lizefan.x@bytedance.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 9e1b016 commit 6479b29

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

tools/testing/selftests/cgroup/test_zswap.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ static int get_zswap_written_back_pages(size_t *value)
5555
return read_int("/sys/kernel/debug/zswap/written_back_pages", value);
5656
}
5757

58+
static long get_zswpout(const char *cgroup)
59+
{
60+
return cg_read_key_long(cgroup, "memory.stat", "zswpout ");
61+
}
62+
5863
static int allocate_bytes(const char *cgroup, void *arg)
5964
{
6065
size_t size = (size_t)arg;
@@ -68,6 +73,48 @@ static int allocate_bytes(const char *cgroup, void *arg)
6873
return 0;
6974
}
7075

76+
/*
77+
* Sanity test to check that pages are written into zswap.
78+
*/
79+
static int test_zswap_usage(const char *root)
80+
{
81+
long zswpout_before, zswpout_after;
82+
int ret = KSFT_FAIL;
83+
char *test_group;
84+
85+
/* Set up */
86+
test_group = cg_name(root, "no_shrink_test");
87+
if (!test_group)
88+
goto out;
89+
if (cg_create(test_group))
90+
goto out;
91+
if (cg_write(test_group, "memory.max", "1M"))
92+
goto out;
93+
94+
zswpout_before = get_zswpout(test_group);
95+
if (zswpout_before < 0) {
96+
ksft_print_msg("Failed to get zswpout\n");
97+
goto out;
98+
}
99+
100+
/* Allocate more than memory.max to push memory into zswap */
101+
if (cg_run(test_group, allocate_bytes, (void *)MB(4)))
102+
goto out;
103+
104+
/* Verify that pages come into zswap */
105+
zswpout_after = get_zswpout(test_group);
106+
if (zswpout_after <= zswpout_before) {
107+
ksft_print_msg("zswpout does not increase after test program\n");
108+
goto out;
109+
}
110+
ret = KSFT_PASS;
111+
112+
out:
113+
cg_destroy(test_group);
114+
free(test_group);
115+
return ret;
116+
}
117+
71118
/*
72119
* When trying to store a memcg page in zswap, if the memcg hits its memory
73120
* limit in zswap, writeback should not be triggered.
@@ -235,6 +282,7 @@ struct zswap_test {
235282
int (*fn)(const char *root);
236283
const char *name;
237284
} tests[] = {
285+
T(test_zswap_usage),
238286
T(test_no_kmem_bypass),
239287
T(test_no_invasive_cgroup_shrink),
240288
};

0 commit comments

Comments
 (0)