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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
287c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <configd.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate mdb_ctf_id_t request_enum;
337c478bd9Sstevel@tonic-gate mdb_ctf_id_t response_enum;
347c478bd9Sstevel@tonic-gate mdb_ctf_id_t ptr_type_enum;
357c478bd9Sstevel@tonic-gate mdb_ctf_id_t thread_state_enum;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate hrtime_t max_time_seen;
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate static void
enum_lookup(char * out,size_t size,mdb_ctf_id_t id,int val,const char * prefix,const char * prefix2)407c478bd9Sstevel@tonic-gate enum_lookup(char *out, size_t size, mdb_ctf_id_t id, int val,
417c478bd9Sstevel@tonic-gate     const char *prefix, const char *prefix2)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	const char *cp;
447c478bd9Sstevel@tonic-gate 	size_t len = strlen(prefix);
457c478bd9Sstevel@tonic-gate 	size_t len2 = strlen(prefix2);
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 	if ((cp = mdb_ctf_enum_name(id, val)) != NULL) {
487c478bd9Sstevel@tonic-gate 		if (strncmp(cp, prefix, len) == 0)
497c478bd9Sstevel@tonic-gate 			cp += len;
507c478bd9Sstevel@tonic-gate 		if (strncmp(cp, prefix2, len2) == 0)
517c478bd9Sstevel@tonic-gate 			cp += len2;
527c478bd9Sstevel@tonic-gate 		(void) strlcpy(out, cp, size);
537c478bd9Sstevel@tonic-gate 	} else {
547c478bd9Sstevel@tonic-gate 		mdb_snprintf(out, size, "? (%d)", val);
557c478bd9Sstevel@tonic-gate 	}
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static void
make_lower(char * out,size_t sz)597c478bd9Sstevel@tonic-gate make_lower(char *out, size_t sz)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	while (*out != 0 && sz > 0) {
627c478bd9Sstevel@tonic-gate 		if (*out >= 'A' && *out <= 'Z')
637c478bd9Sstevel@tonic-gate 			*out += 'a' - 'A';
647c478bd9Sstevel@tonic-gate 		out++;
657c478bd9Sstevel@tonic-gate 		sz--;
667c478bd9Sstevel@tonic-gate 	}
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
707c478bd9Sstevel@tonic-gate static int
configd_status(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)717c478bd9Sstevel@tonic-gate configd_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate 	int num_servers;
747c478bd9Sstevel@tonic-gate 	int num_started;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if (argc != 0)
777c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&num_servers, "num_servers") == -1) {
807c478bd9Sstevel@tonic-gate 		mdb_warn("unable to read num_servers");
817c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&num_started, "num_started") == -1) {
847c478bd9Sstevel@tonic-gate 		mdb_warn("unable to read num_started");
857c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	mdb_printf(
887c478bd9Sstevel@tonic-gate 	    "\nserver threads:\t%d running, %d starting\n\n", num_servers,
897c478bd9Sstevel@tonic-gate 	    num_started - num_servers);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	if (mdb_walk_dcmd("configd_threads", "configd_thread", argc,
927c478bd9Sstevel@tonic-gate 	    argv) == -1) {
937c478bd9Sstevel@tonic-gate 		mdb_warn("can't walk 'configd_threads'");
947c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1007c478bd9Sstevel@tonic-gate static int
configd_thread(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1017c478bd9Sstevel@tonic-gate configd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	thread_info_t t;
1047c478bd9Sstevel@tonic-gate 	char state[20];
1057c478bd9Sstevel@tonic-gate 	char oldstate[20];
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
1087c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("configd_threads", "configd_thread", argc,
1097c478bd9Sstevel@tonic-gate 		    argv) == -1) {
1107c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk 'configd_threads'");
1117c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
1127c478bd9Sstevel@tonic-gate 		}
1137c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (argc != 0)
1177c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
1207c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %5s %-12s %-12s %-?s %-?s %-?s%</u>\n",
1217c478bd9Sstevel@tonic-gate 		    "ADDR", "TID", "STATE", "PREV_STATE", "CLIENT", "CLIENTRQ",
1227c478bd9Sstevel@tonic-gate 		    "MAINREQ");
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if (mdb_vread(&t, sizeof (t), addr) == -1) {
1267c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read thread_info_t at %p", addr);
1277c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	enum_lookup(state, sizeof (state), thread_state_enum,
1317c478bd9Sstevel@tonic-gate 	    t.ti_state, "TI_", "");
1327c478bd9Sstevel@tonic-gate 	make_lower(state, sizeof (state));
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	enum_lookup(oldstate, sizeof (oldstate), thread_state_enum,
1357c478bd9Sstevel@tonic-gate 	    t.ti_prev_state, "TI_", "");
1367c478bd9Sstevel@tonic-gate 	make_lower(oldstate, sizeof (oldstate));
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %5d %-12s %-12s %?p %?p %?p\n",
1397c478bd9Sstevel@tonic-gate 	    (void *)addr, t.ti_thread, state, oldstate,
1407c478bd9Sstevel@tonic-gate 	    t.ti_active_client, t.ti_client_request, t.ti_main_door_request);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate static int
walk_thread_info_init(mdb_walk_state_t * wsp)1467c478bd9Sstevel@tonic-gate walk_thread_info_init(mdb_walk_state_t *wsp)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&wsp->walk_addr, "thread_list") == -1) {
1497c478bd9Sstevel@tonic-gate 		mdb_warn("unable to read thread_list");
1507c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	if (mdb_layered_walk("uu_list_node", wsp) == -1) {
1547c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't walk 'uu_list_node'");
1557c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate static int
walk_thread_info_step(mdb_walk_state_t * wsp)1627c478bd9Sstevel@tonic-gate walk_thread_info_step(mdb_walk_state_t *wsp)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
1657c478bd9Sstevel@tonic-gate 	thread_info_t ti;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if (mdb_vread(&ti, sizeof (ti), addr) == -1) {
1687c478bd9Sstevel@tonic-gate 		mdb_warn("unable to read thread_info_t at %p", addr);
1697c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &ti, wsp->walk_cbdata));
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static int
request_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1767c478bd9Sstevel@tonic-gate request_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	request_log_entry_t cur;
1797c478bd9Sstevel@tonic-gate 	hrtime_t dur;
1807c478bd9Sstevel@tonic-gate 	hrtime_t dursec;
1817c478bd9Sstevel@tonic-gate 	hrtime_t durnsec;
1827c478bd9Sstevel@tonic-gate 	char durstr[20];
1837c478bd9Sstevel@tonic-gate 	char stampstr[20];
1847c478bd9Sstevel@tonic-gate 	char requstr[30];
1857c478bd9Sstevel@tonic-gate 	char respstr[30];
1867c478bd9Sstevel@tonic-gate 	char typestr[30];
1877c478bd9Sstevel@tonic-gate 	uintptr_t node = 0;
1887c478bd9Sstevel@tonic-gate 	uintptr_t client = 0;
1897c478bd9Sstevel@tonic-gate 	uint64_t clientid = 0;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	int idx;
1927c478bd9Sstevel@tonic-gate 	int opt_v = FALSE;			/* verbose */
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
1957c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd("configd_log", "configd_log", argc,
1967c478bd9Sstevel@tonic-gate 		    argv) == -1) {
1977c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk 'configd_log'");
1987c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
2047c478bd9Sstevel@tonic-gate 	    'c', MDB_OPT_UINTPTR, &client,
2057c478bd9Sstevel@tonic-gate 	    'i', MDB_OPT_UINT64, &clientid,
2067c478bd9Sstevel@tonic-gate 	    'n', MDB_OPT_UINTPTR, &node,
2077c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
2087c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
2117c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>",
2127c478bd9Sstevel@tonic-gate 		    "ADDR", "THRD", "START", "DURATION", "REQUEST",
2137c478bd9Sstevel@tonic-gate 		    "RESPONSE");
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
2177c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read log entry at %p", addr);
2187c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/*
2227c478bd9Sstevel@tonic-gate 	 * apply filters, if any.
2237c478bd9Sstevel@tonic-gate 	 */
2247c478bd9Sstevel@tonic-gate 	if (clientid != 0 && clientid != cur.rl_clientid)
2257c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if (client != 0 && client != (uintptr_t)cur.rl_client)
2287c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (node != 0) {
2317c478bd9Sstevel@tonic-gate 		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
2327c478bd9Sstevel@tonic-gate 			if ((uintptr_t)cur.rl_ptrs[idx].rlp_data == node) {
2337c478bd9Sstevel@tonic-gate 				node = 0;		/* found it */
2347c478bd9Sstevel@tonic-gate 				break;
2357c478bd9Sstevel@tonic-gate 			}
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 		if (node != 0)
2387c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	enum_lookup(requstr, sizeof (requstr), request_enum, cur.rl_request,
2427c478bd9Sstevel@tonic-gate 	    "REP_PROTOCOL_", "");
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (cur.rl_end != 0) {
2457c478bd9Sstevel@tonic-gate 		enum_lookup(respstr, sizeof (respstr), response_enum,
2467c478bd9Sstevel@tonic-gate 		    cur.rl_response, "REP_PROTOCOL_", "FAIL_");
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		dur = cur.rl_end - cur.rl_start;
2497c478bd9Sstevel@tonic-gate 		dursec = dur / NANOSEC;
2507c478bd9Sstevel@tonic-gate 		durnsec = dur % NANOSEC;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 		if (dursec <= 9)
2537c478bd9Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
2547c478bd9Sstevel@tonic-gate 			    "%lld.%06lld",
2557c478bd9Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MICROSEC));
2567c478bd9Sstevel@tonic-gate 		else if (dursec <= 9999)
2577c478bd9Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
2587c478bd9Sstevel@tonic-gate 			    "%lld.%03lld",
259*19449258SJosef 'Jeff' Sipek 			    dursec, NSEC2MSEC(durnsec));
2607c478bd9Sstevel@tonic-gate 		else
2617c478bd9Sstevel@tonic-gate 			mdb_snprintf(durstr, sizeof (durstr),
2627c478bd9Sstevel@tonic-gate 			    "%lld", dursec);
2637c478bd9Sstevel@tonic-gate 	} else {
2647c478bd9Sstevel@tonic-gate 		(void) strcpy(durstr, "-");
2657c478bd9Sstevel@tonic-gate 		(void) strcpy(respstr, "-");
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	if (max_time_seen != 0 && max_time_seen >= cur.rl_start) {
2697c478bd9Sstevel@tonic-gate 		dur = max_time_seen - cur.rl_start;
2707c478bd9Sstevel@tonic-gate 		dursec = dur / NANOSEC;
2717c478bd9Sstevel@tonic-gate 		durnsec = dur % NANOSEC;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		if (dursec <= 99ULL)
2747c478bd9Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
2757c478bd9Sstevel@tonic-gate 			    "-%lld.%09lld", dursec, durnsec);
2767c478bd9Sstevel@tonic-gate 		else if (dursec <= 99999ULL)
2777c478bd9Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
2787c478bd9Sstevel@tonic-gate 			    "-%lld.%06lld",
2797c478bd9Sstevel@tonic-gate 			    dursec, durnsec / (NANOSEC / MICROSEC));
2807c478bd9Sstevel@tonic-gate 		else if (dursec <= 99999999ULL)
2817c478bd9Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
2827c478bd9Sstevel@tonic-gate 			    "-%lld.%03lld",
283*19449258SJosef 'Jeff' Sipek 			    dursec, NSEC2MSEC(durnsec));
2847c478bd9Sstevel@tonic-gate 		else
2857c478bd9Sstevel@tonic-gate 			mdb_snprintf(stampstr, sizeof (stampstr),
2867c478bd9Sstevel@tonic-gate 			    "-%lld", dursec);
2877c478bd9Sstevel@tonic-gate 	} else {
2887c478bd9Sstevel@tonic-gate 		(void) strcpy(stampstr, "-");
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n",
2927c478bd9Sstevel@tonic-gate 	    addr, cur.rl_tid, stampstr, durstr, requstr, respstr);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	if (opt_v) {
2957c478bd9Sstevel@tonic-gate 		mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n",
2967c478bd9Sstevel@tonic-gate 		    cur.rl_client, cur.rl_clientid, cur.rl_num_ptrs,
2977c478bd9Sstevel@tonic-gate 		    cur.rl_start);
2987c478bd9Sstevel@tonic-gate 		for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) {
2997c478bd9Sstevel@tonic-gate 			enum_lookup(typestr, sizeof (typestr), ptr_type_enum,
3007c478bd9Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_type, "RC_PTR_TYPE_", "");
3017c478bd9Sstevel@tonic-gate 			mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr,
3027c478bd9Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_id, cur.rl_ptrs[idx].rlp_ptr,
3037c478bd9Sstevel@tonic-gate 			    cur.rl_ptrs[idx].rlp_data);
3047c478bd9Sstevel@tonic-gate 		}
3057c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate struct request_log_walk {
3117c478bd9Sstevel@tonic-gate 	size_t		rlw_max;
3127c478bd9Sstevel@tonic-gate 	size_t		rlw_count;
3137c478bd9Sstevel@tonic-gate 	size_t		rlw_cur;
3147c478bd9Sstevel@tonic-gate 	struct request_entry {
3157c478bd9Sstevel@tonic-gate 		hrtime_t  timestamp;
3167c478bd9Sstevel@tonic-gate 		uintptr_t addr;
3177c478bd9Sstevel@tonic-gate 	}		*rlw_list;
3187c478bd9Sstevel@tonic-gate };
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate  * we want newer items at the top
3227c478bd9Sstevel@tonic-gate  */
3237c478bd9Sstevel@tonic-gate static int
request_entry_compare(const void * l,const void * r)3247c478bd9Sstevel@tonic-gate request_entry_compare(const void *l, const void *r)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	const struct request_entry *lp = l;
3277c478bd9Sstevel@tonic-gate 	const struct request_entry *rp = r;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	if (rp->timestamp == lp->timestamp)
3307c478bd9Sstevel@tonic-gate 		return (0);
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/*
3337c478bd9Sstevel@tonic-gate 	 * 0 timestamps go first.
3347c478bd9Sstevel@tonic-gate 	 */
3357c478bd9Sstevel@tonic-gate 	if (rp->timestamp == 0)
3367c478bd9Sstevel@tonic-gate 		return (1);
3377c478bd9Sstevel@tonic-gate 	if (lp->timestamp == 0)
3387c478bd9Sstevel@tonic-gate 		return (-1);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (lp->timestamp < rp->timestamp)
3417c478bd9Sstevel@tonic-gate 		return (1);
3427c478bd9Sstevel@tonic-gate 	return (-1);
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3467c478bd9Sstevel@tonic-gate static int
request_log_count_thread(uintptr_t addr,thread_info_t * tip,uint_t * arg)3477c478bd9Sstevel@tonic-gate request_log_count_thread(uintptr_t addr, thread_info_t *tip, uint_t *arg)
3487c478bd9Sstevel@tonic-gate {
3497c478bd9Sstevel@tonic-gate 	(*arg)++;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate static int
request_log_add_thread(uintptr_t addr,thread_info_t * tip,struct request_entry ** arg)3557c478bd9Sstevel@tonic-gate request_log_add_thread(uintptr_t addr, thread_info_t *tip,
3567c478bd9Sstevel@tonic-gate     struct request_entry **arg)
3577c478bd9Sstevel@tonic-gate {
3587c478bd9Sstevel@tonic-gate 	if (max_time_seen < tip->ti_log.rl_start)
3597c478bd9Sstevel@tonic-gate 		max_time_seen = tip->ti_log.rl_start;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if (max_time_seen < tip->ti_log.rl_end)
3627c478bd9Sstevel@tonic-gate 		max_time_seen = tip->ti_log.rl_end;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	if (tip->ti_log.rl_start != 0) {
3657c478bd9Sstevel@tonic-gate 		if (tip->ti_log.rl_end)
3667c478bd9Sstevel@tonic-gate 			(*arg)->timestamp = tip->ti_log.rl_start;
3677c478bd9Sstevel@tonic-gate 		else
3687c478bd9Sstevel@tonic-gate 			(*arg)->timestamp = 0;		/* sort to the top */
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		(*arg)->addr = addr + offsetof(thread_info_t, ti_log);
3717c478bd9Sstevel@tonic-gate 		++*arg;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate static int
request_log_walk_init(mdb_walk_state_t * wsp)3777c478bd9Sstevel@tonic-gate request_log_walk_init(mdb_walk_state_t *wsp)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	struct request_log_walk *rlw;
3807c478bd9Sstevel@tonic-gate 	struct request_entry *list, *listp;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	uint_t log_size;
3837c478bd9Sstevel@tonic-gate 	uint_t size;
3847c478bd9Sstevel@tonic-gate 	uint_t idx;
3857c478bd9Sstevel@tonic-gate 	uint_t pos;
3867c478bd9Sstevel@tonic-gate 	request_log_entry_t *base;
3877c478bd9Sstevel@tonic-gate 	request_log_entry_t cur;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&base, "request_log") == -1) {
3907c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read 'request_log'");
3917c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&log_size, "request_log_size") == -1) {
3947c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read 'request_log_size'");
3957c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 	size = log_size;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (mdb_walk("configd_threads", (mdb_walk_cb_t)request_log_count_thread,
4007c478bd9Sstevel@tonic-gate 	    &size) == -1) {
4017c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't walk 'configd_threads'");
4027c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	list = mdb_zalloc(sizeof (*list) * size, UM_SLEEP);
4067c478bd9Sstevel@tonic-gate 	listp = list;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	if (mdb_walk("configd_threads", (mdb_walk_cb_t)request_log_add_thread,
4097c478bd9Sstevel@tonic-gate 	    &listp) == -1) {
4107c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't walk 'configd_threads'");
4117c478bd9Sstevel@tonic-gate 		mdb_free(list, sizeof (*list) * size);
4127c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	pos = listp - list;
4167c478bd9Sstevel@tonic-gate 	for (idx = 0; idx < log_size; idx++) {
4177c478bd9Sstevel@tonic-gate 		uintptr_t addr = (uintptr_t)&base[idx];
4187c478bd9Sstevel@tonic-gate 		if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
4197c478bd9Sstevel@tonic-gate 			mdb_warn("couldn't read log entry at %p", addr);
4207c478bd9Sstevel@tonic-gate 			mdb_free(list, sizeof (*list) * size);
4217c478bd9Sstevel@tonic-gate 			return (WALK_ERR);
4227c478bd9Sstevel@tonic-gate 		}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 		if (max_time_seen < cur.rl_start)
4257c478bd9Sstevel@tonic-gate 			max_time_seen = cur.rl_start;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		if (max_time_seen < cur.rl_end)
4287c478bd9Sstevel@tonic-gate 			max_time_seen = cur.rl_end;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 		if (cur.rl_start != 0) {
4317c478bd9Sstevel@tonic-gate 			list[pos].timestamp = cur.rl_start;
4327c478bd9Sstevel@tonic-gate 			list[pos].addr = addr;
4337c478bd9Sstevel@tonic-gate 			pos++;
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	qsort(list, pos, sizeof (*list), &request_entry_compare);
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	rlw = mdb_zalloc(sizeof (*rlw), UM_SLEEP);
4397c478bd9Sstevel@tonic-gate 	rlw->rlw_max = size;
4407c478bd9Sstevel@tonic-gate 	rlw->rlw_count = pos;
4417c478bd9Sstevel@tonic-gate 	rlw->rlw_cur = 0;
4427c478bd9Sstevel@tonic-gate 	rlw->rlw_list = list;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	wsp->walk_data = rlw;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate static int
request_log_walk_step(mdb_walk_state_t * wsp)4507c478bd9Sstevel@tonic-gate request_log_walk_step(mdb_walk_state_t *wsp)
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	struct request_log_walk *rlw = wsp->walk_data;
4537c478bd9Sstevel@tonic-gate 	uintptr_t addr;
4547c478bd9Sstevel@tonic-gate 	request_log_entry_t cur;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if (rlw->rlw_cur >= rlw->rlw_count)
4577c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	addr = rlw->rlw_list[rlw->rlw_cur++].addr;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	if (mdb_vread(&cur, sizeof (cur), addr) == -1) {
4627c478bd9Sstevel@tonic-gate 		mdb_warn("couldn't read log entry at %p", addr);
4637c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &cur, wsp->walk_cbdata));
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate static void
request_log_walk_fini(mdb_walk_state_t * wsp)4697c478bd9Sstevel@tonic-gate request_log_walk_fini(mdb_walk_state_t *wsp)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	struct request_log_walk *rlw = wsp->walk_data;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	mdb_free(rlw->rlw_list, sizeof (*rlw->rlw_list) * rlw->rlw_max);
4747c478bd9Sstevel@tonic-gate 	mdb_free(rlw, sizeof (*rlw));
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
4787c478bd9Sstevel@tonic-gate 	{ "configd_status", NULL, "svc.configd status summary",
4797c478bd9Sstevel@tonic-gate 	    configd_status },
4807c478bd9Sstevel@tonic-gate 	{ "configd_thread", "?", "Print a thread_info_t tabularly",
4817c478bd9Sstevel@tonic-gate 	    configd_thread },
4827c478bd9Sstevel@tonic-gate 	{ "configd_log", "?[-v] [-c clientptr] [-i clientid]",
4837c478bd9Sstevel@tonic-gate 	    "Print the request log, or a single entry", request_log },
4847c478bd9Sstevel@tonic-gate 	{ NULL }
4857c478bd9Sstevel@tonic-gate };
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
4887c478bd9Sstevel@tonic-gate 	{ "configd_threads", "walks the thread_info_ts for all "
4897c478bd9Sstevel@tonic-gate 	    "threads", walk_thread_info_init, walk_thread_info_step },
4907c478bd9Sstevel@tonic-gate 	{ "configd_log", "walks the request_log_entry_ts",
4917c478bd9Sstevel@tonic-gate 	    request_log_walk_init, request_log_walk_step,
4927c478bd9Sstevel@tonic-gate 	    request_log_walk_fini},
4937c478bd9Sstevel@tonic-gate 	{ NULL }
4947c478bd9Sstevel@tonic-gate };
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
4977c478bd9Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
4987c478bd9Sstevel@tonic-gate };
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)5017c478bd9Sstevel@tonic-gate _mdb_init(void)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rep_protocol_requestid",
5047c478bd9Sstevel@tonic-gate 	    &request_enum) == -1) {
5057c478bd9Sstevel@tonic-gate 		mdb_warn("enum rep_protocol_requestid not found");
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rep_protocol_responseid",
5087c478bd9Sstevel@tonic-gate 	    &response_enum) == -1) {
5097c478bd9Sstevel@tonic-gate 		mdb_warn("enum rep_protocol_responseid not found");
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum rc_ptr_type",
5127c478bd9Sstevel@tonic-gate 	    &ptr_type_enum) == -1) {
5137c478bd9Sstevel@tonic-gate 		mdb_warn("enum rc_ptr_type not found");
5147c478bd9Sstevel@tonic-gate 	}
5157c478bd9Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name("enum thread_state",
5167c478bd9Sstevel@tonic-gate 	    &thread_state_enum) == -1) {
5177c478bd9Sstevel@tonic-gate 		mdb_warn("enum thread_state not found");
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	return (&modinfo);
5207c478bd9Sstevel@tonic-gate }
521