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