Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / mm / slab.h
index 342eac8..6cc323f 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -30,30 +30,6 @@ struct kmem_cache {
        struct list_head list;  /* List of all slab caches on the system */
 };
 
-#else /* !CONFIG_SLOB */
-
-/*
- * This is the main placeholder for memcg-related information in kmem caches.
- * Both the root cache and the child cache will have it. Some fields are used
- * in both cases, other are specific to root caches.
- *
- * @root_cache:        Common to root and child caches.  NULL for root, pointer to
- *             the root cache for children.
- *
- * The following fields are specific to root caches.
- *
- * @memcg_cache: pointer to memcg kmem cache, used by all non-root memory
- *             cgroups.
- * @root_caches_node: list node for slab_root_caches list.
- * @work: work struct used to create the non-root cache.
- */
-struct memcg_cache_params {
-       struct kmem_cache *root_cache;
-
-       struct kmem_cache *memcg_cache;
-       struct list_head __root_caches_node;
-       struct work_struct work;
-};
 #endif /* CONFIG_SLOB */
 
 #ifdef CONFIG_SLAB
@@ -198,7 +174,6 @@ int __kmem_cache_shutdown(struct kmem_cache *);
 void __kmem_cache_release(struct kmem_cache *);
 int __kmem_cache_shrink(struct kmem_cache *);
 void slab_kmem_cache_release(struct kmem_cache *);
-void kmem_cache_shrink_all(struct kmem_cache *s);
 
 struct seq_file;
 struct file;
@@ -265,48 +240,6 @@ static inline bool kmem_cache_debug_flags(struct kmem_cache *s, slab_flags_t fla
 }
 
 #ifdef CONFIG_MEMCG_KMEM
-
-/* List of all root caches. */
-extern struct list_head                slab_root_caches;
-#define root_caches_node       memcg_params.__root_caches_node
-
-static inline bool is_root_cache(struct kmem_cache *s)
-{
-       return !s->memcg_params.root_cache;
-}
-
-static inline bool slab_equal_or_root(struct kmem_cache *s,
-                                     struct kmem_cache *p)
-{
-       return p == s || p == s->memcg_params.root_cache;
-}
-
-/*
- * We use suffixes to the name in memcg because we can't have caches
- * created in the system with the same name. But when we print them
- * locally, better refer to them with the base name
- */
-static inline const char *cache_name(struct kmem_cache *s)
-{
-       if (!is_root_cache(s))
-               s = s->memcg_params.root_cache;
-       return s->name;
-}
-
-static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
-{
-       if (is_root_cache(s))
-               return s;
-       return s->memcg_params.root_cache;
-}
-
-static inline struct kmem_cache *memcg_cache(struct kmem_cache *s)
-{
-       if (is_root_cache(s))
-               return s->memcg_params.memcg_cache;
-       return NULL;
-}
-
 static inline struct obj_cgroup **page_obj_cgroups(struct page *page)
 {
        /*
@@ -324,21 +257,8 @@ static inline bool page_has_obj_cgroups(struct page *page)
        return ((unsigned long)page->obj_cgroups & 0x1UL);
 }
 
-static inline int memcg_alloc_page_obj_cgroups(struct page *page,
-                                              struct kmem_cache *s, gfp_t gfp)
-{
-       unsigned int objects = objs_per_slab_page(s, page);
-       void *vec;
-
-       vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp,
-                          page_to_nid(page));
-       if (!vec)
-               return -ENOMEM;
-
-       kmemleak_not_leak(vec);
-       page->obj_cgroups = (struct obj_cgroup **) ((unsigned long)vec | 0x1UL);
-       return 0;
-}
+int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s,
+                                gfp_t gfp);
 
 static inline void memcg_free_page_obj_cgroups(struct page *page)
 {
@@ -355,38 +275,25 @@ static inline size_t obj_full_size(struct kmem_cache *s)
        return s->size + sizeof(struct obj_cgroup *);
 }
 
-static inline struct kmem_cache *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
-                                               struct obj_cgroup **objcgp,
-                                               size_t objects, gfp_t flags)
+static inline struct obj_cgroup *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
+                                                          size_t objects,
+                                                          gfp_t flags)
 {
-       struct kmem_cache *cachep;
        struct obj_cgroup *objcg;
 
        if (memcg_kmem_bypass())
-               return s;
-
-       cachep = READ_ONCE(s->memcg_params.memcg_cache);
-       if (unlikely(!cachep)) {
-               /*
-                * If memcg cache does not exist yet, we schedule it's
-                * asynchronous creation and let the current allocation
-                * go through with the root cache.
-                */
-               queue_work(system_wq, &s->memcg_params.work);
-               return s;
-       }
+               return NULL;
 
        objcg = get_obj_cgroup_from_current();
        if (!objcg)
