selftests: cgroup: add a selftest for memory.reclaim
Add a new test for memory.reclaim that verifies that the interface correctly reclaims memory as intended, from both anon and file pages. Link: https://lkml.kernel.org/r/20220425190040.2475377-5-yosryahmed@google.com Signed-off-by: Yosry Ahmed <yosryahmed@google.com> Acked-by: Roman Gushchin <roman.gushchin@linux.dev> Acked-by: David Rientjes <rientjes@google.com> Cc: Chen Wandun <chenwandun@huawei.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Greg Thelen <gthelen@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Michal Hocko <mhocko@suse.com> Cc: "Michal Koutn" <mkoutny@suse.com> Cc: Shakeel Butt <shakeelb@google.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Tejun Heo <tj@kernel.org> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Vaibhav Jain <vaibhav@linux.ibm.com> Cc: Wei Xu <weixugc@google.com> Cc: Yu Zhao <yuzhao@google.com> Cc: Zefan Li <lizefan.x@bytedance.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Родитель
a3622a53e6
Коммит
eae3cb2e87
|
@ -760,6 +760,111 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test checks that memory.reclaim reclaims the given
|
||||
* amount of memory (from both anon and file, if possible).
|
||||
*/
|
||||
static int test_memcg_reclaim(const char *root)
|
||||
{
|
||||
int ret = KSFT_FAIL, fd, retries;
|
||||
char *memcg;
|
||||
long current, expected_usage, to_reclaim;
|
||||
char buf[64];
|
||||
|
||||
memcg = cg_name(root, "memcg_test");
|
||||
if (!memcg)
|
||||
goto cleanup;
|
||||
|
||||
if (cg_create(memcg))
|
||||
goto cleanup;
|
||||
|
||||
current = cg_read_long(memcg, "memory.current");
|
||||
if (current != 0)
|
||||
goto cleanup;
|
||||
|
||||
fd = get_temp_fd();
|
||||
if (fd < 0)
|
||||
goto cleanup;
|
||||
|
||||
cg_run_nowait(memcg, alloc_pagecache_50M_noexit, (void *)(long)fd);
|
||||
|
||||
/*
|
||||
* If swap is enabled, try to reclaim from both anon and file, else try
|
||||
* to reclaim from file only.
|
||||
*/
|
||||
if (is_swap_enabled()) {
|
||||
cg_run_nowait(memcg, alloc_anon_noexit, (void *) MB(50));
|
||||
expected_usage = MB(100);
|
||||
} else
|
||||
expected_usage = MB(50);
|
||||
|
||||
/*
|
||||
* Wait until current usage reaches the expected usage (or we run out of
|
||||
* retries).
|
||||
*/
|
||||
retries = 5;
|
||||
while (!values_close(cg_read_long(memcg, "memory.current"),
|
||||
expected_usage, 10)) {
|
||||
if (retries--) {
|
||||
sleep(1);
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"failed to allocate %ld for memcg reclaim test\n",
|
||||
expected_usage);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim until current reaches 30M, this makes sure we hit both anon
|
||||
* and file if swap is enabled.
|
||||
*/
|
||||
retries = 5;
|
||||
while (true) {
|
||||
int err;
|
||||
|
||||
current = cg_read_long(memcg, "memory.current");
|
||||
to_reclaim = current - MB(30);
|
||||
|
||||
/*
|
||||
* We only keep looping if we get EAGAIN, which means we could
|
||||
* not reclaim the full amount.
|
||||
*/
|
||||
if (to_reclaim <= 0)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
snprintf(buf, sizeof(buf), "%ld", to_reclaim);
|
||||
err = cg_write(memcg, "memory.reclaim", buf);
|
||||
if (!err) {
|
||||
/*
|
||||
* If writing succeeds, then the written amount should have been
|
||||
* fully reclaimed (and maybe more).
|
||||
*/
|
||||
current = cg_read_long(memcg, "memory.current");
|
||||
if (!values_close(current, MB(30), 3) && current > MB(30))
|
||||
goto cleanup;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The kernel could not reclaim the full amount, try again. */
|
||||
if (err == -EAGAIN && retries--)
|
||||
continue;
|
||||
|
||||
/* We got an unexpected error or ran out of retries. */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = KSFT_PASS;
|
||||
cleanup:
|
||||
cg_destroy(memcg);
|
||||
free(memcg);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int alloc_anon_50M_check_swap(const char *cgroup, void *arg)
|
||||
{
|
||||
long mem_max = (long)arg;
|
||||
|
@ -1264,6 +1369,7 @@ struct memcg_test {
|
|||
T(test_memcg_high),
|
||||
T(test_memcg_high_sync),
|
||||
T(test_memcg_max),
|
||||
T(test_memcg_reclaim),
|
||||
T(test_memcg_oom_events),
|
||||
T(test_memcg_swap_max),
|
||||
T(test_memcg_sock),
|
||||
|
|
Загрузка…
Ссылка в новой задаче