void memcg_update_array_size(int num_groups);
 
-struct kmem_cache *
-__memcg_kmem_get_cache(struct kmem_cache *cachep);
+struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep);
+void __memcg_kmem_put_cache(struct kmem_cache *cachep);
 
 int __memcg_charge_slab(struct kmem_cache *cachep, gfp_t gfp, int order);
 void __memcg_uncharge_slab(struct kmem_cache *cachep, int order);
 
        return __memcg_kmem_get_cache(cachep);
 }
+
+static __always_inline void memcg_kmem_put_cache(struct kmem_cache *cachep)
+{
+       if (memcg_kmem_enabled())
+               __memcg_kmem_put_cache(cachep);
+}
 #else
 #define for_each_memcg_cache_index(_idx)       \
        for (; NULL; )
 {
        return cachep;
 }
+
+static inline void memcg_kmem_put_cache(struct kmem_cache *cachep)
+{
+}
 #endif /* CONFIG_MEMCG_KMEM */
 #endif /* _LINUX_MEMCONTROL_H */
 
 
        if (!cachep)
                return;
 
-       css_get(&memcg->css);
        list_add(&cachep->memcg_params->list, &memcg->memcg_slab_caches);
 
        /*
        list_del(&cachep->memcg_params->list);
 
        kmem_cache_destroy(cachep);
-
-       /* drop the reference taken in memcg_register_cache */
-       css_put(&memcg->css);
 }
 
 int __memcg_cleanup_cache_params(struct kmem_cache *s)
        mutex_lock(&memcg_slab_mutex);
        list_for_each_entry_safe(params, tmp, &memcg->memcg_slab_caches, list) {
                cachep = memcg_params_to_cache(params);
-               kmem_cache_shrink(cachep);
-               if (atomic_read(&cachep->memcg_params->nr_pages) == 0)
-                       memcg_unregister_cache(cachep);
+               memcg_unregister_cache(cachep);
        }
        mutex_unlock(&memcg_slab_mutex);
 }
        struct memcg_register_cache_work *cw;
 
        cw = kmalloc(sizeof(*cw), GFP_NOWAIT);
-       if (cw == NULL) {
-               css_put(&memcg->css);
+       if (!cw)
                return;
-       }
+
+       css_get(&memcg->css);
 
        cw->memcg = memcg;
        cw->cachep = cachep;
 int __memcg_charge_slab(struct kmem_cache *cachep, gfp_t gfp, int order)
 {
        unsigned int nr_pages = 1 << order;
-       int res;
 
-       res = memcg_charge_kmem(cachep->memcg_params->memcg, gfp, nr_pages);
-       if (!res)
-               atomic_add(nr_pages, &cachep->memcg_params->nr_pages);
-       return res;
+       return memcg_charge_kmem(cachep->memcg_params->memcg, gfp, nr_pages);
 }
 
 void __memcg_uncharge_slab(struct kmem_cache *cachep, int order)
        unsigned int nr_pages = 1 << order;
 
        memcg_uncharge_kmem(cachep->memcg_params->memcg, nr_pages);
-       atomic_sub(nr_pages, &cachep->memcg_params->nr_pages);
 }
 
 /*
        if (current->memcg_kmem_skip_account)
                return cachep;
 
-       rcu_read_lock();
-       memcg = mem_cgroup_from_task(rcu_dereference(current->mm->owner));
-
+       memcg = get_mem_cgroup_from_mm(current->mm);
        if (!memcg_kmem_is_active(memcg))
                goto out;
 
        memcg_cachep = cache_from_memcg_idx(cachep, memcg_cache_id(memcg));
-       if (likely(memcg_cachep)) {
-               cachep = memcg_cachep;
-               goto out;
-       }
-
-       /* The corresponding put will be done in the workqueue. */
-       if (!css_tryget_online(&memcg->css))
-               goto out;
-       rcu_read_unlock();
+       if (likely(memcg_cachep))
+               return memcg_cachep;
 
        /*
         * If we are in a safe context (can wait, and not in interrupt
         * defer everything.
         */
        memcg_schedule_register_cache(memcg, cachep);
-       return cachep;
 out:
-       rcu_read_unlock();
+       css_put(&memcg->css);
        return cachep;
 }
 
+void __memcg_kmem_put_cache(struct kmem_cache *cachep)
+{
+       if (!is_root_cache(cachep))
+               css_put(&cachep->memcg_params->memcg->css);
+}
+
 /*
  * We need to verify if the allocation against current->mm->owner's memcg is
  * possible for the given order. But the page is not allocated yet, so we'll
        memcg_uncharge_kmem(memcg, 1 << order);
        page->mem_cgroup = NULL;
 }
-#else
-static inline void memcg_unregister_all_caches(struct mem_cgroup *memcg)
-{
-}
 #endif /* CONFIG_MEMCG_KMEM */
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 
 static void memcg_destroy_kmem(struct mem_cgroup *memcg)
 {
+       memcg_unregister_all_caches(memcg);
        mem_cgroup_sockets_destroy(memcg);
 }
 #else
        }
        spin_unlock(&memcg->event_list_lock);
 
-       memcg_unregister_all_caches(memcg);
        vmpressure_cleanup(&memcg->vmpressure);
 }
 
 
        kmemleak_free(x);
 }
 
-static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
+static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
+                                                    gfp_t flags)
 {
        flags &= gfp_allowed_mask;
        lockdep_trace_alloc(flags);
        might_sleep_if(flags & __GFP_WAIT);
 
-       return should_failslab(s->object_size, flags, s->flags);
+       if (should_failslab(s->object_size, flags, s->flags))
+               return NULL;
+
+       return memcg_kmem_get_cache(s, flags);
 }
 
 static inline void slab_post_alloc_hook(struct kmem_cache *s,
        flags &= gfp_allowed_mask;
        kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
        kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags);
+       memcg_kmem_put_cache(s);
 }
 
 static inline void slab_free_hook(struct kmem_cache *s, void *x)
        struct page *page;
        unsigned long tid;
 
-       if (slab_pre_alloc_hook(s, gfpflags))
+       s = slab_pre_alloc_hook(s, gfpflags);
+       if (!s)
                return NULL;
-
-       s = memcg_kmem_get_cache(s, gfpflags);
 redo:
        /*
         * Must read kmem_cache cpu data via this cpu ptr. Preemption is