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