diff options
Diffstat (limited to 'usr/src/cmd/mdb/common/modules/genunix/zone.c')
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/zone.c | 163 |
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); } |