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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <mdb/mdb_modapi.h> 26 27 #include <libuutil.h> 28 #include <libuutil_impl.h> 29 30 #include <librestart_priv.h> /* instance_data_t */ 31 #include <startd.h> 32 33 34 /* 35 * To count the elements of a uu_list_t without knowing its implementation, we 36 * must walk & count them. 37 */ 38 /* ARGSUSED */ 39 static int 40 inc_sz(uintptr_t addr, const void *unknown, void *data) 41 { 42 size_t *sz = data; 43 44 ++(*sz); 45 46 return (WALK_NEXT); 47 } 48 49 /*ARGSUSED*/ 50 static int 51 startd_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 52 { 53 uu_list_t *dgraphp; 54 restarter_instance_list_t ril; 55 u_longlong_t ns_total; 56 u_longlong_t lookups; 57 u_longlong_t dep_inserts, dep_cycle_ns, dep_insert_ns; 58 size_t graph_num, restarter_num; 59 uint64_t ct_maint; 60 uint64_t ct_hwerr; 61 uint64_t ct_service; 62 uint64_t ct_global; 63 uint64_t ct_noprefs; 64 uint64_t ct_from_uninit; 65 uint64_t ct_bad_state; 66 uint64_t ct_ovr_prefs; 67 68 if (mdb_readvar(&lookups, "dictionary_lookups") == -1) { 69 mdb_warn("failed to read 'dictionary_lookups' value\n"); 70 return (DCMD_ERR); 71 } 72 73 if (mdb_readvar(&ns_total, "dictionary_ns_total") == -1) { 74 mdb_warn("failed to read 'dictionary_ns_total' value\n"); 75 return (DCMD_ERR); 76 } 77 78 if (mdb_readvar(&dep_inserts, "dep_inserts") == -1) { 79 mdb_warn("failed to read 'dep_inserts' value\n"); 80 return (DCMD_ERR); 81 } 82 83 if (mdb_readvar(&dep_cycle_ns, "dep_cycle_ns") == -1) { 84 mdb_warn("failed to read 'dep_cycle_ns' value\n"); 85 return (DCMD_ERR); 86 } 87 88 if (mdb_readvar(&dep_insert_ns, "dep_insert_ns") == -1) { 89 mdb_warn("failed to read 'dep_insert_ns' value\n"); 90 return (DCMD_ERR); 91 } 92 93 if (mdb_readvar(&dgraphp, "dgraph") == -1) { 94 mdb_warn("failed to read 'dgraph' value\n"); 95 return (DCMD_ERR); 96 } 97 98 graph_num = 0; 99 if (mdb_pwalk("uu_list_node", inc_sz, &graph_num, 100 (uintptr_t)dgraphp) == -1) { 101 mdb_warn("failed to read uu_list\n"); 102 return (DCMD_ERR); 103 } 104 105 if (mdb_readvar(&ril, "instance_list") == -1) { 106 mdb_warn("failed to read 'instance_list' value\n"); 107 return (DCMD_ERR); 108 } 109 110 restarter_num = 0; 111 if (mdb_pwalk("uu_list_node", inc_sz, &restarter_num, 112 (uintptr_t)ril.ril_instance_list) == -1) { 113 mdb_warn("failed to read uu_list\n"); 114 return (DCMD_ERR); 115 } 116 117 if (mdb_readvar(&ct_maint, "stev_ct_maint") == -1) { 118 mdb_warn("failed to read 'stev_ct_maint'\n"); 119 return (DCMD_ERR); 120 } 121 122 if (mdb_readvar(&ct_hwerr, "stev_ct_hwerr") == -1) { 123 mdb_warn("failed to read 'stev_ct_hwerr'\n"); 124 return (DCMD_ERR); 125 } 126 127 if (mdb_readvar(&ct_service, "stev_ct_service") == -1) { 128 mdb_warn("failed to read 'stev_ct_service'\n"); 129 return (DCMD_ERR); 130 } 131 132 if (mdb_readvar(&ct_global, "stev_ct_global") == -1) { 133 mdb_warn("failed to read 'stev_ct_global'\n"); 134 return (DCMD_ERR); 135 } 136 137 if (mdb_readvar(&ct_noprefs, "stev_ct_noprefs") == -1) { 138 mdb_warn("failed to read 'stev_ct_noprefs'\n"); 139 return (DCMD_ERR); 140 } 141 142 if (mdb_readvar(&ct_from_uninit, "stev_ct_from_uninit") == -1) { 143 mdb_warn("failed to read 'stev_ct_from_uninit'\n"); 144 return (DCMD_ERR); 145 } 146 147 if (mdb_readvar(&ct_bad_state, "stev_ct_bad_state") == -1) { 148 mdb_warn("failed to read 'stev_ct_bad_state'\n"); 149 return (DCMD_ERR); 150 } 151 152 if (mdb_readvar(&ct_ovr_prefs, "stev_ct_ovr_prefs") == -1) { 153 mdb_warn("failed to read 'stev_ct_ovr_prefs'\n"); 154 return (DCMD_ERR); 155 } 156 157 mdb_printf( 158 "General stats\n" 159 " dictionary lookups: %llu\n" 160 " average lookup time: %llu us\n" 161 " graph dependency insertions: %llu\n" 162 " average cycle-check time: %llu us\n" 163 " avg dependency insert time: %llu us\n" 164 " number of nodes in dgraph: %llu\n" 165 "number of nodes in instance_list: %llu\n" 166 "\nState Transition Events\n" 167 " maintenance: %llu\n" 168 " hardware error: %llu\n" 169 " service specific pref: %llu\n" 170 " system wide pref: %llu\n" 171 " no prefs, not raised: %llu\n" 172 " from unint, not raised: %llu\n" 173 " bad state, not raised: %llu\n" 174 " override pref, raised: %llu\n", lookups, 175 lookups ? ns_total / (1000 * lookups) : 0, dep_inserts, 176 dep_inserts ? dep_cycle_ns / (1000 * dep_inserts) : 0, 177 dep_inserts ? dep_insert_ns / (1000 * dep_inserts) : 0, 178 (u_longlong_t)graph_num, (u_longlong_t)restarter_num, 179 ct_maint, ct_hwerr, ct_service, ct_global, ct_noprefs, 180 ct_from_uninit, ct_bad_state, ct_ovr_prefs); 181 182 183 return (DCMD_OK); 184 } 185 186 static char 187 xstate2chr(restarter_instance_state_t s) 188 { 189 switch (s) { 190 case RESTARTER_STATE_UNINIT: return ('u'); 191 case RESTARTER_STATE_DISABLED: return ('d'); 192 case RESTARTER_STATE_OFFLINE: return ('0'); 193 case RESTARTER_STATE_DEGRADED: return ('D'); 194 case RESTARTER_STATE_ONLINE: return ('1'); 195 case RESTARTER_STATE_MAINT: return ('m'); 196 case RESTARTER_STATE_NONE: return ('n'); 197 default: return ('?'); 198 } 199 } 200 201 /*ARGSUSED*/ 202 static int 203 pr_instance(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 204 { 205 restarter_instance_list_t ril; 206 restarter_inst_t ri; 207 char *iname; 208 char statechr = '-'; 209 char typechr; 210 211 if ((flags & DCMD_ADDRSPEC) == 0) { 212 if (mdb_readvar(&ril, "instance_list") == -1) { 213 mdb_warn("failed to read 'instance_list' value\n"); 214 return (DCMD_ERR); 215 } 216 217 if (mdb_pwalk_dcmd("uu_list_node", "instance", 0, NULL, 218 (uintptr_t)ril.ril_instance_list) == -1) { 219 mdb_warn("can't walk instances\n"); 220 return (DCMD_ERR); 221 } 222 223 return (DCMD_OK); 224 } 225 226 if (mdb_vread(&ri, sizeof (restarter_inst_t), addr) == -1) { 227 mdb_warn("couldn't read instance at %a\n"); 228 return (DCMD_ERR); 229 } 230 231 if (DCMD_HDRSPEC(flags)) 232 mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S", 233 "FMRI"); 234 235 iname = mdb_alloc(1024, UM_SLEEP | UM_GC); 236 237 if (mdb_readstr(iname, 1024, (uintptr_t)ri.ri_i.i_fmri) == -1) { 238 mdb_warn("couldn't read instance name\n"); 239 strcpy(iname, "-"); 240 } 241 242 statechr = xstate2chr(ri.ri_i.i_state); 243 typechr = (ri.ri_i.i_enabled) ? 'I' : 'i'; 244 245 mdb_printf("%-10a %3x %c %c %s\n", addr, ri.ri_id, typechr, statechr, 246 iname); 247 248 return (DCMD_OK); 249 } 250 251 /*ARGSUSED*/ 252 static int 253 pr_vertex(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 254 { 255 uu_list_t *dgraphp; 256 graph_vertex_t gv; 257 char *vname; 258 int id; 259 char typechr; 260 char statechr = '-'; 261 262 if ((flags & DCMD_ADDRSPEC) == 0) { 263 if (mdb_readvar(&dgraphp, "dgraph") == -1) { 264 mdb_warn("failed to read 'dgraph' value\n"); 265 return (DCMD_ERR); 266 } 267 268 if (mdb_pwalk_dcmd("uu_list_node", "vertex", 0, NULL, 269 (uintptr_t)dgraphp) == -1) { 270 mdb_warn("can't walk vertices"); 271 return (DCMD_ERR); 272 } 273 274 return (DCMD_OK); 275 } 276 277 if (mdb_vread(&gv, sizeof (graph_vertex_t), addr) == -1) { 278 mdb_warn("couldn't read vertex at %a\n"); 279 return (DCMD_ERR); 280 } 281 282 if (DCMD_HDRSPEC(flags)) 283 mdb_printf("%-10s %-3s %1s %1s %4s\n", "ADDR", "ID", "T", "S", 284 "FMRI"); 285 286 vname = mdb_alloc(1024, UM_SLEEP | UM_GC); 287 288 if (mdb_readstr(vname, 1024, (uintptr_t)gv.gv_name) == -1) { 289 mdb_warn("couldn't read vertex name\n"); 290 strcpy(vname, "-"); 291 } 292 293 id = gv.gv_id; 294 295 switch (gv.gv_type) { 296 case GVT_FILE: 297 typechr = 'f'; 298 break; 299 case GVT_GROUP: 300 switch (gv.gv_depgroup) { 301 case DEPGRP_REQUIRE_ANY: 302 typechr = 'r'; 303 break; 304 case DEPGRP_REQUIRE_ALL: 305 typechr = 'R'; 306 break; 307 case DEPGRP_EXCLUDE_ALL: 308 typechr = 'X'; 309 break; 310 case DEPGRP_OPTIONAL_ALL: 311 typechr = 'o'; 312 break; 313 default: 314 typechr = '?'; 315 break; 316 } 317 break; 318 case GVT_INST: 319 typechr = (gv.gv_flags & GV_ENABLED) ? 'I' : 'i'; 320 statechr = xstate2chr(gv.gv_state); 321 break; 322 case GVT_SVC: 323 typechr = 's'; 324 break; 325 default: 326 typechr = '?'; 327 break; 328 } 329 330 mdb_printf("%-10a %3x %c %c %s\n", addr, id, typechr, statechr, vname); 331 332 return (DCMD_OK); 333 } 334 335 /* ARGSUSED */ 336 static int 337 logbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 338 { 339 GElf_Sym sym; 340 char *buf; 341 char *cp; 342 343 if (mdb_lookup_by_name("logbuf", &sym) == -1) { 344 mdb_warn("The 'logbuf' symbol is missing.\n"); 345 return (DCMD_ERR); 346 } 347 348 buf = mdb_alloc(sym.st_size, UM_SLEEP | UM_GC); 349 350 if (mdb_vread(buf, sym.st_size, sym.st_value) == -1) { 351 mdb_warn("failed to read 'logbuf'\n"); 352 return (DCMD_ERR); 353 } 354 355 cp = strchr(buf, '\0'); 356 357 if (cp == buf) 358 /* Empty */ 359 return (DCMD_OK); 360 361 if (cp >= buf + sym.st_size || 362 strchr(cp + 1, '\0') >= buf + sym.st_size) { 363 mdb_warn("'logbuf' is corrupt\n"); 364 return (DCMD_ERR); 365 } 366 367 mdb_printf("%s", cp + 1); 368 mdb_printf("%s", buf); 369 370 return (DCMD_OK); 371 } 372 373 static const mdb_dcmd_t dcmds[] = { 374 { "instance", NULL, "display svc.startd restarter instance", 375 pr_instance }, 376 { "startd_log", NULL, "display svc.startd debug message buffer", 377 logbuf }, 378 { "startd_status", NULL, "svc.startd status summary", startd_status }, 379 { "vertex", NULL, "display svc.startd dependency graph vertex", 380 pr_vertex }, 381 { NULL } 382 }; 383 384 static const mdb_walker_t walkers[] = { 385 { NULL } 386 }; 387 388 static const mdb_modinfo_t modinfo = { 389 MDB_API_VERSION, dcmds, walkers 390 }; 391 392 const mdb_modinfo_t * 393 _mdb_init(void) 394 { 395 return (&modinfo); 396 } 397