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:
parent
e31ed02433
commit
2c251e814c
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue