Skip to content

Commit e84e492

Browse files
authored
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 <behlendorf1@llnl.gov> Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org> Signed-off-by: Matt Macy <mmacy@FreeBSD.org> Closes #10860
1 parent 7b4e272 commit e84e492

File tree

2 files changed

+116
-61
lines changed

2 files changed

+116
-61
lines changed

module/os/freebsd/spl/spl_kstat.c

Lines changed: 113 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,71 @@ kstat_raw_default_addr(kstat_t *ksp, loff_t n)
8383
return (NULL);
8484
}
8585

86+
static int
87+
kstat_sysctl(SYSCTL_HANDLER_ARGS)
88+
{
89+
kstat_t *ksp = arg1;
90+
kstat_named_t *ksent;
91+
uint64_t val;
92+
93+
ksent = ksp->ks_data;
94+
/* Select the correct element */
95+
ksent += arg2;
96+
/* Update the aggsums before reading */
97+
(void) ksp->ks_update(ksp, KSTAT_READ);
98+
val = ksent->value.ui64;
99+
100+
return (sysctl_handle_64(oidp, &val, 0, req));
101+
}
102+
103+
static int
104+
kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
105+
{
106+
kstat_t *ksp = arg1;
107+
kstat_named_t *ksent = ksp->ks_data;
108+
char *val;
109+
uint32_t len = 0;
110+
111+
/* Select the correct element */
112+
ksent += arg2;
113+
/* Update the aggsums before reading */
114+
(void) ksp->ks_update(ksp, KSTAT_READ);
115+
val = KSTAT_NAMED_STR_PTR(ksent);
116+
len = KSTAT_NAMED_STR_BUFLEN(ksent);
117+
val[len-1] = '\0';
118+
119+
return (sysctl_handle_string(oidp, val, len, req));
120+
}
121+
122+
static int
123+
kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
124+
{
125+
struct sbuf *sb;
126+
kstat_t *ksp = arg1;
127+
kstat_io_t *kip = ksp->ks_data;
128+
int rc;
129+
130+
sb = sbuf_new_auto();
131+
if (sb == NULL)
132+
return (ENOMEM);
133+
/* Update the aggsums before reading */
134+
(void) ksp->ks_update(ksp, KSTAT_READ);
135+
136+
/* though wlentime & friends are signed, they will never be negative */
137+
sbuf_printf(sb,
138+
"%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
139+
"%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
140+
kip->nread, kip->nwritten,
141+
kip->reads, kip->writes,
142+
kip->wtime, kip->wlentime, kip->wlastupdate,
143+
kip->rtime, kip->rlentime, kip->rlastupdate,
144+
kip->wcnt, kip->rcnt);
145+
rc = sbuf_finish(sb);
146+
if (rc == 0)
147+
rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
148+
sbuf_delete(sb);
149+
return (rc);
150+
}
86151

