aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2011-09-28 07:17:03 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2011-12-02 11:12:41 -0500
commit5f79020cb9fea59a5d4d1712bcd320523b129b35 (patch)
treee726d58389a1cd71999a19015f44716e6b6d747d /mm
parent5611cc4572e889b62a7b4c72a413536bf6a9c416 (diff)
kmemleak: Show where early_log issues come from
Based on initial patch by Steven Rostedt. Early kmemleak warnings did not show where the actual kmemleak API had been called from but rather just a backtrace to the kmemleak_init() function. By having all early kmemleak logs record the stack_trace, we can have kmemleak_init() write exactly where the problem occurred. This patch adds the setting of the kmemleak_warning variable every time a kmemleak warning is issued. The kmemleak_init() function checks this variable during early log replaying and prints the log trace if there was any warning. Reported-by: Steven Rostedt <rostedt@goodmis.org> Cc: Andrew Morton <akpm@google.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/kmemleak.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index f3b2a00fe9c1..8b528e3f8413 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -196,7 +196,9 @@ static atomic_t kmemleak_enabled = ATOMIC_INIT(0);
196static atomic_t kmemleak_initialized = ATOMIC_INIT(0); 196static atomic_t kmemleak_initialized = ATOMIC_INIT(0);
197/* enables or disables early logging of the memory operations */ 197/* enables or disables early logging of the memory operations */
198static atomic_t kmemleak_early_log = ATOMIC_INIT(1); 198static atomic_t kmemleak_early_log = ATOMIC_INIT(1);
199/* set if a fata kmemleak error has occurred */ 199/* set if a kmemleak warning was issued */
200static atomic_t kmemleak_warning = ATOMIC_INIT(0);
201/* set if a fatal kmemleak error has occurred */
200static atomic_t kmemleak_error = ATOMIC_INIT(0); 202static atomic_t kmemleak_error = ATOMIC_INIT(0);
201 203
202/* minimum and maximum address that may be valid pointers */ 204/* minimum and maximum address that may be valid pointers */
@@ -259,9 +261,10 @@ static void kmemleak_disable(void);
259/* 261/*
260 * Print a warning and dump the stack trace. 262 * Print a warning and dump the stack trace.
261 */ 263 */
262#define kmemleak_warn(x...) do { \ 264#define kmemleak_warn(x...) do { \
263 pr_warning(x); \ 265 pr_warning(x); \
264 dump_stack(); \ 266 dump_stack(); \
267 atomic_set(&kmemleak_warning, 1); \
265} while (0) 268} while (0)
266 269
267/* 270/*
@@ -403,8 +406,8 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
403 object = prio_tree_entry(node, struct kmemleak_object, 406 object = prio_tree_entry(node, struct kmemleak_object,
404 tree_node); 407 tree_node);
405 if (!alias && object->pointer != ptr) { 408 if (!alias && object->pointer != ptr) {
406 pr_warning("Found object by alias at 0x%08lx\n", ptr); 409 kmemleak_warn("Found object by alias at 0x%08lx\n",
407 dump_stack(); 410 ptr);
408 dump_object_info(object); 411 dump_object_info(object);
409 object = NULL; 412 object = NULL;
410 } 413 }
@@ -811,8 +814,7 @@ static void __init log_early(int op_type, const void *ptr, size_t size,
811 log->ptr = ptr; 814 log->ptr = ptr;
812 log->size = size; 815 log->size = size;
813 log->min_count = min_count; 816 log->min_count = min_count;
814 if (op_type == KMEMLEAK_ALLOC) 817 log->trace_len = __save_stack_trace(log->trace);
815 log->trace_len = __save_stack_trace(log->trace);
816 crt_early_log++; 818 crt_early_log++;
817 local_irq_restore(flags); 819 local_irq_restore(flags);
818} 820}
@@ -1659,6 +1661,17 @@ static int kmemleak_boot_config(char *str)
1659} 1661}
1660early_param("kmemleak", kmemleak_boot_config); 1662early_param("kmemleak", kmemleak_boot_config);
1661 1663
1664static void __init print_log_trace(struct early_log *log)
1665{
1666 struct stack_trace trace;
1667
1668 trace.nr_entries = log->trace_len;
1669 trace.entries = log->trace;
1670
1671 pr_notice("Early log backtrace:\n");
1672 print_stack_trace(&trace, 2);
1673}
1674
1662/* 1675/*
1663 * Kmemleak initialization. 1676 * Kmemleak initialization.
1664 */ 1677 */
@@ -1720,7 +1733,13 @@ void __init kmemleak_init(void)
1720 kmemleak_no_scan(log->ptr); 1733 kmemleak_no_scan(log->ptr);
1721 break; 1734 break;
1722 default: 1735 default:
1723 WARN_ON(1); 1736 kmemleak_warn("Unknown early log operation: %d\n",
1737 log->op_type);
1738 }
1739
1740 if (atomic_read(&kmemleak_warning)) {
1741 print_log_trace(log);
1742 atomic_set(&kmemleak_warning, 0);
1724 } 1743 }
1725 } 1744 }
1726} 1745}