1*4582Scth /*
2*4582Scth * CDDL HEADER START
3*4582Scth *
4*4582Scth * The contents of this file are subject to the terms of the
5*4582Scth * Common Development and Distribution License (the "License").
6*4582Scth * You may not use this file except in compliance with the License.
7*4582Scth *
8*4582Scth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4582Scth * or http://www.opensolaris.org/os/licensing.
10*4582Scth * See the License for the specific language governing permissions
11*4582Scth * and limitations under the License.
12*4582Scth *
13*4582Scth * When distributing Covered Code, include this CDDL HEADER in each
14*4582Scth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4582Scth * If applicable, add the following below this CDDL HEADER, with the
16*4582Scth * fields enclosed by brackets "[]" replaced with your own identifying
17*4582Scth * information: Portions Copyright [yyyy] [name of copyright owner]
18*4582Scth *
19*4582Scth * CDDL HEADER END
20*4582Scth */
21*4582Scth
22*4582Scth /*
23*4582Scth * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24*4582Scth * Use is subject to license terms.
25*4582Scth */
26*4582Scth
27*4582Scth #pragma ident "%Z%%M% %I% %E% SMI"
28*4582Scth
29*4582Scth /*
30*4582Scth * Disk & Indicator Monitor configuration file support routines
31*4582Scth */
32*4582Scth
33*4582Scth #include <sys/types.h>
34*4582Scth #include <sys/stat.h>
35*4582Scth #include <fcntl.h>
36*4582Scth #include <unistd.h>
37*4582Scth #include <string.h>
38*4582Scth #include <strings.h>
39*4582Scth #include <errno.h>
40*4582Scth #include <limits.h>
41*4582Scth #include <pthread.h>
42*4582Scth
43*4582Scth #include "disk_monitor.h"
44*4582Scth #include "util.h"
45*4582Scth #include "topo_gather.h"
46*4582Scth
47*4582Scth extern log_class_t g_verbose;
48*4582Scth
49*4582Scth const char *
hotplug_state_string(hotplug_state_t state)50*4582Scth hotplug_state_string(hotplug_state_t state)
51*4582Scth {
52*4582Scth switch (state & ~HPS_FAULTED) {
53*4582Scth default:
54*4582Scth case HPS_UNKNOWN:
55*4582Scth return ("Unknown");
56*4582Scth case HPS_ABSENT:
57*4582Scth return ("Absent");
58*4582Scth case HPS_PRESENT:
59*4582Scth return ("Present");
60*4582Scth case HPS_CONFIGURED:
61*4582Scth return ("Configured");
62*4582Scth case HPS_UNCONFIGURED:
63*4582Scth return ("Unconfigured");
64*4582Scth }
65*4582Scth }
66*4582Scth
67*4582Scth void
conf_error_msg(conf_err_t err,char * buf,int buflen,void * arg)68*4582Scth conf_error_msg(conf_err_t err, char *buf, int buflen, void *arg)
69*4582Scth {
70*4582Scth switch (err) {
71*4582Scth case E_MULTIPLE_IND_LISTS_DEFINED:
72*4582Scth (void) snprintf(buf, buflen, "Multiple Indicator lists "
73*4582Scth "defined");
74*4582Scth break;
75*4582Scth case E_MULTIPLE_INDRULE_LISTS_DEFINED:
76*4582Scth (void) snprintf(buf, buflen, "Multiple Indicator rule lists "
77*4582Scth "defined");
78*4582Scth break;
79*4582Scth case E_INVALID_STATE_CHANGE:
80*4582Scth (void) snprintf(buf, buflen, "Invalid state change");
81*4582Scth break;
82*4582Scth case E_IND_MULTIPLY_DEFINED:
83*4582Scth (void) snprintf(buf, buflen,
84*4582Scth "Multiple Indicator definitions (name & state) detected");
85*4582Scth break;
86*4582Scth case E_IND_ACTION_REDUNDANT:
87*4582Scth (void) snprintf(buf, buflen, "Redundant Indicator actions "
88*4582Scth "specified");
89*4582Scth break;
90*4582Scth case E_IND_ACTION_CONFLICT:
91*4582Scth (void) snprintf(buf, buflen, "Indicator action conflict (+/- "
92*4582Scth "same Indicator) found");
93*4582Scth break;
94*4582Scth case E_IND_MISSING_FAULT_ON:
95*4582Scth (void) snprintf(buf, buflen, "Missing declaration of `+"
96*4582Scth INDICATOR_FAULT_IDENTIFIER "'");
97*4582Scth break;
98*4582Scth case E_IND_MISSING_FAULT_OFF:
99*4582Scth (void) snprintf(buf, buflen, "Missing declaration of `-"
100*4582Scth INDICATOR_FAULT_IDENTIFIER "'");
101*4582Scth break;
102*4582Scth case E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION:
103*4582Scth (void) snprintf(buf, buflen, "`%c%s': Undefined Indicator in "
104*4582Scth BAY_IND_ACTION " property",
105*4582Scth (((ind_action_t *)arg)->ind_state == INDICATOR_ON)
106*4582Scth ? '+' : '-',
107*4582Scth ((ind_action_t *)arg)->ind_name);
108*4582Scth break;
109*4582Scth case E_DUPLICATE_STATE_TRANSITION:
110*4582Scth (void) snprintf(buf, buflen, "Duplicate state transition "
111*4582Scth "(%s -> %s)",
112*4582Scth hotplug_state_string(((state_transition_t *)arg)->begin),
113*4582Scth hotplug_state_string(((state_transition_t *)arg)->end));
114*4582Scth break;
115*4582Scth default:
116*4582Scth (void) snprintf(buf, buflen, "Unknown error");
117*4582Scth break;
118*4582Scth }
119*4582Scth }
120*4582Scth
121*4582Scth static int
string_to_integer(const char * prop,int * value)122*4582Scth string_to_integer(const char *prop, int *value)
123*4582Scth {
124*4582Scth long val;
125*4582Scth
126*4582Scth errno = 0;
127*4582Scth
128*4582Scth val = strtol(prop, NULL, 0);
129*4582Scth
130*4582Scth if (val == 0 && errno != 0)
131*4582Scth return (-1);
132*4582Scth else if (val > INT_MAX || val < INT_MIN) {
133*4582Scth errno = ERANGE;
134*4582Scth return (-1);
135*4582Scth }
136*4582Scth
137*4582Scth if (value != NULL)
138*4582Scth *value = (int)val;
139*4582Scth
140*4582Scth return (0);
141*4582Scth }
142*4582Scth
143*4582Scth const char *
dm_prop_lookup(nvlist_t * props,const char * prop_name)144*4582Scth dm_prop_lookup(nvlist_t *props, const char *prop_name)
145*4582Scth {
146*4582Scth char *str;
147*4582Scth
148*4582Scth if (nvlist_lookup_string(props, prop_name, &str) == 0)
149*4582Scth return ((const char *)str);
150*4582Scth else
151*4582Scth return (NULL);
152*4582Scth }
153*4582Scth
154*4582Scth int
dm_prop_lookup_int(nvlist_t * props,const char * prop_name,int * value)155*4582Scth dm_prop_lookup_int(nvlist_t *props, const char *prop_name, int *value)
156*4582Scth {
157*4582Scth const char *prop = dm_prop_lookup(props, prop_name);
158*4582Scth
159*4582Scth if (prop == NULL)
160*4582Scth return (-1);
161*4582Scth
162*4582Scth return (string_to_integer(prop, value));
163*4582Scth }
164*4582Scth
165*4582Scth nvlist_t *
namevalpr_to_nvlist(namevalpr_t * nvprp)166*4582Scth namevalpr_to_nvlist(namevalpr_t *nvprp)
167*4582Scth {
168*4582Scth nvlist_t *nvlp = NULL;
169*4582Scth
170*4582Scth if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0) != 0) {
171*4582Scth return (NULL);
172*4582Scth }
173*4582Scth
174*4582Scth if (nvlist_add_string(nvlp, nvprp->name, nvprp->value) != 0) {
175*4582Scth nvlist_free(nvlp);
176*4582Scth return (NULL);
177*4582Scth }
178*4582Scth
179*4582Scth return (nvlp);
180*4582Scth }
181*4582Scth
182*4582Scth indicator_t *
new_indicator(ind_state_t lstate,char * namep,char * actionp)183*4582Scth new_indicator(ind_state_t lstate, char *namep, char *actionp)
184*4582Scth {
185*4582Scth indicator_t *newindicator =
186*4582Scth (indicator_t *)dmalloc(sizeof (indicator_t));
187*4582Scth newindicator->ind_state = lstate;
188*4582Scth newindicator->ind_name = namep ? dstrdup(namep) : NULL;
189*4582Scth newindicator->ind_instr_spec = actionp ? dstrdup(actionp) : NULL;
190*4582Scth newindicator->next = NULL;
191*4582Scth return (newindicator);
192*4582Scth }
193*4582Scth
194*4582Scth void
link_indicator(indicator_t ** first,indicator_t * to_add)195*4582Scth link_indicator(indicator_t **first, indicator_t *to_add)
196*4582Scth {
197*4582Scth indicator_t *travptr;
198*4582Scth dm_assert(first != NULL);
199*4582Scth
200*4582Scth if (*first == NULL)
201*4582Scth *first = to_add;
202*4582Scth else {
203*4582Scth travptr = *first;
204*4582Scth while (travptr->next != NULL) {
205*4582Scth travptr = travptr->next;
206*4582Scth }
207*4582Scth travptr->next = to_add;
208*4582Scth }
209*4582Scth }
210*4582Scth
211*4582Scth void
ind_free(indicator_t * indp)212*4582Scth ind_free(indicator_t *indp)
213*4582Scth {
214*4582Scth indicator_t *nextp;
215*4582Scth
216*4582Scth while (indp != NULL) {
217*4582Scth nextp = indp->next;
218*4582Scth if (indp->ind_name)
219*4582Scth dstrfree(indp->ind_name);
220*4582Scth if (indp->ind_instr_spec)
221*4582Scth dstrfree(indp->ind_instr_spec);
222*4582Scth dfree(indp, sizeof (indicator_t));
223*4582Scth indp = nextp;
224*4582Scth }
225*4582Scth }
226*4582Scth
227*4582Scth ind_action_t *
new_indaction(ind_state_t state,char * namep)228*4582Scth new_indaction(ind_state_t state, char *namep)
229*4582Scth {
230*4582Scth ind_action_t *lap = (ind_action_t *)dmalloc(sizeof (ind_action_t));
231*4582Scth lap->ind_state = state;
232*4582Scth lap->ind_name = namep ? dstrdup(namep) : NULL;
233*4582Scth lap->next = NULL;
234*4582Scth return (lap);
235*4582Scth }
236*4582Scth
237*4582Scth void
link_indaction(ind_action_t ** first,ind_action_t * to_add)238*4582Scth link_indaction(ind_action_t **first, ind_action_t *to_add)
239*4582Scth {
240*4582Scth ind_action_t *travptr;
241*4582Scth dm_assert(first != NULL);
242*4582Scth
243*4582Scth if (*first == NULL)
244*4582Scth *first = to_add;
245*4582Scth else {
246*4582Scth travptr = *first;
247*4582Scth while (travptr->next != NULL) {
248*4582Scth travptr = travptr->next;
249*4582Scth }
250*4582Scth travptr->next = to_add;
251*4582Scth }
252*4582Scth }
253*4582Scth
254*4582Scth void
indaction_free(ind_action_t * lap)255*4582Scth indaction_free(ind_action_t *lap)
256*4582Scth {
257*4582Scth ind_action_t *nextp;
258*4582Scth
259*4582Scth /* Free the whole list */
260*4582Scth while (lap != NULL) {
261*4582Scth nextp = lap->next;
262*4582Scth if (lap->ind_name)
263*4582Scth dstrfree(lap->ind_name);
264*4582Scth dfree(lap, sizeof (ind_action_t));
265*4582Scth lap = nextp;
266*4582Scth }
267*4582Scth }
268*4582Scth
269*4582Scth indrule_t *
new_indrule(state_transition_t * st,ind_action_t * actionp)270*4582Scth new_indrule(state_transition_t *st, ind_action_t *actionp)
271*4582Scth {
272*4582Scth indrule_t *lrp = (indrule_t *)dmalloc(sizeof (indrule_t));
273*4582Scth if (st != NULL)
274*4582Scth lrp->strans = *st;
275*4582Scth lrp->action_list = actionp;
276*4582Scth lrp->next = NULL;
277*4582Scth return (lrp);
278*4582Scth }
279*4582Scth
280*4582Scth void
link_indrule(indrule_t ** first,indrule_t * to_add)281*4582Scth link_indrule(indrule_t **first, indrule_t *to_add)
282*4582Scth {
283*4582Scth indrule_t *travptr;
284*4582Scth dm_assert(first != NULL);
285*4582Scth
286*4582Scth if (*first == NULL)
287*4582Scth *first = to_add;
288*4582Scth else {
289*4582Scth travptr = *first;
290*4582Scth while (travptr->next != NULL) {
291*4582Scth travptr = travptr->next;
292*4582Scth }
293*4582Scth travptr->next = to_add;
294*4582Scth }
295*4582Scth }
296*4582Scth
297*4582Scth void
indrule_free(indrule_t * lrp)298*4582Scth indrule_free(indrule_t *lrp)
299*4582Scth {
300*4582Scth indrule_t *nextp;
301*4582Scth
302*4582Scth /* Free the whole list */
303*4582Scth while (lrp != NULL) {
304*4582Scth nextp = lrp->next;
305*4582Scth if (lrp->action_list)
306*4582Scth indaction_free(lrp->action_list);
307*4582Scth dfree(lrp, sizeof (indrule_t));
308*4582Scth lrp = nextp;
309*4582Scth }
310*4582Scth }
311*4582Scth
312*4582Scth dm_fru_t *
new_dmfru(char * manu,char * modl,char * firmrev,char * serno,uint64_t capa)313*4582Scth new_dmfru(char *manu, char *modl, char *firmrev, char *serno, uint64_t capa)
314*4582Scth {
315*4582Scth dm_fru_t *frup = (dm_fru_t *)dzmalloc(sizeof (dm_fru_t));
316*4582Scth
317*4582Scth bcopy(manu, frup->manuf, MIN(sizeof (frup->manuf), strlen(manu) + 1));
318*4582Scth bcopy(modl, frup->model, MIN(sizeof (frup->model), strlen(modl) + 1));
319*4582Scth bcopy(firmrev, frup->rev, MIN(sizeof (frup->rev), strlen(firmrev) + 1));
320*4582Scth bcopy(serno, frup->serial,
321*4582Scth MIN(sizeof (frup->serial), strlen(serno) + 1));
322*4582Scth frup->size_in_bytes = capa;
323*4582Scth return (frup);
324*4582Scth }
325*4582Scth
326*4582Scth void
dmfru_free(dm_fru_t * frup)327*4582Scth dmfru_free(dm_fru_t *frup)
328*4582Scth {
329*4582Scth dfree(frup, sizeof (dm_fru_t));
330*4582Scth }
331*4582Scth
332*4582Scth diskmon_t *
new_diskmon(nvlist_t * app_props,indicator_t * indp,indrule_t * indrp,nvlist_t * nvlp)333*4582Scth new_diskmon(nvlist_t *app_props, indicator_t *indp, indrule_t *indrp,
334*4582Scth nvlist_t *nvlp)
335*4582Scth {
336*4582Scth diskmon_t *dmp = (diskmon_t *)dmalloc(sizeof (diskmon_t));
337*4582Scth
338*4582Scth if (nvlp != NULL)
339*4582Scth dmp->props = nvlp;
340*4582Scth else
341*4582Scth (void) nvlist_alloc(&dmp->props, NV_UNIQUE_NAME, 0);
342*4582Scth
343*4582Scth if (app_props)
344*4582Scth dmp->app_props = app_props;
345*4582Scth else
346*4582Scth (void) nvlist_alloc(&dmp->app_props, NV_UNIQUE_NAME, 0);
347*4582Scth dmp->ind_list = indp;
348*4582Scth dmp->indrule_list = indrp;
349*4582Scth
350*4582Scth dm_assert(pthread_mutex_init(&dmp->manager_mutex, NULL) == 0);
351*4582Scth
352*4582Scth dmp->state = HPS_UNKNOWN;
353*4582Scth
354*4582Scth dmp->initial_configuration = B_TRUE;
355*4582Scth
356*4582Scth dm_assert(pthread_mutex_init(&dmp->fault_indicator_mutex, NULL) == 0);
357*4582Scth dmp->fault_indicator_state = INDICATOR_UNKNOWN;
358*4582Scth
359*4582Scth dmp->configured_yet = B_FALSE;
360*4582Scth dmp->state_change_count = 0;
361*4582Scth
362*4582Scth dm_assert(pthread_mutex_init(&dmp->fru_mutex, NULL) == 0);
363*4582Scth dmp->frup = NULL;
364*4582Scth
365*4582Scth dmp->next = NULL;
366*4582Scth return (dmp);
367*4582Scth }
368*4582Scth
369*4582Scth void
diskmon_free(diskmon_t * dmp)370*4582Scth diskmon_free(diskmon_t *dmp)
371*4582Scth {
372*4582Scth diskmon_t *nextp;
373*4582Scth
374*4582Scth /* Free the whole list */
375*4582Scth while (dmp != NULL) {
376*4582Scth nextp = dmp->next;
377*4582Scth
378*4582Scth if (dmp->props)
379*4582Scth nvlist_free(dmp->props);
380*4582Scth if (dmp->location)
381*4582Scth dstrfree(dmp->location);
382*4582Scth if (dmp->ind_list)
383*4582Scth ind_free(dmp->ind_list);
384*4582Scth if (dmp->indrule_list)
385*4582Scth indrule_free(dmp->indrule_list);
386*4582Scth if (dmp->app_props)
387*4582Scth nvlist_free(dmp->app_props);
388*4582Scth if (dmp->frup)
389*4582Scth dmfru_free(dmp->frup);
390*4582Scth dfree(dmp, sizeof (diskmon_t));
391*4582Scth
392*4582Scth dmp = nextp;
393*4582Scth }
394*4582Scth }
395*4582Scth
396*4582Scth static cfgdata_t *
new_cfgdata(namevalpr_t * nvp,diskmon_t * dmp)397*4582Scth new_cfgdata(namevalpr_t *nvp, diskmon_t *dmp)
398*4582Scth {
399*4582Scth cfgdata_t *cdp = (cfgdata_t *)dzmalloc(sizeof (cfgdata_t));
400*4582Scth
401*4582Scth if (nvp != NULL)
402*4582Scth cdp->props = namevalpr_to_nvlist(nvp);
403*4582Scth else if (nvlist_alloc(&cdp->props, NV_UNIQUE_NAME, 0) != 0) {
404*4582Scth return (NULL);
405*4582Scth }
406*4582Scth
407*4582Scth if (dmp != NULL)
408*4582Scth cdp->disk_list = dmp;
409*4582Scth return (cdp);
410*4582Scth
411*4582Scth }
412*4582Scth
413*4582Scth static void
cfgdata_add_namevalpr(cfgdata_t * cfgp,namevalpr_t * nvp)414*4582Scth cfgdata_add_namevalpr(cfgdata_t *cfgp, namevalpr_t *nvp)
415*4582Scth {
416*4582Scth if (cfgp->props == NULL) {
417*4582Scth (void) nvlist_alloc(&cfgp->props, NV_UNIQUE_NAME, 0);
418*4582Scth }
419*4582Scth (void) nvlist_add_string(cfgp->props, nvp->name, nvp->value);
420*4582Scth }
421*4582Scth
422*4582Scth void
cfgdata_add_diskmon(cfgdata_t * cfgp,diskmon_t * dmp)423*4582Scth cfgdata_add_diskmon(cfgdata_t *cfgp, diskmon_t *dmp)
424*4582Scth {
425*4582Scth if (cfgp->disk_list == NULL) {
426*4582Scth cfgp->disk_list = dmp;
427*4582Scth } else {
428*4582Scth diskmon_t *disklist = cfgp->disk_list;
429*4582Scth
430*4582Scth while (disklist->next != NULL)
431*4582Scth disklist = disklist->next;
432*4582Scth
433*4582Scth disklist->next = dmp;
434*4582Scth }
435*4582Scth }
436*4582Scth
437*4582Scth static void
cfgdata_free(cfgdata_t * cdp)438*4582Scth cfgdata_free(cfgdata_t *cdp)
439*4582Scth {
440*4582Scth nvlist_free(cdp->props);
441*4582Scth diskmon_free(cdp->disk_list);
442*4582Scth dfree(cdp, sizeof (cfgdata_t));
443*4582Scth }
444*4582Scth
445*4582Scth conf_err_t
check_indactions(ind_action_t * indrp)446*4582Scth check_indactions(ind_action_t *indrp)
447*4582Scth {
448*4582Scth char *buf;
449*4582Scth conf_err_t rv = E_NO_ERROR;
450*4582Scth nvlist_t *nvp = NULL;
451*4582Scth int len;
452*4582Scth
453*4582Scth (void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
454*4582Scth
455*4582Scth /*
456*4582Scth * Check indicator actions for conflicts
457*4582Scth */
458*4582Scth while (indrp != NULL && rv == E_NO_ERROR) {
459*4582Scth len = strlen(indrp->ind_name) + 2;
460*4582Scth buf = dmalloc(len);
461*4582Scth (void) snprintf(buf, len, "%c%s",
462*4582Scth indrp->ind_state == INDICATOR_ON ? '+' : '-',
463*4582Scth indrp->ind_name);
464*4582Scth switch (nvlist_lookup_boolean(nvp, buf)) {
465*4582Scth case ENOENT:
466*4582Scth (void) nvlist_add_boolean(nvp, buf);
467*4582Scth break;
468*4582Scth case 0:
469*4582Scth rv = E_IND_ACTION_REDUNDANT;
470*4582Scth break;
471*4582Scth default:
472*4582Scth break;
473*4582Scth }
474*4582Scth
475*4582Scth /* Look for the opposite action. If found, that's an error */
476*4582Scth (void) snprintf(buf, len, "%c%s",
477*4582Scth indrp->ind_state == INDICATOR_ON ? '-' : '+',
478*4582Scth indrp->ind_name);
479*4582Scth switch (nvlist_lookup_boolean(nvp, buf)) {
480*4582Scth case ENOENT:
481*4582Scth break;
482*4582Scth case 0:
483*4582Scth rv = E_IND_ACTION_CONFLICT;
484*4582Scth break;
485*4582Scth default:
486*4582Scth break;
487*4582Scth }
488*4582Scth dfree(buf, len);
489*4582Scth indrp = indrp->next;
490*4582Scth }
491*4582Scth
492*4582Scth nvlist_free(nvp);
493*4582Scth return (rv);
494*4582Scth }
495*4582Scth
496*4582Scth conf_err_t
check_inds(indicator_t * indp)497*4582Scth check_inds(indicator_t *indp)
498*4582Scth {
499*4582Scth char *buf;
500*4582Scth conf_err_t rv = E_NO_ERROR;
501*4582Scth nvlist_t *nvp = NULL;
502*4582Scth int len;
503*4582Scth boolean_t fault_on = B_FALSE, fault_off = B_FALSE;
504*4582Scth
505*4582Scth (void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
506*4582Scth
507*4582Scth /*
508*4582Scth * Check inds for multiple definitions (same identifier or same action)
509*4582Scth */
510*4582Scth while (indp != NULL && rv == E_NO_ERROR) {
511*4582Scth len = strlen(indp->ind_name) + 2;
512*4582Scth buf = dmalloc(len);
513*4582Scth (void) snprintf(buf, len, "%c%s",
514*4582Scth indp->ind_state == INDICATOR_ON ? '+' : '-',
515*4582Scth indp->ind_name);
516*4582Scth
517*4582Scth /* Keep track of the +/-FAULT for checking later */
518*4582Scth if (strcasecmp(buf, "+" INDICATOR_FAULT_IDENTIFIER) == 0)
519*4582Scth fault_on = B_TRUE;
520*4582Scth else if (strcasecmp(buf, "-" INDICATOR_FAULT_IDENTIFIER) == 0)
521*4582Scth fault_off = B_TRUE;
522*4582Scth
523*4582Scth switch (nvlist_lookup_boolean(nvp, buf)) {
524*4582Scth case ENOENT:
525*4582Scth (void) nvlist_add_boolean(nvp, buf);
526*4582Scth break;
527*4582Scth case 0:
528*4582Scth rv = E_IND_MULTIPLY_DEFINED;
529*4582Scth break;
530*4582Scth default:
531*4582Scth break;
532*4582Scth }
533*4582Scth dfree(buf, len);
534*4582Scth indp = indp->next;
535*4582Scth }
536*4582Scth
537*4582Scth /*
538*4582Scth * Make sure we have a -FAULT and +FAULT
539*4582Scth */
540*4582Scth if (!fault_on)
541*4582Scth rv = E_IND_MISSING_FAULT_ON;
542*4582Scth else if (!fault_off)
543*4582Scth rv = E_IND_MISSING_FAULT_OFF;
544*4582Scth
545*4582Scth nvlist_free(nvp);
546*4582Scth return (rv);
547*4582Scth }
548*4582Scth
549*4582Scth conf_err_t
check_indrules(indrule_t * indrp,state_transition_t ** offender)550*4582Scth check_indrules(indrule_t *indrp, state_transition_t **offender)
551*4582Scth {
552*4582Scth char buf[32];
553*4582Scth conf_err_t rv = E_NO_ERROR;
554*4582Scth nvlist_t *nvp = NULL;
555*4582Scth
556*4582Scth /*
557*4582Scth * Ensure that no two rules have the same state transitions.
558*4582Scth */
559*4582Scth
560*4582Scth (void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
561*4582Scth
562*4582Scth while (indrp != NULL && rv == E_NO_ERROR) {
563*4582Scth (void) snprintf(buf, sizeof (buf), "%d-%d",
564*4582Scth (int)indrp->strans.begin, (int)indrp->strans.end);
565*4582Scth switch (nvlist_lookup_boolean(nvp, buf)) {
566*4582Scth case 0:
567*4582Scth *offender = &indrp->strans;
568*4582Scth rv = E_DUPLICATE_STATE_TRANSITION;
569*4582Scth break;
570*4582Scth case ENOENT:
571*4582Scth (void) nvlist_add_boolean(nvp, buf);
572*4582Scth break;
573*4582Scth default:
574*4582Scth break;
575*4582Scth }
576*4582Scth indrp = indrp->next;
577*4582Scth }
578*4582Scth
579*4582Scth nvlist_free(nvp);
580*4582Scth return (rv);
581*4582Scth }
582*4582Scth
583*4582Scth
584*4582Scth conf_err_t
check_consistent_ind_indrules(indicator_t * indp,indrule_t * indrp,ind_action_t ** offender)585*4582Scth check_consistent_ind_indrules(indicator_t *indp, indrule_t *indrp,
586*4582Scth ind_action_t **offender)
587*4582Scth {
588*4582Scth char *buf;
589*4582Scth conf_err_t rv = E_NO_ERROR;
590*4582Scth nvlist_t *nvp = NULL;
591*4582Scth ind_action_t *alp;
592*4582Scth int len;
593*4582Scth
594*4582Scth /*
595*4582Scth * Ensure that every indicator action referenced in each ruleset
596*4582Scth * exists in the indicator list given.
597*4582Scth */
598*4582Scth
599*4582Scth (void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
600*4582Scth
601*4582Scth while (indp != NULL) {
602*4582Scth len = strlen(indp->ind_name) + 2;
603*4582Scth buf = dmalloc(len);
604*4582Scth (void) snprintf(buf, len, "%c%s",
605*4582Scth indp->ind_state == INDICATOR_ON ? '+' : '-',
606*4582Scth indp->ind_name);
607*4582Scth (void) nvlist_add_boolean(nvp, buf);
608*4582Scth dfree(buf, len);
609*4582Scth indp = indp->next;
610*4582Scth }
611*4582Scth
612*4582Scth while (indrp != NULL && rv == E_NO_ERROR) {
613*4582Scth alp = indrp->action_list;
614*4582Scth while (alp != NULL && rv == E_NO_ERROR) {
615*4582Scth len = strlen(alp->ind_name) + 2;
616*4582Scth buf = dmalloc(len);
617*4582Scth (void) snprintf(buf, len, "%c%s",
618*4582Scth alp->ind_state == INDICATOR_ON ? '+' : '-',
619*4582Scth alp->ind_name);
620*4582Scth
621*4582Scth switch (nvlist_lookup_boolean(nvp, buf)) {
622*4582Scth case 0: /* Normal case */
623*4582Scth break;
624*4582Scth case ENOENT:
625*4582Scth *offender = alp;
626*4582Scth rv =
627*4582Scth E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION;
628*4582Scth break;
629*4582Scth default:
630*4582Scth break;
631*4582Scth }
632*4582Scth dfree(buf, len);
633*4582Scth alp = alp->next;
634*4582Scth }
635*4582Scth indrp = indrp->next;
636*4582Scth }
637*4582Scth
638*4582Scth nvlist_free(nvp);
639*4582Scth return (rv);
640*4582Scth }
641*4582Scth
642*4582Scth conf_err_t
check_state_transition(hotplug_state_t s1,hotplug_state_t s2)643*4582Scth check_state_transition(hotplug_state_t s1, hotplug_state_t s2)
644*4582Scth {
645*4582Scth /*
646*4582Scth * The following are valid transitions:
647*4582Scth *
648*4582Scth * HPS_ABSENT -> HPS_PRESENT
649*4582Scth * HPS_ABSENT -> HPS_CONFIGURED
650*4582Scth * HPS_PRESENT -> HPS_CONFIGURED
651*4582Scth * HPS_PRESENT -> HPS_ABSENT
652*4582Scth * HPS_CONFIGURED -> HPS_UNCONFIGURED
653*4582Scth * HPS_CONFIGURED -> HPS_ABSENT
654*4582Scth * HPS_UNCONFIGURED -> HPS_ABSENT
655*4582Scth * HPS_UNCONFIGURED -> HPS_CONFIGURED
656*4582Scth *
657*4582Scth */
658*4582Scth if (s1 == HPS_ABSENT && s2 != HPS_PRESENT && s2 != HPS_CONFIGURED)
659*4582Scth return (E_INVALID_STATE_CHANGE);
660*4582Scth else if (s1 == HPS_PRESENT && (s2 != HPS_CONFIGURED &&
661*4582Scth s2 != HPS_ABSENT))
662*4582Scth return (E_INVALID_STATE_CHANGE);
663*4582Scth else if (s1 == HPS_CONFIGURED && (s2 != HPS_UNCONFIGURED &&
664*4582Scth s2 != HPS_ABSENT))
665*4582Scth return (E_INVALID_STATE_CHANGE);
666*4582Scth else if (s1 == HPS_UNCONFIGURED && (s2 != HPS_ABSENT &&
667*4582Scth s2 != HPS_CONFIGURED))
668*4582Scth return (E_INVALID_STATE_CHANGE);
669*4582Scth else
670*4582Scth return (E_NO_ERROR);
671*4582Scth }
672*4582Scth
673*4582Scth static void
print_inds(indicator_t * indp,FILE * fp,char * prefix)674*4582Scth print_inds(indicator_t *indp, FILE *fp, char *prefix)
675*4582Scth {
676*4582Scth char plusminus;
677*4582Scth
678*4582Scth (void) fprintf(fp, "%sindicators {\n", prefix);
679*4582Scth while (indp != NULL) {
680*4582Scth plusminus = (indp->ind_state == INDICATOR_ON) ? '+' : '-';
681*4582Scth (void) fprintf(fp, "%s\t%c%s = \"%s\"\n", prefix, plusminus,
682*4582Scth indp->ind_name, indp->ind_instr_spec);
683*4582Scth indp = indp->next;
684*4582Scth }
685*4582Scth (void) fprintf(fp, "%s}\n", prefix);
686*4582Scth }
687*4582Scth
688*4582Scth static void
print_indrules(indrule_t * lrp,FILE * fp,char * prefix)689*4582Scth print_indrules(indrule_t *lrp, FILE *fp, char *prefix)
690*4582Scth {
691*4582Scth char plusminus;
692*4582Scth ind_action_t *lap;
693*4582Scth
694*4582Scth (void) fprintf(fp, "%sindicator_rules {\n", prefix);
695*4582Scth while (lrp != NULL) {
696*4582Scth (void) fprintf(fp, "%s\t%12s -> %12s\t{ ", prefix,
697*4582Scth hotplug_state_string(lrp->strans.begin),
698*4582Scth hotplug_state_string(lrp->strans.end));
699*4582Scth lap = lrp->action_list;
700*4582Scth while (lap != NULL) {
701*4582Scth plusminus = (lap->ind_state == INDICATOR_ON)
702*4582Scth ? '+' : '-';
703*4582Scth (void) fprintf(fp, "%c%s", plusminus, lap->ind_name);
704*4582Scth lap = lap->next;
705*4582Scth if (lap != NULL)
706*4582Scth (void) fprintf(fp, ", ");
707*4582Scth }
708*4582Scth (void) fprintf(fp, " }\n");
709*4582Scth lrp = lrp->next;
710*4582Scth }
711*4582Scth (void) fprintf(fp, "%s}\n", prefix);
712*4582Scth }
713*4582Scth
714*4582Scth static void
print_props(nvlist_t * nvlp,FILE * fp,char * prefix)715*4582Scth print_props(nvlist_t *nvlp, FILE *fp, char *prefix)
716*4582Scth {
717*4582Scth nvpair_t *nvp = nvlist_next_nvpair(nvlp, NULL);
718*4582Scth char *name, *str;
719*4582Scth
720*4582Scth while (nvp != NULL) {
721*4582Scth dm_assert(nvpair_type(nvp) == DATA_TYPE_STRING);
722*4582Scth name = nvpair_name(nvp);
723*4582Scth (void) nvlist_lookup_string(nvlp, name, &str);
724*4582Scth (void) fprintf(fp, "%s%s = \"%s\"\n", prefix, name, str);
725*4582Scth nvp = nvlist_next_nvpair(nvlp, nvp);
726*4582Scth }
727*4582Scth }
728*4582Scth
729*4582Scth static void
print_ap(nvlist_t * dpp,FILE * fp,char * prefix)730*4582Scth print_ap(nvlist_t *dpp, FILE *fp, char *prefix)
731*4582Scth {
732*4582Scth int len = strlen(prefix) + 2;
733*4582Scth char *buf = dmalloc(len);
734*4582Scth
735*4582Scth (void) snprintf(buf, len, "%s\t", prefix);
736*4582Scth
737*4582Scth (void) fprintf(fp, "%sap_props {\n", prefix);
738*4582Scth print_props(dpp, fp, buf);
739*4582Scth (void) fprintf(fp, "%s}\n", prefix);
740*4582Scth
741*4582Scth dfree(buf, len);
742*4582Scth }
743*4582Scth
744*4582Scth static void
print_disks(diskmon_t * dmp,FILE * fp,char * prefix)745*4582Scth print_disks(diskmon_t *dmp, FILE *fp, char *prefix)
746*4582Scth {
747*4582Scth int len = strlen(prefix) + 2;
748*4582Scth char *buf = dmalloc(len);
749*4582Scth
750*4582Scth (void) snprintf(buf, len, "%s\t", prefix);
751*4582Scth
752*4582Scth while (dmp != NULL) {
753*4582Scth (void) fprintf(fp, "%sdisk \"%s\" {\n", prefix, dmp->location);
754*4582Scth if (dmp->props) {
755*4582Scth print_props(dmp->props, fp, buf);
756*4582Scth }
757*4582Scth if (dmp->app_props) {
758*4582Scth print_ap(dmp->app_props, fp, buf);
759*4582Scth }
760*4582Scth (void) fprintf(fp, "%s\n", prefix);
761*4582Scth print_inds(dmp->ind_list, fp, buf);
762*4582Scth (void) fprintf(fp, "%s\n", prefix);
763*4582Scth print_indrules(dmp->indrule_list, fp, buf);
764*4582Scth (void) fprintf(fp, "%s}\n", prefix);
765*4582Scth
766*4582Scth if (dmp->next != NULL)
767*4582Scth (void) fprintf(fp, "%s\n", prefix);
768*4582Scth
769*4582Scth dmp = dmp->next;
770*4582Scth }
771*4582Scth
772*4582Scth dfree(buf, len);
773*4582Scth }
774*4582Scth
775*4582Scth static void
print_cfgdata(cfgdata_t * cfgp,FILE * fp,char * prefix)776*4582Scth print_cfgdata(cfgdata_t *cfgp, FILE *fp, char *prefix)
777*4582Scth {
778*4582Scth /* First, print the properties, then the disks */
779*4582Scth
780*4582Scth print_props(cfgp->props, fp, prefix);
781*4582Scth (void) fprintf(fp, "%s\n", prefix);
782*4582Scth print_disks(cfgp->disk_list, fp, prefix);
783*4582Scth }
784*4582Scth
785*4582Scth int
config_init(void)786*4582Scth config_init(void)
787*4582Scth {
788*4582Scth if (init_configuration_from_topo() == 0) {
789*4582Scth config_data = new_cfgdata(NULL, NULL);
790*4582Scth return (0);
791*4582Scth }
792*4582Scth return (-1);
793*4582Scth }
794*4582Scth
795*4582Scth int
config_get(fmd_hdl_t * hdl,const fmd_prop_t * fmd_props)796*4582Scth config_get(fmd_hdl_t *hdl, const fmd_prop_t *fmd_props)
797*4582Scth {
798*4582Scth int err, i = 0;
799*4582Scth char *str = NULL;
800*4582Scth namevalpr_t nvp;
801*4582Scth uint64_t u64;
802*4582Scth boolean_t intfound = B_FALSE, strfound = B_FALSE;
803*4582Scth #define INT64_BUF_LEN 128
804*4582Scth char buf[INT64_BUF_LEN];
805*4582Scth
806*4582Scth u64 = fmd_prop_get_int32(hdl, GLOBAL_PROP_LOG_LEVEL);
807*4582Scth g_verbose = (int)u64;
808*4582Scth
809*4582Scth err = update_configuration_from_topo(hdl, NULL);
810*4582Scth
811*4582Scth /* Pull in the properties from the DE configuration file */
812*4582Scth while (fmd_props[i].fmdp_name != NULL) {
813*4582Scth
814*4582Scth nvp.name = (char *)fmd_props[i].fmdp_name;
815*4582Scth
816*4582Scth switch (fmd_props[i].fmdp_type) {
817*4582Scth case FMD_TYPE_UINT32:
818*4582Scth case FMD_TYPE_INT32:
819*4582Scth intfound = B_TRUE;
820*4582Scth u64 = fmd_prop_get_int32(hdl, fmd_props[i].fmdp_name);
821*4582Scth break;
822*4582Scth case FMD_TYPE_UINT64:
823*4582Scth case FMD_TYPE_INT64:
824*4582Scth intfound = B_TRUE;
825*4582Scth u64 = fmd_prop_get_int64(hdl, fmd_props[i].fmdp_name);
826*4582Scth break;
827*4582Scth case FMD_TYPE_STRING:
828*4582Scth strfound = B_TRUE;
829*4582Scth str = fmd_prop_get_string(hdl, fmd_props[i].fmdp_name);
830*4582Scth break;
831*4582Scth
832*4582Scth }
833*4582Scth
834*4582Scth if (intfound) {
835*4582Scth (void) snprintf(buf, INT64_BUF_LEN, "0x%llx", u64);
836*4582Scth nvp.value = buf;
837*4582Scth intfound = B_FALSE;
838*4582Scth } else if (strfound) {
839*4582Scth nvp.value = str;
840*4582Scth }
841*4582Scth
842*4582Scth log_msg(MM_CONF, "Adding property `%s' with value `%s'\n",
843*4582Scth nvp.name, nvp.value);
844*4582Scth
845*4582Scth cfgdata_add_namevalpr(config_data, &nvp);
846*4582Scth
847*4582Scth if (strfound) {
848*4582Scth strfound = B_FALSE;
849*4582Scth fmd_prop_free_string(hdl, str);
850*4582Scth }
851*4582Scth
852*4582Scth
853*4582Scth i++;
854*4582Scth }
855*4582Scth
856*4582Scth if ((g_verbose & (MM_CONF|MM_OTHER)) == (MM_CONF|MM_OTHER))
857*4582Scth print_cfgdata(config_data, stderr, "");
858*4582Scth
859*4582Scth return (err);
860*4582Scth }
861*4582Scth
862*4582Scth void
config_fini(void)863*4582Scth config_fini(void)
864*4582Scth {
865*4582Scth fini_configuration_from_topo();
866*4582Scth cfgdata_free(config_data);
867*4582Scth config_data = NULL;
868*4582Scth }
869*4582Scth
870*4582Scth nvlist_t *
dm_global_proplist(void)871*4582Scth dm_global_proplist(void)
872*4582Scth {
873*4582Scth return (config_data->props);
874*4582Scth }
875