1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21236884Smm 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24268657Sdelphij * Copyright (c) 2011, 2014 by Delphix. All rights reserved. 25168404Spjd */ 26168404Spjd 27168404Spjd#include <stdio.h> 28249207Smm#include <unistd.h> 29168404Spjd#include <stdio_ext.h> 30168404Spjd#include <stdlib.h> 31168404Spjd#include <ctype.h> 32168404Spjd#include <sys/zfs_context.h> 33168404Spjd#include <sys/spa.h> 34168404Spjd#include <sys/spa_impl.h> 35168404Spjd#include <sys/dmu.h> 36168404Spjd#include <sys/zap.h> 37168404Spjd#include <sys/fs/zfs.h> 38168404Spjd#include <sys/zfs_znode.h> 39219089Spjd#include <sys/zfs_sa.h> 40219089Spjd#include <sys/sa.h> 41219089Spjd#include <sys/sa_impl.h> 42168404Spjd#include <sys/vdev.h> 43168404Spjd#include <sys/vdev_impl.h> 44168404Spjd#include <sys/metaslab_impl.h> 45168404Spjd#include <sys/dmu_objset.h> 46168404Spjd#include <sys/dsl_dir.h> 47168404Spjd#include <sys/dsl_dataset.h> 48168404Spjd#include <sys/dsl_pool.h> 49168404Spjd#include <sys/dbuf.h> 50168404Spjd#include <sys/zil.h> 51168404Spjd#include <sys/zil_impl.h> 52168404Spjd#include <sys/stat.h> 53168404Spjd#include <sys/resource.h> 54168404Spjd#include <sys/dmu_traverse.h> 55168404Spjd#include <sys/zio_checksum.h> 56168404Spjd#include <sys/zio_compress.h> 57185029Spjd#include <sys/zfs_fuid.h> 58208047Smm#include <sys/arc.h> 59219089Spjd#include <sys/ddt.h> 60236884Smm#include <sys/zfeature.h> 61248571Smm#include <zfs_comutil.h> 62185029Spjd#undef ZFS_MAXNAMELEN 63185029Spjd#undef verify 64185029Spjd#include <libzfs.h> 65168404Spjd 66244246Smm#define ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \ 67244246Smm zio_compress_table[(idx)].ci_name : "UNKNOWN") 68244246Smm#define ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \ 69244246Smm zio_checksum_table[(idx)].ci_name : "UNKNOWN") 70244246Smm#define ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \ 71244246Smm dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ? \ 72244246Smm dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN") 73244246Smm#define ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : \ 74244246Smm (((idx) == DMU_OTN_ZAP_DATA || (idx) == DMU_OTN_ZAP_METADATA) ? \ 75244246Smm DMU_OT_ZAP_OTHER : DMU_OT_NUMTYPES)) 76219089Spjd 77219089Spjd#ifndef lint 78268650Sdelphijextern boolean_t zfs_recover; 79273508Sdelphijextern uint64_t zfs_arc_max, zfs_arc_meta_limit; 80275488Sdelphijextern int zfs_vdev_async_read_max_active; 81219089Spjd#else 82268650Sdelphijboolean_t zfs_recover; 83273508Sdelphijuint64_t zfs_arc_max, zfs_arc_meta_limit; 84275488Sdelphijint zfs_vdev_async_read_max_active; 85219089Spjd#endif 86219089Spjd 87168404Spjdconst char cmdname[] = "zdb"; 88168404Spjduint8_t dump_opt[256]; 89168404Spjd 90168404Spjdtypedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size); 91168404Spjd 92168404Spjdextern void dump_intent_log(zilog_t *); 93168404Spjduint64_t *zopt_object = NULL; 94168404Spjdint zopt_objects = 0; 95185029Spjdlibzfs_handle_t *g_zfs; 96273508Sdelphijuint64_t max_inflight = 1000; 97168404Spjd 98168404Spjd/* 99168404Spjd * These libumem hooks provide a reasonable set of defaults for the allocator's 100168404Spjd * debugging facilities. 101168404Spjd */ 102168404Spjdconst char * 103168404Spjd_umem_debug_init() 104168404Spjd{ 105168404Spjd return ("default,verbose"); /* $UMEM_DEBUG setting */ 106168404Spjd} 107168404Spjd 108168404Spjdconst char * 109168404Spjd_umem_logging_init(void) 110168404Spjd{ 111168404Spjd return ("fail,contents"); /* $UMEM_LOGGING setting */ 112168404Spjd} 113168404Spjd 114168404Spjdstatic void 115168404Spjdusage(void) 116168404Spjd{ 117168404Spjd (void) fprintf(stderr, 118269773Sdelphij "Usage: %s [-CumMdibcsDvhLXFPA] [-t txg] [-e [-p path...]] " 119269773Sdelphij "[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n" 120263393Sdelphij " %s [-divPA] [-e -p path...] [-U config] dataset " 121263393Sdelphij "[object...]\n" 122269773Sdelphij " %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] " 123263393Sdelphij "poolname [vdev [metaslab...]]\n" 124263393Sdelphij " %s -R [-A] [-e [-p path...]] poolname " 125263393Sdelphij "vdev:offset:size[:flags]\n" 126263393Sdelphij " %s -S [-PA] [-e [-p path...]] [-U config] poolname\n" 127263393Sdelphij " %s -l [-uA] device\n" 128263393Sdelphij " %s -C [-A] [-U config]\n\n", 129219089Spjd cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname); 130168404Spjd 131219089Spjd (void) fprintf(stderr, " Dataset name must include at least one " 132219089Spjd "separator character '/' or '@'\n"); 133219089Spjd (void) fprintf(stderr, " If dataset name is specified, only that " 134219089Spjd "dataset is dumped\n"); 135219089Spjd (void) fprintf(stderr, " If object numbers are specified, only " 136219089Spjd "those objects are dumped\n\n"); 137219089Spjd (void) fprintf(stderr, " Options to control amount of output:\n"); 138219089Spjd (void) fprintf(stderr, " -u uberblock\n"); 139219089Spjd (void) fprintf(stderr, " -d dataset(s)\n"); 140219089Spjd (void) fprintf(stderr, " -i intent logs\n"); 141219089Spjd (void) fprintf(stderr, " -C config (or cachefile if alone)\n"); 142219089Spjd (void) fprintf(stderr, " -h pool history\n"); 143219089Spjd (void) fprintf(stderr, " -b block statistics\n"); 144219089Spjd (void) fprintf(stderr, " -m metaslabs\n"); 145269773Sdelphij (void) fprintf(stderr, " -M metaslab groups\n"); 146219089Spjd (void) fprintf(stderr, " -c checksum all metadata (twice for " 147209962Smm "all data) blocks\n"); 148219089Spjd (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); 149219089Spjd (void) fprintf(stderr, " -D dedup statistics\n"); 150219089Spjd (void) fprintf(stderr, " -S simulate dedup to measure effect\n"); 151219089Spjd (void) fprintf(stderr, " -v verbose (applies to all others)\n"); 152168404Spjd (void) fprintf(stderr, " -l dump label contents\n"); 153209962Smm (void) fprintf(stderr, " -L disable leak tracking (do not " 154209962Smm "load spacemaps)\n"); 155219089Spjd (void) fprintf(stderr, " -R read and display block from a " 156219089Spjd "device\n\n"); 157219089Spjd (void) fprintf(stderr, " Below options are intended for use " 158268653Sdelphij "with other options:\n"); 159219089Spjd (void) fprintf(stderr, " -A ignore assertions (-A), enable " 160219089Spjd "panic recovery (-AA) or both (-AAA)\n"); 161219089Spjd (void) fprintf(stderr, " -F attempt automatic rewind within " 162219089Spjd "safe range of transaction groups\n"); 163219089Spjd (void) fprintf(stderr, " -U <cachefile_path> -- use alternate " 164185029Spjd "cachefile\n"); 165219089Spjd (void) fprintf(stderr, " -X attempt extreme rewind (does not " 166219089Spjd "work with dataset)\n"); 167219089Spjd (void) fprintf(stderr, " -e pool is exported/destroyed/" 168219089Spjd "has altroot/not in a cachefile\n"); 169219089Spjd (void) fprintf(stderr, " -p <path> -- use one or more with " 170219089Spjd "-e to specify path to vdev dir\n"); 171268653Sdelphij (void) fprintf(stderr, " -x <dumpdir> -- " 172268653Sdelphij "dump all read blocks into specified directory\n"); 173268653Sdelphij (void) fprintf(stderr, " -P print numbers in parseable form\n"); 174219089Spjd (void) fprintf(stderr, " -t <txg> -- highest txg to use when " 175209962Smm "searching for uberblocks\n"); 176269773Sdelphij (void) fprintf(stderr, " -I <number of inflight I/Os> -- " 177268653Sdelphij "specify the maximum number of " 178268653Sdelphij "checksumming I/Os [default is 200]\n"); 179168404Spjd (void) fprintf(stderr, "Specify an option more than once (e.g. -bb) " 180168404Spjd "to make only that option verbose\n"); 181168404Spjd (void) fprintf(stderr, "Default is to dump everything non-verbosely\n"); 182168404Spjd exit(1); 183168404Spjd} 184168404Spjd 185209962Smm/* 186209962Smm * Called for usage errors that are discovered after a call to spa_open(), 187209962Smm * dmu_bonus_hold(), or pool_match(). abort() is called for other errors. 188209962Smm */ 189209962Smm 190168404Spjdstatic void 191168404Spjdfatal(const char *fmt, ...) 192168404Spjd{ 193168404Spjd va_list ap; 194168404Spjd 195168404Spjd va_start(ap, fmt); 196168404Spjd (void) fprintf(stderr, "%s: ", cmdname); 197168404Spjd (void) vfprintf(stderr, fmt, ap); 198168404Spjd va_end(ap); 199168404Spjd (void) fprintf(stderr, "\n"); 200168404Spjd 201209962Smm exit(1); 202168404Spjd} 203168404Spjd 204168404Spjd/* ARGSUSED */ 205168404Spjdstatic void 206168404Spjddump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size) 207168404Spjd{ 208168404Spjd nvlist_t *nv; 209168404Spjd size_t nvsize = *(uint64_t *)data; 210168404Spjd char *packed = umem_alloc(nvsize, UMEM_NOFAIL); 211168404Spjd 212209962Smm VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH)); 213168404Spjd 214168404Spjd VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0); 215168404Spjd 216168404Spjd umem_free(packed, nvsize); 217168404Spjd 218168404Spjd dump_nvlist(nv, 8); 219168404Spjd 220168404Spjd nvlist_free(nv); 221168404Spjd} 222168404Spjd 223248571Smm/* ARGSUSED */ 224219089Spjdstatic void 225248571Smmdump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size) 226248571Smm{ 227248571Smm spa_history_phys_t *shp = data; 228248571Smm 229248571Smm if (shp == NULL) 230248571Smm return; 231248571Smm 232248571Smm (void) printf("\t\tpool_create_len = %llu\n", 233248571Smm (u_longlong_t)shp->sh_pool_create_len); 234248571Smm (void) printf("\t\tphys_max_off = %llu\n", 235248571Smm (u_longlong_t)shp->sh_phys_max_off); 236248571Smm (void) printf("\t\tbof = %llu\n", 237248571Smm (u_longlong_t)shp->sh_bof); 238248571Smm (void) printf("\t\teof = %llu\n", 239248571Smm (u_longlong_t)shp->sh_eof); 240248571Smm (void) printf("\t\trecords_lost = %llu\n", 241248571Smm (u_longlong_t)shp->sh_records_lost); 242248571Smm} 243248571Smm 244248571Smmstatic void 245219089Spjdzdb_nicenum(uint64_t num, char *buf) 246219089Spjd{ 247219089Spjd if (dump_opt['P']) 248219089Spjd (void) sprintf(buf, "%llu", (longlong_t)num); 249219089Spjd else 250219089Spjd nicenum(num, buf); 251219089Spjd} 252219089Spjd 253249207Smmconst char histo_stars[] = "****************************************"; 254249207Smmconst int histo_width = sizeof (histo_stars) - 1; 255168404Spjd 256168404Spjdstatic void 257262093Savgdump_histogram(const uint64_t *histo, int size, int offset) 258168404Spjd{ 259168404Spjd int i; 260249207Smm int minidx = size - 1; 261168404Spjd int maxidx = 0; 262168404Spjd uint64_t max = 0; 263168404Spjd 264249207Smm for (i = 0; i < size; i++) { 265168404Spjd if (histo[i] > max) 266168404Spjd max = histo[i]; 267168404Spjd if (histo[i] > 0 && i > maxidx) 268168404Spjd maxidx = i; 269168404Spjd if (histo[i] > 0 && i < minidx) 270168404Spjd minidx = i; 271168404Spjd } 272168404Spjd 273249207Smm if (max < histo_width) 274249207Smm max = histo_width; 275168404Spjd 276249207Smm for (i = minidx; i <= maxidx; i++) { 277249207Smm (void) printf("\t\t\t%3u: %6llu %s\n", 278262093Savg i + offset, (u_longlong_t)histo[i], 279249207Smm &histo_stars[(max - histo[i]) * histo_width / max]); 280249207Smm } 281168404Spjd} 282168404Spjd 283168404Spjdstatic void 284168404Spjddump_zap_stats(objset_t *os, uint64_t object) 285168404Spjd{ 286168404Spjd int error; 287168404Spjd zap_stats_t zs; 288168404Spjd 289168404Spjd error = zap_get_stats(os, object, &zs); 290168404Spjd if (error) 291168404Spjd return; 292168404Spjd 293168404Spjd if (zs.zs_ptrtbl_len == 0) { 294168404Spjd ASSERT(zs.zs_num_blocks == 1); 295168404Spjd (void) printf("\tmicrozap: %llu bytes, %llu entries\n", 296168404Spjd (u_longlong_t)zs.zs_blocksize, 297168404Spjd (u_longlong_t)zs.zs_num_entries); 298168404Spjd return; 299168404Spjd } 300168404Spjd 301168404Spjd (void) printf("\tFat ZAP stats:\n"); 302168404Spjd 303168404Spjd (void) printf("\t\tPointer table:\n"); 304168404Spjd (void) printf("\t\t\t%llu elements\n", 305168404Spjd (u_longlong_t)zs.zs_ptrtbl_len); 306168404Spjd (void) printf("\t\t\tzt_blk: %llu\n", 307168404Spjd (u_longlong_t)zs.zs_ptrtbl_zt_blk); 308168404Spjd (void) printf("\t\t\tzt_numblks: %llu\n", 309168404Spjd (u_longlong_t)zs.zs_ptrtbl_zt_numblks); 310168404Spjd (void) printf("\t\t\tzt_shift: %llu\n", 311168404Spjd (u_longlong_t)zs.zs_ptrtbl_zt_shift); 312168404Spjd (void) printf("\t\t\tzt_blks_copied: %llu\n", 313168404Spjd (u_longlong_t)zs.zs_ptrtbl_blks_copied); 314168404Spjd (void) printf("\t\t\tzt_nextblk: %llu\n", 315168404Spjd (u_longlong_t)zs.zs_ptrtbl_nextblk); 316168404Spjd 317168404Spjd (void) printf("\t\tZAP entries: %llu\n", 318168404Spjd (u_longlong_t)zs.zs_num_entries); 319168404Spjd (void) printf("\t\tLeaf blocks: %llu\n", 320168404Spjd (u_longlong_t)zs.zs_num_leafs); 321168404Spjd (void) printf("\t\tTotal blocks: %llu\n", 322168404Spjd (u_longlong_t)zs.zs_num_blocks); 323168404Spjd (void) printf("\t\tzap_block_type: 0x%llx\n", 324168404Spjd (u_longlong_t)zs.zs_block_type); 325168404Spjd (void) printf("\t\tzap_magic: 0x%llx\n", 326168404Spjd (u_longlong_t)zs.zs_magic); 327168404Spjd (void) printf("\t\tzap_salt: 0x%llx\n", 328168404Spjd (u_longlong_t)zs.zs_salt); 329168404Spjd 330168404Spjd (void) printf("\t\tLeafs with 2^n pointers:\n"); 331262093Savg dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE, 0); 332168404Spjd 333168404Spjd (void) printf("\t\tBlocks with n*5 entries:\n"); 334262093Savg dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE, 0); 335168404Spjd 336168404Spjd (void) printf("\t\tBlocks n/10 full:\n"); 337262093Savg dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE, 0); 338168404Spjd 339168404Spjd (void) printf("\t\tEntries with n chunks:\n"); 340262093Savg dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE, 0); 341168404Spjd 342168404Spjd (void) printf("\t\tBuckets with n entries:\n"); 343262093Savg dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE, 0); 344168404Spjd} 345168404Spjd 346168404Spjd/*ARGSUSED*/ 347168404Spjdstatic void 348168404Spjddump_none(objset_t *os, uint64_t object, void *data, size_t size) 349168404Spjd{ 350168404Spjd} 351168404Spjd 352168404Spjd/*ARGSUSED*/ 353219089Spjdstatic void 354219089Spjddump_unknown(objset_t *os, uint64_t object, void *data, size_t size) 355219089Spjd{ 356219089Spjd (void) printf("\tUNKNOWN OBJECT TYPE\n"); 357219089Spjd} 358219089Spjd 359219089Spjd/*ARGSUSED*/ 360168404Spjdvoid 361168404Spjddump_uint8(objset_t *os, uint64_t object, void *data, size_t size) 362168404Spjd{ 363168404Spjd} 364168404Spjd 365168404Spjd/*ARGSUSED*/ 366168404Spjdstatic void 367168404Spjddump_uint64(objset_t *os, uint64_t object, void *data, size_t size) 368168404Spjd{ 369168404Spjd} 370168404Spjd 371168404Spjd/*ARGSUSED*/ 372168404Spjdstatic void 373168404Spjddump_zap(objset_t *os, uint64_t object, void *data, size_t size) 374168404Spjd{ 375168404Spjd zap_cursor_t zc; 376168404Spjd zap_attribute_t attr; 377168404Spjd void *prop; 378168404Spjd int i; 379168404Spjd 380168404Spjd dump_zap_stats(os, object); 381168404Spjd (void) printf("\n"); 382168404Spjd 383168404Spjd for (zap_cursor_init(&zc, os, object); 384168404Spjd zap_cursor_retrieve(&zc, &attr) == 0; 385168404Spjd zap_cursor_advance(&zc)) { 386168404Spjd (void) printf("\t\t%s = ", attr.za_name); 387168404Spjd if (attr.za_num_integers == 0) { 388168404Spjd (void) printf("\n"); 389168404Spjd continue; 390168404Spjd } 391168404Spjd prop = umem_zalloc(attr.za_num_integers * 392168404Spjd attr.za_integer_length, UMEM_NOFAIL); 393168404Spjd (void) zap_lookup(os, object, attr.za_name, 394168404Spjd attr.za_integer_length, attr.za_num_integers, prop); 395168404Spjd if (attr.za_integer_length == 1) { 396168404Spjd (void) printf("%s", (char *)prop); 397168404Spjd } else { 398168404Spjd for (i = 0; i < attr.za_num_integers; i++) { 399168404Spjd switch (attr.za_integer_length) { 400168404Spjd case 2: 401168404Spjd (void) printf("%u ", 402168404Spjd ((uint16_t *)prop)[i]); 403168404Spjd break; 404168404Spjd case 4: 405168404Spjd (void) printf("%u ", 406168404Spjd ((uint32_t *)prop)[i]); 407168404Spjd break; 408168404Spjd case 8: 409168404Spjd (void) printf("%lld ", 410168404Spjd (u_longlong_t)((int64_t *)prop)[i]); 411168404Spjd break; 412168404Spjd } 413168404Spjd } 414168404Spjd } 415168404Spjd (void) printf("\n"); 416168404Spjd umem_free(prop, attr.za_num_integers * attr.za_integer_length); 417168404Spjd } 418168404Spjd zap_cursor_fini(&zc); 419168404Spjd} 420168404Spjd 421185029Spjd/*ARGSUSED*/ 422168404Spjdstatic void 423219089Spjddump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size) 424219089Spjd{ 425219089Spjd dump_zap_stats(os, object); 426219089Spjd /* contents are printed elsewhere, properly decoded */ 427219089Spjd} 428219089Spjd 429219089Spjd/*ARGSUSED*/ 430219089Spjdstatic void 431219089Spjddump_sa_attrs(objset_t *os, uint64_t object, void *data, size_t size) 432219089Spjd{ 433219089Spjd zap_cursor_t zc; 434219089Spjd zap_attribute_t attr; 435219089Spjd 436219089Spjd dump_zap_stats(os, object); 437219089Spjd (void) printf("\n"); 438219089Spjd 439219089Spjd for (zap_cursor_init(&zc, os, object); 440219089Spjd zap_cursor_retrieve(&zc, &attr) == 0; 441219089Spjd zap_cursor_advance(&zc)) { 442219089Spjd (void) printf("\t\t%s = ", attr.za_name); 443219089Spjd if (attr.za_num_integers == 0) { 444219089Spjd (void) printf("\n"); 445219089Spjd continue; 446219089Spjd } 447219089Spjd (void) printf(" %llx : [%d:%d:%d]\n", 448219089Spjd (u_longlong_t)attr.za_first_integer, 449219089Spjd (int)ATTR_LENGTH(attr.za_first_integer), 450219089Spjd (int)ATTR_BSWAP(attr.za_first_integer), 451219089Spjd (int)ATTR_NUM(attr.za_first_integer)); 452219089Spjd } 453219089Spjd zap_cursor_fini(&zc); 454219089Spjd} 455219089Spjd 456219089Spjd/*ARGSUSED*/ 457219089Spjdstatic void 458219089Spjddump_sa_layouts(objset_t *os, uint64_t object, void *data, size_t size) 459219089Spjd{ 460219089Spjd zap_cursor_t zc; 461219089Spjd zap_attribute_t attr; 462219089Spjd uint16_t *layout_attrs; 463219089Spjd int i; 464219089Spjd 465219089Spjd dump_zap_stats(os, object); 466219089Spjd (void) printf("\n"); 467219089Spjd 468219089Spjd for (zap_cursor_init(&zc, os, object); 469219089Spjd zap_cursor_retrieve(&zc, &attr) == 0; 470219089Spjd zap_cursor_advance(&zc)) { 471219089Spjd (void) printf("\t\t%s = [", attr.za_name); 472219089Spjd if (attr.za_num_integers == 0) { 473219089Spjd (void) printf("\n"); 474219089Spjd continue; 475219089Spjd } 476219089Spjd 477219089Spjd VERIFY(attr.za_integer_length == 2); 478219089Spjd layout_attrs = umem_zalloc(attr.za_num_integers * 479219089Spjd attr.za_integer_length, UMEM_NOFAIL); 480219089Spjd 481219089Spjd VERIFY(zap_lookup(os, object, attr.za_name, 482219089Spjd attr.za_integer_length, 483219089Spjd attr.za_num_integers, layout_attrs) == 0); 484219089Spjd 485219089Spjd for (i = 0; i != attr.za_num_integers; i++) 486219089Spjd (void) printf(" %d ", (int)layout_attrs[i]); 487219089Spjd (void) printf("]\n"); 488219089Spjd umem_free(layout_attrs, 489219089Spjd attr.za_num_integers * attr.za_integer_length); 490219089Spjd } 491219089Spjd zap_cursor_fini(&zc); 492219089Spjd} 493219089Spjd 494219089Spjd/*ARGSUSED*/ 495219089Spjdstatic void 496185029Spjddump_zpldir(objset_t *os, uint64_t object, void *data, size_t size) 497185029Spjd{ 498185029Spjd zap_cursor_t zc; 499185029Spjd zap_attribute_t attr; 500185029Spjd const char *typenames[] = { 501185029Spjd /* 0 */ "not specified", 502185029Spjd /* 1 */ "FIFO", 503185029Spjd /* 2 */ "Character Device", 504185029Spjd /* 3 */ "3 (invalid)", 505185029Spjd /* 4 */ "Directory", 506185029Spjd /* 5 */ "5 (invalid)", 507185029Spjd /* 6 */ "Block Device", 508185029Spjd /* 7 */ "7 (invalid)", 509185029Spjd /* 8 */ "Regular File", 510185029Spjd /* 9 */ "9 (invalid)", 511185029Spjd /* 10 */ "Symbolic Link", 512185029Spjd /* 11 */ "11 (invalid)", 513185029Spjd /* 12 */ "Socket", 514185029Spjd /* 13 */ "Door", 515185029Spjd /* 14 */ "Event Port", 516185029Spjd /* 15 */ "15 (invalid)", 517185029Spjd }; 518185029Spjd 519185029Spjd dump_zap_stats(os, object); 520185029Spjd (void) printf("\n"); 521185029Spjd 522185029Spjd for (zap_cursor_init(&zc, os, object); 523185029Spjd zap_cursor_retrieve(&zc, &attr) == 0; 524185029Spjd zap_cursor_advance(&zc)) { 525185029Spjd (void) printf("\t\t%s = %lld (type: %s)\n", 526185029Spjd attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer), 527185029Spjd typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]); 528185029Spjd } 529185029Spjd zap_cursor_fini(&zc); 530185029Spjd} 531185029Spjd 532262093Savgint 533262093Savgget_dtl_refcount(vdev_t *vd) 534262093Savg{ 535262093Savg int refcount = 0; 536262093Savg 537262093Savg if (vd->vdev_ops->vdev_op_leaf) { 538262093Savg space_map_t *sm = vd->vdev_dtl_sm; 539262093Savg 540262093Savg if (sm != NULL && 541262093Savg sm->sm_dbuf->db_size == sizeof (space_map_phys_t)) 542262093Savg return (1); 543262093Savg return (0); 544262093Savg } 545262093Savg 546262093Savg for (int c = 0; c < vd->vdev_children; c++) 547262093Savg refcount += get_dtl_refcount(vd->vdev_child[c]); 548262093Savg return (refcount); 549262093Savg} 550262093Savg 551262093Savgint 552262093Savgget_metaslab_refcount(vdev_t *vd) 553262093Savg{ 554262093Savg int refcount = 0; 555262093Savg 556269773Sdelphij if (vd->vdev_top == vd && !vd->vdev_removing) { 557262093Savg for (int m = 0; m < vd->vdev_ms_count; m++) { 558262093Savg space_map_t *sm = vd->vdev_ms[m]->ms_sm; 559262093Savg 560262093Savg if (sm != NULL && 561262093Savg sm->sm_dbuf->db_size == sizeof (space_map_phys_t)) 562262093Savg refcount++; 563262093Savg } 564262093Savg } 565262093Savg for (int c = 0; c < vd->vdev_children; c++) 566262093Savg refcount += get_metaslab_refcount(vd->vdev_child[c]); 567262093Savg 568262093Savg return (refcount); 569262093Savg} 570262093Savg 571262093Savgstatic int 572262093Savgverify_spacemap_refcounts(spa_t *spa) 573262093Savg{ 574263390Sdelphij uint64_t expected_refcount = 0; 575263390Sdelphij uint64_t actual_refcount; 576262093Savg 577263390Sdelphij (void) feature_get_refcount(spa, 578263390Sdelphij &spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM], 579263390Sdelphij &expected_refcount); 580262093Savg actual_refcount = get_dtl_refcount(spa->spa_root_vdev); 581262093Savg actual_refcount += get_metaslab_refcount(spa->spa_root_vdev); 582262093Savg 583262093Savg if (expected_refcount != actual_refcount) { 584263390Sdelphij (void) printf("space map refcount mismatch: expected %lld != " 585263390Sdelphij "actual %lld\n", 586263390Sdelphij (longlong_t)expected_refcount, 587263390Sdelphij (longlong_t)actual_refcount); 588262093Savg return (2); 589262093Savg } 590262093Savg return (0); 591262093Savg} 592262093Savg 593185029Spjdstatic void 594262093Savgdump_spacemap(objset_t *os, space_map_t *sm) 595168404Spjd{ 596168404Spjd uint64_t alloc, offset, entry; 597168404Spjd char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID", 598168404Spjd "INVALID", "INVALID", "INVALID", "INVALID" }; 599168404Spjd 600262093Savg if (sm == NULL) 601168404Spjd return; 602168404Spjd 603168404Spjd /* 604168404Spjd * Print out the freelist entries in both encoded and decoded form. 605168404Spjd */ 606168404Spjd alloc = 0; 607262093Savg for (offset = 0; offset < space_map_length(sm); 608262093Savg offset += sizeof (entry)) { 609262093Savg uint8_t mapshift = sm->sm_shift; 610262093Savg 611262093Savg VERIFY0(dmu_read(os, space_map_object(sm), offset, 612209962Smm sizeof (entry), &entry, DMU_READ_PREFETCH)); 613168404Spjd if (SM_DEBUG_DECODE(entry)) { 614262093Savg 615219089Spjd (void) printf("\t [%6llu] %s: txg %llu, pass %llu\n", 616168404Spjd (u_longlong_t)(offset / sizeof (entry)), 617168404Spjd ddata[SM_DEBUG_ACTION_DECODE(entry)], 618168404Spjd (u_longlong_t)SM_DEBUG_TXG_DECODE(entry), 619168404Spjd (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(entry)); 620168404Spjd } else { 621219089Spjd (void) printf("\t [%6llu] %c range:" 622219089Spjd " %010llx-%010llx size: %06llx\n", 623168404Spjd (u_longlong_t)(offset / sizeof (entry)), 624168404Spjd SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 625168404Spjd (u_longlong_t)((SM_OFFSET_DECODE(entry) << 626262093Savg mapshift) + sm->sm_start), 627168404Spjd (u_longlong_t)((SM_OFFSET_DECODE(entry) << 628262093Savg mapshift) + sm->sm_start + 629262093Savg (SM_RUN_DECODE(entry) << mapshift)), 630168404Spjd (u_longlong_t)(SM_RUN_DECODE(entry) << mapshift)); 631168404Spjd if (SM_TYPE_DECODE(entry) == SM_ALLOC) 632168404Spjd alloc += SM_RUN_DECODE(entry) << mapshift; 633168404Spjd else 634168404Spjd alloc -= SM_RUN_DECODE(entry) << mapshift; 635168404Spjd } 636168404Spjd } 637262093Savg if (alloc != space_map_allocated(sm)) { 638168404Spjd (void) printf("space_map_object alloc (%llu) INCONSISTENT " 639168404Spjd "with space map summary (%llu)\n", 640262093Savg (u_longlong_t)space_map_allocated(sm), (u_longlong_t)alloc); 641168404Spjd } 642168404Spjd} 643168404Spjd 644168404Spjdstatic void 645209962Smmdump_metaslab_stats(metaslab_t *msp) 646209962Smm{ 647219089Spjd char maxbuf[32]; 648262093Savg range_tree_t *rt = msp->ms_tree; 649262093Savg avl_tree_t *t = &msp->ms_size_tree; 650262093Savg int free_pct = range_tree_space(rt) * 100 / msp->ms_size; 651209962Smm 652262093Savg zdb_nicenum(metaslab_block_maxsize(msp), maxbuf); 653209962Smm 654219089Spjd (void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n", 655209962Smm "segments", avl_numnodes(t), "maxsize", maxbuf, 656209962Smm "freepct", free_pct); 657262093Savg (void) printf("\tIn-memory histogram:\n"); 658262093Savg dump_histogram(rt->rt_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 659209962Smm} 660209962Smm 661209962Smmstatic void 662168404Spjddump_metaslab(metaslab_t *msp) 663168404Spjd{ 664168404Spjd vdev_t *vd = msp->ms_group->mg_vd; 665168404Spjd spa_t *spa = vd->vdev_spa; 666262093Savg space_map_t *sm = msp->ms_sm; 667219089Spjd char freebuf[32]; 668168404Spjd 669262093Savg zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf); 670168404Spjd 671168404Spjd (void) printf( 672219089Spjd "\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n", 673262093Savg (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start, 674262093Savg (u_longlong_t)space_map_object(sm), freebuf); 675168404Spjd 676262093Savg if (dump_opt['m'] > 2 && !dump_opt['L']) { 677209962Smm mutex_enter(&msp->ms_lock); 678262093Savg metaslab_load_wait(msp); 679262093Savg if (!msp->ms_loaded) { 680262093Savg VERIFY0(metaslab_load(msp)); 681262093Savg range_tree_stat_verify(msp->ms_tree); 682262093Savg } 683209962Smm dump_metaslab_stats(msp); 684262093Savg metaslab_unload(msp); 685209962Smm mutex_exit(&msp->ms_lock); 686209962Smm } 687168404Spjd 688262093Savg if (dump_opt['m'] > 1 && sm != NULL && 689263390Sdelphij spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) { 690262093Savg /* 691262093Savg * The space map histogram represents free space in chunks 692262093Savg * of sm_shift (i.e. bucket 0 refers to 2^sm_shift). 693262093Savg */ 694269773Sdelphij (void) printf("\tOn-disk histogram:\t\tfragmentation %llu\n", 695269773Sdelphij (u_longlong_t)msp->ms_fragmentation); 696262093Savg dump_histogram(sm->sm_phys->smp_histogram, 697269773Sdelphij SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift); 698262093Savg } 699209962Smm 700262093Savg if (dump_opt['d'] > 5 || dump_opt['m'] > 3) { 701262093Savg ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift)); 702262093Savg 703209962Smm mutex_enter(&msp->ms_lock); 704262093Savg dump_spacemap(spa->spa_meta_objset, msp->ms_sm); 705209962Smm mutex_exit(&msp->ms_lock); 706209962Smm } 707168404Spjd} 708168404Spjd 709168404Spjdstatic void 710219089Spjdprint_vdev_metaslab_header(vdev_t *vd) 711219089Spjd{ 712219089Spjd (void) printf("\tvdev %10llu\n\t%-10s%5llu %-19s %-15s %-10s\n", 713219089Spjd (u_longlong_t)vd->vdev_id, 714219089Spjd "metaslabs", (u_longlong_t)vd->vdev_ms_count, 715219089Spjd "offset", "spacemap", "free"); 716219089Spjd (void) printf("\t%15s %19s %15s %10s\n", 717219089Spjd "---------------", "-------------------", 718219089Spjd "---------------", "-------------"); 719219089Spjd} 720219089Spjd 721219089Spjdstatic void 722269773Sdelphijdump_metaslab_groups(spa_t *spa) 723269773Sdelphij{ 724269773Sdelphij vdev_t *rvd = spa->spa_root_vdev; 725269773Sdelphij metaslab_class_t *mc = spa_normal_class(spa); 726269773Sdelphij uint64_t fragmentation; 727269773Sdelphij 728269773Sdelphij metaslab_class_histogram_verify(mc); 729269773Sdelphij 730269773Sdelphij for (int c = 0; c < rvd->vdev_children; c++) { 731269773Sdelphij vdev_t *tvd = rvd->vdev_child[c]; 732269773Sdelphij metaslab_group_t *mg = tvd->vdev_mg; 733269773Sdelphij 734269773Sdelphij if (mg->mg_class != mc) 735269773Sdelphij continue; 736269773Sdelphij 737269773Sdelphij metaslab_group_histogram_verify(mg); 738269773Sdelphij mg->mg_fragmentation = metaslab_group_fragmentation(mg); 739269773Sdelphij 740269773Sdelphij (void) printf("\tvdev %10llu\t\tmetaslabs%5llu\t\t" 741269773Sdelphij "fragmentation", 742269773Sdelphij (u_longlong_t)tvd->vdev_id, 743269773Sdelphij (u_longlong_t)tvd->vdev_ms_count); 744269773Sdelphij if (mg->mg_fragmentation == ZFS_FRAG_INVALID) { 745269773Sdelphij (void) printf("%3s\n", "-"); 746269773Sdelphij } else { 747269773Sdelphij (void) printf("%3llu%%\n", 748269773Sdelphij (u_longlong_t)mg->mg_fragmentation); 749269773Sdelphij } 750269773Sdelphij dump_histogram(mg->mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 751269773Sdelphij } 752269773Sdelphij 753269773Sdelphij (void) printf("\tpool %s\tfragmentation", spa_name(spa)); 754269773Sdelphij fragmentation = metaslab_class_fragmentation(mc); 755269773Sdelphij if (fragmentation == ZFS_FRAG_INVALID) 756269773Sdelphij (void) printf("\t%3s\n", "-"); 757269773Sdelphij else 758269773Sdelphij (void) printf("\t%3llu%%\n", (u_longlong_t)fragmentation); 759269773Sdelphij dump_histogram(mc->mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 760269773Sdelphij} 761269773Sdelphij 762269773Sdelphijstatic void 763168404Spjddump_metaslabs(spa_t *spa) 764168404Spjd{ 765219089Spjd vdev_t *vd, *rvd = spa->spa_root_vdev; 766219089Spjd uint64_t m, c = 0, children = rvd->vdev_children; 767168404Spjd 768168404Spjd (void) printf("\nMetaslabs:\n"); 769168404Spjd 770219089Spjd if (!dump_opt['d'] && zopt_objects > 0) { 771219089Spjd c = zopt_object[0]; 772219089Spjd 773219089Spjd if (c >= children) 774219089Spjd (void) fatal("bad vdev id: %llu", (u_longlong_t)c); 775219089Spjd 776219089Spjd if (zopt_objects > 1) { 777219089Spjd vd = rvd->vdev_child[c]; 778219089Spjd print_vdev_metaslab_header(vd); 779219089Spjd 780219089Spjd for (m = 1; m < zopt_objects; m++) { 781219089Spjd if (zopt_object[m] < vd->vdev_ms_count) 782219089Spjd dump_metaslab( 783219089Spjd vd->vdev_ms[zopt_object[m]]); 784219089Spjd else 785219089Spjd (void) fprintf(stderr, "bad metaslab " 786219089Spjd "number %llu\n", 787219089Spjd (u_longlong_t)zopt_object[m]); 788219089Spjd } 789219089Spjd (void) printf("\n"); 790219089Spjd return; 791219089Spjd } 792219089Spjd children = c + 1; 793219089Spjd } 794219089Spjd for (; c < children; c++) { 795168404Spjd vd = rvd->vdev_child[c]; 796219089Spjd print_vdev_metaslab_header(vd); 797168404Spjd 798168404Spjd for (m = 0; m < vd->vdev_ms_count; m++) 799168404Spjd dump_metaslab(vd->vdev_ms[m]); 800168404Spjd (void) printf("\n"); 801168404Spjd } 802168404Spjd} 803168404Spjd 804168404Spjdstatic void 805219089Spjddump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index) 806219089Spjd{ 807219089Spjd const ddt_phys_t *ddp = dde->dde_phys; 808219089Spjd const ddt_key_t *ddk = &dde->dde_key; 809219089Spjd char *types[4] = { "ditto", "single", "double", "triple" }; 810219089Spjd char blkbuf[BP_SPRINTF_LEN]; 811219089Spjd blkptr_t blk; 812219089Spjd 813219089Spjd for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) { 814219089Spjd if (ddp->ddp_phys_birth == 0) 815219089Spjd continue; 816219089Spjd ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk); 817263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk); 818219089Spjd (void) printf("index %llx refcnt %llu %s %s\n", 819219089Spjd (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt, 820219089Spjd types[p], blkbuf); 821219089Spjd } 822219089Spjd} 823219089Spjd 824219089Spjdstatic void 825219089Spjddump_dedup_ratio(const ddt_stat_t *dds) 826219089Spjd{ 827219089Spjd double rL, rP, rD, D, dedup, compress, copies; 828219089Spjd 829219089Spjd if (dds->dds_blocks == 0) 830219089Spjd return; 831219089Spjd 832219089Spjd rL = (double)dds->dds_ref_lsize; 833219089Spjd rP = (double)dds->dds_ref_psize; 834219089Spjd rD = (double)dds->dds_ref_dsize; 835219089Spjd D = (double)dds->dds_dsize; 836219089Spjd 837219089Spjd dedup = rD / D; 838219089Spjd compress = rL / rP; 839219089Spjd copies = rD / rP; 840219089Spjd 841219089Spjd (void) printf("dedup = %.2f, compress = %.2f, copies = %.2f, " 842219089Spjd "dedup * compress / copies = %.2f\n\n", 843219089Spjd dedup, compress, copies, dedup * compress / copies); 844219089Spjd} 845219089Spjd 846219089Spjdstatic void 847219089Spjddump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class) 848219089Spjd{ 849219089Spjd char name[DDT_NAMELEN]; 850219089Spjd ddt_entry_t dde; 851219089Spjd uint64_t walk = 0; 852219089Spjd dmu_object_info_t doi; 853219089Spjd uint64_t count, dspace, mspace; 854219089Spjd int error; 855219089Spjd 856219089Spjd error = ddt_object_info(ddt, type, class, &doi); 857219089Spjd 858219089Spjd if (error == ENOENT) 859219089Spjd return; 860219089Spjd ASSERT(error == 0); 861219089Spjd 862245264Sdelphij error = ddt_object_count(ddt, type, class, &count); 863245264Sdelphij ASSERT(error == 0); 864245264Sdelphij if (count == 0) 865219089Spjd return; 866219089Spjd 867219089Spjd dspace = doi.doi_physical_blocks_512 << 9; 868219089Spjd mspace = doi.doi_fill_count * doi.doi_data_block_size; 869219089Spjd 870219089Spjd ddt_object_name(ddt, type, class, name); 871219089Spjd 872219089Spjd (void) printf("%s: %llu entries, size %llu on disk, %llu in core\n", 873219089Spjd name, 874219089Spjd (u_longlong_t)count, 875219089Spjd (u_longlong_t)(dspace / count), 876219089Spjd (u_longlong_t)(mspace / count)); 877219089Spjd 878219089Spjd if (dump_opt['D'] < 3) 879219089Spjd return; 880219089Spjd 881219089Spjd zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]); 882219089Spjd 883219089Spjd if (dump_opt['D'] < 4) 884219089Spjd return; 885219089Spjd 886219089Spjd if (dump_opt['D'] < 5 && class == DDT_CLASS_UNIQUE) 887219089Spjd return; 888219089Spjd 889219089Spjd (void) printf("%s contents:\n\n", name); 890219089Spjd 891219089Spjd while ((error = ddt_object_walk(ddt, type, class, &walk, &dde)) == 0) 892219089Spjd dump_dde(ddt, &dde, walk); 893219089Spjd 894219089Spjd ASSERT(error == ENOENT); 895219089Spjd 896219089Spjd (void) printf("\n"); 897219089Spjd} 898219089Spjd 899219089Spjdstatic void 900219089Spjddump_all_ddts(spa_t *spa) 901219089Spjd{ 902219089Spjd ddt_histogram_t ddh_total = { 0 }; 903219089Spjd ddt_stat_t dds_total = { 0 }; 904219089Spjd 905219089Spjd for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { 906219089Spjd ddt_t *ddt = spa->spa_ddt[c]; 907219089Spjd for (enum ddt_type type = 0; type < DDT_TYPES; type++) { 908219089Spjd for (enum ddt_class class = 0; class < DDT_CLASSES; 909219089Spjd class++) { 910219089Spjd dump_ddt(ddt, type, class); 911219089Spjd } 912219089Spjd } 913219089Spjd } 914219089Spjd 915219089Spjd ddt_get_dedup_stats(spa, &dds_total); 916219089Spjd 917219089Spjd if (dds_total.dds_blocks == 0) { 918219089Spjd (void) printf("All DDTs are empty\n"); 919219089Spjd return; 920219089Spjd } 921219089Spjd 922219089Spjd (void) printf("\n"); 923219089Spjd 924219089Spjd if (dump_opt['D'] > 1) { 925219089Spjd (void) printf("DDT histogram (aggregated over all DDTs):\n"); 926219089Spjd ddt_get_dedup_histogram(spa, &ddh_total); 927219089Spjd zpool_dump_ddt(&dds_total, &ddh_total); 928219089Spjd } 929219089Spjd 930219089Spjd dump_dedup_ratio(&dds_total); 931219089Spjd} 932219089Spjd 933219089Spjdstatic void 934262093Savgdump_dtl_seg(void *arg, uint64_t start, uint64_t size) 935209962Smm{ 936262093Savg char *prefix = arg; 937209962Smm 938209962Smm (void) printf("%s [%llu,%llu) length %llu\n", 939209962Smm prefix, 940209962Smm (u_longlong_t)start, 941209962Smm (u_longlong_t)(start + size), 942209962Smm (u_longlong_t)(size)); 943209962Smm} 944209962Smm 945209962Smmstatic void 946168404Spjddump_dtl(vdev_t *vd, int indent) 947168404Spjd{ 948209962Smm spa_t *spa = vd->vdev_spa; 949209962Smm boolean_t required; 950209962Smm char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" }; 951209962Smm char prefix[256]; 952168404Spjd 953219089Spjd spa_vdev_state_enter(spa, SCL_NONE); 954209962Smm required = vdev_dtl_required(vd); 955209962Smm (void) spa_vdev_state_exit(spa, NULL, 0); 956209962Smm 957168404Spjd if (indent == 0) 958168404Spjd (void) printf("\nDirty time logs:\n\n"); 959168404Spjd 960209962Smm (void) printf("\t%*s%s [%s]\n", indent, "", 961185029Spjd vd->vdev_path ? vd->vdev_path : 962209962Smm vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa), 963209962Smm required ? "DTL-required" : "DTL-expendable"); 964168404Spjd 965209962Smm for (int t = 0; t < DTL_TYPES; t++) { 966262093Savg range_tree_t *rt = vd->vdev_dtl[t]; 967262093Savg if (range_tree_space(rt) == 0) 968209962Smm continue; 969209962Smm (void) snprintf(prefix, sizeof (prefix), "\t%*s%s", 970209962Smm indent + 2, "", name[t]); 971262093Savg mutex_enter(rt->rt_lock); 972262093Savg range_tree_walk(rt, dump_dtl_seg, prefix); 973262093Savg mutex_exit(rt->rt_lock); 974209962Smm if (dump_opt['d'] > 5 && vd->vdev_children == 0) 975262093Savg dump_spacemap(spa->spa_meta_objset, vd->vdev_dtl_sm); 976168404Spjd } 977168404Spjd 978209962Smm for (int c = 0; c < vd->vdev_children; c++) 979168404Spjd dump_dtl(vd->vdev_child[c], indent + 4); 980168404Spjd} 981168404Spjd 982265039Sdelphij/* from spa_history.c: spa_history_create_obj() */ 983265039Sdelphij#define HIS_BUF_LEN_DEF (128 << 10) 984265039Sdelphij#define HIS_BUF_LEN_MAX (1 << 30) 985265039Sdelphij 986219089Spjdstatic void 987219089Spjddump_history(spa_t *spa) 988219089Spjd{ 989219089Spjd nvlist_t **events = NULL; 990265039Sdelphij char *buf = NULL; 991265039Sdelphij uint64_t bufsize = HIS_BUF_LEN_DEF; 992219089Spjd uint64_t resid, len, off = 0; 993219089Spjd uint_t num = 0; 994219089Spjd int error; 995219089Spjd time_t tsec; 996219089Spjd struct tm t; 997219089Spjd char tbuf[30]; 998219089Spjd char internalstr[MAXPATHLEN]; 999219089Spjd 1000265039Sdelphij if ((buf = malloc(bufsize)) == NULL) 1001265039Sdelphij (void) fprintf(stderr, "Unable to read history: " 1002265039Sdelphij "out of memory\n"); 1003219089Spjd do { 1004265039Sdelphij len = bufsize; 1005219089Spjd 1006219089Spjd if ((error = spa_history_get(spa, &off, &len, buf)) != 0) { 1007219089Spjd (void) fprintf(stderr, "Unable to read history: " 1008219089Spjd "error %d\n", error); 1009219089Spjd return; 1010219089Spjd } 1011219089Spjd 1012219089Spjd if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0) 1013219089Spjd break; 1014265039Sdelphij off -= resid; 1015219089Spjd 1016265039Sdelphij /* 1017265039Sdelphij * If the history block is too big, double the buffer 1018265039Sdelphij * size and try again. 1019265039Sdelphij */ 1020265039Sdelphij if (resid == len) { 1021265039Sdelphij free(buf); 1022265039Sdelphij buf = NULL; 1023265039Sdelphij 1024265039Sdelphij bufsize <<= 1; 1025265039Sdelphij if ((bufsize >= HIS_BUF_LEN_MAX) || 1026265039Sdelphij ((buf = malloc(bufsize)) == NULL)) { 1027265039Sdelphij (void) fprintf(stderr, "Unable to read history: " 1028265039Sdelphij "out of memory\n"); 1029265039Sdelphij return; 1030265039Sdelphij } 1031265039Sdelphij } 1032219089Spjd } while (len != 0); 1033265039Sdelphij free(buf); 1034219089Spjd 1035219089Spjd (void) printf("\nHistory:\n"); 1036219089Spjd for (int i = 0; i < num; i++) { 1037219089Spjd uint64_t time, txg, ievent; 1038219089Spjd char *cmd, *intstr; 1039248571Smm boolean_t printed = B_FALSE; 1040219089Spjd 1041219089Spjd if (nvlist_lookup_uint64(events[i], ZPOOL_HIST_TIME, 1042219089Spjd &time) != 0) 1043248571Smm goto next; 1044219089Spjd if (nvlist_lookup_string(events[i], ZPOOL_HIST_CMD, 1045219089Spjd &cmd) != 0) { 1046219089Spjd if (nvlist_lookup_uint64(events[i], 1047219089Spjd ZPOOL_HIST_INT_EVENT, &ievent) != 0) 1048248571Smm goto next; 1049219089Spjd verify(nvlist_lookup_uint64(events[i], 1050219089Spjd ZPOOL_HIST_TXG, &txg) == 0); 1051219089Spjd verify(nvlist_lookup_string(events[i], 1052219089Spjd ZPOOL_HIST_INT_STR, &intstr) == 0); 1053248571Smm if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) 1054248571Smm goto next; 1055219089Spjd 1056219089Spjd (void) snprintf(internalstr, 1057219089Spjd sizeof (internalstr), 1058219089Spjd "[internal %s txg:%lld] %s", 1059219089Spjd zfs_history_event_names[ievent], txg, 1060219089Spjd intstr); 1061219089Spjd cmd = internalstr; 1062219089Spjd } 1063219089Spjd tsec = time; 1064219089Spjd (void) localtime_r(&tsec, &t); 1065219089Spjd (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 1066219089Spjd (void) printf("%s %s\n", tbuf, cmd); 1067248571Smm printed = B_TRUE; 1068248571Smm 1069248571Smmnext: 1070248571Smm if (dump_opt['h'] > 1) { 1071248571Smm if (!printed) 1072248571Smm (void) printf("unrecognized record:\n"); 1073248571Smm dump_nvlist(events[i], 2); 1074248571Smm } 1075219089Spjd } 1076219089Spjd} 1077219089Spjd 1078168404Spjd/*ARGSUSED*/ 1079168404Spjdstatic void 1080168404Spjddump_dnode(objset_t *os, uint64_t object, void *data, size_t size) 1081168404Spjd{ 1082168404Spjd} 1083168404Spjd 1084168404Spjdstatic uint64_t 1085268657Sdelphijblkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp, 1086268657Sdelphij const zbookmark_phys_t *zb) 1087168404Spjd{ 1088219089Spjd if (dnp == NULL) { 1089219089Spjd ASSERT(zb->zb_level < 0); 1090219089Spjd if (zb->zb_object == 0) 1091219089Spjd return (zb->zb_blkid); 1092219089Spjd return (zb->zb_blkid * BP_GET_LSIZE(bp)); 1093219089Spjd } 1094168404Spjd 1095219089Spjd ASSERT(zb->zb_level >= 0); 1096219089Spjd 1097219089Spjd return ((zb->zb_blkid << 1098219089Spjd (zb->zb_level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) * 1099168404Spjd dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT); 1100168404Spjd} 1101168404Spjd 1102168404Spjdstatic void 1103263397Sdelphijsnprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp) 1104168404Spjd{ 1105219089Spjd const dva_t *dva = bp->blk_dva; 1106219089Spjd int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1; 1107168404Spjd 1108249207Smm if (dump_opt['b'] >= 6) { 1109263397Sdelphij snprintf_blkptr(blkbuf, buflen, bp); 1110219089Spjd return; 1111219089Spjd } 1112219089Spjd 1113268649Sdelphij if (BP_IS_EMBEDDED(bp)) { 1114268649Sdelphij (void) sprintf(blkbuf, 1115268649Sdelphij "EMBEDDED et=%u %llxL/%llxP B=%llu", 1116268649Sdelphij (int)BPE_GET_ETYPE(bp), 1117268649Sdelphij (u_longlong_t)BPE_GET_LSIZE(bp), 1118268649Sdelphij (u_longlong_t)BPE_GET_PSIZE(bp), 1119268649Sdelphij (u_longlong_t)bp->blk_birth); 1120268649Sdelphij return; 1121268649Sdelphij } 1122268649Sdelphij 1123168404Spjd blkbuf[0] = '\0'; 1124219089Spjd for (int i = 0; i < ndvas; i++) 1125263397Sdelphij (void) snprintf(blkbuf + strlen(blkbuf), 1126263397Sdelphij buflen - strlen(blkbuf), "%llu:%llx:%llx ", 1127168404Spjd (u_longlong_t)DVA_GET_VDEV(&dva[i]), 1128168404Spjd (u_longlong_t)DVA_GET_OFFSET(&dva[i]), 1129168404Spjd (u_longlong_t)DVA_GET_ASIZE(&dva[i])); 1130168404Spjd 1131263397Sdelphij if (BP_IS_HOLE(bp)) { 1132263397Sdelphij (void) snprintf(blkbuf + strlen(blkbuf), 1133263397Sdelphij buflen - strlen(blkbuf), "B=%llu", 1134263397Sdelphij (u_longlong_t)bp->blk_birth); 1135263397Sdelphij } else { 1136263397Sdelphij (void) snprintf(blkbuf + strlen(blkbuf), 1137263397Sdelphij buflen - strlen(blkbuf), 1138263397Sdelphij "%llxL/%llxP F=%llu B=%llu/%llu", 1139263397Sdelphij (u_longlong_t)BP_GET_LSIZE(bp), 1140263397Sdelphij (u_longlong_t)BP_GET_PSIZE(bp), 1141268649Sdelphij (u_longlong_t)BP_GET_FILL(bp), 1142263397Sdelphij (u_longlong_t)bp->blk_birth, 1143263397Sdelphij (u_longlong_t)BP_PHYSICAL_BIRTH(bp)); 1144263397Sdelphij } 1145168404Spjd} 1146168404Spjd 1147208047Smmstatic void 1148268657Sdelphijprint_indirect(blkptr_t *bp, const zbookmark_phys_t *zb, 1149208047Smm const dnode_phys_t *dnp) 1150168404Spjd{ 1151208047Smm char blkbuf[BP_SPRINTF_LEN]; 1152168404Spjd int l; 1153168404Spjd 1154268649Sdelphij if (!BP_IS_EMBEDDED(bp)) { 1155268649Sdelphij ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type); 1156268649Sdelphij ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level); 1157268649Sdelphij } 1158168404Spjd 1159219089Spjd (void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb)); 1160168404Spjd 1161208047Smm ASSERT(zb->zb_level >= 0); 1162168404Spjd 1163208047Smm for (l = dnp->dn_nlevels - 1; l >= -1; l--) { 1164208047Smm if (l == zb->zb_level) { 1165208047Smm (void) printf("L%llx", (u_longlong_t)zb->zb_level); 1166208047Smm } else { 1167208047Smm (void) printf(" "); 1168168404Spjd } 1169168404Spjd } 1170168404Spjd 1171263397Sdelphij snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp); 1172208047Smm (void) printf("%s\n", blkbuf); 1173208047Smm} 1174208047Smm 1175208047Smmstatic int 1176208047Smmvisit_indirect(spa_t *spa, const dnode_phys_t *dnp, 1177268657Sdelphij blkptr_t *bp, const zbookmark_phys_t *zb) 1178208047Smm{ 1179219089Spjd int err = 0; 1180208047Smm 1181208047Smm if (bp->blk_birth == 0) 1182208047Smm return (0); 1183208047Smm 1184208047Smm print_indirect(bp, zb, dnp); 1185208047Smm 1186263397Sdelphij if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) { 1187277586Sdelphij arc_flags_t flags = ARC_FLAG_WAIT; 1188208047Smm int i; 1189208047Smm blkptr_t *cbp; 1190208047Smm int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; 1191208047Smm arc_buf_t *buf; 1192168404Spjd uint64_t fill = 0; 1193168404Spjd 1194246666Smm err = arc_read(NULL, spa, bp, arc_getbuf_func, &buf, 1195208047Smm ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); 1196208047Smm if (err) 1197208047Smm return (err); 1198219089Spjd ASSERT(buf->b_data); 1199168404Spjd 1200208047Smm /* recursively visit blocks below this */ 1201208047Smm cbp = buf->b_data; 1202208047Smm for (i = 0; i < epb; i++, cbp++) { 1203268657Sdelphij zbookmark_phys_t czb; 1204168404Spjd 1205208047Smm SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object, 1206208047Smm zb->zb_level - 1, 1207208047Smm zb->zb_blkid * epb + i); 1208208047Smm err = visit_indirect(spa, dnp, cbp, &czb); 1209208047Smm if (err) 1210208047Smm break; 1211268649Sdelphij fill += BP_GET_FILL(cbp); 1212168404Spjd } 1213209962Smm if (!err) 1214268649Sdelphij ASSERT3U(fill, ==, BP_GET_FILL(bp)); 1215208047Smm (void) arc_buf_remove_ref(buf, &buf); 1216168404Spjd } 1217168404Spjd 1218208047Smm return (err); 1219168404Spjd} 1220168404Spjd 1221168404Spjd/*ARGSUSED*/ 1222168404Spjdstatic void 1223208047Smmdump_indirect(dnode_t *dn) 1224168404Spjd{ 1225208047Smm dnode_phys_t *dnp = dn->dn_phys; 1226208047Smm int j; 1227268657Sdelphij zbookmark_phys_t czb; 1228168404Spjd 1229168404Spjd (void) printf("Indirect blocks:\n"); 1230168404Spjd 1231219089Spjd SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset), 1232208047Smm dn->dn_object, dnp->dn_nlevels - 1, 0); 1233208047Smm for (j = 0; j < dnp->dn_nblkptr; j++) { 1234208047Smm czb.zb_blkid = j; 1235219089Spjd (void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp, 1236208047Smm &dnp->dn_blkptr[j], &czb); 1237208047Smm } 1238168404Spjd 1239168404Spjd (void) printf("\n"); 1240168404Spjd} 1241168404Spjd 1242168404Spjd/*ARGSUSED*/ 1243168404Spjdstatic void 1244168404Spjddump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size) 1245168404Spjd{ 1246168404Spjd dsl_dir_phys_t *dd = data; 1247168404Spjd time_t crtime; 1248219089Spjd char nice[32]; 1249168404Spjd 1250168404Spjd if (dd == NULL) 1251168404Spjd return; 1252168404Spjd 1253185029Spjd ASSERT3U(size, >=, sizeof (dsl_dir_phys_t)); 1254168404Spjd 1255168404Spjd crtime = dd->dd_creation_time; 1256168404Spjd (void) printf("\t\tcreation_time = %s", ctime(&crtime)); 1257168404Spjd (void) printf("\t\thead_dataset_obj = %llu\n", 1258168404Spjd (u_longlong_t)dd->dd_head_dataset_obj); 1259168404Spjd (void) printf("\t\tparent_dir_obj = %llu\n", 1260168404Spjd (u_longlong_t)dd->dd_parent_obj); 1261185029Spjd (void) printf("\t\torigin_obj = %llu\n", 1262185029Spjd (u_longlong_t)dd->dd_origin_obj); 1263168404Spjd (void) printf("\t\tchild_dir_zapobj = %llu\n", 1264168404Spjd (u_longlong_t)dd->dd_child_dir_zapobj); 1265219089Spjd zdb_nicenum(dd->dd_used_bytes, nice); 1266185029Spjd (void) printf("\t\tused_bytes = %s\n", nice); 1267219089Spjd zdb_nicenum(dd->dd_compressed_bytes, nice); 1268185029Spjd (void) printf("\t\tcompressed_bytes = %s\n", nice); 1269219089Spjd zdb_nicenum(dd->dd_uncompressed_bytes, nice); 1270185029Spjd (void) printf("\t\tuncompressed_bytes = %s\n", nice); 1271219089Spjd zdb_nicenum(dd->dd_quota, nice); 1272185029Spjd (void) printf("\t\tquota = %s\n", nice); 1273219089Spjd zdb_nicenum(dd->dd_reserved, nice); 1274185029Spjd (void) printf("\t\treserved = %s\n", nice); 1275168404Spjd (void) printf("\t\tprops_zapobj = %llu\n", 1276168404Spjd (u_longlong_t)dd->dd_props_zapobj); 1277185029Spjd (void) printf("\t\tdeleg_zapobj = %llu\n", 1278185029Spjd (u_longlong_t)dd->dd_deleg_zapobj); 1279185029Spjd (void) printf("\t\tflags = %llx\n", 1280185029Spjd (u_longlong_t)dd->dd_flags); 1281185029Spjd 1282185029Spjd#define DO(which) \ 1283219089Spjd zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \ 1284185029Spjd (void) printf("\t\tused_breakdown[" #which "] = %s\n", nice) 1285185029Spjd DO(HEAD); 1286185029Spjd DO(SNAP); 1287185029Spjd DO(CHILD); 1288185029Spjd DO(CHILD_RSRV); 1289185029Spjd DO(REFRSRV); 1290185029Spjd#undef DO 1291168404Spjd} 1292168404Spjd 1293168404Spjd/*ARGSUSED*/ 1294168404Spjdstatic void 1295168404Spjddump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size) 1296168404Spjd{ 1297168404Spjd dsl_dataset_phys_t *ds = data; 1298168404Spjd time_t crtime; 1299219089Spjd char used[32], compressed[32], uncompressed[32], unique[32]; 1300168404Spjd char blkbuf[BP_SPRINTF_LEN]; 1301168404Spjd 1302168404Spjd if (ds == NULL) 1303168404Spjd return; 1304168404Spjd 1305168404Spjd ASSERT(size == sizeof (*ds)); 1306168404Spjd crtime = ds->ds_creation_time; 1307236884Smm zdb_nicenum(ds->ds_referenced_bytes, used); 1308219089Spjd zdb_nicenum(ds->ds_compressed_bytes, compressed); 1309219089Spjd zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed); 1310219089Spjd zdb_nicenum(ds->ds_unique_bytes, unique); 1311263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp); 1312168404Spjd 1313185029Spjd (void) printf("\t\tdir_obj = %llu\n", 1314168404Spjd (u_longlong_t)ds->ds_dir_obj); 1315168404Spjd (void) printf("\t\tprev_snap_obj = %llu\n", 1316168404Spjd (u_longlong_t)ds->ds_prev_snap_obj); 1317168404Spjd (void) printf("\t\tprev_snap_txg = %llu\n", 1318168404Spjd (u_longlong_t)ds->ds_prev_snap_txg); 1319168404Spjd (void) printf("\t\tnext_snap_obj = %llu\n", 1320168404Spjd (u_longlong_t)ds->ds_next_snap_obj); 1321168404Spjd (void) printf("\t\tsnapnames_zapobj = %llu\n", 1322168404Spjd (u_longlong_t)ds->ds_snapnames_zapobj); 1323168404Spjd (void) printf("\t\tnum_children = %llu\n", 1324168404Spjd (u_longlong_t)ds->ds_num_children); 1325219089Spjd (void) printf("\t\tuserrefs_obj = %llu\n", 1326219089Spjd (u_longlong_t)ds->ds_userrefs_obj); 1327168404Spjd (void) printf("\t\tcreation_time = %s", ctime(&crtime)); 1328168404Spjd (void) printf("\t\tcreation_txg = %llu\n", 1329168404Spjd (u_longlong_t)ds->ds_creation_txg); 1330168404Spjd (void) printf("\t\tdeadlist_obj = %llu\n", 1331168404Spjd (u_longlong_t)ds->ds_deadlist_obj); 1332168404Spjd (void) printf("\t\tused_bytes = %s\n", used); 1333168404Spjd (void) printf("\t\tcompressed_bytes = %s\n", compressed); 1334168404Spjd (void) printf("\t\tuncompressed_bytes = %s\n", uncompressed); 1335168404Spjd (void) printf("\t\tunique = %s\n", unique); 1336168404Spjd (void) printf("\t\tfsid_guid = %llu\n", 1337168404Spjd (u_longlong_t)ds->ds_fsid_guid); 1338168404Spjd (void) printf("\t\tguid = %llu\n", 1339168404Spjd (u_longlong_t)ds->ds_guid); 1340168404Spjd (void) printf("\t\tflags = %llx\n", 1341168404Spjd (u_longlong_t)ds->ds_flags); 1342185029Spjd (void) printf("\t\tnext_clones_obj = %llu\n", 1343185029Spjd (u_longlong_t)ds->ds_next_clones_obj); 1344185029Spjd (void) printf("\t\tprops_obj = %llu\n", 1345185029Spjd (u_longlong_t)ds->ds_props_obj); 1346168404Spjd (void) printf("\t\tbp = %s\n", blkbuf); 1347168404Spjd} 1348168404Spjd 1349219089Spjd/* ARGSUSED */ 1350219089Spjdstatic int 1351236884Smmdump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx) 1352236884Smm{ 1353236884Smm char blkbuf[BP_SPRINTF_LEN]; 1354236884Smm 1355236884Smm if (bp->blk_birth != 0) { 1356263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); 1357236884Smm (void) printf("\t%s\n", blkbuf); 1358236884Smm } 1359236884Smm return (0); 1360236884Smm} 1361236884Smm 1362236884Smmstatic void 1363236884Smmdump_bptree(objset_t *os, uint64_t obj, char *name) 1364236884Smm{ 1365236884Smm char bytes[32]; 1366236884Smm bptree_phys_t *bt; 1367236884Smm dmu_buf_t *db; 1368236884Smm 1369236884Smm if (dump_opt['d'] < 3) 1370236884Smm return; 1371236884Smm 1372236884Smm VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db)); 1373236884Smm bt = db->db_data; 1374236884Smm zdb_nicenum(bt->bt_bytes, bytes); 1375236884Smm (void) printf("\n %s: %llu datasets, %s\n", 1376236884Smm name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes); 1377236884Smm dmu_buf_rele(db, FTAG); 1378236884Smm 1379236884Smm if (dump_opt['d'] < 5) 1380236884Smm return; 1381236884Smm 1382236884Smm (void) printf("\n"); 1383236884Smm 1384236884Smm (void) bptree_iterate(os, obj, B_FALSE, dump_bptree_cb, NULL, NULL); 1385236884Smm} 1386236884Smm 1387236884Smm/* ARGSUSED */ 1388236884Smmstatic int 1389219089Spjddump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx) 1390219089Spjd{ 1391219089Spjd char blkbuf[BP_SPRINTF_LEN]; 1392219089Spjd 1393219089Spjd ASSERT(bp->blk_birth != 0); 1394263397Sdelphij snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp); 1395219089Spjd (void) printf("\t%s\n", blkbuf); 1396219089Spjd return (0); 1397219089Spjd} 1398219089Spjd 1399168404Spjdstatic void 1400247852Smmdump_bpobj(bpobj_t *bpo, char *name, int indent) 1401168404Spjd{ 1402219089Spjd char bytes[32]; 1403219089Spjd char comp[32]; 1404219089Spjd char uncomp[32]; 1405168404Spjd 1406168404Spjd if (dump_opt['d'] < 3) 1407168404Spjd return; 1408168404Spjd 1409219089Spjd zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes); 1410247852Smm if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) { 1411219089Spjd zdb_nicenum(bpo->bpo_phys->bpo_comp, comp); 1412219089Spjd zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp); 1413247852Smm (void) printf(" %*s: object %llu, %llu local blkptrs, " 1414247852Smm "%llu subobjs, %s (%s/%s comp)\n", 1415247852Smm indent * 8, name, 1416247852Smm (u_longlong_t)bpo->bpo_object, 1417247852Smm (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs, 1418219089Spjd (u_longlong_t)bpo->bpo_phys->bpo_num_subobjs, 1419168404Spjd bytes, comp, uncomp); 1420247852Smm 1421247852Smm for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) { 1422247852Smm uint64_t subobj; 1423247852Smm bpobj_t subbpo; 1424247852Smm int error; 1425247852Smm VERIFY0(dmu_read(bpo->bpo_os, 1426247852Smm bpo->bpo_phys->bpo_subobjs, 1427247852Smm i * sizeof (subobj), sizeof (subobj), &subobj, 0)); 1428247852Smm error = bpobj_open(&subbpo, bpo->bpo_os, subobj); 1429247852Smm if (error != 0) { 1430247852Smm (void) printf("ERROR %u while trying to open " 1431247852Smm "subobj id %llu\n", 1432247852Smm error, (u_longlong_t)subobj); 1433247852Smm continue; 1434247852Smm } 1435247852Smm dump_bpobj(&subbpo, "subobj", indent + 1); 1436248267Smm bpobj_close(&subbpo); 1437247852Smm } 1438168404Spjd } else { 1439247852Smm (void) printf(" %*s: object %llu, %llu blkptrs, %s\n", 1440247852Smm indent * 8, name, 1441247852Smm (u_longlong_t)bpo->bpo_object, 1442247852Smm (u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs, 1443247852Smm bytes); 1444168404Spjd } 1445168404Spjd 1446219089Spjd if (dump_opt['d'] < 5) 1447168404Spjd return; 1448168404Spjd 1449168404Spjd 1450247852Smm if (indent == 0) { 1451247852Smm (void) bpobj_iterate_nofree(bpo, dump_bpobj_cb, NULL, NULL); 1452247852Smm (void) printf("\n"); 1453247852Smm } 1454219089Spjd} 1455168404Spjd 1456219089Spjdstatic void 1457219089Spjddump_deadlist(dsl_deadlist_t *dl) 1458219089Spjd{ 1459219089Spjd dsl_deadlist_entry_t *dle; 1460247852Smm uint64_t unused; 1461219089Spjd char bytes[32]; 1462219089Spjd char comp[32]; 1463219089Spjd char uncomp[32]; 1464219089Spjd 1465219089Spjd if (dump_opt['d'] < 3) 1466219089Spjd return; 1467219089Spjd 1468273349Sdelphij if (dl->dl_oldfmt) { 1469273349Sdelphij dump_bpobj(&dl->dl_bpobj, "old-format deadlist", 0); 1470273349Sdelphij return; 1471273349Sdelphij } 1472273349Sdelphij 1473219089Spjd zdb_nicenum(dl->dl_phys->dl_used, bytes); 1474219089Spjd zdb_nicenum(dl->dl_phys->dl_comp, comp); 1475219089Spjd zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp); 1476219089Spjd (void) printf("\n Deadlist: %s (%s/%s comp)\n", 1477219089Spjd bytes, comp, uncomp); 1478219089Spjd 1479219089Spjd if (dump_opt['d'] < 4) 1480219089Spjd return; 1481219089Spjd 1482219089Spjd (void) printf("\n"); 1483219089Spjd 1484247852Smm /* force the tree to be loaded */ 1485247852Smm dsl_deadlist_space_range(dl, 0, UINT64_MAX, &unused, &unused, &unused); 1486247852Smm 1487219089Spjd for (dle = avl_first(&dl->dl_tree); dle; 1488219089Spjd dle = AVL_NEXT(&dl->dl_tree, dle)) { 1489247852Smm if (dump_opt['d'] >= 5) { 1490247852Smm char buf[128]; 1491247852Smm (void) snprintf(buf, sizeof (buf), "mintxg %llu -> ", 1492247852Smm (longlong_t)dle->dle_mintxg, 1493247852Smm (longlong_t)dle->dle_bpobj.bpo_object); 1494219089Spjd 1495247852Smm dump_bpobj(&dle->dle_bpobj, buf, 0); 1496247852Smm } else { 1497247852Smm (void) printf("mintxg %llu -> obj %llu\n", 1498247852Smm (longlong_t)dle->dle_mintxg, 1499247852Smm (longlong_t)dle->dle_bpobj.bpo_object); 1500247852Smm 1501247852Smm } 1502168404Spjd } 1503168404Spjd} 1504168404Spjd 1505185029Spjdstatic avl_tree_t idx_tree; 1506185029Spjdstatic avl_tree_t domain_tree; 1507185029Spjdstatic boolean_t fuid_table_loaded; 1508219089Spjdstatic boolean_t sa_loaded; 1509219089Spjdsa_attr_type_t *sa_attr_table; 1510185029Spjd 1511185029Spjdstatic void 1512185029Spjdfuid_table_destroy() 1513185029Spjd{ 1514185029Spjd if (fuid_table_loaded) { 1515185029Spjd zfs_fuid_table_destroy(&idx_tree, &domain_tree); 1516185029Spjd fuid_table_loaded = B_FALSE; 1517185029Spjd } 1518185029Spjd} 1519185029Spjd 1520185029Spjd/* 1521185029Spjd * print uid or gid information. 1522185029Spjd * For normal POSIX id just the id is printed in decimal format. 1523185029Spjd * For CIFS files with FUID the fuid is printed in hex followed by 1524247852Smm * the domain-rid string. 1525185029Spjd */ 1526185029Spjdstatic void 1527185029Spjdprint_idstr(uint64_t id, const char *id_type) 1528185029Spjd{ 1529185029Spjd if (FUID_INDEX(id)) { 1530185029Spjd char *domain; 1531185029Spjd 1532185029Spjd domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id)); 1533185029Spjd (void) printf("\t%s %llx [%s-%d]\n", id_type, 1534185029Spjd (u_longlong_t)id, domain, (int)FUID_RID(id)); 1535185029Spjd } else { 1536185029Spjd (void) printf("\t%s %llu\n", id_type, (u_longlong_t)id); 1537185029Spjd } 1538185029Spjd 1539185029Spjd} 1540185029Spjd 1541185029Spjdstatic void 1542219089Spjddump_uidgid(objset_t *os, uint64_t uid, uint64_t gid) 1543185029Spjd{ 1544185029Spjd uint32_t uid_idx, gid_idx; 1545185029Spjd 1546219089Spjd uid_idx = FUID_INDEX(uid); 1547219089Spjd gid_idx = FUID_INDEX(gid); 1548185029Spjd 1549185029Spjd /* Load domain table, if not already loaded */ 1550185029Spjd if (!fuid_table_loaded && (uid_idx || gid_idx)) { 1551185029Spjd uint64_t fuid_obj; 1552185029Spjd 1553185029Spjd /* first find the fuid object. It lives in the master node */ 1554185029Spjd VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 1555185029Spjd 8, 1, &fuid_obj) == 0); 1556209962Smm zfs_fuid_avl_tree_create(&idx_tree, &domain_tree); 1557185029Spjd (void) zfs_fuid_table_load(os, fuid_obj, 1558185029Spjd &idx_tree, &domain_tree); 1559185029Spjd fuid_table_loaded = B_TRUE; 1560185029Spjd } 1561185029Spjd 1562219089Spjd print_idstr(uid, "uid"); 1563219089Spjd print_idstr(gid, "gid"); 1564185029Spjd} 1565185029Spjd 1566168404Spjd/*ARGSUSED*/ 1567168404Spjdstatic void 1568168404Spjddump_znode(objset_t *os, uint64_t object, void *data, size_t size) 1569168404Spjd{ 1570219089Spjd char path[MAXPATHLEN * 2]; /* allow for xattr and failure prefix */ 1571219089Spjd sa_handle_t *hdl; 1572219089Spjd uint64_t xattr, rdev, gen; 1573219089Spjd uint64_t uid, gid, mode, fsize, parent, links; 1574219089Spjd uint64_t pflags; 1575219089Spjd uint64_t acctm[2], modtm[2], chgtm[2], crtm[2]; 1576168404Spjd time_t z_crtime, z_atime, z_mtime, z_ctime; 1577219089Spjd sa_bulk_attr_t bulk[12]; 1578219089Spjd int idx = 0; 1579168404Spjd int error; 1580168404Spjd 1581219089Spjd if (!sa_loaded) { 1582219089Spjd uint64_t sa_attrs = 0; 1583219089Spjd uint64_t version; 1584168404Spjd 1585219089Spjd VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 1586219089Spjd 8, 1, &version) == 0); 1587219089Spjd if (version >= ZPL_VERSION_SA) { 1588219089Spjd VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 1589219089Spjd 8, 1, &sa_attrs) == 0); 1590219089Spjd } 1591219089Spjd if ((error = sa_setup(os, sa_attrs, zfs_attr_table, 1592219089Spjd ZPL_END, &sa_attr_table)) != 0) { 1593219089Spjd (void) printf("sa_setup failed errno %d, can't " 1594219089Spjd "display znode contents\n", error); 1595219089Spjd return; 1596219089Spjd } 1597219089Spjd sa_loaded = B_TRUE; 1598219089Spjd } 1599219089Spjd 1600219089Spjd if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) { 1601219089Spjd (void) printf("Failed to get handle for SA znode\n"); 1602219089Spjd return; 1603219089Spjd } 1604219089Spjd 1605219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_UID], NULL, &uid, 8); 1606219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GID], NULL, &gid, 8); 1607219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_LINKS], NULL, 1608219089Spjd &links, 8); 1609219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_GEN], NULL, &gen, 8); 1610219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MODE], NULL, 1611219089Spjd &mode, 8); 1612219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_PARENT], 1613219089Spjd NULL, &parent, 8); 1614219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_SIZE], NULL, 1615219089Spjd &fsize, 8); 1616219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_ATIME], NULL, 1617219089Spjd acctm, 16); 1618219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_MTIME], NULL, 1619219089Spjd modtm, 16); 1620219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CRTIME], NULL, 1621219089Spjd crtm, 16); 1622219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_CTIME], NULL, 1623219089Spjd chgtm, 16); 1624219089Spjd SA_ADD_BULK_ATTR(bulk, idx, sa_attr_table[ZPL_FLAGS], NULL, 1625219089Spjd &pflags, 8); 1626219089Spjd 1627219089Spjd if (sa_bulk_lookup(hdl, bulk, idx)) { 1628219089Spjd (void) sa_handle_destroy(hdl); 1629219089Spjd return; 1630219089Spjd } 1631219089Spjd 1632168404Spjd error = zfs_obj_to_path(os, object, path, sizeof (path)); 1633168404Spjd if (error != 0) { 1634168404Spjd (void) snprintf(path, sizeof (path), "\?\?\?<object#%llu>", 1635168404Spjd (u_longlong_t)object); 1636168404Spjd } 1637168404Spjd if (dump_opt['d'] < 3) { 1638168404Spjd (void) printf("\t%s\n", path); 1639219089Spjd (void) sa_handle_destroy(hdl); 1640168404Spjd return; 1641168404Spjd } 1642168404Spjd 1643219089Spjd z_crtime = (time_t)crtm[0]; 1644219089Spjd z_atime = (time_t)acctm[0]; 1645219089Spjd z_mtime = (time_t)modtm[0]; 1646219089Spjd z_ctime = (time_t)chgtm[0]; 1647168404Spjd 1648168404Spjd (void) printf("\tpath %s\n", path); 1649219089Spjd dump_uidgid(os, uid, gid); 1650168404Spjd (void) printf("\tatime %s", ctime(&z_atime)); 1651168404Spjd (void) printf("\tmtime %s", ctime(&z_mtime)); 1652168404Spjd (void) printf("\tctime %s", ctime(&z_ctime)); 1653168404Spjd (void) printf("\tcrtime %s", ctime(&z_crtime)); 1654219089Spjd (void) printf("\tgen %llu\n", (u_longlong_t)gen); 1655219089Spjd (void) printf("\tmode %llo\n", (u_longlong_t)mode); 1656219089Spjd (void) printf("\tsize %llu\n", (u_longlong_t)fsize); 1657219089Spjd (void) printf("\tparent %llu\n", (u_longlong_t)parent); 1658219089Spjd (void) printf("\tlinks %llu\n", (u_longlong_t)links); 1659219089Spjd (void) printf("\tpflags %llx\n", (u_longlong_t)pflags); 1660219089Spjd if (sa_lookup(hdl, sa_attr_table[ZPL_XATTR], &xattr, 1661219089Spjd sizeof (uint64_t)) == 0) 1662219089Spjd (void) printf("\txattr %llu\n", (u_longlong_t)xattr); 1663219089Spjd if (sa_lookup(hdl, sa_attr_table[ZPL_RDEV], &rdev, 1664219089Spjd sizeof (uint64_t)) == 0) 1665219089Spjd (void) printf("\trdev 0x%016llx\n", (u_longlong_t)rdev); 1666219089Spjd sa_handle_destroy(hdl); 1667168404Spjd} 1668168404Spjd 1669168404Spjd/*ARGSUSED*/ 1670168404Spjdstatic void 1671168404Spjddump_acl(objset_t *os, uint64_t object, void *data, size_t size) 1672168404Spjd{ 1673168404Spjd} 1674168404Spjd 1675168404Spjd/*ARGSUSED*/ 1676168404Spjdstatic void 1677168404Spjddump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size) 1678168404Spjd{ 1679168404Spjd} 1680168404Spjd 1681219089Spjdstatic object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = { 1682168404Spjd dump_none, /* unallocated */ 1683168404Spjd dump_zap, /* object directory */ 1684168404Spjd dump_uint64, /* object array */ 1685168404Spjd dump_none, /* packed nvlist */ 1686168404Spjd dump_packed_nvlist, /* packed nvlist size */ 1687168404Spjd dump_none, /* bplist */ 1688168404Spjd dump_none, /* bplist header */ 1689168404Spjd dump_none, /* SPA space map header */ 1690168404Spjd dump_none, /* SPA space map */ 1691168404Spjd dump_none, /* ZIL intent log */ 1692168404Spjd dump_dnode, /* DMU dnode */ 1693168404Spjd dump_dmu_objset, /* DMU objset */ 1694168404Spjd dump_dsl_dir, /* DSL directory */ 1695168404Spjd dump_zap, /* DSL directory child map */ 1696168404Spjd dump_zap, /* DSL dataset snap map */ 1697168404Spjd dump_zap, /* DSL props */ 1698168404Spjd dump_dsl_dataset, /* DSL dataset */ 1699168404Spjd dump_znode, /* ZFS znode */ 1700185029Spjd dump_acl, /* ZFS V0 ACL */ 1701168404Spjd dump_uint8, /* ZFS plain file */ 1702185029Spjd dump_zpldir, /* ZFS directory */ 1703168404Spjd dump_zap, /* ZFS master node */ 1704168404Spjd dump_zap, /* ZFS delete queue */ 1705168404Spjd dump_uint8, /* zvol object */ 1706168404Spjd dump_zap, /* zvol prop */ 1707168404Spjd dump_uint8, /* other uint8[] */ 1708168404Spjd dump_uint64, /* other uint64[] */ 1709168404Spjd dump_zap, /* other ZAP */ 1710168404Spjd dump_zap, /* persistent error log */ 1711168404Spjd dump_uint8, /* SPA history */ 1712248571Smm dump_history_offsets, /* SPA history offsets */ 1713168404Spjd dump_zap, /* Pool properties */ 1714185029Spjd dump_zap, /* DSL permissions */ 1715185029Spjd dump_acl, /* ZFS ACL */ 1716185029Spjd dump_uint8, /* ZFS SYSACL */ 1717185029Spjd dump_none, /* FUID nvlist */ 1718185029Spjd dump_packed_nvlist, /* FUID nvlist size */ 1719185029Spjd dump_zap, /* DSL dataset next clones */ 1720185029Spjd dump_zap, /* DSL scrub queue */ 1721209962Smm dump_zap, /* ZFS user/group used */ 1722209962Smm dump_zap, /* ZFS user/group quota */ 1723219089Spjd dump_zap, /* snapshot refcount tags */ 1724219089Spjd dump_ddt_zap, /* DDT ZAP object */ 1725219089Spjd dump_zap, /* DDT statistics */ 1726219089Spjd dump_znode, /* SA object */ 1727219089Spjd dump_zap, /* SA Master Node */ 1728219089Spjd dump_sa_attrs, /* SA attribute registration */ 1729219089Spjd dump_sa_layouts, /* SA attribute layouts */ 1730219089Spjd dump_zap, /* DSL scrub translations */ 1731219089Spjd dump_none, /* fake dedup BP */ 1732219089Spjd dump_zap, /* deadlist */ 1733219089Spjd dump_none, /* deadlist hdr */ 1734219089Spjd dump_zap, /* dsl clones */ 1735219089Spjd dump_none, /* bpobj subobjs */ 1736219089Spjd dump_unknown, /* Unknown type, must be last */ 1737168404Spjd}; 1738168404Spjd 1739168404Spjdstatic void 1740168404Spjddump_object(objset_t *os, uint64_t object, int verbosity, int *print_header) 1741168404Spjd{ 1742168404Spjd dmu_buf_t *db = NULL; 1743168404Spjd dmu_object_info_t doi; 1744168404Spjd dnode_t *dn; 1745168404Spjd void *bonus = NULL; 1746168404Spjd size_t bsize = 0; 1747219089Spjd char iblk[32], dblk[32], lsize[32], asize[32], fill[32]; 1748219089Spjd char bonus_size[32]; 1749168404Spjd char aux[50]; 1750168404Spjd int error; 1751168404Spjd 1752168404Spjd if (*print_header) { 1753219089Spjd (void) printf("\n%10s %3s %5s %5s %5s %5s %6s %s\n", 1754219089Spjd "Object", "lvl", "iblk", "dblk", "dsize", "lsize", 1755219089Spjd "%full", "type"); 1756168404Spjd *print_header = 0; 1757168404Spjd } 1758168404Spjd 1759168404Spjd if (object == 0) { 1760219089Spjd dn = DMU_META_DNODE(os); 1761168404Spjd } else { 1762168404Spjd error = dmu_bonus_hold(os, object, FTAG, &db); 1763168404Spjd if (error) 1764168404Spjd fatal("dmu_bonus_hold(%llu) failed, errno %u", 1765168404Spjd object, error); 1766168404Spjd bonus = db->db_data; 1767168404Spjd bsize = db->db_size; 1768219089Spjd dn = DB_DNODE((dmu_buf_impl_t *)db); 1769168404Spjd } 1770168404Spjd dmu_object_info_from_dnode(dn, &doi); 1771168404Spjd 1772219089Spjd zdb_nicenum(doi.doi_metadata_block_size, iblk); 1773219089Spjd zdb_nicenum(doi.doi_data_block_size, dblk); 1774219089Spjd zdb_nicenum(doi.doi_max_offset, lsize); 1775219089Spjd zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize); 1776219089Spjd zdb_nicenum(doi.doi_bonus_size, bonus_size); 1777219089Spjd (void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count * 1778219089Spjd doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) / 1779219089Spjd doi.doi_max_offset); 1780168404Spjd 1781168404Spjd aux[0] = '\0'; 1782168404Spjd 1783185029Spjd if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) { 1784168404Spjd (void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)", 1785219089Spjd ZDB_CHECKSUM_NAME(doi.doi_checksum)); 1786185029Spjd } 1787168404Spjd 1788185029Spjd if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) { 1789168404Spjd (void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)", 1790219089Spjd ZDB_COMPRESS_NAME(doi.doi_compress)); 1791185029Spjd } 1792168404Spjd 1793219089Spjd (void) printf("%10lld %3u %5s %5s %5s %5s %6s %s%s\n", 1794219089Spjd (u_longlong_t)object, doi.doi_indirection, iblk, dblk, 1795219089Spjd asize, lsize, fill, ZDB_OT_NAME(doi.doi_type), aux); 1796168404Spjd 1797168404Spjd if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) { 1798219089Spjd (void) printf("%10s %3s %5s %5s %5s %5s %6s %s\n", 1799219089Spjd "", "", "", "", "", bonus_size, "bonus", 1800219089Spjd ZDB_OT_NAME(doi.doi_bonus_type)); 1801168404Spjd } 1802168404Spjd 1803168404Spjd if (verbosity >= 4) { 1804219089Spjd (void) printf("\tdnode flags: %s%s%s\n", 1805209962Smm (dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) ? 1806209962Smm "USED_BYTES " : "", 1807209962Smm (dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED) ? 1808219089Spjd "USERUSED_ACCOUNTED " : "", 1809219089Spjd (dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR) ? 1810219089Spjd "SPILL_BLKPTR" : ""); 1811209962Smm (void) printf("\tdnode maxblkid: %llu\n", 1812209962Smm (longlong_t)dn->dn_phys->dn_maxblkid); 1813209962Smm 1814219089Spjd object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object, 1815219089Spjd bonus, bsize); 1816219089Spjd object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0); 1817168404Spjd *print_header = 1; 1818168404Spjd } 1819168404Spjd 1820168404Spjd if (verbosity >= 5) 1821208047Smm dump_indirect(dn); 1822168404Spjd 1823168404Spjd if (verbosity >= 5) { 1824168404Spjd /* 1825168404Spjd * Report the list of segments that comprise the object. 1826168404Spjd */ 1827168404Spjd uint64_t start = 0; 1828168404Spjd uint64_t end; 1829168404Spjd uint64_t blkfill = 1; 1830168404Spjd int minlvl = 1; 1831168404Spjd 1832168404Spjd if (dn->dn_type == DMU_OT_DNODE) { 1833168404Spjd minlvl = 0; 1834168404Spjd blkfill = DNODES_PER_BLOCK; 1835168404Spjd } 1836168404Spjd 1837168404Spjd for (;;) { 1838219089Spjd char segsize[32]; 1839185029Spjd error = dnode_next_offset(dn, 1840185029Spjd 0, &start, minlvl, blkfill, 0); 1841168404Spjd if (error) 1842168404Spjd break; 1843168404Spjd end = start; 1844185029Spjd error = dnode_next_offset(dn, 1845185029Spjd DNODE_FIND_HOLE, &end, minlvl, blkfill, 0); 1846219089Spjd zdb_nicenum(end - start, segsize); 1847168404Spjd (void) printf("\t\tsegment [%016llx, %016llx)" 1848168404Spjd " size %5s\n", (u_longlong_t)start, 1849168404Spjd (u_longlong_t)end, segsize); 1850168404Spjd if (error) 1851168404Spjd break; 1852168404Spjd start = end; 1853168404Spjd } 1854168404Spjd } 1855168404Spjd 1856168404Spjd if (db != NULL) 1857168404Spjd dmu_buf_rele(db, FTAG); 1858168404Spjd} 1859168404Spjd 1860168404Spjdstatic char *objset_types[DMU_OST_NUMTYPES] = { 1861168404Spjd "NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" }; 1862168404Spjd 1863168404Spjdstatic void 1864168404Spjddump_dir(objset_t *os) 1865168404Spjd{ 1866168404Spjd dmu_objset_stats_t dds; 1867168404Spjd uint64_t object, object_count; 1868168404Spjd uint64_t refdbytes, usedobjs, scratch; 1869219089Spjd char numbuf[32]; 1870209962Smm char blkbuf[BP_SPRINTF_LEN + 20]; 1871168404Spjd char osname[MAXNAMELEN]; 1872168404Spjd char *type = "UNKNOWN"; 1873168404Spjd int verbosity = dump_opt['d']; 1874168404Spjd int print_header = 1; 1875168404Spjd int i, error; 1876168404Spjd 1877248571Smm dsl_pool_config_enter(dmu_objset_pool(os), FTAG); 1878168404Spjd dmu_objset_fast_stat(os, &dds); 1879248571Smm dsl_pool_config_exit(dmu_objset_pool(os), FTAG); 1880168404Spjd 1881168404Spjd if (dds.dds_type < DMU_OST_NUMTYPES) 1882168404Spjd type = objset_types[dds.dds_type]; 1883168404Spjd 1884168404Spjd if (dds.dds_type == DMU_OST_META) { 1885168404Spjd dds.dds_creation_txg = TXG_INITIAL; 1886268649Sdelphij usedobjs = BP_GET_FILL(os->os_rootbp); 1887277585Sdelphij refdbytes = dsl_dir_phys(os->os_spa->spa_dsl_pool->dp_mos_dir)-> 1888277585Sdelphij dd_used_bytes; 1889168404Spjd } else { 1890168404Spjd dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch); 1891168404Spjd } 1892168404Spjd 1893268649Sdelphij ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp)); 1894168404Spjd 1895219089Spjd zdb_nicenum(refdbytes, numbuf); 1896168404Spjd 1897168404Spjd if (verbosity >= 4) { 1898263397Sdelphij (void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp "); 1899263397Sdelphij (void) snprintf_blkptr(blkbuf + strlen(blkbuf), 1900263397Sdelphij sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp); 1901168404Spjd } else { 1902168404Spjd blkbuf[0] = '\0'; 1903168404Spjd } 1904168404Spjd 1905168404Spjd dmu_objset_name(os, osname); 1906168404Spjd 1907168404Spjd (void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, " 1908168404Spjd "%s, %llu objects%s\n", 1909168404Spjd osname, type, (u_longlong_t)dmu_objset_id(os), 1910168404Spjd (u_longlong_t)dds.dds_creation_txg, 1911168404Spjd numbuf, (u_longlong_t)usedobjs, blkbuf); 1912168404Spjd 1913219089Spjd if (zopt_objects != 0) { 1914219089Spjd for (i = 0; i < zopt_objects; i++) 1915219089Spjd dump_object(os, zopt_object[i], verbosity, 1916219089Spjd &print_header); 1917219089Spjd (void) printf("\n"); 1918219089Spjd return; 1919219089Spjd } 1920168404Spjd 1921219089Spjd if (dump_opt['i'] != 0 || verbosity >= 2) 1922219089Spjd dump_intent_log(dmu_objset_zil(os)); 1923219089Spjd 1924168404Spjd if (dmu_objset_ds(os) != NULL) 1925219089Spjd dump_deadlist(&dmu_objset_ds(os)->ds_deadlist); 1926168404Spjd 1927168404Spjd if (verbosity < 2) 1928168404Spjd return; 1929168404Spjd 1930263397Sdelphij if (BP_IS_HOLE(os->os_rootbp)) 1931185029Spjd return; 1932185029Spjd 1933168404Spjd dump_object(os, 0, verbosity, &print_header); 1934209962Smm object_count = 0; 1935219089Spjd if (DMU_USERUSED_DNODE(os) != NULL && 1936219089Spjd DMU_USERUSED_DNODE(os)->dn_type != 0) { 1937209962Smm dump_object(os, DMU_USERUSED_OBJECT, verbosity, &print_header); 1938209962Smm dump_object(os, DMU_GROUPUSED_OBJECT, verbosity, &print_header); 1939209962Smm } 1940168404Spjd 1941168404Spjd object = 0; 1942168404Spjd while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) { 1943168404Spjd dump_object(os, object, verbosity, &print_header); 1944168404Spjd object_count++; 1945168404Spjd } 1946168404Spjd 1947168404Spjd ASSERT3U(object_count, ==, usedobjs); 1948168404Spjd 1949168404Spjd (void) printf("\n"); 1950168404Spjd 1951209962Smm if (error != ESRCH) { 1952209962Smm (void) fprintf(stderr, "dmu_object_next() = %d\n", error); 1953209962Smm abort(); 1954209962Smm } 1955168404Spjd} 1956168404Spjd 1957168404Spjdstatic void 1958219089Spjddump_uberblock(uberblock_t *ub, const char *header, const char *footer) 1959168404Spjd{ 1960168404Spjd time_t timestamp = ub->ub_timestamp; 1961168404Spjd 1962219089Spjd (void) printf(header ? header : ""); 1963168404Spjd (void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic); 1964168404Spjd (void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version); 1965168404Spjd (void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg); 1966168404Spjd (void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum); 1967168404Spjd (void) printf("\ttimestamp = %llu UTC = %s", 1968168404Spjd (u_longlong_t)ub->ub_timestamp, asctime(localtime(×tamp))); 1969168404Spjd if (dump_opt['u'] >= 3) { 1970168404Spjd char blkbuf[BP_SPRINTF_LEN]; 1971263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), &ub->ub_rootbp); 1972168404Spjd (void) printf("\trootbp = %s\n", blkbuf); 1973168404Spjd } 1974219089Spjd (void) printf(footer ? footer : ""); 1975168404Spjd} 1976168404Spjd 1977168404Spjdstatic void 1978219089Spjddump_config(spa_t *spa) 1979168404Spjd{ 1980219089Spjd dmu_buf_t *db; 1981219089Spjd size_t nvsize = 0; 1982219089Spjd int error = 0; 1983168404Spjd 1984219089Spjd 1985219089Spjd error = dmu_bonus_hold(spa->spa_meta_objset, 1986219089Spjd spa->spa_config_object, FTAG, &db); 1987219089Spjd 1988219089Spjd if (error == 0) { 1989219089Spjd nvsize = *(uint64_t *)db->db_data; 1990219089Spjd dmu_buf_rele(db, FTAG); 1991219089Spjd 1992219089Spjd (void) printf("\nMOS Configuration:\n"); 1993219089Spjd dump_packed_nvlist(spa->spa_meta_objset, 1994219089Spjd spa->spa_config_object, (void *)&nvsize, 1); 1995219089Spjd } else { 1996219089Spjd (void) fprintf(stderr, "dmu_bonus_hold(%llu) failed, errno %d", 1997219089Spjd (u_longlong_t)spa->spa_config_object, error); 1998168404Spjd } 1999168404Spjd} 2000168404Spjd 2001168404Spjdstatic void 2002185029Spjddump_cachefile(const char *cachefile) 2003185029Spjd{ 2004185029Spjd int fd; 2005185029Spjd struct stat64 statbuf; 2006185029Spjd char *buf; 2007185029Spjd nvlist_t *config; 2008185029Spjd 2009185029Spjd if ((fd = open64(cachefile, O_RDONLY)) < 0) { 2010185029Spjd (void) printf("cannot open '%s': %s\n", cachefile, 2011185029Spjd strerror(errno)); 2012185029Spjd exit(1); 2013185029Spjd } 2014185029Spjd 2015185029Spjd if (fstat64(fd, &statbuf) != 0) { 2016185029Spjd (void) printf("failed to stat '%s': %s\n", cachefile, 2017185029Spjd strerror(errno)); 2018185029Spjd exit(1); 2019185029Spjd } 2020185029Spjd 2021185029Spjd if ((buf = malloc(statbuf.st_size)) == NULL) { 2022185029Spjd (void) fprintf(stderr, "failed to allocate %llu bytes\n", 2023185029Spjd (u_longlong_t)statbuf.st_size); 2024185029Spjd exit(1); 2025185029Spjd } 2026185029Spjd 2027185029Spjd if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { 2028185029Spjd (void) fprintf(stderr, "failed to read %llu bytes\n", 2029185029Spjd (u_longlong_t)statbuf.st_size); 2030185029Spjd exit(1); 2031185029Spjd } 2032185029Spjd 2033185029Spjd (void) close(fd); 2034185029Spjd 2035185029Spjd if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) { 2036185029Spjd (void) fprintf(stderr, "failed to unpack nvlist\n"); 2037185029Spjd exit(1); 2038185029Spjd } 2039185029Spjd 2040185029Spjd free(buf); 2041185029Spjd 2042185029Spjd dump_nvlist(config, 0); 2043185029Spjd 2044185029Spjd nvlist_free(config); 2045185029Spjd} 2046185029Spjd 2047219089Spjd#define ZDB_MAX_UB_HEADER_SIZE 32 2048219089Spjd 2049185029Spjdstatic void 2050219089Spjddump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift) 2051219089Spjd{ 2052219089Spjd vdev_t vd; 2053219089Spjd vdev_t *vdp = &vd; 2054219089Spjd char header[ZDB_MAX_UB_HEADER_SIZE]; 2055219089Spjd 2056219089Spjd vd.vdev_ashift = ashift; 2057219089Spjd vdp->vdev_top = vdp; 2058219089Spjd 2059219089Spjd for (int i = 0; i < VDEV_UBERBLOCK_COUNT(vdp); i++) { 2060219089Spjd uint64_t uoff = VDEV_UBERBLOCK_OFFSET(vdp, i); 2061219089Spjd uberblock_t *ub = (void *)((char *)lbl + uoff); 2062219089Spjd 2063219089Spjd if (uberblock_verify(ub)) 2064219089Spjd continue; 2065219089Spjd (void) snprintf(header, ZDB_MAX_UB_HEADER_SIZE, 2066219089Spjd "Uberblock[%d]\n", i); 2067219089Spjd dump_uberblock(ub, header, ""); 2068219089Spjd } 2069219089Spjd} 2070219089Spjd 2071219089Spjdstatic void 2072168404Spjddump_label(const char *dev) 2073168404Spjd{ 2074168404Spjd int fd; 2075168404Spjd vdev_label_t label; 2076219089Spjd char *path, *buf = label.vl_vdev_phys.vp_nvlist; 2077168404Spjd size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist); 2078168404Spjd struct stat64 statbuf; 2079219089Spjd uint64_t psize, ashift; 2080219089Spjd int len = strlen(dev) + 1; 2081168404Spjd 2082219089Spjd if (strncmp(dev, "/dev/dsk/", 9) == 0) { 2083219089Spjd len++; 2084219089Spjd path = malloc(len); 2085219089Spjd (void) snprintf(path, len, "%s%s", "/dev/rdsk/", dev + 9); 2086219089Spjd } else { 2087219089Spjd path = strdup(dev); 2088219089Spjd } 2089219089Spjd 2090219089Spjd if ((fd = open64(path, O_RDONLY)) < 0) { 2091219089Spjd (void) printf("cannot open '%s': %s\n", path, strerror(errno)); 2092219089Spjd free(path); 2093168404Spjd exit(1); 2094168404Spjd } 2095168404Spjd 2096168404Spjd if (fstat64(fd, &statbuf) != 0) { 2097219089Spjd (void) printf("failed to stat '%s': %s\n", path, 2098168404Spjd strerror(errno)); 2099219089Spjd free(path); 2100219089Spjd (void) close(fd); 2101168404Spjd exit(1); 2102168404Spjd } 2103168404Spjd 2104219089Spjd if (S_ISBLK(statbuf.st_mode)) { 2105219089Spjd (void) printf("cannot use '%s': character device required\n", 2106219089Spjd path); 2107219089Spjd free(path); 2108219089Spjd (void) close(fd); 2109219089Spjd exit(1); 2110196928Spjd } 2111196928Spjd 2112185029Spjd psize = statbuf.st_size; 2113168404Spjd psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t)); 2114168404Spjd 2115219089Spjd for (int l = 0; l < VDEV_LABELS; l++) { 2116168404Spjd nvlist_t *config = NULL; 2117168404Spjd 2118168404Spjd (void) printf("--------------------------------------------\n"); 2119168404Spjd (void) printf("LABEL %d\n", l); 2120168404Spjd (void) printf("--------------------------------------------\n"); 2121168404Spjd 2122168404Spjd if (pread64(fd, &label, sizeof (label), 2123168404Spjd vdev_label_offset(psize, l, 0)) != sizeof (label)) { 2124168404Spjd (void) printf("failed to read label %d\n", l); 2125168404Spjd continue; 2126168404Spjd } 2127168404Spjd 2128168404Spjd if (nvlist_unpack(buf, buflen, &config, 0) != 0) { 2129168404Spjd (void) printf("failed to unpack label %d\n", l); 2130219089Spjd ashift = SPA_MINBLOCKSHIFT; 2131219089Spjd } else { 2132219089Spjd nvlist_t *vdev_tree = NULL; 2133219089Spjd 2134219089Spjd dump_nvlist(config, 4); 2135219089Spjd if ((nvlist_lookup_nvlist(config, 2136219089Spjd ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) || 2137219089Spjd (nvlist_lookup_uint64(vdev_tree, 2138219089Spjd ZPOOL_CONFIG_ASHIFT, &ashift) != 0)) 2139219089Spjd ashift = SPA_MINBLOCKSHIFT; 2140219089Spjd nvlist_free(config); 2141168404Spjd } 2142219089Spjd if (dump_opt['u']) 2143219089Spjd dump_label_uberblocks(&label, ashift); 2144168404Spjd } 2145219089Spjd 2146219089Spjd free(path); 2147219089Spjd (void) close(fd); 2148168404Spjd} 2149168404Spjd 2150276081Sdelphijstatic uint64_t num_large_blocks; 2151276081Sdelphij 2152168404Spjd/*ARGSUSED*/ 2153168404Spjdstatic int 2154219089Spjddump_one_dir(const char *dsname, void *arg) 2155168404Spjd{ 2156168404Spjd int error; 2157168404Spjd objset_t *os; 2158168404Spjd 2159219089Spjd error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os); 2160168404Spjd if (error) { 2161219089Spjd (void) printf("Could not open %s, error %d\n", dsname, error); 2162168404Spjd return (0); 2163168404Spjd } 2164276081Sdelphij if (dmu_objset_ds(os)->ds_large_blocks) 2165276081Sdelphij num_large_blocks++; 2166168404Spjd dump_dir(os); 2167219089Spjd dmu_objset_disown(os, FTAG); 2168185029Spjd fuid_table_destroy(); 2169219089Spjd sa_loaded = B_FALSE; 2170168404Spjd return (0); 2171168404Spjd} 2172168404Spjd 2173168404Spjd/* 2174219089Spjd * Block statistics. 2175168404Spjd */ 2176276081Sdelphij#define PSIZE_HISTO_SIZE (SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 2) 2177168404Spjdtypedef struct zdb_blkstats { 2178249207Smm uint64_t zb_asize; 2179249207Smm uint64_t zb_lsize; 2180249207Smm uint64_t zb_psize; 2181249207Smm uint64_t zb_count; 2182268645Sdelphij uint64_t zb_gangs; 2183268645Sdelphij uint64_t zb_ditto_samevdev; 2184249207Smm uint64_t zb_psize_histogram[PSIZE_HISTO_SIZE]; 2185168404Spjd} zdb_blkstats_t; 2186168404Spjd 2187219089Spjd/* 2188219089Spjd * Extended object types to report deferred frees and dedup auto-ditto blocks. 2189219089Spjd */ 2190219089Spjd#define ZDB_OT_DEFERRED (DMU_OT_NUMTYPES + 0) 2191219089Spjd#define ZDB_OT_DITTO (DMU_OT_NUMTYPES + 1) 2192236884Smm#define ZDB_OT_OTHER (DMU_OT_NUMTYPES + 2) 2193236884Smm#define ZDB_OT_TOTAL (DMU_OT_NUMTYPES + 3) 2194168404Spjd 2195219089Spjdstatic char *zdb_ot_extname[] = { 2196219089Spjd "deferred free", 2197219089Spjd "dedup ditto", 2198236884Smm "other", 2199219089Spjd "Total", 2200219089Spjd}; 2201219089Spjd 2202208047Smm#define ZB_TOTAL DN_MAX_LEVELS 2203168404Spjd 2204168404Spjdtypedef struct zdb_cb { 2205219089Spjd zdb_blkstats_t zcb_type[ZB_TOTAL + 1][ZDB_OT_TOTAL + 1]; 2206219089Spjd uint64_t zcb_dedup_asize; 2207219089Spjd uint64_t zcb_dedup_blocks; 2208268649Sdelphij uint64_t zcb_embedded_blocks[NUM_BP_EMBEDDED_TYPES]; 2209268649Sdelphij uint64_t zcb_embedded_histogram[NUM_BP_EMBEDDED_TYPES] 2210268649Sdelphij [BPE_PAYLOAD_SIZE]; 2211249207Smm uint64_t zcb_start; 2212249207Smm uint64_t zcb_lastprint; 2213249207Smm uint64_t zcb_totalasize; 2214168404Spjd uint64_t zcb_errors[256]; 2215168404Spjd int zcb_readfails; 2216168404Spjd int zcb_haderrors; 2217219089Spjd spa_t *zcb_spa; 2218168404Spjd} zdb_cb_t; 2219168404Spjd 2220168404Spjdstatic void 2221219089Spjdzdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp, 2222219089Spjd dmu_object_type_t type) 2223168404Spjd{ 2224219089Spjd uint64_t refcnt = 0; 2225219089Spjd 2226219089Spjd ASSERT(type < ZDB_OT_TOTAL); 2227219089Spjd 2228219089Spjd if (zilog && zil_bp_tree_add(zilog, bp) != 0) 2229219089Spjd return; 2230219089Spjd 2231185029Spjd for (int i = 0; i < 4; i++) { 2232168404Spjd int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL; 2233219089Spjd int t = (i & 1) ? type : ZDB_OT_TOTAL; 2234268645Sdelphij int equal; 2235168404Spjd zdb_blkstats_t *zb = &zcb->zcb_type[l][t]; 2236168404Spjd 2237168404Spjd zb->zb_asize += BP_GET_ASIZE(bp); 2238168404Spjd zb->zb_lsize += BP_GET_LSIZE(bp); 2239168404Spjd zb->zb_psize += BP_GET_PSIZE(bp); 2240168404Spjd zb->zb_count++; 2241268645Sdelphij 2242276081Sdelphij /* 2243276081Sdelphij * The histogram is only big enough to record blocks up to 2244276081Sdelphij * SPA_OLD_MAXBLOCKSIZE; larger blocks go into the last, 2245276081Sdelphij * "other", bucket. 2246276081Sdelphij */ 2247276081Sdelphij int idx = BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT; 2248276081Sdelphij idx = MIN(idx, SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 1); 2249276081Sdelphij zb->zb_psize_histogram[idx]++; 2250276081Sdelphij 2251268645Sdelphij zb->zb_gangs += BP_COUNT_GANG(bp); 2252268645Sdelphij 2253268645Sdelphij switch (BP_GET_NDVAS(bp)) { 2254268645Sdelphij case 2: 2255268645Sdelphij if (DVA_GET_VDEV(&bp->blk_dva[0]) == 2256268645Sdelphij DVA_GET_VDEV(&bp->blk_dva[1])) 2257268645Sdelphij zb->zb_ditto_samevdev++; 2258268645Sdelphij break; 2259268645Sdelphij case 3: 2260268645Sdelphij equal = (DVA_GET_VDEV(&bp->blk_dva[0]) == 2261268645Sdelphij DVA_GET_VDEV(&bp->blk_dva[1])) + 2262268645Sdelphij (DVA_GET_VDEV(&bp->blk_dva[0]) == 2263268645Sdelphij DVA_GET_VDEV(&bp->blk_dva[2])) + 2264268645Sdelphij (DVA_GET_VDEV(&bp->blk_dva[1]) == 2265268645Sdelphij DVA_GET_VDEV(&bp->blk_dva[2])); 2266268645Sdelphij if (equal != 0) 2267268645Sdelphij zb->zb_ditto_samevdev++; 2268268645Sdelphij break; 2269268645Sdelphij } 2270268645Sdelphij 2271168404Spjd } 2272168404Spjd 2273268649Sdelphij if (BP_IS_EMBEDDED(bp)) { 2274268649Sdelphij zcb->zcb_embedded_blocks[BPE_GET_ETYPE(bp)]++; 2275268649Sdelphij zcb->zcb_embedded_histogram[BPE_GET_ETYPE(bp)] 2276268649Sdelphij [BPE_GET_PSIZE(bp)]++; 2277268649Sdelphij return; 2278268649Sdelphij } 2279268649Sdelphij 2280219089Spjd if (dump_opt['L']) 2281219089Spjd return; 2282168404Spjd 2283219089Spjd if (BP_GET_DEDUP(bp)) { 2284219089Spjd ddt_t *ddt; 2285219089Spjd ddt_entry_t *dde; 2286168404Spjd 2287219089Spjd ddt = ddt_select(zcb->zcb_spa, bp); 2288219089Spjd ddt_enter(ddt); 2289219089Spjd dde = ddt_lookup(ddt, bp, B_FALSE); 2290168404Spjd 2291219089Spjd if (dde == NULL) { 2292219089Spjd refcnt = 0; 2293219089Spjd } else { 2294219089Spjd ddt_phys_t *ddp = ddt_phys_select(dde, bp); 2295219089Spjd ddt_phys_decref(ddp); 2296219089Spjd refcnt = ddp->ddp_refcnt; 2297219089Spjd if (ddt_phys_total_refcnt(dde) == 0) 2298219089Spjd ddt_remove(ddt, dde); 2299185029Spjd } 2300219089Spjd ddt_exit(ddt); 2301185029Spjd } 2302168404Spjd 2303219089Spjd VERIFY3U(zio_wait(zio_claim(NULL, zcb->zcb_spa, 2304219089Spjd refcnt ? 0 : spa_first_txg(zcb->zcb_spa), 2305219089Spjd bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0); 2306168404Spjd} 2307168404Spjd 2308263393Sdelphij/* ARGSUSED */ 2309263393Sdelphijstatic void 2310263393Sdelphijzdb_blkptr_done(zio_t *zio) 2311263393Sdelphij{ 2312263393Sdelphij spa_t *spa = zio->io_spa; 2313263393Sdelphij blkptr_t *bp = zio->io_bp; 2314263393Sdelphij int ioerr = zio->io_error; 2315263393Sdelphij zdb_cb_t *zcb = zio->io_private; 2316268657Sdelphij zbookmark_phys_t *zb = &zio->io_bookmark; 2317263393Sdelphij 2318263393Sdelphij zio_data_buf_free(zio->io_data, zio->io_size); 2319263393Sdelphij 2320263393Sdelphij mutex_enter(&spa->spa_scrub_lock); 2321263393Sdelphij spa->spa_scrub_inflight--; 2322263393Sdelphij cv_broadcast(&spa->spa_scrub_io_cv); 2323263393Sdelphij 2324263393Sdelphij if (ioerr && !(zio->io_flags & ZIO_FLAG_SPECULATIVE)) { 2325263393Sdelphij char blkbuf[BP_SPRINTF_LEN]; 2326263393Sdelphij 2327263393Sdelphij zcb->zcb_haderrors = 1; 2328263393Sdelphij zcb->zcb_errors[ioerr]++; 2329263393Sdelphij 2330263393Sdelphij if (dump_opt['b'] >= 2) 2331263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); 2332263393Sdelphij else 2333263393Sdelphij blkbuf[0] = '\0'; 2334263393Sdelphij 2335263393Sdelphij (void) printf("zdb_blkptr_cb: " 2336263393Sdelphij "Got error %d reading " 2337263393Sdelphij "<%llu, %llu, %lld, %llx> %s -- skipping\n", 2338263393Sdelphij ioerr, 2339263393Sdelphij (u_longlong_t)zb->zb_objset, 2340263393Sdelphij (u_longlong_t)zb->zb_object, 2341263393Sdelphij (u_longlong_t)zb->zb_level, 2342263393Sdelphij (u_longlong_t)zb->zb_blkid, 2343263393Sdelphij blkbuf); 2344263393Sdelphij } 2345263393Sdelphij mutex_exit(&spa->spa_scrub_lock); 2346263393Sdelphij} 2347263393Sdelphij 2348263393Sdelphij/* ARGSUSED */ 2349168404Spjdstatic int 2350246666Smmzdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, 2351268657Sdelphij const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg) 2352168404Spjd{ 2353168404Spjd zdb_cb_t *zcb = arg; 2354209962Smm dmu_object_type_t type; 2355219089Spjd boolean_t is_metadata; 2356168404Spjd 2357263397Sdelphij if (dump_opt['b'] >= 5 && bp->blk_birth > 0) { 2358263397Sdelphij char blkbuf[BP_SPRINTF_LEN]; 2359263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); 2360263397Sdelphij (void) printf("objset %llu object %llu " 2361263397Sdelphij "level %lld offset 0x%llx %s\n", 2362263397Sdelphij (u_longlong_t)zb->zb_objset, 2363263397Sdelphij (u_longlong_t)zb->zb_object, 2364263397Sdelphij (longlong_t)zb->zb_level, 2365263397Sdelphij (u_longlong_t)blkid2offset(dnp, bp, zb), 2366263397Sdelphij blkbuf); 2367263397Sdelphij } 2368263397Sdelphij 2369263397Sdelphij if (BP_IS_HOLE(bp)) 2370208047Smm return (0); 2371185029Spjd 2372209962Smm type = BP_GET_TYPE(bp); 2373185029Spjd 2374236884Smm zdb_count_block(zcb, zilog, bp, 2375236884Smm (type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type); 2376209962Smm 2377236884Smm is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type)); 2378209962Smm 2379268649Sdelphij if (!BP_IS_EMBEDDED(bp) && 2380268649Sdelphij (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata))) { 2381219089Spjd size_t size = BP_GET_PSIZE(bp); 2382263393Sdelphij void *data = zio_data_buf_alloc(size); 2383219089Spjd int flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB | ZIO_FLAG_RAW; 2384208047Smm 2385219089Spjd /* If it's an intent log block, failure is expected. */ 2386219089Spjd if (zb->zb_level == ZB_ZIL_LEVEL) 2387219089Spjd flags |= ZIO_FLAG_SPECULATIVE; 2388219089Spjd 2389263393Sdelphij mutex_enter(&spa->spa_scrub_lock); 2390263393Sdelphij while (spa->spa_scrub_inflight > max_inflight) 2391263393Sdelphij cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock); 2392263393Sdelphij spa->spa_scrub_inflight++; 2393263393Sdelphij mutex_exit(&spa->spa_scrub_lock); 2394219089Spjd 2395263393Sdelphij zio_nowait(zio_read(NULL, spa, bp, data, size, 2396263393Sdelphij zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb)); 2397168404Spjd } 2398168404Spjd 2399168404Spjd zcb->zcb_readfails = 0; 2400168404Spjd 2401275488Sdelphij /* only call gethrtime() every 100 blocks */ 2402275488Sdelphij static int iters; 2403275488Sdelphij if (++iters > 100) 2404275488Sdelphij iters = 0; 2405275488Sdelphij else 2406275488Sdelphij return (0); 2407275488Sdelphij 2408275488Sdelphij if (dump_opt['b'] < 5 && gethrtime() > zcb->zcb_lastprint + NANOSEC) { 2409249207Smm uint64_t now = gethrtime(); 2410249207Smm char buf[10]; 2411249207Smm uint64_t bytes = zcb->zcb_type[ZB_TOTAL][ZDB_OT_TOTAL].zb_asize; 2412249207Smm int kb_per_sec = 2413249207Smm 1 + bytes / (1 + ((now - zcb->zcb_start) / 1000 / 1000)); 2414249207Smm int sec_remaining = 2415249207Smm (zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec; 2416249207Smm 2417249207Smm zfs_nicenum(bytes, buf, sizeof (buf)); 2418249207Smm (void) fprintf(stderr, 2419249207Smm "\r%5s completed (%4dMB/s) " 2420249207Smm "estimated time remaining: %uhr %02umin %02usec ", 2421249207Smm buf, kb_per_sec / 1024, 2422249207Smm sec_remaining / 60 / 60, 2423249207Smm sec_remaining / 60 % 60, 2424249207Smm sec_remaining % 60); 2425249207Smm 2426249207Smm zcb->zcb_lastprint = now; 2427249207Smm } 2428249207Smm 2429168404Spjd return (0); 2430168404Spjd} 2431168404Spjd 2432219089Spjdstatic void 2433262093Savgzdb_leak(void *arg, uint64_t start, uint64_t size) 2434219089Spjd{ 2435262093Savg vdev_t *vd = arg; 2436219089Spjd 2437219089Spjd (void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n", 2438219089Spjd (u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size); 2439219089Spjd} 2440219089Spjd 2441262093Savgstatic metaslab_ops_t zdb_metaslab_ops = { 2442269773Sdelphij NULL /* alloc */ 2443219089Spjd}; 2444219089Spjd 2445219089Spjdstatic void 2446219089Spjdzdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb) 2447219089Spjd{ 2448219089Spjd ddt_bookmark_t ddb = { 0 }; 2449219089Spjd ddt_entry_t dde; 2450219089Spjd int error; 2451219089Spjd 2452219089Spjd while ((error = ddt_walk(spa, &ddb, &dde)) == 0) { 2453219089Spjd blkptr_t blk; 2454219089Spjd ddt_phys_t *ddp = dde.dde_phys; 2455219089Spjd 2456219089Spjd if (ddb.ddb_class == DDT_CLASS_UNIQUE) 2457219089Spjd return; 2458219089Spjd 2459219089Spjd ASSERT(ddt_phys_total_refcnt(&dde) > 1); 2460219089Spjd 2461219089Spjd for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) { 2462219089Spjd if (ddp->ddp_phys_birth == 0) 2463219089Spjd continue; 2464219089Spjd ddt_bp_create(ddb.ddb_checksum, 2465219089Spjd &dde.dde_key, ddp, &blk); 2466219089Spjd if (p == DDT_PHYS_DITTO) { 2467219089Spjd zdb_count_block(zcb, NULL, &blk, ZDB_OT_DITTO); 2468219089Spjd } else { 2469219089Spjd zcb->zcb_dedup_asize += 2470219089Spjd BP_GET_ASIZE(&blk) * (ddp->ddp_refcnt - 1); 2471219089Spjd zcb->zcb_dedup_blocks++; 2472219089Spjd } 2473219089Spjd } 2474219089Spjd if (!dump_opt['L']) { 2475219089Spjd ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum]; 2476219089Spjd ddt_enter(ddt); 2477219089Spjd VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL); 2478219089Spjd ddt_exit(ddt); 2479219089Spjd } 2480219089Spjd } 2481219089Spjd 2482219089Spjd ASSERT(error == ENOENT); 2483219089Spjd} 2484219089Spjd 2485219089Spjdstatic void 2486219089Spjdzdb_leak_init(spa_t *spa, zdb_cb_t *zcb) 2487219089Spjd{ 2488219089Spjd zcb->zcb_spa = spa; 2489219089Spjd 2490219089Spjd if (!dump_opt['L']) { 2491219089Spjd vdev_t *rvd = spa->spa_root_vdev; 2492273508Sdelphij for (uint64_t c = 0; c < rvd->vdev_children; c++) { 2493219089Spjd vdev_t *vd = rvd->vdev_child[c]; 2494273508Sdelphij for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { 2495219089Spjd metaslab_t *msp = vd->vdev_ms[m]; 2496219089Spjd mutex_enter(&msp->ms_lock); 2497262093Savg metaslab_unload(msp); 2498262093Savg 2499262093Savg /* 2500262093Savg * For leak detection, we overload the metaslab 2501262093Savg * ms_tree to contain allocated segments 2502262093Savg * instead of free segments. As a result, 2503262093Savg * we can't use the normal metaslab_load/unload 2504262093Savg * interfaces. 2505262093Savg */ 2506262093Savg if (msp->ms_sm != NULL) { 2507273508Sdelphij (void) fprintf(stderr, 2508273508Sdelphij "\rloading space map for " 2509273508Sdelphij "vdev %llu of %llu, " 2510273508Sdelphij "metaslab %llu of %llu ...", 2511273508Sdelphij (longlong_t)c, 2512273508Sdelphij (longlong_t)rvd->vdev_children, 2513273508Sdelphij (longlong_t)m, 2514273508Sdelphij (longlong_t)vd->vdev_ms_count); 2515273508Sdelphij 2516262093Savg msp->ms_ops = &zdb_metaslab_ops; 2517275488Sdelphij 2518275488Sdelphij /* 2519275488Sdelphij * We don't want to spend the CPU 2520275488Sdelphij * manipulating the size-ordered 2521275488Sdelphij * tree, so clear the range_tree 2522275488Sdelphij * ops. 2523275488Sdelphij */ 2524275488Sdelphij msp->ms_tree->rt_ops = NULL; 2525262093Savg VERIFY0(space_map_load(msp->ms_sm, 2526262093Savg msp->ms_tree, SM_ALLOC)); 2527262093Savg msp->ms_loaded = B_TRUE; 2528262093Savg } 2529219089Spjd mutex_exit(&msp->ms_lock); 2530219089Spjd } 2531219089Spjd } 2532273508Sdelphij (void) fprintf(stderr, "\n"); 2533219089Spjd } 2534219089Spjd 2535219089Spjd spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); 2536219089Spjd 2537219089Spjd zdb_ddt_leak_init(spa, zcb); 2538219089Spjd 2539219089Spjd spa_config_exit(spa, SCL_CONFIG, FTAG); 2540219089Spjd} 2541219089Spjd 2542219089Spjdstatic void 2543219089Spjdzdb_leak_fini(spa_t *spa) 2544219089Spjd{ 2545219089Spjd if (!dump_opt['L']) { 2546219089Spjd vdev_t *rvd = spa->spa_root_vdev; 2547219089Spjd for (int c = 0; c < rvd->vdev_children; c++) { 2548219089Spjd vdev_t *vd = rvd->vdev_child[c]; 2549219089Spjd for (int m = 0; m < vd->vdev_ms_count; m++) { 2550219089Spjd metaslab_t *msp = vd->vdev_ms[m]; 2551219089Spjd mutex_enter(&msp->ms_lock); 2552262093Savg 2553262093Savg /* 2554262093Savg * The ms_tree has been overloaded to 2555262093Savg * contain allocated segments. Now that we 2556262093Savg * finished traversing all blocks, any 2557262093Savg * block that remains in the ms_tree 2558262093Savg * represents an allocated block that we 2559262093Savg * did not claim during the traversal. 2560262093Savg * Claimed blocks would have been removed 2561262093Savg * from the ms_tree. 2562262093Savg */ 2563262093Savg range_tree_vacate(msp->ms_tree, zdb_leak, vd); 2564262093Savg msp->ms_loaded = B_FALSE; 2565262093Savg 2566219089Spjd mutex_exit(&msp->ms_lock); 2567219089Spjd } 2568219089Spjd } 2569219089Spjd } 2570219089Spjd} 2571219089Spjd 2572219089Spjd/* ARGSUSED */ 2573168404Spjdstatic int 2574219089Spjdcount_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx) 2575219089Spjd{ 2576219089Spjd zdb_cb_t *zcb = arg; 2577219089Spjd 2578249207Smm if (dump_opt['b'] >= 5) { 2579219089Spjd char blkbuf[BP_SPRINTF_LEN]; 2580263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); 2581219089Spjd (void) printf("[%s] %s\n", 2582219089Spjd "deferred free", blkbuf); 2583219089Spjd } 2584219089Spjd zdb_count_block(zcb, NULL, bp, ZDB_OT_DEFERRED); 2585219089Spjd return (0); 2586219089Spjd} 2587219089Spjd 2588219089Spjdstatic int 2589168404Spjddump_block_stats(spa_t *spa) 2590168404Spjd{ 2591168404Spjd zdb_cb_t zcb = { 0 }; 2592168404Spjd zdb_blkstats_t *zb, *tzb; 2593219089Spjd uint64_t norm_alloc, norm_space, total_alloc, total_found; 2594219089Spjd int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD; 2595268649Sdelphij boolean_t leaks = B_FALSE; 2596168404Spjd 2597249207Smm (void) printf("\nTraversing all blocks %s%s%s%s%s...\n\n", 2598219089Spjd (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "", 2599219089Spjd (dump_opt['c'] == 1) ? "metadata " : "", 2600219089Spjd dump_opt['c'] ? "checksums " : "", 2601219089Spjd (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "", 2602219089Spjd !dump_opt['L'] ? "nothing leaked " : ""); 2603168404Spjd 2604168404Spjd /* 2605185029Spjd * Load all space maps as SM_ALLOC maps, then traverse the pool 2606185029Spjd * claiming each block we discover. If the pool is perfectly 2607185029Spjd * consistent, the space maps will be empty when we're done. 2608185029Spjd * Anything left over is a leak; any block we can't claim (because 2609185029Spjd * it's not part of any space map) is a double allocation, 2610185029Spjd * reference to a freed block, or an unclaimed log block. 2611168404Spjd */ 2612219089Spjd zdb_leak_init(spa, &zcb); 2613168404Spjd 2614168404Spjd /* 2615168404Spjd * If there's a deferred-free bplist, process that first. 2616168404Spjd */ 2617219089Spjd (void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj, 2618219089Spjd count_block_cb, &zcb, NULL); 2619226616Spjd if (spa_version(spa) >= SPA_VERSION_DEADLISTS) { 2620226616Spjd (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj, 2621226616Spjd count_block_cb, &zcb, NULL); 2622226616Spjd } 2623263390Sdelphij if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) { 2624236884Smm VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset, 2625236884Smm spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb, 2626236884Smm &zcb, NULL)); 2627236884Smm } 2628168404Spjd 2629219089Spjd if (dump_opt['c'] > 1) 2630219089Spjd flags |= TRAVERSE_PREFETCH_DATA; 2631168404Spjd 2632249207Smm zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa)); 2633249207Smm zcb.zcb_start = zcb.zcb_lastprint = gethrtime(); 2634219089Spjd zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb); 2635168404Spjd 2636263393Sdelphij /* 2637263393Sdelphij * If we've traversed the data blocks then we need to wait for those 2638263393Sdelphij * I/Os to complete. We leverage "The Godfather" zio to wait on 2639263393Sdelphij * all async I/Os to complete. 2640263393Sdelphij */ 2641263393Sdelphij if (dump_opt['c']) { 2642273348Sdelphij for (int i = 0; i < max_ncpus; i++) { 2643273348Sdelphij (void) zio_wait(spa->spa_async_zio_root[i]); 2644273348Sdelphij spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL, 2645273348Sdelphij ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE | 2646273348Sdelphij ZIO_FLAG_GODFATHER); 2647273348Sdelphij } 2648263393Sdelphij } 2649263393Sdelphij 2650219089Spjd if (zcb.zcb_haderrors) { 2651168404Spjd (void) printf("\nError counts:\n\n"); 2652168404Spjd (void) printf("\t%5s %s\n", "errno", "count"); 2653219089Spjd for (int e = 0; e < 256; e++) { 2654168404Spjd if (zcb.zcb_errors[e] != 0) { 2655168404Spjd (void) printf("\t%5d %llu\n", 2656168404Spjd e, (u_longlong_t)zcb.zcb_errors[e]); 2657168404Spjd } 2658168404Spjd } 2659168404Spjd } 2660168404Spjd 2661168404Spjd /* 2662168404Spjd * Report any leaked segments. 2663168404Spjd */ 2664219089Spjd zdb_leak_fini(spa); 2665168404Spjd 2666219089Spjd tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL]; 2667185029Spjd 2668219089Spjd norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa)); 2669219089Spjd norm_space = metaslab_class_get_space(spa_normal_class(spa)); 2670168404Spjd 2671219089Spjd total_alloc = norm_alloc + metaslab_class_get_alloc(spa_log_class(spa)); 2672219089Spjd total_found = tzb->zb_asize - zcb.zcb_dedup_asize; 2673185029Spjd 2674219089Spjd if (total_found == total_alloc) { 2675209962Smm if (!dump_opt['L']) 2676209962Smm (void) printf("\n\tNo leaks (block sum matches space" 2677209962Smm " maps exactly)\n"); 2678168404Spjd } else { 2679168404Spjd (void) printf("block traversal size %llu != alloc %llu " 2680209962Smm "(%s %lld)\n", 2681219089Spjd (u_longlong_t)total_found, 2682219089Spjd (u_longlong_t)total_alloc, 2683209962Smm (dump_opt['L']) ? "unreachable" : "leaked", 2684219089Spjd (longlong_t)(total_alloc - total_found)); 2685268649Sdelphij leaks = B_TRUE; 2686168404Spjd } 2687168404Spjd 2688168404Spjd if (tzb->zb_count == 0) 2689168404Spjd return (2); 2690168404Spjd 2691168404Spjd (void) printf("\n"); 2692168404Spjd (void) printf("\tbp count: %10llu\n", 2693168404Spjd (u_longlong_t)tzb->zb_count); 2694268645Sdelphij (void) printf("\tganged count: %10llu\n", 2695268645Sdelphij (longlong_t)tzb->zb_gangs); 2696219089Spjd (void) printf("\tbp logical: %10llu avg: %6llu\n", 2697168404Spjd (u_longlong_t)tzb->zb_lsize, 2698168404Spjd (u_longlong_t)(tzb->zb_lsize / tzb->zb_count)); 2699219089Spjd (void) printf("\tbp physical: %10llu avg:" 2700219089Spjd " %6llu compression: %6.2f\n", 2701168404Spjd (u_longlong_t)tzb->zb_psize, 2702168404Spjd (u_longlong_t)(tzb->zb_psize / tzb->zb_count), 2703168404Spjd (double)tzb->zb_lsize / tzb->zb_psize); 2704219089Spjd (void) printf("\tbp allocated: %10llu avg:" 2705219089Spjd " %6llu compression: %6.2f\n", 2706168404Spjd (u_longlong_t)tzb->zb_asize, 2707168404Spjd (u_longlong_t)(tzb->zb_asize / tzb->zb_count), 2708168404Spjd (double)tzb->zb_lsize / tzb->zb_asize); 2709219089Spjd (void) printf("\tbp deduped: %10llu ref>1:" 2710219089Spjd " %6llu deduplication: %6.2f\n", 2711219089Spjd (u_longlong_t)zcb.zcb_dedup_asize, 2712219089Spjd (u_longlong_t)zcb.zcb_dedup_blocks, 2713219089Spjd (double)zcb.zcb_dedup_asize / tzb->zb_asize + 1.0); 2714219089Spjd (void) printf("\tSPA allocated: %10llu used: %5.2f%%\n", 2715219089Spjd (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space); 2716168404Spjd 2717268649Sdelphij for (bp_embedded_type_t i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) { 2718268649Sdelphij if (zcb.zcb_embedded_blocks[i] == 0) 2719268649Sdelphij continue; 2720268649Sdelphij (void) printf("\n"); 2721268649Sdelphij (void) printf("\tadditional, non-pointer bps of type %u: " 2722268649Sdelphij "%10llu\n", 2723268649Sdelphij i, (u_longlong_t)zcb.zcb_embedded_blocks[i]); 2724268649Sdelphij 2725268649Sdelphij if (dump_opt['b'] >= 3) { 2726268649Sdelphij (void) printf("\t number of (compressed) bytes: " 2727268649Sdelphij "number of bps\n"); 2728268649Sdelphij dump_histogram(zcb.zcb_embedded_histogram[i], 2729268649Sdelphij sizeof (zcb.zcb_embedded_histogram[i]) / 2730268649Sdelphij sizeof (zcb.zcb_embedded_histogram[i][0]), 0); 2731268649Sdelphij } 2732268649Sdelphij } 2733268649Sdelphij 2734268645Sdelphij if (tzb->zb_ditto_samevdev != 0) { 2735268645Sdelphij (void) printf("\tDittoed blocks on same vdev: %llu\n", 2736268645Sdelphij (longlong_t)tzb->zb_ditto_samevdev); 2737268645Sdelphij } 2738268645Sdelphij 2739168404Spjd if (dump_opt['b'] >= 2) { 2740168404Spjd int l, t, level; 2741168404Spjd (void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 2742168404Spjd "\t avg\t comp\t%%Total\tType\n"); 2743168404Spjd 2744219089Spjd for (t = 0; t <= ZDB_OT_TOTAL; t++) { 2745219089Spjd char csize[32], lsize[32], psize[32], asize[32]; 2746268645Sdelphij char avg[32], gang[32]; 2747168404Spjd char *typename; 2748168404Spjd 2749219089Spjd if (t < DMU_OT_NUMTYPES) 2750219089Spjd typename = dmu_ot[t].ot_name; 2751219089Spjd else 2752219089Spjd typename = zdb_ot_extname[t - DMU_OT_NUMTYPES]; 2753168404Spjd 2754168404Spjd if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) { 2755168404Spjd (void) printf("%6s\t%5s\t%5s\t%5s" 2756168404Spjd "\t%5s\t%5s\t%6s\t%s\n", 2757168404Spjd "-", 2758168404Spjd "-", 2759168404Spjd "-", 2760168404Spjd "-", 2761168404Spjd "-", 2762168404Spjd "-", 2763168404Spjd "-", 2764168404Spjd typename); 2765168404Spjd continue; 2766168404Spjd } 2767168404Spjd 2768168404Spjd for (l = ZB_TOTAL - 1; l >= -1; l--) { 2769168404Spjd level = (l == -1 ? ZB_TOTAL : l); 2770168404Spjd zb = &zcb.zcb_type[level][t]; 2771168404Spjd 2772168404Spjd if (zb->zb_asize == 0) 2773168404Spjd continue; 2774168404Spjd 2775168404Spjd if (dump_opt['b'] < 3 && level != ZB_TOTAL) 2776168404Spjd continue; 2777168404Spjd 2778168404Spjd if (level == 0 && zb->zb_asize == 2779168404Spjd zcb.zcb_type[ZB_TOTAL][t].zb_asize) 2780168404Spjd continue; 2781168404Spjd 2782219089Spjd zdb_nicenum(zb->zb_count, csize); 2783219089Spjd zdb_nicenum(zb->zb_lsize, lsize); 2784219089Spjd zdb_nicenum(zb->zb_psize, psize); 2785219089Spjd zdb_nicenum(zb->zb_asize, asize); 2786219089Spjd zdb_nicenum(zb->zb_asize / zb->zb_count, avg); 2787268645Sdelphij zdb_nicenum(zb->zb_gangs, gang); 2788168404Spjd 2789168404Spjd (void) printf("%6s\t%5s\t%5s\t%5s\t%5s" 2790168404Spjd "\t%5.2f\t%6.2f\t", 2791168404Spjd csize, lsize, psize, asize, avg, 2792168404Spjd (double)zb->zb_lsize / zb->zb_psize, 2793168404Spjd 100.0 * zb->zb_asize / tzb->zb_asize); 2794168404Spjd 2795168404Spjd if (level == ZB_TOTAL) 2796168404Spjd (void) printf("%s\n", typename); 2797168404Spjd else 2798168404Spjd (void) printf(" L%d %s\n", 2799168404Spjd level, typename); 2800249207Smm 2801268645Sdelphij if (dump_opt['b'] >= 3 && zb->zb_gangs > 0) { 2802268645Sdelphij (void) printf("\t number of ganged " 2803268645Sdelphij "blocks: %s\n", gang); 2804268645Sdelphij } 2805268645Sdelphij 2806249207Smm if (dump_opt['b'] >= 4) { 2807249207Smm (void) printf("psize " 2808249207Smm "(in 512-byte sectors): " 2809249207Smm "number of blocks\n"); 2810249207Smm dump_histogram(zb->zb_psize_histogram, 2811262093Savg PSIZE_HISTO_SIZE, 0); 2812249207Smm } 2813168404Spjd } 2814168404Spjd } 2815168404Spjd } 2816168404Spjd 2817168404Spjd (void) printf("\n"); 2818168404Spjd 2819168404Spjd if (leaks) 2820168404Spjd return (2); 2821168404Spjd 2822168404Spjd if (zcb.zcb_haderrors) 2823168404Spjd return (3); 2824168404Spjd 2825168404Spjd return (0); 2826168404Spjd} 2827168404Spjd 2828219089Spjdtypedef struct zdb_ddt_entry { 2829219089Spjd ddt_key_t zdde_key; 2830219089Spjd uint64_t zdde_ref_blocks; 2831219089Spjd uint64_t zdde_ref_lsize; 2832219089Spjd uint64_t zdde_ref_psize; 2833219089Spjd uint64_t zdde_ref_dsize; 2834219089Spjd avl_node_t zdde_node; 2835219089Spjd} zdb_ddt_entry_t; 2836219089Spjd 2837219089Spjd/* ARGSUSED */ 2838219089Spjdstatic int 2839219089Spjdzdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, 2840268657Sdelphij const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg) 2841219089Spjd{ 2842219089Spjd avl_tree_t *t = arg; 2843219089Spjd avl_index_t where; 2844219089Spjd zdb_ddt_entry_t *zdde, zdde_search; 2845219089Spjd 2846268649Sdelphij if (BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp)) 2847219089Spjd return (0); 2848219089Spjd 2849219089Spjd if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) { 2850219089Spjd (void) printf("traversing objset %llu, %llu objects, " 2851219089Spjd "%lu blocks so far\n", 2852219089Spjd (u_longlong_t)zb->zb_objset, 2853268649Sdelphij (u_longlong_t)BP_GET_FILL(bp), 2854219089Spjd avl_numnodes(t)); 2855219089Spjd } 2856219089Spjd 2857219089Spjd if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF || 2858236884Smm BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp))) 2859219089Spjd return (0); 2860219089Spjd 2861219089Spjd ddt_key_fill(&zdde_search.zdde_key, bp); 2862219089Spjd 2863219089Spjd zdde = avl_find(t, &zdde_search, &where); 2864219089Spjd 2865219089Spjd if (zdde == NULL) { 2866219089Spjd zdde = umem_zalloc(sizeof (*zdde), UMEM_NOFAIL); 2867219089Spjd zdde->zdde_key = zdde_search.zdde_key; 2868219089Spjd avl_insert(t, zdde, where); 2869219089Spjd } 2870219089Spjd 2871219089Spjd zdde->zdde_ref_blocks += 1; 2872219089Spjd zdde->zdde_ref_lsize += BP_GET_LSIZE(bp); 2873219089Spjd zdde->zdde_ref_psize += BP_GET_PSIZE(bp); 2874219089Spjd zdde->zdde_ref_dsize += bp_get_dsize_sync(spa, bp); 2875219089Spjd 2876219089Spjd return (0); 2877219089Spjd} 2878219089Spjd 2879168404Spjdstatic void 2880219089Spjddump_simulated_ddt(spa_t *spa) 2881219089Spjd{ 2882219089Spjd avl_tree_t t; 2883219089Spjd void *cookie = NULL; 2884219089Spjd zdb_ddt_entry_t *zdde; 2885219089Spjd ddt_histogram_t ddh_total = { 0 }; 2886219089Spjd ddt_stat_t dds_total = { 0 }; 2887219089Spjd 2888219089Spjd avl_create(&t, ddt_entry_compare, 2889219089Spjd sizeof (zdb_ddt_entry_t), offsetof(zdb_ddt_entry_t, zdde_node)); 2890219089Spjd 2891219089Spjd spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); 2892219089Spjd 2893219089Spjd (void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA, 2894219089Spjd zdb_ddt_add_cb, &t); 2895219089Spjd 2896219089Spjd spa_config_exit(spa, SCL_CONFIG, FTAG); 2897219089Spjd 2898219089Spjd while ((zdde = avl_destroy_nodes(&t, &cookie)) != NULL) { 2899219089Spjd ddt_stat_t dds; 2900219089Spjd uint64_t refcnt = zdde->zdde_ref_blocks; 2901219089Spjd ASSERT(refcnt != 0); 2902219089Spjd 2903219089Spjd dds.dds_blocks = zdde->zdde_ref_blocks / refcnt; 2904219089Spjd dds.dds_lsize = zdde->zdde_ref_lsize / refcnt; 2905219089Spjd dds.dds_psize = zdde->zdde_ref_psize / refcnt; 2906219089Spjd dds.dds_dsize = zdde->zdde_ref_dsize / refcnt; 2907219089Spjd 2908219089Spjd dds.dds_ref_blocks = zdde->zdde_ref_blocks; 2909219089Spjd dds.dds_ref_lsize = zdde->zdde_ref_lsize; 2910219089Spjd dds.dds_ref_psize = zdde->zdde_ref_psize; 2911219089Spjd dds.dds_ref_dsize = zdde->zdde_ref_dsize; 2912219089Spjd 2913265740Sdelphij ddt_stat_add(&ddh_total.ddh_stat[highbit64(refcnt) - 1], 2914265740Sdelphij &dds, 0); 2915219089Spjd 2916219089Spjd umem_free(zdde, sizeof (*zdde)); 2917219089Spjd } 2918219089Spjd 2919219089Spjd avl_destroy(&t); 2920219089Spjd 2921219089Spjd ddt_histogram_stat(&dds_total, &ddh_total); 2922219089Spjd 2923219089Spjd (void) printf("Simulated DDT histogram:\n"); 2924219089Spjd 2925219089Spjd zpool_dump_ddt(&dds_total, &ddh_total); 2926219089Spjd 2927219089Spjd dump_dedup_ratio(&dds_total); 2928219089Spjd} 2929219089Spjd 2930219089Spjdstatic void 2931168404Spjddump_zpool(spa_t *spa) 2932168404Spjd{ 2933168404Spjd dsl_pool_t *dp = spa_get_dsl(spa); 2934168404Spjd int rc = 0; 2935168404Spjd 2936219089Spjd if (dump_opt['S']) { 2937219089Spjd dump_simulated_ddt(spa); 2938219089Spjd return; 2939219089Spjd } 2940219089Spjd 2941219089Spjd if (!dump_opt['e'] && dump_opt['C'] > 1) { 2942219089Spjd (void) printf("\nCached configuration:\n"); 2943219089Spjd dump_nvlist(spa->spa_config, 8); 2944219089Spjd } 2945219089Spjd 2946219089Spjd if (dump_opt['C']) 2947219089Spjd dump_config(spa); 2948219089Spjd 2949168404Spjd if (dump_opt['u']) 2950219089Spjd dump_uberblock(&spa->spa_uberblock, "\nUberblock:\n", "\n"); 2951168404Spjd 2952219089Spjd if (dump_opt['D']) 2953219089Spjd dump_all_ddts(spa); 2954219089Spjd 2955219089Spjd if (dump_opt['d'] > 2 || dump_opt['m']) 2956219089Spjd dump_metaslabs(spa); 2957269773Sdelphij if (dump_opt['M']) 2958269773Sdelphij dump_metaslab_groups(spa); 2959219089Spjd 2960219089Spjd if (dump_opt['d'] || dump_opt['i']) { 2961276081Sdelphij uint64_t refcount; 2962168404Spjd dump_dir(dp->dp_meta_objset); 2963168404Spjd if (dump_opt['d'] >= 3) { 2964247852Smm dump_bpobj(&spa->spa_deferred_bpobj, 2965247852Smm "Deferred frees", 0); 2966219089Spjd if (spa_version(spa) >= SPA_VERSION_DEADLISTS) { 2967219089Spjd dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj, 2968247852Smm "Pool snapshot frees", 0); 2969219089Spjd } 2970236884Smm 2971236884Smm if (spa_feature_is_active(spa, 2972263390Sdelphij SPA_FEATURE_ASYNC_DESTROY)) { 2973236884Smm dump_bptree(spa->spa_meta_objset, 2974236884Smm spa->spa_dsl_pool->dp_bptree_obj, 2975236884Smm "Pool dataset frees"); 2976236884Smm } 2977168404Spjd dump_dtl(spa->spa_root_vdev, 0); 2978209962Smm } 2979219089Spjd (void) dmu_objset_find(spa_name(spa), dump_one_dir, 2980219089Spjd NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN); 2981276081Sdelphij 2982276081Sdelphij (void) feature_get_refcount(spa, 2983276081Sdelphij &spa_feature_table[SPA_FEATURE_LARGE_BLOCKS], &refcount); 2984276081Sdelphij if (num_large_blocks != refcount) { 2985276081Sdelphij (void) printf("large_blocks feature refcount mismatch: " 2986276081Sdelphij "expected %lld != actual %lld\n", 2987276081Sdelphij (longlong_t)num_large_blocks, 2988276081Sdelphij (longlong_t)refcount); 2989276081Sdelphij rc = 2; 2990276081Sdelphij } else { 2991276081Sdelphij (void) printf("Verified large_blocks feature refcount " 2992276081Sdelphij "is correct (%llu)\n", (longlong_t)refcount); 2993276081Sdelphij } 2994168404Spjd } 2995276081Sdelphij if (rc == 0 && (dump_opt['b'] || dump_opt['c'])) 2996168404Spjd rc = dump_block_stats(spa); 2997168404Spjd 2998262093Savg if (rc == 0) 2999262093Savg rc = verify_spacemap_refcounts(spa); 3000262093Savg 3001168404Spjd if (dump_opt['s']) 3002168404Spjd show_pool_stats(spa); 3003168404Spjd 3004219089Spjd if (dump_opt['h']) 3005219089Spjd dump_history(spa); 3006219089Spjd 3007168404Spjd if (rc != 0) 3008168404Spjd exit(rc); 3009168404Spjd} 3010168404Spjd 3011168404Spjd#define ZDB_FLAG_CHECKSUM 0x0001 3012168404Spjd#define ZDB_FLAG_DECOMPRESS 0x0002 3013168404Spjd#define ZDB_FLAG_BSWAP 0x0004 3014168404Spjd#define ZDB_FLAG_GBH 0x0008 3015168404Spjd#define ZDB_FLAG_INDIRECT 0x0010 3016168404Spjd#define ZDB_FLAG_PHYS 0x0020 3017168404Spjd#define ZDB_FLAG_RAW 0x0040 3018168404Spjd#define ZDB_FLAG_PRINT_BLKPTR 0x0080 3019168404Spjd 3020168404Spjdint flagbits[256]; 3021168404Spjd 3022168404Spjdstatic void 3023168404Spjdzdb_print_blkptr(blkptr_t *bp, int flags) 3024168404Spjd{ 3025219089Spjd char blkbuf[BP_SPRINTF_LEN]; 3026168404Spjd 3027168404Spjd if (flags & ZDB_FLAG_BSWAP) 3028168404Spjd byteswap_uint64_array((void *)bp, sizeof (blkptr_t)); 3029219089Spjd 3030263397Sdelphij snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); 3031219089Spjd (void) printf("%s\n", blkbuf); 3032168404Spjd} 3033168404Spjd 3034168404Spjdstatic void 3035168404Spjdzdb_dump_indirect(blkptr_t *bp, int nbps, int flags) 3036168404Spjd{ 3037168404Spjd int i; 3038168404Spjd 3039168404Spjd for (i = 0; i < nbps; i++) 3040168404Spjd zdb_print_blkptr(&bp[i], flags); 3041168404Spjd} 3042168404Spjd 3043168404Spjdstatic void 3044168404Spjdzdb_dump_gbh(void *buf, int flags) 3045168404Spjd{ 3046168404Spjd zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags); 3047168404Spjd} 3048168404Spjd 3049168404Spjdstatic void 3050168404Spjdzdb_dump_block_raw(void *buf, uint64_t size, int flags) 3051168404Spjd{ 3052168404Spjd if (flags & ZDB_FLAG_BSWAP) 3053168404Spjd byteswap_uint64_array(buf, size); 3054219089Spjd (void) write(1, buf, size); 3055168404Spjd} 3056168404Spjd 3057168404Spjdstatic void 3058168404Spjdzdb_dump_block(char *label, void *buf, uint64_t size, int flags) 3059168404Spjd{ 3060168404Spjd uint64_t *d = (uint64_t *)buf; 3061168404Spjd int nwords = size / sizeof (uint64_t); 3062168404Spjd int do_bswap = !!(flags & ZDB_FLAG_BSWAP); 3063168404Spjd int i, j; 3064168404Spjd char *hdr, *c; 3065168404Spjd 3066168404Spjd 3067168404Spjd if (do_bswap) 3068168404Spjd hdr = " 7 6 5 4 3 2 1 0 f e d c b a 9 8"; 3069168404Spjd else 3070168404Spjd hdr = " 0 1 2 3 4 5 6 7 8 9 a b c d e f"; 3071168404Spjd 3072168404Spjd (void) printf("\n%s\n%6s %s 0123456789abcdef\n", label, "", hdr); 3073168404Spjd 3074168404Spjd for (i = 0; i < nwords; i += 2) { 3075168404Spjd (void) printf("%06llx: %016llx %016llx ", 3076168404Spjd (u_longlong_t)(i * sizeof (uint64_t)), 3077168404Spjd (u_longlong_t)(do_bswap ? BSWAP_64(d[i]) : d[i]), 3078168404Spjd (u_longlong_t)(do_bswap ? BSWAP_64(d[i + 1]) : d[i + 1])); 3079168404Spjd 3080168404Spjd c = (char *)&d[i]; 3081168404Spjd for (j = 0; j < 2 * sizeof (uint64_t); j++) 3082168404Spjd (void) printf("%c", isprint(c[j]) ? c[j] : '.'); 3083168404Spjd (void) printf("\n"); 3084168404Spjd } 3085168404Spjd} 3086168404Spjd 3087168404Spjd/* 3088168404Spjd * There are two acceptable formats: 3089168404Spjd * leaf_name - For example: c1t0d0 or /tmp/ztest.0a 3090168404Spjd * child[.child]* - For example: 0.1.1 3091168404Spjd * 3092168404Spjd * The second form can be used to specify arbitrary vdevs anywhere 3093168404Spjd * in the heirarchy. For example, in a pool with a mirror of 3094168404Spjd * RAID-Zs, you can specify either RAID-Z vdev with 0.0 or 0.1 . 3095168404Spjd */ 3096168404Spjdstatic vdev_t * 3097168404Spjdzdb_vdev_lookup(vdev_t *vdev, char *path) 3098168404Spjd{ 3099168404Spjd char *s, *p, *q; 3100168404Spjd int i; 3101168404Spjd 3102168404Spjd if (vdev == NULL) 3103168404Spjd return (NULL); 3104168404Spjd 3105168404Spjd /* First, assume the x.x.x.x format */ 3106168404Spjd i = (int)strtoul(path, &s, 10); 3107168404Spjd if (s == path || (s && *s != '.' && *s != '\0')) 3108168404Spjd goto name; 3109168404Spjd if (i < 0 || i >= vdev->vdev_children) 3110168404Spjd return (NULL); 3111168404Spjd 3112168404Spjd vdev = vdev->vdev_child[i]; 3113168404Spjd if (*s == '\0') 3114168404Spjd return (vdev); 3115168404Spjd return (zdb_vdev_lookup(vdev, s+1)); 3116168404Spjd 3117168404Spjdname: 3118168404Spjd for (i = 0; i < vdev->vdev_children; i++) { 3119168404Spjd vdev_t *vc = vdev->vdev_child[i]; 3120168404Spjd 3121168404Spjd if (vc->vdev_path == NULL) { 3122168404Spjd vc = zdb_vdev_lookup(vc, path); 3123168404Spjd if (vc == NULL) 3124168404Spjd continue; 3125168404Spjd else 3126168404Spjd return (vc); 3127168404Spjd } 3128168404Spjd 3129168404Spjd p = strrchr(vc->vdev_path, '/'); 3130168404Spjd p = p ? p + 1 : vc->vdev_path; 3131168404Spjd q = &vc->vdev_path[strlen(vc->vdev_path) - 2]; 3132168404Spjd 3133168404Spjd if (strcmp(vc->vdev_path, path) == 0) 3134168404Spjd return (vc); 3135168404Spjd if (strcmp(p, path) == 0) 3136168404Spjd return (vc); 3137168404Spjd if (strcmp(q, "s0") == 0 && strncmp(p, path, q - p) == 0) 3138168404Spjd return (vc); 3139168404Spjd } 3140168404Spjd 3141168404Spjd return (NULL); 3142168404Spjd} 3143168404Spjd 3144168404Spjd/* 3145168404Spjd * Read a block from a pool and print it out. The syntax of the 3146168404Spjd * block descriptor is: 3147168404Spjd * 3148168404Spjd * pool:vdev_specifier:offset:size[:flags] 3149168404Spjd * 3150168404Spjd * pool - The name of the pool you wish to read from 3151168404Spjd * vdev_specifier - Which vdev (see comment for zdb_vdev_lookup) 3152168404Spjd * offset - offset, in hex, in bytes 3153168404Spjd * size - Amount of data to read, in hex, in bytes 3154168404Spjd * flags - A string of characters specifying options 3155168404Spjd * b: Decode a blkptr at given offset within block 3156168404Spjd * *c: Calculate and display checksums 3157219089Spjd * d: Decompress data before dumping 3158168404Spjd * e: Byteswap data before dumping 3159219089Spjd * g: Display data as a gang block header 3160219089Spjd * i: Display as an indirect block 3161168404Spjd * p: Do I/O to physical offset 3162168404Spjd * r: Dump raw data to stdout 3163168404Spjd * 3164168404Spjd * * = not yet implemented 3165168404Spjd */ 3166168404Spjdstatic void 3167219089Spjdzdb_read_block(char *thing, spa_t *spa) 3168168404Spjd{ 3169219089Spjd blkptr_t blk, *bp = &blk; 3170219089Spjd dva_t *dva = bp->blk_dva; 3171168404Spjd int flags = 0; 3172219089Spjd uint64_t offset = 0, size = 0, psize = 0, lsize = 0, blkptr_offset = 0; 3173168404Spjd zio_t *zio; 3174168404Spjd vdev_t *vd; 3175219089Spjd void *pbuf, *lbuf, *buf; 3176219089Spjd char *s, *p, *dup, *vdev, *flagstr; 3177219089Spjd int i, error; 3178168404Spjd 3179168404Spjd dup = strdup(thing); 3180168404Spjd s = strtok(dup, ":"); 3181168404Spjd vdev = s ? s : ""; 3182168404Spjd s = strtok(NULL, ":"); 3183168404Spjd offset = strtoull(s ? s : "", NULL, 16); 3184168404Spjd s = strtok(NULL, ":"); 3185168404Spjd size = strtoull(s ? s : "", NULL, 16); 3186168404Spjd s = strtok(NULL, ":"); 3187168404Spjd flagstr = s ? s : ""; 3188168404Spjd 3189168404Spjd s = NULL; 3190168404Spjd if (size == 0) 3191168404Spjd s = "size must not be zero"; 3192168404Spjd if (!IS_P2ALIGNED(size, DEV_BSIZE)) 3193168404Spjd s = "size must be a multiple of sector size"; 3194168404Spjd if (!IS_P2ALIGNED(offset, DEV_BSIZE)) 3195168404Spjd s = "offset must be a multiple of sector size"; 3196168404Spjd if (s) { 3197168404Spjd (void) printf("Invalid block specifier: %s - %s\n", thing, s); 3198168404Spjd free(dup); 3199168404Spjd return; 3200168404Spjd } 3201168404Spjd 3202168404Spjd for (s = strtok(flagstr, ":"); s; s = strtok(NULL, ":")) { 3203168404Spjd for (i = 0; flagstr[i]; i++) { 3204168404Spjd int bit = flagbits[(uchar_t)flagstr[i]]; 3205168404Spjd 3206168404Spjd if (bit == 0) { 3207168404Spjd (void) printf("***Invalid flag: %c\n", 3208168404Spjd flagstr[i]); 3209168404Spjd continue; 3210168404Spjd } 3211168404Spjd flags |= bit; 3212168404Spjd 3213168404Spjd /* If it's not something with an argument, keep going */ 3214219089Spjd if ((bit & (ZDB_FLAG_CHECKSUM | 3215168404Spjd ZDB_FLAG_PRINT_BLKPTR)) == 0) 3216168404Spjd continue; 3217168404Spjd 3218168404Spjd p = &flagstr[i + 1]; 3219168404Spjd if (bit == ZDB_FLAG_PRINT_BLKPTR) 3220168404Spjd blkptr_offset = strtoull(p, &p, 16); 3221168404Spjd if (*p != ':' && *p != '\0') { 3222168404Spjd (void) printf("***Invalid flag arg: '%s'\n", s); 3223168404Spjd free(dup); 3224168404Spjd return; 3225168404Spjd } 3226262104Savg i += p - &flagstr[i + 1]; /* skip over the number */ 3227168404Spjd } 3228168404Spjd } 3229168404Spjd 3230168404Spjd vd = zdb_vdev_lookup(spa->spa_root_vdev, vdev); 3231168404Spjd if (vd == NULL) { 3232168404Spjd (void) printf("***Invalid vdev: %s\n", vdev); 3233168404Spjd free(dup); 3234168404Spjd return; 3235168404Spjd } else { 3236168404Spjd if (vd->vdev_path) 3237219089Spjd (void) fprintf(stderr, "Found vdev: %s\n", 3238219089Spjd vd->vdev_path); 3239168404Spjd else 3240219089Spjd (void) fprintf(stderr, "Found vdev type: %s\n", 3241168404Spjd vd->vdev_ops->vdev_op_type); 3242168404Spjd } 3243168404Spjd 3244219089Spjd psize = size; 3245219089Spjd lsize = size; 3246168404Spjd 3247219089Spjd pbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); 3248219089Spjd lbuf = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); 3249168404Spjd 3250219089Spjd BP_ZERO(bp); 3251219089Spjd 3252219089Spjd DVA_SET_VDEV(&dva[0], vd->vdev_id); 3253219089Spjd DVA_SET_OFFSET(&dva[0], offset); 3254219089Spjd DVA_SET_GANG(&dva[0], !!(flags & ZDB_FLAG_GBH)); 3255219089Spjd DVA_SET_ASIZE(&dva[0], vdev_psize_to_asize(vd, psize)); 3256219089Spjd 3257219089Spjd BP_SET_BIRTH(bp, TXG_INITIAL, TXG_INITIAL); 3258219089Spjd 3259219089Spjd BP_SET_LSIZE(bp, lsize); 3260219089Spjd BP_SET_PSIZE(bp, psize); 3261219089Spjd BP_SET_COMPRESS(bp, ZIO_COMPRESS_OFF); 3262219089Spjd BP_SET_CHECKSUM(bp, ZIO_CHECKSUM_OFF); 3263219089Spjd BP_SET_TYPE(bp, DMU_OT_NONE); 3264219089Spjd BP_SET_LEVEL(bp, 0); 3265219089Spjd BP_SET_DEDUP(bp, 0); 3266219089Spjd BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER); 3267219089Spjd 3268185029Spjd spa_config_enter(spa, SCL_STATE, FTAG, RW_READER); 3269168404Spjd zio = zio_root(spa, NULL, NULL, 0); 3270219089Spjd 3271219089Spjd if (vd == vd->vdev_top) { 3272219089Spjd /* 3273219089Spjd * Treat this as a normal block read. 3274219089Spjd */ 3275219089Spjd zio_nowait(zio_read(zio, spa, bp, pbuf, psize, NULL, NULL, 3276219089Spjd ZIO_PRIORITY_SYNC_READ, 3277219089Spjd ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL)); 3278219089Spjd } else { 3279219089Spjd /* 3280219089Spjd * Treat this as a vdev child I/O. 3281219089Spjd */ 3282219089Spjd zio_nowait(zio_vdev_child_io(zio, bp, vd, offset, pbuf, psize, 3283219089Spjd ZIO_TYPE_READ, ZIO_PRIORITY_SYNC_READ, 3284219089Spjd ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE | 3285219089Spjd ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY | 3286219089Spjd ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW, NULL, NULL)); 3287219089Spjd } 3288219089Spjd 3289168404Spjd error = zio_wait(zio); 3290185029Spjd spa_config_exit(spa, SCL_STATE, FTAG); 3291168404Spjd 3292168404Spjd if (error) { 3293168404Spjd (void) printf("Read of %s failed, error: %d\n", thing, error); 3294168404Spjd goto out; 3295168404Spjd } 3296168404Spjd 3297219089Spjd if (flags & ZDB_FLAG_DECOMPRESS) { 3298219089Spjd /* 3299219089Spjd * We don't know how the data was compressed, so just try 3300219089Spjd * every decompress function at every inflated blocksize. 3301219089Spjd */ 3302219089Spjd enum zio_compress c; 3303219089Spjd void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); 3304219089Spjd void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); 3305219089Spjd 3306219089Spjd bcopy(pbuf, pbuf2, psize); 3307219089Spjd 3308219089Spjd VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf + psize, 3309219089Spjd SPA_MAXBLOCKSIZE - psize) == 0); 3310219089Spjd 3311219089Spjd VERIFY(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize, 3312219089Spjd SPA_MAXBLOCKSIZE - psize) == 0); 3313219089Spjd 3314219089Spjd for (lsize = SPA_MAXBLOCKSIZE; lsize > psize; 3315219089Spjd lsize -= SPA_MINBLOCKSIZE) { 3316219089Spjd for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) { 3317219089Spjd if (zio_decompress_data(c, pbuf, lbuf, 3318219089Spjd psize, lsize) == 0 && 3319219089Spjd zio_decompress_data(c, pbuf2, lbuf2, 3320219089Spjd psize, lsize) == 0 && 3321219089Spjd bcmp(lbuf, lbuf2, lsize) == 0) 3322219089Spjd break; 3323219089Spjd } 3324219089Spjd if (c != ZIO_COMPRESS_FUNCTIONS) 3325219089Spjd break; 3326219089Spjd lsize -= SPA_MINBLOCKSIZE; 3327219089Spjd } 3328219089Spjd 3329219089Spjd umem_free(pbuf2, SPA_MAXBLOCKSIZE); 3330219089Spjd umem_free(lbuf2, SPA_MAXBLOCKSIZE); 3331219089Spjd 3332219089Spjd if (lsize <= psize) { 3333219089Spjd (void) printf("Decompress of %s failed\n", thing); 3334219089Spjd goto out; 3335219089Spjd } 3336219089Spjd buf = lbuf; 3337219089Spjd size = lsize; 3338219089Spjd } else { 3339219089Spjd buf = pbuf; 3340219089Spjd size = psize; 3341219089Spjd } 3342219089Spjd 3343168404Spjd if (flags & ZDB_FLAG_PRINT_BLKPTR) 3344168404Spjd zdb_print_blkptr((blkptr_t *)(void *) 3345168404Spjd ((uintptr_t)buf + (uintptr_t)blkptr_offset), flags); 3346168404Spjd else if (flags & ZDB_FLAG_RAW) 3347168404Spjd zdb_dump_block_raw(buf, size, flags); 3348168404Spjd else if (flags & ZDB_FLAG_INDIRECT) 3349168404Spjd zdb_dump_indirect((blkptr_t *)buf, size / sizeof (blkptr_t), 3350168404Spjd flags); 3351168404Spjd else if (flags & ZDB_FLAG_GBH) 3352168404Spjd zdb_dump_gbh(buf, flags); 3353168404Spjd else 3354168404Spjd zdb_dump_block(thing, buf, size, flags); 3355168404Spjd 3356168404Spjdout: 3357219089Spjd umem_free(pbuf, SPA_MAXBLOCKSIZE); 3358219089Spjd umem_free(lbuf, SPA_MAXBLOCKSIZE); 3359168404Spjd free(dup); 3360168404Spjd} 3361168404Spjd 3362185029Spjdstatic boolean_t 3363219089Spjdpool_match(nvlist_t *cfg, char *tgt) 3364185029Spjd{ 3365219089Spjd uint64_t v, guid = strtoull(tgt, NULL, 0); 3366185029Spjd char *s; 3367185029Spjd 3368219089Spjd if (guid != 0) { 3369219089Spjd if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0) 3370219089Spjd return (v == guid); 3371219089Spjd } else { 3372219089Spjd if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0) 3373219089Spjd return (strcmp(s, tgt) == 0); 3374185029Spjd } 3375185029Spjd return (B_FALSE); 3376185029Spjd} 3377185029Spjd 3378219089Spjdstatic char * 3379219089Spjdfind_zpool(char **target, nvlist_t **configp, int dirc, char **dirv) 3380185029Spjd{ 3381219089Spjd nvlist_t *pools; 3382219089Spjd nvlist_t *match = NULL; 3383219089Spjd char *name = NULL; 3384219089Spjd char *sepp = NULL; 3385219089Spjd char sep; 3386219089Spjd int count = 0; 3387219089Spjd importargs_t args = { 0 }; 3388185029Spjd 3389219089Spjd args.paths = dirc; 3390219089Spjd args.path = dirv; 3391219089Spjd args.can_be_active = B_TRUE; 3392185029Spjd 3393219089Spjd if ((sepp = strpbrk(*target, "/@")) != NULL) { 3394219089Spjd sep = *sepp; 3395219089Spjd *sepp = '\0'; 3396185029Spjd } 3397185029Spjd 3398219089Spjd pools = zpool_search_import(g_zfs, &args); 3399185029Spjd 3400185029Spjd if (pools != NULL) { 3401185029Spjd nvpair_t *elem = NULL; 3402185029Spjd while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 3403185029Spjd verify(nvpair_value_nvlist(elem, configp) == 0); 3404219089Spjd if (pool_match(*configp, *target)) { 3405219089Spjd count++; 3406185029Spjd if (match != NULL) { 3407219089Spjd /* print previously found config */ 3408219089Spjd if (name != NULL) { 3409219089Spjd (void) printf("%s\n", name); 3410219089Spjd dump_nvlist(match, 8); 3411219089Spjd name = NULL; 3412219089Spjd } 3413219089Spjd (void) printf("%s\n", 3414219089Spjd nvpair_name(elem)); 3415219089Spjd dump_nvlist(*configp, 8); 3416185029Spjd } else { 3417185029Spjd match = *configp; 3418219089Spjd name = nvpair_name(elem); 3419185029Spjd } 3420185029Spjd } 3421185029Spjd } 3422185029Spjd } 3423219089Spjd if (count > 1) 3424219089Spjd (void) fatal("\tMatched %d pools - use pool GUID " 3425219089Spjd "instead of pool name or \n" 3426219089Spjd "\tpool name part of a dataset name to select pool", count); 3427185029Spjd 3428219089Spjd if (sepp) 3429219089Spjd *sepp = sep; 3430219089Spjd /* 3431219089Spjd * If pool GUID was specified for pool id, replace it with pool name 3432219089Spjd */ 3433219089Spjd if (name && (strstr(*target, name) != *target)) { 3434219089Spjd int sz = 1 + strlen(name) + ((sepp) ? strlen(sepp) : 0); 3435185029Spjd 3436219089Spjd *target = umem_alloc(sz, UMEM_NOFAIL); 3437219089Spjd (void) snprintf(*target, sz, "%s%s", name, sepp ? sepp : ""); 3438219089Spjd } 3439219089Spjd 3440219089Spjd *configp = name ? match : NULL; 3441219089Spjd 3442219089Spjd return (name); 3443185029Spjd} 3444185029Spjd 3445168404Spjdint 3446168404Spjdmain(int argc, char **argv) 3447168404Spjd{ 3448168404Spjd int i, c; 3449168404Spjd struct rlimit rl = { 1024, 1024 }; 3450219089Spjd spa_t *spa = NULL; 3451168404Spjd objset_t *os = NULL; 3452168404Spjd int dump_all = 1; 3453168404Spjd int verbose = 0; 3454219089Spjd int error = 0; 3455219089Spjd char **searchdirs = NULL; 3456219089Spjd int nsearch = 0; 3457219089Spjd char *target; 3458219089Spjd nvlist_t *policy = NULL; 3459219089Spjd uint64_t max_txg = UINT64_MAX; 3460219089Spjd int rewind = ZPOOL_NEVER_REWIND; 3461168404Spjd 3462168404Spjd (void) setrlimit(RLIMIT_NOFILE, &rl); 3463168404Spjd (void) enable_extended_FILE_stdio(-1, -1); 3464168404Spjd 3465168404Spjd dprintf_setup(&argc, argv); 3466168404Spjd 3467268653Sdelphij while ((c = getopt(argc, argv, 3468269773Sdelphij "bcdhilmMI:suCDRSAFLXx:evp:t:U:P")) != -1) { 3469168404Spjd switch (c) { 3470219089Spjd case 'b': 3471219089Spjd case 'c': 3472168404Spjd case 'd': 3473219089Spjd case 'h': 3474168404Spjd case 'i': 3475219089Spjd case 'l': 3476209962Smm case 'm': 3477168404Spjd case 's': 3478219089Spjd case 'u': 3479168404Spjd case 'C': 3480219089Spjd case 'D': 3481269773Sdelphij case 'M': 3482168404Spjd case 'R': 3483219089Spjd case 'S': 3484168404Spjd dump_opt[c]++; 3485168404Spjd dump_all = 0; 3486168404Spjd break; 3487219089Spjd case 'A': 3488219089Spjd case 'F': 3489209962Smm case 'L': 3490219089Spjd case 'X': 3491219089Spjd case 'e': 3492219089Spjd case 'P': 3493209962Smm dump_opt[c]++; 3494209962Smm break; 3495269773Sdelphij case 'I': 3496263393Sdelphij max_inflight = strtoull(optarg, NULL, 0); 3497263393Sdelphij if (max_inflight == 0) { 3498263393Sdelphij (void) fprintf(stderr, "maximum number " 3499263393Sdelphij "of inflight I/Os must be greater " 3500263393Sdelphij "than 0\n"); 3501263393Sdelphij usage(); 3502263393Sdelphij } 3503263393Sdelphij break; 3504185029Spjd case 'p': 3505219089Spjd if (searchdirs == NULL) { 3506219089Spjd searchdirs = umem_alloc(sizeof (char *), 3507219089Spjd UMEM_NOFAIL); 3508219089Spjd } else { 3509219089Spjd char **tmp = umem_alloc((nsearch + 1) * 3510219089Spjd sizeof (char *), UMEM_NOFAIL); 3511219089Spjd bcopy(searchdirs, tmp, nsearch * 3512219089Spjd sizeof (char *)); 3513219089Spjd umem_free(searchdirs, 3514219089Spjd nsearch * sizeof (char *)); 3515219089Spjd searchdirs = tmp; 3516219089Spjd } 3517219089Spjd searchdirs[nsearch++] = optarg; 3518185029Spjd break; 3519209962Smm case 't': 3520219089Spjd max_txg = strtoull(optarg, NULL, 0); 3521219089Spjd if (max_txg < TXG_INITIAL) { 3522209962Smm (void) fprintf(stderr, "incorrect txg " 3523209962Smm "specified: %s\n", optarg); 3524209962Smm usage(); 3525209962Smm } 3526209962Smm break; 3527219089Spjd case 'U': 3528219089Spjd spa_config_path = optarg; 3529219089Spjd break; 3530269773Sdelphij case 'v': 3531269773Sdelphij verbose++; 3532269773Sdelphij break; 3533269773Sdelphij case 'x': 3534269773Sdelphij vn_dumpdir = optarg; 3535269773Sdelphij break; 3536168404Spjd default: 3537168404Spjd usage(); 3538168404Spjd break; 3539168404Spjd } 3540168404Spjd } 3541168404Spjd 3542219089Spjd if (!dump_opt['e'] && searchdirs != NULL) { 3543208047Smm (void) fprintf(stderr, "-p option requires use of -e\n"); 3544208047Smm usage(); 3545208047Smm } 3546185029Spjd 3547273508Sdelphij /* 3548273508Sdelphij * ZDB does not typically re-read blocks; therefore limit the ARC 3549273508Sdelphij * to 256 MB, which can be used entirely for metadata. 3550273508Sdelphij */ 3551273508Sdelphij zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024; 3552273508Sdelphij 3553275488Sdelphij /* 3554275488Sdelphij * "zdb -c" uses checksum-verifying scrub i/os which are async reads. 3555275488Sdelphij * "zdb -b" uses traversal prefetch which uses async reads. 3556275488Sdelphij * For good performance, let several of them be active at once. 3557275488Sdelphij */ 3558275488Sdelphij zfs_vdev_async_read_max_active = 10; 3559275488Sdelphij 3560168404Spjd kernel_init(FREAD); 3561185029Spjd g_zfs = libzfs_init(); 3562185029Spjd ASSERT(g_zfs != NULL); 3563168404Spjd 3564219089Spjd if (dump_all) 3565219089Spjd verbose = MAX(verbose, 1); 3566219089Spjd 3567168404Spjd for (c = 0; c < 256; c++) { 3568219089Spjd if (dump_all && !strchr("elAFLRSXP", c)) 3569168404Spjd dump_opt[c] = 1; 3570168404Spjd if (dump_opt[c]) 3571168404Spjd dump_opt[c] += verbose; 3572168404Spjd } 3573168404Spjd 3574219089Spjd aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2); 3575219089Spjd zfs_recover = (dump_opt['A'] > 1); 3576219089Spjd 3577168404Spjd argc -= optind; 3578168404Spjd argv += optind; 3579168404Spjd 3580219089Spjd if (argc < 2 && dump_opt['R']) 3581219089Spjd usage(); 3582168404Spjd if (argc < 1) { 3583219089Spjd if (!dump_opt['e'] && dump_opt['C']) { 3584185029Spjd dump_cachefile(spa_config_path); 3585168404Spjd return (0); 3586168404Spjd } 3587168404Spjd usage(); 3588168404Spjd } 3589168404Spjd 3590168404Spjd if (dump_opt['l']) { 3591168404Spjd dump_label(argv[0]); 3592168404Spjd return (0); 3593168404Spjd } 3594168404Spjd 3595219089Spjd if (dump_opt['X'] || dump_opt['F']) 3596219089Spjd rewind = ZPOOL_DO_REWIND | 3597219089Spjd (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0); 3598168404Spjd 3599219089Spjd if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 || 3600219089Spjd nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, max_txg) != 0 || 3601219089Spjd nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind) != 0) 3602219089Spjd fatal("internal error: %s", strerror(ENOMEM)); 3603168404Spjd 3604185029Spjd error = 0; 3605219089Spjd target = argv[0]; 3606185029Spjd 3607219089Spjd if (dump_opt['e']) { 3608219089Spjd nvlist_t *cfg = NULL; 3609219089Spjd char *name = find_zpool(&target, &cfg, nsearch, searchdirs); 3610185029Spjd 3611219089Spjd error = ENOENT; 3612219089Spjd if (name) { 3613219089Spjd if (dump_opt['C'] > 1) { 3614219089Spjd (void) printf("\nConfiguration for import:\n"); 3615219089Spjd dump_nvlist(cfg, 8); 3616185029Spjd } 3617219089Spjd if (nvlist_add_nvlist(cfg, 3618219089Spjd ZPOOL_REWIND_POLICY, policy) != 0) { 3619219089Spjd fatal("can't open '%s': %s", 3620219089Spjd target, strerror(ENOMEM)); 3621219089Spjd } 3622219089Spjd if ((error = spa_import(name, cfg, NULL, 3623219089Spjd ZFS_IMPORT_MISSING_LOG)) != 0) { 3624219089Spjd error = spa_import(name, cfg, NULL, 3625219089Spjd ZFS_IMPORT_VERBATIM); 3626219089Spjd } 3627185029Spjd } 3628168404Spjd } 3629168404Spjd 3630185029Spjd if (error == 0) { 3631219089Spjd if (strpbrk(target, "/@") == NULL || dump_opt['R']) { 3632219089Spjd error = spa_open_rewind(target, &spa, FTAG, policy, 3633219089Spjd NULL); 3634219089Spjd if (error) { 3635219089Spjd /* 3636219089Spjd * If we're missing the log device then 3637219089Spjd * try opening the pool after clearing the 3638219089Spjd * log state. 3639219089Spjd */ 3640219089Spjd mutex_enter(&spa_namespace_lock); 3641219089Spjd if ((spa = spa_lookup(target)) != NULL && 3642219089Spjd spa->spa_log_state == SPA_LOG_MISSING) { 3643219089Spjd spa->spa_log_state = SPA_LOG_CLEAR; 3644219089Spjd error = 0; 3645219089Spjd } 3646219089Spjd mutex_exit(&spa_namespace_lock); 3647219089Spjd 3648219089Spjd if (!error) { 3649219089Spjd error = spa_open_rewind(target, &spa, 3650219089Spjd FTAG, policy, NULL); 3651219089Spjd } 3652219089Spjd } 3653185029Spjd } else { 3654219089Spjd error = dmu_objset_own(target, DMU_OST_ANY, 3655219089Spjd B_TRUE, FTAG, &os); 3656185029Spjd } 3657185029Spjd } 3658219089Spjd nvlist_free(policy); 3659185029Spjd 3660168404Spjd if (error) 3661219089Spjd fatal("can't open '%s': %s", target, strerror(error)); 3662168404Spjd 3663168404Spjd argv++; 3664219089Spjd argc--; 3665219089Spjd if (!dump_opt['R']) { 3666219089Spjd if (argc > 0) { 3667219089Spjd zopt_objects = argc; 3668219089Spjd zopt_object = calloc(zopt_objects, sizeof (uint64_t)); 3669219089Spjd for (i = 0; i < zopt_objects; i++) { 3670219089Spjd errno = 0; 3671219089Spjd zopt_object[i] = strtoull(argv[i], NULL, 0); 3672219089Spjd if (zopt_object[i] == 0 && errno != 0) 3673219089Spjd fatal("bad number %s: %s", 3674219089Spjd argv[i], strerror(errno)); 3675219089Spjd } 3676168404Spjd } 3677244246Smm if (os != NULL) { 3678244246Smm dump_dir(os); 3679244246Smm } else if (zopt_objects > 0 && !dump_opt['m']) { 3680244246Smm dump_dir(spa->spa_meta_objset); 3681244246Smm } else { 3682244246Smm dump_zpool(spa); 3683244246Smm } 3684219089Spjd } else { 3685219089Spjd flagbits['b'] = ZDB_FLAG_PRINT_BLKPTR; 3686219089Spjd flagbits['c'] = ZDB_FLAG_CHECKSUM; 3687219089Spjd flagbits['d'] = ZDB_FLAG_DECOMPRESS; 3688219089Spjd flagbits['e'] = ZDB_FLAG_BSWAP; 3689219089Spjd flagbits['g'] = ZDB_FLAG_GBH; 3690219089Spjd flagbits['i'] = ZDB_FLAG_INDIRECT; 3691219089Spjd flagbits['p'] = ZDB_FLAG_PHYS; 3692219089Spjd flagbits['r'] = ZDB_FLAG_RAW; 3693168404Spjd 3694219089Spjd for (i = 0; i < argc; i++) 3695219089Spjd zdb_read_block(argv[i], spa); 3696168404Spjd } 3697168404Spjd 3698219089Spjd (os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG); 3699219089Spjd 3700185029Spjd fuid_table_destroy(); 3701219089Spjd sa_loaded = B_FALSE; 3702185029Spjd 3703185029Spjd libzfs_fini(g_zfs); 3704168404Spjd kernel_fini(); 3705168404Spjd 3706168404Spjd return (0); 3707168404Spjd} 3708