1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21236884Smm
22168404Spjd/*
23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24268657Sdelphij * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
25168404Spjd */
26168404Spjd
27168404Spjd#include <stdio.h>
28249207Smm#include <unistd.h>
29168404Spjd#include <stdio_ext.h>
30168404Spjd#include <stdlib.h>
31168404Spjd#include <ctype.h>
32168404Spjd#include <sys/zfs_context.h>
33168404Spjd#include <sys/spa.h>
34168404Spjd#include <sys/spa_impl.h>
35168404Spjd#include <sys/dmu.h>
36168404Spjd#include <sys/zap.h>
37168404Spjd#include <sys/fs/zfs.h>
38168404Spjd#include <sys/zfs_znode.h>
39219089Spjd#include <sys/zfs_sa.h>
40219089Spjd#include <sys/sa.h>
41219089Spjd#include <sys/sa_impl.h>
42168404Spjd#include <sys/vdev.h>
43168404Spjd#include <sys/vdev_impl.h>
44168404Spjd#include <sys/metaslab_impl.h>
45168404Spjd#include <sys/dmu_objset.h>
46168404Spjd#include <sys/dsl_dir.h>
47168404Spjd#include <sys/dsl_dataset.h>
48168404Spjd#include <sys/dsl_pool.h>
49168404Spjd#include <sys/dbuf.h>
50168404Spjd#include <sys/zil.h>
51168404Spjd#include <sys/zil_impl.h>
52168404Spjd#include <sys/stat.h>
53168404Spjd#include <sys/resource.h>
54168404Spjd#include <sys/dmu_traverse.h>
55168404Spjd#include <sys/zio_checksum.h>
56168404Spjd#include <sys/zio_compress.h>
57185029Spjd#include <sys/zfs_fuid.h>
58208047Smm#include <sys/arc.h>
59219089Spjd#include <sys/ddt.h>
60236884Smm#include <sys/zfeature.h>
61248571Smm#include <zfs_comutil.h>
62185029Spjd#undef ZFS_MAXNAMELEN
63185029Spjd#undef verify
64185029Spjd#include <libzfs.h>
65168404Spjd
66244246Smm#define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ?	\
67244246Smm	zio_compress_table[(idx)].ci_name : "UNKNOWN")
68244246Smm#define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ?	\
69244246Smm	zio_checksum_table[(idx)].ci_name : "UNKNOWN")
70244246Smm#define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ?	\
71244246Smm	dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ?	\
72244246Smm	dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN")
73244246Smm#define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) :		\
74244246Smm	(((idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA) ?	\
75244246Smm	DMU_OT_ZAP_OTHER : DMU_OT_NUMTYPES))
76219089Spjd
77219089Spjd#ifndef lint
78268650Sdelphijextern boolean_t zfs_recover;
79273508Sdelphijextern uint64_t zfs_arc_max, zfs_arc_meta_limit;
80275488Sdelphijextern int zfs_vdev_async_read_max_active;
81219089Spjd#else
82268650Sdelphijboolean_t zfs_recover;
83273508Sdelphijuint64_t zfs_arc_max, zfs_arc_meta_limit;
84275488Sdelphijint zfs_vdev_async_read_max_active;
85219089Spjd#endif
86219089Spjd
87168404Spjdconst char cmdname[] = "zdb";
88168404Spjduint8_t dump_opt[256];
89168404Spjd
90168404Spjdtypedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
91168404Spjd
92168404Spjdextern void dump_intent_log(zilog_t *);
93168404Spjduint64_t *zopt_object = NULL;
94168404Spjdint zopt_objects = 0;
95185029Spjdlibzfs_handle_t *g_zfs;
96273508Sdelphijuint64_t max_inflight = 1000;
97168404Spjd
98168404Spjd/*
99168404Spjd * These libumem hooks provide a reasonable set of defaults for the allocator's
100168404Spjd * debugging facilities.
101168404Spjd */
102168404Spjdconst char *
103168404Spjd_umem_debug_init()
104168404Spjd{
105168404Spjd	return ("default,verbose"); /* $UMEM_DEBUG setting */
106168404Spjd}
107168404Spjd
108168404Spjdconst char *
109168404Spjd_umem_logging_init(void)
110168404Spjd{
111168404Spjd	return ("fail,contents"); /* $UMEM_LOGGING setting */
112168404Spjd}
113168404Spjd
114168404Spjdstatic void
115168404Spjdusage(void)
116168404Spjd{
117168404Spjd	(void) fprintf(stderr,
118269773Sdelphij	    "Usage: %s [-CumMdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
119269773Sdelphij	    "[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n"
120263393Sdelphij	    "       %s [-divPA] [-e -p path...] [-U config] dataset "
121263393Sdelphij	    "[object...]\n"
122269773Sdelphij	    "       %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
123263393Sdelphij	    "poolname [vdev [metaslab...]]\n"
124263393Sdelphij	    "       %s -R [-A] [-e [-p path...]] poolname "
125263393Sdelphij	    "vdev:offset:size[:flags]\n"
126263393Sdelphij	    "       %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
127263393Sdelphij	    "       %s -l [-uA] device\n"
128263393Sdelphij	    "       %s -C [-A] [-U config]\n\n",
129219089Spjd	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
130168404Spjd
131219089Spjd	(void) fprintf(stderr, "    Dataset name must include at least one "
132219089Spjd	    "separator character '/' or '@'\n");
133219089Spjd	(void) fprintf(stderr, "    If dataset name is specified, only that "
134219089Spjd	    "dataset is dumped\n");
135219089Spjd	(void) fprintf(stderr, "    If object numbers are specified, only "
136219089Spjd	    "those objects are dumped\n\n");
137219089Spjd	(void) fprintf(stderr, "    Options to control amount of output:\n");
138219089Spjd	(void) fprintf(stderr, "        -u uberblock\n");
139219089Spjd	(void) fprintf(stderr, "        -d dataset(s)\n");
140219089Spjd	(void) fprintf(stderr, "        -i intent logs\n");
141219089Spjd	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
142219089Spjd	(void) fprintf(stderr, "        -h pool history\n");
143219089Spjd	(void) fprintf(stderr, "        -b block statistics\n");
144219089Spjd	(void) fprintf(stderr, "        -m metaslabs\n");
145269773Sdelphij	(void) fprintf(stderr, "        -M metaslab groups\n");
146219089Spjd	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
147209962Smm	    "all data) blocks\n");
148219089Spjd	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
149219089Spjd	(void) fprintf(stderr, "        -D dedup statistics\n");
150219089Spjd	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
151219089Spjd	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
152168404Spjd	(void) fprintf(stderr, "        -l dump label contents\n");
153209962Smm	(void) fprintf(stderr, "        -L disable leak tracking (do not "
154209962Smm	    "load spacemaps)\n");
155219089Spjd	(void) fprintf(stderr, "        -R read and display block from a "
156219089Spjd	    "device\n\n");
157219089Spjd	(void) fprintf(stderr, "    Below options are intended for use "
158268653Sdelphij	    "with other options:\n");
159219089Spjd	(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
160219089Spjd	    "panic recovery (-AA) or both (-AAA)\n");
161219089Spjd	(void) fprintf(stderr, "        -F attempt automatic rewind within "
162219089Spjd	    "safe range of transaction groups\n");
163219089Spjd	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
164185029Spjd	    "cachefile\n");
165219089Spjd	(void) fprintf(stderr, "        -X attempt extreme rewind (does not "
166219089Spjd	    "work with dataset)\n");
167219089Spjd	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
168219089Spjd	    "has altroot/not in a cachefile\n");
169219089Spjd	(void) fprintf(stderr, "        -p <path> -- use one or more with "
170219089Spjd	    "-e to specify path to vdev dir\n");
171268653Sdelphij	(void) fprintf(stderr, "        -x <dumpdir> -- "
172268653Sdelphij	    "dump all read blocks into specified directory\n");
173268653Sdelphij	(void) fprintf(stderr, "        -P print numbers in parseable form\n");
174219089Spjd	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
175209962Smm	    "searching for uberblocks\n");
176269773Sdelphij	(void) fprintf(stderr, "        -I <number of inflight I/Os> -- "
177268653Sdelphij	    "specify the maximum number of "
178268653Sdelphij	    "checksumming I/Os [default is 200]\n");
179168404Spjd	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
180168404Spjd	    "to make only that option verbose\n");
181168404Spjd	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
182168404Spjd	exit(1);
183168404Spjd}
184168404Spjd
185209962Smm/*
186209962Smm * Called for usage errors that are discovered after a call to spa_open(),
187209962Smm * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
188209962Smm */
189209962Smm
190168404Spjdstatic void
191168404Spjdfatal(const char *fmt, ...)
192168404Spjd{
193168404Spjd	va_list ap;
194168404Spjd
195168404Spjd	va_start(ap, fmt);
196168404Spjd	(void) fprintf(stderr, "%s: ", cmdname);
197168404Spjd	(void) vfprintf(stderr, fmt, ap);
198168404Spjd	va_end(ap);
199168404Spjd	(void) fprintf(stderr, "\n");
200168404Spjd
201209962Smm	exit(1);
202168404Spjd}
203168404Spjd
204168404Spjd/* ARGSUSED */
205168404Spjdstatic void
206168404Spjddump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
207168404Spjd{
208168404Spjd	nvlist_t *nv;
209168404Spjd	size_t nvsize = *(uint64_t *)data;
210168404Spjd	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
211168404Spjd
212209962Smm	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
213168404Spjd
214168404Spjd	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
215168404Spjd
216168404Spjd	umem_free(packed, nvsize);
217168404Spjd
218168404Spjd	dump_nvlist(nv, 8);
219168404Spjd
220168404Spjd	nvlist_free(nv);
221168404Spjd}
222168404Spjd
223248571Smm/* ARGSUSED */
224219089Spjdstatic void
225248571Smmdump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
226248571Smm{
227248571Smm	spa_history_phys_t *shp = data;
228248571Smm
229248571Smm	if (shp == NULL)
230248571Smm		return;
231248571Smm
232248571Smm	(void) printf("\t\tpool_create_len = %llu\n",
233248571Smm	    (u_longlong_t)shp->sh_pool_create_len);
234248571Smm	(void) printf("\t\tphys_max_off = %llu\n",
235248571Smm	    (u_longlong_t)shp->sh_phys_max_off);
236248571Smm	(void) printf("\t\tbof = %llu\n",
237248571Smm	    (u_longlong_t)shp->sh_bof);
238248571Smm	(void) printf("\t\teof = %llu\n",
239248571Smm	    (u_longlong_t)shp->sh_eof);
240248571Smm	(void) printf("\t\trecords_lost = %llu\n",
241248571Smm	    (u_longlong_t)shp->sh_records_lost);
242248571Smm}
243248571Smm
244248571Smmstatic void
245219089Spjdzdb_nicenum(uint64_t num, char *buf)
246219089Spjd{
247219089Spjd	if (dump_opt['P'])
248219089Spjd		(void) sprintf(buf, "%llu", (longlong_t)num);
249219089Spjd	else
250219089Spjd		nicenum(num, buf);
251219089Spjd}
252219089Spjd
253249207Smmconst char histo_stars[] = "****************************************";
254249207Smmconst int histo_width = sizeof (histo_stars) - 1;
255168404Spjd
256168404Spjdstatic void
257262093Savgdump_histogram(const uint64_t *histo, int size, int offset)
258168404Spjd{
259168404Spjd	int i;
260249207Smm	int minidx = size - 1;
261168404Spjd	int maxidx = 0;
262168404Spjd	uint64_t max = 0;
263168404Spjd
264249207Smm	for (i = 0; i < size; i++) {
265168404Spjd		if (histo[i] > max)
266168404Spjd			max = histo[i];
267168404Spjd		if (histo[i] > 0 && i > maxidx)
268168404Spjd			maxidx = i;
269168404Spjd		if (histo[i] > 0 && i < minidx)
270168404Spjd			minidx = i;
271168404Spjd	}
272168404Spjd
273249207Smm	if (max < histo_width)
274249207Smm		max = histo_width;
275168404Spjd
276249207Smm	for (i = minidx; i <= maxidx; i++) {
277249207Smm		(void) printf("\t\t\t%3u: %6llu %s\n",
278262093Savg		    i + offset, (u_longlong_t)histo[i],
279249207Smm		    &histo_stars[(max - histo[i]) * histo_width / max]);
280249207Smm	}
281168404Spjd}
282168404Spjd
283168404Spjdstatic void
284168404Spjddump_zap_stats(objset_t *os, uint64_t object)
285168404Spjd{
286168404Spjd	int error;
287168404Spjd	zap_stats_t zs;
288168404Spjd
289168404Spjd	error = zap_get_stats(os, object, &zs);
290168404Spjd	if (error)
291168404Spjd		return;
292168404Spjd
293168404Spjd	if (zs.zs_ptrtbl_len == 0) {
294168404Spjd		ASSERT(zs.zs_num_blocks == 1);
295168404Spjd		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
296168404Spjd		    (u_longlong_t)zs.zs_blocksize,
297168404Spjd		    (u_longlong_t)zs.zs_num_entries);
298168404Spjd		return;
299168404Spjd	}
300168404Spjd
301168404Spjd	(void) printf("\tFat ZAP stats:\n");
302168404Spjd
303168404Spjd	(void) printf("\t\tPointer table:\n");
304168404Spjd	(void) printf("\t\t\t%llu elements\n",
305168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_len);
306168404Spjd	(void) printf("\t\t\tzt_blk: %llu\n",
307168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
308168404Spjd	(void) printf("\t\t\tzt_numblks: %llu\n",
309168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
310168404Spjd	(void) printf("\t\t\tzt_shift: %llu\n",
311168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
312168404Spjd	(void) printf("\t\t\tzt_blks_copied: %llu\n",
313168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
314168404Spjd	(void) printf("\t\t\tzt_nextblk: %llu\n",
315168404Spjd	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
316168404Spjd
317168404Spjd	(void) printf("\t\tZAP entries: %llu\n",
318168404Spjd	    (u_longlong_t)zs.zs_num_entries);
319168404Spjd	(void) printf("\t\tLeaf blocks: %llu\n",
320168404Spjd	    (u_longlong_t)zs.zs_num_leafs);
321168404Spjd	(void) printf("\t\tTotal blocks: %llu\n",
322168404Spjd	    (u_longlong_t)zs.zs_num_blocks);
323168404Spjd	(void) printf("\t\tzap_block_type: 0x%llx\n",
324168404Spjd	    (u_longlong_t)zs.zs_block_type);
325168404Spjd	(void) printf("\t\tzap_magic: 0x%llx\n",
326168404Spjd	    (u_longlong_t)zs.zs_magic);
327168404Spjd	(void) printf("\t\tzap_salt: 0x%llx\n",
328168404Spjd	    (u_longlong_t)zs.zs_salt);
329168404Spjd
330168404Spjd	(void) printf("\t\tLeafs with 2^n pointers:\n");
331262093Savg	dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE, 0);
332168404Spjd
333168404Spjd	(void) printf("\t\tBlocks with n*5 entries:\n");
334262093Savg	dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE, 0);
335168404Spjd
336168404Spjd	(void) printf("\t\tBlocks n/10 full:\n");
337262093Savg	dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE, 0);
338168404Spjd
339168404Spjd	(void) printf("\t\tEntries with n chunks:\n");
340262093Savg	dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE, 0);
341168404Spjd
342168404Spjd	(void) printf("\t\tBuckets with n entries:\n");
343262093Savg	dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE, 0);
344168404Spjd}
345168404Spjd
346168404Spjd/*ARGSUSED*/
347168404Spjdstatic void
348168404Spjddump_none(objset_t *os, uint64_t object, void *data, size_t size)
349168404Spjd{
350168404Spjd}
351168404Spjd
352168404Spjd/*ARGSUSED*/
353219089Spjdstatic void
354219089Spjddump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
355219089Spjd{
356219089Spjd	(void) printf("\tUNKNOWN OBJECT TYPE\n");
357219089Spjd}
358219089Spjd
359219089Spjd/*ARGSUSED*/
360168404Spjdvoid
361168404Spjddump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
362168404Spjd{
363168404Spjd}
364168404Spjd
365168404Spjd/*ARGSUSED*/
366168404Spjdstatic void
367168404Spjddump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
368168404Spjd{
369168404Spjd}
370168404Spjd
371168404Spjd/*ARGSUSED*/
372168404Spjdstatic void
373168404Spjddump_zap(objset_t *os, uint64_t object, void *data, size_t size)
374168404Spjd{
375168404Spjd	zap_cursor_t zc;
376168404Spjd	zap_attribute_t attr;
377168404Spjd	void *prop;
378168404Spjd	int i;
379168404Spjd
380168404Spjd	dump_zap_stats(os, object);
381168404Spjd	(void) printf("\n");
382168404Spjd
383168404Spjd	for (zap_cursor_init(&zc, os, object);
384168404Spjd	    zap_cursor_retrieve(&zc, &attr) == 0;
385168404Spjd	    zap_cursor_advance(&zc)) {
386168404Spjd		(void) printf("\t\t%s = ", attr.za_name);
387168404Spjd		if (attr.za_num_integers == 0) {
388168404Spjd			(void) printf("\n");
389168404Spjd			continue;
390168404Spjd		}
391168404Spjd		prop = umem_zalloc(attr.za_num_integers *
392168404Spjd		    attr.za_integer_length, UMEM_NOFAIL);
393168404Spjd		(void) zap_lookup(os, object, attr.za_name,
394168404Spjd		    attr.za_integer_length, attr.za_num_integers, prop);
395168404Spjd		if (attr.za_integer_length == 1) {
396168404Spjd			(void) printf("%s", (char *)prop);
397168404Spjd		} else {
398168404Spjd			for (i = 0; i < attr.za_num_integers; i++) {
399168404Spjd				switch (attr.za_integer_length) {
400168404Spjd				case 2:
401168404Spjd					(void) printf("%u ",
402168404Spjd					    ((uint16_t *)prop)[i]);
403168404Spjd					break;
404168404Spjd				case 4:
405168404Spjd					(void) printf("%u ",
406168404Spjd					    ((uint32_t *)prop)[i]);
407168404Spjd					break;
408168404Spjd				case 8:
409168404Spjd					(void) printf("%lld ",
410168404Spjd					    (u_longlong_t)((int64_t *)prop)[i]);
411168404Spjd					break;
412168404Spjd				}
413168404Spjd			}
414168404Spjd		}
415168404Spjd		(void) printf("\n");
416168404Spjd		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
417168404Spjd	}
418168404Spjd	zap_cursor_fini(&zc);
419168404Spjd}
420168404Spjd
421185029Spjd/*ARGSUSED*/
422168404Spjdstatic void
423219089Spjddump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
424219089Spjd{
425219089Spjd	dump_zap_stats(os, object);
426219089Spjd	/* contents are printed elsewhere, properly decoded */
427219089Spjd}
428219089Spjd
429219089Spjd/*ARGSUSED*/
430219089Spjdstatic void
431219089Spjddump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size)
432219089Spjd{
433219089Spjd	zap_cursor_t zc;
434219089Spjd	zap_attribute_t attr;
435219089Spjd
436219089Spjd	dump_zap_stats(os, object);
437219089Spjd	(void) printf("\n");
438219089Spjd
439219089Spjd	for (zap_cursor_init(&zc, os, object);
440219089Spjd	    zap_cursor_retrieve(&zc, &attr) == 0;
441219089Spjd	    zap_cursor_advance(&zc)) {
442219089Spjd		(void) printf("\t\t%s = ", attr.za_name);
443219089Spjd		if (attr.za_num_integers == 0) {
444219089Spjd			(void) printf("\n");
445219089Spjd			continue;
446219089Spjd		}
447219089Spjd		(void) printf(" %llx : [%d:%d:%d]\n",
448219089Spjd		    (u_longlong_t)attr.za_first_integer,
449219089Spjd		    (int)ATTR_LENGTH(attr.za_first_integer),
450219089Spjd		    (int)ATTR_BSWAP(attr.za_first_integer),
451219089Spjd		    (int)ATTR_NUM(attr.za_first_integer));
452219089Spjd	}
453219089Spjd	zap_cursor_fini(&zc);
454219089Spjd}
455219089Spjd
456219089Spjd/*ARGSUSED*/
457219089Spjdstatic void
458219089Spjddump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size)
459219089Spjd{
460219089Spjd	zap_cursor_t zc;
461219089Spjd	zap_attribute_t attr;
462219089Spjd	uint16_t *layout_attrs;
463219089Spjd	int i;
464219089Spjd
465219089Spjd	dump_zap_stats(os, object);
466219089Spjd	(void) printf("\n");
467219089Spjd
468219089Spjd	for (zap_cursor_init(&zc, os, object);
469219089Spjd	    zap_cursor_retrieve(&zc, &attr) == 0;
470219089Spjd	    zap_cursor_advance(&zc)) {
471219089Spjd		(void) printf("\t\t%s = [", attr.za_name);
472219089Spjd		if (attr.za_num_integers == 0) {
473219089Spjd			(void) printf("\n");
474219089Spjd			continue;
475219089Spjd		}
476219089Spjd
477219089Spjd		VERIFY(attr.za_integer_length == 2);
478219089Spjd		layout_attrs = umem_zalloc(attr.za_num_integers *
479219089Spjd		    attr.za_integer_length, UMEM_NOFAIL);
480219089Spjd
481219089Spjd		VERIFY(zap_lookup(os, object, attr.za_name,
482219089Spjd		    attr.za_integer_length,
483219089Spjd		    attr.za_num_integers, layout_attrs) == 0);
484219089Spjd
485219089Spjd		for (i = 0; i != attr.za_num_integers; i++)
486219089Spjd			(void) printf(" %d ", (int)layout_attrs[i]);
487219089Spjd		(void) printf("]\n");
488219089Spjd		umem_free(layout_attrs,
489219089Spjd		    attr.za_num_integers * attr.za_integer_length);
490219089Spjd	}
491219089Spjd	zap_cursor_fini(&zc);
492219089Spjd}
493219089Spjd
494219089Spjd/*ARGSUSED*/
495219089Spjdstatic void
496185029Spjddump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
497185029Spjd{
498185029Spjd	zap_cursor_t zc;
499185029Spjd	zap_attribute_t attr;
500185029Spjd	const char *typenames[] = {
501185029Spjd		/* 0 */ "not specified",
502185029Spjd		/* 1 */ "FIFO",
503185029Spjd		/* 2 */ "Character Device",
504185029Spjd		/* 3 */ "3 (invalid)",
505185029Spjd		/* 4 */ "Directory",
506185029Spjd		/* 5 */ "5 (invalid)",
507185029Spjd		/* 6 */ "Block Device",
508185029Spjd		/* 7 */ "7 (invalid)",
509185029Spjd		/* 8 */ "Regular File",
510185029Spjd		/* 9 */ "9 (invalid)",
511185029Spjd		/* 10 */ "Symbolic Link",
512185029Spjd		/* 11 */ "11 (invalid)",
513185029Spjd		/* 12 */ "Socket",
514185029Spjd		/* 13 */ "Door",
515185029Spjd		/* 14 */ "Event Port",
516185029Spjd		/* 15 */ "15 (invalid)",
517185029Spjd	};
518185029Spjd
519185029Spjd	dump_zap_stats(os, object);
520185029Spjd	(void) printf("\n");
521185029Spjd
522185029Spjd	for (zap_cursor_init(&zc, os, object);
523185029Spjd	    zap_cursor_retrieve(&zc, &attr) == 0;
524185029Spjd	    zap_cursor_advance(&zc)) {
525185029Spjd		(void) printf("\t\t%s = %lld (type: %s)\n",
526185029Spjd		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
527185029Spjd		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
528185029Spjd	}
529185029Spjd	zap_cursor_fini(&zc);
530185029Spjd}
531185029Spjd
532262093Savgint
533262093Savgget_dtl_refcount(vdev_t *vd)
534262093Savg{
535262093Savg	int refcount = 0;
536262093Savg
537262093Savg	if (vd->vdev_ops->vdev_op_leaf) {
538262093Savg		space_map_t *sm = vd->vdev_dtl_sm;
539262093Savg
540262093Savg		if (sm != NULL &&
541262093Savg		    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
542262093Savg			return (1);
543262093Savg		return (0);
544262093Savg	}
545262093Savg
546262093Savg	for (int c = 0; c < vd->vdev_children; c++)
547262093Savg		refcount += get_dtl_refcount(vd->vdev_child[c]);
548262093Savg	return (refcount);
549262093Savg}
550262093Savg
551262093Savgint
552262093Savgget_metaslab_refcount(vdev_t *vd)
553262093Savg{
554262093Savg	int refcount = 0;
555262093Savg
556269773Sdelphij	if (vd->vdev_top == vd && !vd->vdev_removing) {
557262093Savg		for (int m = 0; m < vd->vdev_ms_count; m++) {
558262093Savg			space_map_t *sm = vd->vdev_ms[m]->ms_sm;
559262093Savg
560262093Savg			if (sm != NULL &&
561262093Savg			    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
562262093Savg				refcount++;
563262093Savg		}
564262093Savg	}
565262093Savg	for (int c = 0; c < vd->vdev_children; c++)
566262093Savg		refcount += get_metaslab_refcount(vd->vdev_child[c]);
567262093Savg
568262093Savg	return (refcount);
569262093Savg}
570262093Savg
571262093Savgstatic int
572262093Savgverify_spacemap_refcounts(spa_t *spa)
573262093Savg{
574263390Sdelphij	uint64_t expected_refcount = 0;
575263390Sdelphij	uint64_t actual_refcount;
576262093Savg
577263390Sdelphij	(void) feature_get_refcount(spa,
578263390Sdelphij	    &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
579263390Sdelphij	    &expected_refcount);
580262093Savg	actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
581262093Savg	actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
582262093Savg
583262093Savg	if (expected_refcount != actual_refcount) {
584263390Sdelphij		(void) printf("space map refcount mismatch: expected %lld != "
585263390Sdelphij		    "actual %lld\n",
586263390Sdelphij		    (longlong_t)expected_refcount,
587263390Sdelphij		    (longlong_t)actual_refcount);
588262093Savg		return (2);
589262093Savg	}
590262093Savg	return (0);
591262093Savg}
592262093Savg
593185029Spjdstatic void
594262093Savgdump_spacemap(objset_t *os, space_map_t *sm)
595168404Spjd{
596168404Spjd	uint64_t alloc, offset, entry;
597168404Spjd	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
598168404Spjd			    "INVALID", "INVALID", "INVALID", "INVALID" };
599168404Spjd
600262093Savg	if (sm == NULL)
601168404Spjd		return;
602168404Spjd
603168404Spjd	/*
604168404Spjd	 * Print out the freelist entries in both encoded and decoded form.
605168404Spjd	 */
606168404Spjd	alloc = 0;
607262093Savg	for (offset = 0; offset < space_map_length(sm);
608262093Savg	    offset += sizeof (entry)) {
609262093Savg		uint8_t mapshift = sm->sm_shift;
610262093Savg
611262093Savg		VERIFY0(dmu_read(os, space_map_object(sm), offset,
612209962Smm		    sizeof (entry), &entry, DMU_READ_PREFETCH));
613168404Spjd		if (SM_DEBUG_DECODE(entry)) {
614262093Savg
615219089Spjd			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
616168404Spjd			    (u_longlong_t)(offset / sizeof (entry)),
617168404Spjd			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
618168404Spjd			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
619168404Spjd			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
620168404Spjd		} else {
621219089Spjd			(void) printf("\t    [%6llu]    %c  range:"
622219089Spjd			    " %010llx-%010llx  size: %06llx\n",
623168404Spjd			    (u_longlong_t)(offset / sizeof (entry)),
624168404Spjd			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
625168404Spjd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
626262093Savg			    mapshift) + sm->sm_start),
627168404Spjd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
628262093Savg			    mapshift) + sm->sm_start +
629262093Savg			    (SM_RUN_DECODE(entry) << mapshift)),
630168404Spjd			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
631168404Spjd			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
632168404Spjd				alloc += SM_RUN_DECODE(entry) << mapshift;
633168404Spjd			else
634168404Spjd				alloc -= SM_RUN_DECODE(entry) << mapshift;
635168404Spjd		}
636168404Spjd	}
637262093Savg	if (alloc != space_map_allocated(sm)) {
638168404Spjd		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
639168404Spjd		    "with space map summary (%llu)\n",
640262093Savg		    (u_longlong_t)space_map_allocated(sm), (u_longlong_t)alloc);
641168404Spjd	}
642168404Spjd}
643168404Spjd
644168404Spjdstatic void
645209962Smmdump_metaslab_stats(metaslab_t *msp)
646209962Smm{
647219089Spjd	char maxbuf[32];
648262093Savg	range_tree_t *rt = msp->ms_tree;
649262093Savg	avl_tree_t *t = &msp->ms_size_tree;
650262093Savg	int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
651209962Smm
652262093Savg	zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
653209962Smm
654219089Spjd	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
655209962Smm	    "segments", avl_numnodes(t), "maxsize", maxbuf,
656209962Smm	    "freepct", free_pct);
657262093Savg	(void) printf("\tIn-memory histogram:\n");
658262093Savg	dump_histogram(rt->rt_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
659209962Smm}
660209962Smm
661209962Smmstatic void
662168404Spjddump_metaslab(metaslab_t *msp)
663168404Spjd{
664168404Spjd	vdev_t *vd = msp->ms_group->mg_vd;
665168404Spjd	spa_t *spa = vd->vdev_spa;
666262093Savg	space_map_t *sm = msp->ms_sm;
667219089Spjd	char freebuf[32];
668168404Spjd
669262093Savg	zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
670168404Spjd
671168404Spjd	(void) printf(
672219089Spjd	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
673262093Savg	    (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
674262093Savg	    (u_longlong_t)space_map_object(sm), freebuf);
675168404Spjd
676262093Savg	if (dump_opt['m'] > 2 && !dump_opt['L']) {
677209962Smm		mutex_enter(&msp->ms_lock);
678262093Savg		metaslab_load_wait(msp);
679262093Savg		if (!msp->ms_loaded) {
680262093Savg			VERIFY0(metaslab_load(msp));
681262093Savg			range_tree_stat_verify(msp->ms_tree);
682262093Savg		}
683209962Smm		dump_metaslab_stats(msp);
684262093Savg		metaslab_unload(msp);
685209962Smm		mutex_exit(&msp->ms_lock);
686209962Smm	}
687168404Spjd
688262093Savg	if (dump_opt['m'] > 1 && sm != NULL &&
689263390Sdelphij	    spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
690262093Savg		/*
691262093Savg		 * The space map histogram represents free space in chunks
692262093Savg		 * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
693262093Savg		 */
694269773Sdelphij		(void) printf("\tOn-disk histogram:\t\tfragmentation %llu\n",
695269773Sdelphij		    (u_longlong_t)msp->ms_fragmentation);
696262093Savg		dump_histogram(sm->sm_phys->smp_histogram,
697269773Sdelphij		    SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
698262093Savg	}
699209962Smm
700262093Savg	if (dump_opt['d'] > 5 || dump_opt['m'] > 3) {
701262093Savg		ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
702262093Savg
703209962Smm		mutex_enter(&msp->ms_lock);
704262093Savg		dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
705209962Smm		mutex_exit(&msp->ms_lock);
706209962Smm	}
707168404Spjd}
708168404Spjd
709168404Spjdstatic void
710219089Spjdprint_vdev_metaslab_header(vdev_t *vd)
711219089Spjd{
712219089Spjd	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
713219089Spjd	    (u_longlong_t)vd->vdev_id,
714219089Spjd	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
715219089Spjd	    "offset", "spacemap", "free");
716219089Spjd	(void) printf("\t%15s   %19s   %15s   %10s\n",
717219089Spjd	    "---------------", "-------------------",
718219089Spjd	    "---------------", "-------------");
719219089Spjd}
720219089Spjd
721219089Spjdstatic void
722269773Sdelphijdump_metaslab_groups(spa_t *spa)
723269773Sdelphij{
724269773Sdelphij	vdev_t *rvd = spa->spa_root_vdev;
725269773Sdelphij	metaslab_class_t *mc = spa_normal_class(spa);
726269773Sdelphij	uint64_t fragmentation;
727269773Sdelphij
728269773Sdelphij	metaslab_class_histogram_verify(mc);
729269773Sdelphij
730269773Sdelphij	for (int c = 0; c < rvd->vdev_children; c++) {
731269773Sdelphij		vdev_t *tvd = rvd->vdev_child[c];
732269773Sdelphij		metaslab_group_t *mg = tvd->vdev_mg;
733269773Sdelphij
734269773Sdelphij		if (mg->mg_class != mc)
735269773Sdelphij			continue;
736269773Sdelphij
737269773Sdelphij		metaslab_group_histogram_verify(mg);
738269773Sdelphij		mg->mg_fragmentation = metaslab_group_fragmentation(mg);
739269773Sdelphij
740269773Sdelphij		(void) printf("\tvdev %10llu\t\tmetaslabs%5llu\t\t"
741269773Sdelphij		    "fragmentation",
742269773Sdelphij		    (u_longlong_t)tvd->vdev_id,
743269773Sdelphij		    (u_longlong_t)tvd->vdev_ms_count);
744269773Sdelphij		if (mg->mg_fragmentation == ZFS_FRAG_INVALID) {
745269773Sdelphij			(void) printf("%3s\n", "-");
746269773Sdelphij		} else {
747269773Sdelphij			(void) printf("%3llu%%\n",
748269773Sdelphij			    (u_longlong_t)mg->mg_fragmentation);
749269773Sdelphij		}
750269773Sdelphij		dump_histogram(mg->mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
751269773Sdelphij	}
752269773Sdelphij
753269773Sdelphij	(void) printf("\tpool %s\tfragmentation", spa_name(spa));
754269773Sdelphij	fragmentation = metaslab_class_fragmentation(mc);
755269773Sdelphij	if (fragmentation == ZFS_FRAG_INVALID)
756269773Sdelphij		(void) printf("\t%3s\n", "-");
757269773Sdelphij	else
758269773Sdelphij		(void) printf("\t%3llu%%\n", (u_longlong_t)fragmentation);
759269773Sdelphij	dump_histogram(mc->mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
760269773Sdelphij}
761269773Sdelphij
762269773Sdelphijstatic void
763168404Spjddump_metaslabs(spa_t *spa)
764168404Spjd{
765219089Spjd	vdev_t *vd, *rvd = spa->spa_root_vdev;
766219089Spjd	uint64_t m, c = 0, children = rvd->vdev_children;
767168404Spjd
768168404Spjd	(void) printf("\nMetaslabs:\n");
769168404Spjd
770219089Spjd	if (!dump_opt['d'] && zopt_objects > 0) {
771219089Spjd		c = zopt_object[0];
772219089Spjd
773219089Spjd		if (c >= children)
774219089Spjd			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
775219089Spjd
776219089Spjd		if (zopt_objects > 1) {
777219089Spjd			vd = rvd->vdev_child[c];
778219089Spjd			print_vdev_metaslab_header(vd);
779219089Spjd
780219089Spjd			for (m = 1; m < zopt_objects; m++) {
781219089Spjd				if (zopt_object[m] < vd->vdev_ms_count)
782219089Spjd					dump_metaslab(
783219089Spjd					    vd->vdev_ms[zopt_object[m]]);
784219089Spjd				else
785219089Spjd					(void) fprintf(stderr, "bad metaslab "
786219089Spjd					    "number %llu\n",
787219089Spjd					    (u_longlong_t)zopt_object[m]);
788219089Spjd			}
789219089Spjd			(void) printf("\n");
790219089Spjd			return;
791219089Spjd		}
792219089Spjd		children = c + 1;
793219089Spjd	}
794219089Spjd	for (; c < children; c++) {
795168404Spjd		vd = rvd->vdev_child[c];
796219089Spjd		print_vdev_metaslab_header(vd);
797168404Spjd
798168404Spjd		for (m = 0; m < vd->vdev_ms_count; m++)
799168404Spjd			dump_metaslab(vd->vdev_ms[m]);
800168404Spjd		(void) printf("\n");
801168404Spjd	}
802168404Spjd}
803168404Spjd
804168404Spjdstatic void
805219089Spjddump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
806219089Spjd{
807219089Spjd	const ddt_phys_t *ddp = dde->dde_phys;
808219089Spjd	const ddt_key_t *ddk = &dde->dde_key;
809219089Spjd	char *types[4] = { "ditto", "single", "double", "triple" };
810219089Spjd	char blkbuf[BP_SPRINTF_LEN];
811219089Spjd	blkptr_t blk;
812219089Spjd
813219089Spjd	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
814219089Spjd		if (ddp->ddp_phys_birth == 0)
815219089Spjd			continue;
816219089Spjd		ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
817263397Sdelphij		snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk);
818219089Spjd		(void) printf("index %llx refcnt %llu %s %s\n",
819219089Spjd		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
820219089Spjd		    types[p], blkbuf);
821219089Spjd	}
822219089Spjd}
823219089Spjd
824219089Spjdstatic void
825219089Spjddump_dedup_ratio(const ddt_stat_t *dds)
826219089Spjd{
827219089Spjd	double rL, rP, rD, D, dedup, compress, copies;
828219089Spjd
829219089Spjd	if (dds->dds_blocks == 0)
830219089Spjd		return;
831219089Spjd
832219089Spjd	rL = (double)dds->dds_ref_lsize;
833219089Spjd	rP = (double)dds->dds_ref_psize;
834219089Spjd	rD = (double)dds->dds_ref_dsize;
835219089Spjd	D = (double)dds->dds_dsize;
836219089Spjd
837219089Spjd	dedup = rD / D;
838219089Spjd	compress = rL / rP;
839219089Spjd	copies = rD / rP;
840219089Spjd
841219089Spjd	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
842219089Spjd	    "dedup * compress / copies = %.2f\n\n",
843219089Spjd	    dedup, compress, copies, dedup * compress / copies);
844219089Spjd}
845219089Spjd
846219089Spjdstatic void
847219089Spjddump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
848219089Spjd{
849219089Spjd	char name[DDT_NAMELEN];
850219089Spjd	ddt_entry_t dde;
851219089Spjd	uint64_t walk = 0;
852219089Spjd	dmu_object_info_t doi;
853219089Spjd	uint64_t count, dspace, mspace;
854219089Spjd	int error;
855219089Spjd
856219089Spjd	error = ddt_object_info(ddt, type, class, &doi);
857219089Spjd
858219089Spjd	if (error == ENOENT)
859219089Spjd		return;
860219089Spjd	ASSERT(error == 0);
861219089Spjd
862245264Sdelphij	error = ddt_object_count(ddt, type, class, &count);
863245264Sdelphij	ASSERT(error == 0);
864245264Sdelphij	if (count == 0)
865219089Spjd		return;
866219089Spjd
867219089Spjd	dspace = doi.doi_physical_blocks_512 << 9;
868219089Spjd	mspace = doi.doi_fill_count * doi.doi_data_block_size;
869219089Spjd
870219089Spjd	ddt_object_name(ddt, type, class, name);
871219089Spjd
872219089Spjd	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
873219089Spjd	    name,
874219089Spjd	    (u_longlong_t)count,
875219089Spjd	    (u_longlong_t)(dspace / count),
876219089Spjd	    (u_longlong_t)(mspace / count));
877219089Spjd
878219089Spjd	if (dump_opt['D'] < 3)
879219089Spjd		return;
880219089Spjd
881219089Spjd	zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]);
882219089Spjd
883219089Spjd	if (dump_opt['D'] < 4)
884219089Spjd		return;
885219089Spjd
886219089Spjd	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
887219089Spjd		return;
888219089Spjd
889219089Spjd	(void) printf("%s contents:\n\n", name);
890219089Spjd
891219089Spjd	while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0)
892219089Spjd		dump_dde(ddt, &dde, walk);
893219089Spjd
894219089Spjd	ASSERT(error == ENOENT);
895219089Spjd
896219089Spjd	(void) printf("\n");
897219089Spjd}
898219089Spjd
899219089Spjdstatic void
900219089Spjddump_all_ddts(spa_t *spa)
901219089Spjd{
902219089Spjd	ddt_histogram_t ddh_total = { 0 };
903219089Spjd	ddt_stat_t dds_total = { 0 };
904219089Spjd
905219089Spjd	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
906219089Spjd		ddt_t *ddt = spa->spa_ddt[c];
907219089Spjd		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
908219089Spjd			for (enum ddt_class class = 0; class < DDT_CLASSES;
909219089Spjd			    class++) {
910219089Spjd				dump_ddt(ddt, type, class);
911219089Spjd			}
912219089Spjd		}
913219089Spjd	}
914219089Spjd
915219089Spjd	ddt_get_dedup_stats(spa, &dds_total);
916219089Spjd
917219089Spjd	if (dds_total.dds_blocks == 0) {
918219089Spjd		(void) printf("All DDTs are empty\n");
919219089Spjd		return;
920219089Spjd	}
921219089Spjd
922219089Spjd	(void) printf("\n");
923219089Spjd
924219089Spjd	if (dump_opt['D'] > 1) {
925219089Spjd		(void) printf("DDT histogram (aggregated over all DDTs):\n");
926219089Spjd		ddt_get_dedup_histogram(spa, &ddh_total);
927219089Spjd		zpool_dump_ddt(&dds_total, &ddh_total);
928219089Spjd	}
929219089Spjd
930219089Spjd	dump_dedup_ratio(&dds_total);
931219089Spjd}
932219089Spjd
933219089Spjdstatic void
934262093Savgdump_dtl_seg(void *arg, uint64_t start, uint64_t size)
935209962Smm{
936262093Savg	char *prefix = arg;
937209962Smm
938209962Smm	(void) printf("%s [%llu,%llu) length %llu\n",
939209962Smm	    prefix,
940209962Smm	    (u_longlong_t)start,
941209962Smm	    (u_longlong_t)(start + size),
942209962Smm	    (u_longlong_t)(size));
943209962Smm}
944209962Smm
945209962Smmstatic void
946168404Spjddump_dtl(vdev_t *vd, int indent)
947168404Spjd{
948209962Smm	spa_t *spa = vd->vdev_spa;
949209962Smm	boolean_t required;
950209962Smm	char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" };
951209962Smm	char prefix[256];
952168404Spjd
953219089Spjd	spa_vdev_state_enter(spa, SCL_NONE);
954209962Smm	required = vdev_dtl_required(vd);
955209962Smm	(void) spa_vdev_state_exit(spa, NULL, 0);
956209962Smm
957168404Spjd	if (indent == 0)
958168404Spjd		(void) printf("\nDirty time logs:\n\n");
959168404Spjd
960209962Smm	(void) printf("\t%*s%s [%s]\n", indent, "",
961185029Spjd	    vd->vdev_path ? vd->vdev_path :
962209962Smm	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
963209962Smm	    required ? "DTL-required" : "DTL-expendable");
964168404Spjd
965209962Smm	for (int t = 0; t < DTL_TYPES; t++) {
966262093Savg		range_tree_t *rt = vd->vdev_dtl[t];
967262093Savg		if (range_tree_space(rt) == 0)
968209962Smm			continue;
969209962Smm		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
970209962Smm		    indent + 2, "", name[t]);
971262093Savg		mutex_enter(rt->rt_lock);
972262093Savg		range_tree_walk(rt, dump_dtl_seg, prefix);
973262093Savg		mutex_exit(rt->rt_lock);
974209962Smm		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
975262093Savg			dump_spacemap(spa->spa_meta_objset, vd->vdev_dtl_sm);
976168404Spjd	}
977168404Spjd
978209962Smm	for (int c = 0; c < vd->vdev_children; c++)
979168404Spjd		dump_dtl(vd->vdev_child[c], indent + 4);
980168404Spjd}
981168404Spjd
982265039Sdelphij/* from spa_history.c: spa_history_create_obj() */
983265039Sdelphij#define	HIS_BUF_LEN_DEF	(128 << 10)
984265039Sdelphij#define	HIS_BUF_LEN_MAX	(1 << 30)
985265039Sdelphij
986219089Spjdstatic void
987219089Spjddump_history(spa_t *spa)
988219089Spjd{
989219089Spjd	nvlist_t **events = NULL;
990265039Sdelphij	char *buf = NULL;
991265039Sdelphij	uint64_t bufsize = HIS_BUF_LEN_DEF;
992219089Spjd	uint64_t resid, len, off = 0;
993219089Spjd	uint_t num = 0;
994219089Spjd	int error;
995219089Spjd	time_t tsec;
996219089Spjd	struct tm t;
997219089Spjd	char tbuf[30];
998219089Spjd	char internalstr[MAXPATHLEN];
999219089Spjd
1000265039Sdelphij	if ((buf = malloc(bufsize)) == NULL)
1001265039Sdelphij		(void) fprintf(stderr, "Unable to read history: "
1002265039Sdelphij		    "out of memory\n");
1003219089Spjd	do {
1004265039Sdelphij		len = bufsize;
1005219089Spjd
1006219089Spjd		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
1007219089Spjd			(void) fprintf(stderr, "Unable to read history: "
1008219089Spjd			    "error %d\n", error);
1009219089Spjd			return;
1010219089Spjd		}
1011219089Spjd
1012219089Spjd		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
1013219089Spjd			break;
1014265039Sdelphij		off -= resid;
1015219089Spjd
1016265039Sdelphij		/*
1017265039Sdelphij		 * If the history block is too big, double the buffer
1018265039Sdelphij		 * size and try again.
1019265039Sdelphij		 */
1020265039Sdelphij		if (resid == len) {
1021265039Sdelphij			free(buf);
1022265039Sdelphij			buf = NULL;
1023265039Sdelphij
1024265039Sdelphij			bufsize <<= 1;
1025265039Sdelphij			if ((bufsize >= HIS_BUF_LEN_MAX) ||
1026265039Sdelphij			    ((buf = malloc(bufsize)) == NULL)) {
1027265039Sdelphij				(void) fprintf(stderr, "Unable to read history: "
1028265039Sdelphij				    "out of memory\n");
1029265039Sdelphij				return;
1030265039Sdelphij			}
1031265039Sdelphij		}
1032219089Spjd	} while (len != 0);
1033265039Sdelphij	free(buf);
1034219089Spjd
1035219089Spjd	(void) printf("\nHistory:\n");
1036219089Spjd	for (int i = 0; i < num; i++) {
1037219089Spjd		uint64_t time, txg, ievent;
1038219089Spjd		char *cmd, *intstr;
1039248571Smm		boolean_t printed = B_FALSE;
1040219089Spjd
1041219089Spjd		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
1042219089Spjd		    &time) != 0)
1043248571Smm			goto next;
1044219089Spjd		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
1045219089Spjd		    &cmd) != 0) {
1046219089Spjd			if (nvlist_lookup_uint64(events[i],
1047219089Spjd			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
1048248571Smm				goto next;
1049219089Spjd			verify(nvlist_lookup_uint64(events[i],
1050219089Spjd			    ZPOOL_HIST_TXG, &txg) == 0);
1051219089Spjd			verify(nvlist_lookup_string(events[i],
1052219089Spjd			    ZPOOL_HIST_INT_STR, &intstr) == 0);
1053248571Smm			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS)
1054248571Smm				goto next;
1055219089Spjd
1056219089Spjd			(void) snprintf(internalstr,
1057219089Spjd			    sizeof (internalstr),
1058219089Spjd			    "[internal %s txg:%lld] %s",
1059219089Spjd			    zfs_history_event_names[ievent], txg,
1060219089Spjd			    intstr);
1061219089Spjd			cmd = internalstr;
1062219089Spjd		}
1063219089Spjd		tsec = time;
1064219089Spjd		(void) localtime_r(&tsec, &t);
1065219089Spjd		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
1066219089Spjd		(void) printf("%s %s\n", tbuf, cmd);
1067248571Smm		printed = B_TRUE;
1068248571Smm
1069248571Smmnext:
1070248571Smm		if (dump_opt['h'] > 1) {
1071248571Smm			if (!printed)
1072248571Smm				(void) printf("unrecognized record:\n");
1073248571Smm			dump_nvlist(events[i], 2);
1074248571Smm		}
1075219089Spjd	}
1076219089Spjd}
1077219089Spjd
1078168404Spjd/*ARGSUSED*/
1079168404Spjdstatic void
1080168404Spjddump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
1081168404Spjd{
1082168404Spjd}
1083168404Spjd
1084168404Spjdstatic uint64_t
1085268657Sdelphijblkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp,
1086268657Sdelphij    const zbookmark_phys_t *zb)
1087168404Spjd{
1088219089Spjd	if (dnp == NULL) {
1089219089Spjd		ASSERT(zb->zb_level < 0);
1090219089Spjd		if (zb->zb_object == 0)
1091219089Spjd			return (zb->zb_blkid);
1092219089Spjd		return (zb->zb_blkid * BP_GET_LSIZE(bp));
1093219089Spjd	}
1094168404Spjd
1095219089Spjd	ASSERT(zb->zb_level >= 0);
1096219089Spjd
1097219089Spjd	return ((zb->zb_blkid <<
1098219089Spjd	    (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
1099168404Spjd	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
1100168404Spjd}
1101168404Spjd
1102168404Spjdstatic void
1103263397Sdelphijsnprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
1104168404Spjd{
1105219089Spjd	const dva_t *dva = bp->blk_dva;
1106219089Spjd	int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
1107168404Spjd
1108249207Smm	if (dump_opt['b'] >= 6) {
1109263397Sdelphij		snprintf_blkptr(blkbuf, buflen, bp);
1110219089Spjd		return;
1111219089Spjd	}
1112219089Spjd
1113268649Sdelphij	if (BP_IS_EMBEDDED(bp)) {
1114268649Sdelphij		(void) sprintf(blkbuf,
1115268649Sdelphij		    "EMBEDDED et=%u %llxL/%llxP B=%llu",
1116268649Sdelphij		    (int)BPE_GET_ETYPE(bp),
1117268649Sdelphij		    (u_longlong_t)BPE_GET_LSIZE(bp),
1118268649Sdelphij		    (u_longlong_t)BPE_GET_PSIZE(bp),
1119268649Sdelphij		    (u_longlong_t)bp->blk_birth);
1120268649Sdelphij		return;
1121268649Sdelphij	}
1122268649Sdelphij
1123168404Spjd	blkbuf[0] = '\0';
1124219089Spjd	for (int i = 0; i < ndvas; i++)
1125263397Sdelphij		(void) snprintf(blkbuf + strlen(blkbuf),
1126263397Sdelphij		    buflen - strlen(blkbuf), "%llu:%llx:%llx ",
1127168404Spjd		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
1128168404Spjd		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
1129168404Spjd		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
1130168404Spjd
1131263397Sdelphij	if (BP_IS_HOLE(bp)) {
1132263397Sdelphij		(void) snprintf(blkbuf + strlen(blkbuf),
1133263397Sdelphij		    buflen - strlen(blkbuf), "B=%llu",
1134263397Sdelphij		    (u_longlong_t)bp->blk_birth);
1135263397Sdelphij	} else {
1136263397Sdelphij		(void) snprintf(blkbuf + strlen(blkbuf),
1137263397Sdelphij		    buflen - strlen(blkbuf),
1138263397Sdelphij		    "%llxL/%llxP F=%llu B=%llu/%llu",
1139263397Sdelphij		    (u_longlong_t)BP_GET_LSIZE(bp),
1140263397Sdelphij		    (u_longlong_t)BP_GET_PSIZE(bp),
1141268649Sdelphij		    (u_longlong_t)BP_GET_FILL(bp),
1142263397Sdelphij		    (u_longlong_t)bp->blk_birth,
1143263397Sdelphij		    (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
1144263397Sdelphij	}
1145168404Spjd}
1146168404Spjd
1147208047Smmstatic void
1148268657Sdelphijprint_indirect(blkptr_t *bp, const zbookmark_phys_t *zb,
1149208047Smm    const dnode_phys_t *dnp)
1150168404Spjd{
1151208047Smm	char blkbuf[BP_SPRINTF_LEN];
1152168404Spjd	int l;
1153168404Spjd
1154268649Sdelphij	if (!BP_IS_EMBEDDED(bp)) {
1155268649Sdelphij		ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
1156268649Sdelphij		ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
1157268649Sdelphij	}
1158168404Spjd
1159219089Spjd	(void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
1160168404Spjd
1161208047Smm	ASSERT(zb->zb_level >= 0);
1162168404Spjd
1163208047Smm	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
1164208047Smm		if (l == zb->zb_level) {
1165208047Smm			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
1166208047Smm		} else {
1167208047Smm			(void) printf(" ");
1168168404Spjd		}
1169168404Spjd	}
1170168404Spjd
1171263397Sdelphij	snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
1172208047Smm	(void) printf("%s\n", blkbuf);
1173208047Smm}
1174208047Smm
1175208047Smmstatic int
1176208047Smmvisit_indirect(spa_t *spa, const dnode_phys_t *dnp,
1177268657Sdelphij    blkptr_t *bp, const zbookmark_phys_t *zb)
1178208047Smm{
1179219089Spjd	int err = 0;
1180208047Smm
1181208047Smm	if (bp->blk_birth == 0)
1182208047Smm		return (0);
1183208047Smm
1184208047Smm	print_indirect(bp, zb, dnp);
1185208047Smm
1186263397Sdelphij	if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) {
1187277586Sdelphij		arc_flags_t flags = ARC_FLAG_WAIT;
1188208047Smm		int i;
1189208047Smm		blkptr_t *cbp;
1190208047Smm		int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
1191208047Smm		arc_buf_t *buf;
1192168404Spjd		uint64_t fill = 0;
1193168404Spjd
1194246666Smm		err = arc_read(NULL, spa, bp, arc_getbuf_func, &buf,
1195208047Smm		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
1196208047Smm		if (err)
1197208047Smm			return (err);
1198219089Spjd		ASSERT(buf->b_data);
1199168404Spjd
1200208047Smm		/* recursively visit blocks below this */
1201208047Smm		cbp = buf->b_data;
1202208047Smm		for (i = 0; i < epb; i++, cbp++) {
1203268657Sdelphij			zbookmark_phys_t czb;
1204168404Spjd
1205208047Smm			SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
1206208047Smm			    zb->zb_level - 1,
1207208047Smm			    zb->zb_blkid * epb + i);
1208208047Smm			err = visit_indirect(spa, dnp, cbp, &czb);
1209208047Smm			if (err)
1210208047Smm				break;
1211268649Sdelphij			fill += BP_GET_FILL(cbp);
1212168404Spjd		}
1213209962Smm		if (!err)
1214268649Sdelphij			ASSERT3U(fill, ==, BP_GET_FILL(bp));
1215208047Smm		(void) arc_buf_remove_ref(buf, &buf);
1216168404Spjd	}
1217168404Spjd
1218208047Smm	return (err);
1219168404Spjd}
1220168404Spjd
1221168404Spjd/*ARGSUSED*/
1222168404Spjdstatic void
1223208047Smmdump_indirect(dnode_t *dn)
1224168404Spjd{
1225208047Smm	dnode_phys_t *dnp = dn->dn_phys;
1226208047Smm	int j;
1227268657Sdelphij	zbookmark_phys_t czb;
1228168404Spjd
1229168404Spjd	(void) printf("Indirect blocks:\n");
1230168404Spjd
1231219089Spjd	SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset),
1232208047Smm	    dn->dn_object, dnp->dn_nlevels - 1, 0);
1233208047Smm	for (j = 0; j < dnp->dn_nblkptr; j++) {
1234208047Smm		czb.zb_blkid = j;
1235219089Spjd		(void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp,
1236208047Smm		    &dnp->dn_blkptr[j], &czb);
1237208047Smm	}
1238168404Spjd
1239168404Spjd	(void) printf("\n");
1240168404Spjd}
1241168404Spjd
1242168404Spjd/*ARGSUSED*/
1243168404Spjdstatic void
1244168404Spjddump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
1245168404Spjd{
1246168404Spjd	dsl_dir_phys_t *dd = data;
1247168404Spjd	time_t crtime;
1248219089Spjd	char nice[32];
1249168404Spjd
1250168404Spjd	if (dd == NULL)
1251168404Spjd		return;
1252168404Spjd
1253185029Spjd	ASSERT3U(size, >=, sizeof (dsl_dir_phys_t));
1254168404Spjd
1255168404Spjd	crtime = dd->dd_creation_time;
1256168404Spjd	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1257168404Spjd	(void) printf("\t\thead_dataset_obj = %llu\n",
1258168404Spjd	    (u_longlong_t)dd->dd_head_dataset_obj);
1259168404Spjd	(void) printf("\t\tparent_dir_obj = %llu\n",
1260168404Spjd	    (u_longlong_t)dd->dd_parent_obj);
1261185029Spjd	(void) printf("\t\torigin_obj = %llu\n",
1262185029Spjd	    (u_longlong_t)dd->dd_origin_obj);
1263168404Spjd	(void) printf("\t\tchild_dir_zapobj = %llu\n",
1264168404Spjd	    (u_longlong_t)dd->dd_child_dir_zapobj);
1265219089Spjd	zdb_nicenum(dd->dd_used_bytes, nice);
1266185029Spjd	(void) printf("\t\tused_bytes = %s\n", nice);
1267219089Spjd	zdb_nicenum(dd->dd_compressed_bytes, nice);
1268185029Spjd	(void) printf("\t\tcompressed_bytes = %s\n", nice);
1269219089Spjd	zdb_nicenum(dd->dd_uncompressed_bytes, nice);
1270185029Spjd	(void) printf("\t\tuncompressed_bytes = %s\n", nice);
1271219089Spjd	zdb_nicenum(dd->dd_quota, nice);
1272185029Spjd	(void) printf("\t\tquota = %s\n", nice);
1273219089Spjd	zdb_nicenum(dd->dd_reserved, nice);
1274185029Spjd	(void) printf("\t\treserved = %s\n", nice);
1275168404Spjd	(void) printf("\t\tprops_zapobj = %llu\n",
1276168404Spjd	    (u_longlong_t)dd->dd_props_zapobj);
1277185029Spjd	(void) printf("\t\tdeleg_zapobj = %llu\n",
1278185029Spjd	    (u_longlong_t)dd->dd_deleg_zapobj);
1279185029Spjd	(void) printf("\t\tflags = %llx\n",
1280185029Spjd	    (u_longlong_t)dd->dd_flags);
1281185029Spjd
1282185029Spjd#define	DO(which) \
1283219089Spjd	zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
1284185029Spjd	(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
1285185029Spjd	DO(HEAD);
1286185029Spjd	DO(SNAP);
1287185029Spjd	DO(CHILD);
1288185029Spjd	DO(CHILD_RSRV);
1289185029Spjd	DO(REFRSRV);
1290185029Spjd#undef DO
1291168404Spjd}
1292168404Spjd
1293168404Spjd/*ARGSUSED*/
1294168404Spjdstatic void
1295168404Spjddump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
1296168404Spjd{
1297168404Spjd	dsl_dataset_phys_t *ds = data;
1298168404Spjd	time_t crtime;
1299219089Spjd	char used[32], compressed[32], uncompressed[32], unique[32];
1300168404Spjd	char blkbuf[BP_SPRINTF_LEN];
1301168404Spjd
1302168404Spjd	if (ds == NULL)
1303168404Spjd		return;
1304168404Spjd
1305168404Spjd	ASSERT(size == sizeof (*ds));
1306168404Spjd	crtime = ds->ds_creation_time;
1307236884Smm	zdb_nicenum(ds->ds_referenced_bytes, used);
1308219089Spjd	zdb_nicenum(ds->ds_compressed_bytes, compressed);
1309219089Spjd	zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
1310219089Spjd	zdb_nicenum(ds->ds_unique_bytes, unique);
1311263397Sdelphij	snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
1312168404Spjd
1313185029Spjd	(void) printf("\t\tdir_obj = %llu\n",
1314168404Spjd	    (u_longlong_t)ds->ds_dir_obj);
1315168404Spjd	(void) printf("\t\tprev_snap_obj = %llu\n",
1316168404Spjd	    (u_longlong_t)ds->ds_prev_snap_obj);
1317168404Spjd	(void) printf("\t\tprev_snap_txg = %llu\n",
1318168404Spjd	    (u_longlong_t)ds->ds_prev_snap_txg);
1319168404Spjd	(void) printf("\t\tnext_snap_obj = %llu\n",
1320168404Spjd	    (u_longlong_t)ds->ds_next_snap_obj);
1321168404Spjd	(void) printf("\t\tsnapnames_zapobj = %llu\n",
1322168404Spjd	    (u_longlong_t)ds->ds_snapnames_zapobj);
1323168404Spjd	(void) printf("\t\tnum_children = %llu\n",
1324168404Spjd	    (u_longlong_t)ds->ds_num_children);
1325219089Spjd	(void) printf("\t\tuserrefs_obj = %llu\n",
1326219089Spjd	    (u_longlong_t)ds->ds_userrefs_obj);
1327168404Spjd	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1328168404Spjd	(void) printf("\t\tcreation_txg = %llu\n",
1329168404Spjd	    (u_longlong_t)ds->ds_creation_txg);
1330168404Spjd	(void) printf("\t\tdeadlist_obj = %llu\n",
1331168404Spjd	    (u_longlong_t)ds->ds_deadlist_obj);
1332168404Spjd	(void) printf("\t\tused_bytes = %s\n", used);
1333168404Spjd	(void) printf("\t\tcompressed_bytes = %s\n", compressed);
1334168404Spjd	(void) printf("\t\tuncompressed_bytes = %s\n", uncompressed);
1335168404Spjd	(void) printf("\t\tunique = %s\n", unique);
1336168404Spjd	(void) printf("\t\tfsid_guid = %llu\n",
1337168404Spjd	    (u_longlong_t)ds->ds_fsid_guid);
1338168404Spjd	(void) printf("\t\tguid = %llu\n",
1339168404Spjd	    (u_longlong_t)ds->ds_guid);
1340168404Spjd	(void) printf("\t\tflags = %llx\n",
1341168404Spjd	    (u_longlong_t)ds->ds_flags);
1342185029Spjd	(void) printf("\t\tnext_clones_obj = %llu\n",
1343185029Spjd	    (u_longlong_t)ds->ds_next_clones_obj);
1344185029Spjd	(void) printf("\t\tprops_obj = %llu\n",
1345185029Spjd	    (u_longlong_t)ds->ds_props_obj);
1346168404Spjd	(void) printf("\t\tbp = %s\n", blkbuf);
1347168404Spjd}
1348168404Spjd
1349219089Spjd/* ARGSUSED */
1350219089Spjdstatic int
1351236884Smmdump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
1352236884Smm{
1353236884Smm	char blkbuf[BP_SPRINTF_LEN];
1354236884Smm
1355236884Smm	if (bp->blk_birth != 0) {
1356263397Sdelphij		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
1357236884Smm		(void) printf("\t%s\n", blkbuf);
1358236884Smm	}
1359236884Smm	return (0);
1360236884Smm}
1361236884Smm
1362236884Smmstatic void
1363236884Smmdump_bptree(objset_t *os, uint64_t obj, char *name)
1364236884Smm{
1365236884Smm	char bytes[32];
1366236884Smm	bptree_phys_t *bt;
1367236884Smm	dmu_buf_t *db;
1368236884Smm
1369236884Smm	if (dump_opt['d'] < 3)
1370236884Smm		return;
1371236884Smm
1372236884Smm	VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
1373236884Smm	bt = db->db_data;
1374236884Smm	zdb_nicenum(bt->bt_bytes, bytes);
1375236884Smm	(void) printf("\n    %s: %llu datasets, %s\n",
1376236884Smm	    name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
1377236884Smm	dmu_buf_rele(db, FTAG);
1378236884Smm
1379236884Smm	if (dump_opt['d'] < 5)
1380236884Smm		return;
1381236884Smm
1382236884Smm	(void) printf("\n");
1383236884Smm
1384236884Smm	(void) bptree_iterate(os, obj, B_FALSE, dump_bptree_cb, NULL, NULL);
1385236884Smm}
1386236884Smm
1387236884Smm/* ARGSUSED */
1388236884Smmstatic int
1389219089Spjddump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
1390219089Spjd{
1391219089Spjd	char blkbuf[BP_SPRINTF_LEN];
1392219089Spjd
1393219089Spjd	ASSERT(bp->blk_birth != 0);
1394263397Sdelphij	snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
1395219089Spjd	(void) printf("\t%s\n", blkbuf);
1396219089Spjd	return (0);
1397219089Spjd}
1398219089Spjd
1399168404Spjdstatic void
1400247852Smmdump_bpobj(bpobj_t *bpo, char *name, int indent)
1401168404Spjd{
1402219089Spjd	char bytes[32];
1403219089Spjd	char comp[32];
1404219089Spjd	char uncomp[32];
1405168404Spjd
1406168404Spjd	if (dump_opt['d'] < 3)
1407168404Spjd		return;
1408168404Spjd
1409219089Spjd	zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes);
1410247852Smm	if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
1411219089Spjd		zdb_nicenum(bpo->bpo_phys->bpo_comp, comp);
1412219089Spjd		zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp);
1413247852Smm		(void) printf("    %*s: object %llu, %llu local blkptrs, "
1414247852Smm		    "%llu subobjs, %s (%s/%s comp)\n",
1415247852Smm		    indent * 8, name,
1416247852Smm		    (u_longlong_t)bpo->bpo_object,
1417247852Smm		    (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs,
1418219089Spjd		    (u_longlong_t)bpo->bpo_phys->bpo_num_subobjs,
1419168404Spjd		    bytes, comp, uncomp);
1420247852Smm
1421247852Smm		for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) {
1422247852Smm			uint64_t subobj;
1423247852Smm			bpobj_t subbpo;
1424247852Smm			int error;
1425247852Smm			VERIFY0(dmu_read(bpo->bpo_os,
1426247852Smm			    bpo->bpo_phys->bpo_subobjs,
1427247852Smm			    i * sizeof (subobj), sizeof (subobj), &subobj, 0));
1428247852Smm			error = bpobj_open(&subbpo, bpo->bpo_os, subobj);
1429247852Smm			if (error != 0) {
1430247852Smm				(void) printf("ERROR %u while trying to open "
1431247852Smm				    "subobj id %llu\n",
1432247852Smm				    error, (u_longlong_t)subobj);
1433247852Smm				continue;
1434247852Smm			}
1435247852Smm			dump_bpobj(&subbpo, "subobj", indent + 1);
1436248267Smm			bpobj_close(&subbpo);
1437247852Smm		}
1438168404Spjd	} else {
1439247852Smm		(void) printf("    %*s: object %llu, %llu blkptrs, %s\n",
1440247852Smm		    indent * 8, name,
1441247852Smm		    (u_longlong_t)bpo->bpo_object,
1442247852Smm		    (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs,
1443247852Smm		    bytes);
1444168404Spjd	}
1445168404Spjd
1446219089Spjd	if (dump_opt['d'] < 5)
1447168404Spjd		return;
1448168404Spjd
1449168404Spjd
1450247852Smm	if (indent == 0) {
1451247852Smm		(void) bpobj_iterate_nofree(bpo, dump_bpobj_cb, NULL, NULL);
1452247852Smm		(void) printf("\n");
1453247852Smm	}
1454219089Spjd}
1455168404Spjd
1456219089Spjdstatic void
1457219089Spjddump_deadlist(dsl_deadlist_t *dl)
1458219089Spjd{
1459219089Spjd	dsl_deadlist_entry_t *dle;
1460247852Smm	uint64_t unused;
1461219089Spjd	char bytes[32];
1462219089Spjd	char comp[32];
1463219089Spjd	char uncomp[32];
1464219089Spjd
1465219089Spjd	if (dump_opt['d'] < 3)
1466219089Spjd		return;
1467219089Spjd
1468273349Sdelphij	if (dl->dl_oldfmt) {
1469273349Sdelphij		dump_bpobj(&dl->dl_bpobj, "old-format deadlist", 0);
1470273349Sdelphij		return;
1471273349Sdelphij	}
1472273349Sdelphij
1473219089Spjd	zdb_nicenum(dl->dl_phys->dl_used, bytes);
1474219089Spjd	zdb_nicenum(dl->dl_phys->dl_comp, comp);
1475219089Spjd	zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp);
1476219089Spjd	(void) printf("\n    Deadlist: %s (%s/%s comp)\n",
1477219089Spjd	    bytes, comp, uncomp);
1478219089Spjd
1479219089Spjd	if (dump_opt['d'] < 4)
1480219089Spjd		return;
1481219089Spjd
1482219089Spjd	(void) printf("\n");
1483219089Spjd
1484247852Smm	/* force the tree to be loaded */
1485247852Smm	dsl_deadlist_space_range(dl, 0, UINT64_MAX, &unused, &unused, &unused);
1486247852Smm
1487219089Spjd	for (dle = avl_first(&dl->dl_tree); dle;
1488219089Spjd	    dle = AVL_NEXT(&dl->dl_tree, dle)) {
1489247852Smm		if (dump_opt['d'] >= 5) {
1490247852Smm			char buf[128];
1491247852Smm			(void) snprintf(buf, sizeof (buf), "mintxg %llu -> ",
1492247852Smm			    (longlong_t)dle->dle_mintxg,
1493247852Smm			    (longlong_t)dle->dle_bpobj.bpo_object);
1494219089Spjd
1495247852Smm			dump_bpobj(&dle->dle_bpobj, buf, 0);
1496247852Smm		} else {
1497247852Smm			(void) printf("mintxg %llu -> obj %llu\n",
1498247852Smm			    (longlong_t)dle->dle_mintxg,
1499247852Smm			    (longlong_t)dle->dle_bpobj.bpo_object);
1500247852Smm
1501247852Smm		}
1502168404Spjd	}
1503168404Spjd}
1504168404Spjd
1505185029Spjdstatic avl_tree_t idx_tree;
1506185029Spjdstatic avl_tree_t domain_tree;
1507185029Spjdstatic boolean_t fuid_table_loaded;
1508219089Spjdstatic boolean_t sa_loaded;
1509219089Spjdsa_attr_type_t *sa_attr_table;
1510185029Spjd
1511185029Spjdstatic void
1512185029Spjdfuid_table_destroy()
1513185029Spjd{
1514185029Spjd	if (fuid_table_loaded) {
1515185029Spjd		zfs_fuid_table_destroy(&idx_tree, &domain_tree);
1516185029Spjd		fuid_table_loaded = B_FALSE;
1517185029Spjd	}
1518185029Spjd}
1519185029Spjd
1520185029Spjd/*
1521185029Spjd * print uid or gid information.
1522185029Spjd * For normal POSIX id just the id is printed in decimal format.
1523185029Spjd * For CIFS files with FUID the fuid is printed in hex followed by
1524247852Smm * the domain-rid string.
1525185029Spjd */
1526185029Spjdstatic void
1527185029Spjdprint_idstr(uint64_t id, const char *id_type)
1528185029Spjd{
1529185029Spjd	if (FUID_INDEX(id)) {
1530185029Spjd		char *domain;
1531185029Spjd
1532185029Spjd		domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id));
1533185029Spjd		(void) printf("\t%s     %llx [%s-%d]\n", id_type,
1534185029Spjd		    (u_longlong_t)id, domain, (int)FUID_RID(id));
1535185029Spjd	} else {
1536185029Spjd		(void) printf("\t%s     %llu\n", id_type, (u_longlong_t)id);
1537185029Spjd	}
1538185029Spjd
1539185029Spjd}
1540185029Spjd
1541185029Spjdstatic void
1542219089Spjddump_uidgid(objset_t *os, uint64_t uid, uint64_t gid)
1543185029Spjd{
1544185029Spjd	uint32_t uid_idx, gid_idx;
1545185029Spjd
1546219089Spjd	uid_idx = FUID_INDEX(uid);
1547219089Spjd	gid_idx = FUID_INDEX(gid);
1548185029Spjd
1549185029Spjd	/* Load domain table, if not already loaded */
1550185029Spjd	if (!fuid_table_loaded && (uid_idx || gid_idx)) {
1551185029Spjd		uint64_t fuid_obj;
1552185029Spjd
1553185029Spjd		/* first find the fuid object.  It lives in the master node */
1554185029Spjd		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
1555185029Spjd		    8, 1, &fuid_obj) == 0);
1556209962Smm		zfs_fuid_avl_tree_create(&idx_tree, &domain_tree);
1557185029Spjd		(void) zfs_fuid_table_load(os, fuid_obj,
1558185029Spjd		    &idx_tree, &domain_tree);
1559185029Spjd		fuid_table_loaded = B_TRUE;
1560185029Spjd	}
1561185029Spjd
1562219089Spjd	print_idstr(uid, "uid");
1563219089Spjd	print_idstr(gid, "gid");
1564185029Spjd}
1565185029Spjd
1566168404Spjd/*ARGSUSED*/
1567168404Spjdstatic void
1568168404Spjddump_znode(objset_t *os, uint64_t object, void *data, size_t size)
1569168404Spjd{
1570219089Spjd	char path[MAXPATHLEN * 2];	/* allow for xattr and failure prefix */
1571219089Spjd	sa_handle_t *hdl;
1572219089Spjd	uint64_t xattr, rdev, gen;
1573219089Spjd	uint64_t uid, gid, mode, fsize, parent, links;
1574219089Spjd	uint64_t pflags;
1575219089Spjd	uint64_t acctm[2], modtm[2], chgtm[2], crtm[2];
1576168404Spjd	time_t z_crtime, z_atime, z_mtime, z_ctime;
1577219089Spjd	sa_bulk_attr_t bulk[12];
1578219089Spjd	int idx = 0;
1579168404Spjd	int error;
1580168404Spjd
1581219089Spjd	if (!sa_loaded) {
1582219089Spjd		uint64_t sa_attrs = 0;
1583219089Spjd		uint64_t version;
1584168404Spjd
1585219089Spjd		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
1586219089Spjd		    8, 1, &version) == 0);
1587219089Spjd		if (version >= ZPL_VERSION_SA) {
1588219089Spjd			VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
1589219089Spjd			    8, 1, &sa_attrs) == 0);
1590219089Spjd		}
1591219089Spjd		if ((error = sa_setup(os, sa_attrs, zfs_attr_table,
1592219089Spjd		    ZPL_END, &sa_attr_table)) != 0) {
1593219089Spjd			(void) printf("sa_setup failed errno %d, can't "
1594219089Spjd			    "display znode contents\n", error);
1595219089Spjd			return;
1596219089Spjd		}
1597219089Spjd		sa_loaded = B_TRUE;
1598219089Spjd	}
1599219089Spjd
1600219089Spjd	if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
1601219089Spjd		(void) printf("Failed to get handle for SA znode\n");
1602219089Spjd		return;
1603219089Spjd	}
1604219089Spjd
1605219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_UID], NULL, &uid, 8);
1606219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GID], NULL, &gid, 8);
1607219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_LINKS], NULL,
1608219089Spjd	    &links, 8);
1609219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GEN], NULL, &gen, 8);
1610219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MODE], NULL,
1611219089Spjd	    &mode, 8);
1612219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_PARENT],
1613219089Spjd	    NULL, &parent, 8);
1614219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_SIZE], NULL,
1615219089Spjd	    &fsize, 8);
1616219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_ATIME], NULL,
1617219089Spjd	    acctm, 16);
1618219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MTIME], NULL,
1619219089Spjd	    modtm, 16);
1620219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CRTIME], NULL,
1621219089Spjd	    crtm, 16);
1622219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CTIME], NULL,
1623219089Spjd	    chgtm, 16);
1624219089Spjd	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_FLAGS], NULL,
1625219089Spjd	    &pflags, 8);
1626219089Spjd
1627219089Spjd	if (sa_bulk_lookup(hdl, bulk, idx)) {
1628219089Spjd		(void) sa_handle_destroy(hdl);
1629219089Spjd		return;
1630219089Spjd	}
1631219089Spjd
1632168404Spjd	error = zfs_obj_to_path(os, object, path, sizeof (path));
1633168404Spjd	if (error != 0) {
1634168404Spjd		(void) snprintf(path, sizeof (path), "\?\?\?<object#%llu>",
1635168404Spjd		    (u_longlong_t)object);
1636168404Spjd	}
1637168404Spjd	if (dump_opt['d'] < 3) {
1638168404Spjd		(void) printf("\t%s\n", path);
1639219089Spjd		(void) sa_handle_destroy(hdl);
1640168404Spjd		return;
1641168404Spjd	}
1642168404Spjd
1643219089Spjd	z_crtime = (time_t)crtm[0];
1644219089Spjd	z_atime = (time_t)acctm[0];
1645219089Spjd	z_mtime = (time_t)modtm[0];
1646219089Spjd	z_ctime = (time_t)chgtm[0];
1647168404Spjd
1648168404Spjd	(void) printf("\tpath	%s\n", path);
1649219089Spjd	dump_uidgid(os, uid, gid);
1650168404Spjd	(void) printf("\tatime	%s", ctime(&z_atime));
1651168404Spjd	(void) printf("\tmtime	%s", ctime(&z_mtime));
1652168404Spjd	(void) printf("\tctime	%s", ctime(&z_ctime));
1653168404Spjd	(void) printf("\tcrtime	%s", ctime(&z_crtime));
1654219089Spjd	(void) printf("\tgen	%llu\n", (u_longlong_t)gen);
1655219089Spjd	(void) printf("\tmode	%llo\n", (u_longlong_t)mode);
1656219089Spjd	(void) printf("\tsize	%llu\n", (u_longlong_t)fsize);
1657219089Spjd	(void) printf("\tparent	%llu\n", (u_longlong_t)parent);
1658219089Spjd	(void) printf("\tlinks	%llu\n", (u_longlong_t)links);
1659219089Spjd	(void) printf("\tpflags	%llx\n", (u_longlong_t)pflags);
1660219089Spjd	if (sa_lookup(hdl, sa_attr_table[ZPL_XATTR], &xattr,
1661219089Spjd	    sizeof (uint64_t)) == 0)
1662219089Spjd		(void) printf("\txattr	%llu\n", (u_longlong_t)xattr);
1663219089Spjd	if (sa_lookup(hdl, sa_attr_table[ZPL_RDEV], &rdev,
1664219089Spjd	    sizeof (uint64_t)) == 0)
1665219089Spjd		(void) printf("\trdev	0x%016llx\n", (u_longlong_t)rdev);
1666219089Spjd	sa_handle_destroy(hdl);
1667168404Spjd}
1668168404Spjd
1669168404Spjd/*ARGSUSED*/
1670168404Spjdstatic void
1671168404Spjddump_acl(objset_t *os, uint64_t object, void *data, size_t size)
1672168404Spjd{
1673168404Spjd}
1674168404Spjd
1675168404Spjd/*ARGSUSED*/
1676168404Spjdstatic void
1677168404Spjddump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
1678168404Spjd{
1679168404Spjd}
1680168404Spjd
1681219089Spjdstatic object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
1682168404Spjd	dump_none,		/* unallocated			*/
1683168404Spjd	dump_zap,		/* object directory		*/
1684168404Spjd	dump_uint64,		/* object array			*/
1685168404Spjd	dump_none,		/* packed nvlist		*/
1686168404Spjd	dump_packed_nvlist,	/* packed nvlist size		*/
1687168404Spjd	dump_none,		/* bplist			*/
1688168404Spjd	dump_none,		/* bplist header		*/
1689168404Spjd	dump_none,		/* SPA space map header		*/
1690168404Spjd	dump_none,		/* SPA space map		*/
1691168404Spjd	dump_none,		/* ZIL intent log		*/
1692168404Spjd	dump_dnode,		/* DMU dnode			*/
1693168404Spjd	dump_dmu_objset,	/* DMU objset			*/
1694168404Spjd	dump_dsl_dir,		/* DSL directory		*/
1695168404Spjd	dump_zap,		/* DSL directory child map	*/
1696168404Spjd	dump_zap,		/* DSL dataset snap map		*/
1697168404Spjd	dump_zap,		/* DSL props			*/
1698168404Spjd	dump_dsl_dataset,	/* DSL dataset			*/
1699168404Spjd	dump_znode,		/* ZFS znode			*/
1700185029Spjd	dump_acl,		/* ZFS V0 ACL			*/
1701168404Spjd	dump_uint8,		/* ZFS plain file		*/
1702185029Spjd	dump_zpldir,		/* ZFS directory		*/
1703168404Spjd	dump_zap,		/* ZFS master node		*/
1704168404Spjd	dump_zap,		/* ZFS delete queue		*/
1705168404Spjd	dump_uint8,		/* zvol object			*/
1706168404Spjd	dump_zap,		/* zvol prop			*/
1707168404Spjd	dump_uint8,		/* other uint8[]		*/
1708168404Spjd	dump_uint64,		/* other uint64[]		*/
1709168404Spjd	dump_zap,		/* other ZAP			*/
1710168404Spjd	dump_zap,		/* persistent error log		*/
1711168404Spjd	dump_uint8,		/* SPA history			*/
1712248571Smm	dump_history_offsets,	/* SPA history offsets		*/
1713168404Spjd	dump_zap,		/* Pool properties		*/
1714185029Spjd	dump_zap,		/* DSL permissions		*/
1715185029Spjd	dump_acl,		/* ZFS ACL			*/
1716185029Spjd	dump_uint8,		/* ZFS SYSACL			*/
1717185029Spjd	dump_none,		/* FUID nvlist			*/
1718185029Spjd	dump_packed_nvlist,	/* FUID nvlist size		*/
1719185029Spjd	dump_zap,		/* DSL dataset next clones	*/
1720185029Spjd	dump_zap,		/* DSL scrub queue		*/
1721209962Smm	dump_zap,		/* ZFS user/group used		*/
1722209962Smm	dump_zap,		/* ZFS user/group quota		*/
1723219089Spjd	dump_zap,		/* snapshot refcount tags	*/
1724219089Spjd	dump_ddt_zap,		/* DDT ZAP object		*/
1725219089Spjd	dump_zap,		/* DDT statistics		*/
1726219089Spjd	dump_znode,		/* SA object			*/
1727219089Spjd	dump_zap,		/* SA Master Node		*/
1728219089Spjd	dump_sa_attrs,		/* SA attribute registration	*/
1729219089Spjd	dump_sa_layouts,	/* SA attribute layouts		*/
1730219089Spjd	dump_zap,		/* DSL scrub translations	*/
1731219089Spjd	dump_none,		/* fake dedup BP		*/
1732219089Spjd	dump_zap,		/* deadlist			*/
1733219089Spjd	dump_none,		/* deadlist hdr			*/
1734219089Spjd	dump_zap,		/* dsl clones			*/
1735219089Spjd	dump_none,		/* bpobj subobjs		*/
1736219089Spjd	dump_unknown,		/* Unknown type, must be last	*/
1737168404Spjd};
1738168404Spjd
1739168404Spjdstatic void
1740168404Spjddump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
1741168404Spjd{
1742168404Spjd	dmu_buf_t *db = NULL;
1743168404Spjd	dmu_object_info_t doi;
1744168404Spjd	dnode_t *dn;
1745168404Spjd	void *bonus = NULL;
1746168404Spjd	size_t bsize = 0;
1747219089Spjd	char iblk[32], dblk[32], lsize[32], asize[32], fill[32];
1748219089Spjd	char bonus_size[32];
1749168404Spjd	char aux[50];
1750168404Spjd	int error;
1751168404Spjd
1752168404Spjd	if (*print_header) {
1753219089Spjd		(void) printf("\n%10s  %3s  %5s  %5s  %5s  %5s  %6s  %s\n",
1754219089Spjd		    "Object", "lvl", "iblk", "dblk", "dsize", "lsize",
1755219089Spjd		    "%full", "type");
1756168404Spjd		*print_header = 0;
1757168404Spjd	}
1758168404Spjd
1759168404Spjd	if (object == 0) {
1760219089Spjd		dn = DMU_META_DNODE(os);
1761168404Spjd	} else {
1762168404Spjd		error = dmu_bonus_hold(os, object, FTAG, &db);
1763168404Spjd		if (error)
1764168404Spjd			fatal("dmu_bonus_hold(%llu) failed, errno %u",
1765168404Spjd			    object, error);
1766168404Spjd		bonus = db->db_data;
1767168404Spjd		bsize = db->db_size;
1768219089Spjd		dn = DB_DNODE((dmu_buf_impl_t *)db);
1769168404Spjd	}
1770168404Spjd	dmu_object_info_from_dnode(dn, &doi);
1771168404Spjd
1772219089Spjd	zdb_nicenum(doi.doi_metadata_block_size, iblk);
1773219089Spjd	zdb_nicenum(doi.doi_data_block_size, dblk);
1774219089Spjd	zdb_nicenum(doi.doi_max_offset, lsize);
1775219089Spjd	zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize);
1776219089Spjd	zdb_nicenum(doi.doi_bonus_size, bonus_size);
1777219089Spjd	(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
1778219089Spjd	    doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
1779219089Spjd	    doi.doi_max_offset);
1780168404Spjd
1781168404Spjd	aux[0] = '\0';
1782168404Spjd
1783185029Spjd	if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) {
1784168404Spjd		(void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)",
1785219089Spjd		    ZDB_CHECKSUM_NAME(doi.doi_checksum));
1786185029Spjd	}
1787168404Spjd
1788185029Spjd	if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) {
1789168404Spjd		(void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)",
1790219089Spjd		    ZDB_COMPRESS_NAME(doi.doi_compress));
1791185029Spjd	}
1792168404Spjd
1793219089Spjd	(void) printf("%10lld  %3u  %5s  %5s  %5s  %5s  %6s  %s%s\n",
1794219089Spjd	    (u_longlong_t)object, doi.doi_indirection, iblk, dblk,
1795219089Spjd	    asize, lsize, fill, ZDB_OT_NAME(doi.doi_type), aux);
1796168404Spjd
1797168404Spjd	if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) {
1798219089Spjd		(void) printf("%10s  %3s  %5s  %5s  %5s  %5s  %6s  %s\n",
1799219089Spjd		    "", "", "", "", "", bonus_size, "bonus",
1800219089Spjd		    ZDB_OT_NAME(doi.doi_bonus_type));
1801168404Spjd	}
1802168404Spjd
1803168404Spjd	if (verbosity >= 4) {
1804219089Spjd		(void) printf("\tdnode flags: %s%s%s\n",
1805209962Smm		    (dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) ?
1806209962Smm		    "USED_BYTES " : "",
1807209962Smm		    (dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED) ?
1808219089Spjd		    "USERUSED_ACCOUNTED " : "",
1809219089Spjd		    (dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR) ?
1810219089Spjd		    "SPILL_BLKPTR" : "");
1811209962Smm		(void) printf("\tdnode maxblkid: %llu\n",
1812209962Smm		    (longlong_t)dn->dn_phys->dn_maxblkid);
1813209962Smm
1814219089Spjd		object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object,
1815219089Spjd		    bonus, bsize);
1816219089Spjd		object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
1817168404Spjd		*print_header = 1;
1818168404Spjd	}
1819168404Spjd
1820168404Spjd	if (verbosity >= 5)
1821208047Smm		dump_indirect(dn);
1822168404Spjd
1823168404Spjd	if (verbosity >= 5) {
1824168404Spjd		/*
1825168404Spjd		 * Report the list of segments that comprise the object.
1826168404Spjd		 */
1827168404Spjd		uint64_t start = 0;
1828168404Spjd		uint64_t end;
1829168404Spjd		uint64_t blkfill = 1;
1830168404Spjd		int minlvl = 1;
1831168404Spjd
1832168404Spjd		if (dn->dn_type == DMU_OT_DNODE) {
1833168404Spjd			minlvl = 0;
1834168404Spjd			blkfill = DNODES_PER_BLOCK;
1835168404Spjd		}
1836168404Spjd
1837168404Spjd		for (;;) {
1838219089Spjd			char segsize[32];
1839185029Spjd			error = dnode_next_offset(dn,
1840185029Spjd			    0, &start, minlvl, blkfill, 0);
1841168404Spjd			if (error)
1842168404Spjd				break;
1843168404Spjd			end = start;
1844185029Spjd			error = dnode_next_offset(dn,
1845185029Spjd			    DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
1846219089Spjd			zdb_nicenum(end - start, segsize);
1847168404Spjd			(void) printf("\t\tsegment [%016llx, %016llx)"
1848168404Spjd			    " size %5s\n", (u_longlong_t)start,
1849168404Spjd			    (u_longlong_t)end, segsize);
1850168404Spjd			if (error)
1851168404Spjd				break;
1852168404Spjd			start = end;
1853168404Spjd		}
1854168404Spjd	}
1855168404Spjd
1856168404Spjd	if (db != NULL)
1857168404Spjd		dmu_buf_rele(db, FTAG);
1858168404Spjd}
1859168404Spjd
1860168404Spjdstatic char *objset_types[DMU_OST_NUMTYPES] = {
1861168404Spjd	"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
1862168404Spjd
1863168404Spjdstatic void
1864168404Spjddump_dir(objset_t *os)
1865168404Spjd{
1866168404Spjd	dmu_objset_stats_t dds;
1867168404Spjd	uint64_t object, object_count;
1868168404Spjd	uint64_t refdbytes, usedobjs, scratch;
1869219089Spjd	char numbuf[32];
1870209962Smm	char blkbuf[BP_SPRINTF_LEN + 20];
1871168404Spjd	char osname[MAXNAMELEN];
1872168404Spjd	char *type = "UNKNOWN";
1873168404Spjd	int verbosity = dump_opt['d'];
1874168404Spjd	int print_header = 1;
1875168404Spjd	int i, error;
1876168404Spjd
1877248571Smm	dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
1878168404Spjd	dmu_objset_fast_stat(os, &dds);
1879248571Smm	dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
1880168404Spjd
1881168404Spjd	if (dds.dds_type < DMU_OST_NUMTYPES)
1882168404Spjd		type = objset_types[dds.dds_type];
1883168404Spjd
1884168404Spjd	if (dds.dds_type == DMU_OST_META) {
1885168404Spjd		dds.dds_creation_txg = TXG_INITIAL;
1886268649Sdelphij		usedobjs = BP_GET_FILL(os->os_rootbp);
1887277585Sdelphij		refdbytes = dsl_dir_phys(os->os_spa->spa_dsl_pool->dp_mos_dir)->
1888277585Sdelphij		    dd_used_bytes;
1889168404Spjd	} else {
1890168404Spjd		dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch);
1891168404Spjd	}
1892168404Spjd
1893268649Sdelphij	ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
1894168404Spjd
1895219089Spjd	zdb_nicenum(refdbytes, numbuf);
1896168404Spjd
1897168404Spjd	if (verbosity >= 4) {
1898263397Sdelphij		(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
1899263397Sdelphij		(void) snprintf_blkptr(blkbuf + strlen(blkbuf),
1900263397Sdelphij		    sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp);
1901168404Spjd	} else {
1902168404Spjd		blkbuf[0] = '\0';
1903168404Spjd	}
1904168404Spjd
1905168404Spjd	dmu_objset_name(os, osname);
1906168404Spjd
1907168404Spjd	(void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, "
1908168404Spjd	    "%s, %llu objects%s\n",
1909168404Spjd	    osname, type, (u_longlong_t)dmu_objset_id(os),
1910168404Spjd	    (u_longlong_t)dds.dds_creation_txg,
1911168404Spjd	    numbuf, (u_longlong_t)usedobjs, blkbuf);
1912168404Spjd
1913219089Spjd	if (zopt_objects != 0) {
1914219089Spjd		for (i = 0; i < zopt_objects; i++)
1915219089Spjd			dump_object(os, zopt_object[i], verbosity,
1916219089Spjd			    &print_header);
1917219089Spjd		(void) printf("\n");
1918219089Spjd		return;
1919219089Spjd	}
1920168404Spjd
1921219089Spjd	if (dump_opt['i'] != 0 || verbosity >= 2)
1922219089Spjd		dump_intent_log(dmu_objset_zil(os));
1923219089Spjd
1924168404Spjd	if (dmu_objset_ds(os) != NULL)
1925219089Spjd		dump_deadlist(&dmu_objset_ds(os)->ds_deadlist);
1926168404Spjd
1927168404Spjd	if (verbosity < 2)
1928168404Spjd		return;
1929168404Spjd
1930263397Sdelphij	if (BP_IS_HOLE(os->os_rootbp))
1931185029Spjd		return;
1932185029Spjd
1933168404Spjd	dump_object(os, 0, verbosity, &print_header);
1934209962Smm	object_count = 0;
1935219089Spjd	if (DMU_USERUSED_DNODE(os) != NULL &&
1936219089Spjd	    DMU_USERUSED_DNODE(os)->dn_type != 0) {
1937209962Smm		dump_object(os, DMU_USERUSED_OBJECT, verbosity, &print_header);
1938209962Smm		dump_object(os, DMU_GROUPUSED_OBJECT, verbosity, &print_header);
1939209962Smm	}
1940168404Spjd
1941168404Spjd	object = 0;
1942168404Spjd	while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) {
1943168404Spjd		dump_object(os, object, verbosity, &print_header);
1944168404Spjd		object_count++;
1945168404Spjd	}
1946168404Spjd
1947168404Spjd	ASSERT3U(object_count, ==, usedobjs);
1948168404Spjd
1949168404Spjd	(void) printf("\n");
1950168404Spjd
1951209962Smm	if (error != ESRCH) {
1952209962Smm		(void) fprintf(stderr, "dmu_object_next() = %d\n", error);
1953209962Smm		abort();
1954209962Smm	}
1955168404Spjd}
1956168404Spjd
1957168404Spjdstatic void
1958219089Spjddump_uberblock(uberblock_t *ub, const char *header, const char *footer)
1959168404Spjd{
1960168404Spjd	time_t timestamp = ub->ub_timestamp;
1961168404Spjd
1962219089Spjd	(void) printf(header ? header : "");
1963168404Spjd	(void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic);
1964168404Spjd	(void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version);
1965168404Spjd	(void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg);
1966168404Spjd	(void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum);
1967168404Spjd	(void) printf("\ttimestamp = %llu UTC = %s",
1968168404Spjd	    (u_longlong_t)ub->ub_timestamp, asctime(localtime(&timestamp)));
1969168404Spjd	if (dump_opt['u'] >= 3) {
1970168404Spjd		char blkbuf[BP_SPRINTF_LEN];
1971263397Sdelphij		snprintf_blkptr(blkbuf, sizeof (blkbuf), &ub->ub_rootbp);
1972168404Spjd		(void) printf("\trootbp = %s\n", blkbuf);
1973168404Spjd	}
1974219089Spjd	(void) printf(footer ? footer : "");
1975168404Spjd}
1976168404Spjd
1977168404Spjdstatic void
1978219089Spjddump_config(spa_t *spa)
1979168404Spjd{
1980219089Spjd	dmu_buf_t *db;
1981219089Spjd	size_t nvsize = 0;
1982219089Spjd	int error = 0;
1983168404Spjd
1984219089Spjd
1985219089Spjd	error = dmu_bonus_hold(spa->spa_meta_objset,
1986219089Spjd	    spa->spa_config_object, FTAG, &db);
1987219089Spjd
1988219089Spjd	if (error == 0) {
1989219089Spjd		nvsize = *(uint64_t *)db->db_data;
1990219089Spjd		dmu_buf_rele(db, FTAG);
1991219089Spjd
1992219089Spjd		(void) printf("\nMOS Configuration:\n");
1993219089Spjd		dump_packed_nvlist(spa->spa_meta_objset,
1994219089Spjd		    spa->spa_config_object, (void *)&nvsize, 1);
1995219089Spjd	} else {
1996219089Spjd		(void) fprintf(stderr, "dmu_bonus_hold(%llu) failed, errno %d",
1997219089Spjd		    (u_longlong_t)spa->spa_config_object, error);
1998168404Spjd	}
1999168404Spjd}
2000168404Spjd
2001168404Spjdstatic void
2002185029Spjddump_cachefile(const char *cachefile)
2003185029Spjd{
2004185029Spjd	int fd;
2005185029Spjd	struct stat64 statbuf;
2006185029Spjd	char *buf;
2007185029Spjd	nvlist_t *config;
2008185029Spjd
2009185029Spjd	if ((fd = open64(cachefile, O_RDONLY)) < 0) {
2010185029Spjd		(void) printf("cannot open '%s': %s\n", cachefile,
2011185029Spjd		    strerror(errno));
2012185029Spjd		exit(1);
2013185029Spjd	}
2014185029Spjd
2015185029Spjd	if (fstat64(fd, &statbuf) != 0) {
2016185029Spjd		(void) printf("failed to stat '%s': %s\n", cachefile,
2017185029Spjd		    strerror(errno));
2018185029Spjd		exit(1);
2019185029Spjd	}
2020185029Spjd
2021185029Spjd	if ((buf = malloc(statbuf.st_size)) == NULL) {
2022185029Spjd		(void) fprintf(stderr, "failed to allocate %llu bytes\n",
2023185029Spjd		    (u_longlong_t)statbuf.st_size);
2024185029Spjd		exit(1);
2025185029Spjd	}
2026185029Spjd
2027185029Spjd	if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
2028185029Spjd		(void) fprintf(stderr, "failed to read %llu bytes\n",
2029185029Spjd		    (u_longlong_t)statbuf.st_size);
2030185029Spjd		exit(1);
2031185029Spjd	}
2032185029Spjd
2033185029Spjd	(void) close(fd);
2034185029Spjd
2035185029Spjd	if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
2036185029Spjd		(void) fprintf(stderr, "failed to unpack nvlist\n");
2037185029Spjd		exit(1);
2038185029Spjd	}
2039185029Spjd
2040185029Spjd	free(buf);
2041185029Spjd
2042185029Spjd	dump_nvlist(config, 0);
2043185029Spjd
2044185029Spjd	nvlist_free(config);
2045185029Spjd}
2046185029Spjd
2047219089Spjd#define	ZDB_MAX_UB_HEADER_SIZE 32
2048219089Spjd
2049185029Spjdstatic void
2050219089Spjddump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
2051219089Spjd{
2052219089Spjd	vdev_t vd;
2053219089Spjd	vdev_t *vdp = &vd;
2054219089Spjd	char header[ZDB_MAX_UB_HEADER_SIZE];
2055219089Spjd
2056219089Spjd	vd.vdev_ashift = ashift;
2057219089Spjd	vdp->vdev_top = vdp;
2058219089Spjd
2059219089Spjd	for (int i = 0; i < VDEV_UBERBLOCK_COUNT(vdp); i++) {
2060219089Spjd		uint64_t uoff = VDEV_UBERBLOCK_OFFSET(vdp, i);
2061219089Spjd		uberblock_t *ub = (void *)((char *)lbl + uoff);
2062219089Spjd
2063219089Spjd		if (uberblock_verify(ub))
2064219089Spjd			continue;
2065219089Spjd		(void) snprintf(header, ZDB_MAX_UB_HEADER_SIZE,
2066219089Spjd		    "Uberblock[%d]\n", i);
2067219089Spjd		dump_uberblock(ub, header, "");
2068219089Spjd	}
2069219089Spjd}
2070219089Spjd
2071219089Spjdstatic void
2072168404Spjddump_label(const char *dev)
2073168404Spjd{
2074168404Spjd	int fd;
2075168404Spjd	vdev_label_t label;
2076219089Spjd	char *path, *buf = label.vl_vdev_phys.vp_nvlist;
2077168404Spjd	size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
2078168404Spjd	struct stat64 statbuf;
2079219089Spjd	uint64_t psize, ashift;
2080219089Spjd	int len = strlen(dev) + 1;
2081168404Spjd
2082219089Spjd	if (strncmp(dev, "/dev/dsk/", 9) == 0) {
2083219089Spjd		len++;
2084219089Spjd		path = malloc(len);
2085219089Spjd		(void) snprintf(path, len, "%s%s", "/dev/rdsk/", dev + 9);
2086219089Spjd	} else {
2087219089Spjd		path = strdup(dev);
2088219089Spjd	}
2089219089Spjd
2090219089Spjd	if ((fd = open64(path, O_RDONLY)) < 0) {
2091219089Spjd		(void) printf("cannot open '%s': %s\n", path, strerror(errno));
2092219089Spjd		free(path);
2093168404Spjd		exit(1);
2094168404Spjd	}
2095168404Spjd
2096168404Spjd	if (fstat64(fd, &statbuf) != 0) {
2097219089Spjd		(void) printf("failed to stat '%s': %s\n", path,
2098168404Spjd		    strerror(errno));
2099219089Spjd		free(path);
2100219089Spjd		(void) close(fd);
2101168404Spjd		exit(1);
2102168404Spjd	}
2103168404Spjd
2104219089Spjd	if (S_ISBLK(statbuf.st_mode)) {
2105219089Spjd		(void) printf("cannot use '%s': character device required\n",
2106219089Spjd		    path);
2107219089Spjd		free(path);
2108219089Spjd		(void) close(fd);
2109219089Spjd		exit(1);
2110196928Spjd	}
2111196928Spjd
2112185029Spjd	psize = statbuf.st_size;
2113168404Spjd	psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
2114168404Spjd
2115219089Spjd	for (int l = 0; l < VDEV_LABELS; l++) {
2116168404Spjd		nvlist_t *config = NULL;
2117168404Spjd
2118168404Spjd		(void) printf("--------------------------------------------\n");
2119168404Spjd		(void) printf("LABEL %d\n", l);
2120168404Spjd		(void) printf("--------------------------------------------\n");
2121168404Spjd
2122168404Spjd		if (pread64(fd, &label, sizeof (label),
2123168404Spjd		    vdev_label_offset(psize, l, 0)) != sizeof (label)) {
2124168404Spjd			(void) printf("failed to read label %d\n", l);
2125168404Spjd			continue;
2126168404Spjd		}
2127168404Spjd
2128168404Spjd		if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
2129168404Spjd			(void) printf("failed to unpack label %d\n", l);
2130219089Spjd			ashift = SPA_MINBLOCKSHIFT;
2131219089Spjd		} else {
2132219089Spjd			nvlist_t *vdev_tree = NULL;
2133219089Spjd
2134219089Spjd			dump_nvlist(config, 4);
2135219089Spjd			if ((nvlist_lookup_nvlist(config,
2136219089Spjd			    ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
2137219089Spjd			    (nvlist_lookup_uint64(vdev_tree,
2138219089Spjd			    ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
2139219089Spjd				ashift = SPA_MINBLOCKSHIFT;
2140219089Spjd			nvlist_free(config);
2141168404Spjd		}
2142219089Spjd		if (dump_opt['u'])
2143219089Spjd			dump_label_uberblocks(&label, ashift);
2144168404Spjd	}
2145219089Spjd
2146219089Spjd	free(path);
2147219089Spjd	(void) close(fd);
2148168404Spjd}
2149168404Spjd
2150276081Sdelphijstatic uint64_t num_large_blocks;
2151276081Sdelphij
2152168404Spjd/*ARGSUSED*/
2153168404Spjdstatic int
2154219089Spjddump_one_dir(const char *dsname, void *arg)
2155168404Spjd{
2156168404Spjd	int error;
2157168404Spjd	objset_t *os;
2158168404Spjd
2159219089Spjd	error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
2160168404Spjd	if (error) {
2161219089Spjd		(void) printf("Could not open %s, error %d\n", dsname, error);
2162168404Spjd		return (0);
2163168404Spjd	}
2164276081Sdelphij	if (dmu_objset_ds(os)->ds_large_blocks)
2165276081Sdelphij		num_large_blocks++;
2166168404Spjd	dump_dir(os);
2167219089Spjd	dmu_objset_disown(os, FTAG);
2168185029Spjd	fuid_table_destroy();
2169219089Spjd	sa_loaded = B_FALSE;
2170168404Spjd	return (0);
2171168404Spjd}
2172168404Spjd
2173168404Spjd/*
2174219089Spjd * Block statistics.
2175168404Spjd */
2176276081Sdelphij#define	PSIZE_HISTO_SIZE (SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 2)
2177168404Spjdtypedef struct zdb_blkstats {
2178249207Smm	uint64_t zb_asize;
2179249207Smm	uint64_t zb_lsize;
2180249207Smm	uint64_t zb_psize;
2181249207Smm	uint64_t zb_count;
2182268645Sdelphij	uint64_t zb_gangs;
2183268645Sdelphij	uint64_t zb_ditto_samevdev;
2184249207Smm	uint64_t zb_psize_histogram[PSIZE_HISTO_SIZE];
2185168404Spjd} zdb_blkstats_t;
2186168404Spjd
2187219089Spjd/*
2188219089Spjd * Extended object types to report deferred frees and dedup auto-ditto blocks.
2189219089Spjd */
2190219089Spjd#define	ZDB_OT_DEFERRED	(DMU_OT_NUMTYPES + 0)
2191219089Spjd#define	ZDB_OT_DITTO	(DMU_OT_NUMTYPES + 1)
2192236884Smm#define	ZDB_OT_OTHER	(DMU_OT_NUMTYPES + 2)
2193236884Smm#define	ZDB_OT_TOTAL	(DMU_OT_NUMTYPES + 3)
2194168404Spjd
2195219089Spjdstatic char *zdb_ot_extname[] = {
2196219089Spjd	"deferred free",
2197219089Spjd	"dedup ditto",
2198236884Smm	"other",
2199219089Spjd	"Total",
2200219089Spjd};
2201219089Spjd
2202208047Smm#define	ZB_TOTAL	DN_MAX_LEVELS
2203168404Spjd
2204168404Spjdtypedef struct zdb_cb {
2205219089Spjd	zdb_blkstats_t	zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1];
2206219089Spjd	uint64_t	zcb_dedup_asize;
2207219089Spjd	uint64_t	zcb_dedup_blocks;
2208268649Sdelphij	uint64_t	zcb_embedded_blocks[NUM_BP_EMBEDDED_TYPES];
2209268649Sdelphij	uint64_t	zcb_embedded_histogram[NUM_BP_EMBEDDED_TYPES]
2210268649Sdelphij	    [BPE_PAYLOAD_SIZE];
2211249207Smm	uint64_t	zcb_start;
2212249207Smm	uint64_t	zcb_lastprint;
2213249207Smm	uint64_t	zcb_totalasize;
2214168404Spjd	uint64_t	zcb_errors[256];
2215168404Spjd	int		zcb_readfails;
2216168404Spjd	int		zcb_haderrors;
2217219089Spjd	spa_t		*zcb_spa;
2218168404Spjd} zdb_cb_t;
2219168404Spjd
2220168404Spjdstatic void
2221219089Spjdzdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
2222219089Spjd    dmu_object_type_t type)
2223168404Spjd{
2224219089Spjd	uint64_t refcnt = 0;
2225219089Spjd
2226219089Spjd	ASSERT(type < ZDB_OT_TOTAL);
2227219089Spjd
2228219089Spjd	if (zilog && zil_bp_tree_add(zilog, bp) != 0)
2229219089Spjd		return;
2230219089Spjd
2231185029Spjd	for (int i = 0; i < 4; i++) {
2232168404Spjd		int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL;
2233219089Spjd		int t = (i & 1) ? type : ZDB_OT_TOTAL;
2234268645Sdelphij		int equal;
2235168404Spjd		zdb_blkstats_t *zb = &zcb->zcb_type[l][t];
2236168404Spjd
2237168404Spjd		zb->zb_asize += BP_GET_ASIZE(bp);
2238168404Spjd		zb->zb_lsize += BP_GET_LSIZE(bp);
2239168404Spjd		zb->zb_psize += BP_GET_PSIZE(bp);
2240168404Spjd		zb->zb_count++;
2241268645Sdelphij
2242276081Sdelphij		/*
2243276081Sdelphij		 * The histogram is only big enough to record blocks up to
2244276081Sdelphij		 * SPA_OLD_MAXBLOCKSIZE; larger blocks go into the last,
2245276081Sdelphij		 * "other", bucket.
2246276081Sdelphij		 */
2247276081Sdelphij		int idx = BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT;
2248276081Sdelphij		idx = MIN(idx, SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 1);
2249276081Sdelphij		zb->zb_psize_histogram[idx]++;
2250276081Sdelphij
2251268645Sdelphij		zb->zb_gangs += BP_COUNT_GANG(bp);
2252268645Sdelphij
2253268645Sdelphij		switch (BP_GET_NDVAS(bp)) {
2254268645Sdelphij		case 2:
2255268645Sdelphij			if (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2256268645Sdelphij			    DVA_GET_VDEV(&bp->blk_dva[1]))
2257268645Sdelphij				zb->zb_ditto_samevdev++;
2258268645Sdelphij			break;
2259268645Sdelphij		case 3:
2260268645Sdelphij			equal = (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2261268645Sdelphij			    DVA_GET_VDEV(&bp->blk_dva[1])) +
2262268645Sdelphij			    (DVA_GET_VDEV(&bp->blk_dva[0]) ==
2263268645Sdelphij			    DVA_GET_VDEV(&bp->blk_dva[2])) +
2264268645Sdelphij			    (DVA_GET_VDEV(&bp->blk_dva[1]) ==
2265268645Sdelphij			    DVA_GET_VDEV(&bp->blk_dva[2]));
2266268645Sdelphij			if (equal != 0)
2267268645Sdelphij				zb->zb_ditto_samevdev++;
2268268645Sdelphij			break;
2269268645Sdelphij		}
2270268645Sdelphij
2271168404Spjd	}
2272168404Spjd
2273268649Sdelphij	if (BP_IS_EMBEDDED(bp)) {
2274268649Sdelphij		zcb->zcb_embedded_blocks[BPE_GET_ETYPE(bp)]++;
2275268649Sdelphij		zcb->zcb_embedded_histogram[BPE_GET_ETYPE(bp)]
2276268649Sdelphij		    [BPE_GET_PSIZE(bp)]++;
2277268649Sdelphij		return;
2278268649Sdelphij	}
2279268649Sdelphij
2280219089Spjd	if (dump_opt['L'])
2281219089Spjd		return;
2282168404Spjd
2283219089Spjd	if (BP_GET_DEDUP(bp)) {
2284219089Spjd		ddt_t *ddt;
2285219089Spjd		ddt_entry_t *dde;
2286168404Spjd
2287219089Spjd		ddt = ddt_select(zcb->zcb_spa, bp);
2288219089Spjd		ddt_enter(ddt);
2289219089Spjd		dde = ddt_lookup(ddt, bp, B_FALSE);
2290168404Spjd
2291219089Spjd		if (dde == NULL) {
2292219089Spjd			refcnt = 0;
2293219089Spjd		} else {
2294219089Spjd			ddt_phys_t *ddp = ddt_phys_select(dde, bp);
2295219089Spjd			ddt_phys_decref(ddp);
2296219089Spjd			refcnt = ddp->ddp_refcnt;
2297219089Spjd			if (ddt_phys_total_refcnt(dde) == 0)
2298219089Spjd				ddt_remove(ddt, dde);
2299185029Spjd		}
2300219089Spjd		ddt_exit(ddt);
2301185029Spjd	}
2302168404Spjd
2303219089Spjd	VERIFY3U(zio_wait(zio_claim(NULL, zcb->zcb_spa,
2304219089Spjd	    refcnt ? 0 : spa_first_txg(zcb->zcb_spa),
2305219089Spjd	    bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
2306168404Spjd}
2307168404Spjd
2308263393Sdelphij/* ARGSUSED */
2309263393Sdelphijstatic void
2310263393Sdelphijzdb_blkptr_done(zio_t *zio)
2311263393Sdelphij{
2312263393Sdelphij	spa_t *spa = zio->io_spa;
2313263393Sdelphij	blkptr_t *bp = zio->io_bp;
2314263393Sdelphij	int ioerr = zio->io_error;
2315263393Sdelphij	zdb_cb_t *zcb = zio->io_private;
2316268657Sdelphij	zbookmark_phys_t *zb = &zio->io_bookmark;
2317263393Sdelphij
2318263393Sdelphij	zio_data_buf_free(zio->io_data, zio->io_size);
2319263393Sdelphij
2320263393Sdelphij	mutex_enter(&spa->spa_scrub_lock);
2321263393Sdelphij	spa->spa_scrub_inflight--;
2322263393Sdelphij	cv_broadcast(&spa->spa_scrub_io_cv);
2323263393Sdelphij
2324263393Sdelphij	if (ioerr && !(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
2325263393Sdelphij		char blkbuf[BP_SPRINTF_LEN];
2326263393Sdelphij
2327263393Sdelphij		zcb->zcb_haderrors = 1;
2328263393Sdelphij		zcb->zcb_errors[ioerr]++;
2329263393Sdelphij
2330263393Sdelphij		if (dump_opt['b'] >= 2)
2331263397Sdelphij			snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
2332263393Sdelphij		else
2333263393Sdelphij			blkbuf[0] = '\0';
2334263393Sdelphij
2335263393Sdelphij		(void) printf("zdb_blkptr_cb: "
2336263393Sdelphij		    "Got error %d reading "
2337263393Sdelphij		    "<%llu, %llu, %lld, %llx> %s -- skipping\n",
2338263393Sdelphij		    ioerr,
2339263393Sdelphij		    (u_longlong_t)zb->zb_objset,
2340263393Sdelphij		    (u_longlong_t)zb->zb_object,
2341263393Sdelphij		    (u_longlong_t)zb->zb_level,
2342263393Sdelphij		    (u_longlong_t)zb->zb_blkid,
2343263393Sdelphij		    blkbuf);
2344263393Sdelphij	}
2345263393Sdelphij	mutex_exit(&spa->spa_scrub_lock);
2346263393Sdelphij}
2347263393Sdelphij
2348263393Sdelphij/* ARGSUSED */
2349168404Spjdstatic int
2350246666Smmzdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
2351268657Sdelphij    const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
2352168404Spjd{
2353168404Spjd	zdb_cb_t *zcb = arg;
2354209962Smm	dmu_object_type_t type;
2355219089Spjd	boolean_t is_metadata;
2356168404Spjd
2357263397Sdelphij	if (dump_opt['b'] >= 5 && bp->blk_birth > 0) {
2358263397Sdelphij		char blkbuf[BP_SPRINTF_LEN];
2359263397Sdelphij		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
2360263397Sdelphij		(void) printf("objset %llu object %llu "
2361263397Sdelphij		    "level %lld offset 0x%llx %s\n",
2362263397Sdelphij		    (u_longlong_t)zb->zb_objset,
2363263397Sdelphij		    (u_longlong_t)zb->zb_object,
2364263397Sdelphij		    (longlong_t)zb->zb_level,
2365263397Sdelphij		    (u_longlong_t)blkid2offset(dnp, bp, zb),
2366263397Sdelphij		    blkbuf);
2367263397Sdelphij	}
2368263397Sdelphij
2369263397Sdelphij	if (BP_IS_HOLE(bp))
2370208047Smm		return (0);
2371185029Spjd
2372209962Smm	type = BP_GET_TYPE(bp);
2373185029Spjd
2374236884Smm	zdb_count_block(zcb, zilog, bp,
2375236884Smm	    (type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
2376209962Smm
2377236884Smm	is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
2378209962Smm
2379268649Sdelphij	if (!BP_IS_EMBEDDED(bp) &&
2380268649Sdelphij	    (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata))) {
2381219089Spjd		size_t size = BP_GET_PSIZE(bp);
2382263393Sdelphij		void *data = zio_data_buf_alloc(size);
2383219089Spjd		int flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB | ZIO_FLAG_RAW;
2384208047Smm
2385219089Spjd		/* If it's an intent log block, failure is expected. */
2386219089Spjd		if (zb->zb_level == ZB_ZIL_LEVEL)
2387219089Spjd			flags |= ZIO_FLAG_SPECULATIVE;
2388219089Spjd
2389263393Sdelphij		mutex_enter(&spa->spa_scrub_lock);
2390263393Sdelphij		while (spa->spa_scrub_inflight > max_inflight)
2391263393Sdelphij			cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
2392263393Sdelphij		spa->spa_scrub_inflight++;
2393263393Sdelphij		mutex_exit(&spa->spa_scrub_lock);
2394219089Spjd
2395263393Sdelphij		zio_nowait(zio_read(NULL, spa, bp, data, size,
2396263393Sdelphij		    zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb));
2397168404Spjd	}
2398168404Spjd
2399168404Spjd	zcb->zcb_readfails = 0;
2400168404Spjd
2401275488Sdelphij	/* only call gethrtime() every 100 blocks */
2402275488Sdelphij	static int iters;
2403275488Sdelphij	if (++iters > 100)
2404275488Sdelphij		iters = 0;
2405275488Sdelphij	else
2406275488Sdelphij		return (0);
2407275488Sdelphij
2408275488Sdelphij	if (dump_opt['b'] < 5 && gethrtime() > zcb->zcb_lastprint + NANOSEC) {
2409249207Smm		uint64_t now = gethrtime();
2410249207Smm		char buf[10];
2411249207Smm		uint64_t bytes = zcb->zcb_type[ZB_TOTAL][ZDB_OT_TOTAL].zb_asize;
2412249207Smm		int kb_per_sec =
2413249207Smm		    1 + bytes / (1 + ((now - zcb->zcb_start) / 1000 / 1000));
2414249207Smm		int sec_remaining =
2415249207Smm		    (zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
2416249207Smm
2417249207Smm		zfs_nicenum(bytes, buf, sizeof (buf));
2418249207Smm		(void) fprintf(stderr,
2419249207Smm		    "\r%5s completed (%4dMB/s) "
2420249207Smm		    "estimated time remaining: %uhr %02umin %02usec        ",
2421249207Smm		    buf, kb_per_sec / 1024,
2422249207Smm		    sec_remaining / 60 / 60,
2423249207Smm		    sec_remaining / 60 % 60,
2424249207Smm		    sec_remaining % 60);
2425249207Smm
2426249207Smm		zcb->zcb_lastprint = now;
2427249207Smm	}
2428249207Smm
2429168404Spjd	return (0);
2430168404Spjd}
2431168404Spjd
2432219089Spjdstatic void
2433262093Savgzdb_leak(void *arg, uint64_t start, uint64_t size)
2434219089Spjd{
2435262093Savg	vdev_t *vd = arg;
2436219089Spjd
2437219089Spjd	(void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n",
2438219089Spjd	    (u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size);
2439219089Spjd}
2440219089Spjd
2441262093Savgstatic metaslab_ops_t zdb_metaslab_ops = {
2442269773Sdelphij	NULL	/* alloc */
2443219089Spjd};
2444219089Spjd
2445219089Spjdstatic void
2446219089Spjdzdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb)
2447219089Spjd{
2448219089Spjd	ddt_bookmark_t ddb = { 0 };
2449219089Spjd	ddt_entry_t dde;
2450219089Spjd	int error;
2451219089Spjd
2452219089Spjd	while ((error = ddt_walk(spa, &ddb, &dde)) == 0) {
2453219089Spjd		blkptr_t blk;
2454219089Spjd		ddt_phys_t *ddp = dde.dde_phys;
2455219089Spjd
2456219089Spjd		if (ddb.ddb_class == DDT_CLASS_UNIQUE)
2457219089Spjd			return;
2458219089Spjd
2459219089Spjd		ASSERT(ddt_phys_total_refcnt(&dde) > 1);
2460219089Spjd
2461219089Spjd		for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
2462219089Spjd			if (ddp->ddp_phys_birth == 0)
2463219089Spjd				continue;
2464219089Spjd			ddt_bp_create(ddb.ddb_checksum,
2465219089Spjd			    &dde.dde_key, ddp, &blk);
2466219089Spjd			if (p == DDT_PHYS_DITTO) {
2467219089Spjd				zdb_count_block(zcb, NULL, &blk, ZDB_OT_DITTO);
2468219089Spjd			} else {
2469219089Spjd				zcb->zcb_dedup_asize +=
2470219089Spjd				    BP_GET_ASIZE(&blk) * (ddp->ddp_refcnt - 1);
2471219089Spjd				zcb->zcb_dedup_blocks++;
2472219089Spjd			}
2473219089Spjd		}
2474219089Spjd		if (!dump_opt['L']) {
2475219089Spjd			ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum];
2476219089Spjd			ddt_enter(ddt);
2477219089Spjd			VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL);
2478219089Spjd			ddt_exit(ddt);
2479219089Spjd		}
2480219089Spjd	}
2481219089Spjd
2482219089Spjd	ASSERT(error == ENOENT);
2483219089Spjd}
2484219089Spjd
2485219089Spjdstatic void
2486219089Spjdzdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
2487219089Spjd{
2488219089Spjd	zcb->zcb_spa = spa;
2489219089Spjd
2490219089Spjd	if (!dump_opt['L']) {
2491219089Spjd		vdev_t *rvd = spa->spa_root_vdev;
2492273508Sdelphij		for (uint64_t c = 0; c < rvd->vdev_children; c++) {
2493219089Spjd			vdev_t *vd = rvd->vdev_child[c];
2494273508Sdelphij			for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
2495219089Spjd				metaslab_t *msp = vd->vdev_ms[m];
2496219089Spjd				mutex_enter(&msp->ms_lock);
2497262093Savg				metaslab_unload(msp);
2498262093Savg
2499262093Savg				/*
2500262093Savg				 * For leak detection, we overload the metaslab
2501262093Savg				 * ms_tree to contain allocated segments
2502262093Savg				 * instead of free segments. As a result,
2503262093Savg				 * we can't use the normal metaslab_load/unload
2504262093Savg				 * interfaces.
2505262093Savg				 */
2506262093Savg				if (msp->ms_sm != NULL) {
2507273508Sdelphij					(void) fprintf(stderr,
2508273508Sdelphij					    "\rloading space map for "
2509273508Sdelphij					    "vdev %llu of %llu, "
2510273508Sdelphij					    "metaslab %llu of %llu ...",
2511273508Sdelphij					    (longlong_t)c,
2512273508Sdelphij					    (longlong_t)rvd->vdev_children,
2513273508Sdelphij					    (longlong_t)m,
2514273508Sdelphij					    (longlong_t)vd->vdev_ms_count);
2515273508Sdelphij
2516262093Savg					msp->ms_ops = &zdb_metaslab_ops;
2517275488Sdelphij
2518275488Sdelphij					/*
2519275488Sdelphij					 * We don't want to spend the CPU
2520275488Sdelphij					 * manipulating the size-ordered
2521275488Sdelphij					 * tree, so clear the range_tree
2522275488Sdelphij					 * ops.
2523275488Sdelphij					 */
2524275488Sdelphij					msp->ms_tree->rt_ops = NULL;
2525262093Savg					VERIFY0(space_map_load(msp->ms_sm,
2526262093Savg					    msp->ms_tree, SM_ALLOC));
2527262093Savg					msp->ms_loaded = B_TRUE;
2528262093Savg				}
2529219089Spjd				mutex_exit(&msp->ms_lock);
2530219089Spjd			}
2531219089Spjd		}
2532273508Sdelphij		(void) fprintf(stderr, "\n");
2533219089Spjd	}
2534219089Spjd
2535219089Spjd	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
2536219089Spjd
2537219089Spjd	zdb_ddt_leak_init(spa, zcb);
2538219089Spjd
2539219089Spjd	spa_config_exit(spa, SCL_CONFIG, FTAG);
2540219089Spjd}
2541219089Spjd
2542219089Spjdstatic void
2543219089Spjdzdb_leak_fini(spa_t *spa)
2544219089Spjd{
2545219089Spjd	if (!dump_opt['L']) {
2546219089Spjd		vdev_t *rvd = spa->spa_root_vdev;
2547219089Spjd		for (int c = 0; c < rvd->vdev_children; c++) {
2548219089Spjd			vdev_t *vd = rvd->vdev_child[c];
2549219089Spjd			for (int m = 0; m < vd->vdev_ms_count; m++) {
2550219089Spjd				metaslab_t *msp = vd->vdev_ms[m];
2551219089Spjd				mutex_enter(&msp->ms_lock);
2552262093Savg
2553262093Savg				/*
2554262093Savg				 * The ms_tree has been overloaded to
2555262093Savg				 * contain allocated segments. Now that we
2556262093Savg				 * finished traversing all blocks, any
2557262093Savg				 * block that remains in the ms_tree
2558262093Savg				 * represents an allocated block that we
2559262093Savg				 * did not claim during the traversal.
2560262093Savg				 * Claimed blocks would have been removed
2561262093Savg				 * from the ms_tree.
2562262093Savg				 */
2563262093Savg				range_tree_vacate(msp->ms_tree, zdb_leak, vd);
2564262093Savg				msp->ms_loaded = B_FALSE;
2565262093Savg
2566219089Spjd				mutex_exit(&msp->ms_lock);
2567219089Spjd			}
2568219089Spjd		}
2569219089Spjd	}
2570219089Spjd}
2571219089Spjd
2572219089Spjd/* ARGSUSED */
2573168404Spjdstatic int
2574219089Spjdcount_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
2575219089Spjd{
2576219089Spjd	zdb_cb_t *zcb = arg;
2577219089Spjd
2578249207Smm	if (dump_opt['b'] >= 5) {
2579219089Spjd		char blkbuf[BP_SPRINTF_LEN];
2580263397Sdelphij		snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
2581219089Spjd		(void) printf("[%s] %s\n",
2582219089Spjd		    "deferred free", blkbuf);
2583219089Spjd	}
2584219089Spjd	zdb_count_block(zcb, NULL, bp, ZDB_OT_DEFERRED);
2585219089Spjd	return (0);
2586219089Spjd}
2587219089Spjd
2588219089Spjdstatic int
2589168404Spjddump_block_stats(spa_t *spa)
2590168404Spjd{
2591168404Spjd	zdb_cb_t zcb = { 0 };
2592168404Spjd	zdb_blkstats_t *zb, *tzb;
2593219089Spjd	uint64_t norm_alloc, norm_space, total_alloc, total_found;
2594219089Spjd	int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD;
2595268649Sdelphij	boolean_t leaks = B_FALSE;
2596168404Spjd
2597249207Smm	(void) printf("\nTraversing all blocks %s%s%s%s%s...\n\n",
2598219089Spjd	    (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "",
2599219089Spjd	    (dump_opt['c'] == 1) ? "metadata " : "",
2600219089Spjd	    dump_opt['c'] ? "checksums " : "",
2601219089Spjd	    (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "",
2602219089Spjd	    !dump_opt['L'] ? "nothing leaked " : "");
2603168404Spjd
2604168404Spjd	/*
2605185029Spjd	 * Load all space maps as SM_ALLOC maps, then traverse the pool
2606185029Spjd	 * claiming each block we discover.  If the pool is perfectly
2607185029Spjd	 * consistent, the space maps will be empty when we're done.
2608185029Spjd	 * Anything left over is a leak; any block we can't claim (because
2609185029Spjd	 * it's not part of any space map) is a double allocation,
2610185029Spjd	 * reference to a freed block, or an unclaimed log block.
2611168404Spjd	 */
2612219089Spjd	zdb_leak_init(spa, &zcb);
2613168404Spjd
2614168404Spjd	/*
2615168404Spjd	 * If there's a deferred-free bplist, process that first.
2616168404Spjd	 */
2617219089Spjd	(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
2618219089Spjd	    count_block_cb, &zcb, NULL);
2619226616Spjd	if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2620226616Spjd		(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
2621226616Spjd		    count_block_cb, &zcb, NULL);
2622226616Spjd	}
2623263390Sdelphij	if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {
2624236884Smm		VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
2625236884Smm		    spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
2626236884Smm		    &zcb, NULL));
2627236884Smm	}
2628168404Spjd
2629219089Spjd	if (dump_opt['c'] > 1)
2630219089Spjd		flags |= TRAVERSE_PREFETCH_DATA;
2631168404Spjd
2632249207Smm	zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
2633249207Smm	zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
2634219089Spjd	zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
2635168404Spjd
2636263393Sdelphij	/*
2637263393Sdelphij	 * If we've traversed the data blocks then we need to wait for those
2638263393Sdelphij	 * I/Os to complete. We leverage "The Godfather" zio to wait on
2639263393Sdelphij	 * all async I/Os to complete.
2640263393Sdelphij	 */
2641263393Sdelphij	if (dump_opt['c']) {
2642273348Sdelphij		for (int i = 0; i < max_ncpus; i++) {
2643273348Sdelphij			(void) zio_wait(spa->spa_async_zio_root[i]);
2644273348Sdelphij			spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
2645273348Sdelphij			    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
2646273348Sdelphij			    ZIO_FLAG_GODFATHER);
2647273348Sdelphij		}
2648263393Sdelphij	}
2649263393Sdelphij
2650219089Spjd	if (zcb.zcb_haderrors) {
2651168404Spjd		(void) printf("\nError counts:\n\n");
2652168404Spjd		(void) printf("\t%5s  %s\n", "errno", "count");
2653219089Spjd		for (int e = 0; e < 256; e++) {
2654168404Spjd			if (zcb.zcb_errors[e] != 0) {
2655168404Spjd				(void) printf("\t%5d  %llu\n",
2656168404Spjd				    e, (u_longlong_t)zcb.zcb_errors[e]);
2657168404Spjd			}
2658168404Spjd		}
2659168404Spjd	}
2660168404Spjd
2661168404Spjd	/*
2662168404Spjd	 * Report any leaked segments.
2663168404Spjd	 */
2664219089Spjd	zdb_leak_fini(spa);
2665168404Spjd
2666219089Spjd	tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL];
2667185029Spjd
2668219089Spjd	norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
2669219089Spjd	norm_space = metaslab_class_get_space(spa_normal_class(spa));
2670168404Spjd
2671219089Spjd	total_alloc = norm_alloc + metaslab_class_get_alloc(spa_log_class(spa));
2672219089Spjd	total_found = tzb->zb_asize - zcb.zcb_dedup_asize;
2673185029Spjd
2674219089Spjd	if (total_found == total_alloc) {
2675209962Smm		if (!dump_opt['L'])
2676209962Smm			(void) printf("\n\tNo leaks (block sum matches space"
2677209962Smm			    " maps exactly)\n");
2678168404Spjd	} else {
2679168404Spjd		(void) printf("block traversal size %llu != alloc %llu "
2680209962Smm		    "(%s %lld)\n",
2681219089Spjd		    (u_longlong_t)total_found,
2682219089Spjd		    (u_longlong_t)total_alloc,
2683209962Smm		    (dump_opt['L']) ? "unreachable" : "leaked",
2684219089Spjd		    (longlong_t)(total_alloc - total_found));
2685268649Sdelphij		leaks = B_TRUE;
2686168404Spjd	}
2687168404Spjd
2688168404Spjd	if (tzb->zb_count == 0)
2689168404Spjd		return (2);
2690168404Spjd
2691168404Spjd	(void) printf("\n");
2692168404Spjd	(void) printf("\tbp count:      %10llu\n",
2693168404Spjd	    (u_longlong_t)tzb->zb_count);
2694268645Sdelphij	(void) printf("\tganged count:  %10llu\n",
2695268645Sdelphij	    (longlong_t)tzb->zb_gangs);
2696219089Spjd	(void) printf("\tbp logical:    %10llu      avg: %6llu\n",
2697168404Spjd	    (u_longlong_t)tzb->zb_lsize,
2698168404Spjd	    (u_longlong_t)(tzb->zb_lsize / tzb->zb_count));
2699219089Spjd	(void) printf("\tbp physical:   %10llu      avg:"
2700219089Spjd	    " %6llu     compression: %6.2f\n",
2701168404Spjd	    (u_longlong_t)tzb->zb_psize,
2702168404Spjd	    (u_longlong_t)(tzb->zb_psize / tzb->zb_count),
2703168404Spjd	    (double)tzb->zb_lsize / tzb->zb_psize);
2704219089Spjd	(void) printf("\tbp allocated:  %10llu      avg:"
2705219089Spjd	    " %6llu     compression: %6.2f\n",
2706168404Spjd	    (u_longlong_t)tzb->zb_asize,
2707168404Spjd	    (u_longlong_t)(tzb->zb_asize / tzb->zb_count),
2708168404Spjd	    (double)tzb->zb_lsize / tzb->zb_asize);
2709219089Spjd	(void) printf("\tbp deduped:    %10llu    ref>1:"
2710219089Spjd	    " %6llu   deduplication: %6.2f\n",
2711219089Spjd	    (u_longlong_t)zcb.zcb_dedup_asize,
2712219089Spjd	    (u_longlong_t)zcb.zcb_dedup_blocks,
2713219089Spjd	    (double)zcb.zcb_dedup_asize / tzb->zb_asize + 1.0);
2714219089Spjd	(void) printf("\tSPA allocated: %10llu     used: %5.2f%%\n",
2715219089Spjd	    (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
2716168404Spjd
2717268649Sdelphij	for (bp_embedded_type_t i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
2718268649Sdelphij		if (zcb.zcb_embedded_blocks[i] == 0)
2719268649Sdelphij			continue;
2720268649Sdelphij		(void) printf("\n");
2721268649Sdelphij		(void) printf("\tadditional, non-pointer bps of type %u: "
2722268649Sdelphij		    "%10llu\n",
2723268649Sdelphij		    i, (u_longlong_t)zcb.zcb_embedded_blocks[i]);
2724268649Sdelphij
2725268649Sdelphij		if (dump_opt['b'] >= 3) {
2726268649Sdelphij			(void) printf("\t number of (compressed) bytes:  "
2727268649Sdelphij			    "number of bps\n");
2728268649Sdelphij			dump_histogram(zcb.zcb_embedded_histogram[i],
2729268649Sdelphij			    sizeof (zcb.zcb_embedded_histogram[i]) /
2730268649Sdelphij			    sizeof (zcb.zcb_embedded_histogram[i][0]), 0);
2731268649Sdelphij		}
2732268649Sdelphij	}
2733268649Sdelphij
2734268645Sdelphij	if (tzb->zb_ditto_samevdev != 0) {
2735268645Sdelphij		(void) printf("\tDittoed blocks on same vdev: %llu\n",
2736268645Sdelphij		    (longlong_t)tzb->zb_ditto_samevdev);
2737268645Sdelphij	}
2738268645Sdelphij
2739168404Spjd	if (dump_opt['b'] >= 2) {
2740168404Spjd		int l, t, level;
2741168404Spjd		(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
2742168404Spjd		    "\t  avg\t comp\t%%Total\tType\n");
2743168404Spjd
2744219089Spjd		for (t = 0; t <= ZDB_OT_TOTAL; t++) {
2745219089Spjd			char csize[32], lsize[32], psize[32], asize[32];
2746268645Sdelphij			char avg[32], gang[32];
2747168404Spjd			char *typename;
2748168404Spjd
2749219089Spjd			if (t < DMU_OT_NUMTYPES)
2750219089Spjd				typename = dmu_ot[t].ot_name;
2751219089Spjd			else
2752219089Spjd				typename = zdb_ot_extname[t - DMU_OT_NUMTYPES];
2753168404Spjd
2754168404Spjd			if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) {
2755168404Spjd				(void) printf("%6s\t%5s\t%5s\t%5s"
2756168404Spjd				    "\t%5s\t%5s\t%6s\t%s\n",
2757168404Spjd				    "-",
2758168404Spjd				    "-",
2759168404Spjd				    "-",
2760168404Spjd				    "-",
2761168404Spjd				    "-",
2762168404Spjd				    "-",
2763168404Spjd				    "-",
2764168404Spjd				    typename);
2765168404Spjd				continue;
2766168404Spjd			}
2767168404Spjd
2768168404Spjd			for (l = ZB_TOTAL - 1; l >= -1; l--) {
2769168404Spjd				level = (l == -1 ? ZB_TOTAL : l);
2770168404Spjd				zb = &zcb.zcb_type[level][t];
2771168404Spjd
2772168404Spjd				if (zb->zb_asize == 0)
2773168404Spjd					continue;
2774168404Spjd
2775168404Spjd				if (dump_opt['b'] < 3 && level != ZB_TOTAL)
2776168404Spjd					continue;
2777168404Spjd
2778168404Spjd				if (level == 0 && zb->zb_asize ==
2779168404Spjd				    zcb.zcb_type[ZB_TOTAL][t].zb_asize)
2780168404Spjd					continue;
2781168404Spjd
2782219089Spjd				zdb_nicenum(zb->zb_count, csize);
2783219089Spjd				zdb_nicenum(zb->zb_lsize, lsize);
2784219089Spjd				zdb_nicenum(zb->zb_psize, psize);
2785219089Spjd				zdb_nicenum(zb->zb_asize, asize);
2786219089Spjd				zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
2787268645Sdelphij				zdb_nicenum(zb->zb_gangs, gang);
2788168404Spjd
2789168404Spjd				(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
2790168404Spjd				    "\t%5.2f\t%6.2f\t",
2791168404Spjd				    csize, lsize, psize, asize, avg,
2792168404Spjd				    (double)zb->zb_lsize / zb->zb_psize,
2793168404Spjd				    100.0 * zb->zb_asize / tzb->zb_asize);
2794168404Spjd
2795168404Spjd				if (level == ZB_TOTAL)
2796168404Spjd					(void) printf("%s\n", typename);
2797168404Spjd				else
2798168404Spjd					(void) printf("    L%d %s\n",
2799168404Spjd					    level, typename);
2800249207Smm
2801268645Sdelphij				if (dump_opt['b'] >= 3 && zb->zb_gangs > 0) {
2802268645Sdelphij					(void) printf("\t number of ganged "
2803268645Sdelphij					    "blocks: %s\n", gang);
2804268645Sdelphij				}
2805268645Sdelphij
2806249207Smm				if (dump_opt['b'] >= 4) {
2807249207Smm					(void) printf("psize "
2808249207Smm					    "(in 512-byte sectors): "
2809249207Smm					    "number of blocks\n");
2810249207Smm					dump_histogram(zb->zb_psize_histogram,
2811262093Savg					    PSIZE_HISTO_SIZE, 0);
2812249207Smm				}
2813168404Spjd			}
2814168404Spjd		}
2815168404Spjd	}
2816168404Spjd
2817168404Spjd	(void) printf("\n");
2818168404Spjd
2819168404Spjd	if (leaks)
2820168404Spjd		return (2);
2821168404Spjd
2822168404Spjd	if (zcb.zcb_haderrors)
2823168404Spjd		return (3);
2824168404Spjd
2825168404Spjd	return (0);
2826168404Spjd}
2827168404Spjd
2828219089Spjdtypedef struct zdb_ddt_entry {
2829219089Spjd	ddt_key_t	zdde_key;
2830219089Spjd	uint64_t	zdde_ref_blocks;
2831219089Spjd	uint64_t	zdde_ref_lsize;
2832219089Spjd	uint64_t	zdde_ref_psize;
2833219089Spjd	uint64_t	zdde_ref_dsize;
2834219089Spjd	avl_node_t	zdde_node;
2835219089Spjd} zdb_ddt_entry_t;
2836219089Spjd
2837219089Spjd/* ARGSUSED */
2838219089Spjdstatic int
2839219089Spjdzdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
2840268657Sdelphij    const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
2841219089Spjd{
2842219089Spjd	avl_tree_t *t = arg;
2843219089Spjd	avl_index_t where;
2844219089Spjd	zdb_ddt_entry_t *zdde, zdde_search;
2845219089Spjd
2846268649Sdelphij	if (BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
2847219089Spjd		return (0);
2848219089Spjd
2849219089Spjd	if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
2850219089Spjd		(void) printf("traversing objset %llu, %llu objects, "
2851219089Spjd		    "%lu blocks so far\n",
2852219089Spjd		    (u_longlong_t)zb->zb_objset,
2853268649Sdelphij		    (u_longlong_t)BP_GET_FILL(bp),
2854219089Spjd		    avl_numnodes(t));
2855219089Spjd	}
2856219089Spjd
2857219089Spjd	if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF ||
2858236884Smm	    BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp)))
2859219089Spjd		return (0);
2860219089Spjd
2861219089Spjd	ddt_key_fill(&zdde_search.zdde_key, bp);
2862219089Spjd
2863219089Spjd	zdde = avl_find(t, &zdde_search, &where);
2864219089Spjd
2865219089Spjd	if (zdde == NULL) {
2866219089Spjd		zdde = umem_zalloc(sizeof (*zdde), UMEM_NOFAIL);
2867219089Spjd		zdde->zdde_key = zdde_search.zdde_key;
2868219089Spjd		avl_insert(t, zdde, where);
2869219089Spjd	}
2870219089Spjd
2871219089Spjd	zdde->zdde_ref_blocks += 1;
2872219089Spjd	zdde->zdde_ref_lsize += BP_GET_LSIZE(bp);
2873219089Spjd	zdde->zdde_ref_psize += BP_GET_PSIZE(bp);
2874219089Spjd	zdde->zdde_ref_dsize += bp_get_dsize_sync(spa, bp);
2875219089Spjd
2876219089Spjd	return (0);
2877219089Spjd}
2878219089Spjd
2879168404Spjdstatic void
2880219089Spjddump_simulated_ddt(spa_t *spa)
2881219089Spjd{
2882219089Spjd	avl_tree_t t;
2883219089Spjd	void *cookie = NULL;
2884219089Spjd	zdb_ddt_entry_t *zdde;
2885219089Spjd	ddt_histogram_t ddh_total = { 0 };
2886219089Spjd	ddt_stat_t dds_total = { 0 };
2887219089Spjd
2888219089Spjd	avl_create(&t, ddt_entry_compare,
2889219089Spjd	    sizeof (zdb_ddt_entry_t), offsetof(zdb_ddt_entry_t, zdde_node));
2890219089Spjd
2891219089Spjd	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
2892219089Spjd
2893219089Spjd	(void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
2894219089Spjd	    zdb_ddt_add_cb, &t);
2895219089Spjd
2896219089Spjd	spa_config_exit(spa, SCL_CONFIG, FTAG);
2897219089Spjd
2898219089Spjd	while ((zdde = avl_destroy_nodes(&t, &cookie)) != NULL) {
2899219089Spjd		ddt_stat_t dds;
2900219089Spjd		uint64_t refcnt = zdde->zdde_ref_blocks;
2901219089Spjd		ASSERT(refcnt != 0);
2902219089Spjd
2903219089Spjd		dds.dds_blocks = zdde->zdde_ref_blocks / refcnt;
2904219089Spjd		dds.dds_lsize = zdde->zdde_ref_lsize / refcnt;
2905219089Spjd		dds.dds_psize = zdde->zdde_ref_psize / refcnt;
2906219089Spjd		dds.dds_dsize = zdde->zdde_ref_dsize / refcnt;
2907219089Spjd
2908219089Spjd		dds.dds_ref_blocks = zdde->zdde_ref_blocks;
2909219089Spjd		dds.dds_ref_lsize = zdde->zdde_ref_lsize;
2910219089Spjd		dds.dds_ref_psize = zdde->zdde_ref_psize;
2911219089Spjd		dds.dds_ref_dsize = zdde->zdde_ref_dsize;
2912219089Spjd
2913265740Sdelphij		ddt_stat_add(&ddh_total.ddh_stat[highbit64(refcnt) - 1],
2914265740Sdelphij		    &dds, 0);
2915219089Spjd
2916219089Spjd		umem_free(zdde, sizeof (*zdde));
2917219089Spjd	}
2918219089Spjd
2919219089Spjd	avl_destroy(&t);
2920219089Spjd
2921219089Spjd	ddt_histogram_stat(&dds_total, &ddh_total);
2922219089Spjd
2923219089Spjd	(void) printf("Simulated DDT histogram:\n");
2924219089Spjd
2925219089Spjd	zpool_dump_ddt(&dds_total, &ddh_total);
2926219089Spjd
2927219089Spjd	dump_dedup_ratio(&dds_total);
2928219089Spjd}
2929219089Spjd
2930219089Spjdstatic void
2931168404Spjddump_zpool(spa_t *spa)
2932168404Spjd{
2933168404Spjd	dsl_pool_t *dp = spa_get_dsl(spa);
2934168404Spjd	int rc = 0;
2935168404Spjd
2936219089Spjd	if (dump_opt['S']) {
2937219089Spjd		dump_simulated_ddt(spa);
2938219089Spjd		return;
2939219089Spjd	}
2940219089Spjd
2941219089Spjd	if (!dump_opt['e'] && dump_opt['C'] > 1) {
2942219089Spjd		(void) printf("\nCached configuration:\n");
2943219089Spjd		dump_nvlist(spa->spa_config, 8);
2944219089Spjd	}
2945219089Spjd
2946219089Spjd	if (dump_opt['C'])
2947219089Spjd		dump_config(spa);
2948219089Spjd
2949168404Spjd	if (dump_opt['u'])
2950219089Spjd		dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n");
2951168404Spjd
2952219089Spjd	if (dump_opt['D'])
2953219089Spjd		dump_all_ddts(spa);
2954219089Spjd
2955219089Spjd	if (dump_opt['d'] > 2 || dump_opt['m'])
2956219089Spjd		dump_metaslabs(spa);
2957269773Sdelphij	if (dump_opt['M'])
2958269773Sdelphij		dump_metaslab_groups(spa);
2959219089Spjd
2960219089Spjd	if (dump_opt['d'] || dump_opt['i']) {
2961276081Sdelphij		uint64_t refcount;
2962168404Spjd		dump_dir(dp->dp_meta_objset);
2963168404Spjd		if (dump_opt['d'] >= 3) {
2964247852Smm			dump_bpobj(&spa->spa_deferred_bpobj,
2965247852Smm			    "Deferred frees", 0);
2966219089Spjd			if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
2967219089Spjd				dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
2968247852Smm				    "Pool snapshot frees", 0);
2969219089Spjd			}
2970236884Smm
2971236884Smm			if (spa_feature_is_active(spa,
2972263390Sdelphij			    SPA_FEATURE_ASYNC_DESTROY)) {
2973236884Smm				dump_bptree(spa->spa_meta_objset,
2974236884Smm				    spa->spa_dsl_pool->dp_bptree_obj,
2975236884Smm				    "Pool dataset frees");
2976236884Smm			}
2977168404Spjd			dump_dtl(spa->spa_root_vdev, 0);
2978209962Smm		}
2979219089Spjd		(void) dmu_objset_find(spa_name(spa), dump_one_dir,
2980219089Spjd		    NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
2981276081Sdelphij
2982276081Sdelphij		(void) feature_get_refcount(spa,
2983276081Sdelphij		    &spa_feature_table[SPA_FEATURE_LARGE_BLOCKS], &refcount);
2984276081Sdelphij		if (num_large_blocks != refcount) {
2985276081Sdelphij			(void) printf("large_blocks feature refcount mismatch: "
2986276081Sdelphij			    "expected %lld != actual %lld\n",
2987276081Sdelphij			    (longlong_t)num_large_blocks,
2988276081Sdelphij			    (longlong_t)refcount);
2989276081Sdelphij			rc = 2;
2990276081Sdelphij		} else {
2991276081Sdelphij			(void) printf("Verified large_blocks feature refcount "
2992276081Sdelphij			    "is correct (%llu)\n", (longlong_t)refcount);
2993276081Sdelphij		}
2994168404Spjd	}
2995276081Sdelphij	if (rc == 0 && (dump_opt['b'] || dump_opt['c']))
2996168404Spjd		rc = dump_block_stats(spa);
2997168404Spjd
2998262093Savg	if (rc == 0)
2999262093Savg		rc = verify_spacemap_refcounts(spa);
3000262093Savg
3001168404Spjd	if (dump_opt['s'])
3002168404Spjd		show_pool_stats(spa);
3003168404Spjd
3004219089Spjd	if (dump_opt['h'])
3005219089Spjd		dump_history(spa);
3006219089Spjd
3007168404Spjd	if (rc != 0)
3008168404Spjd		exit(rc);
3009168404Spjd}
3010168404Spjd
3011168404Spjd#define	ZDB_FLAG_CHECKSUM	0x0001
3012168404Spjd#define	ZDB_FLAG_DECOMPRESS	0x0002
3013168404Spjd#define	ZDB_FLAG_BSWAP		0x0004
3014168404Spjd#define	ZDB_FLAG_GBH		0x0008
3015168404Spjd#define	ZDB_FLAG_INDIRECT	0x0010
3016168404Spjd#define	ZDB_FLAG_PHYS		0x0020
3017168404Spjd#define	ZDB_FLAG_RAW		0x0040
3018168404Spjd#define	ZDB_FLAG_PRINT_BLKPTR	0x0080
3019168404Spjd
3020168404Spjdint flagbits[256];
3021168404Spjd
3022168404Spjdstatic void
3023168404Spjdzdb_print_blkptr(blkptr_t *bp, int flags)
3024168404Spjd{
3025219089Spjd	char blkbuf[BP_SPRINTF_LEN];
3026168404Spjd
3027168404Spjd	if (flags & ZDB_FLAG_BSWAP)
3028168404Spjd		byteswap_uint64_array((void *)bp, sizeof (blkptr_t));
3029219089Spjd
3030263397Sdelphij	snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
3031219089Spjd	(void) printf("%s\n", blkbuf);
3032168404Spjd}
3033168404Spjd
3034168404Spjdstatic void
3035168404Spjdzdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
3036168404Spjd{
3037168404Spjd	int i;
3038168404Spjd
3039168404Spjd	for (i = 0; i < nbps; i++)
3040168404Spjd		zdb_print_blkptr(&bp[i], flags);
3041168404Spjd}
3042168404Spjd
3043168404Spjdstatic void
3044168404Spjdzdb_dump_gbh(void *buf, int flags)
3045168404Spjd{
3046168404Spjd	zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
3047168404Spjd}
3048168404Spjd
3049168404Spjdstatic void
3050168404Spjdzdb_dump_block_raw(void *buf, uint64_t size, int flags)
3051168404Spjd{
3052168404Spjd	if (flags & ZDB_FLAG_BSWAP)
3053168404Spjd		byteswap_uint64_array(buf, size);
3054219089Spjd	(void) write(1, buf, size);
3055168404Spjd}
3056168404Spjd
3057168404Spjdstatic void
3058168404Spjdzdb_dump_block(char *label, void *buf, uint64_t size, int flags)
3059168404Spjd{
3060168404Spjd	uint64_t *d = (uint64_t *)buf;
3061168404Spjd	int nwords = size / sizeof (uint64_t);
3062168404Spjd	int do_bswap = !!(flags & ZDB_FLAG_BSWAP);
3063168404Spjd	int i, j;
3064168404Spjd	char *hdr, *c;
3065168404Spjd
3066168404Spjd
3067168404Spjd	if (do_bswap)
3068168404Spjd		hdr = " 7 6 5 4 3 2 1 0   f e d c b a 9 8";
3069168404Spjd	else
3070168404Spjd		hdr = " 0 1 2 3 4 5 6 7   8 9 a b c d e f";
3071168404Spjd
3072168404Spjd	(void) printf("\n%s\n%6s   %s  0123456789abcdef\n", label, "", hdr);
3073168404Spjd
3074168404Spjd	for (i = 0; i < nwords; i += 2) {
3075168404Spjd		(void) printf("%06llx:  %016llx  %016llx  ",
3076168404Spjd		    (u_longlong_t)(i * sizeof (uint64_t)),
3077168404Spjd		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i]) : d[i]),
3078168404Spjd		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i + 1]) : d[i + 1]));
3079168404Spjd
3080168404Spjd		c = (char *)&d[i];
3081168404Spjd		for (j = 0; j < 2 * sizeof (uint64_t); j++)
3082168404Spjd			(void) printf("%c", isprint(c[j]) ? c[j] : '.');
3083168404Spjd		(void) printf("\n");
3084168404Spjd	}
3085168404Spjd}
3086168404Spjd
3087168404Spjd/*
3088168404Spjd * There are two acceptable formats:
3089168404Spjd *	leaf_name	  - For example: c1t0d0 or /tmp/ztest.0a
3090168404Spjd *	child[.child]*    - For example: 0.1.1
3091168404Spjd *
3092168404Spjd * The second form can be used to specify arbitrary vdevs anywhere
3093168404Spjd * in the heirarchy.  For example, in a pool with a mirror of
3094168404Spjd * RAID-Zs, you can specify either RAID-Z vdev with 0.0 or 0.1 .
3095168404Spjd */
3096168404Spjdstatic vdev_t *
3097168404Spjdzdb_vdev_lookup(vdev_t *vdev, char *path)
3098168404Spjd{
3099168404Spjd	char *s, *p, *q;
3100168404Spjd	int i;
3101168404Spjd
3102168404Spjd	if (vdev == NULL)
3103168404Spjd		return (NULL);
3104168404Spjd
3105168404Spjd	/* First, assume the x.x.x.x format */
3106168404Spjd	i = (int)strtoul(path, &s, 10);
3107168404Spjd	if (s == path || (s && *s != '.' && *s != '\0'))
3108168404Spjd		goto name;
3109168404Spjd	if (i < 0 || i >= vdev->vdev_children)
3110168404Spjd		return (NULL);
3111168404Spjd
3112168404Spjd	vdev = vdev->vdev_child[i];
3113168404Spjd	if (*s == '\0')
3114168404Spjd		return (vdev);
3115168404Spjd	return (zdb_vdev_lookup(vdev, s+1));
3116168404Spjd
3117168404Spjdname:
3118168404Spjd	for (i = 0; i < vdev->vdev_children; i++) {
3119168404Spjd		vdev_t *vc = vdev->vdev_child[i];
3120168404Spjd
3121168404Spjd		if (vc->vdev_path == NULL) {
3122168404Spjd			vc = zdb_vdev_lookup(vc, path);
3123168404Spjd			if (vc == NULL)
3124168404Spjd				continue;
3125168404Spjd			else
3126168404Spjd				return (vc);
3127168404Spjd		}
3128168404Spjd
3129168404Spjd		p = strrchr(vc->vdev_path, '/');
3130168404Spjd		p = p ? p + 1 : vc->vdev_path;
3131168404Spjd		q = &vc->vdev_path[strlen(vc->vdev_path) - 2];
3132168404Spjd
3133168404Spjd		if (strcmp(vc->vdev_path, path) == 0)
3134168404Spjd			return (vc);
3135168404Spjd		if (strcmp(p, path) == 0)
3136168404Spjd			return (vc);
3137168404Spjd		if (strcmp(q, "s0") == 0 && strncmp(p, path, q - p) == 0)
3138168404Spjd			return (vc);
3139168404Spjd	}
3140168404Spjd
3141168404Spjd	return (NULL);
3142168404Spjd}
3143168404Spjd
3144168404Spjd/*
3145168404Spjd * Read a block from a pool and print it out.  The syntax of the
3146168404Spjd * block descriptor is:
3147168404Spjd *
3148168404Spjd *	pool:vdev_specifier:offset:size[:flags]
3149168404Spjd *
3150168404Spjd *	pool           - The name of the pool you wish to read from
3151168404Spjd *	vdev_specifier - Which vdev (see comment for zdb_vdev_lookup)
3152168404Spjd *	offset         - offset, in hex, in bytes
3153168404Spjd *	size           - Amount of data to read, in hex, in bytes
3154168404Spjd *	flags          - A string of characters specifying options
3155168404Spjd *		 b: Decode a blkptr at given offset within block
3156168404Spjd *		*c: Calculate and display checksums
3157219089Spjd *		 d: Decompress data before dumping
3158168404Spjd *		 e: Byteswap data before dumping
3159219089Spjd *		 g: Display data as a gang block header
3160219089Spjd *		 i: Display as an indirect block
3161168404Spjd *		 p: Do I/O to physical offset
3162168404Spjd *		 r: Dump raw data to stdout
3163168404Spjd *
3164168404Spjd *              * = not yet implemented
3165168404Spjd */
3166168404Spjdstatic void
3167219089Spjdzdb_read_block(char *thing, spa_t *spa)
3168168404Spjd{
3169219089Spjd	blkptr_t blk, *bp = &blk;
3170219089Spjd	dva_t *dva = bp->blk_dva;
3171168404Spjd	int flags = 0;
3172219089Spjd	uint64_t offset = 0, size = 0, psize = 0, lsize = 0, blkptr_offset = 0;
3173168404Spjd	zio_t *zio;
3174168404Spjd	vdev_t *vd;
3175219089Spjd	void *pbuf, *lbuf, *buf;
3176219089Spjd	char *s, *p, *dup, *vdev, *flagstr;
3177219089Spjd	int i, error;
3178168404Spjd
3179168404Spjd	dup = strdup(thing);
3180168404Spjd	s = strtok(dup, ":");
3181168404Spjd	vdev = s ? s : "";
3182168404Spjd	s = strtok(NULL, ":");
3183168404Spjd	offset = strtoull(s ? s : "", NULL, 16);
3184168404Spjd	s = strtok(NULL, ":");
3185168404Spjd	size = strtoull(s ? s : "", NULL, 16);
3186168404Spjd	s = strtok(NULL, ":");
3187168404Spjd	flagstr = s ? s : "";
3188168404Spjd
3189168404Spjd	s = NULL;
3190168404Spjd	if (size == 0)
3191168404Spjd		s = "size must not be zero";
3192168404Spjd	if (!IS_P2ALIGNED(size, DEV_BSIZE))
3193168404Spjd		s = "size must be a multiple of sector size";
3194168404Spjd	if (!IS_P2ALIGNED(offset, DEV_BSIZE))
3195168404Spjd		s = "offset must be a multiple of sector size";
3196168404Spjd	if (s) {
3197168404Spjd		(void) printf("Invalid block specifier: %s  - %s\n", thing, s);
3198168404Spjd		free(dup);
3199168404Spjd		return;
3200168404Spjd	}
3201168404Spjd
3202168404Spjd	for (s = strtok(flagstr, ":"); s; s = strtok(NULL, ":")) {
3203168404Spjd		for (i = 0; flagstr[i]; i++) {
3204168404Spjd			int bit = flagbits[(uchar_t)flagstr[i]];
3205168404Spjd
3206168404Spjd			if (bit == 0) {
3207168404Spjd				(void) printf("***Invalid flag: %c\n",
3208168404Spjd				    flagstr[i]);
3209168404Spjd				continue;
3210168404Spjd			}
3211168404Spjd			flags |= bit;
3212168404Spjd
3213168404Spjd			/* If it's not something with an argument, keep going */
3214219089Spjd			if ((bit & (ZDB_FLAG_CHECKSUM |
3215168404Spjd			    ZDB_FLAG_PRINT_BLKPTR)) == 0)
3216168404Spjd				continue;
3217168404Spjd
3218168404Spjd			p = &flagstr[i + 1];
3219168404Spjd			if (bit == ZDB_FLAG_PRINT_BLKPTR)
3220168404Spjd				blkptr_offset = strtoull(p, &p, 16);
3221168404Spjd			if (*p != ':' && *p != '\0') {
3222168404Spjd				(void) printf("***Invalid flag arg: '%s'\n", s);
3223168404Spjd				free(dup);
3224168404Spjd				return;
3225168404Spjd			}
3226262104Savg			i += p - &flagstr[i + 1]; /* skip over the number */
3227168404Spjd		}
3228168404Spjd	}
3229168404Spjd
3230168404Spjd	vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev);
3231168404Spjd	if (vd == NULL) {
3232168404Spjd		(void) printf("***Invalid vdev: %s\n", vdev);
3233168404Spjd		free(dup);
3234168404Spjd		return;
3235168404Spjd	} else {
3236168404Spjd		if (vd->vdev_path)
3237219089Spjd			(void) fprintf(stderr, "Found vdev: %s\n",
3238219089Spjd			    vd->vdev_path);
3239168404Spjd		else
3240219089Spjd			(void) fprintf(stderr, "Found vdev type: %s\n",
3241168404Spjd			    vd->vdev_ops->vdev_op_type);
3242168404Spjd	}
3243168404Spjd
3244219089Spjd	psize = size;
3245219089Spjd	lsize = size;
3246168404Spjd
3247219089Spjd	pbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
3248219089Spjd	lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
3249168404Spjd
3250219089Spjd	BP_ZERO(bp);
3251219089Spjd
3252219089Spjd	DVA_SET_VDEV(&dva[0], vd->vdev_id);
3253219089Spjd	DVA_SET_OFFSET(&dva[0], offset);
3254219089Spjd	DVA_SET_GANG(&dva[0], !!(flags & ZDB_FLAG_GBH));
3255219089Spjd	DVA_SET_ASIZE(&dva[0], vdev_psize_to_asize(vd, psize));
3256219089Spjd
3257219089Spjd	BP_SET_BIRTH(bp, TXG_INITIAL, TXG_INITIAL);
3258219089Spjd
3259219089Spjd	BP_SET_LSIZE(bp, lsize);
3260219089Spjd	BP_SET_PSIZE(bp, psize);
3261219089Spjd	BP_SET_COMPRESS(bp, ZIO_COMPRESS_OFF);
3262219089Spjd	BP_SET_CHECKSUM(bp, ZIO_CHECKSUM_OFF);
3263219089Spjd	BP_SET_TYPE(bp, DMU_OT_NONE);
3264219089Spjd	BP_SET_LEVEL(bp, 0);
3265219089Spjd	BP_SET_DEDUP(bp, 0);
3266219089Spjd	BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
3267219089Spjd
3268185029Spjd	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
3269168404Spjd	zio = zio_root(spa, NULL, NULL, 0);
3270219089Spjd
3271219089Spjd	if (vd == vd->vdev_top) {
3272219089Spjd		/*
3273219089Spjd		 * Treat this as a normal block read.
3274219089Spjd		 */
3275219089Spjd		zio_nowait(zio_read(zio, spa, bp, pbuf, psize, NULL, NULL,
3276219089Spjd		    ZIO_PRIORITY_SYNC_READ,
3277219089Spjd		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL));
3278219089Spjd	} else {
3279219089Spjd		/*
3280219089Spjd		 * Treat this as a vdev child I/O.
3281219089Spjd		 */
3282219089Spjd		zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pbuf, psize,
3283219089Spjd		    ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ,
3284219089Spjd		    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE |
3285219089Spjd		    ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
3286219089Spjd		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL, NULL));
3287219089Spjd	}
3288219089Spjd
3289168404Spjd	error = zio_wait(zio);
3290185029Spjd	spa_config_exit(spa, SCL_STATE, FTAG);
3291168404Spjd
3292168404Spjd	if (error) {
3293168404Spjd		(void) printf("Read of %s failed, error: %d\n", thing, error);
3294168404Spjd		goto out;
3295168404Spjd	}
3296168404Spjd
3297219089Spjd	if (flags & ZDB_FLAG_DECOMPRESS) {
3298219089Spjd		/*
3299219089Spjd		 * We don't know how the data was compressed, so just try
3300219089Spjd		 * every decompress function at every inflated blocksize.
3301219089Spjd		 */
3302219089Spjd		enum zio_compress c;
3303219089Spjd		void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
3304219089Spjd		void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
3305219089Spjd
3306219089Spjd		bcopy(pbuf, pbuf2, psize);
3307219089Spjd
3308219089Spjd		VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf + psize,
3309219089Spjd		    SPA_MAXBLOCKSIZE - psize) == 0);
3310219089Spjd
3311219089Spjd		VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize,
3312219089Spjd		    SPA_MAXBLOCKSIZE - psize) == 0);
3313219089Spjd
3314219089Spjd		for (lsize = SPA_MAXBLOCKSIZE; lsize > psize;
3315219089Spjd		    lsize -= SPA_MINBLOCKSIZE) {
3316219089Spjd			for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) {
3317219089Spjd				if (zio_decompress_data(c, pbuf, lbuf,
3318219089Spjd				    psize, lsize) == 0 &&
3319219089Spjd				    zio_decompress_data(c, pbuf2, lbuf2,
3320219089Spjd				    psize, lsize) == 0 &&
3321219089Spjd				    bcmp(lbuf, lbuf2, lsize) == 0)
3322219089Spjd					break;
3323219089Spjd			}
3324219089Spjd			if (c != ZIO_COMPRESS_FUNCTIONS)
3325219089Spjd				break;
3326219089Spjd			lsize -= SPA_MINBLOCKSIZE;
3327219089Spjd		}
3328219089Spjd
3329219089Spjd		umem_free(pbuf2, SPA_MAXBLOCKSIZE);
3330219089Spjd		umem_free(lbuf2, SPA_MAXBLOCKSIZE);
3331219089Spjd
3332219089Spjd		if (lsize <= psize) {
3333219089Spjd			(void) printf("Decompress of %s failed\n", thing);
3334219089Spjd			goto out;
3335219089Spjd		}
3336219089Spjd		buf = lbuf;
3337219089Spjd		size = lsize;
3338219089Spjd	} else {
3339219089Spjd		buf = pbuf;
3340219089Spjd		size = psize;
3341219089Spjd	}
3342219089Spjd
3343168404Spjd	if (flags & ZDB_FLAG_PRINT_BLKPTR)
3344168404Spjd		zdb_print_blkptr((blkptr_t *)(void *)
3345168404Spjd		    ((uintptr_t)buf + (uintptr_t)blkptr_offset), flags);
3346168404Spjd	else if (flags & ZDB_FLAG_RAW)
3347168404Spjd		zdb_dump_block_raw(buf, size, flags);
3348168404Spjd	else if (flags & ZDB_FLAG_INDIRECT)
3349168404Spjd		zdb_dump_indirect((blkptr_t *)buf, size / sizeof (blkptr_t),
3350168404Spjd		    flags);
3351168404Spjd	else if (flags & ZDB_FLAG_GBH)
3352168404Spjd		zdb_dump_gbh(buf, flags);
3353168404Spjd	else
3354168404Spjd		zdb_dump_block(thing, buf, size, flags);
3355168404Spjd
3356168404Spjdout:
3357219089Spjd	umem_free(pbuf, SPA_MAXBLOCKSIZE);
3358219089Spjd	umem_free(lbuf, SPA_MAXBLOCKSIZE);
3359168404Spjd	free(dup);
3360168404Spjd}
3361168404Spjd
3362185029Spjdstatic boolean_t
3363219089Spjdpool_match(nvlist_t *cfg, char *tgt)
3364185029Spjd{
3365219089Spjd	uint64_t v, guid = strtoull(tgt, NULL, 0);
3366185029Spjd	char *s;
3367185029Spjd
3368219089Spjd	if (guid != 0) {
3369219089Spjd		if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0)
3370219089Spjd			return (v == guid);
3371219089Spjd	} else {
3372219089Spjd		if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0)
3373219089Spjd			return (strcmp(s, tgt) == 0);
3374185029Spjd	}
3375185029Spjd	return (B_FALSE);
3376185029Spjd}
3377185029Spjd
3378219089Spjdstatic char *
3379219089Spjdfind_zpool(char **target, nvlist_t **configp, int dirc, char **dirv)
3380185029Spjd{
3381219089Spjd	nvlist_t *pools;
3382219089Spjd	nvlist_t *match = NULL;
3383219089Spjd	char *name = NULL;
3384219089Spjd	char *sepp = NULL;
3385219089Spjd	char sep;
3386219089Spjd	int count = 0;
3387219089Spjd	importargs_t args = { 0 };
3388185029Spjd
3389219089Spjd	args.paths = dirc;
3390219089Spjd	args.path = dirv;
3391219089Spjd	args.can_be_active = B_TRUE;
3392185029Spjd
3393219089Spjd	if ((sepp = strpbrk(*target, "/@")) != NULL) {
3394219089Spjd		sep = *sepp;
3395219089Spjd		*sepp = '\0';
3396185029Spjd	}
3397185029Spjd
3398219089Spjd	pools = zpool_search_import(g_zfs, &args);
3399185029Spjd
3400185029Spjd	if (pools != NULL) {
3401185029Spjd		nvpair_t *elem = NULL;
3402185029Spjd		while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3403185029Spjd			verify(nvpair_value_nvlist(elem, configp) == 0);
3404219089Spjd			if (pool_match(*configp, *target)) {
3405219089Spjd				count++;
3406185029Spjd				if (match != NULL) {
3407219089Spjd					/* print previously found config */
3408219089Spjd					if (name != NULL) {
3409219089Spjd						(void) printf("%s\n", name);
3410219089Spjd						dump_nvlist(match, 8);
3411219089Spjd						name = NULL;
3412219089Spjd					}
3413219089Spjd					(void) printf("%s\n",
3414219089Spjd					    nvpair_name(elem));
3415219089Spjd					dump_nvlist(*configp, 8);
3416185029Spjd				} else {
3417185029Spjd					match = *configp;
3418219089Spjd					name = nvpair_name(elem);
3419185029Spjd				}
3420185029Spjd			}
3421185029Spjd		}
3422185029Spjd	}
3423219089Spjd	if (count > 1)
3424219089Spjd		(void) fatal("\tMatched %d pools - use pool GUID "
3425219089Spjd		    "instead of pool name or \n"
3426219089Spjd		    "\tpool name part of a dataset name to select pool", count);
3427185029Spjd
3428219089Spjd	if (sepp)
3429219089Spjd		*sepp = sep;
3430219089Spjd	/*
3431219089Spjd	 * If pool GUID was specified for pool id, replace it with pool name
3432219089Spjd	 */
3433219089Spjd	if (name && (strstr(*target, name) != *target)) {
3434219089Spjd		int sz = 1 + strlen(name) + ((sepp) ? strlen(sepp) : 0);
3435185029Spjd
3436219089Spjd		*target = umem_alloc(sz, UMEM_NOFAIL);
3437219089Spjd		(void) snprintf(*target, sz, "%s%s", name, sepp ? sepp : "");
3438219089Spjd	}
3439219089Spjd
3440219089Spjd	*configp = name ? match : NULL;
3441219089Spjd
3442219089Spjd	return (name);
3443185029Spjd}
3444185029Spjd
3445168404Spjdint
3446168404Spjdmain(int argc, char **argv)
3447168404Spjd{
3448168404Spjd	int i, c;
3449168404Spjd	struct rlimit rl = { 1024, 1024 };
3450219089Spjd	spa_t *spa = NULL;
3451168404Spjd	objset_t *os = NULL;
3452168404Spjd	int dump_all = 1;
3453168404Spjd	int verbose = 0;
3454219089Spjd	int error = 0;
3455219089Spjd	char **searchdirs = NULL;
3456219089Spjd	int nsearch = 0;
3457219089Spjd	char *target;
3458219089Spjd	nvlist_t *policy = NULL;
3459219089Spjd	uint64_t max_txg = UINT64_MAX;
3460219089Spjd	int rewind = ZPOOL_NEVER_REWIND;
3461168404Spjd
3462168404Spjd	(void) setrlimit(RLIMIT_NOFILE, &rl);
3463168404Spjd	(void) enable_extended_FILE_stdio(-1, -1);
3464168404Spjd
3465168404Spjd	dprintf_setup(&argc, argv);
3466168404Spjd
3467268653Sdelphij	while ((c = getopt(argc, argv,
3468269773Sdelphij	    "bcdhilmMI:suCDRSAFLXx:evp:t:U:P")) != -1) {
3469168404Spjd		switch (c) {
3470219089Spjd		case 'b':
3471219089Spjd		case 'c':
3472168404Spjd		case 'd':
3473219089Spjd		case 'h':
3474168404Spjd		case 'i':
3475219089Spjd		case 'l':
3476209962Smm		case 'm':
3477168404Spjd		case 's':
3478219089Spjd		case 'u':
3479168404Spjd		case 'C':
3480219089Spjd		case 'D':
3481269773Sdelphij		case 'M':
3482168404Spjd		case 'R':
3483219089Spjd		case 'S':
3484168404Spjd			dump_opt[c]++;
3485168404Spjd			dump_all = 0;
3486168404Spjd			break;
3487219089Spjd		case 'A':
3488219089Spjd		case 'F':
3489209962Smm		case 'L':
3490219089Spjd		case 'X':
3491219089Spjd		case 'e':
3492219089Spjd		case 'P':
3493209962Smm			dump_opt[c]++;
3494209962Smm			break;
3495269773Sdelphij		case 'I':
3496263393Sdelphij			max_inflight = strtoull(optarg, NULL, 0);
3497263393Sdelphij			if (max_inflight == 0) {
3498263393Sdelphij				(void) fprintf(stderr, "maximum number "
3499263393Sdelphij				    "of inflight I/Os must be greater "
3500263393Sdelphij				    "than 0\n");
3501263393Sdelphij				usage();
3502263393Sdelphij			}
3503263393Sdelphij			break;
3504185029Spjd		case 'p':
3505219089Spjd			if (searchdirs == NULL) {
3506219089Spjd				searchdirs = umem_alloc(sizeof (char *),
3507219089Spjd				    UMEM_NOFAIL);
3508219089Spjd			} else {
3509219089Spjd				char **tmp = umem_alloc((nsearch + 1) *
3510219089Spjd				    sizeof (char *), UMEM_NOFAIL);
3511219089Spjd				bcopy(searchdirs, tmp, nsearch *
3512219089Spjd				    sizeof (char *));
3513219089Spjd				umem_free(searchdirs,
3514219089Spjd				    nsearch * sizeof (char *));
3515219089Spjd				searchdirs = tmp;
3516219089Spjd			}
3517219089Spjd			searchdirs[nsearch++] = optarg;
3518185029Spjd			break;
3519209962Smm		case 't':
3520219089Spjd			max_txg = strtoull(optarg, NULL, 0);
3521219089Spjd			if (max_txg < TXG_INITIAL) {
3522209962Smm				(void) fprintf(stderr, "incorrect txg "
3523209962Smm				    "specified: %s\n", optarg);
3524209962Smm				usage();
3525209962Smm			}
3526209962Smm			break;
3527219089Spjd		case 'U':
3528219089Spjd			spa_config_path = optarg;
3529219089Spjd			break;
3530269773Sdelphij		case 'v':
3531269773Sdelphij			verbose++;
3532269773Sdelphij			break;
3533269773Sdelphij		case 'x':
3534269773Sdelphij			vn_dumpdir = optarg;
3535269773Sdelphij			break;
3536168404Spjd		default:
3537168404Spjd			usage();
3538168404Spjd			break;
3539168404Spjd		}
3540168404Spjd	}
3541168404Spjd
3542219089Spjd	if (!dump_opt['e'] && searchdirs != NULL) {
3543208047Smm		(void) fprintf(stderr, "-p option requires use of -e\n");
3544208047Smm		usage();
3545208047Smm	}
3546185029Spjd
3547273508Sdelphij	/*
3548273508Sdelphij	 * ZDB does not typically re-read blocks; therefore limit the ARC
3549273508Sdelphij	 * to 256 MB, which can be used entirely for metadata.
3550273508Sdelphij	 */
3551273508Sdelphij	zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
3552273508Sdelphij
3553275488Sdelphij	/*
3554275488Sdelphij	 * "zdb -c" uses checksum-verifying scrub i/os which are async reads.
3555275488Sdelphij	 * "zdb -b" uses traversal prefetch which uses async reads.
3556275488Sdelphij	 * For good performance, let several of them be active at once.
3557275488Sdelphij	 */
3558275488Sdelphij	zfs_vdev_async_read_max_active = 10;
3559275488Sdelphij
3560168404Spjd	kernel_init(FREAD);
3561185029Spjd	g_zfs = libzfs_init();
3562185029Spjd	ASSERT(g_zfs != NULL);
3563168404Spjd
3564219089Spjd	if (dump_all)
3565219089Spjd		verbose = MAX(verbose, 1);
3566219089Spjd
3567168404Spjd	for (c = 0; c < 256; c++) {
3568219089Spjd		if (dump_all && !strchr("elAFLRSXP", c))
3569168404Spjd			dump_opt[c] = 1;
3570168404Spjd		if (dump_opt[c])
3571168404Spjd			dump_opt[c] += verbose;
3572168404Spjd	}
3573168404Spjd
3574219089Spjd	aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2);
3575219089Spjd	zfs_recover = (dump_opt['A'] > 1);
3576219089Spjd
3577168404Spjd	argc -= optind;
3578168404Spjd	argv += optind;
3579168404Spjd
3580219089Spjd	if (argc < 2 && dump_opt['R'])
3581219089Spjd		usage();
3582168404Spjd	if (argc < 1) {
3583219089Spjd		if (!dump_opt['e'] && dump_opt['C']) {
3584185029Spjd			dump_cachefile(spa_config_path);
3585168404Spjd			return (0);
3586168404Spjd		}
3587168404Spjd		usage();
3588168404Spjd	}
3589168404Spjd
3590168404Spjd	if (dump_opt['l']) {
3591168404Spjd		dump_label(argv[0]);
3592168404Spjd		return (0);
3593168404Spjd	}
3594168404Spjd
3595219089Spjd	if (dump_opt['X'] || dump_opt['F'])
3596219089Spjd		rewind = ZPOOL_DO_REWIND |
3597219089Spjd		    (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
3598168404Spjd
3599219089Spjd	if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 ||
3600219089Spjd	    nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, max_txg) != 0 ||
3601219089Spjd	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind) != 0)
3602219089Spjd		fatal("internal error: %s", strerror(ENOMEM));
3603168404Spjd
3604185029Spjd	error = 0;
3605219089Spjd	target = argv[0];
3606185029Spjd
3607219089Spjd	if (dump_opt['e']) {
3608219089Spjd		nvlist_t *cfg = NULL;
3609219089Spjd		char *name = find_zpool(&target, &cfg, nsearch, searchdirs);
3610185029Spjd
3611219089Spjd		error = ENOENT;
3612219089Spjd		if (name) {
3613219089Spjd			if (dump_opt['C'] > 1) {
3614219089Spjd				(void) printf("\nConfiguration for import:\n");
3615219089Spjd				dump_nvlist(cfg, 8);
3616185029Spjd			}
3617219089Spjd			if (nvlist_add_nvlist(cfg,
3618219089Spjd			    ZPOOL_REWIND_POLICY, policy) != 0) {
3619219089Spjd				fatal("can't open '%s': %s",
3620219089Spjd				    target, strerror(ENOMEM));
3621219089Spjd			}
3622219089Spjd			if ((error = spa_import(name, cfg, NULL,
3623219089Spjd			    ZFS_IMPORT_MISSING_LOG)) != 0) {
3624219089Spjd				error = spa_import(name, cfg, NULL,
3625219089Spjd				    ZFS_IMPORT_VERBATIM);
3626219089Spjd			}
3627185029Spjd		}
3628168404Spjd	}
3629168404Spjd
3630185029Spjd	if (error == 0) {
3631219089Spjd		if (strpbrk(target, "/@") == NULL || dump_opt['R']) {
3632219089Spjd			error = spa_open_rewind(target, &spa, FTAG, policy,
3633219089Spjd			    NULL);
3634219089Spjd			if (error) {
3635219089Spjd				/*
3636219089Spjd				 * If we're missing the log device then
3637219089Spjd				 * try opening the pool after clearing the
3638219089Spjd				 * log state.
3639219089Spjd				 */
3640219089Spjd				mutex_enter(&spa_namespace_lock);
3641219089Spjd				if ((spa = spa_lookup(target)) != NULL &&
3642219089Spjd				    spa->spa_log_state == SPA_LOG_MISSING) {
3643219089Spjd					spa->spa_log_state = SPA_LOG_CLEAR;
3644219089Spjd					error = 0;
3645219089Spjd				}
3646219089Spjd				mutex_exit(&spa_namespace_lock);
3647219089Spjd
3648219089Spjd				if (!error) {
3649219089Spjd					error = spa_open_rewind(target, &spa,
3650219089Spjd					    FTAG, policy, NULL);
3651219089Spjd				}
3652219089Spjd			}
3653185029Spjd		} else {
3654219089Spjd			error = dmu_objset_own(target, DMU_OST_ANY,
3655219089Spjd			    B_TRUE, FTAG, &os);
3656185029Spjd		}
3657185029Spjd	}
3658219089Spjd	nvlist_free(policy);
3659185029Spjd
3660168404Spjd	if (error)
3661219089Spjd		fatal("can't open '%s': %s", target, strerror(error));
3662168404Spjd
3663168404Spjd	argv++;
3664219089Spjd	argc--;
3665219089Spjd	if (!dump_opt['R']) {
3666219089Spjd		if (argc > 0) {
3667219089Spjd			zopt_objects = argc;
3668219089Spjd			zopt_object = calloc(zopt_objects, sizeof (uint64_t));
3669219089Spjd			for (i = 0; i < zopt_objects; i++) {
3670219089Spjd				errno = 0;
3671219089Spjd				zopt_object[i] = strtoull(argv[i], NULL, 0);
3672219089Spjd				if (zopt_object[i] == 0 && errno != 0)
3673219089Spjd					fatal("bad number %s: %s",
3674219089Spjd					    argv[i], strerror(errno));
3675219089Spjd			}
3676168404Spjd		}
3677244246Smm		if (os != NULL) {
3678244246Smm			dump_dir(os);
3679244246Smm		} else if (zopt_objects > 0 && !dump_opt['m']) {
3680244246Smm			dump_dir(spa->spa_meta_objset);
3681244246Smm		} else {
3682244246Smm			dump_zpool(spa);
3683244246Smm		}
3684219089Spjd	} else {
3685219089Spjd		flagbits['b'] = ZDB_FLAG_PRINT_BLKPTR;
3686219089Spjd		flagbits['c'] = ZDB_FLAG_CHECKSUM;
3687219089Spjd		flagbits['d'] = ZDB_FLAG_DECOMPRESS;
3688219089Spjd		flagbits['e'] = ZDB_FLAG_BSWAP;
3689219089Spjd		flagbits['g'] = ZDB_FLAG_GBH;
3690219089Spjd		flagbits['i'] = ZDB_FLAG_INDIRECT;
3691219089Spjd		flagbits['p'] = ZDB_FLAG_PHYS;
3692219089Spjd		flagbits['r'] = ZDB_FLAG_RAW;
3693168404Spjd
3694219089Spjd		for (i = 0; i < argc; i++)
3695219089Spjd			zdb_read_block(argv[i], spa);
3696168404Spjd	}
3697168404Spjd
3698219089Spjd	(os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
3699219089Spjd
3700185029Spjd	fuid_table_destroy();
3701219089Spjd	sa_loaded = B_FALSE;
3702185029Spjd
3703185029Spjd	libzfs_fini(g_zfs);
3704168404Spjd	kernel_fini();
3705168404Spjd
3706168404Spjd	return (0);
3707168404Spjd}
3708