Merge branch 'slab/procfs' into slab/next

This commit is contained in:
Pekka Enberg 2012-10-24 09:43:00 +03:00
commit b4f591c45f
4 changed files with 166 additions and 158 deletions

118
mm/slab.c
View File

@ -4276,54 +4276,8 @@ out:
} }
#ifdef CONFIG_SLABINFO #ifdef CONFIG_SLABINFO
void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
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)
{
struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
struct slab *slabp; struct slab *slabp;
unsigned long active_objs; unsigned long active_objs;
unsigned long num_objs; unsigned long num_objs;
@ -4378,13 +4332,20 @@ static int s_show(struct seq_file *m, void *p)
if (error) if (error)
printk(KERN_ERR "slab: cache %s error: %s\n", name, error); printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", sinfo->active_objs = active_objs;
name, active_objs, num_objs, cachep->size, sinfo->num_objs = num_objs;
cachep->num, (1 << cachep->gfporder)); sinfo->active_slabs = active_slabs;
seq_printf(m, " : tunables %4u %4u %4u", sinfo->num_slabs = num_slabs;
cachep->limit, cachep->batchcount, cachep->shared); sinfo->shared_avail = shared_avail;
seq_printf(m, " : slabdata %6lu %6lu %6lu", sinfo->limit = cachep->limit;
active_slabs, num_slabs, shared_avail); 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 #if STATS
{ /* list3 stats */ { /* list3 stats */
unsigned long high = cachep->high_mark; unsigned long high = cachep->high_mark;
@ -4414,31 +4375,8 @@ static int s_show(struct seq_file *m, void *p)
allochit, allocmiss, freehit, freemiss); allochit, allocmiss, freehit, freemiss);
} }
#endif #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 #define MAX_SLABINFO_WRITE 128
/** /**
* slabinfo_write - Tuning for the slab allocator * slabinfo_write - Tuning for the slab allocator
@ -4447,7 +4385,7 @@ static const struct seq_operations slabinfo_op = {
* @count: data length * @count: data length
* @ppos: unused * @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) size_t count, loff_t *ppos)
{ {
char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
@ -4490,19 +4428,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
return res; 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 #ifdef CONFIG_DEBUG_SLAB_LEAK
static void *leaks_start(struct seq_file *m, loff_t *pos) static void *leaks_start(struct seq_file *m, loff_t *pos)
@ -4631,6 +4556,16 @@ static int leaks_show(struct seq_file *m, void *p)
return 0; 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 = { static const struct seq_operations slabstats_op = {
.start = leaks_start, .start = leaks_start,
.next = s_next, .next = s_next,
@ -4665,7 +4600,6 @@ static const struct file_operations proc_slabstats_operations = {
static int __init slab_proc_init(void) static int __init slab_proc_init(void)
{ {
proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
#ifdef CONFIG_DEBUG_SLAB_LEAK #ifdef CONFIG_DEBUG_SLAB_LEAK
proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
#endif #endif

View File

@ -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 *); 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 #endif

View File

@ -13,6 +13,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/page.h> #include <asm/page.h>
@ -192,3 +194,110 @@ int slab_is_available(void)
{ {
return slab_state >= UP; 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 */

View File

@ -5399,49 +5399,14 @@ __initcall(slab_sysfs_init);
* The /proc/slabinfo ABI * The /proc/slabinfo ABI
*/ */
#ifdef CONFIG_SLABINFO #ifdef CONFIG_SLABINFO
static void print_slabinfo_header(struct seq_file *m) void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
{
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)
{ {
unsigned long nr_partials = 0; unsigned long nr_partials = 0;
unsigned long nr_slabs = 0; unsigned long nr_slabs = 0;
unsigned long nr_inuse = 0;
unsigned long nr_objs = 0; unsigned long nr_objs = 0;
unsigned long nr_free = 0; unsigned long nr_free = 0;
struct kmem_cache *s;
int node; int node;
s = list_entry(p, struct kmem_cache, list);
for_each_online_node(node) { for_each_online_node(node) {
struct kmem_cache_node *n = get_node(s, node); struct kmem_cache_node *n = get_node(s, node);
@ -5454,41 +5419,21 @@ static int s_show(struct seq_file *m, void *p)
nr_free += count_partial(n, count_free); nr_free += count_partial(n, count_free);
} }
nr_inuse = nr_objs - nr_free; sinfo->active_objs = nr_objs - nr_free;
sinfo->num_objs = nr_objs;
seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, sinfo->active_slabs = nr_slabs;
nr_objs, s->size, oo_objects(s->oo), sinfo->num_slabs = nr_slabs;
(1 << oo_order(s->oo))); sinfo->objects_per_slab = oo_objects(s->oo);
seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); sinfo->cache_order = oo_order(s->oo);
seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
0UL);
seq_putc(m, '\n');
return 0;
} }
static const struct seq_operations slabinfo_op = { void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s)
.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 = { ssize_t slabinfo_write(struct file *file, const char __user *buffer,
.open = slabinfo_open, size_t count, loff_t *ppos)
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init slab_proc_init(void)
{ {
proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); return -EIO;
return 0;
} }
module_init(slab_proc_init);
#endif /* CONFIG_SLABINFO */ #endif /* CONFIG_SLABINFO */