metaimport.c revision 02f7abc2de45b141dd80c73c77a51b8f797e4b8f
/*
* 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"
/*
* Utility to import SVM disksets into an active SVM configuration.
*/
#include <assert.h>
#include <strings.h>
#include <string.h>
#include <meta.h>
#include <sdssc.h>
static void
{
"%s:\t%s -s setname [-n] [-f] [-v] [%s...]\n",
}
static void
{
}
}
/*
* Returns 0 if there is no overlap, 1 otherwise
*/
static int
{
int is_overlap = 0;
next_set_dr != NULL;
/*
* Chain it, skip if already there
*/
if (overlap_disks == NULL) {
} else {
for (chain = &overlap_disks;
== 0)
break;
}
}
}
if (!is_overlap)
is_overlap = 1;
}
}
}
}
}
return (is_overlap);
}
static void
{
"have been detected in more than one set.\n"
"Import recommendation based upon set creation time.\n"
"Proceed with the import with caution."));
/*
* Look at all overlapping disks. Determine which slice
* would have a replica on it. i.e. either slice 7 or 6.
* Then read the master block. If the disk doesn't have a
* metadb on it, the master block is a dummy master block.
* Both dummy or normal master block contain the timestamp
* which is what we are after. Use this timestamp to issue
* the appropriate recommendation.
*/
int fd = -1;
continue;
continue;
continue;
continue;
mdclrerror(ep);
continue;
}
gettext(" - recommend importing with set "
(&(mbp->mb_setcreatetime))));
}
}
static void
{
int i;
int time_conflict = 0;
/* Choose the best drive to use for the import command */
for (r = d->mid_replicas;
r != NULL;
r = r->mir_next) {
if (r->mir_flags & MDDB_F_ACTIVE) {
good_disk = d;
break;
}
}
}
}
/*
* Make the distinction between a regular diskset and
* a replicated diskset.
*/
if (s->mis_flags & MD_IM_SET_REPLICATED) {
gettext("Replicated diskset found containing disks"));
} else {
gettext("Regular diskset found containing disks"));
}
/*
* Save the set creation time from the first disk in the
* diskset and compare the set creation time on all other
* disks in the set to that. If they are the same, the
* disk really belongs here. If they are different the
* disk probably belongs to a different set and we'll
* need to print out a warning.
*/
if ((firstdisktime.tv_sec ==
d->mid_setcreatetimestamp.tv_sec) &&
(firstdisktime.tv_usec ==
d->mid_setcreatetimestamp.tv_usec)) {
} else {
time_conflict = 1;
}
}
if (time_conflict) {
"in another set.\n Import may corrupt data in the "
"disk set.\n");
}
if (overlap) {
gettext("Diskset creation time"),
}
/*
* when do_cmd is true, we are not actually importing
* a disk set, but want to print out extra information
*/
if (do_cmd) {
/*
* TRANSLATION_NOTE
*
* The translation of the phrase "For more information
* about this set" will be followed by a ":" and a
* suggested command (untranslatable) that the user
* may use to request additional information.
*/
gettext("For more information about this set"),
/*
* TRANSLATION_NOTE
*
* The translation of the phrase "To import this set"
* will be followed by a ":" and a suggested command
* (untranslatable) that the user may use to import
* the specified diskset.
*/
}
}
if (overlap) {
}
}
static void
{
static const char fmt1[] = "%-*.*s %12.12s %12.12s %s\n";
static const char fmt2[] = "%-*.*s %12d %12d ";
int dlen = 0;
int f;
/*
* Run through the drives in this set to find the one with the
* longest common name and the one we want to consider "best"
*/
(r->mir_flags & MDDB_F_ACTIVE)) {
good_disk = d;
break;
}
}
}
if (do_cmd) {
}
/* Make sure the length will hold the column heading */
gettext("replica flags"));
if (d->mid_replicas != NULL) {
for (r = d->mid_replicas;
r != NULL;
r = r->mir_next) {
(r == d->mid_replicas) ?
r->mir_offset, r->mir_length);
for (f = 0; f < MDDB_FLAGS_LEN; f++) {
(void) putchar(
(r->mir_flags & (1 << f)) ?
MDDB_FLAGS_STRING[f] : ' ');
}
}
} else {
}
}
if (overlap) {
gettext("Diskset creation time"),
}
}
if (overlap) {
}
}
int
{
char c;
char *setname_new = NULL;
int report_only = 0;
int verbose = 0;
int version = 0;
int err_on_prune = 0;
int rscount = 0;
int hasreplica;
int have_multiple_sets = 0;
int force = 0;
int overlap = 0;
int partial = 0;
/*
* Get the locale set up before calling any other routines
* with messages to output. 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
(void) textdomain(TEXT_DOMAIN);
/*
* Check to see if the libsds_sc.so is bound on the
* current system. If it is, it means the system is
* part of a cluster.
*
* The import operation is currently not supported
* in a SunCluster environment.
*/
if (sdssc_bind_library() != SDSSC_NOT_BOUND) {
"%s: Import operation not supported under SunCluster\n"),
argv[0]);
exit(0);
}
/* initialize */
}
optind = 1;
opterr = 1;
switch (c) {
case 'f':
force = 1;
break;
case 'n':
dry_run = 1;
break;
case 'r':
report_only = 1;
break;
case 's':
break;
case 'v':
verbose = 1;
break;
case 'V':
version = 1;
break;
case '?':
default:
break;
}
}
if (version == 1)
/* Detect conflicting options */
if ((dry_run != 0) && (report_only != 0))
/* Don't do any real work if we don't have root privilege */
if (meta_check_root(ep) != 0) {
}
if (meta_setup_db_locations(ep) != 0) {
}
/*
* Read remaining arguments into drive name list, otherwise
* call routine to list all drives in system.
*/
int i;
/* For user specified disks, they MUST not be in use */
err_on_prune = 1;
/* All remaining args should be disks */
} else {
}
}
} else {
}
}
/*
* If the user specified disks on the command line, min_count will be
* greater than zero. If they didn't, it should be safe to assume that
* the system in question has at least one drive detected by the
* snapshot code, or we would have barfed earlier initializing the
* metadb.
*/
/*
* Prune the list:
* - get rid of drives in current svm configuration
* - get rid of mounted drives
* - get rid of swap drives
* - get rid of drives in other sets
*
* If drives were specified on the command line, it should be
* an error to find in-use disks in the list. (err_on_prune)
*
* On return from meta_prune_cnames call, dnlp
* will have candidate for replica scan.
*/
/*
* Doctor the drive string in the error structure to list all of the
* unused disks, rather than just one. The output will be done in the
* following !mdisok() block.
*/
md_ds_error_t *ip =
char *dlist;
int sizecnt = 0;
}
}
}
/* Don't continue if we're already hosed */
}
/* ...or if there's nothing to scan */
}
/* Scan qualified disks */
/* is the current drive on the skip list? */
goto skipdisk;
}
/*
* If current disk is part of a partial diskset,
* meta_get_set_info returns an ENOTSUP for this disk.
* Import of partial disksets isn't supported yet,
* so do NOT put this disk onto any list being set up
* by metaimport. The partial diskset error message will
* only be printed once when the first partial diskset is
* detected. If the user is actually trying to import the
* partial diskset, print the error and exit; otherwise,
* print the error and continue.
*/
if (hasreplica == ENOTSUP) {
if (report_only) {
if (!partial) {
partial = 1;
}
mdclrerror(ep);
goto skipdisk;
} else {
}
}
if (hasreplica < 0) {
mdclrerror(ep);
} else {
md_im_set_desc_t *p;
rscount += hasreplica;
/* Eliminate duplicate reporting */
if (hasreplica > 0) {
/*
* Go to the tail for the current set
*/
p = p->mis_next);
for (d = p->mis_drives;
d != NULL;
d = d->mid_next) {
/*
* if the mb_setcreatetime for a disk
* is not the same as the first disk
* in the set, don't put it on the
* skip list. This disk probably
* doesn't really belong in this set
* and we'll want to look at it again
* to figure out where it does belong.
*/
if ((d->mid_setcreatetimestamp.tv_sec !=
firstdisktime.tv_sec) ||
!= firstdisktime.tv_usec))
continue;
skipt =
}
}
}
;
}
/*
* Now have entire list of disks associated with diskset including
* disks listed in mddb locator blocks and namespace. Before importing
* diskset need to recheck that none of these disks is already in use.
* If a disk is found that is already in use, print error and exit.
*/
if (!report_only) {
md_im_set_desc_t *p;
MDE_DS_DRIVEINUSE, 0, NULL,
}
}
}
}
/*
* If there are no unconfigured sets, then our work here is done.
* Hopefully this is friendlier than just not printing anything at all.
*/
if (rscount == 0) {
/*
* If we've found partial disksets but no complete disksets,
* we don't want this to print.
*/
if (!partial) {
"detected"));
}
}
/*
* We'll need this info for both the report content and the import
* decision. By the time we're here, misp should NOT be NULL (or we
* would have exited in the rscount == 0 test above).
*/
have_multiple_sets = 1;
}
/*
* Generate the appropriate (verbose or not) report for all sets
* detected. If we're planning on importing later, only include the
* "suggested import" command if multiple sets were detected. (That
* way, when we error out later, we have still provided useful
* information.)
*/
/*
* Now we should have all the unconfigured sets detected
* check for the overlapping
*/
if (have_multiple_sets) {
if (!report_only) {
"sets detected.\nRerun the command with the "
"suggested options for the desired set."));
}
}
if (verbose) {
} else {
}
/*
* If it's a report-only request, we're done. If it's an import
* request, make sure that we only have one entry in the set list.
*/
if (report_only) {
} else if (have_multiple_sets) {
}
if (setname_new == NULL) {
}
if (dry_run) {
}
}
}
}
}
/*NOTREACHED*/
return (0);
}