zdb.c revision 8f2529de2d60d4fff8eb4d86f71b51584342934e
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#include <stdio.h>
26#include <stdio_ext.h>
27#include <stdlib.h>
28#include <ctype.h>
29#include <sys/zfs_context.h>
30#include <sys/spa.h>
31#include <sys/spa_impl.h>
32#include <sys/dmu.h>
33#include <sys/zap.h>
34#include <sys/fs/zfs.h>
35#include <sys/zfs_znode.h>
36#include <sys/zfs_sa.h>
37#include <sys/sa.h>
38#include <sys/sa_impl.h>
39#include <sys/vdev.h>
40#include <sys/vdev_impl.h>
41#include <sys/metaslab_impl.h>
42#include <sys/dmu_objset.h>
43#include <sys/dsl_dir.h>
44#include <sys/dsl_dataset.h>
45#include <sys/dsl_pool.h>
46#include <sys/dbuf.h>
47#include <sys/zil.h>
48#include <sys/zil_impl.h>
49#include <sys/stat.h>
50#include <sys/resource.h>
51#include <sys/dmu_traverse.h>
52#include <sys/zio_checksum.h>
53#include <sys/zio_compress.h>
54#include <sys/zfs_fuid.h>
55#include <sys/arc.h>
56#include <sys/ddt.h>
57#undef ZFS_MAXNAMELEN
58#undef verify
59#include <libzfs.h>
60
61#define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
62    zio_compress_table[(idx)].ci_name : "UNKNOWN")
63#define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
64    zio_checksum_table[(idx)].ci_name : "UNKNOWN")
65#define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \
66    dmu_ot[(idx)].ot_name : "UNKNOWN")
67#define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : DMU_OT_NUMTYPES)
68
69#ifndef lint
70extern int zfs_recover;
71#else
72int zfs_recover;
73#endif
74
75const char cmdname[] = "zdb";
76uint8_t dump_opt[256];
77
78typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
79
80extern void dump_intent_log(zilog_t *);
81uint64_t *zopt_object = NULL;
82int zopt_objects = 0;
83libzfs_handle_t *g_zfs;
84
85/*
86 * These libumem hooks provide a reasonable set of defaults for the allocator's
87 * debugging facilities.
88 */
89const char *
90_umem_debug_init()
91{
92	return ("default,verbose"); /* $UMEM_DEBUG setting */
93}
94
95const char *
96_umem_logging_init(void)
97{
98	return ("fail,contents"); /* $UMEM_LOGGING setting */
99}
100
101static void
102usage(void)
103{
104	(void) fprintf(stderr,
105	    "Usage: %s [-CumdibcsDvhL] poolname [object...]\n"
106	    "       %s [-div] dataset [object...]\n"
107	    "       %s -m [-L] poolname [vdev [metaslab...]]\n"
108	    "       %s -R poolname vdev:offset:size[:flags]\n"
109	    "       %s -S poolname\n"
110	    "       %s -l [-u] device\n"
111	    "       %s -C\n\n",
112	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
113
114	(void) fprintf(stderr, "    Dataset name must include at least one "
115	    "separator character '/' or '@'\n");
116	(void) fprintf(stderr, "    If dataset name is specified, only that "
117	    "dataset is dumped\n");
118	(void) fprintf(stderr, "    If object numbers are specified, only "
119	    "those objects are dumped\n\n");
120	(void) fprintf(stderr, "    Options to control amount of output:\n");
121	(void) fprintf(stderr, "        -u uberblock\n");
122	(void) fprintf(stderr, "        -d dataset(s)\n");
123	(void) fprintf(stderr, "        -i intent logs\n");
124	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
125	(void) fprintf(stderr, "        -h pool history\n");
126	(void) fprintf(stderr, "        -b block statistics\n");
127	(void) fprintf(stderr, "        -m metaslabs\n");
128	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
129	    "all data) blocks\n");
130	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
131	(void) fprintf(stderr, "        -D dedup statistics\n");
132	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
133	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
134	(void) fprintf(stderr, "        -l dump label contents\n");
135	(void) fprintf(stderr, "        -L disable leak tracking (do not "
136	    "load spacemaps)\n");
137	(void) fprintf(stderr, "        -R read and display block from a "
138	    "device\n\n");
139	(void) fprintf(stderr, "    Below options are intended for use "
140	    "with other options (except -l):\n");
141	(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
142	    "panic recovery (-AA) or both (-AAA)\n");
143	(void) fprintf(stderr, "        -F attempt automatic rewind within "
144	    "safe range of transaction groups\n");
145	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
146	    "cachefile\n");
147	(void) fprintf(stderr, "        -X attempt extreme rewind (does not "
148	    "work with dataset)\n");
149	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
150	    "has altroot/not in a cachefile\n");
151	(void) fprintf(stderr, "        -p <path> -- use one or more with "
152	    "-e to specify path to vdev dir\n");
153	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
154	    "searching for uberblocks\n");
155	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
156	    "to make only that option verbose\n");
157	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
158	exit(1);
159}
160
161/*
162 * Called for usage errors that are discovered after a call to spa_open(),
163 * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
164 */
165
166static void
167fatal(const char *fmt, ...)
168{
169	va_list ap;
170
171	va_start(ap, fmt);
172	(void) fprintf(stderr, "%s: ", cmdname);
173	(void) vfprintf(stderr, fmt, ap);
174	va_end(ap);
175	(void) fprintf(stderr, "\n");
176
177	exit(1);
178}
179
180/* ARGSUSED */
181static void
182dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
183{
184	nvlist_t *nv;
185	size_t nvsize = *(uint64_t *)data;
186	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
187
188	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
189
190	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
191
192	umem_free(packed, nvsize);
193
194	dump_nvlist(nv, 8);
195
196	nvlist_free(nv);
197}
198
199const char dump_zap_stars[] = "****************************************";
200const int dump_zap_width = sizeof (dump_zap_stars) - 1;
201
202static void
203dump_zap_histogram(uint64_t histo[ZAP_HISTOGRAM_SIZE])
204{
205	int i;
206	int minidx = ZAP_HISTOGRAM_SIZE - 1;
207	int maxidx = 0;
208	uint64_t max = 0;
209
210	for (i = 0; i < ZAP_HISTOGRAM_SIZE; i++) {
211		if (histo[i] > max)
212			max = histo[i];
213		if (histo[i] > 0 && i > maxidx)
214			maxidx = i;
215		if (histo[i] > 0 && i < minidx)
216			minidx = i;
217	}
218
219	if (max < dump_zap_width)
220		max = dump_zap_width;
221
222	for (i = minidx; i <= maxidx; i++)
223		(void) printf("\t\t\t%u: %6llu %s\n", i, (u_longlong_t)histo[i],
224		    &dump_zap_stars[(max - histo[i]) * dump_zap_width / max]);
225}
226
227static void
228dump_zap_stats(objset_t *os, uint64_t object)
229{
230	int error;
231	zap_stats_t zs;
232
233	error = zap_get_stats(os, object, &zs);
234	if (error)
235		return;
236
237	if (zs.zs_ptrtbl_len == 0) {
238		ASSERT(zs.zs_num_blocks == 1);
239		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
240		    (u_longlong_t)zs.zs_blocksize,
241		    (u_longlong_t)zs.zs_num_entries);
242		return;
243	}
244
245	(void) printf("\tFat ZAP stats:\n");
246
247	(void) printf("\t\tPointer table:\n");
248	(void) printf("\t\t\t%llu elements\n",
249	    (u_longlong_t)zs.zs_ptrtbl_len);
250	(void) printf("\t\t\tzt_blk: %llu\n",
251	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
252	(void) printf("\t\t\tzt_numblks: %llu\n",
253	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
254	(void) printf("\t\t\tzt_shift: %llu\n",
255	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
256	(void) printf("\t\t\tzt_blks_copied: %llu\n",
257	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
258	(void) printf("\t\t\tzt_nextblk: %llu\n",
259	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
260
261	(void) printf("\t\tZAP entries: %llu\n",
262	    (u_longlong_t)zs.zs_num_entries);
263	(void) printf("\t\tLeaf blocks: %llu\n",
264	    (u_longlong_t)zs.zs_num_leafs);
265	(void) printf("\t\tTotal blocks: %llu\n",
266	    (u_longlong_t)zs.zs_num_blocks);
267	(void) printf("\t\tzap_block_type: 0x%llx\n",
268	    (u_longlong_t)zs.zs_block_type);
269	(void) printf("\t\tzap_magic: 0x%llx\n",
270	    (u_longlong_t)zs.zs_magic);
271	(void) printf("\t\tzap_salt: 0x%llx\n",
272	    (u_longlong_t)zs.zs_salt);
273
274	(void) printf("\t\tLeafs with 2^n pointers:\n");
275	dump_zap_histogram(zs.zs_leafs_with_2n_pointers);
276
277	(void) printf("\t\tBlocks with n*5 entries:\n");
278	dump_zap_histogram(zs.zs_blocks_with_n5_entries);
279
280	(void) printf("\t\tBlocks n/10 full:\n");
281	dump_zap_histogram(zs.zs_blocks_n_tenths_full);
282
283	(void) printf("\t\tEntries with n chunks:\n");
284	dump_zap_histogram(zs.zs_entries_using_n_chunks);
285
286	(void) printf("\t\tBuckets with n entries:\n");
287	dump_zap_histogram(zs.zs_buckets_with_n_entries);
288}
289
290/*ARGSUSED*/
291static void
292dump_none(objset_t *os, uint64_t object, void *data, size_t size)
293{
294}
295
296/*ARGSUSED*/
297static void
298dump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
299{
300	(void) printf("\tUNKNOWN OBJECT TYPE\n");
301}
302
303/*ARGSUSED*/
304void
305dump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
306{
307}
308
309/*ARGSUSED*/
310static void
311dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
312{
313}
314
315/*ARGSUSED*/
316static void
317dump_zap(objset_t *os, uint64_t object, void *data, size_t size)
318{
319	zap_cursor_t zc;
320	zap_attribute_t attr;
321	void *prop;
322	int i;
323
324	dump_zap_stats(os, object);
325	(void) printf("\n");
326
327	for (zap_cursor_init(&zc, os, object);
328	    zap_cursor_retrieve(&zc, &attr) == 0;
329	    zap_cursor_advance(&zc)) {
330		(void) printf("\t\t%s = ", attr.za_name);
331		if (attr.za_num_integers == 0) {
332			(void) printf("\n");
333			continue;
334		}
335		prop = umem_zalloc(attr.za_num_integers *
336		    attr.za_integer_length, UMEM_NOFAIL);
337		(void) zap_lookup(os, object, attr.za_name,
338		    attr.za_integer_length, attr.za_num_integers, prop);
339		if (attr.za_integer_length == 1) {
340			(void) printf("%s", (char *)prop);
341		} else {
342			for (i = 0; i < attr.za_num_integers; i++) {
343				switch (attr.za_integer_length) {
344				case 2:
345					(void) printf("%u ",
346					    ((uint16_t *)prop)[i]);
347					break;
348				case 4:
349					(void) printf("%u ",
350					    ((uint32_t *)prop)[i]);
351					break;
352				case 8:
353					(void) printf("%lld ",
354					    (u_longlong_t)((int64_t *)prop)[i]);
355					break;
356				}
357			}
358		}
359		(void) printf("\n");
360		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
361	}
362	zap_cursor_fini(&zc);
363}
364
365/*ARGSUSED*/
366static void
367dump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
368{
369	dump_zap_stats(os, object);
370	/* contents are printed elsewhere, properly decoded */
371}
372
373/*ARGSUSED*/
374static void
375dump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size)
376{
377	zap_cursor_t zc;
378	zap_attribute_t attr;
379
380	dump_zap_stats(os, object);
381	(void) printf("\n");
382
383	for (zap_cursor_init(&zc, os, object);
384	    zap_cursor_retrieve(&zc, &attr) == 0;
385	    zap_cursor_advance(&zc)) {
386		(void) printf("\t\t%s = ", attr.za_name);
387		if (attr.za_num_integers == 0) {
388			(void) printf("\n");
389			continue;
390		}
391		(void) printf(" %llx : [%d:%d:%d]\n",
392		    (u_longlong_t)attr.za_first_integer,
393		    (int)ATTR_LENGTH(attr.za_first_integer),
394		    (int)ATTR_BSWAP(attr.za_first_integer),
395		    (int)ATTR_NUM(attr.za_first_integer));
396	}
397	zap_cursor_fini(&zc);
398}
399
400/*ARGSUSED*/
401static void
402dump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size)
403{
404	zap_cursor_t zc;
405	zap_attribute_t attr;
406	uint16_t *layout_attrs;
407	int i;
408
409	dump_zap_stats(os, object);
410	(void) printf("\n");
411
412	for (zap_cursor_init(&zc, os, object);
413	    zap_cursor_retrieve(&zc, &attr) == 0;
414	    zap_cursor_advance(&zc)) {
415		(void) printf("\t\t%s = [", attr.za_name);
416		if (attr.za_num_integers == 0) {
417			(void) printf("\n");
418			continue;
419		}
420
421		VERIFY(attr.za_integer_length == 2);
422		layout_attrs = umem_zalloc(attr.za_num_integers *
423		    attr.za_integer_length, UMEM_NOFAIL);
424
425		VERIFY(zap_lookup(os, object, attr.za_name,
426		    attr.za_integer_length,
427		    attr.za_num_integers, layout_attrs) == 0);
428
429		for (i = 0; i != attr.za_num_integers; i++)
430			(void) printf(" %d ", (int)layout_attrs[i]);
431		(void) printf("]\n");
432		umem_free(layout_attrs,
433		    attr.za_num_integers * attr.za_integer_length);
434	}
435	zap_cursor_fini(&zc);
436}
437
438/*ARGSUSED*/
439static void
440dump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
441{
442	zap_cursor_t zc;
443	zap_attribute_t attr;
444	const char *typenames[] = {
445		/* 0 */ "not specified",
446		/* 1 */ "FIFO",
447		/* 2 */ "Character Device",
448		/* 3 */ "3 (invalid)",
449		/* 4 */ "Directory",
450		/* 5 */ "5 (invalid)",
451		/* 6 */ "Block Device",
452		/* 7 */ "7 (invalid)",
453		/* 8 */ "Regular File",
454		/* 9 */ "9 (invalid)",
455		/* 10 */ "Symbolic Link",
456		/* 11 */ "11 (invalid)",
457		/* 12 */ "Socket",
458		/* 13 */ "Door",
459		/* 14 */ "Event Port",
460		/* 15 */ "15 (invalid)",
461	};
462
463	dump_zap_stats(os, object);
464	(void) printf("\n");
465
466	for (zap_cursor_init(&zc, os, object);
467	    zap_cursor_retrieve(&zc, &attr) == 0;
468	    zap_cursor_advance(&zc)) {
469		(void) printf("\t\t%s = %lld (type: %s)\n",
470		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
471		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
472	}
473	zap_cursor_fini(&zc);
474}
475
476static void
477dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
478{
479	uint64_t alloc, offset, entry;
480	uint8_t mapshift = sm->sm_shift;
481	uint64_t mapstart = sm->sm_start;
482	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
483			    "INVALID", "INVALID", "INVALID", "INVALID" };
484
485	if (smo->smo_object == 0)
486		return;
487
488	/*
489	 * Print out the freelist entries in both encoded and decoded form.
490	 */
491	alloc = 0;
492	for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
493		VERIFY(0 == dmu_read(os, smo->smo_object, offset,
494		    sizeof (entry), &entry, DMU_READ_PREFETCH));
495		if (SM_DEBUG_DECODE(entry)) {
496			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
497			    (u_longlong_t)(offset / sizeof (entry)),
498			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
499			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
500			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
501		} else {
502			(void) printf("\t    [%6llu]    %c  range:"
503			    " %010llx-%010llx  size: %06llx\n",
504			    (u_longlong_t)(offset / sizeof (entry)),
505			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
506			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
507			    mapshift) + mapstart),
508			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
509			    mapshift) + mapstart + (SM_RUN_DECODE(entry) <<
510			    mapshift)),
511			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
512			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
513				alloc += SM_RUN_DECODE(entry) << mapshift;
514			else
515				alloc -= SM_RUN_DECODE(entry) << mapshift;
516		}
517	}
518	if (alloc != smo->smo_alloc) {
519		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
520		    "with space map summary (%llu)\n",
521		    (u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc);
522	}
523}
524
525static void
526dump_metaslab_stats(metaslab_t *msp)
527{
528	char maxbuf[5];
529	space_map_t *sm = &msp->ms_map;
530	avl_tree_t *t = sm->sm_pp_root;
531	int free_pct = sm->sm_space * 100 / sm->sm_size;
532
533	nicenum(space_map_maxsize(sm), maxbuf);
534
535	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
536	    "segments", avl_numnodes(t), "maxsize", maxbuf,
537	    "freepct", free_pct);
538}
539
540static void
541dump_metaslab(metaslab_t *msp)
542{
543	vdev_t *vd = msp->ms_group->mg_vd;
544	spa_t *spa = vd->vdev_spa;
545	space_map_t *sm = &msp->ms_map;
546	space_map_obj_t *smo = &msp->ms_smo;
547	char freebuf[5];
548
549	nicenum(sm->sm_size - smo->smo_alloc, freebuf);
550
551	(void) printf(
552	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
553	    (u_longlong_t)(sm->sm_start / sm->sm_size),
554	    (u_longlong_t)sm->sm_start, (u_longlong_t)smo->smo_object, freebuf);
555
556	if (dump_opt['m'] > 1 && !dump_opt['L']) {
557		mutex_enter(&msp->ms_lock);
558		space_map_load_wait(sm);
559		if (!sm->sm_loaded)
560			VERIFY(space_map_load(sm, zfs_metaslab_ops,
561			    SM_FREE, smo, spa->spa_meta_objset) == 0);
562		dump_metaslab_stats(msp);
563		space_map_unload(sm);
564		mutex_exit(&msp->ms_lock);
565	}
566
567	if (dump_opt['d'] > 5 || dump_opt['m'] > 2) {
568		ASSERT(sm->sm_size == (1ULL << vd->vdev_ms_shift));
569
570		mutex_enter(&msp->ms_lock);
571		dump_spacemap(spa->spa_meta_objset, smo, sm);
572		mutex_exit(&msp->ms_lock);
573	}
574}
575
576static void
577print_vdev_metaslab_header(vdev_t *vd)
578{
579	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
580	    (u_longlong_t)vd->vdev_id,
581	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
582	    "offset", "spacemap", "free");
583	(void) printf("\t%15s   %19s   %15s   %10s\n",
584	    "---------------", "-------------------",
585	    "---------------", "-------------");
586}
587
588static void
589dump_metaslabs(spa_t *spa)
590{
591	vdev_t *vd, *rvd = spa->spa_root_vdev;
592	uint64_t m, c = 0, children = rvd->vdev_children;
593
594	(void) printf("\nMetaslabs:\n");
595
596	if (!dump_opt['d'] && zopt_objects > 0) {
597		c = zopt_object[0];
598
599		if (c >= children)
600			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
601
602		if (zopt_objects > 1) {
603			vd = rvd->vdev_child[c];
604			print_vdev_metaslab_header(vd);
605
606			for (m = 1; m < zopt_objects; m++) {
607				if (zopt_object[m] < vd->vdev_ms_count)
608					dump_metaslab(
609					    vd->vdev_ms[zopt_object[m]]);
610				else
611					(void) fprintf(stderr, "bad metaslab "
612					    "number %llu\n",
613					    (u_longlong_t)zopt_object[m]);
614			}
615			(void) printf("\n");
616			return;
617		}
618		children = c + 1;
619	}
620	for (; c < children; c++) {
621		vd = rvd->vdev_child[c];
622		print_vdev_metaslab_header(vd);
623
624		for (m = 0; m < vd->vdev_ms_count; m++)
625			dump_metaslab(vd->vdev_ms[m]);
626		(void) printf("\n");
627	}
628}
629
630static void
631dump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
632{
633	const ddt_phys_t *ddp = dde->dde_phys;
634	const ddt_key_t *ddk = &dde->dde_key;
635	char *types[4] = { "ditto", "single", "double", "triple" };
636	char blkbuf[BP_SPRINTF_LEN];
637	blkptr_t blk;
638
639	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
640		if (ddp->ddp_phys_birth == 0)
641			continue;
642		ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
643		sprintf_blkptr(blkbuf, &blk);
644		(void) printf("index %llx refcnt %llu %s %s\n",
645		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
646		    types[p], blkbuf);
647	}
648}
649
650static void
651dump_dedup_ratio(const ddt_stat_t *dds)
652{
653	double rL, rP, rD, D, dedup, compress, copies;
654
655	if (dds->dds_blocks == 0)
656		return;
657
658	rL = (double)dds->dds_ref_lsize;
659	rP = (double)dds->dds_ref_psize;
660	rD = (double)dds->dds_ref_dsize;
661	D = (double)dds->dds_dsize;
662
663	dedup = rD / D;
664	compress = rL / rP;
665	copies = rD / rP;
666
667	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
668	    "dedup * compress / copies = %.2f\n\n",
669	    dedup, compress, copies, dedup * compress / copies);
670}
671
672static void
673dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
674{
675	char name[DDT_NAMELEN];
676	ddt_entry_t dde;
677	uint64_t walk = 0;
678	dmu_object_info_t doi;
679	uint64_t count, dspace, mspace;
680	int error;
681
682	error = ddt_object_info(ddt, type, class, &doi);
683
684	if (error == ENOENT)
685		return;
686	ASSERT(error == 0);
687
688	count = ddt_object_count(ddt, type, class);
689	dspace = doi.doi_physical_blocks_512 << 9;
690	mspace = doi.doi_fill_count * doi.doi_data_block_size;
691
692	ASSERT(count != 0);	/* we should have destroyed it */
693
694	ddt_object_name(ddt, type, class, name);
695
696	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
697	    name,
698	    (u_longlong_t)count,
699	    (u_longlong_t)(dspace / count),
700	    (u_longlong_t)(mspace / count));
701
702	if (dump_opt['D'] < 3)
703		return;
704
705	zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]);
706
707	if (dump_opt['D'] < 4)
708		return;
709
710	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
711		return;
712
713	(void) printf("%s contents:\n\n", name);
714
715	while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0)
716		dump_dde(ddt, &dde, walk);
717
718	ASSERT(error == ENOENT);
719
720	(void) printf("\n");
721}
722
723static void
724dump_all_ddts(spa_t *spa)
725{
726	ddt_histogram_t ddh_total = { 0 };
727	ddt_stat_t dds_total = { 0 };
728
729	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
730		ddt_t *ddt = spa->spa_ddt[c];
731		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
732			for (enum ddt_class class = 0; class < DDT_CLASSES;
733			    class++) {
734				dump_ddt(ddt, type, class);
735			}
736		}
737	}
738
739	ddt_get_dedup_stats(spa, &dds_total);
740
741	if (dds_total.dds_blocks == 0) {
742		(void) printf("All DDTs are empty\n");
743		return;
744	}
745
746	(void) printf("\n");
747
748	if (dump_opt['D'] > 1) {
749		(void) printf("DDT histogram (aggregated over all DDTs):\n");
750		ddt_get_dedup_histogram(spa, &ddh_total);
751		zpool_dump_ddt(&dds_total, &ddh_total);
752	}
753
754	dump_dedup_ratio(&dds_total);
755}
756
757static void
758dump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size)
759{
760	char *prefix = (void *)sm;
761
762	(void) printf("%s [%llu,%llu) length %llu\n",
763	    prefix,
764	    (u_longlong_t)start,
765	    (u_longlong_t)(start + size),
766	    (u_longlong_t)(size));
767}
768
769static void
770dump_dtl(vdev_t *vd, int indent)
771{
772	spa_t *spa = vd->vdev_spa;
773	boolean_t required;
774	char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" };
775	char prefix[256];
776
777	spa_vdev_state_enter(spa, SCL_NONE);
778	required = vdev_dtl_required(vd);
779	(void) spa_vdev_state_exit(spa, NULL, 0);
780
781	if (indent == 0)
782		(void) printf("\nDirty time logs:\n\n");
783
784	(void) printf("\t%*s%s [%s]\n", indent, "",
785	    vd->vdev_path ? vd->vdev_path :
786	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
787	    required ? "DTL-required" : "DTL-expendable");
788
789	for (int t = 0; t < DTL_TYPES; t++) {
790		space_map_t *sm = &vd->vdev_dtl[t];
791		if (sm->sm_space == 0)
792			continue;
793		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
794		    indent + 2, "", name[t]);
795		mutex_enter(sm->sm_lock);
796		space_map_walk(sm, dump_dtl_seg, (void *)prefix);
797		mutex_exit(sm->sm_lock);
798		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
799			dump_spacemap(spa->spa_meta_objset,
800			    &vd->vdev_dtl_smo, sm);
801	}
802
803	for (int c = 0; c < vd->vdev_children; c++)
804		dump_dtl(vd->vdev_child[c], indent + 4);
805}
806
807static void
808dump_history(spa_t *spa)
809{
810	nvlist_t **events = NULL;
811	char buf[SPA_MAXBLOCKSIZE];
812	uint64_t resid, len, off = 0;
813	uint_t num = 0;
814	int error;
815	time_t tsec;
816	struct tm t;
817	char tbuf[30];
818	char internalstr[MAXPATHLEN];
819
820	do {
821		len = sizeof (buf);
822
823		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
824			(void) fprintf(stderr, "Unable to read history: "
825			    "error %d\n", error);
826			return;
827		}
828
829		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
830			break;
831
832		off -= resid;
833	} while (len != 0);
834
835	(void) printf("\nHistory:\n");
836	for (int i = 0; i < num; i++) {
837		uint64_t time, txg, ievent;
838		char *cmd, *intstr;
839
840		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
841		    &time) != 0)
842			continue;
843		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
844		    &cmd) != 0) {
845			if (nvlist_lookup_uint64(events[i],
846			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
847				continue;
848			verify(nvlist_lookup_uint64(events[i],
849			    ZPOOL_HIST_TXG, &txg) == 0);
850			verify(nvlist_lookup_string(events[i],
851			    ZPOOL_HIST_INT_STR, &intstr) == 0);
852			if (ievent >= LOG_END)
853				continue;
854
855			(void) snprintf(internalstr,
856			    sizeof (internalstr),
857			    "[internal %s txg:%lld] %s",
858			    hist_event_table[ievent], txg,
859			    intstr);
860			cmd = internalstr;
861		}
862		tsec = time;
863		(void) localtime_r(&tsec, &t);
864		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
865		(void) printf("%s %s\n", tbuf, cmd);
866	}
867}
868
869/*ARGSUSED*/
870static void
871dump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
872{
873}
874
875static uint64_t
876blkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp, const zbookmark_t *zb)
877{
878	if (dnp == NULL) {
879		ASSERT(zb->zb_level < 0);
880		if (zb->zb_object == 0)
881			return (zb->zb_blkid);
882		return (zb->zb_blkid * BP_GET_LSIZE(bp));
883	}
884
885	ASSERT(zb->zb_level >= 0);
886
887	return ((zb->zb_blkid <<
888	    (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
889	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
890}
891
892static void
893sprintf_blkptr_compact(char *blkbuf, blkptr_t *bp)
894{
895	dva_t *dva = bp->blk_dva;
896	int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
897
898	if (dump_opt['b'] >= 5) {
899		sprintf_blkptr(blkbuf, bp);
900		return;
901	}
902
903	blkbuf[0] = '\0';
904
905	for (int i = 0; i < ndvas; i++)
906		(void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ",
907		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
908		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
909		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
910
911	(void) sprintf(blkbuf + strlen(blkbuf),
912	    "%llxL/%llxP F=%llu B=%llu/%llu",
913	    (u_longlong_t)BP_GET_LSIZE(bp),
914	    (u_longlong_t)BP_GET_PSIZE(bp),
915	    (u_longlong_t)bp->blk_fill,
916	    (u_longlong_t)bp->blk_birth,
917	    (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
918}
919
920static void
921print_indirect(blkptr_t *bp, const zbookmark_t *zb,
922    const dnode_phys_t *dnp)
923{
924	char blkbuf[BP_SPRINTF_LEN];
925	int l;
926
927	ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
928	ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
929
930	(void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
931
932	ASSERT(zb->zb_level >= 0);
933
934	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
935		if (l == zb->zb_level) {
936			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
937		} else {
938			(void) printf(" ");
939		}
940	}
941
942	sprintf_blkptr_compact(blkbuf, bp);
943	(void) printf("%s\n", blkbuf);
944}
945
946static int
947visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
948    blkptr_t *bp, const zbookmark_t *zb)
949{
950	int err = 0;
951
952	if (bp->blk_birth == 0)
953		return (0);
954
955	print_indirect(bp, zb, dnp);
956
957	if (BP_GET_LEVEL(bp) > 0) {
958		uint32_t flags = ARC_WAIT;
959		int i;
960		blkptr_t *cbp;
961		int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
962		arc_buf_t *buf;
963		uint64_t fill = 0;
964
965		err = arc_read_nolock(NULL, spa, bp, arc_getbuf_func, &buf,
966		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
967		if (err)
968			return (err);
969
970		/* recursively visit blocks below this */
971		cbp = buf->b_data;
972		for (i = 0; i < epb; i++, cbp++) {
973			zbookmark_t czb;
974
975			SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
976			    zb->zb_level - 1,
977			    zb->zb_blkid * epb + i);
978			err = visit_indirect(spa, dnp, cbp, &czb);
979			if (err)
980				break;
981			fill += cbp->blk_fill;
982		}
983		if (!err)
984			ASSERT3U(fill, ==, bp->blk_fill);
985		(void) arc_buf_remove_ref(buf, &buf);
986	}
987
988	return (err);
989}
990
991/*ARGSUSED*/
992static void
993dump_indirect(dnode_t *dn)
994{
995	dnode_phys_t *dnp = dn->dn_phys;
996	int j;
997	zbookmark_t czb;
998
999	(void) printf("Indirect blocks:\n");
1000
1001	SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset),
1002	    dn->dn_object, dnp->dn_nlevels - 1, 0);
1003	for (j = 0; j < dnp->dn_nblkptr; j++) {
1004		czb.zb_blkid = j;
1005		(void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp,
1006		    &dnp->dn_blkptr[j], &czb);
1007	}
1008
1009	(void) printf("\n");
1010}
1011
1012/*ARGSUSED*/
1013static void
1014dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
1015{
1016	dsl_dir_phys_t *dd = data;
1017	time_t crtime;
1018	char nice[6];
1019
1020	if (dd == NULL)
1021		return;
1022
1023	ASSERT3U(size, >=, sizeof (dsl_dir_phys_t));
1024
1025	crtime = dd->dd_creation_time;
1026	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1027	(void) printf("\t\thead_dataset_obj = %llu\n",
1028	    (u_longlong_t)dd->dd_head_dataset_obj);
1029	(void) printf("\t\tparent_dir_obj = %llu\n",
1030	    (u_longlong_t)dd->dd_parent_obj);
1031	(void) printf("\t\torigin_obj = %llu\n",
1032	    (u_longlong_t)dd->dd_origin_obj);
1033	(void) printf("\t\tchild_dir_zapobj = %llu\n",
1034	    (u_longlong_t)dd->dd_child_dir_zapobj);
1035	nicenum(dd->dd_used_bytes, nice);
1036	(void) printf("\t\tused_bytes = %s\n", nice);
1037	nicenum(dd->dd_compressed_bytes, nice);
1038	(void) printf("\t\tcompressed_bytes = %s\n", nice);
1039	nicenum(dd->dd_uncompressed_bytes, nice);
1040	(void) printf("\t\tuncompressed_bytes = %s\n", nice);
1041	nicenum(dd->dd_quota, nice);
1042	(void) printf("\t\tquota = %s\n", nice);
1043	nicenum(dd->dd_reserved, nice);
1044	(void) printf("\t\treserved = %s\n", nice);
1045	(void) printf("\t\tprops_zapobj = %llu\n",
1046	    (u_longlong_t)dd->dd_props_zapobj);
1047	(void) printf("\t\tdeleg_zapobj = %llu\n",
1048	    (u_longlong_t)dd->dd_deleg_zapobj);
1049	(void) printf("\t\tflags = %llx\n",
1050	    (u_longlong_t)dd->dd_flags);
1051
1052#define	DO(which) \
1053	nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
1054	(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
1055	DO(HEAD);
1056	DO(SNAP);
1057	DO(CHILD);
1058	DO(CHILD_RSRV);
1059	DO(REFRSRV);
1060#undef DO
1061}
1062
1063/*ARGSUSED*/
1064static void
1065dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
1066{
1067	dsl_dataset_phys_t *ds = data;
1068	time_t crtime;
1069	char used[6], compressed[6], uncompressed[6], unique[6];
1070	char blkbuf[BP_SPRINTF_LEN];
1071
1072	if (ds == NULL)
1073		return;
1074
1075	ASSERT(size == sizeof (*ds));
1076	crtime = ds->ds_creation_time;
1077	nicenum(ds->ds_used_bytes, used);
1078	nicenum(ds->ds_compressed_bytes, compressed);
1079	nicenum(ds->ds_uncompressed_bytes, uncompressed);
1080	nicenum(ds->ds_unique_bytes, unique);
1081	sprintf_blkptr(blkbuf, &ds->ds_bp);
1082
1083	(void) printf("\t\tdir_obj = %llu\n",
1084	    (u_longlong_t)ds->ds_dir_obj);
1085	(void) printf("\t\tprev_snap_obj = %llu\n",
1086	    (u_longlong_t)ds->ds_prev_snap_obj);
1087	(void) printf("\t\tprev_snap_txg = %llu\n",
1088	    (u_longlong_t)ds->ds_prev_snap_txg);
1089	(void) printf("\t\tnext_snap_obj = %llu\n",
1090	    (u_longlong_t)ds->ds_next_snap_obj);
1091	(void) printf("\t\tsnapnames_zapobj = %llu\n",
1092	    (u_longlong_t)ds->ds_snapnames_zapobj);
1093	(void) printf("\t\tnum_children = %llu\n",
1094	    (u_longlong_t)ds->ds_num_children);
1095	(void) printf("\t\tuserrefs_obj = %llu\n",
1096	    (u_longlong_t)ds->ds_userrefs_obj);
1097	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
1098	(void) printf("\t\tcreation_txg = %llu\n",
1099	    (u_longlong_t)ds->ds_creation_txg);
1100	(void) printf("\t\tdeadlist_obj = %llu\n",
1101	    (u_longlong_t)ds->ds_deadlist_obj);
1102	(void) printf("\t\tused_bytes = %s\n", used);
1103	(void) printf("\t\tcompressed_bytes = %s\n", compressed);
1104	(void) printf("\t\tuncompressed_bytes = %s\n", uncompressed);
1105	(void) printf("\t\tunique = %s\n", unique);
1106	(void) printf("\t\tfsid_guid = %llu\n",
1107	    (u_longlong_t)ds->ds_fsid_guid);
1108	(void) printf("\t\tguid = %llu\n",
1109	    (u_longlong_t)ds->ds_guid);
1110	(void) printf("\t\tflags = %llx\n",
1111	    (u_longlong_t)ds->ds_flags);
1112	(void) printf("\t\tnext_clones_obj = %llu\n",
1113	    (u_longlong_t)ds->ds_next_clones_obj);
1114	(void) printf("\t\tprops_obj = %llu\n",
1115	    (u_longlong_t)ds->ds_props_obj);
1116	(void) printf("\t\tbp = %s\n", blkbuf);
1117}
1118
1119static void
1120dump_bplist(objset_t *mos, uint64_t object, char *name)
1121{
1122	bplist_t bpl = { 0 };
1123	blkptr_t blk, *bp = &blk;
1124	uint64_t itor = 0;
1125	char bytes[6];
1126	char comp[6];
1127	char uncomp[6];
1128
1129	if (dump_opt['d'] < 3)
1130		return;
1131
1132	bplist_init(&bpl);
1133	VERIFY(0 == bplist_open(&bpl, mos, object));
1134	if (bplist_empty(&bpl)) {
1135		bplist_close(&bpl);
1136		bplist_fini(&bpl);
1137		return;
1138	}
1139
1140	nicenum(bpl.bpl_phys->bpl_bytes, bytes);
1141	if (bpl.bpl_dbuf->db_size == sizeof (bplist_phys_t)) {
1142		nicenum(bpl.bpl_phys->bpl_comp, comp);
1143		nicenum(bpl.bpl_phys->bpl_uncomp, uncomp);
1144		(void) printf("\n    %s: %llu entries, %s (%s/%s comp)\n",
1145		    name, (u_longlong_t)bpl.bpl_phys->bpl_entries,
1146		    bytes, comp, uncomp);
1147	} else {
1148		(void) printf("\n    %s: %llu entries, %s\n",
1149		    name, (u_longlong_t)bpl.bpl_phys->bpl_entries, bytes);
1150	}
1151
1152	if (dump_opt['d'] < 5) {
1153		bplist_close(&bpl);
1154		bplist_fini(&bpl);
1155		return;
1156	}
1157
1158	(void) printf("\n");
1159
1160	while (bplist_iterate(&bpl, &itor, bp) == 0) {
1161		char blkbuf[BP_SPRINTF_LEN];
1162
1163		ASSERT(bp->blk_birth != 0);
1164		sprintf_blkptr_compact(blkbuf, bp);
1165		(void) printf("\tItem %3llu: %s\n",
1166		    (u_longlong_t)itor - 1, blkbuf);
1167	}
1168
1169	bplist_close(&bpl);
1170	bplist_fini(&bpl);
1171}
1172
1173static avl_tree_t idx_tree;
1174static avl_tree_t domain_tree;
1175static boolean_t fuid_table_loaded;
1176static boolean_t sa_loaded;
1177sa_attr_type_t *sa_attr_table;
1178
1179static void
1180fuid_table_destroy()
1181{
1182	if (fuid_table_loaded) {
1183		zfs_fuid_table_destroy(&idx_tree, &domain_tree);
1184		fuid_table_loaded = B_FALSE;
1185	}
1186}
1187
1188/*
1189 * print uid or gid information.
1190 * For normal POSIX id just the id is printed in decimal format.
1191 * For CIFS files with FUID the fuid is printed in hex followed by
1192 * the doman-rid string.
1193 */
1194static void
1195print_idstr(uint64_t id, const char *id_type)
1196{
1197	if (FUID_INDEX(id)) {
1198		char *domain;
1199
1200		domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id));
1201		(void) printf("\t%s     %llx [%s-%d]\n", id_type,
1202		    (u_longlong_t)id, domain, (int)FUID_RID(id));
1203	} else {
1204		(void) printf("\t%s     %llu\n", id_type, (u_longlong_t)id);
1205	}
1206
1207}
1208
1209static void
1210dump_uidgid(objset_t *os, uint64_t uid, uint64_t gid)
1211{
1212	uint32_t uid_idx, gid_idx;
1213
1214	uid_idx = FUID_INDEX(uid);
1215	gid_idx = FUID_INDEX(gid);
1216
1217	/* Load domain table, if not already loaded */
1218	if (!fuid_table_loaded && (uid_idx || gid_idx)) {
1219		uint64_t fuid_obj;
1220
1221		/* first find the fuid object.  It lives in the master node */
1222		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
1223		    8, 1, &fuid_obj) == 0);
1224		zfs_fuid_avl_tree_create(&idx_tree, &domain_tree);
1225		(void) zfs_fuid_table_load(os, fuid_obj,
1226		    &idx_tree, &domain_tree);
1227		fuid_table_loaded = B_TRUE;
1228	}
1229
1230	print_idstr(uid, "uid");
1231	print_idstr(gid, "gid");
1232}
1233
1234/*ARGSUSED*/
1235static void
1236dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
1237{
1238	char path[MAXPATHLEN * 2];	/* allow for xattr and failure prefix */
1239	sa_handle_t *hdl;
1240	uint64_t xattr, rdev, gen;
1241	uint64_t uid, gid, mode, fsize, parent, links;
1242	uint64_t pflags;
1243	uint64_t acctm[2], modtm[2], chgtm[2], crtm[2];
1244	time_t z_crtime, z_atime, z_mtime, z_ctime;
1245	sa_bulk_attr_t bulk[12];
1246	int idx = 0;
1247	int error;
1248
1249	if (!sa_loaded) {
1250		uint64_t sa_attrs = 0;
1251		uint64_t version;
1252
1253		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
1254		    8, 1, &version) == 0);
1255		if (version >= ZPL_VERSION_SA) {
1256			VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
1257			    8, 1, &sa_attrs) == 0);
1258		}
1259		sa_attr_table = sa_setup(os, sa_attrs,
1260		    zfs_attr_table, ZPL_END);
1261		sa_loaded = B_TRUE;
1262	}
1263
1264	if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
1265		(void) printf("Failed to get handle for SA znode\n");
1266		return;
1267	}
1268
1269	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_UID], NULL, &uid, 8);
1270	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GID], NULL, &gid, 8);
1271	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_LINKS], NULL,
1272	    &links, 8);
1273	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GEN], NULL, &gen, 8);
1274	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MODE], NULL,
1275	    &mode, 8);
1276	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_PARENT],
1277	    NULL, &parent, 8);
1278	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_SIZE], NULL,
1279	    &fsize, 8);
1280	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_ATIME], NULL,
1281	    acctm, 16);
1282	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MTIME], NULL,
1283	    modtm, 16);
1284	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CRTIME], NULL,
1285	    crtm, 16);
1286	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CTIME], NULL,
1287	    chgtm, 16);
1288	SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_FLAGS], NULL,
1289	    &pflags, 8);
1290
1291	if (sa_bulk_lookup(hdl, bulk, idx)) {
1292		(void) sa_handle_destroy(hdl);
1293		return;
1294	}
1295
1296	error = zfs_obj_to_path(os, object, path, sizeof (path));
1297	if (error != 0) {
1298		(void) snprintf(path, sizeof (path), "\?\?\?<object#%llu>",
1299		    (u_longlong_t)object);
1300	}
1301	if (dump_opt['d'] < 3) {
1302		(void) printf("\t%s\n", path);
1303		(void) sa_handle_destroy(hdl);
1304		return;
1305	}
1306
1307	z_crtime = (time_t)crtm[0];
1308	z_atime = (time_t)acctm[0];
1309	z_mtime = (time_t)modtm[0];
1310	z_ctime = (time_t)chgtm[0];
1311
1312	(void) printf("\tpath	%s\n", path);
1313	dump_uidgid(os, uid, gid);
1314	(void) printf("\tatime	%s", ctime(&z_atime));
1315	(void) printf("\tmtime	%s", ctime(&z_mtime));
1316	(void) printf("\tctime	%s", ctime(&z_ctime));
1317	(void) printf("\tcrtime	%s", ctime(&z_crtime));
1318	(void) printf("\tgen	%llu\n", (u_longlong_t)gen);
1319	(void) printf("\tmode	%llo\n", (u_longlong_t)mode);
1320	(void) printf("\tsize	%llu\n", (u_longlong_t)fsize);
1321	(void) printf("\tparent	%llu\n", (u_longlong_t)parent);
1322	(void) printf("\tlinks	%llu\n", (u_longlong_t)links);
1323	(void) printf("\tpflags	%llx\n", (u_longlong_t)pflags);
1324	if (sa_lookup(hdl, sa_attr_table[ZPL_XATTR], &xattr,
1325	    sizeof (uint64_t)) == 0)
1326		(void) printf("\txattr	%llu\n", (u_longlong_t)xattr);
1327	if (sa_lookup(hdl, sa_attr_table[ZPL_RDEV], &rdev,
1328	    sizeof (uint64_t)) == 0)
1329		(void) printf("\trdev	0x%016llx\n", (u_longlong_t)rdev);
1330	sa_handle_destroy(hdl);
1331}
1332
1333/*ARGSUSED*/
1334static void
1335dump_acl(objset_t *os, uint64_t object, void *data, size_t size)
1336{
1337}
1338
1339/*ARGSUSED*/
1340static void
1341dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
1342{
1343}
1344
1345static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
1346	dump_none,		/* unallocated			*/
1347	dump_zap,		/* object directory		*/
1348	dump_uint64,		/* object array			*/
1349	dump_none,		/* packed nvlist		*/
1350	dump_packed_nvlist,	/* packed nvlist size		*/
1351	dump_none,		/* bplist			*/
1352	dump_none,		/* bplist header		*/
1353	dump_none,		/* SPA space map header		*/
1354	dump_none,		/* SPA space map		*/
1355	dump_none,		/* ZIL intent log		*/
1356	dump_dnode,		/* DMU dnode			*/
1357	dump_dmu_objset,	/* DMU objset			*/
1358	dump_dsl_dir,		/* DSL directory		*/
1359	dump_zap,		/* DSL directory child map	*/
1360	dump_zap,		/* DSL dataset snap map		*/
1361	dump_zap,		/* DSL props			*/
1362	dump_dsl_dataset,	/* DSL dataset			*/
1363	dump_znode,		/* ZFS znode			*/
1364	dump_acl,		/* ZFS V0 ACL			*/
1365	dump_uint8,		/* ZFS plain file		*/
1366	dump_zpldir,		/* ZFS directory		*/
1367	dump_zap,		/* ZFS master node		*/
1368	dump_zap,		/* ZFS delete queue		*/
1369	dump_uint8,		/* zvol object			*/
1370	dump_zap,		/* zvol prop			*/
1371	dump_uint8,		/* other uint8[]		*/
1372	dump_uint64,		/* other uint64[]		*/
1373	dump_zap,		/* other ZAP			*/
1374	dump_zap,		/* persistent error log		*/
1375	dump_uint8,		/* SPA history			*/
1376	dump_uint64,		/* SPA history offsets		*/
1377	dump_zap,		/* Pool properties		*/
1378	dump_zap,		/* DSL permissions		*/
1379	dump_acl,		/* ZFS ACL			*/
1380	dump_uint8,		/* ZFS SYSACL			*/
1381	dump_none,		/* FUID nvlist			*/
1382	dump_packed_nvlist,	/* FUID nvlist size		*/
1383	dump_zap,		/* DSL dataset next clones	*/
1384	dump_zap,		/* DSL scrub queue		*/
1385	dump_zap,		/* ZFS user/group used		*/
1386	dump_zap,		/* ZFS user/group quota		*/
1387	dump_zap,		/* snapshot refcount tags	*/
1388	dump_ddt_zap,		/* DDT ZAP object		*/
1389	dump_zap,		/* DDT statistics		*/
1390	dump_znode,		/* SA object			*/
1391	dump_zap,		/* SA Master Node		*/
1392	dump_sa_attrs,		/* SA attribute registration	*/
1393	dump_sa_layouts,	/* SA attribute layouts		*/
1394	dump_unknown,		/* Unknown type, must be last	*/
1395};
1396
1397static void
1398dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
1399{
1400	dmu_buf_t *db = NULL;
1401	dmu_object_info_t doi;
1402	dnode_t *dn;
1403	void *bonus = NULL;
1404	size_t bsize = 0;
1405	char iblk[6], dblk[6], lsize[6], asize[6], bonus_size[6], fill[7];
1406	char aux[50];
1407	int error;
1408
1409	if (*print_header) {
1410		(void) printf("\n%10s  %3s  %5s  %5s  %5s  %5s  %6s  %s\n",
1411		    "Object", "lvl", "iblk", "dblk", "dsize", "lsize",
1412		    "%full", "type");
1413		*print_header = 0;
1414	}
1415
1416	if (object == 0) {
1417		dn = os->os_meta_dnode;
1418	} else {
1419		error = dmu_bonus_hold(os, object, FTAG, &db);
1420		if (error)
1421			fatal("dmu_bonus_hold(%llu) failed, errno %u",
1422			    object, error);
1423		bonus = db->db_data;
1424		bsize = db->db_size;
1425		dn = ((dmu_buf_impl_t *)db)->db_dnode;
1426	}
1427	dmu_object_info_from_dnode(dn, &doi);
1428
1429	nicenum(doi.doi_metadata_block_size, iblk);
1430	nicenum(doi.doi_data_block_size, dblk);
1431	nicenum(doi.doi_max_offset, lsize);
1432	nicenum(doi.doi_physical_blocks_512 << 9, asize);
1433	nicenum(doi.doi_bonus_size, bonus_size);
1434	(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
1435	    doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
1436	    doi.doi_max_offset);
1437
1438	aux[0] = '\0';
1439
1440	if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) {
1441		(void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)",
1442		    ZDB_CHECKSUM_NAME(doi.doi_checksum));
1443	}
1444
1445	if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) {
1446		(void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)",
1447		    ZDB_COMPRESS_NAME(doi.doi_compress));
1448	}
1449
1450	(void) printf("%10lld  %3u  %5s  %5s  %5s  %5s  %6s  %s%s\n",
1451	    (u_longlong_t)object, doi.doi_indirection, iblk, dblk,
1452	    asize, lsize, fill, ZDB_OT_NAME(doi.doi_type), aux);
1453
1454	if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) {
1455		(void) printf("%10s  %3s  %5s  %5s  %5s  %5s  %6s  %s\n",
1456		    "", "", "", "", "", bonus_size, "bonus",
1457		    ZDB_OT_NAME(doi.doi_bonus_type));
1458	}
1459
1460	if (verbosity >= 4) {
1461		(void) printf("\tdnode flags: %s%s%s\n",
1462		    (dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) ?
1463		    "USED_BYTES " : "",
1464		    (dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED) ?
1465		    "USERUSED_ACCOUNTED " : "",
1466		    (dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR) ?
1467		    "SPILL_BLKPTR" : "");
1468		(void) printf("\tdnode maxblkid: %llu\n",
1469		    (longlong_t)dn->dn_phys->dn_maxblkid);
1470
1471		object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object,
1472		    bonus, bsize);
1473		object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
1474		*print_header = 1;
1475	}
1476
1477	if (verbosity >= 5)
1478		dump_indirect(dn);
1479
1480	if (verbosity >= 5) {
1481		/*
1482		 * Report the list of segments that comprise the object.
1483		 */
1484		uint64_t start = 0;
1485		uint64_t end;
1486		uint64_t blkfill = 1;
1487		int minlvl = 1;
1488
1489		if (dn->dn_type == DMU_OT_DNODE) {
1490			minlvl = 0;
1491			blkfill = DNODES_PER_BLOCK;
1492		}
1493
1494		for (;;) {
1495			char segsize[6];
1496			error = dnode_next_offset(dn,
1497			    0, &start, minlvl, blkfill, 0);
1498			if (error)
1499				break;
1500			end = start;
1501			error = dnode_next_offset(dn,
1502			    DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
1503			nicenum(end - start, segsize);
1504			(void) printf("\t\tsegment [%016llx, %016llx)"
1505			    " size %5s\n", (u_longlong_t)start,
1506			    (u_longlong_t)end, segsize);
1507			if (error)
1508				break;
1509			start = end;
1510		}
1511	}
1512
1513	if (db != NULL)
1514		dmu_buf_rele(db, FTAG);
1515}
1516
1517static char *objset_types[DMU_OST_NUMTYPES] = {
1518	"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
1519
1520static void
1521dump_dir(objset_t *os)
1522{
1523	dmu_objset_stats_t dds;
1524	uint64_t object, object_count;
1525	uint64_t refdbytes, usedobjs, scratch;
1526	char numbuf[8];
1527	char blkbuf[BP_SPRINTF_LEN + 20];
1528	char osname[MAXNAMELEN];
1529	char *type = "UNKNOWN";
1530	int verbosity = dump_opt['d'];
1531	int print_header = 1;
1532	int i, error;
1533
1534	dmu_objset_fast_stat(os, &dds);
1535
1536	if (dds.dds_type < DMU_OST_NUMTYPES)
1537		type = objset_types[dds.dds_type];
1538
1539	if (dds.dds_type == DMU_OST_META) {
1540		dds.dds_creation_txg = TXG_INITIAL;
1541		usedobjs = os->os_rootbp->blk_fill;
1542		refdbytes = os->os_spa->spa_dsl_pool->
1543		    dp_mos_dir->dd_phys->dd_used_bytes;
1544	} else {
1545		dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch);
1546	}
1547
1548	ASSERT3U(usedobjs, ==, os->os_rootbp->blk_fill);
1549
1550	nicenum(refdbytes, numbuf);
1551
1552	if (verbosity >= 4) {
1553		(void) sprintf(blkbuf, ", rootbp ");
1554		(void) sprintf_blkptr(blkbuf + strlen(blkbuf), os->os_rootbp);
1555	} else {
1556		blkbuf[0] = '\0';
1557	}
1558
1559	dmu_objset_name(os, osname);
1560
1561	(void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, "
1562	    "%s, %llu objects%s\n",
1563	    osname, type, (u_longlong_t)dmu_objset_id(os),
1564	    (u_longlong_t)dds.dds_creation_txg,
1565	    numbuf, (u_longlong_t)usedobjs, blkbuf);
1566
1567	if (zopt_objects != 0) {
1568		for (i = 0; i < zopt_objects; i++)
1569			dump_object(os, zopt_object[i], verbosity,
1570			    &print_header);
1571		(void) printf("\n");
1572		return;
1573	}
1574
1575	if (dump_opt['i'] != 0 || verbosity >= 2)
1576		dump_intent_log(dmu_objset_zil(os));
1577
1578	if (dmu_objset_ds(os) != NULL)
1579		dump_bplist(dmu_objset_pool(os)->dp_meta_objset,
1580		    dmu_objset_ds(os)->ds_phys->ds_deadlist_obj, "Deadlist");
1581
1582	if (verbosity < 2)
1583		return;
1584
1585	if (os->os_rootbp->blk_birth == 0)
1586		return;
1587
1588	dump_object(os, 0, verbosity, &print_header);
1589	object_count = 0;
1590	if (os->os_userused_dnode &&
1591	    os->os_userused_dnode->dn_type != 0) {
1592		dump_object(os, DMU_USERUSED_OBJECT, verbosity, &print_header);
1593		dump_object(os, DMU_GROUPUSED_OBJECT, verbosity, &print_header);
1594	}
1595
1596	object = 0;
1597	while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) {
1598		dump_object(os, object, verbosity, &print_header);
1599		object_count++;
1600	}
1601
1602	ASSERT3U(object_count, ==, usedobjs);
1603
1604	(void) printf("\n");
1605
1606	if (error != ESRCH) {
1607		(void) fprintf(stderr, "dmu_object_next() = %d\n", error);
1608		abort();
1609	}
1610}
1611
1612static void
1613dump_uberblock(uberblock_t *ub, const char *header, const char *footer)
1614{
1615	time_t timestamp = ub->ub_timestamp;
1616
1617	(void) printf(header ? header : "");
1618	(void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic);
1619	(void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version);
1620	(void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg);
1621	(void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum);
1622	(void) printf("\ttimestamp = %llu UTC = %s",
1623	    (u_longlong_t)ub->ub_timestamp, asctime(localtime(&timestamp)));
1624	if (dump_opt['u'] >= 3) {
1625		char blkbuf[BP_SPRINTF_LEN];
1626		sprintf_blkptr(blkbuf, &ub->ub_rootbp);
1627		(void) printf("\trootbp = %s\n", blkbuf);
1628	}
1629	(void) printf(footer ? footer : "");
1630}
1631
1632static void
1633dump_config(spa_t *spa)
1634{
1635	dmu_buf_t *db;
1636	size_t nvsize = 0;
1637	int error = 0;
1638
1639
1640	error = dmu_bonus_hold(spa->spa_meta_objset,
1641	    spa->spa_config_object, FTAG, &db);
1642
1643	if (error == 0) {
1644		nvsize = *(uint64_t *)db->db_data;
1645		dmu_buf_rele(db, FTAG);
1646
1647		(void) printf("\nMOS Configuration:\n");
1648		dump_packed_nvlist(spa->spa_meta_objset,
1649		    spa->spa_config_object, (void *)&nvsize, 1);
1650	} else {
1651		(void) fprintf(stderr, "dmu_bonus_hold(%llu) failed, errno %d",
1652		    (u_longlong_t)spa->spa_config_object, error);
1653	}
1654}
1655
1656static void
1657dump_cachefile(const char *cachefile)
1658{
1659	int fd;
1660	struct stat64 statbuf;
1661	char *buf;
1662	nvlist_t *config;
1663
1664	if ((fd = open64(cachefile, O_RDONLY)) < 0) {
1665		(void) printf("cannot open '%s': %s\n", cachefile,
1666		    strerror(errno));
1667		exit(1);
1668	}
1669
1670	if (fstat64(fd, &statbuf) != 0) {
1671		(void) printf("failed to stat '%s': %s\n", cachefile,
1672		    strerror(errno));
1673		exit(1);
1674	}
1675
1676	if ((buf = malloc(statbuf.st_size)) == NULL) {
1677		(void) fprintf(stderr, "failed to allocate %llu bytes\n",
1678		    (u_longlong_t)statbuf.st_size);
1679		exit(1);
1680	}
1681
1682	if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
1683		(void) fprintf(stderr, "failed to read %llu bytes\n",
1684		    (u_longlong_t)statbuf.st_size);
1685		exit(1);
1686	}
1687
1688	(void) close(fd);
1689
1690	if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
1691		(void) fprintf(stderr, "failed to unpack nvlist\n");
1692		exit(1);
1693	}
1694
1695	free(buf);
1696
1697	dump_nvlist(config, 0);
1698
1699	nvlist_free(config);
1700}
1701
1702#define	ZDB_MAX_UB_HEADER_SIZE 32
1703
1704static void
1705dump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
1706{
1707	vdev_t vd;
1708	vdev_t *vdp = &vd;
1709	char header[ZDB_MAX_UB_HEADER_SIZE];
1710
1711	vd.vdev_ashift = ashift;
1712	vdp->vdev_top = vdp;
1713
1714	for (int i = 0; i < VDEV_UBERBLOCK_COUNT(vdp); i++) {
1715		uint64_t uoff = VDEV_UBERBLOCK_OFFSET(vdp, i);
1716		uberblock_t *ub = (void *)((char *)lbl + uoff);
1717
1718		if (uberblock_verify(ub))
1719			continue;
1720		(void) snprintf(header, ZDB_MAX_UB_HEADER_SIZE,
1721		    "Uberblock[%d]\n", i);
1722		dump_uberblock(ub, header, "");
1723	}
1724}
1725
1726static void
1727dump_label(const char *dev)
1728{
1729	int fd;
1730	vdev_label_t label;
1731	char *path, *buf = label.vl_vdev_phys.vp_nvlist;
1732	size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
1733	struct stat64 statbuf;
1734	uint64_t psize, ashift;
1735	int len = strlen(dev) + 1;
1736
1737	if (strncmp(dev, "/dev/dsk/", 9) == 0) {
1738		len++;
1739		path = malloc(len);
1740		(void) snprintf(path, len, "%s%s", "/dev/rdsk/", dev + 9);
1741	} else {
1742		path = strdup(dev);
1743	}
1744
1745	if ((fd = open64(path, O_RDONLY)) < 0) {
1746		(void) printf("cannot open '%s': %s\n", path, strerror(errno));
1747		free(path);
1748		exit(1);
1749	}
1750
1751	if (fstat64(fd, &statbuf) != 0) {
1752		(void) printf("failed to stat '%s': %s\n", path,
1753		    strerror(errno));
1754		free(path);
1755		(void) close(fd);
1756		exit(1);
1757	}
1758
1759	if (S_ISBLK(statbuf.st_mode)) {
1760		(void) printf("cannot use '%s': character device required\n",
1761		    path);
1762		free(path);
1763		(void) close(fd);
1764		exit(1);
1765	}
1766
1767	psize = statbuf.st_size;
1768	psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
1769
1770	for (int l = 0; l < VDEV_LABELS; l++) {
1771		nvlist_t *config = NULL;
1772
1773		(void) printf("--------------------------------------------\n");
1774		(void) printf("LABEL %d\n", l);
1775		(void) printf("--------------------------------------------\n");
1776
1777		if (pread64(fd, &label, sizeof (label),
1778		    vdev_label_offset(psize, l, 0)) != sizeof (label)) {
1779			(void) printf("failed to read label %d\n", l);
1780			continue;
1781		}
1782
1783		if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
1784			(void) printf("failed to unpack label %d\n", l);
1785			ashift = SPA_MINBLOCKSHIFT;
1786		} else {
1787			nvlist_t *vdev_tree = NULL;
1788
1789			dump_nvlist(config, 4);
1790			if ((nvlist_lookup_nvlist(config,
1791			    ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
1792			    (nvlist_lookup_uint64(vdev_tree,
1793			    ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
1794				ashift = SPA_MINBLOCKSHIFT;
1795			nvlist_free(config);
1796		}
1797		if (dump_opt['u'])
1798			dump_label_uberblocks(&label, ashift);
1799	}
1800
1801	free(path);
1802	(void) close(fd);
1803}
1804
1805/*ARGSUSED*/
1806static int
1807dump_one_dir(const char *dsname, void *arg)
1808{
1809	int error;
1810	objset_t *os;
1811
1812	error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
1813	if (error) {
1814		(void) printf("Could not open %s, error %d\n", dsname, error);
1815		return (0);
1816	}
1817	dump_dir(os);
1818	dmu_objset_disown(os, FTAG);
1819	fuid_table_destroy();
1820	sa_loaded = B_FALSE;
1821	return (0);
1822}
1823
1824/*
1825 * Block statistics.
1826 */
1827typedef struct zdb_blkstats {
1828	uint64_t	zb_asize;
1829	uint64_t	zb_lsize;
1830	uint64_t	zb_psize;
1831	uint64_t	zb_count;
1832} zdb_blkstats_t;
1833
1834/*
1835 * Extended object types to report deferred frees and dedup auto-ditto blocks.
1836 */
1837#define	ZDB_OT_DEFERRED	(DMU_OT_NUMTYPES + 0)
1838#define	ZDB_OT_DITTO	(DMU_OT_NUMTYPES + 1)
1839#define	ZDB_OT_TOTAL	(DMU_OT_NUMTYPES + 2)
1840
1841static char *zdb_ot_extname[] = {
1842	"deferred free",
1843	"dedup ditto",
1844	"Total",
1845};
1846
1847#define	ZB_TOTAL	DN_MAX_LEVELS
1848
1849typedef struct zdb_cb {
1850	zdb_blkstats_t	zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1];
1851	uint64_t	zcb_dedup_asize;
1852	uint64_t	zcb_dedup_blocks;
1853	uint64_t	zcb_errors[256];
1854	int		zcb_readfails;
1855	int		zcb_haderrors;
1856} zdb_cb_t;
1857
1858static void
1859zdb_count_block(spa_t *spa, zilog_t *zilog, zdb_cb_t *zcb, const blkptr_t *bp,
1860    dmu_object_type_t type)
1861{
1862	uint64_t refcnt = 0;
1863
1864	ASSERT(type < ZDB_OT_TOTAL);
1865
1866	if (zilog && zil_bp_tree_add(zilog, bp) != 0)
1867		return;
1868
1869	for (int i = 0; i < 4; i++) {
1870		int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL;
1871		int t = (i & 1) ? type : ZDB_OT_TOTAL;
1872		zdb_blkstats_t *zb = &zcb->zcb_type[l][t];
1873
1874		zb->zb_asize += BP_GET_ASIZE(bp);
1875		zb->zb_lsize += BP_GET_LSIZE(bp);
1876		zb->zb_psize += BP_GET_PSIZE(bp);
1877		zb->zb_count++;
1878	}
1879
1880	if (dump_opt['L'])
1881		return;
1882
1883	if (BP_GET_DEDUP(bp)) {
1884		ddt_t *ddt;
1885		ddt_entry_t *dde;
1886
1887		ddt = ddt_select(spa, bp);
1888		ddt_enter(ddt);
1889		dde = ddt_lookup(ddt, bp, B_FALSE);
1890
1891		if (dde == NULL) {
1892			refcnt = 0;
1893		} else {
1894			ddt_phys_t *ddp = ddt_phys_select(dde, bp);
1895			ddt_phys_decref(ddp);
1896			refcnt = ddp->ddp_refcnt;
1897			if (ddt_phys_total_refcnt(dde) == 0)
1898				ddt_remove(ddt, dde);
1899		}
1900		ddt_exit(ddt);
1901	}
1902
1903	VERIFY3U(zio_wait(zio_claim(NULL, spa,
1904	    refcnt ? 0 : spa_first_txg(spa),
1905	    bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
1906}
1907
1908static int
1909zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
1910    const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
1911{
1912	zdb_cb_t *zcb = arg;
1913	char blkbuf[BP_SPRINTF_LEN];
1914	dmu_object_type_t type;
1915	boolean_t is_metadata;
1916
1917	if (bp == NULL)
1918		return (0);
1919
1920	type = BP_GET_TYPE(bp);
1921
1922	zdb_count_block(spa, zilog, zcb, bp, type);
1923
1924	is_metadata = (BP_GET_LEVEL(bp) != 0 || dmu_ot[type].ot_metadata);
1925
1926	if (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata)) {
1927		int ioerr;
1928		size_t size = BP_GET_PSIZE(bp);
1929		void *data = malloc(size);
1930		int flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB | ZIO_FLAG_RAW;
1931
1932		/* If it's an intent log block, failure is expected. */
1933		if (zb->zb_level == ZB_ZIL_LEVEL)
1934			flags |= ZIO_FLAG_SPECULATIVE;
1935
1936		ioerr = zio_wait(zio_read(NULL, spa, bp, data, size,
1937		    NULL, NULL, ZIO_PRIORITY_ASYNC_READ, flags, zb));
1938
1939		free(data);
1940
1941		if (ioerr && !(flags & ZIO_FLAG_SPECULATIVE)) {
1942			zcb->zcb_haderrors = 1;
1943			zcb->zcb_errors[ioerr]++;
1944
1945			if (dump_opt['b'] >= 2)
1946				sprintf_blkptr(blkbuf, bp);
1947			else
1948				blkbuf[0] = '\0';
1949
1950			(void) printf("zdb_blkptr_cb: "
1951			    "Got error %d reading "
1952			    "<%llu, %llu, %lld, %llx> %s -- skipping\n",
1953			    ioerr,
1954			    (u_longlong_t)zb->zb_objset,
1955			    (u_longlong_t)zb->zb_object,
1956			    (u_longlong_t)zb->zb_level,
1957			    (u_longlong_t)zb->zb_blkid,
1958			    blkbuf);
1959		}
1960	}
1961
1962	zcb->zcb_readfails = 0;
1963
1964	if (dump_opt['b'] >= 4) {
1965		sprintf_blkptr(blkbuf, bp);
1966		(void) printf("objset %llu object %llu "
1967		    "level %lld offset 0x%llx %s\n",
1968		    (u_longlong_t)zb->zb_objset,
1969		    (u_longlong_t)zb->zb_object,
1970		    (longlong_t)zb->zb_level,
1971		    (u_longlong_t)blkid2offset(dnp, bp, zb),
1972		    blkbuf);
1973	}
1974
1975	return (0);
1976}
1977
1978static void
1979zdb_leak(space_map_t *sm, uint64_t start, uint64_t size)
1980{
1981	vdev_t *vd = sm->sm_ppd;
1982
1983	(void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n",
1984	    (u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size);
1985}
1986
1987/* ARGSUSED */
1988static void
1989zdb_space_map_load(space_map_t *sm)
1990{
1991}
1992
1993static void
1994zdb_space_map_unload(space_map_t *sm)
1995{
1996	space_map_vacate(sm, zdb_leak, sm);
1997}
1998
1999/* ARGSUSED */
2000static void
2001zdb_space_map_claim(space_map_t *sm, uint64_t start, uint64_t size)
2002{
2003}
2004
2005static space_map_ops_t zdb_space_map_ops = {
2006	zdb_space_map_load,
2007	zdb_space_map_unload,
2008	NULL,	/* alloc */
2009	zdb_space_map_claim,
2010	NULL,	/* free */
2011	NULL	/* maxsize */
2012};
2013
2014static void
2015zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb)
2016{
2017	ddt_bookmark_t ddb = { 0 };
2018	ddt_entry_t dde;
2019	int error;
2020
2021	while ((error = ddt_walk(spa, &ddb, &dde)) == 0) {
2022		blkptr_t blk;
2023		ddt_phys_t *ddp = dde.dde_phys;
2024
2025		if (ddb.ddb_class == DDT_CLASS_UNIQUE)
2026			return;
2027
2028		ASSERT(ddt_phys_total_refcnt(&dde) > 1);
2029
2030		for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
2031			if (ddp->ddp_phys_birth == 0)
2032				continue;
2033			ddt_bp_create(ddb.ddb_checksum,
2034			    &dde.dde_key, ddp, &blk);
2035			if (p == DDT_PHYS_DITTO) {
2036				zdb_count_block(spa, NULL, zcb, &blk,
2037				    ZDB_OT_DITTO);
2038			} else {
2039				zcb->zcb_dedup_asize +=
2040				    BP_GET_ASIZE(&blk) * (ddp->ddp_refcnt - 1);
2041				zcb->zcb_dedup_blocks++;
2042			}
2043		}
2044		if (!dump_opt['L']) {
2045			ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum];
2046			ddt_enter(ddt);
2047			VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL);
2048			ddt_exit(ddt);
2049		}
2050	}
2051
2052	ASSERT(error == ENOENT);
2053}
2054
2055static void
2056zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
2057{
2058	if (!dump_opt['L']) {
2059		vdev_t *rvd = spa->spa_root_vdev;
2060		for (int c = 0; c < rvd->vdev_children; c++) {
2061			vdev_t *vd = rvd->vdev_child[c];
2062			for (int m = 0; m < vd->vdev_ms_count; m++) {
2063				metaslab_t *msp = vd->vdev_ms[m];
2064				mutex_enter(&msp->ms_lock);
2065				space_map_unload(&msp->ms_map);
2066				VERIFY(space_map_load(&msp->ms_map,
2067				    &zdb_space_map_ops, SM_ALLOC, &msp->ms_smo,
2068				    spa->spa_meta_objset) == 0);
2069				msp->ms_map.sm_ppd = vd;
2070				mutex_exit(&msp->ms_lock);
2071			}
2072		}
2073	}
2074
2075	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
2076
2077	zdb_ddt_leak_init(spa, zcb);
2078
2079	spa_config_exit(spa, SCL_CONFIG, FTAG);
2080}
2081
2082static void
2083zdb_leak_fini(spa_t *spa)
2084{
2085	if (!dump_opt['L']) {
2086		vdev_t *rvd = spa->spa_root_vdev;
2087		for (int c = 0; c < rvd->vdev_children; c++) {
2088			vdev_t *vd = rvd->vdev_child[c];
2089			for (int m = 0; m < vd->vdev_ms_count; m++) {
2090				metaslab_t *msp = vd->vdev_ms[m];
2091				mutex_enter(&msp->ms_lock);
2092				space_map_unload(&msp->ms_map);
2093				mutex_exit(&msp->ms_lock);
2094			}
2095		}
2096	}
2097}
2098
2099static int
2100dump_block_stats(spa_t *spa)
2101{
2102	zdb_cb_t zcb = { 0 };
2103	zdb_blkstats_t *zb, *tzb;
2104	uint64_t norm_alloc, norm_space, total_alloc, total_found;
2105	int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD;
2106	int leaks = 0;
2107
2108	(void) printf("\nTraversing all blocks %s%s%s%s%s...\n",
2109	    (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "",
2110	    (dump_opt['c'] == 1) ? "metadata " : "",
2111	    dump_opt['c'] ? "checksums " : "",
2112	    (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "",
2113	    !dump_opt['L'] ? "nothing leaked " : "");
2114
2115	/*
2116	 * Load all space maps as SM_ALLOC maps, then traverse the pool
2117	 * claiming each block we discover.  If the pool is perfectly
2118	 * consistent, the space maps will be empty when we're done.
2119	 * Anything left over is a leak; any block we can't claim (because
2120	 * it's not part of any space map) is a double allocation,
2121	 * reference to a freed block, or an unclaimed log block.
2122	 */
2123	zdb_leak_init(spa, &zcb);
2124
2125	/*
2126	 * If there's a deferred-free bplist, process that first.
2127	 */
2128	if (spa->spa_deferred_bplist_obj != 0) {
2129		bplist_t *bpl = &spa->spa_deferred_bplist;
2130		blkptr_t blk;
2131		uint64_t itor = 0;
2132
2133		VERIFY(0 == bplist_open(bpl, spa->spa_meta_objset,
2134		    spa->spa_deferred_bplist_obj));
2135
2136		while (bplist_iterate(bpl, &itor, &blk) == 0) {
2137			if (dump_opt['b'] >= 4) {
2138				char blkbuf[BP_SPRINTF_LEN];
2139				sprintf_blkptr(blkbuf, &blk);
2140				(void) printf("[%s] %s\n",
2141				    "deferred free", blkbuf);
2142			}
2143			zdb_count_block(spa, NULL, &zcb, &blk, ZDB_OT_DEFERRED);
2144		}
2145
2146		bplist_close(bpl);
2147	}
2148
2149	if (dump_opt['c'] > 1)
2150		flags |= TRAVERSE_PREFETCH_DATA;
2151
2152	zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
2153
2154	if (zcb.zcb_haderrors) {
2155		(void) printf("\nError counts:\n\n");
2156		(void) printf("\t%5s  %s\n", "errno", "count");
2157		for (int e = 0; e < 256; e++) {
2158			if (zcb.zcb_errors[e] != 0) {
2159				(void) printf("\t%5d  %llu\n",
2160				    e, (u_longlong_t)zcb.zcb_errors[e]);
2161			}
2162		}
2163	}
2164
2165	/*
2166	 * Report any leaked segments.
2167	 */
2168	zdb_leak_fini(spa);
2169
2170	tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL];
2171
2172	norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa));
2173	norm_space = metaslab_class_get_space(spa_normal_class(spa));
2174
2175	total_alloc = norm_alloc + metaslab_class_get_alloc(spa_log_class(spa));
2176	total_found = tzb->zb_asize - zcb.zcb_dedup_asize;
2177
2178	if (total_found == total_alloc) {
2179		if (!dump_opt['L'])
2180			(void) printf("\n\tNo leaks (block sum matches space"
2181			    " maps exactly)\n");
2182	} else {
2183		(void) printf("block traversal size %llu != alloc %llu "
2184		    "(%s %lld)\n",
2185		    (u_longlong_t)total_found,
2186		    (u_longlong_t)total_alloc,
2187		    (dump_opt['L']) ? "unreachable" : "leaked",
2188		    (longlong_t)(total_alloc - total_found));
2189		leaks = 1;
2190	}
2191
2192	if (tzb->zb_count == 0)
2193		return (2);
2194
2195	(void) printf("\n");
2196	(void) printf("\tbp count:      %10llu\n",
2197	    (u_longlong_t)tzb->zb_count);
2198	(void) printf("\tbp logical:    %10llu      avg: %6llu\n",
2199	    (u_longlong_t)tzb->zb_lsize,
2200	    (u_longlong_t)(tzb->zb_lsize / tzb->zb_count));
2201	(void) printf("\tbp physical:   %10llu      avg:"
2202	    " %6llu     compression: %6.2f\n",
2203	    (u_longlong_t)tzb->zb_psize,
2204	    (u_longlong_t)(tzb->zb_psize / tzb->zb_count),
2205	    (double)tzb->zb_lsize / tzb->zb_psize);
2206	(void) printf("\tbp allocated:  %10llu      avg:"
2207	    " %6llu     compression: %6.2f\n",
2208	    (u_longlong_t)tzb->zb_asize,
2209	    (u_longlong_t)(tzb->zb_asize / tzb->zb_count),
2210	    (double)tzb->zb_lsize / tzb->zb_asize);
2211	(void) printf("\tbp deduped:    %10llu    ref>1:"
2212	    " %6llu   deduplication: %6.2f\n",
2213	    (u_longlong_t)zcb.zcb_dedup_asize,
2214	    (u_longlong_t)zcb.zcb_dedup_blocks,
2215	    (double)zcb.zcb_dedup_asize / tzb->zb_asize + 1.0);
2216	(void) printf("\tSPA allocated: %10llu     used: %5.2f%%\n",
2217	    (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
2218
2219	if (dump_opt['b'] >= 2) {
2220		int l, t, level;
2221		(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
2222		    "\t  avg\t comp\t%%Total\tType\n");
2223
2224		for (t = 0; t <= ZDB_OT_TOTAL; t++) {
2225			char csize[6], lsize[6], psize[6], asize[6], avg[6];
2226			char *typename;
2227
2228			if (t < DMU_OT_NUMTYPES)
2229				typename = dmu_ot[t].ot_name;
2230			else
2231				typename = zdb_ot_extname[t - DMU_OT_NUMTYPES];
2232
2233			if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) {
2234				(void) printf("%6s\t%5s\t%5s\t%5s"
2235				    "\t%5s\t%5s\t%6s\t%s\n",
2236				    "-",
2237				    "-",
2238				    "-",
2239				    "-",
2240				    "-",
2241				    "-",
2242				    "-",
2243				    typename);
2244				continue;
2245			}
2246
2247			for (l = ZB_TOTAL - 1; l >= -1; l--) {
2248				level = (l == -1 ? ZB_TOTAL : l);
2249				zb = &zcb.zcb_type[level][t];
2250
2251				if (zb->zb_asize == 0)
2252					continue;
2253
2254				if (dump_opt['b'] < 3 && level != ZB_TOTAL)
2255					continue;
2256
2257				if (level == 0 && zb->zb_asize ==
2258				    zcb.zcb_type[ZB_TOTAL][t].zb_asize)
2259					continue;
2260
2261				nicenum(zb->zb_count, csize);
2262				nicenum(zb->zb_lsize, lsize);
2263				nicenum(zb->zb_psize, psize);
2264				nicenum(zb->zb_asize, asize);
2265				nicenum(zb->zb_asize / zb->zb_count, avg);
2266
2267				(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
2268				    "\t%5.2f\t%6.2f\t",
2269				    csize, lsize, psize, asize, avg,
2270				    (double)zb->zb_lsize / zb->zb_psize,
2271				    100.0 * zb->zb_asize / tzb->zb_asize);
2272
2273				if (level == ZB_TOTAL)
2274					(void) printf("%s\n", typename);
2275				else
2276					(void) printf("    L%d %s\n",
2277					    level, typename);
2278			}
2279		}
2280	}
2281
2282	(void) printf("\n");
2283
2284	if (leaks)
2285		return (2);
2286
2287	if (zcb.zcb_haderrors)
2288		return (3);
2289
2290	return (0);
2291}
2292
2293typedef struct zdb_ddt_entry {
2294	ddt_key_t	zdde_key;
2295	uint64_t	zdde_ref_blocks;
2296	uint64_t	zdde_ref_lsize;
2297	uint64_t	zdde_ref_psize;
2298	uint64_t	zdde_ref_dsize;
2299	avl_node_t	zdde_node;
2300} zdb_ddt_entry_t;
2301
2302/* ARGSUSED */
2303static int
2304zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
2305    const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
2306{
2307	avl_tree_t *t = arg;
2308	avl_index_t where;
2309	zdb_ddt_entry_t *zdde, zdde_search;
2310
2311	if (bp == NULL)
2312		return (0);
2313
2314	if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
2315		(void) printf("traversing objset %llu, %llu objects, "
2316		    "%lu blocks so far\n",
2317		    (u_longlong_t)zb->zb_objset,
2318		    (u_longlong_t)bp->blk_fill,
2319		    avl_numnodes(t));
2320	}
2321
2322	if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF ||
2323	    BP_GET_LEVEL(bp) > 0 || dmu_ot[BP_GET_TYPE(bp)].ot_metadata)
2324		return (0);
2325
2326	ddt_key_fill(&zdde_search.zdde_key, bp);
2327
2328	zdde = avl_find(t, &zdde_search, &where);
2329
2330	if (zdde == NULL) {
2331		zdde = umem_zalloc(sizeof (*zdde), UMEM_NOFAIL);
2332		zdde->zdde_key = zdde_search.zdde_key;
2333		avl_insert(t, zdde, where);
2334	}
2335
2336	zdde->zdde_ref_blocks += 1;
2337	zdde->zdde_ref_lsize += BP_GET_LSIZE(bp);
2338	zdde->zdde_ref_psize += BP_GET_PSIZE(bp);
2339	zdde->zdde_ref_dsize += bp_get_dsize_sync(spa, bp);
2340
2341	return (0);
2342}
2343
2344static void
2345dump_simulated_ddt(spa_t *spa)
2346{
2347	avl_tree_t t;
2348	void *cookie = NULL;
2349	zdb_ddt_entry_t *zdde;
2350	ddt_histogram_t ddh_total = { 0 };
2351	ddt_stat_t dds_total = { 0 };
2352
2353	avl_create(&t, ddt_entry_compare,
2354	    sizeof (zdb_ddt_entry_t), offsetof(zdb_ddt_entry_t, zdde_node));
2355
2356	spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
2357
2358	(void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
2359	    zdb_ddt_add_cb, &t);
2360
2361	spa_config_exit(spa, SCL_CONFIG, FTAG);
2362
2363	while ((zdde = avl_destroy_nodes(&t, &cookie)) != NULL) {
2364		ddt_stat_t dds;
2365		uint64_t refcnt = zdde->zdde_ref_blocks;
2366		ASSERT(refcnt != 0);
2367
2368		dds.dds_blocks = zdde->zdde_ref_blocks / refcnt;
2369		dds.dds_lsize = zdde->zdde_ref_lsize / refcnt;
2370		dds.dds_psize = zdde->zdde_ref_psize / refcnt;
2371		dds.dds_dsize = zdde->zdde_ref_dsize / refcnt;
2372
2373		dds.dds_ref_blocks = zdde->zdde_ref_blocks;
2374		dds.dds_ref_lsize = zdde->zdde_ref_lsize;
2375		dds.dds_ref_psize = zdde->zdde_ref_psize;
2376		dds.dds_ref_dsize = zdde->zdde_ref_dsize;
2377
2378		ddt_stat_add(&ddh_total.ddh_stat[highbit(refcnt) - 1], &dds, 0);
2379
2380		umem_free(zdde, sizeof (*zdde));
2381	}
2382
2383	avl_destroy(&t);
2384
2385	ddt_histogram_stat(&dds_total, &ddh_total);
2386
2387	(void) printf("Simulated DDT histogram:\n");
2388
2389	zpool_dump_ddt(&dds_total, &ddh_total);
2390
2391	dump_dedup_ratio(&dds_total);
2392}
2393
2394static void
2395dump_zpool(spa_t *spa)
2396{
2397	dsl_pool_t *dp = spa_get_dsl(spa);
2398	int rc = 0;
2399
2400	if (dump_opt['S']) {
2401		dump_simulated_ddt(spa);
2402		return;
2403	}
2404
2405	if (!dump_opt['e'] && dump_opt['C'] > 1) {
2406		(void) printf("\nCached configuration:\n");
2407		dump_nvlist(spa->spa_config, 8);
2408	}
2409
2410	if (dump_opt['C'])
2411		dump_config(spa);
2412
2413	if (dump_opt['u'])
2414		dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n");
2415
2416	if (dump_opt['D'])
2417		dump_all_ddts(spa);
2418
2419	if (dump_opt['d'] > 2 || dump_opt['m'])
2420		dump_metaslabs(spa);
2421
2422	if (dump_opt['d'] || dump_opt['i']) {
2423		dump_dir(dp->dp_meta_objset);
2424		if (dump_opt['d'] >= 3) {
2425			dump_bplist(dp->dp_meta_objset,
2426			    spa->spa_deferred_bplist_obj, "Deferred frees");
2427			dump_dtl(spa->spa_root_vdev, 0);
2428		}
2429		(void) dmu_objset_find(spa_name(spa), dump_one_dir,
2430		    NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
2431	}
2432	if (dump_opt['b'] || dump_opt['c'])
2433		rc = dump_block_stats(spa);
2434
2435	if (dump_opt['s'])
2436		show_pool_stats(spa);
2437
2438	if (dump_opt['h'])
2439		dump_history(spa);
2440
2441	if (rc != 0)
2442		exit(rc);
2443}
2444
2445#define	ZDB_FLAG_CHECKSUM	0x0001
2446#define	ZDB_FLAG_DECOMPRESS	0x0002
2447#define	ZDB_FLAG_BSWAP		0x0004
2448#define	ZDB_FLAG_GBH		0x0008
2449#define	ZDB_FLAG_INDIRECT	0x0010
2450#define	ZDB_FLAG_PHYS		0x0020
2451#define	ZDB_FLAG_RAW		0x0040
2452#define	ZDB_FLAG_PRINT_BLKPTR	0x0080
2453
2454int flagbits[256];
2455
2456static void
2457zdb_print_blkptr(blkptr_t *bp, int flags)
2458{
2459	char blkbuf[BP_SPRINTF_LEN];
2460
2461	if (flags & ZDB_FLAG_BSWAP)
2462		byteswap_uint64_array((void *)bp, sizeof (blkptr_t));
2463
2464	sprintf_blkptr(blkbuf, bp);
2465	(void) printf("%s\n", blkbuf);
2466}
2467
2468static void
2469zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
2470{
2471	int i;
2472
2473	for (i = 0; i < nbps; i++)
2474		zdb_print_blkptr(&bp[i], flags);
2475}
2476
2477static void
2478zdb_dump_gbh(void *buf, int flags)
2479{
2480	zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
2481}
2482
2483static void
2484zdb_dump_block_raw(void *buf, uint64_t size, int flags)
2485{
2486	if (flags & ZDB_FLAG_BSWAP)
2487		byteswap_uint64_array(buf, size);
2488	(void) write(1, buf, size);
2489}
2490
2491static void
2492zdb_dump_block(char *label, void *buf, uint64_t size, int flags)
2493{
2494	uint64_t *d = (uint64_t *)buf;
2495	int nwords = size / sizeof (uint64_t);
2496	int do_bswap = !!(flags & ZDB_FLAG_BSWAP);
2497	int i, j;
2498	char *hdr, *c;
2499
2500
2501	if (do_bswap)
2502		hdr = " 7 6 5 4 3 2 1 0   f e d c b a 9 8";
2503	else
2504		hdr = " 0 1 2 3 4 5 6 7   8 9 a b c d e f";
2505
2506	(void) printf("\n%s\n%6s   %s  0123456789abcdef\n", label, "", hdr);
2507
2508	for (i = 0; i < nwords; i += 2) {
2509		(void) printf("%06llx:  %016llx  %016llx  ",
2510		    (u_longlong_t)(i * sizeof (uint64_t)),
2511		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i]) : d[i]),
2512		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i + 1]) : d[i + 1]));
2513
2514		c = (char *)&d[i];
2515		for (j = 0; j < 2 * sizeof (uint64_t); j++)
2516			(void) printf("%c", isprint(c[j]) ? c[j] : '.');
2517		(void) printf("\n");
2518	}
2519}
2520
2521/*
2522 * There are two acceptable formats:
2523 *	leaf_name	  - For example: c1t0d0 or /tmp/ztest.0a
2524 *	child[.child]*    - For example: 0.1.1
2525 *
2526 * The second form can be used to specify arbitrary vdevs anywhere
2527 * in the heirarchy.  For example, in a pool with a mirror of
2528 * RAID-Zs, you can specify either RAID-Z vdev with 0.0 or 0.1 .
2529 */
2530static vdev_t *
2531zdb_vdev_lookup(vdev_t *vdev, char *path)
2532{
2533	char *s, *p, *q;
2534	int i;
2535
2536	if (vdev == NULL)
2537		return (NULL);
2538
2539	/* First, assume the x.x.x.x format */
2540	i = (int)strtoul(path, &s, 10);
2541	if (s == path || (s && *s != '.' && *s != '\0'))
2542		goto name;
2543	if (i < 0 || i >= vdev->vdev_children)
2544		return (NULL);
2545
2546	vdev = vdev->vdev_child[i];
2547	if (*s == '\0')
2548		return (vdev);
2549	return (zdb_vdev_lookup(vdev, s+1));
2550
2551name:
2552	for (i = 0; i < vdev->vdev_children; i++) {
2553		vdev_t *vc = vdev->vdev_child[i];
2554
2555		if (vc->vdev_path == NULL) {
2556			vc = zdb_vdev_lookup(vc, path);
2557			if (vc == NULL)
2558				continue;
2559			else
2560				return (vc);
2561		}
2562
2563		p = strrchr(vc->vdev_path, '/');
2564		p = p ? p + 1 : vc->vdev_path;
2565		q = &vc->vdev_path[strlen(vc->vdev_path) - 2];
2566
2567		if (strcmp(vc->vdev_path, path) == 0)
2568			return (vc);
2569		if (strcmp(p, path) == 0)
2570			return (vc);
2571		if (strcmp(q, "s0") == 0 && strncmp(p, path, q - p) == 0)
2572			return (vc);
2573	}
2574
2575	return (NULL);
2576}
2577
2578/*
2579 * Read a block from a pool and print it out.  The syntax of the
2580 * block descriptor is:
2581 *
2582 *	pool:vdev_specifier:offset:size[:flags]
2583 *
2584 *	pool           - The name of the pool you wish to read from
2585 *	vdev_specifier - Which vdev (see comment for zdb_vdev_lookup)
2586 *	offset         - offset, in hex, in bytes
2587 *	size           - Amount of data to read, in hex, in bytes
2588 *	flags          - A string of characters specifying options
2589 *		 b: Decode a blkptr at given offset within block
2590 *		*c: Calculate and display checksums
2591 *		 d: Decompress data before dumping
2592 *		 e: Byteswap data before dumping
2593 *		 g: Display data as a gang block header
2594 *		 i: Display as an indirect block
2595 *		 p: Do I/O to physical offset
2596 *		 r: Dump raw data to stdout
2597 *
2598 *              * = not yet implemented
2599 */
2600static void
2601zdb_read_block(char *thing, spa_t *spa)
2602{
2603	blkptr_t blk, *bp = &blk;
2604	dva_t *dva = bp->blk_dva;
2605	int flags = 0;
2606	uint64_t offset = 0, size = 0, psize = 0, lsize = 0, blkptr_offset = 0;
2607	zio_t *zio;
2608	vdev_t *vd;
2609	void *pbuf, *lbuf, *buf;
2610	char *s, *p, *dup, *vdev, *flagstr;
2611	int i, error;
2612
2613	dup = strdup(thing);
2614	s = strtok(dup, ":");
2615	vdev = s ? s : "";
2616	s = strtok(NULL, ":");
2617	offset = strtoull(s ? s : "", NULL, 16);
2618	s = strtok(NULL, ":");
2619	size = strtoull(s ? s : "", NULL, 16);
2620	s = strtok(NULL, ":");
2621	flagstr = s ? s : "";
2622
2623	s = NULL;
2624	if (size == 0)
2625		s = "size must not be zero";
2626	if (!IS_P2ALIGNED(size, DEV_BSIZE))
2627		s = "size must be a multiple of sector size";
2628	if (!IS_P2ALIGNED(offset, DEV_BSIZE))
2629		s = "offset must be a multiple of sector size";
2630	if (s) {
2631		(void) printf("Invalid block specifier: %s  - %s\n", thing, s);
2632		free(dup);
2633		return;
2634	}
2635
2636	for (s = strtok(flagstr, ":"); s; s = strtok(NULL, ":")) {
2637		for (i = 0; flagstr[i]; i++) {
2638			int bit = flagbits[(uchar_t)flagstr[i]];
2639
2640			if (bit == 0) {
2641				(void) printf("***Invalid flag: %c\n",
2642				    flagstr[i]);
2643				continue;
2644			}
2645			flags |= bit;
2646
2647			/* If it's not something with an argument, keep going */
2648			if ((bit & (ZDB_FLAG_CHECKSUM |
2649			    ZDB_FLAG_PRINT_BLKPTR)) == 0)
2650				continue;
2651
2652			p = &flagstr[i + 1];
2653			if (bit == ZDB_FLAG_PRINT_BLKPTR)
2654				blkptr_offset = strtoull(p, &p, 16);
2655			if (*p != ':' && *p != '\0') {
2656				(void) printf("***Invalid flag arg: '%s'\n", s);
2657				free(dup);
2658				return;
2659			}
2660		}
2661	}
2662
2663	vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev);
2664	if (vd == NULL) {
2665		(void) printf("***Invalid vdev: %s\n", vdev);
2666		free(dup);
2667		return;
2668	} else {
2669		if (vd->vdev_path)
2670			(void) fprintf(stderr, "Found vdev: %s\n",
2671			    vd->vdev_path);
2672		else
2673			(void) fprintf(stderr, "Found vdev type: %s\n",
2674			    vd->vdev_ops->vdev_op_type);
2675	}
2676
2677	psize = size;
2678	lsize = size;
2679
2680	pbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
2681	lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
2682
2683	BP_ZERO(bp);
2684
2685	DVA_SET_VDEV(&dva[0], vd->vdev_id);
2686	DVA_SET_OFFSET(&dva[0], offset);
2687	DVA_SET_GANG(&dva[0], !!(flags & ZDB_FLAG_GBH));
2688	DVA_SET_ASIZE(&dva[0], vdev_psize_to_asize(vd, psize));
2689
2690	BP_SET_BIRTH(bp, TXG_INITIAL, TXG_INITIAL);
2691
2692	BP_SET_LSIZE(bp, lsize);
2693	BP_SET_PSIZE(bp, psize);
2694	BP_SET_COMPRESS(bp, ZIO_COMPRESS_OFF);
2695	BP_SET_CHECKSUM(bp, ZIO_CHECKSUM_OFF);
2696	BP_SET_TYPE(bp, DMU_OT_NONE);
2697	BP_SET_LEVEL(bp, 0);
2698	BP_SET_DEDUP(bp, 0);
2699	BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
2700
2701	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
2702	zio = zio_root(spa, NULL, NULL, 0);
2703
2704	if (vd == vd->vdev_top) {
2705		/*
2706		 * Treat this as a normal block read.
2707		 */
2708		zio_nowait(zio_read(zio, spa, bp, pbuf, psize, NULL, NULL,
2709		    ZIO_PRIORITY_SYNC_READ,
2710		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL));
2711	} else {
2712		/*
2713		 * Treat this as a vdev child I/O.
2714		 */
2715		zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pbuf, psize,
2716		    ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ,
2717		    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE |
2718		    ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY |
2719		    ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL, NULL));
2720	}
2721
2722	error = zio_wait(zio);
2723	spa_config_exit(spa, SCL_STATE, FTAG);
2724
2725	if (error) {
2726		(void) printf("Read of %s failed, error: %d\n", thing, error);
2727		goto out;
2728	}
2729
2730	if (flags & ZDB_FLAG_DECOMPRESS) {
2731		/*
2732		 * We don't know how the data was compressed, so just try
2733		 * every decompress function at every inflated blocksize.
2734		 */
2735		enum zio_compress c;
2736		void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
2737		void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
2738
2739		bcopy(pbuf, pbuf2, psize);
2740
2741		VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf + psize,
2742		    SPA_MAXBLOCKSIZE - psize) == 0);
2743
2744		VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize,
2745		    SPA_MAXBLOCKSIZE - psize) == 0);
2746
2747		for (lsize = SPA_MAXBLOCKSIZE; lsize > psize;
2748		    lsize -= SPA_MINBLOCKSIZE) {
2749			for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) {
2750				if (zio_decompress_data(c, pbuf, lbuf,
2751				    psize, lsize) == 0 &&
2752				    zio_decompress_data(c, pbuf2, lbuf2,
2753				    psize, lsize) == 0 &&
2754				    bcmp(lbuf, lbuf2, lsize) == 0)
2755					break;
2756			}
2757			if (c != ZIO_COMPRESS_FUNCTIONS)
2758				break;
2759			lsize -= SPA_MINBLOCKSIZE;
2760		}
2761
2762		umem_free(pbuf2, SPA_MAXBLOCKSIZE);
2763		umem_free(lbuf2, SPA_MAXBLOCKSIZE);
2764
2765		if (lsize <= psize) {
2766			(void) printf("Decompress of %s failed\n", thing);
2767			goto out;
2768		}
2769		buf = lbuf;
2770		size = lsize;
2771	} else {
2772		buf = pbuf;
2773		size = psize;
2774	}
2775
2776	if (flags & ZDB_FLAG_PRINT_BLKPTR)
2777		zdb_print_blkptr((blkptr_t *)(void *)
2778		    ((uintptr_t)buf + (uintptr_t)blkptr_offset), flags);
2779	else if (flags & ZDB_FLAG_RAW)
2780		zdb_dump_block_raw(buf, size, flags);
2781	else if (flags & ZDB_FLAG_INDIRECT)
2782		zdb_dump_indirect((blkptr_t *)buf, size / sizeof (blkptr_t),
2783		    flags);
2784	else if (flags & ZDB_FLAG_GBH)
2785		zdb_dump_gbh(buf, flags);
2786	else
2787		zdb_dump_block(thing, buf, size, flags);
2788
2789out:
2790	umem_free(pbuf, SPA_MAXBLOCKSIZE);
2791	umem_free(lbuf, SPA_MAXBLOCKSIZE);
2792	free(dup);
2793}
2794
2795static boolean_t
2796pool_match(nvlist_t *cfg, char *tgt)
2797{
2798	uint64_t v, guid = strtoull(tgt, NULL, 0);
2799	char *s;
2800
2801	if (guid != 0) {
2802		if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0)
2803			return (v == guid);
2804	} else {
2805		if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0)
2806			return (strcmp(s, tgt) == 0);
2807	}
2808	return (B_FALSE);
2809}
2810
2811static char *
2812find_zpool(char **target, nvlist_t **configp, int dirc, char **dirv)
2813{
2814	nvlist_t *pools;
2815	nvlist_t *match = NULL;
2816	char *name = NULL;
2817	char *sepp = NULL;
2818	char sep;
2819	int count = 0;
2820	importargs_t args = { 0 };
2821
2822	args.paths = dirc;
2823	args.path = dirv;
2824	args.can_be_active = B_TRUE;
2825
2826	if ((sepp = strpbrk(*target, "/@")) != NULL) {
2827		sep = *sepp;
2828		*sepp = '\0';
2829	}
2830
2831	pools = zpool_search_import(g_zfs, &args);
2832
2833	if (pools != NULL) {
2834		nvpair_t *elem = NULL;
2835		while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2836			verify(nvpair_value_nvlist(elem, configp) == 0);
2837			if (pool_match(*configp, *target)) {
2838				count++;
2839				if (match != NULL) {
2840					/* print previously found config */
2841					if (name != NULL) {
2842						(void) printf("%s\n", name);
2843						dump_nvlist(match, 8);
2844						name = NULL;
2845					}
2846					(void) printf("%s\n",
2847					    nvpair_name(elem));
2848					dump_nvlist(*configp, 8);
2849				} else {
2850					match = *configp;
2851					name = nvpair_name(elem);
2852				}
2853			}
2854		}
2855	}
2856	if (count > 1)
2857		(void) fatal("\tMatched %d pools - use pool GUID "
2858		    "instead of pool name or \n"
2859		    "\tpool name part of a dataset name to select pool", count);
2860
2861	if (sepp)
2862		*sepp = sep;
2863	/*
2864	 * If pool GUID was specified for pool id, replace it with pool name
2865	 */
2866	if (name && (strstr(*target, name) != *target)) {
2867		int sz = 1 + strlen(name) + ((sepp) ? strlen(sepp) : 0);
2868
2869		*target = umem_alloc(sz, UMEM_NOFAIL);
2870		(void) snprintf(*target, sz, "%s%s", name, sepp ? sepp : "");
2871	}
2872
2873	*configp = name ? match : NULL;
2874
2875	return (name);
2876}
2877
2878int
2879main(int argc, char **argv)
2880{
2881	int i, c;
2882	struct rlimit rl = { 1024, 1024 };
2883	spa_t *spa = NULL;
2884	objset_t *os = NULL;
2885	int dump_all = 1;
2886	int verbose = 0;
2887	int error = 0;
2888	char **searchdirs = NULL;
2889	int nsearch = 0;
2890	char *target;
2891	nvlist_t *policy = NULL;
2892	uint64_t max_txg = UINT64_MAX;
2893	int rewind = ZPOOL_NEVER_REWIND;
2894
2895	(void) setrlimit(RLIMIT_NOFILE, &rl);
2896	(void) enable_extended_FILE_stdio(-1, -1);
2897
2898	dprintf_setup(&argc, argv);
2899
2900	while ((c = getopt(argc, argv, "bcdhilmsuCDRSAFLXevp:t:U:")) != -1) {
2901		switch (c) {
2902		case 'b':
2903		case 'c':
2904		case 'd':
2905		case 'h':
2906		case 'i':
2907		case 'l':
2908		case 'm':
2909		case 's':
2910		case 'u':
2911		case 'C':
2912		case 'D':
2913		case 'R':
2914		case 'S':
2915			dump_opt[c]++;
2916			dump_all = 0;
2917			break;
2918		case 'A':
2919		case 'F':
2920		case 'L':
2921		case 'X':
2922		case 'e':
2923			dump_opt[c]++;
2924			break;
2925		case 'v':
2926			verbose++;
2927			break;
2928		case 'p':
2929			if (searchdirs == NULL) {
2930				searchdirs = umem_alloc(sizeof (char *),
2931				    UMEM_NOFAIL);
2932			} else {
2933				char **tmp = umem_alloc((nsearch + 1) *
2934				    sizeof (char *), UMEM_NOFAIL);
2935				bcopy(searchdirs, tmp, nsearch *
2936				    sizeof (char *));
2937				umem_free(searchdirs,
2938				    nsearch * sizeof (char *));
2939				searchdirs = tmp;
2940			}
2941			searchdirs[nsearch++] = optarg;
2942			break;
2943		case 't':
2944			max_txg = strtoull(optarg, NULL, 0);
2945			if (max_txg < TXG_INITIAL) {
2946				(void) fprintf(stderr, "incorrect txg "
2947				    "specified: %s\n", optarg);
2948				usage();
2949			}
2950			break;
2951		case 'U':
2952			spa_config_path = optarg;
2953			break;
2954		default:
2955			usage();
2956			break;
2957		}
2958	}
2959
2960	if (!dump_opt['e'] && searchdirs != NULL) {
2961		(void) fprintf(stderr, "-p option requires use of -e\n");
2962		usage();
2963	}
2964
2965	kernel_init(FREAD);
2966	g_zfs = libzfs_init();
2967	ASSERT(g_zfs != NULL);
2968
2969	if (dump_all)
2970		verbose = MAX(verbose, 1);
2971
2972	for (c = 0; c < 256; c++) {
2973		if (dump_all && !strchr("elAFLRSX", c))
2974			dump_opt[c] = 1;
2975		if (dump_opt[c])
2976			dump_opt[c] += verbose;
2977	}
2978
2979	aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2);
2980	zfs_recover = (dump_opt['A'] > 1);
2981
2982	argc -= optind;
2983	argv += optind;
2984
2985	if (argc < 2 && dump_opt['R'])
2986		usage();
2987	if (argc < 1) {
2988		if (!dump_opt['e'] && dump_opt['C']) {
2989			dump_cachefile(spa_config_path);
2990			return (0);
2991		}
2992		usage();
2993	}
2994
2995	if (dump_opt['l']) {
2996		dump_label(argv[0]);
2997		return (0);
2998	}
2999
3000	if (dump_opt['X'] || dump_opt['F'])
3001		rewind = ZPOOL_DO_REWIND |
3002		    (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
3003
3004	if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 ||
3005	    nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, max_txg) != 0 ||
3006	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind) != 0)
3007		fatal("internal error: %s", strerror(ENOMEM));
3008
3009	error = 0;
3010	target = argv[0];
3011
3012	if (dump_opt['e']) {
3013		nvlist_t *cfg = NULL;
3014		char *name = find_zpool(&target, &cfg, nsearch, searchdirs);
3015
3016		error = ENOENT;
3017		if (name) {
3018			if (dump_opt['C'] > 1) {
3019				(void) printf("\nConfiguration for import:\n");
3020				dump_nvlist(cfg, 8);
3021			}
3022			if (nvlist_add_nvlist(cfg,
3023			    ZPOOL_REWIND_POLICY, policy) != 0) {
3024				fatal("can't open '%s': %s",
3025				    target, strerror(ENOMEM));
3026			}
3027			if ((error = spa_import(name, cfg, NULL)) != 0)
3028				error = spa_import_verbatim(name, cfg, NULL);
3029		}
3030	}
3031
3032	if (error == 0) {
3033		if (strpbrk(target, "/@") == NULL || dump_opt['R']) {
3034			error = spa_open_rewind(target, &spa, FTAG, policy,
3035			    NULL);
3036			if (error) {
3037				/*
3038				 * If we're missing the log device then
3039				 * try opening the pool after clearing the
3040				 * log state.
3041				 */
3042				mutex_enter(&spa_namespace_lock);
3043				if ((spa = spa_lookup(target)) != NULL &&
3044				    spa->spa_log_state == SPA_LOG_MISSING) {
3045					spa->spa_log_state = SPA_LOG_CLEAR;
3046					error = 0;
3047				}
3048				mutex_exit(&spa_namespace_lock);
3049
3050				if (!error) {
3051					error = spa_open_rewind(target, &spa,
3052					    FTAG, policy, NULL);
3053				}
3054			}
3055		} else {
3056			error = dmu_objset_own(target, DMU_OST_ANY,
3057			    B_TRUE, FTAG, &os);
3058		}
3059	}
3060	nvlist_free(policy);
3061
3062	if (error)
3063		fatal("can't open '%s': %s", target, strerror(error));
3064
3065	argv++;
3066	argc--;
3067	if (!dump_opt['R']) {
3068		if (argc > 0) {
3069			zopt_objects = argc;
3070			zopt_object = calloc(zopt_objects, sizeof (uint64_t));
3071			for (i = 0; i < zopt_objects; i++) {
3072				errno = 0;
3073				zopt_object[i] = strtoull(argv[i], NULL, 0);
3074				if (zopt_object[i] == 0 && errno != 0)
3075					fatal("bad number %s: %s",
3076					    argv[i], strerror(errno));
3077			}
3078		}
3079		(os != NULL) ? dump_dir(os) : dump_zpool(spa);
3080	} else {
3081		flagbits['b'] = ZDB_FLAG_PRINT_BLKPTR;
3082		flagbits['c'] = ZDB_FLAG_CHECKSUM;
3083		flagbits['d'] = ZDB_FLAG_DECOMPRESS;
3084		flagbits['e'] = ZDB_FLAG_BSWAP;
3085		flagbits['g'] = ZDB_FLAG_GBH;
3086		flagbits['i'] = ZDB_FLAG_INDIRECT;
3087		flagbits['p'] = ZDB_FLAG_PHYS;
3088		flagbits['r'] = ZDB_FLAG_RAW;
3089
3090		for (i = 0; i < argc; i++)
3091			zdb_read_block(argv[i], spa);
3092	}
3093
3094	(os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
3095
3096	fuid_table_destroy();
3097	sa_loaded = B_FALSE;
3098
3099	libzfs_fini(g_zfs);
3100	kernel_fini();
3101
3102	return (0);
3103}
3104