xref: /titanic_41/usr/src/cmd/lvm/metassist/layout/layout_mirror.c (revision b6c8bd52ccb0f3491c2bd1f5867985cef630564a)
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