Skip to content

Commit 938438b

Browse files
ihorodon-bradyUmer Saleem
committed
Add a diagnostic kstat for obtaining pool status
This kstat output does not require taking the spa_namespace lock, as in the case for 'zpool status'. It can be used for investigations when pools are in a hung state while holding global locks required for a traditional 'zpool status' to proceed. This kstat is not safe to use in conditions where pools are in the process of configuration changes (i.e., adding/removing devices). Therefore, this kstat is not intended to be a general replacement or alternative to using 'zpool status'. The newly introduced zfs_lockless_read_enabled module parameter enables traversal of related kernel structures in cases where the required read locks cannot be taken. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Co-authored-by: Don Brady <[email protected]> Co-authored-by: Umer Saleem <[email protected]> Signed-off-by: Igor Ostapenko <[email protected]>
1 parent db62886 commit 938438b

25 files changed

+1570
-362
lines changed

cmd/zfs/zfs_main.c

+3-9
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
#include "zfs_util.h"
8282
#include "zfs_comutil.h"
8383
#include "zfs_projectutil.h"
84+
#include "json.h"
8485

8586
libzfs_handle_t *g_zfs;
8687

@@ -1907,18 +1908,11 @@ is_recvd_column(zprop_get_cbdata_t *cbp)
19071908
static nvlist_t *
19081909
zfs_json_schema(int maj_v, int min_v)
19091910
{
1910-
nvlist_t *sch = NULL;
1911-
nvlist_t *ov = NULL;
19121911
char cmd[MAX_CMD_LEN];
19131912
snprintf(cmd, MAX_CMD_LEN, "zfs %s", current_command->name);
19141913

1915-
sch = fnvlist_alloc();
1916-
ov = fnvlist_alloc();
1917-
fnvlist_add_string(ov, "command", cmd);
1918-
fnvlist_add_uint32(ov, "vers_major", maj_v);
1919-
fnvlist_add_uint32(ov, "vers_minor", min_v);
1920-
fnvlist_add_nvlist(sch, "output_version", ov);
1921-
fnvlist_free(ov);
1914+
nvlist_t *sch = fnvlist_alloc();
1915+
json_add_output_version(sch, cmd, maj_v, min_v);
19221916
return (sch);
19231917
}
19241918

cmd/zpool/zpool_main.c

+7-45
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
#include "zfs_comutil.h"
7777
#include "zfeature_common.h"
7878
#include "zfs_valstr.h"
79+
#include "json.h"
80+
#include "literals.h"
7981

8082
#include "statcommon.h"
8183

@@ -309,41 +311,6 @@ static const char *checkpoint_state_str[] = {
309311
"DISCARDING"
310312
};
311313

