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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * fme.c -- fault management exercise module 277c478bd9Sstevel@tonic-gate * 287c478bd9Sstevel@tonic-gate * this module provides the simulated fault management exercise. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 367c478bd9Sstevel@tonic-gate #include <strings.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <alloca.h> 397c478bd9Sstevel@tonic-gate #include <libnvpair.h> 407c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 417c478bd9Sstevel@tonic-gate #include <fm/fmd_api.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" 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* imported from eft.c... */ 597c478bd9Sstevel@tonic-gate extern int Autoconvict; 607c478bd9Sstevel@tonic-gate extern char *Autoclose; 617c478bd9Sstevel@tonic-gate extern hrtime_t Hesitate; 627c478bd9Sstevel@tonic-gate extern nv_alloc_t Eft_nv_hdl; 63*0cc1f05eSjrutt extern int Max_fme; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* fme under construction is global so we can free it on module abort */ 667c478bd9Sstevel@tonic-gate static struct fme *Nfmep; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate static const char *Undiag_reason; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static int Nextid = 0; 717c478bd9Sstevel@tonic-gate 72*0cc1f05eSjrutt static int Open_fme_count = 0; /* Count of open FMEs */ 73*0cc1f05eSjrutt 747c478bd9Sstevel@tonic-gate /* list of fault management exercises underway */ 757c478bd9Sstevel@tonic-gate static struct fme { 767c478bd9Sstevel@tonic-gate struct fme *next; /* next exercise */ 777c478bd9Sstevel@tonic-gate unsigned long long ull; /* time when fme was created */ 787c478bd9Sstevel@tonic-gate int id; /* FME id */ 797c478bd9Sstevel@tonic-gate struct cfgdata *cfgdata; /* full configuration data */ 807c478bd9Sstevel@tonic-gate struct lut *eventtree; /* propagation tree for this FME */ 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * The initial error report that created this FME is kept in 837c478bd9Sstevel@tonic-gate * two forms. e0 points to the instance tree node and is used 847c478bd9Sstevel@tonic-gate * by fme_eval() as the starting point for the inference 857c478bd9Sstevel@tonic-gate * algorithm. e0r is the event handle FMD passed to us when 867c478bd9Sstevel@tonic-gate * the ereport first arrived and is used when setting timers, 877c478bd9Sstevel@tonic-gate * which are always relative to the time of this initial 887c478bd9Sstevel@tonic-gate * report. 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate struct event *e0; 917c478bd9Sstevel@tonic-gate fmd_event_t *e0r; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate id_t timer; /* for setting an fmd time-out */ 947c478bd9Sstevel@tonic-gate id_t htid; /* for setting hesitation timer */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate struct event *ecurrent; /* ereport under consideration */ 977c478bd9Sstevel@tonic-gate struct event *suspects; /* current suspect list */ 987c478bd9Sstevel@tonic-gate struct event *psuspects; /* previous suspect list */ 997c478bd9Sstevel@tonic-gate int nsuspects; /* count of suspects */ 1007c478bd9Sstevel@tonic-gate int nonfault; /* zero if all suspects T_FAULT */ 1017c478bd9Sstevel@tonic-gate int posted_suspects; /* true if we've posted a diagnosis */ 1027c478bd9Sstevel@tonic-gate int hesitated; /* true if we hesitated */ 1037c478bd9Sstevel@tonic-gate int uniqobs; /* number of unique events observed */ 1047c478bd9Sstevel@tonic-gate int peek; /* just peeking, don't track suspects */ 105*0cc1f05eSjrutt int overflow; /* true if overflow FME */ 1067c478bd9Sstevel@tonic-gate enum fme_state { 1077c478bd9Sstevel@tonic-gate FME_NOTHING = 5000, /* not evaluated yet */ 1087c478bd9Sstevel@tonic-gate FME_WAIT, /* need to wait for more info */ 1097c478bd9Sstevel@tonic-gate FME_CREDIBLE, /* suspect list is credible */ 1107c478bd9Sstevel@tonic-gate FME_DISPROVED /* no valid suspects found */ 1117c478bd9Sstevel@tonic-gate } state; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate unsigned long long pull; /* time passed since created */ 1147c478bd9Sstevel@tonic-gate unsigned long long wull; /* wait until this time for re-eval */ 1157c478bd9Sstevel@tonic-gate struct event *observations; /* observation list */ 1167c478bd9Sstevel@tonic-gate struct lut *globals; /* values of global variables */ 1177c478bd9Sstevel@tonic-gate /* fmd interfacing */ 1187c478bd9Sstevel@tonic-gate fmd_hdl_t *hdl; /* handle for talking with fmd */ 1197c478bd9Sstevel@tonic-gate fmd_case_t *fmcase; /* what fmd 'case' we associate with */ 1207c478bd9Sstevel@tonic-gate /* stats */ 1217c478bd9Sstevel@tonic-gate struct stats *Rcount; 1227c478bd9Sstevel@tonic-gate struct stats *Hcallcount; 1237c478bd9Sstevel@tonic-gate struct stats *Rcallcount; 1247c478bd9Sstevel@tonic-gate struct stats *Ccallcount; 1257c478bd9Sstevel@tonic-gate struct stats *Ecallcount; 1267c478bd9Sstevel@tonic-gate struct stats *Tcallcount; 1277c478bd9Sstevel@tonic-gate struct stats *Marrowcount; 1287c478bd9Sstevel@tonic-gate struct stats *diags; 1297c478bd9Sstevel@tonic-gate } *FMElist, *EFMElist, *ClosedFMEs; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate static struct case_list { 1327c478bd9Sstevel@tonic-gate fmd_case_t *fmcase; 1337c478bd9Sstevel@tonic-gate struct case_list *next; 1347c478bd9Sstevel@tonic-gate } *Undiagablecaselist; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static void fme_eval(struct fme *fmep, fmd_event_t *ffep); 1377c478bd9Sstevel@tonic-gate static enum fme_state hypothesise(struct fme *fmep, struct event *ep, 1387c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay, 1397c478bd9Sstevel@tonic-gate struct arrow *arrowp); 1407c478bd9Sstevel@tonic-gate static struct node *eventprop_lookup(struct event *ep, const char *propname); 1417c478bd9Sstevel@tonic-gate static struct node *pathstring2epnamenp(char *path); 1427c478bd9Sstevel@tonic-gate static void publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep); 1437c478bd9Sstevel@tonic-gate static void restore_suspects(struct fme *fmep); 1447c478bd9Sstevel@tonic-gate static void save_suspects(struct fme *fmep); 1457c478bd9Sstevel@tonic-gate static void destroy_fme(struct fme *f); 1467c478bd9Sstevel@tonic-gate static void fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 1477c478bd9Sstevel@tonic-gate const char *eventstring, const struct ipath *ipp, nvlist_t *nvl); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate static struct fme * 1507c478bd9Sstevel@tonic-gate alloc_fme(void) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate struct fme *fmep; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate fmep = MALLOC(sizeof (*fmep)); 1557c478bd9Sstevel@tonic-gate bzero(fmep, sizeof (*fmep)); 1567c478bd9Sstevel@tonic-gate return (fmep); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * fme_ready -- called when all initialization of the FME (except for 1617c478bd9Sstevel@tonic-gate * stats) has completed successfully. Adds the fme to global lists 1627c478bd9Sstevel@tonic-gate * and establishes its stats. 1637c478bd9Sstevel@tonic-gate */ 1647c478bd9Sstevel@tonic-gate static struct fme * 1657c478bd9Sstevel@tonic-gate fme_ready(struct fme *fmep) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate char nbuf[100]; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate Nfmep = NULL; /* don't need to free this on module abort now */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if (EFMElist) { 1727c478bd9Sstevel@tonic-gate EFMElist->next = fmep; 1737c478bd9Sstevel@tonic-gate EFMElist = fmep; 1747c478bd9Sstevel@tonic-gate } else 1757c478bd9Sstevel@tonic-gate FMElist = EFMElist = fmep; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Rcount", fmep->id); 1787c478bd9Sstevel@tonic-gate fmep->Rcount = stats_new_counter(nbuf, "ereports received", 0); 1797c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Hcall", fmep->id); 1807c478bd9Sstevel@tonic-gate fmep->Hcallcount = stats_new_counter(nbuf, "calls to hypothesise()", 1); 1817c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Rcall", fmep->id); 1827c478bd9Sstevel@tonic-gate fmep->Rcallcount = stats_new_counter(nbuf, 1837c478bd9Sstevel@tonic-gate "calls to requirements_test()", 1); 1847c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Ccall", fmep->id); 1857c478bd9Sstevel@tonic-gate fmep->Ccallcount = stats_new_counter(nbuf, "calls to causes_test()", 1); 1867c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Ecall", fmep->id); 1877c478bd9Sstevel@tonic-gate fmep->Ecallcount = 1887c478bd9Sstevel@tonic-gate stats_new_counter(nbuf, "calls to effects_test()", 1); 1897c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Tcall", fmep->id); 1907c478bd9Sstevel@tonic-gate fmep->Tcallcount = stats_new_counter(nbuf, "calls to triggered()", 1); 1917c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.Marrow", fmep->id); 1927c478bd9Sstevel@tonic-gate fmep->Marrowcount = stats_new_counter(nbuf, 1937c478bd9Sstevel@tonic-gate "arrows marked by mark_arrows()", 1); 1947c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "fme%d.diags", fmep->id); 1957c478bd9Sstevel@tonic-gate fmep->diags = stats_new_counter(nbuf, "suspect lists diagnosed", 0); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB2, "newfme: config snapshot contains..."); 1987c478bd9Sstevel@tonic-gate config_print(O_ALTFP|O_VERB2, fmep->cfgdata->cooked); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate return (fmep); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static struct fme * 2047c478bd9Sstevel@tonic-gate newfme(const char *e0class, const struct ipath *e0ipp) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate struct cfgdata *cfgdata; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if ((cfgdata = config_snapshot()) == NULL) { 2097c478bd9Sstevel@tonic-gate out(O_ALTFP, "newfme: NULL configuration"); 2107c478bd9Sstevel@tonic-gate Undiag_reason = UD_NOCONF; 2117c478bd9Sstevel@tonic-gate return (NULL); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate Nfmep = alloc_fme(); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate Nfmep->id = Nextid++; 2177c478bd9Sstevel@tonic-gate Nfmep->cfgdata = cfgdata; 2187c478bd9Sstevel@tonic-gate Nfmep->posted_suspects = 0; 2197c478bd9Sstevel@tonic-gate Nfmep->uniqobs = 0; 2207c478bd9Sstevel@tonic-gate Nfmep->state = FME_NOTHING; 2217c478bd9Sstevel@tonic-gate Nfmep->pull = 0ULL; 222*0cc1f05eSjrutt Nfmep->overflow = 0; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate Nfmep->fmcase = NULL; 2257c478bd9Sstevel@tonic-gate Nfmep->hdl = NULL; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if ((Nfmep->eventtree = itree_create(cfgdata->cooked)) == NULL) { 2287c478bd9Sstevel@tonic-gate out(O_ALTFP, "newfme: NULL instance tree"); 2297c478bd9Sstevel@tonic-gate Undiag_reason = UD_INSTFAIL; 2307c478bd9Sstevel@tonic-gate config_free(cfgdata); 2317c478bd9Sstevel@tonic-gate FREE(Nfmep); 2327c478bd9Sstevel@tonic-gate Nfmep = NULL; 2337c478bd9Sstevel@tonic-gate return (NULL); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate itree_ptree(O_ALTFP|O_VERB2, Nfmep->eventtree); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate if ((Nfmep->e0 = 2397c478bd9Sstevel@tonic-gate itree_lookup(Nfmep->eventtree, e0class, e0ipp)) == NULL) { 2407c478bd9Sstevel@tonic-gate out(O_ALTFP, "newfme: e0 not in instance tree"); 2417c478bd9Sstevel@tonic-gate Undiag_reason = UD_BADEVENTI; 2427c478bd9Sstevel@tonic-gate itree_free(Nfmep->eventtree); 2437c478bd9Sstevel@tonic-gate config_free(cfgdata); 2447c478bd9Sstevel@tonic-gate FREE(Nfmep); 2457c478bd9Sstevel@tonic-gate Nfmep = NULL; 2467c478bd9Sstevel@tonic-gate return (NULL); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate return (fme_ready(Nfmep)); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate void 2537c478bd9Sstevel@tonic-gate fme_fini(void) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate struct fme *sfp, *fp; 2567c478bd9Sstevel@tonic-gate struct case_list *ucasep, *nextcasep; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate ucasep = Undiagablecaselist; 2597c478bd9Sstevel@tonic-gate while (ucasep != NULL) { 2607c478bd9Sstevel@tonic-gate nextcasep = ucasep->next; 2617c478bd9Sstevel@tonic-gate FREE(ucasep); 2627c478bd9Sstevel@tonic-gate ucasep = nextcasep; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate Undiagablecaselist = NULL; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate /* clean up closed fmes */ 2677c478bd9Sstevel@tonic-gate fp = ClosedFMEs; 2687c478bd9Sstevel@tonic-gate while (fp != NULL) { 2697c478bd9Sstevel@tonic-gate sfp = fp->next; 2707c478bd9Sstevel@tonic-gate destroy_fme(fp); 2717c478bd9Sstevel@tonic-gate fp = sfp; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate ClosedFMEs = NULL; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate fp = FMElist; 2767c478bd9Sstevel@tonic-gate while (fp != NULL) { 2777c478bd9Sstevel@tonic-gate sfp = fp->next; 2787c478bd9Sstevel@tonic-gate destroy_fme(fp); 2797c478bd9Sstevel@tonic-gate fp = sfp; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate FMElist = EFMElist = NULL; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* if we were in the middle of creating an fme, free it now */ 2847c478bd9Sstevel@tonic-gate if (Nfmep) { 2857c478bd9Sstevel@tonic-gate destroy_fme(Nfmep); 2867c478bd9Sstevel@tonic-gate Nfmep = NULL; 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * Allocated space for a buffer name. 20 bytes allows for 2927c478bd9Sstevel@tonic-gate * a ridiculous 9,999,999 unique observations. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate #define OBBUFNMSZ 20 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * serialize_observation 2987c478bd9Sstevel@tonic-gate * 2997c478bd9Sstevel@tonic-gate * Create a recoverable version of the current observation 3007c478bd9Sstevel@tonic-gate * (f->ecurrent). We keep a serialized version of each unique 3017c478bd9Sstevel@tonic-gate * observation in order that we may resume correctly the fme in the 3027c478bd9Sstevel@tonic-gate * correct state if eft or fmd crashes and we're restarted. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate static void 3057c478bd9Sstevel@tonic-gate serialize_observation(struct fme *fp, const char *cls, const struct ipath *ipp) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate size_t pkdlen; 3087c478bd9Sstevel@tonic-gate char tmpbuf[OBBUFNMSZ]; 3097c478bd9Sstevel@tonic-gate char *pkd = NULL; 3107c478bd9Sstevel@tonic-gate char *estr; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", fp->uniqobs); 3137c478bd9Sstevel@tonic-gate estr = ipath2str(cls, ipp); 3147c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, strlen(estr) + 1); 3157c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)estr, 3167c478bd9Sstevel@tonic-gate strlen(estr) + 1); 3177c478bd9Sstevel@tonic-gate FREE(estr); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate if (fp->ecurrent != NULL && fp->ecurrent->nvp != NULL) { 3207c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, 3217c478bd9Sstevel@tonic-gate OBBUFNMSZ, "observed%d.nvp", fp->uniqobs); 3227c478bd9Sstevel@tonic-gate if (nvlist_xpack(fp->ecurrent->nvp, 3237c478bd9Sstevel@tonic-gate &pkd, &pkdlen, NV_ENCODE_XDR, &Eft_nv_hdl) != 0) 3247c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "pack of observed nvl failed"); 3257c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, tmpbuf, pkdlen); 3267c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, tmpbuf, (void *)pkd, pkdlen); 3277c478bd9Sstevel@tonic-gate FREE(pkd); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate fp->uniqobs++; 3317c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 3327c478bd9Sstevel@tonic-gate sizeof (fp->uniqobs)); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * init_fme_bufs -- We keep several bits of state about an fme for 3377c478bd9Sstevel@tonic-gate * use if eft or fmd crashes and we're restarted. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate static void 3407c478bd9Sstevel@tonic-gate init_fme_bufs(struct fme *fp) 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate size_t cfglen = fp->cfgdata->nextfree - fp->cfgdata->begin; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_CFGLEN, sizeof (cfglen)); 3457c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_CFGLEN, (void *)&cfglen, 3467c478bd9Sstevel@tonic-gate sizeof (cfglen)); 3477c478bd9Sstevel@tonic-gate if (cfglen != 0) { 3487c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_CFG, cfglen); 3497c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_CFG, 3507c478bd9Sstevel@tonic-gate fp->cfgdata->begin, cfglen); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_PULL, sizeof (fp->pull)); 3547c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_PULL, (void *)&fp->pull, 3557c478bd9Sstevel@tonic-gate sizeof (fp->pull)); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_ID, sizeof (fp->id)); 3587c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_ID, (void *)&fp->id, 3597c478bd9Sstevel@tonic-gate sizeof (fp->id)); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_NOBS, sizeof (fp->uniqobs)); 3627c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_NOBS, (void *)&fp->uniqobs, 3637c478bd9Sstevel@tonic-gate sizeof (fp->uniqobs)); 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate fmd_buf_create(fp->hdl, fp->fmcase, WOBUF_POSTD, 3667c478bd9Sstevel@tonic-gate sizeof (fp->posted_suspects)); 3677c478bd9Sstevel@tonic-gate fmd_buf_write(fp->hdl, fp->fmcase, WOBUF_POSTD, 3687c478bd9Sstevel@tonic-gate (void *)&fp->posted_suspects, sizeof (fp->posted_suspects)); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate static void 3727c478bd9Sstevel@tonic-gate destroy_fme_bufs(struct fme *fp) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate char tmpbuf[OBBUFNMSZ]; 3757c478bd9Sstevel@tonic-gate int o; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFGLEN); 3787c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_CFG); 3797c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_PULL); 3807c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_ID); 3817c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_POSTD); 3827c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, WOBUF_NOBS); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate for (o = 0; o < fp->uniqobs; o++) { 3857c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", o); 3867c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 3877c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", o); 3887c478bd9Sstevel@tonic-gate fmd_buf_destroy(fp->hdl, fp->fmcase, tmpbuf); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * reconstitute_observations -- convert a case's serialized observations 3947c478bd9Sstevel@tonic-gate * back into struct events. Returns zero if all observations are 3957c478bd9Sstevel@tonic-gate * successfully reconstituted. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate static int 3987c478bd9Sstevel@tonic-gate reconstitute_observations(struct fme *fmep) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate struct event *ep; 4017c478bd9Sstevel@tonic-gate struct node *epnamenp = NULL; 4027c478bd9Sstevel@tonic-gate size_t pkdlen; 4037c478bd9Sstevel@tonic-gate char *pkd = NULL; 4047c478bd9Sstevel@tonic-gate char *tmpbuf = alloca(OBBUFNMSZ); 4057c478bd9Sstevel@tonic-gate char *sepptr; 4067c478bd9Sstevel@tonic-gate char *estr; 4077c478bd9Sstevel@tonic-gate int ocnt; 4087c478bd9Sstevel@tonic-gate int elen; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate for (ocnt = 0; ocnt < fmep->uniqobs; ocnt++) { 4117c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d", ocnt); 4127c478bd9Sstevel@tonic-gate elen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 4137c478bd9Sstevel@tonic-gate if (elen == 0) { 4147c478bd9Sstevel@tonic-gate out(O_ALTFP, 4157c478bd9Sstevel@tonic-gate "reconstitute_observation: no %s buffer found.", 4167c478bd9Sstevel@tonic-gate tmpbuf); 4177c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGOBS; 4187c478bd9Sstevel@tonic-gate break; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate estr = MALLOC(elen); 4227c478bd9Sstevel@tonic-gate fmd_buf_read(fmep->hdl, fmep->fmcase, tmpbuf, estr, elen); 4237c478bd9Sstevel@tonic-gate sepptr = strchr(estr, '@'); 4247c478bd9Sstevel@tonic-gate if (sepptr == NULL) { 4257c478bd9Sstevel@tonic-gate out(O_ALTFP, 4267c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 4277c478bd9Sstevel@tonic-gate "missing @ separator in %s.", 4287c478bd9Sstevel@tonic-gate tmpbuf, estr); 4297c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGPATH; 4307c478bd9Sstevel@tonic-gate FREE(estr); 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate *sepptr = '\0'; 4357c478bd9Sstevel@tonic-gate if ((epnamenp = pathstring2epnamenp(sepptr + 1)) == NULL) { 4367c478bd9Sstevel@tonic-gate out(O_ALTFP, 4377c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 4387c478bd9Sstevel@tonic-gate "trouble converting path string \"%s\" " 4397c478bd9Sstevel@tonic-gate "to internal representation.", 4407c478bd9Sstevel@tonic-gate tmpbuf, sepptr + 1); 4417c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGPATH; 4427c478bd9Sstevel@tonic-gate FREE(estr); 4437c478bd9Sstevel@tonic-gate break; 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* construct the event */ 4477c478bd9Sstevel@tonic-gate ep = itree_lookup(fmep->eventtree, 4487c478bd9Sstevel@tonic-gate stable(estr), ipath(epnamenp)); 4497c478bd9Sstevel@tonic-gate if (ep == NULL) { 4507c478bd9Sstevel@tonic-gate out(O_ALTFP, 4517c478bd9Sstevel@tonic-gate "reconstitute_observation: %s: " 4527c478bd9Sstevel@tonic-gate "lookup of \"%s\" in itree failed.", 4537c478bd9Sstevel@tonic-gate tmpbuf, ipath2str(estr, ipath(epnamenp))); 4547c478bd9Sstevel@tonic-gate Undiag_reason = UD_BADOBS; 4557c478bd9Sstevel@tonic-gate tree_free(epnamenp); 4567c478bd9Sstevel@tonic-gate FREE(estr); 4577c478bd9Sstevel@tonic-gate break; 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate tree_free(epnamenp); 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * We may or may not have a saved nvlist for the observation 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate (void) snprintf(tmpbuf, OBBUFNMSZ, "observed%d.nvp", ocnt); 4657c478bd9Sstevel@tonic-gate pkdlen = fmd_buf_size(fmep->hdl, fmep->fmcase, tmpbuf); 4667c478bd9Sstevel@tonic-gate if (pkdlen != 0) { 4677c478bd9Sstevel@tonic-gate pkd = MALLOC(pkdlen); 4687c478bd9Sstevel@tonic-gate fmd_buf_read(fmep->hdl, 4697c478bd9Sstevel@tonic-gate fmep->fmcase, tmpbuf, pkd, pkdlen); 4707c478bd9Sstevel@tonic-gate if (nvlist_xunpack(pkd, 4717c478bd9Sstevel@tonic-gate pkdlen, &ep->nvp, &Eft_nv_hdl) != 0) 4727c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "pack of observed nvl failed"); 4737c478bd9Sstevel@tonic-gate FREE(pkd); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if (ocnt == 0) 4777c478bd9Sstevel@tonic-gate fmep->e0 = ep; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate FREE(estr); 4807c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 4817c478bd9Sstevel@tonic-gate ep->count++; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 4847c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 4857c478bd9Sstevel@tonic-gate fmep->observations = ep; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if (ocnt == fmep->uniqobs) { 4897c478bd9Sstevel@tonic-gate (void) fme_ready(fmep); 4907c478bd9Sstevel@tonic-gate return (0); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate return (1); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * restart_fme -- called during eft initialization. Reconstitutes 4987c478bd9Sstevel@tonic-gate * an in-progress fme. 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate void 5017c478bd9Sstevel@tonic-gate fme_restart(fmd_hdl_t *hdl, fmd_case_t *inprogress) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate nvlist_t *defect; 5047c478bd9Sstevel@tonic-gate struct case_list *bad; 5057c478bd9Sstevel@tonic-gate struct fme *fmep; 5067c478bd9Sstevel@tonic-gate struct cfgdata *cfgdata = NULL; 5077c478bd9Sstevel@tonic-gate size_t rawsz; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate fmep = alloc_fme(); 5107c478bd9Sstevel@tonic-gate fmep->fmcase = inprogress; 5117c478bd9Sstevel@tonic-gate fmep->hdl = hdl; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_CFGLEN) != sizeof (size_t)) { 5147c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: No config data"); 5157c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGINFO; 5167c478bd9Sstevel@tonic-gate goto badcase; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_CFGLEN, (void *)&rawsz, 5197c478bd9Sstevel@tonic-gate sizeof (size_t)); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if ((fmep->e0r = fmd_case_getprincipal(hdl, inprogress)) == NULL) { 5227c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: No event zero"); 5237c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGZERO; 5247c478bd9Sstevel@tonic-gate goto badcase; 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate cfgdata = MALLOC(sizeof (struct cfgdata)); 5287c478bd9Sstevel@tonic-gate cfgdata->cooked = NULL; 5297c478bd9Sstevel@tonic-gate cfgdata->devcache = NULL; 5307c478bd9Sstevel@tonic-gate cfgdata->cpucache = NULL; 5317c478bd9Sstevel@tonic-gate cfgdata->refcnt = 1; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate if (rawsz > 0) { 5347c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_CFG) != rawsz) { 5357c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: Config data size mismatch"); 5367c478bd9Sstevel@tonic-gate Undiag_reason = UD_CFGMISMATCH; 5377c478bd9Sstevel@tonic-gate goto badcase; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate cfgdata->begin = MALLOC(rawsz); 5407c478bd9Sstevel@tonic-gate cfgdata->end = cfgdata->nextfree = cfgdata->begin + rawsz; 5417c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, 5427c478bd9Sstevel@tonic-gate inprogress, WOBUF_CFG, cfgdata->begin, rawsz); 5437c478bd9Sstevel@tonic-gate } else { 5447c478bd9Sstevel@tonic-gate cfgdata->begin = cfgdata->end = cfgdata->nextfree = NULL; 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate fmep->cfgdata = cfgdata; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate config_cook(cfgdata); 5497c478bd9Sstevel@tonic-gate if ((fmep->eventtree = itree_create(cfgdata->cooked)) == NULL) { 5507c478bd9Sstevel@tonic-gate /* case not properly saved or irretrievable */ 5517c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: NULL instance tree"); 5527c478bd9Sstevel@tonic-gate Undiag_reason = UD_INSTFAIL; 5537c478bd9Sstevel@tonic-gate goto badcase; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate itree_ptree(O_ALTFP|O_VERB2, fmep->eventtree); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_PULL) == 0) { 5597c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: no saved wait time"); 5607c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGINFO; 5617c478bd9Sstevel@tonic-gate goto badcase; 5627c478bd9Sstevel@tonic-gate } else { 5637c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_PULL, (void *)&fmep->pull, 5647c478bd9Sstevel@tonic-gate sizeof (fmep->pull)); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_POSTD) == 0) { 5687c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: no saved posted status"); 5697c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGINFO; 5707c478bd9Sstevel@tonic-gate goto badcase; 5717c478bd9Sstevel@tonic-gate } else { 5727c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_POSTD, 5737c478bd9Sstevel@tonic-gate (void *)&fmep->posted_suspects, 5747c478bd9Sstevel@tonic-gate sizeof (fmep->posted_suspects)); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_ID) == 0) { 5787c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: no saved id"); 5797c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGINFO; 5807c478bd9Sstevel@tonic-gate goto badcase; 5817c478bd9Sstevel@tonic-gate } else { 5827c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_ID, (void *)&fmep->id, 5837c478bd9Sstevel@tonic-gate sizeof (fmep->id)); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate if (Nextid <= fmep->id) 5867c478bd9Sstevel@tonic-gate Nextid = fmep->id + 1; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate if (fmd_buf_size(hdl, inprogress, WOBUF_NOBS) == 0) { 5897c478bd9Sstevel@tonic-gate out(O_ALTFP, "restart_fme: no count of observations"); 5907c478bd9Sstevel@tonic-gate Undiag_reason = UD_MISSINGINFO; 5917c478bd9Sstevel@tonic-gate goto badcase; 5927c478bd9Sstevel@tonic-gate } else { 5937c478bd9Sstevel@tonic-gate fmd_buf_read(hdl, inprogress, WOBUF_NOBS, 5947c478bd9Sstevel@tonic-gate (void *)&fmep->uniqobs, sizeof (fmep->uniqobs)); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate if (reconstitute_observations(fmep) != 0) 5987c478bd9Sstevel@tonic-gate goto badcase; 5997c478bd9Sstevel@tonic-gate 600*0cc1f05eSjrutt Open_fme_count++; 601*0cc1f05eSjrutt 6027c478bd9Sstevel@tonic-gate /* give the diagnosis algorithm a shot at the new FME state */ 6037c478bd9Sstevel@tonic-gate fme_eval(fmep, NULL); 6047c478bd9Sstevel@tonic-gate return; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate badcase: 6077c478bd9Sstevel@tonic-gate if (fmep->eventtree != NULL) 6087c478bd9Sstevel@tonic-gate itree_free(fmep->eventtree); 6097c478bd9Sstevel@tonic-gate config_free(cfgdata); 6107c478bd9Sstevel@tonic-gate destroy_fme_bufs(fmep); 6117c478bd9Sstevel@tonic-gate FREE(fmep); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Since we're unable to restart the case, add it to the undiagable 6157c478bd9Sstevel@tonic-gate * list and solve and close it as appropriate. 6167c478bd9Sstevel@tonic-gate */ 6177c478bd9Sstevel@tonic-gate bad = MALLOC(sizeof (struct case_list)); 6187c478bd9Sstevel@tonic-gate bad->next = NULL; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (Undiagablecaselist != NULL) 6217c478bd9Sstevel@tonic-gate bad->next = Undiagablecaselist; 6227c478bd9Sstevel@tonic-gate Undiagablecaselist = bad; 6237c478bd9Sstevel@tonic-gate bad->fmcase = inprogress; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate out(O_ALTFP, "[case %s (unable to restart), ", 6267c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, bad->fmcase)); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate if (fmd_case_solved(hdl, bad->fmcase)) { 6297c478bd9Sstevel@tonic-gate out(O_ALTFP, "already solved, "); 6307c478bd9Sstevel@tonic-gate } else { 6317c478bd9Sstevel@tonic-gate out(O_ALTFP, "solving, "); 6327c478bd9Sstevel@tonic-gate defect = fmd_nvl_create_fault(hdl, UNDIAGNOSABLE_DEFECT, 100, 6337c478bd9Sstevel@tonic-gate NULL, NULL, NULL); 6347c478bd9Sstevel@tonic-gate if (Undiag_reason != NULL) 6357c478bd9Sstevel@tonic-gate (void) nvlist_add_string(defect, 6367c478bd9Sstevel@tonic-gate UNDIAG_REASON, Undiag_reason); 6377c478bd9Sstevel@tonic-gate fmd_case_add_suspect(hdl, bad->fmcase, defect); 6387c478bd9Sstevel@tonic-gate fmd_case_solve(hdl, bad->fmcase); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (fmd_case_closed(hdl, bad->fmcase)) { 6427c478bd9Sstevel@tonic-gate out(O_ALTFP, "already closed ]"); 6437c478bd9Sstevel@tonic-gate } else { 6447c478bd9Sstevel@tonic-gate out(O_ALTFP, "closing ]"); 6457c478bd9Sstevel@tonic-gate fmd_case_close(hdl, bad->fmcase); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate void 6507c478bd9Sstevel@tonic-gate destroy_fme(struct fme *f) 6517c478bd9Sstevel@tonic-gate { 6527c478bd9Sstevel@tonic-gate stats_delete(f->Rcount); 6537c478bd9Sstevel@tonic-gate stats_delete(f->Hcallcount); 6547c478bd9Sstevel@tonic-gate stats_delete(f->Rcallcount); 6557c478bd9Sstevel@tonic-gate stats_delete(f->Ccallcount); 6567c478bd9Sstevel@tonic-gate stats_delete(f->Ecallcount); 6577c478bd9Sstevel@tonic-gate stats_delete(f->Tcallcount); 6587c478bd9Sstevel@tonic-gate stats_delete(f->Marrowcount); 6597c478bd9Sstevel@tonic-gate stats_delete(f->diags); 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate itree_free(f->eventtree); 6627c478bd9Sstevel@tonic-gate config_free(f->cfgdata); 6637c478bd9Sstevel@tonic-gate FREE(f); 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate static const char * 6677c478bd9Sstevel@tonic-gate fme_state2str(enum fme_state s) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate switch (s) { 6707c478bd9Sstevel@tonic-gate case FME_NOTHING: return ("NOTHING"); 6717c478bd9Sstevel@tonic-gate case FME_WAIT: return ("WAIT"); 6727c478bd9Sstevel@tonic-gate case FME_CREDIBLE: return ("CREDIBLE"); 6737c478bd9Sstevel@tonic-gate case FME_DISPROVED: return ("DISPROVED"); 6747c478bd9Sstevel@tonic-gate default: return ("UNKNOWN"); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate static int 6797c478bd9Sstevel@tonic-gate is_problem(enum nametype t) 6807c478bd9Sstevel@tonic-gate { 6817c478bd9Sstevel@tonic-gate return (t == N_FAULT || t == N_DEFECT || t == N_UPSET); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate static int 6857c478bd9Sstevel@tonic-gate is_fault(enum nametype t) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate return (t == N_FAULT); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate static int 6917c478bd9Sstevel@tonic-gate is_defect(enum nametype t) 6927c478bd9Sstevel@tonic-gate { 6937c478bd9Sstevel@tonic-gate return (t == N_DEFECT); 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate static int 6977c478bd9Sstevel@tonic-gate is_upset(enum nametype t) 6987c478bd9Sstevel@tonic-gate { 6997c478bd9Sstevel@tonic-gate return (t == N_UPSET); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7037c478bd9Sstevel@tonic-gate static void 7047c478bd9Sstevel@tonic-gate clear_causes_tested(struct event *lhs, struct event *ep, void *arg) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate struct bubble *bp; 7077c478bd9Sstevel@tonic-gate struct arrowlist *ap; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 7107c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 7117c478bd9Sstevel@tonic-gate if (bp->t != B_FROM) 7127c478bd9Sstevel@tonic-gate continue; 7137c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 7147c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) 7157c478bd9Sstevel@tonic-gate ap->arrowp->causes_tested = 0; 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * call this function with initcode set to 0 to initialize cycle tracking 7217c478bd9Sstevel@tonic-gate */ 7227c478bd9Sstevel@tonic-gate static void 7237c478bd9Sstevel@tonic-gate initialize_cycles(struct fme *fmep) 7247c478bd9Sstevel@tonic-gate { 7257c478bd9Sstevel@tonic-gate lut_walk(fmep->eventtree, (lut_cb)clear_causes_tested, NULL); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate static void 7297c478bd9Sstevel@tonic-gate fme_print(int flags, struct fme *fmep) 7307c478bd9Sstevel@tonic-gate { 7317c478bd9Sstevel@tonic-gate struct event *ep; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate out(flags, "Fault Management Exercise %d", fmep->id); 7347c478bd9Sstevel@tonic-gate out(flags, "\t State: %s", fme_state2str(fmep->state)); 7357c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t Start time: "); 7367c478bd9Sstevel@tonic-gate ptree_timeval(flags|O_NONL, &fmep->ull); 7377c478bd9Sstevel@tonic-gate out(flags, NULL); 7387c478bd9Sstevel@tonic-gate if (fmep->wull) { 7397c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t Wait time: "); 7407c478bd9Sstevel@tonic-gate ptree_timeval(flags|O_NONL, &fmep->wull); 7417c478bd9Sstevel@tonic-gate out(flags, NULL); 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\t E0: "); 7447c478bd9Sstevel@tonic-gate if (fmep->e0) 7457c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, fmep->e0); 7467c478bd9Sstevel@tonic-gate else 7477c478bd9Sstevel@tonic-gate out(flags|O_NONL, "NULL"); 7487c478bd9Sstevel@tonic-gate out(flags, NULL); 7497c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\tObservations:"); 7507c478bd9Sstevel@tonic-gate for (ep = fmep->observations; ep; ep = ep->observations) { 7517c478bd9Sstevel@tonic-gate out(flags|O_NONL, " "); 7527c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, ep); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate out(flags, NULL); 7557c478bd9Sstevel@tonic-gate out(flags|O_NONL, "\tSuspect list:"); 7567c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 7577c478bd9Sstevel@tonic-gate out(flags|O_NONL, " "); 7587c478bd9Sstevel@tonic-gate itree_pevent_brief(flags|O_NONL, ep); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate out(flags, NULL); 7617c478bd9Sstevel@tonic-gate out(flags|O_VERB2, "\t Tree:"); 7627c478bd9Sstevel@tonic-gate itree_ptree(flags|O_VERB2, fmep->eventtree); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate static struct node * 7667c478bd9Sstevel@tonic-gate pathstring2epnamenp(char *path) 7677c478bd9Sstevel@tonic-gate { 7687c478bd9Sstevel@tonic-gate char *sep = "/"; 7697c478bd9Sstevel@tonic-gate struct node *ret; 7707c478bd9Sstevel@tonic-gate char *ptr; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate if ((ptr = strtok(path, sep)) == NULL) 7737c478bd9Sstevel@tonic-gate out(O_DIE, "pathstring2epnamenp: invalid empty class"); 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate ret = tree_iname(stable(ptr), NULL, 0); 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate while ((ptr = strtok(NULL, sep)) != NULL) 7787c478bd9Sstevel@tonic-gate ret = tree_name_append(ret, 7797c478bd9Sstevel@tonic-gate tree_iname(stable(ptr), NULL, 0)); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate return (ret); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * for a given upset sp, increment the corresponding SERD engine. if the 7867c478bd9Sstevel@tonic-gate * SERD engine trips, return the ename and ipp of the resulting ereport. 7877c478bd9Sstevel@tonic-gate * returns true if engine tripped and *enamep and *ippp were filled in. 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate static int 7903e8d8e18Sdb serd_eval(fmd_hdl_t *hdl, fmd_event_t *ffep, fmd_case_t *fmcase, 7913e8d8e18Sdb struct event *sp, const char **enamep, const struct ipath **ippp) 7927c478bd9Sstevel@tonic-gate { 7937c478bd9Sstevel@tonic-gate struct node *serdinst; 7947c478bd9Sstevel@tonic-gate char *serdname; 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate ASSERT(sp->t == N_UPSET); 7977c478bd9Sstevel@tonic-gate ASSERT(ffep != NULL); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* 8007c478bd9Sstevel@tonic-gate * obtain instanced SERD engine from the upset sp. from this 8017c478bd9Sstevel@tonic-gate * derive serdname, the string used to identify the SERD engine. 8027c478bd9Sstevel@tonic-gate */ 8037c478bd9Sstevel@tonic-gate serdinst = eventprop_lookup(sp, L_engine); 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate if (serdinst == NULL) 8067c478bd9Sstevel@tonic-gate return (NULL); 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate serdname = ipath2str(serdinst->u.stmt.np->u.event.ename->u.name.s, 8097c478bd9Sstevel@tonic-gate ipath(serdinst->u.stmt.np->u.event.epname)); 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate if (!fmd_serd_exists(hdl, serdname)) { 8127c478bd9Sstevel@tonic-gate struct node *nN, *nT; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* no SERD engine yet, so create it */ 8157c478bd9Sstevel@tonic-gate nN = lut_lookup(serdinst->u.stmt.lutp, (void *)L_N, NULL); 8167c478bd9Sstevel@tonic-gate nT = lut_lookup(serdinst->u.stmt.lutp, (void *)L_T, NULL); 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate ASSERT(nN->t == T_NUM); 8197c478bd9Sstevel@tonic-gate ASSERT(nT->t == T_TIMEVAL); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate fmd_serd_create(hdl, serdname, (uint_t)nN->u.ull, 8227c478bd9Sstevel@tonic-gate (hrtime_t)nT->u.ull); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate /* 8277c478bd9Sstevel@tonic-gate * increment SERD engine. if engine fires, reset serd 8287c478bd9Sstevel@tonic-gate * engine and return trip_strcode 8297c478bd9Sstevel@tonic-gate */ 8307c478bd9Sstevel@tonic-gate if (fmd_serd_record(hdl, serdname, ffep)) { 8317c478bd9Sstevel@tonic-gate struct node *tripinst = lut_lookup(serdinst->u.stmt.lutp, 8327c478bd9Sstevel@tonic-gate (void *)L_trip, NULL); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate ASSERT(tripinst != NULL); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate *enamep = tripinst->u.event.ename->u.name.s; 8377c478bd9Sstevel@tonic-gate *ippp = ipath(tripinst->u.event.epname); 8387c478bd9Sstevel@tonic-gate 8393e8d8e18Sdb fmd_case_add_serd(hdl, fmcase, serdname); 8407c478bd9Sstevel@tonic-gate fmd_serd_reset(hdl, serdname); 8417c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "[engine fired: %s, sending: ", serdname); 8427c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, *enamep, *ippp); 8437c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate FREE(serdname); 8467c478bd9Sstevel@tonic-gate return (1); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate FREE(serdname); 8507c478bd9Sstevel@tonic-gate return (0); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate /* 8547c478bd9Sstevel@tonic-gate * search a suspect list for upsets. feed each upset to serd_eval() and 8557c478bd9Sstevel@tonic-gate * build up tripped[], an array of ereports produced by the firing of 8567c478bd9Sstevel@tonic-gate * any SERD engines. then feed each ereport back into 8577c478bd9Sstevel@tonic-gate * fme_receive_report(). 8587c478bd9Sstevel@tonic-gate * 8597c478bd9Sstevel@tonic-gate * returns ntrip, the number of these ereports produced. 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate static int 8627c478bd9Sstevel@tonic-gate upsets_eval(struct fme *fmep, fmd_event_t *ffep) 8637c478bd9Sstevel@tonic-gate { 8647c478bd9Sstevel@tonic-gate /* we build an array of tripped ereports that we send ourselves */ 8657c478bd9Sstevel@tonic-gate struct { 8667c478bd9Sstevel@tonic-gate const char *ename; 8677c478bd9Sstevel@tonic-gate const struct ipath *ipp; 8687c478bd9Sstevel@tonic-gate } *tripped; 8697c478bd9Sstevel@tonic-gate struct event *sp; 8707c478bd9Sstevel@tonic-gate int ntrip, nupset, i; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * we avoid recursion by calling fme_receive_report() at the end of 8747c478bd9Sstevel@tonic-gate * this function with a NULL ffep 8757c478bd9Sstevel@tonic-gate */ 8767c478bd9Sstevel@tonic-gate if (ffep == NULL) 8777c478bd9Sstevel@tonic-gate return (0); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate /* 8807c478bd9Sstevel@tonic-gate * count the number of upsets to determine the upper limit on 8817c478bd9Sstevel@tonic-gate * expected trip ereport strings. remember that one upset can 8827c478bd9Sstevel@tonic-gate * lead to at most one ereport. 8837c478bd9Sstevel@tonic-gate */ 8847c478bd9Sstevel@tonic-gate nupset = 0; 8857c478bd9Sstevel@tonic-gate for (sp = fmep->suspects; sp; sp = sp->suspects) { 8867c478bd9Sstevel@tonic-gate if (sp->t == N_UPSET) 8877c478bd9Sstevel@tonic-gate nupset++; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate if (nupset == 0) 8917c478bd9Sstevel@tonic-gate return (0); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * get to this point if we have upsets and expect some trip 8957c478bd9Sstevel@tonic-gate * ereports 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate tripped = alloca(sizeof (*tripped) * nupset); 8987c478bd9Sstevel@tonic-gate bzero((void *)tripped, sizeof (*tripped) * nupset); 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate ntrip = 0; 9017c478bd9Sstevel@tonic-gate for (sp = fmep->suspects; sp; sp = sp->suspects) 9023e8d8e18Sdb if (sp->t == N_UPSET && 9033e8d8e18Sdb serd_eval(fmep->hdl, ffep, fmep->fmcase, sp, 9043e8d8e18Sdb &tripped[ntrip].ename, &tripped[ntrip].ipp)) 9057c478bd9Sstevel@tonic-gate ntrip++; 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate for (i = 0; i < ntrip; i++) 9087c478bd9Sstevel@tonic-gate fme_receive_report(fmep->hdl, NULL, 9097c478bd9Sstevel@tonic-gate tripped[i].ename, tripped[i].ipp, NULL); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate return (ntrip); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate /* 9157c478bd9Sstevel@tonic-gate * fme_receive_external_report -- call when an external ereport comes in 9167c478bd9Sstevel@tonic-gate * 9177c478bd9Sstevel@tonic-gate * this routine just converts the relevant information from the ereport 9187c478bd9Sstevel@tonic-gate * into a format used internally and passes it on to fme_receive_report(). 9197c478bd9Sstevel@tonic-gate */ 9207c478bd9Sstevel@tonic-gate void 9217c478bd9Sstevel@tonic-gate fme_receive_external_report(fmd_hdl_t *hdl, fmd_event_t *ffep, nvlist_t *nvl, 9227c478bd9Sstevel@tonic-gate const char *eventstring) 9237c478bd9Sstevel@tonic-gate { 9247c478bd9Sstevel@tonic-gate struct node *epnamenp = platform_getpath(nvl); 9257c478bd9Sstevel@tonic-gate const struct ipath *ipp; 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * XFILE: If we ended up without a path, it's an X-file. 9297c478bd9Sstevel@tonic-gate * For now, use our undiagnosable interface. 9307c478bd9Sstevel@tonic-gate */ 9317c478bd9Sstevel@tonic-gate if (epnamenp == NULL) { 9327c478bd9Sstevel@tonic-gate out(O_ALTFP, "XFILE: Unable to get path from ereport"); 9337c478bd9Sstevel@tonic-gate Undiag_reason = UD_NOPATH; 9347c478bd9Sstevel@tonic-gate publish_undiagnosable(hdl, ffep); 9357c478bd9Sstevel@tonic-gate return; 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate ipp = ipath(epnamenp); 9397c478bd9Sstevel@tonic-gate tree_free(epnamenp); 9407c478bd9Sstevel@tonic-gate fme_receive_report(hdl, ffep, stable(eventstring), ipp, nvl); 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate static void 9447c478bd9Sstevel@tonic-gate fme_receive_report(fmd_hdl_t *hdl, fmd_event_t *ffep, 9457c478bd9Sstevel@tonic-gate const char *eventstring, const struct ipath *ipp, nvlist_t *nvl) 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate struct event *ep; 9487c478bd9Sstevel@tonic-gate struct fme *fmep = NULL; 949*0cc1f05eSjrutt struct fme *ofmep = NULL; 950*0cc1f05eSjrutt struct fme *cfmep, *svfmep; 9517c478bd9Sstevel@tonic-gate int matched = 0; 952*0cc1f05eSjrutt nvlist_t *defect; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "fme_receive_report: "); 9557c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 9567c478bd9Sstevel@tonic-gate out(O_ALTFP|O_STAMP, NULL); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* decide which FME it goes to */ 9597c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) { 9607c478bd9Sstevel@tonic-gate int prev_verbose; 9617c478bd9Sstevel@tonic-gate unsigned long long my_delay = TIMEVAL_EVENTUALLY; 9627c478bd9Sstevel@tonic-gate enum fme_state state; 9637c478bd9Sstevel@tonic-gate 964*0cc1f05eSjrutt if (fmep->overflow) { 965*0cc1f05eSjrutt if (!(fmd_case_closed(fmep->hdl, fmep->fmcase))) 966*0cc1f05eSjrutt ofmep = fmep; 967*0cc1f05eSjrutt 968*0cc1f05eSjrutt continue; 969*0cc1f05eSjrutt } 970*0cc1f05eSjrutt 9717c478bd9Sstevel@tonic-gate /* look up event in event tree for this FME */ 9727c478bd9Sstevel@tonic-gate if ((ep = itree_lookup(fmep->eventtree, 9737c478bd9Sstevel@tonic-gate eventstring, ipp)) == NULL) 9747c478bd9Sstevel@tonic-gate continue; 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate /* note observation */ 9777c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 9787c478bd9Sstevel@tonic-gate if (ep->count++ == 0) { 9797c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 9807c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 9817c478bd9Sstevel@tonic-gate fmep->observations = ep; 9827c478bd9Sstevel@tonic-gate ep->nvp = evnv_dupnvl(nvl); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate /* tell hypothesise() not to mess with suspect list */ 9867c478bd9Sstevel@tonic-gate fmep->peek = 1; 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate /* don't want this to be verbose (unless Debug is set) */ 9897c478bd9Sstevel@tonic-gate prev_verbose = Verbose; 9907c478bd9Sstevel@tonic-gate if (Debug == 0) 9917c478bd9Sstevel@tonic-gate Verbose = 0; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate initialize_cycles(fmep); 9947c478bd9Sstevel@tonic-gate state = hypothesise(fmep, fmep->e0, fmep->ull, &my_delay, NULL); 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate fmep->peek = 0; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate /* put verbose flag back */ 9997c478bd9Sstevel@tonic-gate Verbose = prev_verbose; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate if (state != FME_DISPROVED) { 10027c478bd9Sstevel@tonic-gate /* found an FME that explains the ereport */ 10037c478bd9Sstevel@tonic-gate matched++; 10047c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 10057c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 10067c478bd9Sstevel@tonic-gate out(O_ALTFP, " explained by FME%d]", fmep->id); 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate if (ep->count == 1) 10097c478bd9Sstevel@tonic-gate serialize_observation(fmep, eventstring, ipp); 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate if (ffep) 10127c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcount); 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate /* re-eval FME */ 10177c478bd9Sstevel@tonic-gate fme_eval(fmep, ffep); 10187c478bd9Sstevel@tonic-gate } else { 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* not a match, undo noting of observation */ 10217c478bd9Sstevel@tonic-gate fmep->ecurrent = NULL; 10227c478bd9Sstevel@tonic-gate if (--ep->count == 0) { 10237c478bd9Sstevel@tonic-gate /* unlink it from observations */ 10247c478bd9Sstevel@tonic-gate fmep->observations = ep->observations; 10257c478bd9Sstevel@tonic-gate ep->observations = NULL; 10267c478bd9Sstevel@tonic-gate nvlist_free(ep->nvp); 10277c478bd9Sstevel@tonic-gate ep->nvp = NULL; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate if (matched) 10337c478bd9Sstevel@tonic-gate return; /* explained by at least one existing FME */ 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate /* clean up closed fmes */ 1036*0cc1f05eSjrutt cfmep = ClosedFMEs; 1037*0cc1f05eSjrutt while (cfmep != NULL) { 1038*0cc1f05eSjrutt svfmep = cfmep->next; 1039*0cc1f05eSjrutt destroy_fme(cfmep); 1040*0cc1f05eSjrutt cfmep = svfmep; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate ClosedFMEs = NULL; 10437c478bd9Sstevel@tonic-gate 1044*0cc1f05eSjrutt if (ofmep) { 1045*0cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 1046*0cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1047*0cc1f05eSjrutt out(O_ALTFP, " ADDING TO OVERFLOW FME]"); 1048*0cc1f05eSjrutt if (ffep) 1049*0cc1f05eSjrutt fmd_case_add_ereport(hdl, ofmep->fmcase, ffep); 1050*0cc1f05eSjrutt 1051*0cc1f05eSjrutt return; 1052*0cc1f05eSjrutt 1053*0cc1f05eSjrutt } else if (Max_fme && (Open_fme_count >= Max_fme)) { 1054*0cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 1055*0cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1056*0cc1f05eSjrutt out(O_ALTFP, " MAX OPEN FME REACHED]"); 1057*0cc1f05eSjrutt /* Create overflow fme */ 1058*0cc1f05eSjrutt if ((fmep = newfme(eventstring, ipp)) == NULL) { 1059*0cc1f05eSjrutt out(O_ALTFP|O_NONL, "["); 1060*0cc1f05eSjrutt ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 1061*0cc1f05eSjrutt out(O_ALTFP, " CANNOT OPEN OVERFLOW FME]"); 1062*0cc1f05eSjrutt publish_undiagnosable(hdl, ffep); 1063*0cc1f05eSjrutt return; 1064*0cc1f05eSjrutt } 1065*0cc1f05eSjrutt 1066*0cc1f05eSjrutt Open_fme_count++; 1067*0cc1f05eSjrutt 1068*0cc1f05eSjrutt fmep->fmcase = fmd_case_open(hdl, NULL); 1069*0cc1f05eSjrutt fmep->hdl = hdl; 1070*0cc1f05eSjrutt init_fme_bufs(fmep); 1071*0cc1f05eSjrutt fmep->overflow = B_TRUE; 1072*0cc1f05eSjrutt 1073*0cc1f05eSjrutt if (ffep) 1074*0cc1f05eSjrutt fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 1075*0cc1f05eSjrutt 1076*0cc1f05eSjrutt defect = fmd_nvl_create_fault(hdl, UNDIAGNOSABLE_DEFECT, 100, 1077*0cc1f05eSjrutt NULL, NULL, NULL); 1078*0cc1f05eSjrutt (void) nvlist_add_string(defect, UNDIAG_REASON, UD_MAXFME); 1079*0cc1f05eSjrutt fmd_case_add_suspect(hdl, fmep->fmcase, defect); 1080*0cc1f05eSjrutt fmd_case_solve(hdl, fmep->fmcase); 1081*0cc1f05eSjrutt return; 1082*0cc1f05eSjrutt } 1083*0cc1f05eSjrutt 10847c478bd9Sstevel@tonic-gate /* start a new FME */ 10857c478bd9Sstevel@tonic-gate if ((fmep = newfme(eventstring, ipp)) == NULL) { 10867c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 10877c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 10887c478bd9Sstevel@tonic-gate out(O_ALTFP, " CANNOT DIAGNOSE]"); 10897c478bd9Sstevel@tonic-gate publish_undiagnosable(hdl, ffep); 10907c478bd9Sstevel@tonic-gate return; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 1093*0cc1f05eSjrutt Open_fme_count++; 1094*0cc1f05eSjrutt 10957c478bd9Sstevel@tonic-gate /* open a case */ 10967c478bd9Sstevel@tonic-gate fmep->fmcase = fmd_case_open(hdl, NULL); 10977c478bd9Sstevel@tonic-gate fmep->hdl = hdl; 10987c478bd9Sstevel@tonic-gate init_fme_bufs(fmep); 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 11017c478bd9Sstevel@tonic-gate ipath_print(O_ALTFP|O_NONL, eventstring, ipp); 11027c478bd9Sstevel@tonic-gate out(O_ALTFP, " created FME%d, case %s]", fmep->id, 11037c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, fmep->fmcase)); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate ep = fmep->e0; 11067c478bd9Sstevel@tonic-gate ASSERT(ep != NULL); 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate /* note observation */ 11097c478bd9Sstevel@tonic-gate fmep->ecurrent = ep; 11107c478bd9Sstevel@tonic-gate if (ep->count++ == 0) { 11117c478bd9Sstevel@tonic-gate /* link it into list of observations seen */ 11127c478bd9Sstevel@tonic-gate ep->observations = fmep->observations; 11137c478bd9Sstevel@tonic-gate fmep->observations = ep; 11147c478bd9Sstevel@tonic-gate ep->nvp = evnv_dupnvl(nvl); 11157c478bd9Sstevel@tonic-gate serialize_observation(fmep, eventstring, ipp); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcount); 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate if (ffep) { 11217c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, fmep->fmcase, ffep); 11227c478bd9Sstevel@tonic-gate fmd_case_setprincipal(hdl, fmep->fmcase, ffep); 11237c478bd9Sstevel@tonic-gate fmep->e0r = ffep; 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate /* give the diagnosis algorithm a shot at the new FME state */ 11277c478bd9Sstevel@tonic-gate fme_eval(fmep, ffep); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate void 11317c478bd9Sstevel@tonic-gate fme_status(int flags) 11327c478bd9Sstevel@tonic-gate { 11337c478bd9Sstevel@tonic-gate struct fme *fmep; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate if (FMElist == NULL) { 11367c478bd9Sstevel@tonic-gate out(flags, "No fault management exercises underway."); 11377c478bd9Sstevel@tonic-gate return; 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) 11417c478bd9Sstevel@tonic-gate fme_print(flags, fmep); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * "indent" routines used mostly for nicely formatted debug output, but also 11467c478bd9Sstevel@tonic-gate * for sanity checking for infinite recursion bugs. 11477c478bd9Sstevel@tonic-gate */ 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate #define MAX_INDENT 1024 11507c478bd9Sstevel@tonic-gate static const char *indent_s[MAX_INDENT]; 11517c478bd9Sstevel@tonic-gate static int current_indent; 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate static void 11547c478bd9Sstevel@tonic-gate indent_push(const char *s) 11557c478bd9Sstevel@tonic-gate { 11567c478bd9Sstevel@tonic-gate if (current_indent < MAX_INDENT) 11577c478bd9Sstevel@tonic-gate indent_s[current_indent++] = s; 11587c478bd9Sstevel@tonic-gate else 11597c478bd9Sstevel@tonic-gate out(O_DIE, "unexpected recursion depth (%d)", current_indent); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate static void 11637c478bd9Sstevel@tonic-gate indent_set(const char *s) 11647c478bd9Sstevel@tonic-gate { 11657c478bd9Sstevel@tonic-gate current_indent = 0; 11667c478bd9Sstevel@tonic-gate indent_push(s); 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate static void 11707c478bd9Sstevel@tonic-gate indent_pop(void) 11717c478bd9Sstevel@tonic-gate { 11727c478bd9Sstevel@tonic-gate if (current_indent > 0) 11737c478bd9Sstevel@tonic-gate current_indent--; 11747c478bd9Sstevel@tonic-gate else 11757c478bd9Sstevel@tonic-gate out(O_DIE, "recursion underflow"); 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate static void 11797c478bd9Sstevel@tonic-gate indent(void) 11807c478bd9Sstevel@tonic-gate { 11817c478bd9Sstevel@tonic-gate int i; 11827c478bd9Sstevel@tonic-gate if (!Verbose) 11837c478bd9Sstevel@tonic-gate return; 11847c478bd9Sstevel@tonic-gate for (i = 0; i < current_indent; i++) 11857c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, indent_s[i]); 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate static int 11897c478bd9Sstevel@tonic-gate suspects_changed(struct fme *fmep) 11907c478bd9Sstevel@tonic-gate { 11917c478bd9Sstevel@tonic-gate struct event *suspects = fmep->suspects; 11927c478bd9Sstevel@tonic-gate struct event *psuspects = fmep->psuspects; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate while (suspects != NULL && psuspects != NULL) { 11957c478bd9Sstevel@tonic-gate if (suspects != psuspects) 11967c478bd9Sstevel@tonic-gate return (1); 11977c478bd9Sstevel@tonic-gate suspects = suspects->suspects; 11987c478bd9Sstevel@tonic-gate psuspects = psuspects->psuspects; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate return (suspects != psuspects); 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate #define SLNEW 1 12057c478bd9Sstevel@tonic-gate #define SLCHANGED 2 12067c478bd9Sstevel@tonic-gate #define SLWAIT 3 12077c478bd9Sstevel@tonic-gate #define SLDISPROVED 4 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate static void 12107c478bd9Sstevel@tonic-gate print_suspects(int circumstance, struct fme *fmep) 12117c478bd9Sstevel@tonic-gate { 12127c478bd9Sstevel@tonic-gate struct event *ep; 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "["); 12157c478bd9Sstevel@tonic-gate if (circumstance == SLCHANGED) { 12167c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d diagnosis changed. state: %s, " 12177c478bd9Sstevel@tonic-gate "suspect list:", fmep->id, fme_state2str(fmep->state)); 12187c478bd9Sstevel@tonic-gate } else if (circumstance == SLWAIT) { 12197c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d set wait timer ", fmep->id); 12207c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_NONL, &fmep->wull); 12217c478bd9Sstevel@tonic-gate } else if (circumstance == SLDISPROVED) { 12227c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS UNKNOWN", fmep->id); 12237c478bd9Sstevel@tonic-gate } else { 12247c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "FME%d DIAGNOSIS PRODUCED:", fmep->id); 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate if (circumstance == SLWAIT || circumstance == SLDISPROVED) { 12287c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 12297c478bd9Sstevel@tonic-gate return; 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 12337c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, " "); 12347c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_NONL, ep); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate static struct node * 12407c478bd9Sstevel@tonic-gate eventprop_lookup(struct event *ep, const char *propname) 12417c478bd9Sstevel@tonic-gate { 12427c478bd9Sstevel@tonic-gate return (lut_lookup(ep->props, (void *)propname, NULL)); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate #define MAXDIGITIDX 23 12467c478bd9Sstevel@tonic-gate static char numbuf[MAXDIGITIDX + 1]; 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate static int 12497c478bd9Sstevel@tonic-gate node2uint(struct node *n, uint_t *valp) 12507c478bd9Sstevel@tonic-gate { 12517c478bd9Sstevel@tonic-gate struct evalue value; 12527c478bd9Sstevel@tonic-gate struct lut *globals = NULL; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if (n == NULL) 12557c478bd9Sstevel@tonic-gate return (1); 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate /* 12587c478bd9Sstevel@tonic-gate * check value.v since we are being asked to convert an unsigned 12597c478bd9Sstevel@tonic-gate * long long int to an unsigned int 12607c478bd9Sstevel@tonic-gate */ 12617c478bd9Sstevel@tonic-gate if (! eval_expr(n, NULL, NULL, &globals, NULL, NULL, 0, &value) || 12627c478bd9Sstevel@tonic-gate value.t != UINT64 || value.v > (1ULL << 32)) 12637c478bd9Sstevel@tonic-gate return (1); 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate *valp = (uint_t)value.v; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate return (0); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate static nvlist_t * 12717c478bd9Sstevel@tonic-gate node2fmri(struct node *n) 12727c478bd9Sstevel@tonic-gate { 12737c478bd9Sstevel@tonic-gate nvlist_t **pa, *f, *p; 12747c478bd9Sstevel@tonic-gate struct node *nc; 12757c478bd9Sstevel@tonic-gate uint_t depth = 0; 12767c478bd9Sstevel@tonic-gate char *numstr, *nullbyte; 12777c478bd9Sstevel@tonic-gate char *failure; 12787c478bd9Sstevel@tonic-gate int err, i; 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate /* XXX do we need to be able to handle a non-T_NAME node? */ 12817c478bd9Sstevel@tonic-gate if (n == NULL || n->t != T_NAME) 12827c478bd9Sstevel@tonic-gate return (NULL); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate for (nc = n; nc != NULL; nc = nc->u.name.next) { 12857c478bd9Sstevel@tonic-gate if (nc->u.name.child == NULL || nc->u.name.child->t != T_NUM) 12867c478bd9Sstevel@tonic-gate break; 12877c478bd9Sstevel@tonic-gate depth++; 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate if (nc != NULL) { 12917c478bd9Sstevel@tonic-gate /* We bailed early, something went wrong */ 12927c478bd9Sstevel@tonic-gate return (NULL); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate if ((err = nvlist_xalloc(&f, NV_UNIQUE_NAME, &Eft_nv_hdl)) != 0) 12967c478bd9Sstevel@tonic-gate out(O_DIE|O_SYS, "alloc of fmri nvl failed"); 12977c478bd9Sstevel@tonic-gate pa = alloca(depth * sizeof (nvlist_t *)); 12987c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 12997c478bd9Sstevel@tonic-gate pa[i] = NULL; 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate err = nvlist_add_string(f, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC); 13027c478bd9Sstevel@tonic-gate err |= nvlist_add_uint8(f, FM_VERSION, FM_HC_SCHEME_VERSION); 13037c478bd9Sstevel@tonic-gate err |= nvlist_add_string(f, FM_FMRI_HC_ROOT, ""); 13047c478bd9Sstevel@tonic-gate err |= nvlist_add_uint32(f, FM_FMRI_HC_LIST_SZ, depth); 13057c478bd9Sstevel@tonic-gate if (err != 0) { 13067c478bd9Sstevel@tonic-gate failure = "basic construction of FMRI failed"; 13077c478bd9Sstevel@tonic-gate goto boom; 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate numbuf[MAXDIGITIDX] = '\0'; 13117c478bd9Sstevel@tonic-gate nullbyte = &numbuf[MAXDIGITIDX]; 13127c478bd9Sstevel@tonic-gate i = 0; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate for (nc = n; nc != NULL; nc = nc->u.name.next) { 13157c478bd9Sstevel@tonic-gate err = nvlist_xalloc(&p, NV_UNIQUE_NAME, &Eft_nv_hdl); 13167c478bd9Sstevel@tonic-gate if (err != 0) { 13177c478bd9Sstevel@tonic-gate failure = "alloc of an hc-pair failed"; 13187c478bd9Sstevel@tonic-gate goto boom; 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate err = nvlist_add_string(p, FM_FMRI_HC_NAME, nc->u.name.s); 13217c478bd9Sstevel@tonic-gate numstr = ulltostr(nc->u.name.child->u.ull, nullbyte); 13227c478bd9Sstevel@tonic-gate err |= nvlist_add_string(p, FM_FMRI_HC_ID, numstr); 13237c478bd9Sstevel@tonic-gate if (err != 0) { 13247c478bd9Sstevel@tonic-gate failure = "construction of an hc-pair failed"; 13257c478bd9Sstevel@tonic-gate goto boom; 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate pa[i++] = p; 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate err = nvlist_add_nvlist_array(f, FM_FMRI_HC_LIST, pa, depth); 13317c478bd9Sstevel@tonic-gate if (err == 0) { 13327c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 13337c478bd9Sstevel@tonic-gate if (pa[i] != NULL) 13347c478bd9Sstevel@tonic-gate nvlist_free(pa[i]); 13357c478bd9Sstevel@tonic-gate return (f); 13367c478bd9Sstevel@tonic-gate } 13377c478bd9Sstevel@tonic-gate failure = "addition of hc-pair array to FMRI failed"; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate boom: 13407c478bd9Sstevel@tonic-gate for (i = 0; i < depth; i++) 13417c478bd9Sstevel@tonic-gate if (pa[i] != NULL) 13427c478bd9Sstevel@tonic-gate nvlist_free(pa[i]); 13437c478bd9Sstevel@tonic-gate nvlist_free(f); 13447c478bd9Sstevel@tonic-gate out(O_DIE, "%s", failure); 13457c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate static uint_t 13497c478bd9Sstevel@tonic-gate avg(uint_t sum, uint_t cnt) 13507c478bd9Sstevel@tonic-gate { 13517c478bd9Sstevel@tonic-gate unsigned long long s = sum * 10; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate return ((s / cnt / 10) + (((s / cnt % 10) >= 5) ? 1 : 0)); 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate static uint8_t 13577c478bd9Sstevel@tonic-gate percentof(uint_t part, uint_t whole) 13587c478bd9Sstevel@tonic-gate { 13597c478bd9Sstevel@tonic-gate unsigned long long p = part * 1000; 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate return ((p / whole / 10) + (((p / whole % 10) >= 5) ? 1 : 0)); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate static struct rsl { 13657c478bd9Sstevel@tonic-gate struct event *suspect; 13667c478bd9Sstevel@tonic-gate nvlist_t *asru; 13677c478bd9Sstevel@tonic-gate nvlist_t *fru; 13687c478bd9Sstevel@tonic-gate nvlist_t *rsrc; 13697c478bd9Sstevel@tonic-gate }; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate /* 13727c478bd9Sstevel@tonic-gate * rslfree -- free internal members of struct rsl not expected to be 13737c478bd9Sstevel@tonic-gate * freed elsewhere. 13747c478bd9Sstevel@tonic-gate */ 13757c478bd9Sstevel@tonic-gate static void 13767c478bd9Sstevel@tonic-gate rslfree(struct rsl *freeme) 13777c478bd9Sstevel@tonic-gate { 13787c478bd9Sstevel@tonic-gate if (freeme->asru != NULL) 13797c478bd9Sstevel@tonic-gate nvlist_free(freeme->asru); 13807c478bd9Sstevel@tonic-gate if (freeme->fru != NULL) 13817c478bd9Sstevel@tonic-gate nvlist_free(freeme->fru); 13827c478bd9Sstevel@tonic-gate if (freeme->rsrc != NULL && freeme->rsrc != freeme->asru) 13837c478bd9Sstevel@tonic-gate nvlist_free(freeme->rsrc); 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate /* 13877c478bd9Sstevel@tonic-gate * rslcmp -- compare two rsl structures. Use the following 13887c478bd9Sstevel@tonic-gate * comparisons to establish cardinality: 13897c478bd9Sstevel@tonic-gate * 13907c478bd9Sstevel@tonic-gate * 1. Name of the suspect's class. (simple strcmp) 13917c478bd9Sstevel@tonic-gate * 2. Name of the suspect's ASRU. (trickier, since nvlist) 13927c478bd9Sstevel@tonic-gate * 13937c478bd9Sstevel@tonic-gate */ 13947c478bd9Sstevel@tonic-gate static int 13957c478bd9Sstevel@tonic-gate rslcmp(const void *a, const void *b) 13967c478bd9Sstevel@tonic-gate { 13977c478bd9Sstevel@tonic-gate struct rsl *r1 = (struct rsl *)a; 13987c478bd9Sstevel@tonic-gate struct rsl *r2 = (struct rsl *)b; 13997c478bd9Sstevel@tonic-gate int rv; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate rv = strcmp(r1->suspect->enode->u.event.ename->u.name.s, 14027c478bd9Sstevel@tonic-gate r2->suspect->enode->u.event.ename->u.name.s); 14037c478bd9Sstevel@tonic-gate if (rv != 0) 14047c478bd9Sstevel@tonic-gate return (rv); 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate if (r1->asru == NULL && r2->asru == NULL) 14077c478bd9Sstevel@tonic-gate return (0); 14087c478bd9Sstevel@tonic-gate if (r1->asru == NULL) 14097c478bd9Sstevel@tonic-gate return (-1); 14107c478bd9Sstevel@tonic-gate if (r2->asru == NULL) 14117c478bd9Sstevel@tonic-gate return (1); 14127c478bd9Sstevel@tonic-gate return (evnv_cmpnvl(r1->asru, r2->asru, 0)); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate /* 14167c478bd9Sstevel@tonic-gate * rsluniq -- given an array of rsl structures, seek out and "remove" 14177c478bd9Sstevel@tonic-gate * any duplicates. Dups are "remove"d by NULLing the suspect pointer 14187c478bd9Sstevel@tonic-gate * of the array element. Removal also means updating the number of 14197c478bd9Sstevel@tonic-gate * problems and the number of problems which are not faults. User 14207c478bd9Sstevel@tonic-gate * provides the first and last element pointers. 14217c478bd9Sstevel@tonic-gate */ 14227c478bd9Sstevel@tonic-gate static void 14237c478bd9Sstevel@tonic-gate rsluniq(struct rsl *first, struct rsl *last, int *nprobs, int *nnonf) 14247c478bd9Sstevel@tonic-gate { 14257c478bd9Sstevel@tonic-gate struct rsl *cr; 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate if (*nprobs == 1) 14287c478bd9Sstevel@tonic-gate return; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * At this point, we only expect duplicate defects. 14327c478bd9Sstevel@tonic-gate * Eversholt's diagnosis algorithm prevents duplicate 14337c478bd9Sstevel@tonic-gate * suspects, but we rewrite defects in the platform code after 14347c478bd9Sstevel@tonic-gate * the diagnosis is made, and that can introduce new 14357c478bd9Sstevel@tonic-gate * duplicates. 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate while (first <= last) { 14387c478bd9Sstevel@tonic-gate if (first->suspect == NULL || !is_defect(first->suspect->t)) { 14397c478bd9Sstevel@tonic-gate first++; 14407c478bd9Sstevel@tonic-gate continue; 14417c478bd9Sstevel@tonic-gate } 14427c478bd9Sstevel@tonic-gate cr = first + 1; 14437c478bd9Sstevel@tonic-gate while (cr <= last) { 14447c478bd9Sstevel@tonic-gate if (is_defect(first->suspect->t)) { 14457c478bd9Sstevel@tonic-gate if (rslcmp(first, cr) == 0) { 14467c478bd9Sstevel@tonic-gate cr->suspect = NULL; 14477c478bd9Sstevel@tonic-gate rslfree(cr); 14487c478bd9Sstevel@tonic-gate (*nprobs)--; 14497c478bd9Sstevel@tonic-gate (*nnonf)--; 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate /* 14537c478bd9Sstevel@tonic-gate * assume all defects are in order after our 14547c478bd9Sstevel@tonic-gate * sort and short circuit here with "else break" ? 14557c478bd9Sstevel@tonic-gate */ 14567c478bd9Sstevel@tonic-gate cr++; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate first++; 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * get_resources -- for a given suspect, determine what ASRU, FRU and 14647c478bd9Sstevel@tonic-gate * RSRC nvlists should be advertised in the final suspect list. 14657c478bd9Sstevel@tonic-gate */ 14667c478bd9Sstevel@tonic-gate void 14677c478bd9Sstevel@tonic-gate get_resources(struct event *sp, struct rsl *rsrcs, struct config *croot) 14687c478bd9Sstevel@tonic-gate { 14697c478bd9Sstevel@tonic-gate struct node *asrudef, *frudef; 14707c478bd9Sstevel@tonic-gate nvlist_t *asru, *fru; 14717c478bd9Sstevel@tonic-gate nvlist_t *rsrc = NULL; 14727c478bd9Sstevel@tonic-gate char *pathstr; 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate /* 14757c478bd9Sstevel@tonic-gate * First find any ASRU and/or FRU defined in the 14767c478bd9Sstevel@tonic-gate * initial fault tree. 14777c478bd9Sstevel@tonic-gate */ 14787c478bd9Sstevel@tonic-gate asrudef = eventprop_lookup(sp, L_ASRU); 14797c478bd9Sstevel@tonic-gate frudef = eventprop_lookup(sp, L_FRU); 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate /* 14827c478bd9Sstevel@tonic-gate * Create FMRIs based on those definitions 14837c478bd9Sstevel@tonic-gate */ 14847c478bd9Sstevel@tonic-gate asru = node2fmri(asrudef); 14857c478bd9Sstevel@tonic-gate fru = node2fmri(frudef); 14867c478bd9Sstevel@tonic-gate pathstr = ipath2str(NULL, sp->ipp); 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* 14897c478bd9Sstevel@tonic-gate * Allow for platform translations of the FMRIs 14907c478bd9Sstevel@tonic-gate */ 14917c478bd9Sstevel@tonic-gate platform_units_translate(is_defect(sp->t), croot, &asru, &fru, &rsrc, 14927c478bd9Sstevel@tonic-gate pathstr); 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate FREE(pathstr); 14957c478bd9Sstevel@tonic-gate rsrcs->suspect = sp; 14967c478bd9Sstevel@tonic-gate rsrcs->asru = asru; 14977c478bd9Sstevel@tonic-gate rsrcs->fru = fru; 14987c478bd9Sstevel@tonic-gate rsrcs->rsrc = rsrc; 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate /* 15027c478bd9Sstevel@tonic-gate * trim_suspects -- prior to publishing, we may need to remove some 15037c478bd9Sstevel@tonic-gate * suspects from the list. If we're auto-closing upsets, we don't 15047c478bd9Sstevel@tonic-gate * want any of those in the published list. If the ASRUs for multiple 15057c478bd9Sstevel@tonic-gate * defects resolve to the same ASRU (driver) we only want to publish 15067c478bd9Sstevel@tonic-gate * that as a single suspect. 15077c478bd9Sstevel@tonic-gate */ 15087c478bd9Sstevel@tonic-gate static void 15097c478bd9Sstevel@tonic-gate trim_suspects(struct fme *fmep, boolean_t no_upsets, struct rsl **begin, 15107c478bd9Sstevel@tonic-gate struct rsl **end) 15117c478bd9Sstevel@tonic-gate { 15127c478bd9Sstevel@tonic-gate struct event *ep; 15137c478bd9Sstevel@tonic-gate struct rsl *rp; 15147c478bd9Sstevel@tonic-gate int rpcnt; 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate /* 15177c478bd9Sstevel@tonic-gate * First save the suspects in the psuspects, then copy back 15187c478bd9Sstevel@tonic-gate * only the ones we wish to retain. This resets nsuspects to 15197c478bd9Sstevel@tonic-gate * zero. 15207c478bd9Sstevel@tonic-gate */ 15217c478bd9Sstevel@tonic-gate rpcnt = fmep->nsuspects; 15227c478bd9Sstevel@tonic-gate save_suspects(fmep); 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * allocate an array of resource pointers for the suspects. 15267c478bd9Sstevel@tonic-gate * We may end up using less than the full allocation, but this 15277c478bd9Sstevel@tonic-gate * is a very short-lived array. publish_suspects() will free 15287c478bd9Sstevel@tonic-gate * this array when it's done using it. 15297c478bd9Sstevel@tonic-gate */ 15307c478bd9Sstevel@tonic-gate rp = *begin = MALLOC(rpcnt * sizeof (struct rsl)); 15317c478bd9Sstevel@tonic-gate bzero(rp, rpcnt * sizeof (struct rsl)); 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate /* first pass, remove any unwanted upsets and populate our array */ 15347c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = ep->psuspects) { 15357c478bd9Sstevel@tonic-gate if (no_upsets && is_upset(ep->t)) 15367c478bd9Sstevel@tonic-gate continue; 15377c478bd9Sstevel@tonic-gate get_resources(ep, rp, fmep->cfgdata->cooked); 15387c478bd9Sstevel@tonic-gate rp++; 15397c478bd9Sstevel@tonic-gate fmep->nsuspects++; 15407c478bd9Sstevel@tonic-gate if (!is_fault(ep->t)) 15417c478bd9Sstevel@tonic-gate fmep->nonfault++; 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate /* if all we had was unwanted upsets, we're done */ 15457c478bd9Sstevel@tonic-gate if (fmep->nsuspects == 0) 15467c478bd9Sstevel@tonic-gate return; 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate *end = rp - 1; 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate /* sort the array */ 15517c478bd9Sstevel@tonic-gate qsort(*begin, fmep->nsuspects, sizeof (struct rsl), rslcmp); 15527c478bd9Sstevel@tonic-gate rsluniq(*begin, *end, &fmep->nsuspects, &fmep->nonfault); 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate static void 15567c478bd9Sstevel@tonic-gate publish_suspects(struct fme *fmep) 15577c478bd9Sstevel@tonic-gate { 15587c478bd9Sstevel@tonic-gate struct event *ep; 15597c478bd9Sstevel@tonic-gate struct rsl *srl = NULL; 15607c478bd9Sstevel@tonic-gate struct rsl *erl; 15617c478bd9Sstevel@tonic-gate struct rsl *rp; 15627c478bd9Sstevel@tonic-gate nvlist_t *fault; 15637c478bd9Sstevel@tonic-gate uint8_t cert; 15647c478bd9Sstevel@tonic-gate uint_t *frs; 15657c478bd9Sstevel@tonic-gate uint_t fravg, frsum, fr; 15667c478bd9Sstevel@tonic-gate int frcnt, fridx; 15677c478bd9Sstevel@tonic-gate boolean_t no_upsets = B_FALSE; 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->diags); 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate /* 15727c478bd9Sstevel@tonic-gate * The current fmd interfaces don't allow us to solve a case 15737c478bd9Sstevel@tonic-gate * that's already solved. If we make a new case, what of the 15747c478bd9Sstevel@tonic-gate * ereports? We don't appear to have an interface that allows 15757c478bd9Sstevel@tonic-gate * us to access the ereports attached to a case (if we wanted 15767c478bd9Sstevel@tonic-gate * to copy the original case's ereport attachments to the new 15777c478bd9Sstevel@tonic-gate * case) and it's also a bit unclear if there would be any 15787c478bd9Sstevel@tonic-gate * problems with having ereports attached to multiple cases 15797c478bd9Sstevel@tonic-gate * and/or attaching DIAGNOSED ereports to a case. For now, 15807c478bd9Sstevel@tonic-gate * we'll just output a message. 15817c478bd9Sstevel@tonic-gate */ 15827c478bd9Sstevel@tonic-gate if (fmep->posted_suspects || 15837c478bd9Sstevel@tonic-gate fmd_case_solved(fmep->hdl, fmep->fmcase)) { 15847c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, "Revised diagnosis for case %s: ", 15857c478bd9Sstevel@tonic-gate fmd_case_uuid(fmep->hdl, fmep->fmcase)); 15867c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 15877c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, " "); 15887c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_NONL, ep); 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate out(O_ALTFP, NULL); 15917c478bd9Sstevel@tonic-gate return; 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate /* 15957c478bd9Sstevel@tonic-gate * If we're auto-closing upsets, we don't want to include them 15967c478bd9Sstevel@tonic-gate * in any produced suspect lists or certainty accounting. 15977c478bd9Sstevel@tonic-gate */ 15987c478bd9Sstevel@tonic-gate if (Autoclose != NULL) 15997c478bd9Sstevel@tonic-gate if (strcmp(Autoclose, "true") == 0 || 16007c478bd9Sstevel@tonic-gate strcmp(Autoclose, "all") == 0 || 16017c478bd9Sstevel@tonic-gate strcmp(Autoclose, "upsets") == 0) 16027c478bd9Sstevel@tonic-gate no_upsets = B_TRUE; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate trim_suspects(fmep, no_upsets, &srl, &erl); 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate /* 16077c478bd9Sstevel@tonic-gate * If the resulting suspect list has no members, we're 16087c478bd9Sstevel@tonic-gate * done. Returning here will simply close the case. 16097c478bd9Sstevel@tonic-gate */ 16107c478bd9Sstevel@tonic-gate if (fmep->nsuspects == 0) { 16117c478bd9Sstevel@tonic-gate out(O_ALTFP, 16127c478bd9Sstevel@tonic-gate "[FME%d, case %s (all suspects are upsets)]", 16137c478bd9Sstevel@tonic-gate fmep->id, fmd_case_uuid(fmep->hdl, fmep->fmcase)); 16147c478bd9Sstevel@tonic-gate FREE(srl); 16157c478bd9Sstevel@tonic-gate restore_suspects(fmep); 16167c478bd9Sstevel@tonic-gate return; 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 16207c478bd9Sstevel@tonic-gate * If the suspect list is all faults, then for a given fault, 16217c478bd9Sstevel@tonic-gate * say X of N, X's certainty is computed via: 16227c478bd9Sstevel@tonic-gate * 16237c478bd9Sstevel@tonic-gate * fitrate(X) / (fitrate(1) + ... + fitrate(N)) * 100 16247c478bd9Sstevel@tonic-gate * 16257c478bd9Sstevel@tonic-gate * If none of the suspects are faults, and there are N suspects, 16267c478bd9Sstevel@tonic-gate * the certainty of a given suspect is 100/N. 16277c478bd9Sstevel@tonic-gate * 16287c478bd9Sstevel@tonic-gate * If there are are a mixture of faults and other problems in 16297c478bd9Sstevel@tonic-gate * the suspect list, we take an average of the faults' 16307c478bd9Sstevel@tonic-gate * FITrates and treat this average as the FITrate for any 16317c478bd9Sstevel@tonic-gate * non-faults. The fitrate of any given suspect is then 16327c478bd9Sstevel@tonic-gate * computed per the first formula above. 16337c478bd9Sstevel@tonic-gate */ 16347c478bd9Sstevel@tonic-gate if (fmep->nonfault == fmep->nsuspects) { 16357c478bd9Sstevel@tonic-gate /* NO faults in the suspect list */ 16367c478bd9Sstevel@tonic-gate cert = percentof(1, fmep->nsuspects); 16377c478bd9Sstevel@tonic-gate } else { 16387c478bd9Sstevel@tonic-gate /* sum the fitrates */ 16397c478bd9Sstevel@tonic-gate frs = alloca(fmep->nsuspects * sizeof (uint_t)); 16407c478bd9Sstevel@tonic-gate fridx = frcnt = frsum = 0; 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate for (rp = srl; rp <= erl; rp++) { 16437c478bd9Sstevel@tonic-gate struct node *n; 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate if (rp->suspect == NULL) 16467c478bd9Sstevel@tonic-gate continue; 16477c478bd9Sstevel@tonic-gate if (!is_fault(rp->suspect->t)) { 16487c478bd9Sstevel@tonic-gate frs[fridx++] = 0; 16497c478bd9Sstevel@tonic-gate continue; 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate n = eventprop_lookup(rp->suspect, L_FITrate); 16527c478bd9Sstevel@tonic-gate if (node2uint(n, &fr) != 0) { 16537c478bd9Sstevel@tonic-gate out(O_DEBUG|O_NONL, "event "); 16547c478bd9Sstevel@tonic-gate ipath_print(O_DEBUG|O_NONL, 16557c478bd9Sstevel@tonic-gate ep->enode->u.event.ename->u.name.s, 16567c478bd9Sstevel@tonic-gate ep->ipp); 16577c478bd9Sstevel@tonic-gate out(O_DEBUG, " has no FITrate (using 1)"); 16587c478bd9Sstevel@tonic-gate fr = 1; 16597c478bd9Sstevel@tonic-gate } else if (fr == 0) { 16607c478bd9Sstevel@tonic-gate out(O_DEBUG|O_NONL, "event "); 16617c478bd9Sstevel@tonic-gate ipath_print(O_DEBUG|O_NONL, 16627c478bd9Sstevel@tonic-gate ep->enode->u.event.ename->u.name.s, 16637c478bd9Sstevel@tonic-gate ep->ipp); 16647c478bd9Sstevel@tonic-gate out(O_DEBUG, " has zero FITrate (using 1)"); 16657c478bd9Sstevel@tonic-gate fr = 1; 16667c478bd9Sstevel@tonic-gate } 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate frs[fridx++] = fr; 16697c478bd9Sstevel@tonic-gate frsum += fr; 16707c478bd9Sstevel@tonic-gate frcnt++; 16717c478bd9Sstevel@tonic-gate } 16727c478bd9Sstevel@tonic-gate fravg = avg(frsum, frcnt); 16737c478bd9Sstevel@tonic-gate for (fridx = 0; fridx < fmep->nsuspects; fridx++) 16747c478bd9Sstevel@tonic-gate if (frs[fridx] == 0) { 16757c478bd9Sstevel@tonic-gate frs[fridx] = fravg; 16767c478bd9Sstevel@tonic-gate frsum += fravg; 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate /* Add them in reverse order of our sort, as fmd reverses order */ 16817c478bd9Sstevel@tonic-gate for (rp = erl; rp >= srl; rp--) { 16827c478bd9Sstevel@tonic-gate if (rp->suspect == NULL) 16837c478bd9Sstevel@tonic-gate continue; 16847c478bd9Sstevel@tonic-gate if (fmep->nonfault != fmep->nsuspects) 16857c478bd9Sstevel@tonic-gate cert = percentof(frs[--fridx], frsum); 16867c478bd9Sstevel@tonic-gate fault = fmd_nvl_create_fault(fmep->hdl, 16877c478bd9Sstevel@tonic-gate rp->suspect->enode->u.event.ename->u.name.s, 16887c478bd9Sstevel@tonic-gate cert, 16897c478bd9Sstevel@tonic-gate rp->asru, 16907c478bd9Sstevel@tonic-gate rp->fru, 16917c478bd9Sstevel@tonic-gate rp->rsrc); 16927c478bd9Sstevel@tonic-gate if (fault == NULL) 16937c478bd9Sstevel@tonic-gate out(O_DIE, "fault creation failed"); 16947c478bd9Sstevel@tonic-gate fmd_case_add_suspect(fmep->hdl, fmep->fmcase, fault); 16957c478bd9Sstevel@tonic-gate rp->suspect->fault = fault; 16967c478bd9Sstevel@tonic-gate rslfree(rp); 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate fmd_case_solve(fmep->hdl, fmep->fmcase); 16997c478bd9Sstevel@tonic-gate out(O_ALTFP, "[solving FME%d, case %s]", fmep->id, 17007c478bd9Sstevel@tonic-gate fmd_case_uuid(fmep->hdl, fmep->fmcase)); 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate if (Autoconvict) { 17037c478bd9Sstevel@tonic-gate for (rp = srl; rp <= erl; rp++) { 17047c478bd9Sstevel@tonic-gate if (rp->suspect == NULL) 17057c478bd9Sstevel@tonic-gate continue; 17067c478bd9Sstevel@tonic-gate fmd_case_convict(fmep->hdl, 17077c478bd9Sstevel@tonic-gate fmep->fmcase, rp->suspect->fault); 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate out(O_ALTFP, "[convicting FME%d, case %s]", fmep->id, 17107c478bd9Sstevel@tonic-gate fmd_case_uuid(fmep->hdl, fmep->fmcase)); 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate /* 17147c478bd9Sstevel@tonic-gate * revert to the original suspect list 17157c478bd9Sstevel@tonic-gate */ 17167c478bd9Sstevel@tonic-gate FREE(srl); 17177c478bd9Sstevel@tonic-gate restore_suspects(fmep); 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate static void 17217c478bd9Sstevel@tonic-gate publish_undiagnosable(fmd_hdl_t *hdl, fmd_event_t *ffep) 17227c478bd9Sstevel@tonic-gate { 17237c478bd9Sstevel@tonic-gate struct case_list *newcase; 17247c478bd9Sstevel@tonic-gate nvlist_t *defect; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate out(O_ALTFP, 17277c478bd9Sstevel@tonic-gate "[undiagnosable ereport received, " 17287c478bd9Sstevel@tonic-gate "creating and closing a new case (%s)]", 17297c478bd9Sstevel@tonic-gate Undiag_reason ? Undiag_reason : "reason not provided"); 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate newcase = MALLOC(sizeof (struct case_list)); 17327c478bd9Sstevel@tonic-gate newcase->next = NULL; 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate newcase->fmcase = fmd_case_open(hdl, NULL); 17357c478bd9Sstevel@tonic-gate if (Undiagablecaselist != NULL) 17367c478bd9Sstevel@tonic-gate newcase->next = Undiagablecaselist; 17377c478bd9Sstevel@tonic-gate Undiagablecaselist = newcase; 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate if (ffep != NULL) 17407c478bd9Sstevel@tonic-gate fmd_case_add_ereport(hdl, newcase->fmcase, ffep); 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate defect = fmd_nvl_create_fault(hdl, UNDIAGNOSABLE_DEFECT, 100, 17437c478bd9Sstevel@tonic-gate NULL, NULL, NULL); 17447c478bd9Sstevel@tonic-gate if (Undiag_reason != NULL) 17457c478bd9Sstevel@tonic-gate (void) nvlist_add_string(defect, UNDIAG_REASON, Undiag_reason); 17467c478bd9Sstevel@tonic-gate fmd_case_add_suspect(hdl, newcase->fmcase, defect); 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate fmd_case_solve(hdl, newcase->fmcase); 17497c478bd9Sstevel@tonic-gate fmd_case_close(hdl, newcase->fmcase); 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate static void 17537c478bd9Sstevel@tonic-gate fme_undiagnosable(struct fme *f) 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate nvlist_t *defect; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate out(O_ALTFP, "[solving/closing FME%d, case %s (%s)]", 17587c478bd9Sstevel@tonic-gate f->id, fmd_case_uuid(f->hdl, f->fmcase), 17597c478bd9Sstevel@tonic-gate Undiag_reason ? Undiag_reason : "undiagnosable"); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate defect = fmd_nvl_create_fault(f->hdl, UNDIAGNOSABLE_DEFECT, 100, 17627c478bd9Sstevel@tonic-gate NULL, NULL, NULL); 17637c478bd9Sstevel@tonic-gate if (Undiag_reason != NULL) 17647c478bd9Sstevel@tonic-gate (void) nvlist_add_string(defect, UNDIAG_REASON, Undiag_reason); 17657c478bd9Sstevel@tonic-gate fmd_case_add_suspect(f->hdl, f->fmcase, defect); 17667c478bd9Sstevel@tonic-gate fmd_case_solve(f->hdl, f->fmcase); 17677c478bd9Sstevel@tonic-gate destroy_fme_bufs(f); 17687c478bd9Sstevel@tonic-gate fmd_case_close(f->hdl, f->fmcase); 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate /* 17727c478bd9Sstevel@tonic-gate * fme_close_case 17737c478bd9Sstevel@tonic-gate * 17747c478bd9Sstevel@tonic-gate * Find the requested case amongst our fmes and close it. Free up 17757c478bd9Sstevel@tonic-gate * the related fme. 17767c478bd9Sstevel@tonic-gate */ 17777c478bd9Sstevel@tonic-gate void 17787c478bd9Sstevel@tonic-gate fme_close_case(fmd_hdl_t *hdl, fmd_case_t *fmcase) 17797c478bd9Sstevel@tonic-gate { 17807c478bd9Sstevel@tonic-gate struct case_list *ucasep, *prevcasep = NULL; 17817c478bd9Sstevel@tonic-gate struct fme *prev = NULL; 17827c478bd9Sstevel@tonic-gate struct fme *fmep; 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate for (ucasep = Undiagablecaselist; ucasep; ucasep = ucasep->next) { 17857c478bd9Sstevel@tonic-gate if (fmcase != ucasep->fmcase) { 17867c478bd9Sstevel@tonic-gate prevcasep = ucasep; 17877c478bd9Sstevel@tonic-gate continue; 17887c478bd9Sstevel@tonic-gate } 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if (prevcasep == NULL) 17917c478bd9Sstevel@tonic-gate Undiagablecaselist = Undiagablecaselist->next; 17927c478bd9Sstevel@tonic-gate else 17937c478bd9Sstevel@tonic-gate prevcasep->next = ucasep->next; 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate FREE(ucasep); 17967c478bd9Sstevel@tonic-gate return; 17977c478bd9Sstevel@tonic-gate } 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate for (fmep = FMElist; fmep; fmep = fmep->next) { 18007c478bd9Sstevel@tonic-gate if (fmep->hdl == hdl && fmep->fmcase == fmcase) 18017c478bd9Sstevel@tonic-gate break; 18027c478bd9Sstevel@tonic-gate prev = fmep; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate if (fmep == NULL) { 18067c478bd9Sstevel@tonic-gate out(O_WARN, "Eft asked to close unrecognized case [%s].", 18077c478bd9Sstevel@tonic-gate fmd_case_uuid(hdl, fmcase)); 18087c478bd9Sstevel@tonic-gate return; 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate if (EFMElist == fmep) 18127c478bd9Sstevel@tonic-gate EFMElist = prev; 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate if (prev == NULL) 18157c478bd9Sstevel@tonic-gate FMElist = FMElist->next; 18167c478bd9Sstevel@tonic-gate else 18177c478bd9Sstevel@tonic-gate prev->next = fmep->next; 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate fmep->next = NULL; 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate /* Get rid of any timer this fme has set */ 18227c478bd9Sstevel@tonic-gate if (fmep->wull != 0) 18237c478bd9Sstevel@tonic-gate fmd_timer_remove(fmep->hdl, fmep->timer); 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate if (ClosedFMEs == NULL) { 18267c478bd9Sstevel@tonic-gate ClosedFMEs = fmep; 18277c478bd9Sstevel@tonic-gate } else { 18287c478bd9Sstevel@tonic-gate fmep->next = ClosedFMEs; 18297c478bd9Sstevel@tonic-gate ClosedFMEs = fmep; 18307c478bd9Sstevel@tonic-gate } 1831*0cc1f05eSjrutt 1832*0cc1f05eSjrutt Open_fme_count--; 1833*0cc1f05eSjrutt 1834*0cc1f05eSjrutt /* See if we can close the overflow FME */ 1835*0cc1f05eSjrutt if (Open_fme_count <= Max_fme) { 1836*0cc1f05eSjrutt for (fmep = FMElist; fmep; fmep = fmep->next) { 1837*0cc1f05eSjrutt if (fmep->overflow && !(fmd_case_closed(fmep->hdl, 1838*0cc1f05eSjrutt fmep->fmcase))) 1839*0cc1f05eSjrutt break; 1840*0cc1f05eSjrutt } 1841*0cc1f05eSjrutt 1842*0cc1f05eSjrutt if (fmep != NULL) 1843*0cc1f05eSjrutt fmd_case_close(fmep->hdl, fmep->fmcase); 1844*0cc1f05eSjrutt } 18457c478bd9Sstevel@tonic-gate } 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate /* 18487c478bd9Sstevel@tonic-gate * fme_set_timer() 18497c478bd9Sstevel@tonic-gate * If the time we need to wait for the given FME is less than the 18507c478bd9Sstevel@tonic-gate * current timer, kick that old timer out and establish a new one. 18517c478bd9Sstevel@tonic-gate */ 18527c478bd9Sstevel@tonic-gate static void 18537c478bd9Sstevel@tonic-gate fme_set_timer(struct fme *fmep, unsigned long long wull) 18547c478bd9Sstevel@tonic-gate { 18557c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " fme_set_timer: request to wait "); 18567c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &wull); 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate if (wull <= fmep->pull) { 18597c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "already have waited at least "); 18607c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &fmep->pull); 18617c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 18627c478bd9Sstevel@tonic-gate /* we've waited at least wull already, don't need timer */ 18637c478bd9Sstevel@tonic-gate return; 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " currently "); 18677c478bd9Sstevel@tonic-gate if (fmep->wull != 0) { 18687c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "waiting "); 18697c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB, &fmep->wull); 18707c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 18717c478bd9Sstevel@tonic-gate } else { 18727c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "not waiting"); 18737c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 18747c478bd9Sstevel@tonic-gate } 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate if (fmep->wull != 0) 18777c478bd9Sstevel@tonic-gate if (wull >= fmep->wull) 18787c478bd9Sstevel@tonic-gate /* New timer would fire later than established timer */ 18797c478bd9Sstevel@tonic-gate return; 18807c478bd9Sstevel@tonic-gate 18817c478bd9Sstevel@tonic-gate if (fmep->wull != 0) 18827c478bd9Sstevel@tonic-gate fmd_timer_remove(fmep->hdl, fmep->timer); 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate fmep->timer = fmd_timer_install(fmep->hdl, (void *)fmep, 18857c478bd9Sstevel@tonic-gate fmep->e0r, wull); 18867c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, "timer set, id is %ld", fmep->timer); 18877c478bd9Sstevel@tonic-gate fmep->wull = wull; 18887c478bd9Sstevel@tonic-gate } 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate void 18917c478bd9Sstevel@tonic-gate fme_timer_fired(struct fme *fmep, id_t tid) 18927c478bd9Sstevel@tonic-gate { 18937c478bd9Sstevel@tonic-gate struct fme *ffmep = NULL; 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate for (ffmep = FMElist; ffmep; ffmep = ffmep->next) 18967c478bd9Sstevel@tonic-gate if (ffmep == fmep) 18977c478bd9Sstevel@tonic-gate break; 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate if (ffmep == NULL) { 19007c478bd9Sstevel@tonic-gate out(O_WARN, "Timer fired for an FME (%p) not in FMEs list.", 19017c478bd9Sstevel@tonic-gate (void *)fmep); 19027c478bd9Sstevel@tonic-gate return; 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate if (tid != fmep->htid) { 19067c478bd9Sstevel@tonic-gate /* 19077c478bd9Sstevel@tonic-gate * normal timer (not the hesitation timer 19087c478bd9Sstevel@tonic-gate */ 19097c478bd9Sstevel@tonic-gate fmep->pull = fmep->wull; 19107c478bd9Sstevel@tonic-gate fmep->wull = 0; 19117c478bd9Sstevel@tonic-gate fmd_buf_write(fmep->hdl, fmep->fmcase, 19127c478bd9Sstevel@tonic-gate WOBUF_PULL, (void *)&fmep->pull, sizeof (fmep->pull)); 19137c478bd9Sstevel@tonic-gate } else { 19147c478bd9Sstevel@tonic-gate fmep->hesitated = 1; 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate fme_eval(fmep, NULL); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate /* 19207c478bd9Sstevel@tonic-gate * Preserve the fme's suspect list in its psuspects list, NULLing the 19217c478bd9Sstevel@tonic-gate * suspects list in the meantime. 19227c478bd9Sstevel@tonic-gate */ 19237c478bd9Sstevel@tonic-gate static void 19247c478bd9Sstevel@tonic-gate save_suspects(struct fme *fmep) 19257c478bd9Sstevel@tonic-gate { 19267c478bd9Sstevel@tonic-gate struct event *ep; 19277c478bd9Sstevel@tonic-gate struct event *nextep; 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate /* zero out the previous suspect list */ 19307c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = nextep) { 19317c478bd9Sstevel@tonic-gate nextep = ep->psuspects; 19327c478bd9Sstevel@tonic-gate ep->psuspects = NULL; 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate fmep->psuspects = NULL; 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate /* zero out the suspect list, copying it to previous suspect list */ 19377c478bd9Sstevel@tonic-gate fmep->psuspects = fmep->suspects; 19387c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = nextep) { 19397c478bd9Sstevel@tonic-gate nextep = ep->suspects; 19407c478bd9Sstevel@tonic-gate ep->psuspects = ep->suspects; 19417c478bd9Sstevel@tonic-gate ep->suspects = NULL; 19427c478bd9Sstevel@tonic-gate ep->is_suspect = 0; 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate fmep->suspects = NULL; 19457c478bd9Sstevel@tonic-gate fmep->nsuspects = 0; 19467c478bd9Sstevel@tonic-gate fmep->nonfault = 0; 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate /* 19507c478bd9Sstevel@tonic-gate * Retrieve the fme's suspect list from its psuspects list. 19517c478bd9Sstevel@tonic-gate */ 19527c478bd9Sstevel@tonic-gate static void 19537c478bd9Sstevel@tonic-gate restore_suspects(struct fme *fmep) 19547c478bd9Sstevel@tonic-gate { 19557c478bd9Sstevel@tonic-gate struct event *ep; 19567c478bd9Sstevel@tonic-gate struct event *nextep; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate fmep->nsuspects = fmep->nonfault = 0; 19597c478bd9Sstevel@tonic-gate fmep->suspects = fmep->psuspects; 19607c478bd9Sstevel@tonic-gate for (ep = fmep->psuspects; ep; ep = nextep) { 19617c478bd9Sstevel@tonic-gate fmep->nsuspects++; 19627c478bd9Sstevel@tonic-gate if (!is_fault(ep->t)) 19637c478bd9Sstevel@tonic-gate fmep->nonfault++; 19647c478bd9Sstevel@tonic-gate nextep = ep->psuspects; 19657c478bd9Sstevel@tonic-gate ep->suspects = ep->psuspects; 19667c478bd9Sstevel@tonic-gate } 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate /* 19707c478bd9Sstevel@tonic-gate * this is what we use to call the Emrys prototype code instead of main() 19717c478bd9Sstevel@tonic-gate */ 19727c478bd9Sstevel@tonic-gate static void 19737c478bd9Sstevel@tonic-gate fme_eval(struct fme *fmep, fmd_event_t *ffep) 19747c478bd9Sstevel@tonic-gate { 19757c478bd9Sstevel@tonic-gate struct event *ep; 19767c478bd9Sstevel@tonic-gate unsigned long long my_delay = TIMEVAL_EVENTUALLY; 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate save_suspects(fmep); 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, "Evaluate FME %d", fmep->id); 19817c478bd9Sstevel@tonic-gate indent_set(" "); 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate initialize_cycles(fmep); 19847c478bd9Sstevel@tonic-gate fmep->state = hypothesise(fmep, fmep->e0, fmep->ull, &my_delay, NULL); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "FME%d state: %s, suspect list:", fmep->id, 19877c478bd9Sstevel@tonic-gate fme_state2str(fmep->state)); 19887c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 19897c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 19907c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate if (fmep->posted_suspects) { 19957c478bd9Sstevel@tonic-gate /* 19967c478bd9Sstevel@tonic-gate * this FME has already posted a diagnosis, so see if 19977c478bd9Sstevel@tonic-gate * the event changed the diagnosis and print a warning 19987c478bd9Sstevel@tonic-gate * if it did. 19997c478bd9Sstevel@tonic-gate * 20007c478bd9Sstevel@tonic-gate */ 20017c478bd9Sstevel@tonic-gate if (suspects_changed(fmep)) { 20027c478bd9Sstevel@tonic-gate print_suspects(SLCHANGED, fmep); 20037c478bd9Sstevel@tonic-gate publish_suspects(fmep); 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate } else { 20067c478bd9Sstevel@tonic-gate switch (fmep->state) { 20077c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 20087c478bd9Sstevel@tonic-gate /* 20097c478bd9Sstevel@tonic-gate * if the suspect list contains any upsets, we 20107c478bd9Sstevel@tonic-gate * turn off the hesitation logic (by setting 20117c478bd9Sstevel@tonic-gate * the hesitate flag which normally indicates 20127c478bd9Sstevel@tonic-gate * we've already done the hesitate logic). 20137c478bd9Sstevel@tonic-gate * this is done because hesitating with upsets 20147c478bd9Sstevel@tonic-gate * causes us to explain away additional soft errors 20157c478bd9Sstevel@tonic-gate * while the upset FME stays open. 20167c478bd9Sstevel@tonic-gate */ 20177c478bd9Sstevel@tonic-gate if (fmep->hesitated == 0) { 20187c478bd9Sstevel@tonic-gate struct event *s; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate for (s = fmep->suspects; s; s = s->suspects) { 20217c478bd9Sstevel@tonic-gate if (s->t == N_UPSET) { 20227c478bd9Sstevel@tonic-gate fmep->hesitated = 1; 20237c478bd9Sstevel@tonic-gate break; 20247c478bd9Sstevel@tonic-gate } 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate } 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate if (Hesitate && 20297c478bd9Sstevel@tonic-gate fmep->suspects != NULL && 20307c478bd9Sstevel@tonic-gate fmep->suspects->suspects != NULL && 20317c478bd9Sstevel@tonic-gate fmep->hesitated == 0) { 20327c478bd9Sstevel@tonic-gate /* 20337c478bd9Sstevel@tonic-gate * about to publish multi-entry suspect list, 20347c478bd9Sstevel@tonic-gate * set the hesitation timer if not already set. 20357c478bd9Sstevel@tonic-gate */ 20367c478bd9Sstevel@tonic-gate if (fmep->htid == 0) { 20377c478bd9Sstevel@tonic-gate out(O_ALTFP|O_NONL, 20387c478bd9Sstevel@tonic-gate "[hesitate FME%d, case %s ", 20397c478bd9Sstevel@tonic-gate fmep->id, 20407c478bd9Sstevel@tonic-gate fmd_case_uuid(fmep->hdl, 20417c478bd9Sstevel@tonic-gate fmep->fmcase)); 20427c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_NONL, 20437c478bd9Sstevel@tonic-gate (unsigned long long *)&Hesitate); 20447c478bd9Sstevel@tonic-gate out(O_ALTFP, "]"); 20457c478bd9Sstevel@tonic-gate fme_set_timer(fmep, my_delay); 20467c478bd9Sstevel@tonic-gate fmep->htid = 20477c478bd9Sstevel@tonic-gate fmd_timer_install(fmep->hdl, 20487c478bd9Sstevel@tonic-gate (void *)fmep, NULL, Hesitate); 20497c478bd9Sstevel@tonic-gate } else { 20507c478bd9Sstevel@tonic-gate out(O_ALTFP, 20517c478bd9Sstevel@tonic-gate "[still hesitating FME%d, case %s]", 20527c478bd9Sstevel@tonic-gate fmep->id, 20537c478bd9Sstevel@tonic-gate fmd_case_uuid(fmep->hdl, 20547c478bd9Sstevel@tonic-gate fmep->fmcase)); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate } else { 20577c478bd9Sstevel@tonic-gate print_suspects(SLNEW, fmep); 20587c478bd9Sstevel@tonic-gate (void) upsets_eval(fmep, ffep); 20597c478bd9Sstevel@tonic-gate publish_suspects(fmep); 20607c478bd9Sstevel@tonic-gate fmep->posted_suspects = 1; 20617c478bd9Sstevel@tonic-gate fmd_buf_write(fmep->hdl, fmep->fmcase, 20627c478bd9Sstevel@tonic-gate WOBUF_POSTD, 20637c478bd9Sstevel@tonic-gate (void *)&fmep->posted_suspects, 20647c478bd9Sstevel@tonic-gate sizeof (fmep->posted_suspects)); 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate break; 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate case FME_WAIT: 20697c478bd9Sstevel@tonic-gate /* 20707c478bd9Sstevel@tonic-gate * singleton suspect list implies 20717c478bd9Sstevel@tonic-gate * no point in waiting 20727c478bd9Sstevel@tonic-gate */ 20737c478bd9Sstevel@tonic-gate if (fmep->suspects && 20747c478bd9Sstevel@tonic-gate fmep->suspects->suspects == NULL) { 20757c478bd9Sstevel@tonic-gate print_suspects(SLNEW, fmep); 20767c478bd9Sstevel@tonic-gate (void) upsets_eval(fmep, ffep); 20777c478bd9Sstevel@tonic-gate publish_suspects(fmep); 20787c478bd9Sstevel@tonic-gate fmep->posted_suspects = 1; 20797c478bd9Sstevel@tonic-gate fmd_buf_write(fmep->hdl, fmep->fmcase, 20807c478bd9Sstevel@tonic-gate WOBUF_POSTD, 20817c478bd9Sstevel@tonic-gate (void *)&fmep->posted_suspects, 20827c478bd9Sstevel@tonic-gate sizeof (fmep->posted_suspects)); 20837c478bd9Sstevel@tonic-gate fmep->state = FME_CREDIBLE; 20847c478bd9Sstevel@tonic-gate } else { 20857c478bd9Sstevel@tonic-gate ASSERT(my_delay > fmep->ull); 20867c478bd9Sstevel@tonic-gate fme_set_timer(fmep, my_delay); 20877c478bd9Sstevel@tonic-gate print_suspects(SLWAIT, fmep); 20887c478bd9Sstevel@tonic-gate } 20897c478bd9Sstevel@tonic-gate break; 20907c478bd9Sstevel@tonic-gate 20917c478bd9Sstevel@tonic-gate case FME_DISPROVED: 20927c478bd9Sstevel@tonic-gate print_suspects(SLDISPROVED, fmep); 20937c478bd9Sstevel@tonic-gate Undiag_reason = UD_UNSOLVD; 20947c478bd9Sstevel@tonic-gate fme_undiagnosable(fmep); 20957c478bd9Sstevel@tonic-gate break; 20967c478bd9Sstevel@tonic-gate } 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate if (fmep->posted_suspects == 1 && Autoclose != NULL) { 21007c478bd9Sstevel@tonic-gate int doclose = 0; 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate if (strcmp(Autoclose, "true") == 0 || 21037c478bd9Sstevel@tonic-gate strcmp(Autoclose, "all") == 0) 21047c478bd9Sstevel@tonic-gate doclose = 1; 21057c478bd9Sstevel@tonic-gate 21067c478bd9Sstevel@tonic-gate if (strcmp(Autoclose, "upsets") == 0) { 21077c478bd9Sstevel@tonic-gate doclose = 1; 21087c478bd9Sstevel@tonic-gate for (ep = fmep->suspects; ep; ep = ep->suspects) { 21097c478bd9Sstevel@tonic-gate if (ep->t != N_UPSET) { 21107c478bd9Sstevel@tonic-gate doclose = 0; 21117c478bd9Sstevel@tonic-gate break; 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate if (doclose) { 21177c478bd9Sstevel@tonic-gate out(O_ALTFP, "[closing FME%d, case %s (autoclose)]", 21187c478bd9Sstevel@tonic-gate fmep->id, fmd_case_uuid(fmep->hdl, fmep->fmcase)); 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate destroy_fme_bufs(fmep); 21217c478bd9Sstevel@tonic-gate fmd_case_close(fmep->hdl, fmep->fmcase); 21227c478bd9Sstevel@tonic-gate } 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate } 21257c478bd9Sstevel@tonic-gate 21267c478bd9Sstevel@tonic-gate /* 21277c478bd9Sstevel@tonic-gate * below here is the code derived from the Emrys prototype 21287c478bd9Sstevel@tonic-gate */ 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate static void indent(void); 21317c478bd9Sstevel@tonic-gate static int triggered(struct fme *fmep, struct event *ep, int mark); 21327c478bd9Sstevel@tonic-gate static void mark_arrows(struct fme *fmep, struct event *ep, int mark); 21337c478bd9Sstevel@tonic-gate static enum fme_state effects_test(struct fme *fmep, 21347c478bd9Sstevel@tonic-gate struct event *fault_event); 21357c478bd9Sstevel@tonic-gate static enum fme_state requirements_test(struct fme *fmep, struct event *ep, 21367c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay, 21377c478bd9Sstevel@tonic-gate struct arrow *arrowp); 21387c478bd9Sstevel@tonic-gate static enum fme_state causes_test(struct fme *fmep, struct event *ep, 21397c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay); 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate static int 21427c478bd9Sstevel@tonic-gate triggered(struct fme *fmep, struct event *ep, int mark) 21437c478bd9Sstevel@tonic-gate { 21447c478bd9Sstevel@tonic-gate struct bubble *bp; 21457c478bd9Sstevel@tonic-gate struct arrowlist *ap; 21467c478bd9Sstevel@tonic-gate int count = 0; 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Tcallcount); 21497c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 21507c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 21517c478bd9Sstevel@tonic-gate if (bp->t != B_TO) 21527c478bd9Sstevel@tonic-gate continue; 21537c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 21547c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 21557c478bd9Sstevel@tonic-gate /* check count of marks against K in the bubble */ 21567c478bd9Sstevel@tonic-gate if (ap->arrowp->tail->mark == mark && 21577c478bd9Sstevel@tonic-gate ++count >= bp->nork) 21587c478bd9Sstevel@tonic-gate return (1); 21597c478bd9Sstevel@tonic-gate } 21607c478bd9Sstevel@tonic-gate } 21617c478bd9Sstevel@tonic-gate return (0); 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate static void 21657c478bd9Sstevel@tonic-gate mark_arrows(struct fme *fmep, struct event *ep, int mark) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate struct bubble *bp; 21687c478bd9Sstevel@tonic-gate struct arrowlist *ap; 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 21717c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 21727c478bd9Sstevel@tonic-gate if (bp->t != B_FROM) 21737c478bd9Sstevel@tonic-gate continue; 21747c478bd9Sstevel@tonic-gate if (bp->mark != mark) { 21757c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Marrowcount); 21767c478bd9Sstevel@tonic-gate bp->mark = mark; 21777c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 21787c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 21797c478bd9Sstevel@tonic-gate struct constraintlist *ctp; 21807c478bd9Sstevel@tonic-gate struct evalue value; 21817c478bd9Sstevel@tonic-gate int do_not_follow = 0; 21827c478bd9Sstevel@tonic-gate /* 21837c478bd9Sstevel@tonic-gate * see if false constraint prevents us 21847c478bd9Sstevel@tonic-gate * from traversing this arrow, but don't 21857c478bd9Sstevel@tonic-gate * bother if the event is an ereport we 21867c478bd9Sstevel@tonic-gate * haven't seen 21877c478bd9Sstevel@tonic-gate */ 21887c478bd9Sstevel@tonic-gate if (ap->arrowp->head->myevent->t != N_EREPORT || 21897c478bd9Sstevel@tonic-gate ap->arrowp->head->myevent->count != 0) { 21907c478bd9Sstevel@tonic-gate platform_set_payloadnvp( 21917c478bd9Sstevel@tonic-gate ap->arrowp->head->myevent->nvp); 21927c478bd9Sstevel@tonic-gate for (ctp = ap->arrowp->constraints; 21937c478bd9Sstevel@tonic-gate ctp != NULL; ctp = ctp->next) { 21947c478bd9Sstevel@tonic-gate if (eval_expr(ctp->cnode, 21957c478bd9Sstevel@tonic-gate NULL, NULL, 21967c478bd9Sstevel@tonic-gate &fmep->globals, 21977c478bd9Sstevel@tonic-gate fmep->cfgdata->cooked, 21987c478bd9Sstevel@tonic-gate ap->arrowp, 0, 21997c478bd9Sstevel@tonic-gate &value) == 0 || 22007c478bd9Sstevel@tonic-gate value.t == UNDEFINED || 22017c478bd9Sstevel@tonic-gate value.v == 0) { 22027c478bd9Sstevel@tonic-gate do_not_follow = 1; 22037c478bd9Sstevel@tonic-gate break; 22047c478bd9Sstevel@tonic-gate } 22057c478bd9Sstevel@tonic-gate } 22067c478bd9Sstevel@tonic-gate platform_set_payloadnvp(NULL); 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate if (do_not_follow) { 22107c478bd9Sstevel@tonic-gate indent(); 22117c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 22127c478bd9Sstevel@tonic-gate " False arrow to "); 22137c478bd9Sstevel@tonic-gate itree_pevent_brief( 22147c478bd9Sstevel@tonic-gate O_ALTFP|O_VERB|O_NONL, 22157c478bd9Sstevel@tonic-gate ap->arrowp->head->myevent); 22167c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 22177c478bd9Sstevel@tonic-gate ptree(O_ALTFP|O_VERB|O_NONL, 22187c478bd9Sstevel@tonic-gate ctp->cnode, 1, 0); 22197c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 22207c478bd9Sstevel@tonic-gate continue; 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate if (triggered(fmep, ap->arrowp->head->myevent, 22247c478bd9Sstevel@tonic-gate mark)) 22257c478bd9Sstevel@tonic-gate mark_arrows(fmep, 22267c478bd9Sstevel@tonic-gate ap->arrowp->head->myevent, mark); 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate } 22297c478bd9Sstevel@tonic-gate } 22307c478bd9Sstevel@tonic-gate } 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate static enum fme_state 22337c478bd9Sstevel@tonic-gate effects_test(struct fme *fmep, struct event *fault_event) 22347c478bd9Sstevel@tonic-gate { 22357c478bd9Sstevel@tonic-gate struct event *error_event; 22367c478bd9Sstevel@tonic-gate enum fme_state return_value = FME_CREDIBLE; 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Ecallcount); 22397c478bd9Sstevel@tonic-gate indent_push(" E"); 22407c478bd9Sstevel@tonic-gate indent(); 22417c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 22427c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, fault_event); 22437c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate mark_arrows(fmep, fault_event, 1); 22467c478bd9Sstevel@tonic-gate for (error_event = fmep->observations; 22477c478bd9Sstevel@tonic-gate error_event; error_event = error_event->observations) { 22487c478bd9Sstevel@tonic-gate indent(); 22497c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 22507c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, error_event); 22517c478bd9Sstevel@tonic-gate if (!triggered(fmep, error_event, 1)) { 22527c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 22537c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " NOT triggered"); 22547c478bd9Sstevel@tonic-gate break; 22557c478bd9Sstevel@tonic-gate } else { 22567c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " triggered"); 22577c478bd9Sstevel@tonic-gate } 22587c478bd9Sstevel@tonic-gate } 22597c478bd9Sstevel@tonic-gate mark_arrows(fmep, fault_event, 0); 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate indent(); 22627c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-%s ", fme_state2str(return_value)); 22637c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, fault_event); 22647c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 22657c478bd9Sstevel@tonic-gate indent_pop(); 22667c478bd9Sstevel@tonic-gate return (return_value); 22677c478bd9Sstevel@tonic-gate } 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate static enum fme_state 22707c478bd9Sstevel@tonic-gate requirements_test(struct fme *fmep, struct event *ep, 22717c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay, 22727c478bd9Sstevel@tonic-gate struct arrow *arrowp) 22737c478bd9Sstevel@tonic-gate { 22747c478bd9Sstevel@tonic-gate int waiting_events; 22757c478bd9Sstevel@tonic-gate int credible_events; 22767c478bd9Sstevel@tonic-gate enum fme_state return_value = FME_CREDIBLE; 22777c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 22787c478bd9Sstevel@tonic-gate unsigned long long arrow_delay; 22797c478bd9Sstevel@tonic-gate unsigned long long my_delay; 22807c478bd9Sstevel@tonic-gate struct event *ep2; 22817c478bd9Sstevel@tonic-gate struct bubble *bp; 22827c478bd9Sstevel@tonic-gate struct arrowlist *ap; 22837c478bd9Sstevel@tonic-gate 22847c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Rcallcount); 22857c478bd9Sstevel@tonic-gate indent_push(" R"); 22867c478bd9Sstevel@tonic-gate indent(); 22877c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 22887c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 22897c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, ", at latest by: "); 22907c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 22917c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 22927c478bd9Sstevel@tonic-gate 22937c478bd9Sstevel@tonic-gate if (ep->t == N_EREPORT) { 22947c478bd9Sstevel@tonic-gate if (ep->count == 0) { 22957c478bd9Sstevel@tonic-gate if (fmep->pull >= at_latest_by) { 22967c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 22977c478bd9Sstevel@tonic-gate } else { 22987c478bd9Sstevel@tonic-gate *pdelay = at_latest_by; 22997c478bd9Sstevel@tonic-gate return_value = FME_WAIT; 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate } else if (arrowp != NULL) { 23027c478bd9Sstevel@tonic-gate /* 23037c478bd9Sstevel@tonic-gate * evaluate constraints only for current observation 23047c478bd9Sstevel@tonic-gate */ 23057c478bd9Sstevel@tonic-gate struct constraintlist *ctp; 23067c478bd9Sstevel@tonic-gate struct evalue value; 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate platform_set_payloadnvp(ep->nvp); 23097c478bd9Sstevel@tonic-gate for (ctp = arrowp->constraints; ctp != NULL; 23107c478bd9Sstevel@tonic-gate ctp = ctp->next) { 23117c478bd9Sstevel@tonic-gate if (eval_expr(ctp->cnode, NULL, NULL, 23127c478bd9Sstevel@tonic-gate &fmep->globals, fmep->cfgdata->cooked, 23137c478bd9Sstevel@tonic-gate arrowp, 0, &value) == 0 || 23147c478bd9Sstevel@tonic-gate value.t == UNDEFINED || value.v == 0) { 23157c478bd9Sstevel@tonic-gate indent(); 23167c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 23177c478bd9Sstevel@tonic-gate " False constraint "); 23187c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 23197c478bd9Sstevel@tonic-gate ptree(O_ALTFP|O_VERB|O_NONL, 23207c478bd9Sstevel@tonic-gate ctp->cnode, 1, 0); 23217c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 23227c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 23237c478bd9Sstevel@tonic-gate break; 23247c478bd9Sstevel@tonic-gate } 23257c478bd9Sstevel@tonic-gate } 23267c478bd9Sstevel@tonic-gate platform_set_payloadnvp(NULL); 23277c478bd9Sstevel@tonic-gate } 23287c478bd9Sstevel@tonic-gate 23297c478bd9Sstevel@tonic-gate indent(); 23307c478bd9Sstevel@tonic-gate switch (return_value) { 23317c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 23327c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-CREDIBLE "); 23337c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 23347c478bd9Sstevel@tonic-gate break; 23357c478bd9Sstevel@tonic-gate case FME_DISPROVED: 23367c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 23377c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 23387c478bd9Sstevel@tonic-gate break; 23397c478bd9Sstevel@tonic-gate case FME_WAIT: 23407c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-WAIT "); 23417c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 23427c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 23437c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 23447c478bd9Sstevel@tonic-gate break; 23457c478bd9Sstevel@tonic-gate default: 23467c478bd9Sstevel@tonic-gate out(O_DIE, "requirements_test: unexpected fme_state"); 23477c478bd9Sstevel@tonic-gate break; 23487c478bd9Sstevel@tonic-gate } 23497c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 23507c478bd9Sstevel@tonic-gate indent_pop(); 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate return (return_value); 23537c478bd9Sstevel@tonic-gate } 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate /* this event is not a report, descend the tree */ 23567c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 23577c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 23587c478bd9Sstevel@tonic-gate if (bp->t != B_FROM) 23597c478bd9Sstevel@tonic-gate continue; 23607c478bd9Sstevel@tonic-gate if (bp->mark == 0) { 23617c478bd9Sstevel@tonic-gate int n = bp->nork; 23627c478bd9Sstevel@tonic-gate 23637c478bd9Sstevel@tonic-gate bp->mark = 1; 23647c478bd9Sstevel@tonic-gate credible_events = 0; 23657c478bd9Sstevel@tonic-gate waiting_events = 0; 23667c478bd9Sstevel@tonic-gate arrow_delay = TIMEVAL_EVENTUALLY; 23677c478bd9Sstevel@tonic-gate /* 23687c478bd9Sstevel@tonic-gate * n is -1 for 'A' so adjust it. 23697c478bd9Sstevel@tonic-gate * XXX just count up the arrows for now. 23707c478bd9Sstevel@tonic-gate */ 23717c478bd9Sstevel@tonic-gate if (n < 0) { 23727c478bd9Sstevel@tonic-gate n = 0; 23737c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 23747c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) 23757c478bd9Sstevel@tonic-gate n++; 23767c478bd9Sstevel@tonic-gate indent(); 23777c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " Bubble Counted N=%d", n); 23787c478bd9Sstevel@tonic-gate } else { 23797c478bd9Sstevel@tonic-gate indent(); 23807c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " Bubble N=%d", n); 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate 23837c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 23847c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 23857c478bd9Sstevel@tonic-gate ep2 = ap->arrowp->head->myevent; 23867c478bd9Sstevel@tonic-gate if (n <= credible_events) 23877c478bd9Sstevel@tonic-gate break; 23887c478bd9Sstevel@tonic-gate 23897c478bd9Sstevel@tonic-gate if (triggered(fmep, ep2, 1)) 23907c478bd9Sstevel@tonic-gate /* XXX adding max timevals! */ 23917c478bd9Sstevel@tonic-gate switch (requirements_test(fmep, ep2, 23927c478bd9Sstevel@tonic-gate at_latest_by + ap->arrowp->maxdelay, 23937c478bd9Sstevel@tonic-gate &my_delay, ap->arrowp)) { 23947c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 23957c478bd9Sstevel@tonic-gate credible_events++; 23967c478bd9Sstevel@tonic-gate break; 23977c478bd9Sstevel@tonic-gate case FME_DISPROVED: 23987c478bd9Sstevel@tonic-gate break; 23997c478bd9Sstevel@tonic-gate case FME_WAIT: 24007c478bd9Sstevel@tonic-gate if (my_delay < arrow_delay) 24017c478bd9Sstevel@tonic-gate arrow_delay = my_delay; 24027c478bd9Sstevel@tonic-gate waiting_events++; 24037c478bd9Sstevel@tonic-gate break; 24047c478bd9Sstevel@tonic-gate default: 24057c478bd9Sstevel@tonic-gate out(O_DIE, 24067c478bd9Sstevel@tonic-gate "Bug in requirements_test."); 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate else 24097c478bd9Sstevel@tonic-gate credible_events++; 24107c478bd9Sstevel@tonic-gate } 24117c478bd9Sstevel@tonic-gate indent(); 24127c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " Credible: %d Waiting %d", 24137c478bd9Sstevel@tonic-gate credible_events, waiting_events); 24147c478bd9Sstevel@tonic-gate if (credible_events + waiting_events < n) { 24157c478bd9Sstevel@tonic-gate /* Can never meet requirements */ 24167c478bd9Sstevel@tonic-gate indent(); 24177c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 24187c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 24197c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 24207c478bd9Sstevel@tonic-gate indent_pop(); 24217c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 24227c478bd9Sstevel@tonic-gate } 24237c478bd9Sstevel@tonic-gate if (credible_events < n) { /* will have to wait */ 24247c478bd9Sstevel@tonic-gate /* wait time is shortest known */ 24257c478bd9Sstevel@tonic-gate if (arrow_delay < overall_delay) 24267c478bd9Sstevel@tonic-gate overall_delay = arrow_delay; 24277c478bd9Sstevel@tonic-gate return_value = FME_WAIT; 24287c478bd9Sstevel@tonic-gate } 24297c478bd9Sstevel@tonic-gate } else { 24307c478bd9Sstevel@tonic-gate indent(); 24317c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " Mark was set: "); 24327c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 24337c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to"); 24347c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 24357c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 24367c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 24377c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, 24387c478bd9Sstevel@tonic-gate ap->arrowp->head->myevent); 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 24417c478bd9Sstevel@tonic-gate } 24427c478bd9Sstevel@tonic-gate } 24437c478bd9Sstevel@tonic-gate 24447c478bd9Sstevel@tonic-gate /* 24457c478bd9Sstevel@tonic-gate * evaluate constraints for ctlist, which is the list of 24467c478bd9Sstevel@tonic-gate * constraints for the arrow pointing into this node of the tree 24477c478bd9Sstevel@tonic-gate */ 24487c478bd9Sstevel@tonic-gate if (return_value == FME_CREDIBLE && arrowp != NULL) { 24497c478bd9Sstevel@tonic-gate struct constraintlist *ctp; 24507c478bd9Sstevel@tonic-gate struct evalue value; 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate platform_set_payloadnvp(ep->nvp); 24537c478bd9Sstevel@tonic-gate for (ctp = arrowp->constraints; ctp != NULL; 24547c478bd9Sstevel@tonic-gate ctp = ctp->next) { 24557c478bd9Sstevel@tonic-gate if (eval_expr(ctp->cnode, NULL, NULL, &fmep->globals, 24567c478bd9Sstevel@tonic-gate fmep->cfgdata->cooked, arrowp, 0, &value) == 0 || 24577c478bd9Sstevel@tonic-gate value.t == UNDEFINED || value.v == 0) { 24587c478bd9Sstevel@tonic-gate indent(); 24597c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 24607c478bd9Sstevel@tonic-gate " False constraint "); 24617c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 24627c478bd9Sstevel@tonic-gate ptree(O_ALTFP|O_VERB|O_NONL, 24637c478bd9Sstevel@tonic-gate ctp->cnode, 1, 0); 24647c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 24657c478bd9Sstevel@tonic-gate return_value = FME_DISPROVED; 24667c478bd9Sstevel@tonic-gate break; 24677c478bd9Sstevel@tonic-gate } 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate platform_set_payloadnvp(NULL); 24707c478bd9Sstevel@tonic-gate } 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate if (return_value == FME_WAIT) 24737c478bd9Sstevel@tonic-gate *pdelay = overall_delay; 24747c478bd9Sstevel@tonic-gate indent(); 24757c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-%s ", fme_state2str(return_value)); 24767c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 24777c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 24787c478bd9Sstevel@tonic-gate indent_pop(); 24797c478bd9Sstevel@tonic-gate return (return_value); 24807c478bd9Sstevel@tonic-gate } 24817c478bd9Sstevel@tonic-gate 24827c478bd9Sstevel@tonic-gate static enum fme_state 24837c478bd9Sstevel@tonic-gate causes_test(struct fme *fmep, struct event *ep, 24847c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay) 24857c478bd9Sstevel@tonic-gate { 24867c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 24877c478bd9Sstevel@tonic-gate unsigned long long my_delay; 24887c478bd9Sstevel@tonic-gate int credible_results = 0; 24897c478bd9Sstevel@tonic-gate int waiting_results = 0; 24907c478bd9Sstevel@tonic-gate enum fme_state fstate; 24917c478bd9Sstevel@tonic-gate struct event *tail_event; 24927c478bd9Sstevel@tonic-gate struct bubble *bp; 24937c478bd9Sstevel@tonic-gate struct arrowlist *ap; 24947c478bd9Sstevel@tonic-gate int k = 1; 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Ccallcount); 24977c478bd9Sstevel@tonic-gate indent_push(" C"); 24987c478bd9Sstevel@tonic-gate indent(); 24997c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 25007c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 25017c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate for (bp = itree_next_bubble(ep, NULL); bp; 25047c478bd9Sstevel@tonic-gate bp = itree_next_bubble(ep, bp)) { 25057c478bd9Sstevel@tonic-gate if (bp->t != B_TO) 25067c478bd9Sstevel@tonic-gate continue; 25077c478bd9Sstevel@tonic-gate k = bp->nork; /* remember the K value */ 25087c478bd9Sstevel@tonic-gate for (ap = itree_next_arrow(bp, NULL); ap; 25097c478bd9Sstevel@tonic-gate ap = itree_next_arrow(bp, ap)) { 25107c478bd9Sstevel@tonic-gate struct constraintlist *ctp; 25117c478bd9Sstevel@tonic-gate struct evalue value; 25127c478bd9Sstevel@tonic-gate int do_not_follow = 0; 25137c478bd9Sstevel@tonic-gate /* 25147c478bd9Sstevel@tonic-gate * see if false constraint prevents us 25157c478bd9Sstevel@tonic-gate * from traversing this arrow 25167c478bd9Sstevel@tonic-gate */ 25177c478bd9Sstevel@tonic-gate platform_set_payloadnvp(ep->nvp); 25187c478bd9Sstevel@tonic-gate for (ctp = ap->arrowp->constraints; 25197c478bd9Sstevel@tonic-gate ctp != NULL; ctp = ctp->next) { 25207c478bd9Sstevel@tonic-gate if (eval_expr(ctp->cnode, NULL, NULL, 25217c478bd9Sstevel@tonic-gate &fmep->globals, 25227c478bd9Sstevel@tonic-gate fmep->cfgdata->cooked, 25237c478bd9Sstevel@tonic-gate ap->arrowp, 0, 25247c478bd9Sstevel@tonic-gate &value) == 0 || 25257c478bd9Sstevel@tonic-gate value.t == UNDEFINED || 25267c478bd9Sstevel@tonic-gate value.v == 0) { 25277c478bd9Sstevel@tonic-gate do_not_follow = 1; 25287c478bd9Sstevel@tonic-gate break; 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate } 25317c478bd9Sstevel@tonic-gate platform_set_payloadnvp(NULL); 25327c478bd9Sstevel@tonic-gate if (do_not_follow) { 25337c478bd9Sstevel@tonic-gate indent(); 25347c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, 25357c478bd9Sstevel@tonic-gate " False arrow from "); 25367c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, 25377c478bd9Sstevel@tonic-gate ap->arrowp->tail->myevent); 25387c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " "); 25397c478bd9Sstevel@tonic-gate ptree(O_ALTFP|O_VERB|O_NONL, ctp->cnode, 1, 0); 25407c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 25417c478bd9Sstevel@tonic-gate continue; 25427c478bd9Sstevel@tonic-gate } 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate if (ap->arrowp->causes_tested++ > 0) { 25457c478bd9Sstevel@tonic-gate /* 25467c478bd9Sstevel@tonic-gate * get to this point if this is not the 25477c478bd9Sstevel@tonic-gate * first time we're going through this 25487c478bd9Sstevel@tonic-gate * arrow in the causes test. consider this 25497c478bd9Sstevel@tonic-gate * branch to be credible and let the 25507c478bd9Sstevel@tonic-gate * credible/noncredible outcome depend on 25517c478bd9Sstevel@tonic-gate * the other branches in this cycle. 25527c478bd9Sstevel@tonic-gate */ 25537c478bd9Sstevel@tonic-gate fstate = FME_CREDIBLE; 25547c478bd9Sstevel@tonic-gate } else { 25557c478bd9Sstevel@tonic-gate /* 25567c478bd9Sstevel@tonic-gate * get to this point if this is the first 25577c478bd9Sstevel@tonic-gate * time we're going through this arrow. 25587c478bd9Sstevel@tonic-gate */ 25597c478bd9Sstevel@tonic-gate tail_event = ap->arrowp->tail->myevent; 25607c478bd9Sstevel@tonic-gate fstate = hypothesise(fmep, tail_event, 25617c478bd9Sstevel@tonic-gate at_latest_by, 25627c478bd9Sstevel@tonic-gate &my_delay, ap->arrowp); 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate switch (fstate) { 25667c478bd9Sstevel@tonic-gate case FME_WAIT: 25677c478bd9Sstevel@tonic-gate if (my_delay < overall_delay) 25687c478bd9Sstevel@tonic-gate overall_delay = my_delay; 25697c478bd9Sstevel@tonic-gate waiting_results++; 25707c478bd9Sstevel@tonic-gate break; 25717c478bd9Sstevel@tonic-gate case FME_CREDIBLE: 25727c478bd9Sstevel@tonic-gate credible_results++; 25737c478bd9Sstevel@tonic-gate break; 25747c478bd9Sstevel@tonic-gate case FME_DISPROVED: 25757c478bd9Sstevel@tonic-gate break; 25767c478bd9Sstevel@tonic-gate default: 25777c478bd9Sstevel@tonic-gate out(O_DIE, "Bug in causes_test"); 25787c478bd9Sstevel@tonic-gate } 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate ap->arrowp->causes_tested--; 25817c478bd9Sstevel@tonic-gate ASSERT(ap->arrowp->causes_tested >= 0); 25827c478bd9Sstevel@tonic-gate } 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate /* compare against K */ 25857c478bd9Sstevel@tonic-gate if (credible_results + waiting_results < k) { 25867c478bd9Sstevel@tonic-gate indent(); 25877c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 25887c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 25897c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 25907c478bd9Sstevel@tonic-gate indent_pop(); 25917c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate if (waiting_results != 0) { 25947c478bd9Sstevel@tonic-gate *pdelay = overall_delay; 25957c478bd9Sstevel@tonic-gate indent(); 25967c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-WAIT "); 25977c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 25987c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 25997c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 26007c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 26017c478bd9Sstevel@tonic-gate indent_pop(); 26027c478bd9Sstevel@tonic-gate return (FME_WAIT); 26037c478bd9Sstevel@tonic-gate } 26047c478bd9Sstevel@tonic-gate indent(); 26057c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-CREDIBLE "); 26067c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26077c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 26087c478bd9Sstevel@tonic-gate indent_pop(); 26097c478bd9Sstevel@tonic-gate return (FME_CREDIBLE); 26107c478bd9Sstevel@tonic-gate } 26117c478bd9Sstevel@tonic-gate 26127c478bd9Sstevel@tonic-gate static enum fme_state 26137c478bd9Sstevel@tonic-gate hypothesise(struct fme *fmep, struct event *ep, 26147c478bd9Sstevel@tonic-gate unsigned long long at_latest_by, unsigned long long *pdelay, 26157c478bd9Sstevel@tonic-gate struct arrow *arrowp) 26167c478bd9Sstevel@tonic-gate { 26177c478bd9Sstevel@tonic-gate enum fme_state rtr, otr; 26187c478bd9Sstevel@tonic-gate unsigned long long my_delay; 26197c478bd9Sstevel@tonic-gate unsigned long long overall_delay = TIMEVAL_EVENTUALLY; 26207c478bd9Sstevel@tonic-gate 26217c478bd9Sstevel@tonic-gate stats_counter_bump(fmep->Hcallcount); 26227c478bd9Sstevel@tonic-gate indent_push(" H"); 26237c478bd9Sstevel@tonic-gate indent(); 26247c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "->"); 26257c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26267c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, ", at latest by: "); 26277c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &at_latest_by); 26287c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 26297c478bd9Sstevel@tonic-gate 26307c478bd9Sstevel@tonic-gate rtr = requirements_test(fmep, ep, at_latest_by, &my_delay, arrowp); 26317c478bd9Sstevel@tonic-gate mark_arrows(fmep, ep, 0); /* clean up after requirements test */ 26327c478bd9Sstevel@tonic-gate if ((rtr == FME_WAIT) && (my_delay < overall_delay)) 26337c478bd9Sstevel@tonic-gate overall_delay = my_delay; 26347c478bd9Sstevel@tonic-gate if (rtr != FME_DISPROVED) { 26357c478bd9Sstevel@tonic-gate if (is_problem(ep->t)) { 26367c478bd9Sstevel@tonic-gate otr = effects_test(fmep, ep); 26377c478bd9Sstevel@tonic-gate if (otr != FME_DISPROVED) { 26387c478bd9Sstevel@tonic-gate if (fmep->peek == 0 && ep->is_suspect++ == 0) { 26397c478bd9Sstevel@tonic-gate ep->suspects = fmep->suspects; 26407c478bd9Sstevel@tonic-gate fmep->suspects = ep; 26417c478bd9Sstevel@tonic-gate fmep->nsuspects++; 26427c478bd9Sstevel@tonic-gate if (!is_fault(ep->t)) 26437c478bd9Sstevel@tonic-gate fmep->nonfault++; 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate } 26467c478bd9Sstevel@tonic-gate } else 26477c478bd9Sstevel@tonic-gate otr = causes_test(fmep, ep, at_latest_by, &my_delay); 26487c478bd9Sstevel@tonic-gate if ((otr == FME_WAIT) && (my_delay < overall_delay)) 26497c478bd9Sstevel@tonic-gate overall_delay = my_delay; 26507c478bd9Sstevel@tonic-gate if ((otr != FME_DISPROVED) && 26517c478bd9Sstevel@tonic-gate ((rtr == FME_WAIT) || (otr == FME_WAIT))) 26527c478bd9Sstevel@tonic-gate *pdelay = overall_delay; 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate if (rtr == FME_DISPROVED) { 26557c478bd9Sstevel@tonic-gate indent(); 26567c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 26577c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26587c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (doesn't meet requirements)"); 26597c478bd9Sstevel@tonic-gate indent_pop(); 26607c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 26617c478bd9Sstevel@tonic-gate } 26627c478bd9Sstevel@tonic-gate if ((otr == FME_DISPROVED) && is_problem(ep->t)) { 26637c478bd9Sstevel@tonic-gate indent(); 26647c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 26657c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26667c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (doesn't explain all reports)"); 26677c478bd9Sstevel@tonic-gate indent_pop(); 26687c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 26697c478bd9Sstevel@tonic-gate } 26707c478bd9Sstevel@tonic-gate if (otr == FME_DISPROVED) { 26717c478bd9Sstevel@tonic-gate indent(); 26727c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-DISPROVED "); 26737c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26747c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, " (causes are not credible)"); 26757c478bd9Sstevel@tonic-gate indent_pop(); 26767c478bd9Sstevel@tonic-gate return (FME_DISPROVED); 26777c478bd9Sstevel@tonic-gate } 26787c478bd9Sstevel@tonic-gate if ((rtr == FME_WAIT) || (otr == FME_WAIT)) { 26797c478bd9Sstevel@tonic-gate indent(); 26807c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-WAIT "); 26817c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26827c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, " to "); 26837c478bd9Sstevel@tonic-gate ptree_timeval(O_ALTFP|O_VERB|O_NONL, &overall_delay); 26847c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 26857c478bd9Sstevel@tonic-gate indent_pop(); 26867c478bd9Sstevel@tonic-gate return (FME_WAIT); 26877c478bd9Sstevel@tonic-gate } 26887c478bd9Sstevel@tonic-gate indent(); 26897c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB|O_NONL, "<-CREDIBLE "); 26907c478bd9Sstevel@tonic-gate itree_pevent_brief(O_ALTFP|O_VERB|O_NONL, ep); 26917c478bd9Sstevel@tonic-gate out(O_ALTFP|O_VERB, NULL); 26927c478bd9Sstevel@tonic-gate indent_pop(); 26937c478bd9Sstevel@tonic-gate return (FME_CREDIBLE); 26947c478bd9Sstevel@tonic-gate } 2695