meta_trans.c revision d7cd82522afdd890a66c7600b499590ad44e84bd
/*
* 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
/*
* trans operations
*/
#include <meta.h>
#include <meta_basic.h>
#include <stddef.h>
extern char *getfullblkname();
/*
* replace trans
*/
int
{
/* should have same set */
/* the old device binding is now established */
}
return (-1);
}
if (options & MDCMD_PRINT) {
"%s: device %s is replaced with %s\n"),
}
return (0);
}
/*
* FUNCTION: meta_get_trans_names()
* INPUT: sp - the set name to get trans from
* options - options from the command line
* OUTPUT: nlpp - list of all trans names
* ep - return error pointer
* RETURNS: int - -1 if error, 0 success
* PURPOSE: returns a list of all trans in the metadb
* for all devices in the specified set
*/
int
mdnamelist_t **nlpp,
int options,
)
{
}
/*
* free trans unit
*/
void
)
{
}
/*
* get trans (common)
*/
int fast,
)
{
char *miscname;
int gotlog;
/* must have set */
/* short circuit */
}
/* get miscname and unit */
return (NULL);
return (NULL);
}
return (NULL);
/* allocate trans */
/* get common info */
/* get master */
goto out;
/* get log */
if (gotlog) {
goto out;
/* calculate the kernels start block */
mdclrerror(ep);
"%s: suspected bad start block [trans]\n"),
}
/* override any start_blk */
}
/* get flags, etc. */
/* cleanup, return success */
return (transp);
/* cleanup, return error */
out:
return (NULL);
}
/*
* get trans
*/
)
{
}
/*
* check trans for dev
*/
static int
)
{
/* should be in the same set */
/* get unit */
return (-1);
/* check master */
if ((! metaismeta(masternp)) &&
return (-1);
}
/* check log */
(! (options & MDCHK_ALLOW_LOG)) &&
(! metaismeta(lognp))) {
int err;
/* check same drive since metagetstart() can fail */
return (-1);
/* check overlap */
if (err != 0) {
return (-1);
return (-1);
}
}
}
/* return success */
return (0);
}
/*
* check to see if we're in a trans
*/
int
)
{
mdnamelist_t *p;
int rval = 0;
/* should have a set */
/* for each trans */
return (-1);
/* check trans */
rval = -1;
break;
}
}
/* cleanup, return success */
return (rval);
}
/*
* check master
*/
int
int force,
)
{
mdchkopts_t options = 0;
/* 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);
} else { /* Metadevices only! */
return (-1);
/*
* Since soft partitions may appear at the top or bottom
* of the metadevice stack, we check them separately.
* A trans may be built on top of a soft partition if
* the soft partition has no parent (can't rely on the
* MD_CAN_PARENT flag in this case since a soft partition
* built on a metadevice clears this flag to prevent nested
* configurations).
*/
return (0);
}
}
/* return success */
return (0);
}
/*
* check log
*/
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);
} else { /* Metadevices only! */
return (-1);
/*
* Since soft partitions may appear at the top or bottom
* of the metadevice stack, we check them separately.
* A trans may be built on top of a soft partition if
* the soft partition has no parent (can't rely on the
* MD_CAN_PARENT flag in this case since a soft partition
* built on a metadevice clears this flag to prevent nested
* configurations).
*
*/
return (0);
}
}
/* return success */
return (0);
}
/*
* print trans
*/
static int
char *fname,
)
{
int rval = -1;
/* print name and -t */
goto out;
/* print master */
/*
* 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, print ctds or d number */
goto out;
}
/* print log */
/*
* 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 */
goto out;
}
}
/* print terminating newline */
goto out;
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
* convert flags to repair action
*/
char *
)
{
int len;
int err = -1;
if (!transp) {
goto out;
}
/*
* if in any of these states, the log_error word is not (yet) meaningful
*/
goto out;
}
" To Fix: Please refer to the log device's status.\n");
goto out;
}
goto out;
}
goto out;
}
}
err = 0;
out:
if (err != 0) {
if (actionp) {
}
}
return (actionp);
}
/*
* convert log state to repair action
*/
char *
)
{
char umnt_msg[1024];
char fsck_msg[1024];
char mnt_msg[1024];
mdnamelist_t *p;
md_trans_t *tp;
int rc;
int len = 0;
/*
* If a the trans devices listed in transnlp contain
* devices which are in error and are sub-mount points
* of each other, than it would need to be reverse sorted.
* When this actually occurs, and customers find the usage
* message insufficiently clear, then we should take the
* hit to sort it.
*/
/*
* this preliminary loop is necessary to keep the
* fsck message greppable, if possible
*/
goto out;
}
continue;
}
continue;
}
mdclrerror(ep);
goto out;
}
mdclrerror(ep);
goto out;
}
if (is_mounted) {
if (!mp) {
goto out;
}
/*
* not greppable; there must be multiple commands, so
* add preliminary newline so the formatting is uniform
*/
goto out;
}
}
if (mp) {
}
}
/*
* although the log may either be in error or hard-error
* states, the action is the same; unmount, fsck and remount
* all fs associated with this log
*/
goto out;
}
continue;
}
continue;
}
mdclrerror(ep);
goto out;
}
mdclrerror(ep);
goto out;
}
if (is_mounted) {
if (!mp) {
goto out;
}
}
if (is_mounted) {
if (rc < 0) {
goto out;
}
}
(any_in_error) ? fsck_msg :
if (rc < 0) {
goto out;
}
if (is_mounted) {
"%s mount %s %s\n",
if (rc < 0) {
goto out;
}
}
if (mp) {
}
any_in_error |= TRUE;
}
if (!any_in_error) {
goto out;
}
len = 0;
goto out;
}
goto out;
}
out:
if (mp) {
}
}
return (rmsg);
}
/*
* printable log state
*/
char *
)
{
/* grab time */
if (tstate != 0) {
}
/* return state */
} else if (log_error & LDL_HERROR) {
} else {
}
}
/*
* printable trans state
*/
char *
)
{
/* grab time */
if (tstate != 0) {
}
/* return state */
}
/*
* report trans
*/
static int
char *fname,
)
{
char *mt_state;
char *timep;
int rval = -1;
char *devid = "";
/* print header */
if (options & PRINT_HEADER) {
" (Feature replaced see message below)\n"),
goto out;
}
}
/* print state */
!= 0)
goto out;
}
if (options & PRINT_TIMES) {
} else {
timep = "";
}
goto out;
}
if ((tstate & MD_DEV_ERRORED) == 0) {
if (actionp) {
goto out;
}
}
}
/* debug stuff */
" Debug Modes:%s%s%s%s%s%s%s%s%s%s%s\n",
== EOF) {
goto out;
}
}
/* print size */
goto out;
}
/* print master */
goto out;
}
/* print log */
" Logging Device: %s\n"),
goto out;
}
}
/* add extra line */
goto out;
/* print master details if regular device */
int len;
/*
* Building a format string on the fly that will
* be used in (f)printf. This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
/* print header */
"\t%-*.*s %-12.12s %-5.5s %s\n",
goto out;
}
/* populate the key in the name_p structure */
return (-1);
}
/* determine if devid does NOT exist */
if (options & PRINT_DEVID)
else {
}
/* print info */
/*
* This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
goto out;
}
/* add extra line */
goto out;
}
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
*/
int
char *fname,
int *meta_print_trans_msgp, /* NULL if transnp != NULL */
)
{
/* should have same set */
/* print all transs */
mdnamelist_t *p;
int cnt;
int rval = 0;
/* get list */
return (-1);
else if (cnt == 0)
return (0);
/* recurse */
rval = -1;
}
*meta_print_trans_msgp = 1;
/* cleanup, return success */
return (rval);
}
/* get unit structure */
return (-1);
/* save unique log */
mdnamelist_t *p;
break;
}
if (p == NULL)
}
/* check for parented */
if ((! (options & PRINT_SUBDEVS)) &&
return (0);
}
/* can't have a large trans or descriptive name trans */
/* print appropriate detail */
if (options & PRINT_SHORT) {
return (-1);
} else {
!= 0)
return (-1);
}
}
/* print underlying metadevices, log is later */
!= 0) {
return (-1);
}
}
/* return success */
return (0);
}
/*
* print log
*/
static int
char *fname,
)
{
/* metadevice info */
if (metaismeta(lognamep)) {
}
/* regular device info */
return (0);
}
/*
* report log
*/
static int
char *fname,
)
{
mdnamelist_t *p;
char *ml_state;
char *timep;
int rval = -1;
char *devid = " ";
md_trans_t *tp;
return (-1);
}
}
/* we must have at least one trans */
rval = 0;
goto out;
}
if ((options & PRINT_LARGEDEVICES) &&
rval = 0;
goto out;
}
/* print header and trans devices, collect log_error and size */
goto out;
}
== EOF) {
goto out;
}
}
goto out;
/* print state */
return (-1);
}
if (options & PRINT_TIMES) {
} else {
timep = "";
}
goto out;
}
if ((tstate & MD_DEV_ERRORED) == 0) {
if (actionp) {
goto out;
}
}
}
/* print size */
goto out;
}
/* MD_DEBUG stuff */
if (options & PRINT_DEBUG) {
int percent;
== NULL) {
return (-1);
}
" Transfer Size: %d blocks\n"),
goto out;
}
else
" Full: %d%% (%ld of %ld blocks)\n"),
goto out;
}
" Reserved: %d%% (%ud of %ud bytes)\n"),
goto out;
}
}
/* add extra line */
goto out;
/* print log details */
if (metaismeta(lognamep)) {
return (-1);
}
} else {
int has_mddb;
char *has_mddb_str;
int len;
/*
* Building a format string on the fly that will
* be used in (f)printf. This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
/* print header */
"\t%-*.*s %-12.12s %-5.5s %s\n",
goto out;
}
/* get info */
return (-1);
}
return (-1);
}
if (has_mddb)
else
/* populate the key in the name_p structure */
return (-1);
}
/* determine if devid does NOT exist */
if (options & PRINT_DEVID)
else {
}
/* print info */
/*
* This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
goto out;
}
}
/* add extra line */
goto out;
/* success */
rval = 0;
/* cleanup, return error */
out:
if (rval != 0)
return (rval);
}
/*
*/
int
char *fname,
)
{
mdnamelist_t *p;
int rval = 0;
/* must have a set */
/* get trans devices */
return (0);
if (! (options & PRINT_SHORT))
return (-1);
/* print all logs */
options |= PRINT_SUBDEVS;
/* print appropriate detail */
if (options & PRINT_SHORT) {
ep) != 0) {
rval = -1;
}
} else {
rval = -1;
}
}
}
/* cleanup, return success */
out:
return (rval);
}
/*
* meta_lockfs_common -- common lock and unlock code
*
* Normally this routine will return a 0 for success. Even if
* lockfs wasn't able to lock down the filesystem. The reason
* for this is that the master device can be in an errored state
* and the lock can't be obtained. We don't want to prevent
* possible recovery in this case and it's not likely any activity
* will be occurring. If the filesystem is healthy with activity
* lockfs will successfully lock the filesystem and return an
* error code of 0.
*
* The one case where this routine returns a non-zero value would
* be if we can't determine the outcome of the lockfs. This should
* never occur because we don't catch signals that could cause
* waitpid() to prematurely return.
*/
static int
{
char *blkname;
FILE *m;
int lock_exit;
/*
* No mnttab means nothing is mounted
*/
*cookie = 0;
return (0);
}
/*
* No match in mnttab so we're not mounted ... at least
* nothing better be mounted.
*/
*cookie = 0;
return (0);
}
(void) fclose(m);
case -1:
/*
* We've got some major trouble here and shouldn't
* continue. The user needs to clear up the problems
* that the system currently has before proceeding
* to detach the log.
*/
*cookie = 0;
return (1);
case 0:
"-c", "Solaris Volume Manager detach lock",
tab_match.mnt_mountp, 0);
/*
* Shouldn't reach here, but if this code is run on
* a release that doesn't have lockfs return an error
* code so that the -f (force) option could be used
* by metadetach.
*/
exit(1);
default:
/*
* We couldn't get status regarding the
* outcome of the lockfs command. We should
* attempt to unlock the filesystem though.
* Return an error code so that if the user
* is trying to force the detach make them
* clear up this problem first.
*/
*cookie = (void *)1;
return (1);
}
*cookie = (void *)1;
return (0);
}
}
/*
* meta_lockfs - if mounted, lock a given device against writes
*
* See comment section for meta_lockfs_common
*/
static int
{
}
/*
* meta_unlockfs - if mounted, unlock the filesystem if previously locked
*
* See comment section for meta_lockfs_common
*/
static void
{
/*
* Simple time saver. We could always try to unlock
* the filesystem, that takes time a resources.
*/
if (*cookie == (void *)1)
}
/*
* meta_trans_detach -- detach log from trans device
*/
int
int *delayed,
)
{
void *lock_cookie;
/* should have a set */
/* check name */
return (-1);
/* save log name */
return (-1);
/*
* If trans device is mounted lock the filesystem
* against writes and mod time updates.
*/
/*
* This device is mounted and we were unable
* lock the device. Data corruption can occur
* if we don't lock the device before removing
* the log so bail out here.
* NOTE: There's one case were the exist status
* of lockfs could have been lost yet the command
* could have run. We should try to unlock the filesystem
* before returning.
*/
}
/* detach log */
*delayed = 0;
/* delayed detach */
*delayed = 1;
} else {
}
}
/*
* Unlock the filesystem
*/
/* clear cache */
/* let em know */
if (options & MDCMD_PRINT) {
if (*delayed) {
"%s: logging device %s will be detached at unmount or reboot\n"),
} else {
"%s: logging device %s is detached\n"),
}
}
/* return success */
return (0);
}
/*
* reset trans
*/
int
)
{
int rval = -1;
/* should have a set */
/* reset all trans */
mdnamelist_t *p;
/* for each trans */
rval = 0;
return (-1);
/* reset trans */
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 */
/* clear metadevice */
goto out;
rval = 0; /* success */
/* let em know */
if (options & MDCMD_PRINT) {
}
/* clear subdevices */
if (! (options & MDCMD_RECURSE))
goto out;
rval = -1;
}
/* (multi-parented) log will be cleared later */
/* cleanup, return success */
out:
return (rval);
}