1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 2212294SMark.Musante@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23789Sahrens */ 24789Sahrens 2512294SMark.Musante@Sun.COM /* Portions Copyright 2010 Robert Milkowski */ 2612294SMark.Musante@Sun.COM 27789Sahrens #include <mdb/mdb_ctf.h> 28789Sahrens #include <sys/zfs_context.h> 29789Sahrens #include <sys/mdb_modapi.h> 30789Sahrens #include <sys/dbuf.h> 31789Sahrens #include <sys/dmu_objset.h> 32789Sahrens #include <sys/dsl_dir.h> 33789Sahrens #include <sys/dsl_pool.h> 34789Sahrens #include <sys/metaslab_impl.h> 35789Sahrens #include <sys/space_map.h> 36789Sahrens #include <sys/list.h> 37789Sahrens #include <sys/spa_impl.h> 38789Sahrens #include <sys/vdev_impl.h> 3911609SMatthew.Ahrens@Sun.COM #include <sys/zap_leaf.h> 4011609SMatthew.Ahrens@Sun.COM #include <sys/zap_impl.h> 4110407SMatthew.Ahrens@Sun.COM #include <ctype.h> 4211935SMark.Shellenbaum@Sun.COM #include <sys/zfs_acl.h> 4311935SMark.Shellenbaum@Sun.COM #include <sys/sa_impl.h> 44789Sahrens 45789Sahrens #ifndef _KERNEL 46789Sahrens #include "../genunix/list.h" 47789Sahrens #endif 48789Sahrens 49789Sahrens #ifdef _KERNEL 50789Sahrens #define ZFS_OBJ_NAME "zfs" 51789Sahrens #else 52789Sahrens #define ZFS_OBJ_NAME "libzpool.so.1" 53789Sahrens #endif 54789Sahrens 5511726SVictor.Latushkin@Sun.COM #ifndef _KERNEL 5611726SVictor.Latushkin@Sun.COM int aok; 5711726SVictor.Latushkin@Sun.COM #endif 5811726SVictor.Latushkin@Sun.COM 59789Sahrens static int 60789Sahrens getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp, 61789Sahrens const char *member, int len, void *buf) 62789Sahrens { 63789Sahrens mdb_ctf_id_t id; 64789Sahrens ulong_t off; 65789Sahrens char name[64]; 66789Sahrens 67789Sahrens if (idp == NULL) { 68789Sahrens if (mdb_ctf_lookup_by_name(type, &id) == -1) { 69789Sahrens mdb_warn("couldn't find type %s", type); 70789Sahrens return (DCMD_ERR); 71789Sahrens } 72789Sahrens idp = &id; 73789Sahrens } else { 74789Sahrens type = name; 75789Sahrens mdb_ctf_type_name(*idp, name, sizeof (name)); 76789Sahrens } 77789Sahrens 78789Sahrens if (mdb_ctf_offsetof(*idp, member, &off) == -1) { 79789Sahrens mdb_warn("couldn't find member %s of type %s\n", member, type); 80789Sahrens return (DCMD_ERR); 81789Sahrens } 82789Sahrens if (off % 8 != 0) { 83789Sahrens mdb_warn("member %s of type %s is unsupported bitfield", 84789Sahrens member, type); 85789Sahrens return (DCMD_ERR); 86789Sahrens } 87789Sahrens off /= 8; 88789Sahrens 89789Sahrens if (mdb_vread(buf, len, addr + off) == -1) { 90789Sahrens mdb_warn("failed to read %s from %s at %p", 91789Sahrens member, type, addr + off); 92789Sahrens return (DCMD_ERR); 93789Sahrens } 94789Sahrens /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */ 95789Sahrens 96789Sahrens return (0); 97789Sahrens } 98789Sahrens 99789Sahrens #define GETMEMB(addr, type, member, dest) \ 100789Sahrens getmember(addr, #type, NULL, #member, sizeof (dest), &(dest)) 101789Sahrens 102789Sahrens #define GETMEMBID(addr, ctfid, member, dest) \ 103789Sahrens getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) 104789Sahrens 105789Sahrens static int 106789Sahrens getrefcount(uintptr_t addr, mdb_ctf_id_t *id, 107789Sahrens const char *member, uint64_t *rc) 108789Sahrens { 109789Sahrens static int gotid; 110789Sahrens static mdb_ctf_id_t rc_id; 111789Sahrens ulong_t off; 112789Sahrens 113789Sahrens if (!gotid) { 114789Sahrens if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { 115789Sahrens mdb_warn("couldn't find struct refcount"); 116789Sahrens return (DCMD_ERR); 117789Sahrens } 118789Sahrens gotid = TRUE; 119789Sahrens } 120789Sahrens 121789Sahrens if (mdb_ctf_offsetof(*id, member, &off) == -1) { 122789Sahrens char name[64]; 123789Sahrens mdb_ctf_type_name(*id, name, sizeof (name)); 124789Sahrens mdb_warn("couldn't find member %s of type %s\n", member, name); 125789Sahrens return (DCMD_ERR); 126789Sahrens } 127789Sahrens off /= 8; 128789Sahrens 129789Sahrens return (GETMEMBID(addr + off, &rc_id, rc_count, *rc)); 130789Sahrens } 131789Sahrens 132*12296SLin.Ling@Sun.COM static boolean_t 133*12296SLin.Ling@Sun.COM strisprint(const char *cp) 134*12296SLin.Ling@Sun.COM { 135*12296SLin.Ling@Sun.COM for (; *cp; cp++) { 136*12296SLin.Ling@Sun.COM if (!isprint(*cp)) 137*12296SLin.Ling@Sun.COM return (B_FALSE); 138*12296SLin.Ling@Sun.COM } 139*12296SLin.Ling@Sun.COM return (B_TRUE); 140*12296SLin.Ling@Sun.COM } 141*12296SLin.Ling@Sun.COM 142789Sahrens static int verbose; 143789Sahrens 144789Sahrens static int 145789Sahrens freelist_walk_init(mdb_walk_state_t *wsp) 146789Sahrens { 147789Sahrens if (wsp->walk_addr == NULL) { 148789Sahrens mdb_warn("must supply starting address\n"); 149789Sahrens return (WALK_ERR); 150789Sahrens } 151789Sahrens 152789Sahrens wsp->walk_data = 0; /* Index into the freelist */ 153789Sahrens return (WALK_NEXT); 154789Sahrens } 155789Sahrens 156789Sahrens static int 157789Sahrens freelist_walk_step(mdb_walk_state_t *wsp) 158789Sahrens { 159789Sahrens uint64_t entry; 160789Sahrens uintptr_t number = (uintptr_t)wsp->walk_data; 1613361Sck153898 char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID", 1623361Sck153898 "INVALID", "INVALID", "INVALID", "INVALID" }; 163789Sahrens int mapshift = SPA_MINBLOCKSHIFT; 164789Sahrens 165789Sahrens if (mdb_vread(&entry, sizeof (entry), wsp->walk_addr) == -1) { 166789Sahrens mdb_warn("failed to read freelist entry %p", wsp->walk_addr); 167789Sahrens return (WALK_DONE); 168789Sahrens } 169789Sahrens wsp->walk_addr += sizeof (entry); 170789Sahrens wsp->walk_data = (void *)(number + 1); 171789Sahrens 172789Sahrens if (SM_DEBUG_DECODE(entry)) { 173789Sahrens mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n", 174789Sahrens number, 175789Sahrens ddata[SM_DEBUG_ACTION_DECODE(entry)], 176789Sahrens SM_DEBUG_TXG_DECODE(entry), 177789Sahrens SM_DEBUG_SYNCPASS_DECODE(entry)); 178789Sahrens } else { 179789Sahrens mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c " 180789Sahrens "size=%06llx", number, 181789Sahrens SM_OFFSET_DECODE(entry) << mapshift, 182789Sahrens (SM_OFFSET_DECODE(entry) + SM_RUN_DECODE(entry)) << 183789Sahrens mapshift, 184789Sahrens SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 185789Sahrens SM_RUN_DECODE(entry) << mapshift); 186789Sahrens if (verbose) 187789Sahrens mdb_printf(" (raw=%012llx)\n", entry); 188789Sahrens mdb_printf("\n"); 189789Sahrens } 190789Sahrens return (WALK_NEXT); 191789Sahrens } 192789Sahrens 193789Sahrens 194789Sahrens static int 195789Sahrens dataset_name(uintptr_t addr, char *buf) 196789Sahrens { 197789Sahrens static int gotid; 198789Sahrens static mdb_ctf_id_t dd_id; 199789Sahrens uintptr_t dd_parent; 200789Sahrens char dd_myname[MAXNAMELEN]; 201789Sahrens 202789Sahrens if (!gotid) { 203789Sahrens if (mdb_ctf_lookup_by_name("struct dsl_dir", 204789Sahrens &dd_id) == -1) { 205789Sahrens mdb_warn("couldn't find struct dsl_dir"); 206789Sahrens return (DCMD_ERR); 207789Sahrens } 208789Sahrens gotid = TRUE; 209789Sahrens } 210789Sahrens if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) || 211789Sahrens GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) { 212789Sahrens return (DCMD_ERR); 213789Sahrens } 214789Sahrens 215789Sahrens if (dd_parent) { 216789Sahrens if (dataset_name(dd_parent, buf)) 217789Sahrens return (DCMD_ERR); 218789Sahrens strcat(buf, "/"); 219789Sahrens } 220789Sahrens 221789Sahrens if (dd_myname[0]) 222789Sahrens strcat(buf, dd_myname); 223789Sahrens else 224789Sahrens strcat(buf, "???"); 225789Sahrens 226789Sahrens return (0); 227789Sahrens } 228789Sahrens 229789Sahrens static int 230789Sahrens objset_name(uintptr_t addr, char *buf) 231789Sahrens { 232789Sahrens static int gotid; 23311954SMark.Shellenbaum@Sun.COM static mdb_ctf_id_t os_id, ds_id; 234789Sahrens uintptr_t os_dsl_dataset; 235789Sahrens char ds_snapname[MAXNAMELEN]; 236789Sahrens uintptr_t ds_dir; 237789Sahrens 238789Sahrens buf[0] = '\0'; 239789Sahrens 240789Sahrens if (!gotid) { 24111954SMark.Shellenbaum@Sun.COM if (mdb_ctf_lookup_by_name("struct objset", 24211954SMark.Shellenbaum@Sun.COM &os_id) == -1) { 24311954SMark.Shellenbaum@Sun.COM mdb_warn("couldn't find struct objset"); 244789Sahrens return (DCMD_ERR); 245789Sahrens } 246789Sahrens if (mdb_ctf_lookup_by_name("struct dsl_dataset", 247789Sahrens &ds_id) == -1) { 248789Sahrens mdb_warn("couldn't find struct dsl_dataset"); 249789Sahrens return (DCMD_ERR); 250789Sahrens } 251789Sahrens 252789Sahrens gotid = TRUE; 253789Sahrens } 254789Sahrens 25511954SMark.Shellenbaum@Sun.COM if (GETMEMBID(addr, &os_id, os_dsl_dataset, os_dsl_dataset)) 256789Sahrens return (DCMD_ERR); 257789Sahrens 258789Sahrens if (os_dsl_dataset == 0) { 259789Sahrens strcat(buf, "mos"); 260789Sahrens return (0); 261789Sahrens } 262789Sahrens 263789Sahrens if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) || 264789Sahrens GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) { 265789Sahrens return (DCMD_ERR); 266789Sahrens } 267789Sahrens 268789Sahrens if (ds_dir && dataset_name(ds_dir, buf)) 269789Sahrens return (DCMD_ERR); 270789Sahrens 271789Sahrens if (ds_snapname[0]) { 272789Sahrens strcat(buf, "@"); 273789Sahrens strcat(buf, ds_snapname); 274789Sahrens } 275789Sahrens return (0); 276789Sahrens } 277789Sahrens 278789Sahrens static void 279789Sahrens enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val, 280789Sahrens const char *prefix) 281789Sahrens { 282789Sahrens const char *cp; 283789Sahrens size_t len = strlen(prefix); 284789Sahrens 285789Sahrens if ((cp = mdb_ctf_enum_name(id, val)) != NULL) { 286789Sahrens if (strncmp(cp, prefix, len) == 0) 287789Sahrens cp += len; 288789Sahrens (void) strncpy(out, cp, size); 289789Sahrens } else { 290789Sahrens mdb_snprintf(out, size, "? (%d)", val); 291789Sahrens } 292789Sahrens } 293789Sahrens 294789Sahrens /* ARGSUSED */ 295789Sahrens static int 2963059Sahrens zfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2973059Sahrens { 2983059Sahrens /* 2993059Sahrens * This table can be approximately generated by running: 3003059Sahrens * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2 3013059Sahrens */ 3023059Sahrens static const char *params[] = { 3033059Sahrens "arc_reduce_dnlc_percent", 3043059Sahrens "zfs_arc_max", 3053059Sahrens "zfs_arc_min", 3063158Smaybee "arc_shrink_shift", 3073059Sahrens "zfs_mdcomp_disable", 3083059Sahrens "zfs_prefetch_disable", 3093059Sahrens "zfetch_max_streams", 3103059Sahrens "zfetch_min_sec_reap", 3113059Sahrens "zfetch_block_cap", 3123059Sahrens "zfetch_array_rd_sz", 3133059Sahrens "zfs_default_bs", 3143059Sahrens "zfs_default_ibs", 3153059Sahrens "metaslab_aliquot", 3163059Sahrens "reference_tracking_enable", 3173059Sahrens "reference_history", 3183059Sahrens "spa_max_replication_override", 31910922SJeff.Bonwick@Sun.COM "spa_mode_global", 3203059Sahrens "zfs_flags", 3216245Smaybee "zfs_txg_synctime", 3226245Smaybee "zfs_txg_timeout", 3236245Smaybee "zfs_write_limit_min", 3246245Smaybee "zfs_write_limit_max", 3256245Smaybee "zfs_write_limit_shift", 3266245Smaybee "zfs_write_limit_override", 3276245Smaybee "zfs_no_write_throttle", 3283059Sahrens "zfs_vdev_cache_max", 3293059Sahrens "zfs_vdev_cache_size", 3303059Sahrens "zfs_vdev_cache_bshift", 3313059Sahrens "vdev_mirror_shift", 3323059Sahrens "zfs_vdev_max_pending", 3333059Sahrens "zfs_vdev_min_pending", 3343059Sahrens "zfs_scrub_limit", 33511147SGeorge.Wilson@Sun.COM "zfs_no_scrub_io", 33611147SGeorge.Wilson@Sun.COM "zfs_no_scrub_prefetch", 3373059Sahrens "zfs_vdev_time_shift", 3383059Sahrens "zfs_vdev_ramp_rate", 3393059Sahrens "zfs_vdev_aggregation_limit", 3403059Sahrens "fzap_default_block_shift", 3413059Sahrens "zfs_immediate_write_sz", 3423059Sahrens "zfs_read_chunk_size", 3433059Sahrens "zfs_nocacheflush", 34412294SMark.Musante@Sun.COM "zil_replay_disable", 3456245Smaybee "metaslab_gang_bang", 3469480SGeorge.Wilson@Sun.COM "metaslab_df_alloc_threshold", 3479480SGeorge.Wilson@Sun.COM "metaslab_df_free_pct", 3483059Sahrens "zio_injection_enabled", 3493059Sahrens "zvol_immediate_write_sz", 3503059Sahrens }; 3513059Sahrens 35210922SJeff.Bonwick@Sun.COM for (int i = 0; i < sizeof (params) / sizeof (params[0]); i++) { 3533059Sahrens int sz; 3543059Sahrens uint64_t val64; 3553059Sahrens uint32_t *val32p = (uint32_t *)&val64; 3563059Sahrens 3573059Sahrens sz = mdb_readvar(&val64, params[i]); 3583059Sahrens if (sz == 4) { 3593059Sahrens mdb_printf("%s = 0x%x\n", params[i], *val32p); 3603059Sahrens } else if (sz == 8) { 3613059Sahrens mdb_printf("%s = 0x%llx\n", params[i], val64); 3623059Sahrens } else { 3633059Sahrens mdb_warn("variable %s not found", params[i]); 3643059Sahrens } 3653059Sahrens } 3663059Sahrens 3673059Sahrens return (DCMD_OK); 3683059Sahrens } 3693059Sahrens 3703059Sahrens /* ARGSUSED */ 3713059Sahrens static int 372789Sahrens blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 373789Sahrens { 37410922SJeff.Bonwick@Sun.COM mdb_ctf_id_t type_enum, checksum_enum, compress_enum; 37510922SJeff.Bonwick@Sun.COM char type[80], checksum[80], compress[80]; 37610922SJeff.Bonwick@Sun.COM blkptr_t blk, *bp = &blk; 37710922SJeff.Bonwick@Sun.COM char buf[BP_SPRINTF_LEN]; 378789Sahrens 37910922SJeff.Bonwick@Sun.COM if (mdb_vread(&blk, sizeof (blkptr_t), addr) == -1) { 380789Sahrens mdb_warn("failed to read blkptr_t"); 381789Sahrens return (DCMD_ERR); 382789Sahrens } 383789Sahrens 38410922SJeff.Bonwick@Sun.COM if (mdb_ctf_lookup_by_name("enum dmu_object_type", &type_enum) == -1 || 38510922SJeff.Bonwick@Sun.COM mdb_ctf_lookup_by_name("enum zio_checksum", &checksum_enum) == -1 || 38610922SJeff.Bonwick@Sun.COM mdb_ctf_lookup_by_name("enum zio_compress", &compress_enum) == -1) { 38710922SJeff.Bonwick@Sun.COM mdb_warn("Could not find blkptr enumerated types"); 388789Sahrens return (DCMD_ERR); 389789Sahrens } 390789Sahrens 39110922SJeff.Bonwick@Sun.COM enum_lookup(type, sizeof (type), type_enum, 39210922SJeff.Bonwick@Sun.COM BP_GET_TYPE(bp), "DMU_OT_"); 39310922SJeff.Bonwick@Sun.COM enum_lookup(checksum, sizeof (checksum), checksum_enum, 39410922SJeff.Bonwick@Sun.COM BP_GET_CHECKSUM(bp), "ZIO_CHECKSUM_"); 39510922SJeff.Bonwick@Sun.COM enum_lookup(compress, sizeof (compress), compress_enum, 39610922SJeff.Bonwick@Sun.COM BP_GET_COMPRESS(bp), "ZIO_COMPRESS_"); 3971775Sbillm 39810922SJeff.Bonwick@Sun.COM SPRINTF_BLKPTR(mdb_snprintf, '\n', buf, bp, type, checksum, compress); 39910922SJeff.Bonwick@Sun.COM 40010922SJeff.Bonwick@Sun.COM mdb_printf("%s\n", buf); 401789Sahrens 402789Sahrens return (DCMD_OK); 403789Sahrens } 404789Sahrens 405789Sahrens /* ARGSUSED */ 406789Sahrens static int 407789Sahrens dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 408789Sahrens { 409789Sahrens mdb_ctf_id_t id; 410789Sahrens dmu_buf_t db; 411789Sahrens uintptr_t objset; 412789Sahrens uint8_t level; 413789Sahrens uint64_t blkid; 414789Sahrens uint64_t holds; 415789Sahrens char objectname[32]; 416789Sahrens char blkidname[32]; 417789Sahrens char path[MAXNAMELEN]; 418789Sahrens 419789Sahrens if (DCMD_HDRSPEC(flags)) { 420789Sahrens mdb_printf(" addr object lvl blkid holds os\n"); 421789Sahrens } 422789Sahrens 423789Sahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &id) == -1) { 424789Sahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 425789Sahrens return (DCMD_ERR); 426789Sahrens } 427789Sahrens 428789Sahrens if (GETMEMBID(addr, &id, db_objset, objset) || 429789Sahrens GETMEMBID(addr, &id, db, db) || 430789Sahrens GETMEMBID(addr, &id, db_level, level) || 431789Sahrens GETMEMBID(addr, &id, db_blkid, blkid)) { 432789Sahrens return (WALK_ERR); 433789Sahrens } 434789Sahrens 435789Sahrens if (getrefcount(addr, &id, "db_holds", &holds)) { 436789Sahrens return (WALK_ERR); 437789Sahrens } 438789Sahrens 439789Sahrens if (db.db_object == DMU_META_DNODE_OBJECT) 440789Sahrens (void) strcpy(objectname, "mdn"); 441789Sahrens else 442789Sahrens (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", 443789Sahrens (u_longlong_t)db.db_object); 444789Sahrens 44511935SMark.Shellenbaum@Sun.COM if (blkid == DMU_BONUS_BLKID) 446789Sahrens (void) strcpy(blkidname, "bonus"); 447789Sahrens else 448789Sahrens (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", 449789Sahrens (u_longlong_t)blkid); 450789Sahrens 451789Sahrens if (objset_name(objset, path)) { 452789Sahrens return (WALK_ERR); 453789Sahrens } 454789Sahrens 455789Sahrens mdb_printf("%p %8s %1u %9s %2llu %s\n", 456789Sahrens addr, objectname, level, blkidname, holds, path); 457789Sahrens 458789Sahrens return (DCMD_OK); 459789Sahrens } 460789Sahrens 461789Sahrens /* ARGSUSED */ 462789Sahrens static int 463789Sahrens dbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 464789Sahrens { 465789Sahrens #define HISTOSZ 32 466789Sahrens uintptr_t dbp; 467789Sahrens dmu_buf_impl_t db; 468789Sahrens dbuf_hash_table_t ht; 469789Sahrens uint64_t bucket, ndbufs; 470789Sahrens uint64_t histo[HISTOSZ]; 471789Sahrens uint64_t histo2[HISTOSZ]; 472789Sahrens int i, maxidx; 473789Sahrens 474789Sahrens if (mdb_readvar(&ht, "dbuf_hash_table") == -1) { 475789Sahrens mdb_warn("failed to read 'dbuf_hash_table'"); 476789Sahrens return (DCMD_ERR); 477789Sahrens } 478789Sahrens 479789Sahrens for (i = 0; i < HISTOSZ; i++) { 480789Sahrens histo[i] = 0; 481789Sahrens histo2[i] = 0; 482789Sahrens } 483789Sahrens 484789Sahrens ndbufs = 0; 485789Sahrens for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) { 486789Sahrens int len; 487789Sahrens 488789Sahrens if (mdb_vread(&dbp, sizeof (void *), 489789Sahrens (uintptr_t)(ht.hash_table+bucket)) == -1) { 490789Sahrens mdb_warn("failed to read hash bucket %u at %p", 491789Sahrens bucket, ht.hash_table+bucket); 492789Sahrens return (DCMD_ERR); 493789Sahrens } 494789Sahrens 495789Sahrens len = 0; 496789Sahrens while (dbp != 0) { 497789Sahrens if (mdb_vread(&db, sizeof (dmu_buf_impl_t), 498789Sahrens dbp) == -1) { 499789Sahrens mdb_warn("failed to read dbuf at %p", dbp); 500789Sahrens return (DCMD_ERR); 501789Sahrens } 502789Sahrens dbp = (uintptr_t)db.db_hash_next; 503789Sahrens for (i = MIN(len, HISTOSZ - 1); i >= 0; i--) 504789Sahrens histo2[i]++; 505789Sahrens len++; 506789Sahrens ndbufs++; 507789Sahrens } 508789Sahrens 509789Sahrens if (len >= HISTOSZ) 510789Sahrens len = HISTOSZ-1; 511789Sahrens histo[len]++; 512789Sahrens } 513789Sahrens 514789Sahrens mdb_printf("hash table has %llu buckets, %llu dbufs " 515789Sahrens "(avg %llu buckets/dbuf)\n", 516789Sahrens ht.hash_table_mask+1, ndbufs, 517789Sahrens (ht.hash_table_mask+1)/ndbufs); 518789Sahrens 519789Sahrens mdb_printf("\n"); 520789Sahrens maxidx = 0; 521789Sahrens for (i = 0; i < HISTOSZ; i++) 522789Sahrens if (histo[i] > 0) 523789Sahrens maxidx = i; 524789Sahrens mdb_printf("hash chain length number of buckets\n"); 525789Sahrens for (i = 0; i <= maxidx; i++) 526789Sahrens mdb_printf("%u %llu\n", i, histo[i]); 527789Sahrens 528789Sahrens mdb_printf("\n"); 529789Sahrens maxidx = 0; 530789Sahrens for (i = 0; i < HISTOSZ; i++) 531789Sahrens if (histo2[i] > 0) 532789Sahrens maxidx = i; 533789Sahrens mdb_printf("hash chain depth number of dbufs\n"); 534789Sahrens for (i = 0; i <= maxidx; i++) 535789Sahrens mdb_printf("%u or more %llu %llu%%\n", 536789Sahrens i, histo2[i], histo2[i]*100/ndbufs); 537789Sahrens 538789Sahrens 539789Sahrens return (DCMD_OK); 540789Sahrens } 541789Sahrens 54211609SMatthew.Ahrens@Sun.COM #define CHAIN_END 0xffff 54311609SMatthew.Ahrens@Sun.COM /* 54411609SMatthew.Ahrens@Sun.COM * ::zap_leaf [-v] 54511609SMatthew.Ahrens@Sun.COM * 54611609SMatthew.Ahrens@Sun.COM * Print a zap_leaf_phys_t, assumed to be 16k 54711609SMatthew.Ahrens@Sun.COM */ 54811609SMatthew.Ahrens@Sun.COM /* ARGSUSED */ 54911609SMatthew.Ahrens@Sun.COM static int 55011609SMatthew.Ahrens@Sun.COM zap_leaf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 55111609SMatthew.Ahrens@Sun.COM { 55211609SMatthew.Ahrens@Sun.COM char buf[16*1024]; 55311609SMatthew.Ahrens@Sun.COM int verbose = B_FALSE; 55411609SMatthew.Ahrens@Sun.COM int four = B_FALSE; 55511609SMatthew.Ahrens@Sun.COM zap_leaf_t l; 55611609SMatthew.Ahrens@Sun.COM zap_leaf_phys_t *zlp = (void *)buf; 55711609SMatthew.Ahrens@Sun.COM int i; 55811609SMatthew.Ahrens@Sun.COM 55911609SMatthew.Ahrens@Sun.COM if (mdb_getopts(argc, argv, 56011609SMatthew.Ahrens@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, 56111609SMatthew.Ahrens@Sun.COM '4', MDB_OPT_SETBITS, TRUE, &four, 56211609SMatthew.Ahrens@Sun.COM NULL) != argc) 56311609SMatthew.Ahrens@Sun.COM return (DCMD_USAGE); 56411609SMatthew.Ahrens@Sun.COM 56511609SMatthew.Ahrens@Sun.COM l.l_phys = zlp; 56611609SMatthew.Ahrens@Sun.COM l.l_bs = 14; /* assume 16k blocks */ 56711609SMatthew.Ahrens@Sun.COM if (four) 56811609SMatthew.Ahrens@Sun.COM l.l_bs = 12; 56911609SMatthew.Ahrens@Sun.COM 57011609SMatthew.Ahrens@Sun.COM if (!(flags & DCMD_ADDRSPEC)) { 57111609SMatthew.Ahrens@Sun.COM return (DCMD_USAGE); 57211609SMatthew.Ahrens@Sun.COM } 57311609SMatthew.Ahrens@Sun.COM 57411609SMatthew.Ahrens@Sun.COM if (mdb_vread(buf, sizeof (buf), addr) == -1) { 57511609SMatthew.Ahrens@Sun.COM mdb_warn("failed to read zap_leaf_phys_t at %p", addr); 57611609SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 57711609SMatthew.Ahrens@Sun.COM } 57811609SMatthew.Ahrens@Sun.COM 57911609SMatthew.Ahrens@Sun.COM if (zlp->l_hdr.lh_block_type != ZBT_LEAF || 58011609SMatthew.Ahrens@Sun.COM zlp->l_hdr.lh_magic != ZAP_LEAF_MAGIC) { 58111609SMatthew.Ahrens@Sun.COM mdb_warn("This does not appear to be a zap_leaf_phys_t"); 58211609SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 58311609SMatthew.Ahrens@Sun.COM } 58411609SMatthew.Ahrens@Sun.COM 58511609SMatthew.Ahrens@Sun.COM mdb_printf("zap_leaf_phys_t at %p:\n", addr); 58611609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_prefix_len = %u\n", zlp->l_hdr.lh_prefix_len); 58711609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_prefix = %llx\n", zlp->l_hdr.lh_prefix); 58811609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_nentries = %u\n", zlp->l_hdr.lh_nentries); 58911609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_nfree = %u\n", zlp->l_hdr.lh_nfree, 59011609SMatthew.Ahrens@Sun.COM zlp->l_hdr.lh_nfree * 100 / (ZAP_LEAF_NUMCHUNKS(&l))); 59111609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_freelist = %u\n", zlp->l_hdr.lh_freelist); 59211609SMatthew.Ahrens@Sun.COM mdb_printf(" lh_flags = %x (%s)\n", zlp->l_hdr.lh_flags, 59311609SMatthew.Ahrens@Sun.COM zlp->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED ? 59411609SMatthew.Ahrens@Sun.COM "ENTRIES_CDSORTED" : ""); 59511609SMatthew.Ahrens@Sun.COM 59611609SMatthew.Ahrens@Sun.COM if (verbose) { 59711609SMatthew.Ahrens@Sun.COM mdb_printf(" hash table:\n"); 59811609SMatthew.Ahrens@Sun.COM for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++) { 59911609SMatthew.Ahrens@Sun.COM if (zlp->l_hash[i] != CHAIN_END) 60011609SMatthew.Ahrens@Sun.COM mdb_printf(" %u: %u\n", i, zlp->l_hash[i]); 60111609SMatthew.Ahrens@Sun.COM } 60211609SMatthew.Ahrens@Sun.COM } 60311609SMatthew.Ahrens@Sun.COM 60411609SMatthew.Ahrens@Sun.COM mdb_printf(" chunks:\n"); 60511609SMatthew.Ahrens@Sun.COM for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) { 60611609SMatthew.Ahrens@Sun.COM /* LINTED: alignment */ 60711609SMatthew.Ahrens@Sun.COM zap_leaf_chunk_t *zlc = &ZAP_LEAF_CHUNK(&l, i); 60811609SMatthew.Ahrens@Sun.COM switch (zlc->l_entry.le_type) { 60911609SMatthew.Ahrens@Sun.COM case ZAP_CHUNK_FREE: 61011609SMatthew.Ahrens@Sun.COM if (verbose) { 61111609SMatthew.Ahrens@Sun.COM mdb_printf(" %u: free; lf_next = %u\n", 61211609SMatthew.Ahrens@Sun.COM i, zlc->l_free.lf_next); 61311609SMatthew.Ahrens@Sun.COM } 61411609SMatthew.Ahrens@Sun.COM break; 61511609SMatthew.Ahrens@Sun.COM case ZAP_CHUNK_ENTRY: 61611609SMatthew.Ahrens@Sun.COM mdb_printf(" %u: entry\n", i); 61711609SMatthew.Ahrens@Sun.COM if (verbose) { 61811609SMatthew.Ahrens@Sun.COM mdb_printf(" le_next = %u\n", 61911609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_next); 62011609SMatthew.Ahrens@Sun.COM } 62111609SMatthew.Ahrens@Sun.COM mdb_printf(" le_name_chunk = %u\n", 62211609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_name_chunk); 62311609SMatthew.Ahrens@Sun.COM mdb_printf(" le_name_numints = %u\n", 62411609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_name_numints); 62511609SMatthew.Ahrens@Sun.COM mdb_printf(" le_value_chunk = %u\n", 62611609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_value_chunk); 62711609SMatthew.Ahrens@Sun.COM mdb_printf(" le_value_intlen = %u\n", 62811609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_value_intlen); 62911609SMatthew.Ahrens@Sun.COM mdb_printf(" le_value_numints = %u\n", 63011609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_value_numints); 63111609SMatthew.Ahrens@Sun.COM mdb_printf(" le_cd = %u\n", 63211609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_cd); 63311609SMatthew.Ahrens@Sun.COM mdb_printf(" le_hash = %llx\n", 63411609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_hash); 63511609SMatthew.Ahrens@Sun.COM break; 63611609SMatthew.Ahrens@Sun.COM case ZAP_CHUNK_ARRAY: 637*12296SLin.Ling@Sun.COM mdb_printf(" %u: array", i); 638*12296SLin.Ling@Sun.COM if (strisprint((char *)zlc->l_array.la_array)) 639*12296SLin.Ling@Sun.COM mdb_printf(" \"%s\"", zlc->l_array.la_array); 640*12296SLin.Ling@Sun.COM mdb_printf("\n"); 64111609SMatthew.Ahrens@Sun.COM if (verbose) { 64211609SMatthew.Ahrens@Sun.COM int j; 64311609SMatthew.Ahrens@Sun.COM mdb_printf(" "); 64411609SMatthew.Ahrens@Sun.COM for (j = 0; j < ZAP_LEAF_ARRAY_BYTES; j++) { 64511609SMatthew.Ahrens@Sun.COM mdb_printf("%02x ", 64611609SMatthew.Ahrens@Sun.COM zlc->l_array.la_array[j]); 64711609SMatthew.Ahrens@Sun.COM } 64811609SMatthew.Ahrens@Sun.COM mdb_printf("\n"); 64911609SMatthew.Ahrens@Sun.COM } 65011609SMatthew.Ahrens@Sun.COM if (zlc->l_array.la_next != CHAIN_END) { 65111609SMatthew.Ahrens@Sun.COM mdb_printf(" lf_next = %u\n", 65211609SMatthew.Ahrens@Sun.COM zlc->l_array.la_next); 65311609SMatthew.Ahrens@Sun.COM } 65411609SMatthew.Ahrens@Sun.COM break; 65511609SMatthew.Ahrens@Sun.COM default: 65611609SMatthew.Ahrens@Sun.COM mdb_printf(" %u: undefined type %u\n", 65711609SMatthew.Ahrens@Sun.COM zlc->l_entry.le_type); 65811609SMatthew.Ahrens@Sun.COM } 65911609SMatthew.Ahrens@Sun.COM } 66011609SMatthew.Ahrens@Sun.COM 66111609SMatthew.Ahrens@Sun.COM return (DCMD_OK); 66211609SMatthew.Ahrens@Sun.COM } 66311609SMatthew.Ahrens@Sun.COM 664789Sahrens typedef struct dbufs_data { 665789Sahrens mdb_ctf_id_t id; 666789Sahrens uint64_t objset; 667789Sahrens uint64_t object; 668789Sahrens uint64_t level; 669789Sahrens uint64_t blkid; 670789Sahrens char *osname; 671789Sahrens } dbufs_data_t; 672789Sahrens 673789Sahrens #define DBUFS_UNSET (0xbaddcafedeadbeefULL) 674789Sahrens 675789Sahrens /* ARGSUSED */ 676789Sahrens static int 677789Sahrens dbufs_cb(uintptr_t addr, const void *unknown, void *arg) 678789Sahrens { 679789Sahrens dbufs_data_t *data = arg; 680789Sahrens uintptr_t objset; 681789Sahrens dmu_buf_t db; 682789Sahrens uint8_t level; 683789Sahrens uint64_t blkid; 684789Sahrens char osname[MAXNAMELEN]; 685789Sahrens 686789Sahrens if (GETMEMBID(addr, &data->id, db_objset, objset) || 687789Sahrens GETMEMBID(addr, &data->id, db, db) || 688789Sahrens GETMEMBID(addr, &data->id, db_level, level) || 689789Sahrens GETMEMBID(addr, &data->id, db_blkid, blkid)) { 690789Sahrens return (WALK_ERR); 691789Sahrens } 692789Sahrens 693789Sahrens if ((data->objset == DBUFS_UNSET || data->objset == objset) && 694789Sahrens (data->osname == NULL || (objset_name(objset, osname) == 0 && 6954055Seschrock strcmp(data->osname, osname) == 0)) && 696789Sahrens (data->object == DBUFS_UNSET || data->object == db.db_object) && 697789Sahrens (data->level == DBUFS_UNSET || data->level == level) && 698789Sahrens (data->blkid == DBUFS_UNSET || data->blkid == blkid)) { 699789Sahrens mdb_printf("%#lr\n", addr); 700789Sahrens } 701789Sahrens return (WALK_NEXT); 702789Sahrens } 703789Sahrens 704789Sahrens /* ARGSUSED */ 705789Sahrens static int 706789Sahrens dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 707789Sahrens { 708789Sahrens dbufs_data_t data; 709789Sahrens char *object = NULL; 710789Sahrens char *blkid = NULL; 711789Sahrens 712789Sahrens data.objset = data.object = data.level = data.blkid = DBUFS_UNSET; 713789Sahrens data.osname = NULL; 714789Sahrens 715789Sahrens if (mdb_getopts(argc, argv, 716789Sahrens 'O', MDB_OPT_UINT64, &data.objset, 717789Sahrens 'n', MDB_OPT_STR, &data.osname, 718789Sahrens 'o', MDB_OPT_STR, &object, 719789Sahrens 'l', MDB_OPT_UINT64, &data.level, 720789Sahrens 'b', MDB_OPT_STR, &blkid) != argc) { 721789Sahrens return (DCMD_USAGE); 722789Sahrens } 723789Sahrens 724789Sahrens if (object) { 725789Sahrens if (strcmp(object, "mdn") == 0) { 726789Sahrens data.object = DMU_META_DNODE_OBJECT; 727789Sahrens } else { 728789Sahrens data.object = mdb_strtoull(object); 729789Sahrens } 730789Sahrens } 731789Sahrens 732789Sahrens if (blkid) { 733789Sahrens if (strcmp(blkid, "bonus") == 0) { 73411935SMark.Shellenbaum@Sun.COM data.blkid = DMU_BONUS_BLKID; 735789Sahrens } else { 736789Sahrens data.blkid = mdb_strtoull(blkid); 737789Sahrens } 738789Sahrens } 739789Sahrens 740789Sahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &data.id) == -1) { 741789Sahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 742789Sahrens return (DCMD_ERR); 743789Sahrens } 744789Sahrens 7452459Sahrens if (mdb_walk("dmu_buf_impl_t", dbufs_cb, &data) != 0) { 746789Sahrens mdb_warn("can't walk dbufs"); 747789Sahrens return (DCMD_ERR); 748789Sahrens } 749789Sahrens 750789Sahrens return (DCMD_OK); 751789Sahrens } 752789Sahrens 753789Sahrens typedef struct abuf_find_data { 754789Sahrens dva_t dva; 755789Sahrens mdb_ctf_id_t id; 756789Sahrens } abuf_find_data_t; 757789Sahrens 758789Sahrens /* ARGSUSED */ 759789Sahrens static int 760789Sahrens abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) 761789Sahrens { 762789Sahrens abuf_find_data_t *data = arg; 763789Sahrens dva_t dva; 764789Sahrens 765789Sahrens if (GETMEMBID(addr, &data->id, b_dva, dva)) { 766789Sahrens return (WALK_ERR); 767789Sahrens } 768789Sahrens 769789Sahrens if (dva.dva_word[0] == data->dva.dva_word[0] && 770789Sahrens dva.dva_word[1] == data->dva.dva_word[1]) { 771789Sahrens mdb_printf("%#lr\n", addr); 772789Sahrens } 773789Sahrens return (WALK_NEXT); 774789Sahrens } 775789Sahrens 776789Sahrens /* ARGSUSED */ 777789Sahrens static int 778789Sahrens abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 779789Sahrens { 780789Sahrens abuf_find_data_t data; 781789Sahrens GElf_Sym sym; 782789Sahrens int i; 783789Sahrens const char *syms[] = { 7842885Sahrens "ARC_mru", 7852885Sahrens "ARC_mru_ghost", 7862885Sahrens "ARC_mfu", 7872885Sahrens "ARC_mfu_ghost", 788789Sahrens }; 789789Sahrens 790789Sahrens if (argc != 2) 791789Sahrens return (DCMD_USAGE); 792789Sahrens 793789Sahrens for (i = 0; i < 2; i ++) { 794789Sahrens switch (argv[i].a_type) { 795789Sahrens case MDB_TYPE_STRING: 796789Sahrens data.dva.dva_word[i] = mdb_strtoull(argv[i].a_un.a_str); 797789Sahrens break; 798789Sahrens case MDB_TYPE_IMMEDIATE: 799789Sahrens data.dva.dva_word[i] = argv[i].a_un.a_val; 800789Sahrens break; 801789Sahrens default: 802789Sahrens return (DCMD_USAGE); 803789Sahrens } 804789Sahrens } 805789Sahrens 806789Sahrens if (mdb_ctf_lookup_by_name("struct arc_buf_hdr", &data.id) == -1) { 807789Sahrens mdb_warn("couldn't find struct arc_buf_hdr"); 808789Sahrens return (DCMD_ERR); 809789Sahrens } 810789Sahrens 811789Sahrens for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { 812789Sahrens if (mdb_lookup_by_name(syms[i], &sym)) { 813789Sahrens mdb_warn("can't find symbol %s", syms[i]); 814789Sahrens return (DCMD_ERR); 815789Sahrens } 816789Sahrens 817789Sahrens if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { 818789Sahrens mdb_warn("can't walk %s", syms[i]); 819789Sahrens return (DCMD_ERR); 820789Sahrens } 821789Sahrens } 822789Sahrens 823789Sahrens return (DCMD_OK); 824789Sahrens } 825789Sahrens 826*12296SLin.Ling@Sun.COM /* ARGSUSED */ 827*12296SLin.Ling@Sun.COM static int 828*12296SLin.Ling@Sun.COM dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg) 829*12296SLin.Ling@Sun.COM { 830*12296SLin.Ling@Sun.COM static mdb_ctf_id_t id; 831*12296SLin.Ling@Sun.COM static boolean_t gotid; 832*12296SLin.Ling@Sun.COM static ulong_t off; 833*12296SLin.Ling@Sun.COM 834*12296SLin.Ling@Sun.COM int *verbosep = arg; 835*12296SLin.Ling@Sun.COM time_t timestamp; 836*12296SLin.Ling@Sun.COM char buf[1024]; 837*12296SLin.Ling@Sun.COM 838*12296SLin.Ling@Sun.COM if (!gotid) { 839*12296SLin.Ling@Sun.COM if (mdb_ctf_lookup_by_name("struct zfs_dbgmsg", &id) == -1) { 840*12296SLin.Ling@Sun.COM mdb_warn("couldn't find struct zfs_dbgmsg"); 841*12296SLin.Ling@Sun.COM return (WALK_ERR); 842*12296SLin.Ling@Sun.COM } 843*12296SLin.Ling@Sun.COM gotid = TRUE; 844*12296SLin.Ling@Sun.COM if (mdb_ctf_offsetof(id, "zdm_msg", &off) == -1) { 845*12296SLin.Ling@Sun.COM mdb_warn("couldn't find zdm_msg"); 846*12296SLin.Ling@Sun.COM return (WALK_ERR); 847*12296SLin.Ling@Sun.COM } 848*12296SLin.Ling@Sun.COM off /= 8; 849*12296SLin.Ling@Sun.COM } 850*12296SLin.Ling@Sun.COM 851*12296SLin.Ling@Sun.COM 852*12296SLin.Ling@Sun.COM if (GETMEMBID(addr, &id, zdm_timestamp, timestamp)) { 853*12296SLin.Ling@Sun.COM return (WALK_ERR); 854*12296SLin.Ling@Sun.COM } 855*12296SLin.Ling@Sun.COM 856*12296SLin.Ling@Sun.COM if (mdb_readstr(buf, sizeof (buf), addr + off) == -1) { 857*12296SLin.Ling@Sun.COM mdb_warn("failed to read zdm_msg at %p\n", addr + off); 858*12296SLin.Ling@Sun.COM return (DCMD_ERR); 859*12296SLin.Ling@Sun.COM } 860*12296SLin.Ling@Sun.COM 861*12296SLin.Ling@Sun.COM if (*verbosep) 862*12296SLin.Ling@Sun.COM mdb_printf("%Y ", timestamp); 863*12296SLin.Ling@Sun.COM 864*12296SLin.Ling@Sun.COM mdb_printf("%s\n", buf); 865*12296SLin.Ling@Sun.COM 866*12296SLin.Ling@Sun.COM if (*verbosep) 867*12296SLin.Ling@Sun.COM (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 868*12296SLin.Ling@Sun.COM 869*12296SLin.Ling@Sun.COM return (WALK_NEXT); 870*12296SLin.Ling@Sun.COM } 871*12296SLin.Ling@Sun.COM 872*12296SLin.Ling@Sun.COM /* ARGSUSED */ 873*12296SLin.Ling@Sun.COM static int 874*12296SLin.Ling@Sun.COM dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 875*12296SLin.Ling@Sun.COM { 876*12296SLin.Ling@Sun.COM GElf_Sym sym; 877*12296SLin.Ling@Sun.COM int verbose = FALSE; 878*12296SLin.Ling@Sun.COM 879*12296SLin.Ling@Sun.COM if (mdb_getopts(argc, argv, 880*12296SLin.Ling@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, 881*12296SLin.Ling@Sun.COM NULL) != argc) 882*12296SLin.Ling@Sun.COM return (DCMD_USAGE); 883*12296SLin.Ling@Sun.COM 884*12296SLin.Ling@Sun.COM if (mdb_lookup_by_name("zfs_dbgmsgs", &sym)) { 885*12296SLin.Ling@Sun.COM mdb_warn("can't find zfs_dbgmsgs"); 886*12296SLin.Ling@Sun.COM return (DCMD_ERR); 887*12296SLin.Ling@Sun.COM } 888*12296SLin.Ling@Sun.COM 889*12296SLin.Ling@Sun.COM if (mdb_pwalk("list", dbgmsg_cb, &verbose, sym.st_value) != 0) { 890*12296SLin.Ling@Sun.COM mdb_warn("can't walk zfs_dbgmsgs"); 891*12296SLin.Ling@Sun.COM return (DCMD_ERR); 892*12296SLin.Ling@Sun.COM } 893*12296SLin.Ling@Sun.COM 894*12296SLin.Ling@Sun.COM return (DCMD_OK); 895*12296SLin.Ling@Sun.COM } 896*12296SLin.Ling@Sun.COM 8973403Sbmc /*ARGSUSED*/ 8983403Sbmc static int 8993403Sbmc arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 9003403Sbmc { 9013403Sbmc kstat_named_t *stats; 9023403Sbmc GElf_Sym sym; 9034787Sahrens int nstats, i; 9043403Sbmc uint_t opt_a = FALSE; 9054787Sahrens uint_t opt_b = FALSE; 9064787Sahrens uint_t shift = 0; 9074787Sahrens const char *suffix; 9083403Sbmc 9094787Sahrens static const char *bytestats[] = { 9104787Sahrens "p", "c", "c_min", "c_max", "size", NULL 9114787Sahrens }; 9124787Sahrens 9134787Sahrens static const char *extras[] = { 9144787Sahrens "arc_no_grow", "arc_tempreserve", 9154787Sahrens "arc_meta_used", "arc_meta_limit", "arc_meta_max", 9164787Sahrens NULL 9173403Sbmc }; 9183403Sbmc 9193403Sbmc if (mdb_lookup_by_name("arc_stats", &sym) == -1) { 9203403Sbmc mdb_warn("failed to find 'arc_stats'"); 9213403Sbmc return (DCMD_ERR); 9223403Sbmc } 9233403Sbmc 9243403Sbmc stats = mdb_zalloc(sym.st_size, UM_SLEEP | UM_GC); 9253403Sbmc 9263403Sbmc if (mdb_vread(stats, sym.st_size, sym.st_value) == -1) { 9273403Sbmc mdb_warn("couldn't read 'arc_stats' at %p", sym.st_value); 9283403Sbmc return (DCMD_ERR); 9293403Sbmc } 9303403Sbmc 9313403Sbmc nstats = sym.st_size / sizeof (kstat_named_t); 9323403Sbmc 9334787Sahrens /* NB: -a / opt_a are ignored for backwards compatability */ 9344787Sahrens if (mdb_getopts(argc, argv, 9354787Sahrens 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 9364787Sahrens 'b', MDB_OPT_SETBITS, TRUE, &opt_b, 9374787Sahrens 'k', MDB_OPT_SETBITS, 10, &shift, 9384787Sahrens 'm', MDB_OPT_SETBITS, 20, &shift, 9394787Sahrens 'g', MDB_OPT_SETBITS, 30, &shift, 9404787Sahrens NULL) != argc) 9413403Sbmc return (DCMD_USAGE); 9423403Sbmc 9434787Sahrens if (!opt_b && !shift) 9444787Sahrens shift = 20; 9453403Sbmc 9464787Sahrens switch (shift) { 9474787Sahrens case 0: 9484787Sahrens suffix = "B"; 9494787Sahrens break; 9504787Sahrens case 10: 9514787Sahrens suffix = "KB"; 9524787Sahrens break; 9534787Sahrens case 20: 9544787Sahrens suffix = "MB"; 9554787Sahrens break; 9564787Sahrens case 30: 9574787Sahrens suffix = "GB"; 9584787Sahrens break; 9594787Sahrens default: 9604787Sahrens suffix = "XX"; 9613403Sbmc } 9623403Sbmc 9634787Sahrens for (i = 0; i < nstats; i++) { 9644787Sahrens int j; 9654787Sahrens boolean_t bytes = B_FALSE; 9663403Sbmc 9674787Sahrens for (j = 0; bytestats[j]; j++) { 9684787Sahrens if (strcmp(stats[i].name, bytestats[j]) == 0) { 9694787Sahrens bytes = B_TRUE; 9704787Sahrens break; 9713403Sbmc } 9723403Sbmc } 9733403Sbmc 9744787Sahrens if (bytes) { 9754787Sahrens mdb_printf("%-25s = %9llu %s\n", stats[i].name, 9764787Sahrens stats[i].value.ui64 >> shift, suffix); 9774787Sahrens } else { 9784787Sahrens mdb_printf("%-25s = %9llu\n", stats[i].name, 9794787Sahrens stats[i].value.ui64); 9803403Sbmc } 9813403Sbmc } 9823403Sbmc 9834787Sahrens for (i = 0; extras[i]; i++) { 9844787Sahrens uint64_t buf; 9854787Sahrens 9864787Sahrens if (mdb_lookup_by_name(extras[i], &sym) == -1) { 9874787Sahrens mdb_warn("failed to find '%s'", extras[i]); 9884787Sahrens return (DCMD_ERR); 9894787Sahrens } 9904787Sahrens 9914787Sahrens if (sym.st_size != sizeof (uint64_t) && 9924787Sahrens sym.st_size != sizeof (uint32_t)) { 9934787Sahrens mdb_warn("expected scalar for variable '%s'\n", 9944787Sahrens extras[i]); 9954787Sahrens return (DCMD_ERR); 9964787Sahrens } 9973403Sbmc 9984787Sahrens if (mdb_vread(&buf, sym.st_size, sym.st_value) == -1) { 9994787Sahrens mdb_warn("couldn't read '%s'", extras[i]); 10004787Sahrens return (DCMD_ERR); 10014787Sahrens } 10024787Sahrens 10034787Sahrens mdb_printf("%-25s = ", extras[i]); 10044787Sahrens 10054787Sahrens /* NB: all the 64-bit extras happen to be byte counts */ 10064787Sahrens if (sym.st_size == sizeof (uint64_t)) 10074787Sahrens mdb_printf("%9llu %s\n", buf >> shift, suffix); 10084787Sahrens 10094787Sahrens if (sym.st_size == sizeof (uint32_t)) 10104787Sahrens mdb_printf("%9d\n", *((uint32_t *)&buf)); 10114787Sahrens } 10123403Sbmc return (DCMD_OK); 10133403Sbmc } 10143403Sbmc 1015789Sahrens /* 1016789Sahrens * ::spa 1017789Sahrens * 1018789Sahrens * -c Print configuration information as well 1019789Sahrens * -v Print vdev state 1020789Sahrens * -e Print vdev error stats 1021789Sahrens * 1022789Sahrens * Print a summarized spa_t. When given no arguments, prints out a table of all 1023789Sahrens * active pools on the system. 1024789Sahrens */ 1025789Sahrens /* ARGSUSED */ 1026789Sahrens static int 1027789Sahrens spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1028789Sahrens { 1029789Sahrens spa_t spa; 1030789Sahrens const char *statetab[] = { "ACTIVE", "EXPORTED", "DESTROYED", 10317754SJeff.Bonwick@Sun.COM "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" }; 1032789Sahrens const char *state; 1033789Sahrens int config = FALSE; 1034789Sahrens int vdevs = FALSE; 1035789Sahrens int errors = FALSE; 1036789Sahrens 1037789Sahrens if (mdb_getopts(argc, argv, 1038789Sahrens 'c', MDB_OPT_SETBITS, TRUE, &config, 1039789Sahrens 'v', MDB_OPT_SETBITS, TRUE, &vdevs, 1040789Sahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 1041789Sahrens NULL) != argc) 1042789Sahrens return (DCMD_USAGE); 1043789Sahrens 1044789Sahrens if (!(flags & DCMD_ADDRSPEC)) { 1045789Sahrens if (mdb_walk_dcmd("spa", "spa", argc, argv) == -1) { 1046789Sahrens mdb_warn("can't walk spa"); 1047789Sahrens return (DCMD_ERR); 1048789Sahrens } 1049789Sahrens 1050789Sahrens return (DCMD_OK); 1051789Sahrens } 1052789Sahrens 1053789Sahrens if (flags & DCMD_PIPE_OUT) { 1054789Sahrens mdb_printf("%#lr\n", addr); 1055789Sahrens return (DCMD_OK); 1056789Sahrens } 1057789Sahrens 1058789Sahrens if (DCMD_HDRSPEC(flags)) 1059789Sahrens mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE", 1060789Sahrens sizeof (uintptr_t) == 4 ? 60 : 52, "NAME"); 1061789Sahrens 1062789Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1063789Sahrens mdb_warn("failed to read spa_t at %p", addr); 1064789Sahrens return (DCMD_ERR); 1065789Sahrens } 1066789Sahrens 1067789Sahrens if (spa.spa_state < 0 || spa.spa_state > POOL_STATE_UNAVAIL) 10681544Seschrock state = "UNKNOWN"; 1069789Sahrens else 1070789Sahrens state = statetab[spa.spa_state]; 1071789Sahrens 10727754SJeff.Bonwick@Sun.COM mdb_printf("%0?p %9s %s\n", addr, state, spa.spa_name); 1073789Sahrens 1074789Sahrens if (config) { 1075789Sahrens mdb_printf("\n"); 1076789Sahrens mdb_inc_indent(4); 1077789Sahrens if (mdb_call_dcmd("spa_config", addr, flags, 0, 1078789Sahrens NULL) != DCMD_OK) 1079789Sahrens return (DCMD_ERR); 1080789Sahrens mdb_dec_indent(4); 1081789Sahrens } 1082789Sahrens 1083789Sahrens if (vdevs || errors) { 1084789Sahrens mdb_arg_t v; 1085789Sahrens 1086789Sahrens v.a_type = MDB_TYPE_STRING; 1087789Sahrens v.a_un.a_str = "-e"; 1088789Sahrens 1089789Sahrens mdb_printf("\n"); 1090789Sahrens mdb_inc_indent(4); 1091789Sahrens if (mdb_call_dcmd("spa_vdevs", addr, flags, errors ? 1 : 0, 1092789Sahrens &v) != DCMD_OK) 1093789Sahrens return (DCMD_ERR); 1094789Sahrens mdb_dec_indent(4); 1095789Sahrens } 1096789Sahrens 1097789Sahrens return (DCMD_OK); 1098789Sahrens } 1099789Sahrens 1100789Sahrens /* 1101789Sahrens * ::spa_config 1102789Sahrens * 1103789Sahrens * Given a spa_t, print the configuration information stored in spa_config. 1104789Sahrens * Since it's just an nvlist, format it as an indented list of name=value pairs. 1105789Sahrens * We simply read the value of spa_config and pass off to ::nvlist. 1106789Sahrens */ 1107789Sahrens /* ARGSUSED */ 1108789Sahrens static int 1109789Sahrens spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1110789Sahrens { 1111789Sahrens spa_t spa; 1112789Sahrens 1113789Sahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1114789Sahrens return (DCMD_USAGE); 1115789Sahrens 1116789Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1117789Sahrens mdb_warn("failed to read spa_t at %p", addr); 1118789Sahrens return (DCMD_ERR); 1119789Sahrens } 1120789Sahrens 1121789Sahrens if (spa.spa_config == NULL) { 1122789Sahrens mdb_printf("(none)\n"); 1123789Sahrens return (DCMD_OK); 1124789Sahrens } 1125789Sahrens 1126789Sahrens return (mdb_call_dcmd("nvlist", (uintptr_t)spa.spa_config, flags, 1127789Sahrens 0, NULL)); 1128789Sahrens } 1129789Sahrens 1130789Sahrens /* 1131789Sahrens * ::vdev 1132789Sahrens * 1133789Sahrens * Print out a summarized vdev_t, in the following form: 1134789Sahrens * 1135789Sahrens * ADDR STATE AUX DESC 1136789Sahrens * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0 1137789Sahrens * 1138789Sahrens * If '-r' is specified, recursively visit all children. 1139789Sahrens * 1140789Sahrens * With '-e', the statistics associated with the vdev are printed as well. 1141789Sahrens */ 1142789Sahrens static int 11433059Sahrens do_print_vdev(uintptr_t addr, int flags, int depth, int stats, 1144789Sahrens int recursive) 1145789Sahrens { 1146789Sahrens vdev_t vdev; 1147789Sahrens char desc[MAXNAMELEN]; 1148789Sahrens int c, children; 1149789Sahrens uintptr_t *child; 1150789Sahrens const char *state, *aux; 1151789Sahrens 1152789Sahrens if (mdb_vread(&vdev, sizeof (vdev), (uintptr_t)addr) == -1) { 1153789Sahrens mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr); 1154789Sahrens return (DCMD_ERR); 1155789Sahrens } 1156789Sahrens 1157789Sahrens if (flags & DCMD_PIPE_OUT) { 1158789Sahrens mdb_printf("%#lr", addr); 1159789Sahrens } else { 1160789Sahrens if (vdev.vdev_path != NULL) { 1161789Sahrens if (mdb_readstr(desc, sizeof (desc), 1162789Sahrens (uintptr_t)vdev.vdev_path) == -1) { 1163789Sahrens mdb_warn("failed to read vdev_path at %p\n", 1164789Sahrens vdev.vdev_path); 1165789Sahrens return (DCMD_ERR); 1166789Sahrens } 1167789Sahrens } else if (vdev.vdev_ops != NULL) { 1168789Sahrens vdev_ops_t ops; 1169789Sahrens if (mdb_vread(&ops, sizeof (ops), 1170789Sahrens (uintptr_t)vdev.vdev_ops) == -1) { 1171789Sahrens mdb_warn("failed to read vdev_ops at %p\n", 1172789Sahrens vdev.vdev_ops); 1173789Sahrens return (DCMD_ERR); 1174789Sahrens } 1175789Sahrens (void) strcpy(desc, ops.vdev_op_type); 1176789Sahrens } else { 1177789Sahrens (void) strcpy(desc, "<unknown>"); 1178789Sahrens } 1179789Sahrens 1180789Sahrens if (depth == 0 && DCMD_HDRSPEC(flags)) 1181789Sahrens mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n", 1182789Sahrens "ADDR", "STATE", "AUX", 1183789Sahrens sizeof (uintptr_t) == 4 ? 43 : 35, 1184789Sahrens "DESCRIPTION"); 1185789Sahrens 1186789Sahrens mdb_printf("%0?p ", addr); 1187789Sahrens 1188789Sahrens switch (vdev.vdev_state) { 1189789Sahrens case VDEV_STATE_CLOSED: 11904055Seschrock state = "CLOSED"; 11914055Seschrock break; 1192789Sahrens case VDEV_STATE_OFFLINE: 11934055Seschrock state = "OFFLINE"; 11944055Seschrock break; 1195789Sahrens case VDEV_STATE_CANT_OPEN: 11964055Seschrock state = "CANT_OPEN"; 11974055Seschrock break; 1198789Sahrens case VDEV_STATE_DEGRADED: 11994055Seschrock state = "DEGRADED"; 12004055Seschrock break; 1201789Sahrens case VDEV_STATE_HEALTHY: 12024055Seschrock state = "HEALTHY"; 12034055Seschrock break; 12044451Seschrock case VDEV_STATE_REMOVED: 12054451Seschrock state = "REMOVED"; 12064451Seschrock break; 12074451Seschrock case VDEV_STATE_FAULTED: 12084451Seschrock state = "FAULTED"; 12094451Seschrock break; 1210789Sahrens default: 12114055Seschrock state = "UNKNOWN"; 12124055Seschrock break; 1213789Sahrens } 1214789Sahrens 1215789Sahrens switch (vdev.vdev_stat.vs_aux) { 1216789Sahrens case VDEV_AUX_NONE: 1217789Sahrens aux = "-"; 1218789Sahrens break; 1219789Sahrens case VDEV_AUX_OPEN_FAILED: 1220789Sahrens aux = "OPEN_FAILED"; 1221789Sahrens break; 1222789Sahrens case VDEV_AUX_CORRUPT_DATA: 1223789Sahrens aux = "CORRUPT_DATA"; 1224789Sahrens break; 1225789Sahrens case VDEV_AUX_NO_REPLICAS: 1226789Sahrens aux = "NO_REPLICAS"; 1227789Sahrens break; 1228789Sahrens case VDEV_AUX_BAD_GUID_SUM: 1229789Sahrens aux = "BAD_GUID_SUM"; 1230789Sahrens break; 1231789Sahrens case VDEV_AUX_TOO_SMALL: 1232789Sahrens aux = "TOO_SMALL"; 1233789Sahrens break; 1234789Sahrens case VDEV_AUX_BAD_LABEL: 1235789Sahrens aux = "BAD_LABEL"; 1236789Sahrens break; 12377294Sperrin case VDEV_AUX_VERSION_NEWER: 12387294Sperrin aux = "VERS_NEWER"; 12397294Sperrin break; 12407294Sperrin case VDEV_AUX_VERSION_OLDER: 12417294Sperrin aux = "VERS_OLDER"; 12427294Sperrin break; 12437294Sperrin case VDEV_AUX_SPARED: 12447294Sperrin aux = "SPARED"; 12457294Sperrin break; 12467294Sperrin case VDEV_AUX_ERR_EXCEEDED: 12477294Sperrin aux = "ERR_EXCEEDED"; 12487294Sperrin break; 12497294Sperrin case VDEV_AUX_IO_FAILURE: 12507294Sperrin aux = "IO_FAILURE"; 12517294Sperrin break; 12527294Sperrin case VDEV_AUX_BAD_LOG: 12537294Sperrin aux = "BAD_LOG"; 12547294Sperrin break; 125511422SMark.Musante@Sun.COM case VDEV_AUX_EXTERNAL: 125611422SMark.Musante@Sun.COM aux = "EXTERNAL"; 125711422SMark.Musante@Sun.COM break; 125811422SMark.Musante@Sun.COM case VDEV_AUX_SPLIT_POOL: 125911422SMark.Musante@Sun.COM aux = "SPLIT_POOL"; 126011422SMark.Musante@Sun.COM break; 1261789Sahrens default: 1262789Sahrens aux = "UNKNOWN"; 1263789Sahrens break; 1264789Sahrens } 1265789Sahrens 1266789Sahrens mdb_printf("%-9s %-12s %*s%s\n", state, aux, depth, "", desc); 1267789Sahrens 1268789Sahrens if (stats) { 1269789Sahrens vdev_stat_t *vs = &vdev.vdev_stat; 1270789Sahrens int i; 1271789Sahrens 1272789Sahrens mdb_inc_indent(4); 1273789Sahrens mdb_printf("\n"); 1274789Sahrens mdb_printf("%<u> %12s %12s %12s %12s " 1275789Sahrens "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM", 1276789Sahrens "IOCTL"); 1277789Sahrens mdb_printf("OPS "); 1278789Sahrens for (i = 1; i < ZIO_TYPES; i++) 1279789Sahrens mdb_printf("%11#llx%s", vs->vs_ops[i], 1280789Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1281789Sahrens mdb_printf("\n"); 1282789Sahrens mdb_printf("BYTES "); 1283789Sahrens for (i = 1; i < ZIO_TYPES; i++) 1284789Sahrens mdb_printf("%11#llx%s", vs->vs_bytes[i], 1285789Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1286789Sahrens 1287789Sahrens 1288789Sahrens mdb_printf("\n"); 1289789Sahrens mdb_printf("EREAD %10#llx\n", vs->vs_read_errors); 1290789Sahrens mdb_printf("EWRITE %10#llx\n", vs->vs_write_errors); 1291789Sahrens mdb_printf("ECKSUM %10#llx\n", 1292789Sahrens vs->vs_checksum_errors); 1293789Sahrens mdb_dec_indent(4); 1294789Sahrens } 1295789Sahrens 12963059Sahrens if (stats) 1297789Sahrens mdb_printf("\n"); 1298789Sahrens } 1299789Sahrens 1300789Sahrens children = vdev.vdev_children; 1301789Sahrens 1302789Sahrens if (children == 0 || !recursive) 1303789Sahrens return (DCMD_OK); 1304789Sahrens 1305789Sahrens child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1306789Sahrens if (mdb_vread(child, children * sizeof (void *), 1307789Sahrens (uintptr_t)vdev.vdev_child) == -1) { 1308789Sahrens mdb_warn("failed to read vdev children at %p", vdev.vdev_child); 1309789Sahrens return (DCMD_ERR); 1310789Sahrens } 1311789Sahrens 1312789Sahrens for (c = 0; c < children; c++) { 13133059Sahrens if (do_print_vdev(child[c], flags, depth + 2, stats, 1314789Sahrens recursive)) 1315789Sahrens return (DCMD_ERR); 1316789Sahrens } 1317789Sahrens 1318789Sahrens return (DCMD_OK); 1319789Sahrens } 1320789Sahrens 1321789Sahrens static int 1322789Sahrens vdev_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1323789Sahrens { 1324789Sahrens int recursive = FALSE; 1325789Sahrens int stats = FALSE; 13266643Seschrock uint64_t depth = 0; 1327789Sahrens 1328789Sahrens if (mdb_getopts(argc, argv, 1329789Sahrens 'r', MDB_OPT_SETBITS, TRUE, &recursive, 1330789Sahrens 'e', MDB_OPT_SETBITS, TRUE, &stats, 13316643Seschrock 'd', MDB_OPT_UINT64, &depth, 1332789Sahrens NULL) != argc) 1333789Sahrens return (DCMD_USAGE); 1334789Sahrens 1335789Sahrens if (!(flags & DCMD_ADDRSPEC)) { 1336789Sahrens mdb_warn("no vdev_t address given\n"); 1337789Sahrens return (DCMD_ERR); 1338789Sahrens } 1339789Sahrens 13406643Seschrock return (do_print_vdev(addr, flags, (int)depth, stats, recursive)); 1341789Sahrens } 1342789Sahrens 13432459Sahrens typedef struct metaslab_walk_data { 13442459Sahrens uint64_t mw_numvdevs; 13452459Sahrens uintptr_t *mw_vdevs; 13462459Sahrens int mw_curvdev; 13472459Sahrens uint64_t mw_nummss; 13482459Sahrens uintptr_t *mw_mss; 13492459Sahrens int mw_curms; 13502459Sahrens } metaslab_walk_data_t; 13512459Sahrens 13522459Sahrens static int 13532459Sahrens metaslab_walk_step(mdb_walk_state_t *wsp) 13542459Sahrens { 13552459Sahrens metaslab_walk_data_t *mw = wsp->walk_data; 13562459Sahrens metaslab_t ms; 13572459Sahrens uintptr_t msp; 13582459Sahrens 13592459Sahrens if (mw->mw_curvdev >= mw->mw_numvdevs) 13602459Sahrens return (WALK_DONE); 13612459Sahrens 13622459Sahrens if (mw->mw_mss == NULL) { 13632459Sahrens uintptr_t mssp; 13642459Sahrens uintptr_t vdevp; 13652459Sahrens 13662459Sahrens ASSERT(mw->mw_curms == 0); 13672459Sahrens ASSERT(mw->mw_nummss == 0); 13682459Sahrens 13692459Sahrens vdevp = mw->mw_vdevs[mw->mw_curvdev]; 13702459Sahrens if (GETMEMB(vdevp, struct vdev, vdev_ms, mssp) || 13712459Sahrens GETMEMB(vdevp, struct vdev, vdev_ms_count, mw->mw_nummss)) { 13722459Sahrens return (WALK_ERR); 13732459Sahrens } 13742459Sahrens 13752459Sahrens mw->mw_mss = mdb_alloc(mw->mw_nummss * sizeof (void*), 13762459Sahrens UM_SLEEP | UM_GC); 13772459Sahrens if (mdb_vread(mw->mw_mss, mw->mw_nummss * sizeof (void*), 13782459Sahrens mssp) == -1) { 13792459Sahrens mdb_warn("failed to read vdev_ms at %p", mssp); 13802459Sahrens return (WALK_ERR); 13812459Sahrens } 13822459Sahrens } 13832459Sahrens 13842459Sahrens if (mw->mw_curms >= mw->mw_nummss) { 13852459Sahrens mw->mw_mss = NULL; 13862459Sahrens mw->mw_curms = 0; 13872459Sahrens mw->mw_nummss = 0; 13882459Sahrens mw->mw_curvdev++; 13892459Sahrens return (WALK_NEXT); 13902459Sahrens } 13912459Sahrens 13922459Sahrens msp = mw->mw_mss[mw->mw_curms]; 13932459Sahrens if (mdb_vread(&ms, sizeof (metaslab_t), msp) == -1) { 13942459Sahrens mdb_warn("failed to read metaslab_t at %p", msp); 13952459Sahrens return (WALK_ERR); 13962459Sahrens } 13972459Sahrens 13982459Sahrens mw->mw_curms++; 13992459Sahrens 14002459Sahrens return (wsp->walk_callback(msp, &ms, wsp->walk_cbdata)); 14012459Sahrens } 14022459Sahrens 14032459Sahrens /* ARGSUSED */ 14042459Sahrens static int 14052459Sahrens metaslab_walk_init(mdb_walk_state_t *wsp) 14062459Sahrens { 14072459Sahrens metaslab_walk_data_t *mw; 14082459Sahrens uintptr_t root_vdevp; 14092459Sahrens uintptr_t childp; 14102459Sahrens 14112459Sahrens if (wsp->walk_addr == NULL) { 14122459Sahrens mdb_warn("must supply address of spa_t\n"); 14132459Sahrens return (WALK_ERR); 14142459Sahrens } 14152459Sahrens 14162459Sahrens mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC); 14172459Sahrens 14182459Sahrens if (GETMEMB(wsp->walk_addr, struct spa, spa_root_vdev, root_vdevp) || 14192459Sahrens GETMEMB(root_vdevp, struct vdev, vdev_children, mw->mw_numvdevs) || 14202459Sahrens GETMEMB(root_vdevp, struct vdev, vdev_child, childp)) { 14212459Sahrens return (DCMD_ERR); 14222459Sahrens } 14232459Sahrens 14242459Sahrens mw->mw_vdevs = mdb_alloc(mw->mw_numvdevs * sizeof (void *), 14252459Sahrens UM_SLEEP | UM_GC); 14262459Sahrens if (mdb_vread(mw->mw_vdevs, mw->mw_numvdevs * sizeof (void *), 14272459Sahrens childp) == -1) { 14282459Sahrens mdb_warn("failed to read root vdev children at %p", childp); 14292459Sahrens return (DCMD_ERR); 14302459Sahrens } 14312459Sahrens 14322459Sahrens wsp->walk_data = mw; 14332459Sahrens 14342459Sahrens return (WALK_NEXT); 14352459Sahrens } 14362459Sahrens 1437789Sahrens typedef struct mdb_spa { 1438789Sahrens uintptr_t spa_dsl_pool; 1439789Sahrens uintptr_t spa_root_vdev; 1440789Sahrens } mdb_spa_t; 1441789Sahrens 1442789Sahrens typedef struct mdb_dsl_dir { 1443789Sahrens uintptr_t dd_phys; 1444789Sahrens int64_t dd_space_towrite[TXG_SIZE]; 1445789Sahrens } mdb_dsl_dir_t; 1446789Sahrens 1447789Sahrens typedef struct mdb_dsl_dir_phys { 1448789Sahrens uint64_t dd_used_bytes; 1449789Sahrens uint64_t dd_compressed_bytes; 1450789Sahrens uint64_t dd_uncompressed_bytes; 1451789Sahrens } mdb_dsl_dir_phys_t; 1452789Sahrens 1453789Sahrens typedef struct mdb_vdev { 1454789Sahrens uintptr_t vdev_parent; 1455789Sahrens uintptr_t vdev_ms; 1456789Sahrens uint64_t vdev_ms_count; 1457789Sahrens vdev_stat_t vdev_stat; 1458789Sahrens } mdb_vdev_t; 1459789Sahrens 1460789Sahrens typedef struct mdb_metaslab { 1461789Sahrens space_map_t ms_allocmap[TXG_SIZE]; 1462789Sahrens space_map_t ms_freemap[TXG_SIZE]; 1463789Sahrens space_map_t ms_map; 14641732Sbonwick space_map_obj_t ms_smo; 14652459Sahrens space_map_obj_t ms_smo_syncing; 1466789Sahrens } mdb_metaslab_t; 1467789Sahrens 14682459Sahrens typedef struct space_data { 14692459Sahrens uint64_t ms_allocmap[TXG_SIZE]; 14702459Sahrens uint64_t ms_freemap[TXG_SIZE]; 14712459Sahrens uint64_t ms_map; 14722459Sahrens uint64_t avail; 14732459Sahrens uint64_t nowavail; 14742459Sahrens } space_data_t; 14752459Sahrens 14762459Sahrens /* ARGSUSED */ 14772459Sahrens static int 14782459Sahrens space_cb(uintptr_t addr, const void *unknown, void *arg) 14792459Sahrens { 14802459Sahrens space_data_t *sd = arg; 14812459Sahrens mdb_metaslab_t ms; 14822459Sahrens 14832459Sahrens if (GETMEMB(addr, struct metaslab, ms_allocmap, ms.ms_allocmap) || 14842459Sahrens GETMEMB(addr, struct metaslab, ms_freemap, ms.ms_freemap) || 14852459Sahrens GETMEMB(addr, struct metaslab, ms_map, ms.ms_map) || 14862459Sahrens GETMEMB(addr, struct metaslab, ms_smo, ms.ms_smo) || 14872459Sahrens GETMEMB(addr, struct metaslab, ms_smo_syncing, ms.ms_smo_syncing)) { 14882459Sahrens return (WALK_ERR); 14892459Sahrens } 14902459Sahrens 14912459Sahrens sd->ms_allocmap[0] += ms.ms_allocmap[0].sm_space; 14922459Sahrens sd->ms_allocmap[1] += ms.ms_allocmap[1].sm_space; 14932459Sahrens sd->ms_allocmap[2] += ms.ms_allocmap[2].sm_space; 14942459Sahrens sd->ms_allocmap[3] += ms.ms_allocmap[3].sm_space; 14952459Sahrens sd->ms_freemap[0] += ms.ms_freemap[0].sm_space; 14962459Sahrens sd->ms_freemap[1] += ms.ms_freemap[1].sm_space; 14972459Sahrens sd->ms_freemap[2] += ms.ms_freemap[2].sm_space; 14982459Sahrens sd->ms_freemap[3] += ms.ms_freemap[3].sm_space; 14992459Sahrens sd->ms_map += ms.ms_map.sm_space; 15002459Sahrens sd->avail += ms.ms_map.sm_size - ms.ms_smo.smo_alloc; 15012459Sahrens sd->nowavail += ms.ms_map.sm_size - ms.ms_smo_syncing.smo_alloc; 15022459Sahrens 15032459Sahrens return (WALK_NEXT); 15042459Sahrens } 15052459Sahrens 1506789Sahrens /* 1507789Sahrens * ::spa_space [-b] 1508789Sahrens * 1509789Sahrens * Given a spa_t, print out it's on-disk space usage and in-core 1510789Sahrens * estimates of future usage. If -b is given, print space in bytes. 1511789Sahrens * Otherwise print in megabytes. 1512789Sahrens */ 1513789Sahrens /* ARGSUSED */ 1514789Sahrens static int 1515789Sahrens spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1516789Sahrens { 1517789Sahrens mdb_spa_t spa; 1518789Sahrens uintptr_t dp_root_dir; 1519789Sahrens mdb_dsl_dir_t dd; 1520789Sahrens mdb_dsl_dir_phys_t dsp; 1521789Sahrens uint64_t children; 1522789Sahrens uintptr_t childaddr; 15232459Sahrens space_data_t sd; 1524789Sahrens int shift = 20; 1525789Sahrens char *suffix = "M"; 1526789Sahrens int bits = FALSE; 1527789Sahrens 1528789Sahrens if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bits, NULL) != 1529789Sahrens argc) 1530789Sahrens return (DCMD_USAGE); 1531789Sahrens if (!(flags & DCMD_ADDRSPEC)) 1532789Sahrens return (DCMD_USAGE); 1533789Sahrens 1534789Sahrens if (bits) { 1535789Sahrens shift = 0; 1536789Sahrens suffix = ""; 1537789Sahrens } 1538789Sahrens 1539789Sahrens if (GETMEMB(addr, struct spa, spa_dsl_pool, spa.spa_dsl_pool) || 1540789Sahrens GETMEMB(addr, struct spa, spa_root_vdev, spa.spa_root_vdev) || 1541789Sahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_children, children) || 1542789Sahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_child, childaddr) || 1543789Sahrens GETMEMB(spa.spa_dsl_pool, struct dsl_pool, 1544789Sahrens dp_root_dir, dp_root_dir) || 1545789Sahrens GETMEMB(dp_root_dir, struct dsl_dir, dd_phys, dd.dd_phys) || 1546789Sahrens GETMEMB(dp_root_dir, struct dsl_dir, 1547789Sahrens dd_space_towrite, dd.dd_space_towrite) || 1548789Sahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 15492459Sahrens dd_used_bytes, dsp.dd_used_bytes) || 15502459Sahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1551789Sahrens dd_compressed_bytes, dsp.dd_compressed_bytes) || 1552789Sahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1553789Sahrens dd_uncompressed_bytes, dsp.dd_uncompressed_bytes)) { 1554789Sahrens return (DCMD_ERR); 1555789Sahrens } 1556789Sahrens 1557789Sahrens mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n", 1558789Sahrens dd.dd_space_towrite[0] >> shift, suffix, 1559789Sahrens dd.dd_space_towrite[1] >> shift, suffix, 1560789Sahrens dd.dd_space_towrite[2] >> shift, suffix, 1561789Sahrens dd.dd_space_towrite[3] >> shift, suffix); 1562789Sahrens 1563789Sahrens mdb_printf("dd_phys.dd_used_bytes = %llu%s\n", 1564789Sahrens dsp.dd_used_bytes >> shift, suffix); 15652459Sahrens mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n", 15662459Sahrens dsp.dd_compressed_bytes >> shift, suffix); 15672459Sahrens mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n", 15682459Sahrens dsp.dd_uncompressed_bytes >> shift, suffix); 1569789Sahrens 15702459Sahrens bzero(&sd, sizeof (sd)); 15712459Sahrens if (mdb_pwalk("metaslab", space_cb, &sd, addr) != 0) { 15722459Sahrens mdb_warn("can't walk metaslabs"); 15732459Sahrens return (DCMD_ERR); 1574789Sahrens } 1575789Sahrens 1576789Sahrens mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n", 15772459Sahrens sd.ms_allocmap[0] >> shift, suffix, 15782459Sahrens sd.ms_allocmap[1] >> shift, suffix, 15792459Sahrens sd.ms_allocmap[2] >> shift, suffix, 15802459Sahrens sd.ms_allocmap[3] >> shift, suffix); 1581789Sahrens mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n", 15822459Sahrens sd.ms_freemap[0] >> shift, suffix, 15832459Sahrens sd.ms_freemap[1] >> shift, suffix, 15842459Sahrens sd.ms_freemap[2] >> shift, suffix, 15852459Sahrens sd.ms_freemap[3] >> shift, suffix); 15862459Sahrens mdb_printf("ms_map = %llu%s\n", sd.ms_map >> shift, suffix); 15872459Sahrens mdb_printf("last synced avail = %llu%s\n", sd.avail >> shift, suffix); 15882459Sahrens mdb_printf("current syncing avail = %llu%s\n", 15892459Sahrens sd.nowavail >> shift, suffix); 1590789Sahrens 1591789Sahrens return (DCMD_OK); 1592789Sahrens } 1593789Sahrens 1594789Sahrens /* 1595789Sahrens * ::spa_verify 1596789Sahrens * 1597789Sahrens * Given a spa_t, verify that that the pool is self-consistent. 1598789Sahrens * Currently, it only checks to make sure that the vdev tree exists. 1599789Sahrens */ 1600789Sahrens /* ARGSUSED */ 1601789Sahrens static int 1602789Sahrens spa_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1603789Sahrens { 1604789Sahrens spa_t spa; 1605789Sahrens 1606789Sahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1607789Sahrens return (DCMD_USAGE); 1608789Sahrens 1609789Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1610789Sahrens mdb_warn("failed to read spa_t at %p", addr); 1611789Sahrens return (DCMD_ERR); 1612789Sahrens } 1613789Sahrens 1614789Sahrens if (spa.spa_root_vdev == NULL) { 1615789Sahrens mdb_printf("no vdev tree present\n"); 1616789Sahrens return (DCMD_OK); 1617789Sahrens } 1618789Sahrens 1619789Sahrens return (DCMD_OK); 1620789Sahrens } 1621789Sahrens 16228341SEric.Schrock@Sun.COM static int 16238341SEric.Schrock@Sun.COM spa_print_aux(spa_aux_vdev_t *sav, uint_t flags, mdb_arg_t *v, 16248341SEric.Schrock@Sun.COM const char *name) 16258341SEric.Schrock@Sun.COM { 16268341SEric.Schrock@Sun.COM uintptr_t *aux; 16278341SEric.Schrock@Sun.COM size_t len; 16288341SEric.Schrock@Sun.COM int ret, i; 16298341SEric.Schrock@Sun.COM 16308341SEric.Schrock@Sun.COM /* 16318341SEric.Schrock@Sun.COM * Iterate over aux vdevs and print those out as well. This is a 16328341SEric.Schrock@Sun.COM * little annoying because we don't have a root vdev to pass to ::vdev. 16338341SEric.Schrock@Sun.COM * Instead, we print a single line and then call it for each child 16348341SEric.Schrock@Sun.COM * vdev. 16358341SEric.Schrock@Sun.COM */ 16368341SEric.Schrock@Sun.COM if (sav->sav_count != 0) { 16378341SEric.Schrock@Sun.COM v[1].a_type = MDB_TYPE_STRING; 16388341SEric.Schrock@Sun.COM v[1].a_un.a_str = "-d"; 16398341SEric.Schrock@Sun.COM v[2].a_type = MDB_TYPE_IMMEDIATE; 16408341SEric.Schrock@Sun.COM v[2].a_un.a_val = 2; 16418341SEric.Schrock@Sun.COM 16428341SEric.Schrock@Sun.COM len = sav->sav_count * sizeof (uintptr_t); 16438341SEric.Schrock@Sun.COM aux = mdb_alloc(len, UM_SLEEP); 16448341SEric.Schrock@Sun.COM if (mdb_vread(aux, len, 16458341SEric.Schrock@Sun.COM (uintptr_t)sav->sav_vdevs) == -1) { 16468341SEric.Schrock@Sun.COM mdb_free(aux, len); 16478341SEric.Schrock@Sun.COM mdb_warn("failed to read l2cache vdevs at %p", 16488341SEric.Schrock@Sun.COM sav->sav_vdevs); 16498341SEric.Schrock@Sun.COM return (DCMD_ERR); 16508341SEric.Schrock@Sun.COM } 16518341SEric.Schrock@Sun.COM 16528341SEric.Schrock@Sun.COM mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name); 16538341SEric.Schrock@Sun.COM 16548341SEric.Schrock@Sun.COM for (i = 0; i < sav->sav_count; i++) { 16558341SEric.Schrock@Sun.COM ret = mdb_call_dcmd("vdev", aux[i], flags, 3, v); 16568341SEric.Schrock@Sun.COM if (ret != DCMD_OK) { 16578341SEric.Schrock@Sun.COM mdb_free(aux, len); 16588341SEric.Schrock@Sun.COM return (ret); 16598341SEric.Schrock@Sun.COM } 16608341SEric.Schrock@Sun.COM } 16618341SEric.Schrock@Sun.COM 16628341SEric.Schrock@Sun.COM mdb_free(aux, len); 16638341SEric.Schrock@Sun.COM } 16648341SEric.Schrock@Sun.COM 16658341SEric.Schrock@Sun.COM return (0); 16668341SEric.Schrock@Sun.COM } 16678341SEric.Schrock@Sun.COM 1668789Sahrens /* 1669789Sahrens * ::spa_vdevs 1670789Sahrens * 1671789Sahrens * -e Include error stats 1672789Sahrens * 1673789Sahrens * Print out a summarized list of vdevs for the given spa_t. 16746643Seschrock * This is accomplished by invoking "::vdev -re" on the root vdev, as well as 16756643Seschrock * iterating over the cache devices. 1676789Sahrens */ 1677789Sahrens /* ARGSUSED */ 1678789Sahrens static int 1679789Sahrens spa_vdevs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1680789Sahrens { 1681789Sahrens spa_t spa; 16826643Seschrock mdb_arg_t v[3]; 1683789Sahrens int errors = FALSE; 16848341SEric.Schrock@Sun.COM int ret; 1685789Sahrens 1686789Sahrens if (mdb_getopts(argc, argv, 1687789Sahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 1688789Sahrens NULL) != argc) 1689789Sahrens return (DCMD_USAGE); 1690789Sahrens 1691789Sahrens if (!(flags & DCMD_ADDRSPEC)) 1692789Sahrens return (DCMD_USAGE); 1693789Sahrens 1694789Sahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1695789Sahrens mdb_warn("failed to read spa_t at %p", addr); 1696789Sahrens return (DCMD_ERR); 1697789Sahrens } 1698789Sahrens 1699952Seschrock /* 1700952Seschrock * Unitialized spa_t structures can have a NULL root vdev. 1701952Seschrock */ 1702952Seschrock if (spa.spa_root_vdev == NULL) { 1703952Seschrock mdb_printf("no associated vdevs\n"); 1704952Seschrock return (DCMD_OK); 1705952Seschrock } 1706952Seschrock 17076643Seschrock v[0].a_type = MDB_TYPE_STRING; 17086643Seschrock v[0].a_un.a_str = errors ? "-re" : "-r"; 17096643Seschrock 17106643Seschrock ret = mdb_call_dcmd("vdev", (uintptr_t)spa.spa_root_vdev, 17116643Seschrock flags, 1, v); 17126643Seschrock if (ret != DCMD_OK) 17136643Seschrock return (ret); 17146643Seschrock 17158341SEric.Schrock@Sun.COM if (spa_print_aux(&spa.spa_l2cache, flags, v, "cache") != 0 || 17168341SEric.Schrock@Sun.COM spa_print_aux(&spa.spa_spares, flags, v, "spares") != 0) 17178341SEric.Schrock@Sun.COM return (DCMD_ERR); 17186643Seschrock 17196643Seschrock return (DCMD_OK); 1720789Sahrens } 1721789Sahrens 17224055Seschrock /* 17234055Seschrock * ::zio 17244055Seschrock * 17254055Seschrock * Print a summary of zio_t and all its children. This is intended to display a 17264055Seschrock * zio tree, and hence we only pick the most important pieces of information for 17274055Seschrock * the main summary. More detailed information can always be found by doing a 17284055Seschrock * '::print zio' on the underlying zio_t. The columns we display are: 17294055Seschrock * 17304055Seschrock * ADDRESS TYPE STAGE WAITER 17314055Seschrock * 17324055Seschrock * The 'address' column is indented by one space for each depth level as we 17334055Seschrock * descend down the tree. 17344055Seschrock */ 17354217Seschrock 17368632SBill.Moore@Sun.COM #define ZIO_MAXINDENT 24 17378632SBill.Moore@Sun.COM #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT) 17388632SBill.Moore@Sun.COM #define ZIO_WALK_SELF 0 17398632SBill.Moore@Sun.COM #define ZIO_WALK_CHILD 1 17408632SBill.Moore@Sun.COM #define ZIO_WALK_PARENT 2 17418632SBill.Moore@Sun.COM 17428632SBill.Moore@Sun.COM typedef struct zio_print_args { 17438632SBill.Moore@Sun.COM int zpa_current_depth; 17448632SBill.Moore@Sun.COM int zpa_min_depth; 17458632SBill.Moore@Sun.COM int zpa_max_depth; 17468632SBill.Moore@Sun.COM int zpa_type; 17478632SBill.Moore@Sun.COM uint_t zpa_flags; 17488632SBill.Moore@Sun.COM } zio_print_args_t; 17498632SBill.Moore@Sun.COM 17508632SBill.Moore@Sun.COM static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg); 17514217Seschrock 17524055Seschrock static int 17534055Seschrock zio_print_cb(uintptr_t addr, const void *data, void *priv) 17544055Seschrock { 17554055Seschrock const zio_t *zio = data; 17568632SBill.Moore@Sun.COM zio_print_args_t *zpa = priv; 17574055Seschrock mdb_ctf_id_t type_enum, stage_enum; 17588632SBill.Moore@Sun.COM int indent = zpa->zpa_current_depth; 17594055Seschrock const char *type, *stage; 17608632SBill.Moore@Sun.COM uintptr_t laddr; 17614055Seschrock 17628632SBill.Moore@Sun.COM if (indent > ZIO_MAXINDENT) 17638632SBill.Moore@Sun.COM indent = ZIO_MAXINDENT; 17644055Seschrock 17654055Seschrock if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum) == -1 || 17664055Seschrock mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum) == -1) { 17674055Seschrock mdb_warn("failed to lookup zio enums"); 17684055Seschrock return (WALK_ERR); 17694055Seschrock } 17704055Seschrock 17714055Seschrock if ((type = mdb_ctf_enum_name(type_enum, zio->io_type)) != NULL) 17724055Seschrock type += sizeof ("ZIO_TYPE_") - 1; 17734055Seschrock else 17744055Seschrock type = "?"; 17754055Seschrock 17764055Seschrock if ((stage = mdb_ctf_enum_name(stage_enum, zio->io_stage)) != NULL) 17774055Seschrock stage += sizeof ("ZIO_STAGE_") - 1; 17784055Seschrock else 17794055Seschrock stage = "?"; 17804055Seschrock 17818632SBill.Moore@Sun.COM if (zpa->zpa_current_depth >= zpa->zpa_min_depth) { 17828632SBill.Moore@Sun.COM if (zpa->zpa_flags & DCMD_PIPE_OUT) { 17838632SBill.Moore@Sun.COM mdb_printf("%?p\n", addr); 17848632SBill.Moore@Sun.COM } else { 17858632SBill.Moore@Sun.COM mdb_printf("%*s%-*p %-5s %-16s ", indent, "", 17868632SBill.Moore@Sun.COM ZIO_MAXWIDTH - indent, addr, type, stage); 17878632SBill.Moore@Sun.COM if (zio->io_waiter) 17888632SBill.Moore@Sun.COM mdb_printf("%?p\n", zio->io_waiter); 17898632SBill.Moore@Sun.COM else 17908632SBill.Moore@Sun.COM mdb_printf("-\n"); 17918632SBill.Moore@Sun.COM } 17928632SBill.Moore@Sun.COM } 17934055Seschrock 17948632SBill.Moore@Sun.COM if (zpa->zpa_current_depth >= zpa->zpa_max_depth) 17958632SBill.Moore@Sun.COM return (WALK_NEXT); 17968632SBill.Moore@Sun.COM 17978632SBill.Moore@Sun.COM if (zpa->zpa_type == ZIO_WALK_PARENT) 17988632SBill.Moore@Sun.COM laddr = addr + OFFSETOF(zio_t, io_parent_list); 17994055Seschrock else 18008632SBill.Moore@Sun.COM laddr = addr + OFFSETOF(zio_t, io_child_list); 18014055Seschrock 18028632SBill.Moore@Sun.COM zpa->zpa_current_depth++; 18038632SBill.Moore@Sun.COM if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) { 18048632SBill.Moore@Sun.COM mdb_warn("failed to walk zio_t children at %p\n", laddr); 18054055Seschrock return (WALK_ERR); 18064055Seschrock } 18078632SBill.Moore@Sun.COM zpa->zpa_current_depth--; 18084055Seschrock 18094055Seschrock return (WALK_NEXT); 18104055Seschrock } 18114055Seschrock 18128632SBill.Moore@Sun.COM /* ARGSUSED */ 18138632SBill.Moore@Sun.COM static int 18148632SBill.Moore@Sun.COM zio_child_cb(uintptr_t addr, const void *unknown, void *arg) 18158632SBill.Moore@Sun.COM { 18168632SBill.Moore@Sun.COM zio_link_t zl; 18178632SBill.Moore@Sun.COM zio_t zio; 18188632SBill.Moore@Sun.COM uintptr_t ziop; 18198632SBill.Moore@Sun.COM zio_print_args_t *zpa = arg; 18208632SBill.Moore@Sun.COM 18218632SBill.Moore@Sun.COM if (mdb_vread(&zl, sizeof (zl), addr) == -1) { 18228632SBill.Moore@Sun.COM mdb_warn("failed to read zio_link_t at %p", addr); 18238632SBill.Moore@Sun.COM return (WALK_ERR); 18248632SBill.Moore@Sun.COM } 18258632SBill.Moore@Sun.COM 18268632SBill.Moore@Sun.COM if (zpa->zpa_type == ZIO_WALK_PARENT) 18278632SBill.Moore@Sun.COM ziop = (uintptr_t)zl.zl_parent; 18288632SBill.Moore@Sun.COM else 18298632SBill.Moore@Sun.COM ziop = (uintptr_t)zl.zl_child; 18308632SBill.Moore@Sun.COM 18318632SBill.Moore@Sun.COM if (mdb_vread(&zio, sizeof (zio_t), ziop) == -1) { 18328632SBill.Moore@Sun.COM mdb_warn("failed to read zio_t at %p", ziop); 18338632SBill.Moore@Sun.COM return (WALK_ERR); 18348632SBill.Moore@Sun.COM } 18358632SBill.Moore@Sun.COM 18368632SBill.Moore@Sun.COM return (zio_print_cb(ziop, &zio, arg)); 18378632SBill.Moore@Sun.COM } 18388632SBill.Moore@Sun.COM 18398632SBill.Moore@Sun.COM /* ARGSUSED */ 18404055Seschrock static int 18414055Seschrock zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 18424055Seschrock { 18434055Seschrock zio_t zio; 18448632SBill.Moore@Sun.COM zio_print_args_t zpa = { 0 }; 18454055Seschrock 18464055Seschrock if (!(flags & DCMD_ADDRSPEC)) 18474055Seschrock return (DCMD_USAGE); 18484055Seschrock 18498632SBill.Moore@Sun.COM if (mdb_getopts(argc, argv, 18508632SBill.Moore@Sun.COM 'r', MDB_OPT_SETBITS, INT_MAX, &zpa.zpa_max_depth, 18518632SBill.Moore@Sun.COM 'c', MDB_OPT_SETBITS, ZIO_WALK_CHILD, &zpa.zpa_type, 18528632SBill.Moore@Sun.COM 'p', MDB_OPT_SETBITS, ZIO_WALK_PARENT, &zpa.zpa_type, 18538632SBill.Moore@Sun.COM NULL) != argc) 18548632SBill.Moore@Sun.COM return (DCMD_USAGE); 18558632SBill.Moore@Sun.COM 18568632SBill.Moore@Sun.COM zpa.zpa_flags = flags; 18578632SBill.Moore@Sun.COM if (zpa.zpa_max_depth != 0) { 18588632SBill.Moore@Sun.COM if (zpa.zpa_type == ZIO_WALK_SELF) 18598632SBill.Moore@Sun.COM zpa.zpa_type = ZIO_WALK_CHILD; 18608632SBill.Moore@Sun.COM } else if (zpa.zpa_type != ZIO_WALK_SELF) { 18618632SBill.Moore@Sun.COM zpa.zpa_min_depth = 1; 18628632SBill.Moore@Sun.COM zpa.zpa_max_depth = 1; 18638632SBill.Moore@Sun.COM } 18648632SBill.Moore@Sun.COM 18654055Seschrock if (mdb_vread(&zio, sizeof (zio_t), addr) == -1) { 18664055Seschrock mdb_warn("failed to read zio_t at %p", addr); 18674055Seschrock return (DCMD_ERR); 18684055Seschrock } 18694055Seschrock 18708632SBill.Moore@Sun.COM if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) 18718632SBill.Moore@Sun.COM mdb_printf("%<u>%-*s %-5s %-16s %-?s%</u>\n", ZIO_MAXWIDTH, 18724217Seschrock "ADDRESS", "TYPE", "STAGE", "WAITER"); 18734217Seschrock 18748632SBill.Moore@Sun.COM if (zio_print_cb(addr, &zio, &zpa) != WALK_NEXT) 18754055Seschrock return (DCMD_ERR); 18764055Seschrock 18774055Seschrock return (DCMD_OK); 18784055Seschrock } 18794055Seschrock 18804055Seschrock /* 18814055Seschrock * [addr]::zio_state 18824055Seschrock * 18834055Seschrock * Print a summary of all zio_t structures on the system, or for a particular 18844055Seschrock * pool. This is equivalent to '::walk zio_root | ::zio'. 18854055Seschrock */ 18864055Seschrock /*ARGSUSED*/ 18874055Seschrock static int 18884055Seschrock zio_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 18894055Seschrock { 18904055Seschrock /* 18914055Seschrock * MDB will remember the last address of the pipeline, so if we don't 18924055Seschrock * zero this we'll end up trying to walk zio structures for a 18934055Seschrock * non-existent spa_t. 18944055Seschrock */ 18954055Seschrock if (!(flags & DCMD_ADDRSPEC)) 18964055Seschrock addr = 0; 18974055Seschrock 18984055Seschrock return (mdb_pwalk_dcmd("zio_root", "zio", argc, argv, addr)); 18994055Seschrock } 19004055Seschrock 1901789Sahrens typedef struct txg_list_walk_data { 1902789Sahrens uintptr_t lw_head[TXG_SIZE]; 1903789Sahrens int lw_txgoff; 1904789Sahrens int lw_maxoff; 1905789Sahrens size_t lw_offset; 1906789Sahrens void *lw_obj; 1907789Sahrens } txg_list_walk_data_t; 1908789Sahrens 1909789Sahrens static int 1910789Sahrens txg_list_walk_init_common(mdb_walk_state_t *wsp, int txg, int maxoff) 1911789Sahrens { 1912789Sahrens txg_list_walk_data_t *lwd; 1913789Sahrens txg_list_t list; 1914789Sahrens int i; 1915789Sahrens 1916789Sahrens lwd = mdb_alloc(sizeof (txg_list_walk_data_t), UM_SLEEP | UM_GC); 1917789Sahrens if (mdb_vread(&list, sizeof (txg_list_t), wsp->walk_addr) == -1) { 1918789Sahrens mdb_warn("failed to read txg_list_t at %#lx", wsp->walk_addr); 1919789Sahrens return (WALK_ERR); 1920789Sahrens } 1921789Sahrens 1922789Sahrens for (i = 0; i < TXG_SIZE; i++) 1923789Sahrens lwd->lw_head[i] = (uintptr_t)list.tl_head[i]; 1924789Sahrens lwd->lw_offset = list.tl_offset; 1925789Sahrens lwd->lw_obj = mdb_alloc(lwd->lw_offset + sizeof (txg_node_t), 1926789Sahrens UM_SLEEP | UM_GC); 1927789Sahrens lwd->lw_txgoff = txg; 1928789Sahrens lwd->lw_maxoff = maxoff; 1929789Sahrens 1930789Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1931789Sahrens wsp->walk_data = lwd; 1932789Sahrens 1933789Sahrens return (WALK_NEXT); 1934789Sahrens } 1935789Sahrens 1936789Sahrens static int 1937789Sahrens txg_list_walk_init(mdb_walk_state_t *wsp) 1938789Sahrens { 1939789Sahrens return (txg_list_walk_init_common(wsp, 0, TXG_SIZE-1)); 1940789Sahrens } 1941789Sahrens 1942789Sahrens static int 1943789Sahrens txg_list0_walk_init(mdb_walk_state_t *wsp) 1944789Sahrens { 1945789Sahrens return (txg_list_walk_init_common(wsp, 0, 0)); 1946789Sahrens } 1947789Sahrens 1948789Sahrens static int 1949789Sahrens txg_list1_walk_init(mdb_walk_state_t *wsp) 1950789Sahrens { 1951789Sahrens return (txg_list_walk_init_common(wsp, 1, 1)); 1952789Sahrens } 1953789Sahrens 1954789Sahrens static int 1955789Sahrens txg_list2_walk_init(mdb_walk_state_t *wsp) 1956789Sahrens { 1957789Sahrens return (txg_list_walk_init_common(wsp, 2, 2)); 1958789Sahrens } 1959789Sahrens 1960789Sahrens static int 1961789Sahrens txg_list3_walk_init(mdb_walk_state_t *wsp) 1962789Sahrens { 1963789Sahrens return (txg_list_walk_init_common(wsp, 3, 3)); 1964789Sahrens } 1965789Sahrens 1966789Sahrens static int 1967789Sahrens txg_list_walk_step(mdb_walk_state_t *wsp) 1968789Sahrens { 1969789Sahrens txg_list_walk_data_t *lwd = wsp->walk_data; 1970789Sahrens uintptr_t addr; 1971789Sahrens txg_node_t *node; 1972789Sahrens int status; 1973789Sahrens 1974789Sahrens while (wsp->walk_addr == NULL && lwd->lw_txgoff < lwd->lw_maxoff) { 1975789Sahrens lwd->lw_txgoff++; 1976789Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1977789Sahrens } 1978789Sahrens 1979789Sahrens if (wsp->walk_addr == NULL) 1980789Sahrens return (WALK_DONE); 1981789Sahrens 1982789Sahrens addr = wsp->walk_addr - lwd->lw_offset; 1983789Sahrens 1984789Sahrens if (mdb_vread(lwd->lw_obj, 1985789Sahrens lwd->lw_offset + sizeof (txg_node_t), addr) == -1) { 1986789Sahrens mdb_warn("failed to read list element at %#lx", addr); 1987789Sahrens return (WALK_ERR); 1988789Sahrens } 1989789Sahrens 1990789Sahrens status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata); 1991789Sahrens node = (txg_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset); 1992789Sahrens wsp->walk_addr = (uintptr_t)node->tn_next[lwd->lw_txgoff]; 1993789Sahrens 1994789Sahrens return (status); 1995789Sahrens } 1996789Sahrens 1997789Sahrens /* 1998789Sahrens * ::walk spa 1999789Sahrens * 2000789Sahrens * Walk all named spa_t structures in the namespace. This is nothing more than 2001789Sahrens * a layered avl walk. 2002789Sahrens */ 2003789Sahrens static int 2004789Sahrens spa_walk_init(mdb_walk_state_t *wsp) 2005789Sahrens { 2006789Sahrens GElf_Sym sym; 2007789Sahrens 2008789Sahrens if (wsp->walk_addr != NULL) { 2009789Sahrens mdb_warn("spa walk only supports global walks\n"); 2010789Sahrens return (WALK_ERR); 2011789Sahrens } 2012789Sahrens 2013789Sahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "spa_namespace_avl", &sym) == -1) { 2014789Sahrens mdb_warn("failed to find symbol 'spa_namespace_avl'"); 2015789Sahrens return (WALK_ERR); 2016789Sahrens } 2017789Sahrens 2018789Sahrens wsp->walk_addr = (uintptr_t)sym.st_value; 2019789Sahrens 2020789Sahrens if (mdb_layered_walk("avl", wsp) == -1) { 2021789Sahrens mdb_warn("failed to walk 'avl'\n"); 2022789Sahrens return (WALK_ERR); 2023789Sahrens } 2024789Sahrens 2025789Sahrens return (WALK_NEXT); 2026789Sahrens } 2027789Sahrens 2028789Sahrens static int 2029789Sahrens spa_walk_step(mdb_walk_state_t *wsp) 2030789Sahrens { 2031789Sahrens spa_t spa; 2032789Sahrens 2033789Sahrens if (mdb_vread(&spa, sizeof (spa), wsp->walk_addr) == -1) { 2034789Sahrens mdb_warn("failed to read spa_t at %p", wsp->walk_addr); 2035789Sahrens return (WALK_ERR); 2036789Sahrens } 2037789Sahrens 2038789Sahrens return (wsp->walk_callback(wsp->walk_addr, &spa, wsp->walk_cbdata)); 2039789Sahrens } 2040789Sahrens 2041789Sahrens /* 20424055Seschrock * [addr]::walk zio 20434055Seschrock * 20444055Seschrock * Walk all active zio_t structures on the system. This is simply a layered 20454055Seschrock * walk on top of ::walk zio_cache, with the optional ability to limit the 20464055Seschrock * structures to a particular pool. 20474055Seschrock */ 20484055Seschrock static int 20494055Seschrock zio_walk_init(mdb_walk_state_t *wsp) 20504055Seschrock { 20514055Seschrock wsp->walk_data = (void *)wsp->walk_addr; 20524055Seschrock 20534055Seschrock if (mdb_layered_walk("zio_cache", wsp) == -1) { 20544055Seschrock mdb_warn("failed to walk 'zio_cache'\n"); 20554055Seschrock return (WALK_ERR); 20564055Seschrock } 20574055Seschrock 20584055Seschrock return (WALK_NEXT); 20594055Seschrock } 20604055Seschrock 20614055Seschrock static int 20624055Seschrock zio_walk_step(mdb_walk_state_t *wsp) 20634055Seschrock { 20644055Seschrock zio_t zio; 20654055Seschrock 20664055Seschrock if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { 20674055Seschrock mdb_warn("failed to read zio_t at %p", wsp->walk_addr); 20684055Seschrock return (WALK_ERR); 20694055Seschrock } 20704055Seschrock 20714055Seschrock if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) 20724055Seschrock return (WALK_NEXT); 20734055Seschrock 20744055Seschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 20754055Seschrock } 20764055Seschrock 20774055Seschrock /* 20784055Seschrock * [addr]::walk zio_root 20794055Seschrock * 20804055Seschrock * Walk only root zio_t structures, optionally for a particular spa_t. 20814055Seschrock */ 20824055Seschrock static int 20834055Seschrock zio_walk_root_step(mdb_walk_state_t *wsp) 20844055Seschrock { 20854055Seschrock zio_t zio; 20864055Seschrock 20874055Seschrock if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { 20884055Seschrock mdb_warn("failed to read zio_t at %p", wsp->walk_addr); 20894055Seschrock return (WALK_ERR); 20904055Seschrock } 20914055Seschrock 20924055Seschrock if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) 20934055Seschrock return (WALK_NEXT); 20944055Seschrock 20958632SBill.Moore@Sun.COM /* If the parent list is not empty, ignore */ 20968632SBill.Moore@Sun.COM if (zio.io_parent_list.list_head.list_next != 20978632SBill.Moore@Sun.COM &((zio_t *)wsp->walk_addr)->io_parent_list.list_head) 20984055Seschrock return (WALK_NEXT); 20994055Seschrock 21004055Seschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 21014055Seschrock } 21024055Seschrock 21037837SMatthew.Ahrens@Sun.COM #define NICENUM_BUFLEN 6 21047837SMatthew.Ahrens@Sun.COM 21057837SMatthew.Ahrens@Sun.COM static int 21067846SMatthew.Ahrens@Sun.COM snprintfrac(char *buf, int len, 21077846SMatthew.Ahrens@Sun.COM uint64_t numerator, uint64_t denom, int frac_digits) 21087837SMatthew.Ahrens@Sun.COM { 21097846SMatthew.Ahrens@Sun.COM int mul = 1; 21107837SMatthew.Ahrens@Sun.COM int whole, frac, i; 21117837SMatthew.Ahrens@Sun.COM 21127837SMatthew.Ahrens@Sun.COM for (i = frac_digits; i; i--) 21137837SMatthew.Ahrens@Sun.COM mul *= 10; 21147846SMatthew.Ahrens@Sun.COM whole = numerator / denom; 21157846SMatthew.Ahrens@Sun.COM frac = mul * numerator / denom - mul * whole; 21167837SMatthew.Ahrens@Sun.COM return (mdb_snprintf(buf, len, "%u.%0*u", whole, frac_digits, frac)); 21177837SMatthew.Ahrens@Sun.COM } 21187837SMatthew.Ahrens@Sun.COM 21197837SMatthew.Ahrens@Sun.COM static void 21207837SMatthew.Ahrens@Sun.COM mdb_nicenum(uint64_t num, char *buf) 21217837SMatthew.Ahrens@Sun.COM { 21227837SMatthew.Ahrens@Sun.COM uint64_t n = num; 21237837SMatthew.Ahrens@Sun.COM int index = 0; 21247837SMatthew.Ahrens@Sun.COM char *u; 21257837SMatthew.Ahrens@Sun.COM 21267837SMatthew.Ahrens@Sun.COM while (n >= 1024) { 21277837SMatthew.Ahrens@Sun.COM n = (n + (1024 / 2)) / 1024; /* Round up or down */ 21287837SMatthew.Ahrens@Sun.COM index++; 21297837SMatthew.Ahrens@Sun.COM } 21307837SMatthew.Ahrens@Sun.COM 21317837SMatthew.Ahrens@Sun.COM u = &" \0K\0M\0G\0T\0P\0E\0"[index*2]; 21327837SMatthew.Ahrens@Sun.COM 21337837SMatthew.Ahrens@Sun.COM if (index == 0) { 21347837SMatthew.Ahrens@Sun.COM (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu", 21357837SMatthew.Ahrens@Sun.COM (u_longlong_t)n); 21367837SMatthew.Ahrens@Sun.COM } else if (n < 10 && (num & (num - 1)) != 0) { 21377846SMatthew.Ahrens@Sun.COM (void) snprintfrac(buf, NICENUM_BUFLEN, 21387846SMatthew.Ahrens@Sun.COM num, 1ULL << 10 * index, 2); 21397837SMatthew.Ahrens@Sun.COM strcat(buf, u); 21407837SMatthew.Ahrens@Sun.COM } else if (n < 100 && (num & (num - 1)) != 0) { 21417846SMatthew.Ahrens@Sun.COM (void) snprintfrac(buf, NICENUM_BUFLEN, 21427846SMatthew.Ahrens@Sun.COM num, 1ULL << 10 * index, 1); 21437837SMatthew.Ahrens@Sun.COM strcat(buf, u); 21447837SMatthew.Ahrens@Sun.COM } else { 21457837SMatthew.Ahrens@Sun.COM (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu%s", 21467837SMatthew.Ahrens@Sun.COM (u_longlong_t)n, u); 21477837SMatthew.Ahrens@Sun.COM } 21487837SMatthew.Ahrens@Sun.COM } 21497837SMatthew.Ahrens@Sun.COM 21507837SMatthew.Ahrens@Sun.COM /* 21517837SMatthew.Ahrens@Sun.COM * ::zfs_blkstats 21527837SMatthew.Ahrens@Sun.COM * 21537837SMatthew.Ahrens@Sun.COM * -v print verbose per-level information 21547837SMatthew.Ahrens@Sun.COM * 21557837SMatthew.Ahrens@Sun.COM */ 21567837SMatthew.Ahrens@Sun.COM static int 21577837SMatthew.Ahrens@Sun.COM zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 21587837SMatthew.Ahrens@Sun.COM { 21597837SMatthew.Ahrens@Sun.COM boolean_t verbose = B_FALSE; 21607837SMatthew.Ahrens@Sun.COM zfs_all_blkstats_t stats; 21617837SMatthew.Ahrens@Sun.COM dmu_object_type_t t; 21627837SMatthew.Ahrens@Sun.COM zfs_blkstat_t *tzb; 21637837SMatthew.Ahrens@Sun.COM uint64_t ditto; 21647837SMatthew.Ahrens@Sun.COM dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10]; 21657837SMatthew.Ahrens@Sun.COM /* +10 in case it grew */ 21667837SMatthew.Ahrens@Sun.COM 21677837SMatthew.Ahrens@Sun.COM if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) { 21687837SMatthew.Ahrens@Sun.COM mdb_warn("failed to read 'dmu_ot'"); 21697837SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 21707837SMatthew.Ahrens@Sun.COM } 21717837SMatthew.Ahrens@Sun.COM 21727837SMatthew.Ahrens@Sun.COM if (mdb_getopts(argc, argv, 21737837SMatthew.Ahrens@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, 21747837SMatthew.Ahrens@Sun.COM NULL) != argc) 21757837SMatthew.Ahrens@Sun.COM return (DCMD_USAGE); 21767837SMatthew.Ahrens@Sun.COM 21777837SMatthew.Ahrens@Sun.COM if (!(flags & DCMD_ADDRSPEC)) 21787837SMatthew.Ahrens@Sun.COM return (DCMD_USAGE); 21797837SMatthew.Ahrens@Sun.COM 21807837SMatthew.Ahrens@Sun.COM if (GETMEMB(addr, struct spa, spa_dsl_pool, addr) || 21817837SMatthew.Ahrens@Sun.COM GETMEMB(addr, struct dsl_pool, dp_blkstats, addr) || 21827837SMatthew.Ahrens@Sun.COM mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) { 21837837SMatthew.Ahrens@Sun.COM mdb_warn("failed to read data at %p;", addr); 21847837SMatthew.Ahrens@Sun.COM mdb_printf("maybe no stats? run \"zpool scrub\" first."); 21857837SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 21867837SMatthew.Ahrens@Sun.COM } 21877837SMatthew.Ahrens@Sun.COM 21887837SMatthew.Ahrens@Sun.COM tzb = &stats.zab_type[DN_MAX_LEVELS][DMU_OT_NUMTYPES]; 21897837SMatthew.Ahrens@Sun.COM if (tzb->zb_gangs != 0) { 21907837SMatthew.Ahrens@Sun.COM mdb_printf("Ganged blocks: %llu\n", 21917837SMatthew.Ahrens@Sun.COM (longlong_t)tzb->zb_gangs); 21927837SMatthew.Ahrens@Sun.COM } 21937837SMatthew.Ahrens@Sun.COM 21947837SMatthew.Ahrens@Sun.COM ditto = tzb->zb_ditto_2_of_2_samevdev + tzb->zb_ditto_2_of_3_samevdev + 21957837SMatthew.Ahrens@Sun.COM tzb->zb_ditto_3_of_3_samevdev; 21967837SMatthew.Ahrens@Sun.COM if (ditto != 0) { 21977837SMatthew.Ahrens@Sun.COM mdb_printf("Dittoed blocks on same vdev: %llu\n", 21987837SMatthew.Ahrens@Sun.COM (longlong_t)ditto); 21997837SMatthew.Ahrens@Sun.COM } 22007837SMatthew.Ahrens@Sun.COM 22017837SMatthew.Ahrens@Sun.COM mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 22027837SMatthew.Ahrens@Sun.COM "\t avg\t comp\t%%Total\tType\n"); 22037837SMatthew.Ahrens@Sun.COM 22047837SMatthew.Ahrens@Sun.COM for (t = 0; t <= DMU_OT_NUMTYPES; t++) { 22057837SMatthew.Ahrens@Sun.COM char csize[NICENUM_BUFLEN], lsize[NICENUM_BUFLEN]; 22067837SMatthew.Ahrens@Sun.COM char psize[NICENUM_BUFLEN], asize[NICENUM_BUFLEN]; 22077837SMatthew.Ahrens@Sun.COM char avg[NICENUM_BUFLEN]; 22087837SMatthew.Ahrens@Sun.COM char comp[NICENUM_BUFLEN], pct[NICENUM_BUFLEN]; 22097837SMatthew.Ahrens@Sun.COM char typename[64]; 22107837SMatthew.Ahrens@Sun.COM int l; 22117837SMatthew.Ahrens@Sun.COM 22127837SMatthew.Ahrens@Sun.COM 22137837SMatthew.Ahrens@Sun.COM if (t == DMU_OT_DEFERRED) 22147837SMatthew.Ahrens@Sun.COM strcpy(typename, "deferred free"); 22157837SMatthew.Ahrens@Sun.COM else if (t == DMU_OT_TOTAL) 22167837SMatthew.Ahrens@Sun.COM strcpy(typename, "Total"); 22177837SMatthew.Ahrens@Sun.COM else if (mdb_readstr(typename, sizeof (typename), 22187837SMatthew.Ahrens@Sun.COM (uintptr_t)dmu_ot[t].ot_name) == -1) { 22197837SMatthew.Ahrens@Sun.COM mdb_warn("failed to read type name"); 22207837SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 22217837SMatthew.Ahrens@Sun.COM } 22227837SMatthew.Ahrens@Sun.COM 22237837SMatthew.Ahrens@Sun.COM if (stats.zab_type[DN_MAX_LEVELS][t].zb_asize == 0) 22247837SMatthew.Ahrens@Sun.COM continue; 22257837SMatthew.Ahrens@Sun.COM 22267837SMatthew.Ahrens@Sun.COM for (l = -1; l < DN_MAX_LEVELS; l++) { 22277837SMatthew.Ahrens@Sun.COM int level = (l == -1 ? DN_MAX_LEVELS : l); 22287837SMatthew.Ahrens@Sun.COM zfs_blkstat_t *zb = &stats.zab_type[level][t]; 22297837SMatthew.Ahrens@Sun.COM 22307837SMatthew.Ahrens@Sun.COM if (zb->zb_asize == 0) 22317837SMatthew.Ahrens@Sun.COM continue; 22327837SMatthew.Ahrens@Sun.COM 22337837SMatthew.Ahrens@Sun.COM /* 22347837SMatthew.Ahrens@Sun.COM * Don't print each level unless requested. 22357837SMatthew.Ahrens@Sun.COM */ 22367837SMatthew.Ahrens@Sun.COM if (!verbose && level != DN_MAX_LEVELS) 22377837SMatthew.Ahrens@Sun.COM continue; 22387837SMatthew.Ahrens@Sun.COM 22397837SMatthew.Ahrens@Sun.COM /* 22407837SMatthew.Ahrens@Sun.COM * If all the space is level 0, don't print the 22417837SMatthew.Ahrens@Sun.COM * level 0 separately. 22427837SMatthew.Ahrens@Sun.COM */ 22437837SMatthew.Ahrens@Sun.COM if (level == 0 && zb->zb_asize == 22447837SMatthew.Ahrens@Sun.COM stats.zab_type[DN_MAX_LEVELS][t].zb_asize) 22457837SMatthew.Ahrens@Sun.COM continue; 22467837SMatthew.Ahrens@Sun.COM 22477837SMatthew.Ahrens@Sun.COM mdb_nicenum(zb->zb_count, csize); 22487837SMatthew.Ahrens@Sun.COM mdb_nicenum(zb->zb_lsize, lsize); 22497837SMatthew.Ahrens@Sun.COM mdb_nicenum(zb->zb_psize, psize); 22507837SMatthew.Ahrens@Sun.COM mdb_nicenum(zb->zb_asize, asize); 22517837SMatthew.Ahrens@Sun.COM mdb_nicenum(zb->zb_asize / zb->zb_count, avg); 22527846SMatthew.Ahrens@Sun.COM (void) snprintfrac(comp, NICENUM_BUFLEN, 22537846SMatthew.Ahrens@Sun.COM zb->zb_lsize, zb->zb_psize, 2); 22547846SMatthew.Ahrens@Sun.COM (void) snprintfrac(pct, NICENUM_BUFLEN, 22557846SMatthew.Ahrens@Sun.COM 100 * zb->zb_asize, tzb->zb_asize, 2); 22567837SMatthew.Ahrens@Sun.COM 22577837SMatthew.Ahrens@Sun.COM mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s" 22587837SMatthew.Ahrens@Sun.COM "\t%5s\t%6s\t", 22597837SMatthew.Ahrens@Sun.COM csize, lsize, psize, asize, avg, comp, pct); 22607837SMatthew.Ahrens@Sun.COM 22617837SMatthew.Ahrens@Sun.COM if (level == DN_MAX_LEVELS) 22627837SMatthew.Ahrens@Sun.COM mdb_printf("%s\n", typename); 22637837SMatthew.Ahrens@Sun.COM else 22647837SMatthew.Ahrens@Sun.COM mdb_printf(" L%d %s\n", 22657837SMatthew.Ahrens@Sun.COM level, typename); 22667837SMatthew.Ahrens@Sun.COM } 22677837SMatthew.Ahrens@Sun.COM } 22687837SMatthew.Ahrens@Sun.COM 22697837SMatthew.Ahrens@Sun.COM return (DCMD_OK); 22707837SMatthew.Ahrens@Sun.COM } 22717837SMatthew.Ahrens@Sun.COM 227210407SMatthew.Ahrens@Sun.COM /* ARGSUSED */ 227310407SMatthew.Ahrens@Sun.COM static int 227410407SMatthew.Ahrens@Sun.COM reference_cb(uintptr_t addr, const void *ignored, void *arg) 227510407SMatthew.Ahrens@Sun.COM { 227610407SMatthew.Ahrens@Sun.COM static int gotid; 227710407SMatthew.Ahrens@Sun.COM static mdb_ctf_id_t ref_id; 227810407SMatthew.Ahrens@Sun.COM uintptr_t ref_holder; 227910407SMatthew.Ahrens@Sun.COM uintptr_t ref_removed; 228010407SMatthew.Ahrens@Sun.COM uint64_t ref_number; 2281*12296SLin.Ling@Sun.COM boolean_t holder_is_str = B_FALSE; 228210407SMatthew.Ahrens@Sun.COM char holder_str[128]; 228310407SMatthew.Ahrens@Sun.COM boolean_t removed = (boolean_t)arg; 228410407SMatthew.Ahrens@Sun.COM 228510407SMatthew.Ahrens@Sun.COM if (!gotid) { 228610407SMatthew.Ahrens@Sun.COM if (mdb_ctf_lookup_by_name("struct reference", &ref_id) == -1) { 228710407SMatthew.Ahrens@Sun.COM mdb_warn("couldn't find struct reference"); 228810407SMatthew.Ahrens@Sun.COM return (WALK_ERR); 228910407SMatthew.Ahrens@Sun.COM } 229010407SMatthew.Ahrens@Sun.COM gotid = TRUE; 229110407SMatthew.Ahrens@Sun.COM } 229210407SMatthew.Ahrens@Sun.COM 229310407SMatthew.Ahrens@Sun.COM if (GETMEMBID(addr, &ref_id, ref_holder, ref_holder) || 229410407SMatthew.Ahrens@Sun.COM GETMEMBID(addr, &ref_id, ref_removed, ref_removed) || 229510407SMatthew.Ahrens@Sun.COM GETMEMBID(addr, &ref_id, ref_number, ref_number)) 229610407SMatthew.Ahrens@Sun.COM return (WALK_ERR); 229710407SMatthew.Ahrens@Sun.COM 2298*12296SLin.Ling@Sun.COM if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1) 2299*12296SLin.Ling@Sun.COM holder_is_str = strisprint(holder_str); 230010407SMatthew.Ahrens@Sun.COM 230110407SMatthew.Ahrens@Sun.COM if (removed) 230210407SMatthew.Ahrens@Sun.COM mdb_printf("removed "); 230310407SMatthew.Ahrens@Sun.COM mdb_printf("reference "); 230410407SMatthew.Ahrens@Sun.COM if (ref_number != 1) 230510407SMatthew.Ahrens@Sun.COM mdb_printf("with count=%llu ", ref_number); 230610407SMatthew.Ahrens@Sun.COM mdb_printf("with tag %p", (void*)ref_holder); 230710407SMatthew.Ahrens@Sun.COM if (holder_is_str) 230810407SMatthew.Ahrens@Sun.COM mdb_printf(" \"%s\"", holder_str); 230910407SMatthew.Ahrens@Sun.COM mdb_printf(", held at:\n"); 231010407SMatthew.Ahrens@Sun.COM 231110407SMatthew.Ahrens@Sun.COM (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 231210407SMatthew.Ahrens@Sun.COM 231310407SMatthew.Ahrens@Sun.COM if (removed) { 231410407SMatthew.Ahrens@Sun.COM mdb_printf("removed at:\n"); 231510407SMatthew.Ahrens@Sun.COM (void) mdb_call_dcmd("whatis", ref_removed, 231610407SMatthew.Ahrens@Sun.COM DCMD_ADDRSPEC, 0, NULL); 231710407SMatthew.Ahrens@Sun.COM } 231810407SMatthew.Ahrens@Sun.COM 231910407SMatthew.Ahrens@Sun.COM mdb_printf("\n"); 232010407SMatthew.Ahrens@Sun.COM 232110407SMatthew.Ahrens@Sun.COM return (WALK_NEXT); 232210407SMatthew.Ahrens@Sun.COM } 232310407SMatthew.Ahrens@Sun.COM 232410407SMatthew.Ahrens@Sun.COM /* ARGSUSED */ 232510407SMatthew.Ahrens@Sun.COM static int 232610407SMatthew.Ahrens@Sun.COM refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 232710407SMatthew.Ahrens@Sun.COM { 232810407SMatthew.Ahrens@Sun.COM uint64_t rc_count, rc_removed_count; 232910407SMatthew.Ahrens@Sun.COM uintptr_t rc_list, rc_removed; 233010407SMatthew.Ahrens@Sun.COM static int gotid; 233110407SMatthew.Ahrens@Sun.COM static mdb_ctf_id_t rc_id; 233210407SMatthew.Ahrens@Sun.COM ulong_t off; 233310407SMatthew.Ahrens@Sun.COM 233410407SMatthew.Ahrens@Sun.COM if (!(flags & DCMD_ADDRSPEC)) 233510407SMatthew.Ahrens@Sun.COM return (DCMD_USAGE); 233610407SMatthew.Ahrens@Sun.COM 233710407SMatthew.Ahrens@Sun.COM if (!gotid) { 233810407SMatthew.Ahrens@Sun.COM if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { 233910407SMatthew.Ahrens@Sun.COM mdb_warn("couldn't find struct refcount"); 234010407SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 234110407SMatthew.Ahrens@Sun.COM } 234210407SMatthew.Ahrens@Sun.COM gotid = TRUE; 234310407SMatthew.Ahrens@Sun.COM } 234410407SMatthew.Ahrens@Sun.COM 234510407SMatthew.Ahrens@Sun.COM if (GETMEMBID(addr, &rc_id, rc_count, rc_count) || 234610407SMatthew.Ahrens@Sun.COM GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) 234710407SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 234810407SMatthew.Ahrens@Sun.COM 234910407SMatthew.Ahrens@Sun.COM mdb_printf("refcount_t at %p has %llu current holds, " 235010407SMatthew.Ahrens@Sun.COM "%llu recently released holds\n", 235110407SMatthew.Ahrens@Sun.COM addr, (longlong_t)rc_count, (longlong_t)rc_removed_count); 235210407SMatthew.Ahrens@Sun.COM 235310407SMatthew.Ahrens@Sun.COM if (rc_count > 0) 235410407SMatthew.Ahrens@Sun.COM mdb_printf("current holds:\n"); 235510407SMatthew.Ahrens@Sun.COM if (mdb_ctf_offsetof(rc_id, "rc_list", &off) == -1) 235610407SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 235710407SMatthew.Ahrens@Sun.COM rc_list = addr + off/NBBY; 235810407SMatthew.Ahrens@Sun.COM mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list); 235910407SMatthew.Ahrens@Sun.COM 236010407SMatthew.Ahrens@Sun.COM if (rc_removed_count > 0) 236110407SMatthew.Ahrens@Sun.COM mdb_printf("released holds:\n"); 236210407SMatthew.Ahrens@Sun.COM if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1) 236310407SMatthew.Ahrens@Sun.COM return (DCMD_ERR); 236410407SMatthew.Ahrens@Sun.COM rc_removed = addr + off/NBBY; 236510407SMatthew.Ahrens@Sun.COM mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed); 236610407SMatthew.Ahrens@Sun.COM 236710407SMatthew.Ahrens@Sun.COM return (DCMD_OK); 236810407SMatthew.Ahrens@Sun.COM } 236910407SMatthew.Ahrens@Sun.COM 237011935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 237111935SMark.Shellenbaum@Sun.COM static int 237211935SMark.Shellenbaum@Sun.COM sa_attr_table(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 237311935SMark.Shellenbaum@Sun.COM { 237411935SMark.Shellenbaum@Sun.COM sa_attr_table_t *table; 237511935SMark.Shellenbaum@Sun.COM sa_os_t sa_os; 237611935SMark.Shellenbaum@Sun.COM char *name; 237711935SMark.Shellenbaum@Sun.COM int i; 237811935SMark.Shellenbaum@Sun.COM 237911935SMark.Shellenbaum@Sun.COM if (mdb_vread(&sa_os, sizeof (sa_os_t), addr) == -1) { 238011935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read sa_os at %p", addr); 238111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 238211935SMark.Shellenbaum@Sun.COM } 238311935SMark.Shellenbaum@Sun.COM 238411935SMark.Shellenbaum@Sun.COM table = mdb_alloc(sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 238511935SMark.Shellenbaum@Sun.COM UM_SLEEP | UM_GC); 238611935SMark.Shellenbaum@Sun.COM name = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC); 238711935SMark.Shellenbaum@Sun.COM 238811935SMark.Shellenbaum@Sun.COM if (mdb_vread(table, sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 238911935SMark.Shellenbaum@Sun.COM (uintptr_t)sa_os.sa_attr_table) == -1) { 239011935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read sa_os at %p", addr); 239111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 239211935SMark.Shellenbaum@Sun.COM } 239311935SMark.Shellenbaum@Sun.COM 239411935SMark.Shellenbaum@Sun.COM mdb_printf("%<u>%-10s %-10s %-10s %-10s %s%</u>\n", 239511935SMark.Shellenbaum@Sun.COM "ATTR ID", "REGISTERED", "LENGTH", "BSWAP", "NAME"); 239611935SMark.Shellenbaum@Sun.COM for (i = 0; i != sa_os.sa_num_attrs; i++) { 239711935SMark.Shellenbaum@Sun.COM mdb_readstr(name, MAXPATHLEN, (uintptr_t)table[i].sa_name); 239811935SMark.Shellenbaum@Sun.COM mdb_printf("%5x %8x %8x %8x %-s\n", 239911935SMark.Shellenbaum@Sun.COM (int)table[i].sa_attr, (int)table[i].sa_registered, 240011935SMark.Shellenbaum@Sun.COM (int)table[i].sa_length, table[i].sa_byteswap, name); 240111935SMark.Shellenbaum@Sun.COM } 240211935SMark.Shellenbaum@Sun.COM 240311935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 240411935SMark.Shellenbaum@Sun.COM } 240511935SMark.Shellenbaum@Sun.COM 240611935SMark.Shellenbaum@Sun.COM static int 240711935SMark.Shellenbaum@Sun.COM sa_get_off_table(uintptr_t addr, uint32_t **off_tab, int attr_count) 240811935SMark.Shellenbaum@Sun.COM { 240911935SMark.Shellenbaum@Sun.COM uintptr_t idx_table; 241011935SMark.Shellenbaum@Sun.COM 241111935SMark.Shellenbaum@Sun.COM if (GETMEMB(addr, struct sa_idx_tab, sa_idx_tab, idx_table)) { 241211935SMark.Shellenbaum@Sun.COM mdb_printf("can't find offset table in sa_idx_tab\n"); 241311935SMark.Shellenbaum@Sun.COM return (-1); 241411935SMark.Shellenbaum@Sun.COM } 241511935SMark.Shellenbaum@Sun.COM 241611935SMark.Shellenbaum@Sun.COM *off_tab = mdb_alloc(attr_count * sizeof (uint32_t), 241711935SMark.Shellenbaum@Sun.COM UM_SLEEP | UM_GC); 241811935SMark.Shellenbaum@Sun.COM 241911935SMark.Shellenbaum@Sun.COM if (mdb_vread(*off_tab, 242011935SMark.Shellenbaum@Sun.COM attr_count * sizeof (uint32_t), idx_table) == -1) { 242111935SMark.Shellenbaum@Sun.COM mdb_warn("failed to attribute offset table %p", idx_table); 242211935SMark.Shellenbaum@Sun.COM return (-1); 242311935SMark.Shellenbaum@Sun.COM } 242411935SMark.Shellenbaum@Sun.COM 242511935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 242611935SMark.Shellenbaum@Sun.COM } 242711935SMark.Shellenbaum@Sun.COM 242811935SMark.Shellenbaum@Sun.COM /*ARGSUSED*/ 242911935SMark.Shellenbaum@Sun.COM static int 243011935SMark.Shellenbaum@Sun.COM sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 243111935SMark.Shellenbaum@Sun.COM { 243211935SMark.Shellenbaum@Sun.COM uint32_t *offset_tab; 243311935SMark.Shellenbaum@Sun.COM int attr_count; 243411935SMark.Shellenbaum@Sun.COM uint64_t attr_id; 243511935SMark.Shellenbaum@Sun.COM uintptr_t attr_addr; 243611935SMark.Shellenbaum@Sun.COM uintptr_t bonus_tab, spill_tab; 243711935SMark.Shellenbaum@Sun.COM uintptr_t db_bonus, db_spill; 243811935SMark.Shellenbaum@Sun.COM uintptr_t os, os_sa; 243911935SMark.Shellenbaum@Sun.COM uintptr_t db_data; 244011935SMark.Shellenbaum@Sun.COM 244111935SMark.Shellenbaum@Sun.COM if (argc != 1) 244211935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 244311935SMark.Shellenbaum@Sun.COM 244411935SMark.Shellenbaum@Sun.COM if (argv[0].a_type == MDB_TYPE_STRING) 244511935SMark.Shellenbaum@Sun.COM attr_id = mdb_strtoull(argv[0].a_un.a_str); 244611935SMark.Shellenbaum@Sun.COM else 244711935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 244811935SMark.Shellenbaum@Sun.COM 244911935SMark.Shellenbaum@Sun.COM if (GETMEMB(addr, struct sa_handle, sa_bonus_tab, bonus_tab) || 245011935SMark.Shellenbaum@Sun.COM GETMEMB(addr, struct sa_handle, sa_spill_tab, spill_tab) || 245111935SMark.Shellenbaum@Sun.COM GETMEMB(addr, struct sa_handle, sa_os, os) || 245211935SMark.Shellenbaum@Sun.COM GETMEMB(addr, struct sa_handle, sa_bonus, db_bonus) || 245311935SMark.Shellenbaum@Sun.COM GETMEMB(addr, struct sa_handle, sa_spill, db_spill)) { 245411935SMark.Shellenbaum@Sun.COM mdb_printf("Can't find necessary information in sa_handle " 245511935SMark.Shellenbaum@Sun.COM "in sa_handle\n"); 245611935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 245711935SMark.Shellenbaum@Sun.COM } 245811935SMark.Shellenbaum@Sun.COM 245911935SMark.Shellenbaum@Sun.COM if (GETMEMB(os, struct objset, os_sa, os_sa)) { 246011935SMark.Shellenbaum@Sun.COM mdb_printf("Can't find os_sa in objset\n"); 246111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 246211935SMark.Shellenbaum@Sun.COM } 246311935SMark.Shellenbaum@Sun.COM 246411935SMark.Shellenbaum@Sun.COM if (GETMEMB(os_sa, struct sa_os, sa_num_attrs, attr_count)) { 246511935SMark.Shellenbaum@Sun.COM mdb_printf("Can't find sa_num_attrs\n"); 246611935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 246711935SMark.Shellenbaum@Sun.COM } 246811935SMark.Shellenbaum@Sun.COM 246911935SMark.Shellenbaum@Sun.COM if (attr_id > attr_count) { 247011935SMark.Shellenbaum@Sun.COM mdb_printf("attribute id number is out of range\n"); 247111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 247211935SMark.Shellenbaum@Sun.COM } 247311935SMark.Shellenbaum@Sun.COM 247411935SMark.Shellenbaum@Sun.COM if (bonus_tab) { 247511935SMark.Shellenbaum@Sun.COM if (sa_get_off_table(bonus_tab, &offset_tab, 247611935SMark.Shellenbaum@Sun.COM attr_count) == -1) { 247711935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 247811935SMark.Shellenbaum@Sun.COM } 247911935SMark.Shellenbaum@Sun.COM 248011935SMark.Shellenbaum@Sun.COM if (GETMEMB(db_bonus, struct dmu_buf, db_data, db_data)) { 248111935SMark.Shellenbaum@Sun.COM mdb_printf("can't find db_data in bonus dbuf\n"); 248211935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 248311935SMark.Shellenbaum@Sun.COM } 248411935SMark.Shellenbaum@Sun.COM } 248511935SMark.Shellenbaum@Sun.COM 248611935SMark.Shellenbaum@Sun.COM if (bonus_tab && !TOC_ATTR_PRESENT(offset_tab[attr_id]) && 248711935SMark.Shellenbaum@Sun.COM spill_tab == NULL) { 248811935SMark.Shellenbaum@Sun.COM mdb_printf("Attribute does not exist\n"); 248911935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 249011935SMark.Shellenbaum@Sun.COM } else if (!TOC_ATTR_PRESENT(offset_tab[attr_id]) && spill_tab) { 249111935SMark.Shellenbaum@Sun.COM if (sa_get_off_table(spill_tab, &offset_tab, 249211935SMark.Shellenbaum@Sun.COM attr_count) == -1) { 249311935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 249411935SMark.Shellenbaum@Sun.COM } 249511935SMark.Shellenbaum@Sun.COM if (GETMEMB(db_spill, struct dmu_buf, db_data, db_data)) { 249611935SMark.Shellenbaum@Sun.COM mdb_printf("can't find db_data in spill dbuf\n"); 249711935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 249811935SMark.Shellenbaum@Sun.COM } 249911935SMark.Shellenbaum@Sun.COM if (!TOC_ATTR_PRESENT(offset_tab[attr_id])) { 250011935SMark.Shellenbaum@Sun.COM mdb_printf("Attribute does not exist\n"); 250111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 250211935SMark.Shellenbaum@Sun.COM } 250311935SMark.Shellenbaum@Sun.COM } 250411935SMark.Shellenbaum@Sun.COM attr_addr = db_data + TOC_OFF(offset_tab[attr_id]); 250511935SMark.Shellenbaum@Sun.COM mdb_printf("%p\n", attr_addr); 250611935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 250711935SMark.Shellenbaum@Sun.COM } 250811935SMark.Shellenbaum@Sun.COM 250911935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 251011935SMark.Shellenbaum@Sun.COM static int 251111935SMark.Shellenbaum@Sun.COM zfs_ace_print_common(uintptr_t addr, uint_t flags, 251211935SMark.Shellenbaum@Sun.COM uint64_t id, uint32_t access_mask, uint16_t ace_flags, 251311935SMark.Shellenbaum@Sun.COM uint16_t ace_type, int verbose) 251411935SMark.Shellenbaum@Sun.COM { 251511935SMark.Shellenbaum@Sun.COM if (DCMD_HDRSPEC(flags) && !verbose) 251611935SMark.Shellenbaum@Sun.COM mdb_printf("%<u>%-?s %-8s %-8s %-8s %s%</u>\n", 251711935SMark.Shellenbaum@Sun.COM "ADDR", "FLAGS", "MASK", "TYPE", "ID"); 251811935SMark.Shellenbaum@Sun.COM 251911935SMark.Shellenbaum@Sun.COM if (!verbose) { 252011935SMark.Shellenbaum@Sun.COM mdb_printf("%0?p %-8x %-8x %-8x %-llx\n", addr, 252111935SMark.Shellenbaum@Sun.COM ace_flags, access_mask, ace_type, id); 252211935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 252311935SMark.Shellenbaum@Sun.COM } 252411935SMark.Shellenbaum@Sun.COM 252511935SMark.Shellenbaum@Sun.COM switch (ace_flags & ACE_TYPE_FLAGS) { 252611935SMark.Shellenbaum@Sun.COM case ACE_OWNER: 252711935SMark.Shellenbaum@Sun.COM mdb_printf("owner@:"); 252811935SMark.Shellenbaum@Sun.COM break; 252911935SMark.Shellenbaum@Sun.COM case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 253011935SMark.Shellenbaum@Sun.COM mdb_printf("group@:"); 253111935SMark.Shellenbaum@Sun.COM break; 253211935SMark.Shellenbaum@Sun.COM case ACE_EVERYONE: 253311935SMark.Shellenbaum@Sun.COM mdb_printf("everyone@:"); 253411935SMark.Shellenbaum@Sun.COM break; 253511935SMark.Shellenbaum@Sun.COM case ACE_IDENTIFIER_GROUP: 253611935SMark.Shellenbaum@Sun.COM mdb_printf("group:%llx:", (u_longlong_t)id); 253711935SMark.Shellenbaum@Sun.COM break; 253811935SMark.Shellenbaum@Sun.COM case 0: /* User entry */ 253911935SMark.Shellenbaum@Sun.COM mdb_printf("user:%llx:", (u_longlong_t)id); 254011935SMark.Shellenbaum@Sun.COM break; 254111935SMark.Shellenbaum@Sun.COM } 254211935SMark.Shellenbaum@Sun.COM 254311935SMark.Shellenbaum@Sun.COM /* print out permission mask */ 254411935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_READ_DATA) 254511935SMark.Shellenbaum@Sun.COM mdb_printf("r"); 254611935SMark.Shellenbaum@Sun.COM else 254711935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 254811935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_WRITE_DATA) 254911935SMark.Shellenbaum@Sun.COM mdb_printf("w"); 255011935SMark.Shellenbaum@Sun.COM else 255111935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 255211935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_EXECUTE) 255311935SMark.Shellenbaum@Sun.COM mdb_printf("x"); 255411935SMark.Shellenbaum@Sun.COM else 255511935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 255611935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_APPEND_DATA) 255711935SMark.Shellenbaum@Sun.COM mdb_printf("p"); 255811935SMark.Shellenbaum@Sun.COM else 255911935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 256011935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_DELETE) 256111935SMark.Shellenbaum@Sun.COM mdb_printf("d"); 256211935SMark.Shellenbaum@Sun.COM else 256311935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 256411935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_DELETE_CHILD) 256511935SMark.Shellenbaum@Sun.COM mdb_printf("D"); 256611935SMark.Shellenbaum@Sun.COM else 256711935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 256811935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_READ_ATTRIBUTES) 256911935SMark.Shellenbaum@Sun.COM mdb_printf("a"); 257011935SMark.Shellenbaum@Sun.COM else 257111935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 257211935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_WRITE_ATTRIBUTES) 257311935SMark.Shellenbaum@Sun.COM mdb_printf("A"); 257411935SMark.Shellenbaum@Sun.COM else 257511935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 257611935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_READ_NAMED_ATTRS) 257711935SMark.Shellenbaum@Sun.COM mdb_printf("R"); 257811935SMark.Shellenbaum@Sun.COM else 257911935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 258011935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_WRITE_NAMED_ATTRS) 258111935SMark.Shellenbaum@Sun.COM mdb_printf("W"); 258211935SMark.Shellenbaum@Sun.COM else 258311935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 258411935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_READ_ACL) 258511935SMark.Shellenbaum@Sun.COM mdb_printf("c"); 258611935SMark.Shellenbaum@Sun.COM else 258711935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 258811935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_WRITE_ACL) 258911935SMark.Shellenbaum@Sun.COM mdb_printf("C"); 259011935SMark.Shellenbaum@Sun.COM else 259111935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 259211935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_WRITE_OWNER) 259311935SMark.Shellenbaum@Sun.COM mdb_printf("o"); 259411935SMark.Shellenbaum@Sun.COM else 259511935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 259611935SMark.Shellenbaum@Sun.COM if (access_mask & ACE_SYNCHRONIZE) 259711935SMark.Shellenbaum@Sun.COM mdb_printf("s"); 259811935SMark.Shellenbaum@Sun.COM else 259911935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 260011935SMark.Shellenbaum@Sun.COM 260111935SMark.Shellenbaum@Sun.COM mdb_printf(":"); 260211935SMark.Shellenbaum@Sun.COM 260311935SMark.Shellenbaum@Sun.COM /* Print out inheritance flags */ 260411935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_FILE_INHERIT_ACE) 260511935SMark.Shellenbaum@Sun.COM mdb_printf("f"); 260611935SMark.Shellenbaum@Sun.COM else 260711935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 260811935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_DIRECTORY_INHERIT_ACE) 260911935SMark.Shellenbaum@Sun.COM mdb_printf("d"); 261011935SMark.Shellenbaum@Sun.COM else 261111935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 261211935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_INHERIT_ONLY_ACE) 261311935SMark.Shellenbaum@Sun.COM mdb_printf("i"); 261411935SMark.Shellenbaum@Sun.COM else 261511935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 261611935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_NO_PROPAGATE_INHERIT_ACE) 261711935SMark.Shellenbaum@Sun.COM mdb_printf("n"); 261811935SMark.Shellenbaum@Sun.COM else 261911935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 262011935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 262111935SMark.Shellenbaum@Sun.COM mdb_printf("S"); 262211935SMark.Shellenbaum@Sun.COM else 262311935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 262411935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_FAILED_ACCESS_ACE_FLAG) 262511935SMark.Shellenbaum@Sun.COM mdb_printf("F"); 262611935SMark.Shellenbaum@Sun.COM else 262711935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 262811935SMark.Shellenbaum@Sun.COM if (ace_flags & ACE_INHERITED_ACE) 262911935SMark.Shellenbaum@Sun.COM mdb_printf("I"); 263011935SMark.Shellenbaum@Sun.COM else 263111935SMark.Shellenbaum@Sun.COM mdb_printf("-"); 263211935SMark.Shellenbaum@Sun.COM 263311935SMark.Shellenbaum@Sun.COM switch (ace_type) { 263411935SMark.Shellenbaum@Sun.COM case ACE_ACCESS_ALLOWED_ACE_TYPE: 263511935SMark.Shellenbaum@Sun.COM mdb_printf(":allow\n"); 263611935SMark.Shellenbaum@Sun.COM break; 263711935SMark.Shellenbaum@Sun.COM case ACE_ACCESS_DENIED_ACE_TYPE: 263811935SMark.Shellenbaum@Sun.COM mdb_printf(":deny\n"); 263911935SMark.Shellenbaum@Sun.COM break; 264011935SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_AUDIT_ACE_TYPE: 264111935SMark.Shellenbaum@Sun.COM mdb_printf(":audit\n"); 264211935SMark.Shellenbaum@Sun.COM break; 264311935SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_ALARM_ACE_TYPE: 264411935SMark.Shellenbaum@Sun.COM mdb_printf(":alarm\n"); 264511935SMark.Shellenbaum@Sun.COM break; 264611935SMark.Shellenbaum@Sun.COM default: 264711935SMark.Shellenbaum@Sun.COM mdb_printf(":?\n"); 264811935SMark.Shellenbaum@Sun.COM } 264911935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 265011935SMark.Shellenbaum@Sun.COM } 265111935SMark.Shellenbaum@Sun.COM 265211935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 265311935SMark.Shellenbaum@Sun.COM static int 265411935SMark.Shellenbaum@Sun.COM zfs_ace_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 265511935SMark.Shellenbaum@Sun.COM { 265611935SMark.Shellenbaum@Sun.COM zfs_ace_t zace; 265711935SMark.Shellenbaum@Sun.COM int verbose = FALSE; 265811935SMark.Shellenbaum@Sun.COM uint64_t id; 265911935SMark.Shellenbaum@Sun.COM 266011935SMark.Shellenbaum@Sun.COM if (!(flags & DCMD_ADDRSPEC)) 266111935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 266211935SMark.Shellenbaum@Sun.COM 266311935SMark.Shellenbaum@Sun.COM if (mdb_getopts(argc, argv, 266411935SMark.Shellenbaum@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 266511935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 266611935SMark.Shellenbaum@Sun.COM 266711935SMark.Shellenbaum@Sun.COM if (mdb_vread(&zace, sizeof (zfs_ace_t), addr) == -1) { 266811935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read zfs_ace_t"); 266911935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 267011935SMark.Shellenbaum@Sun.COM } 267111935SMark.Shellenbaum@Sun.COM 267211935SMark.Shellenbaum@Sun.COM if ((zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == 0 || 267311935SMark.Shellenbaum@Sun.COM (zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 267411935SMark.Shellenbaum@Sun.COM id = zace.z_fuid; 267511935SMark.Shellenbaum@Sun.COM else 267611935SMark.Shellenbaum@Sun.COM id = -1; 267711935SMark.Shellenbaum@Sun.COM 267811935SMark.Shellenbaum@Sun.COM return (zfs_ace_print_common(addr, flags, id, zace.z_hdr.z_access_mask, 267911935SMark.Shellenbaum@Sun.COM zace.z_hdr.z_flags, zace.z_hdr.z_type, verbose)); 268011935SMark.Shellenbaum@Sun.COM } 268111935SMark.Shellenbaum@Sun.COM 268211935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 268311935SMark.Shellenbaum@Sun.COM static int 268411935SMark.Shellenbaum@Sun.COM zfs_ace0_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 268511935SMark.Shellenbaum@Sun.COM { 268611935SMark.Shellenbaum@Sun.COM ace_t ace; 268711935SMark.Shellenbaum@Sun.COM uint64_t id; 268811935SMark.Shellenbaum@Sun.COM int verbose = FALSE; 268911935SMark.Shellenbaum@Sun.COM 269011935SMark.Shellenbaum@Sun.COM if (!(flags & DCMD_ADDRSPEC)) 269111935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 269211935SMark.Shellenbaum@Sun.COM 269311935SMark.Shellenbaum@Sun.COM if (mdb_getopts(argc, argv, 269411935SMark.Shellenbaum@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 269511935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 269611935SMark.Shellenbaum@Sun.COM 269711935SMark.Shellenbaum@Sun.COM if (mdb_vread(&ace, sizeof (ace_t), addr) == -1) { 269811935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read ace_t"); 269911935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 270011935SMark.Shellenbaum@Sun.COM } 270111935SMark.Shellenbaum@Sun.COM 270211935SMark.Shellenbaum@Sun.COM if ((ace.a_flags & ACE_TYPE_FLAGS) == 0 || 270311935SMark.Shellenbaum@Sun.COM (ace.a_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 270411935SMark.Shellenbaum@Sun.COM id = ace.a_who; 270511935SMark.Shellenbaum@Sun.COM else 270611935SMark.Shellenbaum@Sun.COM id = -1; 270711935SMark.Shellenbaum@Sun.COM 270811935SMark.Shellenbaum@Sun.COM return (zfs_ace_print_common(addr, flags, id, ace.a_access_mask, 270911935SMark.Shellenbaum@Sun.COM ace.a_flags, ace.a_type, verbose)); 271011935SMark.Shellenbaum@Sun.COM } 271111935SMark.Shellenbaum@Sun.COM 271211935SMark.Shellenbaum@Sun.COM typedef struct acl_dump_args { 271311935SMark.Shellenbaum@Sun.COM int a_argc; 271411935SMark.Shellenbaum@Sun.COM const mdb_arg_t *a_argv; 271511935SMark.Shellenbaum@Sun.COM uint16_t a_version; 271611935SMark.Shellenbaum@Sun.COM int a_flags; 271711935SMark.Shellenbaum@Sun.COM } acl_dump_args_t; 271811935SMark.Shellenbaum@Sun.COM 271911935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 272011935SMark.Shellenbaum@Sun.COM static int 272111935SMark.Shellenbaum@Sun.COM acl_aces_cb(uintptr_t addr, const void *unknown, void *arg) 272211935SMark.Shellenbaum@Sun.COM { 272311935SMark.Shellenbaum@Sun.COM acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 272411935SMark.Shellenbaum@Sun.COM 272511935SMark.Shellenbaum@Sun.COM if (acl_args->a_version == 1) { 272611935SMark.Shellenbaum@Sun.COM if (mdb_call_dcmd("zfs_ace", addr, 272711935SMark.Shellenbaum@Sun.COM DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 272811935SMark.Shellenbaum@Sun.COM acl_args->a_argv) != DCMD_OK) { 272911935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 273011935SMark.Shellenbaum@Sun.COM } 273111935SMark.Shellenbaum@Sun.COM } else { 273211935SMark.Shellenbaum@Sun.COM if (mdb_call_dcmd("zfs_ace0", addr, 273311935SMark.Shellenbaum@Sun.COM DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 273411935SMark.Shellenbaum@Sun.COM acl_args->a_argv) != DCMD_OK) { 273511935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 273611935SMark.Shellenbaum@Sun.COM } 273711935SMark.Shellenbaum@Sun.COM } 273811935SMark.Shellenbaum@Sun.COM acl_args->a_flags = DCMD_LOOP; 273911935SMark.Shellenbaum@Sun.COM return (WALK_NEXT); 274011935SMark.Shellenbaum@Sun.COM } 274111935SMark.Shellenbaum@Sun.COM 274211935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 274311935SMark.Shellenbaum@Sun.COM static int 274411935SMark.Shellenbaum@Sun.COM acl_cb(uintptr_t addr, const void *unknown, void *arg) 274511935SMark.Shellenbaum@Sun.COM { 274611935SMark.Shellenbaum@Sun.COM acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 274711935SMark.Shellenbaum@Sun.COM 274811935SMark.Shellenbaum@Sun.COM if (acl_args->a_version == 1) { 274911935SMark.Shellenbaum@Sun.COM if (mdb_pwalk("zfs_acl_node_aces", acl_aces_cb, 275011935SMark.Shellenbaum@Sun.COM arg, addr) != 0) { 275111935SMark.Shellenbaum@Sun.COM mdb_warn("can't walk ACEs"); 275211935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 275311935SMark.Shellenbaum@Sun.COM } 275411935SMark.Shellenbaum@Sun.COM } else { 275511935SMark.Shellenbaum@Sun.COM if (mdb_pwalk("zfs_acl_node_aces0", acl_aces_cb, 275611935SMark.Shellenbaum@Sun.COM arg, addr) != 0) { 275711935SMark.Shellenbaum@Sun.COM mdb_warn("can't walk ACEs"); 275811935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 275911935SMark.Shellenbaum@Sun.COM } 276011935SMark.Shellenbaum@Sun.COM } 276111935SMark.Shellenbaum@Sun.COM return (WALK_NEXT); 276211935SMark.Shellenbaum@Sun.COM } 276311935SMark.Shellenbaum@Sun.COM 276411935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 276511935SMark.Shellenbaum@Sun.COM static int 276611935SMark.Shellenbaum@Sun.COM zfs_acl_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 276711935SMark.Shellenbaum@Sun.COM { 276811935SMark.Shellenbaum@Sun.COM zfs_acl_t zacl; 276911935SMark.Shellenbaum@Sun.COM int verbose = FALSE; 277011935SMark.Shellenbaum@Sun.COM acl_dump_args_t acl_args; 277111935SMark.Shellenbaum@Sun.COM 277211935SMark.Shellenbaum@Sun.COM if (!(flags & DCMD_ADDRSPEC)) 277311935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 277411935SMark.Shellenbaum@Sun.COM 277511935SMark.Shellenbaum@Sun.COM if (mdb_getopts(argc, argv, 277611935SMark.Shellenbaum@Sun.COM 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 277711935SMark.Shellenbaum@Sun.COM return (DCMD_USAGE); 277811935SMark.Shellenbaum@Sun.COM 277911935SMark.Shellenbaum@Sun.COM if (mdb_vread(&zacl, sizeof (zfs_acl_t), addr) == -1) { 278011935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read zfs_acl_t"); 278111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 278211935SMark.Shellenbaum@Sun.COM } 278311935SMark.Shellenbaum@Sun.COM 278411935SMark.Shellenbaum@Sun.COM acl_args.a_argc = argc; 278511935SMark.Shellenbaum@Sun.COM acl_args.a_argv = argv; 278611935SMark.Shellenbaum@Sun.COM acl_args.a_version = zacl.z_version; 278711935SMark.Shellenbaum@Sun.COM acl_args.a_flags = DCMD_LOOPFIRST; 278811935SMark.Shellenbaum@Sun.COM 278911935SMark.Shellenbaum@Sun.COM if (mdb_pwalk("zfs_acl_node", acl_cb, &acl_args, addr) != 0) { 279011935SMark.Shellenbaum@Sun.COM mdb_warn("can't walk ACL"); 279111935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 279211935SMark.Shellenbaum@Sun.COM } 279311935SMark.Shellenbaum@Sun.COM 279411935SMark.Shellenbaum@Sun.COM return (DCMD_OK); 279511935SMark.Shellenbaum@Sun.COM } 279611935SMark.Shellenbaum@Sun.COM 279711935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 279811935SMark.Shellenbaum@Sun.COM static int 279911935SMark.Shellenbaum@Sun.COM zfs_acl_node_walk_init(mdb_walk_state_t *wsp) 280011935SMark.Shellenbaum@Sun.COM { 280111935SMark.Shellenbaum@Sun.COM if (wsp->walk_addr == NULL) { 280211935SMark.Shellenbaum@Sun.COM mdb_warn("must supply address of zfs_acl_node_t\n"); 280311935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 280411935SMark.Shellenbaum@Sun.COM } 280511935SMark.Shellenbaum@Sun.COM 280611935SMark.Shellenbaum@Sun.COM wsp->walk_addr += OFFSETOF(zfs_acl_t, z_acl); 280711935SMark.Shellenbaum@Sun.COM 280811935SMark.Shellenbaum@Sun.COM if (mdb_layered_walk("list", wsp) == -1) { 280911935SMark.Shellenbaum@Sun.COM mdb_warn("failed to walk 'list'\n"); 281011935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 281111935SMark.Shellenbaum@Sun.COM } 281211935SMark.Shellenbaum@Sun.COM 281311935SMark.Shellenbaum@Sun.COM return (WALK_NEXT); 281411935SMark.Shellenbaum@Sun.COM } 281511935SMark.Shellenbaum@Sun.COM 281611935SMark.Shellenbaum@Sun.COM static int 281711935SMark.Shellenbaum@Sun.COM zfs_acl_node_walk_step(mdb_walk_state_t *wsp) 281811935SMark.Shellenbaum@Sun.COM { 281911935SMark.Shellenbaum@Sun.COM zfs_acl_node_t aclnode; 282011935SMark.Shellenbaum@Sun.COM 282111935SMark.Shellenbaum@Sun.COM if (mdb_vread(&aclnode, sizeof (zfs_acl_node_t), 282211935SMark.Shellenbaum@Sun.COM wsp->walk_addr) == -1) { 282311935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read zfs_acl_node at %p", wsp->walk_addr); 282411935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 282511935SMark.Shellenbaum@Sun.COM } 282611935SMark.Shellenbaum@Sun.COM 282711935SMark.Shellenbaum@Sun.COM return (wsp->walk_callback(wsp->walk_addr, &aclnode, wsp->walk_cbdata)); 282811935SMark.Shellenbaum@Sun.COM } 282911935SMark.Shellenbaum@Sun.COM 283011935SMark.Shellenbaum@Sun.COM typedef struct ace_walk_data { 283111935SMark.Shellenbaum@Sun.COM int ace_count; 283211935SMark.Shellenbaum@Sun.COM int ace_version; 283311935SMark.Shellenbaum@Sun.COM } ace_walk_data_t; 283411935SMark.Shellenbaum@Sun.COM 283511935SMark.Shellenbaum@Sun.COM static int 283611935SMark.Shellenbaum@Sun.COM zfs_aces_walk_init_common(mdb_walk_state_t *wsp, int version, 283711935SMark.Shellenbaum@Sun.COM int ace_count, uintptr_t ace_data) 283811935SMark.Shellenbaum@Sun.COM { 283911935SMark.Shellenbaum@Sun.COM ace_walk_data_t *ace_walk_data; 284011935SMark.Shellenbaum@Sun.COM 284111935SMark.Shellenbaum@Sun.COM if (wsp->walk_addr == NULL) { 284211935SMark.Shellenbaum@Sun.COM mdb_warn("must supply address of zfs_acl_node_t\n"); 284311935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 284411935SMark.Shellenbaum@Sun.COM } 284511935SMark.Shellenbaum@Sun.COM 284611935SMark.Shellenbaum@Sun.COM ace_walk_data = mdb_alloc(sizeof (ace_walk_data_t), UM_SLEEP | UM_GC); 284711935SMark.Shellenbaum@Sun.COM 284811935SMark.Shellenbaum@Sun.COM ace_walk_data->ace_count = ace_count; 284911935SMark.Shellenbaum@Sun.COM ace_walk_data->ace_version = version; 285011935SMark.Shellenbaum@Sun.COM 285111935SMark.Shellenbaum@Sun.COM wsp->walk_addr = ace_data; 285211935SMark.Shellenbaum@Sun.COM wsp->walk_data = ace_walk_data; 285311935SMark.Shellenbaum@Sun.COM 285411935SMark.Shellenbaum@Sun.COM return (WALK_NEXT); 285511935SMark.Shellenbaum@Sun.COM } 285611935SMark.Shellenbaum@Sun.COM 285711935SMark.Shellenbaum@Sun.COM static int 285811935SMark.Shellenbaum@Sun.COM zfs_acl_node_aces_walk_init_common(mdb_walk_state_t *wsp, int version) 285911935SMark.Shellenbaum@Sun.COM { 286011935SMark.Shellenbaum@Sun.COM static int gotid; 286111935SMark.Shellenbaum@Sun.COM static mdb_ctf_id_t acl_id; 286211935SMark.Shellenbaum@Sun.COM int z_ace_count; 286311935SMark.Shellenbaum@Sun.COM uintptr_t z_acldata; 286411935SMark.Shellenbaum@Sun.COM 286511935SMark.Shellenbaum@Sun.COM if (!gotid) { 286611935SMark.Shellenbaum@Sun.COM if (mdb_ctf_lookup_by_name("struct zfs_acl_node", 286711935SMark.Shellenbaum@Sun.COM &acl_id) == -1) { 286811935SMark.Shellenbaum@Sun.COM mdb_warn("couldn't find struct zfs_acl_node"); 286911935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 287011935SMark.Shellenbaum@Sun.COM } 287111935SMark.Shellenbaum@Sun.COM gotid = TRUE; 287211935SMark.Shellenbaum@Sun.COM } 287311935SMark.Shellenbaum@Sun.COM 287411935SMark.Shellenbaum@Sun.COM if (GETMEMBID(wsp->walk_addr, &acl_id, z_ace_count, z_ace_count)) { 287511935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 287611935SMark.Shellenbaum@Sun.COM } 287711935SMark.Shellenbaum@Sun.COM if (GETMEMBID(wsp->walk_addr, &acl_id, z_acldata, z_acldata)) { 287811935SMark.Shellenbaum@Sun.COM return (DCMD_ERR); 287911935SMark.Shellenbaum@Sun.COM } 288011935SMark.Shellenbaum@Sun.COM 288111935SMark.Shellenbaum@Sun.COM return (zfs_aces_walk_init_common(wsp, version, 288211935SMark.Shellenbaum@Sun.COM z_ace_count, z_acldata)); 288311935SMark.Shellenbaum@Sun.COM } 288411935SMark.Shellenbaum@Sun.COM 288511935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 288611935SMark.Shellenbaum@Sun.COM static int 288711935SMark.Shellenbaum@Sun.COM zfs_acl_node_aces_walk_init(mdb_walk_state_t *wsp) 288811935SMark.Shellenbaum@Sun.COM { 288911935SMark.Shellenbaum@Sun.COM return (zfs_acl_node_aces_walk_init_common(wsp, 1)); 289011935SMark.Shellenbaum@Sun.COM } 289111935SMark.Shellenbaum@Sun.COM 289211935SMark.Shellenbaum@Sun.COM /* ARGSUSED */ 289311935SMark.Shellenbaum@Sun.COM static int 289411935SMark.Shellenbaum@Sun.COM zfs_acl_node_aces0_walk_init(mdb_walk_state_t *wsp) 289511935SMark.Shellenbaum@Sun.COM { 289611935SMark.Shellenbaum@Sun.COM return (zfs_acl_node_aces_walk_init_common(wsp, 0)); 289711935SMark.Shellenbaum@Sun.COM } 289811935SMark.Shellenbaum@Sun.COM 289911935SMark.Shellenbaum@Sun.COM static int 290011935SMark.Shellenbaum@Sun.COM zfs_aces_walk_step(mdb_walk_state_t *wsp) 290111935SMark.Shellenbaum@Sun.COM { 290211935SMark.Shellenbaum@Sun.COM ace_walk_data_t *ace_data = wsp->walk_data; 290311935SMark.Shellenbaum@Sun.COM zfs_ace_t zace; 290411935SMark.Shellenbaum@Sun.COM ace_t *acep; 290511935SMark.Shellenbaum@Sun.COM int status; 290611935SMark.Shellenbaum@Sun.COM int entry_type; 290711935SMark.Shellenbaum@Sun.COM int allow_type; 290811935SMark.Shellenbaum@Sun.COM uintptr_t ptr; 290911935SMark.Shellenbaum@Sun.COM 291011935SMark.Shellenbaum@Sun.COM if (ace_data->ace_count == 0) 291111935SMark.Shellenbaum@Sun.COM return (WALK_DONE); 291211935SMark.Shellenbaum@Sun.COM 291311935SMark.Shellenbaum@Sun.COM if (mdb_vread(&zace, sizeof (zfs_ace_t), wsp->walk_addr) == -1) { 291411935SMark.Shellenbaum@Sun.COM mdb_warn("failed to read zfs_ace_t at %#lx", 291511935SMark.Shellenbaum@Sun.COM wsp->walk_addr); 291611935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 291711935SMark.Shellenbaum@Sun.COM } 291811935SMark.Shellenbaum@Sun.COM 291911935SMark.Shellenbaum@Sun.COM switch (ace_data->ace_version) { 292011935SMark.Shellenbaum@Sun.COM case 0: 292111935SMark.Shellenbaum@Sun.COM acep = (ace_t *)&zace; 292211935SMark.Shellenbaum@Sun.COM entry_type = acep->a_flags & ACE_TYPE_FLAGS; 292311935SMark.Shellenbaum@Sun.COM allow_type = acep->a_type; 292411935SMark.Shellenbaum@Sun.COM break; 292511935SMark.Shellenbaum@Sun.COM case 1: 292611935SMark.Shellenbaum@Sun.COM entry_type = zace.z_hdr.z_flags & ACE_TYPE_FLAGS; 292711935SMark.Shellenbaum@Sun.COM allow_type = zace.z_hdr.z_type; 292811935SMark.Shellenbaum@Sun.COM break; 292911935SMark.Shellenbaum@Sun.COM default: 293011935SMark.Shellenbaum@Sun.COM return (WALK_ERR); 293111935SMark.Shellenbaum@Sun.COM } 293211935SMark.Shellenbaum@Sun.COM 293311935SMark.Shellenbaum@Sun.COM ptr = (uintptr_t)wsp->walk_addr; 293411935SMark.Shellenbaum@Sun.COM switch (entry_type) { 293511935SMark.Shellenbaum@Sun.COM case ACE_OWNER: 293611935SMark.Shellenbaum@Sun.COM case ACE_EVERYONE: 293711935SMark.Shellenbaum@Sun.COM case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 293811935SMark.Shellenbaum@Sun.COM ptr += ace_data->ace_version == 0 ? 293911935SMark.Shellenbaum@Sun.COM sizeof (ace_t) : sizeof (zfs_ace_hdr_t); 294011935SMark.Shellenbaum@Sun.COM break; 294111935SMark.Shellenbaum@Sun.COM case ACE_IDENTIFIER_GROUP: 294211935SMark.Shellenbaum@Sun.COM default: 294311935SMark.Shellenbaum@Sun.COM switch (allow_type) { 294411935SMark.Shellenbaum@Sun.COM case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 294511935SMark.Shellenbaum@Sun.COM case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 294611935SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 294711935SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 294811935SMark.Shellenbaum@Sun.COM ptr += ace_data->ace_version == 0 ? 294911935SMark.Shellenbaum@Sun.COM sizeof (ace_t) : sizeof (zfs_object_ace_t); 295011935SMark.Shellenbaum@Sun.COM break; 295111935SMark.Shellenbaum@Sun.COM default: 295211935SMark.Shellenbaum@Sun.COM ptr += ace_data->ace_version == 0 ? 295311935SMark.Shellenbaum@Sun.COM sizeof (ace_t) : sizeof (zfs_ace_t); 295411935SMark.Shellenbaum@Sun.COM break; 295511935SMark.Shellenbaum@Sun.COM } 295611935SMark.Shellenbaum@Sun.COM } 295711935SMark.Shellenbaum@Sun.COM 295811935SMark.Shellenbaum@Sun.COM ace_data->ace_count--; 295911935SMark.Shellenbaum@Sun.COM status = wsp->walk_callback(wsp->walk_addr, 296011935SMark.Shellenbaum@Sun.COM (void *)(uintptr_t)&zace, wsp->walk_cbdata); 296111935SMark.Shellenbaum@Sun.COM 296211935SMark.Shellenbaum@Sun.COM wsp->walk_addr = ptr; 296311935SMark.Shellenbaum@Sun.COM return (status); 296411935SMark.Shellenbaum@Sun.COM } 296511935SMark.Shellenbaum@Sun.COM 29664055Seschrock /* 2967789Sahrens * MDB module linkage information: 2968789Sahrens * 2969789Sahrens * We declare a list of structures describing our dcmds, and a function 2970789Sahrens * named _mdb_init to return a pointer to our module information. 2971789Sahrens */ 2972789Sahrens 2973789Sahrens static const mdb_dcmd_t dcmds[] = { 29744787Sahrens { "arc", "[-bkmg]", "print ARC variables", arc_print }, 2975789Sahrens { "blkptr", ":", "print blkptr_t", blkptr }, 2976789Sahrens { "dbuf", ":", "print dmu_buf_impl_t", dbuf }, 2977789Sahrens { "dbuf_stats", ":", "dbuf stats", dbuf_stats }, 2978789Sahrens { "dbufs", 297911954SMark.Shellenbaum@Sun.COM "\t[-O objset_t*] [-n objset_name | \"mos\"] " 29808632SBill.Moore@Sun.COM "[-o object | \"mdn\"] \n" 29818632SBill.Moore@Sun.COM "\t[-l level] [-b blkid | \"bonus\"]", 29828632SBill.Moore@Sun.COM "find dmu_buf_impl_t's that match specified criteria", dbufs }, 2983789Sahrens { "abuf_find", "dva_word[0] dva_word[1]", 29848632SBill.Moore@Sun.COM "find arc_buf_hdr_t of a specified DVA", 29858632SBill.Moore@Sun.COM abuf_find }, 2986789Sahrens { "spa", "?[-cv]", "spa_t summary", spa_print }, 2987789Sahrens { "spa_config", ":", "print spa_t configuration", spa_print_config }, 2988789Sahrens { "spa_verify", ":", "verify spa_t consistency", spa_verify }, 2989789Sahrens { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space }, 2990789Sahrens { "spa_vdevs", ":", "given a spa_t, print vdev summary", spa_vdevs }, 29914787Sahrens { "vdev", ":[-re]\n" 29928632SBill.Moore@Sun.COM "\t-r display recursively\n" 29938632SBill.Moore@Sun.COM "\t-e print statistics", 29948632SBill.Moore@Sun.COM "vdev_t summary", vdev_print }, 29958632SBill.Moore@Sun.COM { "zio", ":[cpr]\n" 29968632SBill.Moore@Sun.COM "\t-c display children\n" 29978632SBill.Moore@Sun.COM "\t-p display parents\n" 29988632SBill.Moore@Sun.COM "\t-r display recursively", 29998632SBill.Moore@Sun.COM "zio_t summary", zio_print }, 30004055Seschrock { "zio_state", "?", "print out all zio_t structures on system or " 30014055Seschrock "for a particular pool", zio_state }, 30027837SMatthew.Ahrens@Sun.COM { "zfs_blkstats", ":[-v]", 30037837SMatthew.Ahrens@Sun.COM "given a spa_t, print block type stats from last scrub", 30047837SMatthew.Ahrens@Sun.COM zfs_blkstats }, 30053059Sahrens { "zfs_params", "", "print zfs tunable parameters", zfs_params }, 300610407SMatthew.Ahrens@Sun.COM { "refcount", "", "print refcount_t holders", refcount }, 300711609SMatthew.Ahrens@Sun.COM { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf }, 300811935SMark.Shellenbaum@Sun.COM { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t", 300911935SMark.Shellenbaum@Sun.COM zfs_acl_dump }, 301011935SMark.Shellenbaum@Sun.COM { "zfs_ace", ":[-v]", "print zfs_ace", zfs_ace_print }, 301111935SMark.Shellenbaum@Sun.COM { "zfs_ace0", ":[-v]", "print zfs_ace0", zfs_ace0_print }, 301211935SMark.Shellenbaum@Sun.COM { "sa_attr_table", ":", "print SA attribute table from sa_os_t", 301311935SMark.Shellenbaum@Sun.COM sa_attr_table}, 301411935SMark.Shellenbaum@Sun.COM { "sa_attr", ": attr_id", 301511935SMark.Shellenbaum@Sun.COM "print SA attribute address when given sa_handle_t", sa_attr_print}, 3016*12296SLin.Ling@Sun.COM { "zfs_dbgmsg", ":[-v]", 3017*12296SLin.Ling@Sun.COM "print zfs debug log", dbgmsg}, 3018789Sahrens { NULL } 3019789Sahrens }; 3020789Sahrens 3021789Sahrens static const mdb_walker_t walkers[] = { 3022789Sahrens /* 3023789Sahrens * In userland, there is no generic provider of list_t walkers, so we 3024789Sahrens * need to add it. 3025789Sahrens */ 3026789Sahrens #ifndef _KERNEL 3027789Sahrens { LIST_WALK_NAME, LIST_WALK_DESC, 3028789Sahrens list_walk_init, list_walk_step, list_walk_fini }, 3029789Sahrens #endif 3030789Sahrens { "zms_freelist", "walk ZFS metaslab freelist", 30312459Sahrens freelist_walk_init, freelist_walk_step, NULL }, 3032789Sahrens { "txg_list", "given any txg_list_t *, walk all entries in all txgs", 30332459Sahrens txg_list_walk_init, txg_list_walk_step, NULL }, 3034789Sahrens { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", 30352459Sahrens txg_list0_walk_init, txg_list_walk_step, NULL }, 3036789Sahrens { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", 30372459Sahrens txg_list1_walk_init, txg_list_walk_step, NULL }, 3038789Sahrens { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", 30392459Sahrens txg_list2_walk_init, txg_list_walk_step, NULL }, 3040789Sahrens { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", 30412459Sahrens txg_list3_walk_init, txg_list_walk_step, NULL }, 30424055Seschrock { "zio", "walk all zio structures, optionally for a particular spa_t", 30434055Seschrock zio_walk_init, zio_walk_step, NULL }, 30444055Seschrock { "zio_root", "walk all root zio_t structures, optionally for a " 30454055Seschrock "particular spa_t", 30464055Seschrock zio_walk_init, zio_walk_root_step, NULL }, 3047789Sahrens { "spa", "walk all spa_t entries in the namespace", 3048789Sahrens spa_walk_init, spa_walk_step, NULL }, 30492459Sahrens { "metaslab", "given a spa_t *, walk all metaslab_t structures", 30502459Sahrens metaslab_walk_init, metaslab_walk_step, NULL }, 305111935SMark.Shellenbaum@Sun.COM { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes", 305211935SMark.Shellenbaum@Sun.COM zfs_acl_node_walk_init, zfs_acl_node_walk_step, NULL }, 305311935SMark.Shellenbaum@Sun.COM { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs", 305411935SMark.Shellenbaum@Sun.COM zfs_acl_node_aces_walk_init, zfs_aces_walk_step, NULL }, 305511935SMark.Shellenbaum@Sun.COM { "zfs_acl_node_aces0", 305611935SMark.Shellenbaum@Sun.COM "given a zfs_acl_node_t, walk all ACEs as ace_t", 305711935SMark.Shellenbaum@Sun.COM zfs_acl_node_aces0_walk_init, zfs_aces_walk_step, NULL }, 3058789Sahrens { NULL } 3059789Sahrens }; 3060789Sahrens 3061789Sahrens static const mdb_modinfo_t modinfo = { 3062789Sahrens MDB_API_VERSION, dcmds, walkers 3063789Sahrens }; 3064789Sahrens 3065789Sahrens const mdb_modinfo_t * 3066789Sahrens _mdb_init(void) 3067789Sahrens { 3068789Sahrens return (&modinfo); 3069789Sahrens } 3070