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