xref: /onnv-gate/usr/src/cmd/mdb/common/modules/svc.configd/configd.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 #include <mdb/mdb_ctf.h>
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #include <configd.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate mdb_ctf_id_t request_enum;
35*0Sstevel@tonic-gate mdb_ctf_id_t response_enum;
36*0Sstevel@tonic-gate mdb_ctf_id_t ptr_type_enum;
37*0Sstevel@tonic-gate mdb_ctf_id_t thread_state_enum;
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate hrtime_t max_time_seen;
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate static void
enum_lookup(char * out,size_t size,mdb_ctf_id_t id,int val,const char * prefix,const char * prefix2)42*0Sstevel@tonic-gate enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val,
43*0Sstevel@tonic-gate     const char *prefix, const char *prefix2)
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate 	const char *cp;
46*0Sstevel@tonic-gate 	size_t len = strlen(prefix);
47*0Sstevel@tonic-gate 	size_t len2 = strlen(prefix2);
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 	if ((cp = mdb_ctf_enum_name(id, val)) != NULL) {
50*0Sstevel@tonic-gate 		if (strncmp(cp, prefix, len) == 0)
51*0Sstevel@tonic-gate 			cp += len;
52*0Sstevel@tonic-gate 		if (strncmp(cp, prefix2, len2) == 0)
53*0Sstevel@tonic-gate 			cp += len2;
54*0Sstevel@tonic-gate 		(void) strlcpy(out, cp, size);
55*0Sstevel@tonic-gate 	} else {
56*0Sstevel@tonic-gate 		mdb_snprintf(out, size, "? (%d)", val);
57*0Sstevel@tonic-gate 	}
58*0Sstevel@tonic-gate }
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate static void
make_lower(char * out,size_t sz)61*0Sstevel@tonic-gate make_lower(char *out, size_t sz)
62*0Sstevel@tonic-gate {
63*0Sstevel@tonic-gate 	while (*out != 0 && sz > 0) {
64*0Sstevel@tonic-gate 		if (*out >= 'A' && *out <= 'Z')
65*0Sstevel@tonic-gate 			*out += 'a' - 'A';
66*0Sstevel@tonic-gate 		out++;
67*0Sstevel@tonic-gate 		sz--;
68*0Sstevel@tonic-gate 	}
69*0Sstevel@tonic-gate }
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate /*ARGSUSED*/
72*0Sstevel@tonic-gate static int
configd_status(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)73*0Sstevel@tonic-gate configd_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	int num_servers;
76*0Sstevel@tonic-gate 	int num_started;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	if (argc != 0)
79*0Sstevel@tonic-gate 		return (DCMD_USAGE);
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	if (mdb_readvar(&num_servers, "num_servers") == -1) {
82*0Sstevel@tonic-gate 		mdb_warn("unable to read num_servers");
83*0Sstevel@tonic-gate 		return (DCMD_ERR);
84*0Sstevel@tonic-gate 	}
85*0Sstevel@tonic-gate 	if (mdb_readvar(&num_started, "num_started") == -1) {
86*0Sstevel@tonic-gate 		mdb_warn("unable to read num_started");
87*0Sstevel@tonic-gate 		return (DCMD_ERR);
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 	mdb_printf(
90*0Sstevel@tonic-gate 	    "\nserver threads:\t%d running, %d starting\n\n", num_servers,
91*0Sstevel@tonic-gate 	    num_started - num_servers);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	if (mdb_walk_dcmd("configd_threads", "configd_thread", argc,
94*0Sstevel@tonic-gate 	    argv) == -1) {
95*0Sstevel@tonic-gate 		mdb_warn("can't walk 'configd_threads'");
96*0Sstevel@tonic-gate 		return (DCMD_ERR);
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 	return (DCMD_OK);
99*0Sstevel@tonic-gate }
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate /*ARGSUSED*/
102*0Sstevel@tonic-gate static int
configd_thread(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)103*0Sstevel@tonic-gate configd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
104*0Sstevel@tonic-gate {
105*0Sstevel@tonic-gate 	thread_info_t t;
106*0Sstevel@tonic-gate 	char state[20];
107*0Sstevel@tonic-gate 	char oldstate[20];
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
110*0Sstevel@tonic-gate 		if (mdb_walk_dcmd("configd_threads", "configd_thread", argc,
111*0Sstevel@tonic-gate 		    argv) == -1) {
112*0Sstevel@tonic-gate 			mdb_warn("can't walk 'configd_threads'");
113*0Sstevel@tonic-gate 			return (DCMD_ERR);
114*0Sstevel@tonic-gate 		}
115*0Sstevel@tonic-gate 		return (DCMD_OK);
116*0Sstevel@tonic-gate 	}
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	if (argc != 0)
119*0Sstevel@tonic-gate 		return (DCMD_USAGE);
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
122*0Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %5s %-12s %-12s %-?s %-?s %-?s%</u>\n",
123*0Sstevel@tonic-gate 		    "ADDR", "TID", "STATE", "PREV_STATE", "CLIENT", "CLIENTRQ",
124*0Sstevel@tonic-gate 		    "MAINREQ");
125*0Sstevel@tonic-gate 	}
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	if (mdb_vread(&t, sizeof (t), addr) == -1) {
128*0Sstevel@tonic-gate 		mdb_warn("failed to read thread_info_t at %p", addr);
129*0Sstevel@tonic-gate 		return (DCMD_ERR);
130*0Sstevel@tonic-gate 	}
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	enum_lookup(state, sizeof (state), thread_state_enum,
133*0Sstevel@tonic-gate 	    t.ti_state, "TI_", "");
134*0Sstevel@tonic-gate 	make_lower(state, sizeof (state));
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	enum_lookup(oldstate, sizeof (oldstate), thread_state_enum,
137*0Sstevel@tonic-gate 	    t.ti_prev_state, "TI_", "");
138*0Sstevel@tonic-gate 	make_lower(oldstate, sizeof (oldstate));
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	mdb_printf("%0?p %5d %-12s %-12s %?p %?p %?p\n",
141*0Sstevel@tonic-gate 	    (void *)addr, t.ti_thread, state, oldstate,
142*0Sstevel@tonic-gate 	    t.ti_active_client, t.ti_client_request, t.ti_main_door_request);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 	return (DCMD_OK);
145*0Sstevel@tonic-gate }
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate static int
walk_thread_info_init(mdb_walk_state_t * wsp)148*0Sstevel@tonic-gate walk_thread_info_init(mdb_walk_state_t *wsp)
149*0Sstevel@tonic-gate {
150*0Sstevel@tonic-gate 	if (mdb_readvar(&wsp->walk_addr, "thread_list") == -1) {
151*0Sstevel@tonic-gate 		mdb_warn("unable to read thread_list");
152*0Sstevel@tonic-gate 		return (WALK_ERR);
153*0Sstevel@tonic-gate 	}
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	if (mdb_layered_walk("uu_list_node", wsp) == -1) {
156*0Sstevel@tonic-gate 		mdb_warn("couldn't walk 'uu_list_node'");
157*0Sstevel@tonic-gate 		return (WALK_ERR);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	return (WALK_NEXT);
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate static int
walk_thread_info_step(mdb_walk_state_t * wsp)164*0Sstevel@tonic-gate walk_thread_info_step(mdb_walk_state_t *wsp)
165*0Sstevel@tonic-gate {
166*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
167*0Sstevel@tonic-gate 	thread_info_t ti;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	if (mdb_vread(&ti, sizeof (ti), addr) == -1) {
170*0Sstevel@tonic-gate 		mdb_warn("unable to read thread_info_t at %p", addr);
171*0Sstevel@tonic-gate 		return (WALK_ERR);
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &ti, wsp->walk_cbdata));
175*0Sstevel@tonic-gate }
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate static int
request_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)178*0Sstevel@tonic-gate request_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
179*0Sstevel@tonic-gate {
180*0Sstevel@tonic-gate 	request_log_entry_t cur;
181*0Sstevel@tonic-gate 	hrtime_t dur;
182*0Sstevel@tonic-gate 	hrtime_t dursec;
183*0Sstevel@tonic-gate 	hrtime_t durnsec;
184*0Sstevel@tonic-gate 	char durstr[20];
185*0Sstevel@tonic-gate 	char stampstr[20];
186*0Sstevel@tonic-gate 	char requstr[30];
187*0Sstevel@tonic-gate 	char respstr[30];
188*0Sstevel@tonic-gate 	char typestr[30];
189*0Sstevel@tonic-gate 	uintptr_t node = 0;
190*0Sstevel@tonic-gate 	uintptr_t client = 0;
191*0Sstevel@tonic-gate 	uint64_t clientid = 0;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	int idx;
194*0Sstevel@tonic-gate 	int opt_v = FALSE;			/* verbose */
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
197*0Sstevel@tonic-gate 		if (mdb_walk_dcmd("configd_log", "configd_log", argc,
198*0Sstevel@tonic-gate 		    argv) == -1) {
199*0Sstevel@tonic-gate 			mdb_warn("can't walk 'configd_log'");
200*0Sstevel@tonic-gate 			return (DCMD_ERR);
201*0Sstevel@tonic-gate 		}
202*0Sstevel@tonic-gate 		return (DCMD_OK);
203*0Sstevel@tonic-gate 	}
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
206*0Sstevel@tonic-gate 	    'c', MDB_OPT_UINTPTR, &client,
207*0Sstevel@tonic-gate 	    'i', MDB_OPT_UINT64, &clientid,
208*0Sstevel@tonic-gate 	    'n', MDB_OPT_UINTPTR, &node,
209*0Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
210*0Sstevel@tonic-gate 		return (DCMD_USAGE);
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
213*0Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>",
214*0Sstevel@tonic-gate 		    "ADDR", "THRD", "START", "DURATION", "REQUEST",
215*0Sstevel@tonic-gate 		    "RESPONSE");
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
219*0Sstevel@tonic-gate 		mdb_warn("couldn't read log entry at %p", addr);
220*0Sstevel@tonic-gate 		return (DCMD_ERR);
221*0Sstevel@tonic-gate 	}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	/*
224*0Sstevel@tonic-gate 	 * apply filters, if any.
225*0Sstevel@tonic-gate 	 */
226*0Sstevel@tonic-gate 	if (clientid != 0 && clientid != cur.rl_clientid)
227*0Sstevel@tonic-gate 		return (DCMD_OK);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	if (client != 0 && client != (uintptr_t)cur.rl_client)
230*0Sstevel@tonic-gate 		return (DCMD_OK);
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	if (node != 0) {
233*0Sstevel@tonic-gate 		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
234*0Sstevel@tonic-gate 			if ((uintptr_t)cur.rl_ptrs[idx].rlp_data == node) {
235*0Sstevel@tonic-gate 				node = 0;		/* found it */
236*0Sstevel@tonic-gate 				break;
237*0Sstevel@tonic-gate 			}
238*0Sstevel@tonic-gate 		}
239*0Sstevel@tonic-gate 		if (node != 0)
240*0Sstevel@tonic-gate 			return (DCMD_OK);
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	enum_lookup(requstr, sizeof (requstr), request_enum, cur.rl_request,
244*0Sstevel@tonic-gate 	    "REP_PROTOCOL_", "");
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	if (cur.rl_end != 0) {
247*0Sstevel@tonic-gate 		enum_lookup(respstr, sizeof (respstr), response_enum,
248*0Sstevel@tonic-gate 		    cur.rl_response, "REP_PROTOCOL_", "FAIL_");
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 		dur = cur.rl_end - cur.rl_start;
251*0Sstevel@tonic-gate 		dursec = dur / NANOSEC;
252*0Sstevel@tonic-gate 		durnsec = dur % NANOSEC;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 		if (dursec <= 9)
255*0Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
256*0Sstevel@tonic-gate 			    "%lld.%06lld",
257*0Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MICROSEC));
258*0Sstevel@tonic-gate 		else if (dursec <= 9999)
259*0Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
260*0Sstevel@tonic-gate 			    "%lld.%03lld",
261*0Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MILLISEC));
262*0Sstevel@tonic-gate 		else
263*0Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
264*0Sstevel@tonic-gate 			    "%lld", dursec);
265*0Sstevel@tonic-gate 	} else {
266*0Sstevel@tonic-gate 		(void) strcpy(durstr, "-");
267*0Sstevel@tonic-gate 		(void) strcpy(respstr, "-");
268*0Sstevel@tonic-gate 	}
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	if (max_time_seen != 0 && max_time_seen >= cur.rl_start) {
271*0Sstevel@tonic-gate 		dur = max_time_seen - cur.rl_start;
272*0Sstevel@tonic-gate 		dursec = dur / NANOSEC;
273*0Sstevel@tonic-gate 		durnsec = dur % NANOSEC;
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 		if (dursec <= 99ULL)
276*0Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
277*0Sstevel@tonic-gate 			    "-%lld.%09lld", dursec, durnsec);
278*0Sstevel@tonic-gate 		else if (dursec <= 99999ULL)
279*0Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
280*0Sstevel@tonic-gate 			    "-%lld.%06lld",
281*0Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MICROSEC));
282*0Sstevel@tonic-gate 		else if (dursec <= 99999999ULL)
283*0Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
284*0Sstevel@tonic-gate 			    "-%lld.%03lld",
285*0Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MILLISEC));
286*0Sstevel@tonic-gate 		else
287*0Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
288*0Sstevel@tonic-gate 			    "-%lld", dursec);
289*0Sstevel@tonic-gate 	} else {
290*0Sstevel@tonic-gate 		(void) strcpy(stampstr, "-");
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n",
294*0Sstevel@tonic-gate 	    addr, cur.rl_tid, stampstr, durstr, requstr, respstr);
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	if (opt_v) {
297*0Sstevel@tonic-gate 		mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n",
298*0Sstevel@tonic-gate 		    cur.rl_client, cur.rl_clientid, cur.rl_num_ptrs,
299*0Sstevel@tonic-gate 		    cur.rl_start);
300*0Sstevel@tonic-gate 		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
301*0Sstevel@tonic-gate 			enum_lookup(typestr, sizeof (typestr), ptr_type_enum,
302*0Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_type, "RC_PTR_TYPE_", "");
303*0Sstevel@tonic-gate 			mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr,
304*0Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_id, cur.rl_ptrs[idx].rlp_ptr,
305*0Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_data);
306*0Sstevel@tonic-gate 		}
307*0Sstevel@tonic-gate 		mdb_printf("\n");
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate 	return (DCMD_OK);
310*0Sstevel@tonic-gate }
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate struct request_log_walk {
313*0Sstevel@tonic-gate 	size_t		rlw_max;
314*0Sstevel@tonic-gate 	size_t		rlw_count;
315*0Sstevel@tonic-gate 	size_t		rlw_cur;
316*0Sstevel@tonic-gate 	struct request_entry {
317*0Sstevel@tonic-gate 		hrtime_t  timestamp;
318*0Sstevel@tonic-gate 		uintptr_t addr;
319*0Sstevel@tonic-gate 	}		*rlw_list;
320*0Sstevel@tonic-gate };
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate /*
323*0Sstevel@tonic-gate  * we want newer items at the top
324*0Sstevel@tonic-gate  */
325*0Sstevel@tonic-gate static int
request_entry_compare(const void * l,const void * r)326*0Sstevel@tonic-gate request_entry_compare(const void *l, const void *r)
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate 	const struct request_entry *lp = l;
329*0Sstevel@tonic-gate 	const struct request_entry *rp = r;
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 	if (rp->timestamp == lp->timestamp)
332*0Sstevel@tonic-gate 		return (0);
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	/*
335*0Sstevel@tonic-gate 	 * 0 timestamps go first.
336*0Sstevel@tonic-gate 	 */
337*0Sstevel@tonic-gate 	if (rp->timestamp == 0)
338*0Sstevel@tonic-gate 		return (1);
339*0Sstevel@tonic-gate 	if (lp->timestamp == 0)
340*0Sstevel@tonic-gate 		return (-1);
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	if (lp->timestamp < rp->timestamp)
343*0Sstevel@tonic-gate 		return (1);
344*0Sstevel@tonic-gate 	return (-1);
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate /*ARGSUSED*/
348*0Sstevel@tonic-gate static int
request_log_count_thread(uintptr_t addr,thread_info_t * tip,uint_t * arg)349*0Sstevel@tonic-gate request_log_count_thread(uintptr_t addr, thread_info_t *tip, uint_t *arg)
350*0Sstevel@tonic-gate {
351*0Sstevel@tonic-gate 	(*arg)++;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 	return (WALK_NEXT);
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate static int
request_log_add_thread(uintptr_t addr,thread_info_t * tip,struct request_entry ** arg)357*0Sstevel@tonic-gate request_log_add_thread(uintptr_t addr, thread_info_t *tip,
358*0Sstevel@tonic-gate     struct request_entry **arg)
359*0Sstevel@tonic-gate {
360*0Sstevel@tonic-gate 	if (max_time_seen < tip->ti_log.rl_start)
361*0Sstevel@tonic-gate 		max_time_seen = tip->ti_log.rl_start;
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate 	if (max_time_seen < tip->ti_log.rl_end)
364*0Sstevel@tonic-gate 		max_time_seen = tip->ti_log.rl_end;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	if (tip->ti_log.rl_start != 0) {
367*0Sstevel@tonic-gate 		if (tip->ti_log.rl_end)
368*0Sstevel@tonic-gate 			(*arg)->timestamp = tip->ti_log.rl_start;
369*0Sstevel@tonic-gate 		else
370*0Sstevel@tonic-gate 			(*arg)->timestamp = 0;		/* sort to the top */
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 		(*arg)->addr = addr + offsetof(thread_info_t, ti_log);
373*0Sstevel@tonic-gate 		++*arg;
374*0Sstevel@tonic-gate 	}
375*0Sstevel@tonic-gate 	return (WALK_NEXT);
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate static int
request_log_walk_init(mdb_walk_state_t * wsp)379*0Sstevel@tonic-gate request_log_walk_init(mdb_walk_state_t *wsp)
380*0Sstevel@tonic-gate {
381*0Sstevel@tonic-gate 	struct request_log_walk *rlw;
382*0Sstevel@tonic-gate 	struct request_entry *list, *listp;
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 	uint_t log_size;
385*0Sstevel@tonic-gate 	uint_t size;
386*0Sstevel@tonic-gate 	uint_t idx;
387*0Sstevel@tonic-gate 	uint_t pos;
388*0Sstevel@tonic-gate 	request_log_entry_t *base;
389*0Sstevel@tonic-gate 	request_log_entry_t cur;
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	if (mdb_readvar(&base, "request_log") == -1) {
392*0Sstevel@tonic-gate 		mdb_warn("couldn't read 'request_log'");
393*0Sstevel@tonic-gate 		return (WALK_ERR);
394*0Sstevel@tonic-gate 	}
395*0Sstevel@tonic-gate 	if (mdb_readvar(&log_size, "request_log_size") == -1) {
396*0Sstevel@tonic-gate 		mdb_warn("couldn't read 'request_log_size'");
397*0Sstevel@tonic-gate 		return (WALK_ERR);
398*0Sstevel@tonic-gate 	}
399*0Sstevel@tonic-gate 	size = log_size;
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	if (mdb_walk("configd_threads", (mdb_walk_cb_t)request_log_count_thread,
402*0Sstevel@tonic-gate 	    &size) == -1) {
403*0Sstevel@tonic-gate 		mdb_warn("couldn't walk 'configd_threads'");
404*0Sstevel@tonic-gate 		return (WALK_ERR);
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	list = mdb_zalloc(sizeof (*list) * size, UM_SLEEP);
408*0Sstevel@tonic-gate 	listp = list;
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	if (mdb_walk("configd_threads", (mdb_walk_cb_t)request_log_add_thread,
411*0Sstevel@tonic-gate 	    &listp) == -1) {
412*0Sstevel@tonic-gate 		mdb_warn("couldn't walk 'configd_threads'");
413*0Sstevel@tonic-gate 		mdb_free(list, sizeof (*list) * size);
414*0Sstevel@tonic-gate 		return (WALK_ERR);
415*0Sstevel@tonic-gate 	}
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	pos = listp - list;
418*0Sstevel@tonic-gate 	for (idx = 0; idx < log_size; idx++) {
419*0Sstevel@tonic-gate 		uintptr_t addr = (uintptr_t)&base[idx];
420*0Sstevel@tonic-gate 		if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
421*0Sstevel@tonic-gate 			mdb_warn("couldn't read log entry at %p", addr);
422*0Sstevel@tonic-gate 			mdb_free(list, sizeof (*list) * size);
423*0Sstevel@tonic-gate 			return (WALK_ERR);
424*0Sstevel@tonic-gate 		}
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 		if (max_time_seen < cur.rl_start)
427*0Sstevel@tonic-gate 			max_time_seen = cur.rl_start;
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate 		if (max_time_seen < cur.rl_end)
430*0Sstevel@tonic-gate 			max_time_seen = cur.rl_end;
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate 		if (cur.rl_start != 0) {
433*0Sstevel@tonic-gate 			list[pos].timestamp = cur.rl_start;
434*0Sstevel@tonic-gate 			list[pos].addr = addr;
435*0Sstevel@tonic-gate 			pos++;
436*0Sstevel@tonic-gate 		}
437*0Sstevel@tonic-gate 	}
438*0Sstevel@tonic-gate 	qsort(list, pos, sizeof (*list), &request_entry_compare);
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate 	rlw = mdb_zalloc(sizeof (*rlw), UM_SLEEP);
441*0Sstevel@tonic-gate 	rlw->rlw_max = size;
442*0Sstevel@tonic-gate 	rlw->rlw_count = pos;
443*0Sstevel@tonic-gate 	rlw->rlw_cur = 0;
444*0Sstevel@tonic-gate 	rlw->rlw_list = list;
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	wsp->walk_data = rlw;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	return (WALK_NEXT);
449*0Sstevel@tonic-gate }
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate static int
request_log_walk_step(mdb_walk_state_t * wsp)452*0Sstevel@tonic-gate request_log_walk_step(mdb_walk_state_t *wsp)
453*0Sstevel@tonic-gate {
454*0Sstevel@tonic-gate 	struct request_log_walk *rlw = wsp->walk_data;
455*0Sstevel@tonic-gate 	uintptr_t addr;
456*0Sstevel@tonic-gate 	request_log_entry_t cur;
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 	if (rlw->rlw_cur >= rlw->rlw_count)
459*0Sstevel@tonic-gate 		return (WALK_DONE);
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	addr = rlw->rlw_list[rlw->rlw_cur++].addr;
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 	if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
464*0Sstevel@tonic-gate 		mdb_warn("couldn't read log entry at %p", addr);
465*0Sstevel@tonic-gate 		return (WALK_ERR);
466*0Sstevel@tonic-gate 	}
467*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &cur, wsp->walk_cbdata));
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate static void
request_log_walk_fini(mdb_walk_state_t * wsp)471*0Sstevel@tonic-gate request_log_walk_fini(mdb_walk_state_t *wsp)
472*0Sstevel@tonic-gate {
473*0Sstevel@tonic-gate 	struct request_log_walk *rlw = wsp->walk_data;
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	mdb_free(rlw->rlw_list, sizeof (*rlw->rlw_list) * rlw->rlw_max);
476*0Sstevel@tonic-gate 	mdb_free(rlw, sizeof (*rlw));
477*0Sstevel@tonic-gate }
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
480*0Sstevel@tonic-gate 	{ "configd_status", NULL, "svc.configd status summary",
481*0Sstevel@tonic-gate 	    configd_status },
482*0Sstevel@tonic-gate 	{ "configd_thread", "?", "Print a thread_info_t tabularly",
483*0Sstevel@tonic-gate 	    configd_thread },
484*0Sstevel@tonic-gate 	{ "configd_log", "?[-v] [-c clientptr] [-i clientid]",
485*0Sstevel@tonic-gate 	    "Print the request log, or a single entry", request_log },
486*0Sstevel@tonic-gate 	{ NULL }
487*0Sstevel@tonic-gate };
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
490*0Sstevel@tonic-gate 	{ "configd_threads", "walks the thread_info_ts for all "
491*0Sstevel@tonic-gate 	    "threads", walk_thread_info_init, walk_thread_info_step },
492*0Sstevel@tonic-gate 	{ "configd_log", "walks the request_log_entry_ts",
493*0Sstevel@tonic-gate 	    request_log_walk_init, request_log_walk_step,
494*0Sstevel@tonic-gate 	    request_log_walk_fini},
495*0Sstevel@tonic-gate 	{ NULL }
496*0Sstevel@tonic-gate };
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
499*0Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
500*0Sstevel@tonic-gate };
501*0Sstevel@tonic-gate 
502*0Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)503*0Sstevel@tonic-gate _mdb_init(void)
504*0Sstevel@tonic-gate {
505*0Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rep_protocol_requestid",
506*0Sstevel@tonic-gate 	    &request_enum) == -1) {
507*0Sstevel@tonic-gate 		mdb_warn("enum rep_protocol_requestid not found");
508*0Sstevel@tonic-gate 	}
509*0Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rep_protocol_responseid",
510*0Sstevel@tonic-gate 	    &response_enum) == -1) {
511*0Sstevel@tonic-gate 		mdb_warn("enum rep_protocol_responseid not found");
512*0Sstevel@tonic-gate 	}
513*0Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rc_ptr_type",
514*0Sstevel@tonic-gate 	    &ptr_type_enum) == -1) {
515*0Sstevel@tonic-gate 		mdb_warn("enum rc_ptr_type not found");
516*0Sstevel@tonic-gate 	}
517*0Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum thread_state",
518*0Sstevel@tonic-gate 	    &thread_state_enum) == -1) {
519*0Sstevel@tonic-gate 		mdb_warn("enum thread_state not found");
520*0Sstevel@tonic-gate 	}
521*0Sstevel@tonic-gate 	return (&modinfo);
522*0Sstevel@tonic-gate }
523