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