All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Catalin Marinas <catalin.marinas@arm.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH 01/14] kmemleak: Add the base support
Date: Mon, 29 Dec 2008 16:23:14 -0800	[thread overview]
Message-ID: <20081229162314.1cc7a549.akpm@linux-foundation.org> (raw)
In-Reply-To: <20081219181302.7778.15966.stgit@pc1117.cambridge.arm.com>

On Fri, 19 Dec 2008 18:13:02 +0000
Catalin Marinas <catalin.marinas@arm.com> wrote:

> 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 unreferenced objects are not freed but only shown in
> /sys/kernel/debug/kmemleak. Enabling this feature introduces an
> overhead to memory allocations.
> 
>
> ...
>
> --- a/init/main.c
> +++ b/init/main.c
> @@ -56,6 +56,7 @@
>  #include <linux/debug_locks.h>
>  #include <linux/debugobjects.h>
>  #include <linux/lockdep.h>
> +#include <linux/kmemleak.h>
>  #include <linux/pid_namespace.h>
>  #include <linux/device.h>
>  #include <linux/kthread.h>
> @@ -653,6 +654,8 @@ asmlinkage void __init start_kernel(void)
>  	enable_debug_pagealloc();
>  	cpu_hotplug_init();
>  	kmem_cache_init();
> +	prio_tree_init();
> +	kmemleak_init();

prio_tree_init() can be moved waaaay early, so we might as well do that
now, rather than just moving it a little bit.

>  	debug_objects_mem_init();
>  	idr_init_cache();
>  	setup_per_cpu_pageset();
> @@ -662,7 +665,6 @@ asmlinkage void __init start_kernel(void)
>  	calibrate_delay();
>  	pidmap_init();
>  	pgtable_cache_init();
> -	prio_tree_init();
>  	anon_vma_init();
>  #ifdef CONFIG_X86
>  	if (efi_enabled)
>
> ...
>
> +#define print_helper(seq, x...)	do {	\
> +	if (seq)			\
> +		seq_printf(seq, x);	\
> +	else				\
> +		pr_info(x);		\
> +} while (0)

grumblemutter.  Evaluates `seq' more than once.

> +static void print_unreferenced(struct seq_file *seq,
> +			       struct kmemleak_object *object)
> +{
> +	char namebuf[KSYM_NAME_LEN + 1] = "";
> +	char *modname;
> +	unsigned long symsize;
> +	int i;
> +
> +	print_helper(seq, "unreferenced object 0x%08lx (size %zu):\n",
> +		     object->pointer, object->size);
> +	print_helper(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
> +		     object->comm, object->pid, object->jiffies);
> +	print_helper(seq, "  backtrace:\n");
> +
> +	for (i = 0; i < object->trace_len; i++) {
> +		unsigned long trace = object->trace[i];
> +		unsigned long offset = 0;
> +
> +		kallsyms_lookup(trace, &symsize, &offset, &modname, namebuf);
> +		print_helper(seq, "    [<%08lx>] %s\n", trace, namebuf);

Can this use the %p magic?

> +	}
> +}
> +
>
> ...
>
> +static void scan_yield(void)
> +{
> +	might_sleep();
> +
> +	if (time_is_before_eq_jiffies(next_scan_yield)) {
> +		schedule();
> +		next_scan_yield = jiffies + jiffies_scan_yield;
> +	}

I bet you could use __ratelimit() here.  Although that probably won't
clarify anything, and it's slower ;)

> +}
> +
> +/*
> + * Memory scanning is a long process and it needs to be interruptable. This
> + * function checks whether such interrupt condition occured.
> + */
> +static int scan_should_stop(void)
> +{
> +	if (!atomic_read(&kmemleak_enabled))
> +		return 1;
> +	/*
> +	 * This function may be called from either process or kthread context,
> +	 * hence the need to check for both stop conditions.
> +	 */
> +	if ((current->mm && signal_pending(current)) ||
> +	    (!current->mm && kthread_should_stop()))
> +		return 1;
> +	return 0;
> +}

	if (current->mm)
		return signal_pending(current);
	else
		return kthread_should_stop();

nicer, no?

>
> ...
>
> +/*
> + * Stop the automatic memory scanning thread. This function must be called
> + * with the kmemleak_mutex held.
> + */
> +void stop_scan_thread(void)
> +{
> +	if (scan_thread) {
> +		kthread_stop(scan_thread);
> +		scan_thread = NULL;
> +	}
> +}

so... why do we need a kernel thread?

We could have (for the sake of argument) a sys_kmemleak_scan() which
does a single scan then returns.  Or something like that.  That way,
userspace directly gets to set the scanning frequency, thread priority,
etc.

>
> ...
>
> +static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
> +			      size_t size, loff_t *ppos)
> +{
> +	char buf[64];
> +	int buf_size;
> +
> +	if (!atomic_read(&kmemleak_enabled))
> +		return -EBUSY;
> +
> +	buf_size = min(size, (sizeof(buf) - 1));
> +	if (copy_from_user(buf, user_buf, buf_size))
> +		return -EFAULT;
> +	buf[buf_size] = 0;

maybe strncpy_from_user()?

> +	if (strncmp(buf, "off", 3) == 0)
> +		kmemleak_disable();
> +	else if (strncmp(buf, "stack=on", 8) == 0)
> +		kmemleak_stack_scan = 1;
> +	else if (strncmp(buf, "stack=off", 9) == 0)
> +		kmemleak_stack_scan = 0;
> +	else if (strncmp(buf, "scan=on", 7) == 0)
> +		start_scan_thread();
> +	else if (strncmp(buf, "scan=off", 8) == 0)
> +		stop_scan_thread();
> +	else if (strncmp(buf, "scan=", 5) == 0) {
> +		unsigned long secs;
> +		int err;
> +
> +		err = strict_strtoul(buf + 5, 0, &secs);
> +		if (err < 0)
> +			return err;
> +		stop_scan_thread();
> +		if (secs) {
> +			jiffies_scan_wait = msecs_to_jiffies(secs * 1000);
> +			start_scan_thread();
> +		}
> +	} else
> +		return -EINVAL;
> +
> +	/* ignore the rest of the buffer, only one command at a time */
> +	*ppos += size;
> +	return size;
> +}
> +
>
> ...
>
> +static void kmemleak_cleanup(void)
> +{
> +	struct task_struct *cleanup_thread;
> +
> +	cleanup_thread = kthread_run(kmemleak_cleanup_thread, NULL,
> +				     "kmemleak-cleanup");

#define TASK_COMM_LEN 16

So the above kernel thread will appear in `ps' output as "kmemleak-cleanu",
won't it?

