memcg: use generic slab iterators for showing slabinfo
authorVladimir Davydov <vdavydov@parallels.com>
Wed, 10 Dec 2014 23:44:19 +0000 (15:44 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 Dec 2014 01:41:07 +0000 (17:41 -0800)
Let's use generic slab_start/next/stop for showing memcg caches info.  In
contrast to the current implementation, this will work even if all memcg
caches' info doesn't fit into a seq buffer (a page), plus it simply looks
neater.

Actually, the main reason I do this isn't mere cleanup.  I'm going to zap
the memcg_slab_caches list, because I find it useless provided we have the
slab_caches list, and this patch is a step in this direction.

It should be noted that before this patch an attempt to read
memory.kmem.slabinfo of a cgroup that doesn't have kmem limit set resulted
in -EIO, while after this patch it will silently show nothing except the
header, but I don't think it will frustrate anyone.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
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>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/slab.h
mm/memcontrol.c
mm/slab.h
mm/slab_common.c

index c265bec..8a2457d 100644 (file)
@@ -513,10 +513,6 @@ struct memcg_cache_params {
 
 int memcg_update_all_caches(int num_memcgs);
 
-struct seq_file;
-int cache_show(struct kmem_cache *s, struct seq_file *m);
-void print_slabinfo_header(struct seq_file *m);
-
 /**
  * kmalloc_array - allocate memory for an array.
  * @n: number of elements.
index 32e3b19..9d30129 100644 (file)
@@ -2547,26 +2547,6 @@ static struct kmem_cache *memcg_params_to_cache(struct memcg_cache_params *p)
        return cache_from_memcg_idx(cachep, memcg_cache_id(p->memcg));
 }
 
-#ifdef CONFIG_SLABINFO
-static int mem_cgroup_slabinfo_read(struct seq_file *m, void *v)
-{
-       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
-       struct memcg_cache_params *params;
-
-       if (!memcg_kmem_is_active(memcg))
-               return -EIO;
-
-       print_slabinfo_header(m);
-
-       mutex_lock(&memcg_slab_mutex);
-       list_for_each_entry(params, &memcg->memcg_slab_caches, list)
-               cache_show(memcg_params_to_cache(params), m);
-       mutex_unlock(&memcg_slab_mutex);
-
-       return 0;
-}
-#endif
-
 static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp,
                             unsigned long nr_pages)
 {
@@ -4708,7 +4688,10 @@ static struct cftype mem_cgroup_files[] = {
 #ifdef CONFIG_SLABINFO
        {
                .name = "kmem.slabinfo",
-               .seq_show = mem_cgroup_slabinfo_read,
+               .seq_start = slab_start,
+               .seq_next = slab_next,
+               .seq_stop = slab_stop,
+               .seq_show = memcg_slab_show,
        },
 #endif
 #endif
index 078acbc..1cf4005 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -360,5 +360,6 @@ static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node)
 void *slab_start(struct seq_file *m, loff_t *pos);
 void *slab_next(struct seq_file *m, void *p, loff_t *pos);
 void slab_stop(struct seq_file *m, void *p);
+int memcg_slab_show(struct seq_file *m, void *p);
 
 #endif /* MM_SLAB_H */
index 2a3f5ff..e03dd6f 100644 (file)
@@ -811,7 +811,7 @@ EXPORT_SYMBOL(kmalloc_order_trace);
 #define SLABINFO_RIGHTS S_IRUSR
 #endif
 
-void print_slabinfo_header(struct seq_file *m)
+static void print_slabinfo_header(struct seq_file *m)
 {
        /*
         * Output format version, so at least we can change it
@@ -876,7 +876,7 @@ memcg_accumulate_slabinfo(struct kmem_cache *s, struct slabinfo *info)
        }
 }
 
-int cache_show(struct kmem_cache *s, struct seq_file *m)
+static void cache_show(struct kmem_cache *s, struct seq_file *m)
 {
        struct slabinfo sinfo;
 
@@ -895,7 +895,6 @@ int cache_show(struct kmem_cache *s, struct seq_file *m)
                   sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail);
        slabinfo_show_stats(m, s);
        seq_putc(m, '\n');
-       return 0;
 }
 
 static int slab_show(struct seq_file *m, void *p)
@@ -904,10 +903,24 @@ static int slab_show(struct seq_file *m, void *p)
 
        if (p == slab_caches.next)
                print_slabinfo_header(m);
-       if (!is_root_cache(s))
-               return 0;
-       return cache_show(s, m);
+       if (is_root_cache(s))
+               cache_show(s, m);
+       return 0;
+}
+
+#ifdef CONFIG_MEMCG_KMEM
+int memcg_slab_show(struct seq_file *m, void *p)
+{
+       struct kmem_cache *s = list_entry(p, struct kmem_cache, list);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+       if (p == slab_caches.next)
+               print_slabinfo_header(m);
+       if (!is_root_cache(s) && s->memcg_params->memcg == memcg)
+               cache_show(s, m);
+       return 0;
 }
+#endif
 
 /*
  * slabinfo_op - iterator that generates /proc/slabinfo