meta_hotspares.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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"
/*
* 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
/*
* hotspares utilities
*/
#include <meta.h>
/*
* FUNCTION: meta_get_hsp_names()
* INPUT: sp - the set name to get hotspares from
* options - options from the command line
* OUTPUT: hspnlpp - list of all hotspare names
* ep - return error pointer
* RETURNS: int - -1 if error, 0 success
* PURPOSE: returns a list of all hotspares in the metadb
* for all devices in the specified set
*/
/*ARGSUSED*/
int
int options,
)
{
int i;
/* we must have a set */
/* get number of devices */
} else {
return (-1);
}
}
/* malloc minor number buffer to be filled by ioctl */
return (ENOMEM);
}
return (-1);
}
/* get name */
== NULL)
goto out;
/* append to list */
/* next device */
m_ptr++;
}
}
out:
return (-1);
}
/*
* get information of a specific hotspare pool from driver
*/
static get_hsp_t *
)
{
/* should have a set */
/* get size of unit structure */
return (NULL);
}
/* get actual unit structure */
return (NULL);
}
}
/*
* free hotspare pool unit
*/
void
)
{
}
}
/*
* get hotspare pool unit (common)
*/
md_hsp_t *
int fast,
)
{
/* must have set */
/* short circuit */
/* get unit */
return (NULL);
/* allocate hsp */
/* allocate hotspares */
/* if empty hotspare pool, we are done */
/* get name, refcount */
/* get hotspares */
/* get hotspare name */
goto out;
/* get hotspare state */
goto out;
}
}
/* cleanup, return success */
return (hspp);
/* cleanup, return error */
out:
return (NULL);
}
/*
* get hotspare pool unit
*/
md_hsp_t *
)
{
}
/*
* check hotspare pool for dev
*/
static int
)
{
uint_t i;
/* should be in the same set */
/* get unit */
return (-1);
/* look in hotspares */
/* check overlap */
if (metaismeta(hsnp))
continue;
return (-1);
}
/* return success */
return (0);
}
/*
* check to see if we're in a hotspare pool
*/
int
)
{
mdhspnamelist_t *p;
int rval = 0;
/* should have a set */
/* for each hotspare pool */
return (-1);
/* check hotspare pool */
rval = -1;
break;
}
}
/* cleanup, return success */
return (rval);
}
/*
* check hotspare
*/
int
)
{
/* make sure we have a disk */
return (-1);
/* check to ensure that it is not already in use */
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 hsp
*/
static int
char *fname,
)
{
int rval = -1;
/* print name */
goto out;
/* print hotspares */
/* print hotspare */
/*
* then just print out the cxtxdxsx or the dx, metainit
* will assume the default, otherwise we need the full
* pathname to make sure this works as we intend.
*/
/* not standard path, print full pathname */
goto out;
} else {
/* standard path, just print ctd or d value */
goto out;
}
}
/* terminate last line */
goto out;
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* hotspare state name
*/
char *
)
{
/* grab time */
switch (state) {
case HSS_AVAILABLE:
case HSS_RESERVED:
case HSS_BROKEN:
case HSS_UNUSED:
default:
}
}
/*
* report hsp
*/
static int
mdnamelist_t **nlpp,
char *fname,
md_error_t *ep,
)
{
int rval = -1;
char *devid = "";
int large_hs_dev_cnt = 0;
if (options & PRINT_LARGEDEVICES) {
large_hs_dev_cnt += 1;
!= 0)
goto out;
}
}
if (large_hs_dev_cnt == 0) {
rval = 0;
goto out;
}
}
/* print header */
goto out;
}
/*
* This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
/*
* if the length is to short to print out all of the header
* force the matter
*/
len += 2;
if (options & PRINT_LARGEDEVICES) {
"%s: 1 hot spare (1 big device)\n\t%-*.*s "
"%-12.12s%-8.6s\t\t%s\n",
goto out;
}
} else {
"%s: 1 hot spare\n\t%-*.*s %-12.12s%-8.6s\t\t%s\n",
goto out;
}
}
} else {
/*
* This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
len = 0;
}
len += 2;
if (options & PRINT_LARGEDEVICES) {
"%s: %u hot spares (%d big device(s))\n\t%-*.*s "
"%-12.12s%-8.6s\t\t%s\n",
goto out;
}
} else {
"%-12.12s%-8.6s\t\t%s\n",
goto out;
}
}
}
/* print hotspares */
char *hs_state;
char *timep;
/* populate the key in the name_p structure */
return (-1);
}
if (options & PRINT_LARGEDEVICES) {
continue;
}
/* determine if devid does NOT exist */
if (options & PRINT_DEVID) {
else {
}
}
/* print hotspare */
/*
* This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
if (! (options & PRINT_TIMES)) {
" %-*s %-12s %lld blocks\t%s\n",
goto out;
}
} else {
" %-*s\t %-11s %8lld blocks%s\t%s\n",
goto out;
}
}
}
/* 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 hsps */
mdhspnamelist_t *p;
int cnt;
int rval = 0;
return (-1);
else if (cnt == 0)
return (0);
/* recurse */
rval = -1;
}
/* cleanup, return success */
return (rval);
}
/* get unit structure */
return (-1);
/* print appropriate detail */
if (options & PRINT_SHORT)
else
}
/*
* check for valid hotspare pool
*/
int
)
{
return (-1);
return (0);
}
/*
* invalidate hotspare pool info
*/
void
)
{
/* free it up */
return;
/* clear cache */
}
/*
*/
int
)
{
mdnamelist_t *p;
/* should have a set */
/* clear cache */
/* setup hotspare pool info */
/* add empty hotspare pool */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
goto success;
}
/* add hotspares */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
/* should be in same set */
/* check it out */
return (-1);
return (-1);
else if (size == 0)
return (-1);
return (-1);
/* In dryrun mode (DOIT not set) we must not alter the mddb */
if (options & MDCMD_DOIT) {
/* store name in namespace */
return (-1);
}
if ((options & MDCMD_DOIT) &&
}
}
}
/* print success message */
if (options & MDCMD_PRINT) {
"%s: Hotspare pool is setup\n"),
"%s: Hotspare is added\n"),
} else {
"%s: Hotspares are added\n"),
}
}
/* return success */
return (0);
}
/*
* delete hotspares from pool
*/
int
)
{
mdnamelist_t *p;
/* should have a set */
/* clear cache */
/* setup hotspare pool info */
/* delete empty hotspare pool */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
goto success;
}
/* delete hotspares */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
/* should be in same set */
/* delete hotspare */
}
/* print success message */
if (options & MDCMD_PRINT) {
"%s: Hotspare pool is cleared\n"),
"%s: Hotspare is deleted\n"),
} else {
"%s: Hotspares are deleted\n"),
}
}
/* return success */
return (0);
}
/*
* replace hotspare in pool
*/
int
)
{
int rebind;
char *new_devidp = NULL;
int ret;
/* should be in same set */
/* save new binding incase this is a rebind where oldnp==newnp */
/* invalidate, then get the hotspare (fill in oldnp from metadb) */
return (-1);
/* the old device binding is now established */
/*
* check for the case where oldnp and newnp indicate the same
* device, but the dev_t of the device has changed between old
* and new. This is called a rebind. On entry the dev_t
* represents the new device binding determined from the
* filesystem (meta_getdev). After calling meta_get_hsp
* oldnp (and maybe newnp if this is a rebind) is updated based
* to the old binding from the metadb (done by metakeyname).
*/
rebind = 1;
} else {
rebind = 0;
}
if (rebind) {
}
/*
* Save a copy of the devid associated with the new disk, the reason
* is that the meta_check_hotspare() call could cause the devid to
* be changed to that of the devid that is currently stored in the
* replica namespace for the disk in question. This devid could be
* stale if we are replacing the disk. The function that overwrites
* the devid is dr2drivedesc().
*/
/* if it's a multi-node diskset clear new_devidp */
if (!metaislocalset(sp)) {
return (-1);
}
if (MD_MNSET_DESC(sd)) {
new_devidp = NULL;
}
}
/* check it out */
return (-1);
}
mdclrerror(ep);
}
return (-1);
}
return (-1);
}
return (-1);
}
return (-1);
}
/* In dryrun mode (DOIT not set) we must not alter the mddb */
if (options & MDCMD_DOIT) {
/* store name in namespace */
return (-1);
}
/*
* Copy back the saved devid.
*/
if (new_devidp != NULL) {
new_devidp = NULL;
}
/* In dryrun mode (DOIT not set) we must not alter the mddb */
if (options & MDCMD_DOIT) {
/* store name in namespace */
return (-1);
}
/*
* We are 'rebind'ing a disk that is in a diskset so as well
* as updating the diskset's namespace the local set needs
* to be updated because it also contains a reference to the
* disk in question.
*/
ep);
if (ret != METADEVADM_SUCCESS) {
/*
* In dryrun mode (DOIT not set) we must not alter
* the mddb
*/
if (options & MDCMD_DOIT) {
mdclrerror(&xep);
return (-1);
}
}
}
/* replace hotspare */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
if (options & MDCMD_DOIT) {
}
}
/* clear cache */
/* let em know */
if (options & MDCMD_PRINT) {
"%s: Hotspare %s is replaced with %s\n"),
}
/* return success */
return (0);
}
/*
* enable hotspares
*/
int
)
{
int rval = -1;
/* should have a set */
/* setup device info */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
/* get the list of hotspare names */
goto out;
/* enable hotspares for each components */
int rebind = 0;
/* get the file_system dev binding */
return (-1);
/*
* search for the component in each hotspare pool
* and replace it (instead of enable) if the binding
* has changed.
*/
/*
* in_hsp will call meta_get_hsp which will fill
* in hspnp with metadb version of component
*/
/*
* check for the case where the dev_t has
* changed between the filesystem and the
* metadb. This is called a rebind, and
* is handled by meta_hs_replace.
*/
/*
* establish file system binding
*/
rebind++;
if (rval != 0)
goto out;
}
}
}
if (rebind)
continue;
/* enable the component in all hotspares that use it */
goto out;
goto out;
goto out;
goto out;
goto out;
}
/* enable hotspare */
goto out;
}
/*
* Are we dealing with a non-local set? If so need to update
* the local namespace so that the disk record has the correct
* devid.
*/
if (!metaislocalset(sp)) {
if (rval != METADEVADM_SUCCESS) {
/*
* Failed to update the local set. Nothing to
* do here apart from report the error. The
* namespace is most likely broken and some
* form of remedial recovery is going to
* be required.
*/
mdclrerror(ep);
}
}
/* clear cache */
/* let em know */
if (options & MDCMD_PRINT) {
"hotspare %s is enabled\n"),
}
}
/* clear whole cache */
}
/* return success */
rval = 0;
out:
if (hspnlp)
return (rval);
}
/*
* check for dups in the hsp itself
*/
static int
)
{
uint_t h;
for (h = 0; (h < hsi); ++h) {
return (-1);
}
return (0);
}
/*
* check hsp
*/
/*ARGSUSED2*/
int
)
{
/* check hotspares */
/* check hotspare */
return (-1);
return (-1);
} else if (size == 0) {
}
/* check this hsp too */
return (-1);
}
/* return success */
return (0);
}
/*
* create hsp
*/
int
)
{
int rval = -1;
/* validate hsp */
return (-1);
/* if we're not doing anything, return success */
if (! (options & MDCMD_DOIT))
return (0);
/* create hsp */
}
options |= MDCMD_INIT;
/* cleanup, return success */
return (rval);
}
/*
* initialize hsp
* NOTE: this functions is metainit(1m)'s command line parser!
*/
int
mdsetname_t **spp,
int argc,
char *argv[],
)
{
int rval = -1;
/* get hsp name */
if (argc < 1)
goto syntax;
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 hsp */
if (argc > 0) {
}
/* setup pool */
/* parse hotspares */
++hsi) {
/* parse hotspare name */
goto out;
}
/* we should be at the end */
if (argc != 0)
goto syntax;
/* create hotspare pool */
goto out;
rval = 0; /* success */
goto out;
/* syntax error */
goto out;
/* options error */
goto out;
/* cleanup, return error */
out:
return (rval);
}
/*
* reset hotspare pool
*/
int
)
{
uint_t i;
int rval = -1;
/* should have the same set */
/* reset all hotspares */
mdhspnamelist_t *p;
/* for each hotspare pool */
rval = 0;
return (-1);
/* reset hotspare pool */
/*
* If this is a multi-node set, we send a series
* of individual metaclear commands.
*/
rval = -1;
break;
}
} else {
ep) != 0) {
rval = -1;
break;
}
}
}
/* cleanup, return success */
return (rval);
}
/* get unit structure */
return (-1);
/* make sure nobody owns us */
}
/* clear hotspare pool members */
/* clear cache */
/* clear hotspare */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
goto out;
}
}
/* clear hotspare pool */
/* If DOIT is not set, it's a dryrun */
if ((options & MDCMD_DOIT) == 0) {
}
goto out;
}
rval = 0; /* success */
/* let em know */
if (options & MDCMD_PRINT) {
"%s: Hotspare pool is cleared\n"),
}
/* clear subdevices (nothing to do) */
/* cleanup, return success */
out:
return (rval);
}