Merge tag 'pstore-v4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
[linux-2.6-block.git] / mm / slab_common.c
index 10f127b2de7c04acb0e87ae1bc8e346babe1617b..98dcdc3520623bf776164982224b7b258e9a2291 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/poison.h>
 #include <linux/interrupt.h>
 #include <linux/memory.h>
+#include <linux/cache.h>
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
@@ -81,38 +82,19 @@ unsigned int kmem_cache_size(struct kmem_cache *s)
 EXPORT_SYMBOL(kmem_cache_size);
 
 #ifdef CONFIG_DEBUG_VM
-static int kmem_cache_sanity_check(const char *name, size_t size)
+static int kmem_cache_sanity_check(const char *name, unsigned int size)
 {
-       struct kmem_cache *s = NULL;
-
        if (!name || in_interrupt() || size < sizeof(void *) ||
                size > KMALLOC_MAX_SIZE) {
                pr_err("kmem_cache_create(%s) integrity check failed\n", name);
                return -EINVAL;
        }
 
-       list_for_each_entry(s, &slab_caches, list) {
-               char tmp;
-               int res;
-
-               /*
-                * This happens when the module gets unloaded and doesn't
-                * destroy its slab cache and no-one else reuses the vmalloc
-                * area of the module.  Print a warning.
-                */
-               res = probe_kernel_address(s->name, tmp);
-               if (res) {
-                       pr_err("Slab cache with size %d has lost its name\n",
-                              s->object_size);
-                       continue;
-               }
-       }
-
        WARN_ON(strchr(name, ' '));     /* It confuses parsers */
        return 0;
 }
 #else
-static inline int kmem_cache_sanity_check(const char *name, size_t size)
+static inline int kmem_cache_sanity_check(const char *name, unsigned int size)
 {
        return 0;
 }
@@ -279,8 +261,8 @@ static inline void memcg_unlink_cache(struct kmem_cache *s)
  * Figure out what the alignment of the objects will be given a set of
  * flags, a user specified alignment and the size of the objects.
  */
