xref: /titanic_41/usr/src/cmd/lvm/metassist/common/volume_defaults.c (revision 8d483882aa3390058094b043f3d62187b5d1de03)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 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 #include <string.h>
30 #include <libintl.h>
31 #include "volume_defaults.h"
32 #include "volume_error.h"
33 
34 /*
35  * Methods which manipulate a defaults_t struct
36  */
37 
38 static int defaults_get_singleton_component(
39 	defaults_t *defaults, char *disksetname,
40 	component_type_t type, devconfig_t **component, boolean_t create);
41 
42 /*
43  * Constructor: Create a defaults_t struct populated with default
44  * values. This defaults_t must be freed.
45  *
46  * @param       defaults
47  *              RETURN: a pointer to a new defaults_t
48  *
49  * @return      0
50  *              if successful
51  *
52  * @return      non-zero
53  *              if an error occurred.  Use get_error_string() to
54  *              retrieve the associated error message.
55  */
56 int
57 new_defaults(
58 	defaults_t **defaults)
59 {
60 	devconfig_t *diskset;
61 	int error = 0;
62 
63 	*defaults = (defaults_t *)calloc(1, sizeof (defaults_t));
64 	if (*defaults == NULL) {
65 	    volume_set_error(gettext("new_defaults calloc() failed"));
66 	    return (-1);
67 	}
68 
69 	/*
70 	 * Create initial "global" (disk set-independent) defaults, as
71 	 * a devconfig_t of type disk set with NULL name
72 	 */
73 	if ((error = new_devconfig(&diskset, TYPE_DISKSET)) != 0) {
74 	    free_defaults(*defaults);
75 	    return (error);
76 	}
77 
78 	/* Append global defaults disk set to disksets */
79 	defaults_set_disksets(
80 	    *defaults, dlist_append(dlist_new_item(diskset),
81 	    defaults_get_disksets(*defaults), AT_TAIL));
82 
83 	/* Set defaults */
84 	if ((error = defaults_set_mirror_nsubs(
85 		*defaults, NULL, DEFAULT_MIRROR_NSUBS)) != 0 ||
86 
87 	    (error = defaults_set_mirror_read(
88 		*defaults, NULL, DEFAULT_MIRROR_READ)) != 0 ||
89 
90 	    (error = defaults_set_mirror_write(
91 		*defaults, NULL, DEFAULT_MIRROR_WRITE)) != 0 ||
92 
93 	    (error = defaults_set_mirror_pass(
94 		*defaults, NULL, DEFAULT_MIRROR_PASS)) != 0 ||
95 
96 	    (error = defaults_set_mirror_usehsp(
97 		*defaults, NULL, DEFAULT_MIRROR_USEHSP)) != 0 ||
98 
99 	    (error = defaults_set_concat_usehsp(
100 		*defaults, NULL, DEFAULT_CONCAT_USEHSP)) != 0 ||
101 
102 	    (error = defaults_set_stripe_interlace(
103 		*defaults, NULL, DEFAULT_STRIPE_INTERLACE)) != 0 ||
104 
105 	    (error = defaults_set_stripe_mincomp(
106 		*defaults, NULL, DEFAULT_STRIPE_MINCOMP)) != 0 ||
107 
108 	    (error = defaults_set_stripe_maxcomp(
109 		*defaults, NULL, DEFAULT_STRIPE_MAXCOMP)) != 0 ||
110 
111 	    (error = defaults_set_stripe_usehsp(
112 		*defaults, NULL, DEFAULT_STRIPE_USEHSP)) != 0 ||
113 
114 	    (error = defaults_set_volume_redundancy_level(
115 		*defaults, NULL, DEFAULT_VOLUME_REDUND_LEVEL)) != 0 ||
116 
117 	    (error = defaults_set_volume_npaths(
118 		*defaults, NULL, DEFAULT_VOLUME_NPATHS)) != 0 ||
119 
120 	    (error = defaults_set_volume_usehsp(
121 		*defaults, NULL, DEFAULT_VOLUME_USEHSP)) != 0) {
122 
123 	    free_defaults(*defaults);
124 	    return (error);
125 	}
126 
127 	return (0);
128 }
129 
130 /*
131  * Free memory (recursively) allocated to a defaults_t struct
132  *
133  * @param       arg
134  *              pointer to the defaults_t struct to free
135  */
136 void
137 free_defaults(
138 	void *arg)
139 {
140 	defaults_t *defaults = (defaults_t *)arg;
141 
142 	if (defaults == NULL) {
143 	    return;
144 	}
145 
146 	/* Free the disksets */
147 	if (defaults->disksets != NULL) {
148 	    dlist_free_items(defaults->disksets, free_devconfig);
149 	}
150 
151 	/* Free the devconfig itself */
152 	free(defaults);
153 }
154 
155 /*
156  * Set list of diskset specific defaults
157  *
158  * @param       defaults
159  *              a defaults_t hierarchy representing default settings
160  *              for all disk sets and specific disk sets
161  *
162  * @param       disksets
163  *              a dlist_t representing the defaults for specific
164  *              named disk sets
165  */
166 void
167 defaults_set_disksets(
168 	defaults_t *defaults,
169 	dlist_t *disksets)
170 {
171 	defaults->disksets = disksets;
172 }
173 
174 /*
175  * Get list of diskset specific defaults
176  *
177  * @param       defaults
178  *              a defaults_t hierarchy representing default settings
179  *              for all disk sets and specific disk sets
180  *
181  * @return      a dlist_t representing the defaults for specific
182  *              named disk sets
183  */
184 dlist_t *
185 defaults_get_disksets(
186 	defaults_t *defaults)
187 {
188 	return (defaults->disksets);
189 }
190 
191 /*
192  * Get a disk set with the given name from the given defaults_t
193  *
194  * @param       defaults
195  *              a defaults_t hierarchy representing default settings
196  *              for all disk sets and specific disk sets
197  *
198  * @param       name
199  *              the name of the disk set whose defaults to retrieve,
200  *              or NULL to get the defaults for all disk sets
201  *
202  * @param       diskset
203  *              RETURN: defaults for the given named disk set, or
204  *              defaults for all disk sets if name is NULL
205  *
206  * @return      ENOENT
207  *              if the named disk set does not exist
208  *
209  * @return      0
210  *              if the named disk set exists
211  */
212 int
213 defaults_get_diskset_by_name(
214 	defaults_t *defaults,
215 	char *name,
216 	devconfig_t **diskset)
217 {
218 	dlist_t *list;
219 	*diskset = NULL;
220 
221 	/* Get list of disk sets */
222 	list = defaults_get_disksets(defaults);
223 	if (list != NULL) {
224 
225 	    /* For each disk set-specific defaults... */
226 	    for (; list != NULL; list = list->next) {
227 
228 		char *dname = NULL;
229 		devconfig_t *d = (devconfig_t *)list->obj;
230 
231 		/* Get the name if this disk set */
232 		devconfig_get_name(d, &dname);
233 
234 		/* Do the names match? */
235 		if (
236 		    /* Global defaults disk set */
237 		    (name == NULL && dname == NULL) ||
238 
239 		    /* Named disk set */
240 		    (name != NULL && dname != NULL &&
241 			strcmp(name, dname) == 0)) {
242 
243 		    *diskset = d;
244 		    break;
245 		}
246 	    }
247 	}
248 
249 	/* Diskset doesn't exist */
250 	if (*diskset == NULL) {
251 	    return (ENOENT);
252 	}
253 
254 	return (0);
255 }
256 
257 /*
258  * Get the first component of the given type from the given disk set.
259  * If not found, create the component if requested.
260  *
261  * @return      ENOENT
262  *              if the given disk set does not exist, or it exists,
263  *              but the requested component does not exist under it
264  *              and its creation was not requested
265  *
266  * @return      0
267  *              if the requested component exists or was created
268  *
269  * @return      non-zero
270  *              if the requested component does not exist and could
271  *              not be created
272  */
273 static int
274 defaults_get_singleton_component(
275 	defaults_t *defaults,
276 	char *disksetname,
277 	component_type_t type,
278 	devconfig_t **component,
279 	boolean_t create)
280 {
281 	int error;
282 	devconfig_t *diskset;
283 
284 	/* Get the disk set referred to */
285 	if ((error = defaults_get_diskset_by_name(
286 	    defaults, disksetname, &diskset)) != 0) {
287 
288 	    volume_set_error(
289 		gettext("could not get defaults for disk set %s"),
290 		disksetname == NULL ? gettext("<NULL>") : disksetname);
291 
292 	    return (error);
293 	}
294 
295 	/*
296 	 * Get the singleton component under this disk set, create if
297 	 * requested
298 	 */
299 	return (devconfig_get_component(diskset, type, component, create));
300 }
301 
302 /*
303  * Set name of the the default HSP to use
304  *
305  * @param       defaults
306  *              a defaults_t hierarchy representing default settings
307  *              for all disk sets and specific disk sets
308  *
309  * @param       diskset
310  *              the name of the disk set to which to apply this
311  *              default setting, or NULL to apply default
312  *              setting to all disk sets
313  *
314  * @param       name
315  *              the name of the default HSP to use
316  *
317  * @return      0
318  *              if successful
319  *
320  * @return      non-zero
321  *              if an error occurred.  Use get_error_string() to
322  *              retrieve the associated error message.
323  */
324 int
325 defaults_set_hsp_name(
326 	defaults_t *defaults,
327 	char *diskset,
328 	char *name)
329 {
330 	devconfig_t *hsp = NULL;
331 	int error = 0;
332 
333 	/* Get/create singleton HSP element for this disk set */
334 	if ((error = defaults_get_singleton_component(
335 		defaults, diskset, TYPE_HSP, &hsp, TRUE)) != 0) {
336 	    /* volume_set_error already called */
337 	    return (error);
338 	}
339 
340 	/* Set the name attribute */
341 	return (devconfig_set_hsp_name(hsp, name));
342 }
343 
344 /*
345  * Get the name of the default HSP to use
346  *
347  * @param       defaults
348  *              a defaults_t hierarchy representing default settings
349  *              for all disk sets and specific disk sets
350  *
351  * @param       diskset
352  *              the name of the disk set to which to apply this
353  *              default setting, or NULL to apply default
354  *              setting to all disk sets
355  *
356  * @param       name
357  *              RETURN: the name of the default HSP to use
358  *
359  * @return      0
360  *              if successful
361  *
362  * @return      non-zero
363  *              if an error occurred.  Use get_error_string() to
364  *              retrieve the associated error message.
365  */
366 int
367 defaults_get_hsp_name(
368     defaults_t *defaults,
369     char *diskset,
370     char **name)
371 {
372 	char *disksets[2];
373 	devconfig_t *hsp;
374 	int error;
375 	int i = 0;
376 
377 	/* Check both the given and global (NULL) disk sets for the value */
378 	disksets[0] = diskset;
379 	disksets[1] = NULL;
380 	do {
381 	    /* Get/create singleton HSP element for this disk set */
382 	    error = defaults_get_singleton_component(
383 		defaults, disksets[i], TYPE_HSP, &hsp, FALSE);
384 
385 	    switch (error) {
386 		/* HSP found for this disk set */
387 		case 0:
388 		    /* Get the nsubs attribute */
389 		    if ((error = devconfig_get_name(hsp, name)) == 0) {
390 			/* nsubs attribute found */
391 			return (0);
392 		    }
393 
394 		/* FALLTHROUGH */
395 
396 		/* HSP not found for this disk set */
397 		case ENOENT:
398 		break;
399 
400 		/* Invalid disk set, or HSP couldn't be created */
401 		default:
402 		    /* volume_set_error already called */
403 		    return (error);
404 	    }
405 
406 	/* Stop after the global (NULL) disk set has been searched */
407 	} while (disksets[i++] != NULL);
408 
409 	return (ENOENT);
410 }
411 
412 /*
413  * Set the default number of submirrors for mirrored volumes
414  *
415  * @param       defaults
416  *              a defaults_t hierarchy representing default settings
417  *              for all disk sets and specific disk sets
418  *
419  * @param       diskset
420  *              the name of the disk set to which to apply this
421  *              default setting, or NULL to apply default
422  *              setting to all disk sets
423  *
424  * @param       val
425  *              the value to set as the default number of submirrors
426  *              for mirrored volumes
427  *
428  * @return      0
429  *              if successful
430  *
431  * @return      non-zero
432  *              if an error occurred.  Use get_error_string() to
433  *              retrieve the associated error message.
434  */
435 int
436 defaults_set_mirror_nsubs(
437 	defaults_t *defaults,
438 	char *diskset,
439 	uint16_t val)
440 {
441 	devconfig_t *mirror = NULL;
442 	int error = 0;
443 
444 	/* Get/create singleton mirror element for this disk set */
445 	if ((error = defaults_get_singleton_component(
446 		defaults, diskset, TYPE_MIRROR, &mirror, TRUE)) != 0) {
447 	    /* volume_set_error already called */
448 	    return (error);
449 	}
450 
451 	/* Set the nsubs attribute */
452 	return (devconfig_set_mirror_nsubs(mirror, val));
453 }
454 
455 /*
456  * Get the default number of submirrors for mirrored volumes
457  *
458  * @param       defaults
459  *              a defaults_t hierarchy representing default settings
460  *              for all disk sets and specific disk sets
461  *
462  * @param       diskset
463  *              the name of the disk set to which to apply this
464  *              default setting, or NULL to apply default
465  *              setting to all disk sets
466  *
467  * @param       val
468  *              RETURN: the default number of submirrors for mirrored
469  *              volumes
470  *
471  * @return      0
472  *              if successful
473  *
474  * @return      non-zero
475  *              if an error occurred.  Use get_error_string() to
476  *              retrieve the associated error message.
477  */
478 int
479 defaults_get_mirror_nsubs(
480 	defaults_t *defaults,
481 	char *diskset,
482 	uint16_t *val)
483 {
484 	char *disksets[2];
485 	devconfig_t *mirror;
486 	int error;
487 	int i = 0;
488 
489 	/* Check both the given and global (NULL) disk sets for the value */
490 	disksets[0] = diskset;
491 	disksets[1] = NULL;
492 	do {
493 	    /* Get/create singleton mirror element for this disk set */
494 	    error = defaults_get_singleton_component(
495 		defaults, disksets[i], TYPE_MIRROR, &mirror, FALSE);
496 
497 	    switch (error) {
498 		/* mirror found for this disk set */
499 		case 0:
500 		    /* Get the nsubs attribute */
501 		    if ((error = devconfig_get_mirror_nsubs(
502 			    mirror, val)) == 0) {
503 			/* nsubs attribute found */
504 			return (0);
505 		    }
506 
507 		/* FALLTHROUGH */
508 
509 		/* mirror not found for this disk set */
510 		case ENOENT:
511 		break;
512 
513 		/* Invalid disk set, or mirror couldn't be created */
514 		default:
515 		    /* volume_set_error already called */
516 		    return (error);
517 	    }
518 
519 	/* Stop after the global (NULL) disk set has been searched */
520 	} while (disksets[i++] != NULL);
521 
522 	return (ENOENT);
523 }
524 
525 /*
526  * Set the default read strategy for mirrored volumes
527  *
528  * @param       defaults
529  *              a defaults_t hierarchy representing default settings
530  *              for all disk sets and specific disk sets
531  *
532  * @param       diskset
533  *              the name of the disk set to which to apply this
534  *              default setting, or NULL to apply default
535  *              setting to all disk sets
536  *
537  * @param       val
538  *              the value to set as the default read strategy for
539  *              mirrored volumes
540  *
541  * @return      0
542  *              if successful
543  *
544  * @return      non-zero
545  *              if an error occurred.  Use get_error_string() to
546  *              retrieve the associated error message.
547  */
548 int
549 defaults_set_mirror_read(
550 	defaults_t *defaults,
551 	char *diskset,
552 	mirror_read_strategy_t val)
553 {
554 	devconfig_t *mirror = NULL;
555 	int error = 0;
556 
557 	/* Get/create singleton mirror element for this disk set */
558 	if ((error = defaults_get_singleton_component(
559 		defaults, diskset, TYPE_MIRROR, &mirror, TRUE)) != 0) {
560 	    /* volume_set_error already called */
561 	    return (error);
562 	}
563 
564 	/* Set the read attribute */
565 	return (devconfig_set_mirror_read(mirror, val));
566 }
567 
568 /*
569  * Get the default read strategy for mirrored volumes
570  *
571  * @param       defaults
572  *              a defaults_t hierarchy representing default settings
573  *              for all disk sets and specific disk sets
574  *
575  * @param       diskset
576  *              the name of the disk set to which to apply this
577  *              default setting, or NULL to apply default
578  *              setting to all disk sets
579  *
580  * @param       val
581  *              RETURN: the default read strategy for mirrored volumes
582  *
583  * @return      0
584  *              if successful
585  *
586  * @return      non-zero
587  *              if an error occurred.  Use get_error_string() to
588  *              retrieve the associated error message.
589  */
590 int
591 defaults_get_mirror_read(
592 	defaults_t *defaults,
593 	char *diskset,
594 	mirror_read_strategy_t *val)
595 {
596 	char *disksets[2];
597 	devconfig_t *mirror;
598 	int error;
599 	int i = 0;
600 
601 	/* Check both the given and global (NULL) disk sets for the value */
602 	disksets[0] = diskset;
603 	disksets[1] = NULL;
604 	do {
605 	    /* Get/create singleton mirror element for this disk set */
606 	    error = defaults_get_singleton_component(
607 		defaults, disksets[i], TYPE_MIRROR, &mirror, FALSE);
608 
609 	    switch (error) {
610 		/* mirror found for this disk set */
611 		case 0:
612 		    /* Get the read attribute */
613 		    if ((error = devconfig_get_mirror_read(mirror, val)) == 0) {
614 			/* read attribute found */
615 			return (0);
616 		    }
617 
618 		/* FALLTHROUGH */
619 
620 		/* mirror not found for this disk set */
621 		case ENOENT:
622 		break;
623 
624 		/* Invalid disk set, or mirror couldn't be created */
625 		default:
626 		    /* volume_set_error already called */
627 		    return (error);
628 	    }
629 
630 	/* Stop after the global (NULL) disk set has been searched */
631 	} while (disksets[i++] != NULL);
632 
633 	return (ENOENT);
634 }
635 
636 /*
637  * Set the default write strategy for mirrored volumes
638  *
639  * @param       defaults
640  *              a defaults_t hierarchy representing default settings
641  *              for all disk sets and specific disk sets
642  *
643  * @param       diskset
644  *              the name of the disk set to which to apply this
645  *              default setting, or NULL to apply default
646  *              setting to all disk sets
647  *
648  * @param       val
649  *              the value to set as the default write strategy for
650  *              mirrored volumes
651  *
652  * @return      0
653  *              if successful
654  *
655  * @return      non-zero
656  *              if an error occurred.  Use get_error_string() to
657  *              retrieve the associated error message.
658  */
659 int
660 defaults_set_mirror_write(
661 	defaults_t *defaults,
662 	char *diskset,
663 	mirror_write_strategy_t val)
664 {
665 	devconfig_t *mirror = NULL;
666 	int error = 0;
667 
668 	/* Get/create singleton mirror element for this disk set */
669 	if ((error = defaults_get_singleton_component(
670 		defaults, diskset, TYPE_MIRROR, &mirror, TRUE)) != 0) {
671 	    /* volume_set_error already called */
672 	    return (error);
673 	}
674 
675 	/* Set the write attribute */
676 	return (devconfig_set_mirror_write(mirror, val));
677 }
678 
679 /*
680  * Get the default write strategy for mirrored volumes
681  *
682  * @param       defaults
683  *              a defaults_t hierarchy representing default settings
684  *              for all disk sets and specific disk sets
685  *
686  * @param       diskset
687  *              the name of the disk set to which to apply this
688  *              default setting, or NULL to apply default
689  *              setting to all disk sets
690  *
691  * @param       val
692  *              RETURN: the default write strategy for mirrored
693  *              volumes
694  *
695  * @return      0
696  *              if successful
697  *
698  * @return      non-zero
699  *              if an error occurred.  Use get_error_string() to
700  *              retrieve the associated error message.
701  */
702 int
703 defaults_get_mirror_write(
704 	defaults_t *defaults,
705 	char *diskset,
706 	mirror_write_strategy_t *val)
707 {
708 	char *disksets[2];
709 	devconfig_t *mirror;
710 	int error;
711 	int i = 0;
712 
713 	/* Check both the given and global (NULL) disk sets for the value */
714 	disksets[0] = diskset;
715 	disksets[1] = NULL;
716 	do {
717 	    /* Get/create singleton mirror element for this disk set */
718 	    error = defaults_get_singleton_component(
719 		defaults, disksets[i], TYPE_MIRROR, &mirror, FALSE);
720 
721 	    switch (error) {
722 		/* mirror found for this disk set */
723 		case 0:
724 		    /* Get the write attribute */
725 		    if ((error = devconfig_get_mirror_write(
726 			    mirror, val)) == 0) {
727 			/* write attribute found */
728 			return (0);
729 		    }
730 
731 		/* FALLTHROUGH */
732 
733 		/* mirror not found for this disk set */
734 		case ENOENT:
735 		break;
736 
737 		/* Invalid disk set, or mirror couldn't be created */
738 		default:
739 		    /* volume_set_error already called */
740 		    return (error);
741 	    }
742 
743 	/* Stop after the global (NULL) disk set has been searched */
744 	} while (disksets[i++] != NULL);
745 
746 	return (ENOENT);
747 }
748 
749 /*
750  * Set the default resync pass for mirrored volumes
751  *
752  * @param       defaults
753  *              a defaults_t hierarchy representing default settings
754  *              for all disk sets and specific disk sets
755  *
756  * @param       diskset
757  *              the name of the disk set to which to apply this
758  *              default setting, or NULL to apply default
759  *              setting to all disk sets
760  *
761  * @param       val
762  *              the value to set as the default resync pass for
763  *              mirrored volumes
764  *
765  * @return      0
766  *              if successful
767  *
768  * @return      non-zero
769  *              if an error occurred.  Use get_error_string() to
770  *              retrieve the associated error message.
771  */
772 int
773 defaults_set_mirror_pass(
774 	defaults_t *defaults,
775 	char *diskset,
776 	uint16_t val)
777 {
778 	devconfig_t *mirror = NULL;
779 	int error = 0;
780 
781 	/* Get/create singleton mirror element for this disk set */
782 	if ((error = defaults_get_singleton_component(
783 		defaults, diskset, TYPE_MIRROR, &mirror, TRUE)) != 0) {
784 	    /* volume_set_error already called */
785 	    return (error);
786 	}
787 
788 	/* Set the pass attribute */
789 	return (devconfig_set_mirror_pass(mirror, val));
790 }
791 
792 /*
793  * Get the default resync pass for mirrored volumes
794  *
795  * @param       defaults
796  *              a defaults_t hierarchy representing default settings
797  *              for all disk sets and specific disk sets
798  *
799  * @param       diskset
800  *              the name of the disk set to which to apply this
801  *              default setting, or NULL to apply default
802  *              setting to all disk sets
803  *
804  * @param       val
805  *              RETURN: the default resync pass for mirrored volumes
806  *
807  * @return      0
808  *              if successful
809  *
810  * @return      non-zero
811  *              if an error occurred.  Use get_error_string() to
812  *              retrieve the associated error message.
813  */
814 int
815 defaults_get_mirror_pass(
816 	defaults_t *defaults,
817 	char *diskset,
818 	uint16_t *val)
819 {
820 	char *disksets[2];
821 	devconfig_t *mirror;
822 	int error;
823 	int i = 0;
824 
825 	/* Check both the given and global (NULL) disk sets for the value */
826 	disksets[0] = diskset;
827 	disksets[1] = NULL;
828 	do {
829 	    /* Get/create singleton mirror element for this disk set */
830 	    error = defaults_get_singleton_component(
831 		defaults, disksets[i], TYPE_MIRROR, &mirror, FALSE);
832 
833 	    switch (error) {
834 		/* mirror found for this disk set */
835 		case 0:
836 		    /* Get the pass attribute */
837 		    if ((error = devconfig_get_mirror_pass(mirror, val)) == 0) {
838 			/* pass attribute found */
839 			return (0);
840 		    }
841 
842 		/* FALLTHROUGH */
843 
844 		/* mirror not found for this disk set */
845 		case ENOENT:
846 		break;
847 
848 		/* Invalid disk set, or mirror couldn't be created */
849 		default:
850 		    /* volume_set_error already called */
851 		    return (error);
852 	    }
853 
854 	/* Stop after the global (NULL) disk set has been searched */
855 	} while (disksets[i++] != NULL);
856 
857 	return (ENOENT);
858 }
859 
860 /*
861  * Set the default HSP creation flag for mirrored volumes
862  *
863  * @param       defaults
864  *              a defaults_t hierarchy representing default settings
865  *              for all disk sets and specific disk sets
866  *
867  * @param       diskset
868  *              the name of the disk set to which to apply this
869  *              default setting, or NULL to apply default
870  *              setting to all disk sets
871  *
872  * @param       val
873  *              the value to set as the default HSP creation flag for
874  *              mirrored volumes
875  *
876  * @return      0
877  *              if successful
878  *
879  * @return      non-zero
880  *              if an error occurred.  Use get_error_string() to
881  *              retrieve the associated error message.
882  */
883 int
884 defaults_set_mirror_usehsp(
885 	defaults_t *defaults,
886 	char *diskset,
887 	boolean_t val)
888 {
889 	devconfig_t *mirror = NULL;
890 	int error = 0;
891 
892 	/* Get/create singleton mirror element for this disk set */
893 	if ((error = defaults_get_singleton_component(
894 		defaults, diskset, TYPE_MIRROR, &mirror, TRUE)) != 0) {
895 	    /* volume_set_error already called */
896 	    return (error);
897 	}
898 
899 	/* Set the usehsp attribute */
900 	return (devconfig_set_volume_usehsp(mirror, val));
901 }
902 
903 /*
904  * Get the default HSP creation flag for mirrored volumes
905  *
906  * @param       defaults
907  *              a defaults_t hierarchy representing default settings
908  *              for all disk sets and specific disk sets
909  *
910  * @param       diskset
911  *              the name of the disk set to which to apply this
912  *              default setting, or NULL to apply default
913  *              setting to all disk sets
914  *
915  * @param       val
916  *              RETURN: the default HSP creation flag for mirrored
917  *              volumes
918  *
919  * @return      0
920  *              if successful
921  *
922  * @return      non-zero
923  *              if an error occurred.  Use get_error_string() to
924  *              retrieve the associated error message.
925  */
926 int
927 defaults_get_mirror_usehsp(
928 	defaults_t *defaults,
929 	char *diskset,
930 	boolean_t *val)
931 {
932 	char *disksets[2];
933 	devconfig_t *mirror;
934 	int error;
935 	int i = 0;
936 
937 	/* Check both the given and global (NULL) disk sets for the value */
938 	disksets[0] = diskset;
939 	disksets[1] = NULL;
940 	do {
941 	    /* Get/create singleton mirror element for this disk set */
942 	    error = defaults_get_singleton_component(
943 		defaults, disksets[i], TYPE_MIRROR, &mirror, FALSE);
944 
945 	    switch (error) {
946 		/* mirror found for this disk set */
947 		case 0:
948 		    /* Get the usehsp attribute */
949 		    if ((error = devconfig_get_volume_usehsp(
950 			    mirror, val)) == 0) {
951 			/* usehsp attribute found */
952 			return (0);
953 		    }
954 
955 		/* FALLTHROUGH */
956 
957 		/* mirror not found for this disk set */
958 		case ENOENT:
959 		break;
960 
961 		/* Invalid disk set, or mirror couldn't be created */
962 		default:
963 		    /* volume_set_error already called */
964 		    return (error);
965 	    }
966 
967 	/* Stop after the global (NULL) disk set has been searched */
968 	} while (disksets[i++] != NULL);
969 
970 	return (ENOENT);
971 }
972 
973 /*
974  * Set the default HSP creation flag for concatenated volumes
975  *
976  * @param       defaults
977  *              a defaults_t hierarchy representing default settings
978  *              for all disk sets and specific disk sets
979  *
980  * @param       diskset
981  *              the name of the disk set to which to apply this
982  *              default setting, or NULL to apply default
983  *              setting to all disk sets
984  *
985  * @param       val
986  *              the value to set as the default HSP creation flag for
987  *              concatenated volumes
988  *
989  * @return      0
990  *              if successful
991  *
992  * @return      non-zero
993  *              if an error occurred.  Use get_error_string() to
994  *              retrieve the associated error message.
995  */
996 int
997 defaults_set_concat_usehsp(
998 	defaults_t *defaults,
999 	char *diskset,
1000 	boolean_t val)
1001 {
1002 	devconfig_t *concat = NULL;
1003 	int error = 0;
1004 
1005 	/* Get/create singleton concat element for this disk set */
1006 	if ((error = defaults_get_singleton_component(
1007 		defaults, diskset, TYPE_CONCAT, &concat, TRUE)) != 0) {
1008 	    /* volume_set_error already called */
1009 	    return (error);
1010 	}
1011 
1012 	/* Set the usehsp attribute */
1013 	return (devconfig_set_volume_usehsp(concat, val));
1014 }
1015 
1016 /*
1017  * Get the default HSP creation flag for concatenated volumes
1018  *
1019  * @param       defaults
1020  *              a defaults_t hierarchy representing default settings
1021  *              for all disk sets and specific disk sets
1022  *
1023  * @param       diskset
1024  *              the name of the disk set to which to apply this
1025  *              default setting, or NULL to apply default
1026  *              setting to all disk sets
1027  *
1028  * @param       val
1029  *              RETURN: the default HSP creation flag for concatenated
1030  *              volumes
1031  *
1032  * @return      0
1033  *              if successful
1034  *
1035  * @return      non-zero
1036  *              if an error occurred.  Use get_error_string() to
1037  *              retrieve the associated error message.
1038  */
1039 int
1040 defaults_get_concat_usehsp(
1041 	defaults_t *defaults,
1042 	char *diskset,
1043 	boolean_t *val)
1044 {
1045 	char *disksets[2];
1046 	devconfig_t *concat;
1047 	int error;
1048 	int i = 0;
1049 
1050 	/* Check both the given and global (NULL) disk sets for the value */
1051 	disksets[0] = diskset;
1052 	disksets[1] = NULL;
1053 	do {
1054 	    /* Get/create singleton concat element for this disk set */
1055 	    error = defaults_get_singleton_component(
1056 		defaults, disksets[i], TYPE_CONCAT, &concat, FALSE);
1057 
1058 	    switch (error) {
1059 		/* concat found for this disk set */
1060 		case 0:
1061 		    /* Get the usehsp attribute */
1062 		    if ((error = devconfig_get_volume_usehsp(
1063 			    concat, val)) == 0) {
1064 			/* usehsp attribute found */
1065 			return (0);
1066 		    }
1067 
1068 		/* FALLTHROUGH */
1069 
1070 		/* concat not found for this disk set */
1071 		case ENOENT:
1072 		break;
1073 
1074 		/* Invalid disk set, or concat couldn't be created */
1075 		default:
1076 		    /* volume_set_error already called */
1077 		    return (error);
1078 	    }
1079 
1080 	/* Stop after the global (NULL) disk set has been searched */
1081 	} while (disksets[i++] != NULL);
1082 
1083 	return (ENOENT);
1084 }
1085 
1086 /*
1087  * Set the default minimum number of components for striped volumes
1088  *
1089  * @param       defaults
1090  *              a defaults_t hierarchy representing default settings
1091  *              for all disk sets and specific disk sets
1092  *
1093  * @param       diskset
1094  *              the name of the disk set to which to apply this
1095  *              default setting, or NULL to apply default
1096  *              setting to all disk sets
1097  *
1098  * @param       val
1099  *              the value to set as the default minimum number of
1100  *              components for striped volumes
1101  *
1102  * @return      0
1103  *              if successful
1104  *
1105  * @return      non-zero
1106  *              if an error occurred.  Use get_error_string() to
1107  *              retrieve the associated error message.
1108  */
1109 int
1110 defaults_set_stripe_mincomp(
1111 	defaults_t *defaults,
1112 	char *diskset,
1113 	uint16_t val)
1114 {
1115 	devconfig_t *stripe = NULL;
1116 	int error = 0;
1117 
1118 	/* Get/create singleton stripe element for this disk set */
1119 	if ((error = defaults_get_singleton_component(
1120 		defaults, diskset, TYPE_STRIPE, &stripe, TRUE)) != 0) {
1121 	    /* volume_set_error already called */
1122 	    return (error);
1123 	}
1124 
1125 	/* Set the mincomp attribute */
1126 	return (devconfig_set_stripe_mincomp(stripe, val));
1127 }
1128 
1129 /*
1130  * Get the default minimum number of components for striped volumes
1131  *
1132  * @param       defaults
1133  *              a defaults_t hierarchy representing default settings
1134  *              for all disk sets and specific disk sets
1135  *
1136  * @param       diskset
1137  *              the name of the disk set to which to apply this
1138  *              default setting, or NULL to apply default
1139  *              setting to all disk sets
1140  *
1141  * @param       val
1142  *              RETURN: the default minimum number of components for
1143  *              striped volumes
1144  *
1145  * @return      0
1146  *              if successful
1147  *
1148  * @return      non-zero
1149  *              if an error occurred.  Use get_error_string() to
1150  *              retrieve the associated error message.
1151  */
1152 int
1153 defaults_get_stripe_mincomp(
1154 	defaults_t *defaults,
1155 	char *diskset,
1156 	uint16_t *val)
1157 {
1158 	char *disksets[2];
1159 	devconfig_t *stripe;
1160 	int error;
1161 	int i = 0;
1162 
1163 	/* Check both the given and global (NULL) disk sets for the value */
1164 	disksets[0] = diskset;
1165 	disksets[1] = NULL;
1166 	do {
1167 	    /* Get/create singleton stripe element for this disk set */
1168 	    error = defaults_get_singleton_component(
1169 		defaults, disksets[i], TYPE_STRIPE, &stripe, FALSE);
1170 
1171 	    switch (error) {
1172 		/* stripe found for this disk set */
1173 		case 0:
1174 		    /* Get the mincomp attribute */
1175 		    if ((error = devconfig_get_stripe_mincomp(
1176 			    stripe, val)) == 0) {
1177 			/* mincomp attribute found */
1178 			return (0);
1179 		    }
1180 
1181 		/* FALLTHROUGH */
1182 
1183 		/* stripe not found for this disk set */
1184 		case ENOENT:
1185 		break;
1186 
1187 		/* Invalid disk set, or stripe couldn't be created */
1188 		default:
1189 		    /* volume_set_error already called */
1190 		    return (error);
1191 	    }
1192 
1193 	/* Stop after the global (NULL) disk set has been searched */
1194 	} while (disksets[i++] != NULL);
1195 
1196 	return (ENOENT);
1197 }
1198 
1199 /*
1200  * Set the default maximum number of components for striped volumes
1201  *
1202  * @param       defaults
1203  *              a defaults_t hierarchy representing default settings
1204  *              for all disk sets and specific disk sets
1205  *
1206  * @param       diskset
1207  *              the name of the disk set to which to apply this
1208  *              default setting, or NULL to apply default
1209  *              setting to all disk sets
1210  *
1211  * @param       val
1212  *              the value to set as the default maximum number of
1213  *              components for striped volumes
1214  *
1215  * @return      0
1216  *              if successful
1217  *
1218  * @return      non-zero
1219  *              if an error occurred.  Use get_error_string() to
1220  *              retrieve the associated error message.
1221  */
1222 int
1223 defaults_set_stripe_maxcomp(
1224 	defaults_t *defaults,
1225 	char *diskset,
1226 	uint16_t val)
1227 {
1228 	devconfig_t *stripe = NULL;
1229 	int error = 0;
1230 
1231 	/* Get/create singleton stripe element for this disk set */
1232 	if ((error = defaults_get_singleton_component(
1233 		defaults, diskset, TYPE_STRIPE, &stripe, TRUE)) != 0) {
1234 	    /* volume_set_error already called */
1235 	    return (error);
1236 	}
1237 
1238 	/* Set the maxcomp attribute */
1239 	return (devconfig_set_stripe_maxcomp(stripe, val));
1240 }
1241 
1242 /*
1243  * Get the default maximum number of components for striped volumes
1244  *
1245  * @param       defaults
1246  *              a defaults_t hierarchy representing default settings
1247  *              for all disk sets and specific disk sets
1248  *
1249  * @param       diskset
1250  *              the name of the disk set to which to apply this
1251  *              default setting, or NULL to apply default
1252  *              setting to all disk sets
1253  *
1254  * @param       val
1255  *              RETURN: the default maximum number of components for
1256  *              striped volumes
1257  *
1258  * @return      0
1259  *              if successful
1260  *
1261  * @return      non-zero
1262  *              if an error occurred.  Use get_error_string() to
1263  *              retrieve the associated error message.
1264  */
1265 int
1266 defaults_get_stripe_maxcomp(
1267 	defaults_t *defaults,
1268 	char *diskset,
1269 	uint16_t *val)
1270 {
1271 	char *disksets[2];
1272 	devconfig_t *stripe;
1273 	int error;
1274 	int i = 0;
1275 
1276 	/* Check both the given and global (NULL) disk sets for the value */
1277 	disksets[0] = diskset;
1278 	disksets[1] = NULL;
1279 	do {
1280 	    /* Get/create singleton stripe element for this disk set */
1281 	    error = defaults_get_singleton_component(
1282 		defaults, disksets[i], TYPE_STRIPE, &stripe, FALSE);
1283 
1284 	    switch (error) {
1285 		/* stripe found for this disk set */
1286 		case 0:
1287 		    /* Get the maxcomp attribute */
1288 		    if ((error = devconfig_get_stripe_maxcomp(
1289 			    stripe, val)) == 0) {
1290 			/* maxcomp attribute found */
1291 			return (0);
1292 		    }
1293 
1294 		/* FALLTHROUGH */
1295 
1296 		/* stripe not found for this disk set */
1297 		case ENOENT:
1298 		break;
1299 
1300 		/* Invalid disk set, or stripe couldn't be created */
1301 		default:
1302 		    /* volume_set_error already called */
1303 		    return (error);
1304 	    }
1305 
1306 	/* Stop after the global (NULL) disk set has been searched */
1307 	} while (disksets[i++] != NULL);
1308 
1309 	return (ENOENT);
1310 }
1311 
1312 /*
1313  * Set the default interlace for striped volumes
1314  *
1315  * @param       defaults
1316  *              a defaults_t hierarchy representing default settings
1317  *              for all disk sets and specific disk sets
1318  *
1319  * @param       diskset
1320  *              the name of the disk set to which to apply this
1321  *              default setting, or NULL to apply default
1322  *              setting to all disk sets
1323  *
1324  * @param       val
1325  *              the value to set as the default interlace for striped
1326  *              volumes
1327  *
1328  * @return      0
1329  *              if successful
1330  *
1331  * @return      non-zero
1332  *              if an error occurred.  Use get_error_string() to
1333  *              retrieve the associated error message.
1334  */
1335 int
1336 defaults_set_stripe_interlace(
1337 	defaults_t *defaults,
1338 	char *diskset,
1339 	uint64_t val)
1340 {
1341 	devconfig_t *stripe = NULL;
1342 	int error = 0;
1343 
1344 	/* Get/create singleton stripe element for this disk set */
1345 	if ((error = defaults_get_singleton_component(
1346 		defaults, diskset, TYPE_STRIPE, &stripe, TRUE)) != 0) {
1347 	    /* volume_set_error already called */
1348 	    return (error);
1349 	}
1350 
1351 	/* Set the interlace attribute */
1352 	return (devconfig_set_stripe_interlace(stripe, val));
1353 }
1354 
1355 /*
1356  * Get the default interlace for striped volumes
1357  *
1358  * @param       defaults
1359  *              a defaults_t hierarchy representing default settings
1360  *              for all disk sets and specific disk sets
1361  *
1362  * @param       diskset
1363  *              the name of the disk set to which to apply this
1364  *              default setting, or NULL to apply default
1365  *              setting to all disk sets
1366  *
1367  * @param       val
1368  *              RETURN: the default interlace for striped volumes
1369  *
1370  * @return      0
1371  *              if successful
1372  *
1373  * @return      non-zero
1374  *              if an error occurred.  Use get_error_string() to
1375  *              retrieve the associated error message.
1376  */
1377 int
1378 defaults_get_stripe_interlace(
1379 	defaults_t *defaults,
1380 	char *diskset,
1381 	uint64_t *val)
1382 {
1383 	char *disksets[2];
1384 	devconfig_t *stripe;
1385 	int error;
1386 	int i = 0;
1387 
1388 	/* Check both the given and global (NULL) disk sets for the value */
1389 	disksets[0] = diskset;
1390 	disksets[1] = NULL;
1391 	do {
1392 	    /* Get/create singleton stripe element for this disk set */
1393 	    error = defaults_get_singleton_component(
1394 		defaults, disksets[i], TYPE_STRIPE, &stripe, FALSE);
1395 
1396 	    switch (error) {
1397 		/* stripe found for this disk set */
1398 		case 0:
1399 		    /* Get the interlace attribute */
1400 		    if ((error = devconfig_get_stripe_interlace(
1401 			    stripe, val)) == 0) {
1402 			/* interlace attribute found */
1403 			return (0);
1404 		    }
1405 
1406 		/* FALLTHROUGH */
1407 
1408 		/* stripe not found for this disk set */
1409 		case ENOENT:
1410 		break;
1411 
1412 		/* Invalid disk set, or stripe couldn't be created */
1413 		default:
1414 		    /* volume_set_error already called */
1415 		    return (error);
1416 	    }
1417 
1418 	/* Stop after the global (NULL) disk set has been searched */
1419 	} while (disksets[i++] != NULL);
1420 
1421 	return (ENOENT);
1422 }
1423 
1424 /*
1425  * Set the default HSP creation flag for striped volumes
1426  *
1427  * @param       defaults
1428  *              a defaults_t hierarchy representing default settings
1429  *              for all disk sets and specific disk sets
1430  *
1431  * @param       diskset
1432  *              the name of the disk set to which to apply this
1433  *              default setting, or NULL to apply default
1434  *              setting to all disk sets
1435  *
1436  * @param       val
1437  *              the value to set as the default HSP creation flag for
1438  *              striped volumes
1439  *
1440  * @return      0
1441  *              if successful
1442  *
1443  * @return      non-zero
1444  *              if an error occurred.  Use get_error_string() to
1445  *              retrieve the associated error message.
1446  */
1447 int
1448 defaults_set_stripe_usehsp(
1449 	defaults_t *defaults,
1450 	char *diskset,
1451 	boolean_t val)
1452 {
1453 	devconfig_t *stripe = NULL;
1454 	int error = 0;
1455 
1456 	/* Get/create singleton stripe element for this disk set */
1457 	if ((error = defaults_get_singleton_component(
1458 		defaults, diskset, TYPE_STRIPE, &stripe, TRUE)) != 0) {
1459 	    /* volume_set_error already called */
1460 	    return (error);
1461 	}
1462 
1463 	/* Set the usehsp attribute */
1464 	return (devconfig_set_volume_usehsp(stripe, val));
1465 }
1466 
1467 /*
1468  * Get the default HSP creation flag for striped volumes
1469  *
1470  * @param       defaults
1471  *              a defaults_t hierarchy representing default settings
1472  *              for all disk sets and specific disk sets
1473  *
1474  * @param       diskset
1475  *              the name of the disk set to which to apply this
1476  *              default setting, or NULL to apply default
1477  *              setting to all disk sets
1478  *
1479  * @param       val
1480  *              RETURN: the default HSP creation flag for striped
1481  *              volumes
1482  *
1483  * @return      0
1484  *              if successful
1485  *
1486  * @return      non-zero
1487  *              if an error occurred.  Use get_error_string() to
1488  *              retrieve the associated error message.
1489  */
1490 int
1491 defaults_get_stripe_usehsp(
1492 	defaults_t *defaults,
1493 	char *diskset,
1494 	boolean_t *val)
1495 {
1496 	char *disksets[2];
1497 	devconfig_t *stripe;
1498 	int error;
1499 	int i = 0;
1500 
1501 	/* Check both the given and global (NULL) disk sets for the value */
1502 	disksets[0] = diskset;
1503 	disksets[1] = NULL;
1504 	do {
1505 	    /* Get/create singleton stripe element for this disk set */
1506 	    error = defaults_get_singleton_component(
1507 		defaults, disksets[i], TYPE_STRIPE, &stripe, FALSE);
1508 
1509 	    switch (error) {
1510 		/* stripe found for this disk set */
1511 		case 0:
1512 		    /* Get the usehsp attribute */
1513 		    if ((error = devconfig_get_volume_usehsp(
1514 			    stripe, val)) == 0) {
1515 			/* usehsp attribute found */
1516 			return (0);
1517 		    }
1518 
1519 		/* FALLTHROUGH */
1520 
1521 		/* stripe not found for this disk set */
1522 		case ENOENT:
1523 		break;
1524 
1525 		/* Invalid disk set, or stripe couldn't be created */
1526 		default:
1527 		    /* volume_set_error already called */
1528 		    return (error);
1529 	    }
1530 
1531 	/* Stop after the global (NULL) disk set has been searched */
1532 	} while (disksets[i++] != NULL);
1533 
1534 	return (ENOENT);
1535 }
1536 
1537 /*
1538  * Set the default redundancy level for generic volumes.
1539  *
1540  * @param       defaults
1541  *              a defaults_t hierarchy representing default settings
1542  *              for all disk sets and specific disk sets
1543  *
1544  * @param       diskset
1545  *              the name of the disk set to which to apply this
1546  *              default setting, or NULL to apply default
1547  *              setting to all disk sets
1548  *
1549  * @param       val
1550  *              If 0, a stripe will be created by default.  If > 0, a
1551  *              mirror with this number of submirrors will be created
1552  *              by default.
1553  *
1554  * @return      0
1555  *              if successful
1556  *
1557  * @return      non-zero
1558  *              if an error occurred.  Use get_error_string() to
1559  *              retrieve the associated error message.
1560  */
1561 int
1562 defaults_set_volume_redundancy_level(
1563 	defaults_t *defaults,
1564 	char *diskset,
1565 	uint16_t val)
1566 {
1567 	devconfig_t *volume = NULL;
1568 	int error = 0;
1569 
1570 	/* Get/create singleton volume element for this disk set */
1571 	if ((error = defaults_get_singleton_component(
1572 		defaults, diskset, TYPE_VOLUME, &volume, TRUE)) != 0) {
1573 	    /* volume_set_error already called */
1574 	    return (error);
1575 	}
1576 
1577 	/* Set the redundancy level */
1578 	return (devconfig_set_volume_redundancy_level(volume, val));
1579 }
1580 
1581 /*
1582  * Get the default redundancy level for generic volumes.
1583  *
1584  * @param       defaults
1585  *              a defaults_t hierarchy representing default settings
1586  *              for all disk sets and specific disk sets
1587  *
1588  * @param       diskset
1589  *              the name of the disk set to which to apply this
1590  *              default setting, or NULL to apply default
1591  *              setting to all disk sets
1592  *
1593  * @param       val
1594  *              RETURN: the default redundancy level for generic
1595  *              volumes
1596  *
1597  * @return      0
1598  *              if successful
1599  *
1600  * @return      non-zero
1601  *              if an error occurred.  Use get_error_string() to
1602  *              retrieve the associated error message.
1603  */
1604 int
1605 defaults_get_volume_redundancy_level(
1606 	defaults_t *defaults,
1607 	char *diskset,
1608 	uint16_t *val)
1609 {
1610 	char *disksets[2];
1611 	devconfig_t *volume;
1612 	int error;
1613 	int i = 0;
1614 
1615 	/* Check both the given and global (NULL) disk sets for the value */
1616 	disksets[0] = diskset;
1617 	disksets[1] = NULL;
1618 	do {
1619 	    /* Get/create singleton volume element for this disk set */
1620 	    error = defaults_get_singleton_component(
1621 		defaults, disksets[i], TYPE_VOLUME, &volume, FALSE);
1622 
1623 	    switch (error) {
1624 		/* volume found for this disk set */
1625 		case 0:
1626 		    /* Get the redundancy level */
1627 		    if ((error = devconfig_get_volume_redundancy_level(
1628 			    volume, val)) == 0) {
1629 			/* redundancy level found */
1630 			return (0);
1631 		    }
1632 
1633 		/* FALLTHROUGH */
1634 
1635 		/* volume not found for this disk set */
1636 		case ENOENT:
1637 		break;
1638 
1639 		/* Invalid disk set, or volume couldn't be created */
1640 		default:
1641 		    /* volume_set_error already called */
1642 		    return (error);
1643 	    }
1644 
1645 	/* Stop after the global (NULL) disk set has been searched */
1646 	} while (disksets[i++] != NULL);
1647 
1648 	return (ENOENT);
1649 }
1650 
1651 /*
1652  * Set the default number of data paths for generic volume
1653  *
1654  * @param       defaults
1655  *              a defaults_t hierarchy representing default settings
1656  *              for all disk sets and specific disk sets
1657  *
1658  * @param       diskset
1659  *              the name of the disk set to which to apply this
1660  *              default setting, or NULL to apply default
1661  *              setting to all disk sets
1662  *
1663  * @param       val
1664  *              the value to set as the default number of data paths
1665  *              for generic volume
1666  *
1667  * @return      0
1668  *              if successful
1669  *
1670  * @return      non-zero
1671  *              if an error occurred.  Use get_error_string() to
1672  *              retrieve the associated error message.
1673  */
1674 int
1675 defaults_set_volume_npaths(
1676 	defaults_t *defaults,
1677 	char *diskset,
1678 	uint16_t val)
1679 {
1680 	devconfig_t *volume = NULL;
1681 	int error = 0;
1682 
1683 	/* Get/create singleton volume element for this disk set */
1684 	if ((error = defaults_get_singleton_component(
1685 		defaults, diskset, TYPE_VOLUME, &volume, TRUE)) != 0) {
1686 	    /* volume_set_error already called */
1687 	    return (error);
1688 	}
1689 
1690 	/* Set the npaths attribute */
1691 	return (devconfig_set_volume_npaths(volume, val));
1692 }
1693 
1694 /*
1695  * Get the default number of data paths for generic volume
1696  *
1697  * @param       defaults
1698  *              a defaults_t hierarchy representing default settings
1699  *              for all disk sets and specific disk sets
1700  *
1701  * @param       diskset
1702  *              the name of the disk set to which to apply this
1703  *              default setting, or NULL to apply default
1704  *              setting to all disk sets
1705  *
1706  * @param       val
1707  *              RETURN: the default number of data paths for generic
1708  *              volume
1709  *
1710  * @return      0
1711  *              if successful
1712  *
1713  * @return      non-zero
1714  *              if an error occurred.  Use get_error_string() to
1715  *              retrieve the associated error message.
1716  */
1717 int
1718 defaults_get_volume_npaths(
1719 	defaults_t *defaults,
1720 	char *diskset,
1721 	uint16_t *val)
1722 {
1723 	char *disksets[2];
1724 	devconfig_t *volume;
1725 	int error;
1726 	int i = 0;
1727 
1728 	/* Check both the given and global (NULL) disk sets for the value */
1729 	disksets[0] = diskset;
1730 	disksets[1] = NULL;
1731 	do {
1732 	    /* Get/create singleton volume element for this disk set */
1733 	    error = defaults_get_singleton_component(
1734 		defaults, disksets[i], TYPE_VOLUME, &volume, FALSE);
1735 
1736 	    switch (error) {
1737 		/* volume found for this disk set */
1738 		case 0:
1739 		    /* Get the npaths attribute */
1740 		    if ((error = devconfig_get_volume_npaths(
1741 			    volume, val)) == 0) {
1742 			/* npaths attribute found */
1743 			return (0);
1744 		    }
1745 
1746 		/* FALLTHROUGH */
1747 
1748 		/* volume not found for this disk set */
1749 		case ENOENT:
1750 		break;
1751 
1752 		/* Invalid disk set, or volume couldn't be created */
1753 		default:
1754 		    /* volume_set_error already called */
1755 		    return (error);
1756 	    }
1757 
1758 	/* Stop after the global (NULL) disk set has been searched */
1759 	} while (disksets[i++] != NULL);
1760 
1761 	return (ENOENT);
1762 }
1763 
1764 /*
1765  * Set the default HSP creation flag for generic volume
1766  *
1767  * @param       defaults
1768  *              a defaults_t hierarchy representing default settings
1769  *              for all disk sets and specific disk sets
1770  *
1771  * @param       diskset
1772  *              the name of the disk set to which to apply this
1773  *              default setting, or NULL to apply default
1774  *              setting to all disk sets
1775  *
1776  * @param       val
1777  *              the value to set as the default HSP creation flag for
1778  *              generic volume
1779  *
1780  * @return      0
1781  *              if successful
1782  *
1783  * @return      non-zero
1784  *              if an error occurred.  Use get_error_string() to
1785  *              retrieve the associated error message.
1786  */
1787 int
1788 defaults_set_volume_usehsp(
1789 	defaults_t *defaults,
1790 	char *diskset,
1791 	boolean_t val)
1792 {
1793 	devconfig_t *volume = NULL;
1794 	int error = 0;
1795 
1796 	/* Get/create singleton volume element for this disk set */
1797 	if ((error = defaults_get_singleton_component(
1798 		defaults, diskset, TYPE_VOLUME, &volume, TRUE)) != 0) {
1799 	    /* volume_set_error already called */
1800 	    return (error);
1801 	}
1802 
1803 	/* Set the usehsp attribute */
1804 	return (devconfig_set_volume_usehsp(volume, val));
1805 }
1806 
1807 /*
1808  * Get the default HSP creation flag for generic volume
1809  *
1810  * @param       defaults
1811  *              a defaults_t hierarchy representing default settings
1812  *              for all disk sets and specific disk sets
1813  *
1814  * @param       diskset
1815  *              the name of the disk set to which to apply this
1816  *              default setting, or NULL to apply default
1817  *              setting to all disk sets
1818  *
1819  * @param       val
1820  *              RETURN: the default HSP creation flag for generic
1821  *              volume
1822  *
1823  * @return      0
1824  *              if successful
1825  *
1826  * @return      non-zero
1827  *              if an error occurred.  Use get_error_string() to
1828  *              retrieve the associated error message.
1829  */
1830 int
1831 defaults_get_volume_usehsp(
1832 	defaults_t *defaults,
1833 	char *diskset,
1834 	boolean_t *val)
1835 {
1836 	char *disksets[2];
1837 	devconfig_t *volume;
1838 	int error;
1839 	int i = 0;
1840 
1841 	/* Check both the given and global (NULL) disk sets for the value */
1842 	disksets[0] = diskset;
1843 	disksets[1] = NULL;
1844 	do {
1845 	    /* Get/create singleton volume element for this disk set */
1846 	    error = defaults_get_singleton_component(
1847 		defaults, disksets[i], TYPE_VOLUME, &volume, FALSE);
1848 
1849 	    switch (error) {
1850 		/* volume found for this disk set */
1851 		case 0:
1852 		    /* Get the usehsp attribute */
1853 		    if ((error = devconfig_get_volume_usehsp(
1854 			    volume, val)) == 0) {
1855 			/* usehsp attribute found */
1856 			return (0);
1857 		    }
1858 
1859 		/* FALLTHROUGH */
1860 
1861 		/* volume not found for this disk set */
1862 		case ENOENT:
1863 		break;
1864 
1865 		/* Invalid disk set, or volume couldn't be created */
1866 		default:
1867 		    /* volume_set_error already called */
1868 		    return (error);
1869 	    }
1870 
1871 	/* Stop after the global (NULL) disk set has been searched */
1872 	} while (disksets[i++] != NULL);
1873 
1874 	return (ENOENT);
1875 }
1876