7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / cmd / lvm / metassist / layout / layout_mirror.c
blobe0d5f48bbe9ae117b53e68645421517d1f65c436
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 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <libintl.h>
31 #include "volume_error.h"
32 #include "volume_dlist.h"
33 #include "volume_output.h"
35 #include "layout_concat.h"
36 #include "layout_device_cache.h"
37 #include "layout_device_util.h"
38 #include "layout_discovery.h"
39 #include "layout_dlist_util.h"
40 #include "layout_messages.h"
41 #include "layout_request.h"
42 #include "layout_slice.h"
43 #include "layout_stripe.h"
44 #include "layout_svm_util.h"
46 #define _LAYOUT_MIRROR_C
48 static int layout_stripe_submirrors(
49 devconfig_t *request,
50 dlist_t *cursubs,
51 uint64_t nbytes,
52 uint16_t nsubs,
53 dlist_t **results);
55 static int layout_concat_submirrors(
56 devconfig_t *request,
57 dlist_t *cursubs,
58 uint64_t nbytes,
59 uint16_t nsubs,
60 dlist_t **results);
62 static int compose_stripe_per_hba(
63 devconfig_t *request,
64 dlist_t *cursubs,
65 dlist_t *hbas,
66 uint64_t nbytes,
67 uint16_t nsubs,
68 uint16_t ncomp,
69 uint16_t mincomp,
70 dlist_t **results);
72 static int compose_stripes_across_hbas(
73 devconfig_t *request,
74 dlist_t *cursubs,
75 dlist_t *hbas,
76 dlist_t *disks,
77 uint64_t nbytes,
78 uint16_t nsubs,
79 uint16_t ncomp,
80 uint16_t mincomp,
81 dlist_t **results);
83 static int compose_stripes_within_hba(
84 devconfig_t *request,
85 dlist_t *cursubs,
86 dlist_t *hbas,
87 uint64_t nbytes,
88 uint16_t nsubs,
89 uint16_t ncomp,
90 uint16_t mincomp,
91 dlist_t **results);
93 static int compose_concat_per_hba(
94 devconfig_t *request,
95 dlist_t *cursubs,
96 dlist_t *hbas,
97 uint64_t nbytes,
98 uint16_t nsubs,
99 dlist_t **results);
101 static int compose_concats_across_hbas(
102 devconfig_t *request,
103 dlist_t *cursubs,
104 dlist_t *hbas,
105 dlist_t *disks,
106 uint64_t nbytes,
107 uint16_t nsubs,
108 dlist_t **results);
110 static int compose_concats_within_hba(
111 devconfig_t *request,
112 dlist_t *cursubs,
113 dlist_t *hba,
114 uint64_t nbytes,
115 uint16_t nsubs,
116 dlist_t **results);
118 static int assemble_mirror(
119 devconfig_t *request,
120 dlist_t *subs,
121 devconfig_t **mirror);
123 static int remove_used_disks(
124 dlist_t **disks,
125 devconfig_t *volume);
127 static int volume_shares_disk(
128 dm_descriptor_t disk,
129 devconfig_t *volume,
130 boolean_t *bool);
132 static int select_mpxio_hbas(
133 dlist_t *hbas,
134 dlist_t **mpxio_hbas);
136 static int set_explicit_submirror_names(
137 dlist_t *reqs,
138 dlist_t *subs);
140 static int set_explicit_submirror_name(
141 devconfig_t *req,
142 devconfig_t *sub);
145 * FUNCTION: layout_mirror(devconfig_t *request, nbytes, dlist_t **results)
147 * INPUT: request - pointer to a request devconfig_t
148 * nsubs - number of submirrors
149 * nbytes - desired mirror size
151 * OUTPUT: results - pointer to a list of volume devconfig_t results
153 * RETURNS: int - 0 on success
154 * !0 otherwise.
156 * PURPOSE: Main driver to handle a mirror request that does not specify
157 * subcomponents.
159 * Striped submirrors are tried first, then concats.
162 layout_mirror(
163 devconfig_t *request,
164 uint16_t nsubs,
165 uint64_t nbytes,
166 dlist_t **results)
168 dlist_t *subs = NULL;
169 dlist_t *item = NULL;
170 boolean_t usehsp = B_FALSE;
171 int error = 0;
173 if ((error = get_volume_faultrecov(request, &usehsp)) != 0) {
174 if (error != ERR_ATTR_UNSET) {
175 return (error);
177 error = 0;
180 print_layout_volume_msg(devconfig_type_to_str(TYPE_MIRROR), nbytes);
182 /* prefer stripe submirrors */
183 if ((error = layout_stripe_submirrors(
184 request, NULL, nbytes, nsubs, &subs)) != 0) {
185 return (error);
188 if (subs == NULL) {
189 /* second chance: mirrored concats */
190 if ((error = layout_concat_submirrors(
191 request, NULL, nbytes, nsubs, &subs)) != 0) {
192 return (error);
196 if (subs != NULL) {
198 devconfig_t *mirror = NULL;
199 dlist_t *iter = NULL;
201 /* unset submirror names prior to final assembly */
202 for (iter = subs; iter != NULL; iter = iter->next) {
203 devconfig_t *sub = (devconfig_t *)iter->obj;
204 char *name = NULL;
206 (void) devconfig_get_name(sub, &name);
207 release_volume_name(name);
208 (void) devconfig_set_name(sub, "");
211 error = assemble_mirror(request, subs, &mirror);
212 if (error == 0) {
214 if ((item = dlist_new_item(mirror)) == NULL) {
215 error = ENOMEM;
216 } else {
217 *results = dlist_append(item, *results, AT_TAIL);
219 /* remember submirrors that need HSPs */
220 if (usehsp == B_TRUE) {
221 error = add_to_hsp_list(
222 devconfig_get_components(mirror));
225 print_layout_success_msg();
227 } else {
228 /* cleanup submirrors */
229 dlist_free_items(subs, free_devconfig_object);
230 subs = NULL;
233 } else if (error != 0) {
235 print_debug_failure_msg(devconfig_type_to_str(TYPE_MIRROR),
236 get_error_string(error));
238 } else {
240 print_insufficient_resources_msg(
241 devconfig_type_to_str(TYPE_MIRROR));
242 error = -1;
245 return (error);
249 * FUNCTION: populate_explicit_mirror(devconfig_t *request,
250 * dlist_t **results)
252 * INPUT: request - pointer to a request devconfig_t
254 * OUTPUT: results - pointer to a list of volume devconfig_t results
256 * RETURNS: int - 0 on success
257 * !0 otherwise.
259 * PURPOSE: Processes the input mirror request specifying explicit layout
260 * constraints on the submirrors.
262 * Primary submirror constraint is explicit type, either
263 * stripe or concat. Submirror types may be mixed.
265 * Submirror sizes or components may be specified explicitly.
267 * If the mirror does not specify a size, assume the first explicit
268 * submirror size is the desired size. If a submirror does not
269 * specify a size or components, use the mirror size.
271 * Scan the submirror requests: those with specific components
272 * get assembled as encountered. The remainder are grouped by
273 * type and handled by layout_stripe_submirrors() or
274 * layout_concat_submirrors().
276 * If all specified submirrors can be assembled, the final mirror
277 * is assembled and appended to the results list.
280 populate_explicit_mirror(
281 devconfig_t *request,
282 dlist_t **results)
284 dlist_t *composed = NULL;
285 dlist_t *list = NULL;
286 dlist_t *iter = NULL;
287 dlist_t *concats_by_size = NULL;
288 dlist_t *stripes_by_size = NULL;
289 int nsubs = 0;
290 int error = 0;
291 uint64_t msize = 0;
292 boolean_t usehsp = B_FALSE;
294 list = devconfig_get_components(request);
295 nsubs = dlist_length(list);
297 if ((error = get_volume_faultrecov(request, &usehsp)) != 0) {
298 if (error != ERR_ATTR_UNSET) {
299 return (error);
301 error = 0;
304 if ((error = devconfig_get_size(request, &msize)) != 0) {
305 if (error == ERR_ATTR_UNSET) {
306 error = 0;
307 msize = 0;
308 } else {
309 return (error);
313 print_layout_explicit_msg(devconfig_type_to_str(TYPE_MIRROR));
316 * Scan the list of specified submirrors, collect those that only
317 * specify size (or no size). Process those with explicit components
318 * immediately.
320 composed = NULL;
321 for (iter = list; (iter != NULL) && (error == 0); iter = iter->next) {
323 devconfig_t *comp = (devconfig_t *)iter->obj;
324 component_type_t ctype = TYPE_UNKNOWN;
325 dlist_t *clist = NULL;
326 uint64_t csize = 0;
327 dlist_t *item = NULL;
329 (void) devconfig_get_type(comp, &ctype);
330 (void) devconfig_get_size(comp, &csize);
331 clist = devconfig_get_components(comp);
333 if (clist != NULL) {
335 /* components specified */
337 if (ctype == TYPE_STRIPE) {
338 error = populate_explicit_stripe(comp, &item);
339 } else {
340 error = populate_explicit_concat(comp, &item);
343 if (error == 0) {
344 set_explicit_submirror_name(
345 comp, (devconfig_t *)item->obj);
346 composed = dlist_append(item, composed, AT_TAIL);
349 } else {
351 /* no components specified */
353 /* if no size is specified, it needs to be inferred */
355 if (msize == 0) {
356 /* mirror specified no size, first explicit submirror */
357 /* size is assumed to be the desired mirror size */
358 msize = csize;
360 if (csize == 0) {
361 /* this submirror specified no size, use mirror size */
362 devconfig_set_size(comp, msize);
365 if ((item = dlist_new_item(comp)) == NULL) {
366 error = ENOMEM;
367 break;
370 if (ctype == TYPE_STRIPE) {
371 stripes_by_size = dlist_append(
372 item, stripes_by_size, AT_TAIL);
373 } else {
374 concats_by_size = dlist_append(
375 item, concats_by_size, AT_TAIL);
381 /* compose stripes specified by size */
382 if ((error == 0) && (stripes_by_size != NULL)) {
383 uint16_t n = dlist_length(stripes_by_size);
384 dlist_t *stripes = NULL;
385 if ((error = layout_stripe_submirrors(
386 request, composed, msize, n, &stripes)) == 0) {
388 /* adjust stripe names */
389 set_explicit_submirror_names(stripes_by_size, stripes);
390 composed = dlist_append(stripes, composed, AT_TAIL);
392 } else {
393 /* these stripes failed, skip concats_by_size */
394 dlist_free_items(stripes, free_devconfig_object);
395 dlist_free_items(concats_by_size, NULL);
396 concats_by_size = NULL;
398 dlist_free_items(stripes_by_size, NULL);
401 /* compose concats specified by size */
402 if ((error == 0) && (concats_by_size != NULL)) {
403 uint16_t n = dlist_length(concats_by_size);
404 dlist_t *concats = NULL;
405 if ((error = layout_concat_submirrors(
406 request, composed, msize, n, &concats)) == 0) {
408 /* adjust concat names */
409 set_explicit_submirror_names(concats_by_size, concats);
410 composed = dlist_append(concats, composed, AT_TAIL);
412 } else {
414 /* these concats failed */
415 dlist_free_items(concats, free_devconfig_object);
418 dlist_free_items(concats_by_size, NULL);
421 if ((composed != NULL) && ((dlist_length(composed) == nsubs))) {
423 /* assemble final mirror */
425 devconfig_t *mirror = NULL;
426 dlist_t *item = NULL;
428 if ((error = assemble_mirror(request, composed, &mirror)) == 0) {
430 if ((item = dlist_new_item(mirror)) == NULL) {
431 error = ENOMEM;
432 } else {
433 *results = dlist_append(item, *results, AT_TAIL);
434 if (usehsp == B_TRUE) {
435 error = add_to_hsp_list(
436 devconfig_get_components(mirror));
438 print_layout_success_msg();
442 } else if (error != 0) {
444 print_debug_failure_msg(
445 devconfig_type_to_str(TYPE_MIRROR),
446 get_error_string(error));
448 } else {
450 dlist_free_items(composed, free_devconfig_object);
451 print_insufficient_resources_msg(
452 devconfig_type_to_str(TYPE_MIRROR));
453 error = -1;
456 return (error);
460 * FUNCTION: assemble_mirror(devconfig_t *request, dlist_t *subs,
461 * devconfig_t **mirror)
463 * INPUT: request - pointer to a devconfig_t of the current request
464 * subs - pointer to a list of composed submirrors
466 * OUPUT: mirror - pointer to a devconfig_t to hold final mirror
468 * RETURNS: int - 0 on success
469 * !0 otherwise.
471 * PURPOSE: Helper which creates and populates a mirror devconfig_t
472 * struct using information from the input request and the
473 * list of submirror components.
475 * Determines the name of the mirror either from the request
476 * or from the default naming scheme and assigns names to
477 * unnamed submirrors according to the default naming scheme.
479 * Sets the read and write strategies, and the resync pass
480 * number for the mirror if values are specified in the request.
482 * Attaches the input list of submirrors to the devconfig.
484 static int
485 assemble_mirror(
486 devconfig_t *request,
487 dlist_t *subs,
488 devconfig_t **mirror)
490 dlist_t *iter = NULL;
491 char *name = NULL;
492 int error = 0;
494 if ((error = new_devconfig(mirror, TYPE_MIRROR)) == 0) {
495 /* set stripe name, use requested name if specified */
496 if ((error = devconfig_get_name(request, &name)) != 0) {
497 if (error != ERR_ATTR_UNSET) {
498 volume_set_error(gettext("error getting requested name\n"));
499 } else {
500 error = 0;
504 if (error == 0) {
505 if (name == NULL) {
506 if ((error = get_next_volume_name(&name,
507 TYPE_MIRROR)) == 0) {
508 error = devconfig_set_name(*mirror, name);
509 free(name);
510 /* get name for generating submirror names below */
511 error = devconfig_get_name(*mirror, &name);
513 } else {
514 error = devconfig_set_name(*mirror, name);
519 /* assign name to any unnamed submirror */
520 for (iter = subs;
521 (error == 0) && (iter != NULL);
522 iter = iter->next) {
524 devconfig_t *sub = (devconfig_t *)iter->obj;
525 char *subname = NULL;
527 error = devconfig_get_name(sub, &subname);
528 if ((error == ERR_ATTR_UNSET) || (subname == NULL) ||
529 (*subname == '\0')) {
530 ((error = get_next_submirror_name(name, &subname)) != 0) ||
531 (error = devconfig_set_name(sub, subname));
532 free(subname);
536 if (error == 0) {
537 mirror_read_strategy_t read = 0;
538 if ((error = get_mirror_read_strategy(request, &read)) == 0) {
539 error = devconfig_set_mirror_read(*mirror, read);
540 } else if (error == ERR_ATTR_UNSET) {
541 error = 0;
545 if (error == 0) {
546 mirror_write_strategy_t write = 0;
547 if ((error = get_mirror_write_strategy(request, &write)) == 0) {
548 error = devconfig_set_mirror_write(*mirror, write);
549 } else if (error == ERR_ATTR_UNSET) {
550 error = 0;
554 if (error == 0) {
555 uint16_t pass = 0;
556 if ((error = get_mirror_pass(request, &pass)) == 0) {
557 error = devconfig_set_mirror_pass(*mirror, pass);
558 } else if (error == ERR_ATTR_UNSET) {
559 error = 0;
563 /* arrange submirrors in ascending size order */
564 if (error == 0) {
565 dlist_t *sorted = NULL;
566 dlist_t *next = NULL;
568 iter = subs;
569 while (iter != NULL) {
571 next = iter->next;
572 iter->next = NULL;
573 iter->prev = NULL;
575 sorted = dlist_insert_ordered(iter,
576 sorted, ASCENDING, compare_devconfig_sizes);
578 iter = next;
580 subs = sorted;
583 if (error == 0) {
584 devconfig_set_components(*mirror, subs);
585 } else {
586 free_devconfig(*mirror);
587 *mirror = NULL;
590 return (error);
594 * FUNCTION: layout_stripe_submirrors(devconfig_t *request, dlist_t *cursubs,
595 * uint64_t nbytes, uint16_t nsubs, dlist_t **results)
597 * INPUT: request - pointer to a devconfig_t of the current request
598 * cursubs - pointer to a list of already composed submirrors
599 * these may affect disk and HBA choices for new
600 * submirrors being composed and are passed along
601 * into the component selection functions.
602 * nbytes - the desired capacity for the stripes
604 * OUPUT: results - pointer to a list of composed volumes
606 * RETURNS: int - 0 on success
607 * !0 otherwise.
609 * PURPOSE: Main layout driver for composing stripe submirrors.
611 * Attempts to construct nsub submirrors of size nbytes.
613 * Several different layout strategies are tried in order
614 * of preference until one succeeds or there are none left.
616 * 1 - mirror with all stripes on the MPXIO "controller"
617 * . requires MPXIO to be enabled
618 * . requires nsubs * mincomp available disks on the
619 * MPXIO HBA
621 * 2 - mirror with stripes within separate HBAs of same type
622 * . requires nsubs HBAs with mincomp disks
623 * . stripe width is driven by number of disks on HBA
625 * 3 - mirror with stripes across HBAs of same type
626 * . requires mincomp HBAs with nsubs disks
627 * (each stripe has a disk per HBA)
628 * . stripe width is driven by number of HBAs
630 * 4 - mirror with stripes within separate HBAs of mixed type
631 * . requires nsubs HBAs with mincomp disks
632 * . stripe width is driven by number of disks on HBA
634 * 5 - mirror with stripes across HBAs of mixed type
635 * . requires mincomp HBAs with nsubs disks
636 * (each stripe has a disk per HBA)
637 * . stripe width is driven by number of HBAs
639 * 6 - mirror with all stripes within the same HBA
640 * . requires an HBA with mincomp * nsubs disks
642 * get available HBAs
644 * group HBAs by characteristics
645 * for (each HBA grouping) and (nsub stripes not composed) {
646 * select next HBA group
647 * for (strategy[1,2,3]) and (nsub stripes not composed) {
648 * compose nsub stripes using HBAs in group
652 * if (nsub stripes not composed) {
653 * for (strategy[4,5,6]) and (nsub stripes not composed) {
654 * compose nsub stripes using all HBAs
658 * if (all stripes composed) {
659 * append composed stripes to results
663 static int
664 layout_stripe_submirrors(
665 devconfig_t *request,
666 dlist_t *cursubs,
667 uint64_t nbytes,
668 uint16_t nsubs,
669 dlist_t **results)
672 * these enums define the # of strategies and the preference order
673 * in which they are tried
675 typedef enum {
676 ALL_STRIPES_ON_MPXIO = 0,
677 STRIPE_PER_SIMILAR_HBA,
678 STRIPE_ACROSS_SIMILAR_HBAS,
679 N_SIMILAR_HBA_STRATEGIES
680 } similar_hba_strategy_order_t;
682 typedef enum {
683 STRIPE_PER_ANY_HBA = 0,
684 STRIPE_ACROSS_ANY_HBAS,
685 STRIPE_WITHIN_ANY_HBA,
686 N_ANY_HBA_STRATEGIES
687 } any_hba_strategy_order_t;
689 dlist_t *usable_hbas = NULL;
690 dlist_t *similar_hba_groups = NULL;
691 dlist_t *iter = NULL;
692 dlist_t *subs = NULL;
694 boolean_t usehsp = B_FALSE;
695 uint16_t mincomp = 0;
696 uint16_t maxcomp = 0;
698 int error = 0;
700 (error = get_usable_hbas(&usable_hbas));
701 if (error != 0) {
702 return (error);
705 print_layout_submirrors_msg(devconfig_type_to_str(TYPE_STRIPE),
706 nbytes, nsubs);
708 if (dlist_length(usable_hbas) == 0) {
709 print_no_hbas_msg();
710 volume_set_error(gettext("There are no usable HBAs."));
711 return (-1);
714 similar_hba_groups = NULL;
715 ((error = group_similar_hbas(usable_hbas, &similar_hba_groups)) != 0) ||
718 * determine the min/max number of stripe components
719 * based on the request, the diskset defaults or the
720 * global defaults. These are absolute limits, the
721 * actual values are determined by the number of HBAs
722 * and/or disks available.
724 (error = get_stripe_min_comp(request, &mincomp)) ||
725 (error = get_stripe_max_comp(request, &maxcomp)) ||
726 (error = get_volume_faultrecov(request, &usehsp));
727 if (error != 0) {
728 return (error);
731 for (iter = similar_hba_groups;
732 (error == 0) && (subs == NULL) && (iter != NULL);
733 iter = iter->next) {
735 dlist_t *hbas = (dlist_t *)iter->obj;
737 similar_hba_strategy_order_t order;
739 for (order = ALL_STRIPES_ON_MPXIO;
740 (order < N_SIMILAR_HBA_STRATEGIES) &&
741 (subs == NULL) && (error == 0);
742 order++) {
744 dlist_t *selhbas = NULL;
745 dlist_t *disks = NULL;
746 int n = 0;
748 switch (order) {
750 case ALL_STRIPES_ON_MPXIO:
752 if (is_mpxio_enabled() == B_TRUE) {
753 dlist_t *mpxio_hbas = NULL;
755 /* see if any HBA supports MPXIO */
756 error = select_mpxio_hbas(hbas, &mpxio_hbas);
757 if ((error == 0) && (mpxio_hbas != NULL)) {
759 /* BEGIN CSTYLED */
760 oprintf(OUTPUT_TERSE,
761 gettext(" -->Strategy 1: use %d-%d MPXIO disks\n"),
762 mincomp * nsubs, maxcomp * nsubs);
763 /* END CSTYLED */
765 /* see if MPXIO HBA has enough disks */
766 error = select_hbas_with_n_disks(
767 request, mpxio_hbas, (mincomp * nsubs),
768 &selhbas, &disks);
770 if ((error == 0) && (dlist_length(selhbas) > 0)) {
771 error = compose_stripes_within_hba(
772 request, cursubs, mpxio_hbas, nbytes,
773 nsubs, maxcomp, mincomp, &subs);
774 } else {
775 print_insufficient_hbas_msg(n);
779 dlist_free_items(mpxio_hbas, NULL);
782 break;
784 case STRIPE_PER_SIMILAR_HBA:
786 error = select_hbas_with_n_disks(
787 request, hbas, mincomp, &selhbas, &disks);
789 if (error == 0) {
791 /* BEGIN CSTYLED */
792 oprintf(OUTPUT_TERSE,
793 gettext(" -->Strategy 2: use %d-%d disks from %d similar HBAs - stripe per HBA\n"),
794 mincomp, maxcomp, nsubs);
795 /* END CSTYLED */
797 if ((n = dlist_length(selhbas)) >= nsubs) {
798 error = compose_stripe_per_hba(
799 request, cursubs, selhbas, nbytes,
800 nsubs, maxcomp, mincomp, &subs);
801 } else {
802 print_insufficient_hbas_msg(n);
806 break;
808 case STRIPE_ACROSS_SIMILAR_HBAS:
810 error = select_hbas_with_n_disks(
811 request, hbas, nsubs, &selhbas, &disks);
813 if (error == 0) {
815 /* BEGIN CSTYLED */
816 oprintf(OUTPUT_TERSE,
817 gettext(" -->Strategy 3: use %d disks from %d-%d similar HBAs - stripe across HBAs \n"),
818 nsubs, mincomp, maxcomp);
819 /* END CSTYLED */
821 if ((n = dlist_length(selhbas)) >= mincomp) {
822 error = compose_stripes_across_hbas(
823 request, cursubs, selhbas, disks,
824 nbytes, nsubs, maxcomp, mincomp, &subs);
825 } else {
826 print_insufficient_hbas_msg(n);
830 break;
832 default:
833 break;
836 dlist_free_items(selhbas, NULL);
837 dlist_free_items(disks, NULL);
841 for (iter = similar_hba_groups; iter != NULL; iter = iter->next) {
842 dlist_free_items((dlist_t *)iter->obj, NULL);
844 dlist_free_items(similar_hba_groups, NULL);
846 /* retry using all available HBAs */
847 if (subs == NULL) {
849 any_hba_strategy_order_t order;
851 for (order = STRIPE_PER_ANY_HBA;
852 (order < N_ANY_HBA_STRATEGIES) &&
853 (subs == NULL) && (error == 0);
854 order++) {
856 dlist_t *selhbas = NULL;
857 dlist_t *disks = NULL;
858 int n = 0;
860 switch (order) {
862 case STRIPE_PER_ANY_HBA:
864 error = select_hbas_with_n_disks(
865 request, usable_hbas, nsubs, &selhbas, &disks);
867 if (error == 0) {
869 /* BEGIN CSTYLED */
870 oprintf(OUTPUT_TERSE,
871 gettext(" -->Strategy 4: use %d-%d disks from any %d HBAs - stripe per HBA\n"),
872 mincomp, maxcomp, nsubs);
873 /* END CSTYLED */
875 if ((n = dlist_length(selhbas)) >= nsubs) {
876 error = compose_stripe_per_hba(
877 request, cursubs, selhbas, nbytes,
878 nsubs, maxcomp, mincomp, &subs);
879 } else {
880 print_insufficient_hbas_msg(n);
884 break;
886 case STRIPE_ACROSS_ANY_HBAS:
888 error = select_hbas_with_n_disks(
889 request, usable_hbas, nsubs, &selhbas, &disks);
891 if (error == 0) {
893 /* BEGIN CSTYLED */
894 oprintf(OUTPUT_TERSE,
895 gettext(" -->Strategy 5: use %d disks from %d-%d HBAs - stripe across HBAs \n"),
896 nsubs, mincomp, maxcomp);
897 /* END CSTYLED */
899 if ((n = dlist_length(selhbas)) >= mincomp) {
900 error = compose_stripes_across_hbas(
901 request, cursubs, selhbas, disks,
902 nbytes, nsubs, maxcomp, mincomp, &subs);
903 } else {
904 print_insufficient_hbas_msg(n);
908 break;
910 case STRIPE_WITHIN_ANY_HBA:
912 error = select_hbas_with_n_disks(
913 request, usable_hbas, (mincomp * nsubs),
914 &selhbas, &disks);
916 if (error == 0) {
918 /* BEGIN CSTYLED */
919 oprintf(OUTPUT_TERSE,
920 gettext(" -->Strategy 6: use %d-%d disks from any single HBA - %d stripes within HBA\n"),
921 mincomp * nsubs, maxcomp * nsubs, nsubs);
922 /* END CSTYLED */
923 if ((n = dlist_length(selhbas)) > 0) {
924 error = compose_stripes_within_hba(
925 request, cursubs, selhbas, nbytes,
926 nsubs, maxcomp, mincomp, &subs);
927 } else {
928 print_insufficient_hbas_msg(n);
932 break;
934 default:
935 break;
938 dlist_free_items(selhbas, NULL);
939 dlist_free_items(disks, NULL);
943 if (error == 0) {
944 *results = dlist_append(subs, *results, AT_TAIL);
946 return (error);
950 * FUNCTION: layout_concat_submirrors(devconfig_t *request, dlist_t *cursubs,
951 * uint64_t nbytes, uint16_t nsubs, dlist_t **results)
953 * INPUT: request - pointer to a devconfig_t of the current request
954 * cursubs - pointer to a list of already composed submirrors
955 * nbytes - the desired capacity for the concats
957 * OUPUT: results - pointer to a list of composed volumes
959 * RETURNS: int - 0 on success
960 * !0 otherwise.
962 * PURPOSE: Main layout driver for composing concat submirrors.
964 * Attempts to construct nsub submirrors of size nbytes.
966 * Several different layout strategies are tried in order
967 * of preference until one succeeds or there are none left.
969 * 1 - mirror with all concats on the MPXIO "controller"
970 * . requires MPXIO to be enabled
971 * . requires nsubs available disks on the MPXIO HBA
973 * 2 - mirror with concats on separate HBAs of same type
974 * . requires nsubs HBAs with available disks
976 * 3 - mirror with concats across HBAs of same type
977 * . requires an HBA with at least 1 available disk
979 * 4 - mirror with concats on separate HBAs of mixed type
980 * . requires nsubs HBAs with available disks
982 * 5 - mirror with concats across HBAs of mixed type
983 * . requires an HBA with at least 1 available disk
985 * 6 - mirror with all concats on the same HBA
986 * . requires an HBA with at least nsubs available disks
988 * get available HBAs
990 * group HBAs by characteristics
991 * for (each HBA grouping) and (nsub concats not composed) {
992 * select next HBA group
993 * for (strategy[1,2,3]) and (nsub concats not composed) {
994 * compose nsub concats, nbytes in size
998 * if (nsub concats not composed) {
999 * for (strategy[4,5,6]) and (nsub concats not composed) {
1000 * compose nsub concats, nbytes in size
1004 * if (all concats composed) {
1005 * append composed concats to results
1009 static int
1010 layout_concat_submirrors(
1011 devconfig_t *request,
1012 dlist_t *cursubs,
1013 uint64_t nbytes,
1014 uint16_t nsubs,
1015 dlist_t **results)
1018 * these enums define the # of strategies and the preference order
1019 * in which they are tried
1021 typedef enum {
1022 ALL_CONCATS_ON_MPXIO = 0,
1023 CONCAT_PER_SIMILAR_HBA,
1024 CONCAT_ACROSS_SIMILAR_HBAS,
1025 N_SIMILAR_HBA_STRATEGIES
1026 } similar_hba_strategy_order_t;
1028 typedef enum {
1029 CONCAT_PER_ANY_HBA = 0,
1030 CONCAT_ACROSS_ANY_HBAS,
1031 CONCAT_WITHIN_ANY_HBA,
1032 N_ANY_HBA_STRATEGIES
1033 } any_hba_strategy_order_t;
1035 dlist_t *usable_hbas = NULL;
1036 dlist_t *similar_hba_groups = NULL;
1037 dlist_t *iter = NULL;
1038 dlist_t *subs = NULL;
1040 boolean_t usehsp = B_FALSE;
1042 int error = 0;
1044 (error = get_usable_hbas(&usable_hbas));
1045 if (error != 0) {
1046 return (error);
1049 print_layout_submirrors_msg(devconfig_type_to_str(TYPE_CONCAT),
1050 nbytes, nsubs);
1052 if (dlist_length(usable_hbas) == 0) {
1053 print_no_hbas_msg();
1054 volume_set_error(gettext("There are no usable HBAs."));
1055 return (-1);
1058 similar_hba_groups = NULL;
1059 ((error = group_similar_hbas(usable_hbas, &similar_hba_groups)) != 0) ||
1060 (error = get_volume_faultrecov(request, &usehsp));
1061 if (error != 0) {
1062 return (error);
1065 for (iter = similar_hba_groups;
1066 (error == 0) && (subs == NULL) && (iter != NULL);
1067 iter = iter->next) {
1069 dlist_t *hbas = (dlist_t *)iter->obj;
1071 similar_hba_strategy_order_t order;
1073 for (order = ALL_CONCATS_ON_MPXIO;
1074 (order < N_SIMILAR_HBA_STRATEGIES) &&
1075 (subs == NULL) && (error == 0);
1076 order++) {
1078 dlist_t *selhbas = NULL;
1079 dlist_t *disks = NULL;
1080 int n = 0;
1082 switch (order) {
1084 case ALL_CONCATS_ON_MPXIO:
1086 if (is_mpxio_enabled() == B_TRUE) {
1087 dlist_t *mpxio_hbas = NULL;
1089 /* see if any HBA supports MPXIO */
1090 error = select_mpxio_hbas(hbas, &mpxio_hbas);
1091 if ((error == 0) && (mpxio_hbas != NULL)) {
1093 /* BEGIN CSTYLED */
1094 oprintf(OUTPUT_TERSE,
1095 gettext(" -->Strategy 1: use at least %d MPXIO disks\n"),
1096 nsubs);
1097 /* END CSTYLED */
1099 /* see if MPXIO HBA has enough disks */
1100 error = select_hbas_with_n_disks(
1101 request, hbas, nsubs, &selhbas, &disks);
1103 if ((error == 0) &&
1104 ((n = dlist_length(selhbas)) > 0)) {
1105 error = compose_concats_within_hba(
1106 request, cursubs, mpxio_hbas, nbytes,
1107 nsubs, &subs);
1108 } else {
1109 print_insufficient_hbas_msg(n);
1113 dlist_free_items(mpxio_hbas, NULL);
1116 break;
1118 case CONCAT_PER_SIMILAR_HBA:
1120 error = select_hbas_with_n_disks(
1121 request, hbas, 1, &selhbas, &disks);
1123 if (error == 0) {
1125 /* BEGIN CSTYLED */
1126 oprintf(OUTPUT_TERSE,
1127 gettext(" -->Strategy 2: use any disks from %d similar HBAs - concat per HBA\n"),
1128 nsubs);
1129 /* END CSTYLED */
1131 if ((n = dlist_length(selhbas)) >= nsubs) {
1132 error = compose_concat_per_hba(
1133 request, cursubs, selhbas,
1134 nbytes, nsubs, &subs);
1135 } else {
1136 print_insufficient_hbas_msg(n);
1140 break;
1142 case CONCAT_ACROSS_SIMILAR_HBAS:
1144 error = select_hbas_with_n_disks(
1145 request, hbas, 1, &selhbas, &disks);
1147 if (error == 0) {
1149 /* BEGIN CSTYLED */
1150 oprintf(OUTPUT_TERSE,
1151 gettext(" -->Strategy 3: use any disks from any similar HBAs - "
1152 "%d concats across HBAs\n"),
1153 nsubs);
1154 /* END CSTYLED */
1155 error = compose_concats_across_hbas(
1156 request, cursubs, selhbas, disks,
1157 nbytes, nsubs, &subs);
1160 break;
1162 default:
1163 break;
1166 dlist_free_items(selhbas, NULL);
1167 dlist_free_items(disks, NULL);
1171 for (iter = similar_hba_groups; iter != NULL; iter = iter->next) {
1172 dlist_free_items((dlist_t *)iter->obj, NULL);
1174 dlist_free_items(similar_hba_groups, NULL);
1176 /* retry using all available HBAs */
1177 if (subs == NULL) {
1179 any_hba_strategy_order_t order;
1181 for (order = CONCAT_PER_ANY_HBA;
1182 (order < N_ANY_HBA_STRATEGIES) &&
1183 (subs == NULL) && (error == 0);
1184 order++) {
1186 dlist_t *selhbas = NULL;
1187 dlist_t *disks = NULL;
1188 int n = 0;
1190 switch (order) {
1192 case CONCAT_PER_ANY_HBA:
1194 error = select_hbas_with_n_disks(
1195 request, usable_hbas, 1, &selhbas, &disks);
1197 if (error == 0) {
1199 /* BEGIN CSTYLED */
1200 oprintf(OUTPUT_TERSE,
1201 gettext(" -->Strategy 4: use any disks from %d HBAs - concat per HBA\n"),
1202 nsubs);
1203 /* END CSTYLED */
1204 if ((n = dlist_length(selhbas)) >= nsubs) {
1205 error = compose_concat_per_hba(
1206 request, cursubs, selhbas,
1207 nbytes, nsubs, &subs);
1208 } else {
1209 print_insufficient_hbas_msg(n);
1212 break;
1214 case CONCAT_ACROSS_ANY_HBAS:
1216 error = select_hbas_with_n_disks(
1217 request, usable_hbas, 1, &selhbas, &disks);
1219 if (error == 0) {
1221 /* BEGIN CSTYLED */
1222 oprintf(OUTPUT_TERSE,
1223 gettext(" -->Strategy 5: use any disks from any HBA - %d concats across HBAs\n"),
1224 nsubs);
1225 /* END CSTYLED */
1226 error = compose_concats_across_hbas(
1227 request, cursubs, selhbas, disks,
1228 nbytes, nsubs, &subs);
1231 break;
1233 case CONCAT_WITHIN_ANY_HBA:
1235 error = select_hbas_with_n_disks(
1236 request, usable_hbas, 1, &selhbas, &disks);
1238 if (error == 0) {
1240 /* BEGIN CSTYLED */
1241 oprintf(OUTPUT_TERSE,
1242 gettext(" -->Strategy 6: use any disks from any single HBA - %d concats within an HBA\n"),
1243 nsubs);
1244 /* END CSTYLED */
1246 if ((n = dlist_length(selhbas)) > 0) {
1247 error = compose_concats_within_hba(
1248 request, cursubs, selhbas,
1249 nbytes, nsubs, &subs);
1250 } else {
1251 print_insufficient_hbas_msg(n);
1255 break;
1257 default:
1258 break;
1261 dlist_free_items(selhbas, NULL);
1262 dlist_free_items(disks, NULL);
1266 if (error == 0) {
1267 *results = dlist_append(subs, *results, AT_TAIL);
1270 return (error);
1274 * FUNCTION: compose_stripe_per_hba(devconfig_t *request,
1275 * dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
1276 * uint16_t nsubs, int maxcomp, int mincomp,
1277 * dlist_t **results)
1279 * INPUT: request - pointer to a devconfig_t of the current request
1280 * cursubs - pointer to a list of already composed submirrors
1281 * hbas - pointer to a list of available HBAs
1282 * nbytes - the desired capacity for the stripes
1283 * nsubs - the desired number of stripes
1284 * maxcomp - the maximum number of stripe components
1285 * mincomp - the minimum number of stripe components
1287 * OUPUT: results - pointer to a list of composed volumes
1289 * RETURNS: int - 0 on success
1290 * !0 otherwise.
1292 * PURPOSE: Layout function which composes the requested number of stripes
1293 * of the desired size using available disks on any of the HBAs
1294 * from the input list.
1296 * The number of components within the composed stripes will be
1297 * in the range of mincomp to ncomp, preferring more components
1298 * over fewer. All stripes composed by a single call to this
1299 * function will have the same number of components.
1301 * Each stripe will use disks from a single HBA.
1303 * All input HBAs are expected to have at least mincomp available
1304 * disks.
1306 * If the stripes can be composed, they are appended to the list
1307 * of result volumes.
1309 * while (more HBAs and more stripes to compose) {
1310 * select next HBA
1311 * get available space for this HBA
1312 * get available disks for this HBA
1313 * if (not enough space or disks) {
1314 * continue
1317 * use # disks as # of stripe components - limit to maxcomp
1318 * for ((ncomps downto mincomp) && (more stripes to compose)) {
1319 * while (more stripes to compose) {
1320 * if a stripe can be composed using disks {
1321 * save stripe
1322 * increment stripe count
1324 * while (more HBAs and more stripes to compose) {
1325 * select next HBA
1326 * get available space for this HBA
1327 * get available disks for this HBA
1328 * if (not enough space or disks) {
1329 * continue
1331 * if a stripe can be composed using disks {
1332 * save stripe
1333 * increment stripe count
1337 * if (not all stripes composed) {
1338 * delete any compose stripes
1343 * if (not all stripes composed) {
1344 * delete any stripes composed
1348 * if (not all stripes composed) {
1349 * delete any stripes composed
1352 * append composed stripes to results
1354 static int
1355 compose_stripe_per_hba(
1356 devconfig_t *request,
1357 dlist_t *cursubs,
1358 dlist_t *hbas,
1359 uint64_t nbytes,
1360 uint16_t nsubs,
1361 uint16_t maxcomp,
1362 uint16_t mincomp,
1363 dlist_t **results)
1365 int error = 0;
1366 dlist_t *list = NULL;
1367 dlist_t *iter = NULL;
1369 oprintf(OUTPUT_VERBOSE,
1370 gettext(" --->Trying to compose %d Stripes with "
1371 "%d-%d components on separate HBAs.\n"),
1372 nsubs, mincomp, maxcomp);
1374 for (iter = hbas;
1375 (list == NULL) && (iter != NULL) && (error == 0);
1376 iter = iter->next) {
1378 dm_descriptor_t hba = (uintptr_t)iter->obj;
1379 dlist_t *disks = NULL;
1380 uint64_t space = 0;
1381 int ncomp = 0;
1382 char *name;
1384 ((error = get_display_name(hba, &name)) != 0) ||
1385 (error = hba_get_avail_disks_and_space(request,
1386 hba, &disks, &space));
1387 if (error != 0) {
1388 continue;
1391 /* check for sufficient space and minimum # of disks */
1392 if (space < nbytes) {
1393 (void) print_hba_insufficient_space_msg(name, space);
1394 dlist_free_items(disks, NULL);
1395 continue;
1398 if ((ncomp = dlist_length(disks)) < mincomp) {
1399 print_insufficient_disks_msg(ncomp);
1400 dlist_free_items(disks, NULL);
1401 continue;
1404 /* make the stripe as wide as possible, up to maxcomp */
1405 for (ncomp = ((ncomp > maxcomp) ? maxcomp : ncomp);
1406 (list == NULL) && (ncomp >= mincomp) && (error == 0);
1407 ncomp--) {
1409 int count = 0;
1411 /* try composing nsubs stripes with ncomp components */
1412 while (count < nsubs) {
1414 devconfig_t *stripe = NULL;
1415 dlist_t *item = NULL;
1416 dlist_t *iter1 = NULL;
1418 /* build first stripe using disks on this HBA */
1419 if (((error = populate_stripe(request, nbytes,
1420 disks, ncomp, cursubs, &stripe)) != 0) ||
1421 (stripe == NULL)) {
1422 /* first stripe failed at the current width */
1423 /* break while loop and try a different width */
1424 break;
1427 /* composed a stripe */
1428 if ((item = dlist_new_item((void*)stripe)) == NULL) {
1429 error = ENOMEM;
1430 break;
1432 ++count;
1433 list = dlist_append(item, list, AT_TAIL);
1435 /* compose stripes on remaining HBAs */
1436 for (iter1 = iter->next;
1437 (count < nsubs) && (iter1 != NULL) && (error == 0);
1438 iter1 = iter1->next) {
1440 dm_descriptor_t hba1 = (uintptr_t)iter1->obj;
1441 uint64_t space1 = 0;
1442 dlist_t *disks1 = NULL;
1444 error = hba_get_avail_disks_and_space(request,
1445 hba1, &disks1, &space1);
1446 if (error != 0) {
1447 continue;
1450 /* enough space/disks on this HBA? */
1451 if ((dlist_length(disks1) < ncomp) ||
1452 (space1 < nbytes)) {
1453 dlist_free_items(disks1, NULL);
1454 continue;
1457 stripe = NULL;
1458 error = populate_stripe(
1459 request, nbytes, disks1,
1460 ncomp, cursubs, &stripe);
1462 if (stripe != NULL) {
1463 /* prepare to compose another */
1464 if ((item = dlist_new_item(
1465 (void *)stripe)) == NULL) {
1466 error = ENOMEM;
1467 break;
1469 list = dlist_append(item, list, AT_TAIL);
1470 ++count;
1473 dlist_free_items(disks1, NULL);
1474 disks1 = NULL;
1477 if ((iter1 == NULL) && (count < nsubs)) {
1479 * no HBAs remain and haven't composed
1480 * enough stripes at the current width.
1481 * break while loop and try another width.
1483 break;
1487 if (count < nsubs) {
1489 * stripe composition at current width failed...
1490 * prepare to try a narrower width.
1491 * NB: narrower widths may work since some HBA(s)
1492 * may have fewer available disks
1494 print_layout_submirrors_failed_msg(
1495 devconfig_type_to_str(TYPE_STRIPE),
1496 count, nsubs);
1498 dlist_free_items(list, free_devconfig_object);
1499 list = NULL;
1503 dlist_free_items(disks, NULL);
1504 disks = NULL;
1507 if (error == 0) {
1508 *results = dlist_append(list, *results, AT_TAIL);
1509 } else {
1510 dlist_free_items(list, free_devconfig_object);
1513 return (error);
1517 * FUNCTION: compose_stripes_across_hbas(devconfig_t *request,
1518 * dlist_t *cursubs, dlist_t *hbas, dlist_t *disks,
1519 * uint64_t nbytes, uint16_t nsubs, int maxcomp,
1520 * int mincomp, dlist_t **results)
1522 * INPUT: request - pointer to a devconfig_t of the current request
1523 * cursubs - pointer to a list of already composed submirrors
1524 * hbas - pointer to a list of available HBAs
1525 * disks - pointer to a list of available disks on the HBAs
1526 * nbytes - the desired capacity for the stripes
1527 * nsubs - the desired number of stripes
1528 * ncomp - the maximum number of stripe components
1529 * mincomp - the minimum number of stripe components
1531 * OUPUT: results - pointer to a list of composed volumes
1533 * RETURNS: int - 0 on success
1534 * !0 otherwise.
1536 * PURPOSE: Layout function which composes the requested number of stripes
1537 * of the desired size using available disks on any of the HBAs
1538 * from the input list.
1540 * The number of components within the composed stripes will be
1541 * in the range of mincomp to ncomp, preferring more components
1542 * over fewer. All stripes composed by a single call to this
1543 * function will have the same number of components.
1545 * Each stripe will use a disk from several different HBAs.
1547 * All input HBAs are expected to have at least nsubs available
1548 * disks.
1550 * If the stripes can be composed, they are appended to the list
1551 * of result volumes.
1553 * for (ncomps downto mincomp) {
1555 * copy the input disk list
1556 * while (more stripes to compose) {
1557 * if a stripe can be composed using disks {
1558 * save stripe
1559 * remove used disks from disk list
1560 * increment stripe count
1561 * } else
1562 * end while loop
1565 * free copied disk list
1566 * if (not all stripes composed) {
1567 * delete any stripes composed
1568 * decrement ncomps
1572 * if (not all stripes composed) {
1573 * delete any stripes composed
1576 * append composed stripes to results
1578 static int
1579 compose_stripes_across_hbas(
1580 devconfig_t *request,
1581 dlist_t *cursubs,
1582 dlist_t *hbas,
1583 dlist_t *disks,
1584 uint64_t nbytes,
1585 uint16_t nsubs,
1586 uint16_t ncomp,
1587 uint16_t mincomp,
1588 dlist_t **results)
1590 int error = 0;
1591 int count = 0;
1593 dlist_t *list = NULL;
1595 while ((ncomp >= mincomp) && (count < nsubs) && (error == 0)) {
1597 dlist_t *iter;
1598 dlist_t *item;
1599 dlist_t *disks_copy = NULL;
1601 oprintf(OUTPUT_VERBOSE,
1602 gettext(" --->Trying to compose %d Stripes with "
1603 "%d components across %d HBAs.\n"),
1604 nsubs, ncomp, dlist_length(hbas));
1606 /* copy disk list, it is modified by the while loop */
1607 for (iter = disks; iter != NULL; iter = iter->next) {
1608 if ((item = dlist_new_item(iter->obj)) == NULL) {
1609 error = ENOMEM;
1610 } else {
1611 disks_copy = dlist_append(item, disks_copy, AT_HEAD);
1615 /* compose nsubs stripe submirrors of ncomp components */
1616 while ((count < nsubs) && (error == 0)) {
1618 devconfig_t *stripe = NULL;
1619 dlist_t *item = NULL;
1621 error = populate_stripe(
1622 request, nbytes, disks_copy, ncomp, cursubs, &stripe);
1624 if ((error == 0) && (stripe != NULL)) {
1625 if ((item = dlist_new_item((void *)stripe)) == NULL) {
1626 error = ENOMEM;
1627 } else {
1628 ++count;
1629 list = dlist_append(item, list, AT_TAIL);
1630 error = remove_used_disks(&disks_copy, stripe);
1632 } else if (stripe == NULL) {
1633 break;
1637 /* free copy of disk list */
1638 dlist_free_items(disks_copy, NULL);
1639 disks_copy = NULL;
1641 if ((error == 0) && (count < nsubs)) {
1642 /* failed to compose enough stripes at this width, */
1643 /* prepare to try again with the next narrower width. */
1644 print_layout_submirrors_failed_msg(
1645 devconfig_type_to_str(TYPE_STRIPE),
1646 count, nsubs);
1648 dlist_free_items(list, free_devconfig_object);
1649 list = NULL;
1650 count = 0;
1651 --ncomp;
1655 if (count < nsubs) {
1656 dlist_free_items(list, free_devconfig_object);
1657 list = NULL;
1658 } else {
1659 *results = dlist_append(list, *results, AT_TAIL);
1662 return (error);
1666 * FUNCTION: compose_stripes_within_hba(devconfig_t *request,
1667 * dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
1668 * uint16_t nsubs, int maxcomp, int mincomp,
1669 * dlist_t **results)
1671 * INPUT: request - pointer to a devconfig_t of the current request
1672 * cursubs - pointer to a list of already composed submirrors
1673 * hbas - pointer to a list of available HBAs
1674 * nbytes - the desired capacity for the stripes
1675 * nsubs - the desired number of stripes
1676 * maxcomp - the maximum number of stripe components
1677 * mincomp - the minimum number of stripe components
1678 * nsubs - the number of stripes to be composed
1680 * OUPUT: results - pointer to a list of composed volumes
1682 * RETURNS: int - 0 on success
1683 * !0 otherwise.
1685 * PURPOSE: Layout function which composes the requested number of stripes
1686 * of the desired size using available disks within any single
1687 * HBA from the input list.
1689 * The number of components within the composed stripes will be
1690 * in the range of mincomp to maxcomp, preferring more components
1691 * over fewer. All stripes composed by a single call to this
1692 * function will have the same number of components.
1694 * All stripes will use disks from a single HBA.
1696 * All input HBAs are expected to have at least nsubs * mincomp
1697 * available disks and total space sufficient for subs stripes.
1699 * If the stripes can be composed, they are appended to the list
1700 * of result volumes.
1702 * while (more HBAs and more stripes need to be composed) {
1703 * select next HBA
1704 * if (not enough available space on this HBA) {
1705 * continue;
1707 * get available disks for HBA
1708 * use # disks as # of stripe components - limit to maxcomp
1709 * for (ncomps downto mincomp) {
1710 * if ((ncomps * nsubs) > ndisks) {
1711 * continue;
1713 * while (more stripes need to be composed) {
1714 * if a stripe can be composed using disks {
1715 * save stripe
1716 * remove used disks from disk list
1717 * } else
1718 * end while loop
1720 * if (not all stripes composed) {
1721 * delete any stripes composed
1726 * if (not all stripes composed) {
1727 * delete any stripes composed
1730 * append composed stripes to results
1732 static int
1733 compose_stripes_within_hba(
1734 devconfig_t *request,
1735 dlist_t *cursubs,
1736 dlist_t *hbas,
1737 uint64_t nbytes,
1738 uint16_t nsubs,
1739 uint16_t maxcomp,
1740 uint16_t mincomp,
1741 dlist_t **results)
1743 int error = 0;
1744 int count = 0;
1746 dlist_t *list = NULL;
1747 dlist_t *iter = NULL;
1749 for (iter = hbas;
1750 (count < nsubs) && (iter != NULL) && (error == 0);
1751 iter = iter->next) {
1753 dm_descriptor_t hba = (uintptr_t)iter->obj;
1754 uint64_t space = 0;
1755 dlist_t *disks = NULL;
1756 int ndisks = 0;
1757 int ncomp = 0;
1758 char *name = NULL;
1760 ((error = get_display_name(hba, &name)) != 0) ||
1761 (error = hba_get_avail_disks_and_space(request,
1762 hba, &disks, &space));
1763 if (error != 0) {
1764 dlist_free_items(disks, NULL);
1765 continue;
1768 if (space < (nsubs * nbytes)) {
1769 (void) print_hba_insufficient_space_msg(name, space);
1770 dlist_free_items(disks, NULL);
1771 continue;
1774 ndisks = dlist_length(disks);
1777 * try composing stripes from ncomp down to mincomp.
1778 * stop when nsubs stripes have been composed, or when the
1779 * minimum stripe width has been tried
1781 for (ncomp = maxcomp;
1782 (ncomp >= mincomp) && (count != nsubs) && (error == 0);
1783 ncomp--) {
1785 oprintf(OUTPUT_VERBOSE,
1786 gettext(" --->Trying to compose %d Stripes with "
1787 "%d components on a single HBA.\n"),
1788 nsubs, ncomp);
1790 if (ndisks < (ncomp * nsubs)) {
1791 print_insufficient_disks_msg(ndisks);
1792 continue;
1795 /* try composing nsubs stripes, each ncomp wide */
1796 for (count = 0; (count < nsubs) && (error == 0); count++) {
1798 devconfig_t *stripe = NULL;
1800 error = populate_stripe(
1801 request, nbytes, disks, ncomp, cursubs, &stripe);
1803 if ((error == 0) && (stripe != NULL)) {
1805 dlist_t *item = dlist_new_item((void *)stripe);
1806 if (item == NULL) {
1807 error = ENOMEM;
1808 } else {
1809 list = dlist_append(item, list, AT_TAIL);
1810 error = remove_used_disks(&disks, stripe);
1812 } else if (stripe == NULL) {
1813 break;
1817 if (count < nsubs) {
1818 /* failed to compose enough stripes at this width, */
1819 /* prepare to try again with fewer components */
1820 print_layout_submirrors_failed_msg(
1821 devconfig_type_to_str(TYPE_STRIPE),
1822 count, nsubs);
1824 dlist_free_items(list, free_devconfig_object);
1825 list = NULL;
1829 dlist_free_items(disks, NULL);
1832 if (count < nsubs) {
1833 dlist_free_items(list, free_devconfig_object);
1834 list = NULL;
1837 *results = list;
1839 return (error);
1843 * FUNCTION: compose_concats_per_hba(devconfig_t *request,
1844 * dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
1845 * uint16_t nsubs, dlist_t **results)
1847 * INPUT: request - pointer to a devconfig_t of the current request
1848 * cursubs - pointer to a list of already composed submirrors
1849 * hbas - pointer to a list of available HBAs
1850 * nbytes - the desired capacity for the concats
1851 * nsubs - the number of concats to be composed
1853 * OUPUT: results - pointer to a list of composed volumes
1855 * RETURNS: int - 0 on success
1856 * !0 otherwise.
1858 * PURPOSE: Layout function which composes the requested number of concats
1859 * of the desired size using available disks within HBAs from the
1860 * input list. Each concat will be composed using disks from a
1861 * single HBA.
1863 * If the concats can be composed, they are appended to the list
1864 * of result volumes.
1866 * while (more HBAs AND more concats need to be composed) {
1867 * if (not enough available space on this HBA) {
1868 * continue;
1871 * get available disks for HBA
1872 * if (concat can be composed) {
1873 * save concat
1874 * increment count
1878 * if (not all stripes composed) {
1879 * delete any concats composed
1882 * append composed concats to results
1884 static int
1885 compose_concat_per_hba(
1886 devconfig_t *request,
1887 dlist_t *cursubs,
1888 dlist_t *hbas,
1889 uint64_t nbytes,
1890 uint16_t nsubs,
1891 dlist_t **results)
1893 int error = 0;
1894 int count = 0;
1896 dlist_t *list = NULL;
1897 dlist_t *iter = NULL;
1899 oprintf(OUTPUT_VERBOSE,
1900 gettext(" --->Trying to compose %d Concats on "
1901 "separate HBAs.\n"), nsubs);
1903 for (iter = hbas;
1904 (iter != NULL) && (error == 0) && (count < nsubs);
1905 iter = iter->next) {
1907 dm_descriptor_t hba = (uintptr_t)iter->obj;
1908 uint64_t space = 0;
1909 devconfig_t *concat = NULL;
1910 dlist_t *disks = NULL;
1912 error = hba_get_avail_disks_and_space(request, hba, &disks, &space);
1913 if ((error == 0) && (space >= nbytes)) {
1914 error = populate_concat(
1915 request, nbytes, disks, cursubs, &concat);
1918 if ((error == 0) && (concat != NULL)) {
1919 dlist_t *item = dlist_new_item((void *)concat);
1920 if (item == NULL) {
1921 error = ENOMEM;
1922 } else {
1923 ++count;
1924 list = dlist_append(item, list, AT_TAIL);
1928 dlist_free_items(disks, NULL);
1931 if (count != nsubs) {
1932 print_layout_submirrors_failed_msg(
1933 devconfig_type_to_str(TYPE_CONCAT),
1934 count, nsubs);
1936 dlist_free_items(list, free_devconfig_object);
1937 list = NULL;
1938 } else {
1939 *results = dlist_append(list, *results, AT_TAIL);
1942 return (error);
1946 * FUNCTION: compose_concats_across_hbas(devconfig_t *request,
1947 * dlist_t *cursubs, dlist_t *hbas, dlist_t *disks,
1948 * uint64_t nbytes, uint16_t nsubs, dlist_t **results)
1950 * INPUT: request - pointer to a devconfig_t of the current request
1951 * cursubs - pointer to a list of already composed submirrors
1952 * hbas - pointer to a list of available HBAs
1953 * disks - pointer to a list of available disks on the HBAs
1954 * nbytes - the desired capacity for the concats
1955 * nsubs - the number of concats to be composed
1957 * OUPUT: results - pointer to a list of composed volumes
1959 * RETURNS: int - 0 on success
1960 * !0 otherwise.
1962 * PURPOSE: Layout function which composes the requested number of concats
1963 * of the desired size using any available disks from the input
1964 * list of available HBAs.
1966 * If the concats can be composed, they are appended to the list
1967 * of result volumes.
1969 * copy the input disk list
1970 * while (more concats need to be composed) {
1971 * if (a concat can be composed using remaining disks) {
1972 * save concat
1973 * remove used disks from disk list
1974 * increment count
1975 * } else {
1976 * end while loop
1980 * if (not all concats composed) {
1981 * delete any concats composed
1984 * append composed concats to results
1986 static int
1987 compose_concats_across_hbas(
1988 devconfig_t *request,
1989 dlist_t *cursubs,
1990 dlist_t *hbas,
1991 dlist_t *disks,
1992 uint64_t nbytes,
1993 uint16_t nsubs,
1994 dlist_t **results)
1996 int error = 0;
1997 int count = 0;
1999 dlist_t *list = NULL;
2000 dlist_t *item = NULL;
2001 dlist_t *iter = NULL;
2002 dlist_t *disks_copy = NULL;
2004 /* copy disk list, it is modified by the while loop */
2005 for (iter = disks; iter != NULL; iter = iter->next) {
2006 if ((item = dlist_new_item(iter->obj)) == NULL) {
2007 error = ENOMEM;
2008 } else {
2009 disks_copy = dlist_append(item, disks_copy, AT_HEAD);
2013 while ((count < nsubs) && (error == 0)) {
2015 devconfig_t *concat = NULL;
2017 error = populate_concat(
2018 request, nbytes, disks_copy, cursubs, &concat);
2020 if ((error == 0) && (concat != NULL)) {
2022 item = dlist_new_item((void *)concat);
2023 if (item == NULL) {
2024 error = ENOMEM;
2025 } else {
2026 count++;
2027 list = dlist_append(item, list, AT_TAIL);
2028 error = remove_used_disks(&disks_copy, concat);
2030 } else if (concat == NULL) {
2031 break;
2035 /* free copy of disk list */
2036 dlist_free_items(disks_copy, NULL);
2037 disks_copy = NULL;
2039 if (count != nsubs) {
2040 print_layout_submirrors_failed_msg(
2041 devconfig_type_to_str(TYPE_CONCAT),
2042 count, nsubs);
2044 dlist_free_items(list, free_devconfig_object);
2045 list = NULL;
2046 } else {
2047 *results = dlist_append(list, *results, AT_TAIL);
2050 return (error);
2054 * FUNCTION: compose_concats_within_hba(devconfig_t *request,
2055 * dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
2056 * uint16_t nsubs, dlist_t **results)
2058 * INPUT: request - pointer to a devconfig_t of the current request
2059 * cursubs - pointer to a list of already composed submirrors
2060 * hbas - pointer to a list of available HBAs
2061 * nbytes - the desired capacity for the concats
2062 * nsubs - the number of concats to be composed
2064 * OUPUT: results - pointer to a list of composed volumes
2066 * RETURNS: int - 0 on success
2067 * !0 otherwise.
2069 * PURPOSE: Layout function which composes the requested number of concats
2070 * of the desired size using available disks within any single
2071 * HBA from the input list.
2074 * HBAs in the list are expected to have at least 2 available
2075 * disks and total space sufficient for the submirrors.
2077 * If the concats can be composed, they are appended to the list
2078 * of result volumes.
2080 * while (more HBAs) {
2081 * if (not enough available space on this HBA) {
2082 * continue;
2085 * get available disks for HBA
2086 * while (more concats need to be composed) {
2087 * if a concat can be composed using disks {
2088 * save concat
2089 * remove used disks from disk list
2090 * increment count
2091 * } else {
2092 * delete any concats composed
2093 * end while loop
2098 * if (not all concats composed) {
2099 * delete any concats composed
2102 * append composed concats to results
2104 static int
2105 compose_concats_within_hba(
2106 devconfig_t *request,
2107 dlist_t *cursubs,
2108 dlist_t *hbas,
2109 uint64_t nbytes,
2110 uint16_t nsubs,
2111 dlist_t **results)
2113 int error = 0;
2115 dlist_t *iter = NULL;
2116 dlist_t *list = NULL;
2117 int count = 0;
2119 oprintf(OUTPUT_VERBOSE,
2120 gettext(" --->Trying to compose %d Concats within "
2121 "a single HBA.\n"), nsubs);
2123 for (iter = hbas;
2124 (count < nsubs) && (error == 0) && (iter != NULL);
2125 iter = iter->next) {
2127 dm_descriptor_t hba = (uintptr_t)iter->obj;
2128 dlist_t *disks = NULL;
2129 uint64_t space = 0;
2131 error = hba_get_avail_disks_and_space(request, hba, &disks, &space);
2132 if ((error == 0) && (space >= (nsubs * nbytes))) {
2134 /* try composing nsubs concats all on this HBA */
2135 count = 0;
2136 while ((count < nsubs) && (error == 0)) {
2137 devconfig_t *concat = NULL;
2138 dlist_t *item = NULL;
2140 error = populate_concat(
2141 request, nbytes, disks, cursubs, &concat);
2143 if ((error == 0) && (concat != NULL)) {
2144 item = dlist_new_item((void*)concat);
2145 if (item == NULL) {
2146 error = ENOMEM;
2147 } else {
2148 count++;
2149 list = dlist_append(item, list, AT_TAIL);
2150 error = remove_used_disks(&disks, concat);
2152 } else if (concat == NULL) {
2153 dlist_free_items(list, free_devconfig_object);
2154 list = NULL;
2155 break;
2160 dlist_free_items(disks, NULL);
2163 if (count < nsubs) {
2164 print_layout_submirrors_failed_msg(
2165 devconfig_type_to_str(TYPE_CONCAT),
2166 count, nsubs);
2168 dlist_free_items(list, free_devconfig_object);
2169 list = NULL;
2170 } else {
2171 *results = dlist_append(list, *results, AT_TAIL);
2174 return (error);
2178 * FUNCTION: remove_used_disks(dlist_t **disks, devconfig_t *volume)
2180 * INPUT: disks - pointer to a list of disks
2181 * volume - pointer to a devconfig_t volume
2183 * OUPUT: disks - pointer to new list of disks
2185 * RETURNS: int - 0 on success
2186 * !0 otherwise.
2188 * PURPOSE: Helper which updates the input list of disks by removing
2189 * those which have slices used by the input volume.
2191 * Constructs a new list containing only disks not used by
2192 * the volume.
2194 * The original list is freed.
2196 static int
2197 remove_used_disks(
2198 dlist_t **disks,
2199 devconfig_t *volume)
2201 dlist_t *list = NULL;
2202 dlist_t *iter = NULL;
2203 dlist_t *item = NULL;
2204 int error = 0;
2206 for (iter = *disks; (iter != NULL) && (error == 0); iter = iter->next) {
2208 dm_descriptor_t diskp = (uintptr_t)iter->obj;
2209 boolean_t shares = B_FALSE;
2211 error = volume_shares_disk(diskp, volume, &shares);
2212 if ((error == 0) && (shares != B_TRUE)) {
2213 /* disk is unused */
2214 if ((item = dlist_new_item((void*)(uintptr_t)diskp)) == NULL) {
2215 error = ENOMEM;
2216 } else {
2217 list = dlist_append(item, list, AT_TAIL);
2222 if (error != 0) {
2223 dlist_free_items(list, NULL);
2224 } else {
2226 /* free original disk list, return new list */
2227 dlist_free_items(*disks, NULL);
2229 *disks = list;
2232 return (error);
2236 * FUNCTION: volume_shares_disk(dm_descriptor_t disk,
2237 * devconfig_t *volume, boolean_t *shares)
2239 * INPUT: disk - a dm_descriptor_t handle for the disk of interest
2240 * volume - a devconfig_t pointer to a volume
2241 * bool - a boolean_t pointer to hold the result
2243 * RETURNS: int - 0 on success
2244 * !0 otherwise
2246 * PURPOSE: Determines if the input disk has a slice that is used
2247 * as a component by the input volume.
2249 * If the disk contributes a slice component, bool is set
2250 * to B_TRUE, B_FALSE otherwise.
2252 static int
2253 volume_shares_disk(
2254 dm_descriptor_t disk,
2255 devconfig_t *volume,
2256 boolean_t *shares)
2258 dlist_t *iter = NULL;
2259 int error = 0;
2261 *shares = B_FALSE;
2263 /* look at all slices in the volume */
2264 for (iter = devconfig_get_components(volume);
2265 (iter != NULL) && (*shares == B_FALSE) && (error == 0);
2266 iter = iter->next) {
2268 devconfig_t *dev = (devconfig_t *)iter->obj;
2270 if (devconfig_isA(dev, TYPE_SLICE)) {
2272 /* get disk for volume's slice */
2273 dm_descriptor_t odisk = NULL;
2274 char *oname = NULL;
2276 ((error = devconfig_get_name(dev, &oname)) != 0) ||
2277 (error = get_disk_for_named_slice(oname, &odisk));
2279 if (error == 0) {
2280 if (compare_descriptor_names(
2281 (void*)(uintptr_t)disk, (void*)(uintptr_t)odisk) == 0) {
2282 /* otherslice is on same disk, stop */
2283 *shares = B_TRUE;
2289 return (error);
2293 * FUNCTION: select_mpxio_hbas(dlist_t *hbas, dlist_t **mpxio_hbas)
2295 * INPUT: hbas - pointer to a list of dm_descriptor_t HBA handles
2297 * OUTPUT: mpxio_hbas - pointer to a new list of containing HBAs that
2298 * are multiplex enabled.
2300 * RETURNS: int - 0 on success
2301 * !0 otherwise.
2303 * PURPOSE: Iterates the input list of HBAs and builds a new list
2304 * containing those that are multiplex enabled.
2306 * The output list should be passed to dlist_free_items()
2307 * when no longer needed.
2309 static int
2310 select_mpxio_hbas(
2311 dlist_t *hbas,
2312 dlist_t **mpxio_hbas)
2314 dlist_t *iter;
2315 int error = 0;
2317 for (iter = hbas; (iter != NULL) && (error == 0); iter = iter->next) {
2318 dm_descriptor_t hba = (uintptr_t)iter->obj;
2319 boolean_t ismpxio = B_FALSE;
2320 if ((error = hba_is_multiplex(hba, &ismpxio)) == 0) {
2321 if (ismpxio == B_TRUE) {
2322 dlist_t *item = dlist_new_item((void *)(uintptr_t)hba);
2323 if (item != NULL) {
2324 *mpxio_hbas =
2325 dlist_append(item, *mpxio_hbas, AT_TAIL);
2326 } else {
2327 error = ENOMEM;
2333 if (error != 0) {
2334 dlist_free_items(*mpxio_hbas, NULL);
2335 *mpxio_hbas = NULL;
2338 return (error);
2342 * FUNCTION: set_explicit_submirror_names(dlist_t *reqs, dlist_t *subs)
2344 * INPUT: reqs - pointer to a list of request devconfig_ts
2345 * subs - pointer to a list of volume devconfig_ts
2347 * SIDEEFFECT: Modifies the volume names.
2349 * RETURNS: int - 0 on success
2350 * !0 otherwise.
2352 * PURPOSE: Iterates the lists of volumes and requests and calls
2353 * set_explicit_mirror_name for each pair.
2355 static int
2356 set_explicit_submirror_names(
2357 dlist_t *reqs,
2358 dlist_t *subs)
2360 int error = 0;
2362 while ((reqs != NULL) && (subs != NULL) && (error == 0)) {
2364 error = set_explicit_submirror_name(
2365 (devconfig_t *)reqs->obj,
2366 (devconfig_t *)subs->obj);
2368 reqs = reqs->next;
2369 subs = subs->next;
2372 return (error);
2376 * FUNCTION: set_explicit_submirror_name(dlist_t *req, dlist_t *sub)
2378 * INPUT: req - pointer to a request devconfig_t
2379 * sub - pointer to a volume devconfig_t
2381 * SIDEEFFECT: Modifies the volume name.
2383 * RETURNS: int - 0 on success
2384 * !0 otherwise.
2386 * PURPOSE: Clears the volume's current name and returns the name
2387 * to the available pool.
2389 * If a name is specified in the request, the name is used
2390 * as the volume's name.
2392 * (Unnamed submirrors will have default names assigned
2393 * during final mirror assembly.)
2395 static int
2396 set_explicit_submirror_name(
2397 devconfig_t *req,
2398 devconfig_t *sub)
2400 char *name = NULL;
2401 int error = 0;
2403 /* unset current submirror name */
2404 (void) devconfig_get_name(sub, &name);
2405 release_volume_name(name);
2406 (void) devconfig_set_name(sub, "");
2408 if (devconfig_get_name(req, &name) != ERR_ATTR_UNSET) {
2409 (void) devconfig_set_name(sub, name);
2412 return (error);