1724365f7Ssethg /*
2724365f7Ssethg  * CDDL HEADER START
3724365f7Ssethg  *
4724365f7Ssethg  * The contents of this file are subject to the terms of the
5724365f7Ssethg  * Common Development and Distribution License (the "License").
6724365f7Ssethg  * You may not use this file except in compliance with the License.
7724365f7Ssethg  *
8724365f7Ssethg  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9724365f7Ssethg  * or http://www.opensolaris.org/os/licensing.
10724365f7Ssethg  * See the License for the specific language governing permissions
11724365f7Ssethg  * and limitations under the License.
12724365f7Ssethg  *
13724365f7Ssethg  * When distributing Covered Code, include this CDDL HEADER in each
14724365f7Ssethg  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15724365f7Ssethg  * If applicable, add the following below this CDDL HEADER, with the
16724365f7Ssethg  * fields enclosed by brackets "[]" replaced with your own identifying
17724365f7Ssethg  * information: Portions Copyright [yyyy] [name of copyright owner]
18724365f7Ssethg  *
19724365f7Ssethg  * CDDL HEADER END
20724365f7Ssethg  */
21724365f7Ssethg 
22724365f7Ssethg /*
2324db4641Seschrock  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24724365f7Ssethg  * Use is subject to license terms.
25724365f7Ssethg  */
26724365f7Ssethg 
27724365f7Ssethg /*
28724365f7Ssethg  * Disk & Indicator Monitor configuration file support routines
29724365f7Ssethg  */
30724365f7Ssethg 
31724365f7Ssethg #include <sys/types.h>
32724365f7Ssethg #include <sys/stat.h>
33724365f7Ssethg #include <fcntl.h>
34724365f7Ssethg #include <unistd.h>
35724365f7Ssethg #include <string.h>
36724365f7Ssethg #include <strings.h>
37724365f7Ssethg #include <errno.h>
38724365f7Ssethg #include <limits.h>
39724365f7Ssethg #include <pthread.h>
40724365f7Ssethg 
41184cd04cScth #include "disk_monitor.h"
42724365f7Ssethg #include "util.h"
43724365f7Ssethg #include "topo_gather.h"
44724365f7Ssethg 
45724365f7Ssethg extern log_class_t g_verbose;
46724365f7Ssethg 
47724365f7Ssethg const char *
hotplug_state_string(hotplug_state_t state)48724365f7Ssethg hotplug_state_string(hotplug_state_t state)
49724365f7Ssethg {
50724365f7Ssethg 	switch (state & ~HPS_FAULTED) {
51724365f7Ssethg 	default:
52724365f7Ssethg 	case HPS_UNKNOWN:
53724365f7Ssethg 		return ("Unknown");
54724365f7Ssethg 	case HPS_ABSENT:
55724365f7Ssethg 		return ("Absent");
56724365f7Ssethg 	case HPS_PRESENT:
57724365f7Ssethg 		return ("Present");
58724365f7Ssethg 	case HPS_CONFIGURED:
59724365f7Ssethg 		return ("Configured");
60724365f7Ssethg 	case HPS_UNCONFIGURED:
61724365f7Ssethg 		return ("Unconfigured");
62724365f7Ssethg 	}
63724365f7Ssethg }
64724365f7Ssethg 
65724365f7Ssethg void
conf_error_msg(conf_err_t err,char * buf,int buflen,void * arg)66724365f7Ssethg conf_error_msg(conf_err_t err, char *buf, int buflen, void *arg)
67724365f7Ssethg {
68724365f7Ssethg 	switch (err) {
69724365f7Ssethg 	case E_MULTIPLE_IND_LISTS_DEFINED:
70724365f7Ssethg 		(void) snprintf(buf, buflen, "Multiple Indicator lists "
71724365f7Ssethg 		    "defined");
72724365f7Ssethg 		break;
73724365f7Ssethg 	case E_MULTIPLE_INDRULE_LISTS_DEFINED:
74724365f7Ssethg 		(void) snprintf(buf, buflen, "Multiple Indicator rule lists "
75724365f7Ssethg 		    "defined");
76724365f7Ssethg 		break;
77724365f7Ssethg 	case E_INVALID_STATE_CHANGE:
78724365f7Ssethg 		(void) snprintf(buf, buflen, "Invalid state change");
79724365f7Ssethg 		break;
80724365f7Ssethg 	case E_IND_MULTIPLY_DEFINED:
81724365f7Ssethg 		(void) snprintf(buf, buflen,
82724365f7Ssethg 		    "Multiple Indicator definitions (name & state) detected");
83724365f7Ssethg 		break;
84724365f7Ssethg 	case E_IND_ACTION_REDUNDANT:
85724365f7Ssethg 		(void) snprintf(buf, buflen, "Redundant Indicator actions "
86724365f7Ssethg 		    "specified");
87724365f7Ssethg 		break;
88724365f7Ssethg 	case E_IND_ACTION_CONFLICT:
89724365f7Ssethg 		(void) snprintf(buf, buflen, "Indicator action conflict (+/- "
90724365f7Ssethg 		    "same Indicator) found");
91724365f7Ssethg 		break;
92724365f7Ssethg 	case E_IND_MISSING_FAULT_ON:
93724365f7Ssethg 		(void) snprintf(buf, buflen, "Missing declaration of `+"
94724365f7Ssethg 		    INDICATOR_FAULT_IDENTIFIER "'");
95724365f7Ssethg 		break;
96724365f7Ssethg 	case E_IND_MISSING_FAULT_OFF:
97724365f7Ssethg 		(void) snprintf(buf, buflen, "Missing declaration of `-"
98724365f7Ssethg 		    INDICATOR_FAULT_IDENTIFIER "'");
99724365f7Ssethg 		break;
100724365f7Ssethg 	case E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION:
101724365f7Ssethg 		(void) snprintf(buf, buflen, "`%c%s': Undefined Indicator in "
102184cd04cScth 		    BAY_IND_ACTION " property",
103724365f7Ssethg 		    (((ind_action_t *)arg)->ind_state == INDICATOR_ON)
104724365f7Ssethg 		    ? '+' : '-',
105724365f7Ssethg 		    ((ind_action_t *)arg)->ind_name);
106724365f7Ssethg 		break;
107724365f7Ssethg 	case E_DUPLICATE_STATE_TRANSITION:
108724365f7Ssethg 		(void) snprintf(buf, buflen, "Duplicate state transition "
109724365f7Ssethg 		    "(%s -> %s)",
110724365f7Ssethg 		    hotplug_state_string(((state_transition_t *)arg)->begin),
111724365f7Ssethg 		    hotplug_state_string(((state_transition_t *)arg)->end));
112724365f7Ssethg 		break;
113724365f7Ssethg 	default:
114724365f7Ssethg 		(void) snprintf(buf, buflen, "Unknown error");
115724365f7Ssethg 		break;
116724365f7Ssethg 	}
117724365f7Ssethg }
118724365f7Ssethg 
119724365f7Ssethg static int
string_to_integer(const char * prop,int * value)120724365f7Ssethg string_to_integer(const char *prop, int *value)
121724365f7Ssethg {
122724365f7Ssethg 	long val;
123724365f7Ssethg 
124724365f7Ssethg 	errno = 0;
125724365f7Ssethg 
126724365f7Ssethg 	val = strtol(prop, NULL, 0);
127724365f7Ssethg 
128724365f7Ssethg 	if (val == 0 && errno != 0)
129724365f7Ssethg 		return (-1);
130724365f7Ssethg 	else if (val > INT_MAX || val < INT_MIN) {
131724365f7Ssethg 		errno = ERANGE;
132724365f7Ssethg 		return (-1);
133724365f7Ssethg 	}
134724365f7Ssethg 
135724365f7Ssethg 	if (value != NULL)
136724365f7Ssethg 		*value = (int)val;
137724365f7Ssethg 
138724365f7Ssethg 	return (0);
139724365f7Ssethg }
140724365f7Ssethg 
141724365f7Ssethg const char *
dm_prop_lookup(nvlist_t * props,const char * prop_name)142724365f7Ssethg dm_prop_lookup(nvlist_t *props, const char *prop_name)
143724365f7Ssethg {
144724365f7Ssethg 	char *str;
145724365f7Ssethg 
146724365f7Ssethg 	if (nvlist_lookup_string(props, prop_name, &str) == 0)
147724365f7Ssethg 		return ((const char *)str);
148724365f7Ssethg 	else
149724365f7Ssethg 		return (NULL);
150724365f7Ssethg }
151724365f7Ssethg 
152724365f7Ssethg int
dm_prop_lookup_int(nvlist_t * props,const char * prop_name,int * value)153724365f7Ssethg dm_prop_lookup_int(nvlist_t *props, const char *prop_name, int *value)
154724365f7Ssethg {
155724365f7Ssethg 	const char *prop = dm_prop_lookup(props, prop_name);
156724365f7Ssethg 
157724365f7Ssethg 	if (prop == NULL)
158724365f7Ssethg 		return (-1);
159724365f7Ssethg 
160724365f7Ssethg 	return (string_to_integer(prop, value));
161724365f7Ssethg }
162724365f7Ssethg 
163724365f7Ssethg nvlist_t *
namevalpr_to_nvlist(namevalpr_t * nvprp)164724365f7Ssethg namevalpr_to_nvlist(namevalpr_t *nvprp)
165724365f7Ssethg {
166724365f7Ssethg 	nvlist_t *nvlp = NULL;
167724365f7Ssethg 
168724365f7Ssethg 	if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0) != 0) {
169724365f7Ssethg 		return (NULL);
170724365f7Ssethg 	}
171724365f7Ssethg 
172724365f7Ssethg 	if (nvlist_add_string(nvlp, nvprp->name, nvprp->value) != 0) {
173724365f7Ssethg 		nvlist_free(nvlp);
174724365f7Ssethg 		return (NULL);
175724365f7Ssethg 	}
176724365f7Ssethg 
177724365f7Ssethg 	return (nvlp);
178724365f7Ssethg }
179724365f7Ssethg 
180724365f7Ssethg indicator_t *
new_indicator(ind_state_t lstate,char * namep,char * actionp)181724365f7Ssethg new_indicator(ind_state_t lstate, char *namep, char *actionp)
182724365f7Ssethg {
183724365f7Ssethg 	indicator_t *newindicator =
184724365f7Ssethg 	    (indicator_t *)dmalloc(sizeof (indicator_t));
185724365f7Ssethg 	newindicator->ind_state = lstate;
186724365f7Ssethg 	newindicator->ind_name = namep ? dstrdup(namep) : NULL;
187724365f7Ssethg 	newindicator->ind_instr_spec = actionp ? dstrdup(actionp) : NULL;
188724365f7Ssethg 	newindicator->next = NULL;
189724365f7Ssethg 	return (newindicator);
190724365f7Ssethg }
191724365f7Ssethg 
192724365f7Ssethg void
link_indicator(indicator_t ** first,indicator_t * to_add)193724365f7Ssethg link_indicator(indicator_t **first, indicator_t *to_add)
194724365f7Ssethg {
195724365f7Ssethg 	indicator_t *travptr;
1967a0b67e3Ssethg 	dm_assert(first != NULL);
197724365f7Ssethg 
198724365f7Ssethg 	if (*first == NULL)
199724365f7Ssethg 		*first = to_add;
200724365f7Ssethg 	else {
201724365f7Ssethg 		travptr = *first;
202724365f7Ssethg 		while (travptr->next != NULL) {
203724365f7Ssethg 			travptr = travptr->next;
204724365f7Ssethg 		}
205724365f7Ssethg 		travptr->next = to_add;
206724365f7Ssethg 	}
207724365f7Ssethg }
208724365f7Ssethg 
209724365f7Ssethg void
ind_free(indicator_t * indp)210724365f7Ssethg ind_free(indicator_t *indp)
211724365f7Ssethg {
212724365f7Ssethg 	indicator_t *nextp;
213724365f7Ssethg 
214724365f7Ssethg 	while (indp != NULL) {
215724365f7Ssethg 		nextp = indp->next;
216724365f7Ssethg 		if (indp->ind_name)
217724365f7Ssethg 			dstrfree(indp->ind_name);
218724365f7Ssethg 		if (indp->ind_instr_spec)
219724365f7Ssethg 			dstrfree(indp->ind_instr_spec);
220724365f7Ssethg 		dfree(indp, sizeof (indicator_t));
221724365f7Ssethg 		indp = nextp;
222724365f7Ssethg 	}
223724365f7Ssethg }
224724365f7Ssethg 
225724365f7Ssethg ind_action_t *
new_indaction(ind_state_t state,char * namep)226724365f7Ssethg new_indaction(ind_state_t state, char *namep)
227724365f7Ssethg {
228724365f7Ssethg 	ind_action_t *lap = (ind_action_t *)dmalloc(sizeof (ind_action_t));
229724365f7Ssethg 	lap->ind_state = state;
230724365f7Ssethg 	lap->ind_name = namep ? dstrdup(namep) : NULL;
231724365f7Ssethg 	lap->next = NULL;
232724365f7Ssethg 	return (lap);
233724365f7Ssethg }
234724365f7Ssethg 
235724365f7Ssethg void
link_indaction(ind_action_t ** first,ind_action_t * to_add)236724365f7Ssethg link_indaction(ind_action_t **first, ind_action_t *to_add)
237724365f7Ssethg {
238724365f7Ssethg 	ind_action_t *travptr;
2397a0b67e3Ssethg 	dm_assert(first != NULL);
240724365f7Ssethg 
241724365f7Ssethg 	if (*first == NULL)
242724365f7Ssethg 		*first = to_add;
243724365f7Ssethg 	else {
244724365f7Ssethg 		travptr = *first;
245724365f7Ssethg 		while (travptr->next != NULL) {
246724365f7Ssethg 			travptr = travptr->next;
247724365f7Ssethg 		}
248724365f7Ssethg 		travptr->next = to_add;
249724365f7Ssethg 	}
250724365f7Ssethg }
251724365f7Ssethg 
252724365f7Ssethg void
indaction_free(ind_action_t * lap)253724365f7Ssethg indaction_free(ind_action_t *lap)
254724365f7Ssethg {
255724365f7Ssethg 	ind_action_t *nextp;
256724365f7Ssethg 
257724365f7Ssethg 	/* Free the whole list */
258724365f7Ssethg 	while (lap != NULL) {
259724365f7Ssethg 		nextp = lap->next;
260724365f7Ssethg 		if (lap->ind_name)
261724365f7Ssethg 			dstrfree(lap->ind_name);
262724365f7Ssethg 		dfree(lap, sizeof (ind_action_t));
263724365f7Ssethg 		lap = nextp;
264724365f7Ssethg 	}
265724365f7Ssethg }
266724365f7Ssethg 
267724365f7Ssethg indrule_t *
new_indrule(state_transition_t * st,ind_action_t * actionp)268724365f7Ssethg new_indrule(state_transition_t *st, ind_action_t *actionp)
269724365f7Ssethg {
270724365f7Ssethg 	indrule_t *lrp = (indrule_t *)dmalloc(sizeof (indrule_t));
271724365f7Ssethg 	if (st != NULL)
272724365f7Ssethg 		lrp->strans = *st;
273724365f7Ssethg 	lrp->action_list = actionp;
274724365f7Ssethg 	lrp->next = NULL;
275724365f7Ssethg 	return (lrp);
276724365f7Ssethg }
277724365f7Ssethg 
278724365f7Ssethg void
link_indrule(indrule_t ** first,indrule_t * to_add)279724365f7Ssethg link_indrule(indrule_t **first, indrule_t *to_add)
280724365f7Ssethg {
281724365f7Ssethg 	indrule_t *travptr;
2827a0b67e3Ssethg 	dm_assert(first != NULL);
283724365f7Ssethg 
284724365f7Ssethg 	if (*first == NULL)
285724365f7Ssethg 		*first = to_add;
286724365f7Ssethg 	else {
287724365f7Ssethg 		travptr = *first;
288724365f7Ssethg 		while (travptr->next != NULL) {
289724365f7Ssethg 			travptr = travptr->next;
290724365f7Ssethg 		}
291724365f7Ssethg 		travptr->next = to_add;
292724365f7Ssethg 	}
293724365f7Ssethg }
294724365f7Ssethg 
295724365f7Ssethg void
indrule_free(indrule_t * lrp)296724365f7Ssethg indrule_free(indrule_t *lrp)
297724365f7Ssethg {
298724365f7Ssethg 	indrule_t *nextp;
299724365f7Ssethg 
300724365f7Ssethg 	/* Free the whole list */
301724365f7Ssethg 	while (lrp != NULL) {
302724365f7Ssethg 		nextp = lrp->next;
303724365f7Ssethg 		if (lrp->action_list)
304724365f7Ssethg 			indaction_free(lrp->action_list);
305724365f7Ssethg 		dfree(lrp, sizeof (indrule_t));
306724365f7Ssethg 		lrp = nextp;
307724365f7Ssethg 	}
308724365f7Ssethg }
309724365f7Ssethg 
310724365f7Ssethg dm_fru_t *
new_dmfru(char * manu,char * modl,char * firmrev,char * serno,uint64_t capa)311724365f7Ssethg new_dmfru(char *manu, char *modl, char *firmrev, char *serno, uint64_t capa)
312724365f7Ssethg {
313724365f7Ssethg 	dm_fru_t *frup = (dm_fru_t *)dzmalloc(sizeof (dm_fru_t));
314724365f7Ssethg 
315724365f7Ssethg 	bcopy(manu, frup->manuf, MIN(sizeof (frup->manuf), strlen(manu) + 1));
316724365f7Ssethg 	bcopy(modl, frup->model, MIN(sizeof (frup->model), strlen(modl) + 1));
317724365f7Ssethg 	bcopy(firmrev, frup->rev, MIN(sizeof (frup->rev), strlen(firmrev) + 1));
318724365f7Ssethg 	bcopy(serno, frup->serial,
319724365f7Ssethg 	    MIN(sizeof (frup->serial), strlen(serno) + 1));
320724365f7Ssethg 	frup->size_in_bytes = capa;
321724365f7Ssethg 	return (frup);
322724365f7Ssethg }
323724365f7Ssethg 
324724365f7Ssethg void
dmfru_free(dm_fru_t * frup)325724365f7Ssethg dmfru_free(dm_fru_t *frup)
326724365f7Ssethg {
327724365f7Ssethg 	dfree(frup, sizeof (dm_fru_t));
328724365f7Ssethg }
329724365f7Ssethg 
330724365f7Ssethg diskmon_t *
new_diskmon(nvlist_t * app_props,indicator_t * indp,indrule_t * indrp,nvlist_t * nvlp)331724365f7Ssethg new_diskmon(nvlist_t *app_props, indicator_t *indp, indrule_t *indrp,
332724365f7Ssethg     nvlist_t *nvlp)
333724365f7Ssethg {
334724365f7Ssethg 	diskmon_t *dmp = (diskmon_t *)dmalloc(sizeof (diskmon_t));
335724365f7Ssethg 
336724365f7Ssethg 	if (nvlp != NULL)
337724365f7Ssethg 		dmp->props = nvlp;
338724365f7Ssethg 	else
339724365f7Ssethg 		(void) nvlist_alloc(&dmp->props, NV_UNIQUE_NAME, 0);
340724365f7Ssethg 
341724365f7Ssethg 	if (app_props)
342724365f7Ssethg 		dmp->app_props = app_props;
343724365f7Ssethg 	else
344724365f7Ssethg 		(void) nvlist_alloc(&dmp->app_props, NV_UNIQUE_NAME, 0);
345724365f7Ssethg 	dmp->ind_list = indp;
346724365f7Ssethg 	dmp->indrule_list = indrp;
347724365f7Ssethg 
3487a0b67e3Ssethg 	dm_assert(pthread_mutex_init(&dmp->manager_mutex, NULL) == 0);
349724365f7Ssethg 
350724365f7Ssethg 	dmp->state = HPS_UNKNOWN;
351724365f7Ssethg 
352724365f7Ssethg 	dmp->initial_configuration = B_TRUE;
353724365f7Ssethg 
3547a0b67e3Ssethg 	dm_assert(pthread_mutex_init(&dmp->fault_indicator_mutex, NULL) == 0);
355724365f7Ssethg 	dmp->fault_indicator_state = INDICATOR_UNKNOWN;
356724365f7Ssethg 
357724365f7Ssethg 	dmp->configured_yet = B_FALSE;
358724365f7Ssethg 	dmp->state_change_count = 0;
359724365f7Ssethg 
3607a0b67e3Ssethg 	dm_assert(pthread_mutex_init(&dmp->fru_mutex, NULL) == 0);
361724365f7Ssethg 	dmp->frup = NULL;
362724365f7Ssethg 
363724365f7Ssethg 	dmp->next = NULL;
364724365f7Ssethg 	return (dmp);
365724365f7Ssethg }
366724365f7Ssethg 
367724365f7Ssethg void
diskmon_free(diskmon_t * dmp)368724365f7Ssethg diskmon_free(diskmon_t *dmp)
369724365f7Ssethg {
370724365f7Ssethg 	diskmon_t *nextp;
371724365f7Ssethg 
372724365f7Ssethg 	/* Free the whole list */
373724365f7Ssethg 	while (dmp != NULL) {
374724365f7Ssethg 		nextp = dmp->next;
375724365f7Ssethg 
376*aab83bb8SJosef 'Jeff' Sipek 		nvlist_free(dmp->props);
377724365f7Ssethg 		if (dmp->location)
378724365f7Ssethg 			dstrfree(dmp->location);
379724365f7Ssethg 		if (dmp->ind_list)
380724365f7Ssethg 			ind_free(dmp->ind_list);
381724365f7Ssethg 		if (dmp->indrule_list)
382724365f7Ssethg 			indrule_free(dmp->indrule_list);
383*aab83bb8SJosef 'Jeff' Sipek 		nvlist_free(dmp->app_props);
384724365f7Ssethg 		if (dmp->frup)
385724365f7Ssethg 			dmfru_free(dmp->frup);
386724365f7Ssethg 		dfree(dmp, sizeof (diskmon_t));
387724365f7Ssethg 
388724365f7Ssethg 		dmp = nextp;
389724365f7Ssethg 	}
390724365f7Ssethg }
391724365f7Ssethg 
392724365f7Ssethg static cfgdata_t *
new_cfgdata(namevalpr_t * nvp,diskmon_t * dmp)393724365f7Ssethg new_cfgdata(namevalpr_t *nvp, diskmon_t *dmp)
394724365f7Ssethg {
395724365f7Ssethg 	cfgdata_t *cdp = (cfgdata_t *)dzmalloc(sizeof (cfgdata_t));
396724365f7Ssethg 
397724365f7Ssethg 	if (nvp != NULL)
398724365f7Ssethg 		cdp->props = namevalpr_to_nvlist(nvp);
399724365f7Ssethg 	else if (nvlist_alloc(&cdp->props, NV_UNIQUE_NAME, 0) != 0) {
400724365f7Ssethg 		return (NULL);
401724365f7Ssethg 	}
402724365f7Ssethg 
403724365f7Ssethg 	if (dmp != NULL)
404724365f7Ssethg 		cdp->disk_list = dmp;
405724365f7Ssethg 	return (cdp);
406724365f7Ssethg 
407724365f7Ssethg }
408724365f7Ssethg 
409724365f7Ssethg static void
cfgdata_add_namevalpr(cfgdata_t * cfgp,namevalpr_t * nvp)410724365f7Ssethg cfgdata_add_namevalpr(cfgdata_t *cfgp, namevalpr_t *nvp)
411724365f7Ssethg {
412724365f7Ssethg 	if (cfgp->props == NULL) {
413724365f7Ssethg 		(void) nvlist_alloc(&cfgp->props, NV_UNIQUE_NAME, 0);
414724365f7Ssethg 	}
415724365f7Ssethg 	(void) nvlist_add_string(cfgp->props, nvp->name, nvp->value);
416724365f7Ssethg }
417724365f7Ssethg 
418724365f7Ssethg void
cfgdata_add_diskmon(cfgdata_t * cfgp,diskmon_t * dmp)419724365f7Ssethg cfgdata_add_diskmon(cfgdata_t *cfgp, diskmon_t *dmp)
420724365f7Ssethg {
421724365f7Ssethg 	if (cfgp->disk_list == NULL) {
422724365f7Ssethg 		cfgp->disk_list = dmp;
423724365f7Ssethg 	} else {
424724365f7Ssethg 		diskmon_t *disklist = cfgp->disk_list;
425724365f7Ssethg 
426724365f7Ssethg 		while (disklist->next != NULL)
427724365f7Ssethg 			disklist = disklist->next;
428724365f7Ssethg 
429724365f7Ssethg 		disklist->next = dmp;
430724365f7Ssethg 	}
431724365f7Ssethg }
432724365f7Ssethg 
433724365f7Ssethg static void
cfgdata_free(cfgdata_t * cdp)434724365f7Ssethg cfgdata_free(cfgdata_t *cdp)
435724365f7Ssethg {
436724365f7Ssethg 	nvlist_free(cdp->props);
437724365f7Ssethg 	diskmon_free(cdp->disk_list);
438724365f7Ssethg 	dfree(cdp, sizeof (cfgdata_t));
439724365f7Ssethg }
440724365f7Ssethg 
441724365f7Ssethg conf_err_t
check_indactions(ind_action_t * indrp)442724365f7Ssethg check_indactions(ind_action_t *indrp)
443724365f7Ssethg {
444724365f7Ssethg 	char *buf;
445724365f7Ssethg 	conf_err_t rv = E_NO_ERROR;
446724365f7Ssethg 	nvlist_t *nvp = NULL;
447724365f7Ssethg 	int len;
448724365f7Ssethg 
449724365f7Ssethg 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
450724365f7Ssethg 
451724365f7Ssethg 	/*
452724365f7Ssethg 	 * Check indicator actions for conflicts
453724365f7Ssethg 	 */
454724365f7Ssethg 	while (indrp != NULL && rv == E_NO_ERROR) {
455724365f7Ssethg 		len = strlen(indrp->ind_name) + 2;
456724365f7Ssethg 		buf = dmalloc(len);
457724365f7Ssethg 		(void) snprintf(buf, len, "%c%s",
458724365f7Ssethg 		    indrp->ind_state == INDICATOR_ON ? '+' : '-',
459724365f7Ssethg 		    indrp->ind_name);
460724365f7Ssethg 		switch (nvlist_lookup_boolean(nvp, buf)) {
461724365f7Ssethg 		case ENOENT:
462724365f7Ssethg 			(void) nvlist_add_boolean(nvp, buf);
463724365f7Ssethg 			break;
464724365f7Ssethg 		case 0:
465724365f7Ssethg 			rv = E_IND_ACTION_REDUNDANT;
466724365f7Ssethg 			break;
467724365f7Ssethg 		default:
468724365f7Ssethg 			break;
469724365f7Ssethg 		}
470724365f7Ssethg 
471724365f7Ssethg 		/* Look for the opposite action.  If found, that's an error */
472724365f7Ssethg 		(void) snprintf(buf, len, "%c%s",
473724365f7Ssethg 		    indrp->ind_state == INDICATOR_ON ? '-' : '+',
474724365f7Ssethg 		    indrp->ind_name);
475724365f7Ssethg 		switch (nvlist_lookup_boolean(nvp, buf)) {
476724365f7Ssethg 		case ENOENT:
477724365f7Ssethg 			break;
478724365f7Ssethg 		case 0:
479724365f7Ssethg 			rv = E_IND_ACTION_CONFLICT;
480724365f7Ssethg 			break;
481724365f7Ssethg 		default:
482724365f7Ssethg 			break;
483724365f7Ssethg 		}
484724365f7Ssethg 		dfree(buf, len);
485724365f7Ssethg 		indrp = indrp->next;
486724365f7Ssethg 	}
487724365f7Ssethg 
488724365f7Ssethg 	nvlist_free(nvp);
489724365f7Ssethg 	return (rv);
490724365f7Ssethg }
491724365f7Ssethg 
492724365f7Ssethg conf_err_t
check_inds(indicator_t * indp)493724365f7Ssethg check_inds(indicator_t *indp)
494724365f7Ssethg {
495724365f7Ssethg 	char *buf;
496724365f7Ssethg 	conf_err_t rv = E_NO_ERROR;
497724365f7Ssethg 	nvlist_t *nvp = NULL;
498724365f7Ssethg 	int len;
499724365f7Ssethg 	boolean_t fault_on = B_FALSE, fault_off = B_FALSE;
500724365f7Ssethg 
501724365f7Ssethg 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
502724365f7Ssethg 
503724365f7Ssethg 	/*
504724365f7Ssethg 	 * Check inds for multiple definitions (same identifier or same action)
505724365f7Ssethg 	 */
506724365f7Ssethg 	while (indp != NULL && rv == E_NO_ERROR) {
507724365f7Ssethg 		len = strlen(indp->ind_name) + 2;
508724365f7Ssethg 		buf = dmalloc(len);
509724365f7Ssethg 		(void) snprintf(buf, len, "%c%s",
510724365f7Ssethg 		    indp->ind_state == INDICATOR_ON ? '+' : '-',
511724365f7Ssethg 		    indp->ind_name);
512724365f7Ssethg 
513724365f7Ssethg 		/* Keep track of the +/-FAULT for checking later */
514724365f7Ssethg 		if (strcasecmp(buf, "+" INDICATOR_FAULT_IDENTIFIER) == 0)
515724365f7Ssethg 			fault_on = B_TRUE;
516724365f7Ssethg 		else if (strcasecmp(buf, "-" INDICATOR_FAULT_IDENTIFIER) == 0)
517724365f7Ssethg 			fault_off = B_TRUE;
518724365f7Ssethg 
519724365f7Ssethg 		switch (nvlist_lookup_boolean(nvp, buf)) {
520724365f7Ssethg 		case ENOENT:
521724365f7Ssethg 			(void) nvlist_add_boolean(nvp, buf);
522724365f7Ssethg 			break;
523724365f7Ssethg 		case 0:
524724365f7Ssethg 			rv = E_IND_MULTIPLY_DEFINED;
525724365f7Ssethg 			break;
526724365f7Ssethg 		default:
527724365f7Ssethg 			break;
528724365f7Ssethg 		}
529724365f7Ssethg 		dfree(buf, len);
530724365f7Ssethg 		indp = indp->next;
531724365f7Ssethg 	}
532724365f7Ssethg 
533724365f7Ssethg 	/*
534724365f7Ssethg 	 * Make sure we have a -FAULT and +FAULT
535724365f7Ssethg 	 */
536724365f7Ssethg 	if (!fault_on)
537724365f7Ssethg 		rv = E_IND_MISSING_FAULT_ON;
538724365f7Ssethg 	else if (!fault_off)
539724365f7Ssethg 		rv = E_IND_MISSING_FAULT_OFF;
540724365f7Ssethg 
541724365f7Ssethg 	nvlist_free(nvp);
542724365f7Ssethg 	return (rv);
543724365f7Ssethg }
544724365f7Ssethg 
545724365f7Ssethg conf_err_t
check_indrules(indrule_t * indrp,state_transition_t ** offender)546724365f7Ssethg check_indrules(indrule_t *indrp, state_transition_t **offender)
547724365f7Ssethg {
548724365f7Ssethg 	char buf[32];
549724365f7Ssethg 	conf_err_t rv = E_NO_ERROR;
550724365f7Ssethg 	nvlist_t *nvp = NULL;
551724365f7Ssethg 
552724365f7Ssethg 	/*
553724365f7Ssethg 	 * Ensure that no two rules have the same state transitions.
554724365f7Ssethg 	 */
555724365f7Ssethg 
556724365f7Ssethg 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
557724365f7Ssethg 
558724365f7Ssethg 	while (indrp != NULL && rv == E_NO_ERROR) {
559724365f7Ssethg 		(void) snprintf(buf, sizeof (buf), "%d-%d",
560724365f7Ssethg 		    (int)indrp->strans.begin, (int)indrp->strans.end);
561724365f7Ssethg 		switch (nvlist_lookup_boolean(nvp, buf)) {
562724365f7Ssethg 		case 0:
563724365f7Ssethg 			*offender = &indrp->strans;
564724365f7Ssethg 			rv = E_DUPLICATE_STATE_TRANSITION;
565724365f7Ssethg 			break;
566724365f7Ssethg 		case ENOENT:
567724365f7Ssethg 			(void) nvlist_add_boolean(nvp, buf);
568724365f7Ssethg 			break;
569724365f7Ssethg 		default:
570724365f7Ssethg 			break;
571724365f7Ssethg 		}
572724365f7Ssethg 		indrp = indrp->next;
573724365f7Ssethg 	}
574724365f7Ssethg 
575724365f7Ssethg 	nvlist_free(nvp);
576724365f7Ssethg 	return (rv);
577724365f7Ssethg }
578724365f7Ssethg 
579724365f7Ssethg 
580724365f7Ssethg conf_err_t
check_consistent_ind_indrules(indicator_t * indp,indrule_t * indrp,ind_action_t ** offender)581724365f7Ssethg check_consistent_ind_indrules(indicator_t *indp, indrule_t *indrp,
582724365f7Ssethg     ind_action_t **offender)
583724365f7Ssethg {
584724365f7Ssethg 	char *buf;
585724365f7Ssethg 	conf_err_t rv = E_NO_ERROR;
586724365f7Ssethg 	nvlist_t *nvp = NULL;
587724365f7Ssethg 	ind_action_t *alp;
588724365f7Ssethg 	int len;
589724365f7Ssethg 
590724365f7Ssethg 	/*
591724365f7Ssethg 	 * Ensure that every indicator action referenced in each ruleset
592724365f7Ssethg 	 * exists in the indicator list given.
593724365f7Ssethg 	 */
594724365f7Ssethg 
595724365f7Ssethg 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
596724365f7Ssethg 
597724365f7Ssethg 	while (indp != NULL) {
598724365f7Ssethg 		len = strlen(indp->ind_name) + 2;
599724365f7Ssethg 		buf = dmalloc(len);
600724365f7Ssethg 		(void) snprintf(buf, len, "%c%s",
601724365f7Ssethg 		    indp->ind_state == INDICATOR_ON ? '+' : '-',
602724365f7Ssethg 		    indp->ind_name);
603724365f7Ssethg 		(void) nvlist_add_boolean(nvp, buf);
604724365f7Ssethg 		dfree(buf, len);
605724365f7Ssethg 		indp = indp->next;
606724365f7Ssethg 	}
607724365f7Ssethg 
608724365f7Ssethg 	while (indrp != NULL && rv == E_NO_ERROR) {
609724365f7Ssethg 		alp = indrp->action_list;
610724365f7Ssethg 		while (alp != NULL && rv == E_NO_ERROR) {
611724365f7Ssethg 			len = strlen(alp->ind_name) + 2;
612724365f7Ssethg 			buf = dmalloc(len);
613724365f7Ssethg 			(void) snprintf(buf, len, "%c%s",
614724365f7Ssethg 			    alp->ind_state == INDICATOR_ON ? '+' : '-',
615724365f7Ssethg 			    alp->ind_name);
616724365f7Ssethg 
617724365f7Ssethg 			switch (nvlist_lookup_boolean(nvp, buf)) {
618724365f7Ssethg 			case 0:		/* Normal case */
619724365f7Ssethg 				break;
620724365f7Ssethg 			case ENOENT:
621724365f7Ssethg 				*offender = alp;
622724365f7Ssethg 				rv =
623724365f7Ssethg 				    E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION;
624724365f7Ssethg 				break;
625724365f7Ssethg 			default:
626724365f7Ssethg 				break;
627724365f7Ssethg 			}
628724365f7Ssethg 			dfree(buf, len);
629724365f7Ssethg 			alp = alp->next;
630724365f7Ssethg 		}
631724365f7Ssethg 		indrp = indrp->next;
632724365f7Ssethg 	}
633724365f7Ssethg 
634724365f7Ssethg 	nvlist_free(nvp);
635724365f7Ssethg 	return (rv);
636724365f7Ssethg }
637724365f7Ssethg 
638724365f7Ssethg conf_err_t
check_state_transition(hotplug_state_t s1,hotplug_state_t s2)639724365f7Ssethg check_state_transition(hotplug_state_t s1, hotplug_state_t s2)
640724365f7Ssethg {
641724365f7Ssethg 	/*
642724365f7Ssethg 	 * The following are valid transitions:
643724365f7Ssethg 	 *
644724365f7Ssethg 	 * HPS_ABSENT -> HPS_PRESENT
645724365f7Ssethg 	 * HPS_ABSENT -> HPS_CONFIGURED
646724365f7Ssethg 	 * HPS_PRESENT -> HPS_CONFIGURED
647724365f7Ssethg 	 * HPS_PRESENT -> HPS_ABSENT
648724365f7Ssethg 	 * HPS_CONFIGURED -> HPS_UNCONFIGURED
649724365f7Ssethg 	 * HPS_CONFIGURED -> HPS_ABSENT
650724365f7Ssethg 	 * HPS_UNCONFIGURED -> HPS_ABSENT
651724365f7Ssethg 	 * HPS_UNCONFIGURED -> HPS_CONFIGURED
652724365f7Ssethg 	 *
653724365f7Ssethg 	 */
654724365f7Ssethg 	if (s1 == HPS_ABSENT && s2 != HPS_PRESENT && s2 != HPS_CONFIGURED)
655724365f7Ssethg 		return (E_INVALID_STATE_CHANGE);
656724365f7Ssethg 	else if (s1 == HPS_PRESENT && (s2 != HPS_CONFIGURED &&
657724365f7Ssethg 	    s2 != HPS_ABSENT))
658724365f7Ssethg 		return (E_INVALID_STATE_CHANGE);
659724365f7Ssethg 	else if (s1 == HPS_CONFIGURED && (s2 != HPS_UNCONFIGURED &&
660724365f7Ssethg 	    s2 != HPS_ABSENT))
661724365f7Ssethg 		return (E_INVALID_STATE_CHANGE);
662724365f7Ssethg 	else if (s1 == HPS_UNCONFIGURED && (s2 != HPS_ABSENT &&
663724365f7Ssethg 	    s2 != HPS_CONFIGURED))
664724365f7Ssethg 		return (E_INVALID_STATE_CHANGE);
665724365f7Ssethg 	else
666724365f7Ssethg 		return (E_NO_ERROR);
667724365f7Ssethg }
668724365f7Ssethg 
669724365f7Ssethg static void
print_inds(indicator_t * indp,FILE * fp,char * prefix)670724365f7Ssethg print_inds(indicator_t *indp, FILE *fp, char *prefix)
671724365f7Ssethg {
672724365f7Ssethg 	char plusminus;
673724365f7Ssethg 
674724365f7Ssethg 	(void) fprintf(fp, "%sindicators {\n", prefix);
675724365f7Ssethg 	while (indp != NULL) {
676724365f7Ssethg 		plusminus = (indp->ind_state == INDICATOR_ON) ? '+' : '-';
677724365f7Ssethg 		(void) fprintf(fp, "%s\t%c%s = \"%s\"\n", prefix, plusminus,
678724365f7Ssethg 		    indp->ind_name, indp->ind_instr_spec);
679724365f7Ssethg 		indp = indp->next;
680724365f7Ssethg 	}
681724365f7Ssethg 	(void) fprintf(fp, "%s}\n", prefix);
682724365f7Ssethg }
683724365f7Ssethg 
684724365f7Ssethg static void
print_indrules(indrule_t * lrp,FILE * fp,char * prefix)685724365f7Ssethg print_indrules(indrule_t *lrp, FILE *fp, char *prefix)
686724365f7Ssethg {
687724365f7Ssethg 	char plusminus;
688724365f7Ssethg 	ind_action_t *lap;
689724365f7Ssethg 
690724365f7Ssethg 	(void) fprintf(fp, "%sindicator_rules {\n", prefix);
691724365f7Ssethg 	while (lrp != NULL) {
692724365f7Ssethg 		(void) fprintf(fp, "%s\t%12s -> %12s\t{ ", prefix,
693724365f7Ssethg 		    hotplug_state_string(lrp->strans.begin),
694724365f7Ssethg 		    hotplug_state_string(lrp->strans.end));
695724365f7Ssethg 		lap = lrp->action_list;
696724365f7Ssethg 		while (lap != NULL) {
697724365f7Ssethg 			plusminus = (lap->ind_state == INDICATOR_ON)
698724365f7Ssethg 			    ? '+' : '-';
699724365f7Ssethg 			(void) fprintf(fp, "%c%s", plusminus, lap->ind_name);
700724365f7Ssethg 			lap = lap->next;
701724365f7Ssethg 			if (lap != NULL)
702724365f7Ssethg 				(void) fprintf(fp, ", ");
703724365f7Ssethg 		}
704724365f7Ssethg 		(void) fprintf(fp, " }\n");
705724365f7Ssethg 		lrp = lrp->next;
706724365f7Ssethg 	}
707724365f7Ssethg 	(void) fprintf(fp, "%s}\n", prefix);
708724365f7Ssethg }
709724365f7Ssethg 
710724365f7Ssethg static void
print_props(nvlist_t * nvlp,FILE * fp,char * prefix)711724365f7Ssethg print_props(nvlist_t *nvlp, FILE *fp, char *prefix)
712724365f7Ssethg {
713724365f7Ssethg 	nvpair_t *nvp = nvlist_next_nvpair(nvlp, NULL);
714724365f7Ssethg 	char *name, *str;
715724365f7Ssethg 
716724365f7Ssethg 	while (nvp != NULL) {
7177a0b67e3Ssethg 		dm_assert(nvpair_type(nvp) == DATA_TYPE_STRING);
718724365f7Ssethg 		name = nvpair_name(nvp);
719724365f7Ssethg 		(void) nvlist_lookup_string(nvlp, name, &str);
720724365f7Ssethg 		(void) fprintf(fp, "%s%s = \"%s\"\n", prefix, name, str);
721724365f7Ssethg 		nvp = nvlist_next_nvpair(nvlp, nvp);
722724365f7Ssethg 	}
723724365f7Ssethg }
724724365f7Ssethg 
725724365f7Ssethg static void
print_ap(nvlist_t * dpp,FILE * fp,char * prefix)726724365f7Ssethg print_ap(nvlist_t *dpp, FILE *fp, char *prefix)
727724365f7Ssethg {
728724365f7Ssethg 	int len = strlen(prefix) + 2;
729724365f7Ssethg 	char *buf = dmalloc(len);
730724365f7Ssethg 
731724365f7Ssethg 	(void) snprintf(buf, len, "%s\t", prefix);
732724365f7Ssethg 
733724365f7Ssethg 	(void) fprintf(fp, "%sap_props {\n", prefix);
734724365f7Ssethg 	print_props(dpp, fp, buf);
735724365f7Ssethg 	(void) fprintf(fp, "%s}\n", prefix);
736724365f7Ssethg 
737724365f7Ssethg 	dfree(buf, len);
738724365f7Ssethg }
739724365f7Ssethg 
740724365f7Ssethg static void
print_disks(diskmon_t * dmp,FILE * fp,char * prefix)741724365f7Ssethg print_disks(diskmon_t *dmp, FILE *fp, char *prefix)
742724365f7Ssethg {
743724365f7Ssethg 	int len = strlen(prefix) + 2;
744724365f7Ssethg 	char *buf = dmalloc(len);
745724365f7Ssethg 
746724365f7Ssethg 	(void) snprintf(buf, len, "%s\t", prefix);
747724365f7Ssethg 
748724365f7Ssethg 	while (dmp != NULL) {
749724365f7Ssethg 		(void) fprintf(fp, "%sdisk \"%s\" {\n", prefix, dmp->location);
750724365f7Ssethg 		if (dmp->props) {
751724365f7Ssethg 			print_props(dmp->props, fp, buf);
752724365f7Ssethg 		}
753724365f7Ssethg 		if (dmp->app_props) {
754724365f7Ssethg 			print_ap(dmp->app_props, fp, buf);
755724365f7Ssethg 		}
756724365f7Ssethg 		(void) fprintf(fp, "%s\n", prefix);
757724365f7Ssethg 		print_inds(dmp->ind_list, fp, buf);
758724365f7Ssethg 		(void) fprintf(fp, "%s\n", prefix);
759724365f7Ssethg 		print_indrules(dmp->indrule_list, fp, buf);
760724365f7Ssethg 		(void) fprintf(fp, "%s}\n", prefix);
761724365f7Ssethg 
762724365f7Ssethg 		if (dmp->next != NULL)
763724365f7Ssethg 			(void) fprintf(fp, "%s\n", prefix);
764724365f7Ssethg 
765724365f7Ssethg 		dmp = dmp->next;
766724365f7Ssethg 	}
767724365f7Ssethg 
768724365f7Ssethg 	dfree(buf, len);
769724365f7Ssethg }
770724365f7Ssethg 
771724365f7Ssethg static void
print_cfgdata(cfgdata_t * cfgp,FILE * fp,char * prefix)772724365f7Ssethg print_cfgdata(cfgdata_t *cfgp, FILE *fp, char *prefix)
773724365f7Ssethg {
774724365f7Ssethg 	/* First, print the properties, then the disks */
775724365f7Ssethg 
776724365f7Ssethg 	print_props(cfgp->props, fp, prefix);
777724365f7Ssethg 	(void) fprintf(fp, "%s\n", prefix);
778724365f7Ssethg 	print_disks(cfgp->disk_list, fp, prefix);
779724365f7Ssethg }
780724365f7Ssethg 
781724365f7Ssethg int
config_init(void)782724365f7Ssethg config_init(void)
783724365f7Ssethg {
7847a0b67e3Ssethg 	if (init_configuration_from_topo() == 0) {
785724365f7Ssethg 		config_data = new_cfgdata(NULL, NULL);
786724365f7Ssethg 		return (0);
787724365f7Ssethg 	}
788724365f7Ssethg 	return (-1);
789724365f7Ssethg }
790724365f7Ssethg 
791724365f7Ssethg int
config_get(fmd_hdl_t * hdl,const fmd_prop_t * fmd_props)792724365f7Ssethg config_get(fmd_hdl_t *hdl, const fmd_prop_t *fmd_props)
793724365f7Ssethg {
794724365f7Ssethg 	int err, i = 0;
795724365f7Ssethg 	char *str = NULL;
796724365f7Ssethg 	namevalpr_t nvp;
797724365f7Ssethg 	uint64_t u64;
798724365f7Ssethg 	boolean_t intfound = B_FALSE, strfound = B_FALSE;
799724365f7Ssethg #define	INT64_BUF_LEN 128
800724365f7Ssethg 	char buf[INT64_BUF_LEN];
801724365f7Ssethg 
802724365f7Ssethg 	u64 = fmd_prop_get_int32(hdl, GLOBAL_PROP_LOG_LEVEL);
803724365f7Ssethg 	g_verbose = (int)u64;
804724365f7Ssethg 
8050eb822a1Scindi 	err = update_configuration_from_topo(hdl, NULL);
806724365f7Ssethg 
807724365f7Ssethg 	/* Pull in the properties from the DE configuration file */
808724365f7Ssethg 	while (fmd_props[i].fmdp_name != NULL) {
809724365f7Ssethg 
810724365f7Ssethg 		nvp.name = (char *)fmd_props[i].fmdp_name;
811724365f7Ssethg 
812724365f7Ssethg 		switch (fmd_props[i].fmdp_type) {
813724365f7Ssethg 		case FMD_TYPE_UINT32:
814724365f7Ssethg 		case FMD_TYPE_INT32:
815724365f7Ssethg 			intfound = B_TRUE;
816724365f7Ssethg 			u64 = fmd_prop_get_int32(hdl, fmd_props[i].fmdp_name);
817724365f7Ssethg 			break;
818724365f7Ssethg 		case FMD_TYPE_UINT64:
819724365f7Ssethg 		case FMD_TYPE_INT64:
820724365f7Ssethg 			intfound = B_TRUE;
821724365f7Ssethg 			u64 = fmd_prop_get_int64(hdl, fmd_props[i].fmdp_name);
822724365f7Ssethg 			break;
823724365f7Ssethg 		case FMD_TYPE_STRING:
824724365f7Ssethg 			strfound = B_TRUE;
825724365f7Ssethg 			str = fmd_prop_get_string(hdl, fmd_props[i].fmdp_name);
826724365f7Ssethg 			break;
827724365f7Ssethg 
828724365f7Ssethg 		}
829724365f7Ssethg 
830724365f7Ssethg 		if (intfound) {
831724365f7Ssethg 			(void) snprintf(buf, INT64_BUF_LEN, "0x%llx", u64);
832724365f7Ssethg 			nvp.value = buf;
833724365f7Ssethg 			intfound = B_FALSE;
834724365f7Ssethg 		} else if (strfound) {
835724365f7Ssethg 			nvp.value = str;
836724365f7Ssethg 		}
837724365f7Ssethg 
838724365f7Ssethg 		log_msg(MM_CONF, "Adding property `%s' with value `%s'\n",
839724365f7Ssethg 		    nvp.name, nvp.value);
840724365f7Ssethg 
841724365f7Ssethg 		cfgdata_add_namevalpr(config_data, &nvp);
842724365f7Ssethg 
843724365f7Ssethg 		if (strfound) {
844724365f7Ssethg 			strfound = B_FALSE;
845724365f7Ssethg 			fmd_prop_free_string(hdl, str);
846724365f7Ssethg 		}
847724365f7Ssethg 
848724365f7Ssethg 
849724365f7Ssethg 		i++;
850724365f7Ssethg 	}
851724365f7Ssethg 
852724365f7Ssethg 	if ((g_verbose & (MM_CONF|MM_OTHER)) == (MM_CONF|MM_OTHER))
853724365f7Ssethg 		print_cfgdata(config_data, stderr, "");
854724365f7Ssethg 
855724365f7Ssethg 	return (err);
856724365f7Ssethg }
857724365f7Ssethg 
858724365f7Ssethg void
config_fini(void)859724365f7Ssethg config_fini(void)
860724365f7Ssethg {
8617a0b67e3Ssethg 	fini_configuration_from_topo();
862724365f7Ssethg 	cfgdata_free(config_data);
863724365f7Ssethg 	config_data = NULL;
864724365f7Ssethg }
865724365f7Ssethg 
866724365f7Ssethg nvlist_t *
dm_global_proplist(void)867724365f7Ssethg dm_global_proplist(void)
868724365f7Ssethg {
869724365f7Ssethg 	return (config_data->props);
870724365f7Ssethg }
871