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