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