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