xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/zone.c (revision b885580b43755ee4ea1e280b85428893d2ba9291)
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