]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/slab.h
Revert "console: implement lockdep support for console_lock"
[karo-tx-linux.git] / mm / slab.h
index 492eafa0b538c5e30ce05b2c88fca6c69026e369..34a98d642196f5e57e2bc2a1d94f7333b3ab7c48 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -32,6 +32,9 @@ extern struct list_head slab_caches;
 /* The slab cache that manages slab cache information */
 extern struct kmem_cache *kmem_cache;
 
+unsigned long calculate_alignment(unsigned long flags,
+               unsigned long align, unsigned long size);
+
 /* Functions provided by the slab allocators */
 extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags);
 
@@ -40,12 +43,15 @@ extern struct kmem_cache *create_kmalloc_cache(const char *name, size_t size,
 extern void create_boot_cache(struct kmem_cache *, const char *name,
                        size_t size, unsigned long flags);
 
+struct mem_cgroup;
 #ifdef CONFIG_SLUB
-struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
-       size_t align, unsigned long flags, void (*ctor)(void *));
+struct kmem_cache *
+__kmem_cache_alias(struct mem_cgroup *memcg, const char *name, size_t size,
+                  size_t align, unsigned long flags, void (*ctor)(void *));
 #else
-static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
-       size_t align, unsigned long flags, void (*ctor)(void *))
+static inline struct kmem_cache *
+__kmem_cache_alias(struct mem_cgroup *memcg, const char *name, size_t size,
+                  size_t align, unsigned long flags, void (*ctor)(void *))
 { return NULL; }
 #endif
 
@@ -97,4 +103,130 @@ void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo);
 void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s);
 ssize_t slabinfo_write(struct file *file, const char __user *buffer,
                       size_t count, loff_t *ppos);
+
+#ifdef CONFIG_MEMCG_KMEM
+static inline bool is_root_cache(struct kmem_cache *s)
+{
+       return !s->memcg_params || s->memcg_params->is_root_cache;
+}
+
+static inline bool cache_match_memcg(struct kmem_cache *cachep,
+                                    struct mem_cgroup *memcg)
+{
+       return (is_root_cache(cachep) && !memcg) ||
+                               (cachep->memcg_params->memcg == memcg);
+}
+
+static inline void memcg_bind_pages(struct kmem_cache *s, int order)
+{
+       if (!is_root_cache(s))
+               atomic_add(1 << order, &s->memcg_params->nr_pages);
+}
+
+static inline void memcg_release_pages(struct kmem_cache *s, int order)
+{
+       if (is_root_cache(s))
+               return;
+
+       if (atomic_sub_and_test((1 << order), &s->memcg_params->nr_pages))
+               mem_cgroup_destroy_cache(s);
+}
+
+static inline bool slab_equal_or_root(struct kmem_cache *s,
+                                       struct kmem_cache *p)
+{
+       return (p == s) ||
+               (s->memcg_params && (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))
+               return s->memcg_params->root_cache->name;
+       return s->name;
+}
+
+static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+{
+       return s->memcg_params->memcg_caches[idx];
+}
+
+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;
+}
+#else
+static inline bool is_root_cache(struct kmem_cache *s)
+{
+       return true;
+}
+
+static inline bool cache_match_memcg(struct kmem_cache *cachep,
+                                    struct mem_cgroup *memcg)
+{
+       return true;
+}
+
+static inline void memcg_bind_pages(struct kmem_cache *s, int order)
+{
+}
+
+static inline void memcg_release_pages(struct kmem_cache *s, int order)
+{
+}
+
+static inline bool slab_equal_or_root(struct kmem_cache *s,
+                                     struct kmem_cache *p)
+{
+       return true;
+}
+
+static inline const char *cache_name(struct kmem_cache *s)
+{
+       return s->name;
+}
+
+static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+{
+       return NULL;
+}
+
+static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
+{
+       return s;
+}
+#endif
+
+static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
+{
+       struct kmem_cache *cachep;
+       struct page *page;
+
+       /*
+        * When kmemcg is not being used, both assignments should return the
+        * same value. but we don't want to pay the assignment price in that
+        * case. If it is not compiled in, the compiler should be smart enough
+        * to not do even the assignment. In that case, slab_equal_or_root
+        * will also be a constant.
+        */
+       if (!memcg_kmem_enabled() && !unlikely(s->flags & SLAB_DEBUG_FREE))
+               return s;
+
+       page = virt_to_head_page(x);
+       cachep = page->slab_cache;
+       if (slab_equal_or_root(cachep, s))
+               return cachep;
+
+       pr_err("%s: Wrong slab cache. %s but object is from %s\n",
+               __FUNCTION__, cachep->name, s->name);
+       WARN_ON_ONCE(1);
+       return s;
+}
 #endif