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 
  34 #include <sys/nsctl/dsw.h>
  35 #include <sys/nsctl/dsw_dev.h>
  36 
  37 #include <sys/nsctl/nsvers.h>
  38 
  39 #define offsetof(s, m)  ((size_t)(&((s *)0)->m))
  40 
  41 
  42 const mdb_bitmask_t bi_flags_bits[] = {
  43         { "DSW_GOLDEN", DSW_GOLDEN, DSW_GOLDEN },
  44         { "DSW_COPYINGP", DSW_COPYINGP, DSW_COPYINGP },
  45         { "DSW_COPYINGM", DSW_COPYINGM, DSW_COPYINGM },
  46         { "DSW_COPYINGS", DSW_COPYINGS, DSW_COPYINGS },
  47         { "DSW_COPYINGX", DSW_COPYINGX, DSW_COPYINGX },
  48         { "DSW_BMPOFFLINE", DSW_BMPOFFLINE, DSW_BMPOFFLINE },
  49         { "DSW_SHDOFFLINE", DSW_SHDOFFLINE, DSW_SHDOFFLINE },
  50         { "DSW_MSTOFFLINE", DSW_MSTOFFLINE, DSW_MSTOFFLINE },
  51         { "DSW_OVROFFLINE", DSW_OVROFFLINE, DSW_OVROFFLINE },
  52         { "DSW_TREEMAP", DSW_TREEMAP, DSW_TREEMAP },
  53         { "DSW_OVERFLOW", DSW_OVERFLOW, DSW_OVERFLOW },
  54         { "DSW_SHDEXPORT", DSW_SHDEXPORT, DSW_SHDEXPORT },
  55         { "DSW_SHDIMPORT", DSW_SHDIMPORT, DSW_SHDIMPORT },
  56         { "DSW_VOVERFLOW", DSW_VOVERFLOW, DSW_VOVERFLOW },
  57         { "DSW_HANGING", DSW_HANGING, DSW_HANGING },
  58         { "DSW_CFGOFFLINE", DSW_CFGOFFLINE, DSW_CFGOFFLINE },
  59         { "DSW_OVRHDRDRTY", DSW_OVRHDRDRTY, DSW_OVRHDRDRTY },
  60         { "DSW_RESIZED", DSW_RESIZED, DSW_RESIZED },
  61         { "DSW_FRECLAIM", DSW_FRECLAIM, DSW_FRECLAIM },
  62         { NULL, 0, 0 }
  63 };
  64 
  65 const mdb_bitmask_t bi_state_bits[] = {
  66         { "DSW_IOCTL", DSW_IOCTL, DSW_IOCTL },
  67         { "DSW_CLOSING", DSW_CLOSING, DSW_CLOSING },
  68         { "DSW_MSTTARGET", DSW_MSTTARGET, DSW_MSTTARGET },
  69         { "DSW_MULTIMST", DSW_MULTIMST, DSW_MULTIMST },
  70         { NULL, 0, 0 }
  71 };
  72 static uintptr_t nextaddr;
  73 /*
  74  * Display a ii_fd_t
  75  * Requires an address.
  76  */
  77 /*ARGSUSED*/
  78 static int
  79 ii_fd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
  80 {
  81         ii_fd_t fd;
  82 
  83         if (!(flags & DCMD_ADDRSPEC))
  84                 return (DCMD_USAGE);
  85 
  86         if (mdb_vread(&fd, sizeof (fd), addr) != sizeof (fd)) {
  87                 mdb_warn("failed to read ii_fd_t at 0x%p", addr);
  88                 return (DCMD_ERR);
  89         }
  90 
  91         mdb_inc_indent(4);
  92         mdb_printf("ii_info: 0x%p ii_bmp: %d ii_shd: %d ii_ovr: %d ii_optr: "
  93             "0x%p\nii_oflags: 0x%x\n", fd.ii_info, fd.ii_bmp, fd.ii_shd,
  94             fd.ii_ovr, fd.ii_optr, fd.ii_oflags);
  95         mdb_dec_indent(4);
  96 
  97         return (DCMD_OK);
  98 }
  99 
 100 /*
 101  * displays a ii_info_dev structure.
 102  */
 103 /*ARGSUSED*/
 104 static int
 105 ii_info_dev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 106 {
 107         _ii_info_dev_t ipdev;
 108 
 109         if (!(flags & DCMD_ADDRSPEC))
 110                 return (DCMD_USAGE);
 111 
 112         if (mdb_vread(&ipdev, sizeof (ipdev), addr) != sizeof (ipdev)) {
 113                 mdb_warn("failed to read ii_info_dev_t at 0x%p", addr);
 114                 return (DCMD_ERR);
 115         }
 116 
 117         mdb_inc_indent(4);
 118         mdb_printf("bi_fd: 0x%p bi_iodev: 0x%p bi_tok: 0x%p\n",
 119             ipdev.bi_fd, ipdev.bi_iodev, ipdev.bi_tok);
 120         mdb_printf("bi_ref: %d bi_rsrv: %d bi_orsrv: %d\n",
 121             ipdev.bi_ref, ipdev.bi_rsrv, ipdev.bi_orsrv);
 122 
 123         /*
 124          * use nsc_fd to dump the fd details.... if present.
 125          */
 126         if (ipdev.bi_fd) {
 127                 mdb_printf("nsc_fd structure:\n");
 128                 mdb_inc_indent(4);
 129                 mdb_call_dcmd("nsc_fd", (uintptr_t)(ipdev.bi_fd),
 130                     flags, 0, NULL);
 131                 mdb_dec_indent(4);
 132         }
 133         mdb_dec_indent(4);
 134         return (DCMD_OK);
 135 }
 136 
 137 /*
 138  * Displays an _ii_overflow structure
 139  */
 140 /*ARGSUSED*/
 141 static int
 142 ii_overflow(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 143 {
 144         _ii_overflow_t ii_overflow;
 145 
 146         nextaddr = 0;
 147         if (!(flags & DCMD_ADDRSPEC))
 148                 return (DCMD_USAGE);
 149 
 150         if (mdb_vread(&ii_overflow, sizeof (ii_overflow), addr)
 151                 != sizeof (ii_overflow)) {
 152                 mdb_warn("failed to read ii_overflow_t at 0x%p", addr);
 153                 return (DCMD_ERR);
 154         }
 155 
 156         mdb_inc_indent(4);
 157         mdb_printf("_ii_overflow at 0x%p\n", addr);
 158         mdb_printf("_ii_doverflow_t\n");
 159         mdb_inc_indent(4);
 160         mdb_printf("ii_dvolname: %s\n", ii_overflow.ii_volname);
 161         mdb_printf("ii_dhmagic: %x\n", ii_overflow.ii_hmagic);
 162         mdb_printf("ii_dhversion: %x\n", ii_overflow.ii_hversion);
 163         mdb_printf("ii_ddrefcnt: %x\n", ii_overflow.ii_drefcnt);
 164         mdb_printf("ii_dflags: %x\n", ii_overflow.ii_flags);
 165         mdb_printf("ii_dfreehead: %x\n", ii_overflow.ii_freehead);
 166         mdb_printf("ii_dnchunks: %x\n", ii_overflow.ii_nchunks);
 167         mdb_printf("ii_dunused: %x\n", ii_overflow.ii_unused);
 168         mdb_printf("ii_dused: %x\n", ii_overflow.ii_used);
 169         mdb_printf("ii_urefcnt: %x\n", ii_overflow.ii_urefcnt);
 170         mdb_dec_indent(4);
 171 
 172         mdb_printf("ii_mutex: %x\n", ii_overflow.ii_mutex);
 173         mdb_printf("ii_kstat_mutex: %x\n", ii_overflow.ii_kstat_mutex);
 174         mdb_printf("ii_crefcnt: %d\n", ii_overflow.ii_crefcnt);
 175         mdb_printf("ii_detachcnt: %d\n", ii_overflow.ii_detachcnt);
 176         mdb_printf("ii_next: %x\n", ii_overflow.ii_next);
 177 
 178         mdb_printf("Overflow volume:\n");
 179         if (ii_overflow.ii_dev)
 180                 ii_info_dev((uintptr_t)ii_overflow.ii_dev, flags, 0, NULL);
 181 
 182         mdb_printf("  ii_ioname: %s\n", &ii_overflow.ii_ioname);
 183         mdb_dec_indent(4);
 184 
 185         nextaddr = (uintptr_t)ii_overflow.ii_next;
 186         return (DCMD_OK);
 187 }
 188 /*ARGSUSED*/
 189 static int
 190 ii_info(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 191 {
 192         _ii_info_t ii_info = {0};
 193         char string[DSW_NAMELEN];
 194 
 195         nextaddr = 0;
 196         if (!(flags & DCMD_ADDRSPEC))
 197                 return (DCMD_USAGE);
 198 
 199         if (mdb_vread(&ii_info, sizeof (ii_info), addr) != sizeof (ii_info)) {
 200                 mdb_warn("failed to read ii_info_t at 0x%p", addr);
 201                 return (DCMD_ERR);
 202         }
 203 
 204         mdb_printf(
 205                 "bi_next: 0x%p\n"
 206                 "bi_head: 0x%p\t"
 207                 "bi_sibling: 0x%p\n"
 208                 "bi_master: 0x%p\t"
 209                 "bi_nextmst: 0x%p\n",
 210                 ii_info.bi_next, ii_info.bi_head, ii_info.bi_sibling,
 211                 ii_info.bi_master, ii_info.bi_nextmst);
 212 
 213         mdb_printf("bi_mutex: 0x%p\n", ii_info.bi_mutex);
 214 
 215         /*
 216          * Print out all the fds by using ii_info_dev
 217          */
 218         mdb_printf("Cache master:\n");
 219         if (ii_info.bi_mstdev)
 220                 ii_info_dev((uintptr_t)ii_info.bi_mstdev, flags, 0, NULL);
 221 
 222         mdb_printf("Raw master:\n");
 223         if (ii_info.bi_mstrdev)
 224                 ii_info_dev((uintptr_t)ii_info.bi_mstrdev, flags, 0, NULL);
 225 
 226         mdb_printf("Cache shadow:\n");
 227         ii_info_dev((uintptr_t)(addr + offsetof(_ii_info_t, bi_shddev)),
 228             flags, 0, NULL);
 229 
 230         mdb_printf("Raw shadow:\n");
 231         ii_info_dev((uintptr_t)(addr + offsetof(_ii_info_t, bi_shdrdev)),
 232             flags, 0, NULL);
 233 
 234         mdb_printf("Bitmap:\n");
 235         ii_info_dev((uintptr_t)(addr + offsetof(_ii_info_t, bi_bmpdev)),
 236             flags, 0, NULL);
 237 
 238         mdb_printf("bi_keyname: %-*s\n", DSW_NAMELEN, ii_info.bi_keyname);
 239         mdb_printf("bi_bitmap: 0x%p\n", ii_info.bi_bitmap);
 240 
 241         if ((ii_info.bi_cluster == NULL) ||
 242             (mdb_vread(&string, sizeof (string), (uintptr_t)ii_info.bi_cluster)
 243                 != sizeof (string)))
 244                 string[0] = 0;
 245         mdb_printf("bi_cluster: %s\n", string);
 246 
 247         if ((ii_info.bi_group == NULL) ||
 248             (mdb_vread(&string, sizeof (string), (uintptr_t)ii_info.bi_group)
 249                         != sizeof (string)))
 250                 string[0] = 0;
 251         mdb_printf("bi_group: %s\n", string);
 252 
 253         mdb_printf("bi_busy: 0x%p\n", ii_info.bi_busy);
 254 
 255         mdb_printf("bi_shdfba: %0x\t", ii_info.bi_shdfba);
 256         mdb_printf("bi_shdbits: %0x\n", ii_info.bi_shdbits);
 257         mdb_printf("bi_copyfba: %0x\t", ii_info.bi_copyfba);
 258         mdb_printf("bi_copybits: %0x\n", ii_info.bi_copybits);
 259 
 260         mdb_printf("bi_size: %0x\n", ii_info.bi_size);
 261 
 262         mdb_printf("bi_flags: 0x%x <%b>\n",
 263                 ii_info.bi_flags, ii_info.bi_flags, bi_flags_bits);
 264 
 265         mdb_printf("bi_state: 0x%x <%b>\n",
 266                 ii_info.bi_state, ii_info.bi_state, bi_state_bits);
 267 
 268         mdb_printf("bi_disabled: %d\n", ii_info.bi_disabled);
 269         mdb_printf("bi_ioctl: %d\n", ii_info.bi_ioctl);
 270         mdb_printf("bi_release: %d\t", ii_info.bi_release);
 271         mdb_printf("bi_rsrvcnt: %d\n", ii_info.bi_rsrvcnt);
 272 
 273         mdb_printf("bi_copydonecv: %x\t", ii_info.bi_copydonecv);
 274         mdb_printf("bi_reservecv: %x\n", ii_info.bi_reservecv);
 275         mdb_printf("bi_releasecv: %x\t", ii_info.bi_releasecv);
 276         mdb_printf("bi_closingcv: %x\n", ii_info.bi_closingcv);
 277         mdb_printf("bi_ioctlcv: %x\t", ii_info.bi_ioctlcv);
 278         mdb_printf("bi_busycv: %x\n", ii_info.bi_busycv);
 279         mdb_call_dcmd("rwlock", (uintptr_t)(addr +
 280             offsetof(_ii_info_t, bi_busyrw)), flags, 0, NULL);
 281         mdb_printf("bi_bitmap_ops: 0x%p\n", ii_info.bi_bitmap_ops);
 282 
 283         mdb_printf("bi_rsrvmutex: %x\t", ii_info.bi_rsrvmutex);
 284         mdb_printf("bi_rlsemutex: %x\n", ii_info.bi_rlsemutex);
 285         mdb_printf("bi_bmpmutex: %x\n", ii_info.bi_bmpmutex);
 286 
 287         mdb_printf("bi_mstchks: %d\t", ii_info.bi_mstchks);
 288         mdb_printf("bi_shdchks: %d\n", ii_info.bi_shdchks);
 289         mdb_printf("bi_shdchkused: %d\t", ii_info.bi_shdchkused);
 290         mdb_printf("bi_shdfchk: %d\n", ii_info.bi_shdfchk);
 291 
 292         mdb_printf("bi_overflow\n");
 293         if (ii_info.bi_overflow)
 294                 ii_overflow((uintptr_t)ii_info.bi_overflow, flags, 0, NULL);
 295 
 296         mdb_printf("bi_iifd:\n");
 297         if (ii_info.bi_iifd)
 298                 (void) ii_fd((uintptr_t)ii_info.bi_iifd, flags, 0, NULL);
 299 
 300         mdb_printf("bi_throttle_unit: %d\t", ii_info.bi_throttle_unit);
 301         mdb_printf("bi_throttle_delay: %d\n", ii_info.bi_throttle_delay);
 302 
 303         mdb_printf("bi_linkrw:\n");
 304         mdb_call_dcmd("rwlock", (uintptr_t)(addr +
 305             offsetof(_ii_info_t, bi_linkrw)), flags, 0, NULL);
 306 
 307         mdb_printf("bi_chksmutex: %x\n", ii_info.bi_chksmutex);
 308         mdb_printf("bi_locked_pid: %x\n", ii_info.bi_locked_pid);
 309         mdb_printf("bi_kstat: 0x%p\n", ii_info.bi_kstat);
 310         /* ii_kstat_info_t bi_kstat_io; */
 311 
 312         nextaddr = (uintptr_t)ii_info.bi_next;
 313         return (DCMD_OK);
 314 }
 315 
 316 /*
 317  * This should be a walker surely.
 318  */
 319 /*ARGSUSED*/
 320 static int
 321 ii_info_all(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 322 {
 323         uintptr_t myaddr;
 324         /*
 325          * we use the global address.
 326          */
 327         if (flags & DCMD_ADDRSPEC)
 328                 return (DCMD_USAGE);
 329 
 330         if (mdb_readsym(&myaddr, sizeof (myaddr), "_ii_info_top") !=
 331             sizeof (myaddr)) {
 332                 return (DCMD_ERR);
 333         }
 334 
 335         mdb_printf("_ii_info_top contains 0x%lx\n", myaddr);
 336 
 337         while (myaddr) {
 338                 ii_info(myaddr, DCMD_ADDRSPEC, 0, NULL);
 339                 myaddr = nextaddr;
 340         }
 341         return (DCMD_OK);
 342 }
 343 
 344 /*
 345  * Display general ii module information.
 346  */
 347 
 348 #define ii_get_print(kvar, str, fmt, val)               \
 349         if (mdb_readvar(&(val), #kvar) == -1) {             \
 350                 mdb_dec_indent(4);                      \
 351                 mdb_warn("unable to read '" #kvar "'"); \
 352                 return (DCMD_ERR);                      \
 353         }                                               \
 354         mdb_printf("%-20s" fmt "\n", str ":", val)
 355 
 356 /* ARGSUSED */
 357 static int
 358 ii(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 359 {
 360         int maj, min, mic, baseline, i;
 361 
 362         if (argc != 0)
 363                 return (DCMD_USAGE);
 364 
 365         if (mdb_readvar(&maj, "dsw_major_rev") == -1) {
 366                 mdb_warn("unable to read 'dsw_major_rev'");
 367                 return (DCMD_ERR);
 368         }
 369 
 370         if (mdb_readvar(&min, "dsw_minor_rev") == -1) {
 371                 mdb_warn("unable to read 'dsw_minor_rev'");
 372                 return (DCMD_ERR);
 373         }
 374 
 375         if (mdb_readvar(&mic, "dsw_micro_rev") == -1) {
 376                 mdb_warn("unable to read 'dsw_micro_rev'");
 377                 return (DCMD_ERR);
 378         }
 379 
 380         if (mdb_readvar(&baseline, "dsw_baseline_rev") == -1) {
 381                 mdb_warn("unable to read 'dsw_baseline_rev'");
 382                 return (DCMD_ERR);
 383         }
 384 
 385         mdb_printf("Point-in-Time Copy module version: kernel %d.%d.%d.%d; "
 386             "mdb %d.%d.%d.%d\n", maj, min, mic, baseline,
 387             ISS_VERSION_MAJ, ISS_VERSION_MIN, ISS_VERSION_MIC, ISS_VERSION_NUM);
 388 
 389         mdb_inc_indent(4);
 390         ii_get_print(ii_debug, "debug", "%d", i);
 391         ii_get_print(ii_bitmap, "bitmaps", "%d", i);
 392         mdb_dec_indent(4);
 393 
 394         return (DCMD_OK);
 395 }
 396 
 397 
 398 /*
 399  * MDB module linkage information:
 400  */
 401 
 402 static const mdb_dcmd_t dcmds[] = {
 403 { "ii", NULL, "display ii module info", ii },
 404 { "ii_fd", NULL, "display ii_fd structure", ii_fd },
 405 { "ii_info", NULL, "display ii_info structure", ii_info },
 406 { "ii_info_all", NULL, "display all ii_info structures", ii_info_all },
 407 { "ii_info_dev", NULL, "display ii_info_dev structure", ii_info_dev},
 408 { "ii_overflow", NULL, "display ii_overflow structure", ii_overflow},
 409 { NULL }
 410 };
 411 
 412 
 413 static const mdb_walker_t walkers[] = {
 414         { NULL }
 415 };
 416 
 417 
 418 static const mdb_modinfo_t modinfo = {
 419         MDB_API_VERSION, dcmds, walkers
 420 };
 421 
 422 
 423 const mdb_modinfo_t *
 424 _mdb_init(void)
 425 {
 426         return (&modinfo);
 427 }