/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <libintl.h>
#include "volume_error.h"
#include "volume_dlist.h"
#include "volume_output.h"
#include "layout_concat.h"
#include "layout_device_cache.h"
#include "layout_device_util.h"
#include "layout_discovery.h"
#include "layout_dlist_util.h"
#include "layout_messages.h"
#include "layout_request.h"
#include "layout_slice.h"
#include "layout_stripe.h"
#include "layout_svm_util.h"
#define _LAYOUT_MIRROR_C
static int layout_stripe_submirrors(
static int layout_concat_submirrors(
static int compose_stripe_per_hba(
static int compose_stripes_across_hbas(
static int compose_stripes_within_hba(
static int compose_concat_per_hba(
static int compose_concats_across_hbas(
static int compose_concats_within_hba(
static int assemble_mirror(
devconfig_t **mirror);
static int remove_used_disks(
static int volume_shares_disk(
boolean_t *bool);
static int select_mpxio_hbas(
dlist_t **mpxio_hbas);
static int set_explicit_submirror_names(
static int set_explicit_submirror_name(
devconfig_t *sub);
/*
* FUNCTION: layout_mirror(devconfig_t *request, nbytes, dlist_t **results)
*
* INPUT: request - pointer to a request devconfig_t
* nsubs - number of submirrors
* nbytes - desired mirror size
*
* OUTPUT: results - pointer to a list of volume devconfig_t results
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Main driver to handle a mirror request that does not specify
* subcomponents.
*
* Striped submirrors are tried first, then concats.
*/
int
{
int error = 0;
if (error != ERR_ATTR_UNSET) {
return (error);
}
error = 0;
}
/* prefer stripe submirrors */
if ((error = layout_stripe_submirrors(
return (error);
}
/* second chance: mirrored concats */
if ((error = layout_concat_submirrors(
return (error);
}
}
/* unset submirror names prior to final assembly */
}
if (error == 0) {
} else {
/* remember submirrors that need HSPs */
}
}
} else {
/* cleanup submirrors */
}
} else if (error != 0) {
} else {
error = -1;
}
return (error);
}
/*
* FUNCTION: populate_explicit_mirror(devconfig_t *request,
* dlist_t **results)
*
* INPUT: request - pointer to a request devconfig_t
*
* OUTPUT: results - pointer to a list of volume devconfig_t results
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Processes the input mirror request specifying explicit layout
* constraints on the submirrors.
*
* Primary submirror constraint is explicit type, either
* stripe or concat. Submirror types may be mixed.
*
* Submirror sizes or components may be specified explicitly.
*
* If the mirror does not specify a size, assume the first explicit
* submirror size is the desired size. If a submirror does not
* specify a size or components, use the mirror size.
*
* Scan the submirror requests: those with specific components
* get assembled as encountered. The remainder are grouped by
* type and handled by layout_stripe_submirrors() or
* layout_concat_submirrors().
*
* If all specified submirrors can be assembled, the final mirror
* is assembled and appended to the results list.
*/
int
{
int nsubs = 0;
int error = 0;
if (error != ERR_ATTR_UNSET) {
return (error);
}
error = 0;
}
if (error == ERR_ATTR_UNSET) {
error = 0;
msize = 0;
} else {
return (error);
}
}
/*
* Scan the list of specified submirrors, collect those that only
* specify size (or no size). Process those with explicit components
* immediately.
*/
/* components specified */
if (ctype == TYPE_STRIPE) {
} else {
}
if (error == 0) {
}
} else {
/* no components specified */
/* if no size is specified, it needs to be inferred */
if (msize == 0) {
/* mirror specified no size, first explicit submirror */
/* size is assumed to be the desired mirror size */
}
if (csize == 0) {
/* this submirror specified no size, use mirror size */
}
break;
}
if (ctype == TYPE_STRIPE) {
} else {
}
}
}
/* compose stripes specified by size */
if ((error = layout_stripe_submirrors(
/* adjust stripe names */
} else {
/* these stripes failed, skip concats_by_size */
}
}
/* compose concats specified by size */
if ((error = layout_concat_submirrors(
/* adjust concat names */
} else {
/* these concats failed */
}
}
/* assemble final mirror */
} else {
}
}
}
} else if (error != 0) {
} else {
error = -1;
}
return (error);
}
/*
* FUNCTION: assemble_mirror(devconfig_t *request, dlist_t *subs,
* devconfig_t **mirror)
*
* INPUT: request - pointer to a devconfig_t of the current request
* subs - pointer to a list of composed submirrors
*
* OUPUT: mirror - pointer to a devconfig_t to hold final mirror
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which creates and populates a mirror devconfig_t
* struct using information from the input request and the
* list of submirror components.
*
* Determines the name of the mirror either from the request
* or from the default naming scheme and assigns names to
* unnamed submirrors according to the default naming scheme.
*
* Sets the read and write strategies, and the resync pass
* number for the mirror if values are specified in the request.
*
* Attaches the input list of submirrors to the devconfig.
*/
static int
{
int error = 0;
/* set stripe name, use requested name if specified */
if (error != ERR_ATTR_UNSET) {
} else {
error = 0;
}
}
if (error == 0) {
TYPE_MIRROR)) == 0) {
/* get name for generating submirror names below */
}
} else {
}
}
}
/* assign name to any unnamed submirror */
(*subname == '\0')) {
}
}
if (error == 0) {
} else if (error == ERR_ATTR_UNSET) {
error = 0;
}
}
if (error == 0) {
} else if (error == ERR_ATTR_UNSET) {
error = 0;
}
}
if (error == 0) {
} else if (error == ERR_ATTR_UNSET) {
error = 0;
}
}
/* arrange submirrors in ascending size order */
if (error == 0) {
}
}
if (error == 0) {
} else {
}
return (error);
}
/*
* FUNCTION: layout_stripe_submirrors(devconfig_t *request, dlist_t *cursubs,
* uint64_t nbytes, uint16_t nsubs, dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* these may affect disk and HBA choices for new
* submirrors being composed and are passed along
* into the component selection functions.
* nbytes - the desired capacity for the stripes
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Main layout driver for composing stripe submirrors.
*
* Attempts to construct nsub submirrors of size nbytes.
*
* Several different layout strategies are tried in order
* of preference until one succeeds or there are none left.
*
* 1 - mirror with all stripes on the MPXIO "controller"
* . requires MPXIO to be enabled
* . requires nsubs * mincomp available disks on the
* MPXIO HBA
*
* 2 - mirror with stripes within separate HBAs of same type
* . requires nsubs HBAs with mincomp disks
* . stripe width is driven by number of disks on HBA
*
* 3 - mirror with stripes across HBAs of same type
* . requires mincomp HBAs with nsubs disks
* (each stripe has a disk per HBA)
* . stripe width is driven by number of HBAs
*
* 4 - mirror with stripes within separate HBAs of mixed type
* . requires nsubs HBAs with mincomp disks
* . stripe width is driven by number of disks on HBA
*
* 5 - mirror with stripes across HBAs of mixed type
* . requires mincomp HBAs with nsubs disks
* (each stripe has a disk per HBA)
* . stripe width is driven by number of HBAs
*
* 6 - mirror with all stripes within the same HBA
* . requires an HBA with mincomp * nsubs disks
*
* get available HBAs
*
* group HBAs by characteristics
* for (each HBA grouping) and (nsub stripes not composed) {
* select next HBA group
* for (strategy[1,2,3]) and (nsub stripes not composed) {
* compose nsub stripes using HBAs in group
* }
* }
*
* if (nsub stripes not composed) {
* for (strategy[4,5,6]) and (nsub stripes not composed) {
* compose nsub stripes using all HBAs
* }
* }
*
* if (all stripes composed) {
* append composed stripes to results
* }
*
*/
static int
{
/*
* these enums define the # of strategies and the preference order
* in which they are tried
*/
typedef enum {
ALL_STRIPES_ON_MPXIO = 0,
typedef enum {
STRIPE_PER_ANY_HBA = 0,
int error = 0;
if (error != 0) {
return (error);
}
if (dlist_length(usable_hbas) == 0) {
return (-1);
}
/*
* based on the request, the diskset defaults or the
* global defaults. These are absolute limits, the
* actual values are determined by the number of HBAs
*/
if (error != 0) {
return (error);
}
for (iter = similar_hba_groups;
for (order = ALL_STRIPES_ON_MPXIO;
(order < N_SIMILAR_HBA_STRATEGIES) &&
order++) {
int n = 0;
switch (order) {
case ALL_STRIPES_ON_MPXIO:
if (is_mpxio_enabled() == B_TRUE) {
/* see if any HBA supports MPXIO */
/* BEGIN CSTYLED */
gettext(" -->Strategy 1: use %d-%d MPXIO disks\n"),
/* END CSTYLED */
/* see if MPXIO HBA has enough disks */
} else {
}
}
}
break;
case STRIPE_PER_SIMILAR_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 2: use %d-%d disks from %d similar HBAs - stripe per HBA\n"),
/* END CSTYLED */
} else {
}
}
break;
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 3: use %d disks from %d-%d similar HBAs - stripe across HBAs \n"),
/* END CSTYLED */
} else {
}
}
break;
default:
break;
}
}
}
}
/* retry using all available HBAs */
for (order = STRIPE_PER_ANY_HBA;
(order < N_ANY_HBA_STRATEGIES) &&
order++) {
int n = 0;
switch (order) {
case STRIPE_PER_ANY_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 4: use %d-%d disks from any %d HBAs - stripe per HBA\n"),
/* END CSTYLED */
} else {
}
}
break;
case STRIPE_ACROSS_ANY_HBAS:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 5: use %d disks from %d-%d HBAs - stripe across HBAs \n"),
/* END CSTYLED */
} else {
}
}
break;
case STRIPE_WITHIN_ANY_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 6: use %d-%d disks from any single HBA - %d stripes within HBA\n"),
/* END CSTYLED */
if ((n = dlist_length(selhbas)) > 0) {
} else {
}
}
break;
default:
break;
}
}
}
if (error == 0) {
}
return (error);
}
/*
* FUNCTION: layout_concat_submirrors(devconfig_t *request, dlist_t *cursubs,
* uint64_t nbytes, uint16_t nsubs, dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* nbytes - the desired capacity for the concats
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Main layout driver for composing concat submirrors.
*
* Attempts to construct nsub submirrors of size nbytes.
*
* Several different layout strategies are tried in order
* of preference until one succeeds or there are none left.
*
* 1 - mirror with all concats on the MPXIO "controller"
* . requires MPXIO to be enabled
* . requires nsubs available disks on the MPXIO HBA
*
* 2 - mirror with concats on separate HBAs of same type
* . requires nsubs HBAs with available disks
*
* 3 - mirror with concats across HBAs of same type
* . requires an HBA with at least 1 available disk
*
* 4 - mirror with concats on separate HBAs of mixed type
* . requires nsubs HBAs with available disks
*
* 5 - mirror with concats across HBAs of mixed type
* . requires an HBA with at least 1 available disk
*
* 6 - mirror with all concats on the same HBA
* . requires an HBA with at least nsubs available disks
*
* get available HBAs
*
* group HBAs by characteristics
* for (each HBA grouping) and (nsub concats not composed) {
* select next HBA group
* for (strategy[1,2,3]) and (nsub concats not composed) {
* compose nsub concats, nbytes in size
* }
* }
*
* if (nsub concats not composed) {
* for (strategy[4,5,6]) and (nsub concats not composed) {
* compose nsub concats, nbytes in size
* }
* }
*
* if (all concats composed) {
* append composed concats to results
* }
*
*/
static int
{
/*
* these enums define the # of strategies and the preference order
* in which they are tried
*/
typedef enum {
ALL_CONCATS_ON_MPXIO = 0,
typedef enum {
CONCAT_PER_ANY_HBA = 0,
int error = 0;
if (error != 0) {
return (error);
}
if (dlist_length(usable_hbas) == 0) {
return (-1);
}
if (error != 0) {
return (error);
}
for (iter = similar_hba_groups;
for (order = ALL_CONCATS_ON_MPXIO;
(order < N_SIMILAR_HBA_STRATEGIES) &&
order++) {
int n = 0;
switch (order) {
case ALL_CONCATS_ON_MPXIO:
if (is_mpxio_enabled() == B_TRUE) {
/* see if any HBA supports MPXIO */
/* BEGIN CSTYLED */
gettext(" -->Strategy 1: use at least %d MPXIO disks\n"),
nsubs);
/* END CSTYLED */
/* see if MPXIO HBA has enough disks */
if ((error == 0) &&
((n = dlist_length(selhbas)) > 0)) {
} else {
}
}
}
break;
case CONCAT_PER_SIMILAR_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 2: use any disks from %d similar HBAs - concat per HBA\n"),
nsubs);
/* END CSTYLED */
} else {
}
}
break;
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 3: use any disks from any similar HBAs - "
"%d concats across HBAs\n"),
nsubs);
/* END CSTYLED */
}
break;
default:
break;
}
}
}
}
/* retry using all available HBAs */
for (order = CONCAT_PER_ANY_HBA;
(order < N_ANY_HBA_STRATEGIES) &&
order++) {
int n = 0;
switch (order) {
case CONCAT_PER_ANY_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 4: use any disks from %d HBAs - concat per HBA\n"),
nsubs);
/* END CSTYLED */
} else {
}
}
break;
case CONCAT_ACROSS_ANY_HBAS:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 5: use any disks from any HBA - %d concats across HBAs\n"),
nsubs);
/* END CSTYLED */
}
break;
case CONCAT_WITHIN_ANY_HBA:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 6: use any disks from any single HBA - %d concats within an HBA\n"),
nsubs);
/* END CSTYLED */
if ((n = dlist_length(selhbas)) > 0) {
} else {
}
}
break;
default:
break;
}
}
}
if (error == 0) {
}
return (error);
}
/*
* FUNCTION: compose_stripe_per_hba(devconfig_t *request,
* dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
* uint16_t nsubs, int maxcomp, int mincomp,
* dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* nbytes - the desired capacity for the stripes
* nsubs - the desired number of stripes
* maxcomp - the maximum number of stripe components
* mincomp - the minimum number of stripe components
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of stripes
* of the desired size using available disks on any of the HBAs
* from the input list.
*
* The number of components within the composed stripes will be
* in the range of mincomp to ncomp, preferring more components
* over fewer. All stripes composed by a single call to this
* function will have the same number of components.
*
* Each stripe will use disks from a single HBA.
*
* All input HBAs are expected to have at least mincomp available
* disks.
*
* If the stripes can be composed, they are appended to the list
* of result volumes.
*
* while (more HBAs and more stripes to compose) {
* select next HBA
* get available space for this HBA
* get available disks for this HBA
* if (not enough space or disks) {
* continue
* }
*
* use # disks as # of stripe components - limit to maxcomp
* for ((ncomps downto mincomp) && (more stripes to compose)) {
* while (more stripes to compose) {
* if a stripe can be composed using disks {
* save stripe
* increment stripe count
* }
* while (more HBAs and more stripes to compose) {
* select next HBA
* get available space for this HBA
* get available disks for this HBA
* if (not enough space or disks) {
* continue
* }
* if a stripe can be composed using disks {
* save stripe
* increment stripe count
* }
* }
*
* if (not all stripes composed) {
* delete any compose stripes
* }
* }
* }
*
* if (not all stripes composed) {
* delete any stripes composed
* }
* }
*
* if (not all stripes composed) {
* delete any stripes composed
* }
*
* append composed stripes to results
*/
static int
{
int error = 0;
gettext(" --->Trying to compose %d Stripes with "
"%d-%d components on separate HBAs.\n"),
int ncomp = 0;
char *name;
if (error != 0) {
continue;
}
/* check for sufficient space and minimum # of disks */
continue;
}
continue;
}
/* make the stripe as wide as possible, up to maxcomp */
ncomp--) {
int count = 0;
/* try composing nsubs stripes with ncomp components */
/* build first stripe using disks on this HBA */
/* first stripe failed at the current width */
/* break while loop and try a different width */
break;
}
/* composed a stripe */
break;
}
++count;
/* compose stripes on remaining HBAs */
if (error != 0) {
continue;
}
continue;
}
/* prepare to compose another */
if ((item = dlist_new_item(
break;
}
++count;
}
}
/*
* no HBAs remain and haven't composed
* enough stripes at the current width.
* break while loop and try another width.
*/
break;
}
}
/*
* stripe composition at current width failed...
* prepare to try a narrower width.
* NB: narrower widths may work since some HBA(s)
* may have fewer available disks
*/
}
}
}
if (error == 0) {
} else {
}
return (error);
}
/*
* FUNCTION: compose_stripes_across_hbas(devconfig_t *request,
* dlist_t *cursubs, dlist_t *hbas, dlist_t *disks,
* uint64_t nbytes, uint16_t nsubs, int maxcomp,
* int mincomp, dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* disks - pointer to a list of available disks on the HBAs
* nbytes - the desired capacity for the stripes
* nsubs - the desired number of stripes
* ncomp - the maximum number of stripe components
* mincomp - the minimum number of stripe components
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of stripes
* of the desired size using available disks on any of the HBAs
* from the input list.
*
* The number of components within the composed stripes will be
* in the range of mincomp to ncomp, preferring more components
* over fewer. All stripes composed by a single call to this
* function will have the same number of components.
*
* Each stripe will use a disk from several different HBAs.
*
* All input HBAs are expected to have at least nsubs available
* disks.
*
* If the stripes can be composed, they are appended to the list
* of result volumes.
*
* for (ncomps downto mincomp) {
*
* copy the input disk list
* while (more stripes to compose) {
* if a stripe can be composed using disks {
* save stripe
* remove used disks from disk list
* increment stripe count
* } else
* end while loop
* }
*
* free copied disk list
* if (not all stripes composed) {
* delete any stripes composed
* decrement ncomps
* }
* }
*
* if (not all stripes composed) {
* delete any stripes composed
* }
*
* append composed stripes to results
*/
static int
{
int error = 0;
int count = 0;
gettext(" --->Trying to compose %d Stripes with "
"%d components across %d HBAs.\n"),
/* copy disk list, it is modified by the while loop */
} else {
}
}
/* compose nsubs stripe submirrors of ncomp components */
} else {
++count;
}
break;
}
}
/* free copy of disk list */
disks_copy = NULL;
/* failed to compose enough stripes at this width, */
/* prepare to try again with the next narrower width. */
count = 0;
--ncomp;
}
}
} else {
}
return (error);
}
/*
* FUNCTION: compose_stripes_within_hba(devconfig_t *request,
* dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
* uint16_t nsubs, int maxcomp, int mincomp,
* dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* nbytes - the desired capacity for the stripes
* nsubs - the desired number of stripes
* maxcomp - the maximum number of stripe components
* mincomp - the minimum number of stripe components
* nsubs - the number of stripes to be composed
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of stripes
* of the desired size using available disks within any single
* HBA from the input list.
*
* The number of components within the composed stripes will be
* in the range of mincomp to maxcomp, preferring more components
* over fewer. All stripes composed by a single call to this
* function will have the same number of components.
*
* All stripes will use disks from a single HBA.
*
* All input HBAs are expected to have at least nsubs * mincomp
* available disks and total space sufficient for subs stripes.
*
* If the stripes can be composed, they are appended to the list
* of result volumes.
*
* while (more HBAs and more stripes need to be composed) {
* select next HBA
* if (not enough available space on this HBA) {
* continue;
* }
* get available disks for HBA
* use # disks as # of stripe components - limit to maxcomp
* for (ncomps downto mincomp) {
* if ((ncomps * nsubs) > ndisks) {
* continue;
* }
* while (more stripes need to be composed) {
* if a stripe can be composed using disks {
* save stripe
* remove used disks from disk list
* } else
* end while loop
* }
* if (not all stripes composed) {
* delete any stripes composed
* }
* }
* }
*
* if (not all stripes composed) {
* delete any stripes composed
* }
*
* append composed stripes to results
*/
static int
{
int error = 0;
int count = 0;
int ndisks = 0;
int ncomp = 0;
if (error != 0) {
continue;
}
continue;
}
/*
* try composing stripes from ncomp down to mincomp.
* stop when nsubs stripes have been composed, or when the
* minimum stripe width has been tried
*/
ncomp--) {
gettext(" --->Trying to compose %d Stripes with "
"%d components on a single HBA.\n"),
continue;
}
/* try composing nsubs stripes, each ncomp wide */
} else {
}
break;
}
}
/* failed to compose enough stripes at this width, */
/* prepare to try again with fewer components */
}
}
}
}
return (error);
}
/*
* FUNCTION: compose_concats_per_hba(devconfig_t *request,
* dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
* uint16_t nsubs, dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* nbytes - the desired capacity for the concats
* nsubs - the number of concats to be composed
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of concats
* of the desired size using available disks within HBAs from the
* input list. Each concat will be composed using disks from a
* single HBA.
*
* If the concats can be composed, they are appended to the list
* of result volumes.
*
* while (more HBAs AND more concats need to be composed) {
* if (not enough available space on this HBA) {
* continue;
* }
*
* get available disks for HBA
* if (concat can be composed) {
* save concat
* increment count
* }
* }
*
* if (not all stripes composed) {
* delete any concats composed
* }
*
* append composed concats to results
*/
static int
{
int error = 0;
int count = 0;
gettext(" --->Trying to compose %d Concats on "
"separate HBAs.\n"), nsubs);
}
} else {
++count;
}
}
}
} else {
}
return (error);
}
/*
* FUNCTION: 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)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* disks - pointer to a list of available disks on the HBAs
* nbytes - the desired capacity for the concats
* nsubs - the number of concats to be composed
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of concats
* of the desired size using any available disks from the input
* list of available HBAs.
*
* If the concats can be composed, they are appended to the list
* of result volumes.
*
* copy the input disk list
* while (more concats need to be composed) {
* if (a concat can be composed using remaining disks) {
* save concat
* remove used disks from disk list
* increment count
* } else {
* end while loop
* }
* }
*
* if (not all concats composed) {
* delete any concats composed
* }
*
* append composed concats to results
*/
static int
{
int error = 0;
int count = 0;
/* copy disk list, it is modified by the while loop */
} else {
}
}
} else {
count++;
}
break;
}
}
/* free copy of disk list */
disks_copy = NULL;
} else {
}
return (error);
}
/*
* FUNCTION: compose_concats_within_hba(devconfig_t *request,
* dlist_t *cursubs, dlist_t *hbas, uint64_t nbytes,
* uint16_t nsubs, dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* cursubs - pointer to a list of already composed submirrors
* hbas - pointer to a list of available HBAs
* nbytes - the desired capacity for the concats
* nsubs - the number of concats to be composed
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Layout function which composes the requested number of concats
* of the desired size using available disks within any single
* HBA from the input list.
*
*
* HBAs in the list are expected to have at least 2 available
* disks and total space sufficient for the submirrors.
*
* If the concats can be composed, they are appended to the list
* of result volumes.
*
* while (more HBAs) {
* if (not enough available space on this HBA) {
* continue;
* }
*
* get available disks for HBA
* while (more concats need to be composed) {
* if a concat can be composed using disks {
* save concat
* remove used disks from disk list
* increment count
* } else {
* delete any concats composed
* end while loop
* }
* }
* }
*
* if (not all concats composed) {
* delete any concats composed
* }
*
* append composed concats to results
*/
static int
{
int error = 0;
int count = 0;
gettext(" --->Trying to compose %d Concats within "
"a single HBA.\n"), nsubs);
/* try composing nsubs concats all on this HBA */
count = 0;
} else {
count++;
}
break;
}
}
}
}
} else {
}
return (error);
}
/*
* FUNCTION: remove_used_disks(dlist_t **disks, devconfig_t *volume)
*
* INPUT: disks - pointer to a list of disks
* volume - pointer to a devconfig_t volume
*
* OUPUT: disks - pointer to new list of disks
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which updates the input list of disks by removing
* those which have slices used by the input volume.
*
* Constructs a new list containing only disks not used by
* the volume.
*
* The original list is freed.
*/
static int
{
int error = 0;
/* disk is unused */
} else {
}
}
}
if (error != 0) {
} else {
/* free original disk list, return new list */
}
return (error);
}
/*
* FUNCTION: volume_shares_disk(dm_descriptor_t disk,
* devconfig_t *volume, boolean_t *shares)
*
* INPUT: disk - a dm_descriptor_t handle for the disk of interest
* volume - a devconfig_t pointer to a volume
* bool - a boolean_t pointer to hold the result
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Determines if the input disk has a slice that is used
* as a component by the input volume.
*
* If the disk contributes a slice component, bool is set
* to B_TRUE, B_FALSE otherwise.
*/
static int
{
int error = 0;
/* look at all slices in the volume */
/* get disk for volume's slice */
if (error == 0) {
/* otherslice is on same disk, stop */
}
}
}
}
return (error);
}
/*
* FUNCTION: select_mpxio_hbas(dlist_t *hbas, dlist_t **mpxio_hbas)
*
* INPUT: hbas - pointer to a list of dm_descriptor_t HBA handles
*
* OUTPUT: mpxio_hbas - pointer to a new list of containing HBAs that
* are multiplex enabled.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Iterates the input list of HBAs and builds a new list
* containing those that are multiplex enabled.
*
* The output list should be passed to dlist_free_items()
* when no longer needed.
*/
static int
{
int error = 0;
*mpxio_hbas =
} else {
}
}
}
}
if (error != 0) {
*mpxio_hbas = NULL;
}
return (error);
}
/*
* FUNCTION: set_explicit_submirror_names(dlist_t *reqs, dlist_t *subs)
*
* INPUT: reqs - pointer to a list of request devconfig_ts
* subs - pointer to a list of volume devconfig_ts
*
* SIDEEFFECT: Modifies the volume names.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Iterates the lists of volumes and requests and calls
* set_explicit_mirror_name for each pair.
*/
static int
{
int error = 0;
}
return (error);
}
/*
* FUNCTION: set_explicit_submirror_name(dlist_t *req, dlist_t *sub)
*
* INPUT: req - pointer to a request devconfig_t
* sub - pointer to a volume devconfig_t
*
* SIDEEFFECT: Modifies the volume name.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Clears the volume's current name and returns the name
* to the available pool.
*
* If a name is specified in the request, the name is used
* as the volume's name.
*
* (Unnamed submirrors will have default names assigned
* during final mirror assembly.)
*/
static int
{
int error = 0;
/* unset current submirror name */
}
return (error);
}