From: Qian Cai <cai@lca.pw>
To: Uriel Guajardo <urielguajardojr@gmail.com>
Cc: brendanhiggins@google.com, catalin.marinas@arm.com,
akpm@linux-foundation.org, changbin.du@intel.com,
rdunlap@infradead.org, masahiroy@kernel.org,
0x7f454c46@gmail.com, urielguajardo@google.com, krzk@kernel.org,
kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
kunit-dev@googlegroups.com, linux-mm@kvack.org
Subject: Re: [PATCH 2/2] kunit: kmemleak integration
Date: Mon, 6 Jul 2020 17:39:05 -0400 [thread overview]
Message-ID: <20200706213905.GA1916@lca.pw> (raw)
In-Reply-To: <20200706211309.3314644-3-urielguajardojr@gmail.com>
On Mon, Jul 06, 2020 at 09:13:09PM +0000, Uriel Guajardo wrote:
> From: Uriel Guajardo <urielguajardo@google.com>
>
> Integrate kmemleak into the KUnit testing framework.
>
> Kmemleak will now fail the currently running KUnit test case if it finds
> any memory leaks.
>
> The minimum object age for reporting is set to 0 msecs so that leaks are
> not ignored if the test case finishes too quickly.
>
> Signed-off-by: Uriel Guajardo <urielguajardo@google.com>
> ---
> include/linux/kmemleak.h | 11 +++++++++++
> lib/Kconfig.debug | 26 ++++++++++++++++++++++++++
> lib/kunit/test.c | 36 +++++++++++++++++++++++++++++++++++-
> mm/kmemleak.c | 27 +++++++++++++++++++++------
> 4 files changed, 93 insertions(+), 7 deletions(-)
>
> diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
> index 34684b2026ab..0da427934462 100644
> --- a/include/linux/kmemleak.h
> +++ b/include/linux/kmemleak.h
> @@ -35,6 +35,10 @@ extern void kmemleak_free_part_phys(phys_addr_t phys, size_t size) __ref;
> extern void kmemleak_not_leak_phys(phys_addr_t phys) __ref;
> extern void kmemleak_ignore_phys(phys_addr_t phys) __ref;
>
> +extern ssize_t kmemleak_write(struct file *file,
> + const char __user *user_buf,
> + size_t size, loff_t *ppos);
> +
> static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
> int min_count, slab_flags_t flags,
> gfp_t gfp)
> @@ -120,6 +124,13 @@ static inline void kmemleak_ignore_phys(phys_addr_t phys)
> {
> }
>
> +static inline ssize_t kmemleak_write(struct file *file,
> + const char __user *user_buf,
> + size_t size, loff_t *ppos)
> +{
> + return -1;
> +}
> +
> #endif /* CONFIG_DEBUG_KMEMLEAK */
>
> #endif /* __KMEMLEAK_H */
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 21d9c5f6e7ec..e9c492cb3f4d 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -602,6 +602,32 @@ config DEBUG_KMEMLEAK_MEM_POOL_SIZE
> fully initialised, this memory pool acts as an emergency one
> if slab allocations fail.
>
> +config DEBUG_KMEMLEAK_MAX_TRACE
> + int "Kmemleak stack trace length"
> + depends on DEBUG_KMEMLEAK
> + default 16
> +
> +config DEBUG_KMEMLEAK_MSECS_MIN_AGE
> + int "Minimum object age before reporting in msecs"
> + depends on DEBUG_KMEMLEAK
> + default 0 if KUNIT
> + default 5000
> +
> +config DEBUG_KMEMLEAK_SECS_FIRST_SCAN
> + int "Delay before first scan in secs"
> + depends on DEBUG_KMEMLEAK
> + default 60
> +
> +config DEBUG_KMEMLEAK_SECS_SCAN_WAIT
> + int "Delay before subsequent auto scans in secs"
> + depends on DEBUG_KMEMLEAK
> + default 600
> +
> +config DEBUG_KMEMLEAK_MAX_SCAN_SIZE
> + int "Maximum size of scanned block"
> + depends on DEBUG_KMEMLEAK
> + default 4096
> +
Why do you make those configurable? I don't see anywhere you make use of
them except DEBUG_KMEMLEAK_MSECS_MIN_AGE?
Even then, how setting DEBUG_KMEMLEAK_MSECS_MIN_AGE=0 not giving too
many false positives? Kmemleak simply does not work that instantly.
> config DEBUG_KMEMLEAK_TEST
> tristate "Simple test for the kernel memory leak detector"
> depends on DEBUG_KMEMLEAK && m
> diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> index 8580ed831a8f..8d113a6a214b 100644
> --- a/lib/kunit/test.c
> +++ b/lib/kunit/test.c
> @@ -11,6 +11,7 @@
> #include <linux/kref.h>
> #include <linux/sched/debug.h>
> #include <linux/sched.h>
> +#include <linux/kmemleak.h>
>
> #include "debugfs.h"
> #include "string-stream.h"
> @@ -277,6 +278,27 @@ static void kunit_run_case_cleanup(struct kunit *test,
> kunit_case_internal_cleanup(test);
> }
>
> +/*
> + * Manually scans for memory leaks using the kmemleak tool.
> + *
> + * Any leaks that occurred since the previous scan will be
> + * reported and will cause the currently running test to fail.
> + */
> +static inline void kmemleak_scan(void)
> +{
> + loff_t pos;
> + kmemleak_write(NULL, "scan", 5, &pos);
> +}
> +
> +/*
> + * Turn off the background automatic scan that kmemleak performs upon starting
> + */
> +static inline void kmemleak_automatic_scan_off(void)
> +{
> + loff_t pos;
> + kmemleak_write(NULL, "scan=off", 9, &pos);
> +}
> +
> struct kunit_try_catch_context {
> struct kunit *test;
> struct kunit_suite *suite;
> @@ -290,6 +312,12 @@ static void kunit_try_run_case(void *data)
> struct kunit_suite *suite = ctx->suite;
> struct kunit_case *test_case = ctx->test_case;
>
> + /*
> + * Clear any reported memory leaks since last scan, so that only the
> + * leaks pertaining to the test case remain afterwards.
> + */
> + kmemleak_scan();
> +
> current->kunit_test = test;
>
> /*
> @@ -298,7 +326,12 @@ static void kunit_try_run_case(void *data)
> * thread will resume control and handle any necessary clean up.
> */
> kunit_run_case_internal(test, suite, test_case);
> - /* This line may never be reached. */
> +
> + /* These lines may never be reached. */
> +
> + /* Report any detected memory leaks that occurred in the test case */
> + kmemleak_scan();
> +
> kunit_run_case_cleanup(test, suite);
> }
>
> @@ -388,6 +421,7 @@ static void kunit_init_suite(struct kunit_suite *suite)
> int __kunit_test_suites_init(struct kunit_suite **suites)
> {
> unsigned int i;
> + kmemleak_automatic_scan_off();
>
> for (i = 0; suites[i] != NULL; i++) {
> kunit_init_suite(suites[i]);
> diff --git a/mm/kmemleak.c b/mm/kmemleak.c
> index e362dc3d2028..ad046c77e00c 100644
> --- a/mm/kmemleak.c
> +++ b/mm/kmemleak.c
> @@ -99,15 +99,26 @@
> #include <linux/kasan.h>
> #include <linux/kmemleak.h>
> #include <linux/memory_hotplug.h>
> +#include <kunit/test.h>
>
> /*
> * Kmemleak configuration and common defines.
> */
> -#define MAX_TRACE 16 /* stack trace length */
> -#define MSECS_MIN_AGE 5000 /* minimum object age for reporting */
> -#define SECS_FIRST_SCAN 60 /* delay before the first scan */
> -#define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */
> -#define MAX_SCAN_SIZE 4096 /* maximum size of a scanned block */
> +
> +/* stack trace length */
> +#define MAX_TRACE CONFIG_DEBUG_KMEMLEAK_MAX_TRACE
> +
> +/* minimum object age for reporting */
> +#define MSECS_MIN_AGE CONFIG_DEBUG_KMEMLEAK_MSECS_MIN_AGE
> +
> +/* delay before the first scan */
> +#define SECS_FIRST_SCAN CONFIG_DEBUG_KMEMLEAK_SECS_FIRST_SCAN
> +
> +/* subsequent auto scanning delay */
> +#define SECS_SCAN_WAIT CONFIG_DEBUG_KMEMLEAK_SECS_SCAN_WAIT
> +
> +/* maximum size of a scanned lock */
> +#define MAX_SCAN_SIZE CONFIG_DEBUG_KMEMLEAK_MAX_SCAN_SIZE
>
> #define BYTES_PER_POINTER sizeof(void *)
>
> @@ -1490,6 +1501,7 @@ static void kmemleak_scan(void)
> * Check for new or unreferenced objects modified since the previous
> * scan and color them gray until the next scan.
> */
> +#if (!IS_ENABLED(CONFIG_KUNIT))
> rcu_read_lock();
> list_for_each_entry_rcu(object, &object_list, object_list) {
> raw_spin_lock_irqsave(&object->lock, flags);
> @@ -1502,6 +1514,7 @@ static void kmemleak_scan(void)
> raw_spin_unlock_irqrestore(&object->lock, flags);
> }
> rcu_read_unlock();
> +#endif
>
> /*
> * Re-scan the gray list for modified unreferenced objects.
> @@ -1534,6 +1547,8 @@ static void kmemleak_scan(void)
> rcu_read_unlock();
>
> if (new_leaks) {
> + kunit_fail_current_test();
> +
> kmemleak_found_leaks = true;
>
> pr_info("%d new suspected memory leaks (see /sys/kernel/debug/kmemleak)\n",
> @@ -1764,7 +1779,7 @@ static void __kmemleak_do_cleanup(void);
> * 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,
> +ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
> size_t size, loff_t *ppos)
> {
> char buf[64];
> --
> 2.27.0.212.ge8ba1cc988-goog
>
>
next prev parent reply other threads:[~2020-07-06 21:39 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-06 21:13 [PATCH 0/2] KUnit-Kmemleak Integration Uriel Guajardo
2020-07-06 21:13 ` [PATCH 1/2] kunit: support kunit failures from debugging tools Uriel Guajardo
2020-07-06 21:13 ` [PATCH 2/2] kunit: kmemleak integration Uriel Guajardo
2020-07-06 21:39 ` Qian Cai [this message]
2020-07-06 22:48 ` Uriel Guajardo
2020-07-06 23:17 ` Qian Cai
2020-07-07 17:26 ` Uriel Guajardo
2020-07-07 19:34 ` Qian Cai
-- strict thread matches above, loose matches on Subject: below --
2020-07-06 21:03 [PATCH 0/2] KUnit-Kmemleak Integration Uriel Guajardo
2020-07-06 21:03 ` [PATCH 2/2] kunit: kmemleak integration Uriel Guajardo
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=20200706213905.GA1916@lca.pw \
--to=cai@lca.pw \
--cc=0x7f454c46@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=brendanhiggins@google.com \
--cc=catalin.marinas@arm.com \
--cc=changbin.du@intel.com \
--cc=kernel@vger.kernel.org \
--cc=krzk@kernel.org \
--cc=kunit-dev@googlegroups.com \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=masahiroy@kernel.org \
--cc=rdunlap@infradead.org \
--cc=urielguajardo@google.com \
--cc=urielguajardojr@gmail.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).