Commit 95b3692d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'kmemleak' of git://linux-arm.org/linux-2.6

* 'kmemleak' of git://linux-arm.org/linux-2.6:
  kmemleak: Do not force the slab debugging Kconfig options
  kmemleak: use pr_fmt
parents d26ed650 bf96d1e3
...@@ -340,8 +340,6 @@ config DEBUG_KMEMLEAK ...@@ -340,8 +340,6 @@ config DEBUG_KMEMLEAK
bool "Kernel memory leak detector" bool "Kernel memory leak detector"
depends on DEBUG_KERNEL && EXPERIMENTAL && (X86 || ARM) && \ depends on DEBUG_KERNEL && EXPERIMENTAL && (X86 || ARM) && \
!MEMORY_HOTPLUG !MEMORY_HOTPLUG
select DEBUG_SLAB if SLAB
select SLUB_DEBUG if SLUB
select DEBUG_FS if SYSFS select DEBUG_FS if SYSFS
select STACKTRACE if STACKTRACE_SUPPORT select STACKTRACE if STACKTRACE_SUPPORT
select KALLSYMS select KALLSYMS
...@@ -355,6 +353,9 @@ config DEBUG_KMEMLEAK ...@@ -355,6 +353,9 @@ config DEBUG_KMEMLEAK
allocations. See Documentation/kmemleak.txt for more allocations. See Documentation/kmemleak.txt for more
details. details.
Enabling DEBUG_SLAB or SLUB_DEBUG may increase the chances
of finding leaks due to the slab objects poisoning.
In order to access the kmemleak file, debugfs needs to be In order to access the kmemleak file, debugfs needs to be
mounted (usually at /sys/kernel/debug). mounted (usually at /sys/kernel/debug).
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
* structure. * structure.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -311,7 +313,7 @@ static int unreferenced_object(struct kmemleak_object *object) ...@@ -311,7 +313,7 @@ static int unreferenced_object(struct kmemleak_object *object)
static void print_referenced(struct kmemleak_object *object) static void print_referenced(struct kmemleak_object *object)
{ {
pr_info("kmemleak: referenced object 0x%08lx (size %zu)\n", pr_info("referenced object 0x%08lx (size %zu)\n",
object->pointer, object->size); object->pointer, object->size);
} }
...@@ -320,7 +322,7 @@ static void print_unreferenced(struct seq_file *seq, ...@@ -320,7 +322,7 @@ static void print_unreferenced(struct seq_file *seq,
{ {
int i; int i;
print_helper(seq, "kmemleak: unreferenced object 0x%08lx (size %zu):\n", print_helper(seq, "unreferenced object 0x%08lx (size %zu):\n",
object->pointer, object->size); object->pointer, object->size);
print_helper(seq, " comm \"%s\", pid %d, jiffies %lu\n", print_helper(seq, " comm \"%s\", pid %d, jiffies %lu\n",
object->comm, object->pid, object->jiffies); object->comm, object->pid, object->jiffies);
...@@ -344,7 +346,7 @@ static void dump_object_info(struct kmemleak_object *object) ...@@ -344,7 +346,7 @@ static void dump_object_info(struct kmemleak_object *object)
trace.nr_entries = object->trace_len; trace.nr_entries = object->trace_len;
trace.entries = object->trace; trace.entries = object->trace;
pr_notice("kmemleak: Object 0x%08lx (size %zu):\n", pr_notice("Object 0x%08lx (size %zu):\n",
object->tree_node.start, object->size); object->tree_node.start, object->size);
pr_notice(" comm \"%s\", pid %d, jiffies %lu\n", pr_notice(" comm \"%s\", pid %d, jiffies %lu\n",
object->comm, object->pid, object->jiffies); object->comm, object->pid, object->jiffies);
...@@ -372,7 +374,7 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias) ...@@ -372,7 +374,7 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
object = prio_tree_entry(node, struct kmemleak_object, object = prio_tree_entry(node, struct kmemleak_object,
tree_node); tree_node);
if (!alias && object->pointer != ptr) { if (!alias && object->pointer != ptr) {
kmemleak_warn("kmemleak: Found object by alias"); kmemleak_warn("Found object by alias");
object = NULL; object = NULL;
} }
} else } else
...@@ -467,8 +469,7 @@ static void create_object(unsigned long ptr, size_t size, int min_count, ...@@ -467,8 +469,7 @@ static void create_object(unsigned long ptr, size_t size, int min_count,
object = kmem_cache_alloc(object_cache, gfp & GFP_KMEMLEAK_MASK); object = kmem_cache_alloc(object_cache, gfp & GFP_KMEMLEAK_MASK);
if (!object) { if (!object) {
kmemleak_stop("kmemleak: Cannot allocate a kmemleak_object " kmemleak_stop("Cannot allocate a kmemleak_object structure\n");
"structure\n");
return; return;
} }
...@@ -527,8 +528,8 @@ static void create_object(unsigned long ptr, size_t size, int min_count, ...@@ -527,8 +528,8 @@ static void create_object(unsigned long ptr, size_t size, int min_count,
if (node != &object->tree_node) { if (node != &object->tree_node) {
unsigned long flags; unsigned long flags;
kmemleak_stop("kmemleak: Cannot insert 0x%lx into the object " kmemleak_stop("Cannot insert 0x%lx into the object search tree "
"search tree (already existing)\n", ptr); "(already existing)\n", ptr);
object = lookup_object(ptr, 1); object = lookup_object(ptr, 1);
spin_lock_irqsave(&object->lock, flags); spin_lock_irqsave(&object->lock, flags);
dump_object_info(object); dump_object_info(object);
...@@ -553,7 +554,7 @@ static void delete_object(unsigned long ptr) ...@@ -553,7 +554,7 @@ static void delete_object(unsigned long ptr)
write_lock_irqsave(&kmemleak_lock, flags); write_lock_irqsave(&kmemleak_lock, flags);
object = lookup_object(ptr, 0); object = lookup_object(ptr, 0);
if (!object) { if (!object) {
kmemleak_warn("kmemleak: Freeing unknown object at 0x%08lx\n", kmemleak_warn("Freeing unknown object at 0x%08lx\n",
ptr); ptr);
write_unlock_irqrestore(&kmemleak_lock, flags); write_unlock_irqrestore(&kmemleak_lock, flags);
return; return;
...@@ -588,8 +589,7 @@ static void make_gray_object(unsigned long ptr) ...@@ -588,8 +589,7 @@ static void make_gray_object(unsigned long ptr)
object = find_and_get_object(ptr, 0); object = find_and_get_object(ptr, 0);
if (!object) { if (!object) {
kmemleak_warn("kmemleak: Graying unknown object at 0x%08lx\n", kmemleak_warn("Graying unknown object at 0x%08lx\n", ptr);
ptr);
return; return;
} }
...@@ -610,8 +610,7 @@ static void make_black_object(unsigned long ptr) ...@@ -610,8 +610,7 @@ static void make_black_object(unsigned long ptr)
object = find_and_get_object(ptr, 0); object = find_and_get_object(ptr, 0);
if (!object) { if (!object) {
kmemleak_warn("kmemleak: Blacking unknown object at 0x%08lx\n", kmemleak_warn("Blacking unknown object at 0x%08lx\n", ptr);
ptr);
return; return;
} }
...@@ -634,21 +633,20 @@ static void add_scan_area(unsigned long ptr, unsigned long offset, ...@@ -634,21 +633,20 @@ static void add_scan_area(unsigned long ptr, unsigned long offset,
object = find_and_get_object(ptr, 0); object = find_and_get_object(ptr, 0);
if (!object) { if (!object) {
kmemleak_warn("kmemleak: Adding scan area to unknown " kmemleak_warn("Adding scan area to unknown object at 0x%08lx\n",
"object at 0x%08lx\n", ptr); ptr);
return; return;
} }
area = kmem_cache_alloc(scan_area_cache, gfp & GFP_KMEMLEAK_MASK); area = kmem_cache_alloc(scan_area_cache, gfp & GFP_KMEMLEAK_MASK);
if (!area) { if (!area) {
kmemleak_warn("kmemleak: Cannot allocate a scan area\n"); kmemleak_warn("Cannot allocate a scan area\n");
goto out; goto out;
} }
spin_lock_irqsave(&object->lock, flags); spin_lock_irqsave(&object->lock, flags);
if (offset + length > object->size) { if (offset + length > object->size) {
kmemleak_warn("kmemleak: Scan area larger than object " kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
"0x%08lx\n", ptr);
dump_object_info(object); dump_object_info(object);
kmem_cache_free(scan_area_cache, area); kmem_cache_free(scan_area_cache, area);
goto out_unlock; goto out_unlock;
...@@ -677,8 +675,7 @@ static void object_no_scan(unsigned long ptr) ...@@ -677,8 +675,7 @@ static void object_no_scan(unsigned long ptr)
object = find_and_get_object(ptr, 0); object = find_and_get_object(ptr, 0);
if (!object) { if (!object) {
kmemleak_warn("kmemleak: Not scanning unknown object at " kmemleak_warn("Not scanning unknown object at 0x%08lx\n", ptr);
"0x%08lx\n", ptr);
return; return;
} }
...@@ -699,7 +696,7 @@ static void log_early(int op_type, const void *ptr, size_t size, ...@@ -699,7 +696,7 @@ static void log_early(int op_type, const void *ptr, size_t size,
struct early_log *log; struct early_log *log;
if (crt_early_log >= ARRAY_SIZE(early_log)) { if (crt_early_log >= ARRAY_SIZE(early_log)) {
kmemleak_stop("kmemleak: Early log buffer exceeded\n"); kmemleak_stop("Early log buffer exceeded\n");
return; return;
} }
...@@ -966,7 +963,7 @@ static void kmemleak_scan(void) ...@@ -966,7 +963,7 @@ static void kmemleak_scan(void)
* 1 reference to any object at this point. * 1 reference to any object at this point.
*/ */
if (atomic_read(&object->use_count) > 1) { if (atomic_read(&object->use_count) > 1) {
pr_debug("kmemleak: object->use_count = %d\n", pr_debug("object->use_count = %d\n",
atomic_read(&object->use_count)); atomic_read(&object->use_count));
dump_object_info(object); dump_object_info(object);
} }
...@@ -1062,7 +1059,7 @@ static int kmemleak_scan_thread(void *arg) ...@@ -1062,7 +1059,7 @@ static int kmemleak_scan_thread(void *arg)
{ {
static int first_run = 1; static int first_run = 1;
pr_info("kmemleak: Automatic memory scanning thread started\n"); pr_info("Automatic memory scanning thread started\n");
/* /*
* Wait before the first scan to allow the system to fully initialize. * Wait before the first scan to allow the system to fully initialize.
...@@ -1108,7 +1105,7 @@ static int kmemleak_scan_thread(void *arg) ...@@ -1108,7 +1105,7 @@ static int kmemleak_scan_thread(void *arg)
timeout = schedule_timeout_interruptible(timeout); timeout = schedule_timeout_interruptible(timeout);
} }
pr_info("kmemleak: Automatic memory scanning thread ended\n"); pr_info("Automatic memory scanning thread ended\n");
return 0; return 0;
} }
...@@ -1123,7 +1120,7 @@ void start_scan_thread(void) ...@@ -1123,7 +1120,7 @@ void start_scan_thread(void)
return; return;
scan_thread = kthread_run(kmemleak_scan_thread, NULL, "kmemleak"); scan_thread = kthread_run(kmemleak_scan_thread, NULL, "kmemleak");
if (IS_ERR(scan_thread)) { if (IS_ERR(scan_thread)) {
pr_warning("kmemleak: Failed to create the scan thread\n"); pr_warning("Failed to create the scan thread\n");
scan_thread = NULL; scan_thread = NULL;
} }
} }
...@@ -1367,7 +1364,7 @@ static void kmemleak_cleanup(void) ...@@ -1367,7 +1364,7 @@ static void kmemleak_cleanup(void)
cleanup_thread = kthread_run(kmemleak_cleanup_thread, NULL, cleanup_thread = kthread_run(kmemleak_cleanup_thread, NULL,
"kmemleak-clean"); "kmemleak-clean");
if (IS_ERR(cleanup_thread)) if (IS_ERR(cleanup_thread))
pr_warning("kmemleak: Failed to create the clean-up thread\n"); pr_warning("Failed to create the clean-up thread\n");
} }
/* /*
...@@ -1488,8 +1485,7 @@ static int __init kmemleak_late_init(void) ...@@ -1488,8 +1485,7 @@ static int __init kmemleak_late_init(void)
dentry = debugfs_create_file("kmemleak", S_IRUGO, NULL, NULL, dentry = debugfs_create_file("kmemleak", S_IRUGO, NULL, NULL,
&kmemleak_fops); &kmemleak_fops);
if (!dentry) if (!dentry)
pr_warning("kmemleak: Failed to create the debugfs kmemleak " pr_warning("Failed to create the debugfs kmemleak file\n");
"file\n");
mutex_lock(&kmemleak_mutex); mutex_lock(&kmemleak_mutex);
start_scan_thread(); start_scan_thread();
mutex_unlock(&kmemleak_mutex); mutex_unlock(&kmemleak_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment