Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -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
	  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).


+24 −28
Original line number Original line Diff line number Diff line
@@ -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)


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,
{
{
	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)
	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)
		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,


	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,
	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)
	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)


	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)


	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,


	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)


	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,
	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)
		 * 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)
{
{
	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)
			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)
		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)
	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)
	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);