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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include "volume_error.h"
34 #include "volume_devconfig.h"
35 #include "volume_dlist.h"
36 #include "volume_output.h"
38 #include "layout_device_cache.h"
39 #include "layout_device_util.h"
40 #include "layout_discovery.h"
41 #include "layout_dlist_util.h"
42 #include "layout_messages.h"
43 #include "layout_request.h"
44 #include "layout_slice.h"
45 #include "layout_svm_util.h"
47 #define _LAYOUT_STRIPE_C
49 static int compose_stripe(
56 devconfig_t
**stripe
);
58 static int compose_stripe_within_hba(
64 devconfig_t
**stripe
);
66 static int assemble_stripe(
69 devconfig_t
**stripe
);
72 order_stripe_components_alternate_hbas(
75 static int compute_usable_stripe_capacity(
81 * FUNCTION: layout_stripe(devconfig_t *request, uint64_t nbytes,
84 * INPUT: request - pointer to a devconfig_t of the current request
85 * nbytes - the desired capacity of the stripe
87 * OUPUT: results - pointer to a list of composed volumes
89 * RETURNS: int - 0 on success
92 * PURPOSE: Main layout driver for composing stripe volumes.
94 * Attempts to construct a stripe of size nbytes.
96 * Basic goal of all strategies is to build wide-thin stripes:
97 * build widest stripe possible across as many HBAs as possible.
99 * Several different layout strategies are tried in order
100 * of preference until one succeeds or there are none left.
102 * 1 - stripe across similar HBAs
103 * . number of components is driven by # of HBAs
104 * . requires mincomp available HBAs
106 * 2 - stripe within a single HBA
107 * . number of components is driven by # of disks
108 * . requires at least 1 HBA with mincomp disks
110 * 3 - stripe across all available disks on similar HBAs
111 * . number of components is driven by # of disk
112 * . requires at least mincomp disks
114 * 4 - stripe across all available HBAs
115 * . number of components is driven by # of HBAs
116 * . requires at least mincomp HBAs
118 * 5 - stripe across all available disks on all HBAs
119 * . number of components is driven by # of disks
120 * . requires at least mincomp disks
122 * Each strategy tries to compose a stripe with the
123 * maximum number of components first then reduces the
124 * number of components down to mincomp.
126 * get allowed minimum number of stripe components
127 * get allowed maximum number of stripe components
130 * group HBAs by characteristics
131 * for (each HBA grouping) and (stripe not composed) {
132 * select next HBA group
133 * for (strategy[1,2,3]) and (stripe not composed) {
134 * compose stripe using HBAs in group
138 * if (stripe not composed) {
139 * for (strategy[4,5]) and (stripe not composed) {
140 * compose stripe using all HBAs
144 * if (stripe composed) {
145 * append composed stripe to results
151 devconfig_t
*request
,
156 * these enums define the # of strategies and the preference order
157 * in which they are tried
160 STRIPE_ACROSS_SIMILAR_HBAS_DISK_PER
= 0,
161 STRIPE_WITHIN_SIMILAR_HBA
,
162 STRIPE_ACROSS_SIMILAR_HBAS
,
163 N_SIMILAR_HBA_STRATEGIES
164 } similar_hba_strategy_order_t
;
167 STRIPE_ACROSS_ANY_HBAS_DISK_PER
= 0,
168 STRIPE_ACROSS_ANY_HBAS
,
170 } any_hba_strategy_order_t
;
173 dlist_t
*usable_hbas
= NULL
;
174 dlist_t
*similar_hba_groups
= NULL
;
175 dlist_t
*iter
= NULL
;
176 devconfig_t
*stripe
= NULL
;
178 uint16_t mincomp
= 0;
179 uint16_t maxcomp
= 0;
183 (error
= get_usable_hbas(&usable_hbas
));
188 print_layout_volume_msg(devconfig_type_to_str(TYPE_STRIPE
), nbytes
);
190 if (dlist_length(usable_hbas
) == 0) {
192 volume_set_error(gettext("There are no usable HBAs."));
196 ((error
= group_similar_hbas(usable_hbas
, &similar_hba_groups
)) != 0) ||
199 * determine the min/max number of stripe components
200 * based on the request, the diskset defaults or the
201 * global defaults. These are absolute limits, the
202 * actual values are determined by the number of HBAs
203 * and/or disks available.
205 (error
= get_stripe_min_comp(request
, &mincomp
)) ||
206 (error
= get_stripe_max_comp(request
, &maxcomp
));
211 for (iter
= similar_hba_groups
;
212 (error
== 0) && (stripe
== NULL
) && (iter
!= NULL
);
215 dlist_t
*hbas
= (dlist_t
*)iter
->obj
;
217 similar_hba_strategy_order_t order
;
219 for (order
= STRIPE_ACROSS_SIMILAR_HBAS_DISK_PER
;
220 (order
< N_SIMILAR_HBA_STRATEGIES
) &&
221 (stripe
== NULL
) && (error
== 0);
224 dlist_t
*selhbas
= NULL
;
225 dlist_t
*disks
= NULL
;
230 case STRIPE_ACROSS_SIMILAR_HBAS_DISK_PER
:
232 error
= select_hbas_with_n_disks(
233 request
, hbas
, 1, &selhbas
, &disks
);
238 oprintf(OUTPUT_TERSE
,
239 gettext(" -->Strategy 1: use 1 disk from %d-%d similar HBAs - stripe across HBAs\n"),
243 if ((n
= dlist_length(selhbas
)) >= mincomp
) {
244 n
= ((n
> maxcomp
) ? maxcomp
: n
);
245 error
= compose_stripe(
246 request
, nbytes
, disks
, n
,
247 mincomp
, NULL
, &stripe
);
249 print_insufficient_hbas_msg(n
);
255 case STRIPE_WITHIN_SIMILAR_HBA
:
257 error
= select_hbas_with_n_disks(
258 request
, hbas
, mincomp
, &selhbas
, &disks
);
263 oprintf(OUTPUT_TERSE
,
264 gettext(" -->Strategy 2: use %d-%d disks from any single HBA - stripe within HBA\n"),
268 if ((n
= dlist_length(selhbas
)) > 0) {
269 error
= compose_stripe_within_hba(
270 request
, selhbas
, nbytes
,
271 mincomp
, maxcomp
, &stripe
);
273 print_insufficient_disks_msg(n
);
279 case STRIPE_ACROSS_SIMILAR_HBAS
:
281 error
= select_hbas_with_n_disks(
282 request
, hbas
, 1, &selhbas
, &disks
);
287 oprintf(OUTPUT_TERSE
,
288 gettext(" -->Strategy 3: use %d-%d disks from %d similar HBAs - stripe across HBAs\n"),
289 mincomp
, maxcomp
, dlist_length(hbas
));
292 if ((n
= dlist_length(selhbas
)) > 0) {
293 if ((n
= dlist_length(disks
)) >= mincomp
) {
294 n
= ((n
> maxcomp
) ? maxcomp
: n
);
295 error
= compose_stripe(
296 request
, nbytes
, disks
, n
,
297 mincomp
, NULL
, &stripe
);
299 print_insufficient_disks_msg(n
);
302 print_insufficient_hbas_msg(n
);
312 dlist_free_items(disks
, NULL
);
313 dlist_free_items(selhbas
, NULL
);
317 for (iter
= similar_hba_groups
; iter
!= NULL
; iter
= iter
->next
) {
318 dlist_free_items((dlist_t
*)iter
->obj
, NULL
);
320 dlist_free_items(similar_hba_groups
, NULL
);
323 * if striping within similar HBA groups failed,
324 * try across all available HBAs
326 if ((stripe
== NULL
) && (error
== 0)) {
328 any_hba_strategy_order_t order
;
330 for (order
= STRIPE_ACROSS_ANY_HBAS_DISK_PER
;
331 (order
< N_ANY_HBA_STRATEGIES
) &&
332 (stripe
== NULL
) && (error
== 0);
335 dlist_t
*selhbas
= NULL
;
336 dlist_t
*disks
= NULL
;
341 case STRIPE_ACROSS_ANY_HBAS_DISK_PER
:
343 error
= select_hbas_with_n_disks(
344 request
, usable_hbas
, 1, &selhbas
, &disks
);
349 oprintf(OUTPUT_TERSE
,
350 gettext(" -->Strategy 4: use 1 disk from %d-%d available HBAs - stripe across any HBAs\n"),
354 if ((n
= dlist_length(selhbas
)) >= mincomp
) {
356 n
= ((n
> maxcomp
) ? maxcomp
: n
);
357 error
= compose_stripe(
358 request
, nbytes
, disks
, n
,
359 mincomp
, NULL
, &stripe
);
362 print_insufficient_hbas_msg(n
);
368 case STRIPE_ACROSS_ANY_HBAS
:
370 error
= select_hbas_with_n_disks(
371 request
, usable_hbas
, 1, &selhbas
, &disks
);
376 oprintf(OUTPUT_TERSE
,
377 gettext(" -->Strategy 5: use %d-%d disks from %d available HBA - stripe across any HBAs\n"),
378 mincomp
, maxcomp
, dlist_length(selhbas
));
381 if ((n
= dlist_length(disks
)) >= mincomp
) {
383 n
= ((n
> maxcomp
) ? maxcomp
: n
);
384 error
= compose_stripe(
385 request
, nbytes
, disks
, n
,
386 mincomp
, NULL
, &stripe
);
389 print_insufficient_disks_msg(n
);
396 dlist_free_items(disks
, NULL
);
397 dlist_free_items(selhbas
, NULL
);
401 if (stripe
!= NULL
) {
403 dlist_t
*item
= NULL
;
404 if ((item
= dlist_new_item(stripe
)) == NULL
) {
407 *results
= dlist_append(item
, *results
, AT_TAIL
);
408 print_layout_success_msg();
411 } else if (error
!= 0) {
413 print_debug_failure_msg(
414 devconfig_type_to_str(TYPE_STRIPE
),
415 get_error_string(error
));
419 print_insufficient_resources_msg(
420 devconfig_type_to_str(TYPE_STRIPE
));
428 * FUNCTION: populate_stripe(devconfig_t *request, uint64_t nbytes,
429 * dlist_t *disks, uint16_t ncomp, dlist_t *othervols,
430 * devconfig_t **stripe)
432 * INPUT: request - pointer to a request devconfig_t
433 * nbytes - desired stripe size
434 * disks - pointer to a list of availalb disks
435 * ncomp - number of components desired
436 * othervols - pointer to a list of other volumes whose
437 * composition may affect this stripe
438 * (e.g., submirrors of the same mirror)
440 * OUTPUT: stripe - pointer to a devconfig_t to hold resulting stripe
442 * RETURNS: int - 0 on success
445 * PURPOSE: Helper to populate a stripe with the specified number of
446 * components and aggregate capacity using slices on disks
449 * If the othervols list is not empty, the slice components
450 * chosen for the stripe must not on the same disks as any
451 * of the other volumes.
453 * If sufficient slice components can be found, the stripe
454 * is assembled and returned.
458 devconfig_t
*request
,
463 devconfig_t
**stripe
)
466 uint16_t ncomps
= 0; /* number of components found */
467 uint64_t rsize
= 0; /* reqd component size */
469 dlist_t
*other_hbas
= NULL
;
470 dlist_t
*other_disks
= NULL
;
472 dlist_t
*slices
= NULL
;
473 dlist_t
*comps
= NULL
;
479 ((error
= disks_get_avail_slices(request
, disks
, &slices
)) != 0) ||
480 (error
= get_volume_npaths(request
, &npaths
));
485 print_populate_volume_ncomps_msg(
486 devconfig_type_to_str(TYPE_STRIPE
), nbytes
, ncomp
);
488 if (slices
== NULL
) {
489 print_populate_no_slices_msg();
493 /* determine HBAs and disks used by othervols */
494 error
= get_hbas_and_disks_used_by_volumes(othervols
,
495 &other_hbas
, &other_disks
);
497 dlist_free_items(other_hbas
, NULL
);
498 dlist_free_items(other_disks
, NULL
);
502 print_populate_choose_slices_msg();
505 * each stripe component needs to be this size.
506 * Note that the stripe interlace doesn't need to be
507 * taken into account in this computation because any
508 * slice selected as a stripe component will be oversized
509 * to account for interlace and cylinder rounding done
512 rsize
= nbytes
/ ncomp
;
515 * need to select 'ncomp' slices that are at least 'rsize'
516 * large in order to reach the desired capacity.
519 while ((ncomps
< ncomp
) && (error
== 0)) {
521 devconfig_t
*comp
= NULL
;
522 dlist_t
*item
= NULL
;
523 dlist_t
*rmvd
= NULL
;
528 * 1st B_TRUE: require a different disk than those used by
529 * comps and othervols
530 * 2nd B_TRUE: requested size is minimum acceptable
531 * 3rd B_TRUE: add an extra cylinder to the resulting slice, this is
532 * necessary for Stripe components whose sizes get rounded
533 * down to an interlace multiple and then down to a cylinder
537 error
= choose_slice(rsize
, npaths
, slices
, comps
,
538 other_hbas
, other_disks
, B_TRUE
, B_TRUE
, B_TRUE
, &comp
);
540 if ((error
== 0) && (comp
!= NULL
)) {
544 item
= dlist_new_item(comp
);
549 /* add selected component to comp list */
550 comps
= dlist_insert_ordered(
554 compare_devconfig_sizes
);
556 /* remove it from the available list */
557 slices
= dlist_remove_equivalent_item(slices
, (void *) comp
,
558 compare_devconfig_and_descriptor_names
, &rmvd
);
564 /* add the component slice to the used list */
565 if ((error
= devconfig_get_name(comp
, &cname
)) == 0) {
566 error
= add_used_slice_by_name(cname
);
569 } else if (comp
== NULL
) {
570 /* no possible slice */
575 dlist_free_items(slices
, NULL
);
576 dlist_free_items(other_hbas
, NULL
);
577 dlist_free_items(other_disks
, NULL
);
579 if (ncomps
== ncomp
) {
581 if ((error
= assemble_stripe(request
, comps
, stripe
)) == 0) {
582 print_populate_success_msg();
584 dlist_free_items(comps
, free_devconfig_object
);
587 } else if (error
== 0) {
590 print_insufficient_components_msg(ncomps
);
591 dlist_free_items(comps
, free_devconfig_object
);
593 print_populate_no_slices_msg();
601 * FUNCTION: populate_explicit_stripe(devconfig_t *request,
604 * INPUT: request - pointer to a request devconfig_t
606 * OUTPUT: results - pointer to a list of volume devconfig_t results
608 * RETURNS: int - 0 on success
611 * PURPOSE: Processes the input stripe request that specifies explicit
614 * The components have already been validated and reserved,
615 * all that is required is to create devconfig_t structs
616 * for each requested slice.
618 * The net size of the stripe is determined by the slice
621 * The stripe devconfig_t is assembled and appended to the
624 * This function is also called from
625 * layout_mirror.populate_explicit_mirror()
628 populate_explicit_stripe(
629 devconfig_t
*request
,
632 devconfig_t
*stripe
= NULL
;
635 dlist_t
*comps
= NULL
;
636 dlist_t
*iter
= NULL
;
637 dlist_t
*item
= NULL
;
639 print_layout_explicit_msg(devconfig_type_to_str(TYPE_STRIPE
));
641 /* assemble components */
642 iter
= devconfig_get_components(request
);
643 for (; (iter
!= NULL
) && (error
== 0); iter
= iter
->next
) {
644 devconfig_t
*rqst
= (devconfig_t
*)iter
->obj
;
645 dm_descriptor_t rqst_slice
= NULL
;
646 char *rqst_name
= NULL
;
647 devconfig_t
*comp
= NULL
;
649 /* slice components have been validated */
650 /* turn each into a devconfig_t */
651 ((error
= devconfig_get_name(rqst
, &rqst_name
)) != 0) ||
652 (error
= slice_get_by_name(rqst_name
, &rqst_slice
)) ||
653 (error
= create_devconfig_for_slice(rqst_slice
, &comp
));
657 print_layout_explicit_added_msg(rqst_name
);
659 item
= dlist_new_item((void *)comp
);
663 comps
= dlist_append(item
, comps
, AT_TAIL
);
669 error
= assemble_stripe(request
, comps
, &stripe
);
673 if ((item
= dlist_new_item(stripe
)) == NULL
) {
676 *results
= dlist_append(item
, *results
, AT_TAIL
);
677 print_populate_success_msg();
680 dlist_free_items(comps
, free_devconfig
);
687 * FUNCTION: compose_stripe(devconfig_t *request, uint64_t nbytes,
688 * dlist_t *disks, uint16_t max, uint16_t min,
689 * dlist_t *othervols, devconfig_t **stripe)
691 * INPUT: request - pointer to a request devconfig_t
692 * nbytes - desired stripe size
693 * disks - pointer to a list of availalb disks
694 * max - maximum number of components allowed
695 * min - minimum number of components allowed
696 * othervols - pointer to a list of other volumes whose
697 * composition may affect this stripe
698 * (e.g., submirrors of the same mirror)
700 * OUTPUT: stripe - pointer to a devconfig_t to hold resulting stripe
702 * RETURNS: int - 0 on success
705 * PURPOSE: Attempt to compose a stripe of capacity nbytes, with
706 * component slices chosen from the input list of disks.
707 * The number of components in the stripe should be in the
708 * range min <= N <= max, more components are preferred.
710 * If a stripe can be composed, a pointer to it will be
711 * returned in the stripe devconfig_t.
713 * This is a loop wrapped around populate_stripe which
714 * varies the number of components between 'max' and 'min'.
718 devconfig_t
*request
,
724 devconfig_t
**stripe
)
730 for (; (error
== 0) && (*stripe
== NULL
) && (max
>= min
); max
--) {
731 error
= populate_stripe(
732 request
, nbytes
, disks
, max
, othervols
, stripe
);
739 * FUNCTION: compose_stripe_within_hba(devconfig_t *request,
740 * dlist_t *hbas, uint64_t nbytes,
741 * int maxcomp, int mincomp, dlist_t **stripe)
743 * INPUT: request - pointer to a devconfig_t of the current request
744 * hbas - pointer to a list of available HBAs
745 * nbytes - the desired capacity for the stripe
746 * maxcomp - the maximum number of stripe components
747 * mincomp - the minimum number of stripe components
749 * OUTPUT: stripe - pointer to a stripe devconfig_t result
751 * RETURNS: int - 0 on success
754 * PURPOSE: Layout function which compose a stripe of the desired size
755 * using available disks within any single HBA from the input list.
757 * The number of components within the composed stripe will be
758 * in the range of min to max, preferring more components
761 * All input HBAs are expected to have at least mincomp
762 * available disks and total space sufficient for the stripe.
764 * If the stripe can be composed, a pointer to it is returned in
765 * the stripe devconfig_t *.
768 * while (more hbas and stripe not composed) {
770 * if (not enough available space on this HBA) {
773 * get available disks for HBA
774 * use # disks as max # of stripe components
775 * try to compose stripe
780 compose_stripe_within_hba(
781 devconfig_t
*request
,
786 devconfig_t
**stripe
)
790 dlist_t
*iter
= NULL
;
795 (iter
!= NULL
) && (error
== 0) && (*stripe
== NULL
);
798 dm_descriptor_t hba
= (uintptr_t)iter
->obj
;
799 dlist_t
*disks
= NULL
;
804 ((error
= get_display_name(hba
, &name
)) != 0) ||
805 (error
= hba_get_avail_disks_and_space(request
,
806 hba
, &disks
, &space
));
809 if (space
>= nbytes
) {
810 ncomp
= dlist_length(disks
);
811 ncomp
= ((ncomp
> max
) ? max
: ncomp
);
812 error
= compose_stripe(
813 request
, nbytes
, disks
, ncomp
,
816 print_hba_insufficient_space_msg(name
, space
);
820 dlist_free_items(disks
, NULL
);
827 * FUNCTION: assemble_stripe(devconfig_t *request, dlist_t *comps,
828 * devconfig_t **stripe)
830 * INPUT: request - pointer to a devconfig_t of the current request
831 * comps - pointer to a list of slice components
833 * OUPUT: stripe - pointer to a devconfig_t to hold final stripe
835 * RETURNS: int - 0 on success
838 * PURPOSE: Helper which creates and populates a stripe devconfig_t
839 * struct using information from the input request and the
840 * list of slice components.
842 * Determines the name of the stripe either from the request
843 * or from the default naming scheme.
845 * Sets the interlace for the stripe if a value is specified
848 * Attaches the input list of components to the devconfig.
852 devconfig_t
*request
,
854 devconfig_t
**stripe
)
860 if ((error
= new_devconfig(stripe
, TYPE_STRIPE
)) == 0) {
861 /* set stripe name, use requested name if specified */
862 if ((error
= devconfig_get_name(request
, &name
)) != 0) {
863 if (error
!= ERR_ATTR_UNSET
) {
864 volume_set_error(gettext("error getting requested name\n"));
872 if ((error
= get_next_volume_name(&name
,
873 TYPE_STRIPE
)) == 0) {
874 error
= devconfig_set_name(*stripe
, name
);
878 error
= devconfig_set_name(*stripe
, name
);
884 if ((error
= get_stripe_interlace(request
, &ilace
)) == 0) {
885 error
= devconfig_set_stripe_interlace(*stripe
, ilace
);
886 } else if (error
== ENOENT
) {
887 ilace
= get_default_stripe_interlace();
894 if ((error
= compute_usable_stripe_capacity(comps
,
895 ilace
, &nbytes
)) == 0) {
896 error
= devconfig_set_size_in_blocks(*stripe
, nbytes
/DEV_BSIZE
);
901 comps
= order_stripe_components_alternate_hbas(comps
);
902 devconfig_set_components(*stripe
, comps
);
904 free_devconfig(*stripe
);
912 * Order the given stripe component list such that the number of
913 * slices on the same hba adjacent to each other in the list are
917 * the slice component list to order
919 * @return the first element of the resulting list
922 order_stripe_components_alternate_hbas(
927 oprintf(OUTPUT_DEBUG
,
928 gettext("Stripe components before ordering to alternate HBAs:\n"));
930 for (iter
= comps
; iter
!= NULL
; iter
= iter
->next
) {
931 devconfig_t
*slice
= (devconfig_t
*)(iter
->obj
);
933 devconfig_get_name(slice
, &name
);
934 oprintf(OUTPUT_DEBUG
, " %s\n", name
);
937 return (dlist_separate_similar_elements(
938 comps
, compare_slices_on_same_hba
));
942 * FUNCTION: compute_usable_stripe_capacity(dlist_t *comps, uint64_t ilace,
945 * INPUT: comps - pointer to a list of stripe components
946 * ilace - the expected stripe interlace in bytes
948 * OUPUT: nbytes - pointer to hold the computed capacity
950 * RETURNS: int - 0 on success
953 * PURPOSE: Helper which computes the usable size of a stripe taking
954 * into account the interlace and cylinder rounding that
955 * libmeta uses: a stripe component's size is rounded down to
956 * an integral multiple of the interlace and then rounded down
957 * to a cylinder boundary on VTOC labeled disks.
959 * (These libmeta computations are in the meta_stripe_attach()
960 * function of .../lib/lvm/libmeta/common/meta_stripe.c and
961 * meta_adjust_geom() in .../lib/lvm/libmeta/common/meta_init.c)
963 * This function's implementation iterates the input list of
964 * stripe component slices and determines the smallest usable
965 * component capacity.
967 * The usable stripe capacity is then that component capacity
968 * times the number of components.
971 compute_usable_stripe_capacity(
976 uint64_t bytes_per_component
= 0;
981 for (iter
= comps
; (iter
!= NULL
) && (error
== 0); iter
= iter
->next
) {
983 devconfig_t
*comp
= (devconfig_t
*)iter
->obj
;
984 char *comp_name
= NULL
;
985 uint64_t comp_nbytes
= 0;
986 dm_descriptor_t comp_disk
;
987 boolean_t comp_disk_efi
= B_FALSE
;
988 uint64_t comp_disk_bps
= 0; /* disk bytes per sector */
990 ((error
= devconfig_get_size(comp
, &comp_nbytes
)) != 0) ||
991 (error
= devconfig_get_name(comp
, &comp_name
)) ||
992 (error
= get_disk_for_named_slice(comp_name
, &comp_disk
)) ||
993 (error
= disk_get_blocksize(comp_disk
, &comp_disk_bps
)) ||
994 (error
= disk_get_is_efi(comp_disk
, &comp_disk_efi
));
997 if (comp_disk_efi
== B_FALSE
) {
1002 /* do cylinder and interlace rounding for non-EFI disks */
1003 ((error
= disk_get_ncylinders(comp_disk
, &ncyls
)) != 0) ||
1004 (error
= disk_get_nheads(comp_disk
, &nhead
)) ||
1005 (error
= disk_get_nsectors(comp_disk
, &nsect
));
1007 /* compute bytes per cyl */
1008 uint64_t bpc
= nhead
* nsect
* comp_disk_bps
;
1010 /* round nbytes down to a multiple of interlace */
1011 comp_nbytes
= (comp_nbytes
/ ilace
) * ilace
;
1013 /* round nbytes down to a cylinder boundary */
1014 comp_nbytes
= (comp_nbytes
/ bpc
) * bpc
;
1018 /* save smallest component size */
1019 if ((bytes_per_component
== 0) ||
1020 (comp_nbytes
< bytes_per_component
)) {
1021 bytes_per_component
= comp_nbytes
;
1029 /* size of stripe = smallest component size * n components */
1030 *nbytes
= (bytes_per_component
* ncomps
);