xref: /onnv-gate/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include "metad_local.h"
30*0Sstevel@tonic-gate #include <metad.h>
31*0Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
32*0Sstevel@tonic-gate #include <sdssc.h>
33*0Sstevel@tonic-gate #include <sys/lvm/md_mirror.h>
34*0Sstevel@tonic-gate #include <syslog.h>
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
37*0Sstevel@tonic-gate #include <sys/sysevent/svm.h>
38*0Sstevel@tonic-gate #include <thread.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #define	MDDOORS		"/usr/lib/lvm/mddoors"
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate  * rpc.metad daemon
44*0Sstevel@tonic-gate  *
45*0Sstevel@tonic-gate  * The rpc.metad deamon supports two versions of the svm rpc calls - version 1
46*0Sstevel@tonic-gate  * and version 2. The over-the-wire structures sent as part of these rpc calls
47*0Sstevel@tonic-gate  * are also versioned - version 1 and version 2 exist. It must be noted that
48*0Sstevel@tonic-gate  * the version 2 structures have sub-versions or revisions as well. The
49*0Sstevel@tonic-gate  * revisions in the version 2 structures allow for flexiblility in changing
50*0Sstevel@tonic-gate  * over the wire structures without creating a new version of the svm rpc
51*0Sstevel@tonic-gate  * calls. No changes may be made to the version 1 routines or structures used
52*0Sstevel@tonic-gate  * by these routines.
53*0Sstevel@tonic-gate  *
54*0Sstevel@tonic-gate  * If, for example, the version 2 mdrpc_devinfo_args over the wire structure
55*0Sstevel@tonic-gate  * (mdrpc_devinfo_2_args*) is changed then the structure change must be
56*0Sstevel@tonic-gate  * accompanied by the following:
57*0Sstevel@tonic-gate  *
58*0Sstevel@tonic-gate  * Header file changes:
59*0Sstevel@tonic-gate  * . May need to introduce a new structure revision MD_METAD_ARGS_REV_X, where
60*0Sstevel@tonic-gate  *   X is the revision number.
61*0Sstevel@tonic-gate  * . Create mdrpc_devinfo_2_args_rX, where X is the new revision of the
62*0Sstevel@tonic-gate  *   structure.
63*0Sstevel@tonic-gate  * . Add a switch statement in mdrpc_devinfo_2_args.
64*0Sstevel@tonic-gate  *
65*0Sstevel@tonic-gate  * rpc.metad changes:
66*0Sstevel@tonic-gate  * . Check for the structure revision in the appropriate mdrpc_devinfo_svc
67*0Sstevel@tonic-gate  *   routine (mdrpc_devinfo_2_svc).
68*0Sstevel@tonic-gate  *
69*0Sstevel@tonic-gate  * libmeta changes:
70*0Sstevel@tonic-gate  * . In the libmeta code that makes the mdrpc_devinfo rpc call, the arguments
71*0Sstevel@tonic-gate  *   being passed as part of this call (namely mdrpc_devinfo_Y_args) must have
72*0Sstevel@tonic-gate  *   the revision field and associated structure populated correctly.
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate static	md_setkey_t	*my_svc_sk = NULL;
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate /*
78*0Sstevel@tonic-gate  * Add namespace entry to local mddb for using given sideno, key
79*0Sstevel@tonic-gate  * and names.
80*0Sstevel@tonic-gate  */
81*0Sstevel@tonic-gate static int
82*0Sstevel@tonic-gate add_sideno_sidenm(
83*0Sstevel@tonic-gate 	mdsidenames_t	*sidenms,
84*0Sstevel@tonic-gate 	mdkey_t		local_key,
85*0Sstevel@tonic-gate 	side_t		sideno,
86*0Sstevel@tonic-gate 	md_set_desc	*sd,		/* Only used with Version 2 */
87*0Sstevel@tonic-gate 	md_error_t	*ep
88*0Sstevel@tonic-gate )
89*0Sstevel@tonic-gate {
90*0Sstevel@tonic-gate 	mdsidenames_t	*sn;
91*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
92*0Sstevel@tonic-gate 	char		*nm;
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
95*0Sstevel@tonic-gate 		return (-1);
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	for (sn = sidenms; sn != NULL; sn = sn->next)
98*0Sstevel@tonic-gate 		if (sn->sideno == sideno)
99*0Sstevel@tonic-gate 			break;
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	assert(sn != NULL);
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	/*
105*0Sstevel@tonic-gate 	 * SKEW will be used on the traditional diskset despite of the
106*0Sstevel@tonic-gate 	 * rpc version.  SKEW is not used on the multinode diskset
107*0Sstevel@tonic-gate 	 */
108*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
109*0Sstevel@tonic-gate 		nm = meta_getnmbykey(MD_LOCAL_SET, sideno, local_key, ep);
110*0Sstevel@tonic-gate 	} else {
111*0Sstevel@tonic-gate 		nm = meta_getnmbykey(MD_LOCAL_SET, sideno+SKEW, local_key, ep);
112*0Sstevel@tonic-gate 	}
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	if (nm == NULL) {
115*0Sstevel@tonic-gate 		if (! mdisok(ep)) {
116*0Sstevel@tonic-gate 			if (! mdissyserror(ep, ENOENT))
117*0Sstevel@tonic-gate 				return (-1);
118*0Sstevel@tonic-gate 			mdclrerror(ep);
119*0Sstevel@tonic-gate 		}
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 		/*
122*0Sstevel@tonic-gate 		 * Ignore returned key from add_name, only care about errs
123*0Sstevel@tonic-gate 		 *
124*0Sstevel@tonic-gate 		 * SKEW is used for a regular diskset since sideno could
125*0Sstevel@tonic-gate 		 * have a value of 0 in that diskset type.  add_name is
126*0Sstevel@tonic-gate 		 * writing to the local mddb and a sideno of 0 in the
127*0Sstevel@tonic-gate 		 * local mddb is reserved for non-diskset names.
128*0Sstevel@tonic-gate 		 * SKEW is added to the sideno in the local mddb so that
129*0Sstevel@tonic-gate 		 * the sideno for the diskset will never be 0.
130*0Sstevel@tonic-gate 		 *
131*0Sstevel@tonic-gate 		 * In a MNdiskset, the sideno will never be 0 (by design).
132*0Sstevel@tonic-gate 		 * So, no SKEW is needed when writing to the local mddb.
133*0Sstevel@tonic-gate 		 */
134*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
135*0Sstevel@tonic-gate 			if (add_name(local_sp, sideno, local_key,
136*0Sstevel@tonic-gate 			    sn->dname, sn->mnum, sn->cname, ep) == -1)
137*0Sstevel@tonic-gate 				return (-1);
138*0Sstevel@tonic-gate 		} else {
139*0Sstevel@tonic-gate 			if (add_name(local_sp, sideno+SKEW, local_key,
140*0Sstevel@tonic-gate 			    sn->dname, sn->mnum, sn->cname, ep) == -1)
141*0Sstevel@tonic-gate 				return (-1);
142*0Sstevel@tonic-gate 		}
143*0Sstevel@tonic-gate 	} else
144*0Sstevel@tonic-gate 		Free(nm);
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	return (0);
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate /*
150*0Sstevel@tonic-gate  * Delete sidename entry from local set using key and sideno.
151*0Sstevel@tonic-gate  */
152*0Sstevel@tonic-gate static int
153*0Sstevel@tonic-gate del_sideno_sidenm(
154*0Sstevel@tonic-gate 	mdkey_t		sidekey,
155*0Sstevel@tonic-gate 	side_t		sideno,
156*0Sstevel@tonic-gate 	md_error_t	*ep
157*0Sstevel@tonic-gate )
158*0Sstevel@tonic-gate {
159*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
162*0Sstevel@tonic-gate 		return (-1);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	if (del_name(local_sp, sideno, sidekey, ep) == -1)
165*0Sstevel@tonic-gate 		mdclrerror(ep); /* ignore errs */
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	return (0);
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate /*
172*0Sstevel@tonic-gate  * Add namespace entries to local mddb for drives in drive list in
173*0Sstevel@tonic-gate  * set descriptor.
174*0Sstevel@tonic-gate  *
175*0Sstevel@tonic-gate  * If a MNset and if this host is being added to the set (this host
176*0Sstevel@tonic-gate  * is in the node_v list), add a namespace entry for the name of
177*0Sstevel@tonic-gate  * each drive using this host's sideno.
178*0Sstevel@tonic-gate  *
179*0Sstevel@tonic-gate  * If not a MNset, add namespace entries for all the new hosts being
180*0Sstevel@tonic-gate  * added to this set (list in node_v).
181*0Sstevel@tonic-gate  */
182*0Sstevel@tonic-gate static void
183*0Sstevel@tonic-gate add_drv_sidenms(
184*0Sstevel@tonic-gate 	char		*hostname,
185*0Sstevel@tonic-gate 	mdsetname_t	*sp,
186*0Sstevel@tonic-gate 	md_set_desc	*sd,
187*0Sstevel@tonic-gate 	int		node_c,
188*0Sstevel@tonic-gate 	char		**node_v,
189*0Sstevel@tonic-gate 	md_error_t	*ep
190*0Sstevel@tonic-gate )
191*0Sstevel@tonic-gate {
192*0Sstevel@tonic-gate 	mdsetname_t	*my_sp;
193*0Sstevel@tonic-gate 	md_drive_desc	*dd, *my_dd, *p, *q;
194*0Sstevel@tonic-gate 	mddrivename_t	*dn, *my_dn;
195*0Sstevel@tonic-gate 	int		i;
196*0Sstevel@tonic-gate 	side_t		sideno = 0, mysideno = 0;
197*0Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
198*0Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
199*0Sstevel@tonic-gate 	int		devid_same = -1;
200*0Sstevel@tonic-gate 	int		using_devid = 0;
201*0Sstevel@tonic-gate 	md_mnnode_desc	*nd;
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	assert(sd->sd_drvs != NULL);
204*0Sstevel@tonic-gate 	dd = sd->sd_drvs;
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
207*0Sstevel@tonic-gate 		return;
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	if ((my_sp = metasetname(sp->setname, ep)) == NULL)
210*0Sstevel@tonic-gate 		return;
211*0Sstevel@tonic-gate 	metaflushsetname(my_sp);
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	/* If a MN diskset */
214*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
215*0Sstevel@tonic-gate 		/* Find sideno associated with RPC client. */
216*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
217*0Sstevel@tonic-gate 		while (nd) {
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, hostname) == 0) {
220*0Sstevel@tonic-gate 				sideno = nd->nd_nodeid;
221*0Sstevel@tonic-gate 			}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 			/* While looping, find my side num as well */
224*0Sstevel@tonic-gate 			if (strcmp(nd->nd_nodename, mynode()) == 0) {
225*0Sstevel@tonic-gate 				mysideno = nd->nd_nodeid;
226*0Sstevel@tonic-gate 			}
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 			if ((sideno) && (mysideno)) {
229*0Sstevel@tonic-gate 				break;
230*0Sstevel@tonic-gate 			}
231*0Sstevel@tonic-gate 			nd = nd->nd_next;
232*0Sstevel@tonic-gate 		}
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 		if (!sideno) {
235*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_HOSTNOSIDE,
236*0Sstevel@tonic-gate 			    sp->setno, hostname, NULL, sp->setname);
237*0Sstevel@tonic-gate 			return;
238*0Sstevel@tonic-gate 		}
239*0Sstevel@tonic-gate 	} else {
240*0Sstevel@tonic-gate 		/*
241*0Sstevel@tonic-gate 		 * if not a MN diskset
242*0Sstevel@tonic-gate 		 * do action for traditional diskset.
243*0Sstevel@tonic-gate 		 * despite of the rpc version
244*0Sstevel@tonic-gate 		 */
245*0Sstevel@tonic-gate 		for (sideno = 0; sideno < MD_MAXSIDES; sideno++) {
246*0Sstevel@tonic-gate 			/* Skip empty slots */
247*0Sstevel@tonic-gate 			if (sd->sd_nodes[sideno][0] == '\0')
248*0Sstevel@tonic-gate 				continue;
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 			if (strcmp(hostname, sd->sd_nodes[sideno]) == 0)
251*0Sstevel@tonic-gate 				break;
252*0Sstevel@tonic-gate 		}
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 		if (sideno == MD_MAXSIDES) {
255*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_HOSTNOSIDE, sp->setno,
256*0Sstevel@tonic-gate 			    hostname, NULL, sp->setname);
257*0Sstevel@tonic-gate 			return;
258*0Sstevel@tonic-gate 		}
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 	if ((my_dd = metaget_drivedesc_sideno(my_sp, sideno, MD_BASICNAME_OK,
261*0Sstevel@tonic-gate 	    ep)) == NULL) {
262*0Sstevel@tonic-gate 		if (! mdisok(ep))
263*0Sstevel@tonic-gate 			return;
264*0Sstevel@tonic-gate 		/* we are supposed to have drives!!!! */
265*0Sstevel@tonic-gate 		assert(0);
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	/*
269*0Sstevel@tonic-gate 	 * The system is either all devid or all
270*0Sstevel@tonic-gate 	 * non-devid so we look at the first item
271*0Sstevel@tonic-gate 	 * in the list to determine if we're using devids or not.
272*0Sstevel@tonic-gate 	 * We also check to make sure it's not a multi-node diskset.
273*0Sstevel@tonic-gate 	 * If it is, we don't use devid's.
274*0Sstevel@tonic-gate 	 *
275*0Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
276*0Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
277*0Sstevel@tonic-gate 	 * before set the using_devid.
278*0Sstevel@tonic-gate 	 */
279*0Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
280*0Sstevel@tonic-gate 	    (!(MD_MNSET_DESC(sd))))
281*0Sstevel@tonic-gate 		using_devid = 1;
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate 	/*
284*0Sstevel@tonic-gate 	 * We have to match-up the dd that were passed
285*0Sstevel@tonic-gate 	 * across the wire to the dd we have in this daemon.
286*0Sstevel@tonic-gate 	 * That way we can pick up the new sidenames that were
287*0Sstevel@tonic-gate 	 * passed to us and match them up with the local namespace key.
288*0Sstevel@tonic-gate 	 * Only we have the key, this cannot be passed in.
289*0Sstevel@tonic-gate 	 */
290*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
291*0Sstevel@tonic-gate 		dn = p->dd_dnp;
292*0Sstevel@tonic-gate 		devid_remote = NULL;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
295*0Sstevel@tonic-gate 		    using_devid) {
296*0Sstevel@tonic-gate 			/*
297*0Sstevel@tonic-gate 			 * We have a devid so use it
298*0Sstevel@tonic-gate 			 */
299*0Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
300*0Sstevel@tonic-gate 		}
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
303*0Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
304*0Sstevel@tonic-gate 			/* something went really wrong. Can't process */
305*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
306*0Sstevel@tonic-gate 			    hostname, dn->cname, sp->setname);
307*0Sstevel@tonic-gate 			return;
308*0Sstevel@tonic-gate 		}
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 		for (q = my_dd; q != NULL; q = q->dd_next) {
311*0Sstevel@tonic-gate 			my_dn = q->dd_dnp;
312*0Sstevel@tonic-gate 			devid_same = -1;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 			if (my_dn->devid != NULL && using_devid) {
315*0Sstevel@tonic-gate 				if (devid_str_decode(my_dn->devid,
316*0Sstevel@tonic-gate 				    &devid_local, NULL) == 0) {
317*0Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
318*0Sstevel@tonic-gate 					    devid_local);
319*0Sstevel@tonic-gate 					devid_free(devid_local);
320*0Sstevel@tonic-gate 				}
321*0Sstevel@tonic-gate 			}
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 			if (using_devid && devid_same == 0) {
324*0Sstevel@tonic-gate 				break;
325*0Sstevel@tonic-gate 			}
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 			if (!using_devid &&
328*0Sstevel@tonic-gate 			    strcmp(my_dn->cname, dn->cname) == 0)
329*0Sstevel@tonic-gate 				break;
330*0Sstevel@tonic-gate 		}
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 		if (devid_remote) {
333*0Sstevel@tonic-gate 			devid_free(devid_remote);
334*0Sstevel@tonic-gate 		}
335*0Sstevel@tonic-gate 		assert(q != NULL);
336*0Sstevel@tonic-gate 		assert(my_dn->side_names_key != MD_KEYWILD);
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
339*0Sstevel@tonic-gate 			/*
340*0Sstevel@tonic-gate 			 * Add the side names to the local db
341*0Sstevel@tonic-gate 			 * for this node only.
342*0Sstevel@tonic-gate 			 */
343*0Sstevel@tonic-gate 			if (add_sideno_sidenm(dn->side_names,
344*0Sstevel@tonic-gate 			    my_dn->side_names_key, mysideno, sd, ep))
345*0Sstevel@tonic-gate 				return;
346*0Sstevel@tonic-gate 			/*
347*0Sstevel@tonic-gate 			 * Sidenames for this drive were added
348*0Sstevel@tonic-gate 			 * to this host during the routine adddrvs.
349*0Sstevel@tonic-gate 			 * The sidenames that were added are the
350*0Sstevel@tonic-gate 			 * names associated with this drive on
351*0Sstevel@tonic-gate 			 * each of the hosts that were previously
352*0Sstevel@tonic-gate 			 * in the set.
353*0Sstevel@tonic-gate 			 * When the sidename for this drive on
354*0Sstevel@tonic-gate 			 * this host is added, the sidename
355*0Sstevel@tonic-gate 			 * from the host executing the command
356*0Sstevel@tonic-gate 			 * (not this host) is sent to this host.
357*0Sstevel@tonic-gate 			 * This host finds the originating host's
358*0Sstevel@tonic-gate 			 * sidename and can then determine this
359*0Sstevel@tonic-gate 			 * host's sidename.
360*0Sstevel@tonic-gate 			 * The sidenames from the other hosts serve
361*0Sstevel@tonic-gate 			 * only as temporary sidenames until this
362*0Sstevel@tonic-gate 			 * host's sidename can be added.
363*0Sstevel@tonic-gate 			 * In order to conserve space in the
364*0Sstevel@tonic-gate 			 * local mddb, the code now deletes the
365*0Sstevel@tonic-gate 			 * temporary sidenames added during adddrvs.
366*0Sstevel@tonic-gate 			 * When finished, only the sidename for this
367*0Sstevel@tonic-gate 			 * node should be left.
368*0Sstevel@tonic-gate 			 * Ignore any errors during this process since
369*0Sstevel@tonic-gate 			 * a failure to delete the extraneous
370*0Sstevel@tonic-gate 			 * sidenames shouldn't cause this routine
371*0Sstevel@tonic-gate 			 * to fail (in case that sidename didn't exist).
372*0Sstevel@tonic-gate 			 */
373*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
374*0Sstevel@tonic-gate 			while (nd) {
375*0Sstevel@tonic-gate 				if (nd->nd_nodeid != mysideno) {
376*0Sstevel@tonic-gate 					if (del_sideno_sidenm(
377*0Sstevel@tonic-gate 					    dn->side_names_key,
378*0Sstevel@tonic-gate 					    nd->nd_nodeid, ep) == -1)
379*0Sstevel@tonic-gate 						mdclrerror(ep);
380*0Sstevel@tonic-gate 				}
381*0Sstevel@tonic-gate 				nd = nd->nd_next;
382*0Sstevel@tonic-gate 			}
383*0Sstevel@tonic-gate 		} else {
384*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
385*0Sstevel@tonic-gate 				/* Skip empty slots */
386*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
387*0Sstevel@tonic-gate 					continue;
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 				/* Skip nodes not being added */
390*0Sstevel@tonic-gate 				if (! strinlst(sd->sd_nodes[i],
391*0Sstevel@tonic-gate 					node_c, node_v))
392*0Sstevel@tonic-gate 					continue;
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 				/* Add the per side names to local db */
395*0Sstevel@tonic-gate 				if (add_sideno_sidenm(dn->side_names,
396*0Sstevel@tonic-gate 				    my_dn->side_names_key, i, sd, ep))
397*0Sstevel@tonic-gate 					return;
398*0Sstevel@tonic-gate 			}
399*0Sstevel@tonic-gate 		}
400*0Sstevel@tonic-gate 	}
401*0Sstevel@tonic-gate }
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate /* ARGSUSED */
404*0Sstevel@tonic-gate bool_t
405*0Sstevel@tonic-gate mdrpc_flush_internal_common(mdrpc_null_args *args, mdrpc_generic_res *res,
406*0Sstevel@tonic-gate     struct svc_req *rqstp)
407*0Sstevel@tonic-gate {
408*0Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
409*0Sstevel@tonic-gate 	int		err,
410*0Sstevel@tonic-gate 			op_mode = W_OK;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	memset(res, 0, sizeof (*res));
413*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
414*0Sstevel@tonic-gate 		return (FALSE);
415*0Sstevel@tonic-gate 	else if (err != 0)
416*0Sstevel@tonic-gate 		return (TRUE);
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate 	metaflushnames(1);
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	err = svc_fini(ep);
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 	return (TRUE);
423*0Sstevel@tonic-gate }
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate bool_t
426*0Sstevel@tonic-gate mdrpc_flush_internal_1_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
427*0Sstevel@tonic-gate     struct svc_req *rqstp)
428*0Sstevel@tonic-gate {
429*0Sstevel@tonic-gate 	return (mdrpc_flush_internal_common(args, res, rqstp));
430*0Sstevel@tonic-gate }
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate bool_t
433*0Sstevel@tonic-gate mdrpc_flush_internal_2_svc(mdrpc_null_args *args, mdrpc_generic_res *res,
434*0Sstevel@tonic-gate     struct svc_req *rqstp)
435*0Sstevel@tonic-gate {
436*0Sstevel@tonic-gate 	return (mdrpc_flush_internal_common(args, res, rqstp));
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate /*
440*0Sstevel@tonic-gate  * add 1 or more namespace entries per drive record.
441*0Sstevel@tonic-gate  * (into the local namespace)
442*0Sstevel@tonic-gate  */
443*0Sstevel@tonic-gate bool_t
444*0Sstevel@tonic-gate mdrpc_add_drv_sidenms_common(
445*0Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args_r1	*args,
446*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
447*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
448*0Sstevel@tonic-gate )
449*0Sstevel@tonic-gate {
450*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
451*0Sstevel@tonic-gate 	int			err;
452*0Sstevel@tonic-gate 	int			op_mode = W_OK;
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 	/* setup, check permissions */
455*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
456*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
457*0Sstevel@tonic-gate 		return (FALSE);
458*0Sstevel@tonic-gate 	else if (err != 0)
459*0Sstevel@tonic-gate 		return (TRUE);
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
462*0Sstevel@tonic-gate 		return (TRUE);
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 	/* doit */
465*0Sstevel@tonic-gate 	add_drv_sidenms(args->hostname, args->sp, args->sd,
466*0Sstevel@tonic-gate 	    args->node_v.node_v_len, args->node_v.node_v_val, ep);
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 	err = svc_fini(ep);
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	return (TRUE);
471*0Sstevel@tonic-gate }
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate /*
474*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
475*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
476*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
477*0Sstevel@tonic-gate  */
478*0Sstevel@tonic-gate bool_t
479*0Sstevel@tonic-gate mdrpc_add_drv_sidenms_1_svc(
480*0Sstevel@tonic-gate 	mdrpc_drv_sidenm_args	*args,
481*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
482*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
483*0Sstevel@tonic-gate )
484*0Sstevel@tonic-gate {
485*0Sstevel@tonic-gate 	bool_t				retval;
486*0Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args_r1	v2_args;
487*0Sstevel@tonic-gate 	int				i, j;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 	/* allocate memory */
490*0Sstevel@tonic-gate 	v2_args.sd = Zalloc(sizeof (md_set_desc));
491*0Sstevel@tonic-gate 	alloc_newdrvdesc(args->sd->sd_drvs, &v2_args.sd->sd_drvs);
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	/* build args */
494*0Sstevel@tonic-gate 	v2_args.hostname = args->hostname;
495*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
496*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
497*0Sstevel@tonic-gate 	/* set descriptor */
498*0Sstevel@tonic-gate 	v2_args.sd->sd_ctime = args->sd->sd_ctime;
499*0Sstevel@tonic-gate 	v2_args.sd->sd_genid = args->sd->sd_genid;
500*0Sstevel@tonic-gate 	v2_args.sd->sd_setno = args->sd->sd_setno;
501*0Sstevel@tonic-gate 	v2_args.sd->sd_flags = args->sd->sd_flags;
502*0Sstevel@tonic-gate 	for (i = 0; i < MD_MAXSIDES; i++) {
503*0Sstevel@tonic-gate 		v2_args.sd->sd_isown[i] = args->sd->sd_isown[i];
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 		for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j++)
506*0Sstevel@tonic-gate 			v2_args.sd->sd_nodes[i][j] =
507*0Sstevel@tonic-gate 			    args->sd->sd_nodes[i][j];
508*0Sstevel@tonic-gate 	}
509*0Sstevel@tonic-gate 	v2_args.sd->sd_med = args->sd->sd_med;
510*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
511*0Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->sd->sd_drvs, v2_args.sd->sd_drvs);
512*0Sstevel@tonic-gate 	v2_args.node_v.node_v_len = args->node_v.node_v_len;
513*0Sstevel@tonic-gate 	v2_args.node_v.node_v_val = args->node_v.node_v_val;
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	retval = mdrpc_add_drv_sidenms_common(&v2_args, res, rqstp);
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	free(v2_args.sd);
518*0Sstevel@tonic-gate 	free_newdrvdesc(v2_args.sd->sd_drvs);
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	return (retval);
521*0Sstevel@tonic-gate }
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate bool_t
524*0Sstevel@tonic-gate mdrpc_add_drv_sidenms_2_svc(
525*0Sstevel@tonic-gate 	mdrpc_drv_sidenm_2_args	*args,
526*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
527*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
528*0Sstevel@tonic-gate )
529*0Sstevel@tonic-gate {
530*0Sstevel@tonic-gate 	switch (args->rev) {
531*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
532*0Sstevel@tonic-gate 		return (mdrpc_add_drv_sidenms_common(
533*0Sstevel@tonic-gate 		    &args->mdrpc_drv_sidenm_2_args_u.rev1, res, rqstp));
534*0Sstevel@tonic-gate 	    default:
535*0Sstevel@tonic-gate 		return (FALSE);
536*0Sstevel@tonic-gate 	}
537*0Sstevel@tonic-gate }
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate static int
540*0Sstevel@tonic-gate add_sidenamelist(
541*0Sstevel@tonic-gate 	mddrivename_t	*dn,
542*0Sstevel@tonic-gate 	side_t		thisside,
543*0Sstevel@tonic-gate 	md_set_record	*sr, 		/* used by RPC version 2 */
544*0Sstevel@tonic-gate 	md_error_t	*ep
545*0Sstevel@tonic-gate )
546*0Sstevel@tonic-gate {
547*0Sstevel@tonic-gate 	mdsidenames_t	*sn;
548*0Sstevel@tonic-gate 	mdkey_t		key;
549*0Sstevel@tonic-gate 	int		err;
550*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
551*0Sstevel@tonic-gate 	md_mnset_record	*mnsr;
552*0Sstevel@tonic-gate 	md_mnnode_record *nr;
553*0Sstevel@tonic-gate 	uint_t		nodeid = 0;
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
556*0Sstevel@tonic-gate 		return (-1);
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 	key = MD_KEYWILD;
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 	/*
561*0Sstevel@tonic-gate 	 * If a multi-node diskset, find nodeid associated with this node.
562*0Sstevel@tonic-gate 	 */
563*0Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
564*0Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
565*0Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
566*0Sstevel@tonic-gate 		while (nr) {
567*0Sstevel@tonic-gate 			if (strcmp(nr->nr_nodename, mynode()) == 0) {
568*0Sstevel@tonic-gate 				break;
569*0Sstevel@tonic-gate 			}
570*0Sstevel@tonic-gate 			nr = nr->nr_next;
571*0Sstevel@tonic-gate 		}
572*0Sstevel@tonic-gate 		/*
573*0Sstevel@tonic-gate 		 * If node is found, then a new drive is being added to
574*0Sstevel@tonic-gate 		 * a MN set of which this node is a member.
575*0Sstevel@tonic-gate 		 * If node is not found, then this host is being added to
576*0Sstevel@tonic-gate 		 * a MN set that has drives associated with it.
577*0Sstevel@tonic-gate 		 */
578*0Sstevel@tonic-gate 		if (nr)
579*0Sstevel@tonic-gate 			nodeid = nr->nr_nodeid;
580*0Sstevel@tonic-gate 	}
581*0Sstevel@tonic-gate 	for (sn = dn->side_names; sn != NULL; sn = sn->next) {
582*0Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
583*0Sstevel@tonic-gate 			/*
584*0Sstevel@tonic-gate 			 * In multi-node disksets, only add side information
585*0Sstevel@tonic-gate 			 * to the local mddb about this node.
586*0Sstevel@tonic-gate 			 * If the sideno for this node is found, then
587*0Sstevel@tonic-gate 			 * a new drive is being added to a MN set of
588*0Sstevel@tonic-gate 			 * which this node is a member.
589*0Sstevel@tonic-gate 			 * If the sideno for this node is not found, then
590*0Sstevel@tonic-gate 			 * this host is being added to a MNset that
591*0Sstevel@tonic-gate 			 * has drives associated with it.  In this case,
592*0Sstevel@tonic-gate 			 * need to add the sidename associated with the
593*0Sstevel@tonic-gate 			 * rpc client, but since we don't know which node
594*0Sstevel@tonic-gate 			 * is the client, then add temp entries for all sides.
595*0Sstevel@tonic-gate 			 * Later, the sidename for this node will be set
596*0Sstevel@tonic-gate 			 * via add_drv_sidenms and then the temp
597*0Sstevel@tonic-gate 			 * sidenames can be removed.
598*0Sstevel@tonic-gate 			 */
599*0Sstevel@tonic-gate 			if (nodeid == sn->sideno) {
600*0Sstevel@tonic-gate 				if ((err = add_name(local_sp, sn->sideno, key,
601*0Sstevel@tonic-gate 				    sn->dname, sn->mnum, sn->cname, ep)) == -1)
602*0Sstevel@tonic-gate 					return (-1);
603*0Sstevel@tonic-gate 				key = (mdkey_t)err;
604*0Sstevel@tonic-gate 				break;
605*0Sstevel@tonic-gate 			}
606*0Sstevel@tonic-gate 		} else {
607*0Sstevel@tonic-gate 			/*
608*0Sstevel@tonic-gate 			 * When a sidename is added into the namespace the local
609*0Sstevel@tonic-gate 			 * side information for the name is added first of all.
610*0Sstevel@tonic-gate 			 * When the first sidename is created this causes the
611*0Sstevel@tonic-gate 			 * devid of the disk to be recorded in the namespace, if
612*0Sstevel@tonic-gate 			 * the non-local side information is added first then
613*0Sstevel@tonic-gate 			 * there is the possibility of getting the wrong devid
614*0Sstevel@tonic-gate 			 * because there is no guarantee that the dev_t (mnum in
615*0Sstevel@tonic-gate 			 * this instance) is the same across all the nodes in
616*0Sstevel@tonic-gate 			 * the set. So the only way to make sure that the
617*0Sstevel@tonic-gate 			 * correct dev_t is used is to force the adding in of
618*0Sstevel@tonic-gate 			 * the local sidename record first of all. This same
619*0Sstevel@tonic-gate 			 * issue affects add_key_name().
620*0Sstevel@tonic-gate 			 */
621*0Sstevel@tonic-gate 			if (sn->sideno != thisside)
622*0Sstevel@tonic-gate 				continue;
623*0Sstevel@tonic-gate 			if ((err = add_name(local_sp, sn->sideno+SKEW, key,
624*0Sstevel@tonic-gate 			    sn->dname, sn->mnum, sn->cname, ep)) == -1)
625*0Sstevel@tonic-gate 				return (-1);
626*0Sstevel@tonic-gate 			key = (mdkey_t)err;
627*0Sstevel@tonic-gate 			break;
628*0Sstevel@tonic-gate 		}
629*0Sstevel@tonic-gate 	}
630*0Sstevel@tonic-gate 
631*0Sstevel@tonic-gate 	/*
632*0Sstevel@tonic-gate 	 * Now the other sides for non-MN set
633*0Sstevel@tonic-gate 	 */
634*0Sstevel@tonic-gate 	if (!MD_MNSET_REC(sr)) {
635*0Sstevel@tonic-gate 		for (sn = dn->side_names; sn != NULL; sn = sn->next) {
636*0Sstevel@tonic-gate 			if (sn->sideno == thisside)
637*0Sstevel@tonic-gate 				continue;
638*0Sstevel@tonic-gate 			if ((err = add_name(local_sp, sn->sideno+SKEW, key,
639*0Sstevel@tonic-gate 				sn->dname, sn->mnum, sn->cname, ep)) == -1)
640*0Sstevel@tonic-gate 				return (-1);
641*0Sstevel@tonic-gate 			key = (mdkey_t)err;
642*0Sstevel@tonic-gate 		}
643*0Sstevel@tonic-gate 	}
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 	/* Temporarily add all sides. */
646*0Sstevel@tonic-gate 	if ((key == MD_KEYWILD) && (MD_MNSET_REC(sr))) {
647*0Sstevel@tonic-gate 		for (sn = dn->side_names; sn != NULL; sn = sn->next) {
648*0Sstevel@tonic-gate 			sn = dn->side_names;
649*0Sstevel@tonic-gate 			if (sn) {
650*0Sstevel@tonic-gate 				if ((err = add_name(local_sp, sn->sideno, key,
651*0Sstevel@tonic-gate 				    sn->dname, sn->mnum, sn->cname, ep)) == -1)
652*0Sstevel@tonic-gate 						return (-1);
653*0Sstevel@tonic-gate 				key = (mdkey_t)err;
654*0Sstevel@tonic-gate 			}
655*0Sstevel@tonic-gate 		}
656*0Sstevel@tonic-gate 	}
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 	dn->side_names_key = key;
659*0Sstevel@tonic-gate 	return (0);
660*0Sstevel@tonic-gate }
661*0Sstevel@tonic-gate 
662*0Sstevel@tonic-gate static void
663*0Sstevel@tonic-gate adddrvs(
664*0Sstevel@tonic-gate 	char 		*setname,
665*0Sstevel@tonic-gate 	md_drive_desc	*dd,
666*0Sstevel@tonic-gate 	md_timeval32_t	timestamp,
667*0Sstevel@tonic-gate 	ulong_t		genid,
668*0Sstevel@tonic-gate 	md_error_t	*ep
669*0Sstevel@tonic-gate )
670*0Sstevel@tonic-gate {
671*0Sstevel@tonic-gate 	mddb_userreq_t	req;
672*0Sstevel@tonic-gate 	md_drive_record	*dr;
673*0Sstevel@tonic-gate 	md_set_record	*sr;
674*0Sstevel@tonic-gate 	md_drive_desc	*p;
675*0Sstevel@tonic-gate 	mddrivename_t	*dn;
676*0Sstevel@tonic-gate 	mdname_t	*np;
677*0Sstevel@tonic-gate 	md_dev64_t	dev;
678*0Sstevel@tonic-gate 	md_error_t	xep = mdnullerror;
679*0Sstevel@tonic-gate 	int		i;
680*0Sstevel@tonic-gate 
681*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
682*0Sstevel@tonic-gate 		return;
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate 	if (MD_MNSET_REC(sr))
685*0Sstevel@tonic-gate 		i = 0;
686*0Sstevel@tonic-gate 	else {
687*0Sstevel@tonic-gate 		/* get thisside */
688*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
689*0Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
690*0Sstevel@tonic-gate 				continue;
691*0Sstevel@tonic-gate 			if (strcmp(mynode(), sr->sr_nodes[i]) == 0)
692*0Sstevel@tonic-gate 				break;
693*0Sstevel@tonic-gate 		}
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 		if (i == MD_MAXSIDES) {
696*0Sstevel@tonic-gate 			/* so find the first free slot! */
697*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
698*0Sstevel@tonic-gate 				if (sr->sr_nodes[i][0] == '\0')
699*0Sstevel@tonic-gate 					break;
700*0Sstevel@tonic-gate 			}
701*0Sstevel@tonic-gate 		}
702*0Sstevel@tonic-gate 	}
703*0Sstevel@tonic-gate 
704*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
705*0Sstevel@tonic-gate 		uint_t	rep_slice;
706*0Sstevel@tonic-gate 
707*0Sstevel@tonic-gate 		dn = p->dd_dnp;
708*0Sstevel@tonic-gate 
709*0Sstevel@tonic-gate 		/* Add the per side names to the local db */
710*0Sstevel@tonic-gate 		if (add_sidenamelist(dn, (side_t)i,  sr, ep)) {
711*0Sstevel@tonic-gate 				free_sr(sr);
712*0Sstevel@tonic-gate 				return;
713*0Sstevel@tonic-gate 		}
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 		/* Create the drive record */
716*0Sstevel@tonic-gate 		(void) memset(&req, 0, sizeof (req));
717*0Sstevel@tonic-gate 		METAD_SETUP_DR(MD_DB_CREATE, 0);
718*0Sstevel@tonic-gate 		req.ur_size = sizeof (*dr);
719*0Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
720*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
721*0Sstevel@tonic-gate 			free_sr(sr);
722*0Sstevel@tonic-gate 			return;
723*0Sstevel@tonic-gate 		}
724*0Sstevel@tonic-gate 
725*0Sstevel@tonic-gate 		/* Fill in the drive record values */
726*0Sstevel@tonic-gate 		dr = Zalloc(sizeof (*dr));
727*0Sstevel@tonic-gate 		dr->dr_selfid = req.ur_recid;
728*0Sstevel@tonic-gate 		dr->dr_dbcnt = p->dd_dbcnt;
729*0Sstevel@tonic-gate 		dr->dr_dbsize = p->dd_dbsize;
730*0Sstevel@tonic-gate 		dr->dr_key = dn->side_names_key;
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 		dr->dr_ctime = timestamp;
733*0Sstevel@tonic-gate 		dr->dr_genid = genid;
734*0Sstevel@tonic-gate 		dr->dr_revision = MD_DRIVE_RECORD_REVISION;
735*0Sstevel@tonic-gate 		dr->dr_flags = MD_DR_ADD;
736*0Sstevel@tonic-gate 
737*0Sstevel@tonic-gate 		/* Link the drive records and fill in in-core data */
738*0Sstevel@tonic-gate 		dr_cache_add(sr, dr);
739*0Sstevel@tonic-gate 
740*0Sstevel@tonic-gate 		dev = NODEV64;
741*0Sstevel@tonic-gate 		if ((meta_replicaslice(dn, &rep_slice, &xep) == 0) &&
742*0Sstevel@tonic-gate 		    ((np = metaslicename(dn, rep_slice, &xep)) != NULL))
743*0Sstevel@tonic-gate 			dev = np->dev;
744*0Sstevel@tonic-gate 		else
745*0Sstevel@tonic-gate 			mdclrerror(&xep);
746*0Sstevel@tonic-gate 
747*0Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
748*0Sstevel@tonic-gate 		    MD_LOCAL_SET, dev);
749*0Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
750*0Sstevel@tonic-gate 		    sr->sr_setno, dev);
751*0Sstevel@tonic-gate 	}
752*0Sstevel@tonic-gate 
753*0Sstevel@tonic-gate 	/* Commit all the records atomically */
754*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
755*0Sstevel@tonic-gate 	free_sr(sr);
756*0Sstevel@tonic-gate }
757*0Sstevel@tonic-gate 
758*0Sstevel@tonic-gate /*
759*0Sstevel@tonic-gate  * add 1 or more drive records to a set.
760*0Sstevel@tonic-gate  */
761*0Sstevel@tonic-gate bool_t
762*0Sstevel@tonic-gate mdrpc_adddrvs_common(
763*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
764*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
765*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
766*0Sstevel@tonic-gate )
767*0Sstevel@tonic-gate {
768*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
769*0Sstevel@tonic-gate 	int			err;
770*0Sstevel@tonic-gate 	int			op_mode = W_OK;
771*0Sstevel@tonic-gate 
772*0Sstevel@tonic-gate 	/* setup, check permissions */
773*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
774*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
775*0Sstevel@tonic-gate 		return (FALSE);
776*0Sstevel@tonic-gate 	else if (err != 0)
777*0Sstevel@tonic-gate 		return (TRUE);
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
780*0Sstevel@tonic-gate 		return (TRUE);
781*0Sstevel@tonic-gate 
782*0Sstevel@tonic-gate 	/* doit */
783*0Sstevel@tonic-gate 	adddrvs(args->sp->setname, args->drivedescs, args->timestamp,
784*0Sstevel@tonic-gate 	    args->genid, ep);
785*0Sstevel@tonic-gate 
786*0Sstevel@tonic-gate 	err = svc_fini(ep);
787*0Sstevel@tonic-gate 
788*0Sstevel@tonic-gate 	return (TRUE);
789*0Sstevel@tonic-gate }
790*0Sstevel@tonic-gate 
791*0Sstevel@tonic-gate /*
792*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
793*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
794*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
795*0Sstevel@tonic-gate  */
796*0Sstevel@tonic-gate bool_t
797*0Sstevel@tonic-gate mdrpc_adddrvs_1_svc(
798*0Sstevel@tonic-gate 	mdrpc_drives_args	*args,
799*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
800*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
801*0Sstevel@tonic-gate )
802*0Sstevel@tonic-gate {
803*0Sstevel@tonic-gate 	bool_t			retval;
804*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
805*0Sstevel@tonic-gate 
806*0Sstevel@tonic-gate 	/* allocate memory */
807*0Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
808*0Sstevel@tonic-gate 
809*0Sstevel@tonic-gate 	/* build args */
810*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
811*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
812*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
813*0Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
814*0Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
815*0Sstevel@tonic-gate 	v2_args.genid = args->genid;
816*0Sstevel@tonic-gate 
817*0Sstevel@tonic-gate 	retval = mdrpc_adddrvs_common(&v2_args, res, rqstp);
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
820*0Sstevel@tonic-gate 
821*0Sstevel@tonic-gate 	return (retval);
822*0Sstevel@tonic-gate }
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate bool_t
825*0Sstevel@tonic-gate mdrpc_adddrvs_2_svc(
826*0Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
827*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
828*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
829*0Sstevel@tonic-gate )
830*0Sstevel@tonic-gate {
831*0Sstevel@tonic-gate 	switch (args->rev) {
832*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
833*0Sstevel@tonic-gate 		return (mdrpc_adddrvs_common(
834*0Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
835*0Sstevel@tonic-gate 	    default:
836*0Sstevel@tonic-gate 		return (FALSE);
837*0Sstevel@tonic-gate 	}
838*0Sstevel@tonic-gate }
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate static void
841*0Sstevel@tonic-gate addhosts(
842*0Sstevel@tonic-gate 	char		*setname,
843*0Sstevel@tonic-gate 	int		node_c,
844*0Sstevel@tonic-gate 	char		**node_v,
845*0Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
846*0Sstevel@tonic-gate 	md_error_t	*ep
847*0Sstevel@tonic-gate )
848*0Sstevel@tonic-gate {
849*0Sstevel@tonic-gate 	mddb_userreq_t		req;
850*0Sstevel@tonic-gate 	md_set_record		*sr;
851*0Sstevel@tonic-gate 	int			i, j;
852*0Sstevel@tonic-gate 	md_mnset_record		*mnsr;
853*0Sstevel@tonic-gate 	md_mnnode_record	*nr;
854*0Sstevel@tonic-gate 	mddb_set_node_params_t	snp;
855*0Sstevel@tonic-gate 	int			nodecnt;
856*0Sstevel@tonic-gate 	mndiskset_membershiplist_t *nl, *nl2;
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
859*0Sstevel@tonic-gate 		return;
860*0Sstevel@tonic-gate 
861*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
862*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
863*0Sstevel@tonic-gate 		mnsr = (md_mnset_record *)sr;
864*0Sstevel@tonic-gate 		/*
865*0Sstevel@tonic-gate 		 * Verify nodes are in membership list on THIS node.
866*0Sstevel@tonic-gate 		 * Initiating node has verified that nodes are in membership
867*0Sstevel@tonic-gate 		 * list on the initiating node.
868*0Sstevel@tonic-gate 		 * Get membershiplist from API routine.  If there's
869*0Sstevel@tonic-gate 		 * an error, fail to add hosts and pass back error.
870*0Sstevel@tonic-gate 		 */
871*0Sstevel@tonic-gate 		if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
872*0Sstevel@tonic-gate 			free_sr(sr);
873*0Sstevel@tonic-gate 			return;
874*0Sstevel@tonic-gate 		}
875*0Sstevel@tonic-gate 		/* Verify that all nodes are in member list */
876*0Sstevel@tonic-gate 		for (i = 0; i < node_c; i++) {
877*0Sstevel@tonic-gate 			/*
878*0Sstevel@tonic-gate 			 * If node in list isn't a member of the membership,
879*0Sstevel@tonic-gate 			 * just return error.
880*0Sstevel@tonic-gate 			 */
881*0Sstevel@tonic-gate 			if (meta_is_member(node_v[i], NULL, nl) == 0) {
882*0Sstevel@tonic-gate 				meta_free_nodelist(nl);
883*0Sstevel@tonic-gate 				(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
884*0Sstevel@tonic-gate 				    sr->sr_setno, node_v[i], NULL, setname);
885*0Sstevel@tonic-gate 				free_sr(sr);
886*0Sstevel@tonic-gate 				return;
887*0Sstevel@tonic-gate 			}
888*0Sstevel@tonic-gate 		}
889*0Sstevel@tonic-gate 	}
890*0Sstevel@tonic-gate 
891*0Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
892*0Sstevel@tonic-gate 		/* Do MN operation if rpc version supports it and if a MN set */
893*0Sstevel@tonic-gate 		if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
894*0Sstevel@tonic-gate 			mnsr = (md_mnset_record *)sr;
895*0Sstevel@tonic-gate 			/* Create the node record */
896*0Sstevel@tonic-gate 			(void) memset(&req, 0, sizeof (req));
897*0Sstevel@tonic-gate 			METAD_SETUP_NR(MD_DB_CREATE, 0);
898*0Sstevel@tonic-gate 			req.ur_size = sizeof (*nr);
899*0Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
900*0Sstevel@tonic-gate 			    != 0) {
901*0Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
902*0Sstevel@tonic-gate 				meta_free_nodelist(nl);
903*0Sstevel@tonic-gate 				free_sr(sr);
904*0Sstevel@tonic-gate 				return;
905*0Sstevel@tonic-gate 			}
906*0Sstevel@tonic-gate 
907*0Sstevel@tonic-gate 			nr = Zalloc(sizeof (*nr));
908*0Sstevel@tonic-gate 			nr->nr_revision = MD_MNNODE_RECORD_REVISION;
909*0Sstevel@tonic-gate 			nr->nr_selfid = req.ur_recid;
910*0Sstevel@tonic-gate 			nr->nr_ctime = sr->sr_ctime;
911*0Sstevel@tonic-gate 			nr->nr_genid = sr->sr_genid;
912*0Sstevel@tonic-gate 			nr->nr_flags = MD_MN_NODE_ADD;
913*0Sstevel@tonic-gate 			nl2 = nl;
914*0Sstevel@tonic-gate 			while (nl2) {
915*0Sstevel@tonic-gate 				if (strcmp(nl2->msl_node_name, node_v[i])
916*0Sstevel@tonic-gate 				    == 0) {
917*0Sstevel@tonic-gate 					nr->nr_nodeid = nl2->msl_node_id;
918*0Sstevel@tonic-gate 					break;
919*0Sstevel@tonic-gate 				}
920*0Sstevel@tonic-gate 				nl2 = nl2->next;
921*0Sstevel@tonic-gate 			}
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate 			(void) strcpy(nr->nr_nodename, node_v[i]);
924*0Sstevel@tonic-gate 
925*0Sstevel@tonic-gate 			/*
926*0Sstevel@tonic-gate 			 * When a node is added to a MN diskset, set the
927*0Sstevel@tonic-gate 			 * nodeid of this node in the md_set structure
928*0Sstevel@tonic-gate 			 * in the kernel.
929*0Sstevel@tonic-gate 			 */
930*0Sstevel@tonic-gate 			if (strcmp(nr->nr_nodename, mynode()) == 0) {
931*0Sstevel@tonic-gate 				(void) memset(&snp, 0, sizeof (snp));
932*0Sstevel@tonic-gate 				snp.sn_nodeid = nr->nr_nodeid;
933*0Sstevel@tonic-gate 				snp.sn_setno = mnsr->sr_setno;
934*0Sstevel@tonic-gate 				if (metaioctl(MD_MN_SET_NODEID, &snp,
935*0Sstevel@tonic-gate 				    &snp.sn_mde, NULL) != 0) {
936*0Sstevel@tonic-gate 					(void) mdstealerror(ep, &snp.sn_mde);
937*0Sstevel@tonic-gate 					meta_free_nodelist(nl);
938*0Sstevel@tonic-gate 					free_sr(sr);
939*0Sstevel@tonic-gate 					return;
940*0Sstevel@tonic-gate 				}
941*0Sstevel@tonic-gate 			}
942*0Sstevel@tonic-gate 
943*0Sstevel@tonic-gate 			/* Link the node records and fill in in-core data */
944*0Sstevel@tonic-gate 			mnnr_cache_add(mnsr, nr);
945*0Sstevel@tonic-gate 
946*0Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST,
947*0Sstevel@tonic-gate 				mnsr->sr_setno, nr->nr_nodeid);
948*0Sstevel@tonic-gate 		} else {
949*0Sstevel@tonic-gate 			for (j = 0; j < MD_MAXSIDES; j++) {
950*0Sstevel@tonic-gate 				if (sr->sr_nodes[j][0] != '\0')
951*0Sstevel@tonic-gate 					continue;
952*0Sstevel@tonic-gate 				(void) strcpy(sr->sr_nodes[j], node_v[i]);
953*0Sstevel@tonic-gate 				SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD,
954*0Sstevel@tonic-gate 				    SVM_TAG_HOST, sr->sr_setno, j);
955*0Sstevel@tonic-gate 				break;
956*0Sstevel@tonic-gate 			}
957*0Sstevel@tonic-gate 		}
958*0Sstevel@tonic-gate 	}
959*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
960*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
961*0Sstevel@tonic-gate 		meta_free_nodelist(nl);
962*0Sstevel@tonic-gate 	}
963*0Sstevel@tonic-gate 
964*0Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
969*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
970*0Sstevel@tonic-gate 		req.ur_size = sizeof (*mnsr);
971*0Sstevel@tonic-gate 	} else {
972*0Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
973*0Sstevel@tonic-gate 	}
974*0Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
975*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
976*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
977*0Sstevel@tonic-gate 		free_sr(sr);
978*0Sstevel@tonic-gate 		return;
979*0Sstevel@tonic-gate 	}
980*0Sstevel@tonic-gate 
981*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
982*0Sstevel@tonic-gate 
983*0Sstevel@tonic-gate 	free_sr(sr);
984*0Sstevel@tonic-gate }
985*0Sstevel@tonic-gate 
986*0Sstevel@tonic-gate /*
987*0Sstevel@tonic-gate  * add 1 or more hosts to a set.
988*0Sstevel@tonic-gate  */
989*0Sstevel@tonic-gate bool_t
990*0Sstevel@tonic-gate mdrpc_addhosts_common(
991*0Sstevel@tonic-gate 	mdrpc_host_args		*args,
992*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
993*0Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
994*0Sstevel@tonic-gate 	int			version		/* RPC version */
995*0Sstevel@tonic-gate )
996*0Sstevel@tonic-gate {
997*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
998*0Sstevel@tonic-gate 	int			err;
999*0Sstevel@tonic-gate 	int			op_mode = W_OK;
1000*0Sstevel@tonic-gate 
1001*0Sstevel@tonic-gate 	/* setup, check permissions */
1002*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
1003*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1004*0Sstevel@tonic-gate 		return (FALSE);
1005*0Sstevel@tonic-gate 	else if (err != 0)
1006*0Sstevel@tonic-gate 		return (TRUE);
1007*0Sstevel@tonic-gate 
1008*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
1009*0Sstevel@tonic-gate 		return (TRUE);
1010*0Sstevel@tonic-gate 
1011*0Sstevel@tonic-gate 	/* doit */
1012*0Sstevel@tonic-gate 	addhosts(args->sp->setname, args->hosts.hosts_len,
1013*0Sstevel@tonic-gate 	    args->hosts.hosts_val, version, ep);
1014*0Sstevel@tonic-gate 
1015*0Sstevel@tonic-gate 	err = svc_fini(ep);
1016*0Sstevel@tonic-gate 
1017*0Sstevel@tonic-gate 	return (TRUE);
1018*0Sstevel@tonic-gate }
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate bool_t
1021*0Sstevel@tonic-gate mdrpc_addhosts_1_svc(
1022*0Sstevel@tonic-gate 	mdrpc_host_args		*args,
1023*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1024*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1025*0Sstevel@tonic-gate )
1026*0Sstevel@tonic-gate {
1027*0Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
1028*0Sstevel@tonic-gate 	return (mdrpc_addhosts_common(args, res, rqstp, METAD_VERSION));
1029*0Sstevel@tonic-gate }
1030*0Sstevel@tonic-gate 
1031*0Sstevel@tonic-gate bool_t
1032*0Sstevel@tonic-gate mdrpc_addhosts_2_svc(
1033*0Sstevel@tonic-gate 	mdrpc_host_2_args	*args,
1034*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1035*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1036*0Sstevel@tonic-gate )
1037*0Sstevel@tonic-gate {
1038*0Sstevel@tonic-gate 	switch (args->rev) {
1039*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
1040*0Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
1041*0Sstevel@tonic-gate 		return (mdrpc_addhosts_common(
1042*0Sstevel@tonic-gate 		    &args->mdrpc_host_2_args_u.rev1, res,
1043*0Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
1044*0Sstevel@tonic-gate 	    default:
1045*0Sstevel@tonic-gate 		return (FALSE);
1046*0Sstevel@tonic-gate 	}
1047*0Sstevel@tonic-gate }
1048*0Sstevel@tonic-gate 
1049*0Sstevel@tonic-gate static void
1050*0Sstevel@tonic-gate createset(
1051*0Sstevel@tonic-gate 	mdsetname_t		*sp,
1052*0Sstevel@tonic-gate 	md_node_nm_arr_t	nodes,
1053*0Sstevel@tonic-gate 	md_timeval32_t		timestamp,
1054*0Sstevel@tonic-gate 	ulong_t			genid,
1055*0Sstevel@tonic-gate 	md_error_t		*ep
1056*0Sstevel@tonic-gate )
1057*0Sstevel@tonic-gate {
1058*0Sstevel@tonic-gate 	mddb_userreq_t		req;
1059*0Sstevel@tonic-gate 	md_set_record		*sr;
1060*0Sstevel@tonic-gate 	int			i;
1061*0Sstevel@tonic-gate 
1062*0Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
1063*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_CREATE, 0);
1064*0Sstevel@tonic-gate 	req.ur_size = sizeof (*sr);
1065*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1066*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
1067*0Sstevel@tonic-gate 		return;
1068*0Sstevel@tonic-gate 	}
1069*0Sstevel@tonic-gate 
1070*0Sstevel@tonic-gate 	sr = Zalloc(sizeof (*sr));
1071*0Sstevel@tonic-gate 
1072*0Sstevel@tonic-gate 	sr->sr_selfid = req.ur_recid;
1073*0Sstevel@tonic-gate 	sr->sr_setno = sp->setno;
1074*0Sstevel@tonic-gate 	(void) strcpy(sr->sr_setname, sp->setname);
1075*0Sstevel@tonic-gate 
1076*0Sstevel@tonic-gate 	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
1077*0Sstevel@tonic-gate 	    NODEV64);
1078*0Sstevel@tonic-gate 
1079*0Sstevel@tonic-gate 	(void) meta_smf_enable(META_SMF_DISKSET, NULL);
1080*0Sstevel@tonic-gate 
1081*0Sstevel@tonic-gate 	for (i = 0; i < MD_MAXSIDES; i++) {
1082*0Sstevel@tonic-gate 		(void) strcpy(sr->sr_nodes[i], nodes[i]);
1083*0Sstevel@tonic-gate 		/* Skip empty slots */
1084*0Sstevel@tonic-gate 		if (sr->sr_nodes[i][0] == '\0')
1085*0Sstevel@tonic-gate 			continue;
1086*0Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
1087*0Sstevel@tonic-gate 		    i);
1088*0Sstevel@tonic-gate 	}
1089*0Sstevel@tonic-gate 
1090*0Sstevel@tonic-gate 	sr->sr_ctime = timestamp;
1091*0Sstevel@tonic-gate 	sr->sr_genid = genid;
1092*0Sstevel@tonic-gate 	sr->sr_revision = MD_SET_RECORD_REVISION;
1093*0Sstevel@tonic-gate 	sr->sr_flags |= MD_SR_ADD;
1094*0Sstevel@tonic-gate 
1095*0Sstevel@tonic-gate 	sr->sr_mhiargs = defmhiargs;
1096*0Sstevel@tonic-gate 
1097*0Sstevel@tonic-gate 	sr_cache_add(sr);
1098*0Sstevel@tonic-gate 
1099*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
1100*0Sstevel@tonic-gate }
1101*0Sstevel@tonic-gate 
1102*0Sstevel@tonic-gate static void
1103*0Sstevel@tonic-gate mncreateset(
1104*0Sstevel@tonic-gate 	mdsetname_t		*sp,
1105*0Sstevel@tonic-gate 	md_mnnode_desc		*nodelist,
1106*0Sstevel@tonic-gate 	md_timeval32_t		timestamp,
1107*0Sstevel@tonic-gate 	ulong_t			genid,
1108*0Sstevel@tonic-gate 	md_node_nm_t		master_nodenm,
1109*0Sstevel@tonic-gate 	int			master_nodeid,
1110*0Sstevel@tonic-gate 	md_error_t		*ep
1111*0Sstevel@tonic-gate )
1112*0Sstevel@tonic-gate {
1113*0Sstevel@tonic-gate 	mddb_userreq_t			req;
1114*0Sstevel@tonic-gate 	md_mnset_record			*mnsr;
1115*0Sstevel@tonic-gate 	md_mnnode_record		*nr;
1116*0Sstevel@tonic-gate 	md_mnnode_desc			*nd;
1117*0Sstevel@tonic-gate 	mddb_set_node_params_t		snp;
1118*0Sstevel@tonic-gate 	int				nodecnt;
1119*0Sstevel@tonic-gate 	mndiskset_membershiplist_t	*nl;
1120*0Sstevel@tonic-gate 
1121*0Sstevel@tonic-gate 	/*
1122*0Sstevel@tonic-gate 	 * Validate that nodes in set being created are in the
1123*0Sstevel@tonic-gate 	 * membership list on THIS node.
1124*0Sstevel@tonic-gate 	 * Initiating node has verified that nodes are in membership
1125*0Sstevel@tonic-gate 	 * list on the initiating node.
1126*0Sstevel@tonic-gate 	 * Get membershiplist from API routine.  If there's
1127*0Sstevel@tonic-gate 	 * an error, fail to add set and pass back error.
1128*0Sstevel@tonic-gate 	 */
1129*0Sstevel@tonic-gate 	if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
1130*0Sstevel@tonic-gate 		return;
1131*0Sstevel@tonic-gate 	}
1132*0Sstevel@tonic-gate 	/* Verify that all nodes are in member list */
1133*0Sstevel@tonic-gate 	nd = nodelist;
1134*0Sstevel@tonic-gate 	while (nd) {
1135*0Sstevel@tonic-gate 		/*
1136*0Sstevel@tonic-gate 		 * If node in list isn't a member of the membership,
1137*0Sstevel@tonic-gate 		 * just return error.
1138*0Sstevel@tonic-gate 		 */
1139*0Sstevel@tonic-gate 		if (meta_is_member(nd->nd_nodename, 0, nl) == 0) {
1140*0Sstevel@tonic-gate 			meta_free_nodelist(nl);
1141*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
1142*0Sstevel@tonic-gate 			    sp->setno, nd->nd_nodename, NULL, sp->setname);
1143*0Sstevel@tonic-gate 			return;
1144*0Sstevel@tonic-gate 		}
1145*0Sstevel@tonic-gate 		nd = nd->nd_next;
1146*0Sstevel@tonic-gate 	}
1147*0Sstevel@tonic-gate 	meta_free_nodelist(nl);
1148*0Sstevel@tonic-gate 
1149*0Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
1150*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_CREATE, 0);
1151*0Sstevel@tonic-gate 	req.ur_size = sizeof (*mnsr);
1152*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1153*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
1154*0Sstevel@tonic-gate 		return;
1155*0Sstevel@tonic-gate 	}
1156*0Sstevel@tonic-gate 
1157*0Sstevel@tonic-gate 	mnsr = Zalloc(sizeof (*mnsr));
1158*0Sstevel@tonic-gate 	mnsr->sr_selfid = req.ur_recid;
1159*0Sstevel@tonic-gate 	mnsr->sr_setno = sp->setno;
1160*0Sstevel@tonic-gate 	(void) strlcpy(mnsr->sr_setname, sp->setname, MD_MAX_SETNAME);
1161*0Sstevel@tonic-gate 
1162*0Sstevel@tonic-gate 	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_SET, sp->setno,
1163*0Sstevel@tonic-gate 	    NODEV64);
1164*0Sstevel@tonic-gate 
1165*0Sstevel@tonic-gate 	(void) meta_smf_enable(META_SMF_DISKSET | META_SMF_MN_DISKSET, NULL);
1166*0Sstevel@tonic-gate 
1167*0Sstevel@tonic-gate 	nd = nodelist;
1168*0Sstevel@tonic-gate 	while (nd) {
1169*0Sstevel@tonic-gate 		/* Create the node record */
1170*0Sstevel@tonic-gate 		(void) memset(&req, 0, sizeof (req));
1171*0Sstevel@tonic-gate 		METAD_SETUP_NR(MD_DB_CREATE, 0);
1172*0Sstevel@tonic-gate 		req.ur_size = sizeof (*nr);
1173*0Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1174*0Sstevel@tonic-gate 			/* Frees mnsr and any alloc'd node records */
1175*0Sstevel@tonic-gate 			free_sr((struct md_set_record *)mnsr);
1176*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
1177*0Sstevel@tonic-gate 			return;
1178*0Sstevel@tonic-gate 		}
1179*0Sstevel@tonic-gate 
1180*0Sstevel@tonic-gate 		nr = Zalloc(sizeof (*nr));
1181*0Sstevel@tonic-gate 		nr->nr_revision = MD_MNNODE_RECORD_REVISION;
1182*0Sstevel@tonic-gate 		nr->nr_selfid = req.ur_recid;
1183*0Sstevel@tonic-gate 		nr->nr_ctime = timestamp;
1184*0Sstevel@tonic-gate 		nr->nr_genid = genid;
1185*0Sstevel@tonic-gate 		nr->nr_nodeid = nd->nd_nodeid;
1186*0Sstevel@tonic-gate 		nr->nr_flags = nd->nd_flags;
1187*0Sstevel@tonic-gate 		(void) strlcpy(nr->nr_nodename, nd->nd_nodename,
1188*0Sstevel@tonic-gate 			MD_MAX_NODENAME);
1189*0Sstevel@tonic-gate 
1190*0Sstevel@tonic-gate 		/* Link the node records and fill in in-core data */
1191*0Sstevel@tonic-gate 		mnnr_cache_add(mnsr, nr);
1192*0Sstevel@tonic-gate 
1193*0Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HOST, sp->setno,
1194*0Sstevel@tonic-gate 		    nr->nr_nodeid);
1195*0Sstevel@tonic-gate 
1196*0Sstevel@tonic-gate 		nd = nd->nd_next;
1197*0Sstevel@tonic-gate 	}
1198*0Sstevel@tonic-gate 
1199*0Sstevel@tonic-gate 	/*
1200*0Sstevel@tonic-gate 	 * For backward compatibility, fill in mynode name
1201*0Sstevel@tonic-gate 	 * as the only name in the sr_nodes array.  This
1202*0Sstevel@tonic-gate 	 * allows the pre-MNdiskset code to see that there
1203*0Sstevel@tonic-gate 	 * is a node in this diskset.  This will keep the
1204*0Sstevel@tonic-gate 	 * pre-MNdiskset code from removing this set.
1205*0Sstevel@tonic-gate 	 */
1206*0Sstevel@tonic-gate 	(void) strlcpy(mnsr->sr_nodes_bw_compat[0], mynode(), MD_MAX_NODENAME);
1207*0Sstevel@tonic-gate 
1208*0Sstevel@tonic-gate 	mnsr->sr_ctime = timestamp;
1209*0Sstevel@tonic-gate 	mnsr->sr_genid = genid;
1210*0Sstevel@tonic-gate 	mnsr->sr_revision = MD_SET_RECORD_REVISION;
1211*0Sstevel@tonic-gate 	mnsr->sr_flags |= MD_SR_ADD;
1212*0Sstevel@tonic-gate 
1213*0Sstevel@tonic-gate 	mnsr->sr_flags |= MD_SR_MN;
1214*0Sstevel@tonic-gate 	strcpy(mnsr->sr_master_nodenm, master_nodenm);
1215*0Sstevel@tonic-gate 	mnsr->sr_master_nodeid = master_nodeid;
1216*0Sstevel@tonic-gate 
1217*0Sstevel@tonic-gate 	mnsr->sr_mhiargs = defmhiargs;
1218*0Sstevel@tonic-gate 
1219*0Sstevel@tonic-gate 	sr_cache_add((struct md_set_record *)mnsr);
1220*0Sstevel@tonic-gate 
1221*0Sstevel@tonic-gate 	commitset((struct md_set_record *)mnsr, TRUE, ep);
1222*0Sstevel@tonic-gate 
1223*0Sstevel@tonic-gate 	/*
1224*0Sstevel@tonic-gate 	 * When a set is created for the first time, the nodelist
1225*0Sstevel@tonic-gate 	 * will contain this node.
1226*0Sstevel@tonic-gate 	 * When a node is just being added to a set, the nodelist
1227*0Sstevel@tonic-gate 	 * will not contain this node.  This node is added to the
1228*0Sstevel@tonic-gate 	 * set structure with a later call to addhosts.
1229*0Sstevel@tonic-gate 	 *
1230*0Sstevel@tonic-gate 	 * So, if the nodelist contains an entry for this node
1231*0Sstevel@tonic-gate 	 * then set the nodeid of this node in the md_set kernel
1232*0Sstevel@tonic-gate 	 * data structure.
1233*0Sstevel@tonic-gate 	 */
1234*0Sstevel@tonic-gate 	nd = nodelist;
1235*0Sstevel@tonic-gate 	while (nd) {
1236*0Sstevel@tonic-gate 		if (strcmp(nd->nd_nodename, mynode()) == 0) {
1237*0Sstevel@tonic-gate 			break;
1238*0Sstevel@tonic-gate 		}
1239*0Sstevel@tonic-gate 		nd = nd->nd_next;
1240*0Sstevel@tonic-gate 	}
1241*0Sstevel@tonic-gate 	if (nd) {
1242*0Sstevel@tonic-gate 		(void) memset(&snp, 0, sizeof (snp));
1243*0Sstevel@tonic-gate 		snp.sn_nodeid = nd->nd_nodeid;
1244*0Sstevel@tonic-gate 		snp.sn_setno = sp->setno;
1245*0Sstevel@tonic-gate 		if (metaioctl(MD_MN_SET_NODEID, &snp, &snp.sn_mde, NULL) != 0) {
1246*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &snp.sn_mde);
1247*0Sstevel@tonic-gate 			return;
1248*0Sstevel@tonic-gate 		}
1249*0Sstevel@tonic-gate 	}
1250*0Sstevel@tonic-gate }
1251*0Sstevel@tonic-gate 
1252*0Sstevel@tonic-gate /*
1253*0Sstevel@tonic-gate  * create a set on a host
1254*0Sstevel@tonic-gate  */
1255*0Sstevel@tonic-gate bool_t
1256*0Sstevel@tonic-gate mdrpc_createset_common(
1257*0Sstevel@tonic-gate 	mdrpc_createset_args	*args,
1258*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1259*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1260*0Sstevel@tonic-gate )
1261*0Sstevel@tonic-gate {
1262*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
1263*0Sstevel@tonic-gate 	char			stringbuf1[MAXPATHLEN];
1264*0Sstevel@tonic-gate 	char			stringbuf2[MAXPATHLEN];
1265*0Sstevel@tonic-gate 	int			err;
1266*0Sstevel@tonic-gate 	int			op_mode = W_OK;
1267*0Sstevel@tonic-gate 
1268*0Sstevel@tonic-gate 	/* setup, check permissions */
1269*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
1270*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1271*0Sstevel@tonic-gate 		return (FALSE);
1272*0Sstevel@tonic-gate 	else if (err != 0)
1273*0Sstevel@tonic-gate 		return (TRUE);
1274*0Sstevel@tonic-gate 
1275*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
1276*0Sstevel@tonic-gate 		return (TRUE);
1277*0Sstevel@tonic-gate 
1278*0Sstevel@tonic-gate 	/* create the arguments for the symlink() and unlink() calls */
1279*0Sstevel@tonic-gate 	(void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
1280*0Sstevel@tonic-gate 	    args->sp->setname);
1281*0Sstevel@tonic-gate 	(void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
1282*0Sstevel@tonic-gate 	    args->sp->setno);
1283*0Sstevel@tonic-gate 
1284*0Sstevel@tonic-gate 	/*
1285*0Sstevel@tonic-gate 	 * Since we already verified that the setname was OK, make sure to
1286*0Sstevel@tonic-gate 	 * cleanup before proceeding.
1287*0Sstevel@tonic-gate 	 */
1288*0Sstevel@tonic-gate 	if (unlink(stringbuf2) == -1) {
1289*0Sstevel@tonic-gate 		if (errno != ENOENT) {
1290*0Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, stringbuf2);
1291*0Sstevel@tonic-gate 			return (TRUE);
1292*0Sstevel@tonic-gate 		}
1293*0Sstevel@tonic-gate 	}
1294*0Sstevel@tonic-gate 
1295*0Sstevel@tonic-gate 	/* create the set */
1296*0Sstevel@tonic-gate 	createset(args->sp, args->nodes, args->timestamp, args->genid, ep);
1297*0Sstevel@tonic-gate 
1298*0Sstevel@tonic-gate 	if (! mdisok(ep))
1299*0Sstevel@tonic-gate 		return (TRUE);
1300*0Sstevel@tonic-gate 
1301*0Sstevel@tonic-gate 	/* create the symlink */
1302*0Sstevel@tonic-gate 	if (symlink(stringbuf1, stringbuf2) == -1)
1303*0Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, stringbuf2);
1304*0Sstevel@tonic-gate 
1305*0Sstevel@tonic-gate 	err = svc_fini(ep);
1306*0Sstevel@tonic-gate 
1307*0Sstevel@tonic-gate 	return (TRUE);
1308*0Sstevel@tonic-gate }
1309*0Sstevel@tonic-gate 
1310*0Sstevel@tonic-gate bool_t
1311*0Sstevel@tonic-gate mdrpc_createset_1_svc(
1312*0Sstevel@tonic-gate 	mdrpc_createset_args	*args,
1313*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1314*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1315*0Sstevel@tonic-gate )
1316*0Sstevel@tonic-gate {
1317*0Sstevel@tonic-gate 	return (mdrpc_createset_common(args, res, rqstp));
1318*0Sstevel@tonic-gate }
1319*0Sstevel@tonic-gate 
1320*0Sstevel@tonic-gate bool_t
1321*0Sstevel@tonic-gate mdrpc_createset_2_svc(
1322*0Sstevel@tonic-gate 	mdrpc_createset_2_args	*args,
1323*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1324*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1325*0Sstevel@tonic-gate )
1326*0Sstevel@tonic-gate {
1327*0Sstevel@tonic-gate 	switch (args->rev) {
1328*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
1329*0Sstevel@tonic-gate 		return (mdrpc_createset_common(
1330*0Sstevel@tonic-gate 		    &args->mdrpc_createset_2_args_u.rev1, res, rqstp));
1331*0Sstevel@tonic-gate 	    default:
1332*0Sstevel@tonic-gate 		return (FALSE);
1333*0Sstevel@tonic-gate 	}
1334*0Sstevel@tonic-gate }
1335*0Sstevel@tonic-gate 
1336*0Sstevel@tonic-gate bool_t
1337*0Sstevel@tonic-gate mdrpc_mncreateset_common(
1338*0Sstevel@tonic-gate 	mdrpc_mncreateset_args	*args,
1339*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1340*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1341*0Sstevel@tonic-gate )
1342*0Sstevel@tonic-gate {
1343*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
1344*0Sstevel@tonic-gate 	char			stringbuf1[MAXPATHLEN];
1345*0Sstevel@tonic-gate 	char			stringbuf2[MAXPATHLEN];
1346*0Sstevel@tonic-gate 	int			err;
1347*0Sstevel@tonic-gate 	int			op_mode = W_OK;
1348*0Sstevel@tonic-gate 
1349*0Sstevel@tonic-gate 	/* setup, check permissions */
1350*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
1351*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1352*0Sstevel@tonic-gate 		return (FALSE);
1353*0Sstevel@tonic-gate 	else if (err != 0)
1354*0Sstevel@tonic-gate 		return (TRUE);
1355*0Sstevel@tonic-gate 
1356*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
1357*0Sstevel@tonic-gate 		return (TRUE);
1358*0Sstevel@tonic-gate 
1359*0Sstevel@tonic-gate 	/* create the arguments for the symlink() and unlink() calls */
1360*0Sstevel@tonic-gate 	(void) snprintf(stringbuf2, sizeof (stringbuf2), "/dev/md/%s",
1361*0Sstevel@tonic-gate 	    args->sp->setname);
1362*0Sstevel@tonic-gate 	(void) snprintf(stringbuf1, sizeof (stringbuf1), "shared/%d",
1363*0Sstevel@tonic-gate 	    args->sp->setno);
1364*0Sstevel@tonic-gate 
1365*0Sstevel@tonic-gate 	/*
1366*0Sstevel@tonic-gate 	 * Since we already verified that the setname was OK, make sure to
1367*0Sstevel@tonic-gate 	 * cleanup before proceeding.
1368*0Sstevel@tonic-gate 	 */
1369*0Sstevel@tonic-gate 	if (unlink(stringbuf2) == -1) {
1370*0Sstevel@tonic-gate 		if (errno != ENOENT) {
1371*0Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, stringbuf2);
1372*0Sstevel@tonic-gate 			return (TRUE);
1373*0Sstevel@tonic-gate 		}
1374*0Sstevel@tonic-gate 	}
1375*0Sstevel@tonic-gate 
1376*0Sstevel@tonic-gate 	/* create the set */
1377*0Sstevel@tonic-gate 	mncreateset(args->sp, args->nodelist, args->timestamp, args->genid,
1378*0Sstevel@tonic-gate 		    args->master_nodenm, args->master_nodeid, ep);
1379*0Sstevel@tonic-gate 
1380*0Sstevel@tonic-gate 	if (! mdisok(ep)) {
1381*0Sstevel@tonic-gate 		return (TRUE);
1382*0Sstevel@tonic-gate 	}
1383*0Sstevel@tonic-gate 
1384*0Sstevel@tonic-gate 	/* create the symlink */
1385*0Sstevel@tonic-gate 	if (symlink(stringbuf1, stringbuf2) == -1)
1386*0Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, stringbuf2);
1387*0Sstevel@tonic-gate 
1388*0Sstevel@tonic-gate 	err = svc_fini(ep);
1389*0Sstevel@tonic-gate 
1390*0Sstevel@tonic-gate 	return (TRUE);
1391*0Sstevel@tonic-gate }
1392*0Sstevel@tonic-gate 
1393*0Sstevel@tonic-gate bool_t
1394*0Sstevel@tonic-gate mdrpc_mncreateset_2_svc(
1395*0Sstevel@tonic-gate 	mdrpc_mncreateset_2_args	*args,
1396*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1397*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1398*0Sstevel@tonic-gate )
1399*0Sstevel@tonic-gate {
1400*0Sstevel@tonic-gate 	switch (args->rev) {
1401*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
1402*0Sstevel@tonic-gate 		return (mdrpc_mncreateset_common(
1403*0Sstevel@tonic-gate 		    &args->mdrpc_mncreateset_2_args_u.rev1, res, rqstp));
1404*0Sstevel@tonic-gate 	    default:
1405*0Sstevel@tonic-gate 		return (FALSE);
1406*0Sstevel@tonic-gate 	}
1407*0Sstevel@tonic-gate }
1408*0Sstevel@tonic-gate 
1409*0Sstevel@tonic-gate static void
1410*0Sstevel@tonic-gate del_drv_sidenms(
1411*0Sstevel@tonic-gate 	mdsetname_t	*sp,
1412*0Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
1413*0Sstevel@tonic-gate 	md_error_t	*ep
1414*0Sstevel@tonic-gate )
1415*0Sstevel@tonic-gate {
1416*0Sstevel@tonic-gate 	md_set_record	*sr;
1417*0Sstevel@tonic-gate 	md_drive_desc	*dd, *p;
1418*0Sstevel@tonic-gate 	mddrivename_t	*dn;
1419*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
1420*0Sstevel@tonic-gate 	int		i;
1421*0Sstevel@tonic-gate 	int		rb_mode = 0;
1422*0Sstevel@tonic-gate 
1423*0Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
1424*0Sstevel@tonic-gate 		return;
1425*0Sstevel@tonic-gate 
1426*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
1427*0Sstevel@tonic-gate 		return;
1428*0Sstevel@tonic-gate 
1429*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
1430*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1431*0Sstevel@tonic-gate 		/*
1432*0Sstevel@tonic-gate 		 * In the multi-node diskset, there are no diskset
1433*0Sstevel@tonic-gate 		 * entries in the local set for other nodes, so there's
1434*0Sstevel@tonic-gate 		 * nothing to do.
1435*0Sstevel@tonic-gate 		 */
1436*0Sstevel@tonic-gate 		free_sr(sr);
1437*0Sstevel@tonic-gate 		return;
1438*0Sstevel@tonic-gate 	}
1439*0Sstevel@tonic-gate 
1440*0Sstevel@tonic-gate 	if ((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
1441*0Sstevel@tonic-gate 	    ep)) == NULL) {
1442*0Sstevel@tonic-gate 		if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE)) {
1443*0Sstevel@tonic-gate 			metaflushsetname(sp);
1444*0Sstevel@tonic-gate 			if (! mdisok(ep)) {
1445*0Sstevel@tonic-gate 				free_sr(sr);
1446*0Sstevel@tonic-gate 				return;
1447*0Sstevel@tonic-gate 			}
1448*0Sstevel@tonic-gate 			/* we are supposed to have drives!!!! */
1449*0Sstevel@tonic-gate 			assert(0);
1450*0Sstevel@tonic-gate 		}
1451*0Sstevel@tonic-gate 		rb_mode = 1;
1452*0Sstevel@tonic-gate 		mdclrerror(ep);
1453*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
1454*0Sstevel@tonic-gate 			/* Skip empty sides of the diskset */
1455*0Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
1456*0Sstevel@tonic-gate 				continue;
1457*0Sstevel@tonic-gate 			dd = metaget_drivedesc_sideno(sp, i,
1458*0Sstevel@tonic-gate 			    (MD_BASICNAME_OK | PRINT_FAST), ep);
1459*0Sstevel@tonic-gate 			/* Got dd, get out of loop */
1460*0Sstevel@tonic-gate 			if (dd != NULL)
1461*0Sstevel@tonic-gate 				break;
1462*0Sstevel@tonic-gate 
1463*0Sstevel@tonic-gate 			/* some error occurred, get out of loop */
1464*0Sstevel@tonic-gate 			if (! mdisok(ep))
1465*0Sstevel@tonic-gate 				break;
1466*0Sstevel@tonic-gate 		}
1467*0Sstevel@tonic-gate 		/*
1468*0Sstevel@tonic-gate 		 * At this point, we have one of three possibilities:
1469*0Sstevel@tonic-gate 		 *	1) dd != NULL (we have found drives using an alternate
1470*0Sstevel@tonic-gate 		 *	   side.)
1471*0Sstevel@tonic-gate 		 *	2) dd == NULL (no drives) && mdisok(ep) : assert(0)
1472*0Sstevel@tonic-gate 		 *	3) dd == NULL (no drives) && ! mdisok(ep) : return
1473*0Sstevel@tonic-gate 		 *	   error information to caller.
1474*0Sstevel@tonic-gate 		 */
1475*0Sstevel@tonic-gate 		if (dd == NULL) {
1476*0Sstevel@tonic-gate 			metaflushsetname(sp);
1477*0Sstevel@tonic-gate 			if (! mdisok(ep)) {
1478*0Sstevel@tonic-gate 				free_sr(sr);
1479*0Sstevel@tonic-gate 				return;
1480*0Sstevel@tonic-gate 			}
1481*0Sstevel@tonic-gate 			/* we are supposed to have drives!!!! */
1482*0Sstevel@tonic-gate 			assert(0);
1483*0Sstevel@tonic-gate 		}
1484*0Sstevel@tonic-gate 	}
1485*0Sstevel@tonic-gate 
1486*0Sstevel@tonic-gate 	/*
1487*0Sstevel@tonic-gate 	 * Let's run through each drive descriptor, and delete the
1488*0Sstevel@tonic-gate 	 * sidename for all sides that are not in the sr_nodes array.
1489*0Sstevel@tonic-gate 	 * We will ignore errors, cause the empty side may not
1490*0Sstevel@tonic-gate 	 * have had any names to begin with.
1491*0Sstevel@tonic-gate 	 */
1492*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
1493*0Sstevel@tonic-gate 		dn = p->dd_dnp;
1494*0Sstevel@tonic-gate 
1495*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
1496*0Sstevel@tonic-gate 			/* Skip existing sides of the diskset */
1497*0Sstevel@tonic-gate 			if (!rb_mode && sr->sr_nodes[i][0] != '\0')
1498*0Sstevel@tonic-gate 				continue;
1499*0Sstevel@tonic-gate 			/* An empty side, delete the sidename */
1500*0Sstevel@tonic-gate 			if (del_name(local_sp, i+SKEW,
1501*0Sstevel@tonic-gate 			    dn->side_names_key, ep)) {
1502*0Sstevel@tonic-gate 				if (!mdissyserror(ep, ENOENT)) {
1503*0Sstevel@tonic-gate 					free_sr(sr);
1504*0Sstevel@tonic-gate 					return;
1505*0Sstevel@tonic-gate 				}
1506*0Sstevel@tonic-gate 				mdclrerror(ep);
1507*0Sstevel@tonic-gate 			}
1508*0Sstevel@tonic-gate 		}
1509*0Sstevel@tonic-gate 	}
1510*0Sstevel@tonic-gate 	free_sr(sr);
1511*0Sstevel@tonic-gate 	metaflushsetname(sp);
1512*0Sstevel@tonic-gate }
1513*0Sstevel@tonic-gate 
1514*0Sstevel@tonic-gate /*
1515*0Sstevel@tonic-gate  * delete 1 or more sidenames per drive desc, from the local namespace
1516*0Sstevel@tonic-gate  */
1517*0Sstevel@tonic-gate bool_t
1518*0Sstevel@tonic-gate mdrpc_del_drv_sidenms_common(
1519*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
1520*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1521*0Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
1522*0Sstevel@tonic-gate 	int			version		/* RPC version */
1523*0Sstevel@tonic-gate )
1524*0Sstevel@tonic-gate {
1525*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
1526*0Sstevel@tonic-gate 	int			err;
1527*0Sstevel@tonic-gate 	int			op_mode = W_OK;
1528*0Sstevel@tonic-gate 
1529*0Sstevel@tonic-gate 	/* setup, check permissions */
1530*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
1531*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1532*0Sstevel@tonic-gate 		return (FALSE);
1533*0Sstevel@tonic-gate 	else if (err != 0)
1534*0Sstevel@tonic-gate 		return (TRUE);
1535*0Sstevel@tonic-gate 
1536*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
1537*0Sstevel@tonic-gate 		return (TRUE);
1538*0Sstevel@tonic-gate 
1539*0Sstevel@tonic-gate 	/* doit */
1540*0Sstevel@tonic-gate 	del_drv_sidenms(args->sp, version, ep);
1541*0Sstevel@tonic-gate 
1542*0Sstevel@tonic-gate 	err = svc_fini(ep);
1543*0Sstevel@tonic-gate 
1544*0Sstevel@tonic-gate 	return (TRUE);
1545*0Sstevel@tonic-gate }
1546*0Sstevel@tonic-gate 
1547*0Sstevel@tonic-gate bool_t
1548*0Sstevel@tonic-gate mdrpc_del_drv_sidenms_1_svc(
1549*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
1550*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1551*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1552*0Sstevel@tonic-gate )
1553*0Sstevel@tonic-gate {
1554*0Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
1555*0Sstevel@tonic-gate 	return (mdrpc_del_drv_sidenms_common(args, res, rqstp, METAD_VERSION));
1556*0Sstevel@tonic-gate }
1557*0Sstevel@tonic-gate 
1558*0Sstevel@tonic-gate bool_t
1559*0Sstevel@tonic-gate mdrpc_del_drv_sidenms_2_svc(
1560*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
1561*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1562*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1563*0Sstevel@tonic-gate )
1564*0Sstevel@tonic-gate {
1565*0Sstevel@tonic-gate 	switch (args->rev) {
1566*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
1567*0Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
1568*0Sstevel@tonic-gate 		return (mdrpc_del_drv_sidenms_common(
1569*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res,
1570*0Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
1571*0Sstevel@tonic-gate 	    default:
1572*0Sstevel@tonic-gate 		return (FALSE);
1573*0Sstevel@tonic-gate 	}
1574*0Sstevel@tonic-gate }
1575*0Sstevel@tonic-gate 
1576*0Sstevel@tonic-gate static int
1577*0Sstevel@tonic-gate del_sidenamelist(
1578*0Sstevel@tonic-gate 	md_set_record	*sr,
1579*0Sstevel@tonic-gate 	mddrivename_t	*dn,
1580*0Sstevel@tonic-gate 	md_error_t	*ep
1581*0Sstevel@tonic-gate )
1582*0Sstevel@tonic-gate {
1583*0Sstevel@tonic-gate 	mdsidenames_t	*sn;
1584*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
1585*0Sstevel@tonic-gate 	md_mnset_record	*mnsr;
1586*0Sstevel@tonic-gate 	md_mnnode_record *nr;
1587*0Sstevel@tonic-gate 
1588*0Sstevel@tonic-gate 	if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
1589*0Sstevel@tonic-gate 		return (-1);
1590*0Sstevel@tonic-gate 
1591*0Sstevel@tonic-gate 	for (sn = dn->side_names; sn != NULL; sn = sn->next)
1592*0Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
1593*0Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
1594*0Sstevel@tonic-gate 			/*
1595*0Sstevel@tonic-gate 			 * Only delete side name entries for this node
1596*0Sstevel@tonic-gate 			 * on a multi-node diskset.
1597*0Sstevel@tonic-gate 			 */
1598*0Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
1599*0Sstevel@tonic-gate 			while (nr) {
1600*0Sstevel@tonic-gate 				if (nr->nr_nodeid == sn->sideno) {
1601*0Sstevel@tonic-gate 					if (del_name(local_sp, sn->sideno,
1602*0Sstevel@tonic-gate 					    dn->side_names_key, ep) == -1)
1603*0Sstevel@tonic-gate 						mdclrerror(ep); /* ignore err */
1604*0Sstevel@tonic-gate 					break;
1605*0Sstevel@tonic-gate 				}
1606*0Sstevel@tonic-gate 				nr = nr->nr_next;
1607*0Sstevel@tonic-gate 			}
1608*0Sstevel@tonic-gate 		} else {
1609*0Sstevel@tonic-gate 			if (del_name(local_sp, sn->sideno+SKEW,
1610*0Sstevel@tonic-gate 			    dn->side_names_key, ep) == -1)
1611*0Sstevel@tonic-gate 				mdclrerror(ep);	/* ignore errors */
1612*0Sstevel@tonic-gate 		}
1613*0Sstevel@tonic-gate 
1614*0Sstevel@tonic-gate 	dn->side_names_key = MD_KEYBAD;
1615*0Sstevel@tonic-gate 	return (0);
1616*0Sstevel@tonic-gate }
1617*0Sstevel@tonic-gate 
1618*0Sstevel@tonic-gate static void
1619*0Sstevel@tonic-gate deldrvs(
1620*0Sstevel@tonic-gate 	char		*setname,
1621*0Sstevel@tonic-gate 	md_drive_desc	*dd,
1622*0Sstevel@tonic-gate 	md_error_t	*ep
1623*0Sstevel@tonic-gate )
1624*0Sstevel@tonic-gate {
1625*0Sstevel@tonic-gate 	mdsetname_t	*sp;
1626*0Sstevel@tonic-gate 	md_set_record	*sr;
1627*0Sstevel@tonic-gate 	md_drive_record	*dr;
1628*0Sstevel@tonic-gate 	mddb_userreq_t	req;
1629*0Sstevel@tonic-gate 	md_drive_desc	*p;
1630*0Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
1631*0Sstevel@tonic-gate 	side_t		sideno;
1632*0Sstevel@tonic-gate 	int		i;
1633*0Sstevel@tonic-gate 	int		rb_mode = 0;
1634*0Sstevel@tonic-gate 	mdname_t	*np;
1635*0Sstevel@tonic-gate 	md_dev64_t	dev;
1636*0Sstevel@tonic-gate 	md_error_t	xep = mdnullerror;
1637*0Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
1638*0Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
1639*0Sstevel@tonic-gate 	int		devid_same = -1;
1640*0Sstevel@tonic-gate 	int		using_devid = 0;
1641*0Sstevel@tonic-gate 	md_mnnode_record	*nr;
1642*0Sstevel@tonic-gate 	md_mnset_record		*mnsr;
1643*0Sstevel@tonic-gate 
1644*0Sstevel@tonic-gate 	if ((sp = metasetname(setname, ep)) == NULL)
1645*0Sstevel@tonic-gate 		return;
1646*0Sstevel@tonic-gate 
1647*0Sstevel@tonic-gate 	metaflushsetname(sp);
1648*0Sstevel@tonic-gate 
1649*0Sstevel@tonic-gate 	if ((sideno = getmyside(sp, ep)) == MD_SIDEWILD) {
1650*0Sstevel@tonic-gate 		if (! mdisdserror(ep, MDE_DS_HOSTNOSIDE))
1651*0Sstevel@tonic-gate 			return;
1652*0Sstevel@tonic-gate 		mdclrerror(ep);
1653*0Sstevel@tonic-gate 		/*
1654*0Sstevel@tonic-gate 		 * The set record is incomplete, so we need to make note
1655*0Sstevel@tonic-gate 		 * here so that we can do some special handling later.
1656*0Sstevel@tonic-gate 		 */
1657*0Sstevel@tonic-gate 		rb_mode = 1;
1658*0Sstevel@tonic-gate 	}
1659*0Sstevel@tonic-gate 
1660*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
1661*0Sstevel@tonic-gate 		return;
1662*0Sstevel@tonic-gate 
1663*0Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
1664*0Sstevel@tonic-gate 		return;
1665*0Sstevel@tonic-gate 
1666*0Sstevel@tonic-gate 	/*
1667*0Sstevel@tonic-gate 	 * The system is either all devid or all
1668*0Sstevel@tonic-gate 	 * non-devid so we determine this by looking
1669*0Sstevel@tonic-gate 	 * at the first item in the list.
1670*0Sstevel@tonic-gate 	 *
1671*0Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
1672*0Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
1673*0Sstevel@tonic-gate 	 * before set the using_devid.
1674*0Sstevel@tonic-gate 	 */
1675*0Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
1676*0Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
1677*0Sstevel@tonic-gate 		using_devid = 1;
1678*0Sstevel@tonic-gate 
1679*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
1680*0Sstevel@tonic-gate 		dn = p->dd_dnp;
1681*0Sstevel@tonic-gate 		devid_remote = NULL;
1682*0Sstevel@tonic-gate 
1683*0Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
1684*0Sstevel@tonic-gate 		    using_devid) {
1685*0Sstevel@tonic-gate 			/*
1686*0Sstevel@tonic-gate 			 * We have a devid so use it
1687*0Sstevel@tonic-gate 			 */
1688*0Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
1689*0Sstevel@tonic-gate 		}
1690*0Sstevel@tonic-gate 
1691*0Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
1692*0Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
1693*0Sstevel@tonic-gate 			/* something went really wrong. Can't process */
1694*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
1695*0Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
1696*0Sstevel@tonic-gate 			return;
1697*0Sstevel@tonic-gate 		}
1698*0Sstevel@tonic-gate 
1699*0Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
1700*0Sstevel@tonic-gate 			devid_same = -1;
1701*0Sstevel@tonic-gate 
1702*0Sstevel@tonic-gate 			if (! rb_mode) {
1703*0Sstevel@tonic-gate 				dn1 = metadrivename_withdrkey(sp, sideno,
1704*0Sstevel@tonic-gate 				    dr->dr_key, MD_BASICNAME_OK, ep);
1705*0Sstevel@tonic-gate 				if (dn1 == NULL) {
1706*0Sstevel@tonic-gate 					free_sr(sr);
1707*0Sstevel@tonic-gate 					if (devid_remote)
1708*0Sstevel@tonic-gate 						devid_free(devid_remote);
1709*0Sstevel@tonic-gate 					return;
1710*0Sstevel@tonic-gate 				}
1711*0Sstevel@tonic-gate 			} else {
1712*0Sstevel@tonic-gate 				/*
1713*0Sstevel@tonic-gate 				 * Handle special case here where sidenames
1714*0Sstevel@tonic-gate 				 * from other hosts for this drive may be
1715*0Sstevel@tonic-gate 				 * in the local mddb, but there is no
1716*0Sstevel@tonic-gate 				 * sidename entry for this host for this drive.
1717*0Sstevel@tonic-gate 				 * This could have happened if the node
1718*0Sstevel@tonic-gate 				 * panic'd between the 2 operations when
1719*0Sstevel@tonic-gate 				 * adding this node to the set.
1720*0Sstevel@tonic-gate 				 * So, delete all sidename entries for this
1721*0Sstevel@tonic-gate 				 * drive.
1722*0Sstevel@tonic-gate 				 */
1723*0Sstevel@tonic-gate 				if (MD_MNSET_REC(sr)) {
1724*0Sstevel@tonic-gate 					mnsr = (struct md_mnset_record *)sr;
1725*0Sstevel@tonic-gate 					nr = mnsr->sr_nodechain;
1726*0Sstevel@tonic-gate 					while (nr) {
1727*0Sstevel@tonic-gate 						/* We delete all dr sides */
1728*0Sstevel@tonic-gate 						dn1 = metadrivename_withdrkey(
1729*0Sstevel@tonic-gate 						    sp, nr->nr_nodeid,
1730*0Sstevel@tonic-gate 						    dr->dr_key,
1731*0Sstevel@tonic-gate 						    MD_BASICNAME_OK, ep);
1732*0Sstevel@tonic-gate 
1733*0Sstevel@tonic-gate 						/* if we do, get out of loop */
1734*0Sstevel@tonic-gate 						if (dn1 != NULL)
1735*0Sstevel@tonic-gate 							break;
1736*0Sstevel@tonic-gate 
1737*0Sstevel@tonic-gate 						/* save error for later */
1738*0Sstevel@tonic-gate 						(void) mdstealerror(&xep, ep);
1739*0Sstevel@tonic-gate 
1740*0Sstevel@tonic-gate 						mdclrerror(ep);
1741*0Sstevel@tonic-gate 
1742*0Sstevel@tonic-gate 						nr = nr->nr_next;
1743*0Sstevel@tonic-gate 					}
1744*0Sstevel@tonic-gate 				} else {
1745*0Sstevel@tonic-gate 					/*
1746*0Sstevel@tonic-gate 					 * Handle special case here
1747*0Sstevel@tonic-gate 					 * for traditional diskset
1748*0Sstevel@tonic-gate 					 */
1749*0Sstevel@tonic-gate 					for (i = 0; i < MD_MAXSIDES; i++) {
1750*0Sstevel@tonic-gate 						/* We delete all dr sides */
1751*0Sstevel@tonic-gate 						dn1 = metadrivename_withdrkey(
1752*0Sstevel@tonic-gate 						    sp, i, dr->dr_key,
1753*0Sstevel@tonic-gate 						    MD_BASICNAME_OK, ep);
1754*0Sstevel@tonic-gate 
1755*0Sstevel@tonic-gate 						/* if we do, get out of loop */
1756*0Sstevel@tonic-gate 						if (dn1 != NULL)
1757*0Sstevel@tonic-gate 							break;
1758*0Sstevel@tonic-gate 
1759*0Sstevel@tonic-gate 						/* save error for later */
1760*0Sstevel@tonic-gate 						(void) mdstealerror(&xep, ep);
1761*0Sstevel@tonic-gate 
1762*0Sstevel@tonic-gate 						mdclrerror(ep);
1763*0Sstevel@tonic-gate 					}
1764*0Sstevel@tonic-gate 				}
1765*0Sstevel@tonic-gate 
1766*0Sstevel@tonic-gate 				if (dn1 == NULL) {
1767*0Sstevel@tonic-gate 					(void) mdstealerror(ep, &xep);
1768*0Sstevel@tonic-gate 					free_sr(sr);
1769*0Sstevel@tonic-gate 					if (devid_remote)
1770*0Sstevel@tonic-gate 						devid_free(devid_remote);
1771*0Sstevel@tonic-gate 					return;
1772*0Sstevel@tonic-gate 				}
1773*0Sstevel@tonic-gate 
1774*0Sstevel@tonic-gate 				if (!using_devid)
1775*0Sstevel@tonic-gate 					mdclrerror(ep);
1776*0Sstevel@tonic-gate 			}
1777*0Sstevel@tonic-gate 
1778*0Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
1779*0Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid, &devid_local,
1780*0Sstevel@tonic-gate 				    NULL) == 0) {
1781*0Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
1782*0Sstevel@tonic-gate 					    devid_local);
1783*0Sstevel@tonic-gate 					devid_free(devid_local);
1784*0Sstevel@tonic-gate 				}
1785*0Sstevel@tonic-gate 			}
1786*0Sstevel@tonic-gate 
1787*0Sstevel@tonic-gate 			/*
1788*0Sstevel@tonic-gate 			 * Has the required disk been found - either the devids
1789*0Sstevel@tonic-gate 			 * match if devid are being used or the actual name of
1790*0Sstevel@tonic-gate 			 * the disk matches.
1791*0Sstevel@tonic-gate 			 */
1792*0Sstevel@tonic-gate 			if ((using_devid && devid_same == 0) ||
1793*0Sstevel@tonic-gate 			    (!using_devid &&
1794*0Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)) {
1795*0Sstevel@tonic-gate 				uint_t	rep_slice;
1796*0Sstevel@tonic-gate 
1797*0Sstevel@tonic-gate 				dev = NODEV64;
1798*0Sstevel@tonic-gate 				np = NULL;
1799*0Sstevel@tonic-gate 				if (meta_replicaslice(dn1,
1800*0Sstevel@tonic-gate 				    &rep_slice, &xep) == 0) {
1801*0Sstevel@tonic-gate 					np = metaslicename(dn1,
1802*0Sstevel@tonic-gate 					    rep_slice, &xep);
1803*0Sstevel@tonic-gate 				}
1804*0Sstevel@tonic-gate 
1805*0Sstevel@tonic-gate 				if (np != NULL)
1806*0Sstevel@tonic-gate 					dev = np->dev;
1807*0Sstevel@tonic-gate 				else
1808*0Sstevel@tonic-gate 					mdclrerror(&xep);
1809*0Sstevel@tonic-gate 				break;
1810*0Sstevel@tonic-gate 			}
1811*0Sstevel@tonic-gate 		}
1812*0Sstevel@tonic-gate 
1813*0Sstevel@tonic-gate 		if (dr) {
1814*0Sstevel@tonic-gate 			(void) memset(&req, 0, sizeof (req));
1815*0Sstevel@tonic-gate 			METAD_SETUP_DR(MD_DB_DELETE, dr->dr_selfid)
1816*0Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
1817*0Sstevel@tonic-gate 			    != 0) {
1818*0Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
1819*0Sstevel@tonic-gate 				if (devid_remote)
1820*0Sstevel@tonic-gate 					devid_free(devid_remote);
1821*0Sstevel@tonic-gate 				free_sr(sr);
1822*0Sstevel@tonic-gate 				return;
1823*0Sstevel@tonic-gate 			}
1824*0Sstevel@tonic-gate 
1825*0Sstevel@tonic-gate 			dr_cache_del(sr, dr->dr_selfid);
1826*0Sstevel@tonic-gate 
1827*0Sstevel@tonic-gate 			if (del_sidenamelist(sr, dn1, ep) == -1) {
1828*0Sstevel@tonic-gate 				goto out;
1829*0Sstevel@tonic-gate 			}
1830*0Sstevel@tonic-gate 
1831*0Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
1832*0Sstevel@tonic-gate 			    sr->sr_setno, dev);
1833*0Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
1834*0Sstevel@tonic-gate 			    MD_LOCAL_SET, dev);
1835*0Sstevel@tonic-gate 
1836*0Sstevel@tonic-gate 			continue;
1837*0Sstevel@tonic-gate 		}
1838*0Sstevel@tonic-gate 
1839*0Sstevel@tonic-gate 		if (devid_remote)
1840*0Sstevel@tonic-gate 			devid_free(devid_remote);
1841*0Sstevel@tonic-gate 	}
1842*0Sstevel@tonic-gate 
1843*0Sstevel@tonic-gate out:
1844*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
1845*0Sstevel@tonic-gate 
1846*0Sstevel@tonic-gate 	free_sr(sr);
1847*0Sstevel@tonic-gate }
1848*0Sstevel@tonic-gate 
1849*0Sstevel@tonic-gate /*
1850*0Sstevel@tonic-gate  * delete 1 or more drive records from a host.
1851*0Sstevel@tonic-gate  */
1852*0Sstevel@tonic-gate bool_t
1853*0Sstevel@tonic-gate mdrpc_deldrvs_common(
1854*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
1855*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1856*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1857*0Sstevel@tonic-gate )
1858*0Sstevel@tonic-gate {
1859*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
1860*0Sstevel@tonic-gate 	int			err;
1861*0Sstevel@tonic-gate 	int			op_mode = W_OK;
1862*0Sstevel@tonic-gate 
1863*0Sstevel@tonic-gate 	/* setup, check permissions */
1864*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
1865*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
1866*0Sstevel@tonic-gate 		return (FALSE);
1867*0Sstevel@tonic-gate 	else if (err != 0)
1868*0Sstevel@tonic-gate 		return (TRUE);
1869*0Sstevel@tonic-gate 
1870*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
1871*0Sstevel@tonic-gate 		return (TRUE);
1872*0Sstevel@tonic-gate 
1873*0Sstevel@tonic-gate 	/* doit */
1874*0Sstevel@tonic-gate 	deldrvs(args->sp->setname, args->drivedescs, ep);
1875*0Sstevel@tonic-gate 
1876*0Sstevel@tonic-gate 	err = svc_fini(ep);
1877*0Sstevel@tonic-gate 
1878*0Sstevel@tonic-gate 	return (TRUE);
1879*0Sstevel@tonic-gate }
1880*0Sstevel@tonic-gate 
1881*0Sstevel@tonic-gate /*
1882*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
1883*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
1884*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
1885*0Sstevel@tonic-gate  */
1886*0Sstevel@tonic-gate bool_t
1887*0Sstevel@tonic-gate mdrpc_deldrvs_1_svc(
1888*0Sstevel@tonic-gate 	mdrpc_drives_args	*args,
1889*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1890*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1891*0Sstevel@tonic-gate )
1892*0Sstevel@tonic-gate {
1893*0Sstevel@tonic-gate 	bool_t			retval;
1894*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
1895*0Sstevel@tonic-gate 
1896*0Sstevel@tonic-gate 	/* allocate memory */
1897*0Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
1898*0Sstevel@tonic-gate 
1899*0Sstevel@tonic-gate 	/* build args */
1900*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
1901*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
1902*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
1903*0Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
1904*0Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
1905*0Sstevel@tonic-gate 	v2_args.genid = args->genid;
1906*0Sstevel@tonic-gate 
1907*0Sstevel@tonic-gate 	retval = mdrpc_deldrvs_common(&v2_args, res, rqstp);
1908*0Sstevel@tonic-gate 
1909*0Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
1910*0Sstevel@tonic-gate 
1911*0Sstevel@tonic-gate 	return (retval);
1912*0Sstevel@tonic-gate }
1913*0Sstevel@tonic-gate 
1914*0Sstevel@tonic-gate bool_t
1915*0Sstevel@tonic-gate mdrpc_deldrvs_2_svc(
1916*0Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
1917*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
1918*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
1919*0Sstevel@tonic-gate )
1920*0Sstevel@tonic-gate {
1921*0Sstevel@tonic-gate 	switch (args->rev) {
1922*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
1923*0Sstevel@tonic-gate 		return (mdrpc_deldrvs_common(
1924*0Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
1925*0Sstevel@tonic-gate 	    default:
1926*0Sstevel@tonic-gate 		return (FALSE);
1927*0Sstevel@tonic-gate 	}
1928*0Sstevel@tonic-gate }
1929*0Sstevel@tonic-gate 
1930*0Sstevel@tonic-gate static void
1931*0Sstevel@tonic-gate delhosts(
1932*0Sstevel@tonic-gate 	char		*setname,
1933*0Sstevel@tonic-gate 	int		node_c,
1934*0Sstevel@tonic-gate 	char		**node_v,
1935*0Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
1936*0Sstevel@tonic-gate 	md_error_t	*ep
1937*0Sstevel@tonic-gate )
1938*0Sstevel@tonic-gate {
1939*0Sstevel@tonic-gate 	mddb_userreq_t		req;
1940*0Sstevel@tonic-gate 	md_set_record		*sr;
1941*0Sstevel@tonic-gate 	int			i, j;
1942*0Sstevel@tonic-gate 	md_mnset_record		*mnsr;
1943*0Sstevel@tonic-gate 	md_mnnode_record	*nr;
1944*0Sstevel@tonic-gate 
1945*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
1946*0Sstevel@tonic-gate 		return;
1947*0Sstevel@tonic-gate 
1948*0Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
1949*0Sstevel@tonic-gate 		/* Do MN operation if rpc version supports it and if a MN set */
1950*0Sstevel@tonic-gate 		if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1951*0Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
1952*0Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
1953*0Sstevel@tonic-gate 			while (nr) {
1954*0Sstevel@tonic-gate 				if (strcmp(nr->nr_nodename, node_v[i]) == 0) {
1955*0Sstevel@tonic-gate 					SE_NOTIFY(EC_SVM_CONFIG,
1956*0Sstevel@tonic-gate 						ESC_SVM_REMOVE, SVM_TAG_HOST,
1957*0Sstevel@tonic-gate 						sr->sr_setno, nr->nr_nodeid);
1958*0Sstevel@tonic-gate 					(void) memset(&req, '\0', sizeof (req));
1959*0Sstevel@tonic-gate 					METAD_SETUP_NR(MD_DB_DELETE,
1960*0Sstevel@tonic-gate 					    nr->nr_selfid);
1961*0Sstevel@tonic-gate 					if (metaioctl(MD_DB_USERREQ, &req,
1962*0Sstevel@tonic-gate 					    &req.ur_mde, NULL) != 0) {
1963*0Sstevel@tonic-gate 						(void) mdstealerror(ep,
1964*0Sstevel@tonic-gate 						    &req.ur_mde);
1965*0Sstevel@tonic-gate 						free_sr(sr);
1966*0Sstevel@tonic-gate 						return;
1967*0Sstevel@tonic-gate 					}
1968*0Sstevel@tonic-gate 					mnnr_cache_del(mnsr, nr->nr_selfid);
1969*0Sstevel@tonic-gate 					break;
1970*0Sstevel@tonic-gate 				}
1971*0Sstevel@tonic-gate 				nr = nr->nr_next;
1972*0Sstevel@tonic-gate 			}
1973*0Sstevel@tonic-gate 		} else {
1974*0Sstevel@tonic-gate 			for (j = 0; j < MD_MAXSIDES; j++) {
1975*0Sstevel@tonic-gate 				if (sr->sr_nodes[j][0] == '\0')
1976*0Sstevel@tonic-gate 					continue;
1977*0Sstevel@tonic-gate 				if (strcmp(sr->sr_nodes[j], node_v[i]) != 0)
1978*0Sstevel@tonic-gate 					continue;
1979*0Sstevel@tonic-gate 				(void) memset(sr->sr_nodes[j], '\0',
1980*0Sstevel@tonic-gate 				    sizeof (sr->sr_nodes[j]));
1981*0Sstevel@tonic-gate 				SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE,
1982*0Sstevel@tonic-gate 				    SVM_TAG_HOST, sr->sr_setno, j);
1983*0Sstevel@tonic-gate 				break;
1984*0Sstevel@tonic-gate 			}
1985*0Sstevel@tonic-gate 		}
1986*0Sstevel@tonic-gate 	}
1987*0Sstevel@tonic-gate 
1988*0Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
1989*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
1990*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
1991*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
1992*0Sstevel@tonic-gate 		req.ur_size = sizeof (*mnsr);
1993*0Sstevel@tonic-gate 	} else {
1994*0Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
1995*0Sstevel@tonic-gate 	}
1996*0Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
1997*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1998*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
1999*0Sstevel@tonic-gate 		free_sr(sr);
2000*0Sstevel@tonic-gate 		return;
2001*0Sstevel@tonic-gate 	}
2002*0Sstevel@tonic-gate 
2003*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
2004*0Sstevel@tonic-gate 	free_sr(sr);
2005*0Sstevel@tonic-gate }
2006*0Sstevel@tonic-gate 
2007*0Sstevel@tonic-gate /*
2008*0Sstevel@tonic-gate  * delete 1 or more a hosts from a set.
2009*0Sstevel@tonic-gate  */
2010*0Sstevel@tonic-gate bool_t
2011*0Sstevel@tonic-gate mdrpc_delhosts_common(
2012*0Sstevel@tonic-gate 	mdrpc_host_args		*args,
2013*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2014*0Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
2015*0Sstevel@tonic-gate 	int			version		/* RPC version */
2016*0Sstevel@tonic-gate )
2017*0Sstevel@tonic-gate {
2018*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2019*0Sstevel@tonic-gate 	int			err;
2020*0Sstevel@tonic-gate 	int			op_mode = W_OK;
2021*0Sstevel@tonic-gate 
2022*0Sstevel@tonic-gate 	/* setup, check permissions */
2023*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2024*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2025*0Sstevel@tonic-gate 		return (FALSE);
2026*0Sstevel@tonic-gate 	else if (err != 0)
2027*0Sstevel@tonic-gate 		return (TRUE);
2028*0Sstevel@tonic-gate 
2029*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
2030*0Sstevel@tonic-gate 		return (TRUE);
2031*0Sstevel@tonic-gate 
2032*0Sstevel@tonic-gate 	/* doit */
2033*0Sstevel@tonic-gate 	delhosts(args->sp->setname, args->hosts.hosts_len,
2034*0Sstevel@tonic-gate 	    args->hosts.hosts_val, version, ep);
2035*0Sstevel@tonic-gate 
2036*0Sstevel@tonic-gate 	err = svc_fini(ep);
2037*0Sstevel@tonic-gate 
2038*0Sstevel@tonic-gate 	return (TRUE);
2039*0Sstevel@tonic-gate }
2040*0Sstevel@tonic-gate 
2041*0Sstevel@tonic-gate bool_t
2042*0Sstevel@tonic-gate mdrpc_delhosts_1_svc(
2043*0Sstevel@tonic-gate 	mdrpc_host_args		*args,
2044*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2045*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2046*0Sstevel@tonic-gate )
2047*0Sstevel@tonic-gate {
2048*0Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
2049*0Sstevel@tonic-gate 	return (mdrpc_delhosts_common(args, res, rqstp, METAD_VERSION));
2050*0Sstevel@tonic-gate }
2051*0Sstevel@tonic-gate 
2052*0Sstevel@tonic-gate bool_t
2053*0Sstevel@tonic-gate mdrpc_delhosts_2_svc(
2054*0Sstevel@tonic-gate 	mdrpc_host_2_args	*args,
2055*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2056*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2057*0Sstevel@tonic-gate )
2058*0Sstevel@tonic-gate {
2059*0Sstevel@tonic-gate 	switch (args->rev) {
2060*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2061*0Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
2062*0Sstevel@tonic-gate 		return (mdrpc_delhosts_common(
2063*0Sstevel@tonic-gate 		    &args->mdrpc_host_2_args_u.rev1, res,
2064*0Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
2065*0Sstevel@tonic-gate 	    default:
2066*0Sstevel@tonic-gate 		return (FALSE);
2067*0Sstevel@tonic-gate 	}
2068*0Sstevel@tonic-gate }
2069*0Sstevel@tonic-gate 
2070*0Sstevel@tonic-gate /*
2071*0Sstevel@tonic-gate  * delete a set.
2072*0Sstevel@tonic-gate  */
2073*0Sstevel@tonic-gate bool_t
2074*0Sstevel@tonic-gate mdrpc_delset_common(
2075*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
2076*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2077*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2078*0Sstevel@tonic-gate )
2079*0Sstevel@tonic-gate {
2080*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2081*0Sstevel@tonic-gate 	int			err;
2082*0Sstevel@tonic-gate 	int			op_mode = W_OK;
2083*0Sstevel@tonic-gate 
2084*0Sstevel@tonic-gate 	/* setup, check permissions */
2085*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2086*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2087*0Sstevel@tonic-gate 		return (FALSE);
2088*0Sstevel@tonic-gate 	else if (err != 0)
2089*0Sstevel@tonic-gate 		return (TRUE);
2090*0Sstevel@tonic-gate 
2091*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
2092*0Sstevel@tonic-gate 		return (TRUE);
2093*0Sstevel@tonic-gate 
2094*0Sstevel@tonic-gate 	/* doit */
2095*0Sstevel@tonic-gate 	s_delset(args->sp->setname, ep);
2096*0Sstevel@tonic-gate 
2097*0Sstevel@tonic-gate 	err = svc_fini(ep);
2098*0Sstevel@tonic-gate 
2099*0Sstevel@tonic-gate 	return (TRUE);
2100*0Sstevel@tonic-gate }
2101*0Sstevel@tonic-gate 
2102*0Sstevel@tonic-gate bool_t
2103*0Sstevel@tonic-gate mdrpc_delset_1_svc(
2104*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
2105*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2106*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2107*0Sstevel@tonic-gate )
2108*0Sstevel@tonic-gate {
2109*0Sstevel@tonic-gate 	return (mdrpc_delset_common(args, res, rqstp));
2110*0Sstevel@tonic-gate }
2111*0Sstevel@tonic-gate 
2112*0Sstevel@tonic-gate bool_t
2113*0Sstevel@tonic-gate mdrpc_delset_2_svc(
2114*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
2115*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2116*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2117*0Sstevel@tonic-gate )
2118*0Sstevel@tonic-gate {
2119*0Sstevel@tonic-gate 	switch (args->rev) {
2120*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2121*0Sstevel@tonic-gate 		return (mdrpc_delset_common(
2122*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
2123*0Sstevel@tonic-gate 	    default:
2124*0Sstevel@tonic-gate 		return (FALSE);
2125*0Sstevel@tonic-gate 	}
2126*0Sstevel@tonic-gate }
2127*0Sstevel@tonic-gate 
2128*0Sstevel@tonic-gate /*
2129*0Sstevel@tonic-gate  * return device info
2130*0Sstevel@tonic-gate  */
2131*0Sstevel@tonic-gate static void
2132*0Sstevel@tonic-gate devinfo(
2133*0Sstevel@tonic-gate 	mdsetname_t		*sp,
2134*0Sstevel@tonic-gate 	mddrivename_t		*dp,
2135*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
2136*0Sstevel@tonic-gate 	md_error_t		*ep
2137*0Sstevel@tonic-gate )
2138*0Sstevel@tonic-gate {
2139*0Sstevel@tonic-gate 	mdname_t		*np, *real_np;
2140*0Sstevel@tonic-gate 
2141*0Sstevel@tonic-gate 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
2142*0Sstevel@tonic-gate 		return;
2143*0Sstevel@tonic-gate 
2144*0Sstevel@tonic-gate 	if ((real_np = metaname(&sp, np->bname, ep)) == NULL)
2145*0Sstevel@tonic-gate 		return;
2146*0Sstevel@tonic-gate 
2147*0Sstevel@tonic-gate 	res->dev = real_np->dev;
2148*0Sstevel@tonic-gate 	(void) getdevstamp(dp, (long *)&res->vtime, ep);
2149*0Sstevel@tonic-gate 	res->enc_devid = meta_get_devid(np->rname);
2150*0Sstevel@tonic-gate }
2151*0Sstevel@tonic-gate 
2152*0Sstevel@tonic-gate bool_t
2153*0Sstevel@tonic-gate mdrpc_devinfo_common(
2154*0Sstevel@tonic-gate 	mdrpc_devinfo_2_args_r1	*args,
2155*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
2156*0Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
2157*0Sstevel@tonic-gate )
2158*0Sstevel@tonic-gate {
2159*0Sstevel@tonic-gate 	int			slice;
2160*0Sstevel@tonic-gate 	mdname_t		*np;
2161*0Sstevel@tonic-gate 	mddrivename_t		*dnp = args->drivenamep;
2162*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2163*0Sstevel@tonic-gate 	int			err;
2164*0Sstevel@tonic-gate 	int			op_mode = R_OK;
2165*0Sstevel@tonic-gate 
2166*0Sstevel@tonic-gate 	/* setup, check permissions */
2167*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2168*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2169*0Sstevel@tonic-gate 		return (FALSE);
2170*0Sstevel@tonic-gate 	else if (err != 0)
2171*0Sstevel@tonic-gate 		return (TRUE);
2172*0Sstevel@tonic-gate 
2173*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2174*0Sstevel@tonic-gate 		return (TRUE);
2175*0Sstevel@tonic-gate 
2176*0Sstevel@tonic-gate 	/*
2177*0Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
2178*0Sstevel@tonic-gate 	 * point to the right place.
2179*0Sstevel@tonic-gate 	 */
2180*0Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2181*0Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
2182*0Sstevel@tonic-gate 			return (TRUE);
2183*0Sstevel@tonic-gate 		np->drivenamep = dnp;
2184*0Sstevel@tonic-gate 	}
2185*0Sstevel@tonic-gate 
2186*0Sstevel@tonic-gate 	/* doit */
2187*0Sstevel@tonic-gate 	devinfo(args->sp, dnp, res, ep);
2188*0Sstevel@tonic-gate 
2189*0Sstevel@tonic-gate 	err = svc_fini(ep);
2190*0Sstevel@tonic-gate 
2191*0Sstevel@tonic-gate 	return (TRUE);
2192*0Sstevel@tonic-gate }
2193*0Sstevel@tonic-gate 
2194*0Sstevel@tonic-gate /*
2195*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
2196*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
2197*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
2198*0Sstevel@tonic-gate  */
2199*0Sstevel@tonic-gate bool_t
2200*0Sstevel@tonic-gate mdrpc_devinfo_1_svc(
2201*0Sstevel@tonic-gate 	mdrpc_devinfo_args	*args,
2202*0Sstevel@tonic-gate 	mdrpc_devinfo_res 	*res,
2203*0Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
2204*0Sstevel@tonic-gate )
2205*0Sstevel@tonic-gate {
2206*0Sstevel@tonic-gate 	bool_t			retval;
2207*0Sstevel@tonic-gate 	mdrpc_devinfo_2_args_r1	v2_args;
2208*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res	v2_res;
2209*0Sstevel@tonic-gate 
2210*0Sstevel@tonic-gate 	/* allocate memory */
2211*0Sstevel@tonic-gate 	v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
2212*0Sstevel@tonic-gate 	v2_args.drivenamep->parts.parts_val =
2213*0Sstevel@tonic-gate 	    Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
2214*0Sstevel@tonic-gate 
2215*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
2216*0Sstevel@tonic-gate 	meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
2217*0Sstevel@tonic-gate 	retval = mdrpc_devinfo_common(&v2_args, &v2_res, rqstp);
2218*0Sstevel@tonic-gate 
2219*0Sstevel@tonic-gate 	/*
2220*0Sstevel@tonic-gate 	 * Fill in the result appropriately.
2221*0Sstevel@tonic-gate 	 * Since dev_t's for version 2 are 64-bit,
2222*0Sstevel@tonic-gate 	 * we need to convert them to 32-bit for version 1.
2223*0Sstevel@tonic-gate 	 */
2224*0Sstevel@tonic-gate 	res->dev = meta_cmpldev(v2_res.dev);
2225*0Sstevel@tonic-gate 	res->vtime = v2_res.vtime;
2226*0Sstevel@tonic-gate 	res->status = v2_res.status;
2227*0Sstevel@tonic-gate 
2228*0Sstevel@tonic-gate 	free(v2_args.drivenamep);
2229*0Sstevel@tonic-gate 	free(v2_args.drivenamep->parts.parts_val);
2230*0Sstevel@tonic-gate 
2231*0Sstevel@tonic-gate 	return (retval);
2232*0Sstevel@tonic-gate }
2233*0Sstevel@tonic-gate 
2234*0Sstevel@tonic-gate bool_t
2235*0Sstevel@tonic-gate mdrpc_devinfo_2_svc(
2236*0Sstevel@tonic-gate 	mdrpc_devinfo_2_args	*args,
2237*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res 	*res,
2238*0Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
2239*0Sstevel@tonic-gate )
2240*0Sstevel@tonic-gate {
2241*0Sstevel@tonic-gate 	switch (args->rev) {
2242*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2243*0Sstevel@tonic-gate 		return (mdrpc_devinfo_common(
2244*0Sstevel@tonic-gate 		    &args->mdrpc_devinfo_2_args_u.rev1, res, rqstp));
2245*0Sstevel@tonic-gate 	    default:
2246*0Sstevel@tonic-gate 		return (FALSE);
2247*0Sstevel@tonic-gate 	}
2248*0Sstevel@tonic-gate }
2249*0Sstevel@tonic-gate 
2250*0Sstevel@tonic-gate /*
2251*0Sstevel@tonic-gate  * return device id
2252*0Sstevel@tonic-gate  */
2253*0Sstevel@tonic-gate static void
2254*0Sstevel@tonic-gate mdrpc_get_devid(
2255*0Sstevel@tonic-gate 	mdsetname_t		*sp,
2256*0Sstevel@tonic-gate 	mddrivename_t		*dp,
2257*0Sstevel@tonic-gate 	mdrpc_devid_res 	*res,
2258*0Sstevel@tonic-gate 	md_error_t		*ep
2259*0Sstevel@tonic-gate )
2260*0Sstevel@tonic-gate {
2261*0Sstevel@tonic-gate 	mdname_t	*np;
2262*0Sstevel@tonic-gate 
2263*0Sstevel@tonic-gate 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
2264*0Sstevel@tonic-gate 		return;
2265*0Sstevel@tonic-gate 
2266*0Sstevel@tonic-gate 	if (metaname(&sp, np->bname, ep) == NULL)
2267*0Sstevel@tonic-gate 		return;
2268*0Sstevel@tonic-gate 
2269*0Sstevel@tonic-gate 	res->enc_devid = meta_get_devid(np->rname);
2270*0Sstevel@tonic-gate }
2271*0Sstevel@tonic-gate 
2272*0Sstevel@tonic-gate bool_t
2273*0Sstevel@tonic-gate mdrpc_devid_2_svc(
2274*0Sstevel@tonic-gate 	mdrpc_devid_2_args	*args,
2275*0Sstevel@tonic-gate 	mdrpc_devid_res 	*res,
2276*0Sstevel@tonic-gate 	struct svc_req		*rqstp			/* RPC stuff */
2277*0Sstevel@tonic-gate )
2278*0Sstevel@tonic-gate {
2279*0Sstevel@tonic-gate 	int			slice;
2280*0Sstevel@tonic-gate 	mdname_t		*np;
2281*0Sstevel@tonic-gate 	mddrivename_t		*dnp;
2282*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2283*0Sstevel@tonic-gate 	int			err;
2284*0Sstevel@tonic-gate 	int			op_mode = R_OK;
2285*0Sstevel@tonic-gate 
2286*0Sstevel@tonic-gate 	switch (args->rev) {
2287*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2288*0Sstevel@tonic-gate 		dnp = (&(args->mdrpc_devid_2_args_u.rev1))->drivenamep;
2289*0Sstevel@tonic-gate 		break;
2290*0Sstevel@tonic-gate 	    default:
2291*0Sstevel@tonic-gate 		return (FALSE);
2292*0Sstevel@tonic-gate 	}
2293*0Sstevel@tonic-gate 
2294*0Sstevel@tonic-gate 	/* setup, check permissions */
2295*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2296*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2297*0Sstevel@tonic-gate 		return (FALSE);
2298*0Sstevel@tonic-gate 	else if (err != 0)
2299*0Sstevel@tonic-gate 		return (TRUE);
2300*0Sstevel@tonic-gate 
2301*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2302*0Sstevel@tonic-gate 		return (TRUE);
2303*0Sstevel@tonic-gate 
2304*0Sstevel@tonic-gate 	/*
2305*0Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
2306*0Sstevel@tonic-gate 	 * point to the right place.
2307*0Sstevel@tonic-gate 	 */
2308*0Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2309*0Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
2310*0Sstevel@tonic-gate 			return (TRUE);
2311*0Sstevel@tonic-gate 		np->drivenamep = dnp;
2312*0Sstevel@tonic-gate 	}
2313*0Sstevel@tonic-gate 
2314*0Sstevel@tonic-gate 	/* doit */
2315*0Sstevel@tonic-gate 	mdrpc_get_devid((&(args->mdrpc_devid_2_args_u.rev1))->sp, dnp, res, ep);
2316*0Sstevel@tonic-gate 
2317*0Sstevel@tonic-gate 	err = svc_fini(ep);
2318*0Sstevel@tonic-gate 
2319*0Sstevel@tonic-gate 	return (TRUE);
2320*0Sstevel@tonic-gate }
2321*0Sstevel@tonic-gate 
2322*0Sstevel@tonic-gate /*
2323*0Sstevel@tonic-gate  * This routine should not be called for a multi-node diskset.
2324*0Sstevel@tonic-gate  *
2325*0Sstevel@tonic-gate  * The devid support is disabled for MN diskset so this routine
2326*0Sstevel@tonic-gate  * will not be called if the set is MN diskset.  The check has
2327*0Sstevel@tonic-gate  * been done early in meta_getnextside_devinfo.  However this
2328*0Sstevel@tonic-gate  * routine will be called when the devid support for MN set is
2329*0Sstevel@tonic-gate  * enabled and check is removed.
2330*0Sstevel@tonic-gate  */
2331*0Sstevel@tonic-gate bool_t
2332*0Sstevel@tonic-gate mdrpc_devinfo_by_devid_2_svc(
2333*0Sstevel@tonic-gate 	mdrpc_devidstr_args	*args,
2334*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res	*res,
2335*0Sstevel@tonic-gate 	struct svc_req	  *rqstp		  /* RPC stuff */
2336*0Sstevel@tonic-gate )
2337*0Sstevel@tonic-gate {
2338*0Sstevel@tonic-gate 
2339*0Sstevel@tonic-gate 	char		*devidstr = args->enc_devid;
2340*0Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
2341*0Sstevel@tonic-gate 	ddi_devid_t	devid;
2342*0Sstevel@tonic-gate 	char		*minor_name = NULL;
2343*0Sstevel@tonic-gate 	int		ret = 0;
2344*0Sstevel@tonic-gate 	int		err;
2345*0Sstevel@tonic-gate 	devid_nmlist_t	*disklist = NULL;
2346*0Sstevel@tonic-gate 	int		op_mode = R_OK;
2347*0Sstevel@tonic-gate 	mdname_t	*np;
2348*0Sstevel@tonic-gate 	mdsetname_t	*sp = args->sp;
2349*0Sstevel@tonic-gate 
2350*0Sstevel@tonic-gate 	/* setup, check permissions */
2351*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2352*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2353*0Sstevel@tonic-gate 		return (FALSE);
2354*0Sstevel@tonic-gate 	else if (err != 0)
2355*0Sstevel@tonic-gate 		return (TRUE);
2356*0Sstevel@tonic-gate 
2357*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2358*0Sstevel@tonic-gate 		return (TRUE);
2359*0Sstevel@tonic-gate 
2360*0Sstevel@tonic-gate 	if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
2361*0Sstevel@tonic-gate 		return (TRUE);
2362*0Sstevel@tonic-gate 
2363*0Sstevel@tonic-gate 	/*
2364*0Sstevel@tonic-gate 	 * if we do not have a minor name then look for a character device.
2365*0Sstevel@tonic-gate 	 * This is because the caller (checkdrive_onnode) expects a character
2366*0Sstevel@tonic-gate 	 * device to be returned. The other client of this interface is
2367*0Sstevel@tonic-gate 	 * meta_getnextside_devinfo and this supplies a minor name.
2368*0Sstevel@tonic-gate 	 */
2369*0Sstevel@tonic-gate 	if (minor_name == NULL) {
2370*0Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid,
2371*0Sstevel@tonic-gate 		    DEVID_MINOR_NAME_ALL_CHR, &disklist);
2372*0Sstevel@tonic-gate 	} else {
2373*0Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
2374*0Sstevel@tonic-gate 		    &disklist);
2375*0Sstevel@tonic-gate 		devid_str_free(minor_name);
2376*0Sstevel@tonic-gate 	}
2377*0Sstevel@tonic-gate 
2378*0Sstevel@tonic-gate 	devid_free(devid);
2379*0Sstevel@tonic-gate 	if (ret != 0) {
2380*0Sstevel@tonic-gate 		res->dev = NODEV64;
2381*0Sstevel@tonic-gate 		devid_free_nmlist(disklist);
2382*0Sstevel@tonic-gate 		return (TRUE);
2383*0Sstevel@tonic-gate 	}
2384*0Sstevel@tonic-gate 
2385*0Sstevel@tonic-gate 	np = metaname(&sp, disklist[0].devname, ep);
2386*0Sstevel@tonic-gate 	if (np != NULL) {
2387*0Sstevel@tonic-gate 		mdcinfo_t	*cinfo;
2388*0Sstevel@tonic-gate 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
2389*0Sstevel@tonic-gate 			res->drivername = Strdup(cinfo->dname);
2390*0Sstevel@tonic-gate 		}
2391*0Sstevel@tonic-gate 	}
2392*0Sstevel@tonic-gate 
2393*0Sstevel@tonic-gate 	res->dev = meta_expldev(disklist[0].dev);
2394*0Sstevel@tonic-gate 	res->devname = strdup(disklist[0].devname);
2395*0Sstevel@tonic-gate 
2396*0Sstevel@tonic-gate 	devid_free_nmlist(disklist);
2397*0Sstevel@tonic-gate 
2398*0Sstevel@tonic-gate 	err = svc_fini(ep);
2399*0Sstevel@tonic-gate 
2400*0Sstevel@tonic-gate 	return (TRUE);
2401*0Sstevel@tonic-gate }
2402*0Sstevel@tonic-gate 
2403*0Sstevel@tonic-gate /*
2404*0Sstevel@tonic-gate  * This routine should not be called for a multi-node diskset.
2405*0Sstevel@tonic-gate  *
2406*0Sstevel@tonic-gate  * The devid support is disabled for MN diskset so this routine
2407*0Sstevel@tonic-gate  * will not be called if the set is MN diskset.  The check has
2408*0Sstevel@tonic-gate  * been done early in meta_getnextside_devinfo.  However this
2409*0Sstevel@tonic-gate  * routine will be called when the devid support for MN set is
2410*0Sstevel@tonic-gate  * enabled and check is removed.
2411*0Sstevel@tonic-gate  *
2412*0Sstevel@tonic-gate  * This function will return the device info attempting to use
2413*0Sstevel@tonic-gate  * both the passed in devid and device name.  This is to deal
2414*0Sstevel@tonic-gate  * with systems that use multi-path disks but not running mpxio.
2415*0Sstevel@tonic-gate  * In this situation meta_deviceid_to_nmlist will return multiple
2416*0Sstevel@tonic-gate  * devices.  The orig_devname is used to disambiguate.
2417*0Sstevel@tonic-gate  *
2418*0Sstevel@tonic-gate  */
2419*0Sstevel@tonic-gate bool_t
2420*0Sstevel@tonic-gate mdrpc_devinfo_by_devid_name_2_svc(
2421*0Sstevel@tonic-gate 	mdrpc_devid_name_2_args	*args,
2422*0Sstevel@tonic-gate 	mdrpc_devinfo_2_res	*res,
2423*0Sstevel@tonic-gate 	struct svc_req	  *rqstp		  /* RPC stuff */
2424*0Sstevel@tonic-gate )
2425*0Sstevel@tonic-gate {
2426*0Sstevel@tonic-gate 
2427*0Sstevel@tonic-gate 	char		*devidstr;
2428*0Sstevel@tonic-gate 	char		*orig_devname;
2429*0Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
2430*0Sstevel@tonic-gate 	ddi_devid_t	devid;
2431*0Sstevel@tonic-gate 	char		*minor_name = NULL;
2432*0Sstevel@tonic-gate 	int		ret = 0;
2433*0Sstevel@tonic-gate 	int		err;
2434*0Sstevel@tonic-gate 	int		i;
2435*0Sstevel@tonic-gate 	devid_nmlist_t	*disklist = NULL;
2436*0Sstevel@tonic-gate 	int		op_mode = R_OK;
2437*0Sstevel@tonic-gate 	mdname_t	*np;
2438*0Sstevel@tonic-gate 	mdsetname_t	*sp;
2439*0Sstevel@tonic-gate 
2440*0Sstevel@tonic-gate 	switch (args->rev) {
2441*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2442*0Sstevel@tonic-gate 		sp = (&(args->mdrpc_devid_name_2_args_u.rev1))->sp;
2443*0Sstevel@tonic-gate 		devidstr = (&(args->mdrpc_devid_name_2_args_u.rev1))->enc_devid;
2444*0Sstevel@tonic-gate 		orig_devname =
2445*0Sstevel@tonic-gate 			(&(args->mdrpc_devid_name_2_args_u.rev1))->orig_devname;
2446*0Sstevel@tonic-gate 		break;
2447*0Sstevel@tonic-gate 	    default:
2448*0Sstevel@tonic-gate 		return (FALSE);
2449*0Sstevel@tonic-gate 	}
2450*0Sstevel@tonic-gate 
2451*0Sstevel@tonic-gate 	/* setup, check permissions */
2452*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2453*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2454*0Sstevel@tonic-gate 		return (FALSE);
2455*0Sstevel@tonic-gate 	else if (err != 0)
2456*0Sstevel@tonic-gate 		return (TRUE);
2457*0Sstevel@tonic-gate 
2458*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2459*0Sstevel@tonic-gate 		return (TRUE);
2460*0Sstevel@tonic-gate 
2461*0Sstevel@tonic-gate 	if (devid_str_decode(devidstr, &devid, &minor_name) != 0)
2462*0Sstevel@tonic-gate 		return (TRUE);
2463*0Sstevel@tonic-gate 
2464*0Sstevel@tonic-gate 	/*
2465*0Sstevel@tonic-gate 	 * if we do not have a minor name then look for a character device.
2466*0Sstevel@tonic-gate 	 * This is because the caller (checkdrive_onnode) expects a character
2467*0Sstevel@tonic-gate 	 * device to be returned. The other client of this interface is
2468*0Sstevel@tonic-gate 	 * meta_getnextside_devinfo and this supplies a minor name.
2469*0Sstevel@tonic-gate 	 */
2470*0Sstevel@tonic-gate 	if (minor_name == NULL) {
2471*0Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid,
2472*0Sstevel@tonic-gate 		    DEVID_MINOR_NAME_ALL_CHR, &disklist);
2473*0Sstevel@tonic-gate 	} else {
2474*0Sstevel@tonic-gate 		ret = meta_deviceid_to_nmlist("/dev", devid, minor_name,
2475*0Sstevel@tonic-gate 		    &disklist);
2476*0Sstevel@tonic-gate 		devid_str_free(minor_name);
2477*0Sstevel@tonic-gate 	}
2478*0Sstevel@tonic-gate 
2479*0Sstevel@tonic-gate 	devid_free(devid);
2480*0Sstevel@tonic-gate 	if (ret != 0) {
2481*0Sstevel@tonic-gate 		res->dev = NODEV64;
2482*0Sstevel@tonic-gate 		devid_free_nmlist(disklist);
2483*0Sstevel@tonic-gate 		return (TRUE);
2484*0Sstevel@tonic-gate 	}
2485*0Sstevel@tonic-gate 
2486*0Sstevel@tonic-gate 	/* attempt to match to the device name on the originating node */
2487*0Sstevel@tonic-gate 	for (i = 0; disklist[i].dev != NODEV; i++) {
2488*0Sstevel@tonic-gate 		if (strncmp(orig_devname, disklist[i].devname,
2489*0Sstevel@tonic-gate 					strlen(disklist[i].devname)) == 0)
2490*0Sstevel@tonic-gate 			break;
2491*0Sstevel@tonic-gate 	}
2492*0Sstevel@tonic-gate 
2493*0Sstevel@tonic-gate 	/* if it's not found then use the first disk in the list */
2494*0Sstevel@tonic-gate 	if (disklist[i].dev == NODEV)
2495*0Sstevel@tonic-gate 		i = 0;
2496*0Sstevel@tonic-gate 
2497*0Sstevel@tonic-gate 	np = metaname(&sp, disklist[i].devname, ep);
2498*0Sstevel@tonic-gate 	if (np != NULL) {
2499*0Sstevel@tonic-gate 		mdcinfo_t	*cinfo;
2500*0Sstevel@tonic-gate 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
2501*0Sstevel@tonic-gate 			res->drivername = Strdup(cinfo->dname);
2502*0Sstevel@tonic-gate 		}
2503*0Sstevel@tonic-gate 	}
2504*0Sstevel@tonic-gate 
2505*0Sstevel@tonic-gate 	res->dev = meta_expldev(disklist[i].dev);
2506*0Sstevel@tonic-gate 	res->devname = strdup(disklist[i].devname);
2507*0Sstevel@tonic-gate 
2508*0Sstevel@tonic-gate 	devid_free_nmlist(disklist);
2509*0Sstevel@tonic-gate 
2510*0Sstevel@tonic-gate 	err = svc_fini(ep);
2511*0Sstevel@tonic-gate 
2512*0Sstevel@tonic-gate 	return (TRUE);
2513*0Sstevel@tonic-gate }
2514*0Sstevel@tonic-gate 
2515*0Sstevel@tonic-gate static void
2516*0Sstevel@tonic-gate drvused(mdsetname_t *sp, mddrivename_t *dnp, md_error_t *ep)
2517*0Sstevel@tonic-gate {
2518*0Sstevel@tonic-gate 	if (meta_check_drivemounted(sp, dnp, ep))
2519*0Sstevel@tonic-gate 		return;
2520*0Sstevel@tonic-gate 
2521*0Sstevel@tonic-gate 	if (meta_check_driveswapped(sp, dnp, ep))
2522*0Sstevel@tonic-gate 		return;
2523*0Sstevel@tonic-gate 
2524*0Sstevel@tonic-gate 	if (meta_check_drive_inuse(metasetname(MD_LOCAL_NAME, ep), dnp,
2525*0Sstevel@tonic-gate 	    TRUE, ep))
2526*0Sstevel@tonic-gate 		return;
2527*0Sstevel@tonic-gate 
2528*0Sstevel@tonic-gate 	(void) meta_check_driveinset(sp, dnp, ep);
2529*0Sstevel@tonic-gate }
2530*0Sstevel@tonic-gate 
2531*0Sstevel@tonic-gate /*
2532*0Sstevel@tonic-gate  * determine if a device is in use.
2533*0Sstevel@tonic-gate  */
2534*0Sstevel@tonic-gate bool_t
2535*0Sstevel@tonic-gate mdrpc_drvused_common(
2536*0Sstevel@tonic-gate 	mdrpc_drvused_2_args_r1	*args,
2537*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2538*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2539*0Sstevel@tonic-gate )
2540*0Sstevel@tonic-gate {
2541*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2542*0Sstevel@tonic-gate 	int			slice;
2543*0Sstevel@tonic-gate 	mdname_t		*np;
2544*0Sstevel@tonic-gate 	mddrivename_t		*dnp = args->drivenamep;
2545*0Sstevel@tonic-gate 	int			err;
2546*0Sstevel@tonic-gate 	int			op_mode = R_OK;
2547*0Sstevel@tonic-gate 
2548*0Sstevel@tonic-gate 	/* setup, check permissions */
2549*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2550*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2551*0Sstevel@tonic-gate 		return (FALSE);
2552*0Sstevel@tonic-gate 	else if (err != 0)
2553*0Sstevel@tonic-gate 		return (TRUE);
2554*0Sstevel@tonic-gate 
2555*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2556*0Sstevel@tonic-gate 		return (TRUE);
2557*0Sstevel@tonic-gate 
2558*0Sstevel@tonic-gate 	if (dnp == NULL) {
2559*0Sstevel@tonic-gate 		/* no drive pointer specified */
2560*0Sstevel@tonic-gate 		return (TRUE);
2561*0Sstevel@tonic-gate 	}
2562*0Sstevel@tonic-gate 	/*
2563*0Sstevel@tonic-gate 	 * fix all the drivenamep's in the mdname_t's to
2564*0Sstevel@tonic-gate 	 * point to the right place.
2565*0Sstevel@tonic-gate 	 */
2566*0Sstevel@tonic-gate 	for (slice = 0; (slice < dnp->parts.parts_len); ++slice) {
2567*0Sstevel@tonic-gate 		if ((np = metaslicename(dnp, slice, ep)) == NULL)
2568*0Sstevel@tonic-gate 			return (TRUE);
2569*0Sstevel@tonic-gate 		np->drivenamep = dnp;
2570*0Sstevel@tonic-gate 	}
2571*0Sstevel@tonic-gate 
2572*0Sstevel@tonic-gate 	/* doit */
2573*0Sstevel@tonic-gate 	drvused(args->sp, dnp, ep);
2574*0Sstevel@tonic-gate 
2575*0Sstevel@tonic-gate 	err = svc_fini(ep);
2576*0Sstevel@tonic-gate 
2577*0Sstevel@tonic-gate 	return (TRUE);
2578*0Sstevel@tonic-gate }
2579*0Sstevel@tonic-gate 
2580*0Sstevel@tonic-gate /*
2581*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
2582*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
2583*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
2584*0Sstevel@tonic-gate  */
2585*0Sstevel@tonic-gate bool_t
2586*0Sstevel@tonic-gate mdrpc_drvused_1_svc(
2587*0Sstevel@tonic-gate 	mdrpc_drvused_args	*args,
2588*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2589*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2590*0Sstevel@tonic-gate )
2591*0Sstevel@tonic-gate {
2592*0Sstevel@tonic-gate 	bool_t			retval;
2593*0Sstevel@tonic-gate 	mdrpc_drvused_2_args_r1	v2_args;
2594*0Sstevel@tonic-gate 
2595*0Sstevel@tonic-gate 	/* allocate memory */
2596*0Sstevel@tonic-gate 	v2_args.drivenamep = Zalloc(sizeof (mddrivename_t));
2597*0Sstevel@tonic-gate 	v2_args.drivenamep->parts.parts_val =
2598*0Sstevel@tonic-gate 	    Zalloc(sizeof (mdname_t) * args->drivenamep->parts.parts_len);
2599*0Sstevel@tonic-gate 
2600*0Sstevel@tonic-gate 	/* build args */
2601*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
2602*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
2603*0Sstevel@tonic-gate 
2604*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
2605*0Sstevel@tonic-gate 	meta_conv_drvname_old2new(args->drivenamep, v2_args.drivenamep);
2606*0Sstevel@tonic-gate 	retval = mdrpc_drvused_common(&v2_args, res, rqstp);
2607*0Sstevel@tonic-gate 
2608*0Sstevel@tonic-gate 	free(v2_args.drivenamep);
2609*0Sstevel@tonic-gate 	free(v2_args.drivenamep->parts.parts_val);
2610*0Sstevel@tonic-gate 
2611*0Sstevel@tonic-gate 	return (retval);
2612*0Sstevel@tonic-gate }
2613*0Sstevel@tonic-gate 
2614*0Sstevel@tonic-gate bool_t
2615*0Sstevel@tonic-gate mdrpc_drvused_2_svc(
2616*0Sstevel@tonic-gate 	mdrpc_drvused_2_args	*args,
2617*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2618*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2619*0Sstevel@tonic-gate )
2620*0Sstevel@tonic-gate {
2621*0Sstevel@tonic-gate 	switch (args->rev) {
2622*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2623*0Sstevel@tonic-gate 		return (mdrpc_drvused_common(
2624*0Sstevel@tonic-gate 		    &args->mdrpc_drvused_2_args_u.rev1, res, rqstp));
2625*0Sstevel@tonic-gate 	    default:
2626*0Sstevel@tonic-gate 		return (FALSE);
2627*0Sstevel@tonic-gate 	}
2628*0Sstevel@tonic-gate }
2629*0Sstevel@tonic-gate 
2630*0Sstevel@tonic-gate /*
2631*0Sstevel@tonic-gate  * return a set records selected by name or number.
2632*0Sstevel@tonic-gate  */
2633*0Sstevel@tonic-gate bool_t
2634*0Sstevel@tonic-gate mdrpc_getset_common(
2635*0Sstevel@tonic-gate 	mdrpc_getset_args	*args,
2636*0Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
2637*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2638*0Sstevel@tonic-gate )
2639*0Sstevel@tonic-gate {
2640*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2641*0Sstevel@tonic-gate 	int			err;
2642*0Sstevel@tonic-gate 	int			op_mode = R_OK;
2643*0Sstevel@tonic-gate 
2644*0Sstevel@tonic-gate 	/* setup, check permissions */
2645*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2646*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2647*0Sstevel@tonic-gate 		return (FALSE);
2648*0Sstevel@tonic-gate 	else if (err != 0)
2649*0Sstevel@tonic-gate 		return (TRUE);
2650*0Sstevel@tonic-gate 
2651*0Sstevel@tonic-gate 	/* Don't have a setno, so we don't check the lock */
2652*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2653*0Sstevel@tonic-gate 		return (TRUE);
2654*0Sstevel@tonic-gate 
2655*0Sstevel@tonic-gate 	/* doit */
2656*0Sstevel@tonic-gate 	if (args->setname && *args->setname)
2657*0Sstevel@tonic-gate 		res->sr = setdup(getsetbyname(args->setname, ep));
2658*0Sstevel@tonic-gate 	else if (args->setno > 0)
2659*0Sstevel@tonic-gate 		res->sr = setdup(getsetbynum(args->setno, ep));
2660*0Sstevel@tonic-gate 	else
2661*0Sstevel@tonic-gate 		res->sr = NULL;
2662*0Sstevel@tonic-gate 
2663*0Sstevel@tonic-gate 	err = svc_fini(ep);
2664*0Sstevel@tonic-gate 
2665*0Sstevel@tonic-gate 	return (TRUE);
2666*0Sstevel@tonic-gate }
2667*0Sstevel@tonic-gate 
2668*0Sstevel@tonic-gate bool_t
2669*0Sstevel@tonic-gate mdrpc_getset_1_svc(
2670*0Sstevel@tonic-gate 	mdrpc_getset_args	*args,
2671*0Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
2672*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2673*0Sstevel@tonic-gate )
2674*0Sstevel@tonic-gate {
2675*0Sstevel@tonic-gate 	return (mdrpc_getset_common(args, res, rqstp));
2676*0Sstevel@tonic-gate }
2677*0Sstevel@tonic-gate 
2678*0Sstevel@tonic-gate bool_t
2679*0Sstevel@tonic-gate mdrpc_getset_2_svc(
2680*0Sstevel@tonic-gate 	mdrpc_getset_2_args	*args,
2681*0Sstevel@tonic-gate 	mdrpc_getset_res 	*res,
2682*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2683*0Sstevel@tonic-gate )
2684*0Sstevel@tonic-gate {
2685*0Sstevel@tonic-gate 	switch (args->rev) {
2686*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2687*0Sstevel@tonic-gate 		return (mdrpc_getset_common(
2688*0Sstevel@tonic-gate 		    &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
2689*0Sstevel@tonic-gate 	    default:
2690*0Sstevel@tonic-gate 		return (FALSE);
2691*0Sstevel@tonic-gate 	}
2692*0Sstevel@tonic-gate }
2693*0Sstevel@tonic-gate 
2694*0Sstevel@tonic-gate /*
2695*0Sstevel@tonic-gate  * return a MN set record selected by name or number.
2696*0Sstevel@tonic-gate  */
2697*0Sstevel@tonic-gate bool_t
2698*0Sstevel@tonic-gate mdrpc_mngetset_common(
2699*0Sstevel@tonic-gate 	mdrpc_getset_args	*args,
2700*0Sstevel@tonic-gate 	mdrpc_mngetset_res 	*res,
2701*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2702*0Sstevel@tonic-gate )
2703*0Sstevel@tonic-gate {
2704*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2705*0Sstevel@tonic-gate 	int			err;
2706*0Sstevel@tonic-gate 	int			op_mode = R_OK;
2707*0Sstevel@tonic-gate 	md_set_record		*sr = NULL;
2708*0Sstevel@tonic-gate 	md_mnset_record		*mnsr = NULL;
2709*0Sstevel@tonic-gate 
2710*0Sstevel@tonic-gate 	/* setup, check permissions */
2711*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2712*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2713*0Sstevel@tonic-gate 		return (FALSE);
2714*0Sstevel@tonic-gate 	else if (err != 0)
2715*0Sstevel@tonic-gate 		return (TRUE);
2716*0Sstevel@tonic-gate 
2717*0Sstevel@tonic-gate 	/* Don't have a setno, so we don't check the lock */
2718*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
2719*0Sstevel@tonic-gate 		return (TRUE);
2720*0Sstevel@tonic-gate 
2721*0Sstevel@tonic-gate 	/* doit */
2722*0Sstevel@tonic-gate 	res->mnsr = NULL;
2723*0Sstevel@tonic-gate 	if (args->setname && *args->setname)
2724*0Sstevel@tonic-gate 		sr = getsetbyname(args->setname, ep);
2725*0Sstevel@tonic-gate 	else if (args->setno > 0)
2726*0Sstevel@tonic-gate 		sr = getsetbynum(args->setno, ep);
2727*0Sstevel@tonic-gate 
2728*0Sstevel@tonic-gate 	if ((sr) && (MD_MNSET_REC(sr))) {
2729*0Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
2730*0Sstevel@tonic-gate 		res->mnsr = mnsetdup(mnsr);
2731*0Sstevel@tonic-gate 	}
2732*0Sstevel@tonic-gate 
2733*0Sstevel@tonic-gate 	err = svc_fini(ep);
2734*0Sstevel@tonic-gate 
2735*0Sstevel@tonic-gate 	return (TRUE);
2736*0Sstevel@tonic-gate }
2737*0Sstevel@tonic-gate 
2738*0Sstevel@tonic-gate bool_t
2739*0Sstevel@tonic-gate mdrpc_mngetset_2_svc(
2740*0Sstevel@tonic-gate 	mdrpc_getset_2_args	*args,
2741*0Sstevel@tonic-gate 	mdrpc_mngetset_res	*res,
2742*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2743*0Sstevel@tonic-gate )
2744*0Sstevel@tonic-gate {
2745*0Sstevel@tonic-gate 	switch (args->rev) {
2746*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2747*0Sstevel@tonic-gate 		return (mdrpc_mngetset_common(
2748*0Sstevel@tonic-gate 		    &args->mdrpc_getset_2_args_u.rev1, res, rqstp));
2749*0Sstevel@tonic-gate 	    default:
2750*0Sstevel@tonic-gate 		return (FALSE);
2751*0Sstevel@tonic-gate 	}
2752*0Sstevel@tonic-gate }
2753*0Sstevel@tonic-gate 
2754*0Sstevel@tonic-gate static void
2755*0Sstevel@tonic-gate upd_setmaster(
2756*0Sstevel@tonic-gate 	mdsetname_t	*sp,
2757*0Sstevel@tonic-gate 	md_node_nm_t	master_nodenm,
2758*0Sstevel@tonic-gate 	int		master_nodeid,
2759*0Sstevel@tonic-gate 	md_error_t	*ep
2760*0Sstevel@tonic-gate )
2761*0Sstevel@tonic-gate {
2762*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
2763*0Sstevel@tonic-gate 	md_set_record	*sr;
2764*0Sstevel@tonic-gate 	md_mnset_record	*mnsr;
2765*0Sstevel@tonic-gate 	mddb_setmaster_config_t	sm;
2766*0Sstevel@tonic-gate 
2767*0Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
2768*0Sstevel@tonic-gate 		return;
2769*0Sstevel@tonic-gate 
2770*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
2771*0Sstevel@tonic-gate 
2772*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
2773*0Sstevel@tonic-gate 		return;
2774*0Sstevel@tonic-gate 
2775*0Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
2776*0Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
2777*0Sstevel@tonic-gate 		strlcpy(mnsr->sr_master_nodenm, master_nodenm,
2778*0Sstevel@tonic-gate 			MD_MAX_NODENAME);
2779*0Sstevel@tonic-gate 		mnsr->sr_master_nodeid = master_nodeid;
2780*0Sstevel@tonic-gate 		if (master_nodeid != 0) {
2781*0Sstevel@tonic-gate 			(void) memset(&sm, 0, sizeof (sm));
2782*0Sstevel@tonic-gate 			sm.c_setno = sp->setno;
2783*0Sstevel@tonic-gate 			/* Use magic to help protect ioctl against attack. */
2784*0Sstevel@tonic-gate 			sm.c_magic = MDDB_SETMASTER_MAGIC;
2785*0Sstevel@tonic-gate 			if (strcmp(master_nodenm, mynode()) == 0) {
2786*0Sstevel@tonic-gate 				sm.c_current_host_master = 1;
2787*0Sstevel@tonic-gate 			} else {
2788*0Sstevel@tonic-gate 				sm.c_current_host_master = 0;
2789*0Sstevel@tonic-gate 			}
2790*0Sstevel@tonic-gate 			(void) metaioctl(MD_SETMASTER, &sm, &sm.c_mde, NULL);
2791*0Sstevel@tonic-gate 			mdclrerror(&sm.c_mde);
2792*0Sstevel@tonic-gate 		}
2793*0Sstevel@tonic-gate 	}
2794*0Sstevel@tonic-gate 
2795*0Sstevel@tonic-gate out:
2796*0Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
2797*0Sstevel@tonic-gate 	free_sr(sr);
2798*0Sstevel@tonic-gate }
2799*0Sstevel@tonic-gate 
2800*0Sstevel@tonic-gate /*
2801*0Sstevel@tonic-gate  * set the master and nodeid in node record
2802*0Sstevel@tonic-gate  */
2803*0Sstevel@tonic-gate bool_t
2804*0Sstevel@tonic-gate mdrpc_mnsetmaster_common(
2805*0Sstevel@tonic-gate 	mdrpc_mnsetmaster_args	*args,
2806*0Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
2807*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2808*0Sstevel@tonic-gate )
2809*0Sstevel@tonic-gate {
2810*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2811*0Sstevel@tonic-gate 	int			err;
2812*0Sstevel@tonic-gate 	int			op_mode = W_OK;
2813*0Sstevel@tonic-gate 
2814*0Sstevel@tonic-gate 	/* setup, check permissions */
2815*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2816*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2817*0Sstevel@tonic-gate 		return (FALSE);
2818*0Sstevel@tonic-gate 	else if (err != 0)
2819*0Sstevel@tonic-gate 		return (TRUE);
2820*0Sstevel@tonic-gate 
2821*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
2822*0Sstevel@tonic-gate 		return (TRUE);
2823*0Sstevel@tonic-gate 
2824*0Sstevel@tonic-gate 	/* doit */
2825*0Sstevel@tonic-gate 	upd_setmaster(args->sp, args->master_nodenm, args->master_nodeid, ep);
2826*0Sstevel@tonic-gate 
2827*0Sstevel@tonic-gate 	err = svc_fini(ep);
2828*0Sstevel@tonic-gate 
2829*0Sstevel@tonic-gate 	return (TRUE);
2830*0Sstevel@tonic-gate }
2831*0Sstevel@tonic-gate 
2832*0Sstevel@tonic-gate bool_t
2833*0Sstevel@tonic-gate mdrpc_mnsetmaster_2_svc(
2834*0Sstevel@tonic-gate 	mdrpc_mnsetmaster_2_args	*args,
2835*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
2836*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2837*0Sstevel@tonic-gate )
2838*0Sstevel@tonic-gate {
2839*0Sstevel@tonic-gate 	switch (args->rev) {
2840*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
2841*0Sstevel@tonic-gate 		return (mdrpc_mnsetmaster_common(
2842*0Sstevel@tonic-gate 		    &args->mdrpc_mnsetmaster_2_args_u.rev1, res, rqstp));
2843*0Sstevel@tonic-gate 	    default:
2844*0Sstevel@tonic-gate 		return (FALSE);
2845*0Sstevel@tonic-gate 	}
2846*0Sstevel@tonic-gate }
2847*0Sstevel@tonic-gate 
2848*0Sstevel@tonic-gate /*
2849*0Sstevel@tonic-gate  * Join this node to the diskset.
2850*0Sstevel@tonic-gate  * Pass stale_flag information to snarf_set so that snarf code
2851*0Sstevel@tonic-gate  * can choose a STALE or non-STALE state when starting the set.
2852*0Sstevel@tonic-gate  * If master is STALE, any joining node will join a stale set regardless
2853*0Sstevel@tonic-gate  * of the number of accessible mddbs.  Also, if master is at 50%
2854*0Sstevel@tonic-gate  * accessible replicas and is in the TOOFEW state, don't mark newly
2855*0Sstevel@tonic-gate  * joining node as STALE; mark it TOOFEW instead.
2856*0Sstevel@tonic-gate  */
2857*0Sstevel@tonic-gate static void
2858*0Sstevel@tonic-gate joinset(
2859*0Sstevel@tonic-gate 	mdsetname_t	*sp,
2860*0Sstevel@tonic-gate 	int		flags,
2861*0Sstevel@tonic-gate 	md_error_t	*ep
2862*0Sstevel@tonic-gate )
2863*0Sstevel@tonic-gate {
2864*0Sstevel@tonic-gate 	mdsetname_t		*local_sp;
2865*0Sstevel@tonic-gate 	md_drive_desc		*mydd;
2866*0Sstevel@tonic-gate 	bool_t			stale_bool;
2867*0Sstevel@tonic-gate 	mddb_block_parm_t	mbp;
2868*0Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
2869*0Sstevel@tonic-gate 
2870*0Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
2871*0Sstevel@tonic-gate 		return;
2872*0Sstevel@tonic-gate 
2873*0Sstevel@tonic-gate 	/*
2874*0Sstevel@tonic-gate 	 * Start mddoors daemon here.
2875*0Sstevel@tonic-gate 	 * mddoors itself takes care there will be
2876*0Sstevel@tonic-gate 	 * only one instance running, so starting it twice won't hurt
2877*0Sstevel@tonic-gate 	 */
2878*0Sstevel@tonic-gate 	pclose(popen(MDDOORS, "w"));
2879*0Sstevel@tonic-gate 
2880*0Sstevel@tonic-gate 	/*
2881*0Sstevel@tonic-gate 	 * Get latest copy of data.  If a drive was just added causing
2882*0Sstevel@tonic-gate 	 * nodes to get joined - this drive won't be in the local
2883*0Sstevel@tonic-gate 	 * name caches drive list yet.
2884*0Sstevel@tonic-gate 	 */
2885*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
2886*0Sstevel@tonic-gate 
2887*0Sstevel@tonic-gate 	mydd = metaget_drivedesc(local_sp, (MD_BASICNAME_OK | PRINT_FAST), ep);
2888*0Sstevel@tonic-gate 	if (mydd) {
2889*0Sstevel@tonic-gate 		/* Causes mddbs to be loaded in kernel */
2890*0Sstevel@tonic-gate 		if (setup_db_bydd(local_sp, mydd, 0, ep) == -1) {
2891*0Sstevel@tonic-gate 			/* If ep isn't set for some reason, set it */
2892*0Sstevel@tonic-gate 			if (! mdisok(ep)) {
2893*0Sstevel@tonic-gate 				(void) mdmddberror(ep, MDE_DB_NOTNOW, NODEV64,
2894*0Sstevel@tonic-gate 					sp->setno, 0, NULL);
2895*0Sstevel@tonic-gate 			}
2896*0Sstevel@tonic-gate 			return;
2897*0Sstevel@tonic-gate 		}
2898*0Sstevel@tonic-gate 
2899*0Sstevel@tonic-gate 		if (flags & MNSET_IS_STALE)
2900*0Sstevel@tonic-gate 			stale_bool = TRUE;
2901*0Sstevel@tonic-gate 		else
2902*0Sstevel@tonic-gate 			stale_bool = FALSE;
2903*0Sstevel@tonic-gate 
2904*0Sstevel@tonic-gate 		/*
2905*0Sstevel@tonic-gate 		 * Snarf the set.  No failure has occurred if STALE or
2906*0Sstevel@tonic-gate 		 * ACCOK error was set.  Otherwise, fail the call setting
2907*0Sstevel@tonic-gate 		 * a generic error if no error was already set.
2908*0Sstevel@tonic-gate 		 *
2909*0Sstevel@tonic-gate 		 * STALE means that set has < 50% mddbs.
2910*0Sstevel@tonic-gate 		 * ACCOK means that the mediator provided an extra vote.
2911*0Sstevel@tonic-gate 		 */
2912*0Sstevel@tonic-gate 		if (snarf_set(local_sp, stale_bool, ep) != 0) {
2913*0Sstevel@tonic-gate 			if (!(mdismddberror(ep, MDE_DB_STALE)) &&
2914*0Sstevel@tonic-gate 			    !(mdismddberror(ep, MDE_DB_ACCOK))) {
2915*0Sstevel@tonic-gate 				return;
2916*0Sstevel@tonic-gate 			} else if (mdisok(ep)) {
2917*0Sstevel@tonic-gate 				/* If snarf failed, but no error set - set it */
2918*0Sstevel@tonic-gate 				(void) mdmddberror(ep, MDE_DB_NOTNOW, NODEV64,
2919*0Sstevel@tonic-gate 					sp->setno, 0, NULL);
2920*0Sstevel@tonic-gate 				return;
2921*0Sstevel@tonic-gate 			}
2922*0Sstevel@tonic-gate 		}
2923*0Sstevel@tonic-gate 
2924*0Sstevel@tonic-gate 		/*
2925*0Sstevel@tonic-gate 		 * If node is joining during reconfig cycle, then
2926*0Sstevel@tonic-gate 		 * set mddb_parse to be in blocked state so that
2927*0Sstevel@tonic-gate 		 * mddb reparse messages are not generated until
2928*0Sstevel@tonic-gate 		 * the commd has been resumed later in the reconfig
2929*0Sstevel@tonic-gate 		 * cycle.
2930*0Sstevel@tonic-gate 		 */
2931*0Sstevel@tonic-gate 		if (flags & MNSET_IN_RECONFIG) {
2932*0Sstevel@tonic-gate 			(void) memset(&mbp, 0, sizeof (mbp));
2933*0Sstevel@tonic-gate 			if (s_ownset(sp->setno, &xep) == MD_SETOWNER_YES) {
2934*0Sstevel@tonic-gate 				(void) memset(&mbp, 0, sizeof (mbp));
2935*0Sstevel@tonic-gate 				mbp.c_setno = local_sp->setno;
2936*0Sstevel@tonic-gate 				mbp.c_blk_flags = MDDB_BLOCK_PARSE;
2937*0Sstevel@tonic-gate 				if (metaioctl(MD_MN_MDDB_BLOCK, &mbp,
2938*0Sstevel@tonic-gate 				    &mbp.c_mde, NULL)) {
2939*0Sstevel@tonic-gate 					mdstealerror(&xep, &mbp.c_mde);
2940*0Sstevel@tonic-gate 					mde_perror(ep, gettext(
2941*0Sstevel@tonic-gate 					    "Could not block set %s"),
2942*0Sstevel@tonic-gate 					    sp->setname);
2943*0Sstevel@tonic-gate 					return;
2944*0Sstevel@tonic-gate 				}
2945*0Sstevel@tonic-gate 			}
2946*0Sstevel@tonic-gate 			/*
2947*0Sstevel@tonic-gate 			 * If s_ownset fails and snarf_set succeeded,
2948*0Sstevel@tonic-gate 			 * then can steal the ownset failure information
2949*0Sstevel@tonic-gate 			 * and store it into ep. If snarf_set failed,
2950*0Sstevel@tonic-gate 			 * don't overwrite critical ep information even
2951*0Sstevel@tonic-gate 			 * if s_ownset failed.
2952*0Sstevel@tonic-gate 			 */
2953*0Sstevel@tonic-gate 			if (!mdisok(&xep)) {
2954*0Sstevel@tonic-gate 				/*
2955*0Sstevel@tonic-gate 				 * If snarf_set succeeded or snarf_set failed
2956*0Sstevel@tonic-gate 				 * with MDE_DB_ACCOK (which is set if the
2957*0Sstevel@tonic-gate 				 * mediator provided the extra vote) then
2958*0Sstevel@tonic-gate 				 * steal the xep failure information and put
2959*0Sstevel@tonic-gate 				 * into ep.
2960*0Sstevel@tonic-gate 				 */
2961*0Sstevel@tonic-gate 				if (mdisok(ep) ||
2962*0Sstevel@tonic-gate 				    mdismddberror(ep, MDE_DB_ACCOK)) {
2963*0Sstevel@tonic-gate 					mdstealerror(ep, &xep);
2964*0Sstevel@tonic-gate 				}
2965*0Sstevel@tonic-gate 			}
2966*0Sstevel@tonic-gate 		}
2967*0Sstevel@tonic-gate 	}
2968*0Sstevel@tonic-gate }
2969*0Sstevel@tonic-gate 
2970*0Sstevel@tonic-gate /*
2971*0Sstevel@tonic-gate  * Have this node join the set.
2972*0Sstevel@tonic-gate  * This is called when a node has been
2973*0Sstevel@tonic-gate  * added to a MN diskset that has drives.
2974*0Sstevel@tonic-gate  * Also, called when a node is an alive
2975*0Sstevel@tonic-gate  * member of a MN diskset and the first
2976*0Sstevel@tonic-gate  * drive has been added.
2977*0Sstevel@tonic-gate  */
2978*0Sstevel@tonic-gate bool_t
2979*0Sstevel@tonic-gate mdrpc_joinset_common(
2980*0Sstevel@tonic-gate 	mdrpc_sp_flags_args	*args,
2981*0Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
2982*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
2983*0Sstevel@tonic-gate )
2984*0Sstevel@tonic-gate {
2985*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
2986*0Sstevel@tonic-gate 	int			err;
2987*0Sstevel@tonic-gate 	int			op_mode = W_OK;
2988*0Sstevel@tonic-gate 
2989*0Sstevel@tonic-gate 	/* setup, check permissions */
2990*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
2991*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
2992*0Sstevel@tonic-gate 		return (FALSE);
2993*0Sstevel@tonic-gate 	else if (err != 0)
2994*0Sstevel@tonic-gate 		return (TRUE);
2995*0Sstevel@tonic-gate 
2996*0Sstevel@tonic-gate 	/*
2997*0Sstevel@tonic-gate 	 * During reconfig, joinset can happen without
2998*0Sstevel@tonic-gate 	 * locking first.  Turn off reconfig flag before calling
2999*0Sstevel@tonic-gate 	 * joinset.
3000*0Sstevel@tonic-gate 	 */
3001*0Sstevel@tonic-gate 	if (!(args->flags & MNSET_IN_RECONFIG)) {
3002*0Sstevel@tonic-gate 		if (check_set_lock(op_mode, args->cl_sk, ep))
3003*0Sstevel@tonic-gate 			return (TRUE);
3004*0Sstevel@tonic-gate 	}
3005*0Sstevel@tonic-gate 
3006*0Sstevel@tonic-gate 	/* doit */
3007*0Sstevel@tonic-gate 	joinset(args->sp, args->flags, ep);
3008*0Sstevel@tonic-gate 
3009*0Sstevel@tonic-gate 	err = svc_fini(ep);
3010*0Sstevel@tonic-gate 
3011*0Sstevel@tonic-gate 	return (TRUE);
3012*0Sstevel@tonic-gate }
3013*0Sstevel@tonic-gate 
3014*0Sstevel@tonic-gate bool_t
3015*0Sstevel@tonic-gate mdrpc_joinset_2_svc(
3016*0Sstevel@tonic-gate 	mdrpc_sp_flags_2_args	*args,
3017*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3018*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3019*0Sstevel@tonic-gate )
3020*0Sstevel@tonic-gate {
3021*0Sstevel@tonic-gate 	switch (args->rev) {
3022*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3023*0Sstevel@tonic-gate 		return (mdrpc_joinset_common(
3024*0Sstevel@tonic-gate 		    &args->mdrpc_sp_flags_2_args_u.rev1, res, rqstp));
3025*0Sstevel@tonic-gate 	    default:
3026*0Sstevel@tonic-gate 		return (FALSE);
3027*0Sstevel@tonic-gate 	}
3028*0Sstevel@tonic-gate }
3029*0Sstevel@tonic-gate 
3030*0Sstevel@tonic-gate static void
3031*0Sstevel@tonic-gate withdrawset(
3032*0Sstevel@tonic-gate 	mdsetname_t	*sp,
3033*0Sstevel@tonic-gate 	md_error_t	*ep
3034*0Sstevel@tonic-gate )
3035*0Sstevel@tonic-gate {
3036*0Sstevel@tonic-gate 	mdsetname_t	*my_sp;
3037*0Sstevel@tonic-gate 
3038*0Sstevel@tonic-gate 	if ((my_sp = metasetname(sp->setname, ep)) == NULL)
3039*0Sstevel@tonic-gate 		return;
3040*0Sstevel@tonic-gate 
3041*0Sstevel@tonic-gate 	(void) halt_set(my_sp, ep);
3042*0Sstevel@tonic-gate }
3043*0Sstevel@tonic-gate 
3044*0Sstevel@tonic-gate /*
3045*0Sstevel@tonic-gate  * Have this node withdraw from set.
3046*0Sstevel@tonic-gate  * In response to a failure that occurred
3047*0Sstevel@tonic-gate  * on the client after a joinset.
3048*0Sstevel@tonic-gate  */
3049*0Sstevel@tonic-gate bool_t
3050*0Sstevel@tonic-gate mdrpc_withdrawset_common(
3051*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
3052*0Sstevel@tonic-gate 	mdrpc_generic_res 	*res,
3053*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3054*0Sstevel@tonic-gate )
3055*0Sstevel@tonic-gate {
3056*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3057*0Sstevel@tonic-gate 	int			err;
3058*0Sstevel@tonic-gate 	int			op_mode = W_OK;
3059*0Sstevel@tonic-gate 
3060*0Sstevel@tonic-gate 	/* setup, check permissions */
3061*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3062*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3063*0Sstevel@tonic-gate 		return (FALSE);
3064*0Sstevel@tonic-gate 	else if (err != 0)
3065*0Sstevel@tonic-gate 		return (TRUE);
3066*0Sstevel@tonic-gate 
3067*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
3068*0Sstevel@tonic-gate 		return (TRUE);
3069*0Sstevel@tonic-gate 
3070*0Sstevel@tonic-gate 	/* doit */
3071*0Sstevel@tonic-gate 	withdrawset(args->sp, ep);
3072*0Sstevel@tonic-gate 
3073*0Sstevel@tonic-gate 	err = svc_fini(ep);
3074*0Sstevel@tonic-gate 
3075*0Sstevel@tonic-gate 	return (TRUE);
3076*0Sstevel@tonic-gate }
3077*0Sstevel@tonic-gate 
3078*0Sstevel@tonic-gate bool_t
3079*0Sstevel@tonic-gate mdrpc_withdrawset_2_svc(
3080*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
3081*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3082*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3083*0Sstevel@tonic-gate )
3084*0Sstevel@tonic-gate {
3085*0Sstevel@tonic-gate 	switch (args->rev) {
3086*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3087*0Sstevel@tonic-gate 		return (mdrpc_withdrawset_common(
3088*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3089*0Sstevel@tonic-gate 	    default:
3090*0Sstevel@tonic-gate 		return (FALSE);
3091*0Sstevel@tonic-gate 	}
3092*0Sstevel@tonic-gate }
3093*0Sstevel@tonic-gate 
3094*0Sstevel@tonic-gate static mhd_mhiargs_t *
3095*0Sstevel@tonic-gate gtimeout(mdsetname_t *sp, md_error_t *ep)
3096*0Sstevel@tonic-gate {
3097*0Sstevel@tonic-gate 	md_set_record		*sr;
3098*0Sstevel@tonic-gate 	mhd_mhiargs_t		*mhiargs;
3099*0Sstevel@tonic-gate 
3100*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3101*0Sstevel@tonic-gate 		return (NULL);
3102*0Sstevel@tonic-gate 
3103*0Sstevel@tonic-gate 	mhiargs = Zalloc(sizeof (*mhiargs));
3104*0Sstevel@tonic-gate 	*mhiargs = sr->sr_mhiargs;
3105*0Sstevel@tonic-gate 
3106*0Sstevel@tonic-gate 	free_sr(sr);
3107*0Sstevel@tonic-gate 	return (mhiargs);
3108*0Sstevel@tonic-gate }
3109*0Sstevel@tonic-gate 
3110*0Sstevel@tonic-gate /*
3111*0Sstevel@tonic-gate  * Get the MH timeout values for this set.
3112*0Sstevel@tonic-gate  */
3113*0Sstevel@tonic-gate bool_t
3114*0Sstevel@tonic-gate mdrpc_gtimeout_common(
3115*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
3116*0Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
3117*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3118*0Sstevel@tonic-gate )
3119*0Sstevel@tonic-gate {
3120*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3121*0Sstevel@tonic-gate 	int			err;
3122*0Sstevel@tonic-gate 	int			op_mode = R_OK;
3123*0Sstevel@tonic-gate 
3124*0Sstevel@tonic-gate 	/* setup, check permissions */
3125*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3126*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3127*0Sstevel@tonic-gate 		return (FALSE);
3128*0Sstevel@tonic-gate 	else if (err != 0)
3129*0Sstevel@tonic-gate 		return (TRUE);
3130*0Sstevel@tonic-gate 
3131*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3132*0Sstevel@tonic-gate 		return (TRUE);
3133*0Sstevel@tonic-gate 
3134*0Sstevel@tonic-gate 	/* doit */
3135*0Sstevel@tonic-gate 	res->mhiargsp = gtimeout(args->sp, ep);
3136*0Sstevel@tonic-gate 
3137*0Sstevel@tonic-gate 	err = svc_fini(ep);
3138*0Sstevel@tonic-gate 
3139*0Sstevel@tonic-gate 	return (TRUE);
3140*0Sstevel@tonic-gate }
3141*0Sstevel@tonic-gate 
3142*0Sstevel@tonic-gate bool_t
3143*0Sstevel@tonic-gate mdrpc_gtimeout_1_svc(
3144*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
3145*0Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
3146*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3147*0Sstevel@tonic-gate )
3148*0Sstevel@tonic-gate {
3149*0Sstevel@tonic-gate 	return (mdrpc_gtimeout_common(args, res, rqstp));
3150*0Sstevel@tonic-gate }
3151*0Sstevel@tonic-gate 
3152*0Sstevel@tonic-gate bool_t
3153*0Sstevel@tonic-gate mdrpc_gtimeout_2_svc(
3154*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
3155*0Sstevel@tonic-gate 	mdrpc_gtimeout_res 	*res,
3156*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3157*0Sstevel@tonic-gate )
3158*0Sstevel@tonic-gate {
3159*0Sstevel@tonic-gate 	switch (args->rev) {
3160*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3161*0Sstevel@tonic-gate 		return (mdrpc_gtimeout_common(
3162*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3163*0Sstevel@tonic-gate 	    default:
3164*0Sstevel@tonic-gate 		return (FALSE);
3165*0Sstevel@tonic-gate 	}
3166*0Sstevel@tonic-gate }
3167*0Sstevel@tonic-gate 
3168*0Sstevel@tonic-gate /*
3169*0Sstevel@tonic-gate  * return the official host name for the callee
3170*0Sstevel@tonic-gate  */
3171*0Sstevel@tonic-gate /*ARGSUSED*/
3172*0Sstevel@tonic-gate bool_t
3173*0Sstevel@tonic-gate mdrpc_hostname_common(
3174*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
3175*0Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
3176*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3177*0Sstevel@tonic-gate )
3178*0Sstevel@tonic-gate {
3179*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3180*0Sstevel@tonic-gate 	int			err;
3181*0Sstevel@tonic-gate 	int			op_mode = R_OK;
3182*0Sstevel@tonic-gate 
3183*0Sstevel@tonic-gate 	/* setup, check permissions */
3184*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3185*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3186*0Sstevel@tonic-gate 		return (FALSE);
3187*0Sstevel@tonic-gate 	else if (err != 0)
3188*0Sstevel@tonic-gate 		return (TRUE);
3189*0Sstevel@tonic-gate 
3190*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3191*0Sstevel@tonic-gate 		return (TRUE);
3192*0Sstevel@tonic-gate 
3193*0Sstevel@tonic-gate 	/* doit */
3194*0Sstevel@tonic-gate 	res->hostname = Strdup(mynode());
3195*0Sstevel@tonic-gate 
3196*0Sstevel@tonic-gate 	err = svc_fini(ep);
3197*0Sstevel@tonic-gate 
3198*0Sstevel@tonic-gate 	return (TRUE);
3199*0Sstevel@tonic-gate }
3200*0Sstevel@tonic-gate 
3201*0Sstevel@tonic-gate bool_t
3202*0Sstevel@tonic-gate mdrpc_hostname_1_svc(
3203*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
3204*0Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
3205*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3206*0Sstevel@tonic-gate )
3207*0Sstevel@tonic-gate {
3208*0Sstevel@tonic-gate 	return (mdrpc_hostname_common(args, res, rqstp));
3209*0Sstevel@tonic-gate }
3210*0Sstevel@tonic-gate 
3211*0Sstevel@tonic-gate bool_t
3212*0Sstevel@tonic-gate mdrpc_hostname_2_svc(
3213*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
3214*0Sstevel@tonic-gate 	mdrpc_hostname_res 	*res,
3215*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3216*0Sstevel@tonic-gate )
3217*0Sstevel@tonic-gate {
3218*0Sstevel@tonic-gate 	return (mdrpc_hostname_common(args, res, rqstp));
3219*0Sstevel@tonic-gate }
3220*0Sstevel@tonic-gate 
3221*0Sstevel@tonic-gate /*
3222*0Sstevel@tonic-gate  * return a response
3223*0Sstevel@tonic-gate  */
3224*0Sstevel@tonic-gate /*ARGSUSED*/
3225*0Sstevel@tonic-gate bool_t
3226*0Sstevel@tonic-gate mdrpc_nullproc_common(
3227*0Sstevel@tonic-gate 	void		*args,
3228*0Sstevel@tonic-gate 	md_error_t	*ep,
3229*0Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
3230*0Sstevel@tonic-gate )
3231*0Sstevel@tonic-gate {
3232*0Sstevel@tonic-gate 	*ep = mdnullerror;
3233*0Sstevel@tonic-gate 	/* do nothing */
3234*0Sstevel@tonic-gate 	return (TRUE);
3235*0Sstevel@tonic-gate }
3236*0Sstevel@tonic-gate 
3237*0Sstevel@tonic-gate bool_t
3238*0Sstevel@tonic-gate mdrpc_nullproc_1_svc(
3239*0Sstevel@tonic-gate 	void		*args,
3240*0Sstevel@tonic-gate 	md_error_t	*ep,
3241*0Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
3242*0Sstevel@tonic-gate )
3243*0Sstevel@tonic-gate {
3244*0Sstevel@tonic-gate 	return (mdrpc_nullproc_common(args, ep, rqstp));
3245*0Sstevel@tonic-gate }
3246*0Sstevel@tonic-gate 
3247*0Sstevel@tonic-gate bool_t
3248*0Sstevel@tonic-gate mdrpc_nullproc_2_svc(
3249*0Sstevel@tonic-gate 	void		*args,
3250*0Sstevel@tonic-gate 	md_error_t	*ep,
3251*0Sstevel@tonic-gate 	struct svc_req	*rqstp		/* RPC stuff */
3252*0Sstevel@tonic-gate )
3253*0Sstevel@tonic-gate {
3254*0Sstevel@tonic-gate 	return (mdrpc_nullproc_common(args, ep, rqstp));
3255*0Sstevel@tonic-gate }
3256*0Sstevel@tonic-gate 
3257*0Sstevel@tonic-gate /*
3258*0Sstevel@tonic-gate  * determine if the caller owns the set.
3259*0Sstevel@tonic-gate  */
3260*0Sstevel@tonic-gate bool_t
3261*0Sstevel@tonic-gate mdrpc_ownset_common(
3262*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
3263*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3264*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3265*0Sstevel@tonic-gate )
3266*0Sstevel@tonic-gate {
3267*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3268*0Sstevel@tonic-gate 	int			err;
3269*0Sstevel@tonic-gate 	int			op_mode = R_OK;
3270*0Sstevel@tonic-gate 
3271*0Sstevel@tonic-gate 	/* setup, check permissions */
3272*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3273*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3274*0Sstevel@tonic-gate 		return (FALSE);
3275*0Sstevel@tonic-gate 	else if (err != 0)
3276*0Sstevel@tonic-gate 		return (TRUE);
3277*0Sstevel@tonic-gate 
3278*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3279*0Sstevel@tonic-gate 		return (TRUE);
3280*0Sstevel@tonic-gate 
3281*0Sstevel@tonic-gate 	/* doit */
3282*0Sstevel@tonic-gate 	if (s_ownset(args->sp->setno, ep))
3283*0Sstevel@tonic-gate 		res->value = TRUE;
3284*0Sstevel@tonic-gate 	else
3285*0Sstevel@tonic-gate 		res->value = FALSE;
3286*0Sstevel@tonic-gate 
3287*0Sstevel@tonic-gate 	err = svc_fini(ep);
3288*0Sstevel@tonic-gate 
3289*0Sstevel@tonic-gate 	return (TRUE);
3290*0Sstevel@tonic-gate }
3291*0Sstevel@tonic-gate 
3292*0Sstevel@tonic-gate bool_t
3293*0Sstevel@tonic-gate mdrpc_ownset_1_svc(
3294*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,
3295*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3296*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3297*0Sstevel@tonic-gate )
3298*0Sstevel@tonic-gate {
3299*0Sstevel@tonic-gate 	return (mdrpc_ownset_common(args, res, rqstp));
3300*0Sstevel@tonic-gate }
3301*0Sstevel@tonic-gate 
3302*0Sstevel@tonic-gate bool_t
3303*0Sstevel@tonic-gate mdrpc_ownset_2_svc(
3304*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
3305*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3306*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3307*0Sstevel@tonic-gate )
3308*0Sstevel@tonic-gate {
3309*0Sstevel@tonic-gate 	switch (args->rev) {
3310*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3311*0Sstevel@tonic-gate 		return (mdrpc_ownset_common(
3312*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3313*0Sstevel@tonic-gate 	    default:
3314*0Sstevel@tonic-gate 		return (FALSE);
3315*0Sstevel@tonic-gate 	}
3316*0Sstevel@tonic-gate }
3317*0Sstevel@tonic-gate 
3318*0Sstevel@tonic-gate static int
3319*0Sstevel@tonic-gate setnameok(char *setname, md_error_t *ep)
3320*0Sstevel@tonic-gate {
3321*0Sstevel@tonic-gate 	int			rval = 0;
3322*0Sstevel@tonic-gate 	struct	stat		statb;
3323*0Sstevel@tonic-gate 	md_set_record		*sr = NULL;
3324*0Sstevel@tonic-gate 	char			*setlink = NULL;
3325*0Sstevel@tonic-gate 
3326*0Sstevel@tonic-gate 	setlink = Strdup("/dev/md/");
3327*0Sstevel@tonic-gate 	setlink = Realloc(setlink, strlen(setlink) + strlen(setname) + 1);
3328*0Sstevel@tonic-gate 	(void) strcat(setlink, setname);
3329*0Sstevel@tonic-gate 
3330*0Sstevel@tonic-gate 	if (lstat(setlink, &statb) == -1) {
3331*0Sstevel@tonic-gate 		/*
3332*0Sstevel@tonic-gate 		 * If lstat() fails with ENOENT, setname is OK, if it
3333*0Sstevel@tonic-gate 		 * fails for other than that, we fail the RPC
3334*0Sstevel@tonic-gate 		 */
3335*0Sstevel@tonic-gate 		if (errno == ENOENT) {
3336*0Sstevel@tonic-gate 			rval = 1;
3337*0Sstevel@tonic-gate 			goto out;
3338*0Sstevel@tonic-gate 		}
3339*0Sstevel@tonic-gate 
3340*0Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, setlink);
3341*0Sstevel@tonic-gate 		goto out;
3342*0Sstevel@tonic-gate 	}
3343*0Sstevel@tonic-gate 
3344*0Sstevel@tonic-gate 	/*
3345*0Sstevel@tonic-gate 	 * If the lstat() succeeded, then we see what type of object
3346*0Sstevel@tonic-gate 	 * we are dealing with, if it is a symlink, we do some further
3347*0Sstevel@tonic-gate 	 * checking, if it is not a symlink, then we return an
3348*0Sstevel@tonic-gate 	 * indication that the set name is NOT acceptable.
3349*0Sstevel@tonic-gate 	 */
3350*0Sstevel@tonic-gate 	if (! S_ISLNK(statb.st_mode))
3351*0Sstevel@tonic-gate 		goto out;
3352*0Sstevel@tonic-gate 
3353*0Sstevel@tonic-gate 	/*
3354*0Sstevel@tonic-gate 	 * We look up the setname to see if there is a set
3355*0Sstevel@tonic-gate 	 * with that name, if there is, then we return
3356*0Sstevel@tonic-gate 	 * an indication that the set name is NOT acceptable.
3357*0Sstevel@tonic-gate 	 */
3358*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) != NULL)
3359*0Sstevel@tonic-gate 		goto out;
3360*0Sstevel@tonic-gate 
3361*0Sstevel@tonic-gate 	if (! mdiserror(ep, MDE_NO_SET))
3362*0Sstevel@tonic-gate 		goto out;
3363*0Sstevel@tonic-gate 
3364*0Sstevel@tonic-gate 	mdclrerror(ep);
3365*0Sstevel@tonic-gate 
3366*0Sstevel@tonic-gate 	rval = 1;
3367*0Sstevel@tonic-gate out:
3368*0Sstevel@tonic-gate 	if (sr != NULL)
3369*0Sstevel@tonic-gate 		free_sr(sr);
3370*0Sstevel@tonic-gate 	Free(setlink);
3371*0Sstevel@tonic-gate 	return (rval);
3372*0Sstevel@tonic-gate }
3373*0Sstevel@tonic-gate 
3374*0Sstevel@tonic-gate /*
3375*0Sstevel@tonic-gate  * Make sure the name of the set is OK.
3376*0Sstevel@tonic-gate  */
3377*0Sstevel@tonic-gate bool_t
3378*0Sstevel@tonic-gate mdrpc_setnameok_common(
3379*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,	/* device name */
3380*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3381*0Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
3382*0Sstevel@tonic-gate )
3383*0Sstevel@tonic-gate {
3384*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3385*0Sstevel@tonic-gate 	int			err;
3386*0Sstevel@tonic-gate 	int			op_mode = R_OK;
3387*0Sstevel@tonic-gate 
3388*0Sstevel@tonic-gate 	/* setup, check permissions */
3389*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3390*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3391*0Sstevel@tonic-gate 		return (FALSE);
3392*0Sstevel@tonic-gate 	else if (err != 0)
3393*0Sstevel@tonic-gate 		return (TRUE);
3394*0Sstevel@tonic-gate 
3395*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3396*0Sstevel@tonic-gate 		return (TRUE);
3397*0Sstevel@tonic-gate 
3398*0Sstevel@tonic-gate 	/* doit */
3399*0Sstevel@tonic-gate 	res->value = setnameok(args->sp->setname, ep);
3400*0Sstevel@tonic-gate 
3401*0Sstevel@tonic-gate 	err = svc_fini(ep);
3402*0Sstevel@tonic-gate 
3403*0Sstevel@tonic-gate 	return (TRUE);
3404*0Sstevel@tonic-gate }
3405*0Sstevel@tonic-gate 
3406*0Sstevel@tonic-gate bool_t
3407*0Sstevel@tonic-gate mdrpc_setnameok_1_svc(
3408*0Sstevel@tonic-gate 	mdrpc_sp_args		*args,	/* device name */
3409*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3410*0Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
3411*0Sstevel@tonic-gate )
3412*0Sstevel@tonic-gate {
3413*0Sstevel@tonic-gate 	return (mdrpc_setnameok_common(args, res, rqstp));
3414*0Sstevel@tonic-gate }
3415*0Sstevel@tonic-gate 
3416*0Sstevel@tonic-gate bool_t
3417*0Sstevel@tonic-gate mdrpc_setnameok_2_svc(
3418*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,	/* device name */
3419*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3420*0Sstevel@tonic-gate 	struct svc_req		*rqstp	/* RPC stuff */
3421*0Sstevel@tonic-gate )
3422*0Sstevel@tonic-gate {
3423*0Sstevel@tonic-gate 	switch (args->rev) {
3424*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3425*0Sstevel@tonic-gate 		return (mdrpc_setnameok_common(
3426*0Sstevel@tonic-gate 		    &args->mdrpc_sp_2_args_u.rev1, res, rqstp));
3427*0Sstevel@tonic-gate 	    default:
3428*0Sstevel@tonic-gate 		return (FALSE);
3429*0Sstevel@tonic-gate 	}
3430*0Sstevel@tonic-gate }
3431*0Sstevel@tonic-gate 
3432*0Sstevel@tonic-gate /*
3433*0Sstevel@tonic-gate  * determine if the setnumber we want to share is in use.
3434*0Sstevel@tonic-gate  */
3435*0Sstevel@tonic-gate bool_t
3436*0Sstevel@tonic-gate mdrpc_setnumbusy_common(
3437*0Sstevel@tonic-gate 	mdrpc_setno_args	*args,
3438*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3439*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3440*0Sstevel@tonic-gate )
3441*0Sstevel@tonic-gate {
3442*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3443*0Sstevel@tonic-gate 	md_set_record		*sr = NULL;
3444*0Sstevel@tonic-gate 	int			err;
3445*0Sstevel@tonic-gate 	int			op_mode = R_OK;
3446*0Sstevel@tonic-gate 
3447*0Sstevel@tonic-gate 	/* setup, check permissions */
3448*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3449*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3450*0Sstevel@tonic-gate 		return (FALSE);
3451*0Sstevel@tonic-gate 	else if (err != 0)
3452*0Sstevel@tonic-gate 		return (TRUE);
3453*0Sstevel@tonic-gate 
3454*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3455*0Sstevel@tonic-gate 		return (TRUE);
3456*0Sstevel@tonic-gate 
3457*0Sstevel@tonic-gate 	/* doit */
3458*0Sstevel@tonic-gate 	if ((sr = getsetbynum(args->setno, ep)) != NULL) {
3459*0Sstevel@tonic-gate 		res->value = TRUE;
3460*0Sstevel@tonic-gate 		free_sr(sr);
3461*0Sstevel@tonic-gate 		return (TRUE);
3462*0Sstevel@tonic-gate 	}
3463*0Sstevel@tonic-gate 	res->value = FALSE;
3464*0Sstevel@tonic-gate 	if (mdiserror(ep, MDE_NO_SET))
3465*0Sstevel@tonic-gate 		mdclrerror(ep);
3466*0Sstevel@tonic-gate 
3467*0Sstevel@tonic-gate 	err = svc_fini(ep);
3468*0Sstevel@tonic-gate 
3469*0Sstevel@tonic-gate 	return (TRUE);
3470*0Sstevel@tonic-gate }
3471*0Sstevel@tonic-gate 
3472*0Sstevel@tonic-gate bool_t
3473*0Sstevel@tonic-gate mdrpc_setnumbusy_1_svc(
3474*0Sstevel@tonic-gate 	mdrpc_setno_args	*args,
3475*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3476*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3477*0Sstevel@tonic-gate )
3478*0Sstevel@tonic-gate {
3479*0Sstevel@tonic-gate 	return (mdrpc_setnumbusy_common(args, res, rqstp));
3480*0Sstevel@tonic-gate }
3481*0Sstevel@tonic-gate 
3482*0Sstevel@tonic-gate bool_t
3483*0Sstevel@tonic-gate mdrpc_setnumbusy_2_svc(
3484*0Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
3485*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
3486*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3487*0Sstevel@tonic-gate )
3488*0Sstevel@tonic-gate {
3489*0Sstevel@tonic-gate 	switch (args->rev) {
3490*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3491*0Sstevel@tonic-gate 		return (mdrpc_setnumbusy_common(
3492*0Sstevel@tonic-gate 		    &args->mdrpc_setno_2_args_u.rev1, res, rqstp));
3493*0Sstevel@tonic-gate 	    default:
3494*0Sstevel@tonic-gate 		return (FALSE);
3495*0Sstevel@tonic-gate 	}
3496*0Sstevel@tonic-gate }
3497*0Sstevel@tonic-gate 
3498*0Sstevel@tonic-gate static void
3499*0Sstevel@tonic-gate stimeout(
3500*0Sstevel@tonic-gate 	mdsetname_t	*sp,
3501*0Sstevel@tonic-gate 	mhd_mhiargs_t	*mhiargsp,
3502*0Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
3503*0Sstevel@tonic-gate 	md_error_t	*ep
3504*0Sstevel@tonic-gate )
3505*0Sstevel@tonic-gate {
3506*0Sstevel@tonic-gate 	mddb_userreq_t		req;
3507*0Sstevel@tonic-gate 	md_set_record		*sr;
3508*0Sstevel@tonic-gate 
3509*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3510*0Sstevel@tonic-gate 		return;
3511*0Sstevel@tonic-gate 
3512*0Sstevel@tonic-gate 	sr->sr_mhiargs = *mhiargsp;
3513*0Sstevel@tonic-gate 
3514*0Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
3515*0Sstevel@tonic-gate 
3516*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
3517*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
3518*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
3519*0Sstevel@tonic-gate 		req.ur_size = sizeof (struct md_mnset_record);
3520*0Sstevel@tonic-gate 	} else {
3521*0Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
3522*0Sstevel@tonic-gate 	}
3523*0Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
3524*0Sstevel@tonic-gate 
3525*0Sstevel@tonic-gate 	/*
3526*0Sstevel@tonic-gate 	 * Cluster nodename support
3527*0Sstevel@tonic-gate 	 * Convert nodename -> nodeid
3528*0Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
3529*0Sstevel@tonic-gate 	 * both the nodeid and name.
3530*0Sstevel@tonic-gate 	 */
3531*0Sstevel@tonic-gate 	if ((version == METAD_VERSION) ||
3532*0Sstevel@tonic-gate 	    ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
3533*0Sstevel@tonic-gate 		sdssc_cm_sr_nm2nid(sr);
3534*0Sstevel@tonic-gate 
3535*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
3536*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
3537*0Sstevel@tonic-gate 		return;
3538*0Sstevel@tonic-gate 	}
3539*0Sstevel@tonic-gate 
3540*0Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
3541*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_COMMIT_ONE, sr->sr_selfid)
3542*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
3543*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
3544*0Sstevel@tonic-gate 
3545*0Sstevel@tonic-gate 	/*
3546*0Sstevel@tonic-gate 	 * Cluster nodename support
3547*0Sstevel@tonic-gate 	 * Convert nodeid -> nodename
3548*0Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
3549*0Sstevel@tonic-gate 	 * both the nodeid and name.
3550*0Sstevel@tonic-gate 	 */
3551*0Sstevel@tonic-gate 	if ((version == METAD_VERSION) ||
3552*0Sstevel@tonic-gate 	    ((version == METAD_VERSION_DEVID) && (!(MD_MNSET_REC(sr)))))
3553*0Sstevel@tonic-gate 		sdssc_cm_sr_nid2nm(sr);
3554*0Sstevel@tonic-gate 
3555*0Sstevel@tonic-gate 	free_sr(sr);
3556*0Sstevel@tonic-gate }
3557*0Sstevel@tonic-gate 
3558*0Sstevel@tonic-gate /*
3559*0Sstevel@tonic-gate  * Set MH ioctl timeout values.
3560*0Sstevel@tonic-gate  */
3561*0Sstevel@tonic-gate bool_t
3562*0Sstevel@tonic-gate mdrpc_stimeout_common(
3563*0Sstevel@tonic-gate 	mdrpc_stimeout_args	*args,
3564*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3565*0Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
3566*0Sstevel@tonic-gate 	int			version		/* RPC version */
3567*0Sstevel@tonic-gate )
3568*0Sstevel@tonic-gate {
3569*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3570*0Sstevel@tonic-gate 	int			err;
3571*0Sstevel@tonic-gate 	int			op_mode = W_OK;
3572*0Sstevel@tonic-gate 
3573*0Sstevel@tonic-gate 	/* setup, check permissions */
3574*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3575*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3576*0Sstevel@tonic-gate 		return (FALSE);
3577*0Sstevel@tonic-gate 	else if (err != 0)
3578*0Sstevel@tonic-gate 		return (TRUE);
3579*0Sstevel@tonic-gate 
3580*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, NULL, ep))
3581*0Sstevel@tonic-gate 		return (TRUE);
3582*0Sstevel@tonic-gate 
3583*0Sstevel@tonic-gate 	/* doit */
3584*0Sstevel@tonic-gate 	stimeout(args->sp, args->mhiargsp, version, ep);
3585*0Sstevel@tonic-gate 
3586*0Sstevel@tonic-gate 	err = svc_fini(ep);
3587*0Sstevel@tonic-gate 
3588*0Sstevel@tonic-gate 	return (TRUE);
3589*0Sstevel@tonic-gate }
3590*0Sstevel@tonic-gate 
3591*0Sstevel@tonic-gate bool_t
3592*0Sstevel@tonic-gate mdrpc_stimeout_1_svc(
3593*0Sstevel@tonic-gate 	mdrpc_stimeout_args	*args,
3594*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3595*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3596*0Sstevel@tonic-gate )
3597*0Sstevel@tonic-gate {
3598*0Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
3599*0Sstevel@tonic-gate 	return (mdrpc_stimeout_common(args, res, rqstp, METAD_VERSION));
3600*0Sstevel@tonic-gate }
3601*0Sstevel@tonic-gate 
3602*0Sstevel@tonic-gate bool_t
3603*0Sstevel@tonic-gate mdrpc_stimeout_2_svc(
3604*0Sstevel@tonic-gate 	mdrpc_stimeout_2_args	*args,
3605*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3606*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3607*0Sstevel@tonic-gate )
3608*0Sstevel@tonic-gate {
3609*0Sstevel@tonic-gate 	switch (args->rev) {
3610*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3611*0Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
3612*0Sstevel@tonic-gate 		return (mdrpc_stimeout_common(
3613*0Sstevel@tonic-gate 		    &args->mdrpc_stimeout_2_args_u.rev1, res,
3614*0Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
3615*0Sstevel@tonic-gate 	    default:
3616*0Sstevel@tonic-gate 		return (FALSE);
3617*0Sstevel@tonic-gate 	}
3618*0Sstevel@tonic-gate }
3619*0Sstevel@tonic-gate 
3620*0Sstevel@tonic-gate static void
3621*0Sstevel@tonic-gate upd_dr_dbinfo(
3622*0Sstevel@tonic-gate 	mdsetname_t	*sp,
3623*0Sstevel@tonic-gate 	md_drive_desc	*dd,
3624*0Sstevel@tonic-gate 	md_error_t	*ep
3625*0Sstevel@tonic-gate )
3626*0Sstevel@tonic-gate {
3627*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
3628*0Sstevel@tonic-gate 	md_set_record	*sr;
3629*0Sstevel@tonic-gate 	md_drive_record	*dr;
3630*0Sstevel@tonic-gate 	md_drive_desc	*p;
3631*0Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
3632*0Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
3633*0Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
3634*0Sstevel@tonic-gate 	int		devid_same = -1;
3635*0Sstevel@tonic-gate 	side_t		sideno;
3636*0Sstevel@tonic-gate 	int		using_devid = 0;
3637*0Sstevel@tonic-gate 
3638*0Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
3639*0Sstevel@tonic-gate 		return;
3640*0Sstevel@tonic-gate 
3641*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
3642*0Sstevel@tonic-gate 
3643*0Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
3644*0Sstevel@tonic-gate 		return;
3645*0Sstevel@tonic-gate 
3646*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3647*0Sstevel@tonic-gate 		return;
3648*0Sstevel@tonic-gate 
3649*0Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
3650*0Sstevel@tonic-gate 		return;
3651*0Sstevel@tonic-gate 
3652*0Sstevel@tonic-gate 	/*
3653*0Sstevel@tonic-gate 	 * The system is either all devid or all
3654*0Sstevel@tonic-gate 	 * non-devid so we determine this by looking
3655*0Sstevel@tonic-gate 	 * at the first item in the list.
3656*0Sstevel@tonic-gate 	 *
3657*0Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
3658*0Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
3659*0Sstevel@tonic-gate 	 * before set the using_devid.
3660*0Sstevel@tonic-gate 	 */
3661*0Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
3662*0Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
3663*0Sstevel@tonic-gate 		using_devid = 1;
3664*0Sstevel@tonic-gate 
3665*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
3666*0Sstevel@tonic-gate 		dn = p->dd_dnp;
3667*0Sstevel@tonic-gate 		devid_remote = NULL;
3668*0Sstevel@tonic-gate 
3669*0Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
3670*0Sstevel@tonic-gate 		    using_devid) {
3671*0Sstevel@tonic-gate 			/*
3672*0Sstevel@tonic-gate 			 * We have a devid so use it.
3673*0Sstevel@tonic-gate 			 */
3674*0Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
3675*0Sstevel@tonic-gate 		}
3676*0Sstevel@tonic-gate 
3677*0Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
3678*0Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
3679*0Sstevel@tonic-gate 			/* something went really wrong. Can't process */
3680*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
3681*0Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
3682*0Sstevel@tonic-gate 			return;
3683*0Sstevel@tonic-gate 		}
3684*0Sstevel@tonic-gate 
3685*0Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
3686*0Sstevel@tonic-gate 			devid_same = -1;
3687*0Sstevel@tonic-gate 
3688*0Sstevel@tonic-gate 			dn1 = metadrivename_withdrkey(local_sp, sideno,
3689*0Sstevel@tonic-gate 			    dr->dr_key, MD_BASICNAME_OK, ep);
3690*0Sstevel@tonic-gate 
3691*0Sstevel@tonic-gate 			if (dn1 == NULL) {
3692*0Sstevel@tonic-gate 				if (devid_remote)
3693*0Sstevel@tonic-gate 					devid_free(devid_remote);
3694*0Sstevel@tonic-gate 				goto out;
3695*0Sstevel@tonic-gate 			}
3696*0Sstevel@tonic-gate 
3697*0Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
3698*0Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid, &devid_local,
3699*0Sstevel@tonic-gate 				    NULL) == 0) {
3700*0Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
3701*0Sstevel@tonic-gate 					    devid_local);
3702*0Sstevel@tonic-gate 					devid_free(devid_local);
3703*0Sstevel@tonic-gate 				}
3704*0Sstevel@tonic-gate 			}
3705*0Sstevel@tonic-gate 
3706*0Sstevel@tonic-gate 			if (using_devid && devid_same == 0)
3707*0Sstevel@tonic-gate 				break;
3708*0Sstevel@tonic-gate 
3709*0Sstevel@tonic-gate 			if (!using_devid &&
3710*0Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)
3711*0Sstevel@tonic-gate 				break;
3712*0Sstevel@tonic-gate 		}
3713*0Sstevel@tonic-gate 
3714*0Sstevel@tonic-gate 		if (dr) {
3715*0Sstevel@tonic-gate 			/* Adjust the fields in the copy */
3716*0Sstevel@tonic-gate 			dr->dr_dbcnt = p->dd_dbcnt;
3717*0Sstevel@tonic-gate 			dr->dr_dbsize = p->dd_dbsize;
3718*0Sstevel@tonic-gate 		}
3719*0Sstevel@tonic-gate 		if (devid_remote)
3720*0Sstevel@tonic-gate 			devid_free(devid_remote);
3721*0Sstevel@tonic-gate 	}
3722*0Sstevel@tonic-gate 
3723*0Sstevel@tonic-gate 
3724*0Sstevel@tonic-gate out:
3725*0Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
3726*0Sstevel@tonic-gate 	free_sr(sr);
3727*0Sstevel@tonic-gate }
3728*0Sstevel@tonic-gate 
3729*0Sstevel@tonic-gate /*
3730*0Sstevel@tonic-gate  * update the database count and size field of drive records.
3731*0Sstevel@tonic-gate  */
3732*0Sstevel@tonic-gate bool_t
3733*0Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_common(
3734*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	*args,
3735*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3736*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3737*0Sstevel@tonic-gate )
3738*0Sstevel@tonic-gate {
3739*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3740*0Sstevel@tonic-gate 	int			err;
3741*0Sstevel@tonic-gate 	int			op_mode = W_OK;
3742*0Sstevel@tonic-gate 
3743*0Sstevel@tonic-gate 	/* setup, check permissions */
3744*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3745*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3746*0Sstevel@tonic-gate 		return (FALSE);
3747*0Sstevel@tonic-gate 	else if (err != 0)
3748*0Sstevel@tonic-gate 		return (TRUE);
3749*0Sstevel@tonic-gate 
3750*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
3751*0Sstevel@tonic-gate 		return (TRUE);
3752*0Sstevel@tonic-gate 
3753*0Sstevel@tonic-gate 	/* doit */
3754*0Sstevel@tonic-gate 	upd_dr_dbinfo(args->sp, args->drivedescs, ep);
3755*0Sstevel@tonic-gate 
3756*0Sstevel@tonic-gate 	err = svc_fini(ep);
3757*0Sstevel@tonic-gate 
3758*0Sstevel@tonic-gate 	return (TRUE);
3759*0Sstevel@tonic-gate }
3760*0Sstevel@tonic-gate 
3761*0Sstevel@tonic-gate /*
3762*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
3763*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
3764*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
3765*0Sstevel@tonic-gate  */
3766*0Sstevel@tonic-gate bool_t
3767*0Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_1_svc(
3768*0Sstevel@tonic-gate 	mdrpc_drives_args	*args,
3769*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3770*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3771*0Sstevel@tonic-gate )
3772*0Sstevel@tonic-gate {
3773*0Sstevel@tonic-gate 	bool_t			retval;
3774*0Sstevel@tonic-gate 	mdrpc_drives_2_args_r1	v2_args;
3775*0Sstevel@tonic-gate 
3776*0Sstevel@tonic-gate 	/* allocate memory */
3777*0Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
3778*0Sstevel@tonic-gate 
3779*0Sstevel@tonic-gate 	/* build args */
3780*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
3781*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
3782*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
3783*0Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
3784*0Sstevel@tonic-gate 	v2_args.timestamp = args->timestamp;
3785*0Sstevel@tonic-gate 	v2_args.genid = args->genid;
3786*0Sstevel@tonic-gate 
3787*0Sstevel@tonic-gate 	retval = mdrpc_upd_dr_dbinfo_common(&v2_args, res, rqstp);
3788*0Sstevel@tonic-gate 
3789*0Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
3790*0Sstevel@tonic-gate 
3791*0Sstevel@tonic-gate 	return (retval);
3792*0Sstevel@tonic-gate }
3793*0Sstevel@tonic-gate 
3794*0Sstevel@tonic-gate bool_t
3795*0Sstevel@tonic-gate mdrpc_upd_dr_dbinfo_2_svc(
3796*0Sstevel@tonic-gate 	mdrpc_drives_2_args	*args,
3797*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3798*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3799*0Sstevel@tonic-gate )
3800*0Sstevel@tonic-gate {
3801*0Sstevel@tonic-gate 	switch (args->rev) {
3802*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3803*0Sstevel@tonic-gate 		return (mdrpc_upd_dr_dbinfo_common(
3804*0Sstevel@tonic-gate 		    &args->mdrpc_drives_2_args_u.rev1, res, rqstp));
3805*0Sstevel@tonic-gate 	    default:
3806*0Sstevel@tonic-gate 		return (FALSE);
3807*0Sstevel@tonic-gate 	}
3808*0Sstevel@tonic-gate }
3809*0Sstevel@tonic-gate 
3810*0Sstevel@tonic-gate static void
3811*0Sstevel@tonic-gate upd_dr_flags(
3812*0Sstevel@tonic-gate 	mdsetname_t	*sp,
3813*0Sstevel@tonic-gate 	md_drive_desc	*dd,
3814*0Sstevel@tonic-gate 	uint_t		new_flags,
3815*0Sstevel@tonic-gate 	md_error_t	*ep
3816*0Sstevel@tonic-gate )
3817*0Sstevel@tonic-gate {
3818*0Sstevel@tonic-gate 	mdsetname_t	*local_sp;
3819*0Sstevel@tonic-gate 	md_set_record	*sr;
3820*0Sstevel@tonic-gate 	md_drive_record	*dr;
3821*0Sstevel@tonic-gate 	md_drive_desc	*p;
3822*0Sstevel@tonic-gate 	mddrivename_t	*dn, *dn1;
3823*0Sstevel@tonic-gate 	ddi_devid_t	devid_remote = NULL;
3824*0Sstevel@tonic-gate 	ddi_devid_t	devid_local = NULL;
3825*0Sstevel@tonic-gate 	int		devid_same = -1;
3826*0Sstevel@tonic-gate 	side_t		sideno;
3827*0Sstevel@tonic-gate 	int		using_devid = 0;
3828*0Sstevel@tonic-gate 
3829*0Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
3830*0Sstevel@tonic-gate 		return;
3831*0Sstevel@tonic-gate 
3832*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
3833*0Sstevel@tonic-gate 
3834*0Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
3835*0Sstevel@tonic-gate 		return;
3836*0Sstevel@tonic-gate 
3837*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
3838*0Sstevel@tonic-gate 		return;
3839*0Sstevel@tonic-gate 
3840*0Sstevel@tonic-gate 	if (dd->dd_dnp == NULL)
3841*0Sstevel@tonic-gate 		return;
3842*0Sstevel@tonic-gate 
3843*0Sstevel@tonic-gate 	/*
3844*0Sstevel@tonic-gate 	 * The system is either all devid or all
3845*0Sstevel@tonic-gate 	 * non-devid so we determine this by looking
3846*0Sstevel@tonic-gate 	 * at the first item in the list.
3847*0Sstevel@tonic-gate 	 *
3848*0Sstevel@tonic-gate 	 * For did disks, the dd_dnp->devid is a valid pointer which
3849*0Sstevel@tonic-gate 	 * points to a '' string of devid.  We need to check this
3850*0Sstevel@tonic-gate 	 * before set the using_devid.
3851*0Sstevel@tonic-gate 	 */
3852*0Sstevel@tonic-gate 	if ((dd->dd_dnp->devid != NULL) && (dd->dd_dnp->devid[0] != '\0') &&
3853*0Sstevel@tonic-gate 	    (!(MD_MNSET_REC(sr))))
3854*0Sstevel@tonic-gate 		using_devid = 1;
3855*0Sstevel@tonic-gate 
3856*0Sstevel@tonic-gate 	for (p = dd; p != NULL; p = p->dd_next) {
3857*0Sstevel@tonic-gate 		dn = p->dd_dnp;
3858*0Sstevel@tonic-gate 		devid_remote = NULL;
3859*0Sstevel@tonic-gate 
3860*0Sstevel@tonic-gate 		if (dn->devid != NULL && (strlen(dn->devid) != 0) &&
3861*0Sstevel@tonic-gate 		    using_devid) {
3862*0Sstevel@tonic-gate 			/*
3863*0Sstevel@tonic-gate 			 * We have a devid so use it.
3864*0Sstevel@tonic-gate 			 */
3865*0Sstevel@tonic-gate 			(void) devid_str_decode(dn->devid, &devid_remote, NULL);
3866*0Sstevel@tonic-gate 		}
3867*0Sstevel@tonic-gate 
3868*0Sstevel@tonic-gate 		/* check to make sure using_devid agrees with reality... */
3869*0Sstevel@tonic-gate 		if ((using_devid == 1) && (devid_remote == NULL)) {
3870*0Sstevel@tonic-gate 			/* something went really wrong. Can't process */
3871*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_INVALIDDEVID, sp->setno,
3872*0Sstevel@tonic-gate 			    mynode(), dn->cname, sp->setname);
3873*0Sstevel@tonic-gate 			return;
3874*0Sstevel@tonic-gate 		}
3875*0Sstevel@tonic-gate 
3876*0Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
3877*0Sstevel@tonic-gate 			devid_same = -1;
3878*0Sstevel@tonic-gate 
3879*0Sstevel@tonic-gate 			dn1 = metadrivename_withdrkey(local_sp, sideno,
3880*0Sstevel@tonic-gate 			    dr->dr_key, MD_BASICNAME_OK, ep);
3881*0Sstevel@tonic-gate 
3882*0Sstevel@tonic-gate 			if (dn1 == NULL) {
3883*0Sstevel@tonic-gate 				if (devid_remote)
3884*0Sstevel@tonic-gate 					devid_free(devid_remote);
3885*0Sstevel@tonic-gate 				goto out;
3886*0Sstevel@tonic-gate 			}
3887*0Sstevel@tonic-gate 
3888*0Sstevel@tonic-gate 			if (dn1->devid != NULL && using_devid) {
3889*0Sstevel@tonic-gate 				if (devid_str_decode(dn1->devid,
3890*0Sstevel@tonic-gate 				    &devid_local, NULL) == 0) {
3891*0Sstevel@tonic-gate 					devid_same = devid_compare(devid_remote,
3892*0Sstevel@tonic-gate 					    devid_local);
3893*0Sstevel@tonic-gate 					devid_free(devid_local);
3894*0Sstevel@tonic-gate 				}
3895*0Sstevel@tonic-gate 			}
3896*0Sstevel@tonic-gate 
3897*0Sstevel@tonic-gate 			if (using_devid && devid_same == 0)
3898*0Sstevel@tonic-gate 				break;
3899*0Sstevel@tonic-gate 
3900*0Sstevel@tonic-gate 			if (!using_devid &&
3901*0Sstevel@tonic-gate 			    strcmp(dn->cname, dn1->cname) == 0)
3902*0Sstevel@tonic-gate 				break;
3903*0Sstevel@tonic-gate 		}
3904*0Sstevel@tonic-gate 
3905*0Sstevel@tonic-gate 		if (dr)
3906*0Sstevel@tonic-gate 			dr->dr_flags = new_flags;
3907*0Sstevel@tonic-gate 		if (devid_remote)
3908*0Sstevel@tonic-gate 			devid_free(devid_remote);
3909*0Sstevel@tonic-gate 	}
3910*0Sstevel@tonic-gate out:
3911*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
3912*0Sstevel@tonic-gate 	free_sr(sr);
3913*0Sstevel@tonic-gate }
3914*0Sstevel@tonic-gate 
3915*0Sstevel@tonic-gate /*
3916*0Sstevel@tonic-gate  * update the database count and size field of drive records.
3917*0Sstevel@tonic-gate  */
3918*0Sstevel@tonic-gate bool_t
3919*0Sstevel@tonic-gate mdrpc_upd_dr_flags_common(
3920*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	*args,
3921*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
3922*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
3923*0Sstevel@tonic-gate )
3924*0Sstevel@tonic-gate {
3925*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
3926*0Sstevel@tonic-gate 	int			err;
3927*0Sstevel@tonic-gate 	int			op_mode = W_OK;
3928*0Sstevel@tonic-gate 
3929*0Sstevel@tonic-gate 	/* setup, check permissions */
3930*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
3931*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
3932*0Sstevel@tonic-gate 		return (FALSE);
3933*0Sstevel@tonic-gate 	else if (err != 0)
3934*0Sstevel@tonic-gate 		return (TRUE);
3935*0Sstevel@tonic-gate 
3936*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
3937*0Sstevel@tonic-gate 		return (TRUE);
3938*0Sstevel@tonic-gate 
3939*0Sstevel@tonic-gate 	/* doit */
3940*0Sstevel@tonic-gate 	upd_dr_flags(args->sp, args->drivedescs, args->new_flags, ep);
3941*0Sstevel@tonic-gate 
3942*0Sstevel@tonic-gate 	err = svc_fini(ep);
3943*0Sstevel@tonic-gate 
3944*0Sstevel@tonic-gate 	return (TRUE);
3945*0Sstevel@tonic-gate }
3946*0Sstevel@tonic-gate 
3947*0Sstevel@tonic-gate /*
3948*0Sstevel@tonic-gate  * version 1 of the remote procedure. This procedure is called if the
3949*0Sstevel@tonic-gate  * client is running in version 1. We first convert version 1 arguments
3950*0Sstevel@tonic-gate  * into version 2 arguments and then call the common remote procedure.
3951*0Sstevel@tonic-gate  */
3952*0Sstevel@tonic-gate bool_t
3953*0Sstevel@tonic-gate mdrpc_upd_dr_flags_1_svc(
3954*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_args	*args,
3955*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
3956*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
3957*0Sstevel@tonic-gate )
3958*0Sstevel@tonic-gate {
3959*0Sstevel@tonic-gate 	bool_t				retval;
3960*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	v2_args;
3961*0Sstevel@tonic-gate 
3962*0Sstevel@tonic-gate 	/* allocate memory */
3963*0Sstevel@tonic-gate 	alloc_newdrvdesc(args->drivedescs, &v2_args.drivedescs);
3964*0Sstevel@tonic-gate 
3965*0Sstevel@tonic-gate 	/* build args */
3966*0Sstevel@tonic-gate 	v2_args.cl_sk = args->cl_sk;
3967*0Sstevel@tonic-gate 	v2_args.sp = args->sp;
3968*0Sstevel@tonic-gate 	/* convert v1 args to v2 (revision 1) args */
3969*0Sstevel@tonic-gate 	meta_conv_drvdesc_old2new(args->drivedescs, v2_args.drivedescs);
3970*0Sstevel@tonic-gate 	v2_args.new_flags = args->new_flags;
3971*0Sstevel@tonic-gate 
3972*0Sstevel@tonic-gate 	retval = mdrpc_upd_dr_flags_common(&v2_args, res, rqstp);
3973*0Sstevel@tonic-gate 
3974*0Sstevel@tonic-gate 	free_newdrvdesc(v2_args.drivedescs);
3975*0Sstevel@tonic-gate 
3976*0Sstevel@tonic-gate 	return (retval);
3977*0Sstevel@tonic-gate }
3978*0Sstevel@tonic-gate 
3979*0Sstevel@tonic-gate bool_t
3980*0Sstevel@tonic-gate mdrpc_upd_dr_flags_2_svc(
3981*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args	*args,
3982*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
3983*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
3984*0Sstevel@tonic-gate )
3985*0Sstevel@tonic-gate {
3986*0Sstevel@tonic-gate 	switch (args->rev) {
3987*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
3988*0Sstevel@tonic-gate 		return (mdrpc_upd_dr_flags_common(
3989*0Sstevel@tonic-gate 		    &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
3990*0Sstevel@tonic-gate 	    default:
3991*0Sstevel@tonic-gate 		return (FALSE);
3992*0Sstevel@tonic-gate 	}
3993*0Sstevel@tonic-gate }
3994*0Sstevel@tonic-gate 
3995*0Sstevel@tonic-gate static void
3996*0Sstevel@tonic-gate upd_sr_flags(
3997*0Sstevel@tonic-gate 	mdsetname_t	*sp,
3998*0Sstevel@tonic-gate 	uint_t		new_flags,
3999*0Sstevel@tonic-gate 	md_error_t	*ep
4000*0Sstevel@tonic-gate )
4001*0Sstevel@tonic-gate {
4002*0Sstevel@tonic-gate 	md_set_record	*sr;
4003*0Sstevel@tonic-gate 
4004*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
4005*0Sstevel@tonic-gate 		return;
4006*0Sstevel@tonic-gate 
4007*0Sstevel@tonic-gate 	sr->sr_flags = new_flags;
4008*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
4009*0Sstevel@tonic-gate 	free_sr(sr);
4010*0Sstevel@tonic-gate }
4011*0Sstevel@tonic-gate 
4012*0Sstevel@tonic-gate /*
4013*0Sstevel@tonic-gate  * update the set record flags
4014*0Sstevel@tonic-gate  */
4015*0Sstevel@tonic-gate bool_t
4016*0Sstevel@tonic-gate mdrpc_upd_sr_flags_common(
4017*0Sstevel@tonic-gate 	mdrpc_upd_sr_flags_args	*args,
4018*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4019*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4020*0Sstevel@tonic-gate )
4021*0Sstevel@tonic-gate {
4022*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4023*0Sstevel@tonic-gate 	int			err;
4024*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4025*0Sstevel@tonic-gate 
4026*0Sstevel@tonic-gate 	/* setup, check permissions */
4027*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4028*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4029*0Sstevel@tonic-gate 		return (FALSE);
4030*0Sstevel@tonic-gate 	else if (err != 0)
4031*0Sstevel@tonic-gate 		return (TRUE);
4032*0Sstevel@tonic-gate 
4033*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
4034*0Sstevel@tonic-gate 		return (TRUE);
4035*0Sstevel@tonic-gate 
4036*0Sstevel@tonic-gate 	/* doit */
4037*0Sstevel@tonic-gate 	upd_sr_flags(args->sp, args->new_flags, ep);
4038*0Sstevel@tonic-gate 
4039*0Sstevel@tonic-gate 	err = svc_fini(ep);
4040*0Sstevel@tonic-gate 
4041*0Sstevel@tonic-gate 	return (TRUE);
4042*0Sstevel@tonic-gate }
4043*0Sstevel@tonic-gate 
4044*0Sstevel@tonic-gate bool_t
4045*0Sstevel@tonic-gate mdrpc_upd_sr_flags_1_svc(
4046*0Sstevel@tonic-gate 	mdrpc_upd_sr_flags_args	*args,
4047*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4048*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4049*0Sstevel@tonic-gate )
4050*0Sstevel@tonic-gate {
4051*0Sstevel@tonic-gate 	return (mdrpc_upd_sr_flags_common(args, res, rqstp));
4052*0Sstevel@tonic-gate }
4053*0Sstevel@tonic-gate 
4054*0Sstevel@tonic-gate bool_t
4055*0Sstevel@tonic-gate mdrpc_upd_sr_flags_2_svc(
4056*0Sstevel@tonic-gate 	mdrpc_upd_sr_flags_2_args	*args,
4057*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
4058*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
4059*0Sstevel@tonic-gate )
4060*0Sstevel@tonic-gate {
4061*0Sstevel@tonic-gate 	switch (args->rev) {
4062*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4063*0Sstevel@tonic-gate 		return (mdrpc_upd_sr_flags_common(
4064*0Sstevel@tonic-gate 		    &args->mdrpc_upd_sr_flags_2_args_u.rev1, res, rqstp));
4065*0Sstevel@tonic-gate 	    default:
4066*0Sstevel@tonic-gate 		return (FALSE);
4067*0Sstevel@tonic-gate 	}
4068*0Sstevel@tonic-gate }
4069*0Sstevel@tonic-gate 
4070*0Sstevel@tonic-gate /*
4071*0Sstevel@tonic-gate  * upd_nr_flags updates the node records stored in this node's local mddb
4072*0Sstevel@tonic-gate  * given a node desciptor list and an action.  upd_nr_flags then commits
4073*0Sstevel@tonic-gate  * the node records to the local mddb.
4074*0Sstevel@tonic-gate  *
4075*0Sstevel@tonic-gate  * nd - A linked list of node descriptors that describes the node records
4076*0Sstevel@tonic-gate  *	in this diskset on which the action applies.
4077*0Sstevel@tonic-gate  * flag_action: action to be taken on node records that match the nd list.
4078*0Sstevel@tonic-gate  *	flag_action can be:
4079*0Sstevel@tonic-gate  *		MD_NR_JOIN: set OWN flag in node records
4080*0Sstevel@tonic-gate  *		MD_NR_WITHDRAW: reset OWN flag in node records
4081*0Sstevel@tonic-gate  *		MD_NR_OK: reset ADD flags and set OK flag in node records
4082*0Sstevel@tonic-gate  *		MD_NR_SET: set node record flags based on flags stored in nd
4083*0Sstevel@tonic-gate  *
4084*0Sstevel@tonic-gate  * Typically, the JOIN, WITHDRAW and OK flag_actions are used when setting
4085*0Sstevel@tonic-gate  * all nodes in a diskset to JOIN (add first disk to set), WITHDRAW
4086*0Sstevel@tonic-gate  * (remove last disk from set) or OK (after addition of host to set).
4087*0Sstevel@tonic-gate  *
4088*0Sstevel@tonic-gate  * The SET flag_action is typically used when nodelist contains all nodes
4089*0Sstevel@tonic-gate  * in the diskset, but specific nodes have had flag changes.  An example of
4090*0Sstevel@tonic-gate  * this would be the join/withdraw of a specific node to/from the set.
4091*0Sstevel@tonic-gate  *
4092*0Sstevel@tonic-gate  * Ignore the MD_MN_NODE_RB_JOIN flag if set in node record flag.  This
4093*0Sstevel@tonic-gate  * flag is used by the client to recover in case of failure and should not
4094*0Sstevel@tonic-gate  * be set in the node record flags.
4095*0Sstevel@tonic-gate  */
4096*0Sstevel@tonic-gate static void
4097*0Sstevel@tonic-gate upd_nr_flags(
4098*0Sstevel@tonic-gate 	mdsetname_t	*sp,
4099*0Sstevel@tonic-gate 	md_mnnode_desc	*nd,
4100*0Sstevel@tonic-gate 	uint_t		flag_action,
4101*0Sstevel@tonic-gate 	md_error_t	*ep
4102*0Sstevel@tonic-gate )
4103*0Sstevel@tonic-gate {
4104*0Sstevel@tonic-gate 	mdsetname_t		*local_sp;
4105*0Sstevel@tonic-gate 	md_set_record		*sr;
4106*0Sstevel@tonic-gate 	md_mnset_record		*mnsr;
4107*0Sstevel@tonic-gate 	md_mnnode_desc		*ndp;
4108*0Sstevel@tonic-gate 	md_mnnode_record	*nrp;
4109*0Sstevel@tonic-gate 
4110*0Sstevel@tonic-gate 	if ((local_sp = metasetname(sp->setname, ep)) == NULL)
4111*0Sstevel@tonic-gate 		return;
4112*0Sstevel@tonic-gate 
4113*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
4114*0Sstevel@tonic-gate 
4115*0Sstevel@tonic-gate 	if ((sr = getsetbyname(sp->setname, ep)) == NULL)
4116*0Sstevel@tonic-gate 		return;
4117*0Sstevel@tonic-gate 
4118*0Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr))) {
4119*0Sstevel@tonic-gate 		return;
4120*0Sstevel@tonic-gate 	}
4121*0Sstevel@tonic-gate 	mnsr = (struct md_mnset_record *)sr;
4122*0Sstevel@tonic-gate 
4123*0Sstevel@tonic-gate 	switch (flag_action) {
4124*0Sstevel@tonic-gate 	case MD_NR_JOIN:
4125*0Sstevel@tonic-gate 	case MD_NR_WITHDRAW:
4126*0Sstevel@tonic-gate 	case MD_NR_SET:
4127*0Sstevel@tonic-gate 	case MD_NR_OK:
4128*0Sstevel@tonic-gate 	case MD_NR_DEL:
4129*0Sstevel@tonic-gate 		break;
4130*0Sstevel@tonic-gate 	default:
4131*0Sstevel@tonic-gate 		return;
4132*0Sstevel@tonic-gate 	}
4133*0Sstevel@tonic-gate 
4134*0Sstevel@tonic-gate 	for (ndp = nd; ndp != NULL; ndp = ndp->nd_next) {
4135*0Sstevel@tonic-gate 		/* Find matching node record for given node descriptor */
4136*0Sstevel@tonic-gate 		for (nrp = mnsr->sr_nodechain; nrp != NULL;
4137*0Sstevel@tonic-gate 		    nrp = nrp->nr_next) {
4138*0Sstevel@tonic-gate 			if (ndp->nd_nodeid == nrp->nr_nodeid) {
4139*0Sstevel@tonic-gate 				switch (flag_action) {
4140*0Sstevel@tonic-gate 				case MD_NR_JOIN:
4141*0Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_OWN;
4142*0Sstevel@tonic-gate 					break;
4143*0Sstevel@tonic-gate 				case MD_NR_WITHDRAW:
4144*0Sstevel@tonic-gate 					nrp->nr_flags &= ~MD_MN_NODE_OWN;
4145*0Sstevel@tonic-gate 					break;
4146*0Sstevel@tonic-gate 				case MD_NR_OK:
4147*0Sstevel@tonic-gate 					nrp->nr_flags &=
4148*0Sstevel@tonic-gate 					    ~(MD_MN_NODE_ADD | MD_MN_NODE_DEL);
4149*0Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_OK;
4150*0Sstevel@tonic-gate 					break;
4151*0Sstevel@tonic-gate 				case MD_NR_DEL:
4152*0Sstevel@tonic-gate 					nrp->nr_flags &=
4153*0Sstevel@tonic-gate 					    ~(MD_MN_NODE_OK | MD_MN_NODE_ADD);
4154*0Sstevel@tonic-gate 					nrp->nr_flags |= MD_MN_NODE_DEL;
4155*0Sstevel@tonic-gate 					break;
4156*0Sstevel@tonic-gate 				case MD_NR_SET:
4157*0Sstevel@tonic-gate 					/* Do not set RB_JOIN flag */
4158*0Sstevel@tonic-gate 					nrp->nr_flags =
4159*0Sstevel@tonic-gate 					    ndp->nd_flags & ~MD_MN_NODE_RB_JOIN;
4160*0Sstevel@tonic-gate 					break;
4161*0Sstevel@tonic-gate 				}
4162*0Sstevel@tonic-gate 				break;
4163*0Sstevel@tonic-gate 			}
4164*0Sstevel@tonic-gate 		}
4165*0Sstevel@tonic-gate 	}
4166*0Sstevel@tonic-gate out:
4167*0Sstevel@tonic-gate 	/* Don't increment set genid for node record flag update */
4168*0Sstevel@tonic-gate 	commitset(sr, FALSE, ep);
4169*0Sstevel@tonic-gate 	free_sr(sr);
4170*0Sstevel@tonic-gate }
4171*0Sstevel@tonic-gate 
4172*0Sstevel@tonic-gate /*
4173*0Sstevel@tonic-gate  * init/fini wrapper around upd_nr_flags
4174*0Sstevel@tonic-gate  */
4175*0Sstevel@tonic-gate bool_t
4176*0Sstevel@tonic-gate mdrpc_upd_nr_flags_common(
4177*0Sstevel@tonic-gate 	mdrpc_upd_nr_flags_args	*args,
4178*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4179*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4180*0Sstevel@tonic-gate )
4181*0Sstevel@tonic-gate {
4182*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4183*0Sstevel@tonic-gate 	int			err;
4184*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4185*0Sstevel@tonic-gate 
4186*0Sstevel@tonic-gate 	/* setup, check permissions */
4187*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4188*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4189*0Sstevel@tonic-gate 		return (FALSE);
4190*0Sstevel@tonic-gate 	else if (err != 0)
4191*0Sstevel@tonic-gate 		return (TRUE);
4192*0Sstevel@tonic-gate 
4193*0Sstevel@tonic-gate 	/*
4194*0Sstevel@tonic-gate 	 * During reconfig, node record flags can be updated without
4195*0Sstevel@tonic-gate 	 * locking first.
4196*0Sstevel@tonic-gate 	 */
4197*0Sstevel@tonic-gate 	if (!(args->flags & MNSET_IN_RECONFIG)) {
4198*0Sstevel@tonic-gate 		if (check_set_lock(op_mode, args->cl_sk, ep))
4199*0Sstevel@tonic-gate 			return (TRUE);
4200*0Sstevel@tonic-gate 	}
4201*0Sstevel@tonic-gate 
4202*0Sstevel@tonic-gate 	/* doit */
4203*0Sstevel@tonic-gate 	upd_nr_flags(args->sp, args->nodedescs, args->flag_action, ep);
4204*0Sstevel@tonic-gate 
4205*0Sstevel@tonic-gate 	err = svc_fini(ep);
4206*0Sstevel@tonic-gate 
4207*0Sstevel@tonic-gate 	return (TRUE);
4208*0Sstevel@tonic-gate }
4209*0Sstevel@tonic-gate 
4210*0Sstevel@tonic-gate /*
4211*0Sstevel@tonic-gate  * update the node records using given flag action.
4212*0Sstevel@tonic-gate  */
4213*0Sstevel@tonic-gate bool_t
4214*0Sstevel@tonic-gate mdrpc_upd_nr_flags_2_svc(
4215*0Sstevel@tonic-gate 	mdrpc_upd_nr_flags_2_args	*args,
4216*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
4217*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
4218*0Sstevel@tonic-gate )
4219*0Sstevel@tonic-gate {
4220*0Sstevel@tonic-gate 	switch (args->rev) {
4221*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4222*0Sstevel@tonic-gate 		return (mdrpc_upd_nr_flags_common(
4223*0Sstevel@tonic-gate 		    &args->mdrpc_upd_nr_flags_2_args_u.rev1, res, rqstp));
4224*0Sstevel@tonic-gate 	    default:
4225*0Sstevel@tonic-gate 		return (FALSE);
4226*0Sstevel@tonic-gate 	}
4227*0Sstevel@tonic-gate }
4228*0Sstevel@tonic-gate 
4229*0Sstevel@tonic-gate void
4230*0Sstevel@tonic-gate free_sk(md_setkey_t *skp)
4231*0Sstevel@tonic-gate {
4232*0Sstevel@tonic-gate 	Free(skp->sk_setname);
4233*0Sstevel@tonic-gate 	Free(skp->sk_host);
4234*0Sstevel@tonic-gate 	Free(skp);
4235*0Sstevel@tonic-gate }
4236*0Sstevel@tonic-gate 
4237*0Sstevel@tonic-gate void
4238*0Sstevel@tonic-gate del_sk(set_t setno)
4239*0Sstevel@tonic-gate {
4240*0Sstevel@tonic-gate 	md_setkey_t	*skp;
4241*0Sstevel@tonic-gate 	md_setkey_t	*tskp;
4242*0Sstevel@tonic-gate 
4243*0Sstevel@tonic-gate 	for (skp = tskp = my_svc_sk; skp; tskp = skp, skp = skp->sk_next) {
4244*0Sstevel@tonic-gate 		if (setno == skp->sk_setno) {
4245*0Sstevel@tonic-gate 			if (skp == my_svc_sk)
4246*0Sstevel@tonic-gate 				my_svc_sk = skp->sk_next;
4247*0Sstevel@tonic-gate 			else
4248*0Sstevel@tonic-gate 				tskp->sk_next = skp->sk_next;
4249*0Sstevel@tonic-gate 
4250*0Sstevel@tonic-gate 			Free(skp->sk_setname);
4251*0Sstevel@tonic-gate 			Free(skp->sk_host);
4252*0Sstevel@tonic-gate 			Free(skp);
4253*0Sstevel@tonic-gate 			break;
4254*0Sstevel@tonic-gate 		}
4255*0Sstevel@tonic-gate 	}
4256*0Sstevel@tonic-gate }
4257*0Sstevel@tonic-gate 
4258*0Sstevel@tonic-gate md_setkey_t *
4259*0Sstevel@tonic-gate dupsk(md_setkey_t *skp)
4260*0Sstevel@tonic-gate {
4261*0Sstevel@tonic-gate 	md_setkey_t	*tskp;
4262*0Sstevel@tonic-gate 
4263*0Sstevel@tonic-gate 	tskp = Zalloc(sizeof (md_setkey_t));
4264*0Sstevel@tonic-gate 
4265*0Sstevel@tonic-gate 	*tskp = *skp;
4266*0Sstevel@tonic-gate 	tskp->sk_host = Strdup(skp->sk_host);
4267*0Sstevel@tonic-gate 	tskp->sk_setname = Strdup(skp->sk_setname);
4268*0Sstevel@tonic-gate 
4269*0Sstevel@tonic-gate 	return (tskp);
4270*0Sstevel@tonic-gate }
4271*0Sstevel@tonic-gate 
4272*0Sstevel@tonic-gate md_setkey_t *
4273*0Sstevel@tonic-gate svc_get_setkey(set_t setno)
4274*0Sstevel@tonic-gate {
4275*0Sstevel@tonic-gate 	md_setkey_t	*skp;
4276*0Sstevel@tonic-gate 
4277*0Sstevel@tonic-gate 	for (skp = my_svc_sk; skp != NULL; skp = skp->sk_next)
4278*0Sstevel@tonic-gate 		if (setno == skp->sk_setno)
4279*0Sstevel@tonic-gate 			return (dupsk(skp));
4280*0Sstevel@tonic-gate 	return (NULL);
4281*0Sstevel@tonic-gate }
4282*0Sstevel@tonic-gate 
4283*0Sstevel@tonic-gate void
4284*0Sstevel@tonic-gate svc_set_setkey(md_setkey_t *svc_sk)
4285*0Sstevel@tonic-gate {
4286*0Sstevel@tonic-gate 	md_setkey_t	*skp;
4287*0Sstevel@tonic-gate 
4288*0Sstevel@tonic-gate 	if (my_svc_sk == NULL) {
4289*0Sstevel@tonic-gate 		my_svc_sk = dupsk(svc_sk);
4290*0Sstevel@tonic-gate 		return;
4291*0Sstevel@tonic-gate 	}
4292*0Sstevel@tonic-gate 
4293*0Sstevel@tonic-gate 	for (skp = my_svc_sk; skp->sk_next != NULL; skp = skp->sk_next)
4294*0Sstevel@tonic-gate 		assert(svc_sk->sk_setno != skp->sk_setno);
4295*0Sstevel@tonic-gate 
4296*0Sstevel@tonic-gate 	skp->sk_next = dupsk(svc_sk);
4297*0Sstevel@tonic-gate }
4298*0Sstevel@tonic-gate 
4299*0Sstevel@tonic-gate /*
4300*0Sstevel@tonic-gate  * Unlock the set
4301*0Sstevel@tonic-gate  *
4302*0Sstevel@tonic-gate  * To unlock the set, the user must have the correct key, once this is verified
4303*0Sstevel@tonic-gate  * the set is unlocked and the cached information for the set is flushed.
4304*0Sstevel@tonic-gate  */
4305*0Sstevel@tonic-gate bool_t
4306*0Sstevel@tonic-gate mdrpc_unlock_set_common(
4307*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4308*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4309*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4310*0Sstevel@tonic-gate )
4311*0Sstevel@tonic-gate {
4312*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4313*0Sstevel@tonic-gate 	int			err;
4314*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4315*0Sstevel@tonic-gate 	md_setkey_t		*svc_skp;
4316*0Sstevel@tonic-gate 	md_set_desc		*sd;
4317*0Sstevel@tonic-gate 	mdsetname_t		*sp;
4318*0Sstevel@tonic-gate 	int			multi_node = 0;
4319*0Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
4320*0Sstevel@tonic-gate 
4321*0Sstevel@tonic-gate 	/* setup, check permissions */
4322*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4323*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4324*0Sstevel@tonic-gate 		return (FALSE);
4325*0Sstevel@tonic-gate 	else if (err != 0)
4326*0Sstevel@tonic-gate 		return (TRUE);
4327*0Sstevel@tonic-gate 
4328*0Sstevel@tonic-gate 	/*
4329*0Sstevel@tonic-gate 	 * Is diskset a MN diskset?
4330*0Sstevel@tonic-gate 	 * Don't set error from this check since unlock set can be
4331*0Sstevel@tonic-gate 	 * called after a set has been deleted.
4332*0Sstevel@tonic-gate 	 */
4333*0Sstevel@tonic-gate 	if (((sp = metasetnosetname(args->cl_sk->sk_setno, &xep)) != NULL) &&
4334*0Sstevel@tonic-gate 	    ((sd = metaget_setdesc(sp, &xep)) != NULL)) {
4335*0Sstevel@tonic-gate 		if ((MD_MNSET_DESC(sd))) {
4336*0Sstevel@tonic-gate 			multi_node = 1;
4337*0Sstevel@tonic-gate 		}
4338*0Sstevel@tonic-gate 	}
4339*0Sstevel@tonic-gate 
4340*0Sstevel@tonic-gate 	/* Get the set key, if any */
4341*0Sstevel@tonic-gate 	svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
4342*0Sstevel@tonic-gate 
4343*0Sstevel@tonic-gate 	/* The set is locked */
4344*0Sstevel@tonic-gate 	if (svc_skp != NULL) {
4345*0Sstevel@tonic-gate 
4346*0Sstevel@tonic-gate 		/* Make sure the opener has the right key. */
4347*0Sstevel@tonic-gate 		if (args->cl_sk->sk_key.tv_sec != svc_skp->sk_key.tv_sec ||
4348*0Sstevel@tonic-gate 		    args->cl_sk->sk_key.tv_usec != svc_skp->sk_key.tv_usec) {
4349*0Sstevel@tonic-gate 			(void) mddserror(ep, MDE_DS_ULKSBADKEY,
4350*0Sstevel@tonic-gate 			    svc_skp->sk_setno, mynode(), svc_skp->sk_host,
4351*0Sstevel@tonic-gate 			    svc_skp->sk_setname);
4352*0Sstevel@tonic-gate 			free_sk(svc_skp);
4353*0Sstevel@tonic-gate 			return (TRUE);
4354*0Sstevel@tonic-gate 		}
4355*0Sstevel@tonic-gate 
4356*0Sstevel@tonic-gate 		/* Unlock the set */
4357*0Sstevel@tonic-gate 		del_sk(args->cl_sk->sk_setno);
4358*0Sstevel@tonic-gate 
4359*0Sstevel@tonic-gate 		/* Cleanup */
4360*0Sstevel@tonic-gate 		free_sk(svc_skp);
4361*0Sstevel@tonic-gate 
4362*0Sstevel@tonic-gate 		goto out;
4363*0Sstevel@tonic-gate 	}
4364*0Sstevel@tonic-gate 
4365*0Sstevel@tonic-gate 
4366*0Sstevel@tonic-gate 	/*
4367*0Sstevel@tonic-gate 	 * It is possible on a MN diskset to attempt to unlock a set that
4368*0Sstevel@tonic-gate 	 * is unlocked.  This could occur when the metaset or metadb  command
4369*0Sstevel@tonic-gate 	 * is failing due to another metaset or metadb command running.
4370*0Sstevel@tonic-gate 	 * So, print no warning for MN disksets.
4371*0Sstevel@tonic-gate 	 */
4372*0Sstevel@tonic-gate 	if (multi_node == 0) {
4373*0Sstevel@tonic-gate 		md_eprintf("Warning: set unlocked when unlock_set called!\n");
4374*0Sstevel@tonic-gate 	}
4375*0Sstevel@tonic-gate 
4376*0Sstevel@tonic-gate out:
4377*0Sstevel@tonic-gate 	res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4378*0Sstevel@tonic-gate 
4379*0Sstevel@tonic-gate 	/* Flush the set cache */
4380*0Sstevel@tonic-gate 	sr_cache_flush_setno(args->cl_sk->sk_setno);
4381*0Sstevel@tonic-gate 
4382*0Sstevel@tonic-gate 	return (TRUE);
4383*0Sstevel@tonic-gate }
4384*0Sstevel@tonic-gate 
4385*0Sstevel@tonic-gate bool_t
4386*0Sstevel@tonic-gate mdrpc_unlock_set_1_svc(
4387*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4388*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4389*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4390*0Sstevel@tonic-gate )
4391*0Sstevel@tonic-gate {
4392*0Sstevel@tonic-gate 	return (mdrpc_unlock_set_common(args, res, rqstp));
4393*0Sstevel@tonic-gate }
4394*0Sstevel@tonic-gate 
4395*0Sstevel@tonic-gate bool_t
4396*0Sstevel@tonic-gate mdrpc_unlock_set_2_svc(
4397*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4398*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4399*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4400*0Sstevel@tonic-gate )
4401*0Sstevel@tonic-gate {
4402*0Sstevel@tonic-gate 	return (mdrpc_unlock_set_common(args, res, rqstp));
4403*0Sstevel@tonic-gate }
4404*0Sstevel@tonic-gate 
4405*0Sstevel@tonic-gate /*
4406*0Sstevel@tonic-gate  * Lock the set
4407*0Sstevel@tonic-gate  *
4408*0Sstevel@tonic-gate  * If the user does not hand us a key, then we generate a new key and lock the
4409*0Sstevel@tonic-gate  * set using this new key that was generated, if the user hands us a key then
4410*0Sstevel@tonic-gate  * we use the key to lock the set.
4411*0Sstevel@tonic-gate  */
4412*0Sstevel@tonic-gate bool_t
4413*0Sstevel@tonic-gate mdrpc_lock_set_common(
4414*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4415*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4416*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4417*0Sstevel@tonic-gate )
4418*0Sstevel@tonic-gate {
4419*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4420*0Sstevel@tonic-gate 	int			err;
4421*0Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
4422*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4423*0Sstevel@tonic-gate 	md_setkey_t		*svc_skp;
4424*0Sstevel@tonic-gate 	md_setkey_t		new_sk;
4425*0Sstevel@tonic-gate 	md_set_desc		*sd;
4426*0Sstevel@tonic-gate 	mdsetname_t		*sp;
4427*0Sstevel@tonic-gate 
4428*0Sstevel@tonic-gate 	/* setup, check permissions */
4429*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4430*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4431*0Sstevel@tonic-gate 		return (FALSE);
4432*0Sstevel@tonic-gate 	else if (err != 0)
4433*0Sstevel@tonic-gate 		return (TRUE);
4434*0Sstevel@tonic-gate 
4435*0Sstevel@tonic-gate 	svc_skp = svc_get_setkey(args->cl_sk->sk_setno);
4436*0Sstevel@tonic-gate 
4437*0Sstevel@tonic-gate 	/* The set is unlocked */
4438*0Sstevel@tonic-gate 	if (svc_skp == NULL) {
4439*0Sstevel@tonic-gate 		/* If we have been given a key, use it. */
4440*0Sstevel@tonic-gate 		if (args->cl_sk->sk_key.tv_sec || args->cl_sk->sk_key.tv_usec) {
4441*0Sstevel@tonic-gate 			svc_set_setkey(args->cl_sk);
4442*0Sstevel@tonic-gate 			res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4443*0Sstevel@tonic-gate 			goto out;
4444*0Sstevel@tonic-gate 		}
4445*0Sstevel@tonic-gate 
4446*0Sstevel@tonic-gate 		/* We need to lock it, with a new key */
4447*0Sstevel@tonic-gate 		new_sk = *args->cl_sk;
4448*0Sstevel@tonic-gate 		if (meta_gettimeofday(&new_sk.sk_key) == -1) {
4449*0Sstevel@tonic-gate 			(void) mdsyserror(ep, errno, "meta_gettimeofday()");
4450*0Sstevel@tonic-gate 			mde_perror(&xep, "");
4451*0Sstevel@tonic-gate 			md_exit(NULL, 1);
4452*0Sstevel@tonic-gate 		}
4453*0Sstevel@tonic-gate 		svc_set_setkey(&new_sk);
4454*0Sstevel@tonic-gate 
4455*0Sstevel@tonic-gate 		res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4456*0Sstevel@tonic-gate 		goto out;
4457*0Sstevel@tonic-gate 	}
4458*0Sstevel@tonic-gate 
4459*0Sstevel@tonic-gate 	/*
4460*0Sstevel@tonic-gate 	 * If a MN diskset, the lock_set routine is used as a locking
4461*0Sstevel@tonic-gate 	 * mechanism to keep multiple metaset and/or metadb commads
4462*0Sstevel@tonic-gate 	 * from interfering with each other.  If two metaset/metadb
4463*0Sstevel@tonic-gate 	 * commands are issued at the same time - one will complete
4464*0Sstevel@tonic-gate 	 * and the other command will fail with MDE_DS_NOTNOW_CMD.
4465*0Sstevel@tonic-gate 	 */
4466*0Sstevel@tonic-gate 	if (((sp = metasetnosetname(args->cl_sk->sk_setno, ep)) != NULL) &&
4467*0Sstevel@tonic-gate 	    ((sd = metaget_setdesc(sp, ep)) != NULL) &&
4468*0Sstevel@tonic-gate 	    (MD_MNSET_DESC(sd))) {
4469*0Sstevel@tonic-gate 		(void) mddserror(ep, MDE_DS_NOTNOW_CMD,
4470*0Sstevel@tonic-gate 		    svc_skp->sk_setno, mynode(),
4471*0Sstevel@tonic-gate 		    svc_skp->sk_host, svc_skp->sk_setname);
4472*0Sstevel@tonic-gate 		goto out;
4473*0Sstevel@tonic-gate 	}
4474*0Sstevel@tonic-gate 
4475*0Sstevel@tonic-gate 	md_eprintf("Warning: set locked when lock_set called!\n");
4476*0Sstevel@tonic-gate 
4477*0Sstevel@tonic-gate 	md_eprintf("Lock info:\n");
4478*0Sstevel@tonic-gate 
4479*0Sstevel@tonic-gate 	md_eprintf("\tLock(svc):\n");
4480*0Sstevel@tonic-gate 	md_eprintf("\t\tSetname: %s\n", svc_skp->sk_setname);
4481*0Sstevel@tonic-gate 	md_eprintf("\t\tSetno:   %d\n", svc_skp->sk_setno);
4482*0Sstevel@tonic-gate 	md_eprintf("\t\tHost:    %s\n", svc_skp->sk_host);
4483*0Sstevel@tonic-gate 	md_eprintf("\t\tKey:     %d/%d %s",
4484*0Sstevel@tonic-gate 	    svc_skp->sk_key.tv_sec, svc_skp->sk_key.tv_usec,
4485*0Sstevel@tonic-gate 	    ctime((const time_t *)&svc_skp->sk_key.tv_sec));
4486*0Sstevel@tonic-gate 
4487*0Sstevel@tonic-gate 	md_eprintf("\tLock(cl):\n");
4488*0Sstevel@tonic-gate 	md_eprintf("\t\tSetname: %s\n", args->cl_sk->sk_setname);
4489*0Sstevel@tonic-gate 	md_eprintf("\t\tSetno:   %d\n", args->cl_sk->sk_setno);
4490*0Sstevel@tonic-gate 	md_eprintf("\t\tHost:    %s\n", args->cl_sk->sk_host);
4491*0Sstevel@tonic-gate 	md_eprintf("\t\tKey:     %d/%d %s",
4492*0Sstevel@tonic-gate 	    args->cl_sk->sk_key.tv_sec, args->cl_sk->sk_key.tv_usec,
4493*0Sstevel@tonic-gate 	    ctime((const time_t *)&args->cl_sk->sk_key.tv_sec));
4494*0Sstevel@tonic-gate 
4495*0Sstevel@tonic-gate 	/* The set is locked, do we have the key? */
4496*0Sstevel@tonic-gate 	if (args->cl_sk->sk_key.tv_sec == svc_skp->sk_key.tv_sec &&
4497*0Sstevel@tonic-gate 	    args->cl_sk->sk_key.tv_usec == svc_skp->sk_key.tv_usec) {
4498*0Sstevel@tonic-gate 		res->cl_sk = svc_get_setkey(args->cl_sk->sk_setno);
4499*0Sstevel@tonic-gate 		goto out;
4500*0Sstevel@tonic-gate 	}
4501*0Sstevel@tonic-gate 
4502*0Sstevel@tonic-gate 	/*
4503*0Sstevel@tonic-gate 	 * The set is locked and we do not have the key, so we set up an error.
4504*0Sstevel@tonic-gate 	 */
4505*0Sstevel@tonic-gate 	(void) mddserror(ep, MDE_DS_LKSBADKEY, svc_skp->sk_setno, mynode(),
4506*0Sstevel@tonic-gate 	    svc_skp->sk_host, args->cl_sk->sk_setname);
4507*0Sstevel@tonic-gate 
4508*0Sstevel@tonic-gate out:
4509*0Sstevel@tonic-gate 	if (svc_skp != NULL)
4510*0Sstevel@tonic-gate 		free_sk(svc_skp);
4511*0Sstevel@tonic-gate 
4512*0Sstevel@tonic-gate 	/* Flush the set cache */
4513*0Sstevel@tonic-gate 	sr_cache_flush_setno(args->cl_sk->sk_setno);
4514*0Sstevel@tonic-gate 
4515*0Sstevel@tonic-gate 	return (TRUE);
4516*0Sstevel@tonic-gate }
4517*0Sstevel@tonic-gate 
4518*0Sstevel@tonic-gate bool_t
4519*0Sstevel@tonic-gate mdrpc_lock_set_1_svc(
4520*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4521*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4522*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4523*0Sstevel@tonic-gate )
4524*0Sstevel@tonic-gate {
4525*0Sstevel@tonic-gate 	return (mdrpc_lock_set_common(args, res, rqstp));
4526*0Sstevel@tonic-gate }
4527*0Sstevel@tonic-gate 
4528*0Sstevel@tonic-gate bool_t
4529*0Sstevel@tonic-gate mdrpc_lock_set_2_svc(
4530*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4531*0Sstevel@tonic-gate 	mdrpc_setlock_res	*res,
4532*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4533*0Sstevel@tonic-gate )
4534*0Sstevel@tonic-gate {
4535*0Sstevel@tonic-gate 	return (mdrpc_lock_set_common(args, res, rqstp));
4536*0Sstevel@tonic-gate }
4537*0Sstevel@tonic-gate 
4538*0Sstevel@tonic-gate static void
4539*0Sstevel@tonic-gate updmeds(
4540*0Sstevel@tonic-gate 	char		*setname,
4541*0Sstevel@tonic-gate 	md_h_arr_t	*medp,
4542*0Sstevel@tonic-gate 	int		version,	/* RPC version of calling routine */
4543*0Sstevel@tonic-gate 	md_error_t	*ep
4544*0Sstevel@tonic-gate )
4545*0Sstevel@tonic-gate {
4546*0Sstevel@tonic-gate 	mddb_userreq_t		req;
4547*0Sstevel@tonic-gate 	md_set_record		*sr;
4548*0Sstevel@tonic-gate 	mddb_med_parm_t		mp;
4549*0Sstevel@tonic-gate 
4550*0Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
4551*0Sstevel@tonic-gate 		return;
4552*0Sstevel@tonic-gate 
4553*0Sstevel@tonic-gate 	sr->sr_med = *medp;			/* structure assignment */
4554*0Sstevel@tonic-gate 
4555*0Sstevel@tonic-gate 	(void) memset(&req, '\0', sizeof (req));
4556*0Sstevel@tonic-gate 
4557*0Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
4558*0Sstevel@tonic-gate 	/* Do MN operation if rpc version supports it and if a MN set */
4559*0Sstevel@tonic-gate 	if ((version != METAD_VERSION) && (MD_MNSET_REC(sr))) {
4560*0Sstevel@tonic-gate 		req.ur_size = sizeof (struct md_mnset_record);
4561*0Sstevel@tonic-gate 	} else {
4562*0Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
4563*0Sstevel@tonic-gate 	}
4564*0Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
4565*0Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
4566*0Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
4567*0Sstevel@tonic-gate 		free_sr(sr);
4568*0Sstevel@tonic-gate 		return;
4569*0Sstevel@tonic-gate 	}
4570*0Sstevel@tonic-gate 
4571*0Sstevel@tonic-gate 	commitset(sr, TRUE, ep);
4572*0Sstevel@tonic-gate 
4573*0Sstevel@tonic-gate 	/*
4574*0Sstevel@tonic-gate 	 * If a MN disket, send the mediator list to the kernel.
4575*0Sstevel@tonic-gate 	 */
4576*0Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
4577*0Sstevel@tonic-gate 		(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
4578*0Sstevel@tonic-gate 		mp.med_setno = sr->sr_setno;
4579*0Sstevel@tonic-gate 		if (meta_h2hi(medp, &mp.med, ep)) {
4580*0Sstevel@tonic-gate 			free_sr(sr);
4581*0Sstevel@tonic-gate 			return;
4582*0Sstevel@tonic-gate 		}
4583*0Sstevel@tonic-gate 
4584*0Sstevel@tonic-gate 		/* Resolve the IP addresses for the host list */
4585*0Sstevel@tonic-gate 		if (meta_med_hnm2ip(&mp.med, ep)) {
4586*0Sstevel@tonic-gate 			free_sr(sr);
4587*0Sstevel@tonic-gate 			return;
4588*0Sstevel@tonic-gate 		}
4589*0Sstevel@tonic-gate 
4590*0Sstevel@tonic-gate 		/* If node not yet joined to set, failure is ok. */
4591*0Sstevel@tonic-gate 		if (metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL) != 0) {
4592*0Sstevel@tonic-gate 			if (!mdismddberror(&mp.med_mde, MDE_DB_NOTOWNER)) {
4593*0Sstevel@tonic-gate 				(void) mdstealerror(ep, &mp.med_mde);
4594*0Sstevel@tonic-gate 			}
4595*0Sstevel@tonic-gate 		}
4596*0Sstevel@tonic-gate 	}
4597*0Sstevel@tonic-gate 	free_sr(sr);
4598*0Sstevel@tonic-gate }
4599*0Sstevel@tonic-gate 
4600*0Sstevel@tonic-gate /*
4601*0Sstevel@tonic-gate  * Update the mediator data in the set record
4602*0Sstevel@tonic-gate  */
4603*0Sstevel@tonic-gate bool_t
4604*0Sstevel@tonic-gate mdrpc_updmeds_common(
4605*0Sstevel@tonic-gate 	mdrpc_updmeds_args	*args,
4606*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4607*0Sstevel@tonic-gate 	struct svc_req		*rqstp,		/* RPC stuff */
4608*0Sstevel@tonic-gate 	int			version		/* RPC version */
4609*0Sstevel@tonic-gate )
4610*0Sstevel@tonic-gate {
4611*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4612*0Sstevel@tonic-gate 	int			err;
4613*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4614*0Sstevel@tonic-gate 
4615*0Sstevel@tonic-gate 	/* setup, check permissions */
4616*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4617*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4618*0Sstevel@tonic-gate 		return (FALSE);
4619*0Sstevel@tonic-gate 	else if (err != 0)
4620*0Sstevel@tonic-gate 		return (TRUE);
4621*0Sstevel@tonic-gate 
4622*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
4623*0Sstevel@tonic-gate 		return (TRUE);
4624*0Sstevel@tonic-gate 
4625*0Sstevel@tonic-gate 	/* doit */
4626*0Sstevel@tonic-gate 	updmeds(args->sp->setname, &args->meds, version, ep);
4627*0Sstevel@tonic-gate 
4628*0Sstevel@tonic-gate 	err = svc_fini(ep);
4629*0Sstevel@tonic-gate 
4630*0Sstevel@tonic-gate 	return (TRUE);
4631*0Sstevel@tonic-gate }
4632*0Sstevel@tonic-gate 
4633*0Sstevel@tonic-gate bool_t
4634*0Sstevel@tonic-gate mdrpc_updmeds_1_svc(
4635*0Sstevel@tonic-gate 	mdrpc_updmeds_args	*args,
4636*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4637*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4638*0Sstevel@tonic-gate )
4639*0Sstevel@tonic-gate {
4640*0Sstevel@tonic-gate 	/* Pass RPC version (METAD_VERSION) to common routine */
4641*0Sstevel@tonic-gate 	return (mdrpc_updmeds_common(args, res, rqstp, METAD_VERSION));
4642*0Sstevel@tonic-gate }
4643*0Sstevel@tonic-gate 
4644*0Sstevel@tonic-gate bool_t
4645*0Sstevel@tonic-gate mdrpc_updmeds_2_svc(
4646*0Sstevel@tonic-gate 	mdrpc_updmeds_2_args	*args,
4647*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4648*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4649*0Sstevel@tonic-gate )
4650*0Sstevel@tonic-gate {
4651*0Sstevel@tonic-gate 	switch (args->rev) {
4652*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4653*0Sstevel@tonic-gate 		/* Pass RPC version (METAD_VERSION_DEVID) to common routine */
4654*0Sstevel@tonic-gate 		return (mdrpc_updmeds_common(
4655*0Sstevel@tonic-gate 		    &args->mdrpc_updmeds_2_args_u.rev1, res,
4656*0Sstevel@tonic-gate 		    rqstp, METAD_VERSION_DEVID));
4657*0Sstevel@tonic-gate 	    default:
4658*0Sstevel@tonic-gate 		return (FALSE);
4659*0Sstevel@tonic-gate 	}
4660*0Sstevel@tonic-gate }
4661*0Sstevel@tonic-gate 
4662*0Sstevel@tonic-gate /*
4663*0Sstevel@tonic-gate  * Call routines to suspend, reinit and resume mdcommd.
4664*0Sstevel@tonic-gate  * Called during metaset and metadb command.
4665*0Sstevel@tonic-gate  * NOT called during reconfig cycle.
4666*0Sstevel@tonic-gate  */
4667*0Sstevel@tonic-gate bool_t
4668*0Sstevel@tonic-gate mdrpc_mdcommdctl_2_svc(
4669*0Sstevel@tonic-gate 	mdrpc_mdcommdctl_2_args	*args,
4670*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4671*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4672*0Sstevel@tonic-gate )
4673*0Sstevel@tonic-gate {
4674*0Sstevel@tonic-gate 	mdrpc_mdcommdctl_args	*args_cc;
4675*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4676*0Sstevel@tonic-gate 	int			err;
4677*0Sstevel@tonic-gate 	int			op_mode = R_OK;
4678*0Sstevel@tonic-gate 	int			suspend_ret;
4679*0Sstevel@tonic-gate 
4680*0Sstevel@tonic-gate 	switch (args->rev) {
4681*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4682*0Sstevel@tonic-gate 		/* setup, check permissions */
4683*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
4684*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4685*0Sstevel@tonic-gate 			return (FALSE);
4686*0Sstevel@tonic-gate 		else if (err != 0)
4687*0Sstevel@tonic-gate 			return (TRUE);
4688*0Sstevel@tonic-gate 
4689*0Sstevel@tonic-gate 		args_cc = &(args->mdrpc_mdcommdctl_2_args_u.rev1);
4690*0Sstevel@tonic-gate 		switch (args_cc->flag_action) {
4691*0Sstevel@tonic-gate 			case COMMDCTL_SUSPEND:
4692*0Sstevel@tonic-gate 				suspend_ret = mdmn_suspend(args_cc->setno,
4693*0Sstevel@tonic-gate 				    args_cc->class);
4694*0Sstevel@tonic-gate 				if (suspend_ret != 0) {
4695*0Sstevel@tonic-gate 					(void) mddserror(ep, suspend_ret,
4696*0Sstevel@tonic-gate 					    args_cc->setno, mynode(),
4697*0Sstevel@tonic-gate 					    NULL, mynode());
4698*0Sstevel@tonic-gate 				}
4699*0Sstevel@tonic-gate 				break;
4700*0Sstevel@tonic-gate 			case COMMDCTL_RESUME:
4701*0Sstevel@tonic-gate 				if (mdmn_resume(args_cc->setno,
4702*0Sstevel@tonic-gate 				    args_cc->class, args_cc->flags)) {
4703*0Sstevel@tonic-gate 					(void) mddserror(ep,
4704*0Sstevel@tonic-gate 					    MDE_DS_COMMDCTL_RESUME_FAIL,
4705*0Sstevel@tonic-gate 					    args_cc->setno, mynode(),
4706*0Sstevel@tonic-gate 					    NULL, mynode());
4707*0Sstevel@tonic-gate 				}
4708*0Sstevel@tonic-gate 				break;
4709*0Sstevel@tonic-gate 			case COMMDCTL_REINIT:
4710*0Sstevel@tonic-gate 				if (mdmn_reinit_set(args_cc->setno)) {
4711*0Sstevel@tonic-gate 					(void) mddserror(ep,
4712*0Sstevel@tonic-gate 					    MDE_DS_COMMDCTL_REINIT_FAIL,
4713*0Sstevel@tonic-gate 					    args_cc->setno, mynode(),
4714*0Sstevel@tonic-gate 					    NULL, mynode());
4715*0Sstevel@tonic-gate 				}
4716*0Sstevel@tonic-gate 				break;
4717*0Sstevel@tonic-gate 		}
4718*0Sstevel@tonic-gate 		err = svc_fini(ep);
4719*0Sstevel@tonic-gate 		return (TRUE);
4720*0Sstevel@tonic-gate 
4721*0Sstevel@tonic-gate 	    default:
4722*0Sstevel@tonic-gate 		return (FALSE);
4723*0Sstevel@tonic-gate 	}
4724*0Sstevel@tonic-gate }
4725*0Sstevel@tonic-gate 
4726*0Sstevel@tonic-gate /*
4727*0Sstevel@tonic-gate  * Return TRUE if set is stale.
4728*0Sstevel@tonic-gate  */
4729*0Sstevel@tonic-gate bool_t
4730*0Sstevel@tonic-gate mdrpc_mn_is_stale_2_svc(
4731*0Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
4732*0Sstevel@tonic-gate 	mdrpc_bool_res		*res,
4733*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4734*0Sstevel@tonic-gate )
4735*0Sstevel@tonic-gate {
4736*0Sstevel@tonic-gate 	md_error_t	*ep = &res->status;
4737*0Sstevel@tonic-gate 	mddb_config_t	c;
4738*0Sstevel@tonic-gate 	int		err;
4739*0Sstevel@tonic-gate 	int		op_mode = R_OK;
4740*0Sstevel@tonic-gate 
4741*0Sstevel@tonic-gate 	(void) memset(&c, 0, sizeof (c));
4742*0Sstevel@tonic-gate 	switch (args->rev) {
4743*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4744*0Sstevel@tonic-gate 		c.c_id = 0;
4745*0Sstevel@tonic-gate 		c.c_setno = args->mdrpc_setno_2_args_u.rev1.setno;
4746*0Sstevel@tonic-gate 
4747*0Sstevel@tonic-gate 		/* setup, check permissions */
4748*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
4749*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4750*0Sstevel@tonic-gate 			return (FALSE);
4751*0Sstevel@tonic-gate 		else if (err != 0)
4752*0Sstevel@tonic-gate 			return (TRUE);
4753*0Sstevel@tonic-gate 
4754*0Sstevel@tonic-gate 		if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
4755*0Sstevel@tonic-gate 			mdstealerror(ep, &c.c_mde);
4756*0Sstevel@tonic-gate 			return (TRUE);
4757*0Sstevel@tonic-gate 		}
4758*0Sstevel@tonic-gate 
4759*0Sstevel@tonic-gate 		if (c.c_flags & MDDB_C_STALE) {
4760*0Sstevel@tonic-gate 			res->value = TRUE;
4761*0Sstevel@tonic-gate 		} else {
4762*0Sstevel@tonic-gate 			res->value = FALSE;
4763*0Sstevel@tonic-gate 		}
4764*0Sstevel@tonic-gate 
4765*0Sstevel@tonic-gate 		err = svc_fini(ep);
4766*0Sstevel@tonic-gate 		return (TRUE);
4767*0Sstevel@tonic-gate 
4768*0Sstevel@tonic-gate 	    default:
4769*0Sstevel@tonic-gate 		return (FALSE);
4770*0Sstevel@tonic-gate 	}
4771*0Sstevel@tonic-gate }
4772*0Sstevel@tonic-gate 
4773*0Sstevel@tonic-gate /*
4774*0Sstevel@tonic-gate  * Clear out all clnt_locks held by all MN disksets.
4775*0Sstevel@tonic-gate  * This is only used during a reconfig cycle.
4776*0Sstevel@tonic-gate  */
4777*0Sstevel@tonic-gate /* ARGSUSED */
4778*0Sstevel@tonic-gate mdrpc_clr_mnsetlock_2_svc(
4779*0Sstevel@tonic-gate 	mdrpc_null_args		*args,
4780*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
4781*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4782*0Sstevel@tonic-gate )
4783*0Sstevel@tonic-gate {
4784*0Sstevel@tonic-gate 	set_t			max_sets, setno;
4785*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4786*0Sstevel@tonic-gate 	int			err;
4787*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4788*0Sstevel@tonic-gate 	mdsetname_t		*sp;
4789*0Sstevel@tonic-gate 
4790*0Sstevel@tonic-gate 	/* setup, check permissions */
4791*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4792*0Sstevel@tonic-gate 
4793*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4794*0Sstevel@tonic-gate 		return (FALSE);
4795*0Sstevel@tonic-gate 	else if (err != 0)
4796*0Sstevel@tonic-gate 		return (TRUE);
4797*0Sstevel@tonic-gate 
4798*0Sstevel@tonic-gate 	/*
4799*0Sstevel@tonic-gate 	 * Walk through all possible disksets.
4800*0Sstevel@tonic-gate 	 * For each MN set, delete all keys associated with that set.
4801*0Sstevel@tonic-gate 	 */
4802*0Sstevel@tonic-gate 	if ((max_sets = get_max_sets(ep)) == 0) {
4803*0Sstevel@tonic-gate 		return (TRUE);
4804*0Sstevel@tonic-gate 	}
4805*0Sstevel@tonic-gate 
4806*0Sstevel@tonic-gate 	/* start walking through all possible disksets */
4807*0Sstevel@tonic-gate 	for (setno = 1; setno < max_sets; setno++) {
4808*0Sstevel@tonic-gate 		if ((sp = metasetnosetname(setno, ep)) == NULL) {
4809*0Sstevel@tonic-gate 			if (mdiserror(ep, MDE_NO_SET)) {
4810*0Sstevel@tonic-gate 				/* No set for this setno - continue */
4811*0Sstevel@tonic-gate 				mdclrerror(ep);
4812*0Sstevel@tonic-gate 				continue;
4813*0Sstevel@tonic-gate 			} else {
4814*0Sstevel@tonic-gate 				mde_perror(ep, gettext(
4815*0Sstevel@tonic-gate 				    "Unable to get set %s information"),
4816*0Sstevel@tonic-gate 				    sp->setname);
4817*0Sstevel@tonic-gate 				mdclrerror(ep);
4818*0Sstevel@tonic-gate 				continue;
4819*0Sstevel@tonic-gate 			}
4820*0Sstevel@tonic-gate 		}
4821*0Sstevel@tonic-gate 
4822*0Sstevel@tonic-gate 		/* only check multi-node disksets */
4823*0Sstevel@tonic-gate 		if (!meta_is_mn_set(sp, ep)) {
4824*0Sstevel@tonic-gate 			mdclrerror(ep);
4825*0Sstevel@tonic-gate 			continue;
4826*0Sstevel@tonic-gate 		}
4827*0Sstevel@tonic-gate 
4828*0Sstevel@tonic-gate 		/* Delete keys associated with rpc.metad clnt_lock */
4829*0Sstevel@tonic-gate 		del_sk(setno);
4830*0Sstevel@tonic-gate 	}
4831*0Sstevel@tonic-gate 
4832*0Sstevel@tonic-gate 	*ep = mdnullerror;
4833*0Sstevel@tonic-gate 
4834*0Sstevel@tonic-gate 	err = svc_fini(ep);
4835*0Sstevel@tonic-gate 
4836*0Sstevel@tonic-gate 	return (TRUE);
4837*0Sstevel@tonic-gate }
4838*0Sstevel@tonic-gate 
4839*0Sstevel@tonic-gate /*
4840*0Sstevel@tonic-gate  * Get drive desc on this host for given setno.
4841*0Sstevel@tonic-gate  * This is only used during a reconfig cycle.
4842*0Sstevel@tonic-gate  * Returns a drive desc structure for the given mdsetname
4843*0Sstevel@tonic-gate  * from this host.
4844*0Sstevel@tonic-gate  *
4845*0Sstevel@tonic-gate  * Returned drive desc structure is partially filled in with
4846*0Sstevel@tonic-gate  * the drive name but is not filled in with any other strings
4847*0Sstevel@tonic-gate  * in the drivename structure.
4848*0Sstevel@tonic-gate  */
4849*0Sstevel@tonic-gate bool_t
4850*0Sstevel@tonic-gate mdrpc_getdrivedesc_2_svc(
4851*0Sstevel@tonic-gate 	mdrpc_sp_2_args		*args,
4852*0Sstevel@tonic-gate 	mdrpc_getdrivedesc_res 	*res,
4853*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
4854*0Sstevel@tonic-gate )
4855*0Sstevel@tonic-gate {
4856*0Sstevel@tonic-gate 	md_drive_desc		*dd;
4857*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4858*0Sstevel@tonic-gate 	int			err;
4859*0Sstevel@tonic-gate 	int			op_mode = R_OK;
4860*0Sstevel@tonic-gate 	mdsetname_t		*my_sp;
4861*0Sstevel@tonic-gate 	mdrpc_sp_args		*args_r1;
4862*0Sstevel@tonic-gate 
4863*0Sstevel@tonic-gate 	switch (args->rev) {
4864*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
4865*0Sstevel@tonic-gate 		/* setup, check permissions */
4866*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
4867*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4868*0Sstevel@tonic-gate 			return (FALSE);
4869*0Sstevel@tonic-gate 		else if (err != 0)
4870*0Sstevel@tonic-gate 			return (TRUE);
4871*0Sstevel@tonic-gate 
4872*0Sstevel@tonic-gate 		/* doit */
4873*0Sstevel@tonic-gate 		args_r1 = &args->mdrpc_sp_2_args_u.rev1;
4874*0Sstevel@tonic-gate 		if ((my_sp = metasetname(args_r1->sp->setname, ep)) == NULL)
4875*0Sstevel@tonic-gate 			return (TRUE);
4876*0Sstevel@tonic-gate 
4877*0Sstevel@tonic-gate 		dd = metaget_drivedesc(my_sp,
4878*0Sstevel@tonic-gate 			(MD_BASICNAME_OK | PRINT_FAST), ep);
4879*0Sstevel@tonic-gate 
4880*0Sstevel@tonic-gate 		res->dd = dd_list_dup(dd);
4881*0Sstevel@tonic-gate 
4882*0Sstevel@tonic-gate 		err = svc_fini(ep);
4883*0Sstevel@tonic-gate 
4884*0Sstevel@tonic-gate 		return (TRUE);
4885*0Sstevel@tonic-gate 	    default:
4886*0Sstevel@tonic-gate 		return (FALSE);
4887*0Sstevel@tonic-gate 	}
4888*0Sstevel@tonic-gate }
4889*0Sstevel@tonic-gate 
4890*0Sstevel@tonic-gate /*
4891*0Sstevel@tonic-gate  * Update drive records given list from master during reconfig.
4892*0Sstevel@tonic-gate  * Make this node's list match the master's list which may include
4893*0Sstevel@tonic-gate  * deleting a drive record that is known by this node and not known
4894*0Sstevel@tonic-gate  * by the master node.
4895*0Sstevel@tonic-gate  *
4896*0Sstevel@tonic-gate  * Sync up the set/node/drive record genids to match the genid
4897*0Sstevel@tonic-gate  * passed in the dd structure (all genids in this structure
4898*0Sstevel@tonic-gate  * are the same).
4899*0Sstevel@tonic-gate  */
4900*0Sstevel@tonic-gate bool_t
4901*0Sstevel@tonic-gate mdrpc_upd_dr_reconfig_common(
4902*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args_r1	*args,
4903*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
4904*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
4905*0Sstevel@tonic-gate )
4906*0Sstevel@tonic-gate {
4907*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
4908*0Sstevel@tonic-gate 	int			err;
4909*0Sstevel@tonic-gate 	mdsetname_t		*local_sp;
4910*0Sstevel@tonic-gate 	md_set_record		*sr;
4911*0Sstevel@tonic-gate 	md_mnset_record		*mnsr;
4912*0Sstevel@tonic-gate 	md_drive_record		*dr, *dr_placeholder = NULL;
4913*0Sstevel@tonic-gate 	md_drive_desc		*dd;
4914*0Sstevel@tonic-gate 	mddrivename_t		*dn, *dn1;
4915*0Sstevel@tonic-gate 	side_t			sideno;
4916*0Sstevel@tonic-gate 	md_mnnode_record	*nrp;
4917*0Sstevel@tonic-gate 	int			op_mode = W_OK;
4918*0Sstevel@tonic-gate 	int			change = 0;
4919*0Sstevel@tonic-gate 
4920*0Sstevel@tonic-gate 	/* setup, check permissions */
4921*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
4922*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
4923*0Sstevel@tonic-gate 		return (FALSE);
4924*0Sstevel@tonic-gate 	else if (err != 0)
4925*0Sstevel@tonic-gate 		return (TRUE);
4926*0Sstevel@tonic-gate 
4927*0Sstevel@tonic-gate 	if ((local_sp = metasetname(args->sp->setname, ep)) == NULL)
4928*0Sstevel@tonic-gate 		return (TRUE);
4929*0Sstevel@tonic-gate 
4930*0Sstevel@tonic-gate 	metaflushsetname(local_sp);
4931*0Sstevel@tonic-gate 
4932*0Sstevel@tonic-gate 	if ((sideno = getmyside(local_sp, ep)) == MD_SIDEWILD)
4933*0Sstevel@tonic-gate 		return (TRUE);
4934*0Sstevel@tonic-gate 
4935*0Sstevel@tonic-gate 	if ((sr = getsetbyname(args->sp->setname, ep)) == NULL)
4936*0Sstevel@tonic-gate 		return (TRUE);
4937*0Sstevel@tonic-gate 
4938*0Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr))) {
4939*0Sstevel@tonic-gate 		free_sr(sr);
4940*0Sstevel@tonic-gate 		return (TRUE);
4941*0Sstevel@tonic-gate 	}
4942*0Sstevel@tonic-gate 
4943*0Sstevel@tonic-gate 	mnsr = (md_mnset_record *)sr;
4944*0Sstevel@tonic-gate 	/* Setup genid on set and node records */
4945*0Sstevel@tonic-gate 	if (args->drivedescs) {
4946*0Sstevel@tonic-gate 		if (mnsr->sr_genid != args->drivedescs->dd_genid) {
4947*0Sstevel@tonic-gate 			change = 1;
4948*0Sstevel@tonic-gate 			mnsr->sr_genid = args->drivedescs->dd_genid;
4949*0Sstevel@tonic-gate 		}
4950*0Sstevel@tonic-gate 		nrp = mnsr->sr_nodechain;
4951*0Sstevel@tonic-gate 		while (nrp) {
4952*0Sstevel@tonic-gate 			if (nrp->nr_genid != args->drivedescs->dd_genid) {
4953*0Sstevel@tonic-gate 				change = 1;
4954*0Sstevel@tonic-gate 				nrp->nr_genid = args->drivedescs->dd_genid;
4955*0Sstevel@tonic-gate 			}
4956*0Sstevel@tonic-gate 			nrp = nrp->nr_next;
4957*0Sstevel@tonic-gate 		}
4958*0Sstevel@tonic-gate 	}
4959*0Sstevel@tonic-gate 	for (dr = mnsr->sr_drivechain; dr; dr = dr->dr_next) {
4960*0Sstevel@tonic-gate 		dn1 = metadrivename_withdrkey(local_sp, sideno,
4961*0Sstevel@tonic-gate 		    dr->dr_key, (MD_BASICNAME_OK | PRINT_FAST), ep);
4962*0Sstevel@tonic-gate 		if (dn1 == NULL)
4963*0Sstevel@tonic-gate 			goto out;
4964*0Sstevel@tonic-gate 		for (dd = args->drivedescs; dd != NULL; dd = dd->dd_next) {
4965*0Sstevel@tonic-gate 			dn = dd->dd_dnp;
4966*0Sstevel@tonic-gate 			/* Found this node's drive rec to match dd */
4967*0Sstevel@tonic-gate 			if (strcmp(dn->cname, dn1->cname) == 0)
4968*0Sstevel@tonic-gate 				break;
4969*0Sstevel@tonic-gate 		}
4970*0Sstevel@tonic-gate 
4971*0Sstevel@tonic-gate 		/*
4972*0Sstevel@tonic-gate 		 * If drive found in master's list, make slave match master.
4973*0Sstevel@tonic-gate 		 * If drive not found in master's list, remove drive.
4974*0Sstevel@tonic-gate 		 */
4975*0Sstevel@tonic-gate 		if (dd) {
4976*0Sstevel@tonic-gate 			if ((dr->dr_flags != dd->dd_flags) ||
4977*0Sstevel@tonic-gate 			    (dr->dr_genid != dd->dd_genid)) {
4978*0Sstevel@tonic-gate 				change = 1;
4979*0Sstevel@tonic-gate 				dr->dr_flags = dd->dd_flags;
4980*0Sstevel@tonic-gate 				dr->dr_genid = dd->dd_genid;
4981*0Sstevel@tonic-gate 			}
4982*0Sstevel@tonic-gate 		} else {
4983*0Sstevel@tonic-gate 			/*
4984*0Sstevel@tonic-gate 			 * Delete entry from linked list.  Need to use
4985*0Sstevel@tonic-gate 			 * dr_placeholder so that dr->dr_next points to
4986*0Sstevel@tonic-gate 			 * the next drive record in the list.
4987*0Sstevel@tonic-gate 			 */
4988*0Sstevel@tonic-gate 			if (dr_placeholder == NULL) {
4989*0Sstevel@tonic-gate 				dr_placeholder =
4990*0Sstevel@tonic-gate 					Zalloc(sizeof (md_drive_record));
4991*0Sstevel@tonic-gate 			}
4992*0Sstevel@tonic-gate 			dr_placeholder->dr_next = dr->dr_next;
4993*0Sstevel@tonic-gate 			dr_placeholder->dr_key = dr->dr_key;
4994*0Sstevel@tonic-gate 			sr_del_drv(sr, dr->dr_selfid);
4995*0Sstevel@tonic-gate 			(void) del_sideno_sidenm(dr_placeholder->dr_key,
4996*0Sstevel@tonic-gate 				sideno, ep);
4997*0Sstevel@tonic-gate 			change = 1;
4998*0Sstevel@tonic-gate 			dr = dr_placeholder;
4999*0Sstevel@tonic-gate 		}
5000*0Sstevel@tonic-gate 	}
5001*0Sstevel@tonic-gate out:
5002*0Sstevel@tonic-gate 	/* If incore records are correct, don't need to write to disk */
5003*0Sstevel@tonic-gate 	if (change) {
5004*0Sstevel@tonic-gate 		/* Don't increment the genid in commitset */
5005*0Sstevel@tonic-gate 		commitset(sr, FALSE, ep);
5006*0Sstevel@tonic-gate 	}
5007*0Sstevel@tonic-gate 	free_sr(sr);
5008*0Sstevel@tonic-gate 
5009*0Sstevel@tonic-gate 	err = svc_fini(ep);
5010*0Sstevel@tonic-gate 
5011*0Sstevel@tonic-gate 	if (dr_placeholder != NULL)
5012*0Sstevel@tonic-gate 		Free(dr_placeholder);
5013*0Sstevel@tonic-gate 
5014*0Sstevel@tonic-gate 	return (TRUE);
5015*0Sstevel@tonic-gate }
5016*0Sstevel@tonic-gate 
5017*0Sstevel@tonic-gate /*
5018*0Sstevel@tonic-gate  * Version 2 routine to update this node's drive records based on
5019*0Sstevel@tonic-gate  * list passed in from master node.
5020*0Sstevel@tonic-gate  */
5021*0Sstevel@tonic-gate bool_t
5022*0Sstevel@tonic-gate mdrpc_upd_dr_reconfig_2_svc(
5023*0Sstevel@tonic-gate 	mdrpc_upd_dr_flags_2_args	*args,
5024*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
5025*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
5026*0Sstevel@tonic-gate )
5027*0Sstevel@tonic-gate {
5028*0Sstevel@tonic-gate 	switch (args->rev) {
5029*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5030*0Sstevel@tonic-gate 		return (mdrpc_upd_dr_reconfig_common(
5031*0Sstevel@tonic-gate 		    &args->mdrpc_upd_dr_flags_2_args_u.rev1, res, rqstp));
5032*0Sstevel@tonic-gate 	    default:
5033*0Sstevel@tonic-gate 		return (FALSE);
5034*0Sstevel@tonic-gate 	}
5035*0Sstevel@tonic-gate }
5036*0Sstevel@tonic-gate 
5037*0Sstevel@tonic-gate /*
5038*0Sstevel@tonic-gate  * reset mirror owner for mirrors owned by deleted
5039*0Sstevel@tonic-gate  * or withdrawn host(s).  Hosts being deleted or
5040*0Sstevel@tonic-gate  * withdrawn are designated by nodeid since host is
5041*0Sstevel@tonic-gate  * already deleted or withdrawn from set and may not
5042*0Sstevel@tonic-gate  * be able to translate between a nodename and a nodeid.
5043*0Sstevel@tonic-gate  * If an error occurs, ep will be set to that error information.
5044*0Sstevel@tonic-gate  */
5045*0Sstevel@tonic-gate static void
5046*0Sstevel@tonic-gate reset_mirror_owner(
5047*0Sstevel@tonic-gate 	char		*setname,
5048*0Sstevel@tonic-gate 	int		node_c,
5049*0Sstevel@tonic-gate 	int		*node_id,	/* Array of node ids */
5050*0Sstevel@tonic-gate 	md_error_t	*ep
5051*0Sstevel@tonic-gate )
5052*0Sstevel@tonic-gate {
5053*0Sstevel@tonic-gate 	mdsetname_t		*local_sp;
5054*0Sstevel@tonic-gate 	int			i;
5055*0Sstevel@tonic-gate 	mdnamelist_t		*devnlp = NULL;
5056*0Sstevel@tonic-gate 	mdnamelist_t		*p;
5057*0Sstevel@tonic-gate 	mdname_t		*devnp = NULL;
5058*0Sstevel@tonic-gate 	md_set_mmown_params_t	ownpar_p;
5059*0Sstevel@tonic-gate 	md_set_mmown_params_t	*ownpar = &ownpar_p;
5060*0Sstevel@tonic-gate 	char			*miscname;
5061*0Sstevel@tonic-gate 
5062*0Sstevel@tonic-gate 	if ((local_sp = metasetname(setname, ep)) == NULL)
5063*0Sstevel@tonic-gate 		return;
5064*0Sstevel@tonic-gate 
5065*0Sstevel@tonic-gate 	/* get a list of all the mirrors for current set */
5066*0Sstevel@tonic-gate 	if (meta_get_mirror_names(local_sp, &devnlp, 0, ep) < 0)
5067*0Sstevel@tonic-gate 		return;
5068*0Sstevel@tonic-gate 
5069*0Sstevel@tonic-gate 	/* for each mirror */
5070*0Sstevel@tonic-gate 	for (p = devnlp; (p != NULL); p = p->next) {
5071*0Sstevel@tonic-gate 		devnp = p->namep;
5072*0Sstevel@tonic-gate 
5073*0Sstevel@tonic-gate 		/*
5074*0Sstevel@tonic-gate 		 * we can only do these for mirrors so make sure we
5075*0Sstevel@tonic-gate 		 * really have a mirror device and not a softpartition
5076*0Sstevel@tonic-gate 		 * imitating one. meta_get_mirror_names seems to think
5077*0Sstevel@tonic-gate 		 * softparts on top of a mirror are mirrors!
5078*0Sstevel@tonic-gate 		 */
5079*0Sstevel@tonic-gate 		if ((miscname = metagetmiscname(devnp, ep)) == NULL)
5080*0Sstevel@tonic-gate 			goto out;
5081*0Sstevel@tonic-gate 		if (strcmp(miscname, MD_MIRROR) != 0)
5082*0Sstevel@tonic-gate 			continue;
5083*0Sstevel@tonic-gate 
5084*0Sstevel@tonic-gate 		(void) memset(ownpar, 0, sizeof (*ownpar));
5085*0Sstevel@tonic-gate 		ownpar->d.mnum = meta_getminor(devnp->dev);
5086*0Sstevel@tonic-gate 		MD_SETDRIVERNAME(ownpar, MD_MIRROR, local_sp->setno);
5087*0Sstevel@tonic-gate 
5088*0Sstevel@tonic-gate 		/* get the current owner id */
5089*0Sstevel@tonic-gate 		if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep,
5090*0Sstevel@tonic-gate 		    "MD_MN_GET_MM_OWNER") != 0) {
5091*0Sstevel@tonic-gate 			mde_perror(ep, gettext(
5092*0Sstevel@tonic-gate 			    "Unable to get mirror owner for %s/d%u"),
5093*0Sstevel@tonic-gate 			    local_sp->setname,
5094*0Sstevel@tonic-gate 			    (unsigned)MD_MIN2UNIT(ownpar->d.mnum));
5095*0Sstevel@tonic-gate 			goto out;
5096*0Sstevel@tonic-gate 		}
5097*0Sstevel@tonic-gate 
5098*0Sstevel@tonic-gate 		if (ownpar->d.owner == MD_MN_MIRROR_UNOWNED) {
5099*0Sstevel@tonic-gate 			mdclrerror(ep);
5100*0Sstevel@tonic-gate 			continue;
5101*0Sstevel@tonic-gate 		}
5102*0Sstevel@tonic-gate 		/*
5103*0Sstevel@tonic-gate 		 * reset owner only if the current owner is
5104*0Sstevel@tonic-gate 		 * in the list of nodes being deleted.
5105*0Sstevel@tonic-gate 		 */
5106*0Sstevel@tonic-gate 		for (i = 0; i < node_c; i++) {
5107*0Sstevel@tonic-gate 			if (ownpar->d.owner == node_id[i]) {
5108*0Sstevel@tonic-gate 				if (meta_mn_change_owner(&ownpar,
5109*0Sstevel@tonic-gate 				    local_sp->setno, ownpar->d.mnum,
5110*0Sstevel@tonic-gate 				    MD_MN_MIRROR_UNOWNED,
5111*0Sstevel@tonic-gate 				    MD_MN_MM_ALLOW_CHANGE) == -1) {
5112*0Sstevel@tonic-gate 					mde_perror(ep, gettext(
5113*0Sstevel@tonic-gate 					    "Unable to reset mirror owner for"
5114*0Sstevel@tonic-gate 					    " %s/d%u"), local_sp->setname,
5115*0Sstevel@tonic-gate 					    (unsigned)MD_MIN2UNIT(
5116*0Sstevel@tonic-gate 					    ownpar->d.mnum));
5117*0Sstevel@tonic-gate 					goto out;
5118*0Sstevel@tonic-gate 				}
5119*0Sstevel@tonic-gate 				break;
5120*0Sstevel@tonic-gate 			}
5121*0Sstevel@tonic-gate 		}
5122*0Sstevel@tonic-gate 	}
5123*0Sstevel@tonic-gate 
5124*0Sstevel@tonic-gate out:
5125*0Sstevel@tonic-gate 	/* cleanup */
5126*0Sstevel@tonic-gate 	metafreenamelist(devnlp);
5127*0Sstevel@tonic-gate }
5128*0Sstevel@tonic-gate 
5129*0Sstevel@tonic-gate /*
5130*0Sstevel@tonic-gate  * Wrapper routine for reset_mirror_owner.
5131*0Sstevel@tonic-gate  * Called when hosts are deleted or withdrawn
5132*0Sstevel@tonic-gate  * in order to reset any mirror owners that are needed.
5133*0Sstevel@tonic-gate  */
5134*0Sstevel@tonic-gate bool_t
5135*0Sstevel@tonic-gate mdrpc_reset_mirror_owner_common(
5136*0Sstevel@tonic-gate 	mdrpc_nodeid_args	*args,
5137*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5138*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5139*0Sstevel@tonic-gate )
5140*0Sstevel@tonic-gate {
5141*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
5142*0Sstevel@tonic-gate 	int			err;
5143*0Sstevel@tonic-gate 	int			op_mode = W_OK;
5144*0Sstevel@tonic-gate 
5145*0Sstevel@tonic-gate 	/* setup, check permissions */
5146*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
5147*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5148*0Sstevel@tonic-gate 		return (FALSE);
5149*0Sstevel@tonic-gate 	else if (err != 0)
5150*0Sstevel@tonic-gate 		return (TRUE);
5151*0Sstevel@tonic-gate 
5152*0Sstevel@tonic-gate 	if (check_set_lock(op_mode, args->cl_sk, ep))
5153*0Sstevel@tonic-gate 		return (TRUE);
5154*0Sstevel@tonic-gate 
5155*0Sstevel@tonic-gate 	/* doit */
5156*0Sstevel@tonic-gate 	reset_mirror_owner(args->sp->setname, args->nodeid.nodeid_len,
5157*0Sstevel@tonic-gate 	    args->nodeid.nodeid_val, ep);
5158*0Sstevel@tonic-gate 
5159*0Sstevel@tonic-gate 	err = svc_fini(ep);
5160*0Sstevel@tonic-gate 
5161*0Sstevel@tonic-gate 	return (TRUE);
5162*0Sstevel@tonic-gate }
5163*0Sstevel@tonic-gate 
5164*0Sstevel@tonic-gate /*
5165*0Sstevel@tonic-gate  * RPC service routine to reset the mirror owner for mirrors owned
5166*0Sstevel@tonic-gate  * by the given hosts.  Typically, the list of given hosts is a list
5167*0Sstevel@tonic-gate  * of nodes being deleted or withdrawn from a diskset.
5168*0Sstevel@tonic-gate  * The given hosts are designated by nodeid since host may
5169*0Sstevel@tonic-gate  * already be deleted or withdrawn from set and may not
5170*0Sstevel@tonic-gate  * be able to translate between a nodename and a nodeid.
5171*0Sstevel@tonic-gate  */
5172*0Sstevel@tonic-gate bool_t
5173*0Sstevel@tonic-gate mdrpc_reset_mirror_owner_2_svc(
5174*0Sstevel@tonic-gate 	mdrpc_nodeid_2_args	*args,
5175*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5176*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5177*0Sstevel@tonic-gate )
5178*0Sstevel@tonic-gate {
5179*0Sstevel@tonic-gate 	switch (args->rev) {
5180*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5181*0Sstevel@tonic-gate 		return (mdrpc_reset_mirror_owner_common(
5182*0Sstevel@tonic-gate 		    &args->mdrpc_nodeid_2_args_u.rev1, res,
5183*0Sstevel@tonic-gate 		    rqstp));
5184*0Sstevel@tonic-gate 	    default:
5185*0Sstevel@tonic-gate 		return (FALSE);
5186*0Sstevel@tonic-gate 	}
5187*0Sstevel@tonic-gate }
5188*0Sstevel@tonic-gate 
5189*0Sstevel@tonic-gate /*
5190*0Sstevel@tonic-gate  * Call routines to suspend and resume I/O for the given diskset(s).
5191*0Sstevel@tonic-gate  * Called during reconfig cycle.
5192*0Sstevel@tonic-gate  * Diskset of 0 represents all MN disksets.
5193*0Sstevel@tonic-gate  */
5194*0Sstevel@tonic-gate bool_t
5195*0Sstevel@tonic-gate mdrpc_mn_susp_res_io_2_svc(
5196*0Sstevel@tonic-gate 	mdrpc_mn_susp_res_io_2_args	*args,
5197*0Sstevel@tonic-gate 	mdrpc_generic_res		*res,
5198*0Sstevel@tonic-gate 	struct svc_req			*rqstp		/* RPC stuff */
5199*0Sstevel@tonic-gate )
5200*0Sstevel@tonic-gate {
5201*0Sstevel@tonic-gate 	mdrpc_mn_susp_res_io_args	*args_sr;
5202*0Sstevel@tonic-gate 	md_error_t			*ep = &res->status;
5203*0Sstevel@tonic-gate 	int				err;
5204*0Sstevel@tonic-gate 	int				op_mode = R_OK;
5205*0Sstevel@tonic-gate 
5206*0Sstevel@tonic-gate 	switch (args->rev) {
5207*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5208*0Sstevel@tonic-gate 		/* setup, check permissions */
5209*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
5210*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5211*0Sstevel@tonic-gate 			return (FALSE);
5212*0Sstevel@tonic-gate 		else if (err != 0)
5213*0Sstevel@tonic-gate 			return (TRUE);
5214*0Sstevel@tonic-gate 
5215*0Sstevel@tonic-gate 		args_sr = &(args->mdrpc_mn_susp_res_io_2_args_u.rev1);
5216*0Sstevel@tonic-gate 		switch (args_sr->susp_res_cmd) {
5217*0Sstevel@tonic-gate 		case MN_SUSP_IO:
5218*0Sstevel@tonic-gate 			(void) (metaioctl(MD_MN_SUSPEND_SET,
5219*0Sstevel@tonic-gate 				&args_sr->susp_res_setno, ep, NULL));
5220*0Sstevel@tonic-gate 			break;
5221*0Sstevel@tonic-gate 		case MN_RES_IO:
5222*0Sstevel@tonic-gate 			(void) (metaioctl(MD_MN_RESUME_SET,
5223*0Sstevel@tonic-gate 				&args_sr->susp_res_setno, ep, NULL));
5224*0Sstevel@tonic-gate 			break;
5225*0Sstevel@tonic-gate 		}
5226*0Sstevel@tonic-gate 		err = svc_fini(ep);
5227*0Sstevel@tonic-gate 		return (TRUE);
5228*0Sstevel@tonic-gate 
5229*0Sstevel@tonic-gate 	    default:
5230*0Sstevel@tonic-gate 		return (FALSE);
5231*0Sstevel@tonic-gate 	}
5232*0Sstevel@tonic-gate }
5233*0Sstevel@tonic-gate 
5234*0Sstevel@tonic-gate /*
5235*0Sstevel@tonic-gate  * Resnarf a set after it has been imported
5236*0Sstevel@tonic-gate  */
5237*0Sstevel@tonic-gate bool_t
5238*0Sstevel@tonic-gate mdrpc_resnarf_set_2_svc(
5239*0Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
5240*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5241*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5242*0Sstevel@tonic-gate )
5243*0Sstevel@tonic-gate {
5244*0Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
5245*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
5246*0Sstevel@tonic-gate 	int			err;
5247*0Sstevel@tonic-gate 	int			op_mode = R_OK;
5248*0Sstevel@tonic-gate 
5249*0Sstevel@tonic-gate 	switch (args->rev) {
5250*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5251*0Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
5252*0Sstevel@tonic-gate 		break;
5253*0Sstevel@tonic-gate 	    default:
5254*0Sstevel@tonic-gate 		return (FALSE);
5255*0Sstevel@tonic-gate 	}
5256*0Sstevel@tonic-gate 
5257*0Sstevel@tonic-gate 	(void) memset(res, 0, sizeof (*res));
5258*0Sstevel@tonic-gate 	if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5259*0Sstevel@tonic-gate 		return (FALSE);
5260*0Sstevel@tonic-gate 	else if (err != 0)
5261*0Sstevel@tonic-gate 		return (TRUE);
5262*0Sstevel@tonic-gate 
5263*0Sstevel@tonic-gate 	/* do it */
5264*0Sstevel@tonic-gate 	if (resnarf_set(setno_args->setno, ep) < 0)
5265*0Sstevel@tonic-gate 		return (FALSE);
5266*0Sstevel@tonic-gate 
5267*0Sstevel@tonic-gate 	err = svc_fini(ep);
5268*0Sstevel@tonic-gate 	return (TRUE);
5269*0Sstevel@tonic-gate }
5270*0Sstevel@tonic-gate 
5271*0Sstevel@tonic-gate /*
5272*0Sstevel@tonic-gate  * Creates a resync thread.
5273*0Sstevel@tonic-gate  * Always returns true.
5274*0Sstevel@tonic-gate  */
5275*0Sstevel@tonic-gate bool_t
5276*0Sstevel@tonic-gate mdrpc_mn_mirror_resync_all_2_svc(
5277*0Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
5278*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5279*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5280*0Sstevel@tonic-gate )
5281*0Sstevel@tonic-gate {
5282*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
5283*0Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
5284*0Sstevel@tonic-gate 	int			err;
5285*0Sstevel@tonic-gate 	int			op_mode = R_OK;
5286*0Sstevel@tonic-gate 
5287*0Sstevel@tonic-gate 	switch (args->rev) {
5288*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5289*0Sstevel@tonic-gate 		/* setup, check permissions */
5290*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
5291*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5292*0Sstevel@tonic-gate 			return (FALSE);
5293*0Sstevel@tonic-gate 		else if (err != 0)
5294*0Sstevel@tonic-gate 			return (TRUE);
5295*0Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
5296*0Sstevel@tonic-gate 
5297*0Sstevel@tonic-gate 		/*
5298*0Sstevel@tonic-gate 		 * Need to invoke a metasync on a node newly added to a set.
5299*0Sstevel@tonic-gate 		 */
5300*0Sstevel@tonic-gate 		meta_mn_mirror_resync_all(&(setno_args->setno));
5301*0Sstevel@tonic-gate 
5302*0Sstevel@tonic-gate 		err = svc_fini(ep);
5303*0Sstevel@tonic-gate 		return (TRUE);
5304*0Sstevel@tonic-gate 
5305*0Sstevel@tonic-gate 	    default:
5306*0Sstevel@tonic-gate 		return (FALSE);
5307*0Sstevel@tonic-gate 	}
5308*0Sstevel@tonic-gate }
5309*0Sstevel@tonic-gate 
5310*0Sstevel@tonic-gate /*
5311*0Sstevel@tonic-gate  * Updates ABR state for all softpartitions. Calls meta_mn_sp_update_abr(),
5312*0Sstevel@tonic-gate  * which forks a daemon process to perform this action.
5313*0Sstevel@tonic-gate  * Always returns true.
5314*0Sstevel@tonic-gate  */
5315*0Sstevel@tonic-gate bool_t
5316*0Sstevel@tonic-gate mdrpc_mn_sp_update_abr_2_svc(
5317*0Sstevel@tonic-gate 	mdrpc_setno_2_args	*args,
5318*0Sstevel@tonic-gate 	mdrpc_generic_res	*res,
5319*0Sstevel@tonic-gate 	struct svc_req		*rqstp		/* RPC stuff */
5320*0Sstevel@tonic-gate )
5321*0Sstevel@tonic-gate {
5322*0Sstevel@tonic-gate 	md_error_t		*ep = &res->status;
5323*0Sstevel@tonic-gate 	mdrpc_setno_args	*setno_args;
5324*0Sstevel@tonic-gate 	int			err;
5325*0Sstevel@tonic-gate 	int			op_mode = R_OK;
5326*0Sstevel@tonic-gate 
5327*0Sstevel@tonic-gate 	switch (args->rev) {
5328*0Sstevel@tonic-gate 	    case MD_METAD_ARGS_REV_1:
5329*0Sstevel@tonic-gate 		/* setup, check permissions */
5330*0Sstevel@tonic-gate 		(void) memset(res, 0, sizeof (*res));
5331*0Sstevel@tonic-gate 		if ((err = svc_init(rqstp, op_mode, ep)) < 0)
5332*0Sstevel@tonic-gate 			return (FALSE);
5333*0Sstevel@tonic-gate 		else if (err != 0)
5334*0Sstevel@tonic-gate 			return (TRUE);
5335*0Sstevel@tonic-gate 		setno_args = &args->mdrpc_setno_2_args_u.rev1;
5336*0Sstevel@tonic-gate 
5337*0Sstevel@tonic-gate 		meta_mn_sp_update_abr(&(setno_args->setno));
5338*0Sstevel@tonic-gate 
5339*0Sstevel@tonic-gate 		err = svc_fini(ep);
5340*0Sstevel@tonic-gate 		return (TRUE);
5341*0Sstevel@tonic-gate 
5342*0Sstevel@tonic-gate 	    default:
5343*0Sstevel@tonic-gate 		return (FALSE);
5344*0Sstevel@tonic-gate 	}
5345*0Sstevel@tonic-gate }
5346