diff --git a/include/linux/slab.h b/include/linux/slab.h index 1fb77a9cc148d2a61e3e2f1d1b0b469b01620703..8cf52939d0ab676698083140e8cb80384ee6b263 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -76,7 +76,14 @@ struct cache_sizes { kmem_cache_t *cs_dmacachep; }; extern struct cache_sizes malloc_sizes[]; + +#ifndef CONFIG_DEBUG_SLAB extern void *__kmalloc(size_t, gfp_t); +#else +extern void *__kmalloc_track_caller(size_t, gfp_t, void*); +#define __kmalloc(size, flags) \ + __kmalloc_track_caller(size, flags, __builtin_return_address(0)) +#endif static inline void *kmalloc(size_t size, gfp_t flags) { diff --git a/mm/slab.c b/mm/slab.c index 6fbd6a1cdeb4a34a2d9dd2f20fa344a8f200d516..67527268b01c08b6a6d8239056578c5b81e984b2 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2687,7 +2687,8 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) return objp; } -static inline void *__cache_alloc(struct kmem_cache *cachep, gfp_t flags) +static __always_inline void * +__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) { unsigned long save_flags; void *objp; @@ -2698,7 +2699,7 @@ static inline void *__cache_alloc(struct kmem_cache *cachep, gfp_t flags) objp = ____cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, - __builtin_return_address(0)); + caller); prefetchw(objp); return objp; } @@ -2927,7 +2928,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp) */ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - return __cache_alloc(cachep, flags); + return __cache_alloc(cachep, flags, __builtin_return_address(0)); } EXPORT_SYMBOL(kmem_cache_alloc); @@ -3041,7 +3042,8 @@ EXPORT_SYMBOL(kmalloc_node); * platforms. For example, on i386, it means that the memory must come * from the first 16MB. */ -void *__kmalloc(size_t size, gfp_t flags) +static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, + void *caller) { struct kmem_cache *cachep; @@ -3053,10 +3055,27 @@ void *__kmalloc(size_t size, gfp_t flags) cachep = __find_general_cachep(size, flags); if (unlikely(cachep == NULL)) return NULL; - return __cache_alloc(cachep, flags); + return __cache_alloc(cachep, flags, caller); +} + +#ifndef CONFIG_DEBUG_SLAB + +void *__kmalloc(size_t size, gfp_t flags) +{ + return __do_kmalloc(size, flags, NULL); } EXPORT_SYMBOL(__kmalloc); +#else + +void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller) +{ + return __do_kmalloc(size, flags, caller); +} +EXPORT_SYMBOL(__kmalloc_track_caller); + +#endif + #ifdef CONFIG_SMP /** * __alloc_percpu - allocate one copy of the object for every present