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 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Disk & Indicator Monitor configuration file support routines
31 #include <sys/types.h>
41 #include "disk_monitor.h"
43 #include "topo_gather.h"
45 extern log_class_t g_verbose
;
48 hotplug_state_string(hotplug_state_t state
)
50 switch (state
& ~HPS_FAULTED
) {
59 return ("Configured");
60 case HPS_UNCONFIGURED
:
61 return ("Unconfigured");
66 conf_error_msg(conf_err_t err
, char *buf
, int buflen
, void *arg
)
69 case E_MULTIPLE_IND_LISTS_DEFINED
:
70 (void) snprintf(buf
, buflen
, "Multiple Indicator lists "
73 case E_MULTIPLE_INDRULE_LISTS_DEFINED
:
74 (void) snprintf(buf
, buflen
, "Multiple Indicator rule lists "
77 case E_INVALID_STATE_CHANGE
:
78 (void) snprintf(buf
, buflen
, "Invalid state change");
80 case E_IND_MULTIPLY_DEFINED
:
81 (void) snprintf(buf
, buflen
,
82 "Multiple Indicator definitions (name & state) detected");
84 case E_IND_ACTION_REDUNDANT
:
85 (void) snprintf(buf
, buflen
, "Redundant Indicator actions "
88 case E_IND_ACTION_CONFLICT
:
89 (void) snprintf(buf
, buflen
, "Indicator action conflict (+/- "
90 "same Indicator) found");
92 case E_IND_MISSING_FAULT_ON
:
93 (void) snprintf(buf
, buflen
, "Missing declaration of `+"
94 INDICATOR_FAULT_IDENTIFIER
"'");
96 case E_IND_MISSING_FAULT_OFF
:
97 (void) snprintf(buf
, buflen
, "Missing declaration of `-"
98 INDICATOR_FAULT_IDENTIFIER
"'");
100 case E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION
:
101 (void) snprintf(buf
, buflen
, "`%c%s': Undefined Indicator in "
102 BAY_IND_ACTION
" property",
103 (((ind_action_t
*)arg
)->ind_state
== INDICATOR_ON
)
105 ((ind_action_t
*)arg
)->ind_name
);
107 case E_DUPLICATE_STATE_TRANSITION
:
108 (void) snprintf(buf
, buflen
, "Duplicate state transition "
110 hotplug_state_string(((state_transition_t
*)arg
)->begin
),
111 hotplug_state_string(((state_transition_t
*)arg
)->end
));
114 (void) snprintf(buf
, buflen
, "Unknown error");
120 string_to_integer(const char *prop
, int *value
)
126 val
= strtol(prop
, NULL
, 0);
128 if (val
== 0 && errno
!= 0)
130 else if (val
> INT_MAX
|| val
< INT_MIN
) {
142 dm_prop_lookup(nvlist_t
*props
, const char *prop_name
)
146 if (nvlist_lookup_string(props
, prop_name
, &str
) == 0)
147 return ((const char *)str
);
153 dm_prop_lookup_int(nvlist_t
*props
, const char *prop_name
, int *value
)
155 const char *prop
= dm_prop_lookup(props
, prop_name
);
160 return (string_to_integer(prop
, value
));
164 namevalpr_to_nvlist(namevalpr_t
*nvprp
)
166 nvlist_t
*nvlp
= NULL
;
168 if (nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
, 0) != 0) {
172 if (nvlist_add_string(nvlp
, nvprp
->name
, nvprp
->value
) != 0) {
181 new_indicator(ind_state_t lstate
, char *namep
, char *actionp
)
183 indicator_t
*newindicator
=
184 (indicator_t
*)dmalloc(sizeof (indicator_t
));
185 newindicator
->ind_state
= lstate
;
186 newindicator
->ind_name
= namep
? dstrdup(namep
) : NULL
;
187 newindicator
->ind_instr_spec
= actionp
? dstrdup(actionp
) : NULL
;
188 newindicator
->next
= NULL
;
189 return (newindicator
);
193 link_indicator(indicator_t
**first
, indicator_t
*to_add
)
195 indicator_t
*travptr
;
196 dm_assert(first
!= NULL
);
202 while (travptr
->next
!= NULL
) {
203 travptr
= travptr
->next
;
205 travptr
->next
= to_add
;
210 ind_free(indicator_t
*indp
)
214 while (indp
!= NULL
) {
217 dstrfree(indp
->ind_name
);
218 if (indp
->ind_instr_spec
)
219 dstrfree(indp
->ind_instr_spec
);
220 dfree(indp
, sizeof (indicator_t
));
226 new_indaction(ind_state_t state
, char *namep
)
228 ind_action_t
*lap
= (ind_action_t
*)dmalloc(sizeof (ind_action_t
));
229 lap
->ind_state
= state
;
230 lap
->ind_name
= namep
? dstrdup(namep
) : NULL
;
236 link_indaction(ind_action_t
**first
, ind_action_t
*to_add
)
238 ind_action_t
*travptr
;
239 dm_assert(first
!= NULL
);
245 while (travptr
->next
!= NULL
) {
246 travptr
= travptr
->next
;
248 travptr
->next
= to_add
;
253 indaction_free(ind_action_t
*lap
)
257 /* Free the whole list */
258 while (lap
!= NULL
) {
261 dstrfree(lap
->ind_name
);
262 dfree(lap
, sizeof (ind_action_t
));
268 new_indrule(state_transition_t
*st
, ind_action_t
*actionp
)
270 indrule_t
*lrp
= (indrule_t
*)dmalloc(sizeof (indrule_t
));
273 lrp
->action_list
= actionp
;
279 link_indrule(indrule_t
**first
, indrule_t
*to_add
)
282 dm_assert(first
!= NULL
);
288 while (travptr
->next
!= NULL
) {
289 travptr
= travptr
->next
;
291 travptr
->next
= to_add
;
296 indrule_free(indrule_t
*lrp
)
300 /* Free the whole list */
301 while (lrp
!= NULL
) {
303 if (lrp
->action_list
)
304 indaction_free(lrp
->action_list
);
305 dfree(lrp
, sizeof (indrule_t
));
311 new_dmfru(char *manu
, char *modl
, char *firmrev
, char *serno
, uint64_t capa
)
313 dm_fru_t
*frup
= (dm_fru_t
*)dzmalloc(sizeof (dm_fru_t
));
315 bcopy(manu
, frup
->manuf
, MIN(sizeof (frup
->manuf
), strlen(manu
) + 1));
316 bcopy(modl
, frup
->model
, MIN(sizeof (frup
->model
), strlen(modl
) + 1));
317 bcopy(firmrev
, frup
->rev
, MIN(sizeof (frup
->rev
), strlen(firmrev
) + 1));
318 bcopy(serno
, frup
->serial
,
319 MIN(sizeof (frup
->serial
), strlen(serno
) + 1));
320 frup
->size_in_bytes
= capa
;
325 dmfru_free(dm_fru_t
*frup
)
327 dfree(frup
, sizeof (dm_fru_t
));
331 new_diskmon(nvlist_t
*app_props
, indicator_t
*indp
, indrule_t
*indrp
,
334 diskmon_t
*dmp
= (diskmon_t
*)dmalloc(sizeof (diskmon_t
));
339 (void) nvlist_alloc(&dmp
->props
, NV_UNIQUE_NAME
, 0);
342 dmp
->app_props
= app_props
;
344 (void) nvlist_alloc(&dmp
->app_props
, NV_UNIQUE_NAME
, 0);
345 dmp
->ind_list
= indp
;
346 dmp
->indrule_list
= indrp
;
348 dm_assert(pthread_mutex_init(&dmp
->manager_mutex
, NULL
) == 0);
350 dmp
->state
= HPS_UNKNOWN
;
352 dmp
->initial_configuration
= B_TRUE
;
354 dm_assert(pthread_mutex_init(&dmp
->fault_indicator_mutex
, NULL
) == 0);
355 dmp
->fault_indicator_state
= INDICATOR_UNKNOWN
;
357 dmp
->configured_yet
= B_FALSE
;
358 dmp
->state_change_count
= 0;
360 dm_assert(pthread_mutex_init(&dmp
->fru_mutex
, NULL
) == 0);
368 diskmon_free(diskmon_t
*dmp
)
372 /* Free the whole list */
373 while (dmp
!= NULL
) {
376 nvlist_free(dmp
->props
);
378 dstrfree(dmp
->location
);
380 ind_free(dmp
->ind_list
);
381 if (dmp
->indrule_list
)
382 indrule_free(dmp
->indrule_list
);
383 nvlist_free(dmp
->app_props
);
385 dmfru_free(dmp
->frup
);
386 dfree(dmp
, sizeof (diskmon_t
));
393 new_cfgdata(namevalpr_t
*nvp
, diskmon_t
*dmp
)
395 cfgdata_t
*cdp
= (cfgdata_t
*)dzmalloc(sizeof (cfgdata_t
));
398 cdp
->props
= namevalpr_to_nvlist(nvp
);
399 else if (nvlist_alloc(&cdp
->props
, NV_UNIQUE_NAME
, 0) != 0) {
404 cdp
->disk_list
= dmp
;
410 cfgdata_add_namevalpr(cfgdata_t
*cfgp
, namevalpr_t
*nvp
)
412 if (cfgp
->props
== NULL
) {
413 (void) nvlist_alloc(&cfgp
->props
, NV_UNIQUE_NAME
, 0);
415 (void) nvlist_add_string(cfgp
->props
, nvp
->name
, nvp
->value
);
419 cfgdata_add_diskmon(cfgdata_t
*cfgp
, diskmon_t
*dmp
)
421 if (cfgp
->disk_list
== NULL
) {
422 cfgp
->disk_list
= dmp
;
424 diskmon_t
*disklist
= cfgp
->disk_list
;
426 while (disklist
->next
!= NULL
)
427 disklist
= disklist
->next
;
429 disklist
->next
= dmp
;
434 cfgdata_free(cfgdata_t
*cdp
)
436 nvlist_free(cdp
->props
);
437 diskmon_free(cdp
->disk_list
);
438 dfree(cdp
, sizeof (cfgdata_t
));
442 check_indactions(ind_action_t
*indrp
)
445 conf_err_t rv
= E_NO_ERROR
;
446 nvlist_t
*nvp
= NULL
;
449 (void) nvlist_alloc(&nvp
, NV_UNIQUE_NAME
, 0);
452 * Check indicator actions for conflicts
454 while (indrp
!= NULL
&& rv
== E_NO_ERROR
) {
455 len
= strlen(indrp
->ind_name
) + 2;
457 (void) snprintf(buf
, len
, "%c%s",
458 indrp
->ind_state
== INDICATOR_ON
? '+' : '-',
460 switch (nvlist_lookup_boolean(nvp
, buf
)) {
462 (void) nvlist_add_boolean(nvp
, buf
);
465 rv
= E_IND_ACTION_REDUNDANT
;
471 /* Look for the opposite action. If found, that's an error */
472 (void) snprintf(buf
, len
, "%c%s",
473 indrp
->ind_state
== INDICATOR_ON
? '-' : '+',
475 switch (nvlist_lookup_boolean(nvp
, buf
)) {
479 rv
= E_IND_ACTION_CONFLICT
;
493 check_inds(indicator_t
*indp
)
496 conf_err_t rv
= E_NO_ERROR
;
497 nvlist_t
*nvp
= NULL
;
499 boolean_t fault_on
= B_FALSE
, fault_off
= B_FALSE
;
501 (void) nvlist_alloc(&nvp
, NV_UNIQUE_NAME
, 0);
504 * Check inds for multiple definitions (same identifier or same action)
506 while (indp
!= NULL
&& rv
== E_NO_ERROR
) {
507 len
= strlen(indp
->ind_name
) + 2;
509 (void) snprintf(buf
, len
, "%c%s",
510 indp
->ind_state
== INDICATOR_ON
? '+' : '-',
513 /* Keep track of the +/-FAULT for checking later */
514 if (strcasecmp(buf
, "+" INDICATOR_FAULT_IDENTIFIER
) == 0)
516 else if (strcasecmp(buf
, "-" INDICATOR_FAULT_IDENTIFIER
) == 0)
519 switch (nvlist_lookup_boolean(nvp
, buf
)) {
521 (void) nvlist_add_boolean(nvp
, buf
);
524 rv
= E_IND_MULTIPLY_DEFINED
;
534 * Make sure we have a -FAULT and +FAULT
537 rv
= E_IND_MISSING_FAULT_ON
;
539 rv
= E_IND_MISSING_FAULT_OFF
;
546 check_indrules(indrule_t
*indrp
, state_transition_t
**offender
)
549 conf_err_t rv
= E_NO_ERROR
;
550 nvlist_t
*nvp
= NULL
;
553 * Ensure that no two rules have the same state transitions.
556 (void) nvlist_alloc(&nvp
, NV_UNIQUE_NAME
, 0);
558 while (indrp
!= NULL
&& rv
== E_NO_ERROR
) {
559 (void) snprintf(buf
, sizeof (buf
), "%d-%d",
560 (int)indrp
->strans
.begin
, (int)indrp
->strans
.end
);
561 switch (nvlist_lookup_boolean(nvp
, buf
)) {
563 *offender
= &indrp
->strans
;
564 rv
= E_DUPLICATE_STATE_TRANSITION
;
567 (void) nvlist_add_boolean(nvp
, buf
);
581 check_consistent_ind_indrules(indicator_t
*indp
, indrule_t
*indrp
,
582 ind_action_t
**offender
)
585 conf_err_t rv
= E_NO_ERROR
;
586 nvlist_t
*nvp
= NULL
;
591 * Ensure that every indicator action referenced in each ruleset
592 * exists in the indicator list given.
595 (void) nvlist_alloc(&nvp
, NV_UNIQUE_NAME
, 0);
597 while (indp
!= NULL
) {
598 len
= strlen(indp
->ind_name
) + 2;
600 (void) snprintf(buf
, len
, "%c%s",
601 indp
->ind_state
== INDICATOR_ON
? '+' : '-',
603 (void) nvlist_add_boolean(nvp
, buf
);
608 while (indrp
!= NULL
&& rv
== E_NO_ERROR
) {
609 alp
= indrp
->action_list
;
610 while (alp
!= NULL
&& rv
== E_NO_ERROR
) {
611 len
= strlen(alp
->ind_name
) + 2;
613 (void) snprintf(buf
, len
, "%c%s",
614 alp
->ind_state
== INDICATOR_ON
? '+' : '-',
617 switch (nvlist_lookup_boolean(nvp
, buf
)) {
618 case 0: /* Normal case */
623 E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION
;
639 check_state_transition(hotplug_state_t s1
, hotplug_state_t s2
)
642 * The following are valid transitions:
644 * HPS_ABSENT -> HPS_PRESENT
645 * HPS_ABSENT -> HPS_CONFIGURED
646 * HPS_PRESENT -> HPS_CONFIGURED
647 * HPS_PRESENT -> HPS_ABSENT
648 * HPS_CONFIGURED -> HPS_UNCONFIGURED
649 * HPS_CONFIGURED -> HPS_ABSENT
650 * HPS_UNCONFIGURED -> HPS_ABSENT
651 * HPS_UNCONFIGURED -> HPS_CONFIGURED
654 if (s1
== HPS_ABSENT
&& s2
!= HPS_PRESENT
&& s2
!= HPS_CONFIGURED
)
655 return (E_INVALID_STATE_CHANGE
);
656 else if (s1
== HPS_PRESENT
&& (s2
!= HPS_CONFIGURED
&&
658 return (E_INVALID_STATE_CHANGE
);
659 else if (s1
== HPS_CONFIGURED
&& (s2
!= HPS_UNCONFIGURED
&&
661 return (E_INVALID_STATE_CHANGE
);
662 else if (s1
== HPS_UNCONFIGURED
&& (s2
!= HPS_ABSENT
&&
663 s2
!= HPS_CONFIGURED
))
664 return (E_INVALID_STATE_CHANGE
);
670 print_inds(indicator_t
*indp
, FILE *fp
, char *prefix
)
674 (void) fprintf(fp
, "%sindicators {\n", prefix
);
675 while (indp
!= NULL
) {
676 plusminus
= (indp
->ind_state
== INDICATOR_ON
) ? '+' : '-';
677 (void) fprintf(fp
, "%s\t%c%s = \"%s\"\n", prefix
, plusminus
,
678 indp
->ind_name
, indp
->ind_instr_spec
);
681 (void) fprintf(fp
, "%s}\n", prefix
);
685 print_indrules(indrule_t
*lrp
, FILE *fp
, char *prefix
)
690 (void) fprintf(fp
, "%sindicator_rules {\n", prefix
);
691 while (lrp
!= NULL
) {
692 (void) fprintf(fp
, "%s\t%12s -> %12s\t{ ", prefix
,
693 hotplug_state_string(lrp
->strans
.begin
),
694 hotplug_state_string(lrp
->strans
.end
));
695 lap
= lrp
->action_list
;
696 while (lap
!= NULL
) {
697 plusminus
= (lap
->ind_state
== INDICATOR_ON
)
699 (void) fprintf(fp
, "%c%s", plusminus
, lap
->ind_name
);
702 (void) fprintf(fp
, ", ");
704 (void) fprintf(fp
, " }\n");
707 (void) fprintf(fp
, "%s}\n", prefix
);
711 print_props(nvlist_t
*nvlp
, FILE *fp
, char *prefix
)
713 nvpair_t
*nvp
= nvlist_next_nvpair(nvlp
, NULL
);
716 while (nvp
!= NULL
) {
717 dm_assert(nvpair_type(nvp
) == DATA_TYPE_STRING
);
718 name
= nvpair_name(nvp
);
719 (void) nvlist_lookup_string(nvlp
, name
, &str
);
720 (void) fprintf(fp
, "%s%s = \"%s\"\n", prefix
, name
, str
);
721 nvp
= nvlist_next_nvpair(nvlp
, nvp
);
726 print_ap(nvlist_t
*dpp
, FILE *fp
, char *prefix
)
728 int len
= strlen(prefix
) + 2;
729 char *buf
= dmalloc(len
);
731 (void) snprintf(buf
, len
, "%s\t", prefix
);
733 (void) fprintf(fp
, "%sap_props {\n", prefix
);
734 print_props(dpp
, fp
, buf
);
735 (void) fprintf(fp
, "%s}\n", prefix
);
741 print_disks(diskmon_t
*dmp
, FILE *fp
, char *prefix
)
743 int len
= strlen(prefix
) + 2;
744 char *buf
= dmalloc(len
);
746 (void) snprintf(buf
, len
, "%s\t", prefix
);
748 while (dmp
!= NULL
) {
749 (void) fprintf(fp
, "%sdisk \"%s\" {\n", prefix
, dmp
->location
);
751 print_props(dmp
->props
, fp
, buf
);
753 if (dmp
->app_props
) {
754 print_ap(dmp
->app_props
, fp
, buf
);
756 (void) fprintf(fp
, "%s\n", prefix
);
757 print_inds(dmp
->ind_list
, fp
, buf
);
758 (void) fprintf(fp
, "%s\n", prefix
);
759 print_indrules(dmp
->indrule_list
, fp
, buf
);
760 (void) fprintf(fp
, "%s}\n", prefix
);
762 if (dmp
->next
!= NULL
)
763 (void) fprintf(fp
, "%s\n", prefix
);
772 print_cfgdata(cfgdata_t
*cfgp
, FILE *fp
, char *prefix
)
774 /* First, print the properties, then the disks */
776 print_props(cfgp
->props
, fp
, prefix
);
777 (void) fprintf(fp
, "%s\n", prefix
);
778 print_disks(cfgp
->disk_list
, fp
, prefix
);
784 if (init_configuration_from_topo() == 0) {
785 config_data
= new_cfgdata(NULL
, NULL
);
792 config_get(fmd_hdl_t
*hdl
, const fmd_prop_t
*fmd_props
)
798 boolean_t intfound
= B_FALSE
, strfound
= B_FALSE
;
799 #define INT64_BUF_LEN 128
800 char buf
[INT64_BUF_LEN
];
802 u64
= fmd_prop_get_int32(hdl
, GLOBAL_PROP_LOG_LEVEL
);
803 g_verbose
= (int)u64
;
805 err
= update_configuration_from_topo(hdl
, NULL
);
807 /* Pull in the properties from the DE configuration file */
808 while (fmd_props
[i
].fmdp_name
!= NULL
) {
810 nvp
.name
= (char *)fmd_props
[i
].fmdp_name
;
812 switch (fmd_props
[i
].fmdp_type
) {
813 case FMD_TYPE_UINT32
:
816 u64
= fmd_prop_get_int32(hdl
, fmd_props
[i
].fmdp_name
);
818 case FMD_TYPE_UINT64
:
821 u64
= fmd_prop_get_int64(hdl
, fmd_props
[i
].fmdp_name
);
823 case FMD_TYPE_STRING
:
825 str
= fmd_prop_get_string(hdl
, fmd_props
[i
].fmdp_name
);
831 (void) snprintf(buf
, INT64_BUF_LEN
, "0x%llx", u64
);
834 } else if (strfound
) {
838 log_msg(MM_CONF
, "Adding property `%s' with value `%s'\n",
839 nvp
.name
, nvp
.value
);
841 cfgdata_add_namevalpr(config_data
, &nvp
);
845 fmd_prop_free_string(hdl
, str
);
852 if ((g_verbose
& (MM_CONF
|MM_OTHER
)) == (MM_CONF
|MM_OTHER
))
853 print_cfgdata(config_data
, stderr
, "");
861 fini_configuration_from_topo();
862 cfgdata_free(config_data
);
867 dm_global_proplist(void)
869 return (config_data
->props
);