summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorMatthew Macy <[email protected]>2020-09-01 16:16:56 -0700
committerGitHub <[email protected]>2020-09-01 16:16:56 -0700
commite84e49218f448369929c5c426220445d1698f044 (patch)
treebbd73f9905f6302ea2034a8510950382353c51f2 /module
parent7b4e27232dec4595ef842ce7c0e31aafd255a20a (diff)
FreeBSD: Fix up after spa_stats.c move
Moving spa_stats added the additional burden of supporting KSTAT_TYPE_IO. spa_state_addr will always return a valid value regardless of the value of 'n'. On FreeBSD this will cause an infinite loop as it relies on the raw ops addr routine to indicate that there is no more data. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Matt Macy <[email protected]> Closes #10860
Diffstat (limited to 'module')
-rw-r--r--module/os/freebsd/spl/spl_kstat.c173
-rw-r--r--module/zfs/spa_stats.c4
2 files changed, 116 insertions, 61 deletions
diff --git a/module/os/freebsd/spl/spl_kstat.c b/module/os/freebsd/spl/spl_kstat.c
index d792033ff..92a18de63 100644
--- a/module/os/freebsd/spl/spl_kstat.c
+++ b/module/os/freebsd/spl/spl_kstat.c
@@ -83,6 +83,71 @@ kstat_raw_default_addr(kstat_t *ksp, loff_t n)
return (NULL);
}
+static int
+kstat_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ kstat_t *ksp = arg1;
+ kstat_named_t *ksent;
+ uint64_t val;
+
+ ksent = ksp->ks_data;
+ /* Select the correct element */
+ ksent += arg2;
+ /* Update the aggsums before reading */
+ (void) ksp->ks_update(ksp, KSTAT_READ);
+ val = ksent->value.ui64;
+
+ return (sysctl_handle_64(oidp, &val, 0, req));
+}
+
+static int
+kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
+{
+ kstat_t *ksp = arg1;
+ kstat_named_t *ksent = ksp->ks_data;
+ char *val;
+ uint32_t len = 0;
+
+ /* Select the correct element */
+ ksent += arg2;
+ /* Update the aggsums before reading */
+ (void) ksp->ks_update(ksp, KSTAT_READ);
+ val = KSTAT_NAMED_STR_PTR(ksent);
+ len = KSTAT_NAMED_STR_BUFLEN(ksent);
+ val[len-1] = '\0';
+
+ return (sysctl_handle_string(oidp, val, len, req));
+}
+
+static int
+kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf *sb;
+ kstat_t *ksp = arg1;
+ kstat_io_t *kip = ksp->ks_data;
+ int rc;
+
+ sb = sbuf_new_auto();
+ if (sb == NULL)
+ return (ENOMEM);
+ /* Update the aggsums before reading */
+ (void) ksp->ks_update(ksp, KSTAT_READ);
+
+ /* though wlentime & friends are signed, they will never be negative */
+ sbuf_printf(sb,
+ "%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
+ "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
+ kip->nread, kip->nwritten,
+ kip->reads, kip->writes,
+ kip->wtime, kip->wlentime, kip->wlastupdate,
+ kip->rtime, kip->rlentime, kip->rlastupdate,
+ kip->wcnt, kip->rcnt);
+ rc = sbuf_finish(sb);
+ if (rc == 0)
+ rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
+ sbuf_delete(sb);
+ return (rc);
+}
static int
kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
@@ -235,7 +300,7 @@ __kstat_create(const char *module, int instance, const char *name,
free(ksp, M_KSTAT);
return (NULL);
}
- if (ksp->ks_type != KSTAT_TYPE_RAW) {
+ if (ksp->ks_type == KSTAT_TYPE_NAMED) {
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
SYSCTL_CHILDREN(root),
OID_AUTO, name, CTLFLAG_RW, 0, "");
@@ -253,71 +318,14 @@ __kstat_create(const char *module, int instance, const char *name,
return (ksp);
}
-static int
-kstat_sysctl(SYSCTL_HANDLER_ARGS)
+static void
+kstat_install_named(kstat_t *ksp)
{
- kstat_t *ksp = arg1;
- kstat_named_t *ksent;
- uint64_t val;
-
- ksent = ksp->ks_data;
- /* Select the correct element */
- ksent += arg2;
- /* Update the aggsums before reading */
- (void) ksp->ks_update(ksp, KSTAT_READ);
- val = ksent->value.ui64;
-
- return (sysctl_handle_64(oidp, &val, 0, req));
-}
-
-static int
-kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
-{
- kstat_t *ksp = arg1;
- kstat_named_t *ksent = ksp->ks_data;
- char *val;
- uint32_t len = 0;
-
- /* Select the correct element */
- ksent += arg2;
- /* Update the aggsums before reading */
- (void) ksp->ks_update(ksp, KSTAT_READ);
- val = KSTAT_NAMED_STR_PTR(ksent);
- len = KSTAT_NAMED_STR_BUFLEN(ksent);
- val[len-1] = '\0';
-
- return (sysctl_handle_string(oidp, val, len, req));
-}
-
-void
-kstat_install(kstat_t *ksp)
-{
- struct sysctl_oid *root;
kstat_named_t *ksent;
char *namelast;
int typelast;
ksent = ksp->ks_data;
- if (ksp->ks_ndata == UINT32_MAX)
- VERIFY(ksp->ks_type == KSTAT_TYPE_RAW);
- if (ksp->ks_type == KSTAT_TYPE_RAW) {
- if (ksp->ks_raw_ops.data) {
- root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
- SYSCTL_CHILDREN(ksp->ks_sysctl_root),
- OID_AUTO, ksp->ks_name,
- CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
- kstat_sysctl_raw, "A", ksp->ks_name);
- } else {
- root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
- SYSCTL_CHILDREN(ksp->ks_sysctl_root),
- OID_AUTO, ksp->ks_name,
- CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0,
- kstat_sysctl_raw, "", ksp->ks_name);
- }
- VERIFY(root != NULL);
- ksp->ks_sysctl_root = root;
- return;
- }
VERIFY((ksp->ks_flags & KSTAT_FLAG_VIRTUAL) || ksent != NULL);
@@ -387,6 +395,51 @@ kstat_install(kstat_t *ksp)
}
}
+
+}
+
+void
+kstat_install(kstat_t *ksp)
+{
+ struct sysctl_oid *root;
+
+ if (ksp->ks_ndata == UINT32_MAX)
+ VERIFY(ksp->ks_type == KSTAT_TYPE_RAW);
+
+ switch (ksp->ks_type) {
+ case KSTAT_TYPE_NAMED:
+ return (kstat_install_named(ksp));
+ break;
+ case KSTAT_TYPE_RAW:
+ if (ksp->ks_raw_ops.data) {
+ root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, ksp->ks_name,
+ CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
+ kstat_sysctl_raw, "A", ksp->ks_name);
+ } else {
+ root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, ksp->ks_name,
+ CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0,
+ kstat_sysctl_raw, "", ksp->ks_name);
+ }
+ VERIFY(root != NULL);
+ break;
+ case KSTAT_TYPE_IO:
+ root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
+ SYSCTL_CHILDREN(ksp->ks_sysctl_root),
+ OID_AUTO, ksp->ks_name,
+ CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
+ kstat_sysctl_io, "A", ksp->ks_name);
+ break;
+ case KSTAT_TYPE_TIMER:
+ case KSTAT_TYPE_INTR:
+ default:
+ panic("unsupported kstat type %d\n", ksp->ks_type);
+ }
+ ksp->ks_sysctl_root = root;
+
}
void
diff --git a/module/zfs/spa_stats.c b/module/zfs/spa_stats.c
index 86cefa6dd..5c1073c14 100644
--- a/module/zfs/spa_stats.c
+++ b/module/zfs/spa_stats.c
@@ -835,7 +835,9 @@ spa_mmp_history_add(spa_t *spa, uint64_t txg, uint64_t timestamp,
static void *
spa_state_addr(kstat_t *ksp, loff_t n)
{
- return (ksp->ks_private); /* return the spa_t */
+ if (n == 0)
+ return (ksp->ks_private); /* return the spa_t */
+ return (NULL);
}
static int