From: Christoph Lameter Subject: SLUB: statistics improvements - Fix indentation in unfreeze_slab - FREE_SLAB/ALLOC_SLAB counters were slightly misplaced and counted even if the slab was kept because we were below the mininum of partial slabs. - Export per cpu statistics to user space (follow numa convention but change the n character to c (no slabinfo support for display yet) F.e. christoph@stapp:/sys/kernel/slab/kmalloc-8$ cat alloc_fastpath 9968 c0=4854 c1=1050 c2=468 c3=190 c4=116 c5=1779 c6=185 c7=1326 --- mm/slub.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2008-02-07 11:56:08.454295158 -0800 +++ linux-2.6/mm/slub.c 2008-02-07 11:56:33.062620113 -0800 @@ -1384,7 +1384,7 @@ static void unfreeze_slab(struct kmem_ca } else { stat(c, DEACTIVATE_FULL); if (SlabDebug(page) && (s->flags & SLAB_STORE_USER)) - add_full(n, page); + add_full(n, page); } slab_unlock(page); } else { @@ -1402,6 +1402,7 @@ static void unfreeze_slab(struct kmem_ca slab_unlock(page); } else { slab_unlock(page); + stat(get_cpu_slab(s, raw_smp_processor_id()), FREE_SLAB); discard_slab(s, page); } } @@ -1572,9 +1573,9 @@ new_slab: if (new) { c = get_cpu_slab(s, smp_processor_id()); + stat(c, ALLOC_SLAB); if (c->page) flush_slab(s, c); - stat(c, ALLOC_SLAB); slab_lock(new); SetSlabFrozen(new); c->page = new; @@ -4016,15 +4017,37 @@ SLAB_ATTR(remote_node_defrag_ratio); #ifdef CONFIG_SLUB_STATS +static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si) +{ + unsigned long sum = 0; + int cpu; + int len; + int *data = kmalloc(nr_cpu_ids * sizeof(int), GFP_KERNEL); + + if (!data) + return -ENOMEM; + + for_each_online_cpu(cpu) { + unsigned x = get_cpu_slab(s, cpu)->stat[si]; + + data[cpu] = x; + sum += x; + } + + len = sprintf(buf, "%lu", sum); + + for_each_online_cpu(cpu) { + if (data[cpu] && len < PAGE_SIZE - 20) + len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]); + } + kfree(data); + return len + sprintf(buf + len, "\n"); +} + #define STAT_ATTR(si, text) \ static ssize_t text##_show(struct kmem_cache *s, char *buf) \ { \ - unsigned long sum = 0; \ - int cpu; \ - \ - for_each_online_cpu(cpu) \ - sum += get_cpu_slab(s, cpu)->stat[si]; \ - return sprintf(buf, "%lu\n", sum); \ + return show_stat(s, buf, si); \ } \ SLAB_ATTR_RO(text); \