xref: /onnv-gate/usr/src/cmd/mdb/common/modules/svc.startd/startd.c (revision 2747:87ae3ca2e4c8)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2747Sbustos  * Common Development and Distribution License (the "License").
6*2747Sbustos  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2747Sbustos  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <libuutil.h>
310Sstevel@tonic-gate #include <libuutil_impl.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <librestart_priv.h>		/* instance_data_t */
340Sstevel@tonic-gate #include <startd.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * To count the elements of a uu_list_t without knowing its implementation, we
390Sstevel@tonic-gate  * must walk & count them.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate /* ARGSUSED */
420Sstevel@tonic-gate static int
430Sstevel@tonic-gate inc_sz(uintptr_t addr, const void *unknown, void *data)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate 	size_t *sz = data;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 	++(*sz);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	return (WALK_NEXT);
500Sstevel@tonic-gate }
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*ARGSUSED*/
530Sstevel@tonic-gate static int
540Sstevel@tonic-gate startd_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate 	uu_list_t *dgraphp;
570Sstevel@tonic-gate 	restarter_instance_list_t ril;
580Sstevel@tonic-gate 	u_longlong_t ns_total;
590Sstevel@tonic-gate 	u_longlong_t lookups;
600Sstevel@tonic-gate 	u_longlong_t dep_inserts, dep_cycle_ns, dep_insert_ns;
610Sstevel@tonic-gate 	size_t graph_num, restarter_num;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	if (mdb_readvar(&lookups, "dictionary_lookups") == -1) {
640Sstevel@tonic-gate 		mdb_warn("failed to read 'dictionary_lookups' value\n");
650Sstevel@tonic-gate 		return (DCMD_ERR);
660Sstevel@tonic-gate 	}
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	if (mdb_readvar(&ns_total, "dictionary_ns_total") == -1) {
690Sstevel@tonic-gate 		mdb_warn("failed to read 'dictionary_ns_total' value\n");
700Sstevel@tonic-gate 		return (DCMD_ERR);
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	if (mdb_readvar(&dep_inserts, "dep_inserts") == -1) {
740Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_inserts' value\n");
750Sstevel@tonic-gate 		return (DCMD_ERR);
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (mdb_readvar(&dep_cycle_ns, "dep_cycle_ns") == -1) {
790Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_cycle_ns' value\n");
800Sstevel@tonic-gate 		return (DCMD_ERR);
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	if (mdb_readvar(&dep_insert_ns, "dep_insert_ns") == -1) {
840Sstevel@tonic-gate 		mdb_warn("failed to read 'dep_insert_ns' value\n");
850Sstevel@tonic-gate 		return (DCMD_ERR);
860Sstevel@tonic-gate 	}
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	if (mdb_readvar(&dgraphp, "dgraph") == -1) {
890Sstevel@tonic-gate 		mdb_warn("failed to read 'dgraph' value\n");
900Sstevel@tonic-gate 		return (DCMD_ERR);
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	graph_num = 0;
940Sstevel@tonic-gate 	if (mdb_pwalk("uu_list_node", inc_sz, &graph_num,
950Sstevel@tonic-gate 	    (uintptr_t)dgraphp) == -1) {
960Sstevel@tonic-gate 		mdb_warn("failed to read uu_list\n");
970Sstevel@tonic-gate 		return (DCMD_ERR);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	if (mdb_readvar(&ril, "instance_list") == -1) {
1010Sstevel@tonic-gate 		mdb_warn("failed to read 'instance_list' value\n");
1020Sstevel@tonic-gate 		return (DCMD_ERR);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	restarter_num = 0;
1060Sstevel@tonic-gate 	if (mdb_pwalk("uu_list_node", inc_sz, &restarter_num,
1070Sstevel@tonic-gate 	    (uintptr_t)ril.ril_instance_list) == -1) {
1080Sstevel@tonic-gate 		mdb_warn("failed to read uu_list\n");
1090Sstevel@tonic-gate 		return (DCMD_ERR);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	mdb_printf(
1130Sstevel@tonic-gate 	    "         dictionary lookups: %llu\n"
1140Sstevel@tonic-gate 	    "        average lookup time: %llu us\n"
1150Sstevel@tonic-gate 	    "graph dependency insertions: %llu\n"
1160Sstevel@tonic-gate 	    "   average cycle-check time: %llu us\n"
1170Sstevel@tonic-gate 	    " avg dependency insert time: %llu us\n"
1180Sstevel@tonic-gate 	    "number of nodes in dgraph: %llu\n"
1190Sstevel@tonic-gate 	    "number of nodes in instance_list: %llu\n", lookups,
1200Sstevel@tonic-gate 	    lookups ? ns_total / (1000 * lookups) : 0, dep_inserts,
1210Sstevel@tonic-gate 	    dep_inserts ? dep_cycle_ns / (1000 * dep_inserts) : 0,
1220Sstevel@tonic-gate 	    dep_inserts ? dep_insert_ns / (1000 * dep_inserts) : 0,
1230Sstevel@tonic-gate 	    (u_longlong_t)graph_num, (u_longlong_t)restarter_num);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	return (DCMD_OK);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static char
1290Sstevel@tonic-gate xstate2chr(restarter_instance_state_t s)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	switch (s) {
1320Sstevel@tonic-gate 	case RESTARTER_STATE_UNINIT:	return ('u');
1330Sstevel@tonic-gate 	case RESTARTER_STATE_DISABLED:	return ('d');
1340Sstevel@tonic-gate 	case RESTARTER_STATE_OFFLINE:	return ('0');
1350Sstevel@tonic-gate 	case RESTARTER_STATE_DEGRADED:	return ('D');
1360Sstevel@tonic-gate 	case RESTARTER_STATE_ONLINE:	return ('1');
1370Sstevel@tonic-gate 	case RESTARTER_STATE_MAINT:	return ('m');
1380Sstevel@tonic-gate 	case RESTARTER_STATE_NONE:	return ('n');
1390Sstevel@tonic-gate 	default:			return ('?');
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate /*ARGSUSED*/
1440Sstevel@tonic-gate static int
1450Sstevel@tonic-gate pr_instance(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	restarter_instance_list_t ril;
1480Sstevel@tonic-gate 	restarter_inst_t ri;
1490Sstevel@tonic-gate 	char *iname;
1500Sstevel@tonic-gate 	char statechr = '-';
1510Sstevel@tonic-gate 	char typechr;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
1540Sstevel@tonic-gate 		if (mdb_readvar(&ril, "instance_list") == -1) {
1550Sstevel@tonic-gate 			mdb_warn("failed to read 'instance_list' value\n");
1560Sstevel@tonic-gate 			return (DCMD_ERR);
1570Sstevel@tonic-gate 		}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uu_list_node", "instance", 0, NULL,
1600Sstevel@tonic-gate 		    (uintptr_t)ril.ril_instance_list) == -1) {
1610Sstevel@tonic-gate 			mdb_warn("can't walk instances\n");
1620Sstevel@tonic-gate 			return (DCMD_ERR);
1630Sstevel@tonic-gate 		}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 		return (DCMD_OK);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (mdb_vread(&ri, sizeof (restarter_inst_t), addr) == -1) {
1690Sstevel@tonic-gate 		mdb_warn("couldn't read instance at %a\n");
1700Sstevel@tonic-gate 		return (DCMD_ERR);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
1740Sstevel@tonic-gate 		mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S",
1750Sstevel@tonic-gate 		    "FMRI");
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	iname = mdb_alloc(1024, UM_SLEEP | UM_GC);
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	if (mdb_readstr(iname, 1024, (uintptr_t)ri.ri_i.i_fmri) == -1) {
1800Sstevel@tonic-gate 		mdb_warn("couldn't read instance name\n");
1810Sstevel@tonic-gate 		strcpy(iname, "-");
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	statechr = xstate2chr(ri.ri_i.i_state);
1850Sstevel@tonic-gate 	typechr = (ri.ri_i.i_enabled) ? 'I' : 'i';
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	mdb_printf("%-10a %3x %c %c %s\n", addr, ri.ri_id, typechr, statechr,
1880Sstevel@tonic-gate 	    iname);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	return (DCMD_OK);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate /*ARGSUSED*/
1940Sstevel@tonic-gate static int
1950Sstevel@tonic-gate pr_vertex(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	uu_list_t *dgraphp;
1980Sstevel@tonic-gate 	graph_vertex_t gv;
1990Sstevel@tonic-gate 	char *vname;
2000Sstevel@tonic-gate 	int id;
2010Sstevel@tonic-gate 	char typechr;
2020Sstevel@tonic-gate 	char statechr = '-';
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) == 0) {
2050Sstevel@tonic-gate 		if (mdb_readvar(&dgraphp, "dgraph") == -1) {
2060Sstevel@tonic-gate 			mdb_warn("failed to read 'dgraph' value\n");
2070Sstevel@tonic-gate 			return (DCMD_ERR);
2080Sstevel@tonic-gate 		}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uu_list_node", "vertex", 0, NULL,
2110Sstevel@tonic-gate 		    (uintptr_t)dgraphp) == -1) {
2120Sstevel@tonic-gate 			mdb_warn("can't walk vertices");
2130Sstevel@tonic-gate 			return (DCMD_ERR);
2140Sstevel@tonic-gate 		}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 		return (DCMD_OK);
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	if (mdb_vread(&gv, sizeof (graph_vertex_t), addr) == -1) {
2200Sstevel@tonic-gate 		mdb_warn("couldn't read vertex at %a\n");
2210Sstevel@tonic-gate 		return (DCMD_ERR);
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
2250Sstevel@tonic-gate 		mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S",
2260Sstevel@tonic-gate 		    "FMRI");
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	vname = mdb_alloc(1024, UM_SLEEP | UM_GC);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if (mdb_readstr(vname, 1024, (uintptr_t)gv.gv_name) == -1) {
2310Sstevel@tonic-gate 		mdb_warn("couldn't read vertex name\n");
2320Sstevel@tonic-gate 		strcpy(vname, "-");
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	id = gv.gv_id;
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	switch (gv.gv_type) {
2380Sstevel@tonic-gate 	case GVT_FILE:
2390Sstevel@tonic-gate 		typechr = 'f';
2400Sstevel@tonic-gate 		break;
2410Sstevel@tonic-gate 	case GVT_GROUP:
2420Sstevel@tonic-gate 		switch (gv.gv_depgroup) {
2430Sstevel@tonic-gate 		case DEPGRP_REQUIRE_ANY:
2440Sstevel@tonic-gate 			typechr = 'r';
2450Sstevel@tonic-gate 			break;
2460Sstevel@tonic-gate 		case DEPGRP_REQUIRE_ALL:
2470Sstevel@tonic-gate 			typechr = 'R';
2480Sstevel@tonic-gate 			break;
2490Sstevel@tonic-gate 		case DEPGRP_EXCLUDE_ALL:
2500Sstevel@tonic-gate 			typechr = 'X';
2510Sstevel@tonic-gate 			break;
2520Sstevel@tonic-gate 		case DEPGRP_OPTIONAL_ALL:
2530Sstevel@tonic-gate 			typechr = 'o';
2540Sstevel@tonic-gate 			break;
2550Sstevel@tonic-gate 		default:
2560Sstevel@tonic-gate 			typechr = '?';
2570Sstevel@tonic-gate 			break;
2580Sstevel@tonic-gate 		}
2590Sstevel@tonic-gate 		break;
2600Sstevel@tonic-gate 	case GVT_INST:
2610Sstevel@tonic-gate 		typechr = (gv.gv_flags & GV_ENABLED) ? 'I' : 'i';
2620Sstevel@tonic-gate 		statechr = xstate2chr(gv.gv_state);
2630Sstevel@tonic-gate 		break;
2640Sstevel@tonic-gate 	case GVT_SVC:
2650Sstevel@tonic-gate 		typechr = 's';
2660Sstevel@tonic-gate 		break;
2670Sstevel@tonic-gate 	default:
2680Sstevel@tonic-gate 		typechr = '?';
2690Sstevel@tonic-gate 		break;
2700Sstevel@tonic-gate 	}
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	mdb_printf("%-10a %3x %c %c %s\n", addr, id, typechr, statechr, vname);
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	return (DCMD_OK);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate /* ARGSUSED */
2780Sstevel@tonic-gate static int
2790Sstevel@tonic-gate logbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2800Sstevel@tonic-gate {
281*2747Sbustos 	GElf_Sym sym;
2820Sstevel@tonic-gate 	char *buf;
2830Sstevel@tonic-gate 	char *cp;
2840Sstevel@tonic-gate 
285*2747Sbustos 	if (mdb_lookup_by_name("logbuf", &sym) == -1) {
286*2747Sbustos 		mdb_warn("The 'logbuf' symbol is missing.\n");
2870Sstevel@tonic-gate 		return (DCMD_ERR);
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
290*2747Sbustos 	buf = mdb_alloc(sym.st_size, UM_SLEEP | UM_GC);
2910Sstevel@tonic-gate 
292*2747Sbustos 	if (mdb_vread(buf, sym.st_size, sym.st_value) == -1) {
2930Sstevel@tonic-gate 		mdb_warn("failed to read 'logbuf'\n");
2940Sstevel@tonic-gate 		return (DCMD_ERR);
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	cp = strchr(buf, '\0');
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (cp == buf)
3000Sstevel@tonic-gate 		/* Empty */
3010Sstevel@tonic-gate 		return (DCMD_OK);
3020Sstevel@tonic-gate 
303*2747Sbustos 	if (cp >= buf + sym.st_size ||
304*2747Sbustos 	    strchr(cp + 1, '\0') >= buf + sym.st_size) {
3050Sstevel@tonic-gate 		mdb_warn("'logbuf' is corrupt\n");
3060Sstevel@tonic-gate 		return (DCMD_ERR);
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	mdb_printf("%s", cp + 1);
3100Sstevel@tonic-gate 	mdb_printf("%s", buf);
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	return (DCMD_OK);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
3160Sstevel@tonic-gate 	{ "instance", NULL, "display svc.startd restarter instance",
3170Sstevel@tonic-gate 	    pr_instance },
3180Sstevel@tonic-gate 	{ "startd_log", NULL, "display svc.startd debug message buffer",
3190Sstevel@tonic-gate 	    logbuf },
3200Sstevel@tonic-gate 	{ "startd_status", NULL, "svc.startd status summary", startd_status },
3210Sstevel@tonic-gate 	{ "vertex", NULL, "display svc.startd dependency graph vertex",
3220Sstevel@tonic-gate 	    pr_vertex },
3230Sstevel@tonic-gate 	{ NULL }
3240Sstevel@tonic-gate };
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
3270Sstevel@tonic-gate 	{ NULL }
3280Sstevel@tonic-gate };
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
3310Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
3320Sstevel@tonic-gate };
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate const mdb_modinfo_t *
3350Sstevel@tonic-gate _mdb_init(void)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 	return (&modinfo);
3380Sstevel@tonic-gate }
339