312-
static const char *vdev_state_str[] = {
313-
"UNKNOWN",
314-
"CLOSED",
315-
"OFFLINE",
316-
"REMOVED",
317-
"CANT_OPEN",
318-
"FAULTED",
319-
"DEGRADED",
320-
"ONLINE"
321-
};
322-
323-
static const char *vdev_aux_str[] = {
324-
"NONE",
325-
"OPEN_FAILED",
326-
"CORRUPT_DATA",
327-
"NO_REPLICAS",
328-
"BAD_GUID_SUM",
329-
"TOO_SMALL",
330-
"BAD_LABEL",
331-
"VERSION_NEWER",
332-
"VERSION_OLDER",
333-
"UNSUP_FEAT",
334-
"SPARED",
335-
"ERR_EXCEEDED",
336-
"IO_FAILURE",
337-
"BAD_LOG",
338-
"EXTERNAL",
339-
"SPLIT_POOL",
340-
"BAD_ASHIFT",
341-
"EXTERNAL_PERSIST",
342-
"ACTIVE",
343-
"CHILDREN_OFFLINE",
344-
"ASHIFT_TOO_BIG"
345-
};
346-
347314
static const char *vdev_init_state_str[] = {
348315
"NONE",
349316
"ACTIVE",
@@ -1089,15 +1056,10 @@ static nvlist_t *
10891056
zpool_json_schema(int maj_v, int min_v)
10901057
{
10911058
char cmd[MAX_CMD_LEN];
1092-
nvlist_t *sch = fnvlist_alloc();
1093-
nvlist_t *ov = fnvlist_alloc();
1094-
10951059
snprintf(cmd, MAX_CMD_LEN, "zpool %s", current_command->name);
1096-
fnvlist_add_string(ov, "command", cmd);
1097-
fnvlist_add_uint32(ov, "vers_major", maj_v);
1098-
fnvlist_add_uint32(ov, "vers_minor", min_v);
1099-
fnvlist_add_nvlist(sch, "output_version", ov);
1100-
fnvlist_free(ov);
1060+
1061+
nvlist_t *sch = fnvlist_alloc();
1062+
json_add_output_version(sch, cmd, maj_v, min_v);
11011063
return (sch);
11021064
}
11031065

@@ -1247,7 +1209,7 @@ fill_vdev_info(nvlist_t *list, zpool_handle_t *zhp, char *name,
12471209
if (nvlist_lookup_uint64_array(nvdev, ZPOOL_CONFIG_VDEV_STATS,
12481210
(uint64_t **)&vs, &c) == 0) {
12491211
fnvlist_add_string(list, "state",
1250-
vdev_state_str[vs->vs_state]);
1212+
vdev_state_string(vs->vs_state));
12511213
}
12521214
}
12531215
}
@@ -9275,7 +9237,7 @@ vdev_stats_nvlist(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
92759237
fnvlist_add_string(vds, "was",
92769238
fnvlist_lookup_string(nv, ZPOOL_CONFIG_PATH));
92779239
} else if (vs->vs_aux != VDEV_AUX_NONE) {
9278-
fnvlist_add_string(vds, "aux", vdev_aux_str[vs->vs_aux]);
9240+
fnvlist_add_string(vds, "aux", vdev_aux_string(vs->vs_aux));
92799241
} else if (children == 0 && !isspare &&
92809242
getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL &&
92819243
VDEV_STAT_VALID(vs_physical_ashift, vsc) &&

include/Makefile.am

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ endif
88

99
COMMON_H = \
1010
cityhash.h \
11+
json.h \
12+
literals.h \
1113
zfeature_common.h \
1214
zfs_comutil.h \
1315
zfs_deleg.h \
@@ -176,6 +178,7 @@ COMMON_H = \
176178

177179

178180
KERNEL_H = \
181+
sys/spa_stats_json.h \
179182
sys/zfs_ioctl.h \
180183
sys/zfs_ioctl_impl.h \
181184
sys/zfs_onexit.h \

include/json.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9+
* or https://opensource.org/licenses/CDDL-1.0.
10+
* See the License for the specific language governing permissions
11+
* and limitations under the License.
12+
*
13+
* When distributing Covered Code, include this CDDL HEADER in each
14+
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15+
* If applicable, add the following below this CDDL HEADER, with the
16+
* fields enclosed by brackets "[]" replaced with your own identifying
17+
* information: Portions Copyright [yyyy] [name of copyright owner]
18+
*
19+
* CDDL HEADER END
20+
*/
21+
22+
/*
23+
* Copyright (c) 2025, Klara, Inc.
24+
*/
25+
26+
#ifndef _JSON_H
27+
#define _JSON_H extern __attribute__((visibility("default")))
28+
29+
#include <sys/nvpair.h>
30+
31+
#ifdef __cplusplus
32+
extern "C" {
33+
#endif
34+
35+
_JSON_H void json_add_output_version(nvlist_t *nvl, const char *cmd, int maj_v,
36+
int min_v);
37+
38+
#ifdef __cplusplus
39+
}
40+
#endif
41+
42+
#endif /* _JSON_H */

include/literals.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9+
* or https://opensource.org/licenses/CDDL-1.0.
10+
* See the License for the specific language governing permissions
11+
* and limitations under the License.
12+
*
13+
* When distributing Covered Code, include this CDDL HEADER in each
14+
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15+
* If applicable, add the following below this CDDL HEADER, with the
16+
* fields enclosed by brackets "[]" replaced with your own identifying
17+
* information: Portions Copyright [yyyy] [name of copyright owner]
18+
*
19+
* CDDL HEADER END
20+
*/
21+
22+
/*
23+
* Copyright (c) 2025, Klara, Inc.
24+
*/
25+
26+
#ifndef _LITERALS_H
27+
#define _LITERALS_H extern __attribute__((visibility("default")))
28+
29+
#include <sys/fs/zfs.h>
30+
31+
#ifdef __cplusplus
32+
extern "C" {
33+
#endif
34+
35+
_LITERALS_H const char *vdev_state_string(uint64_t state);
36+
_LITERALS_H const char *vdev_aux_string(uint64_t aux);
37+
38+
#ifdef __cplusplus
39+
}
40+
#endif
41+
42+
#endif /* _LITERALS_H */

include/sys/nvpair.h

+12
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,18 @@ _SYS_NVPAIR_H uint64_t fnvpair_value_uint64(const nvpair_t *nvp);
412412
_SYS_NVPAIR_H const char *fnvpair_value_string(const nvpair_t *nvp);
413413
_SYS_NVPAIR_H nvlist_t *fnvpair_value_nvlist(nvpair_t *nvp);
414414

415+
/* JSON generation */
416+
417+
typedef int (*nvjson_writer_t)(void *, const char *);
418+
typedef struct nvjson {
419+
char *buf;
420+
size_t size;
421+
nvjson_writer_t writer;
422+
void *writer_ctx;
423+
int (*str_handler)(const char *, nvjson_writer_t, void *);
424+
} nvjson_t;
425+
_SYS_NVPAIR_H int nvlist_to_json(nvjson_t *, nvlist_t *);
426+
415427
#ifdef __cplusplus
416428
}
417429
#endif