-               return s;
+               return NULL;
 
        if (obj_cgroup_charge(objcg, flags, objects * obj_full_size(s))) {
                obj_cgroup_put(objcg);
-               cachep = NULL;
+               return NULL;
        }
 
-       *objcgp = objcg;
-       return cachep;
+       return objcg;
 }
 
 static inline void mod_objcg_state(struct obj_cgroup *objcg,
@@ -405,15 +312,27 @@ static inline void mod_objcg_state(struct obj_cgroup *objcg,
 
 static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s,
                                              struct obj_cgroup *objcg,
-                                             size_t size, void **p)
+                                             gfp_t flags, size_t size,
+                                             void **p)
 {
        struct page *page;
        unsigned long off;
        size_t i;
 
+       if (!objcg)
+               return;
+
+       flags &= ~__GFP_ACCOUNT;
        for (i = 0; i < size; i++) {
                if (likely(p[i])) {
                        page = virt_to_head_page(p[i]);
+
+                       if (!page_has_obj_cgroups(page) &&
+                           memcg_alloc_page_obj_cgroups(page, s, flags)) {
+                               obj_cgroup_uncharge(objcg, obj_full_size(s));
+                               continue;
+                       }
+
                        off = obj_to_index(s, page, p[i]);
                        obj_cgroup_get(objcg);
                        page_obj_cgroups(page)[off] = objcg;
@@ -432,13 +351,19 @@ static inline void memcg_slab_free_hook(struct kmem_cache *s, struct page *page,
        struct obj_cgroup *objcg;
        unsigned int off;
 
-       if (!memcg_kmem_enabled() || is_root_cache(s))
+       if (!memcg_kmem_enabled())
+               return;
+
+       if (!page_has_obj_cgroups(page))
                return;
 
        off = obj_to_index(s, page, p);
        objcg = page_obj_cgroups(page)[off];
        page_obj_cgroups(page)[off] = NULL;
 
+       if (!objcg)
+               return;
+
        obj_cgroup_uncharge(objcg, obj_full_size(s));
        mod_objcg_state(objcg, page_pgdat(page), cache_vmstat_idx(s),
                        -obj_full_size(s));
@@ -446,41 +371,7 @@ static inline void memcg_slab_free_hook(struct kmem_cache *s, struct page *page,
        obj_cgroup_put(objcg);
 }
 
-extern void slab_init_memcg_params(struct kmem_cache *);
-extern void memcg_link_cache(struct kmem_cache *s);
-
 #else /* CONFIG_MEMCG_KMEM */
-
-/* If !memcg, all caches are root. */
-#define slab_root_caches       slab_caches
-#define root_caches_node       list
-
-static inline bool is_root_cache(struct kmem_cache *s)
-{
-       return true;
-}
-
-static inline bool slab_equal_or_root(struct kmem_cache *s,
-                                     struct kmem_cache *p)
-{
-       return s == p;
-}
-
-static inline const char *cache_name(struct kmem_cache *s)
-{
-       return s->name;
-}
-
-static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
-{
-       return s;
-}
-
-static inline struct kmem_cache *memcg_cache(struct kmem_cache *s)
-{
-       return NULL;
-}
-
 static inline bool page_has_obj_cgroups(struct page *page)
 {
        return false;
@@ -501,16 +392,17 @@ static inline void memcg_free_page_obj_cgroups(struct page *page)
 {
 }
 
-static inline struct kmem_cache *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
-                                               struct obj_cgroup **objcgp,
-                                               size_t objects, gfp_t flags)
+static inline struct obj_cgroup *memcg_slab_pre_alloc_hook(struct kmem_cache *s,
+                                                          size_t objects,
+                                                          gfp_t flags)
 {
        return NULL;
 }
 
 static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s,
                                              struct obj_cgroup *objcg,
-                                             size_t size, void **p)
+                                             gfp_t flags, size_t size,
+                                             void **p)
 {
 }
 
@@ -518,15 +410,6 @@ static inline void memcg_slab_free_hook(struct kmem_cache *s, struct page *page,
                                        void *p)
 {
 }
-
-static inline void slab_init_memcg_params(struct kmem_cache *s)
-{
-}
-
-static inline void memcg_link_cache(struct kmem_cache *s)
-{
-}
-
 #endif /* CONFIG_MEMCG_KMEM */
 
 static inline struct kmem_cache *virt_to_cache(const void *obj)
@@ -540,27 +423,17 @@ static inline struct kmem_cache *virt_to_cache(const void *obj)
        return page->slab_cache;
 }
 
-static __always_inline int charge_slab_page(struct page *page,
-                                           gfp_t gfp, int order,
-                                           struct kmem_cache *s)
+static __always_inline void account_slab_page(struct page *page, int order,
+                                             struct kmem_cache *s)
 {
-       if (memcg_kmem_enabled() && !is_root_cache(s)) {
-               int ret;
-
-               ret = memcg_alloc_page_obj_cgroups(page, s, gfp);
-               if (ret)
-                       return ret;
-       }
-
        mod_node_page_state(page_pgdat(page), cache_vmstat_idx(s),
                            PAGE_SIZE << order);
-       return 0;
 }
 
-static __always_inline void uncharge_slab_page(struct page *page, int order,
-                                              struct kmem_cache *s)
+static __always_inline void unaccount_slab_page(struct page *page, int order,
+                                               struct kmem_cache *s)
 {
-       if (memcg_kmem_enabled() && !is_root_cache(s))
+       if (memcg_kmem_enabled())
                memcg_free_page_obj_cgroups(page);
 
        mod_node_page_state(page_pgdat(page), cache_vmstat_idx(s),
@@ -572,12 +445,11 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
        struct kmem_cache *cachep;
 
        if (!IS_ENABLED(CONFIG_SLAB_FREELIST_HARDENED) &&
-           !memcg_kmem_enabled() &&
            !kmem_cache_debug_flags(s, SLAB_CONSISTENCY_CHECKS))
                return s;
 
        cachep = virt_to_cache(x);
-       if (WARN(cachep && !slab_equal_or_root(cachep, s),
+       if (WARN(cachep && cachep != s,
                  "%s: Wrong slab cache. %s but object is from %s\n",
                  __func__, s->name, cachep->name))
                print_tracking(cachep, x);
@@ -630,7 +502,7 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
 
        if (memcg_kmem_enabled() &&
            ((flags & __GFP_ACCOUNT) || (s->flags & SLAB_ACCOUNT)))
-               return memcg_slab_pre_alloc_hook(s, objcgp, size, flags);
+               *objcgp = memcg_slab_pre_alloc_hook(s, size, flags);
 
        return s;
 }
@@ -649,8 +521,8 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s,
                                         s->flags, flags);
        }
 
-       if (memcg_kmem_enabled() && !is_root_cache(s))
-               memcg_slab_post_alloc_hook(s, objcg, size, p);
+       if (memcg_kmem_enabled())
+               memcg_slab_post_alloc_hook(s, objcg, flags, size, p);
 }
 
 #ifndef CONFIG_SLOB