Now disabling kmemleak is an irreversible operation, but sometimes we may need to re-enable kmemleak at runtime. So add a knob to enable kmemleak at runtime: echo on > /sys/kernel/debug/kmemleak Signed-off-by: Jianguo Wu <wujianguo@xxxxxxxxxx> --- Documentation/kmemleak.txt | 3 ++- mm/kmemleak.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index b6e3973..8ec56ad 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -44,7 +44,8 @@ objects to be reported as orphan. Memory scanning parameters can be modified at run-time by writing to the /sys/kernel/debug/kmemleak file. The following parameters are supported: - off - disable kmemleak (irreversible) + off - disable kmemleak + on - enable kmemleak stack=on - enable the task stacks scanning (default) stack=off - disable the tasks stacks scanning scan=on - start the automatic memory scanning thread (default) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 31f01c5..02f292c 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -260,6 +260,7 @@ static struct early_log static int crt_early_log __initdata; static void kmemleak_disable(void); +static void kmemleak_enable(void); /* * Print a warning and dump the stack trace. @@ -1616,9 +1617,6 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, int buf_size; int ret; - if (!atomic_read(&kmemleak_enabled)) - return -EBUSY; - buf_size = min(size, (sizeof(buf) - 1)); if (strncpy_from_user(buf, user_buf, buf_size) < 0) return -EFAULT; @@ -1628,6 +1626,19 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, if (ret < 0) return ret; + if (strncmp(buf, "on", 2) == 0) { + if (atomic_read(&kmemleak_enabled)) + ret = -EBUSY; + else + kmemleak_enable(); + goto out; + } + + if (!atomic_read(&kmemleak_enabled)) { + ret = -EBUSY; + goto out; + } + if (strncmp(buf, "off", 3) == 0) kmemleak_disable(); else if (strncmp(buf, "stack=on", 8) == 0) @@ -1703,7 +1714,7 @@ static DECLARE_WORK(cleanup_work, kmemleak_do_cleanup); /* * Disable kmemleak. No memory allocation/freeing will be traced once this - * function is called. Disabling kmemleak is an irreversible operation. + * function is called. */ static void kmemleak_disable(void) { @@ -1721,6 +1732,24 @@ static void kmemleak_disable(void) pr_info("Kernel memory leak detector disabled\n"); } +static void kmemleak_enable(void) +{ + struct kmemleak_object *object; + + /* free the kmemleak internal objects the previous thread scanned */ + rcu_read_lock(); + list_for_each_entry_rcu(object, &object_list, object_list) + delete_object_full(object->pointer); + rcu_read_unlock(); + + atomic_set(&kmemleak_enabled, 1); + atomic_set(&kmemleak_error, 0); + + start_scan_thread(); + + pr_info("Kernel memory leak detector enabled\n"); +} + /* * Allow boot-time kmemleak disabling (enabled by default). */ -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html