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