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