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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/mdb_modapi.h> 27 #include <sys/nsc_thread.h> 28 29 /* needed to maintain identical _sd_bitmap_t sizes */ 30 #define _SD_8K_BLKSIZE 31 #include <sys/nsctl/sd_bcache.h> 32 33 #include <ns/sdbc/sd_io.h> 34 #include <ns/sdbc/sd_ft.h> 35 #include <ns/sdbc/safestore.h> 36 37 /* 38 * initialize cd filter options to this 39 * to differentiate with kernel values in range [-1, sdbc_max_devs] 40 */ 41 #define MDB_CD ((uintptr_t)~1) 42 #define OPT_C_SELECTED (opt_c != MDB_CD) 43 44 /* initialize block filters to this */ 45 #define MDB_BLKNUM ((uintptr_t)~1) 46 #define OPT_B_SELECTED (opt_b != MDB_BLKNUM) 47 48 enum vartype { UINTTYPE = 0, ADDRTYPE, LOCKTYPE, CVTYPE }; 49 50 static void display_var(char *, enum vartype); 51 #ifdef SAFESTORE 52 static void print_wrq(_sd_writeq_t *, uint_t); 53 #endif 54 55 struct walk_info { 56 uintptr_t w_start; 57 uintptr_t w_end; 58 }; 59 60 61 mdb_bitmask_t host_states[] = { 62 { "HOST_NONE", 0xff, _SD_HOST_NONE }, 63 { "HOST_CONFIGURED", 0xff, _SD_HOST_CONFIGURED }, 64 { "HOST_DECONFIGURED", 0xff, _SD_HOST_DECONFIGURED }, 65 { "HOST_NOCACHE", 0xff, _SD_HOST_NOCACHE }, 66 { NULL, 0, 0 } 67 68 }; 69 70 mdb_bitmask_t cache_hints[] = { 71 { "WRTHRU", NSC_WRTHRU, NSC_WRTHRU }, 72 { "FORCED_WRTHRU", NSC_FORCED_WRTHRU, NSC_FORCED_WRTHRU }, 73 { "NOCACHE", NSC_NOCACHE, NSC_NOCACHE }, 74 { "QUEUE", NSC_QUEUE, NSC_QUEUE }, 75 { "RDAHEAD", NSC_RDAHEAD, NSC_RDAHEAD }, 76 { "NO_FORCED_WRTHRU", NSC_NO_FORCED_WRTHRU, NSC_NO_FORCED_WRTHRU }, 77 { "METADATA", NSC_METADATA, NSC_METADATA }, 78 { "SEQ_IO", NSC_SEQ_IO, NSC_SEQ_IO }, 79 { NULL, 0, 0 } 80 81 }; 82 83 84 /* 85 * some cache general dcmds that do not use walkers 86 */ 87 /*ARGSUSED*/ 88 static int 89 sdbc_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 90 { 91 _sd_cache_param_t _sd_cache_config; 92 _sd_net_t _sd_net_config; 93 _sd_ft_info_t _sd_ft_data; 94 uint_t _sd_node_hint; 95 char sdbc_version[17]; 96 97 if (mdb_readvar(sdbc_version, "sdbc_version") == -1) { 98 mdb_warn("failed to read sdbc_version symbol"); 99 } else { 100 sdbc_version[16] = '\0'; /* make sure string is terminated */ 101 mdb_printf("sdbc_version %s\n", sdbc_version); 102 } 103 104 if (mdb_readvar(&_sd_cache_config, "_sd_cache_config") == -1) { 105 mdb_warn("failed to read _sd_cache_config symbol"); 106 } else { 107 108 mdb_printf("SDBC Configuration:\n"); 109 mdb_inc_indent(4); 110 mdb_printf("user magic: %X kernel magic: %X (should match)\n", 111 _SD_MAGIC, _sd_cache_config.magic); 112 mdb_printf( 113 "mirror host: %2d Block size: %4d threads %4d " 114 "write cache: %4dM\n", 115 _sd_cache_config.mirror_host, 116 _sd_cache_config.blk_size, 117 _sd_cache_config.threads, 118 _sd_cache_config.write_cache); 119 mdb_printf("num_handles %4-d cache_mem %4dM prot_lru %d\n", 120 _sd_cache_config.num_handles, 121 _sd_cache_config.cache_mem[0], 122 _sd_cache_config.prot_lru); 123 mdb_printf("gen_pattern %d fill_pattern %?-p num_nodes %d\n", 124 _sd_cache_config.gen_pattern, 125 _sd_cache_config.fill_pattern, 126 _sd_cache_config.num_nodes); 127 mdb_dec_indent(4); 128 } 129 130 if (mdb_readvar(&_sd_net_config, "_sd_net_config") == -1) { 131 mdb_warn("failed to read _sd_net_config symbol"); 132 } else { 133 mdb_inc_indent(4); 134 mdb_printf( 135 "psize %4-d configured %d csize %10-d wsize %10-d cpages %6d\n", 136 _sd_net_config.sn_psize, 137 _sd_net_config.sn_configured, 138 _sd_net_config.sn_csize, 139 _sd_net_config.sn_wsize, 140 _sd_net_config.sn_cpages); 141 142 mdb_dec_indent(4); 143 #ifdef SAFESTORE 144 print_wrq(&(_sd_net_config.sn_wr_queue), FALSE); 145 #endif 146 } 147 148 149 if (mdb_readvar(&_sd_ft_data, "_sd_ft_data") == -1) { 150 mdb_warn("failed to read _sd_ft_data symbol"); 151 152 } else { 153 mdb_printf("FT data:\n"); 154 mdb_inc_indent(4); 155 mdb_printf("crashed %d host_state <%b> numio %d\n", 156 _sd_ft_data.fi_crashed, 157 _sd_ft_data.fi_host_state, host_states, 158 _sd_ft_data.fi_numio); 159 mdb_printf("lock %?-p (owner) rem_sv %h-x sleep %?-p (owner)\n", 160 _sd_ft_data.fi_lock._opaque[0], 161 _sd_ft_data.fi_rem_sv._opaque, 162 _sd_ft_data.fi_sleep._opaque[0]); 163 mdb_dec_indent(4); 164 } 165 166 if (mdb_readvar(&_sd_node_hint, "_sd_node_hint") == -1) { 167 mdb_warn("failed to read _sd_node_hint symbol"); 168 169 } else 170 mdb_printf("Node Hints: %08x <%b>\n", 171 _sd_node_hint, cache_hints); 172 173 display_var("sdbc_wrthru_len", UINTTYPE); 174 display_var("_sd_debug_level", UINTTYPE); 175 display_var("_sdbc_attached", UINTTYPE); 176 177 return (DCMD_OK); 178 } 179 180 static void 181 sdbc_hit_percent(uint_t hits, uint_t misses, char *type) 182 { 183 uint64_t dhits, dmisses; 184 uint64_t hit_rate = 0; 185 186 mdb_printf("%s hits: %u\t %s misses: %u\n", type, hits, type, misses); 187 188 /* a little crude. anything less than 1 percent will show as 0 */ 189 if (hits > 0 || misses > 0) { 190 dhits = (uint64_t)hits; 191 dmisses = (uint64_t)misses; 192 hit_rate = (dhits * 100)/ (dhits + dmisses); 193 mdb_printf("%s hit rate: %lld %%\n", type, hit_rate); 194 } 195 mdb_printf("\n"); 196 } 197 198 /*ARGSUSED*/ 199 static int 200 sdbc_stats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 201 { 202 int i; 203 char *fn; 204 _sd_stats_t *_sd_cache_stats; /* local memory */ 205 uintptr_t _sd_cache_statsp; /* kernel pointer */ 206 _sd_shared_t *sh; 207 int statssize; 208 GElf_Sym sym; 209 int maxdevs; 210 211 if (argc != 0) 212 return (DCMD_USAGE); 213 214 /* get the number of volumes */ 215 if (mdb_readvar(&maxdevs, "sdbc_max_devs") == -1) { 216 mdb_warn("failed to read sdbc_max_devs"); 217 return (DCMD_ERR); 218 } 219 220 statssize = sizeof (_sd_stats_t) + (maxdevs - 1) * 221 sizeof (_sd_shared_t); 222 223 _sd_cache_stats = mdb_zalloc(statssize, UM_SLEEP); 224 225 if (mdb_lookup_by_obj("sdbc", "_sd_cache_stats", &sym) == -1) { 226 mdb_warn("failed to lookup _sd_cache_stats symbol"); 227 return (DCMD_ERR); 228 } 229 230 if (mdb_vread(&_sd_cache_statsp, sizeof (uintptr_t), 231 sym.st_value) == -1) { 232 mdb_warn("failed to read _sd_stats_t pointer"); 233 return (DCMD_ERR); 234 } 235 236 if (mdb_vread(_sd_cache_stats, statssize, _sd_cache_statsp) == -1) { 237 mdb_warn("failed to read _sd_stats_t structure"); 238 return (DCMD_ERR); 239 } 240 241 mdb_printf("Storage Device Block Cache Statistics\n"); 242 mdb_printf("-------------------------------------\n"); 243 244 i = _sd_cache_stats->st_blksize; 245 mdb_printf("Blocksize: 0x%x (%d)\n", i, i); 246 247 mdb_printf("\n"); 248 sdbc_hit_percent(_sd_cache_stats->st_rdhits, _sd_cache_stats->st_rdmiss, 249 "Read"); 250 sdbc_hit_percent(_sd_cache_stats->st_wrhits, _sd_cache_stats->st_wrmiss, 251 "Write"); 252 253 mdb_printf("%3s %10s %8s %8s %8s %8s %8s %7s %4s %4s %s\n", 254 "Cd", "Dev", "Size", 255 "CacheRd", "CacheWr", "DiskRd", "DiskWr", 256 "DirtyBl", "#IO", "Fail", "F"); 257 for (i = 0; i < maxdevs; i++) { 258 sh = &_sd_cache_stats->st_shared[i]; 259 if (!sh->sh_alloc) 260 continue; 261 fn = strrchr(sh->sh_filename, '/'); 262 fn = fn ? fn+1 : sh->sh_filename; 263 mdb_printf("%3d %10s %7d %8d %8d %8d %8d %7d %4d %4d %d\n", 264 sh->sh_cd, fn, sh->sh_filesize, 265 sh->sh_cache_read, sh->sh_cache_write, 266 sh->sh_disk_read, sh->sh_disk_write, 267 sh->sh_numdirty, sh->sh_numio, sh->sh_numfail, 268 sh->sh_failed); 269 } 270 271 mdb_free(_sd_cache_stats, statssize); 272 return (DCMD_OK); 273 } 274 275 /* 276 * display some variables and counters 277 */ 278 static void 279 display_var(char *name, enum vartype type) 280 { 281 uint_t uintval; 282 uintptr_t addrval; 283 kmutex_t lockval; 284 kcondvar_t cvval; 285 286 switch (type) { 287 case UINTTYPE: 288 if (mdb_readvar(&uintval, name) == -1) { 289 mdb_warn("failed to read %s variable", name); 290 } else 291 mdb_printf("%s =\t%8x %12u\n", 292 name, uintval, uintval); 293 break; 294 case ADDRTYPE: 295 if (mdb_readvar(&addrval, name) == -1) { 296 mdb_warn("failed to read %s variable", name); 297 } else 298 mdb_printf("%s =\t%?-p\n", 299 name, addrval); 300 break; 301 case LOCKTYPE: 302 if (mdb_readvar(&lockval, name) == -1) { 303 mdb_warn("failed to read %s lock variable", 304 name); 305 } else 306 mdb_printf("%s =\t%-p (owner)\n", 307 name, lockval._opaque[0]); 308 break; 309 case CVTYPE: 310 if (mdb_readvar(&cvval, name) == -1) { 311 mdb_warn("failed to read %s condvar variable", 312 name); 313 } else 314 mdb_printf("%s = \t%h-x\n", 315 name, cvval._opaque); 316 break; 317 default: 318 mdb_warn("display_var: unknown type"); 319 } 320 } 321 322 mdb_bitmask_t dealloc_flag_vals[] = { 323 { "PROCESS_CACHE_DM", (u_longlong_t)~0, PROCESS_CACHE_DM }, 324 { "CACHE_SHUTDOWN_DM", (u_longlong_t)~0, CACHE_SHUTDOWN_DM }, 325 { "CACHE_THREAD_TERMINATED_DM", 326 (u_longlong_t)~0, CACHE_THREAD_TERMINATED_DM }, 327 { "TIME_DELAY_LVL0", (u_longlong_t)~0, TIME_DELAY_LVL0 }, 328 { "TIME_DELAY_LVL1", (u_longlong_t)~0, TIME_DELAY_LVL1 }, 329 { "TIME_DELAY_LVL2", (u_longlong_t)~0, TIME_DELAY_LVL2 }, 330 { NULL, 0, 0 } 331 }; 332 333 mdb_bitmask_t mdp_bits[] = { 334 { "MONITOR_DYNMEM_PROCESS_DEFAULT", 335 (u_longlong_t)~0, MONITOR_DYNMEM_PROCESS_DEFAULT}, 336 { "RPT_SHUTDOWN_PROCESS_DM", 337 RPT_SHUTDOWN_PROCESS_DM, RPT_SHUTDOWN_PROCESS_DM }, 338 { "RPT_DEALLOC_STATS1_DM", 339 RPT_DEALLOC_STATS1_DM, RPT_DEALLOC_STATS1_DM }, 340 { "RPT_DEALLOC_STATS2_DM", 341 RPT_DEALLOC_STATS2_DM, RPT_DEALLOC_STATS2_DM }, 342 { NULL, 0, 0 } 343 }; 344 345 mdb_bitmask_t process_directive_bits[] = { 346 { "PROCESS_DIRECTIVE_DEFAULT", 347 (u_longlong_t)~0, PROCESS_DIRECTIVE_DEFAULT }, 348 { "WAKE_DEALLOC_THREAD_DM", 349 WAKE_DEALLOC_THREAD_DM, WAKE_DEALLOC_THREAD_DM }, 350 { "MAX_OUT_ACCEL_HIST_FLAG_DM", 351 MAX_OUT_ACCEL_HIST_FLAG_DM, MAX_OUT_ACCEL_HIST_FLAG_DM}, 352 { NULL, 0, 0 } 353 }; 354 355 /*ARGSUSED*/ 356 static int 357 sdbc_vars(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 358 { 359 int sd_dealloc_flag_dm; 360 _dm_process_vars_t dynmem_processing_dm; 361 362 if (argc != 0) 363 return (DCMD_USAGE); 364 365 mdb_printf("counters and other variables:\n"); 366 mdb_inc_indent(4); 367 368 display_var("xmem_inval_hit", UINTTYPE); 369 display_var("xmem_inval_miss", UINTTYPE); 370 display_var("xmem_inval_inuse", UINTTYPE); 371 372 display_var("sdbc_allocb_pageio1", UINTTYPE); 373 display_var("sdbc_allocb_pageio2", UINTTYPE); 374 display_var("sdbc_allocb_inuse", UINTTYPE); 375 display_var("sdbc_allocb_hit", UINTTYPE); 376 display_var("sdbc_allocb_lost", UINTTYPE); 377 display_var("sdbc_pageio_always", UINTTYPE); 378 display_var("sdbc_do_page", UINTTYPE); 379 display_var("sdbc_flush_pageio", UINTTYPE); 380 381 display_var("sdbc_centry_hit", UINTTYPE); 382 display_var("sdbc_centry_inuse", UINTTYPE); 383 display_var("sdbc_centry_lost", UINTTYPE); 384 display_var("sdbc_centry_deallocd", UINTTYPE); 385 386 display_var("_sd_prefetch_opt", UINTTYPE); 387 388 display_var("sdbc_ra_hash", UINTTYPE); 389 display_var("sdbc_ra_none", UINTTYPE); 390 391 display_var("sdbc_static_cache", UINTTYPE); 392 display_var("sdbc_use_dmchain", UINTTYPE); 393 394 /* in no particular order ... */ 395 display_var("sdbc_check_cot", UINTTYPE); 396 display_var("_sd_cctl_groupsz", UINTTYPE); 397 display_var("CBLOCKS", UINTTYPE); 398 display_var("_SD_SELF_HOST", UINTTYPE); 399 display_var("_SD_MIRROR_HOST", UINTTYPE); 400 display_var("sdbc_bio_count", UINTTYPE); 401 display_var("_sd_cblock_shift", UINTTYPE); 402 display_var("_sd_nodes_configured", UINTTYPE); 403 display_var("nv_alloc_factor", UINTTYPE); 404 display_var("_sd_ft_exit", UINTTYPE); 405 display_var("_sd_flush_exit", UINTTYPE); 406 display_var("_sd_node_recovery", UINTTYPE); 407 display_var("_sd_async_recovery", UINTTYPE); 408 display_var("_sdbc_ft_hold_io", UINTTYPE); 409 display_var("mirror_clean_shutdown", UINTTYPE); 410 display_var("_sd_ft_warm_start", UINTTYPE); 411 mdb_dec_indent(4); 412 mdb_printf("\n"); 413 414 /* some addresses of various lists and tables */ 415 mdb_printf("Addresses:\n"); 416 mdb_inc_indent(4); 417 display_var("_sd_htable", ADDRTYPE); 418 display_var("_sdbc_gl_centry_info", ADDRTYPE); 419 display_var("_sdbc_gl_centry_info_nvmem", ADDRTYPE); 420 display_var("_sdbc_gl_centry_info_size", ADDRTYPE); /* size_t */ 421 display_var("_sdbc_gl_file_info", ADDRTYPE); 422 display_var("_sdbc_gl_file_info_size", ADDRTYPE); /* size_t */ 423 mdb_dec_indent(4); 424 mdb_printf("\n"); 425 426 /* dynamic memory variables */ 427 mdb_printf("Dynamic Memory variables and stats:\n"); 428 mdb_inc_indent(4); 429 display_var("_sdbc_memtype_deconfigure_delayed", UINTTYPE); 430 431 if (mdb_readvar(&sd_dealloc_flag_dm, "sd_dealloc_flag_dm") == -1) { 432 mdb_warn("failed to read sd_dealloc_flag_dm symbol"); 433 } else 434 mdb_printf("sd_dealloc_flag_dm %08x <%b>\n", 435 sd_dealloc_flag_dm, 436 sd_dealloc_flag_dm, dealloc_flag_vals); 437 438 if (mdb_readvar(&dynmem_processing_dm, "dynmem_processing_dm") == -1) { 439 mdb_warn("failed to read dynmem_processing_dm structure"); 440 } else { 441 _dm_process_vars_t *dp; 442 443 dp = &dynmem_processing_dm; 444 445 mdb_printf( 446 "thread_dm_cv %h-x thread_dm_lock %?-p (owner)\n", 447 dp->thread_dm_cv._opaque, 448 dp->thread_dm_lock._opaque[0]); 449 450 mdb_printf("sd_dealloc_flagx %x %8Tmax_dyn_list %3-d\n", 451 dp->sd_dealloc_flagx, 452 dp->max_dyn_list); 453 454 mdb_printf("monitor_dynmem_process <%b>\n", 455 dp->monitor_dynmem_process, mdp_bits); 456 457 mdb_printf( 458 "cache_aging_ct1 %3-d %8Tcache_aging_ct2 %3-d cache_aging_ct3 %3-d\n", 459 dp->cache_aging_ct1, 460 dp->cache_aging_ct2, 461 dp->cache_aging_ct3); 462 463 mdb_printf( 464 "cache_aging_sec1 %3-d %8Tcache_aging_sec2 %3-d" 465 " cache_aging_sec3 %3-d\n", 466 dp->cache_aging_sec1, 467 dp->cache_aging_sec2, 468 dp->cache_aging_sec3); 469 470 mdb_printf("cache_aging_pcnt1 %3-d %8Tcache_aging_pcnt2 %3-d\n", 471 dp->cache_aging_pcnt1, 472 dp->cache_aging_pcnt2); 473 474 mdb_printf( 475 "max_holds_pcnt %3-d %8Talloc_ct %8-d dealloc_ct %8-d\n", 476 dp->max_holds_pcnt, 477 dp->alloc_ct, 478 dp->dealloc_ct); 479 480 mdb_printf( 481 "history %4x %8Tnodatas %8-d notavail %8-d candidates %8-d\n", 482 dp->history, 483 dp->nodatas, 484 dp->notavail, 485 dp->candidates); 486 487 mdb_printf( 488 "deallocs %8-d %8Thosts %8-d pests %8-d metas %8-d\n", 489 dp->deallocs, 490 dp->hosts, 491 dp->pests, 492 dp->metas); 493 494 mdb_printf("holds %8-d %8Tothers %8-d\n", 495 dp->holds, 496 dp->others); 497 498 mdb_printf("process_directive <%b>\n", 499 dp->process_directive, process_directive_bits); 500 501 mdb_printf("read_hits %8-d %8Tread_misses %8-d\n", 502 dp->read_hits, 503 dp->read_misses); 504 505 mdb_printf( 506 "write_thru %8-d %8Twrite_hits %8-d write_misses %8-d\n", 507 dp->write_hits, 508 dp->write_misses, 509 dp->write_thru); 510 511 mdb_printf("prefetch_hits %8-d prefetch_misses %8-d\n", 512 dp->prefetch_hits, 513 dp->prefetch_misses); 514 } 515 mdb_dec_indent(4); 516 mdb_printf("\n"); 517 518 /* some locks and condition variables */ 519 mdb_printf("Locks:\n"); 520 mdb_inc_indent(4); 521 display_var("mutex_and_condvar_flag", UINTTYPE); 522 display_var("_sd_cache_lock", LOCKTYPE); 523 display_var("_sd_block_lk", LOCKTYPE); 524 display_var("_sdbc_config_lock", LOCKTYPE); 525 display_var("_sdbc_ft_hold_io_lk", LOCKTYPE); 526 display_var("_sd_flush_cv", CVTYPE); 527 display_var("_sdbc_ft_hold_io_cv", CVTYPE); 528 mdb_dec_indent(4); 529 mdb_printf("\n"); 530 531 return (DCMD_OK); 532 } 533 534 const mdb_bitmask_t nsc_buf_bits[] = { 535 {"HALLOCATED", NSC_HALLOCATED, NSC_HALLOCATED}, 536 {"HACTIVE", NSC_HACTIVE, NSC_HACTIVE}, 537 {"RDBUF", NSC_RDBUF, NSC_RDBUF}, 538 {"WRBUF", NSC_WRBUF, NSC_WRBUF}, 539 {"NOBLOCK", NSC_NOBLOCK, NSC_NOBLOCK}, 540 {"WRTHRU", NSC_WRTHRU, NSC_WRTHRU}, 541 {"NOCACHE", NSC_NOCACHE, NSC_NOCACHE}, 542 {"BCOPY", NSC_BCOPY, NSC_BCOPY}, 543 {"PAGEIO", NSC_PAGEIO, NSC_PAGEIO}, 544 {"PINNABLE", NSC_PINNABLE, NSC_PINNABLE}, 545 {"FORCED_WRTHRU", NSC_FORCED_WRTHRU, NSC_FORCED_WRTHRU}, 546 {"METADATA", NSC_METADATA, NSC_METADATA}, 547 {"MIXED", NSC_MIXED, NSC_MIXED}, 548 {NULL, 0, 0} 549 }; 550 551 552 /* 553 * HELP functions for cache ctl type dcmds 554 */ 555 556 static void 557 cctl_help_common(char *name) 558 { 559 mdb_inc_indent(4); 560 mdb_printf("-c cd displays cctls for cache descriptor 'cd'\n"); 561 mdb_dec_indent(4); 562 mdb_printf("inclusive filters:\n"); 563 mdb_inc_indent(4); 564 mdb_printf("-b blk displays cctls for cache block number 'blk'\n"); 565 mdb_printf("-d displays cctls with dirty bits\n"); 566 mdb_printf("-h displays cctls that are hashed\n"); 567 mdb_printf("-i displays cctls that are inuse\n"); 568 mdb_printf("-o displays cctls that have I/O in progress\n"); 569 mdb_printf("-p displays cctls that have pagio set\n"); 570 mdb_printf("-B displays cctls that are marked BAD\n"); 571 mdb_printf("-H displays cctls that are HOSTS\n"); 572 mdb_printf("-P displays cctls that are PARASITES\n"); 573 mdb_printf("-R displays cctls that are explicit (NSC_RDAHEAD) " 574 "Prefetch bufs\n"); 575 mdb_printf("-r displays cctls that are implicit Prefetch bufs\n"); 576 mdb_printf("-V displays cctls that have valid bits set\n"); 577 mdb_printf("-v verbose\n"); 578 mdb_dec_indent(4); 579 580 mdb_printf("Default: %s displays all cctls in the list\n", name); 581 mdb_printf("\n"); 582 583 mdb_printf("Example:\n"); 584 mdb_inc_indent(4); 585 586 mdb_printf("%s -io -c 5 displays all cctls for cd 5 that are\n" 587 "in use or have I/O in progress\n", name); 588 mdb_dec_indent(4); 589 } 590 591 #define CCTL_OPTIONSTRING "[-vdhiopBHPV][-c cd][-b blknum]" 592 void 593 cctl_help() 594 { 595 mdb_printf("sdbc_cctl displays cache ctl structures\n"); 596 mdb_printf("Usage: [address]::sdbc_cctl " CCTL_OPTIONSTRING "\n"); 597 cctl_help_common("sdbc_cctl"); 598 } 599 600 void 601 cchain_help() 602 { 603 mdb_printf("sdbc_cchain displays cache ctl structures in a" 604 " (alloc) cc_chain\n"); 605 mdb_printf("Usage: address::sdbc_cchain " CCTL_OPTIONSTRING "\n"); 606 cctl_help_common("sdbc_cchain"); 607 } 608 609 void 610 dchain_help() 611 { 612 mdb_printf("sdbc_dchain displays cache ctl structures in a" 613 " dirty chain\n"); 614 mdb_printf("Usage: address::sdbc_dchain " CCTL_OPTIONSTRING "\n"); 615 cctl_help_common("sdbc_dchain"); 616 } 617 618 void 619 dmchain_help() 620 { 621 mdb_printf("sdbc_dmchain displays cache ctl structures in a" 622 " dynamic memory allocation chain\n"); 623 mdb_printf("order of display is:\n" 624 "the cctl represented by the given address,\n" 625 "the cc_head_dm cctl,\n" 626 "the chain starting at cc_next_dm of the head cctl\n"); 627 mdb_printf("Usage: address::sdbc_dmchain " CCTL_OPTIONSTRING "\n"); 628 cctl_help_common("sdbc_dmchain"); 629 } 630 631 void 632 hashchain_help() 633 { 634 mdb_printf("sdbc_hashchain displays cache ctl structures in a" 635 " hash chain\n"); 636 mdb_printf("Usage: address::sdbc_hashchain " CCTL_OPTIONSTRING "\n"); 637 cctl_help_common("sdbc_hashchain"); 638 } 639 640 void 641 hashtable_help() 642 { 643 mdb_printf("sdbc_hashtable displays the hash table and its chains\n"); 644 mdb_printf("Usage: address::sdbc_hashtable " CCTL_OPTIONSTRING "\n"); 645 cctl_help_common("sdbc_hashtable"); 646 } 647 648 649 void 650 lru_help() 651 { 652 mdb_printf("sdbc_lru displays cache ctl structures in the LRU queue\n"); 653 mdb_printf("Usage: [address]::sdbc_lru " CCTL_OPTIONSTRING "\n"); 654 cctl_help_common("sdbc_lru"); 655 } 656 657 /* 658 * help functions for write ctl dcmds 659 */ 660 void 661 wctl_help_common(char *name) 662 { 663 mdb_inc_indent(4); 664 mdb_printf("-v verbose\n"); 665 mdb_printf("-c cd show ctl structs for cache descriptor 'cd'\n"); 666 mdb_printf("-d show ctl structs that have dirty bits set\n"); 667 mdb_dec_indent(4); 668 mdb_printf("Default: %s displays all write ctl in the list\n", name); 669 } 670 671 void 672 wctl_help() 673 { 674 mdb_printf( 675 "sdbc_wctl displays the allocated array of write ctl structures\n"); 676 mdb_printf("Usage: [address]::sdbc_wctl [-vd][-c cd]\n"); 677 wctl_help_common("sdbc_wctl"); 678 } 679 680 void 681 wrq_help() 682 { 683 mdb_printf("sdbc_wrq displays the write ctl queue (wctl free list)\n"); 684 mdb_printf("Usage: [address]::sdbc_wrq [-vd][-c cd]\n"); 685 wctl_help_common("sdbc_wrq"); 686 } 687 688 /* help function for the sdbc_cdinfo dcmd */ 689 void 690 cdinfo_help() 691 { 692 mdb_printf( 693 "sdbc_cdinfo displays cd information from the _sd_cache_files table\n"); 694 mdb_printf("Usage: [address]::sdbc_cdfinfo [-av][-c cd]\n"); 695 mdb_inc_indent(4); 696 mdb_printf("-a displays info for all cd_info structures\n"); 697 mdb_printf("-c cd displays info for cache descriptor 'cd'\n"); 698 mdb_printf("-v verbose\n"); 699 mdb_dec_indent(4); 700 mdb_printf("Default: display info for cd's that are allocated\n"); 701 } 702 703 void 704 ftctl_help() 705 { 706 mdb_printf( 707 "sdbc_ftctl displays the array of fault tolerant structures \n"); 708 mdb_printf("Usage: [address]::sdbc_ftctl [-vd][-c cd]\n"); 709 wctl_help_common("sdbc_ftctl"); 710 } 711 712 /* 713 * help function for the sdbc_handles dcmd 714 */ 715 void 716 handle_help() 717 { 718 mdb_printf("sdbc_handles displays active or allocated" 719 " cache buffer handles\n"); 720 mdb_printf("Usage: [address]::sdbc_handles [-avC][-c cd]\n"); 721 mdb_inc_indent(4); 722 mdb_printf("-a displays all handles\n"); 723 mdb_printf("-c n displays handle for cd n\n"); 724 mdb_printf("-v displays detailed handle data\n"); 725 mdb_printf("-C displays the handle cc_chain\n"); 726 mdb_dec_indent(4); 727 mdb_printf("Default: display only allocated or active handles\n"); 728 } 729 730 /* 731 * help functions for the "global" memory dcmds 732 */ 733 void 734 glcinfo_help() 735 { 736 mdb_printf("sdbc_glcinfo displays the global cache entry info\n"); 737 mdb_printf("Usage: [address]::sdbc_glcinfo [-adC][-c cd][-b fbapos]\n"); 738 mdb_inc_indent(4); 739 mdb_printf("-a displays all global info structs\n"); 740 mdb_printf("-b fbapos displays structs that match FBA block" 741 "(not cache block) 'fbapos'\n"); 742 mdb_printf("-c cd displays structs that match cache descriptor 'cd'\n"); 743 mdb_printf("-d displays structs with dirty bits set\n"); 744 mdb_printf("-C does consistency check against nvram copy\n"); 745 mdb_dec_indent(4); 746 mdb_printf("Default: display entries with a valid cd\n"); 747 } 748 749 void 750 glfinfo_help() 751 { 752 mdb_printf("sdbc_glfinfo displays the global file info\n"); 753 mdb_printf("Usage: [address]::sdbc_glfinfo [-aptC]\n"); 754 mdb_inc_indent(4); 755 mdb_printf("-a displays all global info structs\n"); 756 mdb_printf("-p displays structs for pinned volumes\n"); 757 mdb_printf("-t displays structs for attached volumes\n"); 758 mdb_printf("-C does consistency check against nvram copy\n"); 759 mdb_dec_indent(4); 760 mdb_printf("Default: display entries with non-null filename\n"); 761 } 762 763 764 /* 765 * WALKERS 766 */ 767 768 /* 769 * walker for the cctl list using the cc_link_list_dm pointers 770 */ 771 static int 772 sdbc_cctl_winit(mdb_walk_state_t *wsp) 773 { 774 _sd_cctl_t *_sd_cctl[_SD_CCTL_GROUPS]; /* for getting first entry */ 775 struct walk_info *winfo; 776 777 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 778 779 if (wsp->walk_addr == NULL) { 780 /* 781 * we get the "first" cctl from memory and then traverse 782 * the cc_link_list_dm pointers. 783 * this traversal could start from any cctl. here we start with 784 * the first cctl in the _sd_cctl[] array. 785 */ 786 if (mdb_readvar(_sd_cctl, "_sd_cctl") == -1) { 787 mdb_warn("failed to read _sd_cctl array"); 788 return (DCMD_ERR); 789 } 790 791 wsp->walk_addr = (uintptr_t)_sd_cctl[0]; 792 } 793 794 winfo->w_start = 0; 795 winfo->w_end = wsp->walk_addr; 796 wsp->walk_data = winfo; 797 798 return (WALK_NEXT); 799 } 800 801 static int 802 sdbc_cctl_wstep(mdb_walk_state_t *wsp) 803 { 804 struct walk_info *winfo = wsp->walk_data; 805 _sd_cctl_t centry; 806 int status; 807 808 if (wsp->walk_addr == NULL) /* should not happen */ 809 return (WALK_DONE); 810 811 /* 812 * w_start is 0 on the first iteration so the test 813 * will fail, allowing the first centry to be processed 814 */ 815 if (wsp->walk_addr == winfo->w_start) 816 return (WALK_DONE); 817 818 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 819 wsp->walk_cbdata); 820 821 if (mdb_vread(¢ry, sizeof (_sd_cctl_t), wsp->walk_addr) == -1) { 822 mdb_warn("failed to read centry at %p", wsp->walk_addr); 823 return (WALK_ERR); 824 } 825 wsp->walk_addr = (uintptr_t)(centry.cc_link_list_dm); 826 /* set termination condition. only needs to be done once */ 827 winfo->w_start = winfo->w_end; 828 829 return (status); 830 } 831 832 static void 833 sdbc_cctl_wfini(mdb_walk_state_t *wsp) 834 { 835 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 836 } 837 838 /* 839 * walk the cc_chain list of a _sd_cctl_t 840 * no global walks -- must be called with an address 841 */ 842 static int 843 sdbc_cchain_winit(mdb_walk_state_t *wsp) 844 { 845 if (wsp->walk_addr == NULL) 846 return (WALK_ERR); 847 848 wsp->walk_data = mdb_zalloc(sizeof (_sd_cctl_t), UM_SLEEP); 849 850 return (WALK_NEXT); 851 } 852 853 static int 854 sdbc_cchain_wstep(mdb_walk_state_t *wsp) 855 { 856 int status; 857 858 if (wsp->walk_addr == NULL) 859 return (WALK_DONE); 860 861 if (mdb_vread(wsp->walk_data, sizeof (_sd_cctl_t), wsp->walk_addr) 862 == -1) { 863 mdb_warn("sdbc_cchain_wstep failed to read centry at %p", 864 wsp->walk_addr); 865 return (WALK_ERR); 866 } 867 868 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 869 wsp->walk_cbdata); 870 871 wsp->walk_addr = (uintptr_t)(((_sd_cctl_t *) 872 (wsp->walk_data))->cc_chain); 873 return (status); 874 } 875 876 static void 877 sdbc_cchain_wfini(mdb_walk_state_t *wsp) 878 { 879 mdb_free(wsp->walk_data, sizeof (_sd_cctl_t)); 880 } 881 882 883 /* 884 * walk the dirty chain list of a _sd_cctl_t 885 * no global walks -- must be called with an address 886 */ 887 static int 888 sdbc_dchain_winit(mdb_walk_state_t *wsp) 889 { 890 if (wsp->walk_addr == NULL) 891 return (WALK_ERR); 892 893 wsp->walk_data = mdb_zalloc(sizeof (_sd_cctl_t), UM_SLEEP); 894 895 /* walk data stores the first and subsequent cc_dirty_link */ 896 if (mdb_vread(wsp->walk_data, sizeof (_sd_cctl_t), wsp->walk_addr) 897 == -1) { 898 mdb_warn("sdbc_dchain_winit failed to read centry at %p", 899 wsp->walk_addr); 900 return (WALK_ERR); 901 } 902 903 return (WALK_NEXT); 904 } 905 906 static int 907 sdbc_dchain_wstep(mdb_walk_state_t *wsp) 908 { 909 _sd_cctl_t centry; 910 int status; 911 912 if (wsp->walk_addr == NULL) 913 return (WALK_DONE); 914 915 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 916 wsp->walk_cbdata); 917 918 919 if (mdb_vread(¢ry, sizeof (_sd_cctl_t), wsp->walk_addr) 920 == -1) { 921 mdb_warn("sdbc_dchain_wstep failed to read centry at %p", 922 wsp->walk_addr); 923 return (WALK_ERR); 924 } 925 926 wsp->walk_addr = 927 (uintptr_t)(centry.cc_dirty_next); 928 929 /* end of dirty_next chain? start on subsequent dirty_link */ 930 if (wsp->walk_addr == NULL) { 931 wsp->walk_addr = 932 (uintptr_t)(((_sd_cctl_t *)(wsp->walk_data))->cc_dirty_link); 933 934 /* update dirty link */ 935 /* walk data stores the first and subsequent cc_dirty_link */ 936 if (wsp->walk_addr) { 937 if (mdb_vread(wsp->walk_data, sizeof (_sd_cctl_t), 938 wsp->walk_addr) == -1) { 939 940 mdb_warn( 941 "sdbc_dchain_wstep failed to read centry at %p", 942 wsp->walk_addr); 943 944 return (WALK_ERR); 945 } 946 } 947 } 948 949 return (status); 950 } 951 952 static void 953 sdbc_dchain_wfini(mdb_walk_state_t *wsp) 954 { 955 mdb_free(wsp->walk_data, sizeof (_sd_cctl_t)); 956 } 957 958 /* for stepping thru the dynmem chain */ 959 #define GET_HEAD_DM 0x1 960 #define GET_NEXT_DM 0x2 961 962 /* 963 * walk the dm chain of a cctl 964 * start with current address, then cc_head_dm, then the cc_next_dm chain 965 */ 966 static int 967 sdbc_dmchain_winit(mdb_walk_state_t *wsp) 968 { 969 if (wsp->walk_addr == NULL) 970 return (WALK_ERR); 971 972 wsp->walk_data = (void *)GET_HEAD_DM; 973 974 return (WALK_NEXT); 975 } 976 977 static int 978 sdbc_dmchain_wstep(mdb_walk_state_t *wsp) 979 { 980 _sd_cctl_t centry; 981 int status; 982 983 if (wsp->walk_addr == NULL) 984 return (WALK_DONE); 985 986 if (mdb_vread(¢ry, sizeof (_sd_cctl_t), wsp->walk_addr) 987 == -1) { 988 mdb_warn("sdbc_dmchain_wstep failed to read centry at %p", 989 wsp->walk_addr); 990 return (WALK_ERR); 991 } 992 993 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 994 wsp->walk_cbdata); 995 996 if (wsp->walk_data == (void *)GET_HEAD_DM) { 997 wsp->walk_addr = (uintptr_t)centry.cc_head_dm; 998 wsp->walk_data = (void *)GET_NEXT_DM; 999 } else 1000 wsp->walk_addr = (uintptr_t)centry.cc_next_dm; 1001 1002 return (status); 1003 } 1004 1005 /*ARGSUSED*/ 1006 static void 1007 sdbc_dmchain_wfini(mdb_walk_state_t *wsp) 1008 { 1009 } 1010 1011 /* 1012 * walk a hash chain 1013 * requires an address 1014 */ 1015 /*ARGSUSED*/ 1016 static int 1017 sdbc_hashchain_winit(mdb_walk_state_t *wsp) 1018 { 1019 1020 if (wsp->walk_addr == NULL) 1021 return (WALK_ERR); 1022 1023 1024 return (WALK_NEXT); 1025 } 1026 1027 static int 1028 sdbc_hashchain_wstep(mdb_walk_state_t *wsp) 1029 { 1030 int status; 1031 _sd_hash_hd_t hash_entry; 1032 1033 1034 if (wsp->walk_addr == NULL) 1035 return (WALK_DONE); 1036 1037 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1038 wsp->walk_cbdata); 1039 1040 if (mdb_vread(&hash_entry, sizeof (_sd_hash_hd_t), 1041 wsp->walk_addr) == -1) { 1042 mdb_warn( 1043 "sdbc_hashchain_wstep failed to read hash_entry at %p", 1044 wsp->walk_addr); 1045 return (WALK_ERR); /* will upper layer continue ? */ 1046 } 1047 1048 wsp->walk_addr = (uintptr_t)hash_entry.hh_next; 1049 1050 return (status); 1051 } 1052 1053 /*ARGSUSED*/ 1054 static void 1055 sdbc_hashchain_wfini(mdb_walk_state_t *wsp) 1056 { 1057 } 1058 1059 /* 1060 * walk the sdbc lru list 1061 */ 1062 static int 1063 sdbc_lru_winit(mdb_walk_state_t *wsp) 1064 { 1065 struct walk_info *winfo; 1066 GElf_Sym sym; 1067 1068 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1069 1070 /* if called without an address, start at the head of the queue */ 1071 if (wsp->walk_addr == NULL) { 1072 1073 if (mdb_lookup_by_obj("sdbc", "_sd_lru_q", &sym) == -1) { 1074 mdb_warn("failed to lookup _sd_lru_q symbol"); 1075 return (WALK_ERR); 1076 } 1077 1078 /* &(_sd_lru_q.sq_qhead) */ 1079 wsp->walk_addr = (uintptr_t)(sym.st_value); 1080 } 1081 1082 winfo->w_start = 0; 1083 winfo->w_end = wsp->walk_addr; 1084 wsp->walk_data = winfo; 1085 1086 return (WALK_NEXT); 1087 } 1088 1089 static int 1090 sdbc_lru_wstep(mdb_walk_state_t *wsp) 1091 { 1092 struct walk_info *winfo = wsp->walk_data; 1093 _sd_cctl_t centry; 1094 int status; 1095 1096 if (wsp->walk_addr == NULL) /* should not happen */ 1097 return (WALK_DONE); 1098 1099 /* 1100 * w_start is 0 on the first iteration so the test 1101 * will fail, allowing the first centry to be processed 1102 */ 1103 if (wsp->walk_addr == winfo->w_start) 1104 return (WALK_DONE); 1105 1106 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1107 wsp->walk_cbdata); 1108 1109 if (mdb_vread(¢ry, sizeof (_sd_cctl_t), wsp->walk_addr) == -1) { 1110 mdb_warn("failed to read centry at %p", wsp->walk_addr); 1111 return (WALK_ERR); 1112 } 1113 wsp->walk_addr = (uintptr_t)(centry.cc_next); 1114 1115 /* set termination condition. only needs to be done once */ 1116 winfo->w_start = winfo->w_end; 1117 1118 return (status); 1119 } 1120 1121 static void 1122 sdbc_lru_wfini(mdb_walk_state_t *wsp) 1123 { 1124 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1125 } 1126 1127 1128 #ifdef SAFESTORE 1129 /* 1130 * walk the array of allocated write control structures 1131 */ 1132 1133 static int 1134 sdbc_wctl_winit(mdb_walk_state_t *wsp) 1135 { 1136 _sd_net_t _sd_net_config; 1137 _sd_writeq_t wrq; 1138 struct walk_info *winfo; 1139 int blk_shft; 1140 int count; 1141 1142 1143 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1144 1145 /* need to calculate the end of the array */ 1146 if (mdb_readvar(&_sd_net_config, "_sd_net_config") == -1) { 1147 mdb_warn("failed to read _sd_net_config structure"); 1148 return (WALK_ERR); 1149 } 1150 1151 if (wsp->walk_addr == NULL) 1152 wsp->walk_addr = (uintptr_t)(_sd_net_config.sn_wr_cctl); 1153 1154 /* 1155 * this module assumes 8k block size so this code can 1156 * be commented out if necessary. 1157 */ 1158 if (mdb_readvar(&blk_shft, "_sd_cblock_shift") == -1) { 1159 mdb_warn("failed to read _sd_cblock_shift." 1160 "assuming 8k cache block size"); 1161 blk_shft = 13; 1162 } 1163 1164 count = (_sd_net_config.sn_wpages * _sd_net_config.sn_psize) / 1165 (1 << blk_shft); 1166 1167 winfo->w_end = (uintptr_t)(_sd_net_config.sn_wr_cctl + count); 1168 wsp->walk_data = winfo; 1169 1170 return (WALK_NEXT); 1171 } 1172 1173 static int 1174 sdbc_wctl_wstep(mdb_walk_state_t *wsp) 1175 { 1176 struct walk_info *winfo = wsp->walk_data; 1177 int status; 1178 1179 if (wsp->walk_addr == NULL) 1180 return (WALK_DONE); 1181 1182 if (wsp->walk_addr >= winfo->w_end) 1183 return (WALK_DONE); 1184 1185 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1186 wsp->walk_cbdata); 1187 1188 wsp->walk_addr += sizeof (_sd_wr_cctl_t); 1189 1190 return (status); 1191 1192 } 1193 1194 static void 1195 sdbc_wctl_wfini(mdb_walk_state_t *wsp) 1196 { 1197 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1198 } 1199 1200 /* 1201 * walk the queue (free list) of write control structures 1202 */ 1203 1204 static int 1205 sdbc_wrq_winit(mdb_walk_state_t *wsp) 1206 { 1207 _sd_net_t _sd_net_config; 1208 _sd_writeq_t wrq; 1209 1210 /* if called without an address, start at the head of the queue */ 1211 if (wsp->walk_addr == NULL) { 1212 1213 if (mdb_readvar(&_sd_net_config, "_sd_net_config") == -1) { 1214 mdb_warn("failed to read _sd_net_config structure"); 1215 return (WALK_ERR); 1216 } 1217 1218 wsp->walk_addr = (uintptr_t) 1219 (_sd_net_config.sn_wr_queue.wq_qtop); 1220 } 1221 1222 return (WALK_NEXT); 1223 } 1224 1225 static int 1226 sdbc_wrq_wstep(mdb_walk_state_t *wsp) 1227 { 1228 _sd_wr_cctl_t wctl; 1229 int status; 1230 1231 if (wsp->walk_addr == NULL) 1232 return (WALK_DONE); 1233 1234 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1235 wsp->walk_cbdata); 1236 1237 if (mdb_vread(&wctl, sizeof (_sd_wr_cctl_t), wsp->walk_addr) 1238 == -1) { 1239 mdb_warn("sdbc_cchain_wstep failed to read wctl at %p", 1240 wsp->walk_addr); 1241 return (WALK_ERR); 1242 } 1243 1244 /* special case -- mini-DSP fake wr_cctl */ 1245 if (wsp->walk_addr == (uintptr_t)wctl.wc_next) 1246 return (WALK_DONE); 1247 1248 wsp->walk_addr = (uintptr_t)(wctl.wc_next); 1249 1250 return (WALK_NEXT); 1251 } 1252 1253 static void 1254 sdbc_wrq_wfini(mdb_walk_state_t *wsp) 1255 { 1256 } 1257 #endif /* SAFESTORE */ 1258 /* 1259 * walk the _sd_cache_files array of cd_info structures 1260 */ 1261 static int 1262 sdbc_cdinfo_winit(mdb_walk_state_t *wsp) 1263 { 1264 struct walk_info *winfo; 1265 _sd_cd_info_t *_sd_cache_files_addr; 1266 int maxdevs; 1267 1268 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1269 1270 1271 /* get the address of the cdinfo table */ 1272 if (mdb_readvar(&_sd_cache_files_addr, "_sd_cache_files") == -1) { 1273 mdb_warn("failed to read _sd_cache_files address\n"); 1274 return (WALK_ERR); 1275 } 1276 1277 /* if called without an address, start at the head of the queue */ 1278 if (wsp->walk_addr == NULL) { 1279 /* address of first _sd_cd_info_t */ 1280 wsp->walk_addr = (uintptr_t)(_sd_cache_files_addr); 1281 } 1282 1283 /* get the number of volumes */ 1284 if (mdb_readvar(&maxdevs, "sdbc_max_devs") == -1) { 1285 mdb_warn("failed to read sdbc_max_devs"); 1286 return (WALK_ERR); 1287 } 1288 1289 winfo->w_end = (uintptr_t)(_sd_cache_files_addr + maxdevs); 1290 wsp->walk_data = winfo; 1291 1292 return (WALK_NEXT); 1293 } 1294 1295 static int 1296 sdbc_cdinfo_wstep(mdb_walk_state_t *wsp) 1297 { 1298 struct walk_info *winfo = wsp->walk_data; 1299 int status; 1300 1301 if (wsp->walk_addr >= winfo->w_end) 1302 return (WALK_DONE); 1303 1304 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1305 wsp->walk_cbdata); 1306 1307 wsp->walk_addr += sizeof (_sd_cd_info_t); 1308 1309 return (status); 1310 } 1311 1312 static void 1313 sdbc_cdinfo_wfini(mdb_walk_state_t *wsp) 1314 { 1315 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1316 } 1317 1318 #ifdef SAFESTORE 1319 /* 1320 * walk the array of allocated fault tolerant control structures 1321 */ 1322 static int 1323 sdbc_ftctl_winit(mdb_walk_state_t *wsp) 1324 { 1325 _sd_net_t _sd_net_config; 1326 struct walk_info *winfo; 1327 int blk_shft = 13; /* 8k default */ 1328 int count; 1329 1330 1331 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1332 1333 /* need to calculate the end of the array */ 1334 if (mdb_readvar(&_sd_net_config, "_sd_net_config") == -1) { 1335 mdb_warn("failed to read _sd_net_config structure"); 1336 return (WALK_ERR); 1337 } 1338 1339 if (wsp->walk_addr == NULL) 1340 wsp->walk_addr = (uintptr_t)(_sd_net_config.sn_ft_cctl); 1341 1342 /* 1343 * this module assumes 8k block size so this code can 1344 * be commented out if necessary. 1345 */ 1346 if (mdb_readvar(&blk_shft, "_sd_cblock_shift") == -1) { 1347 mdb_warn("failed to read _sd_cblock_shift." 1348 "assuming 8k cache block size"); 1349 blk_shft = 13; 1350 } 1351 1352 count = (_sd_net_config.sn_wpages * _sd_net_config.sn_psize) / 1353 (1 << blk_shft); 1354 1355 winfo->w_end = (uintptr_t)(_sd_net_config.sn_ft_cctl + count); 1356 wsp->walk_data = winfo; 1357 1358 return (WALK_NEXT); 1359 } 1360 1361 static int 1362 sdbc_ftctl_wstep(mdb_walk_state_t *wsp) 1363 { 1364 struct walk_info *winfo = wsp->walk_data; 1365 int status; 1366 1367 if (wsp->walk_addr == NULL) 1368 return (WALK_DONE); 1369 1370 if (wsp->walk_addr >= winfo->w_end) 1371 return (WALK_DONE); 1372 1373 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1374 wsp->walk_cbdata); 1375 1376 wsp->walk_addr += sizeof (_sd_ft_cctl_t); 1377 1378 return (status); 1379 } 1380 1381 static void 1382 sdbc_ftctl_wfini(mdb_walk_state_t *wsp) 1383 { 1384 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1385 } 1386 #endif /* SAFESTORE */ 1387 1388 /* 1389 * walk the handle list 1390 */ 1391 static int 1392 sdbc_handle_winit(mdb_walk_state_t *wsp) 1393 { 1394 _sd_buf_hlist_t hl; 1395 struct walk_info *winfo; 1396 GElf_Sym sym; 1397 1398 if (mdb_readvar(&hl, "_sd_handle_list") == -1) { 1399 mdb_warn("failed to read _sd_handle_list structure"); 1400 return (WALK_ERR); 1401 } 1402 1403 if (mdb_lookup_by_obj("sdbc", "_sd_handle_list", &sym) == -1) { 1404 mdb_warn("failed to lookup _sd_handle_list symbol"); 1405 return (WALK_ERR); 1406 } 1407 1408 /* if called without an address, start at first element in list */ 1409 if (wsp->walk_addr == NULL) 1410 wsp->walk_addr = (uintptr_t)(hl.hl_top.bh_next); 1411 1412 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1413 1414 winfo->w_end = (uintptr_t)(sym.st_value); /* &_sd_handle_list.hl_top */ 1415 wsp->walk_data = winfo; 1416 1417 return (WALK_NEXT); 1418 } 1419 1420 static int 1421 sdbc_handle_wstep(mdb_walk_state_t *wsp) 1422 { 1423 struct walk_info *winfo = wsp->walk_data; 1424 _sd_buf_handle_t handle; 1425 int status; 1426 1427 if (wsp->walk_addr == NULL) 1428 return (WALK_DONE); 1429 1430 if (wsp->walk_addr == winfo->w_end) 1431 return (WALK_DONE); 1432 1433 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1434 wsp->walk_cbdata); 1435 1436 if (mdb_vread(&handle, sizeof (_sd_buf_handle_t), wsp->walk_addr) 1437 == -1) { 1438 mdb_warn("failed to read handle at %p", wsp->walk_addr); 1439 return (WALK_ERR); 1440 } 1441 1442 wsp->walk_addr = (uintptr_t)(handle.bh_next); 1443 1444 return (status); 1445 } 1446 1447 static void 1448 sdbc_handle_wfini(mdb_walk_state_t *wsp) 1449 { 1450 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1451 } 1452 1453 /* 1454 * walk the global info array (dirty bits) 1455 */ 1456 1457 static int 1458 sdbc_glcinfo_winit(mdb_walk_state_t *wsp) 1459 { 1460 ss_centry_info_t *gl_centry_info; 1461 size_t gl_centry_info_size; 1462 struct walk_info *winfo; 1463 1464 1465 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1466 1467 /* get start of the cache entry metadata */ 1468 if (mdb_readvar(&gl_centry_info, "_sdbc_gl_centry_info") == -1) { 1469 mdb_warn("failed to read _sdbc_gl_centry_info"); 1470 return (WALK_ERR); 1471 } 1472 1473 /* need to calculate the end of the array */ 1474 if (mdb_readvar(&gl_centry_info_size, 1475 "_sdbc_gl_centry_info_size") == -1) { 1476 mdb_warn("failed to read _sdbc_gl_centry_info_size"); 1477 return (WALK_ERR); 1478 } 1479 1480 if (wsp->walk_addr == NULL) 1481 wsp->walk_addr = (uintptr_t)(gl_centry_info); 1482 1483 1484 1485 winfo->w_end = ((uintptr_t)(gl_centry_info)) + gl_centry_info_size; 1486 wsp->walk_data = winfo; 1487 1488 return (WALK_NEXT); 1489 } 1490 1491 static int 1492 sdbc_glcinfo_wstep(mdb_walk_state_t *wsp) 1493 { 1494 struct walk_info *winfo = wsp->walk_data; 1495 int status; 1496 1497 if (wsp->walk_addr == NULL) 1498 return (WALK_DONE); 1499 1500 if (wsp->walk_addr >= winfo->w_end) 1501 return (WALK_DONE); 1502 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1503 wsp->walk_cbdata); 1504 1505 wsp->walk_addr += sizeof (ss_centry_info_t); 1506 1507 return (status); 1508 } 1509 1510 static void 1511 sdbc_glcinfo_wfini(mdb_walk_state_t *wsp) 1512 { 1513 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1514 } 1515 1516 /* 1517 * walk the global file info array 1518 */ 1519 static int 1520 sdbc_glfinfo_winit(mdb_walk_state_t *wsp) 1521 { 1522 ss_voldata_t *gl_file_info; 1523 struct walk_info *winfo; 1524 int maxdevs; 1525 1526 1527 winfo = mdb_zalloc(sizeof (struct walk_info), UM_SLEEP); 1528 1529 /* get start of the cache entry metadata */ 1530 if (mdb_readvar(&gl_file_info, "_sdbc_gl_file_info") == -1) { 1531 mdb_warn("failed to read _sdbc_gl_file_info"); 1532 return (WALK_ERR); 1533 } 1534 1535 1536 if (wsp->walk_addr == NULL) 1537 wsp->walk_addr = (uintptr_t)(gl_file_info); 1538 1539 /* get the number of volumes */ 1540 if (mdb_readvar(&maxdevs, "sdbc_max_devs") == -1) { 1541 mdb_warn("failed to read sdbc_max_devs"); 1542 return (WALK_ERR); 1543 } 1544 1545 /* end of the array */ 1546 winfo->w_end = (uintptr_t)((gl_file_info) + maxdevs); 1547 1548 wsp->walk_data = winfo; 1549 1550 return (WALK_NEXT); 1551 } 1552 1553 static int 1554 sdbc_glfinfo_wstep(mdb_walk_state_t *wsp) 1555 { 1556 struct walk_info *winfo = wsp->walk_data; 1557 int status; 1558 1559 if (wsp->walk_addr == NULL) 1560 return (WALK_DONE); 1561 1562 if (wsp->walk_addr >= winfo->w_end) 1563 return (WALK_DONE); 1564 1565 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1566 wsp->walk_cbdata); 1567 1568 wsp->walk_addr += sizeof (ss_voldata_t); 1569 1570 return (status); 1571 1572 } 1573 1574 static void 1575 sdbc_glfinfo_wfini(mdb_walk_state_t *wsp) 1576 { 1577 mdb_free(wsp->walk_data, sizeof (struct walk_info)); 1578 } 1579 1580 /* end of WALKERS section */ 1581 1582 1583 const mdb_bitmask_t cc_flag_bits[] = { 1584 {"PEND_DIRTY", CC_PEND_DIRTY, CC_PEND_DIRTY}, 1585 {"PINNED", CC_PINNED, CC_PINNED}, 1586 {"PINNABLE", CC_PINNABLE, CC_PINNABLE}, 1587 {"QHEAD", CC_QHEAD, CC_QHEAD}, 1588 {NULL, 0, 0} 1589 }; 1590 1591 const mdb_bitmask_t io_status_bits[] = { 1592 {"IO_NONE", 0xff, _SD_IO_NONE}, 1593 {"IO_INITIATE", 0xff, _SD_IO_INITIATE}, 1594 {"IO_DONE", 0xff, _SD_IO_DONE}, 1595 {"IO_FAILED", 0xff, _SD_IO_FAILED}, 1596 {"IO_DISCARDED", 0xff, _SD_IO_DISCARDED}, 1597 {NULL, 0, 0} 1598 }; 1599 1600 const mdb_bitmask_t cc_aging_bits[] = { 1601 {"FOUND_IN_HASH", FOUND_IN_HASH_DM, FOUND_IN_HASH_DM}, 1602 {"FOUND_HOLD_OVER", FOUND_HOLD_OVER_DM, FOUND_HOLD_OVER_DM}, 1603 {"HOST_ENTRY", HOST_ENTRY_DM, HOST_ENTRY_DM}, 1604 {"PARASITIC_ENTRY", PARASITIC_ENTRY_DM, PARASITIC_ENTRY_DM}, 1605 {"STICKY_METADATA", STICKY_METADATA_DM, STICKY_METADATA_DM}, 1606 {"ELIGIBLE_ENTRY", ELIGIBLE_ENTRY_DM, ELIGIBLE_ENTRY_DM}, 1607 {"HASH_ENTRY", HASH_ENTRY_DM, HASH_ENTRY_DM}, 1608 {"HOLD_ENTRY", HOLD_ENTRY_DM, HOLD_ENTRY_DM}, 1609 {"AVAIL_ENTRY", AVAIL_ENTRY_DM, AVAIL_ENTRY_DM}, 1610 {"BAD_CHAIN", BAD_CHAIN_DM, BAD_CHAIN_DM}, 1611 {"BAD_ENTRY", BAD_ENTRY_DM, BAD_ENTRY_DM}, 1612 {"PREFETCH_I", PREFETCH_BUF_I, PREFETCH_BUF_I}, 1613 {"PREFETCH_E", PREFETCH_BUF_E, PREFETCH_BUF_E}, 1614 {NULL, 0, 0} 1615 }; 1616 1617 1618 /* DCMDS that use walkers */ 1619 1620 /* 1621 * dcmd to display cache entry control structures 1622 */ 1623 static int 1624 sdbc_cctl(uintptr_t addr, uint_t flags, int argc, 1625 const mdb_arg_t *argv) 1626 { 1627 uint_t opt_a = FALSE; 1628 uintptr_t opt_c = MDB_CD; /* cd */ 1629 uintptr_t opt_b = MDB_BLKNUM; /* block num */ 1630 uint_t opt_B = FALSE; /* BAD CHAIN or ENTRY */ 1631 uint_t opt_d = FALSE; /* dirty */ 1632 uint_t opt_H = FALSE; /* HOST */ 1633 uint_t opt_h = FALSE; /* hashed */ 1634 uint_t opt_i = FALSE; /* inuse */ 1635 uint_t opt_p = FALSE; /* pageio */ 1636 uint_t opt_P = FALSE; /* PARASITE */ 1637 uint_t opt_R = FALSE; /* explicit read-ahead (prefetch) */ 1638 uint_t opt_r = FALSE; /* implicit read-ahead (prefetch) */ 1639 uint_t opt_o = FALSE; /* io in progress */ 1640 uint_t opt_m = FALSE; /* has memory allocated */ 1641 uint_t opt_V = FALSE; /* valid bits */ 1642 uint_t opt_v = FALSE; /* verbose */ 1643 uint_t nofilter = FALSE; /* true if b, d, h, i, o, p, V are all false */ 1644 _sd_cctl_t centry; 1645 _sd_cctl_sync_t cc_sync; 1646 1647 /* 1648 * possible enhancements -- option to filter on flag bits 1649 * option that toggles other options. 1650 */ 1651 if (mdb_getopts(argc, argv, 1652 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 1653 'B', MDB_OPT_SETBITS, TRUE, &opt_B, 1654 'b', MDB_OPT_UINTPTR, &opt_b, 1655 'c', MDB_OPT_UINTPTR, &opt_c, 1656 'd', MDB_OPT_SETBITS, TRUE, &opt_d, 1657 'H', MDB_OPT_SETBITS, TRUE, &opt_H, 1658 'h', MDB_OPT_SETBITS, TRUE, &opt_h, 1659 'i', MDB_OPT_SETBITS, TRUE, &opt_i, 1660 'o', MDB_OPT_SETBITS, TRUE, &opt_o, 1661 'm', MDB_OPT_SETBITS, TRUE, &opt_m, 1662 'P', MDB_OPT_SETBITS, TRUE, &opt_P, 1663 'p', MDB_OPT_SETBITS, TRUE, &opt_p, 1664 'R', MDB_OPT_SETBITS, TRUE, &opt_R, 1665 'r', MDB_OPT_SETBITS, TRUE, &opt_r, 1666 'V', MDB_OPT_SETBITS, TRUE, &opt_V, 1667 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 1668 return (DCMD_USAGE); 1669 1670 1671 nofilter = (!OPT_B_SELECTED && !opt_d && !opt_h && !opt_i && 1672 !opt_o && !opt_m && !opt_p && !opt_V && !opt_B && 1673 !opt_P && !opt_H && !opt_R && !opt_r); /* no options */ 1674 1675 if (!(flags & DCMD_ADDRSPEC)) { 1676 if (mdb_walk_dcmd("sdbc`sdbc_cctl", "sdbc`sdbc_cctl", 1677 argc, argv) == -1) { 1678 mdb_warn("failed to walk 'cctl' list"); 1679 return (DCMD_ERR); 1680 } 1681 return (DCMD_OK); 1682 } 1683 1684 if (DCMD_HDRSPEC(flags)) { 1685 mdb_printf("sdbc cache ctl structures:\n"); 1686 } 1687 1688 1689 if (mdb_vread(¢ry, sizeof (_sd_cctl_t), addr) == -1) { 1690 mdb_warn("dcmd failed to read centry at %p", addr); 1691 return (DCMD_ERR); 1692 } 1693 1694 /* filter exclusively on a cd number if specified */ 1695 if (OPT_C_SELECTED && (centry.cc_head.hh_cd != opt_c)) 1696 return (DCMD_OK); 1697 1698 /* all other filters are inclusive */ 1699 if ((nofilter) || 1700 (OPT_B_SELECTED && (centry.cc_head.hh_blk_num == opt_b)) || 1701 (opt_B && (centry.cc_aging_dm & 1702 (BAD_ENTRY_DM | BAD_CHAIN_DM))) || 1703 (opt_d && (centry.cc_dirty)) || 1704 (opt_H && (centry.cc_aging_dm & HOST_ENTRY_DM)) || 1705 (opt_h && (centry.cc_head.hh_hashed)) || 1706 (opt_i && (centry.cc_inuse)) || 1707 (opt_p && (centry.cc_pageio)) || 1708 (opt_P && (centry.cc_aging_dm & PARASITIC_ENTRY_DM)) || 1709 (opt_R && (centry.cc_aging_dm & PREFETCH_BUF_E)) || 1710 (opt_r && (centry.cc_aging_dm & PREFETCH_BUF_I)) || 1711 (opt_V && (centry.cc_valid)) || 1712 (opt_m && (centry.cc_alloc_size_dm)) || 1713 (opt_o && (centry.cc_iostatus != _SD_IO_NONE))) 1714 /*EMPTY*/; 1715 else 1716 return (DCMD_OK); 1717 1718 mdb_inc_indent(4); 1719 mdb_printf( 1720 "%-?p cd %3-d blk_num %10-d valid %04hx dirty %04hx flag %02x\n", 1721 addr, centry.cc_head.hh_cd, 1722 centry.cc_head.hh_blk_num, centry.cc_valid, 1723 centry.cc_dirty, centry.cc_flag); 1724 mdb_dec_indent(4); 1725 1726 if (!opt_v) 1727 return (DCMD_OK); 1728 1729 /* verbose */ 1730 mdb_inc_indent(4); 1731 mdb_printf( 1732 "hashed %d seq %4-d toflush %04hx %8Tawait_use %4-d await_page %4-d\n", 1733 centry.cc_head.hh_hashed, centry.cc_seq, 1734 centry.cc_toflush, centry.cc_await_use, 1735 centry.cc_await_page); 1736 1737 mdb_printf("inuse %d pageio %d cc_flag <%b>\n", 1738 centry.cc_inuse, centry.cc_pageio, 1739 centry.cc_flag, cc_flag_bits); 1740 1741 mdb_printf("iocount %2d iostatus <%b>\n", 1742 centry.cc_iocount, centry.cc_iostatus, io_status_bits); 1743 1744 if (mdb_vread(&cc_sync, sizeof (struct _sd_cctl_sync), 1745 (uintptr_t)centry.cc_sync) 1746 == -1) 1747 mdb_warn("failed to read cc_sync"); /* not catastophic */ 1748 1749 else 1750 mdb_printf("cc_sync blkcv: %h-x %8Tlock: 0x%p (owner)\n", 1751 cc_sync._cc_blkcv._opaque, 1752 cc_sync._cc_lock._opaque[0]); 1753 1754 mdb_printf("dynamic memory allocation:\n"); 1755 mdb_inc_indent(4); 1756 mdb_printf("aging_dm age %3d %4Tage flags: <%b> 0x%x\n", 1757 centry.cc_aging_dm & 0xff, 1758 centry.cc_aging_dm, cc_aging_bits, centry.cc_aging_dm); 1759 1760 mdb_printf("alloc_size_dm %10-d head_dm %?-p\n", 1761 centry.cc_alloc_size_dm, centry.cc_head_dm); 1762 mdb_printf("next_dm %?-p link_list_dm %?-p\n", 1763 centry.cc_next_dm, centry.cc_link_list_dm); 1764 1765 mdb_printf("alloc_ct_dm %10-d dealloc_ct_dm %10-d\n", 1766 centry.cc_alloc_ct_dm, centry.cc_dealloc_ct_dm); 1767 1768 mdb_dec_indent(4); 1769 /* pointers */ 1770 mdb_printf("cctl pointers:\n"); 1771 mdb_inc_indent(4); 1772 1773 mdb_printf("next %?-p prev %?-p chain %?-p\n", 1774 centry.cc_next, centry.cc_prev, centry.cc_chain); 1775 mdb_printf("dirty_next %?-p dirty_link %?-p\n", 1776 centry.cc_dirty_next, centry.cc_dirty_link); 1777 mdb_printf("data %?-p write ctl %?-p\n", 1778 centry.cc_data, centry.cc_write); 1779 1780 mdb_dec_indent(4); 1781 1782 /* dynmem chain */ 1783 mdb_printf("cctl dmqueue index cc_blocks %4-d\n", centry.cc_cblocks); 1784 1785 mdb_printf("anon_addr %?-p anon_len %8-d\n", 1786 centry.cc_anon_addr.sa_virt, centry.cc_anon_len); 1787 1788 /* stats */ 1789 mdb_printf("cctl stats: "); 1790 mdb_inc_indent(4); 1791 mdb_printf("hits %8-d creat time %?-p\n", centry.cc_hits, 1792 centry.cc_creat); 1793 mdb_dec_indent(4); 1794 1795 mdb_printf("\n"); 1796 1797 mdb_dec_indent(4); 1798 1799 return (DCMD_OK); 1800 } 1801 1802 1803 /* 1804 * convenience dcmd to display the _sd_cctl cc_chain list (alloc list) 1805 * Must be called with an address of a cache entry (_sd_cctl_t) 1806 * same options as sdbc_cctl(). 1807 * alternatively the user can call the sdbc_cchain walker 1808 * and pipe the addresses to sdbc_cctl dcmd. 1809 */ 1810 static int 1811 sdbc_cchain(uintptr_t addr, uint_t flags, int argc, 1812 const mdb_arg_t *argv) 1813 { 1814 1815 if (!(flags & DCMD_ADDRSPEC)) 1816 return (DCMD_USAGE); 1817 1818 if (mdb_pwalk_dcmd("sdbc`sdbc_cchain", "sdbc`sdbc_cctl", 1819 argc, argv, addr) 1820 == -1) { 1821 mdb_warn("failed to walk cc_chain at addr %p", addr); 1822 return (DCMD_ERR); 1823 } 1824 1825 return (DCMD_OK); 1826 } 1827 1828 1829 /* 1830 * convenience dcmd to cdisplay the _sd_cctl dirty chain 1831 * (which is really a 2d chain). 1832 * Must be called with an address of a cache entry (_sd_cctl_t) 1833 * same options as sdbc_cctl(). 1834 * alternatively the user can call the sdbc_dchain walker 1835 * and pipe the addresses to sdbc_cctl dcmd. 1836 */ 1837 static int 1838 sdbc_dchain(uintptr_t addr, uint_t flags, int argc, 1839 const mdb_arg_t *argv) 1840 { 1841 1842 if (!(flags & DCMD_ADDRSPEC)) 1843 return (DCMD_USAGE); 1844 1845 if (mdb_pwalk_dcmd("sdbc`sdbc_dchain", "sdbc`sdbc_cctl", 1846 argc, argv, addr) 1847 == -1) { 1848 mdb_warn("failed to walk dirty chain at addr %p", addr); 1849 return (DCMD_ERR); 1850 } 1851 1852 return (DCMD_OK); 1853 } 1854 1855 /* 1856 * convenience dcmd to display the _sd_cctl dm chain list 1857 * Must be called with an address of a cache entry (_sd_cctl_t) 1858 * same options as sdbc_cctl(). 1859 * alternatively the user can call the sdbc_dmchain walker 1860 * and pipe the addresses to sdbc_cctl dcmd. 1861 */ 1862 static int 1863 sdbc_dmchain(uintptr_t addr, uint_t flags, int argc, 1864 const mdb_arg_t *argv) 1865 { 1866 1867 if (!(flags & DCMD_ADDRSPEC)) 1868 return (DCMD_USAGE); 1869 1870 if (mdb_pwalk_dcmd("sdbc`sdbc_dmchain", "sdbc`sdbc_cctl", 1871 argc, argv, addr) 1872 == -1) { 1873 mdb_warn("failed to walk dm chain at addr %p", addr); 1874 return (DCMD_ERR); 1875 } 1876 1877 return (DCMD_OK); 1878 } 1879 1880 /* 1881 * dcmd to walk a hash chain 1882 * requires an address. same options as sdbc_cctl dcmd 1883 */ 1884 static int 1885 sdbc_hashchain(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1886 { 1887 if (!(flags & DCMD_ADDRSPEC)) 1888 return (DCMD_USAGE); 1889 1890 if (mdb_pwalk_dcmd("sdbc`sdbc_hashchain", "sdbc`sdbc_cctl", 1891 argc, argv, addr) == -1) { 1892 mdb_warn("failed to walk hashchain at %p", addr); 1893 return (DCMD_ERR); 1894 } 1895 1896 return (DCMD_OK); 1897 } 1898 1899 1900 static void 1901 display_hash_table(_sd_hash_table_t *addr, _sd_hash_table_t *ht) 1902 { 1903 mdb_printf("hash table (%p):\n", addr); 1904 mdb_inc_indent(4); 1905 mdb_printf("size %7-d bits %2-d mask %8-x nmask %8-x buckets %p\n", 1906 ht->ht_size, ht->ht_bits, ht->ht_mask, 1907 ht->ht_nmask, ht->ht_buckets); 1908 mdb_dec_indent(4); 1909 } 1910 1911 static void 1912 display_hash_bucket(_sd_hash_bucket_t *addr, _sd_hash_bucket_t *hb) 1913 { 1914 kmutex_t lock; 1915 int rc; 1916 1917 if ((rc = mdb_vread(&lock, sizeof (kmutex_t), 1918 (uintptr_t)hb->hb_lock)) == -1) 1919 mdb_warn("failed to read bucket lock at %p", hb->hb_lock); 1920 1921 mdb_printf("hash bucket (%p):\n", addr); 1922 mdb_inc_indent(4); 1923 mdb_printf("head %?-p tail %?-p lock %?-p %s\n", 1924 hb->hb_head, hb->hb_tail, 1925 (rc == -1) ? hb->hb_lock : lock._opaque[0], 1926 (rc == -1) ? "" : "(owner)"); 1927 mdb_printf("inlist %d seq %d\n", hb->hb_inlist, hb->hb_seq); 1928 mdb_dec_indent(4); 1929 } 1930 1931 /* 1932 * dcmd to walk the hash table 1933 * defaults to _sd_htable the cache hash table, 1934 * but wil accept an address which is probably only useful 1935 * in the event that other hash tables are implemented in 1936 * the cache. 1937 * 1938 * calls sdbc_hashchain dcmd. same options as sdbc_cctl dcmd. 1939 */ 1940 static int 1941 sdbc_hashtable(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1942 { 1943 _sd_hash_table_t *sd_htable_addr; 1944 _sd_hash_table_t _sd_htable; 1945 _sd_hash_bucket_t hash_bucket; 1946 int i; 1947 1948 1949 1950 if (!(flags & DCMD_ADDRSPEC)) { 1951 /* get the address of the standard cache hash table */ 1952 if (mdb_readvar(&sd_htable_addr, "_sd_htable") == -1) { 1953 mdb_warn("failed to read _sd_htable address\n"); 1954 return (DCMD_ERR); 1955 } 1956 } else 1957 sd_htable_addr = (_sd_hash_table_t *)addr; 1958 1959 /* read in the hash table structure */ 1960 if (mdb_vread(&_sd_htable, sizeof (_sd_hash_table_t), 1961 (uintptr_t)sd_htable_addr) == -1) { 1962 mdb_warn("failed to read _sd_htable structure at %p\n", 1963 sd_htable_addr); 1964 return (DCMD_ERR); 1965 } 1966 1967 display_hash_table(sd_htable_addr, &_sd_htable); 1968 1969 /* 1970 * read in the hash buckets 1971 * and display chains if there are any 1972 */ 1973 for (i = 0; i < _sd_htable.ht_size; ++i) { 1974 if (mdb_vread(&hash_bucket, sizeof (_sd_hash_bucket_t), 1975 (uintptr_t)(_sd_htable.ht_buckets + i)) == -1) { 1976 mdb_warn("failed to read ht_buckets at %p\n", 1977 _sd_htable.ht_buckets + i); 1978 return (DCMD_ERR); 1979 } 1980 1981 if (hash_bucket.hb_head != NULL) { 1982 display_hash_bucket(_sd_htable.ht_buckets + i, 1983 &hash_bucket); 1984 /* 1985 * if this walk fails, continue trying 1986 * to read hash buckets 1987 */ 1988 if (mdb_call_dcmd("sdbc`sdbc_hashchain", 1989 (uintptr_t)hash_bucket.hb_head, 1990 flags|DCMD_ADDRSPEC, argc, argv) 1991 == -1) 1992 mdb_warn( 1993 "failed to walk hash chain at %p", 1994 hash_bucket.hb_head); 1995 mdb_printf("\n"); 1996 } 1997 } 1998 1999 return (DCMD_OK); 2000 } 2001 /* 2002 * dcmd to display the sdbc lru queue 2003 * same options as sdbc_cctl(). 2004 * alternatively the user can call the sdbc_lru walker 2005 * and pipe the addresses to sdbc_cctl dcmd. 2006 */ 2007 static int 2008 sdbc_lru(uintptr_t addr, uint_t flags, int argc, 2009 const mdb_arg_t *argv) 2010 { 2011 _sd_queue_t _sd_lru_q; 2012 GElf_Sym sym; 2013 2014 if (!(flags & DCMD_ADDRSPEC)) { 2015 if (mdb_lookup_by_obj("sdbc", "_sd_lru_q", &sym) == -1) { 2016 mdb_warn("failed to lookup _sd_lru_q symbol"); 2017 return (DCMD_ERR); 2018 } 2019 2020 if (mdb_vread(&_sd_lru_q, sizeof (_sd_queue_t), 2021 sym.st_value) == -1) { 2022 mdb_warn("failed to read _sd_lru_q structure"); 2023 return (DCMD_ERR); 2024 } 2025 2026 mdb_printf("Cache LRU Queue\n"); 2027 mdb_inc_indent(4); 2028 mdb_printf( 2029 "qlock: 0x%-p (owner) await %d seq %d inq %d req %d noreq %d\n", 2030 _sd_lru_q.sq_qlock._opaque[0], 2031 _sd_lru_q.sq_await, 2032 _sd_lru_q.sq_seq, 2033 _sd_lru_q.sq_inq, 2034 _sd_lru_q.sq_req_stat, 2035 _sd_lru_q.sq_noreq_stat); 2036 2037 addr = (uintptr_t)(sym.st_value); 2038 } 2039 2040 if (mdb_pwalk_dcmd("sdbc`sdbc_lru", "sdbc`sdbc_cctl", 2041 argc, argv, addr) == -1) { 2042 mdb_warn("failed to walk lru at addr %p", addr); 2043 return (DCMD_ERR); 2044 } 2045 2046 return (DCMD_OK); 2047 } 2048 2049 #ifdef SAFESTORE 2050 static void 2051 print_wrq(_sd_writeq_t *wrq, uint_t verbose) 2052 { 2053 int i; 2054 2055 mdb_printf("Cache Write Ctl Queue:\n"); 2056 mdb_inc_indent(4); 2057 mdb_printf("qtop %-p qlock: %-p (owner) inq %d\n", 2058 wrq->wq_qtop, 2059 wrq->wq_qlock._opaque[0], 2060 wrq->wq_inq); 2061 2062 mdb_printf("slp_top %3-d slp_index %3-d slp_inq %3-d\n", 2063 wrq->wq_slp_top, 2064 wrq->wq_slp_index, 2065 wrq->wq_slp_inq); 2066 2067 for (i = 0; verbose && i < SD_WR_SLP_Q_MAX; i += 2) { 2068 mdb_printf("%3d: cv %h-x wq_need %3-d wq_held %3-d%4T", 2069 i, 2070 wrq->wq_slp[i].slp_wqcv._opaque, 2071 wrq->wq_slp[i].slp_wqneed, 2072 wrq->wq_slp[i].slp_wqheld); 2073 if (SD_WR_SLP_Q_MAX > (i + 1)) { 2074 mdb_printf( 2075 "%3d: cv %h-x wq_need %3-d wq_held %3-d%\n", 2076 i+1, 2077 wrq->wq_slp[i+1].slp_wqcv._opaque, 2078 wrq->wq_slp[i+1].slp_wqneed, 2079 wrq->wq_slp[i+1].slp_wqheld); 2080 } 2081 } 2082 mdb_dec_indent(4); 2083 } 2084 2085 /* 2086 * dcmd to display write control structures 2087 */ 2088 2089 static int 2090 sdbc_wctl(uintptr_t addr, uint_t flags, int argc, 2091 const mdb_arg_t *argv) 2092 { 2093 _sd_wr_cctl_t wctl; 2094 ss_centry_info_t gl_info; 2095 ss_centry_info_t nv_gl_info; 2096 uintptr_t opt_c = MDB_CD; 2097 uint_t opt_d = FALSE; 2098 uint_t opt_v = FALSE; 2099 2100 2101 /* TODO option for fba pos */ 2102 if (mdb_getopts(argc, argv, 2103 'd', MDB_OPT_SETBITS, TRUE, &opt_d, 2104 'c', MDB_OPT_UINTPTR, &opt_c, 2105 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 2106 return (DCMD_USAGE); 2107 2108 2109 if (!(flags & DCMD_ADDRSPEC)) { 2110 if (mdb_walk_dcmd("sdbc`sdbc_wctl", "sdbc`sdbc_wctl", 2111 argc, argv) == -1) { 2112 mdb_warn("failed to walk write ctl array"); 2113 return (DCMD_ERR); 2114 } 2115 return (DCMD_OK); 2116 } 2117 2118 if (DCMD_HDRSPEC(flags)) { 2119 mdb_printf("write control block structures:\n"); 2120 } 2121 2122 if (mdb_vread(&wctl, sizeof (_sd_wr_cctl_t), addr) == -1) { 2123 mdb_warn("failed to read wctl at 0x%p", addr); 2124 return (DCMD_ERR); 2125 } 2126 2127 2128 /* 2129 * print "all" is the default. 2130 * filter conditions can only be checked by reading in wc_gl_info 2131 */ 2132 if (opt_c || opt_d || opt_v) 2133 if (mdb_vread(&gl_info, sizeof (ss_centry_info_t), 2134 (uintptr_t)wctl.wc_gl_info) == -1) { 2135 mdb_warn("failed to read at wc_gl_info 0x%p", addr); 2136 return (DCMD_ERR); 2137 } 2138 2139 2140 if (OPT_C_SELECTED && (gl_info.gl_cd != opt_c)) 2141 return (DCMD_OK); 2142 2143 if (opt_d && !(gl_info.gl_dirty)) 2144 return (DCMD_OK); 2145 2146 mdb_inc_indent(4); 2147 mdb_printf("%-p data %-p gl_info %-p Ngl_info %-p flg %02x\n", 2148 addr, 2149 wctl.wc_data, 2150 wctl.wc_gl_info, 2151 wctl.wc_nvmem_gl_info, 2152 wctl.wc_flag); 2153 mdb_dec_indent(4); 2154 2155 /* verbose */ 2156 if (!opt_v) 2157 return (DCMD_OK); 2158 2159 mdb_inc_indent(4); 2160 mdb_printf("next %?-p prev %?-p\n", wctl.wc_next, wctl.wc_prev); 2161 mdb_printf(" gl_info: "); 2162 mdb_printf("cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2163 gl_info.gl_cd, gl_info.gl_fpos, gl_info.gl_dirty & 0xffff, 2164 gl_info.gl_flag, cc_flag_bits); 2165 2166 if (wctl.wc_nvmem_gl_info) { 2167 if (mdb_vread(&nv_gl_info, sizeof (ss_centry_info_t), 2168 (uintptr_t)wctl.wc_nvmem_gl_info) == -1) { 2169 mdb_warn("failed to read at wc_nvmem_gl_info 0x%p", 2170 wctl.wc_nvmem_gl_info); /* not catastophic, continue */ 2171 } else { 2172 2173 /* consistency check */ 2174 if (memcmp(&gl_info, &nv_gl_info, 2175 sizeof (ss_centry_info_t) != 0)) { 2176 mdb_warn("nvram and host memory are NOT identical!"); 2177 mdb_printf("nvmem_gl_info: "); 2178 mdb_printf("cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2179 nv_gl_info.gl_cd, nv_gl_info.gl_fpos, 2180 nv_gl_info.gl_dirty & 0xffff, 2181 nv_gl_info.gl_flag, cc_flag_bits); 2182 } 2183 2184 } 2185 } 2186 2187 mdb_dec_indent(4); 2188 mdb_printf("\n"); 2189 return (DCMD_OK); 2190 } 2191 2192 /* 2193 * dcmd to display write control structures in the free list 2194 * same options as sdbc_wctl 2195 */ 2196 2197 static int 2198 sdbc_wrq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2199 { 2200 _sd_net_t _sd_net_config; 2201 uintptr_t opt_c = MDB_CD; 2202 uint_t opt_d = FALSE; 2203 uint_t opt_v = FALSE; 2204 2205 2206 /* look for verbose option */ 2207 if (mdb_getopts(argc, argv, 2208 'd', MDB_OPT_SETBITS, TRUE, &opt_d, 2209 'c', MDB_OPT_UINTPTR, &opt_c, 2210 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 2211 return (DCMD_USAGE); 2212 2213 if (!(flags & DCMD_ADDRSPEC)) { 2214 if (mdb_readvar(&_sd_net_config, "_sd_net_config") == -1) { 2215 mdb_warn("failed to read _sd_net_config structure"); 2216 return (DCMD_ERR); 2217 } 2218 2219 print_wrq(&(_sd_net_config.sn_wr_queue), opt_v); 2220 2221 addr = (uintptr_t)(_sd_net_config.sn_wr_queue.wq_qtop); 2222 } 2223 2224 if (mdb_pwalk_dcmd("sdbc`sdbc_wrq", "sdbc`sdbc_wctl", 2225 argc, argv, addr) == -1) { 2226 mdb_warn("failed to walk write ctl queue at addr %p", addr); 2227 return (DCMD_ERR); 2228 } 2229 return (DCMD_OK); 2230 } 2231 #endif 2232 2233 /* 2234 * dcmd to display the dm queues 2235 * use sdbc_lru walker to walk each queue. 2236 */ 2237 /*ARGSUSED*/ 2238 static int 2239 sdbc_dmqueues(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2240 { 2241 _sd_queue_t *sdbc_dm_queues; /* kernel address of dm queues */ 2242 int max_dm_queues; 2243 _sd_queue_t *queues = NULL; /* local copy */ 2244 int i; 2245 2246 2247 if (argc != 0) 2248 return (DCMD_USAGE); 2249 2250 if (!(flags & DCMD_ADDRSPEC)) { 2251 if (mdb_readvar(&sdbc_dm_queues, "sdbc_dm_queues") == -1) { 2252 mdb_warn("failed to read sdbc_dm_queues address\n"); 2253 return (DCMD_ERR); 2254 } 2255 2256 if (mdb_readvar(&max_dm_queues, "max_dm_queues") == -1) { 2257 mdb_warn("failed to read max_dm_queues variable\n"); 2258 return (DCMD_ERR); 2259 } 2260 2261 queues = mdb_zalloc(max_dm_queues * sizeof (_sd_queue_t), 2262 UM_SLEEP); 2263 mdb_printf("max_dm_queues %d sdbc_dm_queues %p queues %p\n", 2264 max_dm_queues, sdbc_dm_queues, queues); 2265 2266 if (mdb_vread(queues, max_dm_queues * sizeof (_sd_queue_t), 2267 (uintptr_t)sdbc_dm_queues) == -1) { 2268 mdb_warn("failed to read sdbc_dm_queues"); 2269 return (DCMD_ERR); 2270 } 2271 2272 for (i = 0; i < max_dm_queues; ++i) { 2273 mdb_printf("Cache DM Queue %d %p\n", 2274 queues[i].sq_dmchain_cblocks, 2275 sdbc_dm_queues +i); 2276 mdb_inc_indent(4); 2277 mdb_printf("qlock: 0x%-p (owner) await %d " 2278 "seq %d inq %d req %d noreq %d\n", 2279 queues[i].sq_qlock._opaque[0], 2280 queues[i].sq_await, 2281 queues[i].sq_seq, 2282 queues[i].sq_inq, 2283 queues[i].sq_req_stat, 2284 queues[i].sq_noreq_stat); 2285 2286 mdb_dec_indent(4); 2287 } 2288 } 2289 2290 return (DCMD_OK); 2291 } 2292 2293 2294 mdb_bitmask_t cd_writer_bits[] = { 2295 { "NONE ", (u_longlong_t)~0, _SD_WRITER_NONE }, 2296 { "CREATE ", (u_longlong_t)~0, _SD_WRITER_CREATE }, 2297 { "RUNNING", (u_longlong_t)~0, _SD_WRITER_RUNNING }, 2298 { NULL, 0, 0 } 2299 }; 2300 2301 mdb_bitmask_t sh_failed_status[] = { 2302 { "STATUS OK", (u_longlong_t)~0, 0 }, 2303 { "I/O ERROR", (u_longlong_t)~0, 1 }, 2304 { "OPEN FAIL", (u_longlong_t)~0, 2 }, 2305 { NULL, 0, 0 } 2306 }; 2307 2308 mdb_bitmask_t sh_flag_bits[] = { 2309 { "ATTACHED", CD_ATTACHED, CD_ATTACHED }, 2310 { NULL, 0, 0 } 2311 }; 2312 2313 mdb_bitmask_t sh_alloc_bits[] = { 2314 { "ALLOC_IN_PROGRESS", CD_ALLOC_IN_PROGRESS, CD_ALLOC_IN_PROGRESS }, 2315 { "ALLOCATED", CD_ALLOCATED, CD_ALLOCATED }, 2316 { "CLOSE_IN_PROGRESS", CD_CLOSE_IN_PROGRESS, CD_CLOSE_IN_PROGRESS }, 2317 { NULL, 0, 0 } 2318 }; 2319 2320 /* 2321 * dcmd to display cd information 2322 */ 2323 static int 2324 sdbc_cdinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2325 { 2326 _sd_shared_t sd_shared; 2327 _sd_cd_info_t cdi; 2328 ss_voldata_t gl_file; 2329 char *fn = "nopath"; /* filename if sd_shared info cannot be read */ 2330 uchar_t sh_alloc = 0; /* assume not alloc'd if sd_shared info unavail */ 2331 uintptr_t opt_c = MDB_CD; 2332 uint_t opt_a = FALSE; 2333 uint_t opt_v = FALSE; 2334 int dev_t_chars; 2335 2336 dev_t_chars = sizeof (dev_t) * 2; /* # chars to display dev_t */ 2337 2338 2339 if (mdb_getopts(argc, argv, 2340 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 2341 'c', MDB_OPT_UINTPTR, &opt_c, 2342 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 2343 return (DCMD_USAGE); 2344 2345 if (!(flags & DCMD_ADDRSPEC)) { 2346 if (mdb_walk_dcmd("sdbc`sdbc_cdinfo", "sdbc`sdbc_cdinfo", 2347 argc, argv) == -1) { 2348 mdb_warn("failed to walk cd info array"); 2349 return (DCMD_ERR); 2350 } 2351 return (DCMD_OK); 2352 } 2353 2354 if (DCMD_HDRSPEC(flags)) { 2355 mdb_printf("cd info structures:\n"); 2356 } 2357 2358 if (mdb_vread(&cdi, sizeof (_sd_cd_info_t), addr) == -1) { 2359 mdb_warn("failed to read cd info at 0x%p", addr); 2360 return (DCMD_ERR); 2361 } 2362 2363 /* 2364 * need to do this read even for non-verbose option to 2365 * get the filename and the sh_alloc field 2366 */ 2367 if (cdi.cd_info) { 2368 if (mdb_vread(&sd_shared, sizeof (_sd_shared_t), 2369 (uintptr_t)cdi.cd_info) == -1) { 2370 mdb_warn("failed to read shared cd info at 0x%p", 2371 cdi.cd_info); 2372 /* not catastrophic, keep truckin' */ 2373 } else { 2374 fn = sd_shared.sh_filename; 2375 sh_alloc = sd_shared.sh_alloc; 2376 } 2377 } 2378 2379 if (!opt_a && (sh_alloc == 0)) 2380 return (DCMD_OK); 2381 2382 if (OPT_C_SELECTED && (opt_c != cdi.cd_desc)) 2383 return (DCMD_OK); 2384 2385 mdb_inc_indent(4); 2386 mdb_printf("%p cd %3-d filename %s\n", 2387 addr, cdi.cd_desc, fn); 2388 mdb_printf("alloc <%b> hint <%b>\n", 2389 sh_alloc, sh_alloc_bits, 2390 cdi.cd_hint, cache_hints); 2391 mdb_dec_indent(4); 2392 2393 if (!opt_v) 2394 return (DCMD_OK); 2395 2396 /* verbose */ 2397 mdb_inc_indent(4); 2398 mdb_printf("rawfd %?-p crdev %0*lx iodev %?-p\n", 2399 cdi.cd_rawfd, 2400 dev_t_chars, 2401 cdi.cd_crdev, 2402 cdi.cd_iodev); 2403 mdb_printf("flag %x %8Tlock %?-p writer <%b>\n", 2404 cdi.cd_flag, 2405 cdi.cd_lock._opaque[0], 2406 cdi.cd_writer, cd_writer_bits); 2407 mdb_printf("global %?-p dirty_head %?-p\n", 2408 cdi.cd_global, cdi.cd_dirty_head); 2409 mdb_printf("last_ent %?-p lastchain_ptr %?-p lastchain %d\n", 2410 cdi.cd_last_ent, cdi.cd_lastchain_ptr, 2411 cdi.cd_lastchain); 2412 mdb_printf("io_head %?-p io_tail %?-p fail_head %?-p\n", 2413 cdi.cd_io_head, cdi.cd_io_tail, cdi.cd_fail_head); 2414 mdb_printf( 2415 "cd_info %?-p failover %d recovering %d write_inprogress %d\n", 2416 cdi.cd_info, cdi.cd_failover, 2417 cdi.cd_recovering, 2418 cdi.cd_write_inprogress); 2419 2420 if (cdi.cd_global != NULL) { 2421 if (mdb_vread(&gl_file, sizeof (ss_voldata_t), 2422 (uintptr_t)cdi.cd_global) == -1) 2423 mdb_warn("failed to read cd_global at %p", 2424 cdi.cd_global); 2425 else { 2426 mdb_printf("cd_global: %s\n", gl_file.sv_volname); 2427 mdb_printf("pinned %2-d attached %2-d devidsz %3-d\n", 2428 gl_file.sv_pinned, gl_file.sv_attached, 2429 gl_file.sv_devidsz); 2430 mdb_printf("devid %s\n", gl_file.sv_devid); 2431 mdb_printf("vol %?p\n", gl_file.sv_vol); 2432 } 2433 /* TODO do a consistency check here against the nvram copy */ 2434 } 2435 2436 if (cdi.cd_info == NULL) { 2437 mdb_printf("no shared info\n"); 2438 } else { 2439 mdb_printf("shared:\n"); 2440 mdb_printf("failed <%b> cd %3-d", 2441 sd_shared.sh_failed, sh_failed_status, 2442 sd_shared.sh_cd); 2443 mdb_printf("cache_read %10-d cache_write %10-d\n", 2444 sd_shared.sh_cache_read, sd_shared.sh_cache_write); 2445 mdb_printf("disk_read %10-d disk_write %10-d filesize %10-d\n", 2446 sd_shared.sh_disk_read, sd_shared.sh_disk_write, 2447 sd_shared.sh_filesize); 2448 mdb_printf("numdirty %8-d numio %8-d numfail %8-d\n", 2449 sd_shared.sh_numdirty, 2450 sd_shared.sh_numio, 2451 sd_shared.sh_numfail); 2452 mdb_printf("flushloop %2-d sh_flag <%b>\n", 2453 sd_shared.sh_flushloop, sd_shared.sh_flag, sh_flag_bits); 2454 2455 /* this can be really verbose */ 2456 if (cdi.cd_dirty_head) { 2457 mdb_printf("Dirty Chain (cd_dirty_head):"); 2458 /* TODO reconstruct argv without opt_a */ 2459 if (!opt_a) 2460 mdb_call_dcmd("sdbc_dchain", 2461 (uintptr_t)cdi.cd_dirty_head, 2462 flags, argc, argv); 2463 else /* print with no options */ 2464 mdb_call_dcmd("sdbc_dchain", 2465 (uintptr_t)cdi.cd_dirty_head, 2466 flags, 0, NULL); 2467 } 2468 2469 if (cdi.cd_io_head) { 2470 mdb_printf("I/O Pending Chain (cd_io_head):"); 2471 /* TODO reconstruct argv without opt_a */ 2472 if (!opt_a) 2473 mdb_call_dcmd("sdbc_dchain", 2474 (uintptr_t)cdi.cd_io_head, 2475 flags, argc, argv); 2476 else /* print with no options */ 2477 mdb_call_dcmd("sdbc_dchain", 2478 (uintptr_t)cdi.cd_dirty_head, 2479 flags, 0, NULL); 2480 } 2481 2482 if (cdi.cd_fail_head) { 2483 mdb_printf("Failed Chain (cd_fail_head):"); 2484 /* TODO reconstruct argv without opt_a */ 2485 if (!opt_a) 2486 mdb_call_dcmd("sdbc_dchain", 2487 (uintptr_t)cdi.cd_fail_head, 2488 flags, argc, argv); 2489 else /* print with no options */ 2490 mdb_call_dcmd("sdbc_dchain", 2491 (uintptr_t)cdi.cd_dirty_head, 2492 flags, 0, NULL); 2493 } 2494 } 2495 2496 mdb_dec_indent(4); 2497 2498 mdb_printf("\n"); 2499 2500 return (DCMD_OK); 2501 } 2502 2503 #ifdef SAFESTORE 2504 /* 2505 * dcmd to display fault tolerant control structures 2506 */ 2507 static int 2508 sdbc_ftctl(uintptr_t addr, uint_t flags, int argc, 2509 const mdb_arg_t *argv) 2510 { 2511 _sd_ft_cctl_t ft_cent; 2512 ss_centry_info_t gl_info; 2513 ss_centry_info_t nv_gl_info; 2514 uintptr_t opt_c = MDB_CD; 2515 uint_t opt_d = FALSE; 2516 uint_t opt_v = FALSE; 2517 2518 2519 /* TODO option to select on fpos */ 2520 if (mdb_getopts(argc, argv, 2521 'd', MDB_OPT_SETBITS, TRUE, &opt_d, 2522 'c', MDB_OPT_UINTPTR, &opt_c, 2523 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 2524 return (DCMD_USAGE); 2525 2526 2527 if (!(flags & DCMD_ADDRSPEC)) { 2528 if (mdb_walk_dcmd("sdbc`sdbc_ftctl", "sdbc`sdbc_ftctl", 2529 argc, argv) == -1) { 2530 mdb_warn("failed to walk write ctl array"); 2531 return (DCMD_ERR); 2532 } 2533 return (DCMD_OK); 2534 } 2535 2536 if (DCMD_HDRSPEC(flags)) { 2537 mdb_printf("Ft control block structures:\n"); 2538 } 2539 2540 if (mdb_vread(&ft_cent, sizeof (_sd_ft_cctl_t), addr) == -1) { 2541 mdb_warn("failed to read ft_cent at 0x%p", addr); 2542 return (DCMD_ERR); 2543 } 2544 2545 2546 /* 2547 * print "all" is the default. 2548 * filter conditions can only be checked by reading in wc_gl_info 2549 */ 2550 if (opt_c || opt_d || opt_v) 2551 if (mdb_vread(&gl_info, sizeof (ss_centry_info_t), 2552 (uintptr_t)ft_cent.ft_gl_info) == -1) { 2553 mdb_warn("failed to read at wc_gl_info 0x%p", addr); 2554 return (DCMD_ERR); 2555 } 2556 2557 2558 if (OPT_C_SELECTED && (gl_info.gl_cd != opt_c)) 2559 return (DCMD_OK); 2560 2561 if (opt_d && !(gl_info.gl_dirty)) 2562 return (DCMD_OK); 2563 2564 mdb_inc_indent(4); 2565 mdb_printf("%-p data %?-p qnext %?-p\n", 2566 addr, 2567 ft_cent.ft_qnext, 2568 ft_cent.ft_data); 2569 mdb_printf("gl_info %?-p nvmem_gl_info %?-p\n", 2570 ft_cent.ft_gl_info, 2571 ft_cent.ft_nvmem_gl_info); 2572 mdb_dec_indent(4); 2573 2574 /* verbose */ 2575 if (!opt_v) { 2576 mdb_printf("\n"); 2577 return (DCMD_OK); 2578 } 2579 2580 mdb_inc_indent(4); 2581 mdb_printf(" gl_info: "); 2582 mdb_printf("cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2583 gl_info.gl_cd, gl_info.gl_fpos, gl_info.gl_dirty & 0xffff, 2584 gl_info.gl_flag, cc_flag_bits); 2585 2586 if (ft_cent.ft_nvmem_gl_info) { 2587 if (mdb_vread(&nv_gl_info, sizeof (ss_centry_info_t), 2588 (uintptr_t)ft_cent.ft_nvmem_gl_info) == -1) { 2589 mdb_warn("failed to read at ft_nvmem_gl_info 0x%p", 2590 ft_cent.ft_nvmem_gl_info); /* not catastophic, continue */ 2591 } else { 2592 mdb_printf("nvmem_gl_info: "); 2593 mdb_printf("cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2594 nv_gl_info.gl_cd, nv_gl_info.gl_fpos, 2595 nv_gl_info.gl_dirty & 0xffff, 2596 nv_gl_info.gl_flag, cc_flag_bits); 2597 2598 /* consistency check */ 2599 if (memcmp(&gl_info, &nv_gl_info, sizeof (ss_centry_info_t)) 2600 != 0) { 2601 mdb_warn("nvram and host memory are NOT identical!"); 2602 } 2603 2604 } 2605 } 2606 2607 mdb_dec_indent(4); 2608 mdb_printf("\n"); 2609 return (DCMD_OK); 2610 } 2611 #endif /* SAFESTORE */ 2612 2613 2614 /* dcmd to display buffer handles */ 2615 static int 2616 sdbc_handles(uintptr_t addr, uint_t flags, int argc, 2617 const mdb_arg_t *argv) 2618 { 2619 uint_t opt_a = FALSE; 2620 uintptr_t opt_c = MDB_CD; 2621 uint_t opt_v = FALSE; 2622 uint_t opt_C = FALSE; 2623 _sd_buf_hlist_t hl; 2624 _sd_buf_handle_t bh; 2625 2626 2627 if (mdb_getopts(argc, argv, 2628 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 2629 'c', MDB_OPT_UINTPTR, &opt_c, 2630 'C', MDB_OPT_SETBITS, TRUE, &opt_C, 2631 'v', MDB_OPT_SETBITS, TRUE, &opt_v) != argc) 2632 return (DCMD_USAGE); 2633 2634 2635 if (mdb_readvar(&hl, "_sd_handle_list") == -1) { 2636 mdb_warn("failed to read _sd_handle_list structure"); 2637 return (DCMD_ERR); 2638 } 2639 2640 2641 if (!(flags & DCMD_ADDRSPEC)) { 2642 if (mdb_walk_dcmd("sdbc`sdbc_handles", "sdbc`sdbc_handles", 2643 argc, argv) == -1) { 2644 mdb_warn("failed to walk 'sdbc_handle_list'"); 2645 return (DCMD_ERR); 2646 } 2647 return (DCMD_OK); 2648 } 2649 2650 if (DCMD_HDRSPEC(flags)) { 2651 mdb_printf("Handle List Info:\n"); 2652 2653 mdb_inc_indent(4); 2654 mdb_printf("hl_top.bh_next: 0x%p\n", hl.hl_top.bh_next); 2655 mdb_printf("hl_lock: 0x%p (owner)\n", hl.hl_lock._opaque[0]); 2656 mdb_printf("hl_count: %hd\n", hl.hl_count); 2657 mdb_dec_indent(4); 2658 mdb_printf("buf handles:\n"); 2659 } 2660 2661 if (mdb_vread(&bh, sizeof (bh), addr) == -1) { 2662 mdb_warn("failed to read buf handle at 0x%p", addr); 2663 return (DCMD_ERR); 2664 } 2665 2666 if (!opt_a && !(bh.bh_flag & (NSC_HALLOCATED | NSC_HACTIVE))) 2667 return (DCMD_OK); 2668 2669 /* 2670 * may get false matches on cd option -- 2671 * a cleared bh_cd field will match if user specified cd 0 2672 */ 2673 if (OPT_C_SELECTED && (bh.bh_cd != opt_c)) 2674 return (DCMD_OK); 2675 2676 mdb_inc_indent(4); 2677 mdb_printf("%p %8T cd %3-d %4T<%b> %x\n", addr, bh.bh_cd, 2678 bh.bh_flag, nsc_buf_bits, bh.bh_flag); 2679 2680 /* check for verbose, avoid printing twice */ 2681 if (!opt_v && opt_C) { 2682 mdb_printf("cc_chain: "); 2683 if (bh.bh_centry) 2684 mdb_call_dcmd("sdbc`sdbc_cchain", 2685 (uintptr_t)bh.bh_centry, DCMD_ADDRSPEC, 0, NULL); 2686 } 2687 2688 mdb_dec_indent(4); 2689 2690 if (!opt_v) 2691 return (DCMD_OK); 2692 2693 /* verbose */ 2694 mdb_inc_indent(4); 2695 2696 mdb_printf("callbacks: %-20a%-20a%-20a\n", 2697 bh.bh_disconnect_cb, bh.bh_read_cb, bh.bh_write_cb); 2698 2699 mdb_printf("centry %?p %8T next %?p\n", 2700 bh.bh_centry, bh.bh_next); 2701 mdb_printf("buffer:\n"); 2702 2703 mdb_inc_indent(4); 2704 mdb_printf("fd 0x%p pos %10d len %6d flag 0x%x\n", 2705 bh.bh_buf.sb_fd, bh.bh_fba_pos, bh.bh_fba_len, bh.bh_flag); 2706 2707 mdb_printf("alloc_thread %p busy_thread %p\n", bh.bh_alloc_thread, 2708 bh.bh_busy_thread); 2709 2710 mdb_printf("err %4d %8T bh_vec 0x%p\n", bh.bh_error, bh.bh_vec); 2711 mdb_dec_indent(4); 2712 2713 mdb_printf("bufvec (scatter gather list): %-?s %8T%-s\n", 2714 "ADDR", "LEN"); 2715 { 2716 _sd_bufvec_t *bv, *endvec; 2717 2718 2719 /* todo check for (bh_vec != bh_bufvec) => readahead? */ 2720 2721 bv = bh.bh_bufvec; 2722 endvec = bv + _SD_MAX_BLKS; 2723 mdb_inc_indent(30); 2724 while (bv->bufaddr) { 2725 mdb_printf("%p %8T%d\n", bv->bufaddr, bv->buflen); 2726 ++bv; 2727 if (bv > endvec) { 2728 mdb_warn("END of bh_bufvec ARRAY"); 2729 break; 2730 } 2731 } 2732 mdb_dec_indent(30); 2733 } 2734 2735 if (opt_C) { 2736 mdb_printf("cc_chain: "); 2737 if (bh.bh_centry) 2738 mdb_call_dcmd("sdbc`sdbc_cchain", 2739 (uintptr_t)bh.bh_centry, DCMD_ADDRSPEC, 0, NULL); 2740 } 2741 2742 mdb_dec_indent(4); 2743 mdb_printf("\n"); 2744 2745 return (DCMD_OK); 2746 } 2747 /* 2748 * dcmd to display ss_centry_info_t structures and 2749 * do optional consistency check with the nvram copy 2750 * if configured for nvram safe storage. 2751 */ 2752 2753 static int 2754 sdbc_glcinfo(uintptr_t addr, uint_t flags, int argc, 2755 const mdb_arg_t *argv) 2756 { 2757 ss_centry_info_t gl_centry_info; 2758 /* for doing consistency check */ 2759 2760 ss_centry_info_t *gl_centry_info_start; 2761 ss_centry_info_t *nv_gl_centry_info_start; 2762 uintptr_t nv_addr; 2763 ss_centry_info_t nv_gl_centry_info; 2764 2765 /* options */ 2766 uint_t opt_a = FALSE; 2767 uintptr_t opt_b = MDB_BLKNUM; /* fba pos match */ 2768 uintptr_t opt_c = MDB_CD; 2769 uintptr_t opt_C = FALSE; /* consistency check */ 2770 uint_t opt_d = FALSE; 2771 2772 2773 2774 if (mdb_getopts(argc, argv, 2775 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 2776 'b', MDB_OPT_UINTPTR, &opt_b, 2777 'c', MDB_OPT_UINTPTR, &opt_c, 2778 'C', MDB_OPT_SETBITS, TRUE, &opt_C, 2779 'd', MDB_OPT_SETBITS, TRUE, &opt_d) != argc) 2780 return (DCMD_USAGE); 2781 2782 2783 if (!(flags & DCMD_ADDRSPEC)) { 2784 if (mdb_walk_dcmd("sdbc`sdbc_glcinfo", "sdbc`sdbc_glcinfo", 2785 argc, argv) == -1) { 2786 mdb_warn("failed to walk global centry info array"); 2787 return (DCMD_ERR); 2788 } 2789 return (DCMD_OK); 2790 } 2791 2792 if (DCMD_HDRSPEC(flags)) { 2793 mdb_printf("global cache entry info:\n"); 2794 } 2795 2796 if (mdb_vread(&gl_centry_info, sizeof (ss_centry_info_t), addr) == -1) { 2797 mdb_warn("failed to read gl_centry_info at 0x%p", addr); 2798 return (DCMD_ERR); 2799 } 2800 2801 2802 /* 2803 * default is to print entries initialized with a cd. return if 2804 * no options are selected and cd is invalid. 2805 */ 2806 if (!opt_a && (!OPT_B_SELECTED) && (!OPT_C_SELECTED) && !opt_d && 2807 (gl_centry_info.sc_cd == -1)) 2808 return (DCMD_OK); 2809 2810 2811 /* 2812 * opt_c is exclusive filter. if opt_c is selected and there 2813 * is no match on the cd then return 2814 */ 2815 if (!opt_a && 2816 (OPT_C_SELECTED && (gl_centry_info.sc_cd != opt_c))) 2817 return (DCMD_OK); 2818 2819 /* 2820 * opt_d and opt_b are inclusive. print if either one is chosen 2821 * and the selection condition is true. 2822 */ 2823 if (opt_a || 2824 (!opt_d && (!OPT_B_SELECTED)) || /* no options chosen */ 2825 (opt_d && gl_centry_info.sc_dirty) || 2826 (OPT_B_SELECTED && (gl_centry_info.sc_fpos == opt_b))) 2827 /*EMPTY*/; 2828 else 2829 return (DCMD_OK); 2830 2831 mdb_inc_indent(4); 2832 mdb_printf("%?-p cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2833 addr, 2834 gl_centry_info.sc_cd, 2835 gl_centry_info.sc_fpos, 2836 gl_centry_info.sc_dirty & 0xffff, 2837 gl_centry_info.sc_flag, cc_flag_bits); 2838 2839 if (opt_C) { 2840 /* get start of the cache entry metadata */ 2841 if (mdb_readvar(&gl_centry_info_start, 2842 "_sdbc_gl_centry_info") == -1) { 2843 mdb_warn("failed to read _sdbc_gl_centry_info"); 2844 /* not catastrophic */ 2845 goto end; 2846 } 2847 2848 /* get start of the nvram copy cache entry metadata */ 2849 if (mdb_readvar(&nv_gl_centry_info_start, 2850 "_sdbc_gl_centry_info_nvmem") == -1) { 2851 mdb_warn("failed to read _sdbc_gl_centry_info_nvmem"); 2852 /* not catastrophic */ 2853 goto end; 2854 } 2855 2856 nv_addr = (addr - (uintptr_t)gl_centry_info_start) + 2857 (uintptr_t)nv_gl_centry_info_start; 2858 2859 if (mdb_vread(&nv_gl_centry_info, sizeof (ss_centry_info_t), 2860 nv_addr) == -1) { 2861 mdb_warn("failed to read at nvmem_gl_info 0x%p", 2862 nv_addr); 2863 /* not catastophic, continue */ 2864 } else { 2865 2866 /* consistency check */ 2867 mdb_inc_indent(4); 2868 if (memcmp(&gl_centry_info, &nv_gl_centry_info, 2869 sizeof (ss_centry_info_t) != 0)) { 2870 mdb_warn( 2871 "nvram and host memory are NOT identical!"); 2872 mdb_printf("nvmem_gl_centry_info: "); 2873 mdb_printf( 2874 "%?-p cd %3-d fpos %10-d dirty %04x flag <%b>\n", 2875 nv_addr, 2876 nv_gl_centry_info.sc_cd, 2877 nv_gl_centry_info.sc_fpos, 2878 nv_gl_centry_info.sc_dirty & 0xffff, 2879 nv_gl_centry_info.sc_flag, cc_flag_bits); 2880 mdb_printf("\n"); 2881 } else 2882 mdb_printf("NVRAM ok\n"); 2883 2884 mdb_dec_indent(4); 2885 2886 } 2887 } 2888 2889 end: 2890 mdb_dec_indent(4); 2891 return (DCMD_OK); 2892 } 2893 2894 /* 2895 * dcmd to display ss_voldata_t structures and 2896 * do optional consistency check with the nvram copy 2897 * if configured for nvram safe storage. 2898 */ 2899 2900 static int 2901 sdbc_glfinfo(uintptr_t addr, uint_t flags, int argc, 2902 const mdb_arg_t *argv) 2903 { 2904 ss_voldata_t gl_file_info; 2905 /* for doing consistency check */ 2906 2907 ss_voldata_t *gl_file_info_start; 2908 ss_voldata_t *nv_gl_file_info_start; 2909 uintptr_t nv_addr; 2910 ss_voldata_t nv_gl_file_info; 2911 2912 /* options default: valid filename */ 2913 uint_t opt_a = FALSE; /* all */ 2914 uint_t opt_p = FALSE; /* PINNED */ 2915 uint_t opt_t = FALSE; /* attached */ 2916 uint_t opt_C = FALSE; /* consistency check */ 2917 2918 2919 2920 /* 2921 * possible enhancement -- match on filename, 2922 * or filename part (e.g. controller number) 2923 */ 2924 if (mdb_getopts(argc, argv, 2925 'a', MDB_OPT_SETBITS, TRUE, &opt_a, 2926 'C', MDB_OPT_SETBITS, TRUE, &opt_C, 2927 'p', MDB_OPT_SETBITS, TRUE, &opt_p, 2928 't', MDB_OPT_SETBITS, TRUE, &opt_t) != argc) 2929 return (DCMD_USAGE); 2930 2931 2932 if (!(flags & DCMD_ADDRSPEC)) { 2933 if (mdb_walk_dcmd("sdbc`sdbc_glfinfo", "sdbc`sdbc_glfinfo", 2934 argc, argv) == -1) { 2935 mdb_warn("failed to walk global file info array"); 2936 return (DCMD_ERR); 2937 } 2938 return (DCMD_OK); 2939 } 2940 2941 if (DCMD_HDRSPEC(flags)) { 2942 mdb_printf("global file entry info:\n"); 2943 } 2944 2945 if (mdb_vread(&gl_file_info, sizeof (ss_voldata_t), addr) == -1) { 2946 mdb_warn("failed to read gl_file_info at 0x%p", addr); 2947 return (DCMD_ERR); 2948 } 2949 2950 2951 /* 2952 * default is to print entries initialized with non-null filename. 2953 * return if no options are selected and filename is invalid. 2954 */ 2955 if (!opt_a && !opt_p && !opt_t && 2956 (strlen(gl_file_info.sv_volname) == 0)) 2957 return (DCMD_OK); 2958 2959 2960 if (opt_a || 2961 (!opt_p && !opt_t) || /* no options chosen */ 2962 (opt_p && (gl_file_info.sv_pinned != _SD_NO_HOST)) || 2963 (opt_t && (gl_file_info.sv_attached != _SD_NO_HOST))) 2964 /*EMPTY*/; 2965 else 2966 return (DCMD_OK); 2967 2968 mdb_inc_indent(4); 2969 mdb_printf("%?-p %s\n", addr, gl_file_info.sv_volname); 2970 mdb_printf("pinned %2-d attached %2-d devidsz %3-d\n", 2971 gl_file_info.sv_pinned, 2972 gl_file_info.sv_attached, 2973 gl_file_info.sv_devidsz); 2974 mdb_printf("devid %s\n", gl_file_info.sv_devid); 2975 2976 if (opt_C) { 2977 /* get start of the cache entry metadata */ 2978 if (mdb_readvar(&gl_file_info_start, 2979 "_sdbc_gl_file_info") == -1) { 2980 mdb_warn("failed to read _sdbc_gl_file_info"); 2981 /* not catastrophic */ 2982 goto end; 2983 } 2984 2985 /* get start of the nvram copy cache entry metadata */ 2986 if (mdb_readvar(&nv_gl_file_info_start, 2987 "_sdbc_gl_file_info_nvmem") == -1) { 2988 mdb_warn("failed to read _sdbc_gl_file_info_nvmem"); 2989 /* not catastrophic */ 2990 goto end; 2991 } 2992 2993 nv_addr = (addr - (uintptr_t)gl_file_info_start) + 2994 (uintptr_t)nv_gl_file_info_start; 2995 2996 if (mdb_vread(&nv_gl_file_info, sizeof (ss_voldata_t), 2997 nv_addr) == -1) { 2998 mdb_warn("failed to read nvmem_gl_info at 0x%p", 2999 nv_addr); 3000 /* not catastophic, continue */ 3001 } else { 3002 3003 /* consistency check */ 3004 mdb_inc_indent(4); 3005 if (memcmp(&gl_file_info, &nv_gl_file_info, 3006 sizeof (ss_centry_info_t) != 0)) { 3007 mdb_warn("nvram and host memory are NOT identical!"); 3008 mdb_printf("nvmem_gl_file_info: "); 3009 mdb_printf("%?-p %s\n", nv_addr, 3010 nv_gl_file_info.sv_volname); 3011 mdb_printf("pinned %2-d attached %2-d devidsz %3-d\n", 3012 nv_gl_file_info.sv_pinned, 3013 nv_gl_file_info.sv_attached, 3014 nv_gl_file_info.sv_devidsz); 3015 mdb_printf("devid %s\n", nv_gl_file_info.sv_devid); 3016 } else 3017 mdb_printf("NVRAM ok\n"); 3018 3019 mdb_dec_indent(4); 3020 3021 } 3022 } 3023 3024 end: 3025 mdb_dec_indent(4); 3026 mdb_printf("\n"); 3027 return (DCMD_OK); 3028 } 3029 3030 3031 /* 3032 * MDB module linkage information: 3033 * 3034 * We declare a list of structures describing our dcmds, and a function 3035 * named _mdb_init to return a pointer to our module information. 3036 */ 3037 3038 static const mdb_dcmd_t dcmds[] = { 3039 /* general dcmds */ 3040 { "sdbc_config", NULL, 3041 "display sdbc configuration information", 3042 sdbc_config }, 3043 { "sdbc_stats", NULL, 3044 "display sdbc stats information", 3045 sdbc_stats }, 3046 { "sdbc_vars", NULL, 3047 "display some sdbc variables, counters and addresses", 3048 sdbc_vars }, 3049 3050 /* cctl dcmds */ 3051 {"sdbc_cctl", "?[-vdhioV][-c cd][-b blknum]", 3052 "display sdbc cache ctl structures", 3053 sdbc_cctl, cctl_help }, 3054 {"sdbc_cchain", ":[-vdhioV][-c cd][-b blknum]", 3055 "display cache ctl structure cc_chain", 3056 sdbc_cchain, cchain_help }, 3057 {"sdbc_dchain", ":[-vdhioV][-c cd][-b blknum]", 3058 "display cache ctl structure dirty chain", 3059 sdbc_dchain, dchain_help }, 3060 {"sdbc_dmchain", ":[-vdhioV][-c cd][-b blknum]", 3061 "display dynamic memory cache ctl chain", 3062 sdbc_dmchain, dmchain_help }, 3063 {"sdbc_hashchain", ":[-vdhioV][-c cd][-b blknum]", 3064 "display a hash chain", sdbc_hashchain, hashchain_help }, 3065 {"sdbc_hashtable", "?[-vdhioV][-c cd][-b blknum]", 3066 "display hash table", sdbc_hashtable, hashtable_help }, 3067 {"sdbc_lru", "?[-vdhioV][-c cd][-b blknum]", 3068 "display the cache lru queue", 3069 sdbc_lru, lru_help }, 3070 #ifdef SAFESTORE 3071 /* wctl dcmds */ 3072 {"sdbc_wctl", "?[-vd][-c cd]", 3073 "display the write control structures", 3074 sdbc_wctl, wctl_help }, 3075 {"sdbc_wrq", "?[-vd][-c cd]", 3076 "display the write control queue", 3077 sdbc_wrq, wrq_help }, 3078 #endif /* SAFESTORE */ 3079 3080 /* others */ 3081 {"sdbc_cdinfo", "?[-av][-c cd]", 3082 "display cache descriptor information", 3083 sdbc_cdinfo, cdinfo_help }, 3084 #ifdef SAFESTORE 3085 {"sdbc_ftctl", "?[-vd][-c cd]", 3086 "display the fault tolerant control structures", 3087 sdbc_ftctl, ftctl_help }, 3088 #endif /* SAFESTORE */ 3089 {"sdbc_handles", "?[-avC][-c cd]", 3090 "display sdbc buffer handle information", 3091 sdbc_handles, handle_help }, 3092 3093 { "sdbc_dmqueues", NULL, 3094 "display sdbc dynamic memory buffer queues information", 3095 sdbc_dmqueues }, 3096 3097 /* "global" metadata dcmds */ 3098 {"sdbc_glcinfo", "?[-adC][-c cd][-b fbapos]", 3099 "display the global cache entry info structures", 3100 sdbc_glcinfo, glcinfo_help }, 3101 {"sdbc_glfinfo", "?[-aptC]", 3102 "display the global file info structures", 3103 sdbc_glfinfo, glfinfo_help }, 3104 { NULL } 3105 }; 3106 3107 static const mdb_walker_t walkers[] = { 3108 /* walkers of cctl list and arrays */ 3109 { "sdbc_cchain", "walk the cc_chain (alloc chain) of a cache ctl", 3110 sdbc_cchain_winit, sdbc_cchain_wstep, sdbc_cchain_wfini }, 3111 { "sdbc_cctl", "walk the cache ctl structure list", 3112 sdbc_cctl_winit, sdbc_cctl_wstep, sdbc_cctl_wfini }, 3113 { "sdbc_dchain", "walk the dirty chain of a cache ctl", 3114 sdbc_dchain_winit, sdbc_dchain_wstep, sdbc_dchain_wfini }, 3115 { "sdbc_dmchain", "walk the dynamic memory chain of a cache cctl", 3116 sdbc_dmchain_winit, sdbc_dmchain_wstep, sdbc_dmchain_wfini }, 3117 { "sdbc_hashchain", "walk a hash chain", 3118 sdbc_hashchain_winit, sdbc_hashchain_wstep, 3119 sdbc_hashchain_wfini }, 3120 { "sdbc_lru", "walk the cache lru queue", 3121 sdbc_lru_winit, sdbc_lru_wstep, sdbc_lru_wfini }, 3122 3123 #ifdef SAFESTORE 3124 /* walkers of wctl lists and arrays */ 3125 { "sdbc_wctl", "walk the allocated write ctl array", 3126 sdbc_wctl_winit, sdbc_wctl_wstep, sdbc_wctl_wfini }, 3127 { "sdbc_wrq", "walk the write ctl queue (free list)", 3128 sdbc_wrq_winit, sdbc_wrq_wstep, sdbc_wrq_wfini }, 3129 #endif /* SAFESTORE */ 3130 /* others */ 3131 { "sdbc_cdinfo", 3132 "walk the _sd_cache_files array of cache descriptor information", 3133 sdbc_cdinfo_winit, sdbc_cdinfo_wstep, sdbc_cdinfo_wfini }, 3134 #ifdef SAFESTORE 3135 { "sdbc_ftctl", 3136 "walk the allocated array of fault tolerant structures", 3137 sdbc_ftctl_winit, sdbc_ftctl_wstep, sdbc_ftctl_wfini }, 3138 #endif /* SAFESTORE */ 3139 { "sdbc_handles", "walk array of _sd_buf_handle_t structures", 3140 sdbc_handle_winit, sdbc_handle_wstep, sdbc_handle_wfini }, 3141 3142 /* walkers for metadata arrays */ 3143 { "sdbc_glcinfo", "walk the allocated global cache entry info array", 3144 sdbc_glcinfo_winit, sdbc_glcinfo_wstep, sdbc_glcinfo_wfini }, 3145 { "sdbc_glfinfo", "walk the allocated global file info array", 3146 sdbc_glfinfo_winit, sdbc_glfinfo_wstep, sdbc_glfinfo_wfini }, 3147 { NULL } 3148 }; 3149 3150 static const mdb_modinfo_t modinfo = { 3151 MDB_API_VERSION, dcmds, walkers 3152 }; 3153 3154 const mdb_modinfo_t * 3155 _mdb_init(void) 3156 { 3157 return (&modinfo); 3158 }