7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / lib / lvm / libmeta / common / meta_med.c
blob1d09f755064f6433551463877e53a72b2cc35644
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Just in case we're not in a build environment, make sure that
29 * TEXT_DOMAIN gets set to something.
31 #if !defined(TEXT_DOMAIN)
32 #define TEXT_DOMAIN "SYS_TEST"
33 #endif
36 * Mediator functions
39 #include <meta.h>
40 #include <metamed.h>
41 #include <dlfcn.h>
42 #include <sdssc.h>
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.
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 */
55 static md_timeval32_t def_rpcb_timeout = { MD_CLNT_CREATE_TOUT, 0 };
58 * RPC handle
60 typedef struct {
61 char *hostname;
62 CLIENT *clntp;
63 } med_handle_t;
66 * Data to be sent from med_clnt_create_timed to med_create_helper via
67 * meta_client_create_retry.
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;
76 * Perform the work of actually doing the clnt_create for
77 * meta_client_create_retry.
79 static CLIENT *
80 med_create_helper(char *hostname, void *private, struct timeval *time_out)
82 med_create_data_t *cd = (med_create_data_t *)private;
84 return (clnt_create_timed(hostname, cd->mcd_program, cd->mcd_version,
85 cd->mcd_nettype, time_out));
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
97 med_create_data_t cd; /* Create data. */
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));
107 * Set the timeout value for this client handle.
109 static int
110 cl_sto_medd(
111 CLIENT *clntp,
112 char *hostname,
113 long time_out,
114 md_error_t *ep
117 md_timeval32_t nto;
119 (void) memset(&nto, '\0', sizeof (nto));
121 nto.tv_sec = time_out;
123 if (clnt_control(clntp, CLSET_TIMEOUT, (char *)&nto) != TRUE)
124 return (mdrpcerror(ep, clntp, hostname,
125 dgettext(TEXT_DOMAIN, "metad client set timeout")));
127 return (0);
131 * close RPC connection
133 static void
134 close_medd(
135 med_handle_t *hp
138 assert(hp != NULL);
139 if (hp->hostname != NULL) {
140 Free(hp->hostname);
142 if (hp->clntp != NULL) {
143 auth_destroy(hp->clntp->cl_auth);
144 clnt_destroy(hp->clntp);
146 Free(hp);
150 * open RPC connection to rpc.medd
152 static med_handle_t *
153 open_medd(
154 char *hostname,
155 long time_out,
156 md_error_t *ep
159 CLIENT *clntp;
160 med_handle_t *hp;
162 /* default to local host */
163 if ((hostname == NULL) || (*hostname == '\0'))
164 hostname = mynode();
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);
181 if (cl_sto_medd(clntp, hostname, time_out, ep) != 0)
182 return (NULL);
184 /* return connection */
185 hp = Zalloc(sizeof (*hp));
186 hp->hostname = Strdup(hostname);
187 hp->clntp = clntp;
189 return (hp);
193 * steal and convert med_err_t
196 meddstealerror(
197 md_error_t *ep,
198 med_err_t *medep
201 char buf[BUFSIZ];
202 char *p = buf;
203 size_t psize = BUFSIZ;
204 char *emsg;
205 int rval = -1;
207 /* no error */
208 if (medep->med_errno == 0) {
209 /* assert(medep->name == NULL); */
210 rval = 0;
211 goto out;
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;
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;
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);
240 (void) mderror(ep, MDE_MED_ERROR, buf);
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);
252 static med_handle_t *
253 open_medd_wrap(
254 md_h_t *mdhp,
255 long time_out,
256 md_error_t *ep
259 med_handle_t *hp = NULL;
260 int i;
261 char *hnm;
263 assert(mdhp && mdhp->a_cnt > 0);
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];
270 if ((hp = open_medd(hnm, time_out, ep)) == NULL) {
271 if (mdanyrpcerror(ep) && i != 0) {
272 mdclrerror(ep);
273 continue;
276 return (hp);
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"));
284 return (NULL);
287 static int
288 setup_med_transtab(md_error_t *ep)
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;
297 if ((tp = Zalloc(sizeof (mddb_med_t_parm_t))) == NULL)
298 return (mdsyserror(ep, ENOMEM, "setup_med_transtab"));
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;
305 if (tp->med_tp_setup == 1)
306 goto out;
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);
311 if ((tp = Realloc(tp, alloc_size)) == NULL) {
312 err = mdsyserror(ep, ENOMEM, "setup_med_transtab");
313 goto out;
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;
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);
331 if (metaioctl(MD_MED_SET_T, tp, &tp->med_tp_mde, NULL) != 0)
332 err = mdstealerror(ep, &tp->med_tp_mde);
334 out:
335 Free(tp);
336 return (err);
340 * Externals
344 * NULLPROC - just returns a response
347 clnt_med_null(
348 char *hostname,
349 md_error_t *ep
352 med_handle_t *hp;
353 med_err_t res;
355 /* initialize */
356 mdclrerror(ep);
358 /* do it */
359 if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
360 return (-1);
362 if (med_null_1(NULL, &res, hp->clntp) != RPC_SUCCESS)
363 (void) mdrpcerror(ep, hp->clntp, hostname,
364 dgettext(TEXT_DOMAIN, "medd nullproc"));
366 close_medd(hp);
368 xdr_free(xdr_med_err_t, (char *)&res);
370 if (! mdisok(ep))
371 return (-1);
373 return (0);
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.
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
393 med_handle_t *hp;
394 med_upd_data_args_t args;
395 med_err_t res;
397 /* Initialize */
398 mdclrerror(ep);
399 (void) memset(&args, 0, sizeof (args));
400 (void) memset(&res, 0, sizeof (res));
402 /* Build args */
403 if (obandiskset)
404 args.med.med_caller = Strdup(MED_MN_CALLER);
405 else
406 args.med.med_caller = Strdup(mynode());
408 args.med.med_setname = Strdup(setname);
409 args.med.med_setno = setnum;
410 args.med_data = *meddp;
412 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
413 return (-1);
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);
421 close_medd(hp);
423 xdr_free(xdr_med_upd_data_args_t, (char *)&args);
424 xdr_free(xdr_med_err_t, (char *)&res);
426 if (! mdisok(ep))
427 return (-1);
429 return (0);
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
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
449 int rval = -1;
450 med_handle_t *hp;
451 med_args_t args;
452 med_get_data_res_t res;
454 /* Initialize */
455 mdclrerror(ep);
456 (void) memset(&args, 0, sizeof (args));
457 (void) memset(&res, 0, sizeof (res));
459 /* Build args */
460 if (obandiskset)
461 args.med.med_caller = Strdup(MED_MN_CALLER);
462 else
463 args.med.med_caller = Strdup(mynode());
465 args.med.med_setname = Strdup(setname);
466 args.med.med_setno = setnum;
468 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
469 return (-1);
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);
477 close_medd(hp);
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;
485 xdr_free(xdr_med_args_t, (char *)&args);
486 xdr_free(xdr_med_get_data_res_t, (char *)&res);
488 return (rval);
493 * Update the mediator information on the mediator.
494 * *** This is not normally called from user code, the kernel does this! ***
497 clnt_med_upd_data(
498 md_h_t *mdhp,
499 mdsetname_t *sp,
500 med_data_t *meddp,
501 md_error_t *ep
504 med_handle_t *hp;
505 med_upd_data_args_t args;
506 med_err_t res;
507 md_set_desc *sd;
509 /* initialize */
510 mdclrerror(ep);
511 (void) memset(&args, 0, sizeof (args));
512 (void) memset(&res, 0, sizeof (res));
514 /* build args */
515 if ((sd = metaget_setdesc(sp, ep)) == NULL)
516 return (-1);
518 if (MD_MNSET_DESC(sd))
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.
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.
529 * In the traditional diskset, only a calling node that is
530 * in the mediator record's diskset nodelist can access
531 * mediator data.
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;
540 /* do it */
541 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
542 return (-1);
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);
550 close_medd(hp);
552 xdr_free(xdr_med_upd_data_args_t, (char *)&args);
553 xdr_free(xdr_med_err_t, (char *)&res);
555 if (! mdisok(ep))
556 return (-1);
558 return (0);
562 * Get the mediator data for this client from the mediator
565 clnt_med_get_data(
566 md_h_t *mdhp,
567 mdsetname_t *sp,
568 med_data_t *meddp,
569 md_error_t *ep
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;
578 /* initialize */
579 mdclrerror(ep);
580 (void) memset(&args, 0, sizeof (args));
581 (void) memset(&res, 0, sizeof (res));
583 /* build args */
584 if ((sd = metaget_setdesc(sp, ep)) == NULL)
585 return (-1);
587 if (MD_MNSET_DESC(sd))
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.
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.
598 * In the traditional diskset, only a calling node that is
599 * in the mediator record's diskset nodelist can access
600 * mediator data.
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;
608 /* do it */
609 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
610 return (-1);
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);
618 close_medd(hp);
620 if (mdisok(ep)) {
621 /* do something with the results */
622 (void) memmove(meddp, &res.med_data, sizeof (med_data_t));
623 rval = 0;
626 xdr_free(xdr_med_args_t, (char *)&args);
627 xdr_free(xdr_med_get_data_res_t, (char *)&res);
629 return (rval);
633 * Update the mediator record on the mediator.
636 clnt_med_upd_rec(
637 md_h_t *mdhp,
638 mdsetname_t *sp,
639 med_rec_t *medrp,
640 md_error_t *ep
643 med_handle_t *hp;
644 med_upd_rec_args_t args;
645 med_err_t res;
646 md_set_desc *sd;
648 /* initialize */
649 mdclrerror(ep);
650 (void) memset(&args, 0, sizeof (args));
651 (void) memset(&res, 0, sizeof (res));
653 /* build args */
654 if ((sd = metaget_setdesc(sp, ep)) == NULL)
655 return (-1);
657 if (MD_MNSET_DESC(sd))
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.
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.
668 * In the traditional diskset, only a calling node that is
669 * in the mediator record's diskset nodelist can access
670 * mediator data.
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 */
680 /* do it */
681 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
682 return (-1);
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);
690 close_medd(hp);
692 xdr_free(xdr_med_upd_rec_args_t, (char *)&args);
693 xdr_free(xdr_med_err_t, (char *)&res);
695 if (! mdisok(ep))
696 return (-1);
698 return (0);
702 * Get the mediator record for this client from the mediator
705 clnt_med_get_rec(
706 md_h_t *mdhp,
707 mdsetname_t *sp,
708 med_rec_t *medrp,
709 md_error_t *ep
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;
718 /* initialize */
719 mdclrerror(ep);
720 (void) memset(&args, 0, sizeof (args));
721 (void) memset(&res, 0, sizeof (res));
723 /* build args */
724 if ((sd = metaget_setdesc(sp, ep)) == NULL)
725 return (-1);
727 if (MD_MNSET_DESC(sd))
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.
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.
738 * In the traditional diskset, only a calling node that is
739 * in the mediator record's diskset nodelist can access
740 * mediator data.
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;
748 /* do it */
749 if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
750 return (-1);
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);
758 close_medd(hp);
760 if (mdisok(ep)) {
761 /* do something with the results */
762 (void) memmove(medrp, &res.med_rec, sizeof (med_rec_t));
763 rval = 0;
766 xdr_free(xdr_med_args_t, (char *)&args);
767 xdr_free(xdr_med_get_rec_res_t, (char *)&res);
769 return (rval);
773 * Get the name of the host from the mediator daemon.
776 clnt_med_hostname(
777 char *hostname,
778 char **ret_hostname,
779 md_error_t *ep
782 med_handle_t *hp;
783 med_hnm_res_t res;
784 int rval = -1;
786 /* initialize */
787 mdclrerror(ep);
788 (void) memset(&res, 0, sizeof (res));
790 /* No args */
792 /* do it */
793 if ((hp = open_medd(hostname, CL_DEF_TMO, ep)) == NULL)
794 return (-1);
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);
802 close_medd(hp);
804 if (mdisok(ep)) {
805 /* do something with the results */
806 rval = 0;
808 if (ret_hostname != NULL)
809 *ret_hostname = Strdup(res.med_hnm);
812 xdr_free(xdr_med_hnm_res_t, (char *)&res);
814 return (rval);
818 meta_med_hnm2ip(md_hi_arr_t *mp, md_error_t *ep)
820 int i, j;
821 int max_meds;
823 if ((max_meds = get_max_meds(ep)) == 0)
824 return (-1);
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;
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];
838 * Cluster nodename support
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.
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));
851 /* We only do INET addresses */
852 if (hp->h_addrtype != AF_INET)
853 return (mdsyserror(ep, EPFNOSUPPORT,
854 hnm));
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));
868 return (0);
872 meta_h2hi(md_h_arr_t *mdhp, md_hi_arr_t *mdhip, md_error_t *ep)
874 int i, j;
875 int max_meds;
877 if ((max_meds = get_max_meds(ep)) == 0)
878 return (-1);
880 mdhip->n_cnt = mdhp->n_cnt;
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]);
891 return (0);
895 meta_hi2h(md_hi_arr_t *mdhip, md_h_arr_t *mdhp, md_error_t *ep)
897 int i, j;
898 int max_meds;
900 if ((max_meds = get_max_meds(ep)) == 0)
901 return (-1);
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]);
912 return (0);
916 setup_med_cfg(
917 mdsetname_t *sp,
918 mddb_config_t *cp,
919 int force,
920 md_error_t *ep
923 md_set_desc *sd;
924 int i;
925 int max_meds;
927 if (metaislocalset(sp))
928 return (0);
930 if ((sd = metaget_setdesc(sp, ep)) == NULL)
931 return (-1);
933 if (setup_med_transtab(ep))
934 return (-1);
936 if (meta_h2hi(&sd->sd_med, &cp->c_med, ep))
937 return (-1);
939 /* Make sure the ip addresses are current */
940 if (meta_med_hnm2ip(&cp->c_med, ep))
941 return (-1);
943 if (force)
944 return (0);
946 if ((max_meds = get_max_meds(ep)) == 0)
947 return (-1);
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;
954 if (sd->sd_med.n_lst[i].a_cnt == 0)
955 continue;
957 hnm = sd->sd_med.n_lst[i].a_nm[0];
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);
964 return (0);
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.
974 meta_mediator_info_from_file(char *sname, int verbose, md_error_t *ep)
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;
996 /* Open the meddb file */
997 if ((fd = open(MED_DB_FILE, O_RDONLY, 0)) == -1) {
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.
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);
1011 return (0);
1014 /* Initialize rec_size */
1015 rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE);
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;
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;
1033 dbhbr = (med_db_hdr_t *)rec_buf;
1035 /* Number of records in the mediator file */
1036 c = dbhbr->med_dbh_nm;
1038 for (i = 0; i < c; i++) {
1039 (void) memset(rec_buf, 0, rec_size);
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;
1048 medrecp = (med_rec_t *)rec_buf;
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.
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;
1062 if (sname != NULL) {
1064 * Continue if the set name is not in our interest.
1065 * This is required when this routine is called
1066 * from medstat
1069 if (strcmp(sname, medrecp->med_rec_snm) != 0) {
1070 continue;
1073 if (verbose)
1074 (void) printf("%8.8s\t\t%6.6s\t%6.6s\n",
1075 gettext("Mediator"), gettext("Status"),
1076 gettext("Golden"));
1078 isSetFound = 1;
1079 setname = sname;
1080 } else {
1081 setname = medrecp->med_rec_snm;
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;
1089 for (j = 0; j < MED_MAX_HOSTS; j++) {
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.
1095 if (medrecp->med_rec_meds.n_lst[j].a_cnt == 0)
1096 continue;
1097 mdh = medrecp->med_rec_meds.n_lst[j];
1099 if ((sname != NULL) && (verbose))
1100 (void) printf("%-17.17s\t",
1101 medrecp->med_rec_meds.n_lst[j].a_nm[0]);
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"));
1124 mde_perror(ep, "");
1125 if (mdiserror(ep, MDE_MED_ERROR))
1126 continue;
1127 goto out;
1129 } else {
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.
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));
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"));
1159 if (verbose)
1160 (void) printf("\n");
1161 medok++;
1165 if (sname == NULL) {
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.
1175 if (save_medd.med_dat_sn == 0)
1176 continue;
1178 * Update the latest mediator information
1179 * on this node
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) {
1187 * We had some errors while updaing the
1188 * record. This means this metaset is
1189 * not updated with latest mediator
1190 * information.
1192 mde_perror(ep, "");
1195 } else {
1196 if (golden) {
1197 retval = 0;
1198 goto out;
1200 if (medok < ((medrecp->med_rec_meds.n_cnt / 2) + 1))
1201 retval = 1;
1205 out:
1206 if ((sname != NULL) && (isSetFound == 0)) {
1207 (void) mderror(ep, MDE_NO_SET, sname);
1208 mde_perror(ep, "");
1209 retval = 1;
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);
1219 return (retval);