zdb.c revision 490d05b9daa0e60fbb3aac647c556408e88228bd
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.
24490d05bMatthew Ahrens * Copyright (c) 2013 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
78feef89cVictor Latushkinextern int zfs_recover;
79feef89cVictor Latushkin#else
80feef89cVictor Latushkinint zfs_recover;
81feef89cVictor Latushkin#endif
82feef89cVictor Latushkin
83fa9e406ahrensconst char cmdname[] = "zdb";
84fa9e406ahrensuint8_t dump_opt[256];
86fa9e406ahrenstypedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
88fa9e406ahrensextern void dump_intent_log(zilog_t *);
89fa9e406ahrensuint64_t *zopt_object = NULL;
90fa9e406ahrensint zopt_objects = 0;
91de6628fcklibzfs_handle_t *g_zfs;
9231d7e8fGeorge Wilsonuint64_t max_inflight = 200;
95fa9e406ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
96fa9e406ahrens * debugging facilities.
97fa9e406ahrens */
98fa9e406ahrensconst char *
101fa9e406ahrens	return ("default,verbose"); /* $UMEM_DEBUG setting */
104fa9e406ahrensconst char *
107fa9e406ahrens	return ("fail,contents"); /* $UMEM_LOGGING setting */
110fa9e406ahrensstatic void
113fa9e406ahrens	(void) fprintf(stderr,
11490e894eRichard Lowe	    "Usage: %s [-CumdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
11531d7e8fGeorge Wilson	    "[-U config] [-M inflight I/Os] poolname [object...]\n"
11631d7e8fGeorge Wilson	    "       %s [-divPA] [-e -p path...] [-U config] dataset "
11731d7e8fGeorge Wilson	    "[object...]\n"
11831d7e8fGeorge Wilson	    "       %s -m [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
11990e894eRichard Lowe	    "poolname [vdev [metaslab...]]\n"
12090e894eRichard Lowe	    "       %s -R [-A] [-e [-p path...]] poolname "
12190e894eRichard Lowe	    "vdev:offset:size[:flags]\n"
12231d7e8fGeorge Wilson	    "       %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
12390e894eRichard Lowe	    "       %s -l [-uA] device\n"
12490e894eRichard Lowe	    "       %s -C [-A] [-U config]\n\n",
125bbfd46cJeff Bonwick	    cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
1263ad6c7fVictor Latushkin
1273ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Dataset name must include at least one "
1283ad6c7fVictor Latushkin	    "separator character '/' or '@'\n");
1293ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If dataset name is specified, only that "
1303ad6c7fVictor Latushkin	    "dataset is dumped\n");
1313ad6c7fVictor Latushkin	(void) fprintf(stderr, "    If object numbers are specified, only "
1323ad6c7fVictor Latushkin	    "those objects are dumped\n\n");
1333ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Options to control amount of output:\n");
1343ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -u uberblock\n");
1353ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -d dataset(s)\n");
1363ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -i intent logs\n");
13707428bdVictor Latushkin	(void) fprintf(stderr, "        -C config (or cachefile if alone)\n");
1388f18d1fGeorge Wilson	(void) fprintf(stderr, "        -h pool history\n");
1393ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -b block statistics\n");
1403ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -m metaslabs\n");
1413ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -c checksum all metadata (twice for "
1426365109Victor Latushkin	    "all data) blocks\n");
1433ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
144f0ba89bJeff Bonwick	(void) fprintf(stderr, "        -D dedup statistics\n");
145b24ab67Jeff Bonwick	(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
1463ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -v verbose (applies to all others)\n");
147fa9e406ahrens	(void) fprintf(stderr, "        -l dump label contents\n");
14882a0a98Victor Latushkin	(void) fprintf(stderr, "        -L disable leak tracking (do not "
14982a0a98Victor Latushkin	    "load spacemaps)\n");
150d41e764ek	(void) fprintf(stderr, "        -R read and display block from a "
1513ad6c7fVictor Latushkin	    "device\n\n");
1523ad6c7fVictor Latushkin	(void) fprintf(stderr, "    Below options are intended for use "
1533ad6c7fVictor Latushkin	    "with other options (except -l):\n");
154feef89cVictor Latushkin	(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
155feef89cVictor Latushkin	    "panic recovery (-AA) or both (-AAA)\n");
156c8ee184Victor Latushkin	(void) fprintf(stderr, "        -F attempt automatic rewind within "
157c8ee184Victor Latushkin	    "safe range of transaction groups\n");
1583ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -U <cachefile_path> -- use alternate "
1593ad6c7fVictor Latushkin	    "cachefile\n");
160c8ee184Victor Latushkin	(void) fprintf(stderr, "        -X attempt extreme rewind (does not "
161c8ee184Victor Latushkin	    "work with dataset)\n");
1623ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -e pool is exported/destroyed/"
1633ad6c7fVictor Latushkin	    "has altroot/not in a cachefile\n");
1643ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -p <path> -- use one or more with "
1653ad6c7fVictor Latushkin	    "-e to specify path to vdev dir\n");
16690e894eRichard Lowe	(void) fprintf(stderr, "        -P print numbers in parseable form\n");
1673ad6c7fVictor Latushkin	(void) fprintf(stderr, "        -t <txg> -- highest txg to use when "
1682e55192Victor Latushkin	    "searching for uberblocks\n");
16931d7e8fGeorge Wilson	(void) fprintf(stderr, "        -M <number of inflight I/Os> -- "
17031d7e8fGeorge Wilson	    "specify the maximum number of checksumming I/Os [default is 200]");
171fa9e406ahrens	(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
172fa9e406ahrens	    "to make only that option verbose\n");
173fa9e406ahrens	(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
174fa9e406ahrens	exit(1);
177ccba080Rich Morris/*
178ccba080Rich Morris * Called for usage errors that are discovered after a call to spa_open(),
179ccba080Rich Morris * dmu_bonus_hold(), or pool_match().  abort() is called for other errors.
180ccba080Rich Morris */
181ccba080Rich Morris
182fa9e406ahrensstatic void
183fa9e406ahrensfatal(const char *fmt, ...)
185fa9e406ahrens	va_list ap;
187fa9e406ahrens	va_start(ap, fmt);
188fa9e406ahrens	(void) fprintf(stderr, "%s: ", cmdname);
189fa9e406ahrens	(void) vfprintf(stderr, fmt, ap);
190fa9e406ahrens	va_end(ap);
191fa9e406ahrens	(void) fprintf(stderr, "\n");
193ccba080Rich Morris	exit(1);
196fa9e406ahrens/* ARGSUSED */
197fa9e406ahrensstatic void
198fa9e406ahrensdump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
200fa9e406ahrens	nvlist_t *nv;
201fa9e406ahrens	size_t nvsize = *(uint64_t *)data;
202fa9e406ahrens	char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
2047bfdf01Neil Perrin	VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
206fa9e406ahrens	VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
208fa9e406ahrens	umem_free(packed, nvsize);
210fa9e406ahrens	dump_nvlist(nv, 8);
212fa9e406ahrens	nvlist_free(nv);
2154445fffMatthew Ahrens/* ARGSUSED */
2164445fffMatthew Ahrensstatic void
2174445fffMatthew Ahrensdump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
2184445fffMatthew Ahrens{
2194445fffMatthew Ahrens	spa_history_phys_t *shp = data;
2204445fffMatthew Ahrens
2214445fffMatthew Ahrens	if (shp == NULL)
2224445fffMatthew Ahrens		return;
2234445fffMatthew Ahrens
2244445fffMatthew Ahrens	(void) printf("\t\tpool_create_len = %llu\n",
2254445fffMatthew Ahrens	    (u_longlong_t)shp->sh_pool_create_len);
2264445fffMatthew Ahrens	(void) printf("\t\tphys_max_off = %llu\n",
2274445fffMatthew Ahrens	    (u_longlong_t)shp->sh_phys_max_off);
2284445fffMatthew Ahrens	(void) printf("\t\tbof = %llu\n",
2294445fffMatthew Ahrens	    (u_longlong_t)shp->sh_bof);
2304445fffMatthew Ahrens	(void) printf("\t\teof = %llu\n",
2314445fffMatthew Ahrens	    (u_longlong_t)shp->sh_eof);
2324445fffMatthew Ahrens	(void) printf("\t\trecords_lost = %llu\n",
2334445fffMatthew Ahrens	    (u_longlong_t)shp->sh_records_lost);
2344445fffMatthew Ahrens}
2354445fffMatthew Ahrens
2363f9d6adLin Lingstatic void
2373f9d6adLin Lingzdb_nicenum(uint64_t num, char *buf)
2383f9d6adLin Ling{
2393f9d6adLin Ling	if (dump_opt['P'])
2403f9d6adLin Ling		(void) sprintf(buf, "%llu", (longlong_t)num);
2413f9d6adLin Ling	else
2423f9d6adLin Ling		nicenum(num, buf);
2433f9d6adLin Ling}
2443f9d6adLin Ling
245490d05bMatthew Ahrensconst char histo_stars[] = "****************************************";
246490d05bMatthew Ahrensconst int histo_width = sizeof (histo_stars) - 1;
248fa9e406ahrensstatic void
249490d05bMatthew Ahrensdump_histogram(const uint64_t *histo, int size)
251fa9e406ahrens	int i;
252490d05bMatthew Ahrens	int minidx = size - 1;
253fa9e406ahrens	int maxidx = 0;
254fa9e406ahrens	uint64_t max = 0;
256490d05bMatthew Ahrens	for (i = 0; i < size; i++) {
257fa9e406ahrens		if (histo[i] > max)
258fa9e406ahrens			max = histo[i];
259fa9e406ahrens		if (histo[i] > 0 && i > maxidx)
260fa9e406ahrens			maxidx = i;
261fa9e406ahrens		if (histo[i] > 0 && i < minidx)
262fa9e406ahrens			minidx = i;
263fa9e406ahrens	}
265490d05bMatthew Ahrens	if (max < histo_width)
266490d05bMatthew Ahrens		max = histo_width;
268490d05bMatthew Ahrens	for (i = minidx; i <= maxidx; i++) {
269490d05bMatthew Ahrens		(void) printf("\t\t\t%3u: %6llu %s\n",
270490d05bMatthew Ahrens		    i, (u_longlong_t)histo[i],
271490d05bMatthew Ahrens		    &histo_stars[(max - histo[i]) * histo_width / max]);
272490d05bMatthew Ahrens	}
275fa9e406ahrensstatic void
276fa9e406ahrensdump_zap_stats(objset_t *os, uint64_t object)
278fa9e406ahrens	int error;
279fa9e406ahrens	zap_stats_t zs;
281fa9e406ahrens	error = zap_get_stats(os, object, &zs);
282fa9e406ahrens	if (error)
283fa9e406ahrens		return;
285fa9e406ahrens	if (zs.zs_ptrtbl_len == 0) {
286fa9e406ahrens		ASSERT(zs.zs_num_blocks == 1);
287fa9e406ahrens		(void) printf("\tmicrozap: %llu bytes, %llu entries\n",
288fa9e406ahrens		    (u_longlong_t)zs.zs_blocksize,
289fa9e406ahrens		    (u_longlong_t)zs.zs_num_entries);
290fa9e406ahrens		return;
291fa9e406ahrens	}
293fa9e406ahrens	(void) printf("\tFat ZAP stats:\n");
2958248818nd	(void) printf("\t\tPointer table:\n");
2968248818nd	(void) printf("\t\t\t%llu elements\n",
297fa9e406ahrens	    (u_longlong_t)zs.zs_ptrtbl_len);
2988248818nd	(void) printf("\t\t\tzt_blk: %llu\n",
2998248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_blk);
3008248818nd	(void) printf("\t\t\tzt_numblks: %llu\n",
3018248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_numblks);
3028248818nd	(void) printf("\t\t\tzt_shift: %llu\n",
3038248818nd	    (u_longlong_t)zs.zs_ptrtbl_zt_shift);
3048248818nd	(void) printf("\t\t\tzt_blks_copied: %llu\n",
3058248818nd	    (u_longlong_t)zs.zs_ptrtbl_blks_copied);
3068248818nd	(void) printf("\t\t\tzt_nextblk: %llu\n",
3078248818nd	    (u_longlong_t)zs.zs_ptrtbl_nextblk);
309fa9e406ahrens	(void) printf("\t\tZAP entries: %llu\n",
310fa9e406ahrens	    (u_longlong_t)zs.zs_num_entries);
311fa9e406ahrens	(void) printf("\t\tLeaf blocks: %llu\n",
312fa9e406ahrens	    (u_longlong_t)zs.zs_num_leafs);
313fa9e406ahrens	(void) printf("\t\tTotal blocks: %llu\n",
314fa9e406ahrens	    (u_longlong_t)zs.zs_num_blocks);
3158248818nd	(void) printf("\t\tzap_block_type: 0x%llx\n",
3168248818nd	    (u_longlong_t)zs.zs_block_type);
3178248818nd	(void) printf("\t\tzap_magic: 0x%llx\n",
3188248818nd	    (u_longlong_t)zs.zs_magic);
3198248818nd	(void) printf("\t\tzap_salt: 0x%llx\n",
3208248818nd	    (u_longlong_t)zs.zs_salt);
322fa9e406ahrens	(void) printf("\t\tLeafs with 2^n pointers:\n");
323490d05bMatthew Ahrens	dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE);
325fa9e406ahrens	(void) printf("\t\tBlocks with n*5 entries:\n");
326490d05bMatthew Ahrens	dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE);
328fa9e406ahrens	(void) printf("\t\tBlocks n/10 full:\n");
329490d05bMatthew Ahrens	dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE);
331fa9e406ahrens	(void) printf("\t\tEntries with n chunks:\n");
332490d05bMatthew Ahrens	dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE);
334fa9e406ahrens	(void) printf("\t\tBuckets with n entries:\n");
335490d05bMatthew Ahrens	dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE);
339fa9e406ahrensstatic void
340fa9e406ahrensdump_none(objset_t *os, uint64_t object, void *data, size_t size)
3456de8f41Victor Latushkinstatic void
3466de8f41Victor Latushkindump_unknown(objset_t *os, uint64_t object, void *data, size_t size)
3476de8f41Victor Latushkin{
3486de8f41Victor Latushkin	(void) printf("\tUNKNOWN OBJECT TYPE\n");
3496de8f41Victor Latushkin}
3506de8f41Victor Latushkin
3516de8f41Victor Latushkin/*ARGSUSED*/
353fa9e406ahrensdump_uint8(objset_t *os, uint64_t object, void *data, size_t size)
358fa9e406ahrensstatic void
359fa9e406ahrensdump_uint64(objset_t *os, uint64_t object, void *data, size_t size)
364fa9e406ahrensstatic void
365fa9e406ahrensdump_zap(objset_t *os, uint64_t object, void *data, size_t size)
367fa9e406ahrens	zap_cursor_t zc;
368fa9e406ahrens	zap_attribute_t attr;
369fa9e406ahrens	void *prop;
370fa9e406ahrens	int i;
372fa9e406ahrens	dump_zap_stats(os, object);
373fa9e406ahrens	(void) printf("\n");
375fa9e406ahrens	for (zap_cursor_init(&zc, os, object);
376fa9e406ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
377fa9e406ahrens	    zap_cursor_advance(&zc)) {
378fa9e406ahrens		(void) printf("\t\t%s = ", attr.za_name);
379fa9e406ahrens		if (attr.za_num_integers == 0) {
380fa9e406ahrens			(void) printf("\n");
381fa9e406ahrens			continue;
382fa9e406ahrens		}
383fa9e406ahrens		prop = umem_zalloc(attr.za_num_integers *
384fa9e406ahrens		    attr.za_integer_length, UMEM_NOFAIL);
385fa9e406ahrens		(void) zap_lookup(os, object, attr.za_name,
386fa9e406ahrens		    attr.za_integer_length, attr.za_num_integers, prop);
387fa9e406ahrens		if (attr.za_integer_length == 1) {
388fa9e406ahrens			(void) printf("%s", (char *)prop);
389fa9e406ahrens		} else {
390fa9e406ahrens			for (i = 0; i < attr.za_num_integers; i++) {
391fa9e406ahrens				switch (attr.za_integer_length) {
392fa9e406ahrens				case 2:
393fa9e406ahrens					(void) printf("%u ",
394fa9e406ahrens					    ((uint16_t *)prop)[i]);
395fa9e406ahrens					break;
396fa9e406ahrens				case 4:
397fa9e406ahrens					(void) printf("%u ",
398fa9e406ahrens					    ((uint32_t *)prop)[i]);
399fa9e406ahrens					break;
400fa9e406ahrens				case 8:
401fa9e406ahrens					(void) printf("%lld ",
402fa9e406ahrens					    (u_longlong_t)((int64_t *)prop)[i]);
403fa9e406ahrens					break;
404fa9e406ahrens				}
405fa9e406ahrens			}
406fa9e406ahrens		}
407fa9e406ahrens		(void) printf("\n");
408fa9e406ahrens		umem_free(prop, attr.za_num_integers * attr.za_integer_length);
409fa9e406ahrens	}
41087e5029ahrens	zap_cursor_fini(&zc);
414e743726ahrensstatic void
415486ae71Matthew Ahrensdump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
416486ae71Matthew Ahrens{
417486ae71Matthew Ahrens	dump_zap_stats(os, object);
418486ae71Matthew Ahrens	/* contents are printed elsewhere, properly decoded */
419486ae71Matthew Ahrens}
420486ae71Matthew Ahrens
421486ae71Matthew Ahrens/*ARGSUSED*/
422486ae71Matthew Ahrensstatic void
4230a586ceMark Shellenbaumdump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size)
4240a586ceMark Shellenbaum{
4250a586ceMark Shellenbaum	zap_cursor_t zc;
4260a586ceMark Shellenbaum	zap_attribute_t attr;
4270a586ceMark Shellenbaum
4280a586ceMark Shellenbaum	dump_zap_stats(os, object);
4290a586ceMark Shellenbaum	(void) printf("\n");
4300a586ceMark Shellenbaum
4310a586ceMark Shellenbaum	for (zap_cursor_init(&zc, os, object);
4320a586ceMark Shellenbaum	    zap_cursor_retrieve(&zc, &attr) == 0;
4330a586ceMark Shellenbaum	    zap_cursor_advance(&zc)) {
4340a586ceMark Shellenbaum		(void) printf("\t\t%s = ", attr.za_name);
4350a586ceMark Shellenbaum		if (attr.za_num_integers == 0) {
4360a586ceMark Shellenbaum			(void) printf("\n");
4370a586ceMark Shellenbaum			continue;
4380a586ceMark Shellenbaum		}
4390a586ceMark Shellenbaum		(void) printf(" %llx : [%d:%d:%d]\n",
4400a586ceMark Shellenbaum		    (u_longlong_t)attr.za_first_integer,
4410a586ceMark Shellenbaum		    (int)ATTR_LENGTH(attr.za_first_integer),
4420a586ceMark Shellenbaum		    (int)ATTR_BSWAP(attr.za_first_integer),
4430a586ceMark Shellenbaum		    (int)ATTR_NUM(attr.za_first_integer));
4440a586ceMark Shellenbaum	}
4450a586ceMark Shellenbaum	zap_cursor_fini(&zc);
4460a586ceMark Shellenbaum}
4470a586ceMark Shellenbaum
4480a586ceMark Shellenbaum/*ARGSUSED*/
4490a586ceMark Shellenbaumstatic void
4500a586ceMark Shellenbaumdump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size)
4510a586ceMark Shellenbaum{
4520a586ceMark Shellenbaum	zap_cursor_t zc;
4530a586ceMark Shellenbaum	zap_attribute_t attr;
4540a586ceMark Shellenbaum	uint16_t *layout_attrs;
4550a586ceMark Shellenbaum	int i;
4560a586ceMark Shellenbaum
4570a586ceMark Shellenbaum	dump_zap_stats(os, object);
4580a586ceMark Shellenbaum	(void) printf("\n");
4590a586ceMark Shellenbaum
4600a586ceMark Shellenbaum	for (zap_cursor_init(&zc, os, object);
4610a586ceMark Shellenbaum	    zap_cursor_retrieve(&zc, &attr) == 0;
4620a586ceMark Shellenbaum	    zap_cursor_advance(&zc)) {
4630a586ceMark Shellenbaum		(void) printf("\t\t%s = [", attr.za_name);
4640a586ceMark Shellenbaum		if (attr.za_num_integers == 0) {
4650a586ceMark Shellenbaum			(void) printf("\n");
4660a586ceMark Shellenbaum			continue;
4670a586ceMark Shellenbaum		}
4680a586ceMark Shellenbaum
4690a586ceMark Shellenbaum		VERIFY(attr.za_integer_length == 2);
4700a586ceMark Shellenbaum		layout_attrs = umem_zalloc(attr.za_num_integers *
4710a586ceMark Shellenbaum		    attr.za_integer_length, UMEM_NOFAIL);
4720a586ceMark Shellenbaum
4730a586ceMark Shellenbaum		VERIFY(zap_lookup(os, object, attr.za_name,
4740a586ceMark Shellenbaum		    attr.za_integer_length,
4750a586ceMark Shellenbaum		    attr.za_num_integers, layout_attrs) == 0);
4760a586ceMark Shellenbaum
4770a586ceMark Shellenbaum		for (i = 0; i != attr.za_num_integers; i++)
4780a586ceMark Shellenbaum			(void) printf(" %d ", (int)layout_attrs[i]);
4790a586ceMark Shellenbaum		(void) printf("]\n");
4800a586ceMark Shellenbaum		umem_free(layout_attrs,
4810a586ceMark Shellenbaum		    attr.za_num_integers * attr.za_integer_length);
4820a586ceMark Shellenbaum	}
4830a586ceMark Shellenbaum	zap_cursor_fini(&zc);
4840a586ceMark Shellenbaum}
4850a586ceMark Shellenbaum
4860a586ceMark Shellenbaum/*ARGSUSED*/
4870a586ceMark Shellenbaumstatic void
488e743726ahrensdump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
490e743726ahrens	zap_cursor_t zc;
491e743726ahrens	zap_attribute_t attr;
492e743726ahrens	const char *typenames[] = {
493e743726ahrens		/* 0 */ "not specified",
494e743726ahrens		/* 1 */ "FIFO",
495e743726ahrens		/* 2 */ "Character Device",
496e743726ahrens		/* 3 */ "3 (invalid)",
497e743726ahrens		/* 4 */ "Directory",
498e743726ahrens		/* 5 */ "5 (invalid)",
499e743726ahrens		/* 6 */ "Block Device",
500e743726ahrens		/* 7 */ "7 (invalid)",
501e743726ahrens		/* 8 */ "Regular File",
502e743726ahrens		/* 9 */ "9 (invalid)",
503e743726ahrens		/* 10 */ "Symbolic Link",
504e743726ahrens		/* 11 */ "11 (invalid)",
505e743726ahrens		/* 12 */ "Socket",
506e743726ahrens		/* 13 */ "Door",
507e743726ahrens		/* 14 */ "Event Port",
508e743726ahrens		/* 15 */ "15 (invalid)",
509e743726ahrens	};
511e743726ahrens	dump_zap_stats(os, object);
512e743726ahrens	(void) printf("\n");
514e743726ahrens	for (zap_cursor_init(&zc, os, object);
515e743726ahrens	    zap_cursor_retrieve(&zc, &attr) == 0;
516e743726ahrens	    zap_cursor_advance(&zc)) {
517e743726ahrens		(void) printf("\t\t%s = %lld (type: %s)\n",
518e743726ahrens		    attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
519e743726ahrens		    typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
520e743726ahrens	}
521e743726ahrens	zap_cursor_fini(&zc);
524fa9e406ahrensstatic void
525fa9e406ahrensdump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
527fa9e406ahrens	uint64_t alloc, offset, entry;
528ecc2d60bonwick	uint8_t mapshift = sm->sm_shift;
529fa9e406ahrens	uint64_t mapstart = sm->sm_start;
5308053a26ck	char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
5318053a26ck			    "INVALID", "INVALID", "INVALID", "INVALID" };
533fa9e406ahrens	if (smo->smo_object == 0)
534fa9e406ahrens		return;
536fa9e406ahrens	/*
537fa9e406ahrens	 * Print out the freelist entries in both encoded and decoded form.
538fa9e406ahrens	 */
539fa9e406ahrens	alloc = 0;
540fa9e406ahrens	for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
541b420f3aRichard Lowe		VERIFY3U(0, ==, dmu_read(os, smo->smo_object, offset,
5427bfdf01Neil Perrin		    sizeof (entry), &entry, DMU_READ_PREFETCH));
543fa9e406ahrens		if (SM_DEBUG_DECODE(entry)) {
54487219dbVictor Latushkin			(void) printf("\t    [%6llu] %s: txg %llu, pass %llu\n",
545fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
546fa9e406ahrens			    ddata[SM_DEBUG_ACTION_DECODE(entry)],
5475ad8204nd			    (u_longlong_t)SM_DEBUG_TXG_DECODE(entry),
5485ad8204nd			    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry));
549fa9e406ahrens		} else {
55087219dbVictor Latushkin			(void) printf("\t    [%6llu]    %c  range:"
55187219dbVictor Latushkin			    " %010llx-%010llx  size: %06llx\n",
552fa9e406ahrens			    (u_longlong_t)(offset / sizeof (entry)),
553fa9e406ahrens			    SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
5545ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
5555ad8204nd			    mapshift) + mapstart),
5565ad8204nd			    (u_longlong_t)((SM_OFFSET_DECODE(entry) <<
5575ad8204nd			    mapshift) + mapstart + (SM_RUN_DECODE(entry) <<
5585ad8204nd			    mapshift)),
5595ad8204nd			    (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
560fa9e406ahrens			if (SM_TYPE_DECODE(entry) == SM_ALLOC)
561fa9e406ahrens				alloc += SM_RUN_DECODE(entry) << mapshift;
562fa9e406ahrens			else
563fa9e406ahrens				alloc -= SM_RUN_DECODE(entry) << mapshift;
564fa9e406ahrens		}
565fa9e406ahrens	}
566fa9e406ahrens	if (alloc != smo->smo_alloc) {
567fa9e406ahrens		(void) printf("space_map_object alloc (%llu) INCONSISTENT "
568fa9e406ahrens		    "with space map summary (%llu)\n",
569fa9e406ahrens		    (u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc);
570fa9e406ahrens	}
573fa9e406ahrensstatic void
574d6e555bGeorge Wilsondump_metaslab_stats(metaslab_t *msp)
575d6e555bGeorge Wilson{
5763f9d6adLin Ling	char maxbuf[32];
57716a4a80George Wilson	space_map_t *sm = msp->ms_map;
578d6e555bGeorge Wilson	avl_tree_t *t = sm->sm_pp_root;
579d6e555bGeorge Wilson	int free_pct = sm->sm_space * 100 / sm->sm_size;
580d6e555bGeorge Wilson
5813f9d6adLin Ling	zdb_nicenum(space_map_maxsize(sm), maxbuf);
582d6e555bGeorge Wilson
58387219dbVictor Latushkin	(void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
584d6e555bGeorge Wilson	    "segments", avl_numnodes(t), "maxsize", maxbuf,
585d6e555bGeorge Wilson	    "freepct", free_pct);
586d6e555bGeorge Wilson}
587d6e555bGeorge Wilson
588d6e555bGeorge Wilsonstatic void
589fa9e406ahrensdump_metaslab(metaslab_t *msp)
591fa9e406ahrens	vdev_t *vd = msp->ms_group->mg_vd;
592fa9e406ahrens	spa_t *spa = vd->vdev_spa;
59316a4a80George Wilson	space_map_t *sm = msp->ms_map;
59480eb36fGeorge Wilson	space_map_obj_t *smo = &msp->ms_smo;
5953f9d6adLin Ling	char freebuf[32];
5973f9d6adLin Ling	zdb_nicenum(sm->sm_size - smo->smo_alloc, freebuf);
599fa9e406ahrens	(void) printf(
60087219dbVictor Latushkin	    "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
60180eb36fGeorge Wilson	    (u_longlong_t)(sm->sm_start / sm->sm_size),
60280eb36fGeorge Wilson	    (u_longlong_t)sm->sm_start, (u_longlong_t)smo->smo_object, freebuf);
60487219dbVictor Latushkin	if (dump_opt['m'] > 1 && !dump_opt['L']) {
605d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
60680eb36fGeorge Wilson		space_map_load_wait(sm);
607bc3975bVictor Latushkin		if (!sm->sm_loaded)
60880eb36fGeorge Wilson			VERIFY(space_map_load(sm, zfs_metaslab_ops,
60980eb36fGeorge Wilson			    SM_FREE, smo, spa->spa_meta_objset) == 0);
610bc3975bVictor Latushkin		dump_metaslab_stats(msp);
611bc3975bVictor Latushkin		space_map_unload(sm);
612d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
613d6e555bGeorge Wilson	}
614d6e555bGeorge Wilson
615d6e555bGeorge Wilson	if (dump_opt['d'] > 5 || dump_opt['m'] > 2) {
61680eb36fGeorge Wilson		ASSERT(sm->sm_size == (1ULL << vd->vdev_ms_shift));
617d6e555bGeorge Wilson
618d6e555bGeorge Wilson		mutex_enter(&msp->ms_lock);
61980eb36fGeorge Wilson		dump_spacemap(spa->spa_meta_objset, smo, sm);
620d6e555bGeorge Wilson		mutex_exit(&msp->ms_lock);
621d6e555bGeorge Wilson	}
62287219dbVictor Latushkin}
62487219dbVictor Latushkinstatic void
62587219dbVictor Latushkinprint_vdev_metaslab_header(vdev_t *vd)
62687219dbVictor Latushkin{
62787219dbVictor Latushkin	(void) printf("\tvdev %10llu\n\t%-10s%5llu   %-19s   %-15s   %-10s\n",
62887219dbVictor Latushkin	    (u_longlong_t)vd->vdev_id,
62987219dbVictor Latushkin	    "metaslabs", (u_longlong_t)vd->vdev_ms_count,
63087219dbVictor Latushkin	    "offset", "spacemap", "free");
63187219dbVictor Latushkin	(void) printf("\t%15s   %19s   %15s   %10s\n",
63287219dbVictor Latushkin	    "---------------", "-------------------",
63387219dbVictor Latushkin	    "---------------", "-------------");
636fa9e406ahrensstatic void
637fa9e406ahrensdump_metaslabs(spa_t *spa)
63987219dbVictor Latushkin	vdev_t *vd, *rvd = spa->spa_root_vdev;
64087219dbVictor Latushkin	uint64_t m, c = 0, children = rvd->vdev_children;
642fa9e406ahrens	(void) printf("\nMetaslabs:\n");
64487219dbVictor Latushkin	if (!dump_opt['d'] && zopt_objects > 0) {
64587219dbVictor Latushkin		c = zopt_object[0];
64687219dbVictor Latushkin
64787219dbVictor Latushkin		if (c >= children)
64887219dbVictor Latushkin			(void) fatal("bad vdev id: %llu", (u_longlong_t)c);
65087219dbVictor Latushkin		if (zopt_objects > 1) {
65187219dbVictor Latushkin			vd = rvd->vdev_child[c];
65287219dbVictor Latushkin			print_vdev_metaslab_header(vd);
65387219dbVictor Latushkin
65487219dbVictor Latushkin			for (m = 1; m < zopt_objects; m++) {
65587219dbVictor Latushkin				if (zopt_object[m] < vd->vdev_ms_count)
65687219dbVictor Latushkin					dump_metaslab(
65787219dbVictor Latushkin					    vd->vdev_ms[zopt_object[m]]);
65887219dbVictor Latushkin				else
65987219dbVictor Latushkin					(void) fprintf(stderr, "bad metaslab "
66087219dbVictor Latushkin					    "number %llu\n",
66187219dbVictor Latushkin					    (u_longlong_t)zopt_object[m]);
66287219dbVictor Latushkin			}
66387219dbVictor Latushkin			(void) printf("\n");
66487219dbVictor Latushkin			return;
66587219dbVictor Latushkin		}
66687219dbVictor Latushkin		children = c + 1;
66787219dbVictor Latushkin	}
66887219dbVictor Latushkin	for (; c < children; c++) {
66987219dbVictor Latushkin		vd = rvd->vdev_child[c];
67087219dbVictor Latushkin		print_vdev_metaslab_header(vd);
672fa9e406ahrens		for (m = 0; m < vd->vdev_ms_count; m++)
673fa9e406ahrens			dump_metaslab(vd->vdev_ms[m]);
674fa9e406ahrens		(void) printf("\n");
675fa9e406ahrens	}
678fa9e406ahrensstatic void
679b24ab67Jeff Bonwickdump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
680b24ab67Jeff Bonwick{
681b24ab67Jeff Bonwick	const ddt_phys_t *ddp = dde->dde_phys;
682b24ab67Jeff Bonwick	const ddt_key_t *ddk = &dde->dde_key;
683b24ab67Jeff Bonwick	char *types[4] = { "ditto", "single", "double", "triple" };
684b24ab67Jeff Bonwick	char blkbuf[BP_SPRINTF_LEN];
685b24ab67Jeff Bonwick	blkptr_t blk;
686b24ab67Jeff Bonwick
687b24ab67Jeff Bonwick	for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
688b24ab67Jeff Bonwick		if (ddp->ddp_phys_birth == 0)
689b24ab67Jeff Bonwick			continue;
690bbfd46cJeff Bonwick		ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
691b24ab67Jeff Bonwick		sprintf_blkptr(blkbuf, &blk);
692b24ab67Jeff Bonwick		(void) printf("index %llx refcnt %llu %s %s\n",
693b24ab67Jeff Bonwick		    (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
694b24ab67Jeff Bonwick		    types[p], blkbuf);
695b24ab67Jeff Bonwick	}
696b24ab67Jeff Bonwick}
697b24ab67Jeff Bonwick
698b24ab67Jeff Bonwickstatic void
699b24ab67Jeff Bonwickdump_dedup_ratio(const ddt_stat_t *dds)
700b24ab67Jeff Bonwick{
701b24ab67Jeff Bonwick	double rL, rP, rD, D, dedup, compress, copies;
702b24ab67Jeff Bonwick
703b24ab67Jeff Bonwick	if (dds->dds_blocks == 0)
704b24ab67Jeff Bonwick		return;
705b24ab67Jeff Bonwick
706b24ab67Jeff Bonwick	rL = (double)dds->dds_ref_lsize;
707b24ab67Jeff Bonwick	rP = (double)dds->dds_ref_psize;
708b24ab67Jeff Bonwick	rD = (double)dds->dds_ref_dsize;
709b24ab67Jeff Bonwick	D = (double)dds->dds_dsize;
710b24ab67Jeff Bonwick
711b24ab67Jeff Bonwick	dedup = rD / D;
712b24ab67Jeff Bonwick	compress = rL / rP;
713b24ab67Jeff Bonwick	copies = rD / rP;
714b24ab67Jeff Bonwick
715b24ab67Jeff Bonwick	(void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, "
716b24ab67Jeff Bonwick	    "dedup * compress / copies = %.2f\n\n",
717b24ab67Jeff Bonwick	    dedup, compress, copies, dedup * compress / copies);
718b24ab67Jeff Bonwick}
719b24ab67Jeff Bonwick
720b24ab67Jeff Bonwickstatic void
721b24ab67Jeff Bonwickdump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
722b24ab67Jeff Bonwick{
723b24ab67Jeff Bonwick	char name[DDT_NAMELEN];
724b24ab67Jeff Bonwick	ddt_entry_t dde;
725b24ab67Jeff Bonwick	uint64_t walk = 0;
726b24ab67Jeff Bonwick	dmu_object_info_t doi;
727b24ab67Jeff Bonwick	uint64_t count, dspace, mspace;
728b24ab67Jeff Bonwick	int error;
729b24ab67Jeff Bonwick
730b24ab67Jeff Bonwick	error = ddt_object_info(ddt, type, class, &doi);
731b24ab67Jeff Bonwick
732b24ab67Jeff Bonwick	if (error == ENOENT)
733b24ab67Jeff Bonwick		return;
734b24ab67Jeff Bonwick	ASSERT(error == 0);
735b24ab67Jeff Bonwick
7367448a07George Wilson	if ((count = ddt_object_count(ddt, type, class)) == 0)
7377448a07George Wilson		return;
7387448a07George Wilson
739b24ab67Jeff Bonwick	dspace = doi.doi_physical_blocks_512 << 9;
740b24ab67Jeff Bonwick	mspace = doi.doi_fill_count * doi.doi_data_block_size;
741b24ab67Jeff Bonwick
742b24ab67Jeff Bonwick	ddt_object_name(ddt, type, class, name);
743b24ab67Jeff Bonwick
744b24ab67Jeff Bonwick	(void) printf("%s: %llu entries, size %llu on disk, %llu in core\n",
745b24ab67Jeff Bonwick	    name,
746b24ab67Jeff Bonwick	    (u_longlong_t)count,
747b24ab67Jeff Bonwick	    (u_longlong_t)(dspace / count),
748b24ab67Jeff Bonwick	    (u_longlong_t)(mspace / count));
749b24ab67Jeff Bonwick
750b24ab67Jeff Bonwick	if (dump_opt['D'] < 3)
751b24ab67Jeff Bonwick		return;
752b24ab67Jeff Bonwick
7539eb19f4George Wilson	zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]);
754b24ab67Jeff Bonwick
755b24ab67Jeff Bonwick	if (dump_opt['D'] < 4)
756b24ab67Jeff Bonwick		return;
757b24ab67Jeff Bonwick
758b24ab67Jeff Bonwick	if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE)
759b24ab67Jeff Bonwick		return;
760b24ab67Jeff Bonwick
761b24ab67Jeff Bonwick	(void) printf("%s contents:\n\n", name);
762b24ab67Jeff Bonwick
763bbfd46cJeff Bonwick	while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0)
764b24ab67Jeff Bonwick		dump_dde(ddt, &dde, walk);
765b24ab67Jeff Bonwick
766b24ab67Jeff Bonwick	ASSERT(error == ENOENT);
767b24ab67Jeff Bonwick
768b24ab67Jeff Bonwick	(void) printf("\n");
769b24ab67Jeff Bonwick}
770b24ab67Jeff Bonwick
771b24ab67Jeff Bonwickstatic void
772b24ab67Jeff Bonwickdump_all_ddts(spa_t *spa)
773b24ab67Jeff Bonwick{
774b24ab67Jeff Bonwick	ddt_histogram_t ddh_total = { 0 };
775b24ab67Jeff Bonwick	ddt_stat_t dds_total = { 0 };
776b24ab67Jeff Bonwick
777b24ab67Jeff Bonwick	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
778b24ab67Jeff Bonwick		ddt_t *ddt = spa->spa_ddt[c];
779b24ab67Jeff Bonwick		for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
780b24ab67Jeff Bonwick			for (enum ddt_class class = 0; class < DDT_CLASSES;
781b24ab67Jeff Bonwick			    class++) {
782b24ab67Jeff Bonwick				dump_ddt(ddt, type, class);
783b24ab67Jeff Bonwick			}
784b24ab67Jeff Bonwick		}
785b24ab67Jeff Bonwick	}
786b24ab67Jeff Bonwick
7879eb19f4George Wilson	ddt_get_dedup_stats(spa, &dds_total);
788b24ab67Jeff Bonwick
789b24ab67Jeff Bonwick	if (dds_total.dds_blocks == 0) {
790b24ab67Jeff Bonwick		(void) printf("All DDTs are empty\n");
791b24ab67Jeff Bonwick		return;
792b24ab67Jeff Bonwick	}
793b24ab67Jeff Bonwick
794b24ab67Jeff Bonwick	(void) printf("\n");
795b24ab67Jeff Bonwick
796b24ab67Jeff Bonwick	if (dump_opt['D'] > 1) {
797b24ab67Jeff Bonwick		(void) printf("DDT histogram (aggregated over all DDTs):\n");
7989eb19f4George Wilson		ddt_get_dedup_histogram(spa, &ddh_total);
7999eb19f4George Wilson		zpool_dump_ddt(&dds_total, &ddh_total);
800b24ab67Jeff Bonwick	}
801b24ab67Jeff Bonwick
802b24ab67Jeff Bonwick	dump_dedup_ratio(&dds_total);
803b24ab67Jeff Bonwick}
804b24ab67Jeff Bonwick
805b24ab67Jeff Bonwickstatic void
8068ad4d6dJeff Bonwickdump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size)
8078ad4d6dJeff Bonwick{
8088ad4d6dJeff Bonwick	char *prefix = (void *)sm;
8098ad4d6dJeff Bonwick
8108ad4d6dJeff Bonwick	(void) printf("%s [%llu,%llu) length %llu\n",
8118ad4d6dJeff Bonwick	    prefix,
8128ad4d6dJeff Bonwick	    (u_longlong_t)start,
8138ad4d6dJeff Bonwick	    (u_longlong_t)(start + size),
8148ad4d6dJeff Bonwick	    (u_longlong_t)(size));
8158ad4d6dJeff Bonwick}
8168ad4d6dJeff Bonwick
8178ad4d6dJeff Bonwickstatic void
818fa9e406ahrensdump_dtl(vdev_t *vd, int indent)
8208ad4d6dJeff Bonwick	spa_t *spa = vd->vdev_spa;
8218ad4d6dJeff Bonwick	boolean_t required;
8228ad4d6dJeff Bonwick	char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" };
8238ad4d6dJeff Bonwick	char prefix[256];
8248ad4d6dJeff Bonwick
8258f18d1fGeorge Wilson	spa_vdev_state_enter(spa, SCL_NONE);
8268ad4d6dJeff Bonwick	required = vdev_dtl_required(vd);
8278ad4d6dJeff Bonwick	(void) spa_vdev_state_exit(spa, NULL, 0);
829fa9e406ahrens	if (indent == 0)
830fa9e406ahrens		(void) printf("\nDirty time logs:\n\n");
8328ad4d6dJeff Bonwick	(void) printf("\t%*s%s [%s]\n", indent, "",
833e14bb32Jeff Bonwick	    vd->vdev_path ? vd->vdev_path :
8348ad4d6dJeff Bonwick	    vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa),
8358ad4d6dJeff Bonwick	    required ? "DTL-required" : "DTL-expendable");
8378ad4d6dJeff Bonwick	for (int t = 0; t < DTL_TYPES; t++) {
8388ad4d6dJeff Bonwick		space_map_t *sm = &vd->vdev_dtl[t];
8398ad4d6dJeff Bonwick		if (sm->sm_space == 0)
8408ad4d6dJeff Bonwick			continue;
8418ad4d6dJeff Bonwick		(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
8428ad4d6dJeff Bonwick		    indent + 2, "", name[t]);
8438ad4d6dJeff Bonwick		mutex_enter(sm->sm_lock);
8448ad4d6dJeff Bonwick		space_map_walk(sm, dump_dtl_seg, (void *)prefix);
8458ad4d6dJeff Bonwick		mutex_exit(sm->sm_lock);
8468ad4d6dJeff Bonwick		if (dump_opt['d'] > 5 && vd->vdev_children == 0)
8478ad4d6dJeff Bonwick			dump_spacemap(spa->spa_meta_objset,
8488ad4d6dJeff Bonwick			    &vd->vdev_dtl_smo, sm);
849fa9e406ahrens	}
8518ad4d6dJeff Bonwick	for (int c = 0; c < vd->vdev_children; c++)
852fa9e406ahrens		dump_dtl(vd->vdev_child[c], indent + 4);
8558f18d1fGeorge Wilsonstatic void
8568f18d1fGeorge Wilsondump_history(spa_t *spa)
8578f18d1fGeorge Wilson{
8588f18d1fGeorge Wilson	nvlist_t **events = NULL;
8598f18d1fGeorge Wilson	char buf[SPA_MAXBLOCKSIZE];
860e4161dfVictor Latushkin	uint64_t resid, len, off = 0;
8618f18d1fGeorge Wilson	uint_t num = 0;
8628f18d1fGeorge Wilson	int error;
8638f18d1fGeorge Wilson	time_t tsec;
8648f18d1fGeorge Wilson	struct tm t;
8658f18d1fGeorge Wilson	char tbuf[30];
8668f18d1fGeorge Wilson	char internalstr[MAXPATHLEN];
8678f18d1fGeorge Wilson
8688f18d1fGeorge Wilson	do {
869e4161dfVictor Latushkin		len = sizeof (buf);
870e4161dfVictor Latushkin
8718f18d1fGeorge Wilson		if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
8728f18d1fGeorge Wilson			(void) fprintf(stderr, "Unable to read history: "
8738f18d1fGeorge Wilson			    "error %d\n", error);
8748f18d1fGeorge Wilson			return;
8758f18d1fGeorge Wilson		}
8768f18d1fGeorge Wilson
8778f18d1fGeorge Wilson		if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
8788f18d1fGeorge Wilson			break;
8798f18d1fGeorge Wilson
8808f18d1fGeorge Wilson		off -= resid;
8818f18d1fGeorge Wilson	} while (len != 0);
8828f18d1fGeorge Wilson
8838f18d1fGeorge Wilson	(void) printf("\nHistory:\n");
8848f18d1fGeorge Wilson	for (int i = 0; i < num; i++) {
8858f18d1fGeorge Wilson		uint64_t time, txg, ievent;
8868f18d1fGeorge Wilson		char *cmd, *intstr;
8874445fffMatthew Ahrens		boolean_t printed = B_FALSE;
8888f18d1fGeorge Wilson
8898f18d1fGeorge Wilson		if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME,
8908f18d1fGeorge Wilson		    &time) != 0)
8914445fffMatthew Ahrens			goto next;
8928f18d1fGeorge Wilson		if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD,
8938f18d1fGeorge Wilson		    &cmd) != 0) {
8948f18d1fGeorge Wilson			if (nvlist_lookup_uint64(events[i],
8958f18d1fGeorge Wilson			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
8964445fffMatthew Ahrens				goto next;
8978f18d1fGeorge Wilson			verify(nvlist_lookup_uint64(events[i],
8988f18d1fGeorge Wilson			    ZPOOL_HIST_TXG, &txg) == 0);
8998f18d1fGeorge Wilson			verify(nvlist_lookup_string(events[i],
9008f18d1fGeorge Wilson			    ZPOOL_HIST_INT_STR, &intstr) == 0);
9014445fffMatthew Ahrens			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS)
9024445fffMatthew Ahrens				goto next;
9038f18d1fGeorge Wilson
9048f18d1fGeorge Wilson			(void) snprintf(internalstr,
9058f18d1fGeorge Wilson			    sizeof (internalstr),
9068f18d1fGeorge Wilson			    "[internal %s txg:%lld] %s",
9073f9d6adLin Ling			    zfs_history_event_names[ievent], txg,
9088f18d1fGeorge Wilson			    intstr);
9098f18d1fGeorge Wilson			cmd = internalstr;
9108f18d1fGeorge Wilson		}
9118f18d1fGeorge Wilson		tsec = time;
9128f18d1fGeorge Wilson		(void) localtime_r(&tsec, &t);
9138f18d1fGeorge Wilson		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
9148f18d1fGeorge Wilson		(void) printf("%s %s\n", tbuf, cmd);
9154445fffMatthew Ahrens		printed = B_TRUE;
9164445fffMatthew Ahrens
9174445fffMatthew Ahrensnext:
9184445fffMatthew Ahrens		if (dump_opt['h'] > 1) {
9194445fffMatthew Ahrens			if (!printed)
9204445fffMatthew Ahrens				(void) printf("unrecognized record:\n");
9214445fffMatthew Ahrens			dump_nvlist(events[i], 2);
9224445fffMatthew Ahrens		}
9238f18d1fGeorge Wilson	}
9248f18d1fGeorge Wilson}
9258f18d1fGeorge Wilson
927fa9e406ahrensstatic void
928fa9e406ahrensdump_dnode(objset_t *os, uint64_t object, void *data, size_t size)
932fa9e406ahrensstatic uint64_t
933b24ab67Jeff Bonwickblkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp, const zbookmark_t *zb)
935b24ab67Jeff Bonwick	if (dnp == NULL) {
936b24ab67Jeff Bonwick		ASSERT(zb->zb_level < 0);
937b24ab67Jeff Bonwick		if (zb->zb_object == 0)
938b24ab67Jeff Bonwick			return (zb->zb_blkid);
939b24ab67Jeff Bonwick		return (zb->zb_blkid * BP_GET_LSIZE(bp));
940b24ab67Jeff Bonwick	}
941b24ab67Jeff Bonwick
942b24ab67Jeff Bonwick	ASSERT(zb->zb_level >= 0);
944b24ab67Jeff Bonwick	return ((zb->zb_blkid <<
945b24ab67Jeff Bonwick	    (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) *
946fa9e406ahrens	    dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
94944cd46cbillmstatic void
950cde58dbMatthew Ahrenssprintf_blkptr_compact(char *blkbuf, const blkptr_t *bp)
952cde58dbMatthew Ahrens	const dva_t *dva = bp->blk_dva;
953b24ab67Jeff Bonwick	int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
954b24ab67Jeff Bonwick
955490d05bMatthew Ahrens	if (dump_opt['b'] >= 6) {
956b24ab67Jeff Bonwick		sprintf_blkptr(blkbuf, bp);
957b24ab67Jeff Bonwick		return;
958b24ab67Jeff Bonwick	}
96044cd46cbillm	blkbuf[0] = '\0';
962b24ab67Jeff Bonwick	for (int i = 0; i < ndvas; i++)
96344cd46cbillm		(void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ",
96444cd46cbillm		    (u_longlong_t)DVA_GET_VDEV(&dva[i]),
96544cd46cbillm		    (u_longlong_t)DVA_GET_OFFSET(&dva[i]),
96644cd46cbillm		    (u_longlong_t)DVA_GET_ASIZE(&dva[i]));
968b24ab67Jeff Bonwick	(void) sprintf(blkbuf + strlen(blkbuf),
969b24ab67Jeff Bonwick	    "%llxL/%llxP F=%llu B=%llu/%llu",
97044cd46cbillm	    (u_longlong_t)BP_GET_LSIZE(bp),
97144cd46cbillm	    (u_longlong_t)BP_GET_PSIZE(bp),
97244cd46cbillm	    (u_longlong_t)bp->blk_fill,
973b24ab67Jeff Bonwick	    (u_longlong_t)bp->blk_birth,
974b24ab67Jeff Bonwick	    (u_longlong_t)BP_PHYSICAL_BIRTH(bp));
97788b7b0fMatthew Ahrensstatic void
97888b7b0fMatthew Ahrensprint_indirect(blkptr_t *bp, const zbookmark_t *zb,
97988b7b0fMatthew Ahrens    const dnode_phys_t *dnp)
98188b7b0fMatthew Ahrens	char blkbuf[BP_SPRINTF_LEN];
982fa9e406ahrens	int l;
98488b7b0fMatthew Ahrens	ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
98588b7b0fMatthew Ahrens	ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
987b24ab67Jeff Bonwick	(void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
989fa9e406ahrens	ASSERT(zb->zb_level >= 0);
991fa9e406ahrens	for (l = dnp->dn_nlevels - 1; l >= -1; l--) {
992fa9e406ahrens		if (l == zb->zb_level) {
99388b7b0fMatthew Ahrens			(void) printf("L%llx", (u_longlong_t)zb->zb_level);
994fa9e406ahrens		} else {