Home | History | Annotate | Download | only in common
      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 2009 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 	int		isSetFound = 0;
    995 
    996 	/* Open the meddb file */
    997 	if ((fd = open(MED_DB_FILE, O_RDONLY, 0)) == -1) {
    998 
    999 		/*
   1000 		 * During the start up of the SVM services, this function
   1001 		 * will be called with an empty sname. In that case it is
   1002 		 * entirely possible for the MED_DB_FILE not to exist.
   1003 		 * If so, then no need to report an error.
   1004 		 */
   1005 		if (sname != NULL) {
   1006 			(void) mdsyserror(ep, errno, MED_DB_FILE);
   1007 			mde_perror(ep, dgettext(TEXT_DOMAIN,
   1008 			    "Error in opening meddb file"));
   1009 			return (1);
   1010 		}
   1011 		return (0);
   1012 	}
   1013 
   1014 	/* Initialize rec_size */
   1015 	rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE);
   1016 
   1017 	/* Allocate a record buffer */
   1018 	if ((rec_buf = malloc(rec_size)) == NULL) {
   1019 		(void) mdsyserror(ep, errno, MED_DB_FILE);
   1020 		mde_perror(ep, dgettext(TEXT_DOMAIN,
   1021 		    "Error in allocating memory"));
   1022 		goto out;
   1023 	}
   1024 
   1025 	/* read the file header */
   1026 	if ((read(fd, rec_buf, rec_size)) != rec_size) {
   1027 		(void) mdsyserror(ep, EINVAL, MED_DB_FILE);
   1028 		mde_perror(ep, dgettext(TEXT_DOMAIN,
   1029 		    "Error in reading mediator record"));
   1030 		goto out;
   1031 	}
   1032 
   1033 	dbhbr = (med_db_hdr_t *)rec_buf;
   1034 
   1035 	/* Number of records in the mediator file */
   1036 	c = dbhbr->med_dbh_nm;
   1037 
   1038 	for (i = 0; i < c; i++) {
   1039 		(void) memset(rec_buf, 0, rec_size);
   1040 
   1041 		if (read(fd, rec_buf, rec_size) == -1) {
   1042 			(void) mdsyserror(ep, errno, MED_DB_FILE);
   1043 			mde_perror(ep, dgettext(TEXT_DOMAIN,
   1044 			    "Error in reading mediator record"));
   1045 			goto out;
   1046 		}
   1047 
   1048 		medrecp = (med_rec_t *)rec_buf;
   1049 
   1050 		/*
   1051 		 * For oban diskset first entry in the rec_nodes field is
   1052 		 * "multiowner" and all other entries are empty.
   1053 		 * Check if this is really multiowner diskset.
   1054 		 */
   1055 
   1056 		if ((strcmp(medrecp->med_rec_nodes[0], MED_MN_CALLER) == 0) &&
   1057 		    (medrecp->med_rec_nodes[1][0] == '\0'))
   1058 			obandiskset = TRUE;
   1059 		else
   1060 			obandiskset = FALSE;
   1061 
   1062 		if (sname != NULL) {
   1063 			/*
   1064 			 * Continue if the set name is not in our interest.
   1065 			 * This is required when this routine is called
   1066 			 * from medstat
   1067 			 */
   1068 
   1069 			if (strcmp(sname, medrecp->med_rec_snm) != 0) {
   1070 				continue;
   1071 			}
   1072 
   1073 			if (verbose)
   1074 				(void) printf("%8.8s\t\t%6.6s\t%6.6s\n",
   1075 				    gettext("Mediator"), gettext("Status"),
   1076 				    gettext("Golden"));
   1077 
   1078 			isSetFound = 1;
   1079 			setname = sname;
   1080 		} else {
   1081 			setname = medrecp->med_rec_snm;
   1082 		}
   1083 		setnum = medrecp->med_rec_sn;
   1084 		(void) memset(&medd, '\0', sizeof (medd));
   1085 		(void) memset(&mdh, '\0', sizeof (mdh));
   1086 		(void) memset(&save_medd, '\0', sizeof (save_medd));
   1087 		latest_med_dat_cc = 0;
   1088 
   1089 		for (j = 0; j < MED_MAX_HOSTS; j++) {
   1090 			/*
   1091 			 * It is possible for the n_lst[j] slot to be empty
   1092 			 * if the mediator node has already been removed so
   1093 			 * go to the next slot.
   1094 			 */
   1095 			if (medrecp->med_rec_meds.n_lst[j].a_cnt == 0)
   1096 				continue;
   1097 			mdh = medrecp->med_rec_meds.n_lst[j];
   1098 
   1099 			if ((sname != NULL) && (verbose))
   1100 				(void) printf("%-17.17s\t",
   1101 				    medrecp->med_rec_meds.n_lst[j].a_nm[0]);
   1102 
   1103 			if (clnt_user_med_get_data(&mdh, obandiskset,
   1104 			    setname, setnum, &medd, ep) == -1) {
   1105 				if (sname == NULL) {
   1106 					continue;
   1107 				} else {
   1108 					if (mdanyrpcerror(ep)) {
   1109 						if (verbose)
   1110 							(void) printf("%s\n",
   1111 							    gettext("Unreach"
   1112 							    "able"));
   1113 						continue;
   1114 					} else if (mdiserror(ep,
   1115 					    MDE_MED_ERROR)) {
   1116 						if (verbose)
   1117 							(void) printf("%s\n",
   1118 							    gettext("Bad"));
   1119 					} else {
   1120 						if (verbose)
   1121 							(void) printf("%s\n",
   1122 							    gettext("Fatal"));
   1123 					}
   1124 					mde_perror(ep, "");
   1125 					if (mdiserror(ep, MDE_MED_ERROR))
   1126 						continue;
   1127 					goto out;
   1128 				}
   1129 			} else {
   1130 				/*
   1131 				 * Make sure this node has the correct value
   1132 				 * for the mediator record. If not we want the
   1133 				 * highest value from the other nodes. Save it
   1134 				 * for updating once the loop through all the
   1135 				 * mediator nodes has completed.
   1136 				 */
   1137 				if (sname == NULL) {
   1138 					if (latest_med_dat_cc <
   1139 					    medd.med_dat_cc) {
   1140 						latest_med_dat_cc =
   1141 						    medd.med_dat_cc;
   1142 						(void) memcpy(&save_medd, &medd,
   1143 						    sizeof (medd));
   1144 					}
   1145 				} else {
   1146 					if (verbose)
   1147 						(void) printf("%s",
   1148 						    gettext("Ok"));
   1149 					if (medd.med_dat_fl & MED_DFL_GOLDEN) {
   1150 						if (verbose)
   1151 							(void) printf("\t%s",
   1152 							    gettext("Yes"));
   1153 						golden++;
   1154 					} else {
   1155 						if (verbose)
   1156 							(void) printf("\t%s",
   1157 							    gettext("No"));
   1158 					}
   1159 					if (verbose)
   1160 						(void) printf("\n");
   1161 						medok++;
   1162 				}
   1163 			}
   1164 		}
   1165 		if (sname == NULL) {
   1166 
   1167 			/*
   1168 			 * Mediators only become active when there are
   1169 			 * replica updates to the sets and this can only
   1170 			 * occur when there is a disk in the set.
   1171 			 * If there are no disks found then the save_medd
   1172 			 * structure will be empty. If save_medd is empty,
   1173 			 * do not update the set.
   1174 			 */
   1175 			if (save_medd.med_dat_sn == 0)
   1176 				continue;
   1177 			/*
   1178 			 * Update the latest mediator information
   1179 			 * on this node
   1180 			 */
   1181 			(void) strlcpy(mdh.a_nm[0], mynode(),
   1182 			    sizeof (mdh.a_nm[0]));
   1183 			mdh.a_cnt = 1;
   1184 			if (clnt_user_med_upd_data(&mdh, obandiskset,
   1185 			    setname, setnum, &save_medd, ep) == -1) {
   1186 				/*
   1187 				 * We had some errors while updaing the
   1188 				 * record. This means this metaset is
   1189 				 * not updated with latest mediator
   1190 				 * information.
   1191 				 */
   1192 				mde_perror(ep, "");
   1193 			}
   1194 
   1195 		} else {
   1196 			if (golden) {
   1197 				retval = 0;
   1198 				goto out;
   1199 			}
   1200 			if (medok < ((medrecp->med_rec_meds.n_cnt / 2) + 1))
   1201 				retval = 1;
   1202 		}
   1203 	}
   1204 
   1205 out:
   1206 	if ((sname != NULL) && (isSetFound == 0)) {
   1207 		(void) mderror(ep, MDE_NO_SET, sname);
   1208 		mde_perror(ep, "");
   1209 		retval = 1;
   1210 	}
   1211 	if (rec_buf != NULL)
   1212 		Free(rec_buf);
   1213 	if (close(fd) < 0) {
   1214 		(void) mdsyserror(ep, errno, MED_DB_FILE);
   1215 		mde_perror(ep, dgettext(TEXT_DOMAIN,
   1216 		    "Error in closing meddb file"));
   1217 		return (1);
   1218 	}
   1219 	return (retval);
   1220 }
   1221