17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55b9a3b50Sjv227347 * Common Development and Distribution License (the "License"). 65b9a3b50Sjv227347 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22a19609f8Sjv227347 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23*589efa95SRobert Mustacchi * Copyright (c) 2012, Joyent, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <mdb/mdb_param.h> 277c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 287c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h> 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include "zone.h" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stddef.h> 337c478bd9Sstevel@tonic-gate #include <sys/zone.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #define ZONE_NAMELEN 20 367c478bd9Sstevel@tonic-gate #ifdef _LP64 377c478bd9Sstevel@tonic-gate #define ZONE_PATHLEN 32 387c478bd9Sstevel@tonic-gate #else 397c478bd9Sstevel@tonic-gate #define ZONE_PATHLEN 40 407c478bd9Sstevel@tonic-gate #endif 417c478bd9Sstevel@tonic-gate 42a19609f8Sjv227347 /* 43a19609f8Sjv227347 * Names corresponding to zone_status_t values in sys/zone.h 44a19609f8Sjv227347 */ 45a19609f8Sjv227347 char *zone_status_names[] = { 46a19609f8Sjv227347 "uninitialized", /* ZONE_IS_UNINITIALIZED */ 47a19609f8Sjv227347 "initialized", /* ZONE_IS_INITIALIZED */ 48a19609f8Sjv227347 "ready", /* ZONE_IS_READY */ 49a19609f8Sjv227347 "booting", /* ZONE_IS_BOOTING */ 50a19609f8Sjv227347 "running", /* ZONE_IS_RUNNING */ 51a19609f8Sjv227347 "shutting_down", /* ZONE_IS_SHUTTING_DOWN */ 52a19609f8Sjv227347 "empty", /* ZONE_IS_EMPTY */ 53a19609f8Sjv227347 "down", /* ZONE_IS_DOWN */ 54a19609f8Sjv227347 "dying", /* ZONE_IS_DYING */ 55a19609f8Sjv227347 "dead" /* ZONE_IS_DEAD */ 56a19609f8Sjv227347 }; 57a19609f8Sjv227347 58*589efa95SRobert Mustacchi static int 59*589efa95SRobert Mustacchi zid_lookup_cb(uintptr_t addr, const zone_t *zone, void *arg) 60*589efa95SRobert Mustacchi { 61*589efa95SRobert Mustacchi zoneid_t zid = *(uintptr_t *)arg; 62*589efa95SRobert Mustacchi if (zone->zone_id == zid) 63*589efa95SRobert Mustacchi mdb_printf("%p\n", addr); 64*589efa95SRobert Mustacchi 65*589efa95SRobert Mustacchi return (WALK_NEXT); 66*589efa95SRobert Mustacchi } 67*589efa95SRobert Mustacchi 68*589efa95SRobert Mustacchi /*ARGSUSED*/ 69*589efa95SRobert Mustacchi int 70*589efa95SRobert Mustacchi zid2zone(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 71*589efa95SRobert Mustacchi { 72*589efa95SRobert Mustacchi if (!(flags & DCMD_ADDRSPEC) || argc != 0) 73*589efa95SRobert Mustacchi return (DCMD_USAGE); 74*589efa95SRobert Mustacchi 75*589efa95SRobert Mustacchi if (mdb_walk("zone", (mdb_walk_cb_t)zid_lookup_cb, &addr) == -1) { 76*589efa95SRobert Mustacchi mdb_warn("failed to walk zone"); 77*589efa95SRobert Mustacchi return (DCMD_ERR); 78*589efa95SRobert Mustacchi } 79*589efa95SRobert Mustacchi 80*589efa95SRobert Mustacchi return (DCMD_OK); 81*589efa95SRobert Mustacchi } 82*589efa95SRobert Mustacchi 837c478bd9Sstevel@tonic-gate int 847c478bd9Sstevel@tonic-gate zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate zone_t zn; 877c478bd9Sstevel@tonic-gate char name[ZONE_NAMELEN]; 887c478bd9Sstevel@tonic-gate char path[ZONE_PATHLEN]; 897c478bd9Sstevel@tonic-gate int len; 90a19609f8Sjv227347 uint_t vopt_given; 91a19609f8Sjv227347 uint_t ropt_given; 927c478bd9Sstevel@tonic-gate 93a19609f8Sjv227347 if (argc > 2) 947c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 977c478bd9Sstevel@tonic-gate if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) { 987c478bd9Sstevel@tonic-gate mdb_warn("can't walk zones"); 997c478bd9Sstevel@tonic-gate return (DCMD_ERR); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate return (DCMD_OK); 1027c478bd9Sstevel@tonic-gate } 103a19609f8Sjv227347 104a19609f8Sjv227347 /* 105a19609f8Sjv227347 * Get the optional -r (reference counts) and -v (verbose output) 106a19609f8Sjv227347 * arguments. 107a19609f8Sjv227347 */ 108a19609f8Sjv227347 vopt_given = FALSE; 109a19609f8Sjv227347 ropt_given = FALSE; 110a19609f8Sjv227347 if (argc > 0 && mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, 111a19609f8Sjv227347 &vopt_given, 'r', MDB_OPT_SETBITS, TRUE, &ropt_given, NULL) != argc) 112a19609f8Sjv227347 return (DCMD_USAGE); 113a19609f8Sjv227347 114a19609f8Sjv227347 /* 115a19609f8Sjv227347 * -v can only be specified with -r. 116a19609f8Sjv227347 */ 117a19609f8Sjv227347 if (vopt_given == TRUE && ropt_given == FALSE) 118a19609f8Sjv227347 return (DCMD_USAGE); 119a19609f8Sjv227347 120a19609f8Sjv227347 /* 121a19609f8Sjv227347 * Print a table header, if necessary. 122a19609f8Sjv227347 */ 1237c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 124a19609f8Sjv227347 if (ropt_given == FALSE) 125a19609f8Sjv227347 mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n", 126a19609f8Sjv227347 "ADDR", "ID", "STATUS", "NAME", "PATH"); 127a19609f8Sjv227347 else 128a19609f8Sjv227347 mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n", 129a19609f8Sjv227347 "ADDR", "ID", "REFS", "CREFS", "NAME"); 1307c478bd9Sstevel@tonic-gate } 131a19609f8Sjv227347 132a19609f8Sjv227347 /* 133a19609f8Sjv227347 * Read the zone_t structure at the given address and read its name. 134a19609f8Sjv227347 */ 1357c478bd9Sstevel@tonic-gate if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) { 1367c478bd9Sstevel@tonic-gate mdb_warn("can't read zone_t structure at %p", addr); 1377c478bd9Sstevel@tonic-gate return (DCMD_ERR); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name); 1407c478bd9Sstevel@tonic-gate if (len > 0) { 1417c478bd9Sstevel@tonic-gate if (len == ZONE_NAMELEN) 1427c478bd9Sstevel@tonic-gate (void) strcpy(&name[len - 4], "..."); 1437c478bd9Sstevel@tonic-gate } else { 1447c478bd9Sstevel@tonic-gate (void) strcpy(name, "??"); 1457c478bd9Sstevel@tonic-gate } 146a19609f8Sjv227347 147a19609f8Sjv227347 if (ropt_given == FALSE) { 148a19609f8Sjv227347 char *statusp; 149a19609f8Sjv227347 150a19609f8Sjv227347 /* 151a19609f8Sjv227347 * Default display 152a19609f8Sjv227347 * Fetch the zone's path and print the results. 153a19609f8Sjv227347 */ 154a19609f8Sjv227347 len = mdb_readstr(path, ZONE_PATHLEN, 155a19609f8Sjv227347 (uintptr_t)zn.zone_rootpath); 1567c478bd9Sstevel@tonic-gate if (len > 0) { 1577c478bd9Sstevel@tonic-gate if (len == ZONE_PATHLEN) 1587c478bd9Sstevel@tonic-gate (void) strcpy(&path[len - 4], "..."); 1597c478bd9Sstevel@tonic-gate } else { 1607c478bd9Sstevel@tonic-gate (void) strcpy(path, "??"); 1617c478bd9Sstevel@tonic-gate } 162a19609f8Sjv227347 if (zn.zone_status >= ZONE_IS_UNINITIALIZED && zn.zone_status <= 163a19609f8Sjv227347 ZONE_IS_DEAD) 164a19609f8Sjv227347 statusp = zone_status_names[zn.zone_status]; 165a19609f8Sjv227347 else 166a19609f8Sjv227347 statusp = "???"; 167a19609f8Sjv227347 mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id, 168a19609f8Sjv227347 statusp, name, path); 169a19609f8Sjv227347 } else { 170a19609f8Sjv227347 /* 171a19609f8Sjv227347 * Display the zone's reference counts. 172a19609f8Sjv227347 * Display the zone's subsystem-specific reference counts if 173a19609f8Sjv227347 * the user specified the '-v' option. 174a19609f8Sjv227347 */ 175a19609f8Sjv227347 mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id, 176a19609f8Sjv227347 zn.zone_ref, zn.zone_cred_ref, name); 177a19609f8Sjv227347 if (vopt_given == TRUE) { 178a19609f8Sjv227347 GElf_Sym subsys_names_sym; 179a19609f8Sjv227347 uintptr_t **zone_ref_subsys_names; 180a19609f8Sjv227347 uint_t num_subsys; 181a19609f8Sjv227347 uint_t n; 182a19609f8Sjv227347 183a19609f8Sjv227347 /* 184a19609f8Sjv227347 * Read zone_ref_subsys_names from the kernel image. 185a19609f8Sjv227347 */ 186a19609f8Sjv227347 if (mdb_lookup_by_name("zone_ref_subsys_names", 187a19609f8Sjv227347 &subsys_names_sym) != 0) { 188a19609f8Sjv227347 mdb_warn("can't find zone_ref_subsys_names"); 189a19609f8Sjv227347 return (DCMD_ERR); 190a19609f8Sjv227347 } 191a19609f8Sjv227347 if (subsys_names_sym.st_size != ZONE_REF_NUM_SUBSYS * 192a19609f8Sjv227347 sizeof (char *)) { 193a19609f8Sjv227347 mdb_warn("number of subsystems in target " 194a19609f8Sjv227347 "differs from what mdb expects (mismatched" 195a19609f8Sjv227347 " kernel versions?)"); 196a19609f8Sjv227347 if (subsys_names_sym.st_size < 197a19609f8Sjv227347 ZONE_REF_NUM_SUBSYS * sizeof (char *)) 198a19609f8Sjv227347 num_subsys = subsys_names_sym.st_size / 199a19609f8Sjv227347 sizeof (char *); 200a19609f8Sjv227347 else 201a19609f8Sjv227347 num_subsys = ZONE_REF_NUM_SUBSYS; 202a19609f8Sjv227347 } else { 203a19609f8Sjv227347 num_subsys = ZONE_REF_NUM_SUBSYS; 204a19609f8Sjv227347 } 205a19609f8Sjv227347 if ((zone_ref_subsys_names = mdb_alloc( 206a19609f8Sjv227347 subsys_names_sym.st_size, UM_GC)) == NULL) { 207a19609f8Sjv227347 mdb_warn("out of memory"); 208a19609f8Sjv227347 return (DCMD_ERR); 209a19609f8Sjv227347 } 210a19609f8Sjv227347 if (mdb_readvar(zone_ref_subsys_names, 211a19609f8Sjv227347 "zone_ref_subsys_names") == -1) { 212a19609f8Sjv227347 mdb_warn("can't find zone_ref_subsys_names"); 213a19609f8Sjv227347 return (DCMD_ERR); 214a19609f8Sjv227347 } 215a19609f8Sjv227347 216a19609f8Sjv227347 /* 217a19609f8Sjv227347 * Display each subsystem's reference count if it's 218a19609f8Sjv227347 * nonzero. 219a19609f8Sjv227347 */ 220a19609f8Sjv227347 mdb_inc_indent(7); 221a19609f8Sjv227347 for (n = 0; n < num_subsys; ++n) { 222a19609f8Sjv227347 char subsys_name[16]; 223a19609f8Sjv227347 224a19609f8Sjv227347 /* 225a19609f8Sjv227347 * Skip subsystems lacking outstanding 226a19609f8Sjv227347 * references. 227a19609f8Sjv227347 */ 228a19609f8Sjv227347 if (zn.zone_subsys_ref[n] == 0) 229a19609f8Sjv227347 continue; 230a19609f8Sjv227347 231a19609f8Sjv227347 /* 232a19609f8Sjv227347 * Each subsystem's name must be read from 233a19609f8Sjv227347 * the target's image. 234a19609f8Sjv227347 */ 235a19609f8Sjv227347 if (mdb_readstr(subsys_name, 236a19609f8Sjv227347 sizeof (subsys_name), 237a19609f8Sjv227347 (uintptr_t)zone_ref_subsys_names[n]) == 238a19609f8Sjv227347 -1) { 239a19609f8Sjv227347 mdb_warn("unable to read subsystem name" 240a19609f8Sjv227347 " from zone_ref_subsys_names[%u]", 241a19609f8Sjv227347 n); 242a19609f8Sjv227347 return (DCMD_ERR); 243a19609f8Sjv227347 } 244a19609f8Sjv227347 mdb_printf("%15s: %10u\n", subsys_name, 245a19609f8Sjv227347 zn.zone_subsys_ref[n]); 246a19609f8Sjv227347 } 247a19609f8Sjv227347 mdb_dec_indent(7); 248a19609f8Sjv227347 } 249a19609f8Sjv227347 } 2507c478bd9Sstevel@tonic-gate return (DCMD_OK); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate int 2547c478bd9Sstevel@tonic-gate zone_walk_init(mdb_walk_state_t *wsp) 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate GElf_Sym sym; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2597c478bd9Sstevel@tonic-gate if (mdb_lookup_by_name("zone_active", &sym) == -1) { 2607c478bd9Sstevel@tonic-gate mdb_warn("failed to find 'zone_active'"); 2617c478bd9Sstevel@tonic-gate return (WALK_ERR); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)sym.st_value; 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate if (mdb_layered_walk("list", wsp) == -1) { 2667c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk 'list'"); 2677c478bd9Sstevel@tonic-gate return (WALK_ERR); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate return (WALK_NEXT); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate zone_walk_step(mdb_walk_state_t *wsp) 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2767c478bd9Sstevel@tonic-gate wsp->walk_cbdata)); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate int 2807c478bd9Sstevel@tonic-gate zsd_walk_init(mdb_walk_state_t *wsp) 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2837c478bd9Sstevel@tonic-gate mdb_warn("global walk not supported\n"); 2847c478bd9Sstevel@tonic-gate return (WALK_ERR); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate wsp->walk_addr += offsetof(struct zone, zone_zsd); 2877c478bd9Sstevel@tonic-gate if (mdb_layered_walk("list", wsp) == -1) { 2887c478bd9Sstevel@tonic-gate mdb_warn("couldn't walk 'list'"); 2897c478bd9Sstevel@tonic-gate return (WALK_ERR); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate return (WALK_NEXT); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate int 2957c478bd9Sstevel@tonic-gate zsd_walk_step(mdb_walk_state_t *wsp) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2987c478bd9Sstevel@tonic-gate wsp->walk_cbdata)); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3015b9a3b50Sjv227347 /* 3025b9a3b50Sjv227347 * Helper structure used when walking ZSD entries via zsd(). 3035b9a3b50Sjv227347 */ 3047c478bd9Sstevel@tonic-gate struct zsd_cb_data { 3055b9a3b50Sjv227347 uint_t keygiven; /* Was a key specified (are we */ 3065b9a3b50Sjv227347 /* searching for a specific ZSD */ 3075b9a3b50Sjv227347 /* entry)? */ 3085b9a3b50Sjv227347 zone_key_t key; /* Key of ZSD for which we're looking */ 3095b9a3b50Sjv227347 uint_t found; /* Was the specific ZSD entry found? */ 3105b9a3b50Sjv227347 uint_t voptgiven; /* Display verbose information? */ 3117c478bd9Sstevel@tonic-gate }; 3127c478bd9Sstevel@tonic-gate 3135b9a3b50Sjv227347 /* 3145b9a3b50Sjv227347 * Helper function for zsd() that displays information from a single ZSD struct. 3155b9a3b50Sjv227347 * 'datap' must point to a valid zsd_cb_data struct. 3165b9a3b50Sjv227347 */ 3177c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3187c478bd9Sstevel@tonic-gate static int 3195b9a3b50Sjv227347 zsd_print(uintptr_t addrp, const void * datap, void * privatep) 3207c478bd9Sstevel@tonic-gate { 3215b9a3b50Sjv227347 struct zsd_entry entry; 3225b9a3b50Sjv227347 struct zsd_cb_data *cbdp; 3237c478bd9Sstevel@tonic-gate 3245b9a3b50Sjv227347 if (mdb_vread(&entry, sizeof (entry), addrp) == -1) { 3255b9a3b50Sjv227347 mdb_warn("couldn't read zsd_entry at %p", addrp); 3267c478bd9Sstevel@tonic-gate return (WALK_ERR); 3277c478bd9Sstevel@tonic-gate } 3285b9a3b50Sjv227347 cbdp = (struct zsd_cb_data *)privatep; 3295b9a3b50Sjv227347 3305b9a3b50Sjv227347 /* 3315b9a3b50Sjv227347 * Are we looking for a single entry specified by a key? Then make sure 3325b9a3b50Sjv227347 * that the current ZSD's key is what we're looking for. 3335b9a3b50Sjv227347 */ 3345b9a3b50Sjv227347 if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key) 3357c478bd9Sstevel@tonic-gate return (WALK_NEXT); 3365b9a3b50Sjv227347 3375b9a3b50Sjv227347 mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data, 3385b9a3b50Sjv227347 entry.zsd_flags); 3395b9a3b50Sjv227347 if (cbdp->voptgiven == TRUE) 3405b9a3b50Sjv227347 mdb_printf(" Create CB: %a\n Shutdown CB: %a\n" 3415b9a3b50Sjv227347 " Destroy CB: %a\n", entry.zsd_create, 3425b9a3b50Sjv227347 entry.zsd_shutdown, entry.zsd_destroy); 3435b9a3b50Sjv227347 if (cbdp->keygiven == TRUE) { 3445b9a3b50Sjv227347 cbdp->found = TRUE; 3457c478bd9Sstevel@tonic-gate return (WALK_DONE); 3467c478bd9Sstevel@tonic-gate } 3475b9a3b50Sjv227347 return (WALK_NEXT); 3485b9a3b50Sjv227347 } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate int 3517c478bd9Sstevel@tonic-gate zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate zone_t zone; 3545b9a3b50Sjv227347 const mdb_arg_t *argp; 3555b9a3b50Sjv227347 int argcindex; 3567c478bd9Sstevel@tonic-gate struct zsd_cb_data cbd; 3575b9a3b50Sjv227347 char name[ZONE_NAMELEN]; 3585b9a3b50Sjv227347 int len; 3597c478bd9Sstevel@tonic-gate 3605b9a3b50Sjv227347 /* 3615b9a3b50Sjv227347 * Walk all zones if necessary. 3625b9a3b50Sjv227347 */ 3635b9a3b50Sjv227347 if (argc > 2) 3647c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 3655b9a3b50Sjv227347 if ((flags & DCMD_ADDRSPEC) == 0) { 3665b9a3b50Sjv227347 if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) { 3675b9a3b50Sjv227347 mdb_warn("failed to walk zone\n"); 3685b9a3b50Sjv227347 return (DCMD_ERR); 3695b9a3b50Sjv227347 } 3705b9a3b50Sjv227347 return (DCMD_OK); 3715b9a3b50Sjv227347 } 3725b9a3b50Sjv227347 3735b9a3b50Sjv227347 /* 3745b9a3b50Sjv227347 * Make sure a zone_t can be read from the specified address. 3755b9a3b50Sjv227347 */ 3765b9a3b50Sjv227347 if (mdb_vread(&zone, sizeof (zone), addr) == -1) { 3775b9a3b50Sjv227347 mdb_warn("couldn't read zone_t at %p", (void *)addr); 3785b9a3b50Sjv227347 return (DCMD_ERR); 3795b9a3b50Sjv227347 } 3805b9a3b50Sjv227347 3815b9a3b50Sjv227347 /* 3825b9a3b50Sjv227347 * Get the optional arguments (key or -v or both). Note that 3835b9a3b50Sjv227347 * mdb_getopts() will not parse a key argument because it is not 3845b9a3b50Sjv227347 * preceded by an option letter. We'll get around this by requiring 3855b9a3b50Sjv227347 * that all options precede the optional key argument. 3865b9a3b50Sjv227347 */ 3875b9a3b50Sjv227347 cbd.keygiven = FALSE; 3885b9a3b50Sjv227347 cbd.voptgiven = FALSE; 3895b9a3b50Sjv227347 if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v', 3905b9a3b50Sjv227347 MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) { 3915b9a3b50Sjv227347 /* 3925b9a3b50Sjv227347 * No options may appear after the key. 3935b9a3b50Sjv227347 */ 3945b9a3b50Sjv227347 if (argcindex != argc - 1) 3955b9a3b50Sjv227347 return (DCMD_USAGE); 3965b9a3b50Sjv227347 3975b9a3b50Sjv227347 /* 3985b9a3b50Sjv227347 * The missed argument should be a key. 3995b9a3b50Sjv227347 */ 4005b9a3b50Sjv227347 argp = &argv[argcindex]; 4017c478bd9Sstevel@tonic-gate if (argp->a_type == MDB_TYPE_IMMEDIATE) 4025b9a3b50Sjv227347 cbd.key = argp->a_un.a_val; 4037c478bd9Sstevel@tonic-gate else 4045b9a3b50Sjv227347 cbd.key = mdb_strtoull(argp->a_un.a_str); 4055b9a3b50Sjv227347 cbd.keygiven = TRUE; 4065b9a3b50Sjv227347 cbd.found = FALSE; 4077c478bd9Sstevel@tonic-gate } 4085b9a3b50Sjv227347 4095b9a3b50Sjv227347 /* 4105b9a3b50Sjv227347 * Prepare to output the specified zone's ZSD information. 4115b9a3b50Sjv227347 */ 4125b9a3b50Sjv227347 if (DCMD_HDRSPEC(flags)) 4135b9a3b50Sjv227347 mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY", 4145b9a3b50Sjv227347 "VALUE", "FLAGS"); 4155b9a3b50Sjv227347 len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name); 4165b9a3b50Sjv227347 if (len > 0) { 4175b9a3b50Sjv227347 if (len == ZONE_NAMELEN) 4185b9a3b50Sjv227347 (void) strcpy(&name[len - 4], "..."); 4195b9a3b50Sjv227347 } else { 4205b9a3b50Sjv227347 (void) strcpy(name, "??"); 4215b9a3b50Sjv227347 } 4225b9a3b50Sjv227347 mdb_printf("%-20s ", name); 4235b9a3b50Sjv227347 4245b9a3b50Sjv227347 /* 4255b9a3b50Sjv227347 * Display the requested ZSD entries. 4265b9a3b50Sjv227347 */ 4275b9a3b50Sjv227347 mdb_inc_indent(21); 4285b9a3b50Sjv227347 if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) { 4297c478bd9Sstevel@tonic-gate mdb_warn("failed to walk zsd\n"); 4305b9a3b50Sjv227347 mdb_dec_indent(21); 4317c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4327c478bd9Sstevel@tonic-gate } 4335b9a3b50Sjv227347 if (cbd.keygiven == TRUE && cbd.found == FALSE) { 4345b9a3b50Sjv227347 mdb_printf("no corresponding ZSD entry found\n"); 4355b9a3b50Sjv227347 mdb_dec_indent(21); 4367c478bd9Sstevel@tonic-gate return (DCMD_ERR); 4377c478bd9Sstevel@tonic-gate } 4385b9a3b50Sjv227347 mdb_dec_indent(21); 4397c478bd9Sstevel@tonic-gate return (DCMD_OK); 4407c478bd9Sstevel@tonic-gate } 441