include/sys/spa_impl.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <sys/spa.h>
3636
#include <sys/spa_checkpoint.h>
3737
#include <sys/spa_log_spacemap.h>
38+
#include <sys/spa_stats_json.h>
3839
#include <sys/vdev.h>
3940
#include <sys/vdev_rebuild.h>
4041
#include <sys/vdev_removal.h>
@@ -447,6 +448,7 @@ struct spa {
447448
uint64_t spa_autotrim; /* automatic background trim? */
448449
uint64_t spa_errata; /* errata issues detected */
449450
spa_stats_t spa_stats; /* assorted spa statistics */
451+
spa_stats_json_t spa_stats_json; /* diagnostic status in JSON */
450452
spa_keystore_t spa_keystore; /* loaded crypto keys */
451453

452454
/* arc_memory_throttle() parameters during low memory condition */

include/sys/spa_stats_json.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9+
* or http://opensource.org/licenses/CDDL-1.0.
10+
* See the License for the specific language governing permissions
11+
* and limitations under the License.
12+
*
13+
* When distributing Covered Code, include this CDDL HEADER in each
14+
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15+
* If applicable, add the following below this CDDL HEADER, with the
16+
* fields enclosed by brackets "[]" replaced with your own identifying
17+
* information: Portions Copyright [yyyy] [name of copyright owner]
18+
*
19+
* CDDL HEADER END
20+
*/
21+
22+
/*
23+
* Copyright (c) 2024, Klara, Inc.
24+
*/
25+
26+
#ifndef _SYS_SPA_STATS_JSON_H
27+
#define _SYS_SPA_STATS_JSON_H
28+
29+
#include <sys/spa.h>
30+
#include <sys/kstat.h>
31+
32+
#ifdef __cplusplus
33+
extern "C" {
34+
#endif
35+
36+
typedef struct spa_stats_json {
37+
kmutex_t ssj_lock;
38+
kstat_t *ssj_kstat;
39+
} spa_stats_json_t;
40+
41+
extern int spa_stats_json_generate(spa_t *spa, char *buf, size_t size);
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif
46+
47+
#endif /* _SYS_SPA_STATS_JSON_H */

lib/libnvpair/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ dist_libnvpair_la_SOURCES = \
1717
nodist_libnvpair_la_SOURCES = \
1818
module/nvpair/nvpair_alloc_fixed.c \
1919
module/nvpair/nvpair.c \
20+
module/nvpair/nvpair_json.c \
2021
module/nvpair/fnvpair.c
2122

2223
libnvpair_la_LIBADD = \

lib/libnvpair/libnvpair.abi

+41
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@
196196
<elf-symbol name='nvlist_remove_all' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
197197
<elf-symbol name='nvlist_remove_nvpair' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
198198
<elf-symbol name='nvlist_size' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
199+
<elf-symbol name='nvlist_to_json' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
199200
<elf-symbol name='nvlist_unpack' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
200201
<elf-symbol name='nvlist_xalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
201202
<elf-symbol name='nvlist_xdup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -1879,6 +1880,25 @@
18791880
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'>
18801881
<subrange length='4' type-id='7359adad' id='16fe7105'/>
18811882
</array-type-def>
1883+
<typedef-decl name='nvjson_writer_t' type-id='b98b07cc' id='4e9d7f33'/>
1884+
<class-decl name='nvjson' size-in-bits='320' is-struct='yes' visibility='default' id='dcaf122b'>
1885+
<data-member access='public' layout-offset-in-bits='0'>
1886+
<var-decl name='buf' type-id='26a90f95' visibility='default'/>
1887+
</data-member>
1888+
<data-member access='public' layout-offset-in-bits='64'>
1889+
<var-decl name='size' type-id='b59d7dce' visibility='default'/>
1890+
</data-member>
1891+
<data-member access='public' layout-offset-in-bits='128'>
1892+
<var-decl name='writer' type-id='4e9d7f33' visibility='default'/>
1893+
</data-member>
1894+
<data-member access='public' layout-offset-in-bits='192'>
1895+
<var-decl name='writer_ctx' type-id='eaa32e2f' visibility='default'/>
1896+
</data-member>
1897+
<data-member access='public' layout-offset-in-bits='256'>
1898+
<var-decl name='str_handler' type-id='60a1a574' visibility='default'/>
1899+
</data-member>
1900+
</class-decl>
1901+
<typedef-decl name='nvjson_t' type-id='dcaf122b' id='25417009'/>
18821902
<class-decl name='__mbstate_t' size-in-bits='64' is-struct='yes' naming-typedef-id='55e5b2b5' visibility='default' id='87447a2e'>
18831903
<data-member access='public' layout-offset-in-bits='0'>
18841904
<var-decl name='__count' type-id='95e97e5e' visibility='default'/>
@@ -1898,8 +1918,11 @@
18981918
<typedef-decl name='__mbstate_t' type-id='87447a2e' id='55e5b2b5'/>
18991919
<typedef-decl name='mbstate_t' type-id='55e5b2b5' id='3d7d8cbf'/>
19001920
<typedef-decl name='wchar_t' type-id='95e97e5e' id='928221d2'/>
1921+
<pointer-type-def type-id='d3d2487a' size-in-bits='64' id='60a1a574'/>
1922+
<pointer-type-def type-id='fec2782a' size-in-bits='64' id='b98b07cc'/>
19011923
<pointer-type-def type-id='3d7d8cbf' size-in-bits='64' id='a68021ce'/>
19021924
<qualified-type-def type-id='a68021ce' restrict='yes' id='03aaab72'/>
1925+
<pointer-type-def type-id='25417009' size-in-bits='64' id='cd4de0be'/>
19031926
<pointer-type-def type-id='928221d2' size-in-bits='64' id='323d93c1'/>
19041927
<qualified-type-def type-id='323d93c1' restrict='yes' id='f1358bc3'/>
19051928
<function-decl name='fnvpair_value_boolean_value' mangled-name='fnvpair_value_boolean_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvpair_value_boolean_value'>
@@ -1973,6 +1996,17 @@
19731996
<parameter type-id='5ce45b60' name='nvl'/>
19741997
<return type-id='95e97e5e'/>
19751998
</function-decl>
1999+
<function-type size-in-bits='64' id='d3d2487a'>
2000+
<parameter type-id='80f4b756'/>
2001+
<parameter type-id='4e9d7f33'/>
2002+
<parameter type-id='eaa32e2f'/>
2003+
<return type-id='95e97e5e'/>
2004+
</function-type>
2005+
<function-type size-in-bits='64' id='fec2782a'>
2006+
<parameter type-id='eaa32e2f'/>
2007+
<parameter type-id='80f4b756'/>
2008+
<return type-id='95e97e5e'/>
2009+
</function-type>
19762010
</abi-instr>
19772011
<abi-instr address-size='64' path='lib/libnvpair/nvpair_alloc_system.c' language='LANG_C99'>
19782012
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
@@ -3434,4 +3468,11 @@
34343468
<qualified-type-def type-id='ee1d4944' const='yes' id='4b95388f'/>
34353469
<var-decl name='nv_fixed_ops' type-id='4b95388f' mangled-name='nv_fixed_ops' visibility='default' elf-symbol-id='nv_fixed_ops'/>
34363470
</abi-instr>
3471+
<abi-instr address-size='64' path='module/nvpair/nvpair_json.c' language='LANG_C99'>
3472+
<function-decl name='nvlist_to_json' mangled-name='nvlist_to_json' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='nvlist_to_json'>
3473+
<parameter type-id='cd4de0be'/>
3474+
<parameter type-id='5ce45b60'/>
3475+
<return type-id='95e97e5e'/>
3476+
</function-decl>
3477+
</abi-instr>
34373478
</abi-corpus>

0 commit comments

Comments
 (0)