xref: /onnv-gate/usr/src/cmd/mdb/common/modules/svc.startd/startd.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include <libuutil.h>
32*0Sstevel@tonic-gate #include <libuutil_impl.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <librestart_priv.h>		/* instance_data_t */
35*0Sstevel@tonic-gate #include <startd.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  * To count the elements of a uu_list_t without knowing its implementation, we
40*0Sstevel@tonic-gate  * must walk & count them.
41*0Sstevel@tonic-gate  */
42*0Sstevel@tonic-gate /* ARGSUSED */
43*0Sstevel@tonic-gate static int
44*0Sstevel@tonic-gate inc_sz(uintptr_t addr, const void *unknown, void *data)
45*0Sstevel@tonic-gate {
46*0Sstevel@tonic-gate 	size_t *sz = data;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate 	++(*sz);
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate 	return (WALK_NEXT);
51*0Sstevel@tonic-gate }
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate /*ARGSUSED*/
54*0Sstevel@tonic-gate static int
55*0Sstevel@tonic-gate startd_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
56*0Sstevel@tonic-gate {
57*0Sstevel@tonic-gate 	uu_list_t *dgraphp;
58*0Sstevel@tonic-gate 	restarter_instance_list_t ril;
59*0Sstevel@tonic-gate 	u_longlong_t ns_total;
60*0Sstevel@tonic-gate 	u_longlong_t lookups;
61*0Sstevel@tonic-gate 	u_longlong_t dep_inserts, dep_cycle_ns, dep_insert_ns;
62*0Sstevel@tonic-gate 	size_t graph_num, restarter_num;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	if (mdb_readvar(&lookups, "dictionary_lookups") == -1) {
65*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dictionary_lookups' value\n");
66*0Sstevel@tonic-gate 		return (DCMD_ERR);
67*0Sstevel@tonic-gate 	}
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	if (mdb_readvar(&ns_total, "dictionary_ns_total") == -1) {
70*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dictionary_ns_total' value\n");
71*0Sstevel@tonic-gate 		return (DCMD_ERR);
72*0Sstevel@tonic-gate 	}
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 	if (mdb_readvar(&dep_inserts, "dep_inserts") == -1) {
75*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_inserts' value\n");
76*0Sstevel@tonic-gate 		return (DCMD_ERR);
77*0Sstevel@tonic-gate 	}
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	if (mdb_readvar(&dep_cycle_ns, "dep_cycle_ns") == -1) {
80*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_cycle_ns' value\n");
81*0Sstevel@tonic-gate 		return (DCMD_ERR);
82*0Sstevel@tonic-gate 	}
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	if (mdb_readvar(&dep_insert_ns, "dep_insert_ns") == -1) {
85*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_insert_ns' value\n");
86*0Sstevel@tonic-gate 		return (DCMD_ERR);
87*0Sstevel@tonic-gate 	}
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate 	if (mdb_readvar(&dgraphp, "dgraph") == -1) {
90*0Sstevel@tonic-gate 		mdb_warn("failed to read 'dgraph' value\n");
91*0Sstevel@tonic-gate 		return (DCMD_ERR);
92*0Sstevel@tonic-gate 	}
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	graph_num = 0;
95*0Sstevel@tonic-gate 	if (mdb_pwalk("uu_list_node", inc_sz, &graph_num,
96*0Sstevel@tonic-gate 	    (uintptr_t)dgraphp) == -1) {
97*0Sstevel@tonic-gate 		mdb_warn("failed to read uu_list\n");
98*0Sstevel@tonic-gate 		return (DCMD_ERR);
99*0Sstevel@tonic-gate 	}
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	if (mdb_readvar(&ril, "instance_list") == -1) {
102*0Sstevel@tonic-gate 		mdb_warn("failed to read 'instance_list' value\n");
103*0Sstevel@tonic-gate 		return (DCMD_ERR);
104*0Sstevel@tonic-gate 	}
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	restarter_num = 0;
107*0Sstevel@tonic-gate 	if (mdb_pwalk("uu_list_node", inc_sz, &restarter_num,
108*0Sstevel@tonic-gate 	    (uintptr_t)ril.ril_instance_list) == -1) {
109*0Sstevel@tonic-gate 		mdb_warn("failed to read uu_list\n");
110*0Sstevel@tonic-gate 		return (DCMD_ERR);
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	mdb_printf(
114*0Sstevel@tonic-gate 	    "         dictionary lookups: %llu\n"
115*0Sstevel@tonic-gate 	    "        average lookup time: %llu us\n"
116*0Sstevel@tonic-gate 	    "graph dependency insertions: %llu\n"
117*0Sstevel@tonic-gate 	    "   average cycle-check time: %llu us\n"
118*0Sstevel@tonic-gate 	    " avg dependency insert time: %llu us\n"
119*0Sstevel@tonic-gate 	    "number of nodes in dgraph: %llu\n"
120*0Sstevel@tonic-gate 	    "number of nodes in instance_list: %llu\n", lookups,
121*0Sstevel@tonic-gate 	    lookups ? ns_total / (1000 * lookups) : 0, dep_inserts,
122*0Sstevel@tonic-gate 	    dep_inserts ? dep_cycle_ns / (1000 * dep_inserts) : 0,
123*0Sstevel@tonic-gate 	    dep_inserts ? dep_insert_ns / (1000 * dep_inserts) : 0,
124*0Sstevel@tonic-gate 	    (u_longlong_t)graph_num, (u_longlong_t)restarter_num);
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	return (DCMD_OK);
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate static char
130*0Sstevel@tonic-gate xstate2chr(restarter_instance_state_t s)
131*0Sstevel@tonic-gate {
132*0Sstevel@tonic-gate 	switch (s) {
133*0Sstevel@tonic-gate 	case RESTARTER_STATE_UNINIT:	return ('u');
134*0Sstevel@tonic-gate 	case RESTARTER_STATE_DISABLED:	return ('d');
135*0Sstevel@tonic-gate 	case RESTARTER_STATE_OFFLINE:	return ('0');
136*0Sstevel@tonic-gate 	case RESTARTER_STATE_DEGRADED:	return ('D');
137*0Sstevel@tonic-gate 	case RESTARTER_STATE_ONLINE:	return ('1');
138*0Sstevel@tonic-gate 	case RESTARTER_STATE_MAINT:	return ('m');
139*0Sstevel@tonic-gate 	case RESTARTER_STATE_NONE:	return ('n');
140*0Sstevel@tonic-gate 	default:			return ('?');
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate }
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate /*ARGSUSED*/
145*0Sstevel@tonic-gate static int
146*0Sstevel@tonic-gate pr_instance(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate 	restarter_instance_list_t ril;
149*0Sstevel@tonic-gate 	restarter_inst_t ri;
150*0Sstevel@tonic-gate 	char *iname;
151*0Sstevel@tonic-gate 	char statechr = '-';
152*0Sstevel@tonic-gate 	char typechr;
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
155*0Sstevel@tonic-gate 		if (mdb_readvar(&ril, "instance_list") == -1) {
156*0Sstevel@tonic-gate 			mdb_warn("failed to read 'instance_list' value\n");
157*0Sstevel@tonic-gate 			return (DCMD_ERR);
158*0Sstevel@tonic-gate 		}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uu_list_node", "instance", 0, NULL,
161*0Sstevel@tonic-gate 		    (uintptr_t)ril.ril_instance_list) == -1) {
162*0Sstevel@tonic-gate 			mdb_warn("can't walk instances\n");
163*0Sstevel@tonic-gate 			return (DCMD_ERR);
164*0Sstevel@tonic-gate 		}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 		return (DCMD_OK);
167*0Sstevel@tonic-gate 	}
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	if (mdb_vread(&ri, sizeof (restarter_inst_t), addr) == -1) {
170*0Sstevel@tonic-gate 		mdb_warn("couldn't read instance at %a\n");
171*0Sstevel@tonic-gate 		return (DCMD_ERR);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
175*0Sstevel@tonic-gate 		mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S",
176*0Sstevel@tonic-gate 		    "FMRI");
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	iname = mdb_alloc(1024, UM_SLEEP | UM_GC);
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 	if (mdb_readstr(iname, 1024, (uintptr_t)ri.ri_i.i_fmri) == -1) {
181*0Sstevel@tonic-gate 		mdb_warn("couldn't read instance name\n");
182*0Sstevel@tonic-gate 		strcpy(iname, "-");
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	statechr = xstate2chr(ri.ri_i.i_state);
186*0Sstevel@tonic-gate 	typechr = (ri.ri_i.i_enabled) ? 'I' : 'i';
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	mdb_printf("%-10a %3x %c %c %s\n", addr, ri.ri_id, typechr, statechr,
189*0Sstevel@tonic-gate 	    iname);
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	return (DCMD_OK);
192*0Sstevel@tonic-gate }
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate /*ARGSUSED*/
195*0Sstevel@tonic-gate static int
196*0Sstevel@tonic-gate pr_vertex(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
197*0Sstevel@tonic-gate {
198*0Sstevel@tonic-gate 	uu_list_t *dgraphp;
199*0Sstevel@tonic-gate 	graph_vertex_t gv;
200*0Sstevel@tonic-gate 	char *vname;
201*0Sstevel@tonic-gate 	int id;
202*0Sstevel@tonic-gate 	char typechr;
203*0Sstevel@tonic-gate 	char statechr = '-';
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
206*0Sstevel@tonic-gate 		if (mdb_readvar(&dgraphp, "dgraph") == -1) {
207*0Sstevel@tonic-gate 			mdb_warn("failed to read 'dgraph' value\n");
208*0Sstevel@tonic-gate 			return (DCMD_ERR);
209*0Sstevel@tonic-gate 		}
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uu_list_node", "vertex", 0, NULL,
212*0Sstevel@tonic-gate 		    (uintptr_t)dgraphp) == -1) {
213*0Sstevel@tonic-gate 			mdb_warn("can't walk vertices");
214*0Sstevel@tonic-gate 			return (DCMD_ERR);
215*0Sstevel@tonic-gate 		}
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 		return (DCMD_OK);
218*0Sstevel@tonic-gate 	}
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	if (mdb_vread(&gv, sizeof (graph_vertex_t), addr) == -1) {
221*0Sstevel@tonic-gate 		mdb_warn("couldn't read vertex at %a\n");
222*0Sstevel@tonic-gate 		return (DCMD_ERR);
223*0Sstevel@tonic-gate 	}
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
226*0Sstevel@tonic-gate 		mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S",
227*0Sstevel@tonic-gate 		    "FMRI");
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	vname = mdb_alloc(1024, UM_SLEEP | UM_GC);
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	if (mdb_readstr(vname, 1024, (uintptr_t)gv.gv_name) == -1) {
232*0Sstevel@tonic-gate 		mdb_warn("couldn't read vertex name\n");
233*0Sstevel@tonic-gate 		strcpy(vname, "-");
234*0Sstevel@tonic-gate 	}
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 	id = gv.gv_id;
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	switch (gv.gv_type) {
239*0Sstevel@tonic-gate 	case GVT_FILE:
240*0Sstevel@tonic-gate 		typechr = 'f';
241*0Sstevel@tonic-gate 		break;
242*0Sstevel@tonic-gate 	case GVT_GROUP:
243*0Sstevel@tonic-gate 		switch (gv.gv_depgroup) {
244*0Sstevel@tonic-gate 		case DEPGRP_REQUIRE_ANY:
245*0Sstevel@tonic-gate 			typechr = 'r';
246*0Sstevel@tonic-gate 			break;
247*0Sstevel@tonic-gate 		case DEPGRP_REQUIRE_ALL:
248*0Sstevel@tonic-gate 			typechr = 'R';
249*0Sstevel@tonic-gate 			break;
250*0Sstevel@tonic-gate 		case DEPGRP_EXCLUDE_ALL:
251*0Sstevel@tonic-gate 			typechr = 'X';
252*0Sstevel@tonic-gate 			break;
253*0Sstevel@tonic-gate 		case DEPGRP_OPTIONAL_ALL:
254*0Sstevel@tonic-gate 			typechr = 'o';
255*0Sstevel@tonic-gate 			break;
256*0Sstevel@tonic-gate 		default:
257*0Sstevel@tonic-gate 			typechr = '?';
258*0Sstevel@tonic-gate 			break;
259*0Sstevel@tonic-gate 		}
260*0Sstevel@tonic-gate 		break;
261*0Sstevel@tonic-gate 	case GVT_INST:
262*0Sstevel@tonic-gate 		typechr = (gv.gv_flags & GV_ENABLED) ? 'I' : 'i';
263*0Sstevel@tonic-gate 		statechr = xstate2chr(gv.gv_state);
264*0Sstevel@tonic-gate 		break;
265*0Sstevel@tonic-gate 	case GVT_SVC:
266*0Sstevel@tonic-gate 		typechr = 's';
267*0Sstevel@tonic-gate 		break;
268*0Sstevel@tonic-gate 	default:
269*0Sstevel@tonic-gate 		typechr = '?';
270*0Sstevel@tonic-gate 		break;
271*0Sstevel@tonic-gate 	}
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 	mdb_printf("%-10a %3x %c %c %s\n", addr, id, typechr, statechr, vname);
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	return (DCMD_OK);
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate /* ARGSUSED */
279*0Sstevel@tonic-gate static int
280*0Sstevel@tonic-gate logbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
281*0Sstevel@tonic-gate {
282*0Sstevel@tonic-gate 	size_t logbuf_sz;
283*0Sstevel@tonic-gate 	char *buf;
284*0Sstevel@tonic-gate 	char *cp;
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	if (mdb_readvar(&logbuf_sz, "logbuf_sz") == -1) {
287*0Sstevel@tonic-gate 		mdb_warn("failed to read 'logbuf_sz'\n");
288*0Sstevel@tonic-gate 		return (DCMD_ERR);
289*0Sstevel@tonic-gate 	}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	buf = mdb_alloc(logbuf_sz, UM_SLEEP | UM_GC);
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	if (mdb_readsym(buf, logbuf_sz, "logbuf") == -1) {
294*0Sstevel@tonic-gate 		mdb_warn("failed to read 'logbuf'\n");
295*0Sstevel@tonic-gate 		return (DCMD_ERR);
296*0Sstevel@tonic-gate 	}
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	cp = strchr(buf, '\0');
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	if (cp == buf)
301*0Sstevel@tonic-gate 		/* Empty */
302*0Sstevel@tonic-gate 		return (DCMD_OK);
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	if (cp >= buf + logbuf_sz || strchr(cp + 1, '\0') >= buf + logbuf_sz) {
305*0Sstevel@tonic-gate 		mdb_warn("'logbuf' is corrupt\n");
306*0Sstevel@tonic-gate 		return (DCMD_ERR);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	mdb_printf("%s", cp + 1);
310*0Sstevel@tonic-gate 	mdb_printf("%s", buf);
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 	return (DCMD_OK);
313*0Sstevel@tonic-gate }
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
316*0Sstevel@tonic-gate 	{ "instance", NULL, "display svc.startd restarter instance",
317*0Sstevel@tonic-gate 	    pr_instance },
318*0Sstevel@tonic-gate 	{ "startd_log", NULL, "display svc.startd debug message buffer",
319*0Sstevel@tonic-gate 	    logbuf },
320*0Sstevel@tonic-gate 	{ "startd_status", NULL, "svc.startd status summary", startd_status },
321*0Sstevel@tonic-gate 	{ "vertex", NULL, "display svc.startd dependency graph vertex",
322*0Sstevel@tonic-gate 	    pr_vertex },
323*0Sstevel@tonic-gate 	{ NULL }
324*0Sstevel@tonic-gate };
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
327*0Sstevel@tonic-gate 	{ NULL }
328*0Sstevel@tonic-gate };
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
331*0Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
332*0Sstevel@tonic-gate };
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate const mdb_modinfo_t *
335*0Sstevel@tonic-gate _mdb_init(void)
336*0Sstevel@tonic-gate {
337*0Sstevel@tonic-gate 	return (&modinfo);
338*0Sstevel@tonic-gate }
339