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