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
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]
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"
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().
48 * RETURN: a new devconfig_t
51 * the type of devconfig_t to create
57 * if an error occurred. Use get_error_string() to
58 * retrieve the associated error message.
62 devconfig_t
**devconfig
,
63 component_type_t type
)
67 *devconfig
= (devconfig_t
*)calloc(1, sizeof (devconfig_t
));
68 if (*devconfig
== NULL
) {
69 volume_set_error(gettext("new_devconfig() calloc() failed\n"));
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
);
81 if ((error
= devconfig_set_type(*devconfig
, type
)) != 0) {
82 free_devconfig(*devconfig
);
90 * Free memory (recursively) allocated to a devconfig_t struct
93 * pointer to the devconfig_t to be freed
99 devconfig_t
*devconfig
= (devconfig_t
*)arg
;
101 if (devconfig
== NULL
) {
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 */
130 * Check the type of the given device.
133 * the device whose type to check
136 * the type of the device against which to compare
138 * @return B_TRUE if the device is of the given type, B_FALSE
144 component_type_t type
)
146 component_type_t curtype
;
148 if (device
== NULL
) {
152 if (devconfig_get_type(device
, &curtype
) != 0) {
156 if (curtype
!= type
) {
164 * Get the first component of the given type from the given
165 * devconfig_t. Create the component if create is B_TRUE.
168 * if the requested component does not exist and its
169 * creation was not requested
172 * if the requested component exists or was created
175 * if the requested component did not exist and could not
179 devconfig_get_component(
181 component_type_t type
,
182 devconfig_t
**component
,
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
);
204 /* No component found */
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
));
229 * Set the available devices for use in creating this device
232 * a devconfig_t representing the device to modify
235 * A NULL-terminated array of device names
238 devconfig_set_available(
242 device
->available
= available
;
246 * Get the available devices for use in creating this device
249 * a devconfig_t representing the device to examine
252 * A NULL-terminated array of device names
255 devconfig_get_available(
258 return (device
->available
);
262 * Set the unavailable devices which may not be used in creating this
266 * a devconfig_t representing the device to modify
269 * A NULL-terminated array of device names
272 devconfig_set_unavailable(
276 device
->unavailable
= unavailable
;
280 * Get the unavailable devices for use in creating this device
283 * a devconfig_t representing the device to examine
285 * @return unavailable
286 * A NULL-terminated array of device names
289 devconfig_get_unavailable(
292 return (device
->unavailable
);
296 * Set the subcomponent devices of a given device
299 * a devconfig_t representing the device to examine
302 * A dlist_t containing devconfig_t devices
305 devconfig_set_components(
309 device
->components
= components
;
313 * Get the subcomponent devices of a given device
316 * a devconfig_t representing the device to examine
318 * @return A dlist_t containing devconfig_t devices
321 devconfig_get_components(
324 return (device
->components
);
328 * Set the device name
331 * a devconfig_t representing the device to modify
334 * the value to set as the device name
340 * if an error occurred. Use get_error_string() to
341 * retrieve the associated error message.
348 return (set_string(device
->attributes
, ATTR_NAME
, name
));
352 * Set the disk set name
355 * a devconfig_t representing the diskset to modify
358 * the value to set as the device name
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
,
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
);
380 return (devconfig_set_name(diskset
, name
));
384 * Set the device name
387 * a devconfig_t representing the hsp to modify
390 * the value to set as the device name
396 * if an error occurred. Use get_error_string() to
397 * retrieve the associated error message.
400 devconfig_set_hsp_name(
405 if (!is_hspname(name
)) {
406 volume_set_error(gettext("invalid hot spare pool name: %s"), name
);
410 return (devconfig_set_name(hsp
, name
));
414 * Set the device name
417 * a devconfig_t representing the volume to modify
420 * the value to set as the device name
426 * if an error occurred. Use get_error_string() to
427 * retrieve the associated error message.
430 devconfig_set_volume_name(
435 if (!is_metaname(name
)) {
436 volume_set_error(gettext("invalid volume name: %s"), name
);
440 return (devconfig_set_name(volume
, name
));
444 * Get the device name
447 * a devconfig_t representing the volume to examine
450 * RETURN: the device name
456 * if an error occurred. Use get_error_string() to
457 * retrieve the associated error message.
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
;
476 * Set the device type
479 * a devconfig_t representing the device to modify
482 * the value to set as the device type
488 * if an error occurred. Use get_error_string() to
489 * retrieve the associated error message.
494 component_type_t type
)
496 return (set_uint16(device
->attributes
, ATTR_TYPE
, (uint16_t)type
));
500 * Get the device type
503 * a devconfig_t representing the device to examine
506 * RETURN: the device type
512 * if an error occurred. Use get_error_string() to
513 * retrieve the associated error message.
518 component_type_t
*type
)
521 int error
= get_uint16(device
->attributes
, ATTR_TYPE
, &val
);
524 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
526 volume_set_error(gettext("device type not set"));
527 error
= ERR_ATTR_UNSET
;
532 *type
= (component_type_t
)val
;
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.
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
555 * if an error occurred. Use get_error_string() to
556 * retrieve the associated error message.
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
);
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.
584 * a devconfig_t representing the device to examine
586 * @param size_in_bytes
587 * RETURN: the device size in bytes
593 * if an error occurred. Use get_error_string() to
594 * retrieve the associated error message.
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
;
614 * Set the device size in blocks
617 * a devconfig_t representing the device to modify
620 * the value to set as the device size in blocks
626 * if an error occurred. Use get_error_string() to
627 * retrieve the associated error message.
630 devconfig_set_size_in_blocks(
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
);
642 return (set_uint64(device
->attributes
,
643 ATTR_SIZEINBLOCKS
, size_in_blocks
));
647 * Get the device size in blocks
650 * a devconfig_t representing the device to examine
652 * @param size_in_blocks
653 * RETURN: the device size in blocks
659 * if an error occurred. Use get_error_string() to
660 * retrieve the associated error message.
663 devconfig_get_size_in_blocks(
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
;
680 * Set the the slice index
683 * a devconfig_t representing the slice to modify
686 * the value to set as the the slice index
692 * if an error occurred. Use get_error_string() to
693 * retrieve the associated error message.
696 devconfig_set_slice_index(
700 return (set_uint16(slice
->attributes
, ATTR_SLICE_INDEX
, index
));
704 * Get the slice index
707 * a devconfig_t representing the device to examine
710 * RETURN: the slice index
716 * if an error occurred. Use get_error_string() to
717 * retrieve the associated error message.
720 devconfig_get_slice_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
;
736 * Set the the slice start block
739 * a devconfig_t representing the slice to modify
742 * the value to set as the the slice start block
748 * if an error occurred. Use get_error_string() to
749 * retrieve the associated error message.
752 devconfig_set_slice_start_block(
754 uint64_t start_block
)
756 return (set_uint64(slice
->attributes
,
757 ATTR_SLICE_STARTSECTOR
, start_block
));
761 * Get the slice start block
764 * a devconfig_t representing the device to examine
767 * RETURN: the slice start block
773 * if an error occurred. Use get_error_string() to
774 * retrieve the associated error message.
777 devconfig_get_slice_start_block(
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
;
794 * Set the number of subcomponents in mirror
797 * a devconfig_t representing the mirror to modify
800 * the value to set as the number of subcomponents in
807 * if an error occurred. Use get_error_string() to
808 * retrieve the associated error message.
811 devconfig_set_mirror_nsubs(
815 /* Validate against limits */
816 if (nsubs
< 1 || nsubs
> NMIRROR
) {
818 gettext("number of submirrors (%d) out of valid range (%d-%d)"),
823 return (set_uint16(mirror
->attributes
, ATTR_MIRROR_NSUBMIRRORS
, nsubs
));
827 * Get number of subcomponents in mirror
830 * a devconfig_t representing the device to examine
833 * RETURN: number of subcomponents in mirror
839 * if an error occurred. Use get_error_string() to
840 * retrieve the associated error message.
843 devconfig_get_mirror_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
;
860 * Set the read strategy for mirror
863 * a devconfig_t representing the mirror to modify
866 * the value to set as the read strategy for mirror
872 * if an error occurred. Use get_error_string() to
873 * retrieve the associated error message.
876 devconfig_set_mirror_read(
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
888 * a devconfig_t representing the device to examine
891 * RETURN: read strategy for mirror
897 * if an error occurred. Use get_error_string() to
898 * retrieve the associated error message.
901 devconfig_get_mirror_read(
903 mirror_read_strategy_t
*read
)
906 int error
= get_uint16(mirror
->attributes
, ATTR_MIRROR_READ
, &val
);
909 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
911 volume_set_error(gettext("mirror read strategy not set"));
912 error
= ERR_ATTR_UNSET
;
917 *read
= (mirror_read_strategy_t
)val
;
924 * Set the write strategy for mirror
927 * a devconfig_t representing the mirror to modify
930 * the value to set as the write strategy for mirror
936 * if an error occurred. Use get_error_string() to
937 * retrieve the associated error message.
940 devconfig_set_mirror_write(
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
952 * a devconfig_t representing the device to examine
955 * RETURN: write strategy for mirror
961 * if an error occurred. Use get_error_string() to
962 * retrieve the associated error message.
965 devconfig_get_mirror_write(
967 mirror_write_strategy_t
*write
)
970 int error
= get_uint16(mirror
->attributes
, ATTR_MIRROR_WRITE
, &val
);
973 /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */
975 volume_set_error(gettext("mirror write strategy not set"));
976 error
= ERR_ATTR_UNSET
;
981 *write
= (mirror_write_strategy_t
)val
;
988 * Set the resync pass for mirror
991 * a devconfig_t representing the mirror to modify
994 * the value to set as the resync pass for mirror
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
,
1008 /* Validate against max value */
1009 if (pass
> MD_PASS_MAX
) {
1011 gettext("mirror pass number (%d) out of valid range (0-%d)"),
1016 return (set_uint16(mirror
->attributes
, ATTR_MIRROR_PASSNUM
, pass
));
1020 * Get resync pass for mirror
1023 * a devconfig_t representing the device to examine
1026 * RETURN: resync pass for mirror
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
,
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
;
1052 * Set the minimum number of components in stripe
1055 * a devconfig_t representing the stripe to modify
1058 * the value to set as the minimum number of components
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
,
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
);
1081 return (set_uint16(stripe
->attributes
, ATTR_STRIPE_MINCOMP
, mincomp
));
1085 * Get minimum number of components in stripe
1088 * a devconfig_t representing the device to examine
1091 * RETURN: minimum number of components in stripe
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
,
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
) {
1111 gettext("minimum number of stripe components not set"));
1112 error
= ERR_ATTR_UNSET
;
1119 * Set the maximum number of components in stripe
1122 * a devconfig_t representing the stripe to modify
1125 * the value to set as the maximum number of components
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
,
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
);
1148 return (set_uint16(stripe
->attributes
, ATTR_STRIPE_MAXCOMP
, maxcomp
));
1152 * Get maximum number of components in stripe
1155 * a devconfig_t representing the device to examine
1158 * RETURN: maximum number of components in stripe
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
,
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
) {
1178 gettext("maximum number of stripe components not set"));
1179 error
= ERR_ATTR_UNSET
;
1186 * Set the stripe interlace
1189 * a devconfig_t representing the stripe to modify
1192 * the value to set as the stripe interlace
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
,
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
);
1217 gettext("interlace (%s) out of valid range (%s - %s)"),
1218 intstr
, minstr
, maxstr
);
1227 return (set_uint64(stripe
->attributes
,
1228 ATTR_STRIPE_INTERLACE
, interlace
));
1232 * Get stripe interlace
1235 * a devconfig_t representing the device to examine
1238 * RETURN: stripe interlace
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
;
1265 * Set the redundancy level for a volume.
1268 * a devconfig_t representing the volume to modify
1271 * If 0, a stripe will be created. If > 0, a mirror with
1272 * this number of submirrors will be created.
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
,
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
);
1294 return (set_uint16(volume
->attributes
, ATTR_VOLUME_REDUNDANCY
, rlevel
));
1298 * Get the redundancy level for a volume.
1301 * a devconfig_t representing the device to examine
1304 * RETURN: the redundancy level for a volume
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
,
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
;
1331 * Set the number of paths in volume
1334 * a devconfig_t representing the volume to modify
1337 * the value to set as the number of paths in volume
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
,
1351 /* Validate against limits */
1352 if (npaths
< MIN_NDATAPATHS
|| npaths
> MAX_NDATAPATHS
) {
1354 gettext("number of data paths (%d) out of valid range (%d-%d)"),
1355 npaths
, MIN_NDATAPATHS
, MAX_NDATAPATHS
);
1359 return (set_uint16(volume
->attributes
, ATTR_VOLUME_DATAPATHS
, npaths
));
1363 * Get number of paths in volume
1366 * a devconfig_t representing the device to examine
1369 * RETURN: number of paths in volume
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
,
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
;
1396 * Set the HSP creation option (for volume, stripe, concat, mirror)
1399 * a devconfig_t representing the volume to modify
1402 * the value to set as the HSP creation option
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
,
1416 return (set_boolean(volume
->attributes
, ATTR_VOLUME_USEHSP
, usehsp
));
1420 * Get HSP creation option (for volume, stripe, concat, mirror)
1423 * a devconfig_t representing the device to examine
1426 * RETURN: HSP creation option (for volume, stripe,
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
,
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
;
1454 * Get the string representation of the volume's type
1457 * a valid component_type_t
1459 * @return an internationalized string representing the given
1463 devconfig_type_to_str(
1464 component_type_t 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;
1484 case TYPE_UNKNOWN
: str
= gettext("Unknown"); break;
1491 * Get the string representation of the mirror's read strategy
1494 * a valid mirror_read_strategy_t
1496 * @return an internationalized string representing the given
1500 devconfig_read_strategy_to_str(
1501 mirror_read_strategy_t 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;
1516 * Get the string representation of the mirror's write strategy
1519 * a valid mirror_write_strategy_t
1521 * @return an internationalized string representing the given
1525 devconfig_write_strategy_to_str(
1526 mirror_write_strategy_t write
)
1531 case MIRROR_WRITE_PARALLEL
: str
= gettext("PARALLEL"); break;
1532 case MIRROR_WRITE_SERIAL
: str
= gettext("SERIAL"); break;
1541 * Dump the contents of a devconfig_t struct to stdout.
1544 * the devconfig_t to examine
1547 * a prefix string to print before each line
1551 devconfig_t
*device
,
1554 dlist_t
*comps
= NULL
;
1555 char **array
= NULL
;
1559 component_type_t type
= TYPE_UNKNOWN
;
1560 boolean_t
bool = B_FALSE
;
1563 mirror_read_strategy_t read
;
1564 mirror_write_strategy_t write
;
1566 if (device
== NULL
) {
1571 if (devconfig_get_type(device
, &type
) == 0) {
1572 printf("%s%s\n", prefix
, devconfig_type_to_str(type
));
1576 if (devconfig_get_name(device
, &str
) == 0) {
1577 printf("%s name: %s\n", prefix
, str
);
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
);
1591 if (devconfig_get_volume_usehsp(device
, &bool) == 0) {
1592 printf("%s usehsp: %s\n", prefix
, bool? "TRUE" : "FALSE");
1598 if (devconfig_get_volume_redundancy_level(
1599 device
, &val16
) == 0) {
1600 printf("%s volume redundancy level: %d\n", prefix
, val16
);
1604 if (devconfig_get_volume_npaths(device
, &val16
) == 0) {
1605 printf("%s volume npaths: %d\n", prefix
, val16
);
1612 if (devconfig_get_mirror_nsubs(device
, &val16
) == 0) {
1613 printf("%s mirror nsubs: %d\n", prefix
, val16
);
1617 if (devconfig_get_mirror_read(device
, &read
) == 0) {
1618 printf("%s mirror read: %s\n", prefix
,
1619 devconfig_read_strategy_to_str(read
));
1623 if (devconfig_get_mirror_write(device
, &write
) == 0) {
1624 printf("%s mirror write: %s\n", prefix
,
1625 devconfig_write_strategy_to_str(write
));
1629 if (devconfig_get_mirror_pass(device
, &val16
) == 0) {
1630 printf("%s mirror pass: %d\n", prefix
, val16
);
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
);
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
);
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
]);
1682 comps
= devconfig_get_components(device
);
1683 if (comps
!= NULL
) {
1685 snprintf(buf
, 128, "%s%s", prefix
, " ");
1686 for (; comps
!= NULL
; comps
= comps
->next
) {
1687 devconfig_dump((devconfig_t
*)comps
->obj
, buf
);