test_percpu_basic() currently compares memory.current against only
memory.stat:percpu after creating 1000 child cgroups.

Observed failure:
  #./test_kmem
  ok 1 test_kmem_basic
  ok 2 test_kmem_memcg_deletion
  ok 3 test_kmem_proc_kpagecgroup
  ok 4 test_kmem_kernel_stacks
  ok 5 test_kmem_dead_cgroups
  memory.current 11530240
  percpu 8440000
  not ok 6 test_percpu_basic

That assumption is too strict: child cgroup creation also allocates
slab-backed metadata, so memory.current is expected to be larger than
percpu alone. One visible path is:

  cgroup_mkdir()
    cgroup_create()
      cgroup_addrm_file()
        cgroup_add_file()
          __kernfs_create_file()
            __kernfs_new_node()
              kmem_cache_zalloc()

These kernfs allocations are charged as slab and show up in
memory.stat:slab.

Update the check to compare memory.current against (percpu + slab)
within MAX_VMSTAT_ERROR, and print slab/delta in the failure message to
improve diagnostics.

Signed-off-by: Li Wang <[email protected]>
Cc: Waiman Long <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Shakeel Butt <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: Vlastimil Babka <[email protected]>
---
 tools/testing/selftests/cgroup/test_kmem.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_kmem.c 
b/tools/testing/selftests/cgroup/test_kmem.c
index 249d79113067..4b5799698893 100644
--- a/tools/testing/selftests/cgroup/test_kmem.c
+++ b/tools/testing/selftests/cgroup/test_kmem.c
@@ -353,7 +353,7 @@ static int test_percpu_basic(const char *root)
 {
        int ret = KSFT_FAIL;
        char *parent, *child;
-       long current, percpu;
+       long current, percpu, slab;
        int i;
 
        parent = cg_name(root, "percpu_basic_test");
@@ -379,13 +379,14 @@ static int test_percpu_basic(const char *root)
 
        current = cg_read_long(parent, "memory.current");
        percpu = cg_read_key_long(parent, "memory.stat", "percpu ");
+       slab = cg_read_key_long(parent, "memory.stat", "slab ");
 
-       if (current > 0 && percpu > 0 && labs(current - percpu) <
-           MAX_VMSTAT_ERROR)
+       if (current > 0 && percpu > 0 && slab >= 0 &&
+                       labs(current - (percpu + slab)) < MAX_VMSTAT_ERROR)
                ret = KSFT_PASS;
        else
-               printf("memory.current %ld\npercpu %ld\n",
-                      current, percpu);
+               printf("memory.current %ld\npercpu %ld\nslab %ld\ndelta %ld\n",
+                       current, percpu, slab, current - (percpu + slab));
 
 cleanup_children:
        for (i = 0; i < 1000; i++) {
-- 
2.53.0


Reply via email to