From c6bb9a9028d40ac817af6383d35164370e6480be Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 21 Jul 2018 16:07:13 +0800 Subject: [PATCH] objcache: Add sysctl to expose objcache statistics. --- sys/kern/kern_objcache.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++-- sys/sys/objcache.h | 23 +++++++++++++- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_objcache.c b/sys/kern/kern_objcache.c index 781ed15f68..687095c02d 100644 --- a/sys/kern/kern_objcache.c +++ b/sys/kern/kern_objcache.c @@ -42,6 +42,7 @@ #include #include #include +#include static MALLOC_DEFINE(M_OBJCACHE, "objcache", "Object Cache"); static MALLOC_DEFINE(M_OBJMAG, "objcache mag", "Object Cache Magazine"); @@ -126,7 +127,7 @@ struct objcache_desc { LIST_ENTRY(objcache_desc) next; struct objcache *objcache; int total_objects; -#define OBJCACHE_NAMELEN 36 + int reserved; char name[OBJCACHE_NAMELEN]; }; @@ -154,6 +155,8 @@ struct objcache { struct percpu_objcache cache_percpu[]; /* per-cpu caches */ }; +SYSCTL_NODE(_kern, OID_AUTO, objcache, CTLFLAG_RW, 0, "objcache"); + static struct spinlock objcachelist_spin; static LIST_HEAD(objcachelist, objcache_desc) allobjcaches; static int magazine_capmin; @@ -291,7 +294,7 @@ objcache_create(const char *name, int cluster_limit, int nom_cache, * capacity too due to the preallocated mags. */ if (cluster_limit == 0) { - depot->unallocated_objects = 0x40000000; + depot->unallocated_objects = OBJCACHE_UNLIMITED; } else { depot->unallocated_objects = ncpus * mag_capacity * 2 + cluster_limit; @@ -939,6 +942,79 @@ objcache_destroy(struct objcache *oc) kfree(oc, M_OBJCACHE); } +static int +sysctl_ocstats(SYSCTL_HANDLER_ARGS) +{ + struct objcache_stats stat; + struct objcache_desc marker, *desc; + int error; + + memset(&marker, 0, sizeof(marker)); + + spin_lock(&objcachelist_spin); + + LIST_INSERT_HEAD(&allobjcaches, &marker, next); + while ((desc = LIST_NEXT(&marker, next)) != NULL) { + u_long puts, unalloc; + int cpu; + + LIST_REMOVE(&marker, next); + LIST_INSERT_AFTER(desc, &marker, next); + + if (desc->total_objects == 0) { + /* Marker inserted by another thread. */ + continue; + } + + memset(&stat, 0, sizeof(stat)); + strlcpy(stat.oc_name, desc->name, sizeof(stat.oc_name)); + stat.oc_limit = desc->total_objects; + /* XXX domain aware */ + unalloc = desc->objcache->depot[0].unallocated_objects; + + puts = 0; + for (cpu = 0; cpu < ncpus; ++cpu) { + const struct percpu_objcache *cache; + + cache = &desc->objcache->cache_percpu[cpu]; + puts += cache->puts_cumulative; + + stat.oc_requested += cache->gets_cumulative; + stat.oc_exhausted += cache->gets_exhausted; + stat.oc_failed += cache->gets_null; + stat.oc_allocated += cache->allocs_cumulative; + } + spin_unlock(&objcachelist_spin); + + /* + * Apply fixup. + */ + if (stat.oc_requested > puts) + stat.oc_used = stat.oc_requested - puts; + if (stat.oc_limit > unalloc + stat.oc_used) { + stat.oc_cached = stat.oc_limit - + (unalloc + stat.oc_used); + } + stat.oc_requested += stat.oc_failed; + + /* Send out. */ + error = SYSCTL_OUT(req, &stat, sizeof(stat)); + + /* Hold the lock before we return. */ + spin_lock(&objcachelist_spin); + + if (error) + break; + } + LIST_REMOVE(&marker, next); + + spin_unlock(&objcachelist_spin); + + return error; +} +SYSCTL_PROC(_kern_objcache, OID_AUTO, stats, (CTLTYPE_OPAQUE | CTLFLAG_RD), + 0, 0, sysctl_ocstats, "S,objcache_stats", "objcache statistics"); + static void objcache_init(void) { diff --git a/sys/sys/objcache.h b/sys/sys/objcache.h index 84ea06a324..8f334ba3f0 100644 --- a/sys/sys/objcache.h +++ b/sys/sys/objcache.h @@ -79,7 +79,7 @@ void objcache_populate_linear(struct objcache *oc, void *elts, int nelts, __boolean_t objcache_reclaimlist(struct objcache *oc[], int nlist, int ocflags); void objcache_destroy(struct objcache *oc); -#endif +#endif /* !_KERNEL */ /* * Common underlying allocators. @@ -101,4 +101,25 @@ void objcache_nop_free(void *obj, void *allocator_args); #endif /* _KERNEL */ #endif /* _KERNEL || _KERNEL_STRUCTURES */ + +#define OBJCACHE_UNLIMITED 0x40000000 +#define OBJCACHE_NAMELEN 32 + +struct objcache_stats { + char oc_name[OBJCACHE_NAMELEN]; /* \0 term. */ + + /* + * >= OBJCACHE_UNLIMITED, if unlimited. + */ + u_long oc_limit; + + u_long oc_requested; + u_long oc_used; + u_long oc_cached; + u_long oc_exhausted; + u_long oc_failed; + u_long oc_allocated; + u_long oc_reserved[5]; /* reserved 0. */ +}; + #endif /* !_SYS_OBJCACHE_H_ */ -- 2.11.4.GIT