xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_med.c (revision a18dc42fc967d11feba9b8be61c6727dc6c56b48)
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 /*
24  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 /*
31  * Just in case we're not in a build environment, make sure that
32  * TEXT_DOMAIN gets set to something.
33  */
34 #if !defined(TEXT_DOMAIN)
35 #define	TEXT_DOMAIN "SYS_TEST"
36 #endif
37 
38 /*
39  * Mediator functions
40  */
41 
42 #include <meta.h>
43 #include <metamed.h>
44 #include <dlfcn.h>
45 #include <sdssc.h>
46 
47 /*
48  * There are too many external factors that affect the timing of the
49  * operations, so we set the timeout to a very large value, in this
50  * case 1 day, which should handle HW timeouts, large configurations,
51  * and other potential delays.
52  */
53 #define	CL_LONG_TMO	86400L			/* 1 day */
54 #define	CL_MEDIUM_TMO	3600L			/* 1 hour */
55 #define	CL_SHORT_TMO	600L			/* 10 minutes */
56 #define	CL_DEF_TMO	10L			/* 10 seconds */
57 
58 static	md_timeval32_t def_rpcb_timeout =  { MD_CLNT_CREATE_TOUT, 0 };
59 
60 /*
61  * RPC handle
62  */
63 typedef struct {
64 	char	*hostname;
65 	CLIENT	*clntp;
66 } med_handle_t;
67 
68 /*
69  * Data to be sent from med_clnt_create_timed to med_create_helper via
70  * meta_client_create_retry.
71  */
72 typedef struct {
73 	rpcprog_t	mcd_program;	/* RPC program designation */
74 	rpcvers_t	mcd_version;	/* RPC version */
75 	char		*mcd_nettype;	/* Type of network to use for RPC */
76 } med_create_data_t;
77 
78 /*
79  * Perform the work of actually doing the clnt_create for
80  * meta_client_create_retry.
81  */
82 static CLIENT *
83 med_create_helper(char *hostname, void *private, struct timeval *time_out)
84 {
85 	med_create_data_t	*cd = (med_create_data_t *)private;
86 
87 	return (clnt_create_timed(hostname, cd->mcd_program, cd->mcd_version,
88 		cd->mcd_nettype, time_out));
89 }
90 
91 static
92 CLIENT *med_clnt_create_timed(
93 	char *hostname,
94 	const ulong_t prog,
95 	const ulong_t vers,
96 	char *nettype,
97 	const md_timeval32_t *tp
98 )
99 {
100 	med_create_data_t	cd;	/* Create data. */
101 
102 	cd.mcd_program = prog;
103 	cd.mcd_version = vers;
104 	cd.mcd_nettype = nettype;
105 	return (meta_client_create_retry(hostname, med_create_helper,
106 		(void *)&cd, (time_t)tp->tv_sec, NULL));
107 }
108 
109 /*
110  * Set the timeout value for this client handle.
111  */
112 static int
113 cl_sto_medd(
114 	CLIENT		*clntp,
115 	char		*hostname,
116 	long		time_out,
117 	md_error_t	*ep
118 )
119 {
120 	md_timeval32_t	nto;
121 
122 	(void) memset(&nto, '\0', sizeof (nto));
123 
124 	nto.tv_sec = time_out;
125 
126 	if (clnt_control(clntp, CLSET_TIMEOUT, (char *)&nto) != TRUE)
127 		return (mdrpcerror(ep, clntp, hostname,
128 		    dgettext(TEXT_DOMAIN, "metad client set timeout")));
129 
130 	return (0);
131 }
132 
133 /*
134  * close RPC connection
135  */
136 static void
137 close_medd(
138 	med_handle_t	*hp
139 )
140 {
141 	assert(hp != NULL);
142 	if (hp->hostname != NULL) {
143 		Free(hp->hostname);
144 	}
145 	if (hp->clntp != NULL) {
146 		auth_destroy(hp->clntp->cl_auth);
147 		clnt_destroy(hp->clntp);
148 	}
149 	Free(hp);
150 }
151 
152 /*
153  * open RPC connection to rpc.medd
154  */
155 static med_handle_t *
156 open_medd(
157 	char		*hostname,
158 	long		time_out,
159 	md_error_t	*ep
160 )
161 {
162 	CLIENT		*clntp;
163 	med_handle_t	*hp;
164 
165 	/* default to local host */
166 	if ((hostname == NULL) || (*hostname == '\0'))
167 		hostname = mynode();
168 
169 	/* open RPC connection */
170 	assert(hostname != NULL);
171 	if ((clntp = med_clnt_create_timed(hostname, MED_PROG, MED_VERS,
172 	    "tcp", &def_rpcb_timeout)) == NULL) {
173 		if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
174 			clnt_pcreateerror(hostname);
175 		(void) mdrpccreateerror(ep, hostname,
176 		    "medd med_clnt_create_timed");
177 		return (NULL);
178 	} else {
179 		auth_destroy(clntp->cl_auth);
180 		clntp->cl_auth = authsys_create_default();
181 		assert(clntp->cl_auth != NULL);
182 	}
183 
184 	if (cl_sto_medd(clntp, hostname, time_out, ep) != 0)
185 		return (NULL);
186 
187 	/* return connection */
188 	hp = Zalloc(sizeof (*hp));
189 	hp->hostname = Strdup(hostname);
190 	hp->clntp = clntp;
191 
192 	return (hp);
193 }
194 
195 /*
196  * steal and convert med_err_t
197  */
198 int
199 meddstealerror(
200 	md_error_t	*ep,
201 	med_err_t	*medep
202 )
203 {
204 	char		buf[BUFSIZ];
205 	char		*p = buf;
206 	size_t		psize = BUFSIZ;
207 	char		*emsg;
208 	int		rval = -1;
209 
210 	/* no error */
211 	if (medep->med_errno == 0) {
212 		/* assert(medep->name == NULL); */
213 		rval = 0;
214 		goto out;
215 	}
216 
217 	/* steal error */
218 	if ((medep->med_node != NULL) && (medep->med_node[0] != '\0')) {
219 		(void) snprintf(p, psize, "%s: ", medep->med_node);
220 		p = &buf[strlen(buf)];
221 		psize = buf + BUFSIZ - p;
222 	}
223 
224 	if ((medep->med_misc != NULL) && (medep->med_misc[0] != '\0')) {
225 		(void) snprintf(p, psize, "%s: ", medep->med_misc);
226 		p = &buf[strlen(buf)];
227 		psize = buf + BUFSIZ - p;
228 	}
229 
230 	if (medep->med_errno < 0) {
231 		if ((emsg = med_errnum_to_str(medep->med_errno)) != NULL)
232 			(void) snprintf(p, psize, "%s", emsg);
233 		else
234 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
235 			    "unknown mediator errno %d\n"), medep->med_errno);
236 	} else {
237 		if ((emsg = strerror(medep->med_errno)) != NULL)
238 			(void) snprintf(p, psize, "%s", emsg);
239 		else
240 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
241 			    "errno %d out of range"), medep->med_errno);
242 	}
243 	(void) mderror(ep, MDE_MED_ERROR, buf);
244 
245 	/* cleanup, return success */
246 out:
247 	if (medep->med_node != NULL)
248 		Free(medep->med_node);
249 	if (medep->med_misc != NULL)
250 		Free(medep->med_misc);
251 	(void) memset(medep, 0, sizeof (*medep));
252 	return (rval);
253 }
254 
255 static med_handle_t *
256 open_medd_wrap(
257 	md_h_t		*mdhp,
258 	long		time_out,
259 	md_error_t	*ep
260 )
261 {
262 	med_handle_t		*hp = NULL;
263 	int			i;
264 	char    		*hnm;
265 
266 	assert(mdhp && mdhp->a_cnt > 0);
267 
268 	/* Loop through the hosts listed */
269 	i = min(mdhp->a_cnt, MAX_HOST_ADDRS) - 1;
270 	for (; i >= 0; i--) {
271 		hnm = mdhp->a_nm[i];
272 
273 		if ((hp = open_medd(hnm, time_out, ep)) == NULL) {
274 			if (mdanyrpcerror(ep) && i != 0) {
275 				mdclrerror(ep);
276 				continue;
277 			}
278 		}
279 		return (hp);
280 	}
281 
282 	rpc_createerr.cf_stat = RPC_CANTSEND;
283 	rpc_createerr.cf_error.re_status = 0;
284 	(void) mdrpccreateerror(ep, mdhp->a_nm[0],
285 	    dgettext(TEXT_DOMAIN, "medd open wrap"));
286 
287 	return (NULL);
288 }
289 
290 static int
291 setup_med_transtab(md_error_t *ep)
292 {
293 	mddb_med_t_parm_t	*tp = NULL;
294 	struct	stat		statb;
295 	int			i;
296 	size_t			alloc_size = 0;
297 	int			err = 0;
298 
299 
300 	if ((tp = Zalloc(sizeof (mddb_med_t_parm_t))) == NULL)
301 		return (mdsyserror(ep, ENOMEM, "setup_med_transtab"));
302 
303 	if (metaioctl(MD_MED_GET_TLEN, tp, &tp->med_tp_mde, NULL) != 0) {
304 		err = mdstealerror(ep, &tp->med_tp_mde);
305 		goto out;
306 	}
307 
308 	if (tp->med_tp_setup == 1)
309 		goto out;
310 
311 	alloc_size = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) +
312 	    (sizeof (mddb_med_t_ent_t) * tp->med_tp_nents);
313 
314 	if ((tp = Realloc(tp, alloc_size)) == NULL) {
315 		err = mdsyserror(ep, ENOMEM, "setup_med_transtab");
316 		goto out;
317 	}
318 
319 	if (metaioctl(MD_MED_GET_T, tp, &tp->med_tp_mde, NULL) != 0) {
320 		err = mdstealerror(ep, &tp->med_tp_mde);
321 		goto out;
322 	}
323 
324 	for (i = 0; i < tp->med_tp_nents; i++) {
325 		if (meta_stat(tp->med_tp_ents[i].med_te_nm, &statb) == -1) {
326 			md_perror("setup_med_transtab(): stat():");
327 			tp->med_tp_ents[i].med_te_dev = NODEV64;
328 		} else {
329 			tp->med_tp_ents[i].med_te_dev =
330 				meta_expldev(statb.st_rdev);
331 		}
332 	}
333 
334 	if (metaioctl(MD_MED_SET_T, tp, &tp->med_tp_mde, NULL) != 0)
335 		err = mdstealerror(ep, &tp->med_tp_mde);
336 
337 out:
338 	Free(tp);
339 	return (err);
340 }
341 
342 /*
343  * Externals
344  */
345 
346 /*
347  * NULLPROC - just returns a response
348  */
349 int
350 clnt_med_null(
351 	char			*hostname,
352 	md_error_t		*ep
353 )
354 {
355 	med_handle_t		*hp;
356 	med_err_t		res;
357 
358 	/* initialize */
359 	mdclrerror(ep);
360 
361 	/* do it */
362 	if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
363 		return (-1);
364 
365 	if (med_null_1(NULL, &res, hp->clntp) != RPC_SUCCESS)
366 		(void) mdrpcerror(ep, hp->clntp, hostname,
367 		    dgettext(TEXT_DOMAIN, "medd nullproc"));
368 
369 	close_medd(hp);
370 
371 	xdr_free(xdr_med_err_t, (char *)&res);
372 
373 	if (! mdisok(ep))
374 		return (-1);
375 
376 	return (0);
377 }
378 
379 /*
380  * Update the mediator information on the mediator.
381  * This function does the same functionality as
382  * clnt_med_upd_data() except that it takes different
383  * argument so that host which is just a mediator, can
384  * still update its mediator record.
385  */
386 int
387 clnt_user_med_upd_data(
388 	md_h_t	*mdhp,
389 	bool_t	obandiskset,
390 	char	*setname,
391 	uint_t	setnum,
392 	med_data_t	*meddp,
393 	md_error_t	*ep
394 )
395 {
396 	med_handle_t    	*hp;
397 	med_upd_data_args_t	args;
398 	med_err_t		res;
399 
400 	/* Initialize */
401 	mdclrerror(ep);
402 	(void) memset(&args, 0, sizeof (args));
403 	(void) memset(&res, 0, sizeof (res));
404 
405 	/* Build args */
406 	if (obandiskset)
407 		args.med.med_caller = Strdup(MED_MN_CALLER);
408 	else
409 		args.med.med_caller = Strdup(mynode());
410 
411 	args.med.med_setname = Strdup(setname);
412 	args.med.med_setno = setnum;
413 	args.med_data = *meddp;
414 
415 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
416 		return (-1);
417 
418 	if (med_upd_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
419 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
420 		    dgettext(TEXT_DOMAIN, "medd get record"));
421 	else
422 		(void) meddstealerror(ep, &res);
423 
424 	close_medd(hp);
425 
426 	xdr_free(xdr_med_upd_data_args_t, (char *)&args);
427 	xdr_free(xdr_med_err_t, (char *)&res);
428 
429 	if (! mdisok(ep))
430 		return (-1);
431 
432 	return (0);
433 }
434 
435 /*
436  * Get the mediator information from the client.
437  * The code does same functinality as clnt_med_get_data()
438  * except that it takes different arguments so that
439  * host which doesn't have set information, can still
440  * get access to mediator information
441  */
442 int
443 clnt_user_med_get_data(
444 	md_h_t	*mdhp,
445 	bool_t	obandiskset,
446 	char	*setname,
447 	uint_t	setnum,
448 	med_data_t	*meddp,
449 	md_error_t	*ep
450 )
451 {
452 	int			rval = -1;
453 	med_handle_t		*hp;
454 	med_args_t		args;
455 	med_get_data_res_t	res;
456 
457 	/* Initialize */
458 	mdclrerror(ep);
459 	(void) memset(&args, 0, sizeof (args));
460 	(void) memset(&res, 0, sizeof (res));
461 
462 	/* Build args */
463 	if (obandiskset)
464 		args.med.med_caller = Strdup(MED_MN_CALLER);
465 	else
466 		args.med.med_caller = Strdup(mynode());
467 
468 	args.med.med_setname = Strdup(setname);
469 	args.med.med_setno = setnum;
470 
471 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
472 		return (-1);
473 
474 	if (med_get_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
475 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
476 		    dgettext(TEXT_DOMAIN, "medd get record"));
477 	else
478 		(void) meddstealerror(ep, &res.med_status);
479 
480 	close_medd(hp);
481 
482 	if (mdisok(ep)) {
483 		/* copy the mediator data in meddp */
484 		(void) memmove(meddp, &res.med_data, sizeof (med_data_t));
485 		rval = 0;
486 	}
487 
488 	xdr_free(xdr_med_args_t, (char *)&args);
489 	xdr_free(xdr_med_get_data_res_t, (char *)&res);
490 
491 	return (rval);
492 }
493 
494 
495 /*
496  * Update the mediator information on the mediator.
497  * *** This is not normally called from user code, the kernel does this! ***
498  */
499 int
500 clnt_med_upd_data(
501 	md_h_t			*mdhp,
502 	mdsetname_t		*sp,
503 	med_data_t		*meddp,
504 	md_error_t		*ep
505 )
506 {
507 	med_handle_t		*hp;
508 	med_upd_data_args_t	args;
509 	med_err_t		res;
510 	md_set_desc		*sd;
511 
512 	/* initialize */
513 	mdclrerror(ep);
514 	(void) memset(&args, 0, sizeof (args));
515 	(void) memset(&res, 0, sizeof (res));
516 
517 	/* build args */
518 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
519 		return (-1);
520 
521 	if (MD_MNSET_DESC(sd))
522 		/*
523 		 * In the MN diskset, use a generic nodename, multiowner, as
524 		 * the node initiating the RPC request.  This allows
525 		 * any node to access mediator information.
526 		 *
527 		 * MN diskset reconfig cycle forces consistent
528 		 * view of set/node/drive/mediator information across all nodes
529 		 * in the MN diskset.  This allows the relaxation of
530 		 * node name checking in rpc.metamedd for MN disksets.
531 		 *
532 		 * In the traditional diskset, only a calling node that is
533 		 * in the mediator record's diskset nodelist can access
534 		 * mediator data.
535 		 */
536 		args.med.med_caller = Strdup(MED_MN_CALLER);
537 	else
538 		args.med.med_caller = Strdup(mynode());
539 	args.med.med_setname = Strdup(sp->setname);
540 	args.med.med_setno = sp->setno;
541 	args.med_data = *meddp;
542 
543 	/* do it */
544 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
545 		return (-1);
546 
547 	if (med_upd_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
548 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
549 		    dgettext(TEXT_DOMAIN, "medd update data"));
550 	else
551 		(void) meddstealerror(ep, &res);
552 
553 	close_medd(hp);
554 
555 	xdr_free(xdr_med_upd_data_args_t, (char *)&args);
556 	xdr_free(xdr_med_err_t, (char *)&res);
557 
558 	if (! mdisok(ep))
559 		return (-1);
560 
561 	return (0);
562 }
563 
564 /*
565  * Get the mediator data for this client from the mediator
566  */
567 int
568 clnt_med_get_data(
569 	md_h_t			*mdhp,
570 	mdsetname_t		*sp,
571 	med_data_t		*meddp,
572 	md_error_t		*ep
573 )
574 {
575 	med_handle_t		*hp;
576 	med_args_t		args;
577 	med_get_data_res_t	res;
578 	int			rval = -1;
579 	md_set_desc		*sd;
580 
581 	/* initialize */
582 	mdclrerror(ep);
583 	(void) memset(&args, 0, sizeof (args));
584 	(void) memset(&res, 0, sizeof (res));
585 
586 	/* build args */
587 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
588 		return (-1);
589 
590 	if (MD_MNSET_DESC(sd))
591 		/*
592 		 * In the MN diskset, use a generic nodename, multiowner, as
593 		 * the node initiating the RPC request.  This allows
594 		 * any node to access mediator information.
595 		 *
596 		 * MN diskset reconfig cycle forces consistent
597 		 * view of set/node/drive/mediator information across all nodes
598 		 * in the MN diskset.  This allows the relaxation of
599 		 * node name checking in rpc.metamedd for MN disksets.
600 		 *
601 		 * In the traditional diskset, only a calling node that is
602 		 * in the mediator record's diskset nodelist can access
603 		 * mediator data.
604 		 */
605 		args.med.med_caller = Strdup(MED_MN_CALLER);
606 	else
607 		args.med.med_caller = Strdup(mynode());
608 	args.med.med_setname = Strdup(sp->setname);
609 	args.med.med_setno = sp->setno;
610 
611 	/* do it */
612 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
613 		return (-1);
614 
615 	if (med_get_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
616 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
617 		    dgettext(TEXT_DOMAIN, "medd get data"));
618 	else
619 		(void) meddstealerror(ep, &res.med_status);
620 
621 	close_medd(hp);
622 
623 	if (mdisok(ep)) {
624 		/* do something with the results */
625 		(void) memmove(meddp, &res.med_data, sizeof (med_data_t));
626 		rval = 0;
627 	}
628 
629 	xdr_free(xdr_med_args_t, (char *)&args);
630 	xdr_free(xdr_med_get_data_res_t, (char *)&res);
631 
632 	return (rval);
633 }
634 
635 /*
636  * Update the mediator record on the mediator.
637  */
638 int
639 clnt_med_upd_rec(
640 	md_h_t			*mdhp,
641 	mdsetname_t		*sp,
642 	med_rec_t		*medrp,
643 	md_error_t		*ep
644 )
645 {
646 	med_handle_t		*hp;
647 	med_upd_rec_args_t	args;
648 	med_err_t		res;
649 	md_set_desc		*sd;
650 
651 	/* initialize */
652 	mdclrerror(ep);
653 	(void) memset(&args, 0, sizeof (args));
654 	(void) memset(&res, 0, sizeof (res));
655 
656 	/* build args */
657 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
658 		return (-1);
659 
660 	if (MD_MNSET_DESC(sd))
661 		/*
662 		 * In the MN diskset, use a generic nodename, multiowner, as
663 		 * the node initiating the RPC request.  This allows
664 		 * any node to access mediator information.
665 		 *
666 		 * MN diskset reconfig cycle forces consistent
667 		 * view of set/node/drive/mediator information across all nodes
668 		 * in the MN diskset.  This allows the relaxation of
669 		 * node name checking in rpc.metamedd for MN disksets.
670 		 *
671 		 * In the traditional diskset, only a calling node that is
672 		 * in the mediator record's diskset nodelist can access
673 		 * mediator data.
674 		 */
675 		args.med.med_caller = Strdup(MED_MN_CALLER);
676 	else
677 		args.med.med_caller = Strdup(mynode());
678 	args.med.med_setname = Strdup(sp->setname);
679 	args.med.med_setno = sp->setno;
680 	args.med_flags = 0;
681 	args.med_rec = *medrp;			/* structure assignment */
682 
683 	/* do it */
684 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
685 		return (-1);
686 
687 	if (med_upd_rec_1(&args, &res, hp->clntp) != RPC_SUCCESS)
688 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
689 		    dgettext(TEXT_DOMAIN, "medd update record"));
690 	else
691 		(void) meddstealerror(ep, &res);
692 
693 	close_medd(hp);
694 
695 	xdr_free(xdr_med_upd_rec_args_t, (char *)&args);
696 	xdr_free(xdr_med_err_t, (char *)&res);
697 
698 	if (! mdisok(ep))
699 		return (-1);
700 
701 	return (0);
702 }
703 
704 /*
705  * Get the mediator record for this client from the mediator
706  */
707 int
708 clnt_med_get_rec(
709 	md_h_t			*mdhp,
710 	mdsetname_t		*sp,
711 	med_rec_t		*medrp,
712 	md_error_t		*ep
713 )
714 {
715 	med_handle_t		*hp;
716 	med_args_t		args;
717 	med_get_rec_res_t	res;
718 	int			rval = -1;
719 	md_set_desc		*sd;
720 
721 	/* initialize */
722 	mdclrerror(ep);
723 	(void) memset(&args, 0, sizeof (args));
724 	(void) memset(&res, 0, sizeof (res));
725 
726 	/* build args */
727 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
728 		return (-1);
729 
730 	if (MD_MNSET_DESC(sd))
731 		/*
732 		 * In the MN diskset, use a generic nodename, multiowner, as
733 		 * the node initiating the RPC request.  This allows
734 		 * any node to access mediator information.
735 		 *
736 		 * MN diskset reconfig cycle forces consistent
737 		 * view of set/node/drive/mediator information across all nodes
738 		 * in the MN diskset.  This allows the relaxation of
739 		 * node name checking in rpc.metamedd for MN disksets.
740 		 *
741 		 * In the traditional diskset, only a calling node that is
742 		 * in the mediator record's diskset nodelist can access
743 		 * mediator data.
744 		 */
745 		args.med.med_caller = Strdup(MED_MN_CALLER);
746 	else
747 		args.med.med_caller = Strdup(mynode());
748 	args.med.med_setname = Strdup(sp->setname);
749 	args.med.med_setno = sp->setno;
750 
751 	/* do it */
752 	if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
753 		return (-1);
754 
755 	if (med_get_rec_1(&args, &res, hp->clntp) != RPC_SUCCESS)
756 		(void) mdrpcerror(ep, hp->clntp, hp->hostname,
757 		    dgettext(TEXT_DOMAIN, "medd get record"));
758 	else
759 		(void) meddstealerror(ep, &res.med_status);
760 
761 	close_medd(hp);
762 
763 	if (mdisok(ep)) {
764 		/* do something with the results */
765 		(void) memmove(medrp, &res.med_rec, sizeof (med_rec_t));
766 		rval = 0;
767 	}
768 
769 	xdr_free(xdr_med_args_t, (char *)&args);
770 	xdr_free(xdr_med_get_rec_res_t, (char *)&res);
771 
772 	return (rval);
773 }
774 
775 /*
776  * Get the name of the host from the mediator daemon.
777  */
778 int
779 clnt_med_hostname(
780 	char			*hostname,
781 	char			**ret_hostname,
782 	md_error_t		*ep
783 )
784 {
785 	med_handle_t		*hp;
786 	med_hnm_res_t		res;
787 	int			rval = -1;
788 
789 	/* initialize */
790 	mdclrerror(ep);
791 	(void) memset(&res, 0, sizeof (res));
792 
793 	/* No args */
794 
795 	/* do it */
796 	if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
797 		return (-1);
798 
799 	if (med_hostname_1(NULL, &res, hp->clntp) != RPC_SUCCESS)
800 		(void) mdrpcerror(ep, hp->clntp, hostname,
801 		    dgettext(TEXT_DOMAIN, "medd hostname"));
802 	else
803 		(void) meddstealerror(ep, &res.med_status);
804 
805 	close_medd(hp);
806 
807 	if (mdisok(ep)) {
808 		/* do something with the results */
809 		rval = 0;
810 
811 		if (ret_hostname != NULL)
812 			*ret_hostname = Strdup(res.med_hnm);
813 	}
814 
815 	xdr_free(xdr_med_hnm_res_t, (char *)&res);
816 
817 	return (rval);
818 }
819 
820 int
821 meta_med_hnm2ip(md_hi_arr_t *mp, md_error_t *ep)
822 {
823 	int		i, j;
824 	int		max_meds;
825 
826 	if ((max_meds = get_max_meds(ep)) == 0)
827 		return (-1);
828 
829 	for (i = 0; i < max_meds; i++) {
830 		mp->n_lst[i].a_flg = 0;
831 		/* See if this is the local host */
832 		if (mp->n_lst[i].a_cnt > 0 &&
833 		    strcmp(mp->n_lst[i].a_nm[0], mynode()) == NULL)
834 			mp->n_lst[i].a_flg |= NMIP_F_LOCAL;
835 
836 		for (j = 0; j < mp->n_lst[i].a_cnt; j++) {
837 			struct hostent	*hp;
838 			char		*hnm = mp->n_lst[i].a_nm[j];
839 
840 			/*
841 			 * Cluster nodename support
842 			 *
843 			 * See if the clustering code can give us an IP addr
844 			 * for the stored name. If not, find it the old way
845 			 * which will use the public interface.
846 			 */
847 			if (sdssc_get_priv_ipaddr(mp->n_lst[i].a_nm[j],
848 			    (struct in_addr *)&mp->n_lst[i].a_ip[j]) !=
849 					SDSSC_OKAY) {
850 				if ((hp = gethostbyname(hnm)) == NULL)
851 					return (mdsyserror(ep, EADDRNOTAVAIL,
852 					    hnm));
853 
854 				/* We only do INET addresses */
855 				if (hp->h_addrtype != AF_INET)
856 					return (mdsyserror(ep, EPFNOSUPPORT,
857 					    hnm));
858 
859 				/* We take the first address only */
860 				if (*hp->h_addr_list) {
861 					(void) memmove(&mp->n_lst[i].a_ip[j],
862 					    *hp->h_addr_list,
863 					    sizeof (struct in_addr));
864 				} else
865 					return (mdsyserror(ep, EADDRNOTAVAIL,
866 					    hnm));
867 			}
868 
869 		}
870 	}
871 	return (0);
872 }
873 
874 int
875 meta_h2hi(md_h_arr_t *mdhp, md_hi_arr_t *mdhip, md_error_t *ep)
876 {
877 	int			i, j;
878 	int			max_meds;
879 
880 	if ((max_meds = get_max_meds(ep)) == 0)
881 		return (-1);
882 
883 	mdhip->n_cnt = mdhp->n_cnt;
884 
885 	for (i = 0; i < max_meds; i++) {
886 		mdhip->n_lst[i].a_flg = 0;
887 		mdhip->n_lst[i].a_cnt = mdhp->n_lst[i].a_cnt;
888 		if (mdhp->n_lst[i].a_cnt == 0)
889 			continue;
890 		for (j = 0; j < mdhp->n_lst[i].a_cnt; j++)
891 			(void) strcpy(mdhip->n_lst[i].a_nm[j],
892 			    mdhp->n_lst[i].a_nm[j]);
893 	}
894 	return (0);
895 }
896 
897 int
898 meta_hi2h(md_hi_arr_t *mdhip, md_h_arr_t *mdhp, md_error_t *ep)
899 {
900 	int			i, j;
901 	int			max_meds;
902 
903 	if ((max_meds = get_max_meds(ep)) == 0)
904 		return (-1);
905 
906 	mdhp->n_cnt = mdhip->n_cnt;
907 	for (i = 0; i < max_meds; i++) {
908 		mdhp->n_lst[i].a_cnt = mdhip->n_lst[i].a_cnt;
909 		if (mdhip->n_lst[i].a_cnt == 0)
910 			continue;
911 		for (j = 0; j < mdhip->n_lst[i].a_cnt; j++)
912 			(void) strcpy(mdhp->n_lst[i].a_nm[j],
913 			    mdhip->n_lst[i].a_nm[j]);
914 	}
915 	return (0);
916 }
917 
918 int
919 setup_med_cfg(
920 	mdsetname_t		*sp,
921 	mddb_config_t		*cp,
922 	int			force,
923 	md_error_t		*ep
924 )
925 {
926 	md_set_desc		*sd;
927 	int			i;
928 	int			max_meds;
929 
930 	if (metaislocalset(sp))
931 		return (0);
932 
933 	if ((sd = metaget_setdesc(sp, ep)) == NULL)
934 		return (-1);
935 
936 	if (setup_med_transtab(ep))
937 		return (-1);
938 
939 	if (meta_h2hi(&sd->sd_med, &cp->c_med, ep))
940 		return (-1);
941 
942 	/* Make sure the ip addresses are current */
943 	if (meta_med_hnm2ip(&cp->c_med, ep))
944 		return (-1);
945 
946 	if (force)
947 		return (0);
948 
949 	if ((max_meds = get_max_meds(ep)) == 0)
950 		return (-1);
951 
952 	/* Make sure metamedd still running on host - only chk nodename */
953 	for (i = 0; i < max_meds; i++) {
954 		char		*hostname;
955 		char		*hnm;
956 
957 		if (sd->sd_med.n_lst[i].a_cnt == 0)
958 			continue;
959 
960 		hnm = sd->sd_med.n_lst[i].a_nm[0];
961 
962 		if (clnt_med_hostname(hnm, &hostname, ep))
963 			return (mddserror(ep, MDE_DS_NOMEDONHOST, sp->setno,
964 			    hnm, NULL, sp->setname));
965 		Free(hostname);
966 	}
967 	return (0);
968 }
969 
970 /*
971  * This is a general routine to get mediator information from
972  * file /etc/lvm/meddb. Commands medstat and metainit use this
973  * routine to get mediator information from all mediator hosts or update
974  * its mediator record respectively.
975  */
976 int
977 meta_mediator_info_from_file(char *sname, int verbose, md_error_t *ep)
978 {
979 	uint_t		c;
980 	int		i;
981 	int		j;
982 	int		fd;
983 	int		rec_size;
984 	char		*setname;
985 	uint_t		setnum;
986 	med_rec_t	*rec_buf = NULL;
987 	med_db_hdr_t	*dbhbr;
988 	med_rec_t	*medrecp;
989 	med_data_t	medd;
990 	med_data_t	*save_medd;
991 	md_h_t		mdh;
992 	uint_t		latest_med_dat_cc = 0;
993 	int		retval;
994 	int		medok = 0;
995 	int		golden = 0;
996 	bool_t		obandiskset;
997 
998 	/* Open the meddb file */
999 	if ((fd = open(MED_DB_FILE, O_RDONLY, 0)) == -1) {
1000 		mde_perror(ep, "Error in opening meddb file");
1001 		return (1);
1002 	}
1003 
1004 	/* Initialize rec_size */
1005 	rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE);
1006 
1007 	/* Allocate a record buffer */
1008 	if ((rec_buf = malloc(rec_size)) == NULL) {
1009 		mde_perror(ep, "Error in allocating memory");
1010 		goto out;
1011 	}
1012 
1013 	/* read the file header */
1014 	if ((read(fd, rec_buf, rec_size)) != rec_size) {
1015 		mde_perror(ep, "Error in reading mediator record");
1016 		goto out;
1017 	}
1018 
1019 	dbhbr = (med_db_hdr_t *)rec_buf;
1020 
1021 	/* Number of records in the mediator file */
1022 	c = dbhbr->med_dbh_nm;
1023 
1024 	for (i = 0; i < c; i++) {
1025 		(void) memset(rec_buf, 0, rec_size);
1026 
1027 		if (read(fd, rec_buf, rec_size) == -1) {
1028 			mde_perror(ep, "Error in reading mediator record");
1029 			goto out;
1030 		}
1031 
1032 		medrecp = (med_rec_t *)rec_buf;
1033 
1034 		/*
1035 		 * For oban diskset first entry in the rec_nodes field is
1036 		 * "multiowner" and all other entries are null
1037 		 * Check if this is really multiowner diskset.
1038 		 */
1039 
1040 		if ((strcmp(medrecp->med_rec_nodes[0], MED_MN_CALLER) == 0) &&
1041 		    (medrecp->med_rec_nodes[1] == NULL))
1042 			obandiskset = TRUE;
1043 		else
1044 			obandiskset = FALSE;
1045 
1046 		if (sname != NULL) {
1047 			/*
1048 			 * Continue if the set name is not in our interest.
1049 			 * This is required when this routine is called
1050 			 * from medstat
1051 			 */
1052 
1053 			if (strcmp(sname, medrecp->med_rec_snm) != 0) {
1054 				continue;
1055 			}
1056 
1057 			if (verbose)
1058 				(void) printf("%8.8s\t\t%6.6s\t%6.6s\n",
1059 				    gettext("Mediator"), gettext("Status"),
1060 				    gettext("Golden"));
1061 
1062 			if (medrecp->med_rec_meds.n_cnt == 0) {
1063 				if (verbose)
1064 					(void) printf(gettext(
1065 					    "No mediator hosts configured for"
1066 					    " set \"%s\".\n"),
1067 					    sname);
1068 				goto out;
1069 			}
1070 			setname = sname;
1071 		} else {
1072 			setname = medrecp->med_rec_snm;
1073 		}
1074 		setnum = medrecp->med_rec_sn;
1075 
1076 		for (j = 0; j < medrecp->med_rec_meds.n_cnt; j ++) {
1077 			(void) memset(&medd, 0, sizeof (medd));
1078 			(void) memset(&mdh, 0, sizeof (mdh));
1079 			mdh = medrecp->med_rec_meds.n_lst[j];
1080 
1081 			if ((sname != NULL) && (verbose))
1082 				(void) printf("%-17.17s\t",
1083 					medrecp->med_rec_meds.n_lst[j].a_nm[0]);
1084 
1085 			if (clnt_user_med_get_data(&mdh, obandiskset,
1086 			    setname, setnum, &medd, ep) == -1) {
1087 				if (sname == NULL) {
1088 					continue;
1089 				} else {
1090 					if (mdanyrpcerror(ep)) {
1091 						if (verbose)
1092 							(void) printf("%s\n",
1093 							    gettext("Unreach"
1094 							    "able"));
1095 						continue;
1096 					} else if (mdiserror(ep,
1097 						MDE_MED_ERROR)) {
1098 						if (verbose)
1099 							(void) printf("%s\n",
1100 							    gettext("Bad"));
1101 					} else {
1102 						if (verbose)
1103 							(void) printf("%s\n",
1104 							    gettext("Fatal"));
1105 					}
1106 					mde_perror(ep, "");
1107 					if (mdiserror(ep, MDE_MED_ERROR))
1108 						continue;
1109 					goto out;
1110 				}
1111 			} else {
1112 				if (sname == NULL) {
1113 					if (latest_med_dat_cc <
1114 					    medd.med_dat_cc) {
1115 						latest_med_dat_cc =
1116 						    medd.med_dat_cc;
1117 						save_medd = &medd;
1118 					}
1119 				} else {
1120 					if (verbose)
1121 						(void) printf("%s",
1122 						    gettext("Ok"));
1123 					if (medd.med_dat_fl & MED_DFL_GOLDEN) {
1124 						if (verbose)
1125 							(void) printf("\t%s",
1126 							    gettext("Yes"));
1127 						golden++;
1128 					} else {
1129 						if (verbose)
1130 							(void) printf("\t%s",
1131 							    gettext("No"));
1132 					}
1133 					if (verbose)
1134 						(void) printf("\n");
1135 						medok++;
1136 				}
1137 			}
1138 		}
1139 		if (sname == NULL) {
1140 			/*
1141 			 * Update the latest mediator information
1142 			 * on this node
1143 			 */
1144 			(void) strlcpy(mdh.a_nm[0], mynode(),
1145 			    sizeof (mdh.a_nm[0]));
1146 			if (clnt_user_med_upd_data(&mdh, obandiskset,
1147 			    setname, setnum, save_medd, ep) == -1) {
1148 				/*
1149 				 * We had some errors while updaing the
1150 				 * record. This means this metaset is
1151 				 * not updated with latest mediator
1152 				 * information.
1153 				 */
1154 				mde_perror(ep, "");
1155 				continue;
1156 			}
1157 		} else {
1158 			if (golden) {
1159 				retval = 0;
1160 				goto out;
1161 			}
1162 			if (medok < ((medrecp->med_rec_meds.n_cnt / 2) + 1))
1163 				retval = 1;
1164 		}
1165 	}
1166 
1167 out:
1168 	if (rec_buf != NULL)
1169 		Free(rec_buf);
1170 	if (close(fd) < 0) {
1171 		mde_perror(ep, "Error in closing meddb file");
1172 		return (1);
1173 	}
1174 	return (retval);
1175 }
1176