Re: [PATCH 2/2] kunit: kmemleak integration

From: Qian Cai
Date: Tue Jul 07 2020 - 15:34:43 EST


On Tue, Jul 07, 2020 at 12:26:52PM -0500, Uriel Guajardo wrote:
> On Mon, Jul 6, 2020 at 6:17 PM Qian Cai <cai@xxxxxx> wrote:
> >
> > On Mon, Jul 06, 2020 at 05:48:21PM -0500, Uriel Guajardo wrote:
> > > On Mon, Jul 6, 2020 at 4:39 PM Qian Cai <cai@xxxxxx> wrote:
> > > >
> > > > On Mon, Jul 06, 2020 at 09:13:09PM +0000, Uriel Guajardo wrote:
> > > > > From: Uriel Guajardo <urielguajardo@xxxxxxxxxx>
> > > > >
> > > > > 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@xxxxxxxxxx>
> > > > > ---
> > > > > 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?
> > > >
> > >
> > > That's correct. Strictly speaking, only DEBUG_KMEMLEAK_MSECS_MIN_AGE
> > > is used to set a default when KUnit is configured.
> > >
> > > There is no concrete reason why these other variables need to be
> > > configurable. At the time of writing this, it seemed to make the most
> > > sense to configure the other configuration options, given that I was
> > > already going to make MSECS_MIN_AGE configurable. It can definitely be
> > > taken out.
> > >
> > > > Even then, how setting DEBUG_KMEMLEAK_MSECS_MIN_AGE=0 not giving too
> > > > many false positives? Kmemleak simply does not work that instantly.
> > > >
> > >
> > > I did not experience this issue, but I see your point.
> > >
> > > An alternative that I was thinking about -- and one that is not in
> > > this patch -- is to wait DEBUG_KMEMLEAK_MSECS_MIN_AGE after each test
> > > case in a test suite, while leaving kmemleak's default value as is. I
> > > was hesitant to do this initially because many KUnit test cases run
> > > quick, so this may result in a lot of time just waiting. But if we
> > > leave it configurable, the user can change this as needed and deal
> > > with the possible false positives.
> >
> > I doubt that is good idea. We don't really want people to start
> > reporting those false positives to the MLs just because some kunit tests
> > starts to flag them. It is wasting everyone's time. Reports from
> > DEBUG_KMEMLEAK_MSECS_MIN_AGE=0 are simply trustful. I don't think there
> > is a way around. Kmemleak was designed to have a lot of
> > waitings/re-scans to be useful not even mentioning kfree_rcu() etc until
> > it is redesigned...
>
> I agree with your statement about false positives.
> Is your suggestion to not make MSECS_MIN_AGE configurable and have
> KUnit wait after each test case? Or are you saying that this will not
> work entirely?
> It seems like kmemleak should be able to work in some fashion under
> KUnit, since it has specific documentation over testing parts of code
> (https://www.kernel.org/doc/html/latest/dev-tools/kmemleak.html#testing-specific-sections-with-kmemleak).

It is going to be tough. It is normal that sometimes when there is a
leak. It needs to rescan a few times to make sure it is stable.
Sometimes, even the real leaks will take quite a while to show up.