From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35E9FC433B4 for ; Wed, 12 May 2021 12:24:38 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 52EA9613FC for ; Wed, 12 May 2021 12:24:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 52EA9613FC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id B5A496B0036; Wed, 12 May 2021 08:24:36 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id B30366B006E; Wed, 12 May 2021 08:24:36 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 983616B0070; Wed, 12 May 2021 08:24:36 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0008.hostedemail.com [216.40.44.8]) by kanga.kvack.org (Postfix) with ESMTP id 730356B0036 for ; Wed, 12 May 2021 08:24:36 -0400 (EDT) Received: from smtpin36.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 2987DBA02 for ; Wed, 12 May 2021 12:24:36 +0000 (UTC) X-FDA: 78132497352.36.CBA71CD Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) by imf13.hostedemail.com (Postfix) with ESMTP id DA0B0E000884 for ; Wed, 12 May 2021 12:24:19 +0000 (UTC) Received: by mail-pg1-f170.google.com with SMTP id m190so18121615pga.2 for ; Wed, 12 May 2021 05:24:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=M9SHgQkA6z9+stmgw1yEiMeqR1IrXzIGxSJuahzR2ks=; b=cO4tEg49rwJmqSwMwKMOQ1V3js4bIZeu6XKzfwBjg4l2Uk/RCH1KoWbKMXIeoE4TR3 R9gL0QPtTusc3QwqEUWoEH4xq4liMwy0oT8rQCCjdRDpDR/nMRX+A1h8Cnf/iLzLx6oX +Amh8OQdQO8tsfy7DIlLnYyTUmHKBs3RdWjdVmiQc2M+WSJFWXFKLspuweAM9bbpfoyS FOVBz+kTy3BZc3tqn+RGJsdWym3JOImyweY1bKKPLimUa1TSKi1qmoHrUCxOqakJjYQk gbgNoBHS400nv2hOxGeHYSFj/ea5/wIjK33yos798ZEW3rq0QqRZUGIO6ZPlzxl7ZsDM J2EA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=M9SHgQkA6z9+stmgw1yEiMeqR1IrXzIGxSJuahzR2ks=; b=U4bcePeG14aXBMHshhOZGh6kSATC7zv6Cn8GqlURB9lFv2vxJ0tpUIdUNwv0VUcVsm BA1Xt8au9Ru95D6BQtxgR+KNspqba6Tq1Z330UvX+XUQGnGm8Zy37Mf5ovjuwotFDFWo JC2PxJ/qWwXNU597Lsp2yPUJ6mHIFBFZ6kI4KY9bC8XH6n2i6Sp5BNSwYawhcohTlWxF XXmPghSrSsqbyL555fiUaHvYv1iNbNcLWmIvH60a0xmlp1+f58457m1GH/gaEFE8Cxz/ lVAsSaah+qTxp64j7RSnQgaUhGUftD8EVQT0NB34frAJCo2rQqsYQLGXJGYYsV57b25Z oy2A== X-Gm-Message-State: AOAM531iAPdnnAy6vB0PD2svUh5275B0EtYdaQ6Be3xGISyfZoNSIZJT ah9msG2Stsf6ZNEitGQ5uqUMxNZSoinsSNAWQI4= X-Google-Smtp-Source: ABdhPJyngc3AvAxJEkJ2ScTYQcpeSdKth7kND/Z65q6Jn9GEaBveN7VNEh7YxVlX1bS8S54e75rDxDksK88THJqjiIo= X-Received: by 2002:a62:8389:0:b029:27d:28f4:d583 with SMTP id h131-20020a6283890000b029027d28f4d583mr35610484pfe.33.1620822274504; Wed, 12 May 2021 05:24:34 -0700 (PDT) MIME-Version: 1.0 References: <20210511150734.3492-1-glittao@gmail.com> <20210511150734.3492-2-glittao@gmail.com> In-Reply-To: From: Oliver Glitta Date: Wed, 12 May 2021 14:24:23 +0200 Message-ID: Subject: Re: [PATCH v5 2/3] mm/slub, kunit: add a KUnit test for SLUB debugging functionality To: Marco Elver Cc: Andrew Morton , Brendan Higgins , Christoph Lameter , Daniel Latypov , David Rientjes , Joonsoo Kim , KUnit Development , LKML , Linux Memory Management List , Pekka Enberg , Vlastimil Babka , "open list:KERNEL SELFTEST FRAMEWORK" Content-Type: multipart/alternative; boundary="000000000000ea7c3205c22117cd" X-Rspamd-Queue-Id: DA0B0E000884 Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=cO4tEg49; spf=pass (imf13.hostedemail.com: domain of glittao@gmail.com designates 209.85.215.170 as permitted sender) smtp.mailfrom=glittao@gmail.com; dmarc=pass (policy=none) header.from=gmail.com X-Rspamd-Server: rspam04 X-Stat-Signature: 4ocfw3mjf1gmhja5ey5bu8jxyhk4bhz4 Received-SPF: none (gmail.com>: No applicable sender policy available) receiver=imf13; identity=mailfrom; envelope-from=""; helo=mail-pg1-f170.google.com; client-ip=209.85.215.170 X-HE-DKIM-Result: pass/pass X-HE-Tag: 1620822259-714177 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: --000000000000ea7c3205c22117cd Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable ut 11. 5. 2021 o 17:16 Marco Elver nap=C3=ADsal(a): > > On Tue, 11 May 2021 at 17:07, wrote: > > From: Oliver Glitta > > > > SLUB has resiliency_test() function which is hidden behind #ifdef > > SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody > > runs it. KUnit should be a proper replacement for it. > > > > Try changing byte in redzone after allocation and changing > > pointer to next free node, first byte, 50th byte and redzone > > byte. Check if validation finds errors. > > > > There are several differences from the original resiliency test: > > Tests create own caches with known state instead of corrupting > > shared kmalloc caches. > > > > The corruption of freepointer uses correct offset, the original > > resiliency test got broken with freepointer changes. > > > > Scratch changing random byte test, because it does not have > > meaning in this form where we need deterministic results. > > > > Add new option CONFIG_SLUB_KUNIT_TEST in Kconfig. > > Tests next_pointer, first_word and clobber_50th_byte do not run > > with KASAN option on. Because the test deliberately modifies non-allocated > > objects. > > > > Use kunit_resource to count errors in cache and silence bug reports. > > Count error whenever slab_bug() or slab_fix() is called or when > > the count of pages is wrong. > > > > Signed-off-by: Oliver Glitta > > I think I had already reviewed v4, and the changes here are fine: > > Reviewed-by: Marco Elver Thank you again. I=E2=80=99m sorry about, I forgot to add this tags. > Others who had reviewed/acked v4, probably need to re-ack/review. > Note, I think if you addressed the comments and didn't change much > else, you can typically carry the acks/reviews, unless the other > person changed their mind explicitly. > > > --- > > Changes since v4 > > Use two tests with KASAN dependency. > > Remove setting current test during init and exit. > > > > Changes since v3 > > > > Use kunit_resource to silence bug reports and count errors suggested by > > Marco Elver. > > Make the test depends on !KASAN thanks to report from the kernel test robot. > > > > Changes since v2 > > > > Use bit operation & instead of logical && as reported by kernel test > > robot and Dan Carpenter > > > > Changes since v1 > > > > Conversion from kselftest to KUnit test suggested by Marco Elver. > > Error silencing. > > Error counting improvements. > > > > lib/Kconfig.debug | 12 ++++ > > lib/Makefile | 1 + > > lib/slub_kunit.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++ > > mm/slab.h | 1 + > > mm/slub.c | 46 +++++++++++++- > > 5 files changed, 212 insertions(+), 3 deletions(-) > > create mode 100644 lib/slub_kunit.c > > > > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug > > index 678c13967580..7723f58a9394 100644 > > --- a/lib/Kconfig.debug > > +++ b/lib/Kconfig.debug > > @@ -2429,6 +2429,18 @@ config BITS_TEST > > > > If unsure, say N. > > > > +config SLUB_KUNIT_TEST > > + tristate "KUnit test for SLUB cache error detection" if !KUNIT_ALL_TESTS > > + depends on SLUB_DEBUG && KUNIT > > + default KUNIT_ALL_TESTS > > + help > > + This builds SLUB allocator unit test. > > + Tests SLUB cache debugging functionality. > > + For more information on KUnit and unit tests in general please refer > > + to the KUnit documentation in Documentation/dev-tools/kunit/. > > + > > + If unsure, say N. > > + > > config TEST_UDELAY > > tristate "udelay test driver" > > help > > diff --git a/lib/Makefile b/lib/Makefile > > index e11cfc18b6c0..386215dcb0a0 100644 > > --- a/lib/Makefile > > +++ b/lib/Makefile > > @@ -353,5 +353,6 @@ obj-$(CONFIG_LIST_KUNIT_TEST) +=3D list-test.o > > obj-$(CONFIG_LINEAR_RANGES_TEST) +=3D test_linear_ranges.o > > obj-$(CONFIG_BITS_TEST) +=3D test_bits.o > > obj-$(CONFIG_CMDLINE_KUNIT_TEST) +=3D cmdline_kunit.o > > +obj-$(CONFIG_SLUB_KUNIT_TEST) +=3D slub_kunit.o > > > > obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) +=3D devmem_is_allowed.o > > diff --git a/lib/slub_kunit.c b/lib/slub_kunit.c > > new file mode 100644 > > index 000000000000..f28965f64ef6 > > --- /dev/null > > +++ b/lib/slub_kunit.c > > @@ -0,0 +1,155 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "../mm/slab.h" > > + > > +static struct kunit_resource resource; > > +static int slab_errors; > > + > > +static void test_clobber_zone(struct kunit *test) > > +{ > > + struct kmem_cache *s =3D kmem_cache_create("TestSlub_RZ_alloc", 64, 0, > > + SLAB_RED_ZONE, NULL); > > + u8 *p =3D kmem_cache_alloc(s, GFP_KERNEL); > > + > > + kasan_disable_current(); > > + p[64] =3D 0x12; > > + > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 2, slab_errors); > > + > > + kasan_enable_current(); > > + kmem_cache_free(s, p); > > + kmem_cache_destroy(s); > > +} > > + > > +#ifndef CONFIG_KASAN > > +static void test_next_pointer(struct kunit *test) > > +{ > > + struct kmem_cache *s =3D kmem_cache_create("TestSlub_next_ptr_free", 64, 0, > > + SLAB_POISON, NULL); > > + u8 *p =3D kmem_cache_alloc(s, GFP_KERNEL); > > + unsigned long tmp; > > + unsigned long *ptr_addr; > > + > > + kmem_cache_free(s, p); > > + > > + ptr_addr =3D (unsigned long *)(p + s->offset); > > + tmp =3D *ptr_addr; > > + p[s->offset] =3D 0x12; > > + > > + /* > > + * Expecting three errors. > > + * One for the corrupted freechain and the other one for the wrong > > + * count of objects in use. The third error is fixing broken cache. > > + */ > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 3, slab_errors); > > + > > + /* > > + * Try to repair corrupted freepointer. > > + * Still expecting two errors. The first for the wrong count > > + * of objects in use. > > + * The second error is for fixing broken cache. > > + */ > > + *ptr_addr =3D tmp; > > + slab_errors =3D 0; > > + > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 2, slab_errors); > > + > > + /* > > + * Previous validation repaired the count of objects in use. > > + * Now expecting no error. > > + */ > > + slab_errors =3D 0; > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 0, slab_errors); > > + > > + kmem_cache_destroy(s); > > +} > > + > > +static void test_first_word(struct kunit *test) > > +{ > > + struct kmem_cache *s =3D kmem_cache_create("TestSlub_1th_word_free", 64, 0, > > + SLAB_POISON, NULL); > > + u8 *p =3D kmem_cache_alloc(s, GFP_KERNEL); > > + > > + kmem_cache_free(s, p); > > + *p =3D 0x78; > > + > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 2, slab_errors); > > + > > + kmem_cache_destroy(s); > > +} > > + > > +static void test_clobber_50th_byte(struct kunit *test) > > +{ > > + struct kmem_cache *s =3D kmem_cache_create("TestSlub_50th_word_free", 64, 0, > > + SLAB_POISON, NULL); > > + u8 *p =3D kmem_cache_alloc(s, GFP_KERNEL); > > + > > + kmem_cache_free(s, p); > > + p[50] =3D 0x9a; > > + > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 2, slab_errors); > > + > > + kmem_cache_destroy(s); > > +} > > +#endif > > + > > +static void test_clobber_redzone_free(struct kunit *test) > > +{ > > + struct kmem_cache *s =3D kmem_cache_create("TestSlub_RZ_free", 64, 0, > > + SLAB_RED_ZONE, NULL); > > + u8 *p =3D kmem_cache_alloc(s, GFP_KERNEL); > > + > > + kasan_disable_current(); > > + kmem_cache_free(s, p); > > + p[64] =3D 0xab; > > + > > + validate_slab_cache(s); > > + KUNIT_EXPECT_EQ(test, 2, slab_errors); > > + > > + kasan_enable_current(); > > + kmem_cache_destroy(s); > > +} > > + > > +static int test_init(struct kunit *test) > > +{ > > + slab_errors =3D 0; > > + > > + kunit_add_named_resource(test, NULL, NULL, &resource, > > + "slab_errors", &slab_errors); > > + return 0; > > +} > > + > > +static void test_exit(struct kunit *test) {} > > Does removing test_exit() and not setting it below work? Yes this works. Thank you for that. I try to remove function but I didn't think about not setting it, so it didn't work. I will fix it. > > +static struct kunit_case test_cases[] =3D { > > + KUNIT_CASE(test_clobber_zone), > > + > > +#ifndef CONFIG_KASAN > > + KUNIT_CASE(test_next_pointer), > > + KUNIT_CASE(test_first_word), > > + KUNIT_CASE(test_clobber_50th_byte), > > +#endif > > + > > + KUNIT_CASE(test_clobber_redzone_free), > > + {} > > This is better, and tells us which tests exactly were the ones causing > problems with KASAN. > > > > +}; > > + > > +static struct kunit_suite test_suite =3D { > > + .name =3D "slub_test", > > + .init =3D test_init, > > + .exit =3D test_exit, > > + .test_cases =3D test_cases, > > +}; > > +kunit_test_suite(test_suite); > > + > > +MODULE_LICENSE("GPL"); > > diff --git a/mm/slab.h b/mm/slab.h > > index 18c1927cd196..9b690fa44cae 100644 > > --- a/mm/slab.h > > +++ b/mm/slab.h > > @@ -215,6 +215,7 @@ DECLARE_STATIC_KEY_TRUE(slub_debug_enabled); > > DECLARE_STATIC_KEY_FALSE(slub_debug_enabled); > > #endif > > extern void print_tracking(struct kmem_cache *s, void *object); > > +long validate_slab_cache(struct kmem_cache *s); > > #else > > static inline void print_tracking(struct kmem_cache *s, void *object) > > { > > diff --git a/mm/slub.c b/mm/slub.c > > index feda53ae62ba..985fd6ef033c 100644 > > --- a/mm/slub.c > > +++ b/mm/slub.c > > @@ -35,6 +35,7 @@ > > #include > > #include > > #include > > +#include > > > > #include > > > > @@ -447,6 +448,26 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page, > > static unsigned long object_map[BITS_TO_LONGS(MAX_OBJS_PER_PAGE)]; > > static DEFINE_SPINLOCK(object_map_lock); > > > > +#if IS_ENABLED(CONFIG_KUNIT) > > +static bool slab_add_kunit_errors(void) > > +{ > > + struct kunit_resource *resource; > > + > > + if (likely(!current->kunit_test)) > > + return false; > > + > > + resource =3D kunit_find_named_resource(current->kunit_test, "slab_errors"); > > + if (!resource) > > + return false; > > + > > + (*(int *)resource->data)++; > > + kunit_put_resource(resource); > > + return true; > > +} > > +#else > > +static inline bool slab_add_kunit_errors(void) { return false; } > > +#endif > > + > > /* > > * Determine a map of object in use on a page. > > * > > @@ -677,6 +698,9 @@ static void slab_fix(struct kmem_cache *s, char *fmt, ...) > > struct va_format vaf; > > va_list args; > > > > + if (slab_add_kunit_errors()) > > + return; > > + > > va_start(args, fmt); > > vaf.fmt =3D fmt; > > vaf.va =3D &args; > > @@ -740,6 +764,9 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) > > void object_err(struct kmem_cache *s, struct page *page, > > u8 *object, char *reason) > > { > > + if (slab_add_kunit_errors()) > > + return; > > + > > slab_bug(s, "%s", reason); > > print_trailer(s, page, object); > > } > > @@ -750,6 +777,9 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page, > > va_list args; > > char buf[100]; > > > > + if (slab_add_kunit_errors()) > > + return; > > + > > va_start(args, fmt); > > vsnprintf(buf, sizeof(buf), fmt, args); > > va_end(args); > > @@ -799,12 +829,16 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, > > while (end > fault && end[-1] =3D=3D value) > > end--; > > > > + if (slab_add_kunit_errors()) > > + goto skip_bug_print; > > + > > slab_bug(s, "%s overwritten", what); > > pr_err("0x%p-0x%p @offset=3D%tu. First byte 0x%x instead of 0x%x\n", > > fault, end - 1, fault - addr, > > fault[0], value); > > print_trailer(s, page, object); > > > > +skip_bug_print: > > restore_bytes(s, what, value, fault, end); > > return 0; > > } > > @@ -4662,9 +4696,11 @@ static int validate_slab_node(struct kmem_cache *s, > > validate_slab(s, page); > > count++; > > } > > - if (count !=3D n->nr_partial) > > + if (count !=3D n->nr_partial) { > > pr_err("SLUB %s: %ld partial slabs counted but counter=3D%ld\n", > > s->name, count, n->nr_partial); > > + slab_add_kunit_errors(); > > + } > > > > if (!(s->flags & SLAB_STORE_USER)) > > goto out; > > @@ -4673,16 +4709,18 @@ static int validate_slab_node(struct kmem_cache *s, > > validate_slab(s, page); > > count++; > > } > > - if (count !=3D atomic_long_read(&n->nr_slabs)) > > + if (count !=3D atomic_long_read(&n->nr_slabs)) { > > pr_err("SLUB: %s %ld slabs counted but counter=3D%ld\n"= , > > s->name, count, atomic_long_read(&n->nr_slabs)); > > + slab_add_kunit_errors(); > > + } > > > > out: > > spin_unlock_irqrestore(&n->list_lock, flags); > > return count; > > } > > > > -static long validate_slab_cache(struct kmem_cache *s) > > +long validate_slab_cache(struct kmem_cache *s) > > { > > int node; > > unsigned long count =3D 0; > > @@ -4694,6 +4732,8 @@ static long validate_slab_cache(struct kmem_cache *s) > > > > return count; > > } > > +EXPORT_SYMBOL(validate_slab_cache); > > + > > /* > > * Generate lists of code addresses where slabcache objects are allocated > > * and freed. > > -- > > 2.31.1.272.g89b43f80a5 > > --000000000000ea7c3205c22117cd Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
ut 11. 5. 2021 o 17:16 Marco Elver <elver@google.com> nap=C3=ADsal(a):
=
>
> On Tue, 11 May 2021 at 17:07, <glittao@gmail.com> wrote:
> > From: Oliver Glitta <glittao@gmail.com>
> >
> > SLUB has resiliency_test() function which is hidden behind #ifdef=
> > SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
> > runs it. KUnit should be a proper replacement for it.
> >
> > Try changing byte in redzone after allocation and changing
> > pointer to next free node, first byte, 50th byte and redzone
> > byte. Check if validation finds errors.
> >
> > There are several differences from the original resiliency test:<= br> > > Tests create own caches with known state instead of corrupting > > shared kmalloc caches.
> >
> > The corruption of freepointer uses correct offset, the original > > resiliency test got broken with freepointer changes.
> >
> > Scratch changing random byte test, because it does not have
> > meaning in this form where we need deterministic results.
> >
> > Add new option CONFIG_SLUB_KUNIT_TEST in Kconfig.
> > Tests next_pointer, first_word and clobber_50th_byte do not run > > with KASAN option on. Because the test deliberately modifies non-= allocated
> > objects.
> >
> > Use kunit_resource to count errors in cache and silence bug repor= ts.
> > Count error whenever slab_bug() or slab_fix() is called or when > > the count of pages is wrong.
> >
> > Signed-off-by: Oliver Glitta <glittao@gmail.com>
>
> I think I had already reviewed v4, and the changes here are fine:
>
> Reviewed-by: Marco Elver <elver@google.com>

