freebsd/kstat: allow multi-level module names

This extends the existing special-case for zfs/poolname to split and
create any number of intermediate sysctl names, so that multi-level
module names are possible.

Sponsored-by: Klara, Inc.
Sponsored-by: Syneto
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
This commit is contained in:
Rob Norris 2024-05-16 14:58:15 +10:00 committed by Rob Norris
parent e31ed02433
commit 2c251e814c
1 changed files with 26 additions and 42 deletions

View File

@ -27,6 +27,10 @@
* [1] https://illumos.org/man/1M/kstat * [1] https://illumos.org/man/1M/kstat
* [2] https://illumos.org/man/9f/kstat_create * [2] https://illumos.org/man/9f/kstat_create
*/ */
/*
* Copyright (c) 2024, Klara, Inc.
* Copyright (c) 2024, Syneto
*/
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
@ -287,7 +291,7 @@ __kstat_create(const char *module, int instance, const char *name,
char buf[KSTAT_STRLEN]; char buf[KSTAT_STRLEN];
struct sysctl_oid *root; struct sysctl_oid *root;
kstat_t *ksp; kstat_t *ksp;
char *pool; char *p, *frag;
KASSERT(instance == 0, ("instance=%d", instance)); KASSERT(instance == 0, ("instance=%d", instance));
if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO)) if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
@ -345,74 +349,54 @@ __kstat_create(const char *module, int instance, const char *name,
else else
ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP); ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP);
/* sysctl_ctx_init(&ksp->ks_sysctl_ctx);
* Some kstats use a module name like "zfs/poolname" to distinguish a
* set of kstats belonging to a specific pool. Split on '/' to add an
* extra node for the pool name if needed.
*/
(void) strlcpy(buf, module, KSTAT_STRLEN); (void) strlcpy(buf, module, KSTAT_STRLEN);
module = buf;
pool = strchr(module, '/');
if (pool != NULL)
*pool++ = '\0';
/* /*
* Create sysctl tree for those statistics: * Walk over the module name, splitting on '/', and create the
* * intermediate nodes.
* kstat.<module>[.<pool>].<class>.<name>
*/ */
sysctl_ctx_init(&ksp->ks_sysctl_ctx); root = NULL;
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, p = buf;
SYSCTL_STATIC_CHILDREN(_kstat), OID_AUTO, module, CTLFLAG_RW, 0, while ((frag = strsep(&p, "/")) != NULL) {
""); root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, root ?
if (root == NULL) { SYSCTL_CHILDREN(root) : SYSCTL_STATIC_CHILDREN(_kstat),
printf("%s: Cannot create kstat.%s tree!\n", __func__, module); OID_AUTO, frag, CTLFLAG_RW, 0, "");
sysctl_ctx_free(&ksp->ks_sysctl_ctx);
free(ksp, M_KSTAT);
return (NULL);
}
if (pool != NULL) {
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
SYSCTL_CHILDREN(root), OID_AUTO, pool, CTLFLAG_RW, 0, "");
if (root == NULL) { if (root == NULL) {
printf("%s: Cannot create kstat.%s.%s tree!\n", printf("%s: Cannot create kstat.%s tree!\n",
__func__, module, pool); __func__, buf);
sysctl_ctx_free(&ksp->ks_sysctl_ctx); sysctl_ctx_free(&ksp->ks_sysctl_ctx);
free(ksp, M_KSTAT); free(ksp, M_KSTAT);
return (NULL); return (NULL);
} }
if (p != NULL && p > frag)
p[-1] = '.';
} }
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root), root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root),
OID_AUTO, class, CTLFLAG_RW, 0, ""); OID_AUTO, class, CTLFLAG_RW, 0, "");
if (root == NULL) { if (root == NULL) {
if (pool != NULL) printf("%s: Cannot create kstat.%s.%s tree!\n",
printf("%s: Cannot create kstat.%s.%s.%s tree!\n", __func__, buf, class);
__func__, module, pool, class);
else
printf("%s: Cannot create kstat.%s.%s tree!\n",
__func__, module, class);
sysctl_ctx_free(&ksp->ks_sysctl_ctx); sysctl_ctx_free(&ksp->ks_sysctl_ctx);
free(ksp, M_KSTAT); free(ksp, M_KSTAT);
return (NULL); return (NULL);
} }
if (ksp->ks_type == KSTAT_TYPE_NAMED) { if (ksp->ks_type == KSTAT_TYPE_NAMED) {
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
SYSCTL_CHILDREN(root), SYSCTL_CHILDREN(root),
OID_AUTO, name, CTLFLAG_RW, 0, ""); OID_AUTO, name, CTLFLAG_RW, 0, "");
if (root == NULL) { if (root == NULL) {
if (pool != NULL) printf("%s: Cannot create kstat.%s.%s.%s tree!\n",
printf("%s: Cannot create kstat.%s.%s.%s.%s " __func__, buf, class, name);
"tree!\n", __func__, module, pool, class,
name);
else
printf("%s: Cannot create kstat.%s.%s.%s "
"tree!\n", __func__, module, class, name);
sysctl_ctx_free(&ksp->ks_sysctl_ctx); sysctl_ctx_free(&ksp->ks_sysctl_ctx);
free(ksp, M_KSTAT); free(ksp, M_KSTAT);
return (NULL); return (NULL);
} }
} }
ksp->ks_sysctl_root = root; ksp->ks_sysctl_root = root;
return (ksp); return (ksp);