1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <libintl.h>
30
31 #include "volume_error.h"
32 #include "volume_dlist.h"
33 #include "volume_output.h"
34
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"
45
46 #define _LAYOUT_MIRROR_C
47
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);
54
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);
61
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);
71
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);
82
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);
92
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);
100
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);
109
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);
117
118 static int assemble_mirror(
119 devconfig_t *request,
120 dlist_t *subs,
121 devconfig_t **mirror);
122
123 static int remove_used_disks(
124 dlist_t **disks,
125 devconfig_t *volume);
126
127 static int volume_shares_disk(
128 dm_descriptor_t disk,
129 devconfig_t *volume,
130 boolean_t *bool);
131
132 static int select_mpxio_hbas(
133 dlist_t *hbas,
134 dlist_t **mpxio_hbas);
135
136 static int set_explicit_submirror_names(
137 dlist_t *reqs,
138 dlist_t *subs);
139
140 static int set_explicit_submirror_name(
141 devconfig_t *req,
142 devconfig_t *sub);
143
144 /*
145 * FUNCTION: layout_mirror(devconfig_t *request, nbytes, dlist_t **results)
146 *
147 * INPUT: request - pointer to a request devconfig_t
148 * nsubs - number of submirrors
149 * nbytes - desired mirror size
150 *
151 * OUTPUT: results - pointer to a list of volume devconfig_t results
152 *
153 * RETURNS: int - 0 on success
154 * !0 otherwise.
155 *
156 * PURPOSE: Main driver to handle a mirror request that does not specify
157 * subcomponents.
158 *
159 * Striped submirrors are tried first, then concats.
160 */
161 int
layout_mirror(devconfig_t * request,uint16_t nsubs,uint64_t nbytes,dlist_t ** results)162 layout_mirror(
163 devconfig_t *request,
164 uint16_t nsubs,
165 uint64_t nbytes,
166 dlist_t **results)
167 {
168 dlist_t *subs = NULL;
169 dlist_t *item = NULL;
170 boolean_t usehsp = B_FALSE;
171 int error = 0;
172
173 if ((error = get_volume_faultrecov(request, &usehsp)) != 0) {
174 if (error != ERR_ATTR_UNSET) {
175 return (error);
176 }
177 error = 0;
178 }
179
180 print_layout_volume_msg(devconfig_type_to_str(TYPE_MIRROR), nbytes);
181
182 /* prefer stripe submirrors */
183 if ((error = layout_stripe_submirrors(
184 request, NULL, nbytes, nsubs, &subs)) != 0) {
185 return (error);
186 }
187
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);
193 }
194 }
195
196 if (subs != NULL) {
197
198 devconfig_t *mirror = NULL;
199 dlist_t *iter = NULL;
200
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;
205
206 (void) devconfig_get_name(sub, &name);
207 release_volume_name(name);
208 (void) devconfig_set_name(sub, "");
209 }
210
211 error = assemble_mirror(request, subs, &mirror);
212 if (error == 0) {
213
214 if ((item = dlist_new_item(mirror)) == NULL) {
215 error = ENOMEM;
216 } else {
217 *results = dlist_append(item, *results, AT_TAIL);
218
219 /* remember submirrors that need HSPs */
220 if (usehsp == B_TRUE) {
221 error = add_to_hsp_list(
222 devconfig_get_components(mirror));
223 }
224
225 print_layout_success_msg();
226 }
227 } else {
228 /* cleanup submirrors */
229 dlist_free_items(subs, free_devconfig_object);
230 subs = NULL;
231 }
232
233 } else if (error != 0) {
234
235 print_debug_failure_msg(devconfig_type_to_str(TYPE_MIRROR),
236 get_error_string(error));
237
238 } else {
239
240 print_insufficient_resources_msg(
241 devconfig_type_to_str(TYPE_MIRROR));
242 error = -1;
243 }
244
245 return (error);
246 }
247
248 /*
249 * FUNCTION: populate_explicit_mirror(devconfig_t *request,
250 * dlist_t **results)
251 *
252 * INPUT: request - pointer to a request devconfig_t
253 *
254 * OUTPUT: results - pointer to a list of volume devconfig_t results
255 *
256 * RETURNS: int - 0 on success
257 * !0 otherwise.
258 *
259 * PURPOSE: Processes the input mirror request specifying explicit layout
260 * constraints on the submirrors.
261 *
262 * Primary submirror constraint is explicit type, either
263 * stripe or concat. Submirror types may be mixed.
264 *
265 * Submirror sizes or components may be specified explicitly.
266 *
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.
270 *
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().
275 *
276 * If all specified submirrors can be assembled, the final mirror
277 * is assembled and appended to the results list.
278 */
279 int
populate_explicit_mirror(devconfig_t * request,dlist_t ** results)280 populate_explicit_mirror(
281 devconfig_t *request,
282 dlist_t **results)
283 {
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;
293
294 list = devconfig_get_components(request);
295 nsubs = dlist_length(list);
296
297 if ((error = get_volume_faultrecov(request, &usehsp)) != 0) {
298 if (error != ERR_ATTR_UNSET) {
299 return (error);
300 }
301 error = 0;
302 }
303
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);
310 }
311 }
312
313 print_layout_explicit_msg(devconfig_type_to_str(TYPE_MIRROR));
314
315 /*
316 * Scan the list of specified submirrors, collect those that only
317 * specify size (or no size). Process those with explicit components
318 * immediately.
319 */
320 composed = NULL;
321 for (iter = list; (iter != NULL) && (error == 0); iter = iter->next) {
322
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;
328
329 (void) devconfig_get_type(comp, &ctype);
330 (void) devconfig_get_size(comp, &csize);
331 clist = devconfig_get_components(comp);
332
333 if (clist != NULL) {
334
335 /* components specified */
336
337 if (ctype == TYPE_STRIPE) {
338 error = populate_explicit_stripe(comp, &item);
339 } else {
340 error = populate_explicit_concat(comp, &item);
341 }
342
343 if (error == 0) {
344 set_explicit_submirror_name(
345 comp, (devconfig_t *)item->obj);
346 composed = dlist_append(item, composed, AT_TAIL);
347 }
348
349 } else {
350
351 /* no components specified */
352
353 /* if no size is specified, it needs to be inferred */
354
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;
359 }
360 if (csize == 0) {
361 /* this submirror specified no size, use mirror size */
362 devconfig_set_size(comp, msize);
363 }
364
365 if ((item = dlist_new_item(comp)) == NULL) {
366 error = ENOMEM;
367 break;
368 }
369
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);
376 }
377
378 }
379 }
380
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) {
387
388 /* adjust stripe names */
389 set_explicit_submirror_names(stripes_by_size, stripes);
390 composed = dlist_append(stripes, composed, AT_TAIL);
391
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;
397 }
398 dlist_free_items(stripes_by_size, NULL);
399 }
400
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) {
407
408 /* adjust concat names */
409 set_explicit_submirror_names(concats_by_size, concats);
410 composed = dlist_append(concats, composed, AT_TAIL);
411
412 } else {
413
414 /* these concats failed */
415 dlist_free_items(concats, free_devconfig_object);
416 }
417
418 dlist_free_items(concats_by_size, NULL);
419 }
420
421 if ((composed != NULL) && ((dlist_length(composed) == nsubs))) {
422
423 /* assemble final mirror */
424
425 devconfig_t *mirror = NULL;
426 dlist_t *item = NULL;
427
428 if ((error = assemble_mirror(request, composed, &mirror)) == 0) {
429
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));
437 }
438 print_layout_success_msg();
439 }
440 }
441
442 } else if (error != 0) {
443
444 print_debug_failure_msg(
445 devconfig_type_to_str(TYPE_MIRROR),
446 get_error_string(error));
447
448 } else {
449
450 dlist_free_items(composed, free_devconfig_object);
451 print_insufficient_resources_msg(
452 devconfig_type_to_str(TYPE_MIRROR));
453 error = -1;
454 }
455
456 return (error);
457 }
458
459 /*
460 * FUNCTION: assemble_mirror(devconfig_t *request, dlist_t *subs,
461 * devconfig_t **mirror)
462 *
463 * INPUT: request - pointer to a devconfig_t of the current request
464 * subs - pointer to a list of composed submirrors
465 *
466 * OUPUT: mirror - pointer to a devconfig_t to hold final mirror
467 *
468 * RETURNS: int - 0 on success
469 * !0 otherwise.
470 *
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.
474 *
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.
478 *
479 * Sets the read and write strategies, and the resync pass
480 * number for the mirror if values are specified in the request.
481 *
482 * Attaches the input list of submirrors to the devconfig.
483 */
484 static int
assemble_mirror(devconfig_t * request,dlist_t * subs,devconfig_t ** mirror)485 assemble_mirror(
486 devconfig_t *request,
487 dlist_t *subs,
488 devconfig_t **mirror)
489 {
490 dlist_t *iter = NULL;
491 char *name = NULL;
492 int error = 0;
493
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;
501 }
502 }
503
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);
512 }
513 } else {
514 error = devconfig_set_name(*mirror, name);
515 }
516 }
517 }
518
519 /* assign name to any unnamed submirror */
520 for (iter = subs;
521 (error == 0) && (iter != NULL);
522 iter = iter->next) {
523
524 devconfig_t *sub = (devconfig_t *)iter->obj;
525 char *subname = NULL;
526
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);
533 }
534 }
535
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;
542 }
543 }
544
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;
551 }
552 }
553
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;
560 }
561 }
562
563 /* arrange submirrors in ascending size order */
564 if (error == 0) {
565 dlist_t *sorted = NULL;
566 dlist_t *next = NULL;
567
568 iter = subs;
569 while (iter != NULL) {
570
571 next = iter->next;
572 iter->next = NULL;
573 iter->prev = NULL;
574
575 sorted = dlist_insert_ordered(iter,
576 sorted, ASCENDING, compare_devconfig_sizes);
577
578 iter = next;
579 }
580 subs = sorted;
581 }
582
583 if (error == 0) {
584 devconfig_set_components(*mirror, subs);
585 } else {
586 free_devconfig(*mirror);
587 *mirror = NULL;
588 }
589
590 return (error);
591 }
592
593 /*
594 * FUNCTION: layout_stripe_submirrors(devconfig_t *request, dlist_t *cursubs,
595 * uint64_t nbytes, uint16_t nsubs, dlist_t **results)
596 *
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
603 *
604 * OUPUT: results - pointer to a list of composed volumes
605 *
606 * RETURNS: int - 0 on success
607 * !0 otherwise.
608 *
609 * PURPOSE: Main layout driver for composing stripe submirrors.
610 *
611 * Attempts to construct nsub submirrors of size nbytes.
612 *
613 * Several different layout strategies are tried in order
614 * of preference until one succeeds or there are none left.
615 *
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
620 *
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
624 *
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
629 *
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
633 *
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
638 *
639 * 6 - mirror with all stripes within the same HBA
640 * . requires an HBA with mincomp * nsubs disks
641 *
642 * get available HBAs
643 *
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
649 * }
650 * }
651 *
652 * if (nsub stripes not composed) {
653 * for (strategy[4,5,6]) and (nsub stripes not composed) {
654 * compose nsub stripes using all HBAs
655 * }
656 * }
657 *
658 * if (all stripes composed) {
659 * append composed stripes to results
660 * }
661 *
662 */
663 static int
layout_stripe_submirrors(devconfig_t * request,dlist_t * cursubs,uint64_t nbytes,uint16_t nsubs,dlist_t ** results)664 layout_stripe_submirrors(
665 devconfig_t *request,
666 dlist_t *cursubs,
667 uint64_t nbytes,
668 uint16_t nsubs,
669 dlist_t **results)
670 {
671 /*
672 * these enums define the # of strategies and the preference order
673 * in which they are tried
674 */
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;
681
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;
688
689 dlist_t *usable_hbas = NULL;
690 dlist_t *similar_hba_groups = NULL;
691 dlist_t *iter = NULL;
692 dlist_t *subs = NULL;
693
694 boolean_t usehsp = B_FALSE;
695 uint16_t mincomp = 0;
696 uint16_t maxcomp = 0;
697
698 int error = 0;
699
700 (error = get_usable_hbas(&usable_hbas));
701 if (error != 0) {
702 return (error);
703 }
704
705 print_layout_submirrors_msg(devconfig_type_to_str(TYPE_STRIPE),
706 nbytes, nsubs);
707
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);
712 }
713
714 similar_hba_groups = NULL;
715 ((error = group_similar_hbas(usable_hbas, &similar_hba_groups)) != 0) ||
716
717 /*
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.
723 */
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);
729 }
730
731 for (iter = similar_hba_groups;
732 (error == 0) && (subs == NULL) && (iter != NULL);
733 iter = iter->next) {
734
735 dlist_t *hbas = (dlist_t *)iter->obj;
736
737 similar_hba_strategy_order_t order;
738
739 for (order = ALL_STRIPES_ON_MPXIO;
740 (order < N_SIMILAR_HBA_STRATEGIES) &&
741 (subs == NULL) && (error == 0);
742 order++) {
743
744 dlist_t *selhbas = NULL;
745 dlist_t *disks = NULL;
746 int n = 0;
747
748 switch (order) {
749
750 case ALL_STRIPES_ON_MPXIO:
751
752 if (is_mpxio_enabled() == B_TRUE) {
753 dlist_t *mpxio_hbas = NULL;
754
755 /* see if any HBA supports MPXIO */
756 error = select_mpxio_hbas(hbas, &mpxio_hbas);
757 if ((error == 0) && (mpxio_hbas != NULL)) {
758
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 */
764
765 /* see if MPXIO HBA has enough disks */
766 error = select_hbas_with_n_disks(
767 request, mpxio_hbas, (mincomp * nsubs),
768 &selhbas, &disks);
769
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);
776 }
777 }
778
779 dlist_free_items(mpxio_hbas, NULL);
780 }
781
782 break;
783
784 case STRIPE_PER_SIMILAR_HBA:
785
786 error = select_hbas_with_n_disks(
787 request, hbas, mincomp, &selhbas, &disks);
788
789 if (error == 0) {
790
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 */
796
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);
803 }
804 }
805
806 break;
807
808 case STRIPE_ACROSS_SIMILAR_HBAS:
809
810 error = select_hbas_with_n_disks(
811 request, hbas, nsubs, &selhbas, &disks);
812
813 if (error == 0) {
814
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 */
820
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);
827 }
828 }
829
830 break;
831
832 default:
833 break;
834 }
835
836 dlist_free_items(selhbas, NULL);
837 dlist_free_items(disks, NULL);
838 }
839 }
840
841 for (iter = similar_hba_groups; iter != NULL; iter = iter->next) {
842 dlist_free_items((dlist_t *)iter->obj, NULL);
843 }
844 dlist_free_items(similar_hba_groups, NULL);
845
846 /* retry using all available HBAs */
847 if (subs == NULL) {
848
849 any_hba_strategy_order_t order;
850
851 for (order = STRIPE_PER_ANY_HBA;
852 (order < N_ANY_HBA_STRATEGIES) &&
853 (subs == NULL) && (error == 0);
854 order++) {
855
856 dlist_t *selhbas = NULL;
857 dlist_t *disks = NULL;
858 int n = 0;
859
860 switch (order) {
861
862 case STRIPE_PER_ANY_HBA:
863
864 error = select_hbas_with_n_disks(
865 request, usable_hbas, nsubs, &selhbas, &disks);
866
867 if (error == 0) {
868
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 */
874
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);
881 }
882 }
883
884 break;
885
886 case STRIPE_ACROSS_ANY_HBAS:
887
888 error = select_hbas_with_n_disks(
889 request, usable_hbas, nsubs, &selhbas, &disks);
890
891 if (error == 0) {
892
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 */
898
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);
905 }
906 }
907
908 break;
909
910 case STRIPE_WITHIN_ANY_HBA:
911
912 error = select_hbas_with_n_disks(
913 request, usable_hbas, (mincomp * nsubs),
914 &selhbas, &disks);
915
916 if (error == 0) {
917
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);
929 }
930 }
931
932 break;
933
934 default:
935 break;
936 }
937
938 dlist_free_items(selhbas, NULL);
939 dlist_free_items(disks, NULL);
940 }
941 }
942
943 if (error == 0) {
944 *results = dlist_append(subs, *results, AT_TAIL);
945 }
946 return (error);
947 }
948
949 /*
950 * FUNCTION: layout_concat_submirrors(devconfig_t *request, dlist_t *cursubs,
951 * uint64_t nbytes, uint16_t nsubs, dlist_t **results)
952 *
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
956 *
957 * OUPUT: results - pointer to a list of composed volumes
958 *
959 * RETURNS: int - 0 on success
960 * !0 otherwise.
961 *
962 * PURPOSE: Main layout driver for composing concat submirrors.
963 *
964 * Attempts to construct nsub submirrors of size nbytes.
965 *
966 * Several different layout strategies are tried in order
967 * of preference until one succeeds or there are none left.
968 *
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
972 *
973 * 2 - mirror with concats on separate HBAs of same type
974 * . requires nsubs HBAs with available disks
975 *
976 * 3 - mirror with concats across HBAs of same type
977 * . requires an HBA with at least 1 available disk
978 *
979 * 4 - mirror with concats on separate HBAs of mixed type
980 * . requires nsubs HBAs with available disks
981 *
982 * 5 - mirror with concats across HBAs of mixed type
983 * . requires an HBA with at least 1 available disk
984 *
985 * 6 - mirror with all concats on the same HBA
986 * . requires an HBA with at least nsubs available disks
987 *
988 * get available HBAs
989 *
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
995 * }
996 * }
997 *
998 * if (nsub concats not composed) {
999 * for (strategy[4,5,6]) and (nsub concats not composed) {
1000 * compose nsub concats, nbytes in size
1001 * }
1002 * }
1003 *
1004 * if (all concats composed) {
1005 * append composed concats to results
1006 * }
1007 *
1008 */
1009 static int
layout_concat_submirrors(devconfig_t * request,dlist_t * cursubs,uint64_t nbytes,uint16_t nsubs,dlist_t ** results)1010 layout_concat_submirrors(
1011 devconfig_t *request,
1012 dlist_t *cursubs,
1013 uint64_t nbytes,
1014 uint16_t nsubs,
1015 dlist_t **results)
1016 {
1017 /*
1018 * these enums define the # of strategies and the preference order
1019 * in which they are tried
1020 */
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;
1027
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;
1034
1035 dlist_t *usable_hbas = NULL;
1036 dlist_t *similar_hba_groups = NULL;
1037 dlist_t *iter = NULL;
1038 dlist_t *subs = NULL;
1039
1040 boolean_t usehsp = B_FALSE;
1041
1042 int error = 0;
1043
1044 (error = get_usable_hbas(&usable_hbas));
1045 if (error != 0) {
1046 return (error);
1047 }
1048
1049 print_layout_submirrors_msg(devconfig_type_to_str(TYPE_CONCAT),
1050 nbytes, nsubs);
1051
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);
1056 }
1057
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);
1063 }
1064
1065 for (iter = similar_hba_groups;
1066 (error == 0) && (subs == NULL) && (iter != NULL);
1067 iter = iter->next) {
1068
1069 dlist_t *hbas = (dlist_t *)iter->obj;
1070
1071 similar_hba_strategy_order_t order;
1072
1073 for (order = ALL_CONCATS_ON_MPXIO;
1074 (order < N_SIMILAR_HBA_STRATEGIES) &&
1075 (subs == NULL) && (error == 0);
1076 order++) {
1077
1078 dlist_t *selhbas = NULL;
1079 dlist_t *disks = NULL;
1080 int n = 0;
1081
1082 switch (order) {
1083
1084 case ALL_CONCATS_ON_MPXIO:
1085
1086 if (is_mpxio_enabled() == B_TRUE) {
1087 dlist_t *mpxio_hbas = NULL;
1088
1089 /* see if any HBA supports MPXIO */
1090 error = select_mpxio_hbas(hbas, &mpxio_hbas);
1091 if ((error == 0) && (mpxio_hbas != NULL)) {
1092
1093 /* BEGIN CSTYLED */
1094 oprintf(OUTPUT_TERSE,
1095 gettext(" -->Strategy 1: use at least %d MPXIO disks\n"),
1096 nsubs);
1097 /* END CSTYLED */
1098
1099 /* see if MPXIO HBA has enough disks */
1100 error = select_hbas_with_n_disks(
1101 request, hbas, nsubs, &selhbas, &disks);
1102
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);
1110 }
1111 }
1112
1113 dlist_free_items(mpxio_hbas, NULL);
1114 }
1115
1116 break;
1117
1118 case CONCAT_PER_SIMILAR_HBA:
1119
1120 error = select_hbas_with_n_disks(
1121 request, hbas, 1, &selhbas, &disks);
1122
1123 if (error == 0) {
1124
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 */
1130
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);
1137 }
1138 }
1139
1140 break;
1141
1142 case CONCAT_ACROSS_SIMILAR_HBAS:
1143
1144 error = select_hbas_with_n_disks(
1145 request, hbas, 1, &selhbas, &disks);
1146
1147 if (error == 0) {
1148
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);
1158 }
1159
1160 break;
1161
1162 default:
1163 break;
1164 }
1165
1166 dlist_free_items(selhbas, NULL);
1167 dlist_free_items(disks, NULL);
1168 }
1169 }
1170
1171 for (iter = similar_hba_groups; iter != NULL; iter = iter->next) {
1172 dlist_free_items((dlist_t *)iter->obj, NULL);
1173 }
1174 dlist_free_items(similar_hba_groups, NULL);
1175
1176 /* retry using all available HBAs */
1177 if (subs == NULL) {
1178
1179 any_hba_strategy_order_t order;
1180
1181 for (order = CONCAT_PER_ANY_HBA;
1182 (order < N_ANY_HBA_STRATEGIES) &&
1183 (subs == NULL) && (error == 0);
1184 order++) {
1185
1186 dlist_t *selhbas = NULL;
1187 dlist_t *disks = NULL;
1188 int n = 0;
1189
1190 switch (order) {
1191
1192 case CONCAT_PER_ANY_HBA:
1193
1194 error = select_hbas_with_n_disks(
1195 request, usable_hbas, 1, &selhbas, &disks);
1196
1197 if (error == 0) {
1198
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);
1210 }
1211 }
1212 break;
1213
1214 case CONCAT_ACROSS_ANY_HBAS:
1215
1216 error = select_hbas_with_n_disks(
1217 request, usable_hbas, 1, &selhbas, &disks);
1218
1219 if (error == 0) {
1220
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);
1229 }
1230
1231 break;
1232
1233 case CONCAT_WITHIN_ANY_HBA:
1234
1235 error = select_hbas_with_n_disks(
1236 request, usable_hbas, 1, &selhbas, &disks);
1237
1238 if (error == 0) {
1239
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 */
1245
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);
1252 }
1253
1254 }
1255 break;
1256
1257 default:
1258 break;
1259 }
1260
1261 dlist_free_items(selhbas, NULL);
1262 dlist_free_items(disks, NULL);
1263 }
1264 }
1265
1266 if (error == 0) {
1267 *results = dlist_append(subs, *results, AT_TAIL);
1268 }
1269
1270 return (error);
1271 }
1272
1273 /*
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)
1278 *
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
1286 *
1287 * OUPUT: results - pointer to a list of composed volumes
1288 *
1289 * RETURNS: int - 0 on success
1290 * !0 otherwise.
1291 *
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.
1295 *
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.
1300 *
1301 * Each stripe will use disks from a single HBA.
1302 *
1303 * All input HBAs are expected to have at least mincomp available
1304 * disks.
1305 *
1306 * If the stripes can be composed, they are appended to the list
1307 * of result volumes.
1308 *
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
1315 * }
1316 *
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
1323 * }
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
1330 * }
1331 * if a stripe can be composed using disks {
1332 * save stripe
1333 * increment stripe count
1334 * }
1335 * }
1336 *
1337 * if (not all stripes composed) {
1338 * delete any compose stripes
1339 * }
1340 * }
1341 * }
1342 *
1343 * if (not all stripes composed) {
1344 * delete any stripes composed
1345 * }
1346 * }
1347 *
1348 * if (not all stripes composed) {
1349 * delete any stripes composed
1350 * }
1351 *
1352 * append composed stripes to results
1353 */
1354 static int
compose_stripe_per_hba(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,uint64_t nbytes,uint16_t nsubs,uint16_t maxcomp,uint16_t mincomp,dlist_t ** results)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)
1364 {
1365 int error = 0;
1366 dlist_t *list = NULL;
1367 dlist_t *iter = NULL;
1368
1369 oprintf(OUTPUT_VERBOSE,
1370 gettext(" --->Trying to compose %d Stripes with "
1371 "%d-%d components on separate HBAs.\n"),
1372 nsubs, mincomp, maxcomp);
1373
1374 for (iter = hbas;
1375 (list == NULL) && (iter != NULL) && (error == 0);
1376 iter = iter->next) {
1377
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;
1383
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;
1389 }
1390
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;
1396 }
1397
1398 if ((ncomp = dlist_length(disks)) < mincomp) {
1399 print_insufficient_disks_msg(ncomp);
1400 dlist_free_items(disks, NULL);
1401 continue;
1402 }
1403
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--) {
1408
1409 int count = 0;
1410
1411 /* try composing nsubs stripes with ncomp components */
1412 while (count < nsubs) {
1413
1414 devconfig_t *stripe = NULL;
1415 dlist_t *item = NULL;
1416 dlist_t *iter1 = NULL;
1417
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;
1425 }
1426
1427 /* composed a stripe */
1428 if ((item = dlist_new_item((void*)stripe)) == NULL) {
1429 error = ENOMEM;
1430 break;
1431 }
1432 ++count;
1433 list = dlist_append(item, list, AT_TAIL);
1434
1435 /* compose stripes on remaining HBAs */
1436 for (iter1 = iter->next;
1437 (count < nsubs) && (iter1 != NULL) && (error == 0);
1438 iter1 = iter1->next) {
1439
1440 dm_descriptor_t hba1 = (uintptr_t)iter1->obj;
1441 uint64_t space1 = 0;
1442 dlist_t *disks1 = NULL;
1443
1444 error = hba_get_avail_disks_and_space(request,
1445 hba1, &disks1, &space1);
1446 if (error != 0) {
1447 continue;
1448 }
1449
1450 /* enough space/disks on this HBA? */
1451 if ((dlist_length(disks1) < ncomp) ||
1452 (space1 < nbytes)) {
1453 dlist_free_items(disks1, NULL);
1454 continue;
1455 }
1456
1457 stripe = NULL;
1458 error = populate_stripe(
1459 request, nbytes, disks1,
1460 ncomp, cursubs, &stripe);
1461
1462 if (stripe != NULL) {
1463 /* prepare to compose another */
1464 if ((item = dlist_new_item(
1465 (void *)stripe)) == NULL) {
1466 error = ENOMEM;
1467 break;
1468 }
1469 list = dlist_append(item, list, AT_TAIL);
1470 ++count;
1471 }
1472
1473 dlist_free_items(disks1, NULL);
1474 disks1 = NULL;
1475 }
1476
1477 if ((iter1 == NULL) && (count < nsubs)) {
1478 /*
1479 * no HBAs remain and haven't composed
1480 * enough stripes at the current width.
1481 * break while loop and try another width.
1482 */
1483 break;
1484 }
1485 }
1486
1487 if (count < nsubs) {
1488 /*
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
1493 */
1494 print_layout_submirrors_failed_msg(
1495 devconfig_type_to_str(TYPE_STRIPE),
1496 count, nsubs);
1497
1498 dlist_free_items(list, free_devconfig_object);
1499 list = NULL;
1500 }
1501 }
1502
1503 dlist_free_items(disks, NULL);
1504 disks = NULL;
1505 }
1506
1507 if (error == 0) {
1508 *results = dlist_append(list, *results, AT_TAIL);
1509 } else {
1510 dlist_free_items(list, free_devconfig_object);
1511 }
1512
1513 return (error);
1514 }
1515
1516 /*
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)
1521 *
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
1530 *
1531 * OUPUT: results - pointer to a list of composed volumes
1532 *
1533 * RETURNS: int - 0 on success
1534 * !0 otherwise.
1535 *
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.
1539 *
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.
1544 *
1545 * Each stripe will use a disk from several different HBAs.
1546 *
1547 * All input HBAs are expected to have at least nsubs available
1548 * disks.
1549 *
1550 * If the stripes can be composed, they are appended to the list
1551 * of result volumes.
1552 *
1553 * for (ncomps downto mincomp) {
1554 *
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
1563 * }
1564 *
1565 * free copied disk list
1566 * if (not all stripes composed) {
1567 * delete any stripes composed
1568 * decrement ncomps
1569 * }
1570 * }
1571 *
1572 * if (not all stripes composed) {
1573 * delete any stripes composed
1574 * }
1575 *
1576 * append composed stripes to results
1577 */
1578 static int
compose_stripes_across_hbas(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,dlist_t * disks,uint64_t nbytes,uint16_t nsubs,uint16_t ncomp,uint16_t mincomp,dlist_t ** results)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)
1589 {
1590 int error = 0;
1591 int count = 0;
1592
1593 dlist_t *list = NULL;
1594
1595 while ((ncomp >= mincomp) && (count < nsubs) && (error == 0)) {
1596
1597 dlist_t *iter;
1598 dlist_t *item;
1599 dlist_t *disks_copy = NULL;
1600
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));
1605
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);
1612 }
1613 }
1614
1615 /* compose nsubs stripe submirrors of ncomp components */
1616 while ((count < nsubs) && (error == 0)) {
1617
1618 devconfig_t *stripe = NULL;
1619 dlist_t *item = NULL;
1620
1621 error = populate_stripe(
1622 request, nbytes, disks_copy, ncomp, cursubs, &stripe);
1623
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);
1631 }
1632 } else if (stripe == NULL) {
1633 break;
1634 }
1635 }
1636
1637 /* free copy of disk list */
1638 dlist_free_items(disks_copy, NULL);
1639 disks_copy = NULL;
1640
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);
1647
1648 dlist_free_items(list, free_devconfig_object);
1649 list = NULL;
1650 count = 0;
1651 --ncomp;
1652 }
1653 }
1654
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);
1660 }
1661
1662 return (error);
1663 }
1664
1665 /*
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)
1670 *
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
1679 *
1680 * OUPUT: results - pointer to a list of composed volumes
1681 *
1682 * RETURNS: int - 0 on success
1683 * !0 otherwise.
1684 *
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.
1688 *
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.
1693 *
1694 * All stripes will use disks from a single HBA.
1695 *
1696 * All input HBAs are expected to have at least nsubs * mincomp
1697 * available disks and total space sufficient for subs stripes.
1698 *
1699 * If the stripes can be composed, they are appended to the list
1700 * of result volumes.
1701 *
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;
1706 * }
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;
1712 * }
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
1719 * }
1720 * if (not all stripes composed) {
1721 * delete any stripes composed
1722 * }
1723 * }
1724 * }
1725 *
1726 * if (not all stripes composed) {
1727 * delete any stripes composed
1728 * }
1729 *
1730 * append composed stripes to results
1731 */
1732 static int
compose_stripes_within_hba(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,uint64_t nbytes,uint16_t nsubs,uint16_t maxcomp,uint16_t mincomp,dlist_t ** results)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)
1742 {
1743 int error = 0;
1744 int count = 0;
1745
1746 dlist_t *list = NULL;
1747 dlist_t *iter = NULL;
1748
1749 for (iter = hbas;
1750 (count < nsubs) && (iter != NULL) && (error == 0);
1751 iter = iter->next) {
1752
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;
1759
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;
1766 }
1767
1768 if (space < (nsubs * nbytes)) {
1769 (void) print_hba_insufficient_space_msg(name, space);
1770 dlist_free_items(disks, NULL);
1771 continue;
1772 }
1773
1774 ndisks = dlist_length(disks);
1775
1776 /*
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
1780 */
1781 for (ncomp = maxcomp;
1782 (ncomp >= mincomp) && (count != nsubs) && (error == 0);
1783 ncomp--) {
1784
1785 oprintf(OUTPUT_VERBOSE,
1786 gettext(" --->Trying to compose %d Stripes with "
1787 "%d components on a single HBA.\n"),
1788 nsubs, ncomp);
1789
1790 if (ndisks < (ncomp * nsubs)) {
1791 print_insufficient_disks_msg(ndisks);
1792 continue;
1793 }
1794
1795 /* try composing nsubs stripes, each ncomp wide */
1796 for (count = 0; (count < nsubs) && (error == 0); count++) {
1797
1798 devconfig_t *stripe = NULL;
1799
1800 error = populate_stripe(
1801 request, nbytes, disks, ncomp, cursubs, &stripe);
1802
1803 if ((error == 0) && (stripe != NULL)) {
1804
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);
1811 }
1812 } else if (stripe == NULL) {
1813 break;
1814 }
1815 }
1816
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);
1823
1824 dlist_free_items(list, free_devconfig_object);
1825 list = NULL;
1826 }
1827 }
1828
1829 dlist_free_items(disks, NULL);
1830 }
1831
1832 if (count < nsubs) {
1833 dlist_free_items(list, free_devconfig_object);
1834 list = NULL;
1835 }
1836
1837 *results = list;
1838
1839 return (error);
1840 }
1841
1842 /*
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)
1846 *
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
1852 *
1853 * OUPUT: results - pointer to a list of composed volumes
1854 *
1855 * RETURNS: int - 0 on success
1856 * !0 otherwise.
1857 *
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.
1862 *
1863 * If the concats can be composed, they are appended to the list
1864 * of result volumes.
1865 *
1866 * while (more HBAs AND more concats need to be composed) {
1867 * if (not enough available space on this HBA) {
1868 * continue;
1869 * }
1870 *
1871 * get available disks for HBA
1872 * if (concat can be composed) {
1873 * save concat
1874 * increment count
1875 * }
1876 * }
1877 *
1878 * if (not all stripes composed) {
1879 * delete any concats composed
1880 * }
1881 *
1882 * append composed concats to results
1883 */
1884 static int
compose_concat_per_hba(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,uint64_t nbytes,uint16_t nsubs,dlist_t ** results)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)
1892 {
1893 int error = 0;
1894 int count = 0;
1895
1896 dlist_t *list = NULL;
1897 dlist_t *iter = NULL;
1898
1899 oprintf(OUTPUT_VERBOSE,
1900 gettext(" --->Trying to compose %d Concats on "
1901 "separate HBAs.\n"), nsubs);
1902
1903 for (iter = hbas;
1904 (iter != NULL) && (error == 0) && (count < nsubs);
1905 iter = iter->next) {
1906
1907 dm_descriptor_t hba = (uintptr_t)iter->obj;
1908 uint64_t space = 0;
1909 devconfig_t *concat = NULL;
1910 dlist_t *disks = NULL;
1911
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);
1916 }
1917
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);
1925 }
1926 }
1927
1928 dlist_free_items(disks, NULL);
1929 }
1930
1931 if (count != nsubs) {
1932 print_layout_submirrors_failed_msg(
1933 devconfig_type_to_str(TYPE_CONCAT),
1934 count, nsubs);
1935
1936 dlist_free_items(list, free_devconfig_object);
1937 list = NULL;
1938 } else {
1939 *results = dlist_append(list, *results, AT_TAIL);
1940 }
1941
1942 return (error);
1943 }
1944
1945 /*
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)
1949 *
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
1956 *
1957 * OUPUT: results - pointer to a list of composed volumes
1958 *
1959 * RETURNS: int - 0 on success
1960 * !0 otherwise.
1961 *
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.
1965 *
1966 * If the concats can be composed, they are appended to the list
1967 * of result volumes.
1968 *
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
1977 * }
1978 * }
1979 *
1980 * if (not all concats composed) {
1981 * delete any concats composed
1982 * }
1983 *
1984 * append composed concats to results
1985 */
1986 static int
compose_concats_across_hbas(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,dlist_t * disks,uint64_t nbytes,uint16_t nsubs,dlist_t ** results)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)
1995 {
1996 int error = 0;
1997 int count = 0;
1998
1999 dlist_t *list = NULL;
2000 dlist_t *item = NULL;
2001 dlist_t *iter = NULL;
2002 dlist_t *disks_copy = NULL;
2003
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);
2010 }
2011 }
2012
2013 while ((count < nsubs) && (error == 0)) {
2014
2015 devconfig_t *concat = NULL;
2016
2017 error = populate_concat(
2018 request, nbytes, disks_copy, cursubs, &concat);
2019
2020 if ((error == 0) && (concat != NULL)) {
2021
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);
2029 }
2030 } else if (concat == NULL) {
2031 break;
2032 }
2033 }
2034
2035 /* free copy of disk list */
2036 dlist_free_items(disks_copy, NULL);
2037 disks_copy = NULL;
2038
2039 if (count != nsubs) {
2040 print_layout_submirrors_failed_msg(
2041 devconfig_type_to_str(TYPE_CONCAT),
2042 count, nsubs);
2043
2044 dlist_free_items(list, free_devconfig_object);
2045 list = NULL;
2046 } else {
2047 *results = dlist_append(list, *results, AT_TAIL);
2048 }
2049
2050 return (error);
2051 }
2052
2053 /*
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)
2057 *
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
2063 *
2064 * OUPUT: results - pointer to a list of composed volumes
2065 *
2066 * RETURNS: int - 0 on success
2067 * !0 otherwise.
2068 *
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.
2072 *
2073 *
2074 * HBAs in the list are expected to have at least 2 available
2075 * disks and total space sufficient for the submirrors.
2076 *
2077 * If the concats can be composed, they are appended to the list
2078 * of result volumes.
2079 *
2080 * while (more HBAs) {
2081 * if (not enough available space on this HBA) {
2082 * continue;
2083 * }
2084 *
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
2094 * }
2095 * }
2096 * }
2097 *
2098 * if (not all concats composed) {
2099 * delete any concats composed
2100 * }
2101 *
2102 * append composed concats to results
2103 */
2104 static int
compose_concats_within_hba(devconfig_t * request,dlist_t * cursubs,dlist_t * hbas,uint64_t nbytes,uint16_t nsubs,dlist_t ** results)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)
2112 {
2113 int error = 0;
2114
2115 dlist_t *iter = NULL;
2116 dlist_t *list = NULL;
2117 int count = 0;
2118
2119 oprintf(OUTPUT_VERBOSE,
2120 gettext(" --->Trying to compose %d Concats within "
2121 "a single HBA.\n"), nsubs);
2122
2123 for (iter = hbas;
2124 (count < nsubs) && (error == 0) && (iter != NULL);
2125 iter = iter->next) {
2126
2127 dm_descriptor_t hba = (uintptr_t)iter->obj;
2128 dlist_t *disks = NULL;
2129 uint64_t space = 0;
2130
2131 error = hba_get_avail_disks_and_space(request, hba, &disks, &space);
2132 if ((error == 0) && (space >= (nsubs * nbytes))) {
2133
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;
2139
2140 error = populate_concat(
2141 request, nbytes, disks, cursubs, &concat);
2142
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);
2151 }
2152 } else if (concat == NULL) {
2153 dlist_free_items(list, free_devconfig_object);
2154 list = NULL;
2155 break;
2156 }
2157 }
2158 }
2159
2160 dlist_free_items(disks, NULL);
2161 }
2162
2163 if (count < nsubs) {
2164 print_layout_submirrors_failed_msg(
2165 devconfig_type_to_str(TYPE_CONCAT),
2166 count, nsubs);
2167
2168 dlist_free_items(list, free_devconfig_object);
2169 list = NULL;
2170 } else {
2171 *results = dlist_append(list, *results, AT_TAIL);
2172 }
2173
2174 return (error);
2175 }
2176
2177 /*
2178 * FUNCTION: remove_used_disks(dlist_t **disks, devconfig_t *volume)
2179 *
2180 * INPUT: disks - pointer to a list of disks
2181 * volume - pointer to a devconfig_t volume
2182 *
2183 * OUPUT: disks - pointer to new list of disks
2184 *
2185 * RETURNS: int - 0 on success
2186 * !0 otherwise.
2187 *
2188 * PURPOSE: Helper which updates the input list of disks by removing
2189 * those which have slices used by the input volume.
2190 *
2191 * Constructs a new list containing only disks not used by
2192 * the volume.
2193 *
2194 * The original list is freed.
2195 */
2196 static int
remove_used_disks(dlist_t ** disks,devconfig_t * volume)2197 remove_used_disks(
2198 dlist_t **disks,
2199 devconfig_t *volume)
2200 {
2201 dlist_t *list = NULL;
2202 dlist_t *iter = NULL;
2203 dlist_t *item = NULL;
2204 int error = 0;
2205
2206 for (iter = *disks; (iter != NULL) && (error == 0); iter = iter->next) {
2207
2208 dm_descriptor_t diskp = (uintptr_t)iter->obj;
2209 boolean_t shares = B_FALSE;
2210
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);
2218 }
2219 }
2220 }
2221
2222 if (error != 0) {
2223 dlist_free_items(list, NULL);
2224 } else {
2225
2226 /* free original disk list, return new list */
2227 dlist_free_items(*disks, NULL);
2228
2229 *disks = list;
2230 }
2231
2232 return (error);
2233 }
2234
2235 /*
2236 * FUNCTION: volume_shares_disk(dm_descriptor_t disk,
2237 * devconfig_t *volume, boolean_t *shares)
2238 *
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
2242 *
2243 * RETURNS: int - 0 on success
2244 * !0 otherwise
2245 *
2246 * PURPOSE: Determines if the input disk has a slice that is used
2247 * as a component by the input volume.
2248 *
2249 * If the disk contributes a slice component, bool is set
2250 * to B_TRUE, B_FALSE otherwise.
2251 */
2252 static int
volume_shares_disk(dm_descriptor_t disk,devconfig_t * volume,boolean_t * shares)2253 volume_shares_disk(
2254 dm_descriptor_t disk,
2255 devconfig_t *volume,
2256 boolean_t *shares)
2257 {
2258 dlist_t *iter = NULL;
2259 int error = 0;
2260
2261 *shares = B_FALSE;
2262
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) {
2267
2268 devconfig_t *dev = (devconfig_t *)iter->obj;
2269
2270 if (devconfig_isA(dev, TYPE_SLICE)) {
2271
2272 /* get disk for volume's slice */
2273 dm_descriptor_t odisk = NULL;
2274 char *oname = NULL;
2275
2276 ((error = devconfig_get_name(dev, &oname)) != 0) ||
2277 (error = get_disk_for_named_slice(oname, &odisk));
2278
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;
2284 }
2285 }
2286 }
2287 }
2288
2289 return (error);
2290 }
2291
2292 /*
2293 * FUNCTION: select_mpxio_hbas(dlist_t *hbas, dlist_t **mpxio_hbas)
2294 *
2295 * INPUT: hbas - pointer to a list of dm_descriptor_t HBA handles
2296 *
2297 * OUTPUT: mpxio_hbas - pointer to a new list of containing HBAs that
2298 * are multiplex enabled.
2299 *
2300 * RETURNS: int - 0 on success
2301 * !0 otherwise.
2302 *
2303 * PURPOSE: Iterates the input list of HBAs and builds a new list
2304 * containing those that are multiplex enabled.
2305 *
2306 * The output list should be passed to dlist_free_items()
2307 * when no longer needed.
2308 */
2309 static int
select_mpxio_hbas(dlist_t * hbas,dlist_t ** mpxio_hbas)2310 select_mpxio_hbas(
2311 dlist_t *hbas,
2312 dlist_t **mpxio_hbas)
2313 {
2314 dlist_t *iter;
2315 int error = 0;
2316
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;
2328 }
2329 }
2330 }
2331 }
2332
2333 if (error != 0) {
2334 dlist_free_items(*mpxio_hbas, NULL);
2335 *mpxio_hbas = NULL;
2336 }
2337
2338 return (error);
2339 }
2340
2341 /*
2342 * FUNCTION: set_explicit_submirror_names(dlist_t *reqs, dlist_t *subs)
2343 *
2344 * INPUT: reqs - pointer to a list of request devconfig_ts
2345 * subs - pointer to a list of volume devconfig_ts
2346 *
2347 * SIDEEFFECT: Modifies the volume names.
2348 *
2349 * RETURNS: int - 0 on success
2350 * !0 otherwise.
2351 *
2352 * PURPOSE: Iterates the lists of volumes and requests and calls
2353 * set_explicit_mirror_name for each pair.
2354 */
2355 static int
set_explicit_submirror_names(dlist_t * reqs,dlist_t * subs)2356 set_explicit_submirror_names(
2357 dlist_t *reqs,
2358 dlist_t *subs)
2359 {
2360 int error = 0;
2361
2362 while ((reqs != NULL) && (subs != NULL) && (error == 0)) {
2363
2364 error = set_explicit_submirror_name(
2365 (devconfig_t *)reqs->obj,
2366 (devconfig_t *)subs->obj);
2367
2368 reqs = reqs->next;
2369 subs = subs->next;
2370 }
2371
2372 return (error);
2373 }
2374
2375 /*
2376 * FUNCTION: set_explicit_submirror_name(dlist_t *req, dlist_t *sub)
2377 *
2378 * INPUT: req - pointer to a request devconfig_t
2379 * sub - pointer to a volume devconfig_t
2380 *
2381 * SIDEEFFECT: Modifies the volume name.
2382 *
2383 * RETURNS: int - 0 on success
2384 * !0 otherwise.
2385 *
2386 * PURPOSE: Clears the volume's current name and returns the name
2387 * to the available pool.
2388 *
2389 * If a name is specified in the request, the name is used
2390 * as the volume's name.
2391 *
2392 * (Unnamed submirrors will have default names assigned
2393 * during final mirror assembly.)
2394 */
2395 static int
set_explicit_submirror_name(devconfig_t * req,devconfig_t * sub)2396 set_explicit_submirror_name(
2397 devconfig_t *req,
2398 devconfig_t *sub)
2399 {
2400 char *name = NULL;
2401 int error = 0;
2402
2403 /* unset current submirror name */
2404 (void) devconfig_get_name(sub, &name);
2405 release_volume_name(name);
2406 (void) devconfig_set_name(sub, "");
2407
2408 if (devconfig_get_name(req, &name) != ERR_ATTR_UNSET) {
2409 (void) devconfig_set_name(sub, name);
2410 }
2411
2412 return (error);
2413 }
2414