-static unsigned long calculate_alignment(unsigned long flags,
-               unsigned long align, unsigned long size)
+static unsigned int calculate_alignment(slab_flags_t flags,
+               unsigned int align, unsigned int size)
 {
        /*
         * If the user wants hardware cache aligned objects then follow that
@@ -290,7 +272,7 @@ static unsigned long calculate_alignment(unsigned long flags,
         * alignment though. If that is greater then use it.
         */
        if (flags & SLAB_HWCACHE_ALIGN) {
-               unsigned long ralign;
+               unsigned int ralign;
 
                ralign = cache_line_size();
                while (size <= ralign / 2)
@@ -330,7 +312,7 @@ int slab_unmergeable(struct kmem_cache *s)
        return 0;
 }
 
-struct kmem_cache *find_mergeable(size_t size, size_t align,
+struct kmem_cache *find_mergeable(unsigned int size, unsigned int align,
                slab_flags_t flags, const char *name, void (*ctor)(void *))
 {
        struct kmem_cache *s;
@@ -378,9 +360,9 @@ struct kmem_cache *find_mergeable(size_t size, size_t align,
 }
 
 static struct kmem_cache *create_cache(const char *name,
-               size_t object_size, size_t size, size_t align,
-               slab_flags_t flags, size_t useroffset,
-               size_t usersize, void (*ctor)(void *),
+               unsigned int object_size, unsigned int align,
+               slab_flags_t flags, unsigned int useroffset,
+               unsigned int usersize, void (*ctor)(void *),
                struct mem_cgroup *memcg, struct kmem_cache *root_cache)
 {
        struct kmem_cache *s;
@@ -395,8 +377,7 @@ static struct kmem_cache *create_cache(const char *name,
                goto out;
 
        s->name = name;
-       s->object_size = object_size;
-       s->size = size;
+       s->size = s->object_size = object_size;
        s->align = align;
        s->ctor = ctor;
        s->useroffset = useroffset;
@@ -451,8 +432,10 @@ out_free_cache:
  * as davem.
  */
 struct kmem_cache *
-kmem_cache_create_usercopy(const char *name, size_t size, size_t align,
-                 slab_flags_t flags, size_t useroffset, size_t usersize,
+kmem_cache_create_usercopy(const char *name,
+                 unsigned int size, unsigned int align,
+                 slab_flags_t flags,
+                 unsigned int useroffset, unsigned int usersize,
                  void (*ctor)(void *))
 {
        struct kmem_cache *s = NULL;
@@ -500,7 +483,7 @@ kmem_cache_create_usercopy(const char *name, size_t size, size_t align,
                goto out_unlock;
        }
 
-       s = create_cache(cache_name, size, size,
+       s = create_cache(cache_name, size,
                         calculate_alignment(flags, align, size),
                         flags, useroffset, usersize, ctor, NULL, NULL);
        if (IS_ERR(s)) {
@@ -531,7 +514,7 @@ out_unlock:
 EXPORT_SYMBOL(kmem_cache_create_usercopy);
 
 struct kmem_cache *
-kmem_cache_create(const char *name, size_t size, size_t align,
+kmem_cache_create(const char *name, unsigned int size, unsigned int align,
                slab_flags_t flags, void (*ctor)(void *))
 {
        return kmem_cache_create_usercopy(name, size, align, flags, 0, 0,
@@ -647,7 +630,7 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,
                goto out_unlock;
 
        s = create_cache(cache_name, root_cache->object_size,
-                        root_cache->size, root_cache->align,
+                        root_cache->align,
                         root_cache->flags & CACHE_CREATE_MASK,
                         root_cache->useroffset, root_cache->usersize,
                         root_cache->ctor, memcg, root_cache);
@@ -916,8 +899,9 @@ bool slab_is_available(void)
 
 #ifndef CONFIG_SLOB
 /* Create a cache during boot when no slab services are available yet */
-void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size,
-               slab_flags_t flags, size_t useroffset, size_t usersize)
+void __init create_boot_cache(struct kmem_cache *s, const char *name,
+               unsigned int size, slab_flags_t flags,
+               unsigned int useroffset, unsigned int usersize)
 {
        int err;
 
@@ -932,15 +916,15 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t siz
        err = __kmem_cache_create(s, flags);
 
        if (err)
-               panic("Creation of kmalloc slab %s size=%zu failed. Reason %d\n",
+               panic("Creation of kmalloc slab %s size=%u failed. Reason %d\n",
                                        name, size, err);
 
        s->refcount = -1;       /* Exempt from merging for now */
 }
 
-struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size,
-                               slab_flags_t flags, size_t useroffset,
-                               size_t usersize)
+struct kmem_cache *__init create_kmalloc_cache(const char *name,
+               unsigned int size, slab_flags_t flags,
+               unsigned int useroffset, unsigned int usersize)
 {
        struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
 
@@ -954,11 +938,11 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size,
        return s;
 }
 
-struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __ro_after_init;
 EXPORT_SYMBOL(kmalloc_caches);
 
 #ifdef CONFIG_ZONE_DMA
-struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1] __ro_after_init;
 EXPORT_SYMBOL(kmalloc_dma_caches);
 #endif
 
@@ -968,7 +952,7 @@ EXPORT_SYMBOL(kmalloc_dma_caches);
  * of two cache sizes there. The size of larger slabs can be determined using
  * fls.
  */
-static s8 size_index[24] = {
+static u8 size_index[24] __ro_after_init = {
        3,      /* 8 */
        4,      /* 16 */
        5,      /* 24 */
@@ -995,7 +979,7 @@ static s8 size_index[24] = {
        2       /* 192 */
 };
 
-static inline int size_index_elem(size_t bytes)
+static inline unsigned int size_index_elem(unsigned int bytes)
 {
        return (bytes - 1) / 8;
 }
@@ -1006,7 +990,7 @@ static inline int size_index_elem(size_t bytes)
  */
 struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
 {
-       int index;
+       unsigned int index;
 
        if (unlikely(size > KMALLOC_MAX_SIZE)) {
                WARN_ON_ONCE(!(flags & __GFP_NOWARN));
@@ -1064,13 +1048,13 @@ const struct kmalloc_info_struct kmalloc_info[] __initconst = {
  */
 void __init setup_kmalloc_cache_index_table(void)
 {
-       int i;
+       unsigned int i;
 
        BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
                (KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
 
        for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {
-               int elem = size_index_elem(i);
+               unsigned int elem = size_index_elem(i);
 
                if (elem >= ARRAY_SIZE(size_index))
                        break;
@@ -1137,9 +1121,9 @@ void __init create_kmalloc_caches(slab_flags_t flags)
                struct kmem_cache *s = kmalloc_caches[i];
 
                if (s) {
-                       int size = kmalloc_size(i);
+                       unsigned int size = kmalloc_size(i);
                        char *n = kasprintf(GFP_NOWAIT,
-                                "dma-kmalloc-%d", size);
+                                "dma-kmalloc-%u", size);
 
                        BUG_ON(!n);
                        kmalloc_dma_caches[i] = create_kmalloc_cache(n,
@@ -1182,10 +1166,10 @@ EXPORT_SYMBOL(kmalloc_order_trace);
 #ifdef CONFIG_SLAB_FREELIST_RANDOM
 /* Randomize a generic freelist */
 static void freelist_randomize(struct rnd_state *state, unsigned int *list,
-                       size_t count)
+                              unsigned int count)
 {
-       size_t i;
        unsigned int rand;
+       unsigned int i;
 
        for (i = 0; i < count; i++)
                list[i] = i;
@@ -1532,3 +1516,11 @@ EXPORT_TRACEPOINT_SYMBOL(kmalloc_node);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc_node);
 EXPORT_TRACEPOINT_SYMBOL(kfree);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_free);
+
+int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
+{
+       if (__should_failslab(s, gfpflags))
+               return -ENOMEM;
+       return 0;
+}
+ALLOW_ERROR_INJECTION(should_failslab, ERRNO);