xref: /titanic_50/usr/src/cmd/mdb/common/modules/rdc/rdc.c (revision 174bc6499d233e329ecd3d98a880a7b07df16bfa)
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/types.h>
27 #include <sys/mdb_modapi.h>
28 
29 #include <sys/nsctl/nsctl.h>
30 #include <sys/unistat/spcs_s.h>
31 #include <sys/unistat/spcs_s_k.h>
32 
33 #include <rpc/auth.h>
34 #include <rpc/auth_unix.h>
35 #include <rpc/auth_des.h>
36 #include <rpc/svc.h>
37 #include <rpc/xdr.h>
38 #include <rpc/svc_soc.h>
39 
40 /* HACK HACK  so we can bring in rdc_io.h and friends */
41 #define	nstset_t	char
42 
43 #include <sys/nsctl/rdc.h>
44 #include <sys/nsctl/rdc_prot.h>
45 #include <sys/nsctl/rdc_ioctl.h>
46 #include <sys/nsctl/rdc_io.h>
47 #include <sys/nsctl/rdc_bitmap.h>
48 
49 #include <sys/nsctl/nsvers.h>
50 
51 
52 /*
53  * Walker for an array of rdc_k_info_t structures.
54  * A global walk is assumed to start at rdc_k_info.
55  */
56 
57 struct rdc_kinfo_winfo {
58 	uintptr_t start;
59 	uintptr_t end;
60 };
61 
62 char bitstr[33] = { '0' };
63 
64 static int
65 rdc_k_info_winit(mdb_walk_state_t *wsp)
66 {
67 	struct rdc_kinfo_winfo *winfo;
68 	rdc_k_info_t *rdc_k_info;
69 	int rdc_max_sets;
70 
71 	winfo = mdb_zalloc(sizeof (struct rdc_kinfo_winfo), UM_SLEEP);
72 
73 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
74 		mdb_warn("failed to read 'rdc_k_info'");
75 		mdb_free(winfo,  sizeof (struct rdc_kinfo_winfo));
76 		return (WALK_ERR);
77 	}
78 
79 	if (mdb_readvar(&rdc_max_sets, "rdc_max_sets") == -1) {
80 		mdb_warn("failed to read 'rdc_max_sets'");
81 		mdb_free(winfo, sizeof (struct rdc_kinfo_winfo));
82 		return (WALK_ERR);
83 	}
84 
85 	winfo->start = (uintptr_t)rdc_k_info;
86 	winfo->end = (uintptr_t)(rdc_k_info + rdc_max_sets);
87 
88 	if (wsp->walk_addr == NULL)
89 		wsp->walk_addr = winfo->start;
90 
91 	wsp->walk_data = winfo;
92 	return (WALK_NEXT);
93 }
94 
95 
96 static int
97 rdc_k_info_wstep(mdb_walk_state_t *wsp)
98 {
99 	struct rdc_kinfo_winfo *winfo = wsp->walk_data;
100 	int status;
101 
102 	if (wsp->walk_addr == NULL)
103 		return (WALK_DONE);
104 
105 	if (wsp->walk_addr >= winfo->end)
106 		return (WALK_DONE);
107 
108 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
109 	    wsp->walk_cbdata);
110 
111 	wsp->walk_addr += sizeof (rdc_k_info_t);
112 	return (status);
113 }
114 
115 
116 static void
117 rdc_k_info_wfini(mdb_walk_state_t *wsp)
118 {
119 	mdb_free(wsp->walk_data, sizeof (struct rdc_kinfo_winfo));
120 }
121 
122 /*
123  * Walker for an array of rdc_u_info_t structures.
124  * A global walk is assumed to start at rdc_u_info.
125  */
126 
127 struct rdc_uinfo_winfo {
128 	uintptr_t start;
129 	uintptr_t end;
130 };
131 
132 
133 static int
134 rdc_u_info_winit(mdb_walk_state_t *wsp)
135 {
136 	struct rdc_uinfo_winfo *winfo;
137 	rdc_u_info_t *rdc_u_info;
138 	int rdc_max_sets;
139 
140 	winfo = mdb_zalloc(sizeof (struct rdc_uinfo_winfo), UM_SLEEP);
141 
142 	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
143 		mdb_warn("failed to read 'rdc_u_info'");
144 		mdb_free(winfo,  sizeof (struct rdc_uinfo_winfo));
145 		return (WALK_ERR);
146 	}
147 
148 	if (mdb_readvar(&rdc_max_sets, "rdc_max_sets") == -1) {
149 		mdb_warn("failed to read 'rdc_max_sets'");
150 		mdb_free(winfo, sizeof (struct rdc_uinfo_winfo));
151 		return (WALK_ERR);
152 	}
153 
154 	winfo->start = (uintptr_t)rdc_u_info;
155 	winfo->end = (uintptr_t)(rdc_u_info + rdc_max_sets);
156 
157 	if (wsp->walk_addr == NULL)
158 		wsp->walk_addr = winfo->start;
159 
160 	wsp->walk_data = winfo;
161 	return (WALK_NEXT);
162 }
163 
164 
165 static int
166 rdc_u_info_wstep(mdb_walk_state_t *wsp)
167 {
168 	struct rdc_uinfo_winfo *winfo = wsp->walk_data;
169 	int status;
170 
171 	if (wsp->walk_addr == NULL)
172 		return (WALK_DONE);
173 
174 	if (wsp->walk_addr >= winfo->end)
175 		return (WALK_DONE);
176 
177 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
178 	    wsp->walk_cbdata);
179 
180 	wsp->walk_addr += sizeof (rdc_u_info_t);
181 	return (status);
182 }
183 
184 
185 static void
186 rdc_u_info_wfini(mdb_walk_state_t *wsp)
187 {
188 	mdb_free(wsp->walk_data, sizeof (struct rdc_uinfo_winfo));
189 }
190 
191 /*
192  * Walker for the rdc_if chain.
193  * A global walk is assumed to start at rdc_if_top.
194  */
195 
196 static int
197 rdc_if_winit(mdb_walk_state_t *wsp)
198 {
199 	if (wsp->walk_addr == NULL &&
200 	    mdb_readvar(&wsp->walk_addr, "rdc_if_top") == -1) {
201 		mdb_warn("unable to read 'rdc_if_top'");
202 		return (WALK_ERR);
203 	}
204 
205 	wsp->walk_data = mdb_zalloc(sizeof (rdc_if_t), UM_SLEEP);
206 
207 	return (WALK_NEXT);
208 }
209 
210 
211 static int
212 rdc_if_wstep(mdb_walk_state_t *wsp)
213 {
214 	int status;
215 
216 	if (wsp->walk_addr == NULL)
217 		return (WALK_DONE);
218 
219 	if (mdb_vread(wsp->walk_data,
220 	    sizeof (rdc_if_t), wsp->walk_addr) == -1) {
221 		mdb_warn("failed to read rdc_if at %p", wsp->walk_addr);
222 		return (WALK_DONE);
223 	}
224 
225 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
226 	    wsp->walk_cbdata);
227 
228 	wsp->walk_addr = (uintptr_t)(((rdc_if_t *)wsp->walk_data)->next);
229 	return (status);
230 }
231 
232 
233 static void
234 rdc_if_wfini(mdb_walk_state_t *wsp)
235 {
236 	mdb_free(wsp->walk_data, sizeof (rdc_if_t));
237 }
238 
239 /*
240  * Displays the asynchronous sleep q on the server.
241  */
242 /*ARGSUSED*/
243 static int
244 rdc_sleepq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
245 {
246 	rdc_sleepq_t sq;
247 
248 	if (!(flags & DCMD_ADDRSPEC))
249 		return (DCMD_USAGE);
250 	while (addr) {
251 		if (mdb_vread(&sq, sizeof (sq), addr) != sizeof (sq)) {
252 			mdb_warn("failed to read rdc_sleepq at %p", addr);
253 			return (DCMD_ERR);
254 		}
255 		mdb_printf("sequence number %u  qpos %d \n", sq.seq, sq.qpos);
256 		addr = (uintptr_t)sq.next;
257 	}
258 	return (DCMD_OK);
259 }
260 
261 /*
262  * display the header info for the pending diskq requests
263  */
264 /*ARGSUSED*/
265 static int
266 rdc_iohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
267 {
268 	io_hdr hdr;
269 
270 	if (!(flags & DCMD_ADDRSPEC))
271 		return (DCMD_USAGE);
272 
273 	while (addr) {
274 		if (mdb_vread(&hdr, sizeof (io_hdr), addr) != sizeof (io_hdr)) {
275 			mdb_warn("failed to read io_hdr at %p", addr);
276 			return (DCMD_ERR);
277 		}
278 		mdb_printf("iohdr: type %d pos %d qpos %d len %d flag 0x%x"
279 		" iostatus %x setid %d next %p\n", hdr.dat.type, hdr.dat.pos,
280 		hdr.dat.qpos, hdr.dat.len, hdr.dat.flag, hdr.dat.iostatus,
281 		hdr.dat.setid, hdr.dat.next);
282 
283 		addr = (uintptr_t)hdr.dat.next;
284 	}
285 	return (DCMD_OK);
286 }
287 
288 /*
289  * Display a krdc->group.
290  * Requires an address.
291  */
292 /*ARGSUSED*/
293 static int
294 rdc_group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
295 {
296 	struct rdc_group *group;
297 	disk_queue	*dq;
298 
299 	if (!(flags & DCMD_ADDRSPEC))
300 		return (DCMD_USAGE);
301 
302 
303 	group = mdb_zalloc(sizeof (*group), UM_GC);
304 
305 	if (mdb_vread(group, sizeof (*group), addr) != sizeof (*group)) {
306 		mdb_warn("failed to read rdc_group at %p", addr);
307 		return (DCMD_ERR);
308 	}
309 #ifdef XXXJET
310 	if (DCMD_HDRSPEC(flags)) {
311 		mdb_printf("%-?s  %8T%-8s  %8T%s\n", "ADDR", "MAJOR", "INUSE");
312 	}
313 #endif
314 	mdb_printf("count: %d  %8Twriter: %d  %8T flags: %d\n",
315 	    group->count, group->rdc_writer, group->flags);
316 	mdb_printf("thread num %d\n", group->rdc_thrnum);
317 
318 	dq = &group->diskq;
319 	if (RDC_IS_MEMQ(group)) {
320 		mdb_printf("queue type: Memory based\n");
321 	} else if (RDC_IS_DISKQ(group)) {
322 		mdb_printf("queue type: Disk based  %8Tqstate 0x%x\n",
323 		    QSTATE(dq));
324 	}
325 	mdb_printf("ra_queue head: 0x%p  %8Ttail 0x%p\n",
326 	    group->ra_queue.net_qhead, group->ra_queue.net_qtail);
327 	mdb_printf("ra_queue blocks: %d  %8Titems %d\n",
328 	    group->ra_queue.blocks, group->ra_queue.nitems);
329 	mdb_printf("ra_queue blockhwm: %d itemhwm: %d\n",
330 	    group->ra_queue.blocks_hwm, group->ra_queue.nitems_hwm);
331 	mdb_printf("ra_queue hwmhit: %d qfillsleep: %d\n",
332 	    group->ra_queue.hwmhit, group->ra_queue.qfill_sleeping);
333 	mdb_printf("ra_queue throttle: %ld\n",
334 	    group->ra_queue.throttle_delay);
335 
336 	if (RDC_IS_DISKQ(group)) {
337 		mdb_printf("head: %d %8Tnxtio: %d  %8Ttail %d %8Tlastail: %d\n",
338 		    QHEAD(dq), QNXTIO(dq), QTAIL(dq), LASTQTAIL(dq));
339 		mdb_printf("coalbounds: %d %8Tqwrap: %d\n", QCOALBOUNDS(dq),
340 		    QWRAP(dq));
341 		mdb_printf("blocks: %d  %8Titems %d qfflags 0x%x \n",
342 		    QBLOCKS(dq), QNITEMS(dq), group->ra_queue.qfflags);
343 		mdb_printf("diskq throttle: %ld %8Tflags: %x\n",
344 		    dq->throttle_delay, group->flags);
345 		mdb_printf("disk queue nitems_hwm: %d %8Tblocks_hwm: %d\n",
346 		    dq->nitems_hwm, dq->blocks_hwm);
347 		mdb_printf("diskqfd:   0x%p %8Tdisqrsrv: %d lastio: 0x%p\n",
348 		    group->diskqfd, group->diskqrsrv, dq->lastio);
349 		mdb_printf("outstanding req %d iohdrs 0x%p iohdrs_last 0x%p\n",
350 		    dq->hdrcnt, dq->iohdrs, dq->hdr_last);
351 	}
352 	mdb_printf("seq: %u\n", group->seq);
353 	mdb_printf("seqack: %u\n", group->seqack);
354 	mdb_printf("sleepq: 0x%p\n", group->sleepq);
355 	mdb_printf("asyncstall %d\n", group->asyncstall);
356 	mdb_printf("asyncdis %d\n", group->asyncdis);
357 
358 	mdb_inc_indent(4);
359 	if (group->sleepq) {
360 		rdc_sleepq((uintptr_t)group->sleepq, DCMD_ADDRSPEC,
361 		    0, 0);
362 	}
363 	mdb_dec_indent(4);
364 
365 	return (DCMD_OK);
366 }
367 
368 
369 /*
370  * Display a krdc->lsrv.
371  * Requires an address.
372  */
373 /*ARGSUSED*/
374 static int
375 rdc_srv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
376 {
377 	rdc_srv_t *lsrv;
378 	char name[MAX_RDC_HOST_SIZE];
379 
380 	if (!(flags & DCMD_ADDRSPEC))
381 		return (DCMD_USAGE);
382 
383 
384 	lsrv = mdb_zalloc(sizeof (*lsrv), UM_GC);
385 
386 	if (mdb_vread(lsrv, sizeof (*lsrv), addr) != sizeof (*lsrv)) {
387 		mdb_warn("failed to read rdc_srv at %p", addr);
388 		return (DCMD_ERR);
389 	}
390 
391 	if (mdb_readstr(name, sizeof (name),
392 		(uintptr_t)lsrv->ri_hostname) == -1) {
393 		mdb_warn("failed to read ri_hostname name at %p", addr);
394 		return (DCMD_ERR);
395 	}
396 
397 	mdb_printf("host: %s  %16Tri_knconf 0x%p\n", name, lsrv->ri_knconf);
398 
399 	mdb_printf("ri_addr: 0x%p  %8Tsecdata 0x%p\n",
400 	    addr + OFFSETOF(rdc_srv_t, ri_addr), lsrv->ri_secdata);
401 
402 	return (DCMD_OK);
403 }
404 
405 /*
406  * Display a rdc_if_t.
407  * Requires an address.
408  */
409 static int
410 rdc_if(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
411 {
412 	rdc_if_t *ifp;
413 
414 	if (!(flags & DCMD_ADDRSPEC)) {
415 		/*
416 		 * paranoid mode on: qualify walker name with module name
417 		 * using '`' syntax.
418 		 */
419 		if (mdb_walk_dcmd("rdc`rdc_if",
420 			"rdc`rdc_if", argc, argv) == -1) {
421 			mdb_warn("failed to walk 'rdc_if'");
422 			return (DCMD_ERR);
423 		}
424 		return (DCMD_OK);
425 	}
426 
427 	ifp = mdb_zalloc(sizeof (*ifp), UM_GC);
428 
429 	if (mdb_vread(ifp, sizeof (*ifp), addr) != sizeof (*ifp)) {
430 		mdb_warn("failed to read rdc_srv at %p", addr);
431 		return (DCMD_ERR);
432 	}
433 
434 	mdb_printf("next: 0x%p  %8Tsrv 0x%p\n", ifp->next, ifp->srv);
435 	mdb_printf("if_addr: 0x%p  %8Tr_ifaddr 0x%p\n",
436 	    addr + OFFSETOF(rdc_if_t, ifaddr),
437 	    addr + OFFSETOF(rdc_if_t, r_ifaddr));
438 	mdb_printf("if_down: %d  %8Tprimary %d  %8Tsecondary  %d\n",
439 		ifp->if_down, ifp->isprimary, ifp->issecondary);
440 	mdb_printf("version %d  %8Tnoping  %d\n", ifp->rpc_version,
441 		ifp->no_ping);
442 	mdb_printf("\n");
443 
444 	return (DCMD_OK);
445 }
446 
447 
448 /*
449  * Display a rdc_buf_t
450  * Requires an address.
451  */
452 /*ARGSUSED*/
453 static int
454 rdc_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
455 {
456 	rdc_buf_t *buf;
457 
458 	if (!(flags & DCMD_ADDRSPEC))
459 		return (DCMD_USAGE);
460 
461 
462 	buf = mdb_zalloc(sizeof (*buf), UM_GC);
463 
464 	if (mdb_vread(buf, sizeof (*buf), addr) != sizeof (*buf)) {
465 		mdb_warn("failed to read rdc_buf at %p", addr);
466 		return (DCMD_ERR);
467 	}
468 
469 	mdb_printf("nsc_buf fd: 0x%p  %8Tvec 0x%p\n",
470 	    buf->rdc_bufh.sb_fd, buf->rdc_bufh.sb_vec);
471 
472 	mdb_printf("nsc_buf pos: %d  %8Tlen %d\n",
473 	    buf->rdc_bufh.sb_pos, buf->rdc_bufh.sb_len);
474 
475 	mdb_printf("nsc_buf flag: 0x%x  %8Terror %d\n",
476 	    buf->rdc_bufh.sb_flag, buf->rdc_bufh.sb_error);
477 
478 	mdb_printf("anon_buf : 0x%p  %8Tfd 0x%p  %8Tbufp  0x%p\n",
479 	    buf->rdc_anon, buf->rdc_fd, buf->rdc_bufp);
480 
481 	mdb_printf("vsize: %d  %8Tflags 0x%x\n",
482 	    buf->rdc_vsize, buf->rdc_flags);
483 
484 	return (DCMD_OK);
485 }
486 
487 /*ARGSUSED*/
488 static int
489 rdc_aio(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
490 {
491 	rdc_aio_t *aio;
492 
493 	if (!(flags & DCMD_ADDRSPEC))
494 		return (DCMD_USAGE);
495 
496 	aio = mdb_zalloc(sizeof (*aio), UM_GC);
497 
498 	if (mdb_vread(aio, sizeof (*aio), addr) != sizeof (*aio)) {
499 		mdb_warn("failed to read rdc_aio at %p", addr);
500 		return (DCMD_ERR);
501 	}
502 	mdb_printf("rdc_aio next: %p %8T nsc_buf: %p %8T nsc_qbuf %p\n",
503 	    aio->next, aio->handle, aio->qhandle);
504 	mdb_printf("pos: %d len: %d qpos: %d flag: %x iostatus: %d index: %d"
505 	    " seq: %d\n", aio->pos, aio->len, aio->qpos, aio->flag,
506 	    aio->iostatus, aio->index, aio->seq);
507 	return (DCMD_OK);
508 }
509 
510 /*ARGSUSED*/
511 static int
512 rdc_dset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
513 {
514 	rdc_net_dataset_t *dset;
515 
516 	if (!(flags & DCMD_ADDRSPEC))
517 		return (DCMD_USAGE);
518 
519 	dset = mdb_zalloc(sizeof (*dset), UM_GC);
520 
521 	if (mdb_vread(dset, sizeof (*dset), addr) != sizeof (*dset)) {
522 		mdb_warn("failed to read dset at %p", addr);
523 		return (DCMD_ERR);
524 	}
525 	mdb_printf("dset id: %d %8T dset inuse: %d %8T dset delpend: %d\n",
526 	    dset->id, dset->inuse, dset->delpend);
527 	mdb_printf("dset items: %d %8T dset head %p %8T dset tail %p \n",
528 	    dset->nitems, dset->head, dset->tail);
529 	mdb_printf("dset pos %d %8T dset len %d\n", dset->pos, dset->fbalen);
530 
531 	return (DCMD_OK);
532 }
533 /*
534  * Display a single rdc_k_info structure.
535  * If called with no address, performs a global walk of all rdc_k_info.
536  * -a : all (i.e. display all devices, even if disabled
537  * -v : verbose
538  */
539 
540 const mdb_bitmask_t sv_flag_bits[] = {
541 	{ "NSC_DEVICE", NSC_DEVICE, NSC_DEVICE },
542 	{ "NSC_CACHE", NSC_CACHE, NSC_CACHE },
543 	{ NULL, 0, 0 }
544 };
545 
546 static int
547 rdc_kinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
548 {
549 	rdc_k_info_t *krdc;
550 	rdc_u_info_t *rdc_u_info, *urdc;
551 	int a_opt, v_opt;
552 	int dev_t_chars;
553 
554 	a_opt = v_opt = FALSE;
555 	dev_t_chars = sizeof (dev_t) * 2;	/* # chars to display dev_t */
556 
557 	if (mdb_getopts(argc, argv,
558 	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
559 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
560 		return (DCMD_USAGE);
561 
562 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
563 	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
564 
565 	if (!(flags & DCMD_ADDRSPEC)) {
566 		/*
567 		 * paranoid mode on: qualify walker name with module name
568 		 * using '`' syntax.
569 		 */
570 		if (mdb_walk_dcmd("rdc`rdc_kinfo",
571 			"rdc`rdc_kinfo", argc, argv) == -1) {
572 			mdb_warn("failed to walk 'rdc_kinfo'");
573 			return (DCMD_ERR);
574 		}
575 		return (DCMD_OK);
576 	}
577 	if (DCMD_HDRSPEC(flags)) {
578 		mdb_printf("%-?s  %8T%-*s  %8T%s\n", "ADDR",
579 		    dev_t_chars, "TFLAG", "STATE");
580 	}
581 
582 	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
583 		mdb_warn("failed to read rdc_k_info at %p", addr);
584 		return (DCMD_ERR);
585 	}
586 
587 	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
588 		mdb_warn("failed to read 'rdc_u_info'");
589 		return (DCMD_ERR);
590 	}
591 
592 	urdc = &rdc_u_info[krdc->index];
593 
594 	if (!a_opt && ((krdc->type_flag & RDC_CONFIGURED) == 0))
595 		return (DCMD_OK);
596 
597 	mdb_printf("%?p  %8T%0*lx  %8T", addr, dev_t_chars, krdc->type_flag);
598 
599 
600 	if (krdc->type_flag & RDC_DISABLEPEND)
601 		mdb_printf(" disable pending");
602 	if (krdc->type_flag &  RDC_ASYNCMODE)
603 		mdb_printf(" async");
604 	if (krdc->type_flag & RDC_RESUMEPEND)
605 		mdb_printf(" resume pending");
606 	if (krdc->type_flag & RDC_BUSYWAIT)
607 		mdb_printf(" busywait");
608 #ifdef RDC_SMALLIO
609 	if (krdc->type_flag & RDC_SMALLIO)
610 		mdb_printf(" smallio");
611 #endif
612 
613 	mdb_printf("\n");
614 
615 	if (!v_opt)
616 		return (DCMD_OK);
617 
618 	/*
619 	 * verbose - print the rest of the structure as well.
620 	 */
621 
622 	mdb_inc_indent(4);
623 
624 	mdb_printf("index: %d  %8Trindex: %d  %8Tbusyc: %d  %8Tmaxfbas:  %d\n",
625 	    krdc->index, krdc->remote_index, krdc->busy_count, krdc->maxfbas);
626 
627 	mdb_printf("info_dev:  0x%p %8Tiodev: 0x%p  %8T %8T vers %d\n",
628 	krdc->devices, krdc->iodev, krdc->rpc_version);
629 
630 	mdb_printf("iokstats:  0x%p\n", krdc->io_kstats);
631 	mdb_printf("group:  0x%p %8Tgroup_next:  0x%p\n",
632 		krdc->group, krdc->group_next);
633 	mdb_printf("group lock: 0x%p aux_state: %d\n",
634 	    &krdc->group->lock, krdc->aux_state);
635 
636 	mdb_inc_indent(4);
637 	if (krdc->type_flag & RDC_ASYNCMODE) {
638 		rdc_group((uintptr_t)krdc->group, DCMD_ADDRSPEC, 0, 0);
639 	}
640 	mdb_dec_indent(4);
641 
642 	mdb_printf("servinfo:  0x%p %8Tintf:  0x%p\nbitmap: 0x%p  %8T"
643 	    "bitmap_ref:  0x%p\n",
644 	    krdc->lsrv, krdc->intf, krdc->dcio_bitmap, krdc->bitmap_ref);
645 
646 	mdb_printf("bmap_size:  %d %8Tbmaprsrv: %d%8T bmap_write:  %d\n",
647 	    krdc->bitmap_size, krdc->bmaprsrv, krdc->bitmap_write);
648 
649 	mdb_printf("bitmapfd:  0x%p %8Tremote_fd: 0x%p  %8T\n", krdc->bitmapfd,
650 	    krdc->remote_fd);
651 
652 	mdb_printf("net_dataset:  0x%p %8Tdisk_status: %d  %8T\n",
653 	    krdc->net_dataset, krdc->disk_status);
654 
655 	mdb_printf("many:  0x%p %8Tmulti: 0x%p  %8T\n", krdc->many_next,
656 	    krdc->multi_next);
657 
658 	mdb_printf("rdc_uinfo: 0x%p\n\n", urdc);
659 	mdb_dec_indent(4);
660 	return (DCMD_OK);
661 }
662 
663 
664 static int
665 rdc_uinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
666 {
667 	rdc_u_info_t *urdc;
668 	rdc_k_info_t *rdc_k_info, *krdc, krdc1;
669 	rdc_group_t grp;
670 	disk_queue *dqp = NULL;
671 	int a_opt, v_opt;
672 	int dev_t_chars;
673 	int rdcflags;
674 
675 	a_opt = v_opt = FALSE;
676 	dev_t_chars = sizeof (dev_t) * 2;	/* # chars to display dev_t */
677 
678 	if (mdb_getopts(argc, argv,
679 	    'a', MDB_OPT_SETBITS, TRUE, &a_opt,
680 	    'v', MDB_OPT_SETBITS, TRUE, &v_opt) != argc)
681 		return (DCMD_USAGE);
682 
683 	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
684 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
685 
686 	if (!(flags & DCMD_ADDRSPEC)) {
687 		/*
688 		 * paranoid mode on: qualify walker name with module name
689 		 * using '`' syntax.
690 		 */
691 		if (mdb_walk_dcmd("rdc`rdc_uinfo",
692 			"rdc`rdc_uinfo", argc, argv) == -1) {
693 			mdb_warn("failed to walk 'rdc_uinfo'");
694 			return (DCMD_ERR);
695 		}
696 		return (DCMD_OK);
697 	}
698 	if (DCMD_HDRSPEC(flags)) {
699 		mdb_printf("%-?s  %8T%-*s  %8T%s\n", "ADDR",
700 		    dev_t_chars, "FLAG", "STATE");
701 	}
702 
703 	if (mdb_vread(urdc, sizeof (*urdc), addr) != sizeof (*urdc)) {
704 		mdb_warn("failed to read rdc_u_info at %p", addr);
705 		return (DCMD_ERR);
706 	}
707 
708 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
709 		mdb_warn("failed to read 'rdc_k_info'");
710 		return (DCMD_ERR);
711 	}
712 
713 	krdc = &rdc_k_info[urdc->index];
714 
715 	if (!a_opt && ((urdc->flags & RDC_ENABLED) == 0))
716 		return (DCMD_OK);
717 
718 
719 	if (mdb_vread(&krdc1, sizeof (krdc1),
720 	    (uintptr_t)krdc) != sizeof (krdc1)) {
721 		mdb_warn("failed to read 'rdc_k_info1'");
722 		return (DCMD_ERR);
723 	}
724 
725 	if (krdc1.group) {
726 		if (mdb_vread(&grp, sizeof (grp),
727 		    (uintptr_t)krdc1.group) != sizeof (grp)) {
728 			mdb_warn("failed to read group info ");
729 			return (DCMD_ERR);
730 		}
731 		dqp = &grp.diskq;
732 	}
733 
734 	rdcflags = (urdc->flags | urdc->sync_flags | urdc->bmap_flags);
735 	mdb_printf("%?p  %8T%0*lx  %8T", addr, dev_t_chars, rdcflags);
736 
737 
738 	if (rdcflags & RDC_PRIMARY)
739 		mdb_printf(" primary");
740 	if (rdcflags &  RDC_SLAVE)
741 		mdb_printf(" slave");
742 	if (rdcflags &  RDC_SYNCING)
743 		mdb_printf(" syncing");
744 	if (rdcflags &  RDC_SYNC_NEEDED)
745 		mdb_printf(" sync_need");
746 	if (rdcflags &  RDC_RSYNC_NEEDED)
747 		mdb_printf(" rsync_need");
748 	if (rdcflags & RDC_LOGGING)
749 		mdb_printf(" logging");
750 	if (rdcflags & RDC_QUEUING)
751 		mdb_printf(" queuing");
752 	if (rdcflags & RDC_DISKQ_FAILED)
753 		mdb_printf(" diskq failed");
754 	if (rdcflags & RDC_VOL_FAILED)
755 		mdb_printf(" vol failed");
756 	if (rdcflags & RDC_BMP_FAILED)
757 		mdb_printf(" bmp failed");
758 	if (rdcflags & RDC_ASYNC)
759 		mdb_printf(" async");
760 	if (rdcflags & RDC_CLR_AFTERSYNC)
761 		mdb_printf(" clr_bitmap_aftersync");
762 	if (dqp) {
763 		if (IS_QSTATE(dqp, RDC_QNOBLOCK))
764 			mdb_printf(" noblock");
765 	}
766 #ifdef RDC_SMALLIO
767 	if (rdcflags & RDC_SMALLIO)
768 		mdb_printf(" smallio");
769 #endif
770 
771 	mdb_printf("\n");
772 
773 	if (!v_opt)
774 		return (DCMD_OK);
775 
776 	/*
777 	 * verbose - print the rest of the structure as well.
778 	 */
779 
780 	mdb_inc_indent(4);
781 	mdb_printf("\n");
782 
783 	mdb_printf("primary: %s  %8Tfile: %s  \nbitmap: %s  ",
784 	    urdc->primary.intf, urdc->primary.file, urdc->primary.bitmap);
785 	mdb_printf("netbuf: 0x%p\n", addr + OFFSETOF(rdc_set_t, primary));
786 	mdb_printf("secondary: %s  %8Tfile: %s  \nbitmap: %s  ",
787 	    urdc->secondary.intf, urdc->secondary.file, urdc->secondary.bitmap);
788 	mdb_printf("netbuf: 0x%p\n", addr + OFFSETOF(rdc_set_t, secondary));
789 
790 	mdb_printf("sflags:  %d %8Tbflags: %d%8T mflags:  %d\n",
791 		urdc->sync_flags, urdc->bmap_flags, urdc->mflags);
792 	mdb_printf("index:  %d %8Tsync_pos: %d%8T vsize:  %d\n",
793 		urdc->index, urdc->sync_pos, urdc->volume_size);
794 	mdb_printf("setid:  %d %8Tbits set:  %d %8Tautosync: %d\n",
795 		urdc->setid, urdc->bits_set, urdc->autosync);
796 	mdb_printf("maxqfbas:  %d %8Tmaxqitems: %d\n",
797 		urdc->maxqfbas, urdc->maxqitems);
798 	mdb_printf("netconfig:  %p\n", urdc->netconfig);
799 	mdb_printf("group:  %s %8TdirectIO: %s\n",
800 		urdc->group_name, urdc->direct_file);
801 	mdb_printf("diskqueue: %s ", urdc->disk_queue);
802 	if (dqp) {
803 		mdb_printf("diskqsize: %d\n", QSIZE(dqp));
804 	} else {
805 		mdb_printf("\n");
806 	}
807 	mdb_printf("rdc_k_info: 0x%p\n", krdc);
808 	mdb_printf("\n");
809 	mdb_dec_indent(4);
810 
811 	mdb_printf("\n");
812 	return (DCMD_OK);
813 }
814 
815 /*ARGSUSED*/
816 static int
817 rdc_infodev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
818 {
819 	rdc_info_dev_t *infodev;
820 	_rdc_info_dev_t *infp;
821 
822 	if (!(flags & DCMD_ADDRSPEC))
823 		return (DCMD_USAGE);
824 
825 	infodev = mdb_zalloc(sizeof (*infodev), UM_GC);
826 	infp = mdb_zalloc(sizeof (*infp), UM_GC);
827 
828 	if (mdb_vread(infodev, sizeof (*infodev), addr) != sizeof (*infodev)) {
829 		mdb_warn("failed to read rdc_infodev at 0x%p\n", addr);
830 		return (DCMD_ERR);
831 	}
832 
833 	infp = &infodev->id_cache_dev;
834 	mdb_inc_indent(4);
835 
836 	mdb_printf("id_next: 0x%p\n", infodev->id_next);
837 	mdb_printf("id_cache_dev:\n");
838 
839 	mdb_inc_indent(4);
840 	mdb_printf("bi_fd: 0x%p %8Tbi_iodev: 0x%p %8Tbi_krdc 0x%p\n",
841 	    infp->bi_fd, infp->bi_iodev, infp->bi_krdc);
842 	mdb_printf("bi_rsrv: %d %8Tbi_orsrv: %d %8Tbi_failed: %d %8T\n"
843 	    "bi_ofailed: %d %8Tbi_flag: %d\n", infp->bi_rsrv, infp->bi_orsrv,
844 	    infp->bi_failed, infp->bi_ofailed, infp->bi_flag);
845 
846 	infp = &infodev->id_raw_dev;
847 
848 	mdb_dec_indent(4);
849 	mdb_printf("id_cache_dev:\n");
850 	mdb_inc_indent(4);
851 
852 	mdb_printf("bi_fd: 0x%p %8Tbi_iodev: 0x%p %8Tbi_krdc 0x%p\n",
853 	    infp->bi_fd, infp->bi_iodev, infp->bi_krdc);
854 	mdb_printf("bi_rsrv: %d %8Tbi_orsrv: %d %8Tbi_failed: %d %8T\n"
855 	    "bi_ofailed: %d %8Tbi_flag: %d\n", infp->bi_rsrv, infp->bi_orsrv,
856 	    infp->bi_failed, infp->bi_ofailed, infp->bi_flag);
857 
858 	mdb_dec_indent(4);
859 
860 	mdb_printf("id_sets: %d %8Tid_release: %d %8Tid_flag %d",
861 	    infodev->id_sets, infodev->id_release, infodev->id_flag);
862 
863 	if (infodev->id_flag & RDC_ID_CLOSING) {
864 		mdb_printf("closing");
865 	}
866 	mdb_printf("\n");
867 
868 	mdb_dec_indent(4);
869 	return (DCMD_OK);
870 }
871 
872 /*
873  * Display general sv module information.
874  */
875 
876 #define	rdc_get_print(kvar, str, fmt, val)		\
877 	if (mdb_readvar(&(val), #kvar) == -1) {		\
878 		mdb_dec_indent(4);			\
879 		mdb_warn("unable to read '" #kvar "'");	\
880 		return (DCMD_ERR);			\
881 	}						\
882 	mdb_printf("%-20s" fmt "\n", str ":", val)
883 
884 /*ARGSUSED*/
885 static int
886 rdc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
887 {
888 	int maj, min, mic, baseline, i;
889 
890 	if (argc != 0)
891 		return (DCMD_USAGE);
892 
893 	if (mdb_readvar(&maj, "sndr_major_rev") == -1) {
894 		mdb_warn("unable to read 'sndr_major_rev'");
895 		return (DCMD_ERR);
896 	}
897 
898 	if (mdb_readvar(&min, "sndr_minor_rev") == -1) {
899 		mdb_warn("unable to read 'sndr_minor_rev'");
900 		return (DCMD_ERR);
901 	}
902 
903 	if (mdb_readvar(&mic, "sndr_micro_rev") == -1) {
904 		mdb_warn("unable to read 'sndr_micro_rev'");
905 		return (DCMD_ERR);
906 	}
907 
908 	if (mdb_readvar(&baseline, "sndr_baseline_rev") == -1) {
909 		mdb_warn("unable to read 'sndr_baseline_rev'");
910 		return (DCMD_ERR);
911 	}
912 
913 	mdb_printf("Remote Mirror module version: kernel %d.%d.%d.%d; "
914 		    "mdb %d.%d.%d.%d\n", maj, min, mic, baseline,
915 	    ISS_VERSION_MAJ, ISS_VERSION_MIN, ISS_VERSION_MIC, ISS_VERSION_NUM);
916 	mdb_inc_indent(4);
917 
918 	rdc_get_print(rdc_debug, "debug", "%d", i);
919 	rdc_get_print(rdc_bitmap_mode, "bitmap mode", "%d", i);
920 	rdc_get_print(rdc_max_sets, "max sndr devices", "%d", i);
921 	rdc_get_print(rdc_rpc_tmout, "client RPC timeout", "%d", i);
922 	rdc_get_print(rdc_health_thres, "health threshold", "%d", i);
923 	rdc_get_print(MAX_RDC_FBAS, "max trans fba", "%d", i);
924 
925 	mdb_dec_indent(4);
926 	return (DCMD_OK);
927 }
928 
929 static int
930 rdc_k2u(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
931 {
932 	rdc_k_info_t *krdc;
933 	rdc_u_info_t *rdc_u_info, *urdc;
934 	int rc;
935 
936 	if (!(flags & DCMD_ADDRSPEC))
937 		return (DCMD_USAGE);
938 
939 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
940 	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
941 
942 	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
943 		mdb_warn("failed to read krdc at %p", addr);
944 		return (DCMD_ERR);
945 	}
946 
947 	if (mdb_readvar(&rdc_u_info, "rdc_u_info") == -1) {
948 		mdb_warn("failed to read 'rdc_u_info'");
949 		return (DCMD_ERR);
950 	}
951 
952 	urdc = &rdc_u_info[krdc->index];
953 
954 	rc = rdc_uinfo((uintptr_t)urdc, DCMD_ADDRSPEC, argc, argv);
955 	return (rc);
956 }
957 
958 static int
959 rdc_u2k(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
960 {
961 	rdc_u_info_t *urdc;
962 	rdc_k_info_t *rdc_k_info, *krdc;
963 	int rc;
964 
965 	if (!(flags & DCMD_ADDRSPEC))
966 		return (DCMD_USAGE);
967 
968 	urdc = mdb_zalloc(sizeof (*urdc), UM_GC);
969 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
970 
971 	if (mdb_vread(urdc, sizeof (*urdc), addr) != sizeof (*urdc)) {
972 		mdb_warn("failed to read urdc at %p\n", addr);
973 		return (DCMD_ERR);
974 	}
975 
976 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
977 		mdb_warn("failed to read 'rdc_k_info'");
978 		return (DCMD_ERR);
979 	}
980 
981 	krdc = &rdc_k_info[urdc->index];
982 
983 	rc = rdc_kinfo((uintptr_t)krdc, DCMD_ADDRSPEC, argc, argv);
984 	return (rc);
985 }
986 
987 #ifdef DEBUG
988 /*
989  * This routine is used to set the seq field in the rdc_kinfo->group
990  * structure. Used to test that the queue code handles the integer
991  * overflow correctly.
992  * Takes two arguments index and value.
993  * The index is the index into the kinfo structure array and
994  * the value is the new value to set into the seq field.
995  */
996 /*ARGSUSED*/
997 static int
998 rdc_setseq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
999 {
1000 	rdc_k_info_t *rdc_k_info;
1001 	rdc_group_t *group;
1002 	int index;
1003 	uint_t val;
1004 	uintptr_t pokeaddr;
1005 
1006 	if (argc != 2) {
1007 		mdb_warn("must have two arguments, index and value\n");
1008 		return (DCMD_ERR);
1009 	}
1010 
1011 	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1012 	val = (uint_t)mdb_strtoull(argv[1].a_un.a_str);
1013 
1014 	/*
1015 	 * Find out where in memory the seq field.
1016 	 * The structure offset first.
1017 	 */
1018 
1019 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1020 		mdb_warn("failed to read 'rdc_k_info'");
1021 		return (DCMD_ERR);
1022 	}
1023 	pokeaddr = (uintptr_t)&rdc_k_info[index].group;
1024 	if (mdb_vread(&group, sizeof (rdc_group_t *), pokeaddr) !=
1025 	    sizeof (rdc_group_t *)) {
1026 		mdb_warn("failed to fetch the group structure for set %d\n",
1027 		    index);
1028 		return (DCMD_ERR);
1029 	}
1030 	pokeaddr = (uintptr_t)(&group->seq);
1031 	if (mdb_vwrite(&val, sizeof (val), pokeaddr) != sizeof (val)) {
1032 		mdb_warn("failed to write seq at %p\n", pokeaddr);
1033 		return (DCMD_ERR);
1034 	}
1035 
1036 	return (DCMD_OK);
1037 }
1038 
1039 
1040 /*
1041  * This routine is used to set the seqack field in the rdc_kinfo->group
1042  * structure. Used to test that the queue code handles the integer
1043  * overflow correctly.
1044  * Takes two arguments index and value.
1045  * The index is the index into the kinfo structure array and
1046  * the value is the new value to set into the seqack field.
1047  */
1048 /*ARGSUSED*/
1049 static int
1050 rdc_setseqack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1051 {
1052 	rdc_k_info_t *rdc_k_info;
1053 	rdc_group_t *group;
1054 	int index;
1055 	uint_t val;
1056 	uintptr_t pokeaddr;
1057 
1058 	if (argc != 2) {
1059 		mdb_warn("must have two arguments, index and value\n");
1060 		return (DCMD_ERR);
1061 	}
1062 
1063 	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1064 	val = (uint_t)mdb_strtoull(argv[1].a_un.a_str);
1065 
1066 	/*
1067 	 * Find out where in memory the seqack field.
1068 	 * The structure offset first.
1069 	 */
1070 
1071 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1072 		mdb_warn("failed to read 'rdc_k_info'");
1073 		return (DCMD_ERR);
1074 	}
1075 	pokeaddr = (uintptr_t)&rdc_k_info[index].group;
1076 	if (mdb_vread(&group, sizeof (rdc_group_t *), pokeaddr) !=
1077 	    sizeof (rdc_group_t *)) {
1078 		mdb_warn("failed to fetch the group structure for set %d\n",
1079 		    index);
1080 		return (DCMD_ERR);
1081 	}
1082 	pokeaddr = (uintptr_t)(&group->seqack);
1083 	if (mdb_vwrite(&val, sizeof (val), pokeaddr) != sizeof (val)) {
1084 		mdb_warn("failed to write seqack at %p\n", pokeaddr);
1085 		return (DCMD_ERR);
1086 	}
1087 
1088 	return (DCMD_OK);
1089 }
1090 
1091 /*
1092  * random define printing stuff, just does the define, and print the result
1093  */
1094 /*ARGSUSED*/
1095 static int
1096 fba_to_log_num(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1097 {
1098 	int num;
1099 	if (argc < 1) {
1100 		mdb_warn("must have an argument\n");
1101 		return (DCMD_ERR);
1102 	}
1103 	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1104 	num = FBA_TO_LOG_NUM(num);
1105 	mdb_printf("LOG NUM: %d (0x%x)", num, num);
1106 
1107 	return (DCMD_OK);
1108 }
1109 
1110 /*ARGSUSED*/
1111 static int
1112 log_to_fba_num(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1113 {
1114 	int num;
1115 	if (argc < 1) {
1116 		mdb_warn("must have an argument\n");
1117 		return (DCMD_ERR);
1118 	}
1119 	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1120 	num = LOG_TO_FBA_NUM(num);
1121 	mdb_printf("LOG NUM: %d (0x%x)", num, num);
1122 
1123 	return (DCMD_OK);
1124 }
1125 
1126 static int
1127 bmap_bit_isset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1128 {
1129 	int st;
1130 	int i, num;
1131 	rdc_k_info_t *krdc;
1132 	unsigned char *bmap;
1133 	unsigned char *bmaddr;
1134 	int bmsize;
1135 
1136 	if (!(flags & DCMD_ADDRSPEC))
1137 		return (DCMD_USAGE);
1138 
1139 	if (argc < 1) {
1140 		mdb_warn("must have an argument\n");
1141 		return (DCMD_ERR);
1142 	}
1143 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
1144 
1145 	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
1146 		mdb_warn("failed to read rdc_k_info at %p", addr);
1147 		return (DCMD_ERR);
1148 	}
1149 
1150 	bmaddr = krdc->dcio_bitmap;
1151 	bmsize = krdc->bitmap_size;
1152 	bmap = mdb_zalloc(bmsize, UM_GC);
1153 	if (mdb_vread(bmap, bmsize, (uintptr_t)bmaddr) != bmsize) {
1154 		mdb_warn("failed to read bitmap");
1155 		return (DCMD_ERR);
1156 	}
1157 
1158 	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1159 	st = FBA_TO_LOG_NUM(num);
1160 	i = BMAP_BIT_ISSET(bmap, st);
1161 	mdb_printf(" BIT (%d) for %x %s set (%02x)", st, num, i?"IS":"IS NOT",
1162 	    bmap[IND_BYTE(st)] & 0xff);
1163 
1164 	return (DCMD_OK);
1165 }
1166 
1167 static int
1168 bmap_bitref_isset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1169 {
1170 	int num, st, i;
1171 	rdc_k_info_t *krdc;
1172 	unsigned char *brefbyte;
1173 	unsigned int *brefint;
1174 	void *bradder;
1175 	int brsize;
1176 	size_t refcntsize = sizeof (unsigned char);
1177 	struct bm_ref_ops *refops;
1178 
1179 	if (!(flags & DCMD_ADDRSPEC))
1180 		return (DCMD_USAGE);
1181 
1182 	if (argc < 1) {
1183 		mdb_warn("must have an argument\n");
1184 		return (DCMD_ERR);
1185 	}
1186 
1187 	krdc = mdb_zalloc(sizeof (*krdc), UM_GC);
1188 
1189 	if (mdb_vread(krdc, sizeof (*krdc), addr) != sizeof (*krdc)) {
1190 		mdb_warn("failed to read rdc_k_info at %p", addr);
1191 		return (DCMD_ERR);
1192 	}
1193 
1194 	bradder = krdc->bitmap_ref;
1195 	refops = mdb_zalloc(sizeof (*refops), UM_GC);
1196 	if (mdb_vread(refops, sizeof (*refops), (uintptr_t)krdc->bm_refs) !=
1197 	    sizeof (*refops)) {
1198 		mdb_warn("failed to read bm_refops at %p", krdc->bm_refs);
1199 		return (DCMD_ERR);
1200 	}
1201 	refcntsize = refops->bmap_ref_size;
1202 	brsize = krdc->bitmap_size * BITS_IN_BYTE * refcntsize;
1203 	if (refcntsize == sizeof (unsigned char)) {
1204 		brefbyte = mdb_zalloc(brsize, UM_GC);
1205 		if (mdb_vread(brefbyte, brsize, (uintptr_t)bradder) != brsize) {
1206 			mdb_warn("failed to read bitmap");
1207 			return (DCMD_ERR);
1208 		}
1209 	} else {
1210 		brefint = mdb_zalloc(brsize, UM_GC);
1211 		if (mdb_vread(brefint, brsize, (uintptr_t)bradder) != brsize) {
1212 			mdb_warn("failed to read bitmap");
1213 			return (DCMD_ERR);
1214 		}
1215 	}
1216 
1217 	num = (int)mdb_strtoull(argv[0].a_un.a_str);
1218 	st = FBA_TO_LOG_NUM(num);
1219 	if (refcntsize == sizeof (unsigned char))
1220 		i = brefbyte[st];
1221 	else
1222 		i = brefint[st];
1223 
1224 	mdb_printf("BITREF (%d) for %x %s set (%02x)", st, num, i?"IS":"IS NOT",
1225 	    i);
1226 
1227 	return (DCMD_OK);
1228 }
1229 
1230 /*ARGSUSED*/
1231 static int
1232 ind_byte(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1233 {
1234 	int num;
1235 
1236 	if (argc < 1) {
1237 		mdb_warn("must have an argument\n");
1238 		return (DCMD_ERR);
1239 	}
1240 	num = FBA_TO_LOG_NUM((int)mdb_strtoull(argv[0].a_un.a_str));
1241 	mdb_printf("IND_BYTE: %d", IND_BYTE(num));
1242 
1243 	return (DCMD_OK);
1244 }
1245 
1246 /*ARGSUSED*/
1247 static int
1248 ind_bit(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1249 {
1250 	int num;
1251 
1252 	if (argc < 1) {
1253 		mdb_warn("must have an argument\n");
1254 		return (DCMD_ERR);
1255 	}
1256 	num = FBA_TO_LOG_NUM((int)mdb_strtoull(argv[0].a_un.a_str));
1257 	mdb_printf("IND_BIT: %d 0x%x", IND_BIT(num), IND_BIT(num));
1258 
1259 	return (DCMD_OK);
1260 }
1261 
1262 static char *
1263 print_bit(uint_t bitmask)
1264 {
1265 	int bitval = 1;
1266 	int i;
1267 
1268 	bitstr[32] = '\0';
1269 
1270 	for (i = 31; i >= 0; i--) {
1271 		if (bitmask & bitval) {
1272 			bitstr[i] = '1';
1273 		} else {
1274 			bitstr[i] = '0';
1275 		}
1276 		bitval *= 2;
1277 	}
1278 	return (bitstr);
1279 }
1280 
1281 /*ARGSUSED*/
1282 static int
1283 rdc_bitmask(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1284 {
1285 	uint_t bitmask = 0;
1286 	int first, st, en, pos, len;
1287 
1288 	if (argc < 2) {
1289 		mdb_warn("must have 2 args (pos, len)\n");
1290 		return (DCMD_ERR);
1291 	}
1292 	pos = (int)mdb_strtoull(argv[0].a_un.a_str);
1293 	len = (int)mdb_strtoull(argv[1].a_un.a_str);
1294 
1295 	if (len <= 0) {
1296 		mdb_printf("non positive len specified");
1297 		return (DCMD_ERR);
1298 	}
1299 
1300 	if ((len - pos) > 2048) {
1301 		mdb_printf("len out of range, 32 bit bitmask");
1302 		return (DCMD_ERR);
1303 	}
1304 
1305 	first = st = FBA_TO_LOG_NUM(pos);
1306 	en = FBA_TO_LOG_NUM(pos + len - 1);
1307 	while (st <= en) {
1308 		BMAP_BIT_SET((uchar_t *)&bitmask, st - first);
1309 		st++;
1310 	}
1311 
1312 	mdb_printf("bitmask for POS: %d LEN: %d : 0x%08x (%s)", pos, len,
1313 	    bitmask & 0xffffffff, print_bit(bitmask));
1314 	return (DCMD_OK);
1315 
1316 }
1317 
1318 /*
1319  * Dump the bitmap of the krdc structure indicated by the index
1320  * argument. Used by the ZatoIchi tests.
1321  */
1322 /*ARGSUSED*/
1323 static int
1324 rdc_bmapdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1325 {
1326 	rdc_k_info_t *rdc_k_info;
1327 	int index;
1328 	uintptr_t bmapaddr;
1329 	uintptr_t bmapdata;
1330 	unsigned char *data;
1331 	int bmapsize;
1332 	int i;
1333 	int st = 0;
1334 	int en = 0;
1335 
1336 	if (argc < 1) {
1337 		mdb_warn("must have index argument\n");
1338 		return (DCMD_ERR);
1339 	}
1340 
1341 	i = argc;
1342 	if (i == 3) {
1343 		en = (int)mdb_strtoull(argv[2].a_un.a_str);
1344 		en = FBA_TO_LOG_NUM(en);
1345 		i--;
1346 	}
1347 	if (i == 2) {
1348 		st = (int)mdb_strtoull(argv[1].a_un.a_str);
1349 		st = FBA_TO_LOG_NUM(st);
1350 	}
1351 
1352 	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1353 	/*
1354 	 * Find out where in memory the rdc_k_kinfo array starts
1355 	 */
1356 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1357 		mdb_warn("failed to read 'rdc_k_info'");
1358 		return (DCMD_ERR);
1359 	}
1360 	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_size);
1361 	if (mdb_vread(&bmapsize, sizeof (bmapsize), bmapaddr)
1362 	    != sizeof (bmapsize)) {
1363 		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1364 		return (DCMD_ERR);
1365 	}
1366 
1367 	bmapaddr = (uintptr_t)(&rdc_k_info[index].dcio_bitmap);
1368 	if (mdb_vread(&bmapdata, sizeof (bmapdata), bmapaddr)
1369 	    != sizeof (bmapdata)) {
1370 		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1371 		return (DCMD_ERR);
1372 	}
1373 	data = mdb_zalloc(bmapsize, UM_SLEEP);
1374 
1375 	if (mdb_vread(data, bmapsize, bmapdata) != bmapsize) {
1376 		mdb_warn("failed to read the bitmap data\n");
1377 		mdb_free(data, bmapsize);
1378 		return (DCMD_ERR);
1379 	}
1380 	mdb_printf("bitmap data address 0x%p bitmap size %d\n"
1381 	    "kinfo 0x%p\n", bmapdata, bmapsize, &rdc_k_info[index]);
1382 
1383 	if ((st < 0) || ((st/8) > bmapsize) || (en < 0)) {
1384 		mdb_warn("offset is out of range st %d bms %d en %d",
1385 		    st, bmapsize, en);
1386 		return (DCMD_ERR);
1387 	}
1388 	if (((en/8) > bmapsize) || (en == 0))
1389 		en = bmapsize * 8;
1390 
1391 	mdb_printf("bit start pos: %d bit end pos: %d\n\n", st, en);
1392 	st /= 8;
1393 	en /= 8;
1394 	for (i = st; i < en; i++) {
1395 		mdb_printf("%02x ", data[i] & 0xff);
1396 		if ((i % 16) == 15) {
1397 			int s = LOG_TO_FBA_NUM((i-15)*8);
1398 			int e = LOG_TO_FBA_NUM(((i+1)*8)) - 1;
1399 			mdb_printf(" fbas: %x - %x\n", s, e);
1400 		}
1401 	}
1402 	mdb_printf("\n");
1403 	mdb_free(data, bmapsize);
1404 	return (DCMD_OK);
1405 }
1406 
1407 /*
1408  * dump the bitmap reference count
1409  */
1410 /*ARGSUSED*/
1411 static int
1412 rdc_brefdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1413 {
1414 	rdc_k_info_t *rdc_k_info;
1415 	int index;
1416 	uintptr_t bmapaddr;
1417 	uintptr_t bmapdata;
1418 	unsigned char *data;
1419 	int bmapsize;
1420 	int i;
1421 	int st = 0;
1422 	int en = 0;
1423 
1424 	if (argc < 1) {
1425 		mdb_warn("must have index argument\n");
1426 		return (DCMD_ERR);
1427 	}
1428 	index = (int)mdb_strtoull(argv[0].a_un.a_str);
1429 
1430 	i = argc;
1431 	if (i == 3) {
1432 		en = (int)mdb_strtoull(argv[2].a_un.a_str);
1433 		en = FBA_TO_LOG_NUM(en);
1434 		i--;
1435 
1436 	}
1437 	if (i == 2) {
1438 		st = (int)mdb_strtoull(argv[1].a_un.a_str);
1439 		st = FBA_TO_LOG_NUM(st);
1440 	}
1441 
1442 	/*
1443 	 * Find out where in memory the rdc_k_kinfo array starts
1444 	 */
1445 	if (mdb_readvar(&rdc_k_info, "rdc_k_info") == -1) {
1446 		mdb_warn("failed to read 'rdc_k_info'");
1447 		return (DCMD_ERR);
1448 	}
1449 	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_size);
1450 
1451 	if (mdb_vread(&bmapsize, sizeof (bmapsize), bmapaddr)
1452 	    != sizeof (bmapsize)) {
1453 		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1454 		return (DCMD_ERR);
1455 	}
1456 
1457 	bmapsize *= 8;
1458 	bmapaddr = (uintptr_t)(&rdc_k_info[index].bitmap_ref);
1459 
1460 	if (mdb_vread(&bmapdata, sizeof (bmapdata), bmapaddr)
1461 	    != sizeof (bmapdata)) {
1462 		mdb_warn("failed to read dcio_bitmap at %p\n", bmapaddr);
1463 		return (DCMD_ERR);
1464 	}
1465 	data = mdb_zalloc(bmapsize, UM_SLEEP);
1466 
1467 	if (mdb_vread(data, bmapsize, bmapdata) != bmapsize) {
1468 		mdb_warn("failed to read the bitmap data\n");
1469 		mdb_free(data, bmapsize);
1470 		return (DCMD_ERR);
1471 	}
1472 	mdb_printf("bitmap data address 0x%p bitmap size %d\n"
1473 	    "kinfo 0x%p\n", bmapdata, bmapsize, &rdc_k_info[index]);
1474 
1475 	if ((st < 0) || (st > bmapsize) || (en < 0)) {
1476 		mdb_warn("offset is out of range");
1477 	}
1478 	if ((en > bmapsize) || (en == 0))
1479 		en = bmapsize;
1480 
1481 	mdb_printf("bit start pos: %d bit end pos: %d\n\n", st, en);
1482 
1483 	for (i = st; i < en; i++) {
1484 		mdb_printf("%02x ", data[i] & 0xff);
1485 		if ((i % 16) == 15) {
1486 			int s = LOG_TO_FBA_NUM(i-15);
1487 			int e = LOG_TO_FBA_NUM(i+1) - 1;
1488 			mdb_printf(" fbas: 0x%x - 0x%x \n", s, e);
1489 		}
1490 	}
1491 	mdb_printf("\n");
1492 	mdb_free(data, bmapsize);
1493 	return (DCMD_OK);
1494 }
1495 
1496 static int
1497 rdc_bmapnref(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1498 {
1499 	mdb_printf("\nRDC bitmap info\n");
1500 	rdc_bmapdump(addr, flags, argc, argv);
1501 	mdb_printf("RDC bitmap reference count info\n");
1502 	rdc_brefdump(addr, flags, argc, argv);
1503 	return (DCMD_OK);
1504 }
1505 
1506 #endif
1507 /*
1508  * MDB module linkage information:
1509  */
1510 
1511 static const mdb_dcmd_t dcmds[] = {
1512 	{ "rdc", NULL, "display sndr module info", rdc },
1513 	{ "rdc_buf", "?[-v]", "rdc_buf structure", rdc_buf },
1514 	{ "rdc_kinfo", "?[-av]", "rdc_k_info structure", rdc_kinfo },
1515 	{ "rdc_uinfo", "?[-av]", "rdc_u_info structure", rdc_uinfo },
1516 	{ "rdc_group", "?", "rdc group structure", rdc_group },
1517 	{ "rdc_srv", "?", "rdc_srv structure", rdc_srv },
1518 	{ "rdc_if", "?", "rdc_if structure", rdc_if },
1519 	{ "rdc_infodev", "?", "rdc_info_dev structure", rdc_infodev },
1520 	{ "rdc_k2u", "?", "rdc_kinfo to rdc_uinfo", rdc_k2u },
1521 	{ "rdc_u2k", "?", "rdc_uinfo to rdc_kinfo", rdc_u2k },
1522 	{ "rdc_aio", "?", "rdc_aio structure", rdc_aio},
1523 	{ "rdc_iohdr", "?", "rdc_iohdr structure", rdc_iohdr},
1524 #ifdef DEBUG
1525 	{ "rdc_setseq", "?", "Write seq field in group", rdc_setseq },
1526 	{ "rdc_setseqack", "?", "Write seqack field in group", rdc_setseqack },
1527 	{ "rdc_dset", "?", "Dump dset info", rdc_dset },
1528 	{ "rdc_bmapdump", "?", "Dump bitmap", rdc_bmapdump },
1529 	{ "rdc_brefdump", "?", "Dump bitmap reference count", rdc_brefdump },
1530 	{ "rdc_bmapnref", "?", "Dump bitmap and ref count", rdc_bmapnref },
1531 	{ "rdc_fba2log", "?", "fba to log num", fba_to_log_num },
1532 	{ "rdc_log2fba", "?", "log to fba num", log_to_fba_num },
1533 	{ "rdc_bitisset", "?", "check bit set", bmap_bit_isset },
1534 	{ "rdc_brefisset", "?", "check bit ref set", bmap_bitref_isset },
1535 	{ "rdc_indbyte", "?", "print indbyte", ind_byte },
1536 	{ "rdc_indbit", "?", "print indbit", ind_bit },
1537 	{ "rdc_bitmask", "?", "print bitmask for pos->len", rdc_bitmask },
1538 #endif
1539 	{ NULL }
1540 };
1541 
1542 
1543 static const mdb_walker_t walkers[] = {
1544 	{ "rdc_kinfo", "walk the rdc_k_info array",
1545 	    rdc_k_info_winit, rdc_k_info_wstep, rdc_k_info_wfini },
1546 	{ "rdc_uinfo", "walk the rdc_u_info array",
1547 	    rdc_u_info_winit, rdc_u_info_wstep, rdc_u_info_wfini },
1548 	{ "rdc_if", "walk rdc_if chain",
1549 	    rdc_if_winit, rdc_if_wstep, rdc_if_wfini },
1550 	{ NULL }
1551 };
1552 
1553 
1554 static const mdb_modinfo_t modinfo = {
1555 	MDB_API_VERSION, dcmds, walkers
1556 };
1557 
1558 
1559 const mdb_modinfo_t *
1560 _mdb_init(void)
1561 {
1562 	return (&modinfo);
1563 }
1564