xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_set_med.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 2004 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 /*
30*0Sstevel@tonic-gate  * Metadevice diskset interfaces
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include "meta_set_prv.h"
34*0Sstevel@tonic-gate #include <sys/lvm/md_crc.h>
35*0Sstevel@tonic-gate #include <sys/lvm/mdmed.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
38*0Sstevel@tonic-gate #include <sys/sysevent/svm.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #define	MALSIZ	32
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate static int
add_lst(char *** listp,char * item)43*0Sstevel@tonic-gate add_lst(char ***listp, char *item)
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate 	int	i, j;
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate 	if (*listp) {
48*0Sstevel@tonic-gate 		for (i = 0; (*listp)[i]; i++)
49*0Sstevel@tonic-gate 			/* void */;
50*0Sstevel@tonic-gate 	} else {
51*0Sstevel@tonic-gate 		*listp = (char **)Zalloc(MALSIZ * sizeof (char *));
52*0Sstevel@tonic-gate 		i = 0;
53*0Sstevel@tonic-gate 	}
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 	(*listp)[i] = Strdup(item);
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 	if ((++i % MALSIZ) == 0) {
58*0Sstevel@tonic-gate 		*listp = (char **)Realloc((void *)*listp,
59*0Sstevel@tonic-gate 			(i + MALSIZ) * sizeof (char *));
60*0Sstevel@tonic-gate 		for (j = i; j < (i + MALSIZ); j++)
61*0Sstevel@tonic-gate 			(*listp)[j] = (char *)NULL;
62*0Sstevel@tonic-gate 	}
63*0Sstevel@tonic-gate 	return (i);
64*0Sstevel@tonic-gate }
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static int
del_lst(char *** listp)67*0Sstevel@tonic-gate del_lst(char ***listp)
68*0Sstevel@tonic-gate {
69*0Sstevel@tonic-gate 	int	i;
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	if (*listp) {
72*0Sstevel@tonic-gate 		for (i = 0; (*listp)[i]; i++)
73*0Sstevel@tonic-gate 			free((*listp)[i]);
74*0Sstevel@tonic-gate 		free(*listp);
75*0Sstevel@tonic-gate 		*listp = NULL;
76*0Sstevel@tonic-gate 		return (1);
77*0Sstevel@tonic-gate 	} else
78*0Sstevel@tonic-gate 		return (0);
79*0Sstevel@tonic-gate }
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate static int
validate_med_nodes(mdsetname_t * sp,md_h_arr_t * mhp,md_error_t * ep)83*0Sstevel@tonic-gate validate_med_nodes(
84*0Sstevel@tonic-gate 	mdsetname_t	*sp,
85*0Sstevel@tonic-gate 	md_h_arr_t	*mhp,
86*0Sstevel@tonic-gate 	md_error_t	*ep
87*0Sstevel@tonic-gate )
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate 	char		*hostname;
90*0Sstevel@tonic-gate 	char		*nodename;
91*0Sstevel@tonic-gate 	char		*nm;
92*0Sstevel@tonic-gate 	char		*cp;
93*0Sstevel@tonic-gate 	int		i, j;
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	for (i = 0; i < MED_MAX_HOSTS; i++) {
97*0Sstevel@tonic-gate 		if (mhp->n_lst[i].a_cnt == 0)
98*0Sstevel@tonic-gate 			continue;
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 		for (j = 0; j < mhp->n_lst[i].a_cnt; j++) {
101*0Sstevel@tonic-gate 			nm = mhp->n_lst[i].a_nm[j];
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 			for (cp = nm; *cp; cp++)
104*0Sstevel@tonic-gate 				if (!isprint(*cp) ||
105*0Sstevel@tonic-gate 				    strchr(INVALID_IN_NAMES, *cp) != NULL)
106*0Sstevel@tonic-gate 					return (mddserror(ep,
107*0Sstevel@tonic-gate 					    MDE_DS_INVALIDMEDNAME,
108*0Sstevel@tonic-gate 					    sp->setno, nm, NULL, sp->setname));
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 			if (clnt_med_hostname(nm, &hostname, ep))
111*0Sstevel@tonic-gate 				return (-1);
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 			if (j == 0) {
114*0Sstevel@tonic-gate 				if (strcmp(nm, hostname) != 0) {
115*0Sstevel@tonic-gate 					Free(hostname);
116*0Sstevel@tonic-gate 					return (mddserror(ep,
117*0Sstevel@tonic-gate 					    MDE_DS_NOTNODENAME, sp->setno, nm,
118*0Sstevel@tonic-gate 					    NULL, sp->setname));
119*0Sstevel@tonic-gate 				}
120*0Sstevel@tonic-gate 				nodename = nm;
121*0Sstevel@tonic-gate 			} else {
122*0Sstevel@tonic-gate 				if (strcmp(nodename, hostname) != 0) {
123*0Sstevel@tonic-gate 					Free(hostname);
124*0Sstevel@tonic-gate 					return (mddserror(ep,
125*0Sstevel@tonic-gate 					    MDE_DS_ALIASNOMATCH, sp->setno, nm,
126*0Sstevel@tonic-gate 					    nodename, sp->setname));
127*0Sstevel@tonic-gate 				}
128*0Sstevel@tonic-gate 			}
129*0Sstevel@tonic-gate 			Free(hostname);
130*0Sstevel@tonic-gate 		}
131*0Sstevel@tonic-gate 	}
132*0Sstevel@tonic-gate 	return (0);
133*0Sstevel@tonic-gate }
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate /*
136*0Sstevel@tonic-gate  * Exported Entry Points
137*0Sstevel@tonic-gate  */
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate int
meta_set_addmeds(mdsetname_t * sp,int node_c,char ** node_v,md_error_t * ep)140*0Sstevel@tonic-gate meta_set_addmeds(
141*0Sstevel@tonic-gate 	mdsetname_t		*sp,
142*0Sstevel@tonic-gate 	int			node_c,
143*0Sstevel@tonic-gate 	char			**node_v,
144*0Sstevel@tonic-gate 	md_error_t		*ep
145*0Sstevel@tonic-gate )
146*0Sstevel@tonic-gate {
147*0Sstevel@tonic-gate 	md_set_desc		*sd = NULL;
148*0Sstevel@tonic-gate 	md_drive_desc		*dd = NULL;
149*0Sstevel@tonic-gate 	mddb_med_parm_t		mp;
150*0Sstevel@tonic-gate 	mddb_med_upd_parm_t	mup;
151*0Sstevel@tonic-gate 	md_h_arr_t		t;
152*0Sstevel@tonic-gate 	md_h_arr_t		rb_t;
153*0Sstevel@tonic-gate 	med_rec_t		medr;
154*0Sstevel@tonic-gate 	med_rec_t		rb_medr;
155*0Sstevel@tonic-gate 	char			*cp;
156*0Sstevel@tonic-gate 	char			**n_l = NULL;
157*0Sstevel@tonic-gate 	int			n_c = 0;
158*0Sstevel@tonic-gate 	int			i, j;
159*0Sstevel@tonic-gate 	sigset_t		oldsigs;
160*0Sstevel@tonic-gate 	md_setkey_t		*cl_sk;
161*0Sstevel@tonic-gate 	int			rb_level = 0;
162*0Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
163*0Sstevel@tonic-gate 	int			rval = 0;
164*0Sstevel@tonic-gate 	int			max_meds;
165*0Sstevel@tonic-gate 	md_mnnode_desc		*nd;
166*0Sstevel@tonic-gate 	int			suspend1_flag = 0;
167*0Sstevel@tonic-gate 	int			lock_flag = 0;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	/* Initialize */
170*0Sstevel@tonic-gate 	(void) memset(&t, '\0', sizeof (t));
171*0Sstevel@tonic-gate 	t.n_cnt = node_c;
172*0Sstevel@tonic-gate 	mdclrerror(ep);
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
175*0Sstevel@tonic-gate 		return (-1);
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	/* Make sure we own the set */
178*0Sstevel@tonic-gate 	if (meta_check_ownership(sp, ep) != 0)
179*0Sstevel@tonic-gate 		return (-1);
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	if ((max_meds = get_max_meds(ep)) == 0)
182*0Sstevel@tonic-gate 		return (-1);
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	/*
185*0Sstevel@tonic-gate 	 * The mediator information (which is part of the set record) is
186*0Sstevel@tonic-gate 	 * stored in the local mddbs of each node in the diskset.
187*0Sstevel@tonic-gate 	 * Each node's rpc.metad daemon reads in the set
188*0Sstevel@tonic-gate 	 * records from that node's local mddb and caches them
189*0Sstevel@tonic-gate 	 * internally. Any process needing diskset information contacts its
190*0Sstevel@tonic-gate 	 * local rpc.metad to get this information.  Since each node in the
191*0Sstevel@tonic-gate 	 * diskset is independently reading the set information from its local
192*0Sstevel@tonic-gate 	 * mddb, the set records in the local mddbs must stay
193*0Sstevel@tonic-gate 	 * in-sync, so that all nodes have a consistent view of the diskset.
194*0Sstevel@tonic-gate 	 *
195*0Sstevel@tonic-gate 	 * For a multinode diskset, explicitly verify that all nodes in the
196*0Sstevel@tonic-gate 	 * diskset are ALIVE (i.e. are in the API membership list).  Otherwise,
197*0Sstevel@tonic-gate 	 * fail this operation since all nodes must be ALIVE in order to add
198*0Sstevel@tonic-gate 	 * the mediator information to the set record in their local mddb.
199*0Sstevel@tonic-gate 	 * If a panic of this node leaves the local mddbs set records
200*0Sstevel@tonic-gate 	 * out-of-sync, the reconfig cycle will fix the local mddbs and
201*0Sstevel@tonic-gate 	 * force them back into synchronization.
202*0Sstevel@tonic-gate 	 */
203*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
204*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
205*0Sstevel@tonic-gate 		while (nd) {
206*0Sstevel@tonic-gate 			if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
207*0Sstevel@tonic-gate 				(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
208*0Sstevel@tonic-gate 					sp->setno,
209*0Sstevel@tonic-gate 					nd->nd_nodename, NULL, sp->setname);
210*0Sstevel@tonic-gate 				return (-1);
211*0Sstevel@tonic-gate 			}
212*0Sstevel@tonic-gate 			nd = nd->nd_next;
213*0Sstevel@tonic-gate 		}
214*0Sstevel@tonic-gate 	}
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	/* Parse the command line into a the md_h_arr_t structure */
217*0Sstevel@tonic-gate 	for (i = 0; i < t.n_cnt; i++) {
218*0Sstevel@tonic-gate 		cp = strtok(node_v[i], ",");
219*0Sstevel@tonic-gate 		j = 0;
220*0Sstevel@tonic-gate 		while (cp) {
221*0Sstevel@tonic-gate 			if (strlen(cp) > (size_t)MD_MAX_NODENAME)
222*0Sstevel@tonic-gate 				return (mddserror(ep, MDE_DS_NODENAMETOOLONG,
223*0Sstevel@tonic-gate 				    sp->setno, cp, NULL, sp->setname));
224*0Sstevel@tonic-gate 			if (j >= MAX_HOST_ADDRS)
225*0Sstevel@tonic-gate 				return (mddserror(ep, MDE_DS_TOOMANYALIAS,
226*0Sstevel@tonic-gate 				    sp->setno, cp, NULL, sp->setname));
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 			(void) strcpy(t.n_lst[i].a_nm[j], cp);
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate 			j++;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 			cp = strtok(NULL, ",");
233*0Sstevel@tonic-gate 		}
234*0Sstevel@tonic-gate 		t.n_lst[i].a_cnt = j;
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	/* Make a list of nodes to check */
238*0Sstevel@tonic-gate 	for (i = 0; i < t.n_cnt; i++)
239*0Sstevel@tonic-gate 		for (j = 0; j < t.n_lst[i].a_cnt; j++)
240*0Sstevel@tonic-gate 			n_c = add_lst(&n_l, t.n_lst[i].a_nm[j]);
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	/* Make sure that there are no redundant nodes */
243*0Sstevel@tonic-gate 	rval = nodesuniq(sp, n_c, n_l, ep);
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 	(void) del_lst(&n_l);
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	if (rval != 0)
248*0Sstevel@tonic-gate 		return (rval);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	/*
251*0Sstevel@tonic-gate 	 * Lock the set on current set members.
252*0Sstevel@tonic-gate 	 * Set locking done much earlier for MN diskset than for traditional
253*0Sstevel@tonic-gate 	 * diskset since lock_set and SUSPEND are used to protect against
254*0Sstevel@tonic-gate 	 * other metaset commands running on the other nodes.
255*0Sstevel@tonic-gate 	 */
256*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
257*0Sstevel@tonic-gate 		/* Make sure we are blocking all signals */
258*0Sstevel@tonic-gate 		if (procsigs(TRUE, &oldsigs, &xep) < 0)
259*0Sstevel@tonic-gate 			mdclrerror(&xep);
260*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
261*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
262*0Sstevel@tonic-gate 		while (nd) {
263*0Sstevel@tonic-gate 			if (clnt_lock_set(nd->nd_nodename, sp, ep)) {
264*0Sstevel@tonic-gate 				rval = -1;
265*0Sstevel@tonic-gate 				goto out;
266*0Sstevel@tonic-gate 			}
267*0Sstevel@tonic-gate 			lock_flag = 1;
268*0Sstevel@tonic-gate 			nd = nd->nd_next;
269*0Sstevel@tonic-gate 		}
270*0Sstevel@tonic-gate 		/*
271*0Sstevel@tonic-gate 		 * Lock out other meta* commands by suspending
272*0Sstevel@tonic-gate 		 * class 1 messages across the diskset.
273*0Sstevel@tonic-gate 		 */
274*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
275*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
276*0Sstevel@tonic-gate 		while (nd) {
277*0Sstevel@tonic-gate 			if (clnt_mdcommdctl(nd->nd_nodename,
278*0Sstevel@tonic-gate 			    COMMDCTL_SUSPEND, sp, MD_MSG_CLASS1,
279*0Sstevel@tonic-gate 			    MD_MSCF_NO_FLAGS, ep)) {
280*0Sstevel@tonic-gate 				rval = -1;
281*0Sstevel@tonic-gate 				goto out;
282*0Sstevel@tonic-gate 			}
283*0Sstevel@tonic-gate 			suspend1_flag = 1;
284*0Sstevel@tonic-gate 			nd = nd->nd_next;
285*0Sstevel@tonic-gate 		}
286*0Sstevel@tonic-gate 	}
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	if (validate_med_nodes(sp, &t, ep)) {
289*0Sstevel@tonic-gate 		rval = -1;
290*0Sstevel@tonic-gate 		goto out;
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	/* Check existing mediators against new, if any */
294*0Sstevel@tonic-gate 	if (sd->sd_med.n_cnt > 0) {
295*0Sstevel@tonic-gate 		for (i = 0; i < max_meds; i++)
296*0Sstevel@tonic-gate 			if (sd->sd_med.n_lst[i].a_cnt > 0)
297*0Sstevel@tonic-gate 				n_c = add_lst(&n_l,
298*0Sstevel@tonic-gate 				    sd->sd_med.n_lst[i].a_nm[0]);
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 		for (i = 0; i < t.n_cnt; i++) {
301*0Sstevel@tonic-gate 			if (strinlst(t.n_lst[i].a_nm[0], n_c, n_l)) {
302*0Sstevel@tonic-gate 				(void) del_lst(&n_l);
303*0Sstevel@tonic-gate 				(void) mddserror(ep, MDE_DS_ISMED, sp->setno,
304*0Sstevel@tonic-gate 				    t.n_lst[i].a_nm[0], NULL,
305*0Sstevel@tonic-gate 				    sp->setname);
306*0Sstevel@tonic-gate 				rval = -1;
307*0Sstevel@tonic-gate 				goto out;
308*0Sstevel@tonic-gate 			}
309*0Sstevel@tonic-gate 		}
310*0Sstevel@tonic-gate 		(void) del_lst(&n_l);
311*0Sstevel@tonic-gate 	}
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate 	if ((t.n_cnt + sd->sd_med.n_cnt) > max_meds) {
314*0Sstevel@tonic-gate 		(void) mderror(ep, MDE_TOOMANYMED, NULL);
315*0Sstevel@tonic-gate 		rval = -1;
316*0Sstevel@tonic-gate 		goto out;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	/* Copy the current mediator list for rollback */
320*0Sstevel@tonic-gate 	rb_t = sd->sd_med;			/* structure assignment */
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	/* Setup the mediator record roll-back structure */
323*0Sstevel@tonic-gate 	(void) memset(&rb_medr, '\0', sizeof (med_rec_t));
324*0Sstevel@tonic-gate 	rb_medr.med_rec_mag = MED_REC_MAGIC;
325*0Sstevel@tonic-gate 	rb_medr.med_rec_rev = MED_REC_REV;
326*0Sstevel@tonic-gate 	rb_medr.med_rec_fl  = 0;
327*0Sstevel@tonic-gate 	rb_medr.med_rec_sn  = sp->setno;
328*0Sstevel@tonic-gate 	(void) strcpy(rb_medr.med_rec_snm, sp->setname);
329*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
330*0Sstevel@tonic-gate 		/*
331*0Sstevel@tonic-gate 		 * For a MN diskset the mediator is not given a list of
332*0Sstevel@tonic-gate 		 * hosts in the set.  Instead a generic name (multiowner) is
333*0Sstevel@tonic-gate 		 * given to the mediator which will allow any node to access
334*0Sstevel@tonic-gate 		 * the mediator data as long as it provides the correct
335*0Sstevel@tonic-gate 		 * setname and set number.  In a MN diskset, the mediator
336*0Sstevel@tonic-gate 		 * data is only used when a first node joins the diskset
337*0Sstevel@tonic-gate 		 * and becomes the master of the MN diskset.
338*0Sstevel@tonic-gate 		 *
339*0Sstevel@tonic-gate 		 * The traditional diskset code keeps the host list in
340*0Sstevel@tonic-gate 		 * the mediator record up to date with respect to the host
341*0Sstevel@tonic-gate 		 * list in the traditional diskset.  This keeps an unauthorized
342*0Sstevel@tonic-gate 		 * node in the traditional diskset from accessing the data
343*0Sstevel@tonic-gate 		 * in the mediator record and being able to 'take' the
344*0Sstevel@tonic-gate 		 * diskset.
345*0Sstevel@tonic-gate 		 *
346*0Sstevel@tonic-gate 		 * This additional check is needed in the traditional diskset
347*0Sstevel@tonic-gate 		 * since a panic during the metaset command can leave
348*0Sstevel@tonic-gate 		 * the diskset with some nodes thinking that an
349*0Sstevel@tonic-gate 		 * action has occurred and other nodes thinking the opposite.
350*0Sstevel@tonic-gate 		 * A node may have really been removed from a diskset, but
351*0Sstevel@tonic-gate 		 * that node doesn't realize this so this node must be
352*0Sstevel@tonic-gate 		 * blocked from using the mediator data when attempting
353*0Sstevel@tonic-gate 		 * to 'take' the diskset.
354*0Sstevel@tonic-gate 		 * (Traditional diskset code has each node's rpc.metad
355*0Sstevel@tonic-gate 		 * cleaning up from an inconsistent state without any
356*0Sstevel@tonic-gate 		 * knowledge from the other nodes in the diskset).
357*0Sstevel@tonic-gate 		 *
358*0Sstevel@tonic-gate 		 * In the MN diskset, the reconfig steps force a consistent
359*0Sstevel@tonic-gate 		 * state across all nodes in the diskset, so no node
360*0Sstevel@tonic-gate 		 * needs to be blocked from accessing the mediator data.
361*0Sstevel@tonic-gate 		 * This allow the MN diskset to use a common 'nodename'
362*0Sstevel@tonic-gate 		 * in the mediator record.  This allows the mediator
363*0Sstevel@tonic-gate 		 * daemon to remain unchanged even though a large number of
364*0Sstevel@tonic-gate 		 * nodes are supported by the MN diskset.
365*0Sstevel@tonic-gate 		 */
366*0Sstevel@tonic-gate 		(void) strlcpy(rb_medr.med_rec_nodes[0], MED_MN_CALLER,
367*0Sstevel@tonic-gate 		    MD_MAX_NODENAME_PLUS_1);
368*0Sstevel@tonic-gate 	} else {
369*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++)
370*0Sstevel@tonic-gate 			(void) strcpy(rb_medr.med_rec_nodes[i],
371*0Sstevel@tonic-gate 				sd->sd_nodes[i]);
372*0Sstevel@tonic-gate 	}
373*0Sstevel@tonic-gate 	rb_medr.med_rec_meds = sd->sd_med;	/* structure assigment */
374*0Sstevel@tonic-gate 	(void) memset(&rb_medr.med_rec_data, '\0', sizeof (med_data_t));
375*0Sstevel@tonic-gate 	rb_medr.med_rec_foff = 0;
376*0Sstevel@tonic-gate 	crcgen(&rb_medr, &rb_medr.med_rec_cks, sizeof (med_rec_t), NULL);
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	/* Merge new mediators into the set record */
379*0Sstevel@tonic-gate 	for (i = 0; i < t.n_cnt; i++) {
380*0Sstevel@tonic-gate 		for (j = 0; j < max_meds; j++) {
381*0Sstevel@tonic-gate 			if (sd->sd_med.n_lst[j].a_cnt > 0)
382*0Sstevel@tonic-gate 				continue;
383*0Sstevel@tonic-gate 			sd->sd_med.n_lst[j] = t.n_lst[i];
384*0Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_MEDIATOR,
385*0Sstevel@tonic-gate 			    sp->setno, j);
386*0Sstevel@tonic-gate 			sd->sd_med.n_cnt++;
387*0Sstevel@tonic-gate 			break;
388*0Sstevel@tonic-gate 		}
389*0Sstevel@tonic-gate 	}
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	/*
392*0Sstevel@tonic-gate 	 * Setup the kernel mediator list, which also validates that the
393*0Sstevel@tonic-gate 	 * hosts have valid IP addresses
394*0Sstevel@tonic-gate 	 */
395*0Sstevel@tonic-gate 	(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
396*0Sstevel@tonic-gate 	mp.med_setno = sp->setno;
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 	/* Copy the hostnames */
399*0Sstevel@tonic-gate 	if (meta_h2hi(&sd->sd_med, &mp.med, ep)) {
400*0Sstevel@tonic-gate 		rval = -1;
401*0Sstevel@tonic-gate 		goto out;
402*0Sstevel@tonic-gate 	}
403*0Sstevel@tonic-gate 
404*0Sstevel@tonic-gate 	/* Resolve the IP addresses for the host list */
405*0Sstevel@tonic-gate 	if (meta_med_hnm2ip(&mp.med, ep)) {
406*0Sstevel@tonic-gate 		rval = -1;
407*0Sstevel@tonic-gate 		goto out;
408*0Sstevel@tonic-gate 	}
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	/* Bring the mediator record up to date with the set record */
411*0Sstevel@tonic-gate 	medr = rb_medr;				/* structure assignment */
412*0Sstevel@tonic-gate 	medr.med_rec_meds = sd->sd_med;		/* structure assigment */
413*0Sstevel@tonic-gate 	crcgen(&medr, &medr.med_rec_cks, sizeof (med_rec_t), NULL);
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 	/* END CHECK CODE */
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	/* Lock the set on current set members */
418*0Sstevel@tonic-gate 	if (!(MD_MNSET_DESC(sd))) {
419*0Sstevel@tonic-gate 		/* all signals already blocked for MN disket */
420*0Sstevel@tonic-gate 		md_rb_sig_handling_on();
421*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
422*0Sstevel@tonic-gate 			/* Skip empty slots */
423*0Sstevel@tonic-gate 			if (sd->sd_nodes[i][0] == '\0')
424*0Sstevel@tonic-gate 				continue;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 			if (clnt_lock_set(sd->sd_nodes[i], sp, ep)) {
427*0Sstevel@tonic-gate 				rval = -1;
428*0Sstevel@tonic-gate 				goto out;
429*0Sstevel@tonic-gate 			}
430*0Sstevel@tonic-gate 			lock_flag = 1;
431*0Sstevel@tonic-gate 		}
432*0Sstevel@tonic-gate 	}
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 	RB_TEST(1, "meta_set_addmeds", ep)
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 	RB_PREEMPT;
437*0Sstevel@tonic-gate 	rb_level = 1;	/* level 1 */
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	RB_TEST(2, "meta_set_addmeds", ep)
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	/*
442*0Sstevel@tonic-gate 	 * Add the new mediator information to all hosts in the set.
443*0Sstevel@tonic-gate 	 * For MN diskset, each node sends mediator list to its kernel.
444*0Sstevel@tonic-gate 	 */
445*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
446*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
447*0Sstevel@tonic-gate 		while (nd) {
448*0Sstevel@tonic-gate 			/* All nodes are guaranteed to be ALIVE */
449*0Sstevel@tonic-gate 			if (clnt_updmeds(nd->nd_nodename, sp, &sd->sd_med, ep))
450*0Sstevel@tonic-gate 				goto rollback;
451*0Sstevel@tonic-gate 			nd = nd->nd_next;
452*0Sstevel@tonic-gate 		}
453*0Sstevel@tonic-gate 	} else  {
454*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
455*0Sstevel@tonic-gate 			/* Skip empty slots */
456*0Sstevel@tonic-gate 			if (sd->sd_nodes[i][0] == '\0')
457*0Sstevel@tonic-gate 				continue;
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 			if (clnt_updmeds(sd->sd_nodes[i], sp, &sd->sd_med, ep))
460*0Sstevel@tonic-gate 				goto rollback;
461*0Sstevel@tonic-gate 		}
462*0Sstevel@tonic-gate 	}
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 	RB_TEST(3, "meta_set_addmeds", ep)
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	RB_PREEMPT;
467*0Sstevel@tonic-gate 	rb_level = 2;	/* level 2 */
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	RB_TEST(4, "meta_set_addmeds", ep)
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	if ((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
472*0Sstevel@tonic-gate 	    ep)) == NULL) {
473*0Sstevel@tonic-gate 		if (! mdisok(ep))
474*0Sstevel@tonic-gate 			goto rollback;
475*0Sstevel@tonic-gate 	}
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 	RB_TEST(5, "meta_set_addmeds", ep)
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	RB_PREEMPT;
480*0Sstevel@tonic-gate 	rb_level = 3;	/* level 3 */
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 	RB_TEST(6, "meta_set_addmeds", ep)
483*0Sstevel@tonic-gate 
484*0Sstevel@tonic-gate 	/* Inform the mediator hosts of the new information */
485*0Sstevel@tonic-gate 	for (i = 0; i < max_meds; i++) {
486*0Sstevel@tonic-gate 		if (sd->sd_med.n_lst[i].a_cnt == 0)
487*0Sstevel@tonic-gate 			continue;
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 		/* medr contains new mediator node list */
490*0Sstevel@tonic-gate 		if (clnt_med_upd_rec(&sd->sd_med.n_lst[i], sp, &medr, ep))
491*0Sstevel@tonic-gate 			goto rollback;
492*0Sstevel@tonic-gate 	}
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 	RB_TEST(7, "meta_set_addmeds", ep)
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	RB_PREEMPT;
497*0Sstevel@tonic-gate 	rb_level = 4;	/* level 4 */
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate 	RB_TEST(8, "meta_set_addmeds", ep)
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	/* In MN diskset, mediator list updated in clnt_updmeds call */
502*0Sstevel@tonic-gate 	if (dd != NULL) {
503*0Sstevel@tonic-gate 		if (!(MD_MNSET_DESC(sd))) {
504*0Sstevel@tonic-gate 			if (metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde,
505*0Sstevel@tonic-gate 			    NULL) != 0) {
506*0Sstevel@tonic-gate 				(void) mdstealerror(ep, &mp.med_mde);
507*0Sstevel@tonic-gate 				goto rollback;
508*0Sstevel@tonic-gate 			}
509*0Sstevel@tonic-gate 		}
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 		/*
512*0Sstevel@tonic-gate 		 * If only 50% mddbs available, mediator will be
513*0Sstevel@tonic-gate 		 * golden by this ioctl on a traditional diskset.
514*0Sstevel@tonic-gate 		 *
515*0Sstevel@tonic-gate 		 * On a MN disket, this only happens if the mediator
516*0Sstevel@tonic-gate 		 * add operation is executed on the master node.
517*0Sstevel@tonic-gate 		 * If a slave node is adding the mediator, the mediator
518*0Sstevel@tonic-gate 		 * won't be marked golden until the next mddb change.
519*0Sstevel@tonic-gate 		 */
520*0Sstevel@tonic-gate 		(void) memset(&mup, '\0', sizeof (mddb_med_upd_parm_t));
521*0Sstevel@tonic-gate 		mup.med_setno = sp->setno;
522*0Sstevel@tonic-gate 		if (metaioctl(MD_MED_UPD_MED, &mup, &mup.med_mde, NULL) != 0)
523*0Sstevel@tonic-gate 			mdclrerror(&mup.med_mde);
524*0Sstevel@tonic-gate 	}
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate out:
527*0Sstevel@tonic-gate 	if (suspend1_flag) {
528*0Sstevel@tonic-gate 		/*
529*0Sstevel@tonic-gate 		 * Unlock diskset by resuming messages across the diskset.
530*0Sstevel@tonic-gate 		 * Just resume all classes so that resume is the same whether
531*0Sstevel@tonic-gate 		 * just one class was locked or all classes were locked.
532*0Sstevel@tonic-gate 		 */
533*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
534*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
535*0Sstevel@tonic-gate 		while (nd) {
536*0Sstevel@tonic-gate 			if (clnt_mdcommdctl(nd->nd_nodename, COMMDCTL_RESUME,
537*0Sstevel@tonic-gate 			    sp, MD_MSG_CLASS0, MD_MSCF_NO_FLAGS, &xep)) {
538*0Sstevel@tonic-gate 				if (rval == 0)
539*0Sstevel@tonic-gate 					(void) mdstealerror(ep, &xep);
540*0Sstevel@tonic-gate 				rval = -1;
541*0Sstevel@tonic-gate 				mde_perror(ep, dgettext(TEXT_DOMAIN,
542*0Sstevel@tonic-gate 				    "Unable to resume rpc.mdcommd.\n"));
543*0Sstevel@tonic-gate 			}
544*0Sstevel@tonic-gate 			nd = nd->nd_next;
545*0Sstevel@tonic-gate 		}
546*0Sstevel@tonic-gate 		meta_ping_mnset(sp->setno);
547*0Sstevel@tonic-gate 	}
548*0Sstevel@tonic-gate 	if (lock_flag) {
549*0Sstevel@tonic-gate 		cl_sk = cl_get_setkey(sp->setno, sp->setname);
550*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
551*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
552*0Sstevel@tonic-gate 			while (nd) {
553*0Sstevel@tonic-gate 				/* All nodes are guaranteed to be ALIVE */
554*0Sstevel@tonic-gate 				if (clnt_unlock_set(nd->nd_nodename,
555*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
556*0Sstevel@tonic-gate 					if (rval == 0)
557*0Sstevel@tonic-gate 						(void) mdstealerror(ep, &xep);
558*0Sstevel@tonic-gate 					rval = -1;
559*0Sstevel@tonic-gate 				}
560*0Sstevel@tonic-gate 				nd = nd->nd_next;
561*0Sstevel@tonic-gate 			}
562*0Sstevel@tonic-gate 		} else  {
563*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
564*0Sstevel@tonic-gate 				/* Skip empty slots */
565*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
566*0Sstevel@tonic-gate 					continue;
567*0Sstevel@tonic-gate 
568*0Sstevel@tonic-gate 				if (clnt_unlock_set(sd->sd_nodes[i],
569*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
570*0Sstevel@tonic-gate 					if (rval == 0)
571*0Sstevel@tonic-gate 						(void) mdstealerror(ep, &xep);
572*0Sstevel@tonic-gate 					rval = -1;
573*0Sstevel@tonic-gate 				}
574*0Sstevel@tonic-gate 			}
575*0Sstevel@tonic-gate 		}
576*0Sstevel@tonic-gate 		cl_set_setkey(NULL);
577*0Sstevel@tonic-gate 	}
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	metafreedrivedesc(&dd);
580*0Sstevel@tonic-gate 
581*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
582*0Sstevel@tonic-gate 		/* release signals back to what they were on entry */
583*0Sstevel@tonic-gate 		if (procsigs(FALSE, &oldsigs, &xep) < 0)
584*0Sstevel@tonic-gate 			mdclrerror(&xep);
585*0Sstevel@tonic-gate 	} else {
586*0Sstevel@tonic-gate 		md_rb_sig_handling_off(md_got_sig(), md_which_sig());
587*0Sstevel@tonic-gate 	}
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	return (rval);
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate rollback:
592*0Sstevel@tonic-gate 	/* all signals already blocked for MN disket */
593*0Sstevel@tonic-gate 	if (!(MD_MNSET_DESC(sd))) {
594*0Sstevel@tonic-gate 		if (procsigs(TRUE, &oldsigs, &xep) < 0)
595*0Sstevel@tonic-gate 			mdclrerror(&xep);
596*0Sstevel@tonic-gate 	}
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 	rval = -1;
599*0Sstevel@tonic-gate 
600*0Sstevel@tonic-gate 	/*
601*0Sstevel@tonic-gate 	 * level 4
602*0Sstevel@tonic-gate 	 * In MN diskset, mediator list updated in clnt_updmeds call
603*0Sstevel@tonic-gate 	 */
604*0Sstevel@tonic-gate 	if (rb_level > 3 && (dd != NULL) && (!(MD_MNSET_DESC(sd)))) {
605*0Sstevel@tonic-gate 		(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
606*0Sstevel@tonic-gate 		mp.med_setno = sp->setno;
607*0Sstevel@tonic-gate 		(void) meta_h2hi(&rb_t, &mp.med, &xep);
608*0Sstevel@tonic-gate 		mdclrerror(&xep);
609*0Sstevel@tonic-gate 		(void) meta_med_hnm2ip(&mp.med, &xep);
610*0Sstevel@tonic-gate 		mdclrerror(&xep);
611*0Sstevel@tonic-gate 		(void) metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL);
612*0Sstevel@tonic-gate 	}
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate 	/* level 3 */
615*0Sstevel@tonic-gate 	if (rb_level > 2) {
616*0Sstevel@tonic-gate 		for (i = 0; i < max_meds; i++) {
617*0Sstevel@tonic-gate 			if (sd->sd_med.n_lst[i].a_cnt == 0)
618*0Sstevel@tonic-gate 				continue;
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate 			/*
621*0Sstevel@tonic-gate 			 * rb_medr contains the rollback mediator node list.
622*0Sstevel@tonic-gate 			 * Send the rollback mediator information to the
623*0Sstevel@tonic-gate 			 * new mediator node list.  If a node had this RPC
624*0Sstevel@tonic-gate 			 * called, but its node is not in the mediator node
625*0Sstevel@tonic-gate 			 * list, rpc.metamedd will delete the mediator
626*0Sstevel@tonic-gate 			 * record on that node.
627*0Sstevel@tonic-gate 			 */
628*0Sstevel@tonic-gate 			if (clnt_med_upd_rec(&sd->sd_med.n_lst[i], sp,
629*0Sstevel@tonic-gate 			    &rb_medr, &xep))
630*0Sstevel@tonic-gate 				mdclrerror(&xep);
631*0Sstevel@tonic-gate 		}
632*0Sstevel@tonic-gate 	}
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate 	/* level 2 */
635*0Sstevel@tonic-gate 	if (rb_level > 1) {
636*0Sstevel@tonic-gate 		metafreedrivedesc(&dd);
637*0Sstevel@tonic-gate 	}
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate 	/* level 1 */
640*0Sstevel@tonic-gate 	if (rb_level > 0) {
641*0Sstevel@tonic-gate 		/* Delete mediator information from all hosts in the set */
642*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
643*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
644*0Sstevel@tonic-gate 			while (nd) {
645*0Sstevel@tonic-gate 				/* All nodes are guaranteed to be ALIVE */
646*0Sstevel@tonic-gate 				if (clnt_updmeds(nd->nd_nodename, sp, &rb_t,
647*0Sstevel@tonic-gate 				    &xep))
648*0Sstevel@tonic-gate 					mdclrerror(&xep);
649*0Sstevel@tonic-gate 				nd = nd->nd_next;
650*0Sstevel@tonic-gate 			}
651*0Sstevel@tonic-gate 		} else  {
652*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
653*0Sstevel@tonic-gate 				/* Skip empty slots */
654*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
655*0Sstevel@tonic-gate 					continue;
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 				if (clnt_updmeds(sd->sd_nodes[i], sp, &rb_t,
658*0Sstevel@tonic-gate 				    &xep))
659*0Sstevel@tonic-gate 					mdclrerror(&xep);
660*0Sstevel@tonic-gate 			}
661*0Sstevel@tonic-gate 		}
662*0Sstevel@tonic-gate 	}
663*0Sstevel@tonic-gate 
664*0Sstevel@tonic-gate 	/* level 0 */
665*0Sstevel@tonic-gate 	if (suspend1_flag) {
666*0Sstevel@tonic-gate 		/*
667*0Sstevel@tonic-gate 		 * Unlock diskset by resuming messages across the diskset.
668*0Sstevel@tonic-gate 		 * Just resume all classes so that resume is the same whether
669*0Sstevel@tonic-gate 		 * just one class was locked or all classes were locked.
670*0Sstevel@tonic-gate 		 */
671*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
672*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
673*0Sstevel@tonic-gate 		while (nd) {
674*0Sstevel@tonic-gate 			if (clnt_mdcommdctl(nd->nd_nodename, COMMDCTL_RESUME,
675*0Sstevel@tonic-gate 			    sp, MD_MSG_CLASS0, MD_MSCF_NO_FLAGS, &xep)) {
676*0Sstevel@tonic-gate 				mdclrerror(&xep);
677*0Sstevel@tonic-gate 				mde_perror(ep, dgettext(TEXT_DOMAIN,
678*0Sstevel@tonic-gate 				    "Unable to resume rpc.mdcommd.\n"));
679*0Sstevel@tonic-gate 			}
680*0Sstevel@tonic-gate 			nd = nd->nd_next;
681*0Sstevel@tonic-gate 		}
682*0Sstevel@tonic-gate 		meta_ping_mnset(sp->setno);
683*0Sstevel@tonic-gate 	}
684*0Sstevel@tonic-gate 	if (lock_flag) {
685*0Sstevel@tonic-gate 		cl_sk = cl_get_setkey(sp->setno, sp->setname);
686*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
687*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
688*0Sstevel@tonic-gate 			while (nd) {
689*0Sstevel@tonic-gate 				/* All nodes are guaranteed to be ALIVE */
690*0Sstevel@tonic-gate 				if (clnt_unlock_set(nd->nd_nodename,
691*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
692*0Sstevel@tonic-gate 					mdclrerror(&xep);
693*0Sstevel@tonic-gate 				}
694*0Sstevel@tonic-gate 				nd = nd->nd_next;
695*0Sstevel@tonic-gate 			}
696*0Sstevel@tonic-gate 		} else  {
697*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
698*0Sstevel@tonic-gate 				/* Skip empty slots */
699*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
700*0Sstevel@tonic-gate 					continue;
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate 				if (clnt_unlock_set(sd->sd_nodes[i],
703*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
704*0Sstevel@tonic-gate 					mdclrerror(&xep);
705*0Sstevel@tonic-gate 				}
706*0Sstevel@tonic-gate 			}
707*0Sstevel@tonic-gate 		}
708*0Sstevel@tonic-gate 		cl_set_setkey(NULL);
709*0Sstevel@tonic-gate 	}
710*0Sstevel@tonic-gate 
711*0Sstevel@tonic-gate 	/* release signals back to what they were on entry */
712*0Sstevel@tonic-gate 	if (procsigs(FALSE, &oldsigs, &xep) < 0)
713*0Sstevel@tonic-gate 		mdclrerror(&xep);
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	if (!(MD_MNSET_DESC(sd))) {
716*0Sstevel@tonic-gate 		md_rb_sig_handling_off(md_got_sig(), md_which_sig());
717*0Sstevel@tonic-gate 	}
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 	return (rval);
720*0Sstevel@tonic-gate }
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate int
meta_set_deletemeds(mdsetname_t * sp,int node_c,char ** node_v,int forceflg,md_error_t * ep)723*0Sstevel@tonic-gate meta_set_deletemeds(
724*0Sstevel@tonic-gate 	mdsetname_t		*sp,
725*0Sstevel@tonic-gate 	int			node_c,
726*0Sstevel@tonic-gate 	char			**node_v,
727*0Sstevel@tonic-gate 	int			forceflg,
728*0Sstevel@tonic-gate 	md_error_t		*ep
729*0Sstevel@tonic-gate )
730*0Sstevel@tonic-gate {
731*0Sstevel@tonic-gate 	md_set_desc		*sd = NULL;
732*0Sstevel@tonic-gate 	md_drive_desc		*dd = NULL;
733*0Sstevel@tonic-gate 	mddb_med_parm_t		mp;
734*0Sstevel@tonic-gate 	md_h_arr_t		rb_t;
735*0Sstevel@tonic-gate 	med_rec_t		medr;
736*0Sstevel@tonic-gate 	med_rec_t		rb_medr;
737*0Sstevel@tonic-gate 	int			i, j;
738*0Sstevel@tonic-gate 	char			**n_l = NULL;
739*0Sstevel@tonic-gate 	int			n_c = 0;
740*0Sstevel@tonic-gate 	sigset_t		oldsigs;
741*0Sstevel@tonic-gate 	md_setkey_t		*cl_sk;
742*0Sstevel@tonic-gate 	int			rb_level = 0;
743*0Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
744*0Sstevel@tonic-gate 	int			rval = 0;
745*0Sstevel@tonic-gate 	int			max_meds;
746*0Sstevel@tonic-gate 	md_mnnode_desc		*nd;
747*0Sstevel@tonic-gate 	int			suspend1_flag = 0;
748*0Sstevel@tonic-gate 	int			lock_flag = 0;
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 	mdclrerror(ep);
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
753*0Sstevel@tonic-gate 		return (-1);
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	/* Make sure we own the set */
756*0Sstevel@tonic-gate 	if (meta_check_ownership(sp, ep) != 0)
757*0Sstevel@tonic-gate 		return (-1);
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate 	for (i = 0; i < node_c; i++)
760*0Sstevel@tonic-gate 		if (strchr(node_v[i], ',') != NULL)
761*0Sstevel@tonic-gate 			return (mderror(ep, MDE_ONLYNODENAME, node_v[i]));
762*0Sstevel@tonic-gate 
763*0Sstevel@tonic-gate 	if (nodesuniq(sp, node_c, node_v, ep))
764*0Sstevel@tonic-gate 		return (-1);
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate 	if ((max_meds = get_max_meds(ep)) == 0)
767*0Sstevel@tonic-gate 		return (-1);
768*0Sstevel@tonic-gate 
769*0Sstevel@tonic-gate 	/*
770*0Sstevel@tonic-gate 	 * The mediator information (which is part of the set record) is
771*0Sstevel@tonic-gate 	 * stored in the local mddbs of each node in the diskset.
772*0Sstevel@tonic-gate 	 * Each node's rpc.metad daemon reads in the set
773*0Sstevel@tonic-gate 	 * records from that node's local mddb and caches them
774*0Sstevel@tonic-gate 	 * internally. Any process needing diskset information contacts its
775*0Sstevel@tonic-gate 	 * local rpc.metad to get this information.  Since each node in the
776*0Sstevel@tonic-gate 	 * diskset is independently reading the set information from its local
777*0Sstevel@tonic-gate 	 * mddb, the set records in the local mddbs must stay
778*0Sstevel@tonic-gate 	 * in-sync, so that all nodes have a consistent view of the diskset.
779*0Sstevel@tonic-gate 	 *
780*0Sstevel@tonic-gate 	 * For a multinode diskset, explicitly verify that all nodes in the
781*0Sstevel@tonic-gate 	 * diskset are ALIVE (i.e. are in the API membership list).  Otherwise,
782*0Sstevel@tonic-gate 	 * fail this operation since all nodes must be ALIVE in order to delete
783*0Sstevel@tonic-gate 	 * the mediator information from the set record in their local mddb.
784*0Sstevel@tonic-gate 	 * If a panic of this node leaves the local mddbs set records
785*0Sstevel@tonic-gate 	 * out-of-sync, the reconfig cycle will fix the local mddbs and
786*0Sstevel@tonic-gate 	 * force them back into synchronization.
787*0Sstevel@tonic-gate 	 */
788*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
789*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
790*0Sstevel@tonic-gate 		while (nd) {
791*0Sstevel@tonic-gate 			if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
792*0Sstevel@tonic-gate 				(void) mddserror(ep, MDE_DS_NOTINMEMBERLIST,
793*0Sstevel@tonic-gate 					sp->setno,
794*0Sstevel@tonic-gate 					nd->nd_nodename, NULL, sp->setname);
795*0Sstevel@tonic-gate 				return (-1);
796*0Sstevel@tonic-gate 			}
797*0Sstevel@tonic-gate 			nd = nd->nd_next;
798*0Sstevel@tonic-gate 		}
799*0Sstevel@tonic-gate 	}
800*0Sstevel@tonic-gate 
801*0Sstevel@tonic-gate 	if (sd->sd_med.n_cnt == 0)
802*0Sstevel@tonic-gate 		return (mderror(ep, MDE_NOMED, NULL));
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 	/* Make a list of nodes to check */
805*0Sstevel@tonic-gate 	for (i = 0; i < max_meds; i++)
806*0Sstevel@tonic-gate 		if (sd->sd_med.n_lst[i].a_cnt > 0)
807*0Sstevel@tonic-gate 			n_c = add_lst(&n_l, sd->sd_med.n_lst[i].a_nm[0]);
808*0Sstevel@tonic-gate 
809*0Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
810*0Sstevel@tonic-gate 		if (! strinlst(node_v[i], n_c, n_l)) {
811*0Sstevel@tonic-gate 			(void) del_lst(&n_l);
812*0Sstevel@tonic-gate 			return (mddserror(ep, MDE_DS_ISNOTMED, sp->setno,
813*0Sstevel@tonic-gate 			    node_v[i], NULL, sp->setname));
814*0Sstevel@tonic-gate 		}
815*0Sstevel@tonic-gate 	}
816*0Sstevel@tonic-gate 
817*0Sstevel@tonic-gate 	(void) del_lst(&n_l);
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate 	/* Save a copy of the current mediator information */
820*0Sstevel@tonic-gate 	rb_t = sd->sd_med;			/* structure assignment */
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate 	/* Setup the mediator record for rollback */
823*0Sstevel@tonic-gate 	(void) memset(&rb_medr, '\0', sizeof (med_rec_t));
824*0Sstevel@tonic-gate 	rb_medr.med_rec_mag = MED_REC_MAGIC;
825*0Sstevel@tonic-gate 	rb_medr.med_rec_rev = MED_REC_REV;
826*0Sstevel@tonic-gate 	rb_medr.med_rec_fl  = 0;
827*0Sstevel@tonic-gate 	rb_medr.med_rec_sn  = sp->setno;
828*0Sstevel@tonic-gate 	(void) strcpy(rb_medr.med_rec_snm, sp->setname);
829*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
830*0Sstevel@tonic-gate 		/*
831*0Sstevel@tonic-gate 		 * In MN diskset, use a generic nodename, multiowner, in the
832*0Sstevel@tonic-gate 		 * mediator record which allows any node to access mediator
833*0Sstevel@tonic-gate 		 * information.  MN diskset reconfig cycle forces consistent
834*0Sstevel@tonic-gate 		 * view of set/node/drive/mediator information across all nodes
835*0Sstevel@tonic-gate 		 * in the MN diskset.  This allows the relaxation of
836*0Sstevel@tonic-gate 		 * node name checking in rpc.metamedd for MN disksets.
837*0Sstevel@tonic-gate 		 *
838*0Sstevel@tonic-gate 		 * In the traditional diskset, only a node that is in the
839*0Sstevel@tonic-gate 		 * mediator record's diskset nodelist can access mediator
840*0Sstevel@tonic-gate 		 * data.
841*0Sstevel@tonic-gate 		 */
842*0Sstevel@tonic-gate 		(void) strlcpy(rb_medr.med_rec_nodes[0], MED_MN_CALLER,
843*0Sstevel@tonic-gate 		    MD_MAX_NODENAME_PLUS_1);
844*0Sstevel@tonic-gate 	} else {
845*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++)
846*0Sstevel@tonic-gate 			(void) strcpy(rb_medr.med_rec_nodes[i],
847*0Sstevel@tonic-gate 				sd->sd_nodes[i]);
848*0Sstevel@tonic-gate 	}
849*0Sstevel@tonic-gate 	rb_medr.med_rec_meds = sd->sd_med;	/* structure assignment */
850*0Sstevel@tonic-gate 	(void) memset(&rb_medr.med_rec_data, '\0', sizeof (med_data_t));
851*0Sstevel@tonic-gate 	rb_medr.med_rec_foff = 0;
852*0Sstevel@tonic-gate 	crcgen(&rb_medr, &rb_medr.med_rec_cks, sizeof (med_rec_t), NULL);
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate 	/* Delete the mediators requested from the set */
855*0Sstevel@tonic-gate 	for (i = 0; i < node_c; i++) {
856*0Sstevel@tonic-gate 		for (j = 0; j < max_meds; j++) {
857*0Sstevel@tonic-gate 			if (sd->sd_med.n_lst[j].a_cnt == 0)
858*0Sstevel@tonic-gate 				continue;
859*0Sstevel@tonic-gate 			if (strcmp(node_v[i],
860*0Sstevel@tonic-gate 			    sd->sd_med.n_lst[j].a_nm[0]) != 0)
861*0Sstevel@tonic-gate 				continue;
862*0Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE,
863*0Sstevel@tonic-gate 			    SVM_TAG_MEDIATOR, sp->setno, j);
864*0Sstevel@tonic-gate 			(void) memset(&sd->sd_med.n_lst[j], '\0',
865*0Sstevel@tonic-gate 			    sizeof (md_h_t));
866*0Sstevel@tonic-gate 			sd->sd_med.n_cnt--;
867*0Sstevel@tonic-gate 			break;
868*0Sstevel@tonic-gate 		}
869*0Sstevel@tonic-gate 	}
870*0Sstevel@tonic-gate 
871*0Sstevel@tonic-gate 	medr = rb_medr;				/* structure assignment */
872*0Sstevel@tonic-gate 	medr.med_rec_meds = sd->sd_med;		/* structure assignment */
873*0Sstevel@tonic-gate 	crcgen(&medr, &medr.med_rec_cks, sizeof (med_rec_t), NULL);
874*0Sstevel@tonic-gate 
875*0Sstevel@tonic-gate 	/* END CHECK CODE */
876*0Sstevel@tonic-gate 
877*0Sstevel@tonic-gate 	/* Lock the set on current set members */
878*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
879*0Sstevel@tonic-gate 		/* Make sure we are blocking all signals */
880*0Sstevel@tonic-gate 		if (procsigs(TRUE, &oldsigs, &xep) < 0)
881*0Sstevel@tonic-gate 			mdclrerror(&xep);
882*0Sstevel@tonic-gate 		/*
883*0Sstevel@tonic-gate 		 * Lock the set on current set members.
884*0Sstevel@tonic-gate 		 * lock_set and SUSPEND are used to protect against
885*0Sstevel@tonic-gate 		 * other metaset commands running on the other nodes.
886*0Sstevel@tonic-gate 		 */
887*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
888*0Sstevel@tonic-gate 		while (nd) {
889*0Sstevel@tonic-gate 			/* All nodes are guaranteed to be ALIVE */
890*0Sstevel@tonic-gate 			if (clnt_lock_set(nd->nd_nodename, sp, ep)) {
891*0Sstevel@tonic-gate 				if (forceflg && strcmp(mynode(),
892*0Sstevel@tonic-gate 				    nd->nd_nodename) != 0) {
893*0Sstevel@tonic-gate 					mdclrerror(ep);
894*0Sstevel@tonic-gate 					nd = nd->nd_next;
895*0Sstevel@tonic-gate 					continue;
896*0Sstevel@tonic-gate 				}
897*0Sstevel@tonic-gate 				rval = -1;
898*0Sstevel@tonic-gate 				goto out;
899*0Sstevel@tonic-gate 			}
900*0Sstevel@tonic-gate 			lock_flag = 1;
901*0Sstevel@tonic-gate 			nd = nd->nd_next;
902*0Sstevel@tonic-gate 		}
903*0Sstevel@tonic-gate 		/*
904*0Sstevel@tonic-gate 		 * Lock out other meta* commands by suspending
905*0Sstevel@tonic-gate 		 * class 1 messages across the diskset.
906*0Sstevel@tonic-gate 		 */
907*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
908*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
909*0Sstevel@tonic-gate 		while (nd) {
910*0Sstevel@tonic-gate 			if (clnt_mdcommdctl(nd->nd_nodename,
911*0Sstevel@tonic-gate 			    COMMDCTL_SUSPEND, sp, MD_MSG_CLASS1,
912*0Sstevel@tonic-gate 			    MD_MSCF_NO_FLAGS, ep)) {
913*0Sstevel@tonic-gate 				rval = -1;
914*0Sstevel@tonic-gate 				goto out;
915*0Sstevel@tonic-gate 			}
916*0Sstevel@tonic-gate 			suspend1_flag = 1;
917*0Sstevel@tonic-gate 			nd = nd->nd_next;
918*0Sstevel@tonic-gate 		}
919*0Sstevel@tonic-gate 	} else  {
920*0Sstevel@tonic-gate 		md_rb_sig_handling_on();
921*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
922*0Sstevel@tonic-gate 			/* Skip empty slots */
923*0Sstevel@tonic-gate 			if (sd->sd_nodes[i][0] == '\0')
924*0Sstevel@tonic-gate 				continue;
925*0Sstevel@tonic-gate 
926*0Sstevel@tonic-gate 			if (clnt_lock_set(sd->sd_nodes[i], sp, ep)) {
927*0Sstevel@tonic-gate 				if (forceflg &&
928*0Sstevel@tonic-gate 				    strcmp(mynode(), sd->sd_nodes[i]) != 0) {
929*0Sstevel@tonic-gate 					mdclrerror(ep);
930*0Sstevel@tonic-gate 					continue;
931*0Sstevel@tonic-gate 				}
932*0Sstevel@tonic-gate 				rval = -1;
933*0Sstevel@tonic-gate 				goto out;
934*0Sstevel@tonic-gate 			}
935*0Sstevel@tonic-gate 			lock_flag = 1;
936*0Sstevel@tonic-gate 		}
937*0Sstevel@tonic-gate 	}
938*0Sstevel@tonic-gate 
939*0Sstevel@tonic-gate 	RB_TEST(1, "meta_set_deletemeds", ep)
940*0Sstevel@tonic-gate 
941*0Sstevel@tonic-gate 	RB_PREEMPT;
942*0Sstevel@tonic-gate 	rb_level = 1;	/* level 1 */
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 	RB_TEST(2, "meta_set_deletemeds", ep)
945*0Sstevel@tonic-gate 
946*0Sstevel@tonic-gate 	/* Update the mediator information on all hosts in the set */
947*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
948*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
949*0Sstevel@tonic-gate 		while (nd) {
950*0Sstevel@tonic-gate 			/* All nodes are guaranteed to be ALIVE */
951*0Sstevel@tonic-gate 			if (clnt_updmeds(nd->nd_nodename, sp, &sd->sd_med,
952*0Sstevel@tonic-gate 			    ep)) {
953*0Sstevel@tonic-gate 				if (forceflg && strcmp(mynode(),
954*0Sstevel@tonic-gate 				    nd->nd_nodename) != 0) {
955*0Sstevel@tonic-gate 					mdclrerror(ep);
956*0Sstevel@tonic-gate 					continue;
957*0Sstevel@tonic-gate 				}
958*0Sstevel@tonic-gate 				goto rollback;
959*0Sstevel@tonic-gate 			}
960*0Sstevel@tonic-gate 			nd = nd->nd_next;
961*0Sstevel@tonic-gate 		}
962*0Sstevel@tonic-gate 	} else  {
963*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
964*0Sstevel@tonic-gate 			/* Skip empty slots */
965*0Sstevel@tonic-gate 			if (sd->sd_nodes[i][0] == '\0')
966*0Sstevel@tonic-gate 				continue;
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 			if (clnt_updmeds(sd->sd_nodes[i], sp, &sd->sd_med,
969*0Sstevel@tonic-gate 			    ep)) {
970*0Sstevel@tonic-gate 				if (forceflg && strcmp(mynode(),
971*0Sstevel@tonic-gate 				    sd->sd_nodes[i]) != 0) {
972*0Sstevel@tonic-gate 					mdclrerror(ep);
973*0Sstevel@tonic-gate 					continue;
974*0Sstevel@tonic-gate 				}
975*0Sstevel@tonic-gate 				goto rollback;
976*0Sstevel@tonic-gate 			}
977*0Sstevel@tonic-gate 		}
978*0Sstevel@tonic-gate 	}
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	RB_TEST(3, "meta_set_deletemeds", ep)
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 	RB_PREEMPT;
983*0Sstevel@tonic-gate 	rb_level = 2;	/* level 2 */
984*0Sstevel@tonic-gate 
985*0Sstevel@tonic-gate 	RB_TEST(5, "meta_set_deletemeds", ep)
986*0Sstevel@tonic-gate 
987*0Sstevel@tonic-gate 	if ((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
988*0Sstevel@tonic-gate 	    ep)) == NULL) {
989*0Sstevel@tonic-gate 		if (! mdisok(ep))
990*0Sstevel@tonic-gate 			goto rollback;
991*0Sstevel@tonic-gate 	}
992*0Sstevel@tonic-gate 
993*0Sstevel@tonic-gate 	RB_TEST(5, "meta_set_deletemeds", ep)
994*0Sstevel@tonic-gate 
995*0Sstevel@tonic-gate 	RB_PREEMPT;
996*0Sstevel@tonic-gate 	rb_level = 3;	/* level 3 */
997*0Sstevel@tonic-gate 
998*0Sstevel@tonic-gate 	RB_TEST(6, "meta_set_deletemeds", ep)
999*0Sstevel@tonic-gate 
1000*0Sstevel@tonic-gate 	if (dd != NULL) {
1001*0Sstevel@tonic-gate 		/*
1002*0Sstevel@tonic-gate 		 * Set up the parameters to the call to update the
1003*0Sstevel@tonic-gate 		 * kernel mediator list
1004*0Sstevel@tonic-gate 		 */
1005*0Sstevel@tonic-gate 		(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
1006*0Sstevel@tonic-gate 		mp.med_setno = sp->setno;
1007*0Sstevel@tonic-gate 		if (meta_h2hi(&sd->sd_med, &mp.med, ep))
1008*0Sstevel@tonic-gate 			goto rollback;
1009*0Sstevel@tonic-gate 
1010*0Sstevel@tonic-gate 		/* Resolve the IP addresses for the host list */
1011*0Sstevel@tonic-gate 		if (meta_med_hnm2ip(&mp.med, ep))
1012*0Sstevel@tonic-gate 			goto rollback;
1013*0Sstevel@tonic-gate 
1014*0Sstevel@tonic-gate 		if (metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL) != 0) {
1015*0Sstevel@tonic-gate 			(void) mdstealerror(ep, &mp.med_mde);
1016*0Sstevel@tonic-gate 			goto rollback;
1017*0Sstevel@tonic-gate 		}
1018*0Sstevel@tonic-gate 	}
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 	RB_TEST(7, "meta_set_deletemeds", ep)
1021*0Sstevel@tonic-gate 
1022*0Sstevel@tonic-gate 	RB_PREEMPT;
1023*0Sstevel@tonic-gate 	rb_level = 4;	/* level 4 */
1024*0Sstevel@tonic-gate 
1025*0Sstevel@tonic-gate 	RB_TEST(8, "meta_set_deletemeds", ep)
1026*0Sstevel@tonic-gate 
1027*0Sstevel@tonic-gate 	/* Inform the mediator hosts of the new status */
1028*0Sstevel@tonic-gate 	for (i = 0; i < max_meds; i++) {
1029*0Sstevel@tonic-gate 		if (rb_t.n_lst[i].a_cnt == 0)
1030*0Sstevel@tonic-gate 			continue;
1031*0Sstevel@tonic-gate 
1032*0Sstevel@tonic-gate 		/*
1033*0Sstevel@tonic-gate 		 * medr contains the new mediator node list.
1034*0Sstevel@tonic-gate 		 * Send the new mediator information to the
1035*0Sstevel@tonic-gate 		 * new mediator node list.  If a node had this RPC
1036*0Sstevel@tonic-gate 		 * called, but its node is no longer in the new mediator
1037*0Sstevel@tonic-gate 		 * node list, rpc.metamedd will delete the mediator
1038*0Sstevel@tonic-gate 		 * record on that node.
1039*0Sstevel@tonic-gate 		 */
1040*0Sstevel@tonic-gate 		if (clnt_med_upd_rec(&rb_t.n_lst[i], sp, &medr, ep)) {
1041*0Sstevel@tonic-gate 			if ((forceflg && mdanyrpcerror(ep)) ||
1042*0Sstevel@tonic-gate 			    mdisrpcerror(ep, RPC_PROGNOTREGISTERED)) {
1043*0Sstevel@tonic-gate 				mdclrerror(ep);
1044*0Sstevel@tonic-gate 				continue;
1045*0Sstevel@tonic-gate 			}
1046*0Sstevel@tonic-gate 			goto rollback;
1047*0Sstevel@tonic-gate 		}
1048*0Sstevel@tonic-gate 	}
1049*0Sstevel@tonic-gate 
1050*0Sstevel@tonic-gate out:
1051*0Sstevel@tonic-gate 	if (dd)
1052*0Sstevel@tonic-gate 		metafreedrivedesc(&dd);
1053*0Sstevel@tonic-gate 
1054*0Sstevel@tonic-gate 	if (suspend1_flag) {
1055*0Sstevel@tonic-gate 		/*
1056*0Sstevel@tonic-gate 		 * Unlock diskset by resuming messages across the diskset.
1057*0Sstevel@tonic-gate 		 * Just resume all classes so that resume is the same whether
1058*0Sstevel@tonic-gate 		 * just one class was locked or all classes were locked.
1059*0Sstevel@tonic-gate 		 */
1060*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
1061*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
1062*0Sstevel@tonic-gate 		while (nd) {
1063*0Sstevel@tonic-gate 			if (clnt_mdcommdctl(nd->nd_nodename, COMMDCTL_RESUME,
1064*0Sstevel@tonic-gate 			    sp, MD_MSG_CLASS0, MD_MSCF_NO_FLAGS, &xep)) {
1065*0Sstevel@tonic-gate 				if (rval == 0)
1066*0Sstevel@tonic-gate 					(void) mdstealerror(ep, &xep);
1067*0Sstevel@tonic-gate 				rval = -1;
1068*0Sstevel@tonic-gate 				mde_perror(ep, dgettext(TEXT_DOMAIN,
1069*0Sstevel@tonic-gate 				    "Unable to resume rpc.mdcommd.\n"));
1070*0Sstevel@tonic-gate 			}
1071*0Sstevel@tonic-gate 			nd = nd->nd_next;
1072*0Sstevel@tonic-gate 		}
1073*0Sstevel@tonic-gate 		meta_ping_mnset(sp->setno);
1074*0Sstevel@tonic-gate 	}
1075*0Sstevel@tonic-gate 
1076*0Sstevel@tonic-gate 	cl_sk = cl_get_setkey(sp->setno, sp->setname);
1077*0Sstevel@tonic-gate 	if (lock_flag) {
1078*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
1079*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
1080*0Sstevel@tonic-gate 			while (nd) {
1081*0Sstevel@tonic-gate 				/* All nodes are guaranteed to be ALIVE */
1082*0Sstevel@tonic-gate 				if (clnt_unlock_set(nd->nd_nodename,
1083*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
1084*0Sstevel@tonic-gate 					if (forceflg &&
1085*0Sstevel@tonic-gate 					    strcmp(mynode(),
1086*0Sstevel@tonic-gate 					    nd->nd_nodename) != 0) {
1087*0Sstevel@tonic-gate 						mdclrerror(ep);
1088*0Sstevel@tonic-gate 						continue;
1089*0Sstevel@tonic-gate 					}
1090*0Sstevel@tonic-gate 					if (rval == 0)
1091*0Sstevel@tonic-gate 						(void) mdstealerror(ep, &xep);
1092*0Sstevel@tonic-gate 					rval = -1;
1093*0Sstevel@tonic-gate 				}
1094*0Sstevel@tonic-gate 				nd = nd->nd_next;
1095*0Sstevel@tonic-gate 			}
1096*0Sstevel@tonic-gate 		} else {
1097*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
1098*0Sstevel@tonic-gate 				/* Skip empty slots */
1099*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
1100*0Sstevel@tonic-gate 					continue;
1101*0Sstevel@tonic-gate 
1102*0Sstevel@tonic-gate 				if (clnt_unlock_set(sd->sd_nodes[i],
1103*0Sstevel@tonic-gate 				    cl_sk, &xep)) {
1104*0Sstevel@tonic-gate 					if (forceflg &&
1105*0Sstevel@tonic-gate 					    strcmp(mynode(),
1106*0Sstevel@tonic-gate 					    sd->sd_nodes[i]) != 0) {
1107*0Sstevel@tonic-gate 						mdclrerror(ep);
1108*0Sstevel@tonic-gate 						continue;
1109*0Sstevel@tonic-gate 					}
1110*0Sstevel@tonic-gate 					if (rval == 0)
1111*0Sstevel@tonic-gate 						(void) mdstealerror(ep, &xep);
1112*0Sstevel@tonic-gate 					rval = -1;
1113*0Sstevel@tonic-gate 				}
1114*0Sstevel@tonic-gate 			}
1115*0Sstevel@tonic-gate 		}
1116*0Sstevel@tonic-gate 	}
1117*0Sstevel@tonic-gate 	cl_set_setkey(NULL);
1118*0Sstevel@tonic-gate 
1119*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
1120*0Sstevel@tonic-gate 		/* release signals back to what they were on entry */
1121*0Sstevel@tonic-gate 		if (procsigs(FALSE, &oldsigs, &xep) < 0)
1122*0Sstevel@tonic-gate 			mdclrerror(&xep);
1123*0Sstevel@tonic-gate 	} else {
1124*0Sstevel@tonic-gate 		md_rb_sig_handling_off(md_got_sig(), md_which_sig());
1125*0Sstevel@tonic-gate 	}
1126*0Sstevel@tonic-gate 
1127*0Sstevel@tonic-gate 	return (rval);
1128*0Sstevel@tonic-gate 
1129*0Sstevel@tonic-gate rollback:
1130*0Sstevel@tonic-gate 	/* all signals already blocked for MN disket */
1131*0Sstevel@tonic-gate 	if (!(MD_MNSET_DESC(sd))) {
1132*0Sstevel@tonic-gate 		if (procsigs(TRUE, &oldsigs, &xep) < 0)
1133*0Sstevel@tonic-gate 			mdclrerror(&xep);
1134*0Sstevel@tonic-gate 	}
1135*0Sstevel@tonic-gate 
1136*0Sstevel@tonic-gate 	rval = -1;
1137*0Sstevel@tonic-gate 
1138*0Sstevel@tonic-gate 	(void) del_lst(&n_l);
1139*0Sstevel@tonic-gate 
1140*0Sstevel@tonic-gate 	/* level 4 */
1141*0Sstevel@tonic-gate 	if (rb_level > 4) {
1142*0Sstevel@tonic-gate 		for (i = 0; i < max_meds; i++) {
1143*0Sstevel@tonic-gate 			if (rb_t.n_lst[i].a_cnt == 0)
1144*0Sstevel@tonic-gate 				continue;
1145*0Sstevel@tonic-gate 
1146*0Sstevel@tonic-gate 			/*
1147*0Sstevel@tonic-gate 			 * rb_medr contains the rollback mediator node list.
1148*0Sstevel@tonic-gate 			 * Send the rollback mediator information to the
1149*0Sstevel@tonic-gate 			 * new mediator node list.  This will recreate the
1150*0Sstevel@tonic-gate 			 * mediator record on all nodes where the mediator
1151*0Sstevel@tonic-gate 			 * record had been removed.
1152*0Sstevel@tonic-gate 			 */
1153*0Sstevel@tonic-gate 			if (clnt_med_upd_rec(&rb_t.n_lst[i], sp, &rb_medr,
1154*0Sstevel@tonic-gate 			    &xep))
1155*0Sstevel@tonic-gate 				mdclrerror(&xep);
1156*0Sstevel@tonic-gate 		}
1157*0Sstevel@tonic-gate 	}
1158*0Sstevel@tonic-gate 
1159*0Sstevel@tonic-gate 	/* level 3 */
1160*0Sstevel@tonic-gate 	if (rb_level > 2 && dd != NULL) {
1161*0Sstevel@tonic-gate 		(void) memset(&mp, '\0', sizeof (mddb_med_parm_t));
1162*0Sstevel@tonic-gate 		mp.med_setno = sp->setno;
1163*0Sstevel@tonic-gate 		(void) meta_h2hi(&rb_t, &mp.med, &xep);
1164*0Sstevel@tonic-gate 		mdclrerror(&xep);
1165*0Sstevel@tonic-gate 		(void) meta_med_hnm2ip(&mp.med, &xep);
1166*0Sstevel@tonic-gate 		mdclrerror(&xep);
1167*0Sstevel@tonic-gate 		(void) metaioctl(MD_MED_SET_LST, &mp, &mp.med_mde, NULL);
1168*0Sstevel@tonic-gate 	}
1169*0Sstevel@tonic-gate 
1170*0Sstevel@tonic-gate 	/* level 2 */
1171*0Sstevel@tonic-gate 	if (rb_level > 1) {
1172*0Sstevel@tonic-gate 		metafreedrivedesc(&dd);
1173*0Sstevel@tonic-gate 	}
1174*0Sstevel@tonic-gate 
1175*0Sstevel@tonic-gate 	/* level 1 */
1176*0Sstevel@tonic-gate 	if (rb_level > 0) {
1177*0Sstevel@tonic-gate 		/* Delete mediator information from all hosts in the set */
1178*0Sstevel@tonic-gate 		if (MD_MNSET_DESC(sd)) {
1179*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
1180*0Sstevel@tonic-gate 			while (nd) {
1181*0Sstevel@tonic-gate 				/* All nodes are guaranteed to be ALIVE */
1182*0Sstevel@tonic-gate 				if (clnt_updmeds(nd->nd_nodename, sp, &rb_t,
1183*0Sstevel@tonic-gate 				    &xep))
1184*0Sstevel@tonic-gate 					mdclrerror(&xep);
1185*0Sstevel@tonic-gate 				nd = nd->nd_next;
1186*0Sstevel@tonic-gate 			}
1187*0Sstevel@tonic-gate 		} else  {
1188*0Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
1189*0Sstevel@tonic-gate 				/* Skip empty slots */
1190*0Sstevel@tonic-gate 				if (sd->sd_nodes[i][0] == '\0')
1191*0Sstevel@tonic-gate 					continue;
1192*0Sstevel@tonic-gate 
1193*0Sstevel@tonic-gate 				if (clnt_updmeds(sd->sd_nodes[i], sp, &rb_t,
1194*0Sstevel@tonic-gate 				    &xep))
1195*0Sstevel@tonic-gate 					mdclrerror(&xep);
1196*0Sstevel@tonic-gate 			}
1197*0Sstevel@tonic-gate 		}
1198*0Sstevel@tonic-gate 	}
1199*0Sstevel@tonic-gate 
1200*0Sstevel@tonic-gate 	/* level 0 */
1201*0Sstevel@tonic-gate 	cl_sk = cl_get_setkey(sp->setno, sp->setname);
1202*0Sstevel@tonic-gate 	/* Unlock the set */
1203*0Sstevel@tonic-gate 	/* Don't test lock flag since guaranteed to be set if in rollback */
1204*0Sstevel@tonic-gate 	if (MD_MNSET_DESC(sd)) {
1205*0Sstevel@tonic-gate 		/*
1206*0Sstevel@tonic-gate 		 * Unlock diskset by resuming messages across the diskset.
1207*0Sstevel@tonic-gate 		 * Just resume all classes so that resume is the same whether
1208*0Sstevel@tonic-gate 		 * just one class was locked or all classes were locked.
1209*0Sstevel@tonic-gate 		 */
1210*0Sstevel@tonic-gate 		if (suspend1_flag) {
1211*0Sstevel@tonic-gate 			/* All nodes are guaranteed to be ALIVE */
1212*0Sstevel@tonic-gate 			nd = sd->sd_nodelist;
1213*0Sstevel@tonic-gate 			while (nd) {
1214*0Sstevel@tonic-gate 				if (clnt_mdcommdctl(nd->nd_nodename,
1215*0Sstevel@tonic-gate 				    COMMDCTL_RESUME, sp, MD_MSG_CLASS0,
1216*0Sstevel@tonic-gate 				    MD_MSCF_NO_FLAGS, &xep)) {
1217*0Sstevel@tonic-gate 				    mde_perror(&xep, dgettext(TEXT_DOMAIN,
1218*0Sstevel@tonic-gate 					"Unable to resume rpc.mdcommd.\n"));
1219*0Sstevel@tonic-gate 				    mdclrerror(&xep);
1220*0Sstevel@tonic-gate 				}
1221*0Sstevel@tonic-gate 				nd = nd->nd_next;
1222*0Sstevel@tonic-gate 			}
1223*0Sstevel@tonic-gate 			meta_ping_mnset(sp->setno);
1224*0Sstevel@tonic-gate 		}
1225*0Sstevel@tonic-gate 		nd = sd->sd_nodelist;
1226*0Sstevel@tonic-gate 		/* All nodes are guaranteed to be ALIVE */
1227*0Sstevel@tonic-gate 		while (nd) {
1228*0Sstevel@tonic-gate 			if (clnt_unlock_set(nd->nd_nodename, cl_sk, &xep))
1229*0Sstevel@tonic-gate 				mdclrerror(&xep);
1230*0Sstevel@tonic-gate 			nd = nd->nd_next;
1231*0Sstevel@tonic-gate 		}
1232*0Sstevel@tonic-gate 	} else  {
1233*0Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
1234*0Sstevel@tonic-gate 			/* Skip empty slots */
1235*0Sstevel@tonic-gate 			if (sd->sd_nodes[i][0] == '\0')
1236*0Sstevel@tonic-gate 				continue;
1237*0Sstevel@tonic-gate 
1238*0Sstevel@tonic-gate 			if (clnt_unlock_set(sd->sd_nodes[i], cl_sk, &xep))
1239*0Sstevel@tonic-gate 				mdclrerror(&xep);
1240*0Sstevel@tonic-gate 		}
1241*0Sstevel@tonic-gate 	}
1242*0Sstevel@tonic-gate 	cl_set_setkey(NULL);
1243*0Sstevel@tonic-gate 
1244*0Sstevel@tonic-gate 	/* release signals back to what they were on entry */
1245*0Sstevel@tonic-gate 	if (procsigs(FALSE, &oldsigs, &xep) < 0)
1246*0Sstevel@tonic-gate 		mdclrerror(&xep);
1247*0Sstevel@tonic-gate 
1248*0Sstevel@tonic-gate 	if (!(MD_MNSET_DESC(sd))) {
1249*0Sstevel@tonic-gate 		md_rb_sig_handling_off(md_got_sig(), md_which_sig());
1250*0Sstevel@tonic-gate 	}
1251*0Sstevel@tonic-gate 
1252*0Sstevel@tonic-gate 	return (rval);
1253*0Sstevel@tonic-gate }
1254