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