summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2014-06-06 17:38:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:08:17 -0400
commitffe2c748e283c5dc1b9b9ac116299dbfc11a609b (patch)
treeef16269fb598e941c9e0c90004a8cc20f2133760
parentaae0ad7ae5a997bff1862e6e5eebed39cdf08ff3 (diff)
mm: introduce kmemleak_update_trace()
The memory allocation stack trace is not always useful for debugging a memory leak (e.g. radix_tree_preload). This function, when called, updates the stack trace for an already allocated object. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/kmemleak.txt1
-rw-r--r--include/linux/kmemleak.h4
-rw-r--r--mm/kmemleak.c34
3 files changed, 39 insertions, 0 deletions
diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt
index a7563ec4ea7b..b772418bf064 100644
--- a/Documentation/kmemleak.txt
+++ b/Documentation/kmemleak.txt
@@ -142,6 +142,7 @@ kmemleak_alloc_percpu - notify of a percpu memory block allocation
142kmemleak_free - notify of a memory block freeing 142kmemleak_free - notify of a memory block freeing
143kmemleak_free_part - notify of a partial memory block freeing 143kmemleak_free_part - notify of a partial memory block freeing
144kmemleak_free_percpu - notify of a percpu memory block freeing 144kmemleak_free_percpu - notify of a percpu memory block freeing
145kmemleak_update_trace - update object allocation stack trace
145kmemleak_not_leak - mark an object as not a leak 146kmemleak_not_leak - mark an object as not a leak
146kmemleak_ignore - do not scan or report an object as leak 147kmemleak_ignore - do not scan or report an object as leak
147kmemleak_scan_area - add scan areas inside a memory block 148kmemleak_scan_area - add scan areas inside a memory block
diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
index 5bb424659c04..057e95971014 100644
--- a/include/linux/kmemleak.h
+++ b/include/linux/kmemleak.h
@@ -30,6 +30,7 @@ extern void kmemleak_alloc_percpu(const void __percpu *ptr, size_t size) __ref;
30extern void kmemleak_free(const void *ptr) __ref; 30extern void kmemleak_free(const void *ptr) __ref;
31extern void kmemleak_free_part(const void *ptr, size_t size) __ref; 31extern void kmemleak_free_part(const void *ptr, size_t size) __ref;
32extern void kmemleak_free_percpu(const void __percpu *ptr) __ref; 32extern void kmemleak_free_percpu(const void __percpu *ptr) __ref;
33extern void kmemleak_update_trace(const void *ptr) __ref;
33extern void kmemleak_not_leak(const void *ptr) __ref; 34extern void kmemleak_not_leak(const void *ptr) __ref;
34extern void kmemleak_ignore(const void *ptr) __ref; 35extern void kmemleak_ignore(const void *ptr) __ref;
35extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref; 36extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref;
@@ -83,6 +84,9 @@ static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags)
83static inline void kmemleak_free_percpu(const void __percpu *ptr) 84static inline void kmemleak_free_percpu(const void __percpu *ptr)
84{ 85{
85} 86}
87static inline void kmemleak_update_trace(const void *ptr)
88{
89}
86static inline void kmemleak_not_leak(const void *ptr) 90static inline void kmemleak_not_leak(const void *ptr)
87{ 91{
88} 92}
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 5d4aec44982e..3cda50c1e394 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -990,6 +990,40 @@ void __ref kmemleak_free_percpu(const void __percpu *ptr)
990EXPORT_SYMBOL_GPL(kmemleak_free_percpu); 990EXPORT_SYMBOL_GPL(kmemleak_free_percpu);
991 991
992/** 992/**
993 * kmemleak_update_trace - update object allocation stack trace
994 * @ptr: pointer to beginning of the object
995 *
996 * Override the object allocation stack trace for cases where the actual
997 * allocation place is not always useful.
998 */
999void __ref kmemleak_update_trace(const void *ptr)
1000{
1001 struct kmemleak_object *object;
1002 unsigned long flags;
1003
1004 pr_debug("%s(0x%p)\n", __func__, ptr);
1005
1006 if (!kmemleak_enabled || IS_ERR_OR_NULL(ptr))
1007 return;
1008
1009 object = find_and_get_object((unsigned long)ptr, 1);
1010 if (!object) {
1011#ifdef DEBUG
1012 kmemleak_warn("Updating stack trace for unknown object at %p\n",
1013 ptr);
1014#endif
1015 return;
1016 }
1017
1018 spin_lock_irqsave(&object->lock, flags);
1019 object->trace_len = __save_stack_trace(object->trace);
1020 spin_unlock_irqrestore(&object->lock, flags);
1021
1022 put_object(object);
1023}
1024EXPORT_SYMBOL(kmemleak_update_trace);
1025
1026/**
993 * kmemleak_not_leak - mark an allocated object as false positive 1027 * kmemleak_not_leak - mark an allocated object as false positive
994 * @ptr: pointer to beginning of the object 1028 * @ptr: pointer to beginning of the object
995 * 1029 *