xref: /illumos-gate/usr/src/cmd/zdb/zdb.c (revision 814dcd43c3de9925fd6226c256e4d4327841a0e1)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
21ad135b5dSChristopher Siden 
22fa9e4066Sahrens /*
238f2529deSMark Shellenbaum  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24663207adSDon Brady  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25c3d26abcSMatthew Ahrens  * Copyright (c) 2014 Integros [integros.com]
26ed61ec1dSYuri Pankov  * Copyright 2017 Nexenta Systems, Inc.
27e0f1c0afSOlaf Faaland  * Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC.
28f06dce2cSAndrew Stormont  * Copyright 2017 RackTop Systems.
29fa9e4066Sahrens  */
30fa9e4066Sahrens 
31fa9e4066Sahrens #include <stdio.h>
32490d05b9SMatthew Ahrens #include <unistd.h>
33004388ebScasper #include <stdio_ext.h>
34fa9e4066Sahrens #include <stdlib.h>
3544cd46caSbillm #include <ctype.h>
36fa9e4066Sahrens #include <sys/zfs_context.h>
37fa9e4066Sahrens #include <sys/spa.h>
38fa9e4066Sahrens #include <sys/spa_impl.h>
39fa9e4066Sahrens #include <sys/dmu.h>
40fa9e4066Sahrens #include <sys/zap.h>
41fa9e4066Sahrens #include <sys/fs/zfs.h>
42fa9e4066Sahrens #include <sys/zfs_znode.h>
430a586ceaSMark Shellenbaum #include <sys/zfs_sa.h>
440a586ceaSMark Shellenbaum #include <sys/sa.h>
450a586ceaSMark Shellenbaum #include <sys/sa_impl.h>
46fa9e4066Sahrens #include <sys/vdev.h>
47fa9e4066Sahrens #include <sys/vdev_impl.h>
48fa9e4066Sahrens #include <sys/metaslab_impl.h>
49fa9e4066Sahrens #include <sys/dmu_objset.h>
50fa9e4066Sahrens #include <sys/dsl_dir.h>
51fa9e4066Sahrens #include <sys/dsl_dataset.h>
52fa9e4066Sahrens #include <sys/dsl_pool.h>
53fa9e4066Sahrens #include <sys/dbuf.h>
54fa9e4066Sahrens #include <sys/zil.h>
55fa9e4066Sahrens #include <sys/zil_impl.h>
56fa9e4066Sahrens #include <sys/stat.h>
57fa9e4066Sahrens #include <sys/resource.h>
58fa9e4066Sahrens #include <sys/dmu_traverse.h>
59fa9e4066Sahrens #include <sys/zio_checksum.h>
60fa9e4066Sahrens #include <sys/zio_compress.h>
61e0d35c44Smarks #include <sys/zfs_fuid.h>
6288b7b0f2SMatthew Ahrens #include <sys/arc.h>
63b24ab676SJeff Bonwick #include <sys/ddt.h>
64ad135b5dSChristopher Siden #include <sys/zfeature.h>
65770499e1SDan Kimmel #include <sys/abd.h>
664923c69fSMatthew Ahrens #include <sys/blkptr.h>
6717fb938fSMatthew Ahrens #include <sys/dsl_scan.h>
68eb633035STom Caputi #include <sys/dsl_crypt.h>
694445fffbSMatthew Ahrens #include <zfs_comutil.h>
700a055120SJason King #include <libcmdutils.h>
71de6628f0Sck #undef verify
72de6628f0Sck #include <libzfs.h>
73fa9e4066Sahrens 
743f7978d0SAlan Somers #include "zdb.h"
753f7978d0SAlan Somers 
76e690fb27SChristopher Siden #define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ?	\
77e690fb27SChristopher Siden 	zio_compress_table[(idx)].ci_name : "UNKNOWN")
78e690fb27SChristopher Siden #define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ?	\
79e690fb27SChristopher Siden 	zio_checksum_table[(idx)].ci_name : "UNKNOWN")
80e690fb27SChristopher Siden #define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ?	\
81e690fb27SChristopher Siden 	dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ?	\
82e690fb27SChristopher Siden 	dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN")
83e690fb27SChristopher Siden #define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) :		\
845cabbc6bSPrashanth Sreenivasa 	(idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA ?	\
855cabbc6bSPrashanth Sreenivasa 	DMU_OT_ZAP_OTHER : \
865cabbc6bSPrashanth Sreenivasa 	(idx) == DMU_OTN_UINT64_DATA || (idx) == DMU_OTN_UINT64_METADATA ? \
875cabbc6bSPrashanth Sreenivasa 	DMU_OT_UINT64_OTHER : DMU_OT_NUMTYPES)
886de8f417SVictor Latushkin 
89feef89cfSVictor Latushkin #ifndef lint
904dd77f9eSMatthew Ahrens extern int reference_tracking_enable;
917fd05ac4SMatthew Ahrens extern boolean_t zfs_recover;
9206be9802SMatthew Ahrens extern uint64_t zfs_arc_max, zfs_arc_meta_limit;
93f7950bf1SMatthew Ahrens extern int zfs_vdev_async_read_max_active;
94f06dce2cSAndrew Stormont extern int aok;
95e144c4e6SPavel Zakharov extern boolean_t spa_load_verify_dryrun;
96feef89cfSVictor Latushkin #else
974dd77f9eSMatthew Ahrens int reference_tracking_enable;
987fd05ac4SMatthew Ahrens boolean_t zfs_recover;
9906be9802SMatthew Ahrens uint64_t zfs_arc_max, zfs_arc_meta_limit;
100f7950bf1SMatthew Ahrens int zfs_vdev_async_read_max_active;
101f06dce2cSAndrew Stormont int aok;
102e144c4e6SPavel Zakharov boolean_t spa_load_verify_dryrun;
103feef89cfSVictor Latushkin #endif
104feef89cfSVictor Latushkin 
1053f7978d0SAlan Somers static const char cmdname[] = "zdb";
106fa9e4066Sahrens uint8_t dump_opt[256];
107fa9e4066Sahrens 
108fa9e4066Sahrens typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
109fa9e4066Sahrens 
110fa9e4066Sahrens uint64_t *zopt_object = NULL;
1113f7978d0SAlan Somers static unsigned zopt_objects = 0;
112de6628f0Sck libzfs_handle_t *g_zfs;
11306be9802SMatthew Ahrens uint64_t max_inflight = 1000;
11420b5dafbSPaul Dagnelie static int leaked_objects = 0;
115fa9e4066Sahrens 
116732885fcSMatthew Ahrens static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *);
11717fb938fSMatthew Ahrens static void mos_obj_refd(uint64_t);
118732885fcSMatthew Ahrens 
119fa9e4066Sahrens /*
120fa9e4066Sahrens  * These libumem hooks provide a reasonable set of defaults for the allocator's
121fa9e4066Sahrens  * debugging facilities.
122fa9e4066Sahrens  */
123fa9e4066Sahrens const char *
124fa9e4066Sahrens _umem_debug_init()
125fa9e4066Sahrens {
126fa9e4066Sahrens 	return ("default,verbose"); /* $UMEM_DEBUG setting */
127fa9e4066Sahrens }
128fa9e4066Sahrens 
129fa9e4066Sahrens const char *
130fa9e4066Sahrens _umem_logging_init(void)
131fa9e4066Sahrens {
132fa9e4066Sahrens 	return ("fail,contents"); /* $UMEM_LOGGING setting */
133fa9e4066Sahrens }
134fa9e4066Sahrens 
135fa9e4066Sahrens static void
136fa9e4066Sahrens usage(void)
137fa9e4066Sahrens {
138fa9e4066Sahrens 	(void) fprintf(stderr,
13986714001SSerapheim Dimitropoulos 	    "Usage:\t%s [-AbcdDFGhikLMPsvX] [-e [-V] [-p <path> ...]] "
140ed61ec1dSYuri Pankov 	    "[-I <inflight I/Os>]\n"
141ed61ec1dSYuri Pankov 	    "\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
142ed61ec1dSYuri Pankov 	    "\t\t[<poolname> [<object> ...]]\n"
143dfd5965fSRichard Yao 	    "\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] <dataset> "
144ed61ec1dSYuri Pankov 	    "[<object> ...]\n"
145ed61ec1dSYuri Pankov 	    "\t%s -C [-A] [-U <cache>]\n"
146ed61ec1dSYuri Pankov 	    "\t%s -l [-Aqu] <device>\n"
147dfd5965fSRichard Yao 	    "\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
148dfd5965fSRichard Yao 	    "[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
149ed61ec1dSYuri Pankov 	    "\t%s -O <dataset> <path>\n"
150dfd5965fSRichard Yao 	    "\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
151ed61ec1dSYuri Pankov 	    "\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
1524923c69fSMatthew Ahrens 	    "\t%s -E [-A] word0:word1:...:word15\n"
153dfd5965fSRichard Yao 	    "\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
154dfd5965fSRichard Yao 	    "<poolname>\n\n",
155ed61ec1dSYuri Pankov 	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
1564923c69fSMatthew Ahrens 	    cmdname, cmdname);
1573ad6c7f9SVictor Latushkin 
1583ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "    Dataset name must include at least one "
1593ad6c7f9SVictor Latushkin 	    "separator character '/' or '@'\n");
1603ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "    If dataset name is specified, only that "
1613ad6c7f9SVictor Latushkin 	    "dataset is dumped\n");
1623ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "    If object numbers are specified, only "
1633ad6c7f9SVictor Latushkin 	    "those objects are dumped\n\n");
1643ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "    Options to control amount of output:\n");
1653ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "        -b block statistics\n");
1663ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
1676365109dSVictor Latushkin 	    "all data) blocks\n");
168ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
169ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -d dataset(s)\n");
170f0ba89beSJeff Bonwick 	(void) fprintf(stderr, "        -D dedup statistics\n");
1714923c69fSMatthew Ahrens 	(void) fprintf(stderr, "        -E decode and display block from an "
1724923c69fSMatthew Ahrens 	    "embedded block pointer\n");
173ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -h pool history\n");
174ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -i intent logs\n");
17564723e36SYuri Pankov 	(void) fprintf(stderr, "        -l read label contents\n");
17686714001SSerapheim Dimitropoulos 	(void) fprintf(stderr, "        -k examine the checkpointed state "
17786714001SSerapheim Dimitropoulos 	    "of the pool\n");
17882a0a985SVictor Latushkin 	(void) fprintf(stderr, "        -L disable leak tracking (do not "
17982a0a985SVictor Latushkin 	    "load spacemaps)\n");
180ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -m metaslabs\n");
181ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -M metaslab groups\n");
182ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -O perform object lookups by path\n");
183d41e7643Sek 	(void) fprintf(stderr, "        -R read and display block from a "
184ed61ec1dSYuri Pankov 	    "device\n");
185ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
186ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
187ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -v verbose (applies to all "
188ed61ec1dSYuri Pankov 	    "others)\n\n");
1893ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "    Below options are intended for use "
190df15e419SMatthew Ahrens 	    "with other options:\n");
191feef89cfSVictor Latushkin 	(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
192feef89cfSVictor Latushkin 	    "panic recovery (-AA) or both (-AAA)\n");
1933ad6c7f9SVictor Latushkin 	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
1943ad6c7f9SVictor Latushkin 	    "has altroot/not in a cachefile\n");
195ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -F attempt automatic rewind within "
196ed61ec1dSYuri Pankov 	    "safe range of transaction groups\n");
197ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -G dump zfs_dbgmsg buffer before "
198ed61ec1dSYuri Pankov 	    "exiting\n");
1992e4c9986SGeorge Wilson 	(void) fprintf(stderr, "        -I <number of inflight I/Os> -- "
200df15e419SMatthew Ahrens 	    "specify the maximum number of "
201df15e419SMatthew Ahrens 	    "checksumming I/Os [default is 200]\n");
2020e60744cSPavel Zakharov 	(void) fprintf(stderr, "        -o <variable>=<value> set global "
2030e60744cSPavel Zakharov 	    "variable to an unsigned 32-bit integer value\n");
204ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -p <path> -- use one or more with "
205ed61ec1dSYuri Pankov 	    "-e to specify path to vdev dir\n");
206ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -P print numbers in parseable form\n");
20764723e36SYuri Pankov 	(void) fprintf(stderr, "        -q don't print label contents\n");
208ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
209ed61ec1dSYuri Pankov 	    "searching for uberblocks\n");
21064723e36SYuri Pankov 	(void) fprintf(stderr, "        -u uberblock\n");
211ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
212ed61ec1dSYuri Pankov 	    "cachefile\n");
213dfd5965fSRichard Yao 	(void) fprintf(stderr, "        -V do verbatim import\n");
214ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -x <dumpdir> -- "
215ed61ec1dSYuri Pankov 	    "dump all read blocks into specified directory\n");
216ed61ec1dSYuri Pankov 	(void) fprintf(stderr, "        -X attempt extreme rewind (does not "
217ed61ec1dSYuri Pankov 	    "work with dataset)\n\n");
218fa9e4066Sahrens 	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
219fa9e4066Sahrens 	    "to make only that option verbose\n");
220fa9e4066Sahrens 	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
221fa9e4066Sahrens 	exit(1);
222fa9e4066Sahrens }
223fa9e4066Sahrens 
22429bdd2f9SPavel Zakharov static void
22529bdd2f9SPavel Zakharov dump_debug_buffer()
22629bdd2f9SPavel Zakharov {
22729bdd2f9SPavel Zakharov 	if (dump_opt['G']) {
22829bdd2f9SPavel Zakharov 		(void) printf("\n");
22929bdd2f9SPavel Zakharov 		zfs_dbgmsg_print("zdb");
23029bdd2f9SPavel Zakharov 	}
23129bdd2f9SPavel Zakharov }
23229bdd2f9SPavel Zakharov 
233ccba0801SRich Morris /*
234ccba0801SRich Morris  * Called for usage errors that are discovered after a call to spa_open(),
235ccba0801SRich Morris  * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
236ccba0801SRich Morris  */
237ccba0801SRich Morris 
238fa9e4066Sahrens static void
239fa9e4066Sahrens fatal(const char *fmt, ...)
240fa9e4066Sahrens {
241fa9e4066Sahrens 	va_list ap;
242fa9e4066Sahrens 
243fa9e4066Sahrens 	va_start(ap, fmt);
244fa9e4066Sahrens 	(void) fprintf(stderr, "%s: ", cmdname);
245fa9e4066Sahrens 	(void) vfprintf(stderr, fmt, ap);
246fa9e4066Sahrens 	va_end(ap);
247fa9e4066Sahrens 	(void) fprintf(stderr, "\n");
248fa9e4066Sahrens 
24929bdd2f9SPavel Zakharov 	dump_debug_buffer();
25029bdd2f9SPavel Zakharov 
251ccba0801SRich Morris 	exit(1);
252fa9e4066Sahrens }
253fa9e4066Sahrens 
254fa9e4066Sahrens /* ARGSUSED */
255fa9e4066Sahrens static void
256fa9e4066Sahrens dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
257fa9e4066Sahrens {
258fa9e4066Sahrens 	nvlist_t *nv;
259fa9e4066Sahrens 	size_t nvsize = *(uint64_t *)data;
260fa9e4066Sahrens 	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
261fa9e4066Sahrens 
2627bfdf011SNeil Perrin 	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
263fa9e4066Sahrens 
264fa9e4066Sahrens 	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
265fa9e4066Sahrens 
266fa9e4066Sahrens 	umem_free(packed, nvsize);
267fa9e4066Sahrens 
268fa9e4066Sahrens 	dump_nvlist(nv, 8);
269fa9e4066Sahrens 
270fa9e4066Sahrens 	nvlist_free(nv);
271fa9e4066Sahrens }
272fa9e4066Sahrens 
2734445fffbSMatthew Ahrens /* ARGSUSED */
2744445fffbSMatthew Ahrens static void
2754445fffbSMatthew Ahrens dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
2764445fffbSMatthew Ahrens {
2774445fffbSMatthew Ahrens 	spa_history_phys_t *shp = data;
2784445fffbSMatthew Ahrens 
2794445fffbSMatthew Ahrens 	if (shp == NULL)
2804445fffbSMatthew Ahrens 		return;
2814445fffbSMatthew Ahrens 
2824445fffbSMatthew Ahrens 	(void) printf("\t\tpool_create_len = %llu\n",
2834445fffbSMatthew Ahrens 	    (u_longlong_t)shp->sh_pool_create_len);
2844445fffbSMatthew Ahrens 	(void) printf("\t\tphys_max_off = %llu\n",
2854445fffbSMatthew Ahrens 	    (u_longlong_t)shp->sh_phys_max_off);
2864445fffbSMatthew Ahrens 	(void) printf("\t\tbof = %llu\n",
2874445fffbSMatthew Ahrens 	    (u_longlong_t)shp->sh_bof);
2884445fffbSMatthew Ahrens 	(void) printf("\t\teof = %llu\n",
2894445fffbSMatthew Ahrens 	    (u_longlong_t)shp->sh_eof);
2904445fffbSMatthew Ahrens 	(void) printf("\t\trecords_lost = %llu\n",
2914445fffbSMatthew Ahrens 	    (u_longlong_t)shp->sh_records_lost);
2924445fffbSMatthew Ahrens }
2934445fffbSMatthew Ahrens 
2943f9d6ad7SLin Ling static void
2950a055120SJason King zdb_nicenum(uint64_t num, char *buf, size_t buflen)
2963f9d6ad7SLin Ling {
2973f9d6ad7SLin Ling 	if (dump_opt['P'])
2980a055120SJason King 		(void) snprintf(buf, buflen, "%llu", (longlong_t)num);
2993f9d6ad7SLin Ling 	else
3000a055120SJason King 		nicenum(num, buf, sizeof (buf));
3013f9d6ad7SLin Ling }
3023f9d6ad7SLin Ling 
3033f7978d0SAlan Somers static const char histo_stars[] = "****************************************";
3043f7978d0SAlan Somers static const uint64_t histo_width = sizeof (histo_stars) - 1;
305fa9e4066Sahrens 
306fa9e4066Sahrens static void
3070713e232SGeorge Wilson dump_histogram(const uint64_t *histo, int size, int offset)
308fa9e4066Sahrens {
309fa9e4066Sahrens 	int i;
310490d05b9SMatthew Ahrens 	int minidx = size - 1;
311fa9e4066Sahrens 	int maxidx = 0;
312fa9e4066Sahrens 	uint64_t max = 0;
313fa9e4066Sahrens 
314490d05b9SMatthew Ahrens 	for (i = 0; i < size; i++) {
315fa9e4066Sahrens 		if (histo[i] > max)
316fa9e4066Sahrens 			max = histo[i];
317fa9e4066Sahrens 		if (histo[i] > 0 && i > maxidx)
318fa9e4066Sahrens 			maxidx = i;
319fa9e4066Sahrens 		if (histo[i] > 0 && i < minidx)
320fa9e4066Sahrens 			minidx = i;
321fa9e4066Sahrens 	}
322fa9e4066Sahrens 
323490d05b9SMatthew Ahrens 	if (max < histo_width)
324490d05b9SMatthew Ahrens 		max = histo_width;
325fa9e4066Sahrens 
326490d05b9SMatthew Ahrens 	for (i = minidx; i <= maxidx; i++) {
327490d05b9SMatthew Ahrens 		(void) printf("\t\t\t%3u: %6llu %s\n",
3280713e232SGeorge Wilson 		    i + offset, (u_longlong_t)histo[i],
329490d05b9SMatthew Ahrens 		    &histo_stars[(max - histo[i]) * histo_width / max]);
330490d05b9SMatthew Ahrens 	}
331fa9e4066Sahrens }
332fa9e4066Sahrens 
333fa9e4066Sahrens static void
334fa9e4066Sahrens dump_zap_stats(objset_t *os, uint64_t object)
335fa9e4066Sahrens {
336fa9e4066Sahrens 	int error;
337fa9e4066Sahrens 	zap_stats_t zs;
338fa9e4066Sahrens 
339fa9e4066Sahrens 	error = zap_get_stats(os, object, &zs);
340fa9e4066Sahrens 	if (error)
341fa9e4066Sahrens 		return;
342fa9e4066Sahrens 
343fa9e4066Sahrens 	if (zs.zs_ptrtbl_len == 0) {
344fa9e4066Sahrens 		ASSERT(zs.zs_num_blocks == 1);
345fa9e4066Sahrens 		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
346fa9e4066Sahrens 		    (u_longlong_t)zs.zs_blocksize,
347fa9e4066Sahrens 		    (u_longlong_t)zs.zs_num_entries);
348fa9e4066Sahrens 		return;
349fa9e4066Sahrens 	}
350fa9e4066Sahrens 
351fa9e4066Sahrens 	(void) printf("\tFat ZAP stats:\n");
3528248818dSnd 
3538248818dSnd 	(void) printf("\t\tPointer table:\n");
3548248818dSnd 	(void) printf("\t\t\t%llu elements\n",
355fa9e4066Sahrens 	    (u_longlong_t)zs.zs_ptrtbl_len);
3568248818dSnd 	(void) printf("\t\t\tzt_blk: %llu\n",
3578248818dSnd 	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
3588248818dSnd 	(void) printf("\t\t\tzt_numblks: %llu\n",
3598248818dSnd 	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
3608248818dSnd 	(void) printf("\t\t\tzt_shift: %llu\n",
3618248818dSnd 	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
3628248818dSnd 	(void) printf("\t\t\tzt_blks_copied: %llu\n",
3638248818dSnd 	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
3648248818dSnd 	(void) printf("\t\t\tzt_nextblk: %llu\n",
3658248818dSnd 	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
3668248818dSnd 
367fa9e4066Sahrens 	(void) printf("\t\tZAP entries: %llu\n",
368fa9e4066Sahrens 	    (u_longlong_t)zs.zs_num_entries);
369fa9e4066Sahrens 	(void) printf("\t\tLeaf blocks: %llu\n",
370fa9e4066Sahrens 	    (u_longlong_t)zs.zs_num_leafs);
371fa9e4066Sahrens 	(void) printf("\t\tTotal blocks: %llu\n",
372fa9e4066Sahrens 	    (u_longlong_t)zs.zs_num_blocks);
3738248818dSnd 	(void) printf("\t\tzap_block_type: 0x%llx\n",
3748248818dSnd 	    (u_longlong_t)zs.zs_block_type);
3758248818dSnd 	(void) printf("\t\tzap_magic: 0x%llx\n",
3768248818dSnd 	    (u_longlong_t)zs.zs_magic);
3778248818dSnd 	(void) printf("\t\tzap_salt: 0x%llx\n",
3788248818dSnd 	    (u_longlong_t)zs.zs_salt);
379fa9e4066Sahrens 
380fa9e4066Sahrens 	(void) printf("\t\tLeafs with 2^n pointers:\n");
3810713e232SGeorge Wilson 	dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE, 0);
382fa9e4066Sahrens 
383fa9e4066Sahrens 	(void) printf("\t\tBlocks with n*5 entries:\n");
3840713e232SGeorge Wilson 	dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE, 0);
385fa9e4066Sahrens 
386fa9e4066Sahrens 	(void) printf("\t\tBlocks n/10 full:\n");
3870713e232SGeorge Wilson 	dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE, 0);
388fa9e4066Sahrens 
389fa9e4066Sahrens 	(void) printf("\t\tEntries with n chunks:\n");
3900713e232SGeorge Wilson 	dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE, 0);
391fa9e4066Sahrens 
392fa9e4066Sahrens 	(void) printf("\t\tBuckets with n entries:\n");
3930713e232SGeorge Wilson 	dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE, 0);
394fa9e4066Sahrens }
395fa9e4066Sahrens 
396fa9e4066Sahrens /*ARGSUSED*/
397fa9e4066Sahrens static void
398fa9e4066Sahrens dump_none(objset_t *os, uint64_t object, void *data, size_t size)
399fa9e4066Sahrens {
400fa9e4066Sahrens }
401fa9e4066Sahrens 
4026de8f417SVictor Latushkin /*ARGSUSED*/
4036de8f417SVictor Latushkin static void
4046de8f417SVictor Latushkin dump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
4056de8f417SVictor Latushkin {
4066de8f417SVictor Latushkin 	(void) printf("\tUNKNOWN OBJECT TYPE\n");
4076de8f417SVictor Latushkin }
4086de8f417SVictor Latushkin 
409fa9e4066Sahrens /*ARGSUSED*/
4103f7978d0SAlan Somers static void
411fa9e4066Sahrens dump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
412fa9e4066Sahrens {
413fa9e4066Sahrens }
414fa9e4066Sahrens 
415fa9e4066Sahrens /*ARGSUSED*/
416fa9e4066Sahrens static void
417fa9e4066Sahrens dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
418fa9e4066Sahrens {
419fa9e4066Sahrens }
420fa9e4066Sahrens 
421fa9e4066Sahrens /*ARGSUSED*/
422fa9e4066Sahrens static void
423fa9e4066Sahrens dump_zap(objset_t *os, uint64_t object, void *data, size_t size)
424fa9e4066Sahrens {
425fa9e4066Sahrens 	zap_cursor_t zc;
426fa9e4066Sahrens 	zap_attribute_t attr;
427fa9e4066Sahrens 	void *prop;
4283f7978d0SAlan Somers 	unsigned i;
429fa9e4066Sahrens 
430fa9e4066Sahrens 	dump_zap_stats(os, object);
431fa9e4066Sahrens 	(void) printf("\n");
432fa9e4066Sahrens 
433fa9e4066Sahrens 	for (zap_cursor_init(&zc, os, object);
434fa9e4066Sahrens 	    zap_cursor_retrieve(&zc, &attr) == 0;
435fa9e4066Sahrens 	    zap_cursor_advance(&zc)) {
436fa9e4066Sahrens 		(void) printf("\t\t%s = ", attr.za_name);
437fa9e4066Sahrens 		if (attr.za_num_integers == 0) {
438fa9e4066Sahrens 			(void) printf("\n");
439fa9e4066Sahrens 			continue;
440fa9e4066Sahrens 		}
441fa9e4066Sahrens 		prop = umem_zalloc(attr.za_num_integers *
442fa9e4066Sahrens 		    attr.za_integer_length, UMEM_NOFAIL);
443fa9e4066Sahrens 		(void) zap_lookup(os, object, attr.za_name,
444fa9e4066Sahrens 		    attr.za_integer_length, attr.za_num_integers, prop);
445fa9e4066Sahrens 		if (attr.za_integer_length == 1) {
4462d37a1a3SToomas Soome 			if (strcmp(attr.za_name,
4472d37a1a3SToomas Soome 			    DSL_CRYPTO_KEY_MASTER_KEY) == 0 ||
4482d37a1a3SToomas Soome 			    strcmp(attr.za_name,
4492d37a1a3SToomas Soome 			    DSL_CRYPTO_KEY_HMAC_KEY) == 0 ||
4502d37a1a3SToomas Soome 			    strcmp(attr.za_name, DSL_CRYPTO_KEY_IV) == 0 ||
4512d37a1a3SToomas Soome 			    strcmp(attr.za_name, DSL_CRYPTO_KEY_MAC) == 0) {
4522d37a1a3SToomas Soome 				uint8_t *u8 = prop;
4532d37a1a3SToomas Soome 
4542d37a1a3SToomas Soome 				for (i = 0; i < attr.za_num_integers; i++) {
4552d37a1a3SToomas Soome 					(void) printf("%02x", u8[i]);
4562d37a1a3SToomas Soome 				}
4572d37a1a3SToomas Soome 			} else {
4582d37a1a3SToomas Soome 				(void) printf("%s", (char *)prop);
4592d37a1a3SToomas Soome 			}
460fa9e4066Sahrens 		} else {
461fa9e4066Sahrens 			for (i = 0; i < attr.za_num_integers; i++) {
462fa9e4066Sahrens 				switch (attr.za_integer_length) {
463fa9e4066Sahrens 				case 2:
464fa9e4066Sahrens 					(void) printf("%u ",
465fa9e4066Sahrens 					    ((uint16_t *)prop)[i]);
466fa9e4066Sahrens 					break;
467fa9e4066Sahrens 				case 4:
468fa9e4066Sahrens 					(void) printf("%u ",
469fa9e4066Sahrens 					    ((uint32_t *)prop)[i]);
470fa9e4066Sahrens 					break;
471fa9e4066Sahrens 				case 8:
472fa9e4066Sahrens 					(void) printf("%lld ",
473fa9e4066Sahrens 					    (u_longlong_t)((int64_t *)prop)[i]);
474fa9e4066Sahrens 					break;
475fa9e4066Sahrens 				}
476fa9e4066Sahrens 			}
477fa9e4066Sahrens 		}
478fa9e4066Sahrens 		(void) printf("\n");
479fa9e4066Sahrens 		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
480fa9e4066Sahrens 	}
48187e5029aSahrens 	zap_cursor_fini(&zc);
482fa9e4066Sahrens }
483fa9e4066Sahrens 
484732885fcSMatthew Ahrens static void
485732885fcSMatthew Ahrens dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
486732885fcSMatthew Ahrens {
487732885fcSMatthew Ahrens 	bpobj_phys_t *bpop = data;
488732885fcSMatthew Ahrens 	char bytes[32], comp[32], uncomp[32];
489732885fcSMatthew Ahrens 
4900a055120SJason King 	/* make sure the output won't get truncated */
4910a055120SJason King 	CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
4920a055120SJason King 	CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
4930a055120SJason King 	CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
4940a055120SJason King 
495732885fcSMatthew Ahrens 	if (bpop == NULL)
496732885fcSMatthew Ahrens 		return;
497732885fcSMatthew Ahrens 
4980a055120SJason King 	zdb_nicenum(bpop->bpo_bytes, bytes, sizeof (bytes));
4990a055120SJason King 	zdb_nicenum(bpop->bpo_comp, comp, sizeof (comp));
5000a055120SJason King 	zdb_nicenum(bpop->bpo_uncomp, uncomp, sizeof (uncomp));
501732885fcSMatthew Ahrens 
502732885fcSMatthew Ahrens 	(void) printf("\t\tnum_blkptrs = %llu\n",
503732885fcSMatthew Ahrens 	    (u_longlong_t)bpop->bpo_num_blkptrs);
504732885fcSMatthew Ahrens 	(void) printf("\t\tbytes = %s\n", bytes);
505732885fcSMatthew Ahrens 	if (size >= BPOBJ_SIZE_V1) {
506732885fcSMatthew Ahrens 		(void) printf("\t\tcomp = %s\n", comp);
507732885fcSMatthew Ahrens 		(void) printf("\t\tuncomp = %s\n", uncomp);
508732885fcSMatthew Ahrens 	}
509732885fcSMatthew Ahrens 	if (size >= sizeof (*bpop)) {
510732885fcSMatthew Ahrens 		(void) printf("\t\tsubobjs = %llu\n",
511732885fcSMatthew Ahrens 		    (u_longlong_t)bpop->bpo_subobjs);
512732885fcSMatthew Ahrens 		(void) printf("\t\tnum_subobjs = %llu\n",
513732885fcSMatthew Ahrens 		    (u_longlong_t)bpop->bpo_num_subobjs);
514732885fcSMatthew Ahrens 	}
515732885fcSMatthew Ahrens 
516732885fcSMatthew Ahrens 	if (dump_opt['d'] < 5)
517732885fcSMatthew Ahrens 		return;
518732885fcSMatthew Ahrens 
519732885fcSMatthew Ahrens 	for (uint64_t i = 0; i < bpop->bpo_num_blkptrs; i++) {
520732885fcSMatthew Ahrens 		char blkbuf[BP_SPRINTF_LEN];
521732885fcSMatthew Ahrens 		blkptr_t bp;
522732885fcSMatthew Ahrens 
523732885fcSMatthew Ahrens 		int err = dmu_read(os, object,
524732885fcSMatthew Ahrens 		    i * sizeof (bp), sizeof (bp), &bp, 0);
525732885fcSMatthew Ahrens 		if (err != 0) {
526732885fcSMatthew Ahrens 			(void) printf("got error %u from dmu_read\n", err);
527732885fcSMatthew Ahrens 			break;
528732885fcSMatthew Ahrens 		}
529732885fcSMatthew Ahrens 		snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), &bp);
530732885fcSMatthew Ahrens 		(void) printf("\t%s\n", blkbuf);
531732885fcSMatthew Ahrens 	}
532732885fcSMatthew Ahrens }
533732885fcSMatthew Ahrens 
534732885fcSMatthew Ahrens /* ARGSUSED */
535732885fcSMatthew Ahrens static void
536732885fcSMatthew Ahrens dump_bpobj_subobjs(objset_t *os, uint64_t object, void *data, size_t size)
537732885fcSMatthew Ahrens {
538732885fcSMatthew Ahrens 	dmu_object_info_t doi;
539732885fcSMatthew Ahrens 
540732885fcSMatthew Ahrens 	VERIFY0(dmu_object_info(os, object, &doi));
541732885fcSMatthew Ahrens 	uint64_t *subobjs = kmem_alloc(doi.doi_max_offset, KM_SLEEP);
542732885fcSMatthew Ahrens 
543732885fcSMatthew Ahrens 	int err = dmu_read(os, object, 0, doi.doi_max_offset, subobjs, 0);
544732885fcSMatthew Ahrens 	if (err != 0) {
545732885fcSMatthew Ahrens 		(void) printf("got error %u from dmu_read\n", err);
546732885fcSMatthew Ahrens 		kmem_free(subobjs, doi.doi_max_offset);
547732885fcSMatthew Ahrens 		return;
548732885fcSMatthew Ahrens 	}
549732885fcSMatthew Ahrens 
550732885fcSMatthew Ahrens 	int64_t last_nonzero = -1;
551732885fcSMatthew Ahrens 	for (uint64_t i = 0; i < doi.doi_max_offset / 8; i++) {
552732885fcSMatthew Ahrens 		if (subobjs[i] != 0)
553732885fcSMatthew Ahrens 			last_nonzero = i;
554732885fcSMatthew Ahrens 	}
555732885fcSMatthew Ahrens 
556732885fcSMatthew Ahrens 	for (int64_t i = 0; i <= last_nonzero; i++) {
557732885fcSMatthew Ahrens 		(void) printf("\t%llu\n", (longlong_t)subobjs[i]);
558732885fcSMatthew Ahrens 	}
559732885fcSMatthew Ahrens 	kmem_free(subobjs, doi.doi_max_offset);
560732885fcSMatthew Ahrens }
561732885fcSMatthew Ahrens 
562486ae710SMatthew Ahrens /*ARGSUSED*/
563486ae710SMatthew Ahrens static void
564486ae710SMatthew Ahrens dump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
565486ae710SMatthew Ahrens {
566486ae710SMatthew Ahrens 	dump_zap_stats(os, object);
567486ae710SMatthew Ahrens 	/* contents are printed elsewhere, properly decoded */
568486ae710SMatthew Ahrens }
569486ae710SMatthew Ahrens 
5700a586ceaSMark Shellenbaum /*ARGSUSED*/
5710a586ceaSMark Shellenbaum static void
5720a586ceaSMark Shellenbaum dump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size)
5730a586ceaSMark Shellenbaum {
5740a586ceaSMark Shellenbaum 	zap_cursor_t zc;
5750a586ceaSMark Shellenbaum 	zap_attribute_t attr;
5760a586ceaSMark Shellenbaum 
5770a586ceaSMark Shellenbaum 	dump_zap_stats(os, object);
5780a586ceaSMark Shellenbaum 	(void) printf("\n");
5790a586ceaSMark Shellenbaum 
5800a586ceaSMark Shellenbaum 	for (zap_cursor_init(&zc, os, object);
5810a586ceaSMark Shellenbaum 	    zap_cursor_retrieve(&zc, &attr) == 0;
5820a586ceaSMark Shellenbaum 	    zap_cursor_advance(&zc)) {
5830a586ceaSMark Shellenbaum 		(void) printf("\t\t%s = ", attr.za_name);
5840a586ceaSMark Shellenbaum 		if (attr.za_num_integers == 0) {
5850a586ceaSMark Shellenbaum 			(void) printf("\n");
5860a586ceaSMark Shellenbaum 			continue;
5870a586ceaSMark Shellenbaum 		}
5880a586ceaSMark Shellenbaum 		(void) printf(" %llx : [%d:%d:%d]\n",
5890a586ceaSMark Shellenbaum 		    (u_longlong_t)attr.za_first_integer,
5900a586ceaSMark Shellenbaum 		    (int)ATTR_LENGTH(attr.za_first_integer),
5910a586ceaSMark Shellenbaum 		    (int)ATTR_BSWAP(attr.za_first_integer),
5920a586ceaSMark Shellenbaum 		    (int)ATTR_NUM(attr.za_first_integer));
5930a586ceaSMark Shellenbaum 	}
5940a586ceaSMark Shellenbaum 	zap_cursor_fini(&zc);
5950a586ceaSMark Shellenbaum }
5960a586ceaSMark Shellenbaum 
5970a586ceaSMark Shellenbaum /*ARGSUSED*/
5980a586ceaSMark Shellenbaum static void
5990a586ceaSMark Shellenbaum dump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size)
6000a586ceaSMark Shellenbaum {
6010a586ceaSMark Shellenbaum 	zap_cursor_t zc;
6020a586ceaSMark Shellenbaum 	zap_attribute_t attr;
6030a586ceaSMark Shellenbaum 	uint16_t *layout_attrs;
6043f7978d0SAlan Somers 	unsigned i;
6050a586ceaSMark Shellenbaum 
6060a586ceaSMark Shellenbaum 	dump_zap_stats(os, object);
6070a586ceaSMark Shellenbaum 	(void) printf("\n");
6080a586ceaSMark Shellenbaum 
6090a586ceaSMark Shellenbaum 	for (zap_cursor_init(&zc, os, object);
6100a586ceaSMark Shellenbaum 	    zap_cursor_retrieve(&zc, &attr) == 0;
6110a586ceaSMark Shellenbaum 	    zap_cursor_advance(&zc)) {
6120a586ceaSMark Shellenbaum 		(void) printf("\t\t%s = [", attr.za_name);
6130a586ceaSMark Shellenbaum 		if (attr.za_num_integers == 0) {
6140a586ceaSMark Shellenbaum 			(void) printf("\n");
6150a586ceaSMark Shellenbaum 			continue;
6160a586ceaSMark Shellenbaum 		}
6170a586ceaSMark Shellenbaum 
6180a586ceaSMark Shellenbaum 		VERIFY(attr.za_integer_length == 2);
6190a586ceaSMark Shellenbaum 		layout_attrs = umem_zalloc(attr.za_num_integers *
6200a586ceaSMark Shellenbaum 		    attr.za_integer_length, UMEM_NOFAIL);
6210a586ceaSMark Shellenbaum 
6220a586ceaSMark Shellenbaum 		VERIFY(zap_lookup(os, object, attr.za_name,
6230a586ceaSMark Shellenbaum 		    attr.za_integer_length,
6240a586ceaSMark Shellenbaum 		    attr.za_num_integers, layout_attrs) == 0);
6250a586ceaSMark Shellenbaum 
6260a586ceaSMark Shellenbaum 		for (i = 0; i != attr.za_num_integers; i++)
6270a586ceaSMark Shellenbaum 			(void) printf(" %d ", (int)layout_attrs[i]);
6280a586ceaSMark Shellenbaum 		(void) printf("]\n");
6290a586ceaSMark Shellenbaum 		umem_free(layout_attrs,
6300a586ceaSMark Shellenbaum 		    attr.za_num_integers * attr.za_integer_length);
6310a586ceaSMark Shellenbaum 	}
6320a586ceaSMark Shellenbaum 	zap_cursor_fini(&zc);
6330a586ceaSMark Shellenbaum }
6340a586ceaSMark Shellenbaum 
635e7437265Sahrens /*ARGSUSED*/
636e7437265Sahrens static void
637e7437265Sahrens dump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
638e7437265Sahrens {
639e7437265Sahrens 	zap_cursor_t zc;
640e7437265Sahrens 	zap_attribute_t attr;
641e7437265Sahrens 	const char *typenames[] = {
642e7437265Sahrens 		/* 0 */ "not specified",
643e7437265Sahrens 		/* 1 */ "FIFO",
644e7437265Sahrens 		/* 2 */ "Character Device",
645e7437265Sahrens 		/* 3 */ "3 (invalid)",
646e7437265Sahrens 		/* 4 */ "Directory",
647e7437265Sahrens 		/* 5 */ "5 (invalid)",
648e7437265Sahrens 		/* 6 */ "Block Device",
649e7437265Sahrens 		/* 7 */ "7 (invalid)",
650e7437265Sahrens 		/* 8 */ "Regular File",
651e7437265Sahrens 		/* 9 */ "9 (invalid)",
652e7437265Sahrens 		/* 10 */ "Symbolic Link",
653e7437265Sahrens 		/* 11 */ "11 (invalid)",
654e7437265Sahrens 		/* 12 */ "Socket",
655e7437265Sahrens 		/* 13 */ "Door",
656e7437265Sahrens 		/* 14 */ "Event Port",
657e7437265Sahrens 		/* 15 */ "15 (invalid)",
658e7437265Sahrens 	};
659e7437265Sahrens 
660e7437265Sahrens 	dump_zap_stats(os, object);
661e7437265Sahrens 	(void) printf("\n");
662e7437265Sahrens 
663e7437265Sahrens 	for (zap_cursor_init(&zc, os, object);
664e7437265Sahrens 	    zap_cursor_retrieve(&zc, &attr) == 0;
665e7437265Sahrens 	    zap_cursor_advance(&zc)) {
666e7437265Sahrens 		(void) printf("\t\t%s = %lld (type: %s)\n",
667e7437265Sahrens 		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
668e7437265Sahrens 		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
669e7437265Sahrens 	}
670e7437265Sahrens 	zap_cursor_fini(&zc);
671e7437265Sahrens }
672e7437265Sahrens 
6733f7978d0SAlan Somers static int
6740713e232SGeorge Wilson get_dtl_refcount(vdev_t *vd)
6750713e232SGeorge Wilson {
6760713e232SGeorge Wilson 	int refcount = 0;
6770713e232SGeorge Wilson 
6780713e232SGeorge Wilson 	if (vd->vdev_ops->vdev_op_leaf) {
6790713e232SGeorge Wilson 		space_map_t *sm = vd->vdev_dtl_sm;
6800713e232SGeorge Wilson 
6810713e232SGeorge Wilson 		if (sm != NULL &&
6820713e232SGeorge Wilson 		    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
6830713e232SGeorge Wilson 			return (1);
6840713e232SGeorge Wilson 		return (0);
6850713e232SGeorge Wilson 	}
6860713e232SGeorge Wilson 
6873f7978d0SAlan Somers 	for (unsigned c = 0; c < vd->vdev_children; c++)
6880713e232SGeorge Wilson 		refcount += get_dtl_refcount(vd->vdev_child[c]);
6890713e232SGeorge Wilson 	return (refcount);
6900713e232SGeorge Wilson }
6910713e232SGeorge Wilson 
6923f7978d0SAlan Somers static int
6930713e232SGeorge Wilson get_metaslab_refcount(vdev_t *vd)
6940713e232SGeorge Wilson {
6950713e232SGeorge Wilson 	int refcount = 0;
6960713e232SGeorge Wilson 
6975cabbc6bSPrashanth Sreenivasa 	if (vd->vdev_top == vd) {
6985cabbc6bSPrashanth Sreenivasa 		for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
6990713e232SGeorge Wilson 			space_map_t *sm = vd->vdev_ms[m]->ms_sm;
7000713e232SGeorge Wilson 
7010713e232SGeorge Wilson 			if (sm != NULL &&
7020713e232SGeorge Wilson 			    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
7030713e232SGeorge Wilson 				refcount++;
7040713e232SGeorge Wilson 		}
7050713e232SGeorge Wilson 	}
7063f7978d0SAlan Somers 	for (unsigned c = 0; c < vd->vdev_children; c++)
7070713e232SGeorge Wilson 		refcount += get_metaslab_refcount(vd->vdev_child[c]);
7080713e232SGeorge Wilson 
7090713e232SGeorge Wilson 	return (refcount);
7100713e232SGeorge Wilson }
7110713e232SGeorge Wilson 
7125cabbc6bSPrashanth Sreenivasa static int
7135cabbc6bSPrashanth Sreenivasa get_obsolete_refcount(vdev_t *vd)
7145cabbc6bSPrashanth Sreenivasa {
7155cabbc6bSPrashanth Sreenivasa 	int refcount = 0;
7165cabbc6bSPrashanth Sreenivasa 
7175cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_sm_obj = vdev_obsolete_sm_object(vd);
7185cabbc6bSPrashanth Sreenivasa 	if (vd->vdev_top == vd && obsolete_sm_obj != 0) {
7195cabbc6bSPrashanth Sreenivasa 		dmu_object_info_t doi;
7205cabbc6bSPrashanth Sreenivasa 		VERIFY0(dmu_object_info(vd->vdev_spa->spa_meta_objset,
7215cabbc6bSPrashanth Sreenivasa 		    obsolete_sm_obj, &doi));
7225cabbc6bSPrashanth Sreenivasa 		if (doi.doi_bonus_size == sizeof (space_map_phys_t)) {
7235cabbc6bSPrashanth Sreenivasa 			refcount++;
7245cabbc6bSPrashanth Sreenivasa 		}
7255cabbc6bSPrashanth Sreenivasa 	} else {
7265cabbc6bSPrashanth Sreenivasa 		ASSERT3P(vd->vdev_obsolete_sm, ==, NULL);
7275cabbc6bSPrashanth Sreenivasa 		ASSERT3U(obsolete_sm_obj, ==, 0);
7285cabbc6bSPrashanth Sreenivasa 	}
7295cabbc6bSPrashanth Sreenivasa 	for (unsigned c = 0; c < vd->vdev_children; c++) {
7305cabbc6bSPrashanth Sreenivasa 		refcount += get_obsolete_refcount(vd->vdev_child[c]);
7315cabbc6bSPrashanth Sreenivasa 	}
7325cabbc6bSPrashanth Sreenivasa 
7335cabbc6bSPrashanth Sreenivasa 	return (refcount);
7345cabbc6bSPrashanth Sreenivasa }
7355cabbc6bSPrashanth Sreenivasa 
7365cabbc6bSPrashanth Sreenivasa static int
7375cabbc6bSPrashanth Sreenivasa get_prev_obsolete_spacemap_refcount(spa_t *spa)
7385cabbc6bSPrashanth Sreenivasa {
7395cabbc6bSPrashanth Sreenivasa 	uint64_t prev_obj =
7405cabbc6bSPrashanth Sreenivasa 	    spa->spa_condensing_indirect_phys.scip_prev_obsolete_sm_object;
7415cabbc6bSPrashanth Sreenivasa 	if (prev_obj != 0) {
7425cabbc6bSPrashanth Sreenivasa 		dmu_object_info_t doi;
7435cabbc6bSPrashanth Sreenivasa 		VERIFY0(dmu_object_info(spa->spa_meta_objset, prev_obj, &doi));
7445cabbc6bSPrashanth Sreenivasa 		if (doi.doi_bonus_size == sizeof (space_map_phys_t)) {
7455cabbc6bSPrashanth Sreenivasa 			return (1);
7465cabbc6bSPrashanth Sreenivasa 		}
7475cabbc6bSPrashanth Sreenivasa 	}
7485cabbc6bSPrashanth Sreenivasa 	return (0);
7495cabbc6bSPrashanth Sreenivasa }
7505cabbc6bSPrashanth Sreenivasa 
75186714001SSerapheim Dimitropoulos static int
75286714001SSerapheim Dimitropoulos get_checkpoint_refcount(vdev_t *vd)
75386714001SSerapheim Dimitropoulos {
75486714001SSerapheim Dimitropoulos 	int refcount = 0;
75586714001SSerapheim Dimitropoulos 
75686714001SSerapheim Dimitropoulos 	if (vd->vdev_top == vd && vd->vdev_top_zap != 0 &&
75786714001SSerapheim Dimitropoulos 	    zap_contains(spa_meta_objset(vd->vdev_spa),
75886714001SSerapheim Dimitropoulos 	    vd->vdev_top_zap, VDEV_TOP_ZAP_POOL_CHECKPOINT_SM) == 0)
75986714001SSerapheim Dimitropoulos 		refcount++;
76086714001SSerapheim Dimitropoulos 
76186714001SSerapheim Dimitropoulos 	for (uint64_t c = 0; c < vd->vdev_children; c++)
76286714001SSerapheim Dimitropoulos 		refcount += get_checkpoint_refcount(vd->vdev_child[c]);
76386714001SSerapheim Dimitropoulos 
76486714001SSerapheim Dimitropoulos 	return (refcount);
76586714001SSerapheim Dimitropoulos }
76686714001SSerapheim Dimitropoulos 
767*814dcd43SSerapheim Dimitropoulos static int
768*814dcd43SSerapheim Dimitropoulos get_log_spacemap_refcount(spa_t *spa)
769*814dcd43SSerapheim Dimitropoulos {
770*814dcd43SSerapheim Dimitropoulos 	return (avl_numnodes(&spa->spa_sm_logs_by_txg));
771*814dcd43SSerapheim Dimitropoulos }
772*814dcd43SSerapheim Dimitropoulos 
7730713e232SGeorge Wilson static int
7740713e232SGeorge Wilson verify_spacemap_refcounts(spa_t *spa)
7750713e232SGeorge Wilson {
7762acef22dSMatthew Ahrens 	uint64_t expected_refcount = 0;
7772acef22dSMatthew Ahrens 	uint64_t actual_refcount;
7780713e232SGeorge Wilson 
7792acef22dSMatthew Ahrens 	(void) feature_get_refcount(spa,
7802acef22dSMatthew Ahrens 	    &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
7812acef22dSMatthew Ahrens 	    &expected_refcount);
7820713e232SGeorge Wilson 	actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
7830713e232SGeorge Wilson 	actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
7845cabbc6bSPrashanth Sreenivasa 	actual_refcount += get_obsolete_refcount(spa->spa_root_vdev);
7855cabbc6bSPrashanth Sreenivasa 	actual_refcount += get_prev_obsolete_spacemap_refcount(spa);
78686714001SSerapheim Dimitropoulos 	actual_refcount += get_checkpoint_refcount(spa->spa_root_vdev);
787*814dcd43SSerapheim Dimitropoulos 	actual_refcount += get_log_spacemap_refcount(spa);
7880713e232SGeorge Wilson 
7890713e232SGeorge Wilson 	if (expected_refcount != actual_refcount) {
7902acef22dSMatthew Ahrens 		(void) printf("space map refcount mismatch: expected %lld != "
7912acef22dSMatthew Ahrens 		    "actual %lld\n",
7922acef22dSMatthew Ahrens 		    (longlong_t)expected_refcount,
7932acef22dSMatthew Ahrens 		    (longlong_t)actual_refcount);
7940713e232SGeorge Wilson 		return (2);
7950713e232SGeorge Wilson 	}
7960713e232SGeorge Wilson 	return (0);
7970713e232SGeorge Wilson }
7980713e232SGeorge Wilson 
799fa9e4066Sahrens static void
8000713e232SGeorge Wilson dump_spacemap(objset_t *os, space_map_t *sm)
801fa9e4066Sahrens {
8025cabbc6bSPrashanth Sreenivasa 	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
8035cabbc6bSPrashanth Sreenivasa 	    "INVALID", "INVALID", "INVALID", "INVALID" };
804fa9e4066Sahrens 
8050713e232SGeorge Wilson 	if (sm == NULL)
806fa9e4066Sahrens 		return;
807fa9e4066Sahrens 
8085cabbc6bSPrashanth Sreenivasa 	(void) printf("space map object %llu:\n",
809555d674dSSerapheim Dimitropoulos 	    (longlong_t)sm->sm_object);
810555d674dSSerapheim Dimitropoulos 	(void) printf("  smp_length = 0x%llx\n",
811555d674dSSerapheim Dimitropoulos 	    (longlong_t)sm->sm_phys->smp_length);
8125cabbc6bSPrashanth Sreenivasa 	(void) printf("  smp_alloc = 0x%llx\n",
8135cabbc6bSPrashanth Sreenivasa 	    (longlong_t)sm->sm_phys->smp_alloc);
8145cabbc6bSPrashanth Sreenivasa 
815555d674dSSerapheim Dimitropoulos 	if (dump_opt['d'] < 6 && dump_opt['m'] < 4)
816555d674dSSerapheim Dimitropoulos 		return;
817555d674dSSerapheim Dimitropoulos 
818fa9e4066Sahrens 	/*
819fa9e4066Sahrens 	 * Print out the freelist entries in both encoded and decoded form.
820fa9e4066Sahrens 	 */
82117f11284SSerapheim Dimitropoulos 	uint8_t mapshift = sm->sm_shift;
82217f11284SSerapheim Dimitropoulos 	int64_t alloc = 0;
823555d674dSSerapheim Dimitropoulos 	uint64_t word, entry_id = 0;
82417f11284SSerapheim Dimitropoulos 	for (uint64_t offset = 0; offset < space_map_length(sm);
82517f11284SSerapheim Dimitropoulos 	    offset += sizeof (word)) {
8260713e232SGeorge Wilson 
8270713e232SGeorge Wilson 		VERIFY0(dmu_read(os, space_map_object(sm), offset,
82817f11284SSerapheim Dimitropoulos 		    sizeof (word), &word, DMU_READ_PREFETCH));
8290713e232SGeorge Wilson 
83017f11284SSerapheim Dimitropoulos 		if (sm_entry_is_debug(word)) {
831555d674dSSerapheim Dimitropoulos 			(void) printf("\t    [%6llu] %s: txg %llu pass %llu\n",
832555d674dSSerapheim Dimitropoulos 			    (u_longlong_t)entry_id,
83317f11284SSerapheim Dimitropoulos 			    ddata[SM_DEBUG_ACTION_DECODE(word)],
83417f11284SSerapheim Dimitropoulos 			    (u_longlong_t)SM_DEBUG_TXG_DECODE(word),
83517f11284SSerapheim Dimitropoulos 			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(word));
836555d674dSSerapheim Dimitropoulos 			entry_id++;
83717f11284SSerapheim Dimitropoulos 			continue;
83817f11284SSerapheim Dimitropoulos 		}
83917f11284SSerapheim Dimitropoulos 
84017f11284SSerapheim Dimitropoulos 		uint8_t words;
84117f11284SSerapheim Dimitropoulos 		char entry_type;
84217f11284SSerapheim Dimitropoulos 		uint64_t entry_off, entry_run, entry_vdev = SM_NO_VDEVID;
84317f11284SSerapheim Dimitropoulos 
84417f11284SSerapheim Dimitropoulos 		if (sm_entry_is_single_word(word)) {
84517f11284SSerapheim Dimitropoulos 			entry_type = (SM_TYPE_DECODE(word) == SM_ALLOC) ?
84617f11284SSerapheim Dimitropoulos 			    'A' : 'F';
84717f11284SSerapheim Dimitropoulos 			entry_off = (SM_OFFSET_DECODE(word) << mapshift) +
84817f11284SSerapheim Dimitropoulos 			    sm->sm_start;
84917f11284SSerapheim Dimitropoulos 			entry_run = SM_RUN_DECODE(word) << mapshift;
85017f11284SSerapheim Dimitropoulos 			words = 1;
851fa9e4066Sahrens 		} else {
85217f11284SSerapheim Dimitropoulos 			/* it is a two-word entry so we read another word */
85317f11284SSerapheim Dimitropoulos 			ASSERT(sm_entry_is_double_word(word));
85417f11284SSerapheim Dimitropoulos 
85517f11284SSerapheim Dimitropoulos 			uint64_t extra_word;
85617f11284SSerapheim Dimitropoulos 			offset += sizeof (extra_word);
85717f11284SSerapheim Dimitropoulos 			VERIFY0(dmu_read(os, space_map_object(sm), offset,
85817f11284SSerapheim Dimitropoulos 			    sizeof (extra_word), &extra_word,
85917f11284SSerapheim Dimitropoulos 			    DMU_READ_PREFETCH));
86017f11284SSerapheim Dimitropoulos 
86117f11284SSerapheim Dimitropoulos 			ASSERT3U(offset, <=, space_map_length(sm));
86217f11284SSerapheim Dimitropoulos 
86317f11284SSerapheim Dimitropoulos 			entry_run = SM2_RUN_DECODE(word) << mapshift;
86417f11284SSerapheim Dimitropoulos 			entry_vdev = SM2_VDEV_DECODE(word);
86517f11284SSerapheim Dimitropoulos 			entry_type = (SM2_TYPE_DECODE(extra_word) == SM_ALLOC) ?
86617f11284SSerapheim Dimitropoulos 			    'A' : 'F';
86717f11284SSerapheim Dimitropoulos 			entry_off = (SM2_OFFSET_DECODE(extra_word) <<
86817f11284SSerapheim Dimitropoulos 			    mapshift) + sm->sm_start;
86917f11284SSerapheim Dimitropoulos 			words = 2;
870fa9e4066Sahrens 		}
87117f11284SSerapheim Dimitropoulos 
87217f11284SSerapheim Dimitropoulos 		(void) printf("\t    [%6llu]    %c  range:"
87317f11284SSerapheim Dimitropoulos 		    " %010llx-%010llx  size: %06llx vdev: %06llu words: %u\n",
874555d674dSSerapheim Dimitropoulos 		    (u_longlong_t)entry_id,
87517f11284SSerapheim Dimitropoulos 		    entry_type, (u_longlong_t)entry_off,
87617f11284SSerapheim Dimitropoulos 		    (u_longlong_t)(entry_off + entry_run),
87717f11284SSerapheim Dimitropoulos 		    (u_longlong_t)entry_run,
87817f11284SSerapheim Dimitropoulos 		    (u_longlong_t)entry_vdev, words);
87917f11284SSerapheim Dimitropoulos 
88017f11284SSerapheim Dimitropoulos 		if (entry_type == 'A')
88117f11284SSerapheim Dimitropoulos 			alloc += entry_run;
88217f11284SSerapheim Dimitropoulos 		else
88317f11284SSerapheim Dimitropoulos 			alloc -= entry_run;
884555d674dSSerapheim Dimitropoulos 		entry_id++;
885fa9e4066Sahrens 	}
886555d674dSSerapheim Dimitropoulos 	if (alloc != space_map_allocated(sm)) {
88717f11284SSerapheim Dimitropoulos 		(void) printf("space_map_object alloc (%lld) INCONSISTENT "
88817f11284SSerapheim Dimitropoulos 		    "with space map summary (%lld)\n",
88917f11284SSerapheim Dimitropoulos 		    (longlong_t)space_map_allocated(sm), (longlong_t)alloc);
890fa9e4066Sahrens 	}
891fa9e4066Sahrens }
892fa9e4066Sahrens 
893d6e555bdSGeorge Wilson static void
894d6e555bdSGeorge Wilson dump_metaslab_stats(metaslab_t *msp)
895d6e555bdSGeorge Wilson {
8963f9d6ad7SLin Ling 	char maxbuf[32];
89786714001SSerapheim Dimitropoulos 	range_tree_t *rt = msp->ms_allocatable;
89886714001SSerapheim Dimitropoulos 	avl_tree_t *t = &msp->ms_allocatable_by_size;
8990713e232SGeorge Wilson 	int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
900d6e555bdSGeorge Wilson 
9010a055120SJason King 	/* max sure nicenum has enough space */
9020a055120SJason King 	CTASSERT(sizeof (maxbuf) >= NN_NUMBUF_SZ);
9030a055120SJason King 
9040a055120SJason King 	zdb_nicenum(metaslab_block_maxsize(msp), maxbuf, sizeof (maxbuf));
905d6e555bdSGeorge Wilson 
90687219db7SVictor Latushkin 	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
907d6e555bdSGeorge Wilson 	    "segments", avl_numnodes(t), "maxsize", maxbuf,
908d6e555bdSGeorge Wilson 	    "freepct", free_pct);
9090713e232SGeorge Wilson 	(void) printf("\tIn-memory histogram:\n");
9100713e232SGeorge Wilson 	dump_histogram(rt->rt_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
911d6e555bdSGeorge Wilson }
912d6e555bdSGeorge Wilson 
913fa9e4066Sahrens static void
914fa9e4066Sahrens dump_metaslab(metaslab_t *msp)
915fa9e4066Sahrens {
916fa9e4066Sahrens 	vdev_t *vd = msp->ms_group->mg_vd;
917fa9e4066Sahrens 	spa_t *spa = vd->vdev_spa;
9180713e232SGeorge Wilson 	space_map_t *sm = msp->ms_sm;
9193f9d6ad7SLin Ling 	char freebuf[32];
920fa9e4066Sahrens 
9210a055120SJason King 	zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf,
9220a055120SJason King 	    sizeof (freebuf));
923fa9e4066Sahrens 
924fa9e4066Sahrens 	(void) printf(
92587219db7SVictor Latushkin 	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
9260713e232SGeorge Wilson 	    (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
9270713e232SGeorge Wilson 	    (u_longlong_t)space_map_object(sm), freebuf);
928fa9e4066Sahrens 
9290713e232SGeorge Wilson 	if (dump_opt['m'] > 2 && !dump_opt['L']) {
930d6e555bdSGeorge Wilson 		mutex_enter(&msp->ms_lock);
931a0b03b16SSerapheim Dimitropoulos 		VERIFY0(metaslab_load(msp));
932a0b03b16SSerapheim Dimitropoulos 		range_tree_stat_verify(msp->ms_allocatable);
933bc3975b5SVictor Latushkin 		dump_metaslab_stats(msp);
9340713e232SGeorge Wilson 		metaslab_unload(msp);
935d6e555bdSGeorge Wilson 		mutex_exit(&msp->ms_lock);
936d6e555bdSGeorge Wilson 	}
937d6e555bdSGeorge Wilson 
9380713e232SGeorge Wilson 	if (dump_opt['m'] > 1 && sm != NULL &&
9392acef22dSMatthew Ahrens 	    spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
9400713e232SGeorge Wilson 		/*
9410713e232SGeorge Wilson 		 * The space map histogram represents free space in chunks
9420713e232SGeorge Wilson 		 * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
9430713e232SGeorge Wilson 		 */
9442e4c9986SGeorge Wilson 		(void) printf("\tOn-disk histogram:\t\tfragmentation %llu\n",
9452e4c9986SGeorge Wilson 		    (u_longlong_t)msp->ms_fragmentation);
9460713e232SGeorge Wilson 		dump_histogram(sm->sm_phys->smp_histogram,
9472e4c9986SGeorge Wilson 		    SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
9480713e232SGeorge Wilson 	}
9490713e232SGeorge Wilson 
950555d674dSSerapheim Dimitropoulos 	ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
951555d674dSSerapheim Dimitropoulos 	dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
952*814dcd43SSerapheim Dimitropoulos 
953*814dcd43SSerapheim Dimitropoulos 	if (spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP)) {
954*814dcd43SSerapheim Dimitropoulos 		(void) printf("\tFlush data:\n\tunflushed txg=%llu\n\n",
955*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)metaslab_unflushed_txg(msp));
956*814dcd43SSerapheim Dimitropoulos 	}
95787219db7SVictor Latushkin }
958fa9e4066Sahrens 
95987219db7SVictor Latushkin static void
96087219db7SVictor Latushkin print_vdev_metaslab_header(vdev_t *vd)
96187219db7SVictor Latushkin {
962663207adSDon Brady 	vdev_alloc_bias_t alloc_bias = vd->vdev_alloc_bias;
963*814dcd43SSerapheim Dimitropoulos 	const char *bias_str = "";
964*814dcd43SSerapheim Dimitropoulos 
965*814dcd43SSerapheim Dimitropoulos 	if (alloc_bias == VDEV_BIAS_LOG || vd->vdev_islog) {
966*814dcd43SSerapheim Dimitropoulos 		bias_str = VDEV_ALLOC_BIAS_LOG;
967*814dcd43SSerapheim Dimitropoulos 	} else if (alloc_bias == VDEV_BIAS_SPECIAL) {
968*814dcd43SSerapheim Dimitropoulos 		bias_str = VDEV_ALLOC_BIAS_SPECIAL;
969*814dcd43SSerapheim Dimitropoulos 	} else if (alloc_bias == VDEV_BIAS_DEDUP) {
970*814dcd43SSerapheim Dimitropoulos 		bias_str = VDEV_ALLOC_BIAS_DEDUP;
971*814dcd43SSerapheim Dimitropoulos 	}
972*814dcd43SSerapheim Dimitropoulos 
973*814dcd43SSerapheim Dimitropoulos 	uint64_t ms_flush_data_obj = 0;
974*814dcd43SSerapheim Dimitropoulos 	if (vd->vdev_top_zap != 0) {
975*814dcd43SSerapheim Dimitropoulos 		int error = zap_lookup(spa_meta_objset(vd->vdev_spa),
976*814dcd43SSerapheim Dimitropoulos 		    vd->vdev_top_zap, VDEV_TOP_ZAP_MS_UNFLUSHED_PHYS_TXGS,
977*814dcd43SSerapheim Dimitropoulos 		    sizeof (uint64_t), 1, &ms_flush_data_obj);
978*814dcd43SSerapheim Dimitropoulos 		if (error != ENOENT) {
979*814dcd43SSerapheim Dimitropoulos 			ASSERT0(error);
980*814dcd43SSerapheim Dimitropoulos 		}
981*814dcd43SSerapheim Dimitropoulos 	}
982*814dcd43SSerapheim Dimitropoulos 
983*814dcd43SSerapheim Dimitropoulos 	(void) printf("\tvdev %10llu   %s",
984*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)vd->vdev_id, bias_str);
985663207adSDon Brady 
986*814dcd43SSerapheim Dimitropoulos 	if (ms_flush_data_obj != 0) {
987*814dcd43SSerapheim Dimitropoulos 		(void) printf("   ms_unflushed_phys object %llu",
988*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)ms_flush_data_obj);
989*814dcd43SSerapheim Dimitropoulos 	}
990663207adSDon Brady 
991*814dcd43SSerapheim Dimitropoulos 	(void) printf("\n\t%-10s%5llu   %-19s   %-15s   %-12s\n",
99287219db7SVictor Latushkin 	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
99387219db7SVictor Latushkin 	    "offset", "spacemap", "free");
994663207adSDon Brady 	(void) printf("\t%15s   %19s   %15s   %12s\n",
99587219db7SVictor Latushkin 	    "---------------", "-------------------",
996663207adSDon Brady 	    "---------------", "------------");
997fa9e4066Sahrens }
998fa9e4066Sahrens 
9992e4c9986SGeorge Wilson static void
10002e4c9986SGeorge Wilson dump_metaslab_groups(spa_t *spa)
10012e4c9986SGeorge Wilson {
10022e4c9986SGeorge Wilson 	vdev_t *rvd = spa->spa_root_vdev;
10032e4c9986SGeorge Wilson 	metaslab_class_t *mc = spa_normal_class(spa);
10042e4c9986SGeorge Wilson 	uint64_t fragmentation;
10052e4c9986SGeorge Wilson 
10062e4c9986SGeorge Wilson 	metaslab_class_histogram_verify(mc);
10072e4c9986SGeorge Wilson 
10083f7978d0SAlan Somers 	for (unsigned c = 0; c < rvd->vdev_children; c++) {
10092e4c9986SGeorge Wilson 		vdev_t *tvd = rvd->vdev_child[c];
10102e4c9986SGeorge Wilson 		metaslab_group_t *mg = tvd->vdev_mg;
10112e4c9986SGeorge Wilson 
1012663207adSDon Brady 		if (mg == NULL || mg->mg_class != mc)
10132e4c9986SGeorge Wilson 			continue;
10142e4c9986SGeorge Wilson 
10152e4c9986SGeorge Wilson 		metaslab_group_histogram_verify(mg);
10162e4c9986SGeorge Wilson 		mg->mg_fragmentation = metaslab_group_fragmentation(mg);
10172e4c9986SGeorge Wilson 
10182e4c9986SGeorge Wilson 		(void) printf("\tvdev %10llu\t\tmetaslabs%5llu\t\t"
10192e4c9986SGeorge Wilson 		    "fragmentation",
10202e4c9986SGeorge Wilson 		    (u_longlong_t)tvd->vdev_id,
10212e4c9986SGeorge Wilson 		    (u_longlong_t)tvd->vdev_ms_count);
10222e4c9986SGeorge Wilson 		if (mg->mg_fragmentation == ZFS_FRAG_INVALID) {
10232e4c9986SGeorge Wilson 			(void) printf("%3s\n", "-");
10242e4c9986SGeorge Wilson 		} else {
10252e4c9986SGeorge Wilson 			(void) printf("%3llu%%\n",
10262e4c9986SGeorge Wilson 			    (u_longlong_t)mg->mg_fragmentation);
10272e4c9986SGeorge Wilson 		}
10282e4c9986SGeorge Wilson 		dump_histogram(mg->mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
10292e4c9986SGeorge Wilson 	}
10302e4c9986SGeorge Wilson 
10312e4c9986SGeorge Wilson 	(void) printf("\tpool %s\tfragmentation", spa_name(spa));
10322e4c9986SGeorge Wilson 	fragmentation = metaslab_class_fragmentation(mc);
10332e4c9986SGeorge Wilson 	if (fragmentation == ZFS_FRAG_INVALID)
10342e4c9986SGeorge Wilson 		(void) printf("\t%3s\n", "-");
10352e4c9986SGeorge Wilson 	else
10362e4c9986SGeorge Wilson 		(void) printf("\t%3llu%%\n", (u_longlong_t)fragmentation);
10372e4c9986SGeorge Wilson 	dump_histogram(mc->mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
10382e4c9986SGeorge Wilson }
10392e4c9986SGeorge Wilson 
10405cabbc6bSPrashanth Sreenivasa static void
10415cabbc6bSPrashanth Sreenivasa print_vdev_indirect(vdev_t *vd)
10425cabbc6bSPrashanth Sreenivasa {
10435cabbc6bSPrashanth Sreenivasa 	vdev_indirect_config_t *vic = &vd->vdev_indirect_config;
10445cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
10455cabbc6bSPrashanth Sreenivasa 	vdev_indirect_births_t *vib = vd->vdev_indirect_births;
10465cabbc6bSPrashanth Sreenivasa 
10475cabbc6bSPrashanth Sreenivasa 	if (vim == NULL) {
10485cabbc6bSPrashanth Sreenivasa 		ASSERT3P(vib, ==, NULL);
10495cabbc6bSPrashanth Sreenivasa 		return;
10505cabbc6bSPrashanth Sreenivasa 	}
10515cabbc6bSPrashanth Sreenivasa 
10525cabbc6bSPrashanth Sreenivasa 	ASSERT3U(vdev_indirect_mapping_object(vim), ==,
10535cabbc6bSPrashanth Sreenivasa 	    vic->vic_mapping_object);
10545cabbc6bSPrashanth Sreenivasa 	ASSERT3U(vdev_indirect_births_object(vib), ==,
10555cabbc6bSPrashanth Sreenivasa 	    vic->vic_births_object);
10565cabbc6bSPrashanth Sreenivasa 
10575cabbc6bSPrashanth Sreenivasa 	(void) printf("indirect births obj %llu:\n",
10585cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vic->vic_births_object);
10595cabbc6bSPrashanth Sreenivasa 	(void) printf("    vib_count = %llu\n",
10605cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vdev_indirect_births_count(vib));
10615cabbc6bSPrashanth Sreenivasa 	for (uint64_t i = 0; i < vdev_indirect_births_count(vib); i++) {
10625cabbc6bSPrashanth Sreenivasa 		vdev_indirect_birth_entry_phys_t *cur_vibe =
10635cabbc6bSPrashanth Sreenivasa 		    &vib->vib_entries[i];
10645cabbc6bSPrashanth Sreenivasa 		(void) printf("\toffset %llx -> txg %llu\n",
10655cabbc6bSPrashanth Sreenivasa 		    (longlong_t)cur_vibe->vibe_offset,
10665cabbc6bSPrashanth Sreenivasa 		    (longlong_t)cur_vibe->vibe_phys_birth_txg);
10675cabbc6bSPrashanth Sreenivasa 	}
10685cabbc6bSPrashanth Sreenivasa 	(void) printf("\n");
10695cabbc6bSPrashanth Sreenivasa 
10705cabbc6bSPrashanth Sreenivasa 	(void) printf("indirect mapping obj %llu:\n",
10715cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vic->vic_mapping_object);
10725cabbc6bSPrashanth Sreenivasa 	(void) printf("    vim_max_offset = 0x%llx\n",
10735cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vdev_indirect_mapping_max_offset(vim));
10745cabbc6bSPrashanth Sreenivasa 	(void) printf("    vim_bytes_mapped = 0x%llx\n",
10755cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vdev_indirect_mapping_bytes_mapped(vim));
10765cabbc6bSPrashanth Sreenivasa 	(void) printf("    vim_count = %llu\n",
10775cabbc6bSPrashanth Sreenivasa 	    (longlong_t)vdev_indirect_mapping_num_entries(vim));
10785cabbc6bSPrashanth Sreenivasa 
10795cabbc6bSPrashanth Sreenivasa 	if (dump_opt['d'] <= 5 && dump_opt['m'] <= 3)
10805cabbc6bSPrashanth Sreenivasa 		return;
10815cabbc6bSPrashanth Sreenivasa 
10825cabbc6bSPrashanth Sreenivasa 	uint32_t *counts = vdev_indirect_mapping_load_obsolete_counts(vim);
10835cabbc6bSPrashanth Sreenivasa 
10845cabbc6bSPrashanth Sreenivasa 	for (uint64_t i = 0; i < vdev_indirect_mapping_num_entries(vim); i++) {
10855cabbc6bSPrashanth Sreenivasa 		vdev_indirect_mapping_entry_phys_t *vimep =
10865cabbc6bSPrashanth Sreenivasa 		    &vim->vim_entries[i];
10875cabbc6bSPrashanth Sreenivasa 		(void) printf("\t<%llx:%llx:%llx> -> "
10885cabbc6bSPrashanth Sreenivasa 		    "<%llx:%llx:%llx> (%x obsolete)\n",
10895cabbc6bSPrashanth Sreenivasa 		    (longlong_t)vd->vdev_id,
10905cabbc6bSPrashanth Sreenivasa 		    (longlong_t)DVA_MAPPING_GET_SRC_OFFSET(vimep),
10915cabbc6bSPrashanth Sreenivasa 		    (longlong_t)DVA_GET_ASIZE(&vimep->vimep_dst),
10925cabbc6bSPrashanth Sreenivasa 		    (longlong_t)DVA_GET_VDEV(&vimep->vimep_dst),
10935cabbc6bSPrashanth Sreenivasa 		    (longlong_t)DVA_GET_OFFSET(&vimep->vimep_dst),
10945cabbc6bSPrashanth Sreenivasa 		    (longlong_t)DVA_GET_ASIZE(&vimep->vimep_dst),
10955cabbc6bSPrashanth Sreenivasa 		    counts[i]);
10965cabbc6bSPrashanth Sreenivasa 	}
10975cabbc6bSPrashanth Sreenivasa 	(void) printf("\n");
10985cabbc6bSPrashanth Sreenivasa 
10995cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_sm_object = vdev_obsolete_sm_object(vd);
11005cabbc6bSPrashanth Sreenivasa 	if (obsolete_sm_object != 0) {
11015cabbc6bSPrashanth Sreenivasa 		objset_t *mos = vd->vdev_spa->spa_meta_objset;
11025cabbc6bSPrashanth Sreenivasa 		(void) printf("obsolete space map object %llu:\n",
11035cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)obsolete_sm_object);
11045cabbc6bSPrashanth Sreenivasa 		ASSERT(vd->vdev_obsolete_sm != NULL);
11055cabbc6bSPrashanth Sreenivasa 		ASSERT3U(space_map_object(vd->vdev_obsolete_sm), ==,
11065cabbc6bSPrashanth Sreenivasa 		    obsolete_sm_object);
11075cabbc6bSPrashanth Sreenivasa 		dump_spacemap(mos, vd->vdev_obsolete_sm);
11085cabbc6bSPrashanth Sreenivasa 		(void) printf("\n");
11095cabbc6bSPrashanth Sreenivasa 	}
11105cabbc6bSPrashanth Sreenivasa }
11115cabbc6bSPrashanth Sreenivasa 
1112fa9e4066Sahrens static void
1113fa9e4066Sahrens dump_metaslabs(spa_t *spa)
1114fa9e4066Sahrens {
111587219db7SVictor Latushkin 	vdev_t *vd, *rvd = spa->spa_root_vdev;
111687219db7SVictor Latushkin 	uint64_t m, c = 0, children = rvd->vdev_children;
1117fa9e4066Sahrens 
1118fa9e4066Sahrens 	(void) printf("\nMetaslabs:\n");
1119fa9e4066Sahrens 
112087219db7SVictor Latushkin 	if (!dump_opt['d'] && zopt_objects > 0) {
112187219db7SVictor Latushkin 		c = zopt_object[0];
112287219db7SVictor Latushkin 
112387219db7SVictor Latushkin 		if (c >= children)
112487219db7SVictor Latushkin 			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
1125fa9e4066Sahrens 
112687219db7SVictor Latushkin 		if (zopt_objects > 1) {
112787219db7SVictor Latushkin 			vd = rvd->vdev_child[c];
112887219db7SVictor Latushkin 			print_vdev_metaslab_header(vd);
112987219db7SVictor Latushkin 
113087219db7SVictor Latushkin 			for (m = 1; m < zopt_objects; m++) {
113187219db7SVictor Latushkin 				if (zopt_object[m] < vd->vdev_ms_count)
113287219db7SVictor Latushkin 					dump_metaslab(
113387219db7SVictor Latushkin 					    vd->vdev_ms[zopt_object[m]]);
113487219db7SVictor Latushkin 				else
113587219db7SVictor Latushkin 					(void) fprintf(stderr, "bad metaslab "
113687219db7SVictor Latushkin 					    "number %llu\n",
113787219db7SVictor Latushkin 					    (u_longlong_t)zopt_object[m]);
113887219db7SVictor Latushkin 			}
113987219db7SVictor Latushkin 			(void) printf("\n");
114087219db7SVictor Latushkin 			return;
114187219db7SVictor Latushkin 		}
114287219db7SVictor Latushkin 		children = c + 1;
114387219db7SVictor Latushkin 	}
114487219db7SVictor Latushkin 	for (; c < children; c++) {
114587219db7SVictor Latushkin 		vd = rvd->vdev_child[c];
114687219db7SVictor Latushkin 		print_vdev_metaslab_header(vd);
1147fa9e4066Sahrens 
11485cabbc6bSPrashanth Sreenivasa 		print_vdev_indirect(vd);
11495cabbc6bSPrashanth Sreenivasa 
1150fa9e4066Sahrens 		for (m = 0; m < vd->vdev_ms_count; m++)
1151fa9e4066Sahrens 			dump_metaslab(vd->vdev_ms[m]);
1152fa9e4066Sahrens 		(void) printf("\n");
1153fa9e4066Sahrens 	}
1154fa9e4066Sahrens }
1155fa9e4066Sahrens 
1156*814dcd43SSerapheim Dimitropoulos static void
1157*814dcd43SSerapheim Dimitropoulos dump_log_spacemaps(spa_t *spa)
1158*814dcd43SSerapheim Dimitropoulos {
1159*814dcd43SSerapheim Dimitropoulos 	if (!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))
1160*814dcd43SSerapheim Dimitropoulos 		return;
1161*814dcd43SSerapheim Dimitropoulos 
1162*814dcd43SSerapheim Dimitropoulos 	(void) printf("\nLog Space Maps in Pool:\n");
1163*814dcd43SSerapheim Dimitropoulos 	for (spa_log_sm_t *sls = avl_first(&spa->spa_sm_logs_by_txg);
1164*814dcd43SSerapheim Dimitropoulos 	    sls; sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls)) {
1165*814dcd43SSerapheim Dimitropoulos 		space_map_t *sm = NULL;
1166*814dcd43SSerapheim Dimitropoulos 		VERIFY0(space_map_open(&sm, spa_meta_objset(spa),
1167*814dcd43SSerapheim Dimitropoulos 		    sls->sls_sm_obj, 0, UINT64_MAX, SPA_MINBLOCKSHIFT));
1168*814dcd43SSerapheim Dimitropoulos 
1169*814dcd43SSerapheim Dimitropoulos 		(void) printf("Log Spacemap object %llu txg %llu\n",
1170*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)sls->sls_sm_obj, (u_longlong_t)sls->sls_txg);
1171*814dcd43SSerapheim Dimitropoulos 		dump_spacemap(spa->spa_meta_objset, sm);
1172*814dcd43SSerapheim Dimitropoulos 		space_map_close(sm);
1173*814dcd43SSerapheim Dimitropoulos 	}
1174*814dcd43SSerapheim Dimitropoulos 	(void) printf("\n");
1175*814dcd43SSerapheim Dimitropoulos }
1176*814dcd43SSerapheim Dimitropoulos 
1177b24ab676SJeff Bonwick static void
1178b24ab676SJeff Bonwick dump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
1179b24ab676SJeff Bonwick {
1180b24ab676SJeff Bonwick 	const ddt_phys_t *ddp = dde->dde_phys;
1181b24ab676SJeff Bonwick 	const ddt_key_t *ddk = &dde->dde_key;
11823f7978d0SAlan Somers 	const char *types[4] = { "ditto", "single", "double", "triple" };
1183b24ab676SJeff Bonwick 	char blkbuf[BP_SPRINTF_LEN];
1184b24ab676SJeff Bonwick 	blkptr_t blk;
1185b24ab676SJeff Bonwick 
1186b24ab676SJeff Bonwick 	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
1187b24ab676SJeff Bonwick 		if (ddp->ddp_phys_birth == 0)
1188b24ab676SJeff Bonwick 			continue;
1189bbfd46c4SJeff Bonwick 		ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
119043466aaeSMax Grossman 		snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk);
1191b24ab676SJeff Bonwick 		(void) printf("index %llx refcnt %llu %s %s\n",
1192b24ab676SJeff Bonwick 		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
1193b24ab676SJeff Bonwick 		    types[p], blkbuf);
1194b24ab676SJeff Bonwick 	}
1195b24ab676SJeff Bonwick }
1196b24ab676SJeff Bonwick 
1197b24ab676SJeff Bonwick static void
1198b24ab676SJeff Bonwick dump_dedup_ratio(const ddt_stat_t *dds)
1199b24ab676SJeff Bonwick {
1200b24ab676SJeff Bonwick 	double rL, rP, rD, D, dedup, compress, copies;
1201b24ab676SJeff Bonwick 
1202b24ab676SJeff Bonwick 	if (dds->dds_blocks == 0)
1203b24ab676SJeff Bonwick 		return;
1204b24ab676SJeff Bonwick 
1205b24ab676SJeff Bonwick 	rL = (double)dds->dds_ref_lsize;
1206b24ab676SJeff Bonwick 	rP = (double)dds->dds_ref_psize;
1207b24ab676SJeff Bonwick 	rD = (double)dds->dds_ref_dsize;
1208b24ab676SJeff Bonwick 	D = (double)dds->dds_dsize;
1209b24ab676SJeff Bonwick 
1210b24ab676SJeff Bonwick 	dedup = rD / D;
1211b24ab676SJeff Bonwick 	compress = rL / rP;
1212b24ab676SJeff Bonwick 	copies = rD / rP;
1213b24ab676SJeff Bonwick 
1214b24ab676SJeff Bonwick 	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
1215b24ab676SJeff Bonwick 	    "dedup * compress / copies = %.2f\n\n",
1216b24ab676SJeff Bonwick 	    dedup, compress, copies, dedup * compress / copies);
1217b24ab676SJeff Bonwick }
1218b24ab676SJeff Bonwick 
1219b24ab676SJeff Bonwick static void
1220b24ab676SJeff Bonwick dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
1221b24ab676SJeff Bonwick {
1222b24ab676SJeff Bonwick 	char name[DDT_NAMELEN];
1223b24ab676SJeff Bonwick 	ddt_entry_t dde;
1224b24ab676SJeff Bonwick 	uint64_t walk = 0;
1225b24ab676SJeff Bonwick 	dmu_object_info_t doi;
1226b24ab676SJeff Bonwick 	uint64_t count, dspace, mspace;
1227b24ab676SJeff Bonwick 	int error;
1228b24ab676SJeff Bonwick 
1229b24ab676SJeff Bonwick 	error = ddt_object_info(ddt, type, class, &doi);
1230b24ab676SJeff Bonwick 
1231b24ab676SJeff Bonwick 	if (error == ENOENT)
1232b24ab676SJeff Bonwick 		return;
1233b24ab676SJeff Bonwick 	ASSERT(error == 0);
1234b24ab676SJeff Bonwick 
12357448a079SGeorge Wilson 	if ((count = ddt_object_count(ddt, type, class)) == 0)
12367448a079SGeorge Wilson 		return;
12377448a079SGeorge Wilson 
1238b24ab676SJeff Bonwick 	dspace = doi.doi_physical_blocks_512 << 9;
1239b24ab676SJeff Bonwick 	mspace = doi.doi_fill_count * doi.doi_data_block_size;
1240b24ab676SJeff Bonwick 
1241b24ab676SJeff Bonwick 	ddt_object_name(ddt, type, class, name);
1242b24ab676SJeff Bonwick 
1243b24ab676SJeff Bonwick 	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
1244b24ab676SJeff Bonwick 	    name,
1245b24ab676SJeff Bonwick 	    (u_longlong_t)count,
1246b24ab676SJeff Bonwick 	    (u_longlong_t)(dspace / count),
1247b24ab676SJeff Bonwick 	    (u_longlong_t)(mspace / count));
1248b24ab676SJeff Bonwick 
1249b24ab676SJeff Bonwick 	if (dump_opt['D'] < 3)
1250b24ab676SJeff Bonwick 		return;
1251b24ab676SJeff Bonwick 
12529eb19f4dSGeorge Wilson 	zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]);
1253b24ab676SJeff Bonwick 
1254b24ab676SJeff Bonwick 	if (dump_opt['D'] < 4)
1255b24ab676SJeff Bonwick 		return;
1256b24ab676SJeff Bonwick 
1257b24ab676SJeff Bonwick 	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
1258b24ab676SJeff Bonwick 		return;
1259b24ab676SJeff Bonwick 
1260b24ab676SJeff Bonwick 	(void) printf("%s contents:\n\n", name);
1261b24ab676SJeff Bonwick 
1262bbfd46c4SJeff Bonwick 	while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0)
1263b24ab676SJeff Bonwick 		dump_dde(ddt, &dde, walk);
1264b24ab676SJeff Bonwick 
126517f11284SSerapheim Dimitropoulos 	ASSERT3U(error, ==, ENOENT);
1266b24ab676SJeff Bonwick 
1267b24ab676SJeff Bonwick 	(void) printf("\n");
1268b24ab676SJeff Bonwick }
1269b24ab676SJeff Bonwick 
1270b24ab676SJeff Bonwick static void
1271b24ab676SJeff Bonwick dump_all_ddts(spa_t *spa)
1272b24ab676SJeff Bonwick {
12733f7978d0SAlan Somers 	ddt_histogram_t ddh_total;
12743f7978d0SAlan Somers 	ddt_stat_t dds_total;
12753f7978d0SAlan Somers 
12763f7978d0SAlan Somers 	bzero(&ddh_total, sizeof (ddh_total));
12773f7978d0SAlan Somers 	bzero(&dds_total, sizeof (dds_total));
1278b24ab676SJeff Bonwick 
1279b24ab676SJeff Bonwick 	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
1280b24ab676SJeff Bonwick 		ddt_t *ddt = spa->spa_ddt[c];
1281b24ab676SJeff Bonwick 		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
1282b24ab676SJeff Bonwick 			for (enum ddt_class class = 0; class < DDT_CLASSES;
1283b24ab676SJeff Bonwick 			    class++) {
1284b24ab676SJeff Bonwick 				dump_ddt(ddt, type, class);
1285b24ab676SJeff Bonwick 			}
1286b24ab676SJeff Bonwick 		}
1287b24ab676SJeff Bonwick 	}
1288b24ab676SJeff Bonwick 
12899eb19f4dSGeorge Wilson 	ddt_get_dedup_stats(spa, &dds_total);
1290b24ab676SJeff Bonwick 
1291b24ab676SJeff Bonwick 	if (dds_total.dds_blocks == 0) {
1292b24ab676SJeff Bonwick 		(void) printf("All DDTs are empty\n");
1293b24ab676SJeff Bonwick 		return;
1294b24ab676SJeff Bonwick 	}
1295b24ab676SJeff Bonwick 
1296b24ab676SJeff Bonwick 	(void) printf("\n");
1297b24ab676SJeff Bonwick 
1298b24ab676SJeff Bonwick 	if (dump_opt['D'] > 1) {
1299b24ab676SJeff Bonwick 		(void) printf("DDT histogram (aggregated over all DDTs):\n");
13009eb19f4dSGeorge Wilson 		ddt_get_dedup_histogram(spa, &ddh_total);
13019eb19f4dSGeorge Wilson 		zpool_dump_ddt(&dds_total, &ddh_total);
1302b24ab676SJeff Bonwick 	}
1303b24ab676SJeff Bonwick 
1304b24ab676SJeff Bonwick 	dump_dedup_ratio(&dds_total);
1305b24ab676SJeff Bonwick }
1306b24ab676SJeff Bonwick 
13078ad4d6ddSJeff Bonwick static void
13080713e232SGeorge Wilson dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
13098ad4d6ddSJeff Bonwick {
13100713e232SGeorge Wilson 	char *prefix = arg;
13118ad4d6ddSJeff Bonwick 
13128ad4d6ddSJeff Bonwick 	(void) printf("%s [%llu,%llu) length %llu\n",
13138ad4d6ddSJeff Bonwick 	    prefix,
13148ad4d6ddSJeff Bonwick 	    (u_longlong_t)start,
13158ad4d6ddSJeff Bonwick 	    (u_longlong_t)(start + size),
13168ad4d6ddSJeff Bonwick 	    (u_longlong_t)(size));
13178ad4d6ddSJeff Bonwick }
13188ad4d6ddSJeff Bonwick 
1319fa9e4066Sahrens static void
1320fa9e4066Sahrens dump_dtl(vdev_t *vd, int indent)
1321fa9e4066Sahrens {
13228ad4d6ddSJeff Bonwick 	spa_t *spa = vd->vdev_spa;
13238ad4d6ddSJeff Bonwick 	boolean_t required;
13243f7978d0SAlan Somers 	const char *name[DTL_TYPES] = { "missing", "partial", "scrub",
13253f7978d0SAlan Somers 		"outage" };
13268ad4d6ddSJeff Bonwick 	char prefix[256];
13278ad4d6ddSJeff Bonwick 
13288f18d1faSGeorge Wilson 	spa_vdev_state_enter(spa, SCL_NONE);
13298ad4d6ddSJeff Bonwick 	required = vdev_dtl_required(vd);
13308ad4d6ddSJeff Bonwick 	(void) spa_vdev_state_exit(spa, NULL, 0);
1331fa9e4066Sahrens 
1332fa9e4066Sahrens 	if (indent == 0)
1333fa9e4066Sahrens 		(void) printf("\nDirty time logs:\n\n");
1334fa9e4066Sahrens 
13358ad4d6ddSJeff Bonwick 	(void) printf("\t%*s%s [%s]\n", indent, "",
1336e14bb325SJeff Bonwick 	    vd->vdev_path ? vd->vdev_path :
13378ad4d6ddSJeff Bonwick 	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
13388ad4d6ddSJeff Bonwick 	    required ? "DTL-required" : "DTL-expendable");
1339fa9e4066Sahrens 
13408ad4d6ddSJeff Bonwick 	for (int t = 0; t < DTL_TYPES; t++) {
13410713e232SGeorge Wilson 		range_tree_t *rt = vd->vdev_dtl[t];
13420713e232SGeorge Wilson 		if (range_tree_space(rt) == 0)
13438ad4d6ddSJeff Bonwick 			continue;
13448ad4d6ddSJeff Bonwick 		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
13458ad4d6ddSJeff Bonwick 		    indent + 2, "", name[t]);
13460713e232SGeorge Wilson 		range_tree_walk(rt, dump_dtl_seg, prefix);
13478ad4d6ddSJeff Bonwick 		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
13480713e232SGeorge Wilson 			dump_spacemap(spa->spa_meta_objset, vd->vdev_dtl_sm);
1349fa9e4066Sahrens 	}
1350fa9e4066Sahrens 
13513f7978d0SAlan Somers 	for (unsigned c = 0; c < vd->vdev_children; c++)
1352fa9e4066Sahrens 		dump_dtl(vd->vdev_child[c], indent + 4);
1353fa9e4066Sahrens }
1354fa9e4066Sahrens 
13558f18d1faSGeorge Wilson static void
13568f18d1faSGeorge Wilson dump_history(spa_t *spa)
13578f18d1faSGeorge Wilson {
13588f18d1faSGeorge Wilson 	nvlist_t **events = NULL;
1359e4161df6SVictor Latushkin 	uint64_t resid, len, off = 0;
13608f18d1faSGeorge Wilson 	uint_t num = 0;
13618f18d1faSGeorge Wilson 	int error;
13628f18d1faSGeorge Wilson 	time_t tsec;
13638f18d1faSGeorge Wilson 	struct tm t;
13648f18d1faSGeorge Wilson 	char tbuf[30];
13658f18d1faSGeorge Wilson 	char internalstr[MAXPATHLEN];
13668f18d1faSGeorge Wilson 
13673f84190cSMatthew Ahrens 	char *buf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
13688f18d1faSGeorge Wilson 	do {
13693f84190cSMatthew Ahrens 		len = SPA_MAXBLOCKSIZE;
1370e4161df6SVictor Latushkin 
13718f18d1faSGeorge Wilson 		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
13728f18d1faSGeorge Wilson 			(void) fprintf(stderr, "Unable to read history: "
13738f18d1faSGeorge Wilson 			    "error %d\n", error);
13743f84190cSMatthew Ahrens 			umem_free(buf, SPA_MAXBLOCKSIZE);
13758f18d1faSGeorge Wilson 			return;
13768f18d1faSGeorge Wilson 		}
13778f18d1faSGeorge Wilson 
13788f18d1faSGeorge Wilson 		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
13798f18d1faSGeorge Wilson 			break;
13808f18d1faSGeorge Wilson 
13818f18d1faSGeorge Wilson 		off -= resid;
13828f18d1faSGeorge Wilson 	} while (len != 0);
13833f84190cSMatthew Ahrens 	umem_free(buf, SPA_MAXBLOCKSIZE);
13848f18d1faSGeorge Wilson 
13858f18d1faSGeorge Wilson 	(void) printf("\nHistory:\n");
13863f7978d0SAlan Somers 	for (unsigned i = 0; i < num; i++) {
13878f18d1faSGeorge Wilson 		uint64_t time, txg, ievent;
13888f18d1faSGeorge Wilson 		char *cmd, *intstr;
13894445fffbSMatthew Ahrens 		boolean_t printed = B_FALSE;
13908f18d1faSGeorge Wilson 
13918f18d1faSGeorge Wilson 		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
13928f18d1faSGeorge Wilson 		    &time) != 0)
13934445fffbSMatthew Ahrens 			goto next;
13948f18d1faSGeorge Wilson 		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
13958f18d1faSGeorge Wilson 		    &cmd) != 0) {
13968f18d1faSGeorge Wilson 			if (nvlist_lookup_uint64(events[i],
13978f18d1faSGeorge Wilson 			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
13984445fffbSMatthew Ahrens 				goto next;
13998f18d1faSGeorge Wilson 			verify(nvlist_lookup_uint64(events[i],
14008f18d1faSGeorge Wilson 			    ZPOOL_HIST_TXG, &txg) == 0);
14018f18d1faSGeorge Wilson 			verify(nvlist_lookup_string(events[i],
14028f18d1faSGeorge Wilson 			    ZPOOL_HIST_INT_STR, &intstr) == 0);
14034445fffbSMatthew Ahrens 			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS)
14044445fffbSMatthew Ahrens 				goto next;
14058f18d1faSGeorge Wilson 
14068f18d1faSGeorge Wilson 			(void) snprintf(internalstr,
14078f18d1faSGeorge Wilson 			    sizeof (internalstr),
14083f7978d0SAlan Somers 			    "[internal %s txg:%ju] %s",
14093f7978d0SAlan Somers 			    zfs_history_event_names[ievent], (uintmax_t)txg,
14108f18d1faSGeorge Wilson 			    intstr);
14118f18d1faSGeorge Wilson 			cmd = internalstr;
14128f18d1faSGeorge Wilson 		}
14138f18d1faSGeorge Wilson 		tsec = time;
14148f18d1faSGeorge Wilson 		(void) localtime_r(&tsec, &t);
14158f18d1faSGeorge Wilson 		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
14168f18d1faSGeorge Wilson 		(void) printf("%s %s\n", tbuf, cmd);
14174445fffbSMatthew Ahrens 		printed = B_TRUE;
14184445fffbSMatthew Ahrens 
14194445fffbSMatthew Ahrens next:
14204445fffbSMatthew Ahrens 		if (dump_opt['h'] > 1) {
14214445fffbSMatthew Ahrens 			if (!printed)
14224445fffbSMatthew Ahrens 				(void) printf("unrecognized record:\n");
14234445fffbSMatthew Ahrens 			dump_nvlist(events[i], 2);
14244445fffbSMatthew Ahrens 		}
14258f18d1faSGeorge Wilson 	}
14268f18d1faSGeorge Wilson }
14278f18d1faSGeorge Wilson 
1428fa9e4066Sahrens /*ARGSUSED*/
1429fa9e4066Sahrens static void
1430fa9e4066Sahrens dump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
1431fa9e4066Sahrens {
1432fa9e4066Sahrens }
1433fa9e4066Sahrens 
1434fa9e4066Sahrens static uint64_t
14357802d7bfSMatthew Ahrens blkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp,
14367802d7bfSMatthew Ahrens     const zbookmark_phys_t *zb)
1437fa9e4066Sahrens {
1438b24ab676SJeff Bonwick 	if (dnp == NULL) {
1439b24ab676SJeff Bonwick 		ASSERT(zb->zb_level < 0);
1440b24ab676SJeff Bonwick 		if (zb->zb_object == 0)
1441b24ab676SJeff Bonwick 			return (zb->zb_blkid);
1442b24ab676SJeff Bonwick 		return (zb->zb_blkid * BP_GET_LSIZE(bp));
1443b24ab676SJeff Bonwick 	}
1444b24ab676SJeff Bonwick 
1445b24ab676SJeff Bonwick 	ASSERT(zb->zb_level >= 0);
1446fa9e4066Sahrens 
1447b24ab676SJeff Bonwick 	return ((zb->zb_blkid <<
1448b24ab676SJeff Bonwick 	    (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
1449fa9e4066Sahrens 	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
1450fa9e4066Sahrens }
1451fa9e4066Sahrens 
145244cd46caSbillm static void
145343466aaeSMax Grossman snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
145444cd46caSbillm {
1455cde58dbcSMatthew Ahrens 	const dva_t *dva = bp->blk_dva;
1456eb633035STom Caputi 	unsigned int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
1457b24ab676SJeff Bonwick 
1458490d05b9SMatthew Ahrens 	if (dump_opt['b'] >= 6) {
145943466aaeSMax Grossman 		snprintf_blkptr(blkbuf, buflen, bp);
1460b24ab676SJeff Bonwick 		return;
1461b24ab676SJeff Bonwick 	}
146244cd46caSbillm 
14635d7b4d43SMatthew Ahrens 	if (BP_IS_EMBEDDED(bp)) {
14645d7b4d43SMatthew Ahrens 		(void) sprintf(blkbuf,
14655d7b4d43SMatthew Ahrens 		    "EMBEDDED et=%u %llxL/%llxP B=%llu",
14665d7b4d43SMatthew Ahrens 		    (int)BPE_GET_ETYPE(bp),
14675d7b4d43SMatthew Ahrens 		    (u_longlong_t)BPE_GET_LSIZE(bp),
14685d7b4d43SMatthew Ahrens 		    (u_longlong_t)BPE_GET_PSIZE(bp),
14695d7b4d43SMatthew Ahrens 		    (u_longlong_t)bp->blk_birth);
14705d7b4d43SMatthew Ahrens 		return;
14715d7b4d43SMatthew Ahrens 	}
147244cd46caSbillm 
14735d7b4d43SMatthew Ahrens 	blkbuf[0] = '\0';
1474eb633035STom Caputi 	for (unsigned int i = 0; i < ndvas; i++)
147543466aaeSMax Grossman 		(void) snprintf(blkbuf + strlen(blkbuf),
147643466aaeSMax Grossman 		    buflen - strlen(blkbuf), "%llu:%llx:%llx ",
147744cd46caSbillm 		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
147844cd46caSbillm 		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
147944cd46caSbillm 		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
148044cd46caSbillm 
148143466aaeSMax Grossman 	if (BP_IS_HOLE(bp)) {
148243466aaeSMax Grossman 		(void) snprintf(blkbuf + strlen(blkbuf),
148370163ac5SPrakash Surya 		    buflen - strlen(blkbuf),
148470163ac5SPrakash Surya 		    "%llxL B=%llu",
148570163ac5SPrakash Surya 		    (u_longlong_t)BP_GET_LSIZE(bp),
148643466aaeSMax Grossman 		    (u_longlong_t)bp->blk_birth);
148743466aaeSMax Grossman 	} else {
148843466aaeSMax Grossman 		(void) snprintf(blkbuf + strlen(blkbuf),
148943466aaeSMax Grossman 		    buflen - strlen(blkbuf),
149043466aaeSMax Grossman 		    "%llxL/%llxP F=%llu B=%llu/%llu",
149143466aaeSMax Grossman 		    (u_longlong_t)BP_GET_LSIZE(bp),
149243466aaeSMax Grossman 		    (u_longlong_t)BP_GET_PSIZE(bp),
14935d7b4d43SMatthew Ahrens 		    (u_longlong_t)BP_GET_FILL(bp),
149443466aaeSMax Grossman 		    (u_longlong_t)bp->blk_birth,
149543466aaeSMax Grossman 		    (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
149643466aaeSMax Grossman 	}
149744cd46caSbillm }
149844cd46caSbillm 
149988b7b0f2SMatthew Ahrens static void
15007802d7bfSMatthew Ahrens print_indirect(blkptr_t *bp, const zbookmark_phys_t *zb,
150188b7b0f2SMatthew Ahrens     const dnode_phys_t *dnp)
1502fa9e4066Sahrens {
150388b7b0f2SMatthew Ahrens 	char blkbuf[BP_SPRINTF_LEN];
1504fa9e4066Sahrens 	int l;
1505fa9e4066Sahrens 
15065d7b4d43SMatthew Ahrens 	if (!BP_IS_EMBEDDED(bp)) {
15075d7b4d43SMatthew Ahrens 		ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
15085d7b4d43SMatthew Ahrens 		ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
15095d7b4d43SMatthew Ahrens 	}
1510fa9e4066Sahrens 
1511b24ab676SJeff Bonwick 	(void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
1512fa9e4066Sahrens 
1513fa9e4066Sahrens 	ASSERT(zb->zb_level >= 0);
1514fa9e4066Sahrens 
1515fa9e4066Sahrens 	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
1516fa9e4066Sahrens 		if (l == zb->zb_level) {
151788b7b0f2SMatthew Ahrens 			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
1518fa9e4066Sahrens 		} else {
151988b7b0f2SMatthew Ahrens 			(void) printf(" ");
1520fa9e4066Sahrens 		}
1521fa9e4066Sahrens 	}
1522fa9e4066Sahrens 
152343466aaeSMax Grossman 	snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
152488b7b0f2SMatthew Ahrens 	(void) printf("%s\n", blkbuf);
152588b7b0f2SMatthew Ahrens }
152688b7b0f2SMatthew Ahrens 
152788b7b0f2SMatthew Ahrens static int
152888b7b0f2SMatthew Ahrens visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
15297802d7bfSMatthew Ahrens     blkptr_t *bp, const zbookmark_phys_t *zb)
153088b7b0f2SMatthew Ahrens {
1531e4161df6SVictor Latushkin 	int err = 0;
153288b7b0f2SMatthew Ahrens 
153388b7b0f2SMatthew Ahrens 	if (bp->blk_birth == 0)
153488b7b0f2SMatthew Ahrens 		return (0);
153588b7b0f2SMatthew Ahrens 
153688b7b0f2SMatthew Ahrens 	print_indirect(bp, zb, dnp);
153788b7b0f2SMatthew Ahrens 
153843466aaeSMax Grossman 	if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) {
15397adb730bSGeorge Wilson 		arc_flags_t flags = ARC_FLAG_WAIT;
154088b7b0f2SMatthew Ahrens 		int i;
154188b7b0f2SMatthew Ahrens 		blkptr_t *cbp;
154288b7b0f2SMatthew Ahrens 		int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
154388b7b0f2SMatthew Ahrens 		arc_buf_t *buf;
154488b7b0f2SMatthew Ahrens 		uint64_t fill = 0;
154588b7b0f2SMatthew Ahrens 
15461b912ec7SGeorge Wilson 		err = arc_read(NULL, spa, bp, arc_getbuf_func, &buf,
154788b7b0f2SMatthew Ahrens 		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
154888b7b0f2SMatthew Ahrens 		if (err)
154988b7b0f2SMatthew Ahrens 			return (err);
15503f9d6ad7SLin Ling 		ASSERT(buf->b_data);
155188b7b0f2SMatthew Ahrens 
155288b7b0f2SMatthew Ahrens 		/* recursively visit blocks below this */
155388b7b0f2SMatthew Ahrens 		cbp = buf->b_data;
155488b7b0f2SMatthew Ahrens 		for (i = 0; i < epb; i++, cbp++) {
15557802d7bfSMatthew Ahrens 			zbookmark_phys_t czb;
155688b7b0f2SMatthew Ahrens 
155788b7b0f2SMatthew Ahrens 			SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
155888b7b0f2SMatthew Ahrens 			    zb->zb_level - 1,
155988b7b0f2SMatthew Ahrens 			    zb->zb_blkid * epb + i);
156088b7b0f2SMatthew Ahrens 			err = visit_indirect(spa, dnp, cbp, &czb);
156188b7b0f2SMatthew Ahrens 			if (err)
156288b7b0f2SMatthew Ahrens 				break;
15635d7b4d43SMatthew Ahrens 			fill += BP_GET_FILL(cbp);
156488b7b0f2SMatthew Ahrens 		}
15658ad4d6ddSJeff Bonwick 		if (!err)
15665d7b4d43SMatthew Ahrens 			ASSERT3U(fill, ==, BP_GET_FILL(bp));
1567dcbf3bd6SGeorge Wilson 		arc_buf_destroy(buf, &buf);
1568fa9e4066Sahrens 	}
1569fa9e4066Sahrens 
157088b7b0f2SMatthew Ahrens 	return (err);
1571fa9e4066Sahrens }
1572fa9e4066Sahrens 
1573fa9e4066Sahrens /*ARGSUSED*/
1574fa9e4066Sahrens static void
157588b7b0f2SMatthew Ahrens dump_indirect(dnode_t *dn)
1576fa9e4066Sahrens {
157788b7b0f2SMatthew Ahrens 	dnode_phys_t *dnp = dn->dn_phys;
157888b7b0f2SMatthew Ahrens 	int j;
15797802d7bfSMatthew Ahrens 	zbookmark_phys_t czb;
1580fa9e4066Sahrens 
1581fa9e4066Sahrens 	(void) printf("Indirect blocks:\n");
1582fa9e4066Sahrens 
1583503ad85cSMatthew Ahrens 	SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset),
158488b7b0f2SMatthew Ahrens 	    dn->dn_object, dnp->dn_nlevels - 1, 0);
158588b7b0f2SMatthew Ahrens 	for (j = 0; j < dnp->dn_nblkptr; j++) {
158688b7b0f2SMatthew Ahrens 		czb.zb_blkid = j;
1587503ad85cSMatthew Ahrens 		(void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp,
158888b7b0f2SMatthew Ahrens 		    &dnp->dn_blkptr[j], &czb);
158988b7b0f2SMatthew Ahrens 	}
1590fa9e4066Sahrens 
1591fa9e4066Sahrens 	(void) printf("\n");
1592fa9e4066Sahrens }
1593fa9e4066Sahrens 
1594fa9e4066Sahrens /*ARGSUSED*/
1595fa9e4066Sahrens static void
1596fa9e4066Sahrens dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
1597fa9e4066Sahrens {
1598fa9e4066Sahrens 	dsl_dir_phys_t *dd = data;
1599fa9e4066Sahrens 	time_t crtime;
16003f9d6ad7SLin Ling 	char nice[32];
1601fa9e4066Sahrens 
16020a055120SJason King 	/* make sure nicenum has enough space */
16030a055120SJason King 	CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
16040a055120SJason King 
1605fa9e4066Sahrens 	if (dd == NULL)
1606fa9e4066Sahrens 		return;
1607fa9e4066Sahrens 
1608da6c28aaSamw 	ASSERT3U(size, >=, sizeof (dsl_dir_phys_t));
1609fa9e4066Sahrens 
1610fa9e4066Sahrens 	crtime = dd->dd_creation_time;
1611fa9e4066Sahrens 	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1612fa9e4066Sahrens 	(void) printf("\t\thead_dataset_obj = %llu\n",
1613fa9e4066Sahrens 	    (u_longlong_t)dd->dd_head_dataset_obj);
1614fa9e4066Sahrens 	(void) printf("\t\tparent_dir_obj = %llu\n",
1615fa9e4066Sahrens 	    (u_longlong_t)dd->dd_parent_obj);
16163cb34c60Sahrens 	(void) printf("\t\torigin_obj = %llu\n",
16173cb34c60Sahrens 	    (u_longlong_t)dd->dd_origin_obj);
1618fa9e4066Sahrens 	(void) printf("\t\tchild_dir_zapobj = %llu\n",
1619fa9e4066Sahrens 	    (u_longlong_t)dd->dd_child_dir_zapobj);
16200a055120SJason King 	zdb_nicenum(dd->dd_used_bytes, nice, sizeof (nice));
162174e7dc98SMatthew Ahrens 	(void) printf("\t\tused_bytes = %s\n", nice);
16220a055120SJason King 	zdb_nicenum(dd->dd_compressed_bytes, nice, sizeof (nice));
162374e7dc98SMatthew Ahrens 	(void) printf("\t\tcompressed_bytes = %s\n", nice);
16240a055120SJason King 	zdb_nicenum(dd->dd_uncompressed_bytes, nice, sizeof (nice));
162574e7dc98SMatthew Ahrens 	(void) printf("\t\tuncompressed_bytes = %s\n", nice);
16260a055120SJason King 	zdb_nicenum(dd->dd_quota, nice, sizeof (nice));
162774e7dc98SMatthew Ahrens 	(void) printf("\t\tquota = %s\n", nice);
16280a055120SJason King 	zdb_nicenum(dd->dd_reserved, nice, sizeof (nice));
162974e7dc98SMatthew Ahrens 	(void) printf("\t\treserved = %s\n", nice);
1630fa9e4066Sahrens 	(void) printf("\t\tprops_zapobj = %llu\n",
1631fa9e4066Sahrens 	    (u_longlong_t)dd->dd_props_zapobj);
1632ecd6cf80Smarks 	(void) printf("\t\tdeleg_zapobj = %llu\n",
1633ecd6cf80Smarks 	    (u_longlong_t)dd->dd_deleg_zapobj);
163474e7dc98SMatthew Ahrens 	(void) printf("\t\tflags = %llx\n",
163574e7dc98SMatthew Ahrens 	    (u_longlong_t)dd->dd_flags);
163674e7dc98SMatthew Ahrens 
163774e7dc98SMatthew Ahrens #define	DO(which) \
16380a055120SJason King 	zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice, \
16390a055120SJason King 	    sizeof (nice)); \
164074e7dc98SMatthew Ahrens 	(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
164174e7dc98SMatthew Ahrens 	DO(HEAD);
164274e7dc98SMatthew Ahrens 	DO(SNAP);
164374e7dc98SMatthew Ahrens 	DO(CHILD);
164474e7dc98SMatthew Ahrens 	DO(CHILD_RSRV);
164574e7dc98SMatthew Ahrens 	DO(REFRSRV);
164674e7dc98SMatthew Ahrens #undef DO
164717fb938fSMatthew Ahrens 	(void) printf("\t\tclones = %llu\n",
164817fb938fSMatthew Ahrens 	    (u_longlong_t)dd->dd_clones);
1649fa9e4066Sahrens }
1650fa9e4066Sahrens 
1651fa9e4066Sahrens /*ARGSUSED*/
1652fa9e4066Sahrens static void
1653fa9e4066Sahrens dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
1654fa9e4066Sahrens {
1655fa9e4066Sahrens 	dsl_dataset_phys_t *ds = data;
1656fa9e4066Sahrens 	time_t crtime;
16573f9d6ad7SLin Ling 	char used[32], compressed[32], uncompressed[32], unique[32];
1658fbabab8fSmaybee 	char blkbuf[BP_SPRINTF_LEN];
1659fa9e4066Sahrens 
16600a055120SJason King 	/* make sure nicenum has enough space */
16610a055120SJason King 	CTASSERT(sizeof (used) >= NN_NUMBUF_SZ);
16620a055120SJason King 	CTASSERT(sizeof (compressed) >= NN_NUMBUF_SZ);
16630a055120SJason King 	CTASSERT(sizeof (uncompressed) >= NN_NUMBUF_SZ);
16640a055120SJason King 	CTASSERT(sizeof (unique) >= NN_NUMBUF_SZ);
16650a055120SJason King 
1666fa9e4066Sahrens 	if (ds == NULL)
1667fa9e4066Sahrens 		return;
1668fa9e4066Sahrens 
1669fa9e4066Sahrens 	ASSERT(size == sizeof (*ds));
1670fa9e4066Sahrens 	crtime = ds->ds_creation_time;
16710a055120SJason King 	zdb_nicenum(ds->ds_referenced_bytes, used, sizeof (used));
16720a055120SJason King 	zdb_nicenum(ds->ds_compressed_bytes, compressed, sizeof (compressed));
16730a055120SJason King 	zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed,
16740a055120SJason King 	    sizeof (uncompressed));
16750a055120SJason King 	zdb_nicenum(ds->ds_unique_bytes, unique, sizeof (unique));
167643466aaeSMax Grossman 	snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
1677fa9e4066Sahrens 
1678088f3894Sahrens 	(void) printf("\t\tdir_obj = %llu\n",
1679fa9e4066Sahrens 	    (u_longlong_t)ds->ds_dir_obj);
1680fa9e4066Sahrens 	(void) printf("\t\tprev_snap_obj = %llu\n",
1681fa9e4066Sahrens 	    (u_longlong_t)ds->ds_prev_snap_obj);
1682fa9e4066Sahrens 	(void) printf("\t\tprev_snap_txg = %llu\n",
1683fa9e4066Sahrens 	    (u_longlong_t)ds->ds_prev_snap_txg);
1684fa9e4066Sahrens 	(void) printf("\t\tnext_snap_obj = %llu\n",
1685fa9e4066Sahrens 	    (u_longlong_t)ds->ds_next_snap_obj);
1686fa9e4066Sahrens 	(void) printf("\t\tsnapnames_zapobj = %llu\n",
1687fa9e4066Sahrens 	    (u_longlong_t)ds->ds_snapnames_zapobj);
1688fa9e4066Sahrens 	(void) printf("\t\tnum_children = %llu\n",
1689fa9e4066Sahrens 	    (u_longlong_t)ds->ds_num_children);
1690842727c2SChris Kirby 	(void) printf("\t\tuserrefs_obj = %llu\n",
1691842727c2SChris Kirby 	    (u_longlong_t)ds->ds_userrefs_obj);
1692fa9e4066Sahrens 	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1693fa9e4066Sahrens 	(void) printf("\t\tcreation_txg = %llu\n",
1694fa9e4066Sahrens 	    (u_longlong_t)ds->ds_creation_txg);
1695fa9e4066Sahrens 	(void) printf("\t\tdeadlist_obj = %llu\n",
1696fa9e4066Sahrens 	    (u_longlong_t)ds->ds_deadlist_obj);
1697fa9e4066Sahrens 	(void) printf("\t\tused_bytes = %s\n", used);
1698fa9e4066Sahrens 	(void) printf("\t\tcompressed_bytes = %s\n", compressed);
1699fa9e4066Sahrens 	(void) printf("\t\tuncompressed_bytes = %s\n", uncompressed);
1700fa9e4066Sahrens 	(void) printf("\t\tunique = %s\n", unique);
1701fa9e4066Sahrens 	(void) printf("\t\tfsid_guid = %llu\n",
1702fa9e4066Sahrens 	    (u_longlong_t)ds->ds_fsid_guid);
1703fa9e4066Sahrens 	(void) printf("\t\tguid = %llu\n",
1704fa9e4066Sahrens 	    (u_longlong_t)ds->ds_guid);
170599653d4eSeschrock 	(void) printf("\t\tflags = %llx\n",
170699653d4eSeschrock 	    (u_longlong_t)ds->ds_flags);
1707088f3894Sahrens 	(void) printf("\t\tnext_clones_obj = %llu\n",
1708088f3894Sahrens 	    (u_longlong_t)ds->ds_next_clones_obj);
1709bb0ade09Sahrens 	(void) printf("\t\tprops_obj = %llu\n",
1710bb0ade09Sahrens 	    (u_longlong_t)ds->ds_props_obj);
1711fa9e4066Sahrens 	(void) printf("\t\tbp = %s\n", blkbuf);
1712fa9e4066Sahrens }
1713fa9e4066Sahrens 
1714ad135b5dSChristopher Siden /* ARGSUSED */
1715ad135b5dSChristopher Siden static int
1716ad135b5dSChristopher Siden dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
1717ad135b5dSChristopher Siden {
1718ad135b5dSChristopher Siden 	char blkbuf[BP_SPRINTF_LEN];
1719ad135b5dSChristopher Siden 
1720ad135b5dSChristopher Siden 	if (bp->blk_birth != 0) {
172143466aaeSMax Grossman 		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
1722ad135b5dSChristopher Siden 		(void) printf("\t%s\n", blkbuf);
1723ad135b5dSChristopher Siden 	}
1724ad135b5dSChristopher Siden 	return (0);
1725ad135b5dSChristopher Siden }
1726ad135b5dSChristopher Siden 
1727ad135b5dSChristopher Siden static void
17283f7978d0SAlan Somers dump_bptree(objset_t *os, uint64_t obj, const char *name)
1729ad135b5dSChristopher Siden {
1730ad135b5dSChristopher Siden 	char bytes[32];
1731ad135b5dSChristopher Siden 	bptree_phys_t *bt;
1732ad135b5dSChristopher Siden 	dmu_buf_t *db;
1733ad135b5dSChristopher Siden 
17340a055120SJason King 	/* make sure nicenum has enough space */
17350a055120SJason King 	CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
17360a055120SJason King 
1737ad135b5dSChristopher Siden 	if (dump_opt['d'] < 3)
1738ad135b5dSChristopher Siden 		return;
1739ad135b5dSChristopher Siden 
1740b420f3adSRichard Lowe 	VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
1741ad135b5dSChristopher Siden 	bt = db->db_data;
17420a055120SJason King 	zdb_nicenum(bt->bt_bytes, bytes, sizeof (bytes));
1743ad135b5dSChristopher Siden 	(void) printf("\n    %s: %llu datasets, %s\n",
1744ad135b5dSChristopher Siden 	    name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
1745ad135b5dSChristopher Siden 	dmu_buf_rele(db, FTAG);
1746ad135b5dSChristopher Siden 
1747ad135b5dSChristopher Siden 	if (dump_opt['d'] < 5)
1748ad135b5dSChristopher Siden 		return;
1749ad135b5dSChristopher Siden 
1750ad135b5dSChristopher Siden 	(void) printf("\n");
1751ad135b5dSChristopher Siden 
1752ad135b5dSChristopher Siden 	(void) bptree_iterate(os, obj, B_FALSE, dump_bptree_cb, NULL, NULL);
1753ad135b5dSChristopher Siden }
1754ad135b5dSChristopher Siden 
1755cde58dbcSMatthew Ahrens /* ARGSUSED */
1756cde58dbcSMatthew Ahrens static int
1757cde58dbcSMatthew Ahrens dump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
1758cde58dbcSMatthew Ahrens {
1759cde58dbcSMatthew Ahrens 	char blkbuf[BP_SPRINTF_LEN];
1760cde58dbcSMatthew Ahrens 
1761cde58dbcSMatthew Ahrens 	ASSERT(bp->blk_birth != 0);
176243466aaeSMax Grossman 	snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
1763cde58dbcSMatthew Ahrens 	(void) printf("\t%s\n", blkbuf);
1764cde58dbcSMatthew Ahrens 	return (0);
1765cde58dbcSMatthew Ahrens }
1766cde58dbcSMatthew Ahrens 
1767fa9e4066Sahrens static void
17683f7978d0SAlan Somers dump_full_bpobj(bpobj_t *bpo, const char *name, int indent)
1769fa9e4066Sahrens {
17703f9d6ad7SLin Ling 	char bytes[32];
17713f9d6ad7SLin Ling 	char comp[32];
17723f9d6ad7SLin Ling 	char uncomp[32];
1773fa9e4066Sahrens 
17740a055120SJason King 	/* make sure nicenum has enough space */
17750a055120SJason King 	CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
17760a055120SJason King 	CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
17770a055120SJason King 	CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
17780a055120SJason King 
1779fa9e4066Sahrens 	if (dump_opt['d'] < 3)
1780fa9e4066Sahrens 		return;
1781fa9e4066Sahrens 
17820a055120SJason King 	zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes, sizeof (bytes));
1783d0475637SMatthew Ahrens 	if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
17840a055120SJason King 		zdb_nicenum(bpo->bpo_phys->bpo_comp, comp, sizeof (comp));
17850a055120SJason King 		zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp, sizeof (uncomp));
1786d0475637SMatthew Ahrens 		(void) printf("    %*s: object %llu, %llu local blkptrs, "
1787732885fcSMatthew Ahrens 		    "%llu subobjs in object %llu, %s (%s/%s comp)\n",
1788d0475637SMatthew Ahrens 		    indent * 8, name,
1789d0475637SMatthew Ahrens 		    (u_longlong_t)bpo->bpo_object,
1790d0475637SMatthew Ahrens 		    (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs,
1791cde58dbcSMatthew Ahrens 		    (u_longlong_t)bpo->bpo_phys->bpo_num_subobjs,
1792732885fcSMatthew Ahrens 		    (u_longlong_t)bpo->bpo_phys->bpo_subobjs,
179399653d4eSeschrock 		    bytes, comp, uncomp);
1794d0475637SMatthew Ahrens 
1795d0475637SMatthew Ahrens 		for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) {
1796d0475637SMatthew Ahrens 			uint64_t subobj;
1797d0475637SMatthew Ahrens 			bpobj_t subbpo;
1798d0475637SMatthew Ahrens 			int error;
1799d0475637SMatthew Ahrens 			VERIFY0(dmu_read(bpo->bpo_os,
1800d0475637SMatthew Ahrens 			    bpo->bpo_phys->bpo_subobjs,
1801d0475637SMatthew Ahrens 			    i * sizeof (subobj), sizeof (subobj), &subobj, 0));
1802d0475637SMatthew Ahrens 			error = bpobj_open(&subbpo, bpo->bpo_os, subobj);
1803d0475637SMatthew Ahrens 			if (error != 0) {
1804d0475637SMatthew Ahrens 				(void) printf("ERROR %u while trying to open "
1805d0475637SMatthew Ahrens 				    "subobj id %llu\n",
1806d0475637SMatthew Ahrens 				    error, (u_longlong_t)subobj);
1807d0475637SMatthew Ahrens 				continue;
1808d0475637SMatthew Ahrens 			}
1809732885fcSMatthew Ahrens 			dump_full_bpobj(&subbpo, "subobj", indent + 1);
181077061867SMatthew Ahrens 			bpobj_close(&subbpo);
1811d0475637SMatthew Ahrens 		}
181299653d4eSeschrock 	} else {
1813d0475637SMatthew Ahrens 		(void) printf("    %*s: object %llu, %llu blkptrs, %s\n",
1814d0475637SMatthew Ahrens 		    indent * 8, name,
1815d0475637SMatthew Ahrens 		    (u_longlong_t)bpo->bpo_object,
1816d0475637SMatthew Ahrens 		    (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs,
1817d0475637SMatthew Ahrens 		    bytes);
181899653d4eSeschrock 	}
1819fa9e4066Sahrens 
1820cde58dbcSMatthew Ahrens 	if (dump_opt['d'] < 5)
1821fa9e4066Sahrens 		return;
1822fa9e4066Sahrens 
1823fa9e4066Sahrens 
1824d0475637SMatthew Ahrens 	if (indent == 0) {
1825d0475637SMatthew Ahrens 		(void) bpobj_iterate_nofree(bpo, dump_bpobj_cb, NULL, NULL);
1826d0475637SMatthew Ahrens 		(void) printf("\n");
1827d0475637SMatthew Ahrens 	}
1828cde58dbcSMatthew Ahrens }
182944cd46caSbillm 
183017fb938fSMatthew Ahrens static void
183117fb938fSMatthew Ahrens bpobj_count_refd(bpobj_t *bpo)
183217fb938fSMatthew Ahrens {
183317fb938fSMatthew Ahrens 	mos_obj_refd(bpo->bpo_object);
183417fb938fSMatthew Ahrens 
183517fb938fSMatthew Ahrens 	if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
183617fb938fSMatthew Ahrens 		mos_obj_refd(bpo->bpo_phys->bpo_subobjs);
183717fb938fSMatthew Ahrens 		for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) {
183817fb938fSMatthew Ahrens 			uint64_t subobj;
183917fb938fSMatthew Ahrens 			bpobj_t subbpo;
184017fb938fSMatthew Ahrens 			int error;
184117fb938fSMatthew Ahrens 			VERIFY0(dmu_read(bpo->bpo_os,
184217fb938fSMatthew Ahrens 			    bpo->bpo_phys->bpo_subobjs,
184317fb938fSMatthew Ahrens 			    i * sizeof (subobj), sizeof (subobj), &subobj, 0));
184417fb938fSMatthew Ahrens 			error = bpobj_open(&subbpo, bpo->bpo_os, subobj);
184517fb938fSMatthew Ahrens 			if (error != 0) {
184617fb938fSMatthew Ahrens 				(void) printf("ERROR %u while trying to open "
184717fb938fSMatthew Ahrens 				    "subobj id %llu\n",
184817fb938fSMatthew Ahrens 				    error, (u_longlong_t)subobj);
184917fb938fSMatthew Ahrens 				continue;
185017fb938fSMatthew Ahrens 			}
185117fb938fSMatthew Ahrens 			bpobj_count_refd(&subbpo);
185217fb938fSMatthew Ahrens 			bpobj_close(&subbpo);
185317fb938fSMatthew Ahrens 		}
185417fb938fSMatthew Ahrens 	}
185517fb938fSMatthew Ahrens }
185617fb938fSMatthew Ahrens 
1857cde58dbcSMatthew Ahrens static void
1858cde58dbcSMatthew Ahrens dump_deadlist(dsl_deadlist_t *dl)
1859cde58dbcSMatthew Ahrens {
1860cde58dbcSMatthew Ahrens 	dsl_deadlist_entry_t *dle;
1861d0475637SMatthew Ahrens 	uint64_t unused;
1862cde58dbcSMatthew Ahrens 	char bytes[32];
1863cde58dbcSMatthew Ahrens 	char comp[32];
1864cde58dbcSMatthew Ahrens 	char uncomp[32];
186517fb938fSMatthew Ahrens 	uint64_t empty_bpobj =
186617fb938fSMatthew Ahrens 	    dmu_objset_spa(dl->dl_os)->spa_dsl_pool->dp_empty_bpobj;
186717fb938fSMatthew Ahrens 
186817fb938fSMatthew Ahrens 	/* force the tree to be loaded */
186917fb938fSMatthew Ahrens 	dsl_deadlist_space_range(dl, 0, UINT64_MAX, &unused, &unused, &unused);
187017fb938fSMatthew Ahrens 
187117fb938fSMatthew Ahrens 	if (dl->dl_oldfmt) {
187217fb938fSMatthew Ahrens 		if (dl->dl_bpobj.bpo_object != empty_bpobj)
187317fb938fSMatthew Ahrens 			bpobj_count_refd(&dl->dl_bpobj);
187417fb938fSMatthew Ahrens 	} else {
187517fb938fSMatthew Ahrens 		mos_obj_refd(dl->dl_object);
187617fb938fSMatthew Ahrens 		for (dle = avl_first(&dl->dl_tree); dle;
187717fb938fSMatthew Ahrens 		    dle = AVL_NEXT(&dl->dl_tree, dle)) {
187817fb938fSMatthew Ahrens 			if (dle->dle_bpobj.bpo_object != empty_bpobj)
187917fb938fSMatthew Ahrens 				bpobj_count_refd(&dle->dle_bpobj);
188017fb938fSMatthew Ahrens 		}
188117fb938fSMatthew Ahrens 	}
1882cde58dbcSMatthew Ahrens 
18830a055120SJason King 	/* make sure nicenum has enough space */
18840a055120SJason King 	CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
18850a055120SJason King 	CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
18860a055120SJason King 	CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
18870a055120SJason King 
1888cde58dbcSMatthew Ahrens 	if (dump_opt['d'] < 3)
1889cde58dbcSMatthew Ahrens 		return;
1890cde58dbcSMatthew Ahrens 
189190c76c66SMatthew Ahrens 	if (dl->dl_oldfmt) {
1892732885fcSMatthew Ahrens 		dump_full_bpobj(&dl->dl_bpobj, "old-format deadlist", 0);
189390c76c66SMatthew Ahrens 		return;
189490c76c66SMatthew Ahrens 	}
189590c76c66SMatthew Ahrens 
18960a055120SJason King 	zdb_nicenum(dl->dl_phys->dl_used, bytes, sizeof (bytes));
18970a055120SJason King 	zdb_nicenum(dl->dl_phys->dl_comp, comp, sizeof (comp));
18980a055120SJason King 	zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp, sizeof (uncomp));
1899cde58dbcSMatthew Ahrens 	(void) printf("\n    Deadlist: %s (%s/%s comp)\n",
1900cde58dbcSMatthew Ahrens 	    bytes, comp, uncomp);
1901cde58dbcSMatthew Ahrens 
1902cde58dbcSMatthew Ahrens 	if (dump_opt['d'] < 4)
1903cde58dbcSMatthew Ahrens 		return;
1904cde58dbcSMatthew Ahrens 
1905cde58dbcSMatthew Ahrens 	(void) printf("\n");
1906cde58dbcSMatthew Ahrens 
1907cde58dbcSMatthew Ahrens 	for (dle = avl_first(&dl->dl_tree); dle;
1908cde58dbcSMatthew Ahrens 	    dle = AVL_NEXT(&dl->dl_tree, dle)) {
1909d0475637SMatthew Ahrens 		if (dump_opt['d'] >= 5) {
1910d0475637SMatthew Ahrens 			char buf[128];
1911de05b588SRichard Yao 			(void) snprintf(buf, sizeof (buf),
1912de05b588SRichard Yao 			    "mintxg %llu -> obj %llu",
1913d0475637SMatthew Ahrens 			    (longlong_t)dle->dle_mintxg,
1914d0475637SMatthew Ahrens 			    (longlong_t)dle->dle_bpobj.bpo_object);
1915fa9e4066Sahrens 
1916732885fcSMatthew Ahrens 			dump_full_bpobj(&dle->dle_bpobj, buf, 0);
1917d0475637SMatthew Ahrens 		} else {
1918d0475637SMatthew Ahrens 			(void) printf("mintxg %llu -> obj %llu\n",
1919d0475637SMatthew Ahrens 			    (longlong_t)dle->dle_mintxg,
1920d0475637SMatthew Ahrens 			    (longlong_t)dle->dle_bpobj.bpo_object);
1921d0475637SMatthew Ahrens 		}
1922cde58dbcSMatthew Ahrens 	}
1923fa9e4066Sahrens }
1924fa9e4066Sahrens 
1925e0d35c44Smarks static avl_tree_t idx_tree;
1926e0d35c44Smarks static avl_tree_t domain_tree;
1927e0d35c44Smarks static boolean_t fuid_table_loaded;
1928ed61ec1dSYuri Pankov static objset_t *sa_os = NULL;
1929ed61ec1dSYuri Pankov static sa_attr_type_t *sa_attr_table = NULL;
1930ed61ec1dSYuri Pankov 
1931ed61ec1dSYuri Pankov static int
1932ed61ec1dSYuri Pankov open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
1933ed61ec1dSYuri Pankov {
1934ed61ec1dSYuri Pankov 	int err;
1935ed61ec1dSYuri Pankov 	uint64_t sa_attrs = 0;
1936ed61ec1dSYuri Pankov 	uint64_t version = 0;
1937ed61ec1dSYuri Pankov 
1938ed61ec1dSYuri Pankov 	VERIFY3P(sa_os, ==, NULL);
1939eb633035STom Caputi 	err = dmu_objset_own(path, type, B_TRUE, B_FALSE, tag, osp);
1940ed61ec1dSYuri Pankov 	if (err != 0) {
1941ed61ec1dSYuri Pankov 		(void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
1942ed61ec1dSYuri Pankov 		    strerror(err));
1943ed61ec1dSYuri Pankov 		return (err);
1944ed61ec1dSYuri Pankov 	}
1945ed61ec1dSYuri Pankov 
1946eb633035STom Caputi 	if (dmu_objset_type(*osp) == DMU_OST_ZFS && !(*osp)->os_encrypted) {
1947ed61ec1dSYuri Pankov 		(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
1948ed61ec1dSYuri Pankov 		    8, 1, &version);
1949ed61ec1dSYuri Pankov 		if (version >= ZPL_VERSION_SA) {
1950ed61ec1dSYuri Pankov 			(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
1951ed61ec1dSYuri Pankov 			    8, 1, &sa_attrs);
1952ed61ec1dSYuri Pankov 		}
1953ed61ec1dSYuri Pankov 		err = sa_setup(*osp, sa_attrs, zfs_attr_table, ZPL_END,
1954ed61ec1dSYuri Pankov 		    &sa_attr_table);
1955ed61ec1dSYuri Pankov 		if (err != 0) {
1956ed61ec1dSYuri Pankov 			(void) fprintf(stderr, "sa_setup failed: %s\n",
1957ed61ec1dSYuri Pankov 			    strerror(err));
1958eb633035STom Caputi 			dmu_objset_disown(*osp, B_FALSE, tag);
1959ed61ec1dSYuri Pankov 			*osp = NULL;
1960ed61ec1dSYuri Pankov 		}
1961ed61ec1dSYuri Pankov 	}
1962ed61ec1dSYuri Pankov 	sa_os = *osp;
1963ed61ec1dSYuri Pankov 
1964ed61ec1dSYuri Pankov 	return (0);
1965ed61ec1dSYuri Pankov }
1966ed61ec1dSYuri Pankov 
1967ed61ec1dSYuri Pankov static void
1968ed61ec1dSYuri Pankov close_objset(objset_t *os, void *tag)
1969ed61ec1dSYuri Pankov {
1970ed61ec1dSYuri Pankov 	VERIFY3P(os, ==, sa_os);
1971ed61ec1dSYuri Pankov 	if (os->os_sa != NULL)
1972ed61ec1dSYuri Pankov 		sa_tear_down(os);
1973eb633035STom Caputi 	dmu_objset_disown(os, B_FALSE, tag);
1974ed61ec1dSYuri Pankov 	sa_attr_table = NULL;
1975ed61ec1dSYuri Pankov 	sa_os = NULL;
1976ed61ec1dSYuri Pankov }
1977e0d35c44Smarks 
1978e0d35c44Smarks static void
1979e0d35c44Smarks fuid_table_destroy()
1980e0d35c44Smarks {
1981e0d35c44Smarks 	if (fuid_table_loaded) {
1982e0d35c44Smarks 		zfs_fuid_table_destroy(&idx_tree, &domain_tree);
1983e0d35c44Smarks 		fuid_table_loaded = B_FALSE;
1984e0d35c44Smarks 	}
1985e0d35c44Smarks }
1986e0d35c44Smarks 
1987e0d35c44Smarks /*
1988e0d35c44Smarks  * print uid or gid information.
1989e0d35c44Smarks  * For normal POSIX id just the id is printed in decimal format.
1990e0d35c44Smarks  * For CIFS files with FUID the fuid is printed in hex followed by
1991d0475637SMatthew Ahrens  * the domain-rid string.
1992e0d35c44Smarks  */
1993e0d35c44Smarks static void
1994e0d35c44Smarks print_idstr(uint64_t id, const char *id_type)
1995e0d35c44Smarks {
1996e0d35c44Smarks 	if (FUID_INDEX(id)) {
1997e0d35c44Smarks 		char *domain;
1998e0d35c44Smarks 
1999e0d35c44Smarks 		domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id));
2000e0d35c44Smarks 		(void) printf("\t%s     %llx [%s-%d]\n", id_type,
2001e0d35c44Smarks 		    (u_longlong_t)id, domain, (int)FUID_RID(id));
2002e0d35c44Smarks 	} else {
2003e0d35c44Smarks 		(void) printf("\t%s     %llu\n", id_type, (u_longlong_t)id);
2004e0d35c44Smarks 	}
2005e0d35c44Smarks 
2006e0d35c44Smarks }
2007e0d35c44Smarks 
2008e0d35c44Smarks static void
20090a586ceaSMark Shellenbaum dump_uidgid(objset_t *os, uint64_t uid, uint64_t gid)
2010e0d35c44Smarks {
2011e0d35c44Smarks 	uint32_t uid_idx, gid_idx;
2012e0d35c44Smarks 
20130a586ceaSMark Shellenbaum 	uid_idx = FUID_INDEX(uid);
20140a586ceaSMark Shellenbaum 	gid_idx = FUID_INDEX(gid);
2015e0d35c44Smarks 
2016e0d35c44Smarks 	/* Load domain table, if not already loaded */
2017e0d35c44Smarks 	if (!fuid_table_loaded && (uid_idx || gid_idx)) {
2018e0d35c44Smarks 		uint64_t fuid_obj;
2019e0d35c44Smarks 
2020e0d35c44Smarks 		/* first find the fuid object.  It lives in the master node */
2021e0d35c44Smarks 		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
2022e0d35c44Smarks 		    8, 1, &fuid_obj) == 0);
202389459e17SMark Shellenbaum 		zfs_fuid_avl_tree_create(&idx_tree, &domain_tree);
2024e0d35c44Smarks 		(void) zfs_fuid_table_load(os, fuid_obj,
2025e0d35c44Smarks 		    &idx_tree, &domain_tree);
2026e0d35c44Smarks 		fuid_table_loaded = B_TRUE;
2027e0d35c44Smarks 	}
2028e0d35c44Smarks 
20290a586ceaSMark Shellenbaum 	print_idstr(uid, "uid");
20300a586ceaSMark Shellenbaum 	print_idstr(gid, "gid");
2031e0d35c44Smarks }
2032e0d35c44Smarks 
2033fa9e4066Sahrens /*ARGSUSED*/
2034fa9e4066Sahrens static void
2035fa9e4066Sahrens dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
2036fa9e4066Sahrens {
2037fa9e4066Sahrens 	char path[MAXPATHLEN * 2];	/* allow for xattr and failure prefix */
20380a586ceaSMark Shellenbaum 	sa_handle_t *hdl;
20390a586ceaSMark Shellenbaum 	uint64_t xattr, rdev, gen;
20400a586ceaSMark Shellenbaum 	uint64_t uid, gid, mode, fsize, parent, links;
20418f2529deSMark Shellenbaum 	uint64_t pflags;
20420a586ceaSMark Shellenbaum 	uint64_t acctm[2], modtm[2], chgtm[2], crtm[2];
20430a586ceaSMark Shellenbaum 	time_t z_crtime, z_atime, z_mtime, z_ctime;
20448f2529deSMark Shellenbaum 	sa_bulk_attr_t bulk[12];
20450a586ceaSMark Shellenbaum 	int idx = 0;
204655434c77Sek 	int error;
2047fa9e4066Sahrens 
2048ed61ec1dSYuri Pankov 	VERIFY3P(os, ==, sa_os);
20490a586ceaSMark Shellenbaum 	if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
20500a586ceaSMark Shellenbaum 		(void) printf("Failed to get handle for SA znode\n");
20510a586ceaSMark Shellenbaum 		return;
20520a586ceaSMark Shellenbaum 	}
20530a586ceaSMark Shellenbaum 
20540a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_UID], NULL, &uid, 8);
20550a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GID], NULL, &gid, 8);
20560a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_LINKS], NULL,
20570a586ceaSMark Shellenbaum 	    &links, 8);
20580a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GEN], NULL, &gen, 8);
20590a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MODE], NULL,
20600a586ceaSMark Shellenbaum 	    &mode, 8);
20610a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_PARENT],
20620a586ceaSMark Shellenbaum 	    NULL, &parent, 8);
20630a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_SIZE], NULL,
20640a586ceaSMark Shellenbaum 	    &fsize, 8);
20650a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_ATIME], NULL,
20660a586ceaSMark Shellenbaum 	    acctm, 16);
20670a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MTIME], NULL,
20680a586ceaSMark Shellenbaum 	    modtm, 16);
20690a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CRTIME], NULL,
20700a586ceaSMark Shellenbaum 	    crtm, 16);
20710a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CTIME], NULL,
20720a586ceaSMark Shellenbaum 	    chgtm, 16);
20738f2529deSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_FLAGS], NULL,
20748f2529deSMark Shellenbaum 	    &pflags, 8);
20750a586ceaSMark Shellenbaum 
20760a586ceaSMark Shellenbaum 	if (sa_bulk_lookup(hdl, bulk, idx)) {
20770a586ceaSMark Shellenbaum 		(void) sa_handle_destroy(hdl);
20780a586ceaSMark Shellenbaum 		return;
20790a586ceaSMark Shellenbaum 	}
2080fa9e4066Sahrens 
20810a586ceaSMark Shellenbaum 	z_crtime = (time_t)crtm[0];
20820a586ceaSMark Shellenbaum 	z_atime = (time_t)acctm[0];
20830a586ceaSMark Shellenbaum 	z_mtime = (time_t)modtm[0];
20840a586ceaSMark Shellenbaum 	z_ctime = (time_t)chgtm[0];
2085fa9e4066Sahrens 
2086e548d2faSAlan Somers 	if (dump_opt['d'] > 4) {
2087e548d2faSAlan Somers 		error = zfs_obj_to_path(os, object, path, sizeof (path));
208820b5dafbSPaul Dagnelie 		if (error == ESTALE) {
208920b5dafbSPaul Dagnelie 			(void) snprintf(path, sizeof (path), "on delete queue");
209020b5dafbSPaul Dagnelie 		} else if (error != 0) {
209120b5dafbSPaul Dagnelie 			leaked_objects++;
2092e548d2faSAlan Somers 			(void) snprintf(path, sizeof (path),
209320b5dafbSPaul Dagnelie 			    "path not found, possibly leaked");
2094e548d2faSAlan Somers 		}
2095e548d2faSAlan Somers 		(void) printf("\tpath	%s\n", path);
2096e548d2faSAlan Somers 	}
20970a586ceaSMark Shellenbaum 	dump_uidgid(os, uid, gid);
2098fa9e4066Sahrens 	(void) printf("\tatime	%s", ctime(&z_atime));
2099fa9e4066Sahrens 	(void) printf("\tmtime	%s", ctime(&z_mtime));
2100fa9e4066Sahrens 	(void) printf("\tctime	%s", ctime(&z_ctime));
2101fa9e4066Sahrens 	(void) printf("\tcrtime	%s", ctime(&z_crtime));
21020a586ceaSMark Shellenbaum 	(void) printf("\tgen	%llu\n", (u_longlong_t)gen);
21030a586ceaSMark Shellenbaum 	(void) printf("\tmode	%llo\n", (u_longlong_t)mode);
21040a586ceaSMark Shellenbaum 	(void) printf("\tsize	%llu\n", (u_longlong_t)fsize);
21050a586ceaSMark Shellenbaum 	(void) printf("\tparent	%llu\n", (u_longlong_t)parent);
21060a586ceaSMark Shellenbaum 	(void) printf("\tlinks	%llu\n", (u_longlong_t)links);
21078f2529deSMark Shellenbaum 	(void) printf("\tpflags	%llx\n", (u_longlong_t)pflags);
2108f67950b2SNasf-Fan 	if (dmu_objset_projectquota_enabled(os) && (pflags & ZFS_PROJID)) {
2109f67950b2SNasf-Fan 		uint64_t projid;
2110f67950b2SNasf-Fan 
2111f67950b2SNasf-Fan 		if (sa_lookup(hdl, sa_attr_table[ZPL_PROJID], &projid,
2112f67950b2SNasf-Fan 		    sizeof (uint64_t)) == 0)
2113f67950b2SNasf-Fan 			(void) printf("\tprojid	%llu\n", (u_longlong_t)projid);
2114f67950b2SNasf-Fan 	}
21150a586ceaSMark Shellenbaum 	if (sa_lookup(hdl, sa_attr_table[ZPL_XATTR], &xattr,
21160a586ceaSMark Shellenbaum 	    sizeof (uint64_t)) == 0)
21170a586ceaSMark Shellenbaum 		(void) printf("\txattr	%llu\n", (u_longlong_t)xattr);
21180a586ceaSMark Shellenbaum 	if (sa_lookup(hdl, sa_attr_table[ZPL_RDEV], &rdev,
21190a586ceaSMark Shellenbaum 	    sizeof (uint64_t)) == 0)
21200a586ceaSMark Shellenbaum 		(void) printf("\trdev	0x%016llx\n", (u_longlong_t)rdev);
21210a586ceaSMark Shellenbaum 	sa_handle_destroy(hdl);
2122fa9e4066Sahrens }
2123fa9e4066Sahrens 
2124fa9e4066Sahrens /*ARGSUSED*/
2125fa9e4066Sahrens static void
2126fa9e4066Sahrens dump_acl(objset_t *os, uint64_t object, void *data, size_t size)
2127fa9e4066Sahrens {
2128fa9e4066Sahrens }
2129fa9e4066Sahrens 
2130fa9e4066Sahrens /*ARGSUSED*/
2131fa9e4066Sahrens static void
2132fa9e4066Sahrens dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
2133fa9e4066Sahrens {
2134fa9e4066Sahrens }
2135fa9e4066Sahrens 
2136eb633035STom Caputi 
21376de8f417SVictor Latushkin static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
2138fa9e4066Sahrens 	dump_none,		/* unallocated			*/
2139fa9e4066Sahrens 	dump_zap,		/* object directory		*/
2140fa9e4066Sahrens 	dump_uint64,		/* object array			*/
2141fa9e4066Sahrens 	dump_none,		/* packed nvlist		*/
2142fa9e4066Sahrens 	dump_packed_nvlist,	/* packed nvlist size		*/
2143732885fcSMatthew Ahrens 	dump_none,		/* bpobj			*/
2144732885fcSMatthew Ahrens 	dump_bpobj,		/* bpobj header			*/
2145fa9e4066Sahrens 	dump_none,		/* SPA space map header		*/
2146fa9e4066Sahrens 	dump_none,		/* SPA space map		*/
2147fa9e4066Sahrens 	dump_none,		/* ZIL intent log		*/
2148fa9e4066Sahrens 	dump_dnode,		/* DMU dnode			*/
2149fa9e4066Sahrens 	dump_dmu_objset,	/* DMU objset			*/
2150ea8dc4b6Seschrock 	dump_dsl_dir,		/* DSL directory		*/
2151fa9e4066Sahrens 	dump_zap,		/* DSL directory child map	*/
2152fa9e4066Sahrens 	dump_zap,		/* DSL dataset snap map		*/
2153fa9e4066Sahrens 	dump_zap,		/* DSL props			*/
2154fa9e4066Sahrens 	dump_dsl_dataset,	/* DSL dataset			*/
2155fa9e4066Sahrens 	dump_znode,		/* ZFS znode			*/
2156da6c28aaSamw 	dump_acl,		/* ZFS V0 ACL			*/
2157fa9e4066Sahrens 	dump_uint8,		/* ZFS plain file		*/
2158e7437265Sahrens 	dump_zpldir,		/* ZFS directory		*/
2159fa9e4066Sahrens 	dump_zap,		/* ZFS master node		*/
2160fa9e4066Sahrens 	dump_zap,		/* ZFS delete queue		*/
2161fa9e4066Sahrens 	dump_uint8,		/* zvol object			*/
2162fa9e4066Sahrens 	dump_zap,		/* zvol prop			*/
2163fa9e4066Sahrens 	dump_uint8,		/* other uint8[]		*/
2164fa9e4066Sahrens 	dump_uint64,		/* other uint64[]		*/
2165fa9e4066Sahrens 	dump_zap,		/* other ZAP			*/
2166ea8dc4b6Seschrock 	dump_zap,		/* persistent error log		*/
216706eeb2adSek 	dump_uint8,		/* SPA history			*/
21684445fffbSMatthew Ahrens 	dump_history_offsets,	/* SPA history offsets		*/
2169b1b8ab34Slling 	dump_zap,		/* Pool properties		*/
2170ecd6cf80Smarks 	dump_zap,		/* DSL permissions		*/
2171da6c28aaSamw 	dump_acl,		/* ZFS ACL			*/
2172da6c28aaSamw 	dump_uint8,		/* ZFS SYSACL			*/
2173da6c28aaSamw 	dump_none,		/* FUID nvlist			*/
2174da6c28aaSamw 	dump_packed_nvlist,	/* FUID nvlist size		*/
2175088f3894Sahrens 	dump_zap,		/* DSL dataset next clones	*/
2176088f3894Sahrens 	dump_zap,		/* DSL scrub queue		*/
2177f67950b2SNasf-Fan 	dump_zap,		/* ZFS user/group/project used	*/
2178f67950b2SNasf-Fan 	dump_zap,		/* ZFS user/group/project quota	*/
2179842727c2SChris Kirby 	dump_zap,		/* snapshot refcount tags	*/
2180486ae710SMatthew Ahrens 	dump_ddt_zap,		/* DDT ZAP object		*/
2181b24ab676SJeff Bonwick 	dump_zap,		/* DDT statistics		*/
21820a586ceaSMark Shellenbaum 	dump_znode,		/* SA object			*/
21830a586ceaSMark Shellenbaum 	dump_zap,		/* SA Master Node		*/
21840a586ceaSMark Shellenbaum 	dump_sa_attrs,		/* SA attribute registration	*/
21850a586ceaSMark Shellenbaum 	dump_sa_layouts,	/* SA attribute layouts		*/
21863f9d6ad7SLin Ling 	dump_zap,		/* DSL scrub translations	*/
21873f9d6ad7SLin Ling 	dump_none,		/* fake dedup BP		*/
2188cde58dbcSMatthew Ahrens 	dump_zap,		/* deadlist			*/
2189cde58dbcSMatthew Ahrens 	dump_none,		/* deadlist hdr			*/
2190cde58dbcSMatthew Ahrens 	dump_zap,		/* dsl clones			*/
2191732885fcSMatthew Ahrens 	dump_bpobj_subobjs,	/* bpobj subobjs		*/
21920a586ceaSMark Shellenbaum 	dump_unknown,		/* Unknown type, must be last	*/
2193fa9e4066Sahrens };
2194fa9e4066Sahrens 
2195fa9e4066Sahrens static void
219654811da5SToomas Soome dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
219754811da5SToomas Soome     uint64_t *dnode_slots_used)
2198fa9e4066Sahrens {
2199fa9e4066Sahrens 	dmu_buf_t *db = NULL;
2200fa9e4066Sahrens 	dmu_object_info_t doi;
2201fa9e4066Sahrens 	dnode_t *dn;
2202eb633035STom Caputi 	boolean_t dnode_held = B_FALSE;
2203fa9e4066Sahrens 	void *bonus = NULL;
2204fa9e4066Sahrens 	size_t bsize = 0;
220554811da5SToomas Soome 	char iblk[32], dblk[32], lsize[32], asize[32], fill[32], dnsize[32];
22063f9d6ad7SLin Ling 	char bonus_size[32];
2207fa9e4066Sahrens 	char aux[50];
2208fa9e4066Sahrens 	int error;
2209fa9e4066Sahrens 
22100a055120SJason King 	/* make sure nicenum has enough space */
22110a055120SJason King 	CTASSERT(sizeof (iblk) >= NN_NUMBUF_SZ);
22120a055120SJason King 	CTASSERT(sizeof (dblk) >= NN_NUMBUF_SZ);
22130a055120SJason King 	CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
22140a055120SJason King 	CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
22150a055120SJason King 	CTASSERT(sizeof (bonus_size) >= NN_NUMBUF_SZ);
22160a055120SJason King 
2217fa9e4066Sahrens 	if (*print_header) {
221854811da5SToomas Soome 		(void) printf("\n%10s  %3s  %5s  %5s  %5s  %6s  %5s  %6s  %s\n",
221954811da5SToomas Soome 		    "Object", "lvl", "iblk", "dblk", "dsize", "dnsize",
222054811da5SToomas Soome 		    "lsize", "%full", "type");
2221fa9e4066Sahrens 		*print_header = 0;
2222fa9e4066Sahrens 	}
2223fa9e4066Sahrens 
2224fa9e4066Sahrens 	if (object == 0) {
2225744947dcSTom Erickson 		dn = DMU_META_DNODE(os);
2226eb633035STom Caputi 		dmu_object_info_from_dnode(dn, &doi);
2227fa9e4066Sahrens 	} else {
2228eb633035STom Caputi 		/*
2229eb633035STom Caputi 		 * Encrypted datasets will have sensitive bonus buffers
2230eb633035STom Caputi 		 * encrypted. Therefore we cannot hold the bonus buffer and
2231eb633035STom Caputi 		 * must hold the dnode itself instead.
2232eb633035STom Caputi 		 */
2233eb633035STom Caputi 		error = dmu_object_info(os, object, &doi);
2234ea8dc4b6Seschrock 		if (error)
2235eb633035STom Caputi 			fatal("dmu_object_info() failed, errno %u", error);
2236eb633035STom Caputi 
2237eb633035STom Caputi 		if (os->os_encrypted &&
2238eb633035STom Caputi 		    DMU_OT_IS_ENCRYPTED(doi.doi_bonus_type)) {
2239eb633035STom Caputi 			error = dnode_hold(os, object, FTAG, &dn);
2240eb633035STom Caputi 			if (error)
2241eb633035STom Caputi 				fatal("dnode_hold() failed, errno %u", error);
2242eb633035STom Caputi 			dnode_held = B_TRUE;
2243eb633035STom Caputi 		} else {
2244eb633035STom Caputi 			error = dmu_bonus_hold(os, object, FTAG, &db);
2245eb633035STom Caputi 			if (error)
2246eb633035STom Caputi 				fatal("dmu_bonus_hold(%llu) failed, errno %u",
2247eb633035STom Caputi 				    object, error);
2248eb633035STom Caputi 			bonus = db->db_data;
2249eb633035STom Caputi 			bsize = db->db_size;
2250eb633035STom Caputi 			dn = DB_DNODE((dmu_buf_impl_t *)db);
2251eb633035STom Caputi 		}
2252fa9e4066Sahrens 	}
2253fa9e4066Sahrens 
225454811da5SToomas Soome 	if (dnode_slots_used != NULL)
225554811da5SToomas Soome 		*dnode_slots_used = doi.doi_dnodesize / DNODE_MIN_SIZE;
225654811da5SToomas Soome 
22570a055120SJason King 	zdb_nicenum(doi.doi_metadata_block_size, iblk, sizeof (iblk));
22580a055120SJason King 	zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
22590a055120SJason King 	zdb_nicenum(doi.doi_max_offset, lsize, sizeof (lsize));
22600a055120SJason King 	zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
22610a055120SJason King 	zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
226254811da5SToomas Soome 	zdb_nicenum(doi.doi_dnodesize, dnsize, sizeof (dnsize));
2263b24ab676SJeff Bonwick 	(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
2264bbfd46c4SJeff Bonwick 	    doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
2265bbfd46c4SJeff Bonwick 	    doi.doi_max_offset);
2266fa9e4066Sahrens 
2267fa9e4066Sahrens 	aux[0] = '\0';
2268fa9e4066Sahrens 
2269e7437265Sahrens 	if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) {
2270fa9e4066Sahrens 		(void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)",
22716de8f417SVictor Latushkin 		    ZDB_CHECKSUM_NAME(doi.doi_checksum));
2272e7437265Sahrens 	}
2273fa9e4066Sahrens 
2274e7437265Sahrens 	if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) {
2275fa9e4066Sahrens 		(void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)",
22766de8f417SVictor Latushkin 		    ZDB_COMPRESS_NAME(doi.doi_compress));
2277e7437265Sahrens 	}
2278fa9e4066Sahrens 
227954811da5SToomas Soome 	(void) printf("%10" PRIu64
228054811da5SToomas Soome 	    "  %3u  %5s  %5s  %5s  %5s  %5s  %6s  %s%s\n",
228154811da5SToomas Soome 	    object, doi.doi_indirection, iblk, dblk,
228254811da5SToomas Soome 	    asize, dnsize, lsize, fill, ZDB_OT_NAME(doi.doi_type), aux);
2283fa9e4066Sahrens 
2284fa9e4066Sahrens 	if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) {
228554811da5SToomas Soome 		(void) printf("%10s  %3s  %5s  %5s  %5s  %5s  %5s  %6s  %s\n",
228654811da5SToomas Soome 		    "", "", "", "", "", "", bonus_size, "bonus",
22876de8f417SVictor Latushkin 		    ZDB_OT_NAME(doi.doi_bonus_type));
2288fa9e4066Sahrens 	}
2289fa9e4066Sahrens 
2290fa9e4066Sahrens 	if (verbosity >= 4) {
2291f67950b2SNasf-Fan 		(void) printf("\tdnode flags: %s%s%s%s\n",
229214843421SMatthew Ahrens 		    (dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) ?
229314843421SMatthew Ahrens 		    "USED_BYTES " : "",
229414843421SMatthew Ahrens 		    (dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED) ?
22950a586ceaSMark Shellenbaum 		    "USERUSED_ACCOUNTED " : "",
2296f67950b2SNasf-Fan 		    (dn->dn_phys->dn_flags & DNODE_FLAG_USEROBJUSED_ACCOUNTED) ?
2297f67950b2SNasf-Fan 		    "USEROBJUSED_ACCOUNTED " : "",
22980a586ceaSMark Shellenbaum 		    (dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR) ?
22990a586ceaSMark Shellenbaum 		    "SPILL_BLKPTR" : "");
230014843421SMatthew Ahrens 		(void) printf("\tdnode maxblkid: %llu\n",
230114843421SMatthew Ahrens 		    (longlong_t)dn->dn_phys->dn_maxblkid);
230214843421SMatthew Ahrens 
2303eb633035STom Caputi 		if (!dnode_held) {
2304eb633035STom Caputi 			object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os,
2305eb633035STom Caputi 			    object, bonus, bsize);
2306eb633035STom Caputi 		} else {
2307eb633035STom Caputi 			(void) printf("\t\t(bonus encrypted)\n");
2308eb633035STom Caputi 		}
2309eb633035STom Caputi 
2310eb633035STom Caputi 		if (!os->os_encrypted || !DMU_OT_IS_ENCRYPTED(doi.doi_type)) {
2311eb633035STom Caputi 			object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object,
2312eb633035STom Caputi 			    NULL, 0);
2313eb633035STom Caputi 		} else {
2314eb633035STom Caputi 			(void) printf("\t\t(object encrypted)\n");
2315eb633035STom Caputi 		}
2316eb633035STom Caputi 
2317fa9e4066Sahrens 		*print_header = 1;
2318fa9e4066Sahrens 	}
2319fa9e4066Sahrens 
2320fa9e4066Sahrens 	if (verbosity >= 5)
232188b7b0f2SMatthew Ahrens 		dump_indirect(dn);
2322fa9e4066Sahrens 
2323fa9e4066Sahrens 	if (verbosity >= 5) {
2324fa9e4066Sahrens 		/*
2325fa9e4066Sahrens 		 * Report the list of segments that comprise the object.
2326fa9e4066Sahrens 		 */
2327fa9e4066Sahrens 		uint64_t start = 0;
2328fa9e4066Sahrens 		uint64_t end;
2329fa9e4066Sahrens 		uint64_t blkfill = 1;
2330fa9e4066Sahrens 		int minlvl = 1;
2331fa9e4066Sahrens 
2332fa9e4066Sahrens 		if (dn->dn_type == DMU_OT_DNODE) {
2333fa9e4066Sahrens 			minlvl = 0;
2334fa9e4066Sahrens 			blkfill = DNODES_PER_BLOCK;
2335fa9e4066Sahrens 		}
2336fa9e4066Sahrens 
2337fa9e4066Sahrens 		for (;;) {
23383f9d6ad7SLin Ling 			char segsize[32];
23390a055120SJason King 			/* make sure nicenum has enough space */
23400a055120SJason King 			CTASSERT(sizeof (segsize) >= NN_NUMBUF_SZ);
2341cdb0ab79Smaybee 			error = dnode_next_offset(dn,
2342cdb0ab79Smaybee 			    0, &start, minlvl, blkfill, 0);
2343fa9e4066Sahrens 			if (error)
2344fa9e4066Sahrens 				break;
2345fa9e4066Sahrens 			end = start;
2346cdb0ab79Smaybee 			error = dnode_next_offset(dn,
2347cdb0ab79Smaybee 			    DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
23480a055120SJason King 			zdb_nicenum(end - start, segsize, sizeof (segsize));
2349fa9e4066Sahrens 			(void) printf("\t\tsegment [%016llx, %016llx)"
2350fa9e4066Sahrens 			    " size %5s\n", (u_longlong_t)start,
2351fa9e4066Sahrens 			    (u_longlong_t)end, segsize);
2352fa9e4066Sahrens 			if (error)
2353fa9e4066Sahrens 				break;
2354fa9e4066Sahrens 			start = end;
2355fa9e4066Sahrens 		}
2356fa9e4066Sahrens 	}
2357fa9e4066Sahrens 
2358fa9e4066Sahrens 	if (db != NULL)
2359ea8dc4b6Seschrock 		dmu_buf_rele(db, FTAG);
2360eb633035STom Caputi 	if (dnode_held)
2361eb633035STom Caputi 		dnode_rele(dn, FTAG);
2362fa9e4066Sahrens }
2363fa9e4066Sahrens 
236417fb938fSMatthew Ahrens static void
236517fb938fSMatthew Ahrens count_dir_mos_objects(dsl_dir_t *dd)
236617fb938fSMatthew Ahrens {
236717fb938fSMatthew Ahrens 	mos_obj_refd(dd->dd_object);
236817fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dir_phys(dd)->dd_child_dir_zapobj);
236917fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dir_phys(dd)->dd_deleg_zapobj);
237017fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dir_phys(dd)->dd_props_zapobj);
237117fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dir_phys(dd)->dd_clones);
237217fb938fSMatthew Ahrens }
237317fb938fSMatthew Ahrens 
237417fb938fSMatthew Ahrens static void
237517fb938fSMatthew Ahrens count_ds_mos_objects(dsl_dataset_t *ds)
237617fb938fSMatthew Ahrens {
237717fb938fSMatthew Ahrens 	mos_obj_refd(ds->ds_object);
237817fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dataset_phys(ds)->ds_next_clones_obj);
237917fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dataset_phys(ds)->ds_props_obj);
238017fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dataset_phys(ds)->ds_userrefs_obj);
238117fb938fSMatthew Ahrens 	mos_obj_refd(dsl_dataset_phys(ds)->ds_snapnames_zapobj);
238217fb938fSMatthew Ahrens 
238317fb938fSMatthew Ahrens 	if (!dsl_dataset_is_snapshot(ds)) {
238417fb938fSMatthew Ahrens 		count_dir_mos_objects(ds->ds_dir);
238517fb938fSMatthew Ahrens 	}
238617fb938fSMatthew Ahrens }
238717fb938fSMatthew Ahrens 
23883f7978d0SAlan Somers static const char *objset_types[DMU_OST_NUMTYPES] = {
2389fa9e4066Sahrens 	"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
2390fa9e4066Sahrens 
2391fa9e4066Sahrens static void
2392fa9e4066Sahrens dump_dir(objset_t *os)
2393fa9e4066Sahrens {
2394fa9e4066Sahrens 	dmu_objset_stats_t dds;
2395fa9e4066Sahrens 	uint64_t object, object_count;
2396a2eea2e1Sahrens 	uint64_t refdbytes, usedobjs, scratch;
23973f9d6ad7SLin Ling 	char numbuf[32];
239814843421SMatthew Ahrens 	char blkbuf[BP_SPRINTF_LEN + 20];
23999adfa60dSMatthew Ahrens 	char osname[ZFS_MAX_DATASET_NAME_LEN];
24003f7978d0SAlan Somers 	const char *type = "UNKNOWN";
2401fa9e4066Sahrens 	int verbosity = dump_opt['d'];
2402fa9e4066Sahrens 	int print_header = 1;
24033f7978d0SAlan Somers 	unsigned i;
24043f7978d0SAlan Somers 	int error;
240554811da5SToomas Soome 	uint64_t total_slots_used = 0;
240654811da5SToomas Soome 	uint64_t max_slot_used = 0;
240754811da5SToomas Soome 	uint64_t dnode_slots;
2408fa9e4066Sahrens 
24090a055120SJason King 	/* make sure nicenum has enough space */
24100a055120SJason King 	CTASSERT(sizeof (numbuf) >= NN_NUMBUF_SZ);
24110a055120SJason King 
24123b2aab18SMatthew Ahrens 	dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
2413a2eea2e1Sahrens 	dmu_objset_fast_stat(os, &dds);
24143b2aab18SMatthew Ahrens 	dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
2415fa9e4066Sahrens 
2416fa9e4066Sahrens 	if (dds.dds_type < DMU_OST_NUMTYPES)
2417fa9e4066Sahrens 		type = objset_types[dds.dds_type];
2418fa9e4066Sahrens 
2419fa9e4066Sahrens 	if (dds.dds_type == DMU_OST_META) {
2420fa9e4066Sahrens 		dds.dds_creation_txg = TXG_INITIAL;
24215d7b4d43SMatthew Ahrens 		usedobjs = BP_GET_FILL(os->os_rootbp);
2422c1379625SJustin T. Gibbs 		refdbytes = dsl_dir_phys(os->os_spa->spa_dsl_pool->dp_mos_dir)->
2423c1379625SJustin T. Gibbs 		    dd_used_bytes;
2424a2eea2e1Sahrens 	} else {
2425a2eea2e1Sahrens 		dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch);
2426fa9e4066Sahrens 	}
2427fa9e4066Sahrens 
24285d7b4d43SMatthew Ahrens 	ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
2429fa9e4066Sahrens 
24300a055120SJason King 	zdb_nicenum(refdbytes, numbuf, sizeof (numbuf));
2431fa9e4066Sahrens 
2432fa9e4066Sahrens 	if (verbosity >= 4) {
243343466aaeSMax Grossman 		(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
243443466aaeSMax Grossman 		(void) snprintf_blkptr(blkbuf + strlen(blkbuf),
243543466aaeSMax Grossman 		    sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp);
2436fa9e4066Sahrens 	} else {
2437fa9e4066Sahrens 		blkbuf[0] = '\0';
2438fa9e4066Sahrens 	}
2439fa9e4066Sahrens 
2440fa9e4066Sahrens 	dmu_objset_name(os, osname);
2441fa9e4066Sahrens 
2442a2eea2e1Sahrens 	(void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, "
2443ade2c828SSerapheim Dimitropoulos 	    "%s, %llu objects%s%s\n",
2444fa9e4066Sahrens 	    osname, type, (u_longlong_t)dmu_objset_id(os),
2445fa9e4066Sahrens 	    (u_longlong_t)dds.dds_creation_txg,
2446ade2c828SSerapheim Dimitropoulos 	    numbuf, (u_longlong_t)usedobjs, blkbuf,
2447ade2c828SSerapheim Dimitropoulos 	    (dds.dds_inconsistent) ? " (inconsistent)" : "");
2448fa9e4066Sahrens 
2449b24ab676SJeff Bonwick 	if (zopt_objects != 0) {
2450b24ab676SJeff Bonwick 		for (i = 0; i < zopt_objects; i++)
2451b24ab676SJeff Bonwick 			dump_object(os, zopt_object[i], verbosity,
245254811da5SToomas Soome 			    &print_header, NULL);
2453b24ab676SJeff Bonwick 		(void) printf("\n");
2454b24ab676SJeff Bonwick 		return;
2455b24ab676SJeff Bonwick 	}
2456b24ab676SJeff Bonwick 
2457b24ab676SJeff Bonwick 	if (dump_opt['i'] != 0 || verbosity >= 2)
2458b24ab676SJeff Bonwick 		dump_intent_log(dmu_objset_zil(os));
2459fa9e4066Sahrens 
24605cabbc6bSPrashanth Sreenivasa 	if (dmu_objset_ds(os) != NULL) {
24615cabbc6bSPrashanth Sreenivasa 		dsl_dataset_t *ds = dmu_objset_ds(os);
24625cabbc6bSPrashanth Sreenivasa 		dump_deadlist(&ds->ds_deadlist);
24635cabbc6bSPrashanth Sreenivasa 
24645cabbc6bSPrashanth Sreenivasa 		if (dsl_dataset_remap_deadlist_exists(ds)) {
24655cabbc6bSPrashanth Sreenivasa 			(void) printf("ds_remap_deadlist:\n");
24665cabbc6bSPrashanth Sreenivasa 			dump_deadlist(&ds->ds_remap_deadlist);
24675cabbc6bSPrashanth Sreenivasa 		}
246817fb938fSMatthew Ahrens 		count_ds_mos_objects(ds);
24695cabbc6bSPrashanth Sreenivasa 	}
2470fa9e4066Sahrens 
2471fa9e4066Sahrens 	if (verbosity < 2)
2472fa9e4066Sahrens 		return;
2473fa9e4066Sahrens 
247443466aaeSMax Grossman 	if (BP_IS_HOLE(os->os_rootbp))
2475088f3894Sahrens 		return;
2476088f3894Sahrens 
247754811da5SToomas Soome 	dump_object(os, 0, verbosity, &print_header, NULL);
247814843421SMatthew Ahrens 	object_count = 0;
2479744947dcSTom Erickson 	if (DMU_USERUSED_DNODE(os) != NULL &&
2480744947dcSTom Erickson 	    DMU_USERUSED_DNODE(os)->dn_type != 0) {
248154811da5SToomas Soome 		dump_object(os, DMU_USERUSED_OBJECT, verbosity, &print_header,
248254811da5SToomas Soome 		    NULL);
248354811da5SToomas Soome 		dump_object(os, DMU_GROUPUSED_OBJECT, verbosity, &print_header,
248454811da5SToomas Soome 		    NULL);
248514843421SMatthew Ahrens 	}
2486fa9e4066Sahrens 
2487f67950b2SNasf-Fan 	if (DMU_PROJECTUSED_DNODE(os) != NULL &&
2488f67950b2SNasf-Fan 	    DMU_PROJECTUSED_DNODE(os)->dn_type != 0)
2489f67950b2SNasf-Fan 		dump_object(os, DMU_PROJECTUSED_OBJECT, verbosity,
2490f67950b2SNasf-Fan 		    &print_header, NULL);
2491f67950b2SNasf-Fan 
2492fa9e4066Sahrens 	object = 0;
24936754306eSahrens 	while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) {
249454811da5SToomas Soome 		dump_object(os, object, verbosity, &print_header, &dnode_slots);
2495fa9e4066Sahrens 		object_count++;
249654811da5SToomas Soome 		total_slots_used += dnode_slots;
249754811da5SToomas Soome 		max_slot_used = object + dnode_slots - 1;
2498fa9e4066Sahrens 	}
2499fa9e4066Sahrens 
2500fa9e4066Sahrens 	(void) printf("\n");
2501fa9e4066Sahrens 
250254811da5SToomas Soome 	(void) printf("    Dnode slots:\n");
250354811da5SToomas Soome 	(void) printf("\tTotal used:    %10llu\n",
250454811da5SToomas Soome 	    (u_longlong_t)total_slots_used);
250554811da5SToomas Soome 	(void) printf("\tMax used:      %10llu\n",
250654811da5SToomas Soome 	    (u_longlong_t)max_slot_used);
250754811da5SToomas Soome 	(void) printf("\tPercent empty: %10lf\n",
250854811da5SToomas Soome 	    (double)(max_slot_used - total_slots_used)*100 /
250954811da5SToomas Soome 	    (double)max_slot_used);
251054811da5SToomas Soome 
251154811da5SToomas Soome 	(void) printf("\n");
251254811da5SToomas Soome 
2513ccba0801SRich Morris 	if (error != ESRCH) {
2514ccba0801SRich Morris 		(void) fprintf(stderr, "dmu_object_next() = %d\n", error);
2515ccba0801SRich Morris 		abort();
2516ccba0801SRich Morris 	}
251720b5dafbSPaul Dagnelie 	if (leaked_objects != 0) {
251820b5dafbSPaul Dagnelie 		(void) printf("%d potentially leaked objects detected\n",
251920b5dafbSPaul Dagnelie 		    leaked_objects);
252020b5dafbSPaul Dagnelie 		leaked_objects = 0;
252120b5dafbSPaul Dagnelie 	}
2522a3874b8bSToomas Soome 
2523a3874b8bSToomas Soome 	ASSERT3U(object_count, ==, usedobjs);
2524fa9e4066Sahrens }
2525fa9e4066Sahrens 
2526fa9e4066Sahrens static void
252753b9a4a9SVictor Latushkin dump_uberblock(uberblock_t *ub, const char *header, const char *footer)
2528fa9e4066Sahrens {
2529fa9e4066Sahrens 	time_t timestamp = ub->ub_timestamp;
2530fa9e4066Sahrens 
25313f7978d0SAlan Somers 	(void) printf("%s", header ? header : "");
2532fa9e4066Sahrens 	(void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic);
2533fa9e4066Sahrens 	(void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version);
2534fa9e4066Sahrens 	(void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg);
2535fa9e4066Sahrens 	(void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum);
2536fa9e4066Sahrens 	(void) printf("\ttimestamp = %llu UTC = %s",
2537fa9e4066Sahrens 	    (u_longlong_t)ub->ub_timestamp, asctime(localtime(&timestamp)));
2538e0f1c0afSOlaf Faaland 
2539e0f1c0afSOlaf Faaland 	(void) printf("\tmmp_magic = %016llx\n",
2540e0f1c0afSOlaf Faaland 	    (u_longlong_t)ub->ub_mmp_magic);
2541e0f1c0afSOlaf Faaland 	if (ub->ub_mmp_magic == MMP_MAGIC)
2542e0f1c0afSOlaf Faaland 		(void) printf("\tmmp_delay = %0llu\n",
2543e0f1c0afSOlaf Faaland 		    (u_longlong_t)ub->ub_mmp_delay);
2544e0f1c0afSOlaf Faaland 
2545fa9e4066Sahrens 	if (dump_opt['u'] >= 3) {
2546fbabab8fSmaybee 		char blkbuf[BP_SPRINTF_LEN];
254743466aaeSMax Grossman 		snprintf_blkptr(blkbuf, sizeof (blkbuf), &ub->ub_rootbp);
2548fa9e4066Sahrens 		(void) printf("\trootbp = %s\n", blkbuf);
2549fa9e4066Sahrens 	}
255086714001SSerapheim Dimitropoulos 	(void) printf("\tcheckpoint_txg = %llu\n",
255186714001SSerapheim Dimitropoulos 	    (u_longlong_t)ub->ub_checkpoint_txg);
25523f7978d0SAlan Somers 	(void) printf("%s", footer ? footer : "");
2553fa9e4066Sahrens }
2554fa9e4066Sahrens 
2555fa9e4066Sahrens static void
255607428bdfSVictor Latushkin dump_config(spa_t *spa)
2557fa9e4066Sahrens {
255807428bdfSVictor Latushkin 	dmu_buf_t *db;
255907428bdfSVictor Latushkin 	size_t nvsize = 0;
256007428bdfSVictor Latushkin 	int error = 0;
256107428bdfSVictor Latushkin 
2562fa9e4066Sahrens 
256307428bdfSVictor Latushkin 	error = dmu_bonus_hold(spa->spa_meta_objset,
256407428bdfSVictor Latushkin 	    spa->spa_config_object, FTAG, &db);
256507428bdfSVictor Latushkin 
256607428bdfSVictor Latushkin 	if (error == 0) {
256707428bdfSVictor Latushkin 		nvsize = *(uint64_t *)db->db_data;
256807428bdfSVictor Latushkin 		dmu_buf_rele(db, FTAG);
256907428bdfSVictor Latushkin 
257007428bdfSVictor Latushkin 		(void) printf("\nMOS Configuration:\n");
257107428bdfSVictor Latushkin 		dump_packed_nvlist(spa->spa_meta_objset,
257207428bdfSVictor Latushkin 		    spa->spa_config_object, (void *)&nvsize, 1);
257307428bdfSVictor Latushkin 	} else {
257407428bdfSVictor Latushkin 		(void) fprintf(stderr, "dmu_bonus_hold(%llu) failed, errno %d",
257507428bdfSVictor Latushkin 		    (u_longlong_t)spa->spa_config_object, error);
2576fa9e4066Sahrens 	}
2577fa9e4066Sahrens }
2578fa9e4066Sahrens 
2579c5904d13Seschrock static void
2580c5904d13Seschrock dump_cachefile(const char *cachefile)
2581c5904d13Seschrock {
2582c5904d13Seschrock 	int fd;
2583c5904d13Seschrock 	struct stat64 statbuf;
2584c5904d13Seschrock 	char *buf;
2585c5904d13Seschrock 	nvlist_t *config;
2586c5904d13Seschrock 
2587c5904d13Seschrock 	if ((fd = open64(cachefile, O_RDONLY)) < 0) {
2588c5904d13Seschrock 		(void) printf("cannot open '%s': %s\n", cachefile,
2589c5904d13Seschrock 		    strerror(errno));
2590c5904d13Seschrock 		exit(1);
2591c5904d13Seschrock 	}
2592c5904d13Seschrock 
2593c5904d13Seschrock 	if (fstat64(fd, &statbuf) != 0) {
2594c5904d13Seschrock 		(void) printf("failed to stat '%s': %s\n", cachefile,
2595c5904d13Seschrock 		    strerror(errno));
2596c5904d13Seschrock 		exit(1);
2597c5904d13Seschrock 	}
2598c5904d13Seschrock 
2599c5904d13Seschrock 	if ((buf = malloc(statbuf.st_size)) == NULL) {
2600c5904d13Seschrock 		(void) fprintf(stderr, "failed to allocate %llu bytes\n",
2601c5904d13Seschrock 		    (u_longlong_t)statbuf.st_size);
2602c5904d13Seschrock 		exit(1);
2603c5904d13Seschrock 	}
2604c5904d13Seschrock 
2605c5904d13Seschrock 	if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
2606c5904d13Seschrock 		(void) fprintf(stderr, "failed to read %llu bytes\n",
2607c5904d13Seschrock 		    (u_longlong_t)statbuf.st_size);
2608c5904d13Seschrock 		exit(1);
2609c5904d13Seschrock 	}
2610c5904d13Seschrock 
2611c5904d13Seschrock 	(void) close(fd);
2612c5904d13Seschrock 
2613c5904d13Seschrock 	if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
2614c5904d13Seschrock 		(void) fprintf(stderr, "failed to unpack nvlist\n");
2615c5904d13Seschrock 		exit(1);
2616c5904d13Seschrock 	}
2617c5904d13Seschrock 
2618c5904d13Seschrock 	free(buf);
2619c5904d13Seschrock 
2620c5904d13Seschrock 	dump_nvlist(config, 0);
2621c5904d13Seschrock 
2622c5904d13Seschrock 	nvlist_free(config);
2623c5904d13Seschrock }
2624c5904d13Seschrock 
262553b9a4a9SVictor Latushkin #define	ZDB_MAX_UB_HEADER_SIZE 32
262653b9a4a9SVictor Latushkin 
262753b9a4a9SVictor Latushkin static void
262853b9a4a9SVictor Latushkin dump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
262953b9a4a9SVictor Latushkin {
263053b9a4a9SVictor Latushkin 	vdev_t vd;
263153b9a4a9SVictor Latushkin 	vdev_t *vdp = &vd;
263253b9a4a9SVictor Latushkin 	char header[ZDB_MAX_UB_HEADER_SIZE];
263353b9a4a9SVictor Latushkin 
263453b9a4a9SVictor Latushkin 	vd.vdev_ashift = ashift;
263553b9a4a9SVictor Latushkin 	vdp->vdev_top = vdp;
263653b9a4a9SVictor Latushkin 
263753b9a4a9SVictor Latushkin 	for (int i = 0; i < VDEV_UBERBLOCK_COUNT(vdp); i++) {
263853b9a4a9SVictor Latushkin 		uint64_t uoff = VDEV_UBERBLOCK_OFFSET(vdp, i);
263953b9a4a9SVictor Latushkin 		uberblock_t *ub = (void *)((char *)lbl + uoff);
264053b9a4a9SVictor Latushkin 
264153b9a4a9SVictor Latushkin 		if (uberblock_verify(ub))
264253b9a4a9SVictor Latushkin 			continue;
2643e0f1c0afSOlaf Faaland 
2644e0f1c0afSOlaf Faaland 		if ((dump_opt['u'] < 4) &&
2645e0f1c0afSOlaf Faaland 		    (ub->ub_mmp_magic == MMP_MAGIC) && ub->ub_mmp_delay &&
2646e0f1c0afSOlaf Faaland 		    (i >= VDEV_UBERBLOCK_COUNT(&vd) - MMP_BLOCKS_PER_LABEL))
2647e0f1c0afSOlaf Faaland 			continue;
2648e0f1c0afSOlaf Faaland 
264953b9a4a9SVictor Latushkin 		(void) snprintf(header, ZDB_MAX_UB_HEADER_SIZE,
265053b9a4a9SVictor Latushkin 		    "Uberblock[%d]\n", i);
265153b9a4a9SVictor Latushkin 		dump_uberblock(ub, header, "");
265253b9a4a9SVictor Latushkin 	}
265353b9a4a9SVictor Latushkin }
265453b9a4a9SVictor Latushkin 
2655ed61ec1dSYuri Pankov static char curpath[PATH_MAX];
2656ed61ec1dSYuri Pankov 
2657ed61ec1dSYuri Pankov /*
2658ed61ec1dSYuri Pankov  * Iterate through the path components, recursively passing
2659ed61ec1dSYuri Pankov  * current one's obj and remaining path until we find the obj
2660ed61ec1dSYuri Pankov  * for the last one.
2661ed61ec1dSYuri Pankov  */
2662ed61ec1dSYuri Pankov static int
2663ed61ec1dSYuri Pankov dump_path_impl(objset_t *os, uint64_t obj, char *name)
2664ed61ec1dSYuri Pankov {
2665ed61ec1dSYuri Pankov 	int err;
2666ed61ec1dSYuri Pankov 	int header = 1;
2667ed61ec1dSYuri Pankov 	uint64_t child_obj;
2668ed61ec1dSYuri Pankov 	char *s;
2669ed61ec1dSYuri Pankov 	dmu_buf_t *db;
2670ed61ec1dSYuri Pankov 	dmu_object_info_t doi;
2671ed61ec1dSYuri Pankov 
2672ed61ec1dSYuri Pankov 	if ((s = strchr(name, '/')) != NULL)
2673ed61ec1dSYuri Pankov 		*s = '\0';
2674ed61ec1dSYuri Pankov 	err = zap_lookup(os, obj, name, 8, 1, &child_obj);
2675ed61ec1dSYuri Pankov 
2676ed61ec1dSYuri Pankov 	(void) strlcat(curpath, name, sizeof (curpath));
2677ed61ec1dSYuri Pankov 
2678ed61ec1dSYuri Pankov 	if (err != 0) {
2679ed61ec1dSYuri Pankov 		(void) fprintf(stderr, "failed to lookup %s: %s\n",
2680ed61ec1dSYuri Pankov 		    curpath, strerror(err));
2681ed61ec1dSYuri Pankov 		return (err);
2682ed61ec1dSYuri Pankov 	}
2683ed61ec1dSYuri Pankov 
2684ed61ec1dSYuri Pankov 	child_obj = ZFS_DIRENT_OBJ(child_obj);
2685ed61ec1dSYuri Pankov 	err = sa_buf_hold(os, child_obj, FTAG, &db);
2686ed61ec1dSYuri Pankov 	if (err != 0) {
2687ed61ec1dSYuri Pankov 		(void) fprintf(stderr,
2688ed61ec1dSYuri Pankov 		    "failed to get SA dbuf for obj %llu: %s\n",
2689ed61ec1dSYuri Pankov 		    (u_longlong_t)child_obj, strerror(err));
2690ed61ec1dSYuri Pankov 		return (EINVAL);
2691ed61ec1dSYuri Pankov 	}
2692ed61ec1dSYuri Pankov 	dmu_object_info_from_db(db, &doi);
2693ed61ec1dSYuri Pankov 	sa_buf_rele(db, FTAG);
2694ed61ec1dSYuri Pankov 
2695ed61ec1dSYuri Pankov 	if (doi.doi_bonus_type != DMU_OT_SA &&
2696ed61ec1dSYuri Pankov 	    doi.doi_bonus_type != DMU_OT_ZNODE) {
2697ed61ec1dSYuri Pankov 		(void) fprintf(stderr, "invalid bonus type %d for obj %llu\n",
2698ed61ec1dSYuri Pankov 		    doi.doi_bonus_type, (u_longlong_t)child_obj);
2699ed61ec1dSYuri Pankov 		return (EINVAL);
2700ed61ec1dSYuri Pankov 	}
2701ed61ec1dSYuri Pankov 
2702ed61ec1dSYuri Pankov 	if (dump_opt['v'] > 6) {
2703ed61ec1dSYuri Pankov 		(void) printf("obj=%llu %s type=%d bonustype=%d\n",
2704ed61ec1dSYuri Pankov 		    (u_longlong_t)child_obj, curpath, doi.doi_type,
2705ed61ec1dSYuri Pankov 		    doi.doi_bonus_type);
2706ed61ec1dSYuri Pankov 	}
2707ed61ec1dSYuri Pankov 
2708ed61ec1dSYuri Pankov 	(void) strlcat(curpath, "/", sizeof (curpath));
2709ed61ec1dSYuri Pankov 
2710ed61ec1dSYuri Pankov 	switch (doi.doi_type) {
2711ed61ec1dSYuri Pankov 	case DMU_OT_DIRECTORY_CONTENTS:
2712ed61ec1dSYuri Pankov 		if (s != NULL && *(s + 1) != '\0')
2713ed61ec1dSYuri Pankov 			return (dump_path_impl(os, child_obj, s + 1));
2714ed61ec1dSYuri Pankov 		/*FALLTHROUGH*/
2715ed61ec1dSYuri Pankov 	case DMU_OT_PLAIN_FILE_CONTENTS:
271654811da5SToomas Soome 		dump_object(os, child_obj, dump_opt['v'], &header, NULL);
2717ed61ec1dSYuri Pankov 		return (0);
2718ed61ec1dSYuri Pankov 	default:
2719ed61ec1dSYuri Pankov 		(void) fprintf(stderr, "object %llu has non-file/directory "
2720ed61ec1dSYuri Pankov 		    "type %d\n", (u_longlong_t)obj, doi.doi_type);
2721ed61ec1dSYuri Pankov 		break;
2722ed61ec1dSYuri Pankov 	}
2723ed61ec1dSYuri Pankov 
2724ed61ec1dSYuri Pankov 	return (EINVAL);
2725ed61ec1dSYuri Pankov }
2726ed61ec1dSYuri Pankov 
2727ed61ec1dSYuri Pankov /*
2728ed61ec1dSYuri Pankov  * Dump the blocks for the object specified by path inside the dataset.
2729ed61ec1dSYuri Pankov  */
2730ed61ec1dSYuri Pankov static int
2731ed61ec1dSYuri Pankov dump_path(char *ds, char *path)
2732ed61ec1dSYuri Pankov {
2733ed61ec1dSYuri Pankov 	int err;
2734ed61ec1dSYuri Pankov 	objset_t *os;
2735ed61ec1dSYuri Pankov 	uint64_t root_obj;
2736ed61ec1dSYuri Pankov 
2737ed61ec1dSYuri Pankov 	err = open_objset(ds, DMU_OST_ZFS, FTAG, &os);
2738ed61ec1dSYuri Pankov 	if (err != 0)
2739ed61ec1dSYuri Pankov 		return (err);
2740ed61ec1dSYuri Pankov 
2741ed61ec1dSYuri Pankov 	err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj);
2742ed61ec1dSYuri Pankov 	if (err != 0) {
2743ed61ec1dSYuri Pankov 		(void) fprintf(stderr, "can't lookup root znode: %s\n",
2744ed61ec1dSYuri Pankov 		    strerror(err));
2745eb633035STom Caputi 		dmu_objset_disown(os, B_FALSE, FTAG);
2746ed61ec1dSYuri Pankov 		return (EINVAL);
2747ed61ec1dSYuri Pankov 	}
2748ed61ec1dSYuri Pankov 
2749ed61ec1dSYuri Pankov 	(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
2750ed61ec1dSYuri Pankov 
2751ed61ec1dSYuri Pankov 	err = dump_path_impl(os, root_obj, path);
2752ed61ec1dSYuri Pankov 
2753ed61ec1dSYuri Pankov 	close_objset(os, FTAG);
2754ed61ec1dSYuri Pankov 	return (err);
2755ed61ec1dSYuri Pankov }
2756ed61ec1dSYuri Pankov 
275764723e36SYuri Pankov static int
2758fa9e4066Sahrens dump_label(const char *dev)
2759fa9e4066Sahrens {
2760fa9e4066Sahrens 	int fd;
2761fa9e4066Sahrens 	vdev_label_t label;
276264723e36SYuri Pankov 	char path[MAXPATHLEN];
276364723e36SYuri Pankov 	char *buf = label.vl_vdev_phys.vp_nvlist;
2764fa9e4066Sahrens 	size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
2765fa9e4066Sahrens 	struct stat64 statbuf;
276653b9a4a9SVictor Latushkin 	uint64_t psize, ashift;
276764723e36SYuri Pankov 	boolean_t label_found = B_FALSE;
276864723e36SYuri Pankov 
276964723e36SYuri Pankov 	(void) strlcpy(path, dev, sizeof (path));
277064723e36SYuri Pankov 	if (dev[0] == '/') {
277164723e36SYuri Pankov 		if (strncmp(dev, ZFS_DISK_ROOTD,
277264723e36SYuri Pankov 		    strlen(ZFS_DISK_ROOTD)) == 0) {
277364723e36SYuri Pankov 			(void) snprintf(path, sizeof (path), "%s%s",
277464723e36SYuri Pankov 			    ZFS_RDISK_ROOTD, dev + strlen(ZFS_DISK_ROOTD));
277564723e36SYuri Pankov 		}
277664723e36SYuri Pankov 	} else if (stat64(path, &statbuf) != 0) {
277764723e36SYuri Pankov 		char *s;
2778c6065d0fSGeorge Wilson 
277964723e36SYuri Pankov 		(void) snprintf(path, sizeof (path), "%s%s", ZFS_RDISK_ROOTD,
278064723e36SYuri Pankov 		    dev);
278122c8b958SYuri Pankov 		if (((s = strrchr(dev, 's')) == NULL &&
278222c8b958SYuri Pankov 		    (s = strchr(dev, 'p')) == NULL) ||
278322c8b958SYuri Pankov 		    !isdigit(*(s + 1)))
278464723e36SYuri Pankov 			(void) strlcat(path, "s0", sizeof (path));
2785fa9e4066Sahrens 	}
2786fa9e4066Sahrens 
278722c8b958SYuri Pankov 	if ((fd = open64(path, O_RDONLY)) < 0) {
278822c8b958SYuri Pankov 		(void) fprintf(stderr, "cannot open '%s': %s\n", path,
2789fa9e4066Sahrens 		    strerror(errno));
2790c6065d0fSGeorge Wilson 		exit(1);
2791c6065d0fSGeorge Wilson 	}
2792c6065d0fSGeorge Wilson 
279322c8b958SYuri Pankov 	if (fstat64(fd, &statbuf) != 0) {
279422c8b958SYuri Pankov 		(void) fprintf(stderr, "failed to stat '%s': %s\n", path,
279522c8b958SYuri Pankov 		    strerror(errno));
279622c8b958SYuri Pankov 		(void) close(fd);
279764723e36SYuri Pankov 		exit(1);
279864723e36SYuri Pankov 	}
279964723e36SYuri Pankov 
280022c8b958SYuri Pankov 	if (S_ISBLK(statbuf.st_mode)) {
280122c8b958SYuri Pankov 		(void) fprintf(stderr,
280222c8b958SYuri Pankov 		    "cannot use '%s': character device required\n", path);
280322c8b958SYuri Pankov 		(void) close(fd);
2804c6065d0fSGeorge Wilson 		exit(1);
2805fa9e4066Sahrens 	}
2806fa9e4066Sahrens 
2807fa9e4066Sahrens 	psize = statbuf.st_size;
2808fa9e4066Sahrens 	psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
2809fa9e4066Sahrens 
281053b9a4a9SVictor Latushkin 	for (int l = 0; l < VDEV_LABELS; l++) {
2811fa9e4066Sahrens 		nvlist_t *config = NULL;
2812fa9e4066Sahrens 
281364723e36SYuri Pankov 		if (!dump_opt['q']) {
281464723e36SYuri Pankov 			(void) printf("------------------------------------\n");
281564723e36SYuri Pankov 			(void) printf("LABEL %d\n", l);
281664723e36SYuri Pankov 			(void) printf("------------------------------------\n");
281764723e36SYuri Pankov 		}
2818fa9e4066Sahrens 
28190d981225Seschrock 		if (pread64(fd, &label, sizeof (label),
2820fa9e4066Sahrens 		    vdev_label_offset(psize, l, 0)) != sizeof (label)) {
282164723e36SYuri Pankov 			if (!dump_opt['q'])
282264723e36SYuri Pankov 				(void) printf("failed to read label %d\n", l);
2823fa9e4066Sahrens 			continue;
2824fa9e4066Sahrens 		}
2825fa9e4066Sahrens 
2826fa9e4066Sahrens 		if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
282764723e36SYuri Pankov 			if (!dump_opt['q'])
282864723e36SYuri Pankov 				(void) printf("failed to unpack label %d\n", l);
282953b9a4a9SVictor Latushkin 			ashift = SPA_MINBLOCKSHIFT;
283053b9a4a9SVictor Latushkin 		} else {
283153b9a4a9SVictor Latushkin 			nvlist_t *vdev_tree = NULL;
283253b9a4a9SVictor Latushkin 
283364723e36SYuri Pankov 			if (!dump_opt['q'])
283464723e36SYuri Pankov 				dump_nvlist(config, 4);
283553b9a4a9SVictor Latushkin 			if ((nvlist_lookup_nvlist(config,
283653b9a4a9SVictor Latushkin 			    ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
283753b9a4a9SVictor Latushkin 			    (nvlist_lookup_uint64(vdev_tree,
283853b9a4a9SVictor Latushkin 			    ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
283953b9a4a9SVictor Latushkin 				ashift = SPA_MINBLOCKSHIFT;
284053b9a4a9SVictor Latushkin 			nvlist_free(config);
284164723e36SYuri Pankov 			label_found = B_TRUE;
2842fa9e4066Sahrens 		}
284353b9a4a9SVictor Latushkin 		if (dump_opt['u'])
284453b9a4a9SVictor Latushkin 			dump_label_uberblocks(&label, ashift);
2845fa9e4066Sahrens 	}
2846c6065d0fSGeorge Wilson 
2847c6065d0fSGeorge Wilson 	(void) close(fd);
284864723e36SYuri Pankov 
284964723e36SYuri Pankov 	return (label_found ? 0 : 2);
2850fa9e4066Sahrens }
2851fa9e4066Sahrens 
2852ca0cc391SMatthew Ahrens static uint64_t dataset_feature_count[SPA_FEATURES];
28535cabbc6bSPrashanth Sreenivasa static uint64_t remap_deadlist_count = 0;
2854b5152584SMatthew Ahrens 
2855fa9e4066Sahrens /*ARGSUSED*/
28561d452cf5Sahrens static int
2857fd136879SMatthew Ahrens dump_one_dir(const char *dsname, void *arg)
2858fa9e4066Sahrens {
2859fa9e4066Sahrens 	int error;
2860fa9e4066Sahrens 	objset_t *os;
2861fa9e4066Sahrens 
2862ed61ec1dSYuri Pankov 	error = open_objset(dsname, DMU_OST_ANY, FTAG, &os);
2863ed61ec1dSYuri Pankov 	if (error != 0)
28641d452cf5Sahrens 		return (0);
2865ca0cc391SMatthew Ahrens 
2866ca0cc391SMatthew Ahrens 	for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
2867ca0cc391SMatthew Ahrens 		if (!dmu_objset_ds(os)->ds_feature_inuse[f])
2868ca0cc391SMatthew Ahrens 			continue;
2869ca0cc391SMatthew Ahrens 		ASSERT(spa_feature_table[f].fi_flags &
2870ca0cc391SMatthew Ahrens 		    ZFEATURE_FLAG_PER_DATASET);
2871ca0cc391SMatthew Ahrens 		dataset_feature_count[f]++;
2872ca0cc391SMatthew Ahrens 	}
2873ca0cc391SMatthew Ahrens 
28745cabbc6bSPrashanth Sreenivasa 	if (dsl_dataset_remap_deadlist_exists(dmu_objset_ds(os))) {
28755cabbc6bSPrashanth Sreenivasa 		remap_deadlist_count++;
28765cabbc6bSPrashanth Sreenivasa 	}
28775cabbc6bSPrashanth Sreenivasa 
2878fa9e4066Sahrens 	dump_dir(os);
2879ed61ec1dSYuri Pankov 	close_objset(os, FTAG);
2880e0d35c44Smarks 	fuid_table_destroy();
28811d452cf5Sahrens 	return (0);
2882fa9e4066Sahrens }
2883fa9e4066Sahrens 
2884fa9e4066Sahrens /*
2885b24ab676SJeff Bonwick  * Block statistics.
2886fa9e4066Sahrens  */
2887b5152584SMatthew Ahrens #define	PSIZE_HISTO_SIZE (SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 2)
2888fa9e4066Sahrens typedef struct zdb_blkstats {
2889490d05b9SMatthew Ahrens 	uint64_t zb_asize;
2890490d05b9SMatthew Ahrens 	uint64_t zb_lsize;
2891490d05b9SMatthew Ahrens 	uint64_t zb_psize;
2892490d05b9SMatthew Ahrens 	uint64_t zb_count;
2893d5ee8a13SMatthew Ahrens 	uint64_t zb_gangs;
2894d5ee8a13SMatthew Ahrens 	uint64_t zb_ditto_samevdev;
2895663207adSDon Brady 	uint64_t zb_ditto_same_ms;
2896490d05b9SMatthew Ahrens 	uint64_t zb_psize_histogram[PSIZE_HISTO_SIZE];
2897fa9e4066Sahrens } zdb_blkstats_t;
2898fa9e4066Sahrens 
2899b24ab676SJeff Bonwick /*
2900b24ab676SJeff Bonwick  * Extended object types to report deferred frees and dedup auto-ditto blocks.
2901b24ab676SJeff Bonwick  */
2902b24ab676SJeff Bonwick #define	ZDB_OT_DEFERRED	(DMU_OT_NUMTYPES + 0)
2903b24ab676SJeff Bonwick #define	ZDB_OT_DITTO	(DMU_OT_NUMTYPES + 1)
2904ad135b5dSChristopher Siden #define	ZDB_OT_OTHER	(DMU_OT_NUMTYPES + 2)
2905ad135b5dSChristopher Siden #define	ZDB_OT_TOTAL	(DMU_OT_NUMTYPES + 3)
2906b24ab676SJeff Bonwick 
29073f7978d0SAlan Somers static const char *zdb_ot_extname[] = {
2908b24ab676SJeff Bonwick 	"deferred free",
2909b24ab676SJeff Bonwick 	"dedup ditto",
2910ad135b5dSChristopher Siden 	"other",
2911b24ab676SJeff Bonwick 	"Total",
2912b24ab676SJeff Bonwick };
2913fa9e4066Sahrens 
291488b7b0f2SMatthew Ahrens #define	ZB_TOTAL	DN_MAX_LEVELS
2915fa9e4066Sahrens 
2916fa9e4066Sahrens typedef struct zdb_cb {
2917b24ab676SJeff Bonwick 	zdb_blkstats_t	zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1];
29185cabbc6bSPrashanth Sreenivasa 	uint64_t	zcb_removing_size;
291986714001SSerapheim Dimitropoulos 	uint64_t	zcb_checkpoint_size;
2920b24ab676SJeff Bonwick 	uint64_t	zcb_dedup_asize;
2921b24ab676SJeff Bonwick 	uint64_t	zcb_dedup_blocks;
29225d7b4d43SMatthew Ahrens 	uint64_t	zcb_embedded_blocks[NUM_BP_EMBEDDED_TYPES];
29235d7b4d43SMatthew Ahrens 	uint64_t	zcb_embedded_histogram[NUM_BP_EMBEDDED_TYPES]
29245d7b4d43SMatthew Ahrens 	    [BPE_PAYLOAD_SIZE];
2925490d05b9SMatthew Ahrens 	uint64_t	zcb_start;
29263f7978d0SAlan Somers 	hrtime_t	zcb_lastprint;
2927490d05b9SMatthew Ahrens 	uint64_t	zcb_totalasize;
2928fa9e4066Sahrens 	uint64_t	zcb_errors[256];
2929fa9e4066Sahrens 	int		zcb_readfails;
2930fa9e4066Sahrens 	int		zcb_haderrors;
2931cde58dbcSMatthew Ahrens 	spa_t		*zcb_spa;
29325cabbc6bSPrashanth Sreenivasa 	uint32_t	**zcb_vd_obsolete_counts;
2933fa9e4066Sahrens } zdb_cb_t;
2934fa9e4066Sahrens 
2935663207adSDon Brady /* test if two DVA offsets from same vdev are within the same metaslab */
2936663207adSDon Brady static boolean_t
2937663207adSDon Brady same_metaslab(spa_t *spa, uint64_t vdev, uint64_t off1, uint64_t off2)
2938663207adSDon Brady {
2939663207adSDon Brady 	vdev_t *vd = vdev_lookup_top(spa, vdev);
2940663207adSDon Brady 	uint64_t ms_shift = vd->vdev_ms_shift;
2941663207adSDon Brady 
2942663207adSDon Brady 	return ((off1 >> ms_shift) == (off2 >> ms_shift));
2943663207adSDon Brady }
2944663207adSDon Brady 
2945fa9e4066Sahrens static void
2946cde58dbcSMatthew Ahrens zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
2947b24ab676SJeff Bonwick     dmu_object_type_t type)
2948fa9e4066Sahrens {
2949b24ab676SJeff Bonwick 	uint64_t refcnt = 0;
2950b24ab676SJeff Bonwick 
2951b24ab676SJeff Bonwick 	ASSERT(type < ZDB_OT_TOTAL);
2952b24ab676SJeff Bonwick 
2953b24ab676SJeff Bonwick 	if (zilog && zil_bp_tree_add(zilog, bp) != 0)
2954b24ab676SJeff Bonwick 		return;
2955b24ab676SJeff Bonwick 
2956663207adSDon Brady 	spa_config_enter(zcb->zcb_spa, SCL_CONFIG, FTAG, RW_READER);
2957663207adSDon Brady 
2958e14bb325SJeff Bonwick 	for (int i = 0; i < 4; i++) {
2959fa9e4066Sahrens 		int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL;
2960b24ab676SJeff Bonwick 		int t = (i & 1) ? type : ZDB_OT_TOTAL;
2961d5ee8a13SMatthew Ahrens 		int equal;
2962fa9e4066Sahrens 		zdb_blkstats_t *zb = &zcb->zcb_type[l][t];
2963fa9e4066Sahrens 
2964fa9e4066Sahrens 		zb->zb_asize += BP_GET_ASIZE(bp);
2965fa9e4066Sahrens 		zb->zb_lsize += BP_GET_LSIZE(bp);
2966fa9e4066Sahrens 		zb->zb_psize += BP_GET_PSIZE(bp);
2967fa9e4066Sahrens 		zb->zb_count++;
2968b5152584SMatthew Ahrens 
2969b5152584SMatthew Ahrens 		/*
2970b5152584SMatthew Ahrens 		 * The histogram is only big enough to record blocks up to
2971b5152584SMatthew Ahrens 		 * SPA_OLD_MAXBLOCKSIZE; larger blocks go into the last,
2972b5152584SMatthew Ahrens 		 * "other", bucket.
2973b5152584SMatthew Ahrens 		 */
29743f7978d0SAlan Somers 		unsigned idx = BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT;
2975b5152584SMatthew Ahrens 		idx = MIN(idx, SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 1);
2976b5152584SMatthew Ahrens 		zb->zb_psize_histogram[idx]++;
2977d5ee8a13SMatthew Ahrens 
2978d5ee8a13SMatthew Ahrens 		zb->zb_gangs += BP_COUNT_GANG(bp);
2979d5ee8a13SMatthew Ahrens 
2980d5ee8a13SMatthew Ahrens 		switch (BP_GET_NDVAS(bp)) {
2981d5ee8a13SMatthew Ahrens 		case 2:
2982d5ee8a13SMatthew Ahrens 			if (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2983663207adSDon Brady 			    DVA_GET_VDEV(&bp->blk_dva[1])) {
2984d5ee8a13SMatthew Ahrens 				zb->zb_ditto_samevdev++;
2985663207adSDon Brady 
2986663207adSDon Brady 				if (same_metaslab(zcb->zcb_spa,
2987663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[0]),
2988663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[0]),
2989663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[1])))
2990663207adSDon Brady 					zb->zb_ditto_same_ms++;
2991663207adSDon Brady 			}
2992d5ee8a13SMatthew Ahrens 			break;
2993d5ee8a13SMatthew Ahrens 		case 3:
2994d5ee8a13SMatthew Ahrens 			equal = (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2995d5ee8a13SMatthew Ahrens 			    DVA_GET_VDEV(&bp->blk_dva[1])) +
2996d5ee8a13SMatthew Ahrens 			    (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2997d5ee8a13SMatthew Ahrens 			    DVA_GET_VDEV(&bp->blk_dva[2])) +
2998d5ee8a13SMatthew Ahrens 			    (DVA_GET_VDEV(&bp->blk_dva[1]) ==
2999d5ee8a13SMatthew Ahrens 			    DVA_GET_VDEV(&bp->blk_dva[2]));
3000663207adSDon Brady 			if (equal != 0) {
3001d5ee8a13SMatthew Ahrens 				zb->zb_ditto_samevdev++;
3002663207adSDon Brady 
3003663207adSDon Brady 				if (DVA_GET_VDEV(&bp->blk_dva[0]) ==
3004663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[1]) &&
3005663207adSDon Brady 				    same_metaslab(zcb->zcb_spa,
3006663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[0]),
3007663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[0]),
3008663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[1])))
3009663207adSDon Brady 					zb->zb_ditto_same_ms++;
3010663207adSDon Brady 				else if (DVA_GET_VDEV(&bp->blk_dva[0]) ==
3011663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[2]) &&
3012663207adSDon Brady 				    same_metaslab(zcb->zcb_spa,
3013663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[0]),
3014663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[0]),
3015663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[2])))
3016663207adSDon Brady 					zb->zb_ditto_same_ms++;
3017663207adSDon Brady 				else if (DVA_GET_VDEV(&bp->blk_dva[1]) ==
3018663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[2]) &&
3019663207adSDon Brady 				    same_metaslab(zcb->zcb_spa,
3020663207adSDon Brady 				    DVA_GET_VDEV(&bp->blk_dva[1]),
3021663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[1]),
3022663207adSDon Brady 				    DVA_GET_OFFSET(&bp->blk_dva[2])))
3023663207adSDon Brady 					zb->zb_ditto_same_ms++;
3024663207adSDon Brady 			}
3025d5ee8a13SMatthew Ahrens 			break;
3026d5ee8a13SMatthew Ahrens 		}
3027fa9e4066Sahrens 	}
3028fa9e4066Sahrens 
3029663207adSDon Brady 	spa_config_exit(zcb->zcb_spa, SCL_CONFIG, FTAG);
3030663207adSDon Brady 
30315d7b4d43SMatthew Ahrens 	if (BP_IS_EMBEDDED(bp)) {
30325d7b4d43SMatthew Ahrens 		zcb->zcb_embedded_blocks[BPE_GET_ETYPE(bp)]++;
30335d7b4d43SMatthew Ahrens 		zcb->zcb_embedded_histogram[BPE_GET_ETYPE(bp)]
30345d7b4d43SMatthew Ahrens 		    [BPE_GET_PSIZE(bp)]++;
30355d7b4d43SMatthew Ahrens 		return;
30365d7b4d43SMatthew Ahrens 	}
30375d7b4d43SMatthew Ahrens 
3038b24ab676SJeff Bonwick 	if (dump_opt['L'])
3039b24ab676SJeff Bonwick 		return;
3040b24ab676SJeff Bonwick 
3041b24ab676SJeff Bonwick 	if (BP_GET_DEDUP(bp)) {
3042b24ab676SJeff Bonwick 		ddt_t *ddt;
3043b24ab676SJeff Bonwick 		ddt_entry_t *dde;
3044b24ab676SJeff Bonwick 
3045cde58dbcSMatthew Ahrens 		ddt = ddt_select(zcb->zcb_spa, bp);
3046b24ab676SJeff Bonwick 		ddt_enter(ddt);
3047b24ab676SJeff Bonwick 		dde = ddt_lookup(ddt, bp, B_FALSE);
3048b24ab676SJeff Bonwick 
3049b24ab676SJeff Bonwick 		if (dde == NULL) {
3050b24ab676SJeff Bonwick 			refcnt = 0;
3051b24ab676SJeff Bonwick 		} else {
3052b24ab676SJeff Bonwick 			ddt_phys_t *ddp = ddt_phys_select(dde, bp);
3053b24ab676SJeff Bonwick 			ddt_phys_decref(ddp);
3054b24ab676SJeff Bonwick 			refcnt = ddp->ddp_refcnt;
3055b24ab676SJeff Bonwick 			if (ddt_phys_total_refcnt(dde) == 0)
3056b24ab676SJeff Bonwick 				ddt_remove(ddt, dde);
3057d41e7643Sek 		}
3058b24ab676SJeff Bonwick 		ddt_exit(ddt);
3059d41e7643Sek 	}
3060d41e7643Sek 
3061cde58dbcSMatthew Ahrens 	VERIFY3U(zio_wait(zio_claim(NULL, zcb->zcb_spa,
306286714001SSerapheim Dimitropoulos 	    refcnt ? 0 : spa_min_claim_txg(zcb->zcb_spa),
3063b24ab676SJeff Bonwick 	    bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
3064fa9e4066Sahrens }
3065fa9e4066Sahrens 
306631d7e8faSGeorge Wilson static void
306731d7e8faSGeorge Wilson zdb_blkptr_done(zio_t *zio)
306831d7e8faSGeorge Wilson {
306931d7e8faSGeorge Wilson 	spa_t *spa = zio->io_spa;
307031d7e8faSGeorge Wilson 	blkptr_t *bp = zio->io_bp;
307131d7e8faSGeorge Wilson 	int ioerr = zio->io_error;
307231d7e8faSGeorge Wilson 	zdb_cb_t *zcb = zio->io_private;
30737802d7bfSMatthew Ahrens 	zbookmark_phys_t *zb = &zio->io_bookmark;
307431d7e8faSGeorge Wilson 
3075770499e1SDan Kimmel 	abd_free(zio->io_abd);
307631d7e8faSGeorge Wilson 
307731d7e8faSGeorge Wilson 	mutex_enter(&spa->spa_scrub_lock);
3078a3874b8bSToomas Soome 	spa->spa_load_verify_ios--;
307931d7e8faSGeorge Wilson 	cv_broadcast(&spa->spa_scrub_io_cv);
308031d7e8faSGeorge Wilson 
308131d7e8faSGeorge Wilson 	if (ioerr && !(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
308231d7e8faSGeorge Wilson 		char blkbuf[BP_SPRINTF_LEN];
308331d7e8faSGeorge Wilson 
308431d7e8faSGeorge Wilson 		zcb->zcb_haderrors = 1;
308531d7e8faSGeorge Wilson 		zcb->zcb_errors[ioerr]++;
308631d7e8faSGeorge Wilson 
308731d7e8faSGeorge Wilson 		if (dump_opt['b'] >= 2)
308843466aaeSMax Grossman 			snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
308931d7e8faSGeorge Wilson 		else
309031d7e8faSGeorge Wilson 			blkbuf[0] = '\0';
309131d7e8faSGeorge Wilson 
309231d7e8faSGeorge Wilson 		(void) printf("zdb_blkptr_cb: "
309331d7e8faSGeorge Wilson 		    "Got error %d reading "
309431d7e8faSGeorge Wilson 		    "<%llu, %llu, %lld, %llx> %s -- skipping\n",
309531d7e8faSGeorge Wilson 		    ioerr,
309631d7e8faSGeorge Wilson 		    (u_longlong_t)zb->zb_objset,
309731d7e8faSGeorge Wilson 		    (u_longlong_t)zb->zb_object,
309831d7e8faSGeorge Wilson 		    (u_longlong_t)zb->zb_level,
309931d7e8faSGeorge Wilson 		    (u_longlong_t)zb->zb_blkid,
310031d7e8faSGeorge Wilson 		    blkbuf);
310131d7e8faSGeorge Wilson 	}
310231d7e8faSGeorge Wilson 	mutex_exit(&spa->spa_scrub_lock);
310331d7e8faSGeorge Wilson }
310431d7e8faSGeorge Wilson 
3105fa9e4066Sahrens static int
31061b912ec7SGeorge Wilson zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
31077802d7bfSMatthew Ahrens     const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
3108fa9e4066Sahrens {
3109fa9e4066Sahrens 	zdb_cb_t *zcb = arg;
31106365109dSVictor Latushkin 	dmu_object_type_t type;
3111468c413aSTim Haley 	boolean_t is_metadata;
3112fa9e4066Sahrens 
3113a2cdcdd2SPaul Dagnelie 	if (bp == NULL)
3114a2cdcdd2SPaul Dagnelie 		return (0);
3115a2cdcdd2SPaul Dagnelie 
311643466aaeSMax Grossman 	if (dump_opt['b'] >= 5 && bp->blk_birth > 0) {
311743466aaeSMax Grossman 		char blkbuf[BP_SPRINTF_LEN];
311843466aaeSMax Grossman 		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
311943466aaeSMax Grossman 		(void) printf("objset %llu object %llu "
312043466aaeSMax Grossman 		    "level %lld offset 0x%llx %s\n",
312143466aaeSMax Grossman 		    (u_longlong_t)zb->zb_objset,
312243466aaeSMax Grossman 		    (u_longlong_t)zb->zb_object,
312343466aaeSMax Grossman 		    (longlong_t)zb->zb_level,
312443466aaeSMax Grossman 		    (u_longlong_t)blkid2offset(dnp, bp, zb),
312543466aaeSMax Grossman 		    blkbuf);
312643466aaeSMax Grossman 	}
312743466aaeSMax Grossman 
312843466aaeSMax Grossman 	if (BP_IS_HOLE(bp))
312988b7b0f2SMatthew Ahrens 		return (0);
3130e14bb325SJeff Bonwick 
31316365109dSVictor Latushkin 	type = BP_GET_TYPE(bp);
3132e14bb325SJeff Bonwick 
3133ad135b5dSChristopher Siden 	zdb_count_block(zcb, zilog, bp,
3134ad135b5dSChristopher Siden 	    (type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
31356365109dSVictor Latushkin 
3136ad135b5dSChristopher Siden 	is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
31376365109dSVictor Latushkin 
31385d7b4d43SMatthew Ahrens 	if (!BP_IS_EMBEDDED(bp) &&
31395d7b4d43SMatthew Ahrens 	    (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata))) {
3140468c413aSTim Haley 		size_t size = BP_GET_PSIZE(bp);
3141770499e1SDan Kimmel 		abd_t *abd = abd_alloc(size, B_FALSE);
3142b24ab676SJeff Bonwick 		int flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB | ZIO_FLAG_RAW;
3143b24ab676SJeff Bonwick 
3144b24ab676SJeff Bonwick 		/* If it's an intent log block, failure is expected. */
3145b24ab676SJeff Bonwick 		if (zb->zb_level == ZB_ZIL_LEVEL)
3146b24ab676SJeff Bonwick 			flags |= ZIO_FLAG_SPECULATIVE;
3147b24ab676SJeff Bonwick 
314831d7e8faSGeorge Wilson 		mutex_enter(&spa->spa_scrub_lock);
3149a3874b8bSToomas Soome 		while (spa->spa_load_verify_ios > max_inflight)
315031d7e8faSGeorge Wilson 			cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
3151a3874b8bSToomas Soome 		spa->spa_load_verify_ios++;
315231d7e8faSGeorge Wilson 		mutex_exit(&spa->spa_scrub_lock);
3153b24ab676SJeff Bonwick 
3154770499e1SDan Kimmel 		zio_nowait(zio_read(NULL, spa, bp, abd, size,
315531d7e8faSGeorge Wilson 		    zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb));
3156fa9e4066Sahrens 	}
3157fa9e4066Sahrens 
3158fa9e4066Sahrens 	zcb->zcb_readfails = 0;
3159fa9e4066Sahrens 
3160f7950bf1SMatthew Ahrens 	/* only call gethrtime() every 100 blocks */
3161f7950bf1SMatthew Ahrens 	static int iters;
3162f7950bf1SMatthew Ahrens 	if (++iters > 100)
3163f7950bf1SMatthew Ahrens 		iters = 0;
3164f7950bf1SMatthew Ahrens 	else
3165f7950bf1SMatthew Ahrens 		return (0);
3166f7950bf1SMatthew Ahrens 
3167f7950bf1SMatthew Ahrens 	if (dump_opt['b'] < 5 && gethrtime() > zcb->zcb_lastprint + NANOSEC) {
3168490d05b9SMatthew Ahrens 		uint64_t now = gethrtime();
3169490d05b9SMatthew Ahrens 		char buf[10];
3170490d05b9SMatthew Ahrens 		uint64_t bytes = zcb->zcb_type[ZB_TOTAL][ZDB_OT_TOTAL].zb_asize;
3171490d05b9SMatthew Ahrens 		int kb_per_sec =
3172490d05b9SMatthew Ahrens 		    1 + bytes / (1 + ((now - zcb->zcb_start) / 1000 / 1000));
3173490d05b9SMatthew Ahrens 		int sec_remaining =
3174490d05b9SMatthew Ahrens 		    (zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
3175490d05b9SMatthew Ahrens 
31760a055120SJason King 		/* make sure nicenum has enough space */
31770a055120SJason King 		CTASSERT(sizeof (buf) >= NN_NUMBUF_SZ);
31780a055120SJason King 
3179490d05b9SMatthew Ahrens 		zfs_nicenum(bytes, buf, sizeof (buf));
3180490d05b9SMatthew Ahrens 		(void) fprintf(stderr,
3181490d05b9SMatthew Ahrens 		    "\r%5s completed (%4dMB/s) "
3182490d05b9SMatthew Ahrens 		    "estimated time remaining: %uhr %02umin %02usec        ",
3183490d05b9SMatthew Ahrens 		    buf, kb_per_sec / 1024,
3184490d05b9SMatthew Ahrens 		    sec_remaining / 60 / 60,
3185490d05b9SMatthew Ahrens 		    sec_remaining / 60 % 60,
3186490d05b9SMatthew Ahrens 		    sec_remaining % 60);
3187490d05b9SMatthew Ahrens 
3188490d05b9SMatthew Ahrens 		zcb->zcb_lastprint = now;
3189490d05b9SMatthew Ahrens 	}
3190490d05b9SMatthew Ahrens 
3191fa9e4066Sahrens 	return (0);
3192fa9e4066Sahrens }
3193fa9e4066Sahrens 
3194b24ab676SJeff Bonwick static void
31950713e232SGeorge Wilson zdb_leak(void *arg, uint64_t start, uint64_t size)
3196b24ab676SJeff Bonwick {
31970713e232SGeorge Wilson 	vdev_t *vd = arg;
3198b24ab676SJeff Bonwick 
3199b24ab676SJeff Bonwick 	(void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n",
3200b24ab676SJeff Bonwick 	    (u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size);
3201b24ab676SJeff Bonwick }
3202b24ab676SJeff Bonwick 
32030713e232SGeorge Wilson static metaslab_ops_t zdb_metaslab_ops = {
32042e4c9986SGeorge Wilson 	NULL	/* alloc */
3205b24ab676SJeff Bonwick };
3206b24ab676SJeff Bonwick 
3207*814dcd43SSerapheim Dimitropoulos typedef int (*zdb_log_sm_cb_t)(spa_t *spa, space_map_entry_t *sme,
3208*814dcd43SSerapheim Dimitropoulos     uint64_t txg, void *arg);
3209*814dcd43SSerapheim Dimitropoulos 
3210*814dcd43SSerapheim Dimitropoulos typedef struct unflushed_iter_cb_arg {
3211*814dcd43SSerapheim Dimitropoulos 	spa_t *uic_spa;
3212*814dcd43SSerapheim Dimitropoulos 	uint64_t uic_txg;
3213*814dcd43SSerapheim Dimitropoulos 	void *uic_arg;
3214*814dcd43SSerapheim Dimitropoulos 	zdb_log_sm_cb_t uic_cb;
3215*814dcd43SSerapheim Dimitropoulos } unflushed_iter_cb_arg_t;
3216*814dcd43SSerapheim Dimitropoulos 
3217*814dcd43SSerapheim Dimitropoulos static int
3218*814dcd43SSerapheim Dimitropoulos iterate_through_spacemap_logs_cb(space_map_entry_t *sme, void *arg)
3219*814dcd43SSerapheim Dimitropoulos {
3220*814dcd43SSerapheim Dimitropoulos 	unflushed_iter_cb_arg_t *uic = arg;
3221*814dcd43SSerapheim Dimitropoulos 
3222*814dcd43SSerapheim Dimitropoulos 	return (uic->uic_cb(uic->uic_spa, sme, uic->uic_txg, uic->uic_arg));
3223*814dcd43SSerapheim Dimitropoulos }
3224*814dcd43SSerapheim Dimitropoulos 
3225*814dcd43SSerapheim Dimitropoulos static void
3226*814dcd43SSerapheim Dimitropoulos iterate_through_spacemap_logs(spa_t *spa, zdb_log_sm_cb_t cb, void *arg)
3227*814dcd43SSerapheim Dimitropoulos {
3228*814dcd43SSerapheim Dimitropoulos 	if (!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))
3229*814dcd43SSerapheim Dimitropoulos 		return;
3230*814dcd43SSerapheim Dimitropoulos 
3231*814dcd43SSerapheim Dimitropoulos 	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
3232*814dcd43SSerapheim Dimitropoulos 	for (spa_log_sm_t *sls = avl_first(&spa->spa_sm_logs_by_txg);
3233*814dcd43SSerapheim Dimitropoulos 	    sls; sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls)) {
3234*814dcd43SSerapheim Dimitropoulos 		space_map_t *sm = NULL;
3235*814dcd43SSerapheim Dimitropoulos 		VERIFY0(space_map_open(&sm, spa_meta_objset(spa),
3236*814dcd43SSerapheim Dimitropoulos 		    sls->sls_sm_obj, 0, UINT64_MAX, SPA_MINBLOCKSHIFT));
3237*814dcd43SSerapheim Dimitropoulos 
3238*814dcd43SSerapheim Dimitropoulos 		unflushed_iter_cb_arg_t uic = {
3239*814dcd43SSerapheim Dimitropoulos 			.uic_spa = spa,
3240*814dcd43SSerapheim Dimitropoulos 			.uic_txg = sls->sls_txg,
3241*814dcd43SSerapheim Dimitropoulos 			.uic_arg = arg,
3242*814dcd43SSerapheim Dimitropoulos 			.uic_cb = cb
3243*814dcd43SSerapheim Dimitropoulos 		};
3244*814dcd43SSerapheim Dimitropoulos 
3245*814dcd43SSerapheim Dimitropoulos 		VERIFY0(space_map_iterate(sm, space_map_length(sm),
3246*814dcd43SSerapheim Dimitropoulos 		    iterate_through_spacemap_logs_cb, &uic));
3247*814dcd43SSerapheim Dimitropoulos 		space_map_close(sm);
3248*814dcd43SSerapheim Dimitropoulos 	}
3249*814dcd43SSerapheim Dimitropoulos 	spa_config_exit(spa, SCL_CONFIG, FTAG);
3250*814dcd43SSerapheim Dimitropoulos }
3251*814dcd43SSerapheim Dimitropoulos 
3252*814dcd43SSerapheim Dimitropoulos /* ARGSUSED */
3253*814dcd43SSerapheim Dimitropoulos static int
3254*814dcd43SSerapheim Dimitropoulos load_unflushed_svr_segs_cb(spa_t *spa, space_map_entry_t *sme,
3255*814dcd43SSerapheim Dimitropoulos     uint64_t txg, void *arg)
3256*814dcd43SSerapheim Dimitropoulos {
3257*814dcd43SSerapheim Dimitropoulos 	spa_vdev_removal_t *svr = arg;
3258*814dcd43SSerapheim Dimitropoulos 
3259*814dcd43SSerapheim Dimitropoulos 	uint64_t offset = sme->sme_offset;
3260*814dcd43SSerapheim Dimitropoulos 	uint64_t size = sme->sme_run;
3261*814dcd43SSerapheim Dimitropoulos 
3262*814dcd43SSerapheim Dimitropoulos 	/* skip vdevs we don't care about */
3263*814dcd43SSerapheim Dimitropoulos 	if (sme->sme_vdev != svr->svr_vdev_id)
3264*814dcd43SSerapheim Dimitropoulos 		return (0);
3265*814dcd43SSerapheim Dimitropoulos 
3266*814dcd43SSerapheim Dimitropoulos 	vdev_t *vd = vdev_lookup_top(spa, sme->sme_vdev);
3267*814dcd43SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
3268*814dcd43SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_ALLOC || sme->sme_type == SM_FREE);
3269*814dcd43SSerapheim Dimitropoulos 
3270*814dcd43SSerapheim Dimitropoulos 	if (txg < metaslab_unflushed_txg(ms))
3271*814dcd43SSerapheim Dimitropoulos 		return (0);
3272*814dcd43SSerapheim Dimitropoulos 
3273*814dcd43SSerapheim Dimitropoulos 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
3274*814dcd43SSerapheim Dimitropoulos 	ASSERT(vim != NULL);
3275*814dcd43SSerapheim Dimitropoulos 	if (offset >= vdev_indirect_mapping_max_offset(vim))
3276*814dcd43SSerapheim Dimitropoulos 		return (0);
3277*814dcd43SSerapheim Dimitropoulos 
3278*814dcd43SSerapheim Dimitropoulos 	if (sme->sme_type == SM_ALLOC)
3279*814dcd43SSerapheim Dimitropoulos 		range_tree_add(svr->svr_allocd_segs, offset, size);
3280*814dcd43SSerapheim Dimitropoulos 	else
3281*814dcd43SSerapheim Dimitropoulos 		range_tree_remove(svr->svr_allocd_segs, offset, size);
3282*814dcd43SSerapheim Dimitropoulos 
3283*814dcd43SSerapheim Dimitropoulos 	return (0);
3284*814dcd43SSerapheim Dimitropoulos }
3285*814dcd43SSerapheim Dimitropoulos 
3286b24ab676SJeff Bonwick static void
3287bbfd46c4SJeff Bonwick zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb)
3288b24ab676SJeff Bonwick {
32893f7978d0SAlan Somers 	ddt_bookmark_t ddb;
3290b24ab676SJeff Bonwick 	ddt_entry_t dde;
3291b24ab676SJeff Bonwick 	int error;
3292b24ab676SJeff Bonwick 
3293555d674dSSerapheim Dimitropoulos 	ASSERT(!dump_opt['L']);
3294555d674dSSerapheim Dimitropoulos 
32953f7978d0SAlan Somers 	bzero(&ddb, sizeof (ddb));
3296bbfd46c4SJeff Bonwick 	while ((error = ddt_walk(spa, &ddb, &dde)) == 0) {
3297b24ab676SJeff Bonwick 		blkptr_t blk;
3298b24ab676SJeff Bonwick 		ddt_phys_t *ddp = dde.dde_phys;
3299bbfd46c4SJeff Bonwick 
3300bbfd46c4SJeff Bonwick 		if (ddb.ddb_class == DDT_CLASS_UNIQUE)
3301bbfd46c4SJeff Bonwick 			return;
3302bbfd46c4SJeff Bonwick 
3303b24ab676SJeff Bonwick 		ASSERT(ddt_phys_total_refcnt(&dde) > 1);
3304bbfd46c4SJeff Bonwick 
3305b24ab676SJeff Bonwick 		for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
3306b24ab676SJeff Bonwick 			if (ddp->ddp_phys_birth == 0)
3307b24ab676SJeff Bonwick 				continue;
3308bbfd46c4SJeff Bonwick 			ddt_bp_create(ddb.ddb_checksum,
3309bbfd46c4SJeff Bonwick 			    &dde.dde_key, ddp, &blk);
3310b24ab676SJeff Bonwick 			if (p == DDT_PHYS_DITTO) {
3311cde58dbcSMatthew Ahrens 				zdb_count_block(zcb, NULL, &blk, ZDB_OT_DITTO);
3312b24ab676SJeff Bonwick 			} else {
3313b24ab676SJeff Bonwick 				zcb->zcb_dedup_asize +=
3314b24ab676SJeff Bonwick 				    BP_GET_ASIZE(&blk) * (ddp->ddp_refcnt - 1);
3315b24ab676SJeff Bonwick 				zcb->zcb_dedup_blocks++;
3316b24ab676SJeff Bonwick 			}
3317b24ab676SJeff Bonwick 		}
3318555d674dSSerapheim Dimitropoulos 		ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum];
3319555d674dSSerapheim Dimitropoulos 		ddt_enter(ddt);
3320555d674dSSerapheim Dimitropoulos 		VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL);
3321555d674dSSerapheim Dimitropoulos 		ddt_exit(ddt);
3322b24ab676SJeff Bonwick 	}
3323b24ab676SJeff Bonwick 
3324b24ab676SJeff Bonwick 	ASSERT(error == ENOENT);
3325b24ab676SJeff Bonwick }
3326b24ab676SJeff Bonwick 
33275cabbc6bSPrashanth Sreenivasa /* ARGSUSED */
33285cabbc6bSPrashanth Sreenivasa static void
33295cabbc6bSPrashanth Sreenivasa claim_segment_impl_cb(uint64_t inner_offset, vdev_t *vd, uint64_t offset,
33305cabbc6bSPrashanth Sreenivasa     uint64_t size, void *arg)
33315cabbc6bSPrashanth Sreenivasa {
33325cabbc6bSPrashanth Sreenivasa 	/*
33335cabbc6bSPrashanth Sreenivasa 	 * This callback was called through a remap from
33345cabbc6bSPrashanth Sreenivasa 	 * a device being removed. Therefore, the vdev that
33355cabbc6bSPrashanth Sreenivasa 	 * this callback is applied to is a concrete
33365cabbc6bSPrashanth Sreenivasa 	 * vdev.
33375cabbc6bSPrashanth Sreenivasa 	 */
33385cabbc6bSPrashanth Sreenivasa 	ASSERT(vdev_is_concrete(vd));
33395cabbc6bSPrashanth Sreenivasa 
33405cabbc6bSPrashanth Sreenivasa 	VERIFY0(metaslab_claim_impl(vd, offset, size,
334186714001SSerapheim Dimitropoulos 	    spa_min_claim_txg(vd->vdev_spa)));
33425cabbc6bSPrashanth Sreenivasa }
33435cabbc6bSPrashanth Sreenivasa 
33445cabbc6bSPrashanth Sreenivasa static void
33455cabbc6bSPrashanth Sreenivasa claim_segment_cb(void *arg, uint64_t offset, uint64_t size)
33465cabbc6bSPrashanth Sreenivasa {
33475cabbc6bSPrashanth Sreenivasa 	vdev_t *vd = arg;
33485cabbc6bSPrashanth Sreenivasa 
33495cabbc6bSPrashanth Sreenivasa 	vdev_indirect_ops.vdev_op_remap(vd, offset, size,
33505cabbc6bSPrashanth Sreenivasa 	    claim_segment_impl_cb, NULL);
33515cabbc6bSPrashanth Sreenivasa }
33525cabbc6bSPrashanth Sreenivasa 
33535cabbc6bSPrashanth Sreenivasa /*
33545cabbc6bSPrashanth Sreenivasa  * After accounting for all allocated blocks that are directly referenced,
33555cabbc6bSPrashanth Sreenivasa  * we might have missed a reference to a block from a partially complete
33565cabbc6bSPrashanth Sreenivasa  * (and thus unused) indirect mapping object. We perform a secondary pass
33575cabbc6bSPrashanth Sreenivasa  * through the metaslabs we have already mapped and claim the destination
33585cabbc6bSPrashanth Sreenivasa  * blocks.
33595cabbc6bSPrashanth Sreenivasa  */
33605cabbc6bSPrashanth Sreenivasa static void
33615cabbc6bSPrashanth Sreenivasa zdb_claim_removing(spa_t *spa, zdb_cb_t *zcb)
33625cabbc6bSPrashanth Sreenivasa {
3363555d674dSSerapheim Dimitropoulos 	if (dump_opt['L'])
3364555d674dSSerapheim Dimitropoulos 		return;
3365555d674dSSerapheim Dimitropoulos 
33665cabbc6bSPrashanth Sreenivasa 	if (spa->spa_vdev_removal == NULL)
33675cabbc6bSPrashanth Sreenivasa 		return;
33685cabbc6bSPrashanth Sreenivasa 
33695cabbc6bSPrashanth Sreenivasa 	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
33705cabbc6bSPrashanth Sreenivasa 
33715cabbc6bSPrashanth Sreenivasa 	spa_vdev_removal_t *svr = spa->spa_vdev_removal;
33723a4b1be9SMatthew Ahrens 	vdev_t *vd = vdev_lookup_top(spa, svr->svr_vdev_id);
33735cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
33745cabbc6bSPrashanth Sreenivasa 
3375*814dcd43SSerapheim Dimitropoulos 	ASSERT0(range_tree_space(svr->svr_allocd_segs));
3376*814dcd43SSerapheim Dimitropoulos 
3377*814dcd43SSerapheim Dimitropoulos 	range_tree_t *allocs = range_tree_create(NULL, NULL);
33785cabbc6bSPrashanth Sreenivasa 	for (uint64_t msi = 0; msi < vd->vdev_ms_count; msi++) {
33795cabbc6bSPrashanth Sreenivasa 		metaslab_t *msp = vd->vdev_ms[msi];
33805cabbc6bSPrashanth Sreenivasa 
33815cabbc6bSPrashanth Sreenivasa 		if (msp->ms_start >= vdev_indirect_mapping_max_offset(vim))
33825cabbc6bSPrashanth Sreenivasa 			break;
33835cabbc6bSPrashanth Sreenivasa 
3384*814dcd43SSerapheim Dimitropoulos 		ASSERT0(range_tree_space(allocs));
3385*814dcd43SSerapheim Dimitropoulos 		if (msp->ms_sm != NULL)
3386*814dcd43SSerapheim Dimitropoulos 			VERIFY0(space_map_load(msp->ms_sm, allocs, SM_ALLOC));
3387*814dcd43SSerapheim Dimitropoulos 		range_tree_vacate(allocs, range_tree_add, svr->svr_allocd_segs);
3388*814dcd43SSerapheim Dimitropoulos 	}
3389*814dcd43SSerapheim Dimitropoulos 	range_tree_destroy(allocs);
33905cabbc6bSPrashanth Sreenivasa 
3391*814dcd43SSerapheim Dimitropoulos 	iterate_through_spacemap_logs(spa, load_unflushed_svr_segs_cb, svr);
33925cabbc6bSPrashanth Sreenivasa 
3393*814dcd43SSerapheim Dimitropoulos 	/*
3394*814dcd43SSerapheim Dimitropoulos 	 * Clear everything past what has been synced,
3395*814dcd43SSerapheim Dimitropoulos 	 * because we have not allocated mappings for
3396*814dcd43SSerapheim Dimitropoulos 	 * it yet.
3397*814dcd43SSerapheim Dimitropoulos 	 */
3398*814dcd43SSerapheim Dimitropoulos 	range_tree_clear(svr->svr_allocd_segs,
3399*814dcd43SSerapheim Dimitropoulos 	    vdev_indirect_mapping_max_offset(vim),
3400*814dcd43SSerapheim Dimitropoulos 	    vd->vdev_asize - vdev_indirect_mapping_max_offset(vim));
34015cabbc6bSPrashanth Sreenivasa 
3402*814dcd43SSerapheim Dimitropoulos 	zcb->zcb_removing_size += range_tree_space(svr->svr_allocd_segs);
3403*814dcd43SSerapheim Dimitropoulos 	range_tree_vacate(svr->svr_allocd_segs, claim_segment_cb, vd);
34045cabbc6bSPrashanth Sreenivasa 
34055cabbc6bSPrashanth Sreenivasa 	spa_config_exit(spa, SCL_CONFIG, FTAG);
34065cabbc6bSPrashanth Sreenivasa }
34075cabbc6bSPrashanth Sreenivasa 
34085cabbc6bSPrashanth Sreenivasa /* ARGSUSED */
34095cabbc6bSPrashanth Sreenivasa static int
34105cabbc6bSPrashanth Sreenivasa increment_indirect_mapping_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
34115cabbc6bSPrashanth Sreenivasa {
34125cabbc6bSPrashanth Sreenivasa 	zdb_cb_t *zcb = arg;
34135cabbc6bSPrashanth Sreenivasa 	spa_t *spa = zcb->zcb_spa;
34145cabbc6bSPrashanth Sreenivasa 	vdev_t *vd;
34155cabbc6bSPrashanth Sreenivasa 	const dva_t *dva = &bp->blk_dva[0];
34165cabbc6bSPrashanth Sreenivasa 
34175cabbc6bSPrashanth Sreenivasa 	ASSERT(!dump_opt['L']);
34185cabbc6bSPrashanth Sreenivasa 	ASSERT3U(BP_GET_NDVAS(bp), ==, 1);
34195cabbc6bSPrashanth Sreenivasa 
34205cabbc6bSPrashanth Sreenivasa 	spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
34215cabbc6bSPrashanth Sreenivasa 	vd = vdev_lookup_top(zcb->zcb_spa, DVA_GET_VDEV(dva));
34225cabbc6bSPrashanth Sreenivasa 	ASSERT3P(vd, !=, NULL);
34235cabbc6bSPrashanth Sreenivasa 	spa_config_exit(spa, SCL_VDEV, FTAG);
34245cabbc6bSPrashanth Sreenivasa 
34255cabbc6bSPrashanth Sreenivasa 	ASSERT(vd->vdev_indirect_config.vic_mapping_object != 0);
34265cabbc6bSPrashanth Sreenivasa 	ASSERT3P(zcb->zcb_vd_obsolete_counts[vd->vdev_id], !=, NULL);
34275cabbc6bSPrashanth Sreenivasa 
34285cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_increment_obsolete_count(
34295cabbc6bSPrashanth Sreenivasa 	    vd->vdev_indirect_mapping,
34305cabbc6bSPrashanth Sreenivasa 	    DVA_GET_OFFSET(dva), DVA_GET_ASIZE(dva),
34315cabbc6bSPrashanth Sreenivasa 	    zcb->zcb_vd_obsolete_counts[vd->vdev_id]);
34325cabbc6bSPrashanth Sreenivasa 
34335cabbc6bSPrashanth Sreenivasa 	return (0);
34345cabbc6bSPrashanth Sreenivasa }
34355cabbc6bSPrashanth Sreenivasa 
34365cabbc6bSPrashanth Sreenivasa static uint32_t *
34375cabbc6bSPrashanth Sreenivasa zdb_load_obsolete_counts(vdev_t *vd)
34385cabbc6bSPrashanth Sreenivasa {
34395cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
34405cabbc6bSPrashanth Sreenivasa 	spa_t *spa = vd->vdev_spa;
34415cabbc6bSPrashanth Sreenivasa 	spa_condensing_indirect_phys_t *scip =
34425cabbc6bSPrashanth Sreenivasa 	    &spa->spa_condensing_indirect_phys;
34435cabbc6bSPrashanth Sreenivasa 	uint32_t *counts;
34445cabbc6bSPrashanth Sreenivasa 
34455cabbc6bSPrashanth Sreenivasa 	EQUIV(vdev_obsolete_sm_object(vd) != 0, vd->vdev_obsolete_sm != NULL);
34465cabbc6bSPrashanth Sreenivasa 	counts = vdev_indirect_mapping_load_obsolete_counts(vim);
34475cabbc6bSPrashanth Sreenivasa 	if (vd->vdev_obsolete_sm != NULL) {
34485cabbc6bSPrashanth Sreenivasa 		vdev_indirect_mapping_load_obsolete_spacemap(vim, counts,
34495cabbc6bSPrashanth Sreenivasa 		    vd->vdev_obsolete_sm);
34505cabbc6bSPrashanth Sreenivasa 	}
34515cabbc6bSPrashanth Sreenivasa 	if (scip->scip_vdev == vd->vdev_id &&
34525cabbc6bSPrashanth Sreenivasa 	    scip->scip_prev_obsolete_sm_object != 0) {
34535cabbc6bSPrashanth Sreenivasa 		space_map_t *prev_obsolete_sm = NULL;
34545cabbc6bSPrashanth Sreenivasa 		VERIFY0(space_map_open(&prev_obsolete_sm, spa->spa_meta_objset,
34555cabbc6bSPrashanth Sreenivasa 		    scip->scip_prev_obsolete_sm_object, 0, vd->vdev_asize, 0));
34565cabbc6bSPrashanth Sreenivasa 		vdev_indirect_mapping_load_obsolete_spacemap(vim, counts,
34575cabbc6bSPrashanth Sreenivasa 		    prev_obsolete_sm);
34585cabbc6bSPrashanth Sreenivasa 		space_map_close(prev_obsolete_sm);
34595cabbc6bSPrashanth Sreenivasa 	}
34605cabbc6bSPrashanth Sreenivasa 	return (counts);
34615cabbc6bSPrashanth Sreenivasa }
34625cabbc6bSPrashanth Sreenivasa 
346386714001SSerapheim Dimitropoulos typedef struct checkpoint_sm_exclude_entry_arg {
346486714001SSerapheim Dimitropoulos 	vdev_t *cseea_vd;
346586714001SSerapheim Dimitropoulos 	uint64_t cseea_checkpoint_size;
346686714001SSerapheim Dimitropoulos } checkpoint_sm_exclude_entry_arg_t;
346786714001SSerapheim Dimitropoulos 
346886714001SSerapheim Dimitropoulos static int
346917f11284SSerapheim Dimitropoulos checkpoint_sm_exclude_entry_cb(space_map_entry_t *sme, void *arg)
347086714001SSerapheim Dimitropoulos {
347186714001SSerapheim Dimitropoulos 	checkpoint_sm_exclude_entry_arg_t *cseea = arg;
347286714001SSerapheim Dimitropoulos 	vdev_t *vd = cseea->cseea_vd;
347317f11284SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[sme->sme_offset >> vd->vdev_ms_shift];
347417f11284SSerapheim Dimitropoulos 	uint64_t end = sme->sme_offset + sme->sme_run;
347586714001SSerapheim Dimitropoulos 
347617f11284SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_FREE);
347786714001SSerapheim Dimitropoulos 
347886714001SSerapheim Dimitropoulos 	/*
347986714001SSerapheim Dimitropoulos 	 * Since the vdev_checkpoint_sm exists in the vdev level
348086714001SSerapheim Dimitropoulos 	 * and the ms_sm space maps exist in the metaslab level,
348186714001SSerapheim Dimitropoulos 	 * an entry in the checkpoint space map could theoretically
348286714001SSerapheim Dimitropoulos 	 * cross the boundaries of the metaslab that it belongs.
348386714001SSerapheim Dimitropoulos 	 *
348486714001SSerapheim Dimitropoulos 	 * In reality, because of the way that we populate and
348586714001SSerapheim Dimitropoulos 	 * manipulate the checkpoint's space maps currently,
348686714001SSerapheim Dimitropoulos 	 * there shouldn't be any entries that cross metaslabs.
348786714001SSerapheim Dimitropoulos 	 * Hence the assertion below.
348886714001SSerapheim Dimitropoulos 	 *
348986714001SSerapheim Dimitropoulos 	 * That said, there is no fundamental requirement that
349086714001SSerapheim Dimitropoulos 	 * the checkpoint's space map entries should not cross
349186714001SSerapheim Dimitropoulos 	 * metaslab boundaries. So if needed we could add code
349286714001SSerapheim Dimitropoulos 	 * that handles metaslab-crossing segments in the future.
349386714001SSerapheim Dimitropoulos 	 */
349417f11284SSerapheim Dimitropoulos 	VERIFY3U(sme->sme_offset, >=, ms->ms_start);
349586714001SSerapheim Dimitropoulos 	VERIFY3U(end, <=, ms->ms_start + ms->ms_size);
349686714001SSerapheim Dimitropoulos 
349786714001SSerapheim Dimitropoulos 	/*
349886714001SSerapheim Dimitropoulos 	 * By removing the entry from the allocated segments we
349986714001SSerapheim Dimitropoulos 	 * also verify that the entry is there to begin with.
350086714001SSerapheim Dimitropoulos 	 */
350186714001SSerapheim Dimitropoulos 	mutex_enter(&ms->ms_lock);
350217f11284SSerapheim Dimitropoulos 	range_tree_remove(ms->ms_allocatable, sme->sme_offset, sme->sme_run);
350386714001SSerapheim Dimitropoulos 	mutex_exit(&ms->ms_lock);
350486714001SSerapheim Dimitropoulos 
350517f11284SSerapheim Dimitropoulos 	cseea->cseea_checkpoint_size += sme->sme_run;
350686714001SSerapheim Dimitropoulos 	return (0);
350786714001SSerapheim Dimitropoulos }
350886714001SSerapheim Dimitropoulos 
350986714001SSerapheim Dimitropoulos static void
351086714001SSerapheim Dimitropoulos zdb_leak_init_vdev_exclude_checkpoint(vdev_t *vd, zdb_cb_t *zcb)
351186714001SSerapheim Dimitropoulos {
351286714001SSerapheim Dimitropoulos 	spa_t *spa = vd->vdev_spa;
351386714001SSerapheim Dimitropoulos 	space_map_t *checkpoint_sm = NULL;
351486714001SSerapheim Dimitropoulos 	uint64_t checkpoint_sm_obj;
351586714001SSerapheim Dimitropoulos 
351686714001SSerapheim Dimitropoulos 	/*
351786714001SSerapheim Dimitropoulos 	 * If there is no vdev_top_zap, we are in a pool whose
351886714001SSerapheim Dimitropoulos 	 * version predates the pool checkpoint feature.
351986714001SSerapheim Dimitropoulos 	 */
352086714001SSerapheim Dimitropoulos 	if (vd->vdev_top_zap == 0)
352186714001SSerapheim Dimitropoulos 		return;
352286714001SSerapheim Dimitropoulos 
352386714001SSerapheim Dimitropoulos 	/*
352486714001SSerapheim Dimitropoulos 	 * If there is no reference of the vdev_checkpoint_sm in
352586714001SSerapheim Dimitropoulos 	 * the vdev_top_zap, then one of the following scenarios
352686714001SSerapheim Dimitropoulos 	 * is true:
352786714001SSerapheim Dimitropoulos 	 *
352886714001SSerapheim Dimitropoulos 	 * 1] There is no checkpoint
352986714001SSerapheim Dimitropoulos 	 * 2] There is a checkpoint, but no checkpointed blocks
353086714001SSerapheim Dimitropoulos 	 *    have been freed yet
353186714001SSerapheim Dimitropoulos 	 * 3] The current vdev is indirect
353286714001SSerapheim Dimitropoulos 	 *
353386714001SSerapheim Dimitropoulos 	 * In these cases we return immediately.
353486714001SSerapheim Dimitropoulos 	 */
353586714001SSerapheim Dimitropoulos 	if (zap_contains(spa_meta_objset(spa), vd->vdev_top_zap,
353686714001SSerapheim Dimitropoulos 	    VDEV_TOP_ZAP_POOL_CHECKPOINT_SM) != 0)
353786714001SSerapheim Dimitropoulos 		return;
353886714001SSerapheim Dimitropoulos 
353986714001SSerapheim Dimitropoulos 	VERIFY0(zap_lookup(spa_meta_objset(spa), vd->vdev_top_zap,
354086714001SSerapheim Dimitropoulos 	    VDEV_TOP_ZAP_POOL_CHECKPOINT_SM, sizeof (uint64_t), 1,
354186714001SSerapheim Dimitropoulos 	    &checkpoint_sm_obj));
354286714001SSerapheim Dimitropoulos 
354386714001SSerapheim Dimitropoulos 	checkpoint_sm_exclude_entry_arg_t cseea;
354486714001SSerapheim Dimitropoulos 	cseea.cseea_vd = vd;
354586714001SSerapheim Dimitropoulos 	cseea.cseea_checkpoint_size = 0;
354686714001SSerapheim Dimitropoulos 
354786714001SSerapheim Dimitropoulos 	VERIFY0(space_map_open(&checkpoint_sm, spa_meta_objset(spa),
354886714001SSerapheim Dimitropoulos 	    checkpoint_sm_obj, 0, vd->vdev_asize, vd->vdev_ashift));
354986714001SSerapheim Dimitropoulos 
355086714001SSerapheim Dimitropoulos 	VERIFY0(space_map_iterate(checkpoint_sm,
3551555d674dSSerapheim Dimitropoulos 	    space_map_length(checkpoint_sm),
355286714001SSerapheim Dimitropoulos 	    checkpoint_sm_exclude_entry_cb, &cseea));
355386714001SSerapheim Dimitropoulos 	space_map_close(checkpoint_sm);
355486714001SSerapheim Dimitropoulos 
355586714001SSerapheim Dimitropoulos 	zcb->zcb_checkpoint_size += cseea.cseea_checkpoint_size;
355686714001SSerapheim Dimitropoulos }
355786714001SSerapheim Dimitropoulos 
355886714001SSerapheim Dimitropoulos static void
355986714001SSerapheim Dimitropoulos zdb_leak_init_exclude_checkpoint(spa_t *spa, zdb_cb_t *zcb)
356086714001SSerapheim Dimitropoulos {
3561555d674dSSerapheim Dimitropoulos 	ASSERT(!dump_opt['L']);
3562555d674dSSerapheim Dimitropoulos 
356386714001SSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
356486714001SSerapheim Dimitropoulos 	for (uint64_t c = 0; c < rvd->vdev_children; c++) {
356586714001SSerapheim Dimitropoulos 		ASSERT3U(c, ==, rvd->vdev_child[c]->vdev_id);
356686714001SSerapheim Dimitropoulos 		zdb_leak_init_vdev_exclude_checkpoint(rvd->vdev_child[c], zcb);
356786714001SSerapheim Dimitropoulos 	}
356886714001SSerapheim Dimitropoulos }
356986714001SSerapheim Dimitropoulos 
3570*814dcd43SSerapheim Dimitropoulos static int
3571*814dcd43SSerapheim Dimitropoulos count_unflushed_space_cb(spa_t *spa, space_map_entry_t *sme,
3572*814dcd43SSerapheim Dimitropoulos     uint64_t txg, void *arg)
3573*814dcd43SSerapheim Dimitropoulos {
3574*814dcd43SSerapheim Dimitropoulos 	int64_t *ualloc_space = arg;
3575*814dcd43SSerapheim Dimitropoulos 	uint64_t offset = sme->sme_offset;
3576*814dcd43SSerapheim Dimitropoulos 	uint64_t vdev_id = sme->sme_vdev;
3577*814dcd43SSerapheim Dimitropoulos 
3578*814dcd43SSerapheim Dimitropoulos 	vdev_t *vd = vdev_lookup_top(spa, vdev_id);
3579*814dcd43SSerapheim Dimitropoulos 	if (!vdev_is_concrete(vd))
3580*814dcd43SSerapheim Dimitropoulos 		return (0);
3581*814dcd43SSerapheim Dimitropoulos 
3582*814dcd43SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
3583*814dcd43SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_ALLOC || sme->sme_type == SM_FREE);
3584*814dcd43SSerapheim Dimitropoulos 
3585*814dcd43SSerapheim Dimitropoulos 	if (txg < metaslab_unflushed_txg(ms))
3586*814dcd43SSerapheim Dimitropoulos 		return (0);
3587*814dcd43SSerapheim Dimitropoulos 
3588*814dcd43SSerapheim Dimitropoulos 	if (sme->sme_type == SM_ALLOC)
3589*814dcd43SSerapheim Dimitropoulos 		*ualloc_space += sme->sme_run;
3590*814dcd43SSerapheim Dimitropoulos 	else
3591*814dcd43SSerapheim Dimitropoulos 		*ualloc_space -= sme->sme_run;
3592*814dcd43SSerapheim Dimitropoulos 
3593*814dcd43SSerapheim Dimitropoulos 	return (0);
3594*814dcd43SSerapheim Dimitropoulos }
3595*814dcd43SSerapheim Dimitropoulos 
3596*814dcd43SSerapheim Dimitropoulos static int64_t
3597*814dcd43SSerapheim Dimitropoulos get_unflushed_alloc_space(spa_t *spa)
3598*814dcd43SSerapheim Dimitropoulos {
3599*814dcd43SSerapheim Dimitropoulos 	if (dump_opt['L'])
3600*814dcd43SSerapheim Dimitropoulos 		return (0);
3601*814dcd43SSerapheim Dimitropoulos 
3602*814dcd43SSerapheim Dimitropoulos 	int64_t ualloc_space = 0;
3603*814dcd43SSerapheim Dimitropoulos 	iterate_through_spacemap_logs(spa, count_unflushed_space_cb,
3604*814dcd43SSerapheim Dimitropoulos 	    &ualloc_space);
3605*814dcd43SSerapheim Dimitropoulos 	return (ualloc_space);
3606*814dcd43SSerapheim Dimitropoulos }
3607*814dcd43SSerapheim Dimitropoulos 
3608*814dcd43SSerapheim Dimitropoulos static int
3609*814dcd43SSerapheim Dimitropoulos load_unflushed_cb(spa_t *spa, space_map_entry_t *sme, uint64_t txg, void *arg)
3610*814dcd43SSerapheim Dimitropoulos {
3611*814dcd43SSerapheim Dimitropoulos 	maptype_t *uic_maptype = arg;
3612*814dcd43SSerapheim Dimitropoulos 	uint64_t offset = sme->sme_offset;
3613*814dcd43SSerapheim Dimitropoulos 	uint64_t size = sme->sme_run;
3614*814dcd43SSerapheim Dimitropoulos 	uint64_t vdev_id = sme->sme_vdev;
3615*814dcd43SSerapheim Dimitropoulos 	vdev_t *vd = vdev_lookup_top(spa, vdev_id);
3616*814dcd43SSerapheim Dimitropoulos 
3617*814dcd43SSerapheim Dimitropoulos 	/* skip indirect vdevs */
3618*814dcd43SSerapheim Dimitropoulos 	if (!vdev_is_concrete(vd))
3619*814dcd43SSerapheim Dimitropoulos 		return (0);
3620*814dcd43SSerapheim Dimitropoulos 
3621*814dcd43SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
3622*814dcd43SSerapheim Dimitropoulos 
3623*814dcd43SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_ALLOC || sme->sme_type == SM_FREE);
3624*814dcd43SSerapheim Dimitropoulos 	ASSERT(*uic_maptype == SM_ALLOC || *uic_maptype == SM_FREE);
3625*814dcd43SSerapheim Dimitropoulos 
3626*814dcd43SSerapheim Dimitropoulos 	if (txg < metaslab_unflushed_txg(ms))
3627*814dcd43SSerapheim Dimitropoulos 		return (0);
3628*814dcd43SSerapheim Dimitropoulos 
3629*814dcd43SSerapheim Dimitropoulos 	if (*uic_maptype == sme->sme_type)
3630*814dcd43SSerapheim Dimitropoulos 		range_tree_add(ms->ms_allocatable, offset, size);
3631*814dcd43SSerapheim Dimitropoulos 	else
3632*814dcd43SSerapheim Dimitropoulos 		range_tree_remove(ms->ms_allocatable, offset, size);
3633*814dcd43SSerapheim Dimitropoulos 
3634*814dcd43SSerapheim Dimitropoulos 	return (0);
3635*814dcd43SSerapheim Dimitropoulos }
3636*814dcd43SSerapheim Dimitropoulos 
3637*814dcd43SSerapheim Dimitropoulos static void
3638*814dcd43SSerapheim Dimitropoulos load_unflushed_to_ms_allocatables(spa_t *spa, maptype_t maptype)
3639*814dcd43SSerapheim Dimitropoulos {
3640*814dcd43SSerapheim Dimitropoulos 	iterate_through_spacemap_logs(spa, load_unflushed_cb, &maptype);
3641*814dcd43SSerapheim Dimitropoulos }
3642*814dcd43SSerapheim Dimitropoulos 
364386714001SSerapheim Dimitropoulos static void
364486714001SSerapheim Dimitropoulos load_concrete_ms_allocatable_trees(spa_t *spa, maptype_t maptype)
364586714001SSerapheim Dimitropoulos {
364686714001SSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
364786714001SSerapheim Dimitropoulos 	for (uint64_t i = 0; i < rvd->vdev_children; i++) {
364886714001SSerapheim Dimitropoulos 		vdev_t *vd = rvd->vdev_child[i];
364986714001SSerapheim Dimitropoulos 
365086714001SSerapheim Dimitropoulos 		ASSERT3U(i, ==, vd->vdev_id);
365186714001SSerapheim Dimitropoulos 
365286714001SSerapheim Dimitropoulos 		if (vd->vdev_ops == &vdev_indirect_ops)
365386714001SSerapheim Dimitropoulos 			continue;
365486714001SSerapheim Dimitropoulos 
365586714001SSerapheim Dimitropoulos 		for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
365686714001SSerapheim Dimitropoulos 			metaslab_t *msp = vd->vdev_ms[m];
365786714001SSerapheim Dimitropoulos 
365886714001SSerapheim Dimitropoulos 			(void) fprintf(stderr,
365986714001SSerapheim Dimitropoulos 			    "\rloading concrete vdev %llu, "
366086714001SSerapheim Dimitropoulos 			    "metaslab %llu of %llu ...",
366186714001SSerapheim Dimitropoulos 			    (longlong_t)vd->vdev_id,
366286714001SSerapheim Dimitropoulos 			    (longlong_t)msp->ms_id,
366386714001SSerapheim Dimitropoulos 			    (longlong_t)vd->vdev_ms_count);
366486714001SSerapheim Dimitropoulos 
366586714001SSerapheim Dimitropoulos 			mutex_enter(&msp->ms_lock);
3666*814dcd43SSerapheim Dimitropoulos 			range_tree_vacate(msp->ms_allocatable, NULL, NULL);
366786714001SSerapheim Dimitropoulos 
366886714001SSerapheim Dimitropoulos 			/*
366986714001SSerapheim Dimitropoulos 			 * We don't want to spend the CPU manipulating the
367086714001SSerapheim Dimitropoulos 			 * size-ordered tree, so clear the range_tree ops.
367186714001SSerapheim Dimitropoulos 			 */
367286714001SSerapheim Dimitropoulos 			msp->ms_allocatable->rt_ops = NULL;
367386714001SSerapheim Dimitropoulos 
367486714001SSerapheim Dimitropoulos 			if (msp->ms_sm != NULL) {
367586714001SSerapheim Dimitropoulos 				VERIFY0(space_map_load(msp->ms_sm,
367686714001SSerapheim Dimitropoulos 				    msp->ms_allocatable, maptype));
367786714001SSerapheim Dimitropoulos 			}
367886714001SSerapheim Dimitropoulos 			if (!msp->ms_loaded)
367986714001SSerapheim Dimitropoulos 				msp->ms_loaded = B_TRUE;
368086714001SSerapheim Dimitropoulos 			mutex_exit(&msp->ms_lock);
368186714001SSerapheim Dimitropoulos 		}
368286714001SSerapheim Dimitropoulos 	}
3683*814dcd43SSerapheim Dimitropoulos 
3684*814dcd43SSerapheim Dimitropoulos 	load_unflushed_to_ms_allocatables(spa, maptype);
368586714001SSerapheim Dimitropoulos }
368686714001SSerapheim Dimitropoulos 
368786714001SSerapheim Dimitropoulos /*
368886714001SSerapheim Dimitropoulos  * vm_idxp is an in-out parameter which (for indirect vdevs) is the
368986714001SSerapheim Dimitropoulos  * index in vim_entries that has the first entry in this metaslab.
369086714001SSerapheim Dimitropoulos  * On return, it will be set to the first entry after this metaslab.
369186714001SSerapheim Dimitropoulos  */
369286714001SSerapheim Dimitropoulos static void
369386714001SSerapheim Dimitropoulos load_indirect_ms_allocatable_tree(vdev_t *vd, metaslab_t *msp,
369486714001SSerapheim Dimitropoulos     uint64_t *vim_idxp)
369586714001SSerapheim Dimitropoulos {
369686714001SSerapheim Dimitropoulos 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
369786714001SSerapheim Dimitropoulos 
369886714001SSerapheim Dimitropoulos 	mutex_enter(&msp->ms_lock);
3699*814dcd43SSerapheim Dimitropoulos 	range_tree_vacate(msp->ms_allocatable, NULL, NULL);
370086714001SSerapheim Dimitropoulos 
370186714001SSerapheim Dimitropoulos 	/*
370286714001SSerapheim Dimitropoulos 	 * We don't want to spend the CPU manipulating the
370386714001SSerapheim Dimitropoulos 	 * size-ordered tree, so clear the range_tree ops.
370486714001SSerapheim Dimitropoulos 	 */
370586714001SSerapheim Dimitropoulos 	msp->ms_allocatable->rt_ops = NULL;
370686714001SSerapheim Dimitropoulos 
370786714001SSerapheim Dimitropoulos 	for (; *vim_idxp < vdev_indirect_mapping_num_entries(vim);
370886714001SSerapheim Dimitropoulos 	    (*vim_idxp)++) {
370986714001SSerapheim Dimitropoulos 		vdev_indirect_mapping_entry_phys_t *vimep =
371086714001SSerapheim Dimitropoulos 		    &vim->vim_entries[*vim_idxp];
371186714001SSerapheim Dimitropoulos 		uint64_t ent_offset = DVA_MAPPING_GET_SRC_OFFSET(vimep);
371286714001SSerapheim Dimitropoulos 		uint64_t ent_len = DVA_GET_ASIZE(&vimep->vimep_dst);
371386714001SSerapheim Dimitropoulos 		ASSERT3U(ent_offset, >=, msp->ms_start);
371486714001SSerapheim Dimitropoulos 		if (ent_offset >= msp->ms_start + msp->ms_size)
371586714001SSerapheim Dimitropoulos 			break;
371686714001SSerapheim Dimitropoulos 
371786714001SSerapheim Dimitropoulos 		/*
371886714001SSerapheim Dimitropoulos 		 * Mappings do not cross metaslab boundaries,
371986714001SSerapheim Dimitropoulos 		 * because we create them by walking the metaslabs.
372086714001SSerapheim Dimitropoulos 		 */
372186714001SSerapheim Dimitropoulos 		ASSERT3U(ent_offset + ent_len, <=,
372286714001SSerapheim Dimitropoulos 		    msp->ms_start + msp->ms_size);
372386714001SSerapheim Dimitropoulos 		range_tree_add(msp->ms_allocatable, ent_offset, ent_len);
372486714001SSerapheim Dimitropoulos 	}
372586714001SSerapheim Dimitropoulos 
372686714001SSerapheim Dimitropoulos 	if (!msp->ms_loaded)
372786714001SSerapheim Dimitropoulos 		msp->ms_loaded = B_TRUE;
372886714001SSerapheim Dimitropoulos 	mutex_exit(&msp->ms_lock);
372986714001SSerapheim Dimitropoulos }
373086714001SSerapheim Dimitropoulos 
373186714001SSerapheim Dimitropoulos static void
373286714001SSerapheim Dimitropoulos zdb_leak_init_prepare_indirect_vdevs(spa_t *spa, zdb_cb_t *zcb)
373386714001SSerapheim Dimitropoulos {
3734555d674dSSerapheim Dimitropoulos 	ASSERT(!dump_opt['L']);
3735555d674dSSerapheim Dimitropoulos 
373686714001SSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
373786714001SSerapheim Dimitropoulos 	for (uint64_t c = 0; c < rvd->vdev_children; c++) {
373886714001SSerapheim Dimitropoulos 		vdev_t *vd = rvd->vdev_child[c];
373986714001SSerapheim Dimitropoulos 
374086714001SSerapheim Dimitropoulos 		ASSERT3U(c, ==, vd->vdev_id);
374186714001SSerapheim Dimitropoulos 
374286714001SSerapheim Dimitropoulos 		if (vd->vdev_ops != &vdev_indirect_ops)
374386714001SSerapheim Dimitropoulos 			continue;
374486714001SSerapheim Dimitropoulos 
374586714001SSerapheim Dimitropoulos 		/*
374686714001SSerapheim Dimitropoulos 		 * Note: we don't check for mapping leaks on
374786714001SSerapheim Dimitropoulos 		 * removing vdevs because their ms_allocatable's
374886714001SSerapheim Dimitropoulos 		 * are used to look for leaks in allocated space.
374986714001SSerapheim Dimitropoulos 		 */
375086714001SSerapheim Dimitropoulos 		zcb->zcb_vd_obsolete_counts[c] = zdb_load_obsolete_counts(vd);
375186714001SSerapheim Dimitropoulos 
375286714001SSerapheim Dimitropoulos 		/*
375386714001SSerapheim Dimitropoulos 		 * Normally, indirect vdevs don't have any
375486714001SSerapheim Dimitropoulos 		 * metaslabs.  We want to set them up for
375586714001SSerapheim Dimitropoulos 		 * zio_claim().
375686714001SSerapheim Dimitropoulos 		 */
375786714001SSerapheim Dimitropoulos 		VERIFY0(vdev_metaslab_init(vd, 0));
375886714001SSerapheim Dimitropoulos 
375986714001SSerapheim Dimitropoulos 		vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
376086714001SSerapheim Dimitropoulos 		uint64_t vim_idx = 0;
376186714001SSerapheim Dimitropoulos 		for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
376286714001SSerapheim Dimitropoulos 
376386714001SSerapheim Dimitropoulos 			(void) fprintf(stderr,
376486714001SSerapheim Dimitropoulos 			    "\rloading indirect vdev %llu, "
376586714001SSerapheim Dimitropoulos 			    "metaslab %llu of %llu ...",
376686714001SSerapheim Dimitropoulos 			    (longlong_t)vd->vdev_id,
376786714001SSerapheim Dimitropoulos 			    (longlong_t)vd->vdev_ms[m]->ms_id,
376886714001SSerapheim Dimitropoulos 			    (longlong_t)vd->vdev_ms_count);
376986714001SSerapheim Dimitropoulos 
377086714001SSerapheim Dimitropoulos 			load_indirect_ms_allocatable_tree(vd, vd->vdev_ms[m],
377186714001SSerapheim Dimitropoulos 			    &vim_idx);
377286714001SSerapheim Dimitropoulos 		}
377386714001SSerapheim Dimitropoulos 		ASSERT3U(vim_idx, ==, vdev_indirect_mapping_num_entries(vim));
377486714001SSerapheim Dimitropoulos 	}
377586714001SSerapheim Dimitropoulos }
377686714001SSerapheim Dimitropoulos 
3777b24ab676SJeff Bonwick static void
3778b24ab676SJeff Bonwick zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
3779b24ab676SJeff Bonwick {
3780cde58dbcSMatthew Ahrens 	zcb->zcb_spa = spa;
3781cde58dbcSMatthew Ahrens 
3782555d674dSSerapheim Dimitropoulos 	if (dump_opt['L'])
3783555d674dSSerapheim Dimitropoulos 		return;
37848363e80aSGeorge Wilson 
3785555d674dSSerapheim Dimitropoulos 	dsl_pool_t *dp = spa->spa_dsl_pool;
3786555d674dSSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
37878363e80aSGeorge Wilson 
3788555d674dSSerapheim Dimitropoulos 	/*
3789555d674dSSerapheim Dimitropoulos 	 * We are going to be changing the meaning of the metaslab's
3790555d674dSSerapheim Dimitropoulos 	 * ms_allocatable.  Ensure that the allocator doesn't try to
3791555d674dSSerapheim Dimitropoulos 	 * use the tree.
3792555d674dSSerapheim Dimitropoulos 	 */
3793555d674dSSerapheim Dimitropoulos 	spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
3794555d674dSSerapheim Dimitropoulos 	spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
37955cabbc6bSPrashanth Sreenivasa 
3796555d674dSSerapheim Dimitropoulos 	zcb->zcb_vd_obsolete_counts =
3797555d674dSSerapheim Dimitropoulos 	    umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
3798555d674dSSerapheim Dimitropoulos 	    UMEM_NOFAIL);
37995cabbc6bSPrashanth Sreenivasa 
3800555d674dSSerapheim Dimitropoulos 	/*
3801555d674dSSerapheim Dimitropoulos 	 * For leak detection, we overload the ms_allocatable trees
3802555d674dSSerapheim Dimitropoulos 	 * to contain allocated segments instead of free segments.
3803555d674dSSerapheim Dimitropoulos 	 * As a result, we can't use the normal metaslab_load/unload
3804555d674dSSerapheim Dimitropoulos 	 * interfaces.
3805555d674dSSerapheim Dimitropoulos 	 */
3806555d674dSSerapheim Dimitropoulos 	zdb_leak_init_prepare_indirect_vdevs(spa, zcb);
3807555d674dSSerapheim Dimitropoulos 	load_concrete_ms_allocatable_trees(spa, SM_ALLOC);
38085cabbc6bSPrashanth Sreenivasa 
3809555d674dSSerapheim Dimitropoulos 	/*
3810555d674dSSerapheim Dimitropoulos 	 * On load_concrete_ms_allocatable_trees() we loaded all the
3811555d674dSSerapheim Dimitropoulos 	 * allocated entries from the ms_sm to the ms_allocatable for
3812555d674dSSerapheim Dimitropoulos 	 * each metaslab. If the pool has a checkpoint or is in the
3813555d674dSSerapheim Dimitropoulos 	 * middle of discarding a checkpoint, some of these blocks
3814555d674dSSerapheim Dimitropoulos 	 * may have been freed but their ms_sm may not have been
3815555d674dSSerapheim Dimitropoulos 	 * updated because they are referenced by the checkpoint. In
3816555d674dSSerapheim Dimitropoulos 	 * order to avoid false-positives during leak-detection, we
3817555d674dSSerapheim Dimitropoulos 	 * go through the vdev's checkpoint space map and exclude all
3818555d674dSSerapheim Dimitropoulos 	 * its entries from their relevant ms_allocatable.
3819555d674dSSerapheim Dimitropoulos 	 *
3820555d674dSSerapheim Dimitropoulos 	 * We also aggregate the space held by the checkpoint and add
3821555d674dSSerapheim Dimitropoulos 	 * it to zcb_checkpoint_size.
3822555d674dSSerapheim Dimitropoulos 	 *
3823555d674dSSerapheim Dimitropoulos 	 * Note that at this point we are also verifying that all the
3824555d674dSSerapheim Dimitropoulos 	 * entries on the checkpoint_sm are marked as allocated in
3825555d674dSSerapheim Dimitropoulos 	 * the ms_sm of their relevant metaslab.
3826555d674dSSerapheim Dimitropoulos 	 * [see comment in checkpoint_sm_exclude_entry_cb()]
3827555d674dSSerapheim Dimitropoulos 	 */
3828555d674dSSerapheim Dimitropoulos 	zdb_leak_init_exclude_checkpoint(spa, zcb);
3829555d674dSSerapheim Dimitropoulos 	ASSERT3U(zcb->zcb_checkpoint_size, ==, spa_get_checkpoint_space(spa));
38305cabbc6bSPrashanth Sreenivasa 
3831555d674dSSerapheim Dimitropoulos 	/* for cleaner progress output */
3832555d674dSSerapheim Dimitropoulos 	(void) fprintf(stderr, "\n");
3833555d674dSSerapheim Dimitropoulos 
3834555d674dSSerapheim Dimitropoulos 	if (bpobj_is_open(&dp->dp_obsolete_bpobj)) {
3835555d674dSSerapheim Dimitropoulos 		ASSERT(spa_feature_is_enabled(spa,
3836555d674dSSerapheim Dimitropoulos 		    SPA_FEATURE_DEVICE_REMOVAL));
3837555d674dSSerapheim Dimitropoulos 		(void) bpobj_iterate_nofree(&dp->dp_obsolete_bpobj,
3838555d674dSSerapheim Dimitropoulos 		    increment_indirect_mapping_cb, zcb, NULL);
3839b24ab676SJeff Bonwick 	}
3840b24ab676SJeff Bonwick 
3841b24ab676SJeff Bonwick 	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
3842bbfd46c4SJeff Bonwick 	zdb_ddt_leak_init(spa, zcb);
3843b24ab676SJeff Bonwick 	spa_config_exit(spa, SCL_CONFIG, FTAG);
3844b24ab676SJeff Bonwick }
3845b24ab676SJeff Bonwick 
38465cabbc6bSPrashanth Sreenivasa static boolean_t
38475cabbc6bSPrashanth Sreenivasa zdb_check_for_obsolete_leaks(vdev_t *vd, zdb_cb_t *zcb)
38485cabbc6bSPrashanth Sreenivasa {
38495cabbc6bSPrashanth Sreenivasa 	boolean_t leaks = B_FALSE;
38505cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
38515cabbc6bSPrashanth Sreenivasa 	uint64_t total_leaked = 0;
38525cabbc6bSPrashanth Sreenivasa 
38535cabbc6bSPrashanth Sreenivasa 	ASSERT(vim != NULL);
38545cabbc6bSPrashanth Sreenivasa 
38555cabbc6bSPrashanth Sreenivasa 	for (uint64_t i = 0; i < vdev_indirect_mapping_num_entries(vim); i++) {
38565cabbc6bSPrashanth Sreenivasa 		vdev_indirect_mapping_entry_phys_t *vimep =
38575cabbc6bSPrashanth Sreenivasa 		    &vim->vim_entries[i];
38585cabbc6bSPrashanth Sreenivasa 		uint64_t obsolete_bytes = 0;
38595cabbc6bSPrashanth Sreenivasa 		uint64_t offset = DVA_MAPPING_GET_SRC_OFFSET(vimep);
38605cabbc6bSPrashanth Sreenivasa 		metaslab_t *msp = vd->vdev_ms[offset >> vd->vdev_ms_shift];
38615cabbc6bSPrashanth Sreenivasa 
38625cabbc6bSPrashanth Sreenivasa 		/*
38635cabbc6bSPrashanth Sreenivasa 		 * This is not very efficient but it's easy to
38645cabbc6bSPrashanth Sreenivasa 		 * verify correctness.
38655cabbc6bSPrashanth Sreenivasa 		 */
38665cabbc6bSPrashanth Sreenivasa 		for (uint64_t inner_offset = 0;
38675cabbc6bSPrashanth Sreenivasa 		    inner_offset < DVA_GET_ASIZE(&vimep->vimep_dst);
38685cabbc6bSPrashanth Sreenivasa 		    inner_offset += 1 << vd->vdev_ashift) {
386986714001SSerapheim Dimitropoulos 			if (range_tree_contains(msp->ms_allocatable,
38705cabbc6bSPrashanth Sreenivasa 			    offset + inner_offset, 1 << vd->vdev_ashift)) {
38715cabbc6bSPrashanth Sreenivasa 				obsolete_bytes += 1 << vd->vdev_ashift;
38725cabbc6bSPrashanth Sreenivasa 			}
38735cabbc6bSPrashanth Sreenivasa 		}
38745cabbc6bSPrashanth Sreenivasa 
38755cabbc6bSPrashanth Sreenivasa 		int64_t bytes_leaked = obsolete_bytes -
38765cabbc6bSPrashanth Sreenivasa 		    zcb->zcb_vd_obsolete_counts[vd->vdev_id][i];
38775cabbc6bSPrashanth Sreenivasa 		ASSERT3U(DVA_GET_ASIZE(&vimep->vimep_dst), >=,
38785cabbc6bSPrashanth Sreenivasa 		    zcb->zcb_vd_obsolete_counts[vd->vdev_id][i]);
38795cabbc6bSPrashanth Sreenivasa 		if (bytes_leaked != 0 &&
38805cabbc6bSPrashanth Sreenivasa 		    (vdev_obsolete_counts_are_precise(vd) ||
38815cabbc6bSPrashanth Sreenivasa 		    dump_opt['d'] >= 5)) {
38825cabbc6bSPrashanth Sreenivasa 			(void) printf("obsolete indirect mapping count "
38835cabbc6bSPrashanth Sreenivasa 			    "mismatch on %llu:%llx:%llx : %llx bytes leaked\n",
38845cabbc6bSPrashanth Sreenivasa 			    (u_longlong_t)vd->vdev_id,
38855cabbc6bSPrashanth Sreenivasa 			    (u_longlong_t)DVA_MAPPING_GET_SRC_OFFSET(vimep),
38865cabbc6bSPrashanth Sreenivasa 			    (u_longlong_t)DVA_GET_ASIZE(&vimep->vimep_dst),
38875cabbc6bSPrashanth Sreenivasa 			    (u_longlong_t)bytes_leaked);
38885cabbc6bSPrashanth Sreenivasa 		}
38895cabbc6bSPrashanth Sreenivasa 		total_leaked += ABS(bytes_leaked);
38905cabbc6bSPrashanth Sreenivasa 	}
38915cabbc6bSPrashanth Sreenivasa 
38925cabbc6bSPrashanth Sreenivasa 	if (!vdev_obsolete_counts_are_precise(vd) && total_leaked > 0) {
38935cabbc6bSPrashanth Sreenivasa 		int pct_leaked = total_leaked * 100 /
38945cabbc6bSPrashanth Sreenivasa 		    vdev_indirect_mapping_bytes_mapped(vim);
38955cabbc6bSPrashanth Sreenivasa 		(void) printf("cannot verify obsolete indirect mapping "
38965cabbc6bSPrashanth Sreenivasa 		    "counts of vdev %llu because precise feature was not "
38975cabbc6bSPrashanth Sreenivasa 		    "enabled when it was removed: %d%% (%llx bytes) of mapping"
38985cabbc6bSPrashanth Sreenivasa 		    "unreferenced\n",
38995cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)vd->vdev_id, pct_leaked,
39005cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)total_leaked);
39015cabbc6bSPrashanth Sreenivasa 	} else if (total_leaked > 0) {
39025cabbc6bSPrashanth Sreenivasa 		(void) printf("obsolete indirect mapping count mismatch "
39035cabbc6bSPrashanth Sreenivasa 		    "for vdev %llu -- %llx total bytes mismatched\n",
39045cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)vd->vdev_id,
39055cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)total_leaked);
39065cabbc6bSPrashanth Sreenivasa 		leaks |= B_TRUE;
39075cabbc6bSPrashanth Sreenivasa 	}
39085cabbc6bSPrashanth Sreenivasa 
39095cabbc6bSPrashanth Sreenivasa 	vdev_indirect_mapping_free_obsolete_counts(vim,
39105cabbc6bSPrashanth Sreenivasa 	    zcb->zcb_vd_obsolete_counts[vd->vdev_id]);
39115cabbc6bSPrashanth Sreenivasa 	zcb->zcb_vd_obsolete_counts[vd->vdev_id] = NULL;
39125cabbc6bSPrashanth Sreenivasa 
39135cabbc6bSPrashanth Sreenivasa 	return (leaks);
39145cabbc6bSPrashanth Sreenivasa }
39155cabbc6bSPrashanth Sreenivasa 
39165cabbc6bSPrashanth Sreenivasa static boolean_t
39175cabbc6bSPrashanth Sreenivasa zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
3918b24ab676SJeff Bonwick {
3919555d674dSSerapheim Dimitropoulos 	if (dump_opt['L'])
3920555d674dSSerapheim Dimitropoulos 		return (B_FALSE);
3921555d674dSSerapheim Dimitropoulos 
39225cabbc6bSPrashanth Sreenivasa 	boolean_t leaks = B_FALSE;
39235cabbc6bSPrashanth Sreenivasa 
3924555d674dSSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
3925555d674dSSerapheim Dimitropoulos 	for (unsigned c = 0; c < rvd->vdev_children; c++) {
3926555d674dSSerapheim Dimitropoulos 		vdev_t *vd = rvd->vdev_child[c];
3927555d674dSSerapheim Dimitropoulos #if DEBUG
3928555d674dSSerapheim Dimitropoulos 		metaslab_group_t *mg = vd->vdev_mg;
3929555d674dSSerapheim Dimitropoulos #endif
39308363e80aSGeorge Wilson 
3931555d674dSSerapheim Dimitropoulos 		if (zcb->zcb_vd_obsolete_counts[c] != NULL) {
3932555d674dSSerapheim Dimitropoulos 			leaks |= zdb_check_for_obsolete_leaks(vd, zcb);
3933555d674dSSerapheim Dimitropoulos 		}
3934555d674dSSerapheim Dimitropoulos 
3935555d674dSSerapheim Dimitropoulos 		for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
3936555d674dSSerapheim Dimitropoulos 			metaslab_t *msp = vd->vdev_ms[m];
3937555d674dSSerapheim Dimitropoulos 			ASSERT3P(mg, ==, msp->ms_group);
3938555d674dSSerapheim Dimitropoulos 
3939555d674dSSerapheim Dimitropoulos 			/*
3940555d674dSSerapheim Dimitropoulos 			 * ms_allocatable has been overloaded
3941555d674dSSerapheim Dimitropoulos 			 * to contain allocated segments. Now that
3942555d674dSSerapheim Dimitropoulos 			 * we finished traversing all blocks, any
3943555d674dSSerapheim Dimitropoulos 			 * block that remains in the ms_allocatable
3944555d674dSSerapheim Dimitropoulos 			 * represents an allocated block that we
3945555d674dSSerapheim Dimitropoulos 			 * did not claim during the traversal.
3946555d674dSSerapheim Dimitropoulos 			 * Claimed blocks would have been removed
3947555d674dSSerapheim Dimitropoulos 			 * from the ms_allocatable.  For indirect
3948555d674dSSerapheim Dimitropoulos 			 * vdevs, space remaining in the tree
3949555d674dSSerapheim Dimitropoulos 			 * represents parts of the mapping that are
3950555d674dSSerapheim Dimitropoulos 			 * not referenced, which is not a bug.
3951555d674dSSerapheim Dimitropoulos 			 */
3952555d674dSSerapheim Dimitropoulos 			if (vd->vdev_ops == &vdev_indirect_ops) {
3953555d674dSSerapheim Dimitropoulos 				range_tree_vacate(msp->ms_allocatable,
3954555d674dSSerapheim Dimitropoulos 				    NULL, NULL);
3955555d674dSSerapheim Dimitropoulos 			} else {
3956555d674dSSerapheim Dimitropoulos 				range_tree_vacate(msp->ms_allocatable,
3957555d674dSSerapheim Dimitropoulos 				    zdb_leak, vd);
3958555d674dSSerapheim Dimitropoulos 			}
3959555d674dSSerapheim Dimitropoulos 			if (msp->ms_loaded) {
3960555d674dSSerapheim Dimitropoulos 				msp->ms_loaded = B_FALSE;
3961b24ab676SJeff Bonwick 			}
3962b24ab676SJeff Bonwick 		}
39635cabbc6bSPrashanth Sreenivasa 
3964b24ab676SJeff Bonwick 	}
3965555d674dSSerapheim Dimitropoulos 
3966555d674dSSerapheim Dimitropoulos 	umem_free(zcb->zcb_vd_obsolete_counts,
3967555d674dSSerapheim Dimitropoulos 	    rvd->vdev_children * sizeof (uint32_t *));
3968555d674dSSerapheim Dimitropoulos 	zcb->zcb_vd_obsolete_counts = NULL;
3969555d674dSSerapheim Dimitropoulos 
39705cabbc6bSPrashanth Sreenivasa 	return (leaks);
3971b24ab676SJeff Bonwick }
3972b24ab676SJeff Bonwick 
3973cde58dbcSMatthew Ahrens /* ARGSUSED */
3974cde58dbcSMatthew Ahrens static int
3975cde58dbcSMatthew Ahrens count_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
3976cde58dbcSMatthew Ahrens {
3977cde58dbcSMatthew Ahrens 	zdb_cb_t *zcb = arg;
3978cde58dbcSMatthew Ahrens 
3979490d05b9SMatthew Ahrens 	if (dump_opt['b'] >= 5) {
3980cde58dbcSMatthew Ahrens 		char blkbuf[BP_SPRINTF_LEN];
398143466aaeSMax Grossman 		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
3982cde58dbcSMatthew Ahrens 		(void) printf("[%s] %s\n",
3983cde58dbcSMatthew Ahrens 		    "deferred free", blkbuf);
3984cde58dbcSMatthew Ahrens 	}
3985cde58dbcSMatthew Ahrens 	zdb_count_block(zcb, NULL, bp, ZDB_OT_DEFERRED);
3986cde58dbcSMatthew Ahrens 	return (0);
3987cde58dbcSMatthew Ahrens }
3988cde58dbcSMatthew Ahrens 
3989fa9e4066Sahrens static int
3990fa9e4066Sahrens dump_block_stats(spa_t *spa)
3991fa9e4066Sahrens {
39923f7978d0SAlan Somers 	zdb_cb_t zcb;
3993fa9e4066Sahrens 	zdb_blkstats_t *zb, *tzb;
3994b24ab676SJeff Bonwick 	uint64_t norm_alloc, norm_space, total_alloc, total_found;
3995eb633035STom Caputi 	int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
3996eb633035STom Caputi 	    TRAVERSE_NO_DECRYPT | TRAVERSE_HARD;
39975d7b4d43SMatthew Ahrens 	boolean_t leaks = B_FALSE;
3998663207adSDon Brady 	int err;
3999fa9e4066Sahrens 
40003f7978d0SAlan Somers 	bzero(&zcb, sizeof (zcb));
4001490d05b9SMatthew Ahrens 	(void) printf("\nTraversing all blocks %s%s%s%s%s...\n\n",
4002b24ab676SJeff Bonwick 	    (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "",
4003b24ab676SJeff Bonwick 	    (dump_opt['c'] == 1) ? "metadata " : "",
4004b24ab676SJeff Bonwick 	    dump_opt['c'] ? "checksums " : "",
4005b24ab676SJeff Bonwick 	    (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "",
4006b24ab676SJeff Bonwick 	    !dump_opt['L'] ? "nothing leaked " : "");
4007fa9e4066Sahrens 
4008fa9e4066Sahrens 	/*
4009555d674dSSerapheim Dimitropoulos 	 * When leak detection is enabled we load all space maps as SM_ALLOC
4010555d674dSSerapheim Dimitropoulos 	 * maps, then traverse the pool claiming each block we discover. If
4011555d674dSSerapheim Dimitropoulos 	 * the pool is perfectly consistent, the segment trees will be empty
4012555d674dSSerapheim Dimitropoulos 	 * when we're done. Anything left over is a leak; any block we can't
4013555d674dSSerapheim Dimitropoulos 	 * claim (because it's not part of any space map) is a double
4014555d674dSSerapheim Dimitropoulos 	 * allocation, reference to a freed block, or an unclaimed log block.
4015555d674dSSerapheim Dimitropoulos 	 *
4016555d674dSSerapheim Dimitropoulos 	 * When leak detection is disabled (-L option) we still traverse the
4017555d674dSSerapheim Dimitropoulos 	 * pool claiming each block we discover, but we skip opening any space
4018555d674dSSerapheim Dimitropoulos 	 * maps.
4019fa9e4066Sahrens 	 */
4020555d674dSSerapheim Dimitropoulos 	bzero(&zcb, sizeof (zdb_cb_t));
4021b24ab676SJeff Bonwick 	zdb_leak_init(spa, &zcb);
4022fa9e4066Sahrens 
4023fa9e4066Sahrens 	/*
4024fa9e4066Sahrens 	 * If there's a deferred-free bplist, process that first.
4025fa9e4066Sahrens 	 */
4026cde58dbcSMatthew Ahrens 	(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
4027cde58dbcSMatthew Ahrens 	    count_block_cb, &zcb, NULL);
40285cabbc6bSPrashanth Sreenivasa 
40293b2aab18SMatthew Ahrens 	if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
40303b2aab18SMatthew Ahrens 		(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
40313b2aab18SMatthew Ahrens 		    count_block_cb, &zcb, NULL);
40323b2aab18SMatthew Ahrens 	}
40335cabbc6bSPrashanth Sreenivasa 
40345cabbc6bSPrashanth Sreenivasa 	zdb_claim_removing(spa, &zcb);
40355cabbc6bSPrashanth Sreenivasa 
40362acef22dSMatthew Ahrens 	if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {
4037b420f3adSRichard Lowe 		VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
4038ad135b5dSChristopher Siden 		    spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
4039ad135b5dSChristopher Siden 		    &zcb, NULL));
4040ad135b5dSChristopher Siden 	}
4041fa9e4066Sahrens 
4042bbfd46c4SJeff Bonwick 	if (dump_opt['c'] > 1)
4043bbfd46c4SJeff Bonwick 		flags |= TRAVERSE_PREFETCH_DATA;
4044bbfd46c4SJeff Bonwick 
4045490d05b9SMatthew Ahrens 	zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
4046663207adSDon Brady 	zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa));
4047663207adSDon Brady 	zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
4048490d05b9SMatthew Ahrens 	zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
4049663207adSDon Brady 	err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
4050fa9e4066Sahrens 
405131d7e8faSGeorge Wilson 	/*
405231d7e8faSGeorge Wilson 	 * If we've traversed the data blocks then we need to wait for those
405331d7e8faSGeorge Wilson 	 * I/Os to complete. We leverage "The Godfather" zio to wait on
405431d7e8faSGeorge Wilson 	 * all async I/Os to complete.
405531d7e8faSGeorge Wilson 	 */
405631d7e8faSGeorge Wilson 	if (dump_opt['c']) {
40576f834bc1SMatthew Ahrens 		for (int i = 0; i < max_ncpus; i++) {
40586f834bc1SMatthew Ahrens 			(void) zio_wait(spa->spa_async_zio_root[i]);
40596f834bc1SMatthew Ahrens 			spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
40606f834bc1SMatthew Ahrens 			    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
40616f834bc1SMatthew Ahrens 			    ZIO_FLAG_GODFATHER);
40626f834bc1SMatthew Ahrens 		}
406331d7e8faSGeorge Wilson 	}
406431d7e8faSGeorge Wilson 
4065663207adSDon Brady 	/*
4066663207adSDon Brady 	 * Done after zio_wait() since zcb_haderrors is modified in
4067663207adSDon Brady 	 * zdb_blkptr_done()
4068663207adSDon Brady 	 */
4069663207adSDon Brady 	zcb.zcb_haderrors |= err;
4070663207adSDon Brady 
4071b24ab676SJeff Bonwick 	if (zcb.zcb_haderrors) {
4072fa9e4066Sahrens 		(void) printf("\nError counts:\n\n");
4073fa9e4066Sahrens 		(void) printf("\t%5s  %s\n", "errno", "count");
4074b24ab676SJeff Bonwick 		for (int e = 0; e < 256; e++) {
4075fa9e4066Sahrens 			if (zcb.zcb_errors[e] != 0) {
4076fa9e4066Sahrens 				(void) printf("\t%5d  %llu\n",
4077fa9e4066Sahrens 				    e, (u_longlong_t)zcb.zcb_errors[e]);
4078fa9e4066Sahrens 			}
4079fa9e4066Sahrens 		}
4080fa9e4066Sahrens 	}
4081fa9e4066Sahrens 
4082fa9e4066Sahrens 	/*
4083fa9e4066Sahrens 	 * Report any leaked segments.
4084fa9e4066Sahrens 	 */
40855cabbc6bSPrashanth Sreenivasa 	leaks |= zdb_leak_fini(spa, &zcb);
4086fa9e4066Sahrens 
4087b24ab676SJeff Bonwick 	tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL];
40888654d025Sperrin 
4089b24ab676SJeff Bonwick 	norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
4090b24ab676SJeff Bonwick 	norm_space = metaslab_class_get_space(spa_normal_class(spa));
40918654d025Sperrin 
4092663207adSDon Brady 	total_alloc = norm_alloc +
4093663207adSDon Brady 	    metaslab_class_get_alloc(spa_log_class(spa)) +
4094663207adSDon Brady 	    metaslab_class_get_alloc(spa_special_class(spa)) +
4095*814dcd43SSerapheim Dimitropoulos 	    metaslab_class_get_alloc(spa_dedup_class(spa)) +
4096*814dcd43SSerapheim Dimitropoulos 	    get_unflushed_alloc_space(spa);
40975cabbc6bSPrashanth Sreenivasa 	total_found = tzb->zb_asize - zcb.zcb_dedup_asize +
409886714001SSerapheim Dimitropoulos 	    zcb.zcb_removing_size + zcb.zcb_checkpoint_size;
4099fa9e4066Sahrens 
4100555d674dSSerapheim Dimitropoulos 	if (total_found == total_alloc && !dump_opt['L']) {
4101555d674dSSerapheim Dimitropoulos 		(void) printf("\n\tNo leaks (block sum matches space"
4102555d674dSSerapheim Dimitropoulos 		    " maps exactly)\n");
4103555d674dSSerapheim Dimitropoulos 	} else if (!dump_opt['L']) {
4104fa9e4066Sahrens 		(void) printf("block traversal size %llu != alloc %llu "
410582a0a985SVictor Latushkin 		    "(%s %lld)\n",
4106b24ab676SJeff Bonwick 		    (u_longlong_t)total_found,
4107b24ab676SJeff Bonwick 		    (u_longlong_t)total_alloc,
410882a0a985SVictor Latushkin 		    (dump_opt['L']) ? "unreachable" : "leaked",
4109b24ab676SJeff Bonwick 		    (longlong_t)(total_alloc - total_found));
41105d7b4d43SMatthew Ahrens 		leaks = B_TRUE;
4111fa9e4066Sahrens 	}
4112fa9e4066Sahrens 
4113fa9e4066Sahrens 	if (tzb->zb_count == 0)
4114fa9e4066Sahrens 		return (2);
4115fa9e4066Sahrens 
4116fa9e4066Sahrens 	(void) printf("\n");
4117663207adSDon Brady 	(void) printf("\t%-16s %14llu\n", "bp count:",
4118fa9e4066Sahrens 	    (u_longlong_t)tzb->zb_count);
4119663207adSDon Brady 	(void) printf("\t%-16s %14llu\n", "ganged count:",
4120d5ee8a13SMatthew Ahrens 	    (longlong_t)tzb->zb_gangs);
4121663207adSDon Brady 	(void) printf("\t%-16s %14llu      avg: %6llu\n", "bp logical:",
4122fa9e4066Sahrens 	    (u_longlong_t)tzb->zb_lsize,
4123fa9e4066Sahrens 	    (u_longlong_t)(tzb->zb_lsize / tzb->zb_count));
4124663207adSDon Brady 	(void) printf("\t%-16s %14llu      avg: %6llu     compression: %6.2f\n",
4125663207adSDon Brady 	    "bp physical:", (u_longlong_t)tzb->zb_psize,
4126fa9e4066Sahrens 	    (u_longlong_t)(tzb->zb_psize / tzb->zb_count),
4127fa9e4066Sahrens 	    (double)tzb->zb_lsize / tzb->zb_psize);
4128663207adSDon Brady 	(void) printf("\t%-16s %14llu      avg: %6llu     compression: %6.2f\n",
4129663207adSDon Brady 	    "bp allocated:", (u_longlong_t)tzb->zb_asize,
4130fa9e4066Sahrens 	    (u_longlong_t)(tzb->zb_asize / tzb->zb_count),
4131fa9e4066Sahrens 	    (double)tzb->zb_lsize / tzb->zb_asize);
4132663207adSDon Brady 	(void) printf("\t%-16s %14llu    ref>1: %6llu   deduplication: %6.2f\n",
4133663207adSDon Brady 	    "bp deduped:", (u_longlong_t)zcb.zcb_dedup_asize,
4134b24ab676SJeff Bonwick 	    (u_longlong_t)zcb.zcb_dedup_blocks,
4135b24ab676SJeff Bonwick 	    (double)zcb.zcb_dedup_asize / tzb->zb_asize + 1.0);
4136663207adSDon Brady 	(void) printf("\t%-16s %14llu     used: %5.2f%%\n", "Normal class:",
4137b24ab676SJeff Bonwick 	    (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
4138fa9e4066Sahrens 
4139663207adSDon Brady 	if (spa_special_class(spa)->mc_rotor != NULL) {
4140663207adSDon Brady 		uint64_t alloc = metaslab_class_get_alloc(
4141663207adSDon Brady 		    spa_special_class(spa));
4142663207adSDon Brady 		uint64_t space = metaslab_class_get_space(
4143663207adSDon Brady 		    spa_special_class(spa));
4144663207adSDon Brady 
4145663207adSDon Brady 		(void) printf("\t%-16s %14llu     used: %5.2f%%\n",
4146663207adSDon Brady 		    "Special class", (u_longlong_t)alloc,
4147663207adSDon Brady 		    100.0 * alloc / space);
4148663207adSDon Brady 	}
4149663207adSDon Brady 
4150663207adSDon Brady 	if (spa_dedup_class(spa)->mc_rotor != NULL) {
4151663207adSDon Brady 		uint64_t alloc = metaslab_class_get_alloc(
4152663207adSDon Brady 		    spa_dedup_class(spa));
4153663207adSDon Brady 		uint64_t space = metaslab_class_get_space(
4154663207adSDon Brady 		    spa_dedup_class(spa));
4155663207adSDon Brady 
4156663207adSDon Brady 		(void) printf("\t%-16s %14llu     used: %5.2f%%\n",
4157663207adSDon Brady 		    "Dedup class", (u_longlong_t)alloc,
4158663207adSDon Brady 		    100.0 * alloc / space);
4159663207adSDon Brady 	}
4160663207adSDon Brady 
41615d7b4d43SMatthew Ahrens 	for (bp_embedded_type_t i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
41625d7b4d43SMatthew Ahrens 		if (zcb.zcb_embedded_blocks[i] == 0)
41635d7b4d43SMatthew Ahrens 			continue;
41645d7b4d43SMatthew Ahrens 		(void) printf("\n");
41655d7b4d43SMatthew Ahrens 		(void) printf("\tadditional, non-pointer bps of type %u: "
41665d7b4d43SMatthew Ahrens 		    "%10llu\n",
41675d7b4d43SMatthew Ahrens 		    i, (u_longlong_t)zcb.zcb_embedded_blocks[i]);
41685d7b4d43SMatthew Ahrens 
41695d7b4d43SMatthew Ahrens 		if (dump_opt['b'] >= 3) {
41705d7b4d43SMatthew Ahrens 			(void) printf("\t number of (compressed) bytes:  "
41715d7b4d43SMatthew Ahrens 			    "number of bps\n");
41725d7b4d43SMatthew Ahrens 			dump_histogram(zcb.zcb_embedded_histogram[i],
41735d7b4d43SMatthew Ahrens 			    sizeof (zcb.zcb_embedded_histogram[i]) /
41745d7b4d43SMatthew Ahrens 			    sizeof (zcb.zcb_embedded_histogram[i][0]), 0);
41755d7b4d43SMatthew Ahrens 		}
41765d7b4d43SMatthew Ahrens 	}
41775d7b4d43SMatthew Ahrens 
4178d5ee8a13SMatthew Ahrens 	if (tzb->zb_ditto_samevdev != 0) {
4179d5ee8a13SMatthew Ahrens 		(void) printf("\tDittoed blocks on same vdev: %llu\n",
4180d5ee8a13SMatthew Ahrens 		    (longlong_t)tzb->zb_ditto_samevdev);
4181d5ee8a13SMatthew Ahrens 	}
4182663207adSDon Brady 	if (tzb->zb_ditto_same_ms != 0) {
4183663207adSDon Brady 		(void) printf("\tDittoed blocks in same metaslab: %llu\n",
4184663207adSDon Brady 		    (longlong_t)tzb->zb_ditto_same_ms);
4185663207adSDon Brady 	}
4186d5ee8a13SMatthew Ahrens 
41875cabbc6bSPrashanth Sreenivasa 	for (uint64_t v = 0; v < spa->spa_root_vdev->vdev_children; v++) {
41885cabbc6bSPrashanth Sreenivasa 		vdev_t *vd = spa->spa_root_vdev->vdev_child[v];
41895cabbc6bSPrashanth Sreenivasa 		vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
41905cabbc6bSPrashanth Sreenivasa 
41915cabbc6bSPrashanth Sreenivasa 		if (vim == NULL) {
41925cabbc6bSPrashanth Sreenivasa 			continue;
41935cabbc6bSPrashanth Sreenivasa 		}
41945cabbc6bSPrashanth Sreenivasa 
41955cabbc6bSPrashanth Sreenivasa 		char mem[32];
41965cabbc6bSPrashanth Sreenivasa 		zdb_nicenum(vdev_indirect_mapping_num_entries(vim),
41975cabbc6bSPrashanth Sreenivasa 		    mem, vdev_indirect_mapping_size(vim));
41985cabbc6bSPrashanth Sreenivasa 
41995cabbc6bSPrashanth Sreenivasa 		(void) printf("\tindirect vdev id %llu has %llu segments "
42005cabbc6bSPrashanth Sreenivasa 		    "(%s in memory)\n",
42015cabbc6bSPrashanth Sreenivasa 		    (longlong_t)vd->vdev_id,
42025cabbc6bSPrashanth Sreenivasa 		    (longlong_t)vdev_indirect_mapping_num_entries(vim), mem);
42035cabbc6bSPrashanth Sreenivasa 	}
42045cabbc6bSPrashanth Sreenivasa 
4205fa9e4066Sahrens 	if (dump_opt['b'] >= 2) {
4206fa9e4066Sahrens 		int l, t, level;
4207fa9e4066Sahrens 		(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
4208fa9e4066Sahrens 		    "\t  avg\t comp\t%%Total\tType\n");
4209fa9e4066Sahrens 
4210b24ab676SJeff Bonwick 		for (t = 0; t <= ZDB_OT_TOTAL; t++) {
42113f9d6ad7SLin Ling 			char csize[32], lsize[32], psize[32], asize[32];
4212d5ee8a13SMatthew Ahrens 			char avg[32], gang[32];
42133f7978d0SAlan Somers 			const char *typename;
4214fa9e4066Sahrens 
42150a055120SJason King 			/* make sure nicenum has enough space */
42160a055120SJason King 			CTASSERT(sizeof (csize) >= NN_NUMBUF_SZ);
42170a055120SJason King 			CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
42180a055120SJason King 			CTASSERT(sizeof (psize) >= NN_NUMBUF_SZ);
42190a055120SJason King 			CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
42200a055120SJason King 			CTASSERT(sizeof (avg) >= NN_NUMBUF_SZ);
42210a055120SJason King 			CTASSERT(sizeof (gang) >= NN_NUMBUF_SZ);
42220a055120SJason King 
4223b24ab676SJeff Bonwick 			if (t < DMU_OT_NUMTYPES)
4224b24ab676SJeff Bonwick 				typename = dmu_ot[t].ot_name;
4225b24ab676SJeff Bonwick 			else
4226b24ab676SJeff Bonwick 				typename = zdb_ot_extname[t - DMU_OT_NUMTYPES];
4227fa9e4066Sahrens 
4228fa9e4066Sahrens 			if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) {
4229fa9e4066Sahrens 				(void) printf("%6s\t%5s\t%5s\t%5s"
4230fa9e4066Sahrens 				    "\t%5s\t%5s\t%6s\t%s\n",
4231fa9e4066Sahrens 				    "-",
4232fa9e4066Sahrens 				    "-",
4233fa9e4066Sahrens 				    "-",
4234fa9e4066Sahrens 				    "-",
4235fa9e4066Sahrens 				    "-",
4236fa9e4066Sahrens 				    "-",
4237fa9e4066Sahrens 				    "-",
4238fa9e4066Sahrens 				    typename);
4239fa9e4066Sahrens 				continue;
4240fa9e4066Sahrens 			}
4241fa9e4066Sahrens 
4242fa9e4066Sahrens 			for (l = ZB_TOTAL - 1; l >= -1; l--) {
4243fa9e4066Sahrens 				level = (l == -1 ? ZB_TOTAL : l);
4244fa9e4066Sahrens 				zb = &zcb.zcb_type[level][t];
4245fa9e4066Sahrens 
4246fa9e4066Sahrens 				if (zb->zb_asize == 0)
4247fa9e4066Sahrens 					continue;
4248fa9e4066Sahrens 
4249fa9e4066Sahrens 				if (dump_opt['b'] < 3 && level != ZB_TOTAL)
4250fa9e4066Sahrens 					continue;
4251fa9e4066Sahrens 
4252fa9e4066Sahrens 				if (level == 0 && zb->zb_asize ==
4253fa9e4066Sahrens 				    zcb.zcb_type[ZB_TOTAL][t].zb_asize)
4254fa9e4066Sahrens 					continue;
4255fa9e4066Sahrens 
42560a055120SJason King 				zdb_nicenum(zb->zb_count, csize,
42570a055120SJason King 				    sizeof (csize));
42580a055120SJason King 				zdb_nicenum(zb->zb_lsize, lsize,
42590a055120SJason King 				    sizeof (lsize));
42600a055120SJason King 				zdb_nicenum(zb->zb_psize, psize,
42610a055120SJason King 				    sizeof (psize));
42620a055120SJason King 				zdb_nicenum(zb->zb_asize, asize,
42630a055120SJason King 				    sizeof (asize));
42640a055120SJason King 				zdb_nicenum(zb->zb_asize / zb->zb_count, avg,
42650a055120SJason King 				    sizeof (avg));
42660a055120SJason King 				zdb_nicenum(zb->zb_gangs, gang, sizeof (gang));
4267fa9e4066Sahrens 
4268fa9e4066Sahrens 				(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
4269fa9e4066Sahrens 				    "\t%5.2f\t%6.2f\t",
4270fa9e4066Sahrens 				    csize, lsize, psize, asize, avg,
4271fa9e4066Sahrens 				    (double)zb->zb_lsize / zb->zb_psize,
4272fa9e4066Sahrens 				    100.0 * zb->zb_asize / tzb->zb_asize);
4273fa9e4066Sahrens 
4274fa9e4066Sahrens 				if (level == ZB_TOTAL)
4275fa9e4066Sahrens 					(void) printf("%s\n", typename);
4276fa9e4066Sahrens 				else
4277fa9e4066Sahrens 					(void) printf("    L%d %s\n",
4278fa9e4066Sahrens 					    level, typename);
4279490d05b9SMatthew Ahrens 
4280d5ee8a13SMatthew Ahrens 				if (dump_opt['b'] >= 3 && zb->zb_gangs > 0) {
4281d5ee8a13SMatthew Ahrens 					(void) printf("\t number of ganged "
4282d5ee8a13SMatthew Ahrens 					    "blocks: %s\n", gang);
4283d5ee8a13SMatthew Ahrens 				}
4284d5ee8a13SMatthew Ahrens 
4285490d05b9SMatthew Ahrens 				if (dump_opt['b'] >= 4) {
4286490d05b9SMatthew Ahrens 					(void) printf("psize "
4287490d05b9SMatthew Ahrens 					    "(in 512-byte sectors): "
4288490d05b9SMatthew Ahrens 					    "number of blocks\n");
4289490d05b9SMatthew Ahrens 					dump_histogram(zb->zb_psize_histogram,
42900713e232SGeorge Wilson 					    PSIZE_HISTO_SIZE, 0);
4291490d05b9SMatthew Ahrens 				}
4292fa9e4066Sahrens 			}
4293fa9e4066Sahrens 		}
4294fa9e4066Sahrens 	}
4295fa9e4066Sahrens 
4296fa9e4066Sahrens 	(void) printf("\n");
4297fa9e4066Sahrens 
4298fa9e4066Sahrens 	if (leaks)
4299fa9e4066Sahrens 		return (2);
4300fa9e4066Sahrens 
4301fa9e4066Sahrens 	if (zcb.zcb_haderrors)
4302fa9e4066Sahrens 		return (3);
4303fa9e4066Sahrens 
4304fa9e4066Sahrens 	return (0);
4305fa9e4066Sahrens }
4306fa9e4066Sahrens 
4307b24ab676SJeff Bonwick typedef struct zdb_ddt_entry {
4308b24ab676SJeff Bonwick 	ddt_key_t	zdde_key;
4309b24ab676SJeff Bonwick 	uint64_t	zdde_ref_blocks;
4310b24ab676SJeff Bonwick 	uint64_t	zdde_ref_lsize;
4311b24ab676SJeff Bonwick 	uint64_t	zdde_ref_psize;
4312b24ab676SJeff Bonwick 	uint64_t	zdde_ref_dsize;
4313b24ab676SJeff Bonwick 	avl_node_t	zdde_node;
4314b24ab676SJeff Bonwick } zdb_ddt_entry_t;
4315b24ab676SJeff Bonwick 
4316b24ab676SJeff Bonwick /* ARGSUSED */
4317b24ab676SJeff Bonwick static int
4318b24ab676SJeff Bonwick zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
43197802d7bfSMatthew Ahrens     const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
4320b24ab676SJeff Bonwick {
4321b24ab676SJeff Bonwick 	avl_tree_t *t = arg;
4322b24ab676SJeff Bonwick 	avl_index_t where;
4323b24ab676SJeff Bonwick 	zdb_ddt_entry_t *zdde, zdde_search;
4324b24ab676SJeff Bonwick 
4325a2cdcdd2SPaul Dagnelie 	if (bp == NULL || BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
4326b24ab676SJeff Bonwick 		return (0);
4327b24ab676SJeff Bonwick 
4328b24ab676SJeff Bonwick 	if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
4329b24ab676SJeff Bonwick 		(void) printf("traversing objset %llu, %llu objects, "
4330b24ab676SJeff Bonwick 		    "%lu blocks so far\n",
4331b24ab676SJeff Bonwick 		    (u_longlong_t)zb->zb_objset,
43325d7b4d43SMatthew Ahrens 		    (u_longlong_t)BP_GET_FILL(bp),
4333b24ab676SJeff Bonwick 		    avl_numnodes(t));
4334b24ab676SJeff Bonwick 	}
4335b24ab676SJeff Bonwick 
4336bbfd46c4SJeff Bonwick 	if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF ||
4337ad135b5dSChristopher Siden 	    BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp)))
4338b24ab676SJeff Bonwick 		return (0);
4339b24ab676SJeff Bonwick 
4340b24ab676SJeff Bonwick 	ddt_key_fill(&zdde_search.zdde_key, bp);
4341b24ab676SJeff Bonwick 
4342b24ab676SJeff Bonwick 	zdde = avl_find(t, &zdde_search, &where);
4343b24ab676SJeff Bonwick 
4344b24ab676SJeff Bonwick 	if (zdde == NULL) {
4345b24ab676SJeff Bonwick 		zdde = umem_zalloc(sizeof (*zdde), UMEM_NOFAIL);
4346b24ab676SJeff Bonwick 		zdde->zdde_key = zdde_search.zdde_key;
4347b24ab676SJeff Bonwick 		avl_insert(t, zdde, where);
4348b24ab676SJeff Bonwick 	}
4349b24ab676SJeff Bonwick 
4350b24ab676SJeff Bonwick 	zdde->zdde_ref_blocks += 1;
4351b24ab676SJeff Bonwick 	zdde->zdde_ref_lsize += BP_GET_LSIZE(bp);
4352b24ab676SJeff Bonwick 	zdde->zdde_ref_psize += BP_GET_PSIZE(bp);
4353b24ab676SJeff Bonwick 	zdde->zdde_ref_dsize += bp_get_dsize_sync(spa, bp);
4354b24ab676SJeff Bonwick 
4355b24ab676SJeff Bonwick 	return (0);
4356b24ab676SJeff Bonwick }
4357b24ab676SJeff Bonwick 
4358b24ab676SJeff Bonwick static void
4359b24ab676SJeff Bonwick dump_simulated_ddt(spa_t *spa)
4360b24ab676SJeff Bonwick {
4361b24ab676SJeff Bonwick 	avl_tree_t t;
4362b24ab676SJeff Bonwick 	void *cookie = NULL;
4363b24ab676SJeff Bonwick 	zdb_ddt_entry_t *zdde;
43643f7978d0SAlan Somers 	ddt_histogram_t ddh_total;
43653f7978d0SAlan Somers 	ddt_stat_t dds_total;
4366b24ab676SJeff Bonwick 
43673f7978d0SAlan Somers 	bzero(&ddh_total, sizeof (ddh_total));
43683f7978d0SAlan Somers 	bzero(&dds_total, sizeof (dds_total));
4369b24ab676SJeff Bonwick 	avl_create(&t, ddt_entry_compare,
4370b24ab676SJeff Bonwick 	    sizeof (zdb_ddt_entry_t), offsetof(zdb_ddt_entry_t, zdde_node));
4371b24ab676SJeff Bonwick 
4372b24ab676SJeff Bonwick 	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
4373b24ab676SJeff Bonwick 
4374eb633035STom Caputi 	(void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
4375eb633035STom Caputi 	    TRAVERSE_NO_DECRYPT, zdb_ddt_add_cb, &t);
4376b24ab676SJeff Bonwick 
4377b24ab676SJeff Bonwick 	spa_config_exit(spa, SCL_CONFIG, FTAG);
4378b24ab676SJeff Bonwick 
4379b24ab676SJeff Bonwick 	while ((zdde = avl_destroy_nodes(&t, &cookie)) != NULL) {
4380b24ab676SJeff Bonwick 		ddt_stat_t dds;
4381b24ab676SJeff Bonwick 		uint64_t refcnt = zdde->zdde_ref_blocks;
4382b24ab676SJeff Bonwick 		ASSERT(refcnt != 0);
4383b24ab676SJeff Bonwick 
4384b24ab676SJeff Bonwick 		dds.dds_blocks = zdde->zdde_ref_blocks / refcnt;
4385b24ab676SJeff Bonwick 		dds.dds_lsize = zdde->zdde_ref_lsize / refcnt;
4386b24ab676SJeff Bonwick 		dds.dds_psize = zdde->zdde_ref_psize / refcnt;
4387b24ab676SJeff Bonwick 		dds.dds_dsize = zdde->zdde_ref_dsize / refcnt;
4388b24ab676SJeff Bonwick 
4389b24ab676SJeff Bonwick 		dds.dds_ref_blocks = zdde->zdde_ref_blocks;
4390b24ab676SJeff Bonwick 		dds.dds_ref_lsize = zdde->zdde_ref_lsize;
4391b24ab676SJeff Bonwick 		dds.dds_ref_psize = zdde->zdde_ref_psize;
4392b24ab676SJeff Bonwick 		dds.dds_ref_dsize = zdde->zdde_ref_dsize;
4393b24ab676SJeff Bonwick 
4394bf16b11eSMatthew Ahrens 		ddt_stat_add(&ddh_total.ddh_stat[highbit64(refcnt) - 1],
4395bf16b11eSMatthew Ahrens 		    &dds, 0);
4396b24ab676SJeff Bonwick 
4397b24ab676SJeff Bonwick 		umem_free(zdde, sizeof (*zdde));
4398b24ab676SJeff Bonwick 	}
4399b24ab676SJeff Bonwick 
4400b24ab676SJeff Bonwick 	avl_destroy(&t);
4401b24ab676SJeff Bonwick 
4402b24ab676SJeff Bonwick 	ddt_histogram_stat(&dds_total, &ddh_total);
4403b24ab676SJeff Bonwick 
4404b24ab676SJeff Bonwick 	(void) printf("Simulated DDT histogram:\n");
4405b24ab676SJeff Bonwick 
44069eb19f4dSGeorge Wilson 	zpool_dump_ddt(&dds_total, &ddh_total);
4407b24ab676SJeff Bonwick 
4408b24ab676SJeff Bonwick 	dump_dedup_ratio(&dds_total);
4409b24ab676SJeff Bonwick }
4410b24ab676SJeff Bonwick 
44115cabbc6bSPrashanth Sreenivasa static int
44125cabbc6bSPrashanth Sreenivasa verify_device_removal_feature_counts(spa_t *spa)
44135cabbc6bSPrashanth Sreenivasa {
44145cabbc6bSPrashanth Sreenivasa 	uint64_t dr_feature_refcount = 0;
44155cabbc6bSPrashanth Sreenivasa 	uint64_t oc_feature_refcount = 0;
44165cabbc6bSPrashanth Sreenivasa 	uint64_t indirect_vdev_count = 0;
44175cabbc6bSPrashanth Sreenivasa 	uint64_t precise_vdev_count = 0;
44185cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_counts_object_count = 0;
44195cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_sm_count = 0;
44205cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_counts_count = 0;
44215cabbc6bSPrashanth Sreenivasa 	uint64_t scip_count = 0;
44225cabbc6bSPrashanth Sreenivasa 	uint64_t obsolete_bpobj_count = 0;
44235cabbc6bSPrashanth Sreenivasa 	int ret = 0;
44245cabbc6bSPrashanth Sreenivasa 
44255cabbc6bSPrashanth Sreenivasa 	spa_condensing_indirect_phys_t *scip =
44265cabbc6bSPrashanth Sreenivasa 	    &spa->spa_condensing_indirect_phys;
44275cabbc6bSPrashanth Sreenivasa 	if (scip->scip_next_mapping_object != 0) {
44285cabbc6bSPrashanth Sreenivasa 		vdev_t *vd = spa->spa_root_vdev->vdev_child[scip->scip_vdev];
44295cabbc6bSPrashanth Sreenivasa 		ASSERT(scip->scip_prev_obsolete_sm_object != 0);
44305cabbc6bSPrashanth Sreenivasa 		ASSERT3P(vd->vdev_ops, ==, &vdev_indirect_ops);
44315cabbc6bSPrashanth Sreenivasa 
44325cabbc6bSPrashanth Sreenivasa 		(void) printf("Condensing indirect vdev %llu: new mapping "
44335cabbc6bSPrashanth Sreenivasa 		    "object %llu, prev obsolete sm %llu\n",
44345cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)scip->scip_vdev,
44355cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)scip->scip_next_mapping_object,
44365cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)scip->scip_prev_obsolete_sm_object);
44375cabbc6bSPrashanth Sreenivasa 		if (scip->scip_prev_obsolete_sm_object != 0) {
44385cabbc6bSPrashanth Sreenivasa 			space_map_t *prev_obsolete_sm = NULL;
44395cabbc6bSPrashanth Sreenivasa 			VERIFY0(space_map_open(&prev_obsolete_sm,
44405cabbc6bSPrashanth Sreenivasa 			    spa->spa_meta_objset,
44415cabbc6bSPrashanth Sreenivasa 			    scip->scip_prev_obsolete_sm_object,
44425cabbc6bSPrashanth Sreenivasa 			    0, vd->vdev_asize, 0));
44435cabbc6bSPrashanth Sreenivasa 			dump_spacemap(spa->spa_meta_objset, prev_obsolete_sm);
44445cabbc6bSPrashanth Sreenivasa 			(void) printf("\n");
44455cabbc6bSPrashanth Sreenivasa 			space_map_close(prev_obsolete_sm);
44465cabbc6bSPrashanth Sreenivasa 		}
44475cabbc6bSPrashanth Sreenivasa 
44485cabbc6bSPrashanth Sreenivasa 		scip_count += 2;
44495cabbc6bSPrashanth Sreenivasa 	}
44505cabbc6bSPrashanth Sreenivasa 
44515cabbc6bSPrashanth Sreenivasa 	for (uint64_t i = 0; i < spa->spa_root_vdev->vdev_children; i++) {
44525cabbc6bSPrashanth Sreenivasa 		vdev_t *vd = spa->spa_root_vdev->vdev_child[i];
44535cabbc6bSPrashanth Sreenivasa 		vdev_indirect_config_t *vic = &vd->vdev_indirect_config;
44545cabbc6bSPrashanth Sreenivasa 
44555cabbc6bSPrashanth Sreenivasa 		if (vic->vic_mapping_object != 0) {
44565cabbc6bSPrashanth Sreenivasa 			ASSERT(vd->vdev_ops == &vdev_indirect_ops ||
44575cabbc6bSPrashanth Sreenivasa 			    vd->vdev_removing);
44585cabbc6bSPrashanth Sreenivasa 			indirect_vdev_count++;
44595cabbc6bSPrashanth Sreenivasa 
44605cabbc6bSPrashanth Sreenivasa 			if (vd->vdev_indirect_mapping->vim_havecounts) {
44615cabbc6bSPrashanth Sreenivasa 				obsolete_counts_count++;
44625cabbc6bSPrashanth Sreenivasa 			}
44635cabbc6bSPrashanth Sreenivasa 		}
44645cabbc6bSPrashanth Sreenivasa 		if (vdev_obsolete_counts_are_precise(vd)) {
44655cabbc6bSPrashanth Sreenivasa 			ASSERT(vic->vic_mapping_object != 0);
44665cabbc6bSPrashanth Sreenivasa 			precise_vdev_count++;
44675cabbc6bSPrashanth Sreenivasa 		}
44685cabbc6bSPrashanth Sreenivasa 		if (vdev_obsolete_sm_object(vd) != 0) {
44695cabbc6bSPrashanth Sreenivasa 			ASSERT(vic->vic_mapping_object != 0);
44705cabbc6bSPrashanth Sreenivasa 			obsolete_sm_count++;
44715cabbc6bSPrashanth Sreenivasa 		}
44725cabbc6bSPrashanth Sreenivasa 	}
44735cabbc6bSPrashanth Sreenivasa 
44745cabbc6bSPrashanth Sreenivasa 	(void) feature_get_refcount(spa,
44755cabbc6bSPrashanth Sreenivasa 	    &spa_feature_table[SPA_FEATURE_DEVICE_REMOVAL],
44765cabbc6bSPrashanth Sreenivasa 	    &dr_feature_refcount);
44775cabbc6bSPrashanth Sreenivasa 	(void) feature_get_refcount(spa,
44785cabbc6bSPrashanth Sreenivasa 	    &spa_feature_table[SPA_FEATURE_OBSOLETE_COUNTS],
44795cabbc6bSPrashanth Sreenivasa 	    &oc_feature_refcount);
44805cabbc6bSPrashanth Sreenivasa 
44815cabbc6bSPrashanth Sreenivasa 	if (dr_feature_refcount != indirect_vdev_count) {
44825cabbc6bSPrashanth Sreenivasa 		ret = 1;
44835cabbc6bSPrashanth Sreenivasa 		(void) printf("Number of indirect vdevs (%llu) " \
44845cabbc6bSPrashanth Sreenivasa 		    "does not match feature count (%llu)\n",
44855cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)indirect_vdev_count,
44865cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)dr_feature_refcount);
44875cabbc6bSPrashanth Sreenivasa 	} else {
44885cabbc6bSPrashanth Sreenivasa 		(void) printf("Verified device_removal feature refcount " \
44895cabbc6bSPrashanth Sreenivasa 		    "of %llu is correct\n",
44905cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)dr_feature_refcount);
44915cabbc6bSPrashanth Sreenivasa 	}
44925cabbc6bSPrashanth Sreenivasa 
44935cabbc6bSPrashanth Sreenivasa 	if (zap_contains(spa_meta_objset(spa), DMU_POOL_DIRECTORY_OBJECT,
44945cabbc6bSPrashanth Sreenivasa 	    DMU_POOL_OBSOLETE_BPOBJ) == 0) {
44955cabbc6bSPrashanth Sreenivasa 		obsolete_bpobj_count++;
44965cabbc6bSPrashanth Sreenivasa 	}
44975cabbc6bSPrashanth Sreenivasa 
44985cabbc6bSPrashanth Sreenivasa 
44995cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count = precise_vdev_count;
45005cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count += obsolete_sm_count;
45015cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count += obsolete_counts_count;
45025cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count += scip_count;
45035cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count += obsolete_bpobj_count;
45045cabbc6bSPrashanth Sreenivasa 	obsolete_counts_object_count += remap_deadlist_count;
45055cabbc6bSPrashanth Sreenivasa 
45065cabbc6bSPrashanth Sreenivasa 	if (oc_feature_refcount != obsolete_counts_object_count) {
45075cabbc6bSPrashanth Sreenivasa 		ret = 1;
45085cabbc6bSPrashanth Sreenivasa 		(void) printf("Number of obsolete counts objects (%llu) " \
45095cabbc6bSPrashanth Sreenivasa 		    "does not match feature count (%llu)\n",
45105cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)obsolete_counts_object_count,
45115cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)oc_feature_refcount);
45125cabbc6bSPrashanth Sreenivasa 		(void) printf("pv:%llu os:%llu oc:%llu sc:%llu "
45135cabbc6bSPrashanth Sreenivasa 		    "ob:%llu rd:%llu\n",
45145cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)precise_vdev_count,
45155cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)obsolete_sm_count,
45165cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)obsolete_counts_count,
45175cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)scip_count,
45185cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)obsolete_bpobj_count,
45195cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)remap_deadlist_count);
45205cabbc6bSPrashanth Sreenivasa 	} else {
45215cabbc6bSPrashanth Sreenivasa 		(void) printf("Verified indirect_refcount feature refcount " \
45225cabbc6bSPrashanth Sreenivasa 		    "of %llu is correct\n",
45235cabbc6bSPrashanth Sreenivasa 		    (u_longlong_t)oc_feature_refcount);
45245cabbc6bSPrashanth Sreenivasa 	}
45255cabbc6bSPrashanth Sreenivasa 	return (ret);
45265cabbc6bSPrashanth Sreenivasa }
45275cabbc6bSPrashanth Sreenivasa 
4528e0f1c0afSOlaf Faaland static void
4529e0f1c0afSOlaf Faaland zdb_set_skip_mmp(char *target)
4530e0f1c0afSOlaf Faaland {
4531e0f1c0afSOlaf Faaland 	spa_t *spa;
4532e0f1c0afSOlaf Faaland 
4533e0f1c0afSOlaf Faaland 	/*
4534e0f1c0afSOlaf Faaland 	 * Disable the activity check to allow examination of
4535e0f1c0afSOlaf Faaland 	 * active pools.
4536e0f1c0afSOlaf Faaland 	 */
4537e0f1c0afSOlaf Faaland 	mutex_enter(&spa_namespace_lock);
4538e0f1c0afSOlaf Faaland 	if ((spa = spa_lookup(target)) != NULL) {
4539e0f1c0afSOlaf Faaland 		spa->spa_import_flags |= ZFS_IMPORT_SKIP_MMP;
4540e0f1c0afSOlaf Faaland 	}
4541e0f1c0afSOlaf Faaland 	mutex_exit(&spa_namespace_lock);
4542e0f1c0afSOlaf Faaland }
4543e0f1c0afSOlaf Faaland 
454486714001SSerapheim Dimitropoulos #define	BOGUS_SUFFIX "_CHECKPOINTED_UNIVERSE"
454586714001SSerapheim Dimitropoulos /*
454686714001SSerapheim Dimitropoulos  * Import the checkpointed state of the pool specified by the target
454786714001SSerapheim Dimitropoulos  * parameter as readonly. The function also accepts a pool config
454886714001SSerapheim Dimitropoulos  * as an optional parameter, else it attempts to infer the config by
454986714001SSerapheim Dimitropoulos  * the name of the target pool.
455086714001SSerapheim Dimitropoulos  *
455186714001SSerapheim Dimitropoulos  * Note that the checkpointed state's pool name will be the name of
455286714001SSerapheim Dimitropoulos  * the original pool with the above suffix appened to it. In addition,
455386714001SSerapheim Dimitropoulos  * if the target is not a pool name (e.g. a path to a dataset) then
455486714001SSerapheim Dimitropoulos  * the new_path parameter is populated with the updated path to
455586714001SSerapheim Dimitropoulos  * reflect the fact that we are looking into the checkpointed state.
455686714001SSerapheim Dimitropoulos  *
455786714001SSerapheim Dimitropoulos  * The function returns a newly-allocated copy of the name of the
455886714001SSerapheim Dimitropoulos  * pool containing the checkpointed state. When this copy is no
455986714001SSerapheim Dimitropoulos  * longer needed it should be freed with free(3C). Same thing
456086714001SSerapheim Dimitropoulos  * applies to the new_path parameter if allocated.
456186714001SSerapheim Dimitropoulos  */
456286714001SSerapheim Dimitropoulos static char *
456386714001SSerapheim Dimitropoulos import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
456486714001SSerapheim Dimitropoulos {
456586714001SSerapheim Dimitropoulos 	int error = 0;
456686714001SSerapheim Dimitropoulos 	char *poolname, *bogus_name;
456786714001SSerapheim Dimitropoulos 
456886714001SSerapheim Dimitropoulos 	/* If the target is not a pool, the extract the pool name */
456986714001SSerapheim Dimitropoulos 	char *path_start = strchr(target, '/');
457086714001SSerapheim Dimitropoulos 	if (path_start != NULL) {
457186714001SSerapheim Dimitropoulos 		size_t poolname_len = path_start - target;
457286714001SSerapheim Dimitropoulos 		poolname = strndup(target, poolname_len);
457386714001SSerapheim Dimitropoulos 	} else {
457486714001SSerapheim Dimitropoulos 		poolname = target;
457586714001SSerapheim Dimitropoulos 	}
457686714001SSerapheim Dimitropoulos 
457786714001SSerapheim Dimitropoulos 	if (cfg == NULL) {
4578e0f1c0afSOlaf Faaland 		zdb_set_skip_mmp(poolname);
457986714001SSerapheim Dimitropoulos 		error = spa_get_stats(poolname, &cfg, NULL, 0);
458086714001SSerapheim Dimitropoulos 		if (error != 0) {
458186714001SSerapheim Dimitropoulos 			fatal("Tried to read config of pool \"%s\" but "
458286714001SSerapheim Dimitropoulos 			    "spa_get_stats() failed with error %d\n",
458386714001SSerapheim Dimitropoulos 			    poolname, error);
458486714001SSerapheim Dimitropoulos 		}
458586714001SSerapheim Dimitropoulos 	}
458686714001SSerapheim Dimitropoulos 
458786714001SSerapheim Dimitropoulos 	(void) asprintf(&bogus_name, "%s%s", poolname, BOGUS_SUFFIX);
458886714001SSerapheim Dimitropoulos 	fnvlist_add_string(cfg, ZPOOL_CONFIG_POOL_NAME, bogus_name);
458986714001SSerapheim Dimitropoulos 
459086714001SSerapheim Dimitropoulos 	error = spa_import(bogus_name, cfg, NULL,
4591e0f1c0afSOlaf Faaland 	    ZFS_IMPORT_MISSING_LOG | ZFS_IMPORT_CHECKPOINT |
4592e0f1c0afSOlaf Faaland 	    ZFS_IMPORT_SKIP_MMP);
459386714001SSerapheim Dimitropoulos 	if (error != 0) {
459486714001SSerapheim Dimitropoulos 		fatal("Tried to import pool \"%s\" but spa_import() failed "
459586714001SSerapheim Dimitropoulos 		    "with error %d\n", bogus_name, error);
459686714001SSerapheim Dimitropoulos 	}
459786714001SSerapheim Dimitropoulos 
459886714001SSerapheim Dimitropoulos 	if (new_path != NULL && path_start != NULL)
459986714001SSerapheim Dimitropoulos 		(void) asprintf(new_path, "%s%s", bogus_name, path_start);
460086714001SSerapheim Dimitropoulos 
460186714001SSerapheim Dimitropoulos 	if (target != poolname)
460286714001SSerapheim Dimitropoulos 		free(poolname);
460386714001SSerapheim Dimitropoulos 
460486714001SSerapheim Dimitropoulos 	return (bogus_name);
460586714001SSerapheim Dimitropoulos }
460686714001SSerapheim Dimitropoulos 
460786714001SSerapheim Dimitropoulos typedef struct verify_checkpoint_sm_entry_cb_arg {
460886714001SSerapheim Dimitropoulos 	vdev_t *vcsec_vd;
460986714001SSerapheim Dimitropoulos 
461086714001SSerapheim Dimitropoulos 	/* the following fields are only used for printing progress */
461186714001SSerapheim Dimitropoulos 	uint64_t vcsec_entryid;
461286714001SSerapheim Dimitropoulos 	uint64_t vcsec_num_entries;
461386714001SSerapheim Dimitropoulos } verify_checkpoint_sm_entry_cb_arg_t;
461486714001SSerapheim Dimitropoulos 
461586714001SSerapheim Dimitropoulos #define	ENTRIES_PER_PROGRESS_UPDATE 10000
461686714001SSerapheim Dimitropoulos 
461786714001SSerapheim Dimitropoulos static int
461817f11284SSerapheim Dimitropoulos verify_checkpoint_sm_entry_cb(space_map_entry_t *sme, void *arg)
461986714001SSerapheim Dimitropoulos {
462086714001SSerapheim Dimitropoulos 	verify_checkpoint_sm_entry_cb_arg_t *vcsec = arg;
462186714001SSerapheim Dimitropoulos 	vdev_t *vd = vcsec->vcsec_vd;
462217f11284SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[sme->sme_offset >> vd->vdev_ms_shift];
462317f11284SSerapheim Dimitropoulos 	uint64_t end = sme->sme_offset + sme->sme_run;
462486714001SSerapheim Dimitropoulos 
462517f11284SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_FREE);
462686714001SSerapheim Dimitropoulos 
462786714001SSerapheim Dimitropoulos 	if ((vcsec->vcsec_entryid % ENTRIES_PER_PROGRESS_UPDATE) == 0) {
462886714001SSerapheim Dimitropoulos 		(void) fprintf(stderr,
462986714001SSerapheim Dimitropoulos 		    "\rverifying vdev %llu, space map entry %llu of %llu ...",
463086714001SSerapheim Dimitropoulos 		    (longlong_t)vd->vdev_id,
463186714001SSerapheim Dimitropoulos 		    (longlong_t)vcsec->vcsec_entryid,
463286714001SSerapheim Dimitropoulos 		    (longlong_t)vcsec->vcsec_num_entries);
463386714001SSerapheim Dimitropoulos 	}
463486714001SSerapheim Dimitropoulos 	vcsec->vcsec_entryid++;
463586714001SSerapheim Dimitropoulos 
463686714001SSerapheim Dimitropoulos 	/*
463786714001SSerapheim Dimitropoulos 	 * See comment in checkpoint_sm_exclude_entry_cb()
463886714001SSerapheim Dimitropoulos 	 */
463917f11284SSerapheim Dimitropoulos 	VERIFY3U(sme->sme_offset, >=, ms->ms_start);
464086714001SSerapheim Dimitropoulos 	VERIFY3U(end, <=, ms->ms_start + ms->ms_size);
464186714001SSerapheim Dimitropoulos 
464286714001SSerapheim Dimitropoulos 	/*
464386714001SSerapheim Dimitropoulos 	 * The entries in the vdev_checkpoint_sm should be marked as
464486714001SSerapheim Dimitropoulos 	 * allocated in the checkpointed state of the pool, therefore
464586714001SSerapheim Dimitropoulos 	 * their respective ms_allocateable trees should not contain them.
464686714001SSerapheim Dimitropoulos 	 */
464786714001SSerapheim Dimitropoulos 	mutex_enter(&ms->ms_lock);
4648555d674dSSerapheim Dimitropoulos 	range_tree_verify_not_present(ms->ms_allocatable,
4649555d674dSSerapheim Dimitropoulos 	    sme->sme_offset, sme->sme_run);
465086714001SSerapheim Dimitropoulos 	mutex_exit(&ms->ms_lock);
465186714001SSerapheim Dimitropoulos 
465286714001SSerapheim Dimitropoulos 	return (0);
465386714001SSerapheim Dimitropoulos }
465486714001SSerapheim Dimitropoulos 
465586714001SSerapheim Dimitropoulos /*
465686714001SSerapheim Dimitropoulos  * Verify that all segments in the vdev_checkpoint_sm are allocated
465786714001SSerapheim Dimitropoulos  * according to the checkpoint's ms_sm (i.e. are not in the checkpoint's
465886714001SSerapheim Dimitropoulos  * ms_allocatable).
465986714001SSerapheim Dimitropoulos  *
466086714001SSerapheim Dimitropoulos  * Do so by comparing the checkpoint space maps (vdev_checkpoint_sm) of
466186714001SSerapheim Dimitropoulos  * each vdev in the current state of the pool to the metaslab space maps
466286714001SSerapheim Dimitropoulos  * (ms_sm) of the checkpointed state of the pool.
466386714001SSerapheim Dimitropoulos  *
466486714001SSerapheim Dimitropoulos  * Note that the function changes the state of the ms_allocatable
466586714001SSerapheim Dimitropoulos  * trees of the current spa_t. The entries of these ms_allocatable
466686714001SSerapheim Dimitropoulos  * trees are cleared out and then repopulated from with the free
466786714001SSerapheim Dimitropoulos  * entries of their respective ms_sm space maps.
466886714001SSerapheim Dimitropoulos  */
466986714001SSerapheim Dimitropoulos static void
467086714001SSerapheim Dimitropoulos verify_checkpoint_vdev_spacemaps(spa_t *checkpoint, spa_t *current)
467186714001SSerapheim Dimitropoulos {
467286714001SSerapheim Dimitropoulos 	vdev_t *ckpoint_rvd = checkpoint->spa_root_vdev;
467386714001SSerapheim Dimitropoulos 	vdev_t *current_rvd = current->spa_root_vdev;
467486714001SSerapheim Dimitropoulos 
467586714001SSerapheim Dimitropoulos 	load_concrete_ms_allocatable_trees(checkpoint, SM_FREE);
467686714001SSerapheim Dimitropoulos 
467786714001SSerapheim Dimitropoulos 	for (uint64_t c = 0; c < ckpoint_rvd->vdev_children; c++) {
467886714001SSerapheim Dimitropoulos 		vdev_t *ckpoint_vd = ckpoint_rvd->vdev_child[c];
467986714001SSerapheim Dimitropoulos 		vdev_t *current_vd = current_rvd->vdev_child[c];
468086714001SSerapheim Dimitropoulos 
468186714001SSerapheim Dimitropoulos 		space_map_t *checkpoint_sm = NULL;
468286714001SSerapheim Dimitropoulos 		uint64_t checkpoint_sm_obj;
468386714001SSerapheim Dimitropoulos 
468486714001SSerapheim Dimitropoulos 		if (ckpoint_vd->vdev_ops == &vdev_indirect_ops) {
468586714001SSerapheim Dimitropoulos 			/*
468686714001SSerapheim Dimitropoulos 			 * Since we don't allow device removal in a pool
468786714001SSerapheim Dimitropoulos 			 * that has a checkpoint, we expect that all removed
468886714001SSerapheim Dimitropoulos 			 * vdevs were removed from the pool before the
468986714001SSerapheim Dimitropoulos 			 * checkpoint.
469086714001SSerapheim Dimitropoulos 			 */
469186714001SSerapheim Dimitropoulos 			ASSERT3P(current_vd->vdev_ops, ==, &vdev_indirect_ops);
469286714001SSerapheim Dimitropoulos 			continue;
469386714001SSerapheim Dimitropoulos 		}
469486714001SSerapheim Dimitropoulos 
469586714001SSerapheim Dimitropoulos 		/*
469686714001SSerapheim Dimitropoulos 		 * If the checkpoint space map doesn't exist, then nothing
469786714001SSerapheim Dimitropoulos 		 * here is checkpointed so there's nothing to verify.
469886714001SSerapheim Dimitropoulos 		 */
469986714001SSerapheim Dimitropoulos 		if (current_vd->vdev_top_zap == 0 ||
470086714001SSerapheim Dimitropoulos 		    zap_contains(spa_meta_objset(current),
470186714001SSerapheim Dimitropoulos 		    current_vd->vdev_top_zap,
470286714001SSerapheim Dimitropoulos 		    VDEV_TOP_ZAP_POOL_CHECKPOINT_SM) != 0)
470386714001SSerapheim Dimitropoulos 			continue;
470486714001SSerapheim Dimitropoulos 
470586714001SSerapheim Dimitropoulos 		VERIFY0(zap_lookup(spa_meta_objset(current),
470686714001SSerapheim Dimitropoulos 		    current_vd->vdev_top_zap, VDEV_TOP_ZAP_POOL_CHECKPOINT_SM,
470786714001SSerapheim Dimitropoulos 		    sizeof (uint64_t), 1, &checkpoint_sm_obj));
470886714001SSerapheim Dimitropoulos 
470986714001SSerapheim Dimitropoulos 		VERIFY0(space_map_open(&checkpoint_sm, spa_meta_objset(current),
471086714001SSerapheim Dimitropoulos 		    checkpoint_sm_obj, 0, current_vd->vdev_asize,
471186714001SSerapheim Dimitropoulos 		    current_vd->vdev_ashift));
471286714001SSerapheim Dimitropoulos 
471386714001SSerapheim Dimitropoulos 		verify_checkpoint_sm_entry_cb_arg_t vcsec;
471486714001SSerapheim Dimitropoulos 		vcsec.vcsec_vd = ckpoint_vd;
471586714001SSerapheim Dimitropoulos 		vcsec.vcsec_entryid = 0;
471686714001SSerapheim Dimitropoulos 		vcsec.vcsec_num_entries =
471786714001SSerapheim Dimitropoulos 		    space_map_length(checkpoint_sm) / sizeof (uint64_t);
471886714001SSerapheim Dimitropoulos 		VERIFY0(space_map_iterate(checkpoint_sm,
4719555d674dSSerapheim Dimitropoulos 		    space_map_length(checkpoint_sm),
472086714001SSerapheim Dimitropoulos 		    verify_checkpoint_sm_entry_cb, &vcsec));
472186714001SSerapheim Dimitropoulos 		dump_spacemap(current->spa_meta_objset, checkpoint_sm);
472286714001SSerapheim Dimitropoulos 		space_map_close(checkpoint_sm);
472386714001SSerapheim Dimitropoulos 	}
472486714001SSerapheim Dimitropoulos 
472586714001SSerapheim Dimitropoulos 	/*
472686714001SSerapheim Dimitropoulos 	 * If we've added vdevs since we took the checkpoint, ensure
472786714001SSerapheim Dimitropoulos 	 * that their checkpoint space maps are empty.
472886714001SSerapheim Dimitropoulos 	 */
472986714001SSerapheim Dimitropoulos 	if (ckpoint_rvd->vdev_children < current_rvd->vdev_children) {
473086714001SSerapheim Dimitropoulos 		for (uint64_t c = ckpoint_rvd->vdev_children;
473186714001SSerapheim Dimitropoulos 		    c < current_rvd->vdev_children; c++) {
473286714001SSerapheim Dimitropoulos 			vdev_t *current_vd = current_rvd->vdev_child[c];
473386714001SSerapheim Dimitropoulos 			ASSERT3P(current_vd->vdev_checkpoint_sm, ==, NULL);
473486714001SSerapheim Dimitropoulos 		}
473586714001SSerapheim Dimitropoulos 	}
473686714001SSerapheim Dimitropoulos 
473786714001SSerapheim Dimitropoulos 	/* for cleaner progress output */
473886714001SSerapheim Dimitropoulos 	(void) fprintf(stderr, "\n");
473986714001SSerapheim Dimitropoulos }
474086714001SSerapheim Dimitropoulos 
474186714001SSerapheim Dimitropoulos /*
474286714001SSerapheim Dimitropoulos  * Verifies that all space that's allocated in the checkpoint is
474386714001SSerapheim Dimitropoulos  * still allocated in the current version, by checking that everything
474486714001SSerapheim Dimitropoulos  * in checkpoint's ms_allocatable (which is actually allocated, not
474586714001SSerapheim Dimitropoulos  * allocatable/free) is not present in current's ms_allocatable.
474686714001SSerapheim Dimitropoulos  *
474786714001SSerapheim Dimitropoulos  * Note that the function changes the state of the ms_allocatable
474886714001SSerapheim Dimitropoulos  * trees of both spas when called. The entries of all ms_allocatable
474986714001SSerapheim Dimitropoulos  * trees are cleared out and then repopulated from their respective
475086714001SSerapheim Dimitropoulos  * ms_sm space maps. In the checkpointed state we load the allocated
475186714001SSerapheim Dimitropoulos  * entries, and in the current state we load the free entries.
475286714001SSerapheim Dimitropoulos  */
475386714001SSerapheim Dimitropoulos static void
475486714001SSerapheim Dimitropoulos verify_checkpoint_ms_spacemaps(spa_t *checkpoint, spa_t *current)
475586714001SSerapheim Dimitropoulos {
475686714001SSerapheim Dimitropoulos 	vdev_t *ckpoint_rvd = checkpoint->spa_root_vdev;
475786714001SSerapheim Dimitropoulos 	vdev_t *current_rvd = current->spa_root_vdev;
475886714001SSerapheim Dimitropoulos 
475986714001SSerapheim Dimitropoulos 	load_concrete_ms_allocatable_trees(checkpoint, SM_ALLOC);
476086714001SSerapheim Dimitropoulos 	load_concrete_ms_allocatable_trees(current, SM_FREE);
476186714001SSerapheim Dimitropoulos 
476286714001SSerapheim Dimitropoulos 	for (uint64_t i = 0; i < ckpoint_rvd->vdev_children; i++) {
476386714001SSerapheim Dimitropoulos 		vdev_t *ckpoint_vd = ckpoint_rvd->vdev_child[i];
476486714001SSerapheim Dimitropoulos 		vdev_t *current_vd = current_rvd->vdev_child[i];
476586714001SSerapheim Dimitropoulos 
476686714001SSerapheim Dimitropoulos 		if (ckpoint_vd->vdev_ops == &vdev_indirect_ops) {
476786714001SSerapheim Dimitropoulos 			/*
476886714001SSerapheim Dimitropoulos 			 * See comment in verify_checkpoint_vdev_spacemaps()
476986714001SSerapheim Dimitropoulos 			 */
477086714001SSerapheim Dimitropoulos 			ASSERT3P(current_vd->vdev_ops, ==, &vdev_indirect_ops);
477186714001SSerapheim Dimitropoulos 			continue;
477286714001SSerapheim Dimitropoulos 		}
477386714001SSerapheim Dimitropoulos 
477486714001SSerapheim Dimitropoulos 		for (uint64_t m = 0; m < ckpoint_vd->vdev_ms_count; m++) {
477586714001SSerapheim Dimitropoulos 			metaslab_t *ckpoint_msp = ckpoint_vd->vdev_ms[m];
477686714001SSerapheim Dimitropoulos 			metaslab_t *current_msp = current_vd->vdev_ms[m];
477786714001SSerapheim Dimitropoulos 
477886714001SSerapheim Dimitropoulos 			(void) fprintf(stderr,
477986714001SSerapheim Dimitropoulos 			    "\rverifying vdev %llu of %llu, "
478086714001SSerapheim Dimitropoulos 			    "metaslab %llu of %llu ...",
478186714001SSerapheim Dimitropoulos 			    (longlong_t)current_vd->vdev_id,
478286714001SSerapheim Dimitropoulos 			    (longlong_t)current_rvd->vdev_children,
478386714001SSerapheim Dimitropoulos 			    (longlong_t)current_vd->vdev_ms[m]->ms_id,
478486714001SSerapheim Dimitropoulos 			    (longlong_t)current_vd->vdev_ms_count);
478586714001SSerapheim Dimitropoulos 
478686714001SSerapheim Dimitropoulos 			/*
478786714001SSerapheim Dimitropoulos 			 * We walk through the ms_allocatable trees that
478886714001SSerapheim Dimitropoulos 			 * are loaded with the allocated blocks from the
478986714001SSerapheim Dimitropoulos 			 * ms_sm spacemaps of the checkpoint. For each
479086714001SSerapheim Dimitropoulos 			 * one of these ranges we ensure that none of them
479186714001SSerapheim Dimitropoulos 			 * exists in the ms_allocatable trees of the
479286714001SSerapheim Dimitropoulos 			 * current state which are loaded with the ranges
479386714001SSerapheim Dimitropoulos 			 * that are currently free.
479486714001SSerapheim Dimitropoulos 			 *
479586714001SSerapheim Dimitropoulos 			 * This way we ensure that none of the blocks that
479686714001SSerapheim Dimitropoulos 			 * are part of the checkpoint were freed by mistake.
479786714001SSerapheim Dimitropoulos 			 */
479886714001SSerapheim Dimitropoulos 			range_tree_walk(ckpoint_msp->ms_allocatable,
4799555d674dSSerapheim Dimitropoulos 			    (range_tree_func_t *)range_tree_verify_not_present,
480086714001SSerapheim Dimitropoulos 			    current_msp->ms_allocatable);
480186714001SSerapheim Dimitropoulos 		}
480286714001SSerapheim Dimitropoulos 	}
480386714001SSerapheim Dimitropoulos 
480486714001SSerapheim Dimitropoulos 	/* for cleaner progress output */
480586714001SSerapheim Dimitropoulos 	(void) fprintf(stderr, "\n");
480686714001SSerapheim Dimitropoulos }
480786714001SSerapheim Dimitropoulos 
480886714001SSerapheim Dimitropoulos static void
480986714001SSerapheim Dimitropoulos verify_checkpoint_blocks(spa_t *spa)
481086714001SSerapheim Dimitropoulos {
4811555d674dSSerapheim Dimitropoulos 	ASSERT(!dump_opt['L']);
4812555d674dSSerapheim Dimitropoulos 
481386714001SSerapheim Dimitropoulos 	spa_t *checkpoint_spa;
481486714001SSerapheim Dimitropoulos 	char *checkpoint_pool;
481586714001SSerapheim Dimitropoulos 	nvlist_t *config = NULL;
481686714001SSerapheim Dimitropoulos 	int error = 0;
481786714001SSerapheim Dimitropoulos 
481886714001SSerapheim Dimitropoulos 	/*
481986714001SSerapheim Dimitropoulos 	 * We import the checkpointed state of the pool (under a different
482086714001SSerapheim Dimitropoulos 	 * name) so we can do verification on it against the current state
482186714001SSerapheim Dimitropoulos 	 * of the pool.
482286714001SSerapheim Dimitropoulos 	 */
482386714001SSerapheim Dimitropoulos 	checkpoint_pool = import_checkpointed_state(spa->spa_name, config,
482486714001SSerapheim Dimitropoulos 	    NULL);
482586714001SSerapheim Dimitropoulos 	ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
482686714001SSerapheim Dimitropoulos 
482786714001SSerapheim Dimitropoulos 	error = spa_open(checkpoint_pool, &checkpoint_spa, FTAG);
482886714001SSerapheim Dimitropoulos 	if (error != 0) {
482986714001SSerapheim Dimitropoulos 		fatal("Tried to open pool \"%s\" but spa_open() failed with "
483086714001SSerapheim Dimitropoulos 		    "error %d\n", checkpoint_pool, error);
483186714001SSerapheim Dimitropoulos 	}
483286714001SSerapheim Dimitropoulos 
483386714001SSerapheim Dimitropoulos 	/*
483486714001SSerapheim Dimitropoulos 	 * Ensure that ranges in the checkpoint space maps of each vdev
483586714001SSerapheim Dimitropoulos 	 * are allocated according to the checkpointed state's metaslab
483686714001SSerapheim Dimitropoulos 	 * space maps.
483786714001SSerapheim Dimitropoulos 	 */
483886714001SSerapheim Dimitropoulos 	verify_checkpoint_vdev_spacemaps(checkpoint_spa, spa);
483986714001SSerapheim Dimitropoulos 
484086714001SSerapheim Dimitropoulos 	/*
484186714001SSerapheim Dimitropoulos 	 * Ensure that allocated ranges in the checkpoint's metaslab
484286714001SSerapheim Dimitropoulos 	 * space maps remain allocated in the metaslab space maps of
484386714001SSerapheim Dimitropoulos 	 * the current state.
484486714001SSerapheim Dimitropoulos 	 */
484586714001SSerapheim Dimitropoulos 	verify_checkpoint_ms_spacemaps(checkpoint_spa, spa);
484686714001SSerapheim Dimitropoulos 
484786714001SSerapheim Dimitropoulos 	/*
484886714001SSerapheim Dimitropoulos 	 * Once we are done, we get rid of the checkpointed state.
484986714001SSerapheim Dimitropoulos 	 */
485086714001SSerapheim Dimitropoulos 	spa_close(checkpoint_spa, FTAG);
485186714001SSerapheim Dimitropoulos 	free(checkpoint_pool);
485286714001SSerapheim Dimitropoulos }
485386714001SSerapheim Dimitropoulos 
485486714001SSerapheim Dimitropoulos static void
485586714001SSerapheim Dimitropoulos dump_leftover_checkpoint_blocks(spa_t *spa)
485686714001SSerapheim Dimitropoulos {
485786714001SSerapheim Dimitropoulos 	vdev_t *rvd = spa->spa_root_vdev;
485886714001SSerapheim Dimitropoulos 
485986714001SSerapheim Dimitropoulos 	for (uint64_t i = 0; i < rvd->vdev_children; i++) {
486086714001SSerapheim Dimitropoulos 		vdev_t *vd = rvd->vdev_child[i];
486186714001SSerapheim Dimitropoulos 
486286714001SSerapheim Dimitropoulos 		space_map_t *checkpoint_sm = NULL;
486386714001SSerapheim Dimitropoulos 		uint64_t checkpoint_sm_obj;
486486714001SSerapheim Dimitropoulos 
486586714001SSerapheim Dimitropoulos 		if (vd->vdev_top_zap == 0)
486686714001SSerapheim Dimitropoulos 			continue;
486786714001SSerapheim Dimitropoulos 
486886714001SSerapheim Dimitropoulos 		if (zap_contains(spa_meta_objset(spa), vd->vdev_top_zap,
486986714001SSerapheim Dimitropoulos 		    VDEV_TOP_ZAP_POOL_CHECKPOINT_SM) != 0)
487086714001SSerapheim Dimitropoulos 			continue;
487186714001SSerapheim Dimitropoulos 
487286714001SSerapheim Dimitropoulos 		VERIFY0(zap_lookup(spa_meta_objset(spa), vd->vdev_top_zap,
487386714001SSerapheim Dimitropoulos 		    VDEV_TOP_ZAP_POOL_CHECKPOINT_SM,
487486714001SSerapheim Dimitropoulos 		    sizeof (uint64_t), 1, &checkpoint_sm_obj));
487586714001SSerapheim Dimitropoulos 
487686714001SSerapheim Dimitropoulos 		VERIFY0(space_map_open(&checkpoint_sm, spa_meta_objset(spa),
487786714001SSerapheim Dimitropoulos 		    checkpoint_sm_obj, 0, vd->vdev_asize, vd->vdev_ashift));
487886714001SSerapheim Dimitropoulos 		dump_spacemap(spa->spa_meta_objset, checkpoint_sm);
487986714001SSerapheim Dimitropoulos 		space_map_close(checkpoint_sm);
488086714001SSerapheim Dimitropoulos 	}
488186714001SSerapheim Dimitropoulos }
488286714001SSerapheim Dimitropoulos 
488386714001SSerapheim Dimitropoulos static int
488486714001SSerapheim Dimitropoulos verify_checkpoint(spa_t *spa)
488586714001SSerapheim Dimitropoulos {
488686714001SSerapheim Dimitropoulos 	uberblock_t checkpoint;
488786714001SSerapheim Dimitropoulos 	int error;
488886714001SSerapheim Dimitropoulos 
488986714001SSerapheim Dimitropoulos 	if (!spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT))
489086714001SSerapheim Dimitropoulos 		return (0);
489186714001SSerapheim Dimitropoulos 
489286714001SSerapheim Dimitropoulos 	error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
489386714001SSerapheim Dimitropoulos 	    DMU_POOL_ZPOOL_CHECKPOINT, sizeof (uint64_t),
489486714001SSerapheim Dimitropoulos 	    sizeof (uberblock_t) / sizeof (uint64_t), &checkpoint);
489586714001SSerapheim Dimitropoulos 
489617f11284SSerapheim Dimitropoulos 	if (error == ENOENT && !dump_opt['L']) {
489786714001SSerapheim Dimitropoulos 		/*
489886714001SSerapheim Dimitropoulos 		 * If the feature is active but the uberblock is missing
489986714001SSerapheim Dimitropoulos 		 * then we must be in the middle of discarding the
490086714001SSerapheim Dimitropoulos 		 * checkpoint.
490186714001SSerapheim Dimitropoulos 		 */
490286714001SSerapheim Dimitropoulos 		(void) printf("\nPartially discarded checkpoint "
490386714001SSerapheim Dimitropoulos 		    "state found:\n");
490486714001SSerapheim Dimitropoulos 		dump_leftover_checkpoint_blocks(spa);
490586714001SSerapheim Dimitropoulos 		return (0);
490686714001SSerapheim Dimitropoulos 	} else if (error != 0) {
490786714001SSerapheim Dimitropoulos 		(void) printf("lookup error %d when looking for "
490886714001SSerapheim Dimitropoulos 		    "checkpointed uberblock in MOS\n", error);
490986714001SSerapheim Dimitropoulos 		return (error);
491086714001SSerapheim Dimitropoulos 	}
491186714001SSerapheim Dimitropoulos 	dump_uberblock(&checkpoint, "\nCheckpointed uberblock found:\n", "\n");
491286714001SSerapheim Dimitropoulos 
491386714001SSerapheim Dimitropoulos 	if (checkpoint.ub_checkpoint_txg == 0) {
491486714001SSerapheim Dimitropoulos 		(void) printf("\nub_checkpoint_txg not set in checkpointed "
491586714001SSerapheim Dimitropoulos 		    "uberblock\n");
491686714001SSerapheim Dimitropoulos 		error = 3;
491786714001SSerapheim Dimitropoulos 	}
491886714001SSerapheim Dimitropoulos 
491917f11284SSerapheim Dimitropoulos 	if (error == 0 && !dump_opt['L'])
492086714001SSerapheim Dimitropoulos 		verify_checkpoint_blocks(spa);
492186714001SSerapheim Dimitropoulos 
492286714001SSerapheim Dimitropoulos 	return (error);
492386714001SSerapheim Dimitropoulos }
492486714001SSerapheim Dimitropoulos 
492517fb938fSMatthew Ahrens /* ARGSUSED */
492617fb938fSMatthew Ahrens static void
492717fb938fSMatthew Ahrens mos_leaks_cb(void *arg, uint64_t start, uint64_t size)
492817fb938fSMatthew Ahrens {
492917fb938fSMatthew Ahrens 	for (uint64_t i = start; i < size; i++) {
493017fb938fSMatthew Ahrens 		(void) printf("MOS object %llu referenced but not allocated\n",
493117fb938fSMatthew Ahrens 		    (u_longlong_t)i);
493217fb938fSMatthew Ahrens 	}
493317fb938fSMatthew Ahrens }
493417fb938fSMatthew Ahrens 
493517fb938fSMatthew Ahrens static range_tree_t *mos_refd_objs;
493617fb938fSMatthew Ahrens 
493717fb938fSMatthew Ahrens static void
493817fb938fSMatthew Ahrens mos_obj_refd(uint64_t obj)
493917fb938fSMatthew Ahrens {
494017fb938fSMatthew Ahrens 	if (obj != 0 && mos_refd_objs != NULL)
494117fb938fSMatthew Ahrens 		range_tree_add(mos_refd_objs, obj, 1);
494217fb938fSMatthew Ahrens }
494317fb938fSMatthew Ahrens 
4944*814dcd43SSerapheim Dimitropoulos static void
4945*814dcd43SSerapheim Dimitropoulos mos_leak_vdev_top_zap(vdev_t *vd)
4946*814dcd43SSerapheim Dimitropoulos {
4947*814dcd43SSerapheim Dimitropoulos 	uint64_t ms_flush_data_obj;
4948*814dcd43SSerapheim Dimitropoulos 
4949*814dcd43SSerapheim Dimitropoulos 	int error = zap_lookup(spa_meta_objset(vd->vdev_spa),
4950*814dcd43SSerapheim Dimitropoulos 	    vd->vdev_top_zap, VDEV_TOP_ZAP_MS_UNFLUSHED_PHYS_TXGS,
4951*814dcd43SSerapheim Dimitropoulos 	    sizeof (ms_flush_data_obj), 1, &ms_flush_data_obj);
4952*814dcd43SSerapheim Dimitropoulos 	if (error == ENOENT)
4953*814dcd43SSerapheim Dimitropoulos 		return;
4954*814dcd43SSerapheim Dimitropoulos 	ASSERT0(error);
4955*814dcd43SSerapheim Dimitropoulos 
4956*814dcd43SSerapheim Dimitropoulos 	mos_obj_refd(ms_flush_data_obj);
4957*814dcd43SSerapheim Dimitropoulos }
4958*814dcd43SSerapheim Dimitropoulos 
495917fb938fSMatthew Ahrens static void
496017fb938fSMatthew Ahrens mos_leak_vdev(vdev_t *vd)
496117fb938fSMatthew Ahrens {
496217fb938fSMatthew Ahrens 	mos_obj_refd(vd->vdev_dtl_object);
496317fb938fSMatthew Ahrens 	mos_obj_refd(vd->vdev_ms_array);
496417fb938fSMatthew Ahrens 	mos_obj_refd(vd->vdev_indirect_config.vic_births_object);
496517fb938fSMatthew Ahrens 	mos_obj_refd(vd->vdev_indirect_config.vic_mapping_object);
496617fb938fSMatthew Ahrens 	mos_obj_refd(vd->vdev_leaf_zap);
496717fb938fSMatthew Ahrens 	if (vd->vdev_checkpoint_sm != NULL)
496817fb938fSMatthew Ahrens 		mos_obj_refd(vd->vdev_checkpoint_sm->sm_object);
496917fb938fSMatthew Ahrens 	if (vd->vdev_indirect_mapping != NULL) {
497017fb938fSMatthew Ahrens 		mos_obj_refd(vd->vdev_indirect_mapping->
497117fb938fSMatthew Ahrens 		    vim_phys->vimp_counts_object);
497217fb938fSMatthew Ahrens 	}
497317fb938fSMatthew Ahrens 	if (vd->vdev_obsolete_sm != NULL)
497417fb938fSMatthew Ahrens 		mos_obj_refd(vd->vdev_obsolete_sm->sm_object);
497517fb938fSMatthew Ahrens 
497617fb938fSMatthew Ahrens 	for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
497717fb938fSMatthew Ahrens 		metaslab_t *ms = vd->vdev_ms[m];
497817fb938fSMatthew Ahrens 		mos_obj_refd(space_map_object(ms->ms_sm));
497917fb938fSMatthew Ahrens 	}
498017fb938fSMatthew Ahrens 
4981*814dcd43SSerapheim Dimitropoulos 	if (vd->vdev_top_zap != 0) {
4982*814dcd43SSerapheim Dimitropoulos 		mos_obj_refd(vd->vdev_top_zap);
4983*814dcd43SSerapheim Dimitropoulos 		mos_leak_vdev_top_zap(vd);
4984*814dcd43SSerapheim Dimitropoulos 	}
4985*814dcd43SSerapheim Dimitropoulos 
498617fb938fSMatthew Ahrens 	for (uint64_t c = 0; c < vd->vdev_children; c++) {
498717fb938fSMatthew Ahrens 		mos_leak_vdev(vd->vdev_child[c]);
498817fb938fSMatthew Ahrens 	}
498917fb938fSMatthew Ahrens }
499017fb938fSMatthew Ahrens 
4991*814dcd43SSerapheim Dimitropoulos static void
4992*814dcd43SSerapheim Dimitropoulos mos_leak_log_spacemaps(spa_t *spa)
4993*814dcd43SSerapheim Dimitropoulos {
4994*814dcd43SSerapheim Dimitropoulos 	uint64_t spacemap_zap;
4995*814dcd43SSerapheim Dimitropoulos 
4996*814dcd43SSerapheim Dimitropoulos 	int error = zap_lookup(spa_meta_objset(spa),
4997*814dcd43SSerapheim Dimitropoulos 	    DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_LOG_SPACEMAP_ZAP,
4998*814dcd43SSerapheim Dimitropoulos 	    sizeof (spacemap_zap), 1, &spacemap_zap);
4999*814dcd43SSerapheim Dimitropoulos 	if (error == ENOENT)
5000*814dcd43SSerapheim Dimitropoulos 		return;
5001*814dcd43SSerapheim Dimitropoulos 	ASSERT0(error);
5002*814dcd43SSerapheim Dimitropoulos 
5003*814dcd43SSerapheim Dimitropoulos 	mos_obj_refd(spacemap_zap);
5004*814dcd43SSerapheim Dimitropoulos 	for (spa_log_sm_t *sls = avl_first(&spa->spa_sm_logs_by_txg);
5005*814dcd43SSerapheim Dimitropoulos 	    sls; sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls))
5006*814dcd43SSerapheim Dimitropoulos 		mos_obj_refd(sls->sls_sm_obj);
5007*814dcd43SSerapheim Dimitropoulos }
5008*814dcd43SSerapheim Dimitropoulos 
500917fb938fSMatthew Ahrens static int
501017fb938fSMatthew Ahrens dump_mos_leaks(spa_t *spa)
501117fb938fSMatthew Ahrens {
501217fb938fSMatthew Ahrens 	int rv = 0;
501317fb938fSMatthew Ahrens 	objset_t *mos = spa->spa_meta_objset;
501417fb938fSMatthew Ahrens 	dsl_pool_t *dp = spa->spa_dsl_pool;
501517fb938fSMatthew Ahrens 
501617fb938fSMatthew Ahrens 	/* Visit and mark all referenced objects in the MOS */
501717fb938fSMatthew Ahrens 
501817fb938fSMatthew Ahrens 	mos_obj_refd(DMU_POOL_DIRECTORY_OBJECT);
501917fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_pool_props_object);
502017fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_config_object);
502117fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_ddt_stat_object);
502217fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_feat_desc_obj);
502317fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_feat_enabled_txg_obj);
502417fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_feat_for_read_obj);
502517fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_feat_for_write_obj);
502617fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_history);
502717fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_errlog_last);
502817fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_errlog_scrub);
502917fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_all_vdev_zaps);
503017fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_dsl_pool->dp_bptree_obj);
503117fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_dsl_pool->dp_tmp_userrefs_obj);
503217fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_dsl_pool->dp_scan->scn_phys.scn_queue_obj);
503317fb938fSMatthew Ahrens 	bpobj_count_refd(&spa->spa_deferred_bpobj);
503417fb938fSMatthew Ahrens 	mos_obj_refd(dp->dp_empty_bpobj);
503517fb938fSMatthew Ahrens 	bpobj_count_refd(&dp->dp_obsolete_bpobj);
503617fb938fSMatthew Ahrens 	bpobj_count_refd(&dp->dp_free_bpobj);
503717fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_l2cache.sav_object);
503817fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_spares.sav_object);
503917fb938fSMatthew Ahrens 
5040*814dcd43SSerapheim Dimitropoulos 	if (spa->spa_syncing_log_sm != NULL)
5041*814dcd43SSerapheim Dimitropoulos 		mos_obj_refd(spa->spa_syncing_log_sm->sm_object);
5042*814dcd43SSerapheim Dimitropoulos 	mos_leak_log_spacemaps(spa);
5043*814dcd43SSerapheim Dimitropoulos 
504417fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_condensing_indirect_phys.
504517fb938fSMatthew Ahrens 	    scip_next_mapping_object);
504617fb938fSMatthew Ahrens 	mos_obj_refd(spa->spa_condensing_indirect_phys.
504717fb938fSMatthew Ahrens 	    scip_prev_obsolete_sm_object);
504817fb938fSMatthew Ahrens 	if (spa->spa_condensing_indirect_phys.scip_next_mapping_object != 0) {
504917fb938fSMatthew Ahrens 		vdev_indirect_mapping_t *vim =
505017fb938fSMatthew Ahrens 		    vdev_indirect_mapping_open(mos,
505117fb938fSMatthew Ahrens 		    spa->spa_condensing_indirect_phys.scip_next_mapping_object);
505217fb938fSMatthew Ahrens 		mos_obj_refd(vim->vim_phys->vimp_counts_object);
505317fb938fSMatthew Ahrens 		vdev_indirect_mapping_close(vim);
505417fb938fSMatthew Ahrens 	}
505517fb938fSMatthew Ahrens 
505617fb938fSMatthew Ahrens 	if (dp->dp_origin_snap != NULL) {
505717fb938fSMatthew Ahrens 		dsl_dataset_t *ds;
505817fb938fSMatthew Ahrens 
505917fb938fSMatthew Ahrens 		dsl_pool_config_enter(dp, FTAG);
506017fb938fSMatthew Ahrens 		VERIFY0(dsl_dataset_hold_obj(dp,
506117fb938fSMatthew Ahrens 		    dsl_dataset_phys(dp->dp_origin_snap)->ds_next_snap_obj,
506217fb938fSMatthew Ahrens 		    FTAG, &ds));
506317fb938fSMatthew Ahrens 		count_ds_mos_objects(ds);
506417fb938fSMatthew Ahrens 		dump_deadlist(&ds->ds_deadlist);
506517fb938fSMatthew Ahrens 		dsl_dataset_rele(ds, FTAG);
506617fb938fSMatthew Ahrens 		dsl_pool_config_exit(dp, FTAG);
506717fb938fSMatthew Ahrens 
506817fb938fSMatthew Ahrens 		count_ds_mos_objects(dp->dp_origin_snap);
506917fb938fSMatthew Ahrens 		dump_deadlist(&dp->dp_origin_snap->ds_deadlist);
507017fb938fSMatthew Ahrens 	}
507117fb938fSMatthew Ahrens 	count_dir_mos_objects(dp->dp_mos_dir);
507217fb938fSMatthew Ahrens 	if (dp->dp_free_dir != NULL)
507317fb938fSMatthew Ahrens 		count_dir_mos_objects(dp->dp_free_dir);
507417fb938fSMatthew Ahrens 	if (dp->dp_leak_dir != NULL)
507517fb938fSMatthew Ahrens 		count_dir_mos_objects(dp->dp_leak_dir);
507617fb938fSMatthew Ahrens 
507717fb938fSMatthew Ahrens 	mos_leak_vdev(spa->spa_root_vdev);
507817fb938fSMatthew Ahrens 
507917fb938fSMatthew Ahrens 	for (uint64_t class = 0; class < DDT_CLASSES; class++) {
508017fb938fSMatthew Ahrens 		for (uint64_t type = 0; type < DDT_TYPES; type++) {
508117fb938fSMatthew Ahrens 			for (uint64_t cksum = 0;
508217fb938fSMatthew Ahrens 			    cksum < ZIO_CHECKSUM_FUNCTIONS; cksum++) {
508317fb938fSMatthew Ahrens 				ddt_t *ddt = spa->spa_ddt[cksum];
508417fb938fSMatthew Ahrens 				mos_obj_refd(ddt->ddt_object[type][class]);
508517fb938fSMatthew Ahrens 			}
508617fb938fSMatthew Ahrens 		}
508717fb938fSMatthew Ahrens 	}
508817fb938fSMatthew Ahrens 
508917fb938fSMatthew Ahrens 	/*
509017fb938fSMatthew Ahrens 	 * Visit all allocated objects and make sure they are referenced.
509117fb938fSMatthew Ahrens 	 */
509217fb938fSMatthew Ahrens 	uint64_t object = 0;
509317fb938fSMatthew Ahrens 	while (dmu_object_next(mos, &object, B_FALSE, 0) == 0) {
509417fb938fSMatthew Ahrens 		if (range_tree_contains(mos_refd_objs, object, 1)) {
509517fb938fSMatthew Ahrens 			range_tree_remove(mos_refd_objs, object, 1);
509617fb938fSMatthew Ahrens 		} else {
509717fb938fSMatthew Ahrens 			dmu_object_info_t doi;
509817fb938fSMatthew Ahrens 			const char *name;
509917fb938fSMatthew Ahrens 			dmu_object_info(mos, object, &doi);
510017fb938fSMatthew Ahrens 			if (doi.doi_type & DMU_OT_NEWTYPE) {
510117fb938fSMatthew Ahrens 				dmu_object_byteswap_t bswap =
510217fb938fSMatthew Ahrens 				    DMU_OT_BYTESWAP(doi.doi_type);
510317fb938fSMatthew Ahrens 				name = dmu_ot_byteswap[bswap].ob_name;
510417fb938fSMatthew Ahrens 			} else {
510517fb938fSMatthew Ahrens 				name = dmu_ot[doi.doi_type].ot_name;
510617fb938fSMatthew Ahrens 			}
510717fb938fSMatthew Ahrens 
510817fb938fSMatthew Ahrens 			(void) printf("MOS object %llu (%s) leaked\n",
510917fb938fSMatthew Ahrens 			    (u_longlong_t)object, name);
511017fb938fSMatthew Ahrens 			rv = 2;
511117fb938fSMatthew Ahrens 		}
511217fb938fSMatthew Ahrens 	}
511317fb938fSMatthew Ahrens 	(void) range_tree_walk(mos_refd_objs, mos_leaks_cb, NULL);
511417fb938fSMatthew Ahrens 	if (!range_tree_is_empty(mos_refd_objs))
511517fb938fSMatthew Ahrens 		rv = 2;
511617fb938fSMatthew Ahrens 	range_tree_vacate(mos_refd_objs, NULL, NULL);
511717fb938fSMatthew Ahrens 	range_tree_destroy(mos_refd_objs);
511817fb938fSMatthew Ahrens 	return (rv);
511917fb938fSMatthew Ahrens }
512017fb938fSMatthew Ahrens 
5121*814dcd43SSerapheim Dimitropoulos typedef struct log_sm_obsolete_stats_arg {
5122*814dcd43SSerapheim Dimitropoulos 	uint64_t lsos_current_txg;
5123*814dcd43SSerapheim Dimitropoulos 
5124*814dcd43SSerapheim Dimitropoulos 	uint64_t lsos_total_entries;
5125*814dcd43SSerapheim Dimitropoulos 	uint64_t lsos_valid_entries;
5126*814dcd43SSerapheim Dimitropoulos 
5127*814dcd43SSerapheim Dimitropoulos 	uint64_t lsos_sm_entries;
5128*814dcd43SSerapheim Dimitropoulos 	uint64_t lsos_valid_sm_entries;
5129*814dcd43SSerapheim Dimitropoulos } log_sm_obsolete_stats_arg_t;
5130*814dcd43SSerapheim Dimitropoulos 
5131*814dcd43SSerapheim Dimitropoulos static int
5132*814dcd43SSerapheim Dimitropoulos log_spacemap_obsolete_stats_cb(spa_t *spa, space_map_entry_t *sme,
5133*814dcd43SSerapheim Dimitropoulos     uint64_t txg, void *arg)
5134*814dcd43SSerapheim Dimitropoulos {
5135*814dcd43SSerapheim Dimitropoulos 	log_sm_obsolete_stats_arg_t *lsos = arg;
5136*814dcd43SSerapheim Dimitropoulos 	uint64_t offset = sme->sme_offset;
5137*814dcd43SSerapheim Dimitropoulos 	uint64_t vdev_id = sme->sme_vdev;
5138*814dcd43SSerapheim Dimitropoulos 
5139*814dcd43SSerapheim Dimitropoulos 	if (lsos->lsos_current_txg == 0) {
5140*814dcd43SSerapheim Dimitropoulos 		/* this is the first log */
5141*814dcd43SSerapheim Dimitropoulos 		lsos->lsos_current_txg = txg;
5142*814dcd43SSerapheim Dimitropoulos 	} else if (lsos->lsos_current_txg < txg) {
5143*814dcd43SSerapheim Dimitropoulos 		/* we just changed log - print stats and reset */
5144*814dcd43SSerapheim Dimitropoulos 		(void) printf("%-8llu valid entries out of %-8llu - txg %llu\n",
5145*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)lsos->lsos_valid_sm_entries,
5146*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)lsos->lsos_sm_entries,
5147*814dcd43SSerapheim Dimitropoulos 		    (u_longlong_t)lsos->lsos_current_txg);
5148*814dcd43SSerapheim Dimitropoulos 		lsos->lsos_valid_sm_entries = 0;
5149*814dcd43SSerapheim Dimitropoulos 		lsos->lsos_sm_entries = 0;
5150*814dcd43SSerapheim Dimitropoulos 		lsos->lsos_current_txg = txg;
5151*814dcd43SSerapheim Dimitropoulos 	}
5152*814dcd43SSerapheim Dimitropoulos 	ASSERT3U(lsos->lsos_current_txg, ==, txg);
5153*814dcd43SSerapheim Dimitropoulos 
5154*814dcd43SSerapheim Dimitropoulos 	lsos->lsos_sm_entries++;
5155*814dcd43SSerapheim Dimitropoulos 	lsos->lsos_total_entries++;
5156*814dcd43SSerapheim Dimitropoulos 
5157*814dcd43SSerapheim Dimitropoulos 	vdev_t *vd = vdev_lookup_top(spa, vdev_id);
5158*814dcd43SSerapheim Dimitropoulos 	if (!vdev_is_concrete(vd))
5159*814dcd43SSerapheim Dimitropoulos 		return (0);
5160*814dcd43SSerapheim Dimitropoulos 
5161*814dcd43SSerapheim Dimitropoulos 	metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
5162*814dcd43SSerapheim Dimitropoulos 	ASSERT(sme->sme_type == SM_ALLOC || sme->sme_type == SM_FREE);
5163*814dcd43SSerapheim Dimitropoulos 
5164*814dcd43SSerapheim Dimitropoulos 	if (txg < metaslab_unflushed_txg(ms))
5165*814dcd43SSerapheim Dimitropoulos 		return (0);
5166*814dcd43SSerapheim Dimitropoulos 	lsos->lsos_valid_sm_entries++;
5167*814dcd43SSerapheim Dimitropoulos 	lsos->lsos_valid_entries++;
5168*814dcd43SSerapheim Dimitropoulos 	return (0);
5169*814dcd43SSerapheim Dimitropoulos }
5170*814dcd43SSerapheim Dimitropoulos 
5171*814dcd43SSerapheim Dimitropoulos static void
5172*814dcd43SSerapheim Dimitropoulos dump_log_spacemap_obsolete_stats(spa_t *spa)
5173*814dcd43SSerapheim Dimitropoulos {
5174*814dcd43SSerapheim Dimitropoulos 	if (!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))
5175*814dcd43SSerapheim Dimitropoulos 		return;
5176*814dcd43SSerapheim Dimitropoulos 
5177*814dcd43SSerapheim Dimitropoulos 	log_sm_obsolete_stats_arg_t lsos;
5178*814dcd43SSerapheim Dimitropoulos 	bzero(&lsos, sizeof (lsos));
5179*814dcd43SSerapheim Dimitropoulos 
5180*814dcd43SSerapheim Dimitropoulos 	(void) printf("Log Space Map Obsolete Entry Statistics:\n");
5181*814dcd43SSerapheim Dimitropoulos 
5182*814dcd43SSerapheim Dimitropoulos 	iterate_through_spacemap_logs(spa,
5183*814dcd43SSerapheim Dimitropoulos 	    log_spacemap_obsolete_stats_cb, &lsos);
5184*814dcd43SSerapheim Dimitropoulos 
5185*814dcd43SSerapheim Dimitropoulos 	/* print stats for latest log */
5186*814dcd43SSerapheim Dimitropoulos 	(void) printf("%-8llu valid entries out of %-8llu - txg %llu\n",
5187*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)lsos.lsos_valid_sm_entries,
5188*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)lsos.lsos_sm_entries,
5189*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)lsos.lsos_current_txg);
5190*814dcd43SSerapheim Dimitropoulos 
5191*814dcd43SSerapheim Dimitropoulos 	(void) printf("%-8llu valid entries out of %-8llu - total\n\n",
5192*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)lsos.lsos_valid_entries,
5193*814dcd43SSerapheim Dimitropoulos 	    (u_longlong_t)lsos.lsos_total_entries);
5194*814dcd43SSerapheim Dimitropoulos }
5195*814dcd43SSerapheim Dimitropoulos 
5196fa9e4066Sahrens static void
5197fa9e4066Sahrens dump_zpool(spa_t *spa)
5198fa9e4066Sahrens {
5199fa9e4066Sahrens 	dsl_pool_t *dp = spa_get_dsl(spa);
5200fa9e4066Sahrens 	int rc = 0;
5201fa9e4066Sahrens 
5202b24ab676SJeff Bonwick 	if (dump_opt['S']) {
5203b24ab676SJeff Bonwick 		dump_simulated_ddt(spa);
5204b24ab676SJeff Bonwick 		return;
5205b24ab676SJeff Bonwick 	}
5206b24ab676SJeff Bonwick 
520707428bdfSVictor Latushkin 	if (!dump_opt['e'] && dump_opt['C'] > 1) {
520807428bdfSVictor Latushkin 		(void) printf("\nCached configuration:\n");
520907428bdfSVictor Latushkin 		dump_nvlist(spa->spa_config, 8);
521007428bdfSVictor Latushkin 	}
521107428bdfSVictor Latushkin 
521207428bdfSVictor Latushkin 	if (dump_opt['C'])
521307428bdfSVictor Latushkin 		dump_config(spa);
521407428bdfSVictor Latushkin 
5215fa9e4066Sahrens 	if (dump_opt['u'])
521653b9a4a9SVictor Latushkin 		dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n");
5217fa9e4066Sahrens 
5218b24ab676SJeff Bonwick 	if (dump_opt['D'])
5219b24ab676SJeff Bonwick 		dump_all_ddts(spa);
5220b24ab676SJeff Bonwick 
522187219db7SVictor Latushkin 	if (dump_opt['d'] > 2 || dump_opt['m'])
522287219db7SVictor Latushkin 		dump_metaslabs(spa);
52232e4c9986SGeorge Wilson 	if (dump_opt['M'])
52242e4c9986SGeorge Wilson 		dump_metaslab_groups(spa);
5225*814dcd43SSerapheim Dimitropoulos 	if (dump_opt['d'] > 2 || dump_opt['m']) {
5226*814dcd43SSerapheim Dimitropoulos 		dump_log_spacemaps(spa);
5227*814dcd43SSerapheim Dimitropoulos 		dump_log_spacemap_obsolete_stats(spa);
5228*814dcd43SSerapheim Dimitropoulos 	}
522987219db7SVictor Latushkin 
523087219db7SVictor Latushkin 	if (dump_opt['d'] || dump_opt['i']) {
523117fb938fSMatthew Ahrens 		mos_refd_objs = range_tree_create(NULL, NULL);
5232fa9e4066Sahrens 		dump_dir(dp->dp_meta_objset);
523317fb938fSMatthew Ahrens 
5234fa9e4066Sahrens 		if (dump_opt['d'] >= 3) {
52355cabbc6bSPrashanth Sreenivasa 			dsl_pool_t *dp = spa->spa_dsl_pool;
5236732885fcSMatthew Ahrens 			dump_full_bpobj(&spa->spa_deferred_bpobj,
5237d0475637SMatthew Ahrens 			    "Deferred frees", 0);
5238cde58dbcSMatthew Ahrens 			if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
52395cabbc6bSPrashanth Sreenivasa 				dump_full_bpobj(&dp->dp_free_bpobj,
5240d0475637SMatthew Ahrens 				    "Pool snapshot frees", 0);
5241ad135b5dSChristopher Siden 			}
52425cabbc6bSPrashanth Sreenivasa 			if (bpobj_is_open(&dp->dp_obsolete_bpobj)) {
52435cabbc6bSPrashanth Sreenivasa 				ASSERT(spa_feature_is_enabled(spa,
52445cabbc6bSPrashanth Sreenivasa 				    SPA_FEATURE_DEVICE_REMOVAL));
52455cabbc6bSPrashanth Sreenivasa 				dump_full_bpobj(&dp->dp_obsolete_bpobj,
52465cabbc6bSPrashanth Sreenivasa 				    "Pool obsolete blocks", 0);
52475cabbc6bSPrashanth Sreenivasa 			}
5248ad135b5dSChristopher Siden 
5249ad135b5dSChristopher Siden 			if (spa_feature_is_active(spa,
52502acef22dSMatthew Ahrens 			    SPA_FEATURE_ASYNC_DESTROY)) {
5251ad135b5dSChristopher Siden 				dump_bptree(spa->spa_meta_objset,
52525cabbc6bSPrashanth Sreenivasa 				    dp->dp_bptree_obj,
5253ad135b5dSChristopher Siden 				    "Pool dataset frees");
5254cde58dbcSMatthew Ahrens 			}
5255fa9e4066Sahrens 			dump_dtl(spa->spa_root_vdev, 0);
5256fa9e4066Sahrens 		}
525707428bdfSVictor Latushkin 		(void) dmu_objset_find(spa_name(spa), dump_one_dir,
525807428bdfSVictor Latushkin 		    NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
5259b5152584SMatthew Ahrens 
526017fb938fSMatthew Ahrens 		if (rc == 0 && !dump_opt['L'])
526117fb938fSMatthew Ahrens 			rc = dump_mos_leaks(spa);
526217fb938fSMatthew Ahrens 
5263ca0cc391SMatthew Ahrens 		for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
5264ca0cc391SMatthew Ahrens 			uint64_t refcount;
5265ca0cc391SMatthew Ahrens 
5266ca0cc391SMatthew Ahrens 			if (!(spa_feature_table[f].fi_flags &
5267c5d1600cSMatthew Ahrens 			    ZFEATURE_FLAG_PER_DATASET) ||
5268c5d1600cSMatthew Ahrens 			    !spa_feature_is_enabled(spa, f)) {
5269ca0cc391SMatthew Ahrens 				ASSERT0(dataset_feature_count[f]);
5270ca0cc391SMatthew Ahrens 				continue;
5271ca0cc391SMatthew Ahrens 			}
5272ca0cc391SMatthew Ahrens 			(void) feature_get_refcount(spa,
5273ca0cc391SMatthew Ahrens 			    &spa_feature_table[f], &refcount);
5274ca0cc391SMatthew Ahrens 			if (dataset_feature_count[f] != refcount) {
5275ca0cc391SMatthew Ahrens 				(void) printf("%s feature refcount mismatch: "
5276ca0cc391SMatthew Ahrens 				    "%lld datasets != %lld refcount\n",
5277ca0cc391SMatthew Ahrens 				    spa_feature_table[f].fi_uname,
5278ca0cc391SMatthew Ahrens 				    (longlong_t)dataset_feature_count[f],
5279ca0cc391SMatthew Ahrens 				    (longlong_t)refcount);
5280ca0cc391SMatthew Ahrens 				rc = 2;
5281ca0cc391SMatthew Ahrens 			} else {
5282ca0cc391SMatthew Ahrens 				(void) printf("Verified %s feature refcount "
5283ca0cc391SMatthew Ahrens 				    "of %llu is correct\n",
5284ca0cc391SMatthew Ahrens 				    spa_feature_table[f].fi_uname,
5285ca0cc391SMatthew Ahrens 				    (longlong_t)refcount);
5286ca0cc391SMatthew Ahrens 			}
5287b5152584SMatthew Ahrens 		}
52885cabbc6bSPrashanth Sreenivasa 
5289*814dcd43SSerapheim Dimitropoulos 		if (rc == 0)
52905cabbc6bSPrashanth Sreenivasa 			rc = verify_device_removal_feature_counts(spa);
5291fa9e4066Sahrens 	}
529217fb938fSMatthew Ahrens 
5293b5152584SMatthew Ahrens 	if (rc == 0 && (dump_opt['b'] || dump_opt['c']))
5294fa9e4066Sahrens 		rc = dump_block_stats(spa);
5295fa9e4066Sahrens 
52960713e232SGeorge Wilson 	if (rc == 0)
52970713e232SGeorge Wilson 		rc = verify_spacemap_refcounts(spa);
52980713e232SGeorge Wilson 
5299fa9e4066Sahrens 	if (dump_opt['s'])
5300fa9e4066Sahrens 		show_pool_stats(spa);
5301fa9e4066Sahrens 
53028f18d1faSGeorge Wilson 	if (dump_opt['h'])
53038f18d1faSGeorge Wilson 		dump_history(spa);
53048f18d1faSGeorge Wilson 
530517f11284SSerapheim Dimitropoulos 	if (rc == 0)
530686714001SSerapheim Dimitropoulos 		rc = verify_checkpoint(spa);
530786714001SSerapheim Dimitropoulos 
530829bdd2f9SPavel Zakharov 	if (rc != 0) {
530929bdd2f9SPavel Zakharov 		dump_debug_buffer();
5310fa9e4066Sahrens 		exit(rc);
531129bdd2f9SPavel Zakharov 	}
5312fa9e4066Sahrens }
5313fa9e4066Sahrens 
531444cd46caSbillm #define	ZDB_FLAG_CHECKSUM	0x0001
531544cd46caSbillm #define	ZDB_FLAG_DECOMPRESS	0x0002
531644cd46caSbillm #define	ZDB_FLAG_BSWAP		0x0004
531744cd46caSbillm #define	ZDB_FLAG_GBH		0x0008
531844cd46caSbillm #define	ZDB_FLAG_INDIRECT	0x0010
531944cd46caSbillm #define	ZDB_FLAG_PHYS		0x0020
532044cd46caSbillm #define	ZDB_FLAG_RAW		0x0040
532144cd46caSbillm #define	ZDB_FLAG_PRINT_BLKPTR	0x0080
532244cd46caSbillm 
53233f7978d0SAlan Somers static int flagbits[256];
532444cd46caSbillm 
532544cd46caSbillm static void
532644cd46caSbillm zdb_print_blkptr(blkptr_t *bp, int flags)
532744cd46caSbillm {
5328b24ab676SJeff Bonwick 	char blkbuf[BP_SPRINTF_LEN];
532944cd46caSbillm 
533044cd46caSbillm 	if (flags & ZDB_FLAG_BSWAP)
533144cd46caSbillm 		byteswap_uint64_array((void *)bp, sizeof (blkptr_t));
5332b24ab676SJeff Bonwick 
533343466aaeSMax Grossman 	snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
5334b24ab676SJeff Bonwick 	(void) printf("%s\n", blkbuf);
533544cd46caSbillm }
533644cd46caSbillm 
533744cd46caSbillm static void
533844cd46caSbillm zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
533944cd46caSbillm {
534044cd46caSbillm 	int i;
534144cd46caSbillm 
534244cd46caSbillm 	for (i = 0; i < nbps; i++)
534344cd46caSbillm 		zdb_print_blkptr(&bp[i], flags);
534444cd46caSbillm }
534544cd46caSbillm 
534644cd46caSbillm static void
534744cd46caSbillm zdb_dump_gbh(void *buf, int flags)
534844cd46caSbillm {
534944cd46caSbillm 	zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
535044cd46caSbillm }
535144cd46caSbillm 
535244cd46caSbillm static void
535344cd46caSbillm zdb_dump_block_raw(void *buf, uint64_t size, int flags)
535444cd46caSbillm {
535544cd46caSbillm 	if (flags & ZDB_FLAG_BSWAP)
535644cd46caSbillm 		byteswap_uint64_array(buf, size);
5357b24ab676SJeff Bonwick 	(void) write(1, buf, size);
535844cd46caSbillm }
535944cd46caSbillm 
536044cd46caSbillm static void
536144cd46caSbillm zdb_dump_block(char *label, void *buf, uint64_t size, int flags)
536244cd46caSbillm {
536344cd46caSbillm 	uint64_t *d = (uint64_t *)buf;
53643f7978d0SAlan Somers 	unsigned nwords = size / sizeof (uint64_t);
536544cd46caSbillm 	int do_bswap = !!(flags & ZDB_FLAG_BSWAP);
53663f7978d0SAlan Somers 	unsigned i, j;
53673f7978d0SAlan Somers 	const char *hdr;
53683f7978d0SAlan Somers 	char *c;
536944cd46caSbillm 
537044cd46caSbillm 
537144cd46caSbillm 	if (do_bswap)
537244cd46caSbillm 		hdr = " 7 6 5 4 3 2 1 0   f e d c b a 9 8";
537344cd46caSbillm 	else
537444cd46caSbillm 		hdr = " 0 1 2 3 4 5 6 7   8 9 a b c d e f";
537544cd46caSbillm 
537644cd46caSbillm 	(void) printf("\n%s\n%6s   %s  0123456789abcdef\n", label, "", hdr);
537744cd46caSbillm 
537844cd46caSbillm 	for (i = 0; i < nwords; i += 2) {
537944cd46caSbillm 		(void) printf("%06llx:  %016llx  %016llx  ",
538044cd46caSbillm 		    (u_longlong_t)(i * sizeof (uint64_t)),
538144cd46caSbillm 		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i]) : d[i]),
538244cd46caSbillm 		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i + 1]) : d[i + 1]));
538344cd46caSbillm 
538444cd46caSbillm 		c = (char *)&d[i];
538544cd46caSbillm 		for (j = 0; j < 2 * sizeof (uint64_t); j++)
538644cd46caSbillm 			(void) printf("%c", isprint(c[j]) ? c[j] : '.');
538744cd46caSbillm 		(void) printf("\n");
538844cd46caSbillm 	}
538944cd46caSbillm }
539044cd46caSbillm 
539144cd46caSbillm /*
539244cd46caSbillm  * There are two acceptable formats:
539344cd46caSbillm  *	leaf_name	  - For example: c1t0d0 or /tmp/ztest.0a
539444cd46caSbillm  *	child[.child]*    - For example: 0.1.1
539544cd46caSbillm  *
539644cd46caSbillm  * The second form can be used to specify arbitrary vdevs anywhere
539744cd46caSbillm  * in the heirarchy.  For example, in a pool with a mirror of
539844cd46caSbillm  * RAID-Zs, you can specify either RAID-Z vdev with 0.0 or 0.1 .
539944cd46caSbillm  */
540044cd46caSbillm static vdev_t *
54013f7978d0SAlan Somers zdb_vdev_lookup(vdev_t *vdev, const char *path)
540244cd46caSbillm {
540344cd46caSbillm 	char *s, *p, *q;
54043f7978d0SAlan Somers 	unsigned i;
540544cd46caSbillm 
540644cd46caSbillm 	if (vdev == NULL)
540744cd46caSbillm 		return (NULL);
540844cd46caSbillm 
540944cd46caSbillm 	/* First, assume the x.x.x.x format */
54103f7978d0SAlan Somers 	i = strtoul(path, &s, 10);
541144cd46caSbillm 	if (s == path || (s && *s != '.' && *s != '\0'))
541244cd46caSbillm 		goto name;
54133f7978d0SAlan Somers 	if (i >= vdev->vdev_children)
541444cd46caSbillm 		return (NULL);
541544cd46caSbillm 
541644cd46caSbillm 	vdev = vdev->vdev_child[i];
541744cd46caSbillm 	if (*s == '\0')
541844cd46caSbillm 		return (vdev);
541944cd46caSbillm 	return (zdb_vdev_lookup(vdev, s+1));
542044cd46caSbillm 
542144cd46caSbillm name:
542244cd46caSbillm 	for (i = 0; i < vdev->vdev_children; i++) {
542344cd46caSbillm 		vdev_t *vc = vdev->vdev_child[i];
542444cd46caSbillm 
542544cd46caSbillm 		if (vc->vdev_path == NULL) {
542644cd46caSbillm 			vc = zdb_vdev_lookup(vc, path);
542744cd46caSbillm 			if (vc == NULL)
542844cd46caSbillm 				continue;
542944cd46caSbillm 			else
543044cd46caSbillm 				return (vc);
543144cd46caSbillm 		}
543244cd46caSbillm 
543344cd46caSbillm 		p = strrchr(vc->vdev_path, '/');
543444cd46caSbillm 		p = p ? p + 1 : vc->vdev_path;
543544cd46caSbillm 		q = &vc->vdev_path[strlen(vc->vdev_path) - 2];
543644cd46caSbillm 
543744cd46caSbillm 		if (strcmp(vc->vdev_path, path) == 0)
543844cd46caSbillm 			return (vc);
543944cd46caSbillm 		if (strcmp(p, path) == 0)
544044cd46caSbillm 			return (vc);
544144cd46caSbillm 		if (strcmp(q, "s0") == 0 && strncmp(p, path, q - p) == 0)
544244cd46caSbillm 			return (vc);
544344cd46caSbillm 	}
544444cd46caSbillm 
544544cd46caSbillm 	return (NULL);
544644cd46caSbillm }
544744cd46caSbillm 
5448770499e1SDan Kimmel /* ARGSUSED */
5449770499e1SDan Kimmel static int
5450770499e1SDan Kimmel random_get_pseudo_bytes_cb(void *buf, size_t len, void *unused)
5451770499e1SDan Kimmel {
5452770499e1SDan Kimmel 	return (random_get_pseudo_bytes(buf, len));
5453770499e1SDan Kimmel }
5454770499e1SDan Kimmel 
545544cd46caSbillm /*
545644cd46caSbillm  * Read a block from a pool and print it out.  The syntax of the
545744cd46caSbillm  * block descriptor is:
545844cd46caSbillm  *
545944cd46caSbillm  *	pool:vdev_specifier:offset:size[:flags]
546044cd46caSbillm  *
546144cd46caSbillm  *	pool           - The name of the pool you wish to read from
546244cd46caSbillm  *	vdev_specifier - Which vdev (see comment for zdb_vdev_lookup)
546344cd46caSbillm  *	offset         - offset, in hex, in bytes
546444cd46caSbillm  *	size           - Amount of data to read, in hex, in bytes
546544cd46caSbillm  *	flags          - A string of characters specifying options
546644cd46caSbillm  *		 b: Decode a blkptr at given offset within block
546744cd46caSbillm  *		*c: Calculate and display checksums
5468b24ab676SJeff Bonwick  *		 d: Decompress data before dumping
546944cd46caSbillm  *		 e: Byteswap data before dumping
5470b24ab676SJeff Bonwick  *		 g: Display data as a gang block header
5471b24ab676SJeff Bonwick  *		 i: Display as an indirect block
547244cd46caSbillm  *		 p: Do I/O to physical offset
547344cd46caSbillm  *		 r: Dump raw data to stdout
547444cd46caSbillm  *
547544cd46caSbillm  *              * = not yet implemented
547644cd46caSbillm  */
547744cd46caSbillm static void
547807428bdfSVictor Latushkin zdb_read_block(char *thing, spa_t *spa)
547944cd46caSbillm {
5480b24ab676SJeff Bonwick 	blkptr_t blk, *bp = &blk;
5481b24ab676SJeff Bonwick 	dva_t *dva = bp->blk_dva;
548244cd46caSbillm 	int flags = 0;
5483b24ab676SJeff Bonwick 	uint64_t offset = 0, size = 0, psize = 0, lsize = 0, blkptr_offset = 0;
548444cd46caSbillm 	zio_t *zio;
548544cd46caSbillm 	vdev_t *vd;
5486770499e1SDan Kimmel 	abd_t *pabd;
5487770499e1SDan Kimmel 	void *lbuf, *buf;
54883f7978d0SAlan Somers 	const char *s, *vdev;
54893f7978d0SAlan Somers 	char *p, *dup, *flagstr;
5490b24ab676SJeff Bonwick 	int i, error;
549144cd46caSbillm 
549244cd46caSbillm 	dup = strdup(thing);
549344cd46caSbillm 	s = strtok(dup, ":");
549444cd46caSbillm 	vdev = s ? s : "";
549544cd46caSbillm 	s = strtok(NULL, ":");
549644cd46caSbillm 	offset = strtoull(s ? s : "", NULL, 16);
549744cd46caSbillm 	s = strtok(NULL, ":");
549844cd46caSbillm 	size = strtoull(s ? s : "", NULL, 16);
549944cd46caSbillm 	s = strtok(NULL, ":");
55003f7978d0SAlan Somers 	if (s)
55013f7978d0SAlan Somers 		flagstr = strdup(s);
55023f7978d0SAlan Somers 	else
55033f7978d0SAlan Somers 		flagstr = strdup("");
550444cd46caSbillm 
550544cd46caSbillm 	s = NULL;
550644cd46caSbillm 	if (size == 0)
550744cd46caSbillm 		s = "size must not be zero";
550844cd46caSbillm 	if (!IS_P2ALIGNED(size, DEV_BSIZE))
550944cd46caSbillm 		s = "size must be a multiple of sector size";
551044cd46caSbillm 	if (!IS_P2ALIGNED(offset, DEV_BSIZE))
551144cd46caSbillm 		s = "offset must be a multiple of sector size";
551244cd46caSbillm 	if (s) {
551344cd46caSbillm 		(void) printf("Invalid block specifier: %s  - %s\n", thing, s);
551444cd46caSbillm 		free(dup);
551544cd46caSbillm 		return;
551644cd46caSbillm 	}
551744cd46caSbillm 
551844cd46caSbillm 	for (s = strtok(flagstr, ":"); s; s = strtok(NULL, ":")) {
551944cd46caSbillm 		for (i = 0; flagstr[i]; i++) {
55205ad82045Snd 			int bit = flagbits[(uchar_t)flagstr[i]];
552144cd46caSbillm 
552244cd46caSbillm 			if (bit == 0) {
552344cd46caSbillm 				(void) printf("***Invalid flag: %c\n",
552444cd46caSbillm 				    flagstr[i]);
552544cd46caSbillm 				continue;
552644cd46caSbillm 			}
552744cd46caSbillm 			flags |= bit;
552844cd46caSbillm 
552944cd46caSbillm 			/* If it's not something with an argument, keep going */
5530b24ab676SJeff Bonwick 			if ((bit & (ZDB_FLAG_CHECKSUM |
553144cd46caSbillm 			    ZDB_FLAG_PRINT_BLKPTR)) == 0)
553244cd46caSbillm 				continue;
553344cd46caSbillm 
553444cd46caSbillm 			p = &flagstr[i + 1];
553544cd46caSbillm 			if (bit == ZDB_FLAG_PRINT_BLKPTR)
553644cd46caSbillm 				blkptr_offset = strtoull(p, &p, 16);
553744cd46caSbillm 			if (*p != ':' && *p != '\0') {
553844cd46caSbillm 				(void) printf("***Invalid flag arg: '%s'\n", s);
553944cd46caSbillm 				free(dup);
554044cd46caSbillm 				return;
554144cd46caSbillm 			}
554244cd46caSbillm 		}
554344cd46caSbillm 	}
55443f7978d0SAlan Somers 	free(flagstr);
554544cd46caSbillm 
554644cd46caSbillm 	vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev);
554744cd46caSbillm 	if (vd == NULL) {
554844cd46caSbillm 		(void) printf("***Invalid vdev: %s\n", vdev);
554944cd46caSbillm 		free(dup);
555044cd46caSbillm 		return;
555144cd46caSbillm 	} else {
555244cd46caSbillm 		if (vd->vdev_path)
5553b24ab676SJeff Bonwick 			(void) fprintf(stderr, "Found vdev: %s\n",
5554b24ab676SJeff Bonwick 			    vd->vdev_path);
555544cd46caSbillm 		else
5556b24ab676SJeff Bonwick 			(void) fprintf(stderr, "Found vdev type: %s\n",
555744cd46caSbillm 			    vd->vdev_ops->vdev_op_type);
555844cd46caSbillm 	}
555944cd46caSbillm 
5560b24ab676SJeff Bonwick 	psize = size;
5561b24ab676SJeff Bonwick 	lsize = size;
556244cd46caSbillm 
5563770499e1SDan Kimmel 	pabd = abd_alloc_linear(SPA_MAXBLOCKSIZE, B_FALSE);
5564b24ab676SJeff Bonwick 	lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
5565b24ab676SJeff Bonwick 
5566b24ab676SJeff Bonwick 	BP_ZERO(bp);
5567b24ab676SJeff Bonwick 
5568b24ab676SJeff Bonwick 	DVA_SET_VDEV(&dva[0], vd->vdev_id);
5569b24ab676SJeff Bonwick 	DVA_SET_OFFSET(&dva[0], offset);
5570b24ab676SJeff Bonwick 	DVA_SET_GANG(&dva[0], !!(flags & ZDB_FLAG_GBH));
5571b24ab676SJeff Bonwick 	DVA_SET_ASIZE(&dva[0], vdev_psize_to_asize(vd, psize));
5572b24ab676SJeff Bonwick 
5573b24ab676SJeff Bonwick 	BP_SET_BIRTH(bp, TXG_INITIAL, TXG_INITIAL);
5574b24ab676SJeff Bonwick 
5575b24ab676SJeff Bonwick 	BP_SET_LSIZE(bp, lsize);
5576b24ab676SJeff Bonwick 	BP_SET_PSIZE(bp, psize);
5577b24ab676SJeff Bonwick 	BP_SET_COMPRESS(bp, ZIO_COMPRESS_OFF);
5578b24ab676SJeff Bonwick 	BP_SET_CHECKSUM(bp, ZIO_CHECKSUM_OFF);
5579b24ab676SJeff Bonwick 	BP_SET_TYPE(bp, DMU_OT_NONE);
5580b24ab676SJeff Bonwick 	BP_SET_LEVEL(bp, 0);
5581b24ab676SJeff Bonwick 	BP_SET_DEDUP(bp, 0);
5582b24ab676SJeff Bonwick 	BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
558344cd46caSbillm 
5584e14bb325SJeff Bonwick 	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
558544cd46caSbillm 	zio = zio_root(spa, NULL, NULL, 0);
5586b24ab676SJeff Bonwick 
5587b24ab676SJeff Bonwick 	if (vd == vd->vdev_top) {
5588b24ab676SJeff Bonwick 		/*
5589b24ab676SJeff Bonwick 		 * Treat this as a normal block read.
5590b24ab676SJeff Bonwick 		 */
5591770499e1SDan Kimmel 		zio_nowait(zio_read(zio, spa, bp, pabd, psize, NULL, NULL,
5592b24ab676SJeff Bonwick 		    ZIO_PRIORITY_SYNC_READ,
5593b24ab676SJeff Bonwick 		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL));
5594b24ab676SJeff Bonwick 	} else {
5595b24ab676SJeff Bonwick 		/*
5596b24ab676SJeff Bonwick 		 * Treat this as a vdev child I/O.
5597b24ab676SJeff Bonwick 		 */
5598770499e1SDan Kimmel 		zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pabd,
5599770499e1SDan Kimmel 		    psize, ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ,
5600b24ab676SJeff Bonwick 		    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE |
5601b24ab676SJeff Bonwick 		    ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
56025cabbc6bSPrashanth Sreenivasa 		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW | ZIO_FLAG_OPTIONAL,
56035cabbc6bSPrashanth Sreenivasa 		    NULL, NULL));
5604b24ab676SJeff Bonwick 	}
5605b24ab676SJeff Bonwick 
560644cd46caSbillm 	error = zio_wait(zio);
5607e14bb325SJeff Bonwick 	spa_config_exit(spa, SCL_STATE, FTAG);
560844cd46caSbillm 
560944cd46caSbillm 	if (error) {
561044cd46caSbillm 		(void) printf("Read of %s failed, error: %d\n", thing, error);
561144cd46caSbillm 		goto out;
561244cd46caSbillm 	}
561344cd46caSbillm 
5614b24ab676SJeff Bonwick 	if (flags & ZDB_FLAG_DECOMPRESS) {
5615b24ab676SJeff Bonwick 		/*
5616b24ab676SJeff Bonwick 		 * We don't know how the data was compressed, so just try
5617b24ab676SJeff Bonwick 		 * every decompress function at every inflated blocksize.
5618b24ab676SJeff Bonwick 		 */
5619b24ab676SJeff Bonwick 		enum zio_compress c;
5620b24ab676SJeff Bonwick 		void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
5621b24ab676SJeff Bonwick 		void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
5622b24ab676SJeff Bonwick 
5623770499e1SDan Kimmel 		abd_copy_to_buf(pbuf2, pabd, psize);
5624b24ab676SJeff Bonwick 
5625770499e1SDan Kimmel 		VERIFY0(abd_iterate_func(pabd, psize, SPA_MAXBLOCKSIZE - psize,
5626770499e1SDan Kimmel 		    random_get_pseudo_bytes_cb, NULL));
5627b24ab676SJeff Bonwick 
5628770499e1SDan Kimmel 		VERIFY0(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize,
5629770499e1SDan Kimmel 		    SPA_MAXBLOCKSIZE - psize));
5630b24ab676SJeff Bonwick 
5631b24ab676SJeff Bonwick 		for (lsize = SPA_MAXBLOCKSIZE; lsize > psize;
5632b24ab676SJeff Bonwick 		    lsize -= SPA_MINBLOCKSIZE) {
5633b24ab676SJeff Bonwick 			for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) {
5634770499e1SDan Kimmel 				if (zio_decompress_data(c, pabd,
5635770499e1SDan Kimmel 				    lbuf, psize, lsize) == 0 &&
5636770499e1SDan Kimmel 				    zio_decompress_data_buf(c, pbuf2,
5637770499e1SDan Kimmel 				    lbuf2, psize, lsize) == 0 &&
5638b24ab676SJeff Bonwick 				    bcmp(lbuf, lbuf2, lsize) == 0)
5639b24ab676SJeff Bonwick 					break;
5640b24ab676SJeff Bonwick 			}
5641b24ab676SJeff Bonwick 			if (c != ZIO_COMPRESS_FUNCTIONS)
5642b24ab676SJeff Bonwick 				break;
5643b24ab676SJeff Bonwick 			lsize -= SPA_MINBLOCKSIZE;
5644b24ab676SJeff Bonwick 		}
5645b24ab676SJeff Bonwick 
5646b24ab676SJeff Bonwick 		umem_free(pbuf2, SPA_MAXBLOCKSIZE);
5647b24ab676SJeff Bonwick 		umem_free(lbuf2, SPA_MAXBLOCKSIZE);
5648b24ab676SJeff Bonwick 
5649b24ab676SJeff Bonwick 		if (lsize <= psize) {
5650b24ab676SJeff Bonwick 			(void) printf("Decompress of %s failed\n", thing);
5651b24ab676SJeff Bonwick 			goto out;
5652b24ab676SJeff Bonwick 		}
5653b24ab676SJeff Bonwick 		buf = lbuf;
5654b24ab676SJeff Bonwick 		size = lsize;
5655b24ab676SJeff Bonwick 	} else {
5656770499e1SDan Kimmel 		buf = abd_to_buf(pabd);
5657b24ab676SJeff Bonwick 		size = psize;
5658b24ab676SJeff Bonwick 	}
5659b24ab676SJeff Bonwick 
566044cd46caSbillm 	if (flags & ZDB_FLAG_PRINT_BLKPTR)
566144cd46caSbillm 		zdb_print_blkptr((blkptr_t *)(void *)
566244cd46caSbillm 		    ((uintptr_t)buf + (uintptr_t)blkptr_offset), flags);
566344cd46caSbillm 	else if (flags & ZDB_FLAG_RAW)
566444cd46caSbillm 		zdb_dump_block_raw(buf, size, flags);
566544cd46caSbillm 	else if (flags & ZDB_FLAG_INDIRECT)
566644cd46caSbillm 		zdb_dump_indirect((blkptr_t *)buf, size / sizeof (blkptr_t),
566744cd46caSbillm 		    flags);
566844cd46caSbillm 	else if (flags & ZDB_FLAG_GBH)
566944cd46caSbillm 		zdb_dump_gbh(buf, flags);
567044cd46caSbillm 	else
567144cd46caSbillm 		zdb_dump_block(thing, buf, size, flags);
567244cd46caSbillm 
567344cd46caSbillm out:
5674770499e1SDan Kimmel 	abd_free(pabd);
5675b24ab676SJeff Bonwick 	umem_free(lbuf, SPA_MAXBLOCKSIZE);
567644cd46caSbillm 	free(dup);
567744cd46caSbillm }
567844cd46caSbillm 
56794923c69fSMatthew Ahrens static void
56804923c69fSMatthew Ahrens zdb_embedded_block(char *thing)
56814923c69fSMatthew Ahrens {
56823f7978d0SAlan Somers 	blkptr_t bp;
56834923c69fSMatthew Ahrens 	unsigned long long *words = (void *)&bp;
568403a4c2f4SJorgen Lundman 	char *buf;
56854923c69fSMatthew Ahrens 	int err;
56864923c69fSMatthew Ahrens 
56873f7978d0SAlan Somers 	bzero(&bp, sizeof (bp));
56884923c69fSMatthew Ahrens 	err = sscanf(thing, "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx:"
56894923c69fSMatthew Ahrens 	    "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx",
56904923c69fSMatthew Ahrens 	    words + 0, words + 1, words + 2, words + 3,
56914923c69fSMatthew Ahrens 	    words + 4, words + 5, words + 6, words + 7,
56924923c69fSMatthew Ahrens 	    words + 8, words + 9, words + 10, words + 11,
56934923c69fSMatthew Ahrens 	    words + 12, words + 13, words + 14, words + 15);
56944923c69fSMatthew Ahrens 	if (err != 16) {
569503a4c2f4SJorgen Lundman 		(void) fprintf(stderr, "invalid input format\n");
56964923c69fSMatthew Ahrens 		exit(1);
56974923c69fSMatthew Ahrens 	}
56984923c69fSMatthew Ahrens 	ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
569903a4c2f4SJorgen Lundman 	buf = malloc(SPA_MAXBLOCKSIZE);
570003a4c2f4SJorgen Lundman 	if (buf == NULL) {
570103a4c2f4SJorgen Lundman 		(void) fprintf(stderr, "out of memory\n");
570203a4c2f4SJorgen Lundman 		exit(1);
570303a4c2f4SJorgen Lundman 	}
57044923c69fSMatthew Ahrens 	err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
57054923c69fSMatthew Ahrens 	if (err != 0) {
570603a4c2f4SJorgen Lundman 		(void) fprintf(stderr, "decode failed: %u\n", err);
57074923c69fSMatthew Ahrens 		exit(1);
57084923c69fSMatthew Ahrens 	}
57094923c69fSMatthew Ahrens 	zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
571003a4c2f4SJorgen Lundman 	free(buf);
57114923c69fSMatthew Ahrens }
57124923c69fSMatthew Ahrens 
5713fa9e4066Sahrens int
5714fa9e4066Sahrens main(int argc, char **argv)
5715fa9e4066Sahrens {
57163f7978d0SAlan Somers 	int c;
5717fa9e4066Sahrens 	struct rlimit rl = { 1024, 1024 };
57183ad6c7f9SVictor Latushkin 	spa_t *spa = NULL;
5719fa9e4066Sahrens 	objset_t *os = NULL;
5720fa9e4066Sahrens 	int dump_all = 1;
5721fa9e4066Sahrens 	int verbose = 0;
5722c8ee1847SVictor Latushkin 	int error = 0;
57233ad6c7f9SVictor Latushkin 	char **searchdirs = NULL;
57243ad6c7f9SVictor Latushkin 	int nsearch = 0;
5725e0f1c0afSOlaf Faaland 	char *target, *target_pool;
5726468c413aSTim Haley 	nvlist_t *policy = NULL;
5727468c413aSTim Haley 	uint64_t max_txg = UINT64_MAX;
5728dfd5965fSRichard Yao 	int flags = ZFS_IMPORT_MISSING_LOG;
5729c8ee1847SVictor Latushkin 	int rewind = ZPOOL_NEVER_REWIND;
5730ae24175bSCyril Plisko 	char *spa_config_path_env;
5731b702644aSTim Chase 	boolean_t target_is_spa = B_TRUE;
573286714001SSerapheim Dimitropoulos 	nvlist_t *cfg = NULL;
5733fa9e4066Sahrens 
5734fa9e4066Sahrens 	(void) setrlimit(RLIMIT_NOFILE, &rl);
5735004388ebScasper 	(void) enable_extended_FILE_stdio(-1, -1);
5736fa9e4066Sahrens 
5737fa9e4066Sahrens 	dprintf_setup(&argc, argv);
5738fa9e4066Sahrens 
5739ae24175bSCyril Plisko 	/*
5740ae24175bSCyril Plisko 	 * If there is an environment variable SPA_CONFIG_PATH it overrides
5741ae24175bSCyril Plisko 	 * default spa_config_path setting. If -U flag is specified it will
5742ae24175bSCyril Plisko 	 * override this environment variable settings once again.
5743ae24175bSCyril Plisko 	 */
5744ae24175bSCyril Plisko 	spa_config_path_env = getenv("SPA_CONFIG_PATH");
5745ae24175bSCyril Plisko 	if (spa_config_path_env != NULL)
5746ae24175bSCyril Plisko 		spa_config_path = spa_config_path_env;
5747ae24175bSCyril Plisko 
5748df15e419SMatthew Ahrens 	while ((c = getopt(argc, argv,
574986714001SSerapheim Dimitropoulos 	    "AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
5750fa9e4066Sahrens 		switch (c) {
5751fa9e4066Sahrens 		case 'b':
5752fa9e4066Sahrens 		case 'c':
5753ed61ec1dSYuri Pankov 		case 'C':
5754b24ab676SJeff Bonwick 		case 'd':
5755ed61ec1dSYuri Pankov 		case 'D':
57564923c69fSMatthew Ahrens 		case 'E':
5757ed61ec1dSYuri Pankov 		case 'G':
5758b24ab676SJeff Bonwick 		case 'h':
5759b24ab676SJeff Bonwick 		case 'i':
5760b24ab676SJeff Bonwick 		case 'l':
5761d6e555bdSGeorge Wilson 		case 'm':
57622e4c9986SGeorge Wilson 		case 'M':
5763ed61ec1dSYuri Pankov 		case 'O':
576444cd46caSbillm 		case 'R':
5765ed61ec1dSYuri Pankov 		case 's':
5766b24ab676SJeff Bonwick 		case 'S':
5767ed61ec1dSYuri Pankov 		case 'u':
5768fa9e4066Sahrens 			dump_opt[c]++;
5769fa9e4066Sahrens 			dump_all = 0;
5770fa9e4066Sahrens 			break;
5771feef89cfSVictor Latushkin 		case 'A':
5772ed61ec1dSYuri Pankov 		case 'e':
5773c8ee1847SVictor Latushkin 		case 'F':
577486714001SSerapheim Dimitropoulos 		case 'k':
577582a0a985SVictor Latushkin 		case 'L':
57763f9d6ad7SLin Ling 		case 'P':
577764723e36SYuri Pankov 		case 'q':
5778ed61ec1dSYuri Pankov 		case 'X':
577982a0a985SVictor Latushkin 			dump_opt[c]++;
578082a0a985SVictor Latushkin 			break;
5781ed61ec1dSYuri Pankov 		/* NB: Sort single match options below. */
57822e4c9986SGeorge Wilson 		case 'I':
578331d7e8faSGeorge Wilson 			max_inflight = strtoull(optarg, NULL, 0);
578431d7e8faSGeorge Wilson 			if (max_inflight == 0) {
578531d7e8faSGeorge Wilson 				(void) fprintf(stderr, "maximum number "
578631d7e8faSGeorge Wilson 				    "of inflight I/Os must be greater "
578731d7e8faSGeorge Wilson 				    "than 0\n");
578831d7e8faSGeorge Wilson 				usage();
578931d7e8faSGeorge Wilson 			}
579031d7e8faSGeorge Wilson 			break;
5791ed61ec1dSYuri Pankov 		case 'o':
5792ed61ec1dSYuri Pankov 			error = set_global_var(optarg);
5793ed61ec1dSYuri Pankov 			if (error != 0)
5794ed61ec1dSYuri Pankov 				usage();
5795ed61ec1dSYuri Pankov 			break;
5796de6628f0Sck 		case 'p':
57973ad6c7f9SVictor Latushkin 			if (searchdirs == NULL) {
57983ad6c7f9SVictor Latushkin 				searchdirs = umem_alloc(sizeof (char *),
57993ad6c7f9SVictor Latushkin 				    UMEM_NOFAIL);
58003ad6c7f9SVictor Latushkin 			} else {
58013ad6c7f9SVictor Latushkin 				char **tmp = umem_alloc((nsearch + 1) *
58023ad6c7f9SVictor Latushkin 				    sizeof (char *), UMEM_NOFAIL);
58033ad6c7f9SVictor Latushkin 				bcopy(searchdirs, tmp, nsearch *
58043ad6c7f9SVictor Latushkin 				    sizeof (char *));
58053ad6c7f9SVictor Latushkin 				umem_free(searchdirs,
58063ad6c7f9SVictor Latushkin 				    nsearch * sizeof (char *));
58073ad6c7f9SVictor Latushkin 				searchdirs = tmp;
58083ad6c7f9SVictor Latushkin 			}
58093ad6c7f9SVictor Latushkin 			searchdirs[nsearch++] = optarg;
5810de6628f0Sck 			break;
58112e551927SVictor Latushkin 		case 't':
5812468c413aSTim Haley 			max_txg = strtoull(optarg, NULL, 0);
5813468c413aSTim Haley 			if (max_txg < TXG_INITIAL) {
58142e551927SVictor Latushkin 				(void) fprintf(stderr, "incorrect txg "
58152e551927SVictor Latushkin 				    "specified: %s\n", optarg);
58162e551927SVictor Latushkin 				usage();
58172e551927SVictor Latushkin 			}
58182e551927SVictor Latushkin 			break;
5819b24ab676SJeff Bonwick 		case 'U':
5820b24ab676SJeff Bonwick 			spa_config_path = optarg;
58214923c69fSMatthew Ahrens 			if (spa_config_path[0] != '/') {
58224923c69fSMatthew Ahrens 				(void) fprintf(stderr,
58234923c69fSMatthew Ahrens 				    "cachefile must be an absolute path "
58244923c69fSMatthew Ahrens 				    "(i.e. start with a slash)\n");
58254923c69fSMatthew Ahrens 				usage();
58264923c69fSMatthew Ahrens 			}
5827b24ab676SJeff Bonwick 			break;
58282e4c9986SGeorge Wilson 		case 'v':
58292e4c9986SGeorge Wilson 			verbose++;
58302e4c9986SGeorge Wilson 			break;
5831dfd5965fSRichard Yao 		case 'V':
5832dfd5965fSRichard Yao 			flags = ZFS_IMPORT_VERBATIM;
5833dfd5965fSRichard Yao 			break;
58342e4c9986SGeorge Wilson 		case 'x':
58352e4c9986SGeorge Wilson 			vn_dumpdir = optarg;
58362e4c9986SGeorge Wilson 			break;
5837fa9e4066Sahrens 		default:
5838fa9e4066Sahrens 			usage();
5839fa9e4066Sahrens 			break;
5840fa9e4066Sahrens 		}
5841fa9e4066Sahrens 	}
5842fa9e4066Sahrens 
58433ad6c7f9SVictor Latushkin 	if (!dump_opt['e'] && searchdirs != NULL) {
584488b7b0f2SMatthew Ahrens 		(void) fprintf(stderr, "-p option requires use of -e\n");
584588b7b0f2SMatthew Ahrens 		usage();
584688b7b0f2SMatthew Ahrens 	}
5847de6628f0Sck 
584806be9802SMatthew Ahrens 	/*
584906be9802SMatthew Ahrens 	 * ZDB does not typically re-read blocks; therefore limit the ARC
585006be9802SMatthew Ahrens 	 * to 256 MB, which can be used entirely for metadata.
585106be9802SMatthew Ahrens 	 */
585206be9802SMatthew Ahrens 	zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
585306be9802SMatthew Ahrens 
5854f7950bf1SMatthew Ahrens 	/*
5855f7950bf1SMatthew Ahrens 	 * "zdb -c" uses checksum-verifying scrub i/os which are async reads.
5856f7950bf1SMatthew Ahrens 	 * "zdb -b" uses traversal prefetch which uses async reads.
5857f7950bf1SMatthew Ahrens 	 * For good performance, let several of them be active at once.
5858f7950bf1SMatthew Ahrens 	 */
5859f7950bf1SMatthew Ahrens 	zfs_vdev_async_read_max_active = 10;
5860f7950bf1SMatthew Ahrens 
58614dd77f9eSMatthew Ahrens 	/*
58624dd77f9eSMatthew Ahrens 	 * Disable reference tracking for better performance.
58634dd77f9eSMatthew Ahrens 	 */
58644dd77f9eSMatthew Ahrens 	reference_tracking_enable = B_FALSE;
58654dd77f9eSMatthew Ahrens 
5866e144c4e6SPavel Zakharov 	/*
5867e144c4e6SPavel Zakharov 	 * Do not fail spa_load when spa_load_verify fails. This is needed
5868e144c4e6SPavel Zakharov 	 * to load non-idle pools.
5869e144c4e6SPavel Zakharov 	 */
5870e144c4e6SPavel Zakharov 	spa_load_verify_dryrun = B_TRUE;
5871e144c4e6SPavel Zakharov 
5872fa9e4066Sahrens 	kernel_init(FREAD);
5873de6628f0Sck 	g_zfs = libzfs_init();
587491ebeef5Sahrens 	ASSERT(g_zfs != NULL);
5875fa9e4066Sahrens 
5876b24ab676SJeff Bonwick 	if (dump_all)
5877b24ab676SJeff Bonwick 		verbose = MAX(verbose, 1);
5878b24ab676SJeff Bonwick 
5879fa9e4066Sahrens 	for (c = 0; c < 256; c++) {
588086714001SSerapheim Dimitropoulos 		if (dump_all && strchr("AeEFklLOPRSX", c) == NULL)
5881fa9e4066Sahrens 			dump_opt[c] = 1;
5882fa9e4066Sahrens 		if (dump_opt[c])
5883fa9e4066Sahrens 			dump_opt[c] += verbose;
5884fa9e4066Sahrens 	}
5885fa9e4066Sahrens 
5886feef89cfSVictor Latushkin 	aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2);
5887feef89cfSVictor Latushkin 	zfs_recover = (dump_opt['A'] > 1);
5888feef89cfSVictor Latushkin 
5889fa9e4066Sahrens 	argc -= optind;
5890fa9e4066Sahrens 	argv += optind;
5891fa9e4066Sahrens 
589207428bdfSVictor Latushkin 	if (argc < 2 && dump_opt['R'])
589307428bdfSVictor Latushkin 		usage();
58944923c69fSMatthew Ahrens 
58954923c69fSMatthew Ahrens 	if (dump_opt['E']) {
58964923c69fSMatthew Ahrens 		if (argc != 1)
58974923c69fSMatthew Ahrens 			usage();
58984923c69fSMatthew Ahrens 		zdb_embedded_block(argv[0]);
58994923c69fSMatthew Ahrens 		return (0);
59004923c69fSMatthew Ahrens 	}
59014923c69fSMatthew Ahrens 
5902fa9e4066Sahrens 	if (argc < 1) {
59033ad6c7f9SVictor Latushkin 		if (!dump_opt['e'] && dump_opt['C']) {
5904e829d913Sck 			dump_cachefile(spa_config_path);
5905fa9e4066Sahrens 			return (0);
5906fa9e4066Sahrens 		}
5907fa9e4066Sahrens 		usage();
5908fa9e4066Sahrens 	}
5909fa9e4066Sahrens 
591064723e36SYuri Pankov 	if (dump_opt['l'])
591164723e36SYuri Pankov 		return (dump_label(argv[0]));
5912fa9e4066Sahrens 
5913ed61ec1dSYuri Pankov 	if (dump_opt['O']) {
5914ed61ec1dSYuri Pankov 		if (argc != 2)
5915ed61ec1dSYuri Pankov 			usage();
5916ed61ec1dSYuri Pankov 		dump_opt['v'] = verbose + 3;
5917ed61ec1dSYuri Pankov 		return (dump_path(argv[0], argv[1]));
5918ed61ec1dSYuri Pankov 	}
5919ed61ec1dSYuri Pankov 
5920c8ee1847SVictor Latushkin 	if (dump_opt['X'] || dump_opt['F'])
5921c8ee1847SVictor Latushkin 		rewind = ZPOOL_DO_REWIND |
5922c8ee1847SVictor Latushkin 		    (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
5923c8ee1847SVictor Latushkin 
5924c8ee1847SVictor Latushkin 	if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 ||
59255dafeea3SPavel Zakharov 	    nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 ||
59265dafeea3SPavel Zakharov 	    nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0)
5927c8ee1847SVictor Latushkin 		fatal("internal error: %s", strerror(ENOMEM));
5928c8ee1847SVictor Latushkin 
5929c5904d13Seschrock 	error = 0;
59303ad6c7f9SVictor Latushkin 	target = argv[0];
5931990b4856Slling 
5932e0f1c0afSOlaf Faaland 	if (strpbrk(target, "/@") != NULL) {
5933e0f1c0afSOlaf Faaland 		size_t targetlen;
5934e0f1c0afSOlaf Faaland 
5935e0f1c0afSOlaf Faaland 		target_pool = strdup(target);
5936e0f1c0afSOlaf Faaland 		*strpbrk(target_pool, "/@") = '\0';
5937e0f1c0afSOlaf Faaland 
5938e0f1c0afSOlaf Faaland 		target_is_spa = B_FALSE;
5939e0f1c0afSOlaf Faaland 		targetlen = strlen(target);
5940e0f1c0afSOlaf Faaland 		if (targetlen && target[targetlen - 1] == '/')
5941e0f1c0afSOlaf Faaland 			target[targetlen - 1] = '\0';
5942e0f1c0afSOlaf Faaland 	} else {
5943e0f1c0afSOlaf Faaland 		target_pool = target;
5944e0f1c0afSOlaf Faaland 	}
5945e0f1c0afSOlaf Faaland 
59463ad6c7f9SVictor Latushkin 	if (dump_opt['e']) {
5947e0f1c0afSOlaf Faaland 		importargs_t args = { 0 };
5948990b4856Slling 
5949e0f1c0afSOlaf Faaland 		args.paths = nsearch;
5950e0f1c0afSOlaf Faaland 		args.path = searchdirs;
5951e0f1c0afSOlaf Faaland 		args.can_be_active = B_TRUE;
5952e0f1c0afSOlaf Faaland 
5953e0f1c0afSOlaf Faaland 		error = zpool_tryimport(g_zfs, target_pool, &cfg, &args);
5954e0f1c0afSOlaf Faaland 
5955e0f1c0afSOlaf Faaland 		if (error == 0) {
595686714001SSerapheim Dimitropoulos 
5957c8ee1847SVictor Latushkin 			if (nvlist_add_nvlist(cfg,
59585dafeea3SPavel Zakharov 			    ZPOOL_LOAD_POLICY, policy) != 0) {
5959468c413aSTim Haley 				fatal("can't open '%s': %s",
5960468c413aSTim Haley 				    target, strerror(ENOMEM));
5961468c413aSTim Haley 			}
5962e0f1c0afSOlaf Faaland 
5963e0f1c0afSOlaf Faaland 			if (dump_opt['C'] > 1) {
5964e0f1c0afSOlaf Faaland 				(void) printf("\nConfiguration for import:\n");
5965e0f1c0afSOlaf Faaland 				dump_nvlist(cfg, 8);
5966e0f1c0afSOlaf Faaland 			}
5967e0f1c0afSOlaf Faaland 
5968e0f1c0afSOlaf Faaland 			/*
5969e0f1c0afSOlaf Faaland 			 * Disable the activity check to allow examination of
5970e0f1c0afSOlaf Faaland 			 * active pools.
5971e0f1c0afSOlaf Faaland 			 */
5972e0f1c0afSOlaf Faaland 			error = spa_import(target_pool, cfg, NULL,
5973e0f1c0afSOlaf Faaland 			    flags | ZFS_IMPORT_SKIP_MMP);
5974de6628f0Sck 		}
5975c5904d13Seschrock 	}
5976c5904d13Seschrock 
597786714001SSerapheim Dimitropoulos 	char *checkpoint_pool = NULL;
597886714001SSerapheim Dimitropoulos 	char *checkpoint_target = NULL;
597986714001SSerapheim Dimitropoulos 	if (dump_opt['k']) {
598086714001SSerapheim Dimitropoulos 		checkpoint_pool = import_checkpointed_state(target, cfg,
598186714001SSerapheim Dimitropoulos 		    &checkpoint_target);
598286714001SSerapheim Dimitropoulos 
598386714001SSerapheim Dimitropoulos 		if (checkpoint_target != NULL)
598486714001SSerapheim Dimitropoulos 			target = checkpoint_target;
598586714001SSerapheim Dimitropoulos 
598686714001SSerapheim Dimitropoulos 	}
598786714001SSerapheim Dimitropoulos 
5988c5904d13Seschrock 	if (error == 0) {
598986714001SSerapheim Dimitropoulos 		if (dump_opt['k'] && (target_is_spa || dump_opt['R'])) {
599086714001SSerapheim Dimitropoulos 			ASSERT(checkpoint_pool != NULL);
599186714001SSerapheim Dimitropoulos 			ASSERT(checkpoint_target == NULL);
599286714001SSerapheim Dimitropoulos 
599386714001SSerapheim Dimitropoulos 			error = spa_open(checkpoint_pool, &spa, FTAG);
599486714001SSerapheim Dimitropoulos 			if (error != 0) {
599586714001SSerapheim Dimitropoulos 				fatal("Tried to open pool \"%s\" but "
599686714001SSerapheim Dimitropoulos 				    "spa_open() failed with error %d\n",
599786714001SSerapheim Dimitropoulos 				    checkpoint_pool, error);
599886714001SSerapheim Dimitropoulos 			}
599986714001SSerapheim Dimitropoulos 
600086714001SSerapheim Dimitropoulos 		} else if (target_is_spa || dump_opt['R']) {
6001e0f1c0afSOlaf Faaland 			zdb_set_skip_mmp(target);
600280eb36f2SGeorge Wilson 			error = spa_open_rewind(target, &spa, FTAG, policy,
600380eb36f2SGeorge Wilson 			    NULL);
60048f18d1faSGeorge Wilson 			if (error) {
60058f18d1faSGeorge Wilson 				/*
60068f18d1faSGeorge Wilson 				 * If we're missing the log device then
60078f18d1faSGeorge Wilson 				 * try opening the pool after clearing the
60088f18d1faSGeorge Wilson 				 * log state.
60098f18d1faSGeorge Wilson 				 */
60108f18d1faSGeorge Wilson 				mutex_enter(&spa_namespace_lock);
60113ad6c7f9SVictor Latushkin 				if ((spa = spa_lookup(target)) != NULL &&
60128f18d1faSGeorge Wilson 				    spa->spa_log_state == SPA_LOG_MISSING) {
60138f18d1faSGeorge Wilson 					spa->spa_log_state = SPA_LOG_CLEAR;
60148f18d1faSGeorge Wilson 					error = 0;
60158f18d1faSGeorge Wilson 				}
60168f18d1faSGeorge Wilson 				mutex_exit(&spa_namespace_lock);
60178f18d1faSGeorge Wilson 
601880eb36f2SGeorge Wilson 				if (!error) {
601980eb36f2SGeorge Wilson 					error = spa_open_rewind(target, &spa,
602080eb36f2SGeorge Wilson 					    FTAG, policy, NULL);
602180eb36f2SGeorge Wilson 				}
60228f18d1faSGeorge Wilson 			}
602307428bdfSVictor Latushkin 		} else {
6024e0f1c0afSOlaf Faaland 			zdb_set_skip_mmp(target);
6025ed61ec1dSYuri Pankov 			error = open_objset(target, DMU_OST_ANY, FTAG, &os);
6026c5904d13Seschrock 		}
6027fa9e4066Sahrens 	}
602880eb36f2SGeorge Wilson 	nvlist_free(policy);
602980eb36f2SGeorge Wilson 
6030fa9e4066Sahrens 	if (error)
60313ad6c7f9SVictor Latushkin 		fatal("can't open '%s': %s", target, strerror(error));
6032fa9e4066Sahrens 
6033fa9e4066Sahrens 	argv++;
603407428bdfSVictor Latushkin 	argc--;
603507428bdfSVictor Latushkin 	if (!dump_opt['R']) {
603607428bdfSVictor Latushkin 		if (argc > 0) {
603707428bdfSVictor Latushkin 			zopt_objects = argc;
603807428bdfSVictor Latushkin 			zopt_object = calloc(zopt_objects, sizeof (uint64_t));
60393f7978d0SAlan Somers 			for (unsigned i = 0; i < zopt_objects; i++) {
604007428bdfSVictor Latushkin 				errno = 0;
604107428bdfSVictor Latushkin 				zopt_object[i] = strtoull(argv[i], NULL, 0);
604207428bdfSVictor Latushkin 				if (zopt_object[i] == 0 && errno != 0)
604387219db7SVictor Latushkin 					fatal("bad number %s: %s",
604407428bdfSVictor Latushkin 					    argv[i], strerror(errno));
604507428bdfSVictor Latushkin 			}
6046fa9e4066Sahrens 		}
6047e690fb27SChristopher Siden 		if (os != NULL) {
6048e690fb27SChristopher Siden 			dump_dir(os);
6049e690fb27SChristopher Siden 		} else if (zopt_objects > 0 && !dump_opt['m']) {
6050e690fb27SChristopher Siden 			dump_dir(spa->spa_meta_objset);
6051e690fb27SChristopher Siden 		} else {
6052e690fb27SChristopher Siden 			dump_zpool(spa);
6053e690fb27SChristopher Siden 		}
6054fa9e4066Sahrens 	} else {
605507428bdfSVictor Latushkin 		flagbits['b'] = ZDB_FLAG_PRINT_BLKPTR;
605607428bdfSVictor Latushkin 		flagbits['c'] = ZDB_FLAG_CHECKSUM;
605707428bdfSVictor Latushkin 		flagbits['d'] = ZDB_FLAG_DECOMPRESS;
605807428bdfSVictor Latushkin 		flagbits['e'] = ZDB_FLAG_BSWAP;
605907428bdfSVictor Latushkin 		flagbits['g'] = ZDB_FLAG_GBH;
606007428bdfSVictor Latushkin 		flagbits['i'] = ZDB_FLAG_INDIRECT;
606107428bdfSVictor Latushkin 		flagbits['p'] = ZDB_FLAG_PHYS;
606207428bdfSVictor Latushkin 		flagbits['r'] = ZDB_FLAG_RAW;
606307428bdfSVictor Latushkin 
60643f7978d0SAlan Somers 		for (int i = 0; i < argc; i++)
606507428bdfSVictor Latushkin 			zdb_read_block(argv[i], spa);
6066fa9e4066Sahrens 	}
6067fa9e4066Sahrens 
606886714001SSerapheim Dimitropoulos 	if (dump_opt['k']) {
606986714001SSerapheim Dimitropoulos 		free(checkpoint_pool);
607086714001SSerapheim Dimitropoulos 		if (!target_is_spa)
607186714001SSerapheim Dimitropoulos 			free(checkpoint_target);
607286714001SSerapheim Dimitropoulos 	}
607386714001SSerapheim Dimitropoulos 
6074ed61ec1dSYuri Pankov 	if (os != NULL)
6075ed61ec1dSYuri Pankov 		close_objset(os, FTAG);
6076ed61ec1dSYuri Pankov 	else
6077ed61ec1dSYuri Pankov 		spa_close(spa, FTAG);
607807428bdfSVictor Latushkin 
6079e0d35c44Smarks 	fuid_table_destroy();
6080e0d35c44Smarks 
608129bdd2f9SPavel Zakharov 	dump_debug_buffer();
608229bdd2f9SPavel Zakharov 
6083de6628f0Sck 	libzfs_fini(g_zfs);
6084fa9e4066Sahrens 	kernel_fini();
6085fa9e4066Sahrens 
608620b5dafbSPaul Dagnelie 	return (error);
6087fa9e4066Sahrens }
6088