/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* mirror operations
*/
#include <meta.h>
#include <thread.h>
extern int md_in_daemon;
extern md_mn_client_list_t *mdmn_clients;
/*
* chain of mirrors
*/
typedef struct mm_unit_list {
/*
* resync mirror
* meta_lock for this set should be held on entry.
*/
int
md_error_t *ep,
)
{
char *miscname;
/* should have a set */
/* make sure we have a mirror */
return (-1);
}
/* start resync */
switch (cmd) {
case MD_RESYNC_FORCE_MNSTART:
break;
case MD_RESYNC_START:
break;
case MD_RESYNC_BLOCK:
break;
case MD_RESYNC_UNBLOCK:
break;
case MD_RESYNC_KILL:
break;
case MD_RESYNC_KILL_NO_WAIT:
break;
default:
/* TODO: Add new error MDE_BAD_RESYNC_FLAGS */
}
/* return success */
return (0);
}
/*
* free units
*/
static void
)
{
uint_t i;
for (i = 0; (i < (MD_PASS_MAX + 1)); ++i) {
mm_unit_list_t *p, *n;
n = p->next;
Free(p);
}
}
}
/*
* setup_units: build lists of units for each pass
*/
static int
)
{
mdnamelist_t *p;
int rval = 0;
/* should have a set */
/* for each mirror */
return (-1);
/* get unit structure */
continue;
}
/* save info */
/* put on list */
}
/* cleanup, return error */
return (rval);
}
/*
* resync all mirrors (in background)
*/
int
)
{
/* should have a set */
/* get mirrors */
return (-1);
/* fork a process */
/*
* md_daemonize will fork off a process. The is the
* parent or error.
*/
if (fval > 0) {
return (0);
}
mdclrerror(ep);
}
/*
* In case this was called thru rsh, the calling process on the other
* side will know, it doesn't have to wait until all the resyncs have
* finished.
* Also initialise the rpc client pool so that this process will use
* a unique pool of clients. If we don't do this, all of the forked
* clients will end up using the same pool of clients which can result
* in hung clients.
*/
(void) close(0);
(void) close(1);
(void) close(2);
mdmn_clients = NULL;
}
/*
* Determine which pass level is the highest that contains mirrors to
* resync. We only need to wait for completion of earlier levels below
* this high watermark. If all mirrors are at the same pass level
* there is no requirement to wait for completion.
*/
max_pass = 1;
break;
}
}
/*
* max_pass now contains the highest pass-level with resyncable mirrors
*/
/* do passes */
int dispatched = 0;
/* skip empty passes */
continue;
/* dispatch all resyncs in pass */
rval = -1;
} else {
++dispatched;
}
} else {
MD_RESYNC_START) != 0) {
rval = -1;
} else {
++dispatched;
}
}
}
/*
* Wait for them to finish iff we are at a level lower than
* max_pass. This orders the resyncs into distinct levels.
* I.e. level 2 resyncs won't start until all level 1 ones
* have completed.
*/
continue;
howlong = 1;
while (dispatched > 0) {
/* wait a while */
/* see if any finished */
continue;
rval = -1;
--dispatched;
--dispatched;
}
}
/* wait a little longer next time */
if (howlong < 10)
++howlong;
}
}
/* cleanup, return success */
if (fval == 0) /* we are the child process so exit */
exit(0);
return (rval);
}
/*
* meta_mn_mirror_resync_all:
* -------------------------
* Resync all mirrors associated with given set (arg). Called when master
* node is adding a node to a diskset. Only want to initiate the resync on
* the current node.
*/
void *
{
int fval;
/* should have a set */
return (NULL);
}
return (NULL);
}
/* fork a process */
/*
* md_daemonize will fork off a process. The is the
* parent or error.
*/
if (fval > 0) {
return (NULL);
}
return (NULL);
}
/*
* Child process should never return back to rpc.metad, but
* should exit.
* Flush all internally cached data inherited from parent process
* since cached data will be cleared when parent process RPC request
* has completed (which is possibly before this child process
* can complete).
* Child process can retrieve and cache its own copy of data from
* rpc.metad that won't be changed by the parent process.
*
* Reset md_in_daemon since this child will be a client of rpc.metad
* not part of the rpc.metad daemon itself.
* md_in_daemon is used by rpc.metad so that libmeta can tell if
* this thread is rpc.metad or any other thread. (If this thread
* was rpc.metad it could use some short circuit code to get data
* directly from rpc.metad instead of doing an RPC call to rpc.metad).
*/
md_in_daemon = 0;
}
}
/*
*/
(void) close(0);
(void) close(1);
(void) close(2);
/* get mirrors */
}
/*
* Determine which pass level is the highest that contains mirrors to
* resync. We only need to wait for completion of earlier levels below
* this high watermark. If all mirrors are at the same pass level
* there is no requirement to wait for completion.
*/
max_pass = 1;
break;
}
}
/*
* max_pass now contains the highest pass-level with resyncable mirrors
*/
/* do passes */
int dispatched = 0;
/* skip empty passes */
continue;
/* dispatch all resyncs in pass */
MD_RESYNC_FORCE_MNSTART) != 0) {
mdclrerror(&mde);
} else {
++dispatched;
}
}
/*
* Wait for them to finish iff we are at a level lower than
* max_pass. This orders the resyncs into distinct levels.
* I.e. level 2 resyncs won't start until all level 1 ones
* have completed.
*/
continue;
howlong = 1;
while (dispatched > 0) {
/* wait a while */
/* see if any finished */
continue;
mdclrerror(&mde);
--dispatched;
--dispatched;
}
}
/* wait a little longer next time */
if (howlong < 10)
++howlong;
}
}
/* cleanup, return success */
/*NOTREACHED*/
return (NULL);
}
/*
* meta_mirror_resync_process:
* --------------------------
* Modify any resync that is in progress on this node for the given set.
*
* Input Parameters:
* sp setname to scan for mirrors
* cmd action to take:
* MD_RESYNC_KILL - kill all resync threads
* MD_RESYNC_BLOCK - block all resync threads
* MD_RESYNC_UNBLOCK - resume all resync threads
* Output Parameters
* ep error return structure
*
* meta_lock for this set should be held on entry.
*/
static void
{
/* Grab all the mirrors from the set (if any) */
return;
/* do passes */
/* skip empty passes */
continue;
/* Process all resyncs in pass */
cmd);
}
}
/* Clear up mirror units */
}
/*
* meta_mirror_resync_process_all:
* ------------------------------
* Issue the given resync command to all mirrors contained in all multi-node
* sets.
*
* Input Parameters:
* cmd - MD_RESYNC_KILL, MD_RESYNC_BLOCK, MD_RESYNC_UNBLOCK
*/
static void
{
/*
* Traverse all sets looking for multi-node capable ones.
*/
mde = mdnullerror;
continue;
if (!MD_MNSET_DESC(sd))
continue;
continue;
}
}
}
}
/*
* meta_mirror_resync_kill_all:
* ---------------------------
* Abort any resync that is in progress on this node. Scan all sets for all
* mirrors.
* Note: this routine is provided for future use. For example to kill all
* resyncs on a node this could be used as long as the
* mddoors / rpc.mdcommd tuple is running on all members of the cluster.
*/
void
{
}
/*
* meta_mirror_resync_block_all:
* ----------------------------
* Block all resyncs that are in progress. This causes the resync state to
* freeze on this machine, and can be resumed by calling
* meta_mirror_resync_unblock_all.
*/
void
{
}
/*
* meta_mirror_resync_unblock_all:
* ------------------------------
* Unblock all previously blocked resync threads on this node.
*/
void
{
}
/*
* meta_mirror_resync_unblock:
* --------------------------
* Unblock any previously blocked resync threads for the given set.
* meta_lock for this set should be held on entry.
*/
void
{
}
/*
* meta_mirror_resync_kill:
* -----------------------
* Kill any resync threads running on mirrors in the given set.
* Called when releasing a set (meta_set_prv.c`halt_set)
*/
void
{
}