Home | History | Annotate | Download | only in genunix
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <mdb/mdb_param.h>
     27 #include <mdb/mdb_modapi.h>
     28 #include <mdb/mdb_ks.h>
     29 
     30 #include "zone.h"
     31 
     32 #include <stddef.h>
     33 #include <sys/zone.h>
     34 
     35 #define	ZONE_NAMELEN	20
     36 #ifdef _LP64
     37 #define	ZONE_PATHLEN	32
     38 #else
     39 #define	ZONE_PATHLEN	40
     40 #endif
     41 
     42 int
     43 zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
     44 {
     45 	zone_t zn;
     46 	char name[ZONE_NAMELEN];
     47 	char path[ZONE_PATHLEN];
     48 	int len;
     49 
     50 	if (argc != 0)
     51 		return (DCMD_USAGE);
     52 
     53 	if (!(flags & DCMD_ADDRSPEC)) {
     54 		if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) {
     55 			mdb_warn("can't walk zones");
     56 			return (DCMD_ERR);
     57 		}
     58 		return (DCMD_OK);
     59 	}
     60 	if (DCMD_HDRSPEC(flags)) {
     61 		mdb_printf("%<u>%?s %6s %-20s %-s%</u>\n",
     62 		    "ADDR", "ID", "NAME", "PATH");
     63 	}
     64 	if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) {
     65 		mdb_warn("can't read zone_t structure at %p", addr);
     66 		return (DCMD_ERR);
     67 	}
     68 	len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name);
     69 	if (len > 0) {
     70 		if (len == ZONE_NAMELEN)
     71 			(void) strcpy(&name[len - 4], "...");
     72 	} else {
     73 		(void) strcpy(name, "??");
     74 	}
     75 	len = mdb_readstr(path, ZONE_PATHLEN, (uintptr_t)zn.zone_rootpath);
     76 	if (len > 0) {
     77 		if (len == ZONE_PATHLEN)
     78 			(void) strcpy(&path[len - 4], "...");
     79 	} else {
     80 		(void) strcpy(path, "??");
     81 	}
     82 	mdb_printf("%0?p %6d %-20s %s\n", addr, zn.zone_id, name, path);
     83 	return (DCMD_OK);
     84 }
     85 
     86 int
     87 zone_walk_init(mdb_walk_state_t *wsp)
     88 {
     89 	GElf_Sym sym;
     90 
     91 	if (wsp->walk_addr == NULL) {
     92 		if (mdb_lookup_by_name("zone_active", &sym) == -1) {
     93 			mdb_warn("failed to find 'zone_active'");
     94 			return (WALK_ERR);
     95 		}
     96 		wsp->walk_addr = (uintptr_t)sym.st_value;
     97 	}
     98 	if (mdb_layered_walk("list", wsp) == -1) {
     99 		mdb_warn("couldn't walk 'list'");
    100 		return (WALK_ERR);
    101 	}
    102 	return (WALK_NEXT);
    103 }
    104 
    105 int
    106 zone_walk_step(mdb_walk_state_t *wsp)
    107 {
    108 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
    109 	    wsp->walk_cbdata));
    110 }
    111 
    112 int
    113 zsd_walk_init(mdb_walk_state_t *wsp)
    114 {
    115 	if (wsp->walk_addr == NULL) {
    116 		mdb_warn("global walk not supported\n");
    117 		return (WALK_ERR);
    118 	}
    119 	wsp->walk_addr += offsetof(struct zone, zone_zsd);
    120 	if (mdb_layered_walk("list", wsp) == -1) {
    121 		mdb_warn("couldn't walk 'list'");
    122 		return (WALK_ERR);
    123 	}
    124 	return (WALK_NEXT);
    125 }
    126 
    127 int
    128 zsd_walk_step(mdb_walk_state_t *wsp)
    129 {
    130 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
    131 	    wsp->walk_cbdata));
    132 }
    133 
    134 /*
    135  * Helper structure used when walking ZSD entries via zsd().
    136  */
    137 struct zsd_cb_data {
    138 	uint_t		keygiven;	/* Was a key specified (are we */
    139 					/* searching for a specific ZSD */
    140 					/* entry)? */
    141 	zone_key_t	key;		/* Key of ZSD for which we're looking */
    142 	uint_t		found;		/* Was the specific ZSD entry found? */
    143 	uint_t		voptgiven;	/* Display verbose information? */
    144 };
    145 
    146 /*
    147  * Helper function for zsd() that displays information from a single ZSD struct.
    148  * 'datap' must point to a valid zsd_cb_data struct.
    149  */
    150 /* ARGSUSED */
    151 static int
    152 zsd_print(uintptr_t addrp, const void * datap, void * privatep)
    153 {
    154 	struct zsd_entry entry;
    155 	struct zsd_cb_data *cbdp;
    156 
    157 	if (mdb_vread(&entry, sizeof (entry), addrp) == -1) {
    158 		mdb_warn("couldn't read zsd_entry at %p", addrp);
    159 		return (WALK_ERR);
    160 	}
    161 	cbdp = (struct zsd_cb_data *)privatep;
    162 
    163 	/*
    164 	 * Are we looking for a single entry specified by a key?  Then make sure
    165 	 * that the current ZSD's key is what we're looking for.
    166 	 */
    167 	if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key)
    168 		return (WALK_NEXT);
    169 
    170 	mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data,
    171 	    entry.zsd_flags);
    172 	if (cbdp->voptgiven == TRUE)
    173 		mdb_printf("    Create CB:   %a\n    Shutdown CB: %a\n"
    174 		    "    Destroy CB:  %a\n", entry.zsd_create,
    175 		    entry.zsd_shutdown, entry.zsd_destroy);
    176 	if (cbdp->keygiven == TRUE) {
    177 		cbdp->found = TRUE;
    178 		return (WALK_DONE);
    179 	}
    180 	return (WALK_NEXT);
    181 }
    182 
    183 int
    184 zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    185 {
    186 	zone_t zone;
    187 	const mdb_arg_t *argp;
    188 	int argcindex;
    189 	struct zsd_cb_data cbd;
    190 	char name[ZONE_NAMELEN];
    191 	int len;
    192 
    193 	/*
    194 	 * Walk all zones if necessary.
    195 	 */
    196 	if (argc > 2)
    197 		return (DCMD_USAGE);
    198 	if ((flags & DCMD_ADDRSPEC) == 0) {
    199 		if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) {
    200 			mdb_warn("failed to walk zone\n");
    201 			return (DCMD_ERR);
    202 		}
    203 		return (DCMD_OK);
    204 	}
    205 
    206 	/*
    207 	 * Make sure a zone_t can be read from the specified address.
    208 	 */
    209 	if (mdb_vread(&zone, sizeof (zone), addr) == -1) {
    210 		mdb_warn("couldn't read zone_t at %p", (void *)addr);
    211 		return (DCMD_ERR);
    212 	}
    213 
    214 	/*
    215 	 * Get the optional arguments (key or -v or both).  Note that
    216 	 * mdb_getopts() will not parse a key argument because it is not
    217 	 * preceded by an option letter.  We'll get around this by requiring
    218 	 * that all options precede the optional key argument.
    219 	 */
    220 	cbd.keygiven = FALSE;
    221 	cbd.voptgiven = FALSE;
    222 	if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v',
    223 	    MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) {
    224 		/*
    225 		 * No options may appear after the key.
    226 		 */
    227 		if (argcindex != argc - 1)
    228 			return (DCMD_USAGE);
    229 
    230 		/*
    231 		 * The missed argument should be a key.
    232 		 */
    233 		argp = &argv[argcindex];
    234 		if (argp->a_type == MDB_TYPE_IMMEDIATE)
    235 			cbd.key = argp->a_un.a_val;
    236 		else
    237 			cbd.key = mdb_strtoull(argp->a_un.a_str);
    238 		cbd.keygiven = TRUE;
    239 		cbd.found = FALSE;
    240 	}
    241 
    242 	/*
    243 	 * Prepare to output the specified zone's ZSD information.
    244 	 */
    245 	if (DCMD_HDRSPEC(flags))
    246 		mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY",
    247 		    "VALUE", "FLAGS");
    248 	len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name);
    249 	if (len > 0) {
    250 		if (len == ZONE_NAMELEN)
    251 			(void) strcpy(&name[len - 4], "...");
    252 	} else {
    253 		(void) strcpy(name, "??");
    254 	}
    255 	mdb_printf("%-20s ", name);
    256 
    257 	/*
    258 	 * Display the requested ZSD entries.
    259 	 */
    260 	mdb_inc_indent(21);
    261 	if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) {
    262 		mdb_warn("failed to walk zsd\n");
    263 		mdb_dec_indent(21);
    264 		return (DCMD_ERR);
    265 	}
    266 	if (cbd.keygiven == TRUE && cbd.found == FALSE) {
    267 		mdb_printf("no corresponding ZSD entry found\n");
    268 		mdb_dec_indent(21);
    269 		return (DCMD_ERR);
    270 	}
    271 	mdb_dec_indent(21);
    272 	return (DCMD_OK);
    273 }
    274