17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55f25dc2aSgavinm * Common Development and Distribution License (the "License"). 65f25dc2aSgavinm * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215f25dc2aSgavinm 227c478bd9Sstevel@tonic-gate /* 23f5961f52SAdrian Frost * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 2433f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 25a3f6a2a4SRob Johnston * Copyright (c) 2018, Joyent, Inc. 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * fme.c -- fault management exercise module 287c478bd9Sstevel@tonic-gate * 297c478bd9Sstevel@tonic-gate * this module provides the simulated fault management exercise. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <strings.h> 367c478bd9Sstevel@tonic-gate #include <ctype.h> 377c478bd9Sstevel@tonic-gate #include <alloca.h> 387c478bd9Sstevel@tonic-gate #include <libnvpair.h> 397c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 407c478bd9Sstevel@tonic-gate #include <fm/fmd_api.h> 41*da40b264SAlex Wilson #include <fm/libtopo.h> 427c478bd9Sstevel@tonic-gate #include "alloc.h" 437c478bd9Sstevel@tonic-gate #include "out.h" 447c478bd9Sstevel@tonic-gate #include "stats.h" 457c478bd9Sstevel@tonic-gate #include "stable.h" 467c478bd9Sstevel@tonic-gate #include "literals.h" 477c478bd9Sstevel@tonic-gate #include "lut.h" 487c478bd9Sstevel@tonic-gate #include "tree.h" 497c478bd9Sstevel@tonic-gate #include "ptree.h" 507c478bd9Sstevel@tonic-gate #include "itree.h" 517c478bd9Sstevel@tonic-gate #include "ipath.h" 527c478bd9Sstevel@tonic-gate #include "fme.h" 537c478bd9Sstevel@tonic-gate #include "evnv.h" 547c478bd9Sstevel@tonic-gate #include "eval.h" 557c478bd9Sstevel@tonic-gate #include "config.h" 567c478bd9Sstevel@tonic-gate #include "platform.h" 57e5ba14ffSstephh #include "esclex.h" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* imported from eft.c... */ 607c478bd9Sstevel@tonic-gate extern hrtime_t Hesitate; 61e5ba14ffSstephh extern char *Serd_Override; 627c478bd9Sstevel@tonic-gate extern nv_alloc_t Eft_nv_hdl; 630cc1f05eSjrutt extern int Max_fme; 647aec1d6eScindi extern fmd_hdl_t *Hdl; 657aec1d6eScindi 667aec1d6eScindi static int Istat_need_save; 67b5016cbbSstephh static int Serd_need_save; 6808f6c065Sgavinm void istat_save(void); 69b5016cbbSstephh void serd_save(void); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* fme under construction is global so we can free it on module abort */ 727c478bd9Sstevel@tonic-gate static struct fme *Nfmep; 737c478bd9Sstevel@tonic-gate 7432d4e834STarik Soydan static int Undiag_reason = UD_VAL_UNKNOWN; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static int Nextid = 0; 777c478bd9Sstevel@tonic-gate 780cc1f05eSjrutt static int Open_fme_count = 0; /* Count of open FMEs */ 790cc1f05eSjrutt 807c478bd9Sstevel@tonic-gate /* list of fault management exercises underway */ 817c478bd9Sstevel@tonic-gate static struct fme { 827c478bd9Sstevel@tonic-gate struct fme *next; /* next exercise */ 837c478bd9Sstevel@tonic-gate unsigned long long ull; /* time when fme was created */ 847c478bd9Sstevel@tonic-gate int id; /* FME id */ 85e5ba14ffSstephh struct config *config; /* cooked configuration data */ 867c478bd9Sstevel@tonic-gate struct lut *eventtree; /* propagation tree for this FME */ 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * The initial error report that created this FME is kept in 897c478bd9Sstevel@tonic-gate * two forms. e0 points to the instance tree node and is used 907c478bd9Sstevel@tonic-gate * by fme_eval() as the starting point for the inference 917c478bd9Sstevel@tonic-gate * algorithm. e0r is the event handle FMD passed to us when 927c478bd9Sstevel@tonic-gate * the ereport first arrived and is used when setting timers, 937c478bd9Sstevel@tonic-gate * which are always relative to the time of this initial 947c478bd9Sstevel@tonic-gate * report. 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate struct event *e0; 977c478bd9Sstevel@tonic-gate fmd_event_t *e0r; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate id_t timer; /* for setting an fmd time-out */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate struct event *ecurrent; /* ereport under consideration */ 1027c478bd9Sstevel@tonic-gate struct event *suspects; /* current suspect list */ 1037c478bd9Sstevel@tonic-gate struct event *psuspects; /* previous suspect list */ 1047c478bd9Sstevel@tonic-gate int nsuspects; /* count of suspects */ 1057c478bd9Sstevel@tonic-gate int posted_suspects; /* true if we've posted a diagnosis */ 1067c478bd9Sstevel@tonic-gate int uniqobs; /* number of unique events observed */ 1077c478bd9Sstevel@tonic-gate int peek; /* just peeking, don't track suspects */ 1080cc1f05eSjrutt int overflow; /* true if overflow FME */ 1097c478bd9Sstevel@tonic-gate enum fme_state { 1107c478bd9Sstevel@tonic-gate FME_NOTHING = 5000, /* not evaluated yet */ 1117c478bd9Sstevel@tonic-gate FME_WAIT, /* need to wait for more info */ 1127c478bd9Sstevel@tonic-gate FME_CREDIBLE, /* suspect list is credible */ 1137aec1d6eScindi FME_DISPROVED, /* no valid suspects found */ 1147aec1d6eScindi FME_DEFERRED /* don't know yet (k-count not met) */ 1157c478bd9Sstevel@tonic-gate } state; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate unsigned long long pull; /* time passed since created */ 1187c478bd9Sstevel@tonic-gate unsigned long long wull; /* wait until this time for re-eval */ 1197c478bd9Sstevel@tonic-gate struct event *observations; /* observation list */ 1207c478bd9Sstevel@tonic-gate struct lut *globals; /* values of global variables */ 1217c478bd9Sstevel@tonic-gate /* fmd interfacing */ 1227c478bd9Sstevel@tonic-gate fmd_hdl_t *hdl; /* handle for talking with fmd */ 1237c478bd9Sstevel@tonic-gate fmd_case_t *fmcase; /* what fmd 'case' we associate with */ 1247c478bd9Sstevel@tonic-gate /* stats */ 1257c478bd9Sstevel@tonic-gate struct stats *Rcount; 1267c478bd9Sstevel@tonic-gate struct stats *Hcallcount; 1277c478bd9Sstevel@tonic-gate struct stats *Rcallcount; 1287c478bd9Sstevel@tonic-gate struct stats *Ccallcount; 1297c478bd9Sstevel@tonic-gate struct stats *Ecallcount; 1307c478bd9Sstevel@tonic-gate struct stats *Tcallcount; 1317c478bd9Sstevel@tonic-gate struct stats *Marrowcount; 1327c478bd9Sstevel@tonic-gate struct stats *diags; 1337c478bd9Sstevel@tonic-gate } *FMElist, *EFMElist, *ClosedFMEs; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static struct case_list { 1367c478bd9Sstevel@tonic-gate fmd_case_t *fmcase; 1377c478bd9Sstevel@tonic-gate struct case_list *next; 1387c478bd9Sstevel@tonic-gate } *Undiagablecaselist; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate static void fme_eval(struct fme *fmep, fmd_event_t *ffep); 1417c478bd9Sstevel@tonic-gate static enum fme_state hypothesise(struct fme *fmep, struct event *ep, 1427aec1d6eScindi unsigned long long at_latest_by, unsigned long long *pdelay); 1437c478bd9Sstevel@tonic-gate static struct node *eventprop_lookup(struct event *ep, const char *propname); 1447c478bd9Sstevel@tonic-gate static struct node *pathstring2epnamenp(char *path); 145b5016cbbSstephh static void publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep, 146705e9f42SStephen Hanson fmd_case_t *fmcase, nvlist_t *detector, char *arg); 147705e9f42SStephen Hanson static char *undiag_2reason_str(int ud, char *arg); 14832d4e834STarik Soydan static const char *undiag_2defect_str(int ud); 1497c478bd9Sstevel@tonic-gate static void restore_suspects(struct fme *fmep); 1507c478bd9Sstevel@tonic-gate static void save_suspects(struct fme *fmep); 1517c478bd9Sstevel@tonic-gate static void destroy_fme(struct fme *f); 1527c478bd9Sstevel@tonic-gate static void fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 1537c478bd9Sstevel@tonic-gate const char *eventstring, const struct ipath *ipp, nvlist_t *nvl); 15408f6c065Sgavinm static void istat_counter_reset_cb(struct istat_entry *entp, 15508f6c065Sgavinm struct stats *statp, const struct ipath *ipp); 156e5ba14ffSstephh static void istat_counter_topo_chg_cb(struct istat_entry *entp, 157e5ba14ffSstephh struct stats *statp, void *unused); 158b5016cbbSstephh static void serd_reset_cb(struct serd_entry *entp, void *unused, 159b5016cbbSstephh const struct ipath *ipp); 160e5ba14ffSstephh static void serd_topo_chg_cb(struct serd_entry *entp, void *unused, 161e5ba14ffSstephh void *unused2); 162b5016cbbSstephh static void destroy_fme_bufs(struct fme *fp); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static struct fme * 1657c478bd9Sstevel@tonic-gate alloc_fme(void) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate struct fme *fmep; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate fmep = MALLOC(sizeof (*fmep)); 1707c478bd9Sstevel@tonic-gate bzero(fmep, sizeof (*fmep)); 1717c478bd9Sstevel@tonic-gate return (fmep); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * fme_ready -- called when all initialization of the FME (except for 1767c478bd9Sstevel@tonic-gate * stats) has completed successfully. Adds the fme to global lists 1777c478bd9Sstevel@tonic-gate * and establishes its stats. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate static struct fme * 1807c478bd9Sstevel@tonic-gate fme_ready(struct fme *fmep) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate char nbuf[100]; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate Nfmep = NULL; /* don't need to free this on module abort now */ 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (EFMElist) { 1877c478bd9Sstevel@tonic-gate EFMElist->next = fmep; 1887c478bd9Sstevel@tonic-gate EFMElist = fmep; 1897c478bd9Sstevel@tonic-gate } else 1907c478bd9Sstevel@tonic-gate FMElist = EFMElist = fmep; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Rcount", fmep->id); 1937c478bd9Sstevel@tonic-gate fmep->Rcount = stats_new_counter(nbuf, "ereports received", 0); 1947c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Hcall", fmep->id); 1957c478bd9Sstevel@tonic-gate fmep->Hcallcount = stats_new_counter(nbuf, "calls to hypothesise()", 1); 1967c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Rcall", fmep->id); 1977c478bd9Sstevel@tonic-gate fmep->Rcallcount = stats_new_counter(nbuf, 1987c478bd9Sstevel@tonic-gate "calls to requirements_test()", 1); 1997c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Ccall", fmep->id); 2007c478bd9Sstevel@tonic-gate fmep->Ccallcount = stats_new_counter(nbuf, "calls to causes_test()", 1); 2017c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Ecall", fmep->id); 2027c478bd9Sstevel@tonic-gate fmep->Ecallcount = 2037c478bd9Sstevel@tonic-gate stats_new_counter(nbuf, "calls to effects_test()", 1); 2047c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Tcall", fmep->id); 2057c478bd9Sstevel@tonic-gate fmep->Tcallcount = stats_new_counter(nbuf, "calls to triggered()", 1); 2067c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Marrow", fmep->id); 2077c478bd9Sstevel@tonic-gate fmep->Marrowcount = stats_new_counter(nbuf, 2087c478bd9Sstevel@tonic-gate "arrows marked by mark_arrows()", 1); 2097c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.diags", fmep->id); 2107c478bd9Sstevel@tonic-gate fmep->diags = stats_new_counter(nbuf, "suspect lists diagnosed", 0); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB2, "newfme: config snapshot contains..."); 213e5ba14ffSstephh config_print(O_ALTFP|O_VERB2, fmep->config); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate return (fmep); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 218b5016cbbSstephh extern void ipath_dummy_lut(struct arrow *); 219b5016cbbSstephh extern struct lut *itree_create_dummy(const char *, const struct ipath *); 220b5016cbbSstephh 221b5016cbbSstephh /* ARGSUSED */ 222b5016cbbSstephh static void 223b5016cbbSstephh set_needed_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 224b5016cbbSstephh { 225b5016cbbSstephh struct bubble *bp; 226b5016cbbSstephh struct arrowlist *ap; 227b5016cbbSstephh 228b5016cbbSstephh for (bp = itree_next_bubble(ep, NULL); bp; 229b5016cbbSstephh bp = itree_next_bubble(ep, bp)) { 230b5016cbbSstephh if (bp->t != B_FROM) 231b5016cbbSstephh continue; 232b5016cbbSstephh for (ap = itree_next_arrow(bp, NULL); ap; 233b5016cbbSstephh ap = itree_next_arrow(bp, ap)) { 234b5016cbbSstephh ap->arrowp->pnode->u.arrow.needed = 1; 235b5016cbbSstephh ipath_dummy_lut(ap->arrowp); 236b5016cbbSstephh } 237b5016cbbSstephh } 238b5016cbbSstephh } 239b5016cbbSstephh 240b5016cbbSstephh /* ARGSUSED */ 241b5016cbbSstephh static void 242b5016cbbSstephh unset_needed_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 243b5016cbbSstephh { 244b5016cbbSstephh struct bubble *bp; 245b5016cbbSstephh struct arrowlist *ap; 246b5016cbbSstephh 247b5016cbbSstephh for (bp = itree_next_bubble(ep, NULL); bp; 248b5016cbbSstephh bp = itree_next_bubble(ep, bp)) { 249b5016cbbSstephh if (bp->t != B_FROM) 250b5016cbbSstephh continue; 251b5016cbbSstephh for (ap = itree_next_arrow(bp, NULL); ap; 252b5016cbbSstephh ap = itree_next_arrow(bp, ap)) 253b5016cbbSstephh ap->arrowp->pnode->u.arrow.needed = 0; 254b5016cbbSstephh } 255b5016cbbSstephh } 256b5016cbbSstephh 257b5016cbbSstephh static void globals_destructor(void *left, void *right, void *arg); 258b5016cbbSstephh static void clear_arrows(struct event *ep, struct event *ep2, struct fme *fmep); 259b5016cbbSstephh 260705e9f42SStephen Hanson static boolean_t 261b5016cbbSstephh prune_propagations(const char *e0class, const struct ipath *e0ipp) 262b5016cbbSstephh { 263b5016cbbSstephh char nbuf[100]; 264b5016cbbSstephh unsigned long long my_delay = TIMEVAL_EVENTUALLY; 265b5016cbbSstephh extern struct lut *Usednames; 266b5016cbbSstephh 267b5016cbbSstephh Nfmep = alloc_fme(); 268b5016cbbSstephh Nfmep->id = Nextid; 269b5016cbbSstephh Nfmep->state = FME_NOTHING; 270b5016cbbSstephh Nfmep->eventtree = itree_create_dummy(e0class, e0ipp); 271b5016cbbSstephh if ((Nfmep->e0 = 272b5016cbbSstephh itree_lookup(Nfmep->eventtree, e0class, e0ipp)) == NULL) { 273b5016cbbSstephh itree_free(Nfmep->eventtree); 274b5016cbbSstephh FREE(Nfmep); 275b5016cbbSstephh Nfmep = NULL; 276705e9f42SStephen Hanson return (B_FALSE); 277b5016cbbSstephh } 278b5016cbbSstephh Nfmep->ecurrent = Nfmep->observations = Nfmep->e0; 279b5016cbbSstephh Nfmep->e0->count++; 280b5016cbbSstephh 281b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Rcount", Nfmep->id); 282b5016cbbSstephh Nfmep->Rcount = stats_new_counter(nbuf, "ereports received", 0); 283b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Hcall", Nfmep->id); 284b5016cbbSstephh Nfmep->Hcallcount = 285b5016cbbSstephh stats_new_counter(nbuf, "calls to hypothesise()", 1); 286b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Rcall", Nfmep->id); 287b5016cbbSstephh Nfmep->Rcallcount = stats_new_counter(nbuf, 288b5016cbbSstephh "calls to requirements_test()", 1); 289b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Ccall", Nfmep->id); 290b5016cbbSstephh Nfmep->Ccallcount = 291b5016cbbSstephh stats_new_counter(nbuf, "calls to causes_test()", 1); 292b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Ecall", Nfmep->id); 293b5016cbbSstephh Nfmep->Ecallcount = 294b5016cbbSstephh stats_new_counter(nbuf, "calls to effects_test()", 1); 295b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Tcall", Nfmep->id); 296b5016cbbSstephh Nfmep->Tcallcount = stats_new_counter(nbuf, "calls to triggered()", 1); 297b5016cbbSstephh (void) sprintf(nbuf, "fme%d.Marrow", Nfmep->id); 298b5016cbbSstephh Nfmep->Marrowcount = stats_new_counter(nbuf, 299b5016cbbSstephh "arrows marked by mark_arrows()", 1); 300b5016cbbSstephh (void) sprintf(nbuf, "fme%d.diags", Nfmep->id); 301b5016cbbSstephh Nfmep->diags = stats_new_counter(nbuf, "suspect lists diagnosed", 0); 302b5016cbbSstephh 303b5016cbbSstephh Nfmep->peek = 1; 304b5016cbbSstephh lut_walk(Nfmep->eventtree, (lut_cb)unset_needed_arrows, (void *)Nfmep); 305b5016cbbSstephh lut_free(Usednames, NULL, NULL); 306b5016cbbSstephh Usednames = NULL; 307b5016cbbSstephh lut_walk(Nfmep->eventtree, (lut_cb)clear_arrows, (void *)Nfmep); 308b5016cbbSstephh (void) hypothesise(Nfmep, Nfmep->e0, Nfmep->ull, &my_delay); 309b5016cbbSstephh itree_prune(Nfmep->eventtree); 310b5016cbbSstephh lut_walk(Nfmep->eventtree, (lut_cb)set_needed_arrows, (void *)Nfmep); 311b5016cbbSstephh 312b5016cbbSstephh stats_delete(Nfmep->Rcount); 313b5016cbbSstephh stats_delete(Nfmep->Hcallcount); 314b5016cbbSstephh stats_delete(Nfmep->Rcallcount); 315b5016cbbSstephh stats_delete(Nfmep->Ccallcount); 316b5016cbbSstephh stats_delete(Nfmep->Ecallcount); 317b5016cbbSstephh stats_delete(Nfmep->Tcallcount); 318b5016cbbSstephh stats_delete(Nfmep->Marrowcount); 319b5016cbbSstephh stats_delete(Nfmep->diags); 320b5016cbbSstephh itree_free(Nfmep->eventtree); 321b5016cbbSstephh lut_free(Nfmep->globals, globals_destructor, NULL); 322b5016cbbSstephh FREE(Nfmep); 323705e9f42SStephen Hanson return (B_TRUE); 324b5016cbbSstephh } 325b5016cbbSstephh 3267c478bd9Sstevel@tonic-gate static struct fme * 327b5016cbbSstephh newfme(const char *e0class, const struct ipath *e0ipp, fmd_hdl_t *hdl, 328a3f6a2a4SRob Johnston fmd_case_t *fmcase, fmd_event_t *ffep, nvlist_t *nvl) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate struct cfgdata *cfgdata; 331b5016cbbSstephh int init_size; 332b5016cbbSstephh extern int alloc_total(); 333705e9f42SStephen Hanson nvlist_t *detector = NULL; 334705e9f42SStephen Hanson char *pathstr; 335705e9f42SStephen Hanson char *arg; 336705e9f42SStephen Hanson 337705e9f42SStephen Hanson /* 338705e9f42SStephen Hanson * First check if e0ipp is actually in the topology so we can give a 339705e9f42SStephen Hanson * more useful error message. 340705e9f42SStephen Hanson */ 341705e9f42SStephen Hanson ipathlastcomp(e0ipp); 342705e9f42SStephen Hanson pathstr = ipath2str(NULL, e0ipp); 343705e9f42SStephen Hanson cfgdata = config_snapshot(); 344*da40b264SAlex Wilson platform_unit_translate(0, cfgdata->cooked, TOPO_PROP_RESOURCE, 345705e9f42SStephen Hanson &detector, pathstr); 346705e9f42SStephen Hanson FREE(pathstr); 347705e9f42SStephen Hanson structconfig_free(cfgdata->cooked); 348705e9f42SStephen Hanson config_free(cfgdata); 349705e9f42SStephen Hanson if (detector == NULL) { 350f5961f52SAdrian Frost /* See if class permits silent discard on unknown component. */ 351f5961f52SAdrian Frost if (lut_lookup(Ereportenames_discard, (void *)e0class, NULL)) { 352f5961f52SAdrian Frost out(O_ALTFP|O_VERB2, "Unable to map \"%s\" ereport " 353f5961f52SAdrian Frost "to component path, but silent discard allowed.", 354f5961f52SAdrian Frost e0class); 355a3f6a2a4SRob Johnston fmd_case_close(hdl, fmcase); 356f5961f52SAdrian Frost } else { 357f5961f52SAdrian Frost Undiag_reason = UD_VAL_BADEVENTPATH; 358f5961f52SAdrian Frost (void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, 359f5961f52SAdrian Frost &detector); 360f5961f52SAdrian Frost arg = ipath2str(e0class, e0ipp); 361f5961f52SAdrian Frost publish_undiagnosable(hdl, ffep, fmcase, detector, arg); 362f5961f52SAdrian Frost FREE(arg); 363f5961f52SAdrian Frost } 364705e9f42SStephen Hanson return (NULL); 365705e9f42SStephen Hanson } 366705e9f42SStephen Hanson 367705e9f42SStephen Hanson /* 368705e9f42SStephen Hanson * Next run a quick first pass of the rules with a dummy config. This 369705e9f42SStephen Hanson * allows us to prune those rules which can't possibly cause this 370705e9f42SStephen Hanson * ereport. 371705e9f42SStephen Hanson */ 372705e9f42SStephen Hanson if (!prune_propagations(e0class, e0ipp)) { 373705e9f42SStephen Hanson /* 374705e9f42SStephen Hanson * The fault class must have been in the rules or we would 375705e9f42SStephen Hanson * not have registered for it (and got a "nosub"), and the 376705e9f42SStephen Hanson * pathname must be in the topology or we would have failed the 377705e9f42SStephen Hanson * previous test. So to get here means the combination of 378705e9f42SStephen Hanson * class and pathname in the ereport must be invalid. 379705e9f42SStephen Hanson */ 380705e9f42SStephen Hanson Undiag_reason = UD_VAL_BADEVENTCLASS; 381705e9f42SStephen Hanson arg = ipath2str(e0class, e0ipp); 382705e9f42SStephen Hanson publish_undiagnosable(hdl, ffep, fmcase, detector, arg); 383705e9f42SStephen Hanson nvlist_free(detector); 384705e9f42SStephen Hanson FREE(arg); 385705e9f42SStephen Hanson return (NULL); 386705e9f42SStephen Hanson } 3877c478bd9Sstevel@tonic-gate 388705e9f42SStephen Hanson /* 389705e9f42SStephen Hanson * Now go ahead and create the real fme using the pruned rules. 390705e9f42SStephen Hanson */ 391b5016cbbSstephh init_size = alloc_total(); 392b5016cbbSstephh out(O_ALTFP|O_STAMP, "start config_snapshot using %d bytes", init_size); 39335f59e50SStephen Hanson nvlist_free(detector); 39435f59e50SStephen Hanson pathstr = ipath2str(NULL, e0ipp); 39532d4e834STarik Soydan cfgdata = config_snapshot(); 396*da40b264SAlex Wilson platform_unit_translate(0, cfgdata->cooked, TOPO_PROP_RESOURCE, 39735f59e50SStephen Hanson &detector, pathstr); 39835f59e50SStephen Hanson FREE(pathstr); 399b5016cbbSstephh platform_save_config(hdl, fmcase); 400b5016cbbSstephh out(O_ALTFP|O_STAMP, "config_snapshot added %d bytes", 401b5016cbbSstephh alloc_total() - init_size); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate Nfmep = alloc_fme(); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate Nfmep->id = Nextid++; 406e5ba14ffSstephh Nfmep->config = cfgdata->cooked; 407e5ba14ffSstephh config_free(cfgdata); 4087c478bd9Sstevel@tonic-gate Nfmep->posted_suspects = 0; 4097c478bd9Sstevel@tonic-gate Nfmep->uniqobs = 0; 4107c478bd9Sstevel@tonic-gate Nfmep->state = FME_NOTHING; 4117c478bd9Sstevel@tonic-gate Nfmep->pull = 0ULL; 4120cc1f05eSjrutt Nfmep->overflow = 0; 4137c478bd9Sstevel@tonic-gate 414b5016cbbSstephh Nfmep->fmcase = fmcase; 415b5016cbbSstephh Nfmep->hdl = hdl; 4167c478bd9Sstevel@tonic-gate 417e5ba14ffSstephh if ((Nfmep->eventtree = itree_create(Nfmep->config)) == NULL) { 41832d4e834STarik Soydan Undiag_reason = UD_VAL_INSTFAIL; 419705e9f42SStephen Hanson arg = ipath2str(e0class, e0ipp); 420705e9f42SStephen Hanson publish_undiagnosable(hdl, ffep, fmcase, detector, arg); 421705e9f42SStephen Hanson nvlist_free(detector); 422705e9f42SStephen Hanson FREE(arg); 423e5ba14ffSstephh structconfig_free(Nfmep->config); 424b5016cbbSstephh destroy_fme_bufs(Nfmep); 4257c478bd9Sstevel@tonic-gate FREE(Nfmep); 4267c478bd9Sstevel@tonic-gate Nfmep = NULL; 4277c478bd9Sstevel@tonic-gate return (NULL); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate itree_ptree(O_ALTFP|O_VERB2, Nfmep->eventtree); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if ((Nfmep->e0 = 4337c478bd9Sstevel@tonic-gate itree_lookup(Nfmep->eventtree, e0class, e0ipp)) == NULL) { 43432d4e834STarik Soydan Undiag_reason = UD_VAL_BADEVENTI; 435705e9f42SStephen Hanson arg = ipath2str(e0class, e0ipp); 436705e9f42SStephen Hanson publish_undiagnosable(hdl, ffep, fmcase, detector, arg); 437705e9f42SStephen Hanson nvlist_free(detector); 438705e9f42SStephen Hanson FREE(arg); 4397c478bd9Sstevel@tonic-gate itree_free(Nfmep->eventtree); 440e5ba14ffSstephh structconfig_free(Nfmep->config); 441b5016cbbSstephh destroy_fme_bufs(Nfmep); 4427c478bd9Sstevel@tonic-gate FREE(Nfmep); 4437c478bd9Sstevel@tonic-gate Nfmep = NULL; 4447c478bd9Sstevel@tonic-gate return (NULL); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 447705e9f42SStephen Hanson nvlist_free(detector); 4487c478bd9Sstevel@tonic-gate return (fme_ready(Nfmep)); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate void 4527c478bd9Sstevel@tonic-gate fme_fini(void) 4537c478bd9Sstevel@tonic-gate { 4547c478bd9Sstevel@tonic-gate struct fme *sfp, *fp; 4557c478bd9Sstevel@tonic-gate struct case_list *ucasep, *nextcasep; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate ucasep = Undiagablecaselist; 4587c478bd9Sstevel@tonic-gate while (ucasep != NULL) { 4597c478bd9Sstevel@tonic-gate nextcasep = ucasep->next; 4607c478bd9Sstevel@tonic-gate FREE(ucasep); 4617c478bd9Sstevel@tonic-gate ucasep = nextcasep; 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate Undiagablecaselist = NULL; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* clean up closed fmes */ 4667c478bd9Sstevel@tonic-gate fp = ClosedFMEs; 4677c478bd9Sstevel@tonic-gate while (fp != NULL) { 4687c478bd9Sstevel@tonic-gate sfp = fp->next; 4697c478bd9Sstevel@tonic-gate destroy_fme(fp); 4707c478bd9Sstevel@tonic-gate fp = sfp; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate ClosedFMEs = NULL; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate fp = FMElist; 4757c478bd9Sstevel@tonic-gate while (fp != NULL) { 4767c478bd9Sstevel@tonic-gate sfp = fp->next; 4777c478bd9Sstevel@tonic-gate destroy_fme(fp); 4787c478bd9Sstevel@tonic-gate fp = sfp; 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate FMElist = EFMElist = NULL; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* if we were in the middle of creating an fme, free it now */ 4837c478bd9Sstevel@tonic-gate if (Nfmep) { 4847c478bd9Sstevel@tonic-gate destroy_fme(Nfmep); 4857c478bd9Sstevel@tonic-gate Nfmep = NULL; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* 4907c478bd9Sstevel@tonic-gate * Allocated space for a buffer name. 20 bytes allows for 4917c478bd9Sstevel@tonic-gate * a ridiculous 9,999,999 unique observations. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate #define OBBUFNMSZ 20 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * serialize_observation 4977c478bd9Sstevel@tonic-gate * 4987c478bd9Sstevel@tonic-gate * Create a recoverable version of the current observation 4997c478bd9Sstevel@tonic-gate * (f->ecurrent). We keep a serialized version of each unique 5007c478bd9Sstevel@tonic-gate * observation in order that we may resume correctly the fme in the 5017c478bd9Sstevel@tonic-gate * correct state if eft or fmd crashes and we're restarted. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate static void 5047c478bd9Sstevel@tonic-gate serialize_observation(struct fme *fp, const char *cls, const struct ipath *ipp) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate size_t pkdlen; 5077c478bd9Sstevel@tonic-gate char tmpbuf[OBBUFNMSZ]; 5087c478bd9Sstevel@tonic-gate char *pkd = NULL; 5097c478bd9Sstevel@tonic-gate char *estr; 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", fp->uniqobs); 5127c478bd9Sstevel@tonic-gate estr = ipath2str(cls, ipp); 5137c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, strlen(estr) + 1); 5147c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)estr, 5157c478bd9Sstevel@tonic-gate strlen(estr) + 1); 5167c478bd9Sstevel@tonic-gate FREE(estr); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate if (fp->ecurrent != NULL && fp->ecurrent->nvp != NULL) { 5197c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, 5207c478bd9Sstevel@tonic-gate OBBUFNMSZ, "observed%d.nvp", fp->uniqobs); 5217c478bd9Sstevel@tonic-gate if (nvlist_xpack(fp->ecurrent->nvp, 5227c478bd9Sstevel@tonic-gate &pkd, &pkdlen, NV_ENCODE_XDR, &Eft_nv_hdl) != 0) 5237c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "pack of observed nvl failed"); 5247c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, pkdlen); 5257c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)pkd, pkdlen); 5267c478bd9Sstevel@tonic-gate FREE(pkd); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate fp->uniqobs++; 5307c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 5317c478bd9Sstevel@tonic-gate sizeof (fp->uniqobs)); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * init_fme_bufs -- We keep several bits of state about an fme for 5367c478bd9Sstevel@tonic-gate * use if eft or fmd crashes and we're restarted. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate static void 5397c478bd9Sstevel@tonic-gate init_fme_bufs(struct fme *fp) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_PULL, sizeof (fp->pull)); 5427c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_PULL, (void *)&fp->pull, 5437c478bd9Sstevel@tonic-gate sizeof (fp->pull)); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_ID, sizeof (fp->id)); 5467c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_ID, (void *)&fp->id, 5477c478bd9Sstevel@tonic-gate sizeof (fp->id)); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_NOBS, sizeof (fp->uniqobs)); 5507c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 5517c478bd9Sstevel@tonic-gate sizeof (fp->uniqobs)); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_POSTD, 5547c478bd9Sstevel@tonic-gate sizeof (fp->posted_suspects)); 5557c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_POSTD, 5567c478bd9Sstevel@tonic-gate (void *)&fp->posted_suspects, sizeof (fp->posted_suspects)); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate static void 5607c478bd9Sstevel@tonic-gate destroy_fme_bufs(struct fme *fp) 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate char tmpbuf[OBBUFNMSZ]; 5637c478bd9Sstevel@tonic-gate int o; 5647c478bd9Sstevel@tonic-gate 565b5016cbbSstephh platform_restore_config(fp->hdl, fp->fmcase); 5667c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFGLEN); 5677c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFG); 5687c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_PULL); 5697c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_ID); 5707c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_POSTD); 5717c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_NOBS); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate for (o = 0; o < fp->uniqobs; o++) { 5747c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", o); 5757c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 5767c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", o); 5777c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 5827c478bd9Sstevel@tonic-gate * reconstitute_observations -- convert a case's serialized observations 5837c478bd9Sstevel@tonic-gate * back into struct events. Returns zero if all observations are 5847c478bd9Sstevel@tonic-gate * successfully reconstituted. 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate static int 5877c478bd9Sstevel@tonic-gate reconstitute_observations(struct fme *fmep) 5887c478bd9Sstevel@tonic-gate { 5897c478bd9Sstevel@tonic-gate struct event *ep; 5907c478bd9Sstevel@tonic-gate struct node *epnamenp = NULL; 5917c478bd9Sstevel@tonic-gate size_t pkdlen; 5927c478bd9Sstevel@tonic-gate char *pkd = NULL; 5937c478bd9Sstevel@tonic-gate char *tmpbuf = alloca(OBBUFNMSZ); 5947c478bd9Sstevel@tonic-gate char *sepptr; 5957c478bd9Sstevel@tonic-gate char *estr; 5967c478bd9Sstevel@tonic-gate int ocnt; 5977c478bd9Sstevel@tonic-gate int elen; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate for (ocnt = 0; ocnt < fmep->uniqobs; ocnt++) { 6007c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", ocnt); 6017c478bd9Sstevel@tonic-gate elen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 6027c478bd9Sstevel@tonic-gate if (elen == 0) { 6037c478bd9Sstevel@tonic-gate out(O_ALTFP, 6047c478bd9Sstevel@tonic-gate "reconstitute_observation: no %s buffer found.", 6057c478bd9Sstevel@tonic-gate tmpbuf); 60632d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGOBS; 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate estr = MALLOC(elen); 6117c478bd9Sstevel@tonic-gate fmd_buf_read(fmep->hdl, fmep->fmcase, tmpbuf, estr, elen); 6127c478bd9Sstevel@tonic-gate sepptr = strchr(estr, '@'); 6137c478bd9Sstevel@tonic-gate if (sepptr == NULL) { 6147c478bd9Sstevel@tonic-gate out(O_ALTFP, 6157c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 6167c478bd9Sstevel@tonic-gate "missing @ separator in %s.", 6177c478bd9Sstevel@tonic-gate tmpbuf, estr); 61832d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGPATH; 6197c478bd9Sstevel@tonic-gate FREE(estr); 6207c478bd9Sstevel@tonic-gate break; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate *sepptr = '\0'; 6247c478bd9Sstevel@tonic-gate if ((epnamenp = pathstring2epnamenp(sepptr + 1)) == NULL) { 6257c478bd9Sstevel@tonic-gate out(O_ALTFP, 6267c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 6277c478bd9Sstevel@tonic-gate "trouble converting path string \"%s\" " 6287c478bd9Sstevel@tonic-gate "to internal representation.", 6297c478bd9Sstevel@tonic-gate tmpbuf, sepptr + 1); 63032d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGPATH; 6317c478bd9Sstevel@tonic-gate FREE(estr); 6327c478bd9Sstevel@tonic-gate break; 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate /* construct the event */ 6367c478bd9Sstevel@tonic-gate ep = itree_lookup(fmep->eventtree, 6377c478bd9Sstevel@tonic-gate stable(estr), ipath(epnamenp)); 6387c478bd9Sstevel@tonic-gate if (ep == NULL) { 6397c478bd9Sstevel@tonic-gate out(O_ALTFP, 6407c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 6417c478bd9Sstevel@tonic-gate "lookup of \"%s\" in itree failed.", 6427c478bd9Sstevel@tonic-gate tmpbuf, ipath2str(estr, ipath(epnamenp))); 64332d4e834STarik Soydan Undiag_reason = UD_VAL_BADOBS; 6447c478bd9Sstevel@tonic-gate tree_free(epnamenp); 6457c478bd9Sstevel@tonic-gate FREE(estr); 6467c478bd9Sstevel@tonic-gate break; 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate tree_free(epnamenp); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * We may or may not have a saved nvlist for the observation 6527c478bd9Sstevel@tonic-gate */ 6537c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", ocnt); 6547c478bd9Sstevel@tonic-gate pkdlen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 6557c478bd9Sstevel@tonic-gate if (pkdlen != 0) { 6567c478bd9Sstevel@tonic-gate pkd = MALLOC(pkdlen); 6577c478bd9Sstevel@tonic-gate fmd_buf_read(fmep->hdl, 6587c478bd9Sstevel@tonic-gate fmep->fmcase, tmpbuf, pkd, pkdlen); 6597aec1d6eScindi ASSERT(ep->nvp == NULL); 6607c478bd9Sstevel@tonic-gate if (nvlist_xunpack(pkd, 6617c478bd9Sstevel@tonic-gate pkdlen, &ep->nvp, &Eft_nv_hdl) != 0) 6627c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "pack of observed nvl failed"); 6637c478bd9Sstevel@tonic-gate FREE(pkd); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (ocnt == 0) 6677c478bd9Sstevel@tonic-gate fmep->e0 = ep; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate FREE(estr); 6707c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 6717c478bd9Sstevel@tonic-gate ep->count++; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 6747c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 6757c478bd9Sstevel@tonic-gate fmep->observations = ep; 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if (ocnt == fmep->uniqobs) { 6797c478bd9Sstevel@tonic-gate (void) fme_ready(fmep); 6807c478bd9Sstevel@tonic-gate return (0); 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate return (1); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* 6877c478bd9Sstevel@tonic-gate * restart_fme -- called during eft initialization. Reconstitutes 6887c478bd9Sstevel@tonic-gate * an in-progress fme. 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate void 6917c478bd9Sstevel@tonic-gate fme_restart(fmd_hdl_t *hdl, fmd_case_t *inprogress) 6927c478bd9Sstevel@tonic-gate { 6937c478bd9Sstevel@tonic-gate nvlist_t *defect; 6947c478bd9Sstevel@tonic-gate struct case_list *bad; 6957c478bd9Sstevel@tonic-gate struct fme *fmep; 696e5ba14ffSstephh struct cfgdata *cfgdata; 6977c478bd9Sstevel@tonic-gate size_t rawsz; 698b5016cbbSstephh struct event *ep; 699b5016cbbSstephh char *tmpbuf = alloca(OBBUFNMSZ); 700b5016cbbSstephh char *sepptr; 701b5016cbbSstephh char *estr; 702b5016cbbSstephh int elen; 703b5016cbbSstephh struct node *epnamenp = NULL; 704b5016cbbSstephh int init_size; 705b5016cbbSstephh extern int alloc_total(); 706705e9f42SStephen Hanson char *reason; 707b5016cbbSstephh 708b5016cbbSstephh /* 709b5016cbbSstephh * ignore solved or closed cases 710b5016cbbSstephh */ 711b5016cbbSstephh if (fmd_case_solved(hdl, inprogress) || 712b5016cbbSstephh fmd_case_closed(hdl, inprogress)) 713b5016cbbSstephh return; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate fmep = alloc_fme(); 7167c478bd9Sstevel@tonic-gate fmep->fmcase = inprogress; 7177c478bd9Sstevel@tonic-gate fmep->hdl = hdl; 7187c478bd9Sstevel@tonic-gate 7199f8ca725Sstephh if (fmd_buf_size(hdl, inprogress, WOBUF_POSTD) == 0) { 7209f8ca725Sstephh out(O_ALTFP, "restart_fme: no saved posted status"); 72132d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGINFO; 7229f8ca725Sstephh goto badcase; 7239f8ca725Sstephh } else { 7249f8ca725Sstephh fmd_buf_read(hdl, inprogress, WOBUF_POSTD, 7259f8ca725Sstephh (void *)&fmep->posted_suspects, 7269f8ca725Sstephh sizeof (fmep->posted_suspects)); 7279f8ca725Sstephh } 7289f8ca725Sstephh 729b5016cbbSstephh if (fmd_buf_size(hdl, inprogress, WOBUF_ID) == 0) { 730b5016cbbSstephh out(O_ALTFP, "restart_fme: no saved id"); 73132d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGINFO; 7329f8ca725Sstephh goto badcase; 733b5016cbbSstephh } else { 734b5016cbbSstephh fmd_buf_read(hdl, inprogress, WOBUF_ID, (void *)&fmep->id, 735b5016cbbSstephh sizeof (fmep->id)); 736b5016cbbSstephh } 737b5016cbbSstephh if (Nextid <= fmep->id) 738b5016cbbSstephh Nextid = fmep->id + 1; 739b5016cbbSstephh 740b5016cbbSstephh out(O_ALTFP, "Replay FME %d", fmep->id); 7419f8ca725Sstephh 7427c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_CFGLEN) != sizeof (size_t)) { 7437c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: No config data"); 74432d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGINFO; 7457c478bd9Sstevel@tonic-gate goto badcase; 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_CFGLEN, (void *)&rawsz, 7487c478bd9Sstevel@tonic-gate sizeof (size_t)); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate if ((fmep->e0r = fmd_case_getprincipal(hdl, inprogress)) == NULL) { 7517c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: No event zero"); 75232d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGZERO; 7537c478bd9Sstevel@tonic-gate goto badcase; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 756b5016cbbSstephh if (fmd_buf_size(hdl, inprogress, WOBUF_PULL) == 0) { 757b5016cbbSstephh out(O_ALTFP, "restart_fme: no saved wait time"); 75832d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGINFO; 759b5016cbbSstephh goto badcase; 760b5016cbbSstephh } else { 761b5016cbbSstephh fmd_buf_read(hdl, inprogress, WOBUF_PULL, (void *)&fmep->pull, 762b5016cbbSstephh sizeof (fmep->pull)); 763b5016cbbSstephh } 764b5016cbbSstephh 765b5016cbbSstephh if (fmd_buf_size(hdl, inprogress, WOBUF_NOBS) == 0) { 766b5016cbbSstephh out(O_ALTFP, "restart_fme: no count of observations"); 76732d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGINFO; 768b5016cbbSstephh goto badcase; 769b5016cbbSstephh } else { 770b5016cbbSstephh fmd_buf_read(hdl, inprogress, WOBUF_NOBS, 771b5016cbbSstephh (void *)&fmep->uniqobs, sizeof (fmep->uniqobs)); 772b5016cbbSstephh } 773b5016cbbSstephh 774b5016cbbSstephh (void) snprintf(tmpbuf, OBBUFNMSZ, "observed0"); 775b5016cbbSstephh elen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 776b5016cbbSstephh if (elen == 0) { 777b5016cbbSstephh out(O_ALTFP, "reconstitute_observation: no %s buffer found.", 778b5016cbbSstephh tmpbuf); 77932d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGOBS; 780b5016cbbSstephh goto badcase; 781b5016cbbSstephh } 782b5016cbbSstephh estr = MALLOC(elen); 783b5016cbbSstephh fmd_buf_read(fmep->hdl, fmep->fmcase, tmpbuf, estr, elen); 784b5016cbbSstephh sepptr = strchr(estr, '@'); 785b5016cbbSstephh if (sepptr == NULL) { 786b5016cbbSstephh out(O_ALTFP, "reconstitute_observation: %s: " 787b5016cbbSstephh "missing @ separator in %s.", 788b5016cbbSstephh tmpbuf, estr); 78932d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGPATH; 790b5016cbbSstephh FREE(estr); 791b5016cbbSstephh goto badcase; 792b5016cbbSstephh } 793b5016cbbSstephh *sepptr = '\0'; 794b5016cbbSstephh if ((epnamenp = pathstring2epnamenp(sepptr + 1)) == NULL) { 795b5016cbbSstephh out(O_ALTFP, "reconstitute_observation: %s: " 796b5016cbbSstephh "trouble converting path string \"%s\" " 797b5016cbbSstephh "to internal representation.", tmpbuf, sepptr + 1); 79832d4e834STarik Soydan Undiag_reason = UD_VAL_MISSINGPATH; 799b5016cbbSstephh FREE(estr); 800b5016cbbSstephh goto badcase; 801b5016cbbSstephh } 802705e9f42SStephen Hanson (void) prune_propagations(stable(estr), ipath(epnamenp)); 803b5016cbbSstephh tree_free(epnamenp); 804b5016cbbSstephh FREE(estr); 805b5016cbbSstephh 806b5016cbbSstephh init_size = alloc_total(); 807b5016cbbSstephh out(O_ALTFP|O_STAMP, "start config_restore using %d bytes", init_size); 8087c478bd9Sstevel@tonic-gate cfgdata = MALLOC(sizeof (struct cfgdata)); 8097c478bd9Sstevel@tonic-gate cfgdata->cooked = NULL; 8107c478bd9Sstevel@tonic-gate cfgdata->devcache = NULL; 811602ca9eaScth cfgdata->devidcache = NULL; 81244ed9dbbSStephen Hanson cfgdata->tpcache = NULL; 8137c478bd9Sstevel@tonic-gate cfgdata->cpucache = NULL; 814b5016cbbSstephh cfgdata->raw_refcnt = 1; 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate if (rawsz > 0) { 8177c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_CFG) != rawsz) { 8187c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: Config data size mismatch"); 81932d4e834STarik Soydan Undiag_reason = UD_VAL_CFGMISMATCH; 8207c478bd9Sstevel@tonic-gate goto badcase; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate cfgdata->begin = MALLOC(rawsz); 8237c478bd9Sstevel@tonic-gate cfgdata->end = cfgdata->nextfree = cfgdata->begin + rawsz; 8247c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, 8257c478bd9Sstevel@tonic-gate inprogress, WOBUF_CFG, cfgdata->begin, rawsz); 8267c478bd9Sstevel@tonic-gate } else { 8277c478bd9Sstevel@tonic-gate cfgdata->begin = cfgdata->end = cfgdata->nextfree = NULL; 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate config_cook(cfgdata); 831e5ba14ffSstephh fmep->config = cfgdata->cooked; 832e5ba14ffSstephh config_free(cfgdata); 833b5016cbbSstephh out(O_ALTFP|O_STAMP, "config_restore added %d bytes", 834b5016cbbSstephh alloc_total() - init_size); 835b5016cbbSstephh 836e5ba14ffSstephh if ((fmep->eventtree = itree_create(fmep->config)) == NULL) { 8377c478bd9Sstevel@tonic-gate /* case not properly saved or irretrievable */ 8387c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: NULL instance tree"); 83932d4e834STarik Soydan Undiag_reason = UD_VAL_INSTFAIL; 8407c478bd9Sstevel@tonic-gate goto badcase; 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate itree_ptree(O_ALTFP|O_VERB2, fmep->eventtree); 8447c478bd9Sstevel@tonic-gate 845b5016cbbSstephh if (reconstitute_observations(fmep) != 0) 8467c478bd9Sstevel@tonic-gate goto badcase; 8477c478bd9Sstevel@tonic-gate 848b5016cbbSstephh out(O_ALTFP|O_NONL, "FME %d replay observations: ", fmep->id); 849b5016cbbSstephh for (ep = fmep->observations; ep; ep = ep->observations) { 850b5016cbbSstephh out(O_ALTFP|O_NONL, " "); 851b5016cbbSstephh itree_pevent_brief(O_ALTFP|O_NONL, ep); 8527c478bd9Sstevel@tonic-gate } 853b5016cbbSstephh out(O_ALTFP, NULL); 8547c478bd9Sstevel@tonic-gate 8550cc1f05eSjrutt Open_fme_count++; 8560cc1f05eSjrutt 8577c478bd9Sstevel@tonic-gate /* give the diagnosis algorithm a shot at the new FME state */ 8589f8ca725Sstephh fme_eval(fmep, fmep->e0r); 8597c478bd9Sstevel@tonic-gate return; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate badcase: 8627c478bd9Sstevel@tonic-gate if (fmep->eventtree != NULL) 8637c478bd9Sstevel@tonic-gate itree_free(fmep->eventtree); 864e5ba14ffSstephh if (fmep->config) 865e5ba14ffSstephh structconfig_free(fmep->config); 8667c478bd9Sstevel@tonic-gate destroy_fme_bufs(fmep); 8677c478bd9Sstevel@tonic-gate FREE(fmep); 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * Since we're unable to restart the case, add it to the undiagable 8717c478bd9Sstevel@tonic-gate * list and solve and close it as appropriate. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate bad = MALLOC(sizeof (struct case_list)); 8747c478bd9Sstevel@tonic-gate bad->next = NULL; 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (Undiagablecaselist != NULL) 8777c478bd9Sstevel@tonic-gate bad->next = Undiagablecaselist; 8787c478bd9Sstevel@tonic-gate Undiagablecaselist = bad; 8797c478bd9Sstevel@tonic-gate bad->fmcase = inprogress; 8807c478bd9Sstevel@tonic-gate 8819f8ca725Sstephh out(O_ALTFP|O_NONL, "[case %s (unable to restart), ", 8827c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, bad->fmcase)); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate if (fmd_case_solved(hdl, bad->fmcase)) { 8859f8ca725Sstephh out(O_ALTFP|O_NONL, "already solved, "); 8867c478bd9Sstevel@tonic-gate } else { 8879f8ca725Sstephh out(O_ALTFP|O_NONL, "solving, "); 88832d4e834STarik Soydan defect = fmd_nvl_create_fault(hdl, 88932d4e834STarik Soydan undiag_2defect_str(Undiag_reason), 100, NULL, NULL, NULL); 890705e9f42SStephen Hanson reason = undiag_2reason_str(Undiag_reason, NULL); 891705e9f42SStephen Hanson (void) nvlist_add_string(defect, UNDIAG_REASON, reason); 892705e9f42SStephen Hanson FREE(reason); 8937c478bd9Sstevel@tonic-gate fmd_case_add_suspect(hdl, bad->fmcase, defect); 8947c478bd9Sstevel@tonic-gate fmd_case_solve(hdl, bad->fmcase); 89532d4e834STarik Soydan Undiag_reason = UD_VAL_UNKNOWN; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate if (fmd_case_closed(hdl, bad->fmcase)) { 8997c478bd9Sstevel@tonic-gate out(O_ALTFP, "already closed ]"); 9007c478bd9Sstevel@tonic-gate } else { 9017c478bd9Sstevel@tonic-gate out(O_ALTFP, "closing ]"); 9027c478bd9Sstevel@tonic-gate fmd_case_close(hdl, bad->fmcase); 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate 9067aec1d6eScindi /*ARGSUSED*/ 9077aec1d6eScindi static void 9087aec1d6eScindi globals_destructor(void *left, void *right, void *arg) 9097aec1d6eScindi { 9107aec1d6eScindi struct evalue *evp = (struct evalue *)right; 9117aec1d6eScindi if (evp->t == NODEPTR) 91280ab886dSwesolows tree_free((struct node *)(uintptr_t)evp->v); 913837416c3Scy evp->v = (uintptr_t)NULL; 9147aec1d6eScindi FREE(evp); 9157aec1d6eScindi } 9167aec1d6eScindi 9177c478bd9Sstevel@tonic-gate void 9187c478bd9Sstevel@tonic-gate destroy_fme(struct fme *f) 9197c478bd9Sstevel@tonic-gate { 9207c478bd9Sstevel@tonic-gate stats_delete(f->Rcount); 9217c478bd9Sstevel@tonic-gate stats_delete(f->Hcallcount); 9227c478bd9Sstevel@tonic-gate stats_delete(f->Rcallcount); 9237c478bd9Sstevel@tonic-gate stats_delete(f->Ccallcount); 9247c478bd9Sstevel@tonic-gate stats_delete(f->Ecallcount); 9257c478bd9Sstevel@tonic-gate stats_delete(f->Tcallcount); 9267c478bd9Sstevel@tonic-gate stats_delete(f->Marrowcount); 9277c478bd9Sstevel@tonic-gate stats_delete(f->diags); 9287c478bd9Sstevel@tonic-gate 9299f8ca725Sstephh if (f->eventtree != NULL) 9309f8ca725Sstephh itree_free(f->eventtree); 931e5ba14ffSstephh if (f->config) 932e5ba14ffSstephh structconfig_free(f->config); 9337aec1d6eScindi lut_free(f->globals, globals_destructor, NULL); 9347c478bd9Sstevel@tonic-gate FREE(f); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate static const char * 9387c478bd9Sstevel@tonic-gate fme_state2str(enum fme_state s) 9397c478bd9Sstevel@tonic-gate { 9407c478bd9Sstevel@tonic-gate switch (s) { 9417c478bd9Sstevel@tonic-gate case FME_NOTHING: return ("NOTHING"); 9427c478bd9Sstevel@tonic-gate case FME_WAIT: return ("WAIT"); 9437c478bd9Sstevel@tonic-gate case FME_CREDIBLE: return ("CREDIBLE"); 9447c478bd9Sstevel@tonic-gate case FME_DISPROVED: return ("DISPROVED"); 9457aec1d6eScindi case FME_DEFERRED: return ("DEFERRED"); 9467c478bd9Sstevel@tonic-gate default: return ("UNKNOWN"); 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate static int 9517c478bd9Sstevel@tonic-gate is_problem(enum nametype t) 9527c478bd9Sstevel@tonic-gate { 9537c478bd9Sstevel@tonic-gate return (t == N_FAULT || t == N_DEFECT || t == N_UPSET); 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate static int 9577c478bd9Sstevel@tonic-gate is_defect(enum nametype t) 9587c478bd9Sstevel@tonic-gate { 9597c478bd9Sstevel@tonic-gate return (t == N_DEFECT); 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate static int 9637c478bd9Sstevel@tonic-gate is_upset(enum nametype t) 9647c478bd9Sstevel@tonic-gate { 9657c478bd9Sstevel@tonic-gate return (t == N_UPSET); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate static void 9697c478bd9Sstevel@tonic-gate fme_print(int flags, struct fme *fmep) 9707c478bd9Sstevel@tonic-gate { 9717c478bd9Sstevel@tonic-gate struct event *ep; 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate out(flags, "Fault Management Exercise %d", fmep->id); 9747c478bd9Sstevel@tonic-gate out(flags, "\t State: %s", fme_state2str(fmep->state)); 9757c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t Start time: "); 9767c478bd9Sstevel@tonic-gate ptree_timeval(flags|O_NONL, &fmep->ull); 9777c478bd9Sstevel@tonic-gate out(flags, NULL); 9787c478bd9Sstevel@tonic-gate if (fmep->wull) { 9797c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t Wait time: "); 9807c478bd9Sstevel@tonic-gate ptree_timeval(flags|O_NONL, &fmep->wull); 9817c478bd9Sstevel@tonic-gate out(flags, NULL); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t E0: "); 9847c478bd9Sstevel@tonic-gate if (fmep->e0) 9857c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, fmep->e0); 9867c478bd9Sstevel@tonic-gate else 9877c478bd9Sstevel@tonic-gate out(flags|O_NONL, "NULL"); 9887c478bd9Sstevel@tonic-gate out(flags, NULL); 9897c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\tObservations:"); 9907c478bd9Sstevel@tonic-gate for (ep = fmep->observations; ep; ep = ep->observations) { 9917c478bd9Sstevel@tonic-gate out(flags|O_NONL, " "); 9927c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, ep); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate out(flags, NULL); 9957c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\tSuspect list:"); 9967c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 9977c478bd9Sstevel@tonic-gate out(flags|O_NONL, " "); 9987c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, ep); 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate out(flags, NULL); 10019f8ca725Sstephh if (fmep->eventtree != NULL) { 10029f8ca725Sstephh out(flags|O_VERB2, "\t Tree:"); 10039f8ca725Sstephh itree_ptree(flags|O_VERB2, fmep->eventtree); 10049f8ca725Sstephh } 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate static struct node * 10087c478bd9Sstevel@tonic-gate pathstring2epnamenp(char *path) 10097c478bd9Sstevel@tonic-gate { 10107c478bd9Sstevel@tonic-gate char *sep = "/"; 10117c478bd9Sstevel@tonic-gate struct node *ret; 10127c478bd9Sstevel@tonic-gate char *ptr; 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if ((ptr = strtok(path, sep)) == NULL) 10157c478bd9Sstevel@tonic-gate out(O_DIE, "pathstring2epnamenp: invalid empty class"); 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate ret = tree_iname(stable(ptr), NULL, 0); 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate while ((ptr = strtok(NULL, sep)) != NULL) 10207c478bd9Sstevel@tonic-gate ret = tree_name_append(ret, 10217c478bd9Sstevel@tonic-gate tree_iname(stable(ptr), NULL, 0)); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate return (ret); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * for a given upset sp, increment the corresponding SERD engine. if the 10287c478bd9Sstevel@tonic-gate * SERD engine trips, return the ename and ipp of the resulting ereport. 10297c478bd9Sstevel@tonic-gate * returns true if engine tripped and *enamep and *ippp were filled in. 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate static int 10327aec1d6eScindi serd_eval(struct fme *fmep, fmd_hdl_t *hdl, fmd_event_t *ffep, 10337aec1d6eScindi fmd_case_t *fmcase, struct event *sp, const char **enamep, 10347aec1d6eScindi const struct ipath **ippp) 10357c478bd9Sstevel@tonic-gate { 10367c478bd9Sstevel@tonic-gate struct node *serdinst; 10377c478bd9Sstevel@tonic-gate char *serdname; 1038049e2ea4SScott Davenport char *serdresource; 10398e7248e5SStephen Hanson char *serdclass; 10407aec1d6eScindi struct node *nid; 1041b5016cbbSstephh struct serd_entry *newentp; 1042049e2ea4SScott Davenport int i, serdn = -1, serdincrement = 1, len = 0; 10438e7248e5SStephen Hanson char *serdsuffix = NULL, *serdt = NULL; 1044b7d3956bSstephh struct evalue *ep; 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate ASSERT(sp->t == N_UPSET); 10477c478bd9Sstevel@tonic-gate ASSERT(ffep != NULL); 10487c478bd9Sstevel@tonic-gate 1049b7d3956bSstephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 1050b7d3956bSstephh (void *)"n", (lut_cmp)strcmp)) != NULL) { 1051b7d3956bSstephh ASSERT(ep->t == UINT64); 1052b7d3956bSstephh serdn = (int)ep->v; 1053b7d3956bSstephh } 1054b7d3956bSstephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 1055b7d3956bSstephh (void *)"t", (lut_cmp)strcmp)) != NULL) { 1056b7d3956bSstephh ASSERT(ep->t == STRING); 1057b7d3956bSstephh serdt = (char *)(uintptr_t)ep->v; 1058b7d3956bSstephh } 1059b7d3956bSstephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 1060b7d3956bSstephh (void *)"suffix", (lut_cmp)strcmp)) != NULL) { 1061b7d3956bSstephh ASSERT(ep->t == STRING); 1062b7d3956bSstephh serdsuffix = (char *)(uintptr_t)ep->v; 1063b7d3956bSstephh } 1064b7d3956bSstephh if ((ep = (struct evalue *)lut_lookup(sp->serdprops, 1065b7d3956bSstephh (void *)"increment", (lut_cmp)strcmp)) != NULL) { 1066b7d3956bSstephh ASSERT(ep->t == UINT64); 1067b7d3956bSstephh serdincrement = (int)ep->v; 1068b7d3956bSstephh } 1069b7d3956bSstephh 10707c478bd9Sstevel@tonic-gate /* 10717c478bd9Sstevel@tonic-gate * obtain instanced SERD engine from the upset sp. from this 10727c478bd9Sstevel@tonic-gate * derive serdname, the string used to identify the SERD engine. 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate serdinst = eventprop_lookup(sp, L_engine); 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate if (serdinst == NULL) 1077b7d3956bSstephh return (-1); 10787c478bd9Sstevel@tonic-gate 10798e7248e5SStephen Hanson len = strlen(serdinst->u.stmt.np->u.event.ename->u.name.s) + 1; 1080049e2ea4SScott Davenport if (serdsuffix != NULL) 1081049e2ea4SScott Davenport len += strlen(serdsuffix); 10828e7248e5SStephen Hanson serdclass = MALLOC(len); 10838e7248e5SStephen Hanson if (serdsuffix != NULL) 10848e7248e5SStephen Hanson (void) snprintf(serdclass, len, "%s%s", 10858e7248e5SStephen Hanson serdinst->u.stmt.np->u.event.ename->u.name.s, serdsuffix); 10868e7248e5SStephen Hanson else 10878e7248e5SStephen Hanson (void) snprintf(serdclass, len, "%s", 10888e7248e5SStephen Hanson serdinst->u.stmt.np->u.event.ename->u.name.s); 10898e7248e5SStephen Hanson serdresource = ipath2str(NULL, 10908e7248e5SStephen Hanson ipath(serdinst->u.stmt.np->u.event.epname)); 10918e7248e5SStephen Hanson len += strlen(serdresource) + 1; 10928e7248e5SStephen Hanson serdname = MALLOC(len); 10938e7248e5SStephen Hanson (void) snprintf(serdname, len, "%s@%s", serdclass, serdresource); 1094049e2ea4SScott Davenport FREE(serdresource); 1095b7d3956bSstephh 10967aec1d6eScindi /* handle serd engine "id" property, if there is one */ 10977aec1d6eScindi if ((nid = 10987aec1d6eScindi lut_lookup(serdinst->u.stmt.lutp, (void *)L_id, NULL)) != NULL) { 10997aec1d6eScindi struct evalue *gval; 11007aec1d6eScindi char suffixbuf[200]; 11017aec1d6eScindi char *suffix; 11027aec1d6eScindi char *nserdname; 11037aec1d6eScindi size_t nname; 11047aec1d6eScindi 11057aec1d6eScindi out(O_ALTFP|O_NONL, "serd \"%s\" id: ", serdname); 11067aec1d6eScindi ptree_name_iter(O_ALTFP|O_NONL, nid); 11077aec1d6eScindi 11087aec1d6eScindi ASSERTinfo(nid->t == T_GLOBID, ptree_nodetype2str(nid->t)); 11097aec1d6eScindi 11107aec1d6eScindi if ((gval = lut_lookup(fmep->globals, 11117aec1d6eScindi (void *)nid->u.globid.s, NULL)) == NULL) { 11127aec1d6eScindi out(O_ALTFP, " undefined"); 11137aec1d6eScindi } else if (gval->t == UINT64) { 11147aec1d6eScindi out(O_ALTFP, " %llu", gval->v); 11157aec1d6eScindi (void) sprintf(suffixbuf, "%llu", gval->v); 11167aec1d6eScindi suffix = suffixbuf; 11177aec1d6eScindi } else { 111880ab886dSwesolows out(O_ALTFP, " \"%s\"", (char *)(uintptr_t)gval->v); 111980ab886dSwesolows suffix = (char *)(uintptr_t)gval->v; 11207aec1d6eScindi } 11217aec1d6eScindi 11227aec1d6eScindi nname = strlen(serdname) + strlen(suffix) + 2; 11237aec1d6eScindi nserdname = MALLOC(nname); 11247aec1d6eScindi (void) snprintf(nserdname, nname, "%s:%s", serdname, suffix); 11257aec1d6eScindi FREE(serdname); 11267aec1d6eScindi serdname = nserdname; 11277aec1d6eScindi } 11287aec1d6eScindi 1129b7d3956bSstephh /* 1130b7d3956bSstephh * if the engine is empty, and we have an override for n/t then 1131b7d3956bSstephh * destroy and recreate it. 1132b7d3956bSstephh */ 1133b7d3956bSstephh if ((serdn != -1 || serdt != NULL) && fmd_serd_exists(hdl, serdname) && 1134b7d3956bSstephh fmd_serd_empty(hdl, serdname)) 1135b7d3956bSstephh fmd_serd_destroy(hdl, serdname); 1136b7d3956bSstephh 11377c478bd9Sstevel@tonic-gate if (!fmd_serd_exists(hdl, serdname)) { 11387c478bd9Sstevel@tonic-gate struct node *nN, *nT; 1139e5ba14ffSstephh const char *s; 1140e5ba14ffSstephh struct node *nodep; 1141e5ba14ffSstephh struct config *cp; 1142e5ba14ffSstephh char *path; 1143e5ba14ffSstephh uint_t nval; 1144e5ba14ffSstephh hrtime_t tval; 1145e5ba14ffSstephh int i; 1146e5ba14ffSstephh char *ptr; 1147e5ba14ffSstephh int got_n_override = 0, got_t_override = 0; 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* no SERD engine yet, so create it */ 1150e5ba14ffSstephh nodep = serdinst->u.stmt.np->u.event.epname; 1151e5ba14ffSstephh path = ipath2str(NULL, ipath(nodep)); 1152e5ba14ffSstephh cp = config_lookup(fmep->config, path, 0); 1153e5ba14ffSstephh FREE((void *)path); 1154e5ba14ffSstephh 1155e5ba14ffSstephh /* 1156e5ba14ffSstephh * We allow serd paramaters to be overridden, either from 1157e5ba14ffSstephh * eft.conf file values (if Serd_Override is set) or from 1158e5ba14ffSstephh * driver properties (for "serd.io.device" engines). 1159e5ba14ffSstephh */ 1160e5ba14ffSstephh if (Serd_Override != NULL) { 1161e5ba14ffSstephh char *save_ptr, *ptr1, *ptr2, *ptr3; 1162e5ba14ffSstephh ptr3 = save_ptr = STRDUP(Serd_Override); 1163e5ba14ffSstephh while (*ptr3 != '\0') { 1164e5ba14ffSstephh ptr1 = strchr(ptr3, ','); 1165e5ba14ffSstephh *ptr1 = '\0'; 11668e7248e5SStephen Hanson if (strcmp(ptr3, serdclass) == 0) { 1167e5ba14ffSstephh ptr2 = strchr(ptr1 + 1, ','); 1168e5ba14ffSstephh *ptr2 = '\0'; 1169e5ba14ffSstephh nval = atoi(ptr1 + 1); 1170e5ba14ffSstephh out(O_ALTFP, "serd override %s_n %d", 11718e7248e5SStephen Hanson serdclass, nval); 1172e5ba14ffSstephh ptr3 = strchr(ptr2 + 1, ' '); 1173e5ba14ffSstephh if (ptr3) 1174e5ba14ffSstephh *ptr3 = '\0'; 1175e5ba14ffSstephh ptr = STRDUP(ptr2 + 1); 1176e5ba14ffSstephh out(O_ALTFP, "serd override %s_t %s", 11778e7248e5SStephen Hanson serdclass, ptr); 1178e5ba14ffSstephh got_n_override = 1; 1179e5ba14ffSstephh got_t_override = 1; 1180e5ba14ffSstephh break; 1181e5ba14ffSstephh } else { 1182e5ba14ffSstephh ptr2 = strchr(ptr1 + 1, ','); 1183e5ba14ffSstephh ptr3 = strchr(ptr2 + 1, ' '); 1184e5ba14ffSstephh if (ptr3 == NULL) 1185e5ba14ffSstephh break; 1186e5ba14ffSstephh } 1187e5ba14ffSstephh ptr3++; 1188e5ba14ffSstephh } 1189e5ba14ffSstephh FREE(save_ptr); 1190e5ba14ffSstephh } 11917c478bd9Sstevel@tonic-gate 1192e5ba14ffSstephh if (cp && got_n_override == 0) { 1193e5ba14ffSstephh /* 11948e7248e5SStephen Hanson * convert serd engine class into property name 1195e5ba14ffSstephh */ 11968e7248e5SStephen Hanson char *prop_name = MALLOC(strlen(serdclass) + 3); 11978e7248e5SStephen Hanson for (i = 0; i < strlen(serdclass); i++) { 11988e7248e5SStephen Hanson if (serdclass[i] == '.') 11998e7248e5SStephen Hanson prop_name[i] = '_'; 1200e5ba14ffSstephh else 12018e7248e5SStephen Hanson prop_name[i] = serdclass[i]; 1202e5ba14ffSstephh } 12038e7248e5SStephen Hanson prop_name[i++] = '_'; 12048e7248e5SStephen Hanson prop_name[i++] = 'n'; 12058e7248e5SStephen Hanson prop_name[i] = '\0'; 12068e7248e5SStephen Hanson if (s = config_getprop(cp, prop_name)) { 1207e5ba14ffSstephh nval = atoi(s); 12088e7248e5SStephen Hanson out(O_ALTFP, "serd override %s_n %s", 12098e7248e5SStephen Hanson serdclass, s); 1210e5ba14ffSstephh got_n_override = 1; 1211e5ba14ffSstephh } 12128e7248e5SStephen Hanson prop_name[i - 1] = 't'; 12138e7248e5SStephen Hanson if (s = config_getprop(cp, prop_name)) { 1214e5ba14ffSstephh ptr = STRDUP(s); 12158e7248e5SStephen Hanson out(O_ALTFP, "serd override %s_t %s", 12168e7248e5SStephen Hanson serdclass, s); 1217e5ba14ffSstephh got_t_override = 1; 1218e5ba14ffSstephh } 12198e7248e5SStephen Hanson FREE(prop_name); 1220e5ba14ffSstephh } 12217c478bd9Sstevel@tonic-gate 1222b7d3956bSstephh if (serdn != -1 && got_n_override == 0) { 1223b7d3956bSstephh nval = serdn; 12248e7248e5SStephen Hanson out(O_ALTFP, "serd override %s_n %d", serdclass, serdn); 1225b7d3956bSstephh got_n_override = 1; 1226b7d3956bSstephh } 1227b7d3956bSstephh if (serdt != NULL && got_t_override == 0) { 1228b7d3956bSstephh ptr = STRDUP(serdt); 12298e7248e5SStephen Hanson out(O_ALTFP, "serd override %s_t %s", serdclass, serdt); 1230b7d3956bSstephh got_t_override = 1; 1231b7d3956bSstephh } 1232b7d3956bSstephh 1233e5ba14ffSstephh if (!got_n_override) { 1234e5ba14ffSstephh nN = lut_lookup(serdinst->u.stmt.lutp, (void *)L_N, 1235e5ba14ffSstephh NULL); 1236e5ba14ffSstephh ASSERT(nN->t == T_NUM); 1237e5ba14ffSstephh nval = (uint_t)nN->u.ull; 1238e5ba14ffSstephh } 1239e5ba14ffSstephh if (!got_t_override) { 1240e5ba14ffSstephh nT = lut_lookup(serdinst->u.stmt.lutp, (void *)L_T, 1241e5ba14ffSstephh NULL); 1242e5ba14ffSstephh ASSERT(nT->t == T_TIMEVAL); 1243e5ba14ffSstephh tval = (hrtime_t)nT->u.ull; 1244e5ba14ffSstephh } else { 1245e5ba14ffSstephh const unsigned long long *ullp; 1246e5ba14ffSstephh const char *suffix; 1247e5ba14ffSstephh int len; 1248e5ba14ffSstephh 1249e5ba14ffSstephh len = strspn(ptr, "0123456789"); 1250e5ba14ffSstephh suffix = stable(&ptr[len]); 1251e5ba14ffSstephh ullp = (unsigned long long *)lut_lookup(Timesuffixlut, 1252e5ba14ffSstephh (void *)suffix, NULL); 1253e5ba14ffSstephh ptr[len] = '\0'; 1254b7d3956bSstephh tval = strtoull(ptr, NULL, 0) * (ullp ? *ullp : 1ll); 1255e5ba14ffSstephh FREE(ptr); 1256e5ba14ffSstephh } 1257e5ba14ffSstephh fmd_serd_create(hdl, serdname, nval, tval); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 1260b5016cbbSstephh newentp = MALLOC(sizeof (*newentp)); 12618e7248e5SStephen Hanson newentp->ename = stable(serdclass); 12628e7248e5SStephen Hanson FREE(serdclass); 1263b5016cbbSstephh newentp->ipath = ipath(serdinst->u.stmt.np->u.event.epname); 1264b5016cbbSstephh newentp->hdl = hdl; 1265b5016cbbSstephh if (lut_lookup(SerdEngines, newentp, (lut_cmp)serd_cmp) == NULL) { 1266b5016cbbSstephh SerdEngines = lut_add(SerdEngines, (void *)newentp, 1267e5ba14ffSstephh (void *)newentp, (lut_cmp)serd_cmp); 1268b5016cbbSstephh Serd_need_save = 1; 1269b5016cbbSstephh serd_save(); 1270b5016cbbSstephh } else { 1271b5016cbbSstephh FREE(newentp); 1272b5016cbbSstephh } 1273b5016cbbSstephh 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate /* 12767c478bd9Sstevel@tonic-gate * increment SERD engine. if engine fires, reset serd 1277b7d3956bSstephh * engine and return trip_strcode if required. 12787c478bd9Sstevel@tonic-gate */ 1279b7d3956bSstephh for (i = 0; i < serdincrement; i++) { 1280b7d3956bSstephh if (fmd_serd_record(hdl, serdname, ffep)) { 1281b7d3956bSstephh fmd_case_add_serd(hdl, fmcase, serdname); 1282b7d3956bSstephh fmd_serd_reset(hdl, serdname); 1283b7d3956bSstephh 1284b7d3956bSstephh if (ippp) { 1285b7d3956bSstephh struct node *tripinst = 1286b7d3956bSstephh lut_lookup(serdinst->u.stmt.lutp, 1287b7d3956bSstephh (void *)L_trip, NULL); 1288b7d3956bSstephh ASSERT(tripinst != NULL); 1289b7d3956bSstephh *enamep = tripinst->u.event.ename->u.name.s; 1290b7d3956bSstephh *ippp = ipath(tripinst->u.event.epname); 1291b7d3956bSstephh out(O_ALTFP|O_NONL, 1292b7d3956bSstephh "[engine fired: %s, sending: ", serdname); 1293b7d3956bSstephh ipath_print(O_ALTFP|O_NONL, *enamep, *ippp); 1294b7d3956bSstephh out(O_ALTFP, "]"); 1295b7d3956bSstephh } else { 1296b7d3956bSstephh out(O_ALTFP, "[engine fired: %s, no trip]", 1297b7d3956bSstephh serdname); 1298b7d3956bSstephh } 1299b7d3956bSstephh FREE(serdname); 1300b7d3956bSstephh return (1); 1301b7d3956bSstephh } 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate FREE(serdname); 13057c478bd9Sstevel@tonic-gate return (0); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* 13097c478bd9Sstevel@tonic-gate * search a suspect list for upsets. feed each upset to serd_eval() and 13107c478bd9Sstevel@tonic-gate * build up tripped[], an array of ereports produced by the firing of 13117c478bd9Sstevel@tonic-gate * any SERD engines. then feed each ereport back into 13127c478bd9Sstevel@tonic-gate * fme_receive_report(). 13137c478bd9Sstevel@tonic-gate * 13147c478bd9Sstevel@tonic-gate * returns ntrip, the number of these ereports produced. 13157c478bd9Sstevel@tonic-gate */ 13167c478bd9Sstevel@tonic-gate static int 13177c478bd9Sstevel@tonic-gate upsets_eval(struct fme *fmep, fmd_event_t *ffep) 13187c478bd9Sstevel@tonic-gate { 13197c478bd9Sstevel@tonic-gate /* we build an array of tripped ereports that we send ourselves */ 13207c478bd9Sstevel@tonic-gate struct { 13217c478bd9Sstevel@tonic-gate const char *ename; 13227c478bd9Sstevel@tonic-gate const struct ipath *ipp; 13237c478bd9Sstevel@tonic-gate } *tripped; 13247c478bd9Sstevel@tonic-gate struct event *sp; 13257c478bd9Sstevel@tonic-gate int ntrip, nupset, i; 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate /* 13287c478bd9Sstevel@tonic-gate * count the number of upsets to determine the upper limit on 13297c478bd9Sstevel@tonic-gate * expected trip ereport strings. remember that one upset can 13307c478bd9Sstevel@tonic-gate * lead to at most one ereport. 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate nupset = 0; 13337c478bd9Sstevel@tonic-gate for (sp = fmep->suspects; sp; sp = sp->suspects) { 13347c478bd9Sstevel@tonic-gate if (sp->t == N_UPSET) 13357c478bd9Sstevel@tonic-gate nupset++; 13367c478bd9Sstevel@tonic-gate } 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate if (nupset == 0) 13397c478bd9Sstevel@tonic-gate return (0); 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* 13427c478bd9Sstevel@tonic-gate * get to this point if we have upsets and expect some trip 13437c478bd9Sstevel@tonic-gate * ereports 13447c478bd9Sstevel@tonic-gate */ 13457c478bd9Sstevel@tonic-gate tripped = alloca(sizeof (*tripped) * nupset); 13467c478bd9Sstevel@tonic-gate bzero((void *)tripped, sizeof (*tripped) * nupset); 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate ntrip = 0; 13497c478bd9Sstevel@tonic-gate for (sp = fmep->suspects; sp; sp = sp->suspects) 13503e8d8e18Sdb if (sp->t == N_UPSET && 13517aec1d6eScindi serd_eval(fmep, fmep->hdl, ffep, fmep->fmcase, sp, 1352b7d3956bSstephh &tripped[ntrip].ename, &tripped[ntrip].ipp) == 1) 13537c478bd9Sstevel@tonic-gate ntrip++; 13547c478bd9Sstevel@tonic-gate 135527134bdaSstephh for (i = 0; i < ntrip; i++) { 135627134bdaSstephh struct event *ep, *nep; 135727134bdaSstephh struct fme *nfmep; 135827134bdaSstephh fmd_case_t *fmcase; 135927134bdaSstephh const struct ipath *ipp; 136027134bdaSstephh const char *eventstring; 136127134bdaSstephh int prev_verbose; 136227134bdaSstephh unsigned long long my_delay = TIMEVAL_EVENTUALLY; 136327134bdaSstephh enum fme_state state; 136427134bdaSstephh 136527134bdaSstephh /* 136627134bdaSstephh * First try and evaluate a case with the trip ereport plus 136727134bdaSstephh * all the other ereports that cause the trip. If that fails 136827134bdaSstephh * to evaluate then try again with just this ereport on its own. 136927134bdaSstephh */ 137027134bdaSstephh out(O_ALTFP|O_NONL, "fme_receive_report_serd: "); 137127134bdaSstephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, tripped[i].ipp); 137227134bdaSstephh out(O_ALTFP|O_STAMP, NULL); 137327134bdaSstephh ep = fmep->e0; 137427134bdaSstephh eventstring = ep->enode->u.event.ename->u.name.s; 137527134bdaSstephh ipp = ep->ipp; 137627134bdaSstephh 137727134bdaSstephh /* 137827134bdaSstephh * create a duplicate fme and case 137927134bdaSstephh */ 138027134bdaSstephh fmcase = fmd_case_open(fmep->hdl, NULL); 138127134bdaSstephh out(O_ALTFP|O_NONL, "duplicate fme for event ["); 138227134bdaSstephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 138327134bdaSstephh out(O_ALTFP, " ]"); 1384705e9f42SStephen Hanson 138527134bdaSstephh if ((nfmep = newfme(eventstring, ipp, fmep->hdl, 1386705e9f42SStephen Hanson fmcase, ffep, ep->nvp)) == NULL) { 138727134bdaSstephh out(O_ALTFP|O_NONL, "["); 138827134bdaSstephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 138927134bdaSstephh out(O_ALTFP, " CANNOT DIAGNOSE]"); 139027134bdaSstephh continue; 139127134bdaSstephh } 1392705e9f42SStephen Hanson 139327134bdaSstephh Open_fme_count++; 139427134bdaSstephh nfmep->pull = fmep->pull; 139527134bdaSstephh init_fme_bufs(nfmep); 139627134bdaSstephh out(O_ALTFP|O_NONL, "["); 139727134bdaSstephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 139827134bdaSstephh out(O_ALTFP, " created FME%d, case %s]", nfmep->id, 139927134bdaSstephh fmd_case_uuid(nfmep->hdl, nfmep->fmcase)); 140027134bdaSstephh if (ffep) { 140127134bdaSstephh fmd_case_setprincipal(nfmep->hdl, nfmep->fmcase, ffep); 1402b7d3956bSstephh fmd_case_add_ereport(nfmep->hdl, nfmep->fmcase, ffep); 140327134bdaSstephh nfmep->e0r = ffep; 140427134bdaSstephh } 140527134bdaSstephh 140627134bdaSstephh /* 140727134bdaSstephh * add the original ereports 140827134bdaSstephh */ 140927134bdaSstephh for (ep = fmep->observations; ep; ep = ep->observations) { 141027134bdaSstephh eventstring = ep->enode->u.event.ename->u.name.s; 141127134bdaSstephh ipp = ep->ipp; 141227134bdaSstephh out(O_ALTFP|O_NONL, "adding event ["); 141327134bdaSstephh ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 141427134bdaSstephh out(O_ALTFP, " ]"); 141527134bdaSstephh nep = itree_lookup(nfmep->eventtree, eventstring, ipp); 141627134bdaSstephh if (nep->count++ == 0) { 141727134bdaSstephh nep->observations = nfmep->observations; 141827134bdaSstephh nfmep->observations = nep; 141927134bdaSstephh serialize_observation(nfmep, eventstring, ipp); 142027134bdaSstephh nep->nvp = evnv_dupnvl(ep->nvp); 142127134bdaSstephh } 1422b7d3956bSstephh if (ep->ffep && ep->ffep != ffep) 142327134bdaSstephh fmd_case_add_ereport(nfmep->hdl, nfmep->fmcase, 1424b7d3956bSstephh ep->ffep); 142527134bdaSstephh stats_counter_bump(nfmep->Rcount); 142627134bdaSstephh } 142727134bdaSstephh 142827134bdaSstephh /* 142927134bdaSstephh * add the serd trigger ereport 143027134bdaSstephh */ 143127134bdaSstephh if ((ep = itree_lookup(nfmep->eventtree, tripped[i].ename, 143227134bdaSstephh tripped[i].ipp)) == NULL) { 143327134bdaSstephh /* 143427134bdaSstephh * The trigger ereport is not in the instance tree. It 143527134bdaSstephh * was presumably removed by prune_propagations() as 143627134bdaSstephh * this combination of events is not present in the 143727134bdaSstephh * rules. 143827134bdaSstephh */ 143927134bdaSstephh out(O_ALTFP, "upsets_eval: e0 not in instance tree"); 144032d4e834STarik Soydan Undiag_reason = UD_VAL_BADEVENTI; 144127134bdaSstephh goto retry_lone_ereport; 144227134bdaSstephh } 144327134bdaSstephh out(O_ALTFP|O_NONL, "adding event ["); 144427134bdaSstephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, tripped[i].ipp); 144527134bdaSstephh out(O_ALTFP, " ]"); 144627134bdaSstephh nfmep->ecurrent = ep; 144727134bdaSstephh ep->nvp = NULL; 144827134bdaSstephh ep->count = 1; 144927134bdaSstephh ep->observations = nfmep->observations; 145027134bdaSstephh nfmep->observations = ep; 145127134bdaSstephh 145227134bdaSstephh /* 145327134bdaSstephh * just peek first. 145427134bdaSstephh */ 145527134bdaSstephh nfmep->peek = 1; 145627134bdaSstephh prev_verbose = Verbose; 145727134bdaSstephh if (Debug == 0) 145827134bdaSstephh Verbose = 0; 145927134bdaSstephh lut_walk(nfmep->eventtree, (lut_cb)clear_arrows, (void *)nfmep); 146027134bdaSstephh state = hypothesise(nfmep, nfmep->e0, nfmep->ull, &my_delay); 146127134bdaSstephh nfmep->peek = 0; 146227134bdaSstephh Verbose = prev_verbose; 146327134bdaSstephh if (state == FME_DISPROVED) { 146427134bdaSstephh out(O_ALTFP, "upsets_eval: hypothesis disproved"); 146532d4e834STarik Soydan Undiag_reason = UD_VAL_UNSOLVD; 146627134bdaSstephh retry_lone_ereport: 146727134bdaSstephh /* 146827134bdaSstephh * However the trigger ereport on its own might be 146927134bdaSstephh * diagnosable, so check for that. Undo the new fme 147027134bdaSstephh * and case we just created and call fme_receive_report. 147127134bdaSstephh */ 147227134bdaSstephh out(O_ALTFP|O_NONL, "["); 147327134bdaSstephh ipath_print(O_ALTFP|O_NONL, tripped[i].ename, 147427134bdaSstephh tripped[i].ipp); 147527134bdaSstephh out(O_ALTFP, " retrying with just trigger ereport]"); 147627134bdaSstephh itree_free(nfmep->eventtree); 147727134bdaSstephh nfmep->eventtree = NULL; 147827134bdaSstephh structconfig_free(nfmep->config); 147927134bdaSstephh nfmep->config = NULL; 148027134bdaSstephh destroy_fme_bufs(nfmep); 148127134bdaSstephh fmd_case_close(nfmep->hdl, nfmep->fmcase); 148227134bdaSstephh fme_receive_report(fmep->hdl, ffep, 148327134bdaSstephh tripped[i].ename, tripped[i].ipp, NULL); 148427134bdaSstephh continue; 148527134bdaSstephh } 148627134bdaSstephh 148727134bdaSstephh /* 148827134bdaSstephh * and evaluate 148927134bdaSstephh */ 149027134bdaSstephh serialize_observation(nfmep, tripped[i].ename, tripped[i].ipp); 149127134bdaSstephh fme_eval(nfmep, ffep); 149227134bdaSstephh } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate return (ntrip); 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate /* 14987c478bd9Sstevel@tonic-gate * fme_receive_external_report -- call when an external ereport comes in 14997c478bd9Sstevel@tonic-gate * 15007c478bd9Sstevel@tonic-gate * this routine just converts the relevant information from the ereport 15017c478bd9Sstevel@tonic-gate * into a format used internally and passes it on to fme_receive_report(). 15027c478bd9Sstevel@tonic-gate */ 15037c478bd9Sstevel@tonic-gate void 15047c478bd9Sstevel@tonic-gate fme_receive_external_report(fmd_hdl_t *hdl, fmd_event_t *ffep, nvlist_t *nvl, 1505602ca9eaScth const char *class) 15067c478bd9Sstevel@tonic-gate { 1507602ca9eaScth struct node *epnamenp; 1508602ca9eaScth fmd_case_t *fmcase; 1509602ca9eaScth const struct ipath *ipp; 1510705e9f42SStephen Hanson nvlist_t *detector = NULL; 15117c478bd9Sstevel@tonic-gate 1512602ca9eaScth class = stable(class); 1513b5016cbbSstephh 1514602ca9eaScth /* Get the component path from the ereport */ 1515602ca9eaScth epnamenp = platform_getpath(nvl); 1516602ca9eaScth 1517602ca9eaScth /* See if we ended up without a path. */ 1518602ca9eaScth if (epnamenp == NULL) { 1519602ca9eaScth /* See if class permits silent discard on unknown component. */ 1520602ca9eaScth if (lut_lookup(Ereportenames_discard, (void *)class, NULL)) { 1521602ca9eaScth out(O_ALTFP|O_VERB2, "Unable to map \"%s\" ereport " 1522602ca9eaScth "to component path, but silent discard allowed.", 1523602ca9eaScth class); 1524602ca9eaScth } else { 1525602ca9eaScth /* 1526602ca9eaScth * XFILE: Failure to find a component is bad unless 1527602ca9eaScth * 'discard_if_config_unknown=1' was specified in the 1528602ca9eaScth * ereport definition. Indicate undiagnosable. 1529602ca9eaScth */ 153032d4e834STarik Soydan Undiag_reason = UD_VAL_NOPATH; 1531602ca9eaScth fmcase = fmd_case_open(hdl, NULL); 1532705e9f42SStephen Hanson 1533705e9f42SStephen Hanson /* 1534705e9f42SStephen Hanson * We don't have a component path here (which means that 1535705e9f42SStephen Hanson * the detector was not in hc-scheme and couldn't be 1536705e9f42SStephen Hanson * converted to hc-scheme. Report the raw detector as 1537705e9f42SStephen Hanson * the suspect resource if there is one. 1538705e9f42SStephen Hanson */ 1539705e9f42SStephen Hanson (void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, 1540705e9f42SStephen Hanson &detector); 1541705e9f42SStephen Hanson publish_undiagnosable(hdl, ffep, fmcase, detector, 1542705e9f42SStephen Hanson (char *)class); 1543602ca9eaScth } 15447c478bd9Sstevel@tonic-gate return; 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate ipp = ipath(epnamenp); 15487c478bd9Sstevel@tonic-gate tree_free(epnamenp); 1549602ca9eaScth fme_receive_report(hdl, ffep, class, ipp, nvl); 15507c478bd9Sstevel@tonic-gate } 15517c478bd9Sstevel@tonic-gate 155208f6c065Sgavinm /*ARGSUSED*/ 155308f6c065Sgavinm void 155408f6c065Sgavinm fme_receive_repair_list(fmd_hdl_t *hdl, fmd_event_t *ffep, nvlist_t *nvl, 155508f6c065Sgavinm const char *eventstring) 155608f6c065Sgavinm { 155708f6c065Sgavinm char *uuid; 155808f6c065Sgavinm nvlist_t **nva; 155908f6c065Sgavinm uint_t nvc; 156008f6c065Sgavinm const struct ipath *ipp; 156108f6c065Sgavinm 156208f6c065Sgavinm if (nvlist_lookup_string(nvl, FM_SUSPECT_UUID, &uuid) != 0 || 156308f6c065Sgavinm nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 156408f6c065Sgavinm &nva, &nvc) != 0) { 156508f6c065Sgavinm out(O_ALTFP, "No uuid or fault list for list.repaired event"); 156608f6c065Sgavinm return; 156708f6c065Sgavinm } 156808f6c065Sgavinm 156908f6c065Sgavinm out(O_ALTFP, "Processing list.repaired from case %s", uuid); 157008f6c065Sgavinm 157108f6c065Sgavinm while (nvc-- != 0) { 157208f6c065Sgavinm /* 1573b5016cbbSstephh * Reset any istat or serd engine associated with this path. 157408f6c065Sgavinm */ 157508f6c065Sgavinm char *path; 157608f6c065Sgavinm 157708f6c065Sgavinm if ((ipp = platform_fault2ipath(*nva++)) == NULL) 157808f6c065Sgavinm continue; 157908f6c065Sgavinm 158008f6c065Sgavinm path = ipath2str(NULL, ipp); 158108f6c065Sgavinm out(O_ALTFP, "fme_receive_repair_list: resetting state for %s", 158208f6c065Sgavinm path); 158308f6c065Sgavinm FREE(path); 158408f6c065Sgavinm 158508f6c065Sgavinm lut_walk(Istats, (lut_cb)istat_counter_reset_cb, (void *)ipp); 158608f6c065Sgavinm istat_save(); 158708f6c065Sgavinm 1588b5016cbbSstephh lut_walk(SerdEngines, (lut_cb)serd_reset_cb, (void *)ipp); 1589b5016cbbSstephh serd_save(); 159008f6c065Sgavinm } 159108f6c065Sgavinm } 159208f6c065Sgavinm 1593e5ba14ffSstephh /*ARGSUSED*/ 1594e5ba14ffSstephh void 1595e5ba14ffSstephh fme_receive_topology_change(void) 1596e5ba14ffSstephh { 1597e5ba14ffSstephh lut_walk(Istats, (lut_cb)istat_counter_topo_chg_cb, NULL); 1598e5ba14ffSstephh istat_save(); 1599e5ba14ffSstephh 1600e5ba14ffSstephh lut_walk(SerdEngines, (lut_cb)serd_topo_chg_cb, NULL); 1601e5ba14ffSstephh serd_save(); 1602e5ba14ffSstephh } 1603e5ba14ffSstephh 16047aec1d6eScindi static int mark_arrows(struct fme *fmep, struct event *ep, int mark, 160500d0963fSdilpreet unsigned long long at_latest_by, unsigned long long *pdelay, int keep); 16067aec1d6eScindi 16077aec1d6eScindi /* ARGSUSED */ 16087aec1d6eScindi static void 16097aec1d6eScindi clear_arrows(struct event *ep, struct event *ep2, struct fme *fmep) 16107aec1d6eScindi { 16117aec1d6eScindi struct bubble *bp; 16127aec1d6eScindi struct arrowlist *ap; 16137aec1d6eScindi 16147aec1d6eScindi ep->cached_state = 0; 161500d0963fSdilpreet ep->keep_in_tree = 0; 16167aec1d6eScindi for (bp = itree_next_bubble(ep, NULL); bp; 16177aec1d6eScindi bp = itree_next_bubble(ep, bp)) { 16187aec1d6eScindi if (bp->t != B_FROM) 16197aec1d6eScindi continue; 16207aec1d6eScindi bp->mark = 0; 16217aec1d6eScindi for (ap = itree_next_arrow(bp, NULL); ap; 16227aec1d6eScindi ap = itree_next_arrow(bp, ap)) 16237aec1d6eScindi ap->arrowp->mark = 0; 16247aec1d6eScindi } 16257aec1d6eScindi } 16267aec1d6eScindi 16277c478bd9Sstevel@tonic-gate static void 16287c478bd9Sstevel@tonic-gate fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 16297c478bd9Sstevel@tonic-gate const char *eventstring, const struct ipath *ipp, nvlist_t *nvl) 16307c478bd9Sstevel@tonic-gate { 16317c478bd9Sstevel@tonic-gate struct event *ep; 16327c478bd9Sstevel@tonic-gate struct fme *fmep = NULL; 16330cc1f05eSjrutt struct fme *ofmep = NULL; 16340cc1f05eSjrutt struct fme *cfmep, *svfmep; 16357c478bd9Sstevel@tonic-gate int matched = 0; 16360cc1f05eSjrutt nvlist_t *defect; 1637b5016cbbSstephh fmd_case_t *fmcase; 1638705e9f42SStephen Hanson char *reason; 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "fme_receive_report: "); 16417c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 16427c478bd9Sstevel@tonic-gate out(O_ALTFP|O_STAMP, NULL); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate /* decide which FME it goes to */ 16457c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) { 16467c478bd9Sstevel@tonic-gate int prev_verbose; 16477c478bd9Sstevel@tonic-gate unsigned long long my_delay = TIMEVAL_EVENTUALLY; 16487c478bd9Sstevel@tonic-gate enum fme_state state; 16497aec1d6eScindi nvlist_t *pre_peek_nvp = NULL; 16507c478bd9Sstevel@tonic-gate 16510cc1f05eSjrutt if (fmep->overflow) { 16520cc1f05eSjrutt if (!(fmd_case_closed(fmep->hdl, fmep->fmcase))) 16530cc1f05eSjrutt ofmep = fmep; 16540cc1f05eSjrutt 16550cc1f05eSjrutt continue; 16560cc1f05eSjrutt } 16570cc1f05eSjrutt 1658d96ce684Sstephh /* 1659d96ce684Sstephh * ignore solved or closed cases 1660d96ce684Sstephh */ 1661d96ce684Sstephh if (fmep->posted_suspects || 1662d96ce684Sstephh fmd_case_solved(fmep->hdl, fmep->fmcase) || 1663d96ce684Sstephh fmd_case_closed(fmep->hdl, fmep->fmcase)) 1664d96ce684Sstephh continue; 1665d96ce684Sstephh 16667c478bd9Sstevel@tonic-gate /* look up event in event tree for this FME */ 16677c478bd9Sstevel@tonic-gate if ((ep = itree_lookup(fmep->eventtree, 16687c478bd9Sstevel@tonic-gate eventstring, ipp)) == NULL) 16697c478bd9Sstevel@tonic-gate continue; 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate /* note observation */ 16727c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 16737c478bd9Sstevel@tonic-gate if (ep->count++ == 0) { 16747c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 16757c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 16767c478bd9Sstevel@tonic-gate fmep->observations = ep; 16777c478bd9Sstevel@tonic-gate ep->nvp = evnv_dupnvl(nvl); 16787aec1d6eScindi } else { 16797aec1d6eScindi /* use new payload values for peek */ 16807aec1d6eScindi pre_peek_nvp = ep->nvp; 16817aec1d6eScindi ep->nvp = evnv_dupnvl(nvl); 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* tell hypothesise() not to mess with suspect list */ 16857c478bd9Sstevel@tonic-gate fmep->peek = 1; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate /* don't want this to be verbose (unless Debug is set) */ 16887c478bd9Sstevel@tonic-gate prev_verbose = Verbose; 16897c478bd9Sstevel@tonic-gate if (Debug == 0) 16907c478bd9Sstevel@tonic-gate Verbose = 0; 16917c478bd9Sstevel@tonic-gate 16927aec1d6eScindi lut_walk(fmep->eventtree, (lut_cb)clear_arrows, (void *)fmep); 16937aec1d6eScindi state = hypothesise(fmep, fmep->e0, fmep->ull, &my_delay); 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate fmep->peek = 0; 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate /* put verbose flag back */ 16987c478bd9Sstevel@tonic-gate Verbose = prev_verbose; 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate if (state != FME_DISPROVED) { 17017c478bd9Sstevel@tonic-gate /* found an FME that explains the ereport */ 17027c478bd9Sstevel@tonic-gate matched++; 17037c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 17047c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 17057c478bd9Sstevel@tonic-gate out(O_ALTFP, " explained by FME%d]", fmep->id); 17067c478bd9Sstevel@tonic-gate 1707aab83bb8SJosef 'Jeff' Sipek nvlist_free(pre_peek_nvp); 17087aec1d6eScindi 17097c478bd9Sstevel@tonic-gate if (ep->count == 1) 17107c478bd9Sstevel@tonic-gate serialize_observation(fmep, eventstring, ipp); 17117c478bd9Sstevel@tonic-gate 1712b7d3956bSstephh if (ffep) { 17137c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 1714b7d3956bSstephh ep->ffep = ffep; 1715b7d3956bSstephh } 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcount); 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate /* re-eval FME */ 17207c478bd9Sstevel@tonic-gate fme_eval(fmep, ffep); 17217c478bd9Sstevel@tonic-gate } else { 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate /* not a match, undo noting of observation */ 17247c478bd9Sstevel@tonic-gate fmep->ecurrent = NULL; 17257c478bd9Sstevel@tonic-gate if (--ep->count == 0) { 17267c478bd9Sstevel@tonic-gate /* unlink it from observations */ 17277c478bd9Sstevel@tonic-gate fmep->observations = ep->observations; 17287c478bd9Sstevel@tonic-gate ep->observations = NULL; 17297c478bd9Sstevel@tonic-gate nvlist_free(ep->nvp); 17307c478bd9Sstevel@tonic-gate ep->nvp = NULL; 17317aec1d6eScindi } else { 17327aec1d6eScindi nvlist_free(ep->nvp); 17337aec1d6eScindi ep->nvp = pre_peek_nvp; 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate if (matched) 17397c478bd9Sstevel@tonic-gate return; /* explained by at least one existing FME */ 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate /* clean up closed fmes */ 17420cc1f05eSjrutt cfmep = ClosedFMEs; 17430cc1f05eSjrutt while (cfmep != NULL) { 17440cc1f05eSjrutt svfmep = cfmep->next; 17450cc1f05eSjrutt destroy_fme(cfmep); 17460cc1f05eSjrutt cfmep = svfmep; 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate ClosedFMEs = NULL; 17497c478bd9Sstevel@tonic-gate 17500cc1f05eSjrutt if (ofmep) { 17510cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 17520cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 17530cc1f05eSjrutt out(O_ALTFP, " ADDING TO OVERFLOW FME]"); 17540cc1f05eSjrutt if (ffep) 17550cc1f05eSjrutt fmd_case_add_ereport(hdl, ofmep->fmcase, ffep); 17560cc1f05eSjrutt 17570cc1f05eSjrutt return; 17580cc1f05eSjrutt 17590cc1f05eSjrutt } else if (Max_fme && (Open_fme_count >= Max_fme)) { 17600cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 17610cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 17620cc1f05eSjrutt out(O_ALTFP, " MAX OPEN FME REACHED]"); 1763b5016cbbSstephh 1764b5016cbbSstephh fmcase = fmd_case_open(hdl, NULL); 1765b5016cbbSstephh 17660cc1f05eSjrutt /* Create overflow fme */ 1767705e9f42SStephen Hanson if ((fmep = newfme(eventstring, ipp, hdl, fmcase, ffep, 1768705e9f42SStephen Hanson nvl)) == NULL) { 17690cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 17700cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 17710cc1f05eSjrutt out(O_ALTFP, " CANNOT OPEN OVERFLOW FME]"); 17720cc1f05eSjrutt return; 17730cc1f05eSjrutt } 17740cc1f05eSjrutt 17750cc1f05eSjrutt Open_fme_count++; 17760cc1f05eSjrutt 17770cc1f05eSjrutt init_fme_bufs(fmep); 17780cc1f05eSjrutt fmep->overflow = B_TRUE; 17790cc1f05eSjrutt 17800cc1f05eSjrutt if (ffep) 17810cc1f05eSjrutt fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 17820cc1f05eSjrutt 178332d4e834STarik Soydan Undiag_reason = UD_VAL_MAXFME; 178432d4e834STarik Soydan defect = fmd_nvl_create_fault(hdl, 178532d4e834STarik Soydan undiag_2defect_str(Undiag_reason), 100, NULL, NULL, NULL); 1786705e9f42SStephen Hanson reason = undiag_2reason_str(Undiag_reason, NULL); 1787705e9f42SStephen Hanson (void) nvlist_add_string(defect, UNDIAG_REASON, reason); 1788705e9f42SStephen Hanson FREE(reason); 17890cc1f05eSjrutt fmd_case_add_suspect(hdl, fmep->fmcase, defect); 17900cc1f05eSjrutt fmd_case_solve(hdl, fmep->fmcase); 179132d4e834STarik Soydan Undiag_reason = UD_VAL_UNKNOWN; 17920cc1f05eSjrutt return; 17930cc1f05eSjrutt } 17940cc1f05eSjrutt 1795b5016cbbSstephh /* open a case */ 1796b5016cbbSstephh fmcase = fmd_case_open(hdl, NULL); 1797b5016cbbSstephh 17987c478bd9Sstevel@tonic-gate /* start a new FME */ 1799705e9f42SStephen Hanson if ((fmep = newfme(eventstring, ipp, hdl, fmcase, ffep, nvl)) == NULL) { 18007c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 18017c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 18027c478bd9Sstevel@tonic-gate out(O_ALTFP, " CANNOT DIAGNOSE]"); 18037c478bd9Sstevel@tonic-gate return; 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18060cc1f05eSjrutt Open_fme_count++; 18070cc1f05eSjrutt 18087c478bd9Sstevel@tonic-gate init_fme_bufs(fmep); 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 18117c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 18127c478bd9Sstevel@tonic-gate out(O_ALTFP, " created FME%d, case %s]", fmep->id, 18137c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, fmep->fmcase)); 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate ep = fmep->e0; 18167c478bd9Sstevel@tonic-gate ASSERT(ep != NULL); 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate /* note observation */ 18197c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 18207c478bd9Sstevel@tonic-gate if (ep->count++ == 0) { 18217c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 18227c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 18237c478bd9Sstevel@tonic-gate fmep->observations = ep; 18247c478bd9Sstevel@tonic-gate ep->nvp = evnv_dupnvl(nvl); 18257c478bd9Sstevel@tonic-gate serialize_observation(fmep, eventstring, ipp); 18267aec1d6eScindi } else { 18277aec1d6eScindi /* new payload overrides any previous */ 18287aec1d6eScindi nvlist_free(ep->nvp); 18297aec1d6eScindi ep->nvp = evnv_dupnvl(nvl); 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcount); 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate if (ffep) { 18357c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 18367c478bd9Sstevel@tonic-gate fmd_case_setprincipal(hdl, fmep->fmcase, ffep); 18377c478bd9Sstevel@tonic-gate fmep->e0r = ffep; 1838b7d3956bSstephh ep->ffep = ffep; 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate /* give the diagnosis algorithm a shot at the new FME state */ 18427c478bd9Sstevel@tonic-gate fme_eval(fmep, ffep); 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate void 18467c478bd9Sstevel@tonic-gate fme_status(int flags) 18477c478bd9Sstevel@tonic-gate { 18487c478bd9Sstevel@tonic-gate struct fme *fmep; 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate if (FMElist == NULL) { 18517c478bd9Sstevel@tonic-gate out(flags, "No fault management exercises underway."); 18527c478bd9Sstevel@tonic-gate return; 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) 18567c478bd9Sstevel@tonic-gate fme_print(flags, fmep); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate /* 18607c478bd9Sstevel@tonic-gate * "indent" routines used mostly for nicely formatted debug output, but also 18617c478bd9Sstevel@tonic-gate * for sanity checking for infinite recursion bugs. 18627c478bd9Sstevel@tonic-gate */ 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate #define MAX_INDENT 1024 18657c478bd9Sstevel@tonic-gate static const char *indent_s[MAX_INDENT]; 18667c478bd9Sstevel@tonic-gate static int current_indent; 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate static void 18697c478bd9Sstevel@tonic-gate indent_push(const char *s) 18707c478bd9Sstevel@tonic-gate { 18717c478bd9Sstevel@tonic-gate if (current_indent < MAX_INDENT) 18727c478bd9Sstevel@tonic-gate indent_s[current_indent++] = s; 18737c478bd9Sstevel@tonic-gate else 18747c478bd9Sstevel@tonic-gate out(O_DIE, "unexpected recursion depth (%d)", current_indent); 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate static void 18787c478bd9Sstevel@tonic-gate indent_set(const char *s) 18797c478bd9Sstevel@tonic-gate { 18807c478bd9Sstevel@tonic-gate current_indent = 0; 18817c478bd9Sstevel@tonic-gate indent_push(s); 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate static void 18857c478bd9Sstevel@tonic-gate indent_pop(void) 18867c478bd9Sstevel@tonic-gate { 18877c478bd9Sstevel@tonic-gate if (current_indent > 0) 18887c478bd9Sstevel@tonic-gate current_indent--; 18897c478bd9Sstevel@tonic-gate else 18907c478bd9Sstevel@tonic-gate out(O_DIE, "recursion underflow"); 18917c478bd9Sstevel@tonic-gate } 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate static void 18947c478bd9Sstevel@tonic-gate indent(void) 18957c478bd9Sstevel@tonic-gate { 18967c478bd9Sstevel@tonic-gate int i; 18977c478bd9Sstevel@tonic-gate if (!Verbose) 18987c478bd9Sstevel@tonic-gate return; 18997c478bd9Sstevel@tonic-gate for (i = 0; i < current_indent; i++) 19007c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, indent_s[i]); 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate #define SLNEW 1 19047c478bd9Sstevel@tonic-gate #define SLCHANGED 2 19057c478bd9Sstevel@tonic-gate #define SLWAIT 3 19067c478bd9Sstevel@tonic-gate #define SLDISPROVED 4 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate static void 19097c478bd9Sstevel@tonic-gate print_suspects(int circumstance, struct fme *fmep) 19107c478bd9Sstevel@tonic-gate { 19117c478bd9Sstevel@tonic-gate struct event *ep; 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 19147c478bd9Sstevel@tonic-gate if (circumstance == SLCHANGED) { 19157c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d diagnosis changed. state: %s, " 19167c478bd9Sstevel@tonic-gate "suspect list:", fmep->id, fme_state2str(fmep->state)); 19177c478bd9Sstevel@tonic-gate } else if (circumstance == SLWAIT) { 1918b5016cbbSstephh out(O_ALTFP|O_NONL, "FME%d set wait timer %ld ", fmep->id, 1919b5016cbbSstephh fmep->timer); 19207c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_NONL, &fmep->wull); 19217c478bd9Sstevel@tonic-gate } else if (circumstance == SLDISPROVED) { 19227c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS UNKNOWN", fmep->id); 19237c478bd9Sstevel@tonic-gate } else { 19247c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS PRODUCED:", fmep->id); 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate if (circumstance == SLWAIT || circumstance == SLDISPROVED) { 19287c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 19297c478bd9Sstevel@tonic-gate return; 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 19337c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, " "); 19347c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_NONL, ep); 19357c478bd9Sstevel@tonic-gate } 19367c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate static struct node * 19407c478bd9Sstevel@tonic-gate eventprop_lookup(struct event *ep, const char *propname) 19417c478bd9Sstevel@tonic-gate { 19427c478bd9Sstevel@tonic-gate return (lut_lookup(ep->props, (void *)propname, NULL)); 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate #define MAXDIGITIDX 23 19467c478bd9Sstevel@tonic-gate static char numbuf[MAXDIGITIDX + 1]; 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate static int 19497c478bd9Sstevel@tonic-gate node2uint(struct node *n, uint_t *valp) 19507c478bd9Sstevel@tonic-gate { 19517c478bd9Sstevel@tonic-gate struct evalue value; 19527c478bd9Sstevel@tonic-gate struct lut *globals = NULL; 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate if (n == NULL) 19557c478bd9Sstevel@tonic-gate return (1); 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate /* 19587c478bd9Sstevel@tonic-gate * check value.v since we are being asked to convert an unsigned 19597c478bd9Sstevel@tonic-gate * long long int to an unsigned int 19607c478bd9Sstevel@tonic-gate */ 19617c478bd9Sstevel@tonic-gate if (! eval_expr(n, NULL, NULL, &globals, NULL, NULL, 0, &value) || 19627c478bd9Sstevel@tonic-gate value.t != UINT64 || value.v > (1ULL << 32)) 19637c478bd9Sstevel@tonic-gate return (1); 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate *valp = (uint_t)value.v; 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate return (0); 19687c478bd9Sstevel@tonic-gate } 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate static nvlist_t * 19717c478bd9Sstevel@tonic-gate node2fmri(struct node *n) 19727c478bd9Sstevel@tonic-gate { 19737c478bd9Sstevel@tonic-gate nvlist_t **pa, *f, *p; 19747c478bd9Sstevel@tonic-gate struct node *nc; 19757c478bd9Sstevel@tonic-gate uint_t depth = 0; 19767c478bd9Sstevel@tonic-gate char *numstr, *nullbyte; 19777c478bd9Sstevel@tonic-gate char *failure; 19787c478bd9Sstevel@tonic-gate int err, i; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate /* XXX do we need to be able to handle a non-T_NAME node? */ 19817c478bd9Sstevel@tonic-gate if (n == NULL || n->t != T_NAME) 19827c478bd9Sstevel@tonic-gate return (NULL); 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate for (nc = n; nc != NULL; nc = nc->u.name.next) { 19857c478bd9Sstevel@tonic-gate if (nc->u.name.child == NULL || nc->u.name.child->t != T_NUM) 19867c478bd9Sstevel@tonic-gate break; 19877c478bd9Sstevel@tonic-gate depth++; 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate if (nc != NULL) { 19917c478bd9Sstevel@tonic-gate /* We bailed early, something went wrong */ 19927c478bd9Sstevel@tonic-gate return (NULL); 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate 19957c478bd9Sstevel@tonic-gate if ((err = nvlist_xalloc(&f, NV_UNIQUE_NAME, &Eft_nv_hdl)) != 0) 19967c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "alloc of fmri nvl failed"); 19977c478bd9Sstevel@tonic-gate pa = alloca(depth * sizeof (nvlist_t *)); 19987c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 19997c478bd9Sstevel@tonic-gate pa[i] = NULL; 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate err = nvlist_add_string(f, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC); 20027c478bd9Sstevel@tonic-gate err |= nvlist_add_uint8(f, FM_VERSION, FM_HC_SCHEME_VERSION); 20037c478bd9Sstevel@tonic-gate err |= nvlist_add_string(f, FM_FMRI_HC_ROOT, ""); 20047c478bd9Sstevel@tonic-gate err |= nvlist_add_uint32(f, FM_FMRI_HC_LIST_SZ, depth); 20057c478bd9Sstevel@tonic-gate if (err != 0) { 20067c478bd9Sstevel@tonic-gate failure = "basic construction of FMRI failed"; 20077c478bd9Sstevel@tonic-gate goto boom; 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate numbuf[MAXDIGITIDX] = '\0'; 20117c478bd9Sstevel@tonic-gate nullbyte = &numbuf[MAXDIGITIDX]; 20127c478bd9Sstevel@tonic-gate i = 0; 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate for (nc = n; nc != NULL; nc = nc->u.name.next) { 20157c478bd9Sstevel@tonic-gate err = nvlist_xalloc(&p, NV_UNIQUE_NAME, &Eft_nv_hdl); 20167c478bd9Sstevel@tonic-gate if (err != 0) { 20177c478bd9Sstevel@tonic-gate failure = "alloc of an hc-pair failed"; 20187c478bd9Sstevel@tonic-gate goto boom; 20197c478bd9Sstevel@tonic-gate } 20207c478bd9Sstevel@tonic-gate err = nvlist_add_string(p, FM_FMRI_HC_NAME, nc->u.name.s); 20217c478bd9Sstevel@tonic-gate numstr = ulltostr(nc->u.name.child->u.ull, nullbyte); 20227c478bd9Sstevel@tonic-gate err |= nvlist_add_string(p, FM_FMRI_HC_ID, numstr); 20237c478bd9Sstevel@tonic-gate if (err != 0) { 20247c478bd9Sstevel@tonic-gate failure = "construction of an hc-pair failed"; 20257c478bd9Sstevel@tonic-gate goto boom; 20267c478bd9Sstevel@tonic-gate } 20277c478bd9Sstevel@tonic-gate pa[i++] = p; 20287c478bd9Sstevel@tonic-gate } 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate err = nvlist_add_nvlist_array(f, FM_FMRI_HC_LIST, pa, depth); 20317c478bd9Sstevel@tonic-gate if (err == 0) { 20327c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 2033aab83bb8SJosef 'Jeff' Sipek nvlist_free(pa[i]); 20347c478bd9Sstevel@tonic-gate return (f); 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate failure = "addition of hc-pair array to FMRI failed"; 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate boom: 20397c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 2040aab83bb8SJosef 'Jeff' Sipek nvlist_free(pa[i]); 20417c478bd9Sstevel@tonic-gate nvlist_free(f); 20427c478bd9Sstevel@tonic-gate out(O_DIE, "%s", failure); 20437c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 204480ab886dSwesolows return (NULL); 20457c478bd9Sstevel@tonic-gate } 20467c478bd9Sstevel@tonic-gate 2047e5ba14ffSstephh /* an ipath cache entry is an array of these, with s==NULL at the end */ 2048e5ba14ffSstephh struct ipath { 2049e5ba14ffSstephh const char *s; /* component name (in stable) */ 2050e5ba14ffSstephh int i; /* instance number */ 2051e5ba14ffSstephh }; 2052e5ba14ffSstephh 2053e5ba14ffSstephh static nvlist_t * 2054e5ba14ffSstephh ipath2fmri(struct ipath *ipath) 2055e5ba14ffSstephh { 2056e5ba14ffSstephh nvlist_t **pa, *f, *p; 2057e5ba14ffSstephh uint_t depth = 0; 2058e5ba14ffSstephh char *numstr, *nullbyte; 2059e5ba14ffSstephh char *failure; 2060e5ba14ffSstephh int err, i; 2061e5ba14ffSstephh struct ipath *ipp; 2062e5ba14ffSstephh 2063e5ba14ffSstephh for (ipp = ipath; ipp->s != NULL; ipp++) 2064e5ba14ffSstephh depth++; 2065e5ba14ffSstephh 2066e5ba14ffSstephh if ((err = nvlist_xalloc(&f, NV_UNIQUE_NAME, &Eft_nv_hdl)) != 0) 2067e5ba14ffSstephh out(O_DIE|O_SYS, "alloc of fmri nvl failed"); 2068e5ba14ffSstephh pa = alloca(depth * sizeof (nvlist_t *)); 2069e5ba14ffSstephh for (i = 0; i < depth; i++) 2070e5ba14ffSstephh pa[i] = NULL; 2071e5ba14ffSstephh 2072e5ba14ffSstephh err = nvlist_add_string(f, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC); 2073e5ba14ffSstephh err |= nvlist_add_uint8(f, FM_VERSION, FM_HC_SCHEME_VERSION); 2074e5ba14ffSstephh err |= nvlist_add_string(f, FM_FMRI_HC_ROOT, ""); 2075e5ba14ffSstephh err |= nvlist_add_uint32(f, FM_FMRI_HC_LIST_SZ, depth); 2076e5ba14ffSstephh if (err != 0) { 2077e5ba14ffSstephh failure = "basic construction of FMRI failed"; 2078e5ba14ffSstephh goto boom; 2079e5ba14ffSstephh } 2080e5ba14ffSstephh 2081e5ba14ffSstephh numbuf[MAXDIGITIDX] = '\0'; 2082e5ba14ffSstephh nullbyte = &numbuf[MAXDIGITIDX]; 2083e5ba14ffSstephh i = 0; 2084e5ba14ffSstephh 2085e5ba14ffSstephh for (ipp = ipath; ipp->s != NULL; ipp++) { 2086e5ba14ffSstephh err = nvlist_xalloc(&p, NV_UNIQUE_NAME, &Eft_nv_hdl); 2087e5ba14ffSstephh if (err != 0) { 2088e5ba14ffSstephh failure = "alloc of an hc-pair failed"; 2089e5ba14ffSstephh goto boom; 2090e5ba14ffSstephh } 2091e5ba14ffSstephh err = nvlist_add_string(p, FM_FMRI_HC_NAME, ipp->s); 2092e5ba14ffSstephh numstr = ulltostr(ipp->i, nullbyte); 2093e5ba14ffSstephh err |= nvlist_add_string(p, FM_FMRI_HC_ID, numstr); 2094e5ba14ffSstephh if (err != 0) { 2095e5ba14ffSstephh failure = "construction of an hc-pair failed"; 2096e5ba14ffSstephh goto boom; 2097e5ba14ffSstephh } 2098e5ba14ffSstephh pa[i++] = p; 2099e5ba14ffSstephh } 2100e5ba14ffSstephh 2101e5ba14ffSstephh err = nvlist_add_nvlist_array(f, FM_FMRI_HC_LIST, pa, depth); 2102e5ba14ffSstephh if (err == 0) { 2103e5ba14ffSstephh for (i = 0; i < depth; i++) 2104aab83bb8SJosef 'Jeff' Sipek nvlist_free(pa[i]); 2105e5ba14ffSstephh return (f); 2106e5ba14ffSstephh } 2107e5ba14ffSstephh failure = "addition of hc-pair array to FMRI failed"; 2108e5ba14ffSstephh 2109e5ba14ffSstephh boom: 2110e5ba14ffSstephh for (i = 0; i < depth; i++) 2111aab83bb8SJosef 'Jeff' Sipek nvlist_free(pa[i]); 2112e5ba14ffSstephh nvlist_free(f); 2113e5ba14ffSstephh out(O_DIE, "%s", failure); 2114e5ba14ffSstephh /*NOTREACHED*/ 2115e5ba14ffSstephh return (NULL); 2116e5ba14ffSstephh } 2117e5ba14ffSstephh 21187c478bd9Sstevel@tonic-gate static uint8_t 21197c478bd9Sstevel@tonic-gate percentof(uint_t part, uint_t whole) 21207c478bd9Sstevel@tonic-gate { 21217c478bd9Sstevel@tonic-gate unsigned long long p = part * 1000; 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate return ((p / whole / 10) + (((p / whole % 10) >= 5) ? 1 : 0)); 21247c478bd9Sstevel@tonic-gate } 21257c478bd9Sstevel@tonic-gate 212680ab886dSwesolows struct rsl { 21277c478bd9Sstevel@tonic-gate struct event *suspect; 21287c478bd9Sstevel@tonic-gate nvlist_t *asru; 21297c478bd9Sstevel@tonic-gate nvlist_t *fru; 21307c478bd9Sstevel@tonic-gate nvlist_t *rsrc; 21317c478bd9Sstevel@tonic-gate }; 21327c478bd9Sstevel@tonic-gate 2133b7d3956bSstephh static void publish_suspects(struct fme *fmep, struct rsl *srl); 2134b7d3956bSstephh 21357c478bd9Sstevel@tonic-gate /* 21367c478bd9Sstevel@tonic-gate * rslfree -- free internal members of struct rsl not expected to be 21377c478bd9Sstevel@tonic-gate * freed elsewhere. 21387c478bd9Sstevel@tonic-gate */ 21397c478bd9Sstevel@tonic-gate static void 21407c478bd9Sstevel@tonic-gate rslfree(struct rsl *freeme) 21417c478bd9Sstevel@tonic-gate { 2142aab83bb8SJosef 'Jeff' Sipek nvlist_free(freeme->asru); 2143aab83bb8SJosef 'Jeff' Sipek nvlist_free(freeme->fru); 2144aab83bb8SJosef 'Jeff' Sipek if (freeme->rsrc != freeme->asru) 21457c478bd9Sstevel@tonic-gate nvlist_free(freeme->rsrc); 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate /* 21497c478bd9Sstevel@tonic-gate * rslcmp -- compare two rsl structures. Use the following 21507c478bd9Sstevel@tonic-gate * comparisons to establish cardinality: 21517c478bd9Sstevel@tonic-gate * 21527c478bd9Sstevel@tonic-gate * 1. Name of the suspect's class. (simple strcmp) 21537c478bd9Sstevel@tonic-gate * 2. Name of the suspect's ASRU. (trickier, since nvlist) 21547c478bd9Sstevel@tonic-gate * 21557c478bd9Sstevel@tonic-gate */ 21567c478bd9Sstevel@tonic-gate static int 21577c478bd9Sstevel@tonic-gate rslcmp(const void *a, const void *b) 21587c478bd9Sstevel@tonic-gate { 21597c478bd9Sstevel@tonic-gate struct rsl *r1 = (struct rsl *)a; 21607c478bd9Sstevel@tonic-gate struct rsl *r2 = (struct rsl *)b; 21617c478bd9Sstevel@tonic-gate int rv; 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate rv = strcmp(r1->suspect->enode->u.event.ename->u.name.s, 21647c478bd9Sstevel@tonic-gate r2->suspect->enode->u.event.ename->u.name.s); 21657c478bd9Sstevel@tonic-gate if (rv != 0) 21667c478bd9Sstevel@tonic-gate return (rv); 21677c478bd9Sstevel@tonic-gate 2168b7d3956bSstephh if (r1->rsrc == NULL && r2->rsrc == NULL) 21697c478bd9Sstevel@tonic-gate return (0); 2170b7d3956bSstephh if (r1->rsrc == NULL) 21717c478bd9Sstevel@tonic-gate return (-1); 2172b7d3956bSstephh if (r2->rsrc == NULL) 21737c478bd9Sstevel@tonic-gate return (1); 2174b7d3956bSstephh return (evnv_cmpnvl(r1->rsrc, r2->rsrc, 0)); 21757c478bd9Sstevel@tonic-gate } 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate /* 21787c478bd9Sstevel@tonic-gate * get_resources -- for a given suspect, determine what ASRU, FRU and 21797c478bd9Sstevel@tonic-gate * RSRC nvlists should be advertised in the final suspect list. 21807c478bd9Sstevel@tonic-gate */ 21817c478bd9Sstevel@tonic-gate void 21827c478bd9Sstevel@tonic-gate get_resources(struct event *sp, struct rsl *rsrcs, struct config *croot) 21837c478bd9Sstevel@tonic-gate { 21847c478bd9Sstevel@tonic-gate struct node *asrudef, *frudef; 2185*da40b264SAlex Wilson const struct ipath *asrupath, *frupath; 2186*da40b264SAlex Wilson nvlist_t *asru = NULL, *fru = NULL; 21877c478bd9Sstevel@tonic-gate nvlist_t *rsrc = NULL; 21887c478bd9Sstevel@tonic-gate char *pathstr; 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate /* 21917c478bd9Sstevel@tonic-gate * First find any ASRU and/or FRU defined in the 21927c478bd9Sstevel@tonic-gate * initial fault tree. 21937c478bd9Sstevel@tonic-gate */ 21947c478bd9Sstevel@tonic-gate asrudef = eventprop_lookup(sp, L_ASRU); 21957c478bd9Sstevel@tonic-gate frudef = eventprop_lookup(sp, L_FRU); 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate /* 2198*da40b264SAlex Wilson * Create ipaths based on those definitions 21997c478bd9Sstevel@tonic-gate */ 2200*da40b264SAlex Wilson asrupath = ipath(asrudef); 2201*da40b264SAlex Wilson frupath = ipath(frudef); 22027c478bd9Sstevel@tonic-gate 22037c478bd9Sstevel@tonic-gate /* 2204b7d3956bSstephh * Allow for platform translations of the FMRIs 22057c478bd9Sstevel@tonic-gate */ 2206*da40b264SAlex Wilson pathstr = ipath2str(NULL, sp->ipp); 2207*da40b264SAlex Wilson platform_unit_translate(is_defect(sp->t), croot, TOPO_PROP_RESOURCE, 2208*da40b264SAlex Wilson &rsrc, pathstr); 2209*da40b264SAlex Wilson FREE(pathstr); 22107c478bd9Sstevel@tonic-gate 2211*da40b264SAlex Wilson pathstr = ipath2str(NULL, asrupath); 2212*da40b264SAlex Wilson platform_unit_translate(is_defect(sp->t), croot, TOPO_PROP_ASRU, 2213*da40b264SAlex Wilson &asru, pathstr); 22147c478bd9Sstevel@tonic-gate FREE(pathstr); 2215*da40b264SAlex Wilson 2216*da40b264SAlex Wilson pathstr = ipath2str(NULL, frupath); 2217*da40b264SAlex Wilson platform_unit_translate(is_defect(sp->t), croot, TOPO_PROP_FRU, 2218*da40b264SAlex Wilson &fru, pathstr); 2219*da40b264SAlex Wilson FREE(pathstr); 2220*da40b264SAlex Wilson 22217c478bd9Sstevel@tonic-gate rsrcs->suspect = sp; 22227c478bd9Sstevel@tonic-gate rsrcs->asru = asru; 22237c478bd9Sstevel@tonic-gate rsrcs->fru = fru; 22247c478bd9Sstevel@tonic-gate rsrcs->rsrc = rsrc; 22257c478bd9Sstevel@tonic-gate } 22267c478bd9Sstevel@tonic-gate 22277c478bd9Sstevel@tonic-gate /* 22287c478bd9Sstevel@tonic-gate * trim_suspects -- prior to publishing, we may need to remove some 22297c478bd9Sstevel@tonic-gate * suspects from the list. If we're auto-closing upsets, we don't 22307c478bd9Sstevel@tonic-gate * want any of those in the published list. If the ASRUs for multiple 22317c478bd9Sstevel@tonic-gate * defects resolve to the same ASRU (driver) we only want to publish 22327c478bd9Sstevel@tonic-gate * that as a single suspect. 22337c478bd9Sstevel@tonic-gate */ 2234b7d3956bSstephh static int 2235b7d3956bSstephh trim_suspects(struct fme *fmep, struct rsl *begin, struct rsl *begin2, 22368e7248e5SStephen Hanson fmd_event_t *ffep) 22377c478bd9Sstevel@tonic-gate { 22387c478bd9Sstevel@tonic-gate struct event *ep; 2239b7d3956bSstephh struct rsl *rp = begin; 2240b7d3956bSstephh struct rsl *rp2 = begin2; 2241b7d3956bSstephh int mess_zero_count = 0; 2242b7d3956bSstephh int serd_rval; 2243b7d3956bSstephh uint_t messval; 22447c478bd9Sstevel@tonic-gate 2245b7d3956bSstephh /* remove any unwanted upsets and populate our array */ 22467c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = ep->psuspects) { 2247b7d3956bSstephh if (is_upset(ep->t)) 22487c478bd9Sstevel@tonic-gate continue; 2249b7d3956bSstephh serd_rval = serd_eval(fmep, fmep->hdl, ffep, fmep->fmcase, ep, 2250b7d3956bSstephh NULL, NULL); 2251b7d3956bSstephh if (serd_rval == 0) 2252b7d3956bSstephh continue; 2253b7d3956bSstephh if (node2uint(eventprop_lookup(ep, L_message), 2254b7d3956bSstephh &messval) == 0 && messval == 0) { 2255b7d3956bSstephh get_resources(ep, rp2, fmep->config); 2256b7d3956bSstephh rp2++; 2257b7d3956bSstephh mess_zero_count++; 2258b7d3956bSstephh } else { 2259b7d3956bSstephh get_resources(ep, rp, fmep->config); 2260b7d3956bSstephh rp++; 2261b7d3956bSstephh fmep->nsuspects++; 2262b7d3956bSstephh } 22637c478bd9Sstevel@tonic-gate } 2264b7d3956bSstephh return (mess_zero_count); 22657c478bd9Sstevel@tonic-gate } 22667c478bd9Sstevel@tonic-gate 22677aec1d6eScindi /* 22687aec1d6eScindi * addpayloadprop -- add a payload prop to a problem 22697aec1d6eScindi */ 22707aec1d6eScindi static void 22717aec1d6eScindi addpayloadprop(const char *lhs, struct evalue *rhs, nvlist_t *fault) 22727aec1d6eScindi { 2273b7d3956bSstephh nvlist_t *rsrc, *hcs; 2274b7d3956bSstephh 22757aec1d6eScindi ASSERT(fault != NULL); 22767aec1d6eScindi ASSERT(lhs != NULL); 22777aec1d6eScindi ASSERT(rhs != NULL); 22787aec1d6eScindi 2279b7d3956bSstephh if (nvlist_lookup_nvlist(fault, FM_FAULT_RESOURCE, &rsrc) != 0) 2280b7d3956bSstephh out(O_DIE, "cannot add payloadprop \"%s\" to fault", lhs); 2281b7d3956bSstephh 2282b7d3956bSstephh if (nvlist_lookup_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, &hcs) != 0) { 2283b7d3956bSstephh out(O_ALTFP|O_VERB2, "addpayloadprop: create hc_specific"); 2284b7d3956bSstephh if (nvlist_xalloc(&hcs, NV_UNIQUE_NAME, &Eft_nv_hdl) != 0) 2285b7d3956bSstephh out(O_DIE, 2286b7d3956bSstephh "cannot add payloadprop \"%s\" to fault", lhs); 2287b7d3956bSstephh if (nvlist_add_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, hcs) != 0) 2288b7d3956bSstephh out(O_DIE, 2289b7d3956bSstephh "cannot add payloadprop \"%s\" to fault", lhs); 2290b7d3956bSstephh nvlist_free(hcs); 2291b7d3956bSstephh if (nvlist_lookup_nvlist(rsrc, FM_FMRI_HC_SPECIFIC, &hcs) != 0) 2292b7d3956bSstephh out(O_DIE, 2293b7d3956bSstephh "cannot add payloadprop \"%s\" to fault", lhs); 2294b7d3956bSstephh } else 2295b7d3956bSstephh out(O_ALTFP|O_VERB2, "addpayloadprop: reuse hc_specific"); 2296b7d3956bSstephh 22977aec1d6eScindi if (rhs->t == UINT64) { 22987aec1d6eScindi out(O_ALTFP|O_VERB2, "addpayloadprop: %s=%llu", lhs, rhs->v); 22997aec1d6eScindi 2300b7d3956bSstephh if (nvlist_add_uint64(hcs, lhs, rhs->v) != 0) 23017aec1d6eScindi out(O_DIE, 23027aec1d6eScindi "cannot add payloadprop \"%s\" to fault", lhs); 23037aec1d6eScindi } else { 23047aec1d6eScindi out(O_ALTFP|O_VERB2, "addpayloadprop: %s=\"%s\"", 230580ab886dSwesolows lhs, (char *)(uintptr_t)rhs->v); 23067aec1d6eScindi 2307b7d3956bSstephh if (nvlist_add_string(hcs, lhs, (char *)(uintptr_t)rhs->v) != 0) 23087aec1d6eScindi out(O_DIE, 23097aec1d6eScindi "cannot add payloadprop \"%s\" to fault", lhs); 23107aec1d6eScindi } 23117aec1d6eScindi } 23127aec1d6eScindi 23137aec1d6eScindi static char *Istatbuf; 23147aec1d6eScindi static char *Istatbufptr; 23157aec1d6eScindi static int Istatsz; 23167aec1d6eScindi 23177aec1d6eScindi /* 23187aec1d6eScindi * istataddsize -- calculate size of istat and add it to Istatsz 23197aec1d6eScindi */ 23207aec1d6eScindi /*ARGSUSED2*/ 23217aec1d6eScindi static void 23227aec1d6eScindi istataddsize(const struct istat_entry *lhs, struct stats *rhs, void *arg) 23237aec1d6eScindi { 23247aec1d6eScindi int val; 23257aec1d6eScindi 23267aec1d6eScindi ASSERT(lhs != NULL); 23277aec1d6eScindi ASSERT(rhs != NULL); 23287aec1d6eScindi 23297aec1d6eScindi if ((val = stats_counter_value(rhs)) == 0) 23307aec1d6eScindi return; /* skip zero-valued stats */ 23317aec1d6eScindi 23327aec1d6eScindi /* count up the size of the stat name */ 23337aec1d6eScindi Istatsz += ipath2strlen(lhs->ename, lhs->ipath); 23347aec1d6eScindi Istatsz++; /* for the trailing NULL byte */ 23357aec1d6eScindi 23367aec1d6eScindi /* count up the size of the stat value */ 23377aec1d6eScindi Istatsz += snprintf(NULL, 0, "%d", val); 23387aec1d6eScindi Istatsz++; /* for the trailing NULL byte */ 23397aec1d6eScindi } 23407aec1d6eScindi 23417aec1d6eScindi /* 23427aec1d6eScindi * istat2str -- serialize an istat, writing result to *Istatbufptr 23437aec1d6eScindi */ 23447aec1d6eScindi /*ARGSUSED2*/ 23457aec1d6eScindi static void 23467aec1d6eScindi istat2str(const struct istat_entry *lhs, struct stats *rhs, void *arg) 23477aec1d6eScindi { 23487aec1d6eScindi char *str; 23497aec1d6eScindi int len; 23507aec1d6eScindi int val; 23517aec1d6eScindi 23527aec1d6eScindi ASSERT(lhs != NULL); 23537aec1d6eScindi ASSERT(rhs != NULL); 23547aec1d6eScindi 23557aec1d6eScindi if ((val = stats_counter_value(rhs)) == 0) 23567aec1d6eScindi return; /* skip zero-valued stats */ 23577aec1d6eScindi 23587aec1d6eScindi /* serialize the stat name */ 23597aec1d6eScindi str = ipath2str(lhs->ename, lhs->ipath); 23607aec1d6eScindi len = strlen(str); 23617aec1d6eScindi 23627aec1d6eScindi ASSERT(Istatbufptr + len + 1 < &Istatbuf[Istatsz]); 23637aec1d6eScindi (void) strlcpy(Istatbufptr, str, &Istatbuf[Istatsz] - Istatbufptr); 23647aec1d6eScindi Istatbufptr += len; 23657aec1d6eScindi FREE(str); 23667aec1d6eScindi *Istatbufptr++ = '\0'; 23677aec1d6eScindi 23687aec1d6eScindi /* serialize the stat value */ 23697aec1d6eScindi Istatbufptr += snprintf(Istatbufptr, &Istatbuf[Istatsz] - Istatbufptr, 23707aec1d6eScindi "%d", val); 23717aec1d6eScindi *Istatbufptr++ = '\0'; 23727aec1d6eScindi 23737aec1d6eScindi ASSERT(Istatbufptr <= &Istatbuf[Istatsz]); 23747aec1d6eScindi } 23757aec1d6eScindi 23767aec1d6eScindi void 23777aec1d6eScindi istat_save() 23787aec1d6eScindi { 23797aec1d6eScindi if (Istat_need_save == 0) 23807aec1d6eScindi return; 23817aec1d6eScindi 23827aec1d6eScindi /* figure out how big the serialzed info is */ 23837aec1d6eScindi Istatsz = 0; 23847aec1d6eScindi lut_walk(Istats, (lut_cb)istataddsize, NULL); 23857aec1d6eScindi 23867aec1d6eScindi if (Istatsz == 0) { 23877aec1d6eScindi /* no stats to save */ 23887aec1d6eScindi fmd_buf_destroy(Hdl, NULL, WOBUF_ISTATS); 23897aec1d6eScindi return; 23907aec1d6eScindi } 23917aec1d6eScindi 23927aec1d6eScindi /* create the serialized buffer */ 23937aec1d6eScindi Istatbufptr = Istatbuf = MALLOC(Istatsz); 23947aec1d6eScindi lut_walk(Istats, (lut_cb)istat2str, NULL); 23957aec1d6eScindi 23967aec1d6eScindi /* clear out current saved stats */ 23977aec1d6eScindi fmd_buf_destroy(Hdl, NULL, WOBUF_ISTATS); 23987aec1d6eScindi 23997aec1d6eScindi /* write out the new version */ 24007aec1d6eScindi fmd_buf_write(Hdl, NULL, WOBUF_ISTATS, Istatbuf, Istatsz); 24017aec1d6eScindi FREE(Istatbuf); 24027aec1d6eScindi 24037aec1d6eScindi Istat_need_save = 0; 24047aec1d6eScindi } 24057aec1d6eScindi 24067aec1d6eScindi int 24077aec1d6eScindi istat_cmp(struct istat_entry *ent1, struct istat_entry *ent2) 24087aec1d6eScindi { 24097aec1d6eScindi if (ent1->ename != ent2->ename) 24107aec1d6eScindi return (ent2->ename - ent1->ename); 24117aec1d6eScindi if (ent1->ipath != ent2->ipath) 24127aec1d6eScindi return ((char *)ent2->ipath - (char *)ent1->ipath); 24137aec1d6eScindi 24147aec1d6eScindi return (0); 24157aec1d6eScindi } 24167aec1d6eScindi 24177aec1d6eScindi /* 24187aec1d6eScindi * istat-verify -- verify the component associated with a stat still exists 24197aec1d6eScindi * 24207aec1d6eScindi * if the component no longer exists, this routine resets the stat and 24217aec1d6eScindi * returns 0. if the component still exists, it returns 1. 24227aec1d6eScindi */ 24237aec1d6eScindi static int 24247aec1d6eScindi istat_verify(struct node *snp, struct istat_entry *entp) 24257aec1d6eScindi { 24267aec1d6eScindi struct stats *statp; 24277aec1d6eScindi nvlist_t *fmri; 24287aec1d6eScindi 24297aec1d6eScindi fmri = node2fmri(snp->u.event.epname); 24307aec1d6eScindi if (platform_path_exists(fmri)) { 24317aec1d6eScindi nvlist_free(fmri); 24327aec1d6eScindi return (1); 24337aec1d6eScindi } 24347aec1d6eScindi nvlist_free(fmri); 24357aec1d6eScindi 24367aec1d6eScindi /* component no longer in system. zero out the associated stats */ 24377aec1d6eScindi if ((statp = (struct stats *) 24387aec1d6eScindi lut_lookup(Istats, entp, (lut_cmp)istat_cmp)) == NULL || 24397aec1d6eScindi stats_counter_value(statp) == 0) 24407aec1d6eScindi return (0); /* stat is already reset */ 24417aec1d6eScindi 24427aec1d6eScindi Istat_need_save = 1; 24437aec1d6eScindi stats_counter_reset(statp); 24447aec1d6eScindi return (0); 24457aec1d6eScindi } 24467aec1d6eScindi 24477aec1d6eScindi static void 24487aec1d6eScindi istat_bump(struct node *snp, int n) 24497aec1d6eScindi { 24507aec1d6eScindi struct stats *statp; 24517aec1d6eScindi struct istat_entry ent; 24527aec1d6eScindi 24537aec1d6eScindi ASSERT(snp != NULL); 24547aec1d6eScindi ASSERTinfo(snp->t == T_EVENT, ptree_nodetype2str(snp->t)); 24557aec1d6eScindi ASSERT(snp->u.event.epname != NULL); 24567aec1d6eScindi 24577aec1d6eScindi /* class name should be hoisted into a single stable entry */ 24587aec1d6eScindi ASSERT(snp->u.event.ename->u.name.next == NULL); 24597aec1d6eScindi ent.ename = snp->u.event.ename->u.name.s; 24607aec1d6eScindi ent.ipath = ipath(snp->u.event.epname); 24617aec1d6eScindi 24627aec1d6eScindi if (!istat_verify(snp, &ent)) { 24637aec1d6eScindi /* component no longer exists in system, nothing to do */ 24647aec1d6eScindi return; 24657aec1d6eScindi } 24667aec1d6eScindi 24677aec1d6eScindi if ((statp = (struct stats *) 24687aec1d6eScindi lut_lookup(Istats, &ent, (lut_cmp)istat_cmp)) == NULL) { 24697aec1d6eScindi /* need to create the counter */ 24707aec1d6eScindi int cnt = 0; 24717aec1d6eScindi struct node *np; 24727aec1d6eScindi char *sname; 24737aec1d6eScindi char *snamep; 24747aec1d6eScindi struct istat_entry *newentp; 24757aec1d6eScindi 24767aec1d6eScindi /* count up the size of the stat name */ 24777aec1d6eScindi np = snp->u.event.ename; 24787aec1d6eScindi while (np != NULL) { 24797aec1d6eScindi cnt += strlen(np->u.name.s); 24807aec1d6eScindi cnt++; /* for the '.' or '@' */ 24817aec1d6eScindi np = np->u.name.next; 24827aec1d6eScindi } 24837aec1d6eScindi np = snp->u.event.epname; 24847aec1d6eScindi while (np != NULL) { 24857aec1d6eScindi cnt += snprintf(NULL, 0, "%s%llu", 24867aec1d6eScindi np->u.name.s, np->u.name.child->u.ull); 24877aec1d6eScindi cnt++; /* for the '/' or trailing NULL byte */ 24887aec1d6eScindi np = np->u.name.next; 24897aec1d6eScindi } 24907aec1d6eScindi 24917aec1d6eScindi /* build the stat name */ 24927aec1d6eScindi snamep = sname = alloca(cnt); 24937aec1d6eScindi np = snp->u.event.ename; 24947aec1d6eScindi while (np != NULL) { 24957aec1d6eScindi snamep += snprintf(snamep, &sname[cnt] - snamep, 24967aec1d6eScindi "%s", np->u.name.s); 24977aec1d6eScindi np = np->u.name.next; 24987aec1d6eScindi if (np) 24997aec1d6eScindi *snamep++ = '.'; 25007aec1d6eScindi } 25017aec1d6eScindi *snamep++ = '@'; 25027aec1d6eScindi np = snp->u.event.epname; 25037aec1d6eScindi while (np != NULL) { 25047aec1d6eScindi snamep += snprintf(snamep, &sname[cnt] - snamep, 25057aec1d6eScindi "%s%llu", np->u.name.s, np->u.name.child->u.ull); 25067aec1d6eScindi np = np->u.name.next; 25077aec1d6eScindi if (np) 25087aec1d6eScindi *snamep++ = '/'; 25097aec1d6eScindi } 25107aec1d6eScindi *snamep++ = '\0'; 25117aec1d6eScindi 25127aec1d6eScindi /* create the new stat & add it to our list */ 25137aec1d6eScindi newentp = MALLOC(sizeof (*newentp)); 25147aec1d6eScindi *newentp = ent; 25157aec1d6eScindi statp = stats_new_counter(NULL, sname, 0); 25167aec1d6eScindi Istats = lut_add(Istats, (void *)newentp, (void *)statp, 25177aec1d6eScindi (lut_cmp)istat_cmp); 25187aec1d6eScindi } 25197aec1d6eScindi 25207aec1d6eScindi /* if n is non-zero, set that value instead of bumping */ 25217aec1d6eScindi if (n) { 25227aec1d6eScindi stats_counter_reset(statp); 25237aec1d6eScindi stats_counter_add(statp, n); 25247aec1d6eScindi } else 25257aec1d6eScindi stats_counter_bump(statp); 25267aec1d6eScindi Istat_need_save = 1; 25278a40a695Sgavinm 25288a40a695Sgavinm ipath_print(O_ALTFP|O_VERB2, ent.ename, ent.ipath); 25298a40a695Sgavinm out(O_ALTFP|O_VERB2, " %s to value %d", n ? "set" : "incremented", 25308a40a695Sgavinm stats_counter_value(statp)); 25317aec1d6eScindi } 25327aec1d6eScindi 25337aec1d6eScindi /*ARGSUSED*/ 25347aec1d6eScindi static void 25357aec1d6eScindi istat_destructor(void *left, void *right, void *arg) 25367aec1d6eScindi { 25377aec1d6eScindi struct istat_entry *entp = (struct istat_entry *)left; 25387aec1d6eScindi struct stats *statp = (struct stats *)right; 25397aec1d6eScindi FREE(entp); 25407aec1d6eScindi stats_delete(statp); 25417aec1d6eScindi } 25427aec1d6eScindi 254308f6c065Sgavinm /* 254408f6c065Sgavinm * Callback used in a walk of the Istats to reset matching stat counters. 254508f6c065Sgavinm */ 254608f6c065Sgavinm static void 254708f6c065Sgavinm istat_counter_reset_cb(struct istat_entry *entp, struct stats *statp, 254808f6c065Sgavinm const struct ipath *ipp) 254908f6c065Sgavinm { 255008f6c065Sgavinm char *path; 255108f6c065Sgavinm 255208f6c065Sgavinm if (entp->ipath == ipp) { 255308f6c065Sgavinm path = ipath2str(entp->ename, ipp); 255408f6c065Sgavinm out(O_ALTFP, "istat_counter_reset_cb: resetting %s", path); 255508f6c065Sgavinm FREE(path); 255608f6c065Sgavinm stats_counter_reset(statp); 255708f6c065Sgavinm Istat_need_save = 1; 255808f6c065Sgavinm } 255908f6c065Sgavinm } 256008f6c065Sgavinm 2561e5ba14ffSstephh /*ARGSUSED*/ 2562e5ba14ffSstephh static void 2563e5ba14ffSstephh istat_counter_topo_chg_cb(struct istat_entry *entp, struct stats *statp, 2564e5ba14ffSstephh void *unused) 2565e5ba14ffSstephh { 2566e5ba14ffSstephh char *path; 2567e5ba14ffSstephh nvlist_t *fmri; 2568e5ba14ffSstephh 2569e5ba14ffSstephh fmri = ipath2fmri((struct ipath *)(entp->ipath)); 2570e5ba14ffSstephh if (!platform_path_exists(fmri)) { 2571e5ba14ffSstephh path = ipath2str(entp->ename, entp->ipath); 2572e5ba14ffSstephh out(O_ALTFP, "istat_counter_topo_chg_cb: not present %s", path); 2573e5ba14ffSstephh FREE(path); 2574e5ba14ffSstephh stats_counter_reset(statp); 2575e5ba14ffSstephh Istat_need_save = 1; 2576e5ba14ffSstephh } 2577e5ba14ffSstephh nvlist_free(fmri); 2578e5ba14ffSstephh } 2579e5ba14ffSstephh 25807aec1d6eScindi void 25817aec1d6eScindi istat_fini(void) 25827aec1d6eScindi { 25837aec1d6eScindi lut_free(Istats, istat_destructor, NULL); 25847aec1d6eScindi } 25857aec1d6eScindi 2586b5016cbbSstephh static char *Serdbuf; 2587b5016cbbSstephh static char *Serdbufptr; 2588b5016cbbSstephh static int Serdsz; 2589b5016cbbSstephh 2590b5016cbbSstephh /* 2591b5016cbbSstephh * serdaddsize -- calculate size of serd and add it to Serdsz 2592b5016cbbSstephh */ 2593b5016cbbSstephh /*ARGSUSED*/ 2594b5016cbbSstephh static void 2595b5016cbbSstephh serdaddsize(const struct serd_entry *lhs, struct stats *rhs, void *arg) 2596b5016cbbSstephh { 2597b5016cbbSstephh ASSERT(lhs != NULL); 2598b5016cbbSstephh 2599b5016cbbSstephh /* count up the size of the stat name */ 2600b5016cbbSstephh Serdsz += ipath2strlen(lhs->ename, lhs->ipath); 2601b5016cbbSstephh Serdsz++; /* for the trailing NULL byte */ 2602b5016cbbSstephh } 2603b5016cbbSstephh 2604b5016cbbSstephh /* 2605b5016cbbSstephh * serd2str -- serialize a serd engine, writing result to *Serdbufptr 2606b5016cbbSstephh */ 2607b5016cbbSstephh /*ARGSUSED*/ 2608b5016cbbSstephh static void 2609b5016cbbSstephh serd2str(const struct serd_entry *lhs, struct stats *rhs, void *arg) 2610b5016cbbSstephh { 2611b5016cbbSstephh char *str; 2612b5016cbbSstephh int len; 2613b5016cbbSstephh 2614b5016cbbSstephh ASSERT(lhs != NULL); 2615b5016cbbSstephh 2616b5016cbbSstephh /* serialize the serd engine name */ 2617b5016cbbSstephh str = ipath2str(lhs->ename, lhs->ipath); 2618b5016cbbSstephh len = strlen(str); 2619b5016cbbSstephh 2620b5016cbbSstephh ASSERT(Serdbufptr + len + 1 <= &Serdbuf[Serdsz]); 2621b5016cbbSstephh (void) strlcpy(Serdbufptr, str, &Serdbuf[Serdsz] - Serdbufptr); 2622b5016cbbSstephh Serdbufptr += len; 2623b5016cbbSstephh FREE(str); 2624b5016cbbSstephh *Serdbufptr++ = '\0'; 2625b5016cbbSstephh ASSERT(Serdbufptr <= &Serdbuf[Serdsz]); 2626b5016cbbSstephh } 2627b5016cbbSstephh 2628b5016cbbSstephh void 2629b5016cbbSstephh serd_save() 2630b5016cbbSstephh { 2631b5016cbbSstephh if (Serd_need_save == 0) 2632b5016cbbSstephh return; 2633b5016cbbSstephh 2634b5016cbbSstephh /* figure out how big the serialzed info is */ 2635b5016cbbSstephh Serdsz = 0; 2636b5016cbbSstephh lut_walk(SerdEngines, (lut_cb)serdaddsize, NULL); 2637b5016cbbSstephh 2638b5016cbbSstephh if (Serdsz == 0) { 2639b5016cbbSstephh /* no serd engines to save */ 2640b5016cbbSstephh fmd_buf_destroy(Hdl, NULL, WOBUF_SERDS); 2641b5016cbbSstephh return; 2642b5016cbbSstephh } 2643b5016cbbSstephh 2644b5016cbbSstephh /* create the serialized buffer */ 2645b5016cbbSstephh Serdbufptr = Serdbuf = MALLOC(Serdsz); 2646b5016cbbSstephh lut_walk(SerdEngines, (lut_cb)serd2str, NULL); 2647b5016cbbSstephh 2648b5016cbbSstephh /* clear out current saved stats */ 2649b5016cbbSstephh fmd_buf_destroy(Hdl, NULL, WOBUF_SERDS); 2650b5016cbbSstephh 2651b5016cbbSstephh /* write out the new version */ 2652b5016cbbSstephh fmd_buf_write(Hdl, NULL, WOBUF_SERDS, Serdbuf, Serdsz); 2653b5016cbbSstephh FREE(Serdbuf); 2654b5016cbbSstephh Serd_need_save = 0; 2655b5016cbbSstephh } 2656b5016cbbSstephh 2657b5016cbbSstephh int 2658b5016cbbSstephh serd_cmp(struct serd_entry *ent1, struct serd_entry *ent2) 2659b5016cbbSstephh { 2660b5016cbbSstephh if (ent1->ename != ent2->ename) 2661b5016cbbSstephh return (ent2->ename - ent1->ename); 2662b5016cbbSstephh if (ent1->ipath != ent2->ipath) 2663b5016cbbSstephh return ((char *)ent2->ipath - (char *)ent1->ipath); 2664b5016cbbSstephh 2665b5016cbbSstephh return (0); 2666b5016cbbSstephh } 2667b5016cbbSstephh 2668b5016cbbSstephh void 2669b5016cbbSstephh fme_serd_load(fmd_hdl_t *hdl) 2670b5016cbbSstephh { 2671b5016cbbSstephh int sz; 2672b5016cbbSstephh char *sbuf; 2673b5016cbbSstephh char *sepptr; 2674b5016cbbSstephh char *ptr; 2675b5016cbbSstephh struct serd_entry *newentp; 2676b5016cbbSstephh struct node *epname; 2677b5016cbbSstephh nvlist_t *fmri; 2678b5016cbbSstephh char *namestring; 2679b5016cbbSstephh 2680b5016cbbSstephh if ((sz = fmd_buf_size(hdl, NULL, WOBUF_SERDS)) == 0) 2681b5016cbbSstephh return; 2682b5016cbbSstephh sbuf = alloca(sz); 2683b5016cbbSstephh fmd_buf_read(hdl, NULL, WOBUF_SERDS, sbuf, sz); 2684b5016cbbSstephh ptr = sbuf; 2685b5016cbbSstephh while (ptr < &sbuf[sz]) { 2686b5016cbbSstephh sepptr = strchr(ptr, '@'); 2687b5016cbbSstephh *sepptr = '\0'; 2688b5016cbbSstephh namestring = ptr; 2689b5016cbbSstephh sepptr++; 2690b5016cbbSstephh ptr = sepptr; 2691b5016cbbSstephh ptr += strlen(ptr); 2692b5016cbbSstephh ptr++; /* move past the '\0' separating paths */ 2693b5016cbbSstephh epname = pathstring2epnamenp(sepptr); 2694b5016cbbSstephh fmri = node2fmri(epname); 2695b5016cbbSstephh if (platform_path_exists(fmri)) { 2696b5016cbbSstephh newentp = MALLOC(sizeof (*newentp)); 2697b5016cbbSstephh newentp->hdl = hdl; 2698b5016cbbSstephh newentp->ipath = ipath(epname); 2699b5016cbbSstephh newentp->ename = stable(namestring); 2700b5016cbbSstephh SerdEngines = lut_add(SerdEngines, (void *)newentp, 2701e5ba14ffSstephh (void *)newentp, (lut_cmp)serd_cmp); 2702b5016cbbSstephh } else 2703b5016cbbSstephh Serd_need_save = 1; 2704e5ba14ffSstephh tree_free(epname); 2705b5016cbbSstephh nvlist_free(fmri); 2706b5016cbbSstephh } 2707b5016cbbSstephh /* save it back again in case some of the paths no longer exist */ 2708b5016cbbSstephh serd_save(); 2709b5016cbbSstephh } 2710b5016cbbSstephh 2711b5016cbbSstephh /*ARGSUSED*/ 2712b5016cbbSstephh static void 2713b5016cbbSstephh serd_destructor(void *left, void *right, void *arg) 2714b5016cbbSstephh { 2715b5016cbbSstephh struct serd_entry *entp = (struct serd_entry *)left; 2716b5016cbbSstephh FREE(entp); 2717b5016cbbSstephh } 2718b5016cbbSstephh 2719b5016cbbSstephh /* 2720b5016cbbSstephh * Callback used in a walk of the SerdEngines to reset matching serd engines. 2721b5016cbbSstephh */ 2722b5016cbbSstephh /*ARGSUSED*/ 2723b5016cbbSstephh static void 2724b5016cbbSstephh serd_reset_cb(struct serd_entry *entp, void *unused, const struct ipath *ipp) 2725b5016cbbSstephh { 2726b5016cbbSstephh char *path; 2727b5016cbbSstephh 2728b5016cbbSstephh if (entp->ipath == ipp) { 2729b5016cbbSstephh path = ipath2str(entp->ename, ipp); 2730b5016cbbSstephh out(O_ALTFP, "serd_reset_cb: resetting %s", path); 2731b5016cbbSstephh fmd_serd_reset(entp->hdl, path); 2732b5016cbbSstephh FREE(path); 2733b5016cbbSstephh Serd_need_save = 1; 2734b5016cbbSstephh } 2735b5016cbbSstephh } 2736b5016cbbSstephh 2737e5ba14ffSstephh /*ARGSUSED*/ 2738e5ba14ffSstephh static void 2739e5ba14ffSstephh serd_topo_chg_cb(struct serd_entry *entp, void *unused, void *unused2) 2740e5ba14ffSstephh { 2741e5ba14ffSstephh char *path; 2742e5ba14ffSstephh nvlist_t *fmri; 2743e5ba14ffSstephh 2744e5ba14ffSstephh fmri = ipath2fmri((struct ipath *)(entp->ipath)); 2745e5ba14ffSstephh if (!platform_path_exists(fmri)) { 2746e5ba14ffSstephh path = ipath2str(entp->ename, entp->ipath); 2747e5ba14ffSstephh out(O_ALTFP, "serd_topo_chg_cb: not present %s", path); 2748e5ba14ffSstephh fmd_serd_reset(entp->hdl, path); 2749e5ba14ffSstephh FREE(path); 2750e5ba14ffSstephh Serd_need_save = 1; 2751e5ba14ffSstephh } 2752e5ba14ffSstephh nvlist_free(fmri); 2753e5ba14ffSstephh } 2754e5ba14ffSstephh 2755b5016cbbSstephh void 2756b5016cbbSstephh serd_fini(void) 2757b5016cbbSstephh { 2758b5016cbbSstephh lut_free(SerdEngines, serd_destructor, NULL); 2759b5016cbbSstephh } 2760b5016cbbSstephh 27617c478bd9Sstevel@tonic-gate static void 2762b7d3956bSstephh publish_suspects(struct fme *fmep, struct rsl *srl) 27637c478bd9Sstevel@tonic-gate { 27647c478bd9Sstevel@tonic-gate struct rsl *rp; 27657c478bd9Sstevel@tonic-gate nvlist_t *fault; 27667c478bd9Sstevel@tonic-gate uint8_t cert; 27677c478bd9Sstevel@tonic-gate uint_t *frs; 27688e7248e5SStephen Hanson uint_t frsum, fr; 27697aec1d6eScindi uint_t messval; 2770b7d3956bSstephh uint_t retireval; 2771b7d3956bSstephh uint_t responseval; 27727aec1d6eScindi struct node *snp; 27737c478bd9Sstevel@tonic-gate int frcnt, fridx; 27747aec1d6eScindi boolean_t allfaulty = B_TRUE; 2775b7d3956bSstephh struct rsl *erl = srl + fmep->nsuspects - 1; 27767c478bd9Sstevel@tonic-gate 27777c478bd9Sstevel@tonic-gate /* 2778b7d3956bSstephh * sort the array 27797c478bd9Sstevel@tonic-gate */ 2780b7d3956bSstephh qsort(srl, fmep->nsuspects, sizeof (struct rsl), rslcmp); 27817c478bd9Sstevel@tonic-gate 27828e7248e5SStephen Hanson /* sum the fitrates */ 27838e7248e5SStephen Hanson frs = alloca(fmep->nsuspects * sizeof (uint_t)); 27848e7248e5SStephen Hanson fridx = frcnt = frsum = 0; 27857c478bd9Sstevel@tonic-gate 27868e7248e5SStephen Hanson for (rp = srl; rp <= erl; rp++) { 27878e7248e5SStephen Hanson struct node *n; 27887c478bd9Sstevel@tonic-gate 27898e7248e5SStephen Hanson n = eventprop_lookup(rp->suspect, L_FITrate); 27908e7248e5SStephen Hanson if (node2uint(n, &fr) != 0) { 27918e7248e5SStephen Hanson out(O_DEBUG|O_NONL, "event "); 27928e7248e5SStephen Hanson ipath_print(O_DEBUG|O_NONL, 27938e7248e5SStephen Hanson rp->suspect->enode->u.event.ename->u.name.s, 27948e7248e5SStephen Hanson rp->suspect->ipp); 2795f6e214c7SGavin Maltby out(O_VERB, " has no FITrate (using 1)"); 27968e7248e5SStephen Hanson fr = 1; 27978e7248e5SStephen Hanson } else if (fr == 0) { 27988e7248e5SStephen Hanson out(O_DEBUG|O_NONL, "event "); 27998e7248e5SStephen Hanson ipath_print(O_DEBUG|O_NONL, 28008e7248e5SStephen Hanson rp->suspect->enode->u.event.ename->u.name.s, 28018e7248e5SStephen Hanson rp->suspect->ipp); 2802f6e214c7SGavin Maltby out(O_VERB, " has zero FITrate (using 1)"); 28038e7248e5SStephen Hanson fr = 1; 28047c478bd9Sstevel@tonic-gate } 28058e7248e5SStephen Hanson 28068e7248e5SStephen Hanson frs[fridx++] = fr; 28078e7248e5SStephen Hanson frsum += fr; 28088e7248e5SStephen Hanson frcnt++; 28097c478bd9Sstevel@tonic-gate } 28107c478bd9Sstevel@tonic-gate 28117c478bd9Sstevel@tonic-gate /* Add them in reverse order of our sort, as fmd reverses order */ 28127c478bd9Sstevel@tonic-gate for (rp = erl; rp >= srl; rp--) { 28138e7248e5SStephen Hanson cert = percentof(frs[--fridx], frsum); 28147c478bd9Sstevel@tonic-gate fault = fmd_nvl_create_fault(fmep->hdl, 28157c478bd9Sstevel@tonic-gate rp->suspect->enode->u.event.ename->u.name.s, 28167c478bd9Sstevel@tonic-gate cert, 28177c478bd9Sstevel@tonic-gate rp->asru, 28187c478bd9Sstevel@tonic-gate rp->fru, 28197c478bd9Sstevel@tonic-gate rp->rsrc); 28207c478bd9Sstevel@tonic-gate if (fault == NULL) 28217c478bd9Sstevel@tonic-gate out(O_DIE, "fault creation failed"); 28227aec1d6eScindi /* if "message" property exists, add it to the fault */ 28237aec1d6eScindi if (node2uint(eventprop_lookup(rp->suspect, L_message), 28247aec1d6eScindi &messval) == 0) { 28257aec1d6eScindi 28267aec1d6eScindi out(O_ALTFP, 28277aec1d6eScindi "[FME%d, %s adds message=%d to suspect list]", 28287aec1d6eScindi fmep->id, 28297aec1d6eScindi rp->suspect->enode->u.event.ename->u.name.s, 28307aec1d6eScindi messval); 28317aec1d6eScindi if (nvlist_add_boolean_value(fault, 28327aec1d6eScindi FM_SUSPECT_MESSAGE, 28337aec1d6eScindi (messval) ? B_TRUE : B_FALSE) != 0) { 28347aec1d6eScindi out(O_DIE, "cannot add no-message to fault"); 28357aec1d6eScindi } 28367aec1d6eScindi } 2837b7d3956bSstephh 2838b7d3956bSstephh /* if "retire" property exists, add it to the fault */ 2839b7d3956bSstephh if (node2uint(eventprop_lookup(rp->suspect, L_retire), 2840b7d3956bSstephh &retireval) == 0) { 2841b7d3956bSstephh 2842b7d3956bSstephh out(O_ALTFP, 2843b7d3956bSstephh "[FME%d, %s adds retire=%d to suspect list]", 2844b7d3956bSstephh fmep->id, 2845b7d3956bSstephh rp->suspect->enode->u.event.ename->u.name.s, 2846b7d3956bSstephh retireval); 2847b7d3956bSstephh if (nvlist_add_boolean_value(fault, 2848b7d3956bSstephh FM_SUSPECT_RETIRE, 2849b7d3956bSstephh (retireval) ? B_TRUE : B_FALSE) != 0) { 2850b7d3956bSstephh out(O_DIE, "cannot add no-retire to fault"); 2851b7d3956bSstephh } 2852b7d3956bSstephh } 2853b7d3956bSstephh 2854b7d3956bSstephh /* if "response" property exists, add it to the fault */ 2855b7d3956bSstephh if (node2uint(eventprop_lookup(rp->suspect, L_response), 2856b7d3956bSstephh &responseval) == 0) { 2857b7d3956bSstephh 2858b7d3956bSstephh out(O_ALTFP, 2859b7d3956bSstephh "[FME%d, %s adds response=%d to suspect list]", 2860b7d3956bSstephh fmep->id, 2861b7d3956bSstephh rp->suspect->enode->u.event.ename->u.name.s, 2862b7d3956bSstephh responseval); 2863b7d3956bSstephh if (nvlist_add_boolean_value(fault, 2864b7d3956bSstephh FM_SUSPECT_RESPONSE, 2865b7d3956bSstephh (responseval) ? B_TRUE : B_FALSE) != 0) { 2866b7d3956bSstephh out(O_DIE, "cannot add no-response to fault"); 2867b7d3956bSstephh } 2868b7d3956bSstephh } 2869b7d3956bSstephh 28707aec1d6eScindi /* add any payload properties */ 28717aec1d6eScindi lut_walk(rp->suspect->payloadprops, 28727aec1d6eScindi (lut_cb)addpayloadprop, (void *)fault); 28737c478bd9Sstevel@tonic-gate rslfree(rp); 28745f25dc2aSgavinm 28755f25dc2aSgavinm /* 28765f25dc2aSgavinm * If "action" property exists, evaluate it; this must be done 2877b7d3956bSstephh * before the allfaulty check below since some actions may 287825c6ff4bSstephh * modify the asru to be used in fmd_nvl_fmri_has_fault. This 28795f25dc2aSgavinm * needs to be restructured if any new actions are introduced 28805f25dc2aSgavinm * that have effects that we do not want to be visible if 28815f25dc2aSgavinm * we decide not to publish in the dupclose check below. 28825f25dc2aSgavinm */ 28837aec1d6eScindi if ((snp = eventprop_lookup(rp->suspect, L_action)) != NULL) { 28847aec1d6eScindi struct evalue evalue; 28857aec1d6eScindi 28867aec1d6eScindi out(O_ALTFP|O_NONL, 28877aec1d6eScindi "[FME%d, %s action ", fmep->id, 28887aec1d6eScindi rp->suspect->enode->u.event.ename->u.name.s); 28897aec1d6eScindi ptree_name_iter(O_ALTFP|O_NONL, snp); 28907aec1d6eScindi out(O_ALTFP, "]"); 28917aec1d6eScindi Action_nvl = fault; 28927aec1d6eScindi (void) eval_expr(snp, NULL, NULL, NULL, NULL, 28937aec1d6eScindi NULL, 0, &evalue); 28947aec1d6eScindi } 28955f25dc2aSgavinm 2896b7d3956bSstephh fmd_case_add_suspect(fmep->hdl, fmep->fmcase, fault); 2897b7d3956bSstephh 28987aec1d6eScindi /* 2899567cc2e6Sstephh * check if the asru is already marked as "faulty". 29007aec1d6eScindi */ 2901567cc2e6Sstephh if (allfaulty) { 29027aec1d6eScindi nvlist_t *asru; 29037aec1d6eScindi 2904b7d3956bSstephh out(O_ALTFP|O_VERB, "FME%d dup check ", fmep->id); 29057aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, rp->suspect); 29067aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " "); 29077aec1d6eScindi if (nvlist_lookup_nvlist(fault, 29087aec1d6eScindi FM_FAULT_ASRU, &asru) != 0) { 29097aec1d6eScindi out(O_ALTFP|O_VERB, "NULL asru"); 29107aec1d6eScindi allfaulty = B_FALSE; 291125c6ff4bSstephh } else if (fmd_nvl_fmri_has_fault(fmep->hdl, asru, 291225c6ff4bSstephh FMD_HAS_FAULT_ASRU, NULL)) { 29137aec1d6eScindi out(O_ALTFP|O_VERB, "faulty"); 29147aec1d6eScindi } else { 29157aec1d6eScindi out(O_ALTFP|O_VERB, "not faulty"); 29167aec1d6eScindi allfaulty = B_FALSE; 29177aec1d6eScindi } 29187aec1d6eScindi } 29197aec1d6eScindi 29207aec1d6eScindi } 29215f25dc2aSgavinm 2922567cc2e6Sstephh if (!allfaulty) { 2923567cc2e6Sstephh /* 2924567cc2e6Sstephh * don't update the count stat if all asrus are already 2925567cc2e6Sstephh * present and unrepaired in the asru cache 2926567cc2e6Sstephh */ 29275f25dc2aSgavinm for (rp = erl; rp >= srl; rp--) { 29285f25dc2aSgavinm struct event *suspect = rp->suspect; 29295f25dc2aSgavinm 29305f25dc2aSgavinm if (suspect == NULL) 29315f25dc2aSgavinm continue; 29325f25dc2aSgavinm 29335f25dc2aSgavinm /* if "count" exists, increment the appropriate stat */ 29345f25dc2aSgavinm if ((snp = eventprop_lookup(suspect, 29355f25dc2aSgavinm L_count)) != NULL) { 29365f25dc2aSgavinm out(O_ALTFP|O_NONL, 29375f25dc2aSgavinm "[FME%d, %s count ", fmep->id, 29385f25dc2aSgavinm suspect->enode->u.event.ename->u.name.s); 29395f25dc2aSgavinm ptree_name_iter(O_ALTFP|O_NONL, snp); 29405f25dc2aSgavinm out(O_ALTFP, "]"); 29415f25dc2aSgavinm istat_bump(snp, 0); 29425f25dc2aSgavinm 29435f25dc2aSgavinm } 29445f25dc2aSgavinm } 29455f25dc2aSgavinm istat_save(); /* write out any istat changes */ 29467c478bd9Sstevel@tonic-gate } 29477c478bd9Sstevel@tonic-gate } 29487c478bd9Sstevel@tonic-gate 294932d4e834STarik Soydan static const char * 295032d4e834STarik Soydan undiag_2defect_str(int ud) 295132d4e834STarik Soydan { 295232d4e834STarik Soydan switch (ud) { 295332d4e834STarik Soydan case UD_VAL_MISSINGINFO: 295432d4e834STarik Soydan case UD_VAL_MISSINGOBS: 295532d4e834STarik Soydan case UD_VAL_MISSINGPATH: 295632d4e834STarik Soydan case UD_VAL_MISSINGZERO: 295732d4e834STarik Soydan case UD_VAL_BADOBS: 295832d4e834STarik Soydan case UD_VAL_CFGMISMATCH: 295932d4e834STarik Soydan return (UNDIAG_DEFECT_CHKPT); 296032d4e834STarik Soydan 296132d4e834STarik Soydan case UD_VAL_BADEVENTI: 2962705e9f42SStephen Hanson case UD_VAL_BADEVENTPATH: 2963705e9f42SStephen Hanson case UD_VAL_BADEVENTCLASS: 296432d4e834STarik Soydan case UD_VAL_INSTFAIL: 296532d4e834STarik Soydan case UD_VAL_NOPATH: 296632d4e834STarik Soydan case UD_VAL_UNSOLVD: 296732d4e834STarik Soydan return (UNDIAG_DEFECT_FME); 296832d4e834STarik Soydan 296932d4e834STarik Soydan case UD_VAL_MAXFME: 297032d4e834STarik Soydan return (UNDIAG_DEFECT_LIMIT); 297132d4e834STarik Soydan 297232d4e834STarik Soydan case UD_VAL_UNKNOWN: 297332d4e834STarik Soydan default: 297432d4e834STarik Soydan return (UNDIAG_DEFECT_UNKNOWN); 297532d4e834STarik Soydan } 297632d4e834STarik Soydan } 297732d4e834STarik Soydan 2978705e9f42SStephen Hanson static const char * 2979705e9f42SStephen Hanson undiag_2fault_str(int ud) 298032d4e834STarik Soydan { 298132d4e834STarik Soydan switch (ud) { 298232d4e834STarik Soydan case UD_VAL_BADEVENTI: 2983705e9f42SStephen Hanson case UD_VAL_BADEVENTPATH: 2984705e9f42SStephen Hanson case UD_VAL_BADEVENTCLASS: 2985705e9f42SStephen Hanson case UD_VAL_INSTFAIL: 2986705e9f42SStephen Hanson case UD_VAL_NOPATH: 2987705e9f42SStephen Hanson case UD_VAL_UNSOLVD: 2988705e9f42SStephen Hanson return (UNDIAG_FAULT_FME); 2989705e9f42SStephen Hanson default: 2990705e9f42SStephen Hanson return (NULL); 2991705e9f42SStephen Hanson } 2992705e9f42SStephen Hanson } 2993705e9f42SStephen Hanson 2994705e9f42SStephen Hanson static char * 2995705e9f42SStephen Hanson undiag_2reason_str(int ud, char *arg) 2996705e9f42SStephen Hanson { 2997705e9f42SStephen Hanson const char *ptr; 2998705e9f42SStephen Hanson char *buf; 2999705e9f42SStephen Hanson int with_arg = 0; 3000705e9f42SStephen Hanson 3001705e9f42SStephen Hanson switch (ud) { 3002705e9f42SStephen Hanson case UD_VAL_BADEVENTPATH: 3003705e9f42SStephen Hanson ptr = UD_STR_BADEVENTPATH; 3004705e9f42SStephen Hanson with_arg = 1; 3005705e9f42SStephen Hanson break; 3006705e9f42SStephen Hanson case UD_VAL_BADEVENTCLASS: 3007705e9f42SStephen Hanson ptr = UD_STR_BADEVENTCLASS; 3008705e9f42SStephen Hanson with_arg = 1; 3009705e9f42SStephen Hanson break; 3010705e9f42SStephen Hanson case UD_VAL_BADEVENTI: 3011705e9f42SStephen Hanson ptr = UD_STR_BADEVENTI; 3012705e9f42SStephen Hanson with_arg = 1; 3013705e9f42SStephen Hanson break; 301432d4e834STarik Soydan case UD_VAL_BADOBS: 3015705e9f42SStephen Hanson ptr = UD_STR_BADOBS; 3016705e9f42SStephen Hanson break; 301732d4e834STarik Soydan case UD_VAL_CFGMISMATCH: 3018705e9f42SStephen Hanson ptr = UD_STR_CFGMISMATCH; 3019705e9f42SStephen Hanson break; 302032d4e834STarik Soydan case UD_VAL_INSTFAIL: 3021705e9f42SStephen Hanson ptr = UD_STR_INSTFAIL; 3022705e9f42SStephen Hanson with_arg = 1; 3023705e9f42SStephen Hanson break; 302432d4e834STarik Soydan case UD_VAL_MAXFME: 3025705e9f42SStephen Hanson ptr = UD_STR_MAXFME; 3026705e9f42SStephen Hanson break; 302732d4e834STarik Soydan case UD_VAL_MISSINGINFO: 3028705e9f42SStephen Hanson ptr = UD_STR_MISSINGINFO; 3029705e9f42SStephen Hanson break; 303032d4e834STarik Soydan case UD_VAL_MISSINGOBS: 3031705e9f42SStephen Hanson ptr = UD_STR_MISSINGOBS; 3032705e9f42SStephen Hanson break; 303332d4e834STarik Soydan case UD_VAL_MISSINGPATH: 3034705e9f42SStephen Hanson ptr = UD_STR_MISSINGPATH; 3035705e9f42SStephen Hanson break; 303632d4e834STarik Soydan case UD_VAL_MISSINGZERO: 3037705e9f42SStephen Hanson ptr = UD_STR_MISSINGZERO; 3038705e9f42SStephen Hanson break; 303932d4e834STarik Soydan case UD_VAL_NOPATH: 3040705e9f42SStephen Hanson ptr = UD_STR_NOPATH; 3041705e9f42SStephen Hanson with_arg = 1; 3042705e9f42SStephen Hanson break; 304332d4e834STarik Soydan case UD_VAL_UNSOLVD: 3044705e9f42SStephen Hanson ptr = UD_STR_UNSOLVD; 3045705e9f42SStephen Hanson break; 304632d4e834STarik Soydan case UD_VAL_UNKNOWN: 304732d4e834STarik Soydan default: 3048705e9f42SStephen Hanson ptr = UD_STR_UNKNOWN; 3049705e9f42SStephen Hanson break; 305032d4e834STarik Soydan } 3051705e9f42SStephen Hanson if (with_arg) { 3052705e9f42SStephen Hanson buf = MALLOC(strlen(ptr) + strlen(arg) - 1); 3053705e9f42SStephen Hanson (void) sprintf(buf, ptr, arg); 3054705e9f42SStephen Hanson } else { 3055705e9f42SStephen Hanson buf = MALLOC(strlen(ptr) + 1); 3056705e9f42SStephen Hanson (void) sprintf(buf, ptr); 3057705e9f42SStephen Hanson } 3058705e9f42SStephen Hanson return (buf); 305932d4e834STarik Soydan } 306032d4e834STarik Soydan 30617c478bd9Sstevel@tonic-gate static void 3062705e9f42SStephen Hanson publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep, fmd_case_t *fmcase, 3063705e9f42SStephen Hanson nvlist_t *detector, char *arg) 30647c478bd9Sstevel@tonic-gate { 30657c478bd9Sstevel@tonic-gate struct case_list *newcase; 3066705e9f42SStephen Hanson nvlist_t *defect, *fault; 3067705e9f42SStephen Hanson const char *faultstr; 3068705e9f42SStephen Hanson char *reason = undiag_2reason_str(Undiag_reason, arg); 30697c478bd9Sstevel@tonic-gate 30707c478bd9Sstevel@tonic-gate out(O_ALTFP, 30717c478bd9Sstevel@tonic-gate "[undiagnosable ereport received, " 3072705e9f42SStephen Hanson "creating and closing a new case (%s)]", reason); 30737c478bd9Sstevel@tonic-gate 30747c478bd9Sstevel@tonic-gate newcase = MALLOC(sizeof (struct case_list)); 30757c478bd9Sstevel@tonic-gate newcase->next = NULL; 3076b5016cbbSstephh newcase->fmcase = fmcase; 30777c478bd9Sstevel@tonic-gate if (Undiagablecaselist != NULL) 30787c478bd9Sstevel@tonic-gate newcase->next = Undiagablecaselist; 30797c478bd9Sstevel@tonic-gate Undiagablecaselist = newcase; 30807c478bd9Sstevel@tonic-gate 30817c478bd9Sstevel@tonic-gate if (ffep != NULL) 30827c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, newcase->fmcase, ffep); 30837c478bd9Sstevel@tonic-gate 3084705e9f42SStephen Hanson /* add defect */ 308532d4e834STarik Soydan defect = fmd_nvl_create_fault(hdl, 3086705e9f42SStephen Hanson undiag_2defect_str(Undiag_reason), 50, NULL, NULL, detector); 3087705e9f42SStephen Hanson (void) nvlist_add_string(defect, UNDIAG_REASON, reason); 3088705e9f42SStephen Hanson (void) nvlist_add_boolean_value(defect, FM_SUSPECT_RETIRE, B_FALSE); 3089705e9f42SStephen Hanson (void) nvlist_add_boolean_value(defect, FM_SUSPECT_RESPONSE, B_FALSE); 30907c478bd9Sstevel@tonic-gate fmd_case_add_suspect(hdl, newcase->fmcase, defect); 30917c478bd9Sstevel@tonic-gate 3092705e9f42SStephen Hanson /* add fault if appropriate */ 3093705e9f42SStephen Hanson faultstr = undiag_2fault_str(Undiag_reason); 3094705e9f42SStephen Hanson if (faultstr != NULL) { 3095705e9f42SStephen Hanson fault = fmd_nvl_create_fault(hdl, faultstr, 50, NULL, NULL, 3096705e9f42SStephen Hanson detector); 3097705e9f42SStephen Hanson (void) nvlist_add_string(fault, UNDIAG_REASON, reason); 3098705e9f42SStephen Hanson (void) nvlist_add_boolean_value(fault, FM_SUSPECT_RETIRE, 3099705e9f42SStephen Hanson B_FALSE); 3100705e9f42SStephen Hanson (void) nvlist_add_boolean_value(fault, FM_SUSPECT_RESPONSE, 3101705e9f42SStephen Hanson B_FALSE); 3102705e9f42SStephen Hanson fmd_case_add_suspect(hdl, newcase->fmcase, fault); 3103705e9f42SStephen Hanson } 3104705e9f42SStephen Hanson FREE(reason); 3105705e9f42SStephen Hanson 3106705e9f42SStephen Hanson /* solve and close case */ 31077c478bd9Sstevel@tonic-gate fmd_case_solve(hdl, newcase->fmcase); 31087c478bd9Sstevel@tonic-gate fmd_case_close(hdl, newcase->fmcase); 310932d4e834STarik Soydan Undiag_reason = UD_VAL_UNKNOWN; 31107c478bd9Sstevel@tonic-gate } 31117c478bd9Sstevel@tonic-gate 31127c478bd9Sstevel@tonic-gate static void 31137c478bd9Sstevel@tonic-gate fme_undiagnosable(struct fme *f) 31147c478bd9Sstevel@tonic-gate { 3115705e9f42SStephen Hanson nvlist_t *defect, *fault, *detector = NULL; 3116705e9f42SStephen Hanson struct event *ep; 3117705e9f42SStephen Hanson char *pathstr; 3118705e9f42SStephen Hanson const char *faultstr; 3119705e9f42SStephen Hanson char *reason = undiag_2reason_str(Undiag_reason, NULL); 31207c478bd9Sstevel@tonic-gate 31217c478bd9Sstevel@tonic-gate out(O_ALTFP, "[solving/closing FME%d, case %s (%s)]", 3122705e9f42SStephen Hanson f->id, fmd_case_uuid(f->hdl, f->fmcase), reason); 3123705e9f42SStephen Hanson 3124705e9f42SStephen Hanson for (ep = f->observations; ep; ep = ep->observations) { 3125705e9f42SStephen Hanson 3126705e9f42SStephen Hanson if (ep->ffep != f->e0r) 3127705e9f42SStephen Hanson fmd_case_add_ereport(f->hdl, f->fmcase, ep->ffep); 3128705e9f42SStephen Hanson 3129705e9f42SStephen Hanson pathstr = ipath2str(NULL, ipath(platform_getpath(ep->nvp))); 3130*da40b264SAlex Wilson platform_unit_translate(0, f->config, TOPO_PROP_RESOURCE, 3131*da40b264SAlex Wilson &detector, pathstr); 3132705e9f42SStephen Hanson FREE(pathstr); 3133705e9f42SStephen Hanson 3134705e9f42SStephen Hanson /* add defect */ 3135705e9f42SStephen Hanson defect = fmd_nvl_create_fault(f->hdl, 3136705e9f42SStephen Hanson undiag_2defect_str(Undiag_reason), 50 / f->uniqobs, 3137705e9f42SStephen Hanson NULL, NULL, detector); 3138705e9f42SStephen Hanson (void) nvlist_add_string(defect, UNDIAG_REASON, reason); 3139705e9f42SStephen Hanson (void) nvlist_add_boolean_value(defect, FM_SUSPECT_RETIRE, 3140705e9f42SStephen Hanson B_FALSE); 3141705e9f42SStephen Hanson (void) nvlist_add_boolean_value(defect, FM_SUSPECT_RESPONSE, 3142705e9f42SStephen Hanson B_FALSE); 3143705e9f42SStephen Hanson fmd_case_add_suspect(f->hdl, f->fmcase, defect); 3144705e9f42SStephen Hanson 3145705e9f42SStephen Hanson /* add fault if appropriate */ 3146705e9f42SStephen Hanson faultstr = undiag_2fault_str(Undiag_reason); 3147705e9f42SStephen Hanson if (faultstr == NULL) 3148705e9f42SStephen Hanson continue; 3149705e9f42SStephen Hanson fault = fmd_nvl_create_fault(f->hdl, faultstr, 50 / f->uniqobs, 3150705e9f42SStephen Hanson NULL, NULL, detector); 3151705e9f42SStephen Hanson (void) nvlist_add_string(fault, UNDIAG_REASON, reason); 3152705e9f42SStephen Hanson (void) nvlist_add_boolean_value(fault, FM_SUSPECT_RETIRE, 3153705e9f42SStephen Hanson B_FALSE); 3154705e9f42SStephen Hanson (void) nvlist_add_boolean_value(fault, FM_SUSPECT_RESPONSE, 3155705e9f42SStephen Hanson B_FALSE); 3156705e9f42SStephen Hanson fmd_case_add_suspect(f->hdl, f->fmcase, fault); 3157705e9f42SStephen Hanson nvlist_free(detector); 3158705e9f42SStephen Hanson } 3159705e9f42SStephen Hanson FREE(reason); 31607c478bd9Sstevel@tonic-gate fmd_case_solve(f->hdl, f->fmcase); 31617c478bd9Sstevel@tonic-gate fmd_case_close(f->hdl, f->fmcase); 316232d4e834STarik Soydan Undiag_reason = UD_VAL_UNKNOWN; 31637c478bd9Sstevel@tonic-gate } 31647c478bd9Sstevel@tonic-gate 31657c478bd9Sstevel@tonic-gate /* 31667c478bd9Sstevel@tonic-gate * fme_close_case 31677c478bd9Sstevel@tonic-gate * 31687c478bd9Sstevel@tonic-gate * Find the requested case amongst our fmes and close it. Free up 31697c478bd9Sstevel@tonic-gate * the related fme. 31707c478bd9Sstevel@tonic-gate */ 31717c478bd9Sstevel@tonic-gate void 31727c478bd9Sstevel@tonic-gate fme_close_case(fmd_hdl_t *hdl, fmd_case_t *fmcase) 31737c478bd9Sstevel@tonic-gate { 31747c478bd9Sstevel@tonic-gate struct case_list *ucasep, *prevcasep = NULL; 31757c478bd9Sstevel@tonic-gate struct fme *prev = NULL; 31767c478bd9Sstevel@tonic-gate struct fme *fmep; 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate for (ucasep = Undiagablecaselist; ucasep; ucasep = ucasep->next) { 31797c478bd9Sstevel@tonic-gate if (fmcase != ucasep->fmcase) { 31807c478bd9Sstevel@tonic-gate prevcasep = ucasep; 31817c478bd9Sstevel@tonic-gate continue; 31827c478bd9Sstevel@tonic-gate } 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate if (prevcasep == NULL) 31857c478bd9Sstevel@tonic-gate Undiagablecaselist = Undiagablecaselist->next; 31867c478bd9Sstevel@tonic-gate else 31877c478bd9Sstevel@tonic-gate prevcasep->next = ucasep->next; 31887c478bd9Sstevel@tonic-gate 31897c478bd9Sstevel@tonic-gate FREE(ucasep); 31907c478bd9Sstevel@tonic-gate return; 31917c478bd9Sstevel@tonic-gate } 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) { 31947c478bd9Sstevel@tonic-gate if (fmep->hdl == hdl && fmep->fmcase == fmcase) 31957c478bd9Sstevel@tonic-gate break; 31967c478bd9Sstevel@tonic-gate prev = fmep; 31977c478bd9Sstevel@tonic-gate } 31987c478bd9Sstevel@tonic-gate 31997c478bd9Sstevel@tonic-gate if (fmep == NULL) { 32007c478bd9Sstevel@tonic-gate out(O_WARN, "Eft asked to close unrecognized case [%s].", 32017c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, fmcase)); 32027c478bd9Sstevel@tonic-gate return; 32037c478bd9Sstevel@tonic-gate } 32047c478bd9Sstevel@tonic-gate 32057c478bd9Sstevel@tonic-gate if (EFMElist == fmep) 32067c478bd9Sstevel@tonic-gate EFMElist = prev; 32077c478bd9Sstevel@tonic-gate 32087c478bd9Sstevel@tonic-gate if (prev == NULL) 32097c478bd9Sstevel@tonic-gate FMElist = FMElist->next; 32107c478bd9Sstevel@tonic-gate else 32117c478bd9Sstevel@tonic-gate prev->next = fmep->next; 32127c478bd9Sstevel@tonic-gate 32137c478bd9Sstevel@tonic-gate fmep->next = NULL; 32147c478bd9Sstevel@tonic-gate 32157c478bd9Sstevel@tonic-gate /* Get rid of any timer this fme has set */ 32167c478bd9Sstevel@tonic-gate if (fmep->wull != 0) 32177c478bd9Sstevel@tonic-gate fmd_timer_remove(fmep->hdl, fmep->timer); 32187c478bd9Sstevel@tonic-gate 32197c478bd9Sstevel@tonic-gate if (ClosedFMEs == NULL) { 32207c478bd9Sstevel@tonic-gate ClosedFMEs = fmep; 32217c478bd9Sstevel@tonic-gate } else { 32227c478bd9Sstevel@tonic-gate fmep->next = ClosedFMEs; 32237c478bd9Sstevel@tonic-gate ClosedFMEs = fmep; 32247c478bd9Sstevel@tonic-gate } 32250cc1f05eSjrutt 32260cc1f05eSjrutt Open_fme_count--; 32270cc1f05eSjrutt 32280cc1f05eSjrutt /* See if we can close the overflow FME */ 32290cc1f05eSjrutt if (Open_fme_count <= Max_fme) { 32300cc1f05eSjrutt for (fmep = FMElist; fmep; fmep = fmep->next) { 32310cc1f05eSjrutt if (fmep->overflow && !(fmd_case_closed(fmep->hdl, 32320cc1f05eSjrutt fmep->fmcase))) 32330cc1f05eSjrutt break; 32340cc1f05eSjrutt } 32350cc1f05eSjrutt 32360cc1f05eSjrutt if (fmep != NULL) 32370cc1f05eSjrutt fmd_case_close(fmep->hdl, fmep->fmcase); 32380cc1f05eSjrutt } 32397c478bd9Sstevel@tonic-gate } 32407c478bd9Sstevel@tonic-gate 32417c478bd9Sstevel@tonic-gate /* 32427c478bd9Sstevel@tonic-gate * fme_set_timer() 32437c478bd9Sstevel@tonic-gate * If the time we need to wait for the given FME is less than the 32447c478bd9Sstevel@tonic-gate * current timer, kick that old timer out and establish a new one. 32457c478bd9Sstevel@tonic-gate */ 32467aec1d6eScindi static int 32477c478bd9Sstevel@tonic-gate fme_set_timer(struct fme *fmep, unsigned long long wull) 32487c478bd9Sstevel@tonic-gate { 32497c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " fme_set_timer: request to wait "); 32507c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &wull); 32517c478bd9Sstevel@tonic-gate 32527c478bd9Sstevel@tonic-gate if (wull <= fmep->pull) { 32537c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "already have waited at least "); 32547c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &fmep->pull); 32557c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 32567c478bd9Sstevel@tonic-gate /* we've waited at least wull already, don't need timer */ 32577aec1d6eScindi return (0); 32587c478bd9Sstevel@tonic-gate } 32597c478bd9Sstevel@tonic-gate 32607c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " currently "); 32617c478bd9Sstevel@tonic-gate if (fmep->wull != 0) { 32627c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "waiting "); 32637c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &fmep->wull); 32647c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 32657c478bd9Sstevel@tonic-gate } else { 32667c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "not waiting"); 32677c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 32687c478bd9Sstevel@tonic-gate } 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate if (fmep->wull != 0) 32717c478bd9Sstevel@tonic-gate if (wull >= fmep->wull) 32727c478bd9Sstevel@tonic-gate /* New timer would fire later than established timer */ 32737aec1d6eScindi return (0); 32747c478bd9Sstevel@tonic-gate 32757aec1d6eScindi if (fmep->wull != 0) { 32767c478bd9Sstevel@tonic-gate fmd_timer_remove(fmep->hdl, fmep->timer); 32777aec1d6eScindi } 32787c478bd9Sstevel@tonic-gate 32797c478bd9Sstevel@tonic-gate fmep->timer = fmd_timer_install(fmep->hdl, (void *)fmep, 32807c478bd9Sstevel@tonic-gate fmep->e0r, wull); 32817c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, "timer set, id is %ld", fmep->timer); 32827c478bd9Sstevel@tonic-gate fmep->wull = wull; 32837aec1d6eScindi return (1); 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate void 32877c478bd9Sstevel@tonic-gate fme_timer_fired(struct fme *fmep, id_t tid) 32887c478bd9Sstevel@tonic-gate { 32897c478bd9Sstevel@tonic-gate struct fme *ffmep = NULL; 32907c478bd9Sstevel@tonic-gate 32917c478bd9Sstevel@tonic-gate for (ffmep = FMElist; ffmep; ffmep = ffmep->next) 32927c478bd9Sstevel@tonic-gate if (ffmep == fmep) 32937c478bd9Sstevel@tonic-gate break; 32947c478bd9Sstevel@tonic-gate 32957c478bd9Sstevel@tonic-gate if (ffmep == NULL) { 32967c478bd9Sstevel@tonic-gate out(O_WARN, "Timer fired for an FME (%p) not in FMEs list.", 32977c478bd9Sstevel@tonic-gate (void *)fmep); 32987c478bd9Sstevel@tonic-gate return; 32997c478bd9Sstevel@tonic-gate } 33007c478bd9Sstevel@tonic-gate 3301b5016cbbSstephh out(O_ALTFP|O_VERB, "Timer fired %lx", tid); 3302d96ce684Sstephh fmep->pull = fmep->wull; 3303d96ce684Sstephh fmep->wull = 0; 3304d96ce684Sstephh fmd_buf_write(fmep->hdl, fmep->fmcase, 3305d96ce684Sstephh WOBUF_PULL, (void *)&fmep->pull, sizeof (fmep->pull)); 3306b5016cbbSstephh 330700d0963fSdilpreet fme_eval(fmep, fmep->e0r); 33087c478bd9Sstevel@tonic-gate } 33097c478bd9Sstevel@tonic-gate 33107c478bd9Sstevel@tonic-gate /* 33117c478bd9Sstevel@tonic-gate * Preserve the fme's suspect list in its psuspects list, NULLing the 33127c478bd9Sstevel@tonic-gate * suspects list in the meantime. 33137c478bd9Sstevel@tonic-gate */ 33147c478bd9Sstevel@tonic-gate static void 33157c478bd9Sstevel@tonic-gate save_suspects(struct fme *fmep) 33167c478bd9Sstevel@tonic-gate { 33177c478bd9Sstevel@tonic-gate struct event *ep; 33187c478bd9Sstevel@tonic-gate struct event *nextep; 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate /* zero out the previous suspect list */ 33217c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = nextep) { 33227c478bd9Sstevel@tonic-gate nextep = ep->psuspects; 33237c478bd9Sstevel@tonic-gate ep->psuspects = NULL; 33247c478bd9Sstevel@tonic-gate } 33257c478bd9Sstevel@tonic-gate fmep->psuspects = NULL; 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gate /* zero out the suspect list, copying it to previous suspect list */ 33287c478bd9Sstevel@tonic-gate fmep->psuspects = fmep->suspects; 33297c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = nextep) { 33307c478bd9Sstevel@tonic-gate nextep = ep->suspects; 33317c478bd9Sstevel@tonic-gate ep->psuspects = ep->suspects; 33327c478bd9Sstevel@tonic-gate ep->suspects = NULL; 33337c478bd9Sstevel@tonic-gate ep->is_suspect = 0; 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate fmep->suspects = NULL; 33367c478bd9Sstevel@tonic-gate fmep->nsuspects = 0; 33377c478bd9Sstevel@tonic-gate } 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate /* 33407c478bd9Sstevel@tonic-gate * Retrieve the fme's suspect list from its psuspects list. 33417c478bd9Sstevel@tonic-gate */ 33427c478bd9Sstevel@tonic-gate static void 33437c478bd9Sstevel@tonic-gate restore_suspects(struct fme *fmep) 33447c478bd9Sstevel@tonic-gate { 33457c478bd9Sstevel@tonic-gate struct event *ep; 33467c478bd9Sstevel@tonic-gate struct event *nextep; 33477c478bd9Sstevel@tonic-gate 33488e7248e5SStephen Hanson fmep->nsuspects = 0; 33497c478bd9Sstevel@tonic-gate fmep->suspects = fmep->psuspects; 33507c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = nextep) { 33517c478bd9Sstevel@tonic-gate fmep->nsuspects++; 33527c478bd9Sstevel@tonic-gate nextep = ep->psuspects; 33537c478bd9Sstevel@tonic-gate ep->suspects = ep->psuspects; 33547c478bd9Sstevel@tonic-gate } 33557c478bd9Sstevel@tonic-gate } 33567c478bd9Sstevel@tonic-gate 33577c478bd9Sstevel@tonic-gate /* 33587c478bd9Sstevel@tonic-gate * this is what we use to call the Emrys prototype code instead of main() 33597c478bd9Sstevel@tonic-gate */ 33607c478bd9Sstevel@tonic-gate static void 33617c478bd9Sstevel@tonic-gate fme_eval(struct fme *fmep, fmd_event_t *ffep) 33627c478bd9Sstevel@tonic-gate { 33637c478bd9Sstevel@tonic-gate struct event *ep; 33647c478bd9Sstevel@tonic-gate unsigned long long my_delay = TIMEVAL_EVENTUALLY; 3365b7d3956bSstephh struct rsl *srl = NULL; 3366b7d3956bSstephh struct rsl *srl2 = NULL; 3367b7d3956bSstephh int mess_zero_count; 3368b7d3956bSstephh int rpcnt; 33697c478bd9Sstevel@tonic-gate 33707c478bd9Sstevel@tonic-gate save_suspects(fmep); 33717c478bd9Sstevel@tonic-gate 3372b5016cbbSstephh out(O_ALTFP, "Evaluate FME %d", fmep->id); 33737c478bd9Sstevel@tonic-gate indent_set(" "); 33747c478bd9Sstevel@tonic-gate 33757aec1d6eScindi lut_walk(fmep->eventtree, (lut_cb)clear_arrows, (void *)fmep); 33767aec1d6eScindi fmep->state = hypothesise(fmep, fmep->e0, fmep->ull, &my_delay); 33777c478bd9Sstevel@tonic-gate 3378b5016cbbSstephh out(O_ALTFP|O_NONL, "FME%d state: %s, suspect list:", fmep->id, 33797c478bd9Sstevel@tonic-gate fme_state2str(fmep->state)); 33807c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 3381b5016cbbSstephh out(O_ALTFP|O_NONL, " "); 3382b5016cbbSstephh itree_pevent_brief(O_ALTFP|O_NONL, ep); 33837c478bd9Sstevel@tonic-gate } 3384b5016cbbSstephh out(O_ALTFP, NULL); 33857c478bd9Sstevel@tonic-gate 3386d96ce684Sstephh switch (fmep->state) { 3387d96ce684Sstephh case FME_CREDIBLE: 3388d96ce684Sstephh print_suspects(SLNEW, fmep); 3389d96ce684Sstephh (void) upsets_eval(fmep, ffep); 3390d96ce684Sstephh 33917c478bd9Sstevel@tonic-gate /* 3392d96ce684Sstephh * we may have already posted suspects in upsets_eval() which 3393d96ce684Sstephh * can recurse into fme_eval() again. If so then just return. 33947c478bd9Sstevel@tonic-gate */ 3395d96ce684Sstephh if (fmep->posted_suspects) 3396d96ce684Sstephh return; 33977c478bd9Sstevel@tonic-gate 3398b7d3956bSstephh stats_counter_bump(fmep->diags); 3399b7d3956bSstephh rpcnt = fmep->nsuspects; 3400b7d3956bSstephh save_suspects(fmep); 3401b7d3956bSstephh 3402b7d3956bSstephh /* 3403b7d3956bSstephh * create two lists, one for "message=1" faults and one for 3404b7d3956bSstephh * "message=0" faults. If we have a mixture we will generate 3405b7d3956bSstephh * two separate suspect lists. 3406b7d3956bSstephh */ 3407b7d3956bSstephh srl = MALLOC(rpcnt * sizeof (struct rsl)); 3408b7d3956bSstephh bzero(srl, rpcnt * sizeof (struct rsl)); 3409b7d3956bSstephh srl2 = MALLOC(rpcnt * sizeof (struct rsl)); 3410b7d3956bSstephh bzero(srl2, rpcnt * sizeof (struct rsl)); 34118e7248e5SStephen Hanson mess_zero_count = trim_suspects(fmep, srl, srl2, ffep); 3412b7d3956bSstephh 3413b7d3956bSstephh /* 3414b7d3956bSstephh * If the resulting suspect list has no members, we're 3415b7d3956bSstephh * done so simply close the case. Otherwise sort and publish. 3416b7d3956bSstephh */ 3417b7d3956bSstephh if (fmep->nsuspects == 0 && mess_zero_count == 0) { 3418b7d3956bSstephh out(O_ALTFP, 3419b7d3956bSstephh "[FME%d, case %s (all suspects are upsets)]", 3420b7d3956bSstephh fmep->id, fmd_case_uuid(fmep->hdl, fmep->fmcase)); 3421b7d3956bSstephh fmd_case_close(fmep->hdl, fmep->fmcase); 3422b7d3956bSstephh } else if (fmep->nsuspects != 0 && mess_zero_count == 0) { 3423b7d3956bSstephh publish_suspects(fmep, srl); 3424b7d3956bSstephh out(O_ALTFP, "[solving FME%d, case %s]", fmep->id, 3425b7d3956bSstephh fmd_case_uuid(fmep->hdl, fmep->fmcase)); 3426b7d3956bSstephh fmd_case_solve(fmep->hdl, fmep->fmcase); 3427b7d3956bSstephh } else if (fmep->nsuspects == 0 && mess_zero_count != 0) { 3428b7d3956bSstephh fmep->nsuspects = mess_zero_count; 3429b7d3956bSstephh publish_suspects(fmep, srl2); 3430b7d3956bSstephh out(O_ALTFP, "[solving FME%d, case %s]", fmep->id, 3431b7d3956bSstephh fmd_case_uuid(fmep->hdl, fmep->fmcase)); 3432b7d3956bSstephh fmd_case_solve(fmep->hdl, fmep->fmcase); 3433b7d3956bSstephh } else { 3434b7d3956bSstephh struct event *obsp; 3435b7d3956bSstephh struct fme *nfmep; 3436b7d3956bSstephh 3437b7d3956bSstephh publish_suspects(fmep, srl); 3438b7d3956bSstephh out(O_ALTFP, "[solving FME%d, case %s]", fmep->id, 3439b7d3956bSstephh fmd_case_uuid(fmep->hdl, fmep->fmcase)); 3440b7d3956bSstephh fmd_case_solve(fmep->hdl, fmep->fmcase); 3441b7d3956bSstephh 3442b7d3956bSstephh /* 3443b7d3956bSstephh * Got both message=0 and message=1 so create a 3444b7d3956bSstephh * duplicate case. Also need a temporary duplicate fme 3445b7d3956bSstephh * structure for use by publish_suspects(). 3446b7d3956bSstephh */ 3447b7d3956bSstephh nfmep = alloc_fme(); 3448b7d3956bSstephh nfmep->id = Nextid++; 3449b7d3956bSstephh nfmep->hdl = fmep->hdl; 3450b7d3956bSstephh nfmep->nsuspects = mess_zero_count; 3451b7d3956bSstephh nfmep->fmcase = fmd_case_open(fmep->hdl, NULL); 3452b7d3956bSstephh out(O_ALTFP|O_STAMP, 3453b7d3956bSstephh "[creating parallel FME%d, case %s]", nfmep->id, 3454b7d3956bSstephh fmd_case_uuid(nfmep->hdl, nfmep->fmcase)); 3455b7d3956bSstephh Open_fme_count++; 3456b7d3956bSstephh if (ffep) { 3457b7d3956bSstephh fmd_case_setprincipal(nfmep->hdl, 3458b7d3956bSstephh nfmep->fmcase, ffep); 3459b7d3956bSstephh fmd_case_add_ereport(nfmep->hdl, 3460b7d3956bSstephh nfmep->fmcase, ffep); 3461b7d3956bSstephh } 3462b7d3956bSstephh for (obsp = fmep->observations; obsp; 3463b7d3956bSstephh obsp = obsp->observations) 3464b7d3956bSstephh if (obsp->ffep && obsp->ffep != ffep) 3465b7d3956bSstephh fmd_case_add_ereport(nfmep->hdl, 3466b7d3956bSstephh nfmep->fmcase, obsp->ffep); 3467b7d3956bSstephh 3468b7d3956bSstephh publish_suspects(nfmep, srl2); 3469b7d3956bSstephh out(O_ALTFP, "[solving FME%d, case %s]", nfmep->id, 3470b7d3956bSstephh fmd_case_uuid(nfmep->hdl, nfmep->fmcase)); 3471b7d3956bSstephh fmd_case_solve(nfmep->hdl, nfmep->fmcase); 3472b7d3956bSstephh FREE(nfmep); 3473b7d3956bSstephh } 3474b7d3956bSstephh FREE(srl); 3475b7d3956bSstephh FREE(srl2); 3476b7d3956bSstephh restore_suspects(fmep); 3477b7d3956bSstephh 3478d96ce684Sstephh fmep->posted_suspects = 1; 3479d96ce684Sstephh fmd_buf_write(fmep->hdl, fmep->fmcase, 3480d96ce684Sstephh WOBUF_POSTD, 3481d96ce684Sstephh (void *)&fmep->posted_suspects, 3482d96ce684Sstephh sizeof (fmep->posted_suspects)); 34837c478bd9Sstevel@tonic-gate 3484d96ce684Sstephh /* 3485d96ce684Sstephh * Now the suspects have been posted, we can clear up 3486d96ce684Sstephh * the instance tree as we won't be looking at it again. 3487d96ce684Sstephh * Also cancel the timer as the case is now solved. 3488d96ce684Sstephh */ 3489d96ce684Sstephh if (fmep->wull != 0) { 3490d96ce684Sstephh fmd_timer_remove(fmep->hdl, fmep->timer); 3491d96ce684Sstephh fmep->wull = 0; 34927c478bd9Sstevel@tonic-gate } 3493d96ce684Sstephh break; 3494d96ce684Sstephh 3495d96ce684Sstephh case FME_WAIT: 3496d96ce684Sstephh ASSERT(my_delay > fmep->ull); 3497d96ce684Sstephh (void) fme_set_timer(fmep, my_delay); 3498d96ce684Sstephh print_suspects(SLWAIT, fmep); 3499b5016cbbSstephh itree_prune(fmep->eventtree); 3500b5016cbbSstephh return; 3501d96ce684Sstephh 3502d96ce684Sstephh case FME_DISPROVED: 3503d96ce684Sstephh print_suspects(SLDISPROVED, fmep); 350432d4e834STarik Soydan Undiag_reason = UD_VAL_UNSOLVD; 3505d96ce684Sstephh fme_undiagnosable(fmep); 3506d96ce684Sstephh break; 35077c478bd9Sstevel@tonic-gate } 35087c478bd9Sstevel@tonic-gate 3509b5016cbbSstephh itree_free(fmep->eventtree); 3510b5016cbbSstephh fmep->eventtree = NULL; 3511e5ba14ffSstephh structconfig_free(fmep->config); 3512e5ba14ffSstephh fmep->config = NULL; 3513b5016cbbSstephh destroy_fme_bufs(fmep); 35147c478bd9Sstevel@tonic-gate } 35157c478bd9Sstevel@tonic-gate 35167c478bd9Sstevel@tonic-gate static void indent(void); 35177c478bd9Sstevel@tonic-gate static int triggered(struct fme *fmep, struct event *ep, int mark); 35187c478bd9Sstevel@tonic-gate static enum fme_state effects_test(struct fme *fmep, 35197aec1d6eScindi struct event *fault_event, unsigned long long at_latest_by, 35207aec1d6eScindi unsigned long long *pdelay); 35217c478bd9Sstevel@tonic-gate static enum fme_state requirements_test(struct fme *fmep, struct event *ep, 35227aec1d6eScindi unsigned long long at_latest_by, unsigned long long *pdelay); 35237c478bd9Sstevel@tonic-gate static enum fme_state causes_test(struct fme *fmep, struct event *ep, 35247c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay); 35257c478bd9Sstevel@tonic-gate 35267aec1d6eScindi static int 35277aec1d6eScindi checkconstraints(struct fme *fmep, struct arrow *arrowp) 35287aec1d6eScindi { 35297aec1d6eScindi struct constraintlist *ctp; 35307aec1d6eScindi struct evalue value; 3531b5016cbbSstephh char *sep = ""; 35327aec1d6eScindi 35337aec1d6eScindi if (arrowp->forever_false) { 35347aec1d6eScindi indent(); 35357aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " Forever false constraint: "); 35367aec1d6eScindi for (ctp = arrowp->constraints; ctp != NULL; ctp = ctp->next) { 35377aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, sep); 35387aec1d6eScindi ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 35397aec1d6eScindi sep = ", "; 35407aec1d6eScindi } 35417aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 35427aec1d6eScindi return (0); 35437aec1d6eScindi } 3544b5016cbbSstephh if (arrowp->forever_true) { 3545b5016cbbSstephh indent(); 3546b5016cbbSstephh out(O_ALTFP|O_VERB|O_NONL, " Forever true constraint: "); 3547b5016cbbSstephh for (ctp = arrowp->constraints; ctp != NULL; ctp = ctp->next) { 3548b5016cbbSstephh out(O_ALTFP|O_VERB|O_NONL, sep); 3549b5016cbbSstephh ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 3550b5016cbbSstephh sep = ", "; 3551b5016cbbSstephh } 3552b5016cbbSstephh out(O_ALTFP|O_VERB, NULL); 3553b5016cbbSstephh return (1); 3554b5016cbbSstephh } 35557aec1d6eScindi 35567aec1d6eScindi for (ctp = arrowp->constraints; ctp != NULL; ctp = ctp->next) { 35577aec1d6eScindi if (eval_expr(ctp->cnode, NULL, NULL, 3558e5ba14ffSstephh &fmep->globals, fmep->config, 35597aec1d6eScindi arrowp, 0, &value)) { 35607aec1d6eScindi /* evaluation successful */ 35617aec1d6eScindi if (value.t == UNDEFINED || value.v == 0) { 35627aec1d6eScindi /* known false */ 35637aec1d6eScindi arrowp->forever_false = 1; 35647aec1d6eScindi indent(); 35657aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 35667aec1d6eScindi " False constraint: "); 35677aec1d6eScindi ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 35687aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 35697aec1d6eScindi return (0); 35707aec1d6eScindi } 35717aec1d6eScindi } else { 35727aec1d6eScindi /* evaluation unsuccessful -- unknown value */ 35737aec1d6eScindi indent(); 35747aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 35757aec1d6eScindi " Deferred constraint: "); 35767aec1d6eScindi ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 35777aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 3578b5016cbbSstephh return (1); 35797aec1d6eScindi } 35807aec1d6eScindi } 35817aec1d6eScindi /* known true */ 3582b5016cbbSstephh arrowp->forever_true = 1; 3583b5016cbbSstephh indent(); 3584b5016cbbSstephh out(O_ALTFP|O_VERB|O_NONL, " True constraint: "); 3585b5016cbbSstephh for (ctp = arrowp->constraints; ctp != NULL; ctp = ctp->next) { 3586b5016cbbSstephh out(O_ALTFP|O_VERB|O_NONL, sep); 3587b5016cbbSstephh ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 3588b5016cbbSstephh sep = ", "; 3589b5016cbbSstephh } 3590b5016cbbSstephh out(O_ALTFP|O_VERB, NULL); 35917aec1d6eScindi return (1); 35927aec1d6eScindi } 35937aec1d6eScindi 35947c478bd9Sstevel@tonic-gate static int 35957c478bd9Sstevel@tonic-gate triggered(struct fme *fmep, struct event *ep, int mark) 35967c478bd9Sstevel@tonic-gate { 35977c478bd9Sstevel@tonic-gate struct bubble *bp; 35987c478bd9Sstevel@tonic-gate struct arrowlist *ap; 35997c478bd9Sstevel@tonic-gate int count = 0; 36007c478bd9Sstevel@tonic-gate 36017c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Tcallcount); 36027c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 36037c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 36047c478bd9Sstevel@tonic-gate if (bp->t != B_TO) 36057c478bd9Sstevel@tonic-gate continue; 36067c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 36077c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 36087c478bd9Sstevel@tonic-gate /* check count of marks against K in the bubble */ 36097aec1d6eScindi if ((ap->arrowp->mark & mark) && 36107c478bd9Sstevel@tonic-gate ++count >= bp->nork) 36117c478bd9Sstevel@tonic-gate return (1); 36127c478bd9Sstevel@tonic-gate } 36137c478bd9Sstevel@tonic-gate } 36147c478bd9Sstevel@tonic-gate return (0); 36157c478bd9Sstevel@tonic-gate } 36167c478bd9Sstevel@tonic-gate 36177aec1d6eScindi static int 36187aec1d6eScindi mark_arrows(struct fme *fmep, struct event *ep, int mark, 361900d0963fSdilpreet unsigned long long at_latest_by, unsigned long long *pdelay, int keep) 36207c478bd9Sstevel@tonic-gate { 36217c478bd9Sstevel@tonic-gate struct bubble *bp; 36227c478bd9Sstevel@tonic-gate struct arrowlist *ap; 36237aec1d6eScindi unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 36247aec1d6eScindi unsigned long long my_delay; 36257aec1d6eScindi enum fme_state result; 36267aec1d6eScindi int retval = 0; 36277c478bd9Sstevel@tonic-gate 36287c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 36297c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 36307c478bd9Sstevel@tonic-gate if (bp->t != B_FROM) 36317c478bd9Sstevel@tonic-gate continue; 36327aec1d6eScindi stats_counter_bump(fmep->Marrowcount); 36337aec1d6eScindi for (ap = itree_next_arrow(bp, NULL); ap; 36347aec1d6eScindi ap = itree_next_arrow(bp, ap)) { 36357aec1d6eScindi struct event *ep2 = ap->arrowp->head->myevent; 36367aec1d6eScindi /* 36377aec1d6eScindi * if we're clearing marks, we can avoid doing 36387aec1d6eScindi * all that work evaluating constraints. 36397aec1d6eScindi */ 36407aec1d6eScindi if (mark == 0) { 3641b5016cbbSstephh if (ap->arrowp->arrow_marked == 0) 3642b5016cbbSstephh continue; 3643b5016cbbSstephh ap->arrowp->arrow_marked = 0; 36447aec1d6eScindi ap->arrowp->mark &= ~EFFECTS_COUNTER; 364500d0963fSdilpreet if (keep && (ep2->cached_state & 364600d0963fSdilpreet (WAIT_EFFECT|CREDIBLE_EFFECT|PARENT_WAIT))) 364700d0963fSdilpreet ep2->keep_in_tree = 1; 36487aec1d6eScindi ep2->cached_state &= 36497aec1d6eScindi ~(WAIT_EFFECT|CREDIBLE_EFFECT|PARENT_WAIT); 365000d0963fSdilpreet (void) mark_arrows(fmep, ep2, mark, 0, NULL, 365100d0963fSdilpreet keep); 36527aec1d6eScindi continue; 36537aec1d6eScindi } 3654b5016cbbSstephh ap->arrowp->arrow_marked = 1; 36557aec1d6eScindi if (ep2->cached_state & REQMNTS_DISPROVED) { 36567aec1d6eScindi indent(); 36577aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 36587aec1d6eScindi " ALREADY DISPROVED "); 36597aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 36607aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 36617aec1d6eScindi continue; 36627aec1d6eScindi } 36637aec1d6eScindi if (ep2->cached_state & WAIT_EFFECT) { 36647aec1d6eScindi indent(); 36657aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 36667aec1d6eScindi " ALREADY EFFECTS WAIT "); 36677aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 36687aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 36697aec1d6eScindi continue; 36707aec1d6eScindi } 36717aec1d6eScindi if (ep2->cached_state & CREDIBLE_EFFECT) { 36727aec1d6eScindi indent(); 36737aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 36747aec1d6eScindi " ALREADY EFFECTS CREDIBLE "); 36757aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 36767aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 36777aec1d6eScindi continue; 36787aec1d6eScindi } 36797aec1d6eScindi if ((ep2->cached_state & PARENT_WAIT) && 36807aec1d6eScindi (mark & PARENT_WAIT)) { 36817aec1d6eScindi indent(); 36827aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 36837aec1d6eScindi " ALREADY PARENT EFFECTS WAIT "); 36847aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 36857aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 36867aec1d6eScindi continue; 36877aec1d6eScindi } 36887aec1d6eScindi platform_set_payloadnvp(ep2->nvp); 368900d0963fSdilpreet if (checkconstraints(fmep, ap->arrowp) == 0) { 36907aec1d6eScindi platform_set_payloadnvp(NULL); 36917aec1d6eScindi indent(); 36927aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 36937aec1d6eScindi " CONSTRAINTS FAIL "); 36947aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 36957aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 36967aec1d6eScindi continue; 36977aec1d6eScindi } 36987aec1d6eScindi platform_set_payloadnvp(NULL); 36997aec1d6eScindi ap->arrowp->mark |= EFFECTS_COUNTER; 37007aec1d6eScindi if (!triggered(fmep, ep2, EFFECTS_COUNTER)) { 37017aec1d6eScindi indent(); 37027aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 37037aec1d6eScindi " K-COUNT NOT YET MET "); 37047aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 37057aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 37067aec1d6eScindi continue; 37077aec1d6eScindi } 37087aec1d6eScindi ep2->cached_state &= ~PARENT_WAIT; 3709d96ce684Sstephh /* 3710d96ce684Sstephh * if we've reached an ereport and no propagation time 3711d96ce684Sstephh * is specified, use the Hesitate value 3712d96ce684Sstephh */ 3713d96ce684Sstephh if (ep2->t == N_EREPORT && at_latest_by == 0ULL && 3714d96ce684Sstephh ap->arrowp->maxdelay == 0ULL) { 3715d96ce684Sstephh out(O_ALTFP|O_VERB|O_NONL, " default wait "); 3716d96ce684Sstephh itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 3717d96ce684Sstephh out(O_ALTFP|O_VERB, NULL); 3718b5016cbbSstephh result = requirements_test(fmep, ep2, Hesitate, 3719b5016cbbSstephh &my_delay); 3720d96ce684Sstephh } else { 3721d96ce684Sstephh result = requirements_test(fmep, ep2, 3722d96ce684Sstephh at_latest_by + ap->arrowp->maxdelay, 3723d96ce684Sstephh &my_delay); 3724d96ce684Sstephh } 37257aec1d6eScindi if (result == FME_WAIT) { 37267aec1d6eScindi retval = WAIT_EFFECT; 37277aec1d6eScindi if (overall_delay > my_delay) 37287aec1d6eScindi overall_delay = my_delay; 37297aec1d6eScindi ep2->cached_state |= WAIT_EFFECT; 37307aec1d6eScindi indent(); 37317aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " EFFECTS WAIT "); 37327aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 37337aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 37347aec1d6eScindi indent_push(" E"); 37357aec1d6eScindi if (mark_arrows(fmep, ep2, PARENT_WAIT, 373600d0963fSdilpreet at_latest_by, &my_delay, 0) == 373700d0963fSdilpreet WAIT_EFFECT) { 37387aec1d6eScindi retval = WAIT_EFFECT; 37397aec1d6eScindi if (overall_delay > my_delay) 37407aec1d6eScindi overall_delay = my_delay; 37417c478bd9Sstevel@tonic-gate } 37427aec1d6eScindi indent_pop(); 37437aec1d6eScindi } else if (result == FME_DISPROVED) { 37447aec1d6eScindi indent(); 37457aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 37467aec1d6eScindi " EFFECTS DISPROVED "); 37477aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 37487aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 37497aec1d6eScindi } else { 37507aec1d6eScindi ep2->cached_state |= mark; 37517aec1d6eScindi indent(); 37527aec1d6eScindi if (mark == CREDIBLE_EFFECT) 37537c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 37547aec1d6eScindi " EFFECTS CREDIBLE "); 37557aec1d6eScindi else 37567aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 37577aec1d6eScindi " PARENT EFFECTS WAIT "); 37587aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep2); 37597aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 37607aec1d6eScindi indent_push(" E"); 37617aec1d6eScindi if (mark_arrows(fmep, ep2, mark, at_latest_by, 376200d0963fSdilpreet &my_delay, 0) == WAIT_EFFECT) { 37637aec1d6eScindi retval = WAIT_EFFECT; 37647aec1d6eScindi if (overall_delay > my_delay) 37657aec1d6eScindi overall_delay = my_delay; 37667c478bd9Sstevel@tonic-gate } 37677aec1d6eScindi indent_pop(); 37687c478bd9Sstevel@tonic-gate } 37697c478bd9Sstevel@tonic-gate } 37707c478bd9Sstevel@tonic-gate } 37717aec1d6eScindi if (retval == WAIT_EFFECT) 37727aec1d6eScindi *pdelay = overall_delay; 37737aec1d6eScindi return (retval); 37747c478bd9Sstevel@tonic-gate } 37757c478bd9Sstevel@tonic-gate 37767c478bd9Sstevel@tonic-gate static enum fme_state 37777aec1d6eScindi effects_test(struct fme *fmep, struct event *fault_event, 37787aec1d6eScindi unsigned long long at_latest_by, unsigned long long *pdelay) 37797c478bd9Sstevel@tonic-gate { 37807c478bd9Sstevel@tonic-gate struct event *error_event; 37817c478bd9Sstevel@tonic-gate enum fme_state return_value = FME_CREDIBLE; 37827aec1d6eScindi unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 37837aec1d6eScindi unsigned long long my_delay; 37847c478bd9Sstevel@tonic-gate 37857c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Ecallcount); 37867c478bd9Sstevel@tonic-gate indent_push(" E"); 37877c478bd9Sstevel@tonic-gate indent(); 37887c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 37897c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, fault_event); 37907c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 37917c478bd9Sstevel@tonic-gate 3792d96ce684Sstephh if (mark_arrows(fmep, fault_event, CREDIBLE_EFFECT, at_latest_by, 3793d96ce684Sstephh &my_delay, 0) == WAIT_EFFECT) { 3794d96ce684Sstephh return_value = FME_WAIT; 3795d96ce684Sstephh if (overall_delay > my_delay) 3796d96ce684Sstephh overall_delay = my_delay; 3797d96ce684Sstephh } 37987c478bd9Sstevel@tonic-gate for (error_event = fmep->observations; 37997c478bd9Sstevel@tonic-gate error_event; error_event = error_event->observations) { 38007c478bd9Sstevel@tonic-gate indent(); 38017c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 38027c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, error_event); 38037aec1d6eScindi if (!(error_event->cached_state & CREDIBLE_EFFECT)) { 38047aec1d6eScindi if (error_event->cached_state & 38057aec1d6eScindi (PARENT_WAIT|WAIT_EFFECT)) { 38067aec1d6eScindi out(O_ALTFP|O_VERB, " NOT YET triggered"); 38077aec1d6eScindi continue; 38087aec1d6eScindi } 38097c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 38107c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " NOT triggered"); 38117c478bd9Sstevel@tonic-gate break; 38127c478bd9Sstevel@tonic-gate } else { 38137c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " triggered"); 38147c478bd9Sstevel@tonic-gate } 38157c478bd9Sstevel@tonic-gate } 381600d0963fSdilpreet if (return_value == FME_DISPROVED) { 381700d0963fSdilpreet (void) mark_arrows(fmep, fault_event, 0, 0, NULL, 0); 381800d0963fSdilpreet } else { 381900d0963fSdilpreet fault_event->keep_in_tree = 1; 382000d0963fSdilpreet (void) mark_arrows(fmep, fault_event, 0, 0, NULL, 1); 382100d0963fSdilpreet } 38227c478bd9Sstevel@tonic-gate 38237c478bd9Sstevel@tonic-gate indent(); 38247aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-EFFECTS %s ", 38257aec1d6eScindi fme_state2str(return_value)); 38267c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, fault_event); 38277c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 38287c478bd9Sstevel@tonic-gate indent_pop(); 38297aec1d6eScindi if (return_value == FME_WAIT) 38307aec1d6eScindi *pdelay = overall_delay; 38317c478bd9Sstevel@tonic-gate return (return_value); 38327c478bd9Sstevel@tonic-gate } 38337c478bd9Sstevel@tonic-gate 38347c478bd9Sstevel@tonic-gate static enum fme_state 38357c478bd9Sstevel@tonic-gate requirements_test(struct fme *fmep, struct event *ep, 38367aec1d6eScindi unsigned long long at_latest_by, unsigned long long *pdelay) 38377c478bd9Sstevel@tonic-gate { 38387c478bd9Sstevel@tonic-gate int waiting_events; 38397c478bd9Sstevel@tonic-gate int credible_events; 38407aec1d6eScindi int deferred_events; 38417c478bd9Sstevel@tonic-gate enum fme_state return_value = FME_CREDIBLE; 38427c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 38437c478bd9Sstevel@tonic-gate unsigned long long arrow_delay; 38447c478bd9Sstevel@tonic-gate unsigned long long my_delay; 38457c478bd9Sstevel@tonic-gate struct event *ep2; 38467c478bd9Sstevel@tonic-gate struct bubble *bp; 38477c478bd9Sstevel@tonic-gate struct arrowlist *ap; 38487c478bd9Sstevel@tonic-gate 38497aec1d6eScindi if (ep->cached_state & REQMNTS_CREDIBLE) { 38507aec1d6eScindi indent(); 38517aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " REQMNTS ALREADY CREDIBLE "); 38527aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 38537aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 38547aec1d6eScindi return (FME_CREDIBLE); 38557aec1d6eScindi } 38567aec1d6eScindi if (ep->cached_state & REQMNTS_DISPROVED) { 38577aec1d6eScindi indent(); 38587aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " REQMNTS ALREADY DISPROVED "); 38597aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 38607aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 38617aec1d6eScindi return (FME_DISPROVED); 38627aec1d6eScindi } 38637aec1d6eScindi if (ep->cached_state & REQMNTS_WAIT) { 38647aec1d6eScindi indent(); 38657aec1d6eScindi *pdelay = ep->cached_delay; 38667aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, " REQMNTS ALREADY WAIT "); 38677aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 38687aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, ", wait for: "); 38697aec1d6eScindi ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 38707aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 38717aec1d6eScindi return (FME_WAIT); 38727aec1d6eScindi } 38737c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcallcount); 38747c478bd9Sstevel@tonic-gate indent_push(" R"); 38757c478bd9Sstevel@tonic-gate indent(); 38767c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 38777c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 38787c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, ", at latest by: "); 38797c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 38807c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 38817c478bd9Sstevel@tonic-gate 38827c478bd9Sstevel@tonic-gate if (ep->t == N_EREPORT) { 38837c478bd9Sstevel@tonic-gate if (ep->count == 0) { 38847c478bd9Sstevel@tonic-gate if (fmep->pull >= at_latest_by) { 38857c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 38867c478bd9Sstevel@tonic-gate } else { 38877aec1d6eScindi ep->cached_delay = *pdelay = at_latest_by; 38887c478bd9Sstevel@tonic-gate return_value = FME_WAIT; 38897c478bd9Sstevel@tonic-gate } 38907c478bd9Sstevel@tonic-gate } 38917c478bd9Sstevel@tonic-gate 38927c478bd9Sstevel@tonic-gate indent(); 38937c478bd9Sstevel@tonic-gate switch (return_value) { 38947c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 38957aec1d6eScindi ep->cached_state |= REQMNTS_CREDIBLE; 38967aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-REQMNTS CREDIBLE "); 38977c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 38987c478bd9Sstevel@tonic-gate break; 38997c478bd9Sstevel@tonic-gate case FME_DISPROVED: 39007aec1d6eScindi ep->cached_state |= REQMNTS_DISPROVED; 39017aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-REQMNTS DISPROVED "); 39027c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 39037c478bd9Sstevel@tonic-gate break; 39047c478bd9Sstevel@tonic-gate case FME_WAIT: 39057aec1d6eScindi ep->cached_state |= REQMNTS_WAIT; 39067aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-REQMNTS WAIT "); 39077c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 39087c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 39097c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 39107c478bd9Sstevel@tonic-gate break; 39117c478bd9Sstevel@tonic-gate default: 39127c478bd9Sstevel@tonic-gate out(O_DIE, "requirements_test: unexpected fme_state"); 39137c478bd9Sstevel@tonic-gate break; 39147c478bd9Sstevel@tonic-gate } 39157c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 39167c478bd9Sstevel@tonic-gate indent_pop(); 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate return (return_value); 39197c478bd9Sstevel@tonic-gate } 39207c478bd9Sstevel@tonic-gate 39217c478bd9Sstevel@tonic-gate /* this event is not a report, descend the tree */ 39227c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 39237c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 39247aec1d6eScindi int n; 39257aec1d6eScindi 39267c478bd9Sstevel@tonic-gate if (bp->t != B_FROM) 39277c478bd9Sstevel@tonic-gate continue; 39287c478bd9Sstevel@tonic-gate 39297aec1d6eScindi n = bp->nork; 39307aec1d6eScindi 39317aec1d6eScindi credible_events = 0; 39327aec1d6eScindi waiting_events = 0; 39337aec1d6eScindi deferred_events = 0; 39347aec1d6eScindi arrow_delay = TIMEVAL_EVENTUALLY; 39357aec1d6eScindi /* 39367aec1d6eScindi * n is -1 for 'A' so adjust it. 39377aec1d6eScindi * XXX just count up the arrows for now. 39387aec1d6eScindi */ 39397aec1d6eScindi if (n < 0) { 39407aec1d6eScindi n = 0; 39417aec1d6eScindi for (ap = itree_next_arrow(bp, NULL); ap; 39427aec1d6eScindi ap = itree_next_arrow(bp, ap)) 39437aec1d6eScindi n++; 39447aec1d6eScindi indent(); 39457aec1d6eScindi out(O_ALTFP|O_VERB, " Bubble Counted N=%d", n); 39467aec1d6eScindi } else { 39477aec1d6eScindi indent(); 39487aec1d6eScindi out(O_ALTFP|O_VERB, " Bubble N=%d", n); 39497aec1d6eScindi } 39507c478bd9Sstevel@tonic-gate 39517aec1d6eScindi if (n == 0) 39527aec1d6eScindi continue; 39537aec1d6eScindi if (!(bp->mark & (BUBBLE_ELIDED|BUBBLE_OK))) { 39547c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 39557c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 39567c478bd9Sstevel@tonic-gate ep2 = ap->arrowp->head->myevent; 39577aec1d6eScindi platform_set_payloadnvp(ep2->nvp); 3958b7d3956bSstephh (void) checkconstraints(fmep, ap->arrowp); 39598cffa125SStephen Hanson if (!ap->arrowp->forever_false) { 39607aec1d6eScindi /* 3961b7d3956bSstephh * if all arrows are invalidated by the 39627aec1d6eScindi * constraints, then we should elide the 39637aec1d6eScindi * whole bubble to be consistant with 39647aec1d6eScindi * the tree creation time behaviour 39657aec1d6eScindi */ 3966b7d3956bSstephh bp->mark |= BUBBLE_OK; 39677aec1d6eScindi platform_set_payloadnvp(NULL); 39687c478bd9Sstevel@tonic-gate break; 39697aec1d6eScindi } 39707aec1d6eScindi platform_set_payloadnvp(NULL); 39717aec1d6eScindi } 39727aec1d6eScindi } 39737aec1d6eScindi for (ap = itree_next_arrow(bp, NULL); ap; 39747aec1d6eScindi ap = itree_next_arrow(bp, ap)) { 39757aec1d6eScindi ep2 = ap->arrowp->head->myevent; 39767aec1d6eScindi if (n <= credible_events) 39777aec1d6eScindi break; 39787c478bd9Sstevel@tonic-gate 39797aec1d6eScindi ap->arrowp->mark |= REQMNTS_COUNTER; 39807aec1d6eScindi if (triggered(fmep, ep2, REQMNTS_COUNTER)) 39817aec1d6eScindi /* XXX adding max timevals! */ 39827aec1d6eScindi switch (requirements_test(fmep, ep2, 39837aec1d6eScindi at_latest_by + ap->arrowp->maxdelay, 39847aec1d6eScindi &my_delay)) { 39857aec1d6eScindi case FME_DEFERRED: 39867aec1d6eScindi deferred_events++; 39877aec1d6eScindi break; 39887aec1d6eScindi case FME_CREDIBLE: 39897c478bd9Sstevel@tonic-gate credible_events++; 39907aec1d6eScindi break; 39917aec1d6eScindi case FME_DISPROVED: 39927aec1d6eScindi break; 39937aec1d6eScindi case FME_WAIT: 39947aec1d6eScindi if (my_delay < arrow_delay) 39957aec1d6eScindi arrow_delay = my_delay; 39967aec1d6eScindi waiting_events++; 39977aec1d6eScindi break; 39987aec1d6eScindi default: 39997aec1d6eScindi out(O_DIE, 40007aec1d6eScindi "Bug in requirements_test."); 40017aec1d6eScindi } 40027aec1d6eScindi else 40037aec1d6eScindi deferred_events++; 40047aec1d6eScindi } 4005b7d3956bSstephh if (!(bp->mark & BUBBLE_OK) && waiting_events == 0) { 4006b7d3956bSstephh bp->mark |= BUBBLE_ELIDED; 4007b7d3956bSstephh continue; 4008b7d3956bSstephh } 40097aec1d6eScindi indent(); 40107aec1d6eScindi out(O_ALTFP|O_VERB, " Credible: %d Waiting %d", 40117aec1d6eScindi credible_events + deferred_events, waiting_events); 40127aec1d6eScindi if (credible_events + deferred_events + waiting_events < n) { 40137aec1d6eScindi /* Can never meet requirements */ 40147aec1d6eScindi ep->cached_state |= REQMNTS_DISPROVED; 40157c478bd9Sstevel@tonic-gate indent(); 40167aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-REQMNTS DISPROVED "); 40177c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 40187c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 40197aec1d6eScindi indent_pop(); 40207aec1d6eScindi return (FME_DISPROVED); 40217aec1d6eScindi } 40227aec1d6eScindi if (credible_events + deferred_events < n) { 40237aec1d6eScindi /* will have to wait */ 40247aec1d6eScindi /* wait time is shortest known */ 40257aec1d6eScindi if (arrow_delay < overall_delay) 40267aec1d6eScindi overall_delay = arrow_delay; 40277aec1d6eScindi return_value = FME_WAIT; 40287aec1d6eScindi } else if (credible_events < n) { 40297aec1d6eScindi if (return_value != FME_WAIT) 40307aec1d6eScindi return_value = FME_DEFERRED; 40317c478bd9Sstevel@tonic-gate } 40327c478bd9Sstevel@tonic-gate } 40337c478bd9Sstevel@tonic-gate 40347c478bd9Sstevel@tonic-gate /* 40357aec1d6eScindi * don't mark as FME_DEFERRED. If this event isn't reached by another 40367aec1d6eScindi * path, then this will be considered FME_CREDIBLE. But if it is 40377aec1d6eScindi * reached by a different path so the K-count is met, then might 40387aec1d6eScindi * get overridden by FME_WAIT or FME_DISPROVED. 40397c478bd9Sstevel@tonic-gate */ 40407aec1d6eScindi if (return_value == FME_WAIT) { 40417aec1d6eScindi ep->cached_state |= REQMNTS_WAIT; 40427aec1d6eScindi ep->cached_delay = *pdelay = overall_delay; 40437aec1d6eScindi } else if (return_value == FME_CREDIBLE) { 40447aec1d6eScindi ep->cached_state |= REQMNTS_CREDIBLE; 40457c478bd9Sstevel@tonic-gate } 40467c478bd9Sstevel@tonic-gate indent(); 40477aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-REQMNTS %s ", 40487aec1d6eScindi fme_state2str(return_value)); 40497c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 40507c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 40517c478bd9Sstevel@tonic-gate indent_pop(); 40527c478bd9Sstevel@tonic-gate return (return_value); 40537c478bd9Sstevel@tonic-gate } 40547c478bd9Sstevel@tonic-gate 40557c478bd9Sstevel@tonic-gate static enum fme_state 40567c478bd9Sstevel@tonic-gate causes_test(struct fme *fmep, struct event *ep, 40577c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay) 40587c478bd9Sstevel@tonic-gate { 40597c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 40607c478bd9Sstevel@tonic-gate unsigned long long my_delay; 40617c478bd9Sstevel@tonic-gate int credible_results = 0; 40627c478bd9Sstevel@tonic-gate int waiting_results = 0; 40637c478bd9Sstevel@tonic-gate enum fme_state fstate; 40647c478bd9Sstevel@tonic-gate struct event *tail_event; 40657c478bd9Sstevel@tonic-gate struct bubble *bp; 40667c478bd9Sstevel@tonic-gate struct arrowlist *ap; 40677c478bd9Sstevel@tonic-gate int k = 1; 40687c478bd9Sstevel@tonic-gate 40697c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Ccallcount); 40707c478bd9Sstevel@tonic-gate indent_push(" C"); 40717c478bd9Sstevel@tonic-gate indent(); 40727c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 40737c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 40747c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 40757c478bd9Sstevel@tonic-gate 40767c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 40777c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 40787c478bd9Sstevel@tonic-gate if (bp->t != B_TO) 40797c478bd9Sstevel@tonic-gate continue; 40807c478bd9Sstevel@tonic-gate k = bp->nork; /* remember the K value */ 40817c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 40827c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 40837c478bd9Sstevel@tonic-gate int do_not_follow = 0; 40847aec1d6eScindi 40857aec1d6eScindi /* 40867aec1d6eScindi * if we get to the same event multiple times 40877aec1d6eScindi * only worry about the first one. 40887aec1d6eScindi */ 40897aec1d6eScindi if (ap->arrowp->tail->myevent->cached_state & 40907aec1d6eScindi CAUSES_TESTED) { 40917aec1d6eScindi indent(); 40927aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, 40937aec1d6eScindi " causes test already run for "); 40947aec1d6eScindi itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, 40957aec1d6eScindi ap->arrowp->tail->myevent); 40967aec1d6eScindi out(O_ALTFP|O_VERB, NULL); 40977aec1d6eScindi continue; 40987aec1d6eScindi } 40997aec1d6eScindi 41007c478bd9Sstevel@tonic-gate /* 41017c478bd9Sstevel@tonic-gate * see if false constraint prevents us 41027c478bd9Sstevel@tonic-gate * from traversing this arrow 41037c478bd9Sstevel@tonic-gate */ 41047c478bd9Sstevel@tonic-gate platform_set_payloadnvp(ep->nvp); 410500d0963fSdilpreet if (checkconstraints(fmep, ap->arrowp) == 0) 41067aec1d6eScindi do_not_follow = 1; 41077c478bd9Sstevel@tonic-gate platform_set_payloadnvp(NULL); 41087c478bd9Sstevel@tonic-gate if (do_not_follow) { 41097c478bd9Sstevel@tonic-gate indent(); 41107c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 41117c478bd9Sstevel@tonic-gate " False arrow from "); 41127c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, 41137c478bd9Sstevel@tonic-gate ap->arrowp->tail->myevent); 41147c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 41157c478bd9Sstevel@tonic-gate continue; 41167c478bd9Sstevel@tonic-gate } 41177c478bd9Sstevel@tonic-gate 41187aec1d6eScindi ap->arrowp->tail->myevent->cached_state |= 41197aec1d6eScindi CAUSES_TESTED; 41207aec1d6eScindi tail_event = ap->arrowp->tail->myevent; 41217aec1d6eScindi fstate = hypothesise(fmep, tail_event, at_latest_by, 41227aec1d6eScindi &my_delay); 41237c478bd9Sstevel@tonic-gate 41247c478bd9Sstevel@tonic-gate switch (fstate) { 41257c478bd9Sstevel@tonic-gate case FME_WAIT: 41267c478bd9Sstevel@tonic-gate if (my_delay < overall_delay) 41277c478bd9Sstevel@tonic-gate overall_delay = my_delay; 41287c478bd9Sstevel@tonic-gate waiting_results++; 41297c478bd9Sstevel@tonic-gate break; 41307c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 41317c478bd9Sstevel@tonic-gate credible_results++; 41327c478bd9Sstevel@tonic-gate break; 41337c478bd9Sstevel@tonic-gate case FME_DISPROVED: 41347c478bd9Sstevel@tonic-gate break; 41357c478bd9Sstevel@tonic-gate default: 41367c478bd9Sstevel@tonic-gate out(O_DIE, "Bug in causes_test"); 41377c478bd9Sstevel@tonic-gate } 41387c478bd9Sstevel@tonic-gate } 41397c478bd9Sstevel@tonic-gate } 41407c478bd9Sstevel@tonic-gate /* compare against K */ 41417c478bd9Sstevel@tonic-gate if (credible_results + waiting_results < k) { 41427c478bd9Sstevel@tonic-gate indent(); 41437aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-CAUSES DISPROVED "); 41447c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 41457c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 41467c478bd9Sstevel@tonic-gate indent_pop(); 41477c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 41487c478bd9Sstevel@tonic-gate } 41497c478bd9Sstevel@tonic-gate if (waiting_results != 0) { 41507c478bd9Sstevel@tonic-gate *pdelay = overall_delay; 41517c478bd9Sstevel@tonic-gate indent(); 41527aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-CAUSES WAIT "); 41537c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 41547c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 41557c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 41567c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 41577c478bd9Sstevel@tonic-gate indent_pop(); 41587c478bd9Sstevel@tonic-gate return (FME_WAIT); 41597c478bd9Sstevel@tonic-gate } 41607c478bd9Sstevel@tonic-gate indent(); 41617aec1d6eScindi out(O_ALTFP|O_VERB|O_NONL, "<-CAUSES CREDIBLE "); 41627c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 41637c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 41647c478bd9Sstevel@tonic-gate indent_pop(); 41657c478bd9Sstevel@tonic-gate return (FME_CREDIBLE); 41667c478bd9Sstevel@tonic-gate } 41677c478bd9Sstevel@tonic-gate 41687c478bd9Sstevel@tonic-gate static enum fme_state 41697c478bd9Sstevel@tonic-gate hypothesise(struct fme *fmep, struct event *ep, 4170a3f6a2a4SRob Johnston unsigned long long at_latest_by, unsigned long long *pdelay) 41717c478bd9Sstevel@tonic-gate { 41727c478bd9Sstevel@tonic-gate enum fme_state rtr, otr; 41737c478bd9Sstevel@tonic-gate unsigned long long my_delay; 41747c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 41757c478bd9Sstevel@tonic-gate 41767c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Hcallcount); 41777c478bd9Sstevel@tonic-gate indent_push(" H"); 41787c478bd9Sstevel@tonic-gate indent(); 41797c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 41807c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 41817c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, ", at latest by: "); 41827c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 41837c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 41847c478bd9Sstevel@tonic-gate 41857aec1d6eScindi rtr = requirements_test(fmep, ep, at_latest_by, &my_delay); 41867c478bd9Sstevel@tonic-gate if ((rtr == FME_WAIT) && (my_delay < overall_delay)) 41877c478bd9Sstevel@tonic-gate overall_delay = my_delay; 41887c478bd9Sstevel@tonic-gate if (rtr != FME_DISPROVED) { 41897c478bd9Sstevel@tonic-gate if (is_problem(ep->t)) { 41907aec1d6eScindi otr = effects_test(fmep, ep, at_latest_by, &my_delay); 41917c478bd9Sstevel@tonic-gate if (otr != FME_DISPROVED) { 4192b5016cbbSstephh if (fmep->peek == 0 && ep->is_suspect == 0) { 41937c478bd9Sstevel@tonic-gate ep->suspects = fmep->suspects; 4194b5016cbbSstephh ep->is_suspect = 1; 41957c478bd9Sstevel@tonic-gate fmep->suspects = ep; 41967c478bd9Sstevel@tonic-gate fmep->nsuspects++; 41977c478bd9Sstevel@tonic-gate } 41987c478bd9Sstevel@tonic-gate } 41997c478bd9Sstevel@tonic-gate } else 42007c478bd9Sstevel@tonic-gate otr = causes_test(fmep, ep, at_latest_by, &my_delay); 42017c478bd9Sstevel@tonic-gate if ((otr == FME_WAIT) && (my_delay < overall_delay)) 42027c478bd9Sstevel@tonic-gate overall_delay = my_delay; 42037c478bd9Sstevel@tonic-gate if ((otr != FME_DISPROVED) && 42047c478bd9Sstevel@tonic-gate ((rtr == FME_WAIT) || (otr == FME_WAIT))) 42057c478bd9Sstevel@tonic-gate *pdelay = overall_delay; 42067c478bd9Sstevel@tonic-gate } 42077c478bd9Sstevel@tonic-gate if (rtr == FME_DISPROVED) { 42087c478bd9Sstevel@tonic-gate indent(); 42097c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 42107c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 42117c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (doesn't meet requirements)"); 42127c478bd9Sstevel@tonic-gate indent_pop(); 42137c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 42147c478bd9Sstevel@tonic-gate } 42157c478bd9Sstevel@tonic-gate if ((otr == FME_DISPROVED) && is_problem(ep->t)) { 42167c478bd9Sstevel@tonic-gate indent(); 42177c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 42187c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 42197c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (doesn't explain all reports)"); 42207c478bd9Sstevel@tonic-gate indent_pop(); 42217c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 42227c478bd9Sstevel@tonic-gate } 42237c478bd9Sstevel@tonic-gate if (otr == FME_DISPROVED) { 42247c478bd9Sstevel@tonic-gate indent(); 42257c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 42267c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 42277c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (causes are not credible)"); 42287c478bd9Sstevel@tonic-gate indent_pop(); 42297c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 42307c478bd9Sstevel@tonic-gate } 42317c478bd9Sstevel@tonic-gate if ((rtr == FME_WAIT) || (otr == FME_WAIT)) { 42327c478bd9Sstevel@tonic-gate indent(); 42337c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-WAIT "); 42347c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 42357c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 42367c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &overall_delay); 42377c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 42387c478bd9Sstevel@tonic-gate indent_pop(); 42397c478bd9Sstevel@tonic-gate return (FME_WAIT); 42407c478bd9Sstevel@tonic-gate } 42417c478bd9Sstevel@tonic-gate indent(); 42427c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-CREDIBLE "); 42437c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 42447c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 42457c478bd9Sstevel@tonic-gate indent_pop(); 42467c478bd9Sstevel@tonic-gate return (FME_CREDIBLE); 42477c478bd9Sstevel@tonic-gate } 42487aec1d6eScindi 42497aec1d6eScindi /* 42507aec1d6eScindi * fme_istat_load -- reconstitute any persistent istats 42517aec1d6eScindi */ 42527aec1d6eScindi void 42537aec1d6eScindi fme_istat_load(fmd_hdl_t *hdl) 42547aec1d6eScindi { 42557aec1d6eScindi int sz; 42567aec1d6eScindi char *sbuf; 42577aec1d6eScindi char *ptr; 42587aec1d6eScindi 42597aec1d6eScindi if ((sz = fmd_buf_size(hdl, NULL, WOBUF_ISTATS)) == 0) { 42607aec1d6eScindi out(O_ALTFP, "fme_istat_load: No stats"); 42617aec1d6eScindi return; 42627aec1d6eScindi } 42637aec1d6eScindi 42647aec1d6eScindi sbuf = alloca(sz); 42657aec1d6eScindi 42667aec1d6eScindi fmd_buf_read(hdl, NULL, WOBUF_ISTATS, sbuf, sz); 42677aec1d6eScindi 42687aec1d6eScindi /* 42697aec1d6eScindi * pick apart the serialized stats 42707aec1d6eScindi * 42717aec1d6eScindi * format is: 42727aec1d6eScindi * <class-name>, '@', <path>, '\0', <value>, '\0' 42737aec1d6eScindi * for example: 42747aec1d6eScindi * "stat.first@stat0/path0\02\0stat.second@stat0/path1\023\0" 42757aec1d6eScindi * 42767aec1d6eScindi * since this is parsing our own serialized data, any parsing issues 42777aec1d6eScindi * are fatal, so we check for them all with ASSERT() below. 42787aec1d6eScindi */ 42797aec1d6eScindi ptr = sbuf; 42807aec1d6eScindi while (ptr < &sbuf[sz]) { 42817aec1d6eScindi char *sepptr; 42827aec1d6eScindi struct node *np; 42837aec1d6eScindi int val; 42847aec1d6eScindi 42857aec1d6eScindi sepptr = strchr(ptr, '@'); 42867aec1d6eScindi ASSERT(sepptr != NULL); 42877aec1d6eScindi *sepptr = '\0'; 42887aec1d6eScindi 42897aec1d6eScindi /* construct the event */ 42907aec1d6eScindi np = newnode(T_EVENT, NULL, 0); 42917aec1d6eScindi np->u.event.ename = newnode(T_NAME, NULL, 0); 42927aec1d6eScindi np->u.event.ename->u.name.t = N_STAT; 42937aec1d6eScindi np->u.event.ename->u.name.s = stable(ptr); 42947aec1d6eScindi np->u.event.ename->u.name.it = IT_ENAME; 42957aec1d6eScindi np->u.event.ename->u.name.last = np->u.event.ename; 42967aec1d6eScindi 42977aec1d6eScindi ptr = sepptr + 1; 42987aec1d6eScindi ASSERT(ptr < &sbuf[sz]); 42997aec1d6eScindi ptr += strlen(ptr); 43007aec1d6eScindi ptr++; /* move past the '\0' separating path from value */ 43017aec1d6eScindi ASSERT(ptr < &sbuf[sz]); 43027aec1d6eScindi ASSERT(isdigit(*ptr)); 43037aec1d6eScindi val = atoi(ptr); 43047aec1d6eScindi ASSERT(val > 0); 43057aec1d6eScindi ptr += strlen(ptr); 43067aec1d6eScindi ptr++; /* move past the final '\0' for this entry */ 43077aec1d6eScindi 43087aec1d6eScindi np->u.event.epname = pathstring2epnamenp(sepptr + 1); 43097aec1d6eScindi ASSERT(np->u.event.epname != NULL); 43107aec1d6eScindi 43117aec1d6eScindi istat_bump(np, val); 43127aec1d6eScindi tree_free(np); 43137aec1d6eScindi } 43147aec1d6eScindi 43157aec1d6eScindi istat_save(); 43167aec1d6eScindi } 4317