Loading mm/slab.c +26 −92 Original line number Diff line number Diff line Loading @@ -4276,54 +4276,8 @@ static void cache_reap(struct work_struct *w) } #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { /* * Output format version, so at least we can change it * without _too_ many complaints. */ #if STATS seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); #else seq_puts(m, "slabinfo - version: 2.1\n"); #endif seq_puts(m, "# name <active_objs> <num_objs> <objsize> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); #if STATS seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); #endif seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) { struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; Loading Loading @@ -4378,13 +4332,20 @@ static int s_show(struct seq_file *m, void *p) if (error) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", name, active_objs, num_objs, cachep->size, cachep->num, (1 << cachep->gfporder)); seq_printf(m, " : tunables %4u %4u %4u", cachep->limit, cachep->batchcount, cachep->shared); seq_printf(m, " : slabdata %6lu %6lu %6lu", active_slabs, num_slabs, shared_avail); sinfo->active_objs = active_objs; sinfo->num_objs = num_objs; sinfo->active_slabs = active_slabs; sinfo->num_slabs = num_slabs; sinfo->shared_avail = shared_avail; sinfo->limit = cachep->limit; sinfo->batchcount = cachep->batchcount; sinfo->shared = cachep->shared; sinfo->objects_per_slab = cachep->num; sinfo->cache_order = cachep->gfporder; } void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) { #if STATS { /* list3 stats */ unsigned long high = cachep->high_mark; Loading Loading @@ -4414,31 +4375,8 @@ static int s_show(struct seq_file *m, void *p) allochit, allocmiss, freehit, freemiss); } #endif seq_putc(m, '\n'); return 0; } /* * slabinfo_op - iterator that generates /proc/slabinfo * * Output layout: * cache-name * num-active-objs * total-objs * object size * num-active-slabs * total-slabs * num-pages-per-slab * + further values on SMP and with statistics enabled */ static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; #define MAX_SLABINFO_WRITE 128 /** * slabinfo_write - Tuning for the slab allocator Loading @@ -4447,7 +4385,7 @@ static const struct seq_operations slabinfo_op = { * @count: data length * @ppos: unused */ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; Loading Loading @@ -4490,19 +4428,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, return res; } static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .write = slabinfo_write, .llseek = seq_lseek, .release = seq_release, }; #ifdef CONFIG_DEBUG_SLAB_LEAK static void *leaks_start(struct seq_file *m, loff_t *pos) Loading Loading @@ -4631,6 +4556,16 @@ static int leaks_show(struct seq_file *m, void *p) return 0; } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static const struct seq_operations slabstats_op = { .start = leaks_start, .next = s_next, Loading Loading @@ -4665,7 +4600,6 @@ static const struct file_operations proc_slabstats_operations = { static int __init slab_proc_init(void) { proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations); #ifdef CONFIG_DEBUG_SLAB_LEAK proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); #endif Loading mm/slab.h +20 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,24 @@ static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t siz int __kmem_cache_shutdown(struct kmem_cache *); struct seq_file; struct file; struct slabinfo { unsigned long active_objs; unsigned long num_objs; unsigned long active_slabs; unsigned long num_slabs; unsigned long shared_avail; unsigned int limit; unsigned int batchcount; unsigned int shared; unsigned int objects_per_slab; unsigned int cache_order; }; void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo); void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s); ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos); #endif mm/slab_common.c +109 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include <linux/module.h> #include <linux/cpu.h> #include <linux/uaccess.h> #include <linux/seq_file.h> #include <linux/proc_fs.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm/page.h> Loading Loading @@ -192,3 +194,110 @@ int slab_is_available(void) { return slab_state >= UP; } #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { /* * Output format version, so at least we can change it * without _too_ many complaints. */ #ifdef CONFIG_DEBUG_SLAB seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); #else seq_puts(m, "slabinfo - version: 2.1\n"); #endif seq_puts(m, "# name <active_objs> <num_objs> <objsize> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); #ifdef CONFIG_DEBUG_SLAB seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); #endif seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) { struct kmem_cache *s = list_entry(p, struct kmem_cache, list); struct slabinfo sinfo; memset(&sinfo, 0, sizeof(sinfo)); get_slabinfo(s, &sinfo); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, sinfo.active_objs, sinfo.num_objs, s->size, sinfo.objects_per_slab, (1 << sinfo.cache_order)); seq_printf(m, " : tunables %4u %4u %4u", sinfo.limit, sinfo.batchcount, sinfo.shared); seq_printf(m, " : slabdata %6lu %6lu %6lu", sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); slabinfo_show_stats(m, s); seq_putc(m, '\n'); return 0; } /* * slabinfo_op - iterator that generates /proc/slabinfo * * Output layout: * cache-name * num-active-objs * total-objs * object size * num-active-slabs * total-slabs * num-pages-per-slab * + further values on SMP and with statistics enabled */ static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .write = slabinfo_write, .llseek = seq_lseek, .release = seq_release, }; static int __init slab_proc_init(void) { proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); return 0; } module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */ mm/slub.c +11 −66 Original line number Diff line number Diff line Loading @@ -5399,49 +5399,14 @@ __initcall(slab_sysfs_init); * The /proc/slabinfo ABI */ #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { seq_puts(m, "slabinfo - version: 2.1\n"); seq_puts(m, "# name <active_objs> <num_objs> <object_size> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) { unsigned long nr_partials = 0; unsigned long nr_slabs = 0; unsigned long nr_inuse = 0; unsigned long nr_objs = 0; unsigned long nr_free = 0; struct kmem_cache *s; int node; s = list_entry(p, struct kmem_cache, list); for_each_online_node(node) { struct kmem_cache_node *n = get_node(s, node); Loading @@ -5454,41 +5419,21 @@ static int s_show(struct seq_file *m, void *p) nr_free += count_partial(n, count_free); } nr_inuse = nr_objs - nr_free; seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, nr_objs, s->size, oo_objects(s->oo), (1 << oo_order(s->oo))); seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs, 0UL); seq_putc(m, '\n'); return 0; sinfo->active_objs = nr_objs - nr_free; sinfo->num_objs = nr_objs; sinfo->active_slabs = nr_slabs; sinfo->num_slabs = nr_slabs; sinfo->objects_per_slab = oo_objects(s->oo); sinfo->cache_order = oo_order(s->oo); } static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; static int slabinfo_open(struct inode *inode, struct file *file) void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; static int __init slab_proc_init(void) ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); return 0; return -EIO; } module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */ Loading
mm/slab.c +26 −92 Original line number Diff line number Diff line Loading @@ -4276,54 +4276,8 @@ static void cache_reap(struct work_struct *w) } #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { /* * Output format version, so at least we can change it * without _too_ many complaints. */ #if STATS seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); #else seq_puts(m, "slabinfo - version: 2.1\n"); #endif seq_puts(m, "# name <active_objs> <num_objs> <objsize> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); #if STATS seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); #endif seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) { struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; Loading Loading @@ -4378,13 +4332,20 @@ static int s_show(struct seq_file *m, void *p) if (error) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", name, active_objs, num_objs, cachep->size, cachep->num, (1 << cachep->gfporder)); seq_printf(m, " : tunables %4u %4u %4u", cachep->limit, cachep->batchcount, cachep->shared); seq_printf(m, " : slabdata %6lu %6lu %6lu", active_slabs, num_slabs, shared_avail); sinfo->active_objs = active_objs; sinfo->num_objs = num_objs; sinfo->active_slabs = active_slabs; sinfo->num_slabs = num_slabs; sinfo->shared_avail = shared_avail; sinfo->limit = cachep->limit; sinfo->batchcount = cachep->batchcount; sinfo->shared = cachep->shared; sinfo->objects_per_slab = cachep->num; sinfo->cache_order = cachep->gfporder; } void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) { #if STATS { /* list3 stats */ unsigned long high = cachep->high_mark; Loading Loading @@ -4414,31 +4375,8 @@ static int s_show(struct seq_file *m, void *p) allochit, allocmiss, freehit, freemiss); } #endif seq_putc(m, '\n'); return 0; } /* * slabinfo_op - iterator that generates /proc/slabinfo * * Output layout: * cache-name * num-active-objs * total-objs * object size * num-active-slabs * total-slabs * num-pages-per-slab * + further values on SMP and with statistics enabled */ static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; #define MAX_SLABINFO_WRITE 128 /** * slabinfo_write - Tuning for the slab allocator Loading @@ -4447,7 +4385,7 @@ static const struct seq_operations slabinfo_op = { * @count: data length * @ppos: unused */ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; Loading Loading @@ -4490,19 +4428,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, return res; } static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .write = slabinfo_write, .llseek = seq_lseek, .release = seq_release, }; #ifdef CONFIG_DEBUG_SLAB_LEAK static void *leaks_start(struct seq_file *m, loff_t *pos) Loading Loading @@ -4631,6 +4556,16 @@ static int leaks_show(struct seq_file *m, void *p) return 0; } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static const struct seq_operations slabstats_op = { .start = leaks_start, .next = s_next, Loading Loading @@ -4665,7 +4600,6 @@ static const struct file_operations proc_slabstats_operations = { static int __init slab_proc_init(void) { proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations); #ifdef CONFIG_DEBUG_SLAB_LEAK proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); #endif Loading
mm/slab.h +20 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,24 @@ static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t siz int __kmem_cache_shutdown(struct kmem_cache *); struct seq_file; struct file; struct slabinfo { unsigned long active_objs; unsigned long num_objs; unsigned long active_slabs; unsigned long num_slabs; unsigned long shared_avail; unsigned int limit; unsigned int batchcount; unsigned int shared; unsigned int objects_per_slab; unsigned int cache_order; }; void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo); void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s); ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos); #endif
mm/slab_common.c +109 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ #include <linux/module.h> #include <linux/cpu.h> #include <linux/uaccess.h> #include <linux/seq_file.h> #include <linux/proc_fs.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm/page.h> Loading Loading @@ -192,3 +194,110 @@ int slab_is_available(void) { return slab_state >= UP; } #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { /* * Output format version, so at least we can change it * without _too_ many complaints. */ #ifdef CONFIG_DEBUG_SLAB seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); #else seq_puts(m, "slabinfo - version: 2.1\n"); #endif seq_puts(m, "# name <active_objs> <num_objs> <objsize> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); #ifdef CONFIG_DEBUG_SLAB seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); #endif seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) { struct kmem_cache *s = list_entry(p, struct kmem_cache, list); struct slabinfo sinfo; memset(&sinfo, 0, sizeof(sinfo)); get_slabinfo(s, &sinfo); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, sinfo.active_objs, sinfo.num_objs, s->size, sinfo.objects_per_slab, (1 << sinfo.cache_order)); seq_printf(m, " : tunables %4u %4u %4u", sinfo.limit, sinfo.batchcount, sinfo.shared); seq_printf(m, " : slabdata %6lu %6lu %6lu", sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); slabinfo_show_stats(m, s); seq_putc(m, '\n'); return 0; } /* * slabinfo_op - iterator that generates /proc/slabinfo * * Output layout: * cache-name * num-active-objs * total-objs * object size * num-active-slabs * total-slabs * num-pages-per-slab * + further values on SMP and with statistics enabled */ static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .write = slabinfo_write, .llseek = seq_lseek, .release = seq_release, }; static int __init slab_proc_init(void) { proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); return 0; } module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */
mm/slub.c +11 −66 Original line number Diff line number Diff line Loading @@ -5399,49 +5399,14 @@ __initcall(slab_sysfs_init); * The /proc/slabinfo ABI */ #ifdef CONFIG_SLABINFO static void print_slabinfo_header(struct seq_file *m) { seq_puts(m, "slabinfo - version: 2.1\n"); seq_puts(m, "# name <active_objs> <num_objs> <object_size> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); seq_putc(m, '\n'); } static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) { unsigned long nr_partials = 0; unsigned long nr_slabs = 0; unsigned long nr_inuse = 0; unsigned long nr_objs = 0; unsigned long nr_free = 0; struct kmem_cache *s; int node; s = list_entry(p, struct kmem_cache, list); for_each_online_node(node) { struct kmem_cache_node *n = get_node(s, node); Loading @@ -5454,41 +5419,21 @@ static int s_show(struct seq_file *m, void *p) nr_free += count_partial(n, count_free); } nr_inuse = nr_objs - nr_free; seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, nr_objs, s->size, oo_objects(s->oo), (1 << oo_order(s->oo))); seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs, 0UL); seq_putc(m, '\n'); return 0; sinfo->active_objs = nr_objs - nr_free; sinfo->num_objs = nr_objs; sinfo->active_slabs = nr_slabs; sinfo->num_slabs = nr_slabs; sinfo->objects_per_slab = oo_objects(s->oo); sinfo->cache_order = oo_order(s->oo); } static const struct seq_operations slabinfo_op = { .start = s_start, .next = s_next, .stop = s_stop, .show = s_show, }; static int slabinfo_open(struct inode *inode, struct file *file) void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s) { return seq_open(file, &slabinfo_op); } static const struct file_operations proc_slabinfo_operations = { .open = slabinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; static int __init slab_proc_init(void) ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); return 0; return -EIO; } module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */