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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <mdb/mdb_modapi.h> 30 #include <mdb/mdb_ks.h> 31 #include <sys/types.h> 32 #include <sys/sysmacros.h> 33 #include <sys/fs/ufs_inode.h> 34 #include <sys/fs/ufs_acl.h> 35 #include <sys/fs/ufs_fs.h> 36 37 typedef struct inode_walk_data { 38 int iw_inohsz; 39 int iw_inohcnt; 40 uintptr_t iw_ihead; 41 inode_t iw_inode; 42 } inode_walk_data_t; 43 44 static int 45 inode_walk_init(mdb_walk_state_t *wsp) 46 { 47 int inohsz; 48 uintptr_t ihead; 49 union ihead ih; 50 inode_walk_data_t *iw; 51 52 if (wsp->walk_addr != NULL) { 53 mdb_warn("inode_cache only supports global walks\n"); 54 return (WALK_ERR); 55 } 56 57 if (mdb_readvar(&inohsz, "inohsz") == -1) { 58 mdb_warn("failed to read 'inohsz'"); 59 return (WALK_ERR); 60 } 61 62 if (inohsz == 0) 63 return (WALK_DONE); 64 65 if (mdb_readvar(&ihead, "ihead") == -1) { 66 mdb_warn("failed to read 'ihead'"); 67 return (WALK_ERR); 68 } 69 70 if (mdb_vread(&ih, sizeof (union ihead), ihead) == -1) { 71 mdb_warn("failed to read ihead at %p", ihead); 72 return (WALK_DONE); 73 } 74 75 iw = mdb_alloc(sizeof (inode_walk_data_t), UM_SLEEP); 76 iw->iw_inohsz = inohsz; 77 iw->iw_inohcnt = 0; 78 iw->iw_ihead = ihead; 79 80 wsp->walk_addr = (uintptr_t)ih.ih_chain[0]; 81 wsp->walk_data = iw; 82 83 return (WALK_NEXT); 84 } 85 86 static int 87 inode_walk_step(mdb_walk_state_t *wsp) 88 { 89 uintptr_t addr = wsp->walk_addr; 90 inode_walk_data_t *iw = wsp->walk_data; 91 union ihead ih; 92 93 while (addr == iw->iw_ihead) { 94 if (++iw->iw_inohcnt >= iw->iw_inohsz) 95 return (WALK_DONE); 96 97 iw->iw_ihead += sizeof (union ihead); 98 99 if (mdb_vread(&ih, sizeof (union ihead), iw->iw_ihead) == -1) { 100 mdb_warn("failed to read ihead at %p", iw->iw_ihead); 101 return (WALK_DONE); 102 } 103 addr = (uintptr_t)ih.ih_chain[0]; 104 } 105 106 if (mdb_vread(&iw->iw_inode, sizeof (inode_t), addr) == -1) { 107 mdb_warn("failed to read inode at %p", addr); 108 return (WALK_DONE); 109 } 110 111 wsp->walk_addr = (uintptr_t)iw->iw_inode.i_forw; 112 113 return (wsp->walk_callback(addr, (void *)(uintptr_t)iw->iw_inohcnt, 114 wsp->walk_cbdata)); 115 } 116 117 static void 118 inode_walk_fini(mdb_walk_state_t *wsp) 119 { 120 mdb_free(wsp->walk_data, sizeof (inode_walk_data_t)); 121 } 122 123 typedef struct inode_cbdata { 124 ino_t id_inumber; 125 dev_t id_device; 126 uintptr_t id_addr; 127 uint_t id_flags; 128 } inode_cbdata_t; 129 130 static int 131 inode_cache_cb(uintptr_t addr, const int inohcnt, inode_cbdata_t *id) 132 { 133 inode_t inode; 134 int inohsz; 135 136 if (mdb_vread(&inode, sizeof (inode), addr) == -1) { 137 mdb_warn("failed to read inode_t at %p", addr); 138 return (WALK_ERR); 139 } 140 141 if (id->id_device != 0 && inode.i_dev != id->id_device) 142 return (WALK_NEXT); 143 144 if (id->id_inumber != 0 && inode.i_number != id->id_inumber) 145 return (WALK_NEXT); 146 147 if (id->id_flags & DCMD_ADDRSPEC && addr != id->id_addr) 148 return (WALK_NEXT); 149 150 if (id->id_flags & DCMD_PIPE_OUT) { 151 mdb_printf("%p\n", addr); 152 return (WALK_NEXT); 153 } 154 155 mdb_printf("%0?p %10lld %15lx", 156 addr, (u_longlong_t)inode.i_number, inode.i_dev); 157 158 /* 159 * INOHASH needs inohsz. 160 */ 161 if (mdb_readvar(&inohsz, "inohsz") == -1) { 162 mdb_warn("failed to read 'inohsz'"); 163 return (WALK_ERR); 164 } 165 166 /* 167 * Is the inode in the hash chain it should be? 168 */ 169 if (inohcnt == INOHASH(inode.i_number)) { 170 mdb_printf(" %5d\n", inohcnt); 171 } else { 172 mdb_printf(" %<b>%5d/%5d ??</b>\n", 173 inohcnt, INOHASH(inode.i_number)); 174 } 175 176 return (WALK_NEXT); 177 } 178 179 /*ARGSUSED*/ 180 static int 181 inode_cache(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 182 { 183 inode_cbdata_t id; 184 185 id.id_inumber = 0; 186 id.id_device = 0; 187 id.id_addr = addr; 188 id.id_flags = flags; 189 190 if (mdb_getopts(argc, argv, 191 'i', MDB_OPT_UINT64, &id.id_inumber, 192 'd', MDB_OPT_UINTPTR, &id.id_device, NULL) != argc) 193 return (DCMD_USAGE); 194 195 if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 196 mdb_printf("%<u>%-?s %10s %15s %5s%</u>\n", 197 "ADDR", "INUMBER", "DEVICE", "CHAIN"); 198 } 199 200 if (mdb_walk("inode_cache", (mdb_walk_cb_t)inode_cache_cb, &id) == -1) { 201 mdb_warn("can't walk inode cache"); 202 return (DCMD_ERR); 203 } 204 205 return (DCMD_OK); 206 } 207 208 /*ARGSUSED*/ 209 static int 210 inode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 211 { 212 uint_t verbose = FALSE; 213 inode_t inode; 214 char buf[64]; 215 char path[MAXPATHLEN]; 216 217 static const mdb_bitmask_t i_flag_masks[] = { 218 { "UPD", IUPD, IUPD }, 219 { "ACC", IACC, IACC }, 220 { "MOD", IMOD, IMOD }, 221 { "CHG", ICHG, ICHG }, 222 { "NOACC", INOACC, INOACC }, 223 { "MODTIME", IMODTIME, IMODTIME }, 224 { "REF", IREF, IREF }, 225 { "SYNC", ISYNC, ISYNC }, 226 { "FASTSYMLNK", IFASTSYMLNK, IFASTSYMLNK }, 227 { "MODACC", IMODACC, IMODACC }, 228 { "ATTCHG", IATTCHG, IATTCHG }, 229 { "BDWRITE", IBDWRITE, IBDWRITE }, 230 { "STALE", ISTALE, ISTALE }, 231 { "DEL", IDEL, IDEL }, 232 { "DIRECTIO", IDIRECTIO, IDIRECTIO }, 233 { "JUNKIQ", IJUNKIQ, IJUNKIQ }, 234 { NULL, 0, 0 } 235 }; 236 237 static const mdb_bitmask_t i_modetype_masks[] = { 238 { "p", IFMT, IFIFO }, 239 { "c", IFMT, IFCHR }, 240 { "d", IFMT, IFDIR }, 241 { "b", IFMT, IFBLK }, 242 { "-", IFMT, IFREG }, 243 { "l", IFMT, IFLNK }, 244 { "S", IFMT, IFSHAD }, 245 { "s", IFMT, IFSOCK }, 246 { "A", IFMT, IFATTRDIR }, 247 { NULL, 0, 0 } 248 }; 249 250 if (!(flags & DCMD_ADDRSPEC)) 251 return (DCMD_USAGE); 252 253 if (mdb_getopts(argc, argv, 254 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 255 return (DCMD_USAGE); 256 257 if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 258 mdb_printf("%<u>%-?s %10s %1s %5s %8s", 259 "ADDR", "INUMBER", "T", "MODE", "SIZE"); 260 261 if (verbose) 262 mdb_printf(" %11s %-22s%</u>\n", "DEVICE", "FLAG"); 263 else 264 mdb_printf(" %-12s %-21s%</u>\n", "MTIME", "NAME"); 265 } 266 267 if (mdb_vread(&inode, sizeof (inode), addr) == -1) { 268 mdb_warn("failed to read inode_t at %p", addr); 269 return (DCMD_ERR); 270 } 271 272 mdb_printf("%0?p %10lld %b %5#o %8llx", 273 addr, (u_longlong_t)inode.i_number, inode.i_mode, i_modetype_masks, 274 inode.i_mode & ~IFMT, inode.i_size); 275 276 if (verbose) { 277 278 mdb_printf(" %11lx <%b>\n", 279 inode.i_dev, inode.i_flag, i_flag_masks); 280 281 mdb_inc_indent(2); 282 283 mdb_printf("%Y\n", inode.i_mtime.tv_sec); 284 285 if (mdb_vnode2path((uintptr_t)inode.i_vnode, path, 286 sizeof (path)) == 0 && *path != '\0') 287 mdb_printf("%s\n", path); 288 else 289 mdb_printf("??\n"); 290 291 mdb_dec_indent(2); 292 293 return (DCMD_OK); 294 } 295 296 /* 297 * Not verbose, everything must fit into one line. 298 */ 299 mdb_snprintf(buf, sizeof (buf), "%Y", inode.i_mtime.tv_sec); 300 buf[17] = '\0'; /* drop seconds */ 301 if (buf[0] == '1' || buf[0] == '2') 302 mdb_printf(" %12s", buf + 5); /* drop year */ 303 else 304 mdb_printf(" %-12s", "?"); 305 306 if (mdb_vnode2path((uintptr_t)inode.i_vnode, path, 307 sizeof (path)) == 0 && *path != '\0') { 308 if (strlen(path) <= 21) 309 mdb_printf(" %-21s\n", path); 310 else 311 mdb_printf(" ...%-18s\n", path + strlen(path) - 18); 312 } else { 313 mdb_printf(" ??\n"); 314 } 315 316 return (DCMD_OK); 317 } 318 319 static struct { 320 int am_offset; 321 char *am_tag; 322 } acl_map[] = { 323 { offsetof(si_t, aowner), "USER_OBJ" }, 324 { offsetof(si_t, agroup), "GROUP_OBJ" }, 325 { offsetof(si_t, aother), "OTHER_OBJ" }, 326 { offsetof(si_t, ausers), "USER" }, 327 { offsetof(si_t, agroups), "GROUP" }, 328 { offsetof(si_t, downer), "DEF_USER_OBJ" }, 329 { offsetof(si_t, dgroup), "DEF_GROUP_OBJ" }, 330 { offsetof(si_t, dother), "DEF_OTHER_OBJ" }, 331 { offsetof(si_t, dusers), "DEF_USER" }, 332 { offsetof(si_t, dgroups), "DEF_GROUP" }, 333 { -1, NULL } 334 }; 335 336 static int 337 acl_walk_init(mdb_walk_state_t *wsp) 338 { 339 uintptr_t addr = wsp->walk_addr; 340 inode_t inode; 341 si_t *si; 342 ufs_ic_acl_t **aclpp; 343 344 if (addr == NULL) { 345 mdb_warn("acl walk needs an inode address\n"); 346 return (WALK_ERR); 347 } 348 349 if (mdb_vread(&inode, sizeof (inode), addr) == -1) { 350 mdb_warn("failed to read inode_t at %p", addr); 351 return (WALK_ERR); 352 } 353 354 if (inode.i_ufs_acl == NULL) 355 return (WALK_DONE); 356 357 si = mdb_alloc(sizeof (si_t), UM_SLEEP); 358 359 if (mdb_vread(si, sizeof (si_t), (uintptr_t)inode.i_ufs_acl) == -1) { 360 mdb_warn("failed to read si_t at %p", inode.i_ufs_acl); 361 mdb_free(si, sizeof (si_t)); 362 return (WALK_ERR); 363 } 364 365 /* LINTED - alignment */ 366 aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[0].am_offset); 367 368 wsp->walk_addr = (uintptr_t)*aclpp; 369 wsp->walk_data = si; 370 wsp->walk_arg = 0; 371 372 return (WALK_NEXT); 373 } 374 375 static int 376 acl_walk_step(mdb_walk_state_t *wsp) 377 { 378 uintptr_t addr = wsp->walk_addr; 379 si_t *si = wsp->walk_data; 380 uint_t i = (uintptr_t)wsp->walk_arg; 381 ufs_ic_acl_t **aclpp; 382 ufs_ic_acl_t acl; 383 384 while (addr == NULL) { 385 wsp->walk_arg = (void *)(uintptr_t)++i; 386 387 if (acl_map[i].am_offset == -1) 388 return (WALK_DONE); 389 390 /* LINTED - alignment */ 391 aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[i].am_offset); 392 393 addr = (uintptr_t)*aclpp; 394 } 395 396 if (mdb_vread(&acl, sizeof (acl), addr) == -1) { 397 mdb_warn("failed to read acl at %p", addr); 398 return (WALK_DONE); 399 } 400 401 wsp->walk_addr = (uintptr_t)acl.acl_ic_next; 402 403 return (wsp->walk_callback(addr, &acl, acl_map[i].am_tag)); 404 } 405 406 static void 407 acl_walk_fini(mdb_walk_state_t *wsp) 408 { 409 mdb_free(wsp->walk_data, sizeof (si_t)); 410 } 411 412 static int 413 acl_cb(uintptr_t addr, const void *arg, void *data) 414 { 415 ufs_ic_acl_t *aclp = (ufs_ic_acl_t *)arg; 416 417 mdb_printf("%?p %-16s %7#o %10d\n", 418 addr, (char *)data, aclp->acl_ic_perm, aclp->acl_ic_who); 419 420 return (WALK_NEXT); 421 } 422 423 /*ARGSUSED*/ 424 static int 425 acl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 426 { 427 if (!(flags & DCMD_ADDRSPEC)) 428 return (DCMD_USAGE); 429 430 if (argc != 0) 431 return (DCMD_USAGE); 432 433 if (DCMD_HDRSPEC(flags)) { 434 mdb_printf("%<u>%?s %-16s %7s %10s%</u>\n", 435 "ADDR", "TAG", "PERM", "WHO"); 436 } 437 438 if (mdb_pwalk("acl", (mdb_walk_cb_t)acl_cb, NULL, addr) == -1) { 439 mdb_warn("can't walk acls of inode %p", addr); 440 return (DCMD_ERR); 441 } 442 443 return (DCMD_OK); 444 } 445 446 447 static int 448 cg_walk_init(mdb_walk_state_t *wsp) 449 { 450 if (mdb_layered_walk("buf", wsp) == -1) { 451 mdb_warn("couldn't walk bio buf hash"); 452 return (WALK_ERR); 453 } 454 455 return (WALK_NEXT); 456 } 457 458 static int 459 cg_walk_step(mdb_walk_state_t *wsp) 460 { 461 uintptr_t addr = (uintptr_t)((const buf_t *)wsp->walk_layer)->b_un.b_cg; 462 struct cg cg; 463 464 if (mdb_vread(&cg, sizeof (cg), addr) == -1) { 465 mdb_warn("failed to read cg struct at %p", addr); 466 return (WALK_ERR); 467 } 468 469 if (cg.cg_magic != CG_MAGIC) 470 return (WALK_NEXT); 471 472 return (wsp->walk_callback(addr, &cg, wsp->walk_cbdata)); 473 } 474 475 static void 476 pbits(const uchar_t *cp, const int max, const int linelen) 477 { 478 int i, j, len; 479 char entry[40]; 480 int linecnt = -1; 481 482 for (i = 0; i < max; i++) { 483 if (isset(cp, i)) { 484 len = mdb_snprintf(entry, sizeof (entry), "%d", i); 485 j = i; 486 while ((i + 1) < max && isset(cp, i+1)) 487 i++; 488 if (i != j) 489 len += mdb_snprintf(entry + len, 490 sizeof (entry) - len, "-%d", i); 491 492 if (linecnt == -1) { 493 /* first entry */ 494 mdb_printf("%s", entry); 495 linecnt = linelen - len; 496 } else if (linecnt - (len + 3) > 0) { 497 /* subsequent entry on same line */ 498 mdb_printf(", %s", entry); 499 linecnt -= len + 2; 500 } else { 501 /* subsequent enty on new line */ 502 mdb_printf(",\n%s", entry); 503 linecnt = linelen - len; 504 } 505 } 506 } 507 mdb_printf("\n"); 508 } 509 510 /*ARGSUSED*/ 511 static int 512 cg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 513 { 514 uint_t verbose = FALSE; 515 struct cg cg; 516 struct cg *cgp = &cg; 517 size_t size; 518 int i, j, cnt, off; 519 int32_t *blktot; 520 short *blks; 521 522 if (!(flags & DCMD_ADDRSPEC)) { 523 if (mdb_walk_dcmd("cg", "cg", argc, argv) == -1) { 524 mdb_warn("can't walk cylinder group structs"); 525 return (DCMD_ERR); 526 } 527 return (DCMD_OK); 528 } 529 530 if (mdb_getopts(argc, argv, 531 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 532 return (DCMD_USAGE); 533 534 if (mdb_vread(cgp, sizeof (cg), addr) == -1) { 535 mdb_warn("failed to read cg struct at %p", addr); 536 return (DCMD_ERR); 537 } 538 539 if (!verbose) { 540 if (DCMD_HDRSPEC(flags)) 541 mdb_printf("%<u>%4s %?s %10s %10s %10s %10s%</u>\n", 542 "CGX", "CG", "NDIR", "NBFREE", "NIFREE", "NFFREE"); 543 544 mdb_printf("%4d %?p %10d %10d %10d %10d\n", cgp->cg_cgx, 545 addr, cgp->cg_cs.cs_ndir, cgp->cg_cs.cs_nbfree, 546 cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree); 547 548 return (DCMD_OK); 549 } 550 551 /* 552 * Verbose: produce output similiar to "fstyp -v". 553 */ 554 if (cgp->cg_btotoff >= cgp->cg_nextfreeoff || 555 cgp->cg_boff >= cgp->cg_nextfreeoff || 556 cgp->cg_iusedoff >= cgp->cg_nextfreeoff || 557 cgp->cg_freeoff >= cgp->cg_nextfreeoff) { 558 mdb_warn("struct cg at %p seems broken\n", addr); 559 return (DCMD_ERR); 560 } 561 562 size = cgp->cg_nextfreeoff; 563 cgp = mdb_alloc(size, UM_SLEEP); 564 565 if (mdb_vread(cgp, size, addr) == -1) { 566 mdb_warn("failed to read struct cg and maps at %p", addr); 567 mdb_free(cgp, size); 568 return (DCMD_ERR); 569 } 570 571 mdb_printf("%<b>cg %d (%0?p)%</b>\n", cgp->cg_cgx, addr); 572 573 mdb_inc_indent(4); 574 575 mdb_printf("time:\t%Y\n", cgp->cg_time); 576 mdb_printf("ndir:\t%d\n", cgp->cg_cs.cs_ndir); 577 mdb_printf("nbfree:\t%d\n", cgp->cg_cs.cs_nbfree); 578 mdb_printf("nifree:\t%d\n", cgp->cg_cs.cs_nifree); 579 mdb_printf("nffree:\t%d\n", cgp->cg_cs.cs_nffree); 580 581 mdb_printf("frsum:"); 582 for (i = 1; i < MAXFRAG; i++) 583 mdb_printf("\t%d", cgp->cg_frsum[i]); 584 mdb_printf("\n"); 585 586 off = cgp->cg_iusedoff; 587 mdb_printf("used inode map (%0?p):\n", (char *)addr + off); 588 mdb_inc_indent(4); 589 pbits((uchar_t *)cgp + off, cgp->cg_niblk / sizeof (char), 72); 590 mdb_dec_indent(4); 591 592 off = cgp->cg_freeoff; 593 mdb_printf("free block map (%0?p):\n", (char *)addr + off); 594 mdb_inc_indent(4); 595 pbits((uchar_t *)cgp + off, cgp->cg_ndblk / sizeof (char), 72); 596 mdb_dec_indent(4); 597 598 /* LINTED - alignment */ 599 blktot = (int32_t *)((char *)cgp + cgp->cg_btotoff); 600 /* LINTED - alignment */ 601 blks = (short *)((char *)cgp + cgp->cg_boff); 602 cnt = (cgp->cg_iusedoff - cgp->cg_boff) / cgp->cg_ncyl / sizeof (short); 603 mdb_printf("free block positions:\n"); 604 mdb_inc_indent(4); 605 606 for (i = 0; i < cgp->cg_ncyl; i++) { 607 mdb_printf("c%d:\t(%d)\t", i, blktot[i]); 608 for (j = 0; j < cnt; j++) 609 mdb_printf(" %d", blks[i*cnt + j]); 610 mdb_printf("\n"); 611 } 612 mdb_dec_indent(4); 613 614 mdb_printf("\n"); 615 mdb_dec_indent(4); 616 617 mdb_free(cgp, size); 618 619 return (DCMD_OK); 620 } 621 622 void 623 inode_cache_help(void) 624 { 625 mdb_printf( 626 "Displays cached inode_t. If an address, an inode number and/or a\n" 627 "device is specified, searches inode cache for inodes which match\n" 628 "the specified criteria. Prints nothing but the address, if\n" 629 "output is a pipe.\n" 630 "\n" 631 "Options:\n" 632 " -d device Filter out inodes, which reside on the specified" 633 " device.\n" 634 " -i inumber Filter out inodes with the specified inode" 635 " number.\n"); 636 } 637 638 /* 639 * MDB module linkage 640 */ 641 static const mdb_dcmd_t dcmds[] = { 642 { "inode_cache", "?[-d device] [-i inumber]", 643 "search/display inodes from inode cache", 644 inode_cache, inode_cache_help }, 645 { "inode", ":[-v]", "display summarized inode_t", inode }, 646 { "acl", ":", "given an inode, display its in core acl's", acl_dcmd }, 647 { "cg", "?[-v]", "display a summarized cylinder group structure", cg }, 648 { NULL } 649 }; 650 651 static const mdb_walker_t walkers[] = { 652 { "inode_cache", "walk inode cache", 653 inode_walk_init, inode_walk_step, inode_walk_fini }, 654 { "acl", "given an inode, walk chains of in core acl's", 655 acl_walk_init, acl_walk_step, acl_walk_fini }, 656 { "cg", "walk cg's in bio buffer cache", 657 cg_walk_init, cg_walk_step, NULL }, 658 { NULL } 659 }; 660 661 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 662 663 const mdb_modinfo_t * 664 _mdb_init(void) 665 { 666 return (&modinfo); 667 } 668