]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mm/slub: distinguish and print stack traces in debugfs files
authorOliver Glitta <glittao@gmail.com>
Fri, 21 May 2021 12:11:25 +0000 (14:11 +0200)
committerVlastimil Babka <vbabka@suse.cz>
Wed, 6 Apr 2022 09:03:43 +0000 (11:03 +0200)
Aggregate objects in slub cache by unique stack trace in addition to
caller address when producing contents of debugfs files alloc_traces and
free_traces in debugfs. Also add the stack traces to the debugfs output.
This makes it much more useful to e.g. debug memory leaks.

Signed-off-by: Oliver Glitta <glittao@gmail.com>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Reviewed-and-tested-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
mm/slub.c

index 98c1450c23f0ba4abdac6f583ef6fa500f56d0fb..f2e550e1adf081f1e955ff7c5b95e2223ae08d35 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5064,6 +5064,7 @@ EXPORT_SYMBOL(validate_slab_cache);
  */
 
 struct location {
+       depot_stack_handle_t handle;
        unsigned long count;
        unsigned long addr;
        long long sum_time;
@@ -5116,9 +5117,13 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
 {
        long start, end, pos;
        struct location *l;
-       unsigned long caddr;
+       unsigned long caddr, chandle;
        unsigned long age = jiffies - track->when;
+       depot_stack_handle_t handle = 0;
 
+#ifdef CONFIG_STACKDEPOT
+       handle = READ_ONCE(track->handle);
+#endif
        start = -1;
        end = t->count;
 
@@ -5133,7 +5138,8 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                        break;
 
                caddr = t->loc[pos].addr;
-               if (track->addr == caddr) {
+               chandle = t->loc[pos].handle;
+               if ((track->addr == caddr) && (handle == chandle)) {
 
                        l = &t->loc[pos];
                        l->count++;
@@ -5158,6 +5164,8 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
 
                if (track->addr < caddr)
                        end = pos;
+               else if (track->addr == caddr && handle < chandle)
+                       end = pos;
                else
                        start = pos;
        }
@@ -5180,6 +5188,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
        l->max_time = age;
        l->min_pid = track->pid;
        l->max_pid = track->pid;
+       l->handle = handle;
        cpumask_clear(to_cpumask(l->cpus));
        cpumask_set_cpu(track->cpu, to_cpumask(l->cpus));
        nodes_clear(l->nodes);
@@ -6089,6 +6098,21 @@ static int slab_debugfs_show(struct seq_file *seq, void *v)
                        seq_printf(seq, " nodes=%*pbl",
                                 nodemask_pr_args(&l->nodes));
 
+#ifdef CONFIG_STACKDEPOT
+               {
+                       depot_stack_handle_t handle;
+                       unsigned long *entries;
+                       unsigned int nr_entries, j;
+
+                       handle = READ_ONCE(l->handle);
+                       if (handle) {
+                               nr_entries = stack_depot_fetch(handle, &entries);
+                               seq_puts(seq, "\n");
+                               for (j = 0; j < nr_entries; j++)
+                                       seq_printf(seq, "        %pS\n", (void *)entries[j]);
+                       }
+               }
+#endif
                seq_puts(seq, "\n");
        }