meta_stripe.c revision b2178a54bfad47b786da1c125ad5c89bbffb0a03
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Just in case we're not in a build environment, make sure that
* TEXT_DOMAIN gets set to something.
*/
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
/*
* stripe operations
*/
#include <limits.h>
#include <stdlib.h>
#include <meta.h>
#define QUOTE(x) #x
/*
*/
int
)
{
size,
/* should have same set */
/* the old device binding is now established */
}
return (-1);
return (-1);
return (-1);
return (-1);
}
/* In dryrun mode (DOIT not set) we must not alter the mddb */
if (options & MDCMD_DOIT) {
return (-1);
}
/*
* There is no need to call meta_fixdevid() here as this function is
* only called by the metareplace -c command which actually does
* nothing (in terms of a resync) and thus does nothing with the devid.
*/
/* Is this just a dryrun ? */
if ((options & MDCMD_DOIT) == 0) {
}
if (label == 0)
else
if (options & MDCMD_DOIT)
}
if (options & MDCMD_PRINT) {
"%s: device %s is replaced with %s\n"),
}
return (0);
}
/*
* FUNCTION: meta_get_stripe_names()
* INPUT: sp - the set name to get stripes from
* options - options from the command line
* OUTPUT: nlpp - list of all stripe names
* ep - return error pointer
* RETURNS: int - -1 if error, 0 success
* PURPOSE: returns a list of all stripes in the metadb
* for all devices in the specified set
*/
int
mdnamelist_t **nlpp,
int options,
)
{
}
/*
* free stripe
*/
void
)
{
}
}
}
}
/*
* get stripe (common)
*/
int fast,
)
{
char *miscname;
/* must have set */
/* short circuit */
}
/* get miscname and unit */
return (NULL);
return (NULL);
}
return (NULL);
/* allocate stripe */
/* allocate rows */
/* get common info */
/* get options */
goto out;
}
/* get rows */
/* get interlace */
/* allocate comps */
/* get components */
++comp, ++c) {
/* get the component name */
goto out;
/* if hotspared */
/* get the hotspare name */
goto out;
ep) == MD_DISKADDR_ERROR)
mdclrerror(ep);
(hs_start_blk != 0))
"%s: suspected bad start block,"
(hs_start_blk == 0) &&
"%s: suspected bad start block, "
}
/* override any start_blk */
/* get the right component start_blk */
} else {
ep) == MD_DISKADDR_ERROR)
mdclrerror(ep);
(comp_start_blk != 0))
"%s: suspected bad start block,"
" seems labelled [stripe]"),
(comp_start_blk == 0) &&
"%s: suspected bad start block, "
"seems unlabelled [stripe]"),
}
}
/* override any start_blk */
/* get state */
/* get time of last state change */
/* get lasterr count */
}
}
/* cleanup, return success */
return (stripep);
/* cleanup, return error */
out:
return (NULL);
}
/*
* get stripe
*/
)
{
}
/*
* check stripe for dev
*/
static int
)
{
/* should be in the same set */
/* get unit */
return (-1);
/* look in rows */
/* look in columns */
int err;
/* check same drive since metagetstart() can fail */
return (-1);
else if (err == 0)
continue;
/* check overlap */
return (-1);
ep) != 0) {
return (-1);
}
}
}
/* return success */
return (0);
}
/*
* check to see if we're in a stripe
*/
int
)
{
mdnamelist_t *p;
int rval = 0;
/* should have a set */
/* for each stripe */
return (-1);
/* check stripe */
rval = -1;
break;
}
}
/* cleanup, return success */
return (rval);
}
/*
* check component
*/
int
int force,
)
{
/*
* See if we are a soft partition: meta_sp_issp() returns 0 if
* np points to a soft partition, so the if and else clauses
* here represent "not a soft partition" and "soft partition,"
* respectively.
*/
/* make sure we have a disk */
return (-1);
} else {
/* make sure soft partition can parent & doesn't have parent */
return (-1);
}
}
}
/* check to ensure that it is not already in use */
if ((! force) &&
return (-1);
}
/* make sure it is in the set */
return (-1);
/* make sure its not in a metadevice */
return (-1);
/* return success */
return (0);
}
/*
* print stripe
*/
static int
char *fname,
)
{
int rval = -1;
if (options & PRINT_LARGEDEVICES) {
rval = 0;
goto out;
}
}
rval = 0;
goto out;
}
}
/* print name and num rows */
goto out;
/* print rows */
/* print num components */
goto out;
/*
* Print components. Always print the full path name.
*/
goto out;
}
/* print interlace */
goto out;
/* print continuation */
goto out;
}
/* print hotspare name */
goto out;
/* terminate last line */
goto out;
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* convert component state to name
*/
char *
)
{
/* grab time */
if (tstate != 0) {
}
/* return state */
switch (state) {
case CS_OKAY:
case CS_ERRED:
case CS_LAST_ERRED:
case CS_RESYNC:
default:
}
}
/*
* print subdevice stripe row
*/
static int
char *fname,
)
{
int rval = -1;
int len = 0;
/*
* building a format string on the fly that will be used
* in fprintf. This is to allow really really long ctd names
*/
}
len += 2;
/* print header */
if (! (options & PRINT_TIMES)) {
"\t%-*.*s %-12.12s %5.5s %12.12s %5.5s %s\n",
goto out;
}
} else {
"\t%-*s %5s %5s %-11s %-5s %-9s %s\n",
len,
goto out;
}
}
/* print components */
int has_mddb;
char *has_mddb_str;
char *comp_state;
char *devid = " ";
/* get info */
return (-1);
}
return (-1);
}
if (has_mddb)
else
/*
* If the component is a metadevice, print out either
* unavailable or the state of the metadevice, if not
* a metadevice, print nothing if the state of the
* stripe is unavailable
*/
if (metaismeta(namep)) {
return (-1);
} else {
/*
* if top_tstate is set, that implies that you have
* a ctd type device with an unavailable metadevice
* on top of it. If so, print a - for it's state
*/
if (top_tstate != 0)
comp_state = "-";
else
tstate & MD_DEV_ERRORED);
}
/* populate the key in the name_p structure */
== NULL) {
return (-1);
}
/* determine if devid does NOT exist */
if (options & PRINT_DEVID) {
else {
}
}
/* print info */
/*
* building a format string on the fly that will be used
* in fprintf. This is to allow really really long ctd names
*/
if (! (options & PRINT_TIMES)) {
"\t%-*s %8lld %-5.5s %12.12s %5.5s %s\n",
goto out;
}
} else {
"\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n",
goto out;
}
}
}
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* print toplevel stripe row
*/
/*ARGSUSED4*/
static int
char *fname,
)
{
int rval = -1;
char *devid = " ";
int len = 0;
/*
* building a format string on the fly that will be used
* in fprintf. This is to allow really really long ctd names
*/
}
len += 2;
/* print header */
"\t%-*.*s %-12.12s %-5.5s\t%s\n",
goto out;
}
/* print components */
int has_mddb;
char *has_mddb_str;
/* get info */
return (-1);
}
return (-1);
}
if (has_mddb)
else
/* populate the key in the name_p structure */
== NULL) {
return (-1);
}
/* determine if devid does NOT exist */
if (options & PRINT_DEVID) {
} else {
}
}
/* print info */
/*
* building a format string on the fly that will be used
* in fprintf. This is to allow really really long ctd names
*/
"\t%-*s %8lld %-5.5s\t%s\n", len,
goto out;
}
}
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* print stripe options
*/
int
char *fname,
)
{
int rval = -1;
/* print options */
goto out;
}
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* report stripe
*/
static int
mdnamelist_t **nlpp,
char *fname,
)
{
int rval = -1;
/*
* if the -B option has been specified check to see if the
* metadevice is s "big" one and print if so, also if a
* big device we need to store the ctd involved for use in
* printing out the relocation information.
*/
if (options & PRINT_LARGEDEVICES) {
rval = 0;
goto out;
} else {
goto out;
}
}
/*
* if the -D option has been specified check to see if the
* metadevice has a descriptive name and print if so, also if a
* descriptive device name we need to store the ctd involved
* for use in printing out the relocation information.
*/
rval = 0;
goto out;
} else {
goto out;
}
}
/* print header */
if (options & PRINT_HEADER) {
goto out;
}
}
/* print hotspare pool */
return (-1);
}
}
!= 0)
return (-1);
}
if ((tstate & MD_DEV_ERRORED) != 0) {
" State: Unavailable\n"
" Reconnect disk and invoke: metastat -i\n")) == EOF) {
goto out;
}
}
/* print size */
== EOF) {
goto out;
}
/* print rows */
/* print stripe and interlace */
" Stripe %u: (interlace: %lld blocks)\n"),
goto out;
}
} else {
" Stripe %u:\n"),
goto out;
}
}
/* print components appropriately */
return (-1);
}
} else {
ep) != 0) {
return (-1);
}
}
}
/* add extra line */
goto out;
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
*/
int
mdnamelist_t **nlpp,
char *fname,
)
{
/* should have same set */
/* print all stripes */
mdnamelist_t *p;
int cnt;
int rval = 0;
/* get list */
return (-1);
else if (cnt == 0)
return (0);
/* recurse */
rval = -1;
}
/* cleanup, return success */
return (rval);
}
/* get unit structure */
return (-1);
/* check for parented */
if ((! (options & PRINT_SUBDEVS)) &&
return (0);
}
/* print appropriate detail */
if (options & PRINT_SHORT) {
return (-1);
} else {
ep) != 0)
return (-1);
}
/* Recurse on components that are metadevices */
/* look for components that are metadevices */
if ((metaismeta(namep)) &&
return (-1);
}
}
}
return (0);
}
/*
* find stripe component to replace
*/
int
)
{
uint_t lasterrcnt = 0;
/* get stripe */
return (-1);
/*
* Try to find the first erred component.
* If there is not one, then look for the
* first last_erred component.
*/
}
}
}
}
}
}
/* return component */
}
/* return success */
return (0);
}
/*
* invalidate component names
*/
static int
)
{
return (-1);
}
}
return (0);
}
/*
* attach components to stripe
*/
int
)
{
diskaddr_t disk_size = 0;
uint_t write_reinstruct = 0;
uint_t read_reinstruct = 0;
int rval = -1;
int create_flag = MD_CRO_32BIT;
/* should have a set */
/* check type */
return (-1);
/* check and count components */
newcomps = 0;
mdnamelist_t *p;
/* check against existing devices */
return (-1);
/* check against ourselves */
return (-1);
}
}
/* count */
++newcomps;
}
/* get old unit */
return (-1);
/* if zero, inherit the last rows interlace value */
if (interlace == 0) {
}
/*
* calculate size of new unit structure
*/
/* unit + rows */
/* number of new components being added */
/* count the # of components in the old unit */
/* allocate new unit */
/* compute new data */
/* for each new device */
/* figure out how big */
goto out;
goto out;
goto out;
}
if (newcomps > 1)
/* adjust for smallest disk */
if (disk_size == 0) {
}
/* get worst reinstructs */
goto out;
/* In dryrun mode (DOIT not set) we must not alter the mddb */
if (options & MDCMD_DOIT) {
/* store name in namespace */
goto out;
}
/* build new component */
}
/* compute new size */
"unit size overflow, limit is %lld blocks\n"),
limit);
} else {
}
/* adjust geometry */
goto out;
/* if in dryrun mode, we are done here. */
if ((options & MDCMD_DOIT) == 0) {
if (options & MDCMD_PRINT) {
if (newcomps == 1) {
"%s: attaching component would suceed\n"),
} else {
"%s: attaching components would suceed\n"),
}
}
rval = 0; /* success */
goto out;
}
/* grow stripe */
if (create_flag == MD_CRO_32BIT) {
} else {
}
}
goto out;
}
/* clear cache */
goto out;
/* let em know */
if (options & MDCMD_PRINT) {
if (newcomps == 1) {
} else {
}
}
/* grow any parents */
return (-1);
rval = 0; /* success */
/* cleanup, return error */
out:
if (options & MDCMD_DOIT) {
if (rval != 0)
}
return (rval);
}
/*
* get stripe parameters
*/
int
)
{
/* should have a set */
/* check name */
return (-1);
/* get unit */
return (-1);
/* return parameters */
else
return (0);
}
/*
* set stripe parameters
*/
int
)
{
/* should have a set */
/* check name */
return (-1);
/* set parameters */
/* clear cache */
/* return success */
return (0);
}
/*
* check for dups in the stripe itself
*/
static int
)
{
uint_t r;
for (r = 0; (r <= row); ++r) {
uint_t c;
for (c = 0; (c < e); ++c) {
return (-1);
}
}
}
return (0);
}
/*
* default stripe interlace
*/
{
/* default to 512k, round up if necessary */
return (interlace);
}
/*
* convert interlaces
*/
int
char *uname,
)
{
}
return (0);
}
/*
* check stripe
*/
int
)
{
/* check rows */
}
/* check number */
}
/* compute default interlace */
}
/* check interlace */
ep) != 0) {
return (-1);
}
/* check components */
/* check component */
if (!updateit) {
return (-1);
ep)) == MD_DISKADDR_ERROR) ||
return (-1);
}
if (size == 0)
}
/* check this stripe too */
return (-1);
}
}
/* check hotspare pool name */
if (doit) {
return (-1);
}
}
/* return success */
return (0);
}
/*
* setup stripe geometry
*/
static int
)
{
uint_t write_reinstruct = 0;
uint_t read_reinstruct = 0;
diskaddr_t first_row_size = 0;
char *miscname;
int is_sp = 0;
/* get worst reinstructs */
return (-1);
}
}
if ((geomp = metagetgeom(
return (-1);
}
/*
* Figure out if the first component is a softpartition as the
* truncation check only occurs on them.
*/
if ((miscname = metagetmiscname(
return (-1);
is_sp = 1;
}
/* setup geometry from first device */
return (-1);
/*
* Here we want to make sure that any truncation did not
* result in lost data (or, more appropriately, inaccessible
* data).
*
* This is mainly a danger for (1, 1) concats, but it is
* mathematically possible for other somewhat contrived
* arrangements where in the sum of the lengths of each row
* beyond the first is smaller than the cylinder size of the
* only component in the first row.
*
* It is tempting to simply test for truncation here, by
* (md->c.un_total_blocks < md->c.un_actual_tb). That does
* not tell us, however, if rounding resulted in data loss,
* rather only that it occurred. The somewhat less obvious
* test below covers both the obvious (1, 1) case and the
* aforementioned corner case.
*/
if (is_sp == 1) {
/*
* The only difference here is the text of the error
* message, since the remediation is slightly
* different in the one-component versus
* multiple-component cases.
*/
if (nrow == 1) {
} else {
}
/*
* By the size comparison above and the initialization
* of buf[] in terms of ULLONG_MAX, we guarantee that
* the value arg is non-negative and that we won't
* overflow the container.
*/
return (-1);
}
}
/* return success */
return (0);
}
/*
* create stripe
*/
int
)
{
diskaddr_t cum_blocks = 0;
int rval = -1;
int create_flag = MD_CRO_32BIT;
/* validate stripe */
return (-1);
/* allocate stripe unit */
}
/* do rows */
diskaddr_t disk_size = 0;
/* setup component count and offfset */
/* do components */
/*
* get start and size
* if first component is labelled, include label
*/
goto out;
goto out;
int has_db;
goto out;
goto out;
}
}
/* make sure we still have something left */
goto out;
}
/*
* round down by interlace: this only applies
* if this row is a stripe, as indicated by
* (ncomp > 1)
*/
if (ncomp > 1)
if (size == 0) {
goto out;
}
/*
* adjust for smallest disk: for a concat (any
* row with only one component), this will
* never hit the second conditional.
*/
if (disk_size == 0) {
}
if (options & MDCMD_DOIT) {
/* store name in namespace */
goto out;
}
/* setup component */
}
/* setup row */
if (cum_blocks > limit) {
cum_blocks = limit;
"unit size overflow, limit is %lld blocks\n"),
limit);
}
}
/* setup unit */
else
/* fill in the size of the stripe */
if (options & MDCMD_UPDATE) {
}
}
/*
* If the device is being truncated then only allow this
* if the user is aware (using the -f option) or they
* option).
*/
"%s: WARNING: This form of metainit is not recommended.\n"
"The stripe is truncating the size of the underlying device.\n"
"Please see ERRORS in metainit(1M) for additional information.\n"),
mdclrerror(ep);
} else {
goto out;
}
}
/* if we're not doing anything, return success */
if (! (options & MDCMD_DOIT)) {
rval = 0; /* success */
goto out;
}
/* create stripe */
/* did the user tell us to generate a large device? */
if (create_flag == MD_CRO_64BIT) {
} else {
}
goto out;
}
rval = 0; /* success */
/* cleanup, return success */
out:
if (rval != 0) {
}
rval = -1;
}
return (rval);
}
/*
* initialize stripe
* NOTE: this functions is metainit(1m)'s command line parser!
*/
int
mdsetname_t **spp,
int argc,
char *argv[],
)
{
int old_optind;
int c;
int rval = -1;
/* get stripe name */
if (argc < 1)
goto syntax;
goto out;
goto out;
if (!(options & MDCMD_NOLOCK)) {
/* grab set lock */
goto out;
goto out;
}
/* see if it exists already */
goto out;
goto out;
} else {
mdclrerror(ep);
}
/* parse general options */
optind = 0;
opterr = 0;
goto options;
/* allocate stripe */
/* setup common */
/* allocate and parse rows */
if (argc < 1) {
uname);
goto out;
goto syntax;
} else if (nrow < 1) {
uname);
goto out;
}
/* allocate and parse components */
if (argc < 1) {
goto out;
((int)ncomp < 0)) {
goto syntax;
} else if (ncomp < 1) {
goto out;
}
/* parse component name */
if (argc < 1) {
goto out;
}
goto out;
}
/* check for soft partition */
/* check disk */
goto out;
}
}
}
/* parse row options */
old_optind = optind = 0;
opterr = 0;
switch (c) {
case 'i':
goto out;
}
goto out;
break;
default:
goto done_row_opts;
}
old_optind = optind;
}
}
/* parse stripe options */
old_optind = optind = 0;
opterr = 0;
switch (c) {
case 'h':
goto out;
}
/*
* Get out if the specified hotspare pool really
* doesn't exist.
*/
goto out;
}
break;
default:
argc += old_optind;
argv += old_optind;
goto options;
}
old_optind = optind;
}
/* we should be at the end */
if (argc != 0)
goto syntax;
/* create stripe */
goto out;
rval = 0; /* success */
/* let em know */
if (options & MDCMD_PRINT) {
uname);
}
goto out;
/* syntax error */
goto out;
/* options error */
goto out;
/* cleanup, return error */
out:
return (rval);
}
/*
* reset stripes
*/
int
)
{
int rval = -1;
/* should have same set */
/* reset all stripes */
mdnamelist_t *p;
/* for each stripe */
rval = 0;
return (-1);
/* reset stripe */
/*
* If this is a multi-node set, we send a series
* of individual metaclear commands.
*/
rval = -1;
break;
}
} else {
rval = -1;
break;
}
}
}
/* cleanup, return success */
return (rval);
}
/* check name */
return (-1);
/* get unit structure */
return (-1);
/* make sure nobody owns us */
}
/* clear subdevices cache */
return (-1);
/* clear metadevice */
goto out;
rval = 0; /* success */
/* let em know */
if (options & MDCMD_PRINT) {
}
/* clear subdevices */
if (! (options & MDCMD_RECURSE))
goto out;
/* only recurse on metadevices */
if (! metaismeta(compnp))
continue;
rval = -1;
}
}
/* cleanup, return success */
out:
return (rval);
}
/*
* reports TRUE if any stripe component is in error
*/
int
{
int row;
goto out;
}
goto out;
}
}
}
}
out:
mdclrerror(ep);
return (any_errs);
}