> +	if (IS_ERR(cleanup_thread))
> +		pr_warning("kmemleak: Failed to create the clean-up thread\n");
> +}
> +
>
> ...
>



  parent reply	other threads:[~2008-12-30  0:23 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-19 18:12 [PATCH 00/14] Kernel memory leak detector Catalin Marinas
2008-12-19 18:13 ` [PATCH 01/14] kmemleak: Add the base support Catalin Marinas
2008-12-19 20:08   ` Pekka Enberg
2008-12-19 22:02     ` Ingo Molnar
2008-12-19 22:14       ` Andrew Morton
2008-12-22 13:05         ` Catalin Marinas
2008-12-30  0:23   ` Andrew Morton [this message]
2008-12-30  7:38     ` Ingo Molnar
2008-12-30  7:44       ` Andrew Morton
2008-12-30  7:52         ` Ingo Molnar
2008-12-30  7:59           ` Andrew Morton
2008-12-30 10:48     ` Catalin Marinas
2008-12-19 18:13 ` [PATCH 02/14] kmemleak: Add documentation on the memory leak detector Catalin Marinas
2008-12-19 18:30   ` Randy Dunlap
2008-12-19 18:13 ` [PATCH 03/14] kmemleak: Add the slab memory allocation/freeing hooks Catalin Marinas
2008-12-19 20:05   ` Pekka Enberg
2008-12-19 18:13 ` [PATCH 04/14] kmemleak: Add the slob " Catalin Marinas
2008-12-19 18:13 ` [PATCH 05/14] kmemleak: Add the slub " Catalin Marinas
2008-12-19 20:05   ` Pekka Enberg
2008-12-19 18:13 ` [PATCH 06/14] kmemleak: Add the vmalloc " Catalin Marinas
2008-12-19 18:13 ` [PATCH 07/14] kmemleak: Add kmemleak_alloc callback from alloc_large_system_hash Catalin Marinas
2008-12-19 18:13 ` [PATCH 08/14] kmemleak: Add modules support Catalin Marinas
2008-12-19 18:13 ` [PATCH 09/14] x86: Provide _sdata in the vmlinux_*.lds.S files Catalin Marinas
2008-12-19 18:13 ` [PATCH 10/14] arm: Provide _sdata and __bss_stop in the vmlinux.lds.S file Catalin Marinas
2008-12-19 18:13 ` [PATCH 11/14] kmemleak: Remove some of the kmemleak false positives Catalin Marinas
2008-12-19 20:15   ` Pekka Enberg
2008-12-22 12:04     ` Catalin Marinas
2008-12-19 18:14 ` [PATCH 12/14] kmemleak: Enable the building of the memory leak detector Catalin Marinas
2008-12-19 18:14 ` [PATCH 13/14] kmemleak: Simple testing module for kmemleak Catalin Marinas
2008-12-19 18:14 ` [PATCH 14/14] kmemleak: Add the corresponding MAINTAINERS entry Catalin Marinas
2008-12-30  0:23 ` [PATCH 00/14] Kernel memory leak detector Andrew Morton
2008-12-30 11:43   ` Catalin Marinas
2009-01-08 22:45 ` Andrew Morton
2009-01-12  9:51   ` Catalin Marinas
2009-01-12 10:21     ` Andrew Morton
2009-01-12 10:33       ` Stephen Rothwell
2009-01-12 11:13         ` Catalin Marinas
2009-01-14 12:30         ` Catalin Marinas
2009-01-14 14:01           ` Stephen Rothwell
2009-01-14 14:50             ` Catalin Marinas
2009-01-15 22:09               ` Mike Snitzer
2009-01-16  9:22                 ` Catalin Marinas
  -- strict thread matches above, loose matches on Subject: below --
2009-04-24 16:40 Catalin Marinas
2009-04-24 16:41 ` [PATCH 01/14] kmemleak: Add the base support Catalin Marinas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081229162314.1cc7a549.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=catalin.marinas@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.