From: Catalin Marinas <catalin.marinas@xxxxxxx>
This patch adds the base support for the kernel memory leak detector. It
traces the memory allocation/freeing in a way similar to the Boehm's
conservative garbage collector, the difference being that the orphan
pointers are not freed but only shown in /proc/memleak. Enabling this
feature would introduce an overhead to memory allocations.[snip]
Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx>
---
include/linux/kernel.h | 13 +
include/linux/memleak.h | 55 +++++
init/main.c | 5
lib/Kconfig.debug | 11 +
mm/Makefile | 2
mm/memleak.c | 549 +++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 632 insertions(+), 3 deletions(-)
diff --git a/include/linux/memleak.h b/include/linux/memleak.h[snip]
+#define memleak_offsetof(type, member) \
+ (__builtin_constant_p(&((type *) 0)->member) ? \
+ ((size_t) &((type *) 0)->member) : 0)
+
+config DEBUG_MEMLEAK
+ bool "Kernel memory leak detector"
+ depends on DEBUG_KERNEL && SLAB
+ help
+ Say Y here if you want to enable the memory leak
+ detector. The memory allocation/freeing is traced in a way
+ similar to the Boehm's conservative garbage collector, the
+ difference being that the orphan pointers are not freed but
+ only shown in /proc/memleak. Enabling this feature would
+ introduce an overhead to memory allocations.
+#define MAX_TRACE 1
+#endif
+
+
+extern struct memleak_offset __memleak_offsets_start[];
+extern struct memleak_offset __memleak_offsets_end[];
+
+
+struct memleak_alias {
+static inline void delete_pointer(unsigned long ptr)
+/* Freeing function hook
+ */
+ delete_pointer((unsigned long) ptr);
+static void memleak_scan(void)
+{
+ unsigned long flags;
+ struct memleak_pointer *pointer;
+ struct task_struct *task;
+ int node;
+#ifdef CONFIG_SMP
+ int i;
+#endif
+ memleak_scan_block((void *) pointer->pointer,
+ (void *) (pointer->pointer + pointer->size));
+static void *memleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct list_head *n = ((struct memleak_pointer *) v)->pointer_list.next;
+
+ ++(*pos);
+
+ return (n != &pointer_list)
+ ? list_entry(n, struct memleak_pointer, pointer_list)
+ : NULL;
+int __init memleak_init(void)
+{
+ struct memleak_offset *ml_off;
+ int aliases = 0;
+ unsigned long flags;
+
+ printk(KERN_INFO "Kernel memory leak detector\n");
+#if 0
+ /* make some orphan pointers for testing */
+ kmalloc(32, GFP_KERNEL);
+ kmalloc(32, GFP_KERNEL);
+ kmem_cache_alloc(pointer_cache, GFP_ATOMIC);
+ kmem_cache_alloc(pointer_cache, GFP_ATOMIC);
+ vmalloc(64);
+ vmalloc(64);
+#endif