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