10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 58111SJordan.Vaughan@Sun.com * Common Development and Distribution License (the "License"). 68111SJordan.Vaughan@Sun.com * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*13096SJordan.Vaughan@Sun.com * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate #include <mdb/mdb_param.h> 260Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 270Sstevel@tonic-gate #include <mdb/mdb_ks.h> 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include "zone.h" 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <stddef.h> 320Sstevel@tonic-gate #include <sys/zone.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #define ZONE_NAMELEN 20 350Sstevel@tonic-gate #ifdef _LP64 360Sstevel@tonic-gate #define ZONE_PATHLEN 32 370Sstevel@tonic-gate #else 380Sstevel@tonic-gate #define ZONE_PATHLEN 40 390Sstevel@tonic-gate #endif 400Sstevel@tonic-gate 41*13096SJordan.Vaughan@Sun.com /* 42*13096SJordan.Vaughan@Sun.com * Names corresponding to zone_status_t values in sys/zone.h 43*13096SJordan.Vaughan@Sun.com */ 44*13096SJordan.Vaughan@Sun.com char *zone_status_names[] = { 45*13096SJordan.Vaughan@Sun.com "uninitialized", /* ZONE_IS_UNINITIALIZED */ 46*13096SJordan.Vaughan@Sun.com "initialized", /* ZONE_IS_INITIALIZED */ 47*13096SJordan.Vaughan@Sun.com "ready", /* ZONE_IS_READY */ 48*13096SJordan.Vaughan@Sun.com "booting", /* ZONE_IS_BOOTING */ 49*13096SJordan.Vaughan@Sun.com "running", /* ZONE_IS_RUNNING */ 50*13096SJordan.Vaughan@Sun.com "shutting_down", /* ZONE_IS_SHUTTING_DOWN */ 51*13096SJordan.Vaughan@Sun.com "empty", /* ZONE_IS_EMPTY */ 52*13096SJordan.Vaughan@Sun.com "down", /* ZONE_IS_DOWN */ 53*13096SJordan.Vaughan@Sun.com "dying", /* ZONE_IS_DYING */ 54*13096SJordan.Vaughan@Sun.com "dead" /* ZONE_IS_DEAD */ 55*13096SJordan.Vaughan@Sun.com }; 56*13096SJordan.Vaughan@Sun.com 570Sstevel@tonic-gate int 580Sstevel@tonic-gate zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 590Sstevel@tonic-gate { 600Sstevel@tonic-gate zone_t zn; 610Sstevel@tonic-gate char name[ZONE_NAMELEN]; 620Sstevel@tonic-gate char path[ZONE_PATHLEN]; 630Sstevel@tonic-gate int len; 64*13096SJordan.Vaughan@Sun.com uint_t vopt_given; 65*13096SJordan.Vaughan@Sun.com uint_t ropt_given; 660Sstevel@tonic-gate 67*13096SJordan.Vaughan@Sun.com if (argc > 2) 680Sstevel@tonic-gate return (DCMD_USAGE); 690Sstevel@tonic-gate 700Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 710Sstevel@tonic-gate if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) { 720Sstevel@tonic-gate mdb_warn("can't walk zones"); 730Sstevel@tonic-gate return (DCMD_ERR); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate return (DCMD_OK); 760Sstevel@tonic-gate } 77*13096SJordan.Vaughan@Sun.com 78*13096SJordan.Vaughan@Sun.com /* 79*13096SJordan.Vaughan@Sun.com * Get the optional -r (reference counts) and -v (verbose output) 80*13096SJordan.Vaughan@Sun.com * arguments. 81*13096SJordan.Vaughan@Sun.com */ 82*13096SJordan.Vaughan@Sun.com vopt_given = FALSE; 83*13096SJordan.Vaughan@Sun.com ropt_given = FALSE; 84*13096SJordan.Vaughan@Sun.com if (argc > 0 && mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, 85*13096SJordan.Vaughan@Sun.com &vopt_given, 'r', MDB_OPT_SETBITS, TRUE, &ropt_given, NULL) != argc) 86*13096SJordan.Vaughan@Sun.com return (DCMD_USAGE); 87*13096SJordan.Vaughan@Sun.com 88*13096SJordan.Vaughan@Sun.com /* 89*13096SJordan.Vaughan@Sun.com * -v can only be specified with -r. 90*13096SJordan.Vaughan@Sun.com */ 91*13096SJordan.Vaughan@Sun.com if (vopt_given == TRUE && ropt_given == FALSE) 92*13096SJordan.Vaughan@Sun.com return (DCMD_USAGE); 93*13096SJordan.Vaughan@Sun.com 94*13096SJordan.Vaughan@Sun.com /* 95*13096SJordan.Vaughan@Sun.com * Print a table header, if necessary. 96*13096SJordan.Vaughan@Sun.com */ 970Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) { 98*13096SJordan.Vaughan@Sun.com if (ropt_given == FALSE) 99*13096SJordan.Vaughan@Sun.com mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n", 100*13096SJordan.Vaughan@Sun.com "ADDR", "ID", "STATUS", "NAME", "PATH"); 101*13096SJordan.Vaughan@Sun.com else 102*13096SJordan.Vaughan@Sun.com mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n", 103*13096SJordan.Vaughan@Sun.com "ADDR", "ID", "REFS", "CREFS", "NAME"); 1040Sstevel@tonic-gate } 105*13096SJordan.Vaughan@Sun.com 106*13096SJordan.Vaughan@Sun.com /* 107*13096SJordan.Vaughan@Sun.com * Read the zone_t structure at the given address and read its name. 108*13096SJordan.Vaughan@Sun.com */ 1090Sstevel@tonic-gate if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) { 1100Sstevel@tonic-gate mdb_warn("can't read zone_t structure at %p", addr); 1110Sstevel@tonic-gate return (DCMD_ERR); 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name); 1140Sstevel@tonic-gate if (len > 0) { 1150Sstevel@tonic-gate if (len == ZONE_NAMELEN) 1160Sstevel@tonic-gate (void) strcpy(&name[len - 4], "..."); 1170Sstevel@tonic-gate } else { 1180Sstevel@tonic-gate (void) strcpy(name, "??"); 1190Sstevel@tonic-gate } 120*13096SJordan.Vaughan@Sun.com 121*13096SJordan.Vaughan@Sun.com if (ropt_given == FALSE) { 122*13096SJordan.Vaughan@Sun.com char *statusp; 123*13096SJordan.Vaughan@Sun.com 124*13096SJordan.Vaughan@Sun.com /* 125*13096SJordan.Vaughan@Sun.com * Default display 126*13096SJordan.Vaughan@Sun.com * Fetch the zone's path and print the results. 127*13096SJordan.Vaughan@Sun.com */ 128*13096SJordan.Vaughan@Sun.com len = mdb_readstr(path, ZONE_PATHLEN, 129*13096SJordan.Vaughan@Sun.com (uintptr_t)zn.zone_rootpath); 130*13096SJordan.Vaughan@Sun.com if (len > 0) { 131*13096SJordan.Vaughan@Sun.com if (len == ZONE_PATHLEN) 132*13096SJordan.Vaughan@Sun.com (void) strcpy(&path[len - 4], "..."); 133*13096SJordan.Vaughan@Sun.com } else { 134*13096SJordan.Vaughan@Sun.com (void) strcpy(path, "??"); 135*13096SJordan.Vaughan@Sun.com } 136*13096SJordan.Vaughan@Sun.com if (zn.zone_status >= ZONE_IS_UNINITIALIZED && zn.zone_status <= 137*13096SJordan.Vaughan@Sun.com ZONE_IS_DEAD) 138*13096SJordan.Vaughan@Sun.com statusp = zone_status_names[zn.zone_status]; 139*13096SJordan.Vaughan@Sun.com else 140*13096SJordan.Vaughan@Sun.com statusp = "???"; 141*13096SJordan.Vaughan@Sun.com mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id, 142*13096SJordan.Vaughan@Sun.com statusp, name, path); 1430Sstevel@tonic-gate } else { 144*13096SJordan.Vaughan@Sun.com /* 145*13096SJordan.Vaughan@Sun.com * Display the zone's reference counts. 146*13096SJordan.Vaughan@Sun.com * Display the zone's subsystem-specific reference counts if 147*13096SJordan.Vaughan@Sun.com * the user specified the '-v' option. 148*13096SJordan.Vaughan@Sun.com */ 149*13096SJordan.Vaughan@Sun.com mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id, 150*13096SJordan.Vaughan@Sun.com zn.zone_ref, zn.zone_cred_ref, name); 151*13096SJordan.Vaughan@Sun.com if (vopt_given == TRUE) { 152*13096SJordan.Vaughan@Sun.com GElf_Sym subsys_names_sym; 153*13096SJordan.Vaughan@Sun.com uintptr_t **zone_ref_subsys_names; 154*13096SJordan.Vaughan@Sun.com uint_t num_subsys; 155*13096SJordan.Vaughan@Sun.com uint_t n; 156*13096SJordan.Vaughan@Sun.com 157*13096SJordan.Vaughan@Sun.com /* 158*13096SJordan.Vaughan@Sun.com * Read zone_ref_subsys_names from the kernel image. 159*13096SJordan.Vaughan@Sun.com */ 160*13096SJordan.Vaughan@Sun.com if (mdb_lookup_by_name("zone_ref_subsys_names", 161*13096SJordan.Vaughan@Sun.com &subsys_names_sym) != 0) { 162*13096SJordan.Vaughan@Sun.com mdb_warn("can't find zone_ref_subsys_names"); 163*13096SJordan.Vaughan@Sun.com return (DCMD_ERR); 164*13096SJordan.Vaughan@Sun.com } 165*13096SJordan.Vaughan@Sun.com if (subsys_names_sym.st_size != ZONE_REF_NUM_SUBSYS * 166*13096SJordan.Vaughan@Sun.com sizeof (char *)) { 167*13096SJordan.Vaughan@Sun.com mdb_warn("number of subsystems in target " 168*13096SJordan.Vaughan@Sun.com "differs from what mdb expects (mismatched" 169*13096SJordan.Vaughan@Sun.com " kernel versions?)"); 170*13096SJordan.Vaughan@Sun.com if (subsys_names_sym.st_size < 171*13096SJordan.Vaughan@Sun.com ZONE_REF_NUM_SUBSYS * sizeof (char *)) 172*13096SJordan.Vaughan@Sun.com num_subsys = subsys_names_sym.st_size / 173*13096SJordan.Vaughan@Sun.com sizeof (char *); 174*13096SJordan.Vaughan@Sun.com else 175*13096SJordan.Vaughan@Sun.com num_subsys = ZONE_REF_NUM_SUBSYS; 176*13096SJordan.Vaughan@Sun.com } else { 177*13096SJordan.Vaughan@Sun.com num_subsys = ZONE_REF_NUM_SUBSYS; 178*13096SJordan.Vaughan@Sun.com } 179*13096SJordan.Vaughan@Sun.com if ((zone_ref_subsys_names = mdb_alloc( 180*13096SJordan.Vaughan@Sun.com subsys_names_sym.st_size, UM_GC)) == NULL) { 181*13096SJordan.Vaughan@Sun.com mdb_warn("out of memory"); 182*13096SJordan.Vaughan@Sun.com return (DCMD_ERR); 183*13096SJordan.Vaughan@Sun.com } 184*13096SJordan.Vaughan@Sun.com if (mdb_readvar(zone_ref_subsys_names, 185*13096SJordan.Vaughan@Sun.com "zone_ref_subsys_names") == -1) { 186*13096SJordan.Vaughan@Sun.com mdb_warn("can't find zone_ref_subsys_names"); 187*13096SJordan.Vaughan@Sun.com return (DCMD_ERR); 188*13096SJordan.Vaughan@Sun.com } 189*13096SJordan.Vaughan@Sun.com 190*13096SJordan.Vaughan@Sun.com /* 191*13096SJordan.Vaughan@Sun.com * Display each subsystem's reference count if it's 192*13096SJordan.Vaughan@Sun.com * nonzero. 193*13096SJordan.Vaughan@Sun.com */ 194*13096SJordan.Vaughan@Sun.com mdb_inc_indent(7); 195*13096SJordan.Vaughan@Sun.com for (n = 0; n < num_subsys; ++n) { 196*13096SJordan.Vaughan@Sun.com char subsys_name[16]; 197*13096SJordan.Vaughan@Sun.com 198*13096SJordan.Vaughan@Sun.com /* 199*13096SJordan.Vaughan@Sun.com * Skip subsystems lacking outstanding 200*13096SJordan.Vaughan@Sun.com * references. 201*13096SJordan.Vaughan@Sun.com */ 202*13096SJordan.Vaughan@Sun.com if (zn.zone_subsys_ref[n] == 0) 203*13096SJordan.Vaughan@Sun.com continue; 204*13096SJordan.Vaughan@Sun.com 205*13096SJordan.Vaughan@Sun.com /* 206*13096SJordan.Vaughan@Sun.com * Each subsystem's name must be read from 207*13096SJordan.Vaughan@Sun.com * the target's image. 208*13096SJordan.Vaughan@Sun.com */ 209*13096SJordan.Vaughan@Sun.com if (mdb_readstr(subsys_name, 210*13096SJordan.Vaughan@Sun.com sizeof (subsys_name), 211*13096SJordan.Vaughan@Sun.com (uintptr_t)zone_ref_subsys_names[n]) == 212*13096SJordan.Vaughan@Sun.com -1) { 213*13096SJordan.Vaughan@Sun.com mdb_warn("unable to read subsystem name" 214*13096SJordan.Vaughan@Sun.com " from zone_ref_subsys_names[%u]", 215*13096SJordan.Vaughan@Sun.com n); 216*13096SJordan.Vaughan@Sun.com return (DCMD_ERR); 217*13096SJordan.Vaughan@Sun.com } 218*13096SJordan.Vaughan@Sun.com mdb_printf("%15s: %10u\n", subsys_name, 219*13096SJordan.Vaughan@Sun.com zn.zone_subsys_ref[n]); 220*13096SJordan.Vaughan@Sun.com } 221*13096SJordan.Vaughan@Sun.com mdb_dec_indent(7); 222*13096SJordan.Vaughan@Sun.com } 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate return (DCMD_OK); 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate int 2280Sstevel@tonic-gate zone_walk_init(mdb_walk_state_t *wsp) 2290Sstevel@tonic-gate { 2300Sstevel@tonic-gate GElf_Sym sym; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2330Sstevel@tonic-gate if (mdb_lookup_by_name("zone_active", &sym) == -1) { 2340Sstevel@tonic-gate mdb_warn("failed to find 'zone_active'"); 2350Sstevel@tonic-gate return (WALK_ERR); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)sym.st_value; 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate if (mdb_layered_walk("list", wsp) == -1) { 2400Sstevel@tonic-gate mdb_warn("couldn't walk 'list'"); 2410Sstevel@tonic-gate return (WALK_ERR); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate return (WALK_NEXT); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate int 2470Sstevel@tonic-gate zone_walk_step(mdb_walk_state_t *wsp) 2480Sstevel@tonic-gate { 2490Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2508111SJordan.Vaughan@Sun.com wsp->walk_cbdata)); 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate int 2540Sstevel@tonic-gate zsd_walk_init(mdb_walk_state_t *wsp) 2550Sstevel@tonic-gate { 2560Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 2570Sstevel@tonic-gate mdb_warn("global walk not supported\n"); 2580Sstevel@tonic-gate return (WALK_ERR); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate wsp->walk_addr += offsetof(struct zone, zone_zsd); 2610Sstevel@tonic-gate if (mdb_layered_walk("list", wsp) == -1) { 2620Sstevel@tonic-gate mdb_warn("couldn't walk 'list'"); 2630Sstevel@tonic-gate return (WALK_ERR); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate return (WALK_NEXT); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate int 2690Sstevel@tonic-gate zsd_walk_step(mdb_walk_state_t *wsp) 2700Sstevel@tonic-gate { 2710Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 2728111SJordan.Vaughan@Sun.com wsp->walk_cbdata)); 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate 2758111SJordan.Vaughan@Sun.com /* 2768111SJordan.Vaughan@Sun.com * Helper structure used when walking ZSD entries via zsd(). 2778111SJordan.Vaughan@Sun.com */ 2780Sstevel@tonic-gate struct zsd_cb_data { 2798111SJordan.Vaughan@Sun.com uint_t keygiven; /* Was a key specified (are we */ 2808111SJordan.Vaughan@Sun.com /* searching for a specific ZSD */ 2818111SJordan.Vaughan@Sun.com /* entry)? */ 2828111SJordan.Vaughan@Sun.com zone_key_t key; /* Key of ZSD for which we're looking */ 2838111SJordan.Vaughan@Sun.com uint_t found; /* Was the specific ZSD entry found? */ 2848111SJordan.Vaughan@Sun.com uint_t voptgiven; /* Display verbose information? */ 2850Sstevel@tonic-gate }; 2860Sstevel@tonic-gate 2878111SJordan.Vaughan@Sun.com /* 2888111SJordan.Vaughan@Sun.com * Helper function for zsd() that displays information from a single ZSD struct. 2898111SJordan.Vaughan@Sun.com * 'datap' must point to a valid zsd_cb_data struct. 2908111SJordan.Vaughan@Sun.com */ 2910Sstevel@tonic-gate /* ARGSUSED */ 2920Sstevel@tonic-gate static int 2938111SJordan.Vaughan@Sun.com zsd_print(uintptr_t addrp, const void * datap, void * privatep) 2940Sstevel@tonic-gate { 2958111SJordan.Vaughan@Sun.com struct zsd_entry entry; 2968111SJordan.Vaughan@Sun.com struct zsd_cb_data *cbdp; 2970Sstevel@tonic-gate 2988111SJordan.Vaughan@Sun.com if (mdb_vread(&entry, sizeof (entry), addrp) == -1) { 2998111SJordan.Vaughan@Sun.com mdb_warn("couldn't read zsd_entry at %p", addrp); 3000Sstevel@tonic-gate return (WALK_ERR); 3010Sstevel@tonic-gate } 3028111SJordan.Vaughan@Sun.com cbdp = (struct zsd_cb_data *)privatep; 3038111SJordan.Vaughan@Sun.com 3048111SJordan.Vaughan@Sun.com /* 3058111SJordan.Vaughan@Sun.com * Are we looking for a single entry specified by a key? Then make sure 3068111SJordan.Vaughan@Sun.com * that the current ZSD's key is what we're looking for. 3078111SJordan.Vaughan@Sun.com */ 3088111SJordan.Vaughan@Sun.com if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key) 3090Sstevel@tonic-gate return (WALK_NEXT); 3108111SJordan.Vaughan@Sun.com 3118111SJordan.Vaughan@Sun.com mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data, 3128111SJordan.Vaughan@Sun.com entry.zsd_flags); 3138111SJordan.Vaughan@Sun.com if (cbdp->voptgiven == TRUE) 3148111SJordan.Vaughan@Sun.com mdb_printf(" Create CB: %a\n Shutdown CB: %a\n" 3158111SJordan.Vaughan@Sun.com " Destroy CB: %a\n", entry.zsd_create, 3168111SJordan.Vaughan@Sun.com entry.zsd_shutdown, entry.zsd_destroy); 3178111SJordan.Vaughan@Sun.com if (cbdp->keygiven == TRUE) { 3188111SJordan.Vaughan@Sun.com cbdp->found = TRUE; 3198111SJordan.Vaughan@Sun.com return (WALK_DONE); 3208111SJordan.Vaughan@Sun.com } 3218111SJordan.Vaughan@Sun.com return (WALK_NEXT); 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate int 3250Sstevel@tonic-gate zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 3260Sstevel@tonic-gate { 3270Sstevel@tonic-gate zone_t zone; 3288111SJordan.Vaughan@Sun.com const mdb_arg_t *argp; 3298111SJordan.Vaughan@Sun.com int argcindex; 3300Sstevel@tonic-gate struct zsd_cb_data cbd; 3318111SJordan.Vaughan@Sun.com char name[ZONE_NAMELEN]; 3328111SJordan.Vaughan@Sun.com int len; 3330Sstevel@tonic-gate 3348111SJordan.Vaughan@Sun.com /* 3358111SJordan.Vaughan@Sun.com * Walk all zones if necessary. 3368111SJordan.Vaughan@Sun.com */ 3378111SJordan.Vaughan@Sun.com if (argc > 2) 3388111SJordan.Vaughan@Sun.com return (DCMD_USAGE); 3390Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) { 3408111SJordan.Vaughan@Sun.com if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) { 3418111SJordan.Vaughan@Sun.com mdb_warn("failed to walk zone\n"); 3428111SJordan.Vaughan@Sun.com return (DCMD_ERR); 3438111SJordan.Vaughan@Sun.com } 3448111SJordan.Vaughan@Sun.com return (DCMD_OK); 3458111SJordan.Vaughan@Sun.com } 3468111SJordan.Vaughan@Sun.com 3478111SJordan.Vaughan@Sun.com /* 3488111SJordan.Vaughan@Sun.com * Make sure a zone_t can be read from the specified address. 3498111SJordan.Vaughan@Sun.com */ 3508111SJordan.Vaughan@Sun.com if (mdb_vread(&zone, sizeof (zone), addr) == -1) { 3518111SJordan.Vaughan@Sun.com mdb_warn("couldn't read zone_t at %p", (void *)addr); 3520Sstevel@tonic-gate return (DCMD_ERR); 3530Sstevel@tonic-gate } 3548111SJordan.Vaughan@Sun.com 3558111SJordan.Vaughan@Sun.com /* 3568111SJordan.Vaughan@Sun.com * Get the optional arguments (key or -v or both). Note that 3578111SJordan.Vaughan@Sun.com * mdb_getopts() will not parse a key argument because it is not 3588111SJordan.Vaughan@Sun.com * preceded by an option letter. We'll get around this by requiring 3598111SJordan.Vaughan@Sun.com * that all options precede the optional key argument. 3608111SJordan.Vaughan@Sun.com */ 3618111SJordan.Vaughan@Sun.com cbd.keygiven = FALSE; 3628111SJordan.Vaughan@Sun.com cbd.voptgiven = FALSE; 3638111SJordan.Vaughan@Sun.com if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v', 3648111SJordan.Vaughan@Sun.com MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) { 3658111SJordan.Vaughan@Sun.com /* 3668111SJordan.Vaughan@Sun.com * No options may appear after the key. 3678111SJordan.Vaughan@Sun.com */ 3688111SJordan.Vaughan@Sun.com if (argcindex != argc - 1) 3698111SJordan.Vaughan@Sun.com return (DCMD_USAGE); 3708111SJordan.Vaughan@Sun.com 3718111SJordan.Vaughan@Sun.com /* 3728111SJordan.Vaughan@Sun.com * The missed argument should be a key. 3738111SJordan.Vaughan@Sun.com */ 3748111SJordan.Vaughan@Sun.com argp = &argv[argcindex]; 3758111SJordan.Vaughan@Sun.com if (argp->a_type == MDB_TYPE_IMMEDIATE) 3768111SJordan.Vaughan@Sun.com cbd.key = argp->a_un.a_val; 3778111SJordan.Vaughan@Sun.com else 3788111SJordan.Vaughan@Sun.com cbd.key = mdb_strtoull(argp->a_un.a_str); 3798111SJordan.Vaughan@Sun.com cbd.keygiven = TRUE; 3808111SJordan.Vaughan@Sun.com cbd.found = FALSE; 3818111SJordan.Vaughan@Sun.com } 3828111SJordan.Vaughan@Sun.com 3838111SJordan.Vaughan@Sun.com /* 3848111SJordan.Vaughan@Sun.com * Prepare to output the specified zone's ZSD information. 3858111SJordan.Vaughan@Sun.com */ 3868111SJordan.Vaughan@Sun.com if (DCMD_HDRSPEC(flags)) 3878111SJordan.Vaughan@Sun.com mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY", 3888111SJordan.Vaughan@Sun.com "VALUE", "FLAGS"); 3898111SJordan.Vaughan@Sun.com len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name); 3908111SJordan.Vaughan@Sun.com if (len > 0) { 3918111SJordan.Vaughan@Sun.com if (len == ZONE_NAMELEN) 3928111SJordan.Vaughan@Sun.com (void) strcpy(&name[len - 4], "..."); 3938111SJordan.Vaughan@Sun.com } else { 3948111SJordan.Vaughan@Sun.com (void) strcpy(name, "??"); 3958111SJordan.Vaughan@Sun.com } 3968111SJordan.Vaughan@Sun.com mdb_printf("%-20s ", name); 3978111SJordan.Vaughan@Sun.com 3988111SJordan.Vaughan@Sun.com /* 3998111SJordan.Vaughan@Sun.com * Display the requested ZSD entries. 4008111SJordan.Vaughan@Sun.com */ 4018111SJordan.Vaughan@Sun.com mdb_inc_indent(21); 4028111SJordan.Vaughan@Sun.com if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) { 4038111SJordan.Vaughan@Sun.com mdb_warn("failed to walk zsd\n"); 4048111SJordan.Vaughan@Sun.com mdb_dec_indent(21); 4050Sstevel@tonic-gate return (DCMD_ERR); 4060Sstevel@tonic-gate } 4078111SJordan.Vaughan@Sun.com if (cbd.keygiven == TRUE && cbd.found == FALSE) { 4088111SJordan.Vaughan@Sun.com mdb_printf("no corresponding ZSD entry found\n"); 4098111SJordan.Vaughan@Sun.com mdb_dec_indent(21); 4100Sstevel@tonic-gate return (DCMD_ERR); 4110Sstevel@tonic-gate } 4128111SJordan.Vaughan@Sun.com mdb_dec_indent(21); 4130Sstevel@tonic-gate return (DCMD_OK); 4140Sstevel@tonic-gate } 415