1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 2255da60b9SMark J Musante * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23beb56283SShampavman * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24f78cdc34SPaul Dagnelie * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 25*29d33d42SKody A Kantor * Copyright (c) 2019 Joyent, Inc. 26fa9e4066Sahrens */ 27fa9e4066Sahrens 2855da60b9SMark J Musante /* Portions Copyright 2010 Robert Milkowski */ 2955da60b9SMark J Musante 30fa9e4066Sahrens #include <mdb/mdb_ctf.h> 31fa9e4066Sahrens #include <sys/zfs_context.h> 32fa9e4066Sahrens #include <sys/mdb_modapi.h> 33fa9e4066Sahrens #include <sys/dbuf.h> 34fa9e4066Sahrens #include <sys/dmu_objset.h> 35fa9e4066Sahrens #include <sys/dsl_dir.h> 36fa9e4066Sahrens #include <sys/dsl_pool.h> 37fa9e4066Sahrens #include <sys/metaslab_impl.h> 38fa9e4066Sahrens #include <sys/space_map.h> 39fa9e4066Sahrens #include <sys/list.h> 40fa9e4066Sahrens #include <sys/vdev_impl.h> 413f1f8012SMatthew Ahrens #include <sys/zap_leaf.h> 423f1f8012SMatthew Ahrens #include <sys/zap_impl.h> 439966ca11SMatthew Ahrens #include <ctype.h> 440a586ceaSMark Shellenbaum #include <sys/zfs_acl.h> 450a586ceaSMark Shellenbaum #include <sys/sa_impl.h> 46dcbf3bd6SGeorge Wilson #include <sys/multilist.h> 47fa9e4066Sahrens 48fa9e4066Sahrens #ifdef _KERNEL 49fa9e4066Sahrens #define ZFS_OBJ_NAME "zfs" 50c55e05cbSMatthew Ahrens extern int64_t mdb_gethrtime(void); 51fa9e4066Sahrens #else 52fa9e4066Sahrens #define ZFS_OBJ_NAME "libzpool.so.1" 53fa9e4066Sahrens #endif 54fa9e4066Sahrens 5528e4da25SMatthew Ahrens #define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`" 5628e4da25SMatthew Ahrens 57feef89cfSVictor Latushkin #ifndef _KERNEL 58feef89cfSVictor Latushkin int aok; 59feef89cfSVictor Latushkin #endif 60feef89cfSVictor Latushkin 612e4c9986SGeorge Wilson enum spa_flags { 622e4c9986SGeorge Wilson SPA_FLAG_CONFIG = 1 << 0, 632e4c9986SGeorge Wilson SPA_FLAG_VDEVS = 1 << 1, 642e4c9986SGeorge Wilson SPA_FLAG_ERRORS = 1 << 2, 652e4c9986SGeorge Wilson SPA_FLAG_METASLAB_GROUPS = 1 << 3, 662e4c9986SGeorge Wilson SPA_FLAG_METASLABS = 1 << 4, 672e4c9986SGeorge Wilson SPA_FLAG_HISTOGRAMS = 1 << 5 682e4c9986SGeorge Wilson }; 692e4c9986SGeorge Wilson 7091e2a09fSSteve Gonczi /* 7191e2a09fSSteve Gonczi * If any of these flags are set, call spa_vdevs in spa_print 7291e2a09fSSteve Gonczi */ 732e4c9986SGeorge Wilson #define SPA_FLAG_ALL_VDEV \ 742e4c9986SGeorge Wilson (SPA_FLAG_VDEVS | SPA_FLAG_ERRORS | SPA_FLAG_METASLAB_GROUPS | \ 7591e2a09fSSteve Gonczi SPA_FLAG_METASLABS) 762e4c9986SGeorge Wilson 77fa9e4066Sahrens static int 78fa9e4066Sahrens getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp, 79fa9e4066Sahrens const char *member, int len, void *buf) 80fa9e4066Sahrens { 81fa9e4066Sahrens mdb_ctf_id_t id; 82fa9e4066Sahrens ulong_t off; 83fa9e4066Sahrens char name[64]; 84fa9e4066Sahrens 85fa9e4066Sahrens if (idp == NULL) { 86fa9e4066Sahrens if (mdb_ctf_lookup_by_name(type, &id) == -1) { 87fa9e4066Sahrens mdb_warn("couldn't find type %s", type); 88fa9e4066Sahrens return (DCMD_ERR); 89fa9e4066Sahrens } 90fa9e4066Sahrens idp = &id; 91fa9e4066Sahrens } else { 92fa9e4066Sahrens type = name; 93fa9e4066Sahrens mdb_ctf_type_name(*idp, name, sizeof (name)); 94fa9e4066Sahrens } 95fa9e4066Sahrens 96fa9e4066Sahrens if (mdb_ctf_offsetof(*idp, member, &off) == -1) { 97fa9e4066Sahrens mdb_warn("couldn't find member %s of type %s\n", member, type); 98fa9e4066Sahrens return (DCMD_ERR); 99fa9e4066Sahrens } 100fa9e4066Sahrens if (off % 8 != 0) { 101fa9e4066Sahrens mdb_warn("member %s of type %s is unsupported bitfield", 102fa9e4066Sahrens member, type); 103fa9e4066Sahrens return (DCMD_ERR); 104fa9e4066Sahrens } 105fa9e4066Sahrens off /= 8; 106fa9e4066Sahrens 107fa9e4066Sahrens if (mdb_vread(buf, len, addr + off) == -1) { 108fa9e4066Sahrens mdb_warn("failed to read %s from %s at %p", 109fa9e4066Sahrens member, type, addr + off); 110fa9e4066Sahrens return (DCMD_ERR); 111fa9e4066Sahrens } 112fa9e4066Sahrens /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */ 113fa9e4066Sahrens 114fa9e4066Sahrens return (0); 115fa9e4066Sahrens } 116fa9e4066Sahrens 11728e4da25SMatthew Ahrens #define GETMEMB(addr, structname, member, dest) \ 11828e4da25SMatthew Ahrens getmember(addr, ZFS_STRUCT structname, NULL, #member, \ 11928e4da25SMatthew Ahrens sizeof (dest), &(dest)) 120fa9e4066Sahrens 121fa9e4066Sahrens #define GETMEMBID(addr, ctfid, member, dest) \ 122fa9e4066Sahrens getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) 123fa9e4066Sahrens 1243f9d6ad7SLin Ling static boolean_t 1253f9d6ad7SLin Ling strisprint(const char *cp) 1263f9d6ad7SLin Ling { 1273f9d6ad7SLin Ling for (; *cp; cp++) { 1283f9d6ad7SLin Ling if (!isprint(*cp)) 1293f9d6ad7SLin Ling return (B_FALSE); 1303f9d6ad7SLin Ling } 1313f9d6ad7SLin Ling return (B_TRUE); 1323f9d6ad7SLin Ling } 1333f9d6ad7SLin Ling 13417f11284SSerapheim Dimitropoulos /* 13517f11284SSerapheim Dimitropoulos * <addr>::sm_entries <buffer length in bytes> 13617f11284SSerapheim Dimitropoulos * 13717f11284SSerapheim Dimitropoulos * Treat the buffer specified by the given address as a buffer that contains 13817f11284SSerapheim Dimitropoulos * space map entries. Iterate over the specified number of entries and print 13917f11284SSerapheim Dimitropoulos * them in both encoded and decoded form. 14017f11284SSerapheim Dimitropoulos */ 14117f11284SSerapheim Dimitropoulos /* ARGSUSED */ 142fa9e4066Sahrens static int 14317f11284SSerapheim Dimitropoulos sm_entries(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 144fa9e4066Sahrens { 14517f11284SSerapheim Dimitropoulos uint64_t bufsz = 0; 14617f11284SSerapheim Dimitropoulos boolean_t preview = B_FALSE; 147fa9e4066Sahrens 14817f11284SSerapheim Dimitropoulos if (!(flags & DCMD_ADDRSPEC)) 14917f11284SSerapheim Dimitropoulos return (DCMD_USAGE); 150fa9e4066Sahrens 15117f11284SSerapheim Dimitropoulos if (argc < 1) { 15217f11284SSerapheim Dimitropoulos preview = B_TRUE; 15317f11284SSerapheim Dimitropoulos bufsz = 2; 15417f11284SSerapheim Dimitropoulos } else if (argc != 1) { 15517f11284SSerapheim Dimitropoulos return (DCMD_USAGE); 156fa9e4066Sahrens } else { 15717f11284SSerapheim Dimitropoulos switch (argv[0].a_type) { 15817f11284SSerapheim Dimitropoulos case MDB_TYPE_STRING: 15917f11284SSerapheim Dimitropoulos bufsz = mdb_strtoull(argv[0].a_un.a_str); 16017f11284SSerapheim Dimitropoulos break; 16117f11284SSerapheim Dimitropoulos case MDB_TYPE_IMMEDIATE: 16217f11284SSerapheim Dimitropoulos bufsz = argv[0].a_un.a_val; 16317f11284SSerapheim Dimitropoulos break; 16417f11284SSerapheim Dimitropoulos default: 16517f11284SSerapheim Dimitropoulos return (DCMD_USAGE); 166fa9e4066Sahrens } 16717f11284SSerapheim Dimitropoulos } 16817f11284SSerapheim Dimitropoulos 16917f11284SSerapheim Dimitropoulos char *actions[] = { "ALLOC", "FREE", "INVALID" }; 17017f11284SSerapheim Dimitropoulos for (uintptr_t bufend = addr + bufsz; addr < bufend; 17117f11284SSerapheim Dimitropoulos addr += sizeof (uint64_t)) { 17217f11284SSerapheim Dimitropoulos uint64_t nwords; 17317f11284SSerapheim Dimitropoulos uint64_t start_addr = addr; 17417f11284SSerapheim Dimitropoulos 17517f11284SSerapheim Dimitropoulos uint64_t word = 0; 17617f11284SSerapheim Dimitropoulos if (mdb_vread(&word, sizeof (word), addr) == -1) { 17717f11284SSerapheim Dimitropoulos mdb_warn("failed to read space map entry %p", addr); 17817f11284SSerapheim Dimitropoulos return (DCMD_ERR); 17917f11284SSerapheim Dimitropoulos } 18017f11284SSerapheim Dimitropoulos 18117f11284SSerapheim Dimitropoulos if (SM_PREFIX_DECODE(word) == SM_DEBUG_PREFIX) { 18217f11284SSerapheim Dimitropoulos (void) mdb_printf("\t [%6llu] %s: txg %llu, " 18317f11284SSerapheim Dimitropoulos "pass %llu\n", 18417f11284SSerapheim Dimitropoulos (u_longlong_t)(addr), 18517f11284SSerapheim Dimitropoulos actions[SM_DEBUG_ACTION_DECODE(word)], 18617f11284SSerapheim Dimitropoulos (u_longlong_t)SM_DEBUG_TXG_DECODE(word), 18717f11284SSerapheim Dimitropoulos (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(word)); 18817f11284SSerapheim Dimitropoulos continue; 18917f11284SSerapheim Dimitropoulos } 19017f11284SSerapheim Dimitropoulos 19117f11284SSerapheim Dimitropoulos char entry_type; 19217f11284SSerapheim Dimitropoulos uint64_t raw_offset, raw_run, vdev_id = SM_NO_VDEVID; 19317f11284SSerapheim Dimitropoulos 19417f11284SSerapheim Dimitropoulos if (SM_PREFIX_DECODE(word) != SM2_PREFIX) { 19517f11284SSerapheim Dimitropoulos entry_type = (SM_TYPE_DECODE(word) == SM_ALLOC) ? 19617f11284SSerapheim Dimitropoulos 'A' : 'F'; 19717f11284SSerapheim Dimitropoulos raw_offset = SM_OFFSET_DECODE(word); 19817f11284SSerapheim Dimitropoulos raw_run = SM_RUN_DECODE(word); 19917f11284SSerapheim Dimitropoulos nwords = 1; 20017f11284SSerapheim Dimitropoulos } else { 20117f11284SSerapheim Dimitropoulos ASSERT3U(SM_PREFIX_DECODE(word), ==, SM2_PREFIX); 20217f11284SSerapheim Dimitropoulos 20317f11284SSerapheim Dimitropoulos raw_run = SM2_RUN_DECODE(word); 20417f11284SSerapheim Dimitropoulos vdev_id = SM2_VDEV_DECODE(word); 20517f11284SSerapheim Dimitropoulos 20617f11284SSerapheim Dimitropoulos /* it is a two-word entry so we read another word */ 20717f11284SSerapheim Dimitropoulos addr += sizeof (uint64_t); 20817f11284SSerapheim Dimitropoulos if (addr >= bufend) { 20917f11284SSerapheim Dimitropoulos mdb_warn("buffer ends in the middle of a two " 21017f11284SSerapheim Dimitropoulos "word entry\n", addr); 21117f11284SSerapheim Dimitropoulos return (DCMD_ERR); 21217f11284SSerapheim Dimitropoulos } 21317f11284SSerapheim Dimitropoulos 21417f11284SSerapheim Dimitropoulos if (mdb_vread(&word, sizeof (word), addr) == -1) { 21517f11284SSerapheim Dimitropoulos mdb_warn("failed to read space map entry %p", 21617f11284SSerapheim Dimitropoulos addr); 21717f11284SSerapheim Dimitropoulos return (DCMD_ERR); 21817f11284SSerapheim Dimitropoulos } 21917f11284SSerapheim Dimitropoulos 22017f11284SSerapheim Dimitropoulos entry_type = (SM2_TYPE_DECODE(word) == SM_ALLOC) ? 22117f11284SSerapheim Dimitropoulos 'A' : 'F'; 22217f11284SSerapheim Dimitropoulos raw_offset = SM2_OFFSET_DECODE(word); 22317f11284SSerapheim Dimitropoulos nwords = 2; 22417f11284SSerapheim Dimitropoulos } 22517f11284SSerapheim Dimitropoulos 22617f11284SSerapheim Dimitropoulos (void) mdb_printf("\t [%6llx] %c range:" 22717f11284SSerapheim Dimitropoulos " %010llx-%010llx size: %06llx vdev: %06llu words: %llu\n", 22817f11284SSerapheim Dimitropoulos (u_longlong_t)start_addr, 22917f11284SSerapheim Dimitropoulos entry_type, (u_longlong_t)raw_offset, 23017f11284SSerapheim Dimitropoulos (u_longlong_t)(raw_offset + raw_run), 23117f11284SSerapheim Dimitropoulos (u_longlong_t)raw_run, 23217f11284SSerapheim Dimitropoulos (u_longlong_t)vdev_id, (u_longlong_t)nwords); 23317f11284SSerapheim Dimitropoulos 23417f11284SSerapheim Dimitropoulos if (preview) 23517f11284SSerapheim Dimitropoulos break; 23617f11284SSerapheim Dimitropoulos } 23717f11284SSerapheim Dimitropoulos return (DCMD_OK); 238fa9e4066Sahrens } 239fa9e4066Sahrens 240fa9e4066Sahrens static int 24128e4da25SMatthew Ahrens mdb_dsl_dir_name(uintptr_t addr, char *buf) 242fa9e4066Sahrens { 243fa9e4066Sahrens static int gotid; 244fa9e4066Sahrens static mdb_ctf_id_t dd_id; 245fa9e4066Sahrens uintptr_t dd_parent; 2469adfa60dSMatthew Ahrens char dd_myname[ZFS_MAX_DATASET_NAME_LEN]; 247fa9e4066Sahrens 248fa9e4066Sahrens if (!gotid) { 24928e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dir", 250fa9e4066Sahrens &dd_id) == -1) { 251fa9e4066Sahrens mdb_warn("couldn't find struct dsl_dir"); 252fa9e4066Sahrens return (DCMD_ERR); 253fa9e4066Sahrens } 254fa9e4066Sahrens gotid = TRUE; 255fa9e4066Sahrens } 256fa9e4066Sahrens if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) || 257fa9e4066Sahrens GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) { 258fa9e4066Sahrens return (DCMD_ERR); 259fa9e4066Sahrens } 260fa9e4066Sahrens 261fa9e4066Sahrens if (dd_parent) { 26228e4da25SMatthew Ahrens if (mdb_dsl_dir_name(dd_parent, buf)) 263fa9e4066Sahrens return (DCMD_ERR); 264fa9e4066Sahrens strcat(buf, "/"); 265fa9e4066Sahrens } 266fa9e4066Sahrens 267fa9e4066Sahrens if (dd_myname[0]) 268fa9e4066Sahrens strcat(buf, dd_myname); 269fa9e4066Sahrens else 270fa9e4066Sahrens strcat(buf, "???"); 271fa9e4066Sahrens 272fa9e4066Sahrens return (0); 273fa9e4066Sahrens } 274fa9e4066Sahrens 275fa9e4066Sahrens static int 276fa9e4066Sahrens objset_name(uintptr_t addr, char *buf) 277fa9e4066Sahrens { 278fa9e4066Sahrens static int gotid; 2794223fc7cSMark Shellenbaum static mdb_ctf_id_t os_id, ds_id; 280fa9e4066Sahrens uintptr_t os_dsl_dataset; 2819adfa60dSMatthew Ahrens char ds_snapname[ZFS_MAX_DATASET_NAME_LEN]; 282fa9e4066Sahrens uintptr_t ds_dir; 283fa9e4066Sahrens 284fa9e4066Sahrens buf[0] = '\0'; 285fa9e4066Sahrens 286fa9e4066Sahrens if (!gotid) { 28728e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "objset", 2884223fc7cSMark Shellenbaum &os_id) == -1) { 2894223fc7cSMark Shellenbaum mdb_warn("couldn't find struct objset"); 290fa9e4066Sahrens return (DCMD_ERR); 291fa9e4066Sahrens } 29228e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dataset", 293fa9e4066Sahrens &ds_id) == -1) { 294fa9e4066Sahrens mdb_warn("couldn't find struct dsl_dataset"); 295fa9e4066Sahrens return (DCMD_ERR); 296fa9e4066Sahrens } 297fa9e4066Sahrens 298fa9e4066Sahrens gotid = TRUE; 299fa9e4066Sahrens } 300fa9e4066Sahrens 3014223fc7cSMark Shellenbaum if (GETMEMBID(addr, &os_id, os_dsl_dataset, os_dsl_dataset)) 302fa9e4066Sahrens return (DCMD_ERR); 303fa9e4066Sahrens 304fa9e4066Sahrens if (os_dsl_dataset == 0) { 305fa9e4066Sahrens strcat(buf, "mos"); 306fa9e4066Sahrens return (0); 307fa9e4066Sahrens } 308fa9e4066Sahrens 309fa9e4066Sahrens if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) || 310fa9e4066Sahrens GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) { 311fa9e4066Sahrens return (DCMD_ERR); 312fa9e4066Sahrens } 313fa9e4066Sahrens 31428e4da25SMatthew Ahrens if (ds_dir && mdb_dsl_dir_name(ds_dir, buf)) 315fa9e4066Sahrens return (DCMD_ERR); 316fa9e4066Sahrens 317fa9e4066Sahrens if (ds_snapname[0]) { 318fa9e4066Sahrens strcat(buf, "@"); 319fa9e4066Sahrens strcat(buf, ds_snapname); 320fa9e4066Sahrens } 321fa9e4066Sahrens return (0); 322fa9e4066Sahrens } 323fa9e4066Sahrens 3248363e80aSGeorge Wilson static int 3258363e80aSGeorge Wilson enum_lookup(char *type, int val, const char *prefix, size_t size, char *out) 326fa9e4066Sahrens { 327fa9e4066Sahrens const char *cp; 328fa9e4066Sahrens size_t len = strlen(prefix); 3298363e80aSGeorge Wilson mdb_ctf_id_t enum_type; 330fa9e4066Sahrens 3318363e80aSGeorge Wilson if (mdb_ctf_lookup_by_name(type, &enum_type) != 0) { 3328363e80aSGeorge Wilson mdb_warn("Could not find enum for %s", type); 3338363e80aSGeorge Wilson return (-1); 3348363e80aSGeorge Wilson } 3358363e80aSGeorge Wilson 3368363e80aSGeorge Wilson if ((cp = mdb_ctf_enum_name(enum_type, val)) != NULL) { 337fa9e4066Sahrens if (strncmp(cp, prefix, len) == 0) 338fa9e4066Sahrens cp += len; 339fa9e4066Sahrens (void) strncpy(out, cp, size); 340fa9e4066Sahrens } else { 341fa9e4066Sahrens mdb_snprintf(out, size, "? (%d)", val); 342fa9e4066Sahrens } 3438363e80aSGeorge Wilson return (0); 344fa9e4066Sahrens } 345fa9e4066Sahrens 346fa9e4066Sahrens /* ARGSUSED */ 347fa9e4066Sahrens static int 348614409b5Sahrens zfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 349614409b5Sahrens { 350614409b5Sahrens /* 351614409b5Sahrens * This table can be approximately generated by running: 352614409b5Sahrens * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2 353614409b5Sahrens */ 354614409b5Sahrens static const char *params[] = { 35569962b56SMatthew Ahrens "arc_lotsfree_percent", 356bfcdb3d6Sloli10K "arc_pages_pp_reserve", 357bfcdb3d6Sloli10K "arc_reduce_dnlc_percent", 358bfcdb3d6Sloli10K "arc_swapfs_reserve", 359bfcdb3d6Sloli10K "arc_zio_arena_free_shift", 360bfcdb3d6Sloli10K "dbuf_cache_hiwater_pct", 361bfcdb3d6Sloli10K "dbuf_cache_lowater_pct", 362bfcdb3d6Sloli10K "dbuf_cache_max_bytes", 363bfcdb3d6Sloli10K "dbuf_cache_max_shift", 364bfcdb3d6Sloli10K "ddt_zap_indirect_blockshift", 365bfcdb3d6Sloli10K "ddt_zap_leaf_blockshift", 366bfcdb3d6Sloli10K "ditto_same_vdev_distance_shift", 367bfcdb3d6Sloli10K "dmu_find_threads", 368bfcdb3d6Sloli10K "dmu_rescan_dnode_threshold", 369bfcdb3d6Sloli10K "dsl_scan_delay_completion", 370614409b5Sahrens "fzap_default_block_shift", 371bfcdb3d6Sloli10K "l2arc_feed_again", 372bfcdb3d6Sloli10K "l2arc_feed_min_ms", 373bfcdb3d6Sloli10K "l2arc_feed_secs", 374bfcdb3d6Sloli10K "l2arc_headroom", 375bfcdb3d6Sloli10K "l2arc_headroom_boost", 376bfcdb3d6Sloli10K "l2arc_noprefetch", 377bfcdb3d6Sloli10K "l2arc_norw", 378bfcdb3d6Sloli10K "l2arc_write_boost", 379bfcdb3d6Sloli10K "l2arc_write_max", 380bfcdb3d6Sloli10K "metaslab_aliquot", 381bfcdb3d6Sloli10K "metaslab_bias_enabled", 382bfcdb3d6Sloli10K "metaslab_debug_load", 383bfcdb3d6Sloli10K "metaslab_debug_unload", 384d6e555bdSGeorge Wilson "metaslab_df_alloc_threshold", 385d6e555bdSGeorge Wilson "metaslab_df_free_pct", 386bfcdb3d6Sloli10K "metaslab_fragmentation_factor_enabled", 387bfcdb3d6Sloli10K "metaslab_force_ganging", 388bfcdb3d6Sloli10K "metaslab_lba_weighting_enabled", 389bfcdb3d6Sloli10K "metaslab_load_pct", 390bfcdb3d6Sloli10K "metaslab_min_alloc_size", 391bfcdb3d6Sloli10K "metaslab_ndf_clump_shift", 392bfcdb3d6Sloli10K "metaslab_preload_enabled", 393bfcdb3d6Sloli10K "metaslab_preload_limit", 394bfcdb3d6Sloli10K "metaslab_trace_enabled", 395bfcdb3d6Sloli10K "metaslab_trace_max_entries", 396bfcdb3d6Sloli10K "metaslab_unload_delay", 397bfcdb3d6Sloli10K "metaslabs_per_vdev", 398bfcdb3d6Sloli10K "reference_history", 399bfcdb3d6Sloli10K "reference_tracking_enable", 400bfcdb3d6Sloli10K "send_holes_without_birth_time", 401bfcdb3d6Sloli10K "spa_asize_inflation", 402bfcdb3d6Sloli10K "spa_load_verify_data", 403bfcdb3d6Sloli10K "spa_load_verify_maxinflight", 404bfcdb3d6Sloli10K "spa_load_verify_metadata", 405bfcdb3d6Sloli10K "spa_max_replication_override", 406bfcdb3d6Sloli10K "spa_min_slop", 407bfcdb3d6Sloli10K "spa_mode_global", 408bfcdb3d6Sloli10K "spa_slop_shift", 409bfcdb3d6Sloli10K "space_map_blksz", 410bfcdb3d6Sloli10K "vdev_mirror_shift", 411bfcdb3d6Sloli10K "zfetch_max_distance", 412bfcdb3d6Sloli10K "zfs_abd_chunk_size", 413bfcdb3d6Sloli10K "zfs_abd_scatter_enabled", 414bfcdb3d6Sloli10K "zfs_arc_average_blocksize", 415bfcdb3d6Sloli10K "zfs_arc_evict_batch_limit", 416bfcdb3d6Sloli10K "zfs_arc_grow_retry", 417bfcdb3d6Sloli10K "zfs_arc_max", 418bfcdb3d6Sloli10K "zfs_arc_meta_limit", 419bfcdb3d6Sloli10K "zfs_arc_meta_min", 420bfcdb3d6Sloli10K "zfs_arc_min", 421bfcdb3d6Sloli10K "zfs_arc_p_min_shift", 422bfcdb3d6Sloli10K "zfs_arc_shrink_shift", 423bfcdb3d6Sloli10K "zfs_async_block_max_blocks", 424bfcdb3d6Sloli10K "zfs_ccw_retry_interval", 425bfcdb3d6Sloli10K "zfs_commit_timeout_pct", 426bfcdb3d6Sloli10K "zfs_compressed_arc_enabled", 427bfcdb3d6Sloli10K "zfs_condense_indirect_commit_entry_delay_ticks", 428bfcdb3d6Sloli10K "zfs_condense_indirect_vdevs_enable", 429bfcdb3d6Sloli10K "zfs_condense_max_obsolete_bytes", 430bfcdb3d6Sloli10K "zfs_condense_min_mapping_bytes", 431bfcdb3d6Sloli10K "zfs_condense_pct", 432bfcdb3d6Sloli10K "zfs_dbgmsg_maxsize", 433bfcdb3d6Sloli10K "zfs_deadman_checktime_ms", 434bfcdb3d6Sloli10K "zfs_deadman_enabled", 435bfcdb3d6Sloli10K "zfs_deadman_synctime_ms", 436bfcdb3d6Sloli10K "zfs_dedup_prefetch", 437bfcdb3d6Sloli10K "zfs_default_bs", 438bfcdb3d6Sloli10K "zfs_default_ibs", 439bfcdb3d6Sloli10K "zfs_delay_max_ns", 440bfcdb3d6Sloli10K "zfs_delay_min_dirty_percent", 441bfcdb3d6Sloli10K "zfs_delay_resolution_ns", 442bfcdb3d6Sloli10K "zfs_delay_scale", 443bfcdb3d6Sloli10K "zfs_dirty_data_max", 444bfcdb3d6Sloli10K "zfs_dirty_data_max_max", 445bfcdb3d6Sloli10K "zfs_dirty_data_max_percent", 446bfcdb3d6Sloli10K "zfs_dirty_data_sync", 447bfcdb3d6Sloli10K "zfs_flags", 448bfcdb3d6Sloli10K "zfs_free_bpobj_enabled", 449bfcdb3d6Sloli10K "zfs_free_leak_on_eio", 450bfcdb3d6Sloli10K "zfs_free_min_time_ms", 451bfcdb3d6Sloli10K "zfs_fsync_sync_cnt", 452bfcdb3d6Sloli10K "zfs_immediate_write_sz", 453bfcdb3d6Sloli10K "zfs_indirect_condense_obsolete_pct", 454bfcdb3d6Sloli10K "zfs_lua_check_instrlimit_interval", 455bfcdb3d6Sloli10K "zfs_lua_max_instrlimit", 456bfcdb3d6Sloli10K "zfs_lua_max_memlimit", 457bfcdb3d6Sloli10K "zfs_max_recordsize", 458bfcdb3d6Sloli10K "zfs_mdcomp_disable", 459bfcdb3d6Sloli10K "zfs_metaslab_condense_block_threshold", 460bfcdb3d6Sloli10K "zfs_metaslab_fragmentation_threshold", 461bfcdb3d6Sloli10K "zfs_metaslab_segment_weight_enabled", 462bfcdb3d6Sloli10K "zfs_metaslab_switch_threshold", 463bfcdb3d6Sloli10K "zfs_mg_fragmentation_threshold", 464bfcdb3d6Sloli10K "zfs_mg_noalloc_threshold", 465bfcdb3d6Sloli10K "zfs_multilist_num_sublists", 466bfcdb3d6Sloli10K "zfs_no_scrub_io", 467bfcdb3d6Sloli10K "zfs_no_scrub_prefetch", 468bfcdb3d6Sloli10K "zfs_nocacheflush", 469bfcdb3d6Sloli10K "zfs_nopwrite_enabled", 470bfcdb3d6Sloli10K "zfs_object_remap_one_indirect_delay_ticks", 471bfcdb3d6Sloli10K "zfs_obsolete_min_time_ms", 472bfcdb3d6Sloli10K "zfs_pd_bytes_max", 473bfcdb3d6Sloli10K "zfs_per_txg_dirty_frees_percent", 474bfcdb3d6Sloli10K "zfs_prefetch_disable", 475bfcdb3d6Sloli10K "zfs_read_chunk_size", 476bfcdb3d6Sloli10K "zfs_recover", 477bfcdb3d6Sloli10K "zfs_recv_queue_length", 478bfcdb3d6Sloli10K "zfs_redundant_metadata_most_ditto_level", 479bfcdb3d6Sloli10K "zfs_remap_blkptr_enable", 480bfcdb3d6Sloli10K "zfs_remove_max_copy_bytes", 481bfcdb3d6Sloli10K "zfs_remove_max_segment", 482bfcdb3d6Sloli10K "zfs_resilver_delay", 483bfcdb3d6Sloli10K "zfs_resilver_min_time_ms", 484bfcdb3d6Sloli10K "zfs_scan_idle", 485bfcdb3d6Sloli10K "zfs_scan_min_time_ms", 486bfcdb3d6Sloli10K "zfs_scrub_delay", 487bfcdb3d6Sloli10K "zfs_scrub_limit", 488bfcdb3d6Sloli10K "zfs_send_corrupt_data", 489bfcdb3d6Sloli10K "zfs_send_queue_length", 490bfcdb3d6Sloli10K "zfs_send_set_freerecords_bit", 491bfcdb3d6Sloli10K "zfs_sync_pass_deferred_free", 492bfcdb3d6Sloli10K "zfs_sync_pass_dont_compress", 493bfcdb3d6Sloli10K "zfs_sync_pass_rewrite", 494bfcdb3d6Sloli10K "zfs_sync_taskq_batch_pct", 495bfcdb3d6Sloli10K "zfs_top_maxinflight", 496bfcdb3d6Sloli10K "zfs_txg_timeout", 497bfcdb3d6Sloli10K "zfs_vdev_aggregation_limit", 498bfcdb3d6Sloli10K "zfs_vdev_async_read_max_active", 499bfcdb3d6Sloli10K "zfs_vdev_async_read_min_active", 500bfcdb3d6Sloli10K "zfs_vdev_async_write_active_max_dirty_percent", 501bfcdb3d6Sloli10K "zfs_vdev_async_write_active_min_dirty_percent", 502bfcdb3d6Sloli10K "zfs_vdev_async_write_max_active", 503bfcdb3d6Sloli10K "zfs_vdev_async_write_min_active", 504bfcdb3d6Sloli10K "zfs_vdev_cache_bshift", 505bfcdb3d6Sloli10K "zfs_vdev_cache_max", 506bfcdb3d6Sloli10K "zfs_vdev_cache_size", 507bfcdb3d6Sloli10K "zfs_vdev_max_active", 508bfcdb3d6Sloli10K "zfs_vdev_queue_depth_pct", 509bfcdb3d6Sloli10K "zfs_vdev_read_gap_limit", 510bfcdb3d6Sloli10K "zfs_vdev_removal_max_active", 511bfcdb3d6Sloli10K "zfs_vdev_removal_min_active", 512bfcdb3d6Sloli10K "zfs_vdev_scrub_max_active", 513bfcdb3d6Sloli10K "zfs_vdev_scrub_min_active", 514bfcdb3d6Sloli10K "zfs_vdev_sync_read_max_active", 515bfcdb3d6Sloli10K "zfs_vdev_sync_read_min_active", 516bfcdb3d6Sloli10K "zfs_vdev_sync_write_max_active", 517bfcdb3d6Sloli10K "zfs_vdev_sync_write_min_active", 518bfcdb3d6Sloli10K "zfs_vdev_write_gap_limit", 519bfcdb3d6Sloli10K "zfs_write_implies_delete_child", 520bfcdb3d6Sloli10K "zfs_zil_clean_taskq_maxalloc", 521bfcdb3d6Sloli10K "zfs_zil_clean_taskq_minalloc", 522bfcdb3d6Sloli10K "zfs_zil_clean_taskq_nthr_pct", 523bfcdb3d6Sloli10K "zil_replay_disable", 524bfcdb3d6Sloli10K "zil_slog_bulk", 525bfcdb3d6Sloli10K "zio_buf_debug_limit", 526bfcdb3d6Sloli10K "zio_dva_throttle_enabled", 527614409b5Sahrens "zio_injection_enabled", 528614409b5Sahrens "zvol_immediate_write_sz", 529bfcdb3d6Sloli10K "zvol_maxphys", 530bfcdb3d6Sloli10K "zvol_unmap_enabled", 531bfcdb3d6Sloli10K "zvol_unmap_sync_enabled", 5325ac95da7SSerapheim Dimitropoulos "zfs_max_dataset_nesting", 533614409b5Sahrens }; 534614409b5Sahrens 535b24ab676SJeff Bonwick for (int i = 0; i < sizeof (params) / sizeof (params[0]); i++) { 536614409b5Sahrens int sz; 537614409b5Sahrens uint64_t val64; 538614409b5Sahrens uint32_t *val32p = (uint32_t *)&val64; 539614409b5Sahrens 540614409b5Sahrens sz = mdb_readvar(&val64, params[i]); 541614409b5Sahrens if (sz == 4) { 542614409b5Sahrens mdb_printf("%s = 0x%x\n", params[i], *val32p); 543614409b5Sahrens } else if (sz == 8) { 544614409b5Sahrens mdb_printf("%s = 0x%llx\n", params[i], val64); 545614409b5Sahrens } else { 546614409b5Sahrens mdb_warn("variable %s not found", params[i]); 547614409b5Sahrens } 548614409b5Sahrens } 549614409b5Sahrens 550614409b5Sahrens return (DCMD_OK); 551614409b5Sahrens } 552614409b5Sahrens 553614409b5Sahrens /* ARGSUSED */ 554614409b5Sahrens static int 5555cabbc6bSPrashanth Sreenivasa dva(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5565cabbc6bSPrashanth Sreenivasa { 5575cabbc6bSPrashanth Sreenivasa dva_t dva; 5585cabbc6bSPrashanth Sreenivasa if (mdb_vread(&dva, sizeof (dva_t), addr) == -1) { 5595cabbc6bSPrashanth Sreenivasa mdb_warn("failed to read dva_t"); 5605cabbc6bSPrashanth Sreenivasa return (DCMD_ERR); 5615cabbc6bSPrashanth Sreenivasa } 5625cabbc6bSPrashanth Sreenivasa mdb_printf("<%llu:%llx:%llx>\n", 5635cabbc6bSPrashanth Sreenivasa (u_longlong_t)DVA_GET_VDEV(&dva), 5645cabbc6bSPrashanth Sreenivasa (u_longlong_t)DVA_GET_OFFSET(&dva), 5655cabbc6bSPrashanth Sreenivasa (u_longlong_t)DVA_GET_ASIZE(&dva)); 5665cabbc6bSPrashanth Sreenivasa 5675cabbc6bSPrashanth Sreenivasa return (DCMD_OK); 5685cabbc6bSPrashanth Sreenivasa } 5695cabbc6bSPrashanth Sreenivasa 5705cabbc6bSPrashanth Sreenivasa /* ARGSUSED */ 5715cabbc6bSPrashanth Sreenivasa static int 572fa9e4066Sahrens blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 573fa9e4066Sahrens { 574b24ab676SJeff Bonwick char type[80], checksum[80], compress[80]; 575b24ab676SJeff Bonwick blkptr_t blk, *bp = &blk; 576b24ab676SJeff Bonwick char buf[BP_SPRINTF_LEN]; 577fa9e4066Sahrens 578b24ab676SJeff Bonwick if (mdb_vread(&blk, sizeof (blkptr_t), addr) == -1) { 579fa9e4066Sahrens mdb_warn("failed to read blkptr_t"); 580fa9e4066Sahrens return (DCMD_ERR); 581fa9e4066Sahrens } 582fa9e4066Sahrens 5838363e80aSGeorge Wilson if (enum_lookup("enum dmu_object_type", BP_GET_TYPE(bp), "DMU_OT_", 5848363e80aSGeorge Wilson sizeof (type), type) == -1 || 5858363e80aSGeorge Wilson enum_lookup("enum zio_checksum", BP_GET_CHECKSUM(bp), 5868363e80aSGeorge Wilson "ZIO_CHECKSUM_", sizeof (checksum), checksum) == -1 || 5878363e80aSGeorge Wilson enum_lookup("enum zio_compress", BP_GET_COMPRESS(bp), 5888363e80aSGeorge Wilson "ZIO_COMPRESS_", sizeof (compress), compress) == -1) { 589b24ab676SJeff Bonwick mdb_warn("Could not find blkptr enumerated types"); 590fa9e4066Sahrens return (DCMD_ERR); 591fa9e4066Sahrens } 592fa9e4066Sahrens 59343466aaeSMax Grossman SNPRINTF_BLKPTR(mdb_snprintf, '\n', buf, sizeof (buf), bp, type, 59443466aaeSMax Grossman checksum, compress); 595fa9e4066Sahrens 596b24ab676SJeff Bonwick mdb_printf("%s\n", buf); 597fa9e4066Sahrens 598fa9e4066Sahrens return (DCMD_OK); 599fa9e4066Sahrens } 600fa9e4066Sahrens 60128e4da25SMatthew Ahrens typedef struct mdb_dmu_buf_impl { 60228e4da25SMatthew Ahrens struct { 60328e4da25SMatthew Ahrens uint64_t db_object; 6042515f5d4SJustin T. Gibbs uintptr_t db_data; 60528e4da25SMatthew Ahrens } db; 606d5ee8a13SMatthew Ahrens uintptr_t db_objset; 60728e4da25SMatthew Ahrens uint64_t db_level; 60828e4da25SMatthew Ahrens uint64_t db_blkid; 60928e4da25SMatthew Ahrens struct { 61028e4da25SMatthew Ahrens uint64_t rc_count; 61128e4da25SMatthew Ahrens } db_holds; 61228e4da25SMatthew Ahrens } mdb_dmu_buf_impl_t; 61328e4da25SMatthew Ahrens 614fa9e4066Sahrens /* ARGSUSED */ 615fa9e4066Sahrens static int 616fa9e4066Sahrens dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 617fa9e4066Sahrens { 61828e4da25SMatthew Ahrens mdb_dmu_buf_impl_t db; 619fa9e4066Sahrens char objectname[32]; 620fa9e4066Sahrens char blkidname[32]; 6219adfa60dSMatthew Ahrens char path[ZFS_MAX_DATASET_NAME_LEN]; 622ba3132cfSJoe Stein int ptr_width = (int)(sizeof (void *)) * 2; 623fa9e4066Sahrens 62428e4da25SMatthew Ahrens if (DCMD_HDRSPEC(flags)) 625ba3132cfSJoe Stein mdb_printf("%*s %8s %3s %9s %5s %s\n", 626ba3132cfSJoe Stein ptr_width, "addr", "object", "lvl", "blkid", "holds", "os"); 627fa9e4066Sahrens 62828e4da25SMatthew Ahrens if (mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t", 62928e4da25SMatthew Ahrens addr, 0) == -1) 630fa9e4066Sahrens return (DCMD_ERR); 631fa9e4066Sahrens 63228e4da25SMatthew Ahrens if (db.db.db_object == DMU_META_DNODE_OBJECT) 633fa9e4066Sahrens (void) strcpy(objectname, "mdn"); 634fa9e4066Sahrens else 635fa9e4066Sahrens (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", 63628e4da25SMatthew Ahrens (u_longlong_t)db.db.db_object); 637fa9e4066Sahrens 63828e4da25SMatthew Ahrens if (db.db_blkid == DMU_BONUS_BLKID) 639fa9e4066Sahrens (void) strcpy(blkidname, "bonus"); 640fa9e4066Sahrens else 641fa9e4066Sahrens (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", 64228e4da25SMatthew Ahrens (u_longlong_t)db.db_blkid); 643fa9e4066Sahrens 644d5ee8a13SMatthew Ahrens if (objset_name(db.db_objset, path)) { 64528e4da25SMatthew Ahrens return (DCMD_ERR); 646fa9e4066Sahrens } 647fa9e4066Sahrens 648ba3132cfSJoe Stein mdb_printf("%*p %8s %3u %9s %5llu %s\n", ptr_width, addr, 64928e4da25SMatthew Ahrens objectname, (int)db.db_level, blkidname, 65028e4da25SMatthew Ahrens db.db_holds.rc_count, path); 651fa9e4066Sahrens 652fa9e4066Sahrens return (DCMD_OK); 653fa9e4066Sahrens } 654fa9e4066Sahrens 655fa9e4066Sahrens /* ARGSUSED */ 656fa9e4066Sahrens static int 657fa9e4066Sahrens dbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 658fa9e4066Sahrens { 659fa9e4066Sahrens #define HISTOSZ 32 660fa9e4066Sahrens uintptr_t dbp; 661fa9e4066Sahrens dmu_buf_impl_t db; 662fa9e4066Sahrens dbuf_hash_table_t ht; 663fa9e4066Sahrens uint64_t bucket, ndbufs; 664fa9e4066Sahrens uint64_t histo[HISTOSZ]; 665fa9e4066Sahrens uint64_t histo2[HISTOSZ]; 666fa9e4066Sahrens int i, maxidx; 667fa9e4066Sahrens 668fa9e4066Sahrens if (mdb_readvar(&ht, "dbuf_hash_table") == -1) { 669fa9e4066Sahrens mdb_warn("failed to read 'dbuf_hash_table'"); 670fa9e4066Sahrens return (DCMD_ERR); 671fa9e4066Sahrens } 672fa9e4066Sahrens 673fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) { 674fa9e4066Sahrens histo[i] = 0; 675fa9e4066Sahrens histo2[i] = 0; 676fa9e4066Sahrens } 677fa9e4066Sahrens 678fa9e4066Sahrens ndbufs = 0; 679fa9e4066Sahrens for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) { 680fa9e4066Sahrens int len; 681fa9e4066Sahrens 682fa9e4066Sahrens if (mdb_vread(&dbp, sizeof (void *), 683fa9e4066Sahrens (uintptr_t)(ht.hash_table+bucket)) == -1) { 684fa9e4066Sahrens mdb_warn("failed to read hash bucket %u at %p", 685fa9e4066Sahrens bucket, ht.hash_table+bucket); 686fa9e4066Sahrens return (DCMD_ERR); 687fa9e4066Sahrens } 688fa9e4066Sahrens 689fa9e4066Sahrens len = 0; 690fa9e4066Sahrens while (dbp != 0) { 691fa9e4066Sahrens if (mdb_vread(&db, sizeof (dmu_buf_impl_t), 692fa9e4066Sahrens dbp) == -1) { 693fa9e4066Sahrens mdb_warn("failed to read dbuf at %p", dbp); 694fa9e4066Sahrens return (DCMD_ERR); 695fa9e4066Sahrens } 696fa9e4066Sahrens dbp = (uintptr_t)db.db_hash_next; 697fa9e4066Sahrens for (i = MIN(len, HISTOSZ - 1); i >= 0; i--) 698fa9e4066Sahrens histo2[i]++; 699fa9e4066Sahrens len++; 700fa9e4066Sahrens ndbufs++; 701fa9e4066Sahrens } 702fa9e4066Sahrens 703fa9e4066Sahrens if (len >= HISTOSZ) 704fa9e4066Sahrens len = HISTOSZ-1; 705fa9e4066Sahrens histo[len]++; 706fa9e4066Sahrens } 707fa9e4066Sahrens 708fa9e4066Sahrens mdb_printf("hash table has %llu buckets, %llu dbufs " 709fa9e4066Sahrens "(avg %llu buckets/dbuf)\n", 710fa9e4066Sahrens ht.hash_table_mask+1, ndbufs, 711fa9e4066Sahrens (ht.hash_table_mask+1)/ndbufs); 712fa9e4066Sahrens 713fa9e4066Sahrens mdb_printf("\n"); 714fa9e4066Sahrens maxidx = 0; 715fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) 716fa9e4066Sahrens if (histo[i] > 0) 717fa9e4066Sahrens maxidx = i; 718fa9e4066Sahrens mdb_printf("hash chain length number of buckets\n"); 719fa9e4066Sahrens for (i = 0; i <= maxidx; i++) 720fa9e4066Sahrens mdb_printf("%u %llu\n", i, histo[i]); 721fa9e4066Sahrens 722fa9e4066Sahrens mdb_printf("\n"); 723fa9e4066Sahrens maxidx = 0; 724fa9e4066Sahrens for (i = 0; i < HISTOSZ; i++) 725fa9e4066Sahrens if (histo2[i] > 0) 726fa9e4066Sahrens maxidx = i; 727fa9e4066Sahrens mdb_printf("hash chain depth number of dbufs\n"); 728fa9e4066Sahrens for (i = 0; i <= maxidx; i++) 729fa9e4066Sahrens mdb_printf("%u or more %llu %llu%%\n", 730fa9e4066Sahrens i, histo2[i], histo2[i]*100/ndbufs); 731fa9e4066Sahrens 732fa9e4066Sahrens 733fa9e4066Sahrens return (DCMD_OK); 734fa9e4066Sahrens } 735fa9e4066Sahrens 7363f1f8012SMatthew Ahrens #define CHAIN_END 0xffff 7373f1f8012SMatthew Ahrens /* 7383f1f8012SMatthew Ahrens * ::zap_leaf [-v] 7393f1f8012SMatthew Ahrens * 7403f1f8012SMatthew Ahrens * Print a zap_leaf_phys_t, assumed to be 16k 7413f1f8012SMatthew Ahrens */ 7423f1f8012SMatthew Ahrens /* ARGSUSED */ 7433f1f8012SMatthew Ahrens static int 7443f1f8012SMatthew Ahrens zap_leaf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7453f1f8012SMatthew Ahrens { 7463f1f8012SMatthew Ahrens char buf[16*1024]; 7473f1f8012SMatthew Ahrens int verbose = B_FALSE; 7483f1f8012SMatthew Ahrens int four = B_FALSE; 749c1379625SJustin T. Gibbs dmu_buf_t l_dbuf; 7503f1f8012SMatthew Ahrens zap_leaf_t l; 7513f1f8012SMatthew Ahrens zap_leaf_phys_t *zlp = (void *)buf; 7523f1f8012SMatthew Ahrens int i; 7533f1f8012SMatthew Ahrens 7543f1f8012SMatthew Ahrens if (mdb_getopts(argc, argv, 7553f1f8012SMatthew Ahrens 'v', MDB_OPT_SETBITS, TRUE, &verbose, 7563f1f8012SMatthew Ahrens '4', MDB_OPT_SETBITS, TRUE, &four, 7573f1f8012SMatthew Ahrens NULL) != argc) 7583f1f8012SMatthew Ahrens return (DCMD_USAGE); 7593f1f8012SMatthew Ahrens 760c1379625SJustin T. Gibbs l_dbuf.db_data = zlp; 761c1379625SJustin T. Gibbs l.l_dbuf = &l_dbuf; 7623f1f8012SMatthew Ahrens l.l_bs = 14; /* assume 16k blocks */ 7633f1f8012SMatthew Ahrens if (four) 7643f1f8012SMatthew Ahrens l.l_bs = 12; 7653f1f8012SMatthew Ahrens 7663f1f8012SMatthew Ahrens if (!(flags & DCMD_ADDRSPEC)) { 7673f1f8012SMatthew Ahrens return (DCMD_USAGE); 7683f1f8012SMatthew Ahrens } 7693f1f8012SMatthew Ahrens 7703f1f8012SMatthew Ahrens if (mdb_vread(buf, sizeof (buf), addr) == -1) { 7713f1f8012SMatthew Ahrens mdb_warn("failed to read zap_leaf_phys_t at %p", addr); 7723f1f8012SMatthew Ahrens return (DCMD_ERR); 7733f1f8012SMatthew Ahrens } 7743f1f8012SMatthew Ahrens 7753f1f8012SMatthew Ahrens if (zlp->l_hdr.lh_block_type != ZBT_LEAF || 7763f1f8012SMatthew Ahrens zlp->l_hdr.lh_magic != ZAP_LEAF_MAGIC) { 7773f1f8012SMatthew Ahrens mdb_warn("This does not appear to be a zap_leaf_phys_t"); 7783f1f8012SMatthew Ahrens return (DCMD_ERR); 7793f1f8012SMatthew Ahrens } 7803f1f8012SMatthew Ahrens 7813f1f8012SMatthew Ahrens mdb_printf("zap_leaf_phys_t at %p:\n", addr); 7823f1f8012SMatthew Ahrens mdb_printf(" lh_prefix_len = %u\n", zlp->l_hdr.lh_prefix_len); 7833f1f8012SMatthew Ahrens mdb_printf(" lh_prefix = %llx\n", zlp->l_hdr.lh_prefix); 7843f1f8012SMatthew Ahrens mdb_printf(" lh_nentries = %u\n", zlp->l_hdr.lh_nentries); 7853f1f8012SMatthew Ahrens mdb_printf(" lh_nfree = %u\n", zlp->l_hdr.lh_nfree, 7863f1f8012SMatthew Ahrens zlp->l_hdr.lh_nfree * 100 / (ZAP_LEAF_NUMCHUNKS(&l))); 7873f1f8012SMatthew Ahrens mdb_printf(" lh_freelist = %u\n", zlp->l_hdr.lh_freelist); 7883f1f8012SMatthew Ahrens mdb_printf(" lh_flags = %x (%s)\n", zlp->l_hdr.lh_flags, 7893f1f8012SMatthew Ahrens zlp->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED ? 7903f1f8012SMatthew Ahrens "ENTRIES_CDSORTED" : ""); 7913f1f8012SMatthew Ahrens 7923f1f8012SMatthew Ahrens if (verbose) { 7933f1f8012SMatthew Ahrens mdb_printf(" hash table:\n"); 7943f1f8012SMatthew Ahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++) { 7953f1f8012SMatthew Ahrens if (zlp->l_hash[i] != CHAIN_END) 7963f1f8012SMatthew Ahrens mdb_printf(" %u: %u\n", i, zlp->l_hash[i]); 7973f1f8012SMatthew Ahrens } 7983f1f8012SMatthew Ahrens } 7993f1f8012SMatthew Ahrens 8003f1f8012SMatthew Ahrens mdb_printf(" chunks:\n"); 8013f1f8012SMatthew Ahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) { 8023f1f8012SMatthew Ahrens /* LINTED: alignment */ 8033f1f8012SMatthew Ahrens zap_leaf_chunk_t *zlc = &ZAP_LEAF_CHUNK(&l, i); 8043f1f8012SMatthew Ahrens switch (zlc->l_entry.le_type) { 8053f1f8012SMatthew Ahrens case ZAP_CHUNK_FREE: 8063f1f8012SMatthew Ahrens if (verbose) { 8073f1f8012SMatthew Ahrens mdb_printf(" %u: free; lf_next = %u\n", 8083f1f8012SMatthew Ahrens i, zlc->l_free.lf_next); 8093f1f8012SMatthew Ahrens } 8103f1f8012SMatthew Ahrens break; 8113f1f8012SMatthew Ahrens case ZAP_CHUNK_ENTRY: 8123f1f8012SMatthew Ahrens mdb_printf(" %u: entry\n", i); 8133f1f8012SMatthew Ahrens if (verbose) { 8143f1f8012SMatthew Ahrens mdb_printf(" le_next = %u\n", 8153f1f8012SMatthew Ahrens zlc->l_entry.le_next); 8163f1f8012SMatthew Ahrens } 8173f1f8012SMatthew Ahrens mdb_printf(" le_name_chunk = %u\n", 8183f1f8012SMatthew Ahrens zlc->l_entry.le_name_chunk); 8193f1f8012SMatthew Ahrens mdb_printf(" le_name_numints = %u\n", 8203f1f8012SMatthew Ahrens zlc->l_entry.le_name_numints); 8213f1f8012SMatthew Ahrens mdb_printf(" le_value_chunk = %u\n", 8223f1f8012SMatthew Ahrens zlc->l_entry.le_value_chunk); 8233f1f8012SMatthew Ahrens mdb_printf(" le_value_intlen = %u\n", 8243f1f8012SMatthew Ahrens zlc->l_entry.le_value_intlen); 8253f1f8012SMatthew Ahrens mdb_printf(" le_value_numints = %u\n", 8263f1f8012SMatthew Ahrens zlc->l_entry.le_value_numints); 8273f1f8012SMatthew Ahrens mdb_printf(" le_cd = %u\n", 8283f1f8012SMatthew Ahrens zlc->l_entry.le_cd); 8293f1f8012SMatthew Ahrens mdb_printf(" le_hash = %llx\n", 8303f1f8012SMatthew Ahrens zlc->l_entry.le_hash); 8313f1f8012SMatthew Ahrens break; 8323f1f8012SMatthew Ahrens case ZAP_CHUNK_ARRAY: 8333f9d6ad7SLin Ling mdb_printf(" %u: array", i); 8343f9d6ad7SLin Ling if (strisprint((char *)zlc->l_array.la_array)) 8353f9d6ad7SLin Ling mdb_printf(" \"%s\"", zlc->l_array.la_array); 8363f9d6ad7SLin Ling mdb_printf("\n"); 8373f1f8012SMatthew Ahrens if (verbose) { 8383f1f8012SMatthew Ahrens int j; 8393f1f8012SMatthew Ahrens mdb_printf(" "); 8403f1f8012SMatthew Ahrens for (j = 0; j < ZAP_LEAF_ARRAY_BYTES; j++) { 8413f1f8012SMatthew Ahrens mdb_printf("%02x ", 8423f1f8012SMatthew Ahrens zlc->l_array.la_array[j]); 8433f1f8012SMatthew Ahrens } 8443f1f8012SMatthew Ahrens mdb_printf("\n"); 8453f1f8012SMatthew Ahrens } 8463f1f8012SMatthew Ahrens if (zlc->l_array.la_next != CHAIN_END) { 8473f1f8012SMatthew Ahrens mdb_printf(" lf_next = %u\n", 8483f1f8012SMatthew Ahrens zlc->l_array.la_next); 8493f1f8012SMatthew Ahrens } 8503f1f8012SMatthew Ahrens break; 8513f1f8012SMatthew Ahrens default: 8523f1f8012SMatthew Ahrens mdb_printf(" %u: undefined type %u\n", 8533f1f8012SMatthew Ahrens zlc->l_entry.le_type); 8543f1f8012SMatthew Ahrens } 8553f1f8012SMatthew Ahrens } 8563f1f8012SMatthew Ahrens 8573f1f8012SMatthew Ahrens return (DCMD_OK); 8583f1f8012SMatthew Ahrens } 8593f1f8012SMatthew Ahrens 860fa9e4066Sahrens typedef struct dbufs_data { 861fa9e4066Sahrens mdb_ctf_id_t id; 862fa9e4066Sahrens uint64_t objset; 863fa9e4066Sahrens uint64_t object; 864fa9e4066Sahrens uint64_t level; 865fa9e4066Sahrens uint64_t blkid; 866fa9e4066Sahrens char *osname; 867fa9e4066Sahrens } dbufs_data_t; 868fa9e4066Sahrens 869fa9e4066Sahrens #define DBUFS_UNSET (0xbaddcafedeadbeefULL) 870fa9e4066Sahrens 871fa9e4066Sahrens /* ARGSUSED */ 872fa9e4066Sahrens static int 873fa9e4066Sahrens dbufs_cb(uintptr_t addr, const void *unknown, void *arg) 874fa9e4066Sahrens { 875fa9e4066Sahrens dbufs_data_t *data = arg; 876fa9e4066Sahrens uintptr_t objset; 877fa9e4066Sahrens dmu_buf_t db; 878fa9e4066Sahrens uint8_t level; 879fa9e4066Sahrens uint64_t blkid; 8809adfa60dSMatthew Ahrens char osname[ZFS_MAX_DATASET_NAME_LEN]; 881fa9e4066Sahrens 882fa9e4066Sahrens if (GETMEMBID(addr, &data->id, db_objset, objset) || 883fa9e4066Sahrens GETMEMBID(addr, &data->id, db, db) || 884fa9e4066Sahrens GETMEMBID(addr, &data->id, db_level, level) || 885fa9e4066Sahrens GETMEMBID(addr, &data->id, db_blkid, blkid)) { 886fa9e4066Sahrens return (WALK_ERR); 887fa9e4066Sahrens } 888fa9e4066Sahrens 889fa9e4066Sahrens if ((data->objset == DBUFS_UNSET || data->objset == objset) && 890fa9e4066Sahrens (data->osname == NULL || (objset_name(objset, osname) == 0 && 891fa9e4066Sahrens strcmp(data->osname, osname) == 0)) && 892fa9e4066Sahrens (data->object == DBUFS_UNSET || data->object == db.db_object) && 893fa9e4066Sahrens (data->level == DBUFS_UNSET || data->level == level) && 894fa9e4066Sahrens (data->blkid == DBUFS_UNSET || data->blkid == blkid)) { 895fa9e4066Sahrens mdb_printf("%#lr\n", addr); 896fa9e4066Sahrens } 897fa9e4066Sahrens return (WALK_NEXT); 898fa9e4066Sahrens } 899fa9e4066Sahrens 900fa9e4066Sahrens /* ARGSUSED */ 901fa9e4066Sahrens static int 902fa9e4066Sahrens dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 903fa9e4066Sahrens { 904fa9e4066Sahrens dbufs_data_t data; 905fa9e4066Sahrens char *object = NULL; 906fa9e4066Sahrens char *blkid = NULL; 907fa9e4066Sahrens 908fa9e4066Sahrens data.objset = data.object = data.level = data.blkid = DBUFS_UNSET; 909fa9e4066Sahrens data.osname = NULL; 910fa9e4066Sahrens 911fa9e4066Sahrens if (mdb_getopts(argc, argv, 912fa9e4066Sahrens 'O', MDB_OPT_UINT64, &data.objset, 913fa9e4066Sahrens 'n', MDB_OPT_STR, &data.osname, 914fa9e4066Sahrens 'o', MDB_OPT_STR, &object, 915fa9e4066Sahrens 'l', MDB_OPT_UINT64, &data.level, 916fa9e4066Sahrens 'b', MDB_OPT_STR, &blkid) != argc) { 917fa9e4066Sahrens return (DCMD_USAGE); 918fa9e4066Sahrens } 919fa9e4066Sahrens 920fa9e4066Sahrens if (object) { 921fa9e4066Sahrens if (strcmp(object, "mdn") == 0) { 922fa9e4066Sahrens data.object = DMU_META_DNODE_OBJECT; 923fa9e4066Sahrens } else { 924fa9e4066Sahrens data.object = mdb_strtoull(object); 925fa9e4066Sahrens } 926fa9e4066Sahrens } 927fa9e4066Sahrens 928fa9e4066Sahrens if (blkid) { 929fa9e4066Sahrens if (strcmp(blkid, "bonus") == 0) { 9300a586ceaSMark Shellenbaum data.blkid = DMU_BONUS_BLKID; 931fa9e4066Sahrens } else { 932fa9e4066Sahrens data.blkid = mdb_strtoull(blkid); 933fa9e4066Sahrens } 934fa9e4066Sahrens } 935fa9e4066Sahrens 93628e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dmu_buf_impl", &data.id) == -1) { 937fa9e4066Sahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 938fa9e4066Sahrens return (DCMD_ERR); 939fa9e4066Sahrens } 940fa9e4066Sahrens 9415f5f7a6fSahrens if (mdb_walk("dmu_buf_impl_t", dbufs_cb, &data) != 0) { 942fa9e4066Sahrens mdb_warn("can't walk dbufs"); 943fa9e4066Sahrens return (DCMD_ERR); 944fa9e4066Sahrens } 945fa9e4066Sahrens 946fa9e4066Sahrens return (DCMD_OK); 947fa9e4066Sahrens } 948fa9e4066Sahrens 949fa9e4066Sahrens typedef struct abuf_find_data { 950fa9e4066Sahrens dva_t dva; 951fa9e4066Sahrens mdb_ctf_id_t id; 952fa9e4066Sahrens } abuf_find_data_t; 953fa9e4066Sahrens 954fa9e4066Sahrens /* ARGSUSED */ 955fa9e4066Sahrens static int 956fa9e4066Sahrens abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) 957fa9e4066Sahrens { 958fa9e4066Sahrens abuf_find_data_t *data = arg; 959fa9e4066Sahrens dva_t dva; 960fa9e4066Sahrens 961fa9e4066Sahrens if (GETMEMBID(addr, &data->id, b_dva, dva)) { 962fa9e4066Sahrens return (WALK_ERR); 963fa9e4066Sahrens } 964fa9e4066Sahrens 965fa9e4066Sahrens if (dva.dva_word[0] == data->dva.dva_word[0] && 966fa9e4066Sahrens dva.dva_word[1] == data->dva.dva_word[1]) { 967fa9e4066Sahrens mdb_printf("%#lr\n", addr); 968fa9e4066Sahrens } 969fa9e4066Sahrens return (WALK_NEXT); 970fa9e4066Sahrens } 971fa9e4066Sahrens 972fa9e4066Sahrens /* ARGSUSED */ 973fa9e4066Sahrens static int 974fa9e4066Sahrens abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 975fa9e4066Sahrens { 976fa9e4066Sahrens abuf_find_data_t data; 977fa9e4066Sahrens GElf_Sym sym; 978fa9e4066Sahrens int i; 979fa9e4066Sahrens const char *syms[] = { 980a2eea2e1Sahrens "ARC_mru", 981a2eea2e1Sahrens "ARC_mru_ghost", 982a2eea2e1Sahrens "ARC_mfu", 983a2eea2e1Sahrens "ARC_mfu_ghost", 984fa9e4066Sahrens }; 985fa9e4066Sahrens 986fa9e4066Sahrens if (argc != 2) 987fa9e4066Sahrens return (DCMD_USAGE); 988fa9e4066Sahrens 989fa9e4066Sahrens for (i = 0; i < 2; i ++) { 990fa9e4066Sahrens switch (argv[i].a_type) { 991fa9e4066Sahrens case MDB_TYPE_STRING: 992fa9e4066Sahrens data.dva.dva_word[i] = mdb_strtoull(argv[i].a_un.a_str); 993fa9e4066Sahrens break; 994fa9e4066Sahrens case MDB_TYPE_IMMEDIATE: 995fa9e4066Sahrens data.dva.dva_word[i] = argv[i].a_un.a_val; 996fa9e4066Sahrens break; 997fa9e4066Sahrens default: 998fa9e4066Sahrens return (DCMD_USAGE); 999fa9e4066Sahrens } 1000fa9e4066Sahrens } 1001fa9e4066Sahrens 100228e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "arc_buf_hdr", &data.id) == -1) { 1003fa9e4066Sahrens mdb_warn("couldn't find struct arc_buf_hdr"); 1004fa9e4066Sahrens return (DCMD_ERR); 1005fa9e4066Sahrens } 1006fa9e4066Sahrens 1007fa9e4066Sahrens for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { 100822ce0148SMatthew Ahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, syms[i], &sym)) { 1009fa9e4066Sahrens mdb_warn("can't find symbol %s", syms[i]); 1010fa9e4066Sahrens return (DCMD_ERR); 1011fa9e4066Sahrens } 1012fa9e4066Sahrens 1013fa9e4066Sahrens if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { 1014fa9e4066Sahrens mdb_warn("can't walk %s", syms[i]); 1015fa9e4066Sahrens return (DCMD_ERR); 1016fa9e4066Sahrens } 1017fa9e4066Sahrens } 1018fa9e4066Sahrens 1019fa9e4066Sahrens return (DCMD_OK); 1020fa9e4066Sahrens } 1021fa9e4066Sahrens 102228e4da25SMatthew Ahrens 102328e4da25SMatthew Ahrens typedef struct dbgmsg_arg { 102428e4da25SMatthew Ahrens boolean_t da_verbose; 102528e4da25SMatthew Ahrens boolean_t da_address; 102628e4da25SMatthew Ahrens } dbgmsg_arg_t; 102728e4da25SMatthew Ahrens 102844cb6abcSbmc /* ARGSUSED */ 102944cb6abcSbmc static int 10303f9d6ad7SLin Ling dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg) 10313f9d6ad7SLin Ling { 10323f9d6ad7SLin Ling static mdb_ctf_id_t id; 10333f9d6ad7SLin Ling static boolean_t gotid; 10343f9d6ad7SLin Ling static ulong_t off; 10353f9d6ad7SLin Ling 103628e4da25SMatthew Ahrens dbgmsg_arg_t *da = arg; 10373f9d6ad7SLin Ling time_t timestamp; 10383f9d6ad7SLin Ling char buf[1024]; 10393f9d6ad7SLin Ling 10403f9d6ad7SLin Ling if (!gotid) { 104128e4da25SMatthew Ahrens if (mdb_ctf_lookup_by_name(ZFS_STRUCT "zfs_dbgmsg", &id) == 104228e4da25SMatthew Ahrens -1) { 10433f9d6ad7SLin Ling mdb_warn("couldn't find struct zfs_dbgmsg"); 10443f9d6ad7SLin Ling return (WALK_ERR); 10453f9d6ad7SLin Ling } 10463f9d6ad7SLin Ling gotid = TRUE; 10473f9d6ad7SLin Ling if (mdb_ctf_offsetof(id, "zdm_msg", &off) == -1) { 10483f9d6ad7SLin Ling mdb_warn("couldn't find zdm_msg"); 10493f9d6ad7SLin Ling return (WALK_ERR); 10503f9d6ad7SLin Ling } 10513f9d6ad7SLin Ling off /= 8; 10523f9d6ad7SLin Ling } 10533f9d6ad7SLin Ling 10543f9d6ad7SLin Ling 10553f9d6ad7SLin Ling if (GETMEMBID(addr, &id, zdm_timestamp, timestamp)) { 10563f9d6ad7SLin Ling return (WALK_ERR); 10573f9d6ad7SLin Ling } 10583f9d6ad7SLin Ling 10593f9d6ad7SLin Ling if (mdb_readstr(buf, sizeof (buf), addr + off) == -1) { 10603f9d6ad7SLin Ling mdb_warn("failed to read zdm_msg at %p\n", addr + off); 10613f9d6ad7SLin Ling return (DCMD_ERR); 10623f9d6ad7SLin Ling } 10633f9d6ad7SLin Ling 106428e4da25SMatthew Ahrens if (da->da_address) 106528e4da25SMatthew Ahrens mdb_printf("%p ", addr); 106628e4da25SMatthew Ahrens if (da->da_verbose) 10673f9d6ad7SLin Ling mdb_printf("%Y ", timestamp); 10683f9d6ad7SLin Ling 10693f9d6ad7SLin Ling mdb_printf("%s\n", buf); 10703f9d6ad7SLin Ling 107128e4da25SMatthew Ahrens if (da->da_verbose) 10723f9d6ad7SLin Ling (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 10733f9d6ad7SLin Ling 10743f9d6ad7SLin Ling return (WALK_NEXT); 10753f9d6ad7SLin Ling } 10763f9d6ad7SLin Ling 10773f9d6ad7SLin Ling /* ARGSUSED */ 10783f9d6ad7SLin Ling static int 10793f9d6ad7SLin Ling dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 10803f9d6ad7SLin Ling { 10813f9d6ad7SLin Ling GElf_Sym sym; 108228e4da25SMatthew Ahrens dbgmsg_arg_t da = { 0 }; 10833f9d6ad7SLin Ling 10843f9d6ad7SLin Ling if (mdb_getopts(argc, argv, 108528e4da25SMatthew Ahrens 'v', MDB_OPT_SETBITS, B_TRUE, &da.da_verbose, 108628e4da25SMatthew Ahrens 'a', MDB_OPT_SETBITS, B_TRUE, &da.da_address, 10873f9d6ad7SLin Ling NULL) != argc) 10883f9d6ad7SLin Ling return (DCMD_USAGE); 10893f9d6ad7SLin Ling 10903b2aab18SMatthew Ahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "zfs_dbgmsgs", &sym)) { 10913f9d6ad7SLin Ling mdb_warn("can't find zfs_dbgmsgs"); 10923f9d6ad7SLin Ling return (DCMD_ERR); 10933f9d6ad7SLin Ling } 10943f9d6ad7SLin Ling 109528e4da25SMatthew Ahrens if (mdb_pwalk("list", dbgmsg_cb, &da, sym.st_value) != 0) { 10963f9d6ad7SLin Ling mdb_warn("can't walk zfs_dbgmsgs"); 10973f9d6ad7SLin Ling return (DCMD_ERR); 10983f9d6ad7SLin Ling } 10993f9d6ad7SLin Ling 11003f9d6ad7SLin Ling return (DCMD_OK); 11013f9d6ad7SLin Ling } 11023f9d6ad7SLin Ling 11033f9d6ad7SLin Ling /*ARGSUSED*/ 11043f9d6ad7SLin Ling static int 110544cb6abcSbmc arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 110644cb6abcSbmc { 110744cb6abcSbmc kstat_named_t *stats; 110844cb6abcSbmc GElf_Sym sym; 110991ebeef5Sahrens int nstats, i; 111044cb6abcSbmc uint_t opt_a = FALSE; 111191ebeef5Sahrens uint_t opt_b = FALSE; 111291ebeef5Sahrens uint_t shift = 0; 111391ebeef5Sahrens const char *suffix; 111444cb6abcSbmc 111591ebeef5Sahrens static const char *bytestats[] = { 11169253d63dSGeorge Wilson "p", "c", "c_min", "c_max", "size", "duplicate_buffers_size", 111720128a08SGeorge Wilson "arc_meta_used", "arc_meta_limit", "arc_meta_max", 11184076b1bfSPrakash Surya "arc_meta_min", "hdr_size", "data_size", "metadata_size", 11194076b1bfSPrakash Surya "other_size", "anon_size", "anon_evictable_data", 11204076b1bfSPrakash Surya "anon_evictable_metadata", "mru_size", "mru_evictable_data", 11214076b1bfSPrakash Surya "mru_evictable_metadata", "mru_ghost_size", 11224076b1bfSPrakash Surya "mru_ghost_evictable_data", "mru_ghost_evictable_metadata", 11234076b1bfSPrakash Surya "mfu_size", "mfu_evictable_data", "mfu_evictable_metadata", 11244076b1bfSPrakash Surya "mfu_ghost_size", "mfu_ghost_evictable_data", 11254076b1bfSPrakash Surya "mfu_ghost_evictable_metadata", "evict_l2_cached", 11264076b1bfSPrakash Surya "evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes", 11274076b1bfSPrakash Surya "l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size", 1128dcbf3bd6SGeorge Wilson "compressed_size", "uncompressed_size", "overhead_size", 11299253d63dSGeorge Wilson NULL 113091ebeef5Sahrens }; 113191ebeef5Sahrens 113291ebeef5Sahrens static const char *extras[] = { 113391ebeef5Sahrens "arc_no_grow", "arc_tempreserve", 113491ebeef5Sahrens NULL 113544cb6abcSbmc }; 113644cb6abcSbmc 113722ce0148SMatthew Ahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "arc_stats", &sym) == -1) { 113844cb6abcSbmc mdb_warn("failed to find 'arc_stats'"); 113944cb6abcSbmc return (DCMD_ERR); 114044cb6abcSbmc } 114144cb6abcSbmc 114244cb6abcSbmc stats = mdb_zalloc(sym.st_size, UM_SLEEP | UM_GC); 114344cb6abcSbmc 114444cb6abcSbmc if (mdb_vread(stats, sym.st_size, sym.st_value) == -1) { 114544cb6abcSbmc mdb_warn("couldn't read 'arc_stats' at %p", sym.st_value); 114644cb6abcSbmc return (DCMD_ERR); 114744cb6abcSbmc } 114844cb6abcSbmc 114944cb6abcSbmc nstats = sym.st_size / sizeof (kstat_named_t); 115044cb6abcSbmc 115191ebeef5Sahrens /* NB: -a / opt_a are ignored for backwards compatability */ 115291ebeef5Sahrens if (mdb_getopts(argc, argv, 115391ebeef5Sahrens 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 115491ebeef5Sahrens 'b', MDB_OPT_SETBITS, TRUE, &opt_b, 115591ebeef5Sahrens 'k', MDB_OPT_SETBITS, 10, &shift, 115691ebeef5Sahrens 'm', MDB_OPT_SETBITS, 20, &shift, 115791ebeef5Sahrens 'g', MDB_OPT_SETBITS, 30, &shift, 115891ebeef5Sahrens NULL) != argc) 115944cb6abcSbmc return (DCMD_USAGE); 116044cb6abcSbmc 116191ebeef5Sahrens if (!opt_b && !shift) 116291ebeef5Sahrens shift = 20; 116344cb6abcSbmc 116491ebeef5Sahrens switch (shift) { 116591ebeef5Sahrens case 0: 116691ebeef5Sahrens suffix = "B"; 116791ebeef5Sahrens break; 116891ebeef5Sahrens case 10: 116991ebeef5Sahrens suffix = "KB"; 117091ebeef5Sahrens break; 117191ebeef5Sahrens case 20: 117291ebeef5Sahrens suffix = "MB"; 117391ebeef5Sahrens break; 117491ebeef5Sahrens case 30: 117591ebeef5Sahrens suffix = "GB"; 117691ebeef5Sahrens break; 117791ebeef5Sahrens default: 117891ebeef5Sahrens suffix = "XX"; 117991ebeef5Sahrens } 118091ebeef5Sahrens 118144cb6abcSbmc for (i = 0; i < nstats; i++) { 118291ebeef5Sahrens int j; 118391ebeef5Sahrens boolean_t bytes = B_FALSE; 118491ebeef5Sahrens 118591ebeef5Sahrens for (j = 0; bytestats[j]; j++) { 118691ebeef5Sahrens if (strcmp(stats[i].name, bytestats[j]) == 0) { 118791ebeef5Sahrens bytes = B_TRUE; 118891ebeef5Sahrens break; 118991ebeef5Sahrens } 119091ebeef5Sahrens } 119191ebeef5Sahrens 119291ebeef5Sahrens if (bytes) { 119391ebeef5Sahrens mdb_printf("%-25s = %9llu %s\n", stats[i].name, 119491ebeef5Sahrens stats[i].value.ui64 >> shift, suffix); 119591ebeef5Sahrens } else { 119691ebeef5Sahrens mdb_printf("%-25s = %9llu\n", stats[i].name, 119744cb6abcSbmc stats[i].value.ui64); 119844cb6abcSbmc } 119944cb6abcSbmc } 120044cb6abcSbmc 120191ebeef5Sahrens for (i = 0; extras[i]; i++) { 120244cb6abcSbmc uint64_t buf; 120344cb6abcSbmc 120422ce0148SMatthew Ahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, extras[i], &sym) == -1) { 120591ebeef5Sahrens mdb_warn("failed to find '%s'", extras[i]); 120644cb6abcSbmc return (DCMD_ERR); 120744cb6abcSbmc } 120844cb6abcSbmc 120944cb6abcSbmc if (sym.st_size != sizeof (uint64_t) && 121044cb6abcSbmc sym.st_size != sizeof (uint32_t)) { 121191ebeef5Sahrens mdb_warn("expected scalar for variable '%s'\n", 121291ebeef5Sahrens extras[i]); 121344cb6abcSbmc return (DCMD_ERR); 121444cb6abcSbmc } 121544cb6abcSbmc 121644cb6abcSbmc if (mdb_vread(&buf, sym.st_size, sym.st_value) == -1) { 121791ebeef5Sahrens mdb_warn("couldn't read '%s'", extras[i]); 121844cb6abcSbmc return (DCMD_ERR); 121944cb6abcSbmc } 122044cb6abcSbmc 122191ebeef5Sahrens mdb_printf("%-25s = ", extras[i]); 122244cb6abcSbmc 122391ebeef5Sahrens /* NB: all the 64-bit extras happen to be byte counts */ 122444cb6abcSbmc if (sym.st_size == sizeof (uint64_t)) 122591ebeef5Sahrens mdb_printf("%9llu %s\n", buf >> shift, suffix); 122644cb6abcSbmc 122744cb6abcSbmc if (sym.st_size == sizeof (uint32_t)) 122891ebeef5Sahrens mdb_printf("%9d\n", *((uint32_t *)&buf)); 122944cb6abcSbmc } 123044cb6abcSbmc return (DCMD_OK); 123144cb6abcSbmc } 123244cb6abcSbmc 123322ce0148SMatthew Ahrens typedef struct mdb_spa_print { 123422ce0148SMatthew Ahrens pool_state_t spa_state; 12359adfa60dSMatthew Ahrens char spa_name[ZFS_MAX_DATASET_NAME_LEN]; 123691e2a09fSSteve Gonczi uintptr_t spa_normal_class; 123722ce0148SMatthew Ahrens } mdb_spa_print_t; 123822ce0148SMatthew Ahrens 123991e2a09fSSteve Gonczi 124091e2a09fSSteve Gonczi const char histo_stars[] = "****************************************"; 124191e2a09fSSteve Gonczi const int histo_width = sizeof (histo_stars) - 1; 124291e2a09fSSteve Gonczi 124391e2a09fSSteve Gonczi static void 124491e2a09fSSteve Gonczi dump_histogram(const uint64_t *histo, int size, int offset) 124591e2a09fSSteve Gonczi { 124691e2a09fSSteve Gonczi int i; 124791e2a09fSSteve Gonczi int minidx = size - 1; 124891e2a09fSSteve Gonczi int maxidx = 0; 124991e2a09fSSteve Gonczi uint64_t max = 0; 125091e2a09fSSteve Gonczi 125191e2a09fSSteve Gonczi for (i = 0; i < size; i++) { 125291e2a09fSSteve Gonczi if (histo[i] > max) 125391e2a09fSSteve Gonczi max = histo[i]; 125491e2a09fSSteve Gonczi if (histo[i] > 0 && i > maxidx) 125591e2a09fSSteve Gonczi maxidx = i; 125691e2a09fSSteve Gonczi if (histo[i] > 0 && i < minidx) 125791e2a09fSSteve Gonczi minidx = i; 125891e2a09fSSteve Gonczi } 125991e2a09fSSteve Gonczi 126091e2a09fSSteve Gonczi if (max < histo_width) 126191e2a09fSSteve Gonczi max = histo_width; 126291e2a09fSSteve Gonczi 126391e2a09fSSteve Gonczi for (i = minidx; i <= maxidx; i++) { 126491e2a09fSSteve Gonczi mdb_printf("%3u: %6llu %s\n", 126591e2a09fSSteve Gonczi i + offset, (u_longlong_t)histo[i], 126691e2a09fSSteve Gonczi &histo_stars[(max - histo[i]) * histo_width / max]); 126791e2a09fSSteve Gonczi } 126891e2a09fSSteve Gonczi } 126991e2a09fSSteve Gonczi 127091e2a09fSSteve Gonczi typedef struct mdb_metaslab_class { 127191e2a09fSSteve Gonczi uint64_t mc_histogram[RANGE_TREE_HISTOGRAM_SIZE]; 127291e2a09fSSteve Gonczi } mdb_metaslab_class_t; 127391e2a09fSSteve Gonczi 127491e2a09fSSteve Gonczi /* 127591e2a09fSSteve Gonczi * spa_class_histogram(uintptr_t class_addr) 127691e2a09fSSteve Gonczi * 127791e2a09fSSteve Gonczi * Prints free space histogram for a device class 127891e2a09fSSteve Gonczi * 127991e2a09fSSteve Gonczi * Returns DCMD_OK, or DCMD_ERR. 128091e2a09fSSteve Gonczi */ 128191e2a09fSSteve Gonczi static int 128291e2a09fSSteve Gonczi spa_class_histogram(uintptr_t class_addr) 128391e2a09fSSteve Gonczi { 128491e2a09fSSteve Gonczi mdb_metaslab_class_t mc; 128591e2a09fSSteve Gonczi if (mdb_ctf_vread(&mc, "metaslab_class_t", 128691e2a09fSSteve Gonczi "mdb_metaslab_class_t", class_addr, 0) == -1) 128791e2a09fSSteve Gonczi return (DCMD_ERR); 128891e2a09fSSteve Gonczi 128991e2a09fSSteve Gonczi mdb_inc_indent(4); 129091e2a09fSSteve Gonczi dump_histogram(mc.mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 129191e2a09fSSteve Gonczi mdb_dec_indent(4); 129291e2a09fSSteve Gonczi return (DCMD_OK); 129391e2a09fSSteve Gonczi } 129491e2a09fSSteve Gonczi 1295fa9e4066Sahrens /* 1296fa9e4066Sahrens * ::spa 1297fa9e4066Sahrens * 1298fa9e4066Sahrens * -c Print configuration information as well 1299fa9e4066Sahrens * -v Print vdev state 1300fa9e4066Sahrens * -e Print vdev error stats 13012e4c9986SGeorge Wilson * -m Print vdev metaslab info 13022e4c9986SGeorge Wilson * -M print vdev metaslab group info 13032e4c9986SGeorge Wilson * -h Print histogram info (must be combined with -m or -M) 1304fa9e4066Sahrens * 1305fa9e4066Sahrens * Print a summarized spa_t. When given no arguments, prints out a table of all 1306fa9e4066Sahrens * active pools on the system. 1307fa9e4066Sahrens */ 1308fa9e4066Sahrens /* ARGSUSED */ 1309fa9e4066Sahrens static int 1310fa9e4066Sahrens spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1311fa9e4066Sahrens { 1312fa9e4066Sahrens const char *statetab[] = { "ACTIVE", "EXPORTED", "DESTROYED", 1313e14bb325SJeff Bonwick "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" }; 1314fa9e4066Sahrens const char *state; 13152e4c9986SGeorge Wilson int spa_flags = 0; 1316fa9e4066Sahrens 1317fa9e4066Sahrens if (mdb_getopts(argc, argv, 13182e4c9986SGeorge Wilson 'c', MDB_OPT_SETBITS, SPA_FLAG_CONFIG, &spa_flags, 13192e4c9986SGeorge Wilson 'v', MDB_OPT_SETBITS, SPA_FLAG_VDEVS, &spa_flags, 13202e4c9986SGeorge Wilson 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 13212e4c9986SGeorge Wilson 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 13222e4c9986SGeorge Wilson 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 13232e4c9986SGeorge Wilson 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 1324fa9e4066Sahrens NULL) != argc) 1325fa9e4066Sahrens return (DCMD_USAGE); 1326fa9e4066Sahrens 1327fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) { 1328fa9e4066Sahrens if (mdb_walk_dcmd("spa", "spa", argc, argv) == -1) { 1329fa9e4066Sahrens mdb_warn("can't walk spa"); 1330fa9e4066Sahrens return (DCMD_ERR); 1331fa9e4066Sahrens } 1332fa9e4066Sahrens 1333fa9e4066Sahrens return (DCMD_OK); 1334fa9e4066Sahrens } 1335fa9e4066Sahrens 1336fa9e4066Sahrens if (flags & DCMD_PIPE_OUT) { 1337fa9e4066Sahrens mdb_printf("%#lr\n", addr); 1338fa9e4066Sahrens return (DCMD_OK); 1339fa9e4066Sahrens } 1340fa9e4066Sahrens 1341fa9e4066Sahrens if (DCMD_HDRSPEC(flags)) 1342fa9e4066Sahrens mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE", 1343fa9e4066Sahrens sizeof (uintptr_t) == 4 ? 60 : 52, "NAME"); 1344fa9e4066Sahrens 134522ce0148SMatthew Ahrens mdb_spa_print_t spa; 134622ce0148SMatthew Ahrens if (mdb_ctf_vread(&spa, "spa_t", "mdb_spa_print_t", addr, 0) == -1) 1347fa9e4066Sahrens return (DCMD_ERR); 1348fa9e4066Sahrens 1349fa9e4066Sahrens if (spa.spa_state < 0 || spa.spa_state > POOL_STATE_UNAVAIL) 1350ea8dc4b6Seschrock state = "UNKNOWN"; 1351fa9e4066Sahrens else 1352fa9e4066Sahrens state = statetab[spa.spa_state]; 1353fa9e4066Sahrens 1354e14bb325SJeff Bonwick mdb_printf("%0?p %9s %s\n", addr, state, spa.spa_name); 135591e2a09fSSteve Gonczi if (spa_flags & SPA_FLAG_HISTOGRAMS) 135691e2a09fSSteve Gonczi spa_class_histogram(spa.spa_normal_class); 1357fa9e4066Sahrens 13582e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_CONFIG) { 1359fa9e4066Sahrens mdb_printf("\n"); 1360fa9e4066Sahrens mdb_inc_indent(4); 1361fa9e4066Sahrens if (mdb_call_dcmd("spa_config", addr, flags, 0, 1362fa9e4066Sahrens NULL) != DCMD_OK) 1363fa9e4066Sahrens return (DCMD_ERR); 1364fa9e4066Sahrens mdb_dec_indent(4); 1365fa9e4066Sahrens } 1366fa9e4066Sahrens 13672e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_ALL_VDEV) { 1368fa9e4066Sahrens mdb_arg_t v; 13692e4c9986SGeorge Wilson char opts[100] = "-"; 13702e4c9986SGeorge Wilson int args = 13712e4c9986SGeorge Wilson (spa_flags | SPA_FLAG_VDEVS) == SPA_FLAG_VDEVS ? 0 : 1; 13722e4c9986SGeorge Wilson 13732e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_ERRORS) 13742e4c9986SGeorge Wilson strcat(opts, "e"); 13752e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLABS) 13762e4c9986SGeorge Wilson strcat(opts, "m"); 13772e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLAB_GROUPS) 13782e4c9986SGeorge Wilson strcat(opts, "M"); 13792e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_HISTOGRAMS) 13802e4c9986SGeorge Wilson strcat(opts, "h"); 1381fa9e4066Sahrens 1382fa9e4066Sahrens v.a_type = MDB_TYPE_STRING; 13832e4c9986SGeorge Wilson v.a_un.a_str = opts; 1384fa9e4066Sahrens 1385fa9e4066Sahrens mdb_printf("\n"); 1386fa9e4066Sahrens mdb_inc_indent(4); 13872e4c9986SGeorge Wilson if (mdb_call_dcmd("spa_vdevs", addr, flags, args, 1388fa9e4066Sahrens &v) != DCMD_OK) 1389fa9e4066Sahrens return (DCMD_ERR); 1390fa9e4066Sahrens mdb_dec_indent(4); 1391fa9e4066Sahrens } 1392fa9e4066Sahrens 1393fa9e4066Sahrens return (DCMD_OK); 1394fa9e4066Sahrens } 1395fa9e4066Sahrens 139628e4da25SMatthew Ahrens typedef struct mdb_spa_config_spa { 1397d5ee8a13SMatthew Ahrens uintptr_t spa_config; 139828e4da25SMatthew Ahrens } mdb_spa_config_spa_t; 139928e4da25SMatthew Ahrens 1400fa9e4066Sahrens /* 1401fa9e4066Sahrens * ::spa_config 1402fa9e4066Sahrens * 1403fa9e4066Sahrens * Given a spa_t, print the configuration information stored in spa_config. 1404fa9e4066Sahrens * Since it's just an nvlist, format it as an indented list of name=value pairs. 1405fa9e4066Sahrens * We simply read the value of spa_config and pass off to ::nvlist. 1406fa9e4066Sahrens */ 1407fa9e4066Sahrens /* ARGSUSED */ 1408fa9e4066Sahrens static int 1409fa9e4066Sahrens spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1410fa9e4066Sahrens { 141128e4da25SMatthew Ahrens mdb_spa_config_spa_t spa; 1412fa9e4066Sahrens 1413fa9e4066Sahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1414fa9e4066Sahrens return (DCMD_USAGE); 1415fa9e4066Sahrens 141628e4da25SMatthew Ahrens if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_config_spa_t", 141728e4da25SMatthew Ahrens addr, 0) == -1) 1418fa9e4066Sahrens return (DCMD_ERR); 1419fa9e4066Sahrens 1420d5ee8a13SMatthew Ahrens if (spa.spa_config == 0) { 1421fa9e4066Sahrens mdb_printf("(none)\n"); 1422fa9e4066Sahrens return (DCMD_OK); 1423fa9e4066Sahrens } 1424fa9e4066Sahrens 1425d5ee8a13SMatthew Ahrens return (mdb_call_dcmd("nvlist", spa.spa_config, flags, 1426fa9e4066Sahrens 0, NULL)); 1427fa9e4066Sahrens } 1428fa9e4066Sahrens 14292e4c9986SGeorge Wilson 14302e4c9986SGeorge Wilson 14312e4c9986SGeorge Wilson typedef struct mdb_range_tree { 14322e4c9986SGeorge Wilson uint64_t rt_space; 14332e4c9986SGeorge Wilson } mdb_range_tree_t; 14342e4c9986SGeorge Wilson 14352e4c9986SGeorge Wilson typedef struct mdb_metaslab_group { 14362e4c9986SGeorge Wilson uint64_t mg_fragmentation; 14372e4c9986SGeorge Wilson uint64_t mg_histogram[RANGE_TREE_HISTOGRAM_SIZE]; 14388363e80aSGeorge Wilson uintptr_t mg_vd; 14392e4c9986SGeorge Wilson } mdb_metaslab_group_t; 14402e4c9986SGeorge Wilson 14412e4c9986SGeorge Wilson typedef struct mdb_metaslab { 14422e4c9986SGeorge Wilson uint64_t ms_id; 14432e4c9986SGeorge Wilson uint64_t ms_start; 14442e4c9986SGeorge Wilson uint64_t ms_size; 14458363e80aSGeorge Wilson int64_t ms_deferspace; 14462e4c9986SGeorge Wilson uint64_t ms_fragmentation; 14478363e80aSGeorge Wilson uint64_t ms_weight; 144886714001SSerapheim Dimitropoulos uintptr_t ms_allocating[TXG_SIZE]; 144986714001SSerapheim Dimitropoulos uintptr_t ms_checkpointing; 145086714001SSerapheim Dimitropoulos uintptr_t ms_freeing; 145186714001SSerapheim Dimitropoulos uintptr_t ms_freed; 145286714001SSerapheim Dimitropoulos uintptr_t ms_allocatable; 14532e4c9986SGeorge Wilson uintptr_t ms_sm; 14542e4c9986SGeorge Wilson } mdb_metaslab_t; 14552e4c9986SGeorge Wilson 14562e4c9986SGeorge Wilson typedef struct mdb_space_map_phys_t { 145786714001SSerapheim Dimitropoulos int64_t smp_alloc; 14582e4c9986SGeorge Wilson uint64_t smp_histogram[SPACE_MAP_HISTOGRAM_SIZE]; 14592e4c9986SGeorge Wilson } mdb_space_map_phys_t; 14602e4c9986SGeorge Wilson 14612e4c9986SGeorge Wilson typedef struct mdb_space_map { 14622e4c9986SGeorge Wilson uint64_t sm_size; 14632e4c9986SGeorge Wilson uint8_t sm_shift; 14642e4c9986SGeorge Wilson uintptr_t sm_phys; 14652e4c9986SGeorge Wilson } mdb_space_map_t; 14662e4c9986SGeorge Wilson 14672e4c9986SGeorge Wilson typedef struct mdb_vdev { 14688363e80aSGeorge Wilson uintptr_t vdev_path; 14692e4c9986SGeorge Wilson uintptr_t vdev_ms; 14708363e80aSGeorge Wilson uintptr_t vdev_ops; 14712e4c9986SGeorge Wilson uint64_t vdev_ms_count; 14728363e80aSGeorge Wilson uint64_t vdev_id; 14732e4c9986SGeorge Wilson vdev_stat_t vdev_stat; 14742e4c9986SGeorge Wilson } mdb_vdev_t; 14752e4c9986SGeorge Wilson 14768363e80aSGeorge Wilson typedef struct mdb_vdev_ops { 14778363e80aSGeorge Wilson char vdev_op_type[16]; 14788363e80aSGeorge Wilson } mdb_vdev_ops_t; 14798363e80aSGeorge Wilson 14802e4c9986SGeorge Wilson static int 14812e4c9986SGeorge Wilson metaslab_stats(uintptr_t addr, int spa_flags) 14822e4c9986SGeorge Wilson { 14832e4c9986SGeorge Wilson mdb_vdev_t vdev; 14842e4c9986SGeorge Wilson uintptr_t *vdev_ms; 14852e4c9986SGeorge Wilson 14862e4c9986SGeorge Wilson if (mdb_ctf_vread(&vdev, "vdev_t", "mdb_vdev_t", 14872e4c9986SGeorge Wilson (uintptr_t)addr, 0) == -1) { 14882e4c9986SGeorge Wilson mdb_warn("failed to read vdev at %p\n", addr); 14892e4c9986SGeorge Wilson return (DCMD_ERR); 14902e4c9986SGeorge Wilson } 14912e4c9986SGeorge Wilson 14922e4c9986SGeorge Wilson mdb_inc_indent(4); 14932e4c9986SGeorge Wilson mdb_printf("%<u>%-?s %6s %20s %10s %9s%</u>\n", "ADDR", "ID", 14942e4c9986SGeorge Wilson "OFFSET", "FREE", "FRAGMENTATION"); 14952e4c9986SGeorge Wilson 14962e4c9986SGeorge Wilson vdev_ms = mdb_alloc(vdev.vdev_ms_count * sizeof (void *), 14972e4c9986SGeorge Wilson UM_SLEEP | UM_GC); 14982e4c9986SGeorge Wilson if (mdb_vread(vdev_ms, vdev.vdev_ms_count * sizeof (void *), 14992e4c9986SGeorge Wilson (uintptr_t)vdev.vdev_ms) == -1) { 15002e4c9986SGeorge Wilson mdb_warn("failed to read vdev_ms at %p\n", vdev.vdev_ms); 15012e4c9986SGeorge Wilson return (DCMD_ERR); 15022e4c9986SGeorge Wilson } 15032e4c9986SGeorge Wilson 15042e4c9986SGeorge Wilson for (int m = 0; m < vdev.vdev_ms_count; m++) { 15052e4c9986SGeorge Wilson mdb_metaslab_t ms; 15062e4c9986SGeorge Wilson mdb_space_map_t sm = { 0 }; 1507*29d33d42SKody A Kantor mdb_space_map_phys_t smp; 1508d70f65dfSToomas Soome char free[MDB_NICENUM_BUFLEN]; 15092e4c9986SGeorge Wilson 15102e4c9986SGeorge Wilson if (mdb_ctf_vread(&ms, "metaslab_t", "mdb_metaslab_t", 15112e4c9986SGeorge Wilson (uintptr_t)vdev_ms[m], 0) == -1) 15122e4c9986SGeorge Wilson return (DCMD_ERR); 15132e4c9986SGeorge Wilson 1514892ad162SToomas Soome if (ms.ms_sm != 0 && 15152e4c9986SGeorge Wilson mdb_ctf_vread(&sm, "space_map_t", "mdb_space_map_t", 15162e4c9986SGeorge Wilson ms.ms_sm, 0) == -1) 15172e4c9986SGeorge Wilson return (DCMD_ERR); 15182e4c9986SGeorge Wilson 1519*29d33d42SKody A Kantor if (sm.sm_phys != 0) { 1520*29d33d42SKody A Kantor (void) mdb_ctf_vread(&smp, "space_map_phys_t", 1521*29d33d42SKody A Kantor "mdb_space_map_phys_t", sm.sm_phys, 0); 1522*29d33d42SKody A Kantor mdb_nicenum(ms.ms_size - smp.smp_alloc, free); 1523*29d33d42SKody A Kantor } else { 1524*29d33d42SKody A Kantor (void) mdb_snprintf(free, MDB_NICENUM_BUFLEN, "-"); 1525*29d33d42SKody A Kantor } 15262e4c9986SGeorge Wilson 15272e4c9986SGeorge Wilson mdb_printf("%0?p %6llu %20llx %10s ", vdev_ms[m], ms.ms_id, 15282e4c9986SGeorge Wilson ms.ms_start, free); 15292e4c9986SGeorge Wilson if (ms.ms_fragmentation == ZFS_FRAG_INVALID) 15302e4c9986SGeorge Wilson mdb_printf("%9s\n", "-"); 15312e4c9986SGeorge Wilson else 15322e4c9986SGeorge Wilson mdb_printf("%9llu%%\n", ms.ms_fragmentation); 15332e4c9986SGeorge Wilson 1534892ad162SToomas Soome if ((spa_flags & SPA_FLAG_HISTOGRAMS) && ms.ms_sm != 0) { 1535892ad162SToomas Soome if (sm.sm_phys == 0) 15362e4c9986SGeorge Wilson continue; 15372e4c9986SGeorge Wilson 15382e4c9986SGeorge Wilson dump_histogram(smp.smp_histogram, 15392e4c9986SGeorge Wilson SPACE_MAP_HISTOGRAM_SIZE, sm.sm_shift); 15402e4c9986SGeorge Wilson } 15412e4c9986SGeorge Wilson } 15422e4c9986SGeorge Wilson mdb_dec_indent(4); 15432e4c9986SGeorge Wilson return (DCMD_OK); 15442e4c9986SGeorge Wilson } 15452e4c9986SGeorge Wilson 15462e4c9986SGeorge Wilson static int 15472e4c9986SGeorge Wilson metaslab_group_stats(uintptr_t addr, int spa_flags) 15482e4c9986SGeorge Wilson { 15492e4c9986SGeorge Wilson mdb_metaslab_group_t mg; 15502e4c9986SGeorge Wilson if (mdb_ctf_vread(&mg, "metaslab_group_t", "mdb_metaslab_group_t", 15512e4c9986SGeorge Wilson (uintptr_t)addr, 0) == -1) { 15522e4c9986SGeorge Wilson mdb_warn("failed to read vdev_mg at %p\n", addr); 15532e4c9986SGeorge Wilson return (DCMD_ERR); 15542e4c9986SGeorge Wilson } 15552e4c9986SGeorge Wilson 15562e4c9986SGeorge Wilson mdb_inc_indent(4); 15572e4c9986SGeorge Wilson mdb_printf("%<u>%-?s %15s%</u>\n", "ADDR", "FRAGMENTATION"); 15582e4c9986SGeorge Wilson if (mg.mg_fragmentation == ZFS_FRAG_INVALID) 15592e4c9986SGeorge Wilson mdb_printf("%0?p %15s\n", addr, "-"); 15602e4c9986SGeorge Wilson else 15612e4c9986SGeorge Wilson mdb_printf("%0?p %15llu%%\n", addr, mg.mg_fragmentation); 15622e4c9986SGeorge Wilson 15632e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_HISTOGRAMS) 15642e4c9986SGeorge Wilson dump_histogram(mg.mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 15652e4c9986SGeorge Wilson mdb_dec_indent(4); 15662e4c9986SGeorge Wilson return (DCMD_OK); 15672e4c9986SGeorge Wilson } 15682e4c9986SGeorge Wilson 1569fa9e4066Sahrens /* 1570fa9e4066Sahrens * ::vdev 1571fa9e4066Sahrens * 1572fa9e4066Sahrens * Print out a summarized vdev_t, in the following form: 1573fa9e4066Sahrens * 1574fa9e4066Sahrens * ADDR STATE AUX DESC 1575fa9e4066Sahrens * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0 1576fa9e4066Sahrens * 1577fa9e4066Sahrens * If '-r' is specified, recursively visit all children. 1578fa9e4066Sahrens * 1579fa9e4066Sahrens * With '-e', the statistics associated with the vdev are printed as well. 1580fa9e4066Sahrens */ 1581fa9e4066Sahrens static int 15822e4c9986SGeorge Wilson do_print_vdev(uintptr_t addr, int flags, int depth, boolean_t recursive, 15832e4c9986SGeorge Wilson int spa_flags) 1584fa9e4066Sahrens { 1585fa9e4066Sahrens vdev_t vdev; 1586fa9e4066Sahrens char desc[MAXNAMELEN]; 1587fa9e4066Sahrens int c, children; 1588fa9e4066Sahrens uintptr_t *child; 1589fa9e4066Sahrens const char *state, *aux; 1590fa9e4066Sahrens 1591fa9e4066Sahrens if (mdb_vread(&vdev, sizeof (vdev), (uintptr_t)addr) == -1) { 1592fa9e4066Sahrens mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr); 1593fa9e4066Sahrens return (DCMD_ERR); 1594fa9e4066Sahrens } 1595fa9e4066Sahrens 1596fa9e4066Sahrens if (flags & DCMD_PIPE_OUT) { 1597b4952e17SGeorge Wilson mdb_printf("%#lr\n", addr); 1598fa9e4066Sahrens } else { 1599fa9e4066Sahrens if (vdev.vdev_path != NULL) { 1600fa9e4066Sahrens if (mdb_readstr(desc, sizeof (desc), 1601fa9e4066Sahrens (uintptr_t)vdev.vdev_path) == -1) { 1602fa9e4066Sahrens mdb_warn("failed to read vdev_path at %p\n", 1603fa9e4066Sahrens vdev.vdev_path); 1604fa9e4066Sahrens return (DCMD_ERR); 1605fa9e4066Sahrens } 1606fa9e4066Sahrens } else if (vdev.vdev_ops != NULL) { 1607fa9e4066Sahrens vdev_ops_t ops; 1608fa9e4066Sahrens if (mdb_vread(&ops, sizeof (ops), 1609fa9e4066Sahrens (uintptr_t)vdev.vdev_ops) == -1) { 1610fa9e4066Sahrens mdb_warn("failed to read vdev_ops at %p\n", 1611fa9e4066Sahrens vdev.vdev_ops); 1612fa9e4066Sahrens return (DCMD_ERR); 1613fa9e4066Sahrens } 1614fa9e4066Sahrens (void) strcpy(desc, ops.vdev_op_type); 1615fa9e4066Sahrens } else { 1616fa9e4066Sahrens (void) strcpy(desc, "<unknown>"); 1617fa9e4066Sahrens } 1618fa9e4066Sahrens 1619fa9e4066Sahrens if (depth == 0 && DCMD_HDRSPEC(flags)) 1620fa9e4066Sahrens mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n", 1621fa9e4066Sahrens "ADDR", "STATE", "AUX", 1622fa9e4066Sahrens sizeof (uintptr_t) == 4 ? 43 : 35, 1623fa9e4066Sahrens "DESCRIPTION"); 1624fa9e4066Sahrens 1625fa9e4066Sahrens mdb_printf("%0?p ", addr); 1626fa9e4066Sahrens 1627fa9e4066Sahrens switch (vdev.vdev_state) { 1628fa9e4066Sahrens case VDEV_STATE_CLOSED: 1629fa9e4066Sahrens state = "CLOSED"; 1630fa9e4066Sahrens break; 1631fa9e4066Sahrens case VDEV_STATE_OFFLINE: 1632fa9e4066Sahrens state = "OFFLINE"; 1633fa9e4066Sahrens break; 1634fa9e4066Sahrens case VDEV_STATE_CANT_OPEN: 1635fa9e4066Sahrens state = "CANT_OPEN"; 1636fa9e4066Sahrens break; 1637fa9e4066Sahrens case VDEV_STATE_DEGRADED: 1638fa9e4066Sahrens state = "DEGRADED"; 1639fa9e4066Sahrens break; 1640fa9e4066Sahrens case VDEV_STATE_HEALTHY: 1641fa9e4066Sahrens state = "HEALTHY"; 1642fa9e4066Sahrens break; 16433d7072f8Seschrock case VDEV_STATE_REMOVED: 16443d7072f8Seschrock state = "REMOVED"; 16453d7072f8Seschrock break; 16463d7072f8Seschrock case VDEV_STATE_FAULTED: 16473d7072f8Seschrock state = "FAULTED"; 16483d7072f8Seschrock break; 1649fa9e4066Sahrens default: 1650fa9e4066Sahrens state = "UNKNOWN"; 1651fa9e4066Sahrens break; 1652fa9e4066Sahrens } 1653fa9e4066Sahrens 1654fa9e4066Sahrens switch (vdev.vdev_stat.vs_aux) { 1655fa9e4066Sahrens case VDEV_AUX_NONE: 1656fa9e4066Sahrens aux = "-"; 1657fa9e4066Sahrens break; 1658fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 1659fa9e4066Sahrens aux = "OPEN_FAILED"; 1660fa9e4066Sahrens break; 1661fa9e4066Sahrens case VDEV_AUX_CORRUPT_DATA: 1662fa9e4066Sahrens aux = "CORRUPT_DATA"; 1663fa9e4066Sahrens break; 1664fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1665fa9e4066Sahrens aux = "NO_REPLICAS"; 1666fa9e4066Sahrens break; 1667fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1668fa9e4066Sahrens aux = "BAD_GUID_SUM"; 1669fa9e4066Sahrens break; 1670fa9e4066Sahrens case VDEV_AUX_TOO_SMALL: 1671fa9e4066Sahrens aux = "TOO_SMALL"; 1672fa9e4066Sahrens break; 1673fa9e4066Sahrens case VDEV_AUX_BAD_LABEL: 1674fa9e4066Sahrens aux = "BAD_LABEL"; 1675fa9e4066Sahrens break; 1676b87f3af3Sperrin case VDEV_AUX_VERSION_NEWER: 1677b87f3af3Sperrin aux = "VERS_NEWER"; 1678b87f3af3Sperrin break; 1679b87f3af3Sperrin case VDEV_AUX_VERSION_OLDER: 1680b87f3af3Sperrin aux = "VERS_OLDER"; 1681b87f3af3Sperrin break; 1682ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1683ad135b5dSChristopher Siden aux = "UNSUP_FEAT"; 1684ad135b5dSChristopher Siden break; 1685b87f3af3Sperrin case VDEV_AUX_SPARED: 1686b87f3af3Sperrin aux = "SPARED"; 1687b87f3af3Sperrin break; 1688b87f3af3Sperrin case VDEV_AUX_ERR_EXCEEDED: 1689b87f3af3Sperrin aux = "ERR_EXCEEDED"; 1690b87f3af3Sperrin break; 1691b87f3af3Sperrin case VDEV_AUX_IO_FAILURE: 1692b87f3af3Sperrin aux = "IO_FAILURE"; 1693b87f3af3Sperrin break; 1694b87f3af3Sperrin case VDEV_AUX_BAD_LOG: 1695b87f3af3Sperrin aux = "BAD_LOG"; 1696b87f3af3Sperrin break; 16971195e687SMark J Musante case VDEV_AUX_EXTERNAL: 16981195e687SMark J Musante aux = "EXTERNAL"; 16991195e687SMark J Musante break; 17001195e687SMark J Musante case VDEV_AUX_SPLIT_POOL: 17011195e687SMark J Musante aux = "SPLIT_POOL"; 17021195e687SMark J Musante break; 17036f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 17046f793812SPavel Zakharov aux = "CHILDREN_OFFLINE"; 17056f793812SPavel Zakharov break; 1706fa9e4066Sahrens default: 1707fa9e4066Sahrens aux = "UNKNOWN"; 1708fa9e4066Sahrens break; 1709fa9e4066Sahrens } 1710fa9e4066Sahrens 1711fa9e4066Sahrens mdb_printf("%-9s %-12s %*s%s\n", state, aux, depth, "", desc); 1712fa9e4066Sahrens 17132e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_ERRORS) { 1714fa9e4066Sahrens vdev_stat_t *vs = &vdev.vdev_stat; 1715fa9e4066Sahrens int i; 1716fa9e4066Sahrens 1717fa9e4066Sahrens mdb_inc_indent(4); 1718fa9e4066Sahrens mdb_printf("\n"); 1719fa9e4066Sahrens mdb_printf("%<u> %12s %12s %12s %12s " 1720fa9e4066Sahrens "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM", 1721fa9e4066Sahrens "IOCTL"); 1722fa9e4066Sahrens mdb_printf("OPS "); 1723fa9e4066Sahrens for (i = 1; i < ZIO_TYPES; i++) 1724fa9e4066Sahrens mdb_printf("%11#llx%s", vs->vs_ops[i], 1725fa9e4066Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1726fa9e4066Sahrens mdb_printf("\n"); 1727fa9e4066Sahrens mdb_printf("BYTES "); 1728fa9e4066Sahrens for (i = 1; i < ZIO_TYPES; i++) 1729fa9e4066Sahrens mdb_printf("%11#llx%s", vs->vs_bytes[i], 1730fa9e4066Sahrens i == ZIO_TYPES - 1 ? "" : " "); 1731fa9e4066Sahrens 1732fa9e4066Sahrens 1733fa9e4066Sahrens mdb_printf("\n"); 1734fa9e4066Sahrens mdb_printf("EREAD %10#llx\n", vs->vs_read_errors); 1735fa9e4066Sahrens mdb_printf("EWRITE %10#llx\n", vs->vs_write_errors); 1736fa9e4066Sahrens mdb_printf("ECKSUM %10#llx\n", 1737fa9e4066Sahrens vs->vs_checksum_errors); 1738fa9e4066Sahrens mdb_dec_indent(4); 17392e4c9986SGeorge Wilson mdb_printf("\n"); 1740fa9e4066Sahrens } 1741fa9e4066Sahrens 17422e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLAB_GROUPS && 17432e4c9986SGeorge Wilson vdev.vdev_mg != NULL) { 17442e4c9986SGeorge Wilson metaslab_group_stats((uintptr_t)vdev.vdev_mg, 17452e4c9986SGeorge Wilson spa_flags); 17462e4c9986SGeorge Wilson } 17472e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLABS && vdev.vdev_ms != NULL) { 17482e4c9986SGeorge Wilson metaslab_stats((uintptr_t)addr, spa_flags); 17492e4c9986SGeorge Wilson } 1750fa9e4066Sahrens } 1751fa9e4066Sahrens 1752fa9e4066Sahrens children = vdev.vdev_children; 1753fa9e4066Sahrens 1754fa9e4066Sahrens if (children == 0 || !recursive) 1755fa9e4066Sahrens return (DCMD_OK); 1756fa9e4066Sahrens 1757fa9e4066Sahrens child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1758fa9e4066Sahrens if (mdb_vread(child, children * sizeof (void *), 1759fa9e4066Sahrens (uintptr_t)vdev.vdev_child) == -1) { 1760fa9e4066Sahrens mdb_warn("failed to read vdev children at %p", vdev.vdev_child); 1761fa9e4066Sahrens return (DCMD_ERR); 1762fa9e4066Sahrens } 1763fa9e4066Sahrens 1764fa9e4066Sahrens for (c = 0; c < children; c++) { 17652e4c9986SGeorge Wilson if (do_print_vdev(child[c], flags, depth + 2, recursive, 17662e4c9986SGeorge Wilson spa_flags)) { 1767fa9e4066Sahrens return (DCMD_ERR); 1768fa9e4066Sahrens } 17692e4c9986SGeorge Wilson } 1770fa9e4066Sahrens 1771fa9e4066Sahrens return (DCMD_OK); 1772fa9e4066Sahrens } 1773fa9e4066Sahrens 1774fa9e4066Sahrens static int 1775fa9e4066Sahrens vdev_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1776fa9e4066Sahrens { 1777c5904d13Seschrock uint64_t depth = 0; 17782e4c9986SGeorge Wilson boolean_t recursive = B_FALSE; 17792e4c9986SGeorge Wilson int spa_flags = 0; 1780fa9e4066Sahrens 1781fa9e4066Sahrens if (mdb_getopts(argc, argv, 17822e4c9986SGeorge Wilson 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 17832e4c9986SGeorge Wilson 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 17842e4c9986SGeorge Wilson 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 17852e4c9986SGeorge Wilson 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 1786fa9e4066Sahrens 'r', MDB_OPT_SETBITS, TRUE, &recursive, 17872e4c9986SGeorge Wilson 'd', MDB_OPT_UINT64, &depth, NULL) != argc) 1788fa9e4066Sahrens return (DCMD_USAGE); 1789fa9e4066Sahrens 1790fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) { 1791fa9e4066Sahrens mdb_warn("no vdev_t address given\n"); 1792fa9e4066Sahrens return (DCMD_ERR); 1793fa9e4066Sahrens } 1794fa9e4066Sahrens 17952e4c9986SGeorge Wilson return (do_print_vdev(addr, flags, (int)depth, recursive, spa_flags)); 1796fa9e4066Sahrens } 1797fa9e4066Sahrens 17988363e80aSGeorge Wilson typedef struct mdb_metaslab_alloc_trace { 17998363e80aSGeorge Wilson uintptr_t mat_mg; 18008363e80aSGeorge Wilson uintptr_t mat_msp; 18018363e80aSGeorge Wilson uint64_t mat_size; 18028363e80aSGeorge Wilson uint64_t mat_weight; 18038363e80aSGeorge Wilson uint64_t mat_offset; 18048363e80aSGeorge Wilson uint32_t mat_dva_id; 1805f78cdc34SPaul Dagnelie int mat_allocator; 18068363e80aSGeorge Wilson } mdb_metaslab_alloc_trace_t; 18078363e80aSGeorge Wilson 18088363e80aSGeorge Wilson static void 18098363e80aSGeorge Wilson metaslab_print_weight(uint64_t weight) 18108363e80aSGeorge Wilson { 18118363e80aSGeorge Wilson char buf[100]; 18128363e80aSGeorge Wilson 18138363e80aSGeorge Wilson if (WEIGHT_IS_SPACEBASED(weight)) { 18148363e80aSGeorge Wilson mdb_nicenum( 18158363e80aSGeorge Wilson weight & ~(METASLAB_ACTIVE_MASK | METASLAB_WEIGHT_TYPE), 18168363e80aSGeorge Wilson buf); 18178363e80aSGeorge Wilson } else { 1818d70f65dfSToomas Soome char size[MDB_NICENUM_BUFLEN]; 18198363e80aSGeorge Wilson mdb_nicenum(1ULL << WEIGHT_GET_INDEX(weight), size); 18208363e80aSGeorge Wilson (void) mdb_snprintf(buf, sizeof (buf), "%llu x %s", 18218363e80aSGeorge Wilson WEIGHT_GET_COUNT(weight), size); 18228363e80aSGeorge Wilson } 18238363e80aSGeorge Wilson mdb_printf("%11s ", buf); 18248363e80aSGeorge Wilson } 18258363e80aSGeorge Wilson 18268363e80aSGeorge Wilson /* ARGSUSED */ 18278363e80aSGeorge Wilson static int 18288363e80aSGeorge Wilson metaslab_weight(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 18298363e80aSGeorge Wilson { 18308363e80aSGeorge Wilson uint64_t weight = 0; 18318363e80aSGeorge Wilson char active; 18328363e80aSGeorge Wilson 18338363e80aSGeorge Wilson if (argc == 0 && (flags & DCMD_ADDRSPEC)) { 18348363e80aSGeorge Wilson if (mdb_vread(&weight, sizeof (uint64_t), addr) == -1) { 18358363e80aSGeorge Wilson mdb_warn("failed to read weight at %p\n", addr); 18368363e80aSGeorge Wilson return (DCMD_ERR); 18378363e80aSGeorge Wilson } 18388363e80aSGeorge Wilson } else if (argc == 1 && !(flags & DCMD_ADDRSPEC)) { 18398363e80aSGeorge Wilson weight = (argv[0].a_type == MDB_TYPE_IMMEDIATE) ? 18408363e80aSGeorge Wilson argv[0].a_un.a_val : mdb_strtoull(argv[0].a_un.a_str); 18418363e80aSGeorge Wilson } else { 18428363e80aSGeorge Wilson return (DCMD_USAGE); 18438363e80aSGeorge Wilson } 18448363e80aSGeorge Wilson 18458363e80aSGeorge Wilson if (DCMD_HDRSPEC(flags)) { 18468363e80aSGeorge Wilson mdb_printf("%<u>%-6s %9s %9s%</u>\n", 18478363e80aSGeorge Wilson "ACTIVE", "ALGORITHM", "WEIGHT"); 18488363e80aSGeorge Wilson } 18498363e80aSGeorge Wilson 18508363e80aSGeorge Wilson if (weight & METASLAB_WEIGHT_PRIMARY) 18518363e80aSGeorge Wilson active = 'P'; 18528363e80aSGeorge Wilson else if (weight & METASLAB_WEIGHT_SECONDARY) 18538363e80aSGeorge Wilson active = 'S'; 18548363e80aSGeorge Wilson else 18558363e80aSGeorge Wilson active = '-'; 18568363e80aSGeorge Wilson mdb_printf("%6c %8s ", active, 18578363e80aSGeorge Wilson WEIGHT_IS_SPACEBASED(weight) ? "SPACE" : "SEGMENT"); 18588363e80aSGeorge Wilson metaslab_print_weight(weight); 18598363e80aSGeorge Wilson mdb_printf("\n"); 18608363e80aSGeorge Wilson 18618363e80aSGeorge Wilson return (DCMD_OK); 18628363e80aSGeorge Wilson } 18638363e80aSGeorge Wilson 18648363e80aSGeorge Wilson /* ARGSUSED */ 18658363e80aSGeorge Wilson static int 18668363e80aSGeorge Wilson metaslab_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 18678363e80aSGeorge Wilson { 18688363e80aSGeorge Wilson mdb_metaslab_alloc_trace_t mat; 18698363e80aSGeorge Wilson mdb_metaslab_group_t mg = { 0 }; 18708363e80aSGeorge Wilson char result_type[100]; 18718363e80aSGeorge Wilson 18728363e80aSGeorge Wilson if (mdb_ctf_vread(&mat, "metaslab_alloc_trace_t", 18738363e80aSGeorge Wilson "mdb_metaslab_alloc_trace_t", addr, 0) == -1) { 18748363e80aSGeorge Wilson return (DCMD_ERR); 18758363e80aSGeorge Wilson } 18768363e80aSGeorge Wilson 18778363e80aSGeorge Wilson if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) { 1878f78cdc34SPaul Dagnelie mdb_printf("%<u>%6s %6s %8s %11s %11s %18s %18s%</u>\n", 1879f78cdc34SPaul Dagnelie "MSID", "DVA", "ASIZE", "ALLOCATOR", "WEIGHT", "RESULT", 1880f78cdc34SPaul Dagnelie "VDEV"); 18818363e80aSGeorge Wilson } 18828363e80aSGeorge Wilson 1883892ad162SToomas Soome if (mat.mat_msp != 0) { 18848363e80aSGeorge Wilson mdb_metaslab_t ms; 18858363e80aSGeorge Wilson 18868363e80aSGeorge Wilson if (mdb_ctf_vread(&ms, "metaslab_t", "mdb_metaslab_t", 18878363e80aSGeorge Wilson mat.mat_msp, 0) == -1) { 18888363e80aSGeorge Wilson return (DCMD_ERR); 18898363e80aSGeorge Wilson } 18908363e80aSGeorge Wilson mdb_printf("%6llu ", ms.ms_id); 18918363e80aSGeorge Wilson } else { 18928363e80aSGeorge Wilson mdb_printf("%6s ", "-"); 18938363e80aSGeorge Wilson } 18948363e80aSGeorge Wilson 1895f78cdc34SPaul Dagnelie mdb_printf("%6d %8llx %11llx ", mat.mat_dva_id, mat.mat_size, 1896f78cdc34SPaul Dagnelie mat.mat_allocator); 18978363e80aSGeorge Wilson 18988363e80aSGeorge Wilson metaslab_print_weight(mat.mat_weight); 18998363e80aSGeorge Wilson 19008363e80aSGeorge Wilson if ((int64_t)mat.mat_offset < 0) { 19018363e80aSGeorge Wilson if (enum_lookup("enum trace_alloc_type", mat.mat_offset, 19028363e80aSGeorge Wilson "TRACE_", sizeof (result_type), result_type) == -1) { 19038363e80aSGeorge Wilson mdb_warn("Could not find enum for trace_alloc_type"); 19048363e80aSGeorge Wilson return (DCMD_ERR); 19058363e80aSGeorge Wilson } 19068363e80aSGeorge Wilson mdb_printf("%18s ", result_type); 19078363e80aSGeorge Wilson } else { 19088363e80aSGeorge Wilson mdb_printf("%<b>%18llx%</b> ", mat.mat_offset); 19098363e80aSGeorge Wilson } 19108363e80aSGeorge Wilson 1911892ad162SToomas Soome if (mat.mat_mg != 0 && 19128363e80aSGeorge Wilson mdb_ctf_vread(&mg, "metaslab_group_t", "mdb_metaslab_group_t", 19138363e80aSGeorge Wilson mat.mat_mg, 0) == -1) { 19148363e80aSGeorge Wilson return (DCMD_ERR); 19158363e80aSGeorge Wilson } 19168363e80aSGeorge Wilson 1917892ad162SToomas Soome if (mg.mg_vd != 0) { 19188363e80aSGeorge Wilson mdb_vdev_t vdev; 19198363e80aSGeorge Wilson char desc[MAXNAMELEN]; 19208363e80aSGeorge Wilson 19218363e80aSGeorge Wilson if (mdb_ctf_vread(&vdev, "vdev_t", "mdb_vdev_t", 19228363e80aSGeorge Wilson mg.mg_vd, 0) == -1) { 19238363e80aSGeorge Wilson return (DCMD_ERR); 19248363e80aSGeorge Wilson } 19258363e80aSGeorge Wilson 1926892ad162SToomas Soome if (vdev.vdev_path != 0) { 19278363e80aSGeorge Wilson char path[MAXNAMELEN]; 19288363e80aSGeorge Wilson 19298363e80aSGeorge Wilson if (mdb_readstr(path, sizeof (path), 19308363e80aSGeorge Wilson vdev.vdev_path) == -1) { 19318363e80aSGeorge Wilson mdb_warn("failed to read vdev_path at %p\n", 19328363e80aSGeorge Wilson vdev.vdev_path); 19338363e80aSGeorge Wilson return (DCMD_ERR); 19348363e80aSGeorge Wilson } 19358363e80aSGeorge Wilson char *slash; 19368363e80aSGeorge Wilson if ((slash = strrchr(path, '/')) != NULL) { 19378363e80aSGeorge Wilson strcpy(desc, slash + 1); 19388363e80aSGeorge Wilson } else { 19398363e80aSGeorge Wilson strcpy(desc, path); 19408363e80aSGeorge Wilson } 1941892ad162SToomas Soome } else if (vdev.vdev_ops != 0) { 19428363e80aSGeorge Wilson mdb_vdev_ops_t ops; 19438363e80aSGeorge Wilson if (mdb_ctf_vread(&ops, "vdev_ops_t", "mdb_vdev_ops_t", 19448363e80aSGeorge Wilson vdev.vdev_ops, 0) == -1) { 19458363e80aSGeorge Wilson mdb_warn("failed to read vdev_ops at %p\n", 19468363e80aSGeorge Wilson vdev.vdev_ops); 19478363e80aSGeorge Wilson return (DCMD_ERR); 19488363e80aSGeorge Wilson } 19498363e80aSGeorge Wilson (void) mdb_snprintf(desc, sizeof (desc), 19508363e80aSGeorge Wilson "%s-%llu", ops.vdev_op_type, vdev.vdev_id); 19518363e80aSGeorge Wilson } else { 19528363e80aSGeorge Wilson (void) strcpy(desc, "<unknown>"); 19538363e80aSGeorge Wilson } 19548363e80aSGeorge Wilson mdb_printf("%18s\n", desc); 19558363e80aSGeorge Wilson } 19568363e80aSGeorge Wilson 19578363e80aSGeorge Wilson return (DCMD_OK); 19588363e80aSGeorge Wilson } 19598363e80aSGeorge Wilson 19605f5f7a6fSahrens typedef struct metaslab_walk_data { 19615f5f7a6fSahrens uint64_t mw_numvdevs; 19625f5f7a6fSahrens uintptr_t *mw_vdevs; 19635f5f7a6fSahrens int mw_curvdev; 19645f5f7a6fSahrens uint64_t mw_nummss; 19655f5f7a6fSahrens uintptr_t *mw_mss; 19665f5f7a6fSahrens int mw_curms; 19675f5f7a6fSahrens } metaslab_walk_data_t; 19685f5f7a6fSahrens 19695f5f7a6fSahrens static int 19705f5f7a6fSahrens metaslab_walk_step(mdb_walk_state_t *wsp) 19715f5f7a6fSahrens { 19725f5f7a6fSahrens metaslab_walk_data_t *mw = wsp->walk_data; 19735f5f7a6fSahrens metaslab_t ms; 19745f5f7a6fSahrens uintptr_t msp; 19755f5f7a6fSahrens 19765f5f7a6fSahrens if (mw->mw_curvdev >= mw->mw_numvdevs) 19775f5f7a6fSahrens return (WALK_DONE); 19785f5f7a6fSahrens 19795f5f7a6fSahrens if (mw->mw_mss == NULL) { 19805f5f7a6fSahrens uintptr_t mssp; 19815f5f7a6fSahrens uintptr_t vdevp; 19825f5f7a6fSahrens 19835f5f7a6fSahrens ASSERT(mw->mw_curms == 0); 19845f5f7a6fSahrens ASSERT(mw->mw_nummss == 0); 19855f5f7a6fSahrens 19865f5f7a6fSahrens vdevp = mw->mw_vdevs[mw->mw_curvdev]; 198728e4da25SMatthew Ahrens if (GETMEMB(vdevp, "vdev", vdev_ms, mssp) || 198828e4da25SMatthew Ahrens GETMEMB(vdevp, "vdev", vdev_ms_count, mw->mw_nummss)) { 19895f5f7a6fSahrens return (WALK_ERR); 19905f5f7a6fSahrens } 19915f5f7a6fSahrens 19925f5f7a6fSahrens mw->mw_mss = mdb_alloc(mw->mw_nummss * sizeof (void*), 19935f5f7a6fSahrens UM_SLEEP | UM_GC); 19945f5f7a6fSahrens if (mdb_vread(mw->mw_mss, mw->mw_nummss * sizeof (void*), 19955f5f7a6fSahrens mssp) == -1) { 19965f5f7a6fSahrens mdb_warn("failed to read vdev_ms at %p", mssp); 19975f5f7a6fSahrens return (WALK_ERR); 19985f5f7a6fSahrens } 19995f5f7a6fSahrens } 20005f5f7a6fSahrens 20015f5f7a6fSahrens if (mw->mw_curms >= mw->mw_nummss) { 20025f5f7a6fSahrens mw->mw_mss = NULL; 20035f5f7a6fSahrens mw->mw_curms = 0; 20045f5f7a6fSahrens mw->mw_nummss = 0; 20055f5f7a6fSahrens mw->mw_curvdev++; 20065f5f7a6fSahrens return (WALK_NEXT); 20075f5f7a6fSahrens } 20085f5f7a6fSahrens 20095f5f7a6fSahrens msp = mw->mw_mss[mw->mw_curms]; 20105f5f7a6fSahrens if (mdb_vread(&ms, sizeof (metaslab_t), msp) == -1) { 20115f5f7a6fSahrens mdb_warn("failed to read metaslab_t at %p", msp); 20125f5f7a6fSahrens return (WALK_ERR); 20135f5f7a6fSahrens } 20145f5f7a6fSahrens 20155f5f7a6fSahrens mw->mw_curms++; 20165f5f7a6fSahrens 20175f5f7a6fSahrens return (wsp->walk_callback(msp, &ms, wsp->walk_cbdata)); 20185f5f7a6fSahrens } 20195f5f7a6fSahrens 20205f5f7a6fSahrens static int 20215f5f7a6fSahrens metaslab_walk_init(mdb_walk_state_t *wsp) 20225f5f7a6fSahrens { 20235f5f7a6fSahrens metaslab_walk_data_t *mw; 20245f5f7a6fSahrens uintptr_t root_vdevp; 20255f5f7a6fSahrens uintptr_t childp; 20265f5f7a6fSahrens 2027892ad162SToomas Soome if (wsp->walk_addr == 0) { 20285f5f7a6fSahrens mdb_warn("must supply address of spa_t\n"); 20295f5f7a6fSahrens return (WALK_ERR); 20305f5f7a6fSahrens } 20315f5f7a6fSahrens 20325f5f7a6fSahrens mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC); 20335f5f7a6fSahrens 203428e4da25SMatthew Ahrens if (GETMEMB(wsp->walk_addr, "spa", spa_root_vdev, root_vdevp) || 203528e4da25SMatthew Ahrens GETMEMB(root_vdevp, "vdev", vdev_children, mw->mw_numvdevs) || 203628e4da25SMatthew Ahrens GETMEMB(root_vdevp, "vdev", vdev_child, childp)) { 20375f5f7a6fSahrens return (DCMD_ERR); 20385f5f7a6fSahrens } 20395f5f7a6fSahrens 20405f5f7a6fSahrens mw->mw_vdevs = mdb_alloc(mw->mw_numvdevs * sizeof (void *), 20415f5f7a6fSahrens UM_SLEEP | UM_GC); 20425f5f7a6fSahrens if (mdb_vread(mw->mw_vdevs, mw->mw_numvdevs * sizeof (void *), 20435f5f7a6fSahrens childp) == -1) { 20445f5f7a6fSahrens mdb_warn("failed to read root vdev children at %p", childp); 20455f5f7a6fSahrens return (DCMD_ERR); 20465f5f7a6fSahrens } 20475f5f7a6fSahrens 20485f5f7a6fSahrens wsp->walk_data = mw; 20495f5f7a6fSahrens 20505f5f7a6fSahrens return (WALK_NEXT); 20515f5f7a6fSahrens } 20525f5f7a6fSahrens 2053fa9e4066Sahrens typedef struct mdb_spa { 2054fa9e4066Sahrens uintptr_t spa_dsl_pool; 2055fa9e4066Sahrens uintptr_t spa_root_vdev; 2056fa9e4066Sahrens } mdb_spa_t; 2057fa9e4066Sahrens 20582515f5d4SJustin T. Gibbs typedef struct mdb_dsl_pool { 20592515f5d4SJustin T. Gibbs uintptr_t dp_root_dir; 20602515f5d4SJustin T. Gibbs } mdb_dsl_pool_t; 20612515f5d4SJustin T. Gibbs 2062fa9e4066Sahrens typedef struct mdb_dsl_dir { 20632515f5d4SJustin T. Gibbs uintptr_t dd_dbuf; 2064fa9e4066Sahrens int64_t dd_space_towrite[TXG_SIZE]; 2065fa9e4066Sahrens } mdb_dsl_dir_t; 2066fa9e4066Sahrens 2067fa9e4066Sahrens typedef struct mdb_dsl_dir_phys { 2068fa9e4066Sahrens uint64_t dd_used_bytes; 2069fa9e4066Sahrens uint64_t dd_compressed_bytes; 2070fa9e4066Sahrens uint64_t dd_uncompressed_bytes; 2071fa9e4066Sahrens } mdb_dsl_dir_phys_t; 2072fa9e4066Sahrens 20735f5f7a6fSahrens typedef struct space_data { 207486714001SSerapheim Dimitropoulos uint64_t ms_allocating[TXG_SIZE]; 207586714001SSerapheim Dimitropoulos uint64_t ms_checkpointing; 207686714001SSerapheim Dimitropoulos uint64_t ms_freeing; 207786714001SSerapheim Dimitropoulos uint64_t ms_freed; 207886714001SSerapheim Dimitropoulos uint64_t ms_allocatable; 20798363e80aSGeorge Wilson int64_t ms_deferspace; 20805f5f7a6fSahrens uint64_t nowavail; 20815f5f7a6fSahrens } space_data_t; 20825f5f7a6fSahrens 20835f5f7a6fSahrens /* ARGSUSED */ 20845f5f7a6fSahrens static int 20855f5f7a6fSahrens space_cb(uintptr_t addr, const void *unknown, void *arg) 20865f5f7a6fSahrens { 20875f5f7a6fSahrens space_data_t *sd = arg; 20885f5f7a6fSahrens mdb_metaslab_t ms; 20890713e232SGeorge Wilson mdb_range_tree_t rt; 20902e4c9986SGeorge Wilson mdb_space_map_t sm = { 0 }; 20910713e232SGeorge Wilson mdb_space_map_phys_t smp = { 0 }; 20920713e232SGeorge Wilson int i; 20935f5f7a6fSahrens 20940713e232SGeorge Wilson if (mdb_ctf_vread(&ms, "metaslab_t", "mdb_metaslab_t", 20950713e232SGeorge Wilson addr, 0) == -1) 20965f5f7a6fSahrens return (WALK_ERR); 20970713e232SGeorge Wilson 20980713e232SGeorge Wilson for (i = 0; i < TXG_SIZE; i++) { 20990713e232SGeorge Wilson if (mdb_ctf_vread(&rt, "range_tree_t", 210086714001SSerapheim Dimitropoulos "mdb_range_tree_t", ms.ms_allocating[i], 0) == -1) 21012e4c9986SGeorge Wilson return (WALK_ERR); 21022e4c9986SGeorge Wilson 210386714001SSerapheim Dimitropoulos sd->ms_allocating[i] += rt.rt_space; 21040713e232SGeorge Wilson 21055f5f7a6fSahrens } 21065f5f7a6fSahrens 21070713e232SGeorge Wilson if (mdb_ctf_vread(&rt, "range_tree_t", 210886714001SSerapheim Dimitropoulos "mdb_range_tree_t", ms.ms_checkpointing, 0) == -1) 21095f145778SMatthew Ahrens return (WALK_ERR); 211086714001SSerapheim Dimitropoulos sd->ms_checkpointing += rt.rt_space; 21115f145778SMatthew Ahrens 21125f145778SMatthew Ahrens if (mdb_ctf_vread(&rt, "range_tree_t", 211386714001SSerapheim Dimitropoulos "mdb_range_tree_t", ms.ms_freeing, 0) == -1) 21145f145778SMatthew Ahrens return (WALK_ERR); 211586714001SSerapheim Dimitropoulos sd->ms_freeing += rt.rt_space; 21165f145778SMatthew Ahrens 21175f145778SMatthew Ahrens if (mdb_ctf_vread(&rt, "range_tree_t", 211886714001SSerapheim Dimitropoulos "mdb_range_tree_t", ms.ms_freed, 0) == -1) 21192e4c9986SGeorge Wilson return (WALK_ERR); 212086714001SSerapheim Dimitropoulos sd->ms_freed += rt.rt_space; 212186714001SSerapheim Dimitropoulos 212286714001SSerapheim Dimitropoulos if (mdb_ctf_vread(&rt, "range_tree_t", 212386714001SSerapheim Dimitropoulos "mdb_range_tree_t", ms.ms_allocatable, 0) == -1) 212486714001SSerapheim Dimitropoulos return (WALK_ERR); 212586714001SSerapheim Dimitropoulos sd->ms_allocatable += rt.rt_space; 21262e4c9986SGeorge Wilson 2127892ad162SToomas Soome if (ms.ms_sm != 0 && 21280713e232SGeorge Wilson mdb_ctf_vread(&sm, "space_map_t", 21290713e232SGeorge Wilson "mdb_space_map_t", ms.ms_sm, 0) == -1) 21300713e232SGeorge Wilson return (WALK_ERR); 21310713e232SGeorge Wilson 2132892ad162SToomas Soome if (sm.sm_phys != 0) { 21330713e232SGeorge Wilson (void) mdb_ctf_vread(&smp, "space_map_phys_t", 21340713e232SGeorge Wilson "mdb_space_map_phys_t", sm.sm_phys, 0); 21350713e232SGeorge Wilson } 21360713e232SGeorge Wilson 21378363e80aSGeorge Wilson sd->ms_deferspace += ms.ms_deferspace; 21380713e232SGeorge Wilson sd->nowavail += sm.sm_size - smp.smp_alloc; 21395f5f7a6fSahrens 21405f5f7a6fSahrens return (WALK_NEXT); 21415f5f7a6fSahrens } 21425f5f7a6fSahrens 2143fa9e4066Sahrens /* 2144fa9e4066Sahrens * ::spa_space [-b] 2145fa9e4066Sahrens * 2146fa9e4066Sahrens * Given a spa_t, print out it's on-disk space usage and in-core 2147fa9e4066Sahrens * estimates of future usage. If -b is given, print space in bytes. 2148fa9e4066Sahrens * Otherwise print in megabytes. 2149fa9e4066Sahrens */ 2150fa9e4066Sahrens /* ARGSUSED */ 2151fa9e4066Sahrens static int 2152fa9e4066Sahrens spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2153fa9e4066Sahrens { 2154fa9e4066Sahrens mdb_spa_t spa; 21552515f5d4SJustin T. Gibbs mdb_dsl_pool_t dp; 2156fa9e4066Sahrens mdb_dsl_dir_t dd; 21572515f5d4SJustin T. Gibbs mdb_dmu_buf_impl_t db; 2158fa9e4066Sahrens mdb_dsl_dir_phys_t dsp; 21595f5f7a6fSahrens space_data_t sd; 2160fa9e4066Sahrens int shift = 20; 2161fa9e4066Sahrens char *suffix = "M"; 216228e4da25SMatthew Ahrens int bytes = B_FALSE; 2163fa9e4066Sahrens 216428e4da25SMatthew Ahrens if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bytes, NULL) != 2165fa9e4066Sahrens argc) 2166fa9e4066Sahrens return (DCMD_USAGE); 2167fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) 2168fa9e4066Sahrens return (DCMD_USAGE); 2169fa9e4066Sahrens 217028e4da25SMatthew Ahrens if (bytes) { 2171fa9e4066Sahrens shift = 0; 2172fa9e4066Sahrens suffix = ""; 2173fa9e4066Sahrens } 2174fa9e4066Sahrens 21752515f5d4SJustin T. Gibbs if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_t", 21762515f5d4SJustin T. Gibbs addr, 0) == -1 || 21772515f5d4SJustin T. Gibbs mdb_ctf_vread(&dp, ZFS_STRUCT "dsl_pool", "mdb_dsl_pool_t", 21782515f5d4SJustin T. Gibbs spa.spa_dsl_pool, 0) == -1 || 21792515f5d4SJustin T. Gibbs mdb_ctf_vread(&dd, ZFS_STRUCT "dsl_dir", "mdb_dsl_dir_t", 21802515f5d4SJustin T. Gibbs dp.dp_root_dir, 0) == -1 || 21812515f5d4SJustin T. Gibbs mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t", 21822515f5d4SJustin T. Gibbs dd.dd_dbuf, 0) == -1 || 21832515f5d4SJustin T. Gibbs mdb_ctf_vread(&dsp, ZFS_STRUCT "dsl_dir_phys", 21842515f5d4SJustin T. Gibbs "mdb_dsl_dir_phys_t", db.db.db_data, 0) == -1) { 2185fa9e4066Sahrens return (DCMD_ERR); 2186fa9e4066Sahrens } 2187fa9e4066Sahrens 2188fa9e4066Sahrens mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n", 2189fa9e4066Sahrens dd.dd_space_towrite[0] >> shift, suffix, 2190fa9e4066Sahrens dd.dd_space_towrite[1] >> shift, suffix, 2191fa9e4066Sahrens dd.dd_space_towrite[2] >> shift, suffix, 2192fa9e4066Sahrens dd.dd_space_towrite[3] >> shift, suffix); 2193fa9e4066Sahrens 2194fa9e4066Sahrens mdb_printf("dd_phys.dd_used_bytes = %llu%s\n", 2195fa9e4066Sahrens dsp.dd_used_bytes >> shift, suffix); 2196fa9e4066Sahrens mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n", 2197fa9e4066Sahrens dsp.dd_compressed_bytes >> shift, suffix); 2198fa9e4066Sahrens mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n", 2199fa9e4066Sahrens dsp.dd_uncompressed_bytes >> shift, suffix); 2200fa9e4066Sahrens 22015f5f7a6fSahrens bzero(&sd, sizeof (sd)); 22025f5f7a6fSahrens if (mdb_pwalk("metaslab", space_cb, &sd, addr) != 0) { 22035f5f7a6fSahrens mdb_warn("can't walk metaslabs"); 2204fa9e4066Sahrens return (DCMD_ERR); 2205fa9e4066Sahrens } 2206fa9e4066Sahrens 2207fa9e4066Sahrens mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n", 220886714001SSerapheim Dimitropoulos sd.ms_allocating[0] >> shift, suffix, 220986714001SSerapheim Dimitropoulos sd.ms_allocating[1] >> shift, suffix, 221086714001SSerapheim Dimitropoulos sd.ms_allocating[2] >> shift, suffix, 221186714001SSerapheim Dimitropoulos sd.ms_allocating[3] >> shift, suffix); 221286714001SSerapheim Dimitropoulos mdb_printf("ms_checkpointing = %llu%s\n", 221386714001SSerapheim Dimitropoulos sd.ms_checkpointing >> shift, suffix); 221486714001SSerapheim Dimitropoulos mdb_printf("ms_freeing = %llu%s\n", 221586714001SSerapheim Dimitropoulos sd.ms_freeing >> shift, suffix); 221686714001SSerapheim Dimitropoulos mdb_printf("ms_freed = %llu%s\n", 221786714001SSerapheim Dimitropoulos sd.ms_freed >> shift, suffix); 221886714001SSerapheim Dimitropoulos mdb_printf("ms_allocatable = %llu%s\n", 221986714001SSerapheim Dimitropoulos sd.ms_allocatable >> shift, suffix); 22208363e80aSGeorge Wilson mdb_printf("ms_deferspace = %llu%s\n", 22218363e80aSGeorge Wilson sd.ms_deferspace >> shift, suffix); 22225f5f7a6fSahrens mdb_printf("current syncing avail = %llu%s\n", 22235f5f7a6fSahrens sd.nowavail >> shift, suffix); 2224fa9e4066Sahrens 2225fa9e4066Sahrens return (DCMD_OK); 2226fa9e4066Sahrens } 2227fa9e4066Sahrens 222822ce0148SMatthew Ahrens typedef struct mdb_spa_aux_vdev { 222922ce0148SMatthew Ahrens int sav_count; 223022ce0148SMatthew Ahrens uintptr_t sav_vdevs; 223122ce0148SMatthew Ahrens } mdb_spa_aux_vdev_t; 2232fa9e4066Sahrens 223322ce0148SMatthew Ahrens typedef struct mdb_spa_vdevs { 223422ce0148SMatthew Ahrens uintptr_t spa_root_vdev; 223522ce0148SMatthew Ahrens mdb_spa_aux_vdev_t spa_l2cache; 223622ce0148SMatthew Ahrens mdb_spa_aux_vdev_t spa_spares; 223722ce0148SMatthew Ahrens } mdb_spa_vdevs_t; 2238fa9e4066Sahrens 2239ec9f632eSEric Schrock static int 224022ce0148SMatthew Ahrens spa_print_aux(mdb_spa_aux_vdev_t *sav, uint_t flags, mdb_arg_t *v, 2241ec9f632eSEric Schrock const char *name) 2242ec9f632eSEric Schrock { 2243ec9f632eSEric Schrock uintptr_t *aux; 2244ec9f632eSEric Schrock size_t len; 2245ec9f632eSEric Schrock int ret, i; 2246ec9f632eSEric Schrock 2247ec9f632eSEric Schrock /* 2248ec9f632eSEric Schrock * Iterate over aux vdevs and print those out as well. This is a 2249ec9f632eSEric Schrock * little annoying because we don't have a root vdev to pass to ::vdev. 2250ec9f632eSEric Schrock * Instead, we print a single line and then call it for each child 2251ec9f632eSEric Schrock * vdev. 2252ec9f632eSEric Schrock */ 2253ec9f632eSEric Schrock if (sav->sav_count != 0) { 2254ec9f632eSEric Schrock v[1].a_type = MDB_TYPE_STRING; 2255ec9f632eSEric Schrock v[1].a_un.a_str = "-d"; 2256ec9f632eSEric Schrock v[2].a_type = MDB_TYPE_IMMEDIATE; 2257ec9f632eSEric Schrock v[2].a_un.a_val = 2; 2258ec9f632eSEric Schrock 2259ec9f632eSEric Schrock len = sav->sav_count * sizeof (uintptr_t); 2260ec9f632eSEric Schrock aux = mdb_alloc(len, UM_SLEEP); 226122ce0148SMatthew Ahrens if (mdb_vread(aux, len, sav->sav_vdevs) == -1) { 2262ec9f632eSEric Schrock mdb_free(aux, len); 2263ec9f632eSEric Schrock mdb_warn("failed to read l2cache vdevs at %p", 2264ec9f632eSEric Schrock sav->sav_vdevs); 2265ec9f632eSEric Schrock return (DCMD_ERR); 2266ec9f632eSEric Schrock } 2267ec9f632eSEric Schrock 2268ec9f632eSEric Schrock mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name); 2269ec9f632eSEric Schrock 2270ec9f632eSEric Schrock for (i = 0; i < sav->sav_count; i++) { 2271ec9f632eSEric Schrock ret = mdb_call_dcmd("vdev", aux[i], flags, 3, v); 2272ec9f632eSEric Schrock if (ret != DCMD_OK) { 2273ec9f632eSEric Schrock mdb_free(aux, len); 2274ec9f632eSEric Schrock return (ret); 2275ec9f632eSEric Schrock } 2276ec9f632eSEric Schrock } 2277ec9f632eSEric Schrock 2278ec9f632eSEric Schrock mdb_free(aux, len); 2279ec9f632eSEric Schrock } 2280ec9f632eSEric Schrock 2281ec9f632eSEric Schrock return (0); 2282ec9f632eSEric Schrock } 2283ec9f632eSEric Schrock 2284fa9e4066Sahrens /* 2285fa9e4066Sahrens * ::spa_vdevs 2286fa9e4066Sahrens * 2287fa9e4066Sahrens * -e Include error stats 22882e4c9986SGeorge Wilson * -m Include metaslab information 22892e4c9986SGeorge Wilson * -M Include metaslab group information 22902e4c9986SGeorge Wilson * -h Include histogram information (requires -m or -M) 2291fa9e4066Sahrens * 2292fa9e4066Sahrens * Print out a summarized list of vdevs for the given spa_t. 2293c5904d13Seschrock * This is accomplished by invoking "::vdev -re" on the root vdev, as well as 2294c5904d13Seschrock * iterating over the cache devices. 2295fa9e4066Sahrens */ 2296fa9e4066Sahrens /* ARGSUSED */ 2297fa9e4066Sahrens static int 2298fa9e4066Sahrens spa_vdevs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2299fa9e4066Sahrens { 2300c5904d13Seschrock mdb_arg_t v[3]; 2301ec9f632eSEric Schrock int ret; 23022e4c9986SGeorge Wilson char opts[100] = "-r"; 23032e4c9986SGeorge Wilson int spa_flags = 0; 2304fa9e4066Sahrens 2305fa9e4066Sahrens if (mdb_getopts(argc, argv, 23062e4c9986SGeorge Wilson 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 23072e4c9986SGeorge Wilson 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 23082e4c9986SGeorge Wilson 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 23092e4c9986SGeorge Wilson 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 2310fa9e4066Sahrens NULL) != argc) 2311fa9e4066Sahrens return (DCMD_USAGE); 2312fa9e4066Sahrens 2313fa9e4066Sahrens if (!(flags & DCMD_ADDRSPEC)) 2314fa9e4066Sahrens return (DCMD_USAGE); 2315fa9e4066Sahrens 231622ce0148SMatthew Ahrens mdb_spa_vdevs_t spa; 231722ce0148SMatthew Ahrens if (mdb_ctf_vread(&spa, "spa_t", "mdb_spa_vdevs_t", addr, 0) == -1) 2318fa9e4066Sahrens return (DCMD_ERR); 2319fa9e4066Sahrens 2320088e9d47Seschrock /* 2321088e9d47Seschrock * Unitialized spa_t structures can have a NULL root vdev. 2322088e9d47Seschrock */ 2323892ad162SToomas Soome if (spa.spa_root_vdev == 0) { 2324088e9d47Seschrock mdb_printf("no associated vdevs\n"); 2325088e9d47Seschrock return (DCMD_OK); 2326088e9d47Seschrock } 2327088e9d47Seschrock 23282e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_ERRORS) 23292e4c9986SGeorge Wilson strcat(opts, "e"); 23302e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLABS) 23312e4c9986SGeorge Wilson strcat(opts, "m"); 23322e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_METASLAB_GROUPS) 23332e4c9986SGeorge Wilson strcat(opts, "M"); 23342e4c9986SGeorge Wilson if (spa_flags & SPA_FLAG_HISTOGRAMS) 23352e4c9986SGeorge Wilson strcat(opts, "h"); 23362e4c9986SGeorge Wilson 2337c5904d13Seschrock v[0].a_type = MDB_TYPE_STRING; 23382e4c9986SGeorge Wilson v[0].a_un.a_str = opts; 2339fa9e4066Sahrens 2340c5904d13Seschrock ret = mdb_call_dcmd("vdev", (uintptr_t)spa.spa_root_vdev, 2341c5904d13Seschrock flags, 1, v); 2342c5904d13Seschrock if (ret != DCMD_OK) 2343c5904d13Seschrock return (ret); 2344c5904d13Seschrock 2345ec9f632eSEric Schrock if (spa_print_aux(&spa.spa_l2cache, flags, v, "cache") != 0 || 2346ec9f632eSEric Schrock spa_print_aux(&spa.spa_spares, flags, v, "spares") != 0) 2347c5904d13Seschrock return (DCMD_ERR); 2348c5904d13Seschrock 2349c5904d13Seschrock return (DCMD_OK); 2350fa9e4066Sahrens } 2351fa9e4066Sahrens 2352ccae0b50Seschrock /* 2353ccae0b50Seschrock * ::zio 2354ccae0b50Seschrock * 2355ccae0b50Seschrock * Print a summary of zio_t and all its children. This is intended to display a 2356ccae0b50Seschrock * zio tree, and hence we only pick the most important pieces of information for 2357ccae0b50Seschrock * the main summary. More detailed information can always be found by doing a 2358ccae0b50Seschrock * '::print zio' on the underlying zio_t. The columns we display are: 2359ccae0b50Seschrock * 2360c55e05cbSMatthew Ahrens * ADDRESS TYPE STAGE WAITER TIME_ELAPSED 2361ccae0b50Seschrock * 2362ccae0b50Seschrock * The 'address' column is indented by one space for each depth level as we 2363ccae0b50Seschrock * descend down the tree. 2364ccae0b50Seschrock */ 2365fac3008cSeschrock 2366c55e05cbSMatthew Ahrens #define ZIO_MAXINDENT 7 2367a3f829aeSBill Moore #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT) 2368a3f829aeSBill Moore #define ZIO_WALK_SELF 0 2369a3f829aeSBill Moore #define ZIO_WALK_CHILD 1 2370a3f829aeSBill Moore #define ZIO_WALK_PARENT 2 2371a3f829aeSBill Moore 2372a3f829aeSBill Moore typedef struct zio_print_args { 2373a3f829aeSBill Moore int zpa_current_depth; 2374a3f829aeSBill Moore int zpa_min_depth; 2375a3f829aeSBill Moore int zpa_max_depth; 2376a3f829aeSBill Moore int zpa_type; 2377a3f829aeSBill Moore uint_t zpa_flags; 2378a3f829aeSBill Moore } zio_print_args_t; 2379a3f829aeSBill Moore 238028e4da25SMatthew Ahrens typedef struct mdb_zio { 238128e4da25SMatthew Ahrens enum zio_type io_type; 238228e4da25SMatthew Ahrens enum zio_stage io_stage; 2383d5ee8a13SMatthew Ahrens uintptr_t io_waiter; 2384d5ee8a13SMatthew Ahrens uintptr_t io_spa; 238528e4da25SMatthew Ahrens struct { 238628e4da25SMatthew Ahrens struct { 2387d5ee8a13SMatthew Ahrens uintptr_t list_next; 238828e4da25SMatthew Ahrens } list_head; 238928e4da25SMatthew Ahrens } io_parent_list; 239028e4da25SMatthew Ahrens int io_error; 239128e4da25SMatthew Ahrens } mdb_zio_t; 239228e4da25SMatthew Ahrens 2393c55e05cbSMatthew Ahrens typedef struct mdb_zio_timestamp { 2394c55e05cbSMatthew Ahrens hrtime_t io_timestamp; 2395c55e05cbSMatthew Ahrens } mdb_zio_timestamp_t; 2396c55e05cbSMatthew Ahrens 2397a3f829aeSBill Moore static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg); 2398fac3008cSeschrock 2399ccae0b50Seschrock static int 2400c55e05cbSMatthew Ahrens zio_print_cb(uintptr_t addr, zio_print_args_t *zpa) 2401ccae0b50Seschrock { 2402ccae0b50Seschrock mdb_ctf_id_t type_enum, stage_enum; 2403a3f829aeSBill Moore int indent = zpa->zpa_current_depth; 2404ccae0b50Seschrock const char *type, *stage; 2405a3f829aeSBill Moore uintptr_t laddr; 2406c55e05cbSMatthew Ahrens mdb_zio_t zio; 2407c55e05cbSMatthew Ahrens mdb_zio_timestamp_t zio_timestamp = { 0 }; 2408c55e05cbSMatthew Ahrens 2409c55e05cbSMatthew Ahrens if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", addr, 0) == -1) 2410c55e05cbSMatthew Ahrens return (WALK_ERR); 2411c55e05cbSMatthew Ahrens (void) mdb_ctf_vread(&zio_timestamp, ZFS_STRUCT "zio", 2412c55e05cbSMatthew Ahrens "mdb_zio_timestamp_t", addr, MDB_CTF_VREAD_QUIET); 2413ccae0b50Seschrock 2414a3f829aeSBill Moore if (indent > ZIO_MAXINDENT) 2415a3f829aeSBill Moore indent = ZIO_MAXINDENT; 2416ccae0b50Seschrock 2417ccae0b50Seschrock if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum) == -1 || 2418ccae0b50Seschrock mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum) == -1) { 2419ccae0b50Seschrock mdb_warn("failed to lookup zio enums"); 2420ccae0b50Seschrock return (WALK_ERR); 2421ccae0b50Seschrock } 2422ccae0b50Seschrock 2423c55e05cbSMatthew Ahrens if ((type = mdb_ctf_enum_name(type_enum, zio.io_type)) != NULL) 2424ccae0b50Seschrock type += sizeof ("ZIO_TYPE_") - 1; 2425ccae0b50Seschrock else 2426ccae0b50Seschrock type = "?"; 2427ccae0b50Seschrock 2428c55e05cbSMatthew Ahrens if (zio.io_error == 0) { 2429c55e05cbSMatthew Ahrens stage = mdb_ctf_enum_name(stage_enum, zio.io_stage); 243028e4da25SMatthew Ahrens if (stage != NULL) 2431ccae0b50Seschrock stage += sizeof ("ZIO_STAGE_") - 1; 2432ccae0b50Seschrock else 2433ccae0b50Seschrock stage = "?"; 243428e4da25SMatthew Ahrens } else { 243528e4da25SMatthew Ahrens stage = "FAILED"; 243628e4da25SMatthew Ahrens } 2437ccae0b50Seschrock 2438a3f829aeSBill Moore if (zpa->zpa_current_depth >= zpa->zpa_min_depth) { 2439a3f829aeSBill Moore if (zpa->zpa_flags & DCMD_PIPE_OUT) { 2440a3f829aeSBill Moore mdb_printf("%?p\n", addr); 2441a3f829aeSBill Moore } else { 2442a3f829aeSBill Moore mdb_printf("%*s%-*p %-5s %-16s ", indent, "", 2443a3f829aeSBill Moore ZIO_MAXWIDTH - indent, addr, type, stage); 2444d5ee8a13SMatthew Ahrens if (zio.io_waiter != 0) 2445d5ee8a13SMatthew Ahrens mdb_printf("%-16lx ", zio.io_waiter); 2446ccae0b50Seschrock else 2447c55e05cbSMatthew Ahrens mdb_printf("%-16s ", "-"); 2448c55e05cbSMatthew Ahrens #ifdef _KERNEL 2449c55e05cbSMatthew Ahrens if (zio_timestamp.io_timestamp != 0) { 2450c55e05cbSMatthew Ahrens mdb_printf("%llums", (mdb_gethrtime() - 2451c55e05cbSMatthew Ahrens zio_timestamp.io_timestamp) / 2452c55e05cbSMatthew Ahrens 1000000); 2453c55e05cbSMatthew Ahrens } else { 2454c55e05cbSMatthew Ahrens mdb_printf("%-12s ", "-"); 2455c55e05cbSMatthew Ahrens } 2456c55e05cbSMatthew Ahrens #else 2457c55e05cbSMatthew Ahrens mdb_printf("%-12s ", "-"); 2458c55e05cbSMatthew Ahrens #endif 2459c55e05cbSMatthew Ahrens mdb_printf("\n"); 2460a3f829aeSBill Moore } 2461a3f829aeSBill Moore } 2462ccae0b50Seschrock 2463a3f829aeSBill Moore if (zpa->zpa_current_depth >= zpa->zpa_max_depth) 2464a3f829aeSBill Moore return (WALK_NEXT); 2465a3f829aeSBill Moore 2466a3f829aeSBill Moore if (zpa->zpa_type == ZIO_WALK_PARENT) 246728e4da25SMatthew Ahrens laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", 246828e4da25SMatthew Ahrens "io_parent_list"); 2469a3f829aeSBill Moore else 247028e4da25SMatthew Ahrens laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", 247128e4da25SMatthew Ahrens "io_child_list"); 2472a3f829aeSBill Moore 2473a3f829aeSBill Moore zpa->zpa_current_depth++; 2474a3f829aeSBill Moore if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) { 2475a3f829aeSBill Moore mdb_warn("failed to walk zio_t children at %p\n", laddr); 2476a3f829aeSBill Moore return (WALK_ERR); 2477a3f829aeSBill Moore } 2478a3f829aeSBill Moore zpa->zpa_current_depth--; 2479a3f829aeSBill Moore 2480a3f829aeSBill Moore return (WALK_NEXT); 2481a3f829aeSBill Moore } 2482a3f829aeSBill Moore 2483a3f829aeSBill Moore /* ARGSUSED */ 2484a3f829aeSBill Moore static int 2485a3f829aeSBill Moore zio_child_cb(uintptr_t addr, const void *unknown, void *arg) 2486a3f829aeSBill Moore { 2487a3f829aeSBill Moore zio_link_t zl; 2488a3f829aeSBill Moore uintptr_t ziop; 2489a3f829aeSBill Moore zio_print_args_t *zpa = arg; 2490a3f829aeSBill Moore 2491a3f829aeSBill Moore if (mdb_vread(&zl, sizeof (zl), addr) == -1) { 2492a3f829aeSBill Moore mdb_warn("failed to read zio_link_t at %p", addr); 2493ccae0b50Seschrock return (WALK_ERR); 2494ccae0b50Seschrock } 2495ccae0b50Seschrock 2496a3f829aeSBill Moore if (zpa->zpa_type == ZIO_WALK_PARENT) 2497a3f829aeSBill Moore ziop = (uintptr_t)zl.zl_parent; 2498a3f829aeSBill Moore else 2499a3f829aeSBill Moore ziop = (uintptr_t)zl.zl_child; 2500a3f829aeSBill Moore 250169962b56SMatthew Ahrens return (zio_print_cb(ziop, zpa)); 2502ccae0b50Seschrock } 2503ccae0b50Seschrock 2504ccae0b50Seschrock /* ARGSUSED */ 2505ccae0b50Seschrock static int 2506ccae0b50Seschrock zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2507ccae0b50Seschrock { 2508a3f829aeSBill Moore zio_print_args_t zpa = { 0 }; 2509ccae0b50Seschrock 2510ccae0b50Seschrock if (!(flags & DCMD_ADDRSPEC)) 2511ccae0b50Seschrock return (DCMD_USAGE); 2512ccae0b50Seschrock 2513a3f829aeSBill Moore if (mdb_getopts(argc, argv, 2514a3f829aeSBill Moore 'r', MDB_OPT_SETBITS, INT_MAX, &zpa.zpa_max_depth, 2515a3f829aeSBill Moore 'c', MDB_OPT_SETBITS, ZIO_WALK_CHILD, &zpa.zpa_type, 2516a3f829aeSBill Moore 'p', MDB_OPT_SETBITS, ZIO_WALK_PARENT, &zpa.zpa_type, 2517a3f829aeSBill Moore NULL) != argc) 2518a3f829aeSBill Moore return (DCMD_USAGE); 2519a3f829aeSBill Moore 2520a3f829aeSBill Moore zpa.zpa_flags = flags; 2521a3f829aeSBill Moore if (zpa.zpa_max_depth != 0) { 2522a3f829aeSBill Moore if (zpa.zpa_type == ZIO_WALK_SELF) 2523a3f829aeSBill Moore zpa.zpa_type = ZIO_WALK_CHILD; 2524a3f829aeSBill Moore } else if (zpa.zpa_type != ZIO_WALK_SELF) { 2525a3f829aeSBill Moore zpa.zpa_min_depth = 1; 2526a3f829aeSBill Moore zpa.zpa_max_depth = 1; 2527a3f829aeSBill Moore } 2528a3f829aeSBill Moore 2529c55e05cbSMatthew Ahrens if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) { 2530c55e05cbSMatthew Ahrens mdb_printf("%<u>%-*s %-5s %-16s %-16s %-12s%</u>\n", 2531c55e05cbSMatthew Ahrens ZIO_MAXWIDTH, "ADDRESS", "TYPE", "STAGE", "WAITER", 2532c55e05cbSMatthew Ahrens "TIME_ELAPSED"); 2533c55e05cbSMatthew Ahrens } 2534ccae0b50Seschrock 2535c55e05cbSMatthew Ahrens if (zio_print_cb(addr, &zpa) != WALK_NEXT) 2536ccae0b50Seschrock return (DCMD_ERR); 2537ccae0b50Seschrock 2538ccae0b50Seschrock return (DCMD_OK); 2539ccae0b50Seschrock } 2540ccae0b50Seschrock 2541ccae0b50Seschrock /* 2542ccae0b50Seschrock * [addr]::zio_state 2543ccae0b50Seschrock * 2544ccae0b50Seschrock * Print a summary of all zio_t structures on the system, or for a particular 2545ccae0b50Seschrock * pool. This is equivalent to '::walk zio_root | ::zio'. 2546ccae0b50Seschrock */ 2547ccae0b50Seschrock /*ARGSUSED*/ 2548ccae0b50Seschrock static int 2549ccae0b50Seschrock zio_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2550ccae0b50Seschrock { 2551ccae0b50Seschrock /* 2552ccae0b50Seschrock * MDB will remember the last address of the pipeline, so if we don't 2553ccae0b50Seschrock * zero this we'll end up trying to walk zio structures for a 2554ccae0b50Seschrock * non-existent spa_t. 2555ccae0b50Seschrock */ 2556ccae0b50Seschrock if (!(flags & DCMD_ADDRSPEC)) 2557ccae0b50Seschrock addr = 0; 2558ccae0b50Seschrock 2559ccae0b50Seschrock return (mdb_pwalk_dcmd("zio_root", "zio", argc, argv, addr)); 2560ccae0b50Seschrock } 2561ccae0b50Seschrock 2562dcbf3bd6SGeorge Wilson typedef struct mdb_multilist { 2563dcbf3bd6SGeorge Wilson uint64_t ml_num_sublists; 2564dcbf3bd6SGeorge Wilson uintptr_t ml_sublists; 2565dcbf3bd6SGeorge Wilson } mdb_multilist_t; 2566dcbf3bd6SGeorge Wilson 2567dcbf3bd6SGeorge Wilson typedef struct multilist_walk_data { 2568dcbf3bd6SGeorge Wilson uint64_t mwd_idx; 2569dcbf3bd6SGeorge Wilson mdb_multilist_t mwd_ml; 2570dcbf3bd6SGeorge Wilson } multilist_walk_data_t; 2571dcbf3bd6SGeorge Wilson 2572dcbf3bd6SGeorge Wilson /* ARGSUSED */ 2573dcbf3bd6SGeorge Wilson static int 2574dcbf3bd6SGeorge Wilson multilist_print_cb(uintptr_t addr, const void *unknown, void *arg) 2575dcbf3bd6SGeorge Wilson { 2576dcbf3bd6SGeorge Wilson mdb_printf("%#lr\n", addr); 2577dcbf3bd6SGeorge Wilson return (WALK_NEXT); 2578dcbf3bd6SGeorge Wilson } 2579dcbf3bd6SGeorge Wilson 2580dcbf3bd6SGeorge Wilson static int 2581dcbf3bd6SGeorge Wilson multilist_walk_step(mdb_walk_state_t *wsp) 2582dcbf3bd6SGeorge Wilson { 2583dcbf3bd6SGeorge Wilson multilist_walk_data_t *mwd = wsp->walk_data; 2584dcbf3bd6SGeorge Wilson 2585dcbf3bd6SGeorge Wilson if (mwd->mwd_idx >= mwd->mwd_ml.ml_num_sublists) 2586dcbf3bd6SGeorge Wilson return (WALK_DONE); 2587dcbf3bd6SGeorge Wilson 2588dcbf3bd6SGeorge Wilson wsp->walk_addr = mwd->mwd_ml.ml_sublists + 2589dcbf3bd6SGeorge Wilson mdb_ctf_sizeof_by_name("multilist_sublist_t") * mwd->mwd_idx + 2590dcbf3bd6SGeorge Wilson mdb_ctf_offsetof_by_name("multilist_sublist_t", "mls_list"); 2591dcbf3bd6SGeorge Wilson 2592dcbf3bd6SGeorge Wilson mdb_pwalk("list", multilist_print_cb, (void*)NULL, wsp->walk_addr); 2593dcbf3bd6SGeorge Wilson mwd->mwd_idx++; 2594dcbf3bd6SGeorge Wilson 2595dcbf3bd6SGeorge Wilson return (WALK_NEXT); 2596dcbf3bd6SGeorge Wilson } 2597dcbf3bd6SGeorge Wilson 2598dcbf3bd6SGeorge Wilson static int 2599dcbf3bd6SGeorge Wilson multilist_walk_init(mdb_walk_state_t *wsp) 2600dcbf3bd6SGeorge Wilson { 2601dcbf3bd6SGeorge Wilson multilist_walk_data_t *mwd; 2602dcbf3bd6SGeorge Wilson 2603892ad162SToomas Soome if (wsp->walk_addr == 0) { 2604dcbf3bd6SGeorge Wilson mdb_warn("must supply address of multilist_t\n"); 2605dcbf3bd6SGeorge Wilson return (WALK_ERR); 2606dcbf3bd6SGeorge Wilson } 2607dcbf3bd6SGeorge Wilson 2608dcbf3bd6SGeorge Wilson mwd = mdb_zalloc(sizeof (multilist_walk_data_t), UM_SLEEP | UM_GC); 2609dcbf3bd6SGeorge Wilson if (mdb_ctf_vread(&mwd->mwd_ml, "multilist_t", "mdb_multilist_t", 2610dcbf3bd6SGeorge Wilson wsp->walk_addr, 0) == -1) { 2611dcbf3bd6SGeorge Wilson return (WALK_ERR); 2612dcbf3bd6SGeorge Wilson } 2613dcbf3bd6SGeorge Wilson 2614dcbf3bd6SGeorge Wilson if (mwd->mwd_ml.ml_num_sublists == 0 || 2615892ad162SToomas Soome mwd->mwd_ml.ml_sublists == 0) { 2616dcbf3bd6SGeorge Wilson mdb_warn("invalid or uninitialized multilist at %#lx\n", 2617dcbf3bd6SGeorge Wilson wsp->walk_addr); 2618dcbf3bd6SGeorge Wilson return (WALK_ERR); 2619dcbf3bd6SGeorge Wilson } 2620dcbf3bd6SGeorge Wilson 2621dcbf3bd6SGeorge Wilson wsp->walk_data = mwd; 2622dcbf3bd6SGeorge Wilson return (WALK_NEXT); 2623dcbf3bd6SGeorge Wilson } 2624dcbf3bd6SGeorge Wilson 26251393933cSJason King typedef struct mdb_txg_list { 26261393933cSJason King size_t tl_offset; 26271393933cSJason King uintptr_t tl_head[TXG_SIZE]; 26281393933cSJason King } mdb_txg_list_t; 26291393933cSJason King 2630fa9e4066Sahrens typedef struct txg_list_walk_data { 2631fa9e4066Sahrens uintptr_t lw_head[TXG_SIZE]; 2632fa9e4066Sahrens int lw_txgoff; 2633fa9e4066Sahrens int lw_maxoff; 2634fa9e4066Sahrens size_t lw_offset; 2635fa9e4066Sahrens void *lw_obj; 2636fa9e4066Sahrens } txg_list_walk_data_t; 2637fa9e4066Sahrens 2638fa9e4066Sahrens static int 2639fa9e4066Sahrens txg_list_walk_init_common(mdb_walk_state_t *wsp, int txg, int maxoff) 2640fa9e4066Sahrens { 2641fa9e4066Sahrens txg_list_walk_data_t *lwd; 26421393933cSJason King mdb_txg_list_t list; 2643fa9e4066Sahrens int i; 2644fa9e4066Sahrens 2645fa9e4066Sahrens lwd = mdb_alloc(sizeof (txg_list_walk_data_t), UM_SLEEP | UM_GC); 26461393933cSJason King if (mdb_ctf_vread(&list, "txg_list_t", "mdb_txg_list_t", wsp->walk_addr, 26471393933cSJason King 0) == -1) { 2648fa9e4066Sahrens mdb_warn("failed to read txg_list_t at %#lx", wsp->walk_addr); 2649fa9e4066Sahrens return (WALK_ERR); 2650fa9e4066Sahrens } 2651fa9e4066Sahrens 2652fa9e4066Sahrens for (i = 0; i < TXG_SIZE; i++) 26531393933cSJason King lwd->lw_head[i] = list.tl_head[i]; 2654fa9e4066Sahrens lwd->lw_offset = list.tl_offset; 2655fa9e4066Sahrens lwd->lw_obj = mdb_alloc(lwd->lw_offset + sizeof (txg_node_t), 2656fa9e4066Sahrens UM_SLEEP | UM_GC); 2657fa9e4066Sahrens lwd->lw_txgoff = txg; 2658fa9e4066Sahrens lwd->lw_maxoff = maxoff; 2659fa9e4066Sahrens 2660fa9e4066Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 2661fa9e4066Sahrens wsp->walk_data = lwd; 2662fa9e4066Sahrens 2663fa9e4066Sahrens return (WALK_NEXT); 2664fa9e4066Sahrens } 2665fa9e4066Sahrens 2666fa9e4066Sahrens static int 2667fa9e4066Sahrens txg_list_walk_init(mdb_walk_state_t *wsp) 2668fa9e4066Sahrens { 2669fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 0, TXG_SIZE-1)); 2670fa9e4066Sahrens } 2671fa9e4066Sahrens 2672fa9e4066Sahrens static int 2673fa9e4066Sahrens txg_list0_walk_init(mdb_walk_state_t *wsp) 2674fa9e4066Sahrens { 2675fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 0, 0)); 2676fa9e4066Sahrens } 2677fa9e4066Sahrens 2678fa9e4066Sahrens static int 2679fa9e4066Sahrens txg_list1_walk_init(mdb_walk_state_t *wsp) 2680fa9e4066Sahrens { 2681fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 1, 1)); 2682fa9e4066Sahrens } 2683fa9e4066Sahrens 2684fa9e4066Sahrens static int 2685fa9e4066Sahrens txg_list2_walk_init(mdb_walk_state_t *wsp) 2686fa9e4066Sahrens { 2687fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 2, 2)); 2688fa9e4066Sahrens } 2689fa9e4066Sahrens 2690fa9e4066Sahrens static int 2691fa9e4066Sahrens txg_list3_walk_init(mdb_walk_state_t *wsp) 2692fa9e4066Sahrens { 2693fa9e4066Sahrens return (txg_list_walk_init_common(wsp, 3, 3)); 2694fa9e4066Sahrens } 2695fa9e4066Sahrens 2696fa9e4066Sahrens static int 2697fa9e4066Sahrens txg_list_walk_step(mdb_walk_state_t *wsp) 2698fa9e4066Sahrens { 2699fa9e4066Sahrens txg_list_walk_data_t *lwd = wsp->walk_data; 2700fa9e4066Sahrens uintptr_t addr; 2701fa9e4066Sahrens txg_node_t *node; 2702fa9e4066Sahrens int status; 2703fa9e4066Sahrens 2704892ad162SToomas Soome while (wsp->walk_addr == 0 && lwd->lw_txgoff < lwd->lw_maxoff) { 2705fa9e4066Sahrens lwd->lw_txgoff++; 2706fa9e4066Sahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 2707fa9e4066Sahrens } 2708fa9e4066Sahrens 2709892ad162SToomas Soome if (wsp->walk_addr == 0) 2710fa9e4066Sahrens return (WALK_DONE); 2711fa9e4066Sahrens 2712fa9e4066Sahrens addr = wsp->walk_addr - lwd->lw_offset; 2713fa9e4066Sahrens 2714fa9e4066Sahrens if (mdb_vread(lwd->lw_obj, 2715fa9e4066Sahrens lwd->lw_offset + sizeof (txg_node_t), addr) == -1) { 2716fa9e4066Sahrens mdb_warn("failed to read list element at %#lx", addr); 2717fa9e4066Sahrens return (WALK_ERR); 2718fa9e4066Sahrens } 2719fa9e4066Sahrens 2720fa9e4066Sahrens status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata); 2721fa9e4066Sahrens node = (txg_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset); 2722fa9e4066Sahrens wsp->walk_addr = (uintptr_t)node->tn_next[lwd->lw_txgoff]; 2723fa9e4066Sahrens 2724fa9e4066Sahrens return (status); 2725fa9e4066Sahrens } 2726fa9e4066Sahrens 2727fa9e4066Sahrens /* 2728fa9e4066Sahrens * ::walk spa 2729fa9e4066Sahrens * 2730fa9e4066Sahrens * Walk all named spa_t structures in the namespace. This is nothing more than 2731fa9e4066Sahrens * a layered avl walk. 2732fa9e4066Sahrens */ 2733fa9e4066Sahrens static int 2734fa9e4066Sahrens spa_walk_init(mdb_walk_state_t *wsp) 2735fa9e4066Sahrens { 2736fa9e4066Sahrens GElf_Sym sym; 2737fa9e4066Sahrens 2738892ad162SToomas Soome if (wsp->walk_addr != 0) { 2739fa9e4066Sahrens mdb_warn("spa walk only supports global walks\n"); 2740fa9e4066Sahrens return (WALK_ERR); 2741fa9e4066Sahrens } 2742fa9e4066Sahrens 2743fa9e4066Sahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "spa_namespace_avl", &sym) == -1) { 2744fa9e4066Sahrens mdb_warn("failed to find symbol 'spa_namespace_avl'"); 2745fa9e4066Sahrens return (WALK_ERR); 2746fa9e4066Sahrens } 2747fa9e4066Sahrens 2748fa9e4066Sahrens wsp->walk_addr = (uintptr_t)sym.st_value; 2749fa9e4066Sahrens 2750fa9e4066Sahrens if (mdb_layered_walk("avl", wsp) == -1) { 2751fa9e4066Sahrens mdb_warn("failed to walk 'avl'\n"); 2752fa9e4066Sahrens return (WALK_ERR); 2753fa9e4066Sahrens } 2754fa9e4066Sahrens 2755fa9e4066Sahrens return (WALK_NEXT); 2756fa9e4066Sahrens } 2757fa9e4066Sahrens 2758fa9e4066Sahrens static int 2759fa9e4066Sahrens spa_walk_step(mdb_walk_state_t *wsp) 2760fa9e4066Sahrens { 276122ce0148SMatthew Ahrens return (wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata)); 2762fa9e4066Sahrens } 2763fa9e4066Sahrens 2764fa9e4066Sahrens /* 2765ccae0b50Seschrock * [addr]::walk zio 2766ccae0b50Seschrock * 2767ccae0b50Seschrock * Walk all active zio_t structures on the system. This is simply a layered 2768ccae0b50Seschrock * walk on top of ::walk zio_cache, with the optional ability to limit the 2769ccae0b50Seschrock * structures to a particular pool. 2770ccae0b50Seschrock */ 2771ccae0b50Seschrock static int 2772ccae0b50Seschrock zio_walk_init(mdb_walk_state_t *wsp) 2773ccae0b50Seschrock { 2774dee140dfSMatthew Ahrens wsp->walk_data = (void *)wsp->walk_addr; 2775ccae0b50Seschrock 2776ccae0b50Seschrock if (mdb_layered_walk("zio_cache", wsp) == -1) { 2777ccae0b50Seschrock mdb_warn("failed to walk 'zio_cache'\n"); 2778ccae0b50Seschrock return (WALK_ERR); 2779ccae0b50Seschrock } 2780ccae0b50Seschrock 2781ccae0b50Seschrock return (WALK_NEXT); 2782ccae0b50Seschrock } 2783ccae0b50Seschrock 2784ccae0b50Seschrock static int 2785ccae0b50Seschrock zio_walk_step(mdb_walk_state_t *wsp) 2786ccae0b50Seschrock { 278728e4da25SMatthew Ahrens mdb_zio_t zio; 2788dee140dfSMatthew Ahrens uintptr_t spa = (uintptr_t)wsp->walk_data; 2789ccae0b50Seschrock 279028e4da25SMatthew Ahrens if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", 279128e4da25SMatthew Ahrens wsp->walk_addr, 0) == -1) 2792ccae0b50Seschrock return (WALK_ERR); 2793ccae0b50Seschrock 2794dee140dfSMatthew Ahrens if (spa != 0 && spa != zio.io_spa) 2795ccae0b50Seschrock return (WALK_NEXT); 2796ccae0b50Seschrock 2797ccae0b50Seschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 2798ccae0b50Seschrock } 2799ccae0b50Seschrock 2800ccae0b50Seschrock /* 2801ccae0b50Seschrock * [addr]::walk zio_root 2802ccae0b50Seschrock * 2803ccae0b50Seschrock * Walk only root zio_t structures, optionally for a particular spa_t. 2804ccae0b50Seschrock */ 2805ccae0b50Seschrock static int 2806ccae0b50Seschrock zio_walk_root_step(mdb_walk_state_t *wsp) 2807ccae0b50Seschrock { 280828e4da25SMatthew Ahrens mdb_zio_t zio; 2809dee140dfSMatthew Ahrens uintptr_t spa = (uintptr_t)wsp->walk_data; 2810ccae0b50Seschrock 281128e4da25SMatthew Ahrens if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", 281228e4da25SMatthew Ahrens wsp->walk_addr, 0) == -1) 2813ccae0b50Seschrock return (WALK_ERR); 2814ccae0b50Seschrock 2815dee140dfSMatthew Ahrens if (spa != 0 && spa != zio.io_spa) 2816ccae0b50Seschrock return (WALK_NEXT); 2817ccae0b50Seschrock 2818a3f829aeSBill Moore /* If the parent list is not empty, ignore */ 2819d5ee8a13SMatthew Ahrens if (zio.io_parent_list.list_head.list_next != 282028e4da25SMatthew Ahrens wsp->walk_addr + 282128e4da25SMatthew Ahrens mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", "io_parent_list") + 282228e4da25SMatthew Ahrens mdb_ctf_offsetof_by_name("struct list", "list_head")) 2823ccae0b50Seschrock return (WALK_NEXT); 2824ccae0b50Seschrock 2825ccae0b50Seschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 2826ccae0b50Seschrock } 2827ccae0b50Seschrock 282888b7b0f2SMatthew Ahrens /* 282988b7b0f2SMatthew Ahrens * ::zfs_blkstats 283088b7b0f2SMatthew Ahrens * 283188b7b0f2SMatthew Ahrens * -v print verbose per-level information 283288b7b0f2SMatthew Ahrens * 283388b7b0f2SMatthew Ahrens */ 283488b7b0f2SMatthew Ahrens static int 283588b7b0f2SMatthew Ahrens zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 283688b7b0f2SMatthew Ahrens { 283788b7b0f2SMatthew Ahrens boolean_t verbose = B_FALSE; 283888b7b0f2SMatthew Ahrens zfs_all_blkstats_t stats; 283988b7b0f2SMatthew Ahrens dmu_object_type_t t; 284088b7b0f2SMatthew Ahrens zfs_blkstat_t *tzb; 284188b7b0f2SMatthew Ahrens uint64_t ditto; 284288b7b0f2SMatthew Ahrens dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10]; 284388b7b0f2SMatthew Ahrens /* +10 in case it grew */ 284488b7b0f2SMatthew Ahrens 284588b7b0f2SMatthew Ahrens if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) { 284688b7b0f2SMatthew Ahrens mdb_warn("failed to read 'dmu_ot'"); 284788b7b0f2SMatthew Ahrens return (DCMD_ERR); 284888b7b0f2SMatthew Ahrens } 284988b7b0f2SMatthew Ahrens 285088b7b0f2SMatthew Ahrens if (mdb_getopts(argc, argv, 285188b7b0f2SMatthew Ahrens 'v', MDB_OPT_SETBITS, TRUE, &verbose, 285288b7b0f2SMatthew Ahrens NULL) != argc) 285388b7b0f2SMatthew Ahrens return (DCMD_USAGE); 285488b7b0f2SMatthew Ahrens 285588b7b0f2SMatthew Ahrens if (!(flags & DCMD_ADDRSPEC)) 285688b7b0f2SMatthew Ahrens return (DCMD_USAGE); 285788b7b0f2SMatthew Ahrens 285828e4da25SMatthew Ahrens if (GETMEMB(addr, "spa", spa_dsl_pool, addr) || 285928e4da25SMatthew Ahrens GETMEMB(addr, "dsl_pool", dp_blkstats, addr) || 286088b7b0f2SMatthew Ahrens mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) { 286188b7b0f2SMatthew Ahrens mdb_warn("failed to read data at %p;", addr); 286288b7b0f2SMatthew Ahrens mdb_printf("maybe no stats? run \"zpool scrub\" first."); 286388b7b0f2SMatthew Ahrens return (DCMD_ERR); 286488b7b0f2SMatthew Ahrens } 286588b7b0f2SMatthew Ahrens 2866ad135b5dSChristopher Siden tzb = &stats.zab_type[DN_MAX_LEVELS][DMU_OT_TOTAL]; 286788b7b0f2SMatthew Ahrens if (tzb->zb_gangs != 0) { 286888b7b0f2SMatthew Ahrens mdb_printf("Ganged blocks: %llu\n", 286988b7b0f2SMatthew Ahrens (longlong_t)tzb->zb_gangs); 287088b7b0f2SMatthew Ahrens } 287188b7b0f2SMatthew Ahrens 287288b7b0f2SMatthew Ahrens ditto = tzb->zb_ditto_2_of_2_samevdev + tzb->zb_ditto_2_of_3_samevdev + 287388b7b0f2SMatthew Ahrens tzb->zb_ditto_3_of_3_samevdev; 287488b7b0f2SMatthew Ahrens if (ditto != 0) { 287588b7b0f2SMatthew Ahrens mdb_printf("Dittoed blocks on same vdev: %llu\n", 287688b7b0f2SMatthew Ahrens (longlong_t)ditto); 287788b7b0f2SMatthew Ahrens } 287888b7b0f2SMatthew Ahrens 287988b7b0f2SMatthew Ahrens mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 288088b7b0f2SMatthew Ahrens "\t avg\t comp\t%%Total\tType\n"); 288188b7b0f2SMatthew Ahrens 2882ad135b5dSChristopher Siden for (t = 0; t <= DMU_OT_TOTAL; t++) { 2883d70f65dfSToomas Soome char csize[MDB_NICENUM_BUFLEN], lsize[MDB_NICENUM_BUFLEN]; 2884d70f65dfSToomas Soome char psize[MDB_NICENUM_BUFLEN], asize[MDB_NICENUM_BUFLEN]; 2885d70f65dfSToomas Soome char avg[MDB_NICENUM_BUFLEN]; 2886d70f65dfSToomas Soome char comp[MDB_NICENUM_BUFLEN], pct[MDB_NICENUM_BUFLEN]; 288788b7b0f2SMatthew Ahrens char typename[64]; 288888b7b0f2SMatthew Ahrens int l; 288988b7b0f2SMatthew Ahrens 289088b7b0f2SMatthew Ahrens 289188b7b0f2SMatthew Ahrens if (t == DMU_OT_DEFERRED) 289288b7b0f2SMatthew Ahrens strcpy(typename, "deferred free"); 2893ad135b5dSChristopher Siden else if (t == DMU_OT_OTHER) 2894ad135b5dSChristopher Siden strcpy(typename, "other"); 289588b7b0f2SMatthew Ahrens else if (t == DMU_OT_TOTAL) 289688b7b0f2SMatthew Ahrens strcpy(typename, "Total"); 289788b7b0f2SMatthew Ahrens else if (mdb_readstr(typename, sizeof (typename), 289888b7b0f2SMatthew Ahrens (uintptr_t)dmu_ot[t].ot_name) == -1) { 289988b7b0f2SMatthew Ahrens mdb_warn("failed to read type name"); 290088b7b0f2SMatthew Ahrens return (DCMD_ERR); 290188b7b0f2SMatthew Ahrens } 290288b7b0f2SMatthew Ahrens 290388b7b0f2SMatthew Ahrens if (stats.zab_type[DN_MAX_LEVELS][t].zb_asize == 0) 290488b7b0f2SMatthew Ahrens continue; 290588b7b0f2SMatthew Ahrens 290688b7b0f2SMatthew Ahrens for (l = -1; l < DN_MAX_LEVELS; l++) { 290788b7b0f2SMatthew Ahrens int level = (l == -1 ? DN_MAX_LEVELS : l); 290888b7b0f2SMatthew Ahrens zfs_blkstat_t *zb = &stats.zab_type[level][t]; 290988b7b0f2SMatthew Ahrens 291088b7b0f2SMatthew Ahrens if (zb->zb_asize == 0) 291188b7b0f2SMatthew Ahrens continue; 291288b7b0f2SMatthew Ahrens 291388b7b0f2SMatthew Ahrens /* 291488b7b0f2SMatthew Ahrens * Don't print each level unless requested. 291588b7b0f2SMatthew Ahrens */ 291688b7b0f2SMatthew Ahrens if (!verbose && level != DN_MAX_LEVELS) 291788b7b0f2SMatthew Ahrens continue; 291888b7b0f2SMatthew Ahrens 291988b7b0f2SMatthew Ahrens /* 292088b7b0f2SMatthew Ahrens * If all the space is level 0, don't print the 292188b7b0f2SMatthew Ahrens * level 0 separately. 292288b7b0f2SMatthew Ahrens */ 292388b7b0f2SMatthew Ahrens if (level == 0 && zb->zb_asize == 292488b7b0f2SMatthew Ahrens stats.zab_type[DN_MAX_LEVELS][t].zb_asize) 292588b7b0f2SMatthew Ahrens continue; 292688b7b0f2SMatthew Ahrens 292788b7b0f2SMatthew Ahrens mdb_nicenum(zb->zb_count, csize); 292888b7b0f2SMatthew Ahrens mdb_nicenum(zb->zb_lsize, lsize); 292988b7b0f2SMatthew Ahrens mdb_nicenum(zb->zb_psize, psize); 293088b7b0f2SMatthew Ahrens mdb_nicenum(zb->zb_asize, asize); 293188b7b0f2SMatthew Ahrens mdb_nicenum(zb->zb_asize / zb->zb_count, avg); 2932d70f65dfSToomas Soome (void) mdb_snprintfrac(comp, MDB_NICENUM_BUFLEN, 2933ff64c0f7SMatthew Ahrens zb->zb_lsize, zb->zb_psize, 2); 2934d70f65dfSToomas Soome (void) mdb_snprintfrac(pct, MDB_NICENUM_BUFLEN, 2935ff64c0f7SMatthew Ahrens 100 * zb->zb_asize, tzb->zb_asize, 2); 293688b7b0f2SMatthew Ahrens 293788b7b0f2SMatthew Ahrens mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s" 293888b7b0f2SMatthew Ahrens "\t%5s\t%6s\t", 293988b7b0f2SMatthew Ahrens csize, lsize, psize, asize, avg, comp, pct); 294088b7b0f2SMatthew Ahrens 294188b7b0f2SMatthew Ahrens if (level == DN_MAX_LEVELS) 294288b7b0f2SMatthew Ahrens mdb_printf("%s\n", typename); 294388b7b0f2SMatthew Ahrens else 294488b7b0f2SMatthew Ahrens mdb_printf(" L%d %s\n", 294588b7b0f2SMatthew Ahrens level, typename); 294688b7b0f2SMatthew Ahrens } 294788b7b0f2SMatthew Ahrens } 294888b7b0f2SMatthew Ahrens 294988b7b0f2SMatthew Ahrens return (DCMD_OK); 295088b7b0f2SMatthew Ahrens } 295188b7b0f2SMatthew Ahrens 2952d5ee8a13SMatthew Ahrens typedef struct mdb_reference { 2953d5ee8a13SMatthew Ahrens uintptr_t ref_holder; 2954d5ee8a13SMatthew Ahrens uintptr_t ref_removed; 2955d5ee8a13SMatthew Ahrens uint64_t ref_number; 2956d5ee8a13SMatthew Ahrens } mdb_reference_t; 2957d5ee8a13SMatthew Ahrens 29589966ca11SMatthew Ahrens /* ARGSUSED */ 29599966ca11SMatthew Ahrens static int 29609966ca11SMatthew Ahrens reference_cb(uintptr_t addr, const void *ignored, void *arg) 29619966ca11SMatthew Ahrens { 2962d5ee8a13SMatthew Ahrens mdb_reference_t ref; 29633f9d6ad7SLin Ling boolean_t holder_is_str = B_FALSE; 29649966ca11SMatthew Ahrens char holder_str[128]; 29659966ca11SMatthew Ahrens boolean_t removed = (boolean_t)arg; 29669966ca11SMatthew Ahrens 2967d5ee8a13SMatthew Ahrens if (mdb_ctf_vread(&ref, "reference_t", "mdb_reference_t", addr, 2968d5ee8a13SMatthew Ahrens 0) == -1) 2969d5ee8a13SMatthew Ahrens return (DCMD_ERR); 29709966ca11SMatthew Ahrens 2971d5ee8a13SMatthew Ahrens if (mdb_readstr(holder_str, sizeof (holder_str), 2972d5ee8a13SMatthew Ahrens ref.ref_holder) != -1) 29733f9d6ad7SLin Ling holder_is_str = strisprint(holder_str); 29749966ca11SMatthew Ahrens 29759966ca11SMatthew Ahrens if (removed) 29769966ca11SMatthew Ahrens mdb_printf("removed "); 29779966ca11SMatthew Ahrens mdb_printf("reference "); 2978d5ee8a13SMatthew Ahrens if (ref.ref_number != 1) 2979d5ee8a13SMatthew Ahrens mdb_printf("with count=%llu ", ref.ref_number); 2980d5ee8a13SMatthew Ahrens mdb_printf("with tag %lx", ref.ref_holder); 29819966ca11SMatthew Ahrens if (holder_is_str) 29829966ca11SMatthew Ahrens mdb_printf(" \"%s\"", holder_str); 29839966ca11SMatthew Ahrens mdb_printf(", held at:\n"); 29849966ca11SMatthew Ahrens 29859966ca11SMatthew Ahrens (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 29869966ca11SMatthew Ahrens 29879966ca11SMatthew Ahrens if (removed) { 29889966ca11SMatthew Ahrens mdb_printf("removed at:\n"); 2989d5ee8a13SMatthew Ahrens (void) mdb_call_dcmd("whatis", ref.ref_removed, 29909966ca11SMatthew Ahrens DCMD_ADDRSPEC, 0, NULL); 29919966ca11SMatthew Ahrens } 29929966ca11SMatthew Ahrens 29939966ca11SMatthew Ahrens mdb_printf("\n"); 29949966ca11SMatthew Ahrens 29959966ca11SMatthew Ahrens return (WALK_NEXT); 29969966ca11SMatthew Ahrens } 29979966ca11SMatthew Ahrens 2998d5ee8a13SMatthew Ahrens typedef struct mdb_refcount { 2999d5ee8a13SMatthew Ahrens uint64_t rc_count; 3000d5ee8a13SMatthew Ahrens } mdb_refcount_t; 3001d5ee8a13SMatthew Ahrens 3002d5ee8a13SMatthew Ahrens typedef struct mdb_refcount_removed { 3003d5ee8a13SMatthew Ahrens uint64_t rc_removed_count; 3004d5ee8a13SMatthew Ahrens } mdb_refcount_removed_t; 3005d5ee8a13SMatthew Ahrens 3006d5ee8a13SMatthew Ahrens typedef struct mdb_refcount_tracked { 3007d5ee8a13SMatthew Ahrens boolean_t rc_tracked; 3008d5ee8a13SMatthew Ahrens } mdb_refcount_tracked_t; 3009d5ee8a13SMatthew Ahrens 30109966ca11SMatthew Ahrens /* ARGSUSED */ 30119966ca11SMatthew Ahrens static int 30129966ca11SMatthew Ahrens refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 30139966ca11SMatthew Ahrens { 3014d5ee8a13SMatthew Ahrens mdb_refcount_t rc; 3015d5ee8a13SMatthew Ahrens mdb_refcount_removed_t rcr; 3016d5ee8a13SMatthew Ahrens mdb_refcount_tracked_t rct; 3017d5ee8a13SMatthew Ahrens int off; 301828e4da25SMatthew Ahrens boolean_t released = B_FALSE; 30199966ca11SMatthew Ahrens 30209966ca11SMatthew Ahrens if (!(flags & DCMD_ADDRSPEC)) 30219966ca11SMatthew Ahrens return (DCMD_USAGE); 30229966ca11SMatthew Ahrens 302328e4da25SMatthew Ahrens if (mdb_getopts(argc, argv, 302428e4da25SMatthew Ahrens 'r', MDB_OPT_SETBITS, B_TRUE, &released, 302528e4da25SMatthew Ahrens NULL) != argc) 302628e4da25SMatthew Ahrens return (DCMD_USAGE); 302728e4da25SMatthew Ahrens 3028d5ee8a13SMatthew Ahrens if (mdb_ctf_vread(&rc, "refcount_t", "mdb_refcount_t", addr, 3029d5ee8a13SMatthew Ahrens 0) == -1) 30309966ca11SMatthew Ahrens return (DCMD_ERR); 30319966ca11SMatthew Ahrens 3032d5ee8a13SMatthew Ahrens if (mdb_ctf_vread(&rcr, "refcount_t", "mdb_refcount_removed_t", addr, 3033d5ee8a13SMatthew Ahrens MDB_CTF_VREAD_QUIET) == -1) { 3034d5ee8a13SMatthew Ahrens mdb_printf("refcount_t at %p has %llu holds (untracked)\n", 3035d5ee8a13SMatthew Ahrens addr, (longlong_t)rc.rc_count); 303628e4da25SMatthew Ahrens return (DCMD_OK); 303728e4da25SMatthew Ahrens } 303828e4da25SMatthew Ahrens 3039d5ee8a13SMatthew Ahrens if (mdb_ctf_vread(&rct, "refcount_t", "mdb_refcount_tracked_t", addr, 3040d5ee8a13SMatthew Ahrens MDB_CTF_VREAD_QUIET) == -1) { 3041d5ee8a13SMatthew Ahrens /* If this is an old target, it might be tracked. */ 3042d5ee8a13SMatthew Ahrens rct.rc_tracked = B_TRUE; 3043d5ee8a13SMatthew Ahrens } 3044d5ee8a13SMatthew Ahrens 30459966ca11SMatthew Ahrens mdb_printf("refcount_t at %p has %llu current holds, " 30469966ca11SMatthew Ahrens "%llu recently released holds\n", 3047d5ee8a13SMatthew Ahrens addr, (longlong_t)rc.rc_count, (longlong_t)rcr.rc_removed_count); 30489966ca11SMatthew Ahrens 3049d5ee8a13SMatthew Ahrens if (rct.rc_tracked && rc.rc_count > 0) 30509966ca11SMatthew Ahrens mdb_printf("current holds:\n"); 3051d5ee8a13SMatthew Ahrens off = mdb_ctf_offsetof_by_name("refcount_t", "rc_list"); 3052d5ee8a13SMatthew Ahrens if (off == -1) 30539966ca11SMatthew Ahrens return (DCMD_ERR); 3054d5ee8a13SMatthew Ahrens mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off); 30559966ca11SMatthew Ahrens 3056d5ee8a13SMatthew Ahrens if (released && rcr.rc_removed_count > 0) { 30579966ca11SMatthew Ahrens mdb_printf("released holds:\n"); 3058d5ee8a13SMatthew Ahrens 3059d5ee8a13SMatthew Ahrens off = mdb_ctf_offsetof_by_name("refcount_t", "rc_removed"); 3060d5ee8a13SMatthew Ahrens if (off == -1) 30619966ca11SMatthew Ahrens return (DCMD_ERR); 3062421ff020SPrakash Surya mdb_pwalk("list", reference_cb, (void*)B_TRUE, addr + off); 306328e4da25SMatthew Ahrens } 30649966ca11SMatthew Ahrens 30659966ca11SMatthew Ahrens return (DCMD_OK); 30669966ca11SMatthew Ahrens } 30679966ca11SMatthew Ahrens 30680a586ceaSMark Shellenbaum /* ARGSUSED */ 30690a586ceaSMark Shellenbaum static int 30700a586ceaSMark Shellenbaum sa_attr_table(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 30710a586ceaSMark Shellenbaum { 30720a586ceaSMark Shellenbaum sa_attr_table_t *table; 30730a586ceaSMark Shellenbaum sa_os_t sa_os; 30740a586ceaSMark Shellenbaum char *name; 30750a586ceaSMark Shellenbaum int i; 30760a586ceaSMark Shellenbaum 30770a586ceaSMark Shellenbaum if (mdb_vread(&sa_os, sizeof (sa_os_t), addr) == -1) { 30780a586ceaSMark Shellenbaum mdb_warn("failed to read sa_os at %p", addr); 30790a586ceaSMark Shellenbaum return (DCMD_ERR); 30800a586ceaSMark Shellenbaum } 30810a586ceaSMark Shellenbaum 30820a586ceaSMark Shellenbaum table = mdb_alloc(sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 30830a586ceaSMark Shellenbaum UM_SLEEP | UM_GC); 30840a586ceaSMark Shellenbaum name = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC); 30850a586ceaSMark Shellenbaum 30860a586ceaSMark Shellenbaum if (mdb_vread(table, sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 30870a586ceaSMark Shellenbaum (uintptr_t)sa_os.sa_attr_table) == -1) { 30880a586ceaSMark Shellenbaum mdb_warn("failed to read sa_os at %p", addr); 30890a586ceaSMark Shellenbaum return (DCMD_ERR); 30900a586ceaSMark Shellenbaum } 30910a586ceaSMark Shellenbaum 30920a586ceaSMark Shellenbaum mdb_printf("%<u>%-10s %-10s %-10s %-10s %s%</u>\n", 30930a586ceaSMark Shellenbaum "ATTR ID", "REGISTERED", "LENGTH", "BSWAP", "NAME"); 30940a586ceaSMark Shellenbaum for (i = 0; i != sa_os.sa_num_attrs; i++) { 30950a586ceaSMark Shellenbaum mdb_readstr(name, MAXPATHLEN, (uintptr_t)table[i].sa_name); 30960a586ceaSMark Shellenbaum mdb_printf("%5x %8x %8x %8x %-s\n", 30970a586ceaSMark Shellenbaum (int)table[i].sa_attr, (int)table[i].sa_registered, 30980a586ceaSMark Shellenbaum (int)table[i].sa_length, table[i].sa_byteswap, name); 30990a586ceaSMark Shellenbaum } 31000a586ceaSMark Shellenbaum 31010a586ceaSMark Shellenbaum return (DCMD_OK); 31020a586ceaSMark Shellenbaum } 31030a586ceaSMark Shellenbaum 31040a586ceaSMark Shellenbaum static int 31050a586ceaSMark Shellenbaum sa_get_off_table(uintptr_t addr, uint32_t **off_tab, int attr_count) 31060a586ceaSMark Shellenbaum { 31070a586ceaSMark Shellenbaum uintptr_t idx_table; 31080a586ceaSMark Shellenbaum 310928e4da25SMatthew Ahrens if (GETMEMB(addr, "sa_idx_tab", sa_idx_tab, idx_table)) { 31100a586ceaSMark Shellenbaum mdb_printf("can't find offset table in sa_idx_tab\n"); 31110a586ceaSMark Shellenbaum return (-1); 31120a586ceaSMark Shellenbaum } 31130a586ceaSMark Shellenbaum 31140a586ceaSMark Shellenbaum *off_tab = mdb_alloc(attr_count * sizeof (uint32_t), 31150a586ceaSMark Shellenbaum UM_SLEEP | UM_GC); 31160a586ceaSMark Shellenbaum 31170a586ceaSMark Shellenbaum if (mdb_vread(*off_tab, 31180a586ceaSMark Shellenbaum attr_count * sizeof (uint32_t), idx_table) == -1) { 31190a586ceaSMark Shellenbaum mdb_warn("failed to attribute offset table %p", idx_table); 31200a586ceaSMark Shellenbaum return (-1); 31210a586ceaSMark Shellenbaum } 31220a586ceaSMark Shellenbaum 31230a586ceaSMark Shellenbaum return (DCMD_OK); 31240a586ceaSMark Shellenbaum } 31250a586ceaSMark Shellenbaum 31260a586ceaSMark Shellenbaum /*ARGSUSED*/ 31270a586ceaSMark Shellenbaum static int 31280a586ceaSMark Shellenbaum sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 31290a586ceaSMark Shellenbaum { 31300a586ceaSMark Shellenbaum uint32_t *offset_tab; 31310a586ceaSMark Shellenbaum int attr_count; 31320a586ceaSMark Shellenbaum uint64_t attr_id; 31330a586ceaSMark Shellenbaum uintptr_t attr_addr; 31340a586ceaSMark Shellenbaum uintptr_t bonus_tab, spill_tab; 31350a586ceaSMark Shellenbaum uintptr_t db_bonus, db_spill; 31360a586ceaSMark Shellenbaum uintptr_t os, os_sa; 31370a586ceaSMark Shellenbaum uintptr_t db_data; 31380a586ceaSMark Shellenbaum 31390a586ceaSMark Shellenbaum if (argc != 1) 31400a586ceaSMark Shellenbaum return (DCMD_USAGE); 31410a586ceaSMark Shellenbaum 31420a586ceaSMark Shellenbaum if (argv[0].a_type == MDB_TYPE_STRING) 31430a586ceaSMark Shellenbaum attr_id = mdb_strtoull(argv[0].a_un.a_str); 31440a586ceaSMark Shellenbaum else 31450a586ceaSMark Shellenbaum return (DCMD_USAGE); 31460a586ceaSMark Shellenbaum 314728e4da25SMatthew Ahrens if (GETMEMB(addr, "sa_handle", sa_bonus_tab, bonus_tab) || 314828e4da25SMatthew Ahrens GETMEMB(addr, "sa_handle", sa_spill_tab, spill_tab) || 314928e4da25SMatthew Ahrens GETMEMB(addr, "sa_handle", sa_os, os) || 315028e4da25SMatthew Ahrens GETMEMB(addr, "sa_handle", sa_bonus, db_bonus) || 315128e4da25SMatthew Ahrens GETMEMB(addr, "sa_handle", sa_spill, db_spill)) { 31520a586ceaSMark Shellenbaum mdb_printf("Can't find necessary information in sa_handle " 31530a586ceaSMark Shellenbaum "in sa_handle\n"); 31540a586ceaSMark Shellenbaum return (DCMD_ERR); 31550a586ceaSMark Shellenbaum } 31560a586ceaSMark Shellenbaum 315728e4da25SMatthew Ahrens if (GETMEMB(os, "objset", os_sa, os_sa)) { 31580a586ceaSMark Shellenbaum mdb_printf("Can't find os_sa in objset\n"); 31590a586ceaSMark Shellenbaum return (DCMD_ERR); 31600a586ceaSMark Shellenbaum } 31610a586ceaSMark Shellenbaum 316228e4da25SMatthew Ahrens if (GETMEMB(os_sa, "sa_os", sa_num_attrs, attr_count)) { 31630a586ceaSMark Shellenbaum mdb_printf("Can't find sa_num_attrs\n"); 31640a586ceaSMark Shellenbaum return (DCMD_ERR); 31650a586ceaSMark Shellenbaum } 31660a586ceaSMark Shellenbaum 31670a586ceaSMark Shellenbaum if (attr_id > attr_count) { 31680a586ceaSMark Shellenbaum mdb_printf("attribute id number is out of range\n"); 31690a586ceaSMark Shellenbaum return (DCMD_ERR); 31700a586ceaSMark Shellenbaum } 31710a586ceaSMark Shellenbaum 31720a586ceaSMark Shellenbaum if (bonus_tab) { 31730a586ceaSMark Shellenbaum if (sa_get_off_table(bonus_tab, &offset_tab, 31740a586ceaSMark Shellenbaum attr_count) == -1) { 31750a586ceaSMark Shellenbaum return (DCMD_ERR); 31760a586ceaSMark Shellenbaum } 31770a586ceaSMark Shellenbaum 317828e4da25SMatthew Ahrens if (GETMEMB(db_bonus, "dmu_buf", db_data, db_data)) { 31790a586ceaSMark Shellenbaum mdb_printf("can't find db_data in bonus dbuf\n"); 31800a586ceaSMark Shellenbaum return (DCMD_ERR); 31810a586ceaSMark Shellenbaum } 31820a586ceaSMark Shellenbaum } 31830a586ceaSMark Shellenbaum 31840a586ceaSMark Shellenbaum if (bonus_tab && !TOC_ATTR_PRESENT(offset_tab[attr_id]) && 3185892ad162SToomas Soome spill_tab == 0) { 31860a586ceaSMark Shellenbaum mdb_printf("Attribute does not exist\n"); 31870a586ceaSMark Shellenbaum return (DCMD_ERR); 31880a586ceaSMark Shellenbaum } else if (!TOC_ATTR_PRESENT(offset_tab[attr_id]) && spill_tab) { 31890a586ceaSMark Shellenbaum if (sa_get_off_table(spill_tab, &offset_tab, 31900a586ceaSMark Shellenbaum attr_count) == -1) { 31910a586ceaSMark Shellenbaum return (DCMD_ERR); 31920a586ceaSMark Shellenbaum } 319328e4da25SMatthew Ahrens if (GETMEMB(db_spill, "dmu_buf", db_data, db_data)) { 31940a586ceaSMark Shellenbaum mdb_printf("can't find db_data in spill dbuf\n"); 31950a586ceaSMark Shellenbaum return (DCMD_ERR); 31960a586ceaSMark Shellenbaum } 31970a586ceaSMark Shellenbaum if (!TOC_ATTR_PRESENT(offset_tab[attr_id])) { 31980a586ceaSMark Shellenbaum mdb_printf("Attribute does not exist\n"); 31990a586ceaSMark Shellenbaum return (DCMD_ERR); 32000a586ceaSMark Shellenbaum } 32010a586ceaSMark Shellenbaum } 32020a586ceaSMark Shellenbaum attr_addr = db_data + TOC_OFF(offset_tab[attr_id]); 32030a586ceaSMark Shellenbaum mdb_printf("%p\n", attr_addr); 32040a586ceaSMark Shellenbaum return (DCMD_OK); 32050a586ceaSMark Shellenbaum } 32060a586ceaSMark Shellenbaum 32070a586ceaSMark Shellenbaum /* ARGSUSED */ 32080a586ceaSMark Shellenbaum static int 32090a586ceaSMark Shellenbaum zfs_ace_print_common(uintptr_t addr, uint_t flags, 32100a586ceaSMark Shellenbaum uint64_t id, uint32_t access_mask, uint16_t ace_flags, 32110a586ceaSMark Shellenbaum uint16_t ace_type, int verbose) 32120a586ceaSMark Shellenbaum { 32130a586ceaSMark Shellenbaum if (DCMD_HDRSPEC(flags) && !verbose) 32140a586ceaSMark Shellenbaum mdb_printf("%<u>%-?s %-8s %-8s %-8s %s%</u>\n", 32150a586ceaSMark Shellenbaum "ADDR", "FLAGS", "MASK", "TYPE", "ID"); 32160a586ceaSMark Shellenbaum 32170a586ceaSMark Shellenbaum if (!verbose) { 32180a586ceaSMark Shellenbaum mdb_printf("%0?p %-8x %-8x %-8x %-llx\n", addr, 32190a586ceaSMark Shellenbaum ace_flags, access_mask, ace_type, id); 32200a586ceaSMark Shellenbaum return (DCMD_OK); 32210a586ceaSMark Shellenbaum } 32220a586ceaSMark Shellenbaum 32230a586ceaSMark Shellenbaum switch (ace_flags & ACE_TYPE_FLAGS) { 32240a586ceaSMark Shellenbaum case ACE_OWNER: 32250a586ceaSMark Shellenbaum mdb_printf("owner@:"); 32260a586ceaSMark Shellenbaum break; 32270a586ceaSMark Shellenbaum case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 32280a586ceaSMark Shellenbaum mdb_printf("group@:"); 32290a586ceaSMark Shellenbaum break; 32300a586ceaSMark Shellenbaum case ACE_EVERYONE: 32310a586ceaSMark Shellenbaum mdb_printf("everyone@:"); 32320a586ceaSMark Shellenbaum break; 32330a586ceaSMark Shellenbaum case ACE_IDENTIFIER_GROUP: 32340a586ceaSMark Shellenbaum mdb_printf("group:%llx:", (u_longlong_t)id); 32350a586ceaSMark Shellenbaum break; 32360a586ceaSMark Shellenbaum case 0: /* User entry */ 32370a586ceaSMark Shellenbaum mdb_printf("user:%llx:", (u_longlong_t)id); 32380a586ceaSMark Shellenbaum break; 32390a586ceaSMark Shellenbaum } 32400a586ceaSMark Shellenbaum 32410a586ceaSMark Shellenbaum /* print out permission mask */ 32420a586ceaSMark Shellenbaum if (access_mask & ACE_READ_DATA) 32430a586ceaSMark Shellenbaum mdb_printf("r"); 32440a586ceaSMark Shellenbaum else 32450a586ceaSMark Shellenbaum mdb_printf("-"); 32460a586ceaSMark Shellenbaum if (access_mask & ACE_WRITE_DATA) 32470a586ceaSMark Shellenbaum mdb_printf("w"); 32480a586ceaSMark Shellenbaum else 32490a586ceaSMark Shellenbaum mdb_printf("-"); 32500a586ceaSMark Shellenbaum if (access_mask & ACE_EXECUTE) 32510a586ceaSMark Shellenbaum mdb_printf("x"); 32520a586ceaSMark Shellenbaum else 32530a586ceaSMark Shellenbaum mdb_printf("-"); 32540a586ceaSMark Shellenbaum if (access_mask & ACE_APPEND_DATA) 32550a586ceaSMark Shellenbaum mdb_printf("p"); 32560a586ceaSMark Shellenbaum else 32570a586ceaSMark Shellenbaum mdb_printf("-"); 32580a586ceaSMark Shellenbaum if (access_mask & ACE_DELETE) 32590a586ceaSMark Shellenbaum mdb_printf("d"); 32600a586ceaSMark Shellenbaum else 32610a586ceaSMark Shellenbaum mdb_printf("-"); 32620a586ceaSMark Shellenbaum if (access_mask & ACE_DELETE_CHILD) 32630a586ceaSMark Shellenbaum mdb_printf("D"); 32640a586ceaSMark Shellenbaum else 32650a586ceaSMark Shellenbaum mdb_printf("-"); 32660a586ceaSMark Shellenbaum if (access_mask & ACE_READ_ATTRIBUTES) 32670a586ceaSMark Shellenbaum mdb_printf("a"); 32680a586ceaSMark Shellenbaum else 32690a586ceaSMark Shellenbaum mdb_printf("-"); 32700a586ceaSMark Shellenbaum if (access_mask & ACE_WRITE_ATTRIBUTES) 32710a586ceaSMark Shellenbaum mdb_printf("A"); 32720a586ceaSMark Shellenbaum else 32730a586ceaSMark Shellenbaum mdb_printf("-"); 32740a586ceaSMark Shellenbaum if (access_mask & ACE_READ_NAMED_ATTRS) 32750a586ceaSMark Shellenbaum mdb_printf("R"); 32760a586ceaSMark Shellenbaum else 32770a586ceaSMark Shellenbaum mdb_printf("-"); 32780a586ceaSMark Shellenbaum if (access_mask & ACE_WRITE_NAMED_ATTRS) 32790a586ceaSMark Shellenbaum mdb_printf("W"); 32800a586ceaSMark Shellenbaum else 32810a586ceaSMark Shellenbaum mdb_printf("-"); 32820a586ceaSMark Shellenbaum if (access_mask & ACE_READ_ACL) 32830a586ceaSMark Shellenbaum mdb_printf("c"); 32840a586ceaSMark Shellenbaum else 32850a586ceaSMark Shellenbaum mdb_printf("-"); 32860a586ceaSMark Shellenbaum if (access_mask & ACE_WRITE_ACL) 32870a586ceaSMark Shellenbaum mdb_printf("C"); 32880a586ceaSMark Shellenbaum else 32890a586ceaSMark Shellenbaum mdb_printf("-"); 32900a586ceaSMark Shellenbaum if (access_mask & ACE_WRITE_OWNER) 32910a586ceaSMark Shellenbaum mdb_printf("o"); 32920a586ceaSMark Shellenbaum else 32930a586ceaSMark Shellenbaum mdb_printf("-"); 32940a586ceaSMark Shellenbaum if (access_mask & ACE_SYNCHRONIZE) 32950a586ceaSMark Shellenbaum mdb_printf("s"); 32960a586ceaSMark Shellenbaum else 32970a586ceaSMark Shellenbaum mdb_printf("-"); 32980a586ceaSMark Shellenbaum 32990a586ceaSMark Shellenbaum mdb_printf(":"); 33000a586ceaSMark Shellenbaum 33010a586ceaSMark Shellenbaum /* Print out inheritance flags */ 33020a586ceaSMark Shellenbaum if (ace_flags & ACE_FILE_INHERIT_ACE) 33030a586ceaSMark Shellenbaum mdb_printf("f"); 33040a586ceaSMark Shellenbaum else 33050a586ceaSMark Shellenbaum mdb_printf("-"); 33060a586ceaSMark Shellenbaum if (ace_flags & ACE_DIRECTORY_INHERIT_ACE) 33070a586ceaSMark Shellenbaum mdb_printf("d"); 33080a586ceaSMark Shellenbaum else 33090a586ceaSMark Shellenbaum mdb_printf("-"); 33100a586ceaSMark Shellenbaum if (ace_flags & ACE_INHERIT_ONLY_ACE) 33110a586ceaSMark Shellenbaum mdb_printf("i"); 33120a586ceaSMark Shellenbaum else 33130a586ceaSMark Shellenbaum mdb_printf("-"); 33140a586ceaSMark Shellenbaum if (ace_flags & ACE_NO_PROPAGATE_INHERIT_ACE) 33150a586ceaSMark Shellenbaum mdb_printf("n"); 33160a586ceaSMark Shellenbaum else 33170a586ceaSMark Shellenbaum mdb_printf("-"); 33180a586ceaSMark Shellenbaum if (ace_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 33190a586ceaSMark Shellenbaum mdb_printf("S"); 33200a586ceaSMark Shellenbaum else 33210a586ceaSMark Shellenbaum mdb_printf("-"); 33220a586ceaSMark Shellenbaum if (ace_flags & ACE_FAILED_ACCESS_ACE_FLAG) 33230a586ceaSMark Shellenbaum mdb_printf("F"); 33240a586ceaSMark Shellenbaum else 33250a586ceaSMark Shellenbaum mdb_printf("-"); 33260a586ceaSMark Shellenbaum if (ace_flags & ACE_INHERITED_ACE) 33270a586ceaSMark Shellenbaum mdb_printf("I"); 33280a586ceaSMark Shellenbaum else 33290a586ceaSMark Shellenbaum mdb_printf("-"); 33300a586ceaSMark Shellenbaum 33310a586ceaSMark Shellenbaum switch (ace_type) { 33320a586ceaSMark Shellenbaum case ACE_ACCESS_ALLOWED_ACE_TYPE: 33330a586ceaSMark Shellenbaum mdb_printf(":allow\n"); 33340a586ceaSMark Shellenbaum break; 33350a586ceaSMark Shellenbaum case ACE_ACCESS_DENIED_ACE_TYPE: 33360a586ceaSMark Shellenbaum mdb_printf(":deny\n"); 33370a586ceaSMark Shellenbaum break; 33380a586ceaSMark Shellenbaum case ACE_SYSTEM_AUDIT_ACE_TYPE: 33390a586ceaSMark Shellenbaum mdb_printf(":audit\n"); 33400a586ceaSMark Shellenbaum break; 33410a586ceaSMark Shellenbaum case ACE_SYSTEM_ALARM_ACE_TYPE: 33420a586ceaSMark Shellenbaum mdb_printf(":alarm\n"); 33430a586ceaSMark Shellenbaum break; 33440a586ceaSMark Shellenbaum default: 33450a586ceaSMark Shellenbaum mdb_printf(":?\n"); 33460a586ceaSMark Shellenbaum } 33470a586ceaSMark Shellenbaum return (DCMD_OK); 33480a586ceaSMark Shellenbaum } 33490a586ceaSMark Shellenbaum 33500a586ceaSMark Shellenbaum /* ARGSUSED */ 33510a586ceaSMark Shellenbaum static int 33520a586ceaSMark Shellenbaum zfs_ace_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 33530a586ceaSMark Shellenbaum { 33540a586ceaSMark Shellenbaum zfs_ace_t zace; 33550a586ceaSMark Shellenbaum int verbose = FALSE; 33560a586ceaSMark Shellenbaum uint64_t id; 33570a586ceaSMark Shellenbaum 33580a586ceaSMark Shellenbaum if (!(flags & DCMD_ADDRSPEC)) 33590a586ceaSMark Shellenbaum return (DCMD_USAGE); 33600a586ceaSMark Shellenbaum 33610a586ceaSMark Shellenbaum if (mdb_getopts(argc, argv, 33620a586ceaSMark Shellenbaum 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 33630a586ceaSMark Shellenbaum return (DCMD_USAGE); 33640a586ceaSMark Shellenbaum 33650a586ceaSMark Shellenbaum if (mdb_vread(&zace, sizeof (zfs_ace_t), addr) == -1) { 33660a586ceaSMark Shellenbaum mdb_warn("failed to read zfs_ace_t"); 33670a586ceaSMark Shellenbaum return (DCMD_ERR); 33680a586ceaSMark Shellenbaum } 33690a586ceaSMark Shellenbaum 33700a586ceaSMark Shellenbaum if ((zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == 0 || 33710a586ceaSMark Shellenbaum (zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 33720a586ceaSMark Shellenbaum id = zace.z_fuid; 33730a586ceaSMark Shellenbaum else 33740a586ceaSMark Shellenbaum id = -1; 33750a586ceaSMark Shellenbaum 33760a586ceaSMark Shellenbaum return (zfs_ace_print_common(addr, flags, id, zace.z_hdr.z_access_mask, 33770a586ceaSMark Shellenbaum zace.z_hdr.z_flags, zace.z_hdr.z_type, verbose)); 33780a586ceaSMark Shellenbaum } 33790a586ceaSMark Shellenbaum 33800a586ceaSMark Shellenbaum /* ARGSUSED */ 33810a586ceaSMark Shellenbaum static int 33820a586ceaSMark Shellenbaum zfs_ace0_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 33830a586ceaSMark Shellenbaum { 33840a586ceaSMark Shellenbaum ace_t ace; 33850a586ceaSMark Shellenbaum uint64_t id; 33860a586ceaSMark Shellenbaum int verbose = FALSE; 33870a586ceaSMark Shellenbaum 33880a586ceaSMark Shellenbaum if (!(flags & DCMD_ADDRSPEC)) 33890a586ceaSMark Shellenbaum return (DCMD_USAGE); 33900a586ceaSMark Shellenbaum 33910a586ceaSMark Shellenbaum if (mdb_getopts(argc, argv, 33920a586ceaSMark Shellenbaum 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 33930a586ceaSMark Shellenbaum return (DCMD_USAGE); 33940a586ceaSMark Shellenbaum 33950a586ceaSMark Shellenbaum if (mdb_vread(&ace, sizeof (ace_t), addr) == -1) { 33960a586ceaSMark Shellenbaum mdb_warn("failed to read ace_t"); 33970a586ceaSMark Shellenbaum return (DCMD_ERR); 33980a586ceaSMark Shellenbaum } 33990a586ceaSMark Shellenbaum 34000a586ceaSMark Shellenbaum if ((ace.a_flags & ACE_TYPE_FLAGS) == 0 || 34010a586ceaSMark Shellenbaum (ace.a_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 34020a586ceaSMark Shellenbaum id = ace.a_who; 34030a586ceaSMark Shellenbaum else 34040a586ceaSMark Shellenbaum id = -1; 34050a586ceaSMark Shellenbaum 34060a586ceaSMark Shellenbaum return (zfs_ace_print_common(addr, flags, id, ace.a_access_mask, 34070a586ceaSMark Shellenbaum ace.a_flags, ace.a_type, verbose)); 34080a586ceaSMark Shellenbaum } 34090a586ceaSMark Shellenbaum 34100a586ceaSMark Shellenbaum typedef struct acl_dump_args { 34110a586ceaSMark Shellenbaum int a_argc; 34120a586ceaSMark Shellenbaum const mdb_arg_t *a_argv; 34130a586ceaSMark Shellenbaum uint16_t a_version; 34140a586ceaSMark Shellenbaum int a_flags; 34150a586ceaSMark Shellenbaum } acl_dump_args_t; 34160a586ceaSMark Shellenbaum 34170a586ceaSMark Shellenbaum /* ARGSUSED */ 34180a586ceaSMark Shellenbaum static int 34190a586ceaSMark Shellenbaum acl_aces_cb(uintptr_t addr, const void *unknown, void *arg) 34200a586ceaSMark Shellenbaum { 34210a586ceaSMark Shellenbaum acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 34220a586ceaSMark Shellenbaum 34230a586ceaSMark Shellenbaum if (acl_args->a_version == 1) { 34240a586ceaSMark Shellenbaum if (mdb_call_dcmd("zfs_ace", addr, 34250a586ceaSMark Shellenbaum DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 34260a586ceaSMark Shellenbaum acl_args->a_argv) != DCMD_OK) { 34270a586ceaSMark Shellenbaum return (WALK_ERR); 34280a586ceaSMark Shellenbaum } 34290a586ceaSMark Shellenbaum } else { 34300a586ceaSMark Shellenbaum if (mdb_call_dcmd("zfs_ace0", addr, 34310a586ceaSMark Shellenbaum DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 34320a586ceaSMark Shellenbaum acl_args->a_argv) != DCMD_OK) { 34330a586ceaSMark Shellenbaum return (WALK_ERR); 34340a586ceaSMark Shellenbaum } 34350a586ceaSMark Shellenbaum } 34360a586ceaSMark Shellenbaum acl_args->a_flags = DCMD_LOOP; 34370a586ceaSMark Shellenbaum return (WALK_NEXT); 34380a586ceaSMark Shellenbaum } 34390a586ceaSMark Shellenbaum 34400a586ceaSMark Shellenbaum /* ARGSUSED */ 34410a586ceaSMark Shellenbaum static int 34420a586ceaSMark Shellenbaum acl_cb(uintptr_t addr, const void *unknown, void *arg) 34430a586ceaSMark Shellenbaum { 34440a586ceaSMark Shellenbaum acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 34450a586ceaSMark Shellenbaum 34460a586ceaSMark Shellenbaum if (acl_args->a_version == 1) { 34470a586ceaSMark Shellenbaum if (mdb_pwalk("zfs_acl_node_aces", acl_aces_cb, 34480a586ceaSMark Shellenbaum arg, addr) != 0) { 34490a586ceaSMark Shellenbaum mdb_warn("can't walk ACEs"); 34500a586ceaSMark Shellenbaum return (DCMD_ERR); 34510a586ceaSMark Shellenbaum } 34520a586ceaSMark Shellenbaum } else { 34530a586ceaSMark Shellenbaum if (mdb_pwalk("zfs_acl_node_aces0", acl_aces_cb, 34540a586ceaSMark Shellenbaum arg, addr) != 0) { 34550a586ceaSMark Shellenbaum mdb_warn("can't walk ACEs"); 34560a586ceaSMark Shellenbaum return (DCMD_ERR); 34570a586ceaSMark Shellenbaum } 34580a586ceaSMark Shellenbaum } 34590a586ceaSMark Shellenbaum return (WALK_NEXT); 34600a586ceaSMark Shellenbaum } 34610a586ceaSMark Shellenbaum 34620a586ceaSMark Shellenbaum /* ARGSUSED */ 34630a586ceaSMark Shellenbaum static int 34640a586ceaSMark Shellenbaum zfs_acl_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 34650a586ceaSMark Shellenbaum { 34660a586ceaSMark Shellenbaum zfs_acl_t zacl; 34670a586ceaSMark Shellenbaum int verbose = FALSE; 34680a586ceaSMark Shellenbaum acl_dump_args_t acl_args; 34690a586ceaSMark Shellenbaum 34700a586ceaSMark Shellenbaum if (!(flags & DCMD_ADDRSPEC)) 34710a586ceaSMark Shellenbaum return (DCMD_USAGE); 34720a586ceaSMark Shellenbaum 34730a586ceaSMark Shellenbaum if (mdb_getopts(argc, argv, 34740a586ceaSMark Shellenbaum 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 34750a586ceaSMark Shellenbaum return (DCMD_USAGE); 34760a586ceaSMark Shellenbaum 34770a586ceaSMark Shellenbaum if (mdb_vread(&zacl, sizeof (zfs_acl_t), addr) == -1) { 34780a586ceaSMark Shellenbaum mdb_warn("failed to read zfs_acl_t"); 34790a586ceaSMark Shellenbaum return (DCMD_ERR); 34800a586ceaSMark Shellenbaum } 34810a586ceaSMark Shellenbaum 34820a586ceaSMark Shellenbaum acl_args.a_argc = argc; 34830a586ceaSMark Shellenbaum acl_args.a_argv = argv; 34840a586ceaSMark Shellenbaum acl_args.a_version = zacl.z_version; 34850a586ceaSMark Shellenbaum acl_args.a_flags = DCMD_LOOPFIRST; 34860a586ceaSMark Shellenbaum 34870a586ceaSMark Shellenbaum if (mdb_pwalk("zfs_acl_node", acl_cb, &acl_args, addr) != 0) { 34880a586ceaSMark Shellenbaum mdb_warn("can't walk ACL"); 34890a586ceaSMark Shellenbaum return (DCMD_ERR); 34900a586ceaSMark Shellenbaum } 34910a586ceaSMark Shellenbaum 34920a586ceaSMark Shellenbaum return (DCMD_OK); 34930a586ceaSMark Shellenbaum } 34940a586ceaSMark Shellenbaum 34950a586ceaSMark Shellenbaum /* ARGSUSED */ 34960a586ceaSMark Shellenbaum static int 34970a586ceaSMark Shellenbaum zfs_acl_node_walk_init(mdb_walk_state_t *wsp) 34980a586ceaSMark Shellenbaum { 3499892ad162SToomas Soome if (wsp->walk_addr == 0) { 35000a586ceaSMark Shellenbaum mdb_warn("must supply address of zfs_acl_node_t\n"); 35010a586ceaSMark Shellenbaum return (WALK_ERR); 35020a586ceaSMark Shellenbaum } 35030a586ceaSMark Shellenbaum 350428e4da25SMatthew Ahrens wsp->walk_addr += 350528e4da25SMatthew Ahrens mdb_ctf_offsetof_by_name(ZFS_STRUCT "zfs_acl", "z_acl"); 35060a586ceaSMark Shellenbaum 35070a586ceaSMark Shellenbaum if (mdb_layered_walk("list", wsp) == -1) { 35080a586ceaSMark Shellenbaum mdb_warn("failed to walk 'list'\n"); 35090a586ceaSMark Shellenbaum return (WALK_ERR); 35100a586ceaSMark Shellenbaum } 35110a586ceaSMark Shellenbaum 35120a586ceaSMark Shellenbaum return (WALK_NEXT); 35130a586ceaSMark Shellenbaum } 35140a586ceaSMark Shellenbaum 35150a586ceaSMark Shellenbaum static int 35160a586ceaSMark Shellenbaum zfs_acl_node_walk_step(mdb_walk_state_t *wsp) 35170a586ceaSMark Shellenbaum { 35180a586ceaSMark Shellenbaum zfs_acl_node_t aclnode; 35190a586ceaSMark Shellenbaum 35200a586ceaSMark Shellenbaum if (mdb_vread(&aclnode, sizeof (zfs_acl_node_t), 35210a586ceaSMark Shellenbaum wsp->walk_addr) == -1) { 35220a586ceaSMark Shellenbaum mdb_warn("failed to read zfs_acl_node at %p", wsp->walk_addr); 35230a586ceaSMark Shellenbaum return (WALK_ERR); 35240a586ceaSMark Shellenbaum } 35250a586ceaSMark Shellenbaum 35260a586ceaSMark Shellenbaum return (wsp->walk_callback(wsp->walk_addr, &aclnode, wsp->walk_cbdata)); 35270a586ceaSMark Shellenbaum } 35280a586ceaSMark Shellenbaum 35290a586ceaSMark Shellenbaum typedef struct ace_walk_data { 35300a586ceaSMark Shellenbaum int ace_count; 35310a586ceaSMark Shellenbaum int ace_version; 35320a586ceaSMark Shellenbaum } ace_walk_data_t; 35330a586ceaSMark Shellenbaum 35340a586ceaSMark Shellenbaum static int 35350a586ceaSMark Shellenbaum zfs_aces_walk_init_common(mdb_walk_state_t *wsp, int version, 35360a586ceaSMark Shellenbaum int ace_count, uintptr_t ace_data) 35370a586ceaSMark Shellenbaum { 35380a586ceaSMark Shellenbaum ace_walk_data_t *ace_walk_data; 35390a586ceaSMark Shellenbaum 3540892ad162SToomas Soome if (wsp->walk_addr == 0) { 35410a586ceaSMark Shellenbaum mdb_warn("must supply address of zfs_acl_node_t\n"); 35420a586ceaSMark Shellenbaum return (WALK_ERR); 35430a586ceaSMark Shellenbaum } 35440a586ceaSMark Shellenbaum 35450a586ceaSMark Shellenbaum ace_walk_data = mdb_alloc(sizeof (ace_walk_data_t), UM_SLEEP | UM_GC); 35460a586ceaSMark Shellenbaum 35470a586ceaSMark Shellenbaum ace_walk_data->ace_count = ace_count; 35480a586ceaSMark Shellenbaum ace_walk_data->ace_version = version; 35490a586ceaSMark Shellenbaum 35500a586ceaSMark Shellenbaum wsp->walk_addr = ace_data; 35510a586ceaSMark Shellenbaum wsp->walk_data = ace_walk_data; 35520a586ceaSMark Shellenbaum 35530a586ceaSMark Shellenbaum return (WALK_NEXT); 35540a586ceaSMark Shellenbaum } 35550a586ceaSMark Shellenbaum 35560a586ceaSMark Shellenbaum static int 35570a586ceaSMark Shellenbaum zfs_acl_node_aces_walk_init_common(mdb_walk_state_t *wsp, int version) 35580a586ceaSMark Shellenbaum { 35590a586ceaSMark Shellenbaum static int gotid; 35600a586ceaSMark Shellenbaum static mdb_ctf_id_t acl_id; 35610a586ceaSMark Shellenbaum int z_ace_count; 35620a586ceaSMark Shellenbaum uintptr_t z_acldata; 35630a586ceaSMark Shellenbaum 35640a586ceaSMark Shellenbaum if (!gotid) { 35650a586ceaSMark Shellenbaum if (mdb_ctf_lookup_by_name("struct zfs_acl_node", 35660a586ceaSMark Shellenbaum &acl_id) == -1) { 35670a586ceaSMark Shellenbaum mdb_warn("couldn't find struct zfs_acl_node"); 35680a586ceaSMark Shellenbaum return (DCMD_ERR); 35690a586ceaSMark Shellenbaum } 35700a586ceaSMark Shellenbaum gotid = TRUE; 35710a586ceaSMark Shellenbaum } 35720a586ceaSMark Shellenbaum 35730a586ceaSMark Shellenbaum if (GETMEMBID(wsp->walk_addr, &acl_id, z_ace_count, z_ace_count)) { 35740a586ceaSMark Shellenbaum return (DCMD_ERR); 35750a586ceaSMark Shellenbaum } 35760a586ceaSMark Shellenbaum if (GETMEMBID(wsp->walk_addr, &acl_id, z_acldata, z_acldata)) { 35770a586ceaSMark Shellenbaum return (DCMD_ERR); 35780a586ceaSMark Shellenbaum } 35790a586ceaSMark Shellenbaum 35800a586ceaSMark Shellenbaum return (zfs_aces_walk_init_common(wsp, version, 35810a586ceaSMark Shellenbaum z_ace_count, z_acldata)); 35820a586ceaSMark Shellenbaum } 35830a586ceaSMark Shellenbaum 35840a586ceaSMark Shellenbaum /* ARGSUSED */ 35850a586ceaSMark Shellenbaum static int 35860a586ceaSMark Shellenbaum zfs_acl_node_aces_walk_init(mdb_walk_state_t *wsp) 35870a586ceaSMark Shellenbaum { 35880a586ceaSMark Shellenbaum return (zfs_acl_node_aces_walk_init_common(wsp, 1)); 35890a586ceaSMark Shellenbaum } 35900a586ceaSMark Shellenbaum 35910a586ceaSMark Shellenbaum /* ARGSUSED */ 35920a586ceaSMark Shellenbaum static int 35930a586ceaSMark Shellenbaum zfs_acl_node_aces0_walk_init(mdb_walk_state_t *wsp) 35940a586ceaSMark Shellenbaum { 35950a586ceaSMark Shellenbaum return (zfs_acl_node_aces_walk_init_common(wsp, 0)); 35960a586ceaSMark Shellenbaum } 35970a586ceaSMark Shellenbaum 35980a586ceaSMark Shellenbaum static int 35990a586ceaSMark Shellenbaum zfs_aces_walk_step(mdb_walk_state_t *wsp) 36000a586ceaSMark Shellenbaum { 36010a586ceaSMark Shellenbaum ace_walk_data_t *ace_data = wsp->walk_data; 36020a586ceaSMark Shellenbaum zfs_ace_t zace; 36030a586ceaSMark Shellenbaum ace_t *acep; 36040a586ceaSMark Shellenbaum int status; 36050a586ceaSMark Shellenbaum int entry_type; 36060a586ceaSMark Shellenbaum int allow_type; 36070a586ceaSMark Shellenbaum uintptr_t ptr; 36080a586ceaSMark Shellenbaum 36090a586ceaSMark Shellenbaum if (ace_data->ace_count == 0) 36100a586ceaSMark Shellenbaum return (WALK_DONE); 36110a586ceaSMark Shellenbaum 36120a586ceaSMark Shellenbaum if (mdb_vread(&zace, sizeof (zfs_ace_t), wsp->walk_addr) == -1) { 36130a586ceaSMark Shellenbaum mdb_warn("failed to read zfs_ace_t at %#lx", 36140a586ceaSMark Shellenbaum wsp->walk_addr); 36150a586ceaSMark Shellenbaum return (WALK_ERR); 36160a586ceaSMark Shellenbaum } 36170a586ceaSMark Shellenbaum 36180a586ceaSMark Shellenbaum switch (ace_data->ace_version) { 36190a586ceaSMark Shellenbaum case 0: 36200a586ceaSMark Shellenbaum acep = (ace_t *)&zace; 36210a586ceaSMark Shellenbaum entry_type = acep->a_flags & ACE_TYPE_FLAGS; 36220a586ceaSMark Shellenbaum allow_type = acep->a_type; 36230a586ceaSMark Shellenbaum break; 36240a586ceaSMark Shellenbaum case 1: 36250a586ceaSMark Shellenbaum entry_type = zace.z_hdr.z_flags & ACE_TYPE_FLAGS; 36260a586ceaSMark Shellenbaum allow_type = zace.z_hdr.z_type; 36270a586ceaSMark Shellenbaum break; 36280a586ceaSMark Shellenbaum default: 36290a586ceaSMark Shellenbaum return (WALK_ERR); 36300a586ceaSMark Shellenbaum } 36310a586ceaSMark Shellenbaum 36320a586ceaSMark Shellenbaum ptr = (uintptr_t)wsp->walk_addr; 36330a586ceaSMark Shellenbaum switch (entry_type) { 36340a586ceaSMark Shellenbaum case ACE_OWNER: 36350a586ceaSMark Shellenbaum case ACE_EVERYONE: 36360a586ceaSMark Shellenbaum case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 36370a586ceaSMark Shellenbaum ptr += ace_data->ace_version == 0 ? 36380a586ceaSMark Shellenbaum sizeof (ace_t) : sizeof (zfs_ace_hdr_t); 36390a586ceaSMark Shellenbaum break; 36400a586ceaSMark Shellenbaum case ACE_IDENTIFIER_GROUP: 36410a586ceaSMark Shellenbaum default: 36420a586ceaSMark Shellenbaum switch (allow_type) { 36430a586ceaSMark Shellenbaum case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 36440a586ceaSMark Shellenbaum case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 36450a586ceaSMark Shellenbaum case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 36460a586ceaSMark Shellenbaum case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 36470a586ceaSMark Shellenbaum ptr += ace_data->ace_version == 0 ? 36480a586ceaSMark Shellenbaum sizeof (ace_t) : sizeof (zfs_object_ace_t); 36490a586ceaSMark Shellenbaum break; 36500a586ceaSMark Shellenbaum default: 36510a586ceaSMark Shellenbaum ptr += ace_data->ace_version == 0 ? 36520a586ceaSMark Shellenbaum sizeof (ace_t) : sizeof (zfs_ace_t); 36530a586ceaSMark Shellenbaum break; 36540a586ceaSMark Shellenbaum } 36550a586ceaSMark Shellenbaum } 36560a586ceaSMark Shellenbaum 36570a586ceaSMark Shellenbaum ace_data->ace_count--; 36580a586ceaSMark Shellenbaum status = wsp->walk_callback(wsp->walk_addr, 36590a586ceaSMark Shellenbaum (void *)(uintptr_t)&zace, wsp->walk_cbdata); 36600a586ceaSMark Shellenbaum 36610a586ceaSMark Shellenbaum wsp->walk_addr = ptr; 36620a586ceaSMark Shellenbaum return (status); 36630a586ceaSMark Shellenbaum } 36640a586ceaSMark Shellenbaum 366528e4da25SMatthew Ahrens typedef struct mdb_zfs_rrwlock { 3666d5ee8a13SMatthew Ahrens uintptr_t rr_writer; 366728e4da25SMatthew Ahrens boolean_t rr_writer_wanted; 366828e4da25SMatthew Ahrens } mdb_zfs_rrwlock_t; 366928e4da25SMatthew Ahrens 367028e4da25SMatthew Ahrens static uint_t rrw_key; 367128e4da25SMatthew Ahrens 367228e4da25SMatthew Ahrens /* ARGSUSED */ 367328e4da25SMatthew Ahrens static int 367428e4da25SMatthew Ahrens rrwlock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 367528e4da25SMatthew Ahrens { 367628e4da25SMatthew Ahrens mdb_zfs_rrwlock_t rrw; 367728e4da25SMatthew Ahrens 367828e4da25SMatthew Ahrens if (rrw_key == 0) { 367928e4da25SMatthew Ahrens if (mdb_ctf_readsym(&rrw_key, "uint_t", "rrw_tsd_key", 0) == -1) 368028e4da25SMatthew Ahrens return (DCMD_ERR); 368128e4da25SMatthew Ahrens } 368228e4da25SMatthew Ahrens 368328e4da25SMatthew Ahrens if (mdb_ctf_vread(&rrw, "rrwlock_t", "mdb_zfs_rrwlock_t", addr, 368428e4da25SMatthew Ahrens 0) == -1) 368528e4da25SMatthew Ahrens return (DCMD_ERR); 368628e4da25SMatthew Ahrens 3687d5ee8a13SMatthew Ahrens if (rrw.rr_writer != 0) { 3688d5ee8a13SMatthew Ahrens mdb_printf("write lock held by thread %lx\n", rrw.rr_writer); 368928e4da25SMatthew Ahrens return (DCMD_OK); 369028e4da25SMatthew Ahrens } 369128e4da25SMatthew Ahrens 369228e4da25SMatthew Ahrens if (rrw.rr_writer_wanted) { 369328e4da25SMatthew Ahrens mdb_printf("writer wanted\n"); 369428e4da25SMatthew Ahrens } 369528e4da25SMatthew Ahrens 369628e4da25SMatthew Ahrens mdb_printf("anonymous references:\n"); 369728e4da25SMatthew Ahrens (void) mdb_call_dcmd("refcount", addr + 369828e4da25SMatthew Ahrens mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_anon_rcount"), 369928e4da25SMatthew Ahrens DCMD_ADDRSPEC, 0, NULL); 370028e4da25SMatthew Ahrens 370128e4da25SMatthew Ahrens mdb_printf("linked references:\n"); 370228e4da25SMatthew Ahrens (void) mdb_call_dcmd("refcount", addr + 370328e4da25SMatthew Ahrens mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_linked_rcount"), 370428e4da25SMatthew Ahrens DCMD_ADDRSPEC, 0, NULL); 370528e4da25SMatthew Ahrens 370628e4da25SMatthew Ahrens /* 370728e4da25SMatthew Ahrens * XXX This should find references from 370828e4da25SMatthew Ahrens * "::walk thread | ::tsd -v <rrw_key>", but there is no support 370928e4da25SMatthew Ahrens * for programmatic consumption of dcmds, so this would be 371028e4da25SMatthew Ahrens * difficult, potentially requiring reimplementing ::tsd (both 371128e4da25SMatthew Ahrens * user and kernel versions) in this MDB module. 371228e4da25SMatthew Ahrens */ 371328e4da25SMatthew Ahrens 371428e4da25SMatthew Ahrens return (DCMD_OK); 371528e4da25SMatthew Ahrens } 371628e4da25SMatthew Ahrens 3717dcbf3bd6SGeorge Wilson typedef struct mdb_arc_buf_hdr_t { 3718dcbf3bd6SGeorge Wilson uint16_t b_psize; 3719dcbf3bd6SGeorge Wilson uint16_t b_lsize; 3720dcbf3bd6SGeorge Wilson struct { 3721dcbf3bd6SGeorge Wilson uint32_t b_bufcnt; 3722dcbf3bd6SGeorge Wilson uintptr_t b_state; 3723dcbf3bd6SGeorge Wilson } b_l1hdr; 3724dcbf3bd6SGeorge Wilson } mdb_arc_buf_hdr_t; 3725dcbf3bd6SGeorge Wilson 3726dcbf3bd6SGeorge Wilson enum arc_cflags { 3727dcbf3bd6SGeorge Wilson ARC_CFLAG_VERBOSE = 1 << 0, 3728dcbf3bd6SGeorge Wilson ARC_CFLAG_ANON = 1 << 1, 3729dcbf3bd6SGeorge Wilson ARC_CFLAG_MRU = 1 << 2, 3730dcbf3bd6SGeorge Wilson ARC_CFLAG_MFU = 1 << 3, 3731dcbf3bd6SGeorge Wilson ARC_CFLAG_BUFS = 1 << 4, 3732dcbf3bd6SGeorge Wilson }; 3733dcbf3bd6SGeorge Wilson 3734dcbf3bd6SGeorge Wilson typedef struct arc_compression_stats_data { 3735dcbf3bd6SGeorge Wilson GElf_Sym anon_sym; /* ARC_anon symbol */ 3736dcbf3bd6SGeorge Wilson GElf_Sym mru_sym; /* ARC_mru symbol */ 3737dcbf3bd6SGeorge Wilson GElf_Sym mrug_sym; /* ARC_mru_ghost symbol */ 3738dcbf3bd6SGeorge Wilson GElf_Sym mfu_sym; /* ARC_mfu symbol */ 3739dcbf3bd6SGeorge Wilson GElf_Sym mfug_sym; /* ARC_mfu_ghost symbol */ 3740dcbf3bd6SGeorge Wilson GElf_Sym l2c_sym; /* ARC_l2c_only symbol */ 3741dcbf3bd6SGeorge Wilson uint64_t *anon_c_hist; /* histogram of compressed sizes in anon */ 3742dcbf3bd6SGeorge Wilson uint64_t *anon_u_hist; /* histogram of uncompressed sizes in anon */ 3743dcbf3bd6SGeorge Wilson uint64_t *anon_bufs; /* histogram of buffer counts in anon state */ 3744dcbf3bd6SGeorge Wilson uint64_t *mru_c_hist; /* histogram of compressed sizes in mru */ 3745dcbf3bd6SGeorge Wilson uint64_t *mru_u_hist; /* histogram of uncompressed sizes in mru */ 3746dcbf3bd6SGeorge Wilson uint64_t *mru_bufs; /* histogram of buffer counts in mru */ 3747dcbf3bd6SGeorge Wilson uint64_t *mfu_c_hist; /* histogram of compressed sizes in mfu */ 3748dcbf3bd6SGeorge Wilson uint64_t *mfu_u_hist; /* histogram of uncompressed sizes in mfu */ 3749dcbf3bd6SGeorge Wilson uint64_t *mfu_bufs; /* histogram of buffer counts in mfu */ 3750dcbf3bd6SGeorge Wilson uint64_t *all_c_hist; /* histogram of compressed anon + mru + mfu */ 3751dcbf3bd6SGeorge Wilson uint64_t *all_u_hist; /* histogram of uncompressed anon + mru + mfu */ 3752dcbf3bd6SGeorge Wilson uint64_t *all_bufs; /* histogram of buffer counts in all states */ 3753dcbf3bd6SGeorge Wilson int arc_cflags; /* arc compression flags, specified by user */ 3754dcbf3bd6SGeorge Wilson int hist_nbuckets; /* number of buckets in each histogram */ 3755dcbf3bd6SGeorge Wilson } arc_compression_stats_data_t; 3756dcbf3bd6SGeorge Wilson 3757dcbf3bd6SGeorge Wilson int 3758dcbf3bd6SGeorge Wilson highbit64(uint64_t i) 3759dcbf3bd6SGeorge Wilson { 3760dcbf3bd6SGeorge Wilson int h = 1; 3761dcbf3bd6SGeorge Wilson 3762dcbf3bd6SGeorge Wilson if (i == 0) 3763dcbf3bd6SGeorge Wilson return (0); 3764dcbf3bd6SGeorge Wilson if (i & 0xffffffff00000000ULL) { 3765dcbf3bd6SGeorge Wilson h += 32; i >>= 32; 3766dcbf3bd6SGeorge Wilson } 3767dcbf3bd6SGeorge Wilson if (i & 0xffff0000) { 3768dcbf3bd6SGeorge Wilson h += 16; i >>= 16; 3769dcbf3bd6SGeorge Wilson } 3770dcbf3bd6SGeorge Wilson if (i & 0xff00) { 3771dcbf3bd6SGeorge Wilson h += 8; i >>= 8; 3772dcbf3bd6SGeorge Wilson } 3773dcbf3bd6SGeorge Wilson if (i & 0xf0) { 3774dcbf3bd6SGeorge Wilson h += 4; i >>= 4; 3775dcbf3bd6SGeorge Wilson } 3776dcbf3bd6SGeorge Wilson if (i & 0xc) { 3777dcbf3bd6SGeorge Wilson h += 2; i >>= 2; 3778dcbf3bd6SGeorge Wilson } 3779dcbf3bd6SGeorge Wilson if (i & 0x2) { 3780dcbf3bd6SGeorge Wilson h += 1; 3781dcbf3bd6SGeorge Wilson } 3782dcbf3bd6SGeorge Wilson return (h); 3783dcbf3bd6SGeorge Wilson } 3784dcbf3bd6SGeorge Wilson 3785dcbf3bd6SGeorge Wilson /* ARGSUSED */ 3786dcbf3bd6SGeorge Wilson static int 3787dcbf3bd6SGeorge Wilson arc_compression_stats_cb(uintptr_t addr, const void *unknown, void *arg) 3788dcbf3bd6SGeorge Wilson { 3789dcbf3bd6SGeorge Wilson arc_compression_stats_data_t *data = arg; 3790dcbf3bd6SGeorge Wilson mdb_arc_buf_hdr_t hdr; 3791dcbf3bd6SGeorge Wilson int cbucket, ubucket, bufcnt; 3792dcbf3bd6SGeorge Wilson 3793dcbf3bd6SGeorge Wilson if (mdb_ctf_vread(&hdr, "arc_buf_hdr_t", "mdb_arc_buf_hdr_t", 3794dcbf3bd6SGeorge Wilson addr, 0) == -1) { 3795dcbf3bd6SGeorge Wilson return (WALK_ERR); 3796dcbf3bd6SGeorge Wilson } 3797dcbf3bd6SGeorge Wilson 3798dcbf3bd6SGeorge Wilson /* 3799dcbf3bd6SGeorge Wilson * Headers in the ghost states, or the l2c_only state don't have 3800dcbf3bd6SGeorge Wilson * arc buffers linked off of them. Thus, their compressed size 3801dcbf3bd6SGeorge Wilson * is meaningless, so we skip these from the stats. 3802dcbf3bd6SGeorge Wilson */ 3803dcbf3bd6SGeorge Wilson if (hdr.b_l1hdr.b_state == data->mrug_sym.st_value || 3804dcbf3bd6SGeorge Wilson hdr.b_l1hdr.b_state == data->mfug_sym.st_value || 3805dcbf3bd6SGeorge Wilson hdr.b_l1hdr.b_state == data->l2c_sym.st_value) { 3806dcbf3bd6SGeorge Wilson return (WALK_NEXT); 3807dcbf3bd6SGeorge Wilson } 3808dcbf3bd6SGeorge Wilson 3809dcbf3bd6SGeorge Wilson /* 3810dcbf3bd6SGeorge Wilson * The physical size (compressed) and logical size 3811dcbf3bd6SGeorge Wilson * (uncompressed) are in units of SPA_MINBLOCKSIZE. By default, 3812dcbf3bd6SGeorge Wilson * we use the log2 of this value (rounded down to the nearest 3813dcbf3bd6SGeorge Wilson * integer) to determine the bucket to assign this header to. 3814dcbf3bd6SGeorge Wilson * Thus, the histogram is logarithmic with respect to the size 3815dcbf3bd6SGeorge Wilson * of the header. For example, the following is a mapping of the 3816dcbf3bd6SGeorge Wilson * bucket numbers and the range of header sizes they correspond to: 3817dcbf3bd6SGeorge Wilson * 3818dcbf3bd6SGeorge Wilson * 0: 0 byte headers 3819dcbf3bd6SGeorge Wilson * 1: 512 byte headers 3820dcbf3bd6SGeorge Wilson * 2: [1024 - 2048) byte headers 3821dcbf3bd6SGeorge Wilson * 3: [2048 - 4096) byte headers 3822dcbf3bd6SGeorge Wilson * 4: [4096 - 8192) byte headers 3823dcbf3bd6SGeorge Wilson * 5: [8192 - 16394) byte headers 3824dcbf3bd6SGeorge Wilson * 6: [16384 - 32768) byte headers 3825dcbf3bd6SGeorge Wilson * 7: [32768 - 65536) byte headers 3826dcbf3bd6SGeorge Wilson * 8: [65536 - 131072) byte headers 3827dcbf3bd6SGeorge Wilson * 9: 131072 byte headers 3828dcbf3bd6SGeorge Wilson * 3829dcbf3bd6SGeorge Wilson * If the ARC_CFLAG_VERBOSE flag was specified, we use the 3830dcbf3bd6SGeorge Wilson * physical and logical sizes directly. Thus, the histogram will 3831dcbf3bd6SGeorge Wilson * no longer be logarithmic; instead it will be linear with 3832dcbf3bd6SGeorge Wilson * respect to the size of the header. The following is a mapping 3833dcbf3bd6SGeorge Wilson * of the first many bucket numbers and the header size they 3834dcbf3bd6SGeorge Wilson * correspond to: 3835dcbf3bd6SGeorge Wilson * 3836dcbf3bd6SGeorge Wilson * 0: 0 byte headers 3837dcbf3bd6SGeorge Wilson * 1: 512 byte headers 3838dcbf3bd6SGeorge Wilson * 2: 1024 byte headers 3839dcbf3bd6SGeorge Wilson * 3: 1536 byte headers 3840dcbf3bd6SGeorge Wilson * 4: 2048 byte headers 3841dcbf3bd6SGeorge Wilson * 5: 2560 byte headers 3842dcbf3bd6SGeorge Wilson * 6: 3072 byte headers 3843dcbf3bd6SGeorge Wilson * 3844dcbf3bd6SGeorge Wilson * And so on. Keep in mind that a range of sizes isn't used in 3845dcbf3bd6SGeorge Wilson * the case of linear scale because the headers can only 3846dcbf3bd6SGeorge Wilson * increment or decrement in sizes of 512 bytes. So, it's not 3847dcbf3bd6SGeorge Wilson * possible for a header to be sized in between whats listed 3848dcbf3bd6SGeorge Wilson * above. 3849dcbf3bd6SGeorge Wilson * 3850dcbf3bd6SGeorge Wilson * Also, the above mapping values were calculated assuming a 3851dcbf3bd6SGeorge Wilson * SPA_MINBLOCKSHIFT of 512 bytes and a SPA_MAXBLOCKSIZE of 128K. 3852dcbf3bd6SGeorge Wilson */ 3853dcbf3bd6SGeorge Wilson 3854dcbf3bd6SGeorge Wilson if (data->arc_cflags & ARC_CFLAG_VERBOSE) { 3855dcbf3bd6SGeorge Wilson cbucket = hdr.b_psize; 3856dcbf3bd6SGeorge Wilson ubucket = hdr.b_lsize; 3857dcbf3bd6SGeorge Wilson } else { 3858dcbf3bd6SGeorge Wilson cbucket = highbit64(hdr.b_psize); 3859dcbf3bd6SGeorge Wilson ubucket = highbit64(hdr.b_lsize); 3860dcbf3bd6SGeorge Wilson } 3861dcbf3bd6SGeorge Wilson 3862dcbf3bd6SGeorge Wilson bufcnt = hdr.b_l1hdr.b_bufcnt; 3863dcbf3bd6SGeorge Wilson if (bufcnt >= data->hist_nbuckets) 3864dcbf3bd6SGeorge Wilson bufcnt = data->hist_nbuckets - 1; 3865dcbf3bd6SGeorge Wilson 3866dcbf3bd6SGeorge Wilson /* Ensure we stay within the bounds of the histogram array */ 3867dcbf3bd6SGeorge Wilson ASSERT3U(cbucket, <, data->hist_nbuckets); 3868dcbf3bd6SGeorge Wilson ASSERT3U(ubucket, <, data->hist_nbuckets); 3869dcbf3bd6SGeorge Wilson 3870dcbf3bd6SGeorge Wilson if (hdr.b_l1hdr.b_state == data->anon_sym.st_value) { 3871dcbf3bd6SGeorge Wilson data->anon_c_hist[cbucket]++; 3872dcbf3bd6SGeorge Wilson data->anon_u_hist[ubucket]++; 3873dcbf3bd6SGeorge Wilson data->anon_bufs[bufcnt]++; 3874dcbf3bd6SGeorge Wilson } else if (hdr.b_l1hdr.b_state == data->mru_sym.st_value) { 3875dcbf3bd6SGeorge Wilson data->mru_c_hist[cbucket]++; 3876dcbf3bd6SGeorge Wilson data->mru_u_hist[ubucket]++; 3877dcbf3bd6SGeorge Wilson data->mru_bufs[bufcnt]++; 3878dcbf3bd6SGeorge Wilson } else if (hdr.b_l1hdr.b_state == data->mfu_sym.st_value) { 3879dcbf3bd6SGeorge Wilson data->mfu_c_hist[cbucket]++; 3880dcbf3bd6SGeorge Wilson data->mfu_u_hist[ubucket]++; 3881dcbf3bd6SGeorge Wilson data->mfu_bufs[bufcnt]++; 3882dcbf3bd6SGeorge Wilson } 3883dcbf3bd6SGeorge Wilson 3884dcbf3bd6SGeorge Wilson data->all_c_hist[cbucket]++; 3885dcbf3bd6SGeorge Wilson data->all_u_hist[ubucket]++; 3886dcbf3bd6SGeorge Wilson data->all_bufs[bufcnt]++; 3887dcbf3bd6SGeorge Wilson 3888dcbf3bd6SGeorge Wilson return (WALK_NEXT); 3889dcbf3bd6SGeorge Wilson } 3890dcbf3bd6SGeorge Wilson 3891dcbf3bd6SGeorge Wilson /* ARGSUSED */ 3892dcbf3bd6SGeorge Wilson static int 3893dcbf3bd6SGeorge Wilson arc_compression_stats(uintptr_t addr, uint_t flags, int argc, 3894dcbf3bd6SGeorge Wilson const mdb_arg_t *argv) 3895dcbf3bd6SGeorge Wilson { 3896dcbf3bd6SGeorge Wilson arc_compression_stats_data_t data = { 0 }; 3897dcbf3bd6SGeorge Wilson unsigned int max_shifted = SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; 3898dcbf3bd6SGeorge Wilson unsigned int hist_size; 3899dcbf3bd6SGeorge Wilson char range[32]; 3900dcbf3bd6SGeorge Wilson int rc = DCMD_OK; 3901dcbf3bd6SGeorge Wilson 3902dcbf3bd6SGeorge Wilson if (mdb_getopts(argc, argv, 3903dcbf3bd6SGeorge Wilson 'v', MDB_OPT_SETBITS, ARC_CFLAG_VERBOSE, &data.arc_cflags, 3904dcbf3bd6SGeorge Wilson 'a', MDB_OPT_SETBITS, ARC_CFLAG_ANON, &data.arc_cflags, 3905dcbf3bd6SGeorge Wilson 'b', MDB_OPT_SETBITS, ARC_CFLAG_BUFS, &data.arc_cflags, 3906dcbf3bd6SGeorge Wilson 'r', MDB_OPT_SETBITS, ARC_CFLAG_MRU, &data.arc_cflags, 3907dcbf3bd6SGeorge Wilson 'f', MDB_OPT_SETBITS, ARC_CFLAG_MFU, &data.arc_cflags) != argc) 3908dcbf3bd6SGeorge Wilson return (DCMD_USAGE); 3909dcbf3bd6SGeorge Wilson 3910dcbf3bd6SGeorge Wilson if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_anon", &data.anon_sym) || 3911dcbf3bd6SGeorge Wilson mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mru", &data.mru_sym) || 3912dcbf3bd6SGeorge Wilson mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mru_ghost", &data.mrug_sym) || 3913dcbf3bd6SGeorge Wilson mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mfu", &data.mfu_sym) || 3914dcbf3bd6SGeorge Wilson mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mfu_ghost", &data.mfug_sym) || 3915dcbf3bd6SGeorge Wilson mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_l2c_only", &data.l2c_sym)) { 3916dcbf3bd6SGeorge Wilson mdb_warn("can't find arc state symbol"); 3917dcbf3bd6SGeorge Wilson return (DCMD_ERR); 3918dcbf3bd6SGeorge Wilson } 3919dcbf3bd6SGeorge Wilson 3920dcbf3bd6SGeorge Wilson /* 3921dcbf3bd6SGeorge Wilson * Determine the maximum expected size for any header, and use 3922dcbf3bd6SGeorge Wilson * this to determine the number of buckets needed for each 3923dcbf3bd6SGeorge Wilson * histogram. If ARC_CFLAG_VERBOSE is specified, this value is 3924dcbf3bd6SGeorge Wilson * used directly; otherwise the log2 of the maximum size is 3925dcbf3bd6SGeorge Wilson * used. Thus, if using a log2 scale there's a maximum of 10 3926dcbf3bd6SGeorge Wilson * possible buckets, while the linear scale (when using 3927dcbf3bd6SGeorge Wilson * ARC_CFLAG_VERBOSE) has a maximum of 257 buckets. 3928dcbf3bd6SGeorge Wilson */ 3929dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_VERBOSE) 3930dcbf3bd6SGeorge Wilson data.hist_nbuckets = max_shifted + 1; 3931dcbf3bd6SGeorge Wilson else 3932dcbf3bd6SGeorge Wilson data.hist_nbuckets = highbit64(max_shifted) + 1; 3933dcbf3bd6SGeorge Wilson 3934dcbf3bd6SGeorge Wilson hist_size = sizeof (uint64_t) * data.hist_nbuckets; 3935dcbf3bd6SGeorge Wilson 3936dcbf3bd6SGeorge Wilson data.anon_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3937dcbf3bd6SGeorge Wilson data.anon_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3938dcbf3bd6SGeorge Wilson data.anon_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3939dcbf3bd6SGeorge Wilson 3940dcbf3bd6SGeorge Wilson data.mru_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3941dcbf3bd6SGeorge Wilson data.mru_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3942dcbf3bd6SGeorge Wilson data.mru_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3943dcbf3bd6SGeorge Wilson 3944dcbf3bd6SGeorge Wilson data.mfu_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3945dcbf3bd6SGeorge Wilson data.mfu_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3946dcbf3bd6SGeorge Wilson data.mfu_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3947dcbf3bd6SGeorge Wilson 3948dcbf3bd6SGeorge Wilson data.all_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3949dcbf3bd6SGeorge Wilson data.all_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3950dcbf3bd6SGeorge Wilson data.all_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3951dcbf3bd6SGeorge Wilson 3952dcbf3bd6SGeorge Wilson if (mdb_walk("arc_buf_hdr_t_full", arc_compression_stats_cb, 3953dcbf3bd6SGeorge Wilson &data) != 0) { 3954dcbf3bd6SGeorge Wilson mdb_warn("can't walk arc_buf_hdr's"); 3955dcbf3bd6SGeorge Wilson rc = DCMD_ERR; 3956dcbf3bd6SGeorge Wilson goto out; 3957dcbf3bd6SGeorge Wilson } 3958dcbf3bd6SGeorge Wilson 3959dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_VERBOSE) { 3960dcbf3bd6SGeorge Wilson rc = mdb_snprintf(range, sizeof (range), 3961dcbf3bd6SGeorge Wilson "[n*%llu, (n+1)*%llu)", SPA_MINBLOCKSIZE, 3962dcbf3bd6SGeorge Wilson SPA_MINBLOCKSIZE); 3963dcbf3bd6SGeorge Wilson } else { 3964dcbf3bd6SGeorge Wilson rc = mdb_snprintf(range, sizeof (range), 3965dcbf3bd6SGeorge Wilson "[2^(n-1)*%llu, 2^n*%llu)", SPA_MINBLOCKSIZE, 3966dcbf3bd6SGeorge Wilson SPA_MINBLOCKSIZE); 3967dcbf3bd6SGeorge Wilson } 3968dcbf3bd6SGeorge Wilson 3969dcbf3bd6SGeorge Wilson if (rc < 0) { 3970dcbf3bd6SGeorge Wilson /* snprintf failed, abort the dcmd */ 3971dcbf3bd6SGeorge Wilson rc = DCMD_ERR; 3972dcbf3bd6SGeorge Wilson goto out; 3973dcbf3bd6SGeorge Wilson } else { 3974dcbf3bd6SGeorge Wilson /* snprintf succeeded above, reset return code */ 3975dcbf3bd6SGeorge Wilson rc = DCMD_OK; 3976dcbf3bd6SGeorge Wilson } 3977dcbf3bd6SGeorge Wilson 3978dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_ANON) { 3979dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_BUFS) { 3980dcbf3bd6SGeorge Wilson mdb_printf("Histogram of the number of anon buffers " 3981dcbf3bd6SGeorge Wilson "that are associated with an arc hdr.\n"); 3982dcbf3bd6SGeorge Wilson dump_histogram(data.anon_bufs, data.hist_nbuckets, 0); 3983dcbf3bd6SGeorge Wilson mdb_printf("\n"); 3984dcbf3bd6SGeorge Wilson } 3985dcbf3bd6SGeorge Wilson mdb_printf("Histogram of compressed anon buffers.\n" 3986dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 3987dcbf3bd6SGeorge Wilson dump_histogram(data.anon_c_hist, data.hist_nbuckets, 0); 3988dcbf3bd6SGeorge Wilson mdb_printf("\n"); 3989dcbf3bd6SGeorge Wilson 3990dcbf3bd6SGeorge Wilson mdb_printf("Histogram of uncompressed anon buffers.\n" 3991dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 3992dcbf3bd6SGeorge Wilson dump_histogram(data.anon_u_hist, data.hist_nbuckets, 0); 3993dcbf3bd6SGeorge Wilson mdb_printf("\n"); 3994dcbf3bd6SGeorge Wilson } 3995dcbf3bd6SGeorge Wilson 3996dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_MRU) { 3997dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_BUFS) { 3998dcbf3bd6SGeorge Wilson mdb_printf("Histogram of the number of mru buffers " 3999dcbf3bd6SGeorge Wilson "that are associated with an arc hdr.\n"); 4000dcbf3bd6SGeorge Wilson dump_histogram(data.mru_bufs, data.hist_nbuckets, 0); 4001dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4002dcbf3bd6SGeorge Wilson } 4003dcbf3bd6SGeorge Wilson mdb_printf("Histogram of compressed mru buffers.\n" 4004dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4005dcbf3bd6SGeorge Wilson dump_histogram(data.mru_c_hist, data.hist_nbuckets, 0); 4006dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4007dcbf3bd6SGeorge Wilson 4008dcbf3bd6SGeorge Wilson mdb_printf("Histogram of uncompressed mru buffers.\n" 4009dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4010dcbf3bd6SGeorge Wilson dump_histogram(data.mru_u_hist, data.hist_nbuckets, 0); 4011dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4012dcbf3bd6SGeorge Wilson } 4013dcbf3bd6SGeorge Wilson 4014dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_MFU) { 4015dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_BUFS) { 4016dcbf3bd6SGeorge Wilson mdb_printf("Histogram of the number of mfu buffers " 4017dcbf3bd6SGeorge Wilson "that are associated with an arc hdr.\n"); 4018dcbf3bd6SGeorge Wilson dump_histogram(data.mfu_bufs, data.hist_nbuckets, 0); 4019dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4020dcbf3bd6SGeorge Wilson } 4021dcbf3bd6SGeorge Wilson 4022dcbf3bd6SGeorge Wilson mdb_printf("Histogram of compressed mfu buffers.\n" 4023dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4024dcbf3bd6SGeorge Wilson dump_histogram(data.mfu_c_hist, data.hist_nbuckets, 0); 4025dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4026dcbf3bd6SGeorge Wilson 4027dcbf3bd6SGeorge Wilson mdb_printf("Histogram of uncompressed mfu buffers.\n" 4028dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4029dcbf3bd6SGeorge Wilson dump_histogram(data.mfu_u_hist, data.hist_nbuckets, 0); 4030dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4031dcbf3bd6SGeorge Wilson } 4032dcbf3bd6SGeorge Wilson 4033dcbf3bd6SGeorge Wilson if (data.arc_cflags & ARC_CFLAG_BUFS) { 4034dcbf3bd6SGeorge Wilson mdb_printf("Histogram of all buffers that " 4035dcbf3bd6SGeorge Wilson "are associated with an arc hdr.\n"); 4036dcbf3bd6SGeorge Wilson dump_histogram(data.all_bufs, data.hist_nbuckets, 0); 4037dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4038dcbf3bd6SGeorge Wilson } 4039dcbf3bd6SGeorge Wilson 4040dcbf3bd6SGeorge Wilson mdb_printf("Histogram of all compressed buffers.\n" 4041dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4042dcbf3bd6SGeorge Wilson dump_histogram(data.all_c_hist, data.hist_nbuckets, 0); 4043dcbf3bd6SGeorge Wilson mdb_printf("\n"); 4044dcbf3bd6SGeorge Wilson 4045dcbf3bd6SGeorge Wilson mdb_printf("Histogram of all uncompressed buffers.\n" 4046dcbf3bd6SGeorge Wilson "Each bucket represents buffers of size: %s.\n", range); 4047dcbf3bd6SGeorge Wilson dump_histogram(data.all_u_hist, data.hist_nbuckets, 0); 4048dcbf3bd6SGeorge Wilson 4049dcbf3bd6SGeorge Wilson out: 4050dcbf3bd6SGeorge Wilson mdb_free(data.anon_c_hist, hist_size); 4051dcbf3bd6SGeorge Wilson mdb_free(data.anon_u_hist, hist_size); 4052dcbf3bd6SGeorge Wilson mdb_free(data.anon_bufs, hist_size); 4053dcbf3bd6SGeorge Wilson 4054dcbf3bd6SGeorge Wilson mdb_free(data.mru_c_hist, hist_size); 4055dcbf3bd6SGeorge Wilson mdb_free(data.mru_u_hist, hist_size); 4056dcbf3bd6SGeorge Wilson mdb_free(data.mru_bufs, hist_size); 4057dcbf3bd6SGeorge Wilson 4058dcbf3bd6SGeorge Wilson mdb_free(data.mfu_c_hist, hist_size); 4059dcbf3bd6SGeorge Wilson mdb_free(data.mfu_u_hist, hist_size); 4060dcbf3bd6SGeorge Wilson mdb_free(data.mfu_bufs, hist_size); 4061dcbf3bd6SGeorge Wilson 4062dcbf3bd6SGeorge Wilson mdb_free(data.all_c_hist, hist_size); 4063dcbf3bd6SGeorge Wilson mdb_free(data.all_u_hist, hist_size); 4064dcbf3bd6SGeorge Wilson mdb_free(data.all_bufs, hist_size); 4065dcbf3bd6SGeorge Wilson 4066dcbf3bd6SGeorge Wilson return (rc); 4067dcbf3bd6SGeorge Wilson } 4068dcbf3bd6SGeorge Wilson 4069ccae0b50Seschrock /* 4070fa9e4066Sahrens * MDB module linkage information: 4071fa9e4066Sahrens * 4072fa9e4066Sahrens * We declare a list of structures describing our dcmds, and a function 4073fa9e4066Sahrens * named _mdb_init to return a pointer to our module information. 4074fa9e4066Sahrens */ 4075fa9e4066Sahrens 4076fa9e4066Sahrens static const mdb_dcmd_t dcmds[] = { 407791ebeef5Sahrens { "arc", "[-bkmg]", "print ARC variables", arc_print }, 4078fa9e4066Sahrens { "blkptr", ":", "print blkptr_t", blkptr }, 40795cabbc6bSPrashanth Sreenivasa { "dva", ":", "print dva_t", dva }, 4080fa9e4066Sahrens { "dbuf", ":", "print dmu_buf_impl_t", dbuf }, 4081fa9e4066Sahrens { "dbuf_stats", ":", "dbuf stats", dbuf_stats }, 4082fa9e4066Sahrens { "dbufs", 40834223fc7cSMark Shellenbaum "\t[-O objset_t*] [-n objset_name | \"mos\"] " 40843cb34c60Sahrens "[-o object | \"mdn\"] \n" 4085fa9e4066Sahrens "\t[-l level] [-b blkid | \"bonus\"]", 408691ebeef5Sahrens "find dmu_buf_impl_t's that match specified criteria", dbufs }, 4087fa9e4066Sahrens { "abuf_find", "dva_word[0] dva_word[1]", 4088fa9e4066Sahrens "find arc_buf_hdr_t of a specified DVA", 4089fa9e4066Sahrens abuf_find }, 40902e4c9986SGeorge Wilson { "spa", "?[-cevmMh]\n" 40912e4c9986SGeorge Wilson "\t-c display spa config\n" 40922e4c9986SGeorge Wilson "\t-e display vdev statistics\n" 40932e4c9986SGeorge Wilson "\t-v display vdev information\n" 40942e4c9986SGeorge Wilson "\t-m display metaslab statistics\n" 40952e4c9986SGeorge Wilson "\t-M display metaslab group statistics\n" 40962e4c9986SGeorge Wilson "\t-h display histogram (requires -m or -M)\n", 40972e4c9986SGeorge Wilson "spa_t summary", spa_print }, 4098fa9e4066Sahrens { "spa_config", ":", "print spa_t configuration", spa_print_config }, 4099fa9e4066Sahrens { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space }, 41002e4c9986SGeorge Wilson { "spa_vdevs", ":[-emMh]\n" 41012e4c9986SGeorge Wilson "\t-e display vdev statistics\n" 41022e4c9986SGeorge Wilson "\t-m dispaly metaslab statistics\n" 41032e4c9986SGeorge Wilson "\t-M display metaslab group statistic\n" 41042e4c9986SGeorge Wilson "\t-h display histogram (requires -m or -M)\n", 41052e4c9986SGeorge Wilson "given a spa_t, print vdev summary", spa_vdevs }, 410617f11284SSerapheim Dimitropoulos { "sm_entries", "<buffer length in bytes>", 410717f11284SSerapheim Dimitropoulos "print out space map entries from a buffer decoded", 410817f11284SSerapheim Dimitropoulos sm_entries}, 410991e2a09fSSteve Gonczi { "vdev", ":[-remMh]\n" 411091ebeef5Sahrens "\t-r display recursively\n" 41112e4c9986SGeorge Wilson "\t-e display statistics\n" 411291e2a09fSSteve Gonczi "\t-m display metaslab statistics (top level vdev only)\n" 411391e2a09fSSteve Gonczi "\t-M display metaslab group statistics (top level vdev only)\n" 41142e4c9986SGeorge Wilson "\t-h display histogram (requires -m or -M)\n", 411591ebeef5Sahrens "vdev_t summary", vdev_print }, 41162e4c9986SGeorge Wilson { "zio", ":[-cpr]\n" 4117a3f829aeSBill Moore "\t-c display children\n" 4118a3f829aeSBill Moore "\t-p display parents\n" 4119a3f829aeSBill Moore "\t-r display recursively", 4120a3f829aeSBill Moore "zio_t summary", zio_print }, 4121ccae0b50Seschrock { "zio_state", "?", "print out all zio_t structures on system or " 4122ccae0b50Seschrock "for a particular pool", zio_state }, 412388b7b0f2SMatthew Ahrens { "zfs_blkstats", ":[-v]", 412488b7b0f2SMatthew Ahrens "given a spa_t, print block type stats from last scrub", 412588b7b0f2SMatthew Ahrens zfs_blkstats }, 4126614409b5Sahrens { "zfs_params", "", "print zfs tunable parameters", zfs_params }, 412728e4da25SMatthew Ahrens { "refcount", ":[-r]\n" 412828e4da25SMatthew Ahrens "\t-r display recently removed references", 412928e4da25SMatthew Ahrens "print refcount_t holders", refcount }, 41303f1f8012SMatthew Ahrens { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf }, 41310a586ceaSMark Shellenbaum { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t", 41320a586ceaSMark Shellenbaum zfs_acl_dump }, 41330a586ceaSMark Shellenbaum { "zfs_ace", ":[-v]", "print zfs_ace", zfs_ace_print }, 41340a586ceaSMark Shellenbaum { "zfs_ace0", ":[-v]", "print zfs_ace0", zfs_ace0_print }, 41350a586ceaSMark Shellenbaum { "sa_attr_table", ":", "print SA attribute table from sa_os_t", 41360a586ceaSMark Shellenbaum sa_attr_table}, 41370a586ceaSMark Shellenbaum { "sa_attr", ": attr_id", 41380a586ceaSMark Shellenbaum "print SA attribute address when given sa_handle_t", sa_attr_print}, 413928e4da25SMatthew Ahrens { "zfs_dbgmsg", ":[-va]", 41403f9d6ad7SLin Ling "print zfs debug log", dbgmsg}, 414128e4da25SMatthew Ahrens { "rrwlock", ":", 414228e4da25SMatthew Ahrens "print rrwlock_t, including readers", rrwlock}, 41438363e80aSGeorge Wilson { "metaslab_weight", "weight", 41448363e80aSGeorge Wilson "print metaslab weight", metaslab_weight}, 41458363e80aSGeorge Wilson { "metaslab_trace", ":", 41468363e80aSGeorge Wilson "print metaslab allocation trace records", metaslab_trace}, 4147dcbf3bd6SGeorge Wilson { "arc_compression_stats", ":[-vabrf]\n" 4148dcbf3bd6SGeorge Wilson "\t-v verbose, display a linearly scaled histogram\n" 4149dcbf3bd6SGeorge Wilson "\t-a display ARC_anon state statistics individually\n" 4150dcbf3bd6SGeorge Wilson "\t-r display ARC_mru state statistics individually\n" 4151dcbf3bd6SGeorge Wilson "\t-f display ARC_mfu state statistics individually\n" 4152dcbf3bd6SGeorge Wilson "\t-b display histogram of buffer counts\n", 4153dcbf3bd6SGeorge Wilson "print a histogram of compressed arc buffer sizes", 4154dcbf3bd6SGeorge Wilson arc_compression_stats}, 4155fa9e4066Sahrens { NULL } 4156fa9e4066Sahrens }; 4157fa9e4066Sahrens 4158fa9e4066Sahrens static const mdb_walker_t walkers[] = { 4159fa9e4066Sahrens { "txg_list", "given any txg_list_t *, walk all entries in all txgs", 41605f5f7a6fSahrens txg_list_walk_init, txg_list_walk_step, NULL }, 4161fa9e4066Sahrens { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", 41625f5f7a6fSahrens txg_list0_walk_init, txg_list_walk_step, NULL }, 4163fa9e4066Sahrens { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", 41645f5f7a6fSahrens txg_list1_walk_init, txg_list_walk_step, NULL }, 4165fa9e4066Sahrens { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", 41665f5f7a6fSahrens txg_list2_walk_init, txg_list_walk_step, NULL }, 4167fa9e4066Sahrens { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", 41685f5f7a6fSahrens txg_list3_walk_init, txg_list_walk_step, NULL }, 4169ccae0b50Seschrock { "zio", "walk all zio structures, optionally for a particular spa_t", 4170ccae0b50Seschrock zio_walk_init, zio_walk_step, NULL }, 417128e4da25SMatthew Ahrens { "zio_root", 417228e4da25SMatthew Ahrens "walk all root zio_t structures, optionally for a particular spa_t", 4173ccae0b50Seschrock zio_walk_init, zio_walk_root_step, NULL }, 4174fa9e4066Sahrens { "spa", "walk all spa_t entries in the namespace", 4175fa9e4066Sahrens spa_walk_init, spa_walk_step, NULL }, 41765f5f7a6fSahrens { "metaslab", "given a spa_t *, walk all metaslab_t structures", 41775f5f7a6fSahrens metaslab_walk_init, metaslab_walk_step, NULL }, 4178dcbf3bd6SGeorge Wilson { "multilist", "given a multilist_t *, walk all list_t structures", 4179dcbf3bd6SGeorge Wilson multilist_walk_init, multilist_walk_step, NULL }, 41800a586ceaSMark Shellenbaum { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes", 41810a586ceaSMark Shellenbaum zfs_acl_node_walk_init, zfs_acl_node_walk_step, NULL }, 41820a586ceaSMark Shellenbaum { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs", 41830a586ceaSMark Shellenbaum zfs_acl_node_aces_walk_init, zfs_aces_walk_step, NULL }, 41840a586ceaSMark Shellenbaum { "zfs_acl_node_aces0", 41850a586ceaSMark Shellenbaum "given a zfs_acl_node_t, walk all ACEs as ace_t", 41860a586ceaSMark Shellenbaum zfs_acl_node_aces0_walk_init, zfs_aces_walk_step, NULL }, 4187fa9e4066Sahrens { NULL } 4188fa9e4066Sahrens }; 4189fa9e4066Sahrens 4190fa9e4066Sahrens static const mdb_modinfo_t modinfo = { 4191fa9e4066Sahrens MDB_API_VERSION, dcmds, walkers 4192fa9e4066Sahrens }; 4193fa9e4066Sahrens 4194fa9e4066Sahrens const mdb_modinfo_t * 4195fa9e4066Sahrens _mdb_init(void) 4196fa9e4066Sahrens { 4197fa9e4066Sahrens return (&modinfo); 4198fa9e4066Sahrens } 4199