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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 2011, 2016 by Delphix. All rights reserved. 25 */ 26 27 /* Portions Copyright 2010 Robert Milkowski */ 28 29 #include <mdb/mdb_ctf.h> 30 #include <sys/zfs_context.h> 31 #include <sys/mdb_modapi.h> 32 #include <sys/dbuf.h> 33 #include <sys/dmu_objset.h> 34 #include <sys/dsl_dir.h> 35 #include <sys/dsl_pool.h> 36 #include <sys/metaslab_impl.h> 37 #include <sys/space_map.h> 38 #include <sys/list.h> 39 #include <sys/vdev_impl.h> 40 #include <sys/zap_leaf.h> 41 #include <sys/zap_impl.h> 42 #include <ctype.h> 43 #include <sys/zfs_acl.h> 44 #include <sys/sa_impl.h> 45 #include <sys/multilist.h> 46 47 #ifdef _KERNEL 48 #define ZFS_OBJ_NAME "zfs" 49 extern int64_t mdb_gethrtime(void); 50 #else 51 #define ZFS_OBJ_NAME "libzpool.so.1" 52 #endif 53 54 #define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`" 55 56 #ifndef _KERNEL 57 int aok; 58 #endif 59 60 enum spa_flags { 61 SPA_FLAG_CONFIG = 1 << 0, 62 SPA_FLAG_VDEVS = 1 << 1, 63 SPA_FLAG_ERRORS = 1 << 2, 64 SPA_FLAG_METASLAB_GROUPS = 1 << 3, 65 SPA_FLAG_METASLABS = 1 << 4, 66 SPA_FLAG_HISTOGRAMS = 1 << 5 67 }; 68 69 /* 70 * If any of these flags are set, call spa_vdevs in spa_print 71 */ 72 #define SPA_FLAG_ALL_VDEV \ 73 (SPA_FLAG_VDEVS | SPA_FLAG_ERRORS | SPA_FLAG_METASLAB_GROUPS | \ 74 SPA_FLAG_METASLABS) 75 76 static int 77 getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp, 78 const char *member, int len, void *buf) 79 { 80 mdb_ctf_id_t id; 81 ulong_t off; 82 char name[64]; 83 84 if (idp == NULL) { 85 if (mdb_ctf_lookup_by_name(type, &id) == -1) { 86 mdb_warn("couldn't find type %s", type); 87 return (DCMD_ERR); 88 } 89 idp = &id; 90 } else { 91 type = name; 92 mdb_ctf_type_name(*idp, name, sizeof (name)); 93 } 94 95 if (mdb_ctf_offsetof(*idp, member, &off) == -1) { 96 mdb_warn("couldn't find member %s of type %s\n", member, type); 97 return (DCMD_ERR); 98 } 99 if (off % 8 != 0) { 100 mdb_warn("member %s of type %s is unsupported bitfield", 101 member, type); 102 return (DCMD_ERR); 103 } 104 off /= 8; 105 106 if (mdb_vread(buf, len, addr + off) == -1) { 107 mdb_warn("failed to read %s from %s at %p", 108 member, type, addr + off); 109 return (DCMD_ERR); 110 } 111 /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */ 112 113 return (0); 114 } 115 116 #define GETMEMB(addr, structname, member, dest) \ 117 getmember(addr, ZFS_STRUCT structname, NULL, #member, \ 118 sizeof (dest), &(dest)) 119 120 #define GETMEMBID(addr, ctfid, member, dest) \ 121 getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest)) 122 123 static boolean_t 124 strisprint(const char *cp) 125 { 126 for (; *cp; cp++) { 127 if (!isprint(*cp)) 128 return (B_FALSE); 129 } 130 return (B_TRUE); 131 } 132 133 #define NICENUM_BUFLEN 6 134 135 static int 136 snprintfrac(char *buf, int len, 137 uint64_t numerator, uint64_t denom, int frac_digits) 138 { 139 int mul = 1; 140 int whole, frac, i; 141 142 for (i = frac_digits; i; i--) 143 mul *= 10; 144 whole = numerator / denom; 145 frac = mul * numerator / denom - mul * whole; 146 return (mdb_snprintf(buf, len, "%u.%0*u", whole, frac_digits, frac)); 147 } 148 149 static void 150 mdb_nicenum(uint64_t num, char *buf) 151 { 152 uint64_t n = num; 153 int index = 0; 154 char *u; 155 156 while (n >= 1024) { 157 n = (n + (1024 / 2)) / 1024; /* Round up or down */ 158 index++; 159 } 160 161 u = &" \0K\0M\0G\0T\0P\0E\0"[index*2]; 162 163 if (index == 0) { 164 (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu", 165 (u_longlong_t)n); 166 } else if (n < 10 && (num & (num - 1)) != 0) { 167 (void) snprintfrac(buf, NICENUM_BUFLEN, 168 num, 1ULL << 10 * index, 2); 169 strcat(buf, u); 170 } else if (n < 100 && (num & (num - 1)) != 0) { 171 (void) snprintfrac(buf, NICENUM_BUFLEN, 172 num, 1ULL << 10 * index, 1); 173 strcat(buf, u); 174 } else { 175 (void) mdb_snprintf(buf, NICENUM_BUFLEN, "%llu%s", 176 (u_longlong_t)n, u); 177 } 178 } 179 180 static int verbose; 181 182 static int 183 freelist_walk_init(mdb_walk_state_t *wsp) 184 { 185 if (wsp->walk_addr == NULL) { 186 mdb_warn("must supply starting address\n"); 187 return (WALK_ERR); 188 } 189 190 wsp->walk_data = 0; /* Index into the freelist */ 191 return (WALK_NEXT); 192 } 193 194 static int 195 freelist_walk_step(mdb_walk_state_t *wsp) 196 { 197 uint64_t entry; 198 uintptr_t number = (uintptr_t)wsp->walk_data; 199 char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID", 200 "INVALID", "INVALID", "INVALID", "INVALID" }; 201 int mapshift = SPA_MINBLOCKSHIFT; 202 203 if (mdb_vread(&entry, sizeof (entry), wsp->walk_addr) == -1) { 204 mdb_warn("failed to read freelist entry %p", wsp->walk_addr); 205 return (WALK_DONE); 206 } 207 wsp->walk_addr += sizeof (entry); 208 wsp->walk_data = (void *)(number + 1); 209 210 if (SM_DEBUG_DECODE(entry)) { 211 mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n", 212 number, 213 ddata[SM_DEBUG_ACTION_DECODE(entry)], 214 SM_DEBUG_TXG_DECODE(entry), 215 SM_DEBUG_SYNCPASS_DECODE(entry)); 216 } else { 217 mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c " 218 "size=%06llx", number, 219 SM_OFFSET_DECODE(entry) << mapshift, 220 (SM_OFFSET_DECODE(entry) + SM_RUN_DECODE(entry)) << 221 mapshift, 222 SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F', 223 SM_RUN_DECODE(entry) << mapshift); 224 if (verbose) 225 mdb_printf(" (raw=%012llx)\n", entry); 226 mdb_printf("\n"); 227 } 228 return (WALK_NEXT); 229 } 230 231 static int 232 mdb_dsl_dir_name(uintptr_t addr, char *buf) 233 { 234 static int gotid; 235 static mdb_ctf_id_t dd_id; 236 uintptr_t dd_parent; 237 char dd_myname[ZFS_MAX_DATASET_NAME_LEN]; 238 239 if (!gotid) { 240 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dir", 241 &dd_id) == -1) { 242 mdb_warn("couldn't find struct dsl_dir"); 243 return (DCMD_ERR); 244 } 245 gotid = TRUE; 246 } 247 if (GETMEMBID(addr, &dd_id, dd_parent, dd_parent) || 248 GETMEMBID(addr, &dd_id, dd_myname, dd_myname)) { 249 return (DCMD_ERR); 250 } 251 252 if (dd_parent) { 253 if (mdb_dsl_dir_name(dd_parent, buf)) 254 return (DCMD_ERR); 255 strcat(buf, "/"); 256 } 257 258 if (dd_myname[0]) 259 strcat(buf, dd_myname); 260 else 261 strcat(buf, "???"); 262 263 return (0); 264 } 265 266 static int 267 objset_name(uintptr_t addr, char *buf) 268 { 269 static int gotid; 270 static mdb_ctf_id_t os_id, ds_id; 271 uintptr_t os_dsl_dataset; 272 char ds_snapname[ZFS_MAX_DATASET_NAME_LEN]; 273 uintptr_t ds_dir; 274 275 buf[0] = '\0'; 276 277 if (!gotid) { 278 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "objset", 279 &os_id) == -1) { 280 mdb_warn("couldn't find struct objset"); 281 return (DCMD_ERR); 282 } 283 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dataset", 284 &ds_id) == -1) { 285 mdb_warn("couldn't find struct dsl_dataset"); 286 return (DCMD_ERR); 287 } 288 289 gotid = TRUE; 290 } 291 292 if (GETMEMBID(addr, &os_id, os_dsl_dataset, os_dsl_dataset)) 293 return (DCMD_ERR); 294 295 if (os_dsl_dataset == 0) { 296 strcat(buf, "mos"); 297 return (0); 298 } 299 300 if (GETMEMBID(os_dsl_dataset, &ds_id, ds_snapname, ds_snapname) || 301 GETMEMBID(os_dsl_dataset, &ds_id, ds_dir, ds_dir)) { 302 return (DCMD_ERR); 303 } 304 305 if (ds_dir && mdb_dsl_dir_name(ds_dir, buf)) 306 return (DCMD_ERR); 307 308 if (ds_snapname[0]) { 309 strcat(buf, "@"); 310 strcat(buf, ds_snapname); 311 } 312 return (0); 313 } 314 315 static void 316 enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val, 317 const char *prefix) 318 { 319 const char *cp; 320 size_t len = strlen(prefix); 321 322 if ((cp = mdb_ctf_enum_name(id, val)) != NULL) { 323 if (strncmp(cp, prefix, len) == 0) 324 cp += len; 325 (void) strncpy(out, cp, size); 326 } else { 327 mdb_snprintf(out, size, "? (%d)", val); 328 } 329 } 330 331 /* ARGSUSED */ 332 static int 333 zfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 334 { 335 /* 336 * This table can be approximately generated by running: 337 * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2 338 */ 339 static const char *params[] = { 340 "arc_reduce_dnlc_percent", 341 "arc_lotsfree_percent", 342 "zfs_dirty_data_max", 343 "zfs_dirty_data_sync", 344 "zfs_delay_max_ns", 345 "zfs_delay_min_dirty_percent", 346 "zfs_delay_scale", 347 "zfs_vdev_max_active", 348 "zfs_vdev_sync_read_min_active", 349 "zfs_vdev_sync_read_max_active", 350 "zfs_vdev_sync_write_min_active", 351 "zfs_vdev_sync_write_max_active", 352 "zfs_vdev_async_read_min_active", 353 "zfs_vdev_async_read_max_active", 354 "zfs_vdev_async_write_min_active", 355 "zfs_vdev_async_write_max_active", 356 "zfs_vdev_scrub_min_active", 357 "zfs_vdev_scrub_max_active", 358 "zfs_vdev_async_write_active_min_dirty_percent", 359 "zfs_vdev_async_write_active_max_dirty_percent", 360 "spa_asize_inflation", 361 "zfs_arc_max", 362 "zfs_arc_min", 363 "arc_shrink_shift", 364 "zfs_mdcomp_disable", 365 "zfs_prefetch_disable", 366 "zfetch_max_streams", 367 "zfetch_min_sec_reap", 368 "zfetch_block_cap", 369 "zfetch_array_rd_sz", 370 "zfs_default_bs", 371 "zfs_default_ibs", 372 "metaslab_aliquot", 373 "reference_tracking_enable", 374 "reference_history", 375 "spa_max_replication_override", 376 "spa_mode_global", 377 "zfs_flags", 378 "zfs_txg_timeout", 379 "zfs_vdev_cache_max", 380 "zfs_vdev_cache_size", 381 "zfs_vdev_cache_bshift", 382 "vdev_mirror_shift", 383 "zfs_scrub_limit", 384 "zfs_no_scrub_io", 385 "zfs_no_scrub_prefetch", 386 "zfs_vdev_aggregation_limit", 387 "fzap_default_block_shift", 388 "zfs_immediate_write_sz", 389 "zfs_read_chunk_size", 390 "zfs_nocacheflush", 391 "zil_replay_disable", 392 "metaslab_gang_bang", 393 "metaslab_df_alloc_threshold", 394 "metaslab_df_free_pct", 395 "zio_injection_enabled", 396 "zvol_immediate_write_sz", 397 }; 398 399 for (int i = 0; i < sizeof (params) / sizeof (params[0]); i++) { 400 int sz; 401 uint64_t val64; 402 uint32_t *val32p = (uint32_t *)&val64; 403 404 sz = mdb_readvar(&val64, params[i]); 405 if (sz == 4) { 406 mdb_printf("%s = 0x%x\n", params[i], *val32p); 407 } else if (sz == 8) { 408 mdb_printf("%s = 0x%llx\n", params[i], val64); 409 } else { 410 mdb_warn("variable %s not found", params[i]); 411 } 412 } 413 414 return (DCMD_OK); 415 } 416 417 /* ARGSUSED */ 418 static int 419 blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 420 { 421 mdb_ctf_id_t type_enum, checksum_enum, compress_enum; 422 char type[80], checksum[80], compress[80]; 423 blkptr_t blk, *bp = &blk; 424 char buf[BP_SPRINTF_LEN]; 425 426 if (mdb_vread(&blk, sizeof (blkptr_t), addr) == -1) { 427 mdb_warn("failed to read blkptr_t"); 428 return (DCMD_ERR); 429 } 430 431 if (mdb_ctf_lookup_by_name("enum dmu_object_type", &type_enum) == -1 || 432 mdb_ctf_lookup_by_name("enum zio_checksum", &checksum_enum) == -1 || 433 mdb_ctf_lookup_by_name("enum zio_compress", &compress_enum) == -1) { 434 mdb_warn("Could not find blkptr enumerated types"); 435 return (DCMD_ERR); 436 } 437 438 enum_lookup(type, sizeof (type), type_enum, 439 BP_GET_TYPE(bp), "DMU_OT_"); 440 enum_lookup(checksum, sizeof (checksum), checksum_enum, 441 BP_GET_CHECKSUM(bp), "ZIO_CHECKSUM_"); 442 enum_lookup(compress, sizeof (compress), compress_enum, 443 BP_GET_COMPRESS(bp), "ZIO_COMPRESS_"); 444 445 SNPRINTF_BLKPTR(mdb_snprintf, '\n', buf, sizeof (buf), bp, type, 446 checksum, compress); 447 448 mdb_printf("%s\n", buf); 449 450 return (DCMD_OK); 451 } 452 453 typedef struct mdb_dmu_buf_impl { 454 struct { 455 uint64_t db_object; 456 uintptr_t db_data; 457 } db; 458 uintptr_t db_objset; 459 uint64_t db_level; 460 uint64_t db_blkid; 461 struct { 462 uint64_t rc_count; 463 } db_holds; 464 } mdb_dmu_buf_impl_t; 465 466 /* ARGSUSED */ 467 static int 468 dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 469 { 470 mdb_dmu_buf_impl_t db; 471 char objectname[32]; 472 char blkidname[32]; 473 char path[ZFS_MAX_DATASET_NAME_LEN]; 474 int ptr_width = (int)(sizeof (void *)) * 2; 475 476 if (DCMD_HDRSPEC(flags)) 477 mdb_printf("%*s %8s %3s %9s %5s %s\n", 478 ptr_width, "addr", "object", "lvl", "blkid", "holds", "os"); 479 480 if (mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t", 481 addr, 0) == -1) 482 return (DCMD_ERR); 483 484 if (db.db.db_object == DMU_META_DNODE_OBJECT) 485 (void) strcpy(objectname, "mdn"); 486 else 487 (void) mdb_snprintf(objectname, sizeof (objectname), "%llx", 488 (u_longlong_t)db.db.db_object); 489 490 if (db.db_blkid == DMU_BONUS_BLKID) 491 (void) strcpy(blkidname, "bonus"); 492 else 493 (void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx", 494 (u_longlong_t)db.db_blkid); 495 496 if (objset_name(db.db_objset, path)) { 497 return (DCMD_ERR); 498 } 499 500 mdb_printf("%*p %8s %3u %9s %5llu %s\n", ptr_width, addr, 501 objectname, (int)db.db_level, blkidname, 502 db.db_holds.rc_count, path); 503 504 return (DCMD_OK); 505 } 506 507 /* ARGSUSED */ 508 static int 509 dbuf_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 510 { 511 #define HISTOSZ 32 512 uintptr_t dbp; 513 dmu_buf_impl_t db; 514 dbuf_hash_table_t ht; 515 uint64_t bucket, ndbufs; 516 uint64_t histo[HISTOSZ]; 517 uint64_t histo2[HISTOSZ]; 518 int i, maxidx; 519 520 if (mdb_readvar(&ht, "dbuf_hash_table") == -1) { 521 mdb_warn("failed to read 'dbuf_hash_table'"); 522 return (DCMD_ERR); 523 } 524 525 for (i = 0; i < HISTOSZ; i++) { 526 histo[i] = 0; 527 histo2[i] = 0; 528 } 529 530 ndbufs = 0; 531 for (bucket = 0; bucket < ht.hash_table_mask+1; bucket++) { 532 int len; 533 534 if (mdb_vread(&dbp, sizeof (void *), 535 (uintptr_t)(ht.hash_table+bucket)) == -1) { 536 mdb_warn("failed to read hash bucket %u at %p", 537 bucket, ht.hash_table+bucket); 538 return (DCMD_ERR); 539 } 540 541 len = 0; 542 while (dbp != 0) { 543 if (mdb_vread(&db, sizeof (dmu_buf_impl_t), 544 dbp) == -1) { 545 mdb_warn("failed to read dbuf at %p", dbp); 546 return (DCMD_ERR); 547 } 548 dbp = (uintptr_t)db.db_hash_next; 549 for (i = MIN(len, HISTOSZ - 1); i >= 0; i--) 550 histo2[i]++; 551 len++; 552 ndbufs++; 553 } 554 555 if (len >= HISTOSZ) 556 len = HISTOSZ-1; 557 histo[len]++; 558 } 559 560 mdb_printf("hash table has %llu buckets, %llu dbufs " 561 "(avg %llu buckets/dbuf)\n", 562 ht.hash_table_mask+1, ndbufs, 563 (ht.hash_table_mask+1)/ndbufs); 564 565 mdb_printf("\n"); 566 maxidx = 0; 567 for (i = 0; i < HISTOSZ; i++) 568 if (histo[i] > 0) 569 maxidx = i; 570 mdb_printf("hash chain length number of buckets\n"); 571 for (i = 0; i <= maxidx; i++) 572 mdb_printf("%u %llu\n", i, histo[i]); 573 574 mdb_printf("\n"); 575 maxidx = 0; 576 for (i = 0; i < HISTOSZ; i++) 577 if (histo2[i] > 0) 578 maxidx = i; 579 mdb_printf("hash chain depth number of dbufs\n"); 580 for (i = 0; i <= maxidx; i++) 581 mdb_printf("%u or more %llu %llu%%\n", 582 i, histo2[i], histo2[i]*100/ndbufs); 583 584 585 return (DCMD_OK); 586 } 587 588 #define CHAIN_END 0xffff 589 /* 590 * ::zap_leaf [-v] 591 * 592 * Print a zap_leaf_phys_t, assumed to be 16k 593 */ 594 /* ARGSUSED */ 595 static int 596 zap_leaf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 597 { 598 char buf[16*1024]; 599 int verbose = B_FALSE; 600 int four = B_FALSE; 601 dmu_buf_t l_dbuf; 602 zap_leaf_t l; 603 zap_leaf_phys_t *zlp = (void *)buf; 604 int i; 605 606 if (mdb_getopts(argc, argv, 607 'v', MDB_OPT_SETBITS, TRUE, &verbose, 608 '4', MDB_OPT_SETBITS, TRUE, &four, 609 NULL) != argc) 610 return (DCMD_USAGE); 611 612 l_dbuf.db_data = zlp; 613 l.l_dbuf = &l_dbuf; 614 l.l_bs = 14; /* assume 16k blocks */ 615 if (four) 616 l.l_bs = 12; 617 618 if (!(flags & DCMD_ADDRSPEC)) { 619 return (DCMD_USAGE); 620 } 621 622 if (mdb_vread(buf, sizeof (buf), addr) == -1) { 623 mdb_warn("failed to read zap_leaf_phys_t at %p", addr); 624 return (DCMD_ERR); 625 } 626 627 if (zlp->l_hdr.lh_block_type != ZBT_LEAF || 628 zlp->l_hdr.lh_magic != ZAP_LEAF_MAGIC) { 629 mdb_warn("This does not appear to be a zap_leaf_phys_t"); 630 return (DCMD_ERR); 631 } 632 633 mdb_printf("zap_leaf_phys_t at %p:\n", addr); 634 mdb_printf(" lh_prefix_len = %u\n", zlp->l_hdr.lh_prefix_len); 635 mdb_printf(" lh_prefix = %llx\n", zlp->l_hdr.lh_prefix); 636 mdb_printf(" lh_nentries = %u\n", zlp->l_hdr.lh_nentries); 637 mdb_printf(" lh_nfree = %u\n", zlp->l_hdr.lh_nfree, 638 zlp->l_hdr.lh_nfree * 100 / (ZAP_LEAF_NUMCHUNKS(&l))); 639 mdb_printf(" lh_freelist = %u\n", zlp->l_hdr.lh_freelist); 640 mdb_printf(" lh_flags = %x (%s)\n", zlp->l_hdr.lh_flags, 641 zlp->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED ? 642 "ENTRIES_CDSORTED" : ""); 643 644 if (verbose) { 645 mdb_printf(" hash table:\n"); 646 for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++) { 647 if (zlp->l_hash[i] != CHAIN_END) 648 mdb_printf(" %u: %u\n", i, zlp->l_hash[i]); 649 } 650 } 651 652 mdb_printf(" chunks:\n"); 653 for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) { 654 /* LINTED: alignment */ 655 zap_leaf_chunk_t *zlc = &ZAP_LEAF_CHUNK(&l, i); 656 switch (zlc->l_entry.le_type) { 657 case ZAP_CHUNK_FREE: 658 if (verbose) { 659 mdb_printf(" %u: free; lf_next = %u\n", 660 i, zlc->l_free.lf_next); 661 } 662 break; 663 case ZAP_CHUNK_ENTRY: 664 mdb_printf(" %u: entry\n", i); 665 if (verbose) { 666 mdb_printf(" le_next = %u\n", 667 zlc->l_entry.le_next); 668 } 669 mdb_printf(" le_name_chunk = %u\n", 670 zlc->l_entry.le_name_chunk); 671 mdb_printf(" le_name_numints = %u\n", 672 zlc->l_entry.le_name_numints); 673 mdb_printf(" le_value_chunk = %u\n", 674 zlc->l_entry.le_value_chunk); 675 mdb_printf(" le_value_intlen = %u\n", 676 zlc->l_entry.le_value_intlen); 677 mdb_printf(" le_value_numints = %u\n", 678 zlc->l_entry.le_value_numints); 679 mdb_printf(" le_cd = %u\n", 680 zlc->l_entry.le_cd); 681 mdb_printf(" le_hash = %llx\n", 682 zlc->l_entry.le_hash); 683 break; 684 case ZAP_CHUNK_ARRAY: 685 mdb_printf(" %u: array", i); 686 if (strisprint((char *)zlc->l_array.la_array)) 687 mdb_printf(" \"%s\"", zlc->l_array.la_array); 688 mdb_printf("\n"); 689 if (verbose) { 690 int j; 691 mdb_printf(" "); 692 for (j = 0; j < ZAP_LEAF_ARRAY_BYTES; j++) { 693 mdb_printf("%02x ", 694 zlc->l_array.la_array[j]); 695 } 696 mdb_printf("\n"); 697 } 698 if (zlc->l_array.la_next != CHAIN_END) { 699 mdb_printf(" lf_next = %u\n", 700 zlc->l_array.la_next); 701 } 702 break; 703 default: 704 mdb_printf(" %u: undefined type %u\n", 705 zlc->l_entry.le_type); 706 } 707 } 708 709 return (DCMD_OK); 710 } 711 712 typedef struct dbufs_data { 713 mdb_ctf_id_t id; 714 uint64_t objset; 715 uint64_t object; 716 uint64_t level; 717 uint64_t blkid; 718 char *osname; 719 } dbufs_data_t; 720 721 #define DBUFS_UNSET (0xbaddcafedeadbeefULL) 722 723 /* ARGSUSED */ 724 static int 725 dbufs_cb(uintptr_t addr, const void *unknown, void *arg) 726 { 727 dbufs_data_t *data = arg; 728 uintptr_t objset; 729 dmu_buf_t db; 730 uint8_t level; 731 uint64_t blkid; 732 char osname[ZFS_MAX_DATASET_NAME_LEN]; 733 734 if (GETMEMBID(addr, &data->id, db_objset, objset) || 735 GETMEMBID(addr, &data->id, db, db) || 736 GETMEMBID(addr, &data->id, db_level, level) || 737 GETMEMBID(addr, &data->id, db_blkid, blkid)) { 738 return (WALK_ERR); 739 } 740 741 if ((data->objset == DBUFS_UNSET || data->objset == objset) && 742 (data->osname == NULL || (objset_name(objset, osname) == 0 && 743 strcmp(data->osname, osname) == 0)) && 744 (data->object == DBUFS_UNSET || data->object == db.db_object) && 745 (data->level == DBUFS_UNSET || data->level == level) && 746 (data->blkid == DBUFS_UNSET || data->blkid == blkid)) { 747 mdb_printf("%#lr\n", addr); 748 } 749 return (WALK_NEXT); 750 } 751 752 /* ARGSUSED */ 753 static int 754 dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 755 { 756 dbufs_data_t data; 757 char *object = NULL; 758 char *blkid = NULL; 759 760 data.objset = data.object = data.level = data.blkid = DBUFS_UNSET; 761 data.osname = NULL; 762 763 if (mdb_getopts(argc, argv, 764 'O', MDB_OPT_UINT64, &data.objset, 765 'n', MDB_OPT_STR, &data.osname, 766 'o', MDB_OPT_STR, &object, 767 'l', MDB_OPT_UINT64, &data.level, 768 'b', MDB_OPT_STR, &blkid) != argc) { 769 return (DCMD_USAGE); 770 } 771 772 if (object) { 773 if (strcmp(object, "mdn") == 0) { 774 data.object = DMU_META_DNODE_OBJECT; 775 } else { 776 data.object = mdb_strtoull(object); 777 } 778 } 779 780 if (blkid) { 781 if (strcmp(blkid, "bonus") == 0) { 782 data.blkid = DMU_BONUS_BLKID; 783 } else { 784 data.blkid = mdb_strtoull(blkid); 785 } 786 } 787 788 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dmu_buf_impl", &data.id) == -1) { 789 mdb_warn("couldn't find struct dmu_buf_impl_t"); 790 return (DCMD_ERR); 791 } 792 793 if (mdb_walk("dmu_buf_impl_t", dbufs_cb, &data) != 0) { 794 mdb_warn("can't walk dbufs"); 795 return (DCMD_ERR); 796 } 797 798 return (DCMD_OK); 799 } 800 801 typedef struct abuf_find_data { 802 dva_t dva; 803 mdb_ctf_id_t id; 804 } abuf_find_data_t; 805 806 /* ARGSUSED */ 807 static int 808 abuf_find_cb(uintptr_t addr, const void *unknown, void *arg) 809 { 810 abuf_find_data_t *data = arg; 811 dva_t dva; 812 813 if (GETMEMBID(addr, &data->id, b_dva, dva)) { 814 return (WALK_ERR); 815 } 816 817 if (dva.dva_word[0] == data->dva.dva_word[0] && 818 dva.dva_word[1] == data->dva.dva_word[1]) { 819 mdb_printf("%#lr\n", addr); 820 } 821 return (WALK_NEXT); 822 } 823 824 /* ARGSUSED */ 825 static int 826 abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 827 { 828 abuf_find_data_t data; 829 GElf_Sym sym; 830 int i; 831 const char *syms[] = { 832 "ARC_mru", 833 "ARC_mru_ghost", 834 "ARC_mfu", 835 "ARC_mfu_ghost", 836 }; 837 838 if (argc != 2) 839 return (DCMD_USAGE); 840 841 for (i = 0; i < 2; i ++) { 842 switch (argv[i].a_type) { 843 case MDB_TYPE_STRING: 844 data.dva.dva_word[i] = mdb_strtoull(argv[i].a_un.a_str); 845 break; 846 case MDB_TYPE_IMMEDIATE: 847 data.dva.dva_word[i] = argv[i].a_un.a_val; 848 break; 849 default: 850 return (DCMD_USAGE); 851 } 852 } 853 854 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "arc_buf_hdr", &data.id) == -1) { 855 mdb_warn("couldn't find struct arc_buf_hdr"); 856 return (DCMD_ERR); 857 } 858 859 for (i = 0; i < sizeof (syms) / sizeof (syms[0]); i++) { 860 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, syms[i], &sym)) { 861 mdb_warn("can't find symbol %s", syms[i]); 862 return (DCMD_ERR); 863 } 864 865 if (mdb_pwalk("list", abuf_find_cb, &data, sym.st_value) != 0) { 866 mdb_warn("can't walk %s", syms[i]); 867 return (DCMD_ERR); 868 } 869 } 870 871 return (DCMD_OK); 872 } 873 874 875 typedef struct dbgmsg_arg { 876 boolean_t da_verbose; 877 boolean_t da_address; 878 } dbgmsg_arg_t; 879 880 /* ARGSUSED */ 881 static int 882 dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg) 883 { 884 static mdb_ctf_id_t id; 885 static boolean_t gotid; 886 static ulong_t off; 887 888 dbgmsg_arg_t *da = arg; 889 time_t timestamp; 890 char buf[1024]; 891 892 if (!gotid) { 893 if (mdb_ctf_lookup_by_name(ZFS_STRUCT "zfs_dbgmsg", &id) == 894 -1) { 895 mdb_warn("couldn't find struct zfs_dbgmsg"); 896 return (WALK_ERR); 897 } 898 gotid = TRUE; 899 if (mdb_ctf_offsetof(id, "zdm_msg", &off) == -1) { 900 mdb_warn("couldn't find zdm_msg"); 901 return (WALK_ERR); 902 } 903 off /= 8; 904 } 905 906 907 if (GETMEMBID(addr, &id, zdm_timestamp, timestamp)) { 908 return (WALK_ERR); 909 } 910 911 if (mdb_readstr(buf, sizeof (buf), addr + off) == -1) { 912 mdb_warn("failed to read zdm_msg at %p\n", addr + off); 913 return (DCMD_ERR); 914 } 915 916 if (da->da_address) 917 mdb_printf("%p ", addr); 918 if (da->da_verbose) 919 mdb_printf("%Y ", timestamp); 920 921 mdb_printf("%s\n", buf); 922 923 if (da->da_verbose) 924 (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 925 926 return (WALK_NEXT); 927 } 928 929 /* ARGSUSED */ 930 static int 931 dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 932 { 933 GElf_Sym sym; 934 dbgmsg_arg_t da = { 0 }; 935 936 if (mdb_getopts(argc, argv, 937 'v', MDB_OPT_SETBITS, B_TRUE, &da.da_verbose, 938 'a', MDB_OPT_SETBITS, B_TRUE, &da.da_address, 939 NULL) != argc) 940 return (DCMD_USAGE); 941 942 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "zfs_dbgmsgs", &sym)) { 943 mdb_warn("can't find zfs_dbgmsgs"); 944 return (DCMD_ERR); 945 } 946 947 if (mdb_pwalk("list", dbgmsg_cb, &da, sym.st_value) != 0) { 948 mdb_warn("can't walk zfs_dbgmsgs"); 949 return (DCMD_ERR); 950 } 951 952 return (DCMD_OK); 953 } 954 955 /*ARGSUSED*/ 956 static int 957 arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 958 { 959 kstat_named_t *stats; 960 GElf_Sym sym; 961 int nstats, i; 962 uint_t opt_a = FALSE; 963 uint_t opt_b = FALSE; 964 uint_t shift = 0; 965 const char *suffix; 966 967 static const char *bytestats[] = { 968 "p", "c", "c_min", "c_max", "size", "duplicate_buffers_size", 969 "arc_meta_used", "arc_meta_limit", "arc_meta_max", 970 "arc_meta_min", "hdr_size", "data_size", "metadata_size", 971 "other_size", "anon_size", "anon_evictable_data", 972 "anon_evictable_metadata", "mru_size", "mru_evictable_data", 973 "mru_evictable_metadata", "mru_ghost_size", 974 "mru_ghost_evictable_data", "mru_ghost_evictable_metadata", 975 "mfu_size", "mfu_evictable_data", "mfu_evictable_metadata", 976 "mfu_ghost_size", "mfu_ghost_evictable_data", 977 "mfu_ghost_evictable_metadata", "evict_l2_cached", 978 "evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes", 979 "l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size", 980 "compressed_size", "uncompressed_size", "overhead_size", 981 NULL 982 }; 983 984 static const char *extras[] = { 985 "arc_no_grow", "arc_tempreserve", 986 NULL 987 }; 988 989 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "arc_stats", &sym) == -1) { 990 mdb_warn("failed to find 'arc_stats'"); 991 return (DCMD_ERR); 992 } 993 994 stats = mdb_zalloc(sym.st_size, UM_SLEEP | UM_GC); 995 996 if (mdb_vread(stats, sym.st_size, sym.st_value) == -1) { 997 mdb_warn("couldn't read 'arc_stats' at %p", sym.st_value); 998 return (DCMD_ERR); 999 } 1000 1001 nstats = sym.st_size / sizeof (kstat_named_t); 1002 1003 /* NB: -a / opt_a are ignored for backwards compatability */ 1004 if (mdb_getopts(argc, argv, 1005 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 1006 'b', MDB_OPT_SETBITS, TRUE, &opt_b, 1007 'k', MDB_OPT_SETBITS, 10, &shift, 1008 'm', MDB_OPT_SETBITS, 20, &shift, 1009 'g', MDB_OPT_SETBITS, 30, &shift, 1010 NULL) != argc) 1011 return (DCMD_USAGE); 1012 1013 if (!opt_b && !shift) 1014 shift = 20; 1015 1016 switch (shift) { 1017 case 0: 1018 suffix = "B"; 1019 break; 1020 case 10: 1021 suffix = "KB"; 1022 break; 1023 case 20: 1024 suffix = "MB"; 1025 break; 1026 case 30: 1027 suffix = "GB"; 1028 break; 1029 default: 1030 suffix = "XX"; 1031 } 1032 1033 for (i = 0; i < nstats; i++) { 1034 int j; 1035 boolean_t bytes = B_FALSE; 1036 1037 for (j = 0; bytestats[j]; j++) { 1038 if (strcmp(stats[i].name, bytestats[j]) == 0) { 1039 bytes = B_TRUE; 1040 break; 1041 } 1042 } 1043 1044 if (bytes) { 1045 mdb_printf("%-25s = %9llu %s\n", stats[i].name, 1046 stats[i].value.ui64 >> shift, suffix); 1047 } else { 1048 mdb_printf("%-25s = %9llu\n", stats[i].name, 1049 stats[i].value.ui64); 1050 } 1051 } 1052 1053 for (i = 0; extras[i]; i++) { 1054 uint64_t buf; 1055 1056 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, extras[i], &sym) == -1) { 1057 mdb_warn("failed to find '%s'", extras[i]); 1058 return (DCMD_ERR); 1059 } 1060 1061 if (sym.st_size != sizeof (uint64_t) && 1062 sym.st_size != sizeof (uint32_t)) { 1063 mdb_warn("expected scalar for variable '%s'\n", 1064 extras[i]); 1065 return (DCMD_ERR); 1066 } 1067 1068 if (mdb_vread(&buf, sym.st_size, sym.st_value) == -1) { 1069 mdb_warn("couldn't read '%s'", extras[i]); 1070 return (DCMD_ERR); 1071 } 1072 1073 mdb_printf("%-25s = ", extras[i]); 1074 1075 /* NB: all the 64-bit extras happen to be byte counts */ 1076 if (sym.st_size == sizeof (uint64_t)) 1077 mdb_printf("%9llu %s\n", buf >> shift, suffix); 1078 1079 if (sym.st_size == sizeof (uint32_t)) 1080 mdb_printf("%9d\n", *((uint32_t *)&buf)); 1081 } 1082 return (DCMD_OK); 1083 } 1084 1085 typedef struct mdb_spa_print { 1086 pool_state_t spa_state; 1087 char spa_name[ZFS_MAX_DATASET_NAME_LEN]; 1088 uintptr_t spa_normal_class; 1089 } mdb_spa_print_t; 1090 1091 1092 const char histo_stars[] = "****************************************"; 1093 const int histo_width = sizeof (histo_stars) - 1; 1094 1095 static void 1096 dump_histogram(const uint64_t *histo, int size, int offset) 1097 { 1098 int i; 1099 int minidx = size - 1; 1100 int maxidx = 0; 1101 uint64_t max = 0; 1102 1103 for (i = 0; i < size; i++) { 1104 if (histo[i] > max) 1105 max = histo[i]; 1106 if (histo[i] > 0 && i > maxidx) 1107 maxidx = i; 1108 if (histo[i] > 0 && i < minidx) 1109 minidx = i; 1110 } 1111 1112 if (max < histo_width) 1113 max = histo_width; 1114 1115 for (i = minidx; i <= maxidx; i++) { 1116 mdb_printf("%3u: %6llu %s\n", 1117 i + offset, (u_longlong_t)histo[i], 1118 &histo_stars[(max - histo[i]) * histo_width / max]); 1119 } 1120 } 1121 1122 typedef struct mdb_metaslab_class { 1123 uint64_t mc_histogram[RANGE_TREE_HISTOGRAM_SIZE]; 1124 } mdb_metaslab_class_t; 1125 1126 /* 1127 * spa_class_histogram(uintptr_t class_addr) 1128 * 1129 * Prints free space histogram for a device class 1130 * 1131 * Returns DCMD_OK, or DCMD_ERR. 1132 */ 1133 static int 1134 spa_class_histogram(uintptr_t class_addr) 1135 { 1136 mdb_metaslab_class_t mc; 1137 if (mdb_ctf_vread(&mc, "metaslab_class_t", 1138 "mdb_metaslab_class_t", class_addr, 0) == -1) 1139 return (DCMD_ERR); 1140 1141 mdb_inc_indent(4); 1142 dump_histogram(mc.mc_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 1143 mdb_dec_indent(4); 1144 return (DCMD_OK); 1145 } 1146 1147 /* 1148 * ::spa 1149 * 1150 * -c Print configuration information as well 1151 * -v Print vdev state 1152 * -e Print vdev error stats 1153 * -m Print vdev metaslab info 1154 * -M print vdev metaslab group info 1155 * -h Print histogram info (must be combined with -m or -M) 1156 * 1157 * Print a summarized spa_t. When given no arguments, prints out a table of all 1158 * active pools on the system. 1159 */ 1160 /* ARGSUSED */ 1161 static int 1162 spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1163 { 1164 const char *statetab[] = { "ACTIVE", "EXPORTED", "DESTROYED", 1165 "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" }; 1166 const char *state; 1167 int spa_flags = 0; 1168 1169 if (mdb_getopts(argc, argv, 1170 'c', MDB_OPT_SETBITS, SPA_FLAG_CONFIG, &spa_flags, 1171 'v', MDB_OPT_SETBITS, SPA_FLAG_VDEVS, &spa_flags, 1172 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 1173 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 1174 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 1175 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 1176 NULL) != argc) 1177 return (DCMD_USAGE); 1178 1179 if (!(flags & DCMD_ADDRSPEC)) { 1180 if (mdb_walk_dcmd("spa", "spa", argc, argv) == -1) { 1181 mdb_warn("can't walk spa"); 1182 return (DCMD_ERR); 1183 } 1184 1185 return (DCMD_OK); 1186 } 1187 1188 if (flags & DCMD_PIPE_OUT) { 1189 mdb_printf("%#lr\n", addr); 1190 return (DCMD_OK); 1191 } 1192 1193 if (DCMD_HDRSPEC(flags)) 1194 mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE", 1195 sizeof (uintptr_t) == 4 ? 60 : 52, "NAME"); 1196 1197 mdb_spa_print_t spa; 1198 if (mdb_ctf_vread(&spa, "spa_t", "mdb_spa_print_t", addr, 0) == -1) 1199 return (DCMD_ERR); 1200 1201 if (spa.spa_state < 0 || spa.spa_state > POOL_STATE_UNAVAIL) 1202 state = "UNKNOWN"; 1203 else 1204 state = statetab[spa.spa_state]; 1205 1206 mdb_printf("%0?p %9s %s\n", addr, state, spa.spa_name); 1207 if (spa_flags & SPA_FLAG_HISTOGRAMS) 1208 spa_class_histogram(spa.spa_normal_class); 1209 1210 if (spa_flags & SPA_FLAG_CONFIG) { 1211 mdb_printf("\n"); 1212 mdb_inc_indent(4); 1213 if (mdb_call_dcmd("spa_config", addr, flags, 0, 1214 NULL) != DCMD_OK) 1215 return (DCMD_ERR); 1216 mdb_dec_indent(4); 1217 } 1218 1219 if (spa_flags & SPA_FLAG_ALL_VDEV) { 1220 mdb_arg_t v; 1221 char opts[100] = "-"; 1222 int args = 1223 (spa_flags | SPA_FLAG_VDEVS) == SPA_FLAG_VDEVS ? 0 : 1; 1224 1225 if (spa_flags & SPA_FLAG_ERRORS) 1226 strcat(opts, "e"); 1227 if (spa_flags & SPA_FLAG_METASLABS) 1228 strcat(opts, "m"); 1229 if (spa_flags & SPA_FLAG_METASLAB_GROUPS) 1230 strcat(opts, "M"); 1231 if (spa_flags & SPA_FLAG_HISTOGRAMS) 1232 strcat(opts, "h"); 1233 1234 v.a_type = MDB_TYPE_STRING; 1235 v.a_un.a_str = opts; 1236 1237 mdb_printf("\n"); 1238 mdb_inc_indent(4); 1239 if (mdb_call_dcmd("spa_vdevs", addr, flags, args, 1240 &v) != DCMD_OK) 1241 return (DCMD_ERR); 1242 mdb_dec_indent(4); 1243 } 1244 1245 return (DCMD_OK); 1246 } 1247 1248 typedef struct mdb_spa_config_spa { 1249 uintptr_t spa_config; 1250 } mdb_spa_config_spa_t; 1251 1252 /* 1253 * ::spa_config 1254 * 1255 * Given a spa_t, print the configuration information stored in spa_config. 1256 * Since it's just an nvlist, format it as an indented list of name=value pairs. 1257 * We simply read the value of spa_config and pass off to ::nvlist. 1258 */ 1259 /* ARGSUSED */ 1260 static int 1261 spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1262 { 1263 mdb_spa_config_spa_t spa; 1264 1265 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 1266 return (DCMD_USAGE); 1267 1268 if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_config_spa_t", 1269 addr, 0) == -1) 1270 return (DCMD_ERR); 1271 1272 if (spa.spa_config == 0) { 1273 mdb_printf("(none)\n"); 1274 return (DCMD_OK); 1275 } 1276 1277 return (mdb_call_dcmd("nvlist", spa.spa_config, flags, 1278 0, NULL)); 1279 } 1280 1281 1282 1283 typedef struct mdb_range_tree { 1284 uint64_t rt_space; 1285 } mdb_range_tree_t; 1286 1287 typedef struct mdb_metaslab_group { 1288 uint64_t mg_fragmentation; 1289 uint64_t mg_histogram[RANGE_TREE_HISTOGRAM_SIZE]; 1290 } mdb_metaslab_group_t; 1291 1292 typedef struct mdb_metaslab { 1293 uint64_t ms_id; 1294 uint64_t ms_start; 1295 uint64_t ms_size; 1296 uint64_t ms_fragmentation; 1297 uintptr_t ms_alloctree[TXG_SIZE]; 1298 uintptr_t ms_freetree[TXG_SIZE]; 1299 uintptr_t ms_tree; 1300 uintptr_t ms_sm; 1301 } mdb_metaslab_t; 1302 1303 typedef struct mdb_space_map_phys_t { 1304 uint64_t smp_alloc; 1305 uint64_t smp_histogram[SPACE_MAP_HISTOGRAM_SIZE]; 1306 } mdb_space_map_phys_t; 1307 1308 typedef struct mdb_space_map { 1309 uint64_t sm_size; 1310 uint8_t sm_shift; 1311 uint64_t sm_alloc; 1312 uintptr_t sm_phys; 1313 } mdb_space_map_t; 1314 1315 typedef struct mdb_vdev { 1316 uintptr_t vdev_ms; 1317 uint64_t vdev_ms_count; 1318 vdev_stat_t vdev_stat; 1319 } mdb_vdev_t; 1320 1321 static int 1322 metaslab_stats(uintptr_t addr, int spa_flags) 1323 { 1324 mdb_vdev_t vdev; 1325 uintptr_t *vdev_ms; 1326 1327 if (mdb_ctf_vread(&vdev, "vdev_t", "mdb_vdev_t", 1328 (uintptr_t)addr, 0) == -1) { 1329 mdb_warn("failed to read vdev at %p\n", addr); 1330 return (DCMD_ERR); 1331 } 1332 1333 mdb_inc_indent(4); 1334 mdb_printf("%<u>%-?s %6s %20s %10s %9s%</u>\n", "ADDR", "ID", 1335 "OFFSET", "FREE", "FRAGMENTATION"); 1336 1337 vdev_ms = mdb_alloc(vdev.vdev_ms_count * sizeof (void *), 1338 UM_SLEEP | UM_GC); 1339 if (mdb_vread(vdev_ms, vdev.vdev_ms_count * sizeof (void *), 1340 (uintptr_t)vdev.vdev_ms) == -1) { 1341 mdb_warn("failed to read vdev_ms at %p\n", vdev.vdev_ms); 1342 return (DCMD_ERR); 1343 } 1344 1345 for (int m = 0; m < vdev.vdev_ms_count; m++) { 1346 mdb_metaslab_t ms; 1347 mdb_space_map_t sm = { 0 }; 1348 char free[NICENUM_BUFLEN]; 1349 1350 if (mdb_ctf_vread(&ms, "metaslab_t", "mdb_metaslab_t", 1351 (uintptr_t)vdev_ms[m], 0) == -1) 1352 return (DCMD_ERR); 1353 1354 if (ms.ms_sm != NULL && 1355 mdb_ctf_vread(&sm, "space_map_t", "mdb_space_map_t", 1356 ms.ms_sm, 0) == -1) 1357 return (DCMD_ERR); 1358 1359 mdb_nicenum(ms.ms_size - sm.sm_alloc, free); 1360 1361 mdb_printf("%0?p %6llu %20llx %10s ", vdev_ms[m], ms.ms_id, 1362 ms.ms_start, free); 1363 if (ms.ms_fragmentation == ZFS_FRAG_INVALID) 1364 mdb_printf("%9s\n", "-"); 1365 else 1366 mdb_printf("%9llu%%\n", ms.ms_fragmentation); 1367 1368 if ((spa_flags & SPA_FLAG_HISTOGRAMS) && ms.ms_sm != NULL) { 1369 mdb_space_map_phys_t smp; 1370 1371 if (sm.sm_phys == NULL) 1372 continue; 1373 1374 (void) mdb_ctf_vread(&smp, "space_map_phys_t", 1375 "mdb_space_map_phys_t", sm.sm_phys, 0); 1376 1377 dump_histogram(smp.smp_histogram, 1378 SPACE_MAP_HISTOGRAM_SIZE, sm.sm_shift); 1379 } 1380 } 1381 mdb_dec_indent(4); 1382 return (DCMD_OK); 1383 } 1384 1385 static int 1386 metaslab_group_stats(uintptr_t addr, int spa_flags) 1387 { 1388 mdb_metaslab_group_t mg; 1389 if (mdb_ctf_vread(&mg, "metaslab_group_t", "mdb_metaslab_group_t", 1390 (uintptr_t)addr, 0) == -1) { 1391 mdb_warn("failed to read vdev_mg at %p\n", addr); 1392 return (DCMD_ERR); 1393 } 1394 1395 mdb_inc_indent(4); 1396 mdb_printf("%<u>%-?s %15s%</u>\n", "ADDR", "FRAGMENTATION"); 1397 if (mg.mg_fragmentation == ZFS_FRAG_INVALID) 1398 mdb_printf("%0?p %15s\n", addr, "-"); 1399 else 1400 mdb_printf("%0?p %15llu%%\n", addr, mg.mg_fragmentation); 1401 1402 if (spa_flags & SPA_FLAG_HISTOGRAMS) 1403 dump_histogram(mg.mg_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0); 1404 mdb_dec_indent(4); 1405 return (DCMD_OK); 1406 } 1407 1408 /* 1409 * ::vdev 1410 * 1411 * Print out a summarized vdev_t, in the following form: 1412 * 1413 * ADDR STATE AUX DESC 1414 * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0 1415 * 1416 * If '-r' is specified, recursively visit all children. 1417 * 1418 * With '-e', the statistics associated with the vdev are printed as well. 1419 */ 1420 static int 1421 do_print_vdev(uintptr_t addr, int flags, int depth, boolean_t recursive, 1422 int spa_flags) 1423 { 1424 vdev_t vdev; 1425 char desc[MAXNAMELEN]; 1426 int c, children; 1427 uintptr_t *child; 1428 const char *state, *aux; 1429 1430 if (mdb_vread(&vdev, sizeof (vdev), (uintptr_t)addr) == -1) { 1431 mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr); 1432 return (DCMD_ERR); 1433 } 1434 1435 if (flags & DCMD_PIPE_OUT) { 1436 mdb_printf("%#lr\n", addr); 1437 } else { 1438 if (vdev.vdev_path != NULL) { 1439 if (mdb_readstr(desc, sizeof (desc), 1440 (uintptr_t)vdev.vdev_path) == -1) { 1441 mdb_warn("failed to read vdev_path at %p\n", 1442 vdev.vdev_path); 1443 return (DCMD_ERR); 1444 } 1445 } else if (vdev.vdev_ops != NULL) { 1446 vdev_ops_t ops; 1447 if (mdb_vread(&ops, sizeof (ops), 1448 (uintptr_t)vdev.vdev_ops) == -1) { 1449 mdb_warn("failed to read vdev_ops at %p\n", 1450 vdev.vdev_ops); 1451 return (DCMD_ERR); 1452 } 1453 (void) strcpy(desc, ops.vdev_op_type); 1454 } else { 1455 (void) strcpy(desc, "<unknown>"); 1456 } 1457 1458 if (depth == 0 && DCMD_HDRSPEC(flags)) 1459 mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n", 1460 "ADDR", "STATE", "AUX", 1461 sizeof (uintptr_t) == 4 ? 43 : 35, 1462 "DESCRIPTION"); 1463 1464 mdb_printf("%0?p ", addr); 1465 1466 switch (vdev.vdev_state) { 1467 case VDEV_STATE_CLOSED: 1468 state = "CLOSED"; 1469 break; 1470 case VDEV_STATE_OFFLINE: 1471 state = "OFFLINE"; 1472 break; 1473 case VDEV_STATE_CANT_OPEN: 1474 state = "CANT_OPEN"; 1475 break; 1476 case VDEV_STATE_DEGRADED: 1477 state = "DEGRADED"; 1478 break; 1479 case VDEV_STATE_HEALTHY: 1480 state = "HEALTHY"; 1481 break; 1482 case VDEV_STATE_REMOVED: 1483 state = "REMOVED"; 1484 break; 1485 case VDEV_STATE_FAULTED: 1486 state = "FAULTED"; 1487 break; 1488 default: 1489 state = "UNKNOWN"; 1490 break; 1491 } 1492 1493 switch (vdev.vdev_stat.vs_aux) { 1494 case VDEV_AUX_NONE: 1495 aux = "-"; 1496 break; 1497 case VDEV_AUX_OPEN_FAILED: 1498 aux = "OPEN_FAILED"; 1499 break; 1500 case VDEV_AUX_CORRUPT_DATA: 1501 aux = "CORRUPT_DATA"; 1502 break; 1503 case VDEV_AUX_NO_REPLICAS: 1504 aux = "NO_REPLICAS"; 1505 break; 1506 case VDEV_AUX_BAD_GUID_SUM: 1507 aux = "BAD_GUID_SUM"; 1508 break; 1509 case VDEV_AUX_TOO_SMALL: 1510 aux = "TOO_SMALL"; 1511 break; 1512 case VDEV_AUX_BAD_LABEL: 1513 aux = "BAD_LABEL"; 1514 break; 1515 case VDEV_AUX_VERSION_NEWER: 1516 aux = "VERS_NEWER"; 1517 break; 1518 case VDEV_AUX_VERSION_OLDER: 1519 aux = "VERS_OLDER"; 1520 break; 1521 case VDEV_AUX_UNSUP_FEAT: 1522 aux = "UNSUP_FEAT"; 1523 break; 1524 case VDEV_AUX_SPARED: 1525 aux = "SPARED"; 1526 break; 1527 case VDEV_AUX_ERR_EXCEEDED: 1528 aux = "ERR_EXCEEDED"; 1529 break; 1530 case VDEV_AUX_IO_FAILURE: 1531 aux = "IO_FAILURE"; 1532 break; 1533 case VDEV_AUX_BAD_LOG: 1534 aux = "BAD_LOG"; 1535 break; 1536 case VDEV_AUX_EXTERNAL: 1537 aux = "EXTERNAL"; 1538 break; 1539 case VDEV_AUX_SPLIT_POOL: 1540 aux = "SPLIT_POOL"; 1541 break; 1542 default: 1543 aux = "UNKNOWN"; 1544 break; 1545 } 1546 1547 mdb_printf("%-9s %-12s %*s%s\n", state, aux, depth, "", desc); 1548 1549 if (spa_flags & SPA_FLAG_ERRORS) { 1550 vdev_stat_t *vs = &vdev.vdev_stat; 1551 int i; 1552 1553 mdb_inc_indent(4); 1554 mdb_printf("\n"); 1555 mdb_printf("%<u> %12s %12s %12s %12s " 1556 "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM", 1557 "IOCTL"); 1558 mdb_printf("OPS "); 1559 for (i = 1; i < ZIO_TYPES; i++) 1560 mdb_printf("%11#llx%s", vs->vs_ops[i], 1561 i == ZIO_TYPES - 1 ? "" : " "); 1562 mdb_printf("\n"); 1563 mdb_printf("BYTES "); 1564 for (i = 1; i < ZIO_TYPES; i++) 1565 mdb_printf("%11#llx%s", vs->vs_bytes[i], 1566 i == ZIO_TYPES - 1 ? "" : " "); 1567 1568 1569 mdb_printf("\n"); 1570 mdb_printf("EREAD %10#llx\n", vs->vs_read_errors); 1571 mdb_printf("EWRITE %10#llx\n", vs->vs_write_errors); 1572 mdb_printf("ECKSUM %10#llx\n", 1573 vs->vs_checksum_errors); 1574 mdb_dec_indent(4); 1575 mdb_printf("\n"); 1576 } 1577 1578 if (spa_flags & SPA_FLAG_METASLAB_GROUPS && 1579 vdev.vdev_mg != NULL) { 1580 metaslab_group_stats((uintptr_t)vdev.vdev_mg, 1581 spa_flags); 1582 } 1583 if (spa_flags & SPA_FLAG_METASLABS && vdev.vdev_ms != NULL) { 1584 metaslab_stats((uintptr_t)addr, spa_flags); 1585 } 1586 } 1587 1588 children = vdev.vdev_children; 1589 1590 if (children == 0 || !recursive) 1591 return (DCMD_OK); 1592 1593 child = mdb_alloc(children * sizeof (void *), UM_SLEEP | UM_GC); 1594 if (mdb_vread(child, children * sizeof (void *), 1595 (uintptr_t)vdev.vdev_child) == -1) { 1596 mdb_warn("failed to read vdev children at %p", vdev.vdev_child); 1597 return (DCMD_ERR); 1598 } 1599 1600 for (c = 0; c < children; c++) { 1601 if (do_print_vdev(child[c], flags, depth + 2, recursive, 1602 spa_flags)) { 1603 return (DCMD_ERR); 1604 } 1605 } 1606 1607 return (DCMD_OK); 1608 } 1609 1610 static int 1611 vdev_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1612 { 1613 uint64_t depth = 0; 1614 boolean_t recursive = B_FALSE; 1615 int spa_flags = 0; 1616 1617 if (mdb_getopts(argc, argv, 1618 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 1619 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 1620 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 1621 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 1622 'r', MDB_OPT_SETBITS, TRUE, &recursive, 1623 'd', MDB_OPT_UINT64, &depth, NULL) != argc) 1624 return (DCMD_USAGE); 1625 1626 if (!(flags & DCMD_ADDRSPEC)) { 1627 mdb_warn("no vdev_t address given\n"); 1628 return (DCMD_ERR); 1629 } 1630 1631 return (do_print_vdev(addr, flags, (int)depth, recursive, spa_flags)); 1632 } 1633 1634 typedef struct metaslab_walk_data { 1635 uint64_t mw_numvdevs; 1636 uintptr_t *mw_vdevs; 1637 int mw_curvdev; 1638 uint64_t mw_nummss; 1639 uintptr_t *mw_mss; 1640 int mw_curms; 1641 } metaslab_walk_data_t; 1642 1643 static int 1644 metaslab_walk_step(mdb_walk_state_t *wsp) 1645 { 1646 metaslab_walk_data_t *mw = wsp->walk_data; 1647 metaslab_t ms; 1648 uintptr_t msp; 1649 1650 if (mw->mw_curvdev >= mw->mw_numvdevs) 1651 return (WALK_DONE); 1652 1653 if (mw->mw_mss == NULL) { 1654 uintptr_t mssp; 1655 uintptr_t vdevp; 1656 1657 ASSERT(mw->mw_curms == 0); 1658 ASSERT(mw->mw_nummss == 0); 1659 1660 vdevp = mw->mw_vdevs[mw->mw_curvdev]; 1661 if (GETMEMB(vdevp, "vdev", vdev_ms, mssp) || 1662 GETMEMB(vdevp, "vdev", vdev_ms_count, mw->mw_nummss)) { 1663 return (WALK_ERR); 1664 } 1665 1666 mw->mw_mss = mdb_alloc(mw->mw_nummss * sizeof (void*), 1667 UM_SLEEP | UM_GC); 1668 if (mdb_vread(mw->mw_mss, mw->mw_nummss * sizeof (void*), 1669 mssp) == -1) { 1670 mdb_warn("failed to read vdev_ms at %p", mssp); 1671 return (WALK_ERR); 1672 } 1673 } 1674 1675 if (mw->mw_curms >= mw->mw_nummss) { 1676 mw->mw_mss = NULL; 1677 mw->mw_curms = 0; 1678 mw->mw_nummss = 0; 1679 mw->mw_curvdev++; 1680 return (WALK_NEXT); 1681 } 1682 1683 msp = mw->mw_mss[mw->mw_curms]; 1684 if (mdb_vread(&ms, sizeof (metaslab_t), msp) == -1) { 1685 mdb_warn("failed to read metaslab_t at %p", msp); 1686 return (WALK_ERR); 1687 } 1688 1689 mw->mw_curms++; 1690 1691 return (wsp->walk_callback(msp, &ms, wsp->walk_cbdata)); 1692 } 1693 1694 static int 1695 metaslab_walk_init(mdb_walk_state_t *wsp) 1696 { 1697 metaslab_walk_data_t *mw; 1698 uintptr_t root_vdevp; 1699 uintptr_t childp; 1700 1701 if (wsp->walk_addr == NULL) { 1702 mdb_warn("must supply address of spa_t\n"); 1703 return (WALK_ERR); 1704 } 1705 1706 mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC); 1707 1708 if (GETMEMB(wsp->walk_addr, "spa", spa_root_vdev, root_vdevp) || 1709 GETMEMB(root_vdevp, "vdev", vdev_children, mw->mw_numvdevs) || 1710 GETMEMB(root_vdevp, "vdev", vdev_child, childp)) { 1711 return (DCMD_ERR); 1712 } 1713 1714 mw->mw_vdevs = mdb_alloc(mw->mw_numvdevs * sizeof (void *), 1715 UM_SLEEP | UM_GC); 1716 if (mdb_vread(mw->mw_vdevs, mw->mw_numvdevs * sizeof (void *), 1717 childp) == -1) { 1718 mdb_warn("failed to read root vdev children at %p", childp); 1719 return (DCMD_ERR); 1720 } 1721 1722 wsp->walk_data = mw; 1723 1724 return (WALK_NEXT); 1725 } 1726 1727 typedef struct mdb_spa { 1728 uintptr_t spa_dsl_pool; 1729 uintptr_t spa_root_vdev; 1730 } mdb_spa_t; 1731 1732 typedef struct mdb_dsl_pool { 1733 uintptr_t dp_root_dir; 1734 } mdb_dsl_pool_t; 1735 1736 typedef struct mdb_dsl_dir { 1737 uintptr_t dd_dbuf; 1738 int64_t dd_space_towrite[TXG_SIZE]; 1739 } mdb_dsl_dir_t; 1740 1741 typedef struct mdb_dsl_dir_phys { 1742 uint64_t dd_used_bytes; 1743 uint64_t dd_compressed_bytes; 1744 uint64_t dd_uncompressed_bytes; 1745 } mdb_dsl_dir_phys_t; 1746 1747 typedef struct space_data { 1748 uint64_t ms_alloctree[TXG_SIZE]; 1749 uint64_t ms_freetree[TXG_SIZE]; 1750 uint64_t ms_tree; 1751 uint64_t avail; 1752 uint64_t nowavail; 1753 } space_data_t; 1754 1755 /* ARGSUSED */ 1756 static int 1757 space_cb(uintptr_t addr, const void *unknown, void *arg) 1758 { 1759 space_data_t *sd = arg; 1760 mdb_metaslab_t ms; 1761 mdb_range_tree_t rt; 1762 mdb_space_map_t sm = { 0 }; 1763 mdb_space_map_phys_t smp = { 0 }; 1764 int i; 1765 1766 if (mdb_ctf_vread(&ms, "metaslab_t", "mdb_metaslab_t", 1767 addr, 0) == -1) 1768 return (WALK_ERR); 1769 1770 for (i = 0; i < TXG_SIZE; i++) { 1771 if (mdb_ctf_vread(&rt, "range_tree_t", 1772 "mdb_range_tree_t", ms.ms_alloctree[i], 0) == -1) 1773 return (WALK_ERR); 1774 1775 sd->ms_alloctree[i] += rt.rt_space; 1776 1777 if (mdb_ctf_vread(&rt, "range_tree_t", 1778 "mdb_range_tree_t", ms.ms_freetree[i], 0) == -1) 1779 return (WALK_ERR); 1780 1781 sd->ms_freetree[i] += rt.rt_space; 1782 } 1783 1784 if (mdb_ctf_vread(&rt, "range_tree_t", 1785 "mdb_range_tree_t", ms.ms_tree, 0) == -1) 1786 return (WALK_ERR); 1787 1788 if (ms.ms_sm != NULL && 1789 mdb_ctf_vread(&sm, "space_map_t", 1790 "mdb_space_map_t", ms.ms_sm, 0) == -1) 1791 return (WALK_ERR); 1792 1793 if (sm.sm_phys != NULL) { 1794 (void) mdb_ctf_vread(&smp, "space_map_phys_t", 1795 "mdb_space_map_phys_t", sm.sm_phys, 0); 1796 } 1797 1798 sd->ms_tree += rt.rt_space; 1799 sd->avail += sm.sm_size - sm.sm_alloc; 1800 sd->nowavail += sm.sm_size - smp.smp_alloc; 1801 1802 return (WALK_NEXT); 1803 } 1804 1805 /* 1806 * ::spa_space [-b] 1807 * 1808 * Given a spa_t, print out it's on-disk space usage and in-core 1809 * estimates of future usage. If -b is given, print space in bytes. 1810 * Otherwise print in megabytes. 1811 */ 1812 /* ARGSUSED */ 1813 static int 1814 spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1815 { 1816 mdb_spa_t spa; 1817 mdb_dsl_pool_t dp; 1818 mdb_dsl_dir_t dd; 1819 mdb_dmu_buf_impl_t db; 1820 mdb_dsl_dir_phys_t dsp; 1821 space_data_t sd; 1822 int shift = 20; 1823 char *suffix = "M"; 1824 int bytes = B_FALSE; 1825 1826 if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bytes, NULL) != 1827 argc) 1828 return (DCMD_USAGE); 1829 if (!(flags & DCMD_ADDRSPEC)) 1830 return (DCMD_USAGE); 1831 1832 if (bytes) { 1833 shift = 0; 1834 suffix = ""; 1835 } 1836 1837 if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_t", 1838 addr, 0) == -1 || 1839 mdb_ctf_vread(&dp, ZFS_STRUCT "dsl_pool", "mdb_dsl_pool_t", 1840 spa.spa_dsl_pool, 0) == -1 || 1841 mdb_ctf_vread(&dd, ZFS_STRUCT "dsl_dir", "mdb_dsl_dir_t", 1842 dp.dp_root_dir, 0) == -1 || 1843 mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t", 1844 dd.dd_dbuf, 0) == -1 || 1845 mdb_ctf_vread(&dsp, ZFS_STRUCT "dsl_dir_phys", 1846 "mdb_dsl_dir_phys_t", db.db.db_data, 0) == -1) { 1847 return (DCMD_ERR); 1848 } 1849 1850 mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n", 1851 dd.dd_space_towrite[0] >> shift, suffix, 1852 dd.dd_space_towrite[1] >> shift, suffix, 1853 dd.dd_space_towrite[2] >> shift, suffix, 1854 dd.dd_space_towrite[3] >> shift, suffix); 1855 1856 mdb_printf("dd_phys.dd_used_bytes = %llu%s\n", 1857 dsp.dd_used_bytes >> shift, suffix); 1858 mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n", 1859 dsp.dd_compressed_bytes >> shift, suffix); 1860 mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n", 1861 dsp.dd_uncompressed_bytes >> shift, suffix); 1862 1863 bzero(&sd, sizeof (sd)); 1864 if (mdb_pwalk("metaslab", space_cb, &sd, addr) != 0) { 1865 mdb_warn("can't walk metaslabs"); 1866 return (DCMD_ERR); 1867 } 1868 1869 mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n", 1870 sd.ms_alloctree[0] >> shift, suffix, 1871 sd.ms_alloctree[1] >> shift, suffix, 1872 sd.ms_alloctree[2] >> shift, suffix, 1873 sd.ms_alloctree[3] >> shift, suffix); 1874 mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n", 1875 sd.ms_freetree[0] >> shift, suffix, 1876 sd.ms_freetree[1] >> shift, suffix, 1877 sd.ms_freetree[2] >> shift, suffix, 1878 sd.ms_freetree[3] >> shift, suffix); 1879 mdb_printf("ms_tree = %llu%s\n", sd.ms_tree >> shift, suffix); 1880 mdb_printf("last synced avail = %llu%s\n", sd.avail >> shift, suffix); 1881 mdb_printf("current syncing avail = %llu%s\n", 1882 sd.nowavail >> shift, suffix); 1883 1884 return (DCMD_OK); 1885 } 1886 1887 typedef struct mdb_spa_aux_vdev { 1888 int sav_count; 1889 uintptr_t sav_vdevs; 1890 } mdb_spa_aux_vdev_t; 1891 1892 typedef struct mdb_spa_vdevs { 1893 uintptr_t spa_root_vdev; 1894 mdb_spa_aux_vdev_t spa_l2cache; 1895 mdb_spa_aux_vdev_t spa_spares; 1896 } mdb_spa_vdevs_t; 1897 1898 static int 1899 spa_print_aux(mdb_spa_aux_vdev_t *sav, uint_t flags, mdb_arg_t *v, 1900 const char *name) 1901 { 1902 uintptr_t *aux; 1903 size_t len; 1904 int ret, i; 1905 1906 /* 1907 * Iterate over aux vdevs and print those out as well. This is a 1908 * little annoying because we don't have a root vdev to pass to ::vdev. 1909 * Instead, we print a single line and then call it for each child 1910 * vdev. 1911 */ 1912 if (sav->sav_count != 0) { 1913 v[1].a_type = MDB_TYPE_STRING; 1914 v[1].a_un.a_str = "-d"; 1915 v[2].a_type = MDB_TYPE_IMMEDIATE; 1916 v[2].a_un.a_val = 2; 1917 1918 len = sav->sav_count * sizeof (uintptr_t); 1919 aux = mdb_alloc(len, UM_SLEEP); 1920 if (mdb_vread(aux, len, sav->sav_vdevs) == -1) { 1921 mdb_free(aux, len); 1922 mdb_warn("failed to read l2cache vdevs at %p", 1923 sav->sav_vdevs); 1924 return (DCMD_ERR); 1925 } 1926 1927 mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name); 1928 1929 for (i = 0; i < sav->sav_count; i++) { 1930 ret = mdb_call_dcmd("vdev", aux[i], flags, 3, v); 1931 if (ret != DCMD_OK) { 1932 mdb_free(aux, len); 1933 return (ret); 1934 } 1935 } 1936 1937 mdb_free(aux, len); 1938 } 1939 1940 return (0); 1941 } 1942 1943 /* 1944 * ::spa_vdevs 1945 * 1946 * -e Include error stats 1947 * -m Include metaslab information 1948 * -M Include metaslab group information 1949 * -h Include histogram information (requires -m or -M) 1950 * 1951 * Print out a summarized list of vdevs for the given spa_t. 1952 * This is accomplished by invoking "::vdev -re" on the root vdev, as well as 1953 * iterating over the cache devices. 1954 */ 1955 /* ARGSUSED */ 1956 static int 1957 spa_vdevs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1958 { 1959 mdb_arg_t v[3]; 1960 int ret; 1961 char opts[100] = "-r"; 1962 int spa_flags = 0; 1963 1964 if (mdb_getopts(argc, argv, 1965 'e', MDB_OPT_SETBITS, SPA_FLAG_ERRORS, &spa_flags, 1966 'm', MDB_OPT_SETBITS, SPA_FLAG_METASLABS, &spa_flags, 1967 'M', MDB_OPT_SETBITS, SPA_FLAG_METASLAB_GROUPS, &spa_flags, 1968 'h', MDB_OPT_SETBITS, SPA_FLAG_HISTOGRAMS, &spa_flags, 1969 NULL) != argc) 1970 return (DCMD_USAGE); 1971 1972 if (!(flags & DCMD_ADDRSPEC)) 1973 return (DCMD_USAGE); 1974 1975 mdb_spa_vdevs_t spa; 1976 if (mdb_ctf_vread(&spa, "spa_t", "mdb_spa_vdevs_t", addr, 0) == -1) 1977 return (DCMD_ERR); 1978 1979 /* 1980 * Unitialized spa_t structures can have a NULL root vdev. 1981 */ 1982 if (spa.spa_root_vdev == NULL) { 1983 mdb_printf("no associated vdevs\n"); 1984 return (DCMD_OK); 1985 } 1986 1987 if (spa_flags & SPA_FLAG_ERRORS) 1988 strcat(opts, "e"); 1989 if (spa_flags & SPA_FLAG_METASLABS) 1990 strcat(opts, "m"); 1991 if (spa_flags & SPA_FLAG_METASLAB_GROUPS) 1992 strcat(opts, "M"); 1993 if (spa_flags & SPA_FLAG_HISTOGRAMS) 1994 strcat(opts, "h"); 1995 1996 v[0].a_type = MDB_TYPE_STRING; 1997 v[0].a_un.a_str = opts; 1998 1999 ret = mdb_call_dcmd("vdev", (uintptr_t)spa.spa_root_vdev, 2000 flags, 1, v); 2001 if (ret != DCMD_OK) 2002 return (ret); 2003 2004 if (spa_print_aux(&spa.spa_l2cache, flags, v, "cache") != 0 || 2005 spa_print_aux(&spa.spa_spares, flags, v, "spares") != 0) 2006 return (DCMD_ERR); 2007 2008 return (DCMD_OK); 2009 } 2010 2011 /* 2012 * ::zio 2013 * 2014 * Print a summary of zio_t and all its children. This is intended to display a 2015 * zio tree, and hence we only pick the most important pieces of information for 2016 * the main summary. More detailed information can always be found by doing a 2017 * '::print zio' on the underlying zio_t. The columns we display are: 2018 * 2019 * ADDRESS TYPE STAGE WAITER TIME_ELAPSED 2020 * 2021 * The 'address' column is indented by one space for each depth level as we 2022 * descend down the tree. 2023 */ 2024 2025 #define ZIO_MAXINDENT 7 2026 #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT) 2027 #define ZIO_WALK_SELF 0 2028 #define ZIO_WALK_CHILD 1 2029 #define ZIO_WALK_PARENT 2 2030 2031 typedef struct zio_print_args { 2032 int zpa_current_depth; 2033 int zpa_min_depth; 2034 int zpa_max_depth; 2035 int zpa_type; 2036 uint_t zpa_flags; 2037 } zio_print_args_t; 2038 2039 typedef struct mdb_zio { 2040 enum zio_type io_type; 2041 enum zio_stage io_stage; 2042 uintptr_t io_waiter; 2043 uintptr_t io_spa; 2044 struct { 2045 struct { 2046 uintptr_t list_next; 2047 } list_head; 2048 } io_parent_list; 2049 int io_error; 2050 } mdb_zio_t; 2051 2052 typedef struct mdb_zio_timestamp { 2053 hrtime_t io_timestamp; 2054 } mdb_zio_timestamp_t; 2055 2056 static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg); 2057 2058 static int 2059 zio_print_cb(uintptr_t addr, zio_print_args_t *zpa) 2060 { 2061 mdb_ctf_id_t type_enum, stage_enum; 2062 int indent = zpa->zpa_current_depth; 2063 const char *type, *stage; 2064 uintptr_t laddr; 2065 mdb_zio_t zio; 2066 mdb_zio_timestamp_t zio_timestamp = { 0 }; 2067 2068 if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", addr, 0) == -1) 2069 return (WALK_ERR); 2070 (void) mdb_ctf_vread(&zio_timestamp, ZFS_STRUCT "zio", 2071 "mdb_zio_timestamp_t", addr, MDB_CTF_VREAD_QUIET); 2072 2073 if (indent > ZIO_MAXINDENT) 2074 indent = ZIO_MAXINDENT; 2075 2076 if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum) == -1 || 2077 mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum) == -1) { 2078 mdb_warn("failed to lookup zio enums"); 2079 return (WALK_ERR); 2080 } 2081 2082 if ((type = mdb_ctf_enum_name(type_enum, zio.io_type)) != NULL) 2083 type += sizeof ("ZIO_TYPE_") - 1; 2084 else 2085 type = "?"; 2086 2087 if (zio.io_error == 0) { 2088 stage = mdb_ctf_enum_name(stage_enum, zio.io_stage); 2089 if (stage != NULL) 2090 stage += sizeof ("ZIO_STAGE_") - 1; 2091 else 2092 stage = "?"; 2093 } else { 2094 stage = "FAILED"; 2095 } 2096 2097 if (zpa->zpa_current_depth >= zpa->zpa_min_depth) { 2098 if (zpa->zpa_flags & DCMD_PIPE_OUT) { 2099 mdb_printf("%?p\n", addr); 2100 } else { 2101 mdb_printf("%*s%-*p %-5s %-16s ", indent, "", 2102 ZIO_MAXWIDTH - indent, addr, type, stage); 2103 if (zio.io_waiter != 0) 2104 mdb_printf("%-16lx ", zio.io_waiter); 2105 else 2106 mdb_printf("%-16s ", "-"); 2107 #ifdef _KERNEL 2108 if (zio_timestamp.io_timestamp != 0) { 2109 mdb_printf("%llums", (mdb_gethrtime() - 2110 zio_timestamp.io_timestamp) / 2111 1000000); 2112 } else { 2113 mdb_printf("%-12s ", "-"); 2114 } 2115 #else 2116 mdb_printf("%-12s ", "-"); 2117 #endif 2118 mdb_printf("\n"); 2119 } 2120 } 2121 2122 if (zpa->zpa_current_depth >= zpa->zpa_max_depth) 2123 return (WALK_NEXT); 2124 2125 if (zpa->zpa_type == ZIO_WALK_PARENT) 2126 laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", 2127 "io_parent_list"); 2128 else 2129 laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", 2130 "io_child_list"); 2131 2132 zpa->zpa_current_depth++; 2133 if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) { 2134 mdb_warn("failed to walk zio_t children at %p\n", laddr); 2135 return (WALK_ERR); 2136 } 2137 zpa->zpa_current_depth--; 2138 2139 return (WALK_NEXT); 2140 } 2141 2142 /* ARGSUSED */ 2143 static int 2144 zio_child_cb(uintptr_t addr, const void *unknown, void *arg) 2145 { 2146 zio_link_t zl; 2147 uintptr_t ziop; 2148 zio_print_args_t *zpa = arg; 2149 2150 if (mdb_vread(&zl, sizeof (zl), addr) == -1) { 2151 mdb_warn("failed to read zio_link_t at %p", addr); 2152 return (WALK_ERR); 2153 } 2154 2155 if (zpa->zpa_type == ZIO_WALK_PARENT) 2156 ziop = (uintptr_t)zl.zl_parent; 2157 else 2158 ziop = (uintptr_t)zl.zl_child; 2159 2160 return (zio_print_cb(ziop, zpa)); 2161 } 2162 2163 /* ARGSUSED */ 2164 static int 2165 zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2166 { 2167 zio_print_args_t zpa = { 0 }; 2168 2169 if (!(flags & DCMD_ADDRSPEC)) 2170 return (DCMD_USAGE); 2171 2172 if (mdb_getopts(argc, argv, 2173 'r', MDB_OPT_SETBITS, INT_MAX, &zpa.zpa_max_depth, 2174 'c', MDB_OPT_SETBITS, ZIO_WALK_CHILD, &zpa.zpa_type, 2175 'p', MDB_OPT_SETBITS, ZIO_WALK_PARENT, &zpa.zpa_type, 2176 NULL) != argc) 2177 return (DCMD_USAGE); 2178 2179 zpa.zpa_flags = flags; 2180 if (zpa.zpa_max_depth != 0) { 2181 if (zpa.zpa_type == ZIO_WALK_SELF) 2182 zpa.zpa_type = ZIO_WALK_CHILD; 2183 } else if (zpa.zpa_type != ZIO_WALK_SELF) { 2184 zpa.zpa_min_depth = 1; 2185 zpa.zpa_max_depth = 1; 2186 } 2187 2188 if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) { 2189 mdb_printf("%<u>%-*s %-5s %-16s %-16s %-12s%</u>\n", 2190 ZIO_MAXWIDTH, "ADDRESS", "TYPE", "STAGE", "WAITER", 2191 "TIME_ELAPSED"); 2192 } 2193 2194 if (zio_print_cb(addr, &zpa) != WALK_NEXT) 2195 return (DCMD_ERR); 2196 2197 return (DCMD_OK); 2198 } 2199 2200 /* 2201 * [addr]::zio_state 2202 * 2203 * Print a summary of all zio_t structures on the system, or for a particular 2204 * pool. This is equivalent to '::walk zio_root | ::zio'. 2205 */ 2206 /*ARGSUSED*/ 2207 static int 2208 zio_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2209 { 2210 /* 2211 * MDB will remember the last address of the pipeline, so if we don't 2212 * zero this we'll end up trying to walk zio structures for a 2213 * non-existent spa_t. 2214 */ 2215 if (!(flags & DCMD_ADDRSPEC)) 2216 addr = 0; 2217 2218 return (mdb_pwalk_dcmd("zio_root", "zio", argc, argv, addr)); 2219 } 2220 2221 typedef struct mdb_multilist { 2222 uint64_t ml_num_sublists; 2223 uintptr_t ml_sublists; 2224 } mdb_multilist_t; 2225 2226 typedef struct multilist_walk_data { 2227 uint64_t mwd_idx; 2228 mdb_multilist_t mwd_ml; 2229 } multilist_walk_data_t; 2230 2231 /* ARGSUSED */ 2232 static int 2233 multilist_print_cb(uintptr_t addr, const void *unknown, void *arg) 2234 { 2235 mdb_printf("%#lr\n", addr); 2236 return (WALK_NEXT); 2237 } 2238 2239 static int 2240 multilist_walk_step(mdb_walk_state_t *wsp) 2241 { 2242 multilist_walk_data_t *mwd = wsp->walk_data; 2243 2244 if (mwd->mwd_idx >= mwd->mwd_ml.ml_num_sublists) 2245 return (WALK_DONE); 2246 2247 wsp->walk_addr = mwd->mwd_ml.ml_sublists + 2248 mdb_ctf_sizeof_by_name("multilist_sublist_t") * mwd->mwd_idx + 2249 mdb_ctf_offsetof_by_name("multilist_sublist_t", "mls_list"); 2250 2251 mdb_pwalk("list", multilist_print_cb, (void*)NULL, wsp->walk_addr); 2252 mwd->mwd_idx++; 2253 2254 return (WALK_NEXT); 2255 } 2256 2257 static int 2258 multilist_walk_init(mdb_walk_state_t *wsp) 2259 { 2260 multilist_walk_data_t *mwd; 2261 2262 if (wsp->walk_addr == NULL) { 2263 mdb_warn("must supply address of multilist_t\n"); 2264 return (WALK_ERR); 2265 } 2266 2267 mwd = mdb_zalloc(sizeof (multilist_walk_data_t), UM_SLEEP | UM_GC); 2268 if (mdb_ctf_vread(&mwd->mwd_ml, "multilist_t", "mdb_multilist_t", 2269 wsp->walk_addr, 0) == -1) { 2270 return (WALK_ERR); 2271 } 2272 2273 if (mwd->mwd_ml.ml_num_sublists == 0 || 2274 mwd->mwd_ml.ml_sublists == NULL) { 2275 mdb_warn("invalid or uninitialized multilist at %#lx\n", 2276 wsp->walk_addr); 2277 return (WALK_ERR); 2278 } 2279 2280 wsp->walk_data = mwd; 2281 return (WALK_NEXT); 2282 } 2283 2284 typedef struct txg_list_walk_data { 2285 uintptr_t lw_head[TXG_SIZE]; 2286 int lw_txgoff; 2287 int lw_maxoff; 2288 size_t lw_offset; 2289 void *lw_obj; 2290 } txg_list_walk_data_t; 2291 2292 static int 2293 txg_list_walk_init_common(mdb_walk_state_t *wsp, int txg, int maxoff) 2294 { 2295 txg_list_walk_data_t *lwd; 2296 txg_list_t list; 2297 int i; 2298 2299 lwd = mdb_alloc(sizeof (txg_list_walk_data_t), UM_SLEEP | UM_GC); 2300 if (mdb_vread(&list, sizeof (txg_list_t), wsp->walk_addr) == -1) { 2301 mdb_warn("failed to read txg_list_t at %#lx", wsp->walk_addr); 2302 return (WALK_ERR); 2303 } 2304 2305 for (i = 0; i < TXG_SIZE; i++) 2306 lwd->lw_head[i] = (uintptr_t)list.tl_head[i]; 2307 lwd->lw_offset = list.tl_offset; 2308 lwd->lw_obj = mdb_alloc(lwd->lw_offset + sizeof (txg_node_t), 2309 UM_SLEEP | UM_GC); 2310 lwd->lw_txgoff = txg; 2311 lwd->lw_maxoff = maxoff; 2312 2313 wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 2314 wsp->walk_data = lwd; 2315 2316 return (WALK_NEXT); 2317 } 2318 2319 static int 2320 txg_list_walk_init(mdb_walk_state_t *wsp) 2321 { 2322 return (txg_list_walk_init_common(wsp, 0, TXG_SIZE-1)); 2323 } 2324 2325 static int 2326 txg_list0_walk_init(mdb_walk_state_t *wsp) 2327 { 2328 return (txg_list_walk_init_common(wsp, 0, 0)); 2329 } 2330 2331 static int 2332 txg_list1_walk_init(mdb_walk_state_t *wsp) 2333 { 2334 return (txg_list_walk_init_common(wsp, 1, 1)); 2335 } 2336 2337 static int 2338 txg_list2_walk_init(mdb_walk_state_t *wsp) 2339 { 2340 return (txg_list_walk_init_common(wsp, 2, 2)); 2341 } 2342 2343 static int 2344 txg_list3_walk_init(mdb_walk_state_t *wsp) 2345 { 2346 return (txg_list_walk_init_common(wsp, 3, 3)); 2347 } 2348 2349 static int 2350 txg_list_walk_step(mdb_walk_state_t *wsp) 2351 { 2352 txg_list_walk_data_t *lwd = wsp->walk_data; 2353 uintptr_t addr; 2354 txg_node_t *node; 2355 int status; 2356 2357 while (wsp->walk_addr == NULL && lwd->lw_txgoff < lwd->lw_maxoff) { 2358 lwd->lw_txgoff++; 2359 wsp->walk_addr = lwd->lw_head[lwd->lw_txgoff]; 2360 } 2361 2362 if (wsp->walk_addr == NULL) 2363 return (WALK_DONE); 2364 2365 addr = wsp->walk_addr - lwd->lw_offset; 2366 2367 if (mdb_vread(lwd->lw_obj, 2368 lwd->lw_offset + sizeof (txg_node_t), addr) == -1) { 2369 mdb_warn("failed to read list element at %#lx", addr); 2370 return (WALK_ERR); 2371 } 2372 2373 status = wsp->walk_callback(addr, lwd->lw_obj, wsp->walk_cbdata); 2374 node = (txg_node_t *)((uintptr_t)lwd->lw_obj + lwd->lw_offset); 2375 wsp->walk_addr = (uintptr_t)node->tn_next[lwd->lw_txgoff]; 2376 2377 return (status); 2378 } 2379 2380 /* 2381 * ::walk spa 2382 * 2383 * Walk all named spa_t structures in the namespace. This is nothing more than 2384 * a layered avl walk. 2385 */ 2386 static int 2387 spa_walk_init(mdb_walk_state_t *wsp) 2388 { 2389 GElf_Sym sym; 2390 2391 if (wsp->walk_addr != NULL) { 2392 mdb_warn("spa walk only supports global walks\n"); 2393 return (WALK_ERR); 2394 } 2395 2396 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "spa_namespace_avl", &sym) == -1) { 2397 mdb_warn("failed to find symbol 'spa_namespace_avl'"); 2398 return (WALK_ERR); 2399 } 2400 2401 wsp->walk_addr = (uintptr_t)sym.st_value; 2402 2403 if (mdb_layered_walk("avl", wsp) == -1) { 2404 mdb_warn("failed to walk 'avl'\n"); 2405 return (WALK_ERR); 2406 } 2407 2408 return (WALK_NEXT); 2409 } 2410 2411 static int 2412 spa_walk_step(mdb_walk_state_t *wsp) 2413 { 2414 return (wsp->walk_callback(wsp->walk_addr, NULL, wsp->walk_cbdata)); 2415 } 2416 2417 /* 2418 * [addr]::walk zio 2419 * 2420 * Walk all active zio_t structures on the system. This is simply a layered 2421 * walk on top of ::walk zio_cache, with the optional ability to limit the 2422 * structures to a particular pool. 2423 */ 2424 static int 2425 zio_walk_init(mdb_walk_state_t *wsp) 2426 { 2427 wsp->walk_data = (void *)wsp->walk_addr; 2428 2429 if (mdb_layered_walk("zio_cache", wsp) == -1) { 2430 mdb_warn("failed to walk 'zio_cache'\n"); 2431 return (WALK_ERR); 2432 } 2433 2434 return (WALK_NEXT); 2435 } 2436 2437 static int 2438 zio_walk_step(mdb_walk_state_t *wsp) 2439 { 2440 mdb_zio_t zio; 2441 uintptr_t spa = (uintptr_t)wsp->walk_data; 2442 2443 if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", 2444 wsp->walk_addr, 0) == -1) 2445 return (WALK_ERR); 2446 2447 if (spa != 0 && spa != zio.io_spa) 2448 return (WALK_NEXT); 2449 2450 return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 2451 } 2452 2453 /* 2454 * [addr]::walk zio_root 2455 * 2456 * Walk only root zio_t structures, optionally for a particular spa_t. 2457 */ 2458 static int 2459 zio_walk_root_step(mdb_walk_state_t *wsp) 2460 { 2461 mdb_zio_t zio; 2462 uintptr_t spa = (uintptr_t)wsp->walk_data; 2463 2464 if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", 2465 wsp->walk_addr, 0) == -1) 2466 return (WALK_ERR); 2467 2468 if (spa != 0 && spa != zio.io_spa) 2469 return (WALK_NEXT); 2470 2471 /* If the parent list is not empty, ignore */ 2472 if (zio.io_parent_list.list_head.list_next != 2473 wsp->walk_addr + 2474 mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", "io_parent_list") + 2475 mdb_ctf_offsetof_by_name("struct list", "list_head")) 2476 return (WALK_NEXT); 2477 2478 return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata)); 2479 } 2480 2481 /* 2482 * ::zfs_blkstats 2483 * 2484 * -v print verbose per-level information 2485 * 2486 */ 2487 static int 2488 zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2489 { 2490 boolean_t verbose = B_FALSE; 2491 zfs_all_blkstats_t stats; 2492 dmu_object_type_t t; 2493 zfs_blkstat_t *tzb; 2494 uint64_t ditto; 2495 dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10]; 2496 /* +10 in case it grew */ 2497 2498 if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) { 2499 mdb_warn("failed to read 'dmu_ot'"); 2500 return (DCMD_ERR); 2501 } 2502 2503 if (mdb_getopts(argc, argv, 2504 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2505 NULL) != argc) 2506 return (DCMD_USAGE); 2507 2508 if (!(flags & DCMD_ADDRSPEC)) 2509 return (DCMD_USAGE); 2510 2511 if (GETMEMB(addr, "spa", spa_dsl_pool, addr) || 2512 GETMEMB(addr, "dsl_pool", dp_blkstats, addr) || 2513 mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) { 2514 mdb_warn("failed to read data at %p;", addr); 2515 mdb_printf("maybe no stats? run \"zpool scrub\" first."); 2516 return (DCMD_ERR); 2517 } 2518 2519 tzb = &stats.zab_type[DN_MAX_LEVELS][DMU_OT_TOTAL]; 2520 if (tzb->zb_gangs != 0) { 2521 mdb_printf("Ganged blocks: %llu\n", 2522 (longlong_t)tzb->zb_gangs); 2523 } 2524 2525 ditto = tzb->zb_ditto_2_of_2_samevdev + tzb->zb_ditto_2_of_3_samevdev + 2526 tzb->zb_ditto_3_of_3_samevdev; 2527 if (ditto != 0) { 2528 mdb_printf("Dittoed blocks on same vdev: %llu\n", 2529 (longlong_t)ditto); 2530 } 2531 2532 mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE" 2533 "\t avg\t comp\t%%Total\tType\n"); 2534 2535 for (t = 0; t <= DMU_OT_TOTAL; t++) { 2536 char csize[NICENUM_BUFLEN], lsize[NICENUM_BUFLEN]; 2537 char psize[NICENUM_BUFLEN], asize[NICENUM_BUFLEN]; 2538 char avg[NICENUM_BUFLEN]; 2539 char comp[NICENUM_BUFLEN], pct[NICENUM_BUFLEN]; 2540 char typename[64]; 2541 int l; 2542 2543 2544 if (t == DMU_OT_DEFERRED) 2545 strcpy(typename, "deferred free"); 2546 else if (t == DMU_OT_OTHER) 2547 strcpy(typename, "other"); 2548 else if (t == DMU_OT_TOTAL) 2549 strcpy(typename, "Total"); 2550 else if (mdb_readstr(typename, sizeof (typename), 2551 (uintptr_t)dmu_ot[t].ot_name) == -1) { 2552 mdb_warn("failed to read type name"); 2553 return (DCMD_ERR); 2554 } 2555 2556 if (stats.zab_type[DN_MAX_LEVELS][t].zb_asize == 0) 2557 continue; 2558 2559 for (l = -1; l < DN_MAX_LEVELS; l++) { 2560 int level = (l == -1 ? DN_MAX_LEVELS : l); 2561 zfs_blkstat_t *zb = &stats.zab_type[level][t]; 2562 2563 if (zb->zb_asize == 0) 2564 continue; 2565 2566 /* 2567 * Don't print each level unless requested. 2568 */ 2569 if (!verbose && level != DN_MAX_LEVELS) 2570 continue; 2571 2572 /* 2573 * If all the space is level 0, don't print the 2574 * level 0 separately. 2575 */ 2576 if (level == 0 && zb->zb_asize == 2577 stats.zab_type[DN_MAX_LEVELS][t].zb_asize) 2578 continue; 2579 2580 mdb_nicenum(zb->zb_count, csize); 2581 mdb_nicenum(zb->zb_lsize, lsize); 2582 mdb_nicenum(zb->zb_psize, psize); 2583 mdb_nicenum(zb->zb_asize, asize); 2584 mdb_nicenum(zb->zb_asize / zb->zb_count, avg); 2585 (void) snprintfrac(comp, NICENUM_BUFLEN, 2586 zb->zb_lsize, zb->zb_psize, 2); 2587 (void) snprintfrac(pct, NICENUM_BUFLEN, 2588 100 * zb->zb_asize, tzb->zb_asize, 2); 2589 2590 mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s" 2591 "\t%5s\t%6s\t", 2592 csize, lsize, psize, asize, avg, comp, pct); 2593 2594 if (level == DN_MAX_LEVELS) 2595 mdb_printf("%s\n", typename); 2596 else 2597 mdb_printf(" L%d %s\n", 2598 level, typename); 2599 } 2600 } 2601 2602 return (DCMD_OK); 2603 } 2604 2605 typedef struct mdb_reference { 2606 uintptr_t ref_holder; 2607 uintptr_t ref_removed; 2608 uint64_t ref_number; 2609 } mdb_reference_t; 2610 2611 /* ARGSUSED */ 2612 static int 2613 reference_cb(uintptr_t addr, const void *ignored, void *arg) 2614 { 2615 mdb_reference_t ref; 2616 boolean_t holder_is_str = B_FALSE; 2617 char holder_str[128]; 2618 boolean_t removed = (boolean_t)arg; 2619 2620 if (mdb_ctf_vread(&ref, "reference_t", "mdb_reference_t", addr, 2621 0) == -1) 2622 return (DCMD_ERR); 2623 2624 if (mdb_readstr(holder_str, sizeof (holder_str), 2625 ref.ref_holder) != -1) 2626 holder_is_str = strisprint(holder_str); 2627 2628 if (removed) 2629 mdb_printf("removed "); 2630 mdb_printf("reference "); 2631 if (ref.ref_number != 1) 2632 mdb_printf("with count=%llu ", ref.ref_number); 2633 mdb_printf("with tag %lx", ref.ref_holder); 2634 if (holder_is_str) 2635 mdb_printf(" \"%s\"", holder_str); 2636 mdb_printf(", held at:\n"); 2637 2638 (void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL); 2639 2640 if (removed) { 2641 mdb_printf("removed at:\n"); 2642 (void) mdb_call_dcmd("whatis", ref.ref_removed, 2643 DCMD_ADDRSPEC, 0, NULL); 2644 } 2645 2646 mdb_printf("\n"); 2647 2648 return (WALK_NEXT); 2649 } 2650 2651 typedef struct mdb_refcount { 2652 uint64_t rc_count; 2653 } mdb_refcount_t; 2654 2655 typedef struct mdb_refcount_removed { 2656 uint64_t rc_removed_count; 2657 } mdb_refcount_removed_t; 2658 2659 typedef struct mdb_refcount_tracked { 2660 boolean_t rc_tracked; 2661 } mdb_refcount_tracked_t; 2662 2663 /* ARGSUSED */ 2664 static int 2665 refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2666 { 2667 mdb_refcount_t rc; 2668 mdb_refcount_removed_t rcr; 2669 mdb_refcount_tracked_t rct; 2670 int off; 2671 boolean_t released = B_FALSE; 2672 2673 if (!(flags & DCMD_ADDRSPEC)) 2674 return (DCMD_USAGE); 2675 2676 if (mdb_getopts(argc, argv, 2677 'r', MDB_OPT_SETBITS, B_TRUE, &released, 2678 NULL) != argc) 2679 return (DCMD_USAGE); 2680 2681 if (mdb_ctf_vread(&rc, "refcount_t", "mdb_refcount_t", addr, 2682 0) == -1) 2683 return (DCMD_ERR); 2684 2685 if (mdb_ctf_vread(&rcr, "refcount_t", "mdb_refcount_removed_t", addr, 2686 MDB_CTF_VREAD_QUIET) == -1) { 2687 mdb_printf("refcount_t at %p has %llu holds (untracked)\n", 2688 addr, (longlong_t)rc.rc_count); 2689 return (DCMD_OK); 2690 } 2691 2692 if (mdb_ctf_vread(&rct, "refcount_t", "mdb_refcount_tracked_t", addr, 2693 MDB_CTF_VREAD_QUIET) == -1) { 2694 /* If this is an old target, it might be tracked. */ 2695 rct.rc_tracked = B_TRUE; 2696 } 2697 2698 mdb_printf("refcount_t at %p has %llu current holds, " 2699 "%llu recently released holds\n", 2700 addr, (longlong_t)rc.rc_count, (longlong_t)rcr.rc_removed_count); 2701 2702 if (rct.rc_tracked && rc.rc_count > 0) 2703 mdb_printf("current holds:\n"); 2704 off = mdb_ctf_offsetof_by_name("refcount_t", "rc_list"); 2705 if (off == -1) 2706 return (DCMD_ERR); 2707 mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off); 2708 2709 if (released && rcr.rc_removed_count > 0) { 2710 mdb_printf("released holds:\n"); 2711 2712 off = mdb_ctf_offsetof_by_name("refcount_t", "rc_removed"); 2713 if (off == -1) 2714 return (DCMD_ERR); 2715 mdb_pwalk("list", reference_cb, (void*)B_TRUE, addr + off); 2716 } 2717 2718 return (DCMD_OK); 2719 } 2720 2721 /* ARGSUSED */ 2722 static int 2723 sa_attr_table(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2724 { 2725 sa_attr_table_t *table; 2726 sa_os_t sa_os; 2727 char *name; 2728 int i; 2729 2730 if (mdb_vread(&sa_os, sizeof (sa_os_t), addr) == -1) { 2731 mdb_warn("failed to read sa_os at %p", addr); 2732 return (DCMD_ERR); 2733 } 2734 2735 table = mdb_alloc(sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 2736 UM_SLEEP | UM_GC); 2737 name = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC); 2738 2739 if (mdb_vread(table, sizeof (sa_attr_table_t) * sa_os.sa_num_attrs, 2740 (uintptr_t)sa_os.sa_attr_table) == -1) { 2741 mdb_warn("failed to read sa_os at %p", addr); 2742 return (DCMD_ERR); 2743 } 2744 2745 mdb_printf("%<u>%-10s %-10s %-10s %-10s %s%</u>\n", 2746 "ATTR ID", "REGISTERED", "LENGTH", "BSWAP", "NAME"); 2747 for (i = 0; i != sa_os.sa_num_attrs; i++) { 2748 mdb_readstr(name, MAXPATHLEN, (uintptr_t)table[i].sa_name); 2749 mdb_printf("%5x %8x %8x %8x %-s\n", 2750 (int)table[i].sa_attr, (int)table[i].sa_registered, 2751 (int)table[i].sa_length, table[i].sa_byteswap, name); 2752 } 2753 2754 return (DCMD_OK); 2755 } 2756 2757 static int 2758 sa_get_off_table(uintptr_t addr, uint32_t **off_tab, int attr_count) 2759 { 2760 uintptr_t idx_table; 2761 2762 if (GETMEMB(addr, "sa_idx_tab", sa_idx_tab, idx_table)) { 2763 mdb_printf("can't find offset table in sa_idx_tab\n"); 2764 return (-1); 2765 } 2766 2767 *off_tab = mdb_alloc(attr_count * sizeof (uint32_t), 2768 UM_SLEEP | UM_GC); 2769 2770 if (mdb_vread(*off_tab, 2771 attr_count * sizeof (uint32_t), idx_table) == -1) { 2772 mdb_warn("failed to attribute offset table %p", idx_table); 2773 return (-1); 2774 } 2775 2776 return (DCMD_OK); 2777 } 2778 2779 /*ARGSUSED*/ 2780 static int 2781 sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2782 { 2783 uint32_t *offset_tab; 2784 int attr_count; 2785 uint64_t attr_id; 2786 uintptr_t attr_addr; 2787 uintptr_t bonus_tab, spill_tab; 2788 uintptr_t db_bonus, db_spill; 2789 uintptr_t os, os_sa; 2790 uintptr_t db_data; 2791 2792 if (argc != 1) 2793 return (DCMD_USAGE); 2794 2795 if (argv[0].a_type == MDB_TYPE_STRING) 2796 attr_id = mdb_strtoull(argv[0].a_un.a_str); 2797 else 2798 return (DCMD_USAGE); 2799 2800 if (GETMEMB(addr, "sa_handle", sa_bonus_tab, bonus_tab) || 2801 GETMEMB(addr, "sa_handle", sa_spill_tab, spill_tab) || 2802 GETMEMB(addr, "sa_handle", sa_os, os) || 2803 GETMEMB(addr, "sa_handle", sa_bonus, db_bonus) || 2804 GETMEMB(addr, "sa_handle", sa_spill, db_spill)) { 2805 mdb_printf("Can't find necessary information in sa_handle " 2806 "in sa_handle\n"); 2807 return (DCMD_ERR); 2808 } 2809 2810 if (GETMEMB(os, "objset", os_sa, os_sa)) { 2811 mdb_printf("Can't find os_sa in objset\n"); 2812 return (DCMD_ERR); 2813 } 2814 2815 if (GETMEMB(os_sa, "sa_os", sa_num_attrs, attr_count)) { 2816 mdb_printf("Can't find sa_num_attrs\n"); 2817 return (DCMD_ERR); 2818 } 2819 2820 if (attr_id > attr_count) { 2821 mdb_printf("attribute id number is out of range\n"); 2822 return (DCMD_ERR); 2823 } 2824 2825 if (bonus_tab) { 2826 if (sa_get_off_table(bonus_tab, &offset_tab, 2827 attr_count) == -1) { 2828 return (DCMD_ERR); 2829 } 2830 2831 if (GETMEMB(db_bonus, "dmu_buf", db_data, db_data)) { 2832 mdb_printf("can't find db_data in bonus dbuf\n"); 2833 return (DCMD_ERR); 2834 } 2835 } 2836 2837 if (bonus_tab && !TOC_ATTR_PRESENT(offset_tab[attr_id]) && 2838 spill_tab == NULL) { 2839 mdb_printf("Attribute does not exist\n"); 2840 return (DCMD_ERR); 2841 } else if (!TOC_ATTR_PRESENT(offset_tab[attr_id]) && spill_tab) { 2842 if (sa_get_off_table(spill_tab, &offset_tab, 2843 attr_count) == -1) { 2844 return (DCMD_ERR); 2845 } 2846 if (GETMEMB(db_spill, "dmu_buf", db_data, db_data)) { 2847 mdb_printf("can't find db_data in spill dbuf\n"); 2848 return (DCMD_ERR); 2849 } 2850 if (!TOC_ATTR_PRESENT(offset_tab[attr_id])) { 2851 mdb_printf("Attribute does not exist\n"); 2852 return (DCMD_ERR); 2853 } 2854 } 2855 attr_addr = db_data + TOC_OFF(offset_tab[attr_id]); 2856 mdb_printf("%p\n", attr_addr); 2857 return (DCMD_OK); 2858 } 2859 2860 /* ARGSUSED */ 2861 static int 2862 zfs_ace_print_common(uintptr_t addr, uint_t flags, 2863 uint64_t id, uint32_t access_mask, uint16_t ace_flags, 2864 uint16_t ace_type, int verbose) 2865 { 2866 if (DCMD_HDRSPEC(flags) && !verbose) 2867 mdb_printf("%<u>%-?s %-8s %-8s %-8s %s%</u>\n", 2868 "ADDR", "FLAGS", "MASK", "TYPE", "ID"); 2869 2870 if (!verbose) { 2871 mdb_printf("%0?p %-8x %-8x %-8x %-llx\n", addr, 2872 ace_flags, access_mask, ace_type, id); 2873 return (DCMD_OK); 2874 } 2875 2876 switch (ace_flags & ACE_TYPE_FLAGS) { 2877 case ACE_OWNER: 2878 mdb_printf("owner@:"); 2879 break; 2880 case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 2881 mdb_printf("group@:"); 2882 break; 2883 case ACE_EVERYONE: 2884 mdb_printf("everyone@:"); 2885 break; 2886 case ACE_IDENTIFIER_GROUP: 2887 mdb_printf("group:%llx:", (u_longlong_t)id); 2888 break; 2889 case 0: /* User entry */ 2890 mdb_printf("user:%llx:", (u_longlong_t)id); 2891 break; 2892 } 2893 2894 /* print out permission mask */ 2895 if (access_mask & ACE_READ_DATA) 2896 mdb_printf("r"); 2897 else 2898 mdb_printf("-"); 2899 if (access_mask & ACE_WRITE_DATA) 2900 mdb_printf("w"); 2901 else 2902 mdb_printf("-"); 2903 if (access_mask & ACE_EXECUTE) 2904 mdb_printf("x"); 2905 else 2906 mdb_printf("-"); 2907 if (access_mask & ACE_APPEND_DATA) 2908 mdb_printf("p"); 2909 else 2910 mdb_printf("-"); 2911 if (access_mask & ACE_DELETE) 2912 mdb_printf("d"); 2913 else 2914 mdb_printf("-"); 2915 if (access_mask & ACE_DELETE_CHILD) 2916 mdb_printf("D"); 2917 else 2918 mdb_printf("-"); 2919 if (access_mask & ACE_READ_ATTRIBUTES) 2920 mdb_printf("a"); 2921 else 2922 mdb_printf("-"); 2923 if (access_mask & ACE_WRITE_ATTRIBUTES) 2924 mdb_printf("A"); 2925 else 2926 mdb_printf("-"); 2927 if (access_mask & ACE_READ_NAMED_ATTRS) 2928 mdb_printf("R"); 2929 else 2930 mdb_printf("-"); 2931 if (access_mask & ACE_WRITE_NAMED_ATTRS) 2932 mdb_printf("W"); 2933 else 2934 mdb_printf("-"); 2935 if (access_mask & ACE_READ_ACL) 2936 mdb_printf("c"); 2937 else 2938 mdb_printf("-"); 2939 if (access_mask & ACE_WRITE_ACL) 2940 mdb_printf("C"); 2941 else 2942 mdb_printf("-"); 2943 if (access_mask & ACE_WRITE_OWNER) 2944 mdb_printf("o"); 2945 else 2946 mdb_printf("-"); 2947 if (access_mask & ACE_SYNCHRONIZE) 2948 mdb_printf("s"); 2949 else 2950 mdb_printf("-"); 2951 2952 mdb_printf(":"); 2953 2954 /* Print out inheritance flags */ 2955 if (ace_flags & ACE_FILE_INHERIT_ACE) 2956 mdb_printf("f"); 2957 else 2958 mdb_printf("-"); 2959 if (ace_flags & ACE_DIRECTORY_INHERIT_ACE) 2960 mdb_printf("d"); 2961 else 2962 mdb_printf("-"); 2963 if (ace_flags & ACE_INHERIT_ONLY_ACE) 2964 mdb_printf("i"); 2965 else 2966 mdb_printf("-"); 2967 if (ace_flags & ACE_NO_PROPAGATE_INHERIT_ACE) 2968 mdb_printf("n"); 2969 else 2970 mdb_printf("-"); 2971 if (ace_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 2972 mdb_printf("S"); 2973 else 2974 mdb_printf("-"); 2975 if (ace_flags & ACE_FAILED_ACCESS_ACE_FLAG) 2976 mdb_printf("F"); 2977 else 2978 mdb_printf("-"); 2979 if (ace_flags & ACE_INHERITED_ACE) 2980 mdb_printf("I"); 2981 else 2982 mdb_printf("-"); 2983 2984 switch (ace_type) { 2985 case ACE_ACCESS_ALLOWED_ACE_TYPE: 2986 mdb_printf(":allow\n"); 2987 break; 2988 case ACE_ACCESS_DENIED_ACE_TYPE: 2989 mdb_printf(":deny\n"); 2990 break; 2991 case ACE_SYSTEM_AUDIT_ACE_TYPE: 2992 mdb_printf(":audit\n"); 2993 break; 2994 case ACE_SYSTEM_ALARM_ACE_TYPE: 2995 mdb_printf(":alarm\n"); 2996 break; 2997 default: 2998 mdb_printf(":?\n"); 2999 } 3000 return (DCMD_OK); 3001 } 3002 3003 /* ARGSUSED */ 3004 static int 3005 zfs_ace_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3006 { 3007 zfs_ace_t zace; 3008 int verbose = FALSE; 3009 uint64_t id; 3010 3011 if (!(flags & DCMD_ADDRSPEC)) 3012 return (DCMD_USAGE); 3013 3014 if (mdb_getopts(argc, argv, 3015 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 3016 return (DCMD_USAGE); 3017 3018 if (mdb_vread(&zace, sizeof (zfs_ace_t), addr) == -1) { 3019 mdb_warn("failed to read zfs_ace_t"); 3020 return (DCMD_ERR); 3021 } 3022 3023 if ((zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == 0 || 3024 (zace.z_hdr.z_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 3025 id = zace.z_fuid; 3026 else 3027 id = -1; 3028 3029 return (zfs_ace_print_common(addr, flags, id, zace.z_hdr.z_access_mask, 3030 zace.z_hdr.z_flags, zace.z_hdr.z_type, verbose)); 3031 } 3032 3033 /* ARGSUSED */ 3034 static int 3035 zfs_ace0_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3036 { 3037 ace_t ace; 3038 uint64_t id; 3039 int verbose = FALSE; 3040 3041 if (!(flags & DCMD_ADDRSPEC)) 3042 return (DCMD_USAGE); 3043 3044 if (mdb_getopts(argc, argv, 3045 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 3046 return (DCMD_USAGE); 3047 3048 if (mdb_vread(&ace, sizeof (ace_t), addr) == -1) { 3049 mdb_warn("failed to read ace_t"); 3050 return (DCMD_ERR); 3051 } 3052 3053 if ((ace.a_flags & ACE_TYPE_FLAGS) == 0 || 3054 (ace.a_flags & ACE_TYPE_FLAGS) == ACE_IDENTIFIER_GROUP) 3055 id = ace.a_who; 3056 else 3057 id = -1; 3058 3059 return (zfs_ace_print_common(addr, flags, id, ace.a_access_mask, 3060 ace.a_flags, ace.a_type, verbose)); 3061 } 3062 3063 typedef struct acl_dump_args { 3064 int a_argc; 3065 const mdb_arg_t *a_argv; 3066 uint16_t a_version; 3067 int a_flags; 3068 } acl_dump_args_t; 3069 3070 /* ARGSUSED */ 3071 static int 3072 acl_aces_cb(uintptr_t addr, const void *unknown, void *arg) 3073 { 3074 acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 3075 3076 if (acl_args->a_version == 1) { 3077 if (mdb_call_dcmd("zfs_ace", addr, 3078 DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 3079 acl_args->a_argv) != DCMD_OK) { 3080 return (WALK_ERR); 3081 } 3082 } else { 3083 if (mdb_call_dcmd("zfs_ace0", addr, 3084 DCMD_ADDRSPEC|acl_args->a_flags, acl_args->a_argc, 3085 acl_args->a_argv) != DCMD_OK) { 3086 return (WALK_ERR); 3087 } 3088 } 3089 acl_args->a_flags = DCMD_LOOP; 3090 return (WALK_NEXT); 3091 } 3092 3093 /* ARGSUSED */ 3094 static int 3095 acl_cb(uintptr_t addr, const void *unknown, void *arg) 3096 { 3097 acl_dump_args_t *acl_args = (acl_dump_args_t *)arg; 3098 3099 if (acl_args->a_version == 1) { 3100 if (mdb_pwalk("zfs_acl_node_aces", acl_aces_cb, 3101 arg, addr) != 0) { 3102 mdb_warn("can't walk ACEs"); 3103 return (DCMD_ERR); 3104 } 3105 } else { 3106 if (mdb_pwalk("zfs_acl_node_aces0", acl_aces_cb, 3107 arg, addr) != 0) { 3108 mdb_warn("can't walk ACEs"); 3109 return (DCMD_ERR); 3110 } 3111 } 3112 return (WALK_NEXT); 3113 } 3114 3115 /* ARGSUSED */ 3116 static int 3117 zfs_acl_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3118 { 3119 zfs_acl_t zacl; 3120 int verbose = FALSE; 3121 acl_dump_args_t acl_args; 3122 3123 if (!(flags & DCMD_ADDRSPEC)) 3124 return (DCMD_USAGE); 3125 3126 if (mdb_getopts(argc, argv, 3127 'v', MDB_OPT_SETBITS, TRUE, &verbose, TRUE, NULL) != argc) 3128 return (DCMD_USAGE); 3129 3130 if (mdb_vread(&zacl, sizeof (zfs_acl_t), addr) == -1) { 3131 mdb_warn("failed to read zfs_acl_t"); 3132 return (DCMD_ERR); 3133 } 3134 3135 acl_args.a_argc = argc; 3136 acl_args.a_argv = argv; 3137 acl_args.a_version = zacl.z_version; 3138 acl_args.a_flags = DCMD_LOOPFIRST; 3139 3140 if (mdb_pwalk("zfs_acl_node", acl_cb, &acl_args, addr) != 0) { 3141 mdb_warn("can't walk ACL"); 3142 return (DCMD_ERR); 3143 } 3144 3145 return (DCMD_OK); 3146 } 3147 3148 /* ARGSUSED */ 3149 static int 3150 zfs_acl_node_walk_init(mdb_walk_state_t *wsp) 3151 { 3152 if (wsp->walk_addr == NULL) { 3153 mdb_warn("must supply address of zfs_acl_node_t\n"); 3154 return (WALK_ERR); 3155 } 3156 3157 wsp->walk_addr += 3158 mdb_ctf_offsetof_by_name(ZFS_STRUCT "zfs_acl", "z_acl"); 3159 3160 if (mdb_layered_walk("list", wsp) == -1) { 3161 mdb_warn("failed to walk 'list'\n"); 3162 return (WALK_ERR); 3163 } 3164 3165 return (WALK_NEXT); 3166 } 3167 3168 static int 3169 zfs_acl_node_walk_step(mdb_walk_state_t *wsp) 3170 { 3171 zfs_acl_node_t aclnode; 3172 3173 if (mdb_vread(&aclnode, sizeof (zfs_acl_node_t), 3174 wsp->walk_addr) == -1) { 3175 mdb_warn("failed to read zfs_acl_node at %p", wsp->walk_addr); 3176 return (WALK_ERR); 3177 } 3178 3179 return (wsp->walk_callback(wsp->walk_addr, &aclnode, wsp->walk_cbdata)); 3180 } 3181 3182 typedef struct ace_walk_data { 3183 int ace_count; 3184 int ace_version; 3185 } ace_walk_data_t; 3186 3187 static int 3188 zfs_aces_walk_init_common(mdb_walk_state_t *wsp, int version, 3189 int ace_count, uintptr_t ace_data) 3190 { 3191 ace_walk_data_t *ace_walk_data; 3192 3193 if (wsp->walk_addr == NULL) { 3194 mdb_warn("must supply address of zfs_acl_node_t\n"); 3195 return (WALK_ERR); 3196 } 3197 3198 ace_walk_data = mdb_alloc(sizeof (ace_walk_data_t), UM_SLEEP | UM_GC); 3199 3200 ace_walk_data->ace_count = ace_count; 3201 ace_walk_data->ace_version = version; 3202 3203 wsp->walk_addr = ace_data; 3204 wsp->walk_data = ace_walk_data; 3205 3206 return (WALK_NEXT); 3207 } 3208 3209 static int 3210 zfs_acl_node_aces_walk_init_common(mdb_walk_state_t *wsp, int version) 3211 { 3212 static int gotid; 3213 static mdb_ctf_id_t acl_id; 3214 int z_ace_count; 3215 uintptr_t z_acldata; 3216 3217 if (!gotid) { 3218 if (mdb_ctf_lookup_by_name("struct zfs_acl_node", 3219 &acl_id) == -1) { 3220 mdb_warn("couldn't find struct zfs_acl_node"); 3221 return (DCMD_ERR); 3222 } 3223 gotid = TRUE; 3224 } 3225 3226 if (GETMEMBID(wsp->walk_addr, &acl_id, z_ace_count, z_ace_count)) { 3227 return (DCMD_ERR); 3228 } 3229 if (GETMEMBID(wsp->walk_addr, &acl_id, z_acldata, z_acldata)) { 3230 return (DCMD_ERR); 3231 } 3232 3233 return (zfs_aces_walk_init_common(wsp, version, 3234 z_ace_count, z_acldata)); 3235 } 3236 3237 /* ARGSUSED */ 3238 static int 3239 zfs_acl_node_aces_walk_init(mdb_walk_state_t *wsp) 3240 { 3241 return (zfs_acl_node_aces_walk_init_common(wsp, 1)); 3242 } 3243 3244 /* ARGSUSED */ 3245 static int 3246 zfs_acl_node_aces0_walk_init(mdb_walk_state_t *wsp) 3247 { 3248 return (zfs_acl_node_aces_walk_init_common(wsp, 0)); 3249 } 3250 3251 static int 3252 zfs_aces_walk_step(mdb_walk_state_t *wsp) 3253 { 3254 ace_walk_data_t *ace_data = wsp->walk_data; 3255 zfs_ace_t zace; 3256 ace_t *acep; 3257 int status; 3258 int entry_type; 3259 int allow_type; 3260 uintptr_t ptr; 3261 3262 if (ace_data->ace_count == 0) 3263 return (WALK_DONE); 3264 3265 if (mdb_vread(&zace, sizeof (zfs_ace_t), wsp->walk_addr) == -1) { 3266 mdb_warn("failed to read zfs_ace_t at %#lx", 3267 wsp->walk_addr); 3268 return (WALK_ERR); 3269 } 3270 3271 switch (ace_data->ace_version) { 3272 case 0: 3273 acep = (ace_t *)&zace; 3274 entry_type = acep->a_flags & ACE_TYPE_FLAGS; 3275 allow_type = acep->a_type; 3276 break; 3277 case 1: 3278 entry_type = zace.z_hdr.z_flags & ACE_TYPE_FLAGS; 3279 allow_type = zace.z_hdr.z_type; 3280 break; 3281 default: 3282 return (WALK_ERR); 3283 } 3284 3285 ptr = (uintptr_t)wsp->walk_addr; 3286 switch (entry_type) { 3287 case ACE_OWNER: 3288 case ACE_EVERYONE: 3289 case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 3290 ptr += ace_data->ace_version == 0 ? 3291 sizeof (ace_t) : sizeof (zfs_ace_hdr_t); 3292 break; 3293 case ACE_IDENTIFIER_GROUP: 3294 default: 3295 switch (allow_type) { 3296 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 3297 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 3298 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 3299 case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 3300 ptr += ace_data->ace_version == 0 ? 3301 sizeof (ace_t) : sizeof (zfs_object_ace_t); 3302 break; 3303 default: 3304 ptr += ace_data->ace_version == 0 ? 3305 sizeof (ace_t) : sizeof (zfs_ace_t); 3306 break; 3307 } 3308 } 3309 3310 ace_data->ace_count--; 3311 status = wsp->walk_callback(wsp->walk_addr, 3312 (void *)(uintptr_t)&zace, wsp->walk_cbdata); 3313 3314 wsp->walk_addr = ptr; 3315 return (status); 3316 } 3317 3318 typedef struct mdb_zfs_rrwlock { 3319 uintptr_t rr_writer; 3320 boolean_t rr_writer_wanted; 3321 } mdb_zfs_rrwlock_t; 3322 3323 static uint_t rrw_key; 3324 3325 /* ARGSUSED */ 3326 static int 3327 rrwlock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3328 { 3329 mdb_zfs_rrwlock_t rrw; 3330 3331 if (rrw_key == 0) { 3332 if (mdb_ctf_readsym(&rrw_key, "uint_t", "rrw_tsd_key", 0) == -1) 3333 return (DCMD_ERR); 3334 } 3335 3336 if (mdb_ctf_vread(&rrw, "rrwlock_t", "mdb_zfs_rrwlock_t", addr, 3337 0) == -1) 3338 return (DCMD_ERR); 3339 3340 if (rrw.rr_writer != 0) { 3341 mdb_printf("write lock held by thread %lx\n", rrw.rr_writer); 3342 return (DCMD_OK); 3343 } 3344 3345 if (rrw.rr_writer_wanted) { 3346 mdb_printf("writer wanted\n"); 3347 } 3348 3349 mdb_printf("anonymous references:\n"); 3350 (void) mdb_call_dcmd("refcount", addr + 3351 mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_anon_rcount"), 3352 DCMD_ADDRSPEC, 0, NULL); 3353 3354 mdb_printf("linked references:\n"); 3355 (void) mdb_call_dcmd("refcount", addr + 3356 mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_linked_rcount"), 3357 DCMD_ADDRSPEC, 0, NULL); 3358 3359 /* 3360 * XXX This should find references from 3361 * "::walk thread | ::tsd -v <rrw_key>", but there is no support 3362 * for programmatic consumption of dcmds, so this would be 3363 * difficult, potentially requiring reimplementing ::tsd (both 3364 * user and kernel versions) in this MDB module. 3365 */ 3366 3367 return (DCMD_OK); 3368 } 3369 3370 typedef struct mdb_arc_buf_hdr_t { 3371 uint16_t b_psize; 3372 uint16_t b_lsize; 3373 struct { 3374 uint32_t b_bufcnt; 3375 uintptr_t b_state; 3376 uintptr_t b_pdata; 3377 } b_l1hdr; 3378 } mdb_arc_buf_hdr_t; 3379 3380 enum arc_cflags { 3381 ARC_CFLAG_VERBOSE = 1 << 0, 3382 ARC_CFLAG_ANON = 1 << 1, 3383 ARC_CFLAG_MRU = 1 << 2, 3384 ARC_CFLAG_MFU = 1 << 3, 3385 ARC_CFLAG_BUFS = 1 << 4, 3386 }; 3387 3388 typedef struct arc_compression_stats_data { 3389 GElf_Sym anon_sym; /* ARC_anon symbol */ 3390 GElf_Sym mru_sym; /* ARC_mru symbol */ 3391 GElf_Sym mrug_sym; /* ARC_mru_ghost symbol */ 3392 GElf_Sym mfu_sym; /* ARC_mfu symbol */ 3393 GElf_Sym mfug_sym; /* ARC_mfu_ghost symbol */ 3394 GElf_Sym l2c_sym; /* ARC_l2c_only symbol */ 3395 uint64_t *anon_c_hist; /* histogram of compressed sizes in anon */ 3396 uint64_t *anon_u_hist; /* histogram of uncompressed sizes in anon */ 3397 uint64_t *anon_bufs; /* histogram of buffer counts in anon state */ 3398 uint64_t *mru_c_hist; /* histogram of compressed sizes in mru */ 3399 uint64_t *mru_u_hist; /* histogram of uncompressed sizes in mru */ 3400 uint64_t *mru_bufs; /* histogram of buffer counts in mru */ 3401 uint64_t *mfu_c_hist; /* histogram of compressed sizes in mfu */ 3402 uint64_t *mfu_u_hist; /* histogram of uncompressed sizes in mfu */ 3403 uint64_t *mfu_bufs; /* histogram of buffer counts in mfu */ 3404 uint64_t *all_c_hist; /* histogram of compressed anon + mru + mfu */ 3405 uint64_t *all_u_hist; /* histogram of uncompressed anon + mru + mfu */ 3406 uint64_t *all_bufs; /* histogram of buffer counts in all states */ 3407 int arc_cflags; /* arc compression flags, specified by user */ 3408 int hist_nbuckets; /* number of buckets in each histogram */ 3409 } arc_compression_stats_data_t; 3410 3411 int 3412 highbit64(uint64_t i) 3413 { 3414 int h = 1; 3415 3416 if (i == 0) 3417 return (0); 3418 if (i & 0xffffffff00000000ULL) { 3419 h += 32; i >>= 32; 3420 } 3421 if (i & 0xffff0000) { 3422 h += 16; i >>= 16; 3423 } 3424 if (i & 0xff00) { 3425 h += 8; i >>= 8; 3426 } 3427 if (i & 0xf0) { 3428 h += 4; i >>= 4; 3429 } 3430 if (i & 0xc) { 3431 h += 2; i >>= 2; 3432 } 3433 if (i & 0x2) { 3434 h += 1; 3435 } 3436 return (h); 3437 } 3438 3439 /* ARGSUSED */ 3440 static int 3441 arc_compression_stats_cb(uintptr_t addr, const void *unknown, void *arg) 3442 { 3443 arc_compression_stats_data_t *data = arg; 3444 mdb_arc_buf_hdr_t hdr; 3445 int cbucket, ubucket, bufcnt; 3446 3447 if (mdb_ctf_vread(&hdr, "arc_buf_hdr_t", "mdb_arc_buf_hdr_t", 3448 addr, 0) == -1) { 3449 return (WALK_ERR); 3450 } 3451 3452 /* 3453 * Headers in the ghost states, or the l2c_only state don't have 3454 * arc buffers linked off of them. Thus, their compressed size 3455 * is meaningless, so we skip these from the stats. 3456 */ 3457 if (hdr.b_l1hdr.b_state == data->mrug_sym.st_value || 3458 hdr.b_l1hdr.b_state == data->mfug_sym.st_value || 3459 hdr.b_l1hdr.b_state == data->l2c_sym.st_value) { 3460 return (WALK_NEXT); 3461 } 3462 3463 /* 3464 * The physical size (compressed) and logical size 3465 * (uncompressed) are in units of SPA_MINBLOCKSIZE. By default, 3466 * we use the log2 of this value (rounded down to the nearest 3467 * integer) to determine the bucket to assign this header to. 3468 * Thus, the histogram is logarithmic with respect to the size 3469 * of the header. For example, the following is a mapping of the 3470 * bucket numbers and the range of header sizes they correspond to: 3471 * 3472 * 0: 0 byte headers 3473 * 1: 512 byte headers 3474 * 2: [1024 - 2048) byte headers 3475 * 3: [2048 - 4096) byte headers 3476 * 4: [4096 - 8192) byte headers 3477 * 5: [8192 - 16394) byte headers 3478 * 6: [16384 - 32768) byte headers 3479 * 7: [32768 - 65536) byte headers 3480 * 8: [65536 - 131072) byte headers 3481 * 9: 131072 byte headers 3482 * 3483 * If the ARC_CFLAG_VERBOSE flag was specified, we use the 3484 * physical and logical sizes directly. Thus, the histogram will 3485 * no longer be logarithmic; instead it will be linear with 3486 * respect to the size of the header. The following is a mapping 3487 * of the first many bucket numbers and the header size they 3488 * correspond to: 3489 * 3490 * 0: 0 byte headers 3491 * 1: 512 byte headers 3492 * 2: 1024 byte headers 3493 * 3: 1536 byte headers 3494 * 4: 2048 byte headers 3495 * 5: 2560 byte headers 3496 * 6: 3072 byte headers 3497 * 3498 * And so on. Keep in mind that a range of sizes isn't used in 3499 * the case of linear scale because the headers can only 3500 * increment or decrement in sizes of 512 bytes. So, it's not 3501 * possible for a header to be sized in between whats listed 3502 * above. 3503 * 3504 * Also, the above mapping values were calculated assuming a 3505 * SPA_MINBLOCKSHIFT of 512 bytes and a SPA_MAXBLOCKSIZE of 128K. 3506 */ 3507 3508 if (data->arc_cflags & ARC_CFLAG_VERBOSE) { 3509 cbucket = hdr.b_psize; 3510 ubucket = hdr.b_lsize; 3511 } else { 3512 cbucket = highbit64(hdr.b_psize); 3513 ubucket = highbit64(hdr.b_lsize); 3514 } 3515 3516 bufcnt = hdr.b_l1hdr.b_bufcnt; 3517 if (bufcnt >= data->hist_nbuckets) 3518 bufcnt = data->hist_nbuckets - 1; 3519 3520 /* Ensure we stay within the bounds of the histogram array */ 3521 ASSERT3U(cbucket, <, data->hist_nbuckets); 3522 ASSERT3U(ubucket, <, data->hist_nbuckets); 3523 3524 if (hdr.b_l1hdr.b_state == data->anon_sym.st_value) { 3525 data->anon_c_hist[cbucket]++; 3526 data->anon_u_hist[ubucket]++; 3527 data->anon_bufs[bufcnt]++; 3528 } else if (hdr.b_l1hdr.b_state == data->mru_sym.st_value) { 3529 data->mru_c_hist[cbucket]++; 3530 data->mru_u_hist[ubucket]++; 3531 data->mru_bufs[bufcnt]++; 3532 } else if (hdr.b_l1hdr.b_state == data->mfu_sym.st_value) { 3533 data->mfu_c_hist[cbucket]++; 3534 data->mfu_u_hist[ubucket]++; 3535 data->mfu_bufs[bufcnt]++; 3536 } 3537 3538 data->all_c_hist[cbucket]++; 3539 data->all_u_hist[ubucket]++; 3540 data->all_bufs[bufcnt]++; 3541 3542 return (WALK_NEXT); 3543 } 3544 3545 /* ARGSUSED */ 3546 static int 3547 arc_compression_stats(uintptr_t addr, uint_t flags, int argc, 3548 const mdb_arg_t *argv) 3549 { 3550 arc_compression_stats_data_t data = { 0 }; 3551 unsigned int max_shifted = SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; 3552 unsigned int hist_size; 3553 char range[32]; 3554 int rc = DCMD_OK; 3555 3556 if (mdb_getopts(argc, argv, 3557 'v', MDB_OPT_SETBITS, ARC_CFLAG_VERBOSE, &data.arc_cflags, 3558 'a', MDB_OPT_SETBITS, ARC_CFLAG_ANON, &data.arc_cflags, 3559 'b', MDB_OPT_SETBITS, ARC_CFLAG_BUFS, &data.arc_cflags, 3560 'r', MDB_OPT_SETBITS, ARC_CFLAG_MRU, &data.arc_cflags, 3561 'f', MDB_OPT_SETBITS, ARC_CFLAG_MFU, &data.arc_cflags) != argc) 3562 return (DCMD_USAGE); 3563 3564 if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_anon", &data.anon_sym) || 3565 mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mru", &data.mru_sym) || 3566 mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mru_ghost", &data.mrug_sym) || 3567 mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mfu", &data.mfu_sym) || 3568 mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_mfu_ghost", &data.mfug_sym) || 3569 mdb_lookup_by_obj(ZFS_OBJ_NAME, "ARC_l2c_only", &data.l2c_sym)) { 3570 mdb_warn("can't find arc state symbol"); 3571 return (DCMD_ERR); 3572 } 3573 3574 /* 3575 * Determine the maximum expected size for any header, and use 3576 * this to determine the number of buckets needed for each 3577 * histogram. If ARC_CFLAG_VERBOSE is specified, this value is 3578 * used directly; otherwise the log2 of the maximum size is 3579 * used. Thus, if using a log2 scale there's a maximum of 10 3580 * possible buckets, while the linear scale (when using 3581 * ARC_CFLAG_VERBOSE) has a maximum of 257 buckets. 3582 */ 3583 if (data.arc_cflags & ARC_CFLAG_VERBOSE) 3584 data.hist_nbuckets = max_shifted + 1; 3585 else 3586 data.hist_nbuckets = highbit64(max_shifted) + 1; 3587 3588 hist_size = sizeof (uint64_t) * data.hist_nbuckets; 3589 3590 data.anon_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3591 data.anon_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3592 data.anon_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3593 3594 data.mru_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3595 data.mru_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3596 data.mru_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3597 3598 data.mfu_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3599 data.mfu_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3600 data.mfu_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3601 3602 data.all_c_hist = mdb_zalloc(hist_size, UM_SLEEP); 3603 data.all_u_hist = mdb_zalloc(hist_size, UM_SLEEP); 3604 data.all_bufs = mdb_zalloc(hist_size, UM_SLEEP); 3605 3606 if (mdb_walk("arc_buf_hdr_t_full", arc_compression_stats_cb, 3607 &data) != 0) { 3608 mdb_warn("can't walk arc_buf_hdr's"); 3609 rc = DCMD_ERR; 3610 goto out; 3611 } 3612 3613 if (data.arc_cflags & ARC_CFLAG_VERBOSE) { 3614 rc = mdb_snprintf(range, sizeof (range), 3615 "[n*%llu, (n+1)*%llu)", SPA_MINBLOCKSIZE, 3616 SPA_MINBLOCKSIZE); 3617 } else { 3618 rc = mdb_snprintf(range, sizeof (range), 3619 "[2^(n-1)*%llu, 2^n*%llu)", SPA_MINBLOCKSIZE, 3620 SPA_MINBLOCKSIZE); 3621 } 3622 3623 if (rc < 0) { 3624 /* snprintf failed, abort the dcmd */ 3625 rc = DCMD_ERR; 3626 goto out; 3627 } else { 3628 /* snprintf succeeded above, reset return code */ 3629 rc = DCMD_OK; 3630 } 3631 3632 if (data.arc_cflags & ARC_CFLAG_ANON) { 3633 if (data.arc_cflags & ARC_CFLAG_BUFS) { 3634 mdb_printf("Histogram of the number of anon buffers " 3635 "that are associated with an arc hdr.\n"); 3636 dump_histogram(data.anon_bufs, data.hist_nbuckets, 0); 3637 mdb_printf("\n"); 3638 } 3639 mdb_printf("Histogram of compressed anon buffers.\n" 3640 "Each bucket represents buffers of size: %s.\n", range); 3641 dump_histogram(data.anon_c_hist, data.hist_nbuckets, 0); 3642 mdb_printf("\n"); 3643 3644 mdb_printf("Histogram of uncompressed anon buffers.\n" 3645 "Each bucket represents buffers of size: %s.\n", range); 3646 dump_histogram(data.anon_u_hist, data.hist_nbuckets, 0); 3647 mdb_printf("\n"); 3648 } 3649 3650 if (data.arc_cflags & ARC_CFLAG_MRU) { 3651 if (data.arc_cflags & ARC_CFLAG_BUFS) { 3652 mdb_printf("Histogram of the number of mru buffers " 3653 "that are associated with an arc hdr.\n"); 3654 dump_histogram(data.mru_bufs, data.hist_nbuckets, 0); 3655 mdb_printf("\n"); 3656 } 3657 mdb_printf("Histogram of compressed mru buffers.\n" 3658 "Each bucket represents buffers of size: %s.\n", range); 3659 dump_histogram(data.mru_c_hist, data.hist_nbuckets, 0); 3660 mdb_printf("\n"); 3661 3662 mdb_printf("Histogram of uncompressed mru buffers.\n" 3663 "Each bucket represents buffers of size: %s.\n", range); 3664 dump_histogram(data.mru_u_hist, data.hist_nbuckets, 0); 3665 mdb_printf("\n"); 3666 } 3667 3668 if (data.arc_cflags & ARC_CFLAG_MFU) { 3669 if (data.arc_cflags & ARC_CFLAG_BUFS) { 3670 mdb_printf("Histogram of the number of mfu buffers " 3671 "that are associated with an arc hdr.\n"); 3672 dump_histogram(data.mfu_bufs, data.hist_nbuckets, 0); 3673 mdb_printf("\n"); 3674 } 3675 3676 mdb_printf("Histogram of compressed mfu buffers.\n" 3677 "Each bucket represents buffers of size: %s.\n", range); 3678 dump_histogram(data.mfu_c_hist, data.hist_nbuckets, 0); 3679 mdb_printf("\n"); 3680 3681 mdb_printf("Histogram of uncompressed mfu buffers.\n" 3682 "Each bucket represents buffers of size: %s.\n", range); 3683 dump_histogram(data.mfu_u_hist, data.hist_nbuckets, 0); 3684 mdb_printf("\n"); 3685 } 3686 3687 if (data.arc_cflags & ARC_CFLAG_BUFS) { 3688 mdb_printf("Histogram of all buffers that " 3689 "are associated with an arc hdr.\n"); 3690 dump_histogram(data.all_bufs, data.hist_nbuckets, 0); 3691 mdb_printf("\n"); 3692 } 3693 3694 mdb_printf("Histogram of all compressed buffers.\n" 3695 "Each bucket represents buffers of size: %s.\n", range); 3696 dump_histogram(data.all_c_hist, data.hist_nbuckets, 0); 3697 mdb_printf("\n"); 3698 3699 mdb_printf("Histogram of all uncompressed buffers.\n" 3700 "Each bucket represents buffers of size: %s.\n", range); 3701 dump_histogram(data.all_u_hist, data.hist_nbuckets, 0); 3702 3703 out: 3704 mdb_free(data.anon_c_hist, hist_size); 3705 mdb_free(data.anon_u_hist, hist_size); 3706 mdb_free(data.anon_bufs, hist_size); 3707 3708 mdb_free(data.mru_c_hist, hist_size); 3709 mdb_free(data.mru_u_hist, hist_size); 3710 mdb_free(data.mru_bufs, hist_size); 3711 3712 mdb_free(data.mfu_c_hist, hist_size); 3713 mdb_free(data.mfu_u_hist, hist_size); 3714 mdb_free(data.mfu_bufs, hist_size); 3715 3716 mdb_free(data.all_c_hist, hist_size); 3717 mdb_free(data.all_u_hist, hist_size); 3718 mdb_free(data.all_bufs, hist_size); 3719 3720 return (rc); 3721 } 3722 3723 /* 3724 * MDB module linkage information: 3725 * 3726 * We declare a list of structures describing our dcmds, and a function 3727 * named _mdb_init to return a pointer to our module information. 3728 */ 3729 3730 static const mdb_dcmd_t dcmds[] = { 3731 { "arc", "[-bkmg]", "print ARC variables", arc_print }, 3732 { "blkptr", ":", "print blkptr_t", blkptr }, 3733 { "dbuf", ":", "print dmu_buf_impl_t", dbuf }, 3734 { "dbuf_stats", ":", "dbuf stats", dbuf_stats }, 3735 { "dbufs", 3736 "\t[-O objset_t*] [-n objset_name | \"mos\"] " 3737 "[-o object | \"mdn\"] \n" 3738 "\t[-l level] [-b blkid | \"bonus\"]", 3739 "find dmu_buf_impl_t's that match specified criteria", dbufs }, 3740 { "abuf_find", "dva_word[0] dva_word[1]", 3741 "find arc_buf_hdr_t of a specified DVA", 3742 abuf_find }, 3743 { "spa", "?[-cevmMh]\n" 3744 "\t-c display spa config\n" 3745 "\t-e display vdev statistics\n" 3746 "\t-v display vdev information\n" 3747 "\t-m display metaslab statistics\n" 3748 "\t-M display metaslab group statistics\n" 3749 "\t-h display histogram (requires -m or -M)\n", 3750 "spa_t summary", spa_print }, 3751 { "spa_config", ":", "print spa_t configuration", spa_print_config }, 3752 { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space }, 3753 { "spa_vdevs", ":[-emMh]\n" 3754 "\t-e display vdev statistics\n" 3755 "\t-m dispaly metaslab statistics\n" 3756 "\t-M display metaslab group statistic\n" 3757 "\t-h display histogram (requires -m or -M)\n", 3758 "given a spa_t, print vdev summary", spa_vdevs }, 3759 { "vdev", ":[-remMh]\n" 3760 "\t-r display recursively\n" 3761 "\t-e display statistics\n" 3762 "\t-m display metaslab statistics (top level vdev only)\n" 3763 "\t-M display metaslab group statistics (top level vdev only)\n" 3764 "\t-h display histogram (requires -m or -M)\n", 3765 "vdev_t summary", vdev_print }, 3766 { "zio", ":[-cpr]\n" 3767 "\t-c display children\n" 3768 "\t-p display parents\n" 3769 "\t-r display recursively", 3770 "zio_t summary", zio_print }, 3771 { "zio_state", "?", "print out all zio_t structures on system or " 3772 "for a particular pool", zio_state }, 3773 { "zfs_blkstats", ":[-v]", 3774 "given a spa_t, print block type stats from last scrub", 3775 zfs_blkstats }, 3776 { "zfs_params", "", "print zfs tunable parameters", zfs_params }, 3777 { "refcount", ":[-r]\n" 3778 "\t-r display recently removed references", 3779 "print refcount_t holders", refcount }, 3780 { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf }, 3781 { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t", 3782 zfs_acl_dump }, 3783 { "zfs_ace", ":[-v]", "print zfs_ace", zfs_ace_print }, 3784 { "zfs_ace0", ":[-v]", "print zfs_ace0", zfs_ace0_print }, 3785 { "sa_attr_table", ":", "print SA attribute table from sa_os_t", 3786 sa_attr_table}, 3787 { "sa_attr", ": attr_id", 3788 "print SA attribute address when given sa_handle_t", sa_attr_print}, 3789 { "zfs_dbgmsg", ":[-va]", 3790 "print zfs debug log", dbgmsg}, 3791 { "rrwlock", ":", 3792 "print rrwlock_t, including readers", rrwlock}, 3793 { "arc_compression_stats", ":[-vabrf]\n" 3794 "\t-v verbose, display a linearly scaled histogram\n" 3795 "\t-a display ARC_anon state statistics individually\n" 3796 "\t-r display ARC_mru state statistics individually\n" 3797 "\t-f display ARC_mfu state statistics individually\n" 3798 "\t-b display histogram of buffer counts\n", 3799 "print a histogram of compressed arc buffer sizes", 3800 arc_compression_stats}, 3801 { NULL } 3802 }; 3803 3804 static const mdb_walker_t walkers[] = { 3805 { "zms_freelist", "walk ZFS metaslab freelist", 3806 freelist_walk_init, freelist_walk_step, NULL }, 3807 { "txg_list", "given any txg_list_t *, walk all entries in all txgs", 3808 txg_list_walk_init, txg_list_walk_step, NULL }, 3809 { "txg_list0", "given any txg_list_t *, walk all entries in txg 0", 3810 txg_list0_walk_init, txg_list_walk_step, NULL }, 3811 { "txg_list1", "given any txg_list_t *, walk all entries in txg 1", 3812 txg_list1_walk_init, txg_list_walk_step, NULL }, 3813 { "txg_list2", "given any txg_list_t *, walk all entries in txg 2", 3814 txg_list2_walk_init, txg_list_walk_step, NULL }, 3815 { "txg_list3", "given any txg_list_t *, walk all entries in txg 3", 3816 txg_list3_walk_init, txg_list_walk_step, NULL }, 3817 { "zio", "walk all zio structures, optionally for a particular spa_t", 3818 zio_walk_init, zio_walk_step, NULL }, 3819 { "zio_root", 3820 "walk all root zio_t structures, optionally for a particular spa_t", 3821 zio_walk_init, zio_walk_root_step, NULL }, 3822 { "spa", "walk all spa_t entries in the namespace", 3823 spa_walk_init, spa_walk_step, NULL }, 3824 { "metaslab", "given a spa_t *, walk all metaslab_t structures", 3825 metaslab_walk_init, metaslab_walk_step, NULL }, 3826 { "multilist", "given a multilist_t *, walk all list_t structures", 3827 multilist_walk_init, multilist_walk_step, NULL }, 3828 { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes", 3829 zfs_acl_node_walk_init, zfs_acl_node_walk_step, NULL }, 3830 { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs", 3831 zfs_acl_node_aces_walk_init, zfs_aces_walk_step, NULL }, 3832 { "zfs_acl_node_aces0", 3833 "given a zfs_acl_node_t, walk all ACEs as ace_t", 3834 zfs_acl_node_aces0_walk_init, zfs_aces_walk_step, NULL }, 3835 { NULL } 3836 }; 3837 3838 static const mdb_modinfo_t modinfo = { 3839 MDB_API_VERSION, dcmds, walkers 3840 }; 3841 3842 const mdb_modinfo_t * 3843 _mdb_init(void) 3844 { 3845 return (&modinfo); 3846 } 3847