mm/slab.c: fix an infinite loop in leaks_show()
authorQian Cai <cai@lca.pw>
Tue, 14 May 2019 00:16:31 +0000 (17:16 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 15 Jun 2019 09:54:51 +0000 (11:54 +0200)
[ Upstream commit 745e10146c31b1c6ed3326286704ae251b17f663 ]

"cat /proc/slab_allocators" could hang forever on SMP machines with
kmemleak or object debugging enabled due to other CPUs running do_drain()
will keep making kmemleak_object or debug_objects_cache dirty and unable
to escape the first loop in leaks_show(),

do {
set_store_user_clean(cachep);
drain_cpu_caches(cachep);
...

} while (!is_store_user_clean(cachep));

For example,

do_drain
  slabs_destroy
    slab_destroy
      kmem_cache_free
        __cache_free
          ___cache_free
            kmemleak_free_recursive
              delete_object_full
                __delete_object
                  put_object
                    free_object_rcu
                      kmem_cache_free
                        cache_free_debugcheck --> dirty kmemleak_object

One approach is to check cachep->name and skip both kmemleak_object and
debug_objects_cache in leaks_show().  The other is to set store_user_clean
after drain_cpu_caches() which leaves a small window between
drain_cpu_caches() and set_store_user_clean() where per-CPU caches could
be dirty again lead to slightly wrong information has been stored but
could also speed up things significantly which sounds like a good
compromise.  For example,

 # cat /proc/slab_allocators
 0m42.778s # 1st approach
 0m0.737s  # 2nd approach

[akpm@linux-foundation.org: tweak comment]
Link: http://lkml.kernel.org/r/20190411032635.10325-1-cai@lca.pw
Fixes: d31676dfde25 ("mm/slab: alternative implementation for DEBUG_SLAB_LEAK")
Signed-off-by: Qian Cai <cai@lca.pw>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
mm/slab.c

index 843ecea9e336b4b8315194cf9847ad824a106d30..a04aeae4230622c3eb7fc02892f7257e87cfeb93 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4320,8 +4320,12 @@ static int leaks_show(struct seq_file *m, void *p)
         * whole processing.
         */
        do {
-               set_store_user_clean(cachep);
                drain_cpu_caches(cachep);
+               /*
+                * drain_cpu_caches() could make kmemleak_object and
+                * debug_objects_cache dirty, so reset afterwards.
+                */
+               set_store_user_clean(cachep);
 
                x[1] = 0;