]> git.baikalelectronics.ru Git - kernel.git/commitdiff
Revert "mm/slub: use stackdepot to save stack trace in objects"
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 17 Jul 2021 20:27:00 +0000 (13:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 17 Jul 2021 20:27:00 +0000 (13:27 -0700)
This reverts commit 23cf722e8ecc506b49fe559533811c04ff7c93df.

It's not clear why, but it causes unexplained problems in entirely
unrelated xfs code.  The most likely explanation is some slab
corruption, possibly triggered due to CONFIG_SLUB_DEBUG_ON.  See [1].

It ends up having a few other problems too, like build errors on
arch/arc, and Geert reporting it using much more memory on m68k [3] (it
probably does so elsewhere too, but it is probably just more noticeable
on m68k).

The architecture issues (both build and memory use) are likely just
because this change effectively force-enabled STACKDEPOT (along with a
very bad default value for the stackdepot hash size).  But together with
the xfs issue, this all smells like "this commit was not ready" to me.

Link: https://lore.kernel.org/linux-xfs/YPE3l82acwgI2OiV@infradead.org/
Link: https://lore.kernel.org/lkml/202107150600.LkGNb4Vb-lkp@intel.com/
Link: https://lore.kernel.org/lkml/CAMuHMdW=eoVzM1Re5FVoEN87nKfiLmM2+Ah7eNu2KXEhCvbZyA@mail.gmail.com/
Reported-by: Christoph Hellwig <hch@infradead.org>
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
init/Kconfig
mm/slub.c

index bb0d6e6262b152099ce42488f74640388e3dbdcb..55f9f7738ebb4e2a158f5da59c5dd44dac006996 100644 (file)
@@ -1847,7 +1847,6 @@ config SLUB_DEBUG
        default y
        bool "Enable SLUB debugging support" if EXPERT
        depends on SLUB && SYSFS
-       select STACKDEPOT if STACKTRACE_SUPPORT
        help
          SLUB has extensive debug support features. Disabling these can
          result in significant savings in code size. This also disables
index e1644ac6ee7bf7179046e04552901424b208ed61..090fa14628f925febfe73a5108fa5d7c155605e7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -26,7 +26,6 @@
 #include <linux/cpuset.h>
 #include <linux/mempolicy.h>
 #include <linux/ctype.h>
-#include <linux/stackdepot.h>
 #include <linux/debugobjects.h>
 #include <linux/kallsyms.h>
 #include <linux/kfence.h>
@@ -207,8 +206,8 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
 #define TRACK_ADDRS_COUNT 16
 struct track {
        unsigned long addr;     /* Called from address */
-#ifdef CONFIG_STACKDEPOT
-       depot_stack_handle_t handle;
+#ifdef CONFIG_STACKTRACE
+       unsigned long addrs[TRACK_ADDRS_COUNT]; /* Called from address */
 #endif
        int cpu;                /* Was running on cpu */
        int pid;                /* Pid context */
@@ -612,27 +611,22 @@ static struct track *get_track(struct kmem_cache *s, void *object,
        return kasan_reset_tag(p + alloc);
 }
 
-#ifdef CONFIG_STACKDEPOT
-static depot_stack_handle_t save_stack_depot_trace(gfp_t flags)
-{
-       unsigned long entries[TRACK_ADDRS_COUNT];
-       depot_stack_handle_t handle;
-       unsigned int nr_entries;
-
-       nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 4);
-       handle = stack_depot_save(entries, nr_entries, flags);
-       return handle;
-}
-#endif
-
 static void set_track(struct kmem_cache *s, void *object,
                        enum track_item alloc, unsigned long addr)
 {
        struct track *p = get_track(s, object, alloc);
 
        if (addr) {
-#ifdef CONFIG_STACKDEPOT
-               p->handle = save_stack_depot_trace(GFP_NOWAIT);
+#ifdef CONFIG_STACKTRACE
+               unsigned int nr_entries;
+
+               metadata_access_enable();
+               nr_entries = stack_trace_save(kasan_reset_tag(p->addrs),
+                                             TRACK_ADDRS_COUNT, 3);
+               metadata_access_disable();
+
+               if (nr_entries < TRACK_ADDRS_COUNT)
+                       p->addrs[nr_entries] = 0;
 #endif
                p->addr = addr;
                p->cpu = smp_processor_id();
@@ -659,19 +653,14 @@ static void print_track(const char *s, struct track *t, unsigned long pr_time)
 
        pr_err("%s in %pS age=%lu cpu=%u pid=%d\n",
               s, (void *)t->addr, pr_time - t->when, t->cpu, t->pid);
-#ifdef CONFIG_STACKDEPOT
+#ifdef CONFIG_STACKTRACE
        {
-               depot_stack_handle_t handle;
-               unsigned long *entries;
-               unsigned int nr_entries;
-
-               handle = READ_ONCE(t->handle);
-               if (!handle) {
-                       pr_err("object allocation/free stack trace missing\n");
-               } else {
-                       nr_entries = stack_depot_fetch(handle, &entries);
-                       stack_trace_print(entries, nr_entries, 0);
-               }
+               int i;
+               for (i = 0; i < TRACK_ADDRS_COUNT; i++)
+                       if (t->addrs[i])
+                               pr_err("\t%pS\n", (void *)t->addrs[i]);
+                       else
+                               break;
        }
 #endif
 }
@@ -4045,26 +4034,18 @@ void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page)
        objp = fixup_red_left(s, objp);
        trackp = get_track(s, objp, TRACK_ALLOC);
        kpp->kp_ret = (void *)trackp->addr;
-#ifdef CONFIG_STACKDEPOT
-       {
-               depot_stack_handle_t handle;
-               unsigned long *entries;
-               unsigned int nr_entries;
-
-               handle = READ_ONCE(trackp->handle);
-               if (handle) {
-                       nr_entries = stack_depot_fetch(handle, &entries);
-                       for (i = 0; i < KS_ADDRS_COUNT && i < nr_entries; i++)
-                               kpp->kp_stack[i] = (void *)entries[i];
-               }
+#ifdef CONFIG_STACKTRACE
+       for (i = 0; i < KS_ADDRS_COUNT && i < TRACK_ADDRS_COUNT; i++) {
+               kpp->kp_stack[i] = (void *)trackp->addrs[i];
+               if (!kpp->kp_stack[i])
+                       break;
+       }
 
-               trackp = get_track(s, objp, TRACK_FREE);
-               handle = READ_ONCE(trackp->handle);
-               if (handle) {
-                       nr_entries = stack_depot_fetch(handle, &entries);
-                       for (i = 0; i < KS_ADDRS_COUNT && i < nr_entries; i++)
-                               kpp->kp_free_stack[i] = (void *)entries[i];
-               }
+       trackp = get_track(s, objp, TRACK_FREE);
+       for (i = 0; i < KS_ADDRS_COUNT && i < TRACK_ADDRS_COUNT; i++) {
+               kpp->kp_free_stack[i] = (void *)trackp->addrs[i];
+               if (!kpp->kp_free_stack[i])
+                       break;
        }
 #endif
 #endif