1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1493 gavinm * Common Development and Distribution License (the "License"). 6 1493 gavinm * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1493 gavinm 22 0 stevel /* 23 9078 Stephen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel * 26 0 stevel * fme.c -- fault management exercise module 27 0 stevel * 28 0 stevel * this module provides the simulated fault management exercise. 29 0 stevel */ 30 0 stevel 31 0 stevel #include <stdio.h> 32 0 stevel #include <stdlib.h> 33 0 stevel #include <string.h> 34 0 stevel #include <strings.h> 35 0 stevel #include <ctype.h> 36 0 stevel #include <alloca.h> 37 0 stevel #include <libnvpair.h> 38 0 stevel #include <sys/fm/protocol.h> 39 0 stevel #include <fm/fmd_api.h> 40 0 stevel #include "alloc.h" 41 0 stevel #include "out.h" 42 0 stevel #include "stats.h" 43 0 stevel #include "stable.h" 44 0 stevel #include "literals.h" 45 0 stevel #include "lut.h" 46 0 stevel #include "tree.h" 47 0 stevel #include "ptree.h" 48 0 stevel #include "itree.h" 49 0 stevel #include "ipath.h" 50 0 stevel #include "fme.h" 51 0 stevel #include "evnv.h" 52 0 stevel #include "eval.h" 53 0 stevel #include "config.h" 54 0 stevel #include "platform.h" 55 5204 stephh #include "esclex.h" 56 0 stevel 57 0 stevel /* imported from eft.c... */ 58 0 stevel extern hrtime_t Hesitate; 59 5204 stephh extern char *Serd_Override; 60 0 stevel extern nv_alloc_t Eft_nv_hdl; 61 814 jrutt extern int Max_fme; 62 1414 cindi extern fmd_hdl_t *Hdl; 63 1414 cindi 64 1414 cindi static int Istat_need_save; 65 4436 stephh static int Serd_need_save; 66 2120 gavinm void istat_save(void); 67 4436 stephh void serd_save(void); 68 0 stevel 69 0 stevel /* fme under construction is global so we can free it on module abort */ 70 0 stevel static struct fme *Nfmep; 71 0 stevel 72 7748 Tarik static int Undiag_reason = UD_VAL_UNKNOWN; 73 0 stevel 74 0 stevel static int Nextid = 0; 75 814 jrutt 76 814 jrutt static int Open_fme_count = 0; /* Count of open FMEs */ 77 0 stevel 78 0 stevel /* list of fault management exercises underway */ 79 0 stevel static struct fme { 80 0 stevel struct fme *next; /* next exercise */ 81 0 stevel unsigned long long ull; /* time when fme was created */ 82 0 stevel int id; /* FME id */ 83 5204 stephh struct config *config; /* cooked configuration data */ 84 0 stevel struct lut *eventtree; /* propagation tree for this FME */ 85 0 stevel /* 86 0 stevel * The initial error report that created this FME is kept in 87 0 stevel * two forms. e0 points to the instance tree node and is used 88 0 stevel * by fme_eval() as the starting point for the inference 89 0 stevel * algorithm. e0r is the event handle FMD passed to us when 90 0 stevel * the ereport first arrived and is used when setting timers, 91 0 stevel * which are always relative to the time of this initial 92 0 stevel * report. 93 0 stevel */ 94 0 stevel struct event *e0; 95 0 stevel fmd_event_t *e0r; 96 0 stevel 97 0 stevel id_t timer; /* for setting an fmd time-out */ 98 0 stevel 99 0 stevel struct event *ecurrent; /* ereport under consideration */ 100 0 stevel struct event *suspects; /* current suspect list */ 101 0 stevel struct event *psuspects; /* previous suspect list */ 102 0 stevel int nsuspects; /* count of suspects */ 103 0 stevel int posted_suspects; /* true if we've posted a diagnosis */ 104 0 stevel int uniqobs; /* number of unique events observed */ 105 0 stevel int peek; /* just peeking, don't track suspects */ 106 814 jrutt int overflow; /* true if overflow FME */ 107 0 stevel enum fme_state { 108 0 stevel FME_NOTHING = 5000, /* not evaluated yet */ 109 0 stevel FME_WAIT, /* need to wait for more info */ 110 0 stevel FME_CREDIBLE, /* suspect list is credible */ 111 1414 cindi FME_DISPROVED, /* no valid suspects found */ 112 1414 cindi FME_DEFERRED /* don't know yet (k-count not met) */ 113 0 stevel } state; 114 0 stevel 115 0 stevel unsigned long long pull; /* time passed since created */ 116 0 stevel unsigned long long wull; /* wait until this time for re-eval */ 117 0 stevel struct event *observations; /* observation list */ 118 0 stevel struct lut *globals; /* values of global variables */ 119 0 stevel /* fmd interfacing */ 120 0 stevel fmd_hdl_t *hdl; /* handle for talking with fmd */ 121 0 stevel fmd_case_t *fmcase; /* what fmd 'case' we associate with */ 122 0 stevel /* stats */ 123 0 stevel struct stats *Rcount; 124 0 stevel struct stats *Hcallcount; 125 0 stevel struct stats *Rcallcount; 126 0 stevel struct stats *Ccallcount; 127 0 stevel struct stats *Ecallcount; 128 0 stevel struct stats *Tcallcount; 129 0 stevel struct stats *Marrowcount; 130 0 stevel struct stats *diags; 131 0 stevel } *FMElist, *EFMElist, *ClosedFMEs; 132 0 stevel 133 0 stevel static struct case_list { 134 0 stevel fmd_case_t *fmcase; 135 0 stevel struct case_list *next; 136 0 stevel } *Undiagablecaselist; 137 0 stevel 138 0 stevel static void fme_eval(struct fme *fmep, fmd_event_t *ffep); 139 0 stevel static enum fme_state hypothesise(struct fme *fmep, struct event *ep, 140 1414 cindi unsigned long long at_latest_by, unsigned long long *pdelay); 141 0 stevel static struct node *eventprop_lookup(struct event *ep, const char *propname); 142 0 stevel static struct node *pathstring2epnamenp(char *path); 143 4436 stephh static void publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep, 144 4436 stephh fmd_case_t *fmcase); 145 7748 Tarik static const char *undiag_2reason_str(int ud); 146 7748 Tarik static const char *undiag_2defect_str(int ud); 147 0 stevel static void restore_suspects(struct fme *fmep); 148 0 stevel static void save_suspects(struct fme *fmep); 149 0 stevel static void destroy_fme(struct fme *f); 150 0 stevel static void fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 151 0 stevel const char *eventstring, const struct ipath *ipp, nvlist_t *nvl); 152 2120 gavinm static void istat_counter_reset_cb(struct istat_entry *entp, 153 2120 gavinm struct stats *statp, const struct ipath *ipp); 154 5204 stephh static void istat_counter_topo_chg_cb(struct istat_entry *entp, 155 5204 stephh struct stats *statp, void *unused); 156 4436 stephh static void serd_reset_cb(struct serd_entry *entp, void *unused, 157 4436 stephh const struct ipath *ipp); 158 5204 stephh static void serd_topo_chg_cb(struct serd_entry *entp, void *unused, 159 5204 stephh void *unused2); 160 4436 stephh static void destroy_fme_bufs(struct fme *fp); 161 0 stevel 162 0 stevel static struct fme * 163 0 stevel alloc_fme(void) 164 0 stevel { 165 0 stevel struct fme *fmep; 166 0 stevel 167 0 stevel fmep = MALLOC(sizeof (*fmep)); 168 0 stevel bzero(fmep, sizeof (*fmep)); 169 0 stevel return (fmep); 170 0 stevel } 171 0 stevel 172 0 stevel /* 173 0 stevel * fme_ready -- called when all initialization of the FME (except for 174 0 stevel * stats) has completed successfully. Adds the fme to global lists 175 0 stevel * and establishes its stats. 176 0 stevel */ 177 0 stevel static struct fme * 178 0 stevel fme_ready(struct fme *fmep) 179 0 stevel { 180 0 stevel char nbuf[100]; 181 0 stevel 182 0 stevel Nfmep = NULL; /* don't need to free this on module abort now */ 183 0 stevel 184 0 stevel if (EFMElist) { 185 0 stevel EFMElist->next = fmep; 186 0 stevel EFMElist = fmep; 187 0 stevel } else 188 0 stevel FMElist = EFMElist = fmep; 189 0 stevel 190 0 stevel (void) sprintf(nbuf, "fme%d.Rcount", fmep->id); 191 0 stevel fmep->Rcount = stats_new_counter(nbuf, "ereports received", 0); 192 0 stevel (void) sprintf(nbuf, "fme%d.Hcall", fmep->id); 193 0 stevel fmep->Hcallcount = stats_new_counter(nbuf, "calls to hypothesise()", 1); 194 0 stevel (void) sprintf(nbuf, "fme%d.Rcall", fmep->id); 195 0 stevel fmep->Rcallcount = stats_new_counter(nbuf, 196 0 stevel "calls to requirements_test()", 1); 197 0 stevel (void) sprintf(nbuf, "fme%d.Ccall", fmep->id); 198 0 stevel fmep->Ccallcount = stats_new_counter(nbuf, "calls to causes_test()", 1); 199 0 stevel (void) sprintf(nbuf, "fme%d.Ecall", fmep->id); 200 0 stevel fmep->Ecallcount = 201 0 stevel stats_new_counter(nbuf, "calls to effects_test()", 1); 202 0 stevel (void) sprintf(nbuf, "fme%d.Tcall", fmep->id); 203 0 stevel fmep->Tcallcount = stats_new_counter(nbuf, "calls to triggered()", 1); 204 0 stevel (void) sprintf(nbuf, "fme%d.Marrow", fmep->id); 205 0 stevel fmep->Marrowcount = stats_new_counter(nbuf, 206 0 stevel "arrows marked by mark_arrows()", 1); 207 0 stevel (void) sprintf(nbuf, "fme%d.diags", fmep->id); 208 0 stevel fmep->diags = stats_new_counter(nbuf, "suspect lists diagnosed", 0); 209 0 stevel 210 0 stevel out(O_ALTFP|O_VERB2, "newfme: config snapshot contains..."); 211 5204 stephh config_print(O_ALTFP|O_VERB2, fmep->config); 212 0 stevel 213 0 stevel return (fmep); 214 0 stevel } 215 0 stevel 216 4436 stephh extern void ipath_dummy_lut(struct arrow *); 217 4436 stephh extern struct lut *itree_create_dummy(const char *, const struct ipath *); 218 4436 stephh 219 4436 stephh /* ARGSUSED */ 220 4436 stephh static void 221 4436 stephh set_needed_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 222 4436 stephh { 223 4436 stephh struct bubble *bp; 224 4436 stephh struct arrowlist *ap; 225 4436 stephh 226 4436 stephh for (bp = itree_next_bubble(ep, NULL); bp; 227 4436 stephh bp = itree_next_bubble(ep, bp)) { 228 4436 stephh if (bp->t != B_FROM) 229 4436 stephh continue; 230 4436 stephh for (ap = itree_next_arrow(bp, NULL); ap; 231 4436 stephh ap = itree_next_arrow(bp, ap)) { 232 4436 stephh ap->arrowp->pnode->u.arrow.needed = 1; 233 4436 stephh ipath_dummy_lut(ap->arrowp); 234 4436 stephh } 235 4436 stephh } 236 4436 stephh } 237 4436 stephh 238 4436 stephh /* ARGSUSED */ 239 4436 stephh static void 240 4436 stephh unset_needed_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 241 4436 stephh { 242 4436 stephh struct bubble *bp; 243 4436 stephh struct arrowlist *ap; 244 4436 stephh 245 4436 stephh for (bp = itree_next_bubble(ep, NULL); bp; 246 4436 stephh bp = itree_next_bubble(ep, bp)) { 247 4436 stephh if (bp->t != B_FROM) 248 4436 stephh continue; 249 4436 stephh for (ap = itree_next_arrow(bp, NULL); ap; 250 4436 stephh ap = itree_next_arrow(bp, ap)) 251 4436 stephh ap->arrowp->pnode->u.arrow.needed = 0; 252 4436 stephh } 253 4436 stephh } 254 4436 stephh 255 4436 stephh static void globals_destructor(void *left, void *right, void *arg); 256 4436 stephh static void clear_arrows(struct event *ep, struct event *ep2, struct fme *fmep); 257 4436 stephh 258 4436 stephh static void 259 4436 stephh prune_propagations(const char *e0class, const struct ipath *e0ipp) 260 4436 stephh { 261 4436 stephh char nbuf[100]; 262 4436 stephh unsigned long long my_delay = TIMEVAL_EVENTUALLY; 263 4436 stephh extern struct lut *Usednames; 264 4436 stephh 265 4436 stephh Nfmep = alloc_fme(); 266 4436 stephh Nfmep->id = Nextid; 267 4436 stephh Nfmep->state = FME_NOTHING; 268 4436 stephh Nfmep->eventtree = itree_create_dummy(e0class, e0ipp); 269 4436 stephh if ((Nfmep->e0 = 270 4436 stephh itree_lookup(Nfmep->eventtree, e0class, e0ipp)) == NULL) { 271 4436 stephh out(O_ALTFP, "prune_propagations: e0 not in instance tree"); 272 4436 stephh itree_free(Nfmep->eventtree); 273 4436 stephh FREE(Nfmep); 274 4436 stephh Nfmep = NULL; 275 4436 stephh return; 276 4436 stephh } 277 4436 stephh Nfmep->ecurrent = Nfmep->observations = Nfmep->e0; 278 4436 stephh Nfmep->e0->count++; 279 4436 stephh 280 4436 stephh (void) sprintf(nbuf, "fme%d.Rcount", Nfmep->id); 281 4436 stephh Nfmep->Rcount = stats_new_counter(nbuf, "ereports received", 0); 282 4436 stephh (void) sprintf(nbuf, "fme%d.Hcall", Nfmep->id); 283 4436 stephh Nfmep->Hcallcount = 284 4436 stephh stats_new_counter(nbuf, "calls to hypothesise()", 1); 285 4436 stephh (void) sprintf(nbuf, "fme%d.Rcall", Nfmep->id); 286 4436 stephh Nfmep->Rcallcount = stats_new_counter(nbuf, 287 4436 stephh "calls to requirements_test()", 1); 288 4436 stephh (void) sprintf(nbuf, "fme%d.Ccall", Nfmep->id); 289 4436 stephh Nfmep->Ccallcount = 290 4436 stephh stats_new_counter(nbuf, "calls to causes_test()", 1); 291 4436 stephh (void) sprintf(nbuf, "fme%d.Ecall", Nfmep->id); 292 4436 stephh Nfmep->Ecallcount = 293 4436 stephh stats_new_counter(nbuf, "calls to effects_test()", 1); 294 4436 stephh (void) sprintf(nbuf, "fme%d.Tcall", Nfmep->id); 295 4436 stephh Nfmep->Tcallcount = stats_new_counter(nbuf, "calls to triggered()", 1); 296 4436 stephh (void) sprintf(nbuf, "fme%d.Marrow", Nfmep->id); 297 4436 stephh Nfmep->Marrowcount = stats_new_counter(nbuf, 298 4436 stephh "arrows marked by mark_arrows()", 1); 299 4436 stephh (void) sprintf(nbuf, "fme%d.diags", Nfmep->id); 300 4436 stephh Nfmep->diags = stats_new_counter(nbuf, "suspect lists diagnosed", 0); 301 4436 stephh 302 4436 stephh Nfmep->peek = 1; 303 4436 stephh lut_walk(Nfmep->eventtree, (lut_cb)unset_needed_arrows, (void *)Nfmep); 304 4436 stephh lut_free(Usednames, NULL, NULL); 305 4436 stephh Usednames = NULL; 306 4436 stephh lut_walk(Nfmep->eventtree, (lut_cb)clear_arrows, (void *)Nfmep); 307 4436 stephh (void) hypothesise(Nfmep, Nfmep->e0, Nfmep->ull, &my_delay); 308 4436 stephh itree_prune(Nfmep->eventtree); 309 4436 stephh lut_walk(Nfmep->eventtree, (lut_cb)set_needed_arrows, (void *)Nfmep); 310 4436 stephh 311 4436 stephh stats_delete(Nfmep->Rcount); 312 4436 stephh stats_delete(Nfmep->Hcallcount); 313 4436 stephh stats_delete(Nfmep->Rcallcount); 314 4436 stephh stats_delete(Nfmep->Ccallcount); 315 4436 stephh stats_delete(Nfmep->Ecallcount); 316 4436 stephh stats_delete(Nfmep->Tcallcount); 317 4436 stephh stats_delete(Nfmep->Marrowcount); 318 4436 stephh stats_delete(Nfmep->diags); 319 4436 stephh itree_free(Nfmep->eventtree); 320 4436 stephh lut_free(Nfmep->globals, globals_destructor, NULL); 321 4436 stephh FREE(Nfmep); 322 4436 stephh } 323 4436 stephh 324 0 stevel static struct fme * 325 4436 stephh newfme(const char *e0class, const struct ipath *e0ipp, fmd_hdl_t *hdl, 326 4436 stephh fmd_case_t *fmcase) 327 0 stevel { 328 0 stevel struct cfgdata *cfgdata; 329 4436 stephh int init_size; 330 4436 stephh extern int alloc_total(); 331 0 stevel 332 4436 stephh init_size = alloc_total(); 333 4436 stephh out(O_ALTFP|O_STAMP, "start config_snapshot using %d bytes", init_size); 334 7748 Tarik cfgdata = config_snapshot(); 335 4436 stephh platform_save_config(hdl, fmcase); 336 4436 stephh out(O_ALTFP|O_STAMP, "config_snapshot added %d bytes", 337 4436 stephh alloc_total() - init_size); 338 0 stevel 339 0 stevel Nfmep = alloc_fme(); 340 0 stevel 341 0 stevel Nfmep->id = Nextid++; 342 5204 stephh Nfmep->config = cfgdata->cooked; 343 5204 stephh config_free(cfgdata); 344 0 stevel Nfmep->posted_suspects = 0; 345 0 stevel Nfmep->uniqobs = 0; 346 0 stevel Nfmep->state = FME_NOTHING; 347 0 stevel Nfmep->pull = 0ULL; 348 814 jrutt Nfmep->overflow = 0; 349 0 stevel 350 4436 stephh Nfmep->fmcase = fmcase; 351 4436 stephh Nfmep->hdl = hdl; 352 0 stevel 353 5204 stephh if ((Nfmep->eventtree = itree_create(Nfmep->config)) == NULL) { 354 0 stevel out(O_ALTFP, "newfme: NULL instance tree"); 355 7748 Tarik Undiag_reason = UD_VAL_INSTFAIL; 356 5204 stephh structconfig_free(Nfmep->config); 357 4436 stephh destroy_fme_bufs(Nfmep); 358 0 stevel FREE(Nfmep); 359 0 stevel Nfmep = NULL; 360 0 stevel return (NULL); 361 0 stevel } 362 0 stevel 363 0 stevel itree_ptree(O_ALTFP|O_VERB2, Nfmep->eventtree); 364 0 stevel 365 0 stevel if ((Nfmep->e0 = 366 0 stevel itree_lookup(Nfmep->eventtree, e0class, e0ipp)) == NULL) { 367 0 stevel out(O_ALTFP, "newfme: e0 not in instance tree"); 368 7748 Tarik Undiag_reason = UD_VAL_BADEVENTI; 369 0 stevel itree_free(Nfmep->eventtree); 370 5204 stephh structconfig_free(Nfmep->config); 371 4436 stephh destroy_fme_bufs(Nfmep); 372 0 stevel FREE(Nfmep); 373 0 stevel Nfmep = NULL; 374 0 stevel return (NULL); 375 0 stevel } 376 0 stevel 377 0 stevel return (fme_ready(Nfmep)); 378 0 stevel } 379 0 stevel 380 0 stevel void 381 0 stevel fme_fini(void) 382 0 stevel { 383 0 stevel struct fme *sfp, *fp; 384 0 stevel struct case_list *ucasep, *nextcasep; 385 0 stevel 386 0 stevel ucasep = Undiagablecaselist; 387 0 stevel while (ucasep != NULL) { 388 0 stevel nextcasep = ucasep->next; 389 0 stevel FREE(ucasep); 390 0 stevel ucasep = nextcasep; 391 0 stevel } 392 0 stevel Undiagablecaselist = NULL; 393 0 stevel 394 0 stevel /* clean up closed fmes */ 395 0 stevel fp = ClosedFMEs; 396 0 stevel while (fp != NULL) { 397 0 stevel sfp = fp->next; 398 0 stevel destroy_fme(fp); 399 0 stevel fp = sfp; 400 0 stevel } 401 0 stevel ClosedFMEs = NULL; 402 0 stevel 403 0 stevel fp = FMElist; 404 0 stevel while (fp != NULL) { 405 0 stevel sfp = fp->next; 406 0 stevel destroy_fme(fp); 407 0 stevel fp = sfp; 408 0 stevel } 409 0 stevel FMElist = EFMElist = NULL; 410 0 stevel 411 0 stevel /* if we were in the middle of creating an fme, free it now */ 412 0 stevel if (Nfmep) { 413 0 stevel destroy_fme(Nfmep); 414 0 stevel Nfmep = NULL; 415 0 stevel } 416 0 stevel } 417 0 stevel 418 0 stevel /* 419 0 stevel * Allocated space for a buffer name. 20 bytes allows for 420 0 stevel * a ridiculous 9,999,999 unique observations. 421 0 stevel */ 422 0 stevel #define OBBUFNMSZ 20 423 0 stevel 424 0 stevel /* 425 0 stevel * serialize_observation 426 0 stevel * 427 0 stevel * Create a recoverable version of the current observation 428 0 stevel * (f->ecurrent). We keep a serialized version of each unique 429 0 stevel * observation in order that we may resume correctly the fme in the 430 0 stevel * correct state if eft or fmd crashes and we're restarted. 431 0 stevel */ 432 0 stevel static void 433 0 stevel serialize_observation(struct fme *fp, const char *cls, const struct ipath *ipp) 434 0 stevel { 435 0 stevel size_t pkdlen; 436 0 stevel char tmpbuf[OBBUFNMSZ]; 437 0 stevel char *pkd = NULL; 438 0 stevel char *estr; 439 0 stevel 440 0 stevel (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", fp->uniqobs); 441 0 stevel estr = ipath2str(cls, ipp); 442 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, strlen(estr) + 1); 443 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)estr, 444 0 stevel strlen(estr) + 1); 445 0 stevel FREE(estr); 446 0 stevel 447 0 stevel if (fp->ecurrent != NULL && fp->ecurrent->nvp != NULL) { 448 0 stevel (void) snprintf(tmpbuf, 449 0 stevel OBBUFNMSZ, "observed%d.nvp", fp->uniqobs); 450 0 stevel if (nvlist_xpack(fp->ecurrent->nvp, 451 0 stevel &pkd, &pkdlen, NV_ENCODE_XDR, &Eft_nv_hdl) != 0) 452 0 stevel out(O_DIE|O_SYS, "pack of observed nvl failed"); 453 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, pkdlen); 454 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)pkd, pkdlen); 455 0 stevel FREE(pkd); 456 0 stevel } 457 0 stevel 458 0 stevel fp->uniqobs++; 459 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 460 0 stevel sizeof (fp->uniqobs)); 461 0 stevel } 462 0 stevel 463 0 stevel /* 464 0 stevel * init_fme_bufs -- We keep several bits of state about an fme for 465 0 stevel * use if eft or fmd crashes and we're restarted. 466 0 stevel */ 467 0 stevel static void 468 0 stevel init_fme_bufs(struct fme *fp) 469 0 stevel { 470 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_PULL, sizeof (fp->pull)); 471 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_PULL, (void *)&fp->pull, 472 0 stevel sizeof (fp->pull)); 473 0 stevel 474 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_ID, sizeof (fp->id)); 475 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_ID, (void *)&fp->id, 476 0 stevel sizeof (fp->id)); 477 0 stevel 478 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_NOBS, sizeof (fp->uniqobs)); 479 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 480 0 stevel sizeof (fp->uniqobs)); 481 0 stevel 482 0 stevel fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_POSTD, 483 0 stevel sizeof (fp->posted_suspects)); 484 0 stevel fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_POSTD, 485 0 stevel (void *)&fp->posted_suspects, sizeof (fp->posted_suspects)); 486 0 stevel } 487 0 stevel 488 0 stevel static void 489 0 stevel destroy_fme_bufs(struct fme *fp) 490 0 stevel { 491 0 stevel char tmpbuf[OBBUFNMSZ]; 492 0 stevel int o; 493 0 stevel 494 4436 stephh platform_restore_config(fp->hdl, fp->fmcase); 495 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFGLEN); 496 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFG); 497 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_PULL); 498 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_ID); 499 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_POSTD); 500 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_NOBS); 501 0 stevel 502 0 stevel for (o = 0; o < fp->uniqobs; o++) { 503 0 stevel (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", o); 504 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 505 0 stevel (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", o); 506 0 stevel fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 507 0 stevel } 508 0 stevel } 509 0 stevel 510 0 stevel /* 511 0 stevel * reconstitute_observations -- convert a case's serialized observations 512 0 stevel * back into struct events. Returns zero if all observations are 513 0 stevel * successfully reconstituted. 514 0 stevel */ 515 0 stevel static int 516 0 stevel reconstitute_observations(struct fme *fmep) 517 0 stevel { 518 0 stevel struct event *ep; 519 0 stevel struct node *epnamenp = NULL; 520 0 stevel size_t pkdlen; 521 0 stevel char *pkd = NULL; 522 0 stevel char *tmpbuf = alloca(OBBUFNMSZ); 523 0 stevel char *sepptr; 524 0 stevel char *estr; 525 0 stevel int ocnt; 526 0 stevel int elen; 527 0 stevel 528 0 stevel for (ocnt = 0; ocnt < fmep->uniqobs; ocnt++) { 529 0 stevel (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", ocnt); 530 0 stevel elen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 531 0 stevel if (elen == 0) { 532 0 stevel out(O_ALTFP, 533 0 stevel "reconstitute_observation: no %s buffer found.", 534 0 stevel tmpbuf); 535 7748 Tarik Undiag_reason = UD_VAL_MISSINGOBS; 536 0 stevel break; 537 0 stevel } 538 0 stevel 539 0 stevel estr = MALLOC(elen); 540 0 stevel fmd_buf_read(fmep->hdl, fmep->fmcase, tmpbuf, estr, elen); 541 0 stevel sepptr = strchr(estr, '@'); 542 0 stevel if (sepptr == NULL) { 543 0 stevel out(O_ALTFP, 544 0 stevel "reconstitute_observation: %s: " 545 0 stevel "missing @ separator in %s.", 546 0 stevel tmpbuf, estr); 547 7748 Tarik Undiag_reason = UD_VAL_MISSINGPATH; 548 0 stevel FREE(estr); 549 0 stevel break; 550 0 stevel } 551 0 stevel 552 0 stevel *sepptr = '\0'; 553 0 stevel if ((epnamenp = pathstring2epnamenp(sepptr + 1)) == NULL) { 554 0 stevel out(O_ALTFP, 555 0 stevel "reconstitute_observation: %s: " 556 0 stevel "trouble converting path string \"%s\" " 557 0 stevel "to internal representation.", 558 0 stevel tmpbuf, sepptr + 1); 559 7748 Tarik Undiag_reason = UD_VAL_MISSINGPATH; 560 0 stevel FREE(estr); 561 0 stevel break; 562 0 stevel } 563 0 stevel 564 0 stevel /* construct the event */ 565 0 stevel ep = itree_lookup(fmep->eventtree, 566 0 stevel stable(estr), ipath(epnamenp)); 567 0 stevel if (ep == NULL) { 568 0 stevel out(O_ALTFP, 569 0 stevel "reconstitute_observation: %s: " 570 0 stevel "lookup of \"%s\" in itree failed.", 571 0 stevel tmpbuf, ipath2str(estr, ipath(epnamenp))); 572 7748 Tarik Undiag_reason = UD_VAL_BADOBS; 573 0 stevel tree_free(epnamenp); 574 0 stevel FREE(estr); 575 0 stevel break; 576 0 stevel } 577 0 stevel tree_free(epnamenp); 578 0 stevel 579 0 stevel /* 580 0 stevel * We may or may not have a saved nvlist for the observation 581 0 stevel */ 582 0 stevel (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", ocnt); 583 0 stevel pkdlen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 584 0 stevel if (pkdlen != 0) { 585 0 stevel pkd = MALLOC(pkdlen); 586 0 stevel fmd_buf_read(fmep->hdl, 587 0 stevel fmep->fmcase, tmpbuf, pkd, pkdlen); 588 1414 cindi ASSERT(ep->nvp == NULL); 589 0 stevel if (nvlist_xunpack(pkd, 590 0 stevel pkdlen, &ep->nvp, &Eft_nv_hdl) != 0) 591 0 stevel out(O_DIE|O_SYS, "pack of observed nvl failed"); 592 0 stevel FREE(pkd); 593 0 stevel } 594 0 stevel 595 0 stevel if (ocnt == 0) 596 0 stevel fmep->e0 = ep; 597 0 stevel 598 0 stevel FREE(estr); 599 0 stevel fmep->ecurrent = ep; 600 0 stevel ep->count++; 601 0 stevel 602 0 stevel /* link it into list of observations seen */ 603 0 stevel ep->observations = fmep->observations; 604 0 stevel fmep->observations = ep; 605 0 stevel } 606 0 stevel 607 0 stevel if (ocnt == fmep->uniqobs) { 608 0 stevel (void) fme_ready(fmep); 609 0 stevel return (0); 610 0 stevel } 611 0 stevel 612 0 stevel return (1); 613 0 stevel } 614 0 stevel 615 0 stevel /* 616 0 stevel * restart_fme -- called during eft initialization. Reconstitutes 617 0 stevel * an in-progress fme. 618 0 stevel */ 619 0 stevel void 620 0 stevel fme_restart(fmd_hdl_t *hdl, fmd_case_t *inprogress) 621 0 stevel { 622 0 stevel nvlist_t *defect; 623 0 stevel struct case_list *bad; 624 0 stevel struct fme *fmep; 625 5204 stephh struct cfgdata *cfgdata; 626 0 stevel size_t rawsz; 627 4436 stephh struct event *ep; 628 4436 stephh char *tmpbuf = alloca(OBBUFNMSZ); 629 4436 stephh char *sepptr; 630 4436 stephh char *estr; 631 4436 stephh int elen; 632 4436 stephh struct node *epnamenp = NULL; 633 4436 stephh int init_size; 634 4436 stephh extern int alloc_total(); 635 4436 stephh 636 4436 stephh /* 637 4436 stephh * ignore solved or closed cases 638 4436 stephh */ 639 4436 stephh if (fmd_case_solved(hdl, inprogress) || 640 4436 stephh fmd_case_closed(hdl, inprogress)) 641 4436 stephh return; 642 0 stevel 643 0 stevel fmep = alloc_fme(); 644 0 stevel fmep->fmcase = inprogress; 645 0 stevel fmep->hdl = hdl; 646 0 stevel 647 2914 stephh if (fmd_buf_size(hdl, inprogress, WOBUF_POSTD) == 0) { 648 2914 stephh out(O_ALTFP, "restart_fme: no saved posted status"); 649 7748 Tarik Undiag_reason = UD_VAL_MISSINGINFO; 650 2914 stephh goto badcase; 651 2914 stephh } else { 652 2914 stephh fmd_buf_read(hdl, inprogress, WOBUF_POSTD, 653 2914 stephh (void *)&fmep->posted_suspects, 654 2914 stephh sizeof (fmep->posted_suspects)); 655 2914 stephh } 656 2914 stephh 657 4436 stephh if (fmd_buf_size(hdl, inprogress, WOBUF_ID) == 0) { 658 4436 stephh out(O_ALTFP, "restart_fme: no saved id"); 659 7748 Tarik Undiag_reason = UD_VAL_MISSINGINFO; 660 2914 stephh goto badcase; 661 4436 stephh } else { 662 4436 stephh fmd_buf_read(hdl, inprogress, WOBUF_ID, (void *)&fmep->id, 663 4436 stephh sizeof (fmep->id)); 664 4436 stephh } 665 4436 stephh if (Nextid <= fmep->id) 666 4436 stephh Nextid = fmep->id + 1; 667 4436 stephh 668 4436 stephh out(O_ALTFP, "Replay FME %d", fmep->id); 669 2914 stephh 670 0 stevel if (fmd_buf_size(hdl, inprogress, WOBUF_CFGLEN) != sizeof (size_t)) { 671 0 stevel out(O_ALTFP, "restart_fme: No config data"); 672 7748 Tarik Undiag_reason = UD_VAL_MISSINGINFO; 673 0 stevel goto badcase; 674 0 stevel } 675 0 stevel fmd_buf_read(hdl, inprogress, WOBUF_CFGLEN, (void *)&rawsz, 676 0 stevel sizeof (size_t)); 677 0 stevel 678 0 stevel if ((fmep->e0r = fmd_case_getprincipal(hdl, inprogress)) == NULL) { 679 0 stevel out(O_ALTFP, "restart_fme: No event zero"); 680 7748 Tarik Undiag_reason = UD_VAL_MISSINGZERO; 681 0 stevel goto badcase; 682 0 stevel } 683 0 stevel 684 4436 stephh if (fmd_buf_size(hdl, inprogress, WOBUF_PULL) == 0) { 685 4436 stephh out(O_ALTFP, "restart_fme: no saved wait time"); 686 7748 Tarik Undiag_reason = UD_VAL_MISSINGINFO; 687 4436 stephh goto badcase; 688 4436 stephh } else { 689 4436 stephh fmd_buf_read(hdl, inprogress, WOBUF_PULL, (void *)&fmep->pull, 690 4436 stephh sizeof (fmep->pull)); 691 4436 stephh } 692 4436 stephh 693 4436 stephh if (fmd_buf_size(hdl, inprogress, WOBUF_NOBS) == 0) { 694 4436 stephh out(O_ALTFP, "restart_fme: no count of observations"); 695 7748 Tarik Undiag_reason = UD_VAL_MISSINGINFO; 696 4436 stephh goto badcase; 697 4436 stephh } else { 698 4436 stephh fmd_buf_read(hdl, inprogress, WOBUF_NOBS, 699 4436 stephh (void *)&fmep->uniqobs, sizeof (fmep->uniqobs)); 700 4436 stephh } 701 4436 stephh 702 4436 stephh (void) snprintf(tmpbuf, OBBUFNMSZ, "observed0"); 703 4436 stephh elen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 704 4436 stephh if (elen == 0) { 705 4436 stephh out(O_ALTFP, "reconstitute_observation: no %s buffer found.", 706 4436 stephh tmpbuf); 707 7748 Tarik Undiag_reason = UD_VAL_MISSINGOBS; 708 4436 stephh goto badcase; 709 4436 stephh } 710 4436 stephh estr = MALLOC(elen); 711 4436 stephh fmd_buf_read(fmep->hdl, fmep->fmcase, tmpbuf, estr, elen); 712 4436 stephh sepptr = strchr(estr, '@'); 713 4436 stephh if (sepptr == NULL) { 714 4436 stephh out(O_ALTFP, "reconstitute_observation: %s: " 715 4436 stephh "missing @ separator in %s.", 716 4436 stephh tmpbuf, estr); 717 7748 Tarik Undiag_reason = UD_VAL_MISSINGPATH; 718 4436 stephh FREE(estr); 719 4436 stephh goto badcase; 720 4436 stephh } 721 4436 stephh *sepptr = '\0'; 722 4436 stephh if ((epnamenp = pathstring2epnamenp(sepptr + 1)) == NULL) { 723 4436 stephh out(O_ALTFP, "reconstitute_observation: %s: " 724 4436 stephh "trouble converting path string \"%s\" " 725 4436 stephh "to internal representation.", tmpbuf, sepptr + 1); 726 7748 Tarik Undiag_reason = UD_VAL_MISSINGPATH; 727 4436 stephh FREE(estr); 728 4436 stephh goto badcase; 729 4436 stephh } 730 4436 stephh prune_propagations(stable(estr), ipath(epnamenp)); 731 4436 stephh tree_free(epnamenp); 732 4436 stephh FREE(estr); 733 4436 stephh 734 4436 stephh init_size = alloc_total(); 735 4436 stephh out(O_ALTFP|O_STAMP, "start config_restore using %d bytes", init_size); 736 0 stevel cfgdata = MALLOC(sizeof (struct cfgdata)); 737 0 stevel cfgdata->cooked = NULL; 738 0 stevel cfgdata->devcache = NULL; 739 6640 cth cfgdata->devidcache = NULL; 740 0 stevel cfgdata->cpucache = NULL; 741 4436 stephh cfgdata->raw_refcnt = 1; 742 0 stevel 743 0 stevel if (rawsz > 0) { 744 0 stevel if (fmd_buf_size(hdl, inprogress, WOBUF_CFG) != rawsz) { 745 0 stevel out(O_ALTFP, "restart_fme: Config data size mismatch"); 746 7748 Tarik Undiag_reason = UD_VAL_CFGMISMATCH; 747 0 stevel goto badcase; 748 0 stevel } 749 0 stevel cfgdata->begin = MALLOC(rawsz); 750 0 stevel cfgdata->end = cfgdata->nextfree = cfgdata->begin + rawsz; 751 0 stevel fmd_buf_read(hdl, 752 0 stevel inprogress, WOBUF_CFG, cfgdata->begin, rawsz); 753 0 stevel } else { 754 0 stevel cfgdata->begin = cfgdata->end = cfgdata->nextfree = NULL; 755 0 stevel } 756 0 stevel 757 0 stevel config_cook(cfgdata); 758 5204 stephh fmep->config = cfgdata->cooked; 759 5204 stephh config_free(cfgdata); 760 4436 stephh out(O_ALTFP|O_STAMP, "config_restore added %d bytes", 761 4436 stephh alloc_total() - init_size); 762 4436 stephh 763 5204 stephh if ((fmep->eventtree = itree_create(fmep->config)) == NULL) { 764 0 stevel /* case not properly saved or irretrievable */ 765 0 stevel out(O_ALTFP, "restart_fme: NULL instance tree"); 766 7748 Tarik Undiag_reason = UD_VAL_INSTFAIL; 767 0 stevel goto badcase; 768 0 stevel } 769 0 stevel 770 0 stevel itree_ptree(O_ALTFP|O_VERB2, fmep->eventtree); 771 0 stevel 772 0 stevel if (reconstitute_observations(fmep) != 0) 773 0 stevel goto badcase; 774 4436 stephh 775 4436 stephh out(O_ALTFP|O_NONL, "FME %d replay observations: ", fmep->id); 776 4436 stephh for (ep = fmep->observations; ep; ep = ep->observations) { 777 4436 stephh out(O_ALTFP|O_NONL, " "); 778 4436 stephh itree_pevent_brief(O_ALTFP|O_NONL, ep); 779 4436 stephh } 780 4436 stephh out(O_ALTFP, NULL); 781 0 stevel 782 814 jrutt Open_fme_count++; 783 814 jrutt 784 0 stevel /* give the diagnosis algorithm a shot at the new FME state */ 785 2914 stephh fme_eval(fmep, fmep->e0r); 786 0 stevel return; 787 0 stevel 788 0 stevel badcase: 789 0 stevel if (fmep->eventtree != NULL) 790 0 stevel itree_free(fmep->eventtree); 791 5204 stephh if (fmep->config) 792 5204 stephh structconfig_free(fmep->config); 793 0 stevel destroy_fme_bufs(fmep); 794 0 stevel FREE(fmep); 795 0 stevel 796 0 stevel /* 797 0 stevel * Since we're unable to restart the case, add it to the undiagable 798 0 stevel * list and solve and close it as appropriate. 799 0 stevel */ 800 0 stevel bad = MALLOC(sizeof (struct case_list)); 801 0 stevel bad->next = NULL; 802 0 stevel 803 0 stevel if (Undiagablecaselist != NULL) 804 0 stevel bad->next = Undiagablecaselist; 805 0 stevel Undiagablecaselist = bad; 806 0 stevel bad->fmcase = inprogress; 807 0 stevel 808 2914 stephh out(O_ALTFP|O_NONL, "[case %s (unable to restart), ", 809 0 stevel fmd_case_uuid(hdl, bad->fmcase)); 810 0 stevel 811 0 stevel if (fmd_case_solved(hdl, bad->fmcase)) { 812 2914 stephh out(O_ALTFP|O_NONL, "already solved, "); 813 0 stevel } else { 814 2914 stephh out(O_ALTFP|O_NONL, "solving, "); 815 7748 Tarik defect = fmd_nvl_create_fault(hdl, 816 7748 Tarik undiag_2defect_str(Undiag_reason), 100, NULL, NULL, NULL); 817 7748 Tarik (void) nvlist_add_string(defect, UNDIAG_REASON, 818 7748 Tarik undiag_2reason_str(Undiag_reason)); 819 0 stevel fmd_case_add_suspect(hdl, bad->fmcase, defect); 820 0 stevel fmd_case_solve(hdl, bad->fmcase); 821 7748 Tarik Undiag_reason = UD_VAL_UNKNOWN; 822 0 stevel } 823 0 stevel 824 0 stevel if (fmd_case_closed(hdl, bad->fmcase)) { 825 0 stevel out(O_ALTFP, "already closed ]"); 826 0 stevel } else { 827 0 stevel out(O_ALTFP, "closing ]"); 828 0 stevel fmd_case_close(hdl, bad->fmcase); 829 0 stevel } 830 0 stevel } 831 0 stevel 832 1414 cindi /*ARGSUSED*/ 833 1414 cindi static void 834 1414 cindi globals_destructor(void *left, void *right, void *arg) 835 1414 cindi { 836 1414 cindi struct evalue *evp = (struct evalue *)right; 837 1414 cindi if (evp->t == NODEPTR) 838 1717 wesolows tree_free((struct node *)(uintptr_t)evp->v); 839 6277 cy152378 evp->v = (uintptr_t)NULL; 840 1414 cindi FREE(evp); 841 1414 cindi } 842 1414 cindi 843 0 stevel void 844 0 stevel destroy_fme(struct fme *f) 845 0 stevel { 846 0 stevel stats_delete(f->Rcount); 847 0 stevel stats_delete(f->Hcallcount); 848 0 stevel stats_delete(f->Rcallcount); 849 0 stevel stats_delete(f->Ccallcount); 850 0 stevel stats_delete(f->Ecallcount); 851 0 stevel stats_delete(f->Tcallcount); 852 0 stevel stats_delete(f->Marrowcount); 853 0 stevel stats_delete(f->diags); 854 0 stevel 855 2914 stephh if (f->eventtree != NULL) 856 2914 stephh itree_free(f->eventtree); 857 5204 stephh if (f->config) 858 5204 stephh structconfig_free(f->config); 859 1414 cindi lut_free(f->globals, globals_destructor, NULL); 860 0 stevel FREE(f); 861 0 stevel } 862 0 stevel 863 0 stevel static const char * 864 0 stevel fme_state2str(enum fme_state s) 865 0 stevel { 866 0 stevel switch (s) { 867 0 stevel case FME_NOTHING: return ("NOTHING"); 868 0 stevel case FME_WAIT: return ("WAIT"); 869 0 stevel case FME_CREDIBLE: return ("CREDIBLE"); 870 0 stevel case FME_DISPROVED: return ("DISPROVED"); 871 1414 cindi case FME_DEFERRED: return ("DEFERRED"); 872 0 stevel default: return ("UNKNOWN"); 873 0 stevel } 874 0 stevel } 875 0 stevel 876 0 stevel static int 877 0 stevel is_problem(enum nametype t) 878 0 stevel { 879 0 stevel return (t == N_FAULT || t == N_DEFECT || t == N_UPSET); 880 0 stevel } 881 0 stevel 882 0 stevel static int 883 0 stevel is_defect(enum nametype t) 884 0 stevel { 885 0 stevel return (t == N_DEFECT); 886 0 stevel } 887 0 stevel 888 0 stevel static int 889 0 stevel is_upset(enum nametype t) 890 0 stevel { 891 0 stevel return (t == N_UPSET); 892 0 stevel } 893 0 stevel 894 0 stevel static void 895 0 stevel fme_print(int flags, struct fme *fmep) 896 0 stevel { 897 0 stevel struct event *ep; 898 0 stevel 899 0 stevel out(flags, "Fault Management Exercise %d", fmep->id); 900 0 stevel out(flags, "\t State: %s", fme_state2str(fmep->state)); 901 0 stevel out(flags|O_NONL, "\t Start time: "); 902 0 stevel ptree_timeval(flags|O_NONL, &fmep->ull); 903 0 stevel out(flags, NULL); 904 0 stevel if (fmep->wull) { 905 0 stevel out(flags|O_NONL, "\t Wait time: "); 906 0 stevel ptree_timeval(flags|O_NONL, &fmep->wull); 907 0 stevel out(flags, NULL); 908 0 stevel } 909 0 stevel out(flags|O_NONL, "\t E0: "); 910 0 stevel if (fmep->e0) 911 0 stevel itree_pevent_brief(flags|O_NONL, fmep->e0); 912 0 stevel else 913 0 stevel out(flags|O_NONL, "NULL"); 914 0 stevel out(flags, NULL); 915 0 stevel out(flags|O_NONL, "\tObservations:"); 916 0 stevel for (ep = fmep->observations; ep; ep = ep->observations) { 917 0 stevel out(flags|O_NONL, " "); 918 0 stevel itree_pevent_brief(flags|O_NONL, ep); 919 0 stevel } 920 0 stevel out(flags, NULL); 921 0 stevel out(flags|O_NONL, "\tSuspect list:"); 922 0 stevel for (ep = fmep->suspects; ep; ep = ep->suspects) { 923 0 stevel out(flags|O_NONL, " "); 924 0 stevel itree_pevent_brief(flags|O_NONL, ep); 925 0 stevel } 926 0 stevel out(flags, NULL); 927 2914 stephh if (fmep->eventtree != NULL) { 928 2914 stephh out(flags|O_VERB2, "\t Tree:"); 929 2914 stephh itree_ptree(flags|O_VERB2, fmep->eventtree); 930 2914 stephh } 931 0 stevel } 932 0 stevel 933 0 stevel static struct node * 934 0 stevel pathstring2epnamenp(char *path) 935 0 stevel { 936 0 stevel char *sep = "/"; 937 0 stevel struct node *ret; 938 0 stevel char *ptr; 939 0 stevel 940 0 stevel if ((ptr = strtok(path, sep)) == NULL) 941 0 stevel out(O_DIE, "pathstring2epnamenp: invalid empty class"); 942 0 stevel 943 0 stevel ret = tree_iname(stable(ptr), NULL, 0); 944 0 stevel 945 0 stevel while ((ptr = strtok(NULL, sep)) != NULL) 946 0 stevel ret = tree_name_append(ret, 947 0 stevel tree_iname(stable(ptr), NULL, 0)); 948 0 stevel 949 0 stevel return (ret); 950 0 stevel } 951 0 stevel 952 0 stevel /* 953 0 stevel * for a given upset sp, increment the corresponding SERD engine. if the 954 0 stevel * SERD engine trips, return the ename and ipp of the resulting ereport. 955 0 stevel * returns true if engine tripped and *enamep and *ippp were filled in. 956 0 stevel */ 957 0 stevel static int 958 1414 cindi serd_eval(struct fme *fmep, fmd_hdl_t *hdl, fmd_event_t *ffep, 959 1414 cindi fmd_case_t *fmcase, struct event *sp, const char **enamep, 960 1414 cindi const struct ipath **ippp) 961 0 stevel { 962 0 stevel struct node *serdinst; 963 0 stevel char *serdname; 964 7337 Scott char *serdresource; 965 8245 Stephen char *serdclass; 966 1414 cindi struct node *nid; 967 4436 stephh struct serd_entry *newentp; 968 7337 Scott int i, serdn = -1, serdincrement = 1, len = 0; 969 8245 Stephen char *serdsuffix = NULL, *serdt = NULL; 970 7197 stephh struct evalue *ep; 971 0 stevel 972 0 stevel ASSERT(sp->t == N_UPSET); 973 0 stevel ASSERT(ffep != NULL); 974 0 stevel 975 7197 stephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 976 7197 stephh (void *)"n", (lut_cmp)strcmp)) != NULL) { 977 7197 stephh ASSERT(ep->t == UINT64); 978 7197 stephh serdn = (int)ep->v; 979 7197 stephh } 980 7197 stephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 981 7197 stephh (void *)"t", (lut_cmp)strcmp)) != NULL) { 982 7197 stephh ASSERT(ep->t == STRING); 983 7197 stephh serdt = (char *)(uintptr_t)ep->v; 984 7197 stephh } 985 7197 stephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 986 7197 stephh (void *)"suffix", (lut_cmp)strcmp)) != NULL) { 987 7197 stephh ASSERT(ep->t == STRING); 988 7197 stephh serdsuffix = (char *)(uintptr_t)ep->v; 989 7197 stephh } 990 7197 stephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 991 7197 stephh (void *)"increment", (lut_cmp)strcmp)) != NULL) { 992 7197 stephh ASSERT(ep->t == UINT64); 993 7197 stephh serdincrement = (int)ep->v; 994 7197 stephh } 995 7197 stephh 996 0 stevel /* 997 0 stevel * obtain instanced SERD engine from the upset sp. from this 998 0 stevel * derive serdname, the string used to identify the SERD engine. 999 0 stevel */ 1000 0 stevel serdinst = eventprop_lookup(sp, L_engine); 1001 0 stevel 1002 0 stevel if (serdinst == NULL) 1003 7197 stephh return (-1); 1004 0 stevel 1005 8245 Stephen len = strlen(serdinst->u.stmt.np->u.event.ename->u.name.s) + 1; 1006 8245 Stephen if (serdsuffix != NULL) 1007 8245 Stephen len += strlen(serdsuffix); 1008 8245 Stephen serdclass = MALLOC(len); 1009 8245 Stephen if (serdsuffix != NULL) 1010 8245 Stephen (void) snprintf(serdclass, len, "%s%s", 1011 8245 Stephen serdinst->u.stmt.np->u.event.ename->u.name.s, serdsuffix); 1012 8245 Stephen else 1013 8245 Stephen (void) snprintf(serdclass, len, "%s", 1014 8245 Stephen serdinst->u.stmt.np->u.event.ename->u.name.s); 1015 7337 Scott serdresource = ipath2str(NULL, 1016 0 stevel ipath(serdinst->u.stmt.np->u.event.epname)); 1017 8245 Stephen len += strlen(serdresource) + 1; 1018 8245 Stephen serdname = MALLOC(len); 1019 8245 Stephen (void) snprintf(serdname, len, "%s@%s", serdclass, serdresource); 1020 7337 Scott FREE(serdresource); 1021 1414 cindi 1022 1414 cindi /* handle serd engine "id" property, if there is one */ 1023 1414 cindi if ((nid = 1024 1414 cindi lut_lookup(serdinst->u.stmt.lutp, (void *)L_id, NULL)) != NULL) { 1025 1414 cindi struct evalue *gval; 1026 1414 cindi char suffixbuf[200]; 1027 1414 cindi char *suffix; 1028 1414 cindi char *nserdname; 1029 1414 cindi size_t nname; 1030 1414 cindi 1031 1414 cindi out(O_ALTFP|O_NONL, "serd \"%s\" id: ", serdname); 1032 1414 cindi ptree_name_iter(O_ALTFP|O_NONL, nid); 1033 1414 cindi 1034 1414 cindi ASSERTinfo(nid->t == T_GLOBID, ptree_nodetype2str(nid->t)); 1035 1414 cindi 1036 1414 cindi if ((gval = lut_lookup(fmep->globals, 1037 1414 cindi (void *)nid->u.globid.s, NULL)) == NULL) { 1038 1414 cindi out(O_ALTFP, " undefined"); 1039 1414 cindi } else if (gval->t == UINT64) { 1040 1414 cindi out(O_ALTFP, " %llu", gval->v); 1041 1414 cindi (void) sprintf(suffixbuf, "%llu", gval->v); 1042 1414 cindi suffix = suffixbuf; 1043 1414 cindi } else { 1044 1717 wesolows out(O_ALTFP, " \"%s\"", (char *)(uintptr_t)gval->v); 1045 1717 wesolows suffix = (char *)(uintptr_t)gval->v; 1046 1414 cindi } 1047 1414 cindi 1048 1414 cindi nname = strlen(serdname) + strlen(suffix) + 2; 1049 1414 cindi nserdname = MALLOC(nname); 1050 1414 cindi (void) snprintf(nserdname, nname, "%s:%s", serdname, suffix); 1051 1414 cindi FREE(serdname); 1052 1414 cindi serdname = nserdname; 1053 1414 cindi } 1054 7197 stephh 1055 7197 stephh /* 1056 7197 stephh * if the engine is empty, and we have an override for n/t then 1057 7197 stephh * destroy and recreate it. 1058 7197 stephh */ 1059 7197 stephh if ((serdn != -1 || serdt != NULL) && fmd_serd_exists(hdl, serdname) && 1060 7197 stephh fmd_serd_empty(hdl, serdname)) 1061 7197 stephh fmd_serd_destroy(hdl, serdname); 1062 0 stevel 1063 0 stevel if (!fmd_serd_exists(hdl, serdname)) { 1064 0 stevel struct node *nN, *nT; 1065 5204 stephh const char *s; 1066 5204 stephh struct node *nodep; 1067 5204 stephh struct config *cp; 1068 5204 stephh char *path; 1069 5204 stephh uint_t nval; 1070 5204 stephh hrtime_t tval; 1071 5204 stephh int i; 1072 5204 stephh char *ptr; 1073 5204 stephh int got_n_override = 0, got_t_override = 0; 1074 0 stevel 1075 0 stevel /* no SERD engine yet, so create it */ 1076 5204 stephh nodep = serdinst->u.stmt.np->u.event.epname; 1077 5204 stephh path = ipath2str(NULL, ipath(nodep)); 1078 5204 stephh cp = config_lookup(fmep->config, path, 0); 1079 5204 stephh FREE((void *)path); 1080 0 stevel 1081 5204 stephh /* 1082 5204 stephh * We allow serd paramaters to be overridden, either from 1083 5204 stephh * eft.conf file values (if Serd_Override is set) or from 1084 5204 stephh * driver properties (for "serd.io.device" engines). 1085 5204 stephh */ 1086 5204 stephh if (Serd_Override != NULL) { 1087 5204 stephh char *save_ptr, *ptr1, *ptr2, *ptr3; 1088 5204 stephh ptr3 = save_ptr = STRDUP(Serd_Override); 1089 5204 stephh while (*ptr3 != '\0') { 1090 5204 stephh ptr1 = strchr(ptr3, ','); 1091 5204 stephh *ptr1 = '\0'; 1092 8245 Stephen if (strcmp(ptr3, serdclass) == 0) { 1093 5204 stephh ptr2 = strchr(ptr1 + 1, ','); 1094 5204 stephh *ptr2 = '\0'; 1095 5204 stephh nval = atoi(ptr1 + 1); 1096 5204 stephh out(O_ALTFP, "serd override %s_n %d", 1097 8245 Stephen serdclass, nval); 1098 5204 stephh ptr3 = strchr(ptr2 + 1, ' '); 1099 5204 stephh if (ptr3) 1100 5204 stephh *ptr3 = '\0'; 1101 5204 stephh ptr = STRDUP(ptr2 + 1); 1102 5204 stephh out(O_ALTFP, "serd override %s_t %s", 1103 8245 Stephen serdclass, ptr); 1104 5204 stephh got_n_override = 1; 1105 5204 stephh got_t_override = 1; 1106 5204 stephh break; 1107 5204 stephh } else { 1108 5204 stephh ptr2 = strchr(ptr1 + 1, ','); 1109 5204 stephh ptr3 = strchr(ptr2 + 1, ' '); 1110 5204 stephh if (ptr3 == NULL) 1111 5204 stephh break; 1112 5204 stephh } 1113 5204 stephh ptr3++; 1114 5204 stephh } 1115 5204 stephh FREE(save_ptr); 1116 5204 stephh } 1117 0 stevel 1118 5204 stephh if (cp && got_n_override == 0) { 1119 5204 stephh /* 1120 8245 Stephen * convert serd engine class into property name 1121 8245 Stephen */ 1122 8245 Stephen char *prop_name = MALLOC(strlen(serdclass) + 3); 1123 8245 Stephen for (i = 0; i < strlen(serdclass); i++) { 1124 8245 Stephen if (serdclass[i] == '.') 1125 8245 Stephen prop_name[i] = '_'; 1126 5204 stephh else 1127 8245 Stephen prop_name[i] = serdclass[i]; 1128 8245 Stephen } 1129 8245 Stephen prop_name[i++] = '_'; 1130 8245 Stephen prop_name[i++] = 'n'; 1131 8245 Stephen prop_name[i] = '\0'; 1132 8245 Stephen if (s = config_getprop(cp, prop_name)) { 1133 5204 stephh nval = atoi(s); 1134 8245 Stephen out(O_ALTFP, "serd override %s_n %s", 1135 8245 Stephen serdclass, s); 1136 5204 stephh got_n_override = 1; 1137 5204 stephh } 1138 8245 Stephen prop_name[i - 1] = 't'; 1139 8245 Stephen if (s = config_getprop(cp, prop_name)) { 1140 5204 stephh ptr = STRDUP(s); 1141 8245 Stephen out(O_ALTFP, "serd override %s_t %s", 1142 8245 Stephen serdclass, s); 1143 5204 stephh got_t_override = 1; 1144 5204 stephh } 1145 8245 Stephen FREE(prop_name); 1146 5204 stephh } 1147 5204 stephh 1148 7197 stephh if (serdn != -1 && got_n_override == 0) { 1149 7197 stephh nval = serdn; 1150 8245 Stephen out(O_ALTFP, "serd override %s_n %d", serdclass, serdn); 1151 7197 stephh got_n_override = 1; 1152 7197 stephh } 1153 7197 stephh if (serdt != NULL && got_t_override == 0) { 1154 7197 stephh ptr = STRDUP(serdt); 1155 8245 Stephen out(O_ALTFP, "serd override %s_t %s", serdclass, serdt); 1156 7197 stephh got_t_override = 1; 1157 7197 stephh } 1158 7197 stephh 1159 5204 stephh if (!got_n_override) { 1160 5204 stephh nN = lut_lookup(serdinst->u.stmt.lutp, (void *)L_N, 1161 5204 stephh NULL); 1162 5204 stephh ASSERT(nN->t == T_NUM); 1163 5204 stephh nval = (uint_t)nN->u.ull; 1164 5204 stephh } 1165 5204 stephh if (!got_t_override) { 1166 5204 stephh nT = lut_lookup(serdinst->u.stmt.lutp, (void *)L_T, 1167 5204 stephh NULL); 1168 5204 stephh ASSERT(nT->t == T_TIMEVAL); 1169 5204 stephh tval = (hrtime_t)nT->u.ull; 1170 5204 stephh } else { 1171 5204 stephh const unsigned long long *ullp; 1172 5204 stephh const char *suffix; 1173 5204 stephh int len; 1174 5204 stephh 1175 5204 stephh len = strspn(ptr, "0123456789"); 1176 5204 stephh suffix = stable(&ptr[len]); 1177 5204 stephh ullp = (unsigned long long *)lut_lookup(Timesuffixlut, 1178 5204 stephh (void *)suffix, NULL); 1179 5204 stephh ptr[len] = '\0'; 1180 7197 stephh tval = strtoull(ptr, NULL, 0) * (ullp ? *ullp : 1ll); 1181 5204 stephh FREE(ptr); 1182 5204 stephh } 1183 5204 stephh fmd_serd_create(hdl, serdname, nval, tval); 1184 4436 stephh } 1185 4436 stephh 1186 4436 stephh newentp = MALLOC(sizeof (*newentp)); 1187 8245 Stephen newentp->ename = stable(serdclass); 1188 8245 Stephen FREE(serdclass); 1189 4436 stephh newentp->ipath = ipath(serdinst->u.stmt.np->u.event.epname); 1190 4436 stephh newentp->hdl = hdl; 1191 4436 stephh if (lut_lookup(SerdEngines, newentp, (lut_cmp)serd_cmp) == NULL) { 1192 4436 stephh SerdEngines = lut_add(SerdEngines, (void *)newentp, 1193 5204 stephh (void *)newentp, (lut_cmp)serd_cmp); 1194 4436 stephh Serd_need_save = 1; 1195 4436 stephh serd_save(); 1196 4436 stephh } else { 1197 4436 stephh FREE(newentp); 1198 0 stevel } 1199 0 stevel 1200 0 stevel 1201 0 stevel /* 1202 0 stevel * increment SERD engine. if engine fires, reset serd 1203 7197 stephh * engine and return trip_strcode if required. 1204 7197 stephh */ 1205 7197 stephh for (i = 0; i < serdincrement; i++) { 1206 7197 stephh if (fmd_serd_record(hdl, serdname, ffep)) { 1207 7197 stephh fmd_case_add_serd(hdl, fmcase, serdname); 1208 7197 stephh fmd_serd_reset(hdl, serdname); 1209 7197 stephh 1210 7197 stephh if (ippp) { 1211 7197 stephh struct node *tripinst = 1212 7197 stephh lut_lookup(serdinst->u.stmt.lutp, 1213 7197 stephh (void *)L_trip, NULL); 1214 7197 stephh ASSERT(tripinst != NULL); 1215 7197 stephh *enamep = tripinst->u.event.ename->u.name.s; 1216 7197 stephh *ippp = ipath(tripinst->u.event.epname); 1217 7197 stephh out(O_ALTFP|O_NONL, 1218 7197 stephh "[engine fired: %s, sending: ", serdname); 1219 7197 stephh ipath_print(O_ALTFP|O_NONL, *enamep, *ippp); 1220 7197 stephh out(O_ALTFP, "]"); 1221 7197 stephh } else { 1222 7197 stephh out(O_ALTFP, "[engine fired: %s, no trip]", 1223 7197 stephh serdname); 1224 7197 stephh } 1225 7197 stephh FREE(serdname); 1226 7197 stephh return (1); 1227 7197 stephh } 1228 0 stevel } 1229 0 stevel 1230 0 stevel FREE(serdname); 1231 0 stevel return (0); 1232 0 stevel } 1233 0 stevel 1234 0 stevel /* 1235 0 stevel * search a suspect list for upsets. feed each upset to serd_eval() and 1236 0 stevel * build up tripped[], an array of ereports produced by the firing of 1237 0 stevel * any SERD engines. then feed each ereport back into 1238 0 stevel * fme_receive_report(). 1239 0 stevel * 1240 0 stevel * returns ntrip, the number of these ereports produced. 1241 0 stevel */ 1242 0 stevel static int 1243 0 stevel upsets_eval(struct fme *fmep, fmd_event_t *ffep) 1244 0 stevel { 1245 0 stevel /* we build an array of tripped ereports that we send ourselves */ 1246 0 stevel struct { 1247 0 stevel const char *ename; 1248 0 stevel const struct ipath *ipp; 1249 0 stevel } *tripped; 1250 0 stevel struct event *sp; 1251 0 stevel int ntrip, nupset, i; 1252 0 stevel 1253 0 stevel /* 1254 0 stevel * count the number of upsets to determine the upper limit on 1255 0 stevel * expected trip ereport strings. remember that one upset can 1256 0 stevel * lead to at most one ereport. 1257 0 stevel */ 1258 0 stevel nupset = 0; 1259 0 stevel for (sp = fmep->suspects; sp; sp = sp->suspects) { 1260 0 stevel if (sp->t == N_UPSET) 1261 0 stevel nupset++; 1262 0 stevel } 1263 0 stevel 1264 0 stevel if (nupset == 0) 1265 0 stevel return (0); 1266 0 stevel 1267 0 stevel /* 1268 0 stevel * get to this point if we have upsets and expect some trip 1269 0 stevel * ereports 1270 0 stevel */ 1271 0 stevel tripped = alloca(sizeof (*tripped) * nupset); 1272 0 stevel bzero((void *)tripped, sizeof (*tripped) * nupset); 1273 0 stevel 1274 0 stevel ntrip = 0; 1275 0 stevel for (sp = fmep->suspects; sp; sp = sp->suspects) 1276 186 db35262 if (sp->t == N_UPSET && 1277 1414 cindi serd_eval(fmep, fmep->hdl, ffep, fmep->fmcase, sp, 1278 7197 stephh &tripped[ntrip].ename, &tripped[ntrip].ipp) == 1) 1279 0 stevel ntrip++; 1280 0 stevel 1281 5947 stephh for (i = 0; i < ntrip; i++) { 1282 5947 stephh struct event *ep, *nep; 1283 5947 stephh struct fme *nfmep; 1284 5947 stephh fmd_case_t *fmcase; 1285 5947 stephh const struct ipath *ipp; 1286 5947 stephh const char *eventstring; 1287 5947 stephh int prev_verbose; 1288 5947 stephh unsigned long long my_delay = TIMEVAL_EVENTUALLY; 1289 5947 stephh enum fme_state state; 1290 5947 stephh 1291 5947 stephh /* 1292 5947 stephh * First try and evaluate a case with the trip ereport plus 1293 5947 stephh * all the other ereports that cause the trip. If that fails 1294 5947 stephh * to evaluate then try again with just this ereport on its own. 1295 5947 stephh */ 1296 5947 stephh out(O_ALTFP|O_NONL, "fme_receive_report_serd: "); 1297 5947 stephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, tripped[i].ipp); 1298 5947 stephh out(O_ALTFP|O_STAMP, NULL); 1299 5947 stephh ep = fmep->e0; 1300 5947 stephh eventstring = ep->enode->u.event.ename->u.name.s; 1301 5947 stephh ipp = ep->ipp; 1302 5947 stephh prune_propagations(eventstring, ipp); 1303 5947 stephh 1304 5947 stephh /* 1305 5947 stephh * create a duplicate fme and case 1306 5947 stephh */ 1307 5947 stephh fmcase = fmd_case_open(fmep->hdl, NULL); 1308 5947 stephh out(O_ALTFP|O_NONL, "duplicate fme for event ["); 1309 5947 stephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1310 5947 stephh out(O_ALTFP, " ]"); 1311 5947 stephh if ((nfmep = newfme(eventstring, ipp, fmep->hdl, 1312 5947 stephh fmcase)) == NULL) { 1313 5947 stephh out(O_ALTFP|O_NONL, "["); 1314 5947 stephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1315 5947 stephh out(O_ALTFP, " CANNOT DIAGNOSE]"); 1316 5947 stephh publish_undiagnosable(fmep->hdl, ffep, fmcase); 1317 5947 stephh continue; 1318 5947 stephh } 1319 5947 stephh Open_fme_count++; 1320 5947 stephh nfmep->pull = fmep->pull; 1321 5947 stephh init_fme_bufs(nfmep); 1322 5947 stephh out(O_ALTFP|O_NONL, "["); 1323 5947 stephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1324 5947 stephh out(O_ALTFP, " created FME%d, case %s]", nfmep->id, 1325 5947 stephh fmd_case_uuid(nfmep->hdl, nfmep->fmcase)); 1326 5947 stephh if (ffep) { 1327 5947 stephh fmd_case_setprincipal(nfmep->hdl, nfmep->fmcase, ffep); 1328 7197 stephh fmd_case_add_ereport(nfmep->hdl, nfmep->fmcase, ffep); 1329 5947 stephh nfmep->e0r = ffep; 1330 5947 stephh } 1331 5947 stephh 1332 5947 stephh /* 1333 5947 stephh * add the original ereports 1334 5947 stephh */ 1335 5947 stephh for (ep = fmep->observations; ep; ep = ep->observations) { 1336 5947 stephh eventstring = ep->enode->u.event.ename->u.name.s; 1337 5947 stephh ipp = ep->ipp; 1338 5947 stephh out(O_ALTFP|O_NONL, "adding event ["); 1339 5947 stephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1340 5947 stephh out(O_ALTFP, " ]"); 1341 5947 stephh nep = itree_lookup(nfmep->eventtree, eventstring, ipp); 1342 5947 stephh if (nep->count++ == 0) { 1343 5947 stephh nep->observations = nfmep->observations; 1344 5947 stephh nfmep->observations = nep; 1345 5947 stephh serialize_observation(nfmep, eventstring, ipp); 1346 5947 stephh nep->nvp = evnv_dupnvl(ep->nvp); 1347 5947 stephh } 1348 7197 stephh if (ep->ffep && ep->ffep != ffep) 1349 5947 stephh fmd_case_add_ereport(nfmep->hdl, nfmep->fmcase, 1350 7197 stephh ep->ffep); 1351 5947 stephh stats_counter_bump(nfmep->Rcount); 1352 5947 stephh } 1353 5947 stephh 1354 5947 stephh /* 1355 5947 stephh * add the serd trigger ereport 1356 5947 stephh */ 1357 5947 stephh if ((ep = itree_lookup(nfmep->eventtree, tripped[i].ename, 1358 5947 stephh tripped[i].ipp)) == NULL) { 1359 5947 stephh /* 1360 5947 stephh * The trigger ereport is not in the instance tree. It 1361 5947 stephh * was presumably removed by prune_propagations() as 1362 5947 stephh * this combination of events is not present in the 1363 5947 stephh * rules. 1364 5947 stephh */ 1365 5947 stephh out(O_ALTFP, "upsets_eval: e0 not in instance tree"); 1366 7748 Tarik Undiag_reason = UD_VAL_BADEVENTI; 1367 5947 stephh goto retry_lone_ereport; 1368 5947 stephh } 1369 5947 stephh out(O_ALTFP|O_NONL, "adding event ["); 1370 5947 stephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, tripped[i].ipp); 1371 5947 stephh out(O_ALTFP, " ]"); 1372 5947 stephh nfmep->ecurrent = ep; 1373 5947 stephh ep->nvp = NULL; 1374 5947 stephh ep->count = 1; 1375 5947 stephh ep->observations = nfmep->observations; 1376 5947 stephh nfmep->observations = ep; 1377 5947 stephh 1378 5947 stephh /* 1379 5947 stephh * just peek first. 1380 5947 stephh */ 1381 5947 stephh nfmep->peek = 1; 1382 5947 stephh prev_verbose = Verbose; 1383 5947 stephh if (Debug == 0) 1384 5947 stephh Verbose = 0; 1385 5947 stephh lut_walk(nfmep->eventtree, (lut_cb)clear_arrows, (void *)nfmep); 1386 5947 stephh state = hypothesise(nfmep, nfmep->e0, nfmep->ull, &my_delay); 1387 5947 stephh nfmep->peek = 0; 1388 5947 stephh Verbose = prev_verbose; 1389 5947 stephh if (state == FME_DISPROVED) { 1390 5947 stephh out(O_ALTFP, "upsets_eval: hypothesis disproved"); 1391 7748 Tarik Undiag_reason = UD_VAL_UNSOLVD; 1392 5947 stephh retry_lone_ereport: 1393 5947 stephh /* 1394 5947 stephh * However the trigger ereport on its own might be 1395 5947 stephh * diagnosable, so check for that. Undo the new fme 1396 5947 stephh * and case we just created and call fme_receive_report. 1397 5947 stephh */ 1398 5947 stephh out(O_ALTFP|O_NONL, "["); 1399 5947 stephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, 1400 5947 stephh tripped[i].ipp); 1401 5947 stephh out(O_ALTFP, " retrying with just trigger ereport]"); 1402 5947 stephh itree_free(nfmep->eventtree); 1403 5947 stephh nfmep->eventtree = NULL; 1404 5947 stephh structconfig_free(nfmep->config); 1405 5947 stephh nfmep->config = NULL; 1406 5947 stephh destroy_fme_bufs(nfmep); 1407 5947 stephh fmd_case_close(nfmep->hdl, nfmep->fmcase); 1408 5947 stephh fme_receive_report(fmep->hdl, ffep, 1409 5947 stephh tripped[i].ename, tripped[i].ipp, NULL); 1410 5947 stephh continue; 1411 5947 stephh } 1412 5947 stephh 1413 5947 stephh /* 1414 5947 stephh * and evaluate 1415 5947 stephh */ 1416 5947 stephh serialize_observation(nfmep, tripped[i].ename, tripped[i].ipp); 1417 5947 stephh fme_eval(nfmep, ffep); 1418 5947 stephh } 1419 0 stevel 1420 0 stevel return (ntrip); 1421 0 stevel } 1422 0 stevel 1423 0 stevel /* 1424 0 stevel * fme_receive_external_report -- call when an external ereport comes in 1425 0 stevel * 1426 0 stevel * this routine just converts the relevant information from the ereport 1427 0 stevel * into a format used internally and passes it on to fme_receive_report(). 1428 0 stevel */ 1429 0 stevel void 1430 0 stevel fme_receive_external_report(fmd_hdl_t *hdl, fmd_event_t *ffep, nvlist_t *nvl, 1431 6640 cth const char *class) 1432 6640 cth { 1433 6640 cth struct node *epnamenp; 1434 6640 cth fmd_case_t *fmcase; 1435 6640 cth const struct ipath *ipp; 1436 6640 cth 1437 6640 cth class = stable(class); 1438 6640 cth 1439 6640 cth /* Get the component path from the ereport */ 1440 6640 cth epnamenp = platform_getpath(nvl); 1441 6640 cth 1442 6640 cth /* See if we ended up without a path. */ 1443 0 stevel if (epnamenp == NULL) { 1444 6640 cth /* See if class permits silent discard on unknown component. */ 1445 6640 cth if (lut_lookup(Ereportenames_discard, (void *)class, NULL)) { 1446 6640 cth out(O_ALTFP|O_VERB2, "Unable to map \"%s\" ereport " 1447 6640 cth "to component path, but silent discard allowed.", 1448 6640 cth class); 1449 6640 cth } else { 1450 6640 cth /* 1451 6640 cth * XFILE: Failure to find a component is bad unless 1452 6640 cth * 'discard_if_config_unknown=1' was specified in the 1453 6640 cth * ereport definition. Indicate undiagnosable. 1454 6640 cth */ 1455 6640 cth out(O_ALTFP, "XFILE: Unable to map \"%s\" ereport " 1456 6640 cth "to component path.", class); 1457 7748 Tarik Undiag_reason = UD_VAL_NOPATH; 1458 6640 cth fmcase = fmd_case_open(hdl, NULL); 1459 6640 cth publish_undiagnosable(hdl, ffep, fmcase); 1460 6640 cth } 1461 0 stevel return; 1462 0 stevel } 1463 0 stevel 1464 0 stevel ipp = ipath(epnamenp); 1465 0 stevel tree_free(epnamenp); 1466 6640 cth fme_receive_report(hdl, ffep, class, ipp, nvl); 1467 2120 gavinm } 1468 2120 gavinm 1469 2120 gavinm /*ARGSUSED*/ 1470 2120 gavinm void 1471 2120 gavinm fme_receive_repair_list(fmd_hdl_t *hdl, fmd_event_t *ffep, nvlist_t *nvl, 1472 2120 gavinm const char *eventstring) 1473 2120 gavinm { 1474 2120 gavinm char *uuid; 1475 2120 gavinm nvlist_t **nva; 1476 2120 gavinm uint_t nvc; 1477 2120 gavinm const struct ipath *ipp; 1478 2120 gavinm 1479 2120 gavinm if (nvlist_lookup_string(nvl, FM_SUSPECT_UUID, &uuid) != 0 || 1480 2120 gavinm nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 1481 2120 gavinm &nva, &nvc) != 0) { 1482 2120 gavinm out(O_ALTFP, "No uuid or fault list for list.repaired event"); 1483 2120 gavinm return; 1484 2120 gavinm } 1485 2120 gavinm 1486 2120 gavinm out(O_ALTFP, "Processing list.repaired from case %s", uuid); 1487 2120 gavinm 1488 2120 gavinm while (nvc-- != 0) { 1489 2120 gavinm /* 1490 4436 stephh * Reset any istat or serd engine associated with this path. 1491 2120 gavinm */ 1492 2120 gavinm char *path; 1493 2120 gavinm 1494 2120 gavinm if ((ipp = platform_fault2ipath(*nva++)) == NULL) 1495 2120 gavinm continue; 1496 2120 gavinm 1497 2120 gavinm path = ipath2str(NULL, ipp); 1498 2120 gavinm out(O_ALTFP, "fme_receive_repair_list: resetting state for %s", 1499 2120 gavinm path); 1500 2120 gavinm FREE(path); 1501 2120 gavinm 1502 2120 gavinm lut_walk(Istats, (lut_cb)istat_counter_reset_cb, (void *)ipp); 1503 2120 gavinm istat_save(); 1504 2120 gavinm 1505 4436 stephh lut_walk(SerdEngines, (lut_cb)serd_reset_cb, (void *)ipp); 1506 4436 stephh serd_save(); 1507 2120 gavinm } 1508 0 stevel } 1509 0 stevel 1510 5204 stephh /*ARGSUSED*/ 1511 5204 stephh void 1512 5204 stephh fme_receive_topology_change(void) 1513 5204 stephh { 1514 5204 stephh lut_walk(Istats, (lut_cb)istat_counter_topo_chg_cb, NULL); 1515 5204 stephh istat_save(); 1516 5204 stephh 1517 5204 stephh lut_walk(SerdEngines, (lut_cb)serd_topo_chg_cb, NULL); 1518 5204 stephh serd_save(); 1519 5204 stephh } 1520 5204 stephh 1521 1414 cindi static int mark_arrows(struct fme *fmep, struct event *ep, int mark, 1522 1865 dilpreet unsigned long long at_latest_by, unsigned long long *pdelay, int keep); 1523 1414 cindi 1524 1414 cindi /* ARGSUSED */ 1525 1414 cindi static void 1526 1414 cindi clear_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 1527 1414 cindi { 1528 1414 cindi struct bubble *bp; 1529 1414 cindi struct arrowlist *ap; 1530 1414 cindi 1531 1414 cindi ep->cached_state = 0; 1532 1865 dilpreet ep->keep_in_tree = 0; 1533 1414 cindi for (bp = itree_next_bubble(ep, NULL); bp; 1534 1414 cindi bp = itree_next_bubble(ep, bp)) { 1535 1414 cindi if (bp->t != B_FROM) 1536 1414 cindi continue; 1537 1414 cindi bp->mark = 0; 1538 1414 cindi for (ap = itree_next_arrow(bp, NULL); ap; 1539 1414 cindi ap = itree_next_arrow(bp, ap)) 1540 1414 cindi ap->arrowp->mark = 0; 1541 1414 cindi } 1542 4436 stephh } 1543 4436 stephh 1544 4436 stephh static void 1545 0 stevel fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 1546 0 stevel const char *eventstring, const struct ipath *ipp, nvlist_t *nvl) 1547 0 stevel { 1548 0 stevel struct event *ep; 1549 0 stevel struct fme *fmep = NULL; 1550 814 jrutt struct fme *ofmep = NULL; 1551 814 jrutt struct fme *cfmep, *svfmep; 1552 0 stevel int matched = 0; 1553 814 jrutt nvlist_t *defect; 1554 4436 stephh fmd_case_t *fmcase; 1555 0 stevel 1556 0 stevel out(O_ALTFP|O_NONL, "fme_receive_report: "); 1557 0 stevel ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1558 0 stevel out(O_ALTFP|O_STAMP, NULL); 1559 0 stevel 1560 0 stevel /* decide which FME it goes to */ 1561 0 stevel for (fmep = FMElist; fmep; fmep = fmep->next) { 1562 0 stevel int prev_verbose; 1563 0 stevel unsigned long long my_delay = TIMEVAL_EVENTUALLY; 1564 0 stevel enum fme_state state; 1565 1414 cindi nvlist_t *pre_peek_nvp = NULL; 1566 814 jrutt 1567 814 jrutt if (fmep->overflow) { 1568 814 jrutt if (!(fmd_case_closed(fmep->hdl, fmep->fmcase))) 1569 814 jrutt ofmep = fmep; 1570 814 jrutt 1571 814 jrutt continue; 1572 814 jrutt } 1573 0 stevel 1574 2318 stephh /* 1575 2318 stephh * ignore solved or closed cases 1576 2318 stephh */ 1577 2318 stephh if (fmep->posted_suspects || 1578 2318 stephh fmd_case_solved(fmep->hdl, fmep->fmcase) || 1579 2318 stephh fmd_case_closed(fmep->hdl, fmep->fmcase)) 1580 2318 stephh continue; 1581 2318 stephh 1582 0 stevel /* look up event in event tree for this FME */ 1583 0 stevel if ((ep = itree_lookup(fmep->eventtree, 1584 0 stevel eventstring, ipp)) == NULL) 1585 0 stevel continue; 1586 0 stevel 1587 0 stevel /* note observation */ 1588 0 stevel fmep->ecurrent = ep; 1589 0 stevel if (ep->count++ == 0) { 1590 0 stevel /* link it into list of observations seen */ 1591 0 stevel ep->observations = fmep->observations; 1592 0 stevel fmep->observations = ep; 1593 0 stevel ep->nvp = evnv_dupnvl(nvl); 1594 1414 cindi } else { 1595 1414 cindi /* use new payload values for peek */ 1596 1414 cindi pre_peek_nvp = ep->nvp; 1597 1414 cindi ep->nvp = evnv_dupnvl(nvl); 1598 0 stevel } 1599 0 stevel 1600 0 stevel /* tell hypothesise() not to mess with suspect list */ 1601 0 stevel fmep->peek = 1; 1602 0 stevel 1603 0 stevel /* don't want this to be verbose (unless Debug is set) */ 1604 0 stevel prev_verbose = Verbose; 1605 0 stevel if (Debug == 0) 1606 0 stevel Verbose = 0; 1607 0 stevel 1608 1414 cindi lut_walk(fmep->eventtree, (lut_cb)clear_arrows, (void *)fmep); 1609 1414 cindi state = hypothesise(fmep, fmep->e0, fmep->ull, &my_delay); 1610 0 stevel 1611 0 stevel fmep->peek = 0; 1612 0 stevel 1613 0 stevel /* put verbose flag back */ 1614 0 stevel Verbose = prev_verbose; 1615 0 stevel 1616 0 stevel if (state != FME_DISPROVED) { 1617 0 stevel /* found an FME that explains the ereport */ 1618 0 stevel matched++; 1619 0 stevel out(O_ALTFP|O_NONL, "["); 1620 0 stevel ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1621 0 stevel out(O_ALTFP, " explained by FME%d]", fmep->id); 1622 1414 cindi 1623 1414 cindi if (pre_peek_nvp) 1624 1414 cindi nvlist_free(pre_peek_nvp); 1625 0 stevel 1626 0 stevel if (ep->count == 1) 1627 0 stevel serialize_observation(fmep, eventstring, ipp); 1628 0 stevel 1629 7197 stephh if (ffep) { 1630 0 stevel fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 1631 7197 stephh ep->ffep = ffep; 1632 7197 stephh } 1633 0 stevel 1634 0 stevel stats_counter_bump(fmep->Rcount); 1635 0 stevel 1636 0 stevel /* re-eval FME */ 1637 0 stevel fme_eval(fmep, ffep); 1638 0 stevel } else { 1639 0 stevel 1640 0 stevel /* not a match, undo noting of observation */ 1641 0 stevel fmep->ecurrent = NULL; 1642 0 stevel if (--ep->count == 0) { 1643 0 stevel /* unlink it from observations */ 1644 0 stevel fmep->observations = ep->observations; 1645 0 stevel ep->observations = NULL; 1646 0 stevel nvlist_free(ep->nvp); 1647 0 stevel ep->nvp = NULL; 1648 1414 cindi } else { 1649 1414 cindi nvlist_free(ep->nvp); 1650 1414 cindi ep->nvp = pre_peek_nvp; 1651 0 stevel } 1652 0 stevel } 1653 0 stevel } 1654 0 stevel 1655 0 stevel if (matched) 1656 0 stevel return; /* explained by at least one existing FME */ 1657 0 stevel 1658 0 stevel /* clean up closed fmes */ 1659 814 jrutt cfmep = ClosedFMEs; 1660 814 jrutt while (cfmep != NULL) { 1661 814 jrutt svfmep = cfmep->next; 1662 814 jrutt destroy_fme(cfmep); 1663 814 jrutt cfmep = svfmep; 1664 0 stevel } 1665 0 stevel ClosedFMEs = NULL; 1666 4436 stephh prune_propagations(eventstring, ipp); 1667 814 jrutt 1668 814 jrutt if (ofmep) { 1669 814 jrutt out(O_ALTFP|O_NONL, "["); 1670 814 jrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1671 814 jrutt out(O_ALTFP, " ADDING TO OVERFLOW FME]"); 1672 814 jrutt if (ffep) 1673 814 jrutt fmd_case_add_ereport(hdl, ofmep->fmcase, ffep); 1674 814 jrutt 1675 814 jrutt return; 1676 814 jrutt 1677 814 jrutt } else if (Max_fme && (Open_fme_count >= Max_fme)) { 1678 814 jrutt out(O_ALTFP|O_NONL, "["); 1679 814 jrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1680 814 jrutt out(O_ALTFP, " MAX OPEN FME REACHED]"); 1681 4436 stephh 1682 4436 stephh fmcase = fmd_case_open(hdl, NULL); 1683 4436 stephh 1684 814 jrutt /* Create overflow fme */ 1685 4436 stephh if ((fmep = newfme(eventstring, ipp, hdl, fmcase)) == NULL) { 1686 814 jrutt out(O_ALTFP|O_NONL, "["); 1687 814 jrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1688 814 jrutt out(O_ALTFP, " CANNOT OPEN OVERFLOW FME]"); 1689 4436 stephh publish_undiagnosable(hdl, ffep, fmcase); 1690 814 jrutt return; 1691 814 jrutt } 1692 814 jrutt 1693 814 jrutt Open_fme_count++; 1694 814 jrutt 1695 814 jrutt init_fme_bufs(fmep); 1696 814 jrutt fmep->overflow = B_TRUE; 1697 814 jrutt 1698 814 jrutt if (ffep) 1699 814 jrutt fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 1700 814 jrutt 1701 7748 Tarik Undiag_reason = UD_VAL_MAXFME; 1702 7748 Tarik defect = fmd_nvl_create_fault(hdl, 1703 7748 Tarik undiag_2defect_str(Undiag_reason), 100, NULL, NULL, NULL); 1704 7748 Tarik (void) nvlist_add_string(defect, UNDIAG_REASON, 1705 7748 Tarik undiag_2reason_str(Undiag_reason)); 1706 814 jrutt fmd_case_add_suspect(hdl, fmep->fmcase, defect); 1707 814 jrutt fmd_case_solve(hdl, fmep->fmcase); 1708 7748 Tarik Undiag_reason = UD_VAL_UNKNOWN; 1709 814 jrutt return; 1710 814 jrutt } 1711 0 stevel 1712 4436 stephh /* open a case */ 1713 4436 stephh fmcase = fmd_case_open(hdl, NULL); 1714 4436 stephh 1715 0 stevel /* start a new FME */ 1716 4436 stephh if ((fmep = newfme(eventstring, ipp, hdl, fmcase)) == NULL) { 1717 0 stevel out(O_ALTFP|O_NONL, "["); 1718 0 stevel ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1719 0 stevel out(O_ALTFP, " CANNOT DIAGNOSE]"); 1720 4436 stephh publish_undiagnosable(hdl, ffep, fmcase); 1721 0 stevel return; 1722 0 stevel } 1723 814 jrutt 1724 814 jrutt Open_fme_count++; 1725 0 stevel 1726 0 stevel init_fme_bufs(fmep); 1727 0 stevel 1728 0 stevel out(O_ALTFP|O_NONL, "["); 1729 0 stevel ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1730 0 stevel out(O_ALTFP, " created FME%d, case %s]", fmep->id, 1731 0 stevel fmd_case_uuid(hdl, fmep->fmcase)); 1732 0 stevel 1733 0 stevel ep = fmep->e0; 1734 0 stevel ASSERT(ep != NULL); 1735 0 stevel 1736 0 stevel /* note observation */ 1737 0 stevel fmep->ecurrent = ep; 1738 0 stevel if (ep->count++ == 0) { 1739 0 stevel /* link it into list of observations seen */ 1740 0 stevel ep->observations = fmep->observations; 1741 0 stevel fmep->observations = ep; 1742 0 stevel ep->nvp = evnv_dupnvl(nvl); 1743 0 stevel serialize_observation(fmep, eventstring, ipp); 1744 1414 cindi } else { 1745 1414 cindi /* new payload overrides any previous */ 1746 1414 cindi nvlist_free(ep->nvp); 1747 1414 cindi ep->nvp = evnv_dupnvl(nvl); 1748 0 stevel } 1749 0 stevel 1750 0 stevel stats_counter_bump(fmep->Rcount); 1751 0 stevel 1752 0 stevel if (ffep) { 1753 0 stevel fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 1754 0 stevel fmd_case_setprincipal(hdl, fmep->fmcase, ffep); 1755 0 stevel fmep->e0r = ffep; 1756 7197 stephh ep->ffep = ffep; 1757 0 stevel } 1758 0 stevel 1759 0 stevel /* give the diagnosis algorithm a shot at the new FME state */ 1760 0 stevel fme_eval(fmep, ffep); 1761 0 stevel } 1762 0 stevel 1763 0 stevel void 1764 0 stevel fme_status(int flags) 1765 0 stevel { 1766 0 stevel struct fme *fmep; 1767 0 stevel 1768 0 stevel if (FMElist == NULL) { 1769 0 stevel out(flags, "No fault management exercises underway."); 1770 0 stevel return; 1771 0 stevel } 1772 0 stevel 1773 0 stevel for (fmep = FMElist; fmep; fmep = fmep->next) 1774 0 stevel fme_print(flags, fmep); 1775 0 stevel } 1776 0 stevel 1777 0 stevel /* 1778 0 stevel * "indent" routines used mostly for nicely formatted debug output, but also 1779 0 stevel * for sanity checking for infinite recursion bugs. 1780 0 stevel */ 1781 0 stevel 1782 0 stevel #define MAX_INDENT 1024 1783 0 stevel static const char *indent_s[MAX_INDENT]; 1784 0 stevel static int current_indent; 1785 0 stevel 1786 0 stevel static void 1787 0 stevel indent_push(const char *s) 1788 0 stevel { 1789 0 stevel if (current_indent < MAX_INDENT) 1790 0 stevel indent_s[current_indent++] = s; 1791 0 stevel else 1792 0 stevel out(O_DIE, "unexpected recursion depth (%d)", current_indent); 1793 0 stevel } 1794 0 stevel 1795 0 stevel static void 1796 0 stevel indent_set(const char *s) 1797 0 stevel { 1798 0 stevel current_indent = 0; 1799 0 stevel indent_push(s); 1800 0 stevel } 1801 0 stevel 1802 0 stevel static void 1803 0 stevel indent_pop(void) 1804 0 stevel { 1805 0 stevel if (current_indent > 0) 1806 0 stevel current_indent--; 1807 0 stevel else 1808 0 stevel out(O_DIE, "recursion underflow"); 1809 0 stevel } 1810 0 stevel 1811 0 stevel static void 1812 0 stevel indent(void) 1813 0 stevel { 1814 0 stevel int i; 1815 0 stevel if (!Verbose) 1816 0 stevel return; 1817 0 stevel for (i = 0; i < current_indent; i++) 1818 0 stevel out(O_ALTFP|O_VERB|O_NONL, indent_s[i]); 1819 0 stevel } 1820 0 stevel 1821 0 stevel #define SLNEW 1 1822 0 stevel #define SLCHANGED 2 1823 0 stevel #define SLWAIT 3 1824 0 stevel #define SLDISPROVED 4 1825 0 stevel 1826 0 stevel static void 1827 0 stevel print_suspects(int circumstance, struct fme *fmep) 1828 0 stevel { 1829 0 stevel struct event *ep; 1830 0 stevel 1831 0 stevel out(O_ALTFP|O_NONL, "["); 1832 0 stevel if (circumstance == SLCHANGED) { 1833 0 stevel out(O_ALTFP|O_NONL, "FME%d diagnosis changed. state: %s, " 1834 0 stevel "suspect list:", fmep->id, fme_state2str(fmep->state)); 1835 0 stevel } else if (circumstance == SLWAIT) { 1836 4436 stephh out(O_ALTFP|O_NONL, "FME%d set wait timer %ld ", fmep->id, 1837 4436 stephh fmep->timer); 1838 0 stevel ptree_timeval(O_ALTFP|O_NONL, &fmep->wull); 1839 0 stevel } else if (circumstance == SLDISPROVED) { 1840 0 stevel out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS UNKNOWN", fmep->id); 1841 0 stevel } else { 1842 0 stevel out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS PRODUCED:", fmep->id); 1843 0 stevel } 1844 0 stevel 1845 0 stevel if (circumstance == SLWAIT || circumstance == SLDISPROVED) { 1846 0 stevel out(O_ALTFP, "]"); 1847 0 stevel return; 1848 0 stevel } 1849 0 stevel 1850 0 stevel for (ep = fmep->suspects; ep; ep = ep->suspects) { 1851 0 stevel out(O_ALTFP|O_NONL, " "); 1852 0 stevel itree_pevent_brief(O_ALTFP|O_NONL, ep); 1853 0 stevel } 1854 0 stevel out(O_ALTFP, "]"); 1855 0 stevel } 1856 0 stevel 1857 0 stevel static struct node * 1858 0 stevel eventprop_lookup(struct event *ep, const char *propname) 1859 0 stevel { 1860 0 stevel return (lut_lookup(ep->props, (void *)propname, NULL)); 1861 0 stevel } 1862 0 stevel 1863 0 stevel #define MAXDIGITIDX 23 1864 0 stevel static char numbuf[MAXDIGITIDX + 1]; 1865 0 stevel 1866 0 stevel static int 1867 0 stevel node2uint(struct node *n, uint_t *valp) 1868 0 stevel { 1869 0 stevel struct evalue value; 1870 0 stevel struct lut *globals = NULL; 1871 0 stevel 1872 0 stevel if (n == NULL) 1873 0 stevel return (1); 1874 0 stevel 1875 0 stevel /* 1876 0 stevel * check value.v since we are being asked to convert an unsigned 1877 0 stevel * long long int to an unsigned int 1878 0 stevel */ 1879 0 stevel if (! eval_expr(n, NULL, NULL, &globals, NULL, NULL, 0, &value) || 1880 0 stevel value.t != UINT64 || value.v > (1ULL << 32)) 1881 0 stevel return (1); 1882 0 stevel 1883 0 stevel *valp = (uint_t)value.v; 1884 0 stevel 1885 0 stevel return (0); 1886 0 stevel } 1887 0 stevel 1888 0 stevel static nvlist_t * 1889 0 stevel node2fmri(struct node *n) 1890 0 stevel { 1891 0 stevel nvlist_t **pa, *f, *p; 1892 0 stevel struct node *nc; 1893 0 stevel uint_t depth = 0; 1894 0 stevel char *numstr, *nullbyte; 1895 0 stevel char *failure; 1896 0 stevel int err, i; 1897 0 stevel 1898 0 stevel /* XXX do we need to be able to handle a non-T_NAME node? */ 1899 0 stevel if (n == NULL || n->t != T_NAME) 1900 0 stevel return (NULL); 1901 0 stevel 1902 0 stevel for (nc = n; nc != NULL; nc = nc->u.name.next) { 1903 0 stevel if (nc->u.name.child == NULL || nc->u.name.child->t != T_NUM) 1904 0 stevel break; 1905 0 stevel depth++; 1906 0 stevel } 1907 0 stevel 1908 0 stevel if (nc != NULL) { 1909 0 stevel /* We bailed early, something went wrong */ 1910 0 stevel return (NULL); 1911 0 stevel } 1912 0 stevel 1913 0 stevel if ((err = nvlist_xalloc(&f, NV_UNIQUE_NAME, &Eft_nv_hdl)) != 0) 1914 0 stevel out(O_DIE|O_SYS, "alloc of fmri nvl failed"); 1915 0 stevel pa = alloca(depth * sizeof (nvlist_t *)); 1916 0 stevel for (i = 0; i < depth; i++) 1917 0 stevel pa[i] = NULL; 1918 0 stevel 1919 0 stevel err = nvlist_add_string(f, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC); 1920 0 stevel err |= nvlist_add_uint8(f, FM_VERSION, FM_HC_SCHEME_VERSION); 1921 0 stevel err |= nvlist_add_string(f, FM_FMRI_HC_ROOT, ""); 1922 0 stevel err |= nvlist_add_uint32(f, FM_FMRI_HC_LIST_SZ, depth); 1923 0 stevel if (err != 0) { 1924 0 stevel failure = "basic construction of FMRI failed"; 1925 0 stevel goto boom; 1926 0 stevel } 1927 0 stevel 1928 0 stevel numbuf[MAXDIGITIDX] = '\0'; 1929 0 stevel nullbyte = &numbuf[MAXDIGITIDX]; 1930 0 stevel i = 0; 1931 0 stevel 1932 0 stevel for (nc = n; nc != NULL; nc = nc->u.name.next) { 1933 0 stevel err = nvlist_xalloc(&p, NV_UNIQUE_NAME, &Eft_nv_hdl); 1934 0 stevel if (err != 0) { 1935 0 stevel failure = "alloc of an hc-pair failed"; 1936 0 stevel goto boom; 1937 0 stevel } 1938 0 stevel err = nvlist_add_string(p, FM_FMRI_HC_NAME, nc->u.name.s); 1939 0 stevel numstr = ulltostr(nc->u.name.child->u.ull, nullbyte); 1940 0 stevel err |= nvlist_add_string(p, FM_FMRI_HC_ID, numstr); 1941 0 stevel if (err != 0) { 1942 0 stevel failure = "construction of an hc-pair failed"; 1943 0 stevel goto boom; 1944 0 stevel } 1945 0 stevel pa[i++] = p; 1946 0 stevel } 1947 0 stevel 1948 0 stevel err = nvlist_add_nvlist_array(f, FM_FMRI_HC_LIST, pa, depth); 1949 0 stevel if (err == 0) { 1950 0 stevel for (i = 0; i < depth; i++) 1951 0 stevel if (pa[i] != NULL) 1952 0 stevel nvlist_free(pa[i]); 1953 0 stevel return (f); 1954 0 stevel } 1955 0 stevel failure = "addition of hc-pair array to FMRI failed"; 1956 0 stevel 1957 0 stevel boom: 1958 0 stevel for (i = 0; i < depth; i++) 1959 0 stevel if (pa[i] != NULL) 1960 0 stevel nvlist_free(pa[i]); 1961 0 stevel nvlist_free(f); 1962 0 stevel out(O_DIE, "%s", failure); 1963 0 stevel /*NOTREACHED*/ 1964 1717 wesolows return (NULL); 1965 0 stevel } 1966 0 stevel 1967 5204 stephh /* an ipath cache entry is an array of these, with s==NULL at the end */ 1968 5204 stephh struct ipath { 1969 5204 stephh const char *s; /* component name (in stable) */ 1970 5204 stephh int i; /* instance number */ 1971 5204 stephh }; 1972 5204 stephh 1973 5204 stephh static nvlist_t * 1974 5204 stephh ipath2fmri(struct ipath *ipath) 1975 5204 stephh { 1976 5204 stephh nvlist_t **pa, *f, *p; 1977 5204 stephh uint_t depth = 0; 1978 5204 stephh char *numstr, *nullbyte; 1979 5204 stephh char *failure; 1980 5204 stephh int err, i; 1981 5204 stephh struct ipath *ipp; 1982 5204 stephh 1983 5204 stephh for (ipp = ipath; ipp->s != NULL; ipp++) 1984 5204 stephh depth++; 1985 5204 stephh 1986 5204 stephh if ((err = nvlist_xalloc(&f, NV_UNIQUE_NAME, &Eft_nv_hdl)) != 0) 1987 5204 stephh out(O_DIE|O_SYS, "alloc of fmri nvl failed"); 1988 5204 stephh pa = alloca(depth * sizeof (nvlist_t *)); 1989 5204 stephh for (i = 0; i < depth; i++) 1990 5204 stephh pa[i] = NULL; 1991 5204 stephh 1992 5204 stephh err = nvlist_add_string(f, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC); 1993 5204 stephh err |= nvlist_add_uint8(f, FM_VERSION, FM_HC_SCHEME_VERSION); 1994 5204 stephh err |= nvlist_add_string(f, FM_FMRI_HC_ROOT, ""); 1995 5204 stephh err |= nvlist_add_uint32(f, FM_FMRI_HC_LIST_SZ, depth); 1996 5204 stephh if (err != 0) { 1997 5204 stephh failure = "basic construction of FMRI failed"; 1998 5204 stephh goto boom; 1999 5204 stephh } 2000 5204 stephh 2001 5204 stephh numbuf[MAXDIGITIDX] = '\0'; 2002 5204 stephh nullbyte = &numbuf[MAXDIGITIDX]; 2003 5204 stephh i = 0; 2004 5204 stephh 2005 5204 stephh for (ipp = ipath; ipp->s != NULL; ipp++) { 2006 5204 stephh err = nvlist_xalloc(&p, NV_UNIQUE_NAME, &Eft_nv_hdl); 2007 5204 stephh if (err != 0) { 2008 5204 stephh failure = "alloc of an hc-pair failed"; 2009 5204 stephh goto boom; 2010 5204 stephh } 2011 5204 stephh err = nvlist_add_string(p, FM_FMRI_HC_NAME, ipp->s); 2012 5204 stephh numstr = ulltostr(ipp->i, nullbyte); 2013 5204 stephh err |= nvlist_add_string(p, FM_FMRI_HC_ID, numstr); 2014 5204 stephh if (err != 0) { 2015 5204 stephh failure = "construction of an hc-pair failed"; 2016 5204 stephh goto boom; 2017 5204 stephh } 2018 5204 stephh pa[i++] = p; 2019 5204 stephh } 2020 5204 stephh 2021 5204 stephh err = nvlist_add_nvlist_array(f, FM_FMRI_HC_LIST, pa, depth); 2022 5204 stephh if (err == 0) { 2023 5204 stephh for (i = 0; i < depth; i++) 2024 5204 stephh if (pa[i] != NULL) 2025 5204 stephh nvlist_free(pa[i]); 2026 5204 stephh return (f); 2027 5204 stephh } 2028 5204 stephh failure = "addition of hc-pair array to FMRI failed"; 2029 5204 stephh 2030 5204 stephh boom: 2031 5204 stephh for (i = 0; i < depth; i++) 2032 5204 stephh if (pa[i] != NULL) 2033 5204 stephh nvlist_free(pa[i]); 2034 5204 stephh nvlist_free(f); 2035 5204 stephh out(O_DIE, "%s", failure); 2036 5204 stephh /*NOTREACHED*/ 2037 5204 stephh return (NULL); 2038 5204 stephh } 2039 5204 stephh 2040 0 stevel static uint8_t 2041 0 stevel percentof(uint_t part, uint_t whole) 2042 0 stevel { 2043 0 stevel unsigned long long p = part * 1000; 2044 0 stevel 2045 0 stevel return ((p / whole / 10) + (((p / whole % 10) >= 5) ? 1 : 0)); 2046 0 stevel } 2047 0 stevel 2048 1717 wesolows struct rsl { 2049 0 stevel struct event *suspect; 2050 0 stevel nvlist_t *asru; 2051 0 stevel nvlist_t *fru; 2052 0 stevel nvlist_t *rsrc; 2053 0 stevel }; 2054 0 stevel 2055 7197 stephh static void publish_suspects(struct fme *fmep, struct rsl *srl); 2056 7197 stephh 2057 0 stevel /* 2058 0 stevel * rslfree -- free internal members of struct rsl not expected to be 2059 0 stevel * freed elsewhere. 2060 0 stevel */ 2061 0 stevel static void 2062 0 stevel rslfree(struct rsl *freeme) 2063 0 stevel { 2064 0 stevel if (freeme->asru != NULL) 2065 0 stevel nvlist_free(freeme->asru); 2066 0 stevel if (freeme->fru != NULL) 2067 0 stevel nvlist_free(freeme->fru); 2068 0 stevel if (freeme->rsrc != NULL && freeme->rsrc != freeme->asru) 2069 0 stevel nvlist_free(freeme->rsrc); 2070 0 stevel } 2071 0 stevel 2072 0 stevel /* 2073 0 stevel * rslcmp -- compare two rsl structures. Use the following 2074 0 stevel * comparisons to establish cardinality: 2075 0 stevel * 2076 0 stevel * 1. Name of the suspect's class. (simple strcmp) 2077 0 stevel * 2. Name of the suspect's ASRU. (trickier, since nvlist) 2078 0 stevel * 2079 0 stevel */ 2080 0 stevel static int 2081 0 stevel rslcmp(const void *a, const void *b) 2082 0 stevel { 2083 0 stevel struct rsl *r1 = (struct rsl *)a; 2084 0 stevel struct rsl *r2 = (struct rsl *)b; 2085 0 stevel int rv; 2086 0 stevel 2087 0 stevel rv = strcmp(r1->suspect->enode->u.event.ename->u.name.s, 2088 0 stevel r2->suspect->enode->u.event.ename->u.name.s); 2089 0 stevel if (rv != 0) 2090 0 stevel return (rv); 2091 0 stevel 2092 7197 stephh if (r1->rsrc == NULL && r2->rsrc == NULL) 2093 7197 stephh return (0); 2094 7197 stephh if (r1->rsrc == NULL) 2095 0 stevel return (-1); 2096 7197 stephh if (r2->rsrc == NULL) 2097 7197 stephh return (1); 2098 7197 stephh return (evnv_cmpnvl(r1->rsrc, r2->rsrc, 0)); 2099 0 stevel } 2100 0 stevel 2101 0 stevel /* 2102 0 stevel * get_resources -- for a given suspect, determine what ASRU, FRU and 2103 0 stevel * RSRC nvlists should be advertised in the final suspect list. 2104 0 stevel */ 2105 0 stevel void 2106 0 stevel get_resources(struct event *sp, struct rsl *rsrcs, struct config *croot) 2107 0 stevel { 2108 0 stevel struct node *asrudef, *frudef; 2109 0 stevel nvlist_t *asru, *fru; 2110 0 stevel nvlist_t *rsrc = NULL; 2111 0 stevel char *pathstr; 2112 0 stevel 2113 0 stevel /* 2114 0 stevel * First find any ASRU and/or FRU defined in the 2115 0 stevel * initial fault tree. 2116 0 stevel */ 2117 0 stevel asrudef = eventprop_lookup(sp, L_ASRU); 2118 0 stevel frudef = eventprop_lookup(sp, L_FRU); 2119 0 stevel 2120 0 stevel /* 2121 0 stevel * Create FMRIs based on those definitions 2122 0 stevel */ 2123 0 stevel asru = node2fmri(asrudef); 2124 0 stevel fru = node2fmri(frudef); 2125 0 stevel pathstr = ipath2str(NULL, sp->ipp); 2126 0 stevel 2127 0 stevel /* 2128 7197 stephh * Allow for platform translations of the FMRIs 2129 0 stevel */ 2130 0 stevel platform_units_translate(is_defect(sp->t), croot, &asru, &fru, &rsrc, 2131 0 stevel pathstr); 2132 0 stevel 2133 0 stevel FREE(pathstr); 2134 0 stevel rsrcs->suspect = sp; 2135 0 stevel rsrcs->asru = asru; 2136 0 stevel rsrcs->fru = fru; 2137 0 stevel rsrcs->rsrc = rsrc; 2138 0 stevel } 2139 0 stevel 2140 0 stevel /* 2141 0 stevel * trim_suspects -- prior to publishing, we may need to remove some 2142 0 stevel * suspects from the list. If we're auto-closing upsets, we don't 2143 0 stevel * want any of those in the published list. If the ASRUs for multiple 2144 0 stevel * defects resolve to the same ASRU (driver) we only want to publish 2145 0 stevel * that as a single suspect. 2146 0 stevel */ 2147 7197 stephh static int 2148 7197 stephh trim_suspects(struct fme *fmep, struct rsl *begin, struct rsl *begin2, 2149 8245 Stephen fmd_event_t *ffep) 2150 7197 stephh { 2151 7197 stephh struct event *ep; 2152 7197 stephh struct rsl *rp = begin; 2153 7197 stephh struct rsl *rp2 = begin2; 2154 7197 stephh int mess_zero_count = 0; 2155 7197 stephh int serd_rval; 2156 7197 stephh uint_t messval; 2157 7197 stephh 2158 7197 stephh /* remove any unwanted upsets and populate our array */ 2159 0 stevel for (ep = fmep->psuspects; ep; ep = ep->psuspects) { 2160 7197 stephh if (is_upset(ep->t)) 2161 7197 stephh continue; 2162 7197 stephh serd_rval = serd_eval(fmep, fmep->hdl, ffep, fmep->fmcase, ep, 2163 7197 stephh NULL, NULL); 2164 7197 stephh if (serd_rval == 0) 2165 7197 stephh continue; 2166 7197 stephh if (node2uint(eventprop_lookup(ep, L_message), 2167 7197 stephh &messval) == 0 && messval == 0) { 2168 7197 stephh get_resources(ep, rp2, fmep->config); 2169 7197 stephh rp2++; 2170 7197 stephh mess_zero_count++; 2171 7197 stephh } else { 2172 7197 stephh get_resources(ep, rp, fmep->config); 2173 7197 stephh rp++; 2174 7197 stephh fmep->nsuspects++; 2175 7197 stephh } 2176 7197 stephh } 2177 7197 stephh return (mess_zero_count); 2178 0 stevel } 2179 0 stevel 2180 1414 cindi /* 2181 1414 cindi * addpayloadprop -- add a payload prop to a problem 2182 1414 cindi */ 2183 1414 cindi static void 2184 1414 cindi addpayloadprop(const char *lhs, struct evalue *rhs, nvlist_t *fault) 2185 1414 cindi { 2186 7197 stephh nvlist_t *rsrc, *hcs; 2187 7197 stephh 2188 1414 cindi ASSERT(fault != NULL); 2189 1414 cindi ASSERT(lhs != NULL); 2190 1414 cindi ASSERT(rhs != NULL); 2191 7197 stephh 2192 7197 stephh if (nvlist_lookup_nvlist(fault, FM_FAULT_RESOURCE, &rsrc) != 0) 2193 7197 stephh out(O_DIE, "cannot add payloadprop \"%s\" to fault", lhs); 2194 7197 stephh 2195 7197 stephh if (nvlist_lookup_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, &hcs) != 0) { 2196 7197 stephh out(O_ALTFP|O_VERB2, "addpayloadprop: create hc_specific"); 2197 7197 stephh if (nvlist_xalloc(&hcs, NV_UNIQUE_NAME, &Eft_nv_hdl) != 0) 2198 7197 stephh out(O_DIE, 2199 7197 stephh "cannot add payloadprop \"%s\" to fault", lhs); 2200 7197 stephh if (nvlist_add_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, hcs) != 0) 2201 7197 stephh out(O_DIE, 2202 7197 stephh "cannot add payloadprop \"%s\" to fault", lhs); 2203 7197 stephh nvlist_free(hcs); 2204 7197 stephh if (nvlist_lookup_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, &hcs) != 0) 2205 7197 stephh out(O_DIE, 2206 7197 stephh "cannot add payloadprop \"%s\" to fault", lhs); 2207 7197 stephh } else 2208 7197 stephh out(O_ALTFP|O_VERB2, "addpayloadprop: reuse hc_specific"); 2209 1414 cindi 2210 1414 cindi if (rhs->t == UINT64) { 2211 1414 cindi out(O_ALTFP|O_VERB2, "addpayloadprop: %s=%llu", lhs, rhs->v); 2212 1414 cindi 2213 7197 stephh if (nvlist_add_uint64(hcs, lhs, rhs->v) != 0) 2214 1414 cindi out(O_DIE, 2215 1414 cindi "cannot add payloadprop \"%s\" to fault", lhs); 2216 1414 cindi } else { 2217 1414 cindi out(O_ALTFP|O_VERB2, "addpayloadprop: %s=\"%s\"", 2218 1717 wesolows lhs, (char *)(uintptr_t)rhs->v); 2219 1414 cindi 2220 7197 stephh if (nvlist_add_string(hcs, lhs, (char *)(uintptr_t)rhs->v) != 0) 2221 1414 cindi out(O_DIE, 2222 1414 cindi "cannot add payloadprop \"%s\" to fault", lhs); 2223 1414 cindi } 2224 1414 cindi } 2225 1414 cindi 2226 1414 cindi static char *Istatbuf; 2227 1414 cindi static char *Istatbufptr; 2228 1414 cindi static int Istatsz; 2229 1414 cindi 2230 1414 cindi /* 2231 1414 cindi * istataddsize -- calculate size of istat and add it to Istatsz 2232 1414 cindi */ 2233 1414 cindi /*ARGSUSED2*/ 2234 1414 cindi static void 2235 1414 cindi istataddsize(const struct istat_entry *lhs, struct stats *rhs, void *arg) 2236 1414 cindi { 2237 1414 cindi int val; 2238 1414 cindi 2239 1414 cindi ASSERT(lhs != NULL); 2240 1414 cindi ASSERT(rhs != NULL); 2241 1414 cindi 2242 1414 cindi if ((val = stats_counter_value(rhs)) == 0) 2243 1414 cindi return; /* skip zero-valued stats */ 2244 1414 cindi 2245 1414 cindi /* count up the size of the stat name */ 2246 1414 cindi Istatsz += ipath2strlen(lhs->ename, lhs->ipath); 2247 1414 cindi Istatsz++; /* for the trailing NULL byte */ 2248 1414 cindi 2249 1414 cindi /* count up the size of the stat value */ 2250 1414 cindi Istatsz += snprintf(NULL, 0, "%d", val); 2251 1414 cindi Istatsz++; /* for the trailing NULL byte */ 2252 1414 cindi } 2253 1414 cindi 2254 1414 cindi /* 2255 1414 cindi * istat2str -- serialize an istat, writing result to *Istatbufptr 2256 1414 cindi */ 2257 1414 cindi /*ARGSUSED2*/ 2258 1414 cindi static void 2259 1414 cindi istat2str(const struct istat_entry *lhs, struct stats *rhs, void *arg) 2260 1414 cindi { 2261 1414 cindi char *str; 2262 1414 cindi int len; 2263 1414 cindi int val; 2264 1414 cindi 2265 1414 cindi ASSERT(lhs != NULL); 2266 1414 cindi ASSERT(rhs != NULL); 2267 1414 cindi 2268 1414 cindi if ((val = stats_counter_value(rhs)) == 0) 2269 1414 cindi return; /* skip zero-valued stats */ 2270 1414 cindi 2271 1414 cindi /* serialize the stat name */ 2272 1414 cindi str = ipath2str(lhs->ename, lhs->ipath); 2273 1414 cindi len = strlen(str); 2274 1414 cindi 2275 1414 cindi ASSERT(Istatbufptr + len + 1 < &Istatbuf[Istatsz]); 2276 1414 cindi (void) strlcpy(Istatbufptr, str, &Istatbuf[Istatsz] - Istatbufptr); 2277 1414 cindi Istatbufptr += len; 2278 1414 cindi FREE(str); 2279 1414 cindi *Istatbufptr++ = '\0'; 2280 1414 cindi 2281 1414 cindi /* serialize the stat value */ 2282 1414 cindi Istatbufptr += snprintf(Istatbufptr, &Istatbuf[Istatsz] - Istatbufptr, 2283 1414 cindi "%d", val); 2284 1414 cindi *Istatbufptr++ = '\0'; 2285 1414 cindi 2286 1414 cindi ASSERT(Istatbufptr <= &Istatbuf[Istatsz]); 2287 1414 cindi } 2288 1414 cindi 2289 1414 cindi void 2290 1414 cindi istat_save() 2291 1414 cindi { 2292 1414 cindi if (Istat_need_save == 0) 2293 1414 cindi return; 2294 1414 cindi 2295 1414 cindi /* figure out how big the serialzed info is */ 2296 1414 cindi Istatsz = 0; 2297 1414 cindi lut_walk(Istats, (lut_cb)istataddsize, NULL); 2298 1414 cindi 2299 1414 cindi if (Istatsz == 0) { 2300 1414 cindi /* no stats to save */ 2301 1414 cindi fmd_buf_destroy(Hdl, NULL, WOBUF_ISTATS); 2302 1414 cindi return; 2303 1414 cindi } 2304 1414 cindi 2305 1414 cindi /* create the serialized buffer */ 2306 1414 cindi Istatbufptr = Istatbuf = MALLOC(Istatsz); 2307 1414 cindi lut_walk(Istats, (lut_cb)istat2str, NULL); 2308 1414 cindi 2309 1414 cindi /* clear out current saved stats */ 2310 1414 cindi fmd_buf_destroy(Hdl, NULL, WOBUF_ISTATS); 2311 1414 cindi 2312 1414 cindi /* write out the new version */ 2313 1414 cindi fmd_buf_write(Hdl, NULL, WOBUF_ISTATS, Istatbuf, Istatsz); 2314 1414 cindi FREE(Istatbuf); 2315 1414 cindi 2316 1414 cindi Istat_need_save = 0; 2317 1414 cindi } 2318 1414 cindi 2319 1414 cindi int 2320 1414 cindi istat_cmp(struct istat_entry *ent1, struct istat_entry *ent2) 2321 1414 cindi { 2322 1414 cindi if (ent1->ename != ent2->ename) 2323 1414 cindi return (ent2->ename - ent1->ename); 2324 1414 cindi if (ent1->ipath != ent2->ipath) 2325 1414 cindi return ((char *)ent2->ipath - (char *)ent1->ipath); 2326 1414 cindi 2327 1414 cindi return (0); 2328 1414 cindi } 2329 1414 cindi 2330 1414 cindi /* 2331 1414 cindi * istat-verify -- verify the component associated with a stat still exists 2332 1414 cindi * 2333 1414 cindi * if the component no longer exists, this routine resets the stat and 2334 1414 cindi * returns 0. if the component still exists, it returns 1. 2335 1414 cindi */ 2336 1414 cindi static int 2337 1414 cindi istat_verify(struct node *snp, struct istat_entry *entp) 2338 1414 cindi { 2339 1414 cindi struct stats *statp; 2340 1414 cindi nvlist_t *fmri; 2341 1414 cindi 2342 1414 cindi fmri = node2fmri(snp->u.event.epname); 2343 1414 cindi if (platform_path_exists(fmri)) { 2344 1414 cindi nvlist_free(fmri); 2345 1414 cindi return (1); 2346 1414 cindi } 2347 1414 cindi nvlist_free(fmri); 2348 1414 cindi 2349 1414 cindi /* component no longer in system. zero out the associated stats */ 2350 1414 cindi if ((statp = (struct stats *) 2351 1414 cindi lut_lookup(Istats, entp, (lut_cmp)istat_cmp)) == NULL || 2352 1414 cindi stats_counter_value(statp) == 0) 2353 1414 cindi return (0); /* stat is already reset */ 2354 1414 cindi 2355 1414 cindi Istat_need_save = 1; 2356 1414 cindi stats_counter_reset(statp); 2357 1414 cindi return (0); 2358 1414 cindi } 2359 1414 cindi 2360 1414 cindi static void 2361 1414 cindi istat_bump(struct node *snp, int n) 2362 1414 cindi { 2363 1414 cindi struct stats *statp; 2364 1414 cindi struct istat_entry ent; 2365 1414 cindi 2366 1414 cindi ASSERT(snp != NULL); 2367 1414 cindi ASSERTinfo(snp->t == T_EVENT, ptree_nodetype2str(snp->t)); 2368 1414 cindi ASSERT(snp->u.event.epname != NULL); 2369 1414 cindi 2370 1414 cindi /* class name should be hoisted into a single stable entry */ 2371 1414 cindi ASSERT(snp->u.event.ename->u.name.next == NULL); 2372 1414 cindi ent.ename = snp->u.event.ename->u.name.s; 2373 1414 cindi ent.ipath = ipath(snp->u.event.epname); 2374 1414 cindi 2375 1414 cindi if (!istat_verify(snp, &ent)) { 2376 1414 cindi /* component no longer exists in system, nothing to do */ 2377 1414 cindi return; 2378 1414 cindi } 2379 1414 cindi 2380 1414 cindi if ((statp = (struct stats *) 2381 1414 cindi lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) { 2382 1414 cindi /* need to create the counter */ 2383 1414 cindi int cnt = 0; 2384 1414 cindi struct node *np; 2385 1414 cindi char *sname; 2386 1414 cindi char *snamep; 2387 1414 cindi struct istat_entry *newentp; 2388 1414 cindi 2389 1414 cindi /* count up the size of the stat name */ 2390 1414 cindi np = snp->u.event.ename; 2391 1414 cindi while (np != NULL) { 2392 1414 cindi cnt += strlen(np->u.name.s); 2393 1414 cindi cnt++; /* for the '.' or '@' */ 2394 1414 cindi np = np->u.name.next; 2395 1414 cindi } 2396 1414 cindi np = snp->u.event.epname; 2397 1414 cindi while (np != NULL) { 2398 1414 cindi cnt += snprintf(NULL, 0, "%s%llu", 2399 1414 cindi np->u.name.s, np->u.name.child->u.ull); 2400 1414 cindi cnt++; /* for the '/' or trailing NULL byte */ 2401 1414 cindi np = np->u.name.next; 2402 1414 cindi } 2403 1414 cindi 2404 1414 cindi /* build the stat name */ 2405 1414 cindi snamep = sname = alloca(cnt); 2406 1414 cindi np = snp->u.event.ename; 2407 1414 cindi while (np != NULL) { 2408 1414 cindi snamep += snprintf(snamep, &sname[cnt] - snamep, 2409 1414 cindi "%s", np->u.name.s); 2410 1414 cindi np = np->u.name.next; 2411 1414 cindi if (np) 2412 1414 cindi *snamep++ = '.'; 2413 1414 cindi } 2414 1414 cindi *snamep++ = '@'; 2415 1414 cindi np = snp->u.event.epname; 2416 1414 cindi while (np != NULL) { 2417 1414 cindi snamep += snprintf(snamep, &sname[cnt] - snamep, 2418 1414 cindi "%s%llu", np->u.name.s, np->u.name.child->u.ull); 2419 1414 cindi np = np->u.name.next; 2420 1414 cindi if (np) 2421 1414 cindi *snamep++ = '/'; 2422 1414 cindi } 2423 1414 cindi *snamep++ = '\0'; 2424 1414 cindi 2425 1414 cindi /* create the new stat & add it to our list */ 2426 1414 cindi newentp = MALLOC(sizeof (*newentp)); 2427 1414 cindi *newentp = ent; 2428 1414 cindi statp = stats_new_counter(NULL, sname, 0); 2429 1414 cindi Istats = lut_add(Istats, (void *)newentp, (void *)statp, 2430 1414 cindi (lut_cmp)istat_cmp); 2431 1414 cindi } 2432 1414 cindi 2433 1414 cindi /* if n is non-zero, set that value instead of bumping */ 2434 1414 cindi if (n) { 2435 1414 cindi stats_counter_reset(statp); 2436 1414 cindi stats_counter_add(statp, n); 2437 1414 cindi } else 2438 1414 cindi stats_counter_bump(statp); 2439 1414 cindi Istat_need_save = 1; 2440 2869 gavinm 2441 2869 gavinm ipath_print(O_ALTFP|O_VERB2, ent.ename, ent.ipath); 2442 2869 gavinm out(O_ALTFP|O_VERB2, " %s to value %d", n ? "set" : "incremented", 2443 2869 gavinm stats_counter_value(statp)); 2444 1414 cindi } 2445 1414 cindi 2446 1414 cindi /*ARGSUSED*/ 2447 1414 cindi static void 2448 1414 cindi istat_destructor(void *left, void *right, void *arg) 2449 1414 cindi { 2450 1414 cindi struct istat_entry *entp = (struct istat_entry *)left; 2451 1414 cindi struct stats *statp = (struct stats *)right; 2452 1414 cindi FREE(entp); 2453 1414 cindi stats_delete(statp); 2454 2120 gavinm } 2455 2120 gavinm 2456 2120 gavinm /* 2457 2120 gavinm * Callback used in a walk of the Istats to reset matching stat counters. 2458 2120 gavinm */ 2459 2120 gavinm static void 2460 2120 gavinm istat_counter_reset_cb(struct istat_entry *entp, struct stats *statp, 2461 2120 gavinm const struct ipath *ipp) 2462 2120 gavinm { 2463 2120 gavinm char *path; 2464 2120 gavinm 2465 2120 gavinm if (entp->ipath == ipp) { 2466 2120 gavinm path = ipath2str(entp->ename, ipp); 2467 2120 gavinm out(O_ALTFP, "istat_counter_reset_cb: resetting %s", path); 2468 2120 gavinm FREE(path); 2469 2120 gavinm stats_counter_reset(statp); 2470 2120 gavinm Istat_need_save = 1; 2471 2120 gavinm } 2472 1414 cindi } 2473 1414 cindi 2474 5204 stephh /*ARGSUSED*/ 2475 5204 stephh static void 2476 5204 stephh istat_counter_topo_chg_cb(struct istat_entry *entp, struct stats *statp, 2477 5204 stephh void *unused) 2478 5204 stephh { 2479 5204 stephh char *path; 2480 5204 stephh nvlist_t *fmri; 2481 5204 stephh 2482 5204 stephh fmri = ipath2fmri((struct ipath *)(entp->ipath)); 2483 5204 stephh if (!platform_path_exists(fmri)) { 2484 5204 stephh path = ipath2str(entp->ename, entp->ipath); 2485 5204 stephh out(O_ALTFP, "istat_counter_topo_chg_cb: not present %s", path); 2486 5204 stephh FREE(path); 2487 5204 stephh stats_counter_reset(statp); 2488 5204 stephh Istat_need_save = 1; 2489 5204 stephh } 2490 5204 stephh nvlist_free(fmri); 2491 5204 stephh } 2492 5204 stephh 2493 1414 cindi void 2494 1414 cindi istat_fini(void) 2495 1414 cindi { 2496 1414 cindi lut_free(Istats, istat_destructor, NULL); 2497 1414 cindi } 2498 1414 cindi 2499 4436 stephh static char *Serdbuf; 2500 4436 stephh static char *Serdbufptr; 2501 4436 stephh static int Serdsz; 2502 4436 stephh 2503 4436 stephh /* 2504 4436 stephh * serdaddsize -- calculate size of serd and add it to Serdsz 2505 4436 stephh */ 2506 4436 stephh /*ARGSUSED*/ 2507 4436 stephh static void 2508 4436 stephh serdaddsize(const struct serd_entry *lhs, struct stats *rhs, void *arg) 2509 4436 stephh { 2510 4436 stephh ASSERT(lhs != NULL); 2511 4436 stephh 2512 4436 stephh /* count up the size of the stat name */ 2513 4436 stephh Serdsz += ipath2strlen(lhs->ename, lhs->ipath); 2514 4436 stephh Serdsz++; /* for the trailing NULL byte */ 2515 4436 stephh } 2516 4436 stephh 2517 4436 stephh /* 2518 4436 stephh * serd2str -- serialize a serd engine, writing result to *Serdbufptr 2519 4436 stephh */ 2520 4436 stephh /*ARGSUSED*/ 2521 4436 stephh static void 2522 4436 stephh serd2str(const struct serd_entry *lhs, struct stats *rhs, void *arg) 2523 4436 stephh { 2524 4436 stephh char *str; 2525 4436 stephh int len; 2526 4436 stephh 2527 4436 stephh ASSERT(lhs != NULL); 2528 4436 stephh 2529 4436 stephh /* serialize the serd engine name */ 2530 4436 stephh str = ipath2str(lhs->ename, lhs->ipath); 2531 4436 stephh len = strlen(str); 2532 4436 stephh 2533 4436 stephh ASSERT(Serdbufptr + len + 1 <= &Serdbuf[Serdsz]); 2534 4436 stephh (void) strlcpy(Serdbufptr, str, &Serdbuf[Serdsz] - Serdbufptr); 2535 4436 stephh Serdbufptr += len; 2536 4436 stephh FREE(str); 2537 4436 stephh *Serdbufptr++ = '\0'; 2538 4436 stephh ASSERT(Serdbufptr <= &Serdbuf[Serdsz]); 2539 4436 stephh } 2540 4436 stephh 2541 4436 stephh void 2542 4436 stephh serd_save() 2543 4436 stephh { 2544 4436 stephh if (Serd_need_save == 0) 2545 4436 stephh return; 2546 4436 stephh 2547 4436 stephh /* figure out how big the serialzed info is */ 2548 4436 stephh Serdsz = 0; 2549 4436 stephh lut_walk(SerdEngines, (lut_cb)serdaddsize, NULL); 2550 4436 stephh 2551 4436 stephh if (Serdsz == 0) { 2552 4436 stephh /* no serd engines to save */ 2553 4436 stephh fmd_buf_destroy(Hdl, NULL, WOBUF_SERDS); 2554 4436 stephh return; 2555 4436 stephh } 2556 4436 stephh 2557 4436 stephh /* create the serialized buffer */ 2558 4436 stephh Serdbufptr = Serdbuf = MALLOC(Serdsz); 2559 4436 stephh lut_walk(SerdEngines, (lut_cb)serd2str, NULL); 2560 4436 stephh 2561 4436 stephh /* clear out current saved stats */ 2562 4436 stephh fmd_buf_destroy(Hdl, NULL, WOBUF_SERDS); 2563 4436 stephh 2564 4436 stephh /* write out the new version */ 2565 4436 stephh fmd_buf_write(Hdl, NULL, WOBUF_SERDS, Serdbuf, Serdsz); 2566 4436 stephh FREE(Serdbuf); 2567 4436 stephh Serd_need_save = 0; 2568 4436 stephh } 2569 4436 stephh 2570 4436 stephh int 2571 4436 stephh serd_cmp(struct serd_entry *ent1, struct serd_entry *ent2) 2572 4436 stephh { 2573 4436 stephh if (ent1->ename != ent2->ename) 2574 4436 stephh return (ent2->ename - ent1->ename); 2575 4436 stephh if (ent1->ipath != ent2->ipath) 2576 4436 stephh return ((char *)ent2->ipath - (char *)ent1->ipath); 2577 4436 stephh 2578 4436 stephh return (0); 2579 4436 stephh } 2580 4436 stephh 2581 4436 stephh void 2582 4436 stephh fme_serd_load(fmd_hdl_t *hdl) 2583 4436 stephh { 2584 4436 stephh int sz; 2585 4436 stephh char *sbuf; 2586 4436 stephh char *sepptr; 2587 4436 stephh char *ptr; 2588 4436 stephh struct serd_entry *newentp; 2589 4436 stephh struct node *epname; 2590 4436 stephh nvlist_t *fmri; 2591 4436 stephh char *namestring; 2592 4436 stephh 2593 4436 stephh if ((sz = fmd_buf_size(hdl, NULL, WOBUF_SERDS)) == 0) 2594 4436 stephh return; 2595 4436 stephh sbuf = alloca(sz); 2596 4436 stephh fmd_buf_read(hdl, NULL, WOBUF_SERDS, sbuf, sz); 2597 4436 stephh ptr = sbuf; 2598 4436 stephh while (ptr < &sbuf[sz]) { 2599 4436 stephh sepptr = strchr(ptr, '@'); 2600 4436 stephh *sepptr = '\0'; 2601 4436 stephh namestring = ptr; 2602 4436 stephh sepptr++; 2603 4436 stephh ptr = sepptr; 2604 4436 stephh ptr += strlen(ptr); 2605 4436 stephh ptr++; /* move past the '\0' separating paths */ 2606 4436 stephh epname = pathstring2epnamenp(sepptr); 2607 4436 stephh fmri = node2fmri(epname); 2608 4436 stephh if (platform_path_exists(fmri)) { 2609 4436 stephh newentp = MALLOC(sizeof (*newentp)); 2610 4436 stephh newentp->hdl = hdl; 2611 4436 stephh newentp->ipath = ipath(epname); 2612 4436 stephh newentp->ename = stable(namestring); 2613 4436 stephh SerdEngines = lut_add(SerdEngines, (void *)newentp, 2614 5204 stephh (void *)newentp, (lut_cmp)serd_cmp); 2615 4436 stephh } else 2616 4436 stephh Serd_need_save = 1; 2617 5204 stephh tree_free(epname); 2618 4436 stephh nvlist_free(fmri); 2619 4436 stephh } 2620 4436 stephh /* save it back again in case some of the paths no longer exist */ 2621 4436 stephh serd_save(); 2622 4436 stephh } 2623 4436 stephh 2624 4436 stephh /*ARGSUSED*/ 2625 4436 stephh static void 2626 4436 stephh serd_destructor(void *left, void *right, void *arg) 2627 4436 stephh { 2628 4436 stephh struct serd_entry *entp = (struct serd_entry *)left; 2629 4436 stephh FREE(entp); 2630 4436 stephh } 2631 4436 stephh 2632 4436 stephh /* 2633 4436 stephh * Callback used in a walk of the SerdEngines to reset matching serd engines. 2634 4436 stephh */ 2635 4436 stephh /*ARGSUSED*/ 2636 4436 stephh static void 2637 4436 stephh serd_reset_cb(struct serd_entry *entp, void *unused, const struct ipath *ipp) 2638 4436 stephh { 2639 4436 stephh char *path; 2640 4436 stephh 2641 4436 stephh if (entp->ipath == ipp) { 2642 4436 stephh path = ipath2str(entp->ename, ipp); 2643 4436 stephh out(O_ALTFP, "serd_reset_cb: resetting %s", path); 2644 4436 stephh fmd_serd_reset(entp->hdl, path); 2645 4436 stephh FREE(path); 2646 4436 stephh Serd_need_save = 1; 2647 4436 stephh } 2648 5204 stephh } 2649 5204 stephh 2650 5204 stephh /*ARGSUSED*/ 2651 5204 stephh static void 2652 5204 stephh serd_topo_chg_cb(struct serd_entry *entp, void *unused, void *unused2) 2653 5204 stephh { 2654 5204 stephh char *path; 2655 5204 stephh nvlist_t *fmri; 2656 5204 stephh 2657 5204 stephh fmri = ipath2fmri((struct ipath *)(entp->ipath)); 2658 5204 stephh if (!platform_path_exists(fmri)) { 2659 5204 stephh path = ipath2str(entp->ename, entp->ipath); 2660 5204 stephh out(O_ALTFP, "serd_topo_chg_cb: not present %s", path); 2661 5204 stephh fmd_serd_reset(entp->hdl, path); 2662 5204 stephh FREE(path); 2663 5204 stephh Serd_need_save = 1; 2664 5204 stephh } 2665 5204 stephh nvlist_free(fmri); 2666 4436 stephh } 2667 4436 stephh 2668 4436 stephh void 2669 4436 stephh serd_fini(void) 2670 4436 stephh { 2671 4436 stephh lut_free(SerdEngines, serd_destructor, NULL); 2672 4436 stephh } 2673 4436 stephh 2674 0 stevel static void 2675 7197 stephh publish_suspects(struct fme *fmep, struct rsl *srl) 2676 7197 stephh { 2677 0 stevel struct rsl *rp; 2678 0 stevel nvlist_t *fault; 2679 0 stevel uint8_t cert; 2680 0 stevel uint_t *frs; 2681 8245 Stephen uint_t frsum, fr; 2682 1414 cindi uint_t messval; 2683 7197 stephh uint_t retireval; 2684 7197 stephh uint_t responseval; 2685 1414 cindi struct node *snp; 2686 0 stevel int frcnt, fridx; 2687 1414 cindi boolean_t allfaulty = B_TRUE; 2688 7197 stephh struct rsl *erl = srl + fmep->nsuspects - 1; 2689 7197 stephh 2690 7197 stephh /* 2691 7197 stephh * sort the array 2692 7197 stephh */ 2693 7197 stephh qsort(srl, fmep->nsuspects, sizeof (struct rsl), rslcmp); 2694 8245 Stephen 2695 8245 Stephen /* sum the fitrates */ 2696 8245 Stephen frs = alloca(fmep->nsuspects * sizeof (uint_t)); 2697 8245 Stephen fridx = frcnt = frsum = 0; 2698 8245 Stephen 2699 8245 Stephen for (rp = srl; rp <= erl; rp++) { 2700 8245 Stephen struct node *n; 2701 8245 Stephen 2702 8245 Stephen n = eventprop_lookup(rp->suspect, L_FITrate); 2703 8245 Stephen if (node2uint(n, &fr) != 0) { 2704 8245 Stephen out(O_DEBUG|O_NONL, "event "); 2705 8245 Stephen ipath_print(O_DEBUG|O_NONL, 2706 8245 Stephen rp->suspect->enode->u.event.ename->u.name.s, 2707 8245 Stephen rp->suspect->ipp); 2708 8245 Stephen out(O_DEBUG, " has no FITrate (using 1)"); 2709 8245 Stephen fr = 1; 2710 8245 Stephen } else if (fr == 0) { 2711 8245 Stephen out(O_DEBUG|O_NONL, "event "); 2712 8245 Stephen ipath_print(O_DEBUG|O_NONL, 2713 8245 Stephen rp->suspect->enode->u.event.ename->u.name.s, 2714 8245 Stephen rp->suspect->ipp); 2715 8245 Stephen out(O_DEBUG, " has zero FITrate (using 1)"); 2716 8245 Stephen fr = 1; 2717 8245 Stephen } 2718 8245 Stephen 2719 8245 Stephen frs[fridx++] = fr; 2720 8245 Stephen frsum += fr; 2721 8245 Stephen frcnt++; 2722 0 stevel } 2723 0 stevel 2724 0 stevel /* Add them in reverse order of our sort, as fmd reverses order */ 2725 0 stevel for (rp = erl; rp >= srl; rp--) { 2726 8245 Stephen cert = percentof(frs[--fridx], frsum); 2727 0 stevel fault = fmd_nvl_create_fault(fmep->hdl, 2728 0 stevel rp->suspect->enode->u.event.ename->u.name.s, 2729 0 stevel cert, 2730 0 stevel rp->asru, 2731 0 stevel rp->fru, 2732 0 stevel rp->rsrc); 2733 0 stevel if (fault == NULL) 2734 0 stevel out(O_DIE, "fault creation failed"); 2735 1414 cindi /* if "message" property exists, add it to the fault */ 2736 1414 cindi if (node2uint(eventprop_lookup(rp->suspect, L_message), 2737 1414 cindi &messval) == 0) { 2738 1414 cindi 2739 1414 cindi out(O_ALTFP, 2740 1414 cindi "[FME%d, %s adds message=%d to suspect list]", 2741 1414 cindi fmep->id, 2742 1414 cindi rp->suspect->enode->u.event.ename->u.name.s, 2743 1414 cindi messval); 2744 1414 cindi if (nvlist_add_boolean_value(fault, 2745 1414 cindi FM_SUSPECT_MESSAGE, 2746 1414 cindi (messval) ? B_TRUE : B_FALSE) != 0) { 2747 1414 cindi out(O_DIE, "cannot add no-message to fault"); 2748 1414 cindi } 2749 1414 cindi } 2750 7197 stephh 2751 7197 stephh /* if "retire" property exists, add it to the fault */ 2752 7197 stephh if (node2uint(eventprop_lookup(rp->suspect, L_retire), 2753 7197 stephh &retireval) == 0) { 2754 7197 stephh 2755 7197 stephh out(O_ALTFP, 2756 7197 stephh "[FME%d, %s adds retire=%d to suspect list]", 2757 7197 stephh fmep->id, 2758 7197 stephh rp->suspect->enode->u.event.ename->u.name.s, 2759 7197 stephh retireval); 2760 7197 stephh if (nvlist_add_boolean_value(fault, 2761 7197 stephh FM_SUSPECT_RETIRE, 2762 7197 stephh (retireval) ? B_TRUE : B_FALSE) != 0) { 2763 7197 stephh out(O_DIE, "cannot add no-retire to fault"); 2764 7197 stephh } 2765 7197 stephh } 2766 7197 stephh 2767 7197 stephh /* if "response" property exists, add it to the fault */ 2768 7197 stephh if (node2uint(eventprop_lookup(rp->suspect, L_response), 2769 7197 stephh &responseval) == 0) { 2770 7197 stephh 2771 7197 stephh out(O_ALTFP, 2772 7197 stephh "[FME%d, %s adds response=%d to suspect list]", 2773 7197 stephh fmep->id, 2774 7197 stephh rp->suspect->enode->u.event.ename->u.name.s, 2775 7197 stephh responseval); 2776 7197 stephh if (nvlist_add_boolean_value(fault, 2777 7197 stephh FM_SUSPECT_RESPONSE, 2778 7197 stephh (responseval) ? B_TRUE : B_FALSE) != 0) { 2779 7197 stephh out(O_DIE, "cannot add no-response to fault"); 2780 7197 stephh } 2781 7197 stephh } 2782 7197 stephh 2783 1414 cindi /* add any payload properties */ 2784 1414 cindi lut_walk(rp->suspect->payloadprops, 2785 1414 cindi (lut_cb)addpayloadprop, (void *)fault); 2786 0 stevel rslfree(rp); 2787 1493 gavinm 2788 1493 gavinm /* 2789 1493 gavinm * If "action" property exists, evaluate it; this must be done 2790 7197 stephh * before the allfaulty check below since some actions may 2791 7275 stephh * modify the asru to be used in fmd_nvl_fmri_has_fault. This 2792 1493 gavinm * needs to be restructured if any new actions are introduced 2793 1493 gavinm * that have effects that we do not want to be visible if 2794 1493 gavinm * we decide not to publish in the dupclose check below. 2795 1493 gavinm */ 2796 1414 cindi if ((snp = eventprop_lookup(rp->suspect, L_action)) != NULL) { 2797 1414 cindi struct evalue evalue; 2798 1414 cindi 2799 1414 cindi out(O_ALTFP|O_NONL, 2800 1414 cindi "[FME%d, %s action ", fmep->id, 2801 1414 cindi rp->suspect->enode->u.event.ename->u.name.s); 2802 1414 cindi ptree_name_iter(O_ALTFP|O_NONL, snp); 2803 1414 cindi out(O_ALTFP, "]"); 2804 1414 cindi Action_nvl = fault; 2805 1414 cindi (void) eval_expr(snp, NULL, NULL, NULL, NULL, 2806 1414 cindi NULL, 0, &evalue); 2807 1414 cindi } 2808 1493 gavinm 2809 7197 stephh fmd_case_add_suspect(fmep->hdl, fmep->fmcase, fault); 2810 7197 stephh 2811 1414 cindi /* 2812 6228 stephh * check if the asru is already marked as "faulty". 2813 6228 stephh */ 2814 6228 stephh if (allfaulty) { 2815 1414 cindi nvlist_t *asru; 2816 1414 cindi 2817 7197 stephh out(O_ALTFP|O_VERB, "FME%d dup check ", fmep->id); 2818 1414 cindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, rp->suspect); 2819 1414 cindi out(O_ALTFP|O_VERB|O_NONL, " "); 2820 1414 cindi if (nvlist_lookup_nvlist(fault, 2821 1414 cindi FM_FAULT_ASRU, &asru) != 0) { 2822 1414 cindi out(O_ALTFP|O_VERB, "NULL asru"); 2823 1414 cindi allfaulty = B_FALSE; 2824 7275 stephh } else if (fmd_nvl_fmri_has_fault(fmep->hdl, asru, 2825 7275 stephh FMD_HAS_FAULT_ASRU, NULL)) { 2826 1414 cindi out(O_ALTFP|O_VERB, "faulty"); 2827 1414 cindi } else { 2828 1414 cindi out(O_ALTFP|O_VERB, "not faulty"); 2829 1414 cindi allfaulty = B_FALSE; 2830 1414 cindi } 2831 1414 cindi } 2832 1414 cindi 2833 0 stevel } 2834 1493 gavinm 2835 6228 stephh if (!allfaulty) { 2836 6228 stephh /* 2837 6228 stephh * don't update the count stat if all asrus are already 2838 6228 stephh * present and unrepaired in the asru cache 2839 6228 stephh */ 2840 1493 gavinm for (rp = erl; rp >= srl; rp--) { 2841 1493 gavinm struct event *suspect = rp->suspect; 2842 1493 gavinm 2843 1493 gavinm if (suspect == NULL) 2844 1493 gavinm continue; 2845 1493 gavinm 2846 1493 gavinm /* if "count" exists, increment the appropriate stat */ 2847 1493 gavinm if ((snp = eventprop_lookup(suspect, 2848 1493 gavinm L_count)) != NULL) { 2849 1493 gavinm out(O_ALTFP|O_NONL, 2850 1493 gavinm "[FME%d, %s count ", fmep->id, 2851 1493 gavinm suspect->enode->u.event.ename->u.name.s); 2852 1493 gavinm ptree_name_iter(O_ALTFP|O_NONL, snp); 2853 1493 gavinm out(O_ALTFP, "]"); 2854 1493 gavinm istat_bump(snp, 0); 2855 1493 gavinm 2856 1493 gavinm } 2857 1493 gavinm } 2858 1493 gavinm istat_save(); /* write out any istat changes */ 2859 6228 stephh } 2860 0 stevel } 2861 0 stevel 2862 7748 Tarik static const char * 2863 7748 Tarik undiag_2defect_str(int ud) 2864 7748 Tarik { 2865 7748 Tarik switch (ud) { 2866 7748 Tarik case UD_VAL_MISSINGINFO: 2867 7748 Tarik case UD_VAL_MISSINGOBS: 2868 7748 Tarik case UD_VAL_MISSINGPATH: 2869 7748 Tarik case UD_VAL_MISSINGZERO: 2870 7748 Tarik case UD_VAL_BADOBS: 2871 7748 Tarik case UD_VAL_CFGMISMATCH: 2872 7748 Tarik return (UNDIAG_DEFECT_CHKPT); 2873 7748 Tarik break; 2874 7748 Tarik 2875 7748 Tarik case UD_VAL_BADEVENTI: 2876 7748 Tarik case UD_VAL_INSTFAIL: 2877 7748 Tarik case UD_VAL_NOPATH: 2878 7748 Tarik case UD_VAL_UNSOLVD: 2879 7748 Tarik return (UNDIAG_DEFECT_FME); 2880 7748 Tarik break; 2881 7748 Tarik 2882 7748 Tarik case UD_VAL_MAXFME: 2883 7748 Tarik return (UNDIAG_DEFECT_LIMIT); 2884 7748 Tarik break; 2885 7748 Tarik 2886 7748 Tarik case UD_VAL_UNKNOWN: 2887 7748 Tarik default: 2888 7748 Tarik return (UNDIAG_DEFECT_UNKNOWN); 2889 7748 Tarik break; 2890 7748 Tarik } 2891 7748 Tarik } 2892 7748 Tarik 2893 7748 Tarik const char * 2894 7748 Tarik undiag_2reason_str(int ud) 2895 7748 Tarik { 2896 7748 Tarik switch (ud) { 2897 7748 Tarik case UD_VAL_BADEVENTI: 2898 7748 Tarik return (UD_STR_BADEVENTI); 2899 7748 Tarik case UD_VAL_BADOBS: 2900 7748 Tarik return (UD_STR_BADOBS); 2901 7748 Tarik case UD_VAL_CFGMISMATCH: 2902 7748 Tarik return (UD_STR_CFGMISMATCH); 2903 7748 Tarik case UD_VAL_INSTFAIL: 2904 7748 Tarik return (UD_STR_INSTFAIL); 2905 7748 Tarik case UD_VAL_MAXFME: 2906 7748 Tarik return (UD_STR_MAXFME); 2907 7748 Tarik case UD_VAL_MISSINGINFO: 2908 7748 Tarik return (UD_STR_MISSINGINFO); 2909 7748 Tarik case UD_VAL_MISSINGOBS: 2910 7748 Tarik return (UD_STR_MISSINGOBS); 2911 7748 Tarik case UD_VAL_MISSINGPATH: 2912 7748 Tarik return (UD_STR_MISSINGPATH); 2913 7748 Tarik case UD_VAL_MISSINGZERO: 2914 7748 Tarik return (UD_STR_MISSINGZERO); 2915 7748 Tarik case UD_VAL_NOPATH: 2916 7748 Tarik return (UD_STR_NOPATH); 2917 7748 Tarik case UD_VAL_UNSOLVD: 2918 7748 Tarik return (UD_STR_UNSOLVD); 2919 7748 Tarik case UD_VAL_UNKNOWN: 2920 7748 Tarik default: 2921 7748 Tarik return (UD_STR_UNKNOWN); 2922 7748 Tarik } 2923 7748 Tarik } 2924 7748 Tarik 2925 0 stevel static void 2926 4436 stephh publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep, fmd_case_t *fmcase) 2927 0 stevel { 2928 0 stevel struct case_list *newcase; 2929 0 stevel nvlist_t *defect; 2930 0 stevel 2931 0 stevel out(O_ALTFP, 2932 0 stevel "[undiagnosable ereport received, " 2933 0 stevel "creating and closing a new case (%s)]", 2934 7748 Tarik undiag_2reason_str(Undiag_reason)); 2935 0 stevel 2936 0 stevel newcase = MALLOC(sizeof (struct case_list)); 2937 0 stevel newcase->next = NULL; 2938 4436 stephh newcase->fmcase = fmcase; 2939 0 stevel if (Undiagablecaselist != NULL) 2940 0 stevel newcase->next = Undiagablecaselist; 2941 0 stevel Undiagablecaselist = newcase; 2942 0 stevel 2943 0 stevel if (ffep != NULL) 2944 0 stevel fmd_case_add_ereport(hdl, newcase->fmcase, ffep); 2945 0 stevel 2946 7748 Tarik defect = fmd_nvl_create_fault(hdl, 2947 7748 Tarik undiag_2defect_str(Undiag_reason), 100, NULL, NULL, NULL); 2948 7748 Tarik (void) nvlist_add_string(defect, UNDIAG_REASON, 2949 7748 Tarik undiag_2reason_str(Undiag_reason)); 2950 0 stevel fmd_case_add_suspect(hdl, newcase->fmcase, defect); 2951 0