zdb.c revision 87219db7f64d5002b5a8311fd76f7900fda2c4e8
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 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <stdio.h>
27#include <stdio_ext.h>
28#include <stdlib.h>
29#include <ctype.h>
30#include <sys/zfs_context.h>
31#include <sys/spa.h>
32#include <sys/spa_impl.h>
33#include <sys/dmu.h>
34#include <sys/zap.h>
35#include <sys/fs/zfs.h>
36#include <sys/zfs_znode.h>
37#include <sys/vdev.h>
38#include <sys/vdev_impl.h>
39#include <sys/metaslab_impl.h>
40#include <sys/dmu_objset.h>
41#include <sys/dsl_dir.h>
42#include <sys/dsl_dataset.h>
43#include <sys/dsl_pool.h>
44#include <sys/dbuf.h>
45#include <sys/zil.h>
46#include <sys/zil_impl.h>
47#include <sys/stat.h>
48#include <sys/resource.h>
49#include <sys/dmu_traverse.h>
50#include <sys/zio_checksum.h>
51#include <sys/zio_compress.h>
52#include <sys/zfs_fuid.h>
53#include <sys/arc.h>
54#undef ZFS_MAXNAMELEN
55#undef verify
56#include <libzfs.h>
57
58#define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
59    zio_compress_table[(idx)].ci_name : "UNKNOWN")
60#define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
61    zio_checksum_table[(idx)].ci_name : "UNKNOWN")
62#define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \
63    dmu_ot[(idx)].ot_name : "UNKNOWN")
64#define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : DMU_OT_NUMTYPES)
65
66const char cmdname[] = "zdb";
67uint8_t dump_opt[256];
68
69typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
70
71extern void dump_intent_log(zilog_t *);
72uint64_t *zopt_object = NULL;
73int zopt_objects = 0;
74libzfs_handle_t *g_zfs;
75boolean_t zdb_sig_user_data = B_TRUE;
76int zdb_sig_cksumalg = ZIO_CHECKSUM_SHA256;
77
78/*
79 * These libumem hooks provide a reasonable set of defaults for the allocator's
80 * debugging facilities.
81 */
82const char *
83_umem_debug_init()
84{
85	return ("default,verbose"); /* $UMEM_DEBUG setting */
86}
87
88const char *
89_umem_logging_init(void)
90{
91	return ("fail,contents"); /* $UMEM_LOGGING setting */
92}
93
94static void
95usage(void)
96{
97	(void) fprintf(stderr,
98	    "Usage: %s [-CumdibcsvhL] [-S user:cksumalg] "
99	    "poolname [object...]\n"
100	    "       %s [-div] dataset [object...]\n"
101	    "       %s -m [-L] poolname [vdev [metaslab...]]\n"
102	    "       %s -R poolname vdev:offset:size[:flags]\n"
103	    "       %s -l device\n"
104	    "       %s -C\n\n",
105	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
106
107	(void) fprintf(stderr, "    Dataset name must include at least one "
108	    "separator character '/' or '@'\n");
109	(void) fprintf(stderr, "    If dataset name is specified, only that "
110	    "dataset is dumped\n");
111	(void) fprintf(stderr, "    If object numbers are specified, only "
112	    "those objects are dumped\n\n");
113	(void) fprintf(stderr, "    Options to control amount of output:\n");
114	(void) fprintf(stderr, "        -u uberblock\n");
115	(void) fprintf(stderr, "        -d dataset(s)\n");
116	(void) fprintf(stderr, "        -i intent logs\n");
117	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
118	(void) fprintf(stderr, "        -h pool history\n");
119	(void) fprintf(stderr, "        -b block statistics\n");
120	(void) fprintf(stderr, "        -m metaslabs\n");
121	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
122	    "all data) blocks\n");
123	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
124	(void) fprintf(stderr, "        -S <user|all>:<cksum_alg|all> -- "
125	    "dump blkptr signatures\n");
126	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
127	(void) fprintf(stderr, "        -l dump label contents\n");
128	(void) fprintf(stderr, "        -L disable leak tracking (do not "
129	    "load spacemaps)\n");
130	(void) fprintf(stderr, "        -R read and display block from a "
131	    "device\n\n");
132	(void) fprintf(stderr, "    Below options are intended for use "
133	    "with other options (except -l):\n");
134	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
135	    "cachefile\n");
136	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
137	    "has altroot/not in a cachefile\n");
138	(void) fprintf(stderr, "        -p <path> -- use one or more with "
139	    "-e to specify path to vdev dir\n");
140	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
141	    "searching for uberblocks\n");
142	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
143	    "to make only that option verbose\n");
144	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
145	exit(1);
146}
147
148/*
149 * Called for usage errors that are discovered after a call to spa_open(),
150 * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
151 */
152
153static void
154fatal(const char *fmt, ...)
155{
156	va_list ap;
157
158	va_start(ap, fmt);
159	(void) fprintf(stderr, "%s: ", cmdname);
160	(void) vfprintf(stderr, fmt, ap);
161	va_end(ap);
162	(void) fprintf(stderr, "\n");
163
164	exit(1);
165}
166
167/* ARGSUSED */
168static void
169dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
170{
171	nvlist_t *nv;
172	size_t nvsize = *(uint64_t *)data;
173	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
174
175	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
176
177	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
178
179	umem_free(packed, nvsize);
180
181	dump_nvlist(nv, 8);
182
183	nvlist_free(nv);
184}
185
186const char dump_zap_stars[] = "****************************************";
187const int dump_zap_width = sizeof (dump_zap_stars) - 1;
188
189static void
190dump_zap_histogram(uint64_t histo[ZAP_HISTOGRAM_SIZE])
191{
192	int i;
193	int minidx = ZAP_HISTOGRAM_SIZE - 1;
194	int maxidx = 0;
195	uint64_t max = 0;
196
197	for (i = 0; i < ZAP_HISTOGRAM_SIZE; i++) {
198		if (histo[i] > max)
199			max = histo[i];
200		if (histo[i] > 0 && i > maxidx)
201			maxidx = i;
202		if (histo[i] > 0 && i < minidx)
203			minidx = i;
204	}
205
206	if (max < dump_zap_width)
207		max = dump_zap_width;
208
209	for (i = minidx; i <= maxidx; i++)
210		(void) printf("\t\t\t%u: %6llu %s\n", i, (u_longlong_t)histo[i],
211		    &dump_zap_stars[(max - histo[i]) * dump_zap_width / max]);
212}
213
214static void
215dump_zap_stats(objset_t *os, uint64_t object)
216{
217	int error;
218	zap_stats_t zs;
219
220	error = zap_get_stats(os, object, &zs);
221	if (error)
222		return;
223
224	if (zs.zs_ptrtbl_len == 0) {
225		ASSERT(zs.zs_num_blocks == 1);
226		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
227		    (u_longlong_t)zs.zs_blocksize,
228		    (u_longlong_t)zs.zs_num_entries);
229		return;
230	}
231
232	(void) printf("\tFat ZAP stats:\n");
233
234	(void) printf("\t\tPointer table:\n");
235	(void) printf("\t\t\t%llu elements\n",
236	    (u_longlong_t)zs.zs_ptrtbl_len);
237	(void) printf("\t\t\tzt_blk: %llu\n",
238	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
239	(void) printf("\t\t\tzt_numblks: %llu\n",
240	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
241	(void) printf("\t\t\tzt_shift: %llu\n",
242	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
243	(void) printf("\t\t\tzt_blks_copied: %llu\n",
244	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
245	(void) printf("\t\t\tzt_nextblk: %llu\n",
246	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
247
248	(void) printf("\t\tZAP entries: %llu\n",
249	    (u_longlong_t)zs.zs_num_entries);
250	(void) printf("\t\tLeaf blocks: %llu\n",
251	    (u_longlong_t)zs.zs_num_leafs);
252	(void) printf("\t\tTotal blocks: %llu\n",
253	    (u_longlong_t)zs.zs_num_blocks);
254	(void) printf("\t\tzap_block_type: 0x%llx\n",
255	    (u_longlong_t)zs.zs_block_type);
256	(void) printf("\t\tzap_magic: 0x%llx\n",
257	    (u_longlong_t)zs.zs_magic);
258	(void) printf("\t\tzap_salt: 0x%llx\n",
259	    (u_longlong_t)zs.zs_salt);
260
261	(void) printf("\t\tLeafs with 2^n pointers:\n");
262	dump_zap_histogram(zs.zs_leafs_with_2n_pointers);
263
264	(void) printf("\t\tBlocks with n*5 entries:\n");
265	dump_zap_histogram(zs.zs_blocks_with_n5_entries);
266
267	(void) printf("\t\tBlocks n/10 full:\n");
268	dump_zap_histogram(zs.zs_blocks_n_tenths_full);
269
270	(void) printf("\t\tEntries with n chunks:\n");
271	dump_zap_histogram(zs.zs_entries_using_n_chunks);
272
273	(void) printf("\t\tBuckets with n entries:\n");
274	dump_zap_histogram(zs.zs_buckets_with_n_entries);
275}
276
277/*ARGSUSED*/
278static void
279dump_none(objset_t *os, uint64_t object, void *data, size_t size)
280{
281}
282
283/*ARGSUSED*/
284static void
285dump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
286{
287	(void) printf("\tUNKNOWN OBJECT TYPE\n");
288}
289
290/*ARGSUSED*/
291void
292dump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
293{
294}
295
296/*ARGSUSED*/
297static void
298dump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
299{
300}
301
302/*ARGSUSED*/
303static void
304dump_zap(objset_t *os, uint64_t object, void *data, size_t size)
305{
306	zap_cursor_t zc;
307	zap_attribute_t attr;
308	void *prop;
309	int i;
310
311	dump_zap_stats(os, object);
312	(void) printf("\n");
313
314	for (zap_cursor_init(&zc, os, object);
315	    zap_cursor_retrieve(&zc, &attr) == 0;
316	    zap_cursor_advance(&zc)) {
317		(void) printf("\t\t%s = ", attr.za_name);
318		if (attr.za_num_integers == 0) {
319			(void) printf("\n");
320			continue;
321		}
322		prop = umem_zalloc(attr.za_num_integers *
323		    attr.za_integer_length, UMEM_NOFAIL);
324		(void) zap_lookup(os, object, attr.za_name,
325		    attr.za_integer_length, attr.za_num_integers, prop);
326		if (attr.za_integer_length == 1) {
327			(void) printf("%s", (char *)prop);
328		} else {
329			for (i = 0; i < attr.za_num_integers; i++) {
330				switch (attr.za_integer_length) {
331				case 2:
332					(void) printf("%u ",
333					    ((uint16_t *)prop)[i]);
334					break;
335				case 4:
336					(void) printf("%u ",
337					    ((uint32_t *)prop)[i]);
338					break;
339				case 8:
340					(void) printf("%lld ",
341					    (u_longlong_t)((int64_t *)prop)[i]);
342					break;
343				}
344			}
345		}
346		(void) printf("\n");
347		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
348	}
349	zap_cursor_fini(&zc);
350}
351
352/*ARGSUSED*/
353static void
354dump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
355{
356	zap_cursor_t zc;
357	zap_attribute_t attr;
358	const char *typenames[] = {
359		/* 0 */ "not specified",
360		/* 1 */ "FIFO",
361		/* 2 */ "Character Device",
362		/* 3 */ "3 (invalid)",
363		/* 4 */ "Directory",
364		/* 5 */ "5 (invalid)",
365		/* 6 */ "Block Device",
366		/* 7 */ "7 (invalid)",
367		/* 8 */ "Regular File",
368		/* 9 */ "9 (invalid)",
369		/* 10 */ "Symbolic Link",
370		/* 11 */ "11 (invalid)",
371		/* 12 */ "Socket",
372		/* 13 */ "Door",
373		/* 14 */ "Event Port",
374		/* 15 */ "15 (invalid)",
375	};
376
377	dump_zap_stats(os, object);
378	(void) printf("\n");
379
380	for (zap_cursor_init(&zc, os, object);
381	    zap_cursor_retrieve(&zc, &attr) == 0;
382	    zap_cursor_advance(&zc)) {
383		(void) printf("\t\t%s = %lld (type: %s)\n",
384		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
385		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
386	}
387	zap_cursor_fini(&zc);
388}
389
390static void
391dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
392{
393	uint64_t alloc, offset, entry;
394	uint8_t mapshift = sm->sm_shift;
395	uint64_t mapstart = sm->sm_start;
396	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
397			    "INVALID", "INVALID", "INVALID", "INVALID" };
398
399	if (smo->smo_object == 0)
400		return;
401
402	/*
403	 * Print out the freelist entries in both encoded and decoded form.
404	 */
405	alloc = 0;
406	for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
407		VERIFY(0 == dmu_read(os, smo->smo_object, offset,
408		    sizeof (entry), &entry, DMU_READ_PREFETCH));
409		if (SM_DEBUG_DECODE(entry)) {
410			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
411			    (u_longlong_t)(offset / sizeof (entry)),
412			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
413			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
414			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
415		} else {
416			(void) printf("\t    [%6llu]    %c  range:"
417			    " %010llx-%010llx  size: %06llx\n",
418			    (u_longlong_t)(offset / sizeof (entry)),
419			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
420			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
421			    mapshift) + mapstart),
422			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
423			    mapshift) + mapstart + (SM_RUN_DECODE(entry) <<
424			    mapshift)),
425			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
426			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
427				alloc += SM_RUN_DECODE(entry) << mapshift;
428			else
429				alloc -= SM_RUN_DECODE(entry) << mapshift;
430		}
431	}
432	if (alloc != smo->smo_alloc) {
433		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
434		    "with space map summary (%llu)\n",
435		    (u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc);
436	}
437}
438
439static void
440dump_metaslab_stats(metaslab_t *msp)
441{
442	char maxbuf[5];
443	space_map_t *sm = &msp->ms_map;
444	avl_tree_t *t = sm->sm_pp_root;
445	int free_pct = sm->sm_space * 100 / sm->sm_size;
446
447	nicenum(space_map_maxsize(sm), maxbuf);
448
449	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
450	    "segments", avl_numnodes(t), "maxsize", maxbuf,
451	    "freepct", free_pct);
452}
453
454static void
455dump_metaslab(metaslab_t *msp)
456{
457	char freebuf[5];
458	space_map_obj_t *smo = &msp->ms_smo;
459	vdev_t *vd = msp->ms_group->mg_vd;
460	spa_t *spa = vd->vdev_spa;
461
462	nicenum(msp->ms_map.sm_size - smo->smo_alloc, freebuf);
463
464	(void) printf(
465	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
466	    (u_longlong_t)(msp->ms_map.sm_start / msp->ms_map.sm_size),
467	    (u_longlong_t)msp->ms_map.sm_start, (u_longlong_t)smo->smo_object,
468	    freebuf);
469
470	if (dump_opt['m'] > 1 && !dump_opt['L']) {
471		mutex_enter(&msp->ms_lock);
472		VERIFY(space_map_load(&msp->ms_map, zfs_metaslab_ops,
473		    SM_FREE, &msp->ms_smo, spa->spa_meta_objset) == 0);
474		dump_metaslab_stats(msp);
475		space_map_unload(&msp->ms_map);
476		mutex_exit(&msp->ms_lock);
477	}
478
479	if (dump_opt['d'] > 5 || dump_opt['m'] > 2) {
480		ASSERT(msp->ms_map.sm_size == (1ULL << vd->vdev_ms_shift));
481
482		mutex_enter(&msp->ms_lock);
483		dump_spacemap(spa->spa_meta_objset, smo, &msp->ms_map);
484		mutex_exit(&msp->ms_lock);
485	}
486}
487
488static void
489print_vdev_metaslab_header(vdev_t *vd)
490{
491	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
492	    (u_longlong_t)vd->vdev_id,
493	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
494	    "offset", "spacemap", "free");
495	(void) printf("\t%15s   %19s   %15s   %10s\n",
496	    "---------------", "-------------------",
497	    "---------------", "-------------");
498}
499
500static void
501dump_metaslabs(spa_t *spa)
502{
503	vdev_t *vd, *rvd = spa->spa_root_vdev;
504	uint64_t m, c = 0, children = rvd->vdev_children;
505
506	(void) printf("\nMetaslabs:\n");
507
508	if (!dump_opt['d'] && zopt_objects > 0) {
509		c = zopt_object[0];
510
511		if (c >= children)
512			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
513
514		if (zopt_objects > 1) {
515			vd = rvd->vdev_child[c];
516			print_vdev_metaslab_header(vd);
517
518			for (m = 1; m < zopt_objects; m++) {
519				if (zopt_object[m] < vd->vdev_ms_count)
520					dump_metaslab(
521					    vd->vdev_ms[zopt_object[m]]);
522				else
523					(void) fprintf(stderr, "bad metaslab "
524					    "number %llu\n",
525					    (u_longlong_t)zopt_object[m]);
526			}
527			(void) printf("\n");
528			return;
529		}
530		children = c + 1;
531	}
532	for (; c < children; c++) {
533		vd = rvd->vdev_child[c];
534		print_vdev_metaslab_header(vd);
535
536		for (m = 0; m < vd->vdev_ms_count; m++)
537			dump_metaslab(vd->vdev_ms[m]);
538		(void) printf("\n");
539	}
540}
541
542static void
543dump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size)
544{
545	char *prefix = (void *)sm;
546
547	(void) printf("%s [%llu,%llu) length %llu\n",
548	    prefix,
549	    (u_longlong_t)start,
550	    (u_longlong_t)(start + size),
551	    (u_longlong_t)(size));
552}
553
554static void
555dump_dtl(vdev_t *vd, int indent)
556{
557	spa_t *spa = vd->vdev_spa;
558	boolean_t required;
559	char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" };
560	char prefix[256];
561
562	spa_vdev_state_enter(spa, SCL_NONE);
563	required = vdev_dtl_required(vd);
564	(void) spa_vdev_state_exit(spa, NULL, 0);
565
566	if (indent == 0)
567		(void) printf("\nDirty time logs:\n\n");
568
569	(void) printf("\t%*s%s [%s]\n", indent, "",
570	    vd->vdev_path ? vd->vdev_path :
571	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
572	    required ? "DTL-required" : "DTL-expendable");
573
574	for (int t = 0; t < DTL_TYPES; t++) {
575		space_map_t *sm = &vd->vdev_dtl[t];
576		if (sm->sm_space == 0)
577			continue;
578		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
579		    indent + 2, "", name[t]);
580		mutex_enter(sm->sm_lock);
581		space_map_walk(sm, dump_dtl_seg, (void *)prefix);
582		mutex_exit(sm->sm_lock);
583		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
584			dump_spacemap(spa->spa_meta_objset,
585			    &vd->vdev_dtl_smo, sm);
586	}
587
588	for (int c = 0; c < vd->vdev_children; c++)
589		dump_dtl(vd->vdev_child[c], indent + 4);
590}
591
592static void
593dump_history(spa_t *spa)
594{
595	nvlist_t **events = NULL;
596	char buf[SPA_MAXBLOCKSIZE];
597	uint64_t resid, len, off = 0;
598	uint_t num = 0;
599	int error;
600	time_t tsec;
601	struct tm t;
602	char tbuf[30];
603	char internalstr[MAXPATHLEN];
604
605	do {
606		len = sizeof (buf);
607
608		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
609			(void) fprintf(stderr, "Unable to read history: "
610			    "error %d\n", error);
611			return;
612		}
613
614		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
615			break;
616
617		off -= resid;
618	} while (len != 0);
619
620	(void) printf("\nHistory:\n");
621	for (int i = 0; i < num; i++) {
622		uint64_t time, txg, ievent;
623		char *cmd, *intstr;
624
625		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
626		    &time) != 0)
627			continue;
628		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
629		    &cmd) != 0) {
630			if (nvlist_lookup_uint64(events[i],
631			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
632				continue;
633			verify(nvlist_lookup_uint64(events[i],
634			    ZPOOL_HIST_TXG, &txg) == 0);
635			verify(nvlist_lookup_string(events[i],
636			    ZPOOL_HIST_INT_STR, &intstr) == 0);
637			if (ievent >= LOG_END)
638				continue;
639
640			(void) snprintf(internalstr,
641			    sizeof (internalstr),
642			    "[internal %s txg:%lld] %s",
643			    hist_event_table[ievent], txg,
644			    intstr);
645			cmd = internalstr;
646		}
647		tsec = time;
648		(void) localtime_r(&tsec, &t);
649		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
650		(void) printf("%s %s\n", tbuf, cmd);
651	}
652}
653
654/*ARGSUSED*/
655static void
656dump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
657{
658}
659
660static uint64_t
661blkid2offset(const dnode_phys_t *dnp, int level, uint64_t blkid)
662{
663	if (level < 0)
664		return (blkid);
665
666	return ((blkid << (level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
667	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
668}
669
670static void
671sprintf_blkptr_compact(char *blkbuf, blkptr_t *bp, int alldvas)
672{
673	dva_t *dva = bp->blk_dva;
674	int ndvas = alldvas ? BP_GET_NDVAS(bp) : 1;
675	int i;
676
677	blkbuf[0] = '\0';
678
679	for (i = 0; i < ndvas; i++)
680		(void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ",
681		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
682		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
683		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
684
685	(void) sprintf(blkbuf + strlen(blkbuf), "%llxL/%llxP F=%llu B=%llu",
686	    (u_longlong_t)BP_GET_LSIZE(bp),
687	    (u_longlong_t)BP_GET_PSIZE(bp),
688	    (u_longlong_t)bp->blk_fill,
689	    (u_longlong_t)bp->blk_birth);
690}
691
692static void
693print_indirect(blkptr_t *bp, const zbookmark_t *zb,
694    const dnode_phys_t *dnp)
695{
696	char blkbuf[BP_SPRINTF_LEN];
697	int l;
698
699	ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
700	ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
701
702	(void) printf("%16llx ",
703	    (u_longlong_t)blkid2offset(dnp, zb->zb_level, zb->zb_blkid));
704
705	ASSERT(zb->zb_level >= 0);
706
707	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
708		if (l == zb->zb_level) {
709			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
710		} else {
711			(void) printf(" ");
712		}
713	}
714
715	sprintf_blkptr_compact(blkbuf, bp, dump_opt['d'] > 5 ? 1 : 0);
716	(void) printf("%s\n", blkbuf);
717}
718
719#define	SET_BOOKMARK(zb, objset, object, level, blkid)  \
720{                                                       \
721	(zb)->zb_objset = objset;                       \
722	(zb)->zb_object = object;                       \
723	(zb)->zb_level = level;                         \
724	(zb)->zb_blkid = blkid;                         \
725}
726
727static int
728visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
729    blkptr_t *bp, const zbookmark_t *zb)
730{
731	int err = 0;
732
733	if (bp->blk_birth == 0)
734		return (0);
735
736	print_indirect(bp, zb, dnp);
737
738	if (BP_GET_LEVEL(bp) > 0) {
739		uint32_t flags = ARC_WAIT;
740		int i;
741		blkptr_t *cbp;
742		int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
743		arc_buf_t *buf;
744		uint64_t fill = 0;
745
746		err = arc_read_nolock(NULL, spa, bp, arc_getbuf_func, &buf,
747		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
748		if (err)
749			return (err);
750
751		/* recursively visit blocks below this */
752		cbp = buf->b_data;
753		for (i = 0; i < epb; i++, cbp++) {
754			zbookmark_t czb;
755
756			SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
757			    zb->zb_level - 1,
758			    zb->zb_blkid * epb + i);
759			err = visit_indirect(spa, dnp, cbp, &czb);
760			if (err)
761				break;
762			fill += cbp->blk_fill;
763		}
764		if (!err)
765			ASSERT3U(fill, ==, bp->blk_fill);
766		(void) arc_buf_remove_ref(buf, &buf);
767	}
768
769	return (err);
770}
771
772/*ARGSUSED*/
773static void
774dump_indirect(dnode_t *dn)
775{
776	dnode_phys_t *dnp = dn->dn_phys;
777	int j;
778	zbookmark_t czb;
779
780	(void) printf("Indirect blocks:\n");
781
782	SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset),
783	    dn->dn_object, dnp->dn_nlevels - 1, 0);
784	for (j = 0; j < dnp->dn_nblkptr; j++) {
785		czb.zb_blkid = j;
786		(void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp,
787		    &dnp->dn_blkptr[j], &czb);
788	}
789
790	(void) printf("\n");
791}
792
793/*ARGSUSED*/
794static void
795dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
796{
797	dsl_dir_phys_t *dd = data;
798	time_t crtime;
799	char nice[6];
800
801	if (dd == NULL)
802		return;
803
804	ASSERT3U(size, >=, sizeof (dsl_dir_phys_t));
805
806	crtime = dd->dd_creation_time;
807	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
808	(void) printf("\t\thead_dataset_obj = %llu\n",
809	    (u_longlong_t)dd->dd_head_dataset_obj);
810	(void) printf("\t\tparent_dir_obj = %llu\n",
811	    (u_longlong_t)dd->dd_parent_obj);
812	(void) printf("\t\torigin_obj = %llu\n",
813	    (u_longlong_t)dd->dd_origin_obj);
814	(void) printf("\t\tchild_dir_zapobj = %llu\n",
815	    (u_longlong_t)dd->dd_child_dir_zapobj);
816	nicenum(dd->dd_used_bytes, nice);
817	(void) printf("\t\tused_bytes = %s\n", nice);
818	nicenum(dd->dd_compressed_bytes, nice);
819	(void) printf("\t\tcompressed_bytes = %s\n", nice);
820	nicenum(dd->dd_uncompressed_bytes, nice);
821	(void) printf("\t\tuncompressed_bytes = %s\n", nice);
822	nicenum(dd->dd_quota, nice);
823	(void) printf("\t\tquota = %s\n", nice);
824	nicenum(dd->dd_reserved, nice);
825	(void) printf("\t\treserved = %s\n", nice);
826	(void) printf("\t\tprops_zapobj = %llu\n",
827	    (u_longlong_t)dd->dd_props_zapobj);
828	(void) printf("\t\tdeleg_zapobj = %llu\n",
829	    (u_longlong_t)dd->dd_deleg_zapobj);
830	(void) printf("\t\tflags = %llx\n",
831	    (u_longlong_t)dd->dd_flags);
832
833#define	DO(which) \
834	nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
835	(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
836	DO(HEAD);
837	DO(SNAP);
838	DO(CHILD);
839	DO(CHILD_RSRV);
840	DO(REFRSRV);
841#undef DO
842}
843
844/*ARGSUSED*/
845static void
846dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
847{
848	dsl_dataset_phys_t *ds = data;
849	time_t crtime;
850	char used[6], compressed[6], uncompressed[6], unique[6];
851	char blkbuf[BP_SPRINTF_LEN];
852
853	if (ds == NULL)
854		return;
855
856	ASSERT(size == sizeof (*ds));
857	crtime = ds->ds_creation_time;
858	nicenum(ds->ds_used_bytes, used);
859	nicenum(ds->ds_compressed_bytes, compressed);
860	nicenum(ds->ds_uncompressed_bytes, uncompressed);
861	nicenum(ds->ds_unique_bytes, unique);
862	sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, &ds->ds_bp);
863
864	(void) printf("\t\tdir_obj = %llu\n",
865	    (u_longlong_t)ds->ds_dir_obj);
866	(void) printf("\t\tprev_snap_obj = %llu\n",
867	    (u_longlong_t)ds->ds_prev_snap_obj);
868	(void) printf("\t\tprev_snap_txg = %llu\n",
869	    (u_longlong_t)ds->ds_prev_snap_txg);
870	(void) printf("\t\tnext_snap_obj = %llu\n",
871	    (u_longlong_t)ds->ds_next_snap_obj);
872	(void) printf("\t\tsnapnames_zapobj = %llu\n",
873	    (u_longlong_t)ds->ds_snapnames_zapobj);
874	(void) printf("\t\tnum_children = %llu\n",
875	    (u_longlong_t)ds->ds_num_children);
876	(void) printf("\t\tuserrefs_obj = %llu\n",
877	    (u_longlong_t)ds->ds_userrefs_obj);
878	(void) printf("\t\tcreation_time = %s", ctime(&crtime));
879	(void) printf("\t\tcreation_txg = %llu\n",
880	    (u_longlong_t)ds->ds_creation_txg);
881	(void) printf("\t\tdeadlist_obj = %llu\n",
882	    (u_longlong_t)ds->ds_deadlist_obj);
883	(void) printf("\t\tused_bytes = %s\n", used);
884	(void) printf("\t\tcompressed_bytes = %s\n", compressed);
885	(void) printf("\t\tuncompressed_bytes = %s\n", uncompressed);
886	(void) printf("\t\tunique = %s\n", unique);
887	(void) printf("\t\tfsid_guid = %llu\n",
888	    (u_longlong_t)ds->ds_fsid_guid);
889	(void) printf("\t\tguid = %llu\n",
890	    (u_longlong_t)ds->ds_guid);
891	(void) printf("\t\tflags = %llx\n",
892	    (u_longlong_t)ds->ds_flags);
893	(void) printf("\t\tnext_clones_obj = %llu\n",
894	    (u_longlong_t)ds->ds_next_clones_obj);
895	(void) printf("\t\tprops_obj = %llu\n",
896	    (u_longlong_t)ds->ds_props_obj);
897	(void) printf("\t\tbp = %s\n", blkbuf);
898}
899
900static void
901dump_bplist(objset_t *mos, uint64_t object, char *name)
902{
903	bplist_t bpl = { 0 };
904	blkptr_t blk, *bp = &blk;
905	uint64_t itor = 0;
906	char bytes[6];
907	char comp[6];
908	char uncomp[6];
909
910	if (dump_opt['d'] < 3)
911		return;
912
913	mutex_init(&bpl.bpl_lock, NULL, MUTEX_DEFAULT, NULL);
914	VERIFY(0 == bplist_open(&bpl, mos, object));
915	if (bplist_empty(&bpl)) {
916		bplist_close(&bpl);
917		mutex_destroy(&bpl.bpl_lock);
918		return;
919	}
920
921	nicenum(bpl.bpl_phys->bpl_bytes, bytes);
922	if (bpl.bpl_dbuf->db_size == sizeof (bplist_phys_t)) {
923		nicenum(bpl.bpl_phys->bpl_comp, comp);
924		nicenum(bpl.bpl_phys->bpl_uncomp, uncomp);
925		(void) printf("\n    %s: %llu entries, %s (%s/%s comp)\n",
926		    name, (u_longlong_t)bpl.bpl_phys->bpl_entries,
927		    bytes, comp, uncomp);
928	} else {
929		(void) printf("\n    %s: %llu entries, %s\n",
930		    name, (u_longlong_t)bpl.bpl_phys->bpl_entries, bytes);
931	}
932
933	if (dump_opt['d'] < 5) {
934		bplist_close(&bpl);
935		mutex_destroy(&bpl.bpl_lock);
936		return;
937	}
938
939	(void) printf("\n");
940
941	while (bplist_iterate(&bpl, &itor, bp) == 0) {
942		char blkbuf[BP_SPRINTF_LEN];
943
944		ASSERT(bp->blk_birth != 0);
945		sprintf_blkptr_compact(blkbuf, bp, dump_opt['d'] > 5 ? 1 : 0);
946		(void) printf("\tItem %3llu: %s\n",
947		    (u_longlong_t)itor - 1, blkbuf);
948	}
949
950	bplist_close(&bpl);
951	mutex_destroy(&bpl.bpl_lock);
952}
953
954static avl_tree_t idx_tree;
955static avl_tree_t domain_tree;
956static boolean_t fuid_table_loaded;
957
958static void
959fuid_table_destroy()
960{
961	if (fuid_table_loaded) {
962		zfs_fuid_table_destroy(&idx_tree, &domain_tree);
963		fuid_table_loaded = B_FALSE;
964	}
965}
966
967/*
968 * print uid or gid information.
969 * For normal POSIX id just the id is printed in decimal format.
970 * For CIFS files with FUID the fuid is printed in hex followed by
971 * the doman-rid string.
972 */
973static void
974print_idstr(uint64_t id, const char *id_type)
975{
976	if (FUID_INDEX(id)) {
977		char *domain;
978
979		domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id));
980		(void) printf("\t%s     %llx [%s-%d]\n", id_type,
981		    (u_longlong_t)id, domain, (int)FUID_RID(id));
982	} else {
983		(void) printf("\t%s     %llu\n", id_type, (u_longlong_t)id);
984	}
985
986}
987
988static void
989dump_uidgid(objset_t *os, znode_phys_t *zp)
990{
991	uint32_t uid_idx, gid_idx;
992
993	uid_idx = FUID_INDEX(zp->zp_uid);
994	gid_idx = FUID_INDEX(zp->zp_gid);
995
996	/* Load domain table, if not already loaded */
997	if (!fuid_table_loaded && (uid_idx || gid_idx)) {
998		uint64_t fuid_obj;
999
1000		/* first find the fuid object.  It lives in the master node */
1001		VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
1002		    8, 1, &fuid_obj) == 0);
1003		zfs_fuid_avl_tree_create(&idx_tree, &domain_tree);
1004		(void) zfs_fuid_table_load(os, fuid_obj,
1005		    &idx_tree, &domain_tree);
1006		fuid_table_loaded = B_TRUE;
1007	}
1008
1009	print_idstr(zp->zp_uid, "uid");
1010	print_idstr(zp->zp_gid, "gid");
1011}
1012
1013/*ARGSUSED*/
1014static void
1015dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
1016{
1017	znode_phys_t *zp = data;
1018	time_t z_crtime, z_atime, z_mtime, z_ctime;
1019	char path[MAXPATHLEN * 2];	/* allow for xattr and failure prefix */
1020	int error;
1021
1022	ASSERT(size >= sizeof (znode_phys_t));
1023
1024	error = zfs_obj_to_path(os, object, path, sizeof (path));
1025	if (error != 0) {
1026		(void) snprintf(path, sizeof (path), "\?\?\?<object#%llu>",
1027		    (u_longlong_t)object);
1028	}
1029
1030	if (dump_opt['d'] < 3) {
1031		(void) printf("\t%s\n", path);
1032		return;
1033	}
1034
1035	z_crtime = (time_t)zp->zp_crtime[0];
1036	z_atime = (time_t)zp->zp_atime[0];
1037	z_mtime = (time_t)zp->zp_mtime[0];
1038	z_ctime = (time_t)zp->zp_ctime[0];
1039
1040	(void) printf("\tpath	%s\n", path);
1041	dump_uidgid(os, zp);
1042	(void) printf("\tatime	%s", ctime(&z_atime));
1043	(void) printf("\tmtime	%s", ctime(&z_mtime));
1044	(void) printf("\tctime	%s", ctime(&z_ctime));
1045	(void) printf("\tcrtime	%s", ctime(&z_crtime));
1046	(void) printf("\tgen	%llu\n", (u_longlong_t)zp->zp_gen);
1047	(void) printf("\tmode	%llo\n", (u_longlong_t)zp->zp_mode);
1048	(void) printf("\tsize	%llu\n", (u_longlong_t)zp->zp_size);
1049	(void) printf("\tparent	%llu\n", (u_longlong_t)zp->zp_parent);
1050	(void) printf("\tlinks	%llu\n", (u_longlong_t)zp->zp_links);
1051	(void) printf("\txattr	%llu\n", (u_longlong_t)zp->zp_xattr);
1052	(void) printf("\trdev	0x%016llx\n", (u_longlong_t)zp->zp_rdev);
1053}
1054
1055/*ARGSUSED*/
1056static void
1057dump_acl(objset_t *os, uint64_t object, void *data, size_t size)
1058{
1059}
1060
1061/*ARGSUSED*/
1062static void
1063dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
1064{
1065}
1066
1067static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
1068	dump_none,		/* unallocated			*/
1069	dump_zap,		/* object directory		*/
1070	dump_uint64,		/* object array			*/
1071	dump_none,		/* packed nvlist		*/
1072	dump_packed_nvlist,	/* packed nvlist size		*/
1073	dump_none,		/* bplist			*/
1074	dump_none,		/* bplist header		*/
1075	dump_none,		/* SPA space map header		*/
1076	dump_none,		/* SPA space map		*/
1077	dump_none,		/* ZIL intent log		*/
1078	dump_dnode,		/* DMU dnode			*/
1079	dump_dmu_objset,	/* DMU objset			*/
1080	dump_dsl_dir,		/* DSL directory		*/
1081	dump_zap,		/* DSL directory child map	*/
1082	dump_zap,		/* DSL dataset snap map		*/
1083	dump_zap,		/* DSL props			*/
1084	dump_dsl_dataset,	/* DSL dataset			*/
1085	dump_znode,		/* ZFS znode			*/
1086	dump_acl,		/* ZFS V0 ACL			*/
1087	dump_uint8,		/* ZFS plain file		*/
1088	dump_zpldir,		/* ZFS directory		*/
1089	dump_zap,		/* ZFS master node		*/
1090	dump_zap,		/* ZFS delete queue		*/
1091	dump_uint8,		/* zvol object			*/
1092	dump_zap,		/* zvol prop			*/
1093	dump_uint8,		/* other uint8[]		*/
1094	dump_uint64,		/* other uint64[]		*/
1095	dump_zap,		/* other ZAP			*/
1096	dump_zap,		/* persistent error log		*/
1097	dump_uint8,		/* SPA history			*/
1098	dump_uint64,		/* SPA history offsets		*/
1099	dump_zap,		/* Pool properties		*/
1100	dump_zap,		/* DSL permissions		*/
1101	dump_acl,		/* ZFS ACL			*/
1102	dump_uint8,		/* ZFS SYSACL			*/
1103	dump_none,		/* FUID nvlist			*/
1104	dump_packed_nvlist,	/* FUID nvlist size		*/
1105	dump_zap,		/* DSL dataset next clones	*/
1106	dump_zap,		/* DSL scrub queue		*/
1107	dump_zap,		/* ZFS user/group used		*/
1108	dump_zap,		/* ZFS user/group quota		*/
1109	dump_zap,		/* snapshot refcount tags	*/
1110	dump_unknown		/* Unknown type, must be last	*/
1111};
1112
1113static void
1114dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
1115{
1116	dmu_buf_t *db = NULL;
1117	dmu_object_info_t doi;
1118	dnode_t *dn;
1119	void *bonus = NULL;
1120	size_t bsize = 0;
1121	char iblk[6], dblk[6], lsize[6], asize[6], bonus_size[6], segsize[6];
1122	char aux[50];
1123	int error;
1124
1125	if (*print_header) {
1126		(void) printf("\n    Object  lvl   iblk   dblk  lsize"
1127		    "  asize  type\n");
1128		*print_header = 0;
1129	}
1130
1131	if (object == 0) {
1132		dn = os->os_meta_dnode;
1133	} else {
1134		error = dmu_bonus_hold(os, object, FTAG, &db);
1135		if (error)
1136			fatal("dmu_bonus_hold(%llu) failed, errno %u",
1137			    object, error);
1138		bonus = db->db_data;
1139		bsize = db->db_size;
1140		dn = ((dmu_buf_impl_t *)db)->db_dnode;
1141	}
1142	dmu_object_info_from_dnode(dn, &doi);
1143
1144	nicenum(doi.doi_metadata_block_size, iblk);
1145	nicenum(doi.doi_data_block_size, dblk);
1146	nicenum(doi.doi_data_block_size * (doi.doi_max_block_offset + 1),
1147	    lsize);
1148	nicenum(doi.doi_physical_blks << 9, asize);
1149	nicenum(doi.doi_bonus_size, bonus_size);
1150
1151	aux[0] = '\0';
1152
1153	if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) {
1154		(void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)",
1155		    ZDB_CHECKSUM_NAME(doi.doi_checksum));
1156	}
1157
1158	if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) {
1159		(void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)",
1160		    ZDB_COMPRESS_NAME(doi.doi_compress));
1161	}
1162
1163	(void) printf("%10lld  %3u  %5s  %5s  %5s  %5s  %s%s\n",
1164	    (u_longlong_t)object, doi.doi_indirection, iblk, dblk, lsize,
1165	    asize, ZDB_OT_NAME(doi.doi_type), aux);
1166
1167	if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) {
1168		(void) printf("%10s  %3s  %5s  %5s  %5s  %5s  %s\n",
1169		    "", "", "", "", bonus_size, "bonus",
1170		    ZDB_OT_NAME(doi.doi_bonus_type));
1171	}
1172
1173	if (verbosity >= 4) {
1174		(void) printf("\tdnode flags: %s%s\n",
1175		    (dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) ?
1176		    "USED_BYTES " : "",
1177		    (dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED) ?
1178		    "USERUSED_ACCOUNTED " : "");
1179		(void) printf("\tdnode maxblkid: %llu\n",
1180		    (longlong_t)dn->dn_phys->dn_maxblkid);
1181
1182		object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object,
1183		    bonus, bsize);
1184		object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
1185		*print_header = 1;
1186	}
1187
1188	if (verbosity >= 5)
1189		dump_indirect(dn);
1190
1191	if (verbosity >= 5) {
1192		/*
1193		 * Report the list of segments that comprise the object.
1194		 */
1195		uint64_t start = 0;
1196		uint64_t end;
1197		uint64_t blkfill = 1;
1198		int minlvl = 1;
1199
1200		if (dn->dn_type == DMU_OT_DNODE) {
1201			minlvl = 0;
1202			blkfill = DNODES_PER_BLOCK;
1203		}
1204
1205		for (;;) {
1206			error = dnode_next_offset(dn,
1207			    0, &start, minlvl, blkfill, 0);
1208			if (error)
1209				break;
1210			end = start;
1211			error = dnode_next_offset(dn,
1212			    DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
1213			nicenum(end - start, segsize);
1214			(void) printf("\t\tsegment [%016llx, %016llx)"
1215			    " size %5s\n", (u_longlong_t)start,
1216			    (u_longlong_t)end, segsize);
1217			if (error)
1218				break;
1219			start = end;
1220		}
1221	}
1222
1223	if (db != NULL)
1224		dmu_buf_rele(db, FTAG);
1225}
1226
1227static char *objset_types[DMU_OST_NUMTYPES] = {
1228	"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
1229
1230static void
1231dump_dir(objset_t *os)
1232{
1233	dmu_objset_stats_t dds;
1234	uint64_t object, object_count;
1235	uint64_t refdbytes, usedobjs, scratch;
1236	char numbuf[8];
1237	char blkbuf[BP_SPRINTF_LEN + 20];
1238	char osname[MAXNAMELEN];
1239	char *type = "UNKNOWN";
1240	int verbosity = dump_opt['d'];
1241	int print_header = 1;
1242	int i, error;
1243
1244	dmu_objset_fast_stat(os, &dds);
1245
1246	if (dds.dds_type < DMU_OST_NUMTYPES)
1247		type = objset_types[dds.dds_type];
1248
1249	if (dds.dds_type == DMU_OST_META) {
1250		dds.dds_creation_txg = TXG_INITIAL;
1251		usedobjs = os->os_rootbp->blk_fill;
1252		refdbytes = os->os_spa->spa_dsl_pool->
1253		    dp_mos_dir->dd_phys->dd_used_bytes;
1254	} else {
1255		dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch);
1256	}
1257
1258	ASSERT3U(usedobjs, ==, os->os_rootbp->blk_fill);
1259
1260	nicenum(refdbytes, numbuf);
1261
1262	if (verbosity >= 4) {
1263		(void) sprintf(blkbuf, ", rootbp ");
1264		(void) sprintf_blkptr(blkbuf + strlen(blkbuf),
1265		    BP_SPRINTF_LEN - strlen(blkbuf), os->os_rootbp);
1266	} else {
1267		blkbuf[0] = '\0';
1268	}
1269
1270	dmu_objset_name(os, osname);
1271
1272	(void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, "
1273	    "%s, %llu objects%s\n",
1274	    osname, type, (u_longlong_t)dmu_objset_id(os),
1275	    (u_longlong_t)dds.dds_creation_txg,
1276	    numbuf, (u_longlong_t)usedobjs, blkbuf);
1277
1278	dump_intent_log(dmu_objset_zil(os));
1279
1280	if (dmu_objset_ds(os) != NULL)
1281		dump_bplist(dmu_objset_pool(os)->dp_meta_objset,
1282		    dmu_objset_ds(os)->ds_phys->ds_deadlist_obj, "Deadlist");
1283
1284	if (verbosity < 2)
1285		return;
1286
1287	if (os->os_rootbp->blk_birth == 0)
1288		return;
1289
1290	if (zopt_objects != 0) {
1291		for (i = 0; i < zopt_objects; i++)
1292			dump_object(os, zopt_object[i], verbosity,
1293			    &print_header);
1294		(void) printf("\n");
1295		return;
1296	}
1297
1298	dump_object(os, 0, verbosity, &print_header);
1299	object_count = 0;
1300	if (os->os_userused_dnode &&
1301	    os->os_userused_dnode->dn_type != 0) {
1302		dump_object(os, DMU_USERUSED_OBJECT, verbosity, &print_header);
1303		dump_object(os, DMU_GROUPUSED_OBJECT, verbosity, &print_header);
1304	}
1305
1306	object = 0;
1307	while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) {
1308		dump_object(os, object, verbosity, &print_header);
1309		object_count++;
1310	}
1311
1312	ASSERT3U(object_count, ==, usedobjs);
1313
1314	(void) printf("\n");
1315
1316	if (error != ESRCH) {
1317		(void) fprintf(stderr, "dmu_object_next() = %d\n", error);
1318		abort();
1319	}
1320}
1321
1322static void
1323dump_uberblock(uberblock_t *ub)
1324{
1325	time_t timestamp = ub->ub_timestamp;
1326
1327	(void) printf("\nUberblock:\n");
1328	(void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic);
1329	(void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version);
1330	(void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg);
1331	(void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum);
1332	(void) printf("\ttimestamp = %llu UTC = %s",
1333	    (u_longlong_t)ub->ub_timestamp, asctime(localtime(&timestamp)));
1334	if (dump_opt['u'] >= 3) {
1335		char blkbuf[BP_SPRINTF_LEN];
1336		sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, &ub->ub_rootbp);
1337		(void) printf("\trootbp = %s\n", blkbuf);
1338	}
1339	(void) printf("\n");
1340}
1341
1342static void
1343dump_config(spa_t *spa)
1344{
1345	dmu_buf_t *db;
1346	size_t nvsize = 0;
1347	int error = 0;
1348
1349
1350	error = dmu_bonus_hold(spa->spa_meta_objset,
1351	    spa->spa_config_object, FTAG, &db);
1352
1353	if (error == 0) {
1354		nvsize = *(uint64_t *)db->db_data;
1355		dmu_buf_rele(db, FTAG);
1356
1357		(void) printf("\nMOS Configuration:\n");
1358		dump_packed_nvlist(spa->spa_meta_objset,
1359		    spa->spa_config_object, (void *)&nvsize, 1);
1360	} else {
1361		(void) fprintf(stderr, "dmu_bonus_hold(%llu) failed, errno %d",
1362		    (u_longlong_t)spa->spa_config_object, error);
1363	}
1364}
1365
1366static void
1367dump_cachefile(const char *cachefile)
1368{
1369	int fd;
1370	struct stat64 statbuf;
1371	char *buf;
1372	nvlist_t *config;
1373
1374	if ((fd = open64(cachefile, O_RDONLY)) < 0) {
1375		(void) printf("cannot open '%s': %s\n", cachefile,
1376		    strerror(errno));
1377		exit(1);
1378	}
1379
1380	if (fstat64(fd, &statbuf) != 0) {
1381		(void) printf("failed to stat '%s': %s\n", cachefile,
1382		    strerror(errno));
1383		exit(1);
1384	}
1385
1386	if ((buf = malloc(statbuf.st_size)) == NULL) {
1387		(void) fprintf(stderr, "failed to allocate %llu bytes\n",
1388		    (u_longlong_t)statbuf.st_size);
1389		exit(1);
1390	}
1391
1392	if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
1393		(void) fprintf(stderr, "failed to read %llu bytes\n",
1394		    (u_longlong_t)statbuf.st_size);
1395		exit(1);
1396	}
1397
1398	(void) close(fd);
1399
1400	if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
1401		(void) fprintf(stderr, "failed to unpack nvlist\n");
1402		exit(1);
1403	}
1404
1405	free(buf);
1406
1407	dump_nvlist(config, 0);
1408
1409	nvlist_free(config);
1410}
1411
1412static void
1413dump_label(const char *dev)
1414{
1415	int fd;
1416	vdev_label_t label;
1417	char *buf = label.vl_vdev_phys.vp_nvlist;
1418	size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
1419	struct stat64 statbuf;
1420	uint64_t psize;
1421	int l;
1422
1423	if ((fd = open64(dev, O_RDONLY)) < 0) {
1424		(void) printf("cannot open '%s': %s\n", dev, strerror(errno));
1425		exit(1);
1426	}
1427
1428	if (fstat64(fd, &statbuf) != 0) {
1429		(void) printf("failed to stat '%s': %s\n", dev,
1430		    strerror(errno));
1431		exit(1);
1432	}
1433
1434	psize = statbuf.st_size;
1435	psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
1436
1437	for (l = 0; l < VDEV_LABELS; l++) {
1438
1439		nvlist_t *config = NULL;
1440
1441		(void) printf("--------------------------------------------\n");
1442		(void) printf("LABEL %d\n", l);
1443		(void) printf("--------------------------------------------\n");
1444
1445		if (pread64(fd, &label, sizeof (label),
1446		    vdev_label_offset(psize, l, 0)) != sizeof (label)) {
1447			(void) printf("failed to read label %d\n", l);
1448			continue;
1449		}
1450
1451		if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
1452			(void) printf("failed to unpack label %d\n", l);
1453			continue;
1454		}
1455		dump_nvlist(config, 4);
1456		nvlist_free(config);
1457	}
1458}
1459
1460/*ARGSUSED*/
1461static int
1462dump_one_dir(char *dsname, void *arg)
1463{
1464	int error;
1465	objset_t *os;
1466
1467	error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
1468	if (error) {
1469		(void) printf("Could not open %s\n", dsname);
1470		return (0);
1471	}
1472	dump_dir(os);
1473	dmu_objset_disown(os, FTAG);
1474	fuid_table_destroy();
1475	return (0);
1476}
1477
1478static void
1479zdb_leak(space_map_t *sm, uint64_t start, uint64_t size)
1480{
1481	vdev_t *vd = sm->sm_ppd;
1482
1483	(void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n",
1484	    (u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size);
1485}
1486
1487/* ARGSUSED */
1488static void
1489zdb_space_map_load(space_map_t *sm)
1490{
1491}
1492
1493static void
1494zdb_space_map_unload(space_map_t *sm)
1495{
1496	space_map_vacate(sm, zdb_leak, sm);
1497}
1498
1499/* ARGSUSED */
1500static void
1501zdb_space_map_claim(space_map_t *sm, uint64_t start, uint64_t size)
1502{
1503}
1504
1505static space_map_ops_t zdb_space_map_ops = {
1506	zdb_space_map_load,
1507	zdb_space_map_unload,
1508	NULL,	/* alloc */
1509	zdb_space_map_claim,
1510	NULL,	/* free */
1511	NULL	/* maxsize */
1512};
1513
1514static void
1515zdb_leak_init(spa_t *spa)
1516{
1517	vdev_t *rvd = spa->spa_root_vdev;
1518
1519	for (int c = 0; c < rvd->vdev_children; c++) {
1520		vdev_t *vd = rvd->vdev_child[c];
1521		for (int m = 0; m < vd->vdev_ms_count; m++) {
1522			metaslab_t *msp = vd->vdev_ms[m];
1523			mutex_enter(&msp->ms_lock);
1524			VERIFY(space_map_load(&msp->ms_map, &zdb_space_map_ops,
1525			    SM_ALLOC, &msp->ms_smo, spa->spa_meta_objset) == 0);
1526			msp->ms_map.sm_ppd = vd;
1527			mutex_exit(&msp->ms_lock);
1528		}
1529	}
1530}
1531
1532static void
1533zdb_leak_fini(spa_t *spa)
1534{
1535	vdev_t *rvd = spa->spa_root_vdev;
1536
1537	for (int c = 0; c < rvd->vdev_children; c++) {
1538		vdev_t *vd = rvd->vdev_child[c];
1539		for (int m = 0; m < vd->vdev_ms_count; m++) {
1540			metaslab_t *msp = vd->vdev_ms[m];
1541			mutex_enter(&msp->ms_lock);
1542			space_map_unload(&msp->ms_map);
1543			mutex_exit(&msp->ms_lock);
1544		}
1545	}
1546}
1547
1548/*
1549 * Verify that the sum of the sizes of all blocks in the pool adds up
1550 * to the SPA's sa_alloc total.
1551 */
1552typedef struct zdb_blkstats {
1553	uint64_t	zb_asize;
1554	uint64_t	zb_lsize;
1555	uint64_t	zb_psize;
1556	uint64_t	zb_count;
1557} zdb_blkstats_t;
1558
1559#define	DMU_OT_DEFERRED	DMU_OT_NONE
1560#define	DMU_OT_TOTAL	DMU_OT_NUMTYPES
1561
1562#define	ZB_TOTAL	DN_MAX_LEVELS
1563
1564typedef struct zdb_cb {
1565	zdb_blkstats_t	zcb_type[ZB_TOTAL + 1][DMU_OT_TOTAL + 1];
1566	uint64_t	zcb_errors[256];
1567	int		zcb_readfails;
1568	int		zcb_haderrors;
1569} zdb_cb_t;
1570
1571static void
1572zdb_count_block(spa_t *spa, zdb_cb_t *zcb, blkptr_t *bp, dmu_object_type_t type)
1573{
1574	for (int i = 0; i < 4; i++) {
1575		int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL;
1576		int t = (i & 1) ? type : DMU_OT_TOTAL;
1577		zdb_blkstats_t *zb = &zcb->zcb_type[l][t];
1578
1579		zb->zb_asize += BP_GET_ASIZE(bp);
1580		zb->zb_lsize += BP_GET_LSIZE(bp);
1581		zb->zb_psize += BP_GET_PSIZE(bp);
1582		zb->zb_count++;
1583	}
1584
1585	if (dump_opt['S']) {
1586		boolean_t print_sig;
1587
1588		print_sig = !zdb_sig_user_data || (BP_GET_LEVEL(bp) == 0 &&
1589		    BP_GET_TYPE(bp) == DMU_OT_PLAIN_FILE_CONTENTS);
1590
1591		if (BP_GET_CHECKSUM(bp) < zdb_sig_cksumalg)
1592			print_sig = B_FALSE;
1593
1594		if (print_sig) {
1595			(void) printf("%llu\t%lld\t%lld\t%s\t%s\t%s\t"
1596			    "%llx:%llx:%llx:%llx\n",
1597			    (u_longlong_t)BP_GET_LEVEL(bp),
1598			    (longlong_t)BP_GET_PSIZE(bp),
1599			    (longlong_t)BP_GET_NDVAS(bp),
1600			    ZDB_OT_NAME(BP_GET_TYPE(bp)),
1601			    ZDB_CHECKSUM_NAME(BP_GET_CHECKSUM(bp)),
1602			    ZDB_COMPRESS_NAME(BP_GET_COMPRESS(bp)),
1603			    (u_longlong_t)bp->blk_cksum.zc_word[0],
1604			    (u_longlong_t)bp->blk_cksum.zc_word[1],
1605			    (u_longlong_t)bp->blk_cksum.zc_word[2],
1606			    (u_longlong_t)bp->blk_cksum.zc_word[3]);
1607		}
1608	}
1609
1610	if (!dump_opt['L'])
1611		VERIFY(zio_wait(zio_claim(NULL, spa, spa_first_txg(spa), bp,
1612		    NULL, NULL, ZIO_FLAG_MUSTSUCCEED)) == 0);
1613}
1614
1615static int
1616zdb_blkptr_cb(spa_t *spa, blkptr_t *bp, const zbookmark_t *zb,
1617    const dnode_phys_t *dnp, void *arg)
1618{
1619	zdb_cb_t *zcb = arg;
1620	char blkbuf[BP_SPRINTF_LEN];
1621	dmu_object_type_t type;
1622	boolean_t is_l0_metadata;
1623
1624	if (bp == NULL)
1625		return (0);
1626
1627	type = BP_GET_TYPE(bp);
1628
1629	zdb_count_block(spa, zcb, bp, type);
1630
1631	/*
1632	 * if we do metadata-only checksumming there's no need to checksum
1633	 * indirect blocks here because it is done during traverse
1634	 */
1635	is_l0_metadata = (BP_GET_LEVEL(bp) == 0 && type < DMU_OT_NUMTYPES &&
1636	    dmu_ot[type].ot_metadata);
1637
1638	if (dump_opt['c'] > 1 || dump_opt['S'] ||
1639	    (dump_opt['c'] && is_l0_metadata)) {
1640		int ioerr, size;
1641		void *data;
1642
1643		size = BP_GET_LSIZE(bp);
1644		data = malloc(size);
1645		ioerr = zio_wait(zio_read(NULL, spa, bp, data, size,
1646		    NULL, NULL, ZIO_PRIORITY_ASYNC_READ,
1647		    ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB, zb));
1648		free(data);
1649
1650		/* We expect io errors on intent log */
1651		if (ioerr && type != DMU_OT_INTENT_LOG) {
1652			zcb->zcb_haderrors = 1;
1653			zcb->zcb_errors[ioerr]++;
1654
1655			if (dump_opt['b'] >= 2)
1656				sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, bp);
1657			else
1658				blkbuf[0] = '\0';
1659
1660			if (!dump_opt['S']) {
1661				(void) printf("zdb_blkptr_cb: "
1662				    "Got error %d reading "
1663				    "<%llu, %llu, %lld, %llx> %s -- skipping\n",
1664				    ioerr,
1665				    (u_longlong_t)zb->zb_objset,
1666				    (u_longlong_t)zb->zb_object,
1667				    (u_longlong_t)zb->zb_level,
1668				    (u_longlong_t)zb->zb_blkid,
1669				    blkbuf);
1670			}
1671		}
1672	}
1673
1674	zcb->zcb_readfails = 0;
1675
1676	if (dump_opt['b'] >= 4) {
1677		sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, bp);
1678		(void) printf("objset %llu object %llu offset 0x%llx %s\n",
1679		    (u_longlong_t)zb->zb_objset,
1680		    (u_longlong_t)zb->zb_object,
1681		    (u_longlong_t)blkid2offset(dnp, zb->zb_level, zb->zb_blkid),
1682		    blkbuf);
1683	}
1684
1685	return (0);
1686}
1687
1688static int
1689dump_block_stats(spa_t *spa)
1690{
1691	zdb_cb_t zcb = { 0 };
1692	zdb_blkstats_t *zb, *tzb;
1693	uint64_t alloc, space, logalloc;
1694	vdev_t *rvd = spa->spa_root_vdev;
1695	int leaks = 0;
1696	int c, e;
1697
1698	if (!dump_opt['S']) {
1699		(void) printf("\nTraversing all blocks %s%s%s%s%s...\n",
1700		    (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "",
1701		    (dump_opt['c'] == 1) ? "metadata " : "",
1702		    dump_opt['c'] ? "checksums " : "",
1703		    (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "",
1704		    !dump_opt['L'] ? "nothing leaked " : "");
1705	}
1706
1707	/*
1708	 * Load all space maps as SM_ALLOC maps, then traverse the pool
1709	 * claiming each block we discover.  If the pool is perfectly
1710	 * consistent, the space maps will be empty when we're done.
1711	 * Anything left over is a leak; any block we can't claim (because
1712	 * it's not part of any space map) is a double allocation,
1713	 * reference to a freed block, or an unclaimed log block.
1714	 */
1715	if (!dump_opt['L'])
1716		zdb_leak_init(spa);
1717
1718	/*
1719	 * If there's a deferred-free bplist, process that first.
1720	 */
1721	if (spa->spa_sync_bplist_obj != 0) {
1722		bplist_t *bpl = &spa->spa_sync_bplist;
1723		blkptr_t blk;
1724		uint64_t itor = 0;
1725
1726		VERIFY(0 == bplist_open(bpl, spa->spa_meta_objset,
1727		    spa->spa_sync_bplist_obj));
1728
1729		while (bplist_iterate(bpl, &itor, &blk) == 0) {
1730			if (dump_opt['b'] >= 4) {
1731				char blkbuf[BP_SPRINTF_LEN];
1732				sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, &blk);
1733				(void) printf("[%s] %s\n",
1734				    "deferred free", blkbuf);
1735			}
1736			zdb_count_block(spa, &zcb, &blk, DMU_OT_DEFERRED);
1737		}
1738
1739		bplist_close(bpl);
1740	}
1741
1742	zcb.zcb_haderrors |= traverse_pool(spa, zdb_blkptr_cb, &zcb);
1743
1744	if (zcb.zcb_haderrors && !dump_opt['S']) {
1745		(void) printf("\nError counts:\n\n");
1746		(void) printf("\t%5s  %s\n", "errno", "count");
1747		for (e = 0; e < 256; e++) {
1748			if (zcb.zcb_errors[e] != 0) {
1749				(void) printf("\t%5d  %llu\n",
1750				    e, (u_longlong_t)zcb.zcb_errors[e]);
1751			}
1752		}
1753	}
1754
1755	/*
1756	 * Report any leaked segments.
1757	 */
1758	if (!dump_opt['L'])
1759		zdb_leak_fini(spa);
1760
1761	/*
1762	 * If we're interested in printing out the blkptr signatures,
1763	 * return now as we don't print out anything else (including
1764	 * errors and leaks).
1765	 */
1766	if (dump_opt['S'])
1767		return (zcb.zcb_haderrors ? 3 : 0);
1768
1769	alloc = spa_get_alloc(spa);
1770	space = spa_get_space(spa);
1771
1772	/*
1773	 * Log blocks allocated from a separate log device don't count
1774	 * as part of the normal pool space; factor them in here.
1775	 */
1776	logalloc = 0;
1777
1778	for (c = 0; c < rvd->vdev_children; c++)
1779		if (rvd->vdev_child[c]->vdev_islog)
1780			logalloc += rvd->vdev_child[c]->vdev_stat.vs_alloc;
1781
1782	tzb = &zcb.zcb_type[ZB_TOTAL][DMU_OT_TOTAL];
1783
1784	if (tzb->zb_asize == alloc + logalloc) {
1785		if (!dump_opt['L'])
1786			(void) printf("\n\tNo leaks (block sum matches space"
1787			    " maps exactly)\n");
1788	} else {
1789		(void) printf("block traversal size %llu != alloc %llu "
1790		    "(%s %lld)\n",
1791		    (u_longlong_t)tzb->zb_asize,
1792		    (u_longlong_t)alloc + logalloc,
1793		    (dump_opt['L']) ? "unreachable" : "leaked",
1794		    (longlong_t)(alloc + logalloc - tzb->zb_asize));
1795		leaks = 1;
1796	}
1797
1798	if (tzb->zb_count == 0)
1799		return (2);
1800
1801	(void) printf("\n");
1802	(void) printf("\tbp count:      %10llu\n",
1803	    (u_longlong_t)tzb->zb_count);
1804	(void) printf("\tbp logical:    %10llu\t avg: %6llu\n",
1805	    (u_longlong_t)tzb->zb_lsize,
1806	    (u_longlong_t)(tzb->zb_lsize / tzb->zb_count));
1807	(void) printf("\tbp physical:   %10llu\t avg:"
1808	    " %6llu\tcompression: %6.2f\n",
1809	    (u_longlong_t)tzb->zb_psize,
1810	    (u_longlong_t)(tzb->zb_psize / tzb->zb_count),
1811	    (double)tzb->zb_lsize / tzb->zb_psize);
1812	(void) printf("\tbp allocated:  %10llu\t avg:"
1813	    " %6llu\tcompression: %6.2f\n",
1814	    (u_longlong_t)tzb->zb_asize,
1815	    (u_longlong_t)(tzb->zb_asize / tzb->zb_count),
1816	    (double)tzb->zb_lsize / tzb->zb_asize);
1817	(void) printf("\tSPA allocated: %10llu\tused: %5.2f%%\n",
1818	    (u_longlong_t)alloc, 100.0 * alloc / space);
1819
1820	if (dump_opt['b'] >= 2) {
1821		int l, t, level;
1822		(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
1823		    "\t  avg\t comp\t%%Total\tType\n");
1824
1825		for (t = 0; t <= DMU_OT_NUMTYPES; t++) {
1826			char csize[6], lsize[6], psize[6], asize[6], avg[6];
1827			char *typename;
1828
1829			typename = t == DMU_OT_DEFERRED ? "deferred free" :
1830			    t == DMU_OT_TOTAL ? "Total" : dmu_ot[t].ot_name;
1831
1832			if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) {
1833				(void) printf("%6s\t%5s\t%5s\t%5s"
1834				    "\t%5s\t%5s\t%6s\t%s\n",
1835				    "-",
1836				    "-",
1837				    "-",
1838				    "-",
1839				    "-",
1840				    "-",
1841				    "-",
1842				    typename);
1843				continue;
1844			}
1845
1846			for (l = ZB_TOTAL - 1; l >= -1; l--) {
1847				level = (l == -1 ? ZB_TOTAL : l);
1848				zb = &zcb.zcb_type[level][t];
1849
1850				if (zb->zb_asize == 0)
1851					continue;
1852
1853				if (dump_opt['b'] < 3 && level != ZB_TOTAL)
1854					continue;
1855
1856				if (level == 0 && zb->zb_asize ==
1857				    zcb.zcb_type[ZB_TOTAL][t].zb_asize)
1858					continue;
1859
1860				nicenum(zb->zb_count, csize);
1861				nicenum(zb->zb_lsize, lsize);
1862				nicenum(zb->zb_psize, psize);
1863				nicenum(zb->zb_asize, asize);
1864				nicenum(zb->zb_asize / zb->zb_count, avg);
1865
1866				(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
1867				    "\t%5.2f\t%6.2f\t",
1868				    csize, lsize, psize, asize, avg,
1869				    (double)zb->zb_lsize / zb->zb_psize,
1870				    100.0 * zb->zb_asize / tzb->zb_asize);
1871
1872				if (level == ZB_TOTAL)
1873					(void) printf("%s\n", typename);
1874				else
1875					(void) printf("    L%d %s\n",
1876					    level, typename);
1877			}
1878		}
1879	}
1880
1881	(void) printf("\n");
1882
1883	if (leaks)
1884		return (2);
1885
1886	if (zcb.zcb_haderrors)
1887		return (3);
1888
1889	return (0);
1890}
1891
1892static void
1893dump_zpool(spa_t *spa)
1894{
1895	dsl_pool_t *dp = spa_get_dsl(spa);
1896	int rc = 0;
1897
1898	if (!dump_opt['e'] && dump_opt['C'] > 1) {
1899		(void) printf("\nCached configuration:\n");
1900		dump_nvlist(spa->spa_config, 8);
1901	}
1902
1903	if (dump_opt['C'])
1904		dump_config(spa);
1905
1906	if (dump_opt['u'])
1907		dump_uberblock(&spa->spa_uberblock);
1908
1909	if (dump_opt['d'] > 2 || dump_opt['m'])
1910		dump_metaslabs(spa);
1911
1912	if (dump_opt['d'] || dump_opt['i']) {
1913		dump_dir(dp->dp_meta_objset);
1914		if (dump_opt['d'] >= 3) {
1915			dump_bplist(dp->dp_meta_objset,
1916			    spa->spa_sync_bplist_obj, "Deferred frees");
1917			dump_dtl(spa->spa_root_vdev, 0);
1918		}
1919		(void) dmu_objset_find(spa_name(spa), dump_one_dir,
1920		    NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
1921	}
1922	if (dump_opt['b'] || dump_opt['c'] || dump_opt['S'])
1923		rc = dump_block_stats(spa);
1924
1925	if (dump_opt['s'])
1926		show_pool_stats(spa);
1927
1928	if (dump_opt['h'])
1929		dump_history(spa);
1930
1931	if (rc != 0)
1932		exit(rc);
1933}
1934
1935#define	ZDB_FLAG_CHECKSUM	0x0001
1936#define	ZDB_FLAG_DECOMPRESS	0x0002
1937#define	ZDB_FLAG_BSWAP		0x0004
1938#define	ZDB_FLAG_GBH		0x0008
1939#define	ZDB_FLAG_INDIRECT	0x0010
1940#define	ZDB_FLAG_PHYS		0x0020
1941#define	ZDB_FLAG_RAW		0x0040
1942#define	ZDB_FLAG_PRINT_BLKPTR	0x0080
1943
1944int flagbits[256];
1945
1946static void
1947zdb_print_blkptr(blkptr_t *bp, int flags)
1948{
1949	dva_t *dva = bp->blk_dva;
1950	int d;
1951
1952	if (flags & ZDB_FLAG_BSWAP)
1953		byteswap_uint64_array((void *)bp, sizeof (blkptr_t));
1954	/*
1955	 * Super-ick warning:  This code is also duplicated in
1956	 * cmd/mdb/common/modules/zfs/zfs.c .  Yeah, I hate code
1957	 * replication, too.
1958	 */
1959	for (d = 0; d < BP_GET_NDVAS(bp); d++) {
1960		(void) printf("\tDVA[%d]: vdev_id %lld / %llx\n", d,
1961		    (longlong_t)DVA_GET_VDEV(&dva[d]),
1962		    (longlong_t)DVA_GET_OFFSET(&dva[d]));
1963		(void) printf("\tDVA[%d]:       GANG: %-5s  GRID:  %04llx\t"
1964		    "ASIZE: %llx\n", d,
1965		    DVA_GET_GANG(&dva[d]) ? "TRUE" : "FALSE",
1966		    (longlong_t)DVA_GET_GRID(&dva[d]),
1967		    (longlong_t)DVA_GET_ASIZE(&dva[d]));
1968		(void) printf("\tDVA[%d]: %llu:%llx:%llx:%s%s%s%s\n", d,
1969		    (u_longlong_t)DVA_GET_VDEV(&dva[d]),
1970		    (longlong_t)DVA_GET_OFFSET(&dva[d]),
1971		    (longlong_t)BP_GET_PSIZE(bp),
1972		    BP_SHOULD_BYTESWAP(bp) ? "e" : "",
1973		    !DVA_GET_GANG(&dva[d]) && BP_GET_LEVEL(bp) != 0 ?
1974		    "d" : "",
1975		    DVA_GET_GANG(&dva[d]) ? "g" : "",
1976		    BP_GET_COMPRESS(bp) != 0 ? "d" : "");
1977	}
1978	(void) printf("\tLSIZE:  %-16llx\t\tPSIZE: %llx\n",
1979	    (longlong_t)BP_GET_LSIZE(bp), (longlong_t)BP_GET_PSIZE(bp));
1980	(void) printf("\tENDIAN: %6s\t\t\t\t\tTYPE:  %s\n",
1981	    BP_GET_BYTEORDER(bp) ? "LITTLE" : "BIG",
1982	    ZDB_OT_NAME(BP_GET_TYPE(bp)));
1983	(void) printf("\tBIRTH:  %-16llx   LEVEL: %-2llu\tFILL:  %llx\n",
1984	    (u_longlong_t)bp->blk_birth, (u_longlong_t)BP_GET_LEVEL(bp),
1985	    (u_longlong_t)bp->blk_fill);
1986	(void) printf("\tCKFUNC: %-16s\t\tCOMP:  %s\n",
1987	    ZDB_CHECKSUM_NAME(BP_GET_CHECKSUM(bp)),
1988	    ZDB_COMPRESS_NAME(BP_GET_COMPRESS(bp)));
1989	(void) printf("\tCKSUM:  %llx:%llx:%llx:%llx\n",
1990	    (u_longlong_t)bp->blk_cksum.zc_word[0],
1991	    (u_longlong_t)bp->blk_cksum.zc_word[1],
1992	    (u_longlong_t)bp->blk_cksum.zc_word[2],
1993	    (u_longlong_t)bp->blk_cksum.zc_word[3]);
1994}
1995
1996static void
1997zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
1998{
1999	int i;
2000
2001	for (i = 0; i < nbps; i++)
2002		zdb_print_blkptr(&bp[i], flags);
2003}
2004
2005static void
2006zdb_dump_gbh(void *buf, int flags)
2007{
2008	zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
2009}
2010
2011static void
2012zdb_dump_block_raw(void *buf, uint64_t size, int flags)
2013{
2014	if (flags & ZDB_FLAG_BSWAP)
2015		byteswap_uint64_array(buf, size);
2016	(void) write(2, buf, size);
2017}
2018
2019static void
2020zdb_dump_block(char *label, void *buf, uint64_t size, int flags)
2021{
2022	uint64_t *d = (uint64_t *)buf;
2023	int nwords = size / sizeof (uint64_t);
2024	int do_bswap = !!(flags & ZDB_FLAG_BSWAP);
2025	int i, j;
2026	char *hdr, *c;
2027
2028
2029	if (do_bswap)
2030		hdr = " 7 6 5 4 3 2 1 0   f e d c b a 9 8";
2031	else
2032		hdr = " 0 1 2 3 4 5 6 7   8 9 a b c d e f";
2033
2034	(void) printf("\n%s\n%6s   %s  0123456789abcdef\n", label, "", hdr);
2035
2036	for (i = 0; i < nwords; i += 2) {
2037		(void) printf("%06llx:  %016llx  %016llx  ",
2038		    (u_longlong_t)(i * sizeof (uint64_t)),
2039		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i]) : d[i]),
2040		    (u_longlong_t)(do_bswap ? BSWAP_64(d[i + 1]) : d[i + 1]));
2041
2042		c = (char *)&d[i];
2043		for (j = 0; j < 2 * sizeof (uint64_t); j++)
2044			(void) printf("%c", isprint(c[j]) ? c[j] : '.');
2045		(void) printf("\n");
2046	}
2047}
2048
2049/*
2050 * There are two acceptable formats:
2051 *	leaf_name	  - For example: c1t0d0 or /tmp/ztest.0a
2052 *	child[.child]*    - For example: 0.1.1
2053 *
2054 * The second form can be used to specify arbitrary vdevs anywhere
2055 * in the heirarchy.  For example, in a pool with a mirror of
2056 * RAID-Zs, you can specify either RAID-Z vdev with 0.0 or 0.1 .
2057 */
2058static vdev_t *
2059zdb_vdev_lookup(vdev_t *vdev, char *path)
2060{
2061	char *s, *p, *q;
2062	int i;
2063
2064	if (vdev == NULL)
2065		return (NULL);
2066
2067	/* First, assume the x.x.x.x format */
2068	i = (int)strtoul(path, &s, 10);
2069	if (s == path || (s && *s != '.' && *s != '\0'))
2070		goto name;
2071	if (i < 0 || i >= vdev->vdev_children)
2072		return (NULL);
2073
2074	vdev = vdev->vdev_child[i];
2075	if (*s == '\0')
2076		return (vdev);
2077	return (zdb_vdev_lookup(vdev, s+1));
2078
2079name:
2080	for (i = 0; i < vdev->vdev_children; i++) {
2081		vdev_t *vc = vdev->vdev_child[i];
2082
2083		if (vc->vdev_path == NULL) {
2084			vc = zdb_vdev_lookup(vc, path);
2085			if (vc == NULL)
2086				continue;
2087			else
2088				return (vc);
2089		}
2090
2091		p = strrchr(vc->vdev_path, '/');
2092		p = p ? p + 1 : vc->vdev_path;
2093		q = &vc->vdev_path[strlen(vc->vdev_path) - 2];
2094
2095		if (strcmp(vc->vdev_path, path) == 0)
2096			return (vc);
2097		if (strcmp(p, path) == 0)
2098			return (vc);
2099		if (strcmp(q, "s0") == 0 && strncmp(p, path, q - p) == 0)
2100			return (vc);
2101	}
2102
2103	return (NULL);
2104}
2105
2106/*
2107 * Read a block from a pool and print it out.  The syntax of the
2108 * block descriptor is:
2109 *
2110 *	pool:vdev_specifier:offset:size[:flags]
2111 *
2112 *	pool           - The name of the pool you wish to read from
2113 *	vdev_specifier - Which vdev (see comment for zdb_vdev_lookup)
2114 *	offset         - offset, in hex, in bytes
2115 *	size           - Amount of data to read, in hex, in bytes
2116 *	flags          - A string of characters specifying options
2117 *		 b: Decode a blkptr at given offset within block
2118 *		*c: Calculate and display checksums
2119 *		*d: Decompress data before dumping
2120 *		 e: Byteswap data before dumping
2121 *		*g: Display data as a gang block header
2122 *		*i: Display as an indirect block
2123 *		 p: Do I/O to physical offset
2124 *		 r: Dump raw data to stdout
2125 *
2126 *              * = not yet implemented
2127 */
2128static void
2129zdb_read_block(char *thing, spa_t *spa)
2130{
2131	int flags = 0;
2132	uint64_t offset = 0, size = 0, blkptr_offset = 0;
2133	zio_t *zio;
2134	vdev_t *vd;
2135	void *buf;
2136	char *s, *p, *dup, *vdev, *flagstr;
2137	int i, error, zio_flags;
2138
2139	dup = strdup(thing);
2140	s = strtok(dup, ":");
2141	vdev = s ? s : "";
2142	s = strtok(NULL, ":");
2143	offset = strtoull(s ? s : "", NULL, 16);
2144	s = strtok(NULL, ":");
2145	size = strtoull(s ? s : "", NULL, 16);
2146	s = strtok(NULL, ":");
2147	flagstr = s ? s : "";
2148
2149	s = NULL;
2150	if (size == 0)
2151		s = "size must not be zero";
2152	if (!IS_P2ALIGNED(size, DEV_BSIZE))
2153		s = "size must be a multiple of sector size";
2154	if (!IS_P2ALIGNED(offset, DEV_BSIZE))
2155		s = "offset must be a multiple of sector size";
2156	if (s) {
2157		(void) printf("Invalid block specifier: %s  - %s\n", thing, s);
2158		free(dup);
2159		return;
2160	}
2161
2162	for (s = strtok(flagstr, ":"); s; s = strtok(NULL, ":")) {
2163		for (i = 0; flagstr[i]; i++) {
2164			int bit = flagbits[(uchar_t)flagstr[i]];
2165
2166			if (bit == 0) {
2167				(void) printf("***Invalid flag: %c\n",
2168				    flagstr[i]);
2169				continue;
2170			}
2171			flags |= bit;
2172
2173			/* If it's not something with an argument, keep going */
2174			if ((bit & (ZDB_FLAG_CHECKSUM | ZDB_FLAG_DECOMPRESS |
2175			    ZDB_FLAG_PRINT_BLKPTR)) == 0)
2176				continue;
2177
2178			p = &flagstr[i + 1];
2179			if (bit == ZDB_FLAG_PRINT_BLKPTR)
2180				blkptr_offset = strtoull(p, &p, 16);
2181			if (*p != ':' && *p != '\0') {
2182				(void) printf("***Invalid flag arg: '%s'\n", s);
2183				free(dup);
2184				return;
2185			}
2186		}
2187	}
2188
2189	vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev);
2190	if (vd == NULL) {
2191		(void) printf("***Invalid vdev: %s\n", vdev);
2192		free(dup);
2193		return;
2194	} else {
2195		if (vd->vdev_path)
2196			(void) printf("Found vdev: %s\n", vd->vdev_path);
2197		else
2198			(void) printf("Found vdev type: %s\n",
2199			    vd->vdev_ops->vdev_op_type);
2200	}
2201
2202	buf = umem_alloc(size, UMEM_NOFAIL);
2203
2204	zio_flags = ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE |
2205	    ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY;
2206
2207	spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
2208	zio = zio_root(spa, NULL, NULL, 0);
2209	/* XXX todo - cons up a BP so RAID-Z will be happy */
2210	zio_nowait(zio_vdev_child_io(zio, NULL, vd, offset, buf, size,
2211	    ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ, zio_flags, NULL, NULL));
2212	error = zio_wait(zio);
2213	spa_config_exit(spa, SCL_STATE, FTAG);
2214
2215	if (error) {
2216		(void) printf("Read of %s failed, error: %d\n", thing, error);
2217		goto out;
2218	}
2219
2220	if (flags & ZDB_FLAG_PRINT_BLKPTR)
2221		zdb_print_blkptr((blkptr_t *)(void *)
2222		    ((uintptr_t)buf + (uintptr_t)blkptr_offset), flags);
2223	else if (flags & ZDB_FLAG_RAW)
2224		zdb_dump_block_raw(buf, size, flags);
2225	else if (flags & ZDB_FLAG_INDIRECT)
2226		zdb_dump_indirect((blkptr_t *)buf, size / sizeof (blkptr_t),
2227		    flags);
2228	else if (flags & ZDB_FLAG_GBH)
2229		zdb_dump_gbh(buf, flags);
2230	else
2231		zdb_dump_block(thing, buf, size, flags);
2232
2233out:
2234	umem_free(buf, size);
2235	free(dup);
2236}
2237
2238static boolean_t
2239pool_match(nvlist_t *cfg, char *tgt)
2240{
2241	uint64_t v, guid = strtoull(tgt, NULL, 0);
2242	char *s;
2243
2244	if (guid != 0) {
2245		if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0)
2246			return (v == guid);
2247	} else {
2248		if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0)
2249			return (strcmp(s, tgt) == 0);
2250	}
2251	return (B_FALSE);
2252}
2253
2254static char *
2255find_zpool(char **target, nvlist_t **configp, int dirc, char **dirv)
2256{
2257	nvlist_t *pools;
2258	nvlist_t *match = NULL;
2259	char *name = NULL;
2260	char *sepp = NULL;
2261	char sep;
2262	int count = 0;
2263
2264	if ((sepp = strpbrk(*target, "/@")) != NULL) {
2265		sep = *sepp;
2266		*sepp = '\0';
2267	}
2268
2269	pools = zpool_find_import_activeok(g_zfs, dirc, dirv);
2270
2271	if (pools != NULL) {
2272		nvpair_t *elem = NULL;
2273		while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2274			verify(nvpair_value_nvlist(elem, configp) == 0);
2275			if (pool_match(*configp, *target)) {
2276				count++;
2277				if (match != NULL) {
2278					/* print previously found config */
2279					if (name != NULL) {
2280						(void) printf("%s\n", name);
2281						dump_nvlist(match, 8);
2282						name = NULL;
2283					}
2284					(void) printf("%s\n",
2285					    nvpair_name(elem));
2286					dump_nvlist(*configp, 8);
2287				} else {
2288					match = *configp;
2289					name = nvpair_name(elem);
2290				}
2291			}
2292		}
2293	}
2294	if (count > 1)
2295		(void) fatal("\tMatched %d pools - use pool GUID "
2296		    "instead of pool name or \n"
2297		    "\tpool name part of a dataset name to select pool", count);
2298
2299	if (sepp)
2300		*sepp = sep;
2301	/*
2302	 * If pool GUID was specified for pool id, replace it with pool name
2303	 */
2304	if (name && (strstr(*target, name) != *target)) {
2305		int sz = 1 + strlen(name) + ((sepp) ? strlen(sepp) : 0);
2306
2307		*target = umem_alloc(sz, UMEM_NOFAIL);
2308		(void) snprintf(*target, sz, "%s%s", name, sepp ? sepp : "");
2309	}
2310
2311	*configp = name ? match : NULL;
2312
2313	return (name);
2314}
2315
2316int
2317main(int argc, char **argv)
2318{
2319	int i, c;
2320	struct rlimit rl = { 1024, 1024 };
2321	spa_t *spa = NULL;
2322	objset_t *os = NULL;
2323	char *endstr;
2324	int dump_all = 1;
2325	int verbose = 0;
2326	int error;
2327	char **searchdirs = NULL;
2328	int nsearch = 0;
2329	char *target;
2330
2331	(void) setrlimit(RLIMIT_NOFILE, &rl);
2332	(void) enable_extended_FILE_stdio(-1, -1);
2333
2334	dprintf_setup(&argc, argv);
2335
2336	while ((c = getopt(argc, argv, "udhibcmsvCLS:RU:lep:t:")) != -1) {
2337		switch (c) {
2338		case 'u':
2339		case 'd':
2340		case 'i':
2341		case 'h':
2342		case 'b':
2343		case 'c':
2344		case 'm':
2345		case 's':
2346		case 'C':
2347		case 'l':
2348		case 'R':
2349			dump_opt[c]++;
2350			dump_all = 0;
2351			break;
2352		case 'L':
2353		case 'e':
2354			dump_opt[c]++;
2355			break;
2356		case 'v':
2357			verbose++;
2358			break;
2359		case 'U':
2360			spa_config_path = optarg;
2361			break;
2362		case 'p':
2363			if (searchdirs == NULL) {
2364				searchdirs = umem_alloc(sizeof (char *),
2365				    UMEM_NOFAIL);
2366			} else {
2367				char **tmp = umem_alloc((nsearch + 1) *
2368				    sizeof (char *), UMEM_NOFAIL);
2369				bcopy(searchdirs, tmp, nsearch *
2370				    sizeof (char *));
2371				umem_free(searchdirs,
2372				    nsearch * sizeof (char *));
2373				searchdirs = tmp;
2374			}
2375			searchdirs[nsearch++] = optarg;
2376			break;
2377		case 'S':
2378			dump_opt[c]++;
2379			dump_all = 0;
2380			zdb_sig_user_data = (strncmp(optarg, "user:", 5) == 0);
2381			if (!zdb_sig_user_data && strncmp(optarg, "all:", 4))
2382				usage();
2383			endstr = strchr(optarg, ':') + 1;
2384			if (strcmp(endstr, "fletcher2") == 0)
2385				zdb_sig_cksumalg = ZIO_CHECKSUM_FLETCHER_2;
2386			else if (strcmp(endstr, "fletcher4") == 0)
2387				zdb_sig_cksumalg = ZIO_CHECKSUM_FLETCHER_4;
2388			else if (strcmp(endstr, "sha256") == 0)
2389				zdb_sig_cksumalg = ZIO_CHECKSUM_SHA256;
2390			else if (strcmp(endstr, "all") == 0)
2391				zdb_sig_cksumalg = ZIO_CHECKSUM_FLETCHER_2;
2392			else
2393				usage();
2394			break;
2395		case 't':
2396			ub_max_txg = strtoull(optarg, NULL, 0);
2397			if (ub_max_txg < TXG_INITIAL) {
2398				(void) fprintf(stderr, "incorrect txg "
2399				    "specified: %s\n", optarg);
2400				usage();
2401			}
2402			break;
2403		default:
2404			usage();
2405			break;
2406		}
2407	}
2408
2409	if (!dump_opt['e'] && searchdirs != NULL) {
2410		(void) fprintf(stderr, "-p option requires use of -e\n");
2411		usage();
2412	}
2413
2414	kernel_init(FREAD);
2415	g_zfs = libzfs_init();
2416	ASSERT(g_zfs != NULL);
2417
2418	for (c = 0; c < 256; c++) {
2419		if (dump_all && !strchr("elLR", c))
2420			dump_opt[c] = 1;
2421		if (dump_opt[c])
2422			dump_opt[c] += verbose;
2423	}
2424
2425	argc -= optind;
2426	argv += optind;
2427
2428	if (argc < 2 && dump_opt['R'])
2429		usage();
2430	if (argc < 1) {
2431		if (!dump_opt['e'] && dump_opt['C']) {
2432			dump_cachefile(spa_config_path);
2433			return (0);
2434		}
2435		usage();
2436	}
2437
2438	if (dump_opt['l']) {
2439		dump_label(argv[0]);
2440		return (0);
2441	}
2442
2443	error = 0;
2444	target = argv[0];
2445
2446	if (dump_opt['e']) {
2447		nvlist_t *cfg = NULL;
2448		char *name = find_zpool(&target, &cfg, nsearch, searchdirs);
2449
2450		error = ENOENT;
2451		if (name) {
2452			if (dump_opt['C'] > 1) {
2453				(void) printf("\nConfiguration for import:\n");
2454				dump_nvlist(cfg, 8);
2455			}
2456			if ((error = spa_import(name, cfg, NULL)) != 0)
2457				error = spa_import_verbatim(name, cfg, NULL);
2458		}
2459	}
2460
2461	if (error == 0) {
2462		if (strpbrk(target, "/@") == NULL || dump_opt['R']) {
2463			error = spa_open(target, &spa, FTAG);
2464			if (error) {
2465				/*
2466				 * If we're missing the log device then
2467				 * try opening the pool after clearing the
2468				 * log state.
2469				 */
2470				mutex_enter(&spa_namespace_lock);
2471				if ((spa = spa_lookup(target)) != NULL &&
2472				    spa->spa_log_state == SPA_LOG_MISSING) {
2473					spa->spa_log_state = SPA_LOG_CLEAR;
2474					error = 0;
2475				}
2476				mutex_exit(&spa_namespace_lock);
2477
2478				if (!error)
2479					error = spa_open(target, &spa, FTAG);
2480			}
2481		} else {
2482			error = dmu_objset_own(target, DMU_OST_ANY,
2483			    B_TRUE, FTAG, &os);
2484		}
2485	}
2486	if (error)
2487		fatal("can't open '%s': %s", target, strerror(error));
2488
2489	argv++;
2490	argc--;
2491	if (!dump_opt['R']) {
2492		if (argc > 0) {
2493			zopt_objects = argc;
2494			zopt_object = calloc(zopt_objects, sizeof (uint64_t));
2495			for (i = 0; i < zopt_objects; i++) {
2496				errno = 0;
2497				zopt_object[i] = strtoull(argv[i], NULL, 0);
2498				if (zopt_object[i] == 0 && errno != 0)
2499					fatal("bad number %s: %s",
2500					    argv[i], strerror(errno));
2501			}
2502		}
2503		(os != NULL) ? dump_dir(os) : dump_zpool(spa);
2504	} else {
2505		flagbits['b'] = ZDB_FLAG_PRINT_BLKPTR;
2506		flagbits['c'] = ZDB_FLAG_CHECKSUM;
2507		flagbits['d'] = ZDB_FLAG_DECOMPRESS;
2508		flagbits['e'] = ZDB_FLAG_BSWAP;
2509		flagbits['g'] = ZDB_FLAG_GBH;
2510		flagbits['i'] = ZDB_FLAG_INDIRECT;
2511		flagbits['p'] = ZDB_FLAG_PHYS;
2512		flagbits['r'] = ZDB_FLAG_RAW;
2513
2514		for (i = 0; i < argc; i++)
2515			zdb_read_block(argv[i], spa);
2516	}
2517
2518	(os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
2519
2520	fuid_table_destroy();
2521
2522	libzfs_fini(g_zfs);
2523	kernel_fini();
2524
2525	return (0);
2526}
2527