1*fa9e4066Sahrens /* 2*fa9e4066Sahrens * CDDL HEADER START 3*fa9e4066Sahrens * 4*fa9e4066Sahrens * The contents of this file are subject to the terms of the 5*fa9e4066Sahrens * Common Development and Distribution License, Version 1.0 only 6*fa9e4066Sahrens * (the "License"). You may not use this file except in compliance 7*fa9e4066Sahrens * with the License. 8*fa9e4066Sahrens * 9*fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 11*fa9e4066Sahrens * See the License for the specific language governing permissions 12*fa9e4066Sahrens * and limitations under the License. 13*fa9e4066Sahrens * 14*fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15*fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 17*fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18*fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19*fa9e4066Sahrens * 20*fa9e4066Sahrens * CDDL HEADER END 21*fa9e4066Sahrens */ 22*fa9e4066Sahrens /* 23*fa9e4066Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*fa9e4066Sahrens * Use is subject to license terms. 25*fa9e4066Sahrens */ 26*fa9e4066Sahrens 27*fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28*fa9e4066Sahrens 29*fa9e4066Sahrens #include <stdio.h> 30*fa9e4066Sahrens #include <stdlib.h> 31*fa9e4066Sahrens #include <sys/zfs_context.h> 32*fa9e4066Sahrens #include <sys/spa.h> 33*fa9e4066Sahrens #include <sys/spa_impl.h> 34*fa9e4066Sahrens #include <sys/dmu.h> 35*fa9e4066Sahrens #include <sys/zap.h> 36*fa9e4066Sahrens #include <sys/fs/zfs.h> 37*fa9e4066Sahrens #include <sys/zfs_znode.h> 38*fa9e4066Sahrens #include <sys/vdev.h> 39*fa9e4066Sahrens #include <sys/vdev_impl.h> 40*fa9e4066Sahrens #include <sys/metaslab_impl.h> 41*fa9e4066Sahrens #include <sys/dmu_objset.h> 42*fa9e4066Sahrens #include <sys/dsl_dir.h> 43*fa9e4066Sahrens #include <sys/dsl_dataset.h> 44*fa9e4066Sahrens #include <sys/dsl_pool.h> 45*fa9e4066Sahrens #include <sys/dbuf.h> 46*fa9e4066Sahrens #include <sys/zil.h> 47*fa9e4066Sahrens #include <sys/zil_impl.h> 48*fa9e4066Sahrens #include <sys/stat.h> 49*fa9e4066Sahrens #include <sys/resource.h> 50*fa9e4066Sahrens #include <sys/dmu_traverse.h> 51*fa9e4066Sahrens #include <sys/zio_checksum.h> 52*fa9e4066Sahrens #include <sys/zio_compress.h> 53*fa9e4066Sahrens 54*fa9e4066Sahrens const char cmdname[] = "zdb"; 55*fa9e4066Sahrens uint8_t dump_opt[256]; 56*fa9e4066Sahrens 57*fa9e4066Sahrens typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size); 58*fa9e4066Sahrens 59*fa9e4066Sahrens extern void dump_intent_log(zilog_t *); 60*fa9e4066Sahrens uint64_t *zopt_object = NULL; 61*fa9e4066Sahrens int zopt_objects = 0; 62*fa9e4066Sahrens int zdb_advance = ADVANCE_PRE; 63*fa9e4066Sahrens zbookmark_t zdb_noread = { 0, 0, ZB_NO_LEVEL, 0 }; 64*fa9e4066Sahrens 65*fa9e4066Sahrens /* 66*fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 67*fa9e4066Sahrens * debugging facilities. 68*fa9e4066Sahrens */ 69*fa9e4066Sahrens const char * 70*fa9e4066Sahrens _umem_debug_init() 71*fa9e4066Sahrens { 72*fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 73*fa9e4066Sahrens } 74*fa9e4066Sahrens 75*fa9e4066Sahrens const char * 76*fa9e4066Sahrens _umem_logging_init(void) 77*fa9e4066Sahrens { 78*fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 79*fa9e4066Sahrens } 80*fa9e4066Sahrens 81*fa9e4066Sahrens static void 82*fa9e4066Sahrens usage(void) 83*fa9e4066Sahrens { 84*fa9e4066Sahrens (void) fprintf(stderr, 85*fa9e4066Sahrens "Usage: %s [-udibcsvLU] [-O order] [-B os:obj:level:blkid] " 86*fa9e4066Sahrens "dataset [object...]\n" 87*fa9e4066Sahrens " %s -C [pool]\n" 88*fa9e4066Sahrens " %s -l dev\n", 89*fa9e4066Sahrens cmdname, cmdname, cmdname); 90*fa9e4066Sahrens 91*fa9e4066Sahrens (void) fprintf(stderr, " -u uberblock\n"); 92*fa9e4066Sahrens (void) fprintf(stderr, " -d datasets\n"); 93*fa9e4066Sahrens (void) fprintf(stderr, " -C cached pool configuration\n"); 94*fa9e4066Sahrens (void) fprintf(stderr, " -i intent logs\n"); 95*fa9e4066Sahrens (void) fprintf(stderr, " -b block statistics\n"); 96*fa9e4066Sahrens (void) fprintf(stderr, " -c checksum all data blocks\n"); 97*fa9e4066Sahrens (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); 98*fa9e4066Sahrens (void) fprintf(stderr, " -v verbose (applies to all others)\n"); 99*fa9e4066Sahrens (void) fprintf(stderr, " -l dump label contents\n"); 100*fa9e4066Sahrens (void) fprintf(stderr, " -L live pool (allows some errors)\n"); 101*fa9e4066Sahrens (void) fprintf(stderr, " -O [!]<pre|post|prune|data|holes> " 102*fa9e4066Sahrens "visitation order\n"); 103*fa9e4066Sahrens (void) fprintf(stderr, " -U use zpool.cache in /tmp\n"); 104*fa9e4066Sahrens (void) fprintf(stderr, " -B objset:object:level:blkid -- " 105*fa9e4066Sahrens "simulate bad block\n"); 106*fa9e4066Sahrens (void) fprintf(stderr, "Specify an option more than once (e.g. -bb) " 107*fa9e4066Sahrens "to make only that option verbose\n"); 108*fa9e4066Sahrens (void) fprintf(stderr, "Default is to dump everything non-verbosely\n"); 109*fa9e4066Sahrens exit(1); 110*fa9e4066Sahrens } 111*fa9e4066Sahrens 112*fa9e4066Sahrens static void 113*fa9e4066Sahrens fatal(const char *fmt, ...) 114*fa9e4066Sahrens { 115*fa9e4066Sahrens va_list ap; 116*fa9e4066Sahrens 117*fa9e4066Sahrens va_start(ap, fmt); 118*fa9e4066Sahrens (void) fprintf(stderr, "%s: ", cmdname); 119*fa9e4066Sahrens (void) vfprintf(stderr, fmt, ap); 120*fa9e4066Sahrens va_end(ap); 121*fa9e4066Sahrens (void) fprintf(stderr, "\n"); 122*fa9e4066Sahrens 123*fa9e4066Sahrens exit(1); 124*fa9e4066Sahrens } 125*fa9e4066Sahrens 126*fa9e4066Sahrens static void 127*fa9e4066Sahrens dump_nvlist(nvlist_t *list, int indent) 128*fa9e4066Sahrens { 129*fa9e4066Sahrens nvpair_t *elem = NULL; 130*fa9e4066Sahrens 131*fa9e4066Sahrens while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 132*fa9e4066Sahrens switch (nvpair_type(elem)) { 133*fa9e4066Sahrens case DATA_TYPE_STRING: 134*fa9e4066Sahrens { 135*fa9e4066Sahrens char *value; 136*fa9e4066Sahrens 137*fa9e4066Sahrens VERIFY(nvpair_value_string(elem, &value) == 0); 138*fa9e4066Sahrens (void) printf("%*s%s='%s'\n", indent, "", 139*fa9e4066Sahrens nvpair_name(elem), value); 140*fa9e4066Sahrens } 141*fa9e4066Sahrens break; 142*fa9e4066Sahrens 143*fa9e4066Sahrens case DATA_TYPE_UINT64: 144*fa9e4066Sahrens { 145*fa9e4066Sahrens uint64_t value; 146*fa9e4066Sahrens 147*fa9e4066Sahrens VERIFY(nvpair_value_uint64(elem, &value) == 0); 148*fa9e4066Sahrens (void) printf("%*s%s=%llu\n", indent, "", 149*fa9e4066Sahrens nvpair_name(elem), (u_longlong_t)value); 150*fa9e4066Sahrens } 151*fa9e4066Sahrens break; 152*fa9e4066Sahrens 153*fa9e4066Sahrens case DATA_TYPE_NVLIST: 154*fa9e4066Sahrens { 155*fa9e4066Sahrens nvlist_t *value; 156*fa9e4066Sahrens 157*fa9e4066Sahrens VERIFY(nvpair_value_nvlist(elem, &value) == 0); 158*fa9e4066Sahrens (void) printf("%*s%s\n", indent, "", 159*fa9e4066Sahrens nvpair_name(elem)); 160*fa9e4066Sahrens dump_nvlist(value, indent + 4); 161*fa9e4066Sahrens } 162*fa9e4066Sahrens break; 163*fa9e4066Sahrens 164*fa9e4066Sahrens case DATA_TYPE_NVLIST_ARRAY: 165*fa9e4066Sahrens { 166*fa9e4066Sahrens nvlist_t **value; 167*fa9e4066Sahrens uint_t c, count; 168*fa9e4066Sahrens 169*fa9e4066Sahrens VERIFY(nvpair_value_nvlist_array(elem, &value, 170*fa9e4066Sahrens &count) == 0); 171*fa9e4066Sahrens 172*fa9e4066Sahrens for (c = 0; c < count; c++) { 173*fa9e4066Sahrens (void) printf("%*s%s[%u]\n", indent, "", 174*fa9e4066Sahrens nvpair_name(elem), c); 175*fa9e4066Sahrens dump_nvlist(value[c], indent + 8); 176*fa9e4066Sahrens } 177*fa9e4066Sahrens } 178*fa9e4066Sahrens break; 179*fa9e4066Sahrens 180*fa9e4066Sahrens default: 181*fa9e4066Sahrens 182*fa9e4066Sahrens (void) printf("bad config type %d for %s\n", 183*fa9e4066Sahrens nvpair_type(elem), nvpair_name(elem)); 184*fa9e4066Sahrens } 185*fa9e4066Sahrens } 186*fa9e4066Sahrens } 187*fa9e4066Sahrens 188*fa9e4066Sahrens /* ARGSUSED */ 189*fa9e4066Sahrens static void 190*fa9e4066Sahrens dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size) 191*fa9e4066Sahrens { 192*fa9e4066Sahrens nvlist_t *nv; 193*fa9e4066Sahrens size_t nvsize = *(uint64_t *)data; 194*fa9e4066Sahrens char *packed = umem_alloc(nvsize, UMEM_NOFAIL); 195*fa9e4066Sahrens 196*fa9e4066Sahrens dmu_read(os, object, 0, nvsize, packed); 197*fa9e4066Sahrens 198*fa9e4066Sahrens VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0); 199*fa9e4066Sahrens 200*fa9e4066Sahrens umem_free(packed, nvsize); 201*fa9e4066Sahrens 202*fa9e4066Sahrens dump_nvlist(nv, 8); 203*fa9e4066Sahrens 204*fa9e4066Sahrens nvlist_free(nv); 205*fa9e4066Sahrens } 206*fa9e4066Sahrens 207*fa9e4066Sahrens const char dump_zap_stars[] = "****************************************"; 208*fa9e4066Sahrens const int dump_zap_width = sizeof (dump_zap_stars) - 1; 209*fa9e4066Sahrens 210*fa9e4066Sahrens static void 211*fa9e4066Sahrens dump_zap_histogram(uint64_t histo[ZAP_HISTOGRAM_SIZE]) 212*fa9e4066Sahrens { 213*fa9e4066Sahrens int i; 214*fa9e4066Sahrens int minidx = ZAP_HISTOGRAM_SIZE - 1; 215*fa9e4066Sahrens int maxidx = 0; 216*fa9e4066Sahrens uint64_t max = 0; 217*fa9e4066Sahrens 218*fa9e4066Sahrens for (i = 0; i < ZAP_HISTOGRAM_SIZE; i++) { 219*fa9e4066Sahrens if (histo[i] > max) 220*fa9e4066Sahrens max = histo[i]; 221*fa9e4066Sahrens if (histo[i] > 0 && i > maxidx) 222*fa9e4066Sahrens maxidx = i; 223*fa9e4066Sahrens if (histo[i] > 0 && i < minidx) 224*fa9e4066Sahrens minidx = i; 225*fa9e4066Sahrens } 226*fa9e4066Sahrens 227*fa9e4066Sahrens if (max < dump_zap_width) 228*fa9e4066Sahrens max = dump_zap_width; 229*fa9e4066Sahrens 230*fa9e4066Sahrens for (i = minidx; i <= maxidx; i++) 231*fa9e4066Sahrens (void) printf("\t\t\t%u: %6llu %s\n", i, (u_longlong_t)histo[i], 232*fa9e4066Sahrens &dump_zap_stars[(max - histo[i]) * dump_zap_width / max]); 233*fa9e4066Sahrens } 234*fa9e4066Sahrens 235*fa9e4066Sahrens static void 236*fa9e4066Sahrens dump_zap_stats(objset_t *os, uint64_t object) 237*fa9e4066Sahrens { 238*fa9e4066Sahrens int error; 239*fa9e4066Sahrens zap_stats_t zs; 240*fa9e4066Sahrens 241*fa9e4066Sahrens error = zap_get_stats(os, object, &zs); 242*fa9e4066Sahrens if (error) 243*fa9e4066Sahrens return; 244*fa9e4066Sahrens 245*fa9e4066Sahrens if (zs.zs_ptrtbl_len == 0) { 246*fa9e4066Sahrens ASSERT(zs.zs_num_blocks == 1); 247*fa9e4066Sahrens (void) printf("\tmicrozap: %llu bytes, %llu entries\n", 248*fa9e4066Sahrens (u_longlong_t)zs.zs_blocksize, 249*fa9e4066Sahrens (u_longlong_t)zs.zs_num_entries); 250*fa9e4066Sahrens return; 251*fa9e4066Sahrens } 252*fa9e4066Sahrens 253*fa9e4066Sahrens (void) printf("\tFat ZAP stats:\n"); 254*fa9e4066Sahrens (void) printf("\t\tPointer table: %llu elements\n", 255*fa9e4066Sahrens (u_longlong_t)zs.zs_ptrtbl_len); 256*fa9e4066Sahrens (void) printf("\t\tZAP entries: %llu\n", 257*fa9e4066Sahrens (u_longlong_t)zs.zs_num_entries); 258*fa9e4066Sahrens (void) printf("\t\tLeaf blocks: %llu\n", 259*fa9e4066Sahrens (u_longlong_t)zs.zs_num_leafs); 260*fa9e4066Sahrens (void) printf("\t\tTotal blocks: %llu\n", 261*fa9e4066Sahrens (u_longlong_t)zs.zs_num_blocks); 262*fa9e4066Sahrens (void) printf("\t\tOversize blocks: %llu\n", 263*fa9e4066Sahrens (u_longlong_t)zs.zs_num_blocks_large); 264*fa9e4066Sahrens 265*fa9e4066Sahrens (void) printf("\t\tLeafs with 2^n pointers:\n"); 266*fa9e4066Sahrens dump_zap_histogram(zs.zs_leafs_with_2n_pointers); 267*fa9e4066Sahrens 268*fa9e4066Sahrens (void) printf("\t\tLeafs with n chained:\n"); 269*fa9e4066Sahrens dump_zap_histogram(zs.zs_leafs_with_n_chained); 270*fa9e4066Sahrens 271*fa9e4066Sahrens (void) printf("\t\tBlocks with n*5 entries:\n"); 272*fa9e4066Sahrens dump_zap_histogram(zs.zs_blocks_with_n5_entries); 273*fa9e4066Sahrens 274*fa9e4066Sahrens (void) printf("\t\tBlocks n/10 full:\n"); 275*fa9e4066Sahrens dump_zap_histogram(zs.zs_blocks_n_tenths_full); 276*fa9e4066Sahrens 277*fa9e4066Sahrens (void) printf("\t\tEntries with n chunks:\n"); 278*fa9e4066Sahrens dump_zap_histogram(zs.zs_entries_using_n_chunks); 279*fa9e4066Sahrens 280*fa9e4066Sahrens (void) printf("\t\tBuckets with n entries:\n"); 281*fa9e4066Sahrens dump_zap_histogram(zs.zs_buckets_with_n_entries); 282*fa9e4066Sahrens } 283*fa9e4066Sahrens 284*fa9e4066Sahrens /*ARGSUSED*/ 285*fa9e4066Sahrens static void 286*fa9e4066Sahrens dump_none(objset_t *os, uint64_t object, void *data, size_t size) 287*fa9e4066Sahrens { 288*fa9e4066Sahrens } 289*fa9e4066Sahrens 290*fa9e4066Sahrens /*ARGSUSED*/ 291*fa9e4066Sahrens void 292*fa9e4066Sahrens dump_uint8(objset_t *os, uint64_t object, void *data, size_t size) 293*fa9e4066Sahrens { 294*fa9e4066Sahrens } 295*fa9e4066Sahrens 296*fa9e4066Sahrens /*ARGSUSED*/ 297*fa9e4066Sahrens static void 298*fa9e4066Sahrens dump_uint64(objset_t *os, uint64_t object, void *data, size_t size) 299*fa9e4066Sahrens { 300*fa9e4066Sahrens } 301*fa9e4066Sahrens 302*fa9e4066Sahrens /*ARGSUSED*/ 303*fa9e4066Sahrens static void 304*fa9e4066Sahrens dump_zap(objset_t *os, uint64_t object, void *data, size_t size) 305*fa9e4066Sahrens { 306*fa9e4066Sahrens zap_cursor_t zc; 307*fa9e4066Sahrens zap_attribute_t attr; 308*fa9e4066Sahrens void *prop; 309*fa9e4066Sahrens int i; 310*fa9e4066Sahrens 311*fa9e4066Sahrens dump_zap_stats(os, object); 312*fa9e4066Sahrens (void) printf("\n"); 313*fa9e4066Sahrens 314*fa9e4066Sahrens for (zap_cursor_init(&zc, os, object); 315*fa9e4066Sahrens zap_cursor_retrieve(&zc, &attr) == 0; 316*fa9e4066Sahrens zap_cursor_advance(&zc)) { 317*fa9e4066Sahrens (void) printf("\t\t%s = ", attr.za_name); 318*fa9e4066Sahrens if (attr.za_num_integers == 0) { 319*fa9e4066Sahrens (void) printf("\n"); 320*fa9e4066Sahrens continue; 321*fa9e4066Sahrens } 322*fa9e4066Sahrens prop = umem_zalloc(attr.za_num_integers * 323*fa9e4066Sahrens attr.za_integer_length, UMEM_NOFAIL); 324*fa9e4066Sahrens (void) zap_lookup(os, object, attr.za_name, 325*fa9e4066Sahrens attr.za_integer_length, attr.za_num_integers, prop); 326*fa9e4066Sahrens if (attr.za_integer_length == 1) { 327*fa9e4066Sahrens (void) printf("%s", (char *)prop); 328*fa9e4066Sahrens } else { 329*fa9e4066Sahrens for (i = 0; i < attr.za_num_integers; i++) { 330*fa9e4066Sahrens switch (attr.za_integer_length) { 331*fa9e4066Sahrens case 2: 332*fa9e4066Sahrens (void) printf("%u ", 333*fa9e4066Sahrens ((uint16_t *)prop)[i]); 334*fa9e4066Sahrens break; 335*fa9e4066Sahrens case 4: 336*fa9e4066Sahrens (void) printf("%u ", 337*fa9e4066Sahrens ((uint32_t *)prop)[i]); 338*fa9e4066Sahrens break; 339*fa9e4066Sahrens case 8: 340*fa9e4066Sahrens (void) printf("%lld ", 341*fa9e4066Sahrens (u_longlong_t)((int64_t *)prop)[i]); 342*fa9e4066Sahrens break; 343*fa9e4066Sahrens } 344*fa9e4066Sahrens } 345*fa9e4066Sahrens } 346*fa9e4066Sahrens (void) printf("\n"); 347*fa9e4066Sahrens umem_free(prop, attr.za_num_integers * attr.za_integer_length); 348*fa9e4066Sahrens } 349*fa9e4066Sahrens } 350*fa9e4066Sahrens 351*fa9e4066Sahrens static void 352*fa9e4066Sahrens dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm) 353*fa9e4066Sahrens { 354*fa9e4066Sahrens uint64_t alloc, offset, entry; 355*fa9e4066Sahrens int mapshift = sm->sm_shift; 356*fa9e4066Sahrens uint64_t mapstart = sm->sm_start; 357*fa9e4066Sahrens char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID" }; 358*fa9e4066Sahrens 359*fa9e4066Sahrens if (smo->smo_object == 0) 360*fa9e4066Sahrens return; 361*fa9e4066Sahrens 362*fa9e4066Sahrens /* 363*fa9e4066Sahrens * Print out the freelist entries in both encoded and decoded form. 364*fa9e4066Sahrens */ 365*fa9e4066Sahrens alloc = 0; 366*fa9e4066Sahrens for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) { 367*fa9e4066Sahrens dmu_read(os, smo->smo_object, offset, sizeof (entry), &entry); 368*fa9e4066Sahrens if (SM_DEBUG_DECODE(entry)) { 369*fa9e4066Sahrens (void) printf("\t\t[%4llu] %s: txg %llu, pass %llu\n", 370*fa9e4066Sahrens (u_longlong_t)(offset / sizeof (entry)), 371*fa9e4066Sahrens ddata[SM_DEBUG_ACTION_DECODE(entry)], 372*fa9e4066Sahrens SM_DEBUG_TXG_DECODE(entry), 373*fa9e4066Sahrens SM_DEBUG_SYNCPASS_DECODE(entry)); 374*fa9e4066Sahrens } else { 375*fa9e4066Sahrens (void) printf("\t\t[%4llu] %c range:" 376*fa9e4066Sahrens " %08llx-%08llx size: %06llx\n", 377*fa9e4066Sahrens (u_longlong_t)(offset / sizeof (entry)), 378*fa9e4066Sahrens SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 379*fa9e4066Sahrens (SM_OFFSET_DECODE(entry) << mapshift) + mapstart, 380*fa9e4066Sahrens (SM_OFFSET_DECODE(entry) << mapshift) + mapstart + 381*fa9e4066Sahrens (SM_RUN_DECODE(entry) << mapshift), 382*fa9e4066Sahrens (SM_RUN_DECODE(entry) << mapshift)); 383*fa9e4066Sahrens if (SM_TYPE_DECODE(entry) == SM_ALLOC) 384*fa9e4066Sahrens alloc += SM_RUN_DECODE(entry) << mapshift; 385*fa9e4066Sahrens else 386*fa9e4066Sahrens alloc -= SM_RUN_DECODE(entry) << mapshift; 387*fa9e4066Sahrens } 388*fa9e4066Sahrens } 389*fa9e4066Sahrens if (alloc != smo->smo_alloc) { 390*fa9e4066Sahrens (void) printf("space_map_object alloc (%llu) INCONSISTENT " 391*fa9e4066Sahrens "with space map summary (%llu)\n", 392*fa9e4066Sahrens (u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc); 393*fa9e4066Sahrens } 394*fa9e4066Sahrens } 395*fa9e4066Sahrens 396*fa9e4066Sahrens static void 397*fa9e4066Sahrens dump_metaslab(metaslab_t *msp) 398*fa9e4066Sahrens { 399*fa9e4066Sahrens char freebuf[5]; 400*fa9e4066Sahrens space_map_obj_t *smo = msp->ms_smo; 401*fa9e4066Sahrens vdev_t *vd = msp->ms_group->mg_vd; 402*fa9e4066Sahrens spa_t *spa = vd->vdev_spa; 403*fa9e4066Sahrens 404*fa9e4066Sahrens nicenum(msp->ms_map.sm_size - smo->smo_alloc, freebuf); 405*fa9e4066Sahrens 406*fa9e4066Sahrens if (dump_opt['d'] <= 5) { 407*fa9e4066Sahrens (void) printf("\t%10llx %10llu %5s\n", 408*fa9e4066Sahrens (u_longlong_t)msp->ms_map.sm_start, 409*fa9e4066Sahrens (u_longlong_t)smo->smo_object, 410*fa9e4066Sahrens freebuf); 411*fa9e4066Sahrens return; 412*fa9e4066Sahrens } 413*fa9e4066Sahrens 414*fa9e4066Sahrens (void) printf( 415*fa9e4066Sahrens "\tvdev %llu offset %08llx spacemap %4llu free %5s\n", 416*fa9e4066Sahrens (u_longlong_t)vd->vdev_id, (u_longlong_t)msp->ms_map.sm_start, 417*fa9e4066Sahrens (u_longlong_t)smo->smo_object, freebuf); 418*fa9e4066Sahrens 419*fa9e4066Sahrens ASSERT(msp->ms_map.sm_size == (1ULL << vd->vdev_ms_shift)); 420*fa9e4066Sahrens 421*fa9e4066Sahrens dump_spacemap(spa->spa_meta_objset, smo, &msp->ms_map); 422*fa9e4066Sahrens } 423*fa9e4066Sahrens 424*fa9e4066Sahrens static void 425*fa9e4066Sahrens dump_metaslabs(spa_t *spa) 426*fa9e4066Sahrens { 427*fa9e4066Sahrens vdev_t *rvd = spa->spa_root_vdev; 428*fa9e4066Sahrens vdev_t *vd; 429*fa9e4066Sahrens int c, m; 430*fa9e4066Sahrens 431*fa9e4066Sahrens (void) printf("\nMetaslabs:\n"); 432*fa9e4066Sahrens 433*fa9e4066Sahrens for (c = 0; c < rvd->vdev_children; c++) { 434*fa9e4066Sahrens vd = rvd->vdev_child[c]; 435*fa9e4066Sahrens 436*fa9e4066Sahrens spa_config_enter(spa, RW_READER); 437*fa9e4066Sahrens (void) printf("\n vdev %llu = %s\n\n", 438*fa9e4066Sahrens (u_longlong_t)vd->vdev_id, vdev_description(vd)); 439*fa9e4066Sahrens spa_config_exit(spa); 440*fa9e4066Sahrens 441*fa9e4066Sahrens if (dump_opt['d'] <= 5) { 442*fa9e4066Sahrens (void) printf("\t%10s %10s %5s\n", 443*fa9e4066Sahrens "offset", "spacemap", "free"); 444*fa9e4066Sahrens (void) printf("\t%10s %10s %5s\n", 445*fa9e4066Sahrens "------", "--------", "----"); 446*fa9e4066Sahrens } 447*fa9e4066Sahrens for (m = 0; m < vd->vdev_ms_count; m++) 448*fa9e4066Sahrens dump_metaslab(vd->vdev_ms[m]); 449*fa9e4066Sahrens (void) printf("\n"); 450*fa9e4066Sahrens } 451*fa9e4066Sahrens } 452*fa9e4066Sahrens 453*fa9e4066Sahrens static void 454*fa9e4066Sahrens dump_dtl(vdev_t *vd, int indent) 455*fa9e4066Sahrens { 456*fa9e4066Sahrens avl_tree_t *t = &vd->vdev_dtl_map.sm_root; 457*fa9e4066Sahrens spa_t *spa = vd->vdev_spa; 458*fa9e4066Sahrens space_seg_t *ss; 459*fa9e4066Sahrens vdev_t *pvd; 460*fa9e4066Sahrens int c; 461*fa9e4066Sahrens 462*fa9e4066Sahrens if (indent == 0) 463*fa9e4066Sahrens (void) printf("\nDirty time logs:\n\n"); 464*fa9e4066Sahrens 465*fa9e4066Sahrens spa_config_enter(spa, RW_READER); 466*fa9e4066Sahrens (void) printf("\t%*s%s\n", indent, "", vdev_description(vd)); 467*fa9e4066Sahrens spa_config_exit(spa); 468*fa9e4066Sahrens 469*fa9e4066Sahrens for (ss = avl_first(t); ss; ss = AVL_NEXT(t, ss)) { 470*fa9e4066Sahrens /* 471*fa9e4066Sahrens * Everything in this DTL must appear in all parent DTL unions. 472*fa9e4066Sahrens */ 473*fa9e4066Sahrens for (pvd = vd; pvd; pvd = pvd->vdev_parent) 474*fa9e4066Sahrens ASSERT(vdev_dtl_contains(&pvd->vdev_dtl_map, 475*fa9e4066Sahrens ss->ss_start, ss->ss_end - ss->ss_start)); 476*fa9e4066Sahrens (void) printf("\t%*soutage [%llu,%llu] length %llu\n", 477*fa9e4066Sahrens indent, "", 478*fa9e4066Sahrens (u_longlong_t)ss->ss_start, 479*fa9e4066Sahrens (u_longlong_t)ss->ss_end - 1, 480*fa9e4066Sahrens (u_longlong_t)ss->ss_end - ss->ss_start); 481*fa9e4066Sahrens } 482*fa9e4066Sahrens 483*fa9e4066Sahrens (void) printf("\n"); 484*fa9e4066Sahrens 485*fa9e4066Sahrens if (dump_opt['d'] > 5 && vd->vdev_children == 0) { 486*fa9e4066Sahrens dump_spacemap(vd->vdev_spa->spa_meta_objset, &vd->vdev_dtl, 487*fa9e4066Sahrens &vd->vdev_dtl_map); 488*fa9e4066Sahrens (void) printf("\n"); 489*fa9e4066Sahrens } 490*fa9e4066Sahrens 491*fa9e4066Sahrens for (c = 0; c < vd->vdev_children; c++) 492*fa9e4066Sahrens dump_dtl(vd->vdev_child[c], indent + 4); 493*fa9e4066Sahrens } 494*fa9e4066Sahrens 495*fa9e4066Sahrens /*ARGSUSED*/ 496*fa9e4066Sahrens static void 497*fa9e4066Sahrens dump_dnode(objset_t *os, uint64_t object, void *data, size_t size) 498*fa9e4066Sahrens { 499*fa9e4066Sahrens } 500*fa9e4066Sahrens 501*fa9e4066Sahrens static uint64_t 502*fa9e4066Sahrens blkid2offset(dnode_phys_t *dnp, int level, uint64_t blkid) 503*fa9e4066Sahrens { 504*fa9e4066Sahrens if (level < 0) 505*fa9e4066Sahrens return (blkid); 506*fa9e4066Sahrens 507*fa9e4066Sahrens return ((blkid << (level * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) * 508*fa9e4066Sahrens dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT); 509*fa9e4066Sahrens } 510*fa9e4066Sahrens 511*fa9e4066Sahrens /* ARGSUSED */ 512*fa9e4066Sahrens static int 513*fa9e4066Sahrens zdb_indirect_cb(traverse_blk_cache_t *bc, spa_t *spa, void *a) 514*fa9e4066Sahrens { 515*fa9e4066Sahrens zbookmark_t *zb = &bc->bc_bookmark; 516*fa9e4066Sahrens blkptr_t *bp = &bc->bc_blkptr; 517*fa9e4066Sahrens dva_t *dva = &bp->blk_dva[0]; 518*fa9e4066Sahrens void *data = bc->bc_data; 519*fa9e4066Sahrens dnode_phys_t *dnp = bc->bc_dnode; 520*fa9e4066Sahrens char buffer[300]; 521*fa9e4066Sahrens int l; 522*fa9e4066Sahrens 523*fa9e4066Sahrens if (bc->bc_errno) { 524*fa9e4066Sahrens (void) sprintf(buffer, 525*fa9e4066Sahrens "Error %d reading <%llu, %llu, %d, %llu>: ", 526*fa9e4066Sahrens bc->bc_errno, 527*fa9e4066Sahrens (u_longlong_t)zb->zb_objset, 528*fa9e4066Sahrens (u_longlong_t)zb->zb_object, 529*fa9e4066Sahrens zb->zb_level, 530*fa9e4066Sahrens (u_longlong_t)zb->zb_blkid); 531*fa9e4066Sahrens goto out; 532*fa9e4066Sahrens } 533*fa9e4066Sahrens 534*fa9e4066Sahrens if (zb->zb_level == -1) { 535*fa9e4066Sahrens ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_OBJSET); 536*fa9e4066Sahrens ASSERT3U(BP_GET_LEVEL(bp), ==, 0); 537*fa9e4066Sahrens } else { 538*fa9e4066Sahrens ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type); 539*fa9e4066Sahrens ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level); 540*fa9e4066Sahrens } 541*fa9e4066Sahrens 542*fa9e4066Sahrens if (zb->zb_level > 0) { 543*fa9e4066Sahrens uint64_t fill = 0; 544*fa9e4066Sahrens blkptr_t *bpx, *bpend; 545*fa9e4066Sahrens 546*fa9e4066Sahrens for (bpx = data, bpend = bpx + BP_GET_LSIZE(bp) / sizeof (*bpx); 547*fa9e4066Sahrens bpx < bpend; bpx++) { 548*fa9e4066Sahrens if (bpx->blk_birth != 0) { 549*fa9e4066Sahrens ASSERT(bpx->blk_fill > 0); 550*fa9e4066Sahrens fill += bpx->blk_fill; 551*fa9e4066Sahrens } else { 552*fa9e4066Sahrens ASSERT(bpx->blk_fill == 0); 553*fa9e4066Sahrens } 554*fa9e4066Sahrens } 555*fa9e4066Sahrens ASSERT3U(fill, ==, bp->blk_fill); 556*fa9e4066Sahrens } 557*fa9e4066Sahrens 558*fa9e4066Sahrens if (zb->zb_level == 0 && dnp->dn_type == DMU_OT_DNODE) { 559*fa9e4066Sahrens uint64_t fill = 0; 560*fa9e4066Sahrens dnode_phys_t *dnx, *dnend; 561*fa9e4066Sahrens 562*fa9e4066Sahrens for (dnx = data, dnend = dnx + (BP_GET_LSIZE(bp)>>DNODE_SHIFT); 563*fa9e4066Sahrens dnx < dnend; dnx++) { 564*fa9e4066Sahrens if (dnx->dn_type != DMU_OT_NONE) 565*fa9e4066Sahrens fill++; 566*fa9e4066Sahrens } 567*fa9e4066Sahrens ASSERT3U(fill, ==, bp->blk_fill); 568*fa9e4066Sahrens } 569*fa9e4066Sahrens 570*fa9e4066Sahrens (void) sprintf(buffer, "%16llx ", 571*fa9e4066Sahrens (u_longlong_t)blkid2offset(dnp, zb->zb_level, zb->zb_blkid)); 572*fa9e4066Sahrens 573*fa9e4066Sahrens ASSERT(zb->zb_level >= 0); 574*fa9e4066Sahrens 575*fa9e4066Sahrens for (l = dnp->dn_nlevels - 1; l >= -1; l--) { 576*fa9e4066Sahrens if (l == zb->zb_level) { 577*fa9e4066Sahrens (void) sprintf(buffer + strlen(buffer), "L%x", 578*fa9e4066Sahrens zb->zb_level); 579*fa9e4066Sahrens } else { 580*fa9e4066Sahrens (void) sprintf(buffer + strlen(buffer), " "); 581*fa9e4066Sahrens } 582*fa9e4066Sahrens } 583*fa9e4066Sahrens 584*fa9e4066Sahrens out: 585*fa9e4066Sahrens if (bp->blk_birth == 0) { 586*fa9e4066Sahrens (void) sprintf(buffer + strlen(buffer), "<hole>"); 587*fa9e4066Sahrens (void) printf("%s\n", buffer); 588*fa9e4066Sahrens } else { 589*fa9e4066Sahrens // XXBP - Need to print number of active BPs here 590*fa9e4066Sahrens (void) sprintf(buffer + strlen(buffer), 591*fa9e4066Sahrens "vdev=%llu off=%llx %llxL/%llxP/%llxA F=%llu B=%llu", 592*fa9e4066Sahrens (u_longlong_t)DVA_GET_VDEV(dva), 593*fa9e4066Sahrens (u_longlong_t)DVA_GET_OFFSET(dva), 594*fa9e4066Sahrens (u_longlong_t)BP_GET_LSIZE(bp), 595*fa9e4066Sahrens (u_longlong_t)BP_GET_PSIZE(bp), 596*fa9e4066Sahrens (u_longlong_t)DVA_GET_ASIZE(dva), 597*fa9e4066Sahrens (u_longlong_t)bp->blk_fill, 598*fa9e4066Sahrens (u_longlong_t)bp->blk_birth); 599*fa9e4066Sahrens 600*fa9e4066Sahrens (void) printf("%s\n", buffer); 601*fa9e4066Sahrens } 602*fa9e4066Sahrens 603*fa9e4066Sahrens return (bc->bc_errno ? ERESTART : 0); 604*fa9e4066Sahrens } 605*fa9e4066Sahrens 606*fa9e4066Sahrens /*ARGSUSED*/ 607*fa9e4066Sahrens static void 608*fa9e4066Sahrens dump_indirect(objset_t *os, uint64_t object, void *data, size_t size) 609*fa9e4066Sahrens { 610*fa9e4066Sahrens traverse_handle_t *th; 611*fa9e4066Sahrens uint64_t objset = dmu_objset_id(os); 612*fa9e4066Sahrens int advance = zdb_advance; 613*fa9e4066Sahrens 614*fa9e4066Sahrens (void) printf("Indirect blocks:\n"); 615*fa9e4066Sahrens 616*fa9e4066Sahrens if (object == 0) 617*fa9e4066Sahrens advance |= ADVANCE_DATA; 618*fa9e4066Sahrens 619*fa9e4066Sahrens th = traverse_init(dmu_objset_spa(os), zdb_indirect_cb, NULL, advance, 620*fa9e4066Sahrens ZIO_FLAG_CANFAIL); 621*fa9e4066Sahrens th->th_noread = zdb_noread; 622*fa9e4066Sahrens 623*fa9e4066Sahrens traverse_add_dnode(th, 0, -1ULL, objset, object); 624*fa9e4066Sahrens 625*fa9e4066Sahrens while (traverse_more(th) == EAGAIN) 626*fa9e4066Sahrens continue; 627*fa9e4066Sahrens 628*fa9e4066Sahrens (void) printf("\n"); 629*fa9e4066Sahrens 630*fa9e4066Sahrens traverse_fini(th); 631*fa9e4066Sahrens } 632*fa9e4066Sahrens 633*fa9e4066Sahrens /*ARGSUSED*/ 634*fa9e4066Sahrens static void 635*fa9e4066Sahrens dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size) 636*fa9e4066Sahrens { 637*fa9e4066Sahrens dsl_dir_phys_t *dd = data; 638*fa9e4066Sahrens time_t crtime; 639*fa9e4066Sahrens char used[6], compressed[6], uncompressed[6], quota[6], resv[6]; 640*fa9e4066Sahrens 641*fa9e4066Sahrens if (dd == NULL) 642*fa9e4066Sahrens return; 643*fa9e4066Sahrens 644*fa9e4066Sahrens ASSERT(size == sizeof (*dd)); 645*fa9e4066Sahrens 646*fa9e4066Sahrens crtime = dd->dd_creation_time; 647*fa9e4066Sahrens nicenum(dd->dd_used_bytes, used); 648*fa9e4066Sahrens nicenum(dd->dd_compressed_bytes, compressed); 649*fa9e4066Sahrens nicenum(dd->dd_uncompressed_bytes, uncompressed); 650*fa9e4066Sahrens nicenum(dd->dd_quota, quota); 651*fa9e4066Sahrens nicenum(dd->dd_reserved, resv); 652*fa9e4066Sahrens 653*fa9e4066Sahrens (void) printf("\t\tcreation_time = %s", ctime(&crtime)); 654*fa9e4066Sahrens (void) printf("\t\thead_dataset_obj = %llu\n", 655*fa9e4066Sahrens (u_longlong_t)dd->dd_head_dataset_obj); 656*fa9e4066Sahrens (void) printf("\t\tparent_dir_obj = %llu\n", 657*fa9e4066Sahrens (u_longlong_t)dd->dd_parent_obj); 658*fa9e4066Sahrens (void) printf("\t\tclone_parent_obj = %llu\n", 659*fa9e4066Sahrens (u_longlong_t)dd->dd_clone_parent_obj); 660*fa9e4066Sahrens (void) printf("\t\tchild_dir_zapobj = %llu\n", 661*fa9e4066Sahrens (u_longlong_t)dd->dd_child_dir_zapobj); 662*fa9e4066Sahrens (void) printf("\t\tused_bytes = %s\n", used); 663*fa9e4066Sahrens (void) printf("\t\tcompressed_bytes = %s\n", compressed); 664*fa9e4066Sahrens (void) printf("\t\tuncompressed_bytes = %s\n", uncompressed); 665*fa9e4066Sahrens (void) printf("\t\tquota = %s\n", quota); 666*fa9e4066Sahrens (void) printf("\t\treserved = %s\n", resv); 667*fa9e4066Sahrens (void) printf("\t\tprops_zapobj = %llu\n", 668*fa9e4066Sahrens (u_longlong_t)dd->dd_props_zapobj); 669*fa9e4066Sahrens } 670*fa9e4066Sahrens 671*fa9e4066Sahrens /*ARGSUSED*/ 672*fa9e4066Sahrens static void 673*fa9e4066Sahrens dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size) 674*fa9e4066Sahrens { 675*fa9e4066Sahrens dsl_dataset_phys_t *ds = data; 676*fa9e4066Sahrens time_t crtime; 677*fa9e4066Sahrens char used[6], compressed[6], uncompressed[6], unique[6], blkbuf[300]; 678*fa9e4066Sahrens 679*fa9e4066Sahrens if (ds == NULL) 680*fa9e4066Sahrens return; 681*fa9e4066Sahrens 682*fa9e4066Sahrens ASSERT(size == sizeof (*ds)); 683*fa9e4066Sahrens crtime = ds->ds_creation_time; 684*fa9e4066Sahrens nicenum(ds->ds_used_bytes, used); 685*fa9e4066Sahrens nicenum(ds->ds_compressed_bytes, compressed); 686*fa9e4066Sahrens nicenum(ds->ds_uncompressed_bytes, uncompressed); 687*fa9e4066Sahrens nicenum(ds->ds_unique_bytes, unique); 688*fa9e4066Sahrens sprintf_blkptr(blkbuf, &ds->ds_bp); 689*fa9e4066Sahrens 690*fa9e4066Sahrens (void) printf("\t\tdataset_obj = %llu\n", 691*fa9e4066Sahrens (u_longlong_t)ds->ds_dir_obj); 692*fa9e4066Sahrens (void) printf("\t\tprev_snap_obj = %llu\n", 693*fa9e4066Sahrens (u_longlong_t)ds->ds_prev_snap_obj); 694*fa9e4066Sahrens (void) printf("\t\tprev_snap_txg = %llu\n", 695*fa9e4066Sahrens (u_longlong_t)ds->ds_prev_snap_txg); 696*fa9e4066Sahrens (void) printf("\t\tnext_snap_obj = %llu\n", 697*fa9e4066Sahrens (u_longlong_t)ds->ds_next_snap_obj); 698*fa9e4066Sahrens (void) printf("\t\tsnapnames_zapobj = %llu\n", 699*fa9e4066Sahrens (u_longlong_t)ds->ds_snapnames_zapobj); 700*fa9e4066Sahrens (void) printf("\t\tnum_children = %llu\n", 701*fa9e4066Sahrens (u_longlong_t)ds->ds_num_children); 702*fa9e4066Sahrens (void) printf("\t\tcreation_time = %s", ctime(&crtime)); 703*fa9e4066Sahrens (void) printf("\t\tcreation_txg = %llu\n", 704*fa9e4066Sahrens (u_longlong_t)ds->ds_creation_txg); 705*fa9e4066Sahrens (void) printf("\t\tdeadlist_obj = %llu\n", 706*fa9e4066Sahrens (u_longlong_t)ds->ds_deadlist_obj); 707*fa9e4066Sahrens (void) printf("\t\tused_bytes = %s\n", used); 708*fa9e4066Sahrens (void) printf("\t\tcompressed_bytes = %s\n", compressed); 709*fa9e4066Sahrens (void) printf("\t\tuncompressed_bytes = %s\n", uncompressed); 710*fa9e4066Sahrens (void) printf("\t\tunique = %s\n", unique); 711*fa9e4066Sahrens (void) printf("\t\tfsid_guid = %llu\n", 712*fa9e4066Sahrens (u_longlong_t)ds->ds_fsid_guid); 713*fa9e4066Sahrens (void) printf("\t\tguid = %llu\n", 714*fa9e4066Sahrens (u_longlong_t)ds->ds_guid); 715*fa9e4066Sahrens (void) printf("\t\trestoring = %llu\n", 716*fa9e4066Sahrens (u_longlong_t)ds->ds_restoring); 717*fa9e4066Sahrens (void) printf("\t\tbp = %s\n", blkbuf); 718*fa9e4066Sahrens } 719*fa9e4066Sahrens 720*fa9e4066Sahrens static void 721*fa9e4066Sahrens dump_bplist(objset_t *mos, uint64_t object, char *name) 722*fa9e4066Sahrens { 723*fa9e4066Sahrens bplist_t bpl = { 0 }; 724*fa9e4066Sahrens blkptr_t blk, *bp = &blk; 725*fa9e4066Sahrens uint64_t itor = 0; 726*fa9e4066Sahrens char numbuf[6]; 727*fa9e4066Sahrens 728*fa9e4066Sahrens if (dump_opt['d'] < 3) 729*fa9e4066Sahrens return; 730*fa9e4066Sahrens 731*fa9e4066Sahrens bplist_open(&bpl, mos, object); 732*fa9e4066Sahrens if (bplist_empty(&bpl)) { 733*fa9e4066Sahrens bplist_close(&bpl); 734*fa9e4066Sahrens return; 735*fa9e4066Sahrens } 736*fa9e4066Sahrens 737*fa9e4066Sahrens nicenum(bpl.bpl_phys->bpl_bytes, numbuf); 738*fa9e4066Sahrens 739*fa9e4066Sahrens (void) printf("\n %s: %llu entries, %s\n", 740*fa9e4066Sahrens name, (u_longlong_t)bpl.bpl_phys->bpl_entries, numbuf); 741*fa9e4066Sahrens 742*fa9e4066Sahrens if (dump_opt['d'] < 5) { 743*fa9e4066Sahrens bplist_close(&bpl); 744*fa9e4066Sahrens return; 745*fa9e4066Sahrens } 746*fa9e4066Sahrens 747*fa9e4066Sahrens (void) printf("\n"); 748*fa9e4066Sahrens 749*fa9e4066Sahrens while (bplist_iterate(&bpl, &itor, bp) == 0) { 750*fa9e4066Sahrens ASSERT(bp->blk_birth != 0); 751*fa9e4066Sahrens // XXBP - Do we want to see all DVAs, or just one? 752*fa9e4066Sahrens (void) printf("\tItem %3llu: vdev=%llu off=%llx " 753*fa9e4066Sahrens "%llxL/%llxP/%llxA F=%llu B=%llu\n", 754*fa9e4066Sahrens (u_longlong_t)itor - 1, 755*fa9e4066Sahrens (u_longlong_t)DVA_GET_VDEV(&bp->blk_dva[0]), 756*fa9e4066Sahrens (u_longlong_t)DVA_GET_OFFSET(&bp->blk_dva[0]), 757*fa9e4066Sahrens (u_longlong_t)BP_GET_LSIZE(bp), 758*fa9e4066Sahrens (u_longlong_t)BP_GET_PSIZE(bp), 759*fa9e4066Sahrens (u_longlong_t)DVA_GET_ASIZE(&bp->blk_dva[0]), 760*fa9e4066Sahrens (u_longlong_t)bp->blk_fill, 761*fa9e4066Sahrens (u_longlong_t)bp->blk_birth); 762*fa9e4066Sahrens } 763*fa9e4066Sahrens 764*fa9e4066Sahrens bplist_close(&bpl); 765*fa9e4066Sahrens } 766*fa9e4066Sahrens 767*fa9e4066Sahrens static char * 768*fa9e4066Sahrens znode_path(objset_t *os, uint64_t object, char *pathbuf, size_t size) 769*fa9e4066Sahrens { 770*fa9e4066Sahrens dmu_buf_t *db; 771*fa9e4066Sahrens dmu_object_info_t doi; 772*fa9e4066Sahrens znode_phys_t *zp; 773*fa9e4066Sahrens uint64_t parent = 0; 774*fa9e4066Sahrens size_t complen; 775*fa9e4066Sahrens char component[MAXNAMELEN + 1]; 776*fa9e4066Sahrens char *path; 777*fa9e4066Sahrens 778*fa9e4066Sahrens path = pathbuf + size; 779*fa9e4066Sahrens *--path = '\0'; 780*fa9e4066Sahrens 781*fa9e4066Sahrens for (;;) { 782*fa9e4066Sahrens db = dmu_bonus_hold(os, object); 783*fa9e4066Sahrens if (db == NULL) 784*fa9e4066Sahrens break; 785*fa9e4066Sahrens 786*fa9e4066Sahrens dmu_buf_read(db); 787*fa9e4066Sahrens dmu_object_info_from_db(db, &doi); 788*fa9e4066Sahrens zp = db->db_data; 789*fa9e4066Sahrens parent = zp->zp_parent; 790*fa9e4066Sahrens dmu_buf_rele(db); 791*fa9e4066Sahrens 792*fa9e4066Sahrens if (doi.doi_bonus_type != DMU_OT_ZNODE) 793*fa9e4066Sahrens break; 794*fa9e4066Sahrens 795*fa9e4066Sahrens if (parent == object) { 796*fa9e4066Sahrens if (path[0] != '/') 797*fa9e4066Sahrens *--path = '/'; 798*fa9e4066Sahrens return (path); 799*fa9e4066Sahrens } 800*fa9e4066Sahrens 801*fa9e4066Sahrens if (zap_value_search(os, parent, object, component) != 0) 802*fa9e4066Sahrens break; 803*fa9e4066Sahrens 804*fa9e4066Sahrens complen = strlen(component); 805*fa9e4066Sahrens path -= complen; 806*fa9e4066Sahrens bcopy(component, path, complen); 807*fa9e4066Sahrens *--path = '/'; 808*fa9e4066Sahrens 809*fa9e4066Sahrens object = parent; 810*fa9e4066Sahrens } 811*fa9e4066Sahrens 812*fa9e4066Sahrens (void) sprintf(component, "???<object#%llu>", (u_longlong_t)object); 813*fa9e4066Sahrens 814*fa9e4066Sahrens complen = strlen(component); 815*fa9e4066Sahrens path -= complen; 816*fa9e4066Sahrens bcopy(component, path, complen); 817*fa9e4066Sahrens 818*fa9e4066Sahrens return (path); 819*fa9e4066Sahrens } 820*fa9e4066Sahrens 821*fa9e4066Sahrens /*ARGSUSED*/ 822*fa9e4066Sahrens static void 823*fa9e4066Sahrens dump_znode(objset_t *os, uint64_t object, void *data, size_t size) 824*fa9e4066Sahrens { 825*fa9e4066Sahrens znode_phys_t *zp = data; 826*fa9e4066Sahrens time_t z_crtime, z_atime, z_mtime, z_ctime; 827*fa9e4066Sahrens char path[MAXPATHLEN * 2]; /* allow for xattr and failure prefix */ 828*fa9e4066Sahrens 829*fa9e4066Sahrens ASSERT(size >= sizeof (znode_phys_t)); 830*fa9e4066Sahrens 831*fa9e4066Sahrens if (dump_opt['d'] < 3) { 832*fa9e4066Sahrens (void) printf("\t%s\n", 833*fa9e4066Sahrens znode_path(os, object, path, sizeof (path))); 834*fa9e4066Sahrens return; 835*fa9e4066Sahrens } 836*fa9e4066Sahrens 837*fa9e4066Sahrens z_crtime = (time_t)zp->zp_crtime[0]; 838*fa9e4066Sahrens z_atime = (time_t)zp->zp_atime[0]; 839*fa9e4066Sahrens z_mtime = (time_t)zp->zp_mtime[0]; 840*fa9e4066Sahrens z_ctime = (time_t)zp->zp_ctime[0]; 841*fa9e4066Sahrens 842*fa9e4066Sahrens (void) printf("\tpath %s\n", 843*fa9e4066Sahrens znode_path(os, object, path, sizeof (path))); 844*fa9e4066Sahrens (void) printf("\tatime %s", ctime(&z_atime)); 845*fa9e4066Sahrens (void) printf("\tmtime %s", ctime(&z_mtime)); 846*fa9e4066Sahrens (void) printf("\tctime %s", ctime(&z_ctime)); 847*fa9e4066Sahrens (void) printf("\tcrtime %s", ctime(&z_crtime)); 848*fa9e4066Sahrens (void) printf("\tgen %llu\n", (u_longlong_t)zp->zp_gen); 849*fa9e4066Sahrens (void) printf("\tmode %llo\n", (u_longlong_t)zp->zp_mode); 850*fa9e4066Sahrens (void) printf("\tsize %llu\n", (u_longlong_t)zp->zp_size); 851*fa9e4066Sahrens (void) printf("\tparent %llu\n", (u_longlong_t)zp->zp_parent); 852*fa9e4066Sahrens (void) printf("\tlinks %llu\n", (u_longlong_t)zp->zp_links); 853*fa9e4066Sahrens (void) printf("\txattr %llu\n", (u_longlong_t)zp->zp_xattr); 854*fa9e4066Sahrens (void) printf("\trdev 0x%016llx\n", (u_longlong_t)zp->zp_rdev); 855*fa9e4066Sahrens } 856*fa9e4066Sahrens 857*fa9e4066Sahrens /*ARGSUSED*/ 858*fa9e4066Sahrens static void 859*fa9e4066Sahrens dump_acl(objset_t *os, uint64_t object, void *data, size_t size) 860*fa9e4066Sahrens { 861*fa9e4066Sahrens } 862*fa9e4066Sahrens 863*fa9e4066Sahrens /*ARGSUSED*/ 864*fa9e4066Sahrens static void 865*fa9e4066Sahrens dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size) 866*fa9e4066Sahrens { 867*fa9e4066Sahrens } 868*fa9e4066Sahrens 869*fa9e4066Sahrens static object_viewer_t *object_viewer[DMU_OT_NUMTYPES] = { 870*fa9e4066Sahrens dump_none, /* unallocated */ 871*fa9e4066Sahrens dump_zap, /* object directory */ 872*fa9e4066Sahrens dump_uint64, /* object array */ 873*fa9e4066Sahrens dump_none, /* packed nvlist */ 874*fa9e4066Sahrens dump_packed_nvlist, /* packed nvlist size */ 875*fa9e4066Sahrens dump_none, /* bplist */ 876*fa9e4066Sahrens dump_none, /* bplist header */ 877*fa9e4066Sahrens dump_none, /* SPA space map header */ 878*fa9e4066Sahrens dump_none, /* SPA space map */ 879*fa9e4066Sahrens dump_none, /* ZIL intent log */ 880*fa9e4066Sahrens dump_dnode, /* DMU dnode */ 881*fa9e4066Sahrens dump_dmu_objset, /* DMU objset */ 882*fa9e4066Sahrens dump_dsl_dir, /* DSL directory */ 883*fa9e4066Sahrens dump_zap, /* DSL directory child map */ 884*fa9e4066Sahrens dump_zap, /* DSL dataset snap map */ 885*fa9e4066Sahrens dump_zap, /* DSL props */ 886*fa9e4066Sahrens dump_dsl_dataset, /* DSL dataset */ 887*fa9e4066Sahrens dump_znode, /* ZFS znode */ 888*fa9e4066Sahrens dump_acl, /* ZFS ACL */ 889*fa9e4066Sahrens dump_uint8, /* ZFS plain file */ 890*fa9e4066Sahrens dump_zap, /* ZFS directory */ 891*fa9e4066Sahrens dump_zap, /* ZFS master node */ 892*fa9e4066Sahrens dump_zap, /* ZFS delete queue */ 893*fa9e4066Sahrens dump_uint8, /* zvol object */ 894*fa9e4066Sahrens dump_zap, /* zvol prop */ 895*fa9e4066Sahrens dump_uint8, /* other uint8[] */ 896*fa9e4066Sahrens dump_uint64, /* other uint64[] */ 897*fa9e4066Sahrens dump_zap, /* other ZAP */ 898*fa9e4066Sahrens }; 899*fa9e4066Sahrens 900*fa9e4066Sahrens static void 901*fa9e4066Sahrens dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header) 902*fa9e4066Sahrens { 903*fa9e4066Sahrens dmu_buf_t *db = NULL; 904*fa9e4066Sahrens dmu_object_info_t doi; 905*fa9e4066Sahrens dnode_t *dn; 906*fa9e4066Sahrens void *bonus = NULL; 907*fa9e4066Sahrens size_t bsize = 0; 908*fa9e4066Sahrens char iblk[6], dblk[6], lsize[6], psize[6], bonus_size[6], segsize[6]; 909*fa9e4066Sahrens char aux[50]; 910*fa9e4066Sahrens int error; 911*fa9e4066Sahrens 912*fa9e4066Sahrens if (*print_header) { 913*fa9e4066Sahrens (void) printf("\n Object lvl iblk dblk lsize" 914*fa9e4066Sahrens " psize type\n"); 915*fa9e4066Sahrens *print_header = 0; 916*fa9e4066Sahrens } 917*fa9e4066Sahrens 918*fa9e4066Sahrens if (object == 0) { 919*fa9e4066Sahrens dn = os->os->os_meta_dnode; 920*fa9e4066Sahrens } else { 921*fa9e4066Sahrens db = dmu_bonus_hold(os, object); 922*fa9e4066Sahrens if (db == NULL) 923*fa9e4066Sahrens fatal("dmu_bonus_hold(%llu) failed", object); 924*fa9e4066Sahrens dmu_buf_read(db); 925*fa9e4066Sahrens bonus = db->db_data; 926*fa9e4066Sahrens bsize = db->db_size; 927*fa9e4066Sahrens dn = ((dmu_buf_impl_t *)db)->db_dnode; 928*fa9e4066Sahrens } 929*fa9e4066Sahrens dmu_object_info_from_dnode(dn, &doi); 930*fa9e4066Sahrens 931*fa9e4066Sahrens nicenum(doi.doi_metadata_block_size, iblk); 932*fa9e4066Sahrens nicenum(doi.doi_data_block_size, dblk); 933*fa9e4066Sahrens nicenum(doi.doi_data_block_size * (doi.doi_max_block_offset + 1), 934*fa9e4066Sahrens lsize); 935*fa9e4066Sahrens nicenum(doi.doi_physical_blks << 9, psize); 936*fa9e4066Sahrens nicenum(doi.doi_bonus_size, bonus_size); 937*fa9e4066Sahrens 938*fa9e4066Sahrens aux[0] = '\0'; 939*fa9e4066Sahrens 940*fa9e4066Sahrens if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) 941*fa9e4066Sahrens (void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)", 942*fa9e4066Sahrens zio_checksum_table[doi.doi_checksum].ci_name); 943*fa9e4066Sahrens 944*fa9e4066Sahrens if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) 945*fa9e4066Sahrens (void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)", 946*fa9e4066Sahrens zio_compress_table[doi.doi_compress].ci_name); 947*fa9e4066Sahrens 948*fa9e4066Sahrens (void) printf("%10lld %3u %5s %5s %5s %5s %s%s\n", 949*fa9e4066Sahrens (u_longlong_t)object, doi.doi_indirection, iblk, dblk, lsize, 950*fa9e4066Sahrens psize, dmu_ot[doi.doi_type].ot_name, aux); 951*fa9e4066Sahrens 952*fa9e4066Sahrens if (doi.doi_bonus_type != DMU_OT_NONE && verbosity > 3) { 953*fa9e4066Sahrens (void) printf("%10s %3s %5s %5s %5s %5s %s\n", 954*fa9e4066Sahrens "", "", "", "", bonus_size, "bonus", 955*fa9e4066Sahrens dmu_ot[doi.doi_bonus_type].ot_name); 956*fa9e4066Sahrens } 957*fa9e4066Sahrens 958*fa9e4066Sahrens if (verbosity >= 4) { 959*fa9e4066Sahrens object_viewer[doi.doi_bonus_type](os, object, bonus, bsize); 960*fa9e4066Sahrens object_viewer[doi.doi_type](os, object, NULL, 0); 961*fa9e4066Sahrens *print_header = 1; 962*fa9e4066Sahrens } 963*fa9e4066Sahrens 964*fa9e4066Sahrens if (verbosity >= 5) 965*fa9e4066Sahrens dump_indirect(os, object, NULL, 0); 966*fa9e4066Sahrens 967*fa9e4066Sahrens if (verbosity >= 5) { 968*fa9e4066Sahrens /* 969*fa9e4066Sahrens * Report the list of segments that comprise the object. 970*fa9e4066Sahrens */ 971*fa9e4066Sahrens uint64_t start = 0; 972*fa9e4066Sahrens uint64_t end; 973*fa9e4066Sahrens uint64_t blkfill = 1; 974*fa9e4066Sahrens int minlvl = 1; 975*fa9e4066Sahrens 976*fa9e4066Sahrens if (dn->dn_type == DMU_OT_DNODE) { 977*fa9e4066Sahrens minlvl = 0; 978*fa9e4066Sahrens blkfill = DNODES_PER_BLOCK; 979*fa9e4066Sahrens } 980*fa9e4066Sahrens 981*fa9e4066Sahrens for (;;) { 982*fa9e4066Sahrens error = dnode_next_offset(dn, B_FALSE, &start, minlvl, 983*fa9e4066Sahrens blkfill); 984*fa9e4066Sahrens if (error) 985*fa9e4066Sahrens break; 986*fa9e4066Sahrens end = start; 987*fa9e4066Sahrens error = dnode_next_offset(dn, B_TRUE, &end, minlvl, 988*fa9e4066Sahrens blkfill); 989*fa9e4066Sahrens nicenum(end - start, segsize); 990*fa9e4066Sahrens (void) printf("\t\tsegment [%016llx, %016llx)" 991*fa9e4066Sahrens " size %5s\n", (u_longlong_t)start, 992*fa9e4066Sahrens (u_longlong_t)end, segsize); 993*fa9e4066Sahrens if (error) 994*fa9e4066Sahrens break; 995*fa9e4066Sahrens start = end; 996*fa9e4066Sahrens } 997*fa9e4066Sahrens } 998*fa9e4066Sahrens 999*fa9e4066Sahrens if (db != NULL) 1000*fa9e4066Sahrens dmu_buf_rele(db); 1001*fa9e4066Sahrens } 1002*fa9e4066Sahrens 1003*fa9e4066Sahrens static char *objset_types[DMU_OST_NUMTYPES] = { 1004*fa9e4066Sahrens "NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" }; 1005*fa9e4066Sahrens 1006*fa9e4066Sahrens /*ARGSUSED*/ 1007*fa9e4066Sahrens static void 1008*fa9e4066Sahrens dump_dir(objset_t *os) 1009*fa9e4066Sahrens { 1010*fa9e4066Sahrens dmu_objset_stats_t dds; 1011*fa9e4066Sahrens uint64_t object, object_count; 1012*fa9e4066Sahrens char numbuf[8]; 1013*fa9e4066Sahrens char blkbuf[300]; 1014*fa9e4066Sahrens char osname[MAXNAMELEN]; 1015*fa9e4066Sahrens char *type = "UNKNOWN"; 1016*fa9e4066Sahrens int verbosity = dump_opt['d']; 1017*fa9e4066Sahrens int print_header = 1; 1018*fa9e4066Sahrens int i, error; 1019*fa9e4066Sahrens 1020*fa9e4066Sahrens dmu_objset_stats(os, &dds); 1021*fa9e4066Sahrens 1022*fa9e4066Sahrens if (dds.dds_type < DMU_OST_NUMTYPES) 1023*fa9e4066Sahrens type = objset_types[dds.dds_type]; 1024*fa9e4066Sahrens 1025*fa9e4066Sahrens if (dds.dds_type == DMU_OST_META) { 1026*fa9e4066Sahrens dds.dds_creation_txg = TXG_INITIAL; 1027*fa9e4066Sahrens dds.dds_last_txg = os->os->os_rootbp.blk_birth; 1028*fa9e4066Sahrens dds.dds_objects_used = os->os->os_rootbp.blk_fill; 1029*fa9e4066Sahrens dds.dds_space_refd = 1030*fa9e4066Sahrens os->os->os_spa->spa_dsl_pool->dp_mos_dir->dd_used_bytes; 1031*fa9e4066Sahrens } 1032*fa9e4066Sahrens 1033*fa9e4066Sahrens ASSERT3U(dds.dds_objects_used, ==, os->os->os_rootbp.blk_fill); 1034*fa9e4066Sahrens 1035*fa9e4066Sahrens nicenum(dds.dds_space_refd, numbuf); 1036*fa9e4066Sahrens 1037*fa9e4066Sahrens if (verbosity >= 4) { 1038*fa9e4066Sahrens (void) strcpy(blkbuf, ", rootbp "); 1039*fa9e4066Sahrens sprintf_blkptr(blkbuf + strlen(blkbuf), &os->os->os_rootbp); 1040*fa9e4066Sahrens } else { 1041*fa9e4066Sahrens blkbuf[0] = '\0'; 1042*fa9e4066Sahrens } 1043*fa9e4066Sahrens 1044*fa9e4066Sahrens dmu_objset_name(os, osname); 1045*fa9e4066Sahrens 1046*fa9e4066Sahrens (void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, last_txg %llu, " 1047*fa9e4066Sahrens "%s, %llu objects%s\n", 1048*fa9e4066Sahrens osname, type, (u_longlong_t)dmu_objset_id(os), 1049*fa9e4066Sahrens (u_longlong_t)dds.dds_creation_txg, 1050*fa9e4066Sahrens (u_longlong_t)dds.dds_last_txg, 1051*fa9e4066Sahrens numbuf, 1052*fa9e4066Sahrens (u_longlong_t)dds.dds_objects_used, 1053*fa9e4066Sahrens blkbuf); 1054*fa9e4066Sahrens 1055*fa9e4066Sahrens dump_intent_log(dmu_objset_zil(os)); 1056*fa9e4066Sahrens 1057*fa9e4066Sahrens if (dmu_objset_ds(os) != NULL) 1058*fa9e4066Sahrens dump_bplist(dmu_objset_pool(os)->dp_meta_objset, 1059*fa9e4066Sahrens dmu_objset_ds(os)->ds_phys->ds_deadlist_obj, "Deadlist"); 1060*fa9e4066Sahrens 1061*fa9e4066Sahrens if (verbosity < 2) 1062*fa9e4066Sahrens return; 1063*fa9e4066Sahrens 1064*fa9e4066Sahrens if (zopt_objects != 0) { 1065*fa9e4066Sahrens for (i = 0; i < zopt_objects; i++) 1066*fa9e4066Sahrens dump_object(os, zopt_object[i], verbosity, 1067*fa9e4066Sahrens &print_header); 1068*fa9e4066Sahrens (void) printf("\n"); 1069*fa9e4066Sahrens return; 1070*fa9e4066Sahrens } 1071*fa9e4066Sahrens 1072*fa9e4066Sahrens dump_object(os, 0, verbosity, &print_header); 1073*fa9e4066Sahrens object_count = 1; 1074*fa9e4066Sahrens 1075*fa9e4066Sahrens object = 0; 1076*fa9e4066Sahrens while ((error = dmu_object_next(os, &object, B_FALSE)) == 0) { 1077*fa9e4066Sahrens dump_object(os, object, verbosity, &print_header); 1078*fa9e4066Sahrens object_count++; 1079*fa9e4066Sahrens } 1080*fa9e4066Sahrens 1081*fa9e4066Sahrens ASSERT3U(object_count, ==, dds.dds_objects_used); 1082*fa9e4066Sahrens 1083*fa9e4066Sahrens (void) printf("\n"); 1084*fa9e4066Sahrens 1085*fa9e4066Sahrens if (error != ESRCH) 1086*fa9e4066Sahrens fatal("dmu_object_next() = %d", error); 1087*fa9e4066Sahrens } 1088*fa9e4066Sahrens 1089*fa9e4066Sahrens static void 1090*fa9e4066Sahrens dump_uberblock(uberblock_t *ub) 1091*fa9e4066Sahrens { 1092*fa9e4066Sahrens time_t timestamp = ub->ub_timestamp; 1093*fa9e4066Sahrens 1094*fa9e4066Sahrens (void) printf("Uberblock\n\n"); 1095*fa9e4066Sahrens (void) printf("\tmagic = %016llx\n", (u_longlong_t)ub->ub_magic); 1096*fa9e4066Sahrens (void) printf("\tversion = %llu\n", (u_longlong_t)ub->ub_version); 1097*fa9e4066Sahrens (void) printf("\ttxg = %llu\n", (u_longlong_t)ub->ub_txg); 1098*fa9e4066Sahrens (void) printf("\tguid_sum = %llu\n", (u_longlong_t)ub->ub_guid_sum); 1099*fa9e4066Sahrens (void) printf("\ttimestamp = %llu UTC = %s", 1100*fa9e4066Sahrens (u_longlong_t)ub->ub_timestamp, asctime(localtime(×tamp))); 1101*fa9e4066Sahrens if (dump_opt['u'] >= 3) { 1102*fa9e4066Sahrens char blkbuf[300]; 1103*fa9e4066Sahrens sprintf_blkptr(blkbuf, &ub->ub_rootbp); 1104*fa9e4066Sahrens (void) printf("\trootbp = %s\n", blkbuf); 1105*fa9e4066Sahrens } 1106*fa9e4066Sahrens (void) printf("\n"); 1107*fa9e4066Sahrens } 1108*fa9e4066Sahrens 1109*fa9e4066Sahrens static void 1110*fa9e4066Sahrens dump_config(const char *pool) 1111*fa9e4066Sahrens { 1112*fa9e4066Sahrens spa_t *spa = NULL; 1113*fa9e4066Sahrens 1114*fa9e4066Sahrens mutex_enter(&spa_namespace_lock); 1115*fa9e4066Sahrens while ((spa = spa_next(spa)) != NULL) { 1116*fa9e4066Sahrens if (pool == NULL) 1117*fa9e4066Sahrens (void) printf("%s\n", spa_name(spa)); 1118*fa9e4066Sahrens if (pool == NULL || strcmp(pool, spa_name(spa)) == 0) 1119*fa9e4066Sahrens dump_nvlist(spa->spa_config, 4); 1120*fa9e4066Sahrens } 1121*fa9e4066Sahrens mutex_exit(&spa_namespace_lock); 1122*fa9e4066Sahrens } 1123*fa9e4066Sahrens 1124*fa9e4066Sahrens static void 1125*fa9e4066Sahrens dump_label(const char *dev) 1126*fa9e4066Sahrens { 1127*fa9e4066Sahrens int fd; 1128*fa9e4066Sahrens vdev_label_t label; 1129*fa9e4066Sahrens char *buf = label.vl_vdev_phys.vp_nvlist; 1130*fa9e4066Sahrens size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist); 1131*fa9e4066Sahrens struct stat64 statbuf; 1132*fa9e4066Sahrens uint64_t psize; 1133*fa9e4066Sahrens int l; 1134*fa9e4066Sahrens 1135*fa9e4066Sahrens if ((fd = open(dev, O_RDONLY)) < 0) { 1136*fa9e4066Sahrens (void) printf("cannot open '%s': %s\n", dev, strerror(errno)); 1137*fa9e4066Sahrens exit(1); 1138*fa9e4066Sahrens } 1139*fa9e4066Sahrens 1140*fa9e4066Sahrens if (fstat64(fd, &statbuf) != 0) { 1141*fa9e4066Sahrens (void) printf("failed to stat '%s': %s\n", dev, 1142*fa9e4066Sahrens strerror(errno)); 1143*fa9e4066Sahrens exit(1); 1144*fa9e4066Sahrens } 1145*fa9e4066Sahrens 1146*fa9e4066Sahrens psize = statbuf.st_size; 1147*fa9e4066Sahrens psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t)); 1148*fa9e4066Sahrens 1149*fa9e4066Sahrens for (l = 0; l < VDEV_LABELS; l++) { 1150*fa9e4066Sahrens 1151*fa9e4066Sahrens nvlist_t *config = NULL; 1152*fa9e4066Sahrens 1153*fa9e4066Sahrens (void) printf("--------------------------------------------\n"); 1154*fa9e4066Sahrens (void) printf("LABEL %d\n", l); 1155*fa9e4066Sahrens (void) printf("--------------------------------------------\n"); 1156*fa9e4066Sahrens 1157*fa9e4066Sahrens if (pread(fd, &label, sizeof (label), 1158*fa9e4066Sahrens vdev_label_offset(psize, l, 0)) != sizeof (label)) { 1159*fa9e4066Sahrens (void) printf("failed to read label %d\n", l); 1160*fa9e4066Sahrens continue; 1161*fa9e4066Sahrens } 1162*fa9e4066Sahrens 1163*fa9e4066Sahrens if (nvlist_unpack(buf, buflen, &config, 0) != 0) { 1164*fa9e4066Sahrens (void) printf("failed to unpack label %d\n", l); 1165*fa9e4066Sahrens continue; 1166*fa9e4066Sahrens } 1167*fa9e4066Sahrens dump_nvlist(config, 4); 1168*fa9e4066Sahrens nvlist_free(config); 1169*fa9e4066Sahrens } 1170*fa9e4066Sahrens } 1171*fa9e4066Sahrens 1172*fa9e4066Sahrens /*ARGSUSED*/ 1173*fa9e4066Sahrens static void 1174*fa9e4066Sahrens dump_one_dir(char *dsname, void *arg) 1175*fa9e4066Sahrens { 1176*fa9e4066Sahrens int error; 1177*fa9e4066Sahrens objset_t *os; 1178*fa9e4066Sahrens 1179*fa9e4066Sahrens error = dmu_objset_open(dsname, DMU_OST_ANY, 1180*fa9e4066Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1181*fa9e4066Sahrens if (error) { 1182*fa9e4066Sahrens (void) printf("Could not open %s\n", dsname); 1183*fa9e4066Sahrens return; 1184*fa9e4066Sahrens } 1185*fa9e4066Sahrens dump_dir(os); 1186*fa9e4066Sahrens dmu_objset_close(os); 1187*fa9e4066Sahrens } 1188*fa9e4066Sahrens 1189*fa9e4066Sahrens static void 1190*fa9e4066Sahrens zdb_space_map_load(spa_t *spa) 1191*fa9e4066Sahrens { 1192*fa9e4066Sahrens vdev_t *rvd = spa->spa_root_vdev; 1193*fa9e4066Sahrens vdev_t *vd; 1194*fa9e4066Sahrens int c, m, error; 1195*fa9e4066Sahrens 1196*fa9e4066Sahrens for (c = 0; c < rvd->vdev_children; c++) { 1197*fa9e4066Sahrens vd = rvd->vdev_child[c]; 1198*fa9e4066Sahrens for (m = 0; m < vd->vdev_ms_count; m++) { 1199*fa9e4066Sahrens metaslab_t *msp = vd->vdev_ms[m]; 1200*fa9e4066Sahrens space_map_t *sm = &msp->ms_allocmap[0]; 1201*fa9e4066Sahrens mutex_enter(&msp->ms_lock); 1202*fa9e4066Sahrens error = space_map_load(sm, msp->ms_smo, SM_ALLOC, 1203*fa9e4066Sahrens spa->spa_meta_objset, msp->ms_usable_end, 1204*fa9e4066Sahrens sm->sm_size - msp->ms_usable_space); 1205*fa9e4066Sahrens mutex_exit(&msp->ms_lock); 1206*fa9e4066Sahrens if (error) 1207*fa9e4066Sahrens fatal("%s bad space map #%d, error %d", 1208*fa9e4066Sahrens spa->spa_name, c, error); 1209*fa9e4066Sahrens } 1210*fa9e4066Sahrens } 1211*fa9e4066Sahrens } 1212*fa9e4066Sahrens 1213*fa9e4066Sahrens static int 1214*fa9e4066Sahrens zdb_space_map_claim(spa_t *spa, blkptr_t *bp) 1215*fa9e4066Sahrens { 1216*fa9e4066Sahrens dva_t *dva = &bp->blk_dva[0]; 1217*fa9e4066Sahrens uint64_t vdev = DVA_GET_VDEV(dva); 1218*fa9e4066Sahrens uint64_t offset = DVA_GET_OFFSET(dva); 1219*fa9e4066Sahrens uint64_t size = DVA_GET_ASIZE(dva); 1220*fa9e4066Sahrens vdev_t *vd; 1221*fa9e4066Sahrens metaslab_t *msp; 1222*fa9e4066Sahrens space_map_t *allocmap, *freemap; 1223*fa9e4066Sahrens int error; 1224*fa9e4066Sahrens 1225*fa9e4066Sahrens if ((vd = vdev_lookup_top(spa, vdev)) == NULL) 1226*fa9e4066Sahrens return (ENXIO); 1227*fa9e4066Sahrens 1228*fa9e4066Sahrens if ((offset >> vd->vdev_ms_shift) >= vd->vdev_ms_count) 1229*fa9e4066Sahrens return (ENXIO); 1230*fa9e4066Sahrens 1231*fa9e4066Sahrens if (DVA_GET_GANG(dva)) { 1232*fa9e4066Sahrens zio_gbh_phys_t gbh; 1233*fa9e4066Sahrens blkptr_t blk = *bp; 1234*fa9e4066Sahrens int g; 1235*fa9e4066Sahrens 1236*fa9e4066Sahrens /* LINTED - compile time assert */ 1237*fa9e4066Sahrens ASSERT(sizeof (zio_gbh_phys_t) == SPA_GANGBLOCKSIZE); 1238*fa9e4066Sahrens size = vdev_psize_to_asize(vd, SPA_GANGBLOCKSIZE); 1239*fa9e4066Sahrens DVA_SET_GANG(&blk.blk_dva[0], 0); 1240*fa9e4066Sahrens DVA_SET_ASIZE(&blk.blk_dva[0], size); 1241*fa9e4066Sahrens BP_SET_CHECKSUM(&blk, ZIO_CHECKSUM_GANG_HEADER); 1242*fa9e4066Sahrens BP_SET_PSIZE(&blk, SPA_GANGBLOCKSIZE); 1243*fa9e4066Sahrens BP_SET_LSIZE(&blk, SPA_GANGBLOCKSIZE); 1244*fa9e4066Sahrens BP_SET_COMPRESS(&blk, ZIO_COMPRESS_OFF); 1245*fa9e4066Sahrens error = zio_wait(zio_read(NULL, spa, &blk, 1246*fa9e4066Sahrens &gbh, SPA_GANGBLOCKSIZE, NULL, NULL, 1247*fa9e4066Sahrens ZIO_PRIORITY_SYNC_READ, 1248*fa9e4066Sahrens ZIO_FLAG_CANFAIL | ZIO_FLAG_CONFIG_HELD)); 1249*fa9e4066Sahrens if (error) 1250*fa9e4066Sahrens return (error); 1251*fa9e4066Sahrens if (BP_SHOULD_BYTESWAP(&blk)) 1252*fa9e4066Sahrens byteswap_uint64_array(&gbh, SPA_GANGBLOCKSIZE); 1253*fa9e4066Sahrens for (g = 0; g < SPA_GBH_NBLKPTRS; g++) { 1254*fa9e4066Sahrens if (gbh.zg_blkptr[g].blk_birth == 0) 1255*fa9e4066Sahrens break; 1256*fa9e4066Sahrens error = zdb_space_map_claim(spa, &gbh.zg_blkptr[g]); 1257*fa9e4066Sahrens if (error) 1258*fa9e4066Sahrens return (error); 1259*fa9e4066Sahrens } 1260*fa9e4066Sahrens } 1261*fa9e4066Sahrens 1262*fa9e4066Sahrens msp = vd->vdev_ms[offset >> vd->vdev_ms_shift]; 1263*fa9e4066Sahrens allocmap = &msp->ms_allocmap[0]; 1264*fa9e4066Sahrens freemap = &msp->ms_freemap[0]; 1265*fa9e4066Sahrens 1266*fa9e4066Sahrens mutex_enter(&msp->ms_lock); 1267*fa9e4066Sahrens if (space_map_contains(freemap, offset, size)) { 1268*fa9e4066Sahrens mutex_exit(&msp->ms_lock); 1269*fa9e4066Sahrens return (EAGAIN); /* allocated more than once */ 1270*fa9e4066Sahrens } 1271*fa9e4066Sahrens 1272*fa9e4066Sahrens if (!space_map_contains(allocmap, offset, size)) { 1273*fa9e4066Sahrens mutex_exit(&msp->ms_lock); 1274*fa9e4066Sahrens return (ESTALE); /* not allocated at all */ 1275*fa9e4066Sahrens } 1276*fa9e4066Sahrens 1277*fa9e4066Sahrens space_map_remove(allocmap, offset, size); 1278*fa9e4066Sahrens space_map_add(freemap, offset, size); 1279*fa9e4066Sahrens 1280*fa9e4066Sahrens mutex_exit(&msp->ms_lock); 1281*fa9e4066Sahrens 1282*fa9e4066Sahrens return (0); 1283*fa9e4066Sahrens } 1284*fa9e4066Sahrens 1285*fa9e4066Sahrens static void 1286*fa9e4066Sahrens zdb_leak(space_map_t *sm, uint64_t start, uint64_t size) 1287*fa9e4066Sahrens { 1288*fa9e4066Sahrens metaslab_t *msp; 1289*fa9e4066Sahrens 1290*fa9e4066Sahrens /* LINTED */ 1291*fa9e4066Sahrens msp = (metaslab_t *)((char *)sm - offsetof(metaslab_t, ms_allocmap[0])); 1292*fa9e4066Sahrens 1293*fa9e4066Sahrens (void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n", 1294*fa9e4066Sahrens (u_longlong_t)msp->ms_group->mg_vd->vdev_id, 1295*fa9e4066Sahrens (u_longlong_t)start, 1296*fa9e4066Sahrens (u_longlong_t)size); 1297*fa9e4066Sahrens } 1298*fa9e4066Sahrens 1299*fa9e4066Sahrens static void 1300*fa9e4066Sahrens zdb_space_map_vacate(spa_t *spa) 1301*fa9e4066Sahrens { 1302*fa9e4066Sahrens vdev_t *rvd = spa->spa_root_vdev; 1303*fa9e4066Sahrens vdev_t *vd; 1304*fa9e4066Sahrens int c, m; 1305*fa9e4066Sahrens 1306*fa9e4066Sahrens for (c = 0; c < rvd->vdev_children; c++) { 1307*fa9e4066Sahrens vd = rvd->vdev_child[c]; 1308*fa9e4066Sahrens for (m = 0; m < vd->vdev_ms_count; m++) { 1309*fa9e4066Sahrens metaslab_t *msp = vd->vdev_ms[m]; 1310*fa9e4066Sahrens mutex_enter(&msp->ms_lock); 1311*fa9e4066Sahrens space_map_vacate(&msp->ms_allocmap[0], zdb_leak, 1312*fa9e4066Sahrens &msp->ms_allocmap[0]); 1313*fa9e4066Sahrens space_map_vacate(&msp->ms_freemap[0], NULL, NULL); 1314*fa9e4066Sahrens mutex_exit(&msp->ms_lock); 1315*fa9e4066Sahrens } 1316*fa9e4066Sahrens } 1317*fa9e4066Sahrens } 1318*fa9e4066Sahrens 1319*fa9e4066Sahrens static void 1320*fa9e4066Sahrens zdb_refresh_ubsync(spa_t *spa) 1321*fa9e4066Sahrens { 1322*fa9e4066Sahrens uberblock_t ub = { 0 }; 1323*fa9e4066Sahrens vdev_t *rvd = spa->spa_root_vdev; 1324*fa9e4066Sahrens zio_t *zio; 1325*fa9e4066Sahrens 1326*fa9e4066Sahrens /* 1327*fa9e4066Sahrens * Reopen all devices to purge zdb's vdev caches. 1328*fa9e4066Sahrens */ 1329*fa9e4066Sahrens vdev_reopen(rvd, NULL); 1330*fa9e4066Sahrens 1331*fa9e4066Sahrens /* 1332*fa9e4066Sahrens * Reload the uberblock. 1333*fa9e4066Sahrens */ 1334*fa9e4066Sahrens zio = zio_root(spa, NULL, NULL, 1335*fa9e4066Sahrens ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE); 1336*fa9e4066Sahrens vdev_uberblock_load(zio, rvd, &ub); 1337*fa9e4066Sahrens (void) zio_wait(zio); 1338*fa9e4066Sahrens 1339*fa9e4066Sahrens if (ub.ub_txg != 0) 1340*fa9e4066Sahrens spa->spa_ubsync = ub; 1341*fa9e4066Sahrens } 1342*fa9e4066Sahrens 1343*fa9e4066Sahrens /* 1344*fa9e4066Sahrens * Verify that the sum of the sizes of all blocks in the pool adds up 1345*fa9e4066Sahrens * to the SPA's sa_alloc total. 1346*fa9e4066Sahrens */ 1347*fa9e4066Sahrens typedef struct zdb_blkstats { 1348*fa9e4066Sahrens uint64_t zb_asize; 1349*fa9e4066Sahrens uint64_t zb_lsize; 1350*fa9e4066Sahrens uint64_t zb_psize; 1351*fa9e4066Sahrens uint64_t zb_count; 1352*fa9e4066Sahrens } zdb_blkstats_t; 1353*fa9e4066Sahrens 1354*fa9e4066Sahrens #define DMU_OT_DEFERRED DMU_OT_NONE 1355*fa9e4066Sahrens #define DMU_OT_TOTAL DMU_OT_NUMTYPES 1356*fa9e4066Sahrens 1357*fa9e4066Sahrens #define ZB_TOTAL ZB_MAXLEVEL 1358*fa9e4066Sahrens 1359*fa9e4066Sahrens typedef struct zdb_cb { 1360*fa9e4066Sahrens zdb_blkstats_t zcb_type[ZB_TOTAL + 1][DMU_OT_TOTAL + 1]; 1361*fa9e4066Sahrens uint64_t zcb_errors[256]; 1362*fa9e4066Sahrens traverse_blk_cache_t *zcb_cache; 1363*fa9e4066Sahrens int zcb_readfails; 1364*fa9e4066Sahrens int zcb_haderrors; 1365*fa9e4066Sahrens } zdb_cb_t; 1366*fa9e4066Sahrens 1367*fa9e4066Sahrens static blkptr_cb_t zdb_blkptr_cb; 1368*fa9e4066Sahrens 1369*fa9e4066Sahrens static void 1370*fa9e4066Sahrens zdb_count_block(spa_t *spa, zdb_cb_t *zcb, blkptr_t *bp, int type) 1371*fa9e4066Sahrens { 1372*fa9e4066Sahrens int i, error; 1373*fa9e4066Sahrens 1374*fa9e4066Sahrens for (i = 0; i < 4; i++) { 1375*fa9e4066Sahrens int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL; 1376*fa9e4066Sahrens int t = (i & 1) ? type : DMU_OT_TOTAL; 1377*fa9e4066Sahrens zdb_blkstats_t *zb = &zcb->zcb_type[l][t]; 1378*fa9e4066Sahrens 1379*fa9e4066Sahrens zb->zb_asize += BP_GET_ASIZE(bp); 1380*fa9e4066Sahrens zb->zb_lsize += BP_GET_LSIZE(bp); 1381*fa9e4066Sahrens zb->zb_psize += BP_GET_PSIZE(bp); 1382*fa9e4066Sahrens zb->zb_count++; 1383*fa9e4066Sahrens } 1384*fa9e4066Sahrens 1385*fa9e4066Sahrens if (dump_opt['L']) 1386*fa9e4066Sahrens return; 1387*fa9e4066Sahrens 1388*fa9e4066Sahrens error = zdb_space_map_claim(spa, bp); 1389*fa9e4066Sahrens 1390*fa9e4066Sahrens if (error == 0) 1391*fa9e4066Sahrens return; 1392*fa9e4066Sahrens 1393*fa9e4066Sahrens if (error == EAGAIN) 1394*fa9e4066Sahrens (void) fatal("double-allocation, bp=%p", bp); 1395*fa9e4066Sahrens 1396*fa9e4066Sahrens if (error == ESTALE) 1397*fa9e4066Sahrens (void) fatal("reference to freed block, bp=%p", bp); 1398*fa9e4066Sahrens 1399*fa9e4066Sahrens (void) fatal("fatal error %d in bp %p", error, bp); 1400*fa9e4066Sahrens } 1401*fa9e4066Sahrens 1402*fa9e4066Sahrens static void 1403*fa9e4066Sahrens zdb_log_block_cb(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t first_txg) 1404*fa9e4066Sahrens { 1405*fa9e4066Sahrens if (bp->blk_birth < first_txg) { 1406*fa9e4066Sahrens zdb_cb_t *zcb = arg; 1407*fa9e4066Sahrens traverse_blk_cache_t bc = *zcb->zcb_cache; 1408*fa9e4066Sahrens zbookmark_t *zb = &bc.bc_bookmark; 1409*fa9e4066Sahrens 1410*fa9e4066Sahrens zb->zb_objset = bp->blk_cksum.zc_word[2]; 1411*fa9e4066Sahrens zb->zb_blkid = bp->blk_cksum.zc_word[3]; 1412*fa9e4066Sahrens bc.bc_blkptr = *bp; 1413*fa9e4066Sahrens 1414*fa9e4066Sahrens (void) zdb_blkptr_cb(&bc, zilog->zl_spa, arg); 1415*fa9e4066Sahrens } 1416*fa9e4066Sahrens } 1417*fa9e4066Sahrens 1418*fa9e4066Sahrens static int 1419*fa9e4066Sahrens zdb_blkptr_cb(traverse_blk_cache_t *bc, spa_t *spa, void *arg) 1420*fa9e4066Sahrens { 1421*fa9e4066Sahrens zbookmark_t *zb = &bc->bc_bookmark; 1422*fa9e4066Sahrens zdb_cb_t *zcb = arg; 1423*fa9e4066Sahrens blkptr_t *bp = &bc->bc_blkptr; 1424*fa9e4066Sahrens dmu_object_type_t type = BP_GET_TYPE(bp); 1425*fa9e4066Sahrens char blkbuf[300]; 1426*fa9e4066Sahrens int error = 0; 1427*fa9e4066Sahrens 1428*fa9e4066Sahrens if (bc->bc_errno) { 1429*fa9e4066Sahrens if (zcb->zcb_readfails++ < 10 && dump_opt['L']) { 1430*fa9e4066Sahrens zdb_refresh_ubsync(spa); 1431*fa9e4066Sahrens error = EAGAIN; 1432*fa9e4066Sahrens } else { 1433*fa9e4066Sahrens zcb->zcb_haderrors = 1; 1434*fa9e4066Sahrens zcb->zcb_errors[bc->bc_errno]++; 1435*fa9e4066Sahrens error = ERESTART; 1436*fa9e4066Sahrens } 1437*fa9e4066Sahrens 1438*fa9e4066Sahrens if (dump_opt['b'] >= 3 || (dump_opt['b'] >= 2 && bc->bc_errno)) 1439*fa9e4066Sahrens sprintf_blkptr(blkbuf, bp); 1440*fa9e4066Sahrens else 1441*fa9e4066Sahrens blkbuf[0] = '\0'; 1442*fa9e4066Sahrens 1443*fa9e4066Sahrens (void) printf("zdb_blkptr_cb: Got error %d reading " 1444*fa9e4066Sahrens "<%llu, %llu, %d, %llx> %s -- %s\n", 1445*fa9e4066Sahrens bc->bc_errno, 1446*fa9e4066Sahrens (u_longlong_t)zb->zb_objset, 1447*fa9e4066Sahrens (u_longlong_t)zb->zb_object, 1448*fa9e4066Sahrens zb->zb_level, 1449*fa9e4066Sahrens (u_longlong_t)zb->zb_blkid, 1450*fa9e4066Sahrens blkbuf, 1451*fa9e4066Sahrens error == EAGAIN ? "retrying" : "skipping"); 1452*fa9e4066Sahrens 1453*fa9e4066Sahrens return (error); 1454*fa9e4066Sahrens } 1455*fa9e4066Sahrens 1456*fa9e4066Sahrens zcb->zcb_readfails = 0; 1457*fa9e4066Sahrens 1458*fa9e4066Sahrens ASSERT(bp->blk_birth != 0); 1459*fa9e4066Sahrens 1460*fa9e4066Sahrens zdb_count_block(spa, zcb, bp, type); 1461*fa9e4066Sahrens 1462*fa9e4066Sahrens if (dump_opt['b'] >= 4) { 1463*fa9e4066Sahrens sprintf_blkptr(blkbuf, bp); 1464*fa9e4066Sahrens (void) printf("objset %llu object %llu offset 0x%llx %s\n", 1465*fa9e4066Sahrens (u_longlong_t)zb->zb_objset, 1466*fa9e4066Sahrens (u_longlong_t)zb->zb_object, 1467*fa9e4066Sahrens (u_longlong_t)blkid2offset(bc->bc_dnode, 1468*fa9e4066Sahrens zb->zb_level, zb->zb_blkid), 1469*fa9e4066Sahrens blkbuf); 1470*fa9e4066Sahrens } 1471*fa9e4066Sahrens 1472*fa9e4066Sahrens if (type == DMU_OT_OBJSET) { 1473*fa9e4066Sahrens objset_phys_t *osphys = bc->bc_data; 1474*fa9e4066Sahrens zilog_t zilog = { 0 }; 1475*fa9e4066Sahrens zilog.zl_header = &osphys->os_zil_header; 1476*fa9e4066Sahrens zilog.zl_spa = spa; 1477*fa9e4066Sahrens 1478*fa9e4066Sahrens zcb->zcb_cache = bc; 1479*fa9e4066Sahrens 1480*fa9e4066Sahrens zil_parse(&zilog, zdb_log_block_cb, NULL, zcb, 1481*fa9e4066Sahrens spa_first_txg(spa)); 1482*fa9e4066Sahrens } 1483*fa9e4066Sahrens 1484*fa9e4066Sahrens return (0); 1485*fa9e4066Sahrens } 1486*fa9e4066Sahrens 1487*fa9e4066Sahrens static int 1488*fa9e4066Sahrens dump_block_stats(spa_t *spa) 1489*fa9e4066Sahrens { 1490*fa9e4066Sahrens traverse_handle_t *th; 1491*fa9e4066Sahrens zdb_cb_t zcb = { 0 }; 1492*fa9e4066Sahrens zdb_blkstats_t *zb, *tzb; 1493*fa9e4066Sahrens uint64_t alloc, space; 1494*fa9e4066Sahrens int leaks = 0; 1495*fa9e4066Sahrens int advance = zdb_advance; 1496*fa9e4066Sahrens int flags; 1497*fa9e4066Sahrens int e; 1498*fa9e4066Sahrens 1499*fa9e4066Sahrens if (dump_opt['c']) 1500*fa9e4066Sahrens advance |= ADVANCE_DATA; 1501*fa9e4066Sahrens 1502*fa9e4066Sahrens advance |= ADVANCE_PRUNE; 1503*fa9e4066Sahrens 1504*fa9e4066Sahrens (void) printf("\nTraversing all blocks to %sverify" 1505*fa9e4066Sahrens " nothing leaked ...\n", 1506*fa9e4066Sahrens dump_opt['c'] ? "verify checksums and " : ""); 1507*fa9e4066Sahrens 1508*fa9e4066Sahrens /* 1509*fa9e4066Sahrens * Load all space maps. As we traverse the pool, if we find a block 1510*fa9e4066Sahrens * that's not in its space map, that indicates a double-allocation, 1511*fa9e4066Sahrens * reference to a freed block, or an unclaimed block. Otherwise we 1512*fa9e4066Sahrens * remove the block from the space map. If the space maps are not 1513*fa9e4066Sahrens * empty when we're done, that indicates leaked blocks. 1514*fa9e4066Sahrens */ 1515*fa9e4066Sahrens if (!dump_opt['L']) 1516*fa9e4066Sahrens zdb_space_map_load(spa); 1517*fa9e4066Sahrens 1518*fa9e4066Sahrens /* 1519*fa9e4066Sahrens * If there's a deferred-free bplist, process that first. 1520*fa9e4066Sahrens */ 1521*fa9e4066Sahrens if (spa->spa_sync_bplist_obj != 0) { 1522*fa9e4066Sahrens bplist_t *bpl = &spa->spa_sync_bplist; 1523*fa9e4066Sahrens blkptr_t blk; 1524*fa9e4066Sahrens uint64_t itor = 0; 1525*fa9e4066Sahrens 1526*fa9e4066Sahrens bplist_open(bpl, spa->spa_meta_objset, 1527*fa9e4066Sahrens spa->spa_sync_bplist_obj); 1528*fa9e4066Sahrens 1529*fa9e4066Sahrens while (bplist_iterate(bpl, &itor, &blk) == 0) { 1530*fa9e4066Sahrens zdb_count_block(spa, &zcb, &blk, DMU_OT_DEFERRED); 1531*fa9e4066Sahrens if (dump_opt['b'] >= 4) { 1532*fa9e4066Sahrens char blkbuf[300]; 1533*fa9e4066Sahrens sprintf_blkptr(blkbuf, &blk); 1534*fa9e4066Sahrens (void) printf("[%s] %s\n", 1535*fa9e4066Sahrens "deferred free", blkbuf); 1536*fa9e4066Sahrens } 1537*fa9e4066Sahrens } 1538*fa9e4066Sahrens 1539*fa9e4066Sahrens bplist_close(bpl); 1540*fa9e4066Sahrens } 1541*fa9e4066Sahrens 1542*fa9e4066Sahrens /* 1543*fa9e4066Sahrens * Now traverse the pool. If we're read all data to verify checksums, 1544*fa9e4066Sahrens * do a scrubbing read so that we validate all copies. 1545*fa9e4066Sahrens */ 1546*fa9e4066Sahrens flags = ZIO_FLAG_CANFAIL; 1547*fa9e4066Sahrens if (advance & ADVANCE_DATA) 1548*fa9e4066Sahrens flags |= ZIO_FLAG_SCRUB; 1549*fa9e4066Sahrens th = traverse_init(spa, zdb_blkptr_cb, &zcb, advance, flags); 1550*fa9e4066Sahrens th->th_noread = zdb_noread; 1551*fa9e4066Sahrens 1552*fa9e4066Sahrens traverse_add_pool(th, 0, -1ULL); 1553*fa9e4066Sahrens 1554*fa9e4066Sahrens while (traverse_more(th) == EAGAIN) 1555*fa9e4066Sahrens continue; 1556*fa9e4066Sahrens 1557*fa9e4066Sahrens traverse_fini(th); 1558*fa9e4066Sahrens 1559*fa9e4066Sahrens if (zcb.zcb_haderrors) { 1560*fa9e4066Sahrens (void) printf("\nError counts:\n\n"); 1561*fa9e4066Sahrens (void) printf("\t%5s %s\n", "errno", "count"); 1562*fa9e4066Sahrens for (e = 0; e < 256; e++) { 1563*fa9e4066Sahrens if (zcb.zcb_errors[e] != 0) { 1564*fa9e4066Sahrens (void) printf("\t%5d %llu\n", 1565*fa9e4066Sahrens e, (u_longlong_t)zcb.zcb_errors[e]); 1566*fa9e4066Sahrens } 1567*fa9e4066Sahrens } 1568*fa9e4066Sahrens } 1569*fa9e4066Sahrens 1570*fa9e4066Sahrens /* 1571*fa9e4066Sahrens * Report any leaked segments. 1572*fa9e4066Sahrens */ 1573*fa9e4066Sahrens if (!dump_opt['L']) 1574*fa9e4066Sahrens zdb_space_map_vacate(spa); 1575*fa9e4066Sahrens 1576*fa9e4066Sahrens if (dump_opt['L']) 1577*fa9e4066Sahrens (void) printf("\n\n *** Live pool traversal; " 1578*fa9e4066Sahrens "block counts are only approximate ***\n\n"); 1579*fa9e4066Sahrens 1580*fa9e4066Sahrens alloc = spa_get_alloc(spa); 1581*fa9e4066Sahrens space = spa_get_space(spa); 1582*fa9e4066Sahrens 1583*fa9e4066Sahrens tzb = &zcb.zcb_type[ZB_TOTAL][DMU_OT_TOTAL]; 1584*fa9e4066Sahrens 1585*fa9e4066Sahrens if (tzb->zb_asize == alloc) { 1586*fa9e4066Sahrens (void) printf("\n\tNo leaks (block sum matches space" 1587*fa9e4066Sahrens " maps exactly)\n"); 1588*fa9e4066Sahrens } else { 1589*fa9e4066Sahrens (void) printf("block traversal size %llu != alloc %llu " 1590*fa9e4066Sahrens "(leaked %lld)\n", 1591*fa9e4066Sahrens (u_longlong_t)tzb->zb_asize, 1592*fa9e4066Sahrens (u_longlong_t)alloc, 1593*fa9e4066Sahrens (u_longlong_t)(alloc - tzb->zb_asize)); 1594*fa9e4066Sahrens leaks = 1; 1595*fa9e4066Sahrens } 1596*fa9e4066Sahrens 1597*fa9e4066Sahrens if (tzb->zb_count == 0) 1598*fa9e4066Sahrens return (2); 1599*fa9e4066Sahrens 1600*fa9e4066Sahrens (void) printf("\n"); 1601*fa9e4066Sahrens (void) printf("\tbp count: %10llu\n", 1602*fa9e4066Sahrens (u_longlong_t)tzb->zb_count); 1603*fa9e4066Sahrens (void) printf("\tbp logical: %10llu\t avg: %6llu\n", 1604*fa9e4066Sahrens (u_longlong_t)tzb->zb_lsize, 1605*fa9e4066Sahrens (u_longlong_t)(tzb->zb_lsize / tzb->zb_count)); 1606*fa9e4066Sahrens (void) printf("\tbp physical: %10llu\t avg:" 1607*fa9e4066Sahrens " %6llu\tcompression: %6.2f\n", 1608*fa9e4066Sahrens (u_longlong_t)tzb->zb_psize, 1609*fa9e4066Sahrens (u_longlong_t)(tzb->zb_psize / tzb->zb_count), 1610*fa9e4066Sahrens (double)tzb->zb_lsize / tzb->zb_psize); 1611*fa9e4066Sahrens (void) printf("\tbp allocated: %10llu\t avg:" 1612*fa9e4066Sahrens " %6llu\tcompression: %6.2f\n", 1613*fa9e4066Sahrens (u_longlong_t)tzb->zb_asize, 1614*fa9e4066Sahrens (u_longlong_t)(tzb->zb_asize / tzb->zb_count), 1615*fa9e4066Sahrens (double)tzb->zb_lsize / tzb->zb_asize); 1616*fa9e4066Sahrens (void) printf("\tSPA allocated: %10llu\tused: %5.2f%%\n", 1617*fa9e4066Sahrens (u_longlong_t)alloc, 100.0 * alloc / space); 1618*fa9e4066Sahrens 1619*fa9e4066Sahrens if (dump_opt['b'] >= 2) { 1620*fa9e4066Sahrens int l, t, level; 1621*fa9e4066Sahrens (void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 1622*fa9e4066Sahrens "\t avg\t comp\t%%Total\tType\n"); 1623*fa9e4066Sahrens 1624*fa9e4066Sahrens for (t = 0; t <= DMU_OT_NUMTYPES; t++) { 1625*fa9e4066Sahrens char csize[6], lsize[6], psize[6], asize[6], avg[6]; 1626*fa9e4066Sahrens char *typename; 1627*fa9e4066Sahrens 1628*fa9e4066Sahrens typename = t == DMU_OT_DEFERRED ? "deferred free" : 1629*fa9e4066Sahrens t == DMU_OT_TOTAL ? "Total" : dmu_ot[t].ot_name; 1630*fa9e4066Sahrens 1631*fa9e4066Sahrens if (zcb.zcb_type[ZB_TOTAL][t].zb_asize == 0) { 1632*fa9e4066Sahrens (void) printf("%6s\t%5s\t%5s\t%5s" 1633*fa9e4066Sahrens "\t%5s\t%5s\t%6s\t%s\n", 1634*fa9e4066Sahrens "-", 1635*fa9e4066Sahrens "-", 1636*fa9e4066Sahrens "-", 1637*fa9e4066Sahrens "-", 1638*fa9e4066Sahrens "-", 1639*fa9e4066Sahrens "-", 1640*fa9e4066Sahrens "-", 1641*fa9e4066Sahrens typename); 1642*fa9e4066Sahrens continue; 1643*fa9e4066Sahrens } 1644*fa9e4066Sahrens 1645*fa9e4066Sahrens for (l = ZB_TOTAL - 1; l >= -1; l--) { 1646*fa9e4066Sahrens level = (l == -1 ? ZB_TOTAL : l); 1647*fa9e4066Sahrens zb = &zcb.zcb_type[level][t]; 1648*fa9e4066Sahrens 1649*fa9e4066Sahrens if (zb->zb_asize == 0) 1650*fa9e4066Sahrens continue; 1651*fa9e4066Sahrens 1652*fa9e4066Sahrens if (dump_opt['b'] < 3 && level != ZB_TOTAL) 1653*fa9e4066Sahrens continue; 1654*fa9e4066Sahrens 1655*fa9e4066Sahrens if (level == 0 && zb->zb_asize == 1656*fa9e4066Sahrens zcb.zcb_type[ZB_TOTAL][t].zb_asize) 1657*fa9e4066Sahrens continue; 1658*fa9e4066Sahrens 1659*fa9e4066Sahrens nicenum(zb->zb_count, csize); 1660*fa9e4066Sahrens nicenum(zb->zb_lsize, lsize); 1661*fa9e4066Sahrens nicenum(zb->zb_psize, psize); 1662*fa9e4066Sahrens nicenum(zb->zb_asize, asize); 1663*fa9e4066Sahrens nicenum(zb->zb_asize / zb->zb_count, avg); 1664*fa9e4066Sahrens 1665*fa9e4066Sahrens (void) printf("%6s\t%5s\t%5s\t%5s\t%5s" 1666*fa9e4066Sahrens "\t%5.2f\t%6.2f\t", 1667*fa9e4066Sahrens csize, lsize, psize, asize, avg, 1668*fa9e4066Sahrens (double)zb->zb_lsize / zb->zb_psize, 1669*fa9e4066Sahrens 100.0 * zb->zb_asize / tzb->zb_asize); 1670*fa9e4066Sahrens 1671*fa9e4066Sahrens if (level == ZB_TOTAL) 1672*fa9e4066Sahrens (void) printf("%s\n", typename); 1673*fa9e4066Sahrens else 1674*fa9e4066Sahrens (void) printf(" L%d %s\n", 1675*fa9e4066Sahrens level, typename); 1676*fa9e4066Sahrens } 1677*fa9e4066Sahrens } 1678*fa9e4066Sahrens } 1679*fa9e4066Sahrens 1680*fa9e4066Sahrens (void) printf("\n"); 1681*fa9e4066Sahrens 1682*fa9e4066Sahrens if (leaks) 1683*fa9e4066Sahrens return (2); 1684*fa9e4066Sahrens 1685*fa9e4066Sahrens if (zcb.zcb_haderrors) 1686*fa9e4066Sahrens return (3); 1687*fa9e4066Sahrens 1688*fa9e4066Sahrens return (0); 1689*fa9e4066Sahrens } 1690*fa9e4066Sahrens 1691*fa9e4066Sahrens static void 1692*fa9e4066Sahrens dump_zpool(spa_t *spa) 1693*fa9e4066Sahrens { 1694*fa9e4066Sahrens dsl_pool_t *dp = spa_get_dsl(spa); 1695*fa9e4066Sahrens int rc = 0; 1696*fa9e4066Sahrens 1697*fa9e4066Sahrens if (dump_opt['u']) 1698*fa9e4066Sahrens dump_uberblock(&spa->spa_uberblock); 1699*fa9e4066Sahrens 1700*fa9e4066Sahrens if (dump_opt['d'] || dump_opt['i']) { 1701*fa9e4066Sahrens dump_dir(dp->dp_meta_objset); 1702*fa9e4066Sahrens if (dump_opt['d'] >= 3) { 1703*fa9e4066Sahrens dump_bplist(dp->dp_meta_objset, 1704*fa9e4066Sahrens spa->spa_sync_bplist_obj, "Deferred frees"); 1705*fa9e4066Sahrens dump_dtl(spa->spa_root_vdev, 0); 1706*fa9e4066Sahrens dump_metaslabs(spa); 1707*fa9e4066Sahrens } 1708*fa9e4066Sahrens dmu_objset_find(spa->spa_name, dump_one_dir, NULL, 1709*fa9e4066Sahrens DS_FIND_SNAPSHOTS); 1710*fa9e4066Sahrens } 1711*fa9e4066Sahrens 1712*fa9e4066Sahrens if (dump_opt['b'] || dump_opt['c']) 1713*fa9e4066Sahrens rc = dump_block_stats(spa); 1714*fa9e4066Sahrens 1715*fa9e4066Sahrens if (dump_opt['s']) 1716*fa9e4066Sahrens show_pool_stats(spa); 1717*fa9e4066Sahrens 1718*fa9e4066Sahrens if (rc != 0) 1719*fa9e4066Sahrens exit(rc); 1720*fa9e4066Sahrens } 1721*fa9e4066Sahrens 1722*fa9e4066Sahrens int 1723*fa9e4066Sahrens main(int argc, char **argv) 1724*fa9e4066Sahrens { 1725*fa9e4066Sahrens int i, c; 1726*fa9e4066Sahrens struct rlimit rl = { 1024, 1024 }; 1727*fa9e4066Sahrens spa_t *spa; 1728*fa9e4066Sahrens objset_t *os = NULL; 1729*fa9e4066Sahrens char *endstr; 1730*fa9e4066Sahrens int dump_all = 1; 1731*fa9e4066Sahrens int verbose = 0; 1732*fa9e4066Sahrens int error; 1733*fa9e4066Sahrens int flag, set; 1734*fa9e4066Sahrens 1735*fa9e4066Sahrens (void) setrlimit(RLIMIT_NOFILE, &rl); 1736*fa9e4066Sahrens 1737*fa9e4066Sahrens dprintf_setup(&argc, argv); 1738*fa9e4066Sahrens 1739*fa9e4066Sahrens while ((c = getopt(argc, argv, "udibcsvCLO:B:Ul")) != -1) { 1740*fa9e4066Sahrens switch (c) { 1741*fa9e4066Sahrens case 'u': 1742*fa9e4066Sahrens case 'd': 1743*fa9e4066Sahrens case 'i': 1744*fa9e4066Sahrens case 'b': 1745*fa9e4066Sahrens case 'c': 1746*fa9e4066Sahrens case 's': 1747*fa9e4066Sahrens case 'C': 1748*fa9e4066Sahrens case 'l': 1749*fa9e4066Sahrens dump_opt[c]++; 1750*fa9e4066Sahrens dump_all = 0; 1751*fa9e4066Sahrens break; 1752*fa9e4066Sahrens case 'L': 1753*fa9e4066Sahrens dump_opt[c]++; 1754*fa9e4066Sahrens break; 1755*fa9e4066Sahrens case 'O': 1756*fa9e4066Sahrens endstr = optarg; 1757*fa9e4066Sahrens if (endstr[0] == '!') { 1758*fa9e4066Sahrens endstr++; 1759*fa9e4066Sahrens set = 0; 1760*fa9e4066Sahrens } else { 1761*fa9e4066Sahrens set = 1; 1762*fa9e4066Sahrens } 1763*fa9e4066Sahrens if (strcmp(endstr, "post") == 0) { 1764*fa9e4066Sahrens flag = ADVANCE_PRE; 1765*fa9e4066Sahrens set = !set; 1766*fa9e4066Sahrens } else if (strcmp(endstr, "pre") == 0) { 1767*fa9e4066Sahrens flag = ADVANCE_PRE; 1768*fa9e4066Sahrens } else if (strcmp(endstr, "prune") == 0) { 1769*fa9e4066Sahrens flag = ADVANCE_PRUNE; 1770*fa9e4066Sahrens } else if (strcmp(endstr, "data") == 0) { 1771*fa9e4066Sahrens flag = ADVANCE_DATA; 1772*fa9e4066Sahrens } else if (strcmp(endstr, "holes") == 0) { 1773*fa9e4066Sahrens flag = ADVANCE_HOLES; 1774*fa9e4066Sahrens } else { 1775*fa9e4066Sahrens usage(); 1776*fa9e4066Sahrens } 1777*fa9e4066Sahrens if (set) 1778*fa9e4066Sahrens zdb_advance |= flag; 1779*fa9e4066Sahrens else 1780*fa9e4066Sahrens zdb_advance &= ~flag; 1781*fa9e4066Sahrens break; 1782*fa9e4066Sahrens case 'B': 1783*fa9e4066Sahrens endstr = optarg - 1; 1784*fa9e4066Sahrens zdb_noread.zb_objset = strtoull(endstr + 1, &endstr, 0); 1785*fa9e4066Sahrens zdb_noread.zb_object = strtoull(endstr + 1, &endstr, 0); 1786*fa9e4066Sahrens zdb_noread.zb_level = strtol(endstr + 1, &endstr, 0); 1787*fa9e4066Sahrens zdb_noread.zb_blkid = strtoull(endstr + 1, &endstr, 16); 1788*fa9e4066Sahrens (void) printf("simulating bad block " 1789*fa9e4066Sahrens "<%llu, %llu, %d, %llx>\n", 1790*fa9e4066Sahrens (u_longlong_t)zdb_noread.zb_objset, 1791*fa9e4066Sahrens (u_longlong_t)zdb_noread.zb_object, 1792*fa9e4066Sahrens zdb_noread.zb_level, 1793*fa9e4066Sahrens (u_longlong_t)zdb_noread.zb_blkid); 1794*fa9e4066Sahrens break; 1795*fa9e4066Sahrens case 'v': 1796*fa9e4066Sahrens verbose++; 1797*fa9e4066Sahrens break; 1798*fa9e4066Sahrens case 'U': 1799*fa9e4066Sahrens spa_config_dir = "/tmp"; 1800*fa9e4066Sahrens break; 1801*fa9e4066Sahrens default: 1802*fa9e4066Sahrens usage(); 1803*fa9e4066Sahrens break; 1804*fa9e4066Sahrens } 1805*fa9e4066Sahrens } 1806*fa9e4066Sahrens 1807*fa9e4066Sahrens kernel_init(FREAD); 1808*fa9e4066Sahrens 1809*fa9e4066Sahrens for (c = 0; c < 256; c++) { 1810*fa9e4066Sahrens if (dump_all && c != 'L' && c != 'l') 1811*fa9e4066Sahrens dump_opt[c] = 1; 1812*fa9e4066Sahrens if (dump_opt[c]) 1813*fa9e4066Sahrens dump_opt[c] += verbose; 1814*fa9e4066Sahrens } 1815*fa9e4066Sahrens 1816*fa9e4066Sahrens argc -= optind; 1817*fa9e4066Sahrens argv += optind; 1818*fa9e4066Sahrens 1819*fa9e4066Sahrens if (argc < 1) { 1820*fa9e4066Sahrens if (dump_opt['C']) { 1821*fa9e4066Sahrens dump_config(NULL); 1822*fa9e4066Sahrens return (0); 1823*fa9e4066Sahrens } 1824*fa9e4066Sahrens usage(); 1825*fa9e4066Sahrens } 1826*fa9e4066Sahrens 1827*fa9e4066Sahrens if (dump_opt['l']) { 1828*fa9e4066Sahrens dump_label(argv[0]); 1829*fa9e4066Sahrens return (0); 1830*fa9e4066Sahrens } 1831*fa9e4066Sahrens 1832*fa9e4066Sahrens if (dump_opt['C']) 1833*fa9e4066Sahrens dump_config(argv[0]); 1834*fa9e4066Sahrens 1835*fa9e4066Sahrens if (strchr(argv[0], '/') != NULL) { 1836*fa9e4066Sahrens error = dmu_objset_open(argv[0], DMU_OST_ANY, 1837*fa9e4066Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1838*fa9e4066Sahrens } else { 1839*fa9e4066Sahrens error = spa_open(argv[0], &spa, FTAG); 1840*fa9e4066Sahrens } 1841*fa9e4066Sahrens 1842*fa9e4066Sahrens if (error) 1843*fa9e4066Sahrens fatal("can't open %s: error %d", argv[0], error); 1844*fa9e4066Sahrens 1845*fa9e4066Sahrens argv++; 1846*fa9e4066Sahrens if (--argc > 0) { 1847*fa9e4066Sahrens zopt_objects = argc; 1848*fa9e4066Sahrens zopt_object = calloc(zopt_objects, sizeof (uint64_t)); 1849*fa9e4066Sahrens for (i = 0; i < zopt_objects; i++) { 1850*fa9e4066Sahrens errno = 0; 1851*fa9e4066Sahrens zopt_object[i] = strtoull(argv[i], NULL, 0); 1852*fa9e4066Sahrens if (zopt_object[i] == 0 && errno != 0) 1853*fa9e4066Sahrens fatal("bad object number %s: %s", 1854*fa9e4066Sahrens argv[i], strerror(errno)); 1855*fa9e4066Sahrens } 1856*fa9e4066Sahrens } 1857*fa9e4066Sahrens 1858*fa9e4066Sahrens if (os != NULL) { 1859*fa9e4066Sahrens dump_dir(os); 1860*fa9e4066Sahrens dmu_objset_close(os); 1861*fa9e4066Sahrens } else { 1862*fa9e4066Sahrens dump_zpool(spa); 1863*fa9e4066Sahrens spa_close(spa, FTAG); 1864*fa9e4066Sahrens } 1865*fa9e4066Sahrens 1866*fa9e4066Sahrens kernel_fini(); 1867*fa9e4066Sahrens 1868*fa9e4066Sahrens return (0); 1869*fa9e4066Sahrens } 1870