Loading mm/slub.c +99 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,10 @@ #include <linux/jhash.h> #endif #ifdef CONFIG_SLUB_DEBUG #include <linux/debugfs.h> #endif #include "internal.h" /* Loading Loading @@ -6084,6 +6088,85 @@ struct saved_alias { static struct saved_alias *alias_list; #ifdef CONFIG_SLUB_DEBUG static struct dentry *slab_debugfs_top; static int alloc_trace_locations(struct seq_file *seq, struct kmem_cache *s, enum track_item alloc) { unsigned long i; struct loc_track t = { 0, 0, NULL }; int node; unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * sizeof(unsigned long), GFP_KERNEL); struct kmem_cache_node *n; if (!map || !alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location), GFP_KERNEL)) { kfree(map); return -ENOMEM; } /* Push back cpu slabs */ flush_all(s); for_each_kmem_cache_node(s, node, n) { unsigned long flags; struct page *page; if (!atomic_long_read(&n->nr_slabs)) continue; spin_lock_irqsave(&n->list_lock, flags); list_for_each_entry(page, &n->partial, lru) process_slab(&t, s, page, alloc, map); list_for_each_entry(page, &n->full, lru) process_slab(&t, s, page, alloc, map); spin_unlock_irqrestore(&n->list_lock, flags); } for (i = 0; i < t.count; i++) { struct location *l = &t.loc[i]; seq_printf(seq, "alloc_list: call_site=%pS count=%zu object_size=%zu slab_size=%zu slab_name=%s\n", l->addr, l->count, s->object_size, s->size, s->name); } free_loc_track(&t); kfree(map); return 0; } static int slab_debug_alloc_trace(struct seq_file *seq, void *ignored) { struct kmem_cache *slab; list_for_each_entry(slab, &slab_caches, list) { if (!(slab->flags & SLAB_STORE_USER)) continue; alloc_trace_locations(seq, slab, TRACK_ALLOC); } return 0; } static int slab_debug_alloc_trace_open(struct inode *inode, struct file *file) { return single_open(file, slab_debug_alloc_trace, inode->i_private); } static const struct file_operations slab_debug_alloc_fops = { .open = slab_debug_alloc_trace_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; #endif static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; Loading Loading @@ -6213,6 +6296,22 @@ static int __init slab_sysfs_init(void) s->name); } #ifdef CONFIG_SLUB_DEBUG if (slub_debug) { slab_debugfs_top = debugfs_create_dir("slab", NULL); if (!slab_debugfs_top) { pr_err("Couldn't create slab debugfs directory\n"); return -ENODEV; } if (!debugfs_create_file("alloc_trace", 0400, slab_debugfs_top, NULL, &slab_debug_alloc_fops)) { pr_err("Couldn't create slab/tests debugfs directory\n"); return -ENODEV; } } #endif while (alias_list) { struct saved_alias *al = alias_list; Loading Loading
mm/slub.c +99 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,10 @@ #include <linux/jhash.h> #endif #ifdef CONFIG_SLUB_DEBUG #include <linux/debugfs.h> #endif #include "internal.h" /* Loading Loading @@ -6084,6 +6088,85 @@ struct saved_alias { static struct saved_alias *alias_list; #ifdef CONFIG_SLUB_DEBUG static struct dentry *slab_debugfs_top; static int alloc_trace_locations(struct seq_file *seq, struct kmem_cache *s, enum track_item alloc) { unsigned long i; struct loc_track t = { 0, 0, NULL }; int node; unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * sizeof(unsigned long), GFP_KERNEL); struct kmem_cache_node *n; if (!map || !alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location), GFP_KERNEL)) { kfree(map); return -ENOMEM; } /* Push back cpu slabs */ flush_all(s); for_each_kmem_cache_node(s, node, n) { unsigned long flags; struct page *page; if (!atomic_long_read(&n->nr_slabs)) continue; spin_lock_irqsave(&n->list_lock, flags); list_for_each_entry(page, &n->partial, lru) process_slab(&t, s, page, alloc, map); list_for_each_entry(page, &n->full, lru) process_slab(&t, s, page, alloc, map); spin_unlock_irqrestore(&n->list_lock, flags); } for (i = 0; i < t.count; i++) { struct location *l = &t.loc[i]; seq_printf(seq, "alloc_list: call_site=%pS count=%zu object_size=%zu slab_size=%zu slab_name=%s\n", l->addr, l->count, s->object_size, s->size, s->name); } free_loc_track(&t); kfree(map); return 0; } static int slab_debug_alloc_trace(struct seq_file *seq, void *ignored) { struct kmem_cache *slab; list_for_each_entry(slab, &slab_caches, list) { if (!(slab->flags & SLAB_STORE_USER)) continue; alloc_trace_locations(seq, slab, TRACK_ALLOC); } return 0; } static int slab_debug_alloc_trace_open(struct inode *inode, struct file *file) { return single_open(file, slab_debug_alloc_trace, inode->i_private); } static const struct file_operations slab_debug_alloc_fops = { .open = slab_debug_alloc_trace_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; #endif static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; Loading Loading @@ -6213,6 +6296,22 @@ static int __init slab_sysfs_init(void) s->name); } #ifdef CONFIG_SLUB_DEBUG if (slub_debug) { slab_debugfs_top = debugfs_create_dir("slab", NULL); if (!slab_debugfs_top) { pr_err("Couldn't create slab debugfs directory\n"); return -ENODEV; } if (!debugfs_create_file("alloc_trace", 0400, slab_debugfs_top, NULL, &slab_debug_alloc_fops)) { pr_err("Couldn't create slab/tests debugfs directory\n"); return -ENODEV; } } #endif while (alias_list) { struct saved_alias *al = alias_list; Loading