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 }