1fa9e406ahrens/*
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5ea8dc4beschrock * Common Development and Distribution License (the "License").
6ea8dc4beschrock * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
21fa9e406ahrens/*
2255da60bMark J Musante * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23beb5628Shampavman * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24f78cdc3Paul Dagnelie * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
253b44223Jordan Paige Hendricks * Copyright 2019 Joyent, Inc.
26fa9e406ahrens */
27fa9e406ahrens
2855da60bMark J Musante/* Portions Copyright 2010 Robert Milkowski */
2955da60bMark J Musante
30eb63303Tom Caputi/*
31eb63303Tom Caputi * ZFS_MDB lets dmu.h know that we don't have dmu_ot, and we will define our
32eb63303Tom Caputi * own macros to access the target's dmu_ot.  Therefore it must be defined
33eb63303Tom Caputi * before including any ZFS headers.  Note that we don't define
34eb63303Tom Caputi * DMU_OT_IS_ENCRYPTED_IMPL() or DMU_OT_BYTESWAP_IMPL(), therefore using them
35eb63303Tom Caputi * will result in a compilation error.  If they are needed in the future, we
36eb63303Tom Caputi * can implement them similarly to mdb_dmu_ot_is_encrypted_impl().
37eb63303Tom Caputi */
38eb63303Tom Caputi#define	ZFS_MDB
39eb63303Tom Caputi#define	DMU_OT_IS_ENCRYPTED_IMPL(ot) mdb_dmu_ot_is_encrypted_impl(ot)
40eb63303Tom Caputi
41fa9e406ahrens#include <mdb/mdb_ctf.h>
42fa9e406ahrens#include <sys/zfs_context.h>
43fa9e406ahrens#include <sys/mdb_modapi.h>
44fa9e406ahrens#include <sys/dbuf.h>
45fa9e406ahrens#include <sys/dmu_objset.h>
46fa9e406ahrens#include <sys/dsl_dir.h>
47fa9e406ahrens#include <sys/dsl_pool.h>
48fa9e406ahrens#include <sys/metaslab_impl.h>
49fa9e406ahrens#include <sys/space_map.h>
50fa9e406ahrens#include <sys/list.h>
51fa9e406ahrens#include <sys/vdev_impl.h>
523f1f801Matthew Ahrens#include <sys/zap_leaf.h>
533f1f801Matthew Ahrens#include <sys/zap_impl.h>
549966ca1Matthew Ahrens#include <ctype.h>
550a586ceMark Shellenbaum#include <sys/zfs_acl.h>
560a586ceMark Shellenbaum#include <sys/sa_impl.h>
57dcbf3bdGeorge Wilson#include <sys/multilist.h>
58fa9e406ahrens
59fa9e406ahrens#ifdef _KERNEL
60fa9e406ahrens#define	ZFS_OBJ_NAME	"zfs"
61c55e05cMatthew Ahrensextern int64_t mdb_gethrtime(void);
62fa9e406ahrens#else
63fa9e406ahrens#define	ZFS_OBJ_NAME	"libzpool.so.1"
64fa9e406ahrens#endif
65fa9e406ahrens
6628e4da2Matthew Ahrens#define	ZFS_STRUCT	"struct " ZFS_OBJ_NAME "`"
6728e4da2Matthew Ahrens
68feef89cVictor Latushkin#ifndef _KERNEL
69feef89cVictor Latushkinint aok;
70feef89cVictor Latushkin#endif
71feef89cVictor Latushkin
722e4c998George Wilsonenum spa_flags {
732e4c998George Wilson	SPA_FLAG_CONFIG			= 1 << 0,
742e4c998George Wilson	SPA_FLAG_VDEVS			= 1 << 1,
752e4c998George Wilson	SPA_FLAG_ERRORS			= 1 << 2,
762e4c998George Wilson	SPA_FLAG_METASLAB_GROUPS	= 1 << 3,
772e4c998George Wilson	SPA_FLAG_METASLABS		= 1 << 4,
782e4c998George Wilson	SPA_FLAG_HISTOGRAMS		= 1 << 5
792e4c998George Wilson};
802e4c998George Wilson
8191e2a09Steve Gonczi/*
8291e2a09Steve Gonczi * If any of these flags are set, call spa_vdevs in spa_print
8391e2a09Steve Gonczi */
842e4c998George Wilson#define	SPA_FLAG_ALL_VDEV	\
852e4c998George Wilson	(SPA_FLAG_VDEVS | SPA_FLAG_ERRORS | SPA_FLAG_METASLAB_GROUPS | \
8691e2a09Steve Gonczi	SPA_FLAG_METASLABS)
872e4c998George Wilson
88fa9e406ahrensstatic int
89fa9e406ahrensgetmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp,
90fa9e406ahrens    const char *member, int len, void *buf)
91fa9e406ahrens{
92fa9e406ahrens	mdb_ctf_id_t id;
93fa9e406ahrens	ulong_t off;
94fa9e406ahrens	char name[64];
95fa9e406ahrens
96fa9e406ahrens	if (idp == NULL) {
97fa9e406ahrens		if (mdb_ctf_lookup_by_name(type, &id) == -1) {
98fa9e406ahrens			mdb_warn("couldn't find type %s", type);
99fa9e406ahrens			return (DCMD_ERR);
100fa9e406ahrens		}
101fa9e406ahrens		idp = &id;
102fa9e406ahrens	} else {
103fa9e406ahrens		type = name;
104fa9e406ahrens		mdb_ctf_type_name(*idp, name, sizeof (name));
105fa9e406ahrens	}
106fa9e406ahrens
107fa9e406ahrens	if (mdb_ctf_offsetof(*idp, member, &off) == -1) {
108fa9e406ahrens		mdb_warn("couldn't find member %s of type %s\n", member, type);
109fa9e406ahrens		return (DCMD_ERR);
110fa9e406ahrens	}
111fa9e406ahrens	if (off % 8 != 0) {
112fa9e406ahrens		mdb_warn("member %s of type %s is unsupported bitfield",
113fa9e406ahrens		    member, type);
114fa9e406ahrens		return (DCMD_ERR);
115fa9e406ahrens	}
116fa9e406ahrens	off /= 8;
117fa9e406ahrens
118fa9e406ahrens	if (mdb_vread(buf, len, addr + off) == -1) {
119fa9e406ahrens		mdb_warn("failed to read %s from %s at %p",
120fa9e406ahrens		    member, type, addr + off);
121fa9e406ahrens		return (DCMD_ERR);
122fa9e406ahrens	}
123fa9e406ahrens	/* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */
124fa9e406ahrens
125fa9e406ahrens	return (0);
126fa9e406ahrens}
127fa9e406ahrens
12828e4da2Matthew Ahrens#define	GETMEMB(addr, structname, member, dest) \
12928e4da2Matthew Ahrens	getmember(addr, ZFS_STRUCT structname, NULL, #member, \
13028e4da2Matthew Ahrens	sizeof (dest), &(dest))
131fa9e406ahrens
132fa9e406ahrens#define	GETMEMBID(addr, ctfid, member, dest) \
133fa9e406ahrens	getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest))
134fa9e406ahrens
1353f9d6adLin Lingstatic boolean_t
1363f9d6adLin Lingstrisprint(const char *cp)
1373f9d6adLin Ling{
1383f9d6adLin Ling	for (; *cp; cp++) {
1393f9d6adLin Ling		if (!isprint(*cp))
1403f9d6adLin Ling			return (B_FALSE);
1413f9d6adLin Ling	}
1423f9d6adLin Ling	return (B_TRUE);
1433f9d6adLin Ling}
1443f9d6adLin Ling
14517f1128Serapheim Dimitropoulos/*
14617f1128Serapheim Dimitropoulos * <addr>::sm_entries <buffer length in bytes>
14717f1128Serapheim Dimitropoulos *
14817f1128Serapheim Dimitropoulos * Treat the buffer specified by the given address as a buffer that contains
14917f1128Serapheim Dimitropoulos * space map entries. Iterate over the specified number of entries and print
15017f1128Serapheim Dimitropoulos * them in both encoded and decoded form.
15117f1128Serapheim Dimitropoulos */
15217f1128Serapheim Dimitropoulos/* ARGSUSED */
153fa9e406ahrensstatic int
15417f1128Serapheim Dimitropoulossm_entries(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
155fa9e406ahrens{
15617f1128Serapheim Dimitropoulos	uint64_t bufsz = 0;
15717f1128Serapheim Dimitropoulos	boolean_t preview = B_FALSE;
15817f1128Serapheim Dimitropoulos
15917f1128Serapheim Dimitropoulos	if (!(flags & DCMD_ADDRSPEC))
16017f1128Serapheim Dimitropoulos		return (DCMD_USAGE);
16117f1128Serapheim Dimitropoulos
16217f1128Serapheim Dimitropoulos	if (argc < 1) {
16317f1128Serapheim Dimitropoulos		preview = B_TRUE;
16417f1128Serapheim Dimitropoulos		bufsz = 2;
16517f1128Serapheim Dimitropoulos	} else if (argc != 1) {
16617f1128Serapheim Dimitropoulos		return (DCMD_USAGE);
16717f1128Serapheim Dimitropoulos	} else {
16817f1128Serapheim Dimitropoulos		switch (argv[0].a_type) {
16917f1128Serapheim Dimitropoulos		case MDB_TYPE_STRING:
17017f1128Serapheim Dimitropoulos			bufsz = mdb_strtoull(argv[0].a_un.a_str);
17117f1128Serapheim Dimitropoulos			break;
17217f1128Serapheim Dimitropoulos		case MDB_TYPE_IMMEDIATE:
17317f1128Serapheim Dimitropoulos			bufsz = argv[0].a_un.a_val;
17417f1128Serapheim Dimitropoulos			break;
17517f1128Serapheim Dimitropoulos		default:
17617f1128Serapheim Dimitropoulos			return (DCMD_USAGE);
17717f1128Serapheim Dimitropoulos		}
178fa9e406ahrens	}
179fa9e406ahrens
18017f1128Serapheim Dimitropoulos	char *actions[] = { "ALLOC", "FREE", "INVALID" };
18117f1128Serapheim Dimitropoulos	for (uintptr_t bufend = addr + bufsz; addr < bufend;
18217f1128Serapheim Dimitropoulos	    addr += sizeof (uint64_t)) {
18317f1128Serapheim Dimitropoulos		uint64_t nwords;
18417f1128Serapheim Dimitropoulos		uint64_t start_addr = addr;
185fa9e406ahrens
18617f1128Serapheim Dimitropoulos		uint64_t word = 0;
18717f1128Serapheim Dimitropoulos		if (mdb_vread(&word, sizeof (word), addr) == -1) {
18817f1128Serapheim Dimitropoulos			mdb_warn("failed to read space map entry %p", addr);
18917f1128Serapheim Dimitropoulos			return (DCMD_ERR);
19017f1128Serapheim Dimitropoulos		}
191fa9e406ahrens
19217f1128Serapheim Dimitropoulos		if (SM_PREFIX_DECODE(word) == SM_DEBUG_PREFIX) {
19317f1128Serapheim Dimitropoulos			(void) mdb_printf("\t    [%6llu] %s: txg %llu, "
19417f1128Serapheim Dimitropoulos			    "pass %llu\n",
19517f1128Serapheim Dimitropoulos			    (u_longlong_t)(addr),
19617f1128Serapheim Dimitropoulos			    actions[SM_DEBUG_ACTION_DECODE(word)],
19717f1128Serapheim Dimitropoulos			    (u_longlong_t)SM_DEBUG_TXG_DECODE(word),
19817f1128Serapheim Dimitropoulos			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(word));
19917f1128Serapheim Dimitropoulos			continue;
20017f1128Serapheim Dimitropoulos		}
201fa9e406ahrens
20217f1128Serapheim Dimitropoulos		char entry_type;
20317f1128Serapheim Dimitropoulos		uint64_t raw_offset, raw_run, vdev_id = SM_NO_VDEVID;
20417f1128Serapheim Dimitropoulos
20517f1128Serapheim Dimitropoulos		if (SM_PREFIX_DECODE(word) != SM2_PREFIX) {
20617f1128Serapheim Dimitropoulos			entry_type = (SM_TYPE_DECODE(word) == SM_ALLOC) ?
20717f1128Serapheim Dimitropoulos			    'A' : 'F';
20817f1128Serapheim Dimitropoulos			raw_offset = SM_OFFSET_DECODE(word);
20917f1128Serapheim Dimitropoulos			raw_run = SM_RUN_DECODE(word);
21017f1128Serapheim Dimitropoulos			nwords = 1;
21117f1128Serapheim Dimitropoulos		} else {
21217f1128Serapheim Dimitropoulos			ASSERT3U(SM_PREFIX_DECODE(word), ==, SM2_PREFIX);
21317f1128Serapheim Dimitropoulos
21417f1128Serapheim Dimitropoulos			raw_run = SM2_RUN_DECODE(word);
21517f1128Serapheim Dimitropoulos			vdev_id = SM2_VDEV_DECODE(word);
21617f1128Serapheim Dimitropoulos
21717f1128Serapheim Dimitropoulos			/* it is a two-word entry so we read another word */
21817f1128Serapheim Dimitropoulos			addr += sizeof (uint64_t);
21917f1128Serapheim Dimitropoulos			if (addr >= bufend) {
22017f1128Serapheim Dimitropoulos				mdb_warn("buffer ends in the middle of a two "
22117f1128Serapheim Dimitropoulos				    "word entry\n", addr);
22217f1128Serapheim Dimitropoulos				return (DCMD_ERR);
22317f1128Serapheim Dimitropoulos			}
22417f1128Serapheim Dimitropoulos
22517f1128Serapheim Dimitropoulos			if (mdb_vread(&word, sizeof (word), addr) == -1) {
22617f1128Serapheim Dimitropoulos				mdb_warn("failed to read space map entry %p",
22717f1128Serapheim Dimitropoulos				    addr);
22817f1128Serapheim Dimitropoulos				return (DCMD_ERR);
22917f1128Serapheim Dimitropoulos			}
23017f1128Serapheim Dimitropoulos
23117f1128Serapheim Dimitropoulos			entry_type = (SM2_TYPE_DECODE(word) == SM_ALLOC) ?
23217f1128Serapheim Dimitropoulos			    'A' : 'F';
23317f1128Serapheim Dimitropoulos			raw_offset = SM2_OFFSET_DECODE(word);
23417f1128Serapheim Dimitropoulos			nwords = 2;
23517f1128Serapheim Dimitropoulos		}
23617f1128Serapheim Dimitropoulos
23717f1128Serapheim Dimitropoulos		(void) mdb_printf("\t    [%6llx]    %c  range:"
23817f1128Serapheim Dimitropoulos		    " %010llx-%010llx  size: %06llx vdev: %06llu words: %llu\n",
23917f1128Serapheim Dimitropoulos		    (u_longlong_t)start_addr,
24017f1128Serapheim Dimitropoulos		    entry_type, (u_longlong_t)raw_offset,
24117f1128Serapheim Dimitropoulos		    (u_longlong_t)(raw_offset + raw_run),
24217f1128Serapheim Dimitropoulos		    (u_longlong_t)raw_run,
24317f1128Serapheim Dimitropoulos		    (u_longlong_t)vdev_id, (u_longlong_t)nwords);
24417f1128Serapheim Dimitropoulos
24517f1128Serapheim Dimitropoulos		if (preview)
24617f1128Serapheim Dimitropoulos			break;
247fa9e406ahrens	}
24817f1128Serapheim Dimitropoulos	return (DCMD_OK);
249fa9e406ahrens}
250fa9e406ahrens
251fa9e406ahrensstatic int
25228e4da2Matthew Ahrensmdb_dsl_dir_name(uintptr_t addr, char *buf)
253fa9e406ahrens{
254fa9e406ahrens	static int gotid;
255fa9e406ahrens	static mdb_ctf_id_t dd_id;
256fa9e406ahrens	uintptr_t dd_parent;
2579adfa60Matthew Ahrens	char dd_myname[ZFS_MAX_DATASET_NAME_LEN];
258fa9e406ahrens
259fa9e406ahrens	if (!gotid) {
26028e4da2Matthew Ahrens		if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dir",
261fa9e406ahrens		    &dd_id) == -1) {
262fa9e406ahrens			mdb_warn("couldn't find struct dsl_dir");
263fa9e406ahrens			return (DCMD_ERR);
264fa9e406ahrens		}
265fa9e406ahrens		gotid = TRUE;
266fa9e406ahrens	}
267fa9e406ahrens	if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) ||
268fa9e406ahrens	    GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) {
269fa9e406ahrens		return (DCMD_ERR);
270fa9e406ahrens	}
271fa9e406ahrens
272fa9e406ahrens	if (dd_parent) {
27328e4da2Matthew Ahrens		if (mdb_dsl_dir_name(dd_parent, buf))
274fa9e406ahrens			return (DCMD_ERR);
275fa9e406ahrens		strcat(buf, "/");
276fa9e406ahrens	}
277fa9e406ahrens
278fa9e406ahrens	if (dd_myname[0])
279fa9e406ahrens		strcat(buf, dd_myname);
280fa9e406ahrens	else
281fa9e406ahrens		strcat(buf, "???");
282fa9e406ahrens
283fa9e406ahrens	return (0);
284fa9e406ahrens}
285fa9e406ahrens
286fa9e406ahrensstatic int
287fa9e406ahrensobjset_name(uintptr_t addr, char *buf)
288fa9e406ahrens{
289fa9e406ahrens	static int gotid;
2904223fc7Mark Shellenbaum	static mdb_ctf_id_t os_id, ds_id;
291fa9e406ahrens	uintptr_t os_dsl_dataset;
2929adfa60Matthew Ahrens	char ds_snapname[ZFS_MAX_DATASET_NAME_LEN];
293fa9e406ahrens	uintptr_t ds_dir;
294fa9e406ahrens
295fa9e406ahrens	buf[0] = '\0';
296fa9e406ahrens
297fa9e406ahrens	if (!gotid) {
29828e4da2Matthew Ahrens		if (mdb_ctf_lookup_by_name(ZFS_STRUCT "objset",
2994223fc7Mark Shellenbaum		    &os_id) == -1) {
3004223fc7Mark Shellenbaum			mdb_warn("couldn't find struct objset");
301fa9e406ahrens			return (DCMD_ERR);
302fa9e406ahrens		}
30328e4da2Matthew Ahrens		if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dataset",
304fa9e406ahrens		    &ds_id) == -1) {
305fa9e406ahrens			mdb_warn("couldn't find struct dsl_dataset");
306fa9e406ahrens			return (DCMD_ERR);
307fa9e406ahrens		}
308fa9e406ahrens
309fa9e406ahrens		gotid = TRUE;
310fa9e406ahrens	}
311fa9e406ahrens
3124223fc7Mark Shellenbaum	if (GETMEMBID(addr, &os_id, os_dsl_dataset, os_dsl_dataset))
313fa9e406ahrens		return (DCMD_ERR);
314fa9e406ahrens
315fa9e406ahrens	if (os_dsl_dataset == 0) {
316fa9e406ahrens		strcat(buf, "mos");
317fa9e406ahrens		return (0);
318fa9e406ahrens	}
319fa9e406ahrens
320fa9e406ahrens	if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) ||
321fa9e406ahrens	    GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) {
322fa9e406ahrens		return (DCMD_ERR);
323fa9e406ahrens	}
324fa9e406ahrens
32528e4da2Matthew Ahrens	if (ds_dir && mdb_dsl_dir_name(ds_dir, buf))
326fa9e406ahrens		return (DCMD_ERR);
327fa9e406ahrens
328fa9e406ahrens	if (ds_snapname[0]) {
329fa9e406ahrens		strcat(buf, "@");
330fa9e406ahrens		strcat(buf, ds_snapname);
331fa9e406ahrens	}
332fa9e406ahrens	return (0);
333fa9e406ahrens}
334fa9e406ahrens
3358363e80George Wilsonstatic int
3368363e80George Wilsonenum_lookup(char *type, int val, const char *prefix, size_t size, char *out)
337fa9e406ahrens{
338fa9e406ahrens	const char *cp;
339fa9e406ahrens	size_t len = strlen(prefix);
3408363e80George Wilson	mdb_ctf_id_t enum_type;
3418363e80George Wilson
3428363e80George Wilson	if (mdb_ctf_lookup_by_name(type, &enum_type) != 0) {
3438363e80George Wilson		mdb_warn("Could not find enum for %s", type);
3448363e80George Wilson		return (-1);
3458363e80George Wilson	}
346fa9e406ahrens
3478363e80George Wilson	if ((cp = mdb_ctf_enum_name(enum_type, val)) != NULL) {
348fa9e406ahrens		if (strncmp(cp, prefix, len) == 0)
349fa9e406ahrens			cp += len;
350fa9e406ahrens		(void) strncpy(out, cp, size);
351fa9e406ahrens	} else {
352fa9e406ahrens		mdb_snprintf(out, size, "? (%d)", val);
353fa9e406ahrens	}
3548363e80George Wilson	return (0);
355fa9e406ahrens}
356fa9e406ahrens
357fa9e406ahrens/* ARGSUSED */
358fa9e406ahrensstatic int
359614409bahrenszfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
360614409bahrens{
361614409bahrens	/*
362614409bahrens	 * This table can be approximately generated by running:
363614409bahrens	 * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2
364614409bahrens	 */
365614409bahrens	static const char *params[] = {
36669962b5Matthew Ahrens		"arc_lotsfree_percent",
367bfcdb3dloli		"arc_pages_pp_reserve",
368bfcdb3dloli		"arc_reduce_dnlc_percent",
369bfcdb3dloli		"arc_swapfs_reserve",
370bfcdb3dloli		"arc_zio_arena_free_shift",
371bfcdb3dloli		"dbuf_cache_hiwater_pct",
372bfcdb3dloli		"dbuf_cache_lowater_pct",
373bfcdb3dloli		"dbuf_cache_max_bytes",
374bfcdb3dloli		"dbuf_cache_max_shift",
375bfcdb3dloli		"ddt_zap_indirect_blockshift",
376bfcdb3dloli		"ddt_zap_leaf_blockshift",
377bfcdb3dloli		"ditto_same_vdev_distance_shift",
378bfcdb3dloli		"dmu_find_threads",
379bfcdb3dloli		"dmu_rescan_dnode_threshold",
380bfcdb3dloli		"dsl_scan_delay_completion",
381bfcdb3dloli		"fzap_default_block_shift",
382bfcdb3dloli		"l2arc_feed_again",
383bfcdb3dloli		"l2arc_feed_min_ms",
384bfcdb3dloli		"l2arc_feed_secs",
385bfcdb3dloli		"l2arc_headroom",
386bfcdb3dloli		"l2arc_headroom_boost",
387bfcdb3dloli		"l2arc_noprefetch",
388bfcdb3dloli		"l2arc_norw",
389bfcdb3dloli		"l2arc_write_boost",
390bfcdb3dloli		"l2arc_write_max",
391bfcdb3dloli		"metaslab_aliquot",
392bfcdb3dloli		"metaslab_bias_enabled",
393bfcdb3dloli		"metaslab_debug_load",
394bfcdb3dloli		"metaslab_debug_unload",
395bfcdb3dloli		"metaslab_df_alloc_threshold",
396bfcdb3dloli		"metaslab_df_free_pct",
397bfcdb3dloli		"metaslab_fragmentation_factor_enabled",
398bfcdb3dloli		"metaslab_force_ganging",
399bfcdb3dloli		"metaslab_lba_weighting_enabled",
400bfcdb3dloli		"metaslab_load_pct",
401bfcdb3dloli		"metaslab_min_alloc_size",
402bfcdb3dloli		"metaslab_ndf_clump_shift",
403bfcdb3dloli		"metaslab_preload_enabled",
404bfcdb3dloli		"metaslab_preload_limit",
405bfcdb3dloli		"metaslab_trace_enabled",
406bfcdb3dloli		"metaslab_trace_max_entries",
407bfcdb3dloli		"metaslab_unload_delay",
408bfcdb3dloli		"metaslabs_per_vdev",
409bfcdb3dloli		"reference_history",
410bfcdb3dloli		"reference_tracking_enable",
411bfcdb3dloli		"send_holes_without_birth_time",
41269962b5Matthew Ahrens		"spa_asize_inflation",
413bfcdb3dloli		"spa_load_verify_data",
414bfcdb3dloli		"spa_load_verify_maxinflight",
415bfcdb3dloli		"spa_load_verify_metadata",
416bfcdb3dloli		"spa_max_replication_override",
417bfcdb3dloli		"spa_min_slop",
418bfcdb3dloli		"spa_mode_global",
419bfcdb3dloli		"spa_slop_shift",
420bfcdb3dloli		"space_map_blksz",
421bfcdb3dloli		"vdev_mirror_shift",
422bfcdb3dloli		"zfetch_max_distance",
423bfcdb3dloli		"zfs_abd_chunk_size",
424bfcdb3dloli		"zfs_abd_scatter_enabled",
425bfcdb3dloli		"zfs_arc_average_blocksize",
426bfcdb3dloli		"zfs_arc_evict_batch_limit",
427bfcdb3dloli		"zfs_arc_grow_retry",
428614409bahrens		"zfs_arc_max",
429bfcdb3dloli		"zfs_arc_meta_limit",
430bfcdb3dloli		"zfs_arc_meta_min",
431614409bahrens		"zfs_arc_min",
432bfcdb3dloli		"zfs_arc_p_min_shift",
433bfcdb3dloli		"zfs_arc_shrink_shift",
434bfcdb3dloli		"zfs_async_block_max_blocks",
435bfcdb3dloli		"zfs_ccw_retry_interval",
436bfcdb3dloli		"zfs_commit_timeout_pct",
437bfcdb3dloli		"zfs_compressed_arc_enabled",
438bfcdb3dloli		"zfs_condense_indirect_commit_entry_delay_ticks",
439bfcdb3dloli		"zfs_condense_indirect_vdevs_enable",
440bfcdb3dloli		"zfs_condense_max_obsolete_bytes",
441bfcdb3dloli		"zfs_condense_min_mapping_bytes",
442bfcdb3dloli		"zfs_condense_pct",
443bfcdb3dloli		"zfs_dbgmsg_maxsize",
444bfcdb3dloli		"zfs_deadman_checktime_ms",
445bfcdb3dloli		"zfs_deadman_enabled",
446bfcdb3dloli		"zfs_deadman_synctime_ms",
447bfcdb3dloli		"zfs_dedup_prefetch",
448614409bahrens		"zfs_default_bs",
449614409bahrens		"zfs_default_ibs",
450bfcdb3dloli		"zfs_delay_max_ns",
451bfcdb3dloli		"zfs_delay_min_dirty_percent",
452bfcdb3dloli		"zfs_delay_resolution_ns",
453bfcdb3dloli		"zfs_delay_scale",
454bfcdb3dloli		"zfs_dirty_data_max",
455bfcdb3dloli		"zfs_dirty_data_max_max",
456bfcdb3dloli		"zfs_dirty_data_max_percent",
457bfcdb3dloli		"zfs_dirty_data_sync",
458614409bahrens		"zfs_flags",
459bfcdb3dloli		"zfs_free_bpobj_enabled",
460bfcdb3dloli		"zfs_free_leak_on_eio",
461bfcdb3dloli		"zfs_free_min_time_ms",
462bfcdb3dloli		"zfs_fsync_sync_cnt",
463bfcdb3dloli		"zfs_immediate_write_sz",
464bfcdb3dloli		"zfs_indirect_condense_obsolete_pct",
465bfcdb3dloli		"zfs_lua_check_instrlimit_interval",
466bfcdb3dloli		"zfs_lua_max_instrlimit",
467bfcdb3dloli		"zfs_lua_max_memlimit",
468bfcdb3dloli		"zfs_max_recordsize",
469bfcdb3dloli		"zfs_mdcomp_disable",
470bfcdb3dloli		"zfs_metaslab_condense_block_threshold",
471bfcdb3dloli		"zfs_metaslab_fragmentation_threshold",
472bfcdb3dloli		"zfs_metaslab_segment_weight_enabled",
473bfcdb3dloli		"zfs_metaslab_switch_threshold",
474bfcdb3dloli		"zfs_mg_fragmentation_threshold",
475bfcdb3dloli		"zfs_mg_noalloc_threshold",
476bfcdb3dloli		"zfs_multilist_num_sublists",
477b16da2eGeorge Wilson		"zfs_no_scrub_io",
478b16da2eGeorge Wilson		"zfs_no_scrub_prefetch",
479614409bahrens		"zfs_nocacheflush",
480bfcdb3dloli		"zfs_nopwrite_enabled",
481bfcdb3dloli		"zfs_object_remap_one_indirect_delay_ticks",
482bfcdb3dloli		"zfs_obsolete_min_time_ms",
483bfcdb3dloli		"zfs_pd_bytes_max",
484bfcdb3dloli		"zfs_per_txg_dirty_frees_percent",
485bfcdb3dloli		"zfs_prefetch_disable",
486bfcdb3dloli		"zfs_read_chunk_size",
487bfcdb3dloli		"zfs_recover",
488bfcdb3dloli		"zfs_recv_queue_length",
489bfcdb3dloli		"zfs_redundant_metadata_most_ditto_level",
490bfcdb3dloli		"zfs_remap_blkptr_enable",
491bfcdb3dloli		"zfs_remove_max_copy_bytes",
492bfcdb3dloli		"zfs_remove_max_segment",
493bfcdb3dloli		"zfs_resilver_delay",
494bfcdb3dloli		"zfs_resilver_min_time_ms",
495bfcdb3dloli		"zfs_scan_idle",
496bfcdb3dloli		"zfs_scan_min_time_ms",
497bfcdb3dloli		"zfs_scrub_delay",
498bfcdb3dloli		"zfs_scrub_limit",
499bfcdb3dloli		"zfs_send_corrupt_data",
500bfcdb3dloli		"zfs_send_queue_length",
501bfcdb3dloli		"zfs_send_set_freerecords_bit",
502bfcdb3dloli		"zfs_sync_pass_deferred_free",
503bfcdb3dloli		"zfs_sync_pass_dont_compress",
504bfcdb3dloli		"zfs_sync_pass_rewrite",
505bfcdb3dloli		"zfs_sync_taskq_batch_pct",
506bfcdb3dloli		"zfs_top_maxinflight",
507bfcdb3dloli		"zfs_txg_timeout",
508bfcdb3dloli		"zfs_vdev_aggregation_limit",
509bfcdb3dloli		"zfs_vdev_async_read_max_active",
510bfcdb3dloli		"zfs_vdev_async_read_min_active",
511bfcdb3dloli		"zfs_vdev_async_write_active_max_dirty_percent",
512bfcdb3dloli		"zfs_vdev_async_write_active_min_dirty_percent",
513bfcdb3dloli		"zfs_vdev_async_write_max_active",
514bfcdb3dloli		"zfs_vdev_async_write_min_active",
515bfcdb3dloli		"zfs_vdev_cache_bshift",
516bfcdb3dloli		"zfs_vdev_cache_max",
517bfcdb3dloli		"zfs_vdev_cache_size",
518bfcdb3dloli		"zfs_vdev_max_active",
519bfcdb3dloli		"zfs_vdev_queue_depth_pct",
520bfcdb3dloli		"zfs_vdev_read_gap_limit",
521bfcdb3dloli		"zfs_vdev_removal_max_active",
522bfcdb3dloli		"zfs_vdev_removal_min_active",
523bfcdb3dloli		"zfs_vdev_scrub_max_active",
524bfcdb3dloli		"zfs_vdev_scrub_min_active",
525bfcdb3dloli		"zfs_vdev_sync_read_max_active",
526bfcdb3dloli		"zfs_vdev_sync_read_min_active",
527bfcdb3dloli		"zfs_vdev_sync_write_max_active",
528bfcdb3dloli		"zfs_vdev_sync_write_min_active",
529bfcdb3dloli		"zfs_vdev_write_gap_limit",
530bfcdb3dloli		"zfs_write_implies_delete_child",
531bfcdb3dloli		"zfs_zil_clean_taskq_maxalloc",
532bfcdb3dloli		"zfs_zil_clean_taskq_minalloc",
533bfcdb3dloli		"zfs_zil_clean_taskq_nthr_pct",
53455da60bMark J Musante		"zil_replay_disable",
535bfcdb3dloli		"zil_slog_bulk",
536bfcdb3dloli		"zio_buf_debug_limit",
537bfcdb3dloli		"zio_dva_throttle_enabled",
538614409bahrens		"zio_injection_enabled",
539614409bahrens		"zvol_immediate_write_sz",
540bfcdb3dloli		"zvol_maxphys",
541bfcdb3dloli		"zvol_unmap_enabled",
542bfcdb3dloli		"zvol_unmap_sync_enabled",
5435ac95daSerapheim Dimitropoulos		"zfs_max_dataset_nesting",
544614409bahrens	};
545614409bahrens
546b24ab67Jeff Bonwick	for (int i = 0; i < sizeof (params) / sizeof (params[0]); i++) {
547614409bahrens		int sz;
548614409bahrens		uint64_t val64;
549614409bahrens		uint32_t *val32p = (uint32_t *)&val64;
550614409bahrens
551614409bahrens		sz = mdb_readvar(&val64, params[i]);
552614409bahrens		if (sz == 4) {
553614409bahrens			mdb_printf("%s = 0x%x\n", params[i], *val32p);
554614409bahrens		} else if (sz == 8) {
555614409bahrens			mdb_printf("%s = 0x%llx\n", params[i], val64);
556614409bahrens		} else {
557614409bahrens			mdb_warn("variable %s not found", params[i]);
558614409bahrens		}
559614409bahrens	}
560614409bahrens
561614409bahrens	return (DCMD_OK);
562614409bahrens}
563614409bahrens
564614409bahrens/* ARGSUSED */
565614409bahrensstatic int
5665cabbc6Prashanth Sreenivasadva(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5675cabbc6Prashanth Sreenivasa{
5685cabbc6Prashanth Sreenivasa	dva_t dva;
5695cabbc6Prashanth Sreenivasa	if (mdb_vread(&dva, sizeof (dva_t), addr) == -1) {
5705cabbc6Prashanth Sreenivasa		mdb_warn("failed to read dva_t");
5715cabbc6Prashanth Sreenivasa		return (DCMD_ERR);
5725cabbc6Prashanth Sreenivasa	}
5735cabbc6Prashanth Sreenivasa	mdb_printf("<%llu:%llx:%llx>\n",
5745cabbc6Prashanth Sreenivasa	    (u_longlong_t)DVA_GET_VDEV(&dva),
5755cabbc6Prashanth Sreenivasa	    (u_longlong_t)DVA_GET_OFFSET(&dva),
5765cabbc6Prashanth Sreenivasa	    (u_longlong_t)DVA_GET_ASIZE(&dva));
5775cabbc6Prashanth Sreenivasa
5785cabbc6Prashanth Sreenivasa	return (DCMD_OK);
5795cabbc6Prashanth Sreenivasa}
5805cabbc6Prashanth Sreenivasa
581eb63303Tom Caputitypedef struct mdb_dmu_object_type_info {
582eb63303Tom Caputi	boolean_t ot_encrypt;
583eb63303Tom Caputi} mdb_dmu_object_type_info_t;
584eb63303Tom Caputi
585eb63303Tom Caputistatic boolean_t
586eb63303Tom Caputimdb_dmu_ot_is_encrypted_impl(dmu_object_type_t ot)
587eb63303Tom Caputi{
588eb63303Tom Caputi	mdb_dmu_object_type_info_t mdoti;
589eb63303Tom Caputi	GElf_Sym sym;
590eb63303Tom Caputi	size_t sz = mdb_ctf_sizeof_by_name("dmu_object_type_info_t");
591eb63303Tom Caputi
592eb63303Tom Caputi	if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "dmu_ot", &sym)) {
593eb63303Tom Caputi		mdb_warn("failed to find " ZFS_OBJ_NAME "`dmu_ot");
594eb63303Tom Caputi		return (B_FALSE);
595eb63303Tom Caputi	}
596eb63303Tom Caputi
597eb63303Tom Caputi	if (mdb_ctf_vread(&mdoti, "dmu_object_type_info_t",
598eb63303Tom Caputi	    "mdb_dmu_object_type_info_t", sym.st_value + sz * ot, 0) != 0) {
599eb63303Tom Caputi		return (B_FALSE);
600eb63303Tom Caputi	}
601eb63303Tom Caputi
602eb63303Tom Caputi	return (mdoti.ot_encrypt);
603eb63303Tom Caputi}
604eb63303Tom Caputi
6055cabbc6Prashanth Sreenivasa/* ARGSUSED */
6065cabbc6Prashanth Sreenivasastatic int
607fa9e406ahrensblkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
608fa9e406ahrens{
609b24ab67Jeff Bonwick	char type[80], checksum[80], compress[80];
610b24ab67Jeff Bonwick	blkptr_t blk, *bp = &blk;
611b24ab67Jeff Bonwick	char buf[BP_SPRINTF_LEN];
612fa9e406ahrens
613b24ab67Jeff Bonwick	if (mdb_vread(&blk, sizeof (blkptr_t), addr) == -1) {
614fa9e406ahrens		mdb_warn("failed to read blkptr_t");
615fa9e406ahrens		return (DCMD_ERR);
616fa9e406ahrens	}
617fa9e406ahrens
6188363e80George Wilson	if (enum_lookup("enum dmu_object_type", BP_GET_TYPE(bp), "DMU_OT_",
6198363e80George Wilson	    sizeof (type), type) == -1 ||
6208363e80George Wilson	    enum_lookup("enum zio_checksum", BP_GET_CHECKSUM(bp),
6218363e80George Wilson	    "ZIO_CHECKSUM_", sizeof (checksum), checksum) == -1 ||
6228363e80George Wilson	    enum_lookup("enum zio_compress", BP_GET_COMPRESS(bp),
6238363e80George Wilson	    "ZIO_COMPRESS_", sizeof (compress), compress) == -1) {
624b24ab67Jeff Bonwick		mdb_warn("Could not find blkptr enumerated types");
625fa9e406ahrens		return (DCMD_ERR);
626fa9e406ahrens	}
627fa9e406ahrens
62843466aaMax Grossman	SNPRINTF_BLKPTR(mdb_snprintf, '\n', buf, sizeof (buf), bp, type,
62943466aaMax Grossman	    checksum, compress);
630fa9e406ahrens
631b24ab67Jeff Bonwick	mdb_printf("%s\n", buf);
632fa9e406ahrens
633fa9e406ahrens	return (DCMD_OK);
634fa9e406ahrens}
635fa9e406ahrens
63628e4da2Matthew Ahrenstypedef struct mdb_dmu_buf_impl {
63728e4da2Matthew Ahrens	struct {
63828e4da2Matthew Ahrens		uint64_t db_object;
6392515f5dJustin T. Gibbs		uintptr_t db_data;
64028e4da2Matthew Ahrens	} db;
641d5ee8a1Matthew Ahrens	uintptr_t db_objset;
64228e4da2Matthew Ahrens	uint64_t db_level;
64328e4da2Matthew Ahrens	uint64_t db_blkid;
64428e4da2Matthew Ahrens	struct {
64528e4da2Matthew Ahrens		uint64_t rc_count;
64628e4da2Matthew Ahrens	} db_holds;
64728e4da2Matthew Ahrens} mdb_dmu_buf_impl_t;
64828e4da2Matthew Ahrens
649fa9e406ahrens/* ARGSUSED */
650fa9e406ahrensstatic int
651fa9e406ahrensdbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
652fa9e406ahrens{
65328e4da2Matthew Ahrens	mdb_dmu_buf_impl_t db;
654fa9e406ahrens	char objectname[32];
655fa9e406ahrens	char blkidname[32];
6569adfa60Matthew Ahrens	char path[ZFS_MAX_DATASET_NAME_LEN];
657ba3132cJoe Stein	int ptr_width = (int)(sizeof (void *)) * 2;
658fa9e406ahrens
65928e4da2Matthew Ahrens	if (DCMD_HDRSPEC(flags))
660ba3132cJoe Stein		mdb_printf("%*s %8s %3s %9s %5s %s\n",
661ba3132cJoe Stein		    ptr_width, "addr", "object", "lvl", "blkid", "holds", "os");
662fa9e406ahrens
66328e4da2Matthew Ahrens	if (mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t",
66428e4da2Matthew Ahrens	    addr, 0) == -1)
665fa9e406ahrens		return (DCMD_ERR);
666fa9e406ahrens
66728e4da2Matthew Ahrens	if (db.db.db_object == DMU_META_DNODE_OBJECT)
668fa9e406ahrens		(void) strcpy(objectname, "mdn");
669fa9e406ahrens	else
670fa9e406ahrens		(void) mdb_snprintf(objectname, sizeof (objectname), "%llx",
67128e4da2Matthew Ahrens		    (u_longlong_t)db.db.db_object);
672fa9e406ahrens
67328e4da2Matthew Ahrens	if (db.db_blkid == DMU_BONUS_BLKID)
674fa9e406ahrens		(void) strcpy(blkidname, "bonus");
675fa9e406ahrens	else
676fa9e406ahrens		(void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx",
67728e4da2Matthew Ahrens		    (u_longlong_t)db.db_blkid);
678fa9e406ahrens
679d5ee8a1Matthew Ahrens	if (objset_name(db.db_objset, path)) {
68028e4da2Matthew Ahrens		return (DCMD_ERR);
681fa9e406ahrens	}
682fa9e406ahrens
683ba3132cJoe Stein	mdb_printf("%*p %8s %3u %9s %5llu %s\n", ptr_width, addr,
68428e4da2Matthew Ahrens	    objectname, (int)db.db_level, blkidname,
68528e4da2Matthew Ahrens	    db.db_holds.rc_count, path);
686fa9e406ahrens
687fa9e406ahrens	return (DCMD_OK);
688fa9e406ahrens}
689fa9e406ahrens
690fa9e406ahrens/* ARGSUSED */
691fa9e406ahrensstatic int
692fa9e406ahrensdbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
693fa9e406ahrens{
694fa9e406ahrens#define	HISTOSZ 32
695fa9e406ahrens	uintptr_t dbp;
696fa9e406ahrens	dmu_buf_impl_t db;
697fa9e406ahrens	dbuf_hash_table_t ht;
698fa9e406ahrens	uint64_t bucket, ndbufs;
699fa9e406ahrens	uint64_t histo[HISTOSZ];
700fa9e406ahrens	uint64_t histo2[HISTOSZ];
701fa9e406ahrens	int i, maxidx;
702fa9e406ahrens
703fa9e406ahrens	if (mdb_readvar(&ht, "dbuf_hash_table") == -1) {
704fa9e406ahrens		mdb_warn("failed to read 'dbuf_hash_table'");
705fa9e406ahrens		return (DCMD_ERR);
706fa9e406ahrens	}
707fa9e406ahrens
708fa9e406ahrens	for (i = 0; i < HISTOSZ; i++) {
709fa9e406ahrens		histo[i] = 0;
710fa9e406ahrens		histo2[i] = 0;
711fa9e406ahrens	}
712fa9e406ahrens
713fa9e406ahrens	ndbufs = 0;
714fa9e406ahrens	for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) {
715fa9e406ahrens		int len;
716fa9e406ahrens
717fa9e406ahrens		if (mdb_vread(&dbp, sizeof (void *),
718fa9e406ahrens		    (uintptr_t)(ht.hash_table+bucket)) == -1) {
719fa9e406ahrens			mdb_warn("failed to read hash bucket %u at %p",
720fa9e406ahrens			    bucket, ht.hash_table+bucket);
721fa9e406ahrens			return (DCMD_ERR);
722fa9e406ahrens		}
723fa9e406ahrens
724fa9e406ahrens		len = 0;
725fa9e406ahrens		while (dbp != 0) {
726fa9e406ahrens			if (mdb_vread(&db, sizeof (dmu_buf_impl_t),
727fa9e406ahrens			    dbp) == -1) {
728fa9e406ahrens				mdb_warn("failed to read dbuf at %p", dbp);
729fa9e406ahrens				return (DCMD_ERR);
730fa9e406ahrens			}
731fa9e406ahrens			dbp = (uintptr_t)db.db_hash_next;
732fa9e406ahrens			for (i = MIN(len, HISTOSZ - 1); i >= 0; i--)
733fa9e406ahrens				histo2[i]++;
734fa9e406ahrens			len++;
735fa9e406ahrens			ndbufs++;
736fa9e406ahrens		}
737fa9e406ahrens
738fa9e406ahrens		if (len >= HISTOSZ)
739fa9e406ahrens			len = HISTOSZ-1;
740fa9e406ahrens		histo[len]++;
741fa9e406ahrens	}
742fa9e406ahrens
743fa9e406ahrens	mdb_printf("hash table has %llu buckets, %llu dbufs "
744fa9e406ahrens	    "(avg %llu buckets/dbuf)\n",
745fa9e406ahrens	    ht.hash_table_mask+1, ndbufs,
746fa9e406ahrens	    (ht.hash_table_mask+1)/ndbufs);
747fa9e406ahrens
748fa9e406ahrens	mdb_printf("\n");
749fa9e406ahrens	maxidx = 0;
750fa9e406ahrens	for (i = 0; i < HISTOSZ; i++)
751fa9e406ahrens		if (histo[i] > 0)
752fa9e406ahrens			maxidx = i;
753fa9e406ahrens	mdb_printf("hash chain length	number of buckets\n");
754fa9e406ahrens	for (i = 0; i <= maxidx; i++)
755fa9e406ahrens		mdb_printf("%u			%llu\n", i, histo[i]);
756fa9e406ahrens
757fa9e406ahrens	mdb_printf("\n");
758fa9e406ahrens	maxidx = 0;
759fa9e406ahrens	for (i = 0; i < HISTOSZ; i++)
760fa9e406ahrens		if (histo2[i] > 0)
761fa9e406ahrens			maxidx = i;
762fa9e406ahrens	mdb_printf("hash chain depth	number of dbufs\n");
763fa9e406ahrens	for (i = 0; i <= maxidx; i++)
764fa9e406ahrens		mdb_printf("%u or more		%llu	%llu%%\n",
765fa9e406ahrens		    i, histo2[i], histo2[i]*100/ndbufs);
766fa9e406ahrens
767fa9e406ahrens
768fa9e406ahrens	return (DCMD_OK);
769fa9e406ahrens}
770fa9e406ahrens
7713f1f801Matthew Ahrens#define	CHAIN_END 0xffff
7723f1f801Matthew Ahrens/*
7733f1f801Matthew Ahrens * ::zap_leaf [-v]
7743f1f801Matthew Ahrens *
7753f1f801Matthew Ahrens * Print a zap_leaf_phys_t, assumed to be 16k
7763f1f801Matthew Ahrens */
7773f1f801Matthew Ahrens/* ARGSUSED */
7783f1f801Matthew Ahrensstatic int
7793f1f801Matthew Ahrenszap_leaf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7803f1f801Matthew Ahrens{
7813f1f801Matthew Ahrens	char buf[16*1024];
7823f1f801Matthew Ahrens	int verbose = B_FALSE;
7833f1f801Matthew Ahrens	int four = B_FALSE;
784c137962Justin T. Gibbs	dmu_buf_t l_dbuf;
7853f1f801Matthew Ahrens	zap_leaf_t l;
7863f1f801Matthew Ahrens	zap_leaf_phys_t *zlp = (void *)buf;
7873f1f801Matthew Ahrens	int i;
7883f1f801Matthew Ahrens
7893f1f801Matthew Ahrens	if (mdb_getopts(argc, argv,
7903f1f801Matthew Ahrens	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
7913f1f801Matthew Ahrens	    '4', MDB_OPT_SETBITS, TRUE, &four,
7923f1f801Matthew Ahrens	    NULL) != argc)
7933f1f801Matthew Ahrens		return (DCMD_USAGE);
7943f1f801Matthew Ahrens
795c137962Justin T. Gibbs	l_dbuf.db_data = zlp;
796c137962Justin T. Gibbs	l.l_dbuf = &l_dbuf;
7973f1f801Matthew Ahrens	l.l_bs = 14; /* assume 16k blocks */
7983f1f801Matthew Ahrens	if (four)
7993f1f801Matthew Ahrens		l.l_bs = 12;
8003f1f801Matthew Ahrens
8013f1f801Matthew Ahrens	if (!(flags & DCMD_ADDRSPEC)) {
8023f1f801Matthew Ahrens		return (DCMD_USAGE);
8033f1f801Matthew Ahrens	}
8043f1f801Matthew Ahrens
8053f1f801Matthew Ahrens	if (mdb_vread(buf, sizeof (buf), addr) == -1) {
8063f1f801Matthew Ahrens		mdb_warn("failed to read zap_leaf_phys_t at %p", addr);
8073f1f801Matthew Ahrens		return (DCMD_ERR);
8083f1f801Matthew Ahrens	}
8093f1f801Matthew Ahrens
8103f1f801Matthew Ahrens	if (zlp->l_hdr.lh_block_type != ZBT_LEAF ||
8113f1f801Matthew Ahrens	    zlp->l_hdr.lh_magic != ZAP_LEAF_MAGIC) {
8123f1f801Matthew Ahrens		mdb_warn("This does not appear to be a zap_leaf_phys_t");
8133f1f801Matthew Ahrens		return (DCMD_ERR);
8143f1f801Matthew Ahrens	}
8153f1f801Matthew Ahrens
8163f1f801Matthew Ahrens	mdb_printf("zap_leaf_phys_t at %p:\n", addr);
8173f1f801Matthew Ahrens	mdb_printf("    lh_prefix_len = %u\n", zlp->l_hdr.lh_prefix_len);
8183f1f801Matthew Ahrens	mdb_printf("    lh_prefix = %llx\n", zlp->l_hdr.lh_prefix);
8193f1f801Matthew Ahrens	mdb_printf("    lh_nentries = %u\n", zlp->l_hdr.lh_nentries);
8203f1f801Matthew Ahrens	mdb_printf("    lh_nfree = %u\n", zlp->l_hdr.lh_nfree,
8213f1f801Matthew Ahrens	    zlp->l_hdr.lh_nfree * 100 / (ZAP_LEAF_NUMCHUNKS(&l)));
8223f1f801Matthew Ahrens	mdb_printf("    lh_freelist = %u\n", zlp->l_hdr.lh_freelist);
8233f1f801Matthew Ahrens	mdb_printf("    lh_flags = %x (%s)\n", zlp->l_hdr.lh_flags,
8243f1f801Matthew Ahrens	    zlp->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED ?
8253f1f801Matthew Ahrens	    "ENTRIES_CDSORTED" : "");
8263f1f801Matthew Ahrens
8273f1f801Matthew Ahrens	if (verbose) {
8283f1f801Matthew Ahrens		mdb_printf(" hash table:\n");
8293f1f801Matthew Ahrens		for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++) {
8303f1f801Matthew Ahrens			if (zlp->l_hash[i] != CHAIN_END)
8313f1f801Matthew Ahrens				mdb_printf("    %u: %u\n", i, zlp->l_hash[i]);
8323f1f801Matthew Ahrens		}
8333f1f801Matthew Ahrens	}
8343f1f801Matthew Ahrens
8353f1f801Matthew Ahrens	mdb_printf(" chunks:\n");
8363f1f801Matthew Ahrens	for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) {
8373f1f801Matthew Ahrens		/* LINTED: alignment */
8383f1f801Matthew Ahrens		zap_leaf_chunk_t *zlc = &ZAP_LEAF_CHUNK(&l, i);
8393f1f801Matthew Ahrens		switch (zlc->l_entry.le_type) {
8403f1f801Matthew Ahrens		case ZAP_CHUNK_FREE:
8413f1f801Matthew Ahrens			if (verbose) {
8423f1f801Matthew Ahrens				mdb_printf("    %u: free; lf_next = %u\n",
8433f1f801Matthew Ahrens				    i, zlc->l_free.lf_next);
8443f1f801Matthew Ahrens			}
8453f1f801Matthew Ahrens			break;
8463f1f801Matthew Ahrens		case ZAP_CHUNK_ENTRY:
8473f1f801Matthew Ahrens			mdb_printf("    %u: entry\n", i);
8483f1f801Matthew Ahrens			if (verbose) {
8493f1f801Matthew Ahrens				mdb_printf("        le_next = %u\n",
8503f1f801Matthew Ahrens				    zlc->l_entry.le_next);
8513f1f801Matthew Ahrens			}
8523f1f801Matthew Ahrens			mdb_printf("        le_name_chunk = %u\n",
8533f1f801Matthew Ahrens			    zlc->l_entry.le_name_chunk);
8543f1f801Matthew Ahrens			mdb_printf("        le_name_numints = %u\n",
8553f1f801Matthew Ahrens			    zlc->l_entry.le_name_numints);
8563f1f801Matthew Ahrens			mdb_printf("        le_value_chunk = %u\n",
8573f1f801Matthew Ahrens			    zlc->l_entry.le_value_chunk);
8583f1f801Matthew Ahrens			mdb_printf("        le_value_intlen = %u\n",
8593f1f801Matthew Ahrens			    zlc->l_entry.le_value_intlen);
8603f1f801Matthew Ahrens			mdb_printf("        le_value_numints = %u\n",
8613f1f801Matthew Ahrens			    zlc->l_entry.le_value_numints);
8623f1f801Matthew Ahrens			mdb_printf("        le_cd = %u\n",
8633f1f801Matthew Ahrens			    zlc->l_entry.le_cd);
8643f1f801Matthew Ahrens			mdb_printf("        le_hash = %llx\n",
8653f1f801Matthew Ahrens			    zlc->l_entry.le_hash);
8663f1f801Matthew Ahrens			break;
8673f1f801Matthew Ahrens		case ZAP_CHUNK_ARRAY:
8683f9d6adLin Ling			mdb_printf("    %u: array", i);
8693f9d6adLin Ling			if (strisprint((char *)zlc->l_array.la_array))
8703f9d6adLin Ling				mdb_printf(" \"%s\"", zlc->l_array.la_array);
8713f9d6adLin Ling			mdb_printf("\n");
8723f1f801Matthew Ahrens			if (verbose) {
8733f1f801Matthew Ahrens				int j;
8743f1f801Matthew Ahrens				mdb_printf("        ");
8753f1f801Matthew Ahrens				for (j = 0; j < ZAP_LEAF_ARRAY_BYTES; j++) {
8763f1f801Matthew Ahrens					mdb_printf("%02x ",
8773f1f801Matthew Ahrens					    zlc->l_array.la_array[j]);
8783f1f801Matthew Ahrens				}
8793f1f801Matthew Ahrens				mdb_printf("\n");
8803f1f801Matthew Ahrens			}
8813f1f801Matthew Ahrens			if (zlc->l_array.la_next != CHAIN_END) {
8823f1f801Matthew Ahrens				mdb_printf("        lf_next = %u\n",
8833f1f801Matthew Ahrens				    zlc->l_array.la_next);
8843f1f801Matthew Ahrens			}
8853f1f801Matthew Ahrens			break;
8863f1f801Matthew Ahrens		default:
8873f1f801Matthew Ahrens			mdb_printf("    %u: undefined type %u\n",
8883f1f801Matthew Ahrens			    zlc->l_entry.le_type);
8893f1f801Matthew Ahrens		}
8903f1f801Matthew Ahrens	}
8913f1f801Matthew Ahrens
8923f1f801Matthew Ahrens	return (DCMD_OK);
8933f1f801Matthew Ahrens}
8943f1f801Matthew Ahrens
895fa9e406ahrenstypedef struct dbufs_data {
896fa9e406ahrens	mdb_ctf_id_t id;
897fa9e406ahrens	uint64_t objset;
898fa9e406ahrens	uint64_t object;
899fa9e406ahrens	uint64_t level;
900fa9e406ahrens	uint64_t blkid;
901fa9e406ahrens	char *osname;
902fa9e406ahrens} dbufs_data_t;
903fa9e406ahrens
904