diff options
Diffstat (limited to 'usr/src/cmd')
-rw-r--r-- | usr/src/cmd/lvm/rpc.mdcommd/mdcomm.xml | 8 | ||||
-rw-r--r-- | usr/src/cmd/lvm/rpc.mdcommd/mddoors.c | 63 | ||||
-rw-r--r-- | usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_server.c | 237 | ||||
-rw-r--r-- | usr/src/cmd/lvm/rpc.mdcommd/mdmn_commd_service.c | 100 | ||||
-rw-r--r-- | usr/src/cmd/lvm/rpc.mdcommd/mdmn_subr.c | 20 | ||||
-rw-r--r-- | usr/src/cmd/lvm/util/metaclust.c | 24 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/dumpmirror.c | 230 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/md.c | 12 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/metastat.c | 116 | ||||
-rw-r--r-- | usr/src/cmd/mdb/intel/amd64/md/Makefile | 9 | ||||
-rw-r--r-- | usr/src/cmd/mdb/intel/ia32/md/Makefile | 9 | ||||
-rw-r--r-- | usr/src/cmd/mdb/sparc/v9/md/Makefile | 9 |
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 \ |