xref: /onnv-gate/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c (revision 1945:74cee1cd404b)
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
51320Srd117015  * Common Development and Distribution License (the "License").
61320Srd117015  * 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  */
210Sstevel@tonic-gate /*
221320Srd117015  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include "metad_local.h"
290Sstevel@tonic-gate #include <metad.h>
300Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
310Sstevel@tonic-gate #include <sdssc.h>
320Sstevel@tonic-gate #include <sys/lvm/md_mirror.h>
330Sstevel@tonic-gate #include <syslog.h>
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
360Sstevel@tonic-gate #include <sys/sysevent/svm.h>
370Sstevel@tonic-gate #include <thread.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #define	MDDOORS		"/usr/lib/lvm/mddoors"
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * rpc.metad daemon
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * The rpc.metad deamon supports two versions of the svm rpc calls - version 1
450Sstevel@tonic-gate  * and version 2. The over-the-wire structures sent as part of these rpc calls
460Sstevel@tonic-gate  * are also versioned - version 1 and version 2 exist. It must be noted that
470Sstevel@tonic-gate  * the version 2 structures have sub-versions or revisions as well. The
480Sstevel@tonic-gate  * revisions in the version 2 structures allow for flexiblility in changing
490Sstevel@tonic-gate  * over the wire structures without creating a new version of the svm rpc
500Sstevel@tonic-gate  * calls. No changes may be made to the version 1 routines or structures used
510Sstevel@tonic-gate  * by these routines.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * If, for example, the version 2 mdrpc_devinfo_args over the wire structure
540Sstevel@tonic-gate  * (mdrpc_devinfo_2_args*) is changed then the structure change must be
550Sstevel@tonic-gate  * accompanied by the following:
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  * Header file changes:
580Sstevel@tonic-gate  * . May need to introduce a new structure revision MD_METAD_ARGS_REV_X, where
590Sstevel@tonic-gate  *   X is the revision number.
600Sstevel@tonic-gate  * . Create mdrpc_devinfo_2_args_rX, where X is the new revision of the
610Sstevel@tonic-gate  *   structure.
620Sstevel@tonic-gate  * . Add a switch statement in mdrpc_devinfo_2_args.
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * rpc.metad changes:
650Sstevel@tonic-gate  * . Check for the structure revision in the appropriate mdrpc_devinfo_svc
660Sstevel@tonic-gate  *   routine (mdrpc_devinfo_2_svc).
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * libmeta changes:
690Sstevel@tonic-gate  * . In the libmeta code that makes the mdrpc_devinfo rpc call, the arguments
700Sstevel@tonic-gate  *   being passed as part of this call (namely mdrpc_devinfo_Y_args) must have
710Sstevel@tonic-gate  *   the revision field and associated structure populated correctly.
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static	md_setkey_t	*my_svc_sk = NULL;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Add namespace entry to local mddb for using given sideno, key
780Sstevel@tonic-gate  * and names.
790Sstevel@tonic-gate  */
800Sstevel@tonic-gate static int
810Sstevel@tonic-gate add_sideno_sidenm(
820Sstevel@tonic-gate 	mdsidenames_t	*sidenms,
830Sstevel@tonic-gate 	mdkey_t		local_key,
840Sstevel@tonic-gate 	side_t		sideno,
850Sstevel@tonic-gate 	md_set_desc	*sd,		/* Only used with Version 2 */
860Sstevel@tonic-gate 	md_error_t	*ep
870Sstevel@tonic-gate )
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	mdsidenames_t	*sn;
900Sstevel@tonic-gate 	mdsetname_t	*local_sp;
910Sstevel@tonic-gate 	char		*nm;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
940Sstevel@tonic-gate 		return (-1);
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	for (sn = sidenms; sn != NULL; sn = sn->next)
970Sstevel@tonic-gate 		if (sn->sideno == sideno)
980Sstevel@tonic-gate 			break;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	assert(sn != NULL);
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	/*
1040Sstevel@tonic-gate 	 * SKEW will be used on the traditional diskset despite of the
1050Sstevel@tonic-gate 	 * rpc version.  SKEW is not used on the multinode diskset
1060Sstevel@tonic-gate 	 */
1070Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
1080Sstevel@tonic-gate 		nm = meta_getnmbykey(MD_LOCAL_SET, sideno, local_key, ep);
1090Sstevel@tonic-gate 	} else {
1100Sstevel@tonic-gate 		nm = meta_getnmbykey(MD_LOCAL_SET, sideno+SKEW, local_key, ep);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if (nm == NULL) {
1140Sstevel@tonic-gate 		if (! mdisok(ep)) {
1150Sstevel@tonic-gate 			if (! mdissyserror(ep, ENOENT))
1160Sstevel@tonic-gate 				return (-1);
1170Sstevel@tonic-gate 			mdclrerror(ep);
1180Sstevel@tonic-gate 		}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 		/*
1210Sstevel@tonic-gate 		 * Ignore returned key from add_name, only care about errs
1220Sstevel@tonic-gate 		 *
1230Sstevel@tonic-gate 		 * SKEW is used for a regular diskset since sideno could
1240Sstevel@tonic-gate 		 * have a value of 0 in that diskset type.  add_name is
1250Sstevel@tonic-gate 		 * writing to the local mddb and a sideno of 0 in the
1260Sstevel@tonic-gate 		 * local mddb is reserved for non-diskset names.
1270Sstevel@tonic-gate 		 * SKEW is added to the sideno in the local mddb so that
1280Sstevel@tonic-gate 		 * the sideno for the diskset will never be 0.
1290Sstevel@tonic-gate 		 *
1300Sstevel@tonic-gate 		 * In a MNdiskset, the sideno will never be 0 (by design).
1310Sstevel@tonic-gate 		 * So, no SKEW is needed when writing to the local mddb.
1320Sstevel@tonic-gate 		 */
1330Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
1340Sstevel@tonic-gate 			if (add_name(local_sp, sideno, local_key,
135*1945Sjeanm 			    sn->dname, sn->mnum, sn->cname, NULL, NULL,
136*1945Sjeanm 			    ep) == -1)
1370Sstevel@tonic-gate 				return (-1);
1380Sstevel@tonic-gate 		} else {
1390Sstevel@tonic-gate 			if (add_name(local_sp, sideno+SKEW, local_key,
140*1945Sjeanm 			    sn->dname, sn->mnum, sn->cname, NULL, NULL,
141*1945Sjeanm 			    ep) == -1)
1420Sstevel@tonic-gate 				return (-1);
1430Sstevel@tonic-gate 		}
1440Sstevel@tonic-gate 	} else
1450Sstevel@tonic-gate 		Free(nm);
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	return (0);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate /*
1510Sstevel@tonic-gate  * Delete sidename entry from local set using key and sideno.
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate static int
1540Sstevel@tonic-gate del_sideno_sidenm(
1550Sstevel@tonic-gate 	mdkey_t		sidekey,
1560Sstevel@tonic-gate 	side_t		sideno,
1570Sstevel@tonic-gate 	md_error_t	*ep
1580Sstevel@tonic-gate )
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	mdsetname_t	*local_sp;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
1630Sstevel@tonic-gate 		return (-1);
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	if (del_name(local_sp, sideno, sidekey, ep) == -1)
1660Sstevel@tonic-gate 		mdclrerror(ep); /* ignore errs */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	return (0);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Add namespace entries to local mddb for drives in drive list in
1740Sstevel@tonic-gate  * set descriptor.
1750Sstevel@tonic-gate  *
1760Sstevel@tonic-gate  * If a MNset and if this host is being added to the set (this host
1770Sstevel@tonic-gate  * is in the node_v list), add a namespace entry for the name of
1780Sstevel@tonic-gate  * each drive using this host's sideno.
1790Sstevel@tonic-gate  *
1800Sstevel@tonic-gate  * If not a MNset, add namespace entries for all the new hosts being
1810Sstevel@tonic-gate  * added to this set (list in node_v).
1820Sstevel@tonic-gate  */
1830Sstevel@tonic-gate static void
1840Sstevel@tonic-gate add_drv_sidenms(
1850Sstevel@tonic-gate 	char		*hostname,
1860Sstevel@tonic-gate 	mdsetname_t	*sp,
1870Sstevel@tonic-gate 	md_set_desc	*sd,
1880Sstevel@tonic-gate 	int		node_c,
1890Sstevel@tonic-gate 	char		**node_v,
1900Sstevel@tonic-gate 	md_error_t	*ep
1910Sstevel@tonic-gate )
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate 	mdsetname_t	*my_sp;
1940Sstevel@tonic-gate 	md_drive_desc	*dd, *my_dd, *p, *q;
1950Sstevel@tonic-gate 	mddrivename_t	*dn, *my_dn;
1960Sstevel@tonic-gate 	int		i;
1970Sstevel@tonic-gate 	side_t		sideno = 0, mysideno = 0;
1980Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
1990Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
2000Sstevel@tonic-gate 	int		devid_same = -1;
2010Sstevel@tonic-gate 	int		using_devid = 0;
2020Sstevel@tonic-gate 	md_mnnode_desc	*nd;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	assert(sd->sd_drvs != NULL);
2050Sstevel@tonic-gate 	dd = sd->sd_drvs;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
2080Sstevel@tonic-gate 		return;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if ((my_sp = metasetname(sp->setname, ep)) == NULL)
2110Sstevel@tonic-gate 		return;
2120Sstevel@tonic-gate 	metaflushsetname(my_sp);
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	/* If a MN diskset */
2150Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
2160Sstevel@tonic-gate 		/* Find sideno associated with RPC client. */
2170Sstevel@tonic-gate 		nd = sd->sd_nodelist;
2180Sstevel@tonic-gate 		while (nd) {
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, hostname) == 0) {
2210Sstevel@tonic-gate 				sideno = nd->nd_nodeid;
2220Sstevel@tonic-gate 			}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 			/* While looping, find my side num as well */
2250Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, mynode()) == 0) {
2260Sstevel@tonic-gate 				mysideno = nd->nd_nodeid;
2270Sstevel@tonic-gate 			}
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 			if ((sideno) && (mysideno)) {
2300Sstevel@tonic-gate 				break;
2310Sstevel@tonic-gate 			}
2320Sstevel@tonic-gate 			nd = nd->nd_next;
2330Sstevel@tonic-gate 		}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 		if (!sideno) {
2360Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_HOSTNOSIDE,
2370Sstevel@tonic-gate 			    sp->setno, hostname, NULL, sp->setname);
2380Sstevel@tonic-gate 			return;
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 	} else {
2410Sstevel@tonic-gate 		/*
2420Sstevel@tonic-gate 		 * if not a MN diskset
2430Sstevel@tonic-gate 		 * do action for traditional diskset.
2440Sstevel@tonic-gate 		 * despite of the rpc version
2450Sstevel@tonic-gate 		 */
2460Sstevel@tonic-gate 		for (sideno = 0; sideno < MD_MAXSIDES; sideno++) {
2470Sstevel@tonic-gate 			/* Skip empty slots */
2480Sstevel@tonic-gate 			if (sd->sd_nodes[sideno][0] == '\0')
2490Sstevel@tonic-gate 				continue;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 			if (strcmp(hostname, sd->sd_nodes[sideno]) == 0)
2520Sstevel@tonic-gate 				break;
2530Sstevel@tonic-gate 		}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 		if (sideno == MD_MAXSIDES) {
2560Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_HOSTNOSIDE, sp->setno,
2570Sstevel@tonic-gate 			    hostname, NULL, sp->setname);
2580Sstevel@tonic-gate 			return;
2590Sstevel@tonic-gate 		}
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	if ((my_dd = metaget_drivedesc_sideno(my_sp, sideno, MD_BASICNAME_OK,
2620Sstevel@tonic-gate 	    ep)) == NULL) {
2630Sstevel@tonic-gate 		if (! mdisok(ep))
2640Sstevel@tonic-gate 			return;
2650Sstevel@tonic-gate 		/* we are supposed to have drives!!!! */
2660Sstevel@tonic-gate 		assert(0);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	/*
2700Sstevel@tonic-gate 	 * The system is either all devid or all
2710Sstevel@tonic-gate 	 * non-devid so we look at the first item
2720Sstevel@tonic-gate 	 * in the list to determine if we're using devids or not.
2730Sstevel@tonic-gate 	 * We also check to make sure it's not a multi-node diskset.
2740Sstevel@tonic-gate 	 * If it is, we don't use devid's.
2750Sstevel@tonic-gate 	 *
2760Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
2770Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
2780Sstevel@tonic-gate 	 * before set the using_devid.
2790Sstevel@tonic-gate 	 */
2800Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
2810Sstevel@tonic-gate 	    (!(MD_MNSET_DESC(sd))))
2820Sstevel@tonic-gate 		using_devid = 1;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	/*
2850Sstevel@tonic-gate 	 * We have to match-up the dd that were passed
2860Sstevel@tonic-gate 	 * across the wire to the dd we have in this daemon.
2870Sstevel@tonic-gate 	 * That way we can pick up the new sidenames that were
2880Sstevel@tonic-gate 	 * passed to us and match them up with the local namespace key.
2890Sstevel@tonic-gate 	 * Only we have the key, this cannot be passed in.
2900Sstevel@tonic-gate 	 */
2910Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
2920Sstevel@tonic-gate 		dn = p->dd_dnp;
2930Sstevel@tonic-gate 		devid_remote = NULL;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
2960Sstevel@tonic-gate 		    using_devid) {
2970Sstevel@tonic-gate 			/*
2980Sstevel@tonic-gate 			 * We have a devid so use it
2990Sstevel@tonic-gate 			 */
3000Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
3010Sstevel@tonic-gate 		}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
3040Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
3050Sstevel@tonic-gate 			/* something went really wrong. Can't process */
3060Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
3070Sstevel@tonic-gate 			    hostname, dn->cname, sp->setname);
3080Sstevel@tonic-gate 			return;
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 		for (q = my_dd; q != NULL; q = q->dd_next) {
3120Sstevel@tonic-gate 			my_dn = q->dd_dnp;
3130Sstevel@tonic-gate 			devid_same = -1;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 			if (my_dn->devid != NULL && using_devid) {
3160Sstevel@tonic-gate 				if (devid_str_decode(my_dn->devid,
3170Sstevel@tonic-gate 				    &devid_local, NULL) == 0) {
3180Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
3190Sstevel@tonic-gate 					    devid_local);
3200Sstevel@tonic-gate 					devid_free(devid_local);
3210Sstevel@tonic-gate 				}
3220Sstevel@tonic-gate 			}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 			if (using_devid && devid_same == 0) {
3250Sstevel@tonic-gate 				break;
3260Sstevel@tonic-gate 			}
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 			if (!using_devid &&
3290Sstevel@tonic-gate 			    strcmp(my_dn->cname, dn->cname) == 0)
3300Sstevel@tonic-gate 				break;
3310Sstevel@tonic-gate 		}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 		if (devid_remote) {
3340Sstevel@tonic-gate 			devid_free(devid_remote);
3350Sstevel@tonic-gate 		}
3360Sstevel@tonic-gate 		assert(q != NULL);
3370Sstevel@tonic-gate 		assert(my_dn->side_names_key != MD_KEYWILD);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
3400Sstevel@tonic-gate 			/*
3410Sstevel@tonic-gate 			 * Add the side names to the local db
3420Sstevel@tonic-gate 			 * for this node only.
3430Sstevel@tonic-gate 			 */
3440Sstevel@tonic-gate 			if (add_sideno_sidenm(dn->side_names,
3450Sstevel@tonic-gate 			    my_dn->side_names_key, mysideno, sd, ep))
3460Sstevel@tonic-gate 				return;
3470Sstevel@tonic-gate 			/*
3480Sstevel@tonic-gate 			 * Sidenames for this drive were added
3490Sstevel@tonic-gate 			 * to this host during the routine adddrvs.
3500Sstevel@tonic-gate 			 * The sidenames that were added are the
3510Sstevel@tonic-gate 			 * names associated with this drive on
3520Sstevel@tonic-gate 			 * each of the hosts that were previously
3530Sstevel@tonic-gate 			 * in the set.
3540Sstevel@tonic-gate 			 * When the sidename for this drive on
3550Sstevel@tonic-gate 			 * this host is added, the sidename
3560Sstevel@tonic-gate 			 * from the host executing the command
3570Sstevel@tonic-gate 			 * (not this host) is sent to this host.
3580Sstevel@tonic-gate 			 * This host finds the originating host's
3590Sstevel@tonic-gate 			 * sidename and can then determine this
3600Sstevel@tonic-gate 			 * host's sidename.
3610Sstevel@tonic-gate 			 * The sidenames from the other hosts serve
3620Sstevel@tonic-gate 			 * only as temporary sidenames until this
3630Sstevel@tonic-gate 			 * host's sidename can be added.
3640Sstevel@tonic-gate 			 * In order to conserve space in the
3650Sstevel@tonic-gate 			 * local mddb, the code now deletes the
3660Sstevel@tonic-gate 			 * temporary sidenames added during adddrvs.
3670Sstevel@tonic-gate 			 * When finished, only the sidename for this
3680Sstevel@tonic-gate 			 * node should be left.
3690Sstevel@tonic-gate 			 * Ignore any errors during this process since
3700Sstevel@tonic-gate 			 * a failure to delete the extraneous
3710Sstevel@tonic-gate 			 * sidenames shouldn't cause this routine
3720Sstevel@tonic-gate 			 * to fail (in case that sidename didn't exist).
3730Sstevel@tonic-gate 			 */
3740Sstevel@tonic-gate 			nd = sd->sd_nodelist;
3750Sstevel@tonic-gate 			while (nd) {
3760Sstevel@tonic-gate 				if (nd->nd_nodeid != mysideno) {
3770Sstevel@tonic-gate 					if (del_sideno_sidenm(
3780Sstevel@tonic-gate 					    dn->side_names_key,
3790Sstevel@tonic-gate 					    nd->nd_nodeid, ep) == -1)
3800Sstevel@tonic-gate 						mdclrerror(ep);
3810Sstevel@tonic-gate 				}
3820Sstevel@tonic-gate 				nd = nd->nd_next;
3830Sstevel@tonic-gate 			}
3840Sstevel@tonic-gate 		} else {
3850Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
3860Sstevel@tonic-gate 				/* Skip empty slots */
3870Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
3880Sstevel@tonic-gate 					continue;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 				/* Skip nodes not being added */
3910Sstevel@tonic-gate 				if (! strinlst(sd->sd_nodes[i],
3920Sstevel@tonic-gate 					node_c, node_v))
3930Sstevel@tonic-gate 					continue;
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 				/* Add the per side names to local db */
3960Sstevel@tonic-gate 				if (add_sideno_sidenm(dn->side_names,
3970Sstevel@tonic-gate 				    my_dn->side_names_key, i, sd, ep))
3980Sstevel@tonic-gate 					return;
3990Sstevel@tonic-gate 			}
4000Sstevel@tonic-gate 		}
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate /* ARGSUSED */
4050Sstevel@tonic-gate bool_t
4060Sstevel@tonic-gate mdrpc_flush_internal_common(mdrpc_null_args *args, mdrpc_generic_res *res,
4070Sstevel@tonic-gate     struct svc_req *rqstp)
4080Sstevel@tonic-gate {
4090Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
4100Sstevel@tonic-gate 	int		err,
4110Sstevel@tonic-gate 			op_mode = W_OK;
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	memset(res, 0, sizeof (*res));
4140Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4150Sstevel@tonic-gate 		return (FALSE);
4160Sstevel@tonic-gate 	else if (err != 0)
4170Sstevel@tonic-gate 		return (TRUE);
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	metaflushnames(1);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	err = svc_fini(ep);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	return (TRUE);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate bool_t
4270Sstevel@tonic-gate mdrpc_flush_internal_1_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
4280Sstevel@tonic-gate     struct svc_req *rqstp)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate 	return (mdrpc_flush_internal_common(args, res, rqstp));
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate bool_t
4340Sstevel@tonic-gate mdrpc_flush_internal_2_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
4350Sstevel@tonic-gate     struct svc_req *rqstp)
4360Sstevel@tonic-gate {
4370Sstevel@tonic-gate 	return (mdrpc_flush_internal_common(args, res, rqstp));
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate /*
4410Sstevel@tonic-gate  * add 1 or more namespace entries per drive record.
4420Sstevel@tonic-gate  * (into the local namespace)
4430Sstevel@tonic-gate  */
4440Sstevel@tonic-gate bool_t
4450Sstevel@tonic-gate mdrpc_add_drv_sidenms_common(
4460Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args_r1	*args,
4470Sstevel@tonic-gate 	mdrpc_generic_res		*res,
4480Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
4490Sstevel@tonic-gate )
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4520Sstevel@tonic-gate 	int			err;
4530Sstevel@tonic-gate 	int			op_mode = W_OK;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	/* setup, check permissions */
4560Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4570Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4580Sstevel@tonic-gate 		return (FALSE);
4590Sstevel@tonic-gate 	else if (err != 0)
4600Sstevel@tonic-gate 		return (TRUE);
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
4630Sstevel@tonic-gate 		return (TRUE);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	/* doit */
4660Sstevel@tonic-gate 	add_drv_sidenms(args->hostname, args->sp, args->sd,
4670Sstevel@tonic-gate 	    args->node_v.node_v_len, args->node_v.node_v_val, ep);
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	err = svc_fini(ep);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	return (TRUE);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
4760Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
4770Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
4780Sstevel@tonic-gate  */
4790Sstevel@tonic-gate bool_t
4800Sstevel@tonic-gate mdrpc_add_drv_sidenms_1_svc(
4810Sstevel@tonic-gate 	mdrpc_drv_sidenm_args	*args,
4820Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4830Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4840Sstevel@tonic-gate )
4850Sstevel@tonic-gate {
4860Sstevel@tonic-gate 	bool_t				retval;
4870Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args_r1	v2_args;
4880Sstevel@tonic-gate 	int				i, j;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	/* allocate memory */
4910Sstevel@tonic-gate 	v2_args.sd = Zalloc(sizeof (md_set_desc));
4920Sstevel@tonic-gate 	alloc_newdrvdesc(args->sd->sd_drvs, &v2_args.sd->sd_drvs);
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	/* build args */
4950Sstevel@tonic-gate 	v2_args.hostname = args->hostname;
4960Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
4970Sstevel@tonic-gate 	v2_args.sp = args->sp;
4980Sstevel@tonic-gate 	/* set descriptor */
4990Sstevel@tonic-gate 	v2_args.sd->sd_ctime = args->sd->sd_ctime;
5000Sstevel@tonic-gate 	v2_args.sd->sd_genid = args->sd->sd_genid;
5010Sstevel@tonic-gate 	v2_args.sd->sd_setno = args->sd->sd_setno;
5020Sstevel@tonic-gate 	v2_args.sd->sd_flags = args->sd->sd_flags;
5030Sstevel@tonic-gate 	for (i = 0; i < MD_MAXSIDES; i++) {
5040Sstevel@tonic-gate 		v2_args.sd->sd_isown[i] = args->sd->sd_isown[i];
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 		for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j++)
5070Sstevel@tonic-gate 			v2_args.sd->sd_nodes[i][j] =
5080Sstevel@tonic-gate 			    args->sd->sd_nodes[i][j];
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 	v2_args.sd->sd_med = args->sd->sd_med;
5110Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
5120Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->sd->sd_drvs, v2_args.sd->sd_drvs);
5130Sstevel@tonic-gate 	v2_args.node_v.node_v_len = args->node_v.node_v_len;
5140Sstevel@tonic-gate 	v2_args.node_v.node_v_val = args->node_v.node_v_val;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	retval = mdrpc_add_drv_sidenms_common(&v2_args, res, rqstp);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	free(v2_args.sd);
5190Sstevel@tonic-gate 	free_newdrvdesc(v2_args.sd->sd_drvs);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	return (retval);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate bool_t
5250Sstevel@tonic-gate mdrpc_add_drv_sidenms_2_svc(
5260Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args	*args,
5270Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5280Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5290Sstevel@tonic-gate )
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate 	switch (args->rev) {
5320Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5330Sstevel@tonic-gate 		return (mdrpc_add_drv_sidenms_common(
5340Sstevel@tonic-gate 		    &args->mdrpc_drv_sidenm_2_args_u.rev1, res, rqstp));
5350Sstevel@tonic-gate 	    default:
5360Sstevel@tonic-gate 		return (FALSE);
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate static int
5410Sstevel@tonic-gate add_sidenamelist(
5420Sstevel@tonic-gate 	mddrivename_t	*dn,
5430Sstevel@tonic-gate 	side_t		thisside,
5440Sstevel@tonic-gate 	md_set_record	*sr, 		/* used by RPC version 2 */
5450Sstevel@tonic-gate 	md_error_t	*ep
5460Sstevel@tonic-gate )
5470Sstevel@tonic-gate {
5480Sstevel@tonic-gate 	mdsidenames_t	*sn;
5490Sstevel@tonic-gate 	mdkey_t		key;
5500Sstevel@tonic-gate 	int		err;
5510Sstevel@tonic-gate 	mdsetname_t	*local_sp;
5520Sstevel@tonic-gate 	md_mnset_record	*mnsr;
5530Sstevel@tonic-gate 	md_mnnode_record *nr;
5540Sstevel@tonic-gate 	uint_t		nodeid = 0;
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
5570Sstevel@tonic-gate 		return (-1);
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	key = MD_KEYWILD;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	/*
5620Sstevel@tonic-gate 	 * If a multi-node diskset, find nodeid associated with this node.
5630Sstevel@tonic-gate 	 */
5640Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
5650Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
5660Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
5670Sstevel@tonic-gate 		while (nr) {
5680Sstevel@tonic-gate 			if (strcmp(nr->nr_nodename, mynode()) == 0) {
5690Sstevel@tonic-gate 				break;
5700Sstevel@tonic-gate 			}
5710Sstevel@tonic-gate 			nr = nr->nr_next;
5720Sstevel@tonic-gate 		}
5730Sstevel@tonic-gate 		/*
5740Sstevel@tonic-gate 		 * If node is found, then a new drive is being added to
5750Sstevel@tonic-gate 		 * a MN set of which this node is a member.
5760Sstevel@tonic-gate 		 * If node is not found, then this host is being added to
5770Sstevel@tonic-gate 		 * a MN set that has drives associated with it.
5780Sstevel@tonic-gate 		 */
5790Sstevel@tonic-gate 		if (nr)
5800Sstevel@tonic-gate 			nodeid = nr->nr_nodeid;
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate 	for (sn = dn->side_names; sn != NULL; sn = sn->next) {
5830Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
5840Sstevel@tonic-gate 			/*
5850Sstevel@tonic-gate 			 * In multi-node disksets, only add side information
5860Sstevel@tonic-gate 			 * to the local mddb about this node.
5870Sstevel@tonic-gate 			 * If the sideno for this node is found, then
5880Sstevel@tonic-gate 			 * a new drive is being added to a MN set of
5890Sstevel@tonic-gate 			 * which this node is a member.
5900Sstevel@tonic-gate 			 * If the sideno for this node is not found, then
5910Sstevel@tonic-gate 			 * this host is being added to a MNset that
5920Sstevel@tonic-gate 			 * has drives associated with it.  In this case,
5930Sstevel@tonic-gate 			 * need to add the sidename associated with the
5940Sstevel@tonic-gate 			 * rpc client, but since we don't know which node
5950Sstevel@tonic-gate 			 * is the client, then add temp entries for all sides.
5960Sstevel@tonic-gate 			 * Later, the sidename for this node will be set
5970Sstevel@tonic-gate 			 * via add_drv_sidenms and then the temp
5980Sstevel@tonic-gate 			 * sidenames can be removed.
5990Sstevel@tonic-gate 			 */
6000Sstevel@tonic-gate 			if (nodeid == sn->sideno) {
6010Sstevel@tonic-gate 				if ((err = add_name(local_sp, sn->sideno, key,
602*1945Sjeanm 				    sn->dname, sn->mnum, sn->cname,
603*1945Sjeanm 				    NULL, NULL, ep)) == -1)
6040Sstevel@tonic-gate 					return (-1);
6050Sstevel@tonic-gate 				key = (mdkey_t)err;
6060Sstevel@tonic-gate 				break;
6070Sstevel@tonic-gate 			}
6080Sstevel@tonic-gate 		} else {
6090Sstevel@tonic-gate 			/*
6100Sstevel@tonic-gate 			 * When a sidename is added into the namespace the local
6110Sstevel@tonic-gate 			 * side information for the name is added first of all.
6120Sstevel@tonic-gate 			 * When the first sidename is created this causes the
6130Sstevel@tonic-gate 			 * devid of the disk to be recorded in the namespace, if
6140Sstevel@tonic-gate 			 * the non-local side information is added first then
6150Sstevel@tonic-gate 			 * there is the possibility of getting the wrong devid
6160Sstevel@tonic-gate 			 * because there is no guarantee that the dev_t (mnum in
6170Sstevel@tonic-gate 			 * this instance) is the same across all the nodes in
6180Sstevel@tonic-gate 			 * the set. So the only way to make sure that the
6190Sstevel@tonic-gate 			 * correct dev_t is used is to force the adding in of
6200Sstevel@tonic-gate 			 * the local sidename record first of all. This same
6210Sstevel@tonic-gate 			 * issue affects add_key_name().
6220Sstevel@tonic-gate 			 */
6230Sstevel@tonic-gate 			if (sn->sideno != thisside)
6240Sstevel@tonic-gate 				continue;
6250Sstevel@tonic-gate 			if ((err = add_name(local_sp, sn->sideno+SKEW, key,
626*1945Sjeanm 			    sn->dname, sn->mnum, sn->cname, NULL,
627*1945Sjeanm 			    NULL, ep)) == -1)
6280Sstevel@tonic-gate 				return (-1);
6290Sstevel@tonic-gate 			key = (mdkey_t)err;
6300Sstevel@tonic-gate 			break;
6310Sstevel@tonic-gate 		}
6320Sstevel@tonic-gate 	}
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	/*
6350Sstevel@tonic-gate 	 * Now the other sides for non-MN set
6360Sstevel@tonic-gate 	 */
6370Sstevel@tonic-gate 	if (!MD_MNSET_REC(sr)) {
6380Sstevel@tonic-gate 		for (sn = dn->side_names; sn != NULL; sn = sn->next) {
6390Sstevel@tonic-gate 			if (sn->sideno == thisside)
6400Sstevel@tonic-gate 				continue;
6410Sstevel@tonic-gate 			if ((err = add_name(local_sp, sn->sideno+SKEW, key,
642*1945Sjeanm 			    sn->dname, sn->mnum, sn->cname, NULL, NULL,
643*1945Sjeanm 			    ep)) == -1)
6440Sstevel@tonic-gate 				return (-1);
6450Sstevel@tonic-gate 			key = (mdkey_t)err;
6460Sstevel@tonic-gate 		}
6470Sstevel@tonic-gate 	}
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	/* Temporarily add all sides. */
6500Sstevel@tonic-gate 	if ((key == MD_KEYWILD) && (MD_MNSET_REC(sr))) {
6510Sstevel@tonic-gate 		for (sn = dn->side_names; sn != NULL; sn = sn->next) {
6520Sstevel@tonic-gate 			sn = dn->side_names;
6530Sstevel@tonic-gate 			if (sn) {
6540Sstevel@tonic-gate 				if ((err = add_name(local_sp, sn->sideno, key,
655*1945Sjeanm 				    sn->dname, sn->mnum, sn->cname,
656*1945Sjeanm 				    NULL, NULL, ep)) == -1)
6570Sstevel@tonic-gate 						return (-1);
6580Sstevel@tonic-gate 				key = (mdkey_t)err;
6590Sstevel@tonic-gate 			}
6600Sstevel@tonic-gate 		}
6610Sstevel@tonic-gate 	}
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	dn->side_names_key = key;
6640Sstevel@tonic-gate 	return (0);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate 
667*1945Sjeanm /*
668*1945Sjeanm  * imp_adddrvs
669*1945Sjeanm  *    This is a version of adddrvs that is specific to the
670*1945Sjeanm  *    metaimport command. Due to the unavailability of some disks,
671*1945Sjeanm  *    information needs to be obtained about the disk from the devid so
672*1945Sjeanm  *    it can eventually be passed down to add_sidenamelist.
673*1945Sjeanm  *    Go ahead and set drive state to MD_DR_OK here so that no
674*1945Sjeanm  *    later RPC is needed to set OK where UNRLSV_REPLICATED could
675*1945Sjeanm  *    be cleared.  Set record is still set to MD_SR_ADD which will force
676*1945Sjeanm  *    a cleanup of the set in case of panic.
677*1945Sjeanm  */
678*1945Sjeanm void
679*1945Sjeanm imp_adddrvs(
680*1945Sjeanm 	char		*setname,
681*1945Sjeanm 	md_drive_desc	*dd,
682*1945Sjeanm 	md_timeval32_t	timestamp,
683*1945Sjeanm 	ulong_t		genid,
684*1945Sjeanm 	md_error_t	*ep
685*1945Sjeanm )
686*1945Sjeanm {
687*1945Sjeanm 	mddb_userreq_t	req;
688*1945Sjeanm 	md_drive_record	*dr, *tdr;
689*1945Sjeanm 	md_set_record	*sr;
690*1945Sjeanm 	md_drive_desc	*p;
691*1945Sjeanm 	mddrivename_t	*dn;
692*1945Sjeanm 	mdname_t	*np;
693*1945Sjeanm 	md_dev64_t	dev;
694*1945Sjeanm 	md_error_t	xep = mdnullerror;
695*1945Sjeanm 	char		*minorname = NULL;
696*1945Sjeanm 	ddi_devid_t	devidp = NULL;
697*1945Sjeanm 	mdsidenames_t	*sn;
698*1945Sjeanm 	mdsetname_t	*local_sp;
699*1945Sjeanm 
700*1945Sjeanm 
701*1945Sjeanm 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
702*1945Sjeanm 		return;
703*1945Sjeanm 	}
704*1945Sjeanm 
705*1945Sjeanm 	if ((sr = getsetbyname(setname, ep)) == NULL)
706*1945Sjeanm 		return;
707*1945Sjeanm 
708*1945Sjeanm 	for (p = dd; p != NULL; p = p->dd_next) {
709*1945Sjeanm 		uint_t	rep_slice;
710*1945Sjeanm 		int	ret = 0;
711*1945Sjeanm 
712*1945Sjeanm 		dn = p->dd_dnp;
713*1945Sjeanm 
714*1945Sjeanm 		/*
715*1945Sjeanm 		 * We need the minorname and devid string decoded from the
716*1945Sjeanm 		 * devid to add the sidename for this drive to the
717*1945Sjeanm 		 * local set.
718*1945Sjeanm 		 */
719*1945Sjeanm 		ret = devid_str_decode(dn->devid, &devidp, &minorname);
720*1945Sjeanm 		if (ret != 0) {
721*1945Sjeanm 			/* failed to decode the devid */
722*1945Sjeanm 			goto out;
723*1945Sjeanm 		}
724*1945Sjeanm 
725*1945Sjeanm 		sn = dn->side_names;
726*1945Sjeanm 		if (sn == NULL) {
727*1945Sjeanm 			dn->side_names_key = MD_KEYWILD;
728*1945Sjeanm 			continue;
729*1945Sjeanm 		}
730*1945Sjeanm 
731*1945Sjeanm 		if ((dn->side_names_key = add_name(local_sp, SKEW, MD_KEYWILD,
732*1945Sjeanm 		    sn->dname, sn->mnum, sn->cname, minorname, devidp,
733*1945Sjeanm 		    ep)) == -1) {
734*1945Sjeanm 			devid_free(devidp);
735*1945Sjeanm 			devid_str_free(minorname);
736*1945Sjeanm 			goto out;
737*1945Sjeanm 		}
738*1945Sjeanm 
739*1945Sjeanm 		devid_free(devidp);
740*1945Sjeanm 		devid_str_free(minorname);
741*1945Sjeanm 
742*1945Sjeanm 		/* Create the drive record */
743*1945Sjeanm 		(void) memset(&req, 0, sizeof (req));
744*1945Sjeanm 		METAD_SETUP_DR(MD_DB_CREATE, 0);
745*1945Sjeanm 		req.ur_size = sizeof (*dr);
746*1945Sjeanm 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
747*1945Sjeanm 			(void) mdstealerror(ep, &req.ur_mde);
748*1945Sjeanm 			goto out;
749*1945Sjeanm 		}
750*1945Sjeanm 
751*1945Sjeanm 		/* Fill in the drive record values */
752*1945Sjeanm 		dr = Zalloc(sizeof (*dr));
753*1945Sjeanm 		dr->dr_selfid = req.ur_recid;
754*1945Sjeanm 		dr->dr_dbcnt = p->dd_dbcnt;
755*1945Sjeanm 		dr->dr_dbsize = p->dd_dbsize;
756*1945Sjeanm 		dr->dr_key = dn->side_names_key;
757*1945Sjeanm 
758*1945Sjeanm 		dr->dr_ctime = timestamp;
759*1945Sjeanm 		dr->dr_genid = genid;
760*1945Sjeanm 		dr->dr_revision = MD_DRIVE_RECORD_REVISION;
761*1945Sjeanm 		dr->dr_flags = MD_DR_OK;
762*1945Sjeanm 		if (p->dd_flags & MD_DR_UNRSLV_REPLICATED) {
763*1945Sjeanm 			dr->dr_flags |= MD_DR_UNRSLV_REPLICATED;
764*1945Sjeanm 			sr->sr_flags |= MD_SR_UNRSLV_REPLICATED;
765*1945Sjeanm 		}
766*1945Sjeanm 
767*1945Sjeanm 		/* Link the drive records and fill in in-core data */
768*1945Sjeanm 		dr_cache_add(sr, dr);
769*1945Sjeanm 
770*1945Sjeanm 		dev = NODEV64;
771*1945Sjeanm 		if ((meta_replicaslice(dn, &rep_slice, &xep) == 0) &&
772*1945Sjeanm 		    ((np = metaslicename(dn, rep_slice, &xep)) != NULL))
773*1945Sjeanm 			dev = np->dev;
774*1945Sjeanm 		else
775*1945Sjeanm 			mdclrerror(&xep);
776*1945Sjeanm 
777*1945Sjeanm 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
778*1945Sjeanm 		    MD_LOCAL_SET, dev);
779*1945Sjeanm 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
780*1945Sjeanm 		    sr->sr_setno, dev);
781*1945Sjeanm 	}
782*1945Sjeanm 
783*1945Sjeanm 	/* Commit all the records atomically */
784*1945Sjeanm 	commitset(sr, TRUE, ep);
785*1945Sjeanm 	free_sr(sr);
786*1945Sjeanm 	return;
787*1945Sjeanm 
788*1945Sjeanm out:
789*1945Sjeanm 	/* If failures, remove drive records. */
790*1945Sjeanm 	dr = tdr = sr->sr_drivechain;
791*1945Sjeanm 	while (dr != NULL) {
792*1945Sjeanm 		tdr = dr->dr_next;
793*1945Sjeanm 		if (del_name(local_sp, 0, dr->dr_key, &xep))
794*1945Sjeanm 			mdclrerror(&xep);
795*1945Sjeanm 		sr_del_drv(sr, dr->dr_selfid);
796*1945Sjeanm 		dr = tdr;
797*1945Sjeanm 	}
798*1945Sjeanm }
799*1945Sjeanm 
8000Sstevel@tonic-gate static void
8010Sstevel@tonic-gate adddrvs(
8020Sstevel@tonic-gate 	char 		*setname,
8030Sstevel@tonic-gate 	md_drive_desc	*dd,
8040Sstevel@tonic-gate 	md_timeval32_t	timestamp,
8050Sstevel@tonic-gate 	ulong_t		genid,
8060Sstevel@tonic-gate 	md_error_t	*ep
8070Sstevel@tonic-gate )
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate 	mddb_userreq_t	req;
8100Sstevel@tonic-gate 	md_drive_record	*dr;
8110Sstevel@tonic-gate 	md_set_record	*sr;
8120Sstevel@tonic-gate 	md_drive_desc	*p;
8130Sstevel@tonic-gate 	mddrivename_t	*dn;
8140Sstevel@tonic-gate 	mdname_t	*np;
8150Sstevel@tonic-gate 	md_dev64_t	dev;
8160Sstevel@tonic-gate 	md_error_t	xep = mdnullerror;
8170Sstevel@tonic-gate 	int		i;
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
8200Sstevel@tonic-gate 		return;
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	if (MD_MNSET_REC(sr))
8230Sstevel@tonic-gate 		i = 0;
8240Sstevel@tonic-gate 	else {
8250Sstevel@tonic-gate 		/* get thisside */
8260Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
8270Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
8280Sstevel@tonic-gate 				continue;
8290Sstevel@tonic-gate 			if (strcmp(mynode(), sr->sr_nodes[i]) == 0)
8300Sstevel@tonic-gate 				break;
8310Sstevel@tonic-gate 		}
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 		if (i == MD_MAXSIDES) {
8340Sstevel@tonic-gate 			/* so find the first free slot! */
8350Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
8360Sstevel@tonic-gate 				if (sr->sr_nodes[i][0] == '\0')
8370Sstevel@tonic-gate 					break;
8380Sstevel@tonic-gate 			}
8390Sstevel@tonic-gate 		}
8400Sstevel@tonic-gate 	}
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
8430Sstevel@tonic-gate 		uint_t	rep_slice;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 		dn = p->dd_dnp;
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 		/* Add the per side names to the local db */
8480Sstevel@tonic-gate 		if (add_sidenamelist(dn, (side_t)i,  sr, ep)) {
8490Sstevel@tonic-gate 				free_sr(sr);
8500Sstevel@tonic-gate 				return;
8510Sstevel@tonic-gate 		}
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		/* Create the drive record */
8540Sstevel@tonic-gate 		(void) memset(&req, 0, sizeof (req));
8550Sstevel@tonic-gate 		METAD_SETUP_DR(MD_DB_CREATE, 0);
8560Sstevel@tonic-gate 		req.ur_size = sizeof (*dr);
8570Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
8580Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
8590Sstevel@tonic-gate 			free_sr(sr);
8600Sstevel@tonic-gate 			return;
8610Sstevel@tonic-gate 		}
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 		/* Fill in the drive record values */
8640Sstevel@tonic-gate 		dr = Zalloc(sizeof (*dr));
8650Sstevel@tonic-gate 		dr->dr_selfid = req.ur_recid;
8660Sstevel@tonic-gate 		dr->dr_dbcnt = p->dd_dbcnt;
8670Sstevel@tonic-gate 		dr->dr_dbsize = p->dd_dbsize;
8680Sstevel@tonic-gate 		dr->dr_key = dn->side_names_key;
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 		dr->dr_ctime = timestamp;
8710Sstevel@tonic-gate 		dr->dr_genid = genid;
8720Sstevel@tonic-gate 		dr->dr_revision = MD_DRIVE_RECORD_REVISION;
8730Sstevel@tonic-gate 		dr->dr_flags = MD_DR_ADD;
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 		/* Link the drive records and fill in in-core data */
8760Sstevel@tonic-gate 		dr_cache_add(sr, dr);
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 		dev = NODEV64;
8790Sstevel@tonic-gate 		if ((meta_replicaslice(dn, &rep_slice, &xep) == 0) &&
8800Sstevel@tonic-gate 		    ((np = metaslicename(dn, rep_slice, &xep)) != NULL))
8810Sstevel@tonic-gate 			dev = np->dev;
8820Sstevel@tonic-gate 		else
8830Sstevel@tonic-gate 			mdclrerror(&xep);
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
8860Sstevel@tonic-gate 		    MD_LOCAL_SET, dev);
8870Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
8880Sstevel@tonic-gate 		    sr->sr_setno, dev);
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	/* Commit all the records atomically */
8920Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
8930Sstevel@tonic-gate 	free_sr(sr);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate /*
8970Sstevel@tonic-gate  * add 1 or more drive records to a set.
8980Sstevel@tonic-gate  */
8990Sstevel@tonic-gate bool_t
9000Sstevel@tonic-gate mdrpc_adddrvs_common(
9010Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
9020Sstevel@tonic-gate 	mdrpc_generic_res	*res,
9030Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
9040Sstevel@tonic-gate )
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
9070Sstevel@tonic-gate 	int			err;
9080Sstevel@tonic-gate 	int			op_mode = W_OK;
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	/* setup, check permissions */
9110Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
9120Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
9130Sstevel@tonic-gate 		return (FALSE);
9140Sstevel@tonic-gate 	else if (err != 0)
9150Sstevel@tonic-gate 		return (TRUE);
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
9180Sstevel@tonic-gate 		return (TRUE);
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	/* doit */
9210Sstevel@tonic-gate 	adddrvs(args->sp->setname, args->drivedescs, args->timestamp,
9220Sstevel@tonic-gate 	    args->genid, ep);
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	err = svc_fini(ep);
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	return (TRUE);
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate /*
9300Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
9310Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
9320Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
9330Sstevel@tonic-gate  */
9340Sstevel@tonic-gate bool_t
9350Sstevel@tonic-gate mdrpc_adddrvs_1_svc(
9360Sstevel@tonic-gate 	mdrpc_drives_args	*args,
9370Sstevel@tonic-gate 	mdrpc_generic_res	*res,
9380Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
9390Sstevel@tonic-gate )
9400Sstevel@tonic-gate {
9410Sstevel@tonic-gate 	bool_t			retval;
9420Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	/* allocate memory */
9450Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate 	/* build args */
9480Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
9490Sstevel@tonic-gate 	v2_args.sp = args->sp;
9500Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
9510Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
9520Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
9530Sstevel@tonic-gate 	v2_args.genid = args->genid;
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	retval = mdrpc_adddrvs_common(&v2_args, res, rqstp);
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	return (retval);
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate bool_t
9630Sstevel@tonic-gate mdrpc_adddrvs_2_svc(
9640Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
9650Sstevel@tonic-gate 	mdrpc_generic_res	*res,
9660Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
9670Sstevel@tonic-gate )
9680Sstevel@tonic-gate {
9690Sstevel@tonic-gate 	switch (args->rev) {
9700Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
9710Sstevel@tonic-gate 		return (mdrpc_adddrvs_common(
9720Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
9730Sstevel@tonic-gate 	    default:
9740Sstevel@tonic-gate 		return (FALSE);
9750Sstevel@tonic-gate 	}
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate 
978*1945Sjeanm /*
979*1945Sjeanm  * add 1 or more drive records to a set when importing.
980*1945Sjeanm  */
981*1945Sjeanm bool_t
982*1945Sjeanm mdrpc_imp_adddrvs_2_svc(
983*1945Sjeanm 	mdrpc_drives_2_args	*args,
984*1945Sjeanm 	mdrpc_generic_res	*res,
985*1945Sjeanm 	struct svc_req		*rqstp		/* RPC stuff */
986*1945Sjeanm )
987*1945Sjeanm {
988*1945Sjeanm 	mdrpc_drives_2_args_r1	*v2_args;
989*1945Sjeanm 	md_error_t		*ep = &res->status;
990*1945Sjeanm 	int			err;
991*1945Sjeanm 	int			op_mode = W_OK;
992*1945Sjeanm 
993*1945Sjeanm 	switch (args->rev) {
994*1945Sjeanm 	    case MD_METAD_ARGS_REV_1:
995*1945Sjeanm 		v2_args = &args->mdrpc_drives_2_args_u.rev1;
996*1945Sjeanm 		if (v2_args == NULL) {
997*1945Sjeanm 			return (FALSE);
998*1945Sjeanm 		}
999*1945Sjeanm 		break;
1000*1945Sjeanm 	    default:
1001*1945Sjeanm 		return (FALSE);
1002*1945Sjeanm 	}
1003*1945Sjeanm 
1004*1945Sjeanm 	/* setup, check permissions */
1005*1945Sjeanm 	(void) memset(res, 0, sizeof (*res));
1006*1945Sjeanm 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1007*1945Sjeanm 		return (FALSE);
1008*1945Sjeanm 	else if (err != 0)
1009*1945Sjeanm 		return (TRUE);
1010*1945Sjeanm 
1011*1945Sjeanm 	if (check_set_lock(op_mode, v2_args->cl_sk, ep))
1012*1945Sjeanm 		return (TRUE);
1013*1945Sjeanm 
1014*1945Sjeanm 	/* doit */
1015*1945Sjeanm 	imp_adddrvs(v2_args->sp->setname, v2_args->drivedescs,
1016*1945Sjeanm 	    v2_args->timestamp, v2_args->genid, ep);
1017*1945Sjeanm 
1018*1945Sjeanm 	err = svc_fini(ep);
1019*1945Sjeanm 
1020*1945Sjeanm 	return (TRUE);
1021*1945Sjeanm }
1022*1945Sjeanm 
10230Sstevel@tonic-gate static void
10240Sstevel@tonic-gate addhosts(
10250Sstevel@tonic-gate 	char		*setname,
10260Sstevel@tonic-gate 	int		node_c,
10270Sstevel@tonic-gate 	char		**node_v,
10280Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
10290Sstevel@tonic-gate 	md_error_t	*ep
10300Sstevel@tonic-gate )
10310Sstevel@tonic-gate {
10320Sstevel@tonic-gate 	mddb_userreq_t		req;
10330Sstevel@tonic-gate 	md_set_record		*sr;
10340Sstevel@tonic-gate 	int			i, j;
10350Sstevel@tonic-gate 	md_mnset_record		*mnsr;
10360Sstevel@tonic-gate 	md_mnnode_record	*nr;
10370Sstevel@tonic-gate 	mddb_set_node_params_t	snp;
10380Sstevel@tonic-gate 	int			nodecnt;
10390Sstevel@tonic-gate 	mndiskset_membershiplist_t *nl, *nl2;
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
10420Sstevel@tonic-gate 		return;
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
10450Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
10460Sstevel@tonic-gate 		mnsr = (md_mnset_record *)sr;
10470Sstevel@tonic-gate 		/*
10480Sstevel@tonic-gate 		 * Verify nodes are in membership list on THIS node.
10490Sstevel@tonic-gate 		 * Initiating node has verified that nodes are in membership
10500Sstevel@tonic-gate 		 * list on the initiating node.
10510Sstevel@tonic-gate 		 * Get membershiplist from API routine.  If there's
10520Sstevel@tonic-gate 		 * an error, fail to add hosts and pass back error.
10530Sstevel@tonic-gate 		 */
10540Sstevel@tonic-gate 		if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
10550Sstevel@tonic-gate 			free_sr(sr);
10560Sstevel@tonic-gate 			return;
10570Sstevel@tonic-gate 		}
10580Sstevel@tonic-gate 		/* Verify that all nodes are in member list */
10590Sstevel@tonic-gate 		for (i = 0; i < node_c; i++) {
10600Sstevel@tonic-gate 			/*
10610Sstevel@tonic-gate 			 * If node in list isn't a member of the membership,
10620Sstevel@tonic-gate 			 * just return error.
10630Sstevel@tonic-gate 			 */
10640Sstevel@tonic-gate 			if (meta_is_member(node_v[i], NULL, nl) == 0) {
10650Sstevel@tonic-gate 				meta_free_nodelist(nl);
10660Sstevel@tonic-gate 				(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
10670Sstevel@tonic-gate 				    sr->sr_setno, node_v[i], NULL, setname);
10680Sstevel@tonic-gate 				free_sr(sr);
10690Sstevel@tonic-gate 				return;
10700Sstevel@tonic-gate 			}
10710Sstevel@tonic-gate 		}
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
10750Sstevel@tonic-gate 		/* Do MN operation if rpc version supports it and if a MN set */
10760Sstevel@tonic-gate 		if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
10770Sstevel@tonic-gate 			mnsr = (md_mnset_record *)sr;
10780Sstevel@tonic-gate 			/* Create the node record */
10790Sstevel@tonic-gate 			(void) memset(&req, 0, sizeof (req));
10800Sstevel@tonic-gate 			METAD_SETUP_NR(MD_DB_CREATE, 0);
10810Sstevel@tonic-gate 			req.ur_size = sizeof (*nr);
10820Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
10830Sstevel@tonic-gate 			    != 0) {
10840Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
10850Sstevel@tonic-gate 				meta_free_nodelist(nl);
10860Sstevel@tonic-gate 				free_sr(sr);
10870Sstevel@tonic-gate 				return;
10880Sstevel@tonic-gate 			}
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 			nr = Zalloc(sizeof (*nr));
10910Sstevel@tonic-gate 			nr->nr_revision = MD_MNNODE_RECORD_REVISION;
10920Sstevel@tonic-gate 			nr->nr_selfid = req.ur_recid;
10930Sstevel@tonic-gate 			nr->nr_ctime = sr->sr_ctime;
10940Sstevel@tonic-gate 			nr->nr_genid = sr->sr_genid;
10950Sstevel@tonic-gate 			nr->nr_flags = MD_MN_NODE_ADD;
10960Sstevel@tonic-gate 			nl2 = nl;
10970Sstevel@tonic-gate 			while (nl2) {
10980Sstevel@tonic-gate 				if (strcmp(nl2->msl_node_name, node_v[i])
10990Sstevel@tonic-gate 				    == 0) {
11000Sstevel@tonic-gate 					nr->nr_nodeid = nl2->msl_node_id;
11010Sstevel@tonic-gate 					break;
11020Sstevel@tonic-gate 				}
11030Sstevel@tonic-gate 				nl2 = nl2->next;
11040Sstevel@tonic-gate 			}
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 			(void) strcpy(nr->nr_nodename, node_v[i]);
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 			/*
11090Sstevel@tonic-gate 			 * When a node is added to a MN diskset, set the
11100Sstevel@tonic-gate 			 * nodeid of this node in the md_set structure
11110Sstevel@tonic-gate 			 * in the kernel.
11120Sstevel@tonic-gate 			 */
11130Sstevel@tonic-gate 			if (strcmp(nr->nr_nodename, mynode()) == 0) {
11140Sstevel@tonic-gate 				(void) memset(&snp, 0, sizeof (snp));
11150Sstevel@tonic-gate 				snp.sn_nodeid = nr->nr_nodeid;
11160Sstevel@tonic-gate 				snp.sn_setno = mnsr->sr_setno;
11170Sstevel@tonic-gate 				if (metaioctl(MD_MN_SET_NODEID, &snp,
11180Sstevel@tonic-gate 				    &snp.sn_mde, NULL) != 0) {
11190Sstevel@tonic-gate 					(void) mdstealerror(ep, &snp.sn_mde);
11200Sstevel@tonic-gate 					meta_free_nodelist(nl);
11210Sstevel@tonic-gate 					free_sr(sr);
11220Sstevel@tonic-gate 					return;
11230Sstevel@tonic-gate 				}
11240Sstevel@tonic-gate 			}
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 			/* Link the node records and fill in in-core data */
11270Sstevel@tonic-gate 			mnnr_cache_add(mnsr, nr);
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST,
11300Sstevel@tonic-gate 				mnsr->sr_setno, nr->nr_nodeid);
11310Sstevel@tonic-gate 		} else {
11320Sstevel@tonic-gate 			for (j = 0; j < MD_MAXSIDES; j++) {
11330Sstevel@tonic-gate 				if (sr->sr_nodes[j][0] != '\0')
11340Sstevel@tonic-gate 					continue;
11350Sstevel@tonic-gate 				(void) strcpy(sr->sr_nodes[j], node_v[i]);
11360Sstevel@tonic-gate 				SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD,
11370Sstevel@tonic-gate 				    SVM_TAG_HOST, sr->sr_setno, j);
11380Sstevel@tonic-gate 				break;
11390Sstevel@tonic-gate 			}
11400Sstevel@tonic-gate 		}
11410Sstevel@tonic-gate 	}
11420Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
11430Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
11440Sstevel@tonic-gate 		meta_free_nodelist(nl);
11450Sstevel@tonic-gate 	}
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
11520Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
11530Sstevel@tonic-gate 		req.ur_size = sizeof (*mnsr);
11540Sstevel@tonic-gate 	} else {
11550Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
11560Sstevel@tonic-gate 	}
11570Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
11580Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
11590Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
11600Sstevel@tonic-gate 		free_sr(sr);
11610Sstevel@tonic-gate 		return;
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	free_sr(sr);
11670Sstevel@tonic-gate }
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate /*
11700Sstevel@tonic-gate  * add 1 or more hosts to a set.
11710Sstevel@tonic-gate  */
11720Sstevel@tonic-gate bool_t
11730Sstevel@tonic-gate mdrpc_addhosts_common(
11740Sstevel@tonic-gate 	mdrpc_host_args		*args,
11750Sstevel@tonic-gate 	mdrpc_generic_res	*res,
11760Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
11770Sstevel@tonic-gate 	int			version		/* RPC version */
11780Sstevel@tonic-gate )
11790Sstevel@tonic-gate {
11800Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
11810Sstevel@tonic-gate 	int			err;
11820Sstevel@tonic-gate 	int			op_mode = W_OK;
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	/* setup, check permissions */
11850Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
11860Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
11870Sstevel@tonic-gate 		return (FALSE);
11880Sstevel@tonic-gate 	else if (err != 0)
11890Sstevel@tonic-gate 		return (TRUE);
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
11920Sstevel@tonic-gate 		return (TRUE);
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 	/* doit */
11950Sstevel@tonic-gate 	addhosts(args->sp->setname, args->hosts.hosts_len,
11960Sstevel@tonic-gate 	    args->hosts.hosts_val, version, ep);
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate 	err = svc_fini(ep);
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	return (TRUE);
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate bool_t
12040Sstevel@tonic-gate mdrpc_addhosts_1_svc(
12050Sstevel@tonic-gate 	mdrpc_host_args		*args,
12060Sstevel@tonic-gate 	mdrpc_generic_res	*res,
12070Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
12080Sstevel@tonic-gate )
12090Sstevel@tonic-gate {
12100Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
12110Sstevel@tonic-gate 	return (mdrpc_addhosts_common(args, res, rqstp, METAD_VERSION));
12120Sstevel@tonic-gate }
12130Sstevel@tonic-gate 
12140Sstevel@tonic-gate bool_t
12150Sstevel@tonic-gate mdrpc_addhosts_2_svc(
12160Sstevel@tonic-gate 	mdrpc_host_2_args	*args,
12170Sstevel@tonic-gate 	mdrpc_generic_res	*res,
12180Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
12190Sstevel@tonic-gate )
12200Sstevel@tonic-gate {
12210Sstevel@tonic-gate 	switch (args->rev) {
12220Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
12230Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
12240Sstevel@tonic-gate 		return (mdrpc_addhosts_common(
12250Sstevel@tonic-gate 		    &args->mdrpc_host_2_args_u.rev1, res,
12260Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
12270Sstevel@tonic-gate 	    default:
12280Sstevel@tonic-gate 		return (FALSE);
12290Sstevel@tonic-gate 	}
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate static void
12330Sstevel@tonic-gate createset(
12340Sstevel@tonic-gate 	mdsetname_t		*sp,
12350Sstevel@tonic-gate 	md_node_nm_arr_t	nodes,
12360Sstevel@tonic-gate 	md_timeval32_t		timestamp,
12370Sstevel@tonic-gate 	ulong_t			genid,
12380Sstevel@tonic-gate 	md_error_t		*ep
12390Sstevel@tonic-gate )
12400Sstevel@tonic-gate {
12410Sstevel@tonic-gate 	mddb_userreq_t		req;
12420Sstevel@tonic-gate 	md_set_record		*sr;
12430Sstevel@tonic-gate 	int			i;
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
12460Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_CREATE, 0);
12470Sstevel@tonic-gate 	req.ur_size = sizeof (*sr);
12480Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
12490Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
12500Sstevel@tonic-gate 		return;
12510Sstevel@tonic-gate 	}
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	sr = Zalloc(sizeof (*sr));
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	sr->sr_selfid = req.ur_recid;
12560Sstevel@tonic-gate 	sr->sr_setno = sp->setno;
12570Sstevel@tonic-gate 	(void) strcpy(sr->sr_setname, sp->setname);
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
12600Sstevel@tonic-gate 	    NODEV64);
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	(void) meta_smf_enable(META_SMF_DISKSET, NULL);
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 	for (i = 0; i < MD_MAXSIDES; i++) {
12650Sstevel@tonic-gate 		(void) strcpy(sr->sr_nodes[i], nodes[i]);
12660Sstevel@tonic-gate 		/* Skip empty slots */
12670Sstevel@tonic-gate 		if (sr->sr_nodes[i][0] == '\0')
12680Sstevel@tonic-gate 			continue;
12690Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
12700Sstevel@tonic-gate 		    i);
12710Sstevel@tonic-gate 	}
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	sr->sr_ctime = timestamp;
12740Sstevel@tonic-gate 	sr->sr_genid = genid;
12750Sstevel@tonic-gate 	sr->sr_revision = MD_SET_RECORD_REVISION;
12760Sstevel@tonic-gate 	sr->sr_flags |= MD_SR_ADD;
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	sr->sr_mhiargs = defmhiargs;
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	sr_cache_add(sr);
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate static void
12860Sstevel@tonic-gate mncreateset(
12870Sstevel@tonic-gate 	mdsetname_t		*sp,
12880Sstevel@tonic-gate 	md_mnnode_desc		*nodelist,
12890Sstevel@tonic-gate 	md_timeval32_t		timestamp,
12900Sstevel@tonic-gate 	ulong_t			genid,
12910Sstevel@tonic-gate 	md_node_nm_t		master_nodenm,
12920Sstevel@tonic-gate 	int			master_nodeid,
12930Sstevel@tonic-gate 	md_error_t		*ep
12940Sstevel@tonic-gate )
12950Sstevel@tonic-gate {
12960Sstevel@tonic-gate 	mddb_userreq_t			req;
12970Sstevel@tonic-gate 	md_mnset_record			*mnsr;
12980Sstevel@tonic-gate 	md_mnnode_record		*nr;
12990Sstevel@tonic-gate 	md_mnnode_desc			*nd;
13000Sstevel@tonic-gate 	mddb_set_node_params_t		snp;
13010Sstevel@tonic-gate 	int				nodecnt;
13020Sstevel@tonic-gate 	mndiskset_membershiplist_t	*nl;
13030Sstevel@tonic-gate 
13040Sstevel@tonic-gate 	/*
13050Sstevel@tonic-gate 	 * Validate that nodes in set being created are in the
13060Sstevel@tonic-gate 	 * membership list on THIS node.
13070Sstevel@tonic-gate 	 * Initiating node has verified that nodes are in membership
13080Sstevel@tonic-gate 	 * list on the initiating node.
13090Sstevel@tonic-gate 	 * Get membershiplist from API routine.  If there's
13100Sstevel@tonic-gate 	 * an error, fail to add set and pass back error.
13110Sstevel@tonic-gate 	 */
13120Sstevel@tonic-gate 	if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
13130Sstevel@tonic-gate 		return;
13140Sstevel@tonic-gate 	}
13150Sstevel@tonic-gate 	/* Verify that all nodes are in member list */
13160Sstevel@tonic-gate 	nd = nodelist;
13170Sstevel@tonic-gate 	while (nd) {
13180Sstevel@tonic-gate 		/*
13190Sstevel@tonic-gate 		 * If node in list isn't a member of the membership,
13200Sstevel@tonic-gate 		 * just return error.
13210Sstevel@tonic-gate 		 */
13220Sstevel@tonic-gate 		if (meta_is_member(nd->nd_nodename, 0, nl) == 0) {
13230Sstevel@tonic-gate 			meta_free_nodelist(nl);
13240Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
13250Sstevel@tonic-gate 			    sp->setno, nd->nd_nodename, NULL, sp->setname);
13260Sstevel@tonic-gate 			return;
13270Sstevel@tonic-gate 		}
13280Sstevel@tonic-gate 		nd = nd->nd_next;
13290Sstevel@tonic-gate 	}
13300Sstevel@tonic-gate 	meta_free_nodelist(nl);
13310Sstevel@tonic-gate 
13320Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
13330Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_CREATE, 0);
13340Sstevel@tonic-gate 	req.ur_size = sizeof (*mnsr);
13350Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
13360Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
13370Sstevel@tonic-gate 		return;
13380Sstevel@tonic-gate 	}
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	mnsr = Zalloc(sizeof (*mnsr));
13410Sstevel@tonic-gate 	mnsr->sr_selfid = req.ur_recid;
13420Sstevel@tonic-gate 	mnsr->sr_setno = sp->setno;
13430Sstevel@tonic-gate 	(void) strlcpy(mnsr->sr_setname, sp->setname, MD_MAX_SETNAME);
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
13460Sstevel@tonic-gate 	    NODEV64);
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate 	(void) meta_smf_enable(META_SMF_DISKSET | META_SMF_MN_DISKSET, NULL);
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	nd = nodelist;
13510Sstevel@tonic-gate 	while (nd) {
13520Sstevel@tonic-gate 		/* Create the node record */
13530Sstevel@tonic-gate 		(void) memset(&req, 0, sizeof (req));
13540Sstevel@tonic-gate 		METAD_SETUP_NR(MD_DB_CREATE, 0);
13550Sstevel@tonic-gate 		req.ur_size = sizeof (*nr);
13560Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
13570Sstevel@tonic-gate 			/* Frees mnsr and any alloc'd node records */
13580Sstevel@tonic-gate 			free_sr((struct md_set_record *)mnsr);
13590Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
13600Sstevel@tonic-gate 			return;
13610Sstevel@tonic-gate 		}
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 		nr = Zalloc(sizeof (*nr));
13640Sstevel@tonic-gate 		nr->nr_revision = MD_MNNODE_RECORD_REVISION;
13650Sstevel@tonic-gate 		nr->nr_selfid = req.ur_recid;
13660Sstevel@tonic-gate 		nr->nr_ctime = timestamp;
13670Sstevel@tonic-gate 		nr->nr_genid = genid;
13680Sstevel@tonic-gate 		nr->nr_nodeid = nd->nd_nodeid;
13690Sstevel@tonic-gate 		nr->nr_flags = nd->nd_flags;
13700Sstevel@tonic-gate 		(void) strlcpy(nr->nr_nodename, nd->nd_nodename,
13710Sstevel@tonic-gate 			MD_MAX_NODENAME);
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 		/* Link the node records and fill in in-core data */
13740Sstevel@tonic-gate 		mnnr_cache_add(mnsr, nr);
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
13770Sstevel@tonic-gate 		    nr->nr_nodeid);
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 		nd = nd->nd_next;
13800Sstevel@tonic-gate 	}
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 	/*
13830Sstevel@tonic-gate 	 * For backward compatibility, fill in mynode name
13840Sstevel@tonic-gate 	 * as the only name in the sr_nodes array.  This
13850Sstevel@tonic-gate 	 * allows the pre-MNdiskset code to see that there
13860Sstevel@tonic-gate 	 * is a node in this diskset.  This will keep the
13870Sstevel@tonic-gate 	 * pre-MNdiskset code from removing this set.
13880Sstevel@tonic-gate 	 */
13890Sstevel@tonic-gate 	(void) strlcpy(mnsr->sr_nodes_bw_compat[0], mynode(), MD_MAX_NODENAME);
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	mnsr->sr_ctime = timestamp;
13920Sstevel@tonic-gate 	mnsr->sr_genid = genid;
13930Sstevel@tonic-gate 	mnsr->sr_revision = MD_SET_RECORD_REVISION;
13940Sstevel@tonic-gate 	mnsr->sr_flags |= MD_SR_ADD;
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	mnsr->sr_flags |= MD_SR_MN;
13970Sstevel@tonic-gate 	strcpy(mnsr->sr_master_nodenm, master_nodenm);
13980Sstevel@tonic-gate 	mnsr->sr_master_nodeid = master_nodeid;
13990Sstevel@tonic-gate 
14000Sstevel@tonic-gate 	mnsr->sr_mhiargs = defmhiargs;
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	sr_cache_add((struct md_set_record *)mnsr);
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	commitset((struct md_set_record *)mnsr, TRUE, ep);
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	/*
14070Sstevel@tonic-gate 	 * When a set is created for the first time, the nodelist
14080Sstevel@tonic-gate 	 * will contain this node.
14090Sstevel@tonic-gate 	 * When a node is just being added to a set, the nodelist
14100Sstevel@tonic-gate 	 * will not contain this node.  This node is added to the
14110Sstevel@tonic-gate 	 * set structure with a later call to addhosts.
14120Sstevel@tonic-gate 	 *
14130Sstevel@tonic-gate 	 * So, if the nodelist contains an entry for this node
14140Sstevel@tonic-gate 	 * then set the nodeid of this node in the md_set kernel
14150Sstevel@tonic-gate 	 * data structure.
14160Sstevel@tonic-gate 	 */
14170Sstevel@tonic-gate 	nd = nodelist;
14180Sstevel@tonic-gate 	while (nd) {
14190Sstevel@tonic-gate 		if (strcmp(nd->nd_nodename, mynode()) == 0) {
14200Sstevel@tonic-gate 			break;
14210Sstevel@tonic-gate 		}
14220Sstevel@tonic-gate 		nd = nd->nd_next;
14230Sstevel@tonic-gate 	}
14240Sstevel@tonic-gate 	if (nd) {
14250Sstevel@tonic-gate 		(void) memset(&snp, 0, sizeof (snp));
14260Sstevel@tonic-gate 		snp.sn_nodeid = nd->nd_nodeid;
14270Sstevel@tonic-gate 		snp.sn_setno = sp->setno;
14280Sstevel@tonic-gate 		if (metaioctl(MD_MN_SET_NODEID, &snp, &snp.sn_mde, NULL) != 0) {
14290Sstevel@tonic-gate 			(void) mdstealerror(ep, &snp.sn_mde);
14300Sstevel@tonic-gate 			return;
14310Sstevel@tonic-gate 		}
14320Sstevel@tonic-gate 	}
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate /*
14360Sstevel@tonic-gate  * create a set on a host
14370Sstevel@tonic-gate  */
14380Sstevel@tonic-gate bool_t
14390Sstevel@tonic-gate mdrpc_createset_common(
14400Sstevel@tonic-gate 	mdrpc_createset_args	*args,
14410Sstevel@tonic-gate 	mdrpc_generic_res	*res,
14420Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
14430Sstevel@tonic-gate )
14440Sstevel@tonic-gate {
14450Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
14460Sstevel@tonic-gate 	char			stringbuf1[MAXPATHLEN];
14470Sstevel@tonic-gate 	char			stringbuf2[MAXPATHLEN];
14480Sstevel@tonic-gate 	int			err;
14490Sstevel@tonic-gate 	int			op_mode = W_OK;
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	/* setup, check permissions */
14520Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
14530Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
14540Sstevel@tonic-gate 		return (FALSE);
14550Sstevel@tonic-gate 	else if (err != 0)
14560Sstevel@tonic-gate 		return (TRUE);
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
14590Sstevel@tonic-gate 		return (TRUE);
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate 	/* create the arguments for the symlink() and unlink() calls */
14620Sstevel@tonic-gate 	(void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
14630Sstevel@tonic-gate 	    args->sp->setname);
14640Sstevel@tonic-gate 	(void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
14650Sstevel@tonic-gate 	    args->sp->setno);
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 	/*
14680Sstevel@tonic-gate 	 * Since we already verified that the setname was OK, make sure to
14690Sstevel@tonic-gate 	 * cleanup before proceeding.
14700Sstevel@tonic-gate 	 */
14710Sstevel@tonic-gate 	if (unlink(stringbuf2) == -1) {
14720Sstevel@tonic-gate 		if (errno != ENOENT) {
14730Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, stringbuf2);
14740Sstevel@tonic-gate 			return (TRUE);
14750Sstevel@tonic-gate 		}
14760Sstevel@tonic-gate 	}
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate 	/* create the set */
14790Sstevel@tonic-gate 	createset(args->sp, args->nodes, args->timestamp, args->genid, ep);
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	if (! mdisok(ep))
14820Sstevel@tonic-gate 		return (TRUE);
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate 	/* create the symlink */
14850Sstevel@tonic-gate 	if (symlink(stringbuf1, stringbuf2) == -1)
14860Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, stringbuf2);
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	err = svc_fini(ep);
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	return (TRUE);
14910Sstevel@tonic-gate }
14920Sstevel@tonic-gate 
14930Sstevel@tonic-gate bool_t
14940Sstevel@tonic-gate mdrpc_createset_1_svc(
14950Sstevel@tonic-gate 	mdrpc_createset_args	*args,
14960Sstevel@tonic-gate 	mdrpc_generic_res	*res,
14970Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
14980Sstevel@tonic-gate )
14990Sstevel@tonic-gate {
15000Sstevel@tonic-gate 	return (mdrpc_createset_common(args, res, rqstp));
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate bool_t
15040Sstevel@tonic-gate mdrpc_createset_2_svc(
15050Sstevel@tonic-gate 	mdrpc_createset_2_args	*args,
15060Sstevel@tonic-gate 	mdrpc_generic_res	*res,
15070Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
15080Sstevel@tonic-gate )
15090Sstevel@tonic-gate {
15100Sstevel@tonic-gate 	switch (args->rev) {
15110Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
15120Sstevel@tonic-gate 		return (mdrpc_createset_common(
15130Sstevel@tonic-gate 		    &args->mdrpc_createset_2_args_u.rev1, res, rqstp));
15140Sstevel@tonic-gate 	    default:
15150Sstevel@tonic-gate 		return (FALSE);
15160Sstevel@tonic-gate 	}
15170Sstevel@tonic-gate }
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate bool_t
15200Sstevel@tonic-gate mdrpc_mncreateset_common(
15210Sstevel@tonic-gate 	mdrpc_mncreateset_args	*args,
15220Sstevel@tonic-gate 	mdrpc_generic_res	*res,
15230Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
15240Sstevel@tonic-gate )
15250Sstevel@tonic-gate {
15260Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
15270Sstevel@tonic-gate 	char			stringbuf1[MAXPATHLEN];
15280Sstevel@tonic-gate 	char			stringbuf2[MAXPATHLEN];
15290Sstevel@tonic-gate 	int			err;
15300Sstevel@tonic-gate 	int			op_mode = W_OK;
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate 	/* setup, check permissions */
15330Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
15340Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
15350Sstevel@tonic-gate 		return (FALSE);
15360Sstevel@tonic-gate 	else if (err != 0)
15370Sstevel@tonic-gate 		return (TRUE);
15380Sstevel@tonic-gate 
15390Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
15400Sstevel@tonic-gate 		return (TRUE);
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	/* create the arguments for the symlink() and unlink() calls */
15430Sstevel@tonic-gate 	(void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
15440Sstevel@tonic-gate 	    args->sp->setname);
15450Sstevel@tonic-gate 	(void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
15460Sstevel@tonic-gate 	    args->sp->setno);
15470Sstevel@tonic-gate 
15480Sstevel@tonic-gate 	/*
15490Sstevel@tonic-gate 	 * Since we already verified that the setname was OK, make sure to
15500Sstevel@tonic-gate 	 * cleanup before proceeding.
15510Sstevel@tonic-gate 	 */
15520Sstevel@tonic-gate 	if (unlink(stringbuf2) == -1) {
15530Sstevel@tonic-gate 		if (errno != ENOENT) {
15540Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, stringbuf2);
15550Sstevel@tonic-gate 			return (TRUE);
15560Sstevel@tonic-gate 		}
15570Sstevel@tonic-gate 	}
15580Sstevel@tonic-gate 
15590Sstevel@tonic-gate 	/* create the set */
15600Sstevel@tonic-gate 	mncreateset(args->sp, args->nodelist, args->timestamp, args->genid,
15610Sstevel@tonic-gate 		    args->master_nodenm, args->master_nodeid, ep);
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 	if (! mdisok(ep)) {
15640Sstevel@tonic-gate 		return (TRUE);
15650Sstevel@tonic-gate 	}
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 	/* create the symlink */
15680Sstevel@tonic-gate 	if (symlink(stringbuf1, stringbuf2) == -1)
15690Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, stringbuf2);
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 	err = svc_fini(ep);
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	return (TRUE);
15740Sstevel@tonic-gate }
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate bool_t
15770Sstevel@tonic-gate mdrpc_mncreateset_2_svc(
15780Sstevel@tonic-gate 	mdrpc_mncreateset_2_args	*args,
15790Sstevel@tonic-gate 	mdrpc_generic_res	*res,
15800Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
15810Sstevel@tonic-gate )
15820Sstevel@tonic-gate {
15830Sstevel@tonic-gate 	switch (args->rev) {
15840Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
15850Sstevel@tonic-gate 		return (mdrpc_mncreateset_common(
15860Sstevel@tonic-gate 		    &args->mdrpc_mncreateset_2_args_u.rev1, res, rqstp));
15870Sstevel@tonic-gate 	    default:
15880Sstevel@tonic-gate 		return (FALSE);
15890Sstevel@tonic-gate 	}
15900Sstevel@tonic-gate }
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate static void
15930Sstevel@tonic-gate del_drv_sidenms(
15940Sstevel@tonic-gate 	mdsetname_t	*sp,
15950Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
15960Sstevel@tonic-gate 	md_error_t	*ep
15970Sstevel@tonic-gate )
15980Sstevel@tonic-gate {
15990Sstevel@tonic-gate 	md_set_record	*sr;
16000Sstevel@tonic-gate 	md_drive_desc	*dd, *p;
16010Sstevel@tonic-gate 	mddrivename_t	*dn;
16020Sstevel@tonic-gate 	mdsetname_t	*local_sp;
16030Sstevel@tonic-gate 	int		i;
16040Sstevel@tonic-gate 	int		rb_mode = 0;
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
16070Sstevel@tonic-gate 		return;
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
16100Sstevel@tonic-gate 		return;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
16130Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
16140Sstevel@tonic-gate 		/*
16150Sstevel@tonic-gate 		 * In the multi-node diskset, there are no diskset
16160Sstevel@tonic-gate 		 * entries in the local set for other nodes, so there's
16170Sstevel@tonic-gate 		 * nothing to do.
16180Sstevel@tonic-gate 		 */
16190Sstevel@tonic-gate 		free_sr(sr);
16200Sstevel@tonic-gate 		return;
16210Sstevel@tonic-gate 	}
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 	if ((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
16240Sstevel@tonic-gate 	    ep)) == NULL) {
16250Sstevel@tonic-gate 		if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE)) {
16260Sstevel@tonic-gate 			metaflushsetname(sp);
16270Sstevel@tonic-gate 			if (! mdisok(ep)) {
16280Sstevel@tonic-gate 				free_sr(sr);
16290Sstevel@tonic-gate 				return;
16300Sstevel@tonic-gate 			}
16310Sstevel@tonic-gate 			/* we are supposed to have drives!!!! */
16320Sstevel@tonic-gate 			assert(0);
16330Sstevel@tonic-gate 		}
16340Sstevel@tonic-gate 		rb_mode = 1;
16350Sstevel@tonic-gate 		mdclrerror(ep);
16360Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
16370Sstevel@tonic-gate 			/* Skip empty sides of the diskset */
16380Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
16390Sstevel@tonic-gate 				continue;
16400Sstevel@tonic-gate 			dd = metaget_drivedesc_sideno(sp, i,
16410Sstevel@tonic-gate 			    (MD_BASICNAME_OK | PRINT_FAST), ep);
16420Sstevel@tonic-gate 			/* Got dd, get out of loop */
16430Sstevel@tonic-gate 			if (dd != NULL)
16440Sstevel@tonic-gate 				break;
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 			/* some error occurred, get out of loop */
16470Sstevel@tonic-gate 			if (! mdisok(ep))
16480Sstevel@tonic-gate 				break;
16490Sstevel@tonic-gate 		}
16500Sstevel@tonic-gate 		/*
16510Sstevel@tonic-gate 		 * At this point, we have one of three possibilities:
16520Sstevel@tonic-gate 		 *	1) dd != NULL (we have found drives using an alternate
16530Sstevel@tonic-gate 		 *	   side.)
16540Sstevel@tonic-gate 		 *	2) dd == NULL (no drives) && mdisok(ep) : assert(0)
16550Sstevel@tonic-gate 		 *	3) dd == NULL (no drives) && ! mdisok(ep) : return
16560Sstevel@tonic-gate 		 *	   error information to caller.
16570Sstevel@tonic-gate 		 */
16580Sstevel@tonic-gate 		if (dd == NULL) {
16590Sstevel@tonic-gate 			metaflushsetname(sp);
16600Sstevel@tonic-gate 			if (! mdisok(ep)) {
16610Sstevel@tonic-gate 				free_sr(sr);
16620Sstevel@tonic-gate 				return;
16630Sstevel@tonic-gate 			}
16640Sstevel@tonic-gate 			/* we are supposed to have drives!!!! */
16650Sstevel@tonic-gate 			assert(0);
16660Sstevel@tonic-gate 		}
16670Sstevel@tonic-gate 	}
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	/*
16700Sstevel@tonic-gate 	 * Let's run through each drive descriptor, and delete the
16710Sstevel@tonic-gate 	 * sidename for all sides that are not in the sr_nodes array.
16720Sstevel@tonic-gate 	 * We will ignore errors, cause the empty side may not
16730Sstevel@tonic-gate 	 * have had any names to begin with.
16740Sstevel@tonic-gate 	 */
16750Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
16760Sstevel@tonic-gate 		dn = p->dd_dnp;
16770Sstevel@tonic-gate 
16780Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
16790Sstevel@tonic-gate 			/* Skip existing sides of the diskset */
16800Sstevel@tonic-gate 			if (!rb_mode && sr->sr_nodes[i][0] != '\0')
16810Sstevel@tonic-gate 				continue;
16820Sstevel@tonic-gate 			/* An empty side, delete the sidename */
16830Sstevel@tonic-gate 			if (del_name(local_sp, i+SKEW,
16840Sstevel@tonic-gate 			    dn->side_names_key, ep)) {
16850Sstevel@tonic-gate 				if (!mdissyserror(ep, ENOENT)) {
16860Sstevel@tonic-gate 					free_sr(sr);
16870Sstevel@tonic-gate 					return;
16880Sstevel@tonic-gate 				}
16890Sstevel@tonic-gate 				mdclrerror(ep);
16900Sstevel@tonic-gate 			}
16910Sstevel@tonic-gate 		}
16920Sstevel@tonic-gate 	}
16930Sstevel@tonic-gate 	free_sr(sr);
16940Sstevel@tonic-gate 	metaflushsetname(sp);
16950Sstevel@tonic-gate }
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate /*
16980Sstevel@tonic-gate  * delete 1 or more sidenames per drive desc, from the local namespace
16990Sstevel@tonic-gate  */
17000Sstevel@tonic-gate bool_t
17010Sstevel@tonic-gate mdrpc_del_drv_sidenms_common(
17020Sstevel@tonic-gate 	mdrpc_sp_args		*args,
17030Sstevel@tonic-gate 	mdrpc_generic_res	*res,
17040Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
17050Sstevel@tonic-gate 	int			version		/* RPC version */
17060Sstevel@tonic-gate )
17070Sstevel@tonic-gate {
17080Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
17090Sstevel@tonic-gate 	int			err;
17100Sstevel@tonic-gate 	int			op_mode = W_OK;
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate 	/* setup, check permissions */
17130Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
17140Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
17150Sstevel@tonic-gate 		return (FALSE);
17160Sstevel@tonic-gate 	else if (err != 0)
17170Sstevel@tonic-gate 		return (TRUE);
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
17200Sstevel@tonic-gate 		return (TRUE);
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	/* doit */
17230Sstevel@tonic-gate 	del_drv_sidenms(args->sp, version, ep);
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	err = svc_fini(ep);
17260Sstevel@tonic-gate 
17270Sstevel@tonic-gate 	return (TRUE);
17280Sstevel@tonic-gate }
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate bool_t
17310Sstevel@tonic-gate mdrpc_del_drv_sidenms_1_svc(
17320Sstevel@tonic-gate 	mdrpc_sp_args		*args,
17330Sstevel@tonic-gate 	mdrpc_generic_res	*res,
17340Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
17350Sstevel@tonic-gate )
17360Sstevel@tonic-gate {
17370Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
17380Sstevel@tonic-gate 	return (mdrpc_del_drv_sidenms_common(args, res, rqstp, METAD_VERSION));
17390Sstevel@tonic-gate }
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate bool_t
17420Sstevel@tonic-gate mdrpc_del_drv_sidenms_2_svc(
17430Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
17440Sstevel@tonic-gate 	mdrpc_generic_res	*res,
17450Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
17460Sstevel@tonic-gate )
17470Sstevel@tonic-gate {
17480Sstevel@tonic-gate 	switch (args->rev) {
17490Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
17500Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
17510Sstevel@tonic-gate 		return (mdrpc_del_drv_sidenms_common(
17520Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res,
17530Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
17540Sstevel@tonic-gate 	    default:
17550Sstevel@tonic-gate 		return (FALSE);
17560Sstevel@tonic-gate 	}
17570Sstevel@tonic-gate }
17580Sstevel@tonic-gate 
17590Sstevel@tonic-gate static int
17600Sstevel@tonic-gate del_sidenamelist(
17610Sstevel@tonic-gate 	md_set_record	*sr,
17620Sstevel@tonic-gate 	mddrivename_t	*dn,
17630Sstevel@tonic-gate 	md_error_t	*ep
17640Sstevel@tonic-gate )
17650Sstevel@tonic-gate {
17660Sstevel@tonic-gate 	mdsidenames_t	*sn;
17670Sstevel@tonic-gate 	mdsetname_t	*local_sp;
17680Sstevel@tonic-gate 	md_mnset_record	*mnsr;
17690Sstevel@tonic-gate 	md_mnnode_record *nr;
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
17720Sstevel@tonic-gate 		return (-1);
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 	for (sn = dn->side_names; sn != NULL; sn = sn->next)
17750Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
17760Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
17770Sstevel@tonic-gate 			/*
17780Sstevel@tonic-gate 			 * Only delete side name entries for this node
17790Sstevel@tonic-gate 			 * on a multi-node diskset.
17800Sstevel@tonic-gate 			 */
17810Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
17820Sstevel@tonic-gate 			while (nr) {
17830Sstevel@tonic-gate 				if (nr->nr_nodeid == sn->sideno) {
17840Sstevel@tonic-gate 					if (del_name(local_sp, sn->sideno,
17850Sstevel@tonic-gate 					    dn->side_names_key, ep) == -1)
17860Sstevel@tonic-gate 						mdclrerror(ep); /* ignore err */
17870Sstevel@tonic-gate 					break;
17880Sstevel@tonic-gate 				}
17890Sstevel@tonic-gate 				nr = nr->nr_next;
17900Sstevel@tonic-gate 			}
17910Sstevel@tonic-gate 		} else {
17920Sstevel@tonic-gate 			if (del_name(local_sp, sn->sideno+SKEW,
17930Sstevel@tonic-gate 			    dn->side_names_key, ep) == -1)
17940Sstevel@tonic-gate 				mdclrerror(ep);	/* ignore errors */
17950Sstevel@tonic-gate 		}
17960Sstevel@tonic-gate 
17970Sstevel@tonic-gate 	dn->side_names_key = MD_KEYBAD;
17980Sstevel@tonic-gate 	return (0);
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate static void
18020Sstevel@tonic-gate deldrvs(
18030Sstevel@tonic-gate 	char		*setname,
18040Sstevel@tonic-gate 	md_drive_desc	*dd,
18050Sstevel@tonic-gate 	md_error_t	*ep
18060Sstevel@tonic-gate )
18070Sstevel@tonic-gate {
18080Sstevel@tonic-gate 	mdsetname_t	*sp;
18090Sstevel@tonic-gate 	md_set_record	*sr;
18100Sstevel@tonic-gate 	md_drive_record	*dr;
18110Sstevel@tonic-gate 	mddb_userreq_t	req;
18120Sstevel@tonic-gate 	md_drive_desc	*p;
18130Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
18140Sstevel@tonic-gate 	side_t		sideno;
18150Sstevel@tonic-gate 	int		i;
18160Sstevel@tonic-gate 	int		rb_mode = 0;
18170Sstevel@tonic-gate 	mdname_t	*np;
18180Sstevel@tonic-gate 	md_dev64_t	dev;
18190Sstevel@tonic-gate 	md_error_t	xep = mdnullerror;
18200Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
18210Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
18220Sstevel@tonic-gate 	int		devid_same = -1;
18230Sstevel@tonic-gate 	int		using_devid = 0;
18240Sstevel@tonic-gate 	md_mnnode_record	*nr;
18250Sstevel@tonic-gate 	md_mnset_record		*mnsr;
18260Sstevel@tonic-gate 
18270Sstevel@tonic-gate 	if ((sp = metasetname(setname, ep)) == NULL)
18280Sstevel@tonic-gate 		return;
18290Sstevel@tonic-gate 
18300Sstevel@tonic-gate 	metaflushsetname(sp);
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate 	if ((sideno = getmyside(sp, ep)) == MD_SIDEWILD) {
18330Sstevel@tonic-gate 		if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE))
18340Sstevel@tonic-gate 			return;
18350Sstevel@tonic-gate 		mdclrerror(ep);
18360Sstevel@tonic-gate 		/*
18370Sstevel@tonic-gate 		 * The set record is incomplete, so we need to make note
18380Sstevel@tonic-gate 		 * here so that we can do some special handling later.
18390Sstevel@tonic-gate 		 */
18400Sstevel@tonic-gate 		rb_mode = 1;
18410Sstevel@tonic-gate 	}
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
18440Sstevel@tonic-gate 		return;
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
18470Sstevel@tonic-gate 		return;
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	/*
18500Sstevel@tonic-gate 	 * The system is either all devid or all
18510Sstevel@tonic-gate 	 * non-devid so we determine this by looking
18520Sstevel@tonic-gate 	 * at the first item in the list.
18530Sstevel@tonic-gate 	 *
18540Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
18550Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
18560Sstevel@tonic-gate 	 * before set the using_devid.
18570Sstevel@tonic-gate 	 */
18580Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
18590Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
18600Sstevel@tonic-gate 		using_devid = 1;
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
18630Sstevel@tonic-gate 		dn = p->dd_dnp;
18640Sstevel@tonic-gate 		devid_remote = NULL;
18650Sstevel@tonic-gate 
18660Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
18670Sstevel@tonic-gate 		    using_devid) {
18680Sstevel@tonic-gate 			/*
18690Sstevel@tonic-gate 			 * We have a devid so use it
18700Sstevel@tonic-gate 			 */
18710Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
18720Sstevel@tonic-gate 		}
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
18750Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
18760Sstevel@tonic-gate 			/* something went really wrong. Can't process */
18770Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
18780Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
18790Sstevel@tonic-gate 			return;
18800Sstevel@tonic-gate 		}
18810Sstevel@tonic-gate 
18820Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
18830Sstevel@tonic-gate 			devid_same = -1;
18840Sstevel@tonic-gate 
18850Sstevel@tonic-gate 			if (! rb_mode) {
18860Sstevel@tonic-gate 				dn1 = metadrivename_withdrkey(sp, sideno,
18870Sstevel@tonic-gate 				    dr->dr_key, MD_BASICNAME_OK, ep);
18880Sstevel@tonic-gate 				if (dn1 == NULL) {
18890Sstevel@tonic-gate 					free_sr(sr);
18900Sstevel@tonic-gate 					if (devid_remote)
18910Sstevel@tonic-gate 						devid_free(devid_remote);
18920Sstevel@tonic-gate 					return;
18930Sstevel@tonic-gate 				}
18940Sstevel@tonic-gate 			} else {
18950Sstevel@tonic-gate 				/*
18960Sstevel@tonic-gate 				 * Handle special case here where sidenames
18970Sstevel@tonic-gate 				 * from other hosts for this drive may be
18980Sstevel@tonic-gate 				 * in the local mddb, but there is no
18990Sstevel@tonic-gate 				 * sidename entry for this host for this drive.
19000Sstevel@tonic-gate 				 * This could have happened if the node
19010Sstevel@tonic-gate 				 * panic'd between the 2 operations when
19020Sstevel@tonic-gate 				 * adding this node to the set.
19030Sstevel@tonic-gate 				 * So, delete all sidename entries for this
19040Sstevel@tonic-gate 				 * drive.
19050Sstevel@tonic-gate 				 */
19060Sstevel@tonic-gate 				if (MD_MNSET_REC(sr)) {
19070Sstevel@tonic-gate 					mnsr = (struct md_mnset_record *)sr;
19080Sstevel@tonic-gate 					nr = mnsr->sr_nodechain;
19090Sstevel@tonic-gate 					while (nr) {
19100Sstevel@tonic-gate 						/* We delete all dr sides */
19110Sstevel@tonic-gate 						dn1 = metadrivename_withdrkey(
19120Sstevel@tonic-gate 						    sp, nr->nr_nodeid,
19130Sstevel@tonic-gate 						    dr->dr_key,
19140Sstevel@tonic-gate 						    MD_BASICNAME_OK, ep);
19150Sstevel@tonic-gate 
19160Sstevel@tonic-gate 						/* if we do, get out of loop */
19170Sstevel@tonic-gate 						if (dn1 != NULL)
19180Sstevel@tonic-gate 							break;
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate 						/* save error for later */
19210Sstevel@tonic-gate 						(void) mdstealerror(&xep, ep);
19220Sstevel@tonic-gate 
19230Sstevel@tonic-gate 						mdclrerror(ep);
19240Sstevel@tonic-gate 
19250Sstevel@tonic-gate 						nr = nr->nr_next;
19260Sstevel@tonic-gate 					}
19270Sstevel@tonic-gate 				} else {
19280Sstevel@tonic-gate 					/*
19290Sstevel@tonic-gate 					 * Handle special case here
19300Sstevel@tonic-gate 					 * for traditional diskset
19310Sstevel@tonic-gate 					 */
19320Sstevel@tonic-gate 					for (i = 0; i < MD_MAXSIDES; i++) {
19330Sstevel@tonic-gate 						/* We delete all dr sides */
19340Sstevel@tonic-gate 						dn1 = metadrivename_withdrkey(
19350Sstevel@tonic-gate 						    sp, i, dr->dr_key,
19360Sstevel@tonic-gate 						    MD_BASICNAME_OK, ep);
19370Sstevel@tonic-gate 
19380Sstevel@tonic-gate 						/* if we do, get out of loop */
19390Sstevel@tonic-gate 						if (dn1 != NULL)
19400Sstevel@tonic-gate 							break;
19410Sstevel@tonic-gate 
19420Sstevel@tonic-gate 						/* save error for later */
19430Sstevel@tonic-gate 						(void) mdstealerror(&xep, ep);
19440Sstevel@tonic-gate 
19450Sstevel@tonic-gate 						mdclrerror(ep);
19460Sstevel@tonic-gate 					}
19470Sstevel@tonic-gate 				}
19480Sstevel@tonic-gate 
19490Sstevel@tonic-gate 				if (dn1 == NULL) {
19500Sstevel@tonic-gate 					(void) mdstealerror(ep, &xep);
19510Sstevel@tonic-gate 					free_sr(sr);
19520Sstevel@tonic-gate 					if (devid_remote)
19530Sstevel@tonic-gate 						devid_free(devid_remote);
19540Sstevel@tonic-gate 					return;
19550Sstevel@tonic-gate 				}
19560Sstevel@tonic-gate 
19570Sstevel@tonic-gate 				if (!using_devid)
19580Sstevel@tonic-gate 					mdclrerror(ep);
19590Sstevel@tonic-gate 			}
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
19620Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid, &devid_local,
19630Sstevel@tonic-gate 				    NULL) == 0) {
19640Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
19650Sstevel@tonic-gate 					    devid_local);
19660Sstevel@tonic-gate 					devid_free(devid_local);
19670Sstevel@tonic-gate 				}
19680Sstevel@tonic-gate 			}
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate 			/*
19710Sstevel@tonic-gate 			 * Has the required disk been found - either the devids
19720Sstevel@tonic-gate 			 * match if devid are being used or the actual name of
19730Sstevel@tonic-gate 			 * the disk matches.
19740Sstevel@tonic-gate 			 */
19750Sstevel@tonic-gate 			if ((using_devid && devid_same == 0) ||
19760Sstevel@tonic-gate 			    (!using_devid &&
19770Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)) {
19780Sstevel@tonic-gate 				uint_t	rep_slice;
19790Sstevel@tonic-gate 
19800Sstevel@tonic-gate 				dev = NODEV64;
19810Sstevel@tonic-gate 				np = NULL;
19820Sstevel@tonic-gate 				if (meta_replicaslice(dn1,
19830Sstevel@tonic-gate 				    &rep_slice, &xep) == 0) {
19840Sstevel@tonic-gate 					np = metaslicename(dn1,
19850Sstevel@tonic-gate 					    rep_slice, &xep);
19860Sstevel@tonic-gate 				}
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate 				if (np != NULL)
19890Sstevel@tonic-gate 					dev = np->dev;
19900Sstevel@tonic-gate 				else
19910Sstevel@tonic-gate 					mdclrerror(&xep);
19920Sstevel@tonic-gate 				break;
19930Sstevel@tonic-gate 			}
19940Sstevel@tonic-gate 		}
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 		if (dr) {
19970Sstevel@tonic-gate 			(void) memset(&req, 0, sizeof (req));
19980Sstevel@tonic-gate 			METAD_SETUP_DR(MD_DB_DELETE, dr->dr_selfid)
19990Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
20000Sstevel@tonic-gate 			    != 0) {
20010Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
20020Sstevel@tonic-gate 				if (devid_remote)
20030Sstevel@tonic-gate 					devid_free(devid_remote);
20040Sstevel@tonic-gate 				free_sr(sr);
20050Sstevel@tonic-gate 				return;
20060Sstevel@tonic-gate 			}
20070Sstevel@tonic-gate 
20080Sstevel@tonic-gate 			dr_cache_del(sr, dr->dr_selfid);
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate 			if (del_sidenamelist(sr, dn1, ep) == -1) {
20110Sstevel@tonic-gate 				goto out;
20120Sstevel@tonic-gate 			}
20130Sstevel@tonic-gate 
20140Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
20150Sstevel@tonic-gate 			    sr->sr_setno, dev);
20160Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
20170Sstevel@tonic-gate 			    MD_LOCAL_SET, dev);
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 			continue;
20200Sstevel@tonic-gate 		}
20210Sstevel@tonic-gate 
20220Sstevel@tonic-gate 		if (devid_remote)
20230Sstevel@tonic-gate 			devid_free(devid_remote);
20240Sstevel@tonic-gate 	}
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate out:
20270Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
20280Sstevel@tonic-gate 
20290Sstevel@tonic-gate 	free_sr(sr);
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate /*
20330Sstevel@tonic-gate  * delete 1 or more drive records from a host.
20340Sstevel@tonic-gate  */
20350Sstevel@tonic-gate bool_t
20360Sstevel@tonic-gate mdrpc_deldrvs_common(
20370Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
20380Sstevel@tonic-gate 	mdrpc_generic_res	*res,
20390Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
20400Sstevel@tonic-gate )
20410Sstevel@tonic-gate {
20420Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
20430Sstevel@tonic-gate 	int			err;
20440Sstevel@tonic-gate 	int			op_mode = W_OK;
20450Sstevel@tonic-gate 
20460Sstevel@tonic-gate 	/* setup, check permissions */
20470Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
20480Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
20490Sstevel@tonic-gate 		return (FALSE);
20500Sstevel@tonic-gate 	else if (err != 0)
20510Sstevel@tonic-gate 		return (TRUE);
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
20540Sstevel@tonic-gate 		return (TRUE);
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate 	/* doit */
20570Sstevel@tonic-gate 	deldrvs(args->sp->setname, args->drivedescs, ep);
20580Sstevel@tonic-gate 
20590Sstevel@tonic-gate 	err = svc_fini(ep);
20600Sstevel@tonic-gate 
20610Sstevel@tonic-gate 	return (TRUE);
20620Sstevel@tonic-gate }
20630Sstevel@tonic-gate 
20640Sstevel@tonic-gate /*
20650Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
20660Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
20670Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
20680Sstevel@tonic-gate  */
20690Sstevel@tonic-gate bool_t
20700Sstevel@tonic-gate mdrpc_deldrvs_1_svc(
20710Sstevel@tonic-gate 	mdrpc_drives_args	*args,
20720Sstevel@tonic-gate 	mdrpc_generic_res	*res,
20730Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
20740Sstevel@tonic-gate )
20750Sstevel@tonic-gate {
20760Sstevel@tonic-gate 	bool_t			retval;
20770Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
20780Sstevel@tonic-gate 
20790Sstevel@tonic-gate 	/* allocate memory */
20800Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
20810Sstevel@tonic-gate 
20820Sstevel@tonic-gate 	/* build args */
20830Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
20840Sstevel@tonic-gate 	v2_args.sp = args->sp;
20850Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
20860Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
20870Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
20880Sstevel@tonic-gate 	v2_args.genid = args->genid;
20890Sstevel@tonic-gate 
20900Sstevel@tonic-gate 	retval = mdrpc_deldrvs_common(&v2_args, res, rqstp);
20910Sstevel@tonic-gate 
20920Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
20930Sstevel@tonic-gate 
20940Sstevel@tonic-gate 	return (retval);
20950Sstevel@tonic-gate }
20960Sstevel@tonic-gate 
20970Sstevel@tonic-gate bool_t
20980Sstevel@tonic-gate mdrpc_deldrvs_2_svc(
20990Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
21000Sstevel@tonic-gate 	mdrpc_generic_res	*res,
21010Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
21020Sstevel@tonic-gate )
21030Sstevel@tonic-gate {
21040Sstevel@tonic-gate 	switch (args->rev) {
21050Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
21060Sstevel@tonic-gate 		return (mdrpc_deldrvs_common(
21070Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
21080Sstevel@tonic-gate 	    default:
21090Sstevel@tonic-gate 		return (FALSE);
21100Sstevel@tonic-gate 	}
21110Sstevel@tonic-gate }
21120Sstevel@tonic-gate 
21130Sstevel@tonic-gate static void
21140Sstevel@tonic-gate delhosts(
21150Sstevel@tonic-gate 	char		*setname,
21160Sstevel@tonic-gate 	int		node_c,
21170Sstevel@tonic-gate 	char		**node_v,
21180Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
21190Sstevel@tonic-gate 	md_error_t	*ep
21200Sstevel@tonic-gate )
21210Sstevel@tonic-gate {
21220Sstevel@tonic-gate 	mddb_userreq_t		req;
21230Sstevel@tonic-gate 	md_set_record		*sr;
21240Sstevel@tonic-gate 	int			i, j;
21250Sstevel@tonic-gate 	md_mnset_record		*mnsr;
21260Sstevel@tonic-gate 	md_mnnode_record	*nr;
21270Sstevel@tonic-gate 
21280Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
21290Sstevel@tonic-gate 		return;
21300Sstevel@tonic-gate 
21310Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
21320Sstevel@tonic-gate 		/* Do MN operation if rpc version supports it and if a MN set */
21330Sstevel@tonic-gate 		if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
21340Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
21350Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
21360Sstevel@tonic-gate 			while (nr) {
21370Sstevel@tonic-gate 				if (strcmp(nr->nr_nodename, node_v[i]) == 0) {
21380Sstevel@tonic-gate 					SE_NOTIFY(EC_SVM_CONFIG,
21390Sstevel@tonic-gate 						ESC_SVM_REMOVE, SVM_TAG_HOST,
21400Sstevel@tonic-gate 						sr->sr_setno, nr->nr_nodeid);
21410Sstevel@tonic-gate 					(void) memset(&req, '\0', sizeof (req));
21420Sstevel@tonic-gate 					METAD_SETUP_NR(MD_DB_DELETE,
21430Sstevel@tonic-gate 					    nr->nr_selfid);
21440Sstevel@tonic-gate 					if (metaioctl(MD_DB_USERREQ, &req,
21450Sstevel@tonic-gate 					    &req.ur_mde, NULL) != 0) {
21460Sstevel@tonic-gate 						(void) mdstealerror(ep,
21470Sstevel@tonic-gate 						    &req.ur_mde);
21480Sstevel@tonic-gate 						free_sr(sr);
21490Sstevel@tonic-gate 						return;
21500Sstevel@tonic-gate 					}
21510Sstevel@tonic-gate 					mnnr_cache_del(mnsr, nr->nr_selfid);
21520Sstevel@tonic-gate 					break;
21530Sstevel@tonic-gate 				}
21540Sstevel@tonic-gate 				nr = nr->nr_next;
21550Sstevel@tonic-gate 			}
21560Sstevel@tonic-gate 		} else {
21570Sstevel@tonic-gate 			for (j = 0; j < MD_MAXSIDES; j++) {
21580Sstevel@tonic-gate 				if (sr->sr_nodes[j][0] == '\0')
21590Sstevel@tonic-gate 					continue;
21600Sstevel@tonic-gate 				if (strcmp(sr->sr_nodes[j], node_v[i]) != 0)
21610Sstevel@tonic-gate 					continue;
21620Sstevel@tonic-gate 				(void) memset(sr->sr_nodes[j], '\0',
21630Sstevel@tonic-gate 				    sizeof (sr->sr_nodes[j]));
21640Sstevel@tonic-gate 				SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE,
21650Sstevel@tonic-gate 				    SVM_TAG_HOST, sr->sr_setno, j);
21660Sstevel@tonic-gate 				break;
21670Sstevel@tonic-gate 			}
21680Sstevel@tonic-gate 		}
21690Sstevel@tonic-gate 	}
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
21720Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
21730Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
21740Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
21750Sstevel@tonic-gate 		req.ur_size = sizeof (*mnsr);
21760Sstevel@tonic-gate 	} else {
21770Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
21780Sstevel@tonic-gate 	}
21790Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
21800Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
21810Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
21820Sstevel@tonic-gate 		free_sr(sr);
21830Sstevel@tonic-gate 		return;
21840Sstevel@tonic-gate 	}
21850Sstevel@tonic-gate 
21860Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
21870Sstevel@tonic-gate 	free_sr(sr);
21880Sstevel@tonic-gate }
21890Sstevel@tonic-gate 
21900Sstevel@tonic-gate /*
21910Sstevel@tonic-gate  * delete 1 or more a hosts from a set.
21920Sstevel@tonic-gate  */
21930Sstevel@tonic-gate bool_t
21940Sstevel@tonic-gate mdrpc_delhosts_common(
21950Sstevel@tonic-gate 	mdrpc_host_args		*args,
21960Sstevel@tonic-gate 	mdrpc_generic_res	*res,
21970Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
21980Sstevel@tonic-gate 	int			version		/* RPC version */
21990Sstevel@tonic-gate )
22000Sstevel@tonic-gate {
22010Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
22020Sstevel@tonic-gate 	int			err;
22030Sstevel@tonic-gate 	int			op_mode = W_OK;
22040Sstevel@tonic-gate 
22050Sstevel@tonic-gate 	/* setup, check permissions */
22060Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
22070Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
22080Sstevel@tonic-gate 		return (FALSE);
22090Sstevel@tonic-gate 	else if (err != 0)
22100Sstevel@tonic-gate 		return (TRUE);
22110Sstevel@tonic-gate 
22120Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
22130Sstevel@tonic-gate 		return (TRUE);
22140Sstevel@tonic-gate 
22150Sstevel@tonic-gate 	/* doit */
22160Sstevel@tonic-gate 	delhosts(args->sp->setname, args->hosts.hosts_len,
22170Sstevel@tonic-gate 	    args->hosts.hosts_val, version, ep);
22180Sstevel@tonic-gate 
22190Sstevel@tonic-gate 	err = svc_fini(ep);
22200Sstevel@tonic-gate 
22210Sstevel@tonic-gate 	return (TRUE);
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate bool_t
22250Sstevel@tonic-gate mdrpc_delhosts_1_svc(
22260Sstevel@tonic-gate 	mdrpc_host_args		*args,
22270Sstevel@tonic-gate 	mdrpc_generic_res	*res,
22280Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
22290Sstevel@tonic-gate )
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
22320Sstevel@tonic-gate 	return (mdrpc_delhosts_common(args, res, rqstp, METAD_VERSION));
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate bool_t
22360Sstevel@tonic-gate mdrpc_delhosts_2_svc(
22370Sstevel@tonic-gate 	mdrpc_host_2_args	*args,
22380Sstevel@tonic-gate 	mdrpc_generic_res	*res,
22390Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
22400Sstevel@tonic-gate )
22410Sstevel@tonic-gate {
22420Sstevel@tonic-gate 	switch (args->rev) {
22430Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
22440Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
22450Sstevel@tonic-gate 		return (mdrpc_delhosts_common(
22460Sstevel@tonic-gate 		    &args->mdrpc_host_2_args_u.rev1, res,
22470Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
22480Sstevel@tonic-gate 	    default:
22490Sstevel@tonic-gate 		return (FALSE);
22500Sstevel@tonic-gate 	}
22510Sstevel@tonic-gate }
22520Sstevel@tonic-gate 
22530Sstevel@tonic-gate /*
22540Sstevel@tonic-gate  * delete a set.
22550Sstevel@tonic-gate  */
22560Sstevel@tonic-gate bool_t
22570Sstevel@tonic-gate mdrpc_delset_common(
22580Sstevel@tonic-gate 	mdrpc_sp_args		*args,
22590Sstevel@tonic-gate 	mdrpc_generic_res	*res,
22600Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
22610Sstevel@tonic-gate )
22620Sstevel@tonic-gate {
22630Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
22640Sstevel@tonic-gate 	int			err;
22650Sstevel@tonic-gate 	int			op_mode = W_OK;
22660Sstevel@tonic-gate 
22670Sstevel@tonic-gate 	/* setup, check permissions */
22680Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
22690Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
22700Sstevel@tonic-gate 		return (FALSE);
22710Sstevel@tonic-gate 	else if (err != 0)
22720Sstevel@tonic-gate 		return (TRUE);
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
22750Sstevel@tonic-gate 		return (TRUE);
22760Sstevel@tonic-gate 
22770Sstevel@tonic-gate 	/* doit */
22780Sstevel@tonic-gate 	s_delset(args->sp->setname, ep);
22790Sstevel@tonic-gate 
22800Sstevel@tonic-gate 	err = svc_fini(ep);
22810Sstevel@tonic-gate 
22820Sstevel@tonic-gate 	return (TRUE);
22830Sstevel@tonic-gate }
22840Sstevel@tonic-gate 
22850Sstevel@tonic-gate bool_t
22860Sstevel@tonic-gate mdrpc_delset_1_svc(
22870Sstevel@tonic-gate 	mdrpc_sp_args		*args,
22880Sstevel@tonic-gate 	mdrpc_generic_res	*res,
22890Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
22900Sstevel@tonic-gate )
22910Sstevel@tonic-gate {
22920Sstevel@tonic-gate 	return (mdrpc_delset_common(args, res, rqstp));
22930Sstevel@tonic-gate }
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate bool_t
22960Sstevel@tonic-gate mdrpc_delset_2_svc(
22970Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
22980Sstevel@tonic-gate 	mdrpc_generic_res	*res,
22990Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
23000Sstevel@tonic-gate )
23010Sstevel@tonic-gate {
23020Sstevel@tonic-gate 	switch (args->rev) {
23030Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
23040Sstevel@tonic-gate 		return (mdrpc_delset_common(
23050Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
23060Sstevel@tonic-gate 	    default:
23070Sstevel@tonic-gate 		return (FALSE);
23080Sstevel@tonic-gate 	}
23090Sstevel@tonic-gate }
23100Sstevel@tonic-gate 
23110Sstevel@tonic-gate /*
23120Sstevel@tonic-gate  * return device info
23130Sstevel@tonic-gate  */
23140Sstevel@tonic-gate static void
23150Sstevel@tonic-gate devinfo(
23160Sstevel@tonic-gate 	mdsetname_t		*sp,
23170Sstevel@tonic-gate 	mddrivename_t		*dp,
23180Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
23190Sstevel@tonic-gate 	md_error_t		*ep
23200Sstevel@tonic-gate )
23210Sstevel@tonic-gate {
23220Sstevel@tonic-gate 	mdname_t		*np, *real_np;
23230Sstevel@tonic-gate 
23240Sstevel@tonic-gate 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
23250Sstevel@tonic-gate 		return;
23260Sstevel@tonic-gate 
23271623Stw21770 	if ((real_np = metaname(&sp, np->bname, LOGICAL_DEVICE, ep)) == NULL)
23280Sstevel@tonic-gate 		return;
23290Sstevel@tonic-gate 
23300Sstevel@tonic-gate 	res->dev = real_np->dev;
23310Sstevel@tonic-gate 	(void) getdevstamp(dp, (long *)&res->vtime, ep);
23320Sstevel@tonic-gate 	res->enc_devid = meta_get_devid(np->rname);
23330Sstevel@tonic-gate }
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate bool_t
23360Sstevel@tonic-gate mdrpc_devinfo_common(
23370Sstevel@tonic-gate 	mdrpc_devinfo_2_args_r1	*args,
23380Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
23390Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
23400Sstevel@tonic-gate )
23410Sstevel@tonic-gate {
23420Sstevel@tonic-gate 	int			slice;
23430Sstevel@tonic-gate 	mdname_t		*np;
23440Sstevel@tonic-gate 	mddrivename_t		*dnp = args->drivenamep;
23450Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
23460Sstevel@tonic-gate 	int			err;
23470Sstevel@tonic-gate 	int			op_mode = R_OK;
23480Sstevel@tonic-gate 
23490Sstevel@tonic-gate 	/* setup, check permissions */
23500Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
23510Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
23520Sstevel@tonic-gate 		return (FALSE);
23530Sstevel@tonic-gate 	else if (err != 0)
23540Sstevel@tonic-gate 		return (TRUE);
23550Sstevel@tonic-gate 
23560Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
23570Sstevel@tonic-gate 		return (TRUE);
23580Sstevel@tonic-gate 
23590Sstevel@tonic-gate 	/*
23600Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
23610Sstevel@tonic-gate 	 * point to the right place.
23620Sstevel@tonic-gate 	 */
23630Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
23640Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
23650Sstevel@tonic-gate 			return (TRUE);
23660Sstevel@tonic-gate 		np->drivenamep = dnp;
23670Sstevel@tonic-gate 	}
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate 	/* doit */
23700Sstevel@tonic-gate 	devinfo(args->sp, dnp, res, ep);
23710Sstevel@tonic-gate 
23720Sstevel@tonic-gate 	err = svc_fini(ep);
23730Sstevel@tonic-gate 
23740Sstevel@tonic-gate 	return (TRUE);
23750Sstevel@tonic-gate }
23760Sstevel@tonic-gate 
23770Sstevel@tonic-gate /*
23780Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
23790Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
23800Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
23810Sstevel@tonic-gate  */
23820Sstevel@tonic-gate bool_t
23830Sstevel@tonic-gate mdrpc_devinfo_1_svc(
23840Sstevel@tonic-gate 	mdrpc_devinfo_args	*args,
23850Sstevel@tonic-gate 	mdrpc_devinfo_res 	*res,
23860Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
23870Sstevel@tonic-gate )
23880Sstevel@tonic-gate {
23890Sstevel@tonic-gate 	bool_t			retval;
23900Sstevel@tonic-gate 	mdrpc_devinfo_2_args_r1	v2_args;
23910Sstevel@tonic-gate 	mdrpc_devinfo_2_res	v2_res;
23920Sstevel@tonic-gate 
23930Sstevel@tonic-gate 	/* allocate memory */
23940Sstevel@tonic-gate 	v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
23950Sstevel@tonic-gate 	v2_args.drivenamep->parts.parts_val =
23960Sstevel@tonic-gate 	    Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
23970Sstevel@tonic-gate 
23980Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
23990Sstevel@tonic-gate 	meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
24000Sstevel@tonic-gate 	retval = mdrpc_devinfo_common(&v2_args, &v2_res, rqstp);
24010Sstevel@tonic-gate 
24020Sstevel@tonic-gate 	/*
24030Sstevel@tonic-gate 	 * Fill in the result appropriately.
24040Sstevel@tonic-gate 	 * Since dev_t's for version 2 are 64-bit,
24050Sstevel@tonic-gate 	 * we need to convert them to 32-bit for version 1.
24060Sstevel@tonic-gate 	 */
24070Sstevel@tonic-gate 	res->dev = meta_cmpldev(v2_res.dev);
24080Sstevel@tonic-gate 	res->vtime = v2_res.vtime;
24090Sstevel@tonic-gate 	res->status = v2_res.status;
24100Sstevel@tonic-gate 
24110Sstevel@tonic-gate 	free(v2_args.drivenamep);
24120Sstevel@tonic-gate 	free(v2_args.drivenamep->parts.parts_val);
24130Sstevel@tonic-gate 
24140Sstevel@tonic-gate 	return (retval);
24150Sstevel@tonic-gate }
24160Sstevel@tonic-gate 
24170Sstevel@tonic-gate bool_t
24180Sstevel@tonic-gate mdrpc_devinfo_2_svc(
24190Sstevel@tonic-gate 	mdrpc_devinfo_2_args	*args,
24200Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
24210Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
24220Sstevel@tonic-gate )
24230Sstevel@tonic-gate {
24240Sstevel@tonic-gate 	switch (args->rev) {
24250Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
24260Sstevel@tonic-gate 		return (mdrpc_devinfo_common(
24270Sstevel@tonic-gate 		    &args->mdrpc_devinfo_2_args_u.rev1, res, rqstp));
24280Sstevel@tonic-gate 	    default:
24290Sstevel@tonic-gate 		return (FALSE);
24300Sstevel@tonic-gate 	}
24310Sstevel@tonic-gate }
24320Sstevel@tonic-gate 
24330Sstevel@tonic-gate /*
24340Sstevel@tonic-gate  * return device id
24350Sstevel@tonic-gate  */
24360Sstevel@tonic-gate static void
24370Sstevel@tonic-gate mdrpc_get_devid(
24380Sstevel@tonic-gate 	mdsetname_t		*sp,
24390Sstevel@tonic-gate 	mddrivename_t		*dp,
24400Sstevel@tonic-gate 	mdrpc_devid_res 	*res,
24410Sstevel@tonic-gate 	md_error_t		*ep
24420Sstevel@tonic-gate )
24430Sstevel@tonic-gate {
24440Sstevel@tonic-gate 	mdname_t	*np;
24450Sstevel@tonic-gate 
24460Sstevel@tonic-gate 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
24470Sstevel@tonic-gate 		return;
24480Sstevel@tonic-gate 
24491623Stw21770 	if (metaname(&sp, np->bname, LOGICAL_DEVICE, ep) == NULL)
24500Sstevel@tonic-gate 		return;
24510Sstevel@tonic-gate 
24520Sstevel@tonic-gate 	res->enc_devid = meta_get_devid(np->rname);
24530Sstevel@tonic-gate }
24540Sstevel@tonic-gate 
24550Sstevel@tonic-gate bool_t
24560Sstevel@tonic-gate mdrpc_devid_2_svc(
24570Sstevel@tonic-gate 	mdrpc_devid_2_args	*args,
24580Sstevel@tonic-gate 	mdrpc_devid_res 	*res,
24590Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
24600Sstevel@tonic-gate )
24610Sstevel@tonic-gate {
24620Sstevel@tonic-gate 	int			slice;
24630Sstevel@tonic-gate 	mdname_t		*np;
24640Sstevel@tonic-gate 	mddrivename_t		*dnp;
24650Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
24660Sstevel@tonic-gate 	int			err;
24670Sstevel@tonic-gate 	int			op_mode = R_OK;
24680Sstevel@tonic-gate 
24690Sstevel@tonic-gate 	switch (args->rev) {
24700Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
24710Sstevel@tonic-gate 		dnp = (&(args->mdrpc_devid_2_args_u.rev1))->drivenamep;
24720Sstevel@tonic-gate 		break;
24730Sstevel@tonic-gate 	    default:
24740Sstevel@tonic-gate 		return (FALSE);
24750Sstevel@tonic-gate 	}
24760Sstevel@tonic-gate 
24770Sstevel@tonic-gate 	/* setup, check permissions */
24780Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
24790Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
24800Sstevel@tonic-gate 		return (FALSE);
24810Sstevel@tonic-gate 	else if (err != 0)
24820Sstevel@tonic-gate 		return (TRUE);
24830Sstevel@tonic-gate 
24840Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
24850Sstevel@tonic-gate 		return (TRUE);
24860Sstevel@tonic-gate 
24870Sstevel@tonic-gate 	/*
24880Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
24890Sstevel@tonic-gate 	 * point to the right place.
24900Sstevel@tonic-gate 	 */
24910Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
24920Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
24930Sstevel@tonic-gate 			return (TRUE);
24940Sstevel@tonic-gate 		np->drivenamep = dnp;
24950Sstevel@tonic-gate 	}
24960Sstevel@tonic-gate 
24970Sstevel@tonic-gate 	/* doit */
24980Sstevel@tonic-gate 	mdrpc_get_devid((&(args->mdrpc_devid_2_args_u.rev1))->sp, dnp, res, ep);
24990Sstevel@tonic-gate 
25000Sstevel@tonic-gate 	err = svc_fini(ep);
25010Sstevel@tonic-gate 
25020Sstevel@tonic-gate 	return (TRUE);
25030Sstevel@tonic-gate }
25040Sstevel@tonic-gate 
25050Sstevel@tonic-gate /*
25060Sstevel@tonic-gate  * This routine should not be called for a multi-node diskset.
25070Sstevel@tonic-gate  *
25080Sstevel@tonic-gate  * The devid support is disabled for MN diskset so this routine
25090Sstevel@tonic-gate  * will not be called if the set is MN diskset.  The check has
25100Sstevel@tonic-gate  * been done early in meta_getnextside_devinfo.  However this
25110Sstevel@tonic-gate  * routine will be called when the devid support for MN set is
25120Sstevel@tonic-gate  * enabled and check is removed.
25130Sstevel@tonic-gate  */
25140Sstevel@tonic-gate bool_t
25150Sstevel@tonic-gate mdrpc_devinfo_by_devid_2_svc(
25160Sstevel@tonic-gate 	mdrpc_devidstr_args	*args,
25170Sstevel@tonic-gate 	mdrpc_devinfo_2_res	*res,
25180Sstevel@tonic-gate 	struct svc_req	  *rqstp		  /* RPC stuff */
25190Sstevel@tonic-gate )
25200Sstevel@tonic-gate {
25210Sstevel@tonic-gate 
25220Sstevel@tonic-gate 	char		*devidstr = args->enc_devid;
25230Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
25240Sstevel@tonic-gate 	ddi_devid_t	devid;
25250Sstevel@tonic-gate 	char		*minor_name = NULL;
25260Sstevel@tonic-gate 	int		ret = 0;
25270Sstevel@tonic-gate 	int		err;
25280Sstevel@tonic-gate 	devid_nmlist_t	*disklist = NULL;
25290Sstevel@tonic-gate 	int		op_mode = R_OK;
25300Sstevel@tonic-gate 	mdname_t	*np;
25310Sstevel@tonic-gate 	mdsetname_t	*sp = args->sp;
25320Sstevel@tonic-gate 
25330Sstevel@tonic-gate 	/* setup, check permissions */
25340Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
25350Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
25360Sstevel@tonic-gate 		return (FALSE);
25370Sstevel@tonic-gate 	else if (err != 0)
25380Sstevel@tonic-gate 		return (TRUE);
25390Sstevel@tonic-gate 
25400Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
25410Sstevel@tonic-gate 		return (TRUE);
25420Sstevel@tonic-gate 
25430Sstevel@tonic-gate 	if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
25440Sstevel@tonic-gate 		return (TRUE);
25450Sstevel@tonic-gate 
25460Sstevel@tonic-gate 	/*
25470Sstevel@tonic-gate 	 * if we do not have a minor name then look for a character device.
25480Sstevel@tonic-gate 	 * This is because the caller (checkdrive_onnode) expects a character
25490Sstevel@tonic-gate 	 * device to be returned. The other client of this interface is
25500Sstevel@tonic-gate 	 * meta_getnextside_devinfo and this supplies a minor name.
25510Sstevel@tonic-gate 	 */
25520Sstevel@tonic-gate 	if (minor_name == NULL) {
25530Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid,
25540Sstevel@tonic-gate 		    DEVID_MINOR_NAME_ALL_CHR, &disklist);
25550Sstevel@tonic-gate 	} else {
25560Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
25570Sstevel@tonic-gate 		    &disklist);
25580Sstevel@tonic-gate 		devid_str_free(minor_name);
25590Sstevel@tonic-gate 	}
25600Sstevel@tonic-gate 
25610Sstevel@tonic-gate 	devid_free(devid);
25620Sstevel@tonic-gate 	if (ret != 0) {
25630Sstevel@tonic-gate 		res->dev = NODEV64;
25640Sstevel@tonic-gate 		devid_free_nmlist(disklist);
25650Sstevel@tonic-gate 		return (TRUE);
25660Sstevel@tonic-gate 	}
25670Sstevel@tonic-gate 
25681623Stw21770 	np = metaname(&sp, disklist[0].devname, LOGICAL_DEVICE, ep);
25690Sstevel@tonic-gate 	if (np != NULL) {
25700Sstevel@tonic-gate 		mdcinfo_t	*cinfo;
25710Sstevel@tonic-gate 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
25720Sstevel@tonic-gate 			res->drivername = Strdup(cinfo->dname);
25730Sstevel@tonic-gate 		}
25740Sstevel@tonic-gate 	}
25750Sstevel@tonic-gate 
25760Sstevel@tonic-gate 	res->dev = meta_expldev(disklist[0].dev);
25770Sstevel@tonic-gate 	res->devname = strdup(disklist[0].devname);
25780Sstevel@tonic-gate 
25790Sstevel@tonic-gate 	devid_free_nmlist(disklist);
25800Sstevel@tonic-gate 
25810Sstevel@tonic-gate 	err = svc_fini(ep);
25820Sstevel@tonic-gate 
25830Sstevel@tonic-gate 	return (TRUE);
25840Sstevel@tonic-gate }
25850Sstevel@tonic-gate 
25860Sstevel@tonic-gate /*
25870Sstevel@tonic-gate  * This routine should not be called for a multi-node diskset.
25880Sstevel@tonic-gate  *
25890Sstevel@tonic-gate  * The devid support is disabled for MN diskset so this routine
25900Sstevel@tonic-gate  * will not be called if the set is MN diskset.  The check has
25910Sstevel@tonic-gate  * been done early in meta_getnextside_devinfo.  However this
25920Sstevel@tonic-gate  * routine will be called when the devid support for MN set is
25930Sstevel@tonic-gate  * enabled and check is removed.
25940Sstevel@tonic-gate  *
25950Sstevel@tonic-gate  * This function will return the device info attempting to use
25960Sstevel@tonic-gate  * both the passed in devid and device name.  This is to deal
25970Sstevel@tonic-gate  * with systems that use multi-path disks but not running mpxio.
25980Sstevel@tonic-gate  * In this situation meta_deviceid_to_nmlist will return multiple
25990Sstevel@tonic-gate  * devices.  The orig_devname is used to disambiguate.
26000Sstevel@tonic-gate  *
26010Sstevel@tonic-gate  */
26020Sstevel@tonic-gate bool_t
26030Sstevel@tonic-gate mdrpc_devinfo_by_devid_name_2_svc(
26040Sstevel@tonic-gate 	mdrpc_devid_name_2_args	*args,
26050Sstevel@tonic-gate 	mdrpc_devinfo_2_res	*res,
26060Sstevel@tonic-gate 	struct svc_req	  *rqstp		  /* RPC stuff */
26070Sstevel@tonic-gate )
26080Sstevel@tonic-gate {
26090Sstevel@tonic-gate 
26100Sstevel@tonic-gate 	char		*devidstr;
26110Sstevel@tonic-gate 	char		*orig_devname;
26120Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
26130Sstevel@tonic-gate 	ddi_devid_t	devid;
26140Sstevel@tonic-gate 	char		*minor_name = NULL;
26150Sstevel@tonic-gate 	int		ret = 0;
26160Sstevel@tonic-gate 	int		err;
26170Sstevel@tonic-gate 	int		i;
26180Sstevel@tonic-gate 	devid_nmlist_t	*disklist = NULL;
26190Sstevel@tonic-gate 	int		op_mode = R_OK;
26200Sstevel@tonic-gate 	mdname_t	*np;
26210Sstevel@tonic-gate 	mdsetname_t	*sp;
26220Sstevel@tonic-gate 
26230Sstevel@tonic-gate 	switch (args->rev) {
26240Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
26250Sstevel@tonic-gate 		sp = (&(args->mdrpc_devid_name_2_args_u.rev1))->sp;
26260Sstevel@tonic-gate 		devidstr = (&(args->mdrpc_devid_name_2_args_u.rev1))->enc_devid;
26270Sstevel@tonic-gate 		orig_devname =
26280Sstevel@tonic-gate 			(&(args->mdrpc_devid_name_2_args_u.rev1))->orig_devname;
26290Sstevel@tonic-gate 		break;
26300Sstevel@tonic-gate 	    default:
26310Sstevel@tonic-gate 		return (FALSE);
26320Sstevel@tonic-gate 	}
26330Sstevel@tonic-gate 
26340Sstevel@tonic-gate 	/* setup, check permissions */
26350Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
26360Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
26370Sstevel@tonic-gate 		return (FALSE);
26380Sstevel@tonic-gate 	else if (err != 0)
26390Sstevel@tonic-gate 		return (TRUE);
26400Sstevel@tonic-gate 
26410Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
26420Sstevel@tonic-gate 		return (TRUE);
26430Sstevel@tonic-gate 
26440Sstevel@tonic-gate 	if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
26450Sstevel@tonic-gate 		return (TRUE);
26460Sstevel@tonic-gate 
26470Sstevel@tonic-gate 	/*
26480Sstevel@tonic-gate 	 * if we do not have a minor name then look for a character device.
26490Sstevel@tonic-gate 	 * This is because the caller (checkdrive_onnode) expects a character
26500Sstevel@tonic-gate 	 * device to be returned. The other client of this interface is
26510Sstevel@tonic-gate 	 * meta_getnextside_devinfo and this supplies a minor name.
26520Sstevel@tonic-gate 	 */
26530Sstevel@tonic-gate 	if (minor_name == NULL) {
26540Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid,
26550Sstevel@tonic-gate 		    DEVID_MINOR_NAME_ALL_CHR, &disklist);
26560Sstevel@tonic-gate 	} else {
26570Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
26580Sstevel@tonic-gate 		    &disklist);
26590Sstevel@tonic-gate 		devid_str_free(minor_name);
26600Sstevel@tonic-gate 	}
26610Sstevel@tonic-gate 
26620Sstevel@tonic-gate 	devid_free(devid);
26630Sstevel@tonic-gate 	if (ret != 0) {
26640Sstevel@tonic-gate 		res->dev = NODEV64;
26650Sstevel@tonic-gate 		devid_free_nmlist(disklist);
26660Sstevel@tonic-gate 		return (TRUE);
26670Sstevel@tonic-gate 	}
26680Sstevel@tonic-gate 
26690Sstevel@tonic-gate 	/* attempt to match to the device name on the originating node */
26700Sstevel@tonic-gate 	for (i = 0; disklist[i].dev != NODEV; i++) {
26710Sstevel@tonic-gate 		if (strncmp(orig_devname, disklist[i].devname,
26720Sstevel@tonic-gate 					strlen(disklist[i].devname)) == 0)
26730Sstevel@tonic-gate 			break;
26740Sstevel@tonic-gate 	}
26750Sstevel@tonic-gate 
26760Sstevel@tonic-gate 	/* if it's not found then use the first disk in the list */
26770Sstevel@tonic-gate 	if (disklist[i].dev == NODEV)
26780Sstevel@tonic-gate 		i = 0;
26790Sstevel@tonic-gate 
26801623Stw21770 	np = metaname(&sp, disklist[i].devname, LOGICAL_DEVICE, ep);
26810Sstevel@tonic-gate 	if (np != NULL) {
26820Sstevel@tonic-gate 		mdcinfo_t	*cinfo;
26830Sstevel@tonic-gate 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
26840Sstevel@tonic-gate 			res->drivername = Strdup(cinfo->dname);
26850Sstevel@tonic-gate 		}
26860Sstevel@tonic-gate 	}
26870Sstevel@tonic-gate 
26880Sstevel@tonic-gate 	res->dev = meta_expldev(disklist[i].dev);
26890Sstevel@tonic-gate 	res->devname = strdup(disklist[i].devname);
26900Sstevel@tonic-gate 
26910Sstevel@tonic-gate 	devid_free_nmlist(disklist);
26920Sstevel@tonic-gate 
26930Sstevel@tonic-gate 	err = svc_fini(ep);
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate 	return (TRUE);
26960Sstevel@tonic-gate }
26970Sstevel@tonic-gate 
26980Sstevel@tonic-gate static void
26990Sstevel@tonic-gate drvused(mdsetname_t *sp, mddrivename_t *dnp, md_error_t *ep)
27000Sstevel@tonic-gate {
27010Sstevel@tonic-gate 	if (meta_check_drivemounted(sp, dnp, ep))
27020Sstevel@tonic-gate 		return;
27030Sstevel@tonic-gate 
27040Sstevel@tonic-gate 	if (meta_check_driveswapped(sp, dnp, ep))
27050Sstevel@tonic-gate 		return;
27060Sstevel@tonic-gate 
27070Sstevel@tonic-gate 	if (meta_check_drive_inuse(metasetname(MD_LOCAL_NAME, ep), dnp,
27080Sstevel@tonic-gate 	    TRUE, ep))
27090Sstevel@tonic-gate 		return;
27100Sstevel@tonic-gate 
27110Sstevel@tonic-gate 	(void) meta_check_driveinset(sp, dnp, ep);
27120Sstevel@tonic-gate }
27130Sstevel@tonic-gate 
27140Sstevel@tonic-gate /*
27150Sstevel@tonic-gate  * determine if a device is in use.
27160Sstevel@tonic-gate  */
27170Sstevel@tonic-gate bool_t
27180Sstevel@tonic-gate mdrpc_drvused_common(
27190Sstevel@tonic-gate 	mdrpc_drvused_2_args_r1	*args,
27200Sstevel@tonic-gate 	mdrpc_generic_res	*res,
27210Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
27220Sstevel@tonic-gate )
27230Sstevel@tonic-gate {
27240Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
27250Sstevel@tonic-gate 	int			slice;
27260Sstevel@tonic-gate 	mdname_t		*np;
27270Sstevel@tonic-gate 	mddrivename_t		*dnp = args->drivenamep;
27280Sstevel@tonic-gate 	int			err;
27290Sstevel@tonic-gate 	int			op_mode = R_OK;
27300Sstevel@tonic-gate 
27310Sstevel@tonic-gate 	/* setup, check permissions */
27320Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
27330Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
27340Sstevel@tonic-gate 		return (FALSE);
27350Sstevel@tonic-gate 	else if (err != 0)
27360Sstevel@tonic-gate 		return (TRUE);
27370Sstevel@tonic-gate 
27380Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
27390Sstevel@tonic-gate 		return (TRUE);
27400Sstevel@tonic-gate 
27410Sstevel@tonic-gate 	if (dnp == NULL) {
27420Sstevel@tonic-gate 		/* no drive pointer specified */
27430Sstevel@tonic-gate 		return (TRUE);
27440Sstevel@tonic-gate 	}
27450Sstevel@tonic-gate 	/*
27460Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
27470Sstevel@tonic-gate 	 * point to the right place.
27480Sstevel@tonic-gate 	 */
27490Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
27500Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
27510Sstevel@tonic-gate 			return (TRUE);
27520Sstevel@tonic-gate 		np->drivenamep = dnp;
27530Sstevel@tonic-gate 	}
27540Sstevel@tonic-gate 
27550Sstevel@tonic-gate 	/* doit */
27560Sstevel@tonic-gate 	drvused(args->sp, dnp, ep);
27570Sstevel@tonic-gate 
27580Sstevel@tonic-gate 	err = svc_fini(ep);
27590Sstevel@tonic-gate 
27600Sstevel@tonic-gate 	return (TRUE);
27610Sstevel@tonic-gate }
27620Sstevel@tonic-gate 
27630Sstevel@tonic-gate /*
27640Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
27650Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
27660Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
27670Sstevel@tonic-gate  */
27680Sstevel@tonic-gate bool_t
27690Sstevel@tonic-gate mdrpc_drvused_1_svc(
27700Sstevel@tonic-gate 	mdrpc_drvused_args	*args,
27710Sstevel@tonic-gate 	mdrpc_generic_res	*res,
27720Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
27730Sstevel@tonic-gate )
27740Sstevel@tonic-gate {
27750Sstevel@tonic-gate 	bool_t			retval;
27760Sstevel@tonic-gate 	mdrpc_drvused_2_args_r1	v2_args;
27770Sstevel@tonic-gate 
27780Sstevel@tonic-gate 	/* allocate memory */
27790Sstevel@tonic-gate 	v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
27800Sstevel@tonic-gate 	v2_args.drivenamep->parts.parts_val =
27810Sstevel@tonic-gate 	    Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
27820Sstevel@tonic-gate 
27830Sstevel@tonic-gate 	/* build args */
27840Sstevel@tonic-gate 	v2_args.sp = args->sp;
27850Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
27860Sstevel@tonic-gate 
27870Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
27880Sstevel@tonic-gate 	meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
27890Sstevel@tonic-gate 	retval = mdrpc_drvused_common(&v2_args, res, rqstp);
27900Sstevel@tonic-gate 
27910Sstevel@tonic-gate 	free(v2_args.drivenamep);
27920Sstevel@tonic-gate 	free(v2_args.drivenamep->parts.parts_val);
27930Sstevel@tonic-gate 
27940Sstevel@tonic-gate 	return (retval);
27950Sstevel@tonic-gate }
27960Sstevel@tonic-gate 
27970Sstevel@tonic-gate bool_t
27980Sstevel@tonic-gate mdrpc_drvused_2_svc(
27990Sstevel@tonic-gate 	mdrpc_drvused_2_args	*args,
28000Sstevel@tonic-gate 	mdrpc_generic_res	*res,
28010Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
28020Sstevel@tonic-gate )
28030Sstevel@tonic-gate {
28040Sstevel@tonic-gate 	switch (args->rev) {
28050Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
28060Sstevel@tonic-gate 		return (mdrpc_drvused_common(
28070Sstevel@tonic-gate 		    &args->mdrpc_drvused_2_args_u.rev1, res, rqstp));
28080Sstevel@tonic-gate 	    default:
28090Sstevel@tonic-gate 		return (FALSE);
28100Sstevel@tonic-gate 	}
28110Sstevel@tonic-gate }
28120Sstevel@tonic-gate 
28130Sstevel@tonic-gate /*
28140Sstevel@tonic-gate  * return a set records selected by name or number.
28150Sstevel@tonic-gate  */
28160Sstevel@tonic-gate bool_t
28170Sstevel@tonic-gate mdrpc_getset_common(
28180Sstevel@tonic-gate 	mdrpc_getset_args	*args,
28190Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
28200Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
28210Sstevel@tonic-gate )
28220Sstevel@tonic-gate {
28230Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
28240Sstevel@tonic-gate 	int			err;
28250Sstevel@tonic-gate 	int			op_mode = R_OK;
28260Sstevel@tonic-gate 
28270Sstevel@tonic-gate 	/* setup, check permissions */
28280Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
28290Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
28300Sstevel@tonic-gate 		return (FALSE);
28310Sstevel@tonic-gate 	else if (err != 0)
28320Sstevel@tonic-gate 		return (TRUE);
28330Sstevel@tonic-gate 
28340Sstevel@tonic-gate 	/* Don't have a setno, so we don't check the lock */
28350Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
28360Sstevel@tonic-gate 		return (TRUE);
28370Sstevel@tonic-gate 
28380Sstevel@tonic-gate 	/* doit */
28390Sstevel@tonic-gate 	if (args->setname && *args->setname)
28400Sstevel@tonic-gate 		res->sr = setdup(getsetbyname(args->setname, ep));
28410Sstevel@tonic-gate 	else if (args->setno > 0)
28420Sstevel@tonic-gate 		res->sr = setdup(getsetbynum(args->setno, ep));
28430Sstevel@tonic-gate 	else
28440Sstevel@tonic-gate 		res->sr = NULL;
28450Sstevel@tonic-gate 
28460Sstevel@tonic-gate 	err = svc_fini(ep);
28470Sstevel@tonic-gate 
28480Sstevel@tonic-gate 	return (TRUE);
28490Sstevel@tonic-gate }
28500Sstevel@tonic-gate 
28510Sstevel@tonic-gate bool_t
28520Sstevel@tonic-gate mdrpc_getset_1_svc(
28530Sstevel@tonic-gate 	mdrpc_getset_args	*args,
28540Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
28550Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
28560Sstevel@tonic-gate )
28570Sstevel@tonic-gate {
28580Sstevel@tonic-gate 	return (mdrpc_getset_common(args, res, rqstp));
28590Sstevel@tonic-gate }
28600Sstevel@tonic-gate 
28610Sstevel@tonic-gate bool_t
28620Sstevel@tonic-gate mdrpc_getset_2_svc(
28630Sstevel@tonic-gate 	mdrpc_getset_2_args	*args,
28640Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
28650Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
28660Sstevel@tonic-gate )
28670Sstevel@tonic-gate {
28680Sstevel@tonic-gate 	switch (args->rev) {
28690Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
28700Sstevel@tonic-gate 		return (mdrpc_getset_common(
28710Sstevel@tonic-gate 		    &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
28720Sstevel@tonic-gate 	    default:
28730Sstevel@tonic-gate 		return (FALSE);
28740Sstevel@tonic-gate 	}
28750Sstevel@tonic-gate }
28760Sstevel@tonic-gate 
28770Sstevel@tonic-gate /*
28780Sstevel@tonic-gate  * return a MN set record selected by name or number.
28790Sstevel@tonic-gate  */
28800Sstevel@tonic-gate bool_t
28810Sstevel@tonic-gate mdrpc_mngetset_common(
28820Sstevel@tonic-gate 	mdrpc_getset_args	*args,
28830Sstevel@tonic-gate 	mdrpc_mngetset_res 	*res,
28840Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
28850Sstevel@tonic-gate )
28860Sstevel@tonic-gate {
28870Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
28880Sstevel@tonic-gate 	int			err;
28890Sstevel@tonic-gate 	int			op_mode = R_OK;
28900Sstevel@tonic-gate 	md_set_record		*sr = NULL;
28910Sstevel@tonic-gate 	md_mnset_record		*mnsr = NULL;
28920Sstevel@tonic-gate 
28930Sstevel@tonic-gate 	/* setup, check permissions */
28940Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
28950Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
28960Sstevel@tonic-gate 		return (FALSE);
28970Sstevel@tonic-gate 	else if (err != 0)
28980Sstevel@tonic-gate 		return (TRUE);
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate 	/* Don't have a setno, so we don't check the lock */
29010Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
29020Sstevel@tonic-gate 		return (TRUE);
29030Sstevel@tonic-gate 
29040Sstevel@tonic-gate 	/* doit */
29050Sstevel@tonic-gate 	res->mnsr = NULL;
29060Sstevel@tonic-gate 	if (args->setname && *args->setname)
29070Sstevel@tonic-gate 		sr = getsetbyname(args->setname, ep);
29080Sstevel@tonic-gate 	else if (args->setno > 0)
29090Sstevel@tonic-gate 		sr = getsetbynum(args->setno, ep);
29100Sstevel@tonic-gate 
29110Sstevel@tonic-gate 	if ((sr) && (MD_MNSET_REC(sr))) {
29120Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
29130Sstevel@tonic-gate 		res->mnsr = mnsetdup(mnsr);
29140Sstevel@tonic-gate 	}
29150Sstevel@tonic-gate 
29160Sstevel@tonic-gate 	err = svc_fini(ep);
29170Sstevel@tonic-gate 
29180Sstevel@tonic-gate 	return (TRUE);
29190Sstevel@tonic-gate }
29200Sstevel@tonic-gate 
29210Sstevel@tonic-gate bool_t
29220Sstevel@tonic-gate mdrpc_mngetset_2_svc(
29230Sstevel@tonic-gate 	mdrpc_getset_2_args	*args,
29240Sstevel@tonic-gate 	mdrpc_mngetset_res	*res,
29250Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
29260Sstevel@tonic-gate )
29270Sstevel@tonic-gate {
29280Sstevel@tonic-gate 	switch (args->rev) {
29290Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
29300Sstevel@tonic-gate 		return (mdrpc_mngetset_common(
29310Sstevel@tonic-gate 		    &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
29320Sstevel@tonic-gate 	    default:
29330Sstevel@tonic-gate 		return (FALSE);
29340Sstevel@tonic-gate 	}
29350Sstevel@tonic-gate }
29360Sstevel@tonic-gate 
29370Sstevel@tonic-gate static void
29380Sstevel@tonic-gate upd_setmaster(
29390Sstevel@tonic-gate 	mdsetname_t	*sp,
29400Sstevel@tonic-gate 	md_node_nm_t	master_nodenm,
29410Sstevel@tonic-gate 	int		master_nodeid,
29420Sstevel@tonic-gate 	md_error_t	*ep
29430Sstevel@tonic-gate )
29440Sstevel@tonic-gate {
29450Sstevel@tonic-gate 	mdsetname_t	*local_sp;
29460Sstevel@tonic-gate 	md_set_record	*sr;
29470Sstevel@tonic-gate 	md_mnset_record	*mnsr;
29480Sstevel@tonic-gate 	mddb_setmaster_config_t	sm;
29490Sstevel@tonic-gate 
29500Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
29510Sstevel@tonic-gate 		return;
29520Sstevel@tonic-gate 
29530Sstevel@tonic-gate 	metaflushsetname(local_sp);
29540Sstevel@tonic-gate 
29550Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
29560Sstevel@tonic-gate 		return;
29570Sstevel@tonic-gate 
29580Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
29590Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
29600Sstevel@tonic-gate 		strlcpy(mnsr->sr_master_nodenm, master_nodenm,
29610Sstevel@tonic-gate 			MD_MAX_NODENAME);
29620Sstevel@tonic-gate 		mnsr->sr_master_nodeid = master_nodeid;
29630Sstevel@tonic-gate 		if (master_nodeid != 0) {
29640Sstevel@tonic-gate 			(void) memset(&sm, 0, sizeof (sm));
29650Sstevel@tonic-gate 			sm.c_setno = sp->setno;
29660Sstevel@tonic-gate 			/* Use magic to help protect ioctl against attack. */
29670Sstevel@tonic-gate 			sm.c_magic = MDDB_SETMASTER_MAGIC;
29680Sstevel@tonic-gate 			if (strcmp(master_nodenm, mynode()) == 0) {
29690Sstevel@tonic-gate 				sm.c_current_host_master = 1;
29700Sstevel@tonic-gate 			} else {
29710Sstevel@tonic-gate 				sm.c_current_host_master = 0;
29720Sstevel@tonic-gate 			}
29730Sstevel@tonic-gate 			(void) metaioctl(MD_SETMASTER, &sm, &sm.c_mde, NULL);
29740Sstevel@tonic-gate 			mdclrerror(&sm.c_mde);
29750Sstevel@tonic-gate 		}
29760Sstevel@tonic-gate 	}
29770Sstevel@tonic-gate 
29780Sstevel@tonic-gate out:
29790Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
29800Sstevel@tonic-gate 	free_sr(sr);
29810Sstevel@tonic-gate }
29820Sstevel@tonic-gate 
29830Sstevel@tonic-gate /*
29840Sstevel@tonic-gate  * set the master and nodeid in node record
29850Sstevel@tonic-gate  */
29860Sstevel@tonic-gate bool_t
29870Sstevel@tonic-gate mdrpc_mnsetmaster_common(
29880Sstevel@tonic-gate 	mdrpc_mnsetmaster_args	*args,
29890Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
29900Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
29910Sstevel@tonic-gate )
29920Sstevel@tonic-gate {
29930Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
29940Sstevel@tonic-gate 	int			err;
29950Sstevel@tonic-gate 	int			op_mode = W_OK;
29960Sstevel@tonic-gate 
29970Sstevel@tonic-gate 	/* setup, check permissions */
29980Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
29990Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
30000Sstevel@tonic-gate 		return (FALSE);
30010Sstevel@tonic-gate 	else if (err != 0)
30020Sstevel@tonic-gate 		return (TRUE);
30030Sstevel@tonic-gate 
30040Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
30050Sstevel@tonic-gate 		return (TRUE);
30060Sstevel@tonic-gate 
30070Sstevel@tonic-gate 	/* doit */
30080Sstevel@tonic-gate 	upd_setmaster(args->sp, args->master_nodenm, args->master_nodeid, ep);
30090Sstevel@tonic-gate 
30100Sstevel@tonic-gate 	err = svc_fini(ep);
30110Sstevel@tonic-gate 
30120Sstevel@tonic-gate 	return (TRUE);
30130Sstevel@tonic-gate }
30140Sstevel@tonic-gate 
30150Sstevel@tonic-gate bool_t
30160Sstevel@tonic-gate mdrpc_mnsetmaster_2_svc(
30170Sstevel@tonic-gate 	mdrpc_mnsetmaster_2_args	*args,
30180Sstevel@tonic-gate 	mdrpc_generic_res	*res,
30190Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
30200Sstevel@tonic-gate )
30210Sstevel@tonic-gate {
30220Sstevel@tonic-gate 	switch (args->rev) {
30230Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
30240Sstevel@tonic-gate 		return (mdrpc_mnsetmaster_common(
30250Sstevel@tonic-gate 		    &args->mdrpc_mnsetmaster_2_args_u.rev1, res, rqstp));
30260Sstevel@tonic-gate 	    default:
30270Sstevel@tonic-gate 		return (FALSE);
30280Sstevel@tonic-gate 	}
30290Sstevel@tonic-gate }
30300Sstevel@tonic-gate 
30310Sstevel@tonic-gate /*
30320Sstevel@tonic-gate  * Join this node to the diskset.
30330Sstevel@tonic-gate  * Pass stale_flag information to snarf_set so that snarf code
30340Sstevel@tonic-gate  * can choose a STALE or non-STALE state when starting the set.
30350Sstevel@tonic-gate  * If master is STALE, any joining node will join a stale set regardless
30360Sstevel@tonic-gate  * of the number of accessible mddbs.  Also, if master is at 50%
30370Sstevel@tonic-gate  * accessible replicas and is in the TOOFEW state, don't mark newly
30380Sstevel@tonic-gate  * joining node as STALE; mark it TOOFEW instead.
30390Sstevel@tonic-gate  */
30400Sstevel@tonic-gate static void
30410Sstevel@tonic-gate joinset(
30420Sstevel@tonic-gate 	mdsetname_t	*sp,
30430Sstevel@tonic-gate 	int		flags,
30440Sstevel@tonic-gate 	md_error_t	*ep
30450Sstevel@tonic-gate )
30460Sstevel@tonic-gate {
30470Sstevel@tonic-gate 	mdsetname_t		*local_sp;
30480Sstevel@tonic-gate 	md_drive_desc		*mydd;
30490Sstevel@tonic-gate 	bool_t			stale_bool;
30500Sstevel@tonic-gate 	mddb_block_parm_t	mbp;
30510Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
30520Sstevel@tonic-gate 
30530Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
30540Sstevel@tonic-gate 		return;
30550Sstevel@tonic-gate 
30560Sstevel@tonic-gate 	/*
30570Sstevel@tonic-gate 	 * Start mddoors daemon here.
30580Sstevel@tonic-gate 	 * mddoors itself takes care there will be
30590Sstevel@tonic-gate 	 * only one instance running, so starting it twice won't hurt
30600Sstevel@tonic-gate 	 */
30610Sstevel@tonic-gate 	pclose(popen(MDDOORS, "w"));
30620Sstevel@tonic-gate 
30630Sstevel@tonic-gate 	/*
30640Sstevel@tonic-gate 	 * Get latest copy of data.  If a drive was just added causing
30650Sstevel@tonic-gate 	 * nodes to get joined - this drive won't be in the local
30660Sstevel@tonic-gate 	 * name caches drive list yet.
30670Sstevel@tonic-gate 	 */
30680Sstevel@tonic-gate 	metaflushsetname(local_sp);
30690Sstevel@tonic-gate 
30700Sstevel@tonic-gate 	mydd = metaget_drivedesc(local_sp, (MD_BASICNAME_OK | PRINT_FAST), ep);
30710Sstevel@tonic-gate 	if (mydd) {
3072650Sskamm 		/*
3073650Sskamm 		 * Causes mddbs to be loaded into the kernel.
3074650Sskamm 		 * Set the force flag so that replica locations can be loaded
3075650Sskamm 		 * into the kernel even if a mediator node was unavailable.
3076650Sskamm 		 * This allows a node to join an MO diskset when there are
3077650Sskamm 		 * sufficient replicas available, but a mediator node
3078650Sskamm 		 * in unavailable.
3079650Sskamm 		 */
3080650Sskamm 		if (setup_db_bydd(local_sp, mydd, TRUE, ep) == -1) {
30810Sstevel@tonic-gate 			/* If ep isn't set for some reason, set it */
3082650Sskamm 			if (mdisok(ep)) {
308362Sjeanm 				(void) mdmddberror(ep, MDE_DB_NOTNOW,
308462Sjeanm 				    (minor_t)NODEV64, sp->setno, 0, NULL);
30850Sstevel@tonic-gate 			}
30860Sstevel@tonic-gate 			return;
30870Sstevel@tonic-gate 		}
30880Sstevel@tonic-gate 
30890Sstevel@tonic-gate 		if (flags & MNSET_IS_STALE)
30900Sstevel@tonic-gate 			stale_bool = TRUE;
30910Sstevel@tonic-gate 		else
30920Sstevel@tonic-gate 			stale_bool = FALSE;
30930Sstevel@tonic-gate 
30940Sstevel@tonic-gate 		/*
30950Sstevel@tonic-gate 		 * Snarf the set.  No failure has occurred if STALE or
30960Sstevel@tonic-gate 		 * ACCOK error was set.  Otherwise, fail the call setting
30970Sstevel@tonic-gate 		 * a generic error if no error was already set.
30980Sstevel@tonic-gate 		 *
30990Sstevel@tonic-gate 		 * STALE means that set has < 50% mddbs.
31000Sstevel@tonic-gate 		 * ACCOK means that the mediator provided an extra vote.
31010Sstevel@tonic-gate 		 */
31020Sstevel@tonic-gate 		if (snarf_set(local_sp, stale_bool, ep) != 0) {
31030Sstevel@tonic-gate 			if (!(mdismddberror(ep, MDE_DB_STALE)) &&
31040Sstevel@tonic-gate 			    !(mdismddberror(ep, MDE_DB_ACCOK))) {
31050Sstevel@tonic-gate 				return;
31060Sstevel@tonic-gate 			} else if (mdisok(ep)) {
31070Sstevel@tonic-gate 				/* If snarf failed, but no error set - set it */
310862Sjeanm 				(void) mdmddberror(ep, MDE_DB_NOTNOW,
310962Sjeanm 				    (minor_t)NODEV64, sp->setno, 0, NULL);
31100Sstevel@tonic-gate 				return;
31110Sstevel@tonic-gate 			}
31120Sstevel@tonic-gate 		}
31130Sstevel@tonic-gate 
31140Sstevel@tonic-gate 		/*
31150Sstevel@tonic-gate 		 * If node is joining during reconfig cycle, then
31160Sstevel@tonic-gate 		 * set mddb_parse to be in blocked state so that
31170Sstevel@tonic-gate 		 * mddb reparse messages are not generated until
31180Sstevel@tonic-gate 		 * the commd has been resumed later in the reconfig
31190Sstevel@tonic-gate 		 * cycle.
31200Sstevel@tonic-gate 		 */
31210Sstevel@tonic-gate 		if (flags & MNSET_IN_RECONFIG) {
31220Sstevel@tonic-gate 			(void) memset(&mbp, 0, sizeof (mbp));
31230Sstevel@tonic-gate 			if (s_ownset(sp->setno, &xep) == MD_SETOWNER_YES) {
31240Sstevel@tonic-gate 				(void) memset(&mbp, 0, sizeof (mbp));
31250Sstevel@tonic-gate 				mbp.c_setno = local_sp->setno;
31260Sstevel@tonic-gate 				mbp.c_blk_flags = MDDB_BLOCK_PARSE;
31270Sstevel@tonic-gate 				if (metaioctl(MD_MN_MDDB_BLOCK, &mbp,
31280Sstevel@tonic-gate 				    &mbp.c_mde, NULL)) {
31290Sstevel@tonic-gate 					mdstealerror(&xep, &mbp.c_mde);
31300Sstevel@tonic-gate 					mde_perror(ep, gettext(
31310Sstevel@tonic-gate 					    "Could not block set %s"),
31320Sstevel@tonic-gate 					    sp->setname);
31330Sstevel@tonic-gate 					return;
31340Sstevel@tonic-gate 				}
31350Sstevel@tonic-gate 			}
31360Sstevel@tonic-gate 			/*
31370Sstevel@tonic-gate 			 * If s_ownset fails and snarf_set succeeded,
31380Sstevel@tonic-gate 			 * then can steal the ownset failure information
31390Sstevel@tonic-gate 			 * and store it into ep. If snarf_set failed,
31400Sstevel@tonic-gate 			 * don't overwrite critical ep information even
31410Sstevel@tonic-gate 			 * if s_ownset failed.
31420Sstevel@tonic-gate 			 */
31430Sstevel@tonic-gate 			if (!mdisok(&xep)) {
31440Sstevel@tonic-gate 				/*
31450Sstevel@tonic-gate 				 * If snarf_set succeeded or snarf_set failed
31460Sstevel@tonic-gate 				 * with MDE_DB_ACCOK (which is set if the
31470Sstevel@tonic-gate 				 * mediator provided the extra vote) then
31480Sstevel@tonic-gate 				 * steal the xep failure information and put
31490Sstevel@tonic-gate 				 * into ep.
31500Sstevel@tonic-gate 				 */
31510Sstevel@tonic-gate 				if (mdisok(ep) ||
31520Sstevel@tonic-gate 				    mdismddberror(ep, MDE_DB_ACCOK)) {
31530Sstevel@tonic-gate 					mdstealerror(ep, &xep);
31540Sstevel@tonic-gate 				}
31550Sstevel@tonic-gate 			}
31560Sstevel@tonic-gate 		}
31570Sstevel@tonic-gate 	}
31580Sstevel@tonic-gate }
31590Sstevel@tonic-gate 
31600Sstevel@tonic-gate /*
31610Sstevel@tonic-gate  * Have this node join the set.
31620Sstevel@tonic-gate  * This is called when a node has been
31630Sstevel@tonic-gate  * added to a MN diskset that has drives.
31640Sstevel@tonic-gate  * Also, called when a node is an alive
31650Sstevel@tonic-gate  * member of a MN diskset and the first
31660Sstevel@tonic-gate  * drive has been added.
31670Sstevel@tonic-gate  */
31680Sstevel@tonic-gate bool_t
31690Sstevel@tonic-gate mdrpc_joinset_common(
31700Sstevel@tonic-gate 	mdrpc_sp_flags_args	*args,
31710Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
31720Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
31730Sstevel@tonic-gate )
31740Sstevel@tonic-gate {
31750Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
31760Sstevel@tonic-gate 	int			err;
31770Sstevel@tonic-gate 	int			op_mode = W_OK;
31780Sstevel@tonic-gate 
31790Sstevel@tonic-gate 	/* setup, check permissions */
31800Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
31810Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
31820Sstevel@tonic-gate 		return (FALSE);
31830Sstevel@tonic-gate 	else if (err != 0)
31840Sstevel@tonic-gate 		return (TRUE);
31850Sstevel@tonic-gate 
31860Sstevel@tonic-gate 	/*
31870Sstevel@tonic-gate 	 * During reconfig, joinset can happen without
31880Sstevel@tonic-gate 	 * locking first.  Turn off reconfig flag before calling
31890Sstevel@tonic-gate 	 * joinset.
31900Sstevel@tonic-gate 	 */
31910Sstevel@tonic-gate 	if (!(args->flags & MNSET_IN_RECONFIG)) {
31920Sstevel@tonic-gate 		if (check_set_lock(op_mode, args->cl_sk, ep))
31930Sstevel@tonic-gate 			return (TRUE);
31940Sstevel@tonic-gate 	}
31950Sstevel@tonic-gate 
31960Sstevel@tonic-gate 	/* doit */
31970Sstevel@tonic-gate 	joinset(args->sp, args->flags, ep);
31980Sstevel@tonic-gate 
31990Sstevel@tonic-gate 	err = svc_fini(ep);
32000Sstevel@tonic-gate 
32010Sstevel@tonic-gate 	return (TRUE);
32020Sstevel@tonic-gate }
32030Sstevel@tonic-gate 
32040Sstevel@tonic-gate bool_t
32050Sstevel@tonic-gate mdrpc_joinset_2_svc(
32060Sstevel@tonic-gate 	mdrpc_sp_flags_2_args	*args,
32070Sstevel@tonic-gate 	mdrpc_generic_res	*res,
32080Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
32090Sstevel@tonic-gate )
32100Sstevel@tonic-gate {
32110Sstevel@tonic-gate 	switch (args->rev) {
32120Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
32130Sstevel@tonic-gate 		return (mdrpc_joinset_common(
32140Sstevel@tonic-gate 		    &args->mdrpc_sp_flags_2_args_u.rev1, res, rqstp));
32150Sstevel@tonic-gate 	    default:
32160Sstevel@tonic-gate 		return (FALSE);
32170Sstevel@tonic-gate 	}
32180Sstevel@tonic-gate }
32190Sstevel@tonic-gate 
32200Sstevel@tonic-gate static void
32210Sstevel@tonic-gate withdrawset(
32220Sstevel@tonic-gate 	mdsetname_t	*sp,
32230Sstevel@tonic-gate 	md_error_t	*ep
32240Sstevel@tonic-gate )
32250Sstevel@tonic-gate {
32260Sstevel@tonic-gate 	mdsetname_t	*my_sp;
32270Sstevel@tonic-gate 
32280Sstevel@tonic-gate 	if ((my_sp = metasetname(sp->setname, ep)) == NULL)
32290Sstevel@tonic-gate 		return;
32300Sstevel@tonic-gate 
32310Sstevel@tonic-gate 	(void) halt_set(my_sp, ep);
32320Sstevel@tonic-gate }
32330Sstevel@tonic-gate 
32340Sstevel@tonic-gate /*
32350Sstevel@tonic-gate  * Have this node withdraw from set.
32360Sstevel@tonic-gate  * In response to a failure that occurred
32370Sstevel@tonic-gate  * on the client after a joinset.
32380Sstevel@tonic-gate  */
32390Sstevel@tonic-gate bool_t
32400Sstevel@tonic-gate mdrpc_withdrawset_common(
32410Sstevel@tonic-gate 	mdrpc_sp_args		*args,
32420Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
32430Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
32440Sstevel@tonic-gate )
32450Sstevel@tonic-gate {
32460Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
32470Sstevel@tonic-gate 	int			err;
32480Sstevel@tonic-gate 	int			op_mode = W_OK;
32490Sstevel@tonic-gate 
32500Sstevel@tonic-gate 	/* setup, check permissions */
32510Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
32520Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
32530Sstevel@tonic-gate 		return (FALSE);
32540Sstevel@tonic-gate 	else if (err != 0)
32550Sstevel@tonic-gate 		return (TRUE);
32560Sstevel@tonic-gate 
32570Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
32580Sstevel@tonic-gate 		return (TRUE);
32590Sstevel@tonic-gate 
32600Sstevel@tonic-gate 	/* doit */
32610Sstevel@tonic-gate 	withdrawset(args->sp, ep);
32620Sstevel@tonic-gate 
32630Sstevel@tonic-gate 	err = svc_fini(ep);
32640Sstevel@tonic-gate 
32650Sstevel@tonic-gate 	return (TRUE);
32660Sstevel@tonic-gate }
32670Sstevel@tonic-gate 
32680Sstevel@tonic-gate bool_t
32690Sstevel@tonic-gate mdrpc_withdrawset_2_svc(
32700Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
32710Sstevel@tonic-gate 	mdrpc_generic_res	*res,
32720Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
32730Sstevel@tonic-gate )
32740Sstevel@tonic-gate {
32750Sstevel@tonic-gate 	switch (args->rev) {
32760Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
32770Sstevel@tonic-gate 		return (mdrpc_withdrawset_common(
32780Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
32790Sstevel@tonic-gate 	    default:
32800Sstevel@tonic-gate 		return (FALSE);
32810Sstevel@tonic-gate 	}
32820Sstevel@tonic-gate }
32830Sstevel@tonic-gate 
32840Sstevel@tonic-gate static mhd_mhiargs_t *
32850Sstevel@tonic-gate gtimeout(mdsetname_t *sp, md_error_t *ep)
32860Sstevel@tonic-gate {
32870Sstevel@tonic-gate 	md_set_record		*sr;
32880Sstevel@tonic-gate 	mhd_mhiargs_t		*mhiargs;
32890Sstevel@tonic-gate 
32900Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
32910Sstevel@tonic-gate 		return (NULL);
32920Sstevel@tonic-gate 
32930Sstevel@tonic-gate 	mhiargs = Zalloc(sizeof (*mhiargs));
32940Sstevel@tonic-gate 	*mhiargs = sr->sr_mhiargs;
32950Sstevel@tonic-gate 
32960Sstevel@tonic-gate 	free_sr(sr);
32970Sstevel@tonic-gate 	return (mhiargs);
32980Sstevel@tonic-gate }
32990Sstevel@tonic-gate 
33000Sstevel@tonic-gate /*
33010Sstevel@tonic-gate  * Get the MH timeout values for this set.
33020Sstevel@tonic-gate  */
33030Sstevel@tonic-gate bool_t
33040Sstevel@tonic-gate mdrpc_gtimeout_common(
33050Sstevel@tonic-gate 	mdrpc_sp_args		*args,
33060Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
33070Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
33080Sstevel@tonic-gate )
33090Sstevel@tonic-gate {
33100Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
33110Sstevel@tonic-gate 	int			err;
33120Sstevel@tonic-gate 	int			op_mode = R_OK;
33130Sstevel@tonic-gate 
33140Sstevel@tonic-gate 	/* setup, check permissions */
33150Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
33160Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
33170Sstevel@tonic-gate 		return (FALSE);
33180Sstevel@tonic-gate 	else if (err != 0)
33190Sstevel@tonic-gate 		return (TRUE);
33200Sstevel@tonic-gate 
33210Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
33220Sstevel@tonic-gate 		return (TRUE);
33230Sstevel@tonic-gate 
33240Sstevel@tonic-gate 	/* doit */
33250Sstevel@tonic-gate 	res->mhiargsp = gtimeout(args->sp, ep);
33260Sstevel@tonic-gate 
33270Sstevel@tonic-gate 	err = svc_fini(ep);
33280Sstevel@tonic-gate 
33290Sstevel@tonic-gate 	return (TRUE);
33300Sstevel@tonic-gate }
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate bool_t
33330Sstevel@tonic-gate mdrpc_gtimeout_1_svc(
33340Sstevel@tonic-gate 	mdrpc_sp_args		*args,
33350Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
33360Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
33370Sstevel@tonic-gate )
33380Sstevel@tonic-gate {
33390Sstevel@tonic-gate 	return (mdrpc_gtimeout_common(args, res, rqstp));
33400Sstevel@tonic-gate }
33410Sstevel@tonic-gate 
33420Sstevel@tonic-gate bool_t
33430Sstevel@tonic-gate mdrpc_gtimeout_2_svc(
33440Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
33450Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
33460Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
33470Sstevel@tonic-gate )
33480Sstevel@tonic-gate {
33490Sstevel@tonic-gate 	switch (args->rev) {
33500Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
33510Sstevel@tonic-gate 		return (mdrpc_gtimeout_common(
33520Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
33530Sstevel@tonic-gate 	    default:
33540Sstevel@tonic-gate 		return (FALSE);
33550Sstevel@tonic-gate 	}
33560Sstevel@tonic-gate }
33570Sstevel@tonic-gate 
33580Sstevel@tonic-gate /*
33590Sstevel@tonic-gate  * return the official host name for the callee
33600Sstevel@tonic-gate  */
33610Sstevel@tonic-gate /*ARGSUSED*/
33620Sstevel@tonic-gate bool_t
33630Sstevel@tonic-gate mdrpc_hostname_common(
33640Sstevel@tonic-gate 	mdrpc_null_args		*args,
33650Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
33660Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
33670Sstevel@tonic-gate )
33680Sstevel@tonic-gate {
33690Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
33700Sstevel@tonic-gate 	int			err;
33710Sstevel@tonic-gate 	int			op_mode = R_OK;
33720Sstevel@tonic-gate 
33730Sstevel@tonic-gate 	/* setup, check permissions */
33740Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
33750Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
33760Sstevel@tonic-gate 		return (FALSE);
33770Sstevel@tonic-gate 	else if (err != 0)
33780Sstevel@tonic-gate 		return (TRUE);
33790Sstevel@tonic-gate 
33800Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
33810Sstevel@tonic-gate 		return (TRUE);
33820Sstevel@tonic-gate 
33830Sstevel@tonic-gate 	/* doit */
33840Sstevel@tonic-gate 	res->hostname = Strdup(mynode());
33850Sstevel@tonic-gate 
33860Sstevel@tonic-gate 	err = svc_fini(ep);
33870Sstevel@tonic-gate 
33880Sstevel@tonic-gate 	return (TRUE);
33890Sstevel@tonic-gate }
33900Sstevel@tonic-gate 
33910Sstevel@tonic-gate bool_t
33920Sstevel@tonic-gate mdrpc_hostname_1_svc(
33930Sstevel@tonic-gate 	mdrpc_null_args		*args,
33940Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
33950Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
33960Sstevel@tonic-gate )
33970Sstevel@tonic-gate {
33980Sstevel@tonic-gate 	return (mdrpc_hostname_common(args, res, rqstp));
33990Sstevel@tonic-gate }
34000Sstevel@tonic-gate 
34010Sstevel@tonic-gate bool_t
34020Sstevel@tonic-gate mdrpc_hostname_2_svc(
34030Sstevel@tonic-gate 	mdrpc_null_args		*args,
34040Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
34050Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
34060Sstevel@tonic-gate )
34070Sstevel@tonic-gate {
34080Sstevel@tonic-gate 	return (mdrpc_hostname_common(args, res, rqstp));
34090Sstevel@tonic-gate }
34100Sstevel@tonic-gate 
34110Sstevel@tonic-gate /*
34120Sstevel@tonic-gate  * return a response
34130Sstevel@tonic-gate  */
34140Sstevel@tonic-gate /*ARGSUSED*/
34150Sstevel@tonic-gate bool_t
34160Sstevel@tonic-gate mdrpc_nullproc_common(
34170Sstevel@tonic-gate 	void		*args,
34180Sstevel@tonic-gate 	md_error_t	*ep,
34190Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
34200Sstevel@tonic-gate )
34210Sstevel@tonic-gate {
34220Sstevel@tonic-gate 	*ep = mdnullerror;
34230Sstevel@tonic-gate 	/* do nothing */
34240Sstevel@tonic-gate 	return (TRUE);
34250Sstevel@tonic-gate }
34260Sstevel@tonic-gate 
34270Sstevel@tonic-gate bool_t
34280Sstevel@tonic-gate mdrpc_nullproc_1_svc(
34290Sstevel@tonic-gate 	void		*args,
34300Sstevel@tonic-gate 	md_error_t	*ep,
34310Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
34320Sstevel@tonic-gate )
34330Sstevel@tonic-gate {
34340Sstevel@tonic-gate 	return (mdrpc_nullproc_common(args, ep, rqstp));
34350Sstevel@tonic-gate }
34360Sstevel@tonic-gate 
34370Sstevel@tonic-gate bool_t
34380Sstevel@tonic-gate mdrpc_nullproc_2_svc(
34390Sstevel@tonic-gate 	void		*args,
34400Sstevel@tonic-gate 	md_error_t	*ep,
34410Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
34420Sstevel@tonic-gate )
34430Sstevel@tonic-gate {
34440Sstevel@tonic-gate 	return (mdrpc_nullproc_common(args, ep, rqstp));
34450Sstevel@tonic-gate }
34460Sstevel@tonic-gate 
34470Sstevel@tonic-gate /*
34480Sstevel@tonic-gate  * determine if the caller owns the set.
34490Sstevel@tonic-gate  */
34500Sstevel@tonic-gate bool_t
34510Sstevel@tonic-gate mdrpc_ownset_common(
34520Sstevel@tonic-gate 	mdrpc_sp_args		*args,
34530Sstevel@tonic-gate 	mdrpc_bool_res		*res,
34540Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
34550Sstevel@tonic-gate )
34560Sstevel@tonic-gate {
34570Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
34580Sstevel@tonic-gate 	int			err;
34590Sstevel@tonic-gate 	int			op_mode = R_OK;
34600Sstevel@tonic-gate 
34610Sstevel@tonic-gate 	/* setup, check permissions */
34620Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
34630Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
34640Sstevel@tonic-gate 		return (FALSE);
34650Sstevel@tonic-gate 	else if (err != 0)
34660Sstevel@tonic-gate 		return (TRUE);
34670Sstevel@tonic-gate 
34680Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
34690Sstevel@tonic-gate 		return (TRUE);
34700Sstevel@tonic-gate 
34710Sstevel@tonic-gate 	/* doit */
34720Sstevel@tonic-gate 	if (s_ownset(args->sp->setno, ep))
34730Sstevel@tonic-gate 		res->value = TRUE;
34740Sstevel@tonic-gate 	else
34750Sstevel@tonic-gate 		res->value = FALSE;
34760Sstevel@tonic-gate 
34770Sstevel@tonic-gate 	err = svc_fini(ep);
34780Sstevel@tonic-gate 
34790Sstevel@tonic-gate 	return (TRUE);
34800Sstevel@tonic-gate }
34810Sstevel@tonic-gate 
34820Sstevel@tonic-gate bool_t
34830Sstevel@tonic-gate mdrpc_ownset_1_svc(
34840Sstevel@tonic-gate 	mdrpc_sp_args		*args,
34850Sstevel@tonic-gate 	mdrpc_bool_res		*res,
34860Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
34870Sstevel@tonic-gate )
34880Sstevel@tonic-gate {
34890Sstevel@tonic-gate 	return (mdrpc_ownset_common(args, res, rqstp));
34900Sstevel@tonic-gate }
34910Sstevel@tonic-gate 
34920Sstevel@tonic-gate bool_t
34930Sstevel@tonic-gate mdrpc_ownset_2_svc(
34940Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
34950Sstevel@tonic-gate 	mdrpc_bool_res		*res,
34960Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
34970Sstevel@tonic-gate )
34980Sstevel@tonic-gate {
34990Sstevel@tonic-gate 	switch (args->rev) {
35000Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
35010Sstevel@tonic-gate 		return (mdrpc_ownset_common(
35020Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
35030Sstevel@tonic-gate 	    default:
35040Sstevel@tonic-gate 		return (FALSE);
35050Sstevel@tonic-gate 	}
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate 
35080Sstevel@tonic-gate static int
35090Sstevel@tonic-gate setnameok(char *setname, md_error_t *ep)
35100Sstevel@tonic-gate {
35110Sstevel@tonic-gate 	int			rval = 0;
35120Sstevel@tonic-gate 	struct	stat		statb;
35130Sstevel@tonic-gate 	md_set_record		*sr = NULL;
35140Sstevel@tonic-gate 	char			*setlink = NULL;
35150Sstevel@tonic-gate 
35160Sstevel@tonic-gate 	setlink = Strdup("/dev/md/");
35170Sstevel@tonic-gate 	setlink = Realloc(setlink, strlen(setlink) + strlen(setname) + 1);
35180Sstevel@tonic-gate 	(void) strcat(setlink, setname);
35190Sstevel@tonic-gate 
35200Sstevel@tonic-gate 	if (lstat(setlink, &statb) == -1) {
35210Sstevel@tonic-gate 		/*
35220Sstevel@tonic-gate 		 * If lstat() fails with ENOENT, setname is OK, if it
35230Sstevel@tonic-gate 		 * fails for other than that, we fail the RPC
35240Sstevel@tonic-gate 		 */
35250Sstevel@tonic-gate 		if (errno == ENOENT) {
35260Sstevel@tonic-gate 			rval = 1;
35270Sstevel@tonic-gate 			goto out;
35280Sstevel@tonic-gate 		}
35290Sstevel@tonic-gate 
35300Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, setlink);
35310Sstevel@tonic-gate 		goto out;
35320Sstevel@tonic-gate 	}
35330Sstevel@tonic-gate 
35340Sstevel@tonic-gate 	/*
35350Sstevel@tonic-gate 	 * If the lstat() succeeded, then we see what type of object
35360Sstevel@tonic-gate 	 * we are dealing with, if it is a symlink, we do some further
35370Sstevel@tonic-gate 	 * checking, if it is not a symlink, then we return an
35380Sstevel@tonic-gate 	 * indication that the set name is NOT acceptable.
35390Sstevel@tonic-gate 	 */
35400Sstevel@tonic-gate 	if (! S_ISLNK(statb.st_mode))
35410Sstevel@tonic-gate 		goto out;
35420Sstevel@tonic-gate 
35430Sstevel@tonic-gate 	/*
35440Sstevel@tonic-gate 	 * We look up the setname to see if there is a set
35450Sstevel@tonic-gate 	 * with that name, if there is, then we return
35460Sstevel@tonic-gate 	 * an indication that the set name is NOT acceptable.
35470Sstevel@tonic-gate 	 */
35480Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) != NULL)
35490Sstevel@tonic-gate 		goto out;
35500Sstevel@tonic-gate 
35510Sstevel@tonic-gate 	if (! mdiserror(ep, MDE_NO_SET))
35520Sstevel@tonic-gate 		goto out;
35530Sstevel@tonic-gate 
35540Sstevel@tonic-gate 	mdclrerror(ep);
35550Sstevel@tonic-gate 
35560Sstevel@tonic-gate 	rval = 1;
35570Sstevel@tonic-gate out:
35580Sstevel@tonic-gate 	if (sr != NULL)
35590Sstevel@tonic-gate 		free_sr(sr);
35600Sstevel@tonic-gate 	Free(setlink);
35610Sstevel@tonic-gate 	return (rval);
35620Sstevel@tonic-gate }
35630Sstevel@tonic-gate 
35640Sstevel@tonic-gate /*
35650Sstevel@tonic-gate  * Make sure the name of the set is OK.
35660Sstevel@tonic-gate  */
35670Sstevel@tonic-gate bool_t
35680Sstevel@tonic-gate mdrpc_setnameok_common(
35690Sstevel@tonic-gate 	mdrpc_sp_args		*args,	/* device name */
35700Sstevel@tonic-gate 	mdrpc_bool_res		*res,
35710Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
35720Sstevel@tonic-gate )
35730Sstevel@tonic-gate {
35740Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
35750Sstevel@tonic-gate 	int			err;
35760Sstevel@tonic-gate 	int			op_mode = R_OK;
35770Sstevel@tonic-gate 
35780Sstevel@tonic-gate 	/* setup, check permissions */
35790Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
35800Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
35810Sstevel@tonic-gate 		return (FALSE);
35820Sstevel@tonic-gate 	else if (err != 0)
35830Sstevel@tonic-gate 		return (TRUE);
35840Sstevel@tonic-gate 
35850Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
35860Sstevel@tonic-gate 		return (TRUE);
35870Sstevel@tonic-gate 
35880Sstevel@tonic-gate 	/* doit */
35890Sstevel@tonic-gate 	res->value = setnameok(args->sp->setname, ep);
35900Sstevel@tonic-gate 
35910Sstevel@tonic-gate 	err = svc_fini(ep);
35920Sstevel@tonic-gate 
35930Sstevel@tonic-gate 	return (TRUE);
35940Sstevel@tonic-gate }
35950Sstevel@tonic-gate 
35960Sstevel@tonic-gate bool_t
35970Sstevel@tonic-gate mdrpc_setnameok_1_svc(
35980Sstevel@tonic-gate 	mdrpc_sp_args		*args,	/* device name */
35990Sstevel@tonic-gate 	mdrpc_bool_res		*res,
36000Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
36010Sstevel@tonic-gate )
36020Sstevel@tonic-gate {
36030Sstevel@tonic-gate 	return (mdrpc_setnameok_common(args, res, rqstp));
36040Sstevel@tonic-gate }
36050Sstevel@tonic-gate 
36060Sstevel@tonic-gate bool_t
36070Sstevel@tonic-gate mdrpc_setnameok_2_svc(
36080Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,	/* device name */
36090Sstevel@tonic-gate 	mdrpc_bool_res		*res,
36100Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
36110Sstevel@tonic-gate )
36120Sstevel@tonic-gate {
36130Sstevel@tonic-gate 	switch (args->rev) {
36140Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
36150Sstevel@tonic-gate 		return (mdrpc_setnameok_common(
36160Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
36170Sstevel@tonic-gate 	    default:
36180Sstevel@tonic-gate 		return (FALSE);
36190Sstevel@tonic-gate 	}
36200Sstevel@tonic-gate }
36210Sstevel@tonic-gate 
36220Sstevel@tonic-gate /*
36230Sstevel@tonic-gate  * determine if the setnumber we want to share is in use.
36240Sstevel@tonic-gate  */
36250Sstevel@tonic-gate bool_t
36260Sstevel@tonic-gate mdrpc_setnumbusy_common(
36270Sstevel@tonic-gate 	mdrpc_setno_args	*args,
36280Sstevel@tonic-gate 	mdrpc_bool_res		*res,
36290Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
36300Sstevel@tonic-gate )
36310Sstevel@tonic-gate {
36320Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
36330Sstevel@tonic-gate 	md_set_record		*sr = NULL;
36340Sstevel@tonic-gate 	int			err;
36350Sstevel@tonic-gate 	int			op_mode = R_OK;
36360Sstevel@tonic-gate 
36370Sstevel@tonic-gate 	/* setup, check permissions */
36380Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
36390Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
36400Sstevel@tonic-gate 		return (FALSE);
36410Sstevel@tonic-gate 	else if (err != 0)
36420Sstevel@tonic-gate 		return (TRUE);
36430Sstevel@tonic-gate 
36440Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
36450Sstevel@tonic-gate 		return (TRUE);
36460Sstevel@tonic-gate 
36470Sstevel@tonic-gate 	/* doit */
36480Sstevel@tonic-gate 	if ((sr = getsetbynum(args->setno, ep)) != NULL) {
36490Sstevel@tonic-gate 		res->value = TRUE;
36500Sstevel@tonic-gate 		free_sr(sr);
36510Sstevel@tonic-gate 		return (TRUE);
36520Sstevel@tonic-gate 	}
36530Sstevel@tonic-gate 	res->value = FALSE;
36540Sstevel@tonic-gate 	if (mdiserror(ep, MDE_NO_SET))
36550Sstevel@tonic-gate 		mdclrerror(ep);
36560Sstevel@tonic-gate 
36570Sstevel@tonic-gate 	err = svc_fini(ep);
36580Sstevel@tonic-gate 
36590Sstevel@tonic-gate 	return (TRUE);
36600Sstevel@tonic-gate }
36610Sstevel@tonic-gate 
36620Sstevel@tonic-gate bool_t
36630Sstevel@tonic-gate mdrpc_setnumbusy_1_svc(
36640Sstevel@tonic-gate 	mdrpc_setno_args	*args,
36650Sstevel@tonic-gate 	mdrpc_bool_res		*res,
36660Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
36670Sstevel@tonic-gate )
36680Sstevel@tonic-gate {
36690Sstevel@tonic-gate 	return (mdrpc_setnumbusy_common(args, res, rqstp));
36700Sstevel@tonic-gate }
36710Sstevel@tonic-gate 
36720Sstevel@tonic-gate bool_t
36730Sstevel@tonic-gate mdrpc_setnumbusy_2_svc(
36740Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
36750Sstevel@tonic-gate 	mdrpc_bool_res		*res,
36760Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
36770Sstevel@tonic-gate )
36780Sstevel@tonic-gate {
36790Sstevel@tonic-gate 	switch (args->rev) {
36800Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
36810Sstevel@tonic-gate 		return (mdrpc_setnumbusy_common(
36820Sstevel@tonic-gate 		    &args->mdrpc_setno_2_args_u.rev1, res, rqstp));
36830Sstevel@tonic-gate 	    default:
36840Sstevel@tonic-gate 		return (FALSE);
36850Sstevel@tonic-gate 	}
36860Sstevel@tonic-gate }
36870Sstevel@tonic-gate 
36880Sstevel@tonic-gate static void
36890Sstevel@tonic-gate stimeout(
36900Sstevel@tonic-gate 	mdsetname_t	*sp,
36910Sstevel@tonic-gate 	mhd_mhiargs_t	*mhiargsp,
36920Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
36930Sstevel@tonic-gate 	md_error_t	*ep
36940Sstevel@tonic-gate )
36950Sstevel@tonic-gate {
36960Sstevel@tonic-gate 	mddb_userreq_t		req;
36970Sstevel@tonic-gate 	md_set_record		*sr;
36980Sstevel@tonic-gate 
36990Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
37000Sstevel@tonic-gate 		return;
37010Sstevel@tonic-gate 
37020Sstevel@tonic-gate 	sr->sr_mhiargs = *mhiargsp;
37030Sstevel@tonic-gate 
37040Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
37050Sstevel@tonic-gate 
37060Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
37070Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
37080Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
37090Sstevel@tonic-gate 		req.ur_size = sizeof (struct md_mnset_record);
37100Sstevel@tonic-gate 	} else {
37110Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
37120Sstevel@tonic-gate 	}
37130Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
37140Sstevel@tonic-gate 
37150Sstevel@tonic-gate 	/*
37160Sstevel@tonic-gate 	 * Cluster nodename support
37170Sstevel@tonic-gate 	 * Convert nodename -> nodeid
37180Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
37190Sstevel@tonic-gate 	 * both the nodeid and name.
37200Sstevel@tonic-gate 	 */
37210Sstevel@tonic-gate 	if ((version == METAD_VERSION) ||
37220Sstevel@tonic-gate 	    ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
37230Sstevel@tonic-gate 		sdssc_cm_sr_nm2nid(sr);
37240Sstevel@tonic-gate 
37250Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
37260Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
37270Sstevel@tonic-gate 		return;
37280Sstevel@tonic-gate 	}
37290Sstevel@tonic-gate 
37300Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
37310Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_COMMIT_ONE, sr->sr_selfid)
37320Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
37330Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
37340Sstevel@tonic-gate 
37350Sstevel@tonic-gate 	/*
37360Sstevel@tonic-gate 	 * Cluster nodename support
37370Sstevel@tonic-gate 	 * Convert nodeid -> nodename
37380Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
37390Sstevel@tonic-gate 	 * both the nodeid and name.
37400Sstevel@tonic-gate 	 */
37410Sstevel@tonic-gate 	if ((version == METAD_VERSION) ||
37420Sstevel@tonic-gate 	    ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
37430Sstevel@tonic-gate 		sdssc_cm_sr_nid2nm(sr);
37440Sstevel@tonic-gate 
37450Sstevel@tonic-gate 	free_sr(sr);
37460Sstevel@tonic-gate }
37470Sstevel@tonic-gate 
37480Sstevel@tonic-gate /*
37490Sstevel@tonic-gate  * Set MH ioctl timeout values.
37500Sstevel@tonic-gate  */
37510Sstevel@tonic-gate bool_t
37520Sstevel@tonic-gate mdrpc_stimeout_common(
37530Sstevel@tonic-gate 	mdrpc_stimeout_args	*args,
37540Sstevel@tonic-gate 	mdrpc_generic_res	*res,
37550Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
37560Sstevel@tonic-gate 	int			version		/* RPC version */
37570Sstevel@tonic-gate )
37580Sstevel@tonic-gate {
37590Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
37600Sstevel@tonic-gate 	int			err;
37610Sstevel@tonic-gate 	int			op_mode = W_OK;
37620Sstevel@tonic-gate 
37630Sstevel@tonic-gate 	/* setup, check permissions */
37640Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
37650Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
37660Sstevel@tonic-gate 		return (FALSE);
37670Sstevel@tonic-gate 	else if (err != 0)
37680Sstevel@tonic-gate 		return (TRUE);
37690Sstevel@tonic-gate 
37700Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
37710Sstevel@tonic-gate 		return (TRUE);
37720Sstevel@tonic-gate 
37730Sstevel@tonic-gate 	/* doit */
37740Sstevel@tonic-gate 	stimeout(args->sp, args->mhiargsp, version, ep);
37750Sstevel@tonic-gate 
37760Sstevel@tonic-gate 	err = svc_fini(ep);
37770Sstevel@tonic-gate 
37780Sstevel@tonic-gate 	return (TRUE);
37790Sstevel@tonic-gate }
37800Sstevel@tonic-gate 
37810Sstevel@tonic-gate bool_t
37820Sstevel@tonic-gate mdrpc_stimeout_1_svc(
37830Sstevel@tonic-gate 	mdrpc_stimeout_args	*args,
37840Sstevel@tonic-gate 	mdrpc_generic_res	*res,
37850Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
37860Sstevel@tonic-gate )
37870Sstevel@tonic-gate {
37880Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
37890Sstevel@tonic-gate 	return (mdrpc_stimeout_common(args, res, rqstp, METAD_VERSION));
37900Sstevel@tonic-gate }
37910Sstevel@tonic-gate 
37920Sstevel@tonic-gate bool_t
37930Sstevel@tonic-gate mdrpc_stimeout_2_svc(
37940Sstevel@tonic-gate 	mdrpc_stimeout_2_args	*args,
37950Sstevel@tonic-gate 	mdrpc_generic_res	*res,
37960Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
37970Sstevel@tonic-gate )
37980Sstevel@tonic-gate {
37990Sstevel@tonic-gate 	switch (args->rev) {
38000Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
38010Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
38020Sstevel@tonic-gate 		return (mdrpc_stimeout_common(
38030Sstevel@tonic-gate 		    &args->mdrpc_stimeout_2_args_u.rev1, res,
38040Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
38050Sstevel@tonic-gate 	    default:
38060Sstevel@tonic-gate 		return (FALSE);
38070Sstevel@tonic-gate 	}
38080Sstevel@tonic-gate }
38090Sstevel@tonic-gate 
38100Sstevel@tonic-gate static void
38110Sstevel@tonic-gate upd_dr_dbinfo(
38120Sstevel@tonic-gate 	mdsetname_t	*sp,
38130Sstevel@tonic-gate 	md_drive_desc	*dd,
38140Sstevel@tonic-gate 	md_error_t	*ep
38150Sstevel@tonic-gate )
38160Sstevel@tonic-gate {
38170Sstevel@tonic-gate 	mdsetname_t	*local_sp;
38180Sstevel@tonic-gate 	md_set_record	*sr;
38190Sstevel@tonic-gate 	md_drive_record	*dr;
38200Sstevel@tonic-gate 	md_drive_desc	*p;
38210Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
38220Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
38230Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
38240Sstevel@tonic-gate 	int		devid_same = -1;
38250Sstevel@tonic-gate 	side_t		sideno;
38260Sstevel@tonic-gate 	int		using_devid = 0;
38270Sstevel@tonic-gate 
38280Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
38290Sstevel@tonic-gate 		return;
38300Sstevel@tonic-gate 
38310Sstevel@tonic-gate 	metaflushsetname(local_sp);
38320Sstevel@tonic-gate 
38330Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
38340Sstevel@tonic-gate 		return;
38350Sstevel@tonic-gate 
38360Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
38370Sstevel@tonic-gate 		return;
38380Sstevel@tonic-gate 
38390Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
38400Sstevel@tonic-gate 		return;
38410Sstevel@tonic-gate 
38420Sstevel@tonic-gate 	/*
38430Sstevel@tonic-gate 	 * The system is either all devid or all
38440Sstevel@tonic-gate 	 * non-devid so we determine this by looking
38450Sstevel@tonic-gate 	 * at the first item in the list.
38460Sstevel@tonic-gate 	 *
38470Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
38480Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
38490Sstevel@tonic-gate 	 * before set the using_devid.
38500Sstevel@tonic-gate 	 */
38510Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
38520Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
38530Sstevel@tonic-gate 		using_devid = 1;
38540Sstevel@tonic-gate 
38550Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
38560Sstevel@tonic-gate 		dn = p->dd_dnp;
38570Sstevel@tonic-gate 		devid_remote = NULL;
38580Sstevel@tonic-gate 
38590Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
38600Sstevel@tonic-gate 		    using_devid) {
38610Sstevel@tonic-gate 			/*
38620Sstevel@tonic-gate 			 * We have a devid so use it.
38630Sstevel@tonic-gate 			 */
38640Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
38650Sstevel@tonic-gate 		}
38660Sstevel@tonic-gate 
38670Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
38680Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
38690Sstevel@tonic-gate 			/* something went really wrong. Can't process */
38700Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
38710Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
38720Sstevel@tonic-gate 			return;
38730Sstevel@tonic-gate 		}
38740Sstevel@tonic-gate 
38750Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
38760Sstevel@tonic-gate 			devid_same = -1;
38770Sstevel@tonic-gate 
38780Sstevel@tonic-gate 			dn1 = metadrivename_withdrkey(local_sp, sideno,
38790Sstevel@tonic-gate 			    dr->dr_key, MD_BASICNAME_OK, ep);
38800Sstevel@tonic-gate 
38810Sstevel@tonic-gate 			if (dn1 == NULL) {
38820Sstevel@tonic-gate 				if (devid_remote)
38830Sstevel@tonic-gate 					devid_free(devid_remote);
38840Sstevel@tonic-gate 				goto out;
38850Sstevel@tonic-gate 			}
38860Sstevel@tonic-gate 
38870Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
38880Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid, &devid_local,
38890Sstevel@tonic-gate 				    NULL) == 0) {
38900Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
38910Sstevel@tonic-gate 					    devid_local);
38920Sstevel@tonic-gate 					devid_free(devid_local);
38930Sstevel@tonic-gate 				}
38940Sstevel@tonic-gate 			}
38950Sstevel@tonic-gate 
38960Sstevel@tonic-gate 			if (using_devid && devid_same == 0)
38970Sstevel@tonic-gate 				break;
38980Sstevel@tonic-gate 
38990Sstevel@tonic-gate 			if (!using_devid &&
39000Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)
39010Sstevel@tonic-gate 				break;
39020Sstevel@tonic-gate 		}
39030Sstevel@tonic-gate 
39040Sstevel@tonic-gate 		if (dr) {
39050Sstevel@tonic-gate 			/* Adjust the fields in the copy */
39060Sstevel@tonic-gate 			dr->dr_dbcnt = p->dd_dbcnt;
39070Sstevel@tonic-gate 			dr->dr_dbsize = p->dd_dbsize;
39080Sstevel@tonic-gate 		}
39090Sstevel@tonic-gate 		if (devid_remote)
39100Sstevel@tonic-gate 			devid_free(devid_remote);
39110Sstevel@tonic-gate 	}
39120Sstevel@tonic-gate 
39130Sstevel@tonic-gate 
39140Sstevel@tonic-gate out:
39150Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
39160Sstevel@tonic-gate 	free_sr(sr);
39170Sstevel@tonic-gate }
39180Sstevel@tonic-gate 
39190Sstevel@tonic-gate /*
39200Sstevel@tonic-gate  * update the database count and size field of drive records.
39210Sstevel@tonic-gate  */
39220Sstevel@tonic-gate bool_t
39230Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_common(
39240Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
39250Sstevel@tonic-gate 	mdrpc_generic_res	*res,
39260Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
39270Sstevel@tonic-gate )
39280Sstevel@tonic-gate {
39290Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
39300Sstevel@tonic-gate 	int			err;
39310Sstevel@tonic-gate 	int			op_mode = W_OK;
39320Sstevel@tonic-gate 
39330Sstevel@tonic-gate 	/* setup, check permissions */
39340Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
39350Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
39360Sstevel@tonic-gate 		return (FALSE);
39370Sstevel@tonic-gate 	else if (err != 0)
39380Sstevel@tonic-gate 		return (TRUE);
39390Sstevel@tonic-gate 
39400Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
39410Sstevel@tonic-gate 		return (TRUE);
39420Sstevel@tonic-gate 
39430Sstevel@tonic-gate 	/* doit */
39440Sstevel@tonic-gate 	upd_dr_dbinfo(args->sp, args->drivedescs, ep);
39450Sstevel@tonic-gate 
39460Sstevel@tonic-gate 	err = svc_fini(ep);
39470Sstevel@tonic-gate 
39480Sstevel@tonic-gate 	return (TRUE);
39490Sstevel@tonic-gate }
39500Sstevel@tonic-gate 
39510Sstevel@tonic-gate /*
39520Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
39530Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
39540Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
39550Sstevel@tonic-gate  */
39560Sstevel@tonic-gate bool_t
39570Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_1_svc(
39580Sstevel@tonic-gate 	mdrpc_drives_args	*args,
39590Sstevel@tonic-gate 	mdrpc_generic_res	*res,
39600Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
39610Sstevel@tonic-gate )
39620Sstevel@tonic-gate {
39630Sstevel@tonic-gate 	bool_t			retval;
39640Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
39650Sstevel@tonic-gate 
39660Sstevel@tonic-gate 	/* allocate memory */
39670Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
39680Sstevel@tonic-gate 
39690Sstevel@tonic-gate 	/* build args */
39700Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
39710Sstevel@tonic-gate 	v2_args.sp = args->sp;
39720Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
39730Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
39740Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
39750Sstevel@tonic-gate 	v2_args.genid = args->genid;
39760Sstevel@tonic-gate 
39770Sstevel@tonic-gate 	retval = mdrpc_upd_dr_dbinfo_common(&v2_args, res, rqstp);
39780Sstevel@tonic-gate 
39790Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
39800Sstevel@tonic-gate 
39810Sstevel@tonic-gate 	return (retval);
39820Sstevel@tonic-gate }
39830Sstevel@tonic-gate 
39840Sstevel@tonic-gate bool_t
39850Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_2_svc(
39860Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
39870Sstevel@tonic-gate 	mdrpc_generic_res	*res,
39880Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
39890Sstevel@tonic-gate )
39900Sstevel@tonic-gate {
39910Sstevel@tonic-gate 	switch (args->rev) {
39920Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
39930Sstevel@tonic-gate 		return (mdrpc_upd_dr_dbinfo_common(
39940Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
39950Sstevel@tonic-gate 	    default:
39960Sstevel@tonic-gate 		return (FALSE);
39970Sstevel@tonic-gate 	}
39980Sstevel@tonic-gate }
39990Sstevel@tonic-gate 
40000Sstevel@tonic-gate static void
40010Sstevel@tonic-gate upd_dr_flags(
40020Sstevel@tonic-gate 	mdsetname_t	*sp,
40030Sstevel@tonic-gate 	md_drive_desc	*dd,
40040Sstevel@tonic-gate 	uint_t		new_flags,
40050Sstevel@tonic-gate 	md_error_t	*ep
40060Sstevel@tonic-gate )
40070Sstevel@tonic-gate {
40080Sstevel@tonic-gate 	mdsetname_t	*local_sp;
40090Sstevel@tonic-gate 	md_set_record	*sr;
40100Sstevel@tonic-gate 	md_drive_record	*dr;
40110Sstevel@tonic-gate 	md_drive_desc	*p;
40120Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
40130Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
40140Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
40150Sstevel@tonic-gate 	int		devid_same = -1;
40160Sstevel@tonic-gate 	side_t		sideno;
40170Sstevel@tonic-gate 	int		using_devid = 0;
40180Sstevel@tonic-gate 
40190Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
40200Sstevel@tonic-gate 		return;
40210Sstevel@tonic-gate 
40220Sstevel@tonic-gate 	metaflushsetname(local_sp);
40230Sstevel@tonic-gate 
40240Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
40250Sstevel@tonic-gate 		return;
40260Sstevel@tonic-gate 
40270Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
40280Sstevel@tonic-gate 		return;
40290Sstevel@tonic-gate 
40300Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
40310Sstevel@tonic-gate 		return;
40320Sstevel@tonic-gate 
40330Sstevel@tonic-gate 	/*
40340Sstevel@tonic-gate 	 * The system is either all devid or all
40350Sstevel@tonic-gate 	 * non-devid so we determine this by looking
40360Sstevel@tonic-gate 	 * at the first item in the list.
40370Sstevel@tonic-gate 	 *
40380Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
40390Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
40400Sstevel@tonic-gate 	 * before set the using_devid.
40410Sstevel@tonic-gate 	 */
40420Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
40430Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
40440Sstevel@tonic-gate 		using_devid = 1;
40450Sstevel@tonic-gate 
40460Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
40470Sstevel@tonic-gate 		dn = p->dd_dnp;
40480Sstevel@tonic-gate 		devid_remote = NULL;
40490Sstevel@tonic-gate 
40500Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
40510Sstevel@tonic-gate 		    using_devid) {
40520Sstevel@tonic-gate 			/*
40530Sstevel@tonic-gate 			 * We have a devid so use it.
40540Sstevel@tonic-gate 			 */
40550Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
40560Sstevel@tonic-gate 		}
40570Sstevel@tonic-gate 
40580Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
40590Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
40600Sstevel@tonic-gate 			/* something went really wrong. Can't process */
40610Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
40620Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
40630Sstevel@tonic-gate 			return;
40640Sstevel@tonic-gate 		}
40650Sstevel@tonic-gate 
40660Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
40670Sstevel@tonic-gate 			devid_same = -1;
40680Sstevel@tonic-gate 
40690Sstevel@tonic-gate 			dn1 = metadrivename_withdrkey(local_sp, sideno,
40700Sstevel@tonic-gate 			    dr->dr_key, MD_BASICNAME_OK, ep);
40710Sstevel@tonic-gate 
40720Sstevel@tonic-gate 			if (dn1 == NULL) {
40730Sstevel@tonic-gate 				if (devid_remote)
40740Sstevel@tonic-gate 					devid_free(devid_remote);
40750Sstevel@tonic-gate 				goto out;
40760Sstevel@tonic-gate 			}
40770Sstevel@tonic-gate 
40780Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
40790Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid,
40800Sstevel@tonic-gate 				    &devid_local, NULL) == 0) {
40810Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
40820Sstevel@tonic-gate 					    devid_local);
40830Sstevel@tonic-gate 					devid_free(devid_local);
40840Sstevel@tonic-gate 				}
40850Sstevel@tonic-gate 			}
40860Sstevel@tonic-gate 
40870Sstevel@tonic-gate 			if (using_devid && devid_same == 0)
40880Sstevel@tonic-gate 				break;
40890Sstevel@tonic-gate 
40900Sstevel@tonic-gate 			if (!using_devid &&
40910Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)
40920Sstevel@tonic-gate 				break;
40930Sstevel@tonic-gate 		}
40940Sstevel@tonic-gate 
40950Sstevel@tonic-gate 		if (dr)
40960Sstevel@tonic-gate 			dr->dr_flags = new_flags;
40970Sstevel@tonic-gate 		if (devid_remote)
40980Sstevel@tonic-gate 			devid_free(devid_remote);
40990Sstevel@tonic-gate 	}
41000Sstevel@tonic-gate out:
41010Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
41020Sstevel@tonic-gate 	free_sr(sr);
41030Sstevel@tonic-gate }
41040Sstevel@tonic-gate 
41050Sstevel@tonic-gate /*
41060Sstevel@tonic-gate  * update the database count and size field of drive records.
41070Sstevel@tonic-gate  */
41080Sstevel@tonic-gate bool_t
41090Sstevel@tonic-gate mdrpc_upd_dr_flags_common(
41100Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	*args,
41110Sstevel@tonic-gate 	mdrpc_generic_res		*res,
41120Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
41130Sstevel@tonic-gate )
41140Sstevel@tonic-gate {
41150Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
41160Sstevel@tonic-gate 	int			err;
41170Sstevel@tonic-gate 	int			op_mode = W_OK;
41180Sstevel@tonic-gate 
41190Sstevel@tonic-gate 	/* setup, check permissions */
41200Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
41210Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
41220Sstevel@tonic-gate 		return (FALSE);
41230Sstevel@tonic-gate 	else if (err != 0)
41240Sstevel@tonic-gate 		return (TRUE);
41250Sstevel@tonic-gate 
41260Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
41270Sstevel@tonic-gate 		return (TRUE);
41280Sstevel@tonic-gate 
41290Sstevel@tonic-gate 	/* doit */
41300Sstevel@tonic-gate 	upd_dr_flags(args->sp, args->drivedescs, args->new_flags, ep);
41310Sstevel@tonic-gate 
41320Sstevel@tonic-gate 	err = svc_fini(ep);
41330Sstevel@tonic-gate 
41340Sstevel@tonic-gate 	return (TRUE);
41350Sstevel@tonic-gate }
41360Sstevel@tonic-gate 
41370Sstevel@tonic-gate /*
41380Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
41390Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
41400Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
41410Sstevel@tonic-gate  */
41420Sstevel@tonic-gate bool_t
41430Sstevel@tonic-gate mdrpc_upd_dr_flags_1_svc(
41440Sstevel@tonic-gate 	mdrpc_upd_dr_flags_args	*args,
41450Sstevel@tonic-gate 	mdrpc_generic_res	*res,
41460Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
41470Sstevel@tonic-gate )
41480Sstevel@tonic-gate {
41490Sstevel@tonic-gate 	bool_t				retval;
41500Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	v2_args;
41510Sstevel@tonic-gate 
41520Sstevel@tonic-gate 	/* allocate memory */
41530Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
41540Sstevel@tonic-gate 
41550Sstevel@tonic-gate 	/* build args */
41560Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
41570Sstevel@tonic-gate 	v2_args.sp = args->sp;
41580Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
41590Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
41600Sstevel@tonic-gate 	v2_args.new_flags = args->new_flags;
41610Sstevel@tonic-gate 
41620Sstevel@tonic-gate 	retval = mdrpc_upd_dr_flags_common(&v2_args, res, rqstp);
41630Sstevel@tonic-gate 
41640Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
41650Sstevel@tonic-gate 
41660Sstevel@tonic-gate 	return (retval);
41670Sstevel@tonic-gate }
41680Sstevel@tonic-gate 
41690Sstevel@tonic-gate bool_t
41700Sstevel@tonic-gate mdrpc_upd_dr_flags_2_svc(
41710Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args	*args,
41720Sstevel@tonic-gate 	mdrpc_generic_res		*res,
41730Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
41740Sstevel@tonic-gate )
41750Sstevel@tonic-gate {
41760Sstevel@tonic-gate 	switch (args->rev) {
41770Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
41780Sstevel@tonic-gate 		return (mdrpc_upd_dr_flags_common(
41790Sstevel@tonic-gate 		    &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
41800Sstevel@tonic-gate 	    default:
41810Sstevel@tonic-gate 		return (FALSE);
41820Sstevel@tonic-gate 	}
41830Sstevel@tonic-gate }
41840Sstevel@tonic-gate 
41850Sstevel@tonic-gate static void
41860Sstevel@tonic-gate upd_sr_flags(
41870Sstevel@tonic-gate 	mdsetname_t	*sp,
41880Sstevel@tonic-gate 	uint_t		new_flags,
41890Sstevel@tonic-gate 	md_error_t	*ep
41900Sstevel@tonic-gate )
41910Sstevel@tonic-gate {
41920Sstevel@tonic-gate 	md_set_record	*sr;
41930Sstevel@tonic-gate 
41940Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
41950Sstevel@tonic-gate 		return;
41960Sstevel@tonic-gate 
41970Sstevel@tonic-gate 	sr->sr_flags = new_flags;
41980Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
41990Sstevel@tonic-gate 	free_sr(sr);
42000Sstevel@tonic-gate }
42010Sstevel@tonic-gate 
42020Sstevel@tonic-gate /*
42030Sstevel@tonic-gate  * update the set record flags
42040Sstevel@tonic-gate  */
42050Sstevel@tonic-gate bool_t
42060Sstevel@tonic-gate mdrpc_upd_sr_flags_common(
42070Sstevel@tonic-gate 	mdrpc_upd_sr_flags_args	*args,
42080Sstevel@tonic-gate 	mdrpc_generic_res	*res,
42090Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
42100Sstevel@tonic-gate )
42110Sstevel@tonic-gate {
42120Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
42130Sstevel@tonic-gate 	int			err;
42140Sstevel@tonic-gate 	int			op_mode = W_OK;
42150Sstevel@tonic-gate 
42160Sstevel@tonic-gate 	/* setup, check permissions */
42170Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
42180Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
42190Sstevel@tonic-gate 		return (FALSE);
42200Sstevel@tonic-gate 	else if (err != 0)
42210Sstevel@tonic-gate 		return (TRUE);
42220Sstevel@tonic-gate 
42230Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
42240Sstevel@tonic-gate 		return (TRUE);
42250Sstevel@tonic-gate 
42260Sstevel@tonic-gate 	/* doit */
42270Sstevel@tonic-gate 	upd_sr_flags(args->sp, args->new_flags, ep);
42280Sstevel@tonic-gate 
42290Sstevel@tonic-gate 	err = svc_fini(ep);
42300Sstevel@tonic-gate 
42310Sstevel@tonic-gate 	return (TRUE);
42320Sstevel@tonic-gate }
42330Sstevel@tonic-gate 
42340Sstevel@tonic-gate bool_t
42350Sstevel@tonic-gate mdrpc_upd_sr_flags_1_svc(
42360Sstevel@tonic-gate 	mdrpc_upd_sr_flags_args	*args,
42370Sstevel@tonic-gate 	mdrpc_generic_res	*res,
42380Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
42390Sstevel@tonic-gate )
42400Sstevel@tonic-gate {
42410Sstevel@tonic-gate 	return (mdrpc_upd_sr_flags_common(args, res, rqstp));
42420Sstevel@tonic-gate }
42430Sstevel@tonic-gate 
42440Sstevel@tonic-gate bool_t
42450Sstevel@tonic-gate mdrpc_upd_sr_flags_2_svc(
42460Sstevel@tonic-gate 	mdrpc_upd_sr_flags_2_args	*args,
42470Sstevel@tonic-gate 	mdrpc_generic_res		*res,
42480Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
42490Sstevel@tonic-gate )
42500Sstevel@tonic-gate {
42510Sstevel@tonic-gate 	switch (args->rev) {
42520Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
42530Sstevel@tonic-gate 		return (mdrpc_upd_sr_flags_common(
42540Sstevel@tonic-gate 		    &args->mdrpc_upd_sr_flags_2_args_u.rev1, res, rqstp));
42550Sstevel@tonic-gate 	    default:
42560Sstevel@tonic-gate 		return (FALSE);
42570Sstevel@tonic-gate 	}
42580Sstevel@tonic-gate }
42590Sstevel@tonic-gate 
42600Sstevel@tonic-gate /*
42610Sstevel@tonic-gate  * upd_nr_flags updates the node records stored in this node's local mddb
42620Sstevel@tonic-gate  * given a node desciptor list and an action.  upd_nr_flags then commits
42630Sstevel@tonic-gate  * the node records to the local mddb.
42640Sstevel@tonic-gate  *
42650Sstevel@tonic-gate  * nd - A linked list of node descriptors that describes the node records
42660Sstevel@tonic-gate  *	in this diskset on which the action applies.
42670Sstevel@tonic-gate  * flag_action: action to be taken on node records that match the nd list.
42680Sstevel@tonic-gate  *	flag_action can be:
42690Sstevel@tonic-gate  *		MD_NR_JOIN: set OWN flag in node records
42700Sstevel@tonic-gate  *		MD_NR_WITHDRAW: reset OWN flag in node records
42710Sstevel@tonic-gate  *		MD_NR_OK: reset ADD flags and set OK flag in node records
42720Sstevel@tonic-gate  *		MD_NR_SET: set node record flags based on flags stored in nd
42730Sstevel@tonic-gate  *
42740Sstevel@tonic-gate  * Typically, the JOIN, WITHDRAW and OK flag_actions are used when setting
42750Sstevel@tonic-gate  * all nodes in a diskset to JOIN (add first disk to set), WITHDRAW
42760Sstevel@tonic-gate  * (remove last disk from set) or OK (after addition of host to set).
42770Sstevel@tonic-gate  *
42780Sstevel@tonic-gate  * The SET flag_action is typically used when nodelist contains all nodes
42790Sstevel@tonic-gate  * in the diskset, but specific nodes have had flag changes.  An example of
42800Sstevel@tonic-gate  * this would be the join/withdraw of a specific node to/from the set.
42810Sstevel@tonic-gate  *
42820Sstevel@tonic-gate  * Ignore the MD_MN_NODE_RB_JOIN flag if set in node record flag.  This
42830Sstevel@tonic-gate  * flag is used by the client to recover in case of failure and should not
42840Sstevel@tonic-gate  * be set in the node record flags.
42850Sstevel@tonic-gate  */
42860Sstevel@tonic-gate static void
42870Sstevel@tonic-gate upd_nr_flags(
42880Sstevel@tonic-gate 	mdsetname_t	*sp,
42890Sstevel@tonic-gate 	md_mnnode_desc	*nd,
42900Sstevel@tonic-gate 	uint_t		flag_action,
42910Sstevel@tonic-gate 	md_error_t	*ep
42920Sstevel@tonic-gate )
42930Sstevel@tonic-gate {
42940Sstevel@tonic-gate 	mdsetname_t		*local_sp;
42950Sstevel@tonic-gate 	md_set_record		*sr;
42960Sstevel@tonic-gate 	md_mnset_record		*mnsr;
42970Sstevel@tonic-gate 	md_mnnode_desc		*ndp;
42980Sstevel@tonic-gate 	md_mnnode_record	*nrp;
42990Sstevel@tonic-gate 
43000Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
43010Sstevel@tonic-gate 		return;
43020Sstevel@tonic-gate 
43030Sstevel@tonic-gate 	metaflushsetname(local_sp);
43040Sstevel@tonic-gate 
43050Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
43060Sstevel@tonic-gate 		return;
43070Sstevel@tonic-gate 
43080Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr))) {
43090Sstevel@tonic-gate 		return;
43100Sstevel@tonic-gate 	}
43110Sstevel@tonic-gate 	mnsr = (struct md_mnset_record *)sr;
43120Sstevel@tonic-gate 
43130Sstevel@tonic-gate 	switch (flag_action) {
43140Sstevel@tonic-gate 	case MD_NR_JOIN:
43150Sstevel@tonic-gate 	case MD_NR_WITHDRAW:
43160Sstevel@tonic-gate 	case MD_NR_SET:
43170Sstevel@tonic-gate 	case MD_NR_OK:
43180Sstevel@tonic-gate 	case MD_NR_DEL:
43190Sstevel@tonic-gate 		break;
43200Sstevel@tonic-gate 	default:
43210Sstevel@tonic-gate 		return;
43220Sstevel@tonic-gate 	}
43230Sstevel@tonic-gate 
43240Sstevel@tonic-gate 	for (ndp = nd; ndp != NULL; ndp = ndp->nd_next) {
43250Sstevel@tonic-gate 		/* Find matching node record for given node descriptor */
43260Sstevel@tonic-gate 		for (nrp = mnsr->sr_nodechain; nrp != NULL;
43270Sstevel@tonic-gate 		    nrp = nrp->nr_next) {
43280Sstevel@tonic-gate 			if (ndp->nd_nodeid == nrp->nr_nodeid) {
43290Sstevel@tonic-gate 				switch (flag_action) {
43300Sstevel@tonic-gate 				case MD_NR_JOIN:
43310Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_OWN;
43320Sstevel@tonic-gate 					break;
43330Sstevel@tonic-gate 				case MD_NR_WITHDRAW:
43340Sstevel@tonic-gate 					nrp->nr_flags &= ~MD_MN_NODE_OWN;
43350Sstevel@tonic-gate 					break;
43360Sstevel@tonic-gate 				case MD_NR_OK:
43370Sstevel@tonic-gate 					nrp->nr_flags &=
43380Sstevel@tonic-gate 					    ~(MD_MN_NODE_ADD | MD_MN_NODE_DEL);
43390Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_OK;
43400Sstevel@tonic-gate 					break;
43410Sstevel@tonic-gate 				case MD_NR_DEL:
43420Sstevel@tonic-gate 					nrp->nr_flags &=
43430Sstevel@tonic-gate 					    ~(MD_MN_NODE_OK | MD_MN_NODE_ADD);
43440Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_DEL;
43450Sstevel@tonic-gate 					break;
43460Sstevel@tonic-gate 				case MD_NR_SET:
43470Sstevel@tonic-gate 					/* Do not set RB_JOIN flag */
43480Sstevel@tonic-gate 					nrp->nr_flags =
43490Sstevel@tonic-gate 					    ndp->nd_flags & ~MD_MN_NODE_RB_JOIN;
43500Sstevel@tonic-gate 					break;
43510Sstevel@tonic-gate 				}
43520Sstevel@tonic-gate 				break;
43530Sstevel@tonic-gate 			}
43540Sstevel@tonic-gate 		}
43550Sstevel@tonic-gate 	}
43560Sstevel@tonic-gate out:
43570Sstevel@tonic-gate 	/* Don't increment set genid for node record flag update */
43580Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
43590Sstevel@tonic-gate 	free_sr(sr);
43600Sstevel@tonic-gate }
43610Sstevel@tonic-gate 
43620Sstevel@tonic-gate /*
43630Sstevel@tonic-gate  * init/fini wrapper around upd_nr_flags
43640Sstevel@tonic-gate  */
43650Sstevel@tonic-gate bool_t
43660Sstevel@tonic-gate mdrpc_upd_nr_flags_common(
43670Sstevel@tonic-gate 	mdrpc_upd_nr_flags_args	*args,
43680Sstevel@tonic-gate 	mdrpc_generic_res	*res,
43690Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
43700Sstevel@tonic-gate )
43710Sstevel@tonic-gate {
43720Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
43730Sstevel@tonic-gate 	int			err;
43740Sstevel@tonic-gate 	int			op_mode = W_OK;
43750Sstevel@tonic-gate 
43760Sstevel@tonic-gate 	/* setup, check permissions */
43770Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
43780Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
43790Sstevel@tonic-gate 		return (FALSE);
43800Sstevel@tonic-gate 	else if (err != 0)
43810Sstevel@tonic-gate 		return (TRUE);
43820Sstevel@tonic-gate 
43830Sstevel@tonic-gate 	/*
43840Sstevel@tonic-gate 	 * During reconfig, node record flags can be updated without
43850Sstevel@tonic-gate 	 * locking first.
43860Sstevel@tonic-gate 	 */
43870Sstevel@tonic-gate 	if (!(args->flags & MNSET_IN_RECONFIG)) {
43880Sstevel@tonic-gate 		if (check_set_lock(op_mode, args->cl_sk, ep))
43890Sstevel@tonic-gate 			return (TRUE);
43900Sstevel@tonic-gate 	}
43910Sstevel@tonic-gate 
43920Sstevel@tonic-gate 	/* doit */
43930Sstevel@tonic-gate 	upd_nr_flags(args->sp, args->nodedescs, args->flag_action, ep);
43940Sstevel@tonic-gate 
43950Sstevel@tonic-gate 	err = svc_fini(ep);
43960Sstevel@tonic-gate 
43970Sstevel@tonic-gate 	return (TRUE);
43980Sstevel@tonic-gate }
43990Sstevel@tonic-gate 
44000Sstevel@tonic-gate /*
44010Sstevel@tonic-gate  * update the node records using given flag action.
44020Sstevel@tonic-gate  */
44030Sstevel@tonic-gate bool_t
44040Sstevel@tonic-gate mdrpc_upd_nr_flags_2_svc(
44050Sstevel@tonic-gate 	mdrpc_upd_nr_flags_2_args	*args,
44060Sstevel@tonic-gate 	mdrpc_generic_res		*res,
44070Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
44080Sstevel@tonic-gate )
44090Sstevel@tonic-gate {
44100Sstevel@tonic-gate 	switch (args->rev) {
44110Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
44120Sstevel@tonic-gate 		return (mdrpc_upd_nr_flags_common(
44130Sstevel@tonic-gate 		    &args->mdrpc_upd_nr_flags_2_args_u.rev1, res, rqstp));
44140Sstevel@tonic-gate 	    default:
44150Sstevel@tonic-gate 		return (FALSE);
44160Sstevel@tonic-gate 	}
44170Sstevel@tonic-gate }
44180Sstevel@tonic-gate 
44190Sstevel@tonic-gate void
44200Sstevel@tonic-gate free_sk(md_setkey_t *skp)
44210Sstevel@tonic-gate {
44220Sstevel@tonic-gate 	Free(skp->sk_setname);
44230Sstevel@tonic-gate 	Free(skp->sk_host);
44240Sstevel@tonic-gate 	Free(skp);
44250Sstevel@tonic-gate }
44260Sstevel@tonic-gate 
44270Sstevel@tonic-gate void
44280Sstevel@tonic-gate del_sk(set_t setno)
44290Sstevel@tonic-gate {
44300Sstevel@tonic-gate 	md_setkey_t	*skp;
44310Sstevel@tonic-gate 	md_setkey_t	*tskp;
44320Sstevel@tonic-gate 
44330Sstevel@tonic-gate 	for (skp = tskp = my_svc_sk; skp; tskp = skp, skp = skp->sk_next) {
44340Sstevel@tonic-gate 		if (setno == skp->sk_setno) {
44350Sstevel@tonic-gate 			if (skp == my_svc_sk)
44360Sstevel@tonic-gate 				my_svc_sk = skp->sk_next;
44370Sstevel@tonic-gate 			else
44380Sstevel@tonic-gate 				tskp->sk_next = skp->sk_next;
44390Sstevel@tonic-gate 
44400Sstevel@tonic-gate 			Free(skp->sk_setname);
44410Sstevel@tonic-gate 			Free(skp->sk_host);
44420Sstevel@tonic-gate 			Free(skp);
44430Sstevel@tonic-gate 			break;
44440Sstevel@tonic-gate 		}
44450Sstevel@tonic-gate 	}
44460Sstevel@tonic-gate }
44470Sstevel@tonic-gate 
44480Sstevel@tonic-gate md_setkey_t *
44490Sstevel@tonic-gate dupsk(md_setkey_t *skp)
44500Sstevel@tonic-gate {
44510Sstevel@tonic-gate 	md_setkey_t	*tskp;
44520Sstevel@tonic-gate 
44530Sstevel@tonic-gate 	tskp = Zalloc(sizeof (md_setkey_t));
44540Sstevel@tonic-gate 
44550Sstevel@tonic-gate 	*tskp = *skp;
44560Sstevel@tonic-gate 	tskp->sk_host = Strdup(skp->sk_host);
44570Sstevel@tonic-gate 	tskp->sk_setname = Strdup(skp->sk_setname);
44580Sstevel@tonic-gate 
44590Sstevel@tonic-gate 	return (tskp);
44600Sstevel@tonic-gate }
44610Sstevel@tonic-gate 
44620Sstevel@tonic-gate md_setkey_t *
44630Sstevel@tonic-gate svc_get_setkey(set_t setno)
44640Sstevel@tonic-gate {
44650Sstevel@tonic-gate 	md_setkey_t	*skp;
44660Sstevel@tonic-gate 
44670Sstevel@tonic-gate 	for (skp = my_svc_sk; skp != NULL; skp = skp->sk_next)
44680Sstevel@tonic-gate 		if (setno == skp->sk_setno)
44690Sstevel@tonic-gate 			return (dupsk(skp));
44700Sstevel@tonic-gate 	return (NULL);
44710Sstevel@tonic-gate }
44720Sstevel@tonic-gate 
44730Sstevel@tonic-gate void
44740Sstevel@tonic-gate svc_set_setkey(md_setkey_t *svc_sk)
44750Sstevel@tonic-gate {
44760Sstevel@tonic-gate 	md_setkey_t	*skp;
44770Sstevel@tonic-gate 
44780Sstevel@tonic-gate 	if (my_svc_sk == NULL) {
44790Sstevel@tonic-gate 		my_svc_sk = dupsk(svc_sk);
44800Sstevel@tonic-gate 		return;
44810Sstevel@tonic-gate 	}
44820Sstevel@tonic-gate 
44830Sstevel@tonic-gate 	for (skp = my_svc_sk; skp->sk_next != NULL; skp = skp->sk_next)
44840Sstevel@tonic-gate 		assert(svc_sk->sk_setno != skp->sk_setno);
44850Sstevel@tonic-gate 
44860Sstevel@tonic-gate 	skp->sk_next = dupsk(svc_sk);
44870Sstevel@tonic-gate }
44880Sstevel@tonic-gate 
44890Sstevel@tonic-gate /*
44900Sstevel@tonic-gate  * Unlock the set
44910Sstevel@tonic-gate  *
44920Sstevel@tonic-gate  * To unlock the set, the user must have the correct key, once this is verified
44930Sstevel@tonic-gate  * the set is unlocked and the cached information for the set is flushed.
44940Sstevel@tonic-gate  */
44950Sstevel@tonic-gate bool_t
44960Sstevel@tonic-gate mdrpc_unlock_set_common(
44970Sstevel@tonic-gate 	mdrpc_null_args		*args,
44980Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
44990Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
45000Sstevel@tonic-gate )
45010Sstevel@tonic-gate {
45020Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
45030Sstevel@tonic-gate 	int			err;
45040Sstevel@tonic-gate 	int			op_mode = W_OK;
45050Sstevel@tonic-gate 	md_setkey_t		*svc_skp;
45060Sstevel@tonic-gate 	md_set_desc		*sd;
45070Sstevel@tonic-gate 	mdsetname_t		*sp;
45080Sstevel@tonic-gate 	int			multi_node = 0;
45090Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
45100Sstevel@tonic-gate 
45110Sstevel@tonic-gate 	/* setup, check permissions */
45120Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
45130Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
45140Sstevel@tonic-gate 		return (FALSE);
45150Sstevel@tonic-gate 	else if (err != 0)
45160Sstevel@tonic-gate 		return (TRUE);
45170Sstevel@tonic-gate 
45180Sstevel@tonic-gate 	/*
45190Sstevel@tonic-gate 	 * Is diskset a MN diskset?
45200Sstevel@tonic-gate 	 * Don't set error from this check since unlock set can be
45210Sstevel@tonic-gate 	 * called after a set has been deleted.
45220Sstevel@tonic-gate 	 */
45230Sstevel@tonic-gate 	if (((sp = metasetnosetname(args->cl_sk->sk_setno, &xep)) != NULL) &&
45240Sstevel@tonic-gate 	    ((sd = metaget_setdesc(sp, &xep)) != NULL)) {
45250Sstevel@tonic-gate 		if ((MD_MNSET_DESC(sd))) {
45260Sstevel@tonic-gate 			multi_node = 1;
45270Sstevel@tonic-gate 		}
45280Sstevel@tonic-gate 	}
45290Sstevel@tonic-gate 
45300Sstevel@tonic-gate 	/* Get the set key, if any */
45310Sstevel@tonic-gate 	svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
45320Sstevel@tonic-gate 
45330Sstevel@tonic-gate 	/* The set is locked */
45340Sstevel@tonic-gate 	if (svc_skp != NULL) {
45350Sstevel@tonic-gate 
45360Sstevel@tonic-gate 		/* Make sure the opener has the right key. */
45370Sstevel@tonic-gate 		if (args->cl_sk->sk_key.tv_sec != svc_skp->sk_key.tv_sec ||
45380Sstevel@tonic-gate 		    args->cl_sk->sk_key.tv_usec != svc_skp->sk_key.tv_usec) {
45390Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_ULKSBADKEY,
45400Sstevel@tonic-gate 			    svc_skp->sk_setno, mynode(), svc_skp->sk_host,
45410Sstevel@tonic-gate 			    svc_skp->sk_setname);
45420Sstevel@tonic-gate 			free_sk(svc_skp);
45430Sstevel@tonic-gate 			return (TRUE);
45440Sstevel@tonic-gate 		}
45450Sstevel@tonic-gate 
45460Sstevel@tonic-gate 		/* Unlock the set */
45470Sstevel@tonic-gate 		del_sk(args->cl_sk->sk_setno);
45480Sstevel@tonic-gate 
45490Sstevel@tonic-gate 		/* Cleanup */
45500Sstevel@tonic-gate 		free_sk(svc_skp);
45510Sstevel@tonic-gate 
45520Sstevel@tonic-gate 		goto out;
45530Sstevel@tonic-gate 	}
45540Sstevel@tonic-gate 
45550Sstevel@tonic-gate 
45560Sstevel@tonic-gate 	/*
45570Sstevel@tonic-gate 	 * It is possible on a MN diskset to attempt to unlock a set that
45580Sstevel@tonic-gate 	 * is unlocked.  This could occur when the metaset or metadb  command
45590Sstevel@tonic-gate 	 * is failing due to another metaset or metadb command running.
45600Sstevel@tonic-gate 	 * So, print no warning for MN disksets.
45610Sstevel@tonic-gate 	 */
45620Sstevel@tonic-gate 	if (multi_node == 0) {
45630Sstevel@tonic-gate 		md_eprintf("Warning: set unlocked when unlock_set called!\n");
45640Sstevel@tonic-gate 	}
45650Sstevel@tonic-gate 
45660Sstevel@tonic-gate out:
45670Sstevel@tonic-gate 	res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
45680Sstevel@tonic-gate 
45690Sstevel@tonic-gate 	/* Flush the set cache */
45700Sstevel@tonic-gate 	sr_cache_flush_setno(args->cl_sk->sk_setno);
45710Sstevel@tonic-gate 
45720Sstevel@tonic-gate 	return (TRUE);
45730Sstevel@tonic-gate }
45740Sstevel@tonic-gate 
45750Sstevel@tonic-gate bool_t
45760Sstevel@tonic-gate mdrpc_unlock_set_1_svc(
45770Sstevel@tonic-gate 	mdrpc_null_args		*args,
45780Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
45790Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
45800Sstevel@tonic-gate )
45810Sstevel@tonic-gate {
45820Sstevel@tonic-gate 	return (mdrpc_unlock_set_common(args, res, rqstp));
45830Sstevel@tonic-gate }
45840Sstevel@tonic-gate 
45850Sstevel@tonic-gate bool_t
45860Sstevel@tonic-gate mdrpc_unlock_set_2_svc(
45870Sstevel@tonic-gate 	mdrpc_null_args		*args,
45880Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
45890Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
45900Sstevel@tonic-gate )
45910Sstevel@tonic-gate {
45920Sstevel@tonic-gate 	return (mdrpc_unlock_set_common(args, res, rqstp));
45930Sstevel@tonic-gate }
45940Sstevel@tonic-gate 
45950Sstevel@tonic-gate /*
45960Sstevel@tonic-gate  * Lock the set
45970Sstevel@tonic-gate  *
45980Sstevel@tonic-gate  * If the user does not hand us a key, then we generate a new key and lock the
45990Sstevel@tonic-gate  * set using this new key that was generated, if the user hands us a key then
46000Sstevel@tonic-gate  * we use the key to lock the set.
46010Sstevel@tonic-gate  */
46020Sstevel@tonic-gate bool_t
46030Sstevel@tonic-gate mdrpc_lock_set_common(
46040Sstevel@tonic-gate 	mdrpc_null_args		*args,
46050Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
46060Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
46070Sstevel@tonic-gate )
46080Sstevel@tonic-gate {
46090Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
46100Sstevel@tonic-gate 	int			err;
46110Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
46120Sstevel@tonic-gate 	int			op_mode = W_OK;
46130Sstevel@tonic-gate 	md_setkey_t		*svc_skp;
46140Sstevel@tonic-gate 	md_setkey_t		new_sk;
46151320Srd117015 	md_set_desc		*sd = NULL;
46161320Srd117015 	mdsetname_t		*sp = NULL;
46170Sstevel@tonic-gate 
46180Sstevel@tonic-gate 	/* setup, check permissions */
46190Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
46200Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
46210Sstevel@tonic-gate 		return (FALSE);
46220Sstevel@tonic-gate 	else if (err != 0)
46230Sstevel@tonic-gate 		return (TRUE);
46240Sstevel@tonic-gate 
46250Sstevel@tonic-gate 	svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
46260Sstevel@tonic-gate 
46271320Srd117015 	/* The set is locked */
46281320Srd117015 	if (svc_skp != NULL) {
46291320Srd117015 
46301320Srd117015 		/*
46311320Srd117015 		 * This lock request could be for a new diskset, as
46321320Srd117015 		 * such metasetnosetname() may not return anything
46331320Srd117015 		 * useful. Only call it if there is already a key.
46341320Srd117015 		 */
46351320Srd117015 		if ((sp = metasetnosetname(args->cl_sk->sk_setno, ep))
46361320Srd117015 		    != NULL) {
46371320Srd117015 			sd = metaget_setdesc(sp, ep);
46381320Srd117015 		}
46391320Srd117015 
46401320Srd117015 		/*
46411320Srd117015 		 * meta_lock() provides local locking for non-MN
46421320Srd117015 		 * disksets. The local lock is held before we call
46431320Srd117015 		 * this RPC function. We should not receive a lock
46441320Srd117015 		 * request from the host which owns the lock. If we
46451320Srd117015 		 * do, release the lock.
46461320Srd117015 		 */
46471320Srd117015 		if (!((sd != NULL) && (MD_MNSET_DESC(sd))) &&
46481320Srd117015 		    (strcmp(svc_skp->sk_host, args->cl_sk->sk_host) == 0)) {
46491320Srd117015 			md_eprintf(
46501320Srd117015 			    "Warning: set locked when lock_set called!\n");
46511320Srd117015 
46521320Srd117015 			md_eprintf("Held lock info:\n");
46531320Srd117015 
46541320Srd117015 			md_eprintf("\tLock:\n");
46551320Srd117015 			md_eprintf("\t\tSetname: %s\n", svc_skp->sk_setname);
46561320Srd117015 			md_eprintf("\t\tSetno:   %d\n", svc_skp->sk_setno);
46571320Srd117015 			md_eprintf("\t\tHost:    %s\n", svc_skp->sk_host);
46581320Srd117015 			md_eprintf("\t\tKey:     %d/%d %s\n",
46591320Srd117015 			    svc_skp->sk_key.tv_sec, svc_skp->sk_key.tv_usec,
46601320Srd117015 			    ctime((const time_t *)&svc_skp->sk_key.tv_sec));
46611320Srd117015 
46621320Srd117015 			/* Unlock set */
46631320Srd117015 			del_sk(svc_skp->sk_setno);
46641320Srd117015 			free_sk(svc_skp);
46651320Srd117015 			svc_skp = NULL;
46661320Srd117015 
46671320Srd117015 			md_eprintf("Released lock held by requesting host\n");
46681320Srd117015 		}
46691320Srd117015 	}
46701320Srd117015 
46710Sstevel@tonic-gate 	/* The set is unlocked */
46720Sstevel@tonic-gate 	if (svc_skp == NULL) {
46730Sstevel@tonic-gate 		/* If we have been given a key, use it. */
46740Sstevel@tonic-gate 		if (args->cl_sk->sk_key.tv_sec || args->cl_sk->sk_key.tv_usec) {
46750Sstevel@tonic-gate 			svc_set_setkey(args->cl_sk);
46760Sstevel@tonic-gate 			res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
46770Sstevel@tonic-gate 			goto out;
46780Sstevel@tonic-gate 		}
46790Sstevel@tonic-gate 
46800Sstevel@tonic-gate 		/* We need to lock it, with a new key */
46810Sstevel@tonic-gate 		new_sk = *args->cl_sk;
46820Sstevel@tonic-gate 		if (meta_gettimeofday(&new_sk.sk_key) == -1) {
46830Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, "meta_gettimeofday()");
46840Sstevel@tonic-gate 			mde_perror(&xep, "");
46850Sstevel@tonic-gate 			md_exit(NULL, 1);
46860Sstevel@tonic-gate 		}
46870Sstevel@tonic-gate 		svc_set_setkey(&new_sk);
46880Sstevel@tonic-gate 
46890Sstevel@tonic-gate 		res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
46900Sstevel@tonic-gate 		goto out;
46910Sstevel@tonic-gate 	}
46920Sstevel@tonic-gate 
46930Sstevel@tonic-gate 	/*
46940Sstevel@tonic-gate 	 * If a MN diskset, the lock_set routine is used as a locking
46950Sstevel@tonic-gate 	 * mechanism to keep multiple metaset and/or metadb commads
46960Sstevel@tonic-gate 	 * from interfering with each other.  If two metaset/metadb
46970Sstevel@tonic-gate 	 * commands are issued at the same time - one will complete
46980Sstevel@tonic-gate 	 * and the other command will fail with MDE_DS_NOTNOW_CMD.
46990Sstevel@tonic-gate 	 */
47001320Srd117015 	if ((sd != NULL) && MD_MNSET_DESC(sd)) {
47010Sstevel@tonic-gate 		(void) mddserror(ep, MDE_DS_NOTNOW_CMD,
47020Sstevel@tonic-gate 		    svc_skp->sk_setno, mynode(),
47030Sstevel@tonic-gate 		    svc_skp->sk_host, svc_skp->sk_setname);
47040Sstevel@tonic-gate 		goto out;
47050Sstevel@tonic-gate 	}
47060Sstevel@tonic-gate 
47070Sstevel@tonic-gate 	md_eprintf("Warning: set locked when lock_set called!\n");
47080Sstevel@tonic-gate 
47090Sstevel@tonic-gate 	md_eprintf("Lock info:\n");
47100Sstevel@tonic-gate 
47110Sstevel@tonic-gate 	md_eprintf("\tLock(svc):\n");
47120Sstevel@tonic-gate 	md_eprintf("\t\tSetname: %s\n", svc_skp->sk_setname);
47130Sstevel@tonic-gate 	md_eprintf("\t\tSetno:   %d\n", svc_skp->sk_setno);
47140Sstevel@tonic-gate 	md_eprintf("\t\tHost:    %s\n", svc_skp->sk_host);
47150Sstevel@tonic-gate 	md_eprintf("\t\tKey:     %d/%d %s",
47160Sstevel@tonic-gate 	    svc_skp->sk_key.tv_sec, svc_skp->sk_key.tv_usec,
47170Sstevel@tonic-gate 	    ctime((const time_t *)&svc_skp->sk_key.tv_sec));
47180Sstevel@tonic-gate 
47190Sstevel@tonic-gate 	md_eprintf("\tLock(cl):\n");
47200Sstevel@tonic-gate 	md_eprintf("\t\tSetname: %s\n", args->cl_sk->sk_setname);
47210Sstevel@tonic-gate 	md_eprintf("\t\tSetno:   %d\n", args->cl_sk->sk_setno);
47220Sstevel@tonic-gate 	md_eprintf("\t\tHost:    %s\n", args->cl_sk->sk_host);
47230Sstevel@tonic-gate 	md_eprintf("\t\tKey:     %d/%d %s",
47240Sstevel@tonic-gate 	    args->cl_sk->sk_key.tv_sec, args->cl_sk->sk_key.tv_usec,
47250Sstevel@tonic-gate 	    ctime((const time_t *)&args->cl_sk->sk_key.tv_sec));
47260Sstevel@tonic-gate 
47270Sstevel@tonic-gate 	/* The set is locked, do we have the key? */
47280Sstevel@tonic-gate 	if (args->cl_sk->sk_key.tv_sec == svc_skp->sk_key.tv_sec &&
47290Sstevel@tonic-gate 	    args->cl_sk->sk_key.tv_usec == svc_skp->sk_key.tv_usec) {
47300Sstevel@tonic-gate 		res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
47310Sstevel@tonic-gate 		goto out;
47320Sstevel@tonic-gate 	}
47330Sstevel@tonic-gate 
47340Sstevel@tonic-gate 	/*
47350Sstevel@tonic-gate 	 * The set is locked and we do not have the key, so we set up an error.
47360Sstevel@tonic-gate 	 */
47370Sstevel@tonic-gate 	(void) mddserror(ep, MDE_DS_LKSBADKEY, svc_skp->sk_setno, mynode(),
47380Sstevel@tonic-gate 	    svc_skp->sk_host, args->cl_sk->sk_setname);
47390Sstevel@tonic-gate 
47400Sstevel@tonic-gate out:
47410Sstevel@tonic-gate 	if (svc_skp != NULL)
47420Sstevel@tonic-gate 		free_sk(svc_skp);
47430Sstevel@tonic-gate 
47440Sstevel@tonic-gate 	/* Flush the set cache */
47450Sstevel@tonic-gate 	sr_cache_flush_setno(args->cl_sk->sk_setno);
47460Sstevel@tonic-gate 
47470Sstevel@tonic-gate 	return (TRUE);
47480Sstevel@tonic-gate }
47490Sstevel@tonic-gate 
47500Sstevel@tonic-gate bool_t
47510Sstevel@tonic-gate mdrpc_lock_set_1_svc(
47520Sstevel@tonic-gate 	mdrpc_null_args		*args,
47530Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
47540Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
47550Sstevel@tonic-gate )
47560Sstevel@tonic-gate {
47570Sstevel@tonic-gate 	return (mdrpc_lock_set_common(args, res, rqstp));
47580Sstevel@tonic-gate }
47590Sstevel@tonic-gate 
47600Sstevel@tonic-gate bool_t
47610Sstevel@tonic-gate mdrpc_lock_set_2_svc(
47620Sstevel@tonic-gate 	mdrpc_null_args		*args,
47630Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
47640Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
47650Sstevel@tonic-gate )
47660Sstevel@tonic-gate {
47670Sstevel@tonic-gate 	return (mdrpc_lock_set_common(args, res, rqstp));
47680Sstevel@tonic-gate }
47690Sstevel@tonic-gate 
47700Sstevel@tonic-gate static void
47710Sstevel@tonic-gate updmeds(
47720Sstevel@tonic-gate 	char		*setname,
47730Sstevel@tonic-gate 	md_h_arr_t	*medp,
47740Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
47750Sstevel@tonic-gate 	md_error_t	*ep
47760Sstevel@tonic-gate )
47770Sstevel@tonic-gate {
47780Sstevel@tonic-gate 	mddb_userreq_t		req;
47790Sstevel@tonic-gate 	md_set_record		*sr;
47800Sstevel@tonic-gate 	mddb_med_parm_t		mp;
47810Sstevel@tonic-gate 
47820Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
47830Sstevel@tonic-gate 		return;
47840Sstevel@tonic-gate 
47850Sstevel@tonic-gate 	sr->sr_med = *medp;			/* structure assignment */
47860Sstevel@tonic-gate 
47870Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
47880Sstevel@tonic-gate 
47890Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
47900Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
47910Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
47920Sstevel@tonic-gate 		req.ur_size = sizeof (struct md_mnset_record);
47930Sstevel@tonic-gate 	} else {
47940Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
47950Sstevel@tonic-gate 	}
47960Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
47970Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
47980Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
47990Sstevel@tonic-gate 		free_sr(sr);
48000Sstevel@tonic-gate 		return;
48010Sstevel@tonic-gate 	}
48020Sstevel@tonic-gate 
48030Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
48040Sstevel@tonic-gate 
48050Sstevel@tonic-gate 	/*
48060Sstevel@tonic-gate 	 * If a MN disket, send the mediator list to the kernel.
48070Sstevel@tonic-gate 	 */
48080Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
48090Sstevel@tonic-gate 		(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
48100Sstevel@tonic-gate 		mp.med_setno = sr->sr_setno;
48110Sstevel@tonic-gate 		if (meta_h2hi(medp, &mp.med, ep)) {
48120Sstevel@tonic-gate 			free_sr(sr);
48130Sstevel@tonic-gate 			return;
48140Sstevel@tonic-gate 		}
48150Sstevel@tonic-gate 
48160Sstevel@tonic-gate 		/* Resolve the IP addresses for the host list */
48170Sstevel@tonic-gate 		if (meta_med_hnm2ip(&mp.med, ep)) {
48180Sstevel@tonic-gate 			free_sr(sr);
48190Sstevel@tonic-gate 			return;
48200Sstevel@tonic-gate 		}
48210Sstevel@tonic-gate 
48220Sstevel@tonic-gate 		/* If node not yet joined to set, failure is ok. */
48230Sstevel@tonic-gate 		if (metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL) != 0) {
48240Sstevel@tonic-gate 			if (!mdismddberror(&mp.med_mde, MDE_DB_NOTOWNER)) {
48250Sstevel@tonic-gate 				(void) mdstealerror(ep, &mp.med_mde);
48260Sstevel@tonic-gate 			}
48270Sstevel@tonic-gate 		}
48280Sstevel@tonic-gate 	}
48290Sstevel@tonic-gate 	free_sr(sr);
48300Sstevel@tonic-gate }
48310Sstevel@tonic-gate 
48320Sstevel@tonic-gate /*
48330Sstevel@tonic-gate  * Update the mediator data in the set record
48340Sstevel@tonic-gate  */
48350Sstevel@tonic-gate bool_t
48360Sstevel@tonic-gate mdrpc_updmeds_common(
48370Sstevel@tonic-gate 	mdrpc_updmeds_args	*args,
48380Sstevel@tonic-gate 	mdrpc_generic_res	*res,
48390Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
48400Sstevel@tonic-gate 	int			version		/* RPC version */
48410Sstevel@tonic-gate )
48420Sstevel@tonic-gate {
48430Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
48440Sstevel@tonic-gate 	int			err;
48450Sstevel@tonic-gate 	int			op_mode = W_OK;
48460Sstevel@tonic-gate 
48470Sstevel@tonic-gate 	/* setup, check permissions */
48480Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
48490Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
48500Sstevel@tonic-gate 		return (FALSE);
48510Sstevel@tonic-gate 	else if (err != 0)
48520Sstevel@tonic-gate 		return (TRUE);
48530Sstevel@tonic-gate 
48540Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
48550Sstevel@tonic-gate 		return (TRUE);
48560Sstevel@tonic-gate 
48570Sstevel@tonic-gate 	/* doit */
48580Sstevel@tonic-gate 	updmeds(args->sp->setname, &args->meds, version, ep);
48590Sstevel@tonic-gate 
48600Sstevel@tonic-gate 	err = svc_fini(ep);
48610Sstevel@tonic-gate 
48620Sstevel@tonic-gate 	return (TRUE);
48630Sstevel@tonic-gate }
48640Sstevel@tonic-gate 
48650Sstevel@tonic-gate bool_t
48660Sstevel@tonic-gate mdrpc_updmeds_1_svc(
48670Sstevel@tonic-gate 	mdrpc_updmeds_args	*args,
48680Sstevel@tonic-gate 	mdrpc_generic_res	*res,
48690Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
48700Sstevel@tonic-gate )
48710Sstevel@tonic-gate {
48720Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
48730Sstevel@tonic-gate 	return (mdrpc_updmeds_common(args, res, rqstp, METAD_VERSION));
48740Sstevel@tonic-gate }
48750Sstevel@tonic-gate 
48760Sstevel@tonic-gate bool_t
48770Sstevel@tonic-gate mdrpc_updmeds_2_svc(
48780Sstevel@tonic-gate 	mdrpc_updmeds_2_args	*args,
48790Sstevel@tonic-gate 	mdrpc_generic_res	*res,
48800Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
48810Sstevel@tonic-gate )
48820Sstevel@tonic-gate {
48830Sstevel@tonic-gate 	switch (args->rev) {
48840Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
48850Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
48860Sstevel@tonic-gate 		return (mdrpc_updmeds_common(
48870Sstevel@tonic-gate 		    &args->mdrpc_updmeds_2_args_u.rev1, res,
48880Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
48890Sstevel@tonic-gate 	    default:
48900Sstevel@tonic-gate 		return (FALSE);
48910Sstevel@tonic-gate 	}
48920Sstevel@tonic-gate }
48930Sstevel@tonic-gate 
48940Sstevel@tonic-gate /*
48950Sstevel@tonic-gate  * Call routines to suspend, reinit and resume mdcommd.
48960Sstevel@tonic-gate  * Called during metaset and metadb command.
48970Sstevel@tonic-gate  * NOT called during reconfig cycle.
48980Sstevel@tonic-gate  */
48990Sstevel@tonic-gate bool_t
49000Sstevel@tonic-gate mdrpc_mdcommdctl_2_svc(
49010Sstevel@tonic-gate 	mdrpc_mdcommdctl_2_args	*args,
49020Sstevel@tonic-gate 	mdrpc_generic_res	*res,
49030Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
49040Sstevel@tonic-gate )
49050Sstevel@tonic-gate {
49060Sstevel@tonic-gate 	mdrpc_mdcommdctl_args	*args_cc;
49070Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
49080Sstevel@tonic-gate 	int			err;
49090Sstevel@tonic-gate 	int			op_mode = R_OK;
49100Sstevel@tonic-gate 	int			suspend_ret;
49110Sstevel@tonic-gate 
49120Sstevel@tonic-gate 	switch (args->rev) {
49130Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
49140Sstevel@tonic-gate 		/* setup, check permissions */
49150Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
49160Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
49170Sstevel@tonic-gate 			return (FALSE);
49180Sstevel@tonic-gate 		else if (err != 0)
49190Sstevel@tonic-gate 			return (TRUE);
49200Sstevel@tonic-gate 
49210Sstevel@tonic-gate 		args_cc = &(args->mdrpc_mdcommdctl_2_args_u.rev1);
49220Sstevel@tonic-gate 		switch (args_cc->flag_action) {
49230Sstevel@tonic-gate 			case COMMDCTL_SUSPEND:
49240Sstevel@tonic-gate 				suspend_ret = mdmn_suspend(args_cc->setno,
49250Sstevel@tonic-gate 				    args_cc->class);
49260Sstevel@tonic-gate 				if (suspend_ret != 0) {
49270Sstevel@tonic-gate 					(void) mddserror(ep, suspend_ret,
49280Sstevel@tonic-gate 					    args_cc->setno, mynode(),
49290Sstevel@tonic-gate 					    NULL, mynode());
49300Sstevel@tonic-gate 				}
49310Sstevel@tonic-gate 				break;
49320Sstevel@tonic-gate 			case COMMDCTL_RESUME:
49330Sstevel@tonic-gate 				if (mdmn_resume(args_cc->setno,
49340Sstevel@tonic-gate 				    args_cc->class, args_cc->flags)) {
49350Sstevel@tonic-gate 					(void) mddserror(ep,
49360Sstevel@tonic-gate 					    MDE_DS_COMMDCTL_RESUME_FAIL,
49370Sstevel@tonic-gate 					    args_cc->setno, mynode(),
49380Sstevel@tonic-gate 					    NULL, mynode());
49390Sstevel@tonic-gate 				}
49400Sstevel@tonic-gate 				break;
49410Sstevel@tonic-gate 			case COMMDCTL_REINIT:
49420Sstevel@tonic-gate 				if (mdmn_reinit_set(args_cc->setno)) {
49430Sstevel@tonic-gate 					(void) mddserror(ep,
49440Sstevel@tonic-gate 					    MDE_DS_COMMDCTL_REINIT_FAIL,
49450Sstevel@tonic-gate 					    args_cc->setno, mynode(),
49460Sstevel@tonic-gate 					    NULL, mynode());
49470Sstevel@tonic-gate 				}
49480Sstevel@tonic-gate 				break;
49490Sstevel@tonic-gate 		}
49500Sstevel@tonic-gate 		err = svc_fini(ep);
49510Sstevel@tonic-gate 		return (TRUE);
49520Sstevel@tonic-gate 
49530Sstevel@tonic-gate 	    default:
49540Sstevel@tonic-gate 		return (FALSE);
49550Sstevel@tonic-gate 	}
49560Sstevel@tonic-gate }
49570Sstevel@tonic-gate 
49580Sstevel@tonic-gate /*
49590Sstevel@tonic-gate  * Return TRUE if set is stale.
49600Sstevel@tonic-gate  */
49610Sstevel@tonic-gate bool_t
49620Sstevel@tonic-gate mdrpc_mn_is_stale_2_svc(
49630Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
49640Sstevel@tonic-gate 	mdrpc_bool_res		*res,
49650Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
49660Sstevel@tonic-gate )
49670Sstevel@tonic-gate {
49680Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
49690Sstevel@tonic-gate 	mddb_config_t	c;
49700Sstevel@tonic-gate 	int		err;
49710Sstevel@tonic-gate 	int		op_mode = R_OK;
49720Sstevel@tonic-gate 
49730Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
49740Sstevel@tonic-gate 	switch (args->rev) {
49750Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
49760Sstevel@tonic-gate 		c.c_id = 0;
49770Sstevel@tonic-gate 		c.c_setno = args->mdrpc_setno_2_args_u.rev1.setno;
49780Sstevel@tonic-gate 
49790Sstevel@tonic-gate 		/* setup, check permissions */
49800Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
49810Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
49820Sstevel@tonic-gate 			return (FALSE);
49830Sstevel@tonic-gate 		else if (err != 0)
49840Sstevel@tonic-gate 			return (TRUE);
49850Sstevel@tonic-gate 
49860Sstevel@tonic-gate 		if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
49870Sstevel@tonic-gate 			mdstealerror(ep, &c.c_mde);
49880Sstevel@tonic-gate 			return (TRUE);
49890Sstevel@tonic-gate 		}
49900Sstevel@tonic-gate 
49910Sstevel@tonic-gate 		if (c.c_flags & MDDB_C_STALE) {
49920Sstevel@tonic-gate 			res->value = TRUE;
49930Sstevel@tonic-gate 		} else {
49940Sstevel@tonic-gate 			res->value = FALSE;
49950Sstevel@tonic-gate 		}
49960Sstevel@tonic-gate 
49970Sstevel@tonic-gate 		err = svc_fini(ep);
49980Sstevel@tonic-gate 		return (TRUE);
49990Sstevel@tonic-gate 
50000Sstevel@tonic-gate 	    default:
50010Sstevel@tonic-gate 		return (FALSE);
50020Sstevel@tonic-gate 	}
50030Sstevel@tonic-gate }
50040Sstevel@tonic-gate 
50050Sstevel@tonic-gate /*
50060Sstevel@tonic-gate  * Clear out all clnt_locks held by all MN disksets.
50070Sstevel@tonic-gate  * This is only used during a reconfig cycle.
50080Sstevel@tonic-gate  */
50090Sstevel@tonic-gate /* ARGSUSED */
501062Sjeanm int
50110Sstevel@tonic-gate mdrpc_clr_mnsetlock_2_svc(
50120Sstevel@tonic-gate 	mdrpc_null_args		*args,
50130Sstevel@tonic-gate 	mdrpc_generic_res	*res,
50140Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
50150Sstevel@tonic-gate )
50160Sstevel@tonic-gate {
50170Sstevel@tonic-gate 	set_t			max_sets, setno;
50180Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
50190Sstevel@tonic-gate 	int			err;
50200Sstevel@tonic-gate 	int			op_mode = W_OK;
50210Sstevel@tonic-gate 	mdsetname_t		*sp;
50220Sstevel@tonic-gate 
50230Sstevel@tonic-gate 	/* setup, check permissions */
50240Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
50250Sstevel@tonic-gate 
50260Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
50270Sstevel@tonic-gate 		return (FALSE);
50280Sstevel@tonic-gate 	else if (err != 0)
50290Sstevel@tonic-gate 		return (TRUE);
50300Sstevel@tonic-gate 
50310Sstevel@tonic-gate 	/*
50320Sstevel@tonic-gate 	 * Walk through all possible disksets.
50330Sstevel@tonic-gate 	 * For each MN set, delete all keys associated with that set.
50340Sstevel@tonic-gate 	 */
50350Sstevel@tonic-gate 	if ((max_sets = get_max_sets(ep)) == 0) {
50360Sstevel@tonic-gate 		return (TRUE);
50370Sstevel@tonic-gate 	}
50380Sstevel@tonic-gate 
50390Sstevel@tonic-gate 	/* start walking through all possible disksets */
50400Sstevel@tonic-gate 	for (setno = 1; setno < max_sets; setno++) {
50410Sstevel@tonic-gate 		if ((sp = metasetnosetname(setno, ep)) == NULL) {
50420Sstevel@tonic-gate 			if (mdiserror(ep, MDE_NO_SET)) {
50430Sstevel@tonic-gate 				/* No set for this setno - continue */
50440Sstevel@tonic-gate 				mdclrerror(ep);
50450Sstevel@tonic-gate 				continue;
50460Sstevel@tonic-gate 			} else {
50470Sstevel@tonic-gate 				mde_perror(ep, gettext(
50480Sstevel@tonic-gate 				    "Unable to get set %s information"),
50490Sstevel@tonic-gate 				    sp->setname);
50500Sstevel@tonic-gate 				mdclrerror(ep);
50510Sstevel@tonic-gate 				continue;
50520Sstevel@tonic-gate 			}
50530Sstevel@tonic-gate 		}
50540Sstevel@tonic-gate 
50550Sstevel@tonic-gate 		/* only check multi-node disksets */
50560Sstevel@tonic-gate 		if (!meta_is_mn_set(sp, ep)) {
50570Sstevel@tonic-gate 			mdclrerror(ep);
50580Sstevel@tonic-gate 			continue;
50590Sstevel@tonic-gate 		}
50600Sstevel@tonic-gate 
50610Sstevel@tonic-gate 		/* Delete keys associated with rpc.metad clnt_lock */
50620Sstevel@tonic-gate 		del_sk(setno);
50630Sstevel@tonic-gate 	}
50640Sstevel@tonic-gate 
50650Sstevel@tonic-gate 	*ep = mdnullerror;
50660Sstevel@tonic-gate 
50670Sstevel@tonic-gate 	err = svc_fini(ep);
50680Sstevel@tonic-gate 
50690Sstevel@tonic-gate 	return (TRUE);
50700Sstevel@tonic-gate }
50710Sstevel@tonic-gate 
50720Sstevel@tonic-gate /*
50730Sstevel@tonic-gate  * Get drive desc on this host for given setno.
50740Sstevel@tonic-gate  * This is only used during a reconfig cycle.
50750Sstevel@tonic-gate  * Returns a drive desc structure for the given mdsetname
50760Sstevel@tonic-gate  * from this host.
50770Sstevel@tonic-gate  *
50780Sstevel@tonic-gate  * Returned drive desc structure is partially filled in with
50790Sstevel@tonic-gate  * the drive name but is not filled in with any other strings
50800Sstevel@tonic-gate  * in the drivename structure.
50810Sstevel@tonic-gate  */
50820Sstevel@tonic-gate bool_t
50830Sstevel@tonic-gate mdrpc_getdrivedesc_2_svc(
50840Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
50850Sstevel@tonic-gate 	mdrpc_getdrivedesc_res 	*res,
50860Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
50870Sstevel@tonic-gate )
50880Sstevel@tonic-gate {
50890Sstevel@tonic-gate 	md_drive_desc		*dd;
50900Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
50910Sstevel@tonic-gate 	int			err;
50920Sstevel@tonic-gate 	int			op_mode = R_OK;
50930Sstevel@tonic-gate 	mdsetname_t		*my_sp;
50940Sstevel@tonic-gate 	mdrpc_sp_args		*args_r1;
50950Sstevel@tonic-gate 
50960Sstevel@tonic-gate 	switch (args->rev) {
50970Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
50980Sstevel@tonic-gate 		/* setup, check permissions */
50990Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
51000Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
51010Sstevel@tonic-gate 			return (FALSE);
51020Sstevel@tonic-gate 		else if (err != 0)
51030Sstevel@tonic-gate 			return (TRUE);
51040Sstevel@tonic-gate 
51050Sstevel@tonic-gate 		/* doit */
51060Sstevel@tonic-gate 		args_r1 = &args->mdrpc_sp_2_args_u.rev1;
51070Sstevel@tonic-gate 		if ((my_sp = metasetname(args_r1->sp->setname, ep)) == NULL)
51080Sstevel@tonic-gate 			return (TRUE);
51090Sstevel@tonic-gate 
51100Sstevel@tonic-gate 		dd = metaget_drivedesc(my_sp,
51110Sstevel@tonic-gate 			(MD_BASICNAME_OK | PRINT_FAST), ep);
51120Sstevel@tonic-gate 
51130Sstevel@tonic-gate 		res->dd = dd_list_dup(dd);
51140Sstevel@tonic-gate 
51150Sstevel@tonic-gate 		err = svc_fini(ep);
51160Sstevel@tonic-gate 
51170Sstevel@tonic-gate 		return (TRUE);
51180Sstevel@tonic-gate 	    default:
51190Sstevel@tonic-gate 		return (FALSE);
51200Sstevel@tonic-gate 	}
51210Sstevel@tonic-gate }
51220Sstevel@tonic-gate 
51230Sstevel@tonic-gate /*
51240Sstevel@tonic-gate  * Update drive records given list from master during reconfig.
51250Sstevel@tonic-gate  * Make this node's list match the master's list which may include
51260Sstevel@tonic-gate  * deleting a drive record that is known by this node and not known
51270Sstevel@tonic-gate  * by the master node.
51280Sstevel@tonic-gate  *
51290Sstevel@tonic-gate  * Sync up the set/node/drive record genids to match the genid
51300Sstevel@tonic-gate  * passed in the dd structure (all genids in this structure
51310Sstevel@tonic-gate  * are the same).
51320Sstevel@tonic-gate  */
51330Sstevel@tonic-gate bool_t
51340Sstevel@tonic-gate mdrpc_upd_dr_reconfig_common(
51350Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	*args,
51360Sstevel@tonic-gate 	mdrpc_generic_res		*res,
51370Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
51380Sstevel@tonic-gate )
51390Sstevel@tonic-gate {
51400Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
51410Sstevel@tonic-gate 	int			err;
51420Sstevel@tonic-gate 	mdsetname_t		*local_sp;
51430Sstevel@tonic-gate 	md_set_record		*sr;
51440Sstevel@tonic-gate 	md_mnset_record		*mnsr;
51450Sstevel@tonic-gate 	md_drive_record		*dr, *dr_placeholder = NULL;
51460Sstevel@tonic-gate 	md_drive_desc		*dd;
51470Sstevel@tonic-gate 	mddrivename_t		*dn, *dn1;
51480Sstevel@tonic-gate 	side_t			sideno;
51490Sstevel@tonic-gate 	md_mnnode_record	*nrp;
51500Sstevel@tonic-gate 	int			op_mode = W_OK;
51510Sstevel@tonic-gate 	int			change = 0;
51520Sstevel@tonic-gate 
51530Sstevel@tonic-gate 	/* setup, check permissions */
51540Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
51550Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
51560Sstevel@tonic-gate 		return (FALSE);
51570Sstevel@tonic-gate 	else if (err != 0)
51580Sstevel@tonic-gate 		return (TRUE);
51590Sstevel@tonic-gate 
51600Sstevel@tonic-gate 	if ((local_sp = metasetname(args->sp->setname, ep)) == NULL)
51610Sstevel@tonic-gate 		return (TRUE);
51620Sstevel@tonic-gate 
51630Sstevel@tonic-gate 	metaflushsetname(local_sp);
51640Sstevel@tonic-gate 
51650Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
51660Sstevel@tonic-gate 		return (TRUE);
51670Sstevel@tonic-gate 
51680Sstevel@tonic-gate 	if ((sr = getsetbyname(args->sp->setname, ep)) == NULL)
51690Sstevel@tonic-gate 		return (TRUE);
51700Sstevel@tonic-gate 
51710Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr))) {
51720Sstevel@tonic-gate 		free_sr(sr);
51730Sstevel@tonic-gate 		return (TRUE);
51740Sstevel@tonic-gate 	}
51750Sstevel@tonic-gate 
51760Sstevel@tonic-gate 	mnsr = (md_mnset_record *)sr;
51770Sstevel@tonic-gate 	/* Setup genid on set and node records */
51780Sstevel@tonic-gate 	if (args->drivedescs) {
51790Sstevel@tonic-gate 		if (mnsr->sr_genid != args->drivedescs->dd_genid) {
51800Sstevel@tonic-gate 			change = 1;
51810Sstevel@tonic-gate 			mnsr->sr_genid = args->drivedescs->dd_genid;
51820Sstevel@tonic-gate 		}
51830Sstevel@tonic-gate 		nrp = mnsr->sr_nodechain;
51840Sstevel@tonic-gate 		while (nrp) {
51850Sstevel@tonic-gate 			if (nrp->nr_genid != args->drivedescs->dd_genid) {
51860Sstevel@tonic-gate 				change = 1;
51870Sstevel@tonic-gate 				nrp->nr_genid = args->drivedescs->dd_genid;
51880Sstevel@tonic-gate 			}
51890Sstevel@tonic-gate 			nrp = nrp->nr_next;
51900Sstevel@tonic-gate 		}
51910Sstevel@tonic-gate 	}
51920Sstevel@tonic-gate 	for (dr = mnsr->sr_drivechain; dr; dr = dr->dr_next) {
51930Sstevel@tonic-gate 		dn1 = metadrivename_withdrkey(local_sp, sideno,
51940Sstevel@tonic-gate 		    dr->dr_key, (MD_BASICNAME_OK | PRINT_FAST), ep);
51950Sstevel@tonic-gate 		if (dn1 == NULL)
51960Sstevel@tonic-gate 			goto out;
51970Sstevel@tonic-gate 		for (dd = args->drivedescs; dd != NULL; dd = dd->dd_next) {
51980Sstevel@tonic-gate 			dn = dd->dd_dnp;
51990Sstevel@tonic-gate 			/* Found this node's drive rec to match dd */
52000Sstevel@tonic-gate 			if (strcmp(dn->cname, dn1->cname) == 0)
52010Sstevel@tonic-gate 				break;
52020Sstevel@tonic-gate 		}
52030Sstevel@tonic-gate 
52040Sstevel@tonic-gate 		/*
52050Sstevel@tonic-gate 		 * If drive found in master's list, make slave match master.
52060Sstevel@tonic-gate 		 * If drive not found in master's list, remove drive.
52070Sstevel@tonic-gate 		 */
52080Sstevel@tonic-gate 		if (dd) {
52090Sstevel@tonic-gate 			if ((dr->dr_flags != dd->dd_flags) ||
52100Sstevel@tonic-gate 			    (dr->dr_genid != dd->dd_genid)) {
52110Sstevel@tonic-gate 				change = 1;
52120Sstevel@tonic-gate 				dr->dr_flags = dd->dd_flags;
52130Sstevel@tonic-gate 				dr->dr_genid = dd->dd_genid;
52140Sstevel@tonic-gate 			}
52150Sstevel@tonic-gate 		} else {
52160Sstevel@tonic-gate 			/*
52170Sstevel@tonic-gate 			 * Delete entry from linked list.  Need to use
52180Sstevel@tonic-gate 			 * dr_placeholder so that dr->dr_next points to
52190Sstevel@tonic-gate 			 * the next drive record in the list.
52200Sstevel@tonic-gate 			 */
52210Sstevel@tonic-gate 			if (dr_placeholder == NULL) {
52220Sstevel@tonic-gate 				dr_placeholder =
52230Sstevel@tonic-gate 					Zalloc(sizeof (md_drive_record));
52240Sstevel@tonic-gate 			}
52250Sstevel@tonic-gate 			dr_placeholder->dr_next = dr->dr_next;
52260Sstevel@tonic-gate 			dr_placeholder->dr_key = dr->dr_key;
52270Sstevel@tonic-gate 			sr_del_drv(sr, dr->dr_selfid);
52280Sstevel@tonic-gate 			(void) del_sideno_sidenm(dr_placeholder->dr_key,
52290Sstevel@tonic-gate 				sideno, ep);
52300Sstevel@tonic-gate 			change = 1;
52310Sstevel@tonic-gate 			dr = dr_placeholder;
52320Sstevel@tonic-gate 		}
52330Sstevel@tonic-gate 	}
52340Sstevel@tonic-gate out:
52350Sstevel@tonic-gate 	/* If incore records are correct, don't need to write to disk */
52360Sstevel@tonic-gate 	if (change) {
52370Sstevel@tonic-gate 		/* Don't increment the genid in commitset */
52380Sstevel@tonic-gate 		commitset(sr, FALSE, ep);
52390Sstevel@tonic-gate 	}
52400Sstevel@tonic-gate 	free_sr(sr);
52410Sstevel@tonic-gate 
52420Sstevel@tonic-gate 	err = svc_fini(ep);
52430Sstevel@tonic-gate 
52440Sstevel@tonic-gate 	if (dr_placeholder != NULL)
52450Sstevel@tonic-gate 		Free(dr_placeholder);
52460Sstevel@tonic-gate 
52470Sstevel@tonic-gate 	return (TRUE);
52480Sstevel@tonic-gate }
52490Sstevel@tonic-gate 
52500Sstevel@tonic-gate /*
52510Sstevel@tonic-gate  * Version 2 routine to update this node's drive records based on
52520Sstevel@tonic-gate  * list passed in from master node.
52530Sstevel@tonic-gate  */
52540Sstevel@tonic-gate bool_t
52550Sstevel@tonic-gate mdrpc_upd_dr_reconfig_2_svc(
52560Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args	*args,
52570Sstevel@tonic-gate 	mdrpc_generic_res		*res,
52580Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
52590Sstevel@tonic-gate )
52600Sstevel@tonic-gate {
52610Sstevel@tonic-gate 	switch (args->rev) {
52620Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
52630Sstevel@tonic-gate 		return (mdrpc_upd_dr_reconfig_common(
52640Sstevel@tonic-gate 		    &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
52650Sstevel@tonic-gate 	    default:
52660Sstevel@tonic-gate 		return (FALSE);
52670Sstevel@tonic-gate 	}
52680Sstevel@tonic-gate }
52690Sstevel@tonic-gate 
52700Sstevel@tonic-gate /*
52710Sstevel@tonic-gate  * reset mirror owner for mirrors owned by deleted
52720Sstevel@tonic-gate  * or withdrawn host(s).  Hosts being deleted or
52730Sstevel@tonic-gate  * withdrawn are designated by nodeid since host is
52740Sstevel@tonic-gate  * already deleted or withdrawn from set and may not
52750Sstevel@tonic-gate  * be able to translate between a nodename and a nodeid.
52760Sstevel@tonic-gate  * If an error occurs, ep will be set to that error information.
52770Sstevel@tonic-gate  */
52780Sstevel@tonic-gate static void
52790Sstevel@tonic-gate reset_mirror_owner(
52800Sstevel@tonic-gate 	char		*setname,
52810Sstevel@tonic-gate 	int		node_c,
52820Sstevel@tonic-gate 	int		*node_id,	/* Array of node ids */
52830Sstevel@tonic-gate 	md_error_t	*ep
52840Sstevel@tonic-gate )
52850Sstevel@tonic-gate {
52860Sstevel@tonic-gate 	mdsetname_t		*local_sp;
52870Sstevel@tonic-gate 	int			i;
52880Sstevel@tonic-gate 	mdnamelist_t		*devnlp = NULL;
52890Sstevel@tonic-gate 	mdnamelist_t		*p;
52900Sstevel@tonic-gate 	mdname_t		*devnp = NULL;
52910Sstevel@tonic-gate 	md_set_mmown_params_t	ownpar_p;
52920Sstevel@tonic-gate 	md_set_mmown_params_t	*ownpar = &ownpar_p;
52930Sstevel@tonic-gate 	char			*miscname;
52940Sstevel@tonic-gate 
52950Sstevel@tonic-gate 	if ((local_sp = metasetname(setname, ep)) == NULL)
52960Sstevel@tonic-gate 		return;
52970Sstevel@tonic-gate 
52980Sstevel@tonic-gate 	/* get a list of all the mirrors for current set */
52990Sstevel@tonic-gate 	if (meta_get_mirror_names(local_sp, &devnlp, 0, ep) < 0)
53000Sstevel@tonic-gate 		return;
53010Sstevel@tonic-gate 
53020Sstevel@tonic-gate 	/* for each mirror */
53030Sstevel@tonic-gate 	for (p = devnlp; (p != NULL); p = p->next) {
53040Sstevel@tonic-gate 		devnp = p->namep;
53050Sstevel@tonic-gate 
53060Sstevel@tonic-gate 		/*
53070Sstevel@tonic-gate 		 * we can only do these for mirrors so make sure we
53080Sstevel@tonic-gate 		 * really have a mirror device and not a softpartition
53090Sstevel@tonic-gate 		 * imitating one. meta_get_mirror_names seems to think
53100Sstevel@tonic-gate 		 * softparts on top of a mirror are mirrors!
53110Sstevel@tonic-gate 		 */
53120Sstevel@tonic-gate 		if ((miscname = metagetmiscname(devnp, ep)) == NULL)
53130Sstevel@tonic-gate 			goto out;
53140Sstevel@tonic-gate 		if (strcmp(miscname, MD_MIRROR) != 0)
53150Sstevel@tonic-gate 			continue;
53160Sstevel@tonic-gate 
53170Sstevel@tonic-gate 		(void) memset(ownpar, 0, sizeof (*ownpar));
53180Sstevel@tonic-gate 		ownpar->d.mnum = meta_getminor(devnp->dev);
53190Sstevel@tonic-gate 		MD_SETDRIVERNAME(ownpar, MD_MIRROR, local_sp->setno);
53200Sstevel@tonic-gate 
53210Sstevel@tonic-gate 		/* get the current owner id */
53220Sstevel@tonic-gate 		if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep,
53230Sstevel@tonic-gate 		    "MD_MN_GET_MM_OWNER") != 0) {
53240Sstevel@tonic-gate 			mde_perror(ep, gettext(
53251623Stw21770 			    "Unable to get mirror owner for %s/%s"),
53260Sstevel@tonic-gate 			    local_sp->setname,
53271623Stw21770 			    get_mdname(local_sp, ownpar->d.mnum));
53280Sstevel@tonic-gate 			goto out;
53290Sstevel@tonic-gate 		}
53300Sstevel@tonic-gate 
53310Sstevel@tonic-gate 		if (ownpar->d.owner == MD_MN_MIRROR_UNOWNED) {
53320Sstevel@tonic-gate 			mdclrerror(ep);
53330Sstevel@tonic-gate 			continue;
53340Sstevel@tonic-gate 		}
53350Sstevel@tonic-gate 		/*
53360Sstevel@tonic-gate 		 * reset owner only if the current owner is
53370Sstevel@tonic-gate 		 * in the list of nodes being deleted.
53380Sstevel@tonic-gate 		 */
53390Sstevel@tonic-gate 		for (i = 0; i < node_c; i++) {
53400Sstevel@tonic-gate 			if (ownpar->d.owner == node_id[i]) {
53410Sstevel@tonic-gate 				if (meta_mn_change_owner(&ownpar,
53420Sstevel@tonic-gate 				    local_sp->setno, ownpar->d.mnum,
53430Sstevel@tonic-gate 				    MD_MN_MIRROR_UNOWNED,
53440Sstevel@tonic-gate 				    MD_MN_MM_ALLOW_CHANGE) == -1) {
53450Sstevel@tonic-gate 					mde_perror(ep, gettext(
53460Sstevel@tonic-gate 					    "Unable to reset mirror owner for"
53471623Stw21770 					    " %s/%s"), local_sp->setname,
53481623Stw21770 					    get_mdname(local_sp,
53491623Stw21770 						    ownpar->d.mnum));
53500Sstevel@tonic-gate 					goto out;
53510Sstevel@tonic-gate 				}
53520Sstevel@tonic-gate 				break;
53530Sstevel@tonic-gate 			}
53540Sstevel@tonic-gate 		}
53550Sstevel@tonic-gate 	}
53560Sstevel@tonic-gate 
53570Sstevel@tonic-gate out:
53580Sstevel@tonic-gate 	/* cleanup */
53590Sstevel@tonic-gate 	metafreenamelist(devnlp);
53600Sstevel@tonic-gate }
53610Sstevel@tonic-gate 
53620Sstevel@tonic-gate /*
53630Sstevel@tonic-gate  * Wrapper routine for reset_mirror_owner.
53640Sstevel@tonic-gate  * Called when hosts are deleted or withdrawn
53650Sstevel@tonic-gate  * in order to reset any mirror owners that are needed.
53660Sstevel@tonic-gate  */
53670Sstevel@tonic-gate bool_t
53680Sstevel@tonic-gate mdrpc_reset_mirror_owner_common(
53690Sstevel@tonic-gate 	mdrpc_nodeid_args	*args,
53700Sstevel@tonic-gate 	mdrpc_generic_res	*res,
53710Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
53720Sstevel@tonic-gate )
53730Sstevel@tonic-gate {
53740Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
53750Sstevel@tonic-gate 	int			err;
53760Sstevel@tonic-gate 	int			op_mode = W_OK;
53770Sstevel@tonic-gate 
53780Sstevel@tonic-gate 	/* setup, check permissions */
53790Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
53800Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
53810Sstevel@tonic-gate 		return (FALSE);
53820Sstevel@tonic-gate 	else if (err != 0)
53830Sstevel@tonic-gate 		return (TRUE);
53840Sstevel@tonic-gate 
53850Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
53860Sstevel@tonic-gate 		return (TRUE);
53870Sstevel@tonic-gate 
53880Sstevel@tonic-gate 	/* doit */
53890Sstevel@tonic-gate 	reset_mirror_owner(args->sp->setname, args->nodeid.nodeid_len,
53900Sstevel@tonic-gate 	    args->nodeid.nodeid_val, ep);
53910Sstevel@tonic-gate 
53920Sstevel@tonic-gate 	err = svc_fini(ep);
53930Sstevel@tonic-gate 
53940Sstevel@tonic-gate 	return (TRUE);
53950Sstevel@tonic-gate }
53960Sstevel@tonic-gate 
53970Sstevel@tonic-gate /*
53980Sstevel@tonic-gate  * RPC service routine to reset the mirror owner for mirrors owned
53990Sstevel@tonic-gate  * by the given hosts.  Typically, the list of given hosts is a list
54000Sstevel@tonic-gate  * of nodes being deleted or withdrawn from a diskset.
54010Sstevel@tonic-gate  * The given hosts are designated by nodeid since host may
54020Sstevel@tonic-gate  * already be deleted or withdrawn from set and may not
54030Sstevel@tonic-gate  * be able to translate between a nodename and a nodeid.
54040Sstevel@tonic-gate  */
54050Sstevel@tonic-gate bool_t
54060Sstevel@tonic-gate mdrpc_reset_mirror_owner_2_svc(
54070Sstevel@tonic-gate 	mdrpc_nodeid_2_args	*args,
54080Sstevel@tonic-gate 	mdrpc_generic_res	*res,
54090Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
54100Sstevel@tonic-gate )
54110Sstevel@tonic-gate {
54120Sstevel@tonic-gate 	switch (args->rev) {
54130Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
54140Sstevel@tonic-gate 		return (mdrpc_reset_mirror_owner_common(
54150Sstevel@tonic-gate 		    &args->mdrpc_nodeid_2_args_u.rev1, res,
54160Sstevel@tonic-gate 		    rqstp));
54170Sstevel@tonic-gate 	    default:
54180Sstevel@tonic-gate 		return (FALSE);
54190Sstevel@tonic-gate 	}
54200Sstevel@tonic-gate }
54210Sstevel@tonic-gate 
54220Sstevel@tonic-gate /*
54230Sstevel@tonic-gate  * Call routines to suspend and resume I/O for the given diskset(s).
54240Sstevel@tonic-gate  * Called during reconfig cycle.
54250Sstevel@tonic-gate  * Diskset of 0 represents all MN disksets.
54260Sstevel@tonic-gate  */
54270Sstevel@tonic-gate bool_t
54280Sstevel@tonic-gate mdrpc_mn_susp_res_io_2_svc(
54290Sstevel@tonic-gate 	mdrpc_mn_susp_res_io_2_args	*args,
54300Sstevel@tonic-gate 	mdrpc_generic_res		*res,
54310Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
54320Sstevel@tonic-gate )
54330Sstevel@tonic-gate {
54340Sstevel@tonic-gate 	mdrpc_mn_susp_res_io_args	*args_sr;
54350Sstevel@tonic-gate 	md_error_t			*ep = &res->status;
54360Sstevel@tonic-gate 	int				err;
54370Sstevel@tonic-gate 	int				op_mode = R_OK;
54380Sstevel@tonic-gate 
54390Sstevel@tonic-gate 	switch (args->rev) {
54400Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
54410Sstevel@tonic-gate 		/* setup, check permissions */
54420Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
54430Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
54440Sstevel@tonic-gate 			return (FALSE);
54450Sstevel@tonic-gate 		else if (err != 0)
54460Sstevel@tonic-gate 			return (TRUE);
54470Sstevel@tonic-gate 
54480Sstevel@tonic-gate 		args_sr = &(args->mdrpc_mn_susp_res_io_2_args_u.rev1);
54490Sstevel@tonic-gate 		switch (args_sr->susp_res_cmd) {
54500Sstevel@tonic-gate 		case MN_SUSP_IO:
54510Sstevel@tonic-gate 			(void) (metaioctl(MD_MN_SUSPEND_SET,
54520Sstevel@tonic-gate 				&args_sr->susp_res_setno, ep, NULL));
54530Sstevel@tonic-gate 			break;
54540Sstevel@tonic-gate 		case MN_RES_IO:
54550Sstevel@tonic-gate 			(void) (metaioctl(MD_MN_RESUME_SET,
54560Sstevel@tonic-gate 				&args_sr->susp_res_setno, ep, NULL));
54570Sstevel@tonic-gate 			break;
54580Sstevel@tonic-gate 		}
54590Sstevel@tonic-gate 		err = svc_fini(ep);
54600Sstevel@tonic-gate 		return (TRUE);
54610Sstevel@tonic-gate 
54620Sstevel@tonic-gate 	    default:
54630Sstevel@tonic-gate 		return (FALSE);
54640Sstevel@tonic-gate 	}
54650Sstevel@tonic-gate }
54660Sstevel@tonic-gate 
54670Sstevel@tonic-gate /*
54680Sstevel@tonic-gate  * Resnarf a set after it has been imported
54690Sstevel@tonic-gate  */
54700Sstevel@tonic-gate bool_t
54710Sstevel@tonic-gate mdrpc_resnarf_set_2_svc(
54720Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
54730Sstevel@tonic-gate 	mdrpc_generic_res	*res,
54740Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
54750Sstevel@tonic-gate )
54760Sstevel@tonic-gate {
54770Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
54780Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
54790Sstevel@tonic-gate 	int			err;
54800Sstevel@tonic-gate 	int			op_mode = R_OK;
54810Sstevel@tonic-gate 
54820Sstevel@tonic-gate 	switch (args->rev) {
54830Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
54840Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
54850Sstevel@tonic-gate 		break;
54860Sstevel@tonic-gate 	    default:
54870Sstevel@tonic-gate 		return (FALSE);
54880Sstevel@tonic-gate 	}
54890Sstevel@tonic-gate 
54900Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
54910Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
54920Sstevel@tonic-gate 		return (FALSE);
54930Sstevel@tonic-gate 	else if (err != 0)
54940Sstevel@tonic-gate 		return (TRUE);
54950Sstevel@tonic-gate 
54960Sstevel@tonic-gate 	/* do it */
54970Sstevel@tonic-gate 	if (resnarf_set(setno_args->setno, ep) < 0)
54980Sstevel@tonic-gate 		return (FALSE);
54990Sstevel@tonic-gate 
55000Sstevel@tonic-gate 	err = svc_fini(ep);
55010Sstevel@tonic-gate 	return (TRUE);
55020Sstevel@tonic-gate }
55030Sstevel@tonic-gate 
55040Sstevel@tonic-gate /*
55050Sstevel@tonic-gate  * Creates a resync thread.
55060Sstevel@tonic-gate  * Always returns true.
55070Sstevel@tonic-gate  */
55080Sstevel@tonic-gate bool_t
55090Sstevel@tonic-gate mdrpc_mn_mirror_resync_all_2_svc(
55100Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
55110Sstevel@tonic-gate 	mdrpc_generic_res	*res,
55120Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
55130Sstevel@tonic-gate )
55140Sstevel@tonic-gate {
55150Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
55160Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
55170Sstevel@tonic-gate 	int			err;
55180Sstevel@tonic-gate 	int			op_mode = R_OK;
55190Sstevel@tonic-gate 
55200Sstevel@tonic-gate 	switch (args->rev) {
55210Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
55220Sstevel@tonic-gate 		/* setup, check permissions */
55230Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
55240Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
55250Sstevel@tonic-gate 			return (FALSE);
55260Sstevel@tonic-gate 		else if (err != 0)
55270Sstevel@tonic-gate 			return (TRUE);
55280Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
55290Sstevel@tonic-gate 
55300Sstevel@tonic-gate 		/*
55310Sstevel@tonic-gate 		 * Need to invoke a metasync on a node newly added to a set.
55320Sstevel@tonic-gate 		 */
55330Sstevel@tonic-gate 		meta_mn_mirror_resync_all(&(setno_args->setno));
55340Sstevel@tonic-gate 
55350Sstevel@tonic-gate 		err = svc_fini(ep);
55360Sstevel@tonic-gate 		return (TRUE);
55370Sstevel@tonic-gate 
55380Sstevel@tonic-gate 	    default:
55390Sstevel@tonic-gate 		return (FALSE);
55400Sstevel@tonic-gate 	}
55410Sstevel@tonic-gate }
55420Sstevel@tonic-gate 
55430Sstevel@tonic-gate /*
55440Sstevel@tonic-gate  * Updates ABR state for all softpartitions. Calls meta_mn_sp_update_abr(),
55450Sstevel@tonic-gate  * which forks a daemon process to perform this action.
55460Sstevel@tonic-gate  * Always returns true.
55470Sstevel@tonic-gate  */
55480Sstevel@tonic-gate bool_t
55490Sstevel@tonic-gate mdrpc_mn_sp_update_abr_2_svc(
55500Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
55510Sstevel@tonic-gate 	mdrpc_generic_res	*res,
55520Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
55530Sstevel@tonic-gate )
55540Sstevel@tonic-gate {
55550Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
55560Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
55570Sstevel@tonic-gate 	int			err;
55580Sstevel@tonic-gate 	int			op_mode = R_OK;
55590Sstevel@tonic-gate 
55600Sstevel@tonic-gate 	switch (args->rev) {
55610Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
55620Sstevel@tonic-gate 		/* setup, check permissions */
55630Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
55640Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
55650Sstevel@tonic-gate 			return (FALSE);
55660Sstevel@tonic-gate 		else if (err != 0)
55670Sstevel@tonic-gate 			return (TRUE);
55680Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
55690Sstevel@tonic-gate 
55700Sstevel@tonic-gate 		meta_mn_sp_update_abr(&(setno_args->setno));
55710Sstevel@tonic-gate 
55720Sstevel@tonic-gate 		err = svc_fini(ep);
55730Sstevel@tonic-gate 		return (TRUE);
55740Sstevel@tonic-gate 
55750Sstevel@tonic-gate 	    default:
55760Sstevel@tonic-gate 		return (FALSE);
55770Sstevel@tonic-gate 	}
55780Sstevel@tonic-gate }
5579