xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_metad.c (revision 2278144afd2005b3eabcfd9bc412fe5ceb78749d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Just in case we're not in a build environment, make sure that
30  * TEXT_DOMAIN gets set to something.
31  */
32 #if !defined(TEXT_DOMAIN)
33 #define	TEXT_DOMAIN "SYS_TEST"
34 #endif
35 
36 #include <meta.h>
37 #include <metad.h>
38 #include <devid.h>
39 
40 static md_setkey_t	*my_cl_sk = NULL;
41 
42 #define	CL_DEF_TMO	30L
43 
44 /*
45  * Convert an old style mddrivename_t into a new style
46  * mddrivename_t. Meant to be used *ONLY* by rpc.metad
47  */
48 void
49 meta_conv_drvname_old2new(
50 	o_mddrivename_t		*v1_dp,
51 	mddrivename_t		*v2_dp
52 )
53 {
54 	int 		sliceno;
55 	o_mdname_t	*v1_np;
56 	mdname_t	*v2_np;
57 
58 	/* fields that haven't changed */
59 	v2_dp->cname   = v1_dp->cname;
60 	v2_dp->rname   = v1_dp->rname;
61 	v2_dp->type    = v1_dp->type;
62 	v2_dp->errnum  = v1_dp->errnum;
63 
64 	/* geometry information */
65 	v2_dp->geom.ncyl  = v1_dp->geom.ncyl;
66 	v2_dp->geom.nhead = v1_dp->geom.nhead;
67 	v2_dp->geom.nsect = v1_dp->geom.nsect;
68 	v2_dp->geom.rpm   = v1_dp->geom.rpm;
69 	v2_dp->geom.write_reinstruct = v1_dp->geom.write_reinstruct;
70 	v2_dp->geom.read_reinstruct  = v1_dp->geom.read_reinstruct;
71 	v2_dp->geom.blk_sz = 0;
72 
73 	/* controller information */
74 	v2_dp->cinfo = v1_dp->cinfo;
75 
76 	/* vtoc information */
77 	v2_dp->vtoc.nparts    = v1_dp->vtoc.nparts;
78 	v2_dp->vtoc.first_lba = 0;
79 	v2_dp->vtoc.last_lba  = 0;
80 	v2_dp->vtoc.lbasize   = 0;
81 
82 	for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) {
83 		v2_dp->vtoc.parts[sliceno].start =
84 		    (diskaddr_t)v1_dp->vtoc.parts[sliceno].start;
85 		v2_dp->vtoc.parts[sliceno].size =
86 		    (diskaddr_t)v1_dp->vtoc.parts[sliceno].size;
87 		v2_dp->vtoc.parts[sliceno].tag =
88 		    v1_dp->vtoc.parts[sliceno].tag;
89 		v2_dp->vtoc.parts[sliceno].flag =
90 		    v1_dp->vtoc.parts[sliceno].flag;
91 		v2_dp->vtoc.parts[sliceno].label =
92 		    (diskaddr_t)v1_dp->vtoc.parts[sliceno].label;
93 	}
94 
95 	/* The new style vtoc has 17 partitions */
96 	v2_dp->vtoc.parts[MD_MAX_PARTS - 1].start = 0;
97 	v2_dp->vtoc.parts[MD_MAX_PARTS - 1].size  = 0;
98 	v2_dp->vtoc.parts[MD_MAX_PARTS - 1].tag   = 0;
99 	v2_dp->vtoc.parts[MD_MAX_PARTS - 1].flag  = 0;
100 	v2_dp->vtoc.parts[MD_MAX_PARTS - 1].label = 0;
101 
102 	v2_dp->vtoc.typename = v1_dp->vtoc.typename;
103 
104 	/* partition information */
105 	v2_dp->parts.parts_len = v1_dp->parts.parts_len;
106 	for (sliceno = 0; sliceno < v1_dp->parts.parts_len; sliceno++) {
107 		v1_np = &v1_dp->parts.parts_val[sliceno];
108 		v2_np = &v2_dp->parts.parts_val[sliceno];
109 
110 		/*
111 		 * We speculate that if cname for a particular
112 		 * partition does not exist, the other fields
113 		 * don't exist either. In such a case, we don't
114 		 * need to do anything for that partition.
115 		 */
116 		if (v1_np->cname != NULL) {
117 			v2_np->cname = v1_np->cname;
118 			v2_np->bname = v1_np->bname;
119 			v2_np->rname = v1_np->rname;
120 			v2_np->devicesname = v1_np->devicesname;
121 			v2_np->dev = meta_expldev(v1_np->dev);
122 			v2_np->key = v1_np->key;
123 			v2_np->end_blk = (diskaddr_t)v1_np->end_blk;
124 			v2_np->start_blk = (diskaddr_t)v1_np->start_blk;
125 		}
126 		v2_np->drivenamep = v2_dp;
127 	}
128 
129 	/* We don't care about the rest of the fields */
130 	v2_dp->side_names = v1_dp->side_names;
131 	v2_dp->side_names_key = v1_dp->side_names_key;
132 	v2_dp->miscname = v1_dp->miscname;
133 }
134 
135 /*
136  * Convert a new style mddrivename_t into an old style
137  * mddrivename_t. Meant to be used *ONLY* by rpc.metad
138  */
139 void
140 meta_conv_drvname_new2old(
141 	o_mddrivename_t		*v1_dp,
142 	mddrivename_t		*v2_dp
143 )
144 {
145 	int 		sliceno;
146 	o_mdname_t	*v1_np;
147 	mdname_t	*v2_np;
148 
149 	/* fields that haven't changed */
150 	v1_dp->cname   = v2_dp->cname;
151 	v1_dp->rname   = v2_dp->rname;
152 	v1_dp->type    = v2_dp->type;
153 	v1_dp->errnum  = v2_dp->errnum;
154 
155 	/* geometry information */
156 	v1_dp->geom.ncyl  = v2_dp->geom.ncyl;
157 	v1_dp->geom.nhead = v2_dp->geom.nhead;
158 	v1_dp->geom.nsect = v2_dp->geom.nsect;
159 	v1_dp->geom.rpm   = v2_dp->geom.rpm;
160 	v1_dp->geom.write_reinstruct = v2_dp->geom.write_reinstruct;
161 	v1_dp->geom.read_reinstruct  = v2_dp->geom.read_reinstruct;
162 
163 	/* controller information */
164 	v1_dp->cinfo = v2_dp->cinfo;
165 
166 	/* vtoc information */
167 	v1_dp->vtoc.typename = v2_dp->vtoc.typename;
168 	v1_dp->vtoc.nparts   = v2_dp->vtoc.nparts;
169 
170 	for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) {
171 		v1_dp->vtoc.parts[sliceno].start =
172 		    (daddr_t)v2_dp->vtoc.parts[sliceno].start;
173 		v1_dp->vtoc.parts[sliceno].size  =
174 		    (daddr_t)v2_dp->vtoc.parts[sliceno].size;
175 		v1_dp->vtoc.parts[sliceno].tag   =
176 		    v2_dp->vtoc.parts[sliceno].tag;
177 		v1_dp->vtoc.parts[sliceno].flag  =
178 		    v2_dp->vtoc.parts[sliceno].flag;
179 		v1_dp->vtoc.parts[sliceno].label =
180 		    (daddr_t)v2_dp->vtoc.parts[sliceno].label;
181 	}
182 
183 	/* partition information */
184 	v1_dp->parts.parts_len = v2_dp->parts.parts_len;
185 
186 	for (sliceno = 0; sliceno < v2_dp->parts.parts_len; sliceno++) {
187 		v1_np = &v1_dp->parts.parts_val[sliceno];
188 		v2_np = &v2_dp->parts.parts_val[sliceno];
189 
190 		/*
191 		 * We speculate that if cname for a particular
192 		 * partition does not exist then the rest of
193 		 * the fields a partition don't exist either.
194 		 * In such a case, we don't need to do anything
195 		 * for that partition.
196 		 */
197 		if (v2_np->cname != NULL) {
198 			v1_np->cname = v2_np->cname;
199 			v1_np->bname = v2_np->bname;
200 			v1_np->rname = v2_np->rname;
201 			v1_np->devicesname = v2_np->devicesname;
202 			v1_np->dev = meta_cmpldev(v2_np->dev);
203 			v1_np->key = v2_np->key;
204 			v1_np->end_blk = (daddr_t)v2_np->end_blk;
205 			v1_np->start_blk = (daddr_t)v2_np->start_blk;
206 		}
207 		v1_np->drivenamep = v1_dp;
208 	}
209 
210 	/* We don't care about the rest of the fields */
211 	v1_dp->side_names = v2_dp->side_names;
212 	v1_dp->side_names_key = v2_dp->side_names_key;
213 	v1_dp->miscname = v2_dp->miscname;
214 }
215 
216 /*
217  * Convert an old style md_drive_desc_t into a new style
218  * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad
219  */
220 void
221 meta_conv_drvdesc_old2new(
222 	o_md_drive_desc		*v1_dd,
223 	md_drive_desc		*v2_dd
224 )
225 {
226 	md_drive_desc	*dd;
227 	o_md_drive_desc	*o_dd;
228 
229 	dd = v2_dd;
230 
231 	for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) {
232 		dd->dd_ctime = o_dd->dd_ctime;
233 		dd->dd_genid = o_dd->dd_genid;
234 		dd->dd_flags = o_dd->dd_flags;
235 		meta_conv_drvname_old2new(o_dd->dd_dnp, dd->dd_dnp);
236 		dd->dd_dbcnt = o_dd->dd_dbcnt;
237 		dd->dd_dbsize = o_dd->dd_dbsize;
238 		dd = dd->dd_next;
239 	}
240 }
241 
242 /*
243  * Convert an new style md_drive_desc_t into a old style
244  * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad
245  */
246 void
247 meta_conv_drvdesc_new2old(
248 	o_md_drive_desc		*v1_dd,
249 	md_drive_desc		*v2_dd
250 )
251 {
252 	md_drive_desc	*dd;
253 	o_md_drive_desc	*o_dd;
254 
255 	o_dd = v1_dd;
256 
257 	for (dd = v2_dd; dd != NULL; dd = dd->dd_next) {
258 		o_dd->dd_ctime = dd->dd_ctime;
259 		o_dd->dd_genid = dd->dd_genid;
260 		o_dd->dd_flags = dd->dd_flags;
261 		meta_conv_drvname_new2old(o_dd->dd_dnp, dd->dd_dnp);
262 		o_dd->dd_dbcnt = dd->dd_dbcnt;
263 		o_dd->dd_dbsize = dd->dd_dbsize;
264 		o_dd = o_dd->dd_next;
265 	}
266 }
267 
268 /*
269  * Allocate memory for v1 drive descriptor
270  * depending upon the number of drives in the
271  * v2 drive descriptor
272  */
273 void
274 alloc_olddrvdesc(
275 	o_md_drive_desc		**v1_dd,
276 	md_drive_desc		*v2_dd
277 )
278 {
279 	md_drive_desc	*dd;
280 	o_md_drive_desc *new, *head;
281 
282 	head = NULL;
283 
284 	for (dd = v2_dd; dd != NULL; dd = dd->dd_next) {
285 		new = Zalloc(sizeof (o_md_drive_desc));
286 		new->dd_dnp = Zalloc(sizeof (o_mddrivename_t));
287 		new->dd_dnp->parts.parts_val = Zalloc(sizeof (o_mdname_t) *
288 		    dd->dd_dnp->parts.parts_len);
289 		new->dd_next = head;
290 		head = new;
291 	}
292 	*v1_dd = head;
293 }
294 
295 /*
296  * Allocate memory for v2 drive descriptor
297  * depending upon the number of drives in the
298  * v1 drive descriptor
299  */
300 void
301 alloc_newdrvdesc(
302 	o_md_drive_desc		*v1_dd,
303 	md_drive_desc		**v2_dd
304 )
305 {
306 	md_drive_desc	*new, *head;
307 	o_md_drive_desc	*o_dd;
308 
309 	head = NULL;
310 
311 	for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) {
312 		new = Zalloc(sizeof (md_drive_desc));
313 		new->dd_dnp = Zalloc(sizeof (mddrivename_t));
314 		new->dd_dnp->parts.parts_val = Zalloc(sizeof (mdname_t) *
315 		    o_dd->dd_dnp->parts.parts_len);
316 		new->dd_next = head;
317 		head = new;
318 	}
319 	*v2_dd = head;
320 }
321 
322 void
323 free_olddrvdesc(
324 	o_md_drive_desc		*v1_dd
325 )
326 {
327 	o_md_drive_desc	*o_dd, *head;
328 
329 	head = v1_dd;
330 
331 	while (head != NULL) {
332 		o_dd = head;
333 		head = head->dd_next;
334 		free(o_dd->dd_dnp->parts.parts_val);
335 		free(o_dd->dd_dnp);
336 		free(o_dd);
337 	}
338 }
339 
340 void
341 free_newdrvdesc(
342 	md_drive_desc		*v2_dd
343 )
344 {
345 	md_drive_desc	*dd, *head;
346 
347 	head = v2_dd;
348 
349 	while (head != NULL) {
350 		dd = head;
351 		head = head->dd_next;
352 		free(dd->dd_dnp->parts.parts_val);
353 		free(dd->dd_dnp);
354 		free(dd);
355 	}
356 }
357 
358 /*
359  * Return the device id for a given device
360  */
361 char *
362 meta_get_devid(
363 	char	*rname
364 )
365 {
366 	ddi_devid_t	devid;
367 	int		fd;
368 	char		*enc_devid, *dup_enc_devid = NULL;
369 
370 	if ((fd = open(rname, O_RDWR | O_NDELAY, 0)) < 0)
371 		return (NULL);
372 
373 	if (devid_get(fd, &devid) == -1) {
374 		(void) close(fd);
375 		return (NULL);
376 	}
377 	(void) close(fd);
378 
379 	enc_devid = devid_str_encode(devid, NULL);
380 	devid_free(devid);
381 
382 	if (enc_devid != NULL) {
383 		dup_enc_devid = strdup(enc_devid);
384 		devid_str_free(enc_devid);
385 	}
386 
387 	return (dup_enc_devid);
388 }
389 
390 /*
391  * Add side names for the diskset drive records
392  * NOTE: these go into the local set's namespace.
393  */
394 int
395 clnt_add_drv_sidenms(
396 	char			*hostname,
397 	char			*this_host,
398 	mdsetname_t		*sp,
399 	md_set_desc		*sd,
400 	int			node_c,
401 	char			**node_v,
402 	md_error_t		*ep
403 )
404 {
405 	CLIENT				*clntp;
406 	mdrpc_drv_sidenm_args		v1_args;
407 	mdrpc_drv_sidenm_2_args		v2_args;
408 	mdrpc_drv_sidenm_2_args_r1	*v21_args;
409 	mdrpc_generic_res		res;
410 	int				rval;
411 	int				version;
412 	int				i, j;
413 
414 	/* initialize */
415 	mdclrerror(ep);
416 	(void) memset(&v1_args, 0, sizeof (v1_args));
417 	(void) memset(&v2_args, 0, sizeof (v2_args));
418 	(void) memset(&res, 0, sizeof (res));
419 
420 	/* build args */
421 	v2_args.rev = MD_METAD_ARGS_REV_1;
422 	v21_args = &v2_args.mdrpc_drv_sidenm_2_args_u.rev1;
423 	v21_args->hostname = this_host;
424 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
425 	v21_args->sp = sp;
426 	v21_args->sd = sd;
427 	v21_args->node_v.node_v_len = node_c;
428 	v21_args->node_v.node_v_val = node_v;
429 
430 	/* do it */
431 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
432 		int	bool;
433 
434 		/*
435 		 * If the server is local, we call the v2 procedure
436 		 */
437 		bool = mdrpc_add_drv_sidenms_2_svc(&v2_args, &res, NULL);
438 		assert(bool == TRUE);
439 		(void) mdstealerror(ep, &res.status);
440 	} else {
441 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
442 			return (-1);
443 
444 		/*
445 		 * Check the client handle for the version
446 		 * and invoke the appropriate version of the
447 		 * remote procedure
448 		 */
449 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
450 
451 		if (version == METAD_VERSION) {	/* version 1 */
452 
453 			v1_args.sd = Zalloc(sizeof (o_md_set_desc));
454 			alloc_olddrvdesc(&v1_args.sd->sd_drvs, sd->sd_drvs);
455 
456 			/* build args */
457 			v1_args.hostname = this_host;
458 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
459 			v1_args.sp = sp;
460 			/* set descriptor */
461 			v1_args.sd->sd_ctime = sd->sd_ctime;
462 			v1_args.sd->sd_genid = sd->sd_genid;
463 			v1_args.sd->sd_setno = sd->sd_setno;
464 			v1_args.sd->sd_flags = sd->sd_flags;
465 			for (i = 0; i < MD_MAXSIDES; i++) {
466 				v1_args.sd->sd_isown[i] = sd->sd_isown[i];
467 
468 				for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j ++)
469 					v1_args.sd->sd_nodes[i][j] =
470 					    sd->sd_nodes[i][j];
471 			}
472 			v1_args.sd->sd_med = sd->sd_med;
473 			meta_conv_drvdesc_new2old(v1_args.sd->sd_drvs,
474 			    sd->sd_drvs);
475 			v1_args.node_v.node_v_len = node_c;
476 			v1_args.node_v.node_v_val = node_v;
477 
478 			rval = mdrpc_add_drv_sidenms_1(&v1_args, &res, clntp);
479 
480 			free_olddrvdesc(v1_args.sd->sd_drvs);
481 			free(v1_args.sd);
482 
483 			if (rval != RPC_SUCCESS)
484 				(void) mdrpcerror(ep, clntp, hostname,
485 				    dgettext(TEXT_DOMAIN,
486 				    "metad add drive sidenames"));
487 			else
488 				(void) mdstealerror(ep, &res.status);
489 		} else {			/* version 2 */
490 			rval = mdrpc_add_drv_sidenms_2(&v2_args, &res, clntp);
491 
492 			if (rval != RPC_SUCCESS)
493 				(void) mdrpcerror(ep, clntp, hostname,
494 				    dgettext(TEXT_DOMAIN,
495 				    "metad add drive sidenames"));
496 			else
497 				(void) mdstealerror(ep, &res.status);
498 		}
499 
500 		metarpcclose(clntp);
501 	}
502 
503 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
504 
505 	if (! mdisok(ep))
506 		return (-1);
507 
508 	return (0);
509 }
510 
511 /*
512  * Adding drives via metaimport to disksets. Some of the drives may
513  * not be available so we need more information than the basic clnt_adddrvs
514  * offers us.
515  */
516 int
517 clnt_imp_adddrvs(
518 	char			*hostname,
519 	mdsetname_t		*sp,
520 	md_drive_desc		*dd,
521 	md_timeval32_t		timestamp,
522 	ulong_t			genid,
523 	md_error_t		*ep
524 )
525 {
526 	CLIENT			*clntp;
527 	mdrpc_drives_2_args	v2_args;
528 	mdrpc_drives_2_args_r1	*v21_args;
529 	mdrpc_generic_res	res;
530 	int			rval;
531 	int			version;
532 
533 	/* initialize */
534 	mdclrerror(ep);
535 	(void) memset(&v2_args, 0, sizeof (v2_args));
536 	(void) memset(&res, 0, sizeof (res));
537 
538 	/* build args */
539 	v2_args.rev = MD_METAD_ARGS_REV_1;
540 	v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
541 	v21_args->sp = sp;
542 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
543 	v21_args->drivedescs = dd;
544 	v21_args->timestamp = timestamp;
545 	v21_args->genid = genid;
546 
547 	/* do it */
548 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
549 		int	bool;
550 
551 		/*
552 		 * If the server is local, we call the v1 procedure
553 		 */
554 		bool = mdrpc_imp_adddrvs_2(&v2_args, &res, NULL);
555 		assert(bool == TRUE);
556 		(void) mdstealerror(ep, &res.status);
557 	} else {
558 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
559 			return (-1);
560 
561 		/*
562 		 * Check the client handle for the version
563 		 * and invoke the appropriate version of the
564 		 * remote procedure
565 		 */
566 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
567 
568 		/*
569 		 * If the client is version 1, return error
570 		 * otherwise, make the remote procedure call.
571 		 */
572 		if (version == METAD_VERSION) { /* version 1 */
573 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
574 			    sp->setno, hostname, NULL, NULL);
575 			metarpcclose(clntp);
576 			return (-1);
577 		} else {
578 			rval = mdrpc_imp_adddrvs_2(&v2_args, &res, clntp);
579 			if (rval != RPC_SUCCESS)
580 				(void) mdrpcerror(ep, clntp, hostname,
581 				    dgettext(TEXT_DOMAIN,
582 				    "metad imp add drives"));
583 			else
584 				(void) mdstealerror(ep, &res.status);
585 		}
586 
587 		metarpcclose(clntp);
588 	}
589 
590 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
591 
592 	if (! mdisok(ep))
593 		return (-1);
594 
595 	return (0);
596 }
597 
598 
599 /*
600  * Add drives to disksets.
601  */
602 int
603 clnt_adddrvs(
604 	char			*hostname,
605 	mdsetname_t		*sp,
606 	md_drive_desc		*dd,
607 	md_timeval32_t		timestamp,
608 	ulong_t			genid,
609 	md_error_t		*ep
610 )
611 {
612 	CLIENT			*clntp;
613 	mdrpc_drives_args	v1_args;
614 	mdrpc_drives_2_args	v2_args;
615 	mdrpc_drives_2_args_r1	*v21_args;
616 	mdrpc_generic_res	res;
617 	int			rval;
618 	int			version;
619 
620 	/* initialize */
621 	mdclrerror(ep);
622 	(void) memset(&v1_args, 0, sizeof (v1_args));
623 	(void) memset(&v2_args, 0, sizeof (v2_args));
624 	(void) memset(&res, 0, sizeof (res));
625 
626 	/* build args */
627 	v2_args.rev = MD_METAD_ARGS_REV_1;
628 	v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
629 	v21_args->sp = sp;
630 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
631 	v21_args->drivedescs = dd;
632 	v21_args->timestamp = timestamp;
633 	v21_args->genid = genid;
634 
635 	/* do it */
636 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
637 		int	bool;
638 
639 		/*
640 		 * If the server is local, we call the v2 procedure
641 		 */
642 		bool = mdrpc_adddrvs_2_svc(&v2_args, &res, NULL);
643 		assert(bool == TRUE);
644 		(void) mdstealerror(ep, &res.status);
645 	} else {
646 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
647 			return (-1);
648 
649 		/*
650 		 * Check the client handle for the version
651 		 * and invoke the appropriate version of the
652 		 * remote procedure
653 		 */
654 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
655 
656 		if (version == METAD_VERSION) {	/* version 1 */
657 
658 			alloc_olddrvdesc(&v1_args.drivedescs, dd);
659 
660 			/* build args */
661 			v1_args.sp = sp;
662 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
663 			meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
664 			v1_args.timestamp = timestamp;
665 			v1_args.genid = genid;
666 
667 			rval = mdrpc_adddrvs_1(&v1_args, &res, clntp);
668 
669 			free_olddrvdesc(v1_args.drivedescs);
670 
671 			if (rval != RPC_SUCCESS)
672 				(void) mdrpcerror(ep, clntp, hostname,
673 				    dgettext(TEXT_DOMAIN, "metad add drives"));
674 			else
675 				(void) mdstealerror(ep, &res.status);
676 		} else {			/* version 2 */
677 			rval = mdrpc_adddrvs_2(&v2_args, &res, clntp);
678 
679 			if (rval != RPC_SUCCESS)
680 				(void) mdrpcerror(ep, clntp, hostname,
681 				    dgettext(TEXT_DOMAIN, "metad add drives"));
682 			else
683 				(void) mdstealerror(ep, &res.status);
684 		}
685 
686 		metarpcclose(clntp);
687 	}
688 
689 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
690 
691 	if (! mdisok(ep))
692 		return (-1);
693 
694 	return (0);
695 }
696 
697 /*
698  * Add hosts to disksets.
699  */
700 int
701 clnt_addhosts(
702 	char			*hostname,
703 	mdsetname_t		*sp,
704 	int			node_c,
705 	char			**node_v,
706 	md_error_t		*ep
707 )
708 {
709 	CLIENT			*clntp;
710 	mdrpc_host_args		*args;
711 	mdrpc_host_2_args	v2_args;
712 	mdrpc_generic_res	res;
713 	int			version;
714 
715 	/* initialize */
716 	mdclrerror(ep);
717 	(void) memset(&v2_args, 0, sizeof (v2_args));
718 	(void) memset(&res, 0, sizeof (res));
719 
720 	/* build args */
721 	v2_args.rev = MD_METAD_ARGS_REV_1;
722 	args = &v2_args.mdrpc_host_2_args_u.rev1;
723 	args->sp = sp;
724 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
725 	args->hosts.hosts_len = node_c;
726 	args->hosts.hosts_val = node_v;
727 
728 	/* do it */
729 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
730 		int bool;
731 		bool = mdrpc_addhosts_2_svc(&v2_args, &res, NULL);
732 		assert(bool == TRUE);
733 		(void) mdstealerror(ep, &res.status);
734 	} else {
735 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
736 			return (-1);
737 
738 		/*
739 		 * Check the client handle for the version and invoke
740 		 * the appropriate version of the remote procedure
741 		 */
742 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
743 
744 		if (version == METAD_VERSION) {	/* version 1 */
745 			if (mdrpc_addhosts_1(args, &res, clntp) != RPC_SUCCESS)
746 				(void) mdrpcerror(ep, clntp, hostname,
747 				dgettext(TEXT_DOMAIN, "metad add hosts"));
748 			else
749 				(void) mdstealerror(ep, &res.status);
750 		} else {
751 			if (mdrpc_addhosts_2(&v2_args, &res, clntp) !=
752 			    RPC_SUCCESS)
753 				(void) mdrpcerror(ep, clntp, hostname,
754 				dgettext(TEXT_DOMAIN, "metad add hosts"));
755 			else
756 				(void) mdstealerror(ep, &res.status);
757 		}
758 
759 		metarpcclose(clntp);
760 	}
761 
762 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
763 
764 	if (! mdisok(ep))
765 		return (-1);
766 
767 	return (0);
768 }
769 
770 /*
771  * Create disksets.
772  */
773 int
774 clnt_createset(
775 	char			*hostname,
776 	mdsetname_t		*sp,
777 	md_node_nm_arr_t	nodes,
778 	md_timeval32_t		timestamp,
779 	ulong_t			genid,
780 	md_error_t		*ep
781 )
782 {
783 	CLIENT			*clntp;
784 	mdrpc_createset_args	*args;
785 	mdrpc_createset_2_args	v2_args;
786 	mdrpc_generic_res	res;
787 	int			i;
788 	int			version;
789 
790 	/* initialize */
791 	mdclrerror(ep);
792 	(void) memset(&v2_args, 0, sizeof (v2_args));
793 	(void) memset(&res, 0, sizeof (res));
794 
795 	/* build args */
796 	v2_args.rev = MD_METAD_ARGS_REV_1;
797 	args = &v2_args.mdrpc_createset_2_args_u.rev1;
798 	args->sp = sp;
799 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
800 	args->timestamp = timestamp;
801 	args->genid = genid;
802 	for (i = 0; i < MD_MAXSIDES; i++)
803 		(void) strcpy(args->nodes[i], nodes[i]);
804 
805 	/* do it */
806 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
807 		int	bool;
808 		bool = mdrpc_createset_2_svc(&v2_args, &res, NULL);
809 		assert(bool == TRUE);
810 		(void) mdstealerror(ep, &res.status);
811 	} else {
812 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
813 			return (-1);
814 
815 		/*
816 		 * Check the client handle for the version and invoke
817 		 * the appropriate version of the remote procedure
818 		 */
819 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
820 
821 		if (version == METAD_VERSION) {	/* version 1 */
822 			if (mdrpc_createset_1(args, &res, clntp) !=
823 			    RPC_SUCCESS)
824 				(void) mdrpcerror(ep, clntp, hostname,
825 				dgettext(TEXT_DOMAIN, "metad create set"));
826 			else
827 				(void) mdstealerror(ep, &res.status);
828 		} else {
829 			if (mdrpc_createset_2(&v2_args, &res, clntp) !=
830 			    RPC_SUCCESS)
831 				(void) mdrpcerror(ep, clntp, hostname,
832 				dgettext(TEXT_DOMAIN, "metad create set"));
833 			else
834 				(void) mdstealerror(ep, &res.status);
835 		}
836 
837 		metarpcclose(clntp);
838 	}
839 
840 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
841 
842 	if (! mdisok(ep))
843 		return (-1);
844 
845 	return (0);
846 }
847 
848 /*
849  * Create MN disksets.
850  */
851 int
852 clnt_mncreateset(
853 	char			*hostname,
854 	mdsetname_t		*sp,
855 	md_mnnode_desc		*nodelist,
856 	md_timeval32_t		timestamp,
857 	ulong_t			genid,
858 	md_node_nm_t		master_nodenm,
859 	int			master_nodeid,
860 	md_error_t		*ep
861 )
862 {
863 	CLIENT			*clntp;
864 	mdrpc_mncreateset_args	*args;
865 	mdrpc_mncreateset_2_args v2_args;
866 	mdrpc_generic_res	res;
867 	int			version;
868 
869 	/* initialize */
870 	mdclrerror(ep);
871 	(void) memset(&v2_args, 0, sizeof (v2_args));
872 	(void) memset(&res, 0, sizeof (res));
873 
874 	/* build args */
875 	v2_args.rev = MD_METAD_ARGS_REV_1;
876 	args = &v2_args.mdrpc_mncreateset_2_args_u.rev1;
877 	args->sp = sp;
878 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
879 	args->timestamp = timestamp;
880 	args->genid = genid;
881 	(void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME);
882 	args->master_nodeid = master_nodeid;
883 	args->nodelist = nodelist;
884 
885 	/* do it */
886 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
887 		int	bool;
888 		bool = mdrpc_mncreateset_2_svc(&v2_args, &res, NULL);
889 		assert(bool == TRUE);
890 		(void) mdstealerror(ep, &res.status);
891 	} else {
892 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
893 			return (-1);
894 
895 		/*
896 		 * Check the client handle for the version
897 		 */
898 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
899 
900 		/*
901 		 * If the client is version 1, return error
902 		 * otherwise, make the remote procedure call.
903 		 */
904 		if (version == METAD_VERSION) { /* version 1 */
905 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
906 			    sp->setno, hostname, NULL, sp->setname);
907 			metarpcclose(clntp);
908 			return (-1);
909 		} else {
910 			if (mdrpc_mncreateset_2(&v2_args, &res, clntp)
911 							!= RPC_SUCCESS)
912 				(void) mdrpcerror(ep, clntp, hostname,
913 				dgettext(TEXT_DOMAIN, "metad mncreate set"));
914 			else
915 				(void) mdstealerror(ep, &res.status);
916 		}
917 
918 		metarpcclose(clntp);
919 	}
920 
921 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
922 
923 	if (! mdisok(ep))
924 		return (-1);
925 
926 	return (0);
927 }
928 
929 /*
930  * Join MN set
931  */
932 int
933 clnt_joinset(
934 	char			*hostname,
935 	mdsetname_t		*sp,
936 	int			flags,
937 	md_error_t		*ep
938 )
939 {
940 	CLIENT			*clntp;
941 	mdrpc_sp_flags_args	*args;
942 	mdrpc_sp_flags_2_args	v2_args;
943 	mdrpc_generic_res	res;
944 	int			version;
945 
946 	/* initialize */
947 	mdclrerror(ep);
948 	(void) memset(&v2_args, 0, sizeof (v2_args));
949 	(void) memset(&res, 0, sizeof (res));
950 
951 	/* build args */
952 	v2_args.rev = MD_METAD_ARGS_REV_1;
953 	args = &v2_args.mdrpc_sp_flags_2_args_u.rev1;
954 	args->sp = sp;
955 	args->flags = flags;
956 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
957 
958 	/* do it */
959 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
960 		int	bool;
961 		bool = mdrpc_joinset_2_svc(&v2_args, &res, NULL);
962 		assert(bool == TRUE);
963 		(void) mdstealerror(ep, &res.status);
964 	} else {
965 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
966 			return (-1);
967 
968 		/*
969 		 * Check the client handle for the version
970 		 */
971 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
972 
973 		/*
974 		 * If the client is version 1, return error
975 		 * otherwise, make the remote procedure call.
976 		 */
977 		if (version == METAD_VERSION) { /* version 1 */
978 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
979 			    sp->setno, hostname, NULL, sp->setname);
980 			metarpcclose(clntp);
981 			return (-1);
982 		} else {
983 			if (mdrpc_joinset_2(&v2_args, &res, clntp)
984 							!= RPC_SUCCESS)
985 				(void) mdrpcerror(ep, clntp, hostname,
986 				    dgettext(TEXT_DOMAIN, "metad join set"));
987 			else
988 				(void) mdstealerror(ep, &res.status);
989 		}
990 
991 		metarpcclose(clntp);
992 	}
993 
994 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
995 
996 	if (! mdisok(ep))
997 		return (-1);
998 
999 	return (0);
1000 }
1001 
1002 /*
1003  * Withdraw from MN set
1004  */
1005 int
1006 clnt_withdrawset(
1007 	char			*hostname,
1008 	mdsetname_t		*sp,
1009 	md_error_t		*ep
1010 )
1011 {
1012 	CLIENT			*clntp;
1013 	mdrpc_sp_args		*args;
1014 	mdrpc_sp_2_args		v2_args;
1015 	mdrpc_generic_res	res;
1016 	int			version;
1017 
1018 	/* initialize */
1019 	mdclrerror(ep);
1020 	(void) memset(&v2_args, 0, sizeof (v2_args));
1021 	(void) memset(&res, 0, sizeof (res));
1022 
1023 	/* build args */
1024 	v2_args.rev = MD_METAD_ARGS_REV_1;
1025 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
1026 	args->sp = sp;
1027 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1028 
1029 	/* do it */
1030 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1031 		int	bool;
1032 		bool = mdrpc_withdrawset_2_svc(&v2_args, &res, NULL);
1033 		assert(bool == TRUE);
1034 		(void) mdstealerror(ep, &res.status);
1035 	} else {
1036 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1037 			return (-1);
1038 
1039 		/*
1040 		 * Check the client handle for the version
1041 		 */
1042 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1043 
1044 		/*
1045 		 * If the client is version 1, return error
1046 		 * otherwise, make the remote procedure call.
1047 		 */
1048 		if (version == METAD_VERSION) { /* version 1 */
1049 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
1050 			    sp->setno, hostname, NULL, sp->setname);
1051 			metarpcclose(clntp);
1052 			return (-1);
1053 		} else {
1054 			if (mdrpc_withdrawset_2(&v2_args, &res, clntp)
1055 							!= RPC_SUCCESS)
1056 				(void) mdrpcerror(ep, clntp, hostname,
1057 				dgettext(TEXT_DOMAIN,
1058 				    "metad withdraw set"));
1059 			else
1060 				(void) mdstealerror(ep, &res.status);
1061 		}
1062 
1063 		metarpcclose(clntp);
1064 	}
1065 
1066 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1067 
1068 	if (! mdisok(ep))
1069 		return (-1);
1070 
1071 	return (0);
1072 }
1073 
1074 /*
1075  * Delete side names for the diskset drive records
1076  * NOTE: these are removed from the local set's namespace.
1077  */
1078 int
1079 clnt_del_drv_sidenms(
1080 	char			*hostname,
1081 	mdsetname_t		*sp,
1082 	md_error_t		*ep
1083 )
1084 {
1085 	CLIENT			*clntp;
1086 	mdrpc_sp_args		*args;
1087 	mdrpc_sp_2_args		v2_args;
1088 	mdrpc_generic_res	res;
1089 	int			version;
1090 
1091 	/* initialize */
1092 	mdclrerror(ep);
1093 	(void) memset(&v2_args, 0, sizeof (v2_args));
1094 	(void) memset(&res, 0, sizeof (res));
1095 
1096 	/* build args */
1097 	v2_args.rev = MD_METAD_ARGS_REV_1;
1098 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
1099 	args->sp = sp;
1100 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1101 
1102 	/* do it */
1103 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1104 		int	bool;
1105 		bool = mdrpc_del_drv_sidenms_2_svc(&v2_args, &res, NULL);
1106 		assert(bool == TRUE);
1107 		(void) mdstealerror(ep, &res.status);
1108 	} else {
1109 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1110 			return (-1);
1111 
1112 		if (metaget_setdesc(sp, ep) == NULL) {
1113 			if (! mdisok(ep))
1114 				return (-1);
1115 			mdclrerror(ep);
1116 		}
1117 
1118 		/*
1119 		 * Check the client handle for the version and invoke
1120 		 * the appropriate version of the remote procedure
1121 		 */
1122 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1123 
1124 		if (version == METAD_VERSION) {	/* version 1 */
1125 			if (mdrpc_del_drv_sidenms_1(args, &res, clntp) !=
1126 			    RPC_SUCCESS)
1127 				(void) mdrpcerror(ep, clntp, hostname,
1128 				dgettext(TEXT_DOMAIN,
1129 				    "metad delete drive sidenames"));
1130 			else
1131 				(void) mdstealerror(ep, &res.status);
1132 		} else {
1133 			if (mdrpc_del_drv_sidenms_2(&v2_args, &res, clntp) !=
1134 			    RPC_SUCCESS)
1135 				(void) mdrpcerror(ep, clntp, hostname,
1136 				dgettext(TEXT_DOMAIN,
1137 				    "metad delete drive sidenames"));
1138 			else
1139 				(void) mdstealerror(ep, &res.status);
1140 		}
1141 
1142 		metarpcclose(clntp);
1143 	}
1144 
1145 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1146 
1147 	if (! mdisok(ep))
1148 		return (-1);
1149 
1150 	return (0);
1151 }
1152 
1153 /*
1154  * delete drives from the set
1155  */
1156 int
1157 clnt_deldrvs(
1158 	char			*hostname,
1159 	mdsetname_t		*sp,
1160 	md_drive_desc		*dd,
1161 	md_error_t		*ep
1162 )
1163 {
1164 	CLIENT			*clntp;
1165 	mdrpc_drives_args	v1_args;
1166 	mdrpc_drives_2_args	v2_args;
1167 	mdrpc_drives_2_args_r1	*v21_args;
1168 	mdrpc_generic_res	res;
1169 	int			rval;
1170 	int			version;
1171 
1172 	/* initialize */
1173 	mdclrerror(ep);
1174 	(void) memset(&v1_args, 0, sizeof (v1_args));
1175 	(void) memset(&v2_args, 0, sizeof (v2_args));
1176 	(void) memset(&res, 0, sizeof (res));
1177 
1178 	/* build args */
1179 	v2_args.rev = MD_METAD_ARGS_REV_1;
1180 	v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
1181 	v21_args->sp = sp;
1182 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1183 	v21_args->drivedescs = dd;
1184 
1185 	/* do it */
1186 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1187 		int	bool;
1188 
1189 		/*
1190 		 * If the server is local, we call the v2 procedure
1191 		 */
1192 		bool = mdrpc_deldrvs_2_svc(&v2_args, &res, NULL);
1193 		assert(bool == TRUE);
1194 		(void) mdstealerror(ep, &res.status);
1195 	} else {
1196 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1197 			return (-1);
1198 
1199 		/*
1200 		 * Check the client handle for the version
1201 		 * and invoke the appropriate version of the
1202 		 * remote procedure
1203 		 */
1204 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1205 
1206 		if (version == METAD_VERSION) {	/* version 1 */
1207 
1208 			alloc_olddrvdesc(&v1_args.drivedescs, dd);
1209 
1210 			/* build args */
1211 			v1_args.sp = sp;
1212 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
1213 			meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
1214 
1215 			rval = mdrpc_deldrvs_1(&v1_args, &res, clntp);
1216 
1217 			free_olddrvdesc(v1_args.drivedescs);
1218 
1219 			if (rval != RPC_SUCCESS)
1220 				(void) mdrpcerror(ep, clntp, hostname,
1221 				    dgettext(TEXT_DOMAIN,
1222 				    "metad delete drives"));
1223 			else
1224 				(void) mdstealerror(ep, &res.status);
1225 		} else {			/* version 2 */
1226 			rval = mdrpc_deldrvs_2(&v2_args, &res, clntp);
1227 
1228 			if (rval != RPC_SUCCESS)
1229 				(void) mdrpcerror(ep, clntp, hostname,
1230 				    dgettext(TEXT_DOMAIN,
1231 				    "metad delete drives"));
1232 			else
1233 				(void) mdstealerror(ep, &res.status);
1234 		}
1235 
1236 		metarpcclose(clntp);
1237 	}
1238 
1239 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1240 
1241 	if (! mdisok(ep))
1242 		return (-1);
1243 
1244 	return (0);
1245 }
1246 
1247 /*
1248  * delete host(s) from a set.
1249  */
1250 int
1251 clnt_delhosts(
1252 	char			*hostname,
1253 	mdsetname_t		*sp,
1254 	int			node_c,
1255 	char			**node_v,
1256 	md_error_t		*ep
1257 )
1258 {
1259 	CLIENT			*clntp;
1260 	mdrpc_host_args		*args;
1261 	mdrpc_host_2_args	v2_args;
1262 	mdrpc_generic_res	res;
1263 	int			version;
1264 
1265 	/* initialize */
1266 	mdclrerror(ep);
1267 	(void) memset(&v2_args, 0, sizeof (v2_args));
1268 	(void) memset(&res, 0, sizeof (res));
1269 
1270 	/* build args */
1271 	v2_args.rev = MD_METAD_ARGS_REV_1;
1272 	args = &v2_args.mdrpc_host_2_args_u.rev1;
1273 	args->sp = sp;
1274 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1275 	args->hosts.hosts_len = node_c;
1276 	args->hosts.hosts_val = node_v;
1277 
1278 	/* do it */
1279 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1280 		int	bool;
1281 		bool = mdrpc_delhosts_2_svc(&v2_args, &res, NULL);
1282 		assert(bool == TRUE);
1283 		(void) mdstealerror(ep, &res.status);
1284 	} else {
1285 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1286 			return (-1);
1287 
1288 		/*
1289 		 * Check the client handle for the version
1290 		 * and invoke the appropriate version of the
1291 		 * remote procedure
1292 		 */
1293 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1294 
1295 		if (version == METAD_VERSION) {	/* version 1 */
1296 			if (mdrpc_delhosts_1(args, &res, clntp) != RPC_SUCCESS)
1297 				(void) mdrpcerror(ep, clntp, hostname,
1298 				dgettext(TEXT_DOMAIN, "metad delete hosts"));
1299 			else
1300 				(void) mdstealerror(ep, &res.status);
1301 		} else {
1302 			if (mdrpc_delhosts_2(&v2_args, &res, clntp) !=
1303 			    RPC_SUCCESS)
1304 				(void) mdrpcerror(ep, clntp, hostname,
1305 				dgettext(TEXT_DOMAIN, "metad delete hosts"));
1306 			else
1307 				(void) mdstealerror(ep, &res.status);
1308 		}
1309 
1310 		metarpcclose(clntp);
1311 	}
1312 
1313 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1314 
1315 	if (! mdisok(ep))
1316 		return (-1);
1317 
1318 	return (0);
1319 }
1320 
1321 /*
1322  * Delete diskset.
1323  */
1324 int
1325 clnt_delset(
1326 	char			*hostname,
1327 	mdsetname_t		*sp,
1328 	md_error_t		*ep
1329 )
1330 {
1331 	CLIENT			*clntp;
1332 	mdrpc_sp_args		*args;
1333 	mdrpc_sp_2_args		v2_args;
1334 	mdrpc_generic_res	res;
1335 	int			version;
1336 
1337 	/* initialize */
1338 	mdclrerror(ep);
1339 	(void) memset(&v2_args, 0, sizeof (v2_args));
1340 	(void) memset(&res, 0, sizeof (res));
1341 
1342 	/* build args */
1343 	v2_args.rev = MD_METAD_ARGS_REV_1;
1344 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
1345 	args->sp = sp;
1346 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1347 
1348 	/* do it */
1349 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1350 		int	bool;
1351 		bool = mdrpc_delset_2_svc(&v2_args, &res, NULL);
1352 		assert(bool == TRUE);
1353 		(void) mdstealerror(ep, &res.status);
1354 	} else {
1355 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1356 			return (-1);
1357 
1358 		/*
1359 		 * Check the client handle for the version
1360 		 * and invoke the appropriate version of the
1361 		 * remote procedure
1362 		 */
1363 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1364 
1365 		if (version == METAD_VERSION) {	/* version 1 */
1366 			if (mdrpc_delset_1(args, &res, clntp) != RPC_SUCCESS)
1367 				(void) mdrpcerror(ep, clntp, hostname,
1368 				dgettext(TEXT_DOMAIN, "metad delete set"));
1369 			else
1370 				(void) mdstealerror(ep, &res.status);
1371 		} else {
1372 			if (mdrpc_delset_2(&v2_args, &res, clntp) !=
1373 			    RPC_SUCCESS)
1374 				(void) mdrpcerror(ep, clntp, hostname,
1375 				dgettext(TEXT_DOMAIN, "metad delete set"));
1376 			else
1377 				(void) mdstealerror(ep, &res.status);
1378 		}
1379 
1380 		metarpcclose(clntp);
1381 	}
1382 
1383 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1384 
1385 	if (! mdisok(ep))
1386 		return (-1);
1387 
1388 	return (0);
1389 }
1390 
1391 /*
1392  * return remote device info
1393  */
1394 int
1395 clnt_devinfo(
1396 	char			*hostname,
1397 	mdsetname_t		*sp,
1398 	mddrivename_t		*dp,
1399 	md_dev64_t		*ret_dev,
1400 	time_t			*ret_timestamp,
1401 	md_error_t		*ep
1402 )
1403 {
1404 	CLIENT			*clntp;
1405 	mdrpc_devinfo_args	v1_args;
1406 	mdrpc_devinfo_2_args	v2_args;
1407 	mdrpc_devinfo_2_args_r1	*v21_args;
1408 	mdrpc_devinfo_res	v1_res;
1409 	mdrpc_devinfo_2_res	v2_res;
1410 	int			rval, version;
1411 
1412 	/* initialize */
1413 	mdclrerror(ep);
1414 	(void) memset(&v1_args, 0, sizeof (v1_args));
1415 	(void) memset(&v2_args, 0, sizeof (v2_args));
1416 	(void) memset(&v1_res,  0, sizeof (v1_res));
1417 	(void) memset(&v2_res, 	0, sizeof (v2_res));
1418 
1419 	/* build args */
1420 	v2_args.rev = MD_METAD_ARGS_REV_1;
1421 	v21_args = &v2_args.mdrpc_devinfo_2_args_u.rev1;
1422 	v21_args->sp = sp;
1423 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1424 	v21_args->drivenamep = dp;
1425 
1426 	/* do it */
1427 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1428 		int	bool;
1429 
1430 		/*
1431 		 * If the server is local, we call the v2 procedure.
1432 		 */
1433 		bool = mdrpc_devinfo_2_svc(&v2_args, &v2_res, NULL);
1434 		assert(bool == TRUE);
1435 		(void) mdstealerror(ep, &v1_res.status);
1436 	} else {
1437 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1438 			return (-1);
1439 
1440 		/*
1441 		 * Check the client handle for the version
1442 		 * and invoke the appropriate version of
1443 		 * the remote procedure.
1444 		 */
1445 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1446 
1447 		if (version == METAD_VERSION) {	/* version 1 */
1448 			v1_args.drivenamep =
1449 			    Zalloc(sizeof (o_mddrivename_t));
1450 			v1_args.drivenamep->parts.parts_val =
1451 			    Zalloc((sizeof (o_mdname_t)) *
1452 			    dp->parts.parts_len);
1453 
1454 			/* build args */
1455 			v1_args.sp = sp;
1456 			v1_args.cl_sk = cl_get_setkey(sp->setno,
1457 			    sp->setname);
1458 
1459 			/*
1460 			 * Convert v2 arguments to v1 arguments
1461 			 * before sending over the wire.
1462 			 */
1463 			meta_conv_drvname_new2old(v1_args.drivenamep,
1464 			    v21_args->drivenamep);
1465 
1466 			rval = mdrpc_devinfo_1(&v1_args, &v1_res, clntp);
1467 
1468 			free(v1_args.drivenamep->parts.parts_val);
1469 			free(v1_args.drivenamep);
1470 
1471 			if (rval != RPC_SUCCESS)
1472 				(void) mdrpcerror(ep, clntp, hostname,
1473 				    dgettext(TEXT_DOMAIN, "metad device info"));
1474 			else
1475 				(void) mdstealerror(ep, &v1_res.status);
1476 		} else {			/* version 2 */
1477 			rval = mdrpc_devinfo_2(&v2_args, &v2_res, clntp);
1478 			if (rval != RPC_SUCCESS)
1479 				(void) mdrpcerror(ep, clntp, hostname,
1480 				    dgettext(TEXT_DOMAIN, "metad device info"));
1481 			else
1482 				(void) mdstealerror(ep, &v2_res.status);
1483 		}
1484 
1485 		metarpcclose(clntp);
1486 	}
1487 
1488 	if (mdisok(ep)) {
1489 		/* do something with the results */
1490 		rval = 0;
1491 
1492 		if (ret_dev != NULL) {
1493 			if (version == METAD_VERSION)
1494 				*ret_dev = meta_expldev(v1_res.dev);
1495 			else
1496 				*ret_dev = v2_res.dev;
1497 		}
1498 
1499 		if (ret_timestamp != NULL) {
1500 			if (version == METAD_VERSION)
1501 				*ret_timestamp = v1_res.vtime;
1502 			else
1503 				*ret_timestamp = v2_res.vtime;
1504 		}
1505 	}
1506 
1507 	if (version == METAD_VERSION)
1508 		xdr_free(xdr_mdrpc_devinfo_res, (char *)&v1_res);
1509 	else
1510 		xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&v2_res);
1511 
1512 	return (rval);
1513 }
1514 
1515 /*
1516  * return remote device info
1517  */
1518 int
1519 clnt_devid(
1520 	char			*hostname,
1521 	mdsetname_t		*sp,
1522 	mddrivename_t		*dp,
1523 	char			**ret_encdevid,
1524 	md_error_t		*ep
1525 )
1526 {
1527 	CLIENT			*clntp;
1528 	mdrpc_devid_args	*args;
1529 	mdrpc_devid_2_args	v2_args;
1530 	mdrpc_devid_res		res;
1531 	int			rval;
1532 	int			version;
1533 
1534 	/* initialize */
1535 	mdclrerror(ep);
1536 	(void) memset(&v2_args, 0, sizeof (v2_args));
1537 	(void) memset(&res, 0, sizeof (res));
1538 
1539 	/* build args */
1540 	v2_args.rev = MD_METAD_ARGS_REV_1;
1541 	args = &v2_args.mdrpc_devid_2_args_u.rev1;
1542 	args->sp = sp;
1543 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1544 	args->drivenamep = dp;
1545 
1546 	/* do it */
1547 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1548 		int	bool;
1549 
1550 		/*
1551 		 * If the server is local, we call the v2 procedure.
1552 		 */
1553 		bool = mdrpc_devid_2_svc(&v2_args, &res, NULL);
1554 		assert(bool == TRUE);
1555 		(void) mdstealerror(ep, &res.status);
1556 	} else {
1557 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1558 			return (-1);
1559 
1560 		/*
1561 		 * Check the client handle for the version
1562 		 */
1563 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1564 
1565 		/*
1566 		 * If the client is version 1, return error
1567 		 * otherwise, make the remote procedure call.
1568 		 */
1569 		if (version == METAD_VERSION) {	/* version 1 */
1570 			(void) mddserror(ep, MDE_DS_DRIVENOTONHOST, sp->setno,
1571 			    hostname, dp->cname, sp->setname);
1572 		} else {			/* version 2 */
1573 			rval = mdrpc_devid_2(&v2_args, &res, clntp);
1574 
1575 			if (rval != RPC_SUCCESS)
1576 			    (void) mdrpcerror(ep, clntp, hostname,
1577 			    dgettext(TEXT_DOMAIN, "metad devid info"));
1578 			else
1579 			    (void) mdstealerror(ep, &res.status);
1580 		}
1581 
1582 		metarpcclose(clntp);
1583 	}
1584 
1585 	if (mdisok(ep)) {
1586 		/* do something with the results */
1587 		rval = 0;
1588 
1589 		if (ret_encdevid != NULL)
1590 			*ret_encdevid = strdup(res.enc_devid);
1591 
1592 	}
1593 
1594 	xdr_free(xdr_mdrpc_devid_res, (char *)&res);
1595 
1596 	return (rval);
1597 }
1598 
1599 /*
1600  * Get the device information of a disk on a remote host. The information
1601  * retrieved is the device's name, the associated driver and the dev_t.
1602  * The lookup is performed by using the devid of the disk as this is
1603  * unique to the disk.  The device name on the originating node is passed
1604  * in.  If that devname is found when doing the devid to namelist translation
1605  * then that value is used to make the device names as consistent as possible
1606  * across the nodes.
1607  *
1608  * An attempt is made to retrieve this information by calling
1609  * mdrpc_devinfo_by_devid_name_2_svc.  Locally this call should always
1610  * succeed.  In the case where a call is made through a CLIENT handle,
1611  * it is possible that the function hasn't been implemented on the called
1612  * node.  If this is the case fall back to mdrpc_devinfo_by_devidstr_2_svc.
1613  *
1614  * Returns:
1615  * 	-1 	Error
1616  * 	ENOTSUP Operation not supported i.e. procedure not supported on
1617  * 		the remote node
1618  * 	0	Success
1619  */
1620 int
1621 clnt_devinfo_by_devid(
1622 	char		*hostname,
1623 	mdsetname_t	*sp,
1624 	char		*devidstr,
1625 	md_dev64_t	*ret_dev,
1626 	char		*orig_devname,
1627 	char		**ret_devname,
1628 	char		**ret_driver,
1629 	md_error_t	*ep
1630 )
1631 {
1632 	CLIENT			*clntp;
1633 	mdrpc_devidstr_args	devid_args;
1634 	mdrpc_devid_name_args	*args;
1635 	mdrpc_devid_name_2_args	v2_args;
1636 	mdrpc_devinfo_2_res	res;
1637 	int			rval;
1638 	int			version;
1639 
1640 	/* initialize */
1641 	mdclrerror(ep);
1642 	(void) memset(&v2_args, 0, sizeof (v2_args));
1643 	(void) memset(&res, 0, sizeof (res));
1644 
1645 	/* build args */
1646 	v2_args.rev = MD_METAD_ARGS_REV_1;
1647 	args = &v2_args.mdrpc_devid_name_2_args_u.rev1;
1648 	args->enc_devid = devidstr;
1649 	args->orig_devname = orig_devname;
1650 	args->sp = sp;
1651 
1652 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1653 		int	bool;
1654 
1655 		/*
1656 		 * We are calling this locally so call the function
1657 		 * directly.
1658 		 */
1659 		bool = mdrpc_devinfo_by_devid_name_2_svc(&v2_args, &res, NULL);
1660 		assert(bool == TRUE);
1661 		(void) mdstealerror(ep, &res.status);
1662 	} else {
1663 
1664 		/* open connection */
1665 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
1666 			return (-1);
1667 		}
1668 
1669 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1670 
1671 		if (version == METAD_VERSION) { /* Version 1 */
1672 			metarpcclose(clntp);
1673 			return (ENOTSUP);
1674 		}
1675 
1676 		rval = mdrpc_devinfo_by_devid_name_2(&v2_args, &res, clntp);
1677 
1678 		if (rval != RPC_SUCCESS) {
1679 			/* try falling back to devidstr_2_svc */
1680 			(void) memset(&devid_args, 0, sizeof (devid_args));
1681 			(void) memset(&res, 0, sizeof (res));
1682 
1683 			devid_args.enc_devid = devidstr;
1684 			devid_args.sp = sp;
1685 
1686 			rval = mdrpc_devinfo_by_devid_2(
1687 					&devid_args, &res, clntp);
1688 
1689 			if (rval != RPC_SUCCESS) {
1690 				(void) mdrpcerror(ep, clntp, hostname,
1691 				    dgettext(TEXT_DOMAIN,
1692 				    "metad devinfo by devid"));
1693 			} else {
1694 				(void) mdstealerror(ep, &res.status);
1695 			}
1696 		} else {
1697 			(void) mdstealerror(ep, &res.status);
1698 		}
1699 		metarpcclose(clntp);
1700 	}
1701 
1702 	if (mdisok(ep)) {
1703 		rval = 0;
1704 		if (ret_dev != NULL)
1705 			*ret_dev = res.dev;
1706 
1707 		if (ret_devname != NULL && res.devname != NULL)
1708 			*ret_devname = Strdup(res.devname);
1709 
1710 		if (ret_driver != NULL && res.drivername != NULL)
1711 			*ret_driver = Strdup(res.drivername);
1712 	}
1713 
1714 	xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&res);
1715 
1716 	if (! mdisok(ep))
1717 		return (-1);
1718 
1719 	return (0);
1720 
1721 }
1722 
1723 
1724 /*
1725  * return status of whether driver is used, mount
1726  */
1727 int
1728 clnt_drvused(
1729 	char			*hostname,
1730 	mdsetname_t		*sp,
1731 	mddrivename_t		*dp,
1732 	md_error_t		*ep
1733 )
1734 {
1735 	CLIENT			*clntp;
1736 	mdrpc_drvused_args	v1_args;
1737 	mdrpc_drvused_2_args	v2_args;
1738 	mdrpc_drvused_2_args_r1	*v21_args;
1739 	mdrpc_generic_res	res;
1740 	int			rval;
1741 	int			version;
1742 
1743 	/* initialize */
1744 	mdclrerror(ep);
1745 	(void) memset(&v1_args, 0, sizeof (v1_args));
1746 	(void) memset(&v2_args, 0, sizeof (v2_args));
1747 	(void) memset(&res, 0, sizeof (res));
1748 
1749 	/* build args */
1750 	v2_args.rev = MD_METAD_ARGS_REV_1;
1751 	v21_args = &v2_args.mdrpc_drvused_2_args_u.rev1;
1752 	v21_args->sp = sp;
1753 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
1754 	v21_args->drivenamep = dp;
1755 
1756 	/* do it */
1757 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1758 		int	bool;
1759 
1760 		/*
1761 		 * If the server is local, we call the v2 procedure
1762 		 */
1763 		bool = mdrpc_drvused_2_svc(&v2_args, &res, NULL);
1764 		assert(bool == TRUE);
1765 		(void) mdstealerror(ep, &res.status);
1766 	} else {
1767 		/* open connection */
1768 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
1769 			return (-1);
1770 
1771 		/*
1772 		 * Check the client handle for the version
1773 		 * and invoke the appropriate version of the
1774 		 * remote procedure
1775 		 */
1776 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1777 
1778 		if (version == METAD_VERSION) {	/* version 1 */
1779 			v1_args.drivenamep =
1780 			    Zalloc(sizeof (o_mddrivename_t));
1781 			v1_args.drivenamep->parts.parts_val =
1782 			    Zalloc((sizeof (o_mdname_t)) *
1783 			    dp->parts.parts_len);
1784 
1785 			/* build args */
1786 			v1_args.sp = sp;
1787 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
1788 
1789 			/* Convert v2 args to v1 args */
1790 			meta_conv_drvname_new2old(v1_args.drivenamep,
1791 			    v21_args->drivenamep);
1792 
1793 			rval = mdrpc_drvused_1(&v1_args, &res, clntp);
1794 
1795 			free(v1_args.drivenamep->parts.parts_val);
1796 			free(v1_args.drivenamep);
1797 
1798 			if (rval != RPC_SUCCESS)
1799 				(void) mdrpcerror(ep, clntp, hostname,
1800 				    dgettext(TEXT_DOMAIN, "metad drive used"));
1801 			else
1802 				(void) mdstealerror(ep, &res.status);
1803 		} else {			/* version 2 */
1804 			rval = mdrpc_drvused_2(&v2_args, &res, clntp);
1805 			if (rval != RPC_SUCCESS)
1806 				(void) mdrpcerror(ep, clntp, hostname,
1807 				    dgettext(TEXT_DOMAIN, "metad drive used"));
1808 			else
1809 				(void) mdstealerror(ep, &res.status);
1810 		}
1811 
1812 		metarpcclose(clntp);
1813 	}
1814 
1815 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
1816 
1817 	if (! mdisok(ep))
1818 		return (-1);
1819 
1820 	return (0);
1821 }
1822 
1823 void
1824 free_sr(md_set_record *sr)
1825 {
1826 	mdrpc_getset_res	res;
1827 	mdrpc_mngetset_res	mnres;
1828 
1829 	if (md_in_daemon)
1830 		return;
1831 
1832 	/*
1833 	 * dummy up a result struct, to do a deep free of the (mn)sr.
1834 	 * (A deep free means that the xdr_free code will free the
1835 	 * linked list of drive records for the sr and will also free
1836 	 * the linked list of node records for the mnsr.)
1837 	 */
1838 	if (MD_MNSET_REC(sr)) {
1839 		(void) memset(&mnres, 0, sizeof (mnres));
1840 		mnres.mnsr = (struct md_mnset_record *)sr;
1841 		xdr_free(xdr_mdrpc_mngetset_res, (char *)&mnres);
1842 	} else {
1843 		(void) memset(&res, 0, sizeof (res));
1844 		res.sr = sr;
1845 		xdr_free(xdr_mdrpc_getset_res, (char *)&res);
1846 	}
1847 }
1848 
1849 void
1850 short_circuit_getset(
1851 	mdrpc_getset_args	*args,
1852 	mdrpc_getset_res	*res
1853 )
1854 {
1855 	if (args->setname != NULL)
1856 		res->sr = metad_getsetbyname(args->setname, &res->status);
1857 	else
1858 		res->sr = metad_getsetbynum(args->setno, &res->status);
1859 }
1860 
1861 void
1862 short_circuit_mngetset(
1863 	mdrpc_getset_args	*args,
1864 	mdrpc_mngetset_res	*res
1865 )
1866 {
1867 	md_set_record		*sr;
1868 	if (args->setname != NULL)
1869 		sr = metad_getsetbyname(args->setname, &res->status);
1870 	else
1871 		sr = metad_getsetbynum(args->setno, &res->status);
1872 
1873 	if (MD_MNSET_REC(sr)) {
1874 		res->mnsr = (struct md_mnset_record *)sr;
1875 	} else {
1876 		res->mnsr = NULL;
1877 	}
1878 }
1879 
1880 static int
1881 is_auto_take_set(char *setname, set_t setno)
1882 {
1883 	if (setname != NULL)
1884 	    return (metad_isautotakebyname(setname));
1885 	else
1886 	    return (metad_isautotakebynum(setno));
1887 }
1888 
1889 /*
1890  * return the diskset record, and drive records.
1891  * If record is a MNdiskset record, then only the first md_set_record
1892  * bytes were copied from the daemon.
1893  */
1894 int
1895 clnt_getset(
1896 	char			*hostname,
1897 	char			*setname,
1898 	set_t			setno,
1899 	md_set_record		**ret_sr,
1900 	md_error_t		*ep
1901 )
1902 {
1903 	CLIENT			*clntp;
1904 	mdrpc_getset_args	*args;
1905 	mdrpc_getset_2_args	v2_args;
1906 	mdrpc_getset_res	res;
1907 	int			rval = -1;
1908 	int			version;
1909 
1910 	/* initialize */
1911 	mdclrerror(ep);
1912 	(void) memset(&v2_args, 0, sizeof (v2_args));
1913 	(void) memset(&res, 0, sizeof (res));
1914 
1915 	/* build args */
1916 	v2_args.rev = MD_METAD_ARGS_REV_1;
1917 	args = &v2_args.mdrpc_getset_2_args_u.rev1;
1918 	args->setname = setname;
1919 	args->setno   = setno;
1920 
1921 	/* do it */
1922 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
1923 		short_circuit_getset(args, &res);
1924 		(void) mdstealerror(ep, &res.status);
1925 	} else {
1926 	    if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
1927 		/*
1928 		 * This has to work during the boot up before the rpc.metad can
1929 		 * run.  Check to see if we can handle this as a strictly local
1930 		 * diskset.
1931 		 */
1932 		if (is_auto_take_set(setname, setno)) {
1933 		    mdclrerror(ep);
1934 		    short_circuit_getset(args, &res);
1935 		    res.sr = setdup(res.sr);
1936 		    (void) mdstealerror(ep, &res.status);
1937 		} else {
1938 		    return (-1);
1939 		}
1940 	    } else {
1941 
1942 		/*
1943 		 * Check the client handle for the version
1944 		 * and invoke the appropriate version of the
1945 		 * remote procedure
1946 		 */
1947 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
1948 
1949 		if (version == METAD_VERSION) {	/* version 1 */
1950 			if (mdrpc_getset_1(args, &res, clntp) != RPC_SUCCESS)
1951 				(void) mdrpcerror(ep, clntp, hostname,
1952 				dgettext(TEXT_DOMAIN, "metad get set"));
1953 			else
1954 				(void) mdstealerror(ep, &res.status);
1955 		} else {
1956 			if (mdrpc_getset_2(&v2_args, &res, clntp) !=
1957 			    RPC_SUCCESS)
1958 				(void) mdrpcerror(ep, clntp, hostname,
1959 				dgettext(TEXT_DOMAIN, "metad get set"));
1960 			else
1961 				(void) mdstealerror(ep, &res.status);
1962 		}
1963 
1964 		metarpcclose(clntp);
1965 	    }
1966 	}
1967 
1968 	if (mdisok(ep)) {
1969 		rval = 0;
1970 		if (ret_sr != NULL)
1971 			*ret_sr = res.sr;
1972 		else
1973 			if (! md_in_daemon)
1974 				xdr_free(xdr_mdrpc_getset_res, (char *)&res);
1975 	}
1976 
1977 	return (rval);
1978 }
1979 
1980 /*
1981  * return the multi-node diskset record, drive records and node records.
1982  */
1983 int
1984 clnt_mngetset(
1985 	char			*hostname,
1986 	char			*setname,
1987 	set_t			setno,
1988 	md_mnset_record		**ret_mnsr,
1989 	md_error_t		*ep
1990 )
1991 {
1992 	CLIENT			*clntp;
1993 	mdrpc_getset_args	*args;
1994 	mdrpc_getset_2_args	v2_args;
1995 	mdrpc_mngetset_res	res;
1996 	int			rval = -1;
1997 	int			version;
1998 
1999 	/* initialize */
2000 	mdclrerror(ep);
2001 	(void) memset(&v2_args, 0, sizeof (v2_args));
2002 	(void) memset(&res, 0, sizeof (res));
2003 
2004 	/* build args */
2005 	v2_args.rev = MD_METAD_ARGS_REV_1;
2006 	args = &v2_args.mdrpc_getset_2_args_u.rev1;
2007 	args->setname = setname;
2008 	args->setno   = setno;
2009 
2010 	/* do it */
2011 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2012 		short_circuit_mngetset(args, &res);
2013 		(void) mdstealerror(ep, &res.status);
2014 	} else {
2015 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2016 			return (-1);
2017 
2018 		/*
2019 		 * Check the client handle for the version
2020 		 */
2021 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2022 
2023 		/*
2024 		 * If the client is version 1, return error
2025 		 * otherwise, make the remote procedure call.
2026 		 */
2027 		if (version == METAD_VERSION) { /* version 1 */
2028 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2029 				setno, hostname, NULL, setname);
2030 			metarpcclose(clntp);
2031 			return (-1);
2032 		} else {
2033 			if (mdrpc_mngetset_2(&v2_args, &res, clntp)
2034 							!= RPC_SUCCESS)
2035 				(void) mdrpcerror(ep, clntp, hostname,
2036 				    dgettext(TEXT_DOMAIN, "metad mn get set"));
2037 			else
2038 				(void) mdstealerror(ep, &res.status);
2039 		}
2040 
2041 		metarpcclose(clntp);
2042 	}
2043 
2044 	/* If no ep error and no version mismatch - rpc call worked ok */
2045 	if (mdisok(ep)) {
2046 		rval = 0;
2047 		if (ret_mnsr != NULL)
2048 			*ret_mnsr = res.mnsr;
2049 		else
2050 			if (! md_in_daemon)
2051 				xdr_free(xdr_mdrpc_mngetset_res, (char *)&res);
2052 	}
2053 
2054 	return (rval);
2055 }
2056 
2057 /*
2058  * Set master nodeid and nodename in multi-node set record.
2059  */
2060 int
2061 clnt_mnsetmaster(
2062 	char			*hostname,
2063 	mdsetname_t		*sp,
2064 	md_node_nm_t		master_nodenm,
2065 	int			master_nodeid,
2066 	md_error_t		*ep
2067 )
2068 {
2069 	CLIENT			*clntp;
2070 	mdrpc_mnsetmaster_args	*args;
2071 	mdrpc_mnsetmaster_2_args	v2_args;
2072 	mdrpc_generic_res	res;
2073 	int			version;
2074 
2075 	/* initialize */
2076 	mdclrerror(ep);
2077 	(void) memset(&v2_args, 0, sizeof (v2_args));
2078 	(void) memset(&res, 0, sizeof (res));
2079 
2080 	/* build args */
2081 	v2_args.rev = MD_METAD_ARGS_REV_1;
2082 	args = &v2_args.mdrpc_mnsetmaster_2_args_u.rev1;
2083 	args->sp = sp;
2084 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2085 	(void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME);
2086 	args->master_nodeid = master_nodeid;
2087 
2088 	/* do it */
2089 	if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2090 		return (-1);
2091 
2092 	/*
2093 	 * Check the client handle for the version
2094 	 */
2095 	CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2096 
2097 	/*
2098 	 * If the client is version 1, return error
2099 	 * otherwise, make the remote procedure call.
2100 	 */
2101 	if (version == METAD_VERSION) { /* version 1 */
2102 		(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2103 			sp->setno, hostname, NULL, sp->setname);
2104 		metarpcclose(clntp);
2105 		return (-1);
2106 	} else {
2107 		if (mdrpc_mnsetmaster_2(&v2_args, &res, clntp) != RPC_SUCCESS)
2108 			(void) mdrpcerror(ep, clntp, hostname,
2109 			dgettext(TEXT_DOMAIN, "metad multi-owner set master"));
2110 		else
2111 			(void) mdstealerror(ep, &res.status);
2112 	}
2113 
2114 	metarpcclose(clntp);
2115 
2116 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2117 
2118 	if (! mdisok(ep))
2119 		return (-1);
2120 
2121 	return (0);
2122 }
2123 
2124 /*
2125  * Get the MH timeout values.
2126  */
2127 int
2128 clnt_gtimeout(
2129 	char			*hostname,
2130 	mdsetname_t		*sp,
2131 	mhd_mhiargs_t		*ret_mhiargs,
2132 	md_error_t		*ep
2133 )
2134 {
2135 	CLIENT			*clntp;
2136 	mdrpc_sp_args		*args;
2137 	mdrpc_sp_2_args		v2_args;
2138 	mdrpc_gtimeout_res	res;
2139 	int			rval = -1;
2140 	int			version;
2141 
2142 	/* initialize */
2143 	mdclrerror(ep);
2144 	(void) memset(&v2_args, 0, sizeof (v2_args));
2145 	(void) memset(&res, 0, sizeof (res));
2146 
2147 	/* build args */
2148 	v2_args.rev = MD_METAD_ARGS_REV_1;
2149 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
2150 	args->sp = sp;
2151 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2152 
2153 	/* do it */
2154 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2155 		int	bool;
2156 		bool = mdrpc_gtimeout_2_svc(&v2_args, &res, NULL);
2157 		assert(bool == TRUE);
2158 		(void) mdstealerror(ep, &res.status);
2159 	} else {
2160 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2161 			return (-1);
2162 
2163 		/*
2164 		 * Check the client handle for the version
2165 		 * and invoke the appropriate version of the
2166 		 * remote procedure
2167 		 */
2168 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2169 
2170 		if (version == METAD_VERSION) {	/* version 1 */
2171 			if (mdrpc_gtimeout_1(args, &res, clntp) != RPC_SUCCESS)
2172 				(void) mdrpcerror(ep, clntp, hostname,
2173 				dgettext(TEXT_DOMAIN, "metad get timeout"));
2174 			else
2175 				(void) mdstealerror(ep, &res.status);
2176 		} else {
2177 			if (mdrpc_gtimeout_2(&v2_args, &res, clntp) !=
2178 			    RPC_SUCCESS)
2179 				(void) mdrpcerror(ep, clntp, hostname,
2180 				dgettext(TEXT_DOMAIN, "metad get timeout"));
2181 			else
2182 				(void) mdstealerror(ep, &res.status);
2183 		}
2184 
2185 		metarpcclose(clntp);
2186 	}
2187 
2188 	if (mdisok(ep)) {
2189 
2190 		/* do something with the results */
2191 		rval = 0;
2192 
2193 		/* copy md_mhiargs_t */
2194 		if (ret_mhiargs != NULL)
2195 			*ret_mhiargs = *res.mhiargsp;
2196 	}
2197 
2198 	xdr_free(xdr_mdrpc_gtimeout_res, (char *)&res);
2199 
2200 	return (rval);
2201 }
2202 
2203 /*
2204  * get real hostname from remote host
2205  */
2206 int
2207 clnt_hostname(
2208 	char			*hostname,
2209 	char			**ret_hostname,
2210 	md_error_t		*ep
2211 )
2212 {
2213 	CLIENT			*clntp;
2214 	mdrpc_null_args		args;
2215 	mdrpc_hostname_res	res;
2216 	int			rval = -1;
2217 
2218 	/* initialize */
2219 	mdclrerror(ep);
2220 	(void) memset(&args, 0, sizeof (args));
2221 	(void) memset(&res, 0, sizeof (res));
2222 
2223 	/* build args */
2224 	args.cl_sk = NULL;
2225 
2226 	/* do it */
2227 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2228 		int	bool;
2229 		bool = mdrpc_hostname_1_svc(&args, &res, NULL);
2230 		assert(bool == TRUE);
2231 		(void) mdstealerror(ep, &res.status);
2232 	} else {
2233 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2234 			return (-1);
2235 
2236 		if (mdrpc_hostname_1(&args, &res, clntp) != RPC_SUCCESS)
2237 			(void) mdrpcerror(ep, clntp, hostname,
2238 			    dgettext(TEXT_DOMAIN, "metad hostname"));
2239 		else
2240 			(void) mdstealerror(ep, &res.status);
2241 
2242 		metarpcclose(clntp);
2243 	}
2244 
2245 	if (mdisok(ep)) {
2246 		/* do something with the results */
2247 		rval = 0;
2248 
2249 		if (ret_hostname != NULL)
2250 			*ret_hostname = Strdup(res.hostname);
2251 	}
2252 
2253 	xdr_free(xdr_mdrpc_hostname_res, (char *)&res);
2254 
2255 	return (rval);
2256 }
2257 
2258 /*
2259  * NULLPROC - just returns a response
2260  */
2261 int
2262 clnt_nullproc(
2263 	char			*hostname,
2264 	md_error_t		*ep
2265 )
2266 {
2267 	CLIENT			*clntp;
2268 
2269 	/* initialize */
2270 	mdclrerror(ep);
2271 
2272 	/* do it */
2273 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2274 		int	bool;
2275 		bool = mdrpc_nullproc_1_svc(NULL, ep, NULL);
2276 		assert(bool == TRUE);
2277 	} else {
2278 		if ((clntp = metarpcopen(hostname, CL_DEF_TMO, ep)) == NULL)
2279 			return (-1);
2280 
2281 		if (mdrpc_nullproc_1(NULL, ep, clntp) != RPC_SUCCESS)
2282 			(void) mdrpcerror(ep, clntp, hostname,
2283 			    dgettext(TEXT_DOMAIN, "metad nullproc"));
2284 
2285 		metarpcclose(clntp);
2286 	}
2287 
2288 	if (! mdisok(ep))
2289 		return (-1);
2290 
2291 	return (0);
2292 }
2293 
2294 /*
2295  * does host own the set?
2296  */
2297 int
2298 clnt_ownset(
2299 	char			*hostname,
2300 	mdsetname_t		*sp,
2301 	int			*ret_bool,
2302 	md_error_t		*ep
2303 )
2304 {
2305 	CLIENT			*clntp;
2306 	mdrpc_sp_args		*args;
2307 	mdrpc_sp_2_args		v2_args;
2308 	mdrpc_bool_res		res;
2309 	int			rval = -1;
2310 	int			version;
2311 
2312 	/* initialize */
2313 	mdclrerror(ep);
2314 	(void) memset(&v2_args, 0, sizeof (v2_args));
2315 	(void) memset(&res, 0, sizeof (res));
2316 
2317 	/* build args */
2318 	v2_args.rev = MD_METAD_ARGS_REV_1;
2319 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
2320 	args->sp = sp;
2321 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2322 
2323 	/* do it */
2324 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2325 		int	bool;
2326 		bool = mdrpc_ownset_2_svc(&v2_args, &res, NULL);
2327 		assert(bool == TRUE);
2328 		(void) mdstealerror(ep, &res.status);
2329 	} else {
2330 	    if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
2331 		/*
2332 		 * This has to work in the code path from libpreen which is
2333 		 * running within fsck before the rpc.metad can run.  Check
2334 		 * to see if we should handle this as an auto-take diskset.
2335 		 */
2336 		if (is_auto_take_set(sp->setname, sp->setno)) {
2337 		    /* Can't call mdrpc_ownset_2_svc since not in daemon */
2338 		    mdclrerror(ep);
2339 		    if (s_ownset(sp->setno, ep))
2340 			res.value = TRUE;
2341 		    else
2342 			res.value = FALSE;
2343 		} else {
2344 		    return (-1);
2345 		}
2346 
2347 	    } else {
2348 
2349 		/*
2350 		 * Check the client handle for the version
2351 		 * and invoke the appropriate version of the
2352 		 * remote procedure
2353 		 */
2354 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2355 
2356 		if (version == METAD_VERSION) {	/* version 1 */
2357 			if (mdrpc_ownset_1(args, &res, clntp) != RPC_SUCCESS)
2358 				(void) mdrpcerror(ep, clntp, hostname,
2359 				dgettext(TEXT_DOMAIN, "metad own set"));
2360 			else
2361 				(void) mdstealerror(ep, &res.status);
2362 		} else {
2363 			if (mdrpc_ownset_2(&v2_args, &res, clntp) !=
2364 			    RPC_SUCCESS)
2365 				(void) mdrpcerror(ep, clntp, hostname,
2366 				dgettext(TEXT_DOMAIN, "metad own set"));
2367 			else
2368 				(void) mdstealerror(ep, &res.status);
2369 		}
2370 
2371 		metarpcclose(clntp);
2372 	    }
2373 	}
2374 
2375 	if (mdisok(ep)) {
2376 		/* do something with the results */
2377 		rval = 0;
2378 
2379 		if (ret_bool != NULL)
2380 			*ret_bool = res.value;
2381 	}
2382 
2383 	xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2384 
2385 	return (rval);
2386 }
2387 
2388 /*
2389  * Valid set name.
2390  */
2391 int
2392 clnt_setnameok(
2393 	char			*hostname,
2394 	mdsetname_t		*sp,
2395 	int			*ret_bool,
2396 	md_error_t		*ep
2397 )
2398 {
2399 	CLIENT			*clntp;
2400 	mdrpc_sp_args		*args;
2401 	mdrpc_sp_2_args		v2_args;
2402 	mdrpc_bool_res		res;
2403 	int			rval = -1;
2404 	int			version;
2405 
2406 	/* initialize */
2407 	mdclrerror(ep);
2408 	(void) memset(&v2_args, 0, sizeof (v2_args));
2409 	(void) memset(&res, 0, sizeof (res));
2410 
2411 	/* build args */
2412 	v2_args.rev = MD_METAD_ARGS_REV_1;
2413 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
2414 	args->sp = sp;
2415 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2416 
2417 	/* do it */
2418 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2419 		int	bool;
2420 		bool = mdrpc_setnameok_2_svc(&v2_args, &res, NULL);
2421 		assert(bool == TRUE);
2422 		(void) mdstealerror(ep, &res.status);
2423 	} else {
2424 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2425 			return (-1);
2426 
2427 		/*
2428 		 * Check the client handle for the version
2429 		 * and invoke the appropriate version of the
2430 		 * remote procedure
2431 		 */
2432 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2433 
2434 		if (version == METAD_VERSION) {	/* version 1 */
2435 			if (mdrpc_setnameok_1(args, &res, clntp) != RPC_SUCCESS)
2436 				(void) mdrpcerror(ep, clntp, hostname,
2437 				dgettext(TEXT_DOMAIN, "metad setname ok"));
2438 			else
2439 				(void) mdstealerror(ep, &res.status);
2440 		} else {
2441 			if (mdrpc_setnameok_2(&v2_args, &res, clntp) !=
2442 			    RPC_SUCCESS)
2443 				(void) mdrpcerror(ep, clntp, hostname,
2444 				dgettext(TEXT_DOMAIN, "metad setname ok"));
2445 			else
2446 				(void) mdstealerror(ep, &res.status);
2447 		}
2448 
2449 		metarpcclose(clntp);
2450 	}
2451 
2452 	if (mdisok(ep)) {
2453 		/* do something with the results */
2454 		rval = 0;
2455 
2456 		if (ret_bool != NULL)
2457 			*ret_bool = res.value;
2458 	}
2459 
2460 	xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2461 
2462 	return (rval);
2463 }
2464 
2465 /*
2466  * Is set number in-use?
2467  */
2468 int
2469 clnt_setnumbusy(
2470 	char			*hostname,
2471 	set_t			setno,
2472 	int			*ret_bool,
2473 	md_error_t		*ep
2474 )
2475 {
2476 	CLIENT			*clntp;
2477 	mdrpc_setno_args	*args;
2478 	mdrpc_setno_2_args	v2_args;
2479 	mdrpc_bool_res		res;
2480 	int			rval = -1;
2481 	int			version;
2482 
2483 	/* initialize */
2484 	mdclrerror(ep);
2485 	(void) memset(&v2_args, 0, sizeof (v2_args));
2486 	(void) memset(&res, 0, sizeof (res));
2487 
2488 	/* build args */
2489 	v2_args.rev = MD_METAD_ARGS_REV_1;
2490 	args = &v2_args.mdrpc_setno_2_args_u.rev1;
2491 	args->setno = setno;
2492 	args->cl_sk = NULL;
2493 
2494 	/* do it */
2495 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2496 		int	bool;
2497 		bool = mdrpc_setnumbusy_2_svc(&v2_args, &res, NULL);
2498 		assert(bool == TRUE);
2499 		(void) mdstealerror(ep, &res.status);
2500 	} else {
2501 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2502 			return (-1);
2503 
2504 		/*
2505 		 * Check the client handle for the version
2506 		 * and invoke the appropriate version of the
2507 		 * remote procedure
2508 		 */
2509 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2510 
2511 		if (version == METAD_VERSION) {	/* version 1 */
2512 			if (mdrpc_setnumbusy_1(args, &res, clntp) !=
2513 			    RPC_SUCCESS)
2514 				(void) mdrpcerror(ep, clntp, hostname,
2515 				dgettext(TEXT_DOMAIN, "metad setnumber busy"));
2516 			else
2517 				(void) mdstealerror(ep, &res.status);
2518 		} else {
2519 			if (mdrpc_setnumbusy_2(&v2_args, &res, clntp) !=
2520 			    RPC_SUCCESS)
2521 				(void) mdrpcerror(ep, clntp, hostname,
2522 				dgettext(TEXT_DOMAIN, "metad setnumber busy"));
2523 			else
2524 				(void) mdstealerror(ep, &res.status);
2525 		}
2526 
2527 		metarpcclose(clntp);
2528 	}
2529 
2530 	if (mdisok(ep)) {
2531 		/* do something with the results */
2532 		rval = 0;
2533 
2534 		if (ret_bool != NULL)
2535 			*ret_bool = res.value;
2536 	}
2537 
2538 	xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2539 
2540 	return (rval);
2541 }
2542 
2543 /*
2544  * Set the timeout values used into the drive records.
2545  */
2546 int
2547 clnt_stimeout(
2548 	char			*hostname,
2549 	mdsetname_t		*sp,
2550 	mhd_mhiargs_t		*mhiargsp,
2551 	md_error_t		*ep
2552 )
2553 {
2554 	CLIENT			*clntp;
2555 	mdrpc_stimeout_args	*args;
2556 	mdrpc_stimeout_2_args	v2_args;
2557 	mdrpc_generic_res	res;
2558 	int			version;
2559 
2560 	/* initialize */
2561 	mdclrerror(ep);
2562 	(void) memset(&v2_args, 0, sizeof (v2_args));
2563 	(void) memset(&res, 0, sizeof (res));
2564 
2565 	/* build args */
2566 	v2_args.rev = MD_METAD_ARGS_REV_1;
2567 	args = &v2_args.mdrpc_stimeout_2_args_u.rev1;
2568 	args->sp = sp;
2569 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2570 	args->mhiargsp = mhiargsp;
2571 
2572 	/* do it */
2573 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2574 		int	bool;
2575 		bool = mdrpc_stimeout_2_svc(&v2_args, &res, NULL);
2576 		assert(bool == TRUE);
2577 		(void) mdstealerror(ep, &res.status);
2578 	} else {
2579 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2580 			return (-1);
2581 
2582 		/*
2583 		 * Check the client handle for the version
2584 		 * and invoke the appropriate version of the
2585 		 * remote procedure
2586 		 */
2587 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2588 
2589 		if (version == METAD_VERSION) {	/* version 1 */
2590 			if (mdrpc_stimeout_1(args, &res, clntp) != RPC_SUCCESS)
2591 				(void) mdrpcerror(ep, clntp, hostname,
2592 				dgettext(TEXT_DOMAIN, "metad set timeout"));
2593 			else
2594 				(void) mdstealerror(ep, &res.status);
2595 		} else {
2596 			if (mdrpc_stimeout_2(&v2_args, &res, clntp) !=
2597 			    RPC_SUCCESS)
2598 				(void) mdrpcerror(ep, clntp, hostname,
2599 				dgettext(TEXT_DOMAIN, "metad set timeout"));
2600 			else
2601 				(void) mdstealerror(ep, &res.status);
2602 		}
2603 
2604 		metarpcclose(clntp);
2605 	}
2606 
2607 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2608 
2609 	if (! mdisok(ep))
2610 		return (-1);
2611 
2612 	return (0);
2613 }
2614 
2615 /*
2616  * update drive records
2617  */
2618 int
2619 clnt_upd_dr_dbinfo(
2620 	char			*hostname,
2621 	mdsetname_t		*sp,
2622 	md_drive_desc		*dd,
2623 	md_error_t		*ep
2624 )
2625 {
2626 	CLIENT			*clntp;
2627 	mdrpc_drives_args	v1_args;
2628 	mdrpc_drives_2_args	v2_args;
2629 	mdrpc_drives_2_args_r1	*v21_args;
2630 	mdrpc_generic_res	res;
2631 	int			rval;
2632 	int			version;
2633 
2634 	/* initialize */
2635 	mdclrerror(ep);
2636 	(void) memset(&v1_args, 0, sizeof (v1_args));
2637 	(void) memset(&v2_args, 0, sizeof (v2_args));
2638 	(void) memset(&res, 0, sizeof (res));
2639 
2640 	/* build args */
2641 	v2_args.rev = MD_METAD_ARGS_REV_1;
2642 	v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
2643 	v21_args->sp = sp;
2644 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2645 	v21_args->drivedescs = dd;
2646 
2647 	/* do it */
2648 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2649 		int	bool;
2650 
2651 		/*
2652 		 * If the server is local, we call the v2 procedure
2653 		 */
2654 		bool = mdrpc_upd_dr_dbinfo_2_svc(&v2_args, &res, NULL);
2655 		assert(bool == TRUE);
2656 		(void) mdstealerror(ep, &res.status);
2657 	} else {
2658 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2659 			return (-1);
2660 
2661 		/*
2662 		 * Check the client handle for the version
2663 		 * and invoke the appropriate version of the
2664 		 * remote procedure
2665 		 */
2666 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2667 
2668 		if (version == METAD_VERSION) {	/* version 1 */
2669 
2670 			alloc_olddrvdesc(&v1_args.drivedescs, dd);
2671 
2672 			/* build args */
2673 			v1_args.sp = sp;
2674 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2675 			meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2676 
2677 			rval = mdrpc_upd_dr_dbinfo_1(&v1_args, &res, clntp);
2678 
2679 			free_olddrvdesc(v1_args.drivedescs);
2680 
2681 			if (rval != RPC_SUCCESS)
2682 				(void) mdrpcerror(ep, clntp, hostname,
2683 				    dgettext(TEXT_DOMAIN,
2684 				    "metad update drive dbinfo"));
2685 			else
2686 				(void) mdstealerror(ep, &res.status);
2687 		} else {			/* version 2 */
2688 			rval = mdrpc_upd_dr_dbinfo_2(&v2_args, &res, clntp);
2689 
2690 			if (rval != RPC_SUCCESS)
2691 				(void) mdrpcerror(ep, clntp, hostname,
2692 				    dgettext(TEXT_DOMAIN,
2693 				    "metad update drive dbinfo"));
2694 			else
2695 				(void) mdstealerror(ep, &res.status);
2696 		}
2697 
2698 		metarpcclose(clntp);
2699 	}
2700 
2701 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2702 
2703 	if (! mdisok(ep))
2704 		return (-1);
2705 
2706 	return (0);
2707 }
2708 
2709 /*
2710  * update dr_flags field of drive record.
2711  */
2712 int
2713 clnt_upd_dr_flags(
2714 	char			*hostname,
2715 	mdsetname_t		*sp,
2716 	md_drive_desc		*dd,
2717 	uint_t			new_flags,
2718 	md_error_t		*ep
2719 )
2720 {
2721 	CLIENT				*clntp;
2722 	mdrpc_upd_dr_flags_args		v1_args;
2723 	mdrpc_upd_dr_flags_2_args	v2_args;
2724 	mdrpc_upd_dr_flags_2_args_r1	*v21_args;
2725 	mdrpc_generic_res		res;
2726 	int				rval;
2727 	int				version;
2728 
2729 	/* initialize */
2730 	mdclrerror(ep);
2731 	(void) memset(&v1_args, 0, sizeof (v1_args));
2732 	(void) memset(&v2_args, 0, sizeof (v2_args));
2733 	(void) memset(&res, 0, sizeof (res));
2734 
2735 	/* build args */
2736 	v2_args.rev = MD_METAD_ARGS_REV_1;
2737 	v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1;
2738 	v21_args->sp = sp;
2739 	v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2740 	v21_args->drivedescs = dd;
2741 	v21_args->new_flags = new_flags;
2742 
2743 	/* do it */
2744 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2745 		int	bool;
2746 
2747 		/*
2748 		 * If the server is local, we call the v2 procedure
2749 		 */
2750 		bool = mdrpc_upd_dr_flags_2_svc(&v2_args, &res, NULL);
2751 		assert(bool == TRUE);
2752 		(void) mdstealerror(ep, &res.status);
2753 	} else {
2754 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2755 			return (-1);
2756 
2757 		/*
2758 		 * Check the client handle for the version
2759 		 * and invoke the appropriate version of the
2760 		 * remote procedure
2761 		 */
2762 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2763 
2764 		if (version == METAD_VERSION) {	/* version 1 */
2765 
2766 			alloc_olddrvdesc(&v1_args.drivedescs, dd);
2767 
2768 			/* build args */
2769 			v1_args.sp = sp;
2770 			v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2771 			meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2772 			v1_args.new_flags = new_flags;
2773 
2774 			rval = mdrpc_upd_dr_flags_1(&v1_args, &res, clntp);
2775 
2776 			free_olddrvdesc(v1_args.drivedescs);
2777 
2778 			if (rval != RPC_SUCCESS)
2779 				(void) mdrpcerror(ep, clntp, hostname,
2780 				    dgettext(TEXT_DOMAIN,
2781 				    "metad update drive flags"));
2782 			else
2783 				(void) mdstealerror(ep, &res.status);
2784 		} else {			/* version 2 */
2785 			rval = mdrpc_upd_dr_flags_2(&v2_args, &res, clntp);
2786 
2787 			if (rval != RPC_SUCCESS)
2788 				(void) mdrpcerror(ep, clntp, hostname,
2789 				    dgettext(TEXT_DOMAIN,
2790 				    "metad update drive flags"));
2791 			else
2792 				(void) mdstealerror(ep, &res.status);
2793 		}
2794 
2795 		metarpcclose(clntp);
2796 	}
2797 
2798 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2799 
2800 	if (! mdisok(ep)) {
2801 		if (! mdanyrpcerror(ep))
2802 			return (-1);
2803 		if (strcmp(mynode(), hostname) == 0)
2804 			return (-1);
2805 		mdclrerror(ep);
2806 	}
2807 
2808 	return (0);
2809 }
2810 
2811 /*
2812  * update set record flags
2813  * This replaces all of the sr_flags with the new_flags.  It relies on the
2814  * caller to "do the right thing" to preserve the existing flags that should
2815  * not be reset.
2816  */
2817 static int
2818 upd_sr_flags_common(
2819 	char			*hostname,
2820 	mdsetname_t		*sp,
2821 	uint_t			new_flags,
2822 	md_error_t		*ep
2823 )
2824 {
2825 	CLIENT				*clntp;
2826 	mdrpc_upd_sr_flags_args		*args;
2827 	mdrpc_upd_sr_flags_2_args	v2_args;
2828 	mdrpc_generic_res		res;
2829 	int				version;
2830 
2831 	/* initialize */
2832 	mdclrerror(ep);
2833 	(void) memset(&v2_args, 0, sizeof (v2_args));
2834 	(void) memset(&res, 0, sizeof (res));
2835 
2836 	/* build args */
2837 	v2_args.rev = MD_METAD_ARGS_REV_1;
2838 	args = &v2_args.mdrpc_upd_sr_flags_2_args_u.rev1;
2839 	args->sp = sp;
2840 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2841 
2842 	args->new_flags = new_flags;
2843 
2844 	/* do it */
2845 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2846 		int	bool;
2847 		bool = mdrpc_upd_sr_flags_2_svc(&v2_args, &res, NULL);
2848 		assert(bool == TRUE);
2849 		(void) mdstealerror(ep, &res.status);
2850 	} else {
2851 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2852 			return (-1);
2853 
2854 		/*
2855 		 * Check the client handle for the version
2856 		 * and invoke the appropriate version of the
2857 		 * remote procedure
2858 		 */
2859 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2860 
2861 		if (version == METAD_VERSION) {	/* version 1 */
2862 			if (mdrpc_upd_sr_flags_1(args, &res, clntp) !=
2863 			    RPC_SUCCESS)
2864 			    (void) mdrpcerror(ep, clntp, hostname,
2865 			    dgettext(TEXT_DOMAIN, "metad update set flags"));
2866 			else
2867 				(void) mdstealerror(ep, &res.status);
2868 		} else {
2869 			if (mdrpc_upd_sr_flags_2(&v2_args, &res, clntp) !=
2870 			    RPC_SUCCESS)
2871 			    (void) mdrpcerror(ep, clntp, hostname,
2872 			    dgettext(TEXT_DOMAIN, "metad update set flags"));
2873 			else
2874 				(void) mdstealerror(ep, &res.status);
2875 		}
2876 
2877 		metarpcclose(clntp);
2878 	}
2879 
2880 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2881 
2882 	if (! mdisok(ep)) {
2883 		if (! mdanyrpcerror(ep))
2884 			return (-1);
2885 		if (strcmp(mynode(), hostname) == 0)
2886 			return (-1);
2887 		mdclrerror(ep);
2888 	}
2889 
2890 	return (0);
2891 }
2892 
2893 /*
2894  * Enable bits in the set record flags field.  This just turns on the specified
2895  * bits and leaves the other bits alone.
2896  */
2897 int
2898 clnt_enable_sr_flags(
2899 	char			*hostname,
2900 	mdsetname_t		*sp,
2901 	uint_t			flags,
2902 	md_error_t		*ep
2903 )
2904 {
2905 	uint_t		new_flags;
2906 	md_set_desc	*sd;
2907 
2908 	mdclrerror(ep);
2909 
2910 	/* Get the flags from the current set */
2911 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
2912 		return (-1);
2913 
2914 	/* Turn on the specified bits */
2915 	new_flags = (sd->sd_flags | flags);
2916 
2917 	/* do it */
2918 	return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2919 }
2920 
2921 /*
2922  * Disable bits in the set record flags field.  This just turns off the
2923  * specified bits and leaves the other bits alone.
2924  */
2925 int
2926 clnt_disable_sr_flags(
2927 	char			*hostname,
2928 	mdsetname_t		*sp,
2929 	uint_t			flags,
2930 	md_error_t		*ep
2931 )
2932 {
2933 	uint_t		new_flags;
2934 	md_set_desc	*sd;
2935 
2936 	mdclrerror(ep);
2937 
2938 	/* Get the flags from the current set */
2939 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
2940 		return (-1);
2941 
2942 	/* Turn off the specified bits */
2943 	new_flags = (sd->sd_flags & ~flags);
2944 
2945 	/* do it */
2946 	return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2947 }
2948 
2949 /*
2950  * Assign the flags as the new value(s) for the MD_SR_STATE_FLAGS within the
2951  * set record flags field.  This actually can set any bits but only clears
2952  * the bits within the MD_SR_STATE_FLAGS subfield and leaves any other
2953  * bits turned on.  It can be used to clear (state) and set bits all in one
2954  * rpc call.
2955  */
2956 int
2957 clnt_upd_sr_flags(
2958 	char			*hostname,
2959 	mdsetname_t		*sp,
2960 	uint_t			flags,
2961 	md_error_t		*ep
2962 )
2963 {
2964 	uint_t		new_flags;
2965 	md_set_desc	*sd;
2966 
2967 	mdclrerror(ep);
2968 
2969 	/* Get the flags from the current set */
2970 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
2971 		return (-1);
2972 
2973 	/* clear the existing state flags */
2974 	sd->sd_flags &= ~MD_SR_STATE_FLAGS;
2975 
2976 	/* Or in the new value */
2977 	new_flags = (sd->sd_flags | flags);
2978 
2979 	/* do it */
2980 	return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2981 }
2982 
2983 md_setkey_t *
2984 cl_get_setkey(set_t setno, char *setname)
2985 {
2986 
2987 	if (my_cl_sk == NULL) {
2988 		my_cl_sk = Zalloc(sizeof (md_setkey_t));
2989 		my_cl_sk->sk_setno = setno;
2990 		my_cl_sk->sk_setname = Strdup(setname);
2991 		my_cl_sk->sk_host = Strdup(mynode());
2992 	} else {
2993 		my_cl_sk->sk_setno = setno;
2994 		if (my_cl_sk->sk_setname != NULL)
2995 			Free(my_cl_sk->sk_setname);
2996 		my_cl_sk->sk_setname = Strdup(setname);
2997 	}
2998 
2999 	return (my_cl_sk);
3000 }
3001 
3002 void
3003 cl_set_setkey(md_setkey_t *cl_sk)
3004 {
3005 	if ((cl_sk != NULL) && (my_cl_sk != NULL)) {
3006 		assert(my_cl_sk->sk_setno == cl_sk->sk_setno);
3007 		assert(strcmp(my_cl_sk->sk_setname, cl_sk->sk_setname) == 0);
3008 		assert(strcmp(my_cl_sk->sk_host, cl_sk->sk_host) == 0);
3009 		my_cl_sk->sk_key = cl_sk->sk_key;
3010 		return;
3011 	}
3012 
3013 	if (my_cl_sk != NULL) {
3014 		if (my_cl_sk->sk_setname != NULL)
3015 			Free(my_cl_sk->sk_setname);
3016 		if (my_cl_sk->sk_host != NULL)
3017 			Free(my_cl_sk->sk_host);
3018 		Free(my_cl_sk);
3019 	}
3020 
3021 	my_cl_sk = NULL;
3022 
3023 	/* get here, if set called before get */
3024 	if (cl_sk != NULL) {
3025 		my_cl_sk = Zalloc(sizeof (md_setkey_t));
3026 		my_cl_sk->sk_host = Strdup(cl_sk->sk_host);
3027 		my_cl_sk->sk_setno = cl_sk->sk_setno;
3028 		my_cl_sk->sk_setname = Strdup(cl_sk->sk_setname);
3029 		my_cl_sk->sk_key = cl_sk->sk_key;
3030 	}
3031 }
3032 
3033 /*
3034  * Unlock the set after operation is complete.
3035  */
3036 int
3037 clnt_unlock_set(
3038 	char			*hostname,
3039 	md_setkey_t		*cl_sk,
3040 	md_error_t		*ep
3041 )
3042 {
3043 	CLIENT			*clntp;
3044 	mdrpc_null_args		args;
3045 	mdrpc_setlock_res	res;
3046 
3047 	/* initialize */
3048 	mdclrerror(ep);
3049 	(void) memset(&args, 0, sizeof (args));
3050 	(void) memset(&res, 0, sizeof (res));
3051 
3052 	/* build args */
3053 	args.cl_sk = cl_sk;
3054 
3055 	/* do it */
3056 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3057 		int	bool;
3058 		bool = mdrpc_unlock_set_1_svc(&args, &res, NULL);
3059 		assert(bool == TRUE);
3060 		(void) mdstealerror(ep, &res.status);
3061 	} else {
3062 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3063 			return (-1);
3064 
3065 		if (mdrpc_unlock_set_1(&args, &res, clntp) != RPC_SUCCESS)
3066 			(void) mdrpcerror(ep, clntp, hostname,
3067 			    dgettext(TEXT_DOMAIN, "metad unlock set"));
3068 		else
3069 			(void) mdstealerror(ep, &res.status);
3070 
3071 		metarpcclose(clntp);
3072 	}
3073 
3074 	xdr_free(xdr_mdrpc_setlock_res, (char *)&res);
3075 
3076 	if (! mdisok(ep)) {
3077 		if (! mdanyrpcerror(ep))
3078 			return (-1);
3079 		if (strcmp(mynode(), hostname) == 0)
3080 			return (-1);
3081 		mdclrerror(ep);
3082 	}
3083 
3084 	return (0);
3085 }
3086 
3087 /*
3088  * Lock set so that only operators with valid keys are allowed in the daemon.
3089  */
3090 int
3091 clnt_lock_set(
3092 	char			*hostname,
3093 	mdsetname_t		*sp,
3094 	md_error_t		*ep
3095 )
3096 {
3097 	CLIENT			*clntp;
3098 	mdrpc_null_args		args;
3099 	mdrpc_setlock_res	res;
3100 
3101 	/* initialize */
3102 	mdclrerror(ep);
3103 	(void) memset(&args, 0, sizeof (args));
3104 	(void) memset(&res, 0, sizeof (res));
3105 
3106 	/* build args */
3107 	args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
3108 
3109 	/* do it */
3110 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3111 		int	bool;
3112 		bool = mdrpc_lock_set_1_svc(&args, &res, NULL);
3113 		assert(bool == TRUE);
3114 		(void) mdstealerror(ep, &res.status);
3115 	} else {
3116 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3117 			return (-1);
3118 
3119 		if (mdrpc_lock_set_1(&args, &res, clntp) != RPC_SUCCESS)
3120 			(void) mdrpcerror(ep, clntp, hostname,
3121 			    dgettext(TEXT_DOMAIN, "metad lock set"));
3122 		else
3123 			(void) mdstealerror(ep, &res.status);
3124 
3125 		metarpcclose(clntp);
3126 	}
3127 
3128 	if (mdisok(ep))
3129 		cl_set_setkey(res.cl_sk);
3130 
3131 	xdr_free(xdr_mdrpc_setlock_res, (char *)&res);
3132 
3133 	if (! mdisok(ep)) {
3134 		if (! mdanyrpcerror(ep))
3135 			return (-1);
3136 		if (strcmp(mynode(), hostname) == 0)
3137 			return (-1);
3138 		mdclrerror(ep);
3139 	}
3140 
3141 	return (0);
3142 }
3143 
3144 /*
3145  * Add mediator hosts to disksets.
3146  */
3147 int
3148 clnt_updmeds(
3149 	char			*hostname,
3150 	mdsetname_t		*sp,
3151 	md_h_arr_t		*medp,
3152 	md_error_t		*ep
3153 )
3154 {
3155 	CLIENT			*clntp;
3156 	mdrpc_updmeds_args	*args;
3157 	mdrpc_updmeds_2_args	v2_args;
3158 	mdrpc_generic_res	res;
3159 	int			version;
3160 
3161 	/* initialize */
3162 	mdclrerror(ep);
3163 	(void) memset(&v2_args, 0, sizeof (v2_args));
3164 	(void) memset(&res, 0, sizeof (res));
3165 
3166 	/* build args */
3167 	v2_args.rev = MD_METAD_ARGS_REV_1;
3168 	args = &v2_args.mdrpc_updmeds_2_args_u.rev1;
3169 	args->sp = sp;
3170 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
3171 	args->meds = *medp;			/* structure assignment */
3172 
3173 	/* do it */
3174 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3175 		int bool;
3176 		bool = mdrpc_updmeds_2_svc(&v2_args, &res, NULL);
3177 		assert(bool == TRUE);
3178 		(void) mdstealerror(ep, &res.status);
3179 	} else {
3180 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3181 			return (-1);
3182 
3183 		/*
3184 		 * Check the client handle for the version
3185 		 * and invoke the appropriate version of the
3186 		 * remote procedure
3187 		 */
3188 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3189 
3190 		if (version == METAD_VERSION) {	/* version 1 */
3191 			if (mdrpc_updmeds_1(args, &res, clntp) != RPC_SUCCESS)
3192 				(void) mdrpcerror(ep, clntp, hostname,
3193 				dgettext(TEXT_DOMAIN, "metad add hosts"));
3194 			else
3195 				(void) mdstealerror(ep, &res.status);
3196 		} else {
3197 			if (mdrpc_updmeds_2(&v2_args, &res, clntp) !=
3198 			    RPC_SUCCESS)
3199 				(void) mdrpcerror(ep, clntp, hostname,
3200 				dgettext(TEXT_DOMAIN, "metad add hosts"));
3201 			else
3202 				(void) mdstealerror(ep, &res.status);
3203 		}
3204 
3205 		metarpcclose(clntp);
3206 	}
3207 
3208 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3209 
3210 	if (! mdisok(ep))
3211 		return (-1);
3212 
3213 	return (0);
3214 }
3215 
3216 /*
3217  * update nr_flags field of node records based
3218  * on given action.
3219  */
3220 int
3221 clnt_upd_nr_flags(
3222 	char			*hostname,
3223 	mdsetname_t		*sp,
3224 	md_mnnode_desc		*nd,
3225 	uint_t			flag_action,
3226 	uint_t			flags,
3227 	md_error_t		*ep
3228 )
3229 {
3230 	CLIENT				*clntp;
3231 	mdrpc_upd_nr_flags_args		*args;
3232 	mdrpc_upd_nr_flags_2_args	v2_args;
3233 	mdrpc_generic_res		res;
3234 	int				version;
3235 
3236 	/* initialize */
3237 	mdclrerror(ep);
3238 	(void) memset(&v2_args, 0, sizeof (v2_args));
3239 	(void) memset(&res, 0, sizeof (res));
3240 
3241 	/* build args */
3242 	v2_args.rev = MD_METAD_ARGS_REV_1;
3243 	args = &v2_args.mdrpc_upd_nr_flags_2_args_u.rev1;
3244 	args->sp = sp;
3245 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
3246 	args->nodedescs = nd;
3247 	args->flag_action = flag_action;
3248 	args->flags = flags;
3249 
3250 	/* do it */
3251 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3252 		int	bool;
3253 		bool = mdrpc_upd_nr_flags_2_svc(&v2_args, &res, NULL);
3254 		assert(bool == TRUE);
3255 		(void) mdstealerror(ep, &res.status);
3256 	} else {
3257 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3258 			return (-1);
3259 
3260 		/*
3261 		 * Check the client handle for the version
3262 		 */
3263 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3264 
3265 		/*
3266 		 * If the client is version 1, return error
3267 		 * otherwise, make the remote procedure call.
3268 		 */
3269 		if (version == METAD_VERSION) { /* version 1 */
3270 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3271 				sp->setno, hostname, NULL, sp->setname);
3272 			metarpcclose(clntp);
3273 			return (-1);
3274 		} else {
3275 			if (mdrpc_upd_nr_flags_2(&v2_args, &res, clntp)
3276 							!= RPC_SUCCESS)
3277 				(void) mdrpcerror(ep, clntp, hostname,
3278 				dgettext(TEXT_DOMAIN,
3279 				    "metad set node flags"));
3280 			else
3281 				(void) mdstealerror(ep, &res.status);
3282 		}
3283 
3284 		metarpcclose(clntp);
3285 	}
3286 
3287 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3288 
3289 	if (! mdisok(ep)) {
3290 		if (! mdanyrpcerror(ep))
3291 			return (-1);
3292 		if (strcmp(mynode(), hostname) == 0)
3293 			return (-1);
3294 		mdclrerror(ep);
3295 	}
3296 
3297 	return (0);
3298 }
3299 
3300 /*
3301  * Clear set locks for all MN disksets.
3302  * Used during reconfig cycle to recover from failed nodes.
3303  */
3304 int
3305 clnt_clr_mnsetlock(
3306 	char			*hostname,
3307 	md_error_t		*ep
3308 )
3309 {
3310 	CLIENT			*clntp;
3311 	mdrpc_null_args		args;
3312 	mdrpc_generic_res	res;
3313 	int			version;
3314 
3315 	/* initialize */
3316 	mdclrerror(ep);
3317 	(void) memset(&args, 0, sizeof (args));
3318 	(void) memset(&res, 0, sizeof (res));
3319 
3320 	/* do it */
3321 	if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3322 		return (-1);
3323 
3324 	/*
3325 	 * Check the client handle for the version
3326 	 */
3327 	CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3328 
3329 	/*
3330 	 * If the client is version 1, return error
3331 	 * otherwise, make the remote procedure call.
3332 	 */
3333 	if (version == METAD_VERSION) { /* version 1 */
3334 		(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3335 			NULL, hostname, NULL, NULL);
3336 		metarpcclose(clntp);
3337 		return (-1);
3338 	} else {
3339 		if (mdrpc_clr_mnsetlock_2(&args, &res, clntp) != RPC_SUCCESS)
3340 			(void) mdrpcerror(ep, clntp, hostname,
3341 			    dgettext(TEXT_DOMAIN, "metad clr mnsetlock"));
3342 		else
3343 			(void) mdstealerror(ep, &res.status);
3344 	}
3345 
3346 	metarpcclose(clntp);
3347 
3348 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3349 
3350 	if (! mdisok(ep))
3351 		return (-1);
3352 
3353 	return (0);
3354 }
3355 
3356 /*
3357  * Calls to suspend, resume or reinit the rpc.mdcommd daemon.
3358  * This allows a node to remotely suspend, reinit and resume the
3359  * rpc.mdcommd daemon on the given hostname node.  Used by libmeta
3360  * to lock out class 1 messages (metainit, etc) on all nodes when running
3361  * metaset and metadb commands on this node.
3362  *
3363  * When suspending the commd, the suspend request will fail until all
3364  * messages have been drained from the rpc.mdcommd.  This routine will
3365  * spin sending the suspend request until the rpc.mdcommd is drained
3366  * or until rpc.mdcommd returns a failure other than MDMNE_SET_NOT_DRAINED.
3367  *
3368  * Also used to send the rpc.mdcommd daemon a new nodelist by draining all
3369  * messages from the mdcommd and sending a reinit command to have mdcommd
3370  * get the new nodelist from rpc.metad.  Used when nodelist is changed
3371  * during:
3372  *	- addition or deletion of host from diskset
3373  *	- join or withdrawal of host from diskset
3374  *	- addition of first disk to diskset (joins all nodes)
3375  *	- removal of last disk from diskset (withdraws all nodes)
3376  */
3377 int
3378 clnt_mdcommdctl(
3379 	char			*hostname,
3380 	int			flag_action,
3381 	mdsetname_t		*sp,
3382 	md_mn_msgclass_t	class,
3383 	uint_t			flags,
3384 	md_error_t		*ep
3385 )
3386 {
3387 	CLIENT				*clntp;
3388 	mdrpc_mdcommdctl_args		*args;
3389 	mdrpc_mdcommdctl_2_args		v2_args;
3390 	mdrpc_generic_res		res;
3391 	int				version;
3392 	int				suspend_spin = 0;
3393 
3394 	/* initialize */
3395 	mdclrerror(ep);
3396 	(void) memset(&v2_args, 0, sizeof (v2_args));
3397 	(void) memset(&res, 0, sizeof (res));
3398 
3399 	/* build args */
3400 	v2_args.rev = MD_METAD_ARGS_REV_1;
3401 	args = &v2_args.mdrpc_mdcommdctl_2_args_u.rev1;
3402 	args->flag_action = flag_action;
3403 	args->setno = sp->setno;
3404 	args->class = class;
3405 	args->flags = flags;
3406 
3407 	/* do it */
3408 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3409 		int	bool;
3410 		/*
3411 		 * Call v2 procedure directly if rpc.metad on this node is
3412 		 * sending message to itself.
3413 		 */
3414 		if (flag_action == COMMDCTL_SUSPEND) {
3415 			suspend_spin = 1;
3416 			while (suspend_spin) {
3417 				suspend_spin = 0;
3418 				bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res,
3419 					NULL);
3420 				assert(bool == TRUE);
3421 				/*
3422 				 * If set not yet drained, wait a second
3423 				 * and try again.
3424 				 */
3425 				if (mdisdserror(&(res.status),
3426 				    MDE_DS_COMMDCTL_SUSPEND_NYD)) {
3427 					/* Wait a second and try again */
3428 					mdclrerror(&(res.status));
3429 					(void) sleep(1);
3430 					suspend_spin = 1;
3431 				}
3432 			}
3433 		} else {
3434 			bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res, NULL);
3435 			assert(bool == TRUE);
3436 		}
3437 		(void) mdstealerror(ep, &res.status);
3438 	} else {
3439 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3440 			return (-1);
3441 
3442 		/*
3443 		 * Check the client handle for the version
3444 		 */
3445 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3446 
3447 		/*
3448 		 * If the client is version 1, return error
3449 		 * otherwise, make the remote procedure call.
3450 		 */
3451 		if (version == METAD_VERSION) { /* version 1 */
3452 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3453 				sp->setno, hostname, NULL, sp->setname);
3454 			metarpcclose(clntp);
3455 			return (-1);
3456 		}
3457 
3458 		if (flag_action == COMMDCTL_SUSPEND) {
3459 			suspend_spin = 1;
3460 			while (suspend_spin) {
3461 				suspend_spin = 0;
3462 				if (mdrpc_mdcommdctl_2(&v2_args, &res,
3463 				    clntp) != RPC_SUCCESS) {
3464 					(void) mdrpcerror(ep, clntp,
3465 					    hostname,
3466 					    dgettext(TEXT_DOMAIN,
3467 					    "metad commd control"));
3468 				} else {
3469 					/*
3470 					 * If set not yet drained,
3471 					 * wait a second and
3472 					 * and try again.
3473 					 */
3474 					if (mdisdserror(&(res.status),
3475 					    MDE_DS_COMMDCTL_SUSPEND_NYD)) {
3476 						mdclrerror(&(res.status));
3477 						(void) sleep(1);
3478 						suspend_spin = 1;
3479 					} else {
3480 						(void) mdstealerror(ep,
3481 						    &res.status);
3482 					}
3483 				}
3484 			}
3485 		} else {
3486 			if (mdrpc_mdcommdctl_2(&v2_args, &res, clntp)
3487 			    != RPC_SUCCESS)
3488 				(void) mdrpcerror(ep, clntp, hostname,
3489 				dgettext(TEXT_DOMAIN,
3490 				    "metad commd control"));
3491 			else
3492 				(void) mdstealerror(ep, &res.status);
3493 		}
3494 		metarpcclose(clntp);
3495 	}
3496 
3497 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3498 
3499 	if (! mdisok(ep)) {
3500 		if (! mdanyrpcerror(ep))
3501 			return (-1);
3502 		if (strcmp(mynode(), hostname) == 0)
3503 			return (-1);
3504 		mdclrerror(ep);
3505 	}
3506 
3507 	return (0);
3508 }
3509 
3510 /*
3511  * Is owner node stale?
3512  */
3513 int
3514 clnt_mn_is_stale(
3515 	char			*hostname,
3516 	mdsetname_t		*sp,
3517 	int			*ret_bool,
3518 	md_error_t		*ep
3519 )
3520 {
3521 	CLIENT			*clntp;
3522 	mdrpc_setno_args	*args;
3523 	mdrpc_setno_2_args	v2_args;
3524 	mdrpc_bool_res		res;
3525 	int			rval = -1;
3526 	int			version;
3527 
3528 	/* initialize */
3529 	mdclrerror(ep);
3530 	(void) memset(&v2_args, 0, sizeof (v2_args));
3531 	(void) memset(&res, 0, sizeof (res));
3532 
3533 	/* build args */
3534 	v2_args.rev = MD_METAD_ARGS_REV_1;
3535 	args = &v2_args.mdrpc_setno_2_args_u.rev1;
3536 	args->setno = sp->setno;
3537 
3538 	/* do it */
3539 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3540 		int	bool;
3541 		/*
3542 		 * Call v2 procedure directly if rpc.metad on this node is
3543 		 * sending message to itself.
3544 		 */
3545 		bool = mdrpc_mn_is_stale_2_svc(&v2_args, &res, NULL);
3546 		assert(bool == TRUE);
3547 		(void) mdstealerror(ep, &res.status);
3548 	} else {
3549 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3550 			return (-1);
3551 
3552 		/*
3553 		 * Check the client handle for the version
3554 		 * and invoke the appropriate version of the
3555 		 * remote procedure
3556 		 */
3557 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3558 
3559 		/*
3560 		 * If the client is version 1, return error
3561 		 * otherwise, make the remote procedure call.
3562 		 */
3563 		if (version == METAD_VERSION) { /* version 1 */
3564 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3565 			    sp->setno, hostname, NULL, sp->setname);
3566 			metarpcclose(clntp);
3567 			return (-1);
3568 		} else {
3569 			if (mdrpc_mn_is_stale_2(&v2_args, &res, clntp) !=
3570 			    RPC_SUCCESS)
3571 				(void) mdrpcerror(ep, clntp, hostname,
3572 				dgettext(TEXT_DOMAIN, "metad mn is stale"));
3573 			else
3574 				(void) mdstealerror(ep, &res.status);
3575 		}
3576 
3577 		metarpcclose(clntp);
3578 	}
3579 
3580 	if (mdisok(ep)) {
3581 		/* do something with the results */
3582 		rval = 0;
3583 
3584 		if (ret_bool != NULL)
3585 			*ret_bool = res.value;
3586 	}
3587 
3588 	xdr_free(xdr_mdrpc_bool_res, (char *)&res);
3589 
3590 	return (rval);
3591 }
3592 
3593 /*
3594  * Free md_drive_desc linked list of drive descriptors that was alloc'd
3595  * from a call to the RPC routine clnt_getdrivedesc.  Drive descriptors
3596  * are from another node.
3597  */
3598 void
3599 free_rem_dd(md_drive_desc *dd)
3600 {
3601 	mdrpc_getdrivedesc_res	res;
3602 
3603 	/*
3604 	 * dummy up a result struct, to do a deep free of the dd.
3605 	 * (A deep free means that the xdr_free code will free the
3606 	 * linked list of drive descs.)
3607 	 */
3608 	(void) memset(&res, 0, sizeof (res));
3609 	res.dd = (struct md_drive_desc *)dd;
3610 	xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res);
3611 }
3612 
3613 /*
3614  * Get a partially filled in drive desc from remote node.  Used in MN
3615  * disksets during the reconfig cycle to get the diskset drive
3616  * information from another host in order to sync up all nodes.
3617  * Used when the drive record information isn't good enough
3618  * since the drive record doesn't give the name of
3619  * the drive, but just a key into that other node's nodespace.
3620  * Returned drive desc has the drive name filled in but no other strings
3621  * in the drivename structure.
3622  *
3623  * Returns a 0 if RPC was successful, 1 otherwise.
3624  */
3625 int
3626 clnt_getdrivedesc(
3627 	char			*hostname,
3628 	mdsetname_t		*sp,
3629 	md_drive_desc		**ret_dd,
3630 	md_error_t		*ep
3631 )
3632 {
3633 	CLIENT			*clntp;
3634 	mdrpc_sp_args		*args;
3635 	mdrpc_sp_2_args		v2_args;
3636 	mdrpc_getdrivedesc_res	res;
3637 	int			version;
3638 	int			rval = -1;
3639 
3640 	/* initialize */
3641 	mdclrerror(ep);
3642 	(void) memset(&v2_args, 0, sizeof (v2_args));
3643 	(void) memset(&res, 0, sizeof (res));
3644 
3645 	/* build args */
3646 	v2_args.rev = MD_METAD_ARGS_REV_1;
3647 	args = &v2_args.mdrpc_sp_2_args_u.rev1;
3648 	args->sp = sp;
3649 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
3650 
3651 	/* do it */
3652 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3653 		int	bool;
3654 		bool = mdrpc_getdrivedesc_2_svc(&v2_args, &res, NULL);
3655 		assert(bool == TRUE);
3656 		(void) mdstealerror(ep, &res.status);
3657 	} else {
3658 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3659 			return (-1);
3660 
3661 		/*
3662 		 * Check the client handle for the version
3663 		 */
3664 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3665 
3666 		/*
3667 		 * If the client is version 1, return error
3668 		 * otherwise, make the remote procedure call.
3669 		 */
3670 		if (version == METAD_VERSION) { /* version 1 */
3671 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3672 			    sp->setno, hostname, NULL, sp->setname);
3673 			metarpcclose(clntp);
3674 			return (-1);
3675 		} else {
3676 			if (mdrpc_getdrivedesc_2(&v2_args, &res, clntp)
3677 							!= RPC_SUCCESS)
3678 				(void) mdrpcerror(ep, clntp, hostname,
3679 				dgettext(TEXT_DOMAIN,
3680 				    "metad get drive desc set"));
3681 			else
3682 				(void) mdstealerror(ep, &res.status);
3683 		}
3684 
3685 		metarpcclose(clntp);
3686 	}
3687 
3688 	/* If no ep error and no version mismatch - rpc call worked ok */
3689 	if (mdisok(ep)) {
3690 		rval = 0;
3691 		if (ret_dd != NULL)
3692 			*ret_dd = res.dd;
3693 		else
3694 			xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res);
3695 	}
3696 
3697 	return (rval);
3698 }
3699 
3700 /*
3701  * update dr_flags field of drive record.
3702  * Also sync up genid of drive descriptors and make set
3703  * record and node records match the genid.
3704  *
3705  * Returns a 0 if RPC was successful, 1 otherwise.
3706  */
3707 int
3708 clnt_upd_dr_reconfig(
3709 	char			*hostname,
3710 	mdsetname_t		*sp,
3711 	md_drive_desc		*dd,
3712 	md_error_t		*ep
3713 )
3714 {
3715 	CLIENT				*clntp;
3716 	mdrpc_upd_dr_flags_2_args	v2_args;
3717 	mdrpc_upd_dr_flags_2_args_r1	*v21_args;
3718 	mdrpc_generic_res		res;
3719 	int				rval;
3720 	int				version;
3721 
3722 	/* initialize */
3723 	mdclrerror(ep);
3724 	(void) memset(&v2_args, 0, sizeof (v2_args));
3725 	(void) memset(&res, 0, sizeof (res));
3726 
3727 	/* build args */
3728 	v2_args.rev = MD_METAD_ARGS_REV_1;
3729 	v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1;
3730 	v21_args->sp = sp;
3731 	v21_args->drivedescs = dd;
3732 
3733 	/* do it */
3734 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3735 		int	bool;
3736 
3737 		/*
3738 		 * If the server is local, we call the v2 procedure
3739 		 */
3740 		bool = mdrpc_upd_dr_reconfig_2_svc(&v2_args, &res, NULL);
3741 		assert(bool == TRUE);
3742 		(void) mdstealerror(ep, &res.status);
3743 	} else {
3744 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3745 			return (-1);
3746 
3747 		/*
3748 		 * Check the client handle for the version
3749 		 */
3750 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3751 		/*
3752 		 * If the client is version 1, return error
3753 		 * otherwise, make the remote procedure call.
3754 		 */
3755 		if (version == METAD_VERSION) { /* version 1 */
3756 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3757 				sp->setno, hostname, NULL, sp->setname);
3758 			metarpcclose(clntp);
3759 			return (-1);
3760 		} else {
3761 			rval = mdrpc_upd_dr_reconfig_2(&v2_args, &res, clntp);
3762 
3763 			if (rval != RPC_SUCCESS)
3764 				(void) mdrpcerror(ep, clntp, hostname,
3765 				    dgettext(TEXT_DOMAIN,
3766 				    "metad update drive reconfig"));
3767 			else
3768 				(void) mdstealerror(ep, &res.status);
3769 		}
3770 
3771 		metarpcclose(clntp);
3772 	}
3773 
3774 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3775 
3776 	if (! mdisok(ep)) {
3777 		if (! mdanyrpcerror(ep))
3778 			return (-1);
3779 		if (strcmp(mynode(), hostname) == 0)
3780 			return (-1);
3781 		mdclrerror(ep);
3782 	}
3783 
3784 	return (0);
3785 }
3786 
3787 /*
3788  * Reset mirror owner(s) if mirror owner(s) is in the list of
3789  * node's specified in the array of nodeids.
3790  * This is called when a node has been deleted or withdrawn
3791  * from the diskset.
3792  */
3793 int
3794 clnt_reset_mirror_owner(
3795 	char			*hostname,
3796 	mdsetname_t		*sp,
3797 	int			node_c,
3798 	int			node_id[],
3799 	md_error_t		*ep
3800 )
3801 {
3802 	CLIENT			*clntp;
3803 	mdrpc_nodeid_args	*args;
3804 	mdrpc_nodeid_2_args	v2_args;
3805 	mdrpc_generic_res	res;
3806 	int			version;
3807 
3808 	/* initialize */
3809 	mdclrerror(ep);
3810 	(void) memset(&v2_args, 0, sizeof (v2_args));
3811 	(void) memset(&res, 0, sizeof (res));
3812 
3813 	/* build args */
3814 	v2_args.rev = MD_METAD_ARGS_REV_1;
3815 	args = &v2_args.mdrpc_nodeid_2_args_u.rev1;
3816 	args->sp = sp;
3817 	args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
3818 	args->nodeid.nodeid_len = node_c;
3819 	args->nodeid.nodeid_val = &node_id[0];
3820 
3821 	/* do it */
3822 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3823 		int	bool;
3824 		bool = mdrpc_reset_mirror_owner_2_svc(&v2_args, &res, NULL);
3825 		assert(bool == TRUE);
3826 		(void) mdstealerror(ep, &res.status);
3827 	} else {
3828 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3829 			return (-1);
3830 
3831 		/*
3832 		 * Check the client handle for the version
3833 		 * and invoke the appropriate version of the
3834 		 * remote procedure
3835 		 */
3836 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3837 
3838 		/*
3839 		 * If the client is version 1, return error
3840 		 * otherwise, make the remote procedure call.
3841 		 */
3842 		if (version == METAD_VERSION) { /* version 1 */
3843 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3844 			    sp->setno, hostname, NULL, sp->setname);
3845 			metarpcclose(clntp);
3846 			return (-1);
3847 		} else {
3848 			if (mdrpc_reset_mirror_owner_2(&v2_args, &res, clntp)
3849 			    != RPC_SUCCESS)
3850 				(void) mdrpcerror(ep, clntp, hostname,
3851 				dgettext(TEXT_DOMAIN,
3852 					"metad reset mirror owner"));
3853 			else
3854 				(void) mdstealerror(ep, &res.status);
3855 		}
3856 
3857 		metarpcclose(clntp);
3858 	}
3859 
3860 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3861 
3862 	if (! mdisok(ep))
3863 		return (-1);
3864 
3865 	return (0);
3866 }
3867 
3868 /*
3869  * Call to suspend and resume I/O for given diskset(s).
3870  * This allows a node to remotely suspend and resume I/O on
3871  * a MN diskset.  A diskset number of 0 represents all MN disksets.
3872  */
3873 int
3874 clnt_mn_susp_res_io(
3875 	char			*hostname,
3876 	set_t			setno,
3877 	int			cmd,
3878 	md_error_t		*ep
3879 )
3880 {
3881 	CLIENT					*clntp;
3882 	mdrpc_mn_susp_res_io_args		*args;
3883 	mdrpc_mn_susp_res_io_2_args		v2_args;
3884 	mdrpc_generic_res			res;
3885 	int					version;
3886 
3887 	/* initialize */
3888 	mdclrerror(ep);
3889 	(void) memset(&v2_args, 0, sizeof (v2_args));
3890 	(void) memset(&res, 0, sizeof (res));
3891 
3892 	/* build args */
3893 	v2_args.rev = MD_METAD_ARGS_REV_1;
3894 	args = &v2_args.mdrpc_mn_susp_res_io_2_args_u.rev1;
3895 	args->susp_res_cmd = cmd;
3896 	args->susp_res_setno = setno;
3897 
3898 	/* do it */
3899 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
3900 		int	bool;
3901 		/*
3902 		 * Call v2 procedure directly if rpc.metad on this node is
3903 		 * sending message to itself.
3904 		 */
3905 		bool = mdrpc_mn_susp_res_io_2_svc(&v2_args, &res, NULL);
3906 		assert(bool == TRUE);
3907 		(void) mdstealerror(ep, &res.status);
3908 	} else {
3909 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3910 			return (-1);
3911 
3912 		/*
3913 		 * Check the client handle for the version
3914 		 */
3915 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3916 
3917 		/*
3918 		 * If the client is version 1, return error
3919 		 * otherwise, make the remote procedure call.
3920 		 */
3921 		if (version == METAD_VERSION) { /* version 1 */
3922 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
3923 			    setno, hostname, NULL, NULL);
3924 			metarpcclose(clntp);
3925 			return (-1);
3926 		} else {
3927 			if (mdrpc_mn_susp_res_io_2(&v2_args, &res, clntp)
3928 							!= RPC_SUCCESS)
3929 				(void) mdrpcerror(ep, clntp, hostname,
3930 				dgettext(TEXT_DOMAIN,
3931 				    "metad mn_susp_res_io control"));
3932 			else
3933 				(void) mdstealerror(ep, &res.status);
3934 		}
3935 
3936 		metarpcclose(clntp);
3937 	}
3938 
3939 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
3940 
3941 	if (! mdisok(ep)) {
3942 		if (! mdanyrpcerror(ep))
3943 			return (-1);
3944 		if (strcmp(mynode(), hostname) == 0)
3945 			return (-1);
3946 		mdclrerror(ep);
3947 	}
3948 
3949 	return (0);
3950 }
3951 
3952 /*
3953  * Resnarf the set after the set has been imported
3954  *
3955  * We should never be making this procedure call
3956  * over the wire, it's sole purpose is to snarf
3957  * the imported set on the localhost.
3958  */
3959 int
3960 clnt_resnarf_set(
3961 	char		*hostname,
3962 	set_t		setno,
3963 	md_error_t	*ep
3964 )
3965 {
3966 	CLIENT			*clntp;
3967 	mdrpc_setno_2_args	args;
3968 	mdrpc_generic_res	res;
3969 	int			rval = -1;
3970 	int			version;
3971 
3972 	/* initialize */
3973 	mdclrerror(ep);
3974 	(void) memset(&args, 0, sizeof (args));
3975 	(void) memset(&res, 0, sizeof (res));
3976 
3977 	/* build args */
3978 	args.rev = MD_METAD_ARGS_REV_1;
3979 	args.mdrpc_setno_2_args_u.rev1.setno = setno;
3980 	args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
3981 
3982 	/* do it */
3983 	if (strcmp(mynode(), hostname) == 0) {
3984 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
3985 			return (-1);
3986 
3987 		/* Check the client handle for the version */
3988 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
3989 
3990 		/* If the client is version 1, return error */
3991 		if (version == METAD_VERSION) { /* version 1 */
3992 			(void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD,
3993 			    mynode(), NULL, NULL);
3994 		} else {
3995 			rval = mdrpc_resnarf_set_2(&args, &res, clntp);
3996 
3997 			if (rval != RPC_SUCCESS)
3998 				(void) mdrpcerror(ep, clntp, hostname,
3999 				    dgettext(TEXT_DOMAIN, "metad resnarf set"));
4000 			else
4001 				(void) mdstealerror(ep, &res.status);
4002 		}
4003 
4004 		metarpcclose(clntp);
4005 
4006 	} else {
4007 		(void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD,
4008 		    mynode(), NULL, NULL);
4009 	}
4010 
4011 	if (mdisok(ep))
4012 		rval = 0;
4013 
4014 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
4015 
4016 	return (rval);
4017 }
4018 
4019 /*
4020  * Call to start a resync for a given diskset.
4021  * Used when a node has been added to a diskset.
4022  * Should be called after rpc.mdcommd is resumed.
4023  */
4024 int
4025 clnt_mn_mirror_resync_all(
4026 	char			*hostname,
4027 	set_t			setno,
4028 	md_error_t		*ep
4029 )
4030 {
4031 	CLIENT					*clntp;
4032 	mdrpc_setno_2_args			args;
4033 	mdrpc_generic_res			res;
4034 	int					version;
4035 
4036 	/* initialize */
4037 	mdclrerror(ep);
4038 	(void) memset(&args, 0, sizeof (args));
4039 	(void) memset(&res, 0, sizeof (res));
4040 
4041 	/* build args */
4042 	args.rev = MD_METAD_ARGS_REV_1;
4043 	args.mdrpc_setno_2_args_u.rev1.setno = setno;
4044 	args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
4045 
4046 	/* do it */
4047 	if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
4048 		int	bool;
4049 		/*
4050 		 * Call v2 procedure directly if rpc.metad on this node is
4051 		 * sending message to itself.
4052 		 */
4053 		bool = mdrpc_mn_mirror_resync_all_2_svc(&args, &res, NULL);
4054 		assert(bool == TRUE);
4055 		(void) mdstealerror(ep, &res.status);
4056 	} else {
4057 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
4058 			return (-1);
4059 
4060 		/*
4061 		 * Check the client handle for the version
4062 		 */
4063 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
4064 
4065 		/*
4066 		 * If the client is version 1, return error
4067 		 * otherwise, make the remote procedure call.
4068 		 */
4069 		if (version == METAD_VERSION) { /* version 1 */
4070 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
4071 			    setno, hostname, NULL, NULL);
4072 			metarpcclose(clntp);
4073 			return (-1);
4074 		} else {
4075 			if (mdrpc_mn_mirror_resync_all_2(&args, &res, clntp)
4076 							!= RPC_SUCCESS)
4077 				(void) mdrpcerror(ep, clntp, hostname,
4078 				dgettext(TEXT_DOMAIN,
4079 				    "metad mn_mirror_resync_all"));
4080 			else
4081 				(void) mdstealerror(ep, &res.status);
4082 		}
4083 
4084 		metarpcclose(clntp);
4085 	}
4086 
4087 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
4088 
4089 	if (! mdisok(ep)) {
4090 		if (! mdanyrpcerror(ep))
4091 			return (-1);
4092 		if (strcmp(mynode(), hostname) == 0)
4093 			return (-1);
4094 		mdclrerror(ep);
4095 	}
4096 
4097 	return (0);
4098 }
4099 
4100 /*
4101  * Call to update the ABR state for all soft partitions.
4102  * Used when a node has been added to a diskset.
4103  * Should be called after rpc.mdcommd is resumed.
4104  */
4105 int
4106 clnt_mn_sp_update_abr(
4107 	char			*hostname,
4108 	set_t			setno,
4109 	md_error_t		*ep
4110 )
4111 {
4112 	CLIENT					*clntp;
4113 	mdrpc_setno_2_args			args;
4114 	mdrpc_generic_res			res;
4115 	int					version;
4116 
4117 	/* initialize */
4118 	mdclrerror(ep);
4119 	(void) memset(&args, 0, sizeof (args));
4120 	(void) memset(&res, 0, sizeof (res));
4121 
4122 	/* build args */
4123 	args.rev = MD_METAD_ARGS_REV_1;
4124 	args.mdrpc_setno_2_args_u.rev1.setno = setno;
4125 	args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
4126 
4127 	/*
4128 	 * No need to call function if adding local node as ABR cannot
4129 	 * be set.
4130 	 */
4131 	if (strcmp(mynode(), hostname) != 0) {
4132 		if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
4133 			return (-1);
4134 
4135 		/*
4136 		 * Check the client handle for the version
4137 		 */
4138 		CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
4139 
4140 		/*
4141 		 * If the client is version 1, return error
4142 		 * otherwise, make the remote procedure call.
4143 		 */
4144 		if (version == METAD_VERSION) { /* version 1 */
4145 			(void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
4146 			    setno, hostname, NULL, NULL);
4147 			metarpcclose(clntp);
4148 			return (-1);
4149 		} else {
4150 			if (mdrpc_mn_sp_update_abr_2(&args, &res, clntp)
4151 							!= RPC_SUCCESS)
4152 				(void) mdrpcerror(ep, clntp, hostname,
4153 				dgettext(TEXT_DOMAIN,
4154 				    "metad mn_sp_update_abr"));
4155 			else
4156 				(void) mdstealerror(ep, &res.status);
4157 		}
4158 
4159 		metarpcclose(clntp);
4160 	}
4161 
4162 	xdr_free(xdr_mdrpc_generic_res, (char *)&res);
4163 
4164 	if (! mdisok(ep)) {
4165 		if (! mdanyrpcerror(ep))
4166 			return (-1);
4167 		mdclrerror(ep);
4168 	}
4169 
4170 	return (0);
4171 }
4172