10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*1619Ssjelinek * Common Development and Distribution License (the "License").
6*1619Ssjelinek * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*1619Ssjelinek * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
290Sstevel@tonic-gate #include <mdb/mdb_ks.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/sysmacros.h>
320Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
330Sstevel@tonic-gate #include <sys/fs/ufs_acl.h>
340Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
350Sstevel@tonic-gate
36*1619Ssjelinek #include "ufs_cmds.h"
37*1619Ssjelinek
380Sstevel@tonic-gate typedef struct inode_walk_data {
390Sstevel@tonic-gate int iw_inohsz;
400Sstevel@tonic-gate int iw_inohcnt;
410Sstevel@tonic-gate uintptr_t iw_ihead;
420Sstevel@tonic-gate inode_t iw_inode;
430Sstevel@tonic-gate } inode_walk_data_t;
440Sstevel@tonic-gate
450Sstevel@tonic-gate static int
inode_walk_init(mdb_walk_state_t * wsp)460Sstevel@tonic-gate inode_walk_init(mdb_walk_state_t *wsp)
470Sstevel@tonic-gate {
480Sstevel@tonic-gate int inohsz;
490Sstevel@tonic-gate uintptr_t ihead;
500Sstevel@tonic-gate union ihead ih;
510Sstevel@tonic-gate inode_walk_data_t *iw;
520Sstevel@tonic-gate
530Sstevel@tonic-gate if (wsp->walk_addr != NULL) {
540Sstevel@tonic-gate mdb_warn("inode_cache only supports global walks\n");
550Sstevel@tonic-gate return (WALK_ERR);
560Sstevel@tonic-gate }
570Sstevel@tonic-gate
580Sstevel@tonic-gate if (mdb_readvar(&inohsz, "inohsz") == -1) {
590Sstevel@tonic-gate mdb_warn("failed to read 'inohsz'");
600Sstevel@tonic-gate return (WALK_ERR);
610Sstevel@tonic-gate }
620Sstevel@tonic-gate
630Sstevel@tonic-gate if (inohsz == 0)
640Sstevel@tonic-gate return (WALK_DONE);
650Sstevel@tonic-gate
660Sstevel@tonic-gate if (mdb_readvar(&ihead, "ihead") == -1) {
670Sstevel@tonic-gate mdb_warn("failed to read 'ihead'");
680Sstevel@tonic-gate return (WALK_ERR);
690Sstevel@tonic-gate }
700Sstevel@tonic-gate
710Sstevel@tonic-gate if (mdb_vread(&ih, sizeof (union ihead), ihead) == -1) {
720Sstevel@tonic-gate mdb_warn("failed to read ihead at %p", ihead);
730Sstevel@tonic-gate return (WALK_DONE);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate
760Sstevel@tonic-gate iw = mdb_alloc(sizeof (inode_walk_data_t), UM_SLEEP);
770Sstevel@tonic-gate iw->iw_inohsz = inohsz;
780Sstevel@tonic-gate iw->iw_inohcnt = 0;
790Sstevel@tonic-gate iw->iw_ihead = ihead;
800Sstevel@tonic-gate
810Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)ih.ih_chain[0];
820Sstevel@tonic-gate wsp->walk_data = iw;
830Sstevel@tonic-gate
840Sstevel@tonic-gate return (WALK_NEXT);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate static int
inode_walk_step(mdb_walk_state_t * wsp)880Sstevel@tonic-gate inode_walk_step(mdb_walk_state_t *wsp)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
910Sstevel@tonic-gate inode_walk_data_t *iw = wsp->walk_data;
920Sstevel@tonic-gate union ihead ih;
930Sstevel@tonic-gate
940Sstevel@tonic-gate while (addr == iw->iw_ihead) {
950Sstevel@tonic-gate if (++iw->iw_inohcnt >= iw->iw_inohsz)
960Sstevel@tonic-gate return (WALK_DONE);
970Sstevel@tonic-gate
980Sstevel@tonic-gate iw->iw_ihead += sizeof (union ihead);
990Sstevel@tonic-gate
1000Sstevel@tonic-gate if (mdb_vread(&ih, sizeof (union ihead), iw->iw_ihead) == -1) {
1010Sstevel@tonic-gate mdb_warn("failed to read ihead at %p", iw->iw_ihead);
1020Sstevel@tonic-gate return (WALK_DONE);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate addr = (uintptr_t)ih.ih_chain[0];
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate if (mdb_vread(&iw->iw_inode, sizeof (inode_t), addr) == -1) {
1080Sstevel@tonic-gate mdb_warn("failed to read inode at %p", addr);
1090Sstevel@tonic-gate return (WALK_DONE);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->iw_inode.i_forw;
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate return (wsp->walk_callback(addr, (void *)(uintptr_t)iw->iw_inohcnt,
1150Sstevel@tonic-gate wsp->walk_cbdata));
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate static void
inode_walk_fini(mdb_walk_state_t * wsp)1190Sstevel@tonic-gate inode_walk_fini(mdb_walk_state_t *wsp)
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (inode_walk_data_t));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate typedef struct inode_cbdata {
1250Sstevel@tonic-gate ino_t id_inumber;
1260Sstevel@tonic-gate dev_t id_device;
1270Sstevel@tonic-gate uintptr_t id_addr;
1280Sstevel@tonic-gate uint_t id_flags;
1290Sstevel@tonic-gate } inode_cbdata_t;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate static int
inode_cache_cb(uintptr_t addr,const int inohcnt,inode_cbdata_t * id)1320Sstevel@tonic-gate inode_cache_cb(uintptr_t addr, const int inohcnt, inode_cbdata_t *id)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate inode_t inode;
1350Sstevel@tonic-gate int inohsz;
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
1380Sstevel@tonic-gate mdb_warn("failed to read inode_t at %p", addr);
1390Sstevel@tonic-gate return (WALK_ERR);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate if (id->id_device != 0 && inode.i_dev != id->id_device)
1430Sstevel@tonic-gate return (WALK_NEXT);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate if (id->id_inumber != 0 && inode.i_number != id->id_inumber)
1460Sstevel@tonic-gate return (WALK_NEXT);
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate if (id->id_flags & DCMD_ADDRSPEC && addr != id->id_addr)
1490Sstevel@tonic-gate return (WALK_NEXT);
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate if (id->id_flags & DCMD_PIPE_OUT) {
1520Sstevel@tonic-gate mdb_printf("%p\n", addr);
1530Sstevel@tonic-gate return (WALK_NEXT);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate mdb_printf("%0?p %10lld %15lx",
1570Sstevel@tonic-gate addr, (u_longlong_t)inode.i_number, inode.i_dev);
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * INOHASH needs inohsz.
1610Sstevel@tonic-gate */
1620Sstevel@tonic-gate if (mdb_readvar(&inohsz, "inohsz") == -1) {
1630Sstevel@tonic-gate mdb_warn("failed to read 'inohsz'");
1640Sstevel@tonic-gate return (WALK_ERR);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate * Is the inode in the hash chain it should be?
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate if (inohcnt == INOHASH(inode.i_number)) {
1710Sstevel@tonic-gate mdb_printf(" %5d\n", inohcnt);
1720Sstevel@tonic-gate } else {
1730Sstevel@tonic-gate mdb_printf(" %<b>%5d/%5d ??</b>\n",
1740Sstevel@tonic-gate inohcnt, INOHASH(inode.i_number));
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate return (WALK_NEXT);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /*ARGSUSED*/
1810Sstevel@tonic-gate static int
inode_cache(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1820Sstevel@tonic-gate inode_cache(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate inode_cbdata_t id;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate id.id_inumber = 0;
1870Sstevel@tonic-gate id.id_device = 0;
1880Sstevel@tonic-gate id.id_addr = addr;
1890Sstevel@tonic-gate id.id_flags = flags;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate if (mdb_getopts(argc, argv,
1920Sstevel@tonic-gate 'i', MDB_OPT_UINT64, &id.id_inumber,
1930Sstevel@tonic-gate 'd', MDB_OPT_UINTPTR, &id.id_device, NULL) != argc)
1940Sstevel@tonic-gate return (DCMD_USAGE);
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
1970Sstevel@tonic-gate mdb_printf("%<u>%-?s %10s %15s %5s%</u>\n",
1980Sstevel@tonic-gate "ADDR", "INUMBER", "DEVICE", "CHAIN");
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate if (mdb_walk("inode_cache", (mdb_walk_cb_t)inode_cache_cb, &id) == -1) {
2020Sstevel@tonic-gate mdb_warn("can't walk inode cache");
2030Sstevel@tonic-gate return (DCMD_ERR);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate return (DCMD_OK);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate /*ARGSUSED*/
2100Sstevel@tonic-gate static int
inode(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2110Sstevel@tonic-gate inode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate uint_t verbose = FALSE;
2140Sstevel@tonic-gate inode_t inode;
2150Sstevel@tonic-gate char buf[64];
2160Sstevel@tonic-gate char path[MAXPATHLEN];
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate static const mdb_bitmask_t i_flag_masks[] = {
2190Sstevel@tonic-gate { "UPD", IUPD, IUPD },
2200Sstevel@tonic-gate { "ACC", IACC, IACC },
2210Sstevel@tonic-gate { "MOD", IMOD, IMOD },
2220Sstevel@tonic-gate { "CHG", ICHG, ICHG },
2230Sstevel@tonic-gate { "NOACC", INOACC, INOACC },
2240Sstevel@tonic-gate { "MODTIME", IMODTIME, IMODTIME },
2250Sstevel@tonic-gate { "REF", IREF, IREF },
2260Sstevel@tonic-gate { "SYNC", ISYNC, ISYNC },
2270Sstevel@tonic-gate { "FASTSYMLNK", IFASTSYMLNK, IFASTSYMLNK },
2280Sstevel@tonic-gate { "MODACC", IMODACC, IMODACC },
2290Sstevel@tonic-gate { "ATTCHG", IATTCHG, IATTCHG },
2300Sstevel@tonic-gate { "BDWRITE", IBDWRITE, IBDWRITE },
2310Sstevel@tonic-gate { "STALE", ISTALE, ISTALE },
2320Sstevel@tonic-gate { "DEL", IDEL, IDEL },
2330Sstevel@tonic-gate { "DIRECTIO", IDIRECTIO, IDIRECTIO },
2340Sstevel@tonic-gate { "JUNKIQ", IJUNKIQ, IJUNKIQ },
2350Sstevel@tonic-gate { NULL, 0, 0 }
2360Sstevel@tonic-gate };
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate static const mdb_bitmask_t i_modetype_masks[] = {
2390Sstevel@tonic-gate { "p", IFMT, IFIFO },
2400Sstevel@tonic-gate { "c", IFMT, IFCHR },
2410Sstevel@tonic-gate { "d", IFMT, IFDIR },
2420Sstevel@tonic-gate { "b", IFMT, IFBLK },
2430Sstevel@tonic-gate { "-", IFMT, IFREG },
2440Sstevel@tonic-gate { "l", IFMT, IFLNK },
2450Sstevel@tonic-gate { "S", IFMT, IFSHAD },
2460Sstevel@tonic-gate { "s", IFMT, IFSOCK },
2470Sstevel@tonic-gate { "A", IFMT, IFATTRDIR },
2480Sstevel@tonic-gate { NULL, 0, 0 }
2490Sstevel@tonic-gate };
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
2520Sstevel@tonic-gate return (DCMD_USAGE);
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate if (mdb_getopts(argc, argv,
2550Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
2560Sstevel@tonic-gate return (DCMD_USAGE);
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
2590Sstevel@tonic-gate mdb_printf("%<u>%-?s %10s %1s %5s %8s",
2600Sstevel@tonic-gate "ADDR", "INUMBER", "T", "MODE", "SIZE");
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate if (verbose)
2630Sstevel@tonic-gate mdb_printf(" %11s %-22s%</u>\n", "DEVICE", "FLAG");
2640Sstevel@tonic-gate else
2650Sstevel@tonic-gate mdb_printf(" %-12s %-21s%</u>\n", "MTIME", "NAME");
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
2690Sstevel@tonic-gate mdb_warn("failed to read inode_t at %p", addr);
2700Sstevel@tonic-gate return (DCMD_ERR);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate mdb_printf("%0?p %10lld %b %5#o %8llx",
2740Sstevel@tonic-gate addr, (u_longlong_t)inode.i_number, inode.i_mode, i_modetype_masks,
2750Sstevel@tonic-gate inode.i_mode & ~IFMT, inode.i_size);
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate if (verbose) {
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate mdb_printf(" %11lx <%b>\n",
2800Sstevel@tonic-gate inode.i_dev, inode.i_flag, i_flag_masks);
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate mdb_inc_indent(2);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate mdb_printf("%Y\n", inode.i_mtime.tv_sec);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate if (mdb_vnode2path((uintptr_t)inode.i_vnode, path,
2870Sstevel@tonic-gate sizeof (path)) == 0 && *path != '\0')
2880Sstevel@tonic-gate mdb_printf("%s\n", path);
2890Sstevel@tonic-gate else
2900Sstevel@tonic-gate mdb_printf("??\n");
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate mdb_dec_indent(2);
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate return (DCMD_OK);
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * Not verbose, everything must fit into one line.
2990Sstevel@tonic-gate */
3000Sstevel@tonic-gate mdb_snprintf(buf, sizeof (buf), "%Y", inode.i_mtime.tv_sec);
3010Sstevel@tonic-gate buf[17] = '\0'; /* drop seconds */
3020Sstevel@tonic-gate if (buf[0] == '1' || buf[0] == '2')
3030Sstevel@tonic-gate mdb_printf(" %12s", buf + 5); /* drop year */
3040Sstevel@tonic-gate else
3050Sstevel@tonic-gate mdb_printf(" %-12s", "?");
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate if (mdb_vnode2path((uintptr_t)inode.i_vnode, path,
3080Sstevel@tonic-gate sizeof (path)) == 0 && *path != '\0') {
3090Sstevel@tonic-gate if (strlen(path) <= 21)
3100Sstevel@tonic-gate mdb_printf(" %-21s\n", path);
3110Sstevel@tonic-gate else
3120Sstevel@tonic-gate mdb_printf(" ...%-18s\n", path + strlen(path) - 18);
3130Sstevel@tonic-gate } else {
3140Sstevel@tonic-gate mdb_printf(" ??\n");
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate return (DCMD_OK);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate static struct {
3210Sstevel@tonic-gate int am_offset;
3220Sstevel@tonic-gate char *am_tag;
3230Sstevel@tonic-gate } acl_map[] = {
3240Sstevel@tonic-gate { offsetof(si_t, aowner), "USER_OBJ" },
3250Sstevel@tonic-gate { offsetof(si_t, agroup), "GROUP_OBJ" },
3260Sstevel@tonic-gate { offsetof(si_t, aother), "OTHER_OBJ" },
3270Sstevel@tonic-gate { offsetof(si_t, ausers), "USER" },
3280Sstevel@tonic-gate { offsetof(si_t, agroups), "GROUP" },
3290Sstevel@tonic-gate { offsetof(si_t, downer), "DEF_USER_OBJ" },
3300Sstevel@tonic-gate { offsetof(si_t, dgroup), "DEF_GROUP_OBJ" },
3310Sstevel@tonic-gate { offsetof(si_t, dother), "DEF_OTHER_OBJ" },
3320Sstevel@tonic-gate { offsetof(si_t, dusers), "DEF_USER" },
3330Sstevel@tonic-gate { offsetof(si_t, dgroups), "DEF_GROUP" },
3340Sstevel@tonic-gate { -1, NULL }
3350Sstevel@tonic-gate };
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate static int
acl_walk_init(mdb_walk_state_t * wsp)3380Sstevel@tonic-gate acl_walk_init(mdb_walk_state_t *wsp)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
3410Sstevel@tonic-gate inode_t inode;
3420Sstevel@tonic-gate si_t *si;
3430Sstevel@tonic-gate ufs_ic_acl_t **aclpp;
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate if (addr == NULL) {
3460Sstevel@tonic-gate mdb_warn("acl walk needs an inode address\n");
3470Sstevel@tonic-gate return (WALK_ERR);
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate if (mdb_vread(&inode, sizeof (inode), addr) == -1) {
3510Sstevel@tonic-gate mdb_warn("failed to read inode_t at %p", addr);
3520Sstevel@tonic-gate return (WALK_ERR);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate if (inode.i_ufs_acl == NULL)
3560Sstevel@tonic-gate return (WALK_DONE);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate si = mdb_alloc(sizeof (si_t), UM_SLEEP);
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate if (mdb_vread(si, sizeof (si_t), (uintptr_t)inode.i_ufs_acl) == -1) {
3610Sstevel@tonic-gate mdb_warn("failed to read si_t at %p", inode.i_ufs_acl);
3620Sstevel@tonic-gate mdb_free(si, sizeof (si_t));
3630Sstevel@tonic-gate return (WALK_ERR);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate /* LINTED - alignment */
3670Sstevel@tonic-gate aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[0].am_offset);
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)*aclpp;
3700Sstevel@tonic-gate wsp->walk_data = si;
3710Sstevel@tonic-gate wsp->walk_arg = 0;
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate return (WALK_NEXT);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate static int
acl_walk_step(mdb_walk_state_t * wsp)3770Sstevel@tonic-gate acl_walk_step(mdb_walk_state_t *wsp)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr;
3800Sstevel@tonic-gate si_t *si = wsp->walk_data;
3810Sstevel@tonic-gate uint_t i = (uintptr_t)wsp->walk_arg;
3820Sstevel@tonic-gate ufs_ic_acl_t **aclpp;
3830Sstevel@tonic-gate ufs_ic_acl_t acl;
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate while (addr == NULL) {
3860Sstevel@tonic-gate wsp->walk_arg = (void *)(uintptr_t)++i;
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate if (acl_map[i].am_offset == -1)
3890Sstevel@tonic-gate return (WALK_DONE);
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate /* LINTED - alignment */
3920Sstevel@tonic-gate aclpp = (ufs_ic_acl_t **)((caddr_t)si + acl_map[i].am_offset);
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate addr = (uintptr_t)*aclpp;
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate if (mdb_vread(&acl, sizeof (acl), addr) == -1) {
3980Sstevel@tonic-gate mdb_warn("failed to read acl at %p", addr);
3990Sstevel@tonic-gate return (WALK_DONE);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)acl.acl_ic_next;
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate return (wsp->walk_callback(addr, &acl, acl_map[i].am_tag));
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate static void
acl_walk_fini(mdb_walk_state_t * wsp)4080Sstevel@tonic-gate acl_walk_fini(mdb_walk_state_t *wsp)
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (si_t));
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate static int
acl_cb(uintptr_t addr,const void * arg,void * data)4140Sstevel@tonic-gate acl_cb(uintptr_t addr, const void *arg, void *data)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate ufs_ic_acl_t *aclp = (ufs_ic_acl_t *)arg;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate mdb_printf("%?p %-16s %7#o %10d\n",
4190Sstevel@tonic-gate addr, (char *)data, aclp->acl_ic_perm, aclp->acl_ic_who);
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate return (WALK_NEXT);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /*ARGSUSED*/
4250Sstevel@tonic-gate static int
acl_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4260Sstevel@tonic-gate acl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4270Sstevel@tonic-gate {
4280Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
4290Sstevel@tonic-gate return (DCMD_USAGE);
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate if (argc != 0)
4320Sstevel@tonic-gate return (DCMD_USAGE);
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
4350Sstevel@tonic-gate mdb_printf("%<u>%?s %-16s %7s %10s%</u>\n",
4360Sstevel@tonic-gate "ADDR", "TAG", "PERM", "WHO");
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate if (mdb_pwalk("acl", (mdb_walk_cb_t)acl_cb, NULL, addr) == -1) {
4400Sstevel@tonic-gate mdb_warn("can't walk acls of inode %p", addr);
4410Sstevel@tonic-gate return (DCMD_ERR);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate return (DCMD_OK);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate static int
cg_walk_init(mdb_walk_state_t * wsp)4490Sstevel@tonic-gate cg_walk_init(mdb_walk_state_t *wsp)
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate if (mdb_layered_walk("buf", wsp) == -1) {
4520Sstevel@tonic-gate mdb_warn("couldn't walk bio buf hash");
4530Sstevel@tonic-gate return (WALK_ERR);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate return (WALK_NEXT);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate static int
cg_walk_step(mdb_walk_state_t * wsp)4600Sstevel@tonic-gate cg_walk_step(mdb_walk_state_t *wsp)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate uintptr_t addr = (uintptr_t)((const buf_t *)wsp->walk_layer)->b_un.b_cg;
4630Sstevel@tonic-gate struct cg cg;
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate if (mdb_vread(&cg, sizeof (cg), addr) == -1) {
4660Sstevel@tonic-gate mdb_warn("failed to read cg struct at %p", addr);
4670Sstevel@tonic-gate return (WALK_ERR);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate if (cg.cg_magic != CG_MAGIC)
4710Sstevel@tonic-gate return (WALK_NEXT);
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate return (wsp->walk_callback(addr, &cg, wsp->walk_cbdata));
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate static void
pbits(const uchar_t * cp,const int max,const int linelen)4770Sstevel@tonic-gate pbits(const uchar_t *cp, const int max, const int linelen)
4780Sstevel@tonic-gate {
4790Sstevel@tonic-gate int i, j, len;
4800Sstevel@tonic-gate char entry[40];
4810Sstevel@tonic-gate int linecnt = -1;
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate for (i = 0; i < max; i++) {
4840Sstevel@tonic-gate if (isset(cp, i)) {
4850Sstevel@tonic-gate len = mdb_snprintf(entry, sizeof (entry), "%d", i);
4860Sstevel@tonic-gate j = i;
4870Sstevel@tonic-gate while ((i + 1) < max && isset(cp, i+1))
4880Sstevel@tonic-gate i++;
4890Sstevel@tonic-gate if (i != j)
4900Sstevel@tonic-gate len += mdb_snprintf(entry + len,
4910Sstevel@tonic-gate sizeof (entry) - len, "-%d", i);
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (linecnt == -1) {
4940Sstevel@tonic-gate /* first entry */
4950Sstevel@tonic-gate mdb_printf("%s", entry);
4960Sstevel@tonic-gate linecnt = linelen - len;
4970Sstevel@tonic-gate } else if (linecnt - (len + 3) > 0) {
4980Sstevel@tonic-gate /* subsequent entry on same line */
4990Sstevel@tonic-gate mdb_printf(", %s", entry);
5000Sstevel@tonic-gate linecnt -= len + 2;
5010Sstevel@tonic-gate } else {
5020Sstevel@tonic-gate /* subsequent enty on new line */
5030Sstevel@tonic-gate mdb_printf(",\n%s", entry);
5040Sstevel@tonic-gate linecnt = linelen - len;
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate mdb_printf("\n");
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate /*ARGSUSED*/
5120Sstevel@tonic-gate static int
cg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5130Sstevel@tonic-gate cg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate uint_t verbose = FALSE;
5160Sstevel@tonic-gate struct cg cg;
5170Sstevel@tonic-gate struct cg *cgp = &cg;
5180Sstevel@tonic-gate size_t size;
5190Sstevel@tonic-gate int i, j, cnt, off;
5200Sstevel@tonic-gate int32_t *blktot;
5210Sstevel@tonic-gate short *blks;
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
5240Sstevel@tonic-gate if (mdb_walk_dcmd("cg", "cg", argc, argv) == -1) {
5250Sstevel@tonic-gate mdb_warn("can't walk cylinder group structs");
5260Sstevel@tonic-gate return (DCMD_ERR);
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate return (DCMD_OK);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate if (mdb_getopts(argc, argv,
5320Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
5330Sstevel@tonic-gate return (DCMD_USAGE);
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate if (mdb_vread(cgp, sizeof (cg), addr) == -1) {
5360Sstevel@tonic-gate mdb_warn("failed to read cg struct at %p", addr);
5370Sstevel@tonic-gate return (DCMD_ERR);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate if (!verbose) {
5410Sstevel@tonic-gate if (DCMD_HDRSPEC(flags))
5420Sstevel@tonic-gate mdb_printf("%<u>%4s %?s %10s %10s %10s %10s%</u>\n",
5430Sstevel@tonic-gate "CGX", "CG", "NDIR", "NBFREE", "NIFREE", "NFFREE");
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate mdb_printf("%4d %?p %10d %10d %10d %10d\n", cgp->cg_cgx,
5460Sstevel@tonic-gate addr, cgp->cg_cs.cs_ndir, cgp->cg_cs.cs_nbfree,
5470Sstevel@tonic-gate cgp->cg_cs.cs_nifree, cgp->cg_cs.cs_nffree);
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate return (DCMD_OK);
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate /*
5530Sstevel@tonic-gate * Verbose: produce output similiar to "fstyp -v".
5540Sstevel@tonic-gate */
5550Sstevel@tonic-gate if (cgp->cg_btotoff >= cgp->cg_nextfreeoff ||
5560Sstevel@tonic-gate cgp->cg_boff >= cgp->cg_nextfreeoff ||
5570Sstevel@tonic-gate cgp->cg_iusedoff >= cgp->cg_nextfreeoff ||
5580Sstevel@tonic-gate cgp->cg_freeoff >= cgp->cg_nextfreeoff) {
5590Sstevel@tonic-gate mdb_warn("struct cg at %p seems broken\n", addr);
5600Sstevel@tonic-gate return (DCMD_ERR);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate size = cgp->cg_nextfreeoff;
5640Sstevel@tonic-gate cgp = mdb_alloc(size, UM_SLEEP);
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate if (mdb_vread(cgp, size, addr) == -1) {
5670Sstevel@tonic-gate mdb_warn("failed to read struct cg and maps at %p", addr);
5680Sstevel@tonic-gate mdb_free(cgp, size);
5690Sstevel@tonic-gate return (DCMD_ERR);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate mdb_printf("%<b>cg %d (%0?p)%</b>\n", cgp->cg_cgx, addr);
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate mdb_inc_indent(4);
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate mdb_printf("time:\t%Y\n", cgp->cg_time);
5770Sstevel@tonic-gate mdb_printf("ndir:\t%d\n", cgp->cg_cs.cs_ndir);
5780Sstevel@tonic-gate mdb_printf("nbfree:\t%d\n", cgp->cg_cs.cs_nbfree);
5790Sstevel@tonic-gate mdb_printf("nifree:\t%d\n", cgp->cg_cs.cs_nifree);
5800Sstevel@tonic-gate mdb_printf("nffree:\t%d\n", cgp->cg_cs.cs_nffree);
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate mdb_printf("frsum:");
5830Sstevel@tonic-gate for (i = 1; i < MAXFRAG; i++)
5840Sstevel@tonic-gate mdb_printf("\t%d", cgp->cg_frsum[i]);
5850Sstevel@tonic-gate mdb_printf("\n");
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate off = cgp->cg_iusedoff;
5880Sstevel@tonic-gate mdb_printf("used inode map (%0?p):\n", (char *)addr + off);
5890Sstevel@tonic-gate mdb_inc_indent(4);
5900Sstevel@tonic-gate pbits((uchar_t *)cgp + off, cgp->cg_niblk / sizeof (char), 72);
5910Sstevel@tonic-gate mdb_dec_indent(4);
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate off = cgp->cg_freeoff;
5940Sstevel@tonic-gate mdb_printf("free block map (%0?p):\n", (char *)addr + off);
5950Sstevel@tonic-gate mdb_inc_indent(4);
5960Sstevel@tonic-gate pbits((uchar_t *)cgp + off, cgp->cg_ndblk / sizeof (char), 72);
5970Sstevel@tonic-gate mdb_dec_indent(4);
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate /* LINTED - alignment */
6000Sstevel@tonic-gate blktot = (int32_t *)((char *)cgp + cgp->cg_btotoff);
6010Sstevel@tonic-gate /* LINTED - alignment */
6020Sstevel@tonic-gate blks = (short *)((char *)cgp + cgp->cg_boff);
6030Sstevel@tonic-gate cnt = (cgp->cg_iusedoff - cgp->cg_boff) / cgp->cg_ncyl / sizeof (short);
6040Sstevel@tonic-gate mdb_printf("free block positions:\n");
6050Sstevel@tonic-gate mdb_inc_indent(4);
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate for (i = 0; i < cgp->cg_ncyl; i++) {
6080Sstevel@tonic-gate mdb_printf("c%d:\t(%d)\t", i, blktot[i]);
6090Sstevel@tonic-gate for (j = 0; j < cnt; j++)
6100Sstevel@tonic-gate mdb_printf(" %d", blks[i*cnt + j]);
6110Sstevel@tonic-gate mdb_printf("\n");
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate mdb_dec_indent(4);
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate mdb_printf("\n");
6160Sstevel@tonic-gate mdb_dec_indent(4);
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate mdb_free(cgp, size);
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate return (DCMD_OK);
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate void
inode_cache_help(void)6240Sstevel@tonic-gate inode_cache_help(void)
6250Sstevel@tonic-gate {
6260Sstevel@tonic-gate mdb_printf(
6270Sstevel@tonic-gate "Displays cached inode_t. If an address, an inode number and/or a\n"
6280Sstevel@tonic-gate "device is specified, searches inode cache for inodes which match\n"
6290Sstevel@tonic-gate "the specified criteria. Prints nothing but the address, if\n"
6300Sstevel@tonic-gate "output is a pipe.\n"
6310Sstevel@tonic-gate "\n"
6320Sstevel@tonic-gate "Options:\n"
6330Sstevel@tonic-gate " -d device Filter out inodes, which reside on the specified"
6340Sstevel@tonic-gate " device.\n"
6350Sstevel@tonic-gate " -i inumber Filter out inodes with the specified inode"
6360Sstevel@tonic-gate " number.\n");
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate /*
6400Sstevel@tonic-gate * MDB module linkage
6410Sstevel@tonic-gate */
6420Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
6430Sstevel@tonic-gate { "inode_cache", "?[-d device] [-i inumber]",
6440Sstevel@tonic-gate "search/display inodes from inode cache",
6450Sstevel@tonic-gate inode_cache, inode_cache_help },
6460Sstevel@tonic-gate { "inode", ":[-v]", "display summarized inode_t", inode },
6470Sstevel@tonic-gate { "acl", ":", "given an inode, display its in core acl's", acl_dcmd },
6480Sstevel@tonic-gate { "cg", "?[-v]", "display a summarized cylinder group structure", cg },
649*1619Ssjelinek { "mapentry", ":", "dumps ufslog mapentry", mapentry_dcmd },
650*1619Ssjelinek { "mapstats", ":", "dumps ufslog stats", mapstats_dcmd },
6510Sstevel@tonic-gate { NULL }
6520Sstevel@tonic-gate };
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
6550Sstevel@tonic-gate { "inode_cache", "walk inode cache",
6560Sstevel@tonic-gate inode_walk_init, inode_walk_step, inode_walk_fini },
6570Sstevel@tonic-gate { "acl", "given an inode, walk chains of in core acl's",
6580Sstevel@tonic-gate acl_walk_init, acl_walk_step, acl_walk_fini },
6590Sstevel@tonic-gate { "cg", "walk cg's in bio buffer cache",
6600Sstevel@tonic-gate cg_walk_init, cg_walk_step, NULL },
661*1619Ssjelinek { "ufslogmap", "walk map entries in a ufs_log mt_map",
662*1619Ssjelinek ufslogmap_walk_init, ufslogmap_walk_step, NULL },
6630Sstevel@tonic-gate { NULL }
6640Sstevel@tonic-gate };
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)6690Sstevel@tonic-gate _mdb_init(void)
6700Sstevel@tonic-gate {
6710Sstevel@tonic-gate return (&modinfo);
6720Sstevel@tonic-gate }
673