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