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 <mdb/mdb_ctf.h> 30*fa9e4066Sahrens #include <sys/zfs_context.h> 31*fa9e4066Sahrens #include <sys/mdb_modapi.h> 32*fa9e4066Sahrens #include <sys/dbuf.h> 33*fa9e4066Sahrens #include <sys/dmu_objset.h> 34*fa9e4066Sahrens #include <sys/dsl_dir.h> 35*fa9e4066Sahrens #include <sys/dsl_pool.h> 36*fa9e4066Sahrens #include <sys/metaslab_impl.h> 37*fa9e4066Sahrens #include <sys/space_map.h> 38*fa9e4066Sahrens #include <sys/list.h> 39*fa9e4066Sahrens #include <sys/spa_impl.h> 40*fa9e4066Sahrens #include <sys/vdev_impl.h> 41*fa9e4066Sahrens #include <sys/zio_compress.h> 42*fa9e4066Sahrens 43*fa9e4066Sahrens #ifndef _KERNEL 44*fa9e4066Sahrens #include "../genunix/list.h" 45*fa9e4066Sahrens #endif 46*fa9e4066Sahrens 47*fa9e4066Sahrens #ifdef _KERNEL 48*fa9e4066Sahrens #define ZFS_OBJ_NAME "zfs" 49*fa9e4066Sahrens #else 50*fa9e4066Sahrens #define ZFS_OBJ_NAME "libzpool.so.1" 51*fa9e4066Sahrens #endif 52*fa9e4066Sahrens 53*fa9e4066Sahrens static char * 54*fa9e4066Sahrens local_strdup(const char *s) 55*fa9e4066Sahrens { 56*fa9e4066Sahrens char *s1 = mdb_alloc(strlen(s) + 1, UM_SLEEP); 57*fa9e4066Sahrens 58*fa9e4066Sahrens (void) strcpy(s1, s); 59*fa9e4066Sahrens return (s1); 60*fa9e4066Sahrens } 61*fa9e4066Sahrens 62*fa9e4066Sahrens static int 63*fa9e4066Sahrens getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp, 64*fa9e4066Sahrens const char *member, int len, void *buf) 65*fa9e4066Sahrens { 66*fa9e4066Sahrens mdb_ctf_id_t id; 67*fa9e4066Sahrens ulong_t off; 68*fa9e4066Sahrens char name[64]; 69*fa9e4066Sahrens 70*fa9e4066Sahrens if (idp == NULL) { 71*fa9e4066Sahrens if (mdb_ctf_lookup_by_name(type, &id) == -1) { 72*fa9e4066Sahrens mdb_warn("couldn't find type %s", type); 73*fa9e4066Sahrens return (DCMD_ERR); 74*fa9e4066Sahrens } 75*fa9e4066Sahrens idp = &id; 76*fa9e4066Sahrens } else { 77*fa9e4066Sahrens type = name; 78*fa9e4066Sahrens mdb_ctf_type_name(*idp, name, sizeof (name)); 79*fa9e4066Sahrens } 80*fa9e4066Sahrens 81*fa9e4066Sahrens if (mdb_ctf_offsetof(*idp, member, &off) == -1) { 82*fa9e4066Sahrens mdb_warn("couldn't find member %s of type %s\n", member, type); 83*fa9e4066Sahrens return (DCMD_ERR); 84*fa9e4066Sahrens } 85*fa9e4066Sahrens if (off % 8 != 0) { 86*fa9e4066Sahrens mdb_warn("member %s of type %s is unsupported bitfield", 87*fa9e4066Sahrens member, type); 88*fa9e4066Sahrens return (DCMD_ERR); 89*fa9e4066Sahrens } 90*fa9e4066Sahrens off /= 8; 91*fa9e4066Sahrens 92*fa9e4066Sahrens if (mdb_vread(buf, len, addr + off) == -1) { 93*fa9e4066Sahrens mdb_warn("failed to read %s from %s at %p", 94*fa9e4066Sahrens member, type, addr + off); 95*fa9e4066Sahrens return (DCMD_ERR); 96*fa9e4066Sahrens } 97*fa9e4066Sahrens /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */ 98*fa9e4066Sahrens 99*fa9e4066Sahrens return (0); 100*fa9e4066Sahrens } 101*fa9e4066Sahrens 102*fa9e4066Sahrens #define GETMEMB(addr, type, member, dest) \ 103*fa9e4066Sahrens getmember(addr, #type, NULL, #member, sizeof (dest), &(dest)) 104*fa9e4066Sahrens 105*fa9e4066Sahrens #define GETMEMBID(addr, ctfid, member, dest) \ 106*fa9e4066Sahrens getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) 107*fa9e4066Sahrens 108*fa9e4066Sahrens static int 109*fa9e4066Sahrens getrefcount(uintptr_t addr, mdb_ctf_id_t *id, 110*fa9e4066Sahrens const char *member, uint64_t *rc) 111*fa9e4066Sahrens { 112*fa9e4066Sahrens static int gotid; 113*fa9e4066Sahrens static mdb_ctf_id_t rc_id; 114*fa9e4066Sahrens ulong_t off; 115*fa9e4066Sahrens 116*fa9e4066Sahrens if (!gotid) { 117*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { 118*fa9e4066Sahrens mdb_warn("couldn't find struct refcount"); 119*fa9e4066Sahrens return (DCMD_ERR); 120*fa9e4066Sahrens } 121*fa9e4066Sahrens gotid = TRUE; 122*fa9e4066Sahrens } 123*fa9e4066Sahrens 124*fa9e4066Sahrens if (mdb_ctf_offsetof(*id, member, &off) == -1) { 125*fa9e4066Sahrens char name[64]; 126*fa9e4066Sahrens mdb_ctf_type_name(*id, name, sizeof (name)); 127*fa9e4066Sahrens mdb_warn("couldn't find member %s of type %s\n", member, name); 128*fa9e4066Sahrens return (DCMD_ERR); 129*fa9e4066Sahrens } 130*fa9e4066Sahrens off /= 8; 131*fa9e4066Sahrens 132*fa9e4066Sahrens return (GETMEMBID(addr + off, &rc_id, rc_count, *rc)); 133*fa9e4066Sahrens } 134*fa9e4066Sahrens 135*fa9e4066Sahrens static int 136*fa9e4066Sahrens read_symbol(char *sym_name, void **bufp) 137*fa9e4066Sahrens { 138*fa9e4066Sahrens GElf_Sym sym; 139*fa9e4066Sahrens 140*fa9e4066Sahrens if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, sym_name, &sym)) { 141*fa9e4066Sahrens mdb_warn("can't find symbol %s", sym_name); 142*fa9e4066Sahrens return (DCMD_ERR); 143*fa9e4066Sahrens } 144*fa9e4066Sahrens 145*fa9e4066Sahrens *bufp = mdb_alloc(sym.st_size, UM_SLEEP); 146*fa9e4066Sahrens 147*fa9e4066Sahrens if (mdb_vread(*bufp, sym.st_size, sym.st_value) == -1) { 148*fa9e4066Sahrens mdb_warn("can't read data for symbol %s", sym_name); 149*fa9e4066Sahrens mdb_free(*bufp, sym.st_size); 150*fa9e4066Sahrens return (DCMD_ERR); 151*fa9e4066Sahrens } 152*fa9e4066Sahrens 153*fa9e4066Sahrens return (DCMD_OK); 154*fa9e4066Sahrens } 155*fa9e4066Sahrens 156*fa9e4066Sahrens static int verbose; 157*fa9e4066Sahrens 158*fa9e4066Sahrens static int 159*fa9e4066Sahrens freelist_walk_init(mdb_walk_state_t *wsp) 160*fa9e4066Sahrens { 161*fa9e4066Sahrens if (wsp->walk_addr == NULL) { 162*fa9e4066Sahrens mdb_warn("must supply starting address\n"); 163*fa9e4066Sahrens return (WALK_ERR); 164*fa9e4066Sahrens } 165*fa9e4066Sahrens 166*fa9e4066Sahrens wsp->walk_data = 0; /* Index into the freelist */ 167*fa9e4066Sahrens return (WALK_NEXT); 168*fa9e4066Sahrens } 169*fa9e4066Sahrens 170*fa9e4066Sahrens static int 171*fa9e4066Sahrens freelist_walk_step(mdb_walk_state_t *wsp) 172*fa9e4066Sahrens { 173*fa9e4066Sahrens uint64_t entry; 174*fa9e4066Sahrens uintptr_t number = (uintptr_t)wsp->walk_data; 175*fa9e4066Sahrens char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID" }; 176*fa9e4066Sahrens int mapshift = SPA_MINBLOCKSHIFT; 177*fa9e4066Sahrens 178*fa9e4066Sahrens if (mdb_vread(&entry, sizeof (entry), wsp->walk_addr) == -1) { 179*fa9e4066Sahrens mdb_warn("failed to read freelist entry %p", wsp->walk_addr); 180*fa9e4066Sahrens return (WALK_DONE); 181*fa9e4066Sahrens } 182*fa9e4066Sahrens wsp->walk_addr += sizeof (entry); 183*fa9e4066Sahrens wsp->walk_data = (void *)(number + 1); 184*fa9e4066Sahrens 185*fa9e4066Sahrens if (SM_DEBUG_DECODE(entry)) { 186*fa9e4066Sahrens mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n", 187*fa9e4066Sahrens number, 188*fa9e4066Sahrens ddata[SM_DEBUG_ACTION_DECODE(entry)], 189*fa9e4066Sahrens SM_DEBUG_TXG_DECODE(entry), 190*fa9e4066Sahrens SM_DEBUG_SYNCPASS_DECODE(entry)); 191*fa9e4066Sahrens } else { 192*fa9e4066Sahrens mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c " 193*fa9e4066Sahrens "size=%06llx", number, 194*fa9e4066Sahrens SM_OFFSET_DECODE(entry) << mapshift, 195*fa9e4066Sahrens (SM_OFFSET_DECODE(entry) + SM_RUN_DECODE(entry)) << 196*fa9e4066Sahrens mapshift, 197*fa9e4066Sahrens SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 198*fa9e4066Sahrens SM_RUN_DECODE(entry) << mapshift); 199*fa9e4066Sahrens if (verbose) 200*fa9e4066Sahrens mdb_printf(" (raw=%012llx)\n", entry); 201*fa9e4066Sahrens mdb_printf("\n"); 202*fa9e4066Sahrens } 203*fa9e4066Sahrens return (WALK_NEXT); 204*fa9e4066Sahrens } 205*fa9e4066Sahrens 206*fa9e4066Sahrens /* ARGSUSED */ 207*fa9e4066Sahrens static void 208*fa9e4066Sahrens freelist_walk_fini(mdb_walk_state_t *wsp) 209*fa9e4066Sahrens { 210*fa9e4066Sahrens } 211*fa9e4066Sahrens 212*fa9e4066Sahrens typedef struct dbuf_walk_data { 213*fa9e4066Sahrens dbuf_hash_table_t ht; 214*fa9e4066Sahrens int64_t bucket; 215*fa9e4066Sahrens uintptr_t dbp; 216*fa9e4066Sahrens dmu_buf_impl_t db; 217*fa9e4066Sahrens } dbuf_walk_data_t; 218*fa9e4066Sahrens 219*fa9e4066Sahrens static int 220*fa9e4066Sahrens dbuf_walk_init(mdb_walk_state_t *wsp) 221*fa9e4066Sahrens { 222*fa9e4066Sahrens dbuf_walk_data_t *dwd; 223*fa9e4066Sahrens 224*fa9e4066Sahrens if (wsp->walk_addr != NULL) { 225*fa9e4066Sahrens mdb_warn("must supply starting address\n"); 226*fa9e4066Sahrens return (WALK_ERR); 227*fa9e4066Sahrens } 228*fa9e4066Sahrens 229*fa9e4066Sahrens dwd = mdb_alloc(sizeof (dbuf_walk_data_t), UM_SLEEP); 230*fa9e4066Sahrens 231*fa9e4066Sahrens if (mdb_readvar(&dwd->ht, "dbuf_hash_table") == -1) { 232*fa9e4066Sahrens mdb_warn("failed to read 'dbuf_hash_table'"); 233*fa9e4066Sahrens mdb_free(dwd, sizeof (dbuf_walk_data_t)); 234*fa9e4066Sahrens return (WALK_ERR); 235*fa9e4066Sahrens } 236*fa9e4066Sahrens dwd->bucket = -1; 237*fa9e4066Sahrens dwd->dbp = 0; 238*fa9e4066Sahrens wsp->walk_data = dwd; 239*fa9e4066Sahrens return (WALK_NEXT); 240*fa9e4066Sahrens } 241*fa9e4066Sahrens 242*fa9e4066Sahrens static int 243*fa9e4066Sahrens dbuf_walk_step(mdb_walk_state_t *wsp) 244*fa9e4066Sahrens { 245*fa9e4066Sahrens int status; 246*fa9e4066Sahrens dbuf_walk_data_t *dwd = wsp->walk_data; 247*fa9e4066Sahrens 248*fa9e4066Sahrens while (dwd->dbp == 0) { 249*fa9e4066Sahrens dwd->bucket++; 250*fa9e4066Sahrens if (dwd->bucket == dwd->ht.hash_table_mask+1) 251*fa9e4066Sahrens return (WALK_DONE); 252*fa9e4066Sahrens 253*fa9e4066Sahrens if (mdb_vread(&dwd->dbp, sizeof (void *), 254*fa9e4066Sahrens (uintptr_t)(dwd->ht.hash_table+dwd->bucket)) == -1) { 255*fa9e4066Sahrens mdb_warn("failed to read hash bucket %u at %p", 256*fa9e4066Sahrens dwd->bucket, dwd->ht.hash_table+dwd->bucket); 257*fa9e4066Sahrens return (WALK_DONE); 258*fa9e4066Sahrens } 259*fa9e4066Sahrens } 260*fa9e4066Sahrens 261*fa9e4066Sahrens wsp->walk_addr = dwd->dbp; 262*fa9e4066Sahrens if (mdb_vread(&dwd->db, sizeof (dmu_buf_impl_t), 263*fa9e4066Sahrens wsp->walk_addr) == -1) { 264*fa9e4066Sahrens mdb_warn("failed to read dbuf at %p", wsp->walk_addr); 265*fa9e4066Sahrens return (WALK_DONE); 266*fa9e4066Sahrens } 267*fa9e4066Sahrens status = wsp->walk_callback(wsp->walk_addr, &dwd->db, wsp->walk_cbdata); 268*fa9e4066Sahrens 269*fa9e4066Sahrens dwd->dbp = (uintptr_t)dwd->db.db_hash_next; 270*fa9e4066Sahrens return (status); 271*fa9e4066Sahrens } 272*fa9e4066Sahrens 273*fa9e4066Sahrens static void 274*fa9e4066Sahrens dbuf_walk_fini(mdb_walk_state_t *wsp) 275*fa9e4066Sahrens { 276*fa9e4066Sahrens dbuf_walk_data_t *dwd = wsp->walk_data; 277*fa9e4066Sahrens mdb_free(dwd, sizeof (dbuf_walk_data_t)); 278*fa9e4066Sahrens } 279*fa9e4066Sahrens 280*fa9e4066Sahrens static int 281*fa9e4066Sahrens dataset_name(uintptr_t addr, char *buf) 282*fa9e4066Sahrens { 283*fa9e4066Sahrens static int gotid; 284*fa9e4066Sahrens static mdb_ctf_id_t dd_id; 285*fa9e4066Sahrens uintptr_t dd_parent; 286*fa9e4066Sahrens char dd_myname[MAXNAMELEN]; 287*fa9e4066Sahrens 288*fa9e4066Sahrens if (!gotid) { 289*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct dsl_dir", 290*fa9e4066Sahrens &dd_id) == -1) { 291*fa9e4066Sahrens mdb_warn("couldn't find struct dsl_dir"); 292*fa9e4066Sahrens return (DCMD_ERR); 293*fa9e4066Sahrens } 294*fa9e4066Sahrens gotid = TRUE; 295*fa9e4066Sahrens } 296*fa9e4066Sahrens if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) || 297*fa9e4066Sahrens GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) { 298*fa9e4066Sahrens return (DCMD_ERR); 299*fa9e4066Sahrens } 300*fa9e4066Sahrens 301*fa9e4066Sahrens if (dd_parent) { 302*fa9e4066Sahrens if (dataset_name(dd_parent, buf)) 303*fa9e4066Sahrens return (DCMD_ERR); 304*fa9e4066Sahrens strcat(buf, "/"); 305*fa9e4066Sahrens } 306*fa9e4066Sahrens 307*fa9e4066Sahrens if (dd_myname[0]) 308*fa9e4066Sahrens strcat(buf, dd_myname); 309*fa9e4066Sahrens else 310*fa9e4066Sahrens strcat(buf, "???"); 311*fa9e4066Sahrens 312*fa9e4066Sahrens return (0); 313*fa9e4066Sahrens } 314*fa9e4066Sahrens 315*fa9e4066Sahrens static int 316*fa9e4066Sahrens objset_name(uintptr_t addr, char *buf) 317*fa9e4066Sahrens { 318*fa9e4066Sahrens static int gotid; 319*fa9e4066Sahrens static mdb_ctf_id_t osi_id, ds_id; 320*fa9e4066Sahrens uintptr_t os_dsl_dataset; 321*fa9e4066Sahrens char ds_snapname[MAXNAMELEN]; 322*fa9e4066Sahrens uintptr_t ds_dir; 323*fa9e4066Sahrens 324*fa9e4066Sahrens buf[0] = '\0'; 325*fa9e4066Sahrens 326*fa9e4066Sahrens if (!gotid) { 327*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct objset_impl", 328*fa9e4066Sahrens &osi_id) == -1) { 329*fa9e4066Sahrens mdb_warn("couldn't find struct objset_impl"); 330*fa9e4066Sahrens return (DCMD_ERR); 331*fa9e4066Sahrens } 332*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct dsl_dataset", 333*fa9e4066Sahrens &ds_id) == -1) { 334*fa9e4066Sahrens mdb_warn("couldn't find struct dsl_dataset"); 335*fa9e4066Sahrens return (DCMD_ERR); 336*fa9e4066Sahrens } 337*fa9e4066Sahrens 338*fa9e4066Sahrens gotid = TRUE; 339*fa9e4066Sahrens } 340*fa9e4066Sahrens 341*fa9e4066Sahrens if (GETMEMBID(addr, &osi_id, os_dsl_dataset, os_dsl_dataset)) 342*fa9e4066Sahrens return (DCMD_ERR); 343*fa9e4066Sahrens 344*fa9e4066Sahrens if (os_dsl_dataset == 0) { 345*fa9e4066Sahrens strcat(buf, "mos"); 346*fa9e4066Sahrens return (0); 347*fa9e4066Sahrens } 348*fa9e4066Sahrens 349*fa9e4066Sahrens if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) || 350*fa9e4066Sahrens GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) { 351*fa9e4066Sahrens return (DCMD_ERR); 352*fa9e4066Sahrens } 353*fa9e4066Sahrens 354*fa9e4066Sahrens if (ds_dir && dataset_name(ds_dir, buf)) 355*fa9e4066Sahrens return (DCMD_ERR); 356*fa9e4066Sahrens 357*fa9e4066Sahrens if (ds_snapname[0]) { 358*fa9e4066Sahrens strcat(buf, "@"); 359*fa9e4066Sahrens strcat(buf, ds_snapname); 360*fa9e4066Sahrens } 361*fa9e4066Sahrens return (0); 362*fa9e4066Sahrens } 363*fa9e4066Sahrens 364*fa9e4066Sahrens static void 365*fa9e4066Sahrens enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val, 366*fa9e4066Sahrens const char *prefix) 367*fa9e4066Sahrens { 368*fa9e4066Sahrens const char *cp; 369*fa9e4066Sahrens size_t len = strlen(prefix); 370*fa9e4066Sahrens 371*fa9e4066Sahrens if ((cp = mdb_ctf_enum_name(id, val)) != NULL) { 372*fa9e4066Sahrens if (strncmp(cp, prefix, len) == 0) 373*fa9e4066Sahrens cp += len; 374*fa9e4066Sahrens (void) strncpy(out, cp, size); 375*fa9e4066Sahrens } else { 376*fa9e4066Sahrens mdb_snprintf(out, size, "? (%d)", val); 377*fa9e4066Sahrens } 378*fa9e4066Sahrens } 379*fa9e4066Sahrens 380*fa9e4066Sahrens /* ARGSUSED */ 381*fa9e4066Sahrens static int 382*fa9e4066Sahrens zio_pipeline(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 383*fa9e4066Sahrens { 384*fa9e4066Sahrens mdb_ctf_id_t pipe_enum; 385*fa9e4066Sahrens int i; 386*fa9e4066Sahrens char stage[1024]; 387*fa9e4066Sahrens 388*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("enum zio_stage", &pipe_enum) == -1) { 389*fa9e4066Sahrens mdb_warn("Could not find enum zio_stage"); 390*fa9e4066Sahrens return (DCMD_ERR); 391*fa9e4066Sahrens } 392*fa9e4066Sahrens 393*fa9e4066Sahrens for (i = 0; i < 32; i++) { 394*fa9e4066Sahrens if (addr & (1U << i)) { 395*fa9e4066Sahrens enum_lookup(stage, sizeof (stage), pipe_enum, i, 396*fa9e4066Sahrens "ZIO_STAGE_"); 397*fa9e4066Sahrens mdb_printf(" %s\n", stage); 398*fa9e4066Sahrens } 399*fa9e4066Sahrens } 400*fa9e4066Sahrens 401*fa9e4066Sahrens return (DCMD_OK); 402*fa9e4066Sahrens } 403*fa9e4066Sahrens 404*fa9e4066Sahrens /* ARGSUSED */ 405*fa9e4066Sahrens static int 406*fa9e4066Sahrens blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 407*fa9e4066Sahrens { 408*fa9e4066Sahrens blkptr_t bp; 409*fa9e4066Sahrens dva_t *dva; 410*fa9e4066Sahrens dmu_object_type_info_t *doti; 411*fa9e4066Sahrens zio_compress_info_t *zct; 412*fa9e4066Sahrens zio_checksum_info_t *zci; 413*fa9e4066Sahrens int i; 414*fa9e4066Sahrens char buf[MAXPATHLEN]; 415*fa9e4066Sahrens 416*fa9e4066Sahrens if (mdb_vread(&bp, sizeof (blkptr_t), addr) == -1) { 417*fa9e4066Sahrens mdb_warn("failed to read blkptr_t"); 418*fa9e4066Sahrens return (DCMD_ERR); 419*fa9e4066Sahrens } 420*fa9e4066Sahrens 421*fa9e4066Sahrens if (read_symbol("dmu_ot", (void **)&doti) != DCMD_OK) 422*fa9e4066Sahrens return (DCMD_ERR); 423*fa9e4066Sahrens for (i = 0; i < DMU_OT_NUMTYPES; i++) { 424*fa9e4066Sahrens mdb_readstr(buf, sizeof (buf), (uintptr_t)doti[i].ot_name); 425*fa9e4066Sahrens doti[i].ot_name = local_strdup(buf); 426*fa9e4066Sahrens } 427*fa9e4066Sahrens 428*fa9e4066Sahrens if (read_symbol("zio_checksum_table", (void **)&zci) != DCMD_OK) 429*fa9e4066Sahrens return (DCMD_ERR); 430*fa9e4066Sahrens for (i = 0; i < ZIO_CHECKSUM_FUNCTIONS; i++) { 431*fa9e4066Sahrens mdb_readstr(buf, sizeof (buf), (uintptr_t)zci[i].ci_name); 432*fa9e4066Sahrens zci[i].ci_name = local_strdup(buf); 433*fa9e4066Sahrens } 434*fa9e4066Sahrens 435*fa9e4066Sahrens if (read_symbol("zio_compress_table", (void **)&zct) != DCMD_OK) 436*fa9e4066Sahrens return (DCMD_ERR); 437*fa9e4066Sahrens for (i = 0; i < ZIO_COMPRESS_FUNCTIONS; i++) { 438*fa9e4066Sahrens mdb_readstr(buf, sizeof (buf), (uintptr_t)zct[i].ci_name); 439*fa9e4066Sahrens zct[i].ci_name = local_strdup(buf); 440*fa9e4066Sahrens } 441*fa9e4066Sahrens 442*fa9e4066Sahrens for (i = 0; i < SPA_DVAS_PER_BP; i++) { 443*fa9e4066Sahrens dva = &bp.blk_dva[i]; 444*fa9e4066Sahrens mdb_printf("DVA[%d]: vdev_id %lld / %llx\n", i, 445*fa9e4066Sahrens DVA_GET_VDEV(dva), DVA_GET_OFFSET(dva)); 446*fa9e4066Sahrens mdb_printf("DVA[%d]: GRID: %04x\t" 447*fa9e4066Sahrens "ASIZE: %llx\n", i, DVA_GET_GRID(dva), DVA_GET_ASIZE(dva)); 448*fa9e4066Sahrens } 449*fa9e4066Sahrens mdb_printf("LSIZE: %-16llx\t\tPSIZE: %llx\n", 450*fa9e4066Sahrens BP_GET_LSIZE(&bp), BP_GET_PSIZE(&bp)); 451*fa9e4066Sahrens mdb_printf("ENDIAN: %6s GANG: %-5s\tTYPE: %s\n", 452*fa9e4066Sahrens BP_GET_BYTEORDER(&bp) ? "LITTLE" : "BIG", 453*fa9e4066Sahrens DVA_GET_GANG(dva) ? "TRUE" : "FALSE", 454*fa9e4066Sahrens doti[BP_GET_TYPE(&bp)].ot_name); 455*fa9e4066Sahrens mdb_printf("BIRTH: %-16llx LEVEL: %-2d\tFILL: %llx\n", 456*fa9e4066Sahrens bp.blk_birth, BP_GET_LEVEL(&bp), bp.blk_fill); 457*fa9e4066Sahrens mdb_printf("CKFUNC: %-16s\t\tCOMP: %s\n", 458*fa9e4066Sahrens zci[BP_GET_CHECKSUM(&bp)].ci_name, 459*fa9e4066Sahrens zct[BP_GET_COMPRESS(&bp)].ci_name); 460*fa9e4066Sahrens mdb_printf("CKSUM: %llx:%llx:%llx:%llx\n", 461*fa9e4066Sahrens bp.blk_cksum.zc_word[0], 462*fa9e4066Sahrens bp.blk_cksum.zc_word[1], 463*fa9e4066Sahrens bp.blk_cksum.zc_word[2], 464*fa9e4066Sahrens bp.blk_cksum.zc_word[3]); 465*fa9e4066Sahrens 466*fa9e4066Sahrens return (DCMD_OK); 467*fa9e4066Sahrens } 468*fa9e4066Sahrens 469*fa9e4066Sahrens /* ARGSUSED */ 470*fa9e4066Sahrens static int 471*fa9e4066Sahrens dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 472*fa9e4066Sahrens { 473*fa9e4066Sahrens mdb_ctf_id_t id; 474*fa9e4066Sahrens dmu_buf_t db; 475*fa9e4066Sahrens uintptr_t objset; 476*fa9e4066Sahrens uint8_t level; 477*fa9e4066Sahrens uint64_t blkid; 478*fa9e4066Sahrens uint64_t holds; 479*fa9e4066Sahrens char objectname[32]; 480*fa9e4066Sahrens char blkidname[32]; 481*fa9e4066Sahrens char path[MAXNAMELEN]; 482*fa9e4066Sahrens 483*fa9e4066Sahrens if (DCMD_HDRSPEC(flags)) { 484*fa9e4066Sahrens mdb_printf(" addr object lvl blkid holds os\n"); 485*fa9e4066Sahrens } 486*fa9e4066Sahrens 487*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &id) == -1) { 488*fa9e4066Sahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 489*fa9e4066Sahrens return (DCMD_ERR); 490*fa9e4066Sahrens } 491*fa9e4066Sahrens 492*fa9e4066Sahrens if (GETMEMBID(addr, &id, db_objset, objset) || 493*fa9e4066Sahrens GETMEMBID(addr, &id, db, db) || 494*fa9e4066Sahrens GETMEMBID(addr, &id, db_level, level) || 495*fa9e4066Sahrens GETMEMBID(addr, &id, db_blkid, blkid)) { 496*fa9e4066Sahrens return (WALK_ERR); 497*fa9e4066Sahrens } 498*fa9e4066Sahrens 499*fa9e4066Sahrens if (getrefcount(addr, &id, "db_holds", &holds)) { 500*fa9e4066Sahrens return (WALK_ERR); 501*fa9e4066Sahrens } 502*fa9e4066Sahrens 503*fa9e4066Sahrens if (db.db_object == DMU_META_DNODE_OBJECT) 504*fa9e4066Sahrens (void) strcpy(objectname, "mdn"); 505*fa9e4066Sahrens else 506*fa9e4066Sahrens (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", 507*fa9e4066Sahrens (u_longlong_t)db.db_object); 508*fa9e4066Sahrens 509*fa9e4066Sahrens if (blkid == DB_BONUS_BLKID) 510*fa9e4066Sahrens (void) strcpy(blkidname, "bonus"); 511*fa9e4066Sahrens else 512*fa9e4066Sahrens (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", 513*fa9e4066Sahrens (u_longlong_t)blkid); 514*fa9e4066Sahrens 515*fa9e4066Sahrens if (objset_name(objset, path)) { 516*fa9e4066Sahrens return (WALK_ERR); 517*fa9e4066Sahrens } 518*fa9e4066Sahrens 519*fa9e4066Sahrens mdb_printf("%p %8s %1u %9s %2llu %s\n", 520*fa9e4066Sahrens addr, objectname, level, blkidname, holds, path); 521*fa9e4066Sahrens 522*fa9e4066Sahrens return (DCMD_OK); 523*fa9e4066Sahrens } 524*fa9e4066Sahrens 525*fa9e4066Sahrens /* ARGSUSED */ 526*fa9e4066Sahrens static int 527*fa9e4066Sahrens dbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 528*fa9e4066Sahrens { 529*fa9e4066Sahrens #define HISTOSZ 32 530*fa9e4066Sahrens uintptr_t dbp; 531*fa9e4066Sahrens dmu_buf_impl_t db; 532*fa9e4066Sahrens dbuf_hash_table_t ht; 533*fa9e4066Sahrens uint64_t bucket, ndbufs; 534*fa9e4066Sahrens uint64_t histo[HISTOSZ]; 535*fa9e4066Sahrens uint64_t histo2[HISTOSZ]; 536*fa9e4066Sahrens int i, maxidx; 537*fa9e4066Sahrens 538*fa9e4066Sahrens if (mdb_readvar(&ht, "dbuf_hash_table") == -1) { 539*fa9e4066Sahrens mdb_warn("failed to read 'dbuf_hash_table'"); 540*fa9e4066Sahrens return (DCMD_ERR); 541*fa9e4066Sahrens } 542*fa9e4066Sahrens 543*fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) { 544*fa9e4066Sahrens histo[i] = 0; 545*fa9e4066Sahrens histo2[i] = 0; 546*fa9e4066Sahrens } 547*fa9e4066Sahrens 548*fa9e4066Sahrens ndbufs = 0; 549*fa9e4066Sahrens for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) { 550*fa9e4066Sahrens int len; 551*fa9e4066Sahrens 552*fa9e4066Sahrens if (mdb_vread(&dbp, sizeof (void *), 553*fa9e4066Sahrens (uintptr_t)(ht.hash_table+bucket)) == -1) { 554*fa9e4066Sahrens mdb_warn("failed to read hash bucket %u at %p", 555*fa9e4066Sahrens bucket, ht.hash_table+bucket); 556*fa9e4066Sahrens return (DCMD_ERR); 557*fa9e4066Sahrens } 558*fa9e4066Sahrens 559*fa9e4066Sahrens len = 0; 560*fa9e4066Sahrens while (dbp != 0) { 561*fa9e4066Sahrens if (mdb_vread(&db, sizeof (dmu_buf_impl_t), 562*fa9e4066Sahrens dbp) == -1) { 563*fa9e4066Sahrens mdb_warn("failed to read dbuf at %p", dbp); 564*fa9e4066Sahrens return (DCMD_ERR); 565*fa9e4066Sahrens } 566*fa9e4066Sahrens dbp = (uintptr_t)db.db_hash_next; 567*fa9e4066Sahrens for (i = MIN(len, HISTOSZ - 1); i >= 0; i--) 568*fa9e4066Sahrens histo2[i]++; 569*fa9e4066Sahrens len++; 570*fa9e4066Sahrens ndbufs++; 571*fa9e4066Sahrens } 572*fa9e4066Sahrens 573*fa9e4066Sahrens if (len >= HISTOSZ) 574*fa9e4066Sahrens len = HISTOSZ-1; 575*fa9e4066Sahrens histo[len]++; 576*fa9e4066Sahrens } 577*fa9e4066Sahrens 578*fa9e4066Sahrens mdb_printf("hash table has %llu buckets, %llu dbufs " 579*fa9e4066Sahrens "(avg %llu buckets/dbuf)\n", 580*fa9e4066Sahrens ht.hash_table_mask+1, ndbufs, 581*fa9e4066Sahrens (ht.hash_table_mask+1)/ndbufs); 582*fa9e4066Sahrens 583*fa9e4066Sahrens mdb_printf("\n"); 584*fa9e4066Sahrens maxidx = 0; 585*fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) 586*fa9e4066Sahrens if (histo[i] > 0) 587*fa9e4066Sahrens maxidx = i; 588*fa9e4066Sahrens mdb_printf("hash chain length number of buckets\n"); 589*fa9e4066Sahrens for (i = 0; i <= maxidx; i++) 590*fa9e4066Sahrens mdb_printf("%u %llu\n", i, histo[i]); 591*fa9e4066Sahrens 592*fa9e4066Sahrens mdb_printf("\n"); 593*fa9e4066Sahrens maxidx = 0; 594*fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) 595*fa9e4066Sahrens if (histo2[i] > 0) 596*fa9e4066Sahrens maxidx = i; 597*fa9e4066Sahrens mdb_printf("hash chain depth number of dbufs\n"); 598*fa9e4066Sahrens for (i = 0; i <= maxidx; i++) 599*fa9e4066Sahrens mdb_printf("%u or more %llu %llu%%\n", 600*fa9e4066Sahrens i, histo2[i], histo2[i]*100/ndbufs); 601*fa9e4066Sahrens 602*fa9e4066Sahrens 603*fa9e4066Sahrens return (DCMD_OK); 604*fa9e4066Sahrens } 605*fa9e4066Sahrens 606*fa9e4066Sahrens typedef struct dbufs_data { 607*fa9e4066Sahrens mdb_ctf_id_t id; 608*fa9e4066Sahrens uint64_t objset; 609*fa9e4066Sahrens uint64_t object; 610*fa9e4066Sahrens uint64_t level; 611*fa9e4066Sahrens uint64_t blkid; 612*fa9e4066Sahrens char *osname; 613*fa9e4066Sahrens } dbufs_data_t; 614*fa9e4066Sahrens 615*fa9e4066Sahrens #define DBUFS_UNSET (0xbaddcafedeadbeefULL) 616*fa9e4066Sahrens 617*fa9e4066Sahrens /* ARGSUSED */ 618*fa9e4066Sahrens static int 619*fa9e4066Sahrens dbufs_cb(uintptr_t addr, const void *unknown, void *arg) 620*fa9e4066Sahrens { 621*fa9e4066Sahrens dbufs_data_t *data = arg; 622*fa9e4066Sahrens uintptr_t objset; 623*fa9e4066Sahrens dmu_buf_t db; 624*fa9e4066Sahrens uint8_t level; 625*fa9e4066Sahrens uint64_t blkid; 626*fa9e4066Sahrens char osname[MAXNAMELEN]; 627*fa9e4066Sahrens 628*fa9e4066Sahrens if (GETMEMBID(addr, &data->id, db_objset, objset) || 629*fa9e4066Sahrens GETMEMBID(addr, &data->id, db, db) || 630*fa9e4066Sahrens GETMEMBID(addr, &data->id, db_level, level) || 631*fa9e4066Sahrens GETMEMBID(addr, &data->id, db_blkid, blkid)) { 632*fa9e4066Sahrens return (WALK_ERR); 633*fa9e4066Sahrens } 634*fa9e4066Sahrens 635*fa9e4066Sahrens if ((data->objset == DBUFS_UNSET || data->objset == objset) && 636*fa9e4066Sahrens (data->osname == NULL || (objset_name(objset, osname) == 0 && 637*fa9e4066Sahrens strcmp(data->osname, osname) == 0)) && 638*fa9e4066Sahrens (data->object == DBUFS_UNSET || data->object == db.db_object) && 639*fa9e4066Sahrens (data->level == DBUFS_UNSET || data->level == level) && 640*fa9e4066Sahrens (data->blkid == DBUFS_UNSET || data->blkid == blkid)) { 641*fa9e4066Sahrens mdb_printf("%#lr\n", addr); 642*fa9e4066Sahrens } 643*fa9e4066Sahrens return (WALK_NEXT); 644*fa9e4066Sahrens } 645*fa9e4066Sahrens 646*fa9e4066Sahrens /* ARGSUSED */ 647*fa9e4066Sahrens static int 648*fa9e4066Sahrens dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 649*fa9e4066Sahrens { 650*fa9e4066Sahrens dbufs_data_t data; 651*fa9e4066Sahrens char *object = NULL; 652*fa9e4066Sahrens char *blkid = NULL; 653*fa9e4066Sahrens 654*fa9e4066Sahrens data.objset = data.object = data.level = data.blkid = DBUFS_UNSET; 655*fa9e4066Sahrens data.osname = NULL; 656*fa9e4066Sahrens 657*fa9e4066Sahrens if (mdb_getopts(argc, argv, 658*fa9e4066Sahrens 'O', MDB_OPT_UINT64, &data.objset, 659*fa9e4066Sahrens 'n', MDB_OPT_STR, &data.osname, 660*fa9e4066Sahrens 'o', MDB_OPT_STR, &object, 661*fa9e4066Sahrens 'l', MDB_OPT_UINT64, &data.level, 662*fa9e4066Sahrens 'b', MDB_OPT_STR, &blkid) != argc) { 663*fa9e4066Sahrens return (DCMD_USAGE); 664*fa9e4066Sahrens } 665*fa9e4066Sahrens 666*fa9e4066Sahrens if (object) { 667*fa9e4066Sahrens if (strcmp(object, "mdn") == 0) { 668*fa9e4066Sahrens data.object = DMU_META_DNODE_OBJECT; 669*fa9e4066Sahrens } else { 670*fa9e4066Sahrens data.object = mdb_strtoull(object); 671*fa9e4066Sahrens } 672*fa9e4066Sahrens } 673*fa9e4066Sahrens 674*fa9e4066Sahrens if (blkid) { 675*fa9e4066Sahrens if (strcmp(blkid, "bonus") == 0) { 676*fa9e4066Sahrens data.blkid = DB_BONUS_BLKID; 677*fa9e4066Sahrens } else { 678*fa9e4066Sahrens data.blkid = mdb_strtoull(blkid); 679*fa9e4066Sahrens } 680*fa9e4066Sahrens } 681*fa9e4066Sahrens 682*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &data.id) == -1) { 683*fa9e4066Sahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 684*fa9e4066Sahrens return (DCMD_ERR); 685*fa9e4066Sahrens } 686*fa9e4066Sahrens 687*fa9e4066Sahrens if (mdb_pwalk("dbufs", dbufs_cb, &data, 0) != 0) { 688*fa9e4066Sahrens mdb_warn("can't walk dbufs"); 689*fa9e4066Sahrens return (DCMD_ERR); 690*fa9e4066Sahrens } 691*fa9e4066Sahrens 692*fa9e4066Sahrens return (DCMD_OK); 693*fa9e4066Sahrens } 694*fa9e4066Sahrens 695*fa9e4066Sahrens typedef struct abuf_find_data { 696*fa9e4066Sahrens dva_t dva; 697*fa9e4066Sahrens mdb_ctf_id_t id; 698*fa9e4066Sahrens } abuf_find_data_t; 699*fa9e4066Sahrens 700*fa9e4066Sahrens /* ARGSUSED */ 701*fa9e4066Sahrens static int 702*fa9e4066Sahrens abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) 703*fa9e4066Sahrens { 704*fa9e4066Sahrens abuf_find_data_t *data = arg; 705*fa9e4066Sahrens dva_t dva; 706*fa9e4066Sahrens 707*fa9e4066Sahrens if (GETMEMBID(addr, &data->id, b_dva, dva)) { 708*fa9e4066Sahrens return (WALK_ERR); 709*fa9e4066Sahrens } 710*fa9e4066Sahrens 711*fa9e4066Sahrens if (dva.dva_word[0] == data->dva.dva_word[0] && 712*fa9e4066Sahrens dva.dva_word[1] == data->dva.dva_word[1]) { 713*fa9e4066Sahrens mdb_printf("%#lr\n", addr); 714*fa9e4066Sahrens } 715*fa9e4066Sahrens return (WALK_NEXT); 716*fa9e4066Sahrens } 717*fa9e4066Sahrens 718*fa9e4066Sahrens /* ARGSUSED */ 719*fa9e4066Sahrens static int 720*fa9e4066Sahrens abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 721*fa9e4066Sahrens { 722*fa9e4066Sahrens abuf_find_data_t data; 723*fa9e4066Sahrens GElf_Sym sym; 724*fa9e4066Sahrens int i; 725*fa9e4066Sahrens const char *syms[] = { 726*fa9e4066Sahrens "ARC_mru_top", 727*fa9e4066Sahrens "ARC_mru_bot", 728*fa9e4066Sahrens "ARC_mfu_top", 729*fa9e4066Sahrens "ARC_mfu_bot", 730*fa9e4066Sahrens }; 731*fa9e4066Sahrens 732*fa9e4066Sahrens if (argc != 2) 733*fa9e4066Sahrens return (DCMD_USAGE); 734*fa9e4066Sahrens 735*fa9e4066Sahrens for (i = 0; i < 2; i ++) { 736*fa9e4066Sahrens switch (argv[i].a_type) { 737*fa9e4066Sahrens case MDB_TYPE_STRING: 738*fa9e4066Sahrens data.dva.dva_word[i] = mdb_strtoull(argv[i].a_un.a_str); 739*fa9e4066Sahrens break; 740*fa9e4066Sahrens case MDB_TYPE_IMMEDIATE: 741*fa9e4066Sahrens data.dva.dva_word[i] = argv[i].a_un.a_val; 742*fa9e4066Sahrens break; 743*fa9e4066Sahrens default: 744*fa9e4066Sahrens return (DCMD_USAGE); 745*fa9e4066Sahrens } 746*fa9e4066Sahrens } 747*fa9e4066Sahrens 748*fa9e4066Sahrens if (mdb_ctf_lookup_by_name("struct arc_buf_hdr", &data.id) == -1) { 749*fa9e4066Sahrens mdb_warn("couldn't find struct arc_buf_hdr"); 750*fa9e4066Sahrens return (DCMD_ERR); 751*fa9e4066Sahrens } 752*fa9e4066Sahrens 753*fa9e4066Sahrens for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { 754*fa9e4066Sahrens if (mdb_lookup_by_name(syms[i], &sym)) { 755*fa9e4066Sahrens mdb_warn("can't find symbol %s", syms[i]); 756*fa9e4066Sahrens return (DCMD_ERR); 757*fa9e4066Sahrens } 758*fa9e4066Sahrens 759*fa9e4066Sahrens if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { 760*fa9e4066Sahrens mdb_warn("can't walk %s", syms[i]); 761*fa9e4066Sahrens return (DCMD_ERR); 762*fa9e4066Sahrens } 763*fa9e4066Sahrens } 764*fa9e4066Sahrens 765*fa9e4066Sahrens return (DCMD_OK); 766*fa9e4066Sahrens } 767*fa9e4066Sahrens 768*fa9e4066Sahrens void 769*fa9e4066Sahrens abuf_help(void) 770*fa9e4066Sahrens { 771*fa9e4066Sahrens mdb_printf("::abuf_find dva_word[0] dva_word[1]\n"); 772*fa9e4066Sahrens } 773*fa9e4066Sahrens 774*fa9e4066Sahrens /* 775*fa9e4066Sahrens * ::spa 776*fa9e4066Sahrens * 777*fa9e4066Sahrens * -c Print configuration information as well 778*fa9e4066Sahrens * -v Print vdev state 779*fa9e4066Sahrens * -e Print vdev error stats 780*fa9e4066Sahrens * 781*fa9e4066Sahrens * Print a summarized spa_t. When given no arguments, prints out a table of all 782*fa9e4066Sahrens * active pools on the system. 783*fa9e4066Sahrens */ 784*fa9e4066Sahrens /* ARGSUSED */ 785*fa9e4066Sahrens static int 786*fa9e4066Sahrens spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 787*fa9e4066Sahrens { 788*fa9e4066Sahrens spa_t spa; 789*fa9e4066Sahrens char poolname[MAXNAMELEN]; 790*fa9e4066Sahrens const char *statetab[] = { "ACTIVE", "EXPORTED", "DESTROYED", 791*fa9e4066Sahrens "UNINIT", "UNAVAIL" }; 792*fa9e4066Sahrens const char *state; 793*fa9e4066Sahrens int config = FALSE; 794*fa9e4066Sahrens int vdevs = FALSE; 795*fa9e4066Sahrens int errors = FALSE; 796*fa9e4066Sahrens 797*fa9e4066Sahrens if (mdb_getopts(argc, argv, 798*fa9e4066Sahrens 'c', MDB_OPT_SETBITS, TRUE, &config, 799*fa9e4066Sahrens 'v', MDB_OPT_SETBITS, TRUE, &vdevs, 800*fa9e4066Sahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 801*fa9e4066Sahrens NULL) != argc) 802*fa9e4066Sahrens return (DCMD_USAGE); 803*fa9e4066Sahrens 804*fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) { 805*fa9e4066Sahrens if (mdb_walk_dcmd("spa", "spa", argc, argv) == -1) { 806*fa9e4066Sahrens mdb_warn("can't walk spa"); 807*fa9e4066Sahrens return (DCMD_ERR); 808*fa9e4066Sahrens } 809*fa9e4066Sahrens 810*fa9e4066Sahrens return (DCMD_OK); 811*fa9e4066Sahrens } 812*fa9e4066Sahrens 813*fa9e4066Sahrens if (flags & DCMD_PIPE_OUT) { 814*fa9e4066Sahrens mdb_printf("%#lr\n", addr); 815*fa9e4066Sahrens return (DCMD_OK); 816*fa9e4066Sahrens } 817*fa9e4066Sahrens 818*fa9e4066Sahrens if (DCMD_HDRSPEC(flags)) 819*fa9e4066Sahrens mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE", 820*fa9e4066Sahrens sizeof (uintptr_t) == 4 ? 60 : 52, "NAME"); 821*fa9e4066Sahrens 822*fa9e4066Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 823*fa9e4066Sahrens mdb_warn("failed to read spa_t at %p", addr); 824*fa9e4066Sahrens return (DCMD_ERR); 825*fa9e4066Sahrens } 826*fa9e4066Sahrens 827*fa9e4066Sahrens if (mdb_readstr(poolname, sizeof (poolname), (uintptr_t)spa.spa_name) 828*fa9e4066Sahrens == -1) { 829*fa9e4066Sahrens mdb_warn("failed to read pool name at %p", spa.spa_name); 830*fa9e4066Sahrens return (DCMD_ERR); 831*fa9e4066Sahrens } 832*fa9e4066Sahrens 833*fa9e4066Sahrens if (spa.spa_state < 0 || spa.spa_state > POOL_STATE_UNAVAIL) 834*fa9e4066Sahrens state = "UKNNOWN"; 835*fa9e4066Sahrens else 836*fa9e4066Sahrens state = statetab[spa.spa_state]; 837*fa9e4066Sahrens 838*fa9e4066Sahrens mdb_printf("%0?p %9s %s\n", addr, state, poolname); 839*fa9e4066Sahrens 840*fa9e4066Sahrens if (config) { 841*fa9e4066Sahrens mdb_printf("\n"); 842*fa9e4066Sahrens mdb_inc_indent(4); 843*fa9e4066Sahrens if (mdb_call_dcmd("spa_config", addr, flags, 0, 844*fa9e4066Sahrens NULL) != DCMD_OK) 845*fa9e4066Sahrens return (DCMD_ERR); 846*fa9e4066Sahrens mdb_dec_indent(4); 847*fa9e4066Sahrens } 848*fa9e4066Sahrens 849*fa9e4066Sahrens if (vdevs || errors) { 850*fa9e4066Sahrens mdb_arg_t v; 851*fa9e4066Sahrens 852*fa9e4066Sahrens v.a_type = MDB_TYPE_STRING; 853*fa9e4066Sahrens v.a_un.a_str = "-e"; 854*fa9e4066Sahrens 855*fa9e4066Sahrens mdb_printf("\n"); 856*fa9e4066Sahrens mdb_inc_indent(4); 857*fa9e4066Sahrens if (mdb_call_dcmd("spa_vdevs", addr, flags, errors ? 1 : 0, 858*fa9e4066Sahrens &v) != DCMD_OK) 859*fa9e4066Sahrens return (DCMD_ERR); 860*fa9e4066Sahrens mdb_dec_indent(4); 861*fa9e4066Sahrens } 862*fa9e4066Sahrens 863*fa9e4066Sahrens return (DCMD_OK); 864*fa9e4066Sahrens } 865*fa9e4066Sahrens 866*fa9e4066Sahrens /* 867*fa9e4066Sahrens * ::spa_config 868*fa9e4066Sahrens * 869*fa9e4066Sahrens * Given a spa_t, print the configuration information stored in spa_config. 870*fa9e4066Sahrens * Since it's just an nvlist, format it as an indented list of name=value pairs. 871*fa9e4066Sahrens * We simply read the value of spa_config and pass off to ::nvlist. 872*fa9e4066Sahrens */ 873*fa9e4066Sahrens /* ARGSUSED */ 874*fa9e4066Sahrens static int 875*fa9e4066Sahrens spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 876*fa9e4066Sahrens { 877*fa9e4066Sahrens spa_t spa; 878*fa9e4066Sahrens 879*fa9e4066Sahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 880*fa9e4066Sahrens return (DCMD_USAGE); 881*fa9e4066Sahrens 882*fa9e4066Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 883*fa9e4066Sahrens mdb_warn("failed to read spa_t at %p", addr); 884*fa9e4066Sahrens return (DCMD_ERR); 885*fa9e4066Sahrens } 886*fa9e4066Sahrens 887*fa9e4066Sahrens if (spa.spa_config == NULL) { 888*fa9e4066Sahrens mdb_printf("(none)\n"); 889*fa9e4066Sahrens return (DCMD_OK); 890*fa9e4066Sahrens } 891*fa9e4066Sahrens 892*fa9e4066Sahrens return (mdb_call_dcmd("nvlist", (uintptr_t)spa.spa_config, flags, 893*fa9e4066Sahrens 0, NULL)); 894*fa9e4066Sahrens } 895*fa9e4066Sahrens 896*fa9e4066Sahrens void 897*fa9e4066Sahrens vdev_help(void) 898*fa9e4066Sahrens { 899*fa9e4066Sahrens mdb_printf("[vdev_t*]::vdev [-qr]\n" 900*fa9e4066Sahrens "\t-> -q display vdev_queue parameters\n" 901*fa9e4066Sahrens "\t-> -r recursive (visit all children)\n"); 902*fa9e4066Sahrens } 903*fa9e4066Sahrens 904*fa9e4066Sahrens /* 905*fa9e4066Sahrens * ::vdev 906*fa9e4066Sahrens * 907*fa9e4066Sahrens * Print out a summarized vdev_t, in the following form: 908*fa9e4066Sahrens * 909*fa9e4066Sahrens * ADDR STATE AUX DESC 910*fa9e4066Sahrens * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0 911*fa9e4066Sahrens * 912*fa9e4066Sahrens * or with "-q" to print out a vdev_t's vdev_queue parameters: 913*fa9e4066Sahrens * 914*fa9e4066Sahrens * vdev_t: c26ae4c0 915*fa9e4066Sahrens * c26ae73c min pending 0x2 916*fa9e4066Sahrens * c26ae744 max pending 0x23 917*fa9e4066Sahrens * c26ae74c agg limit 0x20000 918*fa9e4066Sahrens * c26ae754 time shift 0x4 919*fa9e4066Sahrens * c26ae75c ramp rate 0x2 920*fa9e4066Sahrens * 921*fa9e4066Sahrens * If '-r' is specified, recursively visit all children. 922*fa9e4066Sahrens * 923*fa9e4066Sahrens * With '-e', the statistics associated with the vdev are printed as well. 924*fa9e4066Sahrens */ 925*fa9e4066Sahrens static int 926*fa9e4066Sahrens do_print_vdev(uintptr_t addr, int flags, int depth, int queue, int stats, 927*fa9e4066Sahrens int recursive) 928*fa9e4066Sahrens { 929*fa9e4066Sahrens vdev_t vdev; 930*fa9e4066Sahrens char desc[MAXNAMELEN]; 931*fa9e4066Sahrens int c, children; 932*fa9e4066Sahrens uintptr_t *child; 933*fa9e4066Sahrens const char *state, *aux; 934*fa9e4066Sahrens 935*fa9e4066Sahrens if (mdb_vread(&vdev, sizeof (vdev), (uintptr_t)addr) == -1) { 936*fa9e4066Sahrens mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr); 937*fa9e4066Sahrens return (DCMD_ERR); 938*fa9e4066Sahrens } 939*fa9e4066Sahrens 940*fa9e4066Sahrens if (flags & DCMD_PIPE_OUT) { 941*fa9e4066Sahrens mdb_printf("%#lr", addr); 942*fa9e4066Sahrens } else { 943*fa9e4066Sahrens if (vdev.vdev_path != NULL) { 944*fa9e4066Sahrens if (mdb_readstr(desc, sizeof (desc), 945*fa9e4066Sahrens (uintptr_t)vdev.vdev_path) == -1) { 946*fa9e4066Sahrens mdb_warn("failed to read vdev_path at %p\n", 947*fa9e4066Sahrens vdev.vdev_path); 948*fa9e4066Sahrens return (DCMD_ERR); 949*fa9e4066Sahrens } 950*fa9e4066Sahrens } else if (vdev.vdev_ops != NULL) { 951*fa9e4066Sahrens vdev_ops_t ops; 952*fa9e4066Sahrens if (mdb_vread(&ops, sizeof (ops), 953*fa9e4066Sahrens (uintptr_t)vdev.vdev_ops) == -1) { 954*fa9e4066Sahrens mdb_warn("failed to read vdev_ops at %p\n", 955*fa9e4066Sahrens vdev.vdev_ops); 956*fa9e4066Sahrens return (DCMD_ERR); 957*fa9e4066Sahrens } 958*fa9e4066Sahrens (void) strcpy(desc, ops.vdev_op_type); 959*fa9e4066Sahrens } else { 960*fa9e4066Sahrens (void) strcpy(desc, "<unknown>"); 961*fa9e4066Sahrens } 962*fa9e4066Sahrens 963*fa9e4066Sahrens if (depth == 0 && DCMD_HDRSPEC(flags)) 964*fa9e4066Sahrens mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n", 965*fa9e4066Sahrens "ADDR", "STATE", "AUX", 966*fa9e4066Sahrens sizeof (uintptr_t) == 4 ? 43 : 35, 967*fa9e4066Sahrens "DESCRIPTION"); 968*fa9e4066Sahrens 969*fa9e4066Sahrens mdb_printf("%0?p ", addr); 970*fa9e4066Sahrens 971*fa9e4066Sahrens switch (vdev.vdev_state) { 972*fa9e4066Sahrens case VDEV_STATE_CLOSED: 973*fa9e4066Sahrens state = "CLOSED"; 974*fa9e4066Sahrens break; 975*fa9e4066Sahrens case VDEV_STATE_OFFLINE: 976*fa9e4066Sahrens state = "OFFLINE"; 977*fa9e4066Sahrens break; 978*fa9e4066Sahrens case VDEV_STATE_CANT_OPEN: 979*fa9e4066Sahrens state = "CANT_OPEN"; 980*fa9e4066Sahrens break; 981*fa9e4066Sahrens case VDEV_STATE_DEGRADED: 982*fa9e4066Sahrens state = "DEGRADED"; 983*fa9e4066Sahrens break; 984*fa9e4066Sahrens case VDEV_STATE_HEALTHY: 985*fa9e4066Sahrens state = "HEALTHY"; 986*fa9e4066Sahrens break; 987*fa9e4066Sahrens default: 988*fa9e4066Sahrens state = "UNKNOWN"; 989*fa9e4066Sahrens break; 990*fa9e4066Sahrens } 991*fa9e4066Sahrens 992*fa9e4066Sahrens switch (vdev.vdev_stat.vs_aux) { 993*fa9e4066Sahrens case VDEV_AUX_NONE: 994*fa9e4066Sahrens aux = "-"; 995*fa9e4066Sahrens break; 996*fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 997*fa9e4066Sahrens aux = "OPEN_FAILED"; 998*fa9e4066Sahrens break; 999*fa9e4066Sahrens case VDEV_AUX_CORRUPT_DATA: 1000*fa9e4066Sahrens aux = "CORRUPT_DATA"; 1001*fa9e4066Sahrens break; 1002*fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1003*fa9e4066Sahrens aux = "NO_REPLICAS"; 1004*fa9e4066Sahrens break; 1005*fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1006*fa9e4066Sahrens aux = "BAD_GUID_SUM"; 1007*fa9e4066Sahrens break; 1008*fa9e4066Sahrens case VDEV_AUX_TOO_SMALL: 1009*fa9e4066Sahrens aux = "TOO_SMALL"; 1010*fa9e4066Sahrens break; 1011*fa9e4066Sahrens case VDEV_AUX_BAD_LABEL: 1012*fa9e4066Sahrens aux = "BAD_LABEL"; 1013*fa9e4066Sahrens break; 1014*fa9e4066Sahrens default: 1015*fa9e4066Sahrens aux = "UNKNOWN"; 1016*fa9e4066Sahrens break; 1017*fa9e4066Sahrens } 1018*fa9e4066Sahrens 1019*fa9e4066Sahrens mdb_printf("%-9s %-12s %*s%s\n", state, aux, depth, "", desc); 1020*fa9e4066Sahrens 1021*fa9e4066Sahrens if (queue) { 1022*fa9e4066Sahrens mdb_inc_indent(4); 1023*fa9e4066Sahrens mdb_printf("\n"); 1024*fa9e4066Sahrens mdb_printf("%p min pending 0x%llx\n", 1025*fa9e4066Sahrens (uintptr_t)(addr + offsetof(vdev_t, 1026*fa9e4066Sahrens vdev_queue.vq_min_pending)), 1027*fa9e4066Sahrens vdev.vdev_queue.vq_min_pending); 1028*fa9e4066Sahrens mdb_printf("%p max pending 0x%llx\n", 1029*fa9e4066Sahrens (uintptr_t)(addr + offsetof(vdev_t, 1030*fa9e4066Sahrens vdev_queue.vq_max_pending)), 1031*fa9e4066Sahrens vdev.vdev_queue.vq_max_pending); 1032*fa9e4066Sahrens mdb_printf("%p agg limit 0x%llx\n", 1033*fa9e4066Sahrens (uintptr_t)(addr + offsetof(vdev_t, 1034*fa9e4066Sahrens vdev_queue.vq_agg_limit)), 1035*fa9e4066Sahrens vdev.vdev_queue.vq_agg_limit); 1036*fa9e4066Sahrens mdb_printf("%p time shift 0x%llx\n", 1037*fa9e4066Sahrens (uintptr_t)(addr + offsetof(vdev_t, 1038*fa9e4066Sahrens vdev_queue.vq_time_shift)), 1039*fa9e4066Sahrens vdev.vdev_queue.vq_time_shift); 1040*fa9e4066Sahrens mdb_printf("%p ramp rate 0x%llx\n", 1041*fa9e4066Sahrens (uintptr_t)(addr + offsetof(vdev_t, 1042*fa9e4066Sahrens vdev_queue.vq_ramp_rate)), 1043*fa9e4066Sahrens vdev.vdev_queue.vq_ramp_rate); 1044*fa9e4066Sahrens mdb_dec_indent(4); 1045*fa9e4066Sahrens } 1046*fa9e4066Sahrens 1047*fa9e4066Sahrens if (stats) { 1048*fa9e4066Sahrens vdev_stat_t *vs = &vdev.vdev_stat; 1049*fa9e4066Sahrens int i; 1050*fa9e4066Sahrens 1051*fa9e4066Sahrens mdb_inc_indent(4); 1052*fa9e4066Sahrens mdb_printf("\n"); 1053*fa9e4066Sahrens mdb_printf("%<u> %12s %12s %12s %12s " 1054*fa9e4066Sahrens "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM", 1055*fa9e4066Sahrens "IOCTL"); 1056*fa9e4066Sahrens mdb_printf("OPS "); 1057*fa9e4066Sahrens for (i = 1; i < ZIO_TYPES; i++) 1058*fa9e4066Sahrens mdb_printf("%11#llx%s", vs->vs_ops[i], 1059*fa9e4066Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1060*fa9e4066Sahrens mdb_printf("\n"); 1061*fa9e4066Sahrens mdb_printf("BYTES "); 1062*fa9e4066Sahrens for (i = 1; i < ZIO_TYPES; i++) 1063*fa9e4066Sahrens mdb_printf("%11#llx%s", vs->vs_bytes[i], 1064*fa9e4066Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1065*fa9e4066Sahrens 1066*fa9e4066Sahrens 1067*fa9e4066Sahrens mdb_printf("\n"); 1068*fa9e4066Sahrens mdb_printf("EREAD %10#llx\n", vs->vs_read_errors); 1069*fa9e4066Sahrens mdb_printf("EWRITE %10#llx\n", vs->vs_write_errors); 1070*fa9e4066Sahrens mdb_printf("ECKSUM %10#llx\n", 1071*fa9e4066Sahrens vs->vs_checksum_errors); 1072*fa9e4066Sahrens mdb_dec_indent(4); 1073*fa9e4066Sahrens } 1074*fa9e4066Sahrens 1075*fa9e4066Sahrens if (queue || stats) 1076*fa9e4066Sahrens mdb_printf("\n"); 1077*fa9e4066Sahrens } 1078*fa9e4066Sahrens 1079*fa9e4066Sahrens children = vdev.vdev_children; 1080*fa9e4066Sahrens 1081*fa9e4066Sahrens if (children == 0 || !recursive) 1082*fa9e4066Sahrens return (DCMD_OK); 1083*fa9e4066Sahrens 1084*fa9e4066Sahrens child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1085*fa9e4066Sahrens if (mdb_vread(child, children * sizeof (void *), 1086*fa9e4066Sahrens (uintptr_t)vdev.vdev_child) == -1) { 1087*fa9e4066Sahrens mdb_warn("failed to read vdev children at %p", vdev.vdev_child); 1088*fa9e4066Sahrens return (DCMD_ERR); 1089*fa9e4066Sahrens } 1090*fa9e4066Sahrens 1091*fa9e4066Sahrens for (c = 0; c < children; c++) { 1092*fa9e4066Sahrens if (do_print_vdev(child[c], flags, depth + 2, queue, stats, 1093*fa9e4066Sahrens recursive)) 1094*fa9e4066Sahrens return (DCMD_ERR); 1095*fa9e4066Sahrens } 1096*fa9e4066Sahrens 1097*fa9e4066Sahrens return (DCMD_OK); 1098*fa9e4066Sahrens } 1099*fa9e4066Sahrens 1100*fa9e4066Sahrens static int 1101*fa9e4066Sahrens vdev_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1102*fa9e4066Sahrens { 1103*fa9e4066Sahrens int print_queue = FALSE; 1104*fa9e4066Sahrens int recursive = FALSE; 1105*fa9e4066Sahrens int stats = FALSE; 1106*fa9e4066Sahrens 1107*fa9e4066Sahrens if (mdb_getopts(argc, argv, 1108*fa9e4066Sahrens 'q', MDB_OPT_SETBITS, TRUE, &print_queue, 1109*fa9e4066Sahrens 'r', MDB_OPT_SETBITS, TRUE, &recursive, 1110*fa9e4066Sahrens 'e', MDB_OPT_SETBITS, TRUE, &stats, 1111*fa9e4066Sahrens NULL) != argc) 1112*fa9e4066Sahrens return (DCMD_USAGE); 1113*fa9e4066Sahrens 1114*fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) { 1115*fa9e4066Sahrens mdb_warn("no vdev_t address given\n"); 1116*fa9e4066Sahrens return (DCMD_ERR); 1117*fa9e4066Sahrens } 1118*fa9e4066Sahrens 1119*fa9e4066Sahrens return (do_print_vdev(addr, flags, 0, print_queue, stats, recursive)); 1120*fa9e4066Sahrens } 1121*fa9e4066Sahrens 1122*fa9e4066Sahrens typedef struct mdb_spa { 1123*fa9e4066Sahrens uintptr_t spa_dsl_pool; 1124*fa9e4066Sahrens uintptr_t spa_root_vdev; 1125*fa9e4066Sahrens } mdb_spa_t; 1126*fa9e4066Sahrens 1127*fa9e4066Sahrens typedef struct mdb_dsl_dir { 1128*fa9e4066Sahrens uintptr_t dd_phys; 1129*fa9e4066Sahrens uint64_t dd_used_bytes; 1130*fa9e4066Sahrens int64_t dd_space_towrite[TXG_SIZE]; 1131*fa9e4066Sahrens } mdb_dsl_dir_t; 1132*fa9e4066Sahrens 1133*fa9e4066Sahrens typedef struct mdb_dsl_dir_phys { 1134*fa9e4066Sahrens uint64_t dd_used_bytes; 1135*fa9e4066Sahrens uint64_t dd_compressed_bytes; 1136*fa9e4066Sahrens uint64_t dd_uncompressed_bytes; 1137*fa9e4066Sahrens } mdb_dsl_dir_phys_t; 1138*fa9e4066Sahrens 1139*fa9e4066Sahrens typedef struct mdb_vdev { 1140*fa9e4066Sahrens uintptr_t vdev_parent; 1141*fa9e4066Sahrens uintptr_t vdev_ms; 1142*fa9e4066Sahrens uint64_t vdev_ms_count; 1143*fa9e4066Sahrens vdev_stat_t vdev_stat; 1144*fa9e4066Sahrens } mdb_vdev_t; 1145*fa9e4066Sahrens 1146*fa9e4066Sahrens typedef struct mdb_metaslab { 1147*fa9e4066Sahrens space_map_t ms_allocmap[TXG_SIZE]; 1148*fa9e4066Sahrens space_map_t ms_freemap[TXG_SIZE]; 1149*fa9e4066Sahrens space_map_t ms_map; 1150*fa9e4066Sahrens uint64_t ms_usable_space; 1151*fa9e4066Sahrens } mdb_metaslab_t; 1152*fa9e4066Sahrens 1153*fa9e4066Sahrens /* 1154*fa9e4066Sahrens * ::spa_space [-b] 1155*fa9e4066Sahrens * 1156*fa9e4066Sahrens * Given a spa_t, print out it's on-disk space usage and in-core 1157*fa9e4066Sahrens * estimates of future usage. If -b is given, print space in bytes. 1158*fa9e4066Sahrens * Otherwise print in megabytes. 1159*fa9e4066Sahrens */ 1160*fa9e4066Sahrens /* ARGSUSED */ 1161*fa9e4066Sahrens static int 1162*fa9e4066Sahrens spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1163*fa9e4066Sahrens { 1164*fa9e4066Sahrens mdb_spa_t spa; 1165*fa9e4066Sahrens uintptr_t dp_root_dir; 1166*fa9e4066Sahrens mdb_dsl_dir_t dd; 1167*fa9e4066Sahrens mdb_dsl_dir_phys_t dsp; 1168*fa9e4066Sahrens uint64_t children; 1169*fa9e4066Sahrens uintptr_t childaddr; 1170*fa9e4066Sahrens uintptr_t *child; 1171*fa9e4066Sahrens uint64_t ms_allocmap[TXG_SIZE] = {0, 0, 0, 0}; 1172*fa9e4066Sahrens uint64_t ms_freemap[TXG_SIZE] = {0, 0, 0, 0}; 1173*fa9e4066Sahrens uint64_t ms_map = 0; 1174*fa9e4066Sahrens uint64_t ms_usable_space = 0; 1175*fa9e4066Sahrens int i, j; 1176*fa9e4066Sahrens int havecompressed = TRUE; 1177*fa9e4066Sahrens int shift = 20; 1178*fa9e4066Sahrens char *suffix = "M"; 1179*fa9e4066Sahrens int bits = FALSE; 1180*fa9e4066Sahrens 1181*fa9e4066Sahrens if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bits, NULL) != 1182*fa9e4066Sahrens argc) 1183*fa9e4066Sahrens return (DCMD_USAGE); 1184*fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) 1185*fa9e4066Sahrens return (DCMD_USAGE); 1186*fa9e4066Sahrens 1187*fa9e4066Sahrens if (bits) { 1188*fa9e4066Sahrens shift = 0; 1189*fa9e4066Sahrens suffix = ""; 1190*fa9e4066Sahrens } 1191*fa9e4066Sahrens 1192*fa9e4066Sahrens if (GETMEMB(addr, struct spa, spa_dsl_pool, spa.spa_dsl_pool) || 1193*fa9e4066Sahrens GETMEMB(addr, struct spa, spa_root_vdev, spa.spa_root_vdev) || 1194*fa9e4066Sahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_children, children) || 1195*fa9e4066Sahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_child, childaddr) || 1196*fa9e4066Sahrens GETMEMB(spa.spa_dsl_pool, struct dsl_pool, 1197*fa9e4066Sahrens dp_root_dir, dp_root_dir) || 1198*fa9e4066Sahrens GETMEMB(dp_root_dir, struct dsl_dir, dd_phys, dd.dd_phys) || 1199*fa9e4066Sahrens GETMEMB(dp_root_dir, struct dsl_dir, 1200*fa9e4066Sahrens dd_used_bytes, dd.dd_used_bytes) || 1201*fa9e4066Sahrens GETMEMB(dp_root_dir, struct dsl_dir, 1202*fa9e4066Sahrens dd_space_towrite, dd.dd_space_towrite) || 1203*fa9e4066Sahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1204*fa9e4066Sahrens dd_used_bytes, dsp.dd_used_bytes)) { 1205*fa9e4066Sahrens return (DCMD_ERR); 1206*fa9e4066Sahrens } 1207*fa9e4066Sahrens 1208*fa9e4066Sahrens if (GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1209*fa9e4066Sahrens dd_compressed_bytes, dsp.dd_compressed_bytes) || 1210*fa9e4066Sahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1211*fa9e4066Sahrens dd_uncompressed_bytes, dsp.dd_uncompressed_bytes)) { 1212*fa9e4066Sahrens havecompressed = FALSE; 1213*fa9e4066Sahrens } 1214*fa9e4066Sahrens 1215*fa9e4066Sahrens child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1216*fa9e4066Sahrens if (mdb_vread(child, children * sizeof (void *), childaddr) == -1) { 1217*fa9e4066Sahrens mdb_warn("failed to read root vdev children at %p", childaddr); 1218*fa9e4066Sahrens return (DCMD_ERR); 1219*fa9e4066Sahrens } 1220*fa9e4066Sahrens 1221*fa9e4066Sahrens mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n", 1222*fa9e4066Sahrens dd.dd_space_towrite[0] >> shift, suffix, 1223*fa9e4066Sahrens dd.dd_space_towrite[1] >> shift, suffix, 1224*fa9e4066Sahrens dd.dd_space_towrite[2] >> shift, suffix, 1225*fa9e4066Sahrens dd.dd_space_towrite[3] >> shift, suffix); 1226*fa9e4066Sahrens mdb_printf("dd_used_bytes = %llu%s\n", 1227*fa9e4066Sahrens dd.dd_used_bytes >> shift, suffix); 1228*fa9e4066Sahrens 1229*fa9e4066Sahrens mdb_printf("dd_phys.dd_used_bytes = %llu%s\n", 1230*fa9e4066Sahrens dsp.dd_used_bytes >> shift, suffix); 1231*fa9e4066Sahrens if (havecompressed) { 1232*fa9e4066Sahrens mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n", 1233*fa9e4066Sahrens dsp.dd_compressed_bytes >> shift, suffix); 1234*fa9e4066Sahrens mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n", 1235*fa9e4066Sahrens dsp.dd_uncompressed_bytes >> shift, suffix); 1236*fa9e4066Sahrens } 1237*fa9e4066Sahrens 1238*fa9e4066Sahrens for (i = 0; i < children; i++) { 1239*fa9e4066Sahrens mdb_vdev_t vd; 1240*fa9e4066Sahrens uintptr_t *vdev_ms; 1241*fa9e4066Sahrens 1242*fa9e4066Sahrens if (GETMEMB(child[i], struct vdev, 1243*fa9e4066Sahrens vdev_parent, vd.vdev_parent) || 1244*fa9e4066Sahrens GETMEMB(child[i], struct vdev, 1245*fa9e4066Sahrens vdev_stat, vd.vdev_stat) || 1246*fa9e4066Sahrens GETMEMB(child[i], struct vdev, vdev_ms, vd.vdev_ms) || 1247*fa9e4066Sahrens GETMEMB(child[i], struct vdev, 1248*fa9e4066Sahrens vdev_ms_count, vd.vdev_ms_count)) { 1249*fa9e4066Sahrens return (DCMD_ERR); 1250*fa9e4066Sahrens } 1251*fa9e4066Sahrens 1252*fa9e4066Sahrens /* 1253*fa9e4066Sahrens * If this is the root vdev, its stats are the pool-wide stats. 1254*fa9e4066Sahrens */ 1255*fa9e4066Sahrens if (vd.vdev_parent == NULL) { 1256*fa9e4066Sahrens mdb_printf("pool_alloc = %llu%s\n", 1257*fa9e4066Sahrens vd.vdev_stat.vs_alloc >> shift, suffix); 1258*fa9e4066Sahrens mdb_printf("pool_space = %llu%s\n", 1259*fa9e4066Sahrens vd.vdev_stat.vs_space >> shift, suffix); 1260*fa9e4066Sahrens } 1261*fa9e4066Sahrens 1262*fa9e4066Sahrens /* 1263*fa9e4066Sahrens * If this is not a top-level vdev, it doesn't have space. 1264*fa9e4066Sahrens */ 1265*fa9e4066Sahrens if (vd.vdev_parent != spa.spa_root_vdev) 1266*fa9e4066Sahrens continue; 1267*fa9e4066Sahrens 1268*fa9e4066Sahrens vdev_ms = mdb_alloc(vd.vdev_ms_count * sizeof (void*), 1269*fa9e4066Sahrens UM_SLEEP | UM_GC); 1270*fa9e4066Sahrens if (mdb_vread(vdev_ms, vd.vdev_ms_count * sizeof (void*), 1271*fa9e4066Sahrens (uintptr_t)vd.vdev_ms) == -1) { 1272*fa9e4066Sahrens mdb_warn("failed to read vdev_ms at %p", vd.vdev_ms); 1273*fa9e4066Sahrens return (DCMD_ERR); 1274*fa9e4066Sahrens } 1275*fa9e4066Sahrens 1276*fa9e4066Sahrens for (j = 0; j < vd.vdev_ms_count; j++) { 1277*fa9e4066Sahrens mdb_metaslab_t ms; 1278*fa9e4066Sahrens 1279*fa9e4066Sahrens if (GETMEMB(vdev_ms[j], struct metaslab, 1280*fa9e4066Sahrens ms_allocmap, ms.ms_allocmap) || 1281*fa9e4066Sahrens GETMEMB(vdev_ms[j], struct metaslab, 1282*fa9e4066Sahrens ms_freemap, ms.ms_freemap) || 1283*fa9e4066Sahrens GETMEMB(vdev_ms[j], struct metaslab, 1284*fa9e4066Sahrens ms_map, ms.ms_map) || 1285*fa9e4066Sahrens GETMEMB(vdev_ms[j], struct metaslab, 1286*fa9e4066Sahrens ms_usable_space, ms.ms_usable_space)) { 1287*fa9e4066Sahrens return (DCMD_ERR); 1288*fa9e4066Sahrens } 1289*fa9e4066Sahrens 1290*fa9e4066Sahrens ms_allocmap[0] += ms.ms_allocmap[0].sm_space; 1291*fa9e4066Sahrens ms_allocmap[1] += ms.ms_allocmap[1].sm_space; 1292*fa9e4066Sahrens ms_allocmap[2] += ms.ms_allocmap[2].sm_space; 1293*fa9e4066Sahrens ms_allocmap[3] += ms.ms_allocmap[3].sm_space; 1294*fa9e4066Sahrens ms_freemap[0] += ms.ms_freemap[0].sm_space; 1295*fa9e4066Sahrens ms_freemap[1] += ms.ms_freemap[1].sm_space; 1296*fa9e4066Sahrens ms_freemap[2] += ms.ms_freemap[2].sm_space; 1297*fa9e4066Sahrens ms_freemap[3] += ms.ms_freemap[3].sm_space; 1298*fa9e4066Sahrens ms_map += ms.ms_map.sm_space; 1299*fa9e4066Sahrens ms_usable_space += ms.ms_usable_space; 1300*fa9e4066Sahrens } 1301*fa9e4066Sahrens } 1302*fa9e4066Sahrens 1303*fa9e4066Sahrens mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n", 1304*fa9e4066Sahrens ms_allocmap[0] >> shift, suffix, 1305*fa9e4066Sahrens ms_allocmap[1] >> shift, suffix, 1306*fa9e4066Sahrens ms_allocmap[2] >> shift, suffix, 1307*fa9e4066Sahrens ms_allocmap[3] >> shift, suffix); 1308*fa9e4066Sahrens mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n", 1309*fa9e4066Sahrens ms_freemap[0] >> shift, suffix, 1310*fa9e4066Sahrens ms_freemap[1] >> shift, suffix, 1311*fa9e4066Sahrens ms_freemap[2] >> shift, suffix, 1312*fa9e4066Sahrens ms_freemap[3] >> shift, suffix); 1313*fa9e4066Sahrens mdb_printf("ms_map = %llu%s\n", ms_map >> shift, suffix); 1314*fa9e4066Sahrens mdb_printf("ms_usable_space = %llu%s\n", 1315*fa9e4066Sahrens ms_usable_space >> shift, suffix); 1316*fa9e4066Sahrens 1317*fa9e4066Sahrens return (DCMD_OK); 1318*fa9e4066Sahrens } 1319*fa9e4066Sahrens 1320*fa9e4066Sahrens /* 1321*fa9e4066Sahrens * ::spa_verify 1322*fa9e4066Sahrens * 1323*fa9e4066Sahrens * Given a spa_t, verify that that the pool is self-consistent. 1324*fa9e4066Sahrens * Currently, it only checks to make sure that the vdev tree exists. 1325*fa9e4066Sahrens */ 1326*fa9e4066Sahrens /* ARGSUSED */ 1327*fa9e4066Sahrens static int 1328*fa9e4066Sahrens spa_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1329*fa9e4066Sahrens { 1330*fa9e4066Sahrens spa_t spa; 1331*fa9e4066Sahrens 1332*fa9e4066Sahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1333*fa9e4066Sahrens return (DCMD_USAGE); 1334*fa9e4066Sahrens 1335*fa9e4066Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1336*fa9e4066Sahrens mdb_warn("failed to read spa_t at %p", addr); 1337*fa9e4066Sahrens return (DCMD_ERR); 1338*fa9e4066Sahrens } 1339*fa9e4066Sahrens 1340*fa9e4066Sahrens if (spa.spa_root_vdev == NULL) { 1341*fa9e4066Sahrens mdb_printf("no vdev tree present\n"); 1342*fa9e4066Sahrens return (DCMD_OK); 1343*fa9e4066Sahrens } 1344*fa9e4066Sahrens 1345*fa9e4066Sahrens return (DCMD_OK); 1346*fa9e4066Sahrens } 1347*fa9e4066Sahrens 1348*fa9e4066Sahrens /* 1349*fa9e4066Sahrens * ::spa_vdevs 1350*fa9e4066Sahrens * 1351*fa9e4066Sahrens * -e Include error stats 1352*fa9e4066Sahrens * 1353*fa9e4066Sahrens * Print out a summarized list of vdevs for the given spa_t. 1354*fa9e4066Sahrens * This is accomplished by invoking "::vdev -re" on the root vdev. 1355*fa9e4066Sahrens */ 1356*fa9e4066Sahrens /* ARGSUSED */ 1357*fa9e4066Sahrens static int 1358*fa9e4066Sahrens spa_vdevs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1359*fa9e4066Sahrens { 1360*fa9e4066Sahrens spa_t spa; 1361*fa9e4066Sahrens mdb_arg_t v; 1362*fa9e4066Sahrens int errors = FALSE; 1363*fa9e4066Sahrens 1364*fa9e4066Sahrens if (mdb_getopts(argc, argv, 1365*fa9e4066Sahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 1366*fa9e4066Sahrens NULL) != argc) 1367*fa9e4066Sahrens return (DCMD_USAGE); 1368*fa9e4066Sahrens 1369*fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) 1370*fa9e4066Sahrens return (DCMD_USAGE); 1371*fa9e4066Sahrens 1372*fa9e4066Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1373*fa9e4066Sahrens mdb_warn("failed to read spa_t at %p", addr); 1374*fa9e4066Sahrens return (DCMD_ERR); 1375*fa9e4066Sahrens } 1376*fa9e4066Sahrens 1377*fa9e4066Sahrens v.a_type = MDB_TYPE_STRING; 1378*fa9e4066Sahrens v.a_un.a_str = errors ? "-re" : "-r"; 1379*fa9e4066Sahrens 1380*fa9e4066Sahrens return (mdb_call_dcmd("vdev", (uintptr_t)spa.spa_root_vdev, 1381*fa9e4066Sahrens flags, 1, &v)); 1382*fa9e4066Sahrens } 1383*fa9e4066Sahrens 1384*fa9e4066Sahrens typedef struct txg_list_walk_data { 1385*fa9e4066Sahrens uintptr_t lw_head[TXG_SIZE]; 1386*fa9e4066Sahrens int lw_txgoff; 1387*fa9e4066Sahrens int lw_maxoff; 1388*fa9e4066Sahrens size_t lw_offset; 1389*fa9e4066Sahrens void *lw_obj; 1390*fa9e4066Sahrens } txg_list_walk_data_t; 1391*fa9e4066Sahrens 1392*fa9e4066Sahrens static int 1393*fa9e4066Sahrens txg_list_walk_init_common(mdb_walk_state_t *wsp, int txg, int maxoff) 1394*fa9e4066Sahrens { 1395*fa9e4066Sahrens txg_list_walk_data_t *lwd; 1396*fa9e4066Sahrens txg_list_t list; 1397*fa9e4066Sahrens int i; 1398*fa9e4066Sahrens 1399*fa9e4066Sahrens lwd = mdb_alloc(sizeof (txg_list_walk_data_t), UM_SLEEP | UM_GC); 1400*fa9e4066Sahrens if (mdb_vread(&list, sizeof (txg_list_t), wsp->walk_addr) == -1) { 1401*fa9e4066Sahrens mdb_warn("failed to read txg_list_t at %#lx", wsp->walk_addr); 1402*fa9e4066Sahrens return (WALK_ERR); 1403*fa9e4066Sahrens } 1404*fa9e4066Sahrens 1405*fa9e4066Sahrens for (i = 0; i < TXG_SIZE; i++) 1406*fa9e4066Sahrens lwd->lw_head[i] = (uintptr_t)list.tl_head[i]; 1407*fa9e4066Sahrens lwd->lw_offset = list.tl_offset; 1408*fa9e4066Sahrens lwd->lw_obj = mdb_alloc(lwd->lw_offset + sizeof (txg_node_t), 1409*fa9e4066Sahrens UM_SLEEP | UM_GC); 1410*fa9e4066Sahrens lwd->lw_txgoff = txg; 1411*fa9e4066Sahrens lwd->lw_maxoff = maxoff; 1412*fa9e4066Sahrens 1413*fa9e4066Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1414*fa9e4066Sahrens wsp->walk_data = lwd; 1415*fa9e4066Sahrens 1416*fa9e4066Sahrens return (WALK_NEXT); 1417*fa9e4066Sahrens } 1418*fa9e4066Sahrens 1419*fa9e4066Sahrens static int 1420*fa9e4066Sahrens txg_list_walk_init(mdb_walk_state_t *wsp) 1421*fa9e4066Sahrens { 1422*fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 0, TXG_SIZE-1)); 1423*fa9e4066Sahrens } 1424*fa9e4066Sahrens 1425*fa9e4066Sahrens static int 1426*fa9e4066Sahrens txg_list0_walk_init(mdb_walk_state_t *wsp) 1427*fa9e4066Sahrens { 1428*fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 0, 0)); 1429*fa9e4066Sahrens } 1430*fa9e4066Sahrens 1431*fa9e4066Sahrens static int 1432*fa9e4066Sahrens txg_list1_walk_init(mdb_walk_state_t *wsp) 1433*fa9e4066Sahrens { 1434*fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 1, 1)); 1435*fa9e4066Sahrens } 1436*fa9e4066Sahrens 1437*fa9e4066Sahrens static int 1438*fa9e4066Sahrens txg_list2_walk_init(mdb_walk_state_t *wsp) 1439*fa9e4066Sahrens { 1440*fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 2, 2)); 1441*fa9e4066Sahrens } 1442*fa9e4066Sahrens 1443*fa9e4066Sahrens static int 1444*fa9e4066Sahrens txg_list3_walk_init(mdb_walk_state_t *wsp) 1445*fa9e4066Sahrens { 1446*fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 3, 3)); 1447*fa9e4066Sahrens } 1448*fa9e4066Sahrens 1449*fa9e4066Sahrens static int 1450*fa9e4066Sahrens txg_list_walk_step(mdb_walk_state_t *wsp) 1451*fa9e4066Sahrens { 1452*fa9e4066Sahrens txg_list_walk_data_t *lwd = wsp->walk_data; 1453*fa9e4066Sahrens uintptr_t addr; 1454*fa9e4066Sahrens txg_node_t *node; 1455*fa9e4066Sahrens int status; 1456*fa9e4066Sahrens 1457*fa9e4066Sahrens while (wsp->walk_addr == NULL && lwd->lw_txgoff < lwd->lw_maxoff) { 1458*fa9e4066Sahrens lwd->lw_txgoff++; 1459*fa9e4066Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1460*fa9e4066Sahrens } 1461*fa9e4066Sahrens 1462*fa9e4066Sahrens if (wsp->walk_addr == NULL) 1463*fa9e4066Sahrens return (WALK_DONE); 1464*fa9e4066Sahrens 1465*fa9e4066Sahrens addr = wsp->walk_addr - lwd->lw_offset; 1466*fa9e4066Sahrens 1467*fa9e4066Sahrens if (mdb_vread(lwd->lw_obj, 1468*fa9e4066Sahrens lwd->lw_offset + sizeof (txg_node_t), addr) == -1) { 1469*fa9e4066Sahrens mdb_warn("failed to read list element at %#lx", addr); 1470*fa9e4066Sahrens return (WALK_ERR); 1471*fa9e4066Sahrens } 1472*fa9e4066Sahrens 1473*fa9e4066Sahrens status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata); 1474*fa9e4066Sahrens node = (txg_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset); 1475*fa9e4066Sahrens wsp->walk_addr = (uintptr_t)node->tn_next[lwd->lw_txgoff]; 1476*fa9e4066Sahrens 1477*fa9e4066Sahrens return (status); 1478*fa9e4066Sahrens } 1479*fa9e4066Sahrens 1480*fa9e4066Sahrens /* ARGSUSED */ 1481*fa9e4066Sahrens static void 1482*fa9e4066Sahrens txg_list_walk_fini(mdb_walk_state_t *wsp) 1483*fa9e4066Sahrens { 1484*fa9e4066Sahrens } 1485*fa9e4066Sahrens 1486*fa9e4066Sahrens /* 1487*fa9e4066Sahrens * ::walk spa 1488*fa9e4066Sahrens * 1489*fa9e4066Sahrens * Walk all named spa_t structures in the namespace. This is nothing more than 1490*fa9e4066Sahrens * a layered avl walk. 1491*fa9e4066Sahrens */ 1492*fa9e4066Sahrens static int 1493*fa9e4066Sahrens spa_walk_init(mdb_walk_state_t *wsp) 1494*fa9e4066Sahrens { 1495*fa9e4066Sahrens GElf_Sym sym; 1496*fa9e4066Sahrens 1497*fa9e4066Sahrens if (wsp->walk_addr != NULL) { 1498*fa9e4066Sahrens mdb_warn("spa walk only supports global walks\n"); 1499*fa9e4066Sahrens return (WALK_ERR); 1500*fa9e4066Sahrens } 1501*fa9e4066Sahrens 1502*fa9e4066Sahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "spa_namespace_avl", &sym) == -1) { 1503*fa9e4066Sahrens mdb_warn("failed to find symbol 'spa_namespace_avl'"); 1504*fa9e4066Sahrens return (WALK_ERR); 1505*fa9e4066Sahrens } 1506*fa9e4066Sahrens 1507*fa9e4066Sahrens wsp->walk_addr = (uintptr_t)sym.st_value; 1508*fa9e4066Sahrens 1509*fa9e4066Sahrens if (mdb_layered_walk("avl", wsp) == -1) { 1510*fa9e4066Sahrens mdb_warn("failed to walk 'avl'\n"); 1511*fa9e4066Sahrens return (WALK_ERR); 1512*fa9e4066Sahrens } 1513*fa9e4066Sahrens 1514*fa9e4066Sahrens return (WALK_NEXT); 1515*fa9e4066Sahrens } 1516*fa9e4066Sahrens 1517*fa9e4066Sahrens static int 1518*fa9e4066Sahrens spa_walk_step(mdb_walk_state_t *wsp) 1519*fa9e4066Sahrens { 1520*fa9e4066Sahrens spa_t spa; 1521*fa9e4066Sahrens 1522*fa9e4066Sahrens if (mdb_vread(&spa, sizeof (spa), wsp->walk_addr) == -1) { 1523*fa9e4066Sahrens mdb_warn("failed to read spa_t at %p", wsp->walk_addr); 1524*fa9e4066Sahrens return (WALK_ERR); 1525*fa9e4066Sahrens } 1526*fa9e4066Sahrens 1527*fa9e4066Sahrens return (wsp->walk_callback(wsp->walk_addr, &spa, wsp->walk_cbdata)); 1528*fa9e4066Sahrens } 1529*fa9e4066Sahrens 1530*fa9e4066Sahrens /* 1531*fa9e4066Sahrens * MDB module linkage information: 1532*fa9e4066Sahrens * 1533*fa9e4066Sahrens * We declare a list of structures describing our dcmds, and a function 1534*fa9e4066Sahrens * named _mdb_init to return a pointer to our module information. 1535*fa9e4066Sahrens */ 1536*fa9e4066Sahrens 1537*fa9e4066Sahrens static const mdb_dcmd_t dcmds[] = { 1538*fa9e4066Sahrens { "blkptr", ":", "print blkptr_t", blkptr }, 1539*fa9e4066Sahrens { "dbuf", ":", "print dmu_buf_impl_t", dbuf }, 1540*fa9e4066Sahrens { "dbuf_stats", ":", "dbuf stats", dbuf_stats }, 1541*fa9e4066Sahrens { "dbufs", 1542*fa9e4066Sahrens "\t[-O objset_t*] [-n objset_name | \"mos\"] [-o object | \"mdn\"] \n" 1543*fa9e4066Sahrens "\t[-l level] [-b blkid | \"bonus\"]", 1544*fa9e4066Sahrens "find dmu_buf_impl_t's that meet criterion", dbufs }, 1545*fa9e4066Sahrens { "abuf_find", "dva_word[0] dva_word[1]", 1546*fa9e4066Sahrens "find arc_buf_hdr_t of a specified DVA", 1547*fa9e4066Sahrens abuf_find }, 1548*fa9e4066Sahrens { "spa", "?[-cv]", "spa_t summary", spa_print }, 1549*fa9e4066Sahrens { "spa_config", ":", "print spa_t configuration", spa_print_config }, 1550*fa9e4066Sahrens { "spa_verify", ":", "verify spa_t consistency", spa_verify }, 1551*fa9e4066Sahrens { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space }, 1552*fa9e4066Sahrens { "spa_vdevs", ":", "given a spa_t, print vdev summary", spa_vdevs }, 1553*fa9e4066Sahrens { "vdev", ":[-qre]", "vdev_t summary", vdev_print }, 1554*fa9e4066Sahrens { "zio_pipeline", ":", "decode a zio pipeline", zio_pipeline }, 1555*fa9e4066Sahrens { NULL } 1556*fa9e4066Sahrens }; 1557*fa9e4066Sahrens 1558*fa9e4066Sahrens static const mdb_walker_t walkers[] = { 1559*fa9e4066Sahrens /* 1560*fa9e4066Sahrens * In userland, there is no generic provider of list_t walkers, so we 1561*fa9e4066Sahrens * need to add it. 1562*fa9e4066Sahrens */ 1563*fa9e4066Sahrens #ifndef _KERNEL 1564*fa9e4066Sahrens { LIST_WALK_NAME, LIST_WALK_DESC, 1565*fa9e4066Sahrens list_walk_init, list_walk_step, list_walk_fini }, 1566*fa9e4066Sahrens #endif 1567*fa9e4066Sahrens { "dbufs", "walk cached ZFS dbufs", 1568*fa9e4066Sahrens dbuf_walk_init, dbuf_walk_step, dbuf_walk_fini }, 1569*fa9e4066Sahrens { "zms_freelist", "walk ZFS metaslab freelist", 1570*fa9e4066Sahrens freelist_walk_init, freelist_walk_step, freelist_walk_fini }, 1571*fa9e4066Sahrens { "txg_list", "given any txg_list_t *, walk all entries in all txgs", 1572*fa9e4066Sahrens txg_list_walk_init, txg_list_walk_step, txg_list_walk_fini }, 1573*fa9e4066Sahrens { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", 1574*fa9e4066Sahrens txg_list0_walk_init, txg_list_walk_step, txg_list_walk_fini }, 1575*fa9e4066Sahrens { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", 1576*fa9e4066Sahrens txg_list1_walk_init, txg_list_walk_step, txg_list_walk_fini }, 1577*fa9e4066Sahrens { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", 1578*fa9e4066Sahrens txg_list2_walk_init, txg_list_walk_step, txg_list_walk_fini }, 1579*fa9e4066Sahrens { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", 1580*fa9e4066Sahrens txg_list3_walk_init, txg_list_walk_step, txg_list_walk_fini }, 1581*fa9e4066Sahrens { "spa", "walk all spa_t entries in the namespace", 1582*fa9e4066Sahrens spa_walk_init, spa_walk_step, NULL }, 1583*fa9e4066Sahrens { NULL } 1584*fa9e4066Sahrens }; 1585*fa9e4066Sahrens 1586*fa9e4066Sahrens static const mdb_modinfo_t modinfo = { 1587*fa9e4066Sahrens MDB_API_VERSION, dcmds, walkers 1588*fa9e4066Sahrens }; 1589*fa9e4066Sahrens 1590*fa9e4066Sahrens const mdb_modinfo_t * 1591*fa9e4066Sahrens _mdb_init(void) 1592*fa9e4066Sahrens { 1593*fa9e4066Sahrens return (&modinfo); 1594*fa9e4066Sahrens } 1595