zdb.c revision 06be98028b8a84e7f327188613dd09a708294d1a
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 */
21ad135b5Christopher Siden
238f2529dMark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
247802d7bMatthew Ahrens * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
25fa9e406ahrens */
27fa9e406ahrens#include <stdio.h>
28490d05bMatthew Ahrens#include <unistd.h>
29004388ecasper#include <stdio_ext.h>
30fa9e406ahrens#include <stdlib.h>
3144cd46cbillm#include <ctype.h>
32fa9e406ahrens#include <sys/zfs_context.h>
33fa9e406ahrens#include <sys/spa.h>
34fa9e406ahrens#include <sys/spa_impl.h>
35fa9e406ahrens#include <sys/dmu.h>
36fa9e406ahrens#include <sys/zap.h>
37fa9e406ahrens#include <sys/fs/zfs.h>
38fa9e406ahrens#include <sys/zfs_znode.h>
390a586ceMark Shellenbaum#include <sys/zfs_sa.h>
400a586ceMark Shellenbaum#include <sys/sa.h>
410a586ceMark Shellenbaum#include <sys/sa_impl.h>
42fa9e406ahrens#include <sys/vdev.h>
43fa9e406ahrens#include <sys/vdev_impl.h>
44fa9e406ahrens#include <sys/metaslab_impl.h>
45fa9e406ahrens#include <sys/dmu_objset.h>
46fa9e406ahrens#include <sys/dsl_dir.h>
47fa9e406ahrens#include <sys/dsl_dataset.h>
48fa9e406ahrens#include <sys/dsl_pool.h>
49fa9e406ahrens#include <sys/dbuf.h>
50fa9e406ahrens#include <sys/zil.h>
51fa9e406ahrens#include <sys/zil_impl.h>
52fa9e406ahrens#include <sys/stat.h>
53fa9e406ahrens#include <sys/resource.h>
54fa9e406ahrens#include <sys/dmu_traverse.h>
55fa9e406ahrens#include <sys/zio_checksum.h>
56fa9e406ahrens#include <sys/zio_compress.h>
57e0d35c4marks#include <sys/zfs_fuid.h>
5888b7b0fMatthew Ahrens#include <sys/arc.h>
59b24ab67Jeff Bonwick#include <sys/ddt.h>
60ad135b5Christopher Siden#include <sys/zfeature.h>
614445fffMatthew Ahrens#include <zfs_comutil.h>
62de6628fck#undef ZFS_MAXNAMELEN
63de6628fck#undef verify
64de6628fck#include <libzfs.h>
66e690fb2Christopher Siden#define	ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ?	\
67e690fb2Christopher Siden	zio_compress_table[(idx)].ci_name : "UNKNOWN")
68e690fb2Christopher Siden#define	ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ?	\
69e690fb2Christopher Siden	zio_checksum_table[(idx)].ci_name : "UNKNOWN")
70e690fb2Christopher Siden#define	ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ?	\
71e690fb2Christopher Siden	dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ?	\
72e690fb2Christopher Siden	dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN")
73e690fb2Christopher Siden#define	ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) :		\
74e690fb2Christopher Siden	(((idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA) ?	\
75e690fb2Christopher Siden	DMU_OT_ZAP_OTHER : DMU_OT_NUMTYPES))
766de8f41Victor Latushkin
77feef89cVictor Latushkin#ifndef lint
787fd05acMatthew Ahrensextern boolean_t zfs_recover;
7906be980Matthew Ahrensextern uint64_t zfs_arc_max, zfs_arc_meta_limit;
80feef89cVictor Latushkin#else
817fd05acMatthew Ahrensboolean_t zfs_recover;
8206be980Matthew Ahrensuint64_t zfs_arc_max, zfs_arc_meta_limit;
83feef89cVictor Latushkin#endif
84feef89cVictor Latushkin
85fa9e406ahrensconst char cmdname[] = "zdb";
86fa9e406ahrensuint8_t dump_opt[256];
88fa9e406ahrenstypedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
90fa9e406ahrensextern void dump_intent_log(zilog_t *);
91fa9e406ahrensuint64_t *zopt_object = NULL;
92fa9e406ahrensint zopt_objects = 0;
93de6628fcklibzfs_handle_t *g_zfs;
9406be980Matthew Ahrensuint64_t max_inflight = 1000;
97fa9e406ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
98fa9e406ahrens * debugging facilities.
99fa9e406ahrens */
100fa9e406ahrensconst char *
103fa9e406ahrens	return ("default,verbose"); /* $UMEM_DEBUG setting */
106fa9e406ahrensconst char *
109fa9e406ahrens	return ("fail,contents"); /* $UMEM_LOGGING setting */
112fa9e406ahrensstatic void
115fa9e406ahrens	(void) fprintf(stderr,
1162e4c998George Wilson	    "Usage: %s [-CumMdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
1172e4c998George Wilson	    "[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n"
11831d7e8fGeorge Wilson	    "       %s [-divPA] [-e -p path...] [-U config] dataset "
11931d7e8fGeorge Wilson	    "[object...]\n"
1202e4c998George Wilson	    "       %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
12190e894eRichard Lowe	    "poolname [vdev [metaslab...]]\n"
12290e894eRichard Lowe	    "       %s -R [-A] [-e [-p path...]] poolname "
12390e894eRichard Lowe	    "vdev:offset:size[:flags]\n"
12431d7e8fGeorge Wilson	    "       %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
12590e894eRichard Lowe	    "       %s -l [-uA] device\n"
12690e894eRichard Lowe	    "       %s -C [-A] [-U config]\n\n",
127bbfd46cJeff Bonwick	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
1283ad6c7fVictor Latushkin
1293ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Dataset name must include at least one "
1303ad6c7fVictor Latushkin	    "separator character '/' or '@'\n");
1313ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If dataset name is specified, only that "
1323ad6c7fVictor Latushkin	    "dataset is dumped\n");
1333ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If object numbers are specified, only "
1343ad6c7fVictor Latushkin	    "those objects are dumped\n\n");
1353ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Options to control amount of output:\n");
1363ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -u uberblock\n");
1373ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -d dataset(s)\n");
1383ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -i intent logs\n");
13907428bdVictor Latushkin	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
1408f18d1fGeorge Wilson	(void) fprintf(stderr, "        -h pool history\n");
1413ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -b block statistics\n");
1423ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -m metaslabs\n");
1432e4c998George Wilson	(void) fprintf(stderr, "        -M metaslab groups\n");
1443ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
1456365109Victor Latushkin	    "all data) blocks\n");
1463ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
147f0ba89bJeff Bonwick	(void) fprintf(stderr, "        -D dedup statistics\n");
148b24ab67Jeff Bonwick	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
1493ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
150fa9e406ahrens	(void) fprintf(stderr, "        -l dump label contents\n");
15182a0a98Victor Latushkin	(void) fprintf(stderr, "        -L disable leak tracking (do not "
15282a0a98Victor Latushkin	    "load spacemaps)\n");
153d41e764ek	(void) fprintf(stderr, "        -R read and display block from a "
1543ad6c7fVictor Latushkin	    "device\n\n");
1553ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Below options are intended for use "
156df15e41Matthew Ahrens	    "with other options:\n");
157feef89cVictor Latushkin	(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
158feef89cVictor Latushkin	    "panic recovery (-AA) or both (-AAA)\n");
159c8ee184Victor Latushkin	(void) fprintf(stderr, "        -F attempt automatic rewind within "
160c8ee184Victor Latushkin	    "safe range of transaction groups\n");
1613ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
1623ad6c7fVictor Latushkin	    "cachefile\n");
163c8ee184Victor Latushkin	(void) fprintf(stderr, "        -X attempt extreme rewind (does not "
164c8ee184Victor Latushkin	    "work with dataset)\n");
1653ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
1663ad6c7fVictor Latushkin	    "has altroot/not in a cachefile\n");
1673ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -p <path> -- use one or more with "
1683ad6c7fVictor Latushkin	    "-e to specify path to vdev dir\n");
169df15e41Matthew Ahrens	(void) fprintf(stderr, "        -x <dumpdir> -- "
170df15e41Matthew Ahrens	    "dump all read blocks into specified directory\n");
17190e894eRichard Lowe	(void) fprintf(stderr, "        -P print numbers in parseable form\n");
1723ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
1732e55192Victor Latushkin	    "searching for uberblocks\n");
1742e4c998George Wilson	(void) fprintf(stderr, "        -I <number of inflight I/Os> -- "
175df15e41Matthew Ahrens	    "specify the maximum number of "
176df15e41Matthew Ahrens	    "checksumming I/Os [default is 200]\n");
177fa9e406ahrens	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
178fa9e406ahrens	    "to make only that option verbose\n");
179fa9e406ahrens	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
180fa9e406ahrens	exit(1);
183ccba080Rich Morris/*
184ccba080Rich Morris * Called for usage errors that are discovered after a call to spa_open(),
185ccba080Rich Morris * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
186ccba080Rich Morris */
187ccba080Rich Morris
188fa9e406ahrensstatic void
189fa9e406ahrensfatal(const char *fmt, ...)
191fa9e406ahrens	va_list ap;
193fa9e406ahrens	va_start(ap, fmt);
194fa9e406ahrens	(void) fprintf(stderr, "%s: ", cmdname);
195fa9e406ahrens	(void) vfprintf(stderr, fmt, ap);
196fa9e406ahrens	va_end(ap);
197fa9e406ahrens	(void) fprintf(stderr, "\n");
199ccba080Rich Morris	exit(1);
202fa9e406ahrens/* ARGSUSED */
203fa9e406ahrensstatic void
204fa9e406ahrensdump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
206fa9e406ahrens	nvlist_t *nv;
207fa9e406ahrens	size_t nvsize = *(uint64_t *)data;
208fa9e406ahrens	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
2107bfdf01Neil Perrin	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
212fa9e406ahrens	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
214fa9e406ahrens	umem_free(packed, nvsize);
216fa9e406ahrens	dump_nvlist(nv, 8);
218fa9e406ahrens	nvlist_free(nv);
2214445fffMatthew Ahrens/* ARGSUSED */
2224445fffMatthew Ahrensstatic void
2234445fffMatthew Ahrensdump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
2244445fffMatthew Ahrens{
2254445fffMatthew Ahrens	spa_history_phys_t *shp = data;
2264445fffMatthew Ahrens
2274445fffMatthew Ahrens	if (shp == NULL)
2284445fffMatthew Ahrens		return;
2294445fffMatthew Ahrens
2304445fffMatthew Ahrens	(void) printf("\t\tpool_create_len = %llu\n",
2314445fffMatthew Ahrens	    (u_longlong_t)shp->sh_pool_create_len);
2324445fffMatthew Ahrens	(void) printf("\t\tphys_max_off = %llu\n",
2334445fffMatthew Ahrens	    (u_longlong_t)shp->sh_phys_max_off);
2344445fffMatthew Ahrens	(void) printf("\t\tbof = %llu\n",
2354445fffMatthew Ahrens	    (u_longlong_t)shp->sh_bof);
2364445fffMatthew Ahrens	(void) printf("\t\teof = %llu\n",
2374445fffMatthew Ahrens	    (u_longlong_t)shp->sh_eof);
2384445fffMatthew Ahrens	(void) printf("\t\trecords_lost = %llu\n",
2394445fffMatthew Ahrens	    (u_longlong_t)shp->sh_records_lost);
2404445fffMatthew Ahrens}
2414445fffMatthew Ahrens
2423f9d6adLin Lingstatic void
2433f9d6adLin Lingzdb_nicenum(uint64_t num, char *buf)
2443f9d6adLin Ling{
2453f9d6adLin Ling	if (dump_opt['P'])
2463f9d6adLin Ling		(void) sprintf(buf, "%llu", (longlong_t)num);
2473f9d6adLin Ling	else
2483f9d6adLin Ling		nicenum(num, buf);
2493f9d6adLin Ling}
2503f9d6adLin Ling
251490d05bMatthew Ahrensconst char histo_stars[] = "****************************************";
252490d05bMatthew Ahrensconst int histo_width = sizeof (histo_stars) - 1;
254fa9e406ahrensstatic void
2550713e23George Wilsondump_histogram(const uint64_t *histo, int size, int offset)
257fa9e406ahrens	int i;
258490d05bMatthew Ahrens	int minidx = size - 1;
259fa9e406ahrens	int maxidx = 0;
260fa9e406ahrens	uint64_t max = 0;
262490d05bMatthew Ahrens	for (i = 0; i < size; i++) {
263fa9e406ahrens		if (histo[i] > max)
264fa9e406ahrens			max = histo[i];
265fa9e406ahrens		if (histo[i] > 0 && i > maxidx)
266fa9e406ahrens			maxidx = i;
267fa9e406ahrens		if (histo[i] > 0 && i < minidx)
268fa9e406ahrens			minidx = i;
269fa9e406ahrens	}
271490d05bMatthew Ahrens	if (max < histo_width)
272490d05bMatthew Ahrens		max = histo_width;
274490d05bMatthew Ahrens	for (i = minidx; i <= maxidx; i++) {
275490d05bMatthew Ahrens		(void) printf("\t\t\t%3u: %6llu %s\n",
2760713e23George Wilson		    i + offset, (u_longlong_t)histo[i],
277490d05bMatthew Ahrens		    &histo_stars[(max - histo[i]) * histo_width / max]);
278490d05bMatthew Ahrens	}
281fa9e406ahrensstatic void
282fa9e406ahrensdump_zap_stats(objset_t *os, uint64_t object)
284fa9e406ahrens	int error;
285fa9e406ahrens	zap_stats_t zs;
287fa9e406ahrens	error = zap_get_stats(os, object, &zs);
288fa9e406ahrens	if (error)
289fa9e406ahrens		return;
291fa9e406ahrens	if (zs.zs_ptrtbl_len == 0) {
292fa9e406ahrens		ASSERT(zs.zs_num_blocks == 1);
293fa9e406ahrens		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
294fa9e406ahrens		    (u_longlong_t)zs.zs_blocksize,
295fa9e406ahrens		    (u_longlong_t)zs.zs_num_entries);
296fa9e406ahrens		return;
297fa9e406ahrens	}
299fa9e406ahrens	(void) printf("\tFat ZAP stats:\n");
3018248818nd	(void) printf("\t\tPointer table:\n");
3028248818nd	(void) printf("\t\t\t%llu elements\n",
303fa9e406ahrens	    (u_longlong_t)zs.zs_ptrtbl_len);
3048248818nd	(void) printf("\t\t\tzt_blk: %llu\n",
3058248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
3068248818nd	(void) printf("\t\t\tzt_numblks: %llu\n",
3078248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
3088248818nd	(void) printf("\t\t\tzt_shift: %llu\n",
3098248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
3108248818nd	(void) printf("\t\t\tzt_blks_copied: %llu\n",
3118248818nd	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
3128248818nd	(void) printf("\t\t\tzt_nextblk: %llu\n",
3138248818nd	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
315fa9e406ahrens	(void) printf("\t\tZAP entries: %llu\n",
316fa9e406ahrens	    (u_longlong_t)zs.zs_num_entries);
317fa9e406ahrens	(void) printf("\t\tLeaf blocks: %llu\n",
318fa9e406ahrens	    (u_longlong_t)zs.zs_num_leafs);
319fa9e406ahrens	(void) printf("\t\tTotal blocks: %llu\n",
320fa9e406ahrens	    (u_longlong_t)zs.zs_num_blocks);
3218248818nd	(void) printf("\t\tzap_block_type: 0x%llx\n",
3228248818nd	    (u_longlong_t)zs.zs_block_type);
3238248818nd	(void) printf("\t\tzap_magic: 0x%llx\n",
3248248818nd	    (u_longlong_t)zs.zs_magic);
3258248818nd	(void) printf("\t\tzap_salt: 0x%llx\n",
3268248818nd	    (u_longlong_t)zs.zs_salt);
328fa9e406ahrens	(void) printf("\t\tLeafs with 2^n pointers:\n");
3290713e23George Wilson	dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE, 0);
331fa9e406ahrens	(void) printf("\t\tBlocks with n*5 entries:\n");
3320713e23George Wilson	dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE, 0);
334fa9e406ahrens	(void) printf("\t\tBlocks n/10 full:\n");
3350713e23George Wilson	dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE, 0);
337fa9e406ahrens	(void) printf("\t\tEntries with n chunks:\n");
3380713e23George Wilson	dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE, 0);
340fa9e406ahrens	(void) printf("\t\tBuckets with n entries:\n");
3410713e23George Wilson	dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE, 0);
345fa9e406ahrensstatic void
346fa9e406ahrensdump_none(objset_t *os, uint64_t object, void *data, size_t size)
3516de8f41Victor Latushkinstatic void
3526de8f41Victor Latushkindump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
3536de8f41Victor Latushkin{
3546de8f41Victor Latushkin	(void) printf("\tUNKNOWN OBJECT TYPE\n");
3556de8f41Victor Latushkin}
3566de8f41Victor Latushkin
3576de8f41Victor Latushkin/*ARGSUSED*/
359fa9e406ahrensdump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
364fa9e406ahrensstatic void
365fa9e406ahrensdump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
370fa9e406ahrensstatic void
371fa9e406ahrensdump_zap(objset_t *os, uint64_t object, void *data, size_t size)
373fa9e406ahrens	zap_cursor_t zc;
374fa9e406ahrens	zap_attribute_t attr;
375fa9e406ahrens	void *prop;
376fa9e406ahrens	int i;
378fa9e406ahrens	dump_zap_stats(os, object);
379fa9e406ahrens	(void) printf("\n");
381fa9e406ahrens	for (zap_cursor_init(&zc, os, object);
382fa9e406ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
383fa9e406ahrens	    zap_cursor_advance(&zc)) {
384fa9e406ahrens		(void) printf("\t\t%s = ", attr.za_name);
385fa9e406ahrens		if (attr.za_num_integers == 0) {
386fa9e406ahrens			(void) printf("\n");
387fa9e406ahrens			continue;
388fa9e406ahrens		}
389fa9e406ahrens		prop = umem_zalloc(attr.za_num_integers *
390fa9e406ahrens		    attr.za_integer_length, UMEM_NOFAIL);
391fa9e406ahrens		(void) zap_lookup(os, object, attr.za_name,
392fa9e406ahrens		    attr.za_integer_length, attr.za_num_integers, prop);
393fa9e406ahrens		if (attr.za_integer_length == 1) {
394fa9e406ahrens			(void) printf("%s", (char *)prop);
395fa9e406ahrens		} else {
396fa9e406ahrens			for (i = 0; i < attr.za_num_integers; i++) {
397fa9e406ahrens				switch (attr.za_integer_length) {
398fa9e406ahrens				case 2:
399fa9e406ahrens					(void) printf("%u ",
400fa9e406ahrens					    ((uint16_t *)prop)[i]);
401fa9e406ahrens					break;
402fa9e406ahrens				case 4:
403fa9e406ahrens					(void) printf("%u ",
404fa9e406ahrens					    ((uint32_t *)prop)[i]);
405fa9e406ahrens					break;
406fa9e406ahrens				case 8:
407fa9e406ahrens					(void) printf("%lld ",
408fa9e406ahrens					    (u_longlong_t)((int64_t *)prop)[i]);
409fa9e406ahrens					break;
410fa9e406ahrens				}
411fa9e406ahrens			}
412fa9e406ahrens		}
413fa9e406ahrens		(void) printf("\n");
414fa9e406ahrens		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
415fa9e406ahrens	}
41687e5029ahrens	zap_cursor_fini(&zc);
420e743726ahrensstatic void
421486ae71Matthew Ahrensdump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
422486ae71Matthew Ahrens{
423486ae71Matthew Ahrens	dump_zap_stats(os, object);
424486ae71Matthew Ahrens	/* contents are printed elsewhere, properly decoded */
425486ae71Matthew Ahrens}
426486ae71Matthew Ahrens
427486ae71Matthew Ahrens/*ARGSUSED*/
428486ae71Matthew Ahrensstatic void
4290a586ceMark Shellenbaumdump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size)
4300a586ceMark Shellenbaum{
4310a586ceMark Shellenbaum	zap_cursor_t zc;
4320a586ceMark Shellenbaum	zap_attribute_t attr;
4330a586ceMark Shellenbaum
4340a586ceMark Shellenbaum	dump_zap_stats(os, object);
4350a586ceMark Shellenbaum	(void) printf("\n");
4360a586ceMark Shellenbaum
4370a586ceMark Shellenbaum	for (zap_cursor_init(&zc, os, object);
4380a586ceMark Shellenbaum	    zap_cursor_retrieve(&zc, &attr) == 0;
4390a586ceMark Shellenbaum	    zap_cursor_advance(&zc)) {
4400a586ceMark Shellenbaum		(void) printf("\t\t%s = ", attr.za_name);
4410a586ceMark Shellenbaum		if (attr.za_num_integers == 0) {
4420a586ceMark Shellenbaum			(void) printf("\n");
4430a586ceMark Shellenbaum			continue;
4440a586ceMark Shellenbaum		}
4450a586ceMark Shellenbaum		(void) printf(" %llx : [%d:%d:%d]\n",
4460a586ceMark Shellenbaum		    (u_longlong_t)attr.za_first_integer,
4470a586ceMark Shellenbaum		    (int)ATTR_LENGTH(attr.za_first_integer),
4480a586ceMark Shellenbaum		    (int)ATTR_BSWAP(attr.za_first_integer),
4490a586ceMark Shellenbaum		    (int)ATTR_NUM(attr.za_first_integer));
4500a586ceMark Shellenbaum	}
4510a586ceMark Shellenbaum	zap_cursor_fini(&zc);
4520a586ceMark Shellenbaum}
4530a586ceMark Shellenbaum
4540a586ceMark Shellenbaum/*ARGSUSED*/
4550a586ceMark Shellenbaumstatic void
4560a586ceMark Shellenbaumdump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size)
4570a586ceMark Shellenbaum{
4580a586ceMark Shellenbaum	zap_cursor_t zc;
4590a586ceMark Shellenbaum	zap_attribute_t attr;
4600a586ceMark Shellenbaum	uint16_t *layout_attrs;
4610a586ceMark Shellenbaum	int i;
4620a586ceMark Shellenbaum
4630a586ceMark Shellenbaum	dump_zap_stats(os, object);
4640a586ceMark Shellenbaum	(void) printf("\n");
4650a586ceMark Shellenbaum
4660a586ceMark Shellenbaum	for (zap_cursor_init(&zc, os, object);
4670a586ceMark Shellenbaum	    zap_cursor_retrieve(&zc, &attr) == 0;
4680a586ceMark Shellenbaum	    zap_cursor_advance(&zc)) {
4690a586ceMark Shellenbaum		(void) printf("\t\t%s = [", attr.za_name);
4700a586ceMark Shellenbaum		if (attr.za_num_integers == 0) {
4710a586ceMark Shellenbaum			(void) printf("\n");
4720a586ceMark Shellenbaum			continue;
4730a586ceMark Shellenbaum		}
4740a586ceMark Shellenbaum
4750a586ceMark Shellenbaum		VERIFY(attr.za_integer_length == 2);
4760a586ceMark Shellenbaum		layout_attrs = umem_zalloc(attr.za_num_integers *
4770a586ceMark Shellenbaum		    attr.za_integer_length, UMEM_NOFAIL);
4780a586ceMark Shellenbaum
4790a586ceMark Shellenbaum		VERIFY(zap_lookup(os, object, attr.za_name,
4800a586ceMark Shellenbaum		    attr.za_integer_length,
4810a586ceMark Shellenbaum		    attr.za_num_integers, layout_attrs) == 0);
4820a586ceMark Shellenbaum
4830a586ceMark Shellenbaum		for (i = 0; i != attr.za_num_integers; i++)
4840a586ceMark Shellenbaum			(void) printf(" %d ", (int)layout_attrs[i]);
4850a586ceMark Shellenbaum		(void) printf("]\n");
4860a586ceMark Shellenbaum		umem_free(layout_attrs,
4870a586ceMark Shellenbaum		    attr.za_num_integers * attr.za_integer_length);
4880a586ceMark Shellenbaum	}
4890a586ceMark Shellenbaum	zap_cursor_fini(&zc);
4900a586ceMark Shellenbaum}
4910a586ceMark Shellenbaum
4920a586ceMark Shellenbaum/*ARGSUSED*/
4930a586ceMark Shellenbaumstatic void
494e743726ahrensdump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
496e743726ahrens	zap_cursor_t zc;
497e743726ahrens	zap_attribute_t attr;
498e743726ahrens	const char *typenames[] = {
499e743726ahrens		/* 0 */ "not specified",
500e743726ahrens		/* 1 */ "FIFO",
501e743726ahrens		/* 2 */ "Character Device",
502e743726ahrens		/* 3 */ "3 (invalid)",
503e743726ahrens		/* 4 */ "Directory",
504e743726ahrens		/* 5 */ "5 (invalid)",
505e743726ahrens		/* 6 */ "Block Device",
506e743726ahrens		/* 7 */ "7 (invalid)",
507e743726ahrens		/* 8 */ "Regular File",
508e743726ahrens		/* 9 */ "9 (invalid)",
509e743726ahrens		/* 10 */ "Symbolic Link",
510e743726ahrens		/* 11 */ "11 (invalid)",
511e743726ahrens		/* 12 */ "Socket",
512e743726ahrens		/* 13 */ "Door",
513e743726ahrens		/* 14 */ "Event Port",
514e743726ahrens		/* 15 */ "15 (invalid)",
515e743726ahrens	};
517e743726ahrens	dump_zap_stats(os, object);
518e743726ahrens	(void) printf("\n");
520e743726ahrens	for (zap_cursor_init(&zc, os, object);
521e743726ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
522e743726ahrens	    zap_cursor_advance(&zc)) {
523e743726ahrens		(void) printf("\t\t%s = %lld (type: %s)\n",
524e743726ahrens		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
525e743726ahrens		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
526e743726ahrens	}
527e743726ahrens	zap_cursor_fini(&zc);
5300713e23George Wilsonint
5310713e23George Wilsonget_dtl_refcount(vdev_t *vd)
5320713e23George Wilson{
5330713e23George Wilson	int refcount = 0;
5340713e23George Wilson
5350713e23George Wilson	if (vd->vdev_ops->vdev_op_leaf) {
5360713e23George Wilson		space_map_t *sm = vd->vdev_dtl_sm;
5370713e23George Wilson
5380713e23George Wilson		if (sm != NULL &&
5390713e23George Wilson		    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
5400713e23George Wilson			return (1);
5410713e23George Wilson		return (0);
5420713e23George Wilson	}
5430713e23George Wilson
5440713e23George Wilson	for (int c = 0; c < vd->vdev_children; c++)
5450713e23George Wilson		refcount += get_dtl_refcount(vd->vdev_child[c]);
5460713e23George Wilson	return (refcount);
5470713e23George Wilson}
5480713e23George Wilson
5490713e23George Wilsonint
5500713e23George Wilsonget_metaslab_refcount(vdev_t *vd)
5510713e23George Wilson{
5520713e23George Wilson	int refcount = 0;
5530713e23George Wilson
5542e4c998George Wilson	if (vd->vdev_top == vd && !vd->vdev_removing) {
5550713e23George Wilson		for (int m = 0; m < vd->vdev_ms_count; m++) {
5560713e23George Wilson			space_map_t *sm = vd->vdev_ms[m]->ms_sm;
5570713e23George Wilson
5580713e23George Wilson			if (sm != NULL &&
5590713e23George Wilson			    sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
5600713e23George Wilson				refcount++;
5610713e23George Wilson		}
5620713e23George Wilson	}
5630713e23George Wilson	for (int c = 0; c < vd->vdev_children; c++)
5640713e23George Wilson		refcount += get_metaslab_refcount(vd->vdev_child[c]);
5650713e23George Wilson
5660713e23George Wilson	return (refcount);
5670713e23George Wilson}
5680713e23George Wilson
5690713e23George Wilsonstatic int
5700713e23George Wilsonverify_spacemap_refcounts(spa_t *spa)
5710713e23George Wilson{
5722acef22Matthew Ahrens	uint64_t expected_refcount = 0;
5732acef22Matthew Ahrens	uint64_t actual_refcount;
5740713e23George Wilson
5752acef22Matthew Ahrens	(void) feature_get_refcount(spa,
5762acef22Matthew Ahrens	    &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
5772acef22Matthew Ahrens	    &expected_refcount);
5780713e23George Wilson	actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
5790713e23George Wilson	actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
5800713e23George Wilson
5810713e23George Wilson	if (expected_refcount != actual_refcount) {
5822acef22Matthew Ahrens		(void) printf("space map refcount mismatch: expected %lld != "
5832acef22Matthew Ahrens		    "actual %lld\n",
5842acef22Matthew Ahrens		    (longlong_t)expected_refcount,
5852acef22Matthew Ahrens		    (longlong_t)actual_refcount);
5860713e23George Wilson		return (2);
5870713e23George Wilson	}
5880713e23George Wilson	return (0);
5890713e23George Wilson}
5900713e23George Wilson
591fa9e406ahrensstatic void
5920713e23George Wilsondump_spacemap(objset_t *os, space_map_t *sm)
594fa9e406ahrens	uint64_t alloc, offset, entry;
5958053a26ck	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
5968053a26ck			    "INVALID", "INVALID", "INVALID", "INVALID" };
5980713e23George Wilson	if (sm == NULL)
599fa9e406ahrens		return;
601fa9e406ahrens	/*
602fa9e406ahrens	 * Print out the freelist entries in both encoded and decoded form.
603fa9e406ahrens	 */
604fa9e406ahrens	alloc = 0;
6050713e23George Wilson	for (offset = 0; offset < space_map_length(sm);
6060713e23George Wilson	    offset += sizeof (entry)) {
6070713e23George Wilson		uint8_t mapshift = sm->sm_shift;
6080713e23George Wilson
6090713e23George Wilson		VERIFY0(dmu_read(os, space_map_object(sm), offset,
6107bfdf01Neil Perrin		    sizeof (entry), &entry, DMU_READ_PREFETCH));
611fa9e406ahrens		if (SM_DEBUG_DECODE(entry)) {
6120713e23George Wilson
61387219dbVictor Latushkin			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
614fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
615fa9e406ahrens			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
6165ad8204nd			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
6175ad8204nd			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
618fa9e406ahrens		} else {
61987219dbVictor Latushkin			(void) printf("\t    [%6llu]    %c  range:"
62087219dbVictor Latushkin			    " %010llx-%010llx  size: %06llx\n",
621fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
622fa9e406ahrens			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
6235ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
6240713e23George Wilson			    mapshift) + sm->sm_start),
6255ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
6260713e23George Wilson			    mapshift) + sm->sm_start +
6270713e23George Wilson			    (SM_RUN_DECODE(entry) << mapshift)),
6285ad8204nd			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
629fa9e406ahrens			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
630fa9e406ahrens				alloc += SM_RUN_DECODE(entry) << mapshift;
631fa9e406ahrens			else
632fa9e406ahrens				alloc -= SM_RUN_DECODE(entry) << mapshift;
633fa9e406ahrens		}
634fa9e406ahrens	}
6350713e23George Wilson	if (alloc != space_map_allocated(sm)) {
636fa9e406ahrens		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
637fa9e406ahrens		    "with space map summary (%llu)\n",
6380713e23George Wilson		    (u_longlong_t)space_map_allocated(sm), (u_longlong_t)alloc);
639fa9e406ahrens	}
642fa9e406ahrensstatic void
643d6e555bGeorge Wilsondump_metaslab_stats(metaslab_t *msp)
644d6e555bGeorge Wilson{
6453f9d6adLin Ling	char maxbuf[32];
6460713e23George Wilson	range_tree_t *rt = msp->ms_tree;
6470713e23George Wilson	avl_tree_t *t = &msp->ms_size_tree;
6480713e23George Wilson	int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
649d6e555bGeorge Wilson
6500713e23George Wilson	zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
651d6e555bGeorge Wilson
65287219dbVictor Latushkin	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
653d6e555bGeorge Wilson	    "segments", avl_numnodes(t), "maxsize", maxbuf,
654d6e555bGeorge Wilson	    "freepct", free_pct);
6550713e23George Wilson	(void) printf("\tIn-memory histogram:\n");
6560713e23George Wilson	dump_histogram(rt->rt_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
657d6e555bGeorge Wilson}
658d6e555bGeorge Wilson
659d6e555bGeorge Wilsonstatic void
660fa9e406ahrensdump_metaslab(metaslab_t *msp)
662fa9e406ahrens	vdev_t *vd = msp->ms_group->mg_vd;
663fa9e406ahrens	spa_t *spa = vd->vdev_spa;
6640713e23George Wilson	space_map_t *sm = msp->ms_sm;
6653f9d6adLin Ling	char freebuf[32];
6670713e23George Wilson	zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
669fa9e406ahrens	(void) printf(
67087219dbVictor Latushkin	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
6710713e23George Wilson	    (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
6720713e23George Wilson	    (u_longlong_t)space_map_object(sm), freebuf);
6740713e23George Wilson	if (dump_opt['m'] > 2 && !dump_opt['L']) {
675d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
6760713e23George Wilson		metaslab_load_wait(msp);
6770713e23George Wilson		if (!msp->ms_loaded) {
6780713e23George Wilson			VERIFY0(metaslab_load(msp));
6790713e23George Wilson			range_tree_stat_verify(msp->ms_tree);
6800713e23George Wilson		}
681bc3975bVictor Latushkin		dump_metaslab_stats(msp);
6820713e23George Wilson		metaslab_unload(msp);
683d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
684d6e555bGeorge Wilson	}
685d6e555bGeorge Wilson
6860713e23George Wilson	if (dump_opt['m'] > 1 && sm != NULL &&
6872acef22Matthew Ahrens	    spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
6880713e23George Wilson		/*
6890713e23George Wilson		 * The space map histogram represents free space in chunks
6900713e23George Wilson		 * of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
6910713e23George Wilson		 */
6922e4c998George Wilson		(void) printf("\tOn-disk histogram:\t\tfragmentation %llu\n",
6932e4c998George Wilson		    (u_longlong_t)msp->ms_fragmentation);
6940713e23George Wilson		dump_histogram(sm->sm_phys->smp_histogram,
6952e4c998George Wilson		    SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
6960713e23George Wilson	}
6970713e23George Wilson
6980713e23George Wilson	if (dump_opt['d'] > 5 || dump_opt['m'] > 3) {
6990713e23George Wilson		ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
700d6e555bGeorge Wilson
701d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
7020713e23George Wilson		dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
703d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
704d6e555bGeorge Wilson	}
70587219dbVictor Latushkin}
70787219dbVictor Latushkinstatic void
70887219dbVictor Latushkinprint_vdev_metaslab_header(vdev_t *vd)
70987219dbVictor Latushkin{
71087219dbVictor Latushkin	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
71187219dbVictor Latushkin	    (u_longlong_t)vd->vdev_id,
71287219dbVictor Latushkin	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
71387219dbVictor Latushkin	    "offset", "spacemap", "free");
71487219dbVictor Latushkin	(void) printf("\t%15s   %19s   %15s   %10s\n",
71587219dbVictor Latushkin	    "---------------", "-------------------",
71687219dbVictor Latushkin	    "---------------", "-------------");
719fa9e406ahrensstatic void
7202e4c998George Wilsondump_metaslab_groups(spa_t *spa)
7212e4c998George Wilson{
7222e4c998George Wilson	vdev_t *rvd = spa->spa_root_vdev;
7232e4c998George Wilson	metaslab_class_t *mc = spa_normal_class(spa);
7242e4c998George Wilson	uint64_t fragmentation;
7252e4c998George Wilson
7262e4c998George Wilson	metaslab_class_histogram_verify(mc);
7272e4c998George Wilson
7282e4c998George Wilson	for (int c = 0; c < rvd->vdev_children; c++) {
7292e4c998George Wilson		vdev_t *tvd = rvd->vdev_child[c];
7302e4c998George Wilson		metaslab_group_t *mg = tvd->vdev_mg;
7312e4c998George Wilson
7322e4c998George Wilson		if (mg->mg_class != mc)
7332e4c998George Wilson			continue;
7342e4c998George Wilson
7352e4c998George Wilson		metaslab_group_histogram_verify(mg);
7362e4c998George Wilson		mg->mg_fragmentation = metaslab_group_fragmentation(mg);
7372e4c998George Wilson
7382e4c998George Wilson		(void) printf("\tvdev %10llu\t\tmetaslabs%5llu\t\t"
7392e4c998George Wilson		    "fragmentation",
7402e4c998George Wilson		    (u_longlong_t)tvd->vdev_id,
7412e4c998George Wilson		    (u_longlong_t)tvd->vdev_ms_count);
7422e4c998George Wilson		if (mg->mg_fragmentation == ZFS_FRAG_INVALID) {
7432e4c998George Wilson			(void) printf("%3s\n", "-");
7442e4c998George Wilson		} else {
7452e4c998George Wilson			(void) printf("%3llu%%\n",
7462e4c998George Wilson			    (u_longlong_t)mg->mg_fragmentation);
7472e4c998George Wilson		}
7482e4c998George Wilson		dump_histogram(mg->mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
7492e4c998George Wilson	}
7502e4c998George Wilson
7512e4c998George Wilson	(void) printf("\tpool %s\tfragmentation", spa_name(spa));
7522e4c998George Wilson	fragmentation = metaslab_class_fragmentation(mc);
7532e4c998George Wilson	if (fragmentation == ZFS_FRAG_INVALID)
7542e4c998George Wilson		(void) printf("\t%3s\n", "-");
7552e4c998George Wilson	else
7562e4c998George Wilson		(void) printf("\t%3llu%%\n", (u_longlong_t)fragmentation);
7572e4c998George Wilson	dump_histogram(mc->mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
7582e4c998George Wilson}
7592e4c998George Wilson
7602e4c998George Wilsonstatic void
761fa9e406ahrensdump_metaslabs(spa_t *spa)
76387219dbVictor Latushkin	vdev_t *vd, *rvd = spa->spa_root_vdev;
76487219dbVictor Latushkin	uint64_t m, c = 0, children = rvd->vdev_children;
766fa9e406ahrens	(void) printf("\nMetaslabs:\n");
76887219dbVictor Latushkin	if (!dump_opt['d'] && zopt_objects > 0) {
76987219dbVictor Latushkin		c = zopt_object[0];
77087219dbVictor Latushkin
77187219dbVictor Latushkin		if (c >= children)
77287219dbVictor Latushkin			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
77487219dbVictor Latushkin		if (zopt_objects > 1) {
77587219dbVictor Latushkin			vd = rvd->vdev_child[c];
77687219dbVictor Latushkin			print_vdev_metaslab_header(vd);
77787219dbVictor Latushkin
77887219dbVictor Latushkin			for (m = 1; m < zopt_objects; m++) {
77987219dbVictor Latushkin				if (zopt_object[m] < vd->vdev_ms_count)
78087219dbVictor Latushkin					dump_metaslab(
78187219dbVictor Latushkin					    vd->vdev_ms[zopt_object[m]]);
78287219dbVictor Latushkin				else
78387219dbVictor Latushkin					(void) fprintf(stderr, "bad metaslab "
78487219dbVictor Latushkin					    "number %llu\n",
78587219dbVictor Latushkin					    (u_longlong_t)zopt_object[m]);
78687219dbVictor Latushkin			}
78787219dbVictor Latushkin			(void) printf("\n");
78887219dbVictor Latushkin			return;
78987219dbVictor Latushkin		}
79087219dbVictor Latushkin		children = c + 1;
79187219dbVictor Latushkin	}
79287219dbVictor Latushkin	for (; c < children; c++) {
79387219dbVictor Latushkin		vd = rvd->vdev_child[c];
79487219dbVictor Latushkin		print_vdev_metaslab_header(vd);
796fa9e406ahrens		for (m = 0; m < vd->vdev_ms_count; m++)
797fa9e406ahrens			dump_metaslab(vd->vdev_ms[m]);
798fa9e406ahrens		(void) printf("\n");
799fa9e406ahrens	}
802fa9e406ahrensstatic void
803b24ab67Jeff Bonwickdump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
804b24ab67Jeff Bonwick{
805b24ab67Jeff Bonwick	const ddt_phys_t *ddp = dde->dde_phys;
806b24ab67Jeff Bonwick	const ddt_key_t *ddk = &dde->dde_key;
807b24ab67Jeff Bonwick	char *types[4] = { "ditto", "single", "double", "triple" };
808b24ab67Jeff Bonwick	char blkbuf[BP_SPRINTF_LEN];
809b24ab67Jeff Bonwick	blkptr_t blk;
810b24ab67Jeff Bonwick
811b24ab67Jeff Bonwick	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
812b24ab67Jeff Bonwick		if (ddp->ddp_phys_birth == 0)
813b24ab67Jeff Bonwick			continue;
814bbfd46cJeff Bonwick		ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
81543466aaMax Grossman		snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk);
816b24ab67Jeff Bonwick		(void) printf("index %llx refcnt %llu %s %s\n",
817b24ab67Jeff Bonwick		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
818b24ab67Jeff Bonwick		    types[p], blkbuf);
819b24ab67Jeff Bonwick	}
820b24ab67Jeff Bonwick}
821b24ab67Jeff Bonwick
822b24ab67Jeff Bonwickstatic void
823b24ab67Jeff Bonwickdump_dedup_ratio(const ddt_stat_t *dds)
824b24ab67Jeff Bonwick{
825b24ab67Jeff Bonwick	double rL, rP, rD, D, dedup, compress, copies;
826b24ab67Jeff Bonwick
827b24ab67Jeff Bonwick	if (dds->dds_blocks == 0)
828b24ab67Jeff Bonwick		return;
829b24ab67Jeff Bonwick
830b24ab67Jeff Bonwick	rL = (double)dds->dds_ref_lsize;
831b24ab67Jeff Bonwick	rP = (double)dds->dds_ref_psize;
832b24ab67Jeff Bonwick	rD = (double)dds->dds_ref_dsize;
833b24ab67Jeff Bonwick	D = (double)dds->dds_dsize;
834b24ab67Jeff Bonwick
835b24ab67Jeff Bonwick	dedup = rD / D;
836b24ab67Jeff Bonwick	compress = rL / rP;
837b24ab67Jeff Bonwick	copies = rD / rP;
838b24ab67Jeff Bonwick
839b24ab67Jeff Bonwick	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
840b24ab67Jeff Bonwick	    "dedup * compress / copies = %.2f\n\n",
841b24ab67Jeff Bonwick	    dedup, compress, copies, dedup * compress / copies);
842b24ab67Jeff Bonwick}
843b24ab67Jeff Bonwick
844b24ab67Jeff Bonwickstatic void
845b24ab67Jeff Bonwickdump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
846b24ab67Jeff Bonwick{
847b24ab67Jeff Bonwick	char name[DDT_NAMELEN];
848b24ab67Jeff Bonwick	ddt_entry_t dde;
849b24ab67Jeff Bonwick	uint64_t walk = 0;
850b24ab67Jeff Bonwick	dmu_object_info_t doi;
851b24ab67Jeff Bonwick	uint64_t count, dspace, mspace;
852b24ab67Jeff Bonwick	int error;
853b24ab67Jeff Bonwick
854b24ab67Jeff Bonwick	error = ddt_object_info(ddt, type, class, &doi);
855b24ab67Jeff Bonwick
856b24ab67Jeff Bonwick	if (error == ENOENT)
857b24ab67Jeff Bonwick		return;
858b24ab67Jeff Bonwick	ASSERT(error == 0);
859b24ab67Jeff Bonwick
8607448a07George Wilson	if ((count = ddt_object_count(ddt, type, class)) == 0)
8617448a07George Wilson		return;
8627448a07George Wilson
863b24ab67Jeff Bonwick	dspace = doi.doi_physical_blocks_512 << 9;
864b24ab67Jeff Bonwick	mspace = doi.doi_fill_count * doi.doi_data_block_size;
865b24ab67Jeff Bonwick
866b24ab67Jeff Bonwick	ddt_object_name(ddt, type, class, name);
867b24ab67Jeff Bonwick
868b24ab67Jeff Bonwick	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
869b24ab67Jeff Bonwick	    name,
870b24ab67Jeff Bonwick	    (u_longlong_t)count,
871b24ab67Jeff Bonwick	    (u_longlong_t)(dspace / count),
872b24ab67Jeff Bonwick	    (u_longlong_t)(mspace / count));
873b24ab67Jeff Bonwick
874b24ab67Jeff Bonwick	if (dump_opt['D'] < 3)
875b24ab67Jeff Bonwick		return;
876b24ab67Jeff Bonwick
8779eb19f4George Wilson	zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]);
878b24ab67Jeff Bonwick
879b24ab67Jeff Bonwick	if (dump_opt['D'] < 4)
880b24ab67Jeff Bonwick		return;
881b24ab67Jeff Bonwick
882b24ab67Jeff Bonwick	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
883b24ab67Jeff Bonwick		return;
884b24ab67Jeff Bonwick
885b24ab67Jeff Bonwick	(void) printf("%s contents:\n\n", name);
886b24ab67Jeff Bonwick
887bbfd46cJeff Bonwick	while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0)
888b24ab67Jeff Bonwick		dump_dde(ddt, &dde, walk);
889b24ab67Jeff Bonwick
890b24ab67Jeff Bonwick	ASSERT(error == ENOENT);
891b24ab67Jeff Bonwick
892b24ab67Jeff Bonwick	(void) printf("\n");
893b24ab67Jeff Bonwick}
894b24ab67Jeff Bonwick
895b24ab67Jeff Bonwickstatic void
896b24ab67Jeff Bonwickdump_all_ddts(spa_t *spa)
897b24ab67Jeff Bonwick{
898b24ab67Jeff Bonwick	ddt_histogram_t ddh_total = { 0 };
899b24ab67Jeff Bonwick	ddt_stat_t dds_total = { 0 };
900b24ab67Jeff Bonwick
901b24ab67Jeff Bonwick	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
902b24ab67Jeff Bonwick		ddt_t *ddt = spa->spa_ddt[c];
903b24ab67Jeff Bonwick		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
904b24ab67Jeff Bonwick			for (enum ddt_class class = 0; class < DDT_CLASSES;
905b24ab67Jeff Bonwick			    class++) {
906b24ab67Jeff Bonwick				dump_ddt(ddt, type, class);
907b24ab67Jeff Bonwick			}
908b24ab67Jeff Bonwick		}
909b24ab67Jeff Bonwick	}
910b24ab67Jeff Bonwick
9119eb19f4George Wilson	ddt_get_dedup_stats(spa, &dds_total);
912b24ab67Jeff Bonwick