xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c (revision 8452:89d32dfdae6e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51623Stw21770  * Common Development and Distribution License (the "License").
61623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*8452SJohn.Wren.Kennedy@Sun.COM 
220Sstevel@tonic-gate /*
237210Srayh  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <unistd.h>
290Sstevel@tonic-gate #include <wait.h>
300Sstevel@tonic-gate #include <sys/time.h>
310Sstevel@tonic-gate #include <syslog.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <meta.h>
340Sstevel@tonic-gate #include <sys/lvm/mdio.h>
350Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
360Sstevel@tonic-gate #include <sys/lvm/md_mirror.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #define	MAX_N_ARGS 64
390Sstevel@tonic-gate #define	MAX_ARG_LEN 1024
407210Srayh #define	MAX_SLEEPS 99
417210Srayh #define	SLEEP_MOD 5
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /* we reserve 1024 bytes for stdout and the same for stderr */
440Sstevel@tonic-gate #define	MAX_OUT	1024
450Sstevel@tonic-gate #define	MAX_ERR	1024
460Sstevel@tonic-gate #define	JUNK 128 /* used to flush stdout and stderr */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*ARGSUSED*/
500Sstevel@tonic-gate void
mdmn_do_cmd(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)510Sstevel@tonic-gate mdmn_do_cmd(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
520Sstevel@tonic-gate {
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/*
550Sstevel@tonic-gate 	 * We are given one string containing all the arguments
560Sstevel@tonic-gate 	 * For execvp() we have to regenerate the arguments again
570Sstevel@tonic-gate 	 */
580Sstevel@tonic-gate 	int	arg;		/* argument that is currently been built */
590Sstevel@tonic-gate 	int	index;		/* runs through arg above */
600Sstevel@tonic-gate 	int	i;		/* helper for for loop */
610Sstevel@tonic-gate 	char	*argv[MAX_N_ARGS]; /* argument array for execvp */
620Sstevel@tonic-gate 	char	*cp;		/* runs through the given command line string */
630Sstevel@tonic-gate 	char	*command = NULL; /* the command we call locally */
640Sstevel@tonic-gate 	int	pout[2];	/* pipe for stdout */
650Sstevel@tonic-gate 	int	perr[2];	/* pipe for stderr */
660Sstevel@tonic-gate 	pid_t	pid;		/* process id */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	cp	= msg->msg_event_data;
690Sstevel@tonic-gate 	arg	= 0;
700Sstevel@tonic-gate 	index	= 0;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	/* init the args array alloc the first one and null out the rest */
730Sstevel@tonic-gate 	argv[0] = Malloc(MAX_ARG_LEN);
740Sstevel@tonic-gate 	for (i = 1; i < MAX_N_ARGS; i++) {
750Sstevel@tonic-gate 		argv[i] = NULL;
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	resp->mmr_comm_state	= MDMNE_ACK; /* Ok state */;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	while (*cp != '\0') {
810Sstevel@tonic-gate 		if (arg == MAX_N_ARGS) {
820Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
830Sstevel@tonic-gate 			    "PANIC: too many arguments specified\n"));
840Sstevel@tonic-gate 			resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
850Sstevel@tonic-gate 			goto out;
860Sstevel@tonic-gate 		}
870Sstevel@tonic-gate 		if (index == MAX_ARG_LEN) {
880Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
890Sstevel@tonic-gate 			    "PANIC: argument too long\n"));
900Sstevel@tonic-gate 			resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
910Sstevel@tonic-gate 			goto out;
920Sstevel@tonic-gate 		}
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 		if ((*cp != ' ') && (*cp != '\t')) {
950Sstevel@tonic-gate 			/*
960Sstevel@tonic-gate 			 * No space or tab: copy char into current
970Sstevel@tonic-gate 			 * argv and advance both pointers
980Sstevel@tonic-gate 			 */
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 			argv[arg][index] = *cp;
1010Sstevel@tonic-gate 			cp++;	/* next char in command line	*/
1020Sstevel@tonic-gate 			index++;	/* next char in argument	*/
1030Sstevel@tonic-gate 		} else {
1040Sstevel@tonic-gate 			/*
1050Sstevel@tonic-gate 			 * space or tab: terminate current argv,
1060Sstevel@tonic-gate 			 * advance arg, reset pointer into arg,
1070Sstevel@tonic-gate 			 * advance pointer in command line
1080Sstevel@tonic-gate 			 */
1090Sstevel@tonic-gate 			argv[arg][index] = '\0';
1100Sstevel@tonic-gate 			arg++; /* next argument */
1110Sstevel@tonic-gate 			argv[arg] = Malloc(MAX_ARG_LEN);
1120Sstevel@tonic-gate 			cp++; /* next char in command line */
1130Sstevel@tonic-gate 			index = 0; /* starts at char 0 */
1140Sstevel@tonic-gate 		}
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 	/* terminate the last real argument */
1170Sstevel@tonic-gate 	argv[arg][index] = '\0';
1180Sstevel@tonic-gate 	/* the last argument is an NULL pointer */
1190Sstevel@tonic-gate 	argv[++arg] = NULL;
1200Sstevel@tonic-gate 	if (pipe(pout) < 0)  {
1210Sstevel@tonic-gate 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1220Sstevel@tonic-gate 		    "PANIC: pipe failed\n"));
1230Sstevel@tonic-gate 		resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
1240Sstevel@tonic-gate 		goto out;
1250Sstevel@tonic-gate 	}
1260Sstevel@tonic-gate 	if (pipe(perr) < 0) {
1270Sstevel@tonic-gate 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1280Sstevel@tonic-gate 		    "PANIC: pipe failed\n"));
1290Sstevel@tonic-gate 		(void) close(pout[0]);
1300Sstevel@tonic-gate 		(void) close(pout[1]);
1310Sstevel@tonic-gate 		resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
1320Sstevel@tonic-gate 		goto out;
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 	command = Strdup(argv[0]);
1350Sstevel@tonic-gate 	(void) strcat(argv[0], ".rpc_call");
1360Sstevel@tonic-gate 	pid = fork1();
1370Sstevel@tonic-gate 	if (pid == (pid_t)-1) {
1380Sstevel@tonic-gate 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1390Sstevel@tonic-gate 		    "PANIC: fork failed\n"));
1400Sstevel@tonic-gate 		resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
1410Sstevel@tonic-gate 		(void) close(pout[0]);
1420Sstevel@tonic-gate 		(void) close(pout[1]);
1430Sstevel@tonic-gate 		(void) close(perr[0]);
1440Sstevel@tonic-gate 		(void) close(perr[1]);
1450Sstevel@tonic-gate 		goto out;
1460Sstevel@tonic-gate 	} else  if (pid == (pid_t)0) {
1470Sstevel@tonic-gate 		/* child */
1480Sstevel@tonic-gate 		(void) close(0);
1490Sstevel@tonic-gate 		/* close the reading channels of pout and perr */
1500Sstevel@tonic-gate 		(void) close(pout[0]);
1510Sstevel@tonic-gate 		(void) close(perr[0]);
1520Sstevel@tonic-gate 		/* redirect stdout */
1530Sstevel@tonic-gate 		if (dup2(pout[1], 1) < 0) {
1540Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1550Sstevel@tonic-gate 			    "PANIC: dup2 failed\n"));
1560Sstevel@tonic-gate 			resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
1570Sstevel@tonic-gate 			return;
1580Sstevel@tonic-gate 		}
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 		/* redirect stderr */
1610Sstevel@tonic-gate 		if (dup2(perr[1], 2) < 0) {
1620Sstevel@tonic-gate 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1630Sstevel@tonic-gate 			    "PANIC: dup2 failed\n"));
1640Sstevel@tonic-gate 			resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
1650Sstevel@tonic-gate 			return;
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 		(void) execvp(command, (char *const *)argv);
1690Sstevel@tonic-gate 		perror("execvp");
1700Sstevel@tonic-gate 		_exit(1);
1710Sstevel@tonic-gate 	} else {
1720Sstevel@tonic-gate 		/* parent process */
1730Sstevel@tonic-gate 		int stat_loc;
1740Sstevel@tonic-gate 		char *out, *err; /* for stdout and stderr of child */
1750Sstevel@tonic-gate 		int i; /* index into the aboves */
1760Sstevel@tonic-gate 		char junk[JUNK];
1770Sstevel@tonic-gate 		int out_done = 0;
1780Sstevel@tonic-gate 		int err_done = 0;
1790Sstevel@tonic-gate 		int out_read = 0;
1800Sstevel@tonic-gate 		int err_read = 0;
1810Sstevel@tonic-gate 		int maxfd;
1820Sstevel@tonic-gate 		fd_set	rset;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 		/* close the writing channels of pout and perr */
1860Sstevel@tonic-gate 		(void) close(pout[1]);
1870Sstevel@tonic-gate 		(void) close(perr[1]);
1880Sstevel@tonic-gate 		resp->mmr_out = Malloc(MAX_OUT);
1890Sstevel@tonic-gate 		resp->mmr_err = Malloc(MAX_ERR);
1900Sstevel@tonic-gate 		resp->mmr_out_size = MAX_OUT;
1910Sstevel@tonic-gate 		resp->mmr_err_size = MAX_ERR;
1920Sstevel@tonic-gate 		out = resp->mmr_out;
1930Sstevel@tonic-gate 		err = resp->mmr_err;
1940Sstevel@tonic-gate 		FD_ZERO(&rset);
1950Sstevel@tonic-gate 		while ((out_done == 0) || (err_done == 0)) {
1960Sstevel@tonic-gate 			FD_SET(pout[0], &rset);
1970Sstevel@tonic-gate 			FD_SET(perr[0], &rset);
1980Sstevel@tonic-gate 			maxfd = max(pout[0], perr[0]) + 1;
1990Sstevel@tonic-gate 			(void) select(maxfd, &rset, NULL, NULL, NULL);
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 			/*
2020Sstevel@tonic-gate 			 * Did the child produce some output to stdout?
2030Sstevel@tonic-gate 			 * If so, read it until we either reach the end of the
2040Sstevel@tonic-gate 			 * output or until we read MAX_OUT bytes.
2050Sstevel@tonic-gate 			 * Whatever comes first.
2060Sstevel@tonic-gate 			 * In case we already read MAX_OUT bytes we simply
2070Sstevel@tonic-gate 			 * read away the output into a junk buffer.
2080Sstevel@tonic-gate 			 * Just to make the child happy
2090Sstevel@tonic-gate 			 */
2100Sstevel@tonic-gate 			if (FD_ISSET(pout[0], &rset)) {
2110Sstevel@tonic-gate 				if (MAX_OUT - out_read - 1 > 0) {
2120Sstevel@tonic-gate 					i = read(pout[0], out,
2137210Srayh 					    MAX_OUT - out_read);
2140Sstevel@tonic-gate 					out_read += i;
2150Sstevel@tonic-gate 					out += i;
2160Sstevel@tonic-gate 				} else {
2170Sstevel@tonic-gate 					/* buffer full, empty stdout */
2180Sstevel@tonic-gate 					i = read(pout[0], junk, JUNK);
2190Sstevel@tonic-gate 				}
2200Sstevel@tonic-gate 				if (i == 0) {
2210Sstevel@tonic-gate 					/* stdout is closed by child */
2220Sstevel@tonic-gate 					out_done++;
2230Sstevel@tonic-gate 				}
2240Sstevel@tonic-gate 			}
2250Sstevel@tonic-gate 			/* same comment as above | sed -e 's/stdout/stderr/' */
2260Sstevel@tonic-gate 			if (FD_ISSET(perr[0], &rset)) {
2270Sstevel@tonic-gate 				if (MAX_ERR - err_read - 1 > 0) {
2280Sstevel@tonic-gate 					i = read(perr[0], err,
2297210Srayh 					    MAX_ERR - err_read);
2300Sstevel@tonic-gate 					err_read += i;
2310Sstevel@tonic-gate 					err += i;
2320Sstevel@tonic-gate 				} else {
2330Sstevel@tonic-gate 					/* buffer full, empty stderr */
2340Sstevel@tonic-gate 					i = read(perr[0], junk, JUNK);
2350Sstevel@tonic-gate 				}
2360Sstevel@tonic-gate 				if (i == 0) {
2370Sstevel@tonic-gate 					/* stderr is closed by child */
2380Sstevel@tonic-gate 					err_done++;
2390Sstevel@tonic-gate 				}
2400Sstevel@tonic-gate 			}
2410Sstevel@tonic-gate 		}
2420Sstevel@tonic-gate 		resp->mmr_out[out_read] = '\0';
2430Sstevel@tonic-gate 		resp->mmr_err[err_read] = '\0';
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		while (waitpid(pid, &stat_loc, 0) < 0) {
2460Sstevel@tonic-gate 			if (errno != EINTR) {
2470Sstevel@tonic-gate 				resp->mmr_comm_state = MDMNE_HANDLER_FAILED;
2480Sstevel@tonic-gate 				break;
2490Sstevel@tonic-gate 			}
2500Sstevel@tonic-gate 		}
2510Sstevel@tonic-gate 		if (errno == 0)
2520Sstevel@tonic-gate 			resp->mmr_exitval = WEXITSTATUS(stat_loc);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 		(void) close(pout[0]);
2550Sstevel@tonic-gate 		(void) close(perr[0]);
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate out:
2580Sstevel@tonic-gate 	for (i = 0; i < MAX_N_ARGS; i++) {
2590Sstevel@tonic-gate 		if (argv[i] != NULL) {
2600Sstevel@tonic-gate 			free(argv[i]);
2610Sstevel@tonic-gate 		}
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 	if (command != NULL) {
2640Sstevel@tonic-gate 		Free(command);
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate /*
2690Sstevel@tonic-gate  * This is for checking if a metadevice is opened, and for
2700Sstevel@tonic-gate  * locking in case it is not and for
2710Sstevel@tonic-gate  * unlocking a locked device
2720Sstevel@tonic-gate  */
2730Sstevel@tonic-gate /*ARGSUSED*/
2740Sstevel@tonic-gate void
mdmn_do_clu(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)2750Sstevel@tonic-gate mdmn_do_clu(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate 	if (msg->msg_type == MD_MN_MSG_CLU_CHECK) {
2780Sstevel@tonic-gate 		md_isopen_t	*d;
2790Sstevel@tonic-gate 		int		ret;
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
2820Sstevel@tonic-gate 		resp->mmr_out_size = 0;
2830Sstevel@tonic-gate 		resp->mmr_err_size = 0;
2840Sstevel@tonic-gate 		resp->mmr_out = NULL;
2850Sstevel@tonic-gate 		resp->mmr_err = NULL;
2860Sstevel@tonic-gate 		d = (md_isopen_t *)(void *)msg->msg_event_data;
2870Sstevel@tonic-gate 		ret = metaioctl(MD_IOCISOPEN, d, &(d->mde), NULL);
2880Sstevel@tonic-gate 		/*
2890Sstevel@tonic-gate 		 * In case the ioctl succeeded, return the open state of
2900Sstevel@tonic-gate 		 * the metadevice. Otherwise we return the error the ioctl
2910Sstevel@tonic-gate 		 * produced. As this is not zero, no attempt is made to
2920Sstevel@tonic-gate 		 * remove/rename the metadevice later
2930Sstevel@tonic-gate 		 */
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		if (ret == 0) {
2960Sstevel@tonic-gate 			resp->mmr_exitval = d->isopen;
2970Sstevel@tonic-gate 		} else {
2980Sstevel@tonic-gate 			/*
2990Sstevel@tonic-gate 			 * When doing a metaclear, one node after the other
3000Sstevel@tonic-gate 			 * does the two steps:
3010Sstevel@tonic-gate 			 * - check on all nodes if this md is opened.
3020Sstevel@tonic-gate 			 * - remove the md locally.
3030Sstevel@tonic-gate 			 * When the 2nd node asks all nodes if the md is
3040Sstevel@tonic-gate 			 * open it starts with the first node.
3050Sstevel@tonic-gate 			 * As this already removed the md, the check
3060Sstevel@tonic-gate 			 * returns MDE_UNIT_NOT_SETUP.
3070Sstevel@tonic-gate 			 * In order to not keep the 2nd node from proceeding,
3080Sstevel@tonic-gate 			 * we map this to an Ok.
3090Sstevel@tonic-gate 			 */
3100Sstevel@tonic-gate 			if (mdismderror(&(d->mde), MDE_UNIT_NOT_SETUP)) {
3110Sstevel@tonic-gate 				mdclrerror(&(d->mde));
3120Sstevel@tonic-gate 				ret = 0;
3130Sstevel@tonic-gate 			}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 			resp->mmr_exitval = ret;
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /* handler for MD_MN_MSG_REQUIRE_OWNER */
3210Sstevel@tonic-gate /*ARGSUSED*/
3220Sstevel@tonic-gate void
mdmn_do_req_owner(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)3230Sstevel@tonic-gate mdmn_do_req_owner(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	md_set_mmown_params_t	setown;
3260Sstevel@tonic-gate 	md_mn_req_owner_t	*d;
3270Sstevel@tonic-gate 	int			ret, n = 0;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	resp->mmr_out_size = 0;
3300Sstevel@tonic-gate 	resp->mmr_err_size = 0;
3310Sstevel@tonic-gate 	resp->mmr_out = NULL;
3320Sstevel@tonic-gate 	resp->mmr_err = NULL;
3330Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
3340Sstevel@tonic-gate 	d = (md_mn_req_owner_t *)(void *)msg->msg_event_data;
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	(void) memset(&setown, 0, sizeof (setown));
3370Sstevel@tonic-gate 	MD_SETDRIVERNAME(&setown, MD_MIRROR, MD_MIN2SET(d->mnum))
3380Sstevel@tonic-gate 	setown.d.mnum = d->mnum;
3390Sstevel@tonic-gate 	setown.d.owner = d->owner;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	/* Retry ownership change if we get EAGAIN returned */
3420Sstevel@tonic-gate 	while ((ret = metaioctl(MD_MN_SET_MM_OWNER, &setown, &setown.mde, NULL))
3430Sstevel@tonic-gate 	    != 0) {
3440Sstevel@tonic-gate 		md_sys_error_t	*ip =
3450Sstevel@tonic-gate 		    &setown.mde.info.md_error_info_t_u.sys_error;
3460Sstevel@tonic-gate 		if (ip->errnum != EAGAIN) {
3470Sstevel@tonic-gate 			break;
3480Sstevel@tonic-gate 		}
3490Sstevel@tonic-gate 		if (n++ >= 10) {
3500Sstevel@tonic-gate 			break;
3510Sstevel@tonic-gate 		}
3520Sstevel@tonic-gate 		(void) sleep(1);
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	resp->mmr_exitval = ret;
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate /*
3590Sstevel@tonic-gate  * handler for MD_MN_MSG_CHOOSE_OWNER
3600Sstevel@tonic-gate  * This is called when a mirror resync has no owner. The master node generates
3610Sstevel@tonic-gate  * this message which is not broadcast to the other nodes. The message is
3620Sstevel@tonic-gate  * required as the kernel does not have access to the nodelist for the set.
3630Sstevel@tonic-gate  */
3640Sstevel@tonic-gate /*ARGSUSED*/
3650Sstevel@tonic-gate void
mdmn_do_choose_owner(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)3660Sstevel@tonic-gate mdmn_do_choose_owner(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate 	md_mn_msg_chowner_t	chownermsg;
3690Sstevel@tonic-gate 	md_mn_msg_chooseid_t	*d;
3700Sstevel@tonic-gate 	int			ret = 0;
3710Sstevel@tonic-gate 	int			nodecnt;
3720Sstevel@tonic-gate 	int			nodeno;
3730Sstevel@tonic-gate 	uint_t			nodeid;
3740Sstevel@tonic-gate 	uint_t			myflags;
3750Sstevel@tonic-gate 	set_t			setno;
3760Sstevel@tonic-gate 	mdsetname_t		*sp;
3770Sstevel@tonic-gate 	md_set_desc		*sd;
3780Sstevel@tonic-gate 	md_mnnode_desc		*nd;
3790Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
3800Sstevel@tonic-gate 	md_mn_result_t		*resp1 = NULL;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	resp->mmr_out_size = 0;
3830Sstevel@tonic-gate 	resp->mmr_err_size = 0;
3840Sstevel@tonic-gate 	resp->mmr_out = NULL;
3850Sstevel@tonic-gate 	resp->mmr_err = NULL;
3860Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
3870Sstevel@tonic-gate 	d = (md_mn_msg_chooseid_t *)(void *)msg->msg_event_data;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	/*
3900Sstevel@tonic-gate 	 * The node to be chosen will be the resync count for the set
3910Sstevel@tonic-gate 	 * modulo the number of live nodes in the set
3920Sstevel@tonic-gate 	 */
3930Sstevel@tonic-gate 	setno = MD_MIN2SET(d->msg_chooseid_mnum);
3940Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
3950Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
3960Sstevel@tonic-gate 		    "MD_MN_MSG_CHOOSE_OWNER: Invalid setno %d\n"), setno);
3970Sstevel@tonic-gate 		resp->mmr_exitval = 1;
3980Sstevel@tonic-gate 		return;
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 	if ((sd = metaget_setdesc(sp, &mde)) == NULL) {
4010Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
4020Sstevel@tonic-gate 		    "MD_MN_MSG_CHOOSE_OWNER: Invalid set pointer\n"));
4030Sstevel@tonic-gate 		resp->mmr_exitval = 1;
4040Sstevel@tonic-gate 		return;
4050Sstevel@tonic-gate 	}
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	/* Count the number of live nodes */
4080Sstevel@tonic-gate 	nodecnt = 0;
4090Sstevel@tonic-gate 	nd = sd->sd_nodelist;
4100Sstevel@tonic-gate 	while (nd) {
4110Sstevel@tonic-gate 		if (nd->nd_flags & MD_MN_NODE_ALIVE)
4120Sstevel@tonic-gate 			nodecnt++;
4130Sstevel@tonic-gate 		nd = nd->nd_next;
4140Sstevel@tonic-gate 	}
4150Sstevel@tonic-gate 	nodeno = (d->msg_chooseid_rcnt%nodecnt);
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	/*
4180Sstevel@tonic-gate 	 * If we've been called with msg_chooseid_set_node set TRUE then we
4190Sstevel@tonic-gate 	 * are simply re-setting the owner id to ensure consistency across
4200Sstevel@tonic-gate 	 * the cluster.
4210Sstevel@tonic-gate 	 * If the flag is reset (B_FALSE) we are requesting a new owner to be
4220Sstevel@tonic-gate 	 * determined.
4230Sstevel@tonic-gate 	 */
4240Sstevel@tonic-gate 	if (d->msg_chooseid_set_node) {
4250Sstevel@tonic-gate 		nodeid = d->msg_chooseid_rcnt;
4260Sstevel@tonic-gate 	} else {
4270Sstevel@tonic-gate 		/* scan the nodelist looking for the required node */
4280Sstevel@tonic-gate 		nodecnt = 0;
4290Sstevel@tonic-gate 		nd = sd->sd_nodelist;
4300Sstevel@tonic-gate 		while (nd) {
4310Sstevel@tonic-gate 			if (nd->nd_flags & MD_MN_NODE_ALIVE) {
4320Sstevel@tonic-gate 				if (nodecnt == nodeno)
4330Sstevel@tonic-gate 					break;
4340Sstevel@tonic-gate 				nodecnt++;
4350Sstevel@tonic-gate 			}
4360Sstevel@tonic-gate 			nd = nd->nd_next;
4370Sstevel@tonic-gate 		}
4380Sstevel@tonic-gate 		nodeid = nd->nd_nodeid;
4390Sstevel@tonic-gate 	}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	/* Send message to all nodes to make ownership change */
4420Sstevel@tonic-gate 	chownermsg.msg_chowner_mnum =  d->msg_chooseid_mnum;
4430Sstevel@tonic-gate 	chownermsg.msg_chowner_nodeid = nodeid;
4440Sstevel@tonic-gate 	myflags = MD_MSGF_NO_LOG;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	/* inherit some flags from the parent message */
4470Sstevel@tonic-gate 	myflags |= msg->msg_flags & MD_MSGF_INHERIT_BITS;
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	ret = mdmn_send_message(MD_MIN2SET(d->msg_chooseid_mnum),
450*8452SJohn.Wren.Kennedy@Sun.COM 	    MD_MN_MSG_CHANGE_OWNER, myflags, 0, (char *)&chownermsg,
4510Sstevel@tonic-gate 	    sizeof (chownermsg), &resp1, &mde);
4520Sstevel@tonic-gate 	if (resp1 != NULL)
4530Sstevel@tonic-gate 		free_result(resp1);
4540Sstevel@tonic-gate 	resp->mmr_exitval = ret;
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate  * Handler for MD_MN_MSG_CHANGE_OWNER
4590Sstevel@tonic-gate  * This is called when we are perfoming a resync and wish to change from
4600Sstevel@tonic-gate  * no mirror owner to an owner chosen by the master.
4610Sstevel@tonic-gate  * This mesage is only relevant for the new owner, the message will be
4620Sstevel@tonic-gate  * ignored by all other nodes
4630Sstevel@tonic-gate  */
4640Sstevel@tonic-gate /*ARGSUSED*/
4650Sstevel@tonic-gate void
mdmn_do_change_owner(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)4660Sstevel@tonic-gate mdmn_do_change_owner(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	md_set_mmown_params_t	setown;
4690Sstevel@tonic-gate 	md_mn_msg_chowner_t	*d;
4700Sstevel@tonic-gate 	int			ret = 0;
4710Sstevel@tonic-gate 	set_t			setno;
4720Sstevel@tonic-gate 	mdsetname_t		*sp;
4730Sstevel@tonic-gate 	md_set_desc		*sd;
4740Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	resp->mmr_out_size = 0;
4770Sstevel@tonic-gate 	resp->mmr_err_size = 0;
4780Sstevel@tonic-gate 	resp->mmr_out = NULL;
4790Sstevel@tonic-gate 	resp->mmr_err = NULL;
4800Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
4810Sstevel@tonic-gate 	d = (md_mn_msg_chowner_t *)(void *)msg->msg_event_data;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	setno = MD_MIN2SET(d->msg_chowner_mnum);
4840Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
4850Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
4860Sstevel@tonic-gate 		    "MD_MN_MSG_CHANGE_OWNER: Invalid setno %d\n"), setno);
4870Sstevel@tonic-gate 		resp->mmr_exitval = 1;
4880Sstevel@tonic-gate 		return;
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 	if ((sd = metaget_setdesc(sp, &mde)) == NULL) {
4910Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
4920Sstevel@tonic-gate 		    "MD_MN_MSG_CHANGE_OWNER: Invalid set pointer\n"));
4930Sstevel@tonic-gate 		resp->mmr_exitval = 1;
4940Sstevel@tonic-gate 		return;
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	if (d->msg_chowner_nodeid == sd->sd_mn_mynode->nd_nodeid) {
4980Sstevel@tonic-gate 		/*
4990Sstevel@tonic-gate 		 * If we are the chosen owner, issue ioctl to make the
5000Sstevel@tonic-gate 		 * ownership change
5010Sstevel@tonic-gate 		 */
5020Sstevel@tonic-gate 		(void) memset(&setown, 0, sizeof (md_set_mmown_params_t));
5030Sstevel@tonic-gate 		setown.d.mnum = d->msg_chowner_mnum;
5040Sstevel@tonic-gate 		setown.d.owner = d->msg_chowner_nodeid;
5050Sstevel@tonic-gate 		setown.d.flags = MD_MN_MM_SPAWN_THREAD;
5060Sstevel@tonic-gate 		MD_SETDRIVERNAME(&setown, MD_MIRROR,
5070Sstevel@tonic-gate 		    MD_MIN2SET(d->msg_chowner_mnum));
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		/*
5100Sstevel@tonic-gate 		 * Single shot at changing the the owner, if it fails EAGAIN,
5110Sstevel@tonic-gate 		 * another node must have become the owner while we are in the
5120Sstevel@tonic-gate 		 * process of making this choice.
5130Sstevel@tonic-gate 		 */
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 		ret = metaioctl(MD_MN_SET_MM_OWNER, &setown,
5160Sstevel@tonic-gate 		    &(setown.mde), NULL);
5170Sstevel@tonic-gate 		if (ret == EAGAIN)
5180Sstevel@tonic-gate 			ret = 0;
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 	resp->mmr_exitval = ret;
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate /* handler for MD_MN_MSG_SUSPEND_WRITES */
5240Sstevel@tonic-gate /*ARGSUSED*/
5250Sstevel@tonic-gate void
mdmn_do_susp_write(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)5260Sstevel@tonic-gate mdmn_do_susp_write(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 	/* Suspend writes to a region of a mirror */
5290Sstevel@tonic-gate 	md_suspend_wr_params_t	suspwr_ioc;
5300Sstevel@tonic-gate 	md_mn_msg_suspwr_t	*d;
5310Sstevel@tonic-gate 	int			ret;
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	resp->mmr_out_size = 0;
5340Sstevel@tonic-gate 	resp->mmr_err_size = 0;
5350Sstevel@tonic-gate 	resp->mmr_out = NULL;
5360Sstevel@tonic-gate 	resp->mmr_err = NULL;
5370Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
5380Sstevel@tonic-gate 	d = (md_mn_msg_suspwr_t *)(void *)msg->msg_event_data;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	(void) memset(&suspwr_ioc, 0, sizeof (md_suspend_wr_params_t));
5410Sstevel@tonic-gate 	MD_SETDRIVERNAME(&suspwr_ioc, MD_MIRROR,
5420Sstevel@tonic-gate 	    MD_MIN2SET(d->msg_suspwr_mnum));
5430Sstevel@tonic-gate 	suspwr_ioc.mnum = d->msg_suspwr_mnum;
5440Sstevel@tonic-gate 	ret = metaioctl(MD_MN_SUSPEND_WRITES, &suspwr_ioc,
5450Sstevel@tonic-gate 	    &(suspwr_ioc.mde), NULL);
5460Sstevel@tonic-gate 	resp->mmr_exitval = ret;
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate /*
5500Sstevel@tonic-gate  * handler for MD_MN_MSG_STATE_UPDATE_RESWR
5510Sstevel@tonic-gate  * This functions update a submirror component state and then resumes writes
5520Sstevel@tonic-gate  * to the mirror
5530Sstevel@tonic-gate  */
5540Sstevel@tonic-gate /*ARGSUSED*/
5550Sstevel@tonic-gate void
mdmn_do_state_upd_reswr(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)5560Sstevel@tonic-gate mdmn_do_state_upd_reswr(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate 	/* Update the state of the component of a mirror */
5590Sstevel@tonic-gate 	md_set_state_params_t	setstate_ioc;
5600Sstevel@tonic-gate 	md_mn_msg_stch_t	*d;
5610Sstevel@tonic-gate 	int			ret;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	resp->mmr_out_size = 0;
5640Sstevel@tonic-gate 	resp->mmr_err_size = 0;
5650Sstevel@tonic-gate 	resp->mmr_out = NULL;
5660Sstevel@tonic-gate 	resp->mmr_err = NULL;
5670Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
5680Sstevel@tonic-gate 	d = (md_mn_msg_stch_t *)(void *)msg->msg_event_data;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	(void) memset(&setstate_ioc, 0, sizeof (md_set_state_params_t));
5710Sstevel@tonic-gate 	MD_SETDRIVERNAME(&setstate_ioc, MD_MIRROR,
5720Sstevel@tonic-gate 	    MD_MIN2SET(d->msg_stch_mnum));
5730Sstevel@tonic-gate 	setstate_ioc.mnum = d->msg_stch_mnum;
5740Sstevel@tonic-gate 	setstate_ioc.sm = d->msg_stch_sm;
5750Sstevel@tonic-gate 	setstate_ioc.comp = d->msg_stch_comp;
5760Sstevel@tonic-gate 	setstate_ioc.state = d->msg_stch_new_state;
5770Sstevel@tonic-gate 	setstate_ioc.hs_id = d->msg_stch_hs_id;
5780Sstevel@tonic-gate 	ret = metaioctl(MD_MN_SET_STATE, &setstate_ioc,
5790Sstevel@tonic-gate 	    &(setstate_ioc.mde), NULL);
5800Sstevel@tonic-gate 	resp->mmr_exitval = ret;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate /*
5840Sstevel@tonic-gate  * submessage generator for MD_MN_MSG_STATE_UPDATE and MD_MN_MSG_STATE_UPDATE2
5850Sstevel@tonic-gate  * This generates 2 messages, the first is SUSPEND_WRITES and
5860Sstevel@tonic-gate  * depending on the type of the original message the second one is
5870Sstevel@tonic-gate  * either STATE_UPDATE_RESWR or STATE_UPDATE_RESWR2 which actually does
5880Sstevel@tonic-gate  * the same, but runs on a higher class.
5890Sstevel@tonic-gate  */
5900Sstevel@tonic-gate int
mdmn_smgen_state_upd(md_mn_msg_t * msg,md_mn_msg_t * msglist[])5910Sstevel@tonic-gate mdmn_smgen_state_upd(md_mn_msg_t *msg, md_mn_msg_t *msglist[])
5920Sstevel@tonic-gate {
5930Sstevel@tonic-gate 	md_mn_msg_t		*nmsg;
5940Sstevel@tonic-gate 	md_mn_msg_stch_t	*d;
5950Sstevel@tonic-gate 	md_mn_msg_stch_t	*stch_data;
5960Sstevel@tonic-gate 	md_mn_msg_suspwr_t	*suspwr_data;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	d = (md_mn_msg_stch_t *)(void *)msg->msg_event_data;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
6010Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
6040Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
6050Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_SUSPEND_WRITES;
6060Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_suspwr_t);
6070Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_suspwr_t));
6080Sstevel@tonic-gate 	suspwr_data = (md_mn_msg_suspwr_t *)(void *)nmsg->msg_event_data;
6090Sstevel@tonic-gate 	suspwr_data->msg_suspwr_mnum = d->msg_stch_mnum;
6100Sstevel@tonic-gate 	msglist[0] = nmsg;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
6130Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
6160Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
6170Sstevel@tonic-gate 	if (msg->msg_type == MD_MN_MSG_STATE_UPDATE2) {
6180Sstevel@tonic-gate 		nmsg->msg_type		= MD_MN_MSG_STATE_UPDATE_RESWR2;
6190Sstevel@tonic-gate 	} else {
6200Sstevel@tonic-gate 		nmsg->msg_type		= MD_MN_MSG_STATE_UPDATE_RESWR;
6210Sstevel@tonic-gate 	}
6220Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_stch_t);
6230Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_stch_t));
6240Sstevel@tonic-gate 	stch_data = (md_mn_msg_stch_t *)(void *)nmsg->msg_event_data;
6250Sstevel@tonic-gate 	stch_data->msg_stch_mnum = d->msg_stch_mnum;
6260Sstevel@tonic-gate 	stch_data->msg_stch_sm = d->msg_stch_sm;
6270Sstevel@tonic-gate 	stch_data->msg_stch_comp = d->msg_stch_comp;
6280Sstevel@tonic-gate 	stch_data->msg_stch_new_state = d->msg_stch_new_state;
6290Sstevel@tonic-gate 	stch_data->msg_stch_hs_id = d->msg_stch_hs_id;
6300Sstevel@tonic-gate 	msglist[1] = nmsg;
6310Sstevel@tonic-gate 	return (2); /* Return the number of submessages generated */
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate /*
6350Sstevel@tonic-gate  * handler for MD_MN_MSG_ALLOCATE_HOTSPARE and MD_MN_MSG_ALLOCATE_HOTSPARE2
6360Sstevel@tonic-gate  * This sends a message to all nodes requesting them to allocate a hotspare
6370Sstevel@tonic-gate  * for the specified component. The component is specified by the mnum of
6380Sstevel@tonic-gate  * the mirror, the submirror index and the component index.
6390Sstevel@tonic-gate  */
6400Sstevel@tonic-gate /*ARGSUSED*/
6410Sstevel@tonic-gate void
mdmn_do_allocate_hotspare(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)6420Sstevel@tonic-gate mdmn_do_allocate_hotspare(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
6430Sstevel@tonic-gate {
6440Sstevel@tonic-gate 	/* Allocate a hotspare for a mirror component */
6450Sstevel@tonic-gate 	md_alloc_hotsp_params_t allochsp_ioc;
6460Sstevel@tonic-gate 	md_mn_msg_allochsp_t    *d;
6470Sstevel@tonic-gate 	int			ret;
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	resp->mmr_out_size = 0;
6500Sstevel@tonic-gate 	resp->mmr_err_size = 0;
6510Sstevel@tonic-gate 	resp->mmr_out = NULL;
6520Sstevel@tonic-gate 	resp->mmr_err = NULL;
6530Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
6540Sstevel@tonic-gate 	d = (md_mn_msg_allochsp_t *)((void *)(msg->msg_event_data));
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	(void) memset(&allochsp_ioc, 0,
6577210Srayh 	    sizeof (md_alloc_hotsp_params_t));
6580Sstevel@tonic-gate 	MD_SETDRIVERNAME(&allochsp_ioc, MD_MIRROR,
6590Sstevel@tonic-gate 	    MD_MIN2SET(d->msg_allochsp_mnum));
6600Sstevel@tonic-gate 	allochsp_ioc.mnum = d->msg_allochsp_mnum;
6610Sstevel@tonic-gate 	allochsp_ioc.sm = d->msg_allochsp_sm;
6620Sstevel@tonic-gate 	allochsp_ioc.comp = d->msg_allochsp_comp;
6630Sstevel@tonic-gate 	allochsp_ioc.hs_id = d->msg_allochsp_hs_id;
6640Sstevel@tonic-gate 	ret = metaioctl(MD_MN_ALLOCATE_HOTSPARE, &allochsp_ioc,
6650Sstevel@tonic-gate 	    &(allochsp_ioc.mde), NULL);
6660Sstevel@tonic-gate 	resp->mmr_exitval = ret;
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate  * handler for MD_MN_MSG_RESYNC_STARTING,MD_MN_MSG_RESYNC_FIRST,
6710Sstevel@tonic-gate  * MD_MN_MSG_RESYNC_NEXT, MD_MN_MSG_RESYNC_FINISH, MD_MN_MSG_RESYNC_PHASE_DONE
6720Sstevel@tonic-gate  */
6730Sstevel@tonic-gate /*ARGSUSED*/
6740Sstevel@tonic-gate void
mdmn_do_resync(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)6750Sstevel@tonic-gate mdmn_do_resync(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
6760Sstevel@tonic-gate {
6777210Srayh 	md_mn_msg_resync_t		*d;
6787210Srayh 	md_mn_rs_params_t		respar;
6797210Srayh 	mddb_setflags_config_t	sf;
6807210Srayh 	md_error_t				ep = mdnullerror;
6817210Srayh 	mdsetname_t				*sp;
6827210Srayh 	int	ret;
6837210Srayh 	int	smi;
6847210Srayh 	int start_flag = 1;
6857210Srayh 	int sleep_count = 0;
6867210Srayh 	unsigned int sleep_time = 2;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	resp->mmr_out_size = 0;
6890Sstevel@tonic-gate 	resp->mmr_err_size = 0;
6900Sstevel@tonic-gate 	resp->mmr_out = NULL;
6910Sstevel@tonic-gate 	resp->mmr_err = NULL;
6920Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
6930Sstevel@tonic-gate 	d = (md_mn_msg_resync_t *)((void *)(msg->msg_event_data));
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	(void) memset(&respar, 0, sizeof (respar));
6960Sstevel@tonic-gate 	MD_SETDRIVERNAME(&respar, MD_MIRROR,
6970Sstevel@tonic-gate 	    MD_MIN2SET(d->msg_resync_mnum))
6980Sstevel@tonic-gate 	respar.msg_type = (int)msg->msg_type;
6990Sstevel@tonic-gate 	respar.mnum = d->msg_resync_mnum;
7000Sstevel@tonic-gate 	respar.rs_type = d->msg_resync_type;
7010Sstevel@tonic-gate 	respar.rs_start = d->msg_resync_start;
7020Sstevel@tonic-gate 	respar.rs_size = d->msg_resync_rsize;
7030Sstevel@tonic-gate 	respar.rs_done = d->msg_resync_done;
7040Sstevel@tonic-gate 	respar.rs_2_do = d->msg_resync_2_do;
7050Sstevel@tonic-gate 	respar.rs_originator = d->msg_originator;
7060Sstevel@tonic-gate 	respar.rs_flags = d->msg_resync_flags;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	for (smi = 0; smi < NMIRROR; smi++) {
7090Sstevel@tonic-gate 		respar.rs_sm_state[smi] = d->msg_sm_state[smi];
7100Sstevel@tonic-gate 		respar.rs_sm_flags[smi] = d->msg_sm_flags[smi];
7110Sstevel@tonic-gate 	}
7120Sstevel@tonic-gate 
7137210Srayh 	/*
7147210Srayh 	 * Prior to running the resync thread first check that the start_step
7157210Srayh 	 * flag (MD_SET_MN_START_RC) added by metaclust's MC_START step has been
7167210Srayh 	 * removed from the set record flags. Ordinarily, this would be removed
7177210Srayh 	 * at MC_STEP4 in metaclust - need to ensure this has happened on all
7187210Srayh 	 * nodes.
7197210Srayh 	 */
7207210Srayh 	(void) memset(&sf, 0, sizeof (sf));
7217210Srayh 	sf.sf_setno = MD_MIN2SET(d->msg_resync_mnum);
7227210Srayh 	sf.sf_flags = MDDB_NM_GET;
7237210Srayh 	/* Use magic to help protect ioctl against attack. */
7247210Srayh 	sf.sf_magic = MDDB_SETFLAGS_MAGIC;
7257210Srayh 	if ((sp = metasetnosetname(sf.sf_setno, &ep)) == NULL) {
7267210Srayh 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
7277210Srayh 		    "MDMN_DO_RESYNC: Invalid setno = %d\n"),
7287210Srayh 		    sf.sf_setno);
7297210Srayh 		(void) mdstealerror(&(resp->mmr_ep), &ep);
7307210Srayh 		resp->mmr_exitval = -1;
7317210Srayh 		return;
7327210Srayh 	}
7337210Srayh 
7347210Srayh 	/* start_flag always true initially */
7357210Srayh 	while (start_flag) {
7367210Srayh 		if (metaioctl(MD_MN_GET_SETFLAGS, &sf, &sf.sf_mde, NULL) != 0) {
7377210Srayh 			syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
7387210Srayh 			    "MDMN_DO_RESYNC: Could not get start_step "
7397210Srayh 			    "flag for set %s - returning\n"),
7407210Srayh 			    sp->setname);
7417210Srayh 			(void) mdstealerror(&(resp->mmr_ep), &sf.sf_mde);
7427210Srayh 			resp->mmr_exitval = -1;
7437210Srayh 			return;
7447210Srayh 		}
7457210Srayh 
7467210Srayh 		/* metaioctl returns successfully - is start flag cleared? */
7477210Srayh 		if (sf.sf_setflags & MD_SET_MN_START_RC) {
7487210Srayh 			start_flag = 1;
7497210Srayh 			(void) sleep(sleep_time);
7507210Srayh 			sleep_count++;
7517210Srayh 			if ((sleep_count == 1) ||
7527210Srayh 			    (sleep_count % SLEEP_MOD) == 0) {
7537210Srayh 				syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
7547210Srayh 				    "MDMN_DO_RESYNC: Waiting for start_step "
7557210Srayh 				    "flag for set %s to be cleared\n"),
7567210Srayh 				    sp->setname);
7577210Srayh 			}
7587210Srayh 			if (sleep_count == MAX_SLEEPS) {
7597210Srayh 				syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
7607210Srayh 				    "MDMN_DO_RESYNC: Could not clear "
7617210Srayh 				    "start_step flag for set %s "
7627210Srayh 				    "- returning\n"), sp->setname);
7637210Srayh 				resp->mmr_exitval = -1;
7647210Srayh 				return;
7657210Srayh 			}
7667210Srayh 		} else {
7677210Srayh 			start_flag = 0;
7687210Srayh 		}
7697210Srayh 	}
7707210Srayh 
7710Sstevel@tonic-gate 	ret = metaioctl(MD_MN_RESYNC, &respar, &respar.mde, NULL);
7727210Srayh 	if (ret) {
7737210Srayh 		(void) mdstealerror(&(resp->mmr_ep), &respar.mde);
7747210Srayh 	}
7750Sstevel@tonic-gate 	resp->mmr_exitval = ret;
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate /*
7790Sstevel@tonic-gate  * handler for MD_MN_MSG_SETSYNC
7800Sstevel@tonic-gate  */
7810Sstevel@tonic-gate /*ARGSUSED*/
7820Sstevel@tonic-gate void
mdmn_do_setsync(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)7830Sstevel@tonic-gate mdmn_do_setsync(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
7840Sstevel@tonic-gate {
7850Sstevel@tonic-gate 	md_mn_msg_setsync_t	*d;
7860Sstevel@tonic-gate 	md_resync_ioctl_t	ri;
7870Sstevel@tonic-gate 	int			ret;
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	resp->mmr_out_size = 0;
7900Sstevel@tonic-gate 	resp->mmr_err_size = 0;
7910Sstevel@tonic-gate 	resp->mmr_out = NULL;
7920Sstevel@tonic-gate 	resp->mmr_err = NULL;
7930Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
7940Sstevel@tonic-gate 	d = (md_mn_msg_setsync_t *)((void *)(msg->msg_event_data));
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	(void) memset(&ri, 0, sizeof (ri));
7970Sstevel@tonic-gate 	MD_SETDRIVERNAME(&ri, MD_MIRROR, MD_MIN2SET(d->setsync_mnum))
7980Sstevel@tonic-gate 	ri.ri_mnum = d->setsync_mnum;
7990Sstevel@tonic-gate 	ri.ri_copysize = d->setsync_copysize;
8000Sstevel@tonic-gate 	ri.ri_flags = d->setsync_flags;
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	ret = metaioctl(MD_MN_SETSYNC, &ri, &ri.mde, NULL);
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	resp->mmr_exitval = ret;
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate /*
8080Sstevel@tonic-gate  * handler for MD_MN_MSG_SET_CAP. As this handler can deal with both mirrors
8090Sstevel@tonic-gate  * and soft partitions, the driver name that is required for the ioctl call
8100Sstevel@tonic-gate  * is included in the message.
8110Sstevel@tonic-gate  */
8120Sstevel@tonic-gate /*ARGSUSED*/
8130Sstevel@tonic-gate void
mdmn_do_set_cap(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)8140Sstevel@tonic-gate mdmn_do_set_cap(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate 	md_mn_msg_setcap_t	*d;
8170Sstevel@tonic-gate 	md_mn_setcap_params_t	setcap_ioc;
8180Sstevel@tonic-gate 	minor_t			mnum;
8190Sstevel@tonic-gate 	int			ret;
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	resp->mmr_out_size = 0;
8220Sstevel@tonic-gate 	resp->mmr_err_size = 0;
8230Sstevel@tonic-gate 	resp->mmr_out = NULL;
8240Sstevel@tonic-gate 	resp->mmr_err = NULL;
8250Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
8260Sstevel@tonic-gate 	d = (md_mn_msg_setcap_t *)((void *)(msg->msg_event_data));
8270Sstevel@tonic-gate 	mnum = d->msg_setcap_mnum;
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	(void) memset(&setcap_ioc, 0, sizeof (setcap_ioc));
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	MD_SETDRIVERNAME(&setcap_ioc, d->msg_setcap_driver, MD_MIN2SET(mnum));
8320Sstevel@tonic-gate 	setcap_ioc.mnum = mnum;
8330Sstevel@tonic-gate 	setcap_ioc.sc_set = d->msg_setcap_set;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	ret = metaioctl(MD_MN_SET_CAP, &setcap_ioc, &setcap_ioc.mde, NULL);
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	resp->mmr_exitval = ret;
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate  * Dummy handler for various CLASS0 messages like
8420Sstevel@tonic-gate  * MD_MN_MSG_VERBOSITY / MD_MN_MSG_RESUME / MD_MN_MSG_SUSPEND ...
8430Sstevel@tonic-gate  */
8440Sstevel@tonic-gate /*ARGSUSED*/
8450Sstevel@tonic-gate void
mdmn_do_dummy(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)8460Sstevel@tonic-gate mdmn_do_dummy(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
8470Sstevel@tonic-gate {
8480Sstevel@tonic-gate 	resp->mmr_out_size = 0;
8490Sstevel@tonic-gate 	resp->mmr_err_size = 0;
8500Sstevel@tonic-gate 	resp->mmr_out = NULL;
8510Sstevel@tonic-gate 	resp->mmr_err = NULL;
8520Sstevel@tonic-gate 	resp->mmr_exitval = 0;
8530Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate /*
8570Sstevel@tonic-gate  * Overall description of mdcommd support that keeps all nodes in-sync
8580Sstevel@tonic-gate  * with the ondisk diskset mddbs.
8590Sstevel@tonic-gate  *
8600Sstevel@tonic-gate  * All configuration changes to the mddb - addition/deletion of metadevices
8610Sstevel@tonic-gate  * or replicas must use a CLASS1 message to block out these changes.
8620Sstevel@tonic-gate  * Changes to the state of existing replicas do not need to block CLASS1
8630Sstevel@tonic-gate  * since there is no conflict when just updating the state of a replica.
8640Sstevel@tonic-gate  *
8650Sstevel@tonic-gate  * Error encountered when master writes to mddbs:
8660Sstevel@tonic-gate  *	As the master updates parts of the mddbs, flags are updated describing
8670Sstevel@tonic-gate  *	what has been written.  When all locks are dropped (either in
8680Sstevel@tonic-gate  *	mddb_setexit or mdioctl), a PARSE message will be generated to all
8690Sstevel@tonic-gate  *	nodes with an index list of known good mddbs and the parse flags.
8700Sstevel@tonic-gate  *	The master node ignore the parse message since it sent it.
8710Sstevel@tonic-gate  *	The slave nodes re-read in the changed part of the mddb using the list
8720Sstevel@tonic-gate  *	of known good replicas that was passed.
8730Sstevel@tonic-gate  *	PARSE message does not block CLASS1.
8740Sstevel@tonic-gate  *	The PARSE message must be the highest class message.  Since this
8750Sstevel@tonic-gate  *	message could be sent on any ioctl, this PARSE message class must
8760Sstevel@tonic-gate  *	be higher than any other class message that could issue an ioctl.
8770Sstevel@tonic-gate  *
8780Sstevel@tonic-gate  *	Master		Slave1		Slave2
8790Sstevel@tonic-gate  * 	Handles_error
8800Sstevel@tonic-gate  *	PARSE		PARSE		PARSE
8810Sstevel@tonic-gate  *
8820Sstevel@tonic-gate  *
8830Sstevel@tonic-gate  * Add/Delete mddbs can occur from the following commands:
8840Sstevel@tonic-gate  *	metadb -s set_name -a/-d
8850Sstevel@tonic-gate  *	metaset -s set_name -a/-d disk
8860Sstevel@tonic-gate  *	metaset -s set_name -b
8870Sstevel@tonic-gate  *
8880Sstevel@tonic-gate  *	The metadb/metaset command is run on the node executing the command
8890Sstevel@tonic-gate  *	and sends an ATTACH/DETACH message to the master node blocking CLASS1
8900Sstevel@tonic-gate  *	messages on all nodes until this message is finished.  The master
8910Sstevel@tonic-gate  *	node generates 3 submessages of BLOCK, SM_ATTACH/SM_DETACH, UNBLOCK.
8920Sstevel@tonic-gate  *	The BLOCK message is only run on the master node and will BLOCK
8930Sstevel@tonic-gate  *	the PARSE messages from being sent to the nodes.
8940Sstevel@tonic-gate  *	The SM_ATTACH/SM_DETACH message is run on all nodes and actually adds or
8950Sstevel@tonic-gate  *	removes the replica(s) from the given disk slice.
8960Sstevel@tonic-gate  *	The UNBLOCK message is only run on the master node and allows the
8970Sstevel@tonic-gate  *	sending of PARSE messages.
8980Sstevel@tonic-gate  *
8990Sstevel@tonic-gate  *	Master		Slave1		Slave2
9000Sstevel@tonic-gate  *			Add mddb cmd
9010Sstevel@tonic-gate  *			ATTACH msg to master
9020Sstevel@tonic-gate  *	BLOCK
9030Sstevel@tonic-gate  *	ATTACH		ATTACH		ATTACH
9040Sstevel@tonic-gate  *	UNBLOCK
9050Sstevel@tonic-gate  *	PARSE		PARSE		PARSE
9060Sstevel@tonic-gate  *	ATTACH msg finished
9070Sstevel@tonic-gate  *
9080Sstevel@tonic-gate  * Add/Delete host side information from the following commands:
9090Sstevel@tonic-gate  *	metaset -s set_name -a/-d -h
9100Sstevel@tonic-gate  *
9110Sstevel@tonic-gate  *	The metaset command is run on the node executing the command and
9120Sstevel@tonic-gate  *	sends a DB_NEWSIDE/DB_DELSIDE message and a MD_NEWSIDE/MD_DELSIDE
9130Sstevel@tonic-gate  *	message whenever a host is added to or deleted from the diskset.
9140Sstevel@tonic-gate  *
9150Sstevel@tonic-gate  *	The side information contains the major name and minor number
9160Sstevel@tonic-gate  *	associated with a disk slice from a certain node's perspective
9170Sstevel@tonic-gate  *	in an (failed) effort to support clustered systems that don't have the
9180Sstevel@tonic-gate  *	same device name for a physical device. (The original designers of
9190Sstevel@tonic-gate  *	SVM eventually took the shortcut of assuming that all device names
9200Sstevel@tonic-gate  *	are the same on all systems, but left the side information in the
9210Sstevel@tonic-gate  *	mddb and namespace.)  The side information is used for disk slices
9220Sstevel@tonic-gate  *	that contain mddbs and/or are components for metadevices.
9230Sstevel@tonic-gate  *
9240Sstevel@tonic-gate  *	The DB_NEWSIDE/DELSIDE command adds or deletes the side information
9250Sstevel@tonic-gate  *	for each mddb for the host being added or deleted.
9260Sstevel@tonic-gate  *	The MD_ADDSIDE/MD_DELSIDE command adds or deletes the side information
9270Sstevel@tonic-gate  *	for all disk slice components that are in the namespace records for
9280Sstevel@tonic-gate  *	the host being added or deleted.
9290Sstevel@tonic-gate  *
9300Sstevel@tonic-gate  *	The DB_NEWSIDE/DB_DELSIDE message does not change any mddb records
9310Sstevel@tonic-gate  *	and only needs to be executed on the master node since the slave
9320Sstevel@tonic-gate  *	nodes will be brought up to date by the PARSE message that is
9330Sstevel@tonic-gate  *	generated as a result of a change to the mddb.
9340Sstevel@tonic-gate  *	The MD_ADDSIDE/MD_DELSIDE message does modify the records in the mddb
9350Sstevel@tonic-gate  *	and needs to be run on all nodes.  The message must block class1
9360Sstevel@tonic-gate  *	messages so that record changing commands don't interfere.
9370Sstevel@tonic-gate  *
9380Sstevel@tonic-gate  *	Master		Slave1		Slave2
9390Sstevel@tonic-gate  *			Add host
9400Sstevel@tonic-gate  *			DB_NEWSIDE msg to master
9410Sstevel@tonic-gate  *	DB_NEWSIDE
9420Sstevel@tonic-gate  *	PARSE		PARSE		PARSE
9430Sstevel@tonic-gate  *	DB_NEWSIDE msg finished
9440Sstevel@tonic-gate  *			MD_NEWSIDE msg to master
9450Sstevel@tonic-gate  *	MD_NEWSIDE	MD_NEWSIDE	MD_NEWSIDE
9460Sstevel@tonic-gate  *	MD_NEWSIDE msg finished
9470Sstevel@tonic-gate  *
9480Sstevel@tonic-gate  *
9490Sstevel@tonic-gate  * Optimized resync record failure:
9500Sstevel@tonic-gate  *	When any node sees a failure to write an optimized resync record
9510Sstevel@tonic-gate  *	that node notifies the master node of the replica that failed.
9520Sstevel@tonic-gate  *	The master node handles the error and updates the rest of the
9530Sstevel@tonic-gate  *	nodes using a PARSE message.  The PARSE message also calls
9540Sstevel@tonic-gate  *	fixoptrecord on each slave node causing each node to fix up
9550Sstevel@tonic-gate  * 	the optimized resync records that are owned by that node (the mirror
9560Sstevel@tonic-gate  *	owner code also sets the optimized resync record owner).  The master
9570Sstevel@tonic-gate  *	node will fix up all optimized resync records that have no owner or
9580Sstevel@tonic-gate  *	are owned by the master node.
9590Sstevel@tonic-gate  *
9600Sstevel@tonic-gate  *	Master		Slave1		Slave2
9610Sstevel@tonic-gate  *					Optimized Record Failure
9620Sstevel@tonic-gate  *					OPTRECERR msg to master
9630Sstevel@tonic-gate  *	Master handles opt rec failure
9640Sstevel@tonic-gate  *	PARSE		PARSE		PARSE
9650Sstevel@tonic-gate  *	OPTRECERR msg finished
9660Sstevel@tonic-gate  *					Slave rewrites optimized record
9670Sstevel@tonic-gate  *
9680Sstevel@tonic-gate  */
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate /*
9710Sstevel@tonic-gate  * Handler for MD_MN_MSG_MDDB_PARSE which send parse messages to the
9720Sstevel@tonic-gate  * slave nodes in order to keep the incore view of the mddbs the
9730Sstevel@tonic-gate  * same on all nodes.
9740Sstevel@tonic-gate  *
9750Sstevel@tonic-gate  * Since master node generated the mddb parse message, do nothing
9760Sstevel@tonic-gate  * if this is the master node.
9770Sstevel@tonic-gate  *
9780Sstevel@tonic-gate  * If this is a slave node, send the parse message down to the kernel
9790Sstevel@tonic-gate  * where this node will re-read in parts of the mddbs.
9800Sstevel@tonic-gate  *
9810Sstevel@tonic-gate  */
9820Sstevel@tonic-gate void
mdmn_do_mddb_parse(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)9830Sstevel@tonic-gate mdmn_do_mddb_parse(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
9840Sstevel@tonic-gate {
9850Sstevel@tonic-gate 	md_mn_msg_mddb_parse_t	*d;
9860Sstevel@tonic-gate 	mddb_parse_parm_t	mpp;
9870Sstevel@tonic-gate 	int			ret = 0;
9880Sstevel@tonic-gate 	int			i;
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate 	resp->mmr_out_size = 0;
9910Sstevel@tonic-gate 	resp->mmr_err_size = 0;
9920Sstevel@tonic-gate 	resp->mmr_out = NULL;
9930Sstevel@tonic-gate 	resp->mmr_err = NULL;
9940Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
9950Sstevel@tonic-gate 	d = (md_mn_msg_mddb_parse_t *)((void *)(msg->msg_event_data));
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	if (flags & MD_MSGF_ON_MASTER)
9980Sstevel@tonic-gate 		return;
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 	(void) memset(&mpp, 0, sizeof (mpp));
10010Sstevel@tonic-gate 	mpp.c_setno = msg->msg_setno;
10020Sstevel@tonic-gate 	mpp.c_parse_flags = d->msg_parse_flags;
10030Sstevel@tonic-gate 	for (i = 0; i < MDDB_NLB; i++) {
10040Sstevel@tonic-gate 		mpp.c_lb_flags[i] = d->msg_lb_flags[i];
10050Sstevel@tonic-gate 	}
10060Sstevel@tonic-gate 	ret = metaioctl(MD_MN_MDDB_PARSE, &mpp, &mpp.c_mde, NULL);
10070Sstevel@tonic-gate 	if (ret)
10080Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &mpp.c_mde);
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 	resp->mmr_exitval = ret;
10110Sstevel@tonic-gate }
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate /*
10140Sstevel@tonic-gate  * Handler for MD_MN_MSG_MDDB_BLOCK which blocks the generation
10150Sstevel@tonic-gate  * of parse messages from this node.
10160Sstevel@tonic-gate  *
10170Sstevel@tonic-gate  * This is needed when attaching/detaching mddbs on the master and the
10180Sstevel@tonic-gate  * slave node is unable to handle a parse message until the slave node
10190Sstevel@tonic-gate  * has done the attach/detach of the mddbs.  So, master node will block
10200Sstevel@tonic-gate  * the parse messages, execute the attach/detach on all nodes and
10210Sstevel@tonic-gate  * then unblock the parse messages which causes the parse message to
10220Sstevel@tonic-gate  * be sent to all nodes.
10230Sstevel@tonic-gate  */
10240Sstevel@tonic-gate /*ARGSUSED*/
10250Sstevel@tonic-gate void
mdmn_do_mddb_block(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)10260Sstevel@tonic-gate mdmn_do_mddb_block(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
10270Sstevel@tonic-gate {
10280Sstevel@tonic-gate 	md_mn_msg_mddb_block_t	*d;
10290Sstevel@tonic-gate 	mddb_block_parm_t	mbp;
10300Sstevel@tonic-gate 	int			ret;
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 	resp->mmr_out_size = 0;
10330Sstevel@tonic-gate 	resp->mmr_err_size = 0;
10340Sstevel@tonic-gate 	resp->mmr_out = NULL;
10350Sstevel@tonic-gate 	resp->mmr_err = NULL;
10360Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
10370Sstevel@tonic-gate 	d = (md_mn_msg_mddb_block_t *)((void *)(msg->msg_event_data));
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	(void) memset(&mbp, 0, sizeof (mbp));
10400Sstevel@tonic-gate 	mbp.c_setno = msg->msg_setno;
10410Sstevel@tonic-gate 	mbp.c_blk_flags = d->msg_block_flags;
10420Sstevel@tonic-gate 	ret = metaioctl(MD_MN_MDDB_BLOCK, &mbp, &mbp.c_mde, NULL);
10430Sstevel@tonic-gate 	if (ret)
10440Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &mbp.c_mde);
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	resp->mmr_exitval = ret;
10470Sstevel@tonic-gate }
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate /*
10500Sstevel@tonic-gate  * Submessage generator for MD_MN_MSG_META_DB_ATTACH which generates
10510Sstevel@tonic-gate  * a BLOCK message on the master node only, a MD_MN_MSG_SM_MDDB_ATTACH
10520Sstevel@tonic-gate  * message on all nodes and then an UNBLOCK message on the master only.
10530Sstevel@tonic-gate  */
10540Sstevel@tonic-gate int
mdmn_smgen_mddb_attach(md_mn_msg_t * msg,md_mn_msg_t * msglist[])10550Sstevel@tonic-gate mdmn_smgen_mddb_attach(md_mn_msg_t *msg, md_mn_msg_t *msglist[])
10560Sstevel@tonic-gate {
10570Sstevel@tonic-gate 	md_mn_msg_t			*nmsg;
10580Sstevel@tonic-gate 	md_mn_msg_meta_db_attach_t	*d;
10590Sstevel@tonic-gate 	md_mn_msg_meta_db_attach_t	*attach_d;
10600Sstevel@tonic-gate 	md_mn_msg_mddb_block_t		*block_d;
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_attach_t *)(void *)msg->msg_event_data;
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
10650Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	nmsg->msg_flags		= (MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST);
10680Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
10690Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_MDDB_BLOCK;
10700Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_mddb_block_t);
10710Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_mddb_block_t));
10720Sstevel@tonic-gate 	block_d = (md_mn_msg_mddb_block_t *)(void *)nmsg->msg_event_data;
10730Sstevel@tonic-gate 	block_d->msg_block_flags = MDDB_BLOCK_PARSE;
10740Sstevel@tonic-gate 	msglist[0] = nmsg;
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
10770Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	/* Don't log submessages and panic on inconsistent results */
10807210Srayh 	nmsg->msg_flags = MD_MSGF_NO_LOG |
10817210Srayh 	    MD_MSGF_PANIC_WHEN_INCONSISTENT;
10820Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
10830Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_SM_MDDB_ATTACH;
10840Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_meta_db_attach_t);
10850Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_meta_db_attach_t));
10860Sstevel@tonic-gate 	attach_d = (md_mn_msg_meta_db_attach_t *)
10877210Srayh 	    (void *)nmsg->msg_event_data;
10880Sstevel@tonic-gate 	attach_d->msg_l_dev = d->msg_l_dev;
10890Sstevel@tonic-gate 	attach_d->msg_cnt = d->msg_cnt;
10900Sstevel@tonic-gate 	attach_d->msg_dbsize = d->msg_dbsize;
10910Sstevel@tonic-gate 	(void) strncpy(attach_d->msg_dname, d->msg_dname, 16);
10920Sstevel@tonic-gate 	attach_d->msg_splitname = d->msg_splitname;
10930Sstevel@tonic-gate 	attach_d->msg_options = d->msg_options;
10940Sstevel@tonic-gate 	msglist[1] = nmsg;
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
10970Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	nmsg->msg_flags		= (MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST);
11000Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
11010Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_MDDB_BLOCK;
11020Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_mddb_block_t);
11030Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_mddb_block_t));
11040Sstevel@tonic-gate 	block_d = (md_mn_msg_mddb_block_t *)(void *)nmsg->msg_event_data;
11050Sstevel@tonic-gate 	block_d->msg_block_flags = MDDB_UNBLOCK_PARSE;
11060Sstevel@tonic-gate 	msglist[2] = nmsg;
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	return (3); /* Return the number of submessages generated */
11090Sstevel@tonic-gate }
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate /*
11120Sstevel@tonic-gate  * Submessage generator for MD_MN_MSG_META_DB_DETACH which generates
11130Sstevel@tonic-gate  * a BLOCK message on the master node only, a MD_MN_MSG_SM_MDDB_DETACH
11140Sstevel@tonic-gate  * message on all nodes and then an UNBLOCK message on the master only.
11150Sstevel@tonic-gate  */
11160Sstevel@tonic-gate int
mdmn_smgen_mddb_detach(md_mn_msg_t * msg,md_mn_msg_t * msglist[])11170Sstevel@tonic-gate mdmn_smgen_mddb_detach(md_mn_msg_t *msg, md_mn_msg_t *msglist[])
11180Sstevel@tonic-gate {
11190Sstevel@tonic-gate 	md_mn_msg_t			*nmsg;
11200Sstevel@tonic-gate 	md_mn_msg_meta_db_detach_t	*d;
11210Sstevel@tonic-gate 	md_mn_msg_meta_db_detach_t	*detach_d;
11220Sstevel@tonic-gate 	md_mn_msg_mddb_block_t		*block_d;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_detach_t *)(void *)msg->msg_event_data;
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
11270Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	nmsg->msg_flags		= (MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST);
11300Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
11310Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_MDDB_BLOCK;
11320Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_mddb_block_t);
11330Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_mddb_block_t));
11340Sstevel@tonic-gate 	block_d = (md_mn_msg_mddb_block_t *)(void *)nmsg->msg_event_data;
11350Sstevel@tonic-gate 	block_d->msg_block_flags = MDDB_BLOCK_PARSE;
11360Sstevel@tonic-gate 	msglist[0] = nmsg;
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
11390Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	/* Don't log submessages and panic on inconsistent results */
11427210Srayh 	nmsg->msg_flags = MD_MSGF_NO_LOG |
11437210Srayh 	    MD_MSGF_PANIC_WHEN_INCONSISTENT;
11440Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
11450Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_SM_MDDB_DETACH;
11460Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_meta_db_detach_t);
11470Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_meta_db_detach_t));
11480Sstevel@tonic-gate 	detach_d = (md_mn_msg_meta_db_detach_t *)
11497210Srayh 	    (void *)nmsg->msg_event_data;
11500Sstevel@tonic-gate 	detach_d->msg_splitname = d->msg_splitname;
11510Sstevel@tonic-gate 	msglist[1] = nmsg;
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
11540Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	nmsg->msg_flags		= (MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST);
11570Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
11580Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_MDDB_BLOCK;
11590Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof (md_mn_msg_mddb_block_t);
11600Sstevel@tonic-gate 	nmsg->msg_event_data	= Zalloc(sizeof (md_mn_msg_mddb_block_t));
11610Sstevel@tonic-gate 	block_d = (md_mn_msg_mddb_block_t *)(void *)nmsg->msg_event_data;
11620Sstevel@tonic-gate 	block_d->msg_block_flags = MDDB_UNBLOCK_PARSE;
11630Sstevel@tonic-gate 	msglist[2] = nmsg;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	return (3); /* Return the number of submessages generated */
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate  * Handler for MD_MN_MSG_SM_MDDB_ATTACH which is used to attach mddbs.
11700Sstevel@tonic-gate  *
11710Sstevel@tonic-gate  * Used when running:
11720Sstevel@tonic-gate  *	metadb -s set_name -a
11730Sstevel@tonic-gate  * 	metaset -s set_name -a/-d disk
11740Sstevel@tonic-gate  *	metaset -s set_name -b
11750Sstevel@tonic-gate  */
11760Sstevel@tonic-gate /*ARGSUSED*/
11770Sstevel@tonic-gate void
mdmn_do_sm_mddb_attach(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)11780Sstevel@tonic-gate mdmn_do_sm_mddb_attach(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
11790Sstevel@tonic-gate {
11800Sstevel@tonic-gate 	md_mn_msg_meta_db_attach_t	*d;
11810Sstevel@tonic-gate 	struct mddb_config		c;
11820Sstevel@tonic-gate 	int				i;
11830Sstevel@tonic-gate 	int				ret = 0;
11840Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
11850Sstevel@tonic-gate 	char				*name, *add_name;
11860Sstevel@tonic-gate 	mdname_t			*np;
11870Sstevel@tonic-gate 	mdsetname_t			*sp;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	resp->mmr_out_size = 0;
11900Sstevel@tonic-gate 	resp->mmr_err_size = 0;
11910Sstevel@tonic-gate 	resp->mmr_out = NULL;
11920Sstevel@tonic-gate 	resp->mmr_err = NULL;
11930Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
11940Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_attach_t *)((void *)(msg->msg_event_data));
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
11970Sstevel@tonic-gate 	c.c_setno = msg->msg_setno;
11980Sstevel@tonic-gate 	c.c_locator.l_dev = meta_cmpldev(d->msg_l_dev);
11990Sstevel@tonic-gate 	(void) strncpy(c.c_locator.l_driver, d->msg_dname,
12007210Srayh 	    sizeof (c.c_locator.l_driver));
12010Sstevel@tonic-gate 	c.c_devname = d->msg_splitname;
12020Sstevel@tonic-gate 	c.c_locator.l_mnum = meta_getminor(d->msg_l_dev);
12030Sstevel@tonic-gate 	c.c_multi_node = 1;
12040Sstevel@tonic-gate 	if ((sp = metasetnosetname(c.c_setno, &ep)) == NULL) {
12050Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
12060Sstevel@tonic-gate 		resp->mmr_exitval = -1;
12070Sstevel@tonic-gate 		return;
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 	(void) strcpy(c.c_setname, sp->setname);
12100Sstevel@tonic-gate 	c.c_sideno = getmyside(sp, &ep);
12110Sstevel@tonic-gate 	if (c.c_sideno == MD_SIDEWILD) {
12120Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
12130Sstevel@tonic-gate 		resp->mmr_exitval = -1;
12140Sstevel@tonic-gate 		return;
12150Sstevel@tonic-gate 	}
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	name = splicename(&d->msg_splitname);
12181623Stw21770 	np = metaname(&sp, name, LOGICAL_DEVICE, &ep);
12191623Stw21770 	Free(name);
12201623Stw21770 	if (np == NULL) {
12210Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
12220Sstevel@tonic-gate 		resp->mmr_exitval = -1;
12230Sstevel@tonic-gate 		return;
12240Sstevel@tonic-gate 	}
12250Sstevel@tonic-gate 	/*
12260Sstevel@tonic-gate 	 * All nodes in MN diskset must do meta_check_replica
12270Sstevel@tonic-gate 	 * since this causes the shared namespace to be
12280Sstevel@tonic-gate 	 * populated by the md driver names while checking
12290Sstevel@tonic-gate 	 * to see if this device is already in use as a
12300Sstevel@tonic-gate 	 * metadevice.
12310Sstevel@tonic-gate 	 */
12320Sstevel@tonic-gate 	if (meta_check_replica(sp, np, d->msg_options, 0,
12330Sstevel@tonic-gate 	    (d->msg_cnt * d->msg_dbsize), &ep)) {
12340Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
12350Sstevel@tonic-gate 		resp->mmr_exitval = -1;
12360Sstevel@tonic-gate 		return;
12370Sstevel@tonic-gate 	}
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate 	for (i = 0; i < d->msg_cnt; i++) {
12400Sstevel@tonic-gate 		c.c_locator.l_blkno = i * d->msg_dbsize + 16;
12410Sstevel@tonic-gate 		if (setup_med_cfg(sp, &c,
12420Sstevel@tonic-gate 		    (d->msg_options & MDCHK_SET_FORCE), &ep)) {
12430Sstevel@tonic-gate 			ret = -1;
12440Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &ep);
12450Sstevel@tonic-gate 			break;
12460Sstevel@tonic-gate 		}
12470Sstevel@tonic-gate 		ret = metaioctl(MD_DB_NEWDEV, &c, &c.c_mde, NULL);
12480Sstevel@tonic-gate 		/* If newdev was successful, continue with attach */
12490Sstevel@tonic-gate 		if (ret == 0) {
12500Sstevel@tonic-gate 			if (meta_db_addsidenms(sp, np, c.c_locator.l_blkno,
12510Sstevel@tonic-gate 			    DB_ADDSIDENMS_NO_BCAST, &ep)) {
12520Sstevel@tonic-gate 				ret = -1;
12530Sstevel@tonic-gate 				(void) mdstealerror(&(resp->mmr_ep), &ep);
12540Sstevel@tonic-gate 				break;
12550Sstevel@tonic-gate 			}
12560Sstevel@tonic-gate 		} else {
12570Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
12580Sstevel@tonic-gate 			break;
12590Sstevel@tonic-gate 		}
12600Sstevel@tonic-gate 	}
12610Sstevel@tonic-gate 	add_name = splicename(&d->msg_splitname);
12621623Stw21770 	if ((np = metaname(&sp, add_name, LOGICAL_DEVICE, &ep)) != NULL) {
12630Sstevel@tonic-gate 		meta_invalidate_name(np);
12640Sstevel@tonic-gate 	} else {
12650Sstevel@tonic-gate 		ret = -1;
12660Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
12670Sstevel@tonic-gate 	}
12680Sstevel@tonic-gate 	Free(add_name);
12690Sstevel@tonic-gate 
12700Sstevel@tonic-gate 	resp->mmr_exitval = ret;
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate  * Handler for MD_MN_MSG_SM_MDDB_DETACH which is used to detach mddbs.
12750Sstevel@tonic-gate  *
12760Sstevel@tonic-gate  * Used when running:
12770Sstevel@tonic-gate  *	metadb -s set_name -d
12780Sstevel@tonic-gate  * 	metaset -s set_name -a/-d disk
12790Sstevel@tonic-gate  *	metaset -s set_name -b
12800Sstevel@tonic-gate  */
12810Sstevel@tonic-gate /*ARGSUSED*/
12820Sstevel@tonic-gate void
mdmn_do_sm_mddb_detach(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)12830Sstevel@tonic-gate mdmn_do_sm_mddb_detach(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
12840Sstevel@tonic-gate {
12850Sstevel@tonic-gate 	md_mn_msg_meta_db_detach_t	*d;
12860Sstevel@tonic-gate 	struct mddb_config		c;
12870Sstevel@tonic-gate 	int				i;
12880Sstevel@tonic-gate 	int				ret = 0;
12890Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
12900Sstevel@tonic-gate 	char				*name, *del_name;
12910Sstevel@tonic-gate 	mdname_t			*np;
12920Sstevel@tonic-gate 	mdsetname_t			*sp;
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	resp->mmr_out_size = 0;
12950Sstevel@tonic-gate 	resp->mmr_err_size = 0;
12960Sstevel@tonic-gate 	resp->mmr_out = NULL;
12970Sstevel@tonic-gate 	resp->mmr_err = NULL;
12980Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
12990Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_detach_t *)((void *)(msg->msg_event_data));
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 	if ((sp = metasetnosetname(msg->msg_setno, &ep)) == NULL) {
13020Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
13030Sstevel@tonic-gate 		resp->mmr_exitval = -1;
13040Sstevel@tonic-gate 		return;
13050Sstevel@tonic-gate 	}
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
13080Sstevel@tonic-gate 	c.c_setno = msg->msg_setno;
13090Sstevel@tonic-gate 	if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
13100Sstevel@tonic-gate 		resp->mmr_exitval = -1;
13110Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
13120Sstevel@tonic-gate 		return;
13130Sstevel@tonic-gate 	}
13140Sstevel@tonic-gate 	i = 0;
13150Sstevel@tonic-gate 	del_name = splicename(&d->msg_splitname);
13160Sstevel@tonic-gate 	while (i < c.c_dbcnt) {
13170Sstevel@tonic-gate 		c.c_id = i;
13180Sstevel@tonic-gate 		if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
13190Sstevel@tonic-gate 			ret = -1;
13200Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
13210Sstevel@tonic-gate 			break;
13220Sstevel@tonic-gate 		}
13230Sstevel@tonic-gate 		name = splicename(&c.c_devname);
13240Sstevel@tonic-gate 		if (strcmp(name, del_name) != 0) {
13250Sstevel@tonic-gate 			Free(name);
13260Sstevel@tonic-gate 			i++;
13270Sstevel@tonic-gate 			continue;
13280Sstevel@tonic-gate 		}
13290Sstevel@tonic-gate 		Free(name);
13300Sstevel@tonic-gate 		/* Found a match - delete mddb */
13310Sstevel@tonic-gate 		if (metaioctl(MD_DB_DELDEV, &c, &c.c_mde, NULL) != 0) {
13320Sstevel@tonic-gate 			ret = -1;
13330Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
13340Sstevel@tonic-gate 			break;
13350Sstevel@tonic-gate 		}
13360Sstevel@tonic-gate 		/* Not incrementing "i" intentionally (dbcnt is changed) */
13370Sstevel@tonic-gate 	}
13381623Stw21770 	if ((np = metaname(&sp, del_name, LOGICAL_DEVICE, &ep)) != NULL) {
13390Sstevel@tonic-gate 		meta_invalidate_name(np);
13400Sstevel@tonic-gate 	} else {
13410Sstevel@tonic-gate 		ret = -1;
13420Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
13430Sstevel@tonic-gate 	}
13440Sstevel@tonic-gate 	Free(del_name);
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	resp->mmr_exitval = ret;
13470Sstevel@tonic-gate }
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate /*
13500Sstevel@tonic-gate  * Handler for MD_MN_MSG_META_DB_NEWSIDE which is used to update the
13510Sstevel@tonic-gate  * side information for each diskset mddb when a new host has been
13520Sstevel@tonic-gate  * added to the diskset.  The side information is the /dev/dsk/ctds name
13530Sstevel@tonic-gate  * that the new node would use to access each mddb.
13540Sstevel@tonic-gate  *
13550Sstevel@tonic-gate  * Since this routine makes no changes to the records in the diskset mddb,
13560Sstevel@tonic-gate  * this routine only needs to be run on the master node.  The master node's
13570Sstevel@tonic-gate  * kernel code will detect that portions of the mddb have changed and
13580Sstevel@tonic-gate  * will send a parse message to all nodes to re-parse parts of the mddb.
13590Sstevel@tonic-gate  *
13600Sstevel@tonic-gate  * Used when running:
13610Sstevel@tonic-gate  * 	metaset -s set_name -a -h new_hostname
13620Sstevel@tonic-gate  */
13630Sstevel@tonic-gate /*ARGSUSED*/
13640Sstevel@tonic-gate void
mdmn_do_meta_db_newside(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)13650Sstevel@tonic-gate mdmn_do_meta_db_newside(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
13660Sstevel@tonic-gate {
13670Sstevel@tonic-gate 	md_mn_msg_meta_db_newside_t	*d;
13680Sstevel@tonic-gate 	struct mddb_config		c;
13690Sstevel@tonic-gate 	int				ret = 0;
13700Sstevel@tonic-gate 	mdsetname_t			*sp;
13710Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	resp->mmr_out_size = 0;
13740Sstevel@tonic-gate 	resp->mmr_err_size = 0;
13750Sstevel@tonic-gate 	resp->mmr_out = NULL;
13760Sstevel@tonic-gate 	resp->mmr_err = NULL;
13770Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
13780Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_newside_t *)((void *)(msg->msg_event_data));
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
13810Sstevel@tonic-gate 	c.c_setno = msg->msg_setno;
13820Sstevel@tonic-gate 	c.c_locator.l_dev = meta_cmpldev(d->msg_l_dev);
13830Sstevel@tonic-gate 	c.c_locator.l_blkno = d->msg_blkno;
13840Sstevel@tonic-gate 	(void) strncpy(c.c_locator.l_driver, d->msg_dname,
13857210Srayh 	    sizeof (c.c_locator.l_driver));
13860Sstevel@tonic-gate 	c.c_devname = d->msg_splitname;
13870Sstevel@tonic-gate 	c.c_locator.l_mnum = d->msg_mnum;
13880Sstevel@tonic-gate 	c.c_multi_node = 1;
13890Sstevel@tonic-gate 	if ((sp = metasetnosetname(c.c_setno, &ep)) == NULL) {
13900Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
13910Sstevel@tonic-gate 		resp->mmr_exitval = -1;
13920Sstevel@tonic-gate 		return;
13930Sstevel@tonic-gate 	}
13940Sstevel@tonic-gate 	(void) strcpy(c.c_setname, sp->setname);
13950Sstevel@tonic-gate 	c.c_sideno = d->msg_sideno;
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 	if ((ret = metaioctl(MD_DB_NEWSIDE, &c, &c.c_mde, NULL)) != 0) {
13980Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
13990Sstevel@tonic-gate 	}
14000Sstevel@tonic-gate 	resp->mmr_exitval = ret;
14010Sstevel@tonic-gate }
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate /*
14040Sstevel@tonic-gate  * Handler for MD_MN_MSG_META_DB_DELSIDE which is used to remove the
14050Sstevel@tonic-gate  * side information for each diskset mddb when a host has been
14060Sstevel@tonic-gate  * deleted from the diskset.  The side information is the /dev/dsk/ctds name
14070Sstevel@tonic-gate  * that the node would use to access each mddb.
14080Sstevel@tonic-gate  *
14090Sstevel@tonic-gate  * Since this routine makes no changes to the records in the diskset mddb,
14100Sstevel@tonic-gate  * this routine only needs to be run on the master node.  The master node's
14110Sstevel@tonic-gate  * kernel code will detect that portions of the mddb have changed and
14120Sstevel@tonic-gate  * will send a parse message to all nodes to re-parse parts of the mddb.
14130Sstevel@tonic-gate  *
14140Sstevel@tonic-gate  * Used when running:
14150Sstevel@tonic-gate  * 	metaset -s set_name -d -h hostname
14160Sstevel@tonic-gate  */
14170Sstevel@tonic-gate /*ARGSUSED*/
14180Sstevel@tonic-gate void
mdmn_do_meta_db_delside(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)14190Sstevel@tonic-gate mdmn_do_meta_db_delside(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
14200Sstevel@tonic-gate {
14210Sstevel@tonic-gate 	md_mn_msg_meta_db_delside_t	*d;
14220Sstevel@tonic-gate 	mddb_config_t			c;
14230Sstevel@tonic-gate 	int				ret = 0;
14240Sstevel@tonic-gate 	mdsetname_t			*sp;
14250Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
14260Sstevel@tonic-gate 
14270Sstevel@tonic-gate 	resp->mmr_out_size = 0;
14280Sstevel@tonic-gate 	resp->mmr_err_size = 0;
14290Sstevel@tonic-gate 	resp->mmr_out = NULL;
14300Sstevel@tonic-gate 	resp->mmr_err = NULL;
14310Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
14320Sstevel@tonic-gate 	d = (md_mn_msg_meta_db_delside_t *)((void *)(msg->msg_event_data));
14330Sstevel@tonic-gate 
14340Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
14350Sstevel@tonic-gate 	c.c_setno = msg->msg_setno;
14360Sstevel@tonic-gate 	c.c_locator.l_dev = meta_cmpldev(d->msg_l_dev);
14370Sstevel@tonic-gate 	c.c_locator.l_blkno = d->msg_blkno;
14380Sstevel@tonic-gate 	c.c_multi_node = 1;
14390Sstevel@tonic-gate 	if ((sp = metasetnosetname(c.c_setno, &ep)) == NULL) {
14400Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
14410Sstevel@tonic-gate 		resp->mmr_exitval = -1;
14420Sstevel@tonic-gate 		return;
14430Sstevel@tonic-gate 	}
14440Sstevel@tonic-gate 	(void) strcpy(c.c_setname, sp->setname);
14450Sstevel@tonic-gate 	c.c_sideno = d->msg_sideno;
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 	if ((ret = metaioctl(MD_DB_DELSIDE, &c, &c.c_mde, NULL)) != 0) {
14480Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &c.c_mde);
14490Sstevel@tonic-gate 	}
14500Sstevel@tonic-gate 	resp->mmr_exitval = ret;
14510Sstevel@tonic-gate }
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate /*
14540Sstevel@tonic-gate  * Handler for MD_MN_MSG_META_MD_ADDSIDE which is used to add the
14550Sstevel@tonic-gate  * side information for each diskset metadevice component (if that
14560Sstevel@tonic-gate  * component is a disk) when a host has been added to the diskset.
14570Sstevel@tonic-gate  * The side information is the /dev/dsk/ctds name that the node would
14580Sstevel@tonic-gate  * use to access the metadevice component.
14590Sstevel@tonic-gate  *
14600Sstevel@tonic-gate  * This routine makes changes to the mddb records and must be run
14610Sstevel@tonic-gate  * on all nodes.
14620Sstevel@tonic-gate  *
14630Sstevel@tonic-gate  * Used when running:
14640Sstevel@tonic-gate  * 	metaset -s set_name -a -h new_hostname
14650Sstevel@tonic-gate  */
14660Sstevel@tonic-gate /*ARGSUSED*/
14670Sstevel@tonic-gate void
mdmn_do_meta_md_addside(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)14680Sstevel@tonic-gate mdmn_do_meta_md_addside(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
14690Sstevel@tonic-gate {
14700Sstevel@tonic-gate 	md_mn_msg_meta_md_addside_t	*d;
14710Sstevel@tonic-gate 	mdnm_params_t			nm;
14720Sstevel@tonic-gate 	mdsetname_t			*sp;
14730Sstevel@tonic-gate 	char				*cname, *dname;
14740Sstevel@tonic-gate 	minor_t				mnum;
14750Sstevel@tonic-gate 	int				done, i;
14760Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate 	resp->mmr_out_size = 0;
14790Sstevel@tonic-gate 	resp->mmr_err_size = 0;
14800Sstevel@tonic-gate 	resp->mmr_out = NULL;
14810Sstevel@tonic-gate 	resp->mmr_err = NULL;
14820Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
14830Sstevel@tonic-gate 	d = (md_mn_msg_meta_md_addside_t *)((void *)(msg->msg_event_data));
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	(void) memset(&nm, 0, sizeof (nm));
14860Sstevel@tonic-gate 	if ((sp = metasetnosetname(msg->msg_setno, &ep)) == NULL) {
14870Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
14880Sstevel@tonic-gate 		resp->mmr_exitval = -1;
14890Sstevel@tonic-gate 		return;
14900Sstevel@tonic-gate 	}
14910Sstevel@tonic-gate 	/* While loop continues until IOCNXTKEY_NM gives nm.key of KEYWILD */
14920Sstevel@tonic-gate 	/*CONSTCOND*/
14930Sstevel@tonic-gate 	while (1) {
14942079Sstevep 		char	*drvnm = NULL;
14952079Sstevep 
14960Sstevel@tonic-gate 		nm.mde = mdnullerror;
14970Sstevel@tonic-gate 		nm.setno = msg->msg_setno;
14980Sstevel@tonic-gate 		nm.side = d->msg_otherside;
14990Sstevel@tonic-gate 		if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) {
15000Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &nm.mde);
15010Sstevel@tonic-gate 			resp->mmr_exitval = -1;
15020Sstevel@tonic-gate 			return;
15030Sstevel@tonic-gate 		}
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 		/* Normal exit path is to eventually get a KEYWILD */
15060Sstevel@tonic-gate 		if (nm.key == MD_KEYWILD) {
15070Sstevel@tonic-gate 			resp->mmr_exitval = 0;
15080Sstevel@tonic-gate 			return;
15090Sstevel@tonic-gate 		}
15100Sstevel@tonic-gate 
15112079Sstevep 		/*
15122079Sstevep 		 * Okay we have a valid key
15132079Sstevep 		 * Let's see if it is hsp or not
15142079Sstevep 		 */
15152079Sstevep 		nm.devname = (uintptr_t)meta_getnmentbykey(msg->msg_setno,
15167210Srayh 		    d->msg_otherside, nm.key, &drvnm, NULL, NULL, &ep);
15172079Sstevep 		if (nm.devname == NULL || drvnm == NULL) {
15182079Sstevep 			if (nm.devname)
15192079Sstevep 				Free((void *)(uintptr_t)nm.devname);
15202079Sstevep 			if (drvnm)
15212079Sstevep 				Free((void *)(uintptr_t)drvnm);
15220Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &ep);
15230Sstevel@tonic-gate 			resp->mmr_exitval = -1;
15240Sstevel@tonic-gate 			return;
15250Sstevel@tonic-gate 		}
15262079Sstevep 
15272079Sstevep 		/*
15282079Sstevep 		 * If it is hsp add here
15292079Sstevep 		 */
15302079Sstevep 		if (strcmp(drvnm, MD_HOTSPARES) == 0) {
15312079Sstevep 			if (add_name(sp, d->msg_sideno, nm.key, MD_HOTSPARES,
15322079Sstevep 			    minor(NODEV), (char *)(uintptr_t)nm.devname,
15332079Sstevep 			    NULL, NULL, &ep) == -1) {
15342079Sstevep 				Free((void *)(uintptr_t)nm.devname);
15352079Sstevep 				Free((void *)(uintptr_t)drvnm);
15362079Sstevep 				(void) mdstealerror(&(resp->mmr_ep), &ep);
15372079Sstevep 				resp->mmr_exitval = -1;
15382079Sstevep 				return;
15392079Sstevep 			} else {
15402079Sstevep 				Free((void *)(uintptr_t)nm.devname);
15412079Sstevep 				Free((void *)(uintptr_t)drvnm);
15422079Sstevep 				continue;
15432079Sstevep 			}
15442079Sstevep 		}
15452079Sstevep 
15460Sstevel@tonic-gate 		nm.side = d->msg_sideno;
154762Sjeanm 		if ((done = meta_getside_devinfo(sp,
154862Sjeanm 		    (char *)(uintptr_t)nm.devname,
15490Sstevel@tonic-gate 		    d->msg_sideno, &cname, &dname, &mnum, &ep)) == -1) {
15500Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &ep);
155162Sjeanm 			Free((void *)(uintptr_t)nm.devname);
15520Sstevel@tonic-gate 			resp->mmr_exitval = -1;
15530Sstevel@tonic-gate 			return;
15540Sstevel@tonic-gate 		}
15552079Sstevep 
155662Sjeanm 		Free((void *)(uintptr_t)nm.devname);
15572079Sstevep 		Free((void *)(uintptr_t)drvnm);
15582079Sstevep 
15590Sstevel@tonic-gate 		if (done != 1) {
15600Sstevel@tonic-gate 			Free(cname);
15610Sstevel@tonic-gate 			Free(dname);
15620Sstevel@tonic-gate 			resp->mmr_exitval = -1;
15630Sstevel@tonic-gate 			return;
15640Sstevel@tonic-gate 		}
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate 		/*
15670Sstevel@tonic-gate 		 * The device reference count can be greater than 1 if
15680Sstevel@tonic-gate 		 * more than one softpart is configured on top of the
15690Sstevel@tonic-gate 		 * same device.  If this is the case then we want to
15700Sstevel@tonic-gate 		 * increment the count to sync up with the other sides.
15710Sstevel@tonic-gate 		 */
15720Sstevel@tonic-gate 		for (i = 0; i < nm.ref_count; i++) {
15730Sstevel@tonic-gate 			if (add_name(sp, d->msg_sideno, nm.key, dname, mnum,
15741945Sjeanm 			    cname, NULL, NULL, &ep) == -1) {
15750Sstevel@tonic-gate 				(void) mdstealerror(&(resp->mmr_ep), &ep);
15760Sstevel@tonic-gate 				Free(cname);
15770Sstevel@tonic-gate 				Free(dname);
15780Sstevel@tonic-gate 				resp->mmr_exitval = -1;
15790Sstevel@tonic-gate 				return;
15800Sstevel@tonic-gate 			}
15810Sstevel@tonic-gate 		}
15820Sstevel@tonic-gate 		Free(cname);
15830Sstevel@tonic-gate 		Free(dname);
15840Sstevel@tonic-gate 	}
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	/*NOTREACHED*/
15870Sstevel@tonic-gate }
15880Sstevel@tonic-gate /*
15890Sstevel@tonic-gate  * Handler for MD_MN_MSG_META_MD_DELSIDE which is used to delete the
15900Sstevel@tonic-gate  * side information for each diskset metadevice component (if that
15910Sstevel@tonic-gate  * component is a disk) when a host has been removed from the diskset.
15920Sstevel@tonic-gate  * The side information is the /dev/dsk/ctds name that the node would
15930Sstevel@tonic-gate  * use to access the metadevice component.
15940Sstevel@tonic-gate  *
15950Sstevel@tonic-gate  * This routine makes changes to the mddb records and must be run
15960Sstevel@tonic-gate  * on all nodes.
15970Sstevel@tonic-gate  *
15980Sstevel@tonic-gate  * Used when running:
15990Sstevel@tonic-gate  * 	metaset -s set_name -d -h hostname
16000Sstevel@tonic-gate  */
16010Sstevel@tonic-gate /*ARGSUSED*/
16020Sstevel@tonic-gate void
mdmn_do_meta_md_delside(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)16030Sstevel@tonic-gate mdmn_do_meta_md_delside(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
16040Sstevel@tonic-gate {
16050Sstevel@tonic-gate 	md_mn_msg_meta_md_delside_t	*d;
16060Sstevel@tonic-gate 	mdnm_params_t			nm;
16070Sstevel@tonic-gate 	mdsetname_t			*sp;
16080Sstevel@tonic-gate 	md_error_t			ep = mdnullerror;
16090Sstevel@tonic-gate 	int				i;
16100Sstevel@tonic-gate 
16110Sstevel@tonic-gate 	resp->mmr_out_size = 0;
16120Sstevel@tonic-gate 	resp->mmr_err_size = 0;
16130Sstevel@tonic-gate 	resp->mmr_out = NULL;
16140Sstevel@tonic-gate 	resp->mmr_err = NULL;
16150Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
16160Sstevel@tonic-gate 	d = (md_mn_msg_meta_md_delside_t *)((void *)(msg->msg_event_data));
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 	if ((sp = metasetnosetname(msg->msg_setno, &ep)) == NULL) {
16190Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &ep);
16200Sstevel@tonic-gate 		resp->mmr_exitval = -1;
16210Sstevel@tonic-gate 		return;
16220Sstevel@tonic-gate 	}
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 	(void) memset(&nm, 0, sizeof (nm));
16250Sstevel@tonic-gate 	nm.key = MD_KEYWILD;
16260Sstevel@tonic-gate 	/*CONSTCOND*/
16270Sstevel@tonic-gate 	while (1) {
16280Sstevel@tonic-gate 		nm.mde = mdnullerror;
16290Sstevel@tonic-gate 		nm.setno = msg->msg_setno;
16300Sstevel@tonic-gate 		nm.side = MD_SIDEWILD;
16310Sstevel@tonic-gate 		if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde, NULL) != 0) {
16320Sstevel@tonic-gate 			(void) mdstealerror(&(resp->mmr_ep), &nm.mde);
16330Sstevel@tonic-gate 			resp->mmr_exitval = -1;
16340Sstevel@tonic-gate 			return;
16350Sstevel@tonic-gate 		}
16360Sstevel@tonic-gate 
16370Sstevel@tonic-gate 		/* Normal exit path is to eventually get a KEYWILD */
16380Sstevel@tonic-gate 		if (nm.key == MD_KEYWILD) {
16390Sstevel@tonic-gate 			resp->mmr_exitval = 0;
16400Sstevel@tonic-gate 			return;
16410Sstevel@tonic-gate 		}
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate 		/*
16440Sstevel@tonic-gate 		 * The device reference count can be greater than 1 if
16450Sstevel@tonic-gate 		 * more than one softpart is configured on top of the
16460Sstevel@tonic-gate 		 * same device.  If this is the case then we want to
16470Sstevel@tonic-gate 		 * decrement the count to zero so the entry can be
16480Sstevel@tonic-gate 		 * actually removed.
16490Sstevel@tonic-gate 		 */
16500Sstevel@tonic-gate 		for (i = 0; i < nm.ref_count; i++) {
16510Sstevel@tonic-gate 			if (del_name(sp, d->msg_sideno, nm.key, &ep) == -1) {
16520Sstevel@tonic-gate 				(void) mdstealerror(&(resp->mmr_ep), &ep);
16530Sstevel@tonic-gate 				resp->mmr_exitval = -1;
16540Sstevel@tonic-gate 				return;
16550Sstevel@tonic-gate 			}
16560Sstevel@tonic-gate 		}
16570Sstevel@tonic-gate 	}
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 	/*NOTREACHED*/
16600Sstevel@tonic-gate }
16610Sstevel@tonic-gate 
16620Sstevel@tonic-gate /*
16630Sstevel@tonic-gate  * Handler for MD_MN_MSG_MDDB_OPTRECERR which is used to notify
16640Sstevel@tonic-gate  * the master node that a node has seen an error when attempting to
16650Sstevel@tonic-gate  * write to the optimized resync records that reside on 2 of the diskset
16660Sstevel@tonic-gate  * mddbs.  Master node will mark the failed replica in error and this
16670Sstevel@tonic-gate  * will send a parse message to all nodes to re-read parts of the mddb
16680Sstevel@tonic-gate  * and to fix their optimized resync records based on this information.
16690Sstevel@tonic-gate  */
16700Sstevel@tonic-gate /*ARGSUSED*/
16710Sstevel@tonic-gate void
mdmn_do_mddb_optrecerr(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)16720Sstevel@tonic-gate mdmn_do_mddb_optrecerr(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
16730Sstevel@tonic-gate {
16740Sstevel@tonic-gate 	md_mn_msg_mddb_optrecerr_t	*d;
16750Sstevel@tonic-gate 	mddb_optrec_parm_t		mop;
16760Sstevel@tonic-gate 	int				ret;
16770Sstevel@tonic-gate 	int				i;
16780Sstevel@tonic-gate 
16790Sstevel@tonic-gate 	resp->mmr_out_size = 0;
16800Sstevel@tonic-gate 	resp->mmr_err_size = 0;
16810Sstevel@tonic-gate 	resp->mmr_out = NULL;
16820Sstevel@tonic-gate 	resp->mmr_err = NULL;
16830Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
16840Sstevel@tonic-gate 	d = (md_mn_msg_mddb_optrecerr_t *)((void *)(msg->msg_event_data));
16850Sstevel@tonic-gate 
16860Sstevel@tonic-gate 	(void) memset(&mop, 0, sizeof (mop));
16870Sstevel@tonic-gate 	mop.c_setno = msg->msg_setno;
16880Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
16890Sstevel@tonic-gate 		mop.c_recerr[i] = d->msg_recerr[i];
16900Sstevel@tonic-gate 	}
16910Sstevel@tonic-gate 	ret = metaioctl(MD_MN_MDDB_OPTRECFIX, &mop, &mop.c_mde, NULL);
16920Sstevel@tonic-gate 	if (ret)
16930Sstevel@tonic-gate 		(void) mdstealerror(&(resp->mmr_ep), &mop.c_mde);
16940Sstevel@tonic-gate 
16950Sstevel@tonic-gate 	resp->mmr_exitval = ret;
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate int
mdmn_smgen_test6(md_mn_msg_t * msg,md_mn_msg_t ** msglist)16990Sstevel@tonic-gate mdmn_smgen_test6(md_mn_msg_t *msg, md_mn_msg_t **msglist)
17000Sstevel@tonic-gate {
17010Sstevel@tonic-gate 	md_mn_msg_t	*nmsg;
17020Sstevel@tonic-gate 
17030Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
17040Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
17050Sstevel@tonic-gate 
17060Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
17070Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
17080Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_TEST2;
17090Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof ("test2");
17100Sstevel@tonic-gate 	nmsg->msg_event_data	= Strdup("test2");
17110Sstevel@tonic-gate 	msglist[0] = nmsg;
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
17140Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
17150Sstevel@tonic-gate 
17160Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
17170Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
17180Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_TEST2;
17190Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof ("test2");
17200Sstevel@tonic-gate 	nmsg->msg_event_data	= Strdup("test2");
17210Sstevel@tonic-gate 	msglist[1] = nmsg;
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
17240Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
17250Sstevel@tonic-gate 
17260Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
17270Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
17280Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_TEST3;
17290Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof ("test3");
17300Sstevel@tonic-gate 	nmsg->msg_event_data	= Strdup("test3");
17310Sstevel@tonic-gate 	msglist[2] = nmsg;
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	nmsg = Zalloc(sizeof (md_mn_msg_t));
17340Sstevel@tonic-gate 	MSGID_COPY(&(msg->msg_msgid), &(nmsg->msg_msgid));
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 	nmsg->msg_flags		= MD_MSGF_NO_LOG; /* Don't log submessages */
17370Sstevel@tonic-gate 	nmsg->msg_setno		= msg->msg_setno;
17380Sstevel@tonic-gate 	nmsg->msg_type		= MD_MN_MSG_TEST4;
17390Sstevel@tonic-gate 	nmsg->msg_event_size	= sizeof ("test4");
17400Sstevel@tonic-gate 	nmsg->msg_event_data	= Strdup("test4");
17410Sstevel@tonic-gate 	msglist[3] = nmsg;
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	return (4); /* Return the number of submessages generated */
17440Sstevel@tonic-gate }
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate /*
17470Sstevel@tonic-gate  * This is to send an MD_IOCSET ioctl to all nodes to create a soft
17480Sstevel@tonic-gate  * partition.
17490Sstevel@tonic-gate  */
17500Sstevel@tonic-gate /*ARGSUSED*/
17510Sstevel@tonic-gate void
mdmn_do_iocset(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)17520Sstevel@tonic-gate mdmn_do_iocset(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
17530Sstevel@tonic-gate {
17540Sstevel@tonic-gate 	md_mn_msg_iocset_t	*d;
17550Sstevel@tonic-gate 	int			ret;
17560Sstevel@tonic-gate 	set_t			setno;
17570Sstevel@tonic-gate 	mdsetname_t		*sp;
17580Sstevel@tonic-gate 	mdname_t		*np;
17590Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
17620Sstevel@tonic-gate 	resp->mmr_out_size = 0;
17630Sstevel@tonic-gate 	resp->mmr_err_size = 0;
17640Sstevel@tonic-gate 	resp->mmr_out = NULL;
17650Sstevel@tonic-gate 	resp->mmr_err = NULL;
17660Sstevel@tonic-gate 	d = (md_mn_msg_iocset_t *)(void *)msg->msg_event_data;
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate 	setno = MD_MIN2SET(d->iocset_params.mnum);
17690Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
17700Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
17710Sstevel@tonic-gate 		    "MD_MN_MSG_IOCSET: Invalid setno %d\n"), setno);
17720Sstevel@tonic-gate 		resp->mmr_exitval = 1;
17730Sstevel@tonic-gate 		return;
17740Sstevel@tonic-gate 	}
17750Sstevel@tonic-gate 
17761623Stw21770 	/*
17771623Stw21770 	 * Device should be in the namespace already
17781623Stw21770 	 */
17790Sstevel@tonic-gate 	if ((np = metamnumname(&sp, d->iocset_params.mnum, 1, &mde)) == NULL) {
17800Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
17810Sstevel@tonic-gate 		    "MD_MN_MSG_IOCSET: Invalid mnum %d\n"),
17820Sstevel@tonic-gate 		    d->iocset_params.mnum);
17830Sstevel@tonic-gate 		resp->mmr_exitval = 1;
17840Sstevel@tonic-gate 		return;
17850Sstevel@tonic-gate 	}
17860Sstevel@tonic-gate 
17871623Stw21770 	/*
17881623Stw21770 	 * Create unit structure
17891623Stw21770 	 */
179062Sjeanm 	d->iocset_params.mdp = (uintptr_t)&d->unit; /* set pointer to unit */
17910Sstevel@tonic-gate 	ret = metaioctl(MD_IOCSET, &(d->iocset_params), &mde, np->cname);
17920Sstevel@tonic-gate 	resp->mmr_exitval = ret;
17930Sstevel@tonic-gate }
17940Sstevel@tonic-gate 
17950Sstevel@tonic-gate /*
17960Sstevel@tonic-gate  * This is to update the status of a softpart
17970Sstevel@tonic-gate  */
17980Sstevel@tonic-gate /*ARGSUSED*/
17990Sstevel@tonic-gate void
mdmn_do_sp_setstat(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)18000Sstevel@tonic-gate mdmn_do_sp_setstat(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
18010Sstevel@tonic-gate {
18020Sstevel@tonic-gate 	md_mn_msg_sp_setstat_t	*d;
18030Sstevel@tonic-gate 	int			ret;
18040Sstevel@tonic-gate 	set_t			setno;
18050Sstevel@tonic-gate 	mdsetname_t		*sp;
18060Sstevel@tonic-gate 	minor_t			mnum;
18070Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
18080Sstevel@tonic-gate 
18090Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
18100Sstevel@tonic-gate 	resp->mmr_out_size = 0;
18110Sstevel@tonic-gate 	resp->mmr_err_size = 0;
18120Sstevel@tonic-gate 	resp->mmr_out = NULL;
18130Sstevel@tonic-gate 	resp->mmr_err = NULL;
18140Sstevel@tonic-gate 	d = (md_mn_msg_sp_setstat_t *)(void *)msg->msg_event_data;
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 	mnum = d->sp_setstat_mnum;
18170Sstevel@tonic-gate 	setno = MD_MIN2SET(mnum);
18180Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
18190Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
18200Sstevel@tonic-gate 		    "MD_MN_MSG_IOCSET: Invalid setno %d\n"), setno);
18210Sstevel@tonic-gate 		resp->mmr_exitval = 1;
18220Sstevel@tonic-gate 		return;
18230Sstevel@tonic-gate 	}
18240Sstevel@tonic-gate 
18250Sstevel@tonic-gate 	ret = meta_sp_setstatus(sp, &mnum, 1, d->sp_setstat_status, &mde);
18260Sstevel@tonic-gate 	resp->mmr_exitval = ret;
18270Sstevel@tonic-gate }
18280Sstevel@tonic-gate 
18290Sstevel@tonic-gate /*
18300Sstevel@tonic-gate  * This is to add a key to the namespace
18310Sstevel@tonic-gate  */
18320Sstevel@tonic-gate /*ARGSUSED*/
18330Sstevel@tonic-gate void
mdmn_do_addkeyname(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)18340Sstevel@tonic-gate mdmn_do_addkeyname(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
18350Sstevel@tonic-gate {
18360Sstevel@tonic-gate 	md_mn_msg_addkeyname_t	*d;
18370Sstevel@tonic-gate 	int			ret;
18380Sstevel@tonic-gate 	set_t			setno;
18390Sstevel@tonic-gate 	mdsetname_t		*sp;
18400Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
18410Sstevel@tonic-gate 	mdname_t		*compnp;
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
18440Sstevel@tonic-gate 	resp->mmr_out_size = 0;
18450Sstevel@tonic-gate 	resp->mmr_err_size = 0;
18460Sstevel@tonic-gate 	resp->mmr_out = NULL;
18470Sstevel@tonic-gate 	resp->mmr_err = NULL;
18480Sstevel@tonic-gate 	d = (md_mn_msg_addkeyname_t *)(void *)msg->msg_event_data;
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 	setno = d->addkeyname_setno;
18510Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
18520Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
18530Sstevel@tonic-gate 		    "MD_MN_ADDKEYNAME: Invalid setno %d\n"), setno);
18540Sstevel@tonic-gate 		resp->mmr_exitval = -1;
18550Sstevel@tonic-gate 		return;
18560Sstevel@tonic-gate 	}
18570Sstevel@tonic-gate 
18581623Stw21770 	compnp = metaname(&sp, d->addkeyname_name, UNKNOWN, &mde);
18590Sstevel@tonic-gate 	if (compnp != NULL) {
18600Sstevel@tonic-gate 		ret = add_key_name(sp, compnp, NULL, &mde);
18610Sstevel@tonic-gate 		if (ret < 0)
18620Sstevel@tonic-gate 			resp->mmr_exitval = -1;
18630Sstevel@tonic-gate 		else
18640Sstevel@tonic-gate 			resp->mmr_exitval = compnp->key;
18650Sstevel@tonic-gate 	} else {
18660Sstevel@tonic-gate 		resp->mmr_exitval = -1;
18670Sstevel@tonic-gate 	}
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate 
18700Sstevel@tonic-gate /*
18710Sstevel@tonic-gate  * This is to delete a key from the namespace
18720Sstevel@tonic-gate  */
18730Sstevel@tonic-gate /*ARGSUSED*/
18740Sstevel@tonic-gate void
mdmn_do_delkeyname(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)18750Sstevel@tonic-gate mdmn_do_delkeyname(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
18760Sstevel@tonic-gate {
18770Sstevel@tonic-gate 	md_mn_msg_delkeyname_t	*d;
18780Sstevel@tonic-gate 	int			ret;
18790Sstevel@tonic-gate 	set_t			setno;
18800Sstevel@tonic-gate 	mdsetname_t		*sp;
18810Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
18820Sstevel@tonic-gate 	mdname_t		*compnp;
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
18850Sstevel@tonic-gate 	resp->mmr_out_size = 0;
18860Sstevel@tonic-gate 	resp->mmr_err_size = 0;
18870Sstevel@tonic-gate 	resp->mmr_out = NULL;
18880Sstevel@tonic-gate 	resp->mmr_err = NULL;
18890Sstevel@tonic-gate 	d = (md_mn_msg_delkeyname_t *)(void *)msg->msg_event_data;
18900Sstevel@tonic-gate 
18910Sstevel@tonic-gate 	setno = d->delkeyname_setno;
18920Sstevel@tonic-gate 	if ((sp = metasetnosetname(setno, &mde)) == NULL) {
18930Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
18940Sstevel@tonic-gate 		    "MD_MN_DELKEYNAME: Invalid setno %d\n"), setno);
18950Sstevel@tonic-gate 		resp->mmr_exitval = -1;
18960Sstevel@tonic-gate 		return;
18970Sstevel@tonic-gate 	}
18980Sstevel@tonic-gate 
18990Sstevel@tonic-gate 	compnp = metadevname(&sp, d->delkeyname_dev, &mde);
19000Sstevel@tonic-gate 	if (compnp != NULL) {
19010Sstevel@tonic-gate 		/*
19020Sstevel@tonic-gate 		 * Reset the key value for the name. This is required because
19030Sstevel@tonic-gate 		 * any previous call of del_key_name for the same component
19040Sstevel@tonic-gate 		 * will have resulted in the key value being reset to MD_KEYBAD
19050Sstevel@tonic-gate 		 * even though there may still be references to this component.
19060Sstevel@tonic-gate 		 */
19070Sstevel@tonic-gate 		compnp->key = d->delkeyname_key;
19080Sstevel@tonic-gate 		ret = del_key_name(sp, compnp, &mde);
19090Sstevel@tonic-gate 		resp->mmr_exitval = ret;
19100Sstevel@tonic-gate 	} else {
19110Sstevel@tonic-gate 		resp->mmr_exitval = -1;
19120Sstevel@tonic-gate 	}
19130Sstevel@tonic-gate }
19140Sstevel@tonic-gate 
19150Sstevel@tonic-gate /*
19160Sstevel@tonic-gate  * This is to get the value of tstate from the master node. We use this
19170Sstevel@tonic-gate  * to get the ABR state of a metadevice from the master.
19180Sstevel@tonic-gate  */
19190Sstevel@tonic-gate /*ARGSUSED*/
19200Sstevel@tonic-gate void
mdmn_do_get_tstate(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)19210Sstevel@tonic-gate mdmn_do_get_tstate(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
19220Sstevel@tonic-gate {
19230Sstevel@tonic-gate 	md_mn_msg_gettstate_t	*d;
19240Sstevel@tonic-gate 	int			ret;
19250Sstevel@tonic-gate 	uint_t			tstate;
19260Sstevel@tonic-gate 	md_error_t		mde = mdnullerror;
19270Sstevel@tonic-gate 
19280Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
19290Sstevel@tonic-gate 	resp->mmr_out_size = 0;
19300Sstevel@tonic-gate 	resp->mmr_err_size = 0;
19310Sstevel@tonic-gate 	resp->mmr_out = NULL;
19320Sstevel@tonic-gate 	resp->mmr_err = NULL;
19330Sstevel@tonic-gate 	d = (md_mn_msg_gettstate_t *)(void *)msg->msg_event_data;
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	ret = meta_get_tstate(d->gettstate_dev, &tstate, &mde);
19360Sstevel@tonic-gate 	if (ret != 0) {
19370Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
19380Sstevel@tonic-gate 		    "MD_MN_GET_TSTATE: Invalid dev %llx\n"), d->gettstate_dev);
19390Sstevel@tonic-gate 		tstate = 0;
19400Sstevel@tonic-gate 	}
19410Sstevel@tonic-gate 	resp->mmr_exitval = tstate;
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate /*
19450Sstevel@tonic-gate  * This is to get the mirror ABR state and the state of its submirrors from
19460Sstevel@tonic-gate  * the master node. We need this to ensure consistent output from metastat
19470Sstevel@tonic-gate  * when a new node joins the cluster during a resync. Without this the
19480Sstevel@tonic-gate  * submirror status will be incorrect until the whole resync is complete which
19490Sstevel@tonic-gate  * may take days for very large metadevices.
19500Sstevel@tonic-gate  */
19510Sstevel@tonic-gate /*ARGSUSED*/
19520Sstevel@tonic-gate void
mdmn_do_get_mirstate(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)19530Sstevel@tonic-gate mdmn_do_get_mirstate(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
19540Sstevel@tonic-gate {
19550Sstevel@tonic-gate 	md_mn_msg_mir_state_t		*d;
19560Sstevel@tonic-gate 	md_mn_msg_mir_state_res_t	*res;		/* Results */
19570Sstevel@tonic-gate 	set_t				setno;
19580Sstevel@tonic-gate 	mdsetname_t			*sp;		/* Set name */
19590Sstevel@tonic-gate 	mdname_t			*mirnp;		/* Mirror name */
19600Sstevel@tonic-gate 	md_error_t			mde = mdnullerror;
19610Sstevel@tonic-gate 	mm_unit_t			*mm;		/* Mirror */
19620Sstevel@tonic-gate 	int				smi;
19630Sstevel@tonic-gate 	uint_t				tstate;
19640Sstevel@tonic-gate 
19650Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
19660Sstevel@tonic-gate 	resp->mmr_out_size = sizeof (md_mn_msg_mir_state_res_t);
19670Sstevel@tonic-gate 	resp->mmr_err_size = 0;
19680Sstevel@tonic-gate 	resp->mmr_out = Malloc(resp->mmr_out_size);
19690Sstevel@tonic-gate 	resp->mmr_err = NULL;
19700Sstevel@tonic-gate 	d = (md_mn_msg_mir_state_t *)(void *)msg->msg_event_data;
19710Sstevel@tonic-gate 	res = (md_mn_msg_mir_state_res_t *)(void *)resp->mmr_out;
19720Sstevel@tonic-gate 
19730Sstevel@tonic-gate 	/* Validate set information from minor number */
19740Sstevel@tonic-gate 	setno = MD_MIN2SET(d->mir_state_mnum);
19750Sstevel@tonic-gate 	sp = metasetnosetname(setno, &mde);
19760Sstevel@tonic-gate 	if (sp == NULL) {
19770Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
19780Sstevel@tonic-gate 		    "MD_MN_GET_MIRROR_STATE: Invalid set %d\n"), setno);
19790Sstevel@tonic-gate 		resp->mmr_exitval = 1;	/* Failure */
19800Sstevel@tonic-gate 		Free(resp->mmr_out);
19810Sstevel@tonic-gate 		resp->mmr_out_size = 0;
19820Sstevel@tonic-gate 		return;
19830Sstevel@tonic-gate 	}
19840Sstevel@tonic-gate 
19850Sstevel@tonic-gate 	/* Construct mirror name from minor number */
19860Sstevel@tonic-gate 	mirnp = metamnumname(&sp, d->mir_state_mnum, 0, &mde);
19870Sstevel@tonic-gate 	if (mirnp == NULL) {
19880Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
19890Sstevel@tonic-gate 		    "MD_MN_GET_MIRROR_STATE: Invalid minor %lx\n"),
19900Sstevel@tonic-gate 		    d->mir_state_mnum);
19910Sstevel@tonic-gate 		resp->mmr_exitval = 2;	/* Failure */
19920Sstevel@tonic-gate 		Free(resp->mmr_out);
19930Sstevel@tonic-gate 		resp->mmr_out_size = 0;
19940Sstevel@tonic-gate 		return;
19950Sstevel@tonic-gate 	}
19960Sstevel@tonic-gate 
19970Sstevel@tonic-gate 	/* Get common mirror structure */
19980Sstevel@tonic-gate 	mm = (mm_unit_t *)meta_get_mdunit(sp, mirnp, &mde);
19990Sstevel@tonic-gate 	if (mm == NULL) {
20000Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
20010Sstevel@tonic-gate 		    "MD_MN_GET_MIRROR_STATE: Invalid mirror minor %x\n"),
20020Sstevel@tonic-gate 		    d->mir_state_mnum);
20030Sstevel@tonic-gate 		resp->mmr_exitval = 3;	/* Failure */
20040Sstevel@tonic-gate 		Free(resp->mmr_out);
20050Sstevel@tonic-gate 		resp->mmr_out_size = 0;
20060Sstevel@tonic-gate 		return;
20070Sstevel@tonic-gate 	}
20080Sstevel@tonic-gate 
20090Sstevel@tonic-gate 	if (meta_get_tstate(d->mir_state_mnum, &tstate, &mde) != 0) {
20100Sstevel@tonic-gate 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
20110Sstevel@tonic-gate 		    "MD_MN_GET_MIRROR_STATE: Invalid minor %lx\n"),
20120Sstevel@tonic-gate 		    d->mir_state_mnum);
20130Sstevel@tonic-gate 		resp->mmr_exitval = 4;	/* Failure */
20140Sstevel@tonic-gate 		Free(resp->mmr_out);
20150Sstevel@tonic-gate 		resp->mmr_out_size = 0;
20160Sstevel@tonic-gate 		return;
20170Sstevel@tonic-gate 	}
20180Sstevel@tonic-gate 	/*
20190Sstevel@tonic-gate 	 * Fill in the sm_state/sm_flags value in the results structure which
20200Sstevel@tonic-gate 	 * gets passed back to the message originator
20210Sstevel@tonic-gate 	 */
20220Sstevel@tonic-gate 	resp->mmr_exitval = 0;
20230Sstevel@tonic-gate 	for (smi = 0; (smi < NMIRROR); smi++) {
20240Sstevel@tonic-gate 		mm_submirror_t *mmsp = &mm->un_sm[smi];
20250Sstevel@tonic-gate 		res->sm_state[smi] = mmsp->sm_state;
20260Sstevel@tonic-gate 		res->sm_flags[smi] = mmsp->sm_flags;
20270Sstevel@tonic-gate 	}
20280Sstevel@tonic-gate 	/* Returm value of tstate for mirror */
20290Sstevel@tonic-gate 	res->mir_tstate = tstate;
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate /*
20330Sstevel@tonic-gate  * This is to issue an ioctl to call poke_hotspares
20340Sstevel@tonic-gate  */
20350Sstevel@tonic-gate /*ARGSUSED*/
20360Sstevel@tonic-gate void
mdmn_do_poke_hotspares(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)20370Sstevel@tonic-gate mdmn_do_poke_hotspares(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
20380Sstevel@tonic-gate {
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 	md_mn_poke_hotspares_t	pokehsp;
20410Sstevel@tonic-gate 	md_mn_msg_pokehsp_t	*d;
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	resp->mmr_out_size = 0;
20440Sstevel@tonic-gate 	resp->mmr_err_size = 0;
20450Sstevel@tonic-gate 	resp->mmr_out = NULL;
20460Sstevel@tonic-gate 	resp->mmr_err = NULL;
20470Sstevel@tonic-gate 	resp->mmr_comm_state = MDMNE_ACK;
20480Sstevel@tonic-gate 	d = (md_mn_msg_pokehsp_t *)(void *)msg->msg_event_data;
20490Sstevel@tonic-gate 
20500Sstevel@tonic-gate 	(void) memset(&pokehsp, 0, sizeof (pokehsp));
20510Sstevel@tonic-gate 	MD_SETDRIVERNAME(&pokehsp, MD_MIRROR, d->pokehsp_setno);
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 	resp->mmr_exitval = metaioctl(MD_MN_POKE_HOTSPARES, &pokehsp,
20540Sstevel@tonic-gate 	    &pokehsp.mde, NULL);
20550Sstevel@tonic-gate }
20561623Stw21770 
20571623Stw21770 /*
20581623Stw21770  * Called to create a softpart during a metarecover operation
20591623Stw21770  */
20601623Stw21770 /*ARGSUSED*/
20611623Stw21770 void
mdmn_do_addmdname(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)20621623Stw21770 mdmn_do_addmdname(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
20631623Stw21770 {
20641623Stw21770 	md_mn_msg_addmdname_t	*d;
20651623Stw21770 	md_error_t		mde = mdnullerror;
20661623Stw21770 	mdsetname_t		*sp;
20671623Stw21770 	int			init = 0;
20681623Stw21770 	mdkey_t			key;
20691623Stw21770 	minor_t			mnum;
20701623Stw21770 
20711623Stw21770 	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
20721623Stw21770 	resp->mmr_out_size = 0;
20731623Stw21770 	resp->mmr_err_size = 0;
20741623Stw21770 	resp->mmr_out = NULL;
20751623Stw21770 	resp->mmr_err = NULL;
20761623Stw21770 	d = (md_mn_msg_addmdname_t *)(void *)msg->msg_event_data;
20771623Stw21770 
20781623Stw21770 	if ((sp = metasetnosetname(d->addmdname_setno, &mde)) == NULL) {
20791623Stw21770 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
20801623Stw21770 		    "MD_MN_MSG_ADDMDNAME: Invalid setno %d\n"),
20811623Stw21770 		    d->addmdname_setno);
20821623Stw21770 		resp->mmr_exitval = 1;
20831623Stw21770 		return;
20841623Stw21770 	}
20851623Stw21770 
20861623Stw21770 	/*
20871623Stw21770 	 * If device node does not exist then init it
20881623Stw21770 	 */
20891623Stw21770 	if (!is_existing_meta_hsp(sp, d->addmdname_name)) {
20907210Srayh 		if ((key = meta_init_make_device(&sp, d->addmdname_name,
20917210Srayh 		    &mde)) <= 0) {
20927210Srayh 			syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
20937210Srayh 			    "MD_MN_MSG_ADDMDNAME: Invalid name %s\n"),
20947210Srayh 			    d->addmdname_name);
20957210Srayh 			resp->mmr_exitval = 1;
20967210Srayh 			return;
20971623Stw21770 		}
20981623Stw21770 
20991623Stw21770 		init = 1;
21001623Stw21770 	}
21011623Stw21770 
21021623Stw21770 	/*
21031623Stw21770 	 * We should have it
21041623Stw21770 	 */
21051623Stw21770 	if (metaname(&sp, d->addmdname_name, META_DEVICE, &mde) == NULL) {
21061623Stw21770 
21077210Srayh 		if (init) {
21087210Srayh 			if (meta_getnmentbykey(sp->setno, MD_SIDEWILD,
21097210Srayh 			    key, NULL, &mnum, NULL, &mde) != NULL) {
21107210Srayh 				(void) metaioctl(
21117210Srayh 				    MD_IOCREM_DEV, &mnum, &mde, NULL);
21127210Srayh 			}
21137210Srayh 		(void) del_self_name(sp, key, &mde);
21141623Stw21770 		}
21151623Stw21770 
21167210Srayh 		resp->mmr_exitval = 1;
21177210Srayh 		return;
21181623Stw21770 	}
21191623Stw21770 
21201623Stw21770 	resp->mmr_exitval = 0;
21211623Stw21770 }
2122*8452SJohn.Wren.Kennedy@Sun.COM 
2123*8452SJohn.Wren.Kennedy@Sun.COM /*
2124*8452SJohn.Wren.Kennedy@Sun.COM  * This is used to issue a MD_MN_RR_DIRTY ioctl to the mirror.
2125*8452SJohn.Wren.Kennedy@Sun.COM  */
2126*8452SJohn.Wren.Kennedy@Sun.COM /*ARGSUSED*/
2127*8452SJohn.Wren.Kennedy@Sun.COM void
mdmn_do_mark_dirty(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)2128*8452SJohn.Wren.Kennedy@Sun.COM mdmn_do_mark_dirty(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
2129*8452SJohn.Wren.Kennedy@Sun.COM {
2130*8452SJohn.Wren.Kennedy@Sun.COM 	md_mn_msg_rr_dirty_t	*d;
2131*8452SJohn.Wren.Kennedy@Sun.COM 	md_mn_rr_dirty_params_t	rp;
2132*8452SJohn.Wren.Kennedy@Sun.COM 	int			ret;
2133*8452SJohn.Wren.Kennedy@Sun.COM 
2134*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_out_size = 0;
2135*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_err_size = 0;
2136*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_out = NULL;
2137*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_err = NULL;
2138*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_comm_state = MDMNE_ACK;
2139*8452SJohn.Wren.Kennedy@Sun.COM 	d = (md_mn_msg_rr_dirty_t *)((void *)(msg->msg_event_data));
2140*8452SJohn.Wren.Kennedy@Sun.COM 
2141*8452SJohn.Wren.Kennedy@Sun.COM 	(void) memset(&rp, 0, sizeof (rp));
2142*8452SJohn.Wren.Kennedy@Sun.COM 	MD_SETDRIVERNAME(&rp, MD_MIRROR, MD_MIN2SET(d->rr_mnum))
2143*8452SJohn.Wren.Kennedy@Sun.COM 	rp.rr_mnum = d->rr_mnum;
2144*8452SJohn.Wren.Kennedy@Sun.COM 	rp.rr_nodeid = d->rr_nodeid;
2145*8452SJohn.Wren.Kennedy@Sun.COM 	rp.rr_start = (ushort_t)((d->rr_range >> 16) & 0xffff);
2146*8452SJohn.Wren.Kennedy@Sun.COM 	rp.rr_end = (ushort_t)(d->rr_range & 0xffff);
2147*8452SJohn.Wren.Kennedy@Sun.COM 
2148*8452SJohn.Wren.Kennedy@Sun.COM 	ret = metaioctl(MD_MN_RR_DIRTY, &rp, &rp.mde, NULL);
2149*8452SJohn.Wren.Kennedy@Sun.COM 
2150*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_exitval = ret;
2151*8452SJohn.Wren.Kennedy@Sun.COM }
2152*8452SJohn.Wren.Kennedy@Sun.COM 
2153*8452SJohn.Wren.Kennedy@Sun.COM /*
2154*8452SJohn.Wren.Kennedy@Sun.COM  * This is used to issue a MD_MN_RR_CLEAN ioctl to the mirror.
2155*8452SJohn.Wren.Kennedy@Sun.COM  */
2156*8452SJohn.Wren.Kennedy@Sun.COM /*ARGSUSED*/
2157*8452SJohn.Wren.Kennedy@Sun.COM void
mdmn_do_mark_clean(md_mn_msg_t * msg,uint_t flags,md_mn_result_t * resp)2158*8452SJohn.Wren.Kennedy@Sun.COM mdmn_do_mark_clean(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
2159*8452SJohn.Wren.Kennedy@Sun.COM {
2160*8452SJohn.Wren.Kennedy@Sun.COM 	md_mn_msg_rr_clean_t	*d;
2161*8452SJohn.Wren.Kennedy@Sun.COM 	md_mn_rr_clean_params_t	*rcp;
2162*8452SJohn.Wren.Kennedy@Sun.COM 	int			ret;
2163*8452SJohn.Wren.Kennedy@Sun.COM 
2164*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_out_size = 0;
2165*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_err_size = 0;
2166*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_out = NULL;
2167*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_err = NULL;
2168*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_comm_state = MDMNE_ACK;
2169*8452SJohn.Wren.Kennedy@Sun.COM 	d = (md_mn_msg_rr_clean_t *)((void *)(msg->msg_event_data));
2170*8452SJohn.Wren.Kennedy@Sun.COM 
2171*8452SJohn.Wren.Kennedy@Sun.COM 	rcp = Zalloc(sizeof (struct md_mn_rr_clean_params) +
2172*8452SJohn.Wren.Kennedy@Sun.COM 	    MDMN_MSG_RR_CLEAN_DATA_BYTES(d));
2173*8452SJohn.Wren.Kennedy@Sun.COM 	MD_SETDRIVERNAME(rcp, MD_MIRROR, MD_MIN2SET(d->rr_mnum))
2174*8452SJohn.Wren.Kennedy@Sun.COM 	rcp->rr_mnum = d->rr_mnum;
2175*8452SJohn.Wren.Kennedy@Sun.COM 	rcp->rr_nodeid = d->rr_nodeid;
2176*8452SJohn.Wren.Kennedy@Sun.COM 	rcp->rr_start_size = d->rr_start_size;
2177*8452SJohn.Wren.Kennedy@Sun.COM 	(void) memcpy(MDMN_RR_CLEAN_PARAMS_DATA(rcp), MDMN_MSG_RR_CLEAN_DATA(d),
2178*8452SJohn.Wren.Kennedy@Sun.COM 	    MDMN_MSG_RR_CLEAN_DATA_BYTES(d));
2179*8452SJohn.Wren.Kennedy@Sun.COM 
2180*8452SJohn.Wren.Kennedy@Sun.COM 	ret = metaioctl(MD_MN_RR_CLEAN, rcp, &rcp->mde, NULL);
2181*8452SJohn.Wren.Kennedy@Sun.COM 
2182*8452SJohn.Wren.Kennedy@Sun.COM 	Free(rcp);
2183*8452SJohn.Wren.Kennedy@Sun.COM 
2184*8452SJohn.Wren.Kennedy@Sun.COM 	resp->mmr_exitval = ret;
2185*8452SJohn.Wren.Kennedy@Sun.COM }
2186