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 <sys/types.h> 31*0Sstevel@tonic-gate #include <sys/sysmacros.h> 32*0Sstevel@tonic-gate #include <sys/time.h> 33*0Sstevel@tonic-gate #include <sys/vnode.h> 34*0Sstevel@tonic-gate #include <sys/fs/snode.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate typedef struct snode_walk_data { 37*0Sstevel@tonic-gate int sw_stablesz; 38*0Sstevel@tonic-gate uintptr_t sw_stable; 39*0Sstevel@tonic-gate } snode_walk_data_t; 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate int 42*0Sstevel@tonic-gate snode_walk_init(mdb_walk_state_t *wsp) 43*0Sstevel@tonic-gate { 44*0Sstevel@tonic-gate int stablesz; 45*0Sstevel@tonic-gate GElf_Sym sym; 46*0Sstevel@tonic-gate uintptr_t stable; 47*0Sstevel@tonic-gate uintptr_t sp; 48*0Sstevel@tonic-gate snode_walk_data_t *sw; 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate if (mdb_readvar(&stablesz, "stablesz") == -1) { 51*0Sstevel@tonic-gate mdb_warn("failed to read 'stablesz'"); 52*0Sstevel@tonic-gate return (WALK_ERR); 53*0Sstevel@tonic-gate } 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate if (stablesz == 0) 56*0Sstevel@tonic-gate return (WALK_DONE); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate if (mdb_lookup_by_name("stable", &sym) == -1) { 59*0Sstevel@tonic-gate mdb_warn("failed to read 'stable'"); 60*0Sstevel@tonic-gate return (WALK_ERR); 61*0Sstevel@tonic-gate } 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate stable = (uintptr_t)sym.st_value; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate if (mdb_vread(&sp, sizeof (sp), stable) == -1) { 66*0Sstevel@tonic-gate mdb_warn("failed to read stable entry at %p", stable); 67*0Sstevel@tonic-gate return (WALK_DONE); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate sw = mdb_alloc(sizeof (snode_walk_data_t), UM_SLEEP); 71*0Sstevel@tonic-gate sw->sw_stablesz = stablesz; 72*0Sstevel@tonic-gate sw->sw_stable = stable; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate wsp->walk_addr = sp; 75*0Sstevel@tonic-gate wsp->walk_data = sw; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate return (WALK_NEXT); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate int 81*0Sstevel@tonic-gate snode_walk_step(mdb_walk_state_t *wsp) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 84*0Sstevel@tonic-gate snode_walk_data_t *sw = wsp->walk_data; 85*0Sstevel@tonic-gate struct snode *sp; 86*0Sstevel@tonic-gate struct snode snode; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate while (addr == NULL) { 89*0Sstevel@tonic-gate if (--sw->sw_stablesz == 0) 90*0Sstevel@tonic-gate return (WALK_DONE); 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate sw->sw_stable += sizeof (struct snode *); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate if (mdb_vread(&sp, sizeof (sp), sw->sw_stable) == -1) { 95*0Sstevel@tonic-gate mdb_warn("failed to read stable entry at %p", 96*0Sstevel@tonic-gate sw->sw_stable); 97*0Sstevel@tonic-gate return (WALK_DONE); 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate addr = (uintptr_t)sp; 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if (mdb_vread(&snode, sizeof (snode), addr) == -1) { 103*0Sstevel@tonic-gate mdb_warn("failed to read snode at %p", addr); 104*0Sstevel@tonic-gate return (WALK_DONE); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)snode.s_next; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate return (wsp->walk_callback(addr, &snode, wsp->walk_cbdata)); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate void 113*0Sstevel@tonic-gate snode_walk_fini(mdb_walk_state_t *wsp) 114*0Sstevel@tonic-gate { 115*0Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (snode_walk_data_t)); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate typedef struct snode_cbdata { 119*0Sstevel@tonic-gate int sd_major; 120*0Sstevel@tonic-gate int sd_minor; 121*0Sstevel@tonic-gate int sd_verbose; 122*0Sstevel@tonic-gate } snode_cbdata_t; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate static int 125*0Sstevel@tonic-gate snode_cb(uintptr_t addr, const struct snode *snode, snode_cbdata_t *sd) 126*0Sstevel@tonic-gate { 127*0Sstevel@tonic-gate static const mdb_bitmask_t s_flag_masks[] = { 128*0Sstevel@tonic-gate { "UPD", SUPD, SUPD }, 129*0Sstevel@tonic-gate { "ACC", SACC, SACC }, 130*0Sstevel@tonic-gate { "CHG", SCHG, SCHG }, 131*0Sstevel@tonic-gate { "PRIV", SPRIV, SPRIV }, 132*0Sstevel@tonic-gate { "LOFFSET", SLOFFSET, SLOFFSET }, 133*0Sstevel@tonic-gate { "LOCKED", SLOCKED, SLOCKED }, 134*0Sstevel@tonic-gate { "WANT", SWANT, SWANT }, 135*0Sstevel@tonic-gate { "CLONE", SCLONE, SCLONE }, 136*0Sstevel@tonic-gate { "NEEDCLOSE", SNEEDCLOSE, SNEEDCLOSE }, 137*0Sstevel@tonic-gate { "DIPSET", SDIPSET, SDIPSET }, 138*0Sstevel@tonic-gate { "SIZEVALID", SSIZEVALID, SSIZEVALID }, 139*0Sstevel@tonic-gate { NULL, 0, 0 } 140*0Sstevel@tonic-gate }; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate int major = getmajor(snode->s_dev); 143*0Sstevel@tonic-gate int minor = getminor(snode->s_dev); 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if (sd->sd_major != -1 && sd->sd_major != major) 146*0Sstevel@tonic-gate return (WALK_NEXT); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (sd->sd_minor != -1 && sd->sd_minor != minor) 149*0Sstevel@tonic-gate return (WALK_NEXT); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (sd->sd_verbose) { 152*0Sstevel@tonic-gate mdb_printf("%0?p %?p %6d %16lx <%b>\n", 153*0Sstevel@tonic-gate addr, snode->s_vnode, snode->s_count, snode->s_dev, 154*0Sstevel@tonic-gate snode->s_flag, s_flag_masks); 155*0Sstevel@tonic-gate } else { 156*0Sstevel@tonic-gate mdb_printf("%p\n", addr); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate return (WALK_NEXT); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate /*ARGSUSED*/ 163*0Sstevel@tonic-gate int 164*0Sstevel@tonic-gate snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate snode_cbdata_t sd; 167*0Sstevel@tonic-gate struct snode snode; 168*0Sstevel@tonic-gate uintptr_t major = 0, dev = 0; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate sd.sd_major = -1; 171*0Sstevel@tonic-gate sd.sd_minor = -1; 172*0Sstevel@tonic-gate sd.sd_verbose = !(flags & DCMD_PIPE_OUT); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate if (mdb_getopts(argc, argv, 175*0Sstevel@tonic-gate 'm', MDB_OPT_UINTPTR, &major, 176*0Sstevel@tonic-gate 'd', MDB_OPT_UINTPTR, &dev, NULL) != argc) 177*0Sstevel@tonic-gate return (DCMD_USAGE); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate if (dev != 0) { 180*0Sstevel@tonic-gate sd.sd_major = getmajor(dev); 181*0Sstevel@tonic-gate sd.sd_minor = getminor(dev); 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate if (major != 0) 185*0Sstevel@tonic-gate sd.sd_major = major; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) { 188*0Sstevel@tonic-gate mdb_printf("%<u>%?s %?s %6s %16s %-15s%</u>\n", 189*0Sstevel@tonic-gate "ADDR", "VNODE", "COUNT", "DEV", "FLAG"); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 193*0Sstevel@tonic-gate if (mdb_walk("snode", (mdb_walk_cb_t)snode_cb, &sd) == -1) { 194*0Sstevel@tonic-gate mdb_warn("can't walk snodes"); 195*0Sstevel@tonic-gate return (DCMD_ERR); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate return (DCMD_OK); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if (mdb_vread(&snode, sizeof (snode), addr) == -1) { 201*0Sstevel@tonic-gate mdb_warn("failed to read snode structure at %p", addr); 202*0Sstevel@tonic-gate return (DCMD_ERR); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate snode_cb(addr, &snode, &sd); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate return (DCMD_OK); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /*ARGSUSED3*/ 211*0Sstevel@tonic-gate int 212*0Sstevel@tonic-gate major2snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 213*0Sstevel@tonic-gate { 214*0Sstevel@tonic-gate snode_cbdata_t sd; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 217*0Sstevel@tonic-gate return (DCMD_USAGE); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate sd.sd_major = addr; 220*0Sstevel@tonic-gate sd.sd_minor = -1; 221*0Sstevel@tonic-gate sd.sd_verbose = 0; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate if (mdb_pwalk("snode", (mdb_walk_cb_t)snode_cb, &sd, 0) != 0) 224*0Sstevel@tonic-gate return (DCMD_ERR); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate return (DCMD_OK); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /*ARGSUSED3*/ 230*0Sstevel@tonic-gate int 231*0Sstevel@tonic-gate dev2snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 232*0Sstevel@tonic-gate { 233*0Sstevel@tonic-gate snode_cbdata_t sd; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || argc != 0) 236*0Sstevel@tonic-gate return (DCMD_USAGE); 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate sd.sd_major = getmajor(addr); 239*0Sstevel@tonic-gate sd.sd_minor = getminor(addr); 240*0Sstevel@tonic-gate sd.sd_verbose = 0; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (mdb_pwalk("snode", (mdb_walk_cb_t)snode_cb, &sd, 0) != 0) 243*0Sstevel@tonic-gate return (DCMD_ERR); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate return (DCMD_OK); 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate void 249*0Sstevel@tonic-gate snode_help(void) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate mdb_printf("Options:\n" 252*0Sstevel@tonic-gate " -d device filter snodes of the specified dev_t\n" 253*0Sstevel@tonic-gate " -m major filter snodes of the specified major number\n"); 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate /* 257*0Sstevel@tonic-gate * MDB module linkage 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 260*0Sstevel@tonic-gate { "dev2snode", ":", "given a dev_t, return the snode", dev2snode }, 261*0Sstevel@tonic-gate { "major2snode", ":", "given a major number, return the snode(s)", 262*0Sstevel@tonic-gate major2snode }, 263*0Sstevel@tonic-gate { "snode", "?[-d device] [-m major]", 264*0Sstevel@tonic-gate "filter and display snode structures", snode, snode_help }, 265*0Sstevel@tonic-gate { NULL } 266*0Sstevel@tonic-gate }; 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 269*0Sstevel@tonic-gate { "snode", "walk global snode lists", 270*0Sstevel@tonic-gate snode_walk_init, snode_walk_step, snode_walk_fini }, 271*0Sstevel@tonic-gate { NULL } 272*0Sstevel@tonic-gate }; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate const mdb_modinfo_t * 277*0Sstevel@tonic-gate _mdb_init(void) 278*0Sstevel@tonic-gate { 279*0Sstevel@tonic-gate return (&modinfo); 280*0Sstevel@tonic-gate } 281