7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / cmd / lvm / metassist / common / volume_devconfig.c
blob1146b894664889c21b6cc3d57c1276b2db3f2c8e
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "volume_devconfig.h"
31 #include <string.h>
32 #include <ctype.h>
33 #include <meta.h>
34 #include "volume_nvpair.h"
35 #include "volume_error.h"
36 #include "volume_output.h"
37 #include "volume_string.h"
40 * Methods which manipulate a devconfig_t struct
44 * Constructor: Create a devconfig_t struct. This devconfig_t must be
45 * freed with free_devconfig().
47 * @param devconfig
48 * RETURN: a new devconfig_t
50 * @param type
51 * the type of devconfig_t to create
53 * @return 0
54 * if successful
56 * @return non-zero
57 * if an error occurred. Use get_error_string() to
58 * retrieve the associated error message.
60 int
61 new_devconfig(
62 devconfig_t **devconfig,
63 component_type_t type)
65 int error;
67 *devconfig = (devconfig_t *)calloc(1, sizeof (devconfig_t));
68 if (*devconfig == NULL) {
69 volume_set_error(gettext("new_devconfig() calloc() failed\n"));
70 return (-1);
73 /* Create attribute list */
74 if ((error = nvlist_alloc(&((*devconfig)->attributes),
75 NV_UNIQUE_NAME_TYPE, 0)) != 0) {
76 volume_set_error(gettext("devconfig_t nvlist_alloc() failed\n"));
77 free_devconfig(*devconfig);
78 return (error);
81 if ((error = devconfig_set_type(*devconfig, type)) != 0) {
82 free_devconfig(*devconfig);
83 return (error);
86 return (0);
90 * Free memory (recursively) allocated to a devconfig_t struct
92 * @param arg
93 * pointer to the devconfig_t to be freed
95 void
96 free_devconfig(
97 void *arg)
99 devconfig_t *devconfig = (devconfig_t *)arg;
101 if (devconfig == NULL) {
102 return;
105 /* Free the attributes nvlist */
106 if (devconfig->attributes != NULL) {
107 nvlist_free(devconfig->attributes);
110 /* Free available devices */
111 if (devconfig->available != NULL) {
112 free_string_array(devconfig->available);
115 /* Free unavailable devices */
116 if (devconfig->unavailable != NULL) {
117 free_string_array(devconfig->unavailable);
120 /* Free the components */
121 if (devconfig->components != NULL) {
122 dlist_free_items(devconfig->components, free_devconfig);
125 /* Free the devconfig itself */
126 free(devconfig);
130 * Check the type of the given device.
132 * @param device
133 * the device whose type to check
135 * @param type
136 * the type of the device against which to compare
138 * @return B_TRUE if the device is of the given type, B_FALSE
139 * otherwise
141 boolean_t
142 devconfig_isA(
143 devconfig_t *device,
144 component_type_t type)
146 component_type_t curtype;
148 if (device == NULL) {
149 return (B_FALSE);
152 if (devconfig_get_type(device, &curtype) != 0) {
153 return (B_FALSE);
156 if (curtype != type) {
157 return (B_FALSE);
160 return (B_TRUE);
164 * Get the first component of the given type from the given
165 * devconfig_t. Create the component if create is B_TRUE.
167 * @return ENOENT
168 * if the requested component does not exist and its
169 * creation was not requested
171 * @return 0
172 * if the requested component exists or was created
174 * @return non-zero
175 * if the requested component did not exist and could not
176 * be created
179 devconfig_get_component(
180 devconfig_t *device,
181 component_type_t type,
182 devconfig_t **component,
183 boolean_t create)
185 dlist_t *list;
186 int error = 0;
187 char *typestr = devconfig_type_to_str(type);
189 oprintf(OUTPUT_DEBUG, gettext("Searching for singleton %s\n"), typestr);
191 /* For each component of this device... */
192 for (list = devconfig_get_components(device);
193 list != NULL; list = list->next) {
195 *component = (devconfig_t *)list->obj;
197 /* Is this subcomponent an instance of the given type? */
198 if (*component != NULL && devconfig_isA(*component, type)) {
199 oprintf(OUTPUT_DEBUG, gettext("Found %s\n"), typestr);
200 return (0);
204 /* No component found */
205 error = ENOENT;
206 *component = NULL;
208 oprintf(OUTPUT_DEBUG, gettext("%s not found\n"), typestr);
210 if (create == B_TRUE) {
211 oprintf(OUTPUT_DEBUG, gettext("Creating %s\n"), typestr);
214 * An existing singleton component of the given type was
215 * not found under the given disk set. So, create one.
217 if ((error = new_devconfig(component, type)) == 0) {
218 /* Attach new component to given device */
219 devconfig_set_components(
220 device, dlist_append(dlist_new_item(*component),
221 devconfig_get_components(device), AT_TAIL));
225 return (error);
229 * Set the available devices for use in creating this device
231 * @param device
232 * a devconfig_t representing the device to modify
234 * @param available
235 * A NULL-terminated array of device names
237 void
238 devconfig_set_available(
239 devconfig_t *device,
240 char **available)
242 device->available = available;
246 * Get the available devices for use in creating this device
248 * @param device
249 * a devconfig_t representing the device to examine
251 * @return available
252 * A NULL-terminated array of device names
254 char **
255 devconfig_get_available(
256 devconfig_t *device)
258 return (device->available);
262 * Set the unavailable devices which may not be used in creating this
263 * device
265 * @param device
266 * a devconfig_t representing the device to modify
268 * @param available
269 * A NULL-terminated array of device names
271 void
272 devconfig_set_unavailable(
273 devconfig_t *device,
274 char **unavailable)
276 device->unavailable = unavailable;
280 * Get the unavailable devices for use in creating this device
282 * @param device
283 * a devconfig_t representing the device to examine
285 * @return unavailable
286 * A NULL-terminated array of device names
288 char **
289 devconfig_get_unavailable(
290 devconfig_t *device)
292 return (device->unavailable);
296 * Set the subcomponent devices of a given device
298 * @param device
299 * a devconfig_t representing the device to examine
301 * @param components
302 * A dlist_t containing devconfig_t devices
304 void
305 devconfig_set_components(
306 devconfig_t *device,
307 dlist_t *components)
309 device->components = components;
313 * Get the subcomponent devices of a given device
315 * @param device
316 * a devconfig_t representing the device to examine
318 * @return A dlist_t containing devconfig_t devices
320 dlist_t *
321 devconfig_get_components(
322 devconfig_t *device)
324 return (device->components);
328 * Set the device name
330 * @param device
331 * a devconfig_t representing the device to modify
333 * @param name
334 * the value to set as the device name
336 * @return 0
337 * if successful
339 * @return non-zero
340 * if an error occurred. Use get_error_string() to
341 * retrieve the associated error message.
344 devconfig_set_name(
345 devconfig_t *device,
346 char *name)
348 return (set_string(device->attributes, ATTR_NAME, name));
352 * Set the disk set name
354 * @param diskset
355 * a devconfig_t representing the diskset to modify
357 * @param name
358 * the value to set as the device name
360 * @return 0
361 * if successful
363 * @return non-zero
364 * if an error occurred. Use get_error_string() to
365 * retrieve the associated error message.
368 devconfig_set_diskset_name(
369 devconfig_t *diskset,
370 char *name)
372 md_error_t error = mdnullerror;
374 /* Verify syntax of disk set name */
375 if (meta_set_checkname(name, &error)) {
376 volume_set_error(gettext("invalid disk set name: %s"), name);
377 return (-1);
380 return (devconfig_set_name(diskset, name));
384 * Set the device name
386 * @param hsp
387 * a devconfig_t representing the hsp to modify
389 * @param name
390 * the value to set as the device name
392 * @return 0
393 * if successful
395 * @return non-zero
396 * if an error occurred. Use get_error_string() to
397 * retrieve the associated error message.
400 devconfig_set_hsp_name(
401 devconfig_t *hsp,
402 char *name)
404 /* Validate name */
405 if (!is_hspname(name)) {
406 volume_set_error(gettext("invalid hot spare pool name: %s"), name);
407 return (-1);
410 return (devconfig_set_name(hsp, name));
414 * Set the device name
416 * @param volume
417 * a devconfig_t representing the volume to modify
419 * @param name
420 * the value to set as the device name
422 * @return 0
423 * if successful
425 * @return non-zero
426 * if an error occurred. Use get_error_string() to
427 * retrieve the associated error message.
430 devconfig_set_volume_name(
431 devconfig_t *volume,
432 char *name)
434 /* Validate name */
435 if (!is_metaname(name)) {
436 volume_set_error(gettext("invalid volume name: %s"), name);
437 return (-1);
440 return (devconfig_set_name(volume, name));
444 * Get the device name
446 * @param volume
447 * a devconfig_t representing the volume to examine
449 * @param name
450 * RETURN: the device name
452 * @return 0
453 * if successful
455 * @return non-zero
456 * if an error occurred. Use get_error_string() to
457 * retrieve the associated error message.
460 devconfig_get_name(
461 devconfig_t *device,
462 char **name)
464 int error = get_string(device->attributes, ATTR_NAME, name);
466 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
467 if (error == ENOENT) {
468 volume_set_error(gettext("device name not set"));
469 error = ERR_ATTR_UNSET;
472 return (error);
476 * Set the device type
478 * @param device
479 * a devconfig_t representing the device to modify
481 * @param type
482 * the value to set as the device type
484 * @return 0
485 * if successful
487 * @return non-zero
488 * if an error occurred. Use get_error_string() to
489 * retrieve the associated error message.
492 devconfig_set_type(
493 devconfig_t *device,
494 component_type_t type)
496 return (set_uint16(device->attributes, ATTR_TYPE, (uint16_t)type));
500 * Get the device type
502 * @param device
503 * a devconfig_t representing the device to examine
505 * @param type
506 * RETURN: the device type
508 * @return 0
509 * if successful
511 * @return non-zero
512 * if an error occurred. Use get_error_string() to
513 * retrieve the associated error message.
516 devconfig_get_type(
517 devconfig_t *device,
518 component_type_t *type)
520 uint16_t val;
521 int error = get_uint16(device->attributes, ATTR_TYPE, &val);
523 switch (error) {
524 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
525 case ENOENT:
526 volume_set_error(gettext("device type not set"));
527 error = ERR_ATTR_UNSET;
528 break;
530 /* Success */
531 case 0:
532 *type = (component_type_t)val;
535 return (error);
539 * Set the device size (for volume, mirror, stripe, concat) in bytes
541 * Note that size in bytes in a 64-bit field cannot hold the size that
542 * can be accessed in a 16 byte CDB. Since CDBs operate on blocks,
543 * the max capacity is 2^73 bytes with 512 byte blocks.
545 * @param device
546 * a devconfig_t representing the device to modify
548 * @param size_in_bytes
549 * the value to set as the device size in bytes
551 * @return 0
552 * if successful
554 * @return non-zero
555 * if an error occurred. Use get_error_string() to
556 * retrieve the associated error message.
559 devconfig_set_size(
560 devconfig_t *device,
561 uint64_t size_in_bytes)
564 /* Validate against limits */
565 /* LINTED -- MIN_SIZE may be 0 */
566 if (size_in_bytes < MIN_SIZE) {
567 volume_set_error(gettext("size (in bytes) too small: %llu"),
568 (unsigned long long)size_in_bytes);
569 return (-1);
572 return (set_uint64(device->attributes,
573 ATTR_SIZEINBYTES, size_in_bytes));
577 * Get the device size (for volume, mirror, stripe, concat) in bytes
579 * Note that size in bytes in a 64-bit field cannot hold the size that
580 * can be accessed in a 16 byte CDB. Since CDBs operate on blocks,
581 * the max capacity is 2^73 bytes with 512 byte blocks.
583 * @param device
584 * a devconfig_t representing the device to examine
586 * @param size_in_bytes
587 * RETURN: the device size in bytes
589 * @return 0
590 * if successful
592 * @return non-zero
593 * if an error occurred. Use get_error_string() to
594 * retrieve the associated error message.
597 devconfig_get_size(
598 devconfig_t *device,
599 uint64_t *size_in_bytes)
601 int error = get_uint64(
602 device->attributes, ATTR_SIZEINBYTES, size_in_bytes);
604 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
605 if (error == ENOENT) {
606 volume_set_error(gettext("size (in bytes) not set"));
607 error = ERR_ATTR_UNSET;
610 return (error);
614 * Set the device size in blocks
616 * @param device
617 * a devconfig_t representing the device to modify
619 * @param type
620 * the value to set as the device size in blocks
622 * @return 0
623 * if successful
625 * @return non-zero
626 * if an error occurred. Use get_error_string() to
627 * retrieve the associated error message.
630 devconfig_set_size_in_blocks(
631 devconfig_t *device,
632 uint64_t size_in_blocks)
634 /* Validate against limits */
635 /* LINTED -- MIN_SIZE_IN_BLOCKS may be 0 */
636 if (size_in_blocks < MIN_SIZE_IN_BLOCKS) {
637 volume_set_error(gettext("size (in blocks) too small: %llu"),
638 (unsigned long long)size_in_blocks);
639 return (-1);
642 return (set_uint64(device->attributes,
643 ATTR_SIZEINBLOCKS, size_in_blocks));
647 * Get the device size in blocks
649 * @param device
650 * a devconfig_t representing the device to examine
652 * @param size_in_blocks
653 * RETURN: the device size in blocks
655 * @return 0
656 * if successful
658 * @return non-zero
659 * if an error occurred. Use get_error_string() to
660 * retrieve the associated error message.
663 devconfig_get_size_in_blocks(
664 devconfig_t *device,
665 uint64_t *size_in_blocks)
667 int error = get_uint64(
668 device->attributes, ATTR_SIZEINBLOCKS, size_in_blocks);
670 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
671 if (error == ENOENT) {
672 volume_set_error(gettext("size (in blocks) not set"));
673 error = ERR_ATTR_UNSET;
676 return (error);
680 * Set the the slice index
682 * @param slice
683 * a devconfig_t representing the slice to modify
685 * @param index
686 * the value to set as the the slice index
688 * @return 0
689 * if successful
691 * @return non-zero
692 * if an error occurred. Use get_error_string() to
693 * retrieve the associated error message.
696 devconfig_set_slice_index(
697 devconfig_t *slice,
698 uint16_t index)
700 return (set_uint16(slice->attributes, ATTR_SLICE_INDEX, index));
704 * Get the slice index
706 * @param device
707 * a devconfig_t representing the device to examine
709 * @param index
710 * RETURN: the slice index
712 * @return 0
713 * if successful
715 * @return non-zero
716 * if an error occurred. Use get_error_string() to
717 * retrieve the associated error message.
720 devconfig_get_slice_index(
721 devconfig_t *slice,
722 uint16_t *index)
724 int error = get_uint16(slice->attributes, ATTR_SLICE_INDEX, index);
726 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
727 if (error == ENOENT) {
728 volume_set_error(gettext("slice index not set"));
729 error = ERR_ATTR_UNSET;
732 return (error);
736 * Set the the slice start block
738 * @param slice
739 * a devconfig_t representing the slice to modify
741 * @param start_block
742 * the value to set as the the slice start block
744 * @return 0
745 * if successful
747 * @return non-zero
748 * if an error occurred. Use get_error_string() to
749 * retrieve the associated error message.
752 devconfig_set_slice_start_block(
753 devconfig_t *slice,
754 uint64_t start_block)
756 return (set_uint64(slice->attributes,
757 ATTR_SLICE_STARTSECTOR, start_block));
761 * Get the slice start block
763 * @param device
764 * a devconfig_t representing the device to examine
766 * @param start_block
767 * RETURN: the slice start block
769 * @return 0
770 * if successful
772 * @return non-zero
773 * if an error occurred. Use get_error_string() to
774 * retrieve the associated error message.
777 devconfig_get_slice_start_block(
778 devconfig_t *slice,
779 uint64_t *start_block)
781 int error = get_uint64(
782 slice->attributes, ATTR_SLICE_STARTSECTOR, start_block);
784 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
785 if (error == ENOENT) {
786 volume_set_error(gettext("slice start block not set"));
787 error = ERR_ATTR_UNSET;
790 return (error);
794 * Set the number of subcomponents in mirror
796 * @param mirror
797 * a devconfig_t representing the mirror to modify
799 * @param nsubs
800 * the value to set as the number of subcomponents in
801 * mirror
803 * @return 0
804 * if successful
806 * @return non-zero
807 * if an error occurred. Use get_error_string() to
808 * retrieve the associated error message.
811 devconfig_set_mirror_nsubs(
812 devconfig_t *mirror,
813 uint16_t nsubs)
815 /* Validate against limits */
816 if (nsubs < 1 || nsubs > NMIRROR) {
817 volume_set_error(
818 gettext("number of submirrors (%d) out of valid range (%d-%d)"),
819 nsubs, 1, NMIRROR);
820 return (-1);
823 return (set_uint16(mirror->attributes, ATTR_MIRROR_NSUBMIRRORS, nsubs));
827 * Get number of subcomponents in mirror
829 * @param device
830 * a devconfig_t representing the device to examine
832 * @param nsubs
833 * RETURN: number of subcomponents in mirror
835 * @return 0
836 * if successful
838 * @return non-zero
839 * if an error occurred. Use get_error_string() to
840 * retrieve the associated error message.
843 devconfig_get_mirror_nsubs(
844 devconfig_t *mirror,
845 uint16_t *nsubs)
847 int error = get_uint16(
848 mirror->attributes, ATTR_MIRROR_NSUBMIRRORS, nsubs);
850 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
851 if (error == ENOENT) {
852 volume_set_error(gettext("number or submirrors not set"));
853 error = ERR_ATTR_UNSET;
856 return (error);
860 * Set the read strategy for mirror
862 * @param mirror
863 * a devconfig_t representing the mirror to modify
865 * @param read
866 * the value to set as the read strategy for mirror
868 * @return 0
869 * if successful
871 * @return non-zero
872 * if an error occurred. Use get_error_string() to
873 * retrieve the associated error message.
876 devconfig_set_mirror_read(
877 devconfig_t *mirror,
878 mirror_read_strategy_t read)
880 return (set_uint16(mirror->attributes,
881 ATTR_MIRROR_READ, (uint16_t)read));
885 * Get read strategy for mirror
887 * @param device
888 * a devconfig_t representing the device to examine
890 * @param read
891 * RETURN: read strategy for mirror
893 * @return 0
894 * if successful
896 * @return non-zero
897 * if an error occurred. Use get_error_string() to
898 * retrieve the associated error message.
901 devconfig_get_mirror_read(
902 devconfig_t *mirror,
903 mirror_read_strategy_t *read)
905 uint16_t val;
906 int error = get_uint16(mirror->attributes, ATTR_MIRROR_READ, &val);
908 switch (error) {
909 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
910 case ENOENT:
911 volume_set_error(gettext("mirror read strategy not set"));
912 error = ERR_ATTR_UNSET;
913 break;
915 /* Success */
916 case 0:
917 *read = (mirror_read_strategy_t)val;
920 return (error);
924 * Set the write strategy for mirror
926 * @param mirror
927 * a devconfig_t representing the mirror to modify
929 * @param write
930 * the value to set as the write strategy for mirror
932 * @return 0
933 * if successful
935 * @return non-zero
936 * if an error occurred. Use get_error_string() to
937 * retrieve the associated error message.
940 devconfig_set_mirror_write(
941 devconfig_t *mirror,
942 mirror_write_strategy_t write)
944 return (set_uint16(mirror->attributes,
945 ATTR_MIRROR_WRITE, (uint16_t)write));
949 * Get write strategy for mirror
951 * @param device
952 * a devconfig_t representing the device to examine
954 * @param write
955 * RETURN: write strategy for mirror
957 * @return 0
958 * if successful
960 * @return non-zero
961 * if an error occurred. Use get_error_string() to
962 * retrieve the associated error message.
965 devconfig_get_mirror_write(
966 devconfig_t *mirror,
967 mirror_write_strategy_t *write)
969 uint16_t val;
970 int error = get_uint16(mirror->attributes, ATTR_MIRROR_WRITE, &val);
972 switch (error) {
973 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
974 case ENOENT:
975 volume_set_error(gettext("mirror write strategy not set"));
976 error = ERR_ATTR_UNSET;
977 break;
979 /* Success */
980 case 0:
981 *write = (mirror_write_strategy_t)val;
984 return (error);
988 * Set the resync pass for mirror
990 * @param mirror
991 * a devconfig_t representing the mirror to modify
993 * @param pass
994 * the value to set as the resync pass for mirror
996 * @return 0
997 * if successful
999 * @return non-zero
1000 * if an error occurred. Use get_error_string() to
1001 * retrieve the associated error message.
1004 devconfig_set_mirror_pass(
1005 devconfig_t *mirror,
1006 uint16_t pass)
1008 /* Validate against max value */
1009 if (pass > MD_PASS_MAX) {
1010 volume_set_error(
1011 gettext("mirror pass number (%d) out of valid range (0-%d)"),
1012 pass, MD_PASS_MAX);
1013 return (-1);
1016 return (set_uint16(mirror->attributes, ATTR_MIRROR_PASSNUM, pass));
1020 * Get resync pass for mirror
1022 * @param device
1023 * a devconfig_t representing the device to examine
1025 * @param pass
1026 * RETURN: resync pass for mirror
1028 * @return 0
1029 * if successful
1031 * @return non-zero
1032 * if an error occurred. Use get_error_string() to
1033 * retrieve the associated error message.
1036 devconfig_get_mirror_pass(
1037 devconfig_t *mirror,
1038 uint16_t *pass)
1040 int error = get_uint16(mirror->attributes, ATTR_MIRROR_PASSNUM, pass);
1042 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1043 if (error == ENOENT) {
1044 volume_set_error(gettext("mirror pass number not set"));
1045 error = ERR_ATTR_UNSET;
1048 return (error);
1052 * Set the minimum number of components in stripe
1054 * @param stripe
1055 * a devconfig_t representing the stripe to modify
1057 * @param mincomp
1058 * the value to set as the minimum number of components
1059 * in stripe
1061 * @return 0
1062 * if successful
1064 * @return non-zero
1065 * if an error occurred. Use get_error_string() to
1066 * retrieve the associated error message.
1069 devconfig_set_stripe_mincomp(
1070 devconfig_t *stripe,
1071 uint16_t mincomp)
1073 /* Validate against minimum value */
1074 if (mincomp < MIN_NSTRIPE_COMP) {
1075 volume_set_error(gettext(
1076 "minimum stripe components (%d) below minimum allowable (%d)"),
1077 mincomp, MIN_NSTRIPE_COMP);
1078 return (-1);
1081 return (set_uint16(stripe->attributes, ATTR_STRIPE_MINCOMP, mincomp));
1085 * Get minimum number of components in stripe
1087 * @param device
1088 * a devconfig_t representing the device to examine
1090 * @param mincomp
1091 * RETURN: minimum number of components in stripe
1093 * @return 0
1094 * if successful
1096 * @return non-zero
1097 * if an error occurred. Use get_error_string() to
1098 * retrieve the associated error message.
1101 devconfig_get_stripe_mincomp(
1102 devconfig_t *stripe,
1103 uint16_t *mincomp)
1105 int error = get_uint16(
1106 stripe->attributes, ATTR_STRIPE_MINCOMP, mincomp);
1108 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1109 if (error == ENOENT) {
1110 volume_set_error(
1111 gettext("minimum number of stripe components not set"));
1112 error = ERR_ATTR_UNSET;
1115 return (error);
1119 * Set the maximum number of components in stripe
1121 * @param stripe
1122 * a devconfig_t representing the stripe to modify
1124 * @param maxcomp
1125 * the value to set as the maximum number of components
1126 * in stripe
1128 * @return 0
1129 * if successful
1131 * @return non-zero
1132 * if an error occurred. Use get_error_string() to
1133 * retrieve the associated error message.
1136 devconfig_set_stripe_maxcomp(
1137 devconfig_t *stripe,
1138 uint16_t maxcomp)
1140 /* Validate against minimum value */
1141 if (maxcomp < MIN_NSTRIPE_COMP) {
1142 volume_set_error(gettext(
1143 "maximum stripe components (%d) below minimum allowable (%d)"),
1144 maxcomp, MIN_NSTRIPE_COMP);
1145 return (-1);
1148 return (set_uint16(stripe->attributes, ATTR_STRIPE_MAXCOMP, maxcomp));
1152 * Get maximum number of components in stripe
1154 * @param device
1155 * a devconfig_t representing the device to examine
1157 * @param maxcomp
1158 * RETURN: maximum number of components in stripe
1160 * @return 0
1161 * if successful
1163 * @return non-zero
1164 * if an error occurred. Use get_error_string() to
1165 * retrieve the associated error message.
1168 devconfig_get_stripe_maxcomp(
1169 devconfig_t *stripe,
1170 uint16_t *maxcomp)
1172 int error = get_uint16(
1173 stripe->attributes, ATTR_STRIPE_MAXCOMP, maxcomp);
1175 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1176 if (error == ENOENT) {
1177 volume_set_error(
1178 gettext("maximum number of stripe components not set"));
1179 error = ERR_ATTR_UNSET;
1182 return (error);
1186 * Set the stripe interlace
1188 * @param stripe
1189 * a devconfig_t representing the stripe to modify
1191 * @param interlace
1192 * the value to set as the stripe interlace
1194 * @return 0
1195 * if successful
1197 * @return non-zero
1198 * if an error occurred. Use get_error_string() to
1199 * retrieve the associated error message.
1202 devconfig_set_stripe_interlace(
1203 devconfig_t *stripe,
1204 uint64_t interlace)
1206 if (interlace < MININTERLACE || interlace > MAXINTERLACE) {
1207 char *intstr = NULL;
1208 char *minstr = NULL;
1209 char *maxstr = NULL;
1211 /* Get string representations of interlaces */
1212 bytes_to_sizestr(interlace, &intstr, universal_units, B_FALSE);
1213 bytes_to_sizestr(MININTERLACE, &minstr, universal_units, B_FALSE);
1214 bytes_to_sizestr(MAXINTERLACE, &maxstr, universal_units, B_FALSE);
1216 volume_set_error(
1217 gettext("interlace (%s) out of valid range (%s - %s)"),
1218 intstr, minstr, maxstr);
1220 free(intstr);
1221 free(minstr);
1222 free(maxstr);
1224 return (-1);
1227 return (set_uint64(stripe->attributes,
1228 ATTR_STRIPE_INTERLACE, interlace));
1232 * Get stripe interlace
1234 * @param device
1235 * a devconfig_t representing the device to examine
1237 * @param interlace
1238 * RETURN: stripe interlace
1240 * @return 0
1241 * if successful
1243 * @return non-zero
1244 * if an error occurred. Use get_error_string() to
1245 * retrieve the associated error message.
1248 devconfig_get_stripe_interlace(
1249 devconfig_t *stripe,
1250 uint64_t *interlace)
1252 int error = get_uint64(
1253 stripe->attributes, ATTR_STRIPE_INTERLACE, interlace);
1255 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1256 if (error == ENOENT) {
1257 volume_set_error(gettext("stripe interlace not set"));
1258 error = ERR_ATTR_UNSET;
1261 return (error);
1265 * Set the redundancy level for a volume.
1267 * @param volume
1268 * a devconfig_t representing the volume to modify
1270 * @param rlevel
1271 * If 0, a stripe will be created. If > 0, a mirror with
1272 * this number of submirrors will be created.
1274 * @return 0
1275 * if successful
1277 * @return non-zero
1278 * if an error occurred. Use get_error_string() to
1279 * retrieve the associated error message.
1282 devconfig_set_volume_redundancy_level(
1283 devconfig_t *volume,
1284 uint16_t rlevel)
1286 /* Validate against limits */
1287 if (rlevel > NMIRROR) {
1288 volume_set_error(gettext(
1289 "volume redundancy level (%d) out of valid range (%d-%d)"),
1290 rlevel, 0, NMIRROR);
1291 return (-1);
1294 return (set_uint16(volume->attributes, ATTR_VOLUME_REDUNDANCY, rlevel));
1298 * Get the redundancy level for a volume.
1300 * @param device
1301 * a devconfig_t representing the device to examine
1303 * @param rlevel
1304 * RETURN: the redundancy level for a volume
1306 * @return 0
1307 * if successful
1309 * @return non-zero
1310 * if an error occurred. Use get_error_string() to
1311 * retrieve the associated error message.
1314 devconfig_get_volume_redundancy_level(
1315 devconfig_t *volume,
1316 uint16_t *rlevel)
1318 int error = get_uint16(
1319 volume->attributes, ATTR_VOLUME_REDUNDANCY, rlevel);
1321 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1322 if (error == ENOENT) {
1323 volume_set_error(gettext("volume redundancy level not set"));
1324 error = ERR_ATTR_UNSET;
1327 return (error);
1331 * Set the number of paths in volume
1333 * @param volume
1334 * a devconfig_t representing the volume to modify
1336 * @param npaths
1337 * the value to set as the number of paths in volume
1339 * @return 0
1340 * if successful
1342 * @return non-zero
1343 * if an error occurred. Use get_error_string() to
1344 * retrieve the associated error message.
1347 devconfig_set_volume_npaths(
1348 devconfig_t *volume,
1349 uint16_t npaths)
1351 /* Validate against limits */
1352 if (npaths < MIN_NDATAPATHS || npaths > MAX_NDATAPATHS) {
1353 volume_set_error(
1354 gettext("number of data paths (%d) out of valid range (%d-%d)"),
1355 npaths, MIN_NDATAPATHS, MAX_NDATAPATHS);
1356 return (-1);
1359 return (set_uint16(volume->attributes, ATTR_VOLUME_DATAPATHS, npaths));
1363 * Get number of paths in volume
1365 * @param device
1366 * a devconfig_t representing the device to examine
1368 * @param npaths
1369 * RETURN: number of paths in volume
1371 * @return 0
1372 * if successful
1374 * @return non-zero
1375 * if an error occurred. Use get_error_string() to
1376 * retrieve the associated error message.
1379 devconfig_get_volume_npaths(
1380 devconfig_t *volume,
1381 uint16_t *npaths)
1383 int error = get_uint16(
1384 volume->attributes, ATTR_VOLUME_DATAPATHS, npaths);
1386 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1387 if (error == ENOENT) {
1388 volume_set_error(gettext("number of data paths not set"));
1389 error = ERR_ATTR_UNSET;
1392 return (error);
1396 * Set the HSP creation option (for volume, stripe, concat, mirror)
1398 * @param volume
1399 * a devconfig_t representing the volume to modify
1401 * @param usehsp
1402 * the value to set as the HSP creation option
1404 * @return 0
1405 * if successful
1407 * @return non-zero
1408 * if an error occurred. Use get_error_string() to
1409 * retrieve the associated error message.
1412 devconfig_set_volume_usehsp(
1413 devconfig_t *volume,
1414 boolean_t usehsp)
1416 return (set_boolean(volume->attributes, ATTR_VOLUME_USEHSP, usehsp));
1420 * Get HSP creation option (for volume, stripe, concat, mirror)
1422 * @param device
1423 * a devconfig_t representing the device to examine
1425 * @param usehsp
1426 * RETURN: HSP creation option (for volume, stripe,
1427 * concat, mirror)
1429 * @return 0
1430 * if successful
1432 * @return non-zero
1433 * if an error occurred. Use get_error_string() to
1434 * retrieve the associated error message.
1437 devconfig_get_volume_usehsp(
1438 devconfig_t *volume,
1439 boolean_t *usehsp)
1441 int error = get_boolean(
1442 volume->attributes, ATTR_VOLUME_USEHSP, usehsp);
1444 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
1445 if (error == ENOENT) {
1446 volume_set_error(gettext("volume usehsp not set"));
1447 error = ERR_ATTR_UNSET;
1450 return (error);
1454 * Get the string representation of the volume's type
1456 * @param type
1457 * a valid component_type_t
1459 * @return an internationalized string representing the given
1460 * type
1462 char *
1463 devconfig_type_to_str(
1464 component_type_t type)
1466 char *str;
1468 switch (type) {
1469 case TYPE_CONCAT: str = gettext("Concat"); break;
1470 case TYPE_CONTROLLER: str = gettext("Controller"); break;
1471 case TYPE_DISKSET: str = gettext("Diskset"); break;
1472 case TYPE_DRIVE: str = gettext("Disk"); break;
1473 case TYPE_EXTENT: str = gettext("Extent"); break;
1474 case TYPE_HOST: str = gettext("Host"); break;
1475 case TYPE_HSP: str = gettext("Hot Spare Pool"); break;
1476 case TYPE_MIRROR: str = gettext("Mirror"); break;
1477 case TYPE_RAID5: str = gettext("Raid5"); break;
1478 case TYPE_SLICE: str = gettext("Slice"); break;
1479 case TYPE_SOFTPART: str = gettext("Soft Partition"); break;
1480 case TYPE_STRIPE: str = gettext("Stripe"); break;
1481 case TYPE_TRANS: str = gettext("Trans"); break;
1482 case TYPE_VOLUME: str = gettext("Volume"); break;
1483 default:
1484 case TYPE_UNKNOWN: str = gettext("Unknown"); break;
1487 return (str);
1491 * Get the string representation of the mirror's read strategy
1493 * @param read
1494 * a valid mirror_read_strategy_t
1496 * @return an internationalized string representing the given
1497 * read strategy
1499 char *
1500 devconfig_read_strategy_to_str(
1501 mirror_read_strategy_t read)
1503 char *str;
1505 switch (read) {
1506 case MIRROR_READ_ROUNDROBIN: str = gettext("ROUNDROBIN"); break;
1507 case MIRROR_READ_GEOMETRIC: str = gettext("GEOMETRIC"); break;
1508 case MIRROR_READ_FIRST: str = gettext("FIRST"); break;
1509 default: str = "";
1512 return (str);
1516 * Get the string representation of the mirror's write strategy
1518 * @param write
1519 * a valid mirror_write_strategy_t
1521 * @return an internationalized string representing the given
1522 * write strategy
1524 char *
1525 devconfig_write_strategy_to_str(
1526 mirror_write_strategy_t write)
1528 char *str;
1530 switch (write) {
1531 case MIRROR_WRITE_PARALLEL: str = gettext("PARALLEL"); break;
1532 case MIRROR_WRITE_SERIAL: str = gettext("SERIAL"); break;
1533 default: str = "";
1536 return (str);
1539 #ifdef DEBUG
1541 * Dump the contents of a devconfig_t struct to stdout.
1543 * @param device
1544 * the devconfig_t to examine
1546 * @param prefix
1547 * a prefix string to print before each line
1549 void
1550 devconfig_dump(
1551 devconfig_t *device,
1552 char *prefix)
1554 dlist_t *comps = NULL;
1555 char **array = NULL;
1556 char *str = NULL;
1557 int i = 0;
1559 component_type_t type = TYPE_UNKNOWN;
1560 boolean_t bool = B_FALSE;
1561 uint16_t val16 = 0;
1562 uint64_t val64 = 0;
1563 mirror_read_strategy_t read;
1564 mirror_write_strategy_t write;
1566 if (device == NULL) {
1567 return;
1570 /* Type */
1571 if (devconfig_get_type(device, &type) == 0) {
1572 printf("%s%s\n", prefix, devconfig_type_to_str(type));
1575 /* Name */
1576 if (devconfig_get_name(device, &str) == 0) {
1577 printf("%s name: %s\n", prefix, str);
1580 /* Size in bytes */
1581 if (devconfig_get_size(device, &val64) == 0) {
1582 printf("%s size in bytes: %llu\n", prefix, val64);
1585 /* Size in blocks */
1586 if (devconfig_get_size_in_blocks(device, &val64) == 0) {
1587 printf("%s size in blocks: %llu\n", prefix, val64);
1590 /* Use HSP */
1591 if (devconfig_get_volume_usehsp(device, &bool) == 0) {
1592 printf("%s usehsp: %s\n", prefix, bool? "TRUE" : "FALSE");
1595 switch (type) {
1596 case TYPE_VOLUME:
1597 /* Volume rlevel */
1598 if (devconfig_get_volume_redundancy_level(
1599 device, &val16) == 0) {
1600 printf("%s volume redundancy level: %d\n", prefix, val16);
1603 /* Volume npaths */
1604 if (devconfig_get_volume_npaths(device, &val16) == 0) {
1605 printf("%s volume npaths: %d\n", prefix, val16);
1607 break;
1609 case TYPE_MIRROR:
1611 /* Mirror nsubs */
1612 if (devconfig_get_mirror_nsubs(device, &val16) == 0) {
1613 printf("%s mirror nsubs: %d\n", prefix, val16);
1616 /* Mirror read */
1617 if (devconfig_get_mirror_read(device, &read) == 0) {
1618 printf("%s mirror read: %s\n", prefix,
1619 devconfig_read_strategy_to_str(read));
1622 /* Mirror write */
1623 if (devconfig_get_mirror_write(device, &write) == 0) {
1624 printf("%s mirror write: %s\n", prefix,
1625 devconfig_write_strategy_to_str(write));
1628 /* Mirror pass */
1629 if (devconfig_get_mirror_pass(device, &val16) == 0) {
1630 printf("%s mirror pass: %d\n", prefix, val16);
1632 break;
1634 case TYPE_STRIPE:
1635 /* Stripe mincomp */
1636 if (devconfig_get_stripe_mincomp(device, &val16) == 0) {
1637 printf("%s stripe mincomp: %d\n", prefix, val16);
1640 /* Stripe maxcomp */
1641 if (devconfig_get_stripe_maxcomp(device, &val16) == 0) {
1642 printf("%s stripe maxcomp: %d\n", prefix, val16);
1645 /* Stripe interlace */
1646 if (devconfig_get_stripe_interlace(device, &val64) == 0) {
1647 printf("%s stripe interlace: %lld\n", prefix, val64);
1649 break;
1651 case TYPE_SLICE:
1652 /* Slice index */
1653 if (devconfig_get_slice_index(device, &val16) == 0) {
1654 printf("%s slice index: %d\n", prefix, val16);
1657 /* Slice start block */
1658 if (devconfig_get_slice_start_block(device, &val64) == 0) {
1659 printf("%s slice start block: %llu\n", prefix, val64);
1661 break;
1664 array = devconfig_get_available(device);
1665 if (array != NULL) {
1666 printf("%s available:\n", prefix);
1667 for (i = 0; array[i] != NULL; i++) {
1668 printf("%s %s\n", prefix, array[i]);
1672 array = devconfig_get_unavailable(device);
1673 if (array != NULL) {
1674 printf("%s unavailable:\n", prefix);
1675 for (i = 0; array[i] != NULL; i++) {
1676 printf("%s %s\n", prefix, array[i]);
1680 printf("\n");
1682 comps = devconfig_get_components(device);
1683 if (comps != NULL) {
1684 char buf[128];
1685 snprintf(buf, 128, "%s%s", prefix, " ");
1686 for (; comps != NULL; comps = comps->next) {
1687 devconfig_dump((devconfig_t *)comps->obj, buf);
1691 #endif /* DEBUG */