diff options
author | Ezequiel Garcia <elezegarcia@gmail.com> | 2012-09-08 16:47:53 -0400 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-09-25 03:14:18 -0400 |
commit | f3f741019595f1e73564d985f5fe8abcbb98c769 (patch) | |
tree | 6a46da5eb60a8bd2bf6bdaf5804e40367b91048f | |
parent | ff4fcd01ec86d98d15d2fd96f22f19bb1d341b88 (diff) |
mm, slob: Add support for kmalloc_track_caller()
Currently slob falls back to regular kmalloc for this case.
With this patch kmalloc_track_caller() is correctly implemented,
thus tracing the specified caller.
This is important to trace accurately allocations performed by
krealloc, kstrdup, kmemdup, etc.
Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | include/linux/slab.h | 6 | ||||
-rw-r--r-- | mm/slob.c | 27 |
2 files changed, 28 insertions, 5 deletions
diff --git a/include/linux/slab.h b/include/linux/slab.h index 0dd2dfa7beca..83d1a1454b7e 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h | |||
@@ -321,7 +321,8 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, | |||
321 | * request comes from. | 321 | * request comes from. |
322 | */ | 322 | */ |
323 | #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ | 323 | #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ |
324 | (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) | 324 | (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ |
325 | (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) | ||
325 | extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); | 326 | extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); |
326 | #define kmalloc_track_caller(size, flags) \ | 327 | #define kmalloc_track_caller(size, flags) \ |
327 | __kmalloc_track_caller(size, flags, _RET_IP_) | 328 | __kmalloc_track_caller(size, flags, _RET_IP_) |
@@ -340,7 +341,8 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); | |||
340 | * allocation request comes from. | 341 | * allocation request comes from. |
341 | */ | 342 | */ |
342 | #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ | 343 | #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ |
343 | (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) | 344 | (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ |
345 | (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) | ||
344 | extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); | 346 | extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); |
345 | #define kmalloc_node_track_caller(size, flags, node) \ | 347 | #define kmalloc_node_track_caller(size, flags, node) \ |
346 | __kmalloc_node_track_caller(size, flags, node, \ | 348 | __kmalloc_node_track_caller(size, flags, node, \ |
@@ -425,7 +425,8 @@ out: | |||
425 | * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend. | 425 | * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend. |
426 | */ | 426 | */ |
427 | 427 | ||
428 | void *__kmalloc_node(size_t size, gfp_t gfp, int node) | 428 | static __always_inline void * |
429 | __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) | ||
429 | { | 430 | { |
430 | unsigned int *m; | 431 | unsigned int *m; |
431 | int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); | 432 | int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); |
@@ -446,7 +447,7 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) | |||
446 | *m = size; | 447 | *m = size; |
447 | ret = (void *)m + align; | 448 | ret = (void *)m + align; |
448 | 449 | ||
449 | trace_kmalloc_node(_RET_IP_, ret, | 450 | trace_kmalloc_node(caller, ret, |
450 | size, size + align, gfp, node); | 451 | size, size + align, gfp, node); |
451 | } else { | 452 | } else { |
452 | unsigned int order = get_order(size); | 453 | unsigned int order = get_order(size); |
@@ -460,15 +461,35 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) | |||
460 | page->private = size; | 461 | page->private = size; |
461 | } | 462 | } |
462 | 463 | ||
463 | trace_kmalloc_node(_RET_IP_, ret, | 464 | trace_kmalloc_node(caller, ret, |
464 | size, PAGE_SIZE << order, gfp, node); | 465 | size, PAGE_SIZE << order, gfp, node); |
465 | } | 466 | } |
466 | 467 | ||
467 | kmemleak_alloc(ret, size, 1, gfp); | 468 | kmemleak_alloc(ret, size, 1, gfp); |
468 | return ret; | 469 | return ret; |
469 | } | 470 | } |
471 | |||
472 | void *__kmalloc_node(size_t size, gfp_t gfp, int node) | ||
473 | { | ||
474 | return __do_kmalloc_node(size, gfp, node, _RET_IP_); | ||
475 | } | ||
470 | EXPORT_SYMBOL(__kmalloc_node); | 476 | EXPORT_SYMBOL(__kmalloc_node); |
471 | 477 | ||
478 | #ifdef CONFIG_TRACING | ||
479 | void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller) | ||
480 | { | ||
481 | return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller); | ||
482 | } | ||
483 | |||
484 | #ifdef CONFIG_NUMA | ||
485 | void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, | ||
486 | int node, unsigned long caller) | ||
487 | { | ||
488 | return __do_kmalloc_node(size, gfp, node, caller); | ||
489 | } | ||
490 | #endif | ||
491 | #endif | ||
492 | |||
472 | void kfree(const void *block) | 493 | void kfree(const void *block) |
473 | { | 494 | { |
474 | struct page *sp; | 495 | struct page *sp; |