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
zid_lookup_cb(uintptr_t addr,const zone_t * zone,void * arg)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
zid2zone(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
zoneprt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
zone_walk_init(mdb_walk_state_t * wsp)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
zone_walk_step(mdb_walk_state_t * wsp)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
zsd_walk_init(mdb_walk_state_t * wsp)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
zsd_walk_step(mdb_walk_state_t * wsp)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
zsd_print(uintptr_t addrp,const void * datap,void * privatep)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
zsd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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