diff --git a/tools/cgroup/slabinfo.py b/tools/cgroup/slabinfo.py
index 40b01a6ec4b0..79909ee36fe3 100755
--- a/tools/cgroup/slabinfo.py
+++ b/tools/cgroup/slabinfo.py
@@ -8,7 +8,10 @@ import argparse
 import sys
 
 from drgn.helpers.linux import list_for_each_entry, list_empty
-from drgn import container_of
+from drgn.helpers.linux import for_each_page
+from drgn.helpers.linux.cpumask import for_each_online_cpu
+from drgn.helpers.linux.percpu import per_cpu_ptr
+from drgn import container_of, FaultError
 
 
 DESC = """
@@ -47,7 +50,7 @@ def is_root_cache(s):
 
 def cache_name(s):
     if is_root_cache(s):
-        return s.name
+        return s.name.string_().decode('utf-8')
     else:
         return s.memcg_params.root_cache.name.string_().decode('utf-8')
 
@@ -99,12 +102,16 @@ def slub_get_slabinfo(s, cfg):
 # SLAB-specific functions can be added here...
 
 
-def cache_show(s, cfg):
+def cache_show(s, cfg, objs):
     if cfg['allocator'] == 'SLUB':
         sinfo = slub_get_slabinfo(s, cfg)
     else:
         err('SLAB isn\'t supported yet')
 
+    if cfg['shared_slab_pages']:
+        sinfo['active_objs'] = objs
+        sinfo['num_objs'] = objs
+
     print('%-17s %6lu %6lu %6u %4u %4d'
           ' : tunables %4u %4u %4u'
           ' : slabdata %6lu %6lu %6lu' % (
@@ -127,9 +134,60 @@ def detect_kernel_config():
     else:
         err('Can\'t determine the slab allocator')
 
+    if prog.type('struct memcg_cache_params').members[1][1] == 'memcg_cache':
+        cfg['shared_slab_pages'] = True
+    else:
+        cfg['shared_slab_pages'] = False
+
     return cfg
 
 
+def for_each_slab_page(prog):
+    PGSlab = 1 << prog.constant('PG_slab')
+    PGHead = 1 << prog.constant('PG_head')
+
+    for page in for_each_page(prog):
+        try:
+            if page.flags.value_() & PGSlab:
+                yield page
+        except FaultError:
+            pass
+
+
+# it doesn't find all objects, because by default full slabs are not
+# placed to the full list. however, it can be used in certain cases.
+def for_each_slab_page_fast(prog):
+    for s in list_for_each_entry('struct kmem_cache',
+                                 prog['slab_caches'].address_of_(),
+                                 'list'):
+        if is_root_cache(s):
+            continue
+
+        if s.cpu_partial:
+            for cpu in for_each_online_cpu(prog):
+                cpu_slab = per_cpu_ptr(s.cpu_slab, cpu)
+                if cpu_slab.page:
+                    yield cpu_slab.page
+
+                page = cpu_slab.partial
+                while page:
+                    yield page
+                    page = page.next
+
+        for node in range(prog['nr_online_nodes'].value_()):
+            n = s.node[node]
+
+            for page in list_for_each_entry('struct page',
+                                            n.partial.address_of_(),
+                                            'slab_list'):
+                yield page
+
+            for page in list_for_each_entry('struct page',
+                                            n.full.address_of_(),
+                                            'slab_list'):
+                yield page
+
+
 def main():
     parser = argparse.ArgumentParser(description=DESC,
                                      formatter_class=argparse.RawTextHelpFormatter)
@@ -150,10 +208,43 @@ def main():
           ' : tunables <limit> <batchcount> <sharedfactor>'
           ' : slabdata <active_slabs> <num_slabs> <sharedavail>')
 
-    for s in list_for_each_entry('struct kmem_cache',
-                                 memcg.kmem_caches.address_of_(),
-                                 'memcg_params.kmem_caches_node'):
-        cache_show(s, cfg)
+    if cfg['shared_slab_pages']:
+        memcg_ptrs = set()
+        stats = {}
+        caches = {}
+
+        # find memcg pointers belonging to the specified cgroup
+        for ptr in list_for_each_entry('struct mem_cgroup_ptr',
+                                       memcg.kmem_memcg_ptr_list.address_of_(),
+                                       'list'):
+            memcg_ptrs.add(ptr.value_())
+
+        # look over all slab pages, belonging to non-root memcgs
+        # and look for objects belonging to the given memory cgroup
+        for page in for_each_slab_page(prog):
+            cache = page.slab_cache
+            if not cache or is_root_cache(cache):
+                continue
+            addr = cache.value_()
+            caches[addr] = cache
+            memcg_vec = page.mem_cgroup_vec
+
+            if addr not in stats:
+                stats[addr] = 0
+
+            for i in range(oo_objects(cache)):
+                if memcg_vec[i].value_() in memcg_ptrs:
+                    stats[addr] += 1
+
+        for addr in caches:
+            if stats[addr] > 0:
+                cache_show(caches[addr], cfg, stats[addr])
+
+    else:
+        for s in list_for_each_entry('struct kmem_cache',
+                                     memcg.kmem_caches.address_of_(),
+                                     'memcg_params.kmem_caches_node'):
+            cache_show(s, cfg, None)
 
 
 main()
