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