Basically, we substitute the reference to the owner memory cgroup in
memcg_cache_params with the index in the memcg_caches array. This
decouples kmem cache from the memcg it was created for and will allow to
reuse it for another cgroup after css offline.

Signed-off-by: Vladimir Davydov <vdavy...@parallels.com>
---
 include/linux/slab.h |    7 +++----
 mm/memcontrol.c      |   18 +++++-------------
 mm/slab_common.c     |   12 +++++-------
 3 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 390341d30b2d..293c04df7953 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -117,8 +117,7 @@ struct kmem_cache *kmem_cache_create(const char *, size_t, 
size_t,
                        void (*)(void *));
 #ifdef CONFIG_MEMCG_KMEM
 struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *,
-                                          struct kmem_cache *,
-                                          const char *);
+                                          struct kmem_cache *);
 #endif
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
@@ -490,7 +489,7 @@ static __always_inline void *kmalloc_node(size_t size, 
gfp_t flags, int node)
  *
  * Child caches will hold extra metadata needed for its operation. Fields are:
  *
- * @memcg: pointer to the memcg this cache belongs to
+ * @id: the index in the root_cache's memcg_caches array.
  * @root_cache: pointer to the global, root cache, this cache was derived from
  */
 struct memcg_cache_params {
@@ -501,7 +500,7 @@ struct memcg_cache_params {
                        struct kmem_cache *memcg_caches[0];
                };
                struct {
-                       struct mem_cgroup *memcg;
+                       int id;
                        struct kmem_cache *root_cache;
                };
        };
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 8c60d7a30f4f..78d12076b01d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2603,8 +2603,6 @@ void memcg_update_array_size(int num)
 static void memcg_register_cache(struct mem_cgroup *memcg,
                                 struct kmem_cache *root_cache)
 {
-       static char memcg_name_buf[NAME_MAX + 1]; /* protected by
-                                                    memcg_slab_mutex */
        struct kmem_cache *cachep;
        int id;
 
@@ -2620,8 +2618,7 @@ static void memcg_register_cache(struct mem_cgroup *memcg,
        if (cache_from_memcg_idx(root_cache, id))
                return;
 
-       cgroup_name(memcg->css.cgroup, memcg_name_buf, NAME_MAX + 1);
-       cachep = memcg_create_kmem_cache(memcg, root_cache, memcg_name_buf);
+       cachep = memcg_create_kmem_cache(memcg, root_cache);
        /*
         * If we could not create a memcg cache, do not complain, because
         * that's not critical at all as we can always proceed with the root
@@ -2630,8 +2627,6 @@ static void memcg_register_cache(struct mem_cgroup *memcg,
        if (!cachep)
                return;
 
-       css_get(&memcg->css);
-
        /*
         * Since readers won't lock (see cache_from_memcg_idx()), we need a
         * barrier here to ensure nobody will see the kmem_cache partially
@@ -2646,7 +2641,6 @@ static void memcg_register_cache(struct mem_cgroup *memcg,
 static void memcg_unregister_cache(struct kmem_cache *cachep)
 {
        struct kmem_cache *root_cache;
-       struct mem_cgroup *memcg;
        int id;
 
        lockdep_assert_held(&memcg_slab_mutex);
@@ -2654,16 +2648,12 @@ static void memcg_unregister_cache(struct kmem_cache 
*cachep)
        BUG_ON(is_root_cache(cachep));
 
        root_cache = cachep->memcg_params->root_cache;
-       memcg = cachep->memcg_params->memcg;
-       id = memcg_cache_id(memcg);
+       id = cachep->memcg_params->id;
 
        BUG_ON(root_cache->memcg_params->memcg_caches[id] != cachep);
        root_cache->memcg_params->memcg_caches[id] = NULL;
 
        kmem_cache_destroy(cachep);
-
-       /* drop the reference taken in memcg_register_cache */
-       css_put(&memcg->css);
 }
 
 /*
@@ -4198,7 +4188,6 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, 
struct cgroup_subsys *ss)
 {
        int ret;
 
-       memcg->kmemcg_id = -1;
        ret = memcg_propagate_kmem(memcg);
        if (ret)
                return ret;
@@ -4743,6 +4732,9 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state 
*parent_css)
        vmpressure_init(&memcg->vmpressure);
        INIT_LIST_HEAD(&memcg->event_list);
        spin_lock_init(&memcg->event_list_lock);
+#ifdef CONFIG_MEMCG_KMEM
+       memcg->kmemcg_id = -1;
+#endif
 
        return &memcg->css;
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index d5e9e050a3ec..974d77db1b39 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -125,7 +125,7 @@ static int memcg_alloc_cache_params(struct mem_cgroup 
*memcg,
                return -ENOMEM;
 
        if (memcg) {
-               s->memcg_params->memcg = memcg;
+               s->memcg_params->id = memcg_cache_id(memcg);
                s->memcg_params->root_cache = root_cache;
        } else
                s->memcg_params->is_root_cache = true;
@@ -426,15 +426,13 @@ EXPORT_SYMBOL(kmem_cache_create);
  * memcg_create_kmem_cache - Create a cache for a memory cgroup.
  * @memcg: The memory cgroup the new cache is for.
  * @root_cache: The parent of the new cache.
- * @memcg_name: The name of the memory cgroup (used for naming the new cache).
  *
  * This function attempts to create a kmem cache that will serve allocation
  * requests going from @memcg to @root_cache. The new cache inherits properties
  * from its parent.
  */
 struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
-                                          struct kmem_cache *root_cache,
-                                          const char *memcg_name)
+                                          struct kmem_cache *root_cache)
 {
        struct kmem_cache *s = NULL;
        char *cache_name;
@@ -444,8 +442,8 @@ struct kmem_cache *memcg_create_kmem_cache(struct 
mem_cgroup *memcg,
 
        mutex_lock(&slab_mutex);
 
-       cache_name = kasprintf(GFP_KERNEL, "%s(%d:%s)", root_cache->name,
-                              memcg_cache_id(memcg), memcg_name);
+       cache_name = kasprintf(GFP_KERNEL, "%s(%d)", root_cache->name,
+                              memcg_cache_id(memcg));
        if (!cache_name)
                goto out_unlock;
 
@@ -912,7 +910,7 @@ int memcg_slab_show(struct seq_file *m, void *p)
 
        if (p == slab_caches.next)
                print_slabinfo_header(m);
-       if (!is_root_cache(s) && s->memcg_params->memcg == memcg)
+       if (!is_root_cache(s) && s->memcg_params->id == memcg_cache_id(memcg))
                cache_show(s, m);
        return 0;
 }
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to