zdb.c revision b24ab6762772a3f6a89393947930c7fa61306783
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5ea8dc4beschrock * Common Development and Distribution License (the "License").
6ea8dc4beschrock * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
22ccba080Rich Morris * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fa9e406ahrens * Use is subject to license terms.
24fa9e406ahrens */
26fa9e406ahrens#include <stdio.h>
27004388ecasper#include <stdio_ext.h>
28fa9e406ahrens#include <stdlib.h>
2944cd46cbillm#include <ctype.h>
30fa9e406ahrens#include <sys/zfs_context.h>
31fa9e406ahrens#include <sys/spa.h>
32fa9e406ahrens#include <sys/spa_impl.h>
33fa9e406ahrens#include <sys/dmu.h>
34fa9e406ahrens#include <sys/zap.h>
35fa9e406ahrens#include <sys/fs/zfs.h>
36fa9e406ahrens#include <sys/zfs_znode.h>
37fa9e406ahrens#include <sys/vdev.h>
38fa9e406ahrens#include <sys/vdev_impl.h>
39fa9e406ahrens#include <sys/metaslab_impl.h>
40fa9e406ahrens#include <sys/dmu_objset.h>
41fa9e406ahrens#include <sys/dsl_dir.h>
42fa9e406ahrens#include <sys/dsl_dataset.h>
43fa9e406ahrens#include <sys/dsl_pool.h>
44fa9e406ahrens#include <sys/dbuf.h>
45fa9e406ahrens#include <sys/zil.h>
46fa9e406ahrens#include <sys/zil_impl.h>
47fa9e406ahrens#include <sys/stat.h>
48fa9e406ahrens#include <sys/resource.h>
49fa9e406ahrens#include <sys/dmu_traverse.h>
50fa9e406ahrens#include <sys/zio_checksum.h>
51fa9e406ahrens#include <sys/zio_compress.h>
52e0d35c4marks#include <sys/zfs_fuid.h>
5388b7b0fMatthew Ahrens#include <sys/arc.h>
54b24ab67Jeff Bonwick#include <sys/ddt.h>
55de6628fck#undef ZFS_MAXNAMELEN
56de6628fck#undef verify
57de6628fck#include <libzfs.h>
596de8f41Victor Latushkin#define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
606de8f41Victor Latushkin    zio_compress_table[(idx)].ci_name : "UNKNOWN")
616de8f41Victor Latushkin#define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
626de8f41Victor Latushkin    zio_checksum_table[(idx)].ci_name : "UNKNOWN")
636de8f41Victor Latushkin#define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \
646de8f41Victor Latushkin    dmu_ot[(idx)].ot_name : "UNKNOWN")
656de8f41Victor Latushkin#define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : DMU_OT_NUMTYPES)
666de8f41Victor Latushkin
67fa9e406ahrensconst char cmdname[] = "zdb";
68fa9e406ahrensuint8_t dump_opt[256];
70fa9e406ahrenstypedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
72fa9e406ahrensextern void dump_intent_log(zilog_t *);
73fa9e406ahrensuint64_t *zopt_object = NULL;
74fa9e406ahrensint zopt_objects = 0;
75de6628fcklibzfs_handle_t *g_zfs;
78fa9e406ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
79fa9e406ahrens * debugging facilities.
80fa9e406ahrens */
81fa9e406ahrensconst char *
84fa9e406ahrens	return ("default,verbose"); /* $UMEM_DEBUG setting */
87fa9e406ahrensconst char *
90fa9e406ahrens	return ("fail,contents"); /* $UMEM_LOGGING setting */
93fa9e406ahrensstatic void
96fa9e406ahrens	(void) fprintf(stderr,
973ad6c7fVictor Latushkin	    "Usage: %s [-CumdibcsvhL] [-S user:cksumalg] "
983ad6c7fVictor Latushkin	    "poolname [object...]\n"
993ad6c7fVictor Latushkin	    "       %s [-div] dataset [object...]\n"
10087219dbVictor Latushkin	    "       %s -m [-L] poolname [vdev [metaslab...]]\n"
10107428bdVictor Latushkin	    "       %s -R poolname vdev:offset:size[:flags]\n"
10207428bdVictor Latushkin	    "       %s -l device\n"
10307428bdVictor Latushkin	    "       %s -C\n\n",
10487219dbVictor Latushkin	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
1053ad6c7fVictor Latushkin
1063ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Dataset name must include at least one "
1073ad6c7fVictor Latushkin	    "separator character '/' or '@'\n");
1083ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If dataset name is specified, only that "
1093ad6c7fVictor Latushkin	    "dataset is dumped\n");
1103ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If object numbers are specified, only "
1113ad6c7fVictor Latushkin	    "those objects are dumped\n\n");
1123ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Options to control amount of output:\n");
1133ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -u uberblock\n");
1143ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -d dataset(s)\n");
1153ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -i intent logs\n");
11607428bdVictor Latushkin	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
1178f18d1fGeorge Wilson	(void) fprintf(stderr, "        -h pool history\n");
1183ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -b block statistics\n");
1193ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -m metaslabs\n");
1203ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
1216365109Victor Latushkin	    "all data) blocks\n");
1223ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
123b24ab67Jeff Bonwick	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
1243ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
125fa9e406ahrens	(void) fprintf(stderr, "        -l dump label contents\n");
12682a0a98Victor Latushkin	(void) fprintf(stderr, "        -L disable leak tracking (do not "
12782a0a98Victor Latushkin	    "load spacemaps)\n");
128d41e764ek	(void) fprintf(stderr, "        -R read and display block from a "
1293ad6c7fVictor Latushkin	    "device\n\n");
1303ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Below options are intended for use "
1313ad6c7fVictor Latushkin	    "with other options (except -l):\n");
1323ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
1333ad6c7fVictor Latushkin	    "cachefile\n");
1343ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
1353ad6c7fVictor Latushkin	    "has altroot/not in a cachefile\n");
1363ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -p <path> -- use one or more with "
1373ad6c7fVictor Latushkin	    "-e to specify path to vdev dir\n");
1383ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
1392e55192Victor Latushkin	    "searching for uberblocks\n");
140fa9e406ahrens	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
141fa9e406ahrens	    "to make only that option verbose\n");
142fa9e406ahrens	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
143fa9e406ahrens	exit(1);
146ccba080Rich Morris/*
147ccba080Rich Morris * Called for usage errors that are discovered after a call to spa_open(),
148ccba080Rich Morris * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
149ccba080Rich Morris */
150ccba080Rich Morris
151fa9e406ahrensstatic void
152fa9e406ahrensfatal(const char *fmt, ...)
154fa9e406ahrens	va_list ap;
156fa9e406ahrens	va_start(ap, fmt);
157fa9e406ahrens	(void) fprintf(stderr, "%s: ", cmdname);
158fa9e406ahrens	(void) vfprintf(stderr, fmt, ap);
159fa9e406ahrens	va_end(ap);
160fa9e406ahrens	(void) fprintf(stderr, "\n");
162ccba080Rich Morris	exit(1);
165fa9e406ahrens/* ARGSUSED */
166fa9e406ahrensstatic void
167fa9e406ahrensdump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
169fa9e406ahrens	nvlist_t *nv;
170fa9e406ahrens	size_t nvsize = *(uint64_t *)data;
171fa9e406ahrens	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
1737bfdf01Neil Perrin	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
175fa9e406ahrens	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
177fa9e406ahrens	umem_free(packed, nvsize);
179fa9e406ahrens	dump_nvlist(nv, 8);
181fa9e406ahrens	nvlist_free(nv);
184fa9e406ahrensconst char dump_zap_stars[] = "****************************************";
185fa9e406ahrensconst int dump_zap_width = sizeof (dump_zap_stars) - 1;
187fa9e406ahrensstatic void
188fa9e406ahrensdump_zap_histogram(uint64_t histo[ZAP_HISTOGRAM_SIZE])
190fa9e406ahrens	int i;
191fa9e406ahrens	int minidx = ZAP_HISTOGRAM_SIZE - 1;
192fa9e406ahrens	int maxidx = 0;
193fa9e406ahrens	uint64_t max = 0;
195fa9e406ahrens	for (i = 0; i < ZAP_HISTOGRAM_SIZE; i++) {
196fa9e406ahrens		if (histo[i] > max)
197fa9e406ahrens			max = histo[i];
198fa9e406ahrens		if (histo[i] > 0 && i > maxidx)
199fa9e406ahrens			maxidx = i;
200fa9e406ahrens		if (histo[i] > 0 && i < minidx)
201fa9e406ahrens			minidx = i;
202fa9e406ahrens	}
204fa9e406ahrens	if (max < dump_zap_width)
205fa9e406ahrens		max = dump_zap_width;
207fa9e406ahrens	for (i = minidx; i <= maxidx; i++)
208fa9e406ahrens		(void) printf("\t\t\t%u: %6llu %s\n", i, (u_longlong_t)histo[i],
209fa9e406ahrens		    &dump_zap_stars[(max - histo[i]) * dump_zap_width / max]);
212fa9e406ahrensstatic void
213fa9e406ahrensdump_zap_stats(objset_t *os, uint64_t object)
215fa9e406ahrens	int error;
216fa9e406ahrens	zap_stats_t zs;
218fa9e406ahrens	error = zap_get_stats(os, object, &zs);
219fa9e406ahrens	if (error)
220fa9e406ahrens		return;
222fa9e406ahrens	if (zs.zs_ptrtbl_len == 0) {
223fa9e406ahrens		ASSERT(zs.zs_num_blocks == 1);
224fa9e406ahrens		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
225fa9e406ahrens		    (u_longlong_t)zs.zs_blocksize,
226fa9e406ahrens		    (u_longlong_t)zs.zs_num_entries);
227fa9e406ahrens		return;
228fa9e406ahrens	}
230fa9e406ahrens	(void) printf("\tFat ZAP stats:\n");
2328248818nd	(void) printf("\t\tPointer table:\n");
2338248818nd	(void) printf("\t\t\t%llu elements\n",
234fa9e406ahrens	    (u_longlong_t)zs.zs_ptrtbl_len);
2358248818nd	(void) printf("\t\t\tzt_blk: %llu\n",
2368248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
2378248818nd	(void) printf("\t\t\tzt_numblks: %llu\n",
2388248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
2398248818nd	(void) printf("\t\t\tzt_shift: %llu\n",
2408248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
2418248818nd	(void) printf("\t\t\tzt_blks_copied: %llu\n",
2428248818nd	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
2438248818nd	(void) printf("\t\t\tzt_nextblk: %llu\n",
2448248818nd	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
246fa9e406ahrens	(void) printf("\t\tZAP entries: %llu\n",
247fa9e406ahrens	    (u_longlong_t)zs.zs_num_entries);
248fa9e406ahrens	(void) printf("\t\tLeaf blocks: %llu\n",
249fa9e406ahrens	    (u_longlong_t)zs.zs_num_leafs);
250fa9e406ahrens	(void) printf("\t\tTotal blocks: %llu\n",
251fa9e406ahrens	    (u_longlong_t)zs.zs_num_blocks);
2528248818nd	(void) printf("\t\tzap_block_type: 0x%llx\n",
2538248818nd	    (u_longlong_t)zs.zs_block_type);
2548248818nd	(void) printf("\t\tzap_magic: 0x%llx\n",
2558248818nd	    (u_longlong_t)zs.zs_magic);
2568248818nd	(void) printf("\t\tzap_salt: 0x%llx\n",
2578248818nd	    (u_longlong_t)zs.zs_salt);
259fa9e406ahrens	(void) printf("\t\tLeafs with 2^n pointers:\n");
260fa9e406ahrens	dump_zap_histogram(zs.zs_leafs_with_2n_pointers);
262fa9e406ahrens	(void) printf("\t\tBlocks with n*5 entries:\n");
263fa9e406ahrens	dump_zap_histogram(zs.zs_blocks_with_n5_entries);
265fa9e406ahrens	(void) printf("\t\tBlocks n/10 full:\n");
266fa9e406ahrens	dump_zap_histogram(zs.zs_blocks_n_tenths_full);
268fa9e406ahrens	(void) printf("\t\tEntries with n chunks:\n");
269fa9e406ahrens	dump_zap_histogram(zs.zs_entries_using_n_chunks);
271fa9e406ahrens	(void) printf("\t\tBuckets with n entries:\n");
272fa9e406ahrens	dump_zap_histogram(zs.zs_buckets_with_n_entries);
276fa9e406ahrensstatic void
277fa9e406ahrensdump_none(objset_t *os, uint64_t object, void *data, size_t size)
2826de8f41Victor Latushkinstatic void
2836de8f41Victor Latushkindump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
2846de8f41Victor Latushkin{
2856de8f41Victor Latushkin	(void) printf("\tUNKNOWN OBJECT TYPE\n");
2866de8f41Victor Latushkin}
2876de8f41Victor Latushkin
2886de8f41Victor Latushkin/*ARGSUSED*/
290fa9e406ahrensdump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
295fa9e406ahrensstatic void
296fa9e406ahrensdump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
301fa9e406ahrensstatic void
302fa9e406ahrensdump_zap(objset_t *os, uint64_t object, void *data, size_t size)
304fa9e406ahrens	zap_cursor_t zc;
305fa9e406ahrens	zap_attribute_t attr;
306fa9e406ahrens	void *prop;
307fa9e406ahrens	int i;
309fa9e406ahrens	dump_zap_stats(os, object);
310fa9e406ahrens	(void) printf("\n");
312fa9e406ahrens	for (zap_cursor_init(&zc, os, object);
313fa9e406ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
314fa9e406ahrens	    zap_cursor_advance(&zc)) {
315fa9e406ahrens		(void) printf("\t\t%s = ", attr.za_name);
316fa9e406ahrens		if (attr.za_num_integers == 0) {
317fa9e406ahrens			(void) printf("\n");
318fa9e406ahrens			continue;
319fa9e406ahrens		}
320fa9e406ahrens		prop = umem_zalloc(attr.za_num_integers *
321fa9e406ahrens		    attr.za_integer_length, UMEM_NOFAIL);
322fa9e406ahrens		(void) zap_lookup(os, object, attr.za_name,
323fa9e406ahrens		    attr.za_integer_length, attr.za_num_integers, prop);
324fa9e406ahrens		if (attr.za_integer_length == 1) {
325fa9e406ahrens			(void) printf("%s", (char *)prop);
326fa9e406ahrens		} else {
327fa9e406ahrens			for (i = 0; i < attr.za_num_integers; i++) {
328fa9e406ahrens				switch (attr.za_integer_length) {
329fa9e406ahrens				case 2:
330fa9e406ahrens					(void) printf("%u ",
331fa9e406ahrens					    ((uint16_t *)prop)[i]);
332fa9e406ahrens					break;
333fa9e406ahrens				case 4:
334fa9e406ahrens					(void) printf("%u ",
335fa9e406ahrens					    ((uint32_t *)prop)[i]);
336fa9e406ahrens					break;
337fa9e406ahrens				case 8:
338fa9e406ahrens					(void) printf("%lld ",
339fa9e406ahrens					    (u_longlong_t)((int64_t *)prop)[i]);
340fa9e406ahrens					break;
341fa9e406ahrens				}
342fa9e406ahrens			}
343fa9e406ahrens		}
344fa9e406ahrens		(void) printf("\n");
345fa9e406ahrens		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
346fa9e406ahrens	}
34787e5029ahrens	zap_cursor_fini(&zc);
351e743726ahrensstatic void
352e743726ahrensdump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
354e743726ahrens	zap_cursor_t zc;
355e743726ahrens	zap_attribute_t attr;
356e743726ahrens	const char *typenames[] = {
357e743726ahrens		/* 0 */ "not specified",
358e743726ahrens		/* 1 */ "FIFO",
359e743726ahrens		/* 2 */ "Character Device",
360e743726ahrens		/* 3 */ "3 (invalid)",
361e743726ahrens		/* 4 */ "Directory",
362e743726ahrens		/* 5 */ "5 (invalid)",
363e743726ahrens		/* 6 */ "Block Device",
364e743726ahrens		/* 7 */ "7 (invalid)",
365e743726ahrens		/* 8 */ "Regular File",
366e743726ahrens		/* 9 */ "9 (invalid)",
367e743726ahrens		/* 10 */ "Symbolic Link",
368e743726ahrens		/* 11 */ "11 (invalid)",
369e743726ahrens		/* 12 */ "Socket",
370e743726ahrens		/* 13 */ "Door",
371e743726ahrens		/* 14 */ "Event Port",
372e743726ahrens		/* 15 */ "15 (invalid)",
373e743726ahrens	};
375e743726ahrens	dump_zap_stats(os, object);
376e743726ahrens	(void) printf("\n");
378e743726ahrens	for (zap_cursor_init(&zc, os, object);
379e743726ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
380e743726ahrens	    zap_cursor_advance(&zc)) {
381e743726ahrens		(void) printf("\t\t%s = %lld (type: %s)\n",
382e743726ahrens		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
383e743726ahrens		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
384e743726ahrens	}
385e743726ahrens	zap_cursor_fini(&zc);
388fa9e406ahrensstatic void
389fa9e406ahrensdump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
391fa9e406ahrens	uint64_t alloc, offset, entry;
392ecc2d60bonwick	uint8_t mapshift = sm->sm_shift;
393fa9e406ahrens	uint64_t mapstart = sm->sm_start;
3948053a26ck	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
3958053a26ck			    "INVALID", "INVALID", "INVALID", "INVALID" };
397fa9e406ahrens	if (smo->smo_object == 0)
398fa9e406ahrens		return;
400fa9e406ahrens	/*
401fa9e406ahrens	 * Print out the freelist entries in both encoded and decoded form.
402fa9e406ahrens	 */
403fa9e406ahrens	alloc = 0;
404fa9e406ahrens	for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
405ea8dc4beschrock		VERIFY(0 == dmu_read(os, smo->smo_object, offset,
4067bfdf01Neil Perrin		    sizeof (entry), &entry, DMU_READ_PREFETCH));
407fa9e406ahrens		if (SM_DEBUG_DECODE(entry)) {
40887219dbVictor Latushkin			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
409fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
410fa9e406ahrens			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
4115ad8204nd			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
4125ad8204nd			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
413fa9e406ahrens		} else {
41487219dbVictor Latushkin			(void) printf("\t    [%6llu]    %c  range:"
41587219dbVictor Latushkin			    " %010llx-%010llx  size: %06llx\n",
416fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
417fa9e406ahrens			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
4185ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
4195ad8204nd			    mapshift) + mapstart),
4205ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
4215ad8204nd			    mapshift) + mapstart + (SM_RUN_DECODE(entry) <<
4225ad8204nd			    mapshift)),
4235ad8204nd			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
424fa9e406ahrens			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
425fa9e406ahrens				alloc += SM_RUN_DECODE(entry) << mapshift;
426fa9e406ahrens			else
427fa9e406ahrens				alloc -= SM_RUN_DECODE(entry) << mapshift;
428fa9e406ahrens		}
429fa9e406ahrens	}
430fa9e406ahrens	if (alloc != smo->smo_alloc) {
431fa9e406ahrens		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
432fa9e406ahrens		    "with space map summary (%llu)\n",
433fa9e406ahrens		    (u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc);
434fa9e406ahrens	}
437fa9e406ahrensstatic void
438d6e555bGeorge Wilsondump_metaslab_stats(metaslab_t *msp)
439d6e555bGeorge Wilson{
440d6e555bGeorge Wilson	char maxbuf[5];
441d6e555bGeorge Wilson	space_map_t *sm = &msp->ms_map;
442d6e555bGeorge Wilson	avl_tree_t *t = sm->sm_pp_root;
443d6e555bGeorge Wilson	int free_pct = sm->sm_space * 100 / sm->sm_size;
444d6e555bGeorge Wilson
445d6e555bGeorge Wilson	nicenum(space_map_maxsize(sm), maxbuf);
446d6e555bGeorge Wilson
44787219dbVictor Latushkin	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
448d6e555bGeorge Wilson	    "segments", avl_numnodes(t), "maxsize", maxbuf,
449d6e555bGeorge Wilson	    "freepct", free_pct);
450d6e555bGeorge Wilson}
451d6e555bGeorge Wilson
452d6e555bGeorge Wilsonstatic void
453fa9e406ahrensdump_metaslab(metaslab_t *msp)
455fa9e406ahrens	char freebuf[5];
456ecc2d60bonwick	space_map_obj_t *smo = &msp->ms_smo;
457fa9e406ahrens	vdev_t *vd = msp->ms_group->mg_vd;
458fa9e406ahrens	spa_t *spa = vd->vdev_spa;
460fa9e406ahrens	nicenum(msp->ms_map.sm_size - smo->smo_alloc, freebuf);
462fa9e406ahrens	(void) printf(
46387219dbVictor Latushkin	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
46487219dbVictor Latushkin	    (u_longlong_t)(msp->ms_map.sm_start / msp->ms_map.sm_size),
46587219dbVictor Latushkin	    (u_longlong_t)msp->ms_map.sm_start, (u_longlong_t)smo->smo_object,
46687219dbVictor Latushkin	    freebuf);
46887219dbVictor Latushkin	if (dump_opt['m'] > 1 && !dump_opt['L']) {
469d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
470d6e555bGeorge Wilson		VERIFY(space_map_load(&msp->ms_map, zfs_metaslab_ops,
471d6e555bGeorge Wilson		    SM_FREE, &msp->ms_smo, spa->spa_meta_objset) == 0);
472d6e555bGeorge Wilson		dump_metaslab_stats(msp);
473d6e555bGeorge Wilson		space_map_unload(&msp->ms_map);
474d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
475d6e555bGeorge Wilson	}
476d6e555bGeorge Wilson
477d6e555bGeorge Wilson	if (dump_opt['d'] > 5 || dump_opt['m'] > 2) {
478d6e555bGeorge Wilson		ASSERT(msp->ms_map.sm_size == (1ULL << vd->vdev_ms_shift));
479d6e555bGeorge Wilson
480d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
481d6e555bGeorge Wilson		dump_spacemap(spa->spa_meta_objset, smo, &msp->ms_map);
482d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
483d6e555bGeorge Wilson	}
48487219dbVictor Latushkin}
48687219dbVictor Latushkinstatic void
48787219dbVictor Latushkinprint_vdev_metaslab_header(vdev_t *vd)
48887219dbVictor Latushkin{
48987219dbVictor Latushkin	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
49087219dbVictor Latushkin	    (u_longlong_t)vd->vdev_id,
49187219dbVictor Latushkin	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
49287219dbVictor Latushkin	    "offset", "spacemap", "free");
49387219dbVictor Latushkin	(void) printf("\t%15s   %19s   %15s   %10s\n",
49487219dbVictor Latushkin	    "---------------", "-------------------",
49587219dbVictor Latushkin	    "---------------", "-------------");
498fa9e406ahrensstatic void
499fa9e406ahrensdump_metaslabs(spa_t *spa)
50187219dbVictor Latushkin	vdev_t *vd, *rvd = spa->spa_root_vdev;
50287219dbVictor Latushkin	uint64_t m, c = 0, children = rvd->vdev_children;
504fa9e406ahrens	(void) printf("\nMetaslabs:\n");
50687219dbVictor Latushkin	if (!dump_opt['d'] && zopt_objects > 0) {
50787219dbVictor Latushkin		c = zopt_object[0];
50887219dbVictor Latushkin
50987219dbVictor Latushkin		if (c >= children)
51087219dbVictor Latushkin			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
51287219dbVictor Latushkin		if (zopt_objects > 1) {
51387219dbVictor Latushkin			vd = rvd->vdev_child[c];
51487219dbVictor Latushkin			print_vdev_metaslab_header(vd);
51587219dbVictor Latushkin
51687219dbVictor Latushkin			for (m = 1; m < zopt_objects; m++) {
51787219dbVictor Latushkin				if (zopt_object[m] < vd->vdev_ms_count)
51887219dbVictor Latushkin					dump_metaslab(
51987219dbVictor Latushkin					    vd->vdev_ms[zopt_object[m]]);
52087219dbVictor Latushkin				else
52187219dbVictor Latushkin					(void) fprintf(stderr, "bad metaslab "
52287219dbVictor Latushkin					    "number %llu\n",
52387219dbVictor Latushkin					    (u_longlong_t)zopt_object[m]);
52487219dbVictor Latushkin			}
52587219dbVictor Latushkin			(void) printf("\n");
52687219dbVictor Latushkin			return;
52787219dbVictor Latushkin		}
52887219dbVictor Latushkin		children = c + 1;
52987219dbVictor Latushkin	}
53087219dbVictor Latushkin	for (; c < children; c++) {
53187219dbVictor Latushkin		vd = rvd->vdev_child[c];
53287219dbVictor Latushkin		print_vdev_metaslab_header(vd);
534fa9e406ahrens		for (m = 0; m < vd->vdev_ms_count; m++)
535fa9e406ahrens			dump_metaslab(vd->vdev_ms[m]);
536fa9e406ahrens		(void) printf("\n");
537fa9e406ahrens	}
540fa9e406ahrensstatic void
541b24ab67Jeff Bonwickdump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
542b24ab67Jeff Bonwick{
543b24ab67Jeff Bonwick	const ddt_phys_t *ddp = dde->dde_phys;
544b24ab67Jeff Bonwick	const ddt_key_t *ddk = &dde->dde_key;
545b24ab67Jeff Bonwick	char *types[4] = { "ditto", "single", "double", "triple" };
546b24ab67Jeff Bonwick	char blkbuf[BP_SPRINTF_LEN];
547b24ab67Jeff Bonwick	blkptr_t blk;
548b24ab67Jeff Bonwick
549b24ab67Jeff Bonwick	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
550b24ab67Jeff Bonwick		if (ddp->ddp_phys_birth == 0)
551b24ab67Jeff Bonwick			continue;
552b24ab67Jeff Bonwick		ddt_bp_create(ddt, ddk, ddp, &blk);
553b24ab67Jeff Bonwick		sprintf_blkptr(blkbuf, &blk);
554b24ab67Jeff Bonwick		(void) printf("index %llx refcnt %llu %s %s\n",
555b24ab67Jeff Bonwick		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
556b24ab67Jeff Bonwick		    types[p], blkbuf);
557b24ab67Jeff Bonwick	}
558b24ab67Jeff Bonwick}
559b24ab67Jeff Bonwick
560b24ab67Jeff Bonwickstatic void
561b24ab67Jeff Bonwickdump_dedup_ratio(const ddt_stat_t *dds)
562b24ab67Jeff Bonwick{
563b24ab67Jeff Bonwick	double rL, rP, rD, D, dedup, compress, copies;
564b24ab67Jeff Bonwick
565b24ab67Jeff Bonwick	if (dds->dds_blocks == 0)
566b24ab67Jeff Bonwick		return;
567b24ab67Jeff Bonwick
568b24ab67Jeff Bonwick	rL = (double)dds->dds_ref_lsize;
569b24ab67Jeff Bonwick	rP = (double)dds->dds_ref_psize;
570b24ab67Jeff Bonwick	rD = (double)dds->dds_ref_dsize;
571b24ab67Jeff Bonwick	D = (double)dds->dds_dsize;
572b24ab67Jeff Bonwick
573b24ab67Jeff Bonwick	dedup = rD / D;
574b24ab67Jeff Bonwick	compress = rL / rP;
575b24ab67Jeff Bonwick	copies = rD / rP;
576b24ab67Jeff Bonwick
577b24ab67Jeff Bonwick	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
578b24ab67Jeff Bonwick	    "dedup * compress / copies = %.2f\n\n",
579b24ab67Jeff Bonwick	    dedup, compress, copies, dedup * compress / copies);
580b24ab67Jeff Bonwick}
581b24ab67Jeff Bonwick
582b24ab67Jeff Bonwickstatic void
583b24ab67Jeff Bonwickdump_ddt_stat(const ddt_stat_t *dds, int h)
584b24ab67Jeff Bonwick{
585b24ab67Jeff Bonwick	char refcnt[6];
586b24ab67Jeff Bonwick	char blocks[6], lsize[6], psize[6], dsize[6];
587b24ab67Jeff Bonwick	char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6];
588b24ab67Jeff Bonwick
589b24ab67Jeff Bonwick	if (dds->dds_blocks == 0)
590b24ab67Jeff Bonwick		return;
591b24ab67Jeff Bonwick
592b24ab67Jeff Bonwick	if (h == -1)
593b24ab67Jeff Bonwick		(void) strcpy(refcnt, "Total");
594b24ab67Jeff Bonwick	else
595b24ab67Jeff Bonwick		nicenum(1ULL << h, refcnt);
596b24ab67Jeff Bonwick
597b24ab67Jeff Bonwick	nicenum(dds->dds_blocks, blocks);
598b24ab67Jeff Bonwick	nicenum(dds->dds_lsize, lsize);
599b24ab67Jeff Bonwick	nicenum(dds->dds_psize, psize);
600b24ab67Jeff Bonwick	nicenum(dds->dds_dsize, dsize);
601b24ab67Jeff Bonwick	nicenum(dds->dds_ref_blocks, ref_blocks);
602b24ab67Jeff Bonwick	nicenum(dds->dds_ref_lsize, ref_lsize);
603b24ab67Jeff Bonwick	nicenum(dds->dds_ref_psize, ref_psize);
604b24ab67Jeff Bonwick	nicenum(dds->dds_ref_dsize, ref_dsize);
605b24ab67Jeff Bonwick
606b24ab67Jeff Bonwick	(void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
607b24ab67Jeff Bonwick	    refcnt,
608b24ab67Jeff Bonwick	    blocks, lsize, psize, dsize,
609b24ab67Jeff Bonwick	    ref_blocks, ref_lsize, ref_psize, ref_dsize);
610b24ab67Jeff Bonwick}
611b24ab67Jeff Bonwick
612b24ab67Jeff Bonwickstatic void
613b24ab67Jeff Bonwickdump_ddt_histogram(const ddt_histogram_t *ddh)
614b24ab67Jeff Bonwick{
615b24ab67Jeff Bonwick	ddt_stat_t dds_total = { 0 };
616b24ab67Jeff Bonwick
617b24ab67Jeff Bonwick	ddt_histogram_stat(&dds_total, ddh);
618b24ab67Jeff Bonwick
619b24ab67Jeff Bonwick	(void) printf("\n");
620b24ab67Jeff Bonwick
621b24ab67Jeff Bonwick	(void) printf("bucket   "
622b24ab67Jeff Bonwick	    "           allocated             "
623b24ab67Jeff Bonwick	    "          referenced          \n");
624b24ab67Jeff Bonwick	(void) printf("______   "
625b24ab67Jeff Bonwick	    "______________________________   "
626b24ab67Jeff Bonwick	    "______________________________\n");
627b24ab67Jeff Bonwick
628b24ab67Jeff Bonwick	(void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
629b24ab67Jeff Bonwick	    "refcnt",
630b24ab67Jeff Bonwick	    "blocks", "LSIZE", "PSIZE", "DSIZE",
631b24ab67Jeff Bonwick	    "blocks", "LSIZE", "PSIZE", "DSIZE");
632b24ab67Jeff Bonwick
633b24ab67Jeff Bonwick	(void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
634b24ab67Jeff Bonwick	    "------",
635b24ab67Jeff Bonwick	    "------", "-----", "-----", "-----",
636b24ab67Jeff Bonwick	    "------", "-----", "-----", "-----");
637b24ab67Jeff Bonwick
638b24ab67Jeff Bonwick	for (int h = 0; h < 64; h++)
639b24ab67Jeff Bonwick		dump_ddt_stat(&ddh->ddh_stat[h], h);
640b24ab67Jeff Bonwick
641b24ab67Jeff Bonwick	dump_ddt_stat(&dds_total, -1);
642b24ab67Jeff Bonwick
643b24ab67Jeff Bonwick	(void) printf("\n");
644b24ab67Jeff Bonwick}
645b24ab67Jeff Bonwick
646b24ab67Jeff Bonwickstatic void
647b24ab67Jeff Bonwickdump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
648b24ab67Jeff Bonwick{
649b24ab67Jeff Bonwick	char name[DDT_NAMELEN];
650b24ab67Jeff Bonwick	ddt_entry_t dde;
651b24ab67Jeff Bonwick	uint64_t walk = 0;
652b24ab67Jeff Bonwick	dmu_object_info_t doi;
653b24ab67Jeff Bonwick	uint64_t count, dspace, mspace;
654b24ab67Jeff Bonwick	int error;
655b24ab67Jeff Bonwick
656b24ab67Jeff Bonwick	error = ddt_object_info(ddt, type, class, &doi);
657b24ab67Jeff Bonwick
658b24ab67Jeff Bonwick	if (error == ENOENT)
659b24ab67Jeff Bonwick		return;
660b24ab67Jeff Bonwick	ASSERT(error == 0);
661b24ab67Jeff Bonwick
662b24ab67Jeff Bonwick	count = ddt_object_count(ddt, type, class);
663b24ab67Jeff Bonwick	dspace = doi.doi_physical_blocks_512 << 9;
664b24ab67Jeff Bonwick	mspace = doi.doi_fill_count * doi.doi_data_block_size;
665b24ab67Jeff Bonwick
666b24ab67Jeff Bonwick	ASSERT(count != 0);	/* we should have destroyed it */
667b24ab67Jeff Bonwick
668b24ab67Jeff Bonwick	ddt_object_name(ddt, type, class, name);
669b24ab67Jeff Bonwick
670b24ab67Jeff Bonwick	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
671b24ab67Jeff Bonwick	    name,
672b24ab67Jeff Bonwick	    (u_longlong_t)count,
673b24ab67Jeff Bonwick	    (u_longlong_t)(dspace / count),
674b24ab67Jeff Bonwick	    (u_longlong_t)(mspace / count));
675b24ab67Jeff Bonwick
676b24ab67Jeff Bonwick	if (dump_opt['D'] < 3)
677b24ab67Jeff Bonwick		return;
678b24ab67Jeff Bonwick
679b24ab67Jeff Bonwick	dump_ddt_histogram(&ddt->ddt_histogram[type][class]);
680b24ab67Jeff Bonwick
681b24ab67Jeff Bonwick	if (dump_opt['D'] < 4)
682b24ab67Jeff Bonwick		return;
683b24ab67Jeff Bonwick
684b24ab67Jeff Bonwick	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
685b24ab67Jeff Bonwick		return;
686b24ab67Jeff Bonwick
687b24ab67Jeff Bonwick	(void) printf("%s contents:\n\n", name);
688b24ab67Jeff Bonwick
689b24ab67Jeff Bonwick	while ((error = ddt_object_walk(ddt, type, class, &dde, &walk)) == 0)
690b24ab67Jeff Bonwick		dump_dde(ddt, &dde, walk);
691b24ab67Jeff Bonwick
692b24ab67Jeff Bonwick	ASSERT(error == ENOENT);
693b24ab67Jeff Bonwick
694b24ab67Jeff Bonwick	(void) printf("\n");
695b24ab67Jeff Bonwick}
696b24ab67Jeff Bonwick
697b24ab67Jeff Bonwickstatic void
698b24ab67Jeff Bonwickdump_all_ddts(spa_t *spa)
699b24ab67Jeff Bonwick{
700b24ab67Jeff Bonwick	ddt_histogram_t ddh_total = { 0 };
701b24ab67Jeff Bonwick	ddt_stat_t dds_total = { 0 };
702b24ab67Jeff Bonwick
703b24ab67Jeff Bonwick	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
704b24ab67Jeff Bonwick		ddt_t *ddt = spa->spa_ddt[c];
705b24ab67Jeff Bonwick		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
706b24ab67Jeff Bonwick			for (enum ddt_class class = 0; class < DDT_CLASSES;
707b24ab67Jeff Bonwick			    class++) {
708b24ab67Jeff Bonwick				ddt_histogram_add(&ddh_total,
709b24ab67Jeff Bonwick				    &ddt->ddt_histogram[type][class]);
710b24ab67Jeff Bonwick				dump_ddt(ddt, type, class);
711b24ab67Jeff Bonwick			}
712b24ab67Jeff Bonwick		}
713b24ab67Jeff Bonwick	}
714b24ab67Jeff Bonwick
715b24ab67Jeff Bonwick	ddt_histogram_stat(&dds_total, &ddh_total);
716b24ab67Jeff Bonwick
717b24ab67Jeff Bonwick	if (dds_total.dds_blocks == 0) {
718b24ab67Jeff Bonwick		(void) printf("All DDTs are empty\n");
719b24ab67Jeff Bonwick		return;
720b24ab67Jeff Bonwick	}
721b24ab67Jeff Bonwick
722b24ab67Jeff Bonwick	(void) printf("\n");
723b24ab67Jeff Bonwick
724b24ab67Jeff Bonwick	if (dump_opt['D'] > 1) {
725b24ab67Jeff Bonwick		(void) printf("DDT histogram (aggregated over all DDTs):\n");
726b24ab67Jeff Bonwick		dump_ddt_histogram(&ddh_total);
727b24ab67Jeff Bonwick	}
728b24ab67Jeff Bonwick
729b24ab67Jeff Bonwick	dump_dedup_ratio(&dds_total);
730b24ab67Jeff Bonwick}
731b24ab67Jeff Bonwick
732b24ab67Jeff Bonwickstatic void
7338ad4d6dJeff Bonwickdump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size)
7348ad4d6dJeff Bonwick{
7358ad4d6dJeff Bonwick	char *prefix = (void *)sm;
7368ad4d6dJeff Bonwick
7378ad4d6dJeff Bonwick	(void) printf("%s [%llu,%llu) length %llu\n",
7388ad4d6dJeff Bonwick	    prefix,
7398ad4d6dJeff Bonwick	    (u_longlong_t)start,
7408ad4d6dJeff Bonwick	    (u_longlong_t)(start + size),
7418ad4d6dJeff Bonwick	    (u_longlong_t)(size));
7428ad4d6dJeff Bonwick}
7438ad4d6dJeff Bonwick
7448ad4d6dJeff Bonwickstatic void
745fa9e406ahrensdump_dtl(vdev_t *vd, int indent)
7478ad4d6dJeff Bonwick	spa_t *spa = vd->vdev_spa;
7488ad4d6dJeff Bonwick	boolean_t required;
7498ad4d6dJeff Bonwick	char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" };
7508ad4d6dJeff Bonwick	char prefix[256];
7518ad4d6dJeff Bonwick
7528f18d1fGeorge Wilson	spa_vdev_state_enter(spa, SCL_NONE);
7538ad4d6dJeff Bonwick	required = vdev_dtl_required(vd);
7548ad4d6dJeff Bonwick	(void) spa_vdev_state_exit(spa, NULL, 0);
756fa9e406ahrens	if (indent == 0)
757fa9e406ahrens		(void) printf("\nDirty time logs:\n\n");
7598ad4d6dJeff Bonwick	(void) printf("\t%*s%s [%s]\n", indent, "",
760e14bb32Jeff Bonwick	    vd->vdev_path ? vd->vdev_path :
7618ad4d6dJeff Bonwick	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
7628ad4d6dJeff Bonwick	    required ? "DTL-required" : "DTL-expendable");
7648ad4d6dJeff Bonwick	for (int t = 0; t < DTL_TYPES; t++) {
7658ad4d6dJeff Bonwick		space_map_t *sm = &vd->vdev_dtl[t];
7668ad4d6dJeff Bonwick		if (sm->sm_space == 0)
7678ad4d6dJeff Bonwick			continue;
7688ad4d6dJeff Bonwick		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
7698ad4d6dJeff Bonwick		    indent + 2, "", name[t]);
7708ad4d6dJeff Bonwick		mutex_enter(sm->sm_lock);
7718ad4d6dJeff Bonwick		space_map_walk(sm, dump_dtl_seg, (void *)prefix);
7728ad4d6dJeff Bonwick		mutex_exit(sm->sm_lock);
7738ad4d6dJeff Bonwick		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
7748ad4d6dJeff Bonwick			dump_spacemap(spa->spa_meta_objset,
7758ad4d6dJeff Bonwick			    &vd->vdev_dtl_smo, sm);
776fa9e406ahrens	}
7788ad4d6dJeff Bonwick	for (int c = 0; c < vd->vdev_children; c++)
779fa9e406ahrens		dump_dtl(vd->vdev_child[c], indent + 4);
7828f18d1fGeorge Wilsonstatic void
7838f18d1fGeorge Wilsondump_history(spa_t *spa)
7848f18d1fGeorge Wilson{
7858f18d1fGeorge Wilson	nvlist_t **events = NULL;
7868f18d1fGeorge Wilson	char buf[SPA_MAXBLOCKSIZE];
787e4161dfVictor Latushkin	uint64_t resid, len, off = 0;
7888f18d1fGeorge Wilson	uint_t num = 0;
7898f18d1fGeorge Wilson	int error;
7908f18d1fGeorge Wilson	time_t tsec;
7918f18d1fGeorge Wilson	struct tm t;
7928f18d1fGeorge Wilson	char tbuf[30];
7938f18d1fGeorge Wilson	char internalstr[MAXPATHLEN];
7948f18d1fGeorge Wilson
7958f18d1fGeorge Wilson	do {
796e4161dfVictor Latushkin		len = sizeof (buf);
797e4161dfVictor Latushkin
7988f18d1fGeorge Wilson		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
7998f18d1fGeorge Wilson			(void) fprintf(stderr, "Unable to read history: "
8008f18d1fGeorge Wilson			    "error %d\n", error);
8018f18d1fGeorge Wilson			return;
8028f18d1fGeorge Wilson		}
8038f18d1fGeorge Wilson
8048f18d1fGeorge Wilson		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
8058f18d1fGeorge Wilson			break;
8068f18d1fGeorge Wilson
8078f18d1fGeorge Wilson		off -= resid;
8088f18d1fGeorge Wilson	} while (len != 0);
8098f18d1fGeorge Wilson
8108f18d1fGeorge Wilson	(void) printf("\nHistory:\n");
8118f18d1fGeorge Wilson	for (int i = 0; i < num; i++) {
8128f18d1fGeorge Wilson		uint64_t time, txg, ievent;
8138f18d1fGeorge Wilson		char *cmd, *intstr;
8148f18d1fGeorge Wilson
8158f18d1fGeorge Wilson		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
8168f18d1fGeorge Wilson		    &time) != 0)
8178f18d1fGeorge Wilson			continue;
8188f18d1fGeorge Wilson		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
8198f18d1fGeorge Wilson		    &cmd) != 0) {
8208f18d1fGeorge Wilson			if (nvlist_lookup_uint64(events[i],
8218f18d1fGeorge Wilson			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
8228f18d1fGeorge Wilson				continue;
8238f18d1fGeorge Wilson			verify(nvlist_lookup_uint64(events[i],
8248f18d1fGeorge Wilson			    ZPOOL_HIST_TXG, &txg) == 0);
8258f18d1fGeorge Wilson			verify(nvlist_lookup_string(events[i],
8268f18d1fGeorge Wilson			    ZPOOL_HIST_INT_STR, &intstr) == 0);
8278f18d1fGeorge Wilson			if (ievent >= LOG_END)
8288f18d1fGeorge Wilson				continue;
8298f18d1fGeorge Wilson
8308f18d1fGeorge Wilson			(void) snprintf(internalstr,
8318f18d1fGeorge Wilson			    sizeof (internalstr),
8328f18d1fGeorge Wilson			    "[internal %s txg:%lld] %s",
8338f18d1fGeorge Wilson			    hist_event_table[ievent], txg,
8348f18d1fGeorge Wilson			    intstr);
8358f18d1fGeorge Wilson			cmd = internalstr;
8368f18d1fGeorge Wilson		}
8378f18d1fGeorge Wilson		tsec = time;
8388f18d1fGeorge Wilson		(void) localtime_r(&tsec, &t);
8398f18d1fGeorge Wilson		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
8408f18d1fGeorge Wilson		(void) printf("%s %s\n", tbuf, cmd);
8418f18d1fGeorge Wilson	}
8428f18d1fGeorge Wilson}
8438f18d1fGeorge Wilson
845fa9e406ahrensstatic void
846fa9e406ahrensdump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
850fa9e406ahrensstatic uint64_t
851b24ab67Jeff Bonwickblkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp, const zbookmark_t *zb)
853b24ab67Jeff Bonwick	if (dnp == NULL) {
854b24ab67Jeff Bonwick		ASSERT(zb->zb_level < 0);
855b24ab67Jeff Bonwick		if (zb->zb_object == 0)
856b24ab67Jeff Bonwick			return (zb->zb_blkid);
857b24ab67Jeff Bonwick		return (zb->zb_blkid * BP_GET_LSIZE(bp));
858b24ab67Jeff Bonwick	}
859b24ab67Jeff Bonwick
860b24ab67Jeff Bonwick	ASSERT(zb->zb_level >= 0);
862b24ab67Jeff Bonwick	return ((zb->zb_blkid <<
863b24ab67Jeff Bonwick	    (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
864fa9e406ahrens	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
86744cd46cbillmstatic void
868b24ab67Jeff Bonwicksprintf_blkptr_compact(char *blkbuf, blkptr_t *bp)
87044cd46cbillm	dva_t *dva = bp->blk_dva;
871b24ab67Jeff Bonwick	int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
872b24ab67Jeff Bonwick
873b24ab67Jeff Bonwick	if (dump_opt['b'] >= 5) {
874b24ab67Jeff Bonwick		sprintf_blkptr(blkbuf, bp);
875b24ab67Jeff Bonwick		return;
876b24ab67Jeff Bonwick	}
87844cd46cbillm	blkbuf[0] = '\0';
880b24ab67Jeff Bonwick	for (int i = 0; i < ndvas; i++)
88144cd46cbillm		(void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ",
88244cd46cbillm		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
88344cd46cbillm		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
88444cd46cbillm		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
886b24ab67Jeff Bonwick	(void) sprintf(blkbuf + strlen(blkbuf),
887b24ab67Jeff Bonwick	    "%llxL/%llxP F=%llu B=%llu/%llu",
88844cd46cbillm	    (u_longlong_t)BP_GET_LSIZE(bp),
88944cd46cbillm	    (u_longlong_t)BP_GET_PSIZE(bp),
89044cd46cbillm	    (u_longlong_t)bp->blk_fill,
891b24ab67Jeff Bonwick	    (u_longlong_t)bp->blk_birth,
892b24ab67Jeff Bonwick	    (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
89588b7b0fMatthew Ahrensstatic void
89688b7b0fMatthew Ahrensprint_indirect(blkptr_t *bp, const zbookmark_t *zb,
89788b7b0fMatthew Ahrens    const dnode_phys_t *dnp)
89988b7b0fMatthew Ahrens	char blkbuf[BP_SPRINTF_LEN];
900fa9e406ahrens	int l;
90288b7b0fMatthew Ahrens	ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
90388b7b0fMatthew Ahrens	ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
905b24ab67Jeff Bonwick	(void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
907fa9e406ahrens	ASSERT(zb->zb_level >= 0);
909fa9e406ahrens	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
910fa9e406ahrens		if (l == zb->zb_level) {
91188b7b0fMatthew Ahrens			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
912fa9e406ahrens		} else {
91388b7b0fMatthew Ahrens			(void) printf(" ");
914fa9e406ahrens		}
915fa9e406ahrens	}
917b24ab67Jeff Bonwick	sprintf_blkptr_compact(blkbuf, bp);
91888b7b0fMatthew Ahrens	(void) printf("%s\n", blkbuf);
91988b7b0fMatthew Ahrens}
92088b7b0fMatthew Ahrens
92188b7b0fMatthew Ahrensstatic int
92288b7b0fMatthew Ahrensvisit_indirect(spa_t *spa, const dnode_phys_t *dnp,
92388b7b0fMatthew Ahrens    blkptr_t *bp, const zbookmark_t *zb)
92488b7b0fMatthew Ahrens{
925e4161dfVictor Latushkin	int err = 0;
92688b7b0fMatthew Ahrens
92788b7b0fMatthew Ahrens	if (bp->blk_birth == 0)
92888b7b0fMatthew Ahrens		return (0);
92988b7b0fMatthew Ahrens
93088b7b0fMatthew Ahrens	print_indirect(bp, zb, dnp);
93188b7b0fMatthew Ahrens
93288b7b0fMatthew Ahrens	if (BP_GET_LEVEL(bp) > 0) {
93388b7b0fMatthew Ahrens		uint32_t flags = ARC_WAIT;
93488b7b0fMatthew Ahrens		int i;
93588b7b0fMatthew Ahrens		blkptr_t *cbp;
93688b7b0fMatthew Ahrens		int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
93788b7b0fMatthew Ahrens		arc_buf_t *buf;
93888b7b0fMatthew Ahrens		uint64_t fill = 0;
93988b7b0fMatthew Ahrens
94088b7b0fMatthew Ahrens		err = arc_read_nolock(NULL, spa, bp, arc_getbuf_func, &buf,
94188b7b0fMatthew Ahrens		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
94288b7b0fMatthew Ahrens		if (err)
94388b7b0fMatthew Ahrens			return (err);
94488b7b0fMatthew Ahrens
94588b7b0fMatthew Ahrens		/* recursively visit blocks below this */
94688b7b0fMatthew Ahrens		cbp = buf->b_data;
94788b7b0fMatthew Ahrens		for (i = 0; i < epb; i++, cbp++) {
94888b7b0fMatthew Ahrens			zbookmark_t czb;
94988b7b0fMatthew Ahrens
95088b7b0fMatthew Ahrens			SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
95188b7b0fMatthew Ahrens			    zb->zb_level - 1,
95288b7b0fMatthew Ahrens			    zb->zb_blkid * epb + i);
95388b7b0fMatthew Ahrens			err = visit_indirect(spa, dnp, cbp, &czb);
95488b7b0fMatthew Ahrens			if (err)
95588b7b0fMatthew Ahrens				break;
95688b7b0fMatthew Ahrens			fill += cbp->blk_fill;
95788b7b0fMatthew Ahrens		}
9588ad4d6dJeff Bonwick		if (!err)
9598ad4d6dJeff Bonwick			ASSERT3U(fill, ==, bp->blk_fill);
96088b7b0fMatthew Ahrens		(void) arc_buf_remove_ref(buf, &buf);
961fa9e406ahrens	}
96388b7b0fMatthew Ahrens	return (err);
967fa9e406ahrensstatic void
96888b7b0fMatthew Ahrensdump_indirect(dnode_t *dn)
97088b7b0fMatthew Ahrens	dnode_phys_t *dnp = dn->dn_phys;
97188b7b0fMatthew Ahrens	int j;
97288b7b0fMatthew Ahrens	zbookmark_t czb;
974fa9e406ahrens	(void) printf("Indirect blocks:\n");
976503ad85Matthew Ahrens	SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset),
97788b7b0fMatthew Ahrens	    dn->dn_object, dnp->dn_nlevels - 1, 0);
97888b7b0fMatthew Ahrens	for (j = 0; j < dnp->dn_nblkptr; j++) {
97988b7b0fMatthew Ahrens		czb.zb_blkid = j;
980503ad85Matthew Ahrens		(void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp,
98188b7b0fMatthew Ahrens		    &dnp->dn_blkptr[j], &czb);
98288b7b0fMatthew Ahrens	}
984fa9e406ahrens	(void) printf("\n");
988fa9e406ahrensstatic void
989fa9e406ahrensdump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
991fa9e406ahrens	dsl_dir_phys_t *dd = data;
992fa9e406ahrens	time_t crtime;
99374e7dc9Matthew Ahrens	char nice[6];
995fa9e406ahrens	if (dd == NULL)
996fa9e406ahrens		return;