From: Li Zefan <lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
To: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>,
LKML <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
Cgroups <cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: [PATCH v4 2/4] kmemleak: allow freeing internal objects after kmemleak was disabled
Date: Fri, 28 Mar 2014 18:50:34 +0800 [thread overview]
Message-ID: <533553FA.4030009@huawei.com> (raw)
In-Reply-To: <533553E2.7050801-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Currently if kmemleak is disabled, the kmemleak objects can never be
freed, no matter if it's disabled by a user or due to fatal errors.
Those objects can be a big waste of memory.
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
1200264 1197433 99% 0.30K 46164 26 369312K kmemleak_object
With this patch, after kmemleak was disabled you can reclaim memory with:
# echo clear > /sys/kernel/debug/kmemleak
Also inform users about this with a printk.
v4: rephrase the printk string.
v3: Catalin wasn't suggesting to use "off" handler, but he wants to be
able to read memory leaks even when kmemleak is explicitly disabled.
v2: use "off" handler instead of "clear" handler to do this, suggested
by Catalin.
Acked-by: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
Signed-off-by: Li Zefan <lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
Documentation/kmemleak.txt | 15 ++++++++++++++-
mm/kmemleak.c | 46 ++++++++++++++++++++++++++++++++--------------
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt
index 6dc8013..a7563ec 100644
--- a/Documentation/kmemleak.txt
+++ b/Documentation/kmemleak.txt
@@ -51,7 +51,8 @@ Memory scanning parameters can be modified at run-time by writing to the
(default 600, 0 to stop the automatic scanning)
scan - trigger a memory scan
clear - clear list of current memory leak suspects, done by
- marking all current reported unreferenced objects grey
+ marking all current reported unreferenced objects grey,
+ or free all kmemleak objects if kmemleak has been disabled.
dump=<addr> - dump information about the object found at <addr>
Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on
@@ -118,6 +119,18 @@ Then as usual to get your report with:
# cat /sys/kernel/debug/kmemleak
+Freeing kmemleak internal objects
+---------------------------------
+
+To allow access to previosuly found memory leaks after kmemleak has been
+disabled by the user or due to an fatal error, internal kmemleak objects
+won't be freed when kmemleak is disabled, and those objects may occupy
+a large part of physical memory.
+
+In this situation, you may reclaim memory with:
+
+ # echo clear > /sys/kernel/debug/kmemleak
+
Kmemleak API
------------
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 474379e..06cd220 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1600,6 +1600,8 @@ static void kmemleak_clear(void)
kmemleak_found_leaks = false;
}
+static void __kmemleak_do_cleanup(void);
+
/*
* File write operation to configure kmemleak at run-time. The following
* commands can be written to the /sys/kernel/debug/kmemleak file:
@@ -1612,7 +1614,8 @@ static void kmemleak_clear(void)
* disable it)
* scan - trigger a memory scan
* clear - mark all current reported unreferenced kmemleak objects as
- * grey to ignore printing them
+ * grey to ignore printing them, or free all kmemleak objects
+ * if kmemleak has been disabled.
* dump=... - dump information about the object found at the given address
*/
static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
@@ -1622,9 +1625,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;
@@ -1634,6 +1634,19 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
if (ret < 0)
return ret;
+ if (strncmp(buf, "clear", 5) == 0) {
+ if (atomic_read(&kmemleak_enabled))
+ kmemleak_clear();
+ else
+ __kmemleak_do_cleanup();
+ 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)
@@ -1657,8 +1670,6 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
}
} else if (strncmp(buf, "scan", 4) == 0)
kmemleak_scan();
- else if (strncmp(buf, "clear", 5) == 0)
- kmemleak_clear();
else if (strncmp(buf, "dump=", 5) == 0)
ret = dump_str_object_info(buf + 5);
else
@@ -1683,6 +1694,16 @@ static const struct file_operations kmemleak_fops = {
.release = kmemleak_release,
};
+static void __kmemleak_do_cleanup(void)
+{
+ struct kmemleak_object *object;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list)
+ delete_object_full(object->pointer);
+ rcu_read_unlock();
+}
+
/*
* Stop the memory scanning thread and free the kmemleak internal objects if
* no previous scan thread (otherwise, kmemleak may still have some useful
@@ -1690,17 +1711,14 @@ static const struct file_operations kmemleak_fops = {
*/
static void kmemleak_do_cleanup(struct work_struct *work)
{
- struct kmemleak_object *object;
-
mutex_lock(&scan_mutex);
stop_scan_thread();
- if (!kmemleak_found_leaks) {
- rcu_read_lock();
- list_for_each_entry_rcu(object, &object_list, object_list)
- delete_object_full(object->pointer);
- rcu_read_unlock();
- }
+ if (!kmemleak_found_leaks)
+ __kmemleak_do_cleanup();
+ else
+ pr_info("Kmemleak disabled without freeing internal data. "
+ "Reclaim the memory with \"echo clear > /sys/kernel/debug/kmemleak\"\n");
mutex_unlock(&scan_mutex);
}
--
1.8.0.2
WARNING: multiple messages have this Message-ID (diff)
From: Li Zefan <lizefan@huawei.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>,
LKML <linux-kernel@vger.kernel.org>,
Cgroups <cgroups@vger.kernel.org>
Subject: [PATCH v4 2/4] kmemleak: allow freeing internal objects after kmemleak was disabled
Date: Fri, 28 Mar 2014 18:50:34 +0800 [thread overview]
Message-ID: <533553FA.4030009@huawei.com> (raw)
In-Reply-To: <533553E2.7050801@huawei.com>
Currently if kmemleak is disabled, the kmemleak objects can never be
freed, no matter if it's disabled by a user or due to fatal errors.
Those objects can be a big waste of memory.
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
1200264 1197433 99% 0.30K 46164 26 369312K kmemleak_object
With this patch, after kmemleak was disabled you can reclaim memory with:
# echo clear > /sys/kernel/debug/kmemleak
Also inform users about this with a printk.
v4: rephrase the printk string.
v3: Catalin wasn't suggesting to use "off" handler, but he wants to be
able to read memory leaks even when kmemleak is explicitly disabled.
v2: use "off" handler instead of "clear" handler to do this, suggested
by Catalin.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Li Zefan <lizefan@huawei.com>
---
Documentation/kmemleak.txt | 15 ++++++++++++++-
mm/kmemleak.c | 46 ++++++++++++++++++++++++++++++++--------------
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt
index 6dc8013..a7563ec 100644
--- a/Documentation/kmemleak.txt
+++ b/Documentation/kmemleak.txt
@@ -51,7 +51,8 @@ Memory scanning parameters can be modified at run-time by writing to the
(default 600, 0 to stop the automatic scanning)
scan - trigger a memory scan
clear - clear list of current memory leak suspects, done by
- marking all current reported unreferenced objects grey
+ marking all current reported unreferenced objects grey,
+ or free all kmemleak objects if kmemleak has been disabled.
dump=<addr> - dump information about the object found at <addr>
Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on
@@ -118,6 +119,18 @@ Then as usual to get your report with:
# cat /sys/kernel/debug/kmemleak
+Freeing kmemleak internal objects
+---------------------------------
+
+To allow access to previosuly found memory leaks after kmemleak has been
+disabled by the user or due to an fatal error, internal kmemleak objects
+won't be freed when kmemleak is disabled, and those objects may occupy
+a large part of physical memory.
+
+In this situation, you may reclaim memory with:
+
+ # echo clear > /sys/kernel/debug/kmemleak
+
Kmemleak API
------------
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 474379e..06cd220 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1600,6 +1600,8 @@ static void kmemleak_clear(void)
kmemleak_found_leaks = false;
}
+static void __kmemleak_do_cleanup(void);
+
/*
* File write operation to configure kmemleak at run-time. The following
* commands can be written to the /sys/kernel/debug/kmemleak file:
@@ -1612,7 +1614,8 @@ static void kmemleak_clear(void)
* disable it)
* scan - trigger a memory scan
* clear - mark all current reported unreferenced kmemleak objects as
- * grey to ignore printing them
+ * grey to ignore printing them, or free all kmemleak objects
+ * if kmemleak has been disabled.
* dump=... - dump information about the object found at the given address
*/
static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
@@ -1622,9 +1625,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;
@@ -1634,6 +1634,19 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
if (ret < 0)
return ret;
+ if (strncmp(buf, "clear", 5) == 0) {
+ if (atomic_read(&kmemleak_enabled))
+ kmemleak_clear();
+ else
+ __kmemleak_do_cleanup();
+ 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)
@@ -1657,8 +1670,6 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
}
} else if (strncmp(buf, "scan", 4) == 0)
kmemleak_scan();
- else if (strncmp(buf, "clear", 5) == 0)
- kmemleak_clear();
else if (strncmp(buf, "dump=", 5) == 0)
ret = dump_str_object_info(buf + 5);
else
@@ -1683,6 +1694,16 @@ static const struct file_operations kmemleak_fops = {
.release = kmemleak_release,
};
+static void __kmemleak_do_cleanup(void)
+{
+ struct kmemleak_object *object;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(object, &object_list, object_list)
+ delete_object_full(object->pointer);
+ rcu_read_unlock();
+}
+
/*
* Stop the memory scanning thread and free the kmemleak internal objects if
* no previous scan thread (otherwise, kmemleak may still have some useful
@@ -1690,17 +1711,14 @@ static const struct file_operations kmemleak_fops = {
*/
static void kmemleak_do_cleanup(struct work_struct *work)
{
- struct kmemleak_object *object;
-
mutex_lock(&scan_mutex);
stop_scan_thread();
- if (!kmemleak_found_leaks) {
- rcu_read_lock();
- list_for_each_entry_rcu(object, &object_list, object_list)
- delete_object_full(object->pointer);
- rcu_read_unlock();
- }
+ if (!kmemleak_found_leaks)
+ __kmemleak_do_cleanup();
+ else
+ pr_info("Kmemleak disabled without freeing internal data. "
+ "Reclaim the memory with \"echo clear > /sys/kernel/debug/kmemleak\"\n");
mutex_unlock(&scan_mutex);
}
--
1.8.0.2
next prev parent reply other threads:[~2014-03-28 10:50 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-28 10:50 [PATCH v4 1/4] kmemleak: free internal objects only if there're no leaks to be reported Li Zefan
2014-03-28 10:50 ` Li Zefan
[not found] ` <533553E2.7050801-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
2014-03-28 10:50 ` Li Zefan [this message]
2014-03-28 10:50 ` [PATCH v4 2/4] kmemleak: allow freeing internal objects after kmemleak was disabled Li Zefan
2014-03-28 10:50 ` [PATCH v4 3/4] kmemleak: remove redundant code Li Zefan
2014-03-28 10:50 ` Li Zefan
2014-03-28 10:51 ` [PATCH v4 4/4] kmemleak: change some global variables to int Li Zefan
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=533553FA.4030009@huawei.com \
--to=lizefan-hv44wf8li93qt0dzr+alfa@public.gmane.org \
--cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
--cc=catalin.marinas-5wv7dgnIgG8@public.gmane.org \
--cc=cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.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.