On Wed, Feb 26, 2025 at 05:12:01PM +0900, Hyesoo Yu wrote: > If a slab object is corrupted or an error occurs in its internal > value, continuing after restoration may cause other side effects. > At this point, it is difficult to debug because the problem occurred > in the past. It is useful to use WARN() to catch errors at the point > of issue because WARN() could trigger panic for system debugging when > panic_on_warn is enabled. WARN() is added where to detect the error > on slab_err and object_err. > > It makes sense to only do the WARN() after printing the logs. slab_err > is splited to __slab_err that calls the WARN() and it is called after > printing logs. > > Changes in v4: > - Remove WARN() in kmem_cache_destroy to remove redundant warning. > > Changes in v3: > - move the WARN from slab_fix to slab_err, object_err and check_obj to > use WARN on all error reporting paths. > > Changes in v2: > - Replace direct calling with BUG_ON with the use of WARN in slab_fix. Same here, please rephrase the changelog without "Changes in vN" in the changelog, and move the patch version changes below "---" line. > Signed-off-by: Hyesoo Yu <hyesoo.yu@xxxxxxxxxxx> > --- Otherwise this change in general looks good to me (with a suggestion below). Please feel free to add: Reviewed-by: Harry Yoo <harry.yoo@xxxxxxxxxx> # Suggestion There's a case where SLUB just calls pr_err() and dump_stack() instead of slab_err() or object_err() in free_consistency_checks(). I would like to add something like this: diff --git a/mm/slub.c b/mm/slub.c index b7660ee85db0..d5609fa63da4 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1022,12 +1022,16 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) { struct va_format vaf; va_list args; + const char *name = "<unknown>"; + + if (s) + name = s->name; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; pr_err("=============================================================================\n"); - pr_err("BUG %s (%s): %pV\n", s->name, print_tainted(), &vaf); + pr_err("BUG %s (%s): %pV\n", name, print_tainted(), &vaf); pr_err("-----------------------------------------------------------------------------\n\n"); va_end(args); } @@ -1628,9 +1632,8 @@ static inline int free_consistency_checks(struct kmem_cache *s, slab_err(s, slab, "Attempt to free object(0x%p) outside of slab", object); } else if (!slab->slab_cache) { - pr_err("SLUB <none>: no slab for object 0x%p.\n", - object); - dump_stack(); + slab_err(NULL, slab, "No slab for object 0x%p", + object); } else object_err(s, slab, object, "page slab pointer corrupt."); -- Cheers, Harry > mm/slab_common.c | 3 --- > mm/slub.c | 31 +++++++++++++++++++------------ > 2 files changed, 19 insertions(+), 15 deletions(-) > > diff --git a/mm/slab_common.c b/mm/slab_common.c > index 477fa471da18..d13f4ffe252b 100644 > --- a/mm/slab_common.c > +++ b/mm/slab_common.c > @@ -517,9 +517,6 @@ void kmem_cache_destroy(struct kmem_cache *s) > kasan_cache_shutdown(s); > > err = __kmem_cache_shutdown(s); > - if (!slab_in_kunit_test()) > - WARN(err, "%s %s: Slab cache still has objects when called from %pS", > - __func__, s->name, (void *)_RET_IP_); > > list_del(&s->list); > > diff --git a/mm/slub.c b/mm/slub.c > index 8c13cd43c0fd..4961eeccf3ad 100644 > --- a/mm/slub.c > +++ b/mm/slub.c > @@ -1096,8 +1096,6 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p) > /* Beginning of the filler is the free pointer */ > print_section(KERN_ERR, "Padding ", p + off, > size_from_object(s) - off); > - > - dump_stack(); > } > > static void object_err(struct kmem_cache *s, struct slab *slab, > @@ -1109,6 +1107,8 @@ static void object_err(struct kmem_cache *s, struct slab *slab, > slab_bug(s, "%s", reason); > print_trailer(s, slab, object); > add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); > + > + WARN_ON(1); > } > > static bool freelist_corrupted(struct kmem_cache *s, struct slab *slab, > @@ -1125,6 +1125,14 @@ static bool freelist_corrupted(struct kmem_cache *s, struct slab *slab, > return false; > } > > +static void __slab_err(struct slab *slab) > +{ > + print_slab_info(slab); > + add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); > + > + WARN_ON(1); > +} > + > static __printf(3, 4) void slab_err(struct kmem_cache *s, struct slab *slab, > const char *fmt, ...) > { > @@ -1138,9 +1146,7 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct slab *slab, > vsnprintf(buf, sizeof(buf), fmt, args); > va_end(args); > slab_bug(s, "%s", buf); > - print_slab_info(slab); > - dump_stack(); > - add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); > + __slab_err(slab); > } > > static void init_object(struct kmem_cache *s, void *object, u8 val) > @@ -1313,9 +1319,10 @@ slab_pad_check(struct kmem_cache *s, struct slab *slab) > while (end > fault && end[-1] == POISON_INUSE) > end--; > > - slab_err(s, slab, "Padding overwritten. 0x%p-0x%p @offset=%tu", > - fault, end - 1, fault - start); > + slab_bug(s, "Padding overwritten. 0x%p-0x%p @offset=%tu", > + fault, end - 1, fault - start); > print_section(KERN_ERR, "Padding ", pad, remainder); > + __slab_err(slab); > > restore_bytes(s, "slab padding", POISON_INUSE, fault, end); > } > @@ -5428,14 +5435,13 @@ static int calculate_sizes(struct kmem_cache_args *args, struct kmem_cache *s) > return !!oo_objects(s->oo); > } > > -static void list_slab_objects(struct kmem_cache *s, struct slab *slab, > - const char *text) > +static void list_slab_objects(struct kmem_cache *s, struct slab *slab) > { > #ifdef CONFIG_SLUB_DEBUG > void *addr = slab_address(slab); > void *p; > > - slab_err(s, slab, text, s->name); > + slab_bug(s, "Objects remaining on __kmem_cache_shutdown()"); > > spin_lock(&object_map_lock); > __fill_map(object_map, s, slab); > @@ -5450,6 +5456,8 @@ static void list_slab_objects(struct kmem_cache *s, struct slab *slab, > } > } > spin_unlock(&object_map_lock); > + > + __slab_err(slab); > #endif > } > > @@ -5470,8 +5478,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) > remove_partial(n, slab); > list_add(&slab->slab_list, &discard); > } else { > - list_slab_objects(s, slab, > - "Objects remaining in %s on __kmem_cache_shutdown()"); > + list_slab_objects(s, slab); > } > } > spin_unlock_irq(&n->list_lock); > -- > 2.28.0 >