summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml8
-rw-r--r--usr/src/cmd/lvm/rpc.mdcommd/mddoors.c63
-rw-r--r--usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c237
-rw-r--r--usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c100
-rw-r--r--usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c20
-rw-r--r--usr/src/cmd/lvm/util/metaclust.c24
-rw-r--r--usr/src/cmd/mdb/common/modules/md/dumpmirror.c230
-rw-r--r--usr/src/cmd/mdb/common/modules/md/md.c12
-rw-r--r--usr/src/cmd/mdb/common/modules/md/metastat.c116
-rw-r--r--usr/src/cmd/mdb/intel/amd64/md/Makefile9
-rw-r--r--usr/src/cmd/mdb/intel/ia32/md/Makefile9
-rw-r--r--usr/src/cmd/mdb/sparc/v9/md/Makefile9
12 files changed, 618 insertions, 219 deletions
diff --git a/usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml b/usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml
index c3cff1c1ca..e9910ae6ef 100644
--- a/usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml
+++ b/usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml
@@ -1,7 +1,7 @@
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--
- Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
@@ -23,8 +23,6 @@
CDDL HEADER END
- pragma ident "%Z%%M% %I% %E% SMI"
-
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
@@ -82,8 +80,8 @@
<propval name='endpoint_type' type='astring' value='tli' />
<propval name='wait' type='boolean' value='true' />
<propval name='isrpc' type='boolean' value='true' />
- <propval name='rpc_low_version' type='integer' value='1' />
- <propval name='rpc_high_version' type='integer' value='1' />
+ <propval name='rpc_low_version' type='integer' value='2' />
+ <propval name='rpc_high_version' type='integer' value='2' />
<propval name='proto' type='astring' value='tcp' />
</property_group>
diff --git a/usr/src/cmd/lvm/rpc.mdcommd/mddoors.c b/usr/src/cmd/lvm/rpc.mdcommd/mddoors.c
index 401bd07421..7c12bb59eb 100644
--- a/usr/src/cmd/lvm/rpc.mdcommd/mddoors.c
+++ b/usr/src/cmd/lvm/rpc.mdcommd/mddoors.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <door.h>
#include <locale.h>
#include <meta.h>
@@ -106,7 +104,7 @@ exit_daemon_lock(void)
if (close(daemon_lock_fd) == -1) {
syslog(LOG_DAEMON | LOG_DEBUG,
gettext("close(%s) failed - %s\n"),
- daemon_lock_file, strerror(errno));
+ daemon_lock_file, strerror(errno));
return;
}
unlink(daemon_lock_file);
@@ -133,37 +131,32 @@ door2rpc(void *cookie, /* required by the doors infrastructure */
md_mn_kresult_t kresult;
md_mn_kmsg_t *kmsg = (md_mn_kmsg_t *)(void *)argp;
- err = mdmn_send_message(kmsg->kmsg_setno,
- kmsg->kmsg_type,
- kmsg->kmsg_flags,
- (char *)&(kmsg->kmsg_data),
- kmsg->kmsg_size,
- &result,
- &ep);
+ err = mdmn_send_message(kmsg->kmsg_setno, kmsg->kmsg_type,
+ kmsg->kmsg_flags, kmsg->kmsg_recipient, (char *)&(kmsg->kmsg_data),
+ kmsg->kmsg_size, &result, &ep);
+
if (result == NULL) {
kresult.kmmr_comm_state = MDMNE_RPC_FAIL;
} else {
kresult.kmmr_comm_state = result->mmr_comm_state;
- }
- if (err == 0) {
- kresult.kmmr_msgtype = result->mmr_msgtype;
- kresult.kmmr_flags = result->mmr_flags;
- kresult.kmmr_exitval = result->mmr_exitval;
- kresult.kmmr_failing_node = result->mmr_failing_node;
- size = result->mmr_out_size;
- if (size > 0) {
- /* This is the maximum of data we can transfer, here */
- if (size > MDMN_MAX_KRES_DATA) {
- size = MDMN_MAX_KRES_DATA;
+ if (err == 0) {
+ kresult.kmmr_msgtype = result->mmr_msgtype;
+ kresult.kmmr_flags = result->mmr_flags;
+ kresult.kmmr_exitval = result->mmr_exitval;
+ kresult.kmmr_failing_node = result->mmr_failing_node;
+ size = result->mmr_out_size;
+ if (size > 0) {
+ /* This is the max data we can transfer, here */
+ if (size > MDMN_MAX_KRES_DATA) {
+ size = MDMN_MAX_KRES_DATA;
+ }
+ bcopy(result->mmr_out, &(kresult.kmmr_res_data),
+ size);
+ kresult.kmmr_res_size = size;
+ } else {
+ kresult.kmmr_res_size = 0;
}
- bcopy(result->mmr_out, &(kresult.kmmr_res_data), size);
- kresult.kmmr_res_size = size;
- } else {
- kresult.kmmr_res_size = 0;
}
- }
-
- if (result != NULL) {
free_result(result);
}
@@ -252,7 +245,7 @@ main(void)
* At this point we are single threaded.
* We give mdmn_send_message() a chance to initialize safely.
*/
- (void) mdmn_send_message(0, 0, 0, 0, 0, 0, 0);
+ (void) mdmn_send_message(0, 0, 0, 0, 0, 0, 0, 0);
/* setup the door handle */
mdmn_door_handle = door_create(door2rpc, NULL,
@@ -266,12 +259,12 @@ main(void)
if (metaioctl(MD_MN_SET_DOORH, &mdmn_door_handle, &ep,
"mddoors") != 0) {
syslog(LOG_DAEMON | LOG_DEBUG, gettext(
- "Couldn't set door handle"));
+ "Couldn't set door handle"));
exit(1);
}
(void) pause();
syslog(LOG_DAEMON | LOG_ERR, gettext(
- "Unexpected exit from pause()"));
+ "Unexpected exit from pause()"));
return (1);
}
diff --git a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c
index 1413b2791d..9fda15beec 100644
--- a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c
+++ b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c
@@ -18,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -42,38 +41,40 @@
/*
* This is the communication daemon for SVM Multi Node Disksets.
* It runs on every node and provides the following rpc services:
- * - mdmn_send_svc_1
- * - mdmn_work_svc_1
- * - mdmn_wakeup_initiator_svc_1
- * - mdmn_wakeup_master_svc_1
- * - mdmn_comm_lock_svc_1
- * - mdmn_comm_unlock_svc_1
- * - mdmn_comm_suspend_svc_1
- * - mdmn_comm_resume_svc_1
- * - mdmn_comm_reinit_set_svc_1
+ * - mdmn_send_svc_2
+ * - mdmn_work_svc_2
+ * - mdmn_wakeup_initiator_svc_2
+ * - mdmn_wakeup_master_svc_2
+ * - mdmn_comm_lock_svc_2
+ * - mdmn_comm_unlock_svc_2
+ * - mdmn_comm_suspend_svc_2
+ * - mdmn_comm_resume_svc_2
+ * - mdmn_comm_reinit_set_svc_2
* where send, lock, unlock and reinit are meant for external use,
* work and the two wakeups are for internal use only.
*
* NOTE:
- * On every node only one of those xxx_1 functions can be active at the
+ * On every node only one of those xxx_2 functions can be active at the
* same time because the daemon is single threaded.
*
+ * (not quite true, as mdmn_send_svc_2 and mdmn_work_svc_2 do thr_create()s
+ * as part of their handlers, so those aspects are multi-threaded)
*
* In case an event occurs that has to be propagated to all the nodes...
*
* One node (the initiator)
* calls the libmeta function mdmn_send_message()
- * This function calls the local daemon thru mdmn_send_svc_1.
+ * This function calls the local daemon thru mdmn_send_svc_2.
*
* On the initiator:
- * mdmn_send_svc_1()
+ * mdmn_send_svc_2()
* - starts a thread -> mdmn_send_to_work() and returns.
* mdmn_send_to_work()
* - sends this message over to the master of the diskset.
- * This is done by calling mdmn_work_svc_1 on the master.
+ * This is done by calling mdmn_work_svc_2 on the master.
* - registers to the initiator_table
* - exits without doing a svc_sendreply() for the call to
- * mdmn_send_svc_1. This means that call is blocked until somebody
+ * mdmn_send_svc_2. This means that call is blocked until somebody
* (see end of this comment) does a svc_sendreply().
* This means mdmn_send_message() does not yet return.
* - A timeout surveillance is started at this point.
@@ -82,42 +83,42 @@
* to the caller.
*
* On the master:
- * mdmn_work_svc_1()
+ * mdmn_work_svc_2()
* - starts a thread -> mdmn_master_process_msg() and returns
* mdmn_master_process_msg()
* - logs the message to the change log
* - executes the message locally
* - flags the message in the change log
- * - sends the message to mdmn_work_svc_1() on all the
+ * - sends the message to mdmn_work_svc_2() on all the
* other nodes (slaves)
- * after each call to mdmn_work_svc_1 the thread goes to sleep and
- * will be woken up by mdmn_wakeup_master_svc_1() as soon as the
+ * after each call to mdmn_work_svc_2 the thread goes to sleep and
+ * will be woken up by mdmn_wakeup_master_svc_2() as soon as the
* slave node is done with this message.
* - In case the slave doesn't respond in a apropriate time, an error
* is assumed to ensure the master doesn't wait forever.
*
* On a slave:
- * mdmn_work_svc_1()
+ * mdmn_work_svc_2()
* - starts a thread -> mdmn_slave_process_msg() and returns
* mdmn_slave_process_msg()
* - processes this message locally by calling the appropriate message
* handler, that creates some result.
- * - sends that result thru a call to mdmn_wakeup_master_svc_1() to
+ * - sends that result thru a call to mdmn_wakeup_master_svc_2() to
* the master.
*
* Back on the master:
- * mdmn_wakeup_master_svc_1()
+ * mdmn_wakeup_master_svc_2()
* - stores the result into the master_table.
* - signals the mdmn_master_process_msg-thread.
* - returns
* mdmn_master_process_msg()
* - after getting the results from all nodes
* - sends them back to the initiating node thru a call to
- * mdmn_wakeup_initiator_svc_1.
+ * mdmn_wakeup_initiator_svc_2.
*
* Back on the initiator:
- * mdmn_wakeup_initiator_svc_1()
- * - calls svc_sendreply() which makes the call to mdmn_send_svc_1()
+ * mdmn_wakeup_initiator_svc_2()
+ * - calls svc_sendreply() which makes the call to mdmn_send_svc_2()
* return.
* which allows the initial mdmn_send_message() call to return.
*/
@@ -195,8 +196,8 @@ mdmn_clnt_create(char *ignore, void *data, struct timeval *time_out)
{
md_mnnode_desc *node = (md_mnnode_desc *)data;
- return (clnt_create_timed(node->nd_priv_ic, MDMN_COMMD, ONE, "tcp",
- time_out));
+ return (clnt_create_timed(node->nd_priv_ic, MDMN_COMMD, TWO, "tcp",
+ time_out));
}
#define FLUSH_DEBUGFILE() \
@@ -219,15 +220,15 @@ panic_system(int nid, md_mn_msgtype_t type, int master_err, int master_exitval,
if (master_err != MDMNE_ACK) {
snprintf(msg_buf, MAXPATHLEN, "rpc.mdcommd: RPC fail on master "
- "when processing message type %d\n", type);
+ "when processing message type %d\n", type);
} else if (slave_result == NULL) {
snprintf(msg_buf, MAXPATHLEN, "rpc.mdcommd: RPC fail on node "
- "%d when processing message type %d\n", nid, type);
+ "%d when processing message type %d\n", nid, type);
} else {
snprintf(msg_buf, MAXPATHLEN, "rpc.mdcommd: Inconsistent "
- "return value from node %d when processing message "
- "type %d. Master exitval = %d, Slave exitval = %d\n",
- nid, type, master_exitval, slave_result->mmr_exitval);
+ "return value from node %d when processing message "
+ "type %d. Master exitval = %d, Slave exitval = %d\n",
+ nid, type, master_exitval, slave_result->mmr_exitval);
}
commd_err.size = strlen(msg_buf);
commd_err.md_message = (uint64_t)(uintptr_t)&msg_buf[0];
@@ -335,12 +336,17 @@ timeout_initiator(set_t setno, md_mn_msgclass_t class)
commd_debug(MD_MMV_MISC, "timeout_ini: (%d, 0x%llx-%d)\n",
MSGID_ELEMS(mid));
+ /*
+ * Give the result the corresponding msgid from the failed message.
+ */
+ MSGID_COPY(&mid, &(resultp->mmr_msgid));
/* return to mdmn_send_message() and let it deal with the situation */
mdmn_svc_sendreply(transp, xdr_md_mn_result_t, (char *)resultp);
free(resultp);
commd_debug(MD_MMV_MISC, "timeout_ini: sendreplied\n");
+ svc_done(transp);
mdmn_unregister_initiator_table(setno, class);
}
@@ -499,13 +505,13 @@ mdmn_is_node_dead(md_mnnode_desc *node)
* Perform some global initializations.
*
* the following routines have to call this before operation can start:
- * - mdmn_send_svc_1
- * - mdmn_work_svc_1
- * - mdmn_comm_lock_svc_1
- * - mdmn_comm_unlock_svc_1
- * - mdmn_comm_suspend_svc_1
- * - mdmn_comm_resume_svc_1
- * - mdmn_comm_reinit_set_svc_1
+ * - mdmn_send_svc_2
+ * - mdmn_work_svc_2
+ * - mdmn_comm_lock_svc_2
+ * - mdmn_comm_unlock_svc_2
+ * - mdmn_comm_suspend_svc_2
+ * - mdmn_comm_resume_svc_2
+ * - mdmn_comm_reinit_set_svc_2
*
* This is a single threaded daemon, so it can only be in one of the above
* routines at the same time.
@@ -547,8 +553,7 @@ global_init(void)
__savetime = gethrtime();
(void) time(&clock_val);
- commd_debug(MD_MMV_MISC, "global init called %s\n",
- ctime(&clock_val));
+ commd_debug(MD_MMV_MISC, "global init called %s\n", ctime(&clock_val));
/* start a thread that flushes out the debug on a regular basis */
thr_create(NULL, 0, (void *(*)(void *))flush_fcout,
@@ -663,9 +668,9 @@ mdmn_init_client(set_t setno, md_mn_nodeid_t nid)
*/
while ((client[setno][nid] == (CLIENT *) NULL) &&
(tout < MD_CLNT_CREATE_TOUT)) {
- client[setno][nid] = meta_client_create_retry
- (node->nd_nodename, mdmn_clnt_create,
- (void *) node, MD_CLNT_CREATE_SUBTIMEOUT, &ep);
+ client[setno][nid] = meta_client_create_retry(
+ node->nd_nodename, mdmn_clnt_create,
+ (void *) node, MD_CLNT_CREATE_SUBTIMEOUT, &ep);
/* Is the node dead? */
if (mdmn_is_node_dead(node) == 1) {
commd_debug(MD_MMV_SYSLOG,
@@ -889,9 +894,9 @@ mdmn_init_set(set_t setno, int todo)
*/
while ((client[setno][nid] == (CLIENT *) NULL) &&
(tout < MD_CLNT_CREATE_TOUT)) {
- client[setno][nid] = meta_client_create_retry
- (node->nd_nodename, mdmn_clnt_create,
- (void *) node, MD_CLNT_CREATE_SUBTIMEOUT, &ep);
+ client[setno][nid] = meta_client_create_retry(
+ node->nd_nodename, mdmn_clnt_create,
+ (void *) node, MD_CLNT_CREATE_SUBTIMEOUT, &ep);
/* Is the node dead? */
if (mdmn_is_node_dead(node) == 1) {
commd_debug(MD_MMV_SYSLOG,
@@ -942,7 +947,7 @@ mdmn_init_set(set_t setno, int todo)
void *
mdmn_send_to_work(void *arg)
{
- int *rpc_err;
+ int *rpc_err = NULL;
int success;
int try_master;
set_t setno;
@@ -956,9 +961,6 @@ mdmn_send_to_work(void *arg)
msg = matp->mat_msg;
transp = matp->mat_transp;
- /* the alloc was done in mdmn_send_svc_1 */
- free(matp);
-
class = mdmn_get_message_class(msg->msg_type);
setno = msg->msg_setno;
@@ -980,8 +982,7 @@ mdmn_send_to_work(void *arg)
if (success == MDMNE_CLASS_BUSY) {
md_mn_msgid_t active_mid;
- mdmn_get_initiator_table_id(setno, class,
- &active_mid);
+ mdmn_get_initiator_table_id(setno, class, &active_mid);
commd_debug(MD_MMV_SEND,
"send_to_work: received but locally busy "
@@ -1011,7 +1012,8 @@ mdmn_send_to_work(void *arg)
* Send the request to the work function on the master
* this call will return immediately
*/
- rpc_err = mdmn_work_1(msg, client[setno][set_master]);
+ rpc_err = mdmn_work_2(msg, client[setno][set_master],
+ set_master);
/* Everything's Ok? */
if (rpc_err == NULL) {
@@ -1043,7 +1045,7 @@ mdmn_send_to_work(void *arg)
/*
* If we are here, we sucessfully delivered the message.
* We register the initiator_table, so that
- * wakeup_initiator_1 can do the sendreply with the
+ * wakeup_initiator_2 can do the sendreply with the
* results for us.
*/
success = MDMNE_ACK;
@@ -1068,15 +1070,27 @@ mdmn_send_to_work(void *arg)
md_mn_result_t *resultp;
resultp = Zalloc(sizeof (md_mn_result_t));
resultp->mmr_comm_state = success;
+ /*
+ * copy the MSGID so that we know _which_ message
+ * failed (if the transp has got mangled)
+ */
+ MSGID_COPY(&(msg->msg_msgid), &(resultp->mmr_msgid));
mdmn_svc_sendreply(transp, xdr_md_mn_result_t, (char *)resultp);
commd_debug(MD_MMV_SEND,
"send_to_work: not registered (%d, 0x%llx-%d) cs=%d\n",
MSGID_ELEMS(msg->msg_msgid), success);
free_result(resultp);
+ /*
+ * We don't have a timeout registered to wake us up, so we're
+ * now done with this handle. Release it back to the pool.
+ */
+ svc_done(transp);
}
free_msg(msg);
+ /* the alloc was done in mdmn_send_svc_2 */
+ Free(matp);
mutex_unlock(mx);
return (NULL);
@@ -1186,7 +1200,7 @@ do_send_message(md_mn_msg_t *msg, md_mnnode_desc *node)
int timeout_retries = 0;
int *ret = NULL;
set_t setno;
- cond_t *cv; /* see mdmn_wakeup_master_svc_1 */
+ cond_t *cv; /* see mdmn_wakeup_master_svc_2 */
mutex_t *mx; /* protection for class_busy */
timestruc_t timeout; /* surveillance for remote daemon */
md_mn_nodeid_t nid;
@@ -1251,7 +1265,7 @@ retry_rpc:
}
/* send it over, it will return immediately */
- ret = mdmn_work_1(msg, client[setno][nid]);
+ ret = mdmn_work_2(msg, client[setno][nid], nid);
rw_unlock(&client_rwlock[setno]);
@@ -1462,7 +1476,7 @@ mdmn_master_process_msg(md_mn_msg_t *msg)
result->mmr_comm_state = MDMNE_LOG_FAIL;
/*
* Note that the mark_busy was already done by
- * mdmn_work_svc_1()
+ * mdmn_work_svc_2()
*/
mutex_lock(&mdmn_busy_mutex[setno]);
mdmn_mark_class_unbusy(setno, orig_class);
@@ -1487,8 +1501,8 @@ mdmn_master_process_msg(md_mn_msg_t *msg)
commd_debug(MD_MMV_SYSLOG,
"proc_mas: No client for initiator \n");
} else {
- ret = mdmn_wakeup_initiator_1(result,
- client[setno][sender]);
+ ret = mdmn_wakeup_initiator_2(result,
+ client[setno][sender], sender);
}
rw_unlock(&client_rwlock[setno]);
@@ -1677,6 +1691,12 @@ proceed:
continue;
}
+ /* If a DIRECTED message, skip non-recipient nodes */
+ if ((cmsg->msg_flags & MD_MSGF_DIRECTED) &&
+ nid != cmsg->msg_recipient) {
+ continue;
+ }
+
mutex_lock(mx);
/*
* Register the node that is addressed,
@@ -1865,7 +1885,8 @@ proceed:
commd_debug(MD_MMV_SYSLOG,
"proc_mas: unable to create client for initiator\n");
} else {
- ret = mdmn_wakeup_initiator_1(result, client[setno][sender]);
+ ret = mdmn_wakeup_initiator_2(result, client[setno][sender],
+ sender);
}
rw_unlock(&client_rwlock[setno]);
@@ -2046,14 +2067,14 @@ mdmn_slave_process_msg(md_mn_msg_t *msg)
rw_unlock(&client_rwlock[setno]);
break;
} else {
- ret = mdmn_wakeup_master_1(result,
- client[setno][sender]);
+ ret = mdmn_wakeup_master_2(result,
+ client[setno][sender], sender);
/*
- * if mdmn_wakeup_master_1 returns NULL, it can be that
+ * if mdmn_wakeup_master_2 returns NULL, it can be that
* the master (or the commd on the master) had died.
* In that case, we destroy the client to the master
* and retry.
- * If mdmn_wakeup_master_1 doesn't return MDMNE_ACK,
+ * If mdmn_wakeup_master_2 doesn't return MDMNE_ACK,
* the commd on the master is alive but
* something else is wrong,
* in that case a retry doesn't make sense => break out
@@ -2097,8 +2118,19 @@ mdmn_slave_process_msg(md_mn_msg_t *msg)
}
-md_mn_result_t *
-mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
+/*
+ * mdmn_send_svc_2:
+ * ---------------
+ * Check that the issuing node is a legitimate one (i.e. is licensed to send
+ * messages to us), that the RPC request can be staged.
+ *
+ * Returns:
+ * 0 => no RPC request is in-flight, no deferred svc_sendreply()
+ * 1 => queued RPC request in-flight. Completion will be made (later)
+ * by a wakeup_initiator_2() [hopefully]
+ */
+int
+mdmn_send_svc_2(md_mn_msg_t *omsg, struct svc_req *rqstp)
{
int err;
set_t setno;
@@ -2121,7 +2153,7 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
mdmn_svc_sendreply(transp, xdr_md_mn_result_t, (char *)resultp);
free_result(resultp);
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
- return (NULL);
+ return (0);
}
/* check if the global initialization is done */
@@ -2152,7 +2184,7 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
(char *)resultp);
free_result(resultp);
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
- return (NULL);
+ return (0);
}
}
@@ -2169,7 +2201,7 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
mdmn_svc_sendreply(transp, xdr_md_mn_result_t, (char *)resultp);
free_result(resultp);
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
- return (NULL);
+ return (0);
}
@@ -2184,10 +2216,10 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
free_result(resultp);
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
commd_debug(MD_MMV_SEND,
- "send: type locked (%d, 0x%llx-%d), set=%d, class=%d, "
- "type=%d\n", MSGID_ELEMS(msg->msg_msgid), setno, class,
- msg->msg_type);
- return (NULL);
+ "send: type locked (%d, 0x%llx-%d), set=%d, class=%d, "
+ "type=%d\n", MSGID_ELEMS(msg->msg_msgid), setno, class,
+ msg->msg_type);
+ return (0);
}
@@ -2213,7 +2245,7 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
free_result(resultp);
commd_debug(MD_MMV_SEND,
"send: init err = %d\n", err);
- return (NULL);
+ return (0);
}
}
@@ -2227,10 +2259,10 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
free_result(resultp);
commd_debug(MD_MMV_SEND,
- "send: class suspended (%d, 0x%llx-%d), set=%d, "
- "class=%d, type=%d\n", MSGID_ELEMS(msg->msg_msgid),
- setno, class, msg->msg_type);
- return (NULL);
+ "send: class suspended (%d, 0x%llx-%d), set=%d, "
+ "class=%d, type=%d\n", MSGID_ELEMS(msg->msg_msgid),
+ setno, class, msg->msg_type);
+ return (0);
}
mutex_unlock(&mdmn_busy_mutex[setno]);
@@ -2238,10 +2270,10 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
if (check_license(rqstp, 0) == FALSE) {
svc_freeargs(transp, xdr_md_mn_msg_t, (caddr_t)msg);
commd_debug(MD_MMV_SEND,
- "send: check licence fail(%d, 0x%llx-%d), set=%d, "
- "class=%d, type=%d\n", MSGID_ELEMS(msg->msg_msgid),
- setno, class, msg->msg_type);
- return (NULL);
+ "send: check licence fail(%d, 0x%llx-%d), set=%d, "
+ "class=%d, type=%d\n", MSGID_ELEMS(msg->msg_msgid),
+ setno, class, msg->msg_type);
+ return (0);
}
@@ -2268,17 +2300,17 @@ mdmn_send_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
MSGID_ELEMS(msg->msg_msgid));
/*
* We return here without sending results. This will be done by
- * mdmn_wakeup_initiator_svc_1() as soon as the results are available.
+ * mdmn_wakeup_initiator_svc_2() as soon as the results are available.
* Until then the calling send_message will be blocked, while we
* are able to take calls.
*/
- return (NULL);
+ return (1);
}
/* ARGSUSED */
int *
-mdmn_work_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
+mdmn_work_svc_2(md_mn_msg_t *omsg, struct svc_req *rqstp)
{
int err;
set_t setno;
@@ -2362,7 +2394,7 @@ mdmn_work_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
mutex_lock(&mdmn_busy_mutex[setno]);
- /* check if class is locked via a call to mdmn_comm_lock_svc_1 */
+ /* check if class is locked via a call to mdmn_comm_lock_svc_2 */
if (mdmn_is_class_locked(setno, class) == TRUE) {
mutex_unlock(&mdmn_busy_mutex[setno]);
*retval = MDMNE_CLASS_LOCKED;
@@ -2430,14 +2462,14 @@ mdmn_work_svc_1(md_mn_msg_t *omsg, struct svc_req *rqstp)
/* ARGSUSED */
int *
-mdmn_wakeup_initiator_svc_1(md_mn_result_t *res, struct svc_req *rqstp)
+mdmn_wakeup_initiator_svc_2(md_mn_result_t *res, struct svc_req *rqstp)
{
int *retval;
int err;
set_t setno;
mutex_t *mx; /* protection of initiator_table */
- SVCXPRT *transp;
+ SVCXPRT *transp = NULL;
md_mn_msgid_t initiator_table_id;
md_mn_msgclass_t class;
@@ -2491,13 +2523,14 @@ mdmn_wakeup_initiator_svc_1(md_mn_result_t *res, struct svc_req *rqstp)
* Search the initiator wakeup table.
* If we find an entry here (which should always be true)
* we are on the initiating node and we wakeup the original
- * local rpc call
+ * local rpc call.
*/
mdmn_get_initiator_table_id(setno, class, &initiator_table_id);
if (MSGID_CMP(&(initiator_table_id), &(res->mmr_msgid))) {
transp = mdmn_get_initiator_table_transp(setno, class);
mdmn_svc_sendreply(transp, xdr_md_mn_result_t, (char *)res);
+ svc_done(transp);
mdmn_unregister_initiator_table(setno, class);
*retval = MDMNE_ACK;
@@ -2532,7 +2565,7 @@ mdmn_wakeup_initiator_svc_1(md_mn_result_t *res, struct svc_req *rqstp)
*/
/* ARGSUSED */
int *
-mdmn_wakeup_master_svc_1(md_mn_result_t *ores, struct svc_req *rqstp)
+mdmn_wakeup_master_svc_2(md_mn_result_t *ores, struct svc_req *rqstp)
{
int *retval;
@@ -2645,7 +2678,7 @@ mdmn_wakeup_master_svc_1(md_mn_result_t *ores, struct svc_req *rqstp)
* This is mainly done for debug purpose.
* This set/class combination immediately is blocked,
* even in the middle of sending messages to multiple slaves.
- * This remains until the user issues a mdmn_comm_unlock_svc_1 for the same
+ * This remains until the user issues a mdmn_comm_unlock_svc_2 for the same
* set/class combination.
*
* Special messages of class MD_MSG_CLASS0 can never be locked.
@@ -2666,7 +2699,7 @@ mdmn_wakeup_master_svc_1(md_mn_result_t *ores, struct svc_req *rqstp)
/* ARGSUSED */
int *
-mdmn_comm_lock_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
+mdmn_comm_lock_svc_2(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
{
int *retval;
set_t setno = msc->msc_set;
@@ -2722,7 +2755,7 @@ mdmn_comm_lock_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
*/
/* ARGSUSED */
int *
-mdmn_comm_unlock_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
+mdmn_comm_unlock_svc_2(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
{
int *retval;
set_t setno = msc->msc_set;
@@ -2766,7 +2799,7 @@ mdmn_comm_unlock_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
}
/*
- * mdmn_comm_suspend_svc_1(setno, class)
+ * mdmn_comm_suspend_svc_2(setno, class)
*
* Drain all outstanding messages for a given set/class combination
* and don't allow new messages to be processed.
@@ -2812,7 +2845,7 @@ mdmn_comm_unlock_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
/* ARGSUSED */
int *
-mdmn_comm_suspend_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
+mdmn_comm_suspend_svc_2(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
{
int *retval;
int failure = 0;
@@ -2902,7 +2935,7 @@ mdmn_comm_suspend_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
}
/*
- * mdmn_comm_resume_svc_1(setno, class)
+ * mdmn_comm_resume_svc_2(setno, class)
*
* Resume processing messages for a given set.
* This incorporates the repeal of a previous suspend operation.
@@ -2927,7 +2960,7 @@ mdmn_comm_suspend_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
*/
/* ARGSUSED */
int *
-mdmn_comm_resume_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
+mdmn_comm_resume_svc_2(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
{
int *retval;
set_t startset, endset;
@@ -3029,7 +3062,7 @@ mdmn_comm_resume_svc_1(md_mn_set_and_class_t *msc, struct svc_req *rqstp)
}
/* ARGSUSED */
int *
-mdmn_comm_reinit_set_svc_1(set_t *setnop, struct svc_req *rqstp)
+mdmn_comm_reinit_set_svc_2(set_t *setnop, struct svc_req *rqstp)
{
int *retval;
md_mnnode_desc *node;
@@ -3093,7 +3126,7 @@ mdmn_comm_reinit_set_svc_1(set_t *setnop, struct svc_req *rqstp)
/* ARGSUSED */
int *
-mdmn_comm_msglock_svc_1(md_mn_type_and_lock_t *mmtl, struct svc_req *rqstp)
+mdmn_comm_msglock_svc_2(md_mn_type_and_lock_t *mmtl, struct svc_req *rqstp)
{
int *retval;
md_mn_msgtype_t type = mmtl->mmtl_type;
diff --git a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c
index 5525f8546a..f4e6478dc7 100644
--- a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c
+++ b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/lvm/mdmn_commd.h>
#include <stdio.h>
#include <stdlib.h> /* getenv, exit */
@@ -60,16 +58,16 @@ static int _rpcpmstart; /* Started by a port monitor ? */
static int _rpcsvcstate = _IDLE; /* Set when a request is serviced */
static int _rpcsvccount = 0; /* Number of requests being serviced */
-extern md_mn_result_t *mdmn_send_svc_1();
-extern int *mdmn_work_svc_1();
-extern int *mdmn_wakeup_initiator_svc_1();
-extern int *mdmn_wakeup_master_svc_1();
-extern int *mdmn_comm_lock_svc_1();
-extern int *mdmn_comm_unlock_svc_1();
-extern int *mdmn_comm_suspend_svc_1();
-extern int *mdmn_comm_resume_svc_1();
-extern int *mdmn_comm_reinit_set_svc_1();
-extern int *mdmn_comm_msglock_svc_1();
+extern int mdmn_send_svc_2();
+extern int *mdmn_work_svc_2();
+extern int *mdmn_wakeup_initiator_svc_2();
+extern int *mdmn_wakeup_master_svc_2();
+extern int *mdmn_comm_lock_svc_2();
+extern int *mdmn_comm_unlock_svc_2();
+extern int *mdmn_comm_suspend_svc_2();
+extern int *mdmn_comm_resume_svc_2();
+extern int *mdmn_comm_reinit_set_svc_2();
+extern int *mdmn_comm_msglock_svc_2();
static void
@@ -107,7 +105,7 @@ closedown(void)
}
static void
-mdmn_commd_1(rqstp, transp)
+mdmn_commd_2(rqstp, transp)
struct svc_req *rqstp;
register SVCXPRT *transp;
{
@@ -124,7 +122,6 @@ mdmn_commd_1(rqstp, transp)
char *(*local)();
int free_result = 0;
-
_rpcsvccount++;
switch (rqstp->rq_proc) {
case NULLPROC:
@@ -132,6 +129,7 @@ mdmn_commd_1(rqstp, transp)
(char *)NULL);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
+ svc_done(transp);
return;
case mdmn_send:
@@ -140,81 +138,94 @@ mdmn_commd_1(rqstp, transp)
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
svcerr_decode(transp);
+ svc_done(transp);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
return;
}
/*
- * mdmn_send_1 will not always do a sendreply.
+ * mdmn_send_2 will not always do a sendreply.
* it will register in a table and let the mdmn_wakeup1
* do the sendreply for that call.
* in order to register properly we need the transp handle
+ * If we get a 0 back from mdmn_send_svc_2() we have no pending
+ * RPC in-flight, so we drop the service count.
*/
- (void) mdmn_send_svc_1((md_mn_msg_t *)&argument, rqstp);
+ if (mdmn_send_svc_2((md_mn_msg_t *)&argument, rqstp) == 0) {
+ _rpcsvccount--;
+ _rpcsvcstate = _SERVED;
+ svc_done(rqstp->rq_xprt);
+ }
- return; /* xdr_free is called by mdmn_wakeup_initiator_svc_1 */
+ return; /* xdr_free is called by mdmn_wakeup_initiator_svc_2 */
case mdmn_work:
_xdr_argument = xdr_md_mn_msg_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_work_svc_1;
+ local = (char *(*)()) mdmn_work_svc_2;
free_result = 1;
break;
case mdmn_wakeup_master:
_xdr_argument = xdr_md_mn_result_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_wakeup_master_svc_1;
+ local = (char *(*)()) mdmn_wakeup_master_svc_2;
free_result = 1;
break;
case mdmn_wakeup_initiator:
+ /*
+ * We must have had an in-flight RPC request to get here,
+ * so drop the in-flight count.
+ */
_xdr_argument = xdr_md_mn_result_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_wakeup_initiator_svc_1;
+ local = (char *(*)()) mdmn_wakeup_initiator_svc_2;
free_result = 1;
+ _rpcsvccount--;
break;
case mdmn_comm_lock:
_xdr_argument = xdr_md_mn_set_and_class_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_lock_svc_1;
+ local = (char *(*)()) mdmn_comm_lock_svc_2;
break;
case mdmn_comm_unlock:
_xdr_argument = xdr_md_mn_set_and_class_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_unlock_svc_1;
+ local = (char *(*)()) mdmn_comm_unlock_svc_2;
break;
case mdmn_comm_suspend:
_xdr_argument = xdr_md_mn_set_and_class_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_suspend_svc_1;
+ local = (char *(*)()) mdmn_comm_suspend_svc_2;
break;
case mdmn_comm_resume:
_xdr_argument = xdr_md_mn_set_and_class_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_resume_svc_1;
+ local = (char *(*)()) mdmn_comm_resume_svc_2;
break;
case mdmn_comm_reinit_set:
_xdr_argument = xdr_u_int;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_reinit_set_svc_1;
+ local = (char *(*)()) mdmn_comm_reinit_set_svc_2;
break;
case mdmn_comm_msglock:
_xdr_argument = xdr_md_mn_type_and_lock_t;
_xdr_result = xdr_int;
- local = (char *(*)()) mdmn_comm_msglock_svc_1;
+ local = (char *(*)()) mdmn_comm_msglock_svc_2;
break;
default:
svcerr_noproc(transp);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
+ svc_done(transp);
return;
}
(void) memset((char *)&argument, 0, sizeof (argument));
@@ -222,6 +233,7 @@ mdmn_commd_1(rqstp, transp)
svcerr_decode(transp);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
+ svc_done(transp);
return;
}
result = (*local)(&argument, rqstp);
@@ -231,12 +243,15 @@ mdmn_commd_1(rqstp, transp)
}
if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
_msgout(gettext("unable to free arguments"));
+ svc_done(transp);
exit(1);
}
if (free_result == 1) {
free(result);
}
+
+ svc_done(transp);
_rpcsvccount--;
_rpcsvcstate = _SERVED;
}
@@ -249,6 +264,7 @@ static void
exit_commd()
{
md_error_t ep = mdnullerror;
+ syslog(LOG_DAEMON | LOG_DEBUG, gettext("mdcommd exiting"));
(void) metaioctl(MD_MN_SET_COMMD_RUNNING, 0, &ep, "rpc.mdcommd");
}
@@ -259,10 +275,23 @@ main()
pid_t pid;
int i;
md_error_t ep = mdnullerror;
+ int mode = RPC_SVC_MT_USER;
(void) sigset(SIGPIPE, SIG_IGN);
/*
+ * Attempt to set MT_USER behaviour for mdcommd service routines.
+ * If this isn't done, there is a possibility that the transport
+ * handle might be freed before the thread created by mdmn_send_svc_2
+ * can use it. A consequence of this is that svc_done() must be
+ * called on the handle when it's no longer needed.
+ */
+ if (rpc_control(RPC_SVC_MTMODE_SET, &mode) == FALSE) {
+ _msgout(gettext("cannot set MT_USER mode for RPC service"));
+ exit(1);
+ }
+
+ /*
* If stdin looks like a TLI endpoint, we assume
* that we were started by a port monitor. If
* t_getstate fails with TBADF, this is not a
@@ -294,9 +323,9 @@ main()
}
if (nconf)
freenetconfigent(nconf);
- if (!svc_reg(transp, MDMN_COMMD, ONE, mdmn_commd_1, 0)) {
+ if (!svc_reg(transp, MDMN_COMMD, TWO, mdmn_commd_2, 0)) {
_msgout(gettext(
- "unable to register (MDMN_COMMD, ONE)."));
+ "unable to register (MDMN_COMMD, TWO)."));
exit(1);
}
@@ -307,7 +336,8 @@ main()
(void) alarm(_RPCSVC_CLOSEDOWN/2);
}
- (void) metaioctl(MD_MN_SET_COMMD_RUNNING, (void *)1, &ep,
+ pid = getpid();
+ (void) metaioctl(MD_MN_SET_COMMD_RUNNING, (void *)pid, &ep,
"rpc.mdcommd");
svc_run();
exit(1);
@@ -343,8 +373,8 @@ main()
openlog("mdmn_commd", LOG_PID, LOG_DAEMON);
#endif
}
- if (!svc_create(mdmn_commd_1, MDMN_COMMD, ONE, "tcp")) {
- _msgout(gettext("unable to create (MDMN_COMMD, ONE) for tcp."));
+ if (!svc_create(mdmn_commd_2, MDMN_COMMD, TWO, "tcp")) {
+ _msgout(gettext("unable to create (MDMN_COMMD, TWO) for tcp."));
exit(1);
}
diff --git a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c
index 715c4a3307..e05022bf5b 100644
--- a/usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c
+++ b/usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -446,6 +444,7 @@ dump_msg(uint_t dbc, char *prefix, md_mn_msg_t *msg)
commd_debug(dbc, "%s sender = %d\n", prefix, msg->msg_sender);
commd_debug(dbc, "%s flags = 0x%x\n", prefix, msg->msg_flags);
commd_debug(dbc, "%s setno = %d\n", prefix, msg->msg_setno);
+ commd_debug(dbc, "%s recipient = %d\n", prefix, msg->msg_recipient);
commd_debug(dbc, "%s type = %d\n", prefix, msg->msg_type);
commd_debug(dbc, "%s size = %d\n", prefix, msg->msg_event_size);
if (msg->msg_event_size) {
@@ -513,9 +512,8 @@ mdmn_get_mce_by_msg(md_mn_msg_t *msg)
class = msg->msg_msgid.mid_oclass;
}
- mct_index = submsg +
- class * MAX_SUBMESSAGES +
- nodeid * MAX_SUBMESSAGES * MD_MN_NCLASSES;
+ mct_index = submsg + class * MAX_SUBMESSAGES +
+ nodeid * MAX_SUBMESSAGES * MD_MN_NCLASSES;
mct_offset = mct_index * sizeof (md_mn_mce_t);
@@ -694,12 +692,12 @@ mdmn_check_completion(md_mn_msg_t *msg, md_mn_result_t *result)
}
}
commd_debug(MD_MMV_MISC,
- "mdmn_check_completion: msg already processed \n");
+ "mdmn_check_completion: msg already processed \n");
dump_result(MD_MMV_MISC, "mdmn_check_completion", result);
return (MDMN_MCT_DONE);
}
commd_debug(MD_MMV_MISC,
- "mdmn_check_completion: msg not yet processed\n");
+ "mdmn_check_completion: msg not yet processed\n");
return (MDMN_MCT_NOT_DONE);
}
diff --git a/usr/src/cmd/lvm/util/metaclust.c b/usr/src/cmd/lvm/util/metaclust.c
index deeff350e2..cb98329aac 100644
--- a/usr/src/cmd/lvm/util/metaclust.c
+++ b/usr/src/cmd/lvm/util/metaclust.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <meta.h>
#include <sdssc.h>
#include <signal.h>
@@ -117,6 +115,8 @@ static void
sigalarmhandler(int sig)
{
int i, n, ret, stat_loc = 0;
+ FILE *pgcore;
+ char corecmd[256];
n = sizeof (step_table) / sizeof (step_table[0]);
for (i = 0; i < n; i++) {
@@ -130,6 +130,25 @@ sigalarmhandler(int sig)
step_table[i].step_nam,
meta_print_hrtime(gethrtime() - start_time));
+ /*
+ * 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
+ */
+
+ (void) memset(corecmd, 0, sizeof (corecmd));
+ (void) snprintf(corecmd, sizeof (corecmd),
+ "/bin/gcore -g %d >/dev/null 2>&1", (int)c_pid);
+
+ pgcore = popen(corecmd, "r");
+
+ if (pgcore == NULL) {
+ meta_mc_log(MC_LOG1, gettext("Could not grab core for pid %s"),
+ c_pid);
+ } else {
+ (void) pclose(pgcore);
+ }
+
if ((ret = kill(c_pid, SIGKILL)) == 0) {
/*
* The child will wait forever until the status is retrieved
@@ -1762,7 +1781,6 @@ main(int argc, char **argv)
"rpc.mdcommd for set %s\n"), sp->setname);
md_exit(local_sp, 1);
}
- meta_ping_mnset(setno);
/* Unblock mddb parse messages */
if (s_ownset(sp->setno, ep) == MD_SETOWNER_YES) {
diff --git a/usr/src/cmd/mdb/common/modules/md/dumpmirror.c b/usr/src/cmd/mdb/common/modules/md/dumpmirror.c
new file mode 100644
index 0000000000..53e70438b7
--- /dev/null
+++ b/usr/src/cmd/mdb/common/modules/md/dumpmirror.c
@@ -0,0 +1,230 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "mdinclude.h"
+
+/*
+ * Display an arbitrary bitmap by showing the set bits in the array.
+ * Output will be <start>-<end> for ranges or <position> for singleton bits.
+ */
+static void
+print_mm_bm(unsigned char *bm, uint_t size, char *bm_name)
+{
+ int i;
+ int first_set = -1;
+ int need_comma = 0;
+
+ mdb_printf("%s set bits: ", bm_name);
+ for (i = 0; i < size; i++) {
+ if (isset(bm, i)) {
+ if (first_set == -1) {
+ first_set = i;
+ }
+ } else {
+ if (first_set != -1) {
+ if (first_set != (i-1)) {
+ mdb_printf("%s%u-%u",
+ (need_comma ? "," : ""),
+ first_set, (i-1));
+ } else {
+ mdb_printf("%s%u",
+ (need_comma ? "," : ""), first_set);
+ }
+ need_comma = 1;
+ first_set = -1;
+ }
+ }
+ }
+ if (first_set != -1) {
+ mdb_printf("%s%u-%u", (need_comma ? "," : ""), first_set,
+ size-1);
+ }
+ mdb_printf("\n");
+}
+
+/*
+ * Print uchar_t sized count fields (typically un_pernode_dirty_map entries)
+ */
+
+static void
+print_mm_cnt_c(unsigned char *bm, uint_t size, char *bm_name)
+{
+ int i;
+ int need_comma = 0;
+
+ mdb_printf("%s set counts: ", bm_name);
+ for (i = 0; i < size; i++) {
+ if (bm[i]) {
+ mdb_printf("%s(%d,%3d)", (need_comma ? "," : ""), i,
+ (uint_t)bm[i]);
+ need_comma = 1;
+ }
+ }
+ mdb_printf("\n");
+}
+
+static void
+print_mm_cnt_w(unsigned short *bm, uint_t size, char *bm_name)
+{
+ int i;
+ int need_comma = 0;
+
+ mdb_printf("%s set counts: ", bm_name);
+ for (i = 0; i < size; i++) {
+ if (bm[i]) {
+ mdb_printf("%s(%d,%5d)", (need_comma ? "," : ""), i,
+ (uint_t)bm[i]);
+ need_comma = 1;
+ }
+ }
+ mdb_printf("\n");
+}
+
+/*
+ * Print the associated bitmaps for the specified mm_unit_t
+ * These are:
+ * un_pernode_dirty_bm
+ * un_goingclean_bm
+ * un_dirty_bm
+ * un_goingdirty_bm
+ * un_resync_bm
+ *
+ * Associated counts for unit:
+ * un_pernode_dirty_sum[] (uchar_t)
+ * un_outstanding_writes[] (ushort_t)
+ *
+ */
+
+/* ARGSUSED */
+int
+printmmbm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ mm_unit_t mm, *mmp;
+ unsigned char *rr_dirty_bm, *rr_goingclean_bm, *rr_goingdirty_bm;
+ unsigned char *rr_resync_bm;
+ uintptr_t un_dbm, un_gcbm, un_gdbm, un_rrbm, un_pnds, un_ow;
+ uint_t num_rr, rr_bitmap_size;
+ int i;
+ uintptr_t un_pernode_bm;
+ unsigned char *rr_pernode_dirty, *rr_pnds;
+ unsigned short *rr_ow;
+ /* just enough for un_pernode_dirty_bm[] plus three digits */
+ char pernode_str[25];
+
+ if (argc != 0)
+ return (DCMD_USAGE);
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ mdb_warn("No mm_unit_t address specified");
+ return (DCMD_ERR);
+ }
+
+ if (mdb_vread(&mm, sizeof (mm_unit_t), addr) == -1) {
+ mdb_warn("failed to read mm_unit_t at %p\n", addr);
+ return (DCMD_ERR);
+ }
+
+ mmp = &mm;
+
+ num_rr = mm.un_rrd_num;
+
+ un_dbm = (uintptr_t)mmp->un_dirty_bm;
+ un_gcbm = (uintptr_t)mmp->un_goingclean_bm;
+ un_gdbm = (uintptr_t)mmp->un_goingdirty_bm;
+ un_rrbm = (uintptr_t)mmp->un_resync_bm;
+ un_pnds = (uintptr_t)mmp->un_pernode_dirty_sum;
+ un_ow = (uintptr_t)mmp->un_outstanding_writes;
+
+ rr_bitmap_size = howmany(num_rr, NBBY);
+ rr_dirty_bm = (unsigned char *)mdb_alloc(rr_bitmap_size,
+ UM_SLEEP|UM_GC);
+ rr_goingclean_bm = (unsigned char *)mdb_alloc(rr_bitmap_size,
+ UM_SLEEP|UM_GC);
+ rr_goingdirty_bm = (unsigned char *)mdb_alloc(rr_bitmap_size,
+ UM_SLEEP|UM_GC);
+ rr_resync_bm = (unsigned char *)mdb_alloc(rr_bitmap_size,
+ UM_SLEEP|UM_GC);
+ rr_pnds = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC);
+ rr_ow = (unsigned short *)mdb_alloc(num_rr * sizeof (unsigned short),
+ UM_SLEEP|UM_GC);
+
+ if (mdb_vread(rr_dirty_bm, rr_bitmap_size, un_dbm) == -1) {
+ mdb_warn("failed to read un_dirty_bm at %p\n", un_dbm);
+ return (DCMD_ERR);
+ }
+ if (mdb_vread(rr_goingclean_bm, rr_bitmap_size, un_gcbm) == -1) {
+ mdb_warn("failed to read un_goingclean_bm at %p\n", un_gcbm);
+ return (DCMD_ERR);
+ }
+ if (mdb_vread(rr_goingdirty_bm, rr_bitmap_size, un_gdbm) == -1) {
+ mdb_warn("failed to read un_goingdirty_bm at %p\n", un_gdbm);
+ return (DCMD_ERR);
+ }
+ if (mdb_vread(rr_resync_bm, rr_bitmap_size, un_rrbm) == -1) {
+ mdb_warn("failed to read un_resync_bm at %p\n", un_rrbm);
+ return (DCMD_ERR);
+ }
+ if (mdb_vread(rr_pnds, num_rr, un_pnds) == -1) {
+ mdb_warn("failed to read un_pernode_dirty_sum at %p\n",
+ un_pnds);
+ return (DCMD_ERR);
+ }
+ if (mdb_vread(rr_ow, num_rr * sizeof (unsigned short), un_ow) == -1) {
+ mdb_warn("failed to read un_outstanding_writes at %p\n", un_ow);
+ return (DCMD_ERR);
+ }
+
+ print_mm_bm(rr_dirty_bm, num_rr, "un_dirty_bm");
+ print_mm_bm(rr_goingclean_bm, num_rr, "un_goingclean_bm");
+ print_mm_bm(rr_goingdirty_bm, num_rr, "un_goingdirty_bm");
+ print_mm_bm(rr_resync_bm, num_rr, "un_resync_bm");
+
+ /*
+ * Load all the un_pernode_bm[] entries and iterate through the non-
+ * NULL entries
+ */
+ rr_pernode_dirty = (unsigned char *)mdb_alloc(rr_bitmap_size,
+ UM_SLEEP|UM_GC);
+
+ for (i = 0; i < 128; i++) {
+ un_pernode_bm = (uintptr_t)mmp->un_pernode_dirty_bm[i];
+ if (un_pernode_bm) {
+ mdb_snprintf(pernode_str, sizeof (pernode_str),
+ "un_pernode_dirty_bm[%d]", i);
+ if (mdb_vread(rr_pernode_dirty, rr_bitmap_size,
+ un_pernode_bm) == -1) {
+ mdb_warn("failed to read %s at %p\n",
+ pernode_str, un_pernode_bm);
+ return (DCMD_ERR);
+ }
+ print_mm_bm(rr_pernode_dirty, num_rr, pernode_str);
+ }
+ }
+ print_mm_cnt_c(rr_pnds, num_rr, "un_pernode_dirty_sum");
+
+ print_mm_cnt_w(rr_ow, num_rr, "un_outstanding_writes");
+
+ return (DCMD_OK);
+}
diff --git a/usr/src/cmd/mdb/common/modules/md/md.c b/usr/src/cmd/mdb/common/modules/md/md.c
index b23804c10b..371dfa14f3 100644
--- a/usr/src/cmd/mdb/common/modules/md/md.c
+++ b/usr/src/cmd/mdb/common/modules/md/md.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/mdb_modapi.h>
@@ -37,6 +34,7 @@ extern int set_io(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int dumpnamespace(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int dumpsetaddr(uintptr_t, uint_t, int, const mdb_arg_t *);
extern int dumphotspare(uintptr_t, uint_t, int, const mdb_arg_t *);
+extern int printmmbm(uintptr_t, uint_t, int, const mdb_arg_t *);
extern void set_io_help();
/* from mdbgen */
@@ -79,6 +77,8 @@ const mdb_dcmd_t dcmds[] = {
dumpsetaddr },
{ "simple_de_ic", NULL, "simple mddb_de_ic_t",
simple_de_ic },
+ { "printmmbm", NULL, "print bitmaps for given mm_unit_t",
+ printmmbm },
{ NULL }
};
diff --git a/usr/src/cmd/mdb/common/modules/md/metastat.c b/usr/src/cmd/mdb/common/modules/md/metastat.c
index cf01c779f0..d3f27ec233 100644
--- a/usr/src/cmd/mdb/common/modules/md/metastat.c
+++ b/usr/src/cmd/mdb/common/modules/md/metastat.c
@@ -2,9 +2,8 @@
* 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.
+ * 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
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "mdinclude.h"
typedef struct submirror_cb {
@@ -117,16 +115,84 @@ print_submirror(uintptr_t addr, void *arg, submirror_cb_t *data)
return (WALK_NEXT);
}
+/*
+ * Construct an RLE count for the number of 'cleared' bits in the given 'bm'
+ * Output the RLE count in form: [<set>.<cleared>.<set>.<cleared>...]
+ * RLE is Run Length Encoding, a method for compactly describing a bitmap
+ * as a series of numbers indicating the count of consecutive set or cleared
+ * bits.
+ *
+ * Input:
+ * <bm> bitmap to scan
+ * <size> length of bitmap (in bits)
+ * <comp_bm> RLE count array to be updated
+ * <opstr> Descriptive text for bitmap RLE count display
+ */
+static void
+print_comp_bm(unsigned char *bm, uint_t size, ushort_t *comp_bm, char *opstr)
+{
+ int cnt_clean, tot_dirty, cur_idx;
+ int i, cur_clean, cur_dirty, printit, max_set_cnt, max_reset_cnt;
+
+ cnt_clean = 1;
+ printit = 0;
+ cur_clean = 0;
+ cur_dirty = 0;
+ cur_idx = 0;
+ tot_dirty = 0;
+ max_set_cnt = max_reset_cnt = 0;
+ for (i = 0; i < size; i++) {
+ if (isset(bm, i)) {
+ /* If we're counting clean bits, flush the count out */
+ if (cnt_clean) {
+ cnt_clean = 0;
+ comp_bm[cur_idx] = cur_clean;
+ printit = 1;
+ if (cur_clean > max_reset_cnt) {
+ max_reset_cnt = cur_clean;
+ }
+ }
+ cur_clean = 0;
+ cur_dirty++;
+ tot_dirty++;
+ } else {
+ if (!cnt_clean) {
+ cnt_clean = 1;
+ comp_bm[cur_idx] = cur_dirty;
+ printit = 1;
+ if (cur_dirty > max_set_cnt) {
+ max_set_cnt = cur_dirty;
+ }
+ }
+ cur_dirty = 0;
+ cur_clean++;
+ }
+ if (printit) {
+ mdb_printf("%u.", comp_bm[cur_idx++]);
+ printit = 0;
+ }
+ }
+
+ mdb_printf("\nTotal %s bits = %lu\n", opstr, tot_dirty);
+ mdb_printf("Total %s transactions = %lu\n", opstr, cur_idx);
+ mdb_printf("Maximum %s set count = %lu, reset count = %lu\n", opstr,
+ max_set_cnt, max_reset_cnt);
+}
+
void
print_mirror(void *un_addr, void *mdcptr, uint_t verbose)
{
- mm_unit_t mm;
+ mm_unit_t mm, *mmp;
void **ptr;
int setno = 0;
minor_t un_self_id;
diskaddr_t un_total_blocks;
ushort_t mm_un_nsm;
submirror_cb_t data;
+ uint_t num_rr, rr_blksize;
+ ushort_t *comp_rr;
+ unsigned char *rr_dirty_bm, *rr_goingclean_bm;
+ uintptr_t un_dbm, un_gcbm;
/* read in the device */
if (mdb_vread(&mm, sizeof (mm_unit_t),
@@ -134,6 +200,9 @@ print_mirror(void *un_addr, void *mdcptr, uint_t verbose)
mdb_warn("failed to read mm_unit_t at %p\n", un_addr);
return;
}
+
+ mmp = &mm;
+
un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id;
un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks;
mm_un_nsm = mm.un_nsm;
@@ -148,6 +217,39 @@ print_mirror(void *un_addr, void *mdcptr, uint_t verbose)
}
mdb_inc_indent(2);
mdb_printf("Size: %llu blocks\n", un_total_blocks);
+
+ /*
+ * Dump out the current un_dirty_bm together with its size
+ * Also, attempt to Run Length encode the bitmap to see if this
+ * is a viable option
+ */
+ num_rr = mm.un_rrd_num;
+ rr_blksize = mm.un_rrd_blksize;
+
+ un_dbm = (uintptr_t)mmp->un_dirty_bm;
+ un_gcbm = (uintptr_t)mmp->un_goingclean_bm;
+
+ mdb_printf("RR size: %lu bits\n", num_rr);
+ mdb_printf("RR block size: %lu blocks\n", rr_blksize);
+
+ rr_dirty_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC);
+ rr_goingclean_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC);
+ comp_rr = (ushort_t *)mdb_alloc(num_rr * sizeof (ushort_t),
+ UM_SLEEP|UM_GC);
+
+ if (mdb_vread(rr_dirty_bm, num_rr, un_dbm) == -1) {
+ mdb_warn("failed to read un_dirty_bm at %p\n", un_dbm);
+ return;
+ }
+ if (mdb_vread(rr_goingclean_bm, num_rr, un_gcbm) == -1) {
+ mdb_warn("failed to read un_goingclean_bm at %p\n", un_gcbm);
+ return;
+ }
+
+ print_comp_bm(rr_dirty_bm, num_rr, comp_rr, "dirty");
+
+ print_comp_bm(rr_goingclean_bm, num_rr, comp_rr, "clean");
+
/*
* find the sub mirrors, search through each metadevice looking
* at the un_parent.
diff --git a/usr/src/cmd/mdb/intel/amd64/md/Makefile b/usr/src/cmd/mdb/intel/amd64/md/Makefile
index db8020f91c..879bc72856 100644
--- a/usr/src/cmd/mdb/intel/amd64/md/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/md/Makefile
@@ -2,9 +2,8 @@
# 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.
+# 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
# or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
MODULE = md.so
MDBTGT = kvm
MODSRCS = dumphotspare.c \
+ dumpmirror.c \
dumpnamespace.c \
findset.c \
md.c \
diff --git a/usr/src/cmd/mdb/intel/ia32/md/Makefile b/usr/src/cmd/mdb/intel/ia32/md/Makefile
index 1ae436a304..8531855e44 100644
--- a/usr/src/cmd/mdb/intel/ia32/md/Makefile
+++ b/usr/src/cmd/mdb/intel/ia32/md/Makefile
@@ -2,9 +2,8 @@
# 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.
+# 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
# or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
MODULE = md.so
MDBTGT = kvm
MODSRCS = dumphotspare.c \
+ dumpmirror.c \
dumpnamespace.c \
findset.c \
md.c \
diff --git a/usr/src/cmd/mdb/sparc/v9/md/Makefile b/usr/src/cmd/mdb/sparc/v9/md/Makefile
index d88a16960a..d0ad7e3906 100644
--- a/usr/src/cmd/mdb/sparc/v9/md/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/md/Makefile
@@ -2,9 +2,8 @@
# 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.
+# 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
# or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#pragma ident "%Z%%M% %I% %E% SMI"
MODULE = md.so
MDBTGT = kvm
MODSRCS = dumphotspare.c \
+ dumpmirror.c \
dumpnamespace.c \
findset.c \
md.c \