kselftests: cgroup: add perpcu memory accounting test
Add a simple test to check the percpu memory accounting. The test creates a cgroup tree with 1000 child cgroups and checks values of memory.current and memory.stat::percpu. Signed-off-by: Roman Gushchin <guro@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: Dennis Zhou <dennis@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Michal Hocko <mhocko@kernel.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: Shakeel Butt <shakeelb@google.com> Cc: Tejun Heo <tj@kernel.org> Cc: Tobin C. Harding <tobin@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Waiman Long <longman@redhat.com> Cc: Michal Koutný <mkoutny@suse.com> Cc: Bixuan Cui <cuibixuan@huawei.com> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Link: http://lkml.kernel.org/r/20200608230819.832349-6-guro@fb.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
3e38e0aaca
Коммит
90631e1dea
|
@ -18,6 +18,15 @@
|
|||
#include "cgroup_util.h"
|
||||
|
||||
|
||||
/*
|
||||
* Memory cgroup charging and vmstat data aggregation is performed using
|
||||
* percpu batches 32 pages big (look at MEMCG_CHARGE_BATCH). So the maximum
|
||||
* discrepancy between charge and vmstat entries is number of cpus multiplied
|
||||
* by 32 pages multiplied by 2.
|
||||
*/
|
||||
#define MAX_VMSTAT_ERROR (4096 * 32 * 2 * get_nprocs())
|
||||
|
||||
|
||||
static int alloc_dcache(const char *cgroup, void *arg)
|
||||
{
|
||||
unsigned long i;
|
||||
|
@ -180,7 +189,7 @@ static int test_kmem_memcg_deletion(const char *root)
|
|||
goto cleanup;
|
||||
|
||||
sum = slab + anon + file + kernel_stack;
|
||||
if (abs(sum - current) < 4096 * 32 * 2 * get_nprocs()) {
|
||||
if (abs(sum - current) < MAX_VMSTAT_ERROR) {
|
||||
ret = KSFT_PASS;
|
||||
} else {
|
||||
printf("memory.current = %ld\n", current);
|
||||
|
@ -331,6 +340,64 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test creates a sub-tree with 1000 memory cgroups.
|
||||
* Then it checks that the memory.current on the parent level
|
||||
* is greater than 0 and approximates matches the percpu value
|
||||
* from memory.stat.
|
||||
*/
|
||||
static int test_percpu_basic(const char *root)
|
||||
{
|
||||
int ret = KSFT_FAIL;
|
||||
char *parent, *child;
|
||||
long current, percpu;
|
||||
int i;
|
||||
|
||||
parent = cg_name(root, "percpu_basic_test");
|
||||
if (!parent)
|
||||
goto cleanup;
|
||||
|
||||
if (cg_create(parent))
|
||||
goto cleanup;
|
||||
|
||||
if (cg_write(parent, "cgroup.subtree_control", "+memory"))
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
child = cg_name_indexed(parent, "child", i);
|
||||
if (!child)
|
||||
return -1;
|
||||
|
||||
if (cg_create(child))
|
||||
goto cleanup_children;
|
||||
|
||||
free(child);
|
||||
}
|
||||
|
||||
current = cg_read_long(parent, "memory.current");
|
||||
percpu = cg_read_key_long(parent, "memory.stat", "percpu ");
|
||||
|
||||
if (current > 0 && percpu > 0 && abs(current - percpu) <
|
||||
MAX_VMSTAT_ERROR)
|
||||
ret = KSFT_PASS;
|
||||
else
|
||||
printf("memory.current %ld\npercpu %ld\n",
|
||||
current, percpu);
|
||||
|
||||
cleanup_children:
|
||||
for (i = 0; i < 1000; i++) {
|
||||
child = cg_name_indexed(parent, "child", i);
|
||||
cg_destroy(child);
|
||||
free(child);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cg_destroy(parent);
|
||||
free(parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define T(x) { x, #x }
|
||||
struct kmem_test {
|
||||
int (*fn)(const char *root);
|
||||
|
@ -341,6 +408,7 @@ struct kmem_test {
|
|||
T(test_kmem_proc_kpagecgroup),
|
||||
T(test_kmem_kernel_stacks),
|
||||
T(test_kmem_dead_cgroups),
|
||||
T(test_percpu_basic),
|
||||
};
|
||||
#undef T
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче