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
sdbc_config(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_hit_percent(uint_t hits,uint_t misses,char * type)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
sdbc_stats(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
display_var(char * name,enum vartype type)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
sdbc_vars(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
cctl_help_common(char * name)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
cctl_help()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
cchain_help()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
dchain_help()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
dmchain_help()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
hashchain_help()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
hashtable_help()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
lru_help()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
wctl_help_common(char * name)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
wctl_help()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
wrq_help()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
cdinfo_help()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
ftctl_help()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
handle_help()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
glcinfo_help()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
glfinfo_help()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
sdbc_cctl_winit(mdb_walk_state_t * wsp)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
sdbc_cctl_wstep(mdb_walk_state_t * wsp)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
sdbc_cctl_wfini(mdb_walk_state_t * wsp)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
sdbc_cchain_winit(mdb_walk_state_t * wsp)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
sdbc_cchain_wstep(mdb_walk_state_t * wsp)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
sdbc_cchain_wfini(mdb_walk_state_t * wsp)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
sdbc_dchain_winit(mdb_walk_state_t * wsp)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
sdbc_dchain_wstep(mdb_walk_state_t * wsp)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
sdbc_dchain_wfini(mdb_walk_state_t * wsp)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
sdbc_dmchain_winit(mdb_walk_state_t * wsp)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
sdbc_dmchain_wstep(mdb_walk_state_t * wsp)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
sdbc_dmchain_wfini(mdb_walk_state_t * wsp)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
sdbc_hashchain_winit(mdb_walk_state_t * wsp)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
sdbc_hashchain_wstep(mdb_walk_state_t * wsp)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
sdbc_hashchain_wfini(mdb_walk_state_t * wsp)1055 sdbc_hashchain_wfini(mdb_walk_state_t *wsp)
1056 {
1057 }
1058
1059 /*
1060 * walk the sdbc lru list
1061 */
1062 static int
sdbc_lru_winit(mdb_walk_state_t * wsp)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
sdbc_lru_wstep(mdb_walk_state_t * wsp)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
sdbc_lru_wfini(mdb_walk_state_t * wsp)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
sdbc_wctl_winit(mdb_walk_state_t * wsp)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
sdbc_wctl_wstep(mdb_walk_state_t * wsp)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
sdbc_wctl_wfini(mdb_walk_state_t * wsp)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
sdbc_wrq_winit(mdb_walk_state_t * wsp)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
sdbc_wrq_wstep(mdb_walk_state_t * wsp)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
sdbc_wrq_wfini(mdb_walk_state_t * wsp)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
sdbc_cdinfo_winit(mdb_walk_state_t * wsp)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
sdbc_cdinfo_wstep(mdb_walk_state_t * wsp)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
sdbc_cdinfo_wfini(mdb_walk_state_t * wsp)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
sdbc_ftctl_winit(mdb_walk_state_t * wsp)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
sdbc_ftctl_wstep(mdb_walk_state_t * wsp)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
sdbc_ftctl_wfini(mdb_walk_state_t * wsp)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
sdbc_handle_winit(mdb_walk_state_t * wsp)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
sdbc_handle_wstep(mdb_walk_state_t * wsp)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
sdbc_handle_wfini(mdb_walk_state_t * wsp)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
sdbc_glcinfo_winit(mdb_walk_state_t * wsp)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
sdbc_glcinfo_wstep(mdb_walk_state_t * wsp)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
sdbc_glcinfo_wfini(mdb_walk_state_t * wsp)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
sdbc_glfinfo_winit(mdb_walk_state_t * wsp)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
sdbc_glfinfo_wstep(mdb_walk_state_t * wsp)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
sdbc_glfinfo_wfini(mdb_walk_state_t * wsp)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
sdbc_cctl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_cchain(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_dchain(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_dmchain(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_hashchain(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
display_hash_table(_sd_hash_table_t * addr,_sd_hash_table_t * ht)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
display_hash_bucket(_sd_hash_bucket_t * addr,_sd_hash_bucket_t * hb)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
sdbc_hashtable(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_lru(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
print_wrq(_sd_writeq_t * wrq,uint_t verbose)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
sdbc_wctl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_wrq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_dmqueues(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_cdinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_ftctl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_handles(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_glcinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
sdbc_glfinfo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
_mdb_init(void)3155 _mdb_init(void)
3156 {
3157 return (&modinfo);
3158 }
3159