Generic Slab statistics module A statistic module for generic slab allocator framework. The creator of a cache must register the slab cache with register_slab() in order for something to show up in slabinfo. Slabinfo only displays the number of slabs used, it will not display the number of objects. Signed-off-by: Christoph Lameter Index: linux-2.6.18-rc4-mm2/fs/proc/proc_misc.c =================================================================== --- linux-2.6.18-rc4-mm2.orig/fs/proc/proc_misc.c 2006-08-23 12:36:59.772706994 -0700 +++ linux-2.6.18-rc4-mm2/fs/proc/proc_misc.c 2006-08-25 19:16:57.337118315 -0700 @@ -389,9 +389,11 @@ static struct file_operations proc_modul }; #endif -#ifdef CONFIG_SLAB +#if defined(CONFIG_SLAB) || defined(CONFIG_MODULAR_SLAB) extern struct seq_operations slabinfo_op; +#ifdef CONFIG_SLAB extern ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *); +#endif static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); @@ -399,12 +401,14 @@ static int slabinfo_open(struct inode *i static struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, +#ifdef CONFIG_SLAB .write = slabinfo_write, +#endif .llseek = seq_lseek, .release = seq_release, }; -#ifdef CONFIG_DEBUG_SLAB_LEAK +#if defined(CONFIG_DEBUG_SLAB_LEAK) && defined(CONFIG_SLAB) extern struct seq_operations slabstats_op; static int slabstats_open(struct inode *inode, struct file *file) { @@ -775,9 +779,9 @@ void __init proc_misc_init(void) create_seq_entry("partitions", 0, &proc_partitions_operations); create_seq_entry("stat", 0, &proc_stat_operations); create_seq_entry("interrupts", 0, &proc_interrupts_operations); -#ifdef CONFIG_SLAB +#if defined(CONFIG_SLAB) || defined(CONFIG_MODULAR_SLAB) create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); -#ifdef CONFIG_DEBUG_SLAB_LEAK +#if defined(CONFIG_DEBUG_SLAB_LEAK) && defined(CONFIG_SLAB) create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations); #endif #endif Index: linux-2.6.18-rc4-mm2/mm/Makefile =================================================================== --- linux-2.6.18-rc4-mm2.orig/mm/Makefile 2006-08-25 19:08:07.053500816 -0700 +++ linux-2.6.18-rc4-mm2/mm/Makefile 2006-08-25 19:16:57.338094817 -0700 @@ -25,4 +25,4 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += memory_h obj-$(CONFIG_FS_XIP) += filemap_xip.o obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_SMP) += allocpercpu.o -obj-$(CONFIG_MODULAR_SLAB) += allocator.o slabifier.o +obj-$(CONFIG_MODULAR_SLAB) += allocator.o slabifier.o slabstat.o Index: linux-2.6.18-rc4-mm2/mm/slabstat.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.18-rc4-mm2/mm/slabstat.c 2006-08-25 19:17:38.250604270 -0700 @@ -0,0 +1,96 @@ +/* + * linux/mm/slabstat.c + */ + +#include +#include + +static DECLARE_RWSEM(slabstat_sem); + +LIST_HEAD(slab_caches); + +void register_slab(struct slab_cache *s) +{ + down_write(&slabstat_sem); + list_add(&s->list, &slab_caches); + up_write(&slabstat_sem); +} + +void unregister_slab(struct slab_cache *s) +{ + down_write(&slabstat_sem); + list_add(&s->list, &slab_caches); + up_write(&slabstat_sem); +} + +static void print_slabinfo_header(struct seq_file *m) +{ + /* + * Output format version, so at least we can change it + * without _too_ many complaints. + */ + seq_puts(m, "slabinfo - version: 3.0\n"); + seq_puts(m, "# name " + " "); + seq_putc(m, '\n'); +} + +static void *s_start(struct seq_file *m, loff_t *pos) +{ + loff_t n = *pos; + struct list_head *p; + + down_read(&slabstat_sem); + if (!n) + print_slabinfo_header(m); + p = slab_caches.next; + while (n--) { + p = p->next; + if (p == &slab_caches) + return NULL; + } + return list_entry(p, struct slab_cache, list); +} + +static void *s_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct slab_cache *s = p; + ++*pos; + return s->list.next == &slab_caches ? + NULL : list_entry(s->list.next, struct slab_cache, list); +} + +static void s_stop(struct seq_file *m, void *p) +{ + up_read(&slabstat_sem); +} + +static int s_show(struct seq_file *m, void *p) +{ + struct slab_cache *s = p; + unsigned long total_slabs; + unsigned long active_slabs; + unsigned long partial_slabs; + unsigned long objects; + + objects = s->slab_alloc->get_objects(s, &total_slabs, + &active_slabs, &partial_slabs); + + seq_printf(m, "%-20s %7lu %7u %7lu %7lu %7lu %2d %s", + s->name, objects, s->size, total_slabs, partial_slabs, + active_slabs, s->order, s->page_alloc->name); + + seq_putc(m, '\n'); + return 0; +} + +/* + * slabinfo_op - iterator that generates /proc/slabinfo + */ +struct seq_operations slabinfo_op = { + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show, +}; + Index: linux-2.6.18-rc4-mm2/include/linux/slabstat.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.18-rc4-mm2/include/linux/slabstat.h 2006-08-25 19:16:57.339071319 -0700 @@ -0,0 +1,9 @@ +#ifndef _LINUX_SLABSTAT_H +#define _LINUX_SLABSTAT_H +#include + +void register_slab(struct slab_cache *s); +void unregister_slab(struct slab_cache *s); + +#endif /* _LINUX_SLABSTAT_H */ +