summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/common/modules/genunix/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/mdb/common/modules/genunix/zone.c')
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/zone.c163
1 files changed, 152 insertions, 11 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/zone.c b/usr/src/cmd/mdb/common/modules/genunix/zone.c
index 28912479b3..96f6b598ec 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/zone.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/zone.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <mdb/mdb_param.h>
@@ -39,6 +38,22 @@
#define ZONE_PATHLEN 40
#endif
+/*
+ * Names corresponding to zone_status_t values in sys/zone.h
+ */
+char *zone_status_names[] = {
+ "uninitialized", /* ZONE_IS_UNINITIALIZED */
+ "initialized", /* ZONE_IS_INITIALIZED */
+ "ready", /* ZONE_IS_READY */
+ "booting", /* ZONE_IS_BOOTING */
+ "running", /* ZONE_IS_RUNNING */
+ "shutting_down", /* ZONE_IS_SHUTTING_DOWN */
+ "empty", /* ZONE_IS_EMPTY */
+ "down", /* ZONE_IS_DOWN */
+ "dying", /* ZONE_IS_DYING */
+ "dead" /* ZONE_IS_DEAD */
+};
+
int
zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
@@ -46,8 +61,10 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
char name[ZONE_NAMELEN];
char path[ZONE_PATHLEN];
int len;
+ uint_t vopt_given;
+ uint_t ropt_given;
- if (argc != 0)
+ if (argc > 2)
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC)) {
@@ -57,10 +74,38 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
return (DCMD_OK);
}
+
+ /*
+ * Get the optional -r (reference counts) and -v (verbose output)
+ * arguments.
+ */
+ vopt_given = FALSE;
+ ropt_given = FALSE;
+ if (argc > 0 && mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE,
+ &vopt_given, 'r', MDB_OPT_SETBITS, TRUE, &ropt_given, NULL) != argc)
+ return (DCMD_USAGE);
+
+ /*
+ * -v can only be specified with -r.
+ */
+ if (vopt_given == TRUE && ropt_given == FALSE)
+ return (DCMD_USAGE);
+
+ /*
+ * Print a table header, if necessary.
+ */
if (DCMD_HDRSPEC(flags)) {
- mdb_printf("%<u>%?s %6s %-20s %-s%</u>\n",
- "ADDR", "ID", "NAME", "PATH");
+ if (ropt_given == FALSE)
+ mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n",
+ "ADDR", "ID", "STATUS", "NAME", "PATH");
+ else
+ mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n",
+ "ADDR", "ID", "REFS", "CREFS", "NAME");
}
+
+ /*
+ * Read the zone_t structure at the given address and read its name.
+ */
if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) {
mdb_warn("can't read zone_t structure at %p", addr);
return (DCMD_ERR);
@@ -72,14 +117,110 @@ zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
} else {
(void) strcpy(name, "??");
}
- len = mdb_readstr(path, ZONE_PATHLEN, (uintptr_t)zn.zone_rootpath);
- if (len > 0) {
- if (len == ZONE_PATHLEN)
- (void) strcpy(&path[len - 4], "...");
+
+ if (ropt_given == FALSE) {
+ char *statusp;
+
+ /*
+ * Default display
+ * Fetch the zone's path and print the results.
+ */
+ len = mdb_readstr(path, ZONE_PATHLEN,
+ (uintptr_t)zn.zone_rootpath);
+ if (len > 0) {
+ if (len == ZONE_PATHLEN)
+ (void) strcpy(&path[len - 4], "...");
+ } else {
+ (void) strcpy(path, "??");
+ }
+ if (zn.zone_status >= ZONE_IS_UNINITIALIZED && zn.zone_status <=
+ ZONE_IS_DEAD)
+ statusp = zone_status_names[zn.zone_status];
+ else
+ statusp = "???";
+ mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id,
+ statusp, name, path);
} else {
- (void) strcpy(path, "??");
+ /*
+ * Display the zone's reference counts.
+ * Display the zone's subsystem-specific reference counts if
+ * the user specified the '-v' option.
+ */
+ mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id,
+ zn.zone_ref, zn.zone_cred_ref, name);
+ if (vopt_given == TRUE) {
+ GElf_Sym subsys_names_sym;
+ uintptr_t **zone_ref_subsys_names;
+ uint_t num_subsys;
+ uint_t n;
+
+ /*
+ * Read zone_ref_subsys_names from the kernel image.
+ */
+ if (mdb_lookup_by_name("zone_ref_subsys_names",
+ &subsys_names_sym) != 0) {
+ mdb_warn("can't find zone_ref_subsys_names");
+ return (DCMD_ERR);
+ }
+ if (subsys_names_sym.st_size != ZONE_REF_NUM_SUBSYS *
+ sizeof (char *)) {
+ mdb_warn("number of subsystems in target "
+ "differs from what mdb expects (mismatched"
+ " kernel versions?)");
+ if (subsys_names_sym.st_size <
+ ZONE_REF_NUM_SUBSYS * sizeof (char *))
+ num_subsys = subsys_names_sym.st_size /
+ sizeof (char *);
+ else
+ num_subsys = ZONE_REF_NUM_SUBSYS;
+ } else {
+ num_subsys = ZONE_REF_NUM_SUBSYS;
+ }
+ if ((zone_ref_subsys_names = mdb_alloc(
+ subsys_names_sym.st_size, UM_GC)) == NULL) {
+ mdb_warn("out of memory");
+ return (DCMD_ERR);
+ }
+ if (mdb_readvar(zone_ref_subsys_names,
+ "zone_ref_subsys_names") == -1) {
+ mdb_warn("can't find zone_ref_subsys_names");
+ return (DCMD_ERR);
+ }
+
+ /*
+ * Display each subsystem's reference count if it's
+ * nonzero.
+ */
+ mdb_inc_indent(7);
+ for (n = 0; n < num_subsys; ++n) {
+ char subsys_name[16];
+
+ /*
+ * Skip subsystems lacking outstanding
+ * references.
+ */
+ if (zn.zone_subsys_ref[n] == 0)
+ continue;
+
+ /*
+ * Each subsystem's name must be read from
+ * the target's image.
+ */
+ if (mdb_readstr(subsys_name,
+ sizeof (subsys_name),
+ (uintptr_t)zone_ref_subsys_names[n]) ==
+ -1) {
+ mdb_warn("unable to read subsystem name"
+ " from zone_ref_subsys_names[%u]",
+ n);
+ return (DCMD_ERR);
+ }
+ mdb_printf("%15s: %10u\n", subsys_name,
+ zn.zone_subsys_ref[n]);
+ }
+ mdb_dec_indent(7);
+ }
}
- mdb_printf("%0?p %6d %-20s %s\n", addr, zn.zone_id, name, path);
return (DCMD_OK);
}