dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / genunix / zone.c
blobc8f7d6924e70cf9e5ddc9dfd85b6772184d5e4e8
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 #include <mdb/mdb_param.h>
27 #include <mdb/mdb_modapi.h>
28 #include <mdb/mdb_ks.h>
30 #include "zone.h"
32 #include <stddef.h>
33 #include <sys/zone.h>
35 #define ZONE_NAMELEN 20
36 #ifdef _LP64
37 #define ZONE_PATHLEN 32
38 #else
39 #define ZONE_PATHLEN 40
40 #endif
43 * Names corresponding to zone_status_t values in sys/zone.h
45 char *zone_status_names[] = {
46 "uninitialized", /* ZONE_IS_UNINITIALIZED */
47 "initialized", /* ZONE_IS_INITIALIZED */
48 "ready", /* ZONE_IS_READY */
49 "booting", /* ZONE_IS_BOOTING */
50 "running", /* ZONE_IS_RUNNING */
51 "shutting_down", /* ZONE_IS_SHUTTING_DOWN */
52 "empty", /* ZONE_IS_EMPTY */
53 "down", /* ZONE_IS_DOWN */
54 "dying", /* ZONE_IS_DYING */
55 "dead" /* ZONE_IS_DEAD */
58 static int
59 zid_lookup_cb(uintptr_t addr, const zone_t *zone, void *arg)
61 zoneid_t zid = *(uintptr_t *)arg;
62 if (zone->zone_id == zid)
63 mdb_printf("%p\n", addr);
65 return (WALK_NEXT);
68 /*ARGSUSED*/
69 int
70 zid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
72 if (!(flags & DCMD_ADDRSPEC) || argc != 0)
73 return (DCMD_USAGE);
75 if (mdb_walk("zone", (mdb_walk_cb_t)zid_lookup_cb, &addr) == -1) {
76 mdb_warn("failed to walk zone");
77 return (DCMD_ERR);
80 return (DCMD_OK);
83 int
84 zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
86 zone_t zn;
87 char name[ZONE_NAMELEN];
88 char path[ZONE_PATHLEN];
89 int len;
90 uint_t vopt_given;
91 uint_t ropt_given;
93 if (argc > 2)
94 return (DCMD_USAGE);
96 if (!(flags & DCMD_ADDRSPEC)) {
97 if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) {
98 mdb_warn("can't walk zones");
99 return (DCMD_ERR);
101 return (DCMD_OK);
105 * Get the optional -r (reference counts) and -v (verbose output)
106 * arguments.
108 vopt_given = FALSE;
109 ropt_given = FALSE;
110 if (argc > 0 && mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE,
111 &vopt_given, 'r', MDB_OPT_SETBITS, TRUE, &ropt_given, NULL) != argc)
112 return (DCMD_USAGE);
115 * -v can only be specified with -r.
117 if (vopt_given == TRUE && ropt_given == FALSE)
118 return (DCMD_USAGE);
121 * Print a table header, if necessary.
123 if (DCMD_HDRSPEC(flags)) {
124 if (ropt_given == FALSE)
125 mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n",
126 "ADDR", "ID", "STATUS", "NAME", "PATH");
127 else
128 mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n",
129 "ADDR", "ID", "REFS", "CREFS", "NAME");
133 * Read the zone_t structure at the given address and read its name.
135 if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) {
136 mdb_warn("can't read zone_t structure at %p", addr);
137 return (DCMD_ERR);
139 len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name);
140 if (len > 0) {
141 if (len == ZONE_NAMELEN)
142 (void) strcpy(&name[len - 4], "...");
143 } else {
144 (void) strcpy(name, "??");
147 if (ropt_given == FALSE) {
148 char *statusp;
151 * Default display
152 * Fetch the zone's path and print the results.
154 len = mdb_readstr(path, ZONE_PATHLEN,
155 (uintptr_t)zn.zone_rootpath);
156 if (len > 0) {
157 if (len == ZONE_PATHLEN)
158 (void) strcpy(&path[len - 4], "...");
159 } else {
160 (void) strcpy(path, "??");
162 if (zn.zone_status >= ZONE_IS_UNINITIALIZED && zn.zone_status <=
163 ZONE_IS_DEAD)
164 statusp = zone_status_names[zn.zone_status];
165 else
166 statusp = "???";
167 mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id,
168 statusp, name, path);
169 } else {
171 * Display the zone's reference counts.
172 * Display the zone's subsystem-specific reference counts if
173 * the user specified the '-v' option.
175 mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id,
176 zn.zone_ref, zn.zone_cred_ref, name);
177 if (vopt_given == TRUE) {
178 GElf_Sym subsys_names_sym;
179 uintptr_t **zone_ref_subsys_names;
180 uint_t num_subsys;
181 uint_t n;
184 * Read zone_ref_subsys_names from the kernel image.
186 if (mdb_lookup_by_name("zone_ref_subsys_names",
187 &subsys_names_sym) != 0) {
188 mdb_warn("can't find zone_ref_subsys_names");
189 return (DCMD_ERR);
191 if (subsys_names_sym.st_size != ZONE_REF_NUM_SUBSYS *
192 sizeof (char *)) {
193 mdb_warn("number of subsystems in target "
194 "differs from what mdb expects (mismatched"
195 " kernel versions?)");
196 if (subsys_names_sym.st_size <
197 ZONE_REF_NUM_SUBSYS * sizeof (char *))
198 num_subsys = subsys_names_sym.st_size /
199 sizeof (char *);
200 else
201 num_subsys = ZONE_REF_NUM_SUBSYS;
202 } else {
203 num_subsys = ZONE_REF_NUM_SUBSYS;
205 if ((zone_ref_subsys_names = mdb_alloc(
206 subsys_names_sym.st_size, UM_GC)) == NULL) {
207 mdb_warn("out of memory");
208 return (DCMD_ERR);
210 if (mdb_readvar(zone_ref_subsys_names,
211 "zone_ref_subsys_names") == -1) {
212 mdb_warn("can't find zone_ref_subsys_names");
213 return (DCMD_ERR);
217 * Display each subsystem's reference count if it's
218 * nonzero.
220 mdb_inc_indent(7);
221 for (n = 0; n < num_subsys; ++n) {
222 char subsys_name[16];
225 * Skip subsystems lacking outstanding
226 * references.
228 if (zn.zone_subsys_ref[n] == 0)
229 continue;
232 * Each subsystem's name must be read from
233 * the target's image.
235 if (mdb_readstr(subsys_name,
236 sizeof (subsys_name),
237 (uintptr_t)zone_ref_subsys_names[n]) ==
238 -1) {
239 mdb_warn("unable to read subsystem name"
240 " from zone_ref_subsys_names[%u]",
242 return (DCMD_ERR);
244 mdb_printf("%15s: %10u\n", subsys_name,
245 zn.zone_subsys_ref[n]);
247 mdb_dec_indent(7);
250 return (DCMD_OK);
254 zone_walk_init(mdb_walk_state_t *wsp)
256 GElf_Sym sym;
258 if (wsp->walk_addr == (uintptr_t)NULL) {
259 if (mdb_lookup_by_name("zone_active", &sym) == -1) {
260 mdb_warn("failed to find 'zone_active'");
261 return (WALK_ERR);
263 wsp->walk_addr = (uintptr_t)sym.st_value;
265 if (mdb_layered_walk("list", wsp) == -1) {
266 mdb_warn("couldn't walk 'list'");
267 return (WALK_ERR);
269 return (WALK_NEXT);
273 zone_walk_step(mdb_walk_state_t *wsp)
275 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
276 wsp->walk_cbdata));
280 zsd_walk_init(mdb_walk_state_t *wsp)
282 if (wsp->walk_addr == (uintptr_t)NULL) {
283 mdb_warn("global walk not supported\n");
284 return (WALK_ERR);
286 wsp->walk_addr += offsetof(struct zone, zone_zsd);
287 if (mdb_layered_walk("list", wsp) == -1) {
288 mdb_warn("couldn't walk 'list'");
289 return (WALK_ERR);
291 return (WALK_NEXT);
295 zsd_walk_step(mdb_walk_state_t *wsp)
297 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
298 wsp->walk_cbdata));
302 * Helper structure used when walking ZSD entries via zsd().
304 struct zsd_cb_data {
305 uint_t keygiven; /* Was a key specified (are we */
306 /* searching for a specific ZSD */
307 /* entry)? */
308 zone_key_t key; /* Key of ZSD for which we're looking */
309 uint_t found; /* Was the specific ZSD entry found? */
310 uint_t voptgiven; /* Display verbose information? */
314 * Helper function for zsd() that displays information from a single ZSD struct.
315 * 'datap' must point to a valid zsd_cb_data struct.
317 /* ARGSUSED */
318 static int
319 zsd_print(uintptr_t addrp, const void * datap, void * privatep)
321 struct zsd_entry entry;
322 struct zsd_cb_data *cbdp;
324 if (mdb_vread(&entry, sizeof (entry), addrp) == -1) {
325 mdb_warn("couldn't read zsd_entry at %p", addrp);
326 return (WALK_ERR);
328 cbdp = (struct zsd_cb_data *)privatep;
331 * Are we looking for a single entry specified by a key? Then make sure
332 * that the current ZSD's key is what we're looking for.
334 if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key)
335 return (WALK_NEXT);
337 mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data,
338 entry.zsd_flags);
339 if (cbdp->voptgiven == TRUE)
340 mdb_printf(" Create CB: %a\n Shutdown CB: %a\n"
341 " Destroy CB: %a\n", entry.zsd_create,
342 entry.zsd_shutdown, entry.zsd_destroy);
343 if (cbdp->keygiven == TRUE) {
344 cbdp->found = TRUE;
345 return (WALK_DONE);
347 return (WALK_NEXT);
351 zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
353 zone_t zone;
354 const mdb_arg_t *argp;
355 int argcindex;
356 struct zsd_cb_data cbd;
357 char name[ZONE_NAMELEN];
358 int len;
361 * Walk all zones if necessary.
363 if (argc > 2)
364 return (DCMD_USAGE);
365 if ((flags & DCMD_ADDRSPEC) == 0) {
366 if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) {
367 mdb_warn("failed to walk zone\n");
368 return (DCMD_ERR);
370 return (DCMD_OK);
374 * Make sure a zone_t can be read from the specified address.
376 if (mdb_vread(&zone, sizeof (zone), addr) == -1) {
377 mdb_warn("couldn't read zone_t at %p", (void *)addr);
378 return (DCMD_ERR);
382 * Get the optional arguments (key or -v or both). Note that
383 * mdb_getopts() will not parse a key argument because it is not
384 * preceded by an option letter. We'll get around this by requiring
385 * that all options precede the optional key argument.
387 cbd.keygiven = FALSE;
388 cbd.voptgiven = FALSE;
389 if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v',
390 MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) {
392 * No options may appear after the key.
394 if (argcindex != argc - 1)
395 return (DCMD_USAGE);
398 * The missed argument should be a key.
400 argp = &argv[argcindex];
401 if (argp->a_type == MDB_TYPE_IMMEDIATE)
402 cbd.key = argp->a_un.a_val;
403 else
404 cbd.key = mdb_strtoull(argp->a_un.a_str);
405 cbd.keygiven = TRUE;
406 cbd.found = FALSE;
410 * Prepare to output the specified zone's ZSD information.
412 if (DCMD_HDRSPEC(flags))
413 mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY",
414 "VALUE", "FLAGS");
415 len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name);
416 if (len > 0) {
417 if (len == ZONE_NAMELEN)
418 (void) strcpy(&name[len - 4], "...");
419 } else {
420 (void) strcpy(name, "??");
422 mdb_printf("%-20s ", name);
425 * Display the requested ZSD entries.
427 mdb_inc_indent(21);
428 if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) {
429 mdb_warn("failed to walk zsd\n");
430 mdb_dec_indent(21);
431 return (DCMD_ERR);
433 if (cbd.keygiven == TRUE && cbd.found == FALSE) {
434 mdb_printf("no corresponding ZSD entry found\n");
435 mdb_dec_indent(21);
436 return (DCMD_ERR);
438 mdb_dec_indent(21);
439 return (DCMD_OK);