/*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <libintl.h>
#include "libdiskmgt.h"
#include "volume_error.h"
#include "volume_defaults.h"
#include "volume_devconfig.h"
#include "volume_dlist.h"
#include "volume_output.h"
#include "volume_request.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_svm_util.h"
#define _LAYOUT_CONCAT_C
static int
devconfig_t **concat);
static int
devconfig_t **concat);
/*
* FUNCTION: layout_concat(devconfig_t *request, uint64_t nbytes,
* dlist_t **results)
*
* INPUT: request - pointer to a devconfig_t of the current request
* nbytes - the desired capacity of the concat
*
* OUPUT: results - pointer to a list of composed volumes
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Main layout driver for composing concat volumes.
*
* Attempts to construct a concat of size nbytes.
*
* Several different layout strategies are tried in order
* of preference until one succeeds or there are none left.
*
* 1 - concat within an HBA
* . requires sufficient space available on the HBA
*
* 2 - concat across all available similar HBAs
*
* 3 - concat across all available HBAs
*
* get available HBAs
*
* group HBAs by characteristics
* for (each HBA grouping) and (concat not composed) {
* select next HBA group
* for (strategy[1,2]) and (concat not composed) {
* compose concat using HBAs in group
* }
* }
*
* if (concat not composed) {
* for (strategy[3]) and (concat not composed) {
* compose concat using all HBAs
* }
* }
*
* if (concat composed) {
* append composed concat to results
* }
*/
int
{
/*
* these enums define the # of strategies and the preference order
* in which they are tried
*/
typedef enum {
typedef enum {
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 = CONCAT_WITHIN_SIMILAR_HBA;
(order < N_SIMILAR_HBA_STRATEGIES) &&
order++) {
switch (order) {
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 1: use disks from a single HBA - concat within HBA\n"));
/* END CSTYLED */
}
break;
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 2: use disks from all similar HBAs - concat across HBAs\n"));
/* END CSTYLED */
}
break;
default:
break;
}
}
}
}
/* try all HBAs */
for (order = CONCAT_ACROSS_ANY_HBAS;
(order < N_ANY_HBA_STRATEGIES) &&
order++) {
switch (order) {
case CONCAT_ACROSS_ANY_HBAS:
if (error == 0) {
/* BEGIN CSTYLED */
gettext(" -->Strategy 3: use disks from all available HBAs - concat across HBAs\n"));
/* END CSTYLED */
}
break;
default:
break;
}
}
}
} else {
}
} else if (error != 0) {
} else {
error = -1;
}
return (error);
}
static int
{
int error = 0;
char *name;
/* check for sufficient space on the HBA */
if (error == 0) {
} else {
}
}
}
return (error);
}
/*
* FUNCTION: populate_concat(devconfig_t *request, uint64_t nbytes,
* dlist_t *disks, dlist_t *othervols,
* devconfig_t **concat)
*
* INPUT: request - pointer to a request devconfig_t
* nbytes - desired concat size
* disks - pointer to a list of availalb disks
* othervols - pointer to a list of other volumes whose
* composition may affect this concat
* (e.g., submirrors of the same mirror)
*
* OUTPUT: concat - pointer to a devconfig_t to hold resulting concat
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper to populate a concat with the specified aggregate
* capacity using slices on disks in the input list.
*
* If the othervols list is not empty, the slice components
* chosen for the concat must not on the same disks as any
* of the other volumes.
*
* If sufficient slice components can be found, the concat
* is assembled and returned.
*/
int
{
int error = 0;
if (error != 0) {
return (error);
}
return (0);
}
/* determine HBAs and disks used by othervols */
&other_hbas, &other_disks);
if (error != 0) {
return (error);
}
/* BEGIN CSTYLED */
/*
* 1st B_TRUE: require a different disk than those used by
* comps and othervols
* 1st B_FALSE: slice with size less that requested is acceptable
* 2nd B_FALSE: do not add an extra cylinder when resizing slice,
* this is only necessary for Stripe components whose sizes
* get rounded down to an interlace multiple and then down
* to a cylinder boundary.
*
*/
/* END CSTYLED */
} else {
/* add selected component to comp list */
/* remove it from the available list */
}
/* add the component slice to the used list */
}
/* increment concat's capacity */
if ((error == 0) &&
}
}
} else {
/* no possible slice */
break;
}
}
if (error == 0) {
} else {
/* undo any slicing done for the concat */
}
} else if (error == 0) {
if (capacity > 0) {
} else {
}
}
return (error);
}
/*
* FUNCTION: populate_explicit_concat(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 concat request that specifies explicit
* slice components.
*
* The components have already been validated and reserved,
* all that is required is to create devconfig_t structs
* for each requested slice.
*
* The net size of the concat is determined by the slice
* components.
*
* The concat devconfig_t is assembled and appended to the
* results list.
*
* This function is also called from
* layout_mirror.populate_explicit_mirror()
*/
int
{
int error = 0;
/* assemble components */
/* slice components have been validated */
/* turn each into a devconfig_t */
if (error == 0) {
} else {
}
}
}
if (error == 0) {
}
if (error == 0) {
} else {
}
} else {
}
return (error);
}
/*
* FUNCTION: assemble_concat(devconfig_t *request, dlist_t *comps,
* devconfig_t **concat)
*
* INPUT: request - pointer to a devconfig_t of the current request
* comps - pointer to a list of slice components
*
* OUPUT: concat - pointer to a devconfig_t to hold final concat
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which creates and populates a concat devconfig_t
* struct using information from the input request and the
* list of slice components.
*
* Determines the name of the concat either from the request
* or from the default naming scheme.
*
* Attaches the input list of components to the devconfig.
*/
static int
{
int error = 0;
/* set concat name, use requested name if specified */
if (error != ERR_ATTR_UNSET) {
} else {
error = 0;
}
}
if (error == 0) {
TYPE_CONCAT)) == 0) {
}
} else {
}
}
}
if (error == 0) {
/* compute and save true size of concat */
if (error == 0) {
&comp_nblks)) == 0) {
nblks += comp_nblks;
}
}
if (error == 0) {
}
}
}
if (error == 0) {
} else {
}
return (error);
}