4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
29 #include <fm/fmd_api.h>
30 #include <libnvpair.h>
31 #include <fm/libtopo.h>
52 * eversholt diagnosis engine (eft.so) main entry points
55 fmd_hdl_t
*Hdl
; /* handle in global for platform.c */
57 int Debug
= 1; /* turn on here and let fmd_hdl_debug() decide if really on */
58 hrtime_t Hesitate
; /* hesitation time in ns */
59 char *Serd_Override
; /* override for Serd engines */
62 int Warn
; /* zero -- eft.so should not issue language warnings */
64 int Max_fme
; /* Maximum number of open FMEs */
66 /* stuff exported by yacc-generated parsers */
67 extern void yyparse(void);
70 extern struct lut
*Dicts
;
72 extern void literals_init(void);
73 extern void literals_fini(void);
77 void (*hdlr
)(fmd_hdl_t
*, fmd_event_t
*, nvlist_t
*, const char *);
79 { "ereport.", fme_receive_external_report
},
80 { "list.repaired", fme_receive_repair_list
},
86 eft_recv(fmd_hdl_t
*hdl
, fmd_event_t
*ep
, nvlist_t
*nvl
, const char *class)
88 struct eftsubr
*sp
= eftsubrs
;
90 while (sp
->prefix
!= NULL
) {
91 if (strncmp(class, sp
->prefix
, strlen(sp
->prefix
)) == 0)
96 if (sp
->prefix
!= NULL
) {
97 (sp
->hdlr
)(hdl
, ep
, nvl
, class);
100 "eft_recv: event class \"%s\" does not match our "
101 "subscriptions", class);
107 eft_timeout(fmd_hdl_t
*hdl
, id_t tid
, void *arg
)
110 "\neft.so timer %ld fired with arg %p", tid
, arg
);
115 fme_timer_fired(arg
, tid
);
119 eft_close(fmd_hdl_t
*hdl
, fmd_case_t
*fmcase
)
121 out(O_ALTFP
, "eft_close called for case %s",
122 fmd_case_uuid(hdl
, fmcase
));
123 fme_close_case(hdl
, fmcase
);
127 * The "serd_override" property allows the N and T parameters of specified serd
128 * engines to be overridden. The property is a string consisting of one or more
129 * space separated triplets. Each triplet is of the form "name,N,T" where "name"
130 * is the name of the serd engine and N and T are the new paremeters to use.
131 * For example "serd.io.device.nonfatal,5,3h" would set the parameters for the
132 * serd.io.device.nonfatal engine to 5 in 3 hours.
134 static const fmd_prop_t eft_props
[] = {
135 { "estats", FMD_TYPE_BOOL
, "false" },
136 { "hesitate", FMD_TYPE_INT64
, "10000000000" },
137 { "serd_override", FMD_TYPE_STRING
, NULL
},
138 { "verbose", FMD_TYPE_INT32
, "0" },
139 { "warn", FMD_TYPE_BOOL
, "false" },
140 { "status", FMD_TYPE_STRING
, NULL
},
141 { "maxfme", FMD_TYPE_INT32
, "0" },
147 eft_topo_change(fmd_hdl_t
*hdl
, topo_hdl_t
*thp
)
149 fme_receive_topology_change();
152 static const fmd_hdl_ops_t eft_ops
= {
153 eft_recv
, /* fmdo_recv */
154 eft_timeout
, /* fmdo_timeout */
155 eft_close
, /* fmdo_close */
156 NULL
, /* fmdo_stats */
158 NULL
, /* fmdo_send */
159 eft_topo_change
/* fmdo_topo_change */
162 #define xstr(s) str(s)
165 static const fmd_hdl_info_t fmd_info
= {
166 "eft diagnosis engine",
167 xstr(VERSION_MAJOR
) "." xstr(VERSION_MINOR
),
172 * ename_strdup -- like strdup but ename comes in and class string goes out
175 ename_strdup(struct node
*np
)
181 /* calculate length of buffer required */
183 for (mynp
= np
; mynp
; mynp
= mynp
->u
.name
.next
)
184 len
+= strlen(mynp
->u
.name
.s
) + 1; /* +1 for dot or NULL */
189 /* now build the string */
191 (void) strcat(buf
, np
->u
.name
.s
);
192 np
= np
->u
.name
.next
;
194 (void) strcat(buf
, ".");
202 dosubscribe(struct node
*lhs
, struct node
*rhs
, void *arg
)
204 char *ename
= ename_strdup(lhs
);
206 fmd_hdl_subscribe(Hdl
, ename
);
212 dodiscardprint(struct node
*lhs
, struct node
*rhs
, void *arg
)
214 char *ename
= (char *)lhs
;
216 out(O_VERB
, "allow silent discard_if_config_unknown: \"%s\"", ename
);
219 extern struct stats
*Filecount
;
222 * Call all of the _fini() routines to clean up the exiting DE
227 platform_free_eft_files(Efts
);
249 doopendict(const char *lhs
, void *rhs
, void *arg
)
251 out(O_VERB
, "opendict: \"%s\"", lhs
);
252 fmd_hdl_opendict(Hdl
, lhs
);
256 _fmd_init(fmd_hdl_t
*hdl
)
258 fmd_case_t
*casep
= NULL
;
262 (void) fmd_hdl_register(hdl
, FMD_API_VERSION
, &fmd_info
);
264 /* keep handle for routines like out() which need it */
267 /* set up out(O_ALTFP) first things so it is available for debug */
270 if ((fname
= fmd_prop_get_string(hdl
, "status")) != NULL
) {
273 if ((fp
= fopen(fname
, "a")) == NULL
) {
274 fmd_prop_free_string(hdl
, fname
);
275 out(O_DIE
|O_SYS
, "status property file: %s", fname
);
278 (void) setlinebuf(fp
);
281 out(O_DEBUG
, "appending status changes to \"%s\"", fname
);
282 fmd_prop_free_string(hdl
, fname
);
284 out(O_ALTFP
|O_STAMP
, "\neft.so startup");
288 Estats
= fmd_prop_get_int32(hdl
, "estats");
298 Efts
= platform_get_eft_files();
299 lex_init(Efts
, NULL
, 0);
303 * If we read no .eft files, we can't do any
304 * diagnosing, so we just unload ourselves
306 if (stats_counter_value(Filecount
) == 0) {
309 fmd_hdl_debug(hdl
, "no fault trees provided.");
310 fmd_hdl_unregister(hdl
);
317 if (count
= out_errcount())
318 out(O_DIE
, "%d language error%s encountered, exiting.",
321 /* subscribe to events we expect to consume */
322 lut_walk(Ereportenames
, (lut_cb
)dosubscribe
, NULL
);
323 lut_walk(Ereportenames_discard
, (lut_cb
)dodiscardprint
, NULL
);
325 /* subscribe to repair events so we can clear state on repair */
326 fmd_hdl_subscribe(hdl
, "list.repaired");
328 /* open dictionaries referenced by all .eft files */
329 lut_walk(Dicts
, (lut_cb
)doopendict
, NULL
);
331 Verbose
= fmd_prop_get_int32(hdl
, "verbose");
332 Warn
= fmd_prop_get_int32(hdl
, "warn");
333 Hesitate
= fmd_prop_get_int64(hdl
, "hesitate");
334 Serd_Override
= fmd_prop_get_string(hdl
, "serd_override");
335 Max_fme
= fmd_prop_get_int32(hdl
, "maxfme");
337 out(O_DEBUG
, "initialized, verbose %d warn %d maxfme %d",
338 Verbose
, Warn
, Max_fme
);
343 out(O_VERB
, "reconstituting any existing fmes");
344 while ((casep
= fmd_case_next(hdl
, casep
)) != NULL
) {
345 fme_restart(hdl
, casep
);
351 _fmd_fini(fmd_hdl_t
*hdl
)