1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 789 ahrens /* 22 8632 Bill * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 789 ahrens * Use is subject to license terms. 24 789 ahrens */ 25 789 ahrens 26 789 ahrens #include <mdb/mdb_ctf.h> 27 789 ahrens #include <sys/zfs_context.h> 28 789 ahrens #include <sys/mdb_modapi.h> 29 789 ahrens #include <sys/dbuf.h> 30 789 ahrens #include <sys/dmu_objset.h> 31 789 ahrens #include <sys/dsl_dir.h> 32 789 ahrens #include <sys/dsl_pool.h> 33 789 ahrens #include <sys/metaslab_impl.h> 34 789 ahrens #include <sys/space_map.h> 35 789 ahrens #include <sys/list.h> 36 789 ahrens #include <sys/spa_impl.h> 37 789 ahrens #include <sys/vdev_impl.h> 38 10407 Matthew #include <ctype.h> 39 789 ahrens 40 789 ahrens #ifndef _KERNEL 41 789 ahrens #include "../genunix/list.h" 42 789 ahrens #endif 43 789 ahrens 44 789 ahrens #ifdef _KERNEL 45 789 ahrens #define ZFS_OBJ_NAME "zfs" 46 789 ahrens #else 47 789 ahrens #define ZFS_OBJ_NAME "libzpool.so.1" 48 789 ahrens #endif 49 789 ahrens 50 789 ahrens static int 51 789 ahrens getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp, 52 789 ahrens const char *member, int len, void *buf) 53 789 ahrens { 54 789 ahrens mdb_ctf_id_t id; 55 789 ahrens ulong_t off; 56 789 ahrens char name[64]; 57 789 ahrens 58 789 ahrens if (idp == NULL) { 59 789 ahrens if (mdb_ctf_lookup_by_name(type, &id) == -1) { 60 789 ahrens mdb_warn("couldn't find type %s", type); 61 789 ahrens return (DCMD_ERR); 62 789 ahrens } 63 789 ahrens idp = &id; 64 789 ahrens } else { 65 789 ahrens type = name; 66 789 ahrens mdb_ctf_type_name(*idp, name, sizeof (name)); 67 789 ahrens } 68 789 ahrens 69 789 ahrens if (mdb_ctf_offsetof(*idp, member, &off) == -1) { 70 789 ahrens mdb_warn("couldn't find member %s of type %s\n", member, type); 71 789 ahrens return (DCMD_ERR); 72 789 ahrens } 73 789 ahrens if (off % 8 != 0) { 74 789 ahrens mdb_warn("member %s of type %s is unsupported bitfield", 75 789 ahrens member, type); 76 789 ahrens return (DCMD_ERR); 77 789 ahrens } 78 789 ahrens off /= 8; 79 789 ahrens 80 789 ahrens if (mdb_vread(buf, len, addr + off) == -1) { 81 789 ahrens mdb_warn("failed to read %s from %s at %p", 82 789 ahrens member, type, addr + off); 83 789 ahrens return (DCMD_ERR); 84 789 ahrens } 85 789 ahrens /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */ 86 789 ahrens 87 789 ahrens return (0); 88 789 ahrens } 89 789 ahrens 90 789 ahrens #define GETMEMB(addr, type, member, dest) \ 91 789 ahrens getmember(addr, #type, NULL, #member, sizeof (dest), &(dest)) 92 789 ahrens 93 789 ahrens #define GETMEMBID(addr, ctfid, member, dest) \ 94 789 ahrens getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) 95 789 ahrens 96 789 ahrens static int 97 789 ahrens getrefcount(uintptr_t addr, mdb_ctf_id_t *id, 98 789 ahrens const char *member, uint64_t *rc) 99 789 ahrens { 100 789 ahrens static int gotid; 101 789 ahrens static mdb_ctf_id_t rc_id; 102 789 ahrens ulong_t off; 103 789 ahrens 104 789 ahrens if (!gotid) { 105 789 ahrens if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { 106 789 ahrens mdb_warn("couldn't find struct refcount"); 107 789 ahrens return (DCMD_ERR); 108 789 ahrens } 109 789 ahrens gotid = TRUE; 110 789 ahrens } 111 789 ahrens 112 789 ahrens if (mdb_ctf_offsetof(*id, member, &off) == -1) { 113 789 ahrens char name[64]; 114 789 ahrens mdb_ctf_type_name(*id, name, sizeof (name)); 115 789 ahrens mdb_warn("couldn't find member %s of type %s\n", member, name); 116 789 ahrens return (DCMD_ERR); 117 789 ahrens } 118 789 ahrens off /= 8; 119 789 ahrens 120 789 ahrens return (GETMEMBID(addr + off, &rc_id, rc_count, *rc)); 121 789 ahrens } 122 789 ahrens 123 789 ahrens static int verbose; 124 789 ahrens 125 789 ahrens static int 126 789 ahrens freelist_walk_init(mdb_walk_state_t *wsp) 127 789 ahrens { 128 789 ahrens if (wsp->walk_addr == NULL) { 129 789 ahrens mdb_warn("must supply starting address\n"); 130 789 ahrens return (WALK_ERR); 131 789 ahrens } 132 789 ahrens 133 789 ahrens wsp->walk_data = 0; /* Index into the freelist */ 134 789 ahrens return (WALK_NEXT); 135 789 ahrens } 136 789 ahrens 137 789 ahrens static int 138 789 ahrens freelist_walk_step(mdb_walk_state_t *wsp) 139 789 ahrens { 140 789 ahrens uint64_t entry; 141 789 ahrens uintptr_t number = (uintptr_t)wsp->walk_data; 142 3361 ck153898 char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID", 143 3361 ck153898 "INVALID", "INVALID", "INVALID", "INVALID" }; 144 789 ahrens int mapshift = SPA_MINBLOCKSHIFT; 145 789 ahrens 146 789 ahrens if (mdb_vread(&entry, sizeof (entry), wsp->walk_addr) == -1) { 147 789 ahrens mdb_warn("failed to read freelist entry %p", wsp->walk_addr); 148 789 ahrens return (WALK_DONE); 149 789 ahrens } 150 789 ahrens wsp->walk_addr += sizeof (entry); 151 789 ahrens wsp->walk_data = (void *)(number + 1); 152 789 ahrens 153 789 ahrens if (SM_DEBUG_DECODE(entry)) { 154 789 ahrens mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n", 155 789 ahrens number, 156 789 ahrens ddata[SM_DEBUG_ACTION_DECODE(entry)], 157 789 ahrens SM_DEBUG_TXG_DECODE(entry), 158 789 ahrens SM_DEBUG_SYNCPASS_DECODE(entry)); 159 789 ahrens } else { 160 789 ahrens mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c " 161 789 ahrens "size=%06llx", number, 162 789 ahrens SM_OFFSET_DECODE(entry) << mapshift, 163 789 ahrens (SM_OFFSET_DECODE(entry) + SM_RUN_DECODE(entry)) << 164 789 ahrens mapshift, 165 789 ahrens SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 166 789 ahrens SM_RUN_DECODE(entry) << mapshift); 167 789 ahrens if (verbose) 168 789 ahrens mdb_printf(" (raw=%012llx)\n", entry); 169 789 ahrens mdb_printf("\n"); 170 789 ahrens } 171 789 ahrens return (WALK_NEXT); 172 789 ahrens } 173 789 ahrens 174 789 ahrens 175 789 ahrens static int 176 789 ahrens dataset_name(uintptr_t addr, char *buf) 177 789 ahrens { 178 789 ahrens static int gotid; 179 789 ahrens static mdb_ctf_id_t dd_id; 180 789 ahrens uintptr_t dd_parent; 181 789 ahrens char dd_myname[MAXNAMELEN]; 182 789 ahrens 183 789 ahrens if (!gotid) { 184 789 ahrens if (mdb_ctf_lookup_by_name("struct dsl_dir", 185 789 ahrens &dd_id) == -1) { 186 789 ahrens mdb_warn("couldn't find struct dsl_dir"); 187 789 ahrens return (DCMD_ERR); 188 789 ahrens } 189 789 ahrens gotid = TRUE; 190 789 ahrens } 191 789 ahrens if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) || 192 789 ahrens GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) { 193 789 ahrens return (DCMD_ERR); 194 789 ahrens } 195 789 ahrens 196 789 ahrens if (dd_parent) { 197 789 ahrens if (dataset_name(dd_parent, buf)) 198 789 ahrens return (DCMD_ERR); 199 789 ahrens strcat(buf, "/"); 200 789 ahrens } 201 789 ahrens 202 789 ahrens if (dd_myname[0]) 203 789 ahrens strcat(buf, dd_myname); 204 789 ahrens else 205 789 ahrens strcat(buf, "???"); 206 789 ahrens 207 789 ahrens return (0); 208 789 ahrens } 209 789 ahrens 210 789 ahrens static int 211 789 ahrens objset_name(uintptr_t addr, char *buf) 212 789 ahrens { 213 789 ahrens static int gotid; 214 10298 Matthew static mdb_ctf_id_t os_id, ds_id; 215 789 ahrens uintptr_t os_dsl_dataset; 216 789 ahrens char ds_snapname[MAXNAMELEN]; 217 789 ahrens uintptr_t ds_dir; 218 789 ahrens 219 789 ahrens buf[0] = '\0'; 220 789 ahrens 221 789 ahrens if (!gotid) { 222 10298 Matthew if (mdb_ctf_lookup_by_name("struct objset", 223 10298 Matthew &os_id) == -1) { 224 10298 Matthew mdb_warn("couldn't find struct objset"); 225 789 ahrens return (DCMD_ERR); 226 789 ahrens } 227 789 ahrens if (mdb_ctf_lookup_by_name("struct dsl_dataset", 228 789 ahrens &ds_id) == -1) { 229 789 ahrens mdb_warn("couldn't find struct dsl_dataset"); 230 789 ahrens return (DCMD_ERR); 231 789 ahrens } 232 789 ahrens 233 789 ahrens gotid = TRUE; 234 789 ahrens } 235 789 ahrens 236 10298 Matthew if (GETMEMBID(addr, &os_id, os_dsl_dataset, os_dsl_dataset)) 237 789 ahrens return (DCMD_ERR); 238 789 ahrens 239 789 ahrens if (os_dsl_dataset == 0) { 240 789 ahrens strcat(buf, "mos"); 241 789 ahrens return (0); 242 789 ahrens } 243 789 ahrens 244 789 ahrens if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) || 245 789 ahrens GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) { 246 789 ahrens return (DCMD_ERR); 247 789 ahrens } 248 789 ahrens 249 789 ahrens if (ds_dir && dataset_name(ds_dir, buf)) 250 789 ahrens return (DCMD_ERR); 251 789 ahrens 252 789 ahrens if (ds_snapname[0]) { 253 789 ahrens strcat(buf, "@"); 254 789 ahrens strcat(buf, ds_snapname); 255 789 ahrens } 256 789 ahrens return (0); 257 789 ahrens } 258 789 ahrens 259 789 ahrens static void 260 789 ahrens enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val, 261 789 ahrens const char *prefix) 262 789 ahrens { 263 789 ahrens const char *cp; 264 789 ahrens size_t len = strlen(prefix); 265 789 ahrens 266 789 ahrens if ((cp = mdb_ctf_enum_name(id, val)) != NULL) { 267 789 ahrens if (strncmp(cp, prefix, len) == 0) 268 789 ahrens cp += len; 269 789 ahrens (void) strncpy(out, cp, size); 270 789 ahrens } else { 271 789 ahrens mdb_snprintf(out, size, "? (%d)", val); 272 789 ahrens } 273 789 ahrens } 274 789 ahrens 275 789 ahrens /* ARGSUSED */ 276 789 ahrens static int 277 3059 ahrens zfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 278 3059 ahrens { 279 3059 ahrens /* 280 3059 ahrens * This table can be approximately generated by running: 281 3059 ahrens * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2 282 3059 ahrens */ 283 3059 ahrens static const char *params[] = { 284 3059 ahrens "arc_reduce_dnlc_percent", 285 3059 ahrens "zfs_arc_max", 286 3059 ahrens "zfs_arc_min", 287 3158 maybee "arc_shrink_shift", 288 3059 ahrens "zfs_mdcomp_disable", 289 3059 ahrens "zfs_prefetch_disable", 290 3059 ahrens "zfetch_max_streams", 291 3059 ahrens "zfetch_min_sec_reap", 292 3059 ahrens "zfetch_block_cap", 293 3059 ahrens "zfetch_array_rd_sz", 294 3059 ahrens "zfs_default_bs", 295 3059 ahrens "zfs_default_ibs", 296 3059 ahrens "metaslab_aliquot", 297 3059 ahrens "reference_tracking_enable", 298 3059 ahrens "reference_history", 299 3059 ahrens "spa_max_replication_override", 300 10922 Jeff "spa_mode_global", 301 3059 ahrens "zfs_flags", 302 6245 maybee "zfs_txg_synctime", 303 6245 maybee "zfs_txg_timeout", 304 6245 maybee "zfs_write_limit_min", 305 6245 maybee "zfs_write_limit_max", 306 6245 maybee "zfs_write_limit_shift", 307 6245 maybee "zfs_write_limit_override", 308 6245 maybee "zfs_no_write_throttle", 309 3059 ahrens "zfs_vdev_cache_max", 310 3059 ahrens "zfs_vdev_cache_size", 311 3059 ahrens "zfs_vdev_cache_bshift", 312 3059 ahrens "vdev_mirror_shift", 313 3059 ahrens "zfs_vdev_max_pending", 314 3059 ahrens "zfs_vdev_min_pending", 315 3059 ahrens "zfs_scrub_limit", 316 11147 George "zfs_no_scrub_io", 317 11147 George "zfs_no_scrub_prefetch", 318 3059 ahrens "zfs_vdev_time_shift", 319 3059 ahrens "zfs_vdev_ramp_rate", 320 3059 ahrens "zfs_vdev_aggregation_limit", 321 3059 ahrens "fzap_default_block_shift", 322 3059 ahrens "zfs_immediate_write_sz", 323 3059 ahrens "zfs_read_chunk_size", 324 3059 ahrens "zil_disable", 325 3059 ahrens "zfs_nocacheflush", 326 6245 maybee "metaslab_gang_bang", 327 9480 George "metaslab_df_alloc_threshold", 328 9480 George "metaslab_df_free_pct", 329 3059 ahrens "zio_injection_enabled", 330 3059 ahrens "zvol_immediate_write_sz", 331 3059 ahrens }; 332 3059 ahrens 333 10922 Jeff for (int i = 0; i < sizeof (params) / sizeof (params[0]); i++) { 334 3059 ahrens int sz; 335 3059 ahrens uint64_t val64; 336 3059 ahrens uint32_t *val32p = (uint32_t *)&val64; 337 3059 ahrens 338 3059 ahrens sz = mdb_readvar(&val64, params[i]); 339 3059 ahrens if (sz == 4) { 340 3059 ahrens mdb_printf("%s = 0x%x\n", params[i], *val32p); 341 3059 ahrens } else if (sz == 8) { 342 3059 ahrens mdb_printf("%s = 0x%llx\n", params[i], val64); 343 3059 ahrens } else { 344 3059 ahrens mdb_warn("variable %s not found", params[i]); 345 789 ahrens } 346 789 ahrens } 347 789 ahrens 348 789 ahrens return (DCMD_OK); 349 789 ahrens } 350 789 ahrens 351 789 ahrens /* ARGSUSED */ 352 789 ahrens static int 353 789 ahrens blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 354 789 ahrens { 355 10922 Jeff mdb_ctf_id_t type_enum, checksum_enum, compress_enum; 356 10922 Jeff char type[80], checksum[80], compress[80]; 357 10922 Jeff blkptr_t blk, *bp = &blk; 358 10922 Jeff char buf[BP_SPRINTF_LEN]; 359 789 ahrens 360 10922 Jeff if (mdb_vread(&blk, sizeof (blkptr_t), addr) == -1) { 361 789 ahrens mdb_warn("failed to read blkptr_t"); 362 789 ahrens return (DCMD_ERR); 363 789 ahrens } 364 789 ahrens 365 10922 Jeff if (mdb_ctf_lookup_by_name("enum dmu_object_type", &type_enum) == -1 || 366 10922 Jeff mdb_ctf_lookup_by_name("enum zio_checksum", &checksum_enum) == -1 || 367 10922 Jeff mdb_ctf_lookup_by_name("enum zio_compress", &compress_enum) == -1) { 368 10922 Jeff mdb_warn("Could not find blkptr enumerated types"); 369 789 ahrens return (DCMD_ERR); 370 789 ahrens } 371 789 ahrens 372 10922 Jeff enum_lookup(type, sizeof (type), type_enum, 373 10922 Jeff BP_GET_TYPE(bp), "DMU_OT_"); 374 10922 Jeff enum_lookup(checksum, sizeof (checksum), checksum_enum, 375 10922 Jeff BP_GET_CHECKSUM(bp), "ZIO_CHECKSUM_"); 376 10922 Jeff enum_lookup(compress, sizeof (compress), compress_enum, 377 10922 Jeff BP_GET_COMPRESS(bp), "ZIO_COMPRESS_"); 378 789 ahrens 379 10922 Jeff SPRINTF_BLKPTR(mdb_snprintf, '\n', buf, bp, type, checksum, compress); 380 789 ahrens 381 10922 Jeff mdb_printf("%s\n", buf); 382 789 ahrens 383 789 ahrens return (DCMD_OK); 384 789 ahrens } 385 789 ahrens 386 789 ahrens /* ARGSUSED */ 387 789 ahrens static int 388 789 ahrens dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 389 789 ahrens { 390 789 ahrens mdb_ctf_id_t id; 391 789 ahrens dmu_buf_t db; 392 789 ahrens uintptr_t objset; 393 789 ahrens uint8_t level; 394 789 ahrens uint64_t blkid; 395 789 ahrens uint64_t holds; 396 789 ahrens char objectname[32]; 397 789 ahrens char blkidname[32]; 398 789 ahrens char path[MAXNAMELEN]; 399 789 ahrens 400 789 ahrens if (DCMD_HDRSPEC(flags)) { 401 789 ahrens mdb_printf(" addr object lvl blkid holds os\n"); 402 789 ahrens } 403 789 ahrens 404 789 ahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &id) == -1) { 405 789 ahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 406 789 ahrens return (DCMD_ERR); 407 789 ahrens } 408 789 ahrens 409 789 ahrens if (GETMEMBID(addr, &id, db_objset, objset) || 410 789 ahrens GETMEMBID(addr, &id, db, db) || 411 789 ahrens GETMEMBID(addr, &id, db_level, level) || 412 789 ahrens GETMEMBID(addr, &id, db_blkid, blkid)) { 413 789 ahrens return (WALK_ERR); 414 789 ahrens } 415 789 ahrens 416 789 ahrens if (getrefcount(addr, &id, "db_holds", &holds)) { 417 789 ahrens return (WALK_ERR); 418 789 ahrens } 419 789 ahrens 420 789 ahrens if (db.db_object == DMU_META_DNODE_OBJECT) 421 789 ahrens (void) strcpy(objectname, "mdn"); 422 789 ahrens else 423 789 ahrens (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", 424 789 ahrens (u_longlong_t)db.db_object); 425 789 ahrens 426 789 ahrens if (blkid == DB_BONUS_BLKID) 427 789 ahrens (void) strcpy(blkidname, "bonus"); 428 789 ahrens else 429 789 ahrens (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", 430 789 ahrens (u_longlong_t)blkid); 431 789 ahrens 432 789 ahrens if (objset_name(objset, path)) { 433 789 ahrens return (WALK_ERR); 434 789 ahrens } 435 789 ahrens 436 789 ahrens mdb_printf("%p %8s %1u %9s %2llu %s\n", 437 789 ahrens addr, objectname, level, blkidname, holds, path); 438 789 ahrens 439 789 ahrens return (DCMD_OK); 440 789 ahrens } 441 789 ahrens 442 789 ahrens /* ARGSUSED */ 443 789 ahrens static int 444 789 ahrens dbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 445 789 ahrens { 446 789 ahrens #define HISTOSZ 32 447 789 ahrens uintptr_t dbp; 448 789 ahrens dmu_buf_impl_t db; 449 789 ahrens dbuf_hash_table_t ht; 450 789 ahrens uint64_t bucket, ndbufs; 451 789 ahrens uint64_t histo[HISTOSZ]; 452 789 ahrens uint64_t histo2[HISTOSZ]; 453 789 ahrens int i, maxidx; 454 789 ahrens 455 789 ahrens if (mdb_readvar(&ht, "dbuf_hash_table") == -1) { 456 789 ahrens mdb_warn("failed to read 'dbuf_hash_table'"); 457 789 ahrens return (DCMD_ERR); 458 789 ahrens } 459 789 ahrens 460 789 ahrens for (i = 0; i < HISTOSZ; i++) { 461 789 ahrens histo[i] = 0; 462 789 ahrens histo2[i] = 0; 463 789 ahrens } 464 789 ahrens 465 789 ahrens ndbufs = 0; 466 789 ahrens for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) { 467 789 ahrens int len; 468 789 ahrens 469 789 ahrens if (mdb_vread(&dbp, sizeof (void *), 470 789 ahrens (uintptr_t)(ht.hash_table+bucket)) == -1) { 471 789 ahrens mdb_warn("failed to read hash bucket %u at %p", 472 789 ahrens bucket, ht.hash_table+bucket); 473 789 ahrens return (DCMD_ERR); 474 789 ahrens } 475 789 ahrens 476 789 ahrens len = 0; 477 789 ahrens while (dbp != 0) { 478 789 ahrens if (mdb_vread(&db, sizeof (dmu_buf_impl_t), 479 789 ahrens dbp) == -1) { 480 789 ahrens mdb_warn("failed to read dbuf at %p", dbp); 481 789 ahrens return (DCMD_ERR); 482 789 ahrens } 483 789 ahrens dbp = (uintptr_t)db.db_hash_next; 484 789 ahrens for (i = MIN(len, HISTOSZ - 1); i >= 0; i--) 485 789 ahrens histo2[i]++; 486 789 ahrens len++; 487 789 ahrens ndbufs++; 488 789 ahrens } 489 789 ahrens 490 789 ahrens if (len >= HISTOSZ) 491 789 ahrens len = HISTOSZ-1; 492 789 ahrens histo[len]++; 493 789 ahrens } 494 789 ahrens 495 789 ahrens mdb_printf("hash table has %llu buckets, %llu dbufs " 496 789 ahrens "(avg %llu buckets/dbuf)\n", 497 789 ahrens ht.hash_table_mask+1, ndbufs, 498 789 ahrens (ht.hash_table_mask+1)/ndbufs); 499 789 ahrens 500 789 ahrens mdb_printf("\n"); 501 789 ahrens maxidx = 0; 502 789 ahrens for (i = 0; i < HISTOSZ; i++) 503 789 ahrens if (histo[i] > 0) 504 789 ahrens maxidx = i; 505 789 ahrens mdb_printf("hash chain length number of buckets\n"); 506 789 ahrens for (i = 0; i <= maxidx; i++) 507 789 ahrens mdb_printf("%u %llu\n", i, histo[i]); 508 789 ahrens 509 789 ahrens mdb_printf("\n"); 510 789 ahrens maxidx = 0; 511 789 ahrens for (i = 0; i < HISTOSZ; i++) 512 789 ahrens if (histo2[i] > 0) 513 789 ahrens maxidx = i; 514 789 ahrens mdb_printf("hash chain depth number of dbufs\n"); 515 789 ahrens for (i = 0; i <= maxidx; i++) 516 789 ahrens mdb_printf("%u or more %llu %llu%%\n", 517 789 ahrens i, histo2[i], histo2[i]*100/ndbufs); 518 789 ahrens 519 789 ahrens 520 789 ahrens return (DCMD_OK); 521 789 ahrens } 522 789 ahrens 523 789 ahrens typedef struct dbufs_data { 524 789 ahrens mdb_ctf_id_t id; 525 789 ahrens uint64_t objset; 526 789 ahrens uint64_t object; 527 789 ahrens uint64_t level; 528 789 ahrens uint64_t blkid; 529 789 ahrens char *osname; 530 789 ahrens } dbufs_data_t; 531 789 ahrens 532 789 ahrens #define DBUFS_UNSET (0xbaddcafedeadbeefULL) 533 789 ahrens 534 789 ahrens /* ARGSUSED */ 535 789 ahrens static int 536 789 ahrens dbufs_cb(uintptr_t addr, const void *unknown, void *arg) 537 789 ahrens { 538 789 ahrens dbufs_data_t *data = arg; 539 789 ahrens uintptr_t objset; 540 789 ahrens dmu_buf_t db; 541 789 ahrens uint8_t level; 542 789 ahrens uint64_t blkid; 543 789 ahrens char osname[MAXNAMELEN]; 544 789 ahrens 545 789 ahrens if (GETMEMBID(addr, &data->id, db_objset, objset) || 546 789 ahrens GETMEMBID(addr, &data->id, db, db) || 547 789 ahrens GETMEMBID(addr, &data->id, db_level, level) || 548 789 ahrens GETMEMBID(addr, &data->id, db_blkid, blkid)) { 549 789 ahrens return (WALK_ERR); 550 789 ahrens } 551 789 ahrens 552 789 ahrens if ((data->objset == DBUFS_UNSET || data->objset == objset) && 553 789 ahrens (data->osname == NULL || (objset_name(objset, osname) == 0 && 554 4055 eschrock strcmp(data->osname, osname) == 0)) && 555 789 ahrens (data->object == DBUFS_UNSET || data->object == db.db_object) && 556 789 ahrens (data->level == DBUFS_UNSET || data->level == level) && 557 789 ahrens (data->blkid == DBUFS_UNSET || data->blkid == blkid)) { 558 789 ahrens mdb_printf("%#lr\n", addr); 559 789 ahrens } 560 789 ahrens return (WALK_NEXT); 561 789 ahrens } 562 789 ahrens 563 789 ahrens /* ARGSUSED */ 564 789 ahrens static int 565 789 ahrens dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 566 789 ahrens { 567 789 ahrens dbufs_data_t data; 568 789 ahrens char *object = NULL; 569 789 ahrens char *blkid = NULL; 570 789 ahrens 571 789 ahrens data.objset = data.object = data.level = data.blkid = DBUFS_UNSET; 572 789 ahrens data.osname = NULL; 573 789 ahrens 574 789 ahrens if (mdb_getopts(argc, argv, 575 789 ahrens 'O', MDB_OPT_UINT64, &data.objset, 576 789 ahrens 'n', MDB_OPT_STR, &data.osname, 577 789 ahrens 'o', MDB_OPT_STR, &object, 578 789 ahrens 'l', MDB_OPT_UINT64, &data.level, 579 789 ahrens 'b', MDB_OPT_STR, &blkid) != argc) { 580 789 ahrens return (DCMD_USAGE); 581 789 ahrens } 582 789 ahrens 583 789 ahrens if (object) { 584 789 ahrens if (strcmp(object, "mdn") == 0) { 585 789 ahrens data.object = DMU_META_DNODE_OBJECT; 586 789 ahrens } else { 587 789 ahrens data.object = mdb_strtoull(object); 588 789 ahrens } 589 789 ahrens } 590 789 ahrens 591 789 ahrens if (blkid) { 592 789 ahrens if (strcmp(blkid, "bonus") == 0) { 593 789 ahrens data.blkid = DB_BONUS_BLKID; 594 789 ahrens } else { 595 789 ahrens data.blkid = mdb_strtoull(blkid); 596 789 ahrens } 597 789 ahrens } 598 789 ahrens 599 789 ahrens if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &data.id) == -1) { 600 789 ahrens mdb_warn("couldn't find struct dmu_buf_impl_t"); 601 789 ahrens return (DCMD_ERR); 602 789 ahrens } 603 789 ahrens 604 2459 ahrens if (mdb_walk("dmu_buf_impl_t", dbufs_cb, &data) != 0) { 605 789 ahrens mdb_warn("can't walk dbufs"); 606 789 ahrens return (DCMD_ERR); 607 789 ahrens } 608 789 ahrens 609 789 ahrens return (DCMD_OK); 610 789 ahrens } 611 789 ahrens 612 789 ahrens typedef struct abuf_find_data { 613 789 ahrens dva_t dva; 614 789 ahrens mdb_ctf_id_t id; 615 789 ahrens } abuf_find_data_t; 616 789 ahrens 617 789 ahrens /* ARGSUSED */ 618 789 ahrens static int 619 789 ahrens abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) 620 789 ahrens { 621 789 ahrens abuf_find_data_t *data = arg; 622 789 ahrens dva_t dva; 623 789 ahrens 624 789 ahrens if (GETMEMBID(addr, &data->id, b_dva, dva)) { 625 789 ahrens return (WALK_ERR); 626 789 ahrens } 627 789 ahrens 628 789 ahrens if (dva.dva_word[0] == data->dva.dva_word[0] && 629 789 ahrens dva.dva_word[1] == data->dva.dva_word[1]) { 630 789 ahrens mdb_printf("%#lr\n", addr); 631 789 ahrens } 632 789 ahrens return (WALK_NEXT); 633 789 ahrens } 634 789 ahrens 635 789 ahrens /* ARGSUSED */ 636 789 ahrens static int 637 789 ahrens abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 638 789 ahrens { 639 789 ahrens abuf_find_data_t data; 640 789 ahrens GElf_Sym sym; 641 789 ahrens int i; 642 789 ahrens const char *syms[] = { 643 2885 ahrens "ARC_mru", 644 2885 ahrens "ARC_mru_ghost", 645 2885 ahrens "ARC_mfu", 646 2885 ahrens "ARC_mfu_ghost", 647 789 ahrens }; 648 789 ahrens 649 789 ahrens if (argc != 2) 650 789 ahrens return (DCMD_USAGE); 651 789 ahrens 652 789 ahrens for (i = 0; i < 2; i ++) { 653 789 ahrens switch (argv[i].a_type) { 654 789 ahrens case MDB_TYPE_STRING: 655 789 ahrens data.dva.dva_word[i] = mdb_strtoull(argv[i].a_un.a_str); 656 789 ahrens break; 657 789 ahrens case MDB_TYPE_IMMEDIATE: 658 789 ahrens data.dva.dva_word[i] = argv[i].a_un.a_val; 659 789 ahrens break; 660 789 ahrens default: 661 789 ahrens return (DCMD_USAGE); 662 789 ahrens } 663 789 ahrens } 664 789 ahrens 665 789 ahrens if (mdb_ctf_lookup_by_name("struct arc_buf_hdr", &data.id) == -1) { 666 789 ahrens mdb_warn("couldn't find struct arc_buf_hdr"); 667 789 ahrens return (DCMD_ERR); 668 789 ahrens } 669 789 ahrens 670 789 ahrens for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { 671 789 ahrens if (mdb_lookup_by_name(syms[i], &sym)) { 672 789 ahrens mdb_warn("can't find symbol %s", syms[i]); 673 789 ahrens return (DCMD_ERR); 674 789 ahrens } 675 789 ahrens 676 789 ahrens if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { 677 789 ahrens mdb_warn("can't walk %s", syms[i]); 678 789 ahrens return (DCMD_ERR); 679 789 ahrens } 680 789 ahrens } 681 789 ahrens 682 789 ahrens return (DCMD_OK); 683 789 ahrens } 684 789 ahrens 685 3403 bmc /*ARGSUSED*/ 686 3403 bmc static int 687 3403 bmc arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 688 3403 bmc { 689 3403 bmc kstat_named_t *stats; 690 3403 bmc GElf_Sym sym; 691 4787 ahrens int nstats, i; 692 3403 bmc uint_t opt_a = FALSE; 693 4787 ahrens uint_t opt_b = FALSE; 694 4787 ahrens uint_t shift = 0; 695 4787 ahrens const char *suffix; 696 3403 bmc 697 4787 ahrens static const char *bytestats[] = { 698 4787 ahrens "p", "c", "c_min", "c_max", "size", NULL 699 4787 ahrens }; 700 4787 ahrens 701 4787 ahrens static const char *extras[] = { 702 4787 ahrens "arc_no_grow", "arc_tempreserve", 703 4787 ahrens "arc_meta_used", "arc_meta_limit", "arc_meta_max", 704 4787 ahrens NULL 705 3403 bmc }; 706 3403 bmc 707 3403 bmc if (mdb_lookup_by_name("arc_stats", &sym) == -1) { 708 3403 bmc mdb_warn("failed to find 'arc_stats'"); 709 3403 bmc return (DCMD_ERR); 710 3403 bmc } 711 3403 bmc 712 3403 bmc stats = mdb_zalloc(sym.st_size, UM_SLEEP | UM_GC); 713 3403 bmc 714 3403 bmc if (mdb_vread(stats, sym.st_size, sym.st_value) == -1) { 715 3403 bmc mdb_warn("couldn't read 'arc_stats' at %p", sym.st_value); 716 3403 bmc return (DCMD_ERR); 717 3403 bmc } 718 3403 bmc 719 3403 bmc nstats = sym.st_size / sizeof (kstat_named_t); 720 3403 bmc 721 4787 ahrens /* NB: -a / opt_a are ignored for backwards compatability */ 722 4787 ahrens if (mdb_getopts(argc, argv, 723 4787 ahrens 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 724 4787 ahrens 'b', MDB_OPT_SETBITS, TRUE, &opt_b, 725 4787 ahrens 'k', MDB_OPT_SETBITS, 10, &shift, 726 4787 ahrens 'm', MDB_OPT_SETBITS, 20, &shift, 727 4787 ahrens 'g', MDB_OPT_SETBITS, 30, &shift, 728 4787 ahrens NULL) != argc) 729 3403 bmc return (DCMD_USAGE); 730 3403 bmc 731 4787 ahrens if (!opt_b && !shift) 732 4787 ahrens shift = 20; 733 3403 bmc 734 4787 ahrens switch (shift) { 735 4787 ahrens case 0: 736 4787 ahrens suffix = "B"; 737 4787 ahrens break; 738 4787 ahrens case 10: 739 4787 ahrens suffix = "KB"; 740 4787 ahrens break; 741 4787 ahrens case 20: 742 4787 ahrens suffix = "MB"; 743 4787 ahrens break; 744 4787 ahrens case 30: 745 4787 ahrens suffix = "GB"; 746 4787 ahrens break; 747 4787 ahrens default: 748 4787 ahrens suffix = "XX"; 749 4787 ahrens } 750 4787 ahrens 751 4787 ahrens for (i = 0; i < nstats; i++) { 752 4787 ahrens int j; 753 4787 ahrens boolean_t bytes = B_FALSE; 754 4787 ahrens 755 4787 ahrens for (j = 0; bytestats[j]; j++) { 756 4787 ahrens if (strcmp(stats[i].name, bytestats[j]) == 0) { 757 4787 ahrens bytes = B_TRUE; 758 4787 ahrens break; 759 4787 ahrens } 760 3403 bmc } 761 3403 bmc 762 4787 ahrens if (bytes) { 763 4787 ahrens mdb_printf("%-25s = %9llu %s\n", stats[i].name, 764 4787 ahrens stats[i].value.ui64 >> shift, suffix); 765 4787 ahrens } else { 766 4787 ahrens mdb_printf("%-25s = %9llu\n", stats[i].name, 767 4787 ahrens stats[i].value.ui64); 768 3403 bmc } 769 3403 bmc } 770 3403 bmc 771 4787 ahrens for (i = 0; extras[i]; i++) { 772 4787 ahrens uint64_t buf; 773 3403 bmc 774 4787 ahrens if (mdb_lookup_by_name(extras[i], &sym) == -1) { 775 4787 ahrens mdb_warn("failed to find '%s'", extras[i]); 776 4787 ahrens return (DCMD_ERR); 777 4787 ahrens } 778 4787 ahrens 779 4787 ahrens if (sym.st_size != sizeof (uint64_t) && 780 4787 ahrens sym.st_size != sizeof (uint32_t)) { 781 4787 ahrens mdb_warn("expected scalar for variable '%s'\n", 782 4787 ahrens extras[i]); 783 4787 ahrens return (DCMD_ERR); 784 4787 ahrens } 785 4787 ahrens 786 4787 ahrens if (mdb_vread(&buf, sym.st_size, sym.st_value) == -1) { 787 4787 ahrens mdb_warn("couldn't read '%s'", extras[i]); 788 4787 ahrens return (DCMD_ERR); 789 4787 ahrens } 790 4787 ahrens 791 4787 ahrens mdb_printf("%-25s = ", extras[i]); 792 4787 ahrens 793 4787 ahrens /* NB: all the 64-bit extras happen to be byte counts */ 794 4787 ahrens if (sym.st_size == sizeof (uint64_t)) 795 4787 ahrens mdb_printf("%9llu %s\n", buf >> shift, suffix); 796 4787 ahrens 797 4787 ahrens if (sym.st_size == sizeof (uint32_t)) 798 4787 ahrens mdb_printf("%9d\n", *((uint32_t *)&buf)); 799 4787 ahrens } 800 3403 bmc return (DCMD_OK); 801 789 ahrens } 802 789 ahrens 803 789 ahrens /* 804 789 ahrens * ::spa 805 789 ahrens * 806 789 ahrens * -c Print configuration information as well 807 789 ahrens * -v Print vdev state 808 789 ahrens * -e Print vdev error stats 809 789 ahrens * 810 789 ahrens * Print a summarized spa_t. When given no arguments, prints out a table of all 811 789 ahrens * active pools on the system. 812 789 ahrens */ 813 789 ahrens /* ARGSUSED */ 814 789 ahrens static int 815 789 ahrens spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 816 789 ahrens { 817 789 ahrens spa_t spa; 818 789 ahrens const char *statetab[] = { "ACTIVE", "EXPORTED", "DESTROYED", 819 7754 Jeff "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" }; 820 789 ahrens const char *state; 821 789 ahrens int config = FALSE; 822 789 ahrens int vdevs = FALSE; 823 789 ahrens int errors = FALSE; 824 789 ahrens 825 789 ahrens if (mdb_getopts(argc, argv, 826 789 ahrens 'c', MDB_OPT_SETBITS, TRUE, &config, 827 789 ahrens 'v', MDB_OPT_SETBITS, TRUE, &vdevs, 828 789 ahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 829 789 ahrens NULL) != argc) 830 789 ahrens return (DCMD_USAGE); 831 789 ahrens 832 789 ahrens if (!(flags & DCMD_ADDRSPEC)) { 833 789 ahrens if (mdb_walk_dcmd("spa", "spa", argc, argv) == -1) { 834 789 ahrens mdb_warn("can't walk spa"); 835 789 ahrens return (DCMD_ERR); 836 789 ahrens } 837 789 ahrens 838 789 ahrens return (DCMD_OK); 839 789 ahrens } 840 789 ahrens 841 789 ahrens if (flags & DCMD_PIPE_OUT) { 842 789 ahrens mdb_printf("%#lr\n", addr); 843 789 ahrens return (DCMD_OK); 844 789 ahrens } 845 789 ahrens 846 789 ahrens if (DCMD_HDRSPEC(flags)) 847 789 ahrens mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE", 848 789 ahrens sizeof (uintptr_t) == 4 ? 60 : 52, "NAME"); 849 789 ahrens 850 789 ahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 851 789 ahrens mdb_warn("failed to read spa_t at %p", addr); 852 789 ahrens return (DCMD_ERR); 853 789 ahrens } 854 789 ahrens 855 789 ahrens if (spa.spa_state < 0 || spa.spa_state > POOL_STATE_UNAVAIL) 856 1544 eschrock state = "UNKNOWN"; 857 789 ahrens else 858 789 ahrens state = statetab[spa.spa_state]; 859 789 ahrens 860 7754 Jeff mdb_printf("%0?p %9s %s\n", addr, state, spa.spa_name); 861 789 ahrens 862 789 ahrens if (config) { 863 789 ahrens mdb_printf("\n"); 864 789 ahrens mdb_inc_indent(4); 865 789 ahrens if (mdb_call_dcmd("spa_config", addr, flags, 0, 866 789 ahrens NULL) != DCMD_OK) 867 789 ahrens return (DCMD_ERR); 868 789 ahrens mdb_dec_indent(4); 869 789 ahrens } 870 789 ahrens 871 789 ahrens if (vdevs || errors) { 872 789 ahrens mdb_arg_t v; 873 789 ahrens 874 789 ahrens v.a_type = MDB_TYPE_STRING; 875 789 ahrens v.a_un.a_str = "-e"; 876 789 ahrens 877 789 ahrens mdb_printf("\n"); 878 789 ahrens mdb_inc_indent(4); 879 789 ahrens if (mdb_call_dcmd("spa_vdevs", addr, flags, errors ? 1 : 0, 880 789 ahrens &v) != DCMD_OK) 881 789 ahrens return (DCMD_ERR); 882 789 ahrens mdb_dec_indent(4); 883 789 ahrens } 884 789 ahrens 885 789 ahrens return (DCMD_OK); 886 789 ahrens } 887 789 ahrens 888 789 ahrens /* 889 789 ahrens * ::spa_config 890 789 ahrens * 891 789 ahrens * Given a spa_t, print the configuration information stored in spa_config. 892 789 ahrens * Since it's just an nvlist, format it as an indented list of name=value pairs. 893 789 ahrens * We simply read the value of spa_config and pass off to ::nvlist. 894 789 ahrens */ 895 789 ahrens /* ARGSUSED */ 896 789 ahrens static int 897 789 ahrens spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 898 789 ahrens { 899 789 ahrens spa_t spa; 900 789 ahrens 901 789 ahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 902 789 ahrens return (DCMD_USAGE); 903 789 ahrens 904 789 ahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 905 789 ahrens mdb_warn("failed to read spa_t at %p", addr); 906 789 ahrens return (DCMD_ERR); 907 789 ahrens } 908 789 ahrens 909 789 ahrens if (spa.spa_config == NULL) { 910 789 ahrens mdb_printf("(none)\n"); 911 789 ahrens return (DCMD_OK); 912 789 ahrens } 913 789 ahrens 914 789 ahrens return (mdb_call_dcmd("nvlist", (uintptr_t)spa.spa_config, flags, 915 789 ahrens 0, NULL)); 916 789 ahrens } 917 789 ahrens 918 789 ahrens /* 919 789 ahrens * ::vdev 920 789 ahrens * 921 789 ahrens * Print out a summarized vdev_t, in the following form: 922 789 ahrens * 923 789 ahrens * ADDR STATE AUX DESC 924 789 ahrens * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0 925 789 ahrens * 926 789 ahrens * If '-r' is specified, recursively visit all children. 927 789 ahrens * 928 789 ahrens * With '-e', the statistics associated with the vdev are printed as well. 929 789 ahrens */ 930 789 ahrens static int 931 3059 ahrens do_print_vdev(uintptr_t addr, int flags, int depth, int stats, 932 789 ahrens int recursive) 933 789 ahrens { 934 789 ahrens vdev_t vdev; 935 789 ahrens char desc[MAXNAMELEN]; 936 789 ahrens int c, children; 937 789 ahrens uintptr_t *child; 938 789 ahrens const char *state, *aux; 939 789 ahrens 940 789 ahrens if (mdb_vread(&vdev, sizeof (vdev), (uintptr_t)addr) == -1) { 941 789 ahrens mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr); 942 789 ahrens return (DCMD_ERR); 943 789 ahrens } 944 789 ahrens 945 789 ahrens if (flags & DCMD_PIPE_OUT) { 946 789 ahrens mdb_printf("%#lr", addr); 947 789 ahrens } else { 948 789 ahrens if (vdev.vdev_path != NULL) { 949 789 ahrens if (mdb_readstr(desc, sizeof (desc), 950 789 ahrens (uintptr_t)vdev.vdev_path) == -1) { 951 789 ahrens mdb_warn("failed to read vdev_path at %p\n", 952 789 ahrens vdev.vdev_path); 953 789 ahrens return (DCMD_ERR); 954 789 ahrens } 955 789 ahrens } else if (vdev.vdev_ops != NULL) { 956 789 ahrens vdev_ops_t ops; 957 789 ahrens if (mdb_vread(&ops, sizeof (ops), 958 789 ahrens (uintptr_t)vdev.vdev_ops) == -1) { 959 789 ahrens mdb_warn("failed to read vdev_ops at %p\n", 960 789 ahrens vdev.vdev_ops); 961 789 ahrens return (DCMD_ERR); 962 789 ahrens } 963 789 ahrens (void) strcpy(desc, ops.vdev_op_type); 964 789 ahrens } else { 965 789 ahrens (void) strcpy(desc, "<unknown>"); 966 789 ahrens } 967 789 ahrens 968 789 ahrens if (depth == 0 && DCMD_HDRSPEC(flags)) 969 789 ahrens mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n", 970 789 ahrens "ADDR", "STATE", "AUX", 971 789 ahrens sizeof (uintptr_t) == 4 ? 43 : 35, 972 789 ahrens "DESCRIPTION"); 973 789 ahrens 974 789 ahrens mdb_printf("%0?p ", addr); 975 789 ahrens 976 789 ahrens switch (vdev.vdev_state) { 977 789 ahrens case VDEV_STATE_CLOSED: 978 4055 eschrock state = "CLOSED"; 979 4055 eschrock break; 980 789 ahrens case VDEV_STATE_OFFLINE: 981 4055 eschrock state = "OFFLINE"; 982 4055 eschrock break; 983 789 ahrens case VDEV_STATE_CANT_OPEN: 984 4055 eschrock state = "CANT_OPEN"; 985 4055 eschrock break; 986 789 ahrens case VDEV_STATE_DEGRADED: 987 4055 eschrock state = "DEGRADED"; 988 4055 eschrock break; 989 789 ahrens case VDEV_STATE_HEALTHY: 990 4055 eschrock state = "HEALTHY"; 991 4055 eschrock break; 992 4451 eschrock case VDEV_STATE_REMOVED: 993 4451 eschrock state = "REMOVED"; 994 4451 eschrock break; 995 4451 eschrock case VDEV_STATE_FAULTED: 996 4451 eschrock state = "FAULTED"; 997 4451 eschrock break; 998 789 ahrens default: 999 4055 eschrock state = "UNKNOWN"; 1000 4055 eschrock break; 1001 789 ahrens } 1002 789 ahrens 1003 789 ahrens switch (vdev.vdev_stat.vs_aux) { 1004 789 ahrens case VDEV_AUX_NONE: 1005 789 ahrens aux = "-"; 1006 789 ahrens break; 1007 789 ahrens case VDEV_AUX_OPEN_FAILED: 1008 789 ahrens aux = "OPEN_FAILED"; 1009 789 ahrens break; 1010 789 ahrens case VDEV_AUX_CORRUPT_DATA: 1011 789 ahrens aux = "CORRUPT_DATA"; 1012 789 ahrens break; 1013 789 ahrens case VDEV_AUX_NO_REPLICAS: 1014 789 ahrens aux = "NO_REPLICAS"; 1015 789 ahrens break; 1016 789 ahrens case VDEV_AUX_BAD_GUID_SUM: 1017 789 ahrens aux = "BAD_GUID_SUM"; 1018 789 ahrens break; 1019 789 ahrens case VDEV_AUX_TOO_SMALL: 1020 789 ahrens aux = "TOO_SMALL"; 1021 789 ahrens break; 1022 789 ahrens case VDEV_AUX_BAD_LABEL: 1023 789 ahrens aux = "BAD_LABEL"; 1024 789 ahrens break; 1025 7294 perrin case VDEV_AUX_VERSION_NEWER: 1026 7294 perrin aux = "VERS_NEWER"; 1027 7294 perrin break; 1028 7294 perrin case VDEV_AUX_VERSION_OLDER: 1029 7294 perrin aux = "VERS_OLDER"; 1030 7294 perrin break; 1031 7294 perrin case VDEV_AUX_SPARED: 1032 7294 perrin aux = "SPARED"; 1033 7294 perrin break; 1034 7294 perrin case VDEV_AUX_ERR_EXCEEDED: 1035 7294 perrin aux = "ERR_EXCEEDED"; 1036 7294 perrin break; 1037 7294 perrin case VDEV_AUX_IO_FAILURE: 1038 7294 perrin aux = "IO_FAILURE"; 1039 7294 perrin break; 1040 7294 perrin case VDEV_AUX_BAD_LOG: 1041 7294 perrin aux = "BAD_LOG"; 1042 7294 perrin break; 1043 789 ahrens default: 1044 789 ahrens aux = "UNKNOWN"; 1045 789 ahrens break; 1046 789 ahrens } 1047 789 ahrens 1048 789 ahrens mdb_printf("%-9s %-12s %*s%s\n", state, aux, depth, "", desc); 1049 789 ahrens 1050 789 ahrens if (stats) { 1051 789 ahrens vdev_stat_t *vs = &vdev.vdev_stat; 1052 789 ahrens int i; 1053 789 ahrens 1054 789 ahrens mdb_inc_indent(4); 1055 789 ahrens mdb_printf("\n"); 1056 789 ahrens mdb_printf("%<u> %12s %12s %12s %12s " 1057 789 ahrens "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM", 1058 789 ahrens "IOCTL"); 1059 789 ahrens mdb_printf("OPS "); 1060 789 ahrens for (i = 1; i < ZIO_TYPES; i++) 1061 789 ahrens mdb_printf("%11#llx%s", vs->vs_ops[i], 1062 789 ahrens i == ZIO_TYPES - 1 ? "" : " "); 1063 789 ahrens mdb_printf("\n"); 1064 789 ahrens mdb_printf("BYTES "); 1065 789 ahrens for (i = 1; i < ZIO_TYPES; i++) 1066 789 ahrens mdb_printf("%11#llx%s", vs->vs_bytes[i], 1067 789 ahrens i == ZIO_TYPES - 1 ? "" : " "); 1068 789 ahrens 1069 789 ahrens 1070 789 ahrens mdb_printf("\n"); 1071 789 ahrens mdb_printf("EREAD %10#llx\n", vs->vs_read_errors); 1072 789 ahrens mdb_printf("EWRITE %10#llx\n", vs->vs_write_errors); 1073 789 ahrens mdb_printf("ECKSUM %10#llx\n", 1074 789 ahrens vs->vs_checksum_errors); 1075 789 ahrens mdb_dec_indent(4); 1076 789 ahrens } 1077 789 ahrens 1078 3059 ahrens if (stats) 1079 789 ahrens mdb_printf("\n"); 1080 789 ahrens } 1081 789 ahrens 1082 789 ahrens children = vdev.vdev_children; 1083 789 ahrens 1084 789 ahrens if (children == 0 || !recursive) 1085 789 ahrens return (DCMD_OK); 1086 789 ahrens 1087 789 ahrens child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1088 789 ahrens if (mdb_vread(child, children * sizeof (void *), 1089 789 ahrens (uintptr_t)vdev.vdev_child) == -1) { 1090 789 ahrens mdb_warn("failed to read vdev children at %p", vdev.vdev_child); 1091 789 ahrens return (DCMD_ERR); 1092 789 ahrens } 1093 789 ahrens 1094 789 ahrens for (c = 0; c < children; c++) { 1095 3059 ahrens if (do_print_vdev(child[c], flags, depth + 2, stats, 1096 789 ahrens recursive)) 1097 789 ahrens return (DCMD_ERR); 1098 789 ahrens } 1099 789 ahrens 1100 789 ahrens return (DCMD_OK); 1101 789 ahrens } 1102 789 ahrens 1103 789 ahrens static int 1104 789 ahrens vdev_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1105 789 ahrens { 1106 789 ahrens int recursive = FALSE; 1107 789 ahrens int stats = FALSE; 1108 6643 eschrock uint64_t depth = 0; 1109 789 ahrens 1110 789 ahrens if (mdb_getopts(argc, argv, 1111 789 ahrens 'r', MDB_OPT_SETBITS, TRUE, &recursive, 1112 789 ahrens 'e', MDB_OPT_SETBITS, TRUE, &stats, 1113 6643 eschrock 'd', MDB_OPT_UINT64, &depth, 1114 789 ahrens NULL) != argc) 1115 789 ahrens return (DCMD_USAGE); 1116 789 ahrens 1117 789 ahrens if (!(flags & DCMD_ADDRSPEC)) { 1118 789 ahrens mdb_warn("no vdev_t address given\n"); 1119 789 ahrens return (DCMD_ERR); 1120 789 ahrens } 1121 789 ahrens 1122 6643 eschrock return (do_print_vdev(addr, flags, (int)depth, stats, recursive)); 1123 789 ahrens } 1124 789 ahrens 1125 2459 ahrens typedef struct metaslab_walk_data { 1126 2459 ahrens uint64_t mw_numvdevs; 1127 2459 ahrens uintptr_t *mw_vdevs; 1128 2459 ahrens int mw_curvdev; 1129 2459 ahrens uint64_t mw_nummss; 1130 2459 ahrens uintptr_t *mw_mss; 1131 2459 ahrens int mw_curms; 1132 2459 ahrens } metaslab_walk_data_t; 1133 2459 ahrens 1134 2459 ahrens static int 1135 2459 ahrens metaslab_walk_step(mdb_walk_state_t *wsp) 1136 2459 ahrens { 1137 2459 ahrens metaslab_walk_data_t *mw = wsp->walk_data; 1138 2459 ahrens metaslab_t ms; 1139 2459 ahrens uintptr_t msp; 1140 2459 ahrens 1141 2459 ahrens if (mw->mw_curvdev >= mw->mw_numvdevs) 1142 2459 ahrens return (WALK_DONE); 1143 2459 ahrens 1144 2459 ahrens if (mw->mw_mss == NULL) { 1145 2459 ahrens uintptr_t mssp; 1146 2459 ahrens uintptr_t vdevp; 1147 2459 ahrens 1148 2459 ahrens ASSERT(mw->mw_curms == 0); 1149 2459 ahrens ASSERT(mw->mw_nummss == 0); 1150 2459 ahrens 1151 2459 ahrens vdevp = mw->mw_vdevs[mw->mw_curvdev]; 1152 2459 ahrens if (GETMEMB(vdevp, struct vdev, vdev_ms, mssp) || 1153 2459 ahrens GETMEMB(vdevp, struct vdev, vdev_ms_count, mw->mw_nummss)) { 1154 2459 ahrens return (WALK_ERR); 1155 2459 ahrens } 1156 2459 ahrens 1157 2459 ahrens mw->mw_mss = mdb_alloc(mw->mw_nummss * sizeof (void*), 1158 2459 ahrens UM_SLEEP | UM_GC); 1159 2459 ahrens if (mdb_vread(mw->mw_mss, mw->mw_nummss * sizeof (void*), 1160 2459 ahrens mssp) == -1) { 1161 2459 ahrens mdb_warn("failed to read vdev_ms at %p", mssp); 1162 2459 ahrens return (WALK_ERR); 1163 2459 ahrens } 1164 2459 ahrens } 1165 2459 ahrens 1166 2459 ahrens if (mw->mw_curms >= mw->mw_nummss) { 1167 2459 ahrens mw->mw_mss = NULL; 1168 2459 ahrens mw->mw_curms = 0; 1169 2459 ahrens mw->mw_nummss = 0; 1170 2459 ahrens mw->mw_curvdev++; 1171 2459 ahrens return (WALK_NEXT); 1172 2459 ahrens } 1173 2459 ahrens 1174 2459 ahrens msp = mw->mw_mss[mw->mw_curms]; 1175 2459 ahrens if (mdb_vread(&ms, sizeof (metaslab_t), msp) == -1) { 1176 2459 ahrens mdb_warn("failed to read metaslab_t at %p", msp); 1177 2459 ahrens return (WALK_ERR); 1178 2459 ahrens } 1179 2459 ahrens 1180 2459 ahrens mw->mw_curms++; 1181 2459 ahrens 1182 2459 ahrens return (wsp->walk_callback(msp, &ms, wsp->walk_cbdata)); 1183 2459 ahrens } 1184 2459 ahrens 1185 2459 ahrens /* ARGSUSED */ 1186 2459 ahrens static int 1187 2459 ahrens metaslab_walk_init(mdb_walk_state_t *wsp) 1188 2459 ahrens { 1189 2459 ahrens metaslab_walk_data_t *mw; 1190 2459 ahrens uintptr_t root_vdevp; 1191 2459 ahrens uintptr_t childp; 1192 2459 ahrens 1193 2459 ahrens if (wsp->walk_addr == NULL) { 1194 2459 ahrens mdb_warn("must supply address of spa_t\n"); 1195 2459 ahrens return (WALK_ERR); 1196 2459 ahrens } 1197 2459 ahrens 1198 2459 ahrens mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC); 1199 2459 ahrens 1200 2459 ahrens if (GETMEMB(wsp->walk_addr, struct spa, spa_root_vdev, root_vdevp) || 1201 2459 ahrens GETMEMB(root_vdevp, struct vdev, vdev_children, mw->mw_numvdevs) || 1202 2459 ahrens GETMEMB(root_vdevp, struct vdev, vdev_child, childp)) { 1203 2459 ahrens return (DCMD_ERR); 1204 2459 ahrens } 1205 2459 ahrens 1206 2459 ahrens mw->mw_vdevs = mdb_alloc(mw->mw_numvdevs * sizeof (void *), 1207 2459 ahrens UM_SLEEP | UM_GC); 1208 2459 ahrens if (mdb_vread(mw->mw_vdevs, mw->mw_numvdevs * sizeof (void *), 1209 2459 ahrens childp) == -1) { 1210 2459 ahrens mdb_warn("failed to read root vdev children at %p", childp); 1211 2459 ahrens return (DCMD_ERR); 1212 2459 ahrens } 1213 2459 ahrens 1214 2459 ahrens wsp->walk_data = mw; 1215 2459 ahrens 1216 2459 ahrens return (WALK_NEXT); 1217 2459 ahrens } 1218 2459 ahrens 1219 789 ahrens typedef struct mdb_spa { 1220 789 ahrens uintptr_t spa_dsl_pool; 1221 789 ahrens uintptr_t spa_root_vdev; 1222 789 ahrens } mdb_spa_t; 1223 789 ahrens 1224 789 ahrens typedef struct mdb_dsl_dir { 1225 789 ahrens uintptr_t dd_phys; 1226 789 ahrens int64_t dd_space_towrite[TXG_SIZE]; 1227 789 ahrens } mdb_dsl_dir_t; 1228 789 ahrens 1229 789 ahrens typedef struct mdb_dsl_dir_phys { 1230 789 ahrens uint64_t dd_used_bytes; 1231 789 ahrens uint64_t dd_compressed_bytes; 1232 789 ahrens uint64_t dd_uncompressed_bytes; 1233 789 ahrens } mdb_dsl_dir_phys_t; 1234 789 ahrens 1235 789 ahrens typedef struct mdb_vdev { 1236 789 ahrens uintptr_t vdev_parent; 1237 789 ahrens uintptr_t vdev_ms; 1238 789 ahrens uint64_t vdev_ms_count; 1239 789 ahrens vdev_stat_t vdev_stat; 1240 789 ahrens } mdb_vdev_t; 1241 789 ahrens 1242 789 ahrens typedef struct mdb_metaslab { 1243 789 ahrens space_map_t ms_allocmap[TXG_SIZE]; 1244 789 ahrens space_map_t ms_freemap[TXG_SIZE]; 1245 789 ahrens space_map_t ms_map; 1246 1732 bonwick space_map_obj_t ms_smo; 1247 2459 ahrens space_map_obj_t ms_smo_syncing; 1248 789 ahrens } mdb_metaslab_t; 1249 2459 ahrens 1250 2459 ahrens typedef struct space_data { 1251 2459 ahrens uint64_t ms_allocmap[TXG_SIZE]; 1252 2459 ahrens uint64_t ms_freemap[TXG_SIZE]; 1253 2459 ahrens uint64_t ms_map; 1254 2459 ahrens uint64_t avail; 1255 2459 ahrens uint64_t nowavail; 1256 2459 ahrens } space_data_t; 1257 2459 ahrens 1258 2459 ahrens /* ARGSUSED */ 1259 2459 ahrens static int 1260 2459 ahrens space_cb(uintptr_t addr, const void *unknown, void *arg) 1261 2459 ahrens { 1262 2459 ahrens space_data_t *sd = arg; 1263 2459 ahrens mdb_metaslab_t ms; 1264 2459 ahrens 1265 2459 ahrens if (GETMEMB(addr, struct metaslab, ms_allocmap, ms.ms_allocmap) || 1266 2459 ahrens GETMEMB(addr, struct metaslab, ms_freemap, ms.ms_freemap) || 1267 2459 ahrens GETMEMB(addr, struct metaslab, ms_map, ms.ms_map) || 1268 2459 ahrens GETMEMB(addr, struct metaslab, ms_smo, ms.ms_smo) || 1269 2459 ahrens GETMEMB(addr, struct metaslab, ms_smo_syncing, ms.ms_smo_syncing)) { 1270 2459 ahrens return (WALK_ERR); 1271 2459 ahrens } 1272 2459 ahrens 1273 2459 ahrens sd->ms_allocmap[0] += ms.ms_allocmap[0].sm_space; 1274 2459 ahrens sd->ms_allocmap[1] += ms.ms_allocmap[1].sm_space; 1275 2459 ahrens sd->ms_allocmap[2] += ms.ms_allocmap[2].sm_space; 1276 2459 ahrens sd->ms_allocmap[3] += ms.ms_allocmap[3].sm_space; 1277 2459 ahrens sd->ms_freemap[0] += ms.ms_freemap[0].sm_space; 1278 2459 ahrens sd->ms_freemap[1] += ms.ms_freemap[1].sm_space; 1279 2459 ahrens sd->ms_freemap[2] += ms.ms_freemap[2].sm_space; 1280 2459 ahrens sd->ms_freemap[3] += ms.ms_freemap[3].sm_space; 1281 2459 ahrens sd->ms_map += ms.ms_map.sm_space; 1282 2459 ahrens sd->avail += ms.ms_map.sm_size - ms.ms_smo.smo_alloc; 1283 2459 ahrens sd->nowavail += ms.ms_map.sm_size - ms.ms_smo_syncing.smo_alloc; 1284 2459 ahrens 1285 2459 ahrens return (WALK_NEXT); 1286 2459 ahrens } 1287 789 ahrens 1288 789 ahrens /* 1289 789 ahrens * ::spa_space [-b] 1290 789 ahrens * 1291 789 ahrens * Given a spa_t, print out it's on-disk space usage and in-core 1292 789 ahrens * estimates of future usage. If -b is given, print space in bytes. 1293 789 ahrens * Otherwise print in megabytes. 1294 789 ahrens */ 1295 789 ahrens /* ARGSUSED */ 1296 789 ahrens static int 1297 789 ahrens spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1298 789 ahrens { 1299 789 ahrens mdb_spa_t spa; 1300 789 ahrens uintptr_t dp_root_dir; 1301 789 ahrens mdb_dsl_dir_t dd; 1302 789 ahrens mdb_dsl_dir_phys_t dsp; 1303 789 ahrens uint64_t children; 1304 789 ahrens uintptr_t childaddr; 1305 2459 ahrens space_data_t sd; 1306 789 ahrens int shift = 20; 1307 789 ahrens char *suffix = "M"; 1308 789 ahrens int bits = FALSE; 1309 789 ahrens 1310 789 ahrens if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bits, NULL) != 1311 789 ahrens argc) 1312 789 ahrens return (DCMD_USAGE); 1313 789 ahrens if (!(flags & DCMD_ADDRSPEC)) 1314 789 ahrens return (DCMD_USAGE); 1315 789 ahrens 1316 789 ahrens if (bits) { 1317 789 ahrens shift = 0; 1318 789 ahrens suffix = ""; 1319 789 ahrens } 1320 789 ahrens 1321 789 ahrens if (GETMEMB(addr, struct spa, spa_dsl_pool, spa.spa_dsl_pool) || 1322 789 ahrens GETMEMB(addr, struct spa, spa_root_vdev, spa.spa_root_vdev) || 1323 789 ahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_children, children) || 1324 789 ahrens GETMEMB(spa.spa_root_vdev, struct vdev, vdev_child, childaddr) || 1325 789 ahrens GETMEMB(spa.spa_dsl_pool, struct dsl_pool, 1326 789 ahrens dp_root_dir, dp_root_dir) || 1327 789 ahrens GETMEMB(dp_root_dir, struct dsl_dir, dd_phys, dd.dd_phys) || 1328 789 ahrens GETMEMB(dp_root_dir, struct dsl_dir, 1329 789 ahrens dd_space_towrite, dd.dd_space_towrite) || 1330 789 ahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1331 2459 ahrens dd_used_bytes, dsp.dd_used_bytes) || 1332 2459 ahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1333 789 ahrens dd_compressed_bytes, dsp.dd_compressed_bytes) || 1334 789 ahrens GETMEMB(dd.dd_phys, struct dsl_dir_phys, 1335 789 ahrens dd_uncompressed_bytes, dsp.dd_uncompressed_bytes)) { 1336 789 ahrens return (DCMD_ERR); 1337 789 ahrens } 1338 789 ahrens 1339 789 ahrens mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n", 1340 789 ahrens dd.dd_space_towrite[0] >> shift, suffix, 1341 789 ahrens dd.dd_space_towrite[1] >> shift, suffix, 1342 789 ahrens dd.dd_space_towrite[2] >> shift, suffix, 1343 789 ahrens dd.dd_space_towrite[3] >> shift, suffix); 1344 789 ahrens 1345 789 ahrens mdb_printf("dd_phys.dd_used_bytes = %llu%s\n", 1346 789 ahrens dsp.dd_used_bytes >> shift, suffix); 1347 2459 ahrens mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n", 1348 2459 ahrens dsp.dd_compressed_bytes >> shift, suffix); 1349 2459 ahrens mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n", 1350 2459 ahrens dsp.dd_uncompressed_bytes >> shift, suffix); 1351 789 ahrens 1352 2459 ahrens bzero(&sd, sizeof (sd)); 1353 2459 ahrens if (mdb_pwalk("metaslab", space_cb, &sd, addr) != 0) { 1354 2459 ahrens mdb_warn("can't walk metaslabs"); 1355 2459 ahrens return (DCMD_ERR); 1356 789 ahrens } 1357 789 ahrens 1358 789 ahrens mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n", 1359 2459 ahrens sd.ms_allocmap[0] >> shift, suffix, 1360 2459 ahrens sd.ms_allocmap[1] >> shift, suffix, 1361 2459 ahrens sd.ms_allocmap[2] >> shift, suffix, 1362 2459 ahrens sd.ms_allocmap[3] >> shift, suffix); 1363 789 ahrens mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n", 1364 2459 ahrens sd.ms_freemap[0] >> shift, suffix, 1365 2459 ahrens sd.ms_freemap[1] >> shift, suffix, 1366 2459 ahrens sd.ms_freemap[2] >> shift, suffix, 1367 2459 ahrens sd.ms_freemap[3] >> shift, suffix); 1368 2459 ahrens mdb_printf("ms_map = %llu%s\n", sd.ms_map >> shift, suffix); 1369 2459 ahrens mdb_printf("last synced avail = %llu%s\n", sd.avail >> shift, suffix); 1370 2459 ahrens mdb_printf("current syncing avail = %llu%s\n", 1371 2459 ahrens sd.nowavail >> shift, suffix); 1372 789 ahrens 1373 789 ahrens return (DCMD_OK); 1374 789 ahrens } 1375 789 ahrens 1376 789 ahrens /* 1377 789 ahrens * ::spa_verify 1378 789 ahrens * 1379 789 ahrens * Given a spa_t, verify that that the pool is self-consistent. 1380 789 ahrens * Currently, it only checks to make sure that the vdev tree exists. 1381 789 ahrens */ 1382 789 ahrens /* ARGSUSED */ 1383 789 ahrens static int 1384 789 ahrens spa_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1385 789 ahrens { 1386 789 ahrens spa_t spa; 1387 789 ahrens 1388 789 ahrens if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1389 789 ahrens return (DCMD_USAGE); 1390 789 ahrens 1391 789 ahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1392 789 ahrens mdb_warn("failed to read spa_t at %p", addr); 1393 789 ahrens return (DCMD_ERR); 1394 789 ahrens } 1395 789 ahrens 1396 789 ahrens if (spa.spa_root_vdev == NULL) { 1397 789 ahrens mdb_printf("no vdev tree present\n"); 1398 789 ahrens return (DCMD_OK); 1399 789 ahrens } 1400 789 ahrens 1401 789 ahrens return (DCMD_OK); 1402 789 ahrens } 1403 789 ahrens 1404 8341 Eric static int 1405 8341 Eric spa_print_aux(spa_aux_vdev_t *sav, uint_t flags, mdb_arg_t *v, 1406 8341 Eric const char *name) 1407 8341 Eric { 1408 8341 Eric uintptr_t *aux; 1409 8341 Eric size_t len; 1410 8341 Eric int ret, i; 1411 8341 Eric 1412 8341 Eric /* 1413 8341 Eric * Iterate over aux vdevs and print those out as well. This is a 1414 8341 Eric * little annoying because we don't have a root vdev to pass to ::vdev. 1415 8341 Eric * Instead, we print a single line and then call it for each child 1416 8341 Eric * vdev. 1417 8341 Eric */ 1418 8341 Eric if (sav->sav_count != 0) { 1419 8341 Eric v[1].a_type = MDB_TYPE_STRING; 1420 8341 Eric v[1].a_un.a_str = "-d"; 1421 8341 Eric v[2].a_type = MDB_TYPE_IMMEDIATE; 1422 8341 Eric v[2].a_un.a_val = 2; 1423 8341 Eric 1424 8341 Eric len = sav->sav_count * sizeof (uintptr_t); 1425 8341 Eric aux = mdb_alloc(len, UM_SLEEP); 1426 8341 Eric if (mdb_vread(aux, len, 1427 8341 Eric (uintptr_t)sav->sav_vdevs) == -1) { 1428 8341 Eric mdb_free(aux, len); 1429 8341 Eric mdb_warn("failed to read l2cache vdevs at %p", 1430 8341 Eric sav->sav_vdevs); 1431 8341 Eric return (DCMD_ERR); 1432 8341 Eric } 1433 8341 Eric 1434 8341 Eric mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name); 1435 8341 Eric 1436 8341 Eric for (i = 0; i < sav->sav_count; i++) { 1437 8341 Eric ret = mdb_call_dcmd("vdev", aux[i], flags, 3, v); 1438 8341 Eric if (ret != DCMD_OK) { 1439 8341 Eric mdb_free(aux, len); 1440 8341 Eric return (ret); 1441 8341 Eric } 1442 8341 Eric } 1443 8341 Eric 1444 8341 Eric mdb_free(aux, len); 1445 8341 Eric } 1446 8341 Eric 1447 8341 Eric return (0); 1448 8341 Eric } 1449 8341 Eric 1450 789 ahrens /* 1451 789 ahrens * ::spa_vdevs 1452 789 ahrens * 1453 789 ahrens * -e Include error stats 1454 789 ahrens * 1455 789 ahrens * Print out a summarized list of vdevs for the given spa_t. 1456 6643 eschrock * This is accomplished by invoking "::vdev -re" on the root vdev, as well as 1457 6643 eschrock * iterating over the cache devices. 1458 789 ahrens */ 1459 789 ahrens /* ARGSUSED */ 1460 789 ahrens static int 1461 789 ahrens spa_vdevs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1462 789 ahrens { 1463 789 ahrens spa_t spa; 1464 6643 eschrock mdb_arg_t v[3]; 1465 789 ahrens int errors = FALSE; 1466 8341 Eric int ret; 1467 789 ahrens 1468 789 ahrens if (mdb_getopts(argc, argv, 1469 789 ahrens 'e', MDB_OPT_SETBITS, TRUE, &errors, 1470 789 ahrens NULL) != argc) 1471 789 ahrens return (DCMD_USAGE); 1472 789 ahrens 1473 789 ahrens if (!(flags & DCMD_ADDRSPEC)) 1474 789 ahrens return (DCMD_USAGE); 1475 789 ahrens 1476 789 ahrens if (mdb_vread(&spa, sizeof (spa), addr) == -1) { 1477 789 ahrens mdb_warn("failed to read spa_t at %p", addr); 1478 789 ahrens return (DCMD_ERR); 1479 789 ahrens } 1480 789 ahrens 1481 952 eschrock /* 1482 952 eschrock * Unitialized spa_t structures can have a NULL root vdev. 1483 952 eschrock */ 1484 952 eschrock if (spa.spa_root_vdev == NULL) { 1485 952 eschrock mdb_printf("no associated vdevs\n"); 1486 952 eschrock return (DCMD_OK); 1487 952 eschrock } 1488 952 eschrock 1489 6643 eschrock v[0].a_type = MDB_TYPE_STRING; 1490 6643 eschrock v[0].a_un.a_str = errors ? "-re" : "-r"; 1491 789 ahrens 1492 6643 eschrock ret = mdb_call_dcmd("vdev", (uintptr_t)spa.spa_root_vdev, 1493 6643 eschrock flags, 1, v); 1494 6643 eschrock if (ret != DCMD_OK) 1495 6643 eschrock return (ret); 1496 6643 eschrock 1497 8341 Eric if (spa_print_aux(&spa.spa_l2cache, flags, v, "cache") != 0 || 1498 8341 Eric spa_print_aux(&spa.spa_spares, flags, v, "spares") != 0) 1499 8341 Eric return (DCMD_ERR); 1500 6643 eschrock 1501 6643 eschrock return (DCMD_OK); 1502 789 ahrens } 1503 789 ahrens 1504 4055 eschrock /* 1505 4055 eschrock * ::zio 1506 4055 eschrock * 1507 4055 eschrock * Print a summary of zio_t and all its children. This is intended to display a 1508 4055 eschrock * zio tree, and hence we only pick the most important pieces of information for 1509 4055 eschrock * the main summary. More detailed information can always be found by doing a 1510 4055 eschrock * '::print zio' on the underlying zio_t. The columns we display are: 1511 4055 eschrock * 1512 4055 eschrock * ADDRESS TYPE STAGE WAITER 1513 4055 eschrock * 1514 4055 eschrock * The 'address' column is indented by one space for each depth level as we 1515 4055 eschrock * descend down the tree. 1516 4055 eschrock */ 1517 4217 eschrock 1518 8632 Bill #define ZIO_MAXINDENT 24 1519 8632 Bill #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT) 1520 8632 Bill #define ZIO_WALK_SELF 0 1521 8632 Bill #define ZIO_WALK_CHILD 1 1522 8632 Bill #define ZIO_WALK_PARENT 2 1523 8632 Bill 1524 8632 Bill typedef struct zio_print_args { 1525 8632 Bill int zpa_current_depth; 1526 8632 Bill int zpa_min_depth; 1527 8632 Bill int zpa_max_depth; 1528 8632 Bill int zpa_type; 1529 8632 Bill uint_t zpa_flags; 1530 8632 Bill } zio_print_args_t; 1531 8632 Bill 1532 8632 Bill static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg); 1533 4217 eschrock 1534 4055 eschrock static int 1535 4055 eschrock zio_print_cb(uintptr_t addr, const void *data, void *priv) 1536 4055 eschrock { 1537 4055 eschrock const zio_t *zio = data; 1538 8632 Bill zio_print_args_t *zpa = priv; 1539 4055 eschrock mdb_ctf_id_t type_enum, stage_enum; 1540 8632 Bill int indent = zpa->zpa_current_depth; 1541 4055 eschrock const char *type, *stage; 1542 8632 Bill uintptr_t laddr; 1543 4055 eschrock 1544 8632 Bill if (indent > ZIO_MAXINDENT) 1545 8632 Bill indent = ZIO_MAXINDENT; 1546 4055 eschrock 1547 4055 eschrock if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum) == -1 || 1548 4055 eschrock mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum) == -1) { 1549 4055 eschrock mdb_warn("failed to lookup zio enums"); 1550 4055 eschrock return (WALK_ERR); 1551 4055 eschrock } 1552 4055 eschrock 1553 4055 eschrock if ((type = mdb_ctf_enum_name(type_enum, zio->io_type)) != NULL) 1554 4055 eschrock type += sizeof ("ZIO_TYPE_") - 1; 1555 4055 eschrock else 1556 4055 eschrock type = "?"; 1557 4055 eschrock 1558 4055 eschrock if ((stage = mdb_ctf_enum_name(stage_enum, zio->io_stage)) != NULL) 1559 4055 eschrock stage += sizeof ("ZIO_STAGE_") - 1; 1560 4055 eschrock else 1561 4055 eschrock stage = "?"; 1562 4055 eschrock 1563 8632 Bill if (zpa->zpa_current_depth >= zpa->zpa_min_depth) { 1564 8632 Bill if (zpa->zpa_flags & DCMD_PIPE_OUT) { 1565 8632 Bill mdb_printf("%?p\n", addr); 1566 8632 Bill } else { 1567 8632 Bill mdb_printf("%*s%-*p %-5s %-16s ", indent, "", 1568 8632 Bill ZIO_MAXWIDTH - indent, addr, type, stage); 1569 8632 Bill if (zio->io_waiter) 1570 8632 Bill mdb_printf("%?p\n", zio->io_waiter); 1571 8632 Bill else 1572 8632 Bill mdb_printf("-\n"); 1573 8632 Bill } 1574 8632 Bill } 1575 4055 eschrock 1576 8632 Bill if (zpa->zpa_current_depth >= zpa->zpa_max_depth) 1577 8632 Bill return (WALK_NEXT); 1578 8632 Bill 1579 8632 Bill if (zpa->zpa_type == ZIO_WALK_PARENT) 1580 8632 Bill laddr = addr + OFFSETOF(zio_t, io_parent_list); 1581 4055 eschrock else 1582 8632 Bill laddr = addr + OFFSETOF(zio_t, io_child_list); 1583 4055 eschrock 1584 8632 Bill zpa->zpa_current_depth++; 1585 8632 Bill if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) { 1586 8632 Bill mdb_warn("failed to walk zio_t children at %p\n", laddr); 1587 4055 eschrock return (WALK_ERR); 1588 4055 eschrock } 1589 8632 Bill zpa->zpa_current_depth--; 1590 4055 eschrock 1591 4055 eschrock return (WALK_NEXT); 1592 4055 eschrock } 1593 4055 eschrock 1594 8632 Bill /* ARGSUSED */ 1595 8632 Bill static int 1596 8632 Bill zio_child_cb(uintptr_t addr, const void *unknown, void *arg) 1597 8632 Bill { 1598 8632 Bill zio_link_t zl; 1599 8632 Bill zio_t zio; 1600 8632 Bill uintptr_t ziop; 1601 8632 Bill zio_print_args_t *zpa = arg; 1602 8632 Bill 1603 8632 Bill if (mdb_vread(&zl, sizeof (zl), addr) == -1) { 1604 8632 Bill mdb_warn("failed to read zio_link_t at %p", addr); 1605 8632 Bill return (WALK_ERR); 1606 8632 Bill } 1607 8632 Bill 1608 8632 Bill if (zpa->zpa_type == ZIO_WALK_PARENT) 1609 8632 Bill ziop = (uintptr_t)zl.zl_parent; 1610 8632 Bill else 1611 8632 Bill ziop = (uintptr_t)zl.zl_child; 1612 8632 Bill 1613 8632 Bill if (mdb_vread(&zio, sizeof (zio_t), ziop) == -1) { 1614 8632 Bill mdb_warn("failed to read zio_t at %p", ziop); 1615 8632 Bill return (WALK_ERR); 1616 8632 Bill } 1617 8632 Bill 1618 8632 Bill return (zio_print_cb(ziop, &zio, arg)); 1619 8632 Bill } 1620 8632 Bill 1621 8632 Bill /* ARGSUSED */ 1622 4055 eschrock static int 1623 4055 eschrock zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1624 4055 eschrock { 1625 4055 eschrock zio_t zio; 1626 8632 Bill zio_print_args_t zpa = { 0 }; 1627 4055 eschrock 1628 4055 eschrock if (!(flags & DCMD_ADDRSPEC)) 1629 4055 eschrock return (DCMD_USAGE); 1630 8632 Bill 1631 8632 Bill if (mdb_getopts(argc, argv, 1632 8632 Bill 'r', MDB_OPT_SETBITS, INT_MAX, &zpa.zpa_max_depth, 1633 8632 Bill 'c', MDB_OPT_SETBITS, ZIO_WALK_CHILD, &zpa.zpa_type, 1634 8632 Bill 'p', MDB_OPT_SETBITS, ZIO_WALK_PARENT, &zpa.zpa_type, 1635 8632 Bill NULL) != argc) 1636 8632 Bill return (DCMD_USAGE); 1637 8632 Bill 1638 8632 Bill zpa.zpa_flags = flags; 1639 8632 Bill if (zpa.zpa_max_depth != 0) { 1640 8632 Bill if (zpa.zpa_type == ZIO_WALK_SELF) 1641 8632 Bill zpa.zpa_type = ZIO_WALK_CHILD; 1642 8632 Bill } else if (zpa.zpa_type != ZIO_WALK_SELF) { 1643 8632 Bill zpa.zpa_min_depth = 1; 1644 8632 Bill zpa.zpa_max_depth = 1; 1645 8632 Bill } 1646 4055 eschrock 1647 4055 eschrock if (mdb_vread(&zio, sizeof (zio_t), addr) == -1) { 1648 4055 eschrock mdb_warn("failed to read zio_t at %p", addr); 1649 4055 eschrock return (DCMD_ERR); 1650 4055 eschrock } 1651 4217 eschrock 1652 8632 Bill if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) 1653 8632 Bill mdb_printf("%<u>%-*s %-5s %-16s %-?s%</u>\n", ZIO_MAXWIDTH, 1654 4217 eschrock "ADDRESS", "TYPE", "STAGE", "WAITER"); 1655 4055 eschrock 1656 8632 Bill if (zio_print_cb(addr, &zio, &zpa) != WALK_NEXT) 1657 4055 eschrock return (DCMD_ERR); 1658 4055 eschrock 1659 4055 eschrock return (DCMD_OK); 1660 4055 eschrock } 1661 4055 eschrock 1662 4055 eschrock /* 1663 4055 eschrock * [addr]::zio_state 1664 4055 eschrock * 1665 4055 eschrock * Print a summary of all zio_t structures on the system, or for a particular 1666 4055 eschrock * pool. This is equivalent to '::walk zio_root | ::zio'. 1667 4055 eschrock */ 1668 4055 eschrock /*ARGSUSED*/ 1669 4055 eschrock static int 1670 4055 eschrock zio_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1671 4055 eschrock { 1672 4055 eschrock /* 1673 4055 eschrock * MDB will remember the last address of the pipeline, so if we don't 1674 4055 eschrock * zero this we'll end up trying to walk zio structures for a 1675 4055 eschrock * non-existent spa_t. 1676 4055 eschrock */ 1677 4055 eschrock if (!(flags & DCMD_ADDRSPEC)) 1678 4055 eschrock addr = 0; 1679 4055 eschrock 1680 4055 eschrock return (mdb_pwalk_dcmd("zio_root", "zio", argc, argv, addr)); 1681 4055 eschrock } 1682 4055 eschrock 1683 789 ahrens typedef struct txg_list_walk_data { 1684 789 ahrens uintptr_t lw_head[TXG_SIZE]; 1685 789 ahrens int lw_txgoff; 1686 789 ahrens int lw_maxoff; 1687 789 ahrens size_t lw_offset; 1688 789 ahrens void *lw_obj; 1689 789 ahrens } txg_list_walk_data_t; 1690 789 ahrens 1691 789 ahrens static int 1692 789 ahrens txg_list_walk_init_common(mdb_walk_state_t *wsp, int txg, int maxoff) 1693 789 ahrens { 1694 789 ahrens txg_list_walk_data_t *lwd; 1695 789 ahrens txg_list_t list; 1696 789 ahrens int i; 1697 789 ahrens 1698 789 ahrens lwd = mdb_alloc(sizeof (txg_list_walk_data_t), UM_SLEEP | UM_GC); 1699 789 ahrens if (mdb_vread(&list, sizeof (txg_list_t), wsp->walk_addr) == -1) { 1700 789 ahrens mdb_warn("failed to read txg_list_t at %#lx", wsp->walk_addr); 1701 789 ahrens return (WALK_ERR); 1702 789 ahrens } 1703 789 ahrens 1704 789 ahrens for (i = 0; i < TXG_SIZE; i++) 1705 789 ahrens lwd->lw_head[i] = (uintptr_t)list.tl_head[i]; 1706 789 ahrens lwd->lw_offset = list.tl_offset; 1707 789 ahrens lwd->lw_obj = mdb_alloc(lwd->lw_offset + sizeof (txg_node_t), 1708 789 ahrens UM_SLEEP | UM_GC); 1709 789 ahrens lwd->lw_txgoff = txg; 1710 789 ahrens lwd->lw_maxoff = maxoff; 1711 789 ahrens 1712 789 ahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1713 789 ahrens wsp->walk_data = lwd; 1714 789 ahrens 1715 789 ahrens return (WALK_NEXT); 1716 789 ahrens } 1717 789 ahrens 1718 789 ahrens static int 1719 789 ahrens txg_list_walk_init(mdb_walk_state_t *wsp) 1720 789 ahrens { 1721 789 ahrens return (txg_list_walk_init_common(wsp, 0, TXG_SIZE-1)); 1722 789 ahrens } 1723 789 ahrens 1724 789 ahrens static int 1725 789 ahrens txg_list0_walk_init(mdb_walk_state_t *wsp) 1726 789 ahrens { 1727 789 ahrens return (txg_list_walk_init_common(wsp, 0, 0)); 1728 789 ahrens } 1729 789 ahrens 1730 789 ahrens static int 1731 789 ahrens txg_list1_walk_init(mdb_walk_state_t *wsp) 1732 789 ahrens { 1733 789 ahrens return (txg_list_walk_init_common(wsp, 1, 1)); 1734 789 ahrens } 1735 789 ahrens 1736 789 ahrens static int 1737 789 ahrens txg_list2_walk_init(mdb_walk_state_t *wsp) 1738 789 ahrens { 1739 789 ahrens return (txg_list_walk_init_common(wsp, 2, 2)); 1740 789 ahrens } 1741 789 ahrens 1742 789 ahrens static int 1743 789 ahrens txg_list3_walk_init(mdb_walk_state_t *wsp) 1744 789 ahrens { 1745 789 ahrens return (txg_list_walk_init_common(wsp, 3, 3)); 1746 789 ahrens } 1747 789 ahrens 1748 789 ahrens static int 1749 789 ahrens txg_list_walk_step(mdb_walk_state_t *wsp) 1750 789 ahrens { 1751 789 ahrens txg_list_walk_data_t *lwd = wsp->walk_data; 1752 789 ahrens uintptr_t addr; 1753 789 ahrens txg_node_t *node; 1754 789 ahrens int status; 1755 789 ahrens 1756 789 ahrens while (wsp->walk_addr == NULL && lwd->lw_txgoff < lwd->lw_maxoff) { 1757 789 ahrens lwd->lw_txgoff++; 1758 789 ahrens wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 1759 789 ahrens } 1760 789 ahrens 1761 789 ahrens if (wsp->walk_addr == NULL) 1762 789 ahrens return (WALK_DONE); 1763 789 ahrens 1764 789 ahrens addr = wsp->walk_addr - lwd->lw_offset; 1765 789 ahrens 1766 789 ahrens if (mdb_vread(lwd->lw_obj, 1767 789 ahrens lwd->lw_offset + sizeof (txg_node_t), addr) == -1) { 1768 789 ahrens mdb_warn("failed to read list element at %#lx", addr); 1769 789 ahrens return (WALK_ERR); 1770 789 ahrens } 1771 789 ahrens 1772 789 ahrens status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata); 1773 789 ahrens node = (txg_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset); 1774 789 ahrens wsp->walk_addr = (uintptr_t)node->tn_next[lwd->lw_txgoff]; 1775 789 ahrens 1776 789 ahrens return (status); 1777 789 ahrens } 1778 789 ahrens 1779 789 ahrens /* 1780 789 ahrens * ::walk spa 1781 789 ahrens * 1782 789 ahrens * Walk all named spa_t structures in the namespace. This is nothing more than 1783 789 ahrens * a layered avl walk. 1784 789 ahrens */ 1785 789 ahrens static int 1786 789 ahrens spa_walk_init(mdb_walk_state_t *wsp) 1787 789 ahrens { 1788 789 ahrens GElf_Sym sym; 1789 789 ahrens 1790 789 ahrens if (wsp->walk_addr != NULL) { 1791 789 ahrens mdb_warn("spa walk only supports global walks\n"); 1792 789 ahrens return (WALK_ERR); 1793 789 ahrens } 1794 789 ahrens 1795 789 ahrens if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "spa_namespace_avl", &sym) == -1) { 1796 789 ahrens mdb_warn("failed to find symbol 'spa_namespace_avl'"); 1797 789 ahrens return (WALK_ERR); 1798 789 ahrens } 1799 789 ahrens 1800 789 ahrens wsp->walk_addr = (uintptr_t)sym.st_value; 1801 789 ahrens 1802 789 ahrens if (mdb_layered_walk("avl", wsp) == -1) { 1803 789 ahrens mdb_warn("failed to walk 'avl'\n"); 1804 789 ahrens return (WALK_ERR); 1805 789 ahrens } 1806 789 ahrens 1807 789 ahrens return (WALK_NEXT); 1808 789 ahrens } 1809 789 ahrens 1810 789 ahrens static int 1811 789 ahrens spa_walk_step(mdb_walk_state_t *wsp) 1812 789 ahrens { 1813 789 ahrens spa_t spa; 1814 789 ahrens 1815 789 ahrens if (mdb_vread(&spa, sizeof (spa), wsp->walk_addr) == -1) { 1816 789 ahrens mdb_warn("failed to read spa_t at %p", wsp->walk_addr); 1817 789 ahrens return (WALK_ERR); 1818 789 ahrens } 1819 789 ahrens 1820 789 ahrens return (wsp->walk_callback(wsp->walk_addr, &spa, wsp->walk_cbdata)); 1821 789 ahrens } 1822 789 ahrens 1823 789 ahrens /* 1824 4055 eschrock * [addr]::walk zio 1825 4055 eschrock * 1826 4055 eschrock * Walk all active zio_t structures on the system. This is simply a layered 1827 4055 eschrock * walk on top of ::walk zio_cache, with the optional ability to limit the 1828 4055 eschrock * structures to a particular pool. 1829 4055 eschrock */ 1830 4055 eschrock static int 1831 4055 eschrock zio_walk_init(mdb_walk_state_t *wsp) 1832 4055 eschrock { 1833 4055 eschrock wsp->walk_data = (void *)wsp->walk_addr; 1834 4055 eschrock 1835 4055 eschrock if (mdb_layered_walk("zio_cache", wsp) == -1) { 1836 4055 eschrock mdb_warn("failed to walk 'zio_cache'\n"); 1837 4055 eschrock return (WALK_ERR); 1838 4055 eschrock } 1839 4055 eschrock 1840 4055 eschrock return (WALK_NEXT); 1841 4055 eschrock } 1842 4055 eschrock 1843 4055 eschrock static int 1844 4055 eschrock zio_walk_step(mdb_walk_state_t *wsp) 1845 4055 eschrock { 1846 4055 eschrock zio_t zio; 1847 4055 eschrock 1848 4055 eschrock if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { 1849 4055 eschrock mdb_warn("failed to read zio_t at %p", wsp->walk_addr); 1850 4055 eschrock return (WALK_ERR); 1851 4055 eschrock } 1852 4055 eschrock 1853 4055 eschrock if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) 1854 4055 eschrock return (WALK_NEXT); 1855 4055 eschrock 1856 4055 eschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 1857 4055 eschrock } 1858 4055 eschrock 1859 4055 eschrock /* 1860 4055 eschrock * [addr]::walk zio_root 1861 4055 eschrock * 1862 4055 eschrock * Walk only root zio_t structures, optionally for a particular spa_t. 1863 4055 eschrock */ 1864 4055 eschrock static int 1865 4055 eschrock zio_walk_root_step(mdb_walk_state_t *wsp) 1866 4055 eschrock { 1867 4055 eschrock zio_t zio; 1868 4055 eschrock 1869 4055 eschrock if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) { 1870 4055 eschrock mdb_warn("failed to read zio_t at %p", wsp->walk_addr); 1871 4055 eschrock return (WALK_ERR); 1872 4055 eschrock } 1873 4055 eschrock 1874 4055 eschrock if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa) 1875 4055 eschrock return (WALK_NEXT); 1876 4055 eschrock 1877 8632 Bill /* If the parent list is not empty, ignore */ 1878 8632 Bill if (zio.io_parent_list.list_head.list_next != 1879 8632 Bill &((zio_t *)wsp->walk_addr)->io_parent_list.list_head) 1880 4055 eschrock return (WALK_NEXT); 1881 4055 eschrock 1882 4055 eschrock return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 1883 4055 eschrock } 1884 4055 eschrock 1885 7837 Matthew #define NICENUM_BUFLEN 6 1886 7837 Matthew 1887 7837 Matthew static int 1888 7846 Matthew snprintfrac(char *buf, int len, 1889 7846 Matthew uint64_t numerator, uint64_t denom, int frac_digits) 1890 7837 Matthew { 1891 7846 Matthew int mul = 1; 1892 7837 Matthew int whole, frac, i; 1893 7837 Matthew 1894 7837 Matthew for (i = frac_digits; i; i--) 1895 7837 Matthew mul *= 10; 1896 7846 Matthew whole = numerator / denom; 1897 7846 Matthew frac = mul * numerator / denom - mul * whole; 1898 7837 Matthew return (mdb_snprintf(buf, len, "%u.%0*u", whole, frac_digits, frac)); 1899 7837 Matthew } 1900 7837 Matthew 1901 7837 Matthew static void 1902 7837 Matthew mdb_nicenum(uint64_t num, char *buf) 1903 7837 Matthew { 1904 7837 Matthew uint64_t n = num; 1905 7837 Matthew int index = 0; 1906 7837 Matthew char *u; 1907 7837 Matthew 1908 7837 Matthew while (n >= 1024) { 1909 7837 Matthew n = (n + (1024 / 2)) / 1024; /* Round up or down */ 1910 7837 Matthew index++; 1911 7837 Matthew } 1912 7837 Matthew 1913 7837 Matthew u = &" \0K\0M\0G\0T\0P\0E\0"[index*2]; 1914 7837 Matthew 1915 7837 Matthew if (index == 0) { 1916 7837 Matthew (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu", 1917 7837 Matthew (u_longlong_t)n); 1918 7837 Matthew } else if (n < 10 && (num & (num - 1)) != 0) { 1919 7846 Matthew (void) snprintfrac(buf, NICENUM_BUFLEN, 1920 7846 Matthew num, 1ULL << 10 * index, 2); 1921 7837 Matthew strcat(buf, u); 1922 7837 Matthew } else if (n < 100 && (num & (num - 1)) != 0) { 1923 7846 Matthew (void) snprintfrac(buf, NICENUM_BUFLEN, 1924 7846 Matthew num, 1ULL << 10 * index, 1); 1925 7837 Matthew strcat(buf, u); 1926 7837 Matthew } else { 1927 7837 Matthew (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu%s", 1928 7837 Matthew (u_longlong_t)n, u); 1929 7837 Matthew } 1930 7837 Matthew } 1931 7837 Matthew 1932 7837 Matthew /* 1933 7837 Matthew * ::zfs_blkstats 1934 7837 Matthew * 1935 7837 Matthew * -v print verbose per-level information 1936 7837 Matthew * 1937 7837 Matthew */ 1938 7837 Matthew static int 1939 7837 Matthew zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1940 7837 Matthew { 1941 7837 Matthew boolean_t verbose = B_FALSE; 1942 7837 Matthew zfs_all_blkstats_t stats; 1943 7837 Matthew dmu_object_type_t t; 1944 7837 Matthew zfs_blkstat_t *tzb; 1945 7837 Matthew uint64_t ditto; 1946 7837 Matthew dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10]; 1947 7837 Matthew /* +10 in case it grew */ 1948 7837 Matthew 1949 7837 Matthew if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) { 1950 7837 Matthew mdb_warn("failed to read 'dmu_ot'"); 1951 7837 Matthew return (DCMD_ERR); 1952 7837 Matthew } 1953 7837 Matthew 1954 7837 Matthew if (mdb_getopts(argc, argv, 1955 7837 Matthew 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1956 7837 Matthew NULL) != argc) 1957 7837 Matthew return (DCMD_USAGE); 1958 7837 Matthew 1959 7837 Matthew if (!(flags & DCMD_ADDRSPEC)) 1960 7837 Matthew return (DCMD_USAGE); 1961 7837 Matthew 1962 7837 Matthew if (GETMEMB(addr, struct spa, spa_dsl_pool, addr) || 1963 7837 Matthew GETMEMB(addr, struct dsl_pool, dp_blkstats, addr) || 1964 7837 Matthew mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) { 1965 7837 Matthew mdb_warn("failed to read data at %p;", addr); 1966 7837 Matthew mdb_printf("maybe no stats? run \"zpool scrub\" first."); 1967 7837 Matthew return (DCMD_ERR); 1968 7837 Matthew } 1969 7837 Matthew 1970 7837 Matthew tzb = &stats.zab_type[DN_MAX_LEVELS][DMU_OT_NUMTYPES]; 1971 7837 Matthew if (tzb->zb_gangs != 0) { 1972 7837 Matthew mdb_printf("Ganged blocks: %llu\n", 1973 7837 Matthew (longlong_t)tzb->zb_gangs); 1974 7837 Matthew } 1975 7837 Matthew 1976 7837 Matthew ditto = tzb->zb_ditto_2_of_2_samevdev + tzb->zb_ditto_2_of_3_samevdev + 1977 7837 Matthew tzb->zb_ditto_3_of_3_samevdev; 1978 7837 Matthew if (ditto != 0) { 1979 7837 Matthew mdb_printf("Dittoed blocks on same vdev: %llu\n", 1980 7837 Matthew (longlong_t)ditto); 1981 7837 Matthew } 1982 7837 Matthew 1983 7837 Matthew mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 1984 7837 Matthew "\t avg\t comp\t%%Total\tType\n"); 1985 7837 Matthew 1986 7837 Matthew for (t = 0; t <= DMU_OT_NUMTYPES; t++) { 1987 7837 Matthew char csize[NICENUM_BUFLEN], lsize[NICENUM_BUFLEN]; 1988 7837 Matthew char psize[NICENUM_BUFLEN], asize[NICENUM_BUFLEN]; 1989 7837 Matthew char avg[NICENUM_BUFLEN]; 1990 7837 Matthew char comp[NICENUM_BUFLEN], pct[NICENUM_BUFLEN]; 1991 7837 Matthew char typename[64]; 1992 7837 Matthew int l; 1993 7837 Matthew 1994 7837 Matthew 1995 7837 Matthew if (t == DMU_OT_DEFERRED) 1996 7837 Matthew strcpy(typename, "deferred free"); 1997 7837 Matthew else if (t == DMU_OT_TOTAL) 1998 7837 Matthew strcpy(typename, "Total"); 1999 7837 Matthew else if (mdb_readstr(typename, sizeof (typename), 2000 7837 Matthew (uintptr_t)dmu_ot[t].ot_name) == -1) { 2001 7837 Matthew mdb_warn("failed to read type name"); 2002 7837 Matthew return (DCMD_ERR); 2003 7837 Matthew } 2004 7837 Matthew 2005 7837 Matthew if (stats.zab_type[DN_MAX_LEVELS][t].zb_asize == 0) 2006 7837 Matthew continue; 2007 7837 Matthew 2008 7837 Matthew for (l = -1; l < DN_MAX_LEVELS; l++) { 2009 7837 Matthew int level = (l == -1 ? DN_MAX_LEVELS : l); 2010 7837 Matthew zfs_blkstat_t *zb = &stats.zab_type[level][t]; 2011 7837 Matthew 2012 7837 Matthew if (zb->zb_asize == 0) 2013 7837 Matthew continue; 2014 7837 Matthew 2015 7837 Matthew /* 2016 7837 Matthew * Don't print each level unless requested. 2017 7837 Matthew */ 2018 7837 Matthew if (!verbose && level != DN_MAX_LEVELS) 2019 7837 Matthew continue; 2020 7837 Matthew 2021 7837 Matthew /* 2022 7837 Matthew * If all the space is level 0, don't print the 2023 7837 Matthew * level 0 separately. 2024 7837 Matthew */ 2025 7837 Matthew if (level == 0 && zb->zb_asize == 2026 7837 Matthew stats.zab_type[DN_MAX_LEVELS][t].zb_asize) 2027 7837 Matthew continue; 2028 7837 Matthew 2029 7837 Matthew mdb_nicenum(zb->zb_count, csize); 2030 7837 Matthew mdb_nicenum(zb->zb_lsize, lsize); 2031 7837 Matthew mdb_nicenum(zb->zb_psize, psize); 2032 7837 Matthew mdb_nicenum(zb->zb_asize, asize); 2033 7837 Matthew mdb_nicenum(zb->zb_asize / zb->zb_count, avg); 2034 7846 Matthew (void) snprintfrac(comp, NICENUM_BUFLEN, 2035 7846 Matthew zb->zb_lsize, zb->zb_psize, 2); 2036 7846 Matthew (void) snprintfrac(pct, NICENUM_BUFLEN, 2037 7846 Matthew 100 * zb->zb_asize, tzb->zb_asize, 2); 2038 7837 Matthew 2039 7837 Matthew mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s" 2040 7837 Matthew "\t%5s\t%6s\t", 2041 7837 Matthew csize, lsize, psize, asize, avg, comp, pct); 2042 7837 Matthew 2043 7837 Matthew if (level == DN_MAX_LEVELS) 2044 7837 Matthew mdb_printf("%s\n", typename); 2045 7837 Matthew else 2046 7837 Matthew mdb_printf(" L%d %s\n", 2047 7837 Matthew level, typename); 2048 7837 Matthew } 2049 7837 Matthew } 2050 7837 Matthew 2051 7837 Matthew return (DCMD_OK); 2052 7837 Matthew } 2053 7837 Matthew 2054 10407 Matthew /* ARGSUSED */ 2055 10407 Matthew static int 2056 10407 Matthew reference_cb(uintptr_t addr, const void *ignored, void *arg) 2057 10407 Matthew { 2058 10407 Matthew static int gotid; 2059 10407 Matthew static mdb_ctf_id_t ref_id; 2060 10407 Matthew uintptr_t ref_holder; 2061 10407 Matthew uintptr_t ref_removed; 2062 10407 Matthew uint64_t ref_number; 2063 10407 Matthew boolean_t holder_is_str; 2064 10407 Matthew char holder_str[128]; 2065 10407 Matthew boolean_t removed = (boolean_t)arg; 2066 10407 Matthew 2067 10407 Matthew if (!gotid) { 2068 10407 Matthew if (mdb_ctf_lookup_by_name("struct reference", &ref_id) == -1) { 2069 10407 Matthew mdb_warn("couldn't find struct reference"); 2070 10407 Matthew return (WALK_ERR); 2071 10407 Matthew } 2072 10407 Matthew gotid = TRUE; 2073 10407 Matthew } 2074 10407 Matthew 2075 10407 Matthew if (GETMEMBID(addr, &ref_id, ref_holder, ref_holder) || 2076 10407 Matthew GETMEMBID(addr, &ref_id, ref_removed, ref_removed) || 2077 10407 Matthew GETMEMBID(addr, &ref_id, ref_number, ref_number)) 2078 10407 Matthew return (WALK_ERR); 2079 10407 Matthew 2080 10407 Matthew if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1) { 2081 10407 Matthew char *cp; 2082 10407 Matthew holder_is_str = B_TRUE; 2083 10407 Matthew for (cp = holder_str; *cp; cp++) { 2084 10407 Matthew if (!isprint(*cp)) { 2085 10407 Matthew holder_is_str = B_FALSE; 2086 10407 Matthew break; 2087 10407 Matthew } 2088 10407 Matthew } 2089 10407 Matthew } else { 2090 10407 Matthew holder_is_str = B_FALSE; 2091 10407 Matthew } 2092 10407 Matthew 2093 10407 Matthew if (removed) 2094 10407 Matthew mdb_printf("removed "); 2095 10407 Matthew mdb_printf("reference "); 2096 10407 Matthew if (ref_number != 1) 2097 10407 Matthew mdb_printf("with count=%llu ", ref_number); 2098 10407 Matthew mdb_printf("with tag %p", (void*)ref_holder); 2099 10407 Matthew if (holder_is_str) 2100 10407 Matthew mdb_printf(" \"%s\"", holder_str); 2101 10407 Matthew mdb_printf(", held at:\n"); 2102 10407 Matthew 2103 10407 Matthew (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 2104 10407 Matthew 2105 10407 Matthew if (removed) { 2106 10407 Matthew mdb_printf("removed at:\n"); 2107 10407 Matthew (void) mdb_call_dcmd("whatis", ref_removed, 2108 10407 Matthew DCMD_ADDRSPEC, 0, NULL); 2109 10407 Matthew } 2110 10407 Matthew 2111 10407 Matthew mdb_printf("\n"); 2112 10407 Matthew 2113 10407 Matthew return (WALK_NEXT); 2114 10407 Matthew } 2115 10407 Matthew 2116 10407 Matthew /* ARGSUSED */ 2117 10407 Matthew static int 2118 10407 Matthew refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2119 10407 Matthew { 2120 10407 Matthew uint64_t rc_count, rc_removed_count; 2121 10407 Matthew uintptr_t rc_list, rc_removed; 2122 10407 Matthew static int gotid; 2123 10407 Matthew static mdb_ctf_id_t rc_id; 2124 10407 Matthew ulong_t off; 2125 10407 Matthew 2126 10407 Matthew if (!(flags & DCMD_ADDRSPEC)) 2127 10407 Matthew return (DCMD_USAGE); 2128 10407 Matthew 2129 10407 Matthew if (!gotid) { 2130 10407 Matthew if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) { 2131 10407 Matthew mdb_warn("couldn't find struct refcount"); 2132 10407 Matthew return (DCMD_ERR); 2133 10407 Matthew } 2134 10407 Matthew gotid = TRUE; 2135 10407 Matthew } 2136 10407 Matthew 2137 10407 Matthew if (GETMEMBID(addr, &rc_id, rc_count, rc_count) || 2138 10407 Matthew GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) 2139 10407 Matthew return (DCMD_ERR); 2140 10407 Matthew 2141 10407 Matthew mdb_printf("refcount_t at %p has %llu current holds, " 2142 10407 Matthew "%llu recently released holds\n", 2143 10407 Matthew addr, (longlong_t)rc_count, (longlong_t)rc_removed_count); 2144 10407 Matthew 2145 10407 Matthew if (rc_count > 0) 2146 10407 Matthew mdb_printf("current holds:\n"); 2147 10407 Matthew if (mdb_ctf_offsetof(rc_id, "rc_list", &off) == -1) 2148 10407 Matthew return (DCMD_ERR); 2149 10407 Matthew rc_list = addr + off/NBBY; 2150 10407 Matthew mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list); 2151 10407 Matthew 2152 10407 Matthew if (rc_removed_count > 0) 2153 10407 Matthew mdb_printf("released holds:\n"); 2154 10407 Matthew if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1) 2155 10407 Matthew return (DCMD_ERR); 2156 10407 Matthew rc_removed = addr + off/NBBY; 2157 10407 Matthew mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed); 2158 10407 Matthew 2159 10407 Matthew return (DCMD_OK); 2160 10407 Matthew } 2161 10407 Matthew 2162 4055 eschrock /* 2163 789 ahrens * MDB module linkage information: 2164 789 ahrens * 2165 789 ahrens * We declare a list of structures describing our dcmds, and a function 2166 789 ahrens * named _mdb_init to return a pointer to our module information. 2167 789 ahrens */ 2168 789 ahrens 2169 789 ahrens static const mdb_dcmd_t dcmds[] = { 2170 4787 ahrens { "arc", "[-bkmg]", "print ARC variables", arc_print }, 2171 789 ahrens { "blkptr", ":", "print blkptr_t", blkptr }, 2172 789 ahrens { "dbuf", ":", "print dmu_buf_impl_t", dbuf }, 2173 789 ahrens { "dbuf_stats", ":", "dbuf stats", dbuf_stats }, 2174 789 ahrens { "dbufs", 2175 10298 Matthew "\t[-O objset_t*] [-n objset_name | \"mos\"] " 2176 8632 Bill "[-o object | \"mdn\"] \n" 2177 8632 Bill "\t[-l level] [-b blkid | \"bonus\"]", 2178 8632 Bill "find dmu_buf_impl_t's that match specified criteria", dbufs }, 2179 789 ahrens { "abuf_find", "dva_word[0] dva_word[1]", 2180 8632 Bill "find arc_buf_hdr_t of a specified DVA", 2181 8632 Bill abuf_find }, 2182 789 ahrens { "spa", "?[-cv]", "spa_t summary", spa_print }, 2183 789 ahrens { "spa_config", ":", "print spa_t configuration", spa_print_config }, 2184 789 ahrens { "spa_verify", ":", "verify spa_t consistency", spa_verify }, 2185 789 ahrens { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space }, 2186 789 ahrens { "spa_vdevs", ":", "given a spa_t, print vdev summary", spa_vdevs }, 2187 4787 ahrens { "vdev", ":[-re]\n" 2188 8632 Bill "\t-r display recursively\n" 2189 8632 Bill "\t-e print statistics", 2190 8632 Bill "vdev_t summary", vdev_print }, 2191 8632 Bill { "zio", ":[cpr]\n" 2192 8632 Bill "\t-c display children\n" 2193 8632 Bill "\t-p display parents\n" 2194 8632 Bill "\t-r display recursively", 2195 8632 Bill "zio_t summary", zio_print }, 2196 4055 eschrock { "zio_state", "?", "print out all zio_t structures on system or " 2197 4055 eschrock "for a particular pool", zio_state }, 2198 7837 Matthew { "zfs_blkstats", ":[-v]", 2199 7837 Matthew "given a spa_t, print block type stats from last scrub", 2200 7837 Matthew zfs_blkstats }, 2201 3059 ahrens { "zfs_params", "", "print zfs tunable parameters", zfs_params }, 2202 10407 Matthew { "refcount", "", "print refcount_t holders", refcount }, 2203 789 ahrens { NULL } 2204 789 ahrens }; 2205 789 ahrens 2206 789 ahrens static const mdb_walker_t walkers[] = { 2207 789 ahrens /* 2208 789 ahrens * In userland, there is no generic provider of list_t walkers, so we 2209 789 ahrens * need to add it. 2210 789 ahrens */ 2211 789 ahrens #ifndef _KERNEL 2212 789 ahrens { LIST_WALK_NAME, LIST_WALK_DESC, 2213 789 ahrens list_walk_init, list_walk_step, list_walk_fini }, 2214 789 ahrens #endif 2215 789 ahrens { "zms_freelist", "walk ZFS metaslab freelist", 2216 2459 ahrens freelist_walk_init, freelist_walk_step, NULL }, 2217 789 ahrens { "txg_list", "given any txg_list_t *, walk all entries in all txgs", 2218 2459 ahrens txg_list_walk_init, txg_list_walk_step, NULL }, 2219 789 ahrens { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", 2220 2459 ahrens txg_list0_walk_init, txg_list_walk_step, NULL }, 2221 789 ahrens { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", 2222 2459 ahrens txg_list1_walk_init, txg_list_walk_step, NULL }, 2223 789 ahrens { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", 2224 2459 ahrens txg_list2_walk_init, txg_list_walk_step, NULL }, 2225 789 ahrens { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", 2226 2459 ahrens txg_list3_walk_init, txg_list_walk_step, NULL }, 2227 4055 eschrock { "zio", "walk all zio structures, optionally for a particular spa_t", 2228 4055 eschrock zio_walk_init, zio_walk_step, NULL }, 2229 4055 eschrock { "zio_root", "walk all root zio_t structures, optionally for a " 2230 4055 eschrock "particular spa_t", 2231 4055 eschrock zio_walk_init, zio_walk_root_step, NULL }, 2232 789 ahrens { "spa", "walk all spa_t entries in the namespace", 2233 789 ahrens spa_walk_init, spa_walk_step, NULL }, 2234 2459 ahrens { "metaslab", "given a spa_t *, walk all metaslab_t structures", 2235 2459 ahrens metaslab_walk_init, metaslab_walk_step, NULL }, 2236 789 ahrens { NULL } 2237 789 ahrens }; 2238 789 ahrens 2239 789 ahrens static const mdb_modinfo_t modinfo = { 2240 789 ahrens MDB_API_VERSION, dcmds, walkers 2241 789 ahrens }; 2242 789 ahrens 2243 789 ahrens const mdb_modinfo_t * 2244 789 ahrens _mdb_init(void) 2245 789 ahrens { 2246 789 ahrens return (&modinfo); 2247 789 ahrens } 2248