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