Thank you again.

I=E2=80= =99m sorry about, I forgot to add this tags.=C2=A0

> Others who had reviewed/acked v4, probably need to re-ack/review.
> Note, I think if you addressed the comments and didn't change much=
> else, you can typically carry the acks/reviews, unless the other
> person changed their mind explicitly.
>
> > ---
> > Changes since v4
> > Use two tests with KASAN dependency.
> > Remove setting current test during init and exit.
> >
> > Changes since v3
> >
> > Use kunit_resource to silence bug reports and count errors sugges= ted by
> > Marco Elver.
> > Make the test depends on !KASAN thanks to report from the kernel = test robot.
> >
> > Changes since v2
> >
> > Use bit operation & instead of logical && as reported= by kernel test
> > robot and Dan Carpenter
> >
> > Changes since v1
> >
> > Conversion from kselftest to KUnit test suggested by Marco Elver.=
> > Error silencing.
> > Error counting improvements.
> >
> >=C2=A0 lib/Kconfig.debug |=C2=A0 12 ++++
> >=C2=A0 lib/Makefile=C2=A0 =C2=A0 =C2=A0 |=C2=A0 =C2=A01 +
> >=C2=A0 lib/slub_kunit.c=C2=A0 | 155 ++++++++++++++++++++++++++++++= ++++++++++++++++
> >=C2=A0 mm/slab.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A01 = +
> >=C2=A0 mm/slub.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 46 +++++= ++++++++-
> >=C2=A0 5 files changed, 212 insertions(+), 3 deletions(-)
> >=C2=A0 create mode 100644 lib/slub_kunit.c
> >
> > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> > index 678c13967580..7723f58a9394 100644
> > --- a/lib/Kconfig.debug
> > +++ b/lib/Kconfig.debug
> > @@ -2429,6 +2429,18 @@ config BITS_TEST
> >
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0If unsure, say N.
> >
> > +config SLUB_KUNIT_TEST
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0tristate "KUnit test for SLUB ca= che error detection" if !KUNIT_ALL_TESTS
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0depends on SLUB_DEBUG && KUNI= T
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0default KUNIT_ALL_TESTS
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0help
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This builds SLUB allocator uni= t test.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Tests SLUB cache debugging fun= ctionality.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0For more information on KUnit = and unit tests in general please refer
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0to the KUnit documentation in = Documentation/dev-tools/kunit/.
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0If unsure, say N.
> > +
> >=C2=A0 config TEST_UDELAY
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tristate "udelay test drive= r"
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0help
> > diff --git a/lib/Makefile b/lib/Makefile
> > index e11cfc18b6c0..386215dcb0a0 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -353,5 +353,6 @@ obj-$(CONFIG_LIST_KUNIT_TEST) +=3D list-test.= o
> >=C2=A0 obj-$(CONFIG_LINEAR_RANGES_TEST) +=3D test_linear_ranges.o<= br> > >=C2=A0 obj-$(CONFIG_BITS_TEST) +=3D test_bits.o
> >=C2=A0 obj-$(CONFIG_CMDLINE_KUNIT_TEST) +=3D cmdline_kunit.o
> > +obj-$(CONFIG_SLUB_KUNIT_TEST) +=3D slub_kunit.o
> >
> >=C2=A0 obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) +=3D devmem_is_= allowed.o
> > diff --git a/lib/slub_kunit.c b/lib/slub_kunit.c
> > new file mode 100644
> > index 000000000000..f28965f64ef6
> > --- /dev/null
> > +++ b/lib/slub_kunit.c
> > @@ -0,0 +1,155 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +#include <kunit/test.h>
> > +#include <linux/mm.h>
> > +#include <linux/slab.h>
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include "../mm/slab.h"
> > +
> > +static struct kunit_resource resource;
> > +static int slab_errors;
> > +
> > +static void test_clobber_zone(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kmem_cache *s =3D kmem_cache_c= reate("TestSlub_RZ_alloc", 64, 0,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SLAB_RED_ZONE, NULL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0u8 *p =3D kmem_cache_alloc(s, GFP_KER= NEL);
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kasan_disable_current();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0p[64] =3D 0x12;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 2, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kasan_enable_current();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_free(s, p);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_destroy(s);
> > +}
> > +
> > +#ifndef CONFIG_KASAN
> > +static void test_next_pointer(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kmem_cache *s =3D kmem_cache_c= reate("TestSlub_next_ptr_free", 64, 0,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SLAB_POISON, NULL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0u8 *p =3D kmem_cache_alloc(s, GFP_KER= NEL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned long tmp;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned long *ptr_addr;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_free(s, p);
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0ptr_addr =3D (unsigned long *)(p + s-= >offset);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0tmp =3D *ptr_addr;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0p[s->offset] =3D 0x12;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * Expecting three errors.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * One for the corrupted freechain an= d the other one for the wrong
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * count of objects in use. The third= error is fixing broken cache.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 3, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * Try to repair corrupted freepointe= r.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * Still expecting two errors. The fi= rst for the wrong count
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * of objects in use.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * The second error is for fixing bro= ken cache.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0*ptr_addr =3D tmp;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0slab_errors =3D 0;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 2, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * Previous validation repaired the c= ount of objects in use.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 * Now expecting no error.
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0slab_errors =3D 0;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 0, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_destroy(s);
> > +}
> > +
> > +static void test_first_word(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kmem_cache *s =3D kmem_cache_c= reate("TestSlub_1th_word_free", 64, 0,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SLAB_POISON, NULL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0u8 *p =3D kmem_cache_alloc(s, GFP_KER= NEL);
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_free(s, p);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0*p =3D 0x78;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 2, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_destroy(s);
> > +}
> > +
> > +static void test_clobber_50th_byte(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kmem_cache *s =3D kmem_cache_c= reate("TestSlub_50th_word_free", 64, 0,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SLAB_POISON, NULL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0u8 *p =3D kmem_cache_alloc(s, GFP_KER= NEL);
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_free(s, p);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0p[50] =3D 0x9a;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 2, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_destroy(s);
> > +}
> > +#endif
> > +
> > +static void test_clobber_redzone_free(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kmem_cache *s =3D kmem_cache_c= reate("TestSlub_RZ_free", 64, 0,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SLAB_RED_ZONE, NULL);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0u8 *p =3D kmem_cache_alloc(s, GFP_KER= NEL);
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kasan_disable_current();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_free(s, p);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0p[64] =3D 0xab;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0validate_slab_cache(s);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_EXPECT_EQ(test, 2, slab_errors)= ;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kasan_enable_current();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kmem_cache_destroy(s);
> > +}
> > +
> > +static int test_init(struct kunit *test)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0slab_errors =3D 0;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kunit_add_named_resource(test, NULL, = NULL, &resource,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0"slab_errors", &slab_errors);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> > +}
> > +
> > +static void test_exit(struct kunit *test) {}
>
> Does removing test_exit() and not setting it below work?

Yes this works. Thank you for that. I try to remove function but I didn'= ;t think about not setting it, so it didn't work. I will fix it.=C2=A0<= /div>

> > +static struct kunit_case test_cases[] =3D {
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_CASE(test_clobber_zone),
> > +
> > +#ifndef CONFIG_KASAN
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_CASE(test_next_pointer),
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_CASE(test_first_word),
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_CASE(test_clobber_50th_byte), > > +#endif
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0KUNIT_CASE(test_clobber_redzone_free)= ,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0{}
>
> This is better, and tells us which tests exactly were the ones causing=
> problems with KASAN.
>
>
> > +};
> > +
> > +static struct kunit_suite test_suite =3D {
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0.name =3D "slub_test",
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0.init =3D test_init,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0.exit =3D test_exit,
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0.test_cases =3D test_cases,
> > +};
> > +kunit_test_suite(test_suite);
> > +
> > +MODULE_LICENSE("GPL");
> > diff --git a/mm/slab.h b/mm/slab.h
> > index 18c1927cd196..9b690fa44cae 100644
> > --- a/mm/slab.h
> > +++ b/mm/slab.h
> > @@ -215,6 +215,7 @@ DECLARE_STATIC_KEY_TRUE(slub_debug_enabled);<= br> > >=C2=A0 DECLARE_STATIC_KEY_FALSE(slub_debug_enabled);
> >=C2=A0 #endif
> >=C2=A0 extern void print_tracking(struct kmem_cache *s, void *obje= ct);
> > +long validate_slab_cache(struct kmem_cache *s);
> >=C2=A0 #else
> >=C2=A0 static inline void print_tracking(struct kmem_cache *s, voi= d *object)
> >=C2=A0 {
> > diff --git a/mm/slub.c b/mm/slub.c
> > index feda53ae62ba..985fd6ef033c 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -35,6 +35,7 @@
> >=C2=A0 #include <linux/prefetch.h>
> >=C2=A0 #include <linux/memcontrol.h>
> >=C2=A0 #include <linux/random.h>
> > +#include <kunit/test.h>
> >
> >=C2=A0 #include <trace/events/kmem.h>
> >
> > @@ -447,6 +448,26 @@ static inline bool cmpxchg_double_slab(struc= t kmem_cache *s, struct page *page,
> >=C2=A0 static unsigned long object_map[BITS_TO_LONGS(MAX_OBJS_PER_= PAGE)];
> >=C2=A0 static DEFINE_SPINLOCK(object_map_lock);
> >
> > +#if IS_ENABLED(CONFIG_KUNIT)
> > +static bool slab_add_kunit_errors(void)
> > +{
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0struct kunit_resource *resource;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (likely(!current->kunit_test))<= br> > > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return fa= lse;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0resource =3D kunit_find_named_resourc= e(current->kunit_test, "slab_errors");
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (!resource)
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return fa= lse;
> > +
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0(*(int *)resource->data)++;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0kunit_put_resource(resource);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0return true;
> > +}
> > +#else
> > +static inline bool slab_add_kunit_errors(void) { return false; }=
> > +#endif
> > +
> >=C2=A0 /*
> >=C2=A0 =C2=A0* Determine a map of object in use on a page.
> >=C2=A0 =C2=A0*
> > @@ -677,6 +698,9 @@ static void slab_fix(struct kmem_cache *s, ch= ar *fmt, ...)
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct va_format vaf;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0va_list args;
> >
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (slab_add_kunit_errors())
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > > +
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0va_start(args, fmt);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vaf.fmt =3D fmt;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vaf.va =3D &args;
> > @@ -740,6 +764,9 @@ static void print_trailer(struct kmem_cache *= s, struct page *page, u8 *p)
> >=C2=A0 void object_err(struct kmem_cache *s, struct page *page, > >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0u8 *object, char *reason)
> >=C2=A0 {
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (slab_add_kunit_errors())
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > > +
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0slab_bug(s, "%s", reas= on);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0print_trailer(s, page, object);<= br> > >=C2=A0 }
> > @@ -750,6 +777,9 @@ static __printf(3, 4) void slab_err(struct km= em_cache *s, struct page *page,
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0va_list args;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0char buf[100];
> >
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (slab_add_kunit_errors())
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > > +
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0va_start(args, fmt);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vsnprintf(buf, sizeof(buf), fmt,= args);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0va_end(args);
> > @@ -799,12 +829,16 @@ static int check_bytes_and_report(struct km= em_cache *s, struct page *page,
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0while (end > fault &&= end[-1] =3D=3D value)
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0end-= -;
> >
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (slab_add_kunit_errors())
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto skip= _bug_print;
> > +
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0slab_bug(s, "%s overwritten= ", what);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pr_err("0x%p-0x%p @offset= =3D%tu. First byte 0x%x instead of 0x%x\n",
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0fault, end - 1, fault - addr,
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0fault[0], value);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0print_trailer(s, page, object);<= br> > >
> > +skip_bug_print:
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0restore_bytes(s, what, value, fa= ult, end);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> >=C2=A0 }
> > @@ -4662,9 +4696,11 @@ static int validate_slab_node(struct kmem_= cache *s,
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vali= date_slab(s, page);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0coun= t++;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> > -=C2=A0 =C2=A0 =C2=A0 =C2=A0if (count !=3D n->nr_partial)
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (count !=3D n->nr_partial) { > >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pr_e= rr("SLUB %s: %ld partial slabs counted but counter=3D%ld\n",
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 s->name, count, n->nr_partial);
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0slab_add_= kunit_errors();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
> >
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!(s->flags & SLAB_STO= RE_USER))
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto= out;
> > @@ -4673,16 +4709,18 @@ static int validate_slab_node(struct kmem= _cache *s,
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vali= date_slab(s, page);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0coun= t++;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> > -=C2=A0 =C2=A0 =C2=A0 =C2=A0if (count !=3D atomic_long_read(&= n->nr_slabs))
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (count !=3D atomic_long_read(&= n->nr_slabs)) {
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pr_e= rr("SLUB: %s %ld slabs counted but counter=3D%ld\n",
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 s->name, count, atomic_long_read(&n->nr_slabs))= ;
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0slab_add_= kunit_errors();
> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0}
> >
> >=C2=A0 out:
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0spin_unlock_irqrestore(&n-&g= t;list_lock, flags);
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return count;
> >=C2=A0 }
> >
> > -static long validate_slab_cache(struct kmem_cache *s)
> > +long validate_slab_cache(struct kmem_cache *s)
> >=C2=A0 {
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int node;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned long count =3D 0;
> > @@ -4694,6 +4732,8 @@ static long validate_slab_cache(struct kmem= _cache *s)
> >
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return count;
> >=C2=A0 }
> > +EXPORT_SYMBOL(validate_slab_cache);
> > +
> >=C2=A0 /*
> >=C2=A0 =C2=A0* Generate lists of code addresses where slabcache ob= jects are allocated
> >=C2=A0 =C2=A0* and freed.
> > --
> > 2.31.1.272.g89b43f80a5
> >
--000000000000ea7c3205c22117cd--