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