From 3336e29cc2e328c6e665de9f4563aa8a4b874194 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Sat, 26 Mar 2011 00:03:32 -0700 Subject: [PATCH] Add slab usage summeries to /proc One of the most common things you want to know when looking at the slab is how much memory is being used. This information was available in /proc/spl/kmem/slab but only on a per-slab basis. This commit adds the following /proc/sys/kernel/spl/kmem/slab* entries to make total slab usage easily available at a glance. slab_kmem_total - Total kmem slab size slab_kmem_avail - Alloc'd kmem slab size slab_kmem_max - Max observed kmem slab size slab_vmem_total - Total vmem slab size slab_vmem_avail - Alloc'd vmem slab size slab_vmem_max - Max observed vmem slab size NOTE: The slab_*_max values are expected to over report because they show maximum values since boot, not current values. --- include/sys/kmem.h | 6 +++ module/spl/spl-proc.c | 120 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/include/sys/kmem.h b/include/sys/kmem.h index 6b6b95c12..d3972f1ca 100644 --- a/include/sys/kmem.h +++ b/include/sys/kmem.h @@ -293,6 +293,9 @@ enum { KMC_BIT_OFFSLAB = 7, /* Objects not on slab */ KMC_BIT_REAPING = 16, /* Reaping in progress */ KMC_BIT_DESTROY = 17, /* Destroy in progress */ + KMC_BIT_TOTAL = 18, /* Proc handler helper bit */ + KMC_BIT_ALLOC = 19, /* Proc handler helper bit */ + KMC_BIT_MAX = 20, /* Proc handler helper bit */ }; /* kmem move callback return values */ @@ -314,6 +317,9 @@ typedef enum kmem_cbrc { #define KMC_OFFSLAB (1 << KMC_BIT_OFFSLAB) #define KMC_REAPING (1 << KMC_BIT_REAPING) #define KMC_DESTROY (1 << KMC_BIT_DESTROY) +#define KMC_TOTAL (1 << KMC_BIT_TOTAL) +#define KMC_ALLOC (1 << KMC_BIT_ALLOC) +#define KMC_MAX (1 << KMC_BIT_MAX) #define KMC_REAP_CHUNK INT_MAX #define KMC_DEFAULT_SEEKS 1 diff --git a/module/spl/spl-proc.c b/module/spl/spl-proc.c index 39b65ff38..d2b295ce0 100644 --- a/module/spl/spl-proc.c +++ b/module/spl/spl-proc.c @@ -100,7 +100,12 @@ struct proc_dir_entry *proc_spl_kstat = NULL; #define CTL_KMEM_KMEMMAX CTL_UNNUMBERED /* Max alloc'd by kmem bytes */ #define CTL_KMEM_VMEMUSED CTL_UNNUMBERED /* Alloc'd vmem bytes */ #define CTL_KMEM_VMEMMAX CTL_UNNUMBERED /* Max alloc'd by vmem bytes */ -#define CTL_KMEM_ALLOC_FAILED CTL_UNNUMBERED /* Cache allocations failed */ +#define CTL_KMEM_SLAB_KMEMTOTAL CTL_UNNUMBERED /* Total kmem slab size */ +#define CTL_KMEM_SLAB_KMEMALLOC CTL_UNNUMBERED /* Alloc'd kmem slab size */ +#define CTL_KMEM_SLAB_KMEMMAX CTL_UNNUMBERED /* Max kmem slab size */ +#define CTL_KMEM_SLAB_VMEMTOTAL CTL_UNNUMBERED /* Total vmem slab size */ +#define CTL_KMEM_SLAB_VMEMALLOC CTL_UNNUMBERED /* Alloc'd vmem slab size */ +#define CTL_KMEM_SLAB_VMEMMAX CTL_UNNUMBERED /* Max vmem slab size */ #endif #else /* HAVE_CTL_UNNUMBERED */ @@ -152,6 +157,12 @@ enum { CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */ CTL_KMEM_VMEMUSED, /* Alloc'd vmem bytes */ CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */ + CTL_KMEM_SLAB_KMEMTOTAL, /* Total kmem slab size */ + CTL_KMEM_SLAB_KMEMALLOC, /* Alloc'd kmem slab size */ + CTL_KMEM_SLAB_KMEMMAX, /* Max kmem slab size */ + CTL_KMEM_SLAB_VMEMTOTAL, /* Total vmem slab size */ + CTL_KMEM_SLAB_VMEMALLOC, /* Alloc'd vmem slab size */ + CTL_KMEM_SLAB_VMEMMAX, /* Max vmem slab size */ #endif }; #endif /* HAVE_CTL_UNNUMBERED */ @@ -424,6 +435,53 @@ SPL_PROC_HANDLER(proc_domemused) SRETURN(rc); } + +SPL_PROC_HANDLER(proc_doslab) +{ + int rc = 0; + unsigned long min = 0, max = ~0, val = 0, mask; + struct ctl_table dummy = *table; + spl_kmem_cache_t *skc; + SENTRY; + + dummy.data = &val; + dummy.proc_handler = &proc_dointvec; + dummy.extra1 = &min; + dummy.extra2 = &max; + + if (write) { + *ppos += *lenp; + } else { + down_read(&spl_kmem_cache_sem); + mask = (unsigned long)table->data; + + list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) { + + /* Only use slabs of the correct kmem/vmem type */ + if (!(skc->skc_flags & mask)) + continue; + + /* Sum the specified field for selected slabs */ + switch (mask & (KMC_TOTAL | KMC_ALLOC | KMC_MAX)) { + case KMC_TOTAL: + val += skc->skc_slab_size * skc->skc_slab_total; + break; + case KMC_ALLOC: + val += skc->skc_obj_size * skc->skc_obj_alloc; + break; + case KMC_MAX: + val += skc->skc_obj_size * skc->skc_obj_max; + break; + } + } + + up_read(&spl_kmem_cache_sem); + rc = spl_proc_doulongvec_minmax(&dummy, write, filp, + buffer, lenp, ppos); + } + + SRETURN(rc); +} #endif /* DEBUG_KMEM */ SPL_PROC_HANDLER(proc_dohostid) @@ -895,6 +953,66 @@ static struct ctl_table spl_kmem_table[] = { .mode = 0444, .proc_handler = &proc_doulongvec_minmax, }, + { + CTL_NAME (CTL_KMEM_SLAB_KMEMTOTAL) + .procname = "slab_kmem_total", + .data = (void *)(KMC_KMEM | KMC_TOTAL), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, + { + CTL_NAME (CTL_KMEM_SLAB_KMEMALLOC) + .procname = "slab_kmem_alloc", + .data = (void *)(KMC_KMEM | KMC_ALLOC), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, + { + CTL_NAME (CTL_KMEM_SLAB_KMEMMAX) + .procname = "slab_kmem_max", + .data = (void *)(KMC_KMEM | KMC_MAX), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, + { + CTL_NAME (CTL_KMEM_SLAB_VMEMTOTAL) + .procname = "slab_vmem_total", + .data = (void *)(KMC_VMEM | KMC_TOTAL), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, + { + CTL_NAME (CTL_KMEM_SLAB_VMEMALLOC) + .procname = "slab_vmem_alloc", + .data = (void *)(KMC_VMEM | KMC_ALLOC), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, + { + CTL_NAME (CTL_KMEM_SLAB_VMEMMAX) + .procname = "slab_vmem_max", + .data = (void *)(KMC_VMEM | KMC_MAX), + .maxlen = sizeof(unsigned long), + .extra1 = &table_min, + .extra2 = &table_max, + .mode = 0444, + .proc_handler = &proc_doslab, + }, {0}, }; #endif /* DEBUG_KMEM */