/*
* 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
*/
/*
*/
#include <assert.h>
#include <ctype.h>
#include <libdevinfo.h>
#include <mdiox.h>
#include <meta.h>
#include "meta_repartition.h"
#include "meta_set_prv.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sdssc.h>
typedef struct did_list {
char *devname;
char *minor_name;
char *driver_name;
int available;
int transplanted;
} did_list_t;
typedef struct replicated_disk {
void *old_devid;
void *new_devid;
/*
* The current implementation limits the max device id length to 256 bytes.
* Should the max device id length be increased, this definition would have to
* be bumped up accordingly
*/
/*
* We store a global list of all the replicated disks in the system. In
* order to prevent us from performing a linear search on this list, we
* store the disks in a two dimensional sparse array. The disks are bucketed
* based on the length of their device ids.
*/
/*
* The list of replicated disks is built just once and this flag is set
* once it's done
*/
int replicated_disk_list_built_pass1 = 0;
int replicated_disk_list_built_pass2 = 0;
static int debug_set = 0;
/*
* Debug function: to turn on import function debugging include IMPORT
* in the MD_DEBUG enviroment variable: MD_DEBUG=...,IMPORT...
*/
/*PRINTFLIKE1*/
static void
{
char *p;
if (debug_set == 0) {
else
}
}
}
static void
{
char *devidstr;
char *p;
if (debug_set == 0) {
else
}
return;
} else {
}
}
static void
{
char *p;
if (debug_set == 0) {
else
}
return;
s->mis_active_replicas);
if (d->mid_o_devid) {
} else {
}
d->mid_minor_name);
(void *)d->mid_replicas);
}
}
}
/*
* Map logical blk to physical
*
* This is based on the routine of the same name in the md kernel module (see
* file md_mddb.c), with the following caveats:
*
* - The kernel routine works on in core master blocks, or mddb_mb_ic_t; this
* routine works instead on the mddb_mb_t read directly from the disk
*/
)
{
/*
* Sanity check: is the block within range? If so, we then assume
* that the block range map in the master block is valid and
* consistent with the block count. Unfortunately, there is no
* reliable way to validate this assumption.
*/
return ((daddr_t)-1);
}
/*
* drive_append()
*
* Append to tail of linked list of md_im_drive_info_t.
*
* Will allocate space for new node and copy args into new space.
*
* Returns pointer to new node.
*/
static md_im_drive_info_t *
)
{
int o_devid_sz;
int devid_sz;
;
mdi_debug("Adding drive: %s (minor: %x) to list [timestamp = '%s']\n",
/*
* If rdid is not NULL then we know we are dealing with
* replicated diskset case. 'devid_sz' will always be the
* size of a valid devid which can be 'did' or 'rdid'
*/
if (nonrep_did_listp->rdid) {
devid_sz);
/*
* Also need to store the 'other' devid
*/
} else {
/*
* In the case of regular diskset, midp->mid_o_devid
* will be a NULL pointer
*/
}
if (nonrep_did_listp->minor_name) {
}
if (nonrep_did_listp->driver_name)
if (nonrep_did_listp->devname)
return (midp);
}
/*
* drive_append_wrapper()
*
* Constant time append wrapper; the append function will always walk the list,
* this will take a tail argument and use the append function on just the tail
* node, doing the appropriate old-tail-next-pointer bookkeeping.
*/
static md_im_drive_info_t **
)
{
mirp);
return (tailpp);
}
/*
* replica_append()
*
* Append to tail of linked list of md_im_replica_info_t.
*
* Will allocate space for new node and copy args into new space.
*
* Returns pointer to new node.
*/
static md_im_replica_info_t *
int flags,
)
{
;
return (mirp);
}
/*
* replica_append_wrapper()
*
* Constant time append wrapper; the append function will always walk the list,
* this will take a tail argument and use the append function on just the tail
* node, doing the appropriate old-tail-next-pointer bookkeeping.
*/
static md_im_replica_info_t **
int flags,
)
{
return (tailpp);
}
/*
* map_replica_disk()
*
* Searches the device id list for a specific
* disk based on the locator block device id array index.
*
* Returns a pointer to the did_list node if a match was
* found or NULL otherwise.
*/
static did_list_t *
int did_index
)
{
return (tailp);
}
/* not found, return failure */
return (NULL);
}
/*
* replicated_list_lookup()
*
* looks up a replicated disk entry in the global replicated disk list
* based upon the length of that disk's device id. returns the new device id
* for the disk.
* If you store the returned devid you must create a local copy.
*/
void *
void *old_devid
)
{
return (NULL);
do {
return (NULL);
}
/*
* replicated_list_insert()
*
* inserts a replicated disk entry into the global replicated disk list
*/
static void
void *old_devid,
void *new_devid
)
{
if (*first_entry == NULL) {
*first_entry = repl_disk;
return;
}
}
/*
* meta_didmin_slice
*
* Parse the passed in minor_name and get the slice number contained within it.
* The format of the minor_name is "<unit>,<unit>s<sliceno>,<raw|blk>".
* sliceno is a numeric value 0..7 (corresponding to CTD slice 'a'..'h'
*
* Returns:
* 0 Success
* -1 Error
*/
static int
char *minor_name,
)
{
char *slicep;
int rval = 0;
rval = -1;
} else {
slicep++;
}
return (rval);
}
/*
* get_replica_disks()
*
* Will step through the locator records in the supplied locator block, and add
* each one with an active replica to a supplied list of md_im_drive_info_t, and
* add the appropriate replicas to the md_im_replica_info_t contained therein.
*/
static void
)
{
int flags;
char *minor_name;
int mtype;
on_list = 0;
continue;
/*
* search the device id list for a
* specific ctds based on the locator
* block device id array index.
*/
/*
* metadrivename() can fail for a slice name
* if there is not an existing mddrivename_t.
* So we use metadiskname() to strip the slice
* number.
*/
ep);
mdi_debug("get_replica_disks: repl_name = %s, dnp_rname = %s\n",
/*
* You could get a dnp match, but if 1 disk
* is unavailable and the other isn't, they
* will have the same dnp due
* to the name being the same, but in fact
* are different disks.
*/
replica_disk->available)) {
on_list = 1;
mdi_debug("on_list: avail: %x, %x "
"mid_devname: %s, replica: %s "
"dnp_rname: %s\n",
break;
}
}
}
mdi_debug("Replica disk: %s (minor: %s), available=%x\n",
if (mtype == DID_MIN_NM) {
}
}
/*
* New on the list so add it
*/
if (!on_list) {
/*
* If the disk isn't available, we don't
* want to try to read from it.
*/
/*
* If any of the following checks fail this
* means the set only has partial replicas
* as the locator block still references these.
* Flag this so that we pass the information
* back in misp->mis_partial on completion.
*/
if (mtype == DID_MIN_NM) {
&sliceno) != 0) {
continue;
}
mdi_debug("replica_sliceno %s = %d\n",
} else {
ep) != 0) {
continue;
}
}
/*
* if the replica slice size is zero,
* don't bother opening
*/
mdi_debug("replica_slice %s no partn\n",
continue;
}
mdi_debug("replica_slice %s no slice "
sliceno);
continue;
}
mdi_debug("replica_slice '%s' !OPEN\n",
continue;
}
/*
* a drive may not have a master block
*/
DEV_BSIZE) <= 0) {
mdi_debug("replica_slice %s, MB bad\n",
mdclrerror(ep);
continue;
}
}
}
/*
* For either of these assertions to fail, it implies
* a NULL return from metadrivename() above. Since
* the args came from a presumed valid locator block,
* that's Bad.
*/
/*
* Extract the parameters describing this replica.
*
* The magic "1" in the length calculation accounts
* for the length of the master block, in addition to
* the block count it describes. (The master block
* will always take up one block on the disk, and
* there will always only be one master block per
* replica, even though much of the code is structured
* to handle noncontiguous replicas.)
*/
/*
* If we're here it means -
*
* we've added the disk to the list of
* disks.
*/
/*
* We need to bump up the number of active
* replica count for each such replica that is
* active so that it can be used later for replica
* quorum check.
*/
if (flags & MDDB_F_ACTIVE) {
}
}
/*
* Update the partial state of the set. This is determined from
* any non-existent or bad replicas discovered while traversing the
* replica-list above.
*/
}
/*
* Take a minor name from a SunCluster did device, and return a
* standard Solaris minor name for the corresponding slice. The
* caller is responsible for verifying that the input argument
* is a did style minor name and for freeing the returned memory.
*/
static char *
{
char *slicep;
char c;
return (NULL);
slicep++;
c = *(slicep + 1);
*(slicep) += 0x31;
*(slicep + 1) = c;
*(slicep) -= 0x31;
return (retstr);
}
/*
* meta_didmin_expand:
*
* Convert a dXsN minor to the corresponding X,XsN,blk fully qualified
* DID minor name
*/
static char *
{
char *p, *tempstr;
char *slice;
if (*tempstr != 'd') {
return (retstr);
}
return (retstr);
}
*slice = '\0';
slice++;
/*
* Constructed DID minor is <UNIT>,<UNIT>sX,blk
* i.e., 2xUNIT + 7 + 1 (terminator)
*/
return (retstr);
}
/*
* append_pnm_rec()
*
* Append pnm_rec_t entry to list of physical devices in the diskset. Entry
* contains a mapping of n_key in NM namespace(or min_key in DID_NM namespace)
* to name of the physical device. This list will be used to ensure that the
* correct names of the physical devices are printed in the metastat output--the
* NM namespace might have stale information about where the physical devices
* were previously located when the diskset was last active.
*/
static void
char *n_name
)
{
char *p;
int len;
p++;
/*
* Allocates pnm_rec_t record for the physical
* device.
*/
/*
* Adds new element to head of pnm_rec_t list.
*/
} else {
}
}
/*
* free_pnm_rec_list()
*
* Freeing all pnm_rec_t entries on the list of physical devices in the
* diskset.
*/
void
{
}
}
/*
* meta_stdmin_to_didmin:
*
* Take a CTD-based replica devid,minor and convert to a corresponding DID
* devid,minor. Need to traverse the list of potential devices matching the
* the specified devid (with no minor) and then find the entry which matches
* the CTD-based 'g', or 'h' minor number
*/
static char *
char *search_path, /* Search patch for devices */
char *repl_minor, /* Replica minor_name (CTD) */
)
{
int i, ret;
char c;
c = *repl_minor;
mdi_debug("meta_stdmin_to_didmin: minor = '%c'\n", c);
if (c < 'a' || c > 'h') {
mdi_debug("Invalid minor_name - not converting\n");
return (retstr);
}
c -= 0x31; /* Convert to 0..7 from a..h */
/*
* Now generate the list of all matching disks for the specified
* devid.
*/
if (ret < 0) {
mdi_debug("devid_deviceid_to_nmlist: FAILED returned %d\n",
ret);
return (retstr);
}
/*
* Traverse the list looking for a matching s<X> entry where <X> == 'c'
* Once we find this we then need to convert it to "U,UsX,blk" so
* that the device lookup works. We need to skip any 'rdsk' entries.
*/
/* Last part of device name '/dXsN' */
continue;
/* Make sure this isn't the raw-device */
continue;
minp++;
continue;
slicep++;
if (*slicep == c) {
/*
* minp+1 .. cslicep = unit number
*/
break;
}
}
return (retstr);
}
/*
* get_disks_from_didnamespace()
* This function was origionally called: get_nonreplica_disks()
*
* Extracts the disks without replicas from the locator name space and adds them
* to the supplied list of md_im_drive_info_t.
* If the print verbose option was given then this function will also
* correct the nm namespace so that the n_name is the right ctd name
*/
static void
int replicated,
)
{
int mtype;
char *minor_name;
char *searchp;
int on_list = 0;
void *valid_did;
int avail = 0;
int clboot = 0;
clboot = 0;
if (clboot != 0)
else
/*
* We got a pointer to an mddb record, which we expect to contain a
* name record; extract the pointer thereto.
*/
/* LINTED */
/* LINTED */
did_shr_rec = (struct devid_shr_rec *)
/* LINTED */
/* LINTED */
/*
* Skip the nm_rec_hdr and iterate on the array of struct minor_name
* at the end of the devid_min_rec
*/
/* LINTED */
on_list = 0;
mdi_debug("Non-replica: minor key: %d (replicated: %d)\n",
/*
* For a given DID_NM key, locate the corresponding device
* id from DID_NM_SHR
*/
/* LINTED */
did = (struct did_shr_name *)
/*
* We got a match, this is the device id we're
* looking for
*/
break;
}
/* we didn't find a match */
}
mdi_debug("Non-replica: found did->did_key: %d\n",
mdi_dump_devid("Non-replica devid",
/*
* If replicated diskset
*/
if (replicated) {
char *temp;
/*
* In this case, did->did_devid will
* be invalid so lookup the real one
*/
/* we have a partial replicated set, fake it */
} else {
}
mdi_dump_devid("Non-replica: replicated devid",
} else {
}
/*
* If the minor name retrieved from the replica
* is from the did driver, convert it to a normal
* minor name for use in meta_deviceid_to_nmlist()
* Note: we have to handle importing a DID-style device
* which may not match our view of the device namespace.
* We can get the correct DID device by searching for the
* corresponding devid + minor_name (gleaned from the CTD
* version of the original did name).
*/
if (clboot) {
/*
* Importing into a SC namespace so we have to handle
* DID drive movement. min_name -> ctd -> new_did
*/
if (mtype == DID_MIN_NM) {
NULL);
} else {
}
} else {
if (mtype == DID_MIN_NM) {
} else {
}
}
/*
* Get a ctds mapping for that device id.
* Since disk is being imported into this system,
* just use the first ctds in list.
*/
/*
* We know the disk is available. Use the
* device information in nmlist.
*/
avail = 0;
mdi_debug("Non-replica: devname = '%s', mnum = 0x%x,"
" minor_name = '%s'\n",
if (mtype == DID_MIN_NM) {
}
} else {
/*
* The disk is not available. That means we need to
* use the (old) device information stored in the
* namespace.
*/
/* search in nm space for a match */
sizeof (struct nm_name);
/* LINTED */
break;
if ((int)used_size <= 0) {
}
}
}
/*
* Use the namespace n_dir_key to look in the
* shared namespace. When we find the matching
* key, that is the devname and minor number we
* want.
*/
offset = sizeof (struct nm_shr_rec) -
sizeof (struct nm_shared_name);
while (key != 0) {
/*
* This complicated looking series
* of code creates a devname of the
* form <sn_name>/<n_name> which
*/
(void) strlcpy(
(void) strlcat(
(void) strlcat(
break;
}
/* LINTED */
SHR_NAMSIZ(snmp));
if ((int)used_size <= 0) {
}
}
if (key == 0) {
mnum = 0;
}
avail = 1;
/*
* Use the namespace n_drv_key to look in the
* shared namespace. When we find the matching
* key, that is the driver name for the disk.
*/
offset = sizeof (struct nm_shr_rec) -
sizeof (struct nm_shared_name);
while (key != 0) {
break;
}
/* LINTED */
SHR_NAMSIZ(snmp));
if ((int)used_size <= 0) {
}
}
if (key == 0)
}
/* Is it already on the list? */
if (midp->mid_available ==
on_list = 1;
break;
}
}
}
if (!on_list) {
/*
* Add drive to pnm_rec_t list of physical devices for
* metastat output.
*/
if (imp_flags & META_IMP_VERBOSE) {
}
if (!avail) {
/* determine the replica slice */
ep) != 0) {
continue;
}
/*
* if the replica slice size is zero,
* don't bother opening
*/
== 0) {
continue;
}
continue;
}
continue;
}
/*
* a drive may not have a master block
*/
DEV_BSIZE) <= 0) {
mdclrerror(ep);
continue;
}
}
/*
* If it is replicated diskset,
* r_did will be non-NULL.
* Passing the devname as NULL because field
* is not currently used for a non-replica disk.
*/
}
}
}
/*
* set_append()
*
* Append to tail of linked list of md_im_set_desc_t.
*
* Will allocate space for new node AND populate it by extracting disks with
* and without replicas from the locator blocks and locator namespace.
*
* Returns pointer to new node.
*/
static md_im_set_desc_t *
)
{
/* run to end of list */
;
/* allocate new list element */
if (replicated)
if (imp_flags & MD_IM_SET_MULTINODE)
/* Get the disks with and without replicas */
}
/*
* An error in this struct could come from either of
* the above routines;
* in both cases, we want to pass it back on up.
*/
return (misp);
}
/*
* add_disk_names()
*
* Iterator to walk the minor node tree of the device snapshot, adding only the
* first non-block instance of each non-cdrom minor node to a list of disks.
*/
static int
{
/*
* skip CD devices
* If a device does not have a device id, we can't
* do anything with it so just exclude it from our
* list.
*
* This would also encompass CD devices and floppy
* devices that don't have a device id.
*/
return (DI_WALK_CONTINUE);
}
/* char disk devices (as opposed to block) */
/* only first occurrence (slice 0) of each instance */
}
}
}
return (DI_WALK_CONTINUE);
}
/*
* meta_list_disks()
*
* Snapshots the device tree and extracts disk devices from the snapshot.
*/
int
{
== DI_NODE_NIL) {
}
return (0);
}
/*
* meta_imp_drvused
*
* Checks if given drive is mounted, swapped, part of disk configuration
* or in use by SVM. ep also has error code set up if drive is in use.
*
* Returns 1 if drive is in use.
* Returns 0 if drive is not in use.
*/
int
)
{
/*
* We pass in db_ep to meta_setup_db_locations
* and never ever use the error contained therein
* because all we're interested in is a check to
* see whether any local metadbs are present.
*/
(((meta_setup_db_locations(db_ep) == 0) &&
return (1);
} else {
return (0);
}
}
/*
* meta_prune_cnames()
*
* Removes in-use disks from the list prior to further processing.
*
* Return value depends on err_on_prune flag: if set, and one or more disks
* are pruned, the return list will be the pruned disks. If not set, or if no
* disks are pruned, the return list will be the unpruned disks.
*/
md_error_t *ep,
int err_on_prune
)
{
int d;
int fcount = 0;
/*
* Assuming we're interested in knowing about
* whatever error occurred, but not in stopping.
*/
mdclrerror(ep);
continue;
}
/*
* Check if the drive is inuse.
*/
fcount++;
mdclrerror(ep);
} else {
}
}
if (fcount) {
if (err_on_prune) {
char *name;
/*
* Use the cname in output if the device is a ctd style
* disk, otherwise use the full path of the raw device.
*/
return (fdnlp);
}
}
return (dnlp);
}
/*
* read_master_block()
*
* Returns:
* < 0 for failure
* 0 for no valid master block
* 1 for valid master block
*
* The supplied buffer will be filled in for EITHER 0 or 1.
*/
int
md_error_t *ep,
int fd,
void *bp,
int bsize
)
{
/*
* The master block magic number can either be MDDB_MAGIC_MB in
* the case of a real master block, or, it can be MDDB_MAGIC_DU
* in the case of a dummy master block
*/
rval = 0;
}
rval = 0;
}
return (rval);
}
/*
* read_locator_block()
*
* Returns:
* < 0 for failure
* 0 for no valid locator block
* 1 for valid locator block
*/
int
md_error_t *ep,
int fd,
void *bp,
int bsize
)
{
}
int
md_error_t *ep,
int fd,
void *bp,
int bcount
)
{
return (bcount);
}
/*
* read_locator_block_did()
*
* Returns:
* < 0 for failure
* 0 for no valid locator name struct
* 1 for valid locator name struct
*/
int
md_error_t *ep,
int fd,
void *bp,
int bsize
)
{
int rval;
return (rval);
}
/*
* read_locator_names()
*
* Returns:
* < 0 for failure
* 0 for no valid locator name struct
* 1 for valid locator name struct
*/
int
md_error_t *ep,
int fd,
void *bp,
int bsize
)
{
int rval;
return (rval);
}
int
md_error_t *ep,
int fd,
int dbblk,
void *bp,
int bsize
)
{
int rval;
return (rval);
}
int
md_error_t *ep,
int fd,
int didblk,
void *bp,
int bsize
)
{
int rval;
return (rval);
}
int
md_error_t *ep,
int fd,
int infoblk,
void *bp,
int bsize
)
{
return (rval);
}
/*
* meta_nm_rec()
*
* Return the DE corresponding to the requested namespace record type.
* Modifies dbp to have a firstentry if one isn't there.
*/
static mddb_de_t *
{
int desize;
/* LINTED */
+ sizeof (dbp->db_firstentry));
/* LINTED */
}
}
break;
}
return (dep);
}
/*
* read_nm_rec()
*
* Reads the NM, NM_DID or NM_DID_SHR record in the mddb and stores the
* configuration data in the buffer 'nm'
*
* Returns:
* < 0 for failure
* 0 for no valid NM/DID_NM/DID_NM_SHR record
* 1 for valid NM/DID_NM/DID_NM_SHR record
*
*/
static int
md_error_t *ep,
int fd,
char **nm,
char *diskname
)
{
/*LINTED*/
dbblk != 0;
sizeof (db))) <= 0)
return (rval);
/*
* Locate NM/DID_NM/DID_NM_SHR record. Normally there is
* only one record per mddb. There is a rare case when we
* can't expand the record. If this is the case then we
* will have multiple NM/DID_NM/DID_NM_SHR records linked
* with r_next_recid.
*
* For now assume the normal case and handle the extended
* namespace in Phase 2.
*/
break;
}
/* If meta_nm_rec() never succeeded, bail out */
return (0);
/* Read in the appropriate record and return configurations */
return (rval);
}
return (rval);
}
return (rval);
}
}
return (1);
}
/*
* is_replicated
*
* Determines whether a disk has been replicated or not. It checks to see
* if the device id stored in the master block is the same as the device id
* registered for that disk on the current system. If the two device ids are
* different, then we know that the disk has been replicated.
*
* If need_devid is set and the disk is replicated, fill in the new_devid.
* Also, if need_devid is set, this routine allocates memory for the device
* ids; the caller of this routine is responsible for free'ing up the memory.
*
* Returns:
* MD_IM_SET_REPLICATED if it's a replicated disk
* 0 if it's not a replicated disk
*/
static int
int fd,
int need_devid,
void **new_devid
)
{
int retval = 0;
return (retval);
return (retval);
if (retval && need_devid) {
}
return (retval);
}
/*
* free_replicated_disks_list()
*
* this frees up all the memory allocated by build_replicated_disks_list
*/
static void
{
int index;
}
}
}
/*
* build_replicated_disks_list()
*
* Builds a list of disks that have been replicated using either a
* remote replication or a point-in-time replication software. The
* list is stored as a two dimensional sparse array.
*
* Returns
* 1 on success
* 0 on failure
*/
int
md_error_t *ep,
)
{
void *new_devid;
/* determine the replica slice */
continue;
/*
* if the replica slice size is zero, don't bother opening
*/
continue;
continue;
/* a drive may not have a master block so we just continue */
mdclrerror(ep);
continue;
}
}
}
return (1);
}
/*
* free_did_list()
*
* Frees the did_list allocated as part of build_did_list
*/
static void
)
{
if (temp->minor_name)
if (temp->driver_name)
}
}
/*
* meta_free_im_replica_info
*
* Frees the md_im_replica_info list
*/
static void
)
{
r = mirp;
while (r != NULL) {
temp = r;
r = r->mir_next;
}
}
/*
* meta_free_im_drive_info
*
* Frees the md_im_drive_info list
*/
static void
)
{
d = midp;
while (d != NULL) {
temp = d;
d = d->mid_next;
/*
* dnp is not on the drivenamelist and is a temp
* dnp for metaimport if the disk is unavailable.
* We need to specifically free it because of this.
* If the disk is available, standard drivelist freeing
* will kick in so we don't need to do it.
*/
if (temp->mid_o_devid)
if (temp->mid_driver_name)
if (temp->mid_devname)
if (temp->mid_replicas) {
}
}
}
}
/*
* meta_free_im_set_desc
*
* Frees the md_im_set_desc_t list
*/
void
)
{
s = misp;
while (s != NULL) {
temp = s;
s = s->mis_next;
if (temp->mis_drives) {
}
}
}
/*
* build_did_list()
*
* Build a list of device ids corresponding to disks in the locator block.
* Memory is allocated here for the nodes in the did_list. The callers of
* this routine must also call free_did_list to free up the memory after
* they're done.
*
* Returns:
* < 0 for failure
* 0 for no valid locator block device id array
* 1 for valid locator block device id array
* ENOTSUP partial diskset, not all disks in a diskset on the
* system where import is being executed
*/
static int
md_error_t *ep,
int fd,
int *replicatedp
)
{
int xlate_devname = 0;
int partial = 0;
int partial_replicated = 0;
char *searchp;
char *devidstr;
int transplanted = 0;
int ntransplanted = 0;
/*
* If the call to cladm fails, try to carry on as a non-SC node.
*/
clboot = 0;
} else {
}
partial_replicated = 0;
continue;
/*
* If we can re-use the buffer that has already been
* read in then just use it. Otherwise free
* the previous one and alloc a new one
*/
if (bp)
(void *)bp, did_info_length) < 0) {
/*
* Failed to read did_info, probably a partial
* set so we should return ENOTSUP... not -1
*/
mdi_debug("build_did_list: phys_read failed"
" did_info_minor = '%s'\n",
return (ENOTSUP);
}
} else {
}
/*
* If we are not able to find the ctd mapping corresponding
* to a given device id, it probably means the device id in
* question is not registered with the system.
*
* Highly likely that the only time this happens, we've hit
* a case where not all the disks that are a part of the
* diskset were moved before importing the diskset.
*
* If set is a replicated diskset, then the device id we get
* from 'lb' will be the 'other' did and we need to lookup
* the real one before we call this routine.
*/
if (*replicatedp) {
/* we have a partial replicated set, fake it */
mdi_debug("partial 2\n");
partial_replicated = 1;
} else {
}
} else {
}
return (-1);
}
/*
* Need to verify the lbp derived devid + minor-name to
* see if the device is accessible on this system. If the
* devid lookup fails we may have a transplanted disk to handle.
* This can happen due to a change in enumeration or by a
* modification of the DID mapping. In this case we need to
* establish the set as a Replicated one and let the kernel
* fix up the correct entries (which we can determine here)
*/
/*
* We've got a valid devid, so lets see _what_ we're actually
* passing around. Note: minor_name is the replica-based
* minor-name.
*/
mdi_debug("Couldn't encode devid for minor '%s'\n",
} else {
}
/*
* Note: we only know that devidstr is a valid format. We need
* to check for the actual existence of it if we're running
* with a DID minor name.
*/
/*
* The minor name type stored in the devid info block (mtype)
* and the minor name type derived from the fd given to
* us by the command line (ttype) might not match. If they
* don't match, we won't be able to find the locator blocks
* and the import will fail. Determine both types to see
* if corrective action is required.
* Note: there is a corner-case with EFI / SMI labelled disks
* in the same set. In this case the minor from the local disk
* replica (fd->this_minor) will not produce a match for the
* devid->minor_name path when passed to meta_deviceid_to_nmlist
*/
if (this_minor != NULL)
return (-1);
}
/*
* Note: the device associated with 'this_minor' is an
* arbitrary replica (typically slice 7). If we have a set
* which mixes EFI and SMI labelled devices we need to make
* sure that we look for a minor that corresponds to the mtype
* minor [can be obtained from meta_stdmin_to_didmin()].
* This needs to be done in all cases, not just SC
*/
/*
* See what the command-line minor + devid results in
*/
mdi_debug("Couldn't encode devid for minor '%s'\n",
} else {
mdi_debug("Devid_this_minor '%s', minor '%s'\n",
}
/*
* minor_name is replica minor_name and matches the devid
* Just have to handle the DID -> CTD and vice-versa conversion
*/
if (ttype == DID_MIN_NM) {
if (mtype == DID_MIN_NM) {
int ret;
char slice_c;
minor_name, &retlist);
if (ret < 0) {
/*
* devid-ID is valid, but devid + minor
* isn't. This is most likely a
* transplant
*/
transplanted = 1;
mdi_debug("%s possible transplant\n",
devidstr);
&sliceno) < 0) {
partial = 1;
transplanted = 0;
continue;
}
/*
* Construct the CTD minor-name to find
* This is simply the slice-name
* 'a'..'h'.
* We extract the DID slice from the
* replica minor name.
*/
&new_dev);
/*
* Populate pseudo-replicated structure
* elements
*/
/* Flag this as a replicated disk ... */
/*
* Update the devname to reflect the new
* disk name.
*/
len);
if (transplanted) {
}
mdi_debug("Transplanted minor '%s'"
" to '%s', dev %s\n",
continue;
} else {
/*
* devid + DID minor is valid, nothing
* else to do.
*/
&sliceno) < 0) {
partial = 1;
continue;
}
}
} else {
/*
* Importing from CTD to DID
*/
}
} else {
/*
* Converting to CTD namespace
*/
if (mtype == DID_MIN_NM) {
/*
* DID -> CTD => extract DID slice and find
* minor-name entry did,<ctd-minor>
*/
} else {
/*
* CTD -> CTD => verify did,minor exists
*/
}
}
/*
* See what we're trying to look for (devid + minor_name)
*/
mdi_debug("mdtn: couldn't encode devid for '%s'\n",
} else {
mdi_debug("Calling mdtn for devid '%s', minor '%s'\n",
}
int len = 0;
/*
* Partial diskset case. We'll need to get the
* device information from the metadb instead
* of the output (nm) of meta_deviceid_to_nmlist.
*/
if (mnset == 0) {
} else {
mn_ln_sideno != MD_SIDEWILD) {
break;
}
}
if (side == MD_MNMAXSIDES)
return (-1);
}
mdi_debug("Partial set [3]: mnlnp at 0x%p, pre='%s', "
continue;
}
/*
* Disk is there. Grab device information from nm structure.
*/
if (xlate_devname != 0) {
mdi_debug("xlate_devname: minor '%s', devname '%s'\n",
} else {
}
}
/*
* Flag this set as being replicated if we've encountered any pathname
* transplants during the list creation.
*/
if (ntransplanted > 0) {
}
/* Free the last bp */
if (bp)
if (partial)
return (partial);
return (1);
}
/*
* meta_ctds_to_dids
*
* If in a SunCluster environment, check all the min_names, and if
* they are ctd names convert them to did names, freeing the memory
* for the original ctd names.
*/
void
{
int i;
char *didp;
int clboot = 0;
return;
if (clboot == 0)
return;
/* skip and names already in did format */
continue;
if (sc_ret == SDSSC_OKAY) {
}
}
}
/*
* check_nm_disks
* Checks the disks listed in the shared did namespace to see if they
* are accessable on the system. If not, return ENOTSUP error to
* indicate we have a partial diskset.
* Returns:
* < 0 for failure
* 0 success
* ENOTSUP partial diskset, not all disks in a diskset on the
* system where import is being executed
*/
static int
struct devid_min_rec *did_nmp,
struct devid_shr_rec *did_shrnmp
)
{
int mtype;
void *did_min_namep;
void *did_shr_namep;
sizeof (struct nm_rec_hdr);
sizeof (struct nm_rec_hdr);
while (used_size > (int)sizeof (struct did_shr_name)) {
/* grab device id and minor name from the shared spaces */
if (devid_valid(did) == 0) {
return (-1);
}
/*
* We need to check that the DID_NM and DID_SHR_NM are in
* sync. It is possible that we took a panic between writing
* the two areas to disk. This would be cleaned up on the
* next snarf but we don't know for sure that snarf has even
* happened since we're reading from disk.
*/
did_min_namep = ((void *)((char *)did_min_namep +
did_nsize));
if (min_used_size < (int)sizeof (struct did_min_name))
continue;
}
/*
* If the minor name retrieved from the replica
* is from the did driver, convert it to a normal
* minor name for use in meta_deviceid_to_nmlist()
*/
if (mtype == DID_MIN_NM) {
if (minor_name == NULL)
return (-1);
} else {
}
/*
* Try to find disk in the system. If we can't find the
* disk, we have a partial diskset.
*/
/* Partial diskset detected */
mdi_debug("check_nm_disks: Partial '%s' 3\n",
return (ENOTSUP);
}
/* increment to next item in the shared spaces */
did_shr_namep = ((void *)((char *)did_shr_namep +
}
return (0);
}
/*
* report_metadb_info()
*
* Generates metadb output for the diskset.
*
*/
static void
char *indent
)
{
int i;
/*
* Looping through all drives in the diskset to print
* out information about the drive and if the verbose
* option is set print out replica data.
*/
if (d->mid_replicas != NULL) {
for (r = d->mid_replicas; r != NULL;
r = r->mir_next) {
for (i = 0; i < MDDB_FLAGS_LEN; i++) {
if (r->mir_flags & (1 << i)) {
(void) putchar(
MDDB_FLAGS_STRING[i]);
} else {
(void) putchar(' ');
}
}
== -1)) {
(void) printf("%7.7s\t\t%7.7s\t",
} else if (r->mir_length == -1) {
(void) printf("%i\t\t%7.7s\t",
r->mir_offset, unk_str);
} else {
(void) printf("%i\t\t%i\t",
r->mir_offset, r->mir_length);
}
(void) printf("\t%s\n",
d->mid_devname);
}
}
}
(void) printf("\n");
}
/*
* meta_replica_quorum will determine if the disks in the set to be
* imported have enough valid replicas to have quorum.
*
* RETURN:
* -1 Set doesn't have quorum
* 0 Set does have quorum
*/
int
)
{
int replica_count = 0;
continue;
/*
* The drive is okay. Now count its replicas
*/
}
}
/* odd number of replicas */
return (-1);
} else {
/* even number of replicas */
return (-1);
}
return (0);
}
/*
* Choose the best drive to use for the metaimport command.
*/
{
/* drive must be available */
continue;
}
/* replica must be active to be a good one */
break;
}
}
}
}
return (good_disk);
}
/*
* report_set_info()
*
* Returns:
* < 0 for failure
* 0 for success
*
*/
static int
int fd,
int set_count,
int overlap,
)
{
int rval = 0;
int i;
int has_overlap = 0;
int no_quorum = 0;
int partial = 0;
/* Calculates the correct indentation. */
indent[0] = 0;
for (i = 0; i < in; i++)
/*
* This will print before the information for the first diskset
* if the verbose option was set.
*/
if (set_count == 1) {
if (imp_flags & META_IMP_REPORT) {
(void) printf("\n%s:\n\n",
gettext("Disksets eligible for import"));
}
}
return (rval);
}
/*
* Make the distinction between a regular diskset and
* a replicated diskset. Also make the distinction
* between a partial vs. full diskset.
*/
if (partial == MD_IM_PARTIAL_DISKSET) {
if (imp_flags & META_IMP_REPORT) {
"Found partial replicated "
"multi-owner diskset"
" containing disks") :
"Found partial replicated regular"
" diskset containing disks"));
} else {
(void) printf("\n%s:\n",
"Importing partial replicated"
" multi-owner diskset containing"
" disks") :
"Importing partial replicated"
" diskset containing disks"));
}
} else {
if (imp_flags & META_IMP_REPORT) {
"Found partial multi-owner diskset"
" containing disks") :
"Found partial regular diskset"
" containing disks"));
} else {
(void) printf("\n%s:\n",
"Importing partial multi-owner"
" diskset containing disks") :
"Importing partial regular diskset"
" containing disks"));
}
}
} else {
if (imp_flags & META_IMP_REPORT) {
"Found replicated multi-owner"
" diskset containing disks") :
"Found replicated diskset"
" containing disks"));
} else {
(void) printf("\n%s:\n",
"Importing replicated multi-owner"
" diskset containing disks") :
"Importing replicated diskset"
" containing disks"));
}
} else {
if (imp_flags & META_IMP_REPORT) {
"Found multi-owner diskset"
" containing disks") :
"Found regular diskset containing"
" disks"));
} else {
(void) printf("\n%s:\n",
gettext("Importing multi-owner diskset"
" containing disks") :
gettext("Importing regular diskset"
" containing disks"));
}
}
}
/*
* Check each drive in the set. If it's unavailable or
* an overlap tell the user.
*/
char *name;
/*
* Use the cname in output if the device is a ctd style
* disk, otherwise use the full path of the raw device.
*/
if (MD_IS_DISK_UNAVAILABLE(d->mid_available)) {
}
if (overlap) {
/*
* There is the potential for an overlap, see if
* this disk is one of the overlapped disks.
*/
has_overlap = 1;
break;
}
}
}
}
/*
* This note explains the (UNAVAIL) that appears next to the
* disks in the diskset that are not available.
*/
if (partial) {
gettext("(UNAVAIL) WARNING: This disk is unavailable on"
"data in the diskset."));
}
/*
* This note explains the (CONFLICT) that appears next to the
* disks whose lb_inittime timestamp does not
* match the rest of the diskset.
*/
if (has_overlap) {
gettext("(CONFLICT) WARNING: This disk has been reused in "
"another diskset or system configuration."), indent,
gettext("Import may corrupt data in the diskset."));
}
/*
* If the verbose flag was given on the command line,
* we will print out the metastat -c information , the
* creation time, and last modified time for the diskset.
*/
if (imp_flags & META_IMP_VERBOSE) {
gettext("Metadatabase information:"));
/*
* Printing creation time and last modified time.
* Last modified: uses the global variable "lastaccess",
* which is set to the last updated timestamp from all of
* the database blocks(db_timestamp) or record blocks
* (rb_timestamp).
* Creation time is the locator block init time
* (lb_inittime).
*/
gettext("Metadevice information:"));
&lastaccess, ep);
if (rval < 0) {
return (rval);
}
gettext("Creation time"),
gettext("Last modified time"),
} else {
/*
* Even if the verbose option is not set, we will print the
* creation time for the diskset.
*/
}
/*
* If the diskset is not actually being imported, then we
* print out extra information about how to import it.
* If the verbose flag was not set, then we will also
* print out information about how to obtain verbose output.
*/
if (imp_flags & META_IMP_REPORT) {
char *name;
/*
* Use the cname in output if the device is a ctd style
* disk, otherwise use the full path of the raw device.
*/
/*
* 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.
*/
if (!(imp_flags & META_IMP_VERBOSE)) {
gettext("For more information about this diskset"),
}
if (meta_replica_quorum(misp) != 0)
no_quorum = 1;
/*
* 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.
*/
(void) printf("%s%s:\n%s %s -f -s <newsetname> %s\n",
} else {
(void) printf("%s%s:\n%s %s -s <newsetname> %s\n",
}
}
(void) printf("\n\n");
return (rval);
}
/*
* meta_get_and_report_set_info
*
* Scans a given drive for set specific information. If the given drive
* has a shared metadb, scans the shared metadb for information pertaining
* to the set.
* If imp_flags has META_IMP_PASS1 set don't report.
*
* Returns:
* <0 for failure
* 0 success but no replicas were found
* 1 success and a replica was found
*/
int
int local_mb_ok,
int *set_count,
int overlap,
)
{
uint_t s;
int fd;
int rval = 0;
int extended_namespace = 0;
int replicated = 0;
int partial = 0;
int mnset;
/*
* Determine and open the replica slice
*/
return (-1);
}
/*
* Test for the size of replica slice in question. If
* the size is zero, we know that this is not a disk that was
* part of a set and it should be silently ignored for import.
*/
return (0);
return (-1);
}
/*
* After the open() succeeds, we should return via the "out"
* label to clean up after ourselves. (Up 'til now, we can
* just return directly, because there are no resources to
* give back.)
*/
goto out;
if (mnset != 0)
rval = 0;
goto out;
}
goto out;
/*
* Once the locator block has been read, we need to
* check if the locator block commit count is zero.
* If it is zero, we know that the replica we're dealing
* with is on a disk that was deleted from the disk set;
* and, it potentially has stale data. We need to quit
* in that case
*/
if (lbp->lb_commitcnt == 0) {
rval = 0;
goto out;
}
/*
* Make sure that the disk being imported has device id
* namespace present for disksets. If a disk doesn't have
* device id namespace, we skip reading the replica on that disk
*/
rval = 0;
goto out;
}
/*
* Grab the locator block device id array. Allocate memory for the
* array first.
*/
lbdid_size)) <= 0)
goto out;
/*
* For a disk that has not been replicated, extract the device ids
* stored in the locator block device id array and store them in
* a list.
*
* If the disk has been replicated using replication software such
* as HDS Truecopy/ShadowImage or EMC SRDF/BCV, the device ids in
* the locator block are invalid and we need to build a list of
* replicated disks.
*/
if (imp_flags & META_IMP_PASS1) {
/*
* We need to do this for both passes but
* replicated_disk_list_built is global so we need some way
* to determine which pass we're on. Set it to the appropriate
* pass's flag.
*/
} else {
}
if (replicated && !(*replicated_disk_list_built)) {
/*
* if there's a replicated diskset involved, we need to
* scan the system one more time and build a list of all
* candidate disks that might be part of that replicated set
*/
rval = 0;
goto out;
}
if (rval == 0)
goto out;
}
/*
* Until here, we've gotten away with fixed sizes for the
* master block and locator block. The locator names,
* however, are sized (and therefore allocated) dynamically
* according to information in the locator block.
*/
lnsize)) <= 0)
goto out;
&replicated);
/*
* An rval of ENOTSUP means we have a partial diskset. We'll want
* to set the partial variable so we can pass this information
* set_append_wrapper later for placing on the misp list.
*/
mdi_debug("meta_get_and_report_set: %s: PARTIAL diskset [1]\n",
}
if (rval < 0)
goto out;
/*
* Read in the NM record
* If no NM record was found, it still is a valid configuration
* but it also means that we won't find any corresponding DID_NM
* or DID_SHR_NM.
*/
< 0)
goto out;
else if (rval == 0)
goto append;
/*
* At this point, we have read in all of the blocks that form
* the nm_rec. We should at least detect the corner case
* mentioned above, in which r_next_recid links to another
* nm_rec. Extended namespace handling is left for Phase 2.
*
* What this should really be is a loop, each iteration of
* which reads in a nm_rec and calls the set_append().
*/
/*LINTED*/
extended_namespace = 1;
rval = 0;
goto out;
}
goto out;
else if (rval == 0)
goto append;
/*LINTED*/
extended_namespace = 1;
rval = 0;
goto out;
}
goto out;
else if (rval == 0)
goto append;
/*LINTED*/
sizeof (int));
extended_namespace = 1;
rval = 0;
goto out;
}
goto out;
else if (rval == 0)
goto append;
/*LINTED*/
sizeof (int));
extended_namespace = 1;
rval = 0;
goto out;
}
/*
* We need to check if all of the disks listed in the namespace
* are actually available. If they aren't we'll return with
* an ENOTSUP error which indicates a partial diskset.
*/
/*
* An rval of ENOTSUP means we have a partial diskset. We'll want
* to set the partial variable so we can pass this information
* to set_append_wrapper later for placing on the misp list.
*/
mdi_debug("mdi_get_and_report_set: %s: PARTIAL diskset [2]\n",
}
if (rval < 0)
goto out;
/* Finally, we've got what we need to process this replica. */
/*LINTED*/
/*LINTED*/
if (!(imp_flags & META_IMP_PASS1)) {
*set_count += 1;
/*LINTED*/
if (rval < 0)
goto out;
}
/* Return the fact that we found at least one set */
rval = 1;
out:
if (fd >= 0)
/*
* If we are at the end of the list, we must free up
* the replicated list too
*/
if (extended_namespace)
return (rval);
}
/*
* meta_update_mb_did
*
* Update or create the master block with the new set number.
* If a non-null devid pointer is given, the devid in the
* master block will also be changed.
*
* This routine is called during the import of a diskset
* (meta_imp_update_mb) and during the take of a diskset that has
* some unresolved replicated drives (meta_unrslv_replicated_mb).
*
* Returns : nothing (void)
*/
static void
void *new_devid, /* devid to be stored in mb */
int new_devid_len,
void *old_devid, /* old devid stored in mb */
int replica_present, /* does replica follow mb? */
int offset,
)
{
int fd;
/* determine the replica slice */
return;
}
/*
* if the replica slice size is zero,
* don't bother opening
*/
return;
}
return;
}
return;
}
return;
return;
}
/* If no replica on disk, check for dummy mb */
if (replica_present == NULL) {
/*
* Check to see if there is a dummy there. If not
* create one. This would happen if the set was
* created before the master block dummy code was
* implemented.
*/
return;
}
}
return;
}
/*
* If a old_devid is non-NULL then we're are dealing with a
* replicated diskset and the devid needs to be updated.
*/
if (old_devid) {
if (mbp->mb_devid_len)
mbp->mb_devid_len);
(char *)new_devid, new_devid_len);
}
}
/*
* Now write out the changes to disk.
* If an error occurs, just continue on.
* Next take of set will register this drive as
* an unresolved replicated drive and will attempt
* to fix the master block again.
*/
return;
}
return;
}
}
/*
* meta_imp_update_mb
*
* Update the master block information during an import.
* Takes an import set descriptor.
*
* Returns : nothing (void)
*/
void
{
/*
* If disk isn't available we can't update, so go to next
*/
continue;
}
if (midp->mid_replicas) {
/*
* If we have replicas on this disk we need to make
* sure that we update the master block on every
* replica on the disk.
*/
}
} else {
/* No replicas, just update the one dummy mb */
}
return;
}
}
/*
* meta_unrslv_replicated_common
*
* Given a drive_desc and a drivenamelist pointer,
* return the devidp associated with the drive_desc,
* the replicated (new) devidp associated with the drive_desc
* and the specific mddrivename in the drivenamelist that
* matches the replicated (new) devidp.
*
* Typically the drivenamelist pointer would be setup by
* the meta_prune_cnames function.
*
* Calling function must free devidp using devid_free.
*
* Returns 0 - success, found new_devidp and dnp_new.
* Returns 1 - failure, didn't find new devid info
*/
static int
int myside,
)
{
int devid_sz;
/* name of replicated drive */
/* Get old devid from drive record */
/* Look up replicated (new) devid */
return (1);
/*
* Using new_devid, find a drivename entry with a matching devid.
* Use the passed in dnlp since it has the new (replicated) disknames
* in it.
*/
&dnp_new_devid, NULL);
if (dnp_new_devid == NULL)
continue;
break;
}
}
/* If can't find new name for drive - nothing to update */
return (1);
/*
* Setup returned value to be the drivename structure associated
* with new (replicated) drive.
*/
/*
* Need to return the new devid including the minor name.
* Find the minor_name here using the sidename or by
* looking in the namespace.
*/
break;
}
/*
* The disk has no side name information
*/
mdclrerror(ep);
return (1);
}
return (1);
/*
* minor_name will be NULL if dnp->devid == NULL
* - see metagetvtoc()
*/
return (1);
else
} else {
return (1);
}
/*
* Now, use the old devid with minor name to lookup
* the replicated (new) devid that will also contain
* a minor name.
*/
return (0);
}
/*
* meta_unrslv_replicated_mb
*
* Update the master block information during a take.
* Takes an md_drive_desc descriptor.
*
* Returns : nothing (void)
*/
void
)
{
int myside;
return;
continue;
/* If don't need to update master block - skip it. */
if (!(d->dd_flags & MD_DR_FIX_MB_DID))
continue;
/*
* Get old and replicated (new) devids associated with this
* drive. Also, get the new (replicated) drivename structure.
*/
mdclrerror(ep);
continue;
}
if (new_devidp) {
int dbcnt;
if (d->dd_dbcnt) {
/*
* Update each master block on the disk
*/
}
} else {
/* update the one dummy mb */
}
return;
}
/* Set drive record flags to ok */
/* Just update this one drive record. */
/* Ignore failure since no bad effect. */
}
}
}
/*
* meta_update_nm_rr_did
*
* Change a devid stored in the diskset namespace and in the local set
* namespace with the new devid.
*
* This routine is called during the import of a diskset
* (meta_imp_update_nn) and during the take of a diskset that has
* some unresolved replicated drives (meta_unrslv_replicated_nm).
*
* Returns : nothing (void)
*/
static void
void *old_devid, /* old devid being replaced */
int old_devid_sz,
void *new_devid, /* devid to be stored in nm */
int new_devid_sz,
int import_flag, /* called during import? */
)
{
struct mddb_config c;
(void) memset(&c, 0, sizeof (c));
/* During import to NOT update the local namespace. */
if (import_flag)
c.c_flags = MDDB_C_IMPORT;
}
}
/*
* meta_imp_update_nm
*
* Change a devid stored in the diskset namespace with the new devid.
* This routine is called during the import of a remotely replicated diskset.
*
* Returns : nothing (void)
*/
void
{
/*
* If disk isn't available we can't update, so go to next
*/
continue;
}
return;
}
}
/*
* meta_unrslv_replicated_nm
*
* Change a devid stored in the diskset namespace and in the local set
* namespace with the new devid.
*
* This routine is called during the take of a diskset that has
* some unresolved replicated drives.
*
* Returns : nothing (void)
*/
void
)
{
md_drive_desc *d = NULL;
char *devid_old_save;
int myside;
return;
continue;
/* If don't need to update namespace - skip it. */
if (!(d->dd_flags & MD_DR_FIX_LB_NM_DID))
continue;
/* Get old devid from drive record */
/*
* Get old and replicated (new) devids associated with this
* drive. Also, get the new (replicated) drivename structure.
*/
mdclrerror(ep);
continue;
}
if (new_devidp) {
return;
}
}
/*
* Using the new devid, fix up the name.
* If meta_upd_ctdnames fails, the next take will re-resolve
* the name from the new devid.
*/
mdclrerror(ep);
}
}
static set_t
char *setname,
)
{
int bool;
return (MD_SET_BAD);
}
/*
* For Sun Cluster we must have a setno which is the same across
* all nodes. sdssc_get_index() will get us this.
*/
setno = MD_SET_BAD;
break;
}
/*
* found one available
*/
if (bool == FALSE)
break;
}
setno = MD_SET_BAD;
}
}
return (setno);
}
int
char *setname,
int force,
)
{
struct mddb_config c;
int stale_flag = 0;
int partial_replicated_flag = 0;
rval_e (*create_func)(char *, int, char **, int);
clboot = 0;
(void) memset(&c, 0, sizeof (c));
c.c_flags = MDDB_C_IMPORT;
if (mnset != 0) {
c.c_multi_node = 1;
/*
* Set the nodeid according to whether this set is being
* imported on a cluster or not, so that later on, we do
* the right thing with side information.
*/
if (clboot != 0) {
} else {
}
} else {
}
} else {
c.c_sideno = 0;
}
/*
* Check to see if the setname that the set is being imported into,
* already exists.
*/
}
/* We expect the setname to be missing, so clear ep here */
mdclrerror(ep);
/*
* Find the next available set number
* We call sdssc_create_begin() to "reserve" a setno for the incoming
* set. Later if we succeed we will commit or clean it up if we fail.
*/
SDSSC_PICK_SETNO) == SDSSC_ERROR) {
}
}
}
c.c_timestamp = tp;
/* Check to see if replica quorum requirement is fulfilled */
if (!force) {
} else {
/*
* If we have a stale diskset, the kernel will
* delete the replicas on the unavailable disks.
* To be consistent, we'll zero out the mirp on those
* disks here.
*/
midp->mid_available)) {
}
}
}
}
(partial_replicated_flag == 0) &&
/*
* We pass the list of the drives in the
* set with replicas on them down to the kernel.
*/
if (!mirp) {
/*
* No replicas on this disk, go to next disk.
*/
continue;
}
/*
* The disk isn't there. We'll need to get the
* disk information from the midp list instead
* of going and looking for it. This means it
* will be information relative to the old
* system.
*/
} else {
== NULL)) {
mdclrerror(ep);
continue;
}
midp->mid_devname);
} else {
}
mdclrerror(ep);
continue;
}
}
}
mdi_debug("meta_imp_set: locator_devname = %s, minor %s\n",
if (midp->mid_o_devid) {
c.c_locator.l_old_devid =
}
if (minor_name) {
sizeof (c.c_locator.l_minor_name));
}
do {
if (c.c_locator.l_old_devid)
c.c_locator.l_old_devid);
}
}
/*
* If the dry run option was specified, flag success
* and exit out
*/
if (dry_run == 1) {
"import should be successful"));
if (c.c_locator.l_old_devid)
return (0);
}
/*
* Now the kernel should have all the information
* regarding the import diskset replica.
* Tell the kernel to load them up and import the set
*/
(void) memset(&c, 0, sizeof (c));
c.c_flags = stale_flag;
if (c.c_locator.l_old_devid)
}
if (mnset == 0) {
} else {
}
/*
* Create a set name for the set.
*/
/* Update the diskset namespace */
/* Release the diskset - even if update_nm failed */
(void) memset(&c, 0, sizeof (c));
/* Don't need device id information from this ioctl */
c.c_locator.l_devid_flags = 0;
return (-1);
}
/* If update_nm failed, then fail the import. */
return (-1);
}
}
/*
* We'll need to update information in the master block due
* to the set number changing and if the case of a replicated
* diskset, the device id changing. May also need to create a
* dummy master block if it's not there.
*/
return (-1);
}
return (-1);
}
if (mnset == 0) {
/*
* Create set record for diskset, but record is left in
* MD_SR_ADD state until after drives are added to set.
*/
return (-1);
}
} else {
return (-1);
}
}
/*
* Create drive records for the disks in the set.
*/
/*
* If the disk isn't available, the dnp->devid is
* no good. It is either blank for the case where
* there is no disk with that devname, or it
* contains the devid for the real disk in the system
* with that name. The problem is, if the disk is
* unavailable, then the devid should be the devid
* of the missing disk. So we're faking a dnp for
* the import. This is needed for creating drive
* records.
*/
NULL);
}
}
}
/* If drives were added without error, set set_record to OK */
}
return (-1);
}
if (c.c_locator.l_old_devid)
return (0);
}