87152
static int
88153
kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
@@ -235,7 +300,7 @@ __kstat_create(const char *module, int instance, const char *name,
235300
free(ksp, M_KSTAT);
236301
return (NULL);
237302
}
238-
if (ksp->ks_type != KSTAT_TYPE_RAW) {
303+
if (ksp->ks_type == KSTAT_TYPE_NAMED) {
239304
root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx,
240305
SYSCTL_CHILDREN(root),
241306
OID_AUTO, name, CTLFLAG_RW, 0, "");
@@ -253,71 +318,14 @@ __kstat_create(const char *module, int instance, const char *name,
253318
return (ksp);
254319
}
255320

256-
static int
257-
kstat_sysctl(SYSCTL_HANDLER_ARGS)
321+
static void
322+
kstat_install_named(kstat_t *ksp)
258323
{
259-
kstat_t *ksp = arg1;
260-
kstat_named_t *ksent;
261-
uint64_t val;
262-
263-
ksent = ksp->ks_data;
264-
/* Select the correct element */
265-
ksent += arg2;
266-
/* Update the aggsums before reading */
267-
(void) ksp->ks_update(ksp, KSTAT_READ);
268-
val = ksent->value.ui64;
269-
270-
return (sysctl_handle_64(oidp, &val, 0, req));
271-
}
272-
273-
static int
274-
kstat_sysctl_string(SYSCTL_HANDLER_ARGS)
275-
{
276-
kstat_t *ksp = arg1;
277-
kstat_named_t *ksent = ksp->ks_data;
278-
char *val;
279-
uint32_t len = 0;
280-
281-
/* Select the correct element */
282-
ksent += arg2;
283-
/* Update the aggsums before reading */
284-
(void) ksp->ks_update(ksp, KSTAT_READ);
285-
val = KSTAT_NAMED_STR_PTR(ksent);
286-
len = KSTAT_NAMED_STR_BUFLEN(ksent);
287-
val[len-1] = '\0';
288-
289-
return (sysctl_handle_string(oidp, val, len, req));
290-
}
291-
292-
void
293-
kstat_install(kstat_t *ksp)
294-
{
295-
struct sysctl_oid *root;
296324
kstat_named_t *ksent;
297325
char *namelast;
298326
int typelast;
299327

300328
ksent = ksp->ks_data;
301-
if (ksp->ks_ndata == UINT32_MAX)
302-
VERIFY(ksp->ks_type == KSTAT_TYPE_RAW);
303-
if (ksp->ks_type == KSTAT_TYPE_RAW) {
304-
if (ksp->ks_raw_ops.data) {
305-
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
306-
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
307-
OID_AUTO, ksp->ks_name,
308-
CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
309-
kstat_sysctl_raw, "A", ksp->ks_name);
310-
} else {
311-
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
312-
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
313-
OID_AUTO, ksp->ks_name,
314-
CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0,
315-
kstat_sysctl_raw, "", ksp->ks_name);
316-
}
317-
VERIFY(root != NULL);
318-
ksp->ks_sysctl_root = root;
319-
return;
320-
}
321329

322330
VERIFY((ksp->ks_flags & KSTAT_FLAG_VIRTUAL) || ksent != NULL);
323331

@@ -387,6 +395,51 @@ kstat_install(kstat_t *ksp)
387395
}
388396

389397
}
398+
399+
}
400+
401+
void
402+
kstat_install(kstat_t *ksp)
403+
{
404+
struct sysctl_oid *root;
405+
406+
if (ksp->ks_ndata == UINT32_MAX)
407+
VERIFY(ksp->ks_type == KSTAT_TYPE_RAW);
408+
409+
switch (ksp->ks_type) {
410+
case KSTAT_TYPE_NAMED:
411+
return (kstat_install_named(ksp));
412+
break;
413+
case KSTAT_TYPE_RAW:
414+
if (ksp->ks_raw_ops.data) {
415+
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
416+
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
417+
OID_AUTO, ksp->ks_name,
418+
CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
419+
kstat_sysctl_raw, "A", ksp->ks_name);
420+
} else {
421+
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
422+
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
423+
OID_AUTO, ksp->ks_name,
424+
CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0,
425+
kstat_sysctl_raw, "", ksp->ks_name);
426+
}
427+
VERIFY(root != NULL);
428+
break;
429+
case KSTAT_TYPE_IO:
430+
root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx,
431+
SYSCTL_CHILDREN(ksp->ks_sysctl_root),
432+
OID_AUTO, ksp->ks_name,
433+
CTLTYPE_STRING | CTLFLAG_RD, ksp, 0,
434+
kstat_sysctl_io, "A", ksp->ks_name);
435+
break;
436+
case KSTAT_TYPE_TIMER:
437+
case KSTAT_TYPE_INTR:
438+
default:
439+
panic("unsupported kstat type %d\n", ksp->ks_type);
440+
}
441+
ksp->ks_sysctl_root = root;
442+
390443
}
391444

392445
void

module/zfs/spa_stats.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,9 @@ spa_mmp_history_add(spa_t *spa, uint64_t txg, uint64_t timestamp,
835835
static void *
836836
spa_state_addr(kstat_t *ksp, loff_t n)
837837
{
838-
return (ksp->ks_private); /* return the spa_t */
838+
if (n == 0)
839+
return (ksp->ks_private); /* return the spa_t */
840+
return (NULL);
839841
}
840842

841843
static int

0 commit comments

Comments
 (0)