/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <meta.h>
#include <sdssc.h>
#include <signal.h>
#include <syslog.h>
#include <metad.h>
/*
* This table defines all the metaclust reconfig steps we understand
*/
typedef enum stpnum {
MC_UNK = 0,
} stepnum_t;
/*
* Structure for step_name -> step_number mapping
*/
struct step_t {
char *step_nam;
};
/*
* Step name to step number mapping table
* This table MUST be sorted alphabetically in ascending order of step name
*/
{ "abort", MC_ABORT },
{ "return", MC_RETURN },
{ "start", MC_START },
{ "step1", MC_STEP1 },
{ "step2", MC_STEP2 },
{ "step3", MC_STEP3 },
{ "step4", MC_STEP4 },
{ "stop", MC_STOP }
};
/*
* If support for a different version is added, the new version number should
* be appended to the version_table below. This list will be searched to
* determine if a version requested via the -V option is supported or not.
*/
static char *version_table[] = {
};
/*
* Binary search comparison routine
*/
static int
{
}
/*
* Timeout expiry alarm signal handler
*/
/*ARGSUSED*/
static void
{
n = sizeof (step_table) / sizeof (step_table[0]);
for (i = 0; i < n; i++) {
break;
}
assert(i != n);
step_table[i].step_nam,
/*
* See what the child was actually doing when the timeout expired.
* A core-dump of this would be _really_ good, so let's just
* try a 'gcore -g c_pid' and hope
*/
c_pid);
} else {
}
/*
* The child will wait forever until the status is retrieved
* so get it now. Keep retrying if the call is interrupted.
*
* The possible results are,
*
* - child killed successfully
* - signal sent but child not killed
* - waitpid failed/interrupted
*/
(void) sleep(2);
break;
}
}
ret = 0;
} else {
ret = 1;
}
/*
* If the kill did not catch the child then it means the child
* exited immediately after the timeout occured.
*/
ret = 0;
}
/*
* make sure not to exit with 205 for any steps other than step1-step4.
* Suncluster reconfiguration can't handle it otherwise.
*/
switch (stepnum) {
case MC_STEP1:
case MC_STEP2:
case MC_STEP3:
case MC_STEP4:
/*
* If the child was killed successfully return 205 for a
* new reconfig cycle otherwise send 1 to panic the node.
*/
if (ret != 0) {
exit(1);
} else {
exit(205);
}
break;
case MC_START:
case MC_STOP:
case MC_ABORT:
case MC_RETURN:
default:
exit(1);
break;
}
}
/*
* Attempt to load local set.
* Returns:
* pointer to mdsetname_t for local set (local_sp) is successful.
* 0 if failure
* if there are no local set mddbs, no error message is printed.
* Otherwise, error message is printed so that user
* can determine why the local set didn't start.
*/
{
/* Does local set exist? If not, give no error */
return (0);
}
/*
* snarf local set
* If fails with MDE_DB_NODB, then just return 1 printing
* no failure.
* Otherwise, print error message, and return 1.
*/
if (meta_setup_db_locations(ep) != 0) {
return (0);
}
/* local set loaded successfully */
return (local_sp);
}
/*
* Purpose: Compose a full path name for a metadevice
*
* On entry: sp - setname pointer
* mnum - minor number of metadevice
* pathname - pointer to array to return path string
* pathlen - max length of pathname array
*/
static int
{
int rtn;
return (-1);
}
return (-1);
}
"Could not create path for device %s\n"),
return (-1);
}
return (0);
}
/*
* Purpose: Walk through all the devices specified for the given set
* and do the action specified in mode
*/
static int
{
mdnamelist_t *p;
int mirror_dev = 0;
int cnt;
int has_parent;
/*
* if we are choosing or resetting the owners then make sure
* we are only doing it for mirror devices
*/
return (-1);
}
/* get a list of all the metadevices for current set */
return (-1);
return (-1);
}
/* If resetting the owner, get the known membership list */
if (mode & RESET_OWNER) {
return (-1);
}
}
/* for each metadevice */
/*
* Get the current setting for mirror ABR state and all of the
* submirror state and flags from the master node. We only
* perform this when going through a 'start' cycle.
*/
char *miscname;
/*
* Ensure that we ignore soft-parts that are returned
* from the meta_get_mirror_names() call
*/
goto out;
continue;
"MD_MN_GET_MIRROR_STATE") != 0) {
"mirror state for %s"),
goto out;
} else {
continue;
}
}
/* check if this is a top level metadevice */
goto out;
has_parent = 1;
} else {
has_parent = 0;
}
char *miscname;
/*
* we can only do these for mirrors so make sure we
* really have a mirror device and not a softpartition
* imitating one. meta_get_mirror_names seems to think
* softparts on top of a mirror are mirrors!
*/
goto out;
continue;
/* get the current owner id */
"MD_MN_GET_MM_OWNER") != 0) {
"mirror owner for %s"),
goto out;
}
}
if (mode & RESET_OWNER) {
mdclrerror(ep);
continue;
}
/*
* reset owner only if the current owner is
* not in the membership list
* Also kill the resync thread so that when the resync
* is started, it will perform an optimized resync
* for any resync regions that were dirty when the
* current owner left the membership.
*/
if (meta_mn_change_owner(&ownpar,
MD_MN_MM_ALLOW_CHANGE) == -1) {
"Unable to reset mirror owner "
"for %s\n"),
goto out;
}
MD_RESYNC_KILL_NO_WAIT) != 0) {
"Unable to kill resync for"
" %s\n"),
goto out;
}
}
}
if (mode & CHOOSE_OWNER) {
/*
* only orphaned resyncs will have no owner.
* if that is the case choose a new owner. Otherwise
* re-establish the existing owner. This covers the
* case where a node that owned the mirror
* the reconfig cycle has completed. In this case the
* other cluster nodes will have the mirror owner marked
* as the rebooted node while it has the owner marked
* as 'None'. We have to reestablish the ownership so
* that the subsequent resync can continue.
*/
MD_MN_MM_CHOOSE_OWNER) == -1) {
"mirror owner for %s\n"),
goto out;
}
}
/*
* For RESET_ABR and UPDATE_ABR - only handle top
* level metadevices.
*/
if (has_parent)
continue;
/*
* Reset the ABR (application based recovery)
* value on all nodes. We are dealing with
* the possibility that we have ABR set but the
* only node that had the device open with ABR has
* left the cluster. We simply open and close the
* device and if this is the last close in the
* cluster, ABR will be cleared on all nodes.
*/
char *miscname;
name[0] = '\0';
/*
* Ensure that we don't include soft-parts in the
* mirror-only call to RESET_ABR. meta_get_mirror_names
* returns a bogus list that includes all soft-parts
* built on mirrors.
*/
goto out;
continue;
/* compose the absolute device path and open it */
sizeof (name)) != 0)
goto out;
name);
continue;
}
}
if (mode & UPDATE_ABR) {
/*
* Update the ABR value on this node. We obtain the
* current ABR state from the master node.
*/
char *miscname;
name[0] = '\0';
/*
* Ensure that we don't include soft-parts in the
* mirror-only call to UPDATE_ABR. meta_get_mirror_names
* returns a bogus list that includes all soft-parts
* built on mirrors.
*/
goto out;
continue;
/* Get tstate from Master */
!= 0)
continue;
/* If not set on the master, nothing to do */
if (!(tstate & MD_ABR_CAP))
continue;
/* compose the absolute device path and open it */
sizeof (name)) != 0)
goto out;
name);
continue;
}
/* set ABR state */
/*
* Ignore if device does not support this
* ioctl
*/
name);
}
continue;
}
continue;
}
"Could not set ABR state for "
"device %s"), name);
goto out;
} else {
"Setting ABR state on device %s\n"), name);
}
}
}
/* cleanup */
if (mode & RESET_OWNER) {
}
return (0);
out:
/* cleanup */
if (mode & RESET_OWNER) {
}
return (-1);
}
/*
* Print usage message
*/
static void
{
"\t%s [-V version] [-t timeout] [-d level] start localnodeid\n"
"\t%s [-V version] [-t timeout] [-d level] step nodelist...\n"
"\t%s [-V version] [-t timeout] [-d level] abort | stop\n"
"\t%s [-V | -? | -h]\n"),
if (!eval) {
"\tValid debug (-d) levels are 1-%d for increasing "
"verbosity.\n\tDefault is -d 3.\n\n"
"\tValid step values are: return | step1 | step2 | "
"step3 | step4\n\n"
"\tNodelist is a space-separated list of node id's\n\n"),
}
}
/*
* Input: Input takes a config step name followed by a list of
* possible node id's.
*
* Returns: 0 - Success
* 1 - Fail
* Node will be removed from cluster membership
* by forcing node to panic.
* 205 - Unsuccessful. Start another reconfig cycle.
* Problem was encountered that could be fixed by
* running another reconfig cycle.
* Problem could be a result of a failure to read
* the nodelist file or that all work could not be
* accomplished in a reconfig step in the amount of
* time given so another reconfig cycle is needed in
* order to finish the current step.
*/
int
{
int c, clust = 0;
int rval = 0;
int version_table_size;
int ret_val;
long commd_timeout = 0;
/*
* Get the locale set up before calling any other routines
* with messages to ouput. Just in case we're not in a build
* environment, make sure that TEXT_DOMAIN gets set to
* something.
*/
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
exit(1);
}
}
/*
* open log and enable libmeta logging. Do it here explicitly
* rather than letting md_init() do it because we are not really
* a daemon and that is what md_init() opens the log as.
*/
optind = 1;
opterr = 0;
switch (c) {
case 'h':
break;
case 'd':
"between 1 and %d inclusive.\n"),
debug);
}
break;
case 'V':
break;
case 't':
}
break;
case '?':
if (optopt == '?') {
} else if (optopt == 'V') {
int i;
"%s: Versions Supported:"), myname);
for (i = 0; i < version_table_size; i++) {
version_table[i]);
}
}
/*FALLTHROUGH*/
default:
break;
}
}
/* initialise the debug level and start time */
/*
* check that the version specified (if any) is supported.
*/
int i, found = 0;
for (i = 0; i < version_table_size; i++) {
found = 1;
break;
}
}
if (!found) {
version);
}
}
/* parse arguments */
if (argc <= 0) {
}
/* convert the step name to the corresponding number */
}
--argc;
++argv;
/* set timeout alarm signal, a value of 0 will disable timeout */
if (timeout > 0) {
int stat_loc = 0;
} else if (c_pid) {
/* parent */
}
"handler"));
}
/*
* wait for child to exit or timeout to expire.
* keep retrying if the call is interrupted
*/
break;
}
}
/* exit with the childs exit value */
} else {
}
}
}
/*
* If a timeout value is given, everything from this point onwards is
* executed in the child process.
*/
switch (stepnum) {
case MC_START:
/*
* Start Step
*
* - Suspend all rpc.mdcommd messages
*/
/* expect the local node id to be given only */
if (argc != 1)
meta_print_hrtime(0));
/*
* With multinode disksets configured we need to
* update all replicas on all cluster nodes to have
* the same status. If local replicas on a cluster
* node are not accessible we need to panic this
* node, otherwise we abort in the reconfig cycle
* To avoid a total cluster outage in the above case
* we panic only the failing node via md_exit(.., 1).
*/
/* panic the node */
}
}
/* start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"get set %d information"), setno);
}
}
/* only check multi-node disksets */
mdclrerror(ep);
continue;
}
/*
* Mddb parse messages are sent amongst the nodes
* in a diskset whenever the locator block or
* locator names structure has been changed.
* A locator block change could occur as a result
* of a disk failure during the reconfig cycle,
* so block the mddb parse messages while the
* rpc.mdcommd is suspended during the reconfig cycle.
*/
}
}
/* suspend commd and spin waiting for drain */
(void) sleep(1);
}
if (ret_val) {
}
/*
* Set start step flag for set. This is set to indicate
* that this node entered the reconfig cycle through
* the start step. This is used during the reconfig
* cycle to determine whether the node had entered
* through the start step or the return step.
*/
/* Use magic to help protect ioctl against attack. */
}
}
break;
case MC_STOP:
/*
* Stop Step
*
* - ???
*/
/* don't expect any more arguments to follow the step name */
if (argc != 0)
break;
case MC_ABORT:
/*
* Abort Step
*
* - Abort rpc.mdcommd
*/
/* don't expect any more arguments to follow the step name */
if (argc != 0)
meta_print_hrtime(0));
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
/*
* abort the rpc.mdcommd. The abort is only issued on this node
* meaning that the abort reconfig step is called on this
* node before a panic while the rest of the cluster will
* undergo a reconfig cycle.
* There is no time relation between this node running a
* reconfig abort and the the rest of the cluster
* running a reconfig cycle meaning that this node may
* panic before, during or after the cluster has run
* a reconfig cycle.
*/
mdmn_abort();
break;
case MC_RETURN:
/*
* Return Step
*
* - Grab local set lock, issue rpc.mdcommd DRAIN ALL
* and release local set lock. Grabbing the local set
* command from starting until the DRAIN ALL is issued.
* so the return step must not issue the DRAIN ALL command
* a RESUME ALL after this return reconfig step has issued
* the DRAIN ALL command.
* After this reconfig step has issued the DRAIN_ALL and
* when attempting to contact the rpc.mdcommd and will
* terminate without making any configuration changes.
* The DRAIN ALL command will keep all other meta* commands
* from running during the reconfig cycle (these commands
* will wait until the rpc.mdcommd is resumed) since the
* reconfig cycle may be changing the diskset configuration.
*/
/* expect the nodelist to follow the step name */
if (argc < 1)
meta_print_hrtime(0));
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
/*
* Suspend any mirror resyncs that are in progress. This
* stops unnecessary timeouts.
*/
}
/*
* All metaset and metadb commands on this node have now
* terminated gracefully. Now, issue a drain all to
* the rpc.mdcommd. Any meta command issued after the
* drain all will either spin sending the command to the
* master until after the reconfig cycle has finished OR
*/
}
/* start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"get set %d information"), setno);
}
}
/* only check multi-node disksets */
mdclrerror(ep);
continue;
}
/*
* Mddb parse messages are sent amongst the nodes
* in a diskset whenever the locator block or
* locator names structure has been changed.
* A locator block change could occur as a result
* of a disk failure during the reconfig cycle,
* so block the mddb parse messages while the
* rpc.commd is suspended during the reconfig cycle.
*/
}
}
/* suspend commd and spin waiting for drain */
(void) sleep(1);
}
if (ret_val) {
}
}
/*
*/
"Unable to resume I/O on node %s for all sets"),
mynode());
}
/*
* commands are now held off using drain all.
*/
break;
case MC_STEP1:
/*
* Step 1
*
* - Populate nodelist file if we are on clustering
* and pick a master node for each MN diskset.
*/
/* expect the nodelist to follow the step name */
if (argc < 1)
meta_print_hrtime(0));
/* Always write nodelist file even if no local set exists */
if (clust == SDSSC_OKAY) {
/* skip to the nodelist args */
"Could not populate nodelist file"));
}
}
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
/*
* At this point, all meta* commands are blocked across
* all disksets since the master rpc.mdcommd has drained or
* the master node has died.
* If a metaset or metadb command had been in progress
* at the start of the reconfig cycle, this command has
* either completed or it has been terminated due to
* the death of the master node.
*
* This means that that it is now ok to remove any
* outstanding clnt_locks associated with multinode
* disksets on this node due to a node panic during
* a metaset operation. This allows the routines that
* choose the master to use rpc.metad to determine the
* master of the diskset.
*/
"clear locks failed %s"),
}
/*
* Call reconfig_choose_master to choose a master for
* each MN diskset, update the nodelist for each diskset
* given the member information and send a reinit message
* to rpc.mdcommd to reload the nodelist.
*/
if (rval == 205) {
/*
* NOTE: Should issue call to reboot remote host that
* is causing the RPC failure. Clustering to
* provide interface in the future. This should
* stop a never-ending set of 205 reconfig cycles.
* Remote host causing failure is stored in
* ep->host if ep is an RPC error.
* if (mdanyrpcerror(ep))
* reboot (ep->host);
*/
"choose master failure of 205 %s"),
} else if (rval != 0) {
"choose master failure %s"),
}
break;
case MC_STEP2:
/*
* Step 2
*
* In Step 2, each node walks the list of disksets. If a
* node is a master of a MN diskset, it synchronizes
* the local set USER records for that diskset.
*
* If disks exist in the diskset and there is a joined
* (owner) node in the diskset, the master will also:
* - synchronize the diskset mddbs to the master
* - play the change log
*
* The master node will now attempt to join any unjoined
* nodes that are currently members in the membership list.
*/
/* expect the nodelist to follow the step name */
if (argc < 1)
meta_print_hrtime(0));
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
}
/* start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else if (mdanyrpcerror(ep)) {
/* Fail on RPC failure to self */
"Unable to get information for "
"set number %d"), setno);
} else {
"Unable to get information for "
"set number %d"), setno);
mdclrerror(ep);
continue;
}
}
if (mdanyrpcerror(ep)) {
/* Fail on RPC failure to self */
"Unable to get information for "
"set number %d"), setno);
}
mdclrerror(ep);
continue;
}
/* Only check MN disksets */
if (!(MD_MNSET_DESC(sd))) {
continue;
}
/* All actions in step 2 are driven by master */
if (!(sd->sd_mn_am_i_master)) {
continue;
}
/*
* Synchronize the USER records in the local mddbs
* for hosts that are members. The USER records
* contain set, drive and host information.
*/
if (rval != 0) {
"Synchronization of user records "
if (rval == 205) {
/*
* NOTE: Should issue call to reboot
* remote host that is causing the RPC
* failure. Clustering to provide
* interface in the future. This
* should stop a never-ending set of
* 205 reconfig cycles.
* Remote host causing failure is
* stored in ep->host if ep is an
* RPC error.
* if (mdanyrpcerror(ep))
* reboot (ep->host);
*/
} else {
}
}
/* Reget sd since sync_user_recs may have flushed it */
}
}
/*
* No drives in set, continue to next set.
*/
/* Done with this set */
continue;
}
/*
* Synchronize the diskset mddbs for hosts
* that are members. This may involve
* playing the changelog and writing out
* to the diskset mddbs.
*/
if (rval != 0) {
"Synchronization of diskset mddbs "
"mddb synchronization failed for "
start_time));
if (rval == 205) {
/*
* NOTE: Should issue call to reboot
* remote host that is causing the RPC
* failure. Clustering to provide
* interface in the future. This
* should stop a never-ending set of
* 205 reconfig cycles.
* Remote host causing failure is
* stored in ep->host if ep is an
* RPC error.
* if (mdanyrpcerror(ep))
* reboot (ep->host);
*/
} else if (rval == 1) {
continue;
} else {
}
}
"synchronization completed for set %s: %s"),
/* Join the starting nodes to the diskset */
if (rval != 0) {
"Join of non-owner (starting) nodes "
"nodes joined for set %s: %s"),
start_time));
if (rval == 205) {
/*
* NOTE: Should issue call to reboot
* remote host that is causing the RPC
* failure. Clustering to provide
* interface in the future. This
* should stop a never-ending set of
* 205 reconfig cycles.
* Remote host causing failure is
* stored in ep->host if ep is an
* RPC error.
* if (mdanyrpcerror(ep))
* reboot (ep->host);
*/
} else {
}
}
}
break;
case MC_STEP3:
/*
* Step 3
*
* For all multinode sets do,
* - Reinitialise rpc.mdcommd
* - Reset mirror owners to null if the current owner is
* no longer in the membership list
*/
/* expect the nodelist to follow the step name */
if (argc < 1)
meta_print_hrtime(0));
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
/*
* walk through all sets on this node which could include:
* - MN disksets
* - traditional disksets
* - non-existent disksets
* start mirror resync for all MN sets
*/
}
/* start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"get set %d information"), setno);
}
}
/* only check multi-node disksets */
mdclrerror(ep);
continue;
}
}
/* If this node isn't joined to set, do nothing */
"not get set %s ownership"),
}
mdclrerror(ep);
continue;
}
"re-initialising rpc.mdcommd and resetting mirror "
/* reinitialzse rpc.mdcommd with new nodelist */
"Could not re-initialise rpc.mdcommd for "
}
NULL) != 0) {
"not get set %s information"),
}
/* Don't do anything else if set is stale */
mdclrerror(ep);
continue;
}
/* reset mirror owners */
}
"re-initialised and mirror owners reset for "
}
break;
case MC_STEP4:
/*
* Step 4
*
* For all multinode sets do:
* - Resume the rpc.mdcommd messages. Must resume all
* sets before issuing I/O to any set since an error
* encountered in a commd suspended set could be
* blocked waiting for commd in another set to resume.
* (This happens since the daemon queues service
* all sets). An open of a soft partition causes
* a read of the watermarks during the open.
* - If set is non-writable (not an owner or STALE), then
* continue to next set.
*
* For all multinode sets do,
* - Reset ABR states for all mirrors, ie clear ABR if not
* open on any node.
* - Reset ABR states for all soft partitions, ie clear ABR if
* not open on any node.
* - For all slave nodes that have entered through the start
* step, update the ABR state to that of the master and
* get the submirror state from the master
* - meta_lock set
* - Resync all mirrors
* - unlock meta_lock for this set.
* - Choose a new owner for any orphaned resyncs
*
* There is one potential issue here. when concurrently
* resetting and updating the ABR state. If the master has ABR
* set, but should no longer have because the only node that
* had the metadevice open and had ABR set has paniced, the
* master will send a message to all nodes to clear the ABR
* state. Meanwhile any node that has come through the
* start step will get tstate from the master and will update
* ABR if it was set in tstate. So, we appear to have a problem
* if the following sequence occurs:-
* - The slave gets tstate with ABR set
* - The master sends a message to clear ABR
* - The slave updates ABR with the value it got from tstate.
* We now have the master with ABR clear and the slave with ABR
* set. Fortunately, having set ABR, the slave will close the
* metadevice after setting ABR and as there are no nodes with
* the device open, the close will send a message to clear ABR
* on all nodes. So, the nodes will all have ABR unset.
*/
/* expect the nodelist to follow the step name */
if (argc < 1)
meta_print_hrtime(0));
/*
* Does local set exist? If not, exit with 0
* since there's no reason to have this node panic if
* the local set cannot be started.
*/
}
/*
* walk through all sets on this node which could include:
* - MN disksets
* - traditional disksets
* - non-existent disksets
* start mirror resync for all MN sets
*/
}
/* Clear set_info structure */
}
/* start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"get set %d information"), setno);
}
}
mdclrerror(ep);
continue;
}
/* only check multi-node disksets */
mdclrerror(ep);
continue;
}
/*
* If not an owner (all mddbs failed) or stale
* (< 50% mddbs operational), then set is
* non-writable so just resume commd and
* unblock mddb messages.
*/
mdclrerror(ep);
}
"not get set %s ownership"),
}
/* Set is owned - is it stale? */
NULL) != 0) {
"not get set %s information"),
}
}
}
/* resume rpc.mdcommd */
commd_timeout)) {
}
/* Unblock mddb parse messages */
}
}
"resumed and messages unblocked for set %s: %s"),
}
int start_step;
/* Skip traditional disksets. */
continue;
/*
* If already determined that this set is
* a non-writable set, then just continue
* to next set since there's nothing else
* to do for a non-writable set.
*/
continue;
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"get set %d information"), setno);
}
}
mdclrerror(ep);
continue;
}
/* See if this node came through the start step */
/* Use magic to help protect ioctl against attack. */
}
/*
* We can now reset the start_step flag for the set
* if it was already set.
*/
if (start_step) {
/*
* Use magic to help protect ioctl
* against attack.
*/
gettext("Could not reset "
"start_step flag for set %s"),
}
}
"ABR state and restarting io's for "
/*
* If we are not the master and we have come through
* the start step, we must update the ABR states
* for mirrors and soft partitions. Also the submirror
* states need to be synchronised so that we see the
* same status as other previously joined members.
* This _must_ be done before starting the resync.
*/
ep) == -1) {
}
ep) == -1) {
}
/*
* Mark the fact that we've got the mirror
* state. This allows the resync thread to
* determine if _it_ needs to issue this. This
* can happen if a node is added to a set after
* a reconfig cycle has completed.
*/
/*
* Use magic to help protect ioctl
* against attack.
*/
gettext("Could not set "
"submirror state flag for set %s"),
}
}
/*
* All remaining actions are only performed by the
* master
*/
if (!(sd->sd_mn_am_i_master)) {
}
continue;
}
/*
* If the master came through the start step, this
* implies that all of the nodes must have done the
* same and hence there can be no applications
* running. Hence no need to reset ABR
*/
if (!start_step) {
/* Reset ABR state for mirrors */
ep) == -1) {
}
/* ...and now the same for soft partitions */
ep) == -1) {
}
}
/*
* choose owners for orphaned resyncs and reset
* non-orphaned resyncs so that an owner node that
* reboots will restart the resync if needed.
*/
/*
* Must unlock set lock before meta_mirror_resync_all
* sends a message to run the metasync command
* which also grabs the meta_lock.
*/
}
/* resync all mirrors in set */
}
}
break;
default:
break;
}
/* NOTREACHED */
return (0);
}