xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_med.c (revision 40cb5e5daa7b80bb70fcf8dadfb20f9281566331)
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 2004 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 /*
38  * Mediator functions
39  */
40 
41 #include <meta.h>
42 #include <metamed.h>
43 #include <dlfcn.h>
44 #include <sdssc.h>
45 
46 /*
47  * There are too many external factors that affect the timing of the
48  * operations, so we set the timeout to a very large value, in this
49  * case 1 day, which should handle HW timeouts, large configurations,
50  * and other potential delays.
51  */
52 #define	CL_LONG_TMO	86400L			/* 1 day */
53 #define	CL_MEDIUM_TMO	3600L			/* 1 hour */
54 #define	CL_SHORT_TMO	600L			/* 10 minutes */
55 #define	CL_DEF_TMO	10L			/* 10 seconds */
56 
57 static	md_timeval32_t def_rpcb_timeout =  { MD_CLNT_CREATE_TOUT, 0 };
58 
59 /*
60  * RPC handle
61  */
62 typedef struct {
63 	char	*hostname;
64 	CLIENT	*clntp;
65 } med_handle_t;
66 
67 /*
68  * Data to be sent from med_clnt_create_timed to med_create_helper via
69  * meta_client_create_retry.
70  */
71 typedef struct {
72 	rpcprog_t	mcd_program;	/* RPC program designation */
73 	rpcvers_t	mcd_version;	/* RPC version */
74 	char		*mcd_nettype;	/* Type of network to use for RPC */
75 } med_create_data_t;
76 
77 /*
78  * Perform the work of actually doing the clnt_create for
79  * meta_client_create_retry.
80  */
81 static CLIENT *
82 med_create_helper(char *hostname, void *private, struct timeval *time_out)
83 {
84 	med_create_data_t	*cd = (med_create_data_t *)private;
85 
86 	return (clnt_create_timed(hostname, cd->mcd_program, cd->mcd_version,
87 		cd->mcd_nettype, time_out));
88 }
89 
90 static
91 CLIENT *med_clnt_create_timed(
92 	char *hostname,
93 	const ulong_t prog,
94 	const ulong_t vers,
95 	char *nettype,
96 	const md_timeval32_t *tp
97 )
98 {
99 	med_create_data_t	cd;	/* Create data. */
100 
101 	cd.mcd_program = prog;
102 	cd.mcd_version = vers;
103 	cd.mcd_nettype = nettype;
104 	return (meta_client_create_retry(hostname, med_create_helper,
105 		(void *)&cd, (time_t)tp->tv_sec, NULL));
106 }
107 
108 /*
109  * Set the timeout value for this client handle.
110  */
111 static int
112 cl_sto_medd(
113 	CLIENT		*clntp,
114 	char		*hostname,
115 	long		time_out,
116 	md_error_t	*ep
117 )
118 {
119 	md_timeval32_t	nto;
120 
121 	(void) memset(&nto, '\0', sizeof (nto));
122 
123 	nto.tv_sec = time_out;
124 
125 	if (clnt_control(clntp, CLSET_TIMEOUT, (char *)&nto) != TRUE)
126 		return (mdrpcerror(ep, clntp, hostname,
127 		    dgettext(TEXT_DOMAIN, "metad client set timeout")));
128 
129 	return (0);
130 }
131 
132 /*
133  * close RPC connection
134  */
135 static void
136 close_medd(
137 	med_handle_t	*hp
138 )
139 {
140 	assert(hp != NULL);
141 	if (hp->hostname != NULL) {
142 		Free(hp->hostname);
143 	}
144 	if (hp->clntp != NULL) {
145 		auth_destroy(hp->clntp->cl_auth);
146 		clnt_destroy(hp->clntp);
147 	}
148 	Free(hp);
149 }
150 
151 /*
152  * open RPC connection to rpc.medd
153  */
154 static med_handle_t *
155 open_medd(
156 	char		*hostname,
157 	long		time_out,
158 	md_error_t	*ep
159 )
160 {
161 	CLIENT		*clntp;
162 	med_handle_t	*hp;
163 
164 	/* default to local host */
165 	if ((hostname == NULL) || (*hostname == '\0'))
166 		hostname = mynode();
167 
168 	/* open RPC connection */
169 	assert(hostname != NULL);
170 	if ((clntp = med_clnt_create_timed(hostname, MED_PROG, MED_VERS,
171 	    "tcp", &def_rpcb_timeout)) == NULL) {
172 		if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
173 			clnt_pcreateerror(hostname);
174 		(void) mdrpccreateerror(ep, hostname,
175 		    "medd med_clnt_create_timed");
176 		return (NULL);
177 	} else {
178 		auth_destroy(clntp->cl_auth);
179 		clntp->cl_auth = authsys_create_default();
180 		assert(clntp->cl_auth != NULL);
181 	}
182 
183 	if (cl_sto_medd(clntp, hostname, time_out, ep) != 0)
184 		return (NULL);
185 
186 	/* return connection */
187 	hp = Zalloc(sizeof (*hp));
188 	hp->hostname = Strdup(hostname);
189 	hp->clntp = clntp;
190 
191 	return (hp);
192 }
193 
194 /*
195  * steal and convert med_err_t
196  */
197 int
198 meddstealerror(
199 	md_error_t	*ep,
200 	med_err_t	*medep
201 )
202 {
203 	char		buf[BUFSIZ];
204 	char		*p = buf;
205 	size_t		psize = BUFSIZ;
206 	char		*emsg;
207 	int		rval = -1;
208 
209 	/* no error */
210 	if (medep->med_errno == 0) {
211 		/* assert(medep->name == NULL); */
212 		rval = 0;
213 		goto out;
214 	}
215 
216 	/* steal error */
217 	if ((medep->med_node != NULL) && (medep->med_node[0] != '\0')) {
218 		(void) snprintf(p, psize, "%s: ", medep->med_node);
219 		p = &buf[strlen(buf)];
220 		psize = buf + BUFSIZ - p;
221 	}
222 
223 	if ((medep->med_misc != NULL) && (medep->med_misc[0] != '\0')) {
224 		(void) snprintf(p, psize, "%s: ", medep->med_misc);
225 		p = &buf[strlen(buf)];
226 		psize = buf + BUFSIZ - p;
227 	}
228 
229 	if (medep->med_errno < 0) {
230 		if ((emsg = med_errnum_to_str(medep->med_errno)) != NULL)
231 			(void) snprintf(p, psize, "%s", emsg);
232 		else
233 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
234 			    "unknown mediator errno %d\n"), medep->med_errno);
235 	} else {
236 		if ((emsg = strerror(medep->med_errno)) != NULL)
237 			(void) snprintf(p, psize, "%s", emsg);
238 		else
239 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
240 			    "errno %d out of range"), medep->med_errno);
241 	}
242 	(void) mderror(ep, MDE_MED_ERROR, buf);
243 
244 	/* cleanup, return success */
245 out:
246 	if (medep->med_node != NULL)
247 		Free(medep->med_node);
248 	if (medep->med_misc != NULL)
249 		Free(medep->med_misc);
250 	(void) memset(medep, 0, sizeof (*medep));
251 	return (rval);
252 }
253 
254 static med_handle_t *
255 open_medd_wrap(
256 	md_h_t		*mdhp,
257 	long		time_out,
258 	md_error_t	*ep
259 )
260 {
261 	med_handle_t		*hp = NULL;
262 	int			i;
263 	char    		*hnm;
264 
265 	assert(mdhp && mdhp->a_cnt > 0);
266 
267 	/* Loop through the hosts listed */
268 	i = min(mdhp->a_cnt, MAX_HOST_ADDRS) - 1;
269 	for (; i >= 0; i--) {
270 		hnm = mdhp->a_nm[i];
271 
272 		if ((hp = open_medd(hnm, time_out, ep)) == NULL) {
273 			if (mdanyrpcerror(ep) && i != 0) {
274 				mdclrerror(ep);
275 				continue;
276 			}
277 		}
278 		return (hp);
279 	}
280 
281 	rpc_createerr.cf_stat = RPC_CANTSEND;
282 	rpc_createerr.cf_error.re_status = 0;
283 	(void) mdrpccreateerror(ep, mdhp->a_nm[0],
284 	    dgettext(TEXT_DOMAIN, "medd open wrap"));
285 
286 	return (NULL);
287 }
288 
289 static int
290 setup_med_transtab(md_error_t *ep)
291 {
292 	mddb_med_t_parm_t	*tp = NULL;
293 	struct	stat		statb;
294 	int			i;
295 	size_t			alloc_size = 0;
296 	int			err = 0;
297 
298 
299 	if ((tp = Zalloc(sizeof (mddb_med_t_parm_t))) == NULL)
300 		return (mdsyserror(ep, ENOMEM, "setup_med_transtab"));
301 
302 	if (metaioctl(MD_MED_GET_TLEN, tp, &tp->med_tp_mde, NULL) != 0) {
303 		err = mdstealerror(ep, &tp->med_tp_mde);
304 		goto out;
305 	}
306 
307 	if (tp->med_tp_setup == 1)
308 		goto out;
309 
310 	alloc_size = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
311 	    (sizeof (mddb_med_t_ent_t) * tp->med_tp_nents);
312 
313 	if ((tp = Realloc(tp, alloc_size)) == NULL) {
314 		err = mdsyserror(ep, ENOMEM, "setup_med_transtab");
315 		goto out;
316 	}
317 
318 	if (metaioctl(MD_MED_GET_T, tp, &tp->med_tp_mde, NULL) != 0) {
319 		err = mdstealerror(ep, &tp->med_tp_mde);
320 		goto out;
321 	}
322 
323 	for (i = 0; i < tp->med_tp_nents; i++) {
324 		if (meta_stat(tp->med_tp_ents[i].med_te_nm, &statb) == -1) {
325 			md_perror("setup_med_transtab(): stat():");
326 			tp->med_tp_ents[i].med_te_dev = NODEV64;
327 		} else {
328 			tp->med_tp_ents[i].med_te_dev =
329 				meta_expldev(statb.st_rdev);
330 		}
331 	}
332 
333 	if (metaioctl(MD_MED_SET_T, tp, &tp->med_tp_mde, NULL) != 0)
334 		err = mdstealerror(ep, &tp->med_tp_mde);
335 
336 out:
337 	Free(tp);
338 	return (err);
339 }
340 
341 /*
342  * Externals
343  */
344 
345 /*
346  * NULLPROC - just returns a response
347  */
348 int
349 clnt_med_null(
350 	char			*hostname,
351 	md_error_t		*ep
352 )
353 {
354 	med_handle_t		*hp;
355 	med_err_t		res;
356 
357 	/* initialize */
358 	mdclrerror(ep);
359 
360 	/* do it */
361 	if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
362 		return (-1);
363 
364 	if (med_null_1(NULL, &res, hp->clntp) != RPC_SUCCESS)
365 		(void) mdrpcerror(ep, hp->clntp, hostname,
366 		    dgettext(TEXT_DOMAIN, "medd nullproc"));
367 
368 	close_medd(hp);
369 
370 	xdr_free(xdr_med_err_t, (char *)&res);
371 
372 	if (! mdisok(ep))
373 		return (-1);
374 
375 	return (0);
376 }
377 
378 /*
379  * Update the mediator information on the mediator.
380  * *** This is not normally called from user code, the kernel does this! ***
381  */
382 int
383 clnt_med_upd_data(
384 	md_h_t			*mdhp,
385 	mdsetname_t		*sp,
386 	med_data_t		*meddp,
387 	md_error_t		*ep
388 )
389 {
390 	med_handle_t		*hp;
391 	med_upd_data_args_t	args;
392 	med_err_t		res;
393 	md_set_desc		*sd;
394 
395 	/* initialize */
396 	mdclrerror(ep);
397 	(void) memset(&args, 0, sizeof (args));
398 	(void) memset(&res, 0, sizeof (res));
399 
400 	/* build args */
401 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
402 		return (-1);
403 
404 	if (MD_MNSET_DESC(sd))
405 		/*
406 		 * In the MN diskset, use a generic nodename, multiowner, as
407 		 * the node initiating the RPC request.  This allows
408 		 * any node to access mediator information.
409 		 *
410 		 * MN diskset reconfig cycle forces consistent
411 		 * view of set/node/drive/mediator information across all nodes
412 		 * in the MN diskset.  This allows the relaxation of
413 		 * node name checking in rpc.metamedd for MN disksets.
414 		 *
415 		 * In the traditional diskset, only a calling node that is
416 		 * in the mediator record's diskset nodelist can access
417 		 * mediator data.
418 		 */
419 		args.med.med_caller = Strdup(MED_MN_CALLER);
420 	else
421 		args.med.med_caller = Strdup(mynode());
422 	args.med.med_setname = Strdup(sp->setname);
423 	args.med.med_setno = sp->setno;
424 	args.med_data = *meddp;
425 
426 	/* do it */
427 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
428 		return (-1);
429 
430 	if (med_upd_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
431 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
432 		    dgettext(TEXT_DOMAIN, "medd update data"));
433 	else
434 		(void) meddstealerror(ep, &res);
435 
436 	close_medd(hp);
437 
438 	xdr_free(xdr_med_upd_data_args_t, (char *)&args);
439 	xdr_free(xdr_med_err_t, (char *)&res);
440 
441 	if (! mdisok(ep))
442 		return (-1);
443 
444 	return (0);
445 }
446 
447 /*
448  * Get the mediator data for this client from the mediator
449  */
450 int
451 clnt_med_get_data(
452 	md_h_t			*mdhp,
453 	mdsetname_t		*sp,
454 	med_data_t		*meddp,
455 	md_error_t		*ep
456 )
457 {
458 	med_handle_t		*hp;
459 	med_args_t		args;
460 	med_get_data_res_t	res;
461 	int			rval = -1;
462 	md_set_desc		*sd;
463 
464 	/* initialize */
465 	mdclrerror(ep);
466 	(void) memset(&args, 0, sizeof (args));
467 	(void) memset(&res, 0, sizeof (res));
468 
469 	/* build args */
470 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
471 		return (-1);
472 
473 	if (MD_MNSET_DESC(sd))
474 		/*
475 		 * In the MN diskset, use a generic nodename, multiowner, as
476 		 * the node initiating the RPC request.  This allows
477 		 * any node to access mediator information.
478 		 *
479 		 * MN diskset reconfig cycle forces consistent
480 		 * view of set/node/drive/mediator information across all nodes
481 		 * in the MN diskset.  This allows the relaxation of
482 		 * node name checking in rpc.metamedd for MN disksets.
483 		 *
484 		 * In the traditional diskset, only a calling node that is
485 		 * in the mediator record's diskset nodelist can access
486 		 * mediator data.
487 		 */
488 		args.med.med_caller = Strdup(MED_MN_CALLER);
489 	else
490 		args.med.med_caller = Strdup(mynode());
491 	args.med.med_setname = Strdup(sp->setname);
492 	args.med.med_setno = sp->setno;
493 
494 	/* do it */
495 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
496 		return (-1);
497 
498 	if (med_get_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
499 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
500 		    dgettext(TEXT_DOMAIN, "medd get data"));
501 	else
502 		(void) meddstealerror(ep, &res.med_status);
503 
504 	close_medd(hp);
505 
506 	if (mdisok(ep)) {
507 		/* do something with the results */
508 		(void) memmove(meddp, &res.med_data, sizeof (med_data_t));
509 		rval = 0;
510 	}
511 
512 	xdr_free(xdr_med_args_t, (char *)&args);
513 	xdr_free(xdr_med_get_data_res_t, (char *)&res);
514 
515 	return (rval);
516 }
517 
518 /*
519  * Update the mediator record on the mediator.
520  */
521 int
522 clnt_med_upd_rec(
523 	md_h_t			*mdhp,
524 	mdsetname_t		*sp,
525 	med_rec_t		*medrp,
526 	md_error_t		*ep
527 )
528 {
529 	med_handle_t		*hp;
530 	med_upd_rec_args_t	args;
531 	med_err_t		res;
532 	md_set_desc		*sd;
533 
534 	/* initialize */
535 	mdclrerror(ep);
536 	(void) memset(&args, 0, sizeof (args));
537 	(void) memset(&res, 0, sizeof (res));
538 
539 	/* build args */
540 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
541 		return (-1);
542 
543 	if (MD_MNSET_DESC(sd))
544 		/*
545 		 * In the MN diskset, use a generic nodename, multiowner, as
546 		 * the node initiating the RPC request.  This allows
547 		 * any node to access mediator information.
548 		 *
549 		 * MN diskset reconfig cycle forces consistent
550 		 * view of set/node/drive/mediator information across all nodes
551 		 * in the MN diskset.  This allows the relaxation of
552 		 * node name checking in rpc.metamedd for MN disksets.
553 		 *
554 		 * In the traditional diskset, only a calling node that is
555 		 * in the mediator record's diskset nodelist can access
556 		 * mediator data.
557 		 */
558 		args.med.med_caller = Strdup(MED_MN_CALLER);
559 	else
560 		args.med.med_caller = Strdup(mynode());
561 	args.med.med_setname = Strdup(sp->setname);
562 	args.med.med_setno = sp->setno;
563 	args.med_flags = 0;
564 	args.med_rec = *medrp;			/* structure assignment */
565 
566 	/* do it */
567 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
568 		return (-1);
569 
570 	if (med_upd_rec_1(&args, &res, hp->clntp) != RPC_SUCCESS)
571 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
572 		    dgettext(TEXT_DOMAIN, "medd update record"));
573 	else
574 		(void) meddstealerror(ep, &res);
575 
576 	close_medd(hp);
577 
578 	xdr_free(xdr_med_upd_rec_args_t, (char *)&args);
579 	xdr_free(xdr_med_err_t, (char *)&res);
580 
581 	if (! mdisok(ep))
582 		return (-1);
583 
584 	return (0);
585 }
586 
587 /*
588  * Get the mediator record for this client from the mediator
589  */
590 int
591 clnt_med_get_rec(
592 	md_h_t			*mdhp,
593 	mdsetname_t		*sp,
594 	med_rec_t		*medrp,
595 	md_error_t		*ep
596 )
597 {
598 	med_handle_t		*hp;
599 	med_args_t		args;
600 	med_get_rec_res_t	res;
601 	int			rval = -1;
602 	md_set_desc		*sd;
603 
604 	/* initialize */
605 	mdclrerror(ep);
606 	(void) memset(&args, 0, sizeof (args));
607 	(void) memset(&res, 0, sizeof (res));
608 
609 	/* build args */
610 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
611 		return (-1);
612 
613 	if (MD_MNSET_DESC(sd))
614 		/*
615 		 * In the MN diskset, use a generic nodename, multiowner, as
616 		 * the node initiating the RPC request.  This allows
617 		 * any node to access mediator information.
618 		 *
619 		 * MN diskset reconfig cycle forces consistent
620 		 * view of set/node/drive/mediator information across all nodes
621 		 * in the MN diskset.  This allows the relaxation of
622 		 * node name checking in rpc.metamedd for MN disksets.
623 		 *
624 		 * In the traditional diskset, only a calling node that is
625 		 * in the mediator record's diskset nodelist can access
626 		 * mediator data.
627 		 */
628 		args.med.med_caller = Strdup(MED_MN_CALLER);
629 	else
630 		args.med.med_caller = Strdup(mynode());
631 	args.med.med_setname = Strdup(sp->setname);
632 	args.med.med_setno = sp->setno;
633 
634 	/* do it */
635 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
636 		return (-1);
637 
638 	if (med_get_rec_1(&args, &res, hp->clntp) != RPC_SUCCESS)
639 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
640 		    dgettext(TEXT_DOMAIN, "medd get record"));
641 	else
642 		(void) meddstealerror(ep, &res.med_status);
643 
644 	close_medd(hp);
645 
646 	if (mdisok(ep)) {
647 		/* do something with the results */
648 		(void) memmove(medrp, &res.med_rec, sizeof (med_rec_t));
649 		rval = 0;
650 	}
651 
652 	xdr_free(xdr_med_args_t, (char *)&args);
653 	xdr_free(xdr_med_get_rec_res_t, (char *)&res);
654 
655 	return (rval);
656 }
657 
658 /*
659  * Get the name of the host from the mediator daemon.
660  */
661 int
662 clnt_med_hostname(
663 	char			*hostname,
664 	char			**ret_hostname,
665 	md_error_t		*ep
666 )
667 {
668 	med_handle_t		*hp;
669 	med_hnm_res_t		res;
670 	int			rval = -1;
671 
672 	/* initialize */
673 	mdclrerror(ep);
674 	(void) memset(&res, 0, sizeof (res));
675 
676 	/* No args */
677 
678 	/* do it */
679 	if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
680 		return (-1);
681 
682 	if (med_hostname_1(NULL, &res, hp->clntp) != RPC_SUCCESS)
683 		(void) mdrpcerror(ep, hp->clntp, hostname,
684 		    dgettext(TEXT_DOMAIN, "medd hostname"));
685 	else
686 		(void) meddstealerror(ep, &res.med_status);
687 
688 	close_medd(hp);
689 
690 	if (mdisok(ep)) {
691 		/* do something with the results */
692 		rval = 0;
693 
694 		if (ret_hostname != NULL)
695 			*ret_hostname = Strdup(res.med_hnm);
696 	}
697 
698 	xdr_free(xdr_med_hnm_res_t, (char *)&res);
699 
700 	return (rval);
701 }
702 
703 int
704 meta_med_hnm2ip(md_hi_arr_t *mp, md_error_t *ep)
705 {
706 	int		i, j;
707 	int		max_meds;
708 
709 	if ((max_meds = get_max_meds(ep)) == 0)
710 		return (-1);
711 
712 	for (i = 0; i < max_meds; i++) {
713 		mp->n_lst[i].a_flg = 0;
714 		/* See if this is the local host */
715 		if (mp->n_lst[i].a_cnt > 0 &&
716 		    strcmp(mp->n_lst[i].a_nm[0], mynode()) == NULL)
717 			mp->n_lst[i].a_flg |= NMIP_F_LOCAL;
718 
719 		for (j = 0; j < mp->n_lst[i].a_cnt; j++) {
720 			struct hostent	*hp;
721 			char		*hnm = mp->n_lst[i].a_nm[j];
722 
723 			/*
724 			 * Cluster nodename support
725 			 *
726 			 * See if the clustering code can give us an IP addr
727 			 * for the stored name. If not, find it the old way
728 			 * which will use the public interface.
729 			 */
730 			if (sdssc_get_priv_ipaddr(mp->n_lst[i].a_nm[j],
731 			    (struct in_addr *)&mp->n_lst[i].a_ip[j]) !=
732 					SDSSC_OKAY) {
733 				if ((hp = gethostbyname(hnm)) == NULL)
734 					return (mdsyserror(ep, EADDRNOTAVAIL,
735 					    hnm));
736 
737 				/* We only do INET addresses */
738 				if (hp->h_addrtype != AF_INET)
739 					return (mdsyserror(ep, EPFNOSUPPORT,
740 					    hnm));
741 
742 				/* We take the first address only */
743 				if (*hp->h_addr_list) {
744 					(void) memmove(&mp->n_lst[i].a_ip[j],
745 					    *hp->h_addr_list,
746 					    sizeof (struct in_addr));
747 				} else
748 					return (mdsyserror(ep, EADDRNOTAVAIL,
749 					    hnm));
750 			}
751 
752 		}
753 	}
754 	return (0);
755 }
756 
757 int
758 meta_h2hi(md_h_arr_t *mdhp, md_hi_arr_t *mdhip, md_error_t *ep)
759 {
760 	int			i, j;
761 	int			max_meds;
762 
763 	if ((max_meds = get_max_meds(ep)) == 0)
764 		return (-1);
765 
766 	mdhip->n_cnt = mdhp->n_cnt;
767 
768 	for (i = 0; i < max_meds; i++) {
769 		mdhip->n_lst[i].a_flg = 0;
770 		mdhip->n_lst[i].a_cnt = mdhp->n_lst[i].a_cnt;
771 		if (mdhp->n_lst[i].a_cnt == 0)
772 			continue;
773 		for (j = 0; j < mdhp->n_lst[i].a_cnt; j++)
774 			(void) strcpy(mdhip->n_lst[i].a_nm[j],
775 			    mdhp->n_lst[i].a_nm[j]);
776 	}
777 	return (0);
778 }
779 
780 int
781 meta_hi2h(md_hi_arr_t *mdhip, md_h_arr_t *mdhp, md_error_t *ep)
782 {
783 	int			i, j;
784 	int			max_meds;
785 
786 	if ((max_meds = get_max_meds(ep)) == 0)
787 		return (-1);
788 
789 	mdhp->n_cnt = mdhip->n_cnt;
790 	for (i = 0; i < max_meds; i++) {
791 		mdhp->n_lst[i].a_cnt = mdhip->n_lst[i].a_cnt;
792 		if (mdhip->n_lst[i].a_cnt == 0)
793 			continue;
794 		for (j = 0; j < mdhip->n_lst[i].a_cnt; j++)
795 			(void) strcpy(mdhp->n_lst[i].a_nm[j],
796 			    mdhip->n_lst[i].a_nm[j]);
797 	}
798 	return (0);
799 }
800 
801 int
802 setup_med_cfg(
803 	mdsetname_t		*sp,
804 	mddb_config_t		*cp,
805 	int			force,
806 	md_error_t		*ep
807 )
808 {
809 	md_set_desc		*sd;
810 	int			i;
811 	int			max_meds;
812 
813 	if (metaislocalset(sp))
814 		return (0);
815 
816 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
817 		return (-1);
818 
819 	if (setup_med_transtab(ep))
820 		return (-1);
821 
822 	if (meta_h2hi(&sd->sd_med, &cp->c_med, ep))
823 		return (-1);
824 
825 	/* Make sure the ip addresses are current */
826 	if (meta_med_hnm2ip(&cp->c_med, ep))
827 		return (-1);
828 
829 	if (force)
830 		return (0);
831 
832 	if ((max_meds = get_max_meds(ep)) == 0)
833 		return (-1);
834 
835 	/* Make sure metamedd still running on host - only chk nodename */
836 	for (i = 0; i < max_meds; i++) {
837 		char		*hostname;
838 		char		*hnm;
839 
840 		if (sd->sd_med.n_lst[i].a_cnt == 0)
841 			continue;
842 
843 		hnm = sd->sd_med.n_lst[i].a_nm[0];
844 
845 		if (clnt_med_hostname(hnm, &hostname, ep))
846 			return (mddserror(ep, MDE_DS_NOMEDONHOST, sp->setno,
847 			    hnm, NULL, sp->setname));
848 		Free(hostname);
849 	}
850 	return (0);
851 }
852