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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/param.h> 27 #include <sys/systm.h> 28 #include <sys/sysmacros.h> 29 #include <sys/errno.h> 30 #include <sys/cmn_err.h> 31 #include <sys/buf.h> 32 #include <sys/disp.h> 33 #include <sys/kmem.h> 34 /* #include <sys/ddi.h> */ 35 /* #include <sys/sunddi.h> */ 36 #include <sys/debug.h> 37 38 #include <sys/time.h> 39 #include <sys/pathname.h> 40 #include <sys/netconfig.h> 41 #include <sys/socket.h> 42 #include <netinet/in.h> 43 44 #include <rpc/types.h> 45 #include <rpc/auth.h> 46 #include <rpc/clnt.h> 47 #include <rpc/clnt_soc.h> 48 #include <rpc/pmap_prot.h> /* PMAPPORT */ 49 #include <rpc/rpc.h> 50 #include <rpc/rpcb_prot.h> 51 #include <rpc/xdr.h> /* This also gets us htonl() et al. */ 52 53 54 #include <sys/lvm/mdmed.h> 55 56 #define MDDB 57 #include <sys/lvm/mdvar.h> 58 #include <sys/lvm/md_mddb.h> 59 #include <sys/lvm/md_crc.h> 60 #include <sys/callb.h> 61 62 /* 63 * Flag to turn off the kernel RPC client delay code. This only takes effect 64 * if the route to the remote node is marked as RTF_REJECT and the RPC path 65 * manager has been flushed such that any 'old' path information is no longer 66 * present. 67 */ 68 static bool_t clset = TRUE; 69 70 extern int md_nmedh; /* declared in md.c */ 71 extern char *md_med_trans_lst; 72 extern md_set_t md_set[]; /* declared in md.c */ 73 74 /* 75 * Structures used only by mediators 76 */ 77 typedef struct med_thr_a_args { 78 uint_t mtaa_mag; 79 char *mtaa_h_nm; 80 in_addr_t mtaa_h_ip; 81 uint_t mtaa_h_flags; 82 int (*mtaa_err_func)(struct med_thr_a_args *); 83 struct med_thr_h_args *mtaa_mthap; 84 int mtaa_flags; 85 rpcprog_t mtaa_prog; 86 rpcvers_t mtaa_vers; 87 rpcproc_t mtaa_proc; 88 xdrproc_t mtaa_inproc; 89 caddr_t mtaa_in; 90 xdrproc_t mtaa_outproc; 91 caddr_t mtaa_out; 92 struct timeval *mtaa_timout; 93 int mtaa_err; 94 } med_thr_a_args_t; 95 96 #define MTAA_MAGIC 0xbadbabed 97 #define MDT_A_OK 0x00000001 98 99 typedef struct med_thr_h_args { 100 uint_t mtha_mag; 101 md_hi_t *mtha_mhp; 102 char *mtha_setname; 103 med_data_t *mtha_meddp; 104 struct med_thr *mtha_mtp; 105 int mtha_flags; 106 set_t mtha_setno; 107 int mtha_a_cnt; 108 kcondvar_t mtha_a_cv; 109 kmutex_t mtha_a_mx; 110 uint_t mtha_a_nthr; 111 med_thr_a_args_t mtha_a_args[MAX_HOST_ADDRS]; 112 } med_thr_h_args_t; 113 114 #define MTHA_MAGIC 0xbadbabee 115 #define MDT_H_OK 0x00000001 116 117 typedef struct med_thr { 118 uint_t mt_mag; 119 kmutex_t mt_mx; 120 kcondvar_t mt_cv; 121 uint_t mt_nthr; 122 med_thr_h_args_t *mt_h_args[MED_MAX_HOSTS]; 123 } med_thr_t; 124 125 #define MTH_MAGIC 0xbadbabef 126 127 #ifdef DEBUG 128 129 static struct timeval btv; 130 static struct timeval etv; 131 132 #define DBGLVL_NONE 0x00000000 133 #define DBGLVL_MAJOR 0x00000100 134 #define DBGLVL_MINOR 0x00000200 135 #define DBGLVL_MINUTE 0x00000400 136 #define DBGLVL_TRIVIA 0x00000800 137 #define DBGLVL_HIDEOUS 0x00001000 138 139 #define DBGFLG_NONE 0x00000000 140 #define DBGFLG_NOPANIC 0x00000001 141 #define DBGFLG_LVLONLY 0x00000002 142 #define DBGFLG_FIXWOULDPANIC 0x00000004 143 144 #define DBGFLG_FLAGMASK 0x0000000F 145 #define DBGFLG_LEVELMASK ~DBGFLG_FLAGMASK 146 147 #define DEBUG_FLAGS (md_medup_failure_dbg & DBGFLG_FLAGMASK) 148 #define DEBUG_LEVEL (md_medup_failure_dbg & DBGFLG_LEVELMASK) 149 150 #ifdef JEC 151 unsigned int md_medup_failure_dbg = DBGLVL_MINOR | DBGFLG_NONE; 152 #else /* ! JEC */ 153 unsigned int md_medup_failure_dbg = DBGLVL_NONE | DBGFLG_NONE; 154 #endif /* JEC */ 155 156 #define DCALL(dbg_level, call) \ 157 { \ 158 if (DEBUG_LEVEL != DBGLVL_NONE) { \ 159 if (DEBUG_FLAGS & DBGFLG_LVLONLY) { \ 160 if (DEBUG_LEVEL & dbg_level) { \ 161 call; \ 162 } \ 163 } else { \ 164 if (dbg_level <= DEBUG_LEVEL) { \ 165 call; \ 166 } \ 167 } \ 168 } \ 169 } 170 171 #define DPRINTF(dbg_level, msg) DCALL(dbg_level, printf msg) 172 173 #define MAJOR(msg) DPRINTF(DBGLVL_MAJOR, msg) 174 #define MINOR(msg) DPRINTF(DBGLVL_MINOR, msg) 175 #define MINUTE(msg) DPRINTF(DBGLVL_MINUTE, msg) 176 #define TRIVIA(msg) DPRINTF(DBGLVL_TRIVIA, msg) 177 #define HIDEOUS(msg) DPRINTF(DBGLVL_HIDEOUS, msg) 178 #define BSTAMP { uniqtime(&btv); } 179 180 #define ESTAMP(msg) \ 181 { \ 182 time_t esec, eusec; \ 183 \ 184 uniqtime(&etv); \ 185 \ 186 eusec = etv.tv_usec - btv.tv_usec; \ 187 esec = etv.tv_sec - btv.tv_sec; \ 188 if (eusec < 0) { \ 189 eusec += MICROSEC; \ 190 esec--; \ 191 } \ 192 MINOR(("%s: sec=%ld, usec=%ld\n", msg, esec, eusec)); \ 193 } 194 195 #else /* ! DEBUG */ 196 197 #define DCALL(ignored_dbg_level, ignored_routine) 198 #define MAJOR(ignored) 199 #define MINOR(ignored) 200 #define MINUTE(ignored) 201 #define TRIVIA(ignored) 202 #define HIDEOUS(ignored) 203 #define BSTAMP { } 204 #define ESTAMP(msg) { } 205 206 #endif /* DEBUG */ 207 208 static int md_med_protocol_retry = 2; 209 static int md_med_transdevs_set = 0; 210 211 /* 212 * Definitions and declarations. 213 */ 214 kmutex_t med_lck; 215 216 struct med_client { 217 rpcprog_t prog; 218 rpcvers_t vers; 219 struct netbuf addr; /* Address to this <prog,vers> */ 220 CLIENT *client; 221 }; 222 223 /* 224 * unrecoverable RPC status codes; cf. rfscall() 225 */ 226 #define MED_IS_UNRECOVERABLE_RPC(s) (((s) == RPC_AUTHERROR) || \ 227 ((s) == RPC_CANTENCODEARGS) || \ 228 ((s) == RPC_CANTDECODERES) || \ 229 ((s) == RPC_VERSMISMATCH) || \ 230 ((s) == RPC_PROCUNAVAIL) || \ 231 ((s) == RPC_PROGUNAVAIL) || \ 232 ((s) == RPC_PROGVERSMISMATCH) || \ 233 ((s) == RPC_CANTDECODEARGS)) 234 235 /* 236 * When trying to contact a portmapper that doesn't speak the version we're 237 * using, we should theoretically get back RPC_PROGVERSMISMATCH. 238 * Unfortunately, some (all?) 4.x hosts return an accept_stat of 239 * PROG_UNAVAIL, which gets mapped to RPC_PROGUNAVAIL, so we have to check 240 * for that, too. 241 */ 242 #define PMAP_WRONG_VERSION(s) ((s) == RPC_PROGVERSMISMATCH || \ 243 (s) == RPC_PROGUNAVAIL) 244 245 #define NULLSTR(str) (! (str) || *(str) == '\0'? "<null>" : (str)) 246 #define NULSTRING "" 247 248 /* Flags used in med_addr (netconfig) table */ 249 250 #define UAFLG_NONE 0x00000000 251 #define UAFLG_SKIP 0x00000001 252 #define UAFLG_ERROR 0x00000002 253 #define UAFLG_RPCERROR 0x00000004 254 #define UAFLG_LOOPBACK 0x00000008 255 #define UAFLG_LOCKINIT 0x00000010 256 257 /* 258 * most of this data is static. The mutex protects the changable items: 259 * ua_flags 260 */ 261 static struct med_addr { 262 struct knetconfig ua_kn; 263 char *ua_devname; /* const */ 264 char *ua_netid; /* const */ 265 uint_t ua_flags; 266 kmutex_t ua_mutex; 267 } med_addr_tab[] = 268 269 /* 270 * The order of the entries in this table is the order in 271 * which we'll try to connect to the user-level daemon. 272 * The final entry must have a NULL ua_devname. 273 * 274 * This is basically a tablified version of /etc/netconfig 275 * (with additional entries for loopback TCP and UDP networks 276 * that are missing from the user-level version.) 277 */ 278 { 279 280 /* loopback UDP */ 281 /* semantics protofmly proto, dev_t */ 282 { { NC_TPI_CLTS, NC_INET, NC_UDP, NODEV }, 283 /* devname netid flags */ 284 "/dev/udp", "udp-loopback", UAFLG_LOOPBACK 285 }, 286 287 /* UDP */ 288 /* semantics protofmly proto, dev_t */ 289 { { NC_TPI_CLTS, NC_INET, NC_UDP, NODEV }, 290 /* devname netid flags */ 291 "/dev/udp", "udp", UAFLG_NONE 292 }, 293 294 /* loopback TCP */ 295 /* semantics protofmly proto, dev_t */ 296 { { NC_TPI_COTS_ORD, NC_INET, NC_TCP, NODEV }, 297 /* devname netid flags */ 298 "/dev/tcp", "tcp-loopback", UAFLG_LOOPBACK 299 }, 300 301 /* TCP */ 302 /* semantics protofmly proto, dev_t */ 303 { { NC_TPI_COTS_ORD, NC_INET, NC_TCP, NODEV }, 304 /* devname netid flags */ 305 "/dev/tcp", "tcp", UAFLG_NONE 306 }, 307 308 /* ticlts */ 309 /* semantics protofmly proto, dev_t */ 310 { { NC_TPI_CLTS, NC_LOOPBACK, NC_NOPROTO, NODEV }, 311 /* devname netid flags */ 312 "/dev/ticlts", "ticlts", UAFLG_LOOPBACK 313 }, 314 315 /* ticotsord */ 316 /* semantics protofmly proto, dev_t */ 317 { { NC_TPI_COTS_ORD, NC_LOOPBACK, NC_NOPROTO, NODEV }, 318 /* devname netid flags */ 319 "/dev/ticotsord", "ticotsord", UAFLG_LOOPBACK 320 }, 321 322 /* ticots */ 323 /* semantics protofmly proto, dev_t */ 324 { { NC_TPI_COTS, NC_LOOPBACK, NC_NOPROTO, NODEV }, 325 /* devname netid flags */ 326 "/dev/ticots", "ticots", UAFLG_LOOPBACK 327 } 328 }; 329 330 /* The number of entries in the table */ 331 int med_addr_tab_nents = sizeof (med_addr_tab) / sizeof (med_addr_tab[0]); 332 333 /* 334 * Private Functions 335 */ 336 337 /* A useful utility. */ 338 static char * 339 med_dup(void *str, int len) 340 { 341 char *s = (char *)kmem_zalloc(len, KM_SLEEP); 342 343 if (s == NULL) 344 return (NULL); 345 346 bcopy(str, s, len); 347 348 return (s); 349 } 350 351 /* 352 * Utilities for manipulating netbuf's. 353 * These utilities are the only knc_protofmly specific functions in the MED. 354 */ 355 356 /* 357 * Utilities to patch a port number (for NC_INET protocols) or a 358 * port name (for NC_LOOPBACK) into a network address. 359 */ 360 static void 361 med_put_inet_port(struct netbuf *addr, ushort_t port) 362 { 363 /* 364 * Easy - we always patch an unsigned short on top of an 365 * unsigned short. No changes to addr's len or maxlen are 366 * necessary. 367 */ 368 /*LINTED*/ 369 ((struct sockaddr_in *)(addr->buf))->sin_port = port; 370 } 371 372 static void 373 med_put_loopback_port(struct netbuf *addr, char *port) 374 { 375 char *dot; 376 char *newbuf; 377 int newlen; 378 379 /* 380 * We must make sure the addr has enough space for us, 381 * patch in `port', and then adjust addr's len and maxlen 382 * to reflect the change. 383 */ 384 if ((dot = strchr(addr->buf, '.')) == (char *)NULL) { 385 TRIVIA(("put_loopb_port - malformed loopback addr %s\n", 386 addr->buf)); 387 return; 388 } 389 390 newlen = (int)((dot - addr->buf + 1) + strlen(port)); 391 if (newlen > addr->maxlen) { 392 newbuf = (char *)kmem_zalloc((size_t)newlen, KM_SLEEP); 393 (void) bcopy(addr->buf, newbuf, (size_t)addr->len); 394 kmem_free(addr->buf, (size_t)addr->maxlen); 395 addr->buf = newbuf; 396 addr->len = addr->maxlen = (uint_t)newlen; 397 dot = strchr(addr->buf, '.'); 398 } else { 399 addr->len = newlen; 400 } 401 402 (void) strncpy(++dot, port, strlen(port)); 403 404 } 405 406 /* 407 * Make sure the given netbuf has a maxlen at least as big as the given 408 * length. 409 */ 410 static void 411 grow_netbuf(struct netbuf *nb, size_t length) 412 { 413 char *newbuf; 414 415 if (nb->maxlen >= length) 416 return; 417 418 newbuf = kmem_zalloc(length, KM_SLEEP); 419 bcopy(nb->buf, newbuf, (size_t)nb->len); 420 kmem_free(nb->buf, (size_t)nb->maxlen); 421 nb->buf = newbuf; 422 nb->maxlen = (uint_t)length; 423 } 424 425 /* 426 * Convert a loopback universal address to a loopback transport address. 427 */ 428 static void 429 loopb_u2t(const char *ua, struct netbuf *addr) 430 { 431 size_t stringlen = strlen(ua) + 1; 432 const char *univp; /* ptr into universal addr */ 433 char *transp; /* ptr into transport addr */ 434 435 /* Make sure the netbuf will be big enough. */ 436 if (addr->maxlen < stringlen) { 437 grow_netbuf(addr, stringlen); 438 } 439 440 univp = ua; 441 transp = addr->buf; 442 while (*univp != NULL) { 443 if (*univp == '\\' && *(univp+1) == '\\') { 444 *transp = '\\'; 445 univp += 2; 446 } else if (*univp == '\\') { 447 /* octal character */ 448 *transp = (((*(univp+1) - '0') & 3) << 6) + 449 (((*(univp+2) - '0') & 7) << 3) + 450 ((*(univp+3) - '0') & 7); 451 univp += 4; 452 } else { 453 *transp = *univp; 454 univp++; 455 } 456 transp++; 457 } 458 459 addr->len = (uint_t)(transp - addr->buf); 460 ASSERT(addr->len <= addr->maxlen); 461 } 462 463 464 /* 465 * xdr_md_pmap 466 * 467 * Taken from libnsl/rpc/pmap_prot.c 468 */ 469 bool_t 470 xdr_md_pmap(xdrs, regs) 471 XDR *xdrs; 472 struct pmap *regs; 473 { 474 if (xdr_u_int(xdrs, ®s->pm_prog) && 475 xdr_u_int(xdrs, ®s->pm_vers) && 476 xdr_u_int(xdrs, ®s->pm_prot)) 477 return (xdr_u_int(xdrs, ®s->pm_port)); 478 return (FALSE); 479 } 480 481 /* 482 * We need an version of CLNT_DESTROY which also frees the auth structure. 483 */ 484 static void 485 med_clnt_destroy(CLIENT **clp) 486 { 487 if (*clp) { 488 if ((*clp)->cl_auth) { 489 AUTH_DESTROY((*clp)->cl_auth); 490 (*clp)->cl_auth = NULL; 491 } 492 CLNT_DESTROY(*clp); 493 *clp = NULL; 494 } 495 } 496 497 /* 498 * Release this med_client entry. 499 * Do also destroy the entry if there was an error != EINTR, 500 * and mark the entry as not-valid, by setting time=0. 501 */ 502 static void 503 med_rel_client(struct med_client *medc, int error) 504 { 505 TRIVIA(("rel_client - addr = (%p, %u %u)\n", 506 (void *) medc->addr.buf, medc->addr.len, medc->addr.maxlen)); 507 /*LINTED*/ 508 if (1 || error && error != EINTR) { 509 TRIVIA(("rel_client - destroying addr = (%p, %u %u)\n", 510 (void *) medc->addr.buf, medc->addr.len, 511 medc->addr.maxlen)); 512 med_clnt_destroy(&medc->client); 513 if (medc->addr.buf) { 514 kmem_free(medc->addr.buf, medc->addr.maxlen); 515 medc->addr.buf = NULL; 516 } 517 } 518 } 519 520 /* 521 * Try to get the address for the desired service by using the old 522 * portmapper protocol. Ignores signals. 523 * 524 * Returns RPC_UNKNOWNPROTO if the request uses the loopback transport. 525 * Use med_get_rpcb_addr instead. 526 */ 527 static enum clnt_stat 528 med_get_pmap_addr( 529 struct knetconfig *kncfp, 530 rpcprog_t prog, 531 rpcvers_t vers, 532 struct netbuf *addr 533 ) 534 { 535 ushort_t port = 0; 536 int error; 537 enum clnt_stat status; 538 CLIENT *client = NULL; 539 struct pmap parms; 540 struct timeval tmo; 541 k_sigset_t oldmask; 542 k_sigset_t newmask; 543 544 /* 545 * Call rpcbind version 2 or earlier (SunOS portmapper, remote 546 * only) to get an address we can use in an RPC client handle. 547 * We simply obtain a port no. for <prog, vers> and plug it 548 * into `addr'. 549 */ 550 if (strcmp(kncfp->knc_protofmly, NC_INET) == 0) { 551 med_put_inet_port(addr, htons(PMAPPORT)); 552 } else { 553 TRIVIA(("get_pmap_addr - unsupported protofmly %s\n", 554 kncfp->knc_protofmly)); 555 status = RPC_UNKNOWNPROTO; 556 goto out; 557 } 558 559 TRIVIA(("get_pmap_addr - semantics=%u, protofmly=%s, proto=%s\n", 560 kncfp->knc_semantics, kncfp->knc_protofmly, kncfp->knc_proto)); 561 562 /* 563 * Mask signals for the duration of the handle creation and 564 * RPC call. This allows relatively normal operation with a 565 * signal already posted to our thread. 566 * 567 * Any further exit paths from this routine must restore 568 * the original signal mask. 569 */ 570 sigfillset(&newmask); 571 sigreplace(&newmask, &oldmask); 572 573 if ((error = clnt_tli_kcreate(kncfp, addr, PMAPPROG, PMAPVERS, 574 0, 0, kcred, &client)) != RPC_SUCCESS) { 575 status = RPC_TLIERROR; 576 sigreplace(&oldmask, (k_sigset_t *)NULL); 577 MINUTE(("get_pmap_addr - kcreate() returned %d\n", error)); 578 goto out; 579 } 580 581 if (!CLNT_CONTROL(client, CLSET_NODELAYONERR, (char *)&clset)) { 582 MINUTE(("get_pmap_addr - unable to set CLSET_NODELAYONERR\n")); 583 } 584 585 client->cl_auth = authkern_create(); 586 587 parms.pm_prog = prog; 588 parms.pm_vers = vers; 589 if (strcmp(kncfp->knc_proto, NC_TCP) == 0) { 590 parms.pm_prot = IPPROTO_TCP; 591 } else { 592 parms.pm_prot = IPPROTO_UDP; 593 } 594 parms.pm_port = 0; 595 tmo = md_med_pmap_timeout; 596 597 if ((status = CLNT_CALL(client, PMAPPROC_GETPORT, 598 xdr_md_pmap, (char *)&parms, 599 xdr_u_short, (char *)&port, 600 tmo)) != RPC_SUCCESS) { 601 sigreplace(&oldmask, (k_sigset_t *)NULL); 602 MINUTE(("get_pmap_addr - CLNT_CALL(GETPORT) returned %d\n", 603 status)); 604 goto out; 605 } 606 607 sigreplace(&oldmask, (k_sigset_t *)NULL); 608 609 /* A zero value of port indicates a mapping failure */ 610 if (port == 0) { 611 status = RPC_PROGNOTREGISTERED; 612 MINUTE(("get_pmap_addr - program not registered\n")); 613 goto out; 614 } 615 616 TRIVIA(("get_pmap_addr - port=%d\n", port)); 617 med_put_inet_port(addr, ntohs(port)); 618 619 out: 620 if (client) 621 med_clnt_destroy(&client); 622 return (status); 623 } 624 625 /* 626 * Try to get the address for the desired service by using the rpcbind 627 * protocol. Ignores signals. 628 */ 629 static enum clnt_stat 630 med_get_rpcb_addr( 631 struct knetconfig *kncfp, 632 rpcprog_t prog, 633 rpcvers_t vers, 634 struct netbuf *addr 635 ) 636 { 637 int error; 638 char *ua = NULL; 639 enum clnt_stat status; 640 RPCB parms; 641 struct timeval tmo; 642 CLIENT *client = NULL; 643 k_sigset_t oldmask; 644 k_sigset_t newmask; 645 ushort_t port; 646 647 /* 648 * Call rpcbind (local or remote) to get an address we can use 649 * in an RPC client handle. 650 */ 651 tmo = md_med_pmap_timeout; 652 parms.r_prog = prog; 653 parms.r_vers = vers; 654 parms.r_addr = parms.r_owner = ""; 655 656 if (strcmp(kncfp->knc_protofmly, NC_INET) == 0) { 657 if (strcmp(kncfp->knc_proto, NC_TCP) == 0) { 658 parms.r_netid = "tcp"; 659 } else { 660 parms.r_netid = "udp"; 661 } 662 med_put_inet_port(addr, htons(PMAPPORT)); 663 } else if (strcmp(kncfp->knc_protofmly, NC_LOOPBACK) == 0) { 664 parms.r_netid = "ticlts"; 665 med_put_loopback_port(addr, "rpc"); 666 TRIVIA(( 667 "get_rpcb_addr - semantics=%s, protofmly=%s, proto=%s\n", 668 (kncfp->knc_semantics == NC_TPI_CLTS ? 669 "NC_TPI_CLTS" : "?"), 670 kncfp->knc_protofmly, kncfp->knc_proto)); 671 } else { 672 TRIVIA(("get_rpcb_addr - unsupported protofmly %s\n", 673 kncfp->knc_protofmly)); 674 status = RPC_UNKNOWNPROTO; 675 goto out; 676 } 677 678 /* 679 * Mask signals for the duration of the handle creation and 680 * RPC calls. This allows relatively normal operation with a 681 * signal already posted to our thread. 682 * 683 * Any further exit paths from this routine must restore 684 * the original signal mask. 685 */ 686 sigfillset(&newmask); 687 sigreplace(&newmask, &oldmask); 688 689 if ((error = clnt_tli_kcreate(kncfp, addr, RPCBPROG, RPCBVERS, 690 0, 0, kcred, &client)) != 0) { 691 status = RPC_TLIERROR; 692 sigreplace(&oldmask, (k_sigset_t *)NULL); 693 MINUTE(("get_rpcb_addr - kcreate() returned %d\n", error)); 694 goto out; 695 } 696 697 if (!CLNT_CONTROL(client, CLSET_NODELAYONERR, (char *)&clset)) { 698 MINUTE(("get_rpcb_addr - unable to set CLSET_NODELAYONERR\n")); 699 } 700 701 client->cl_auth = authkern_create(); 702 703 if ((status = CLNT_CALL(client, RPCBPROC_GETADDR, 704 xdr_rpcb, (char *)&parms, xdr_wrapstring, (char *)&ua, 705 tmo)) != RPC_SUCCESS) { 706 sigreplace(&oldmask, (k_sigset_t *)NULL); 707 MINUTE(("get_rpcb_addr - CLNT_CALL(GETADDR) returned %d\n", 708 status)); 709 goto out; 710 } 711 712 sigreplace(&oldmask, (k_sigset_t *)NULL); 713 714 if (ua == NULL || *ua == NULL) { 715 status = RPC_PROGNOTREGISTERED; 716 MINUTE(("get_rpcb_addr - program not registered\n")); 717 goto out; 718 } 719 720 /* 721 * Convert the universal address to the transport address. 722 * Theoretically, we should call the local rpcbind to translate 723 * from the universal address to the transport address, but it gets 724 * complicated (e.g., there's no direct way to tell rpcbind that we 725 * want an IP address instead of a loopback address). Note that 726 * the transport address is potentially host-specific, so we can't 727 * just ask the remote rpcbind, because it might give us the wrong 728 * answer. 729 */ 730 if (strcmp(kncfp->knc_protofmly, NC_INET) == 0) { 731 port = rpc_uaddr2port(AF_INET, ua); 732 med_put_inet_port(addr, ntohs(port)); 733 } else if (strcmp(kncfp->knc_protofmly, NC_LOOPBACK) == 0) { 734 loopb_u2t(ua, addr); 735 } else { 736 /* "can't happen" - should have been checked for above */ 737 cmn_err(CE_PANIC, "med_get_rpcb_addr: bad protocol family"); 738 } 739 740 out: 741 if (client != NULL) 742 med_clnt_destroy(&client); 743 if (ua != NULL) 744 xdr_free(xdr_wrapstring, (char *)&ua); 745 return (status); 746 } 747 748 /* 749 * Get the RPC client handle to talk to the service at addrp. 750 * Returns: 751 * RPC_SUCCESS Success. 752 * RPC_RPCBFAILURE Couldn't talk to the remote portmapper (e.g., 753 * timeouts). 754 * RPC_INTR Caught a signal before we could successfully return. 755 * RPC_TLIERROR Couldn't initialize the handle after talking to the 756 * remote portmapper (shouldn't happen). 757 */ 758 static enum clnt_stat 759 med_get_rpc_handle( 760 struct knetconfig *kncfp, 761 struct netbuf *addrp, 762 rpcprog_t prog, 763 rpcvers_t vers, 764 CLIENT **clientp 765 ) 766 { 767 enum clnt_stat status; 768 k_sigset_t oldmask; 769 k_sigset_t newmask; 770 int error; 771 772 /* 773 * Try to get the address from either portmapper or rpcbind. 774 * We check for posted signals after trying and failing to 775 * contact the portmapper since it can take uncomfortably 776 * long for this entire procedure to time out. 777 */ 778 BSTAMP 779 status = med_get_pmap_addr(kncfp, prog, vers, addrp); 780 if (MED_IS_UNRECOVERABLE_RPC(status) && status != RPC_UNKNOWNPROTO && 781 ! PMAP_WRONG_VERSION(status)) { 782 status = RPC_RPCBFAILURE; 783 goto bailout; 784 } 785 786 if (status == RPC_SUCCESS) 787 ESTAMP("done OK med_get_pmap_addr") 788 else 789 ESTAMP("done Not OK med_get_pmap_addr") 790 791 if (status != RPC_SUCCESS) { 792 BSTAMP 793 status = med_get_rpcb_addr(kncfp, prog, vers, addrp); 794 if (status != RPC_SUCCESS) { 795 ESTAMP("done Not OK med_get_rpcb_addr") 796 MINOR(( 797 "get_rpc_handle - can't contact portmapper or rpcbind\n")); 798 status = RPC_RPCBFAILURE; 799 goto bailout; 800 } 801 } 802 ESTAMP("done OK med_get_rpcb_addr") 803 804 med_clnt_destroy(clientp); 805 806 /* 807 * Mask signals for the duration of the handle creation, 808 * allowing relatively normal operation with a signal 809 * already posted to our thread. 810 * 811 * Any further exit paths from this routine must restore 812 * the original signal mask. 813 */ 814 sigfillset(&newmask); 815 sigreplace(&newmask, &oldmask); 816 817 if ((error = clnt_tli_kcreate(kncfp, addrp, prog, vers, 818 0, 0, kcred, clientp)) != 0) { 819 status = RPC_TLIERROR; 820 sigreplace(&oldmask, (k_sigset_t *)NULL); 821 MINUTE(("get_rpc_handle - kcreate(prog) returned %d\n", error)); 822 goto bailout; 823 } 824 825 if (!CLNT_CONTROL(*clientp, CLSET_NODELAYONERR, (char *)&clset)) { 826 MINUTE(("get_rpc_handle - unable to set CLSET_NODELAYONERR\n")); 827 } 828 829 (*clientp)->cl_auth = authkern_create(); 830 831 sigreplace(&oldmask, (k_sigset_t *)NULL); 832 833 bailout: 834 return (status); 835 } 836 837 /* 838 * Return a med_client to the <prog,vers>. 839 * The med_client found is marked as in_use. 840 * It is the responsibility of the caller to release the med_client by 841 * calling med_rel_client(). 842 * 843 * Returns: 844 * RPC_SUCCESS Success. 845 * RPC_CANTSEND Temporarily cannot send. 846 * RPC_TLIERROR Unspecified TLI error. 847 * RPC_UNKNOWNPROTO kncfp is from an unrecognised protocol family. 848 * RPC_PROGNOTREGISTERED The prog `prog' isn't registered on the server. 849 * RPC_RPCBFAILURE Couldn't contact portmapper on remote host. 850 * Any unsuccessful return codes from CLNT_CALL(). 851 */ 852 static enum clnt_stat 853 med_get_client( 854 struct knetconfig *kncfp, 855 struct netbuf *addrp, 856 rpcprog_t prog, 857 rpcvers_t vers, 858 struct med_client **mcp 859 ) 860 { 861 struct med_client *med_clnt = NULL; 862 enum clnt_stat status = RPC_SUCCESS; 863 864 mutex_enter(&med_lck); 865 866 /* 867 * Create an med_client 868 */ 869 med_clnt = kmem_zalloc(sizeof (*med_clnt), KM_SLEEP); 870 med_clnt->client = NULL; 871 med_clnt->prog = prog; 872 med_clnt->vers = vers; 873 med_clnt->addr.buf = med_dup(addrp->buf, addrp->maxlen); 874 med_clnt->addr.len = addrp->len; 875 med_clnt->addr.maxlen = addrp->maxlen; 876 877 mutex_exit(&med_lck); 878 879 status = med_get_rpc_handle(kncfp, &med_clnt->addr, prog, vers, 880 &med_clnt->client); 881 882 out: 883 TRIVIA(("get_client - End: med_clnt=%p status=%d, client=%p\n", 884 (void *)med_clnt, status, 885 (med_clnt ? med_clnt->client : (void *) -1L))); 886 887 if (status == RPC_SUCCESS) { 888 *mcp = med_clnt; 889 } else { 890 /* Cleanup */ 891 if (med_clnt) { 892 mutex_enter(&med_lck); 893 med_rel_client(med_clnt, EINVAL); 894 kmem_free(med_clnt, sizeof (*med_clnt)); 895 mutex_exit(&med_lck); 896 } 897 *mcp = NULL; 898 } 899 900 return (status); 901 } 902 903 /* 904 * Make an RPC call to addr via config. 905 * 906 * Returns: 907 * 0 Success. 908 * EIO Couldn't get client handle, timed out, or got unexpected 909 * RPC status within md_med_protocol_retry attempts. 910 * EINVAL Unrecoverable error in RPC call. Causes client handle 911 * to be destroyed. 912 * EINTR RPC call was interrupted within md_med_protocol_retry attempts. 913 */ 914 static int 915 med_callrpc( 916 struct knetconfig *kncfp, 917 struct netbuf *addrp, 918 rpcprog_t prog, 919 rpcvers_t vers, 920 rpcproc_t proc, 921 xdrproc_t inproc, 922 caddr_t in, 923 xdrproc_t outproc, 924 caddr_t out, 925 struct timeval *timout 926 ) 927 { 928 struct med_client *med_clnt = NULL; 929 enum clnt_stat cl_stat; 930 int tries = md_med_protocol_retry; 931 int error; 932 k_sigset_t oldmask; 933 k_sigset_t newmask; 934 935 MINUTE(("med_callrpc - Calling [%u, %u, %u]\n", prog, vers, proc)); 936 937 sigfillset(&newmask); 938 939 while (tries--) { 940 error = 0; 941 cl_stat = med_get_client(kncfp, addrp, prog, vers, &med_clnt); 942 if (MED_IS_UNRECOVERABLE_RPC(cl_stat)) { 943 error = EINVAL; 944 goto rel_client; 945 } else if (cl_stat != RPC_SUCCESS) { 946 error = EIO; 947 continue; 948 } 949 950 ASSERT(med_clnt != NULL); 951 ASSERT(med_clnt->client != NULL); 952 953 sigreplace(&newmask, &oldmask); 954 cl_stat = CLNT_CALL(med_clnt->client, proc, inproc, in, 955 outproc, out, *timout); 956 sigreplace(&oldmask, (k_sigset_t *)NULL); 957 958 switch (cl_stat) { 959 case RPC_SUCCESS: 960 /* 961 * Update the timestamp on the client cache entry. 962 */ 963 error = 0; 964 break; 965 966 case RPC_TIMEDOUT: 967 MINOR(("med_callrpc - RPC_TIMEDOUT\n")); 968 if (timout == 0) { 969 /* 970 * We will always time out when timout == 0. 971 */ 972 error = 0; 973 break; 974 } 975 /* FALLTHROUGH */ 976 case RPC_CANTSEND: 977 case RPC_XPRTFAILED: 978 default: 979 if (MED_IS_UNRECOVERABLE_RPC(cl_stat)) { 980 error = EINVAL; 981 } else { 982 error = EIO; 983 } 984 } 985 986 rel_client: 987 MINOR(("med_callrpc - RPC cl_stat=%d error=%d\n", 988 cl_stat, error)); 989 if (med_clnt != NULL) { 990 med_rel_client(med_clnt, error); 991 kmem_free(med_clnt, sizeof (*med_clnt)); 992 } 993 994 /* 995 * If EIO, loop else we're done. 996 */ 997 if (error != EIO) { 998 break; 999 } 1000 } 1001 1002 MINUTE(("med_callrpc - End: error=%d, tries=%d\n", error, tries)); 1003 1004 return (error); 1005 } 1006 1007 /* 1008 * Try various transports to get the rpc call through. 1009 */ 1010 static int 1011 med_net_callrpc( 1012 char *h_nm, 1013 in_addr_t h_ip, 1014 uint_t h_flags, 1015 rpcprog_t prog, 1016 rpcvers_t vers, 1017 rpcproc_t proc, 1018 xdrproc_t inproc, 1019 caddr_t in, 1020 xdrproc_t outproc, 1021 caddr_t out, 1022 struct timeval *timout 1023 ) 1024 { 1025 int err; 1026 struct med_addr *uap; 1027 int uapi; 1028 struct netbuf dst; 1029 int done = 0; 1030 1031 ASSERT(h_nm != NULL); 1032 ASSERT(h_ip != 0); 1033 1034 /* 1035 * Loop through our table of transports and try to get the data out. 1036 */ 1037 for (uapi = 0; uapi < med_addr_tab_nents && ! done; uapi++) { 1038 1039 /* Shorthand */ 1040 uap = &med_addr_tab[uapi]; 1041 1042 /* 1043 * UAFLG_SKIP is used for debugging and by the protocol 1044 * selection code. 1045 */ 1046 if (uap->ua_flags & UAFLG_SKIP) { 1047 MINUTE(("med_net_callrpc - %s - marked \"skip\"\n", 1048 uap->ua_netid)); 1049 continue; 1050 } 1051 1052 /* 1053 * If we are not talking to this host, we can skip all LOOPBACK 1054 * transport options. 1055 */ 1056 if (! (h_flags & NMIP_F_LOCAL) && 1057 (uap->ua_flags & UAFLG_LOOPBACK)) 1058 continue; 1059 1060 if (uap->ua_flags & UAFLG_ERROR) 1061 continue; 1062 1063 if (uap->ua_flags & UAFLG_RPCERROR) 1064 continue; 1065 1066 /* Unknown protocol, skip it */ 1067 if (! uap->ua_kn.knc_protofmly) { 1068 MINUTE(("med_net_callrpc - bad protofmly\n")); 1069 continue; 1070 } 1071 1072 if (strcmp(uap->ua_kn.knc_protofmly, NC_LOOPBACK) == 0) { 1073 size_t alen = strlen(utsname.nodename) + 1 + 1; 1074 1075 dst.buf = kmem_zalloc(alen, KM_SLEEP); 1076 dst.maxlen = (uint_t)alen; 1077 1078 (void) strcpy(dst.buf, utsname.nodename); 1079 (void) strcat(dst.buf, "."); 1080 1081 } else if (strcmp(uap->ua_kn.knc_protofmly, NC_INET) == 0) { 1082 struct sockaddr_in *s; 1083 1084 /* 1085 * If we have not allocated a buffer for an INET addrs 1086 * or the buffer allocated will not contain an INET 1087 * addr, allocate or re-allocate. 1088 */ 1089 dst.buf = kmem_zalloc(sizeof (struct sockaddr_in), 1090 KM_SLEEP); 1091 dst.maxlen = sizeof (struct sockaddr_in); 1092 1093 /* Short hand */ 1094 /*LINTED*/ 1095 s = (struct sockaddr_in *)dst.buf; 1096 1097 /* Initialize the socket */ 1098 if (uap->ua_flags & UAFLG_LOOPBACK) 1099 s->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1100 else 1101 s->sin_addr.s_addr = h_ip; 1102 s->sin_port = 0; 1103 s->sin_family = AF_INET; 1104 } 1105 1106 dst.len = dst.maxlen; 1107 1108 MINOR(("med_net_callrpc - Trying %s\n", uap->ua_netid)); 1109 1110 err = med_callrpc(&uap->ua_kn, &dst, prog, vers, proc, inproc, 1111 in, outproc, out, timout); 1112 1113 if (dst.buf) { 1114 kmem_free(dst.buf, dst.maxlen); 1115 dst.buf = NULL; 1116 dst.len = 0; 1117 dst.maxlen = 0; 1118 } 1119 1120 if (err) { 1121 MINUTE(("med_net_callrpc - %s failed\n\n", 1122 uap->ua_netid)); 1123 continue; 1124 } 1125 1126 MINUTE(("med_net_callrpc - %s OK\n\n", uap->ua_netid)); 1127 done = 1; 1128 } 1129 1130 /* 1131 * Print a message if we could not reach a host. 1132 */ 1133 if (! done) { 1134 cmn_err(CE_WARN, "%s on host %s not responding", MED_SERVNAME, 1135 h_nm); 1136 return (1); 1137 } 1138 1139 return (0); 1140 } 1141 1142 /* 1143 * Validate the mediator data 1144 */ 1145 static int 1146 med_ok(set_t setno, med_data_t *meddp) 1147 { 1148 /* Not initialized, or not a mediator data record */ 1149 if (meddp->med_dat_mag != MED_DATA_MAGIC) 1150 goto fail; 1151 1152 MINUTE(("Magic OK\n")); 1153 1154 /* Mismatch in revisions */ 1155 if (meddp->med_dat_rev != MED_DATA_REV) 1156 goto fail; 1157 1158 MINUTE(("Revision OK\n")); 1159 1160 /* Not for the right set, this is paranoid */ 1161 if (setno != meddp->med_dat_sn) 1162 goto fail; 1163 1164 MINUTE(("Setno OK\n")); 1165 1166 /* The record checksum is not correct */ 1167 if (crcchk(meddp, &meddp->med_dat_cks, sizeof (med_data_t), NULL)) 1168 goto fail; 1169 1170 MINUTE(("Mediator validated\n")); 1171 1172 return (1); 1173 1174 fail: 1175 return (0); 1176 } 1177 1178 static void 1179 med_adl(med_data_lst_t **meddlpp, med_data_t *meddp) 1180 { 1181 /* 1182 * Run to the end of the list 1183 */ 1184 for (/* void */; (*meddlpp != NULL); meddlpp = &(*meddlpp)->mdl_nx) 1185 /* void */; 1186 1187 *meddlpp = (med_data_lst_t *)kmem_zalloc(sizeof (med_data_lst_t), 1188 KM_SLEEP); 1189 1190 (*meddlpp)->mdl_med = (med_data_t *)med_dup(meddp, sizeof (med_data_t)); 1191 } 1192 1193 static void 1194 mtaa_upd_init(med_thr_a_args_t *mtaap, med_thr_h_args_t *mthap) 1195 { 1196 med_upd_data_args_t *argsp; 1197 med_err_t *resp; 1198 1199 argsp = kmem_zalloc(sizeof (med_upd_data_args_t), KM_SLEEP); 1200 argsp->med.med_setno = mthap->mtha_setno; 1201 if (MD_MNSET_SETNO(argsp->med.med_setno)) { 1202 /* 1203 * In MN diskset, use a generic nodename, multiowner, in the 1204 * mediator record which allows any node to access mediator 1205 * information. MN diskset reconfig cycle forces consistent 1206 * view of set/node/drive/mediator information across all nodes 1207 * in the MN diskset. This allows the relaxation of 1208 * node name checking in rpc.metamedd for MN disksets. 1209 */ 1210 argsp->med.med_caller = md_strdup(MED_MN_CALLER); 1211 } else { 1212 argsp->med.med_caller = md_strdup(utsname.nodename); 1213 } 1214 argsp->med.med_setname = md_strdup(mthap->mtha_setname); 1215 argsp->med_data = *mthap->mtha_meddp; 1216 1217 resp = kmem_zalloc(sizeof (med_err_t), KM_SLEEP); 1218 1219 mtaap->mtaa_mag = MTAA_MAGIC; 1220 mtaap->mtaa_mthap = mthap; 1221 mtaap->mtaa_prog = MED_PROG; 1222 mtaap->mtaa_vers = MED_VERS; 1223 mtaap->mtaa_proc = MED_UPD_DATA; 1224 mtaap->mtaa_inproc = xdr_med_upd_data_args_t; 1225 mtaap->mtaa_in = (caddr_t)argsp; 1226 mtaap->mtaa_outproc = xdr_med_err_t; 1227 mtaap->mtaa_out = (caddr_t)resp; 1228 mtaap->mtaa_timout = (struct timeval *)&md_med_def_timeout; 1229 } 1230 1231 static void 1232 mtaa_upd_free(med_thr_a_args_t *mtaap) 1233 { 1234 med_upd_data_args_t *argsp = (med_upd_data_args_t *)mtaap->mtaa_in; 1235 med_err_t *resp = (med_err_t *)mtaap->mtaa_out; 1236 1237 freestr(argsp->med.med_caller); 1238 freestr(argsp->med.med_setname); 1239 kmem_free(argsp, sizeof (med_upd_data_args_t)); 1240 1241 if (mtaap->mtaa_flags & MDT_A_OK) 1242 xdr_free(mtaap->mtaa_outproc, mtaap->mtaa_out); 1243 1244 kmem_free(resp, sizeof (med_err_t)); 1245 } 1246 1247 static int 1248 mtaa_upd_err(med_thr_a_args_t *mtaap) 1249 { 1250 /*LINTED*/ 1251 med_err_t *resp = (med_err_t *)mtaap->mtaa_out; 1252 1253 if (resp->med_errno == MDE_MED_NOERROR) { 1254 MAJOR(("upd_med_hosts - %s - OK\n\n", mtaap->mtaa_h_nm)); 1255 return (0); 1256 } else { 1257 MAJOR(("upd_med_hosts - %s - errno=%d\n\n", mtaap->mtaa_h_nm, 1258 resp->med_errno)); 1259 return (1); 1260 } 1261 } 1262 1263 static void 1264 mtaa_get_init(med_thr_a_args_t *mtaap, med_thr_h_args_t *mthap) 1265 { 1266 med_args_t *argsp; 1267 med_get_data_res_t *resp; 1268 1269 argsp = kmem_zalloc(sizeof (med_args_t), KM_SLEEP); 1270 argsp->med.med_setno = mthap->mtha_setno; 1271 if (MD_MNSET_SETNO(argsp->med.med_setno)) { 1272 /* 1273 * In MN diskset, use a generic nodename, multiowner, in the 1274 * mediator record which allows any node to access mediator 1275 * information. MN diskset reconfig cycle forces consistent 1276 * view of set/node/drive/mediator information across all nodes 1277 * in the MN diskset. This allows the relaxation of 1278 * node name checking in rpc.metamedd for MN disksets. 1279 */ 1280 argsp->med.med_caller = md_strdup(MED_MN_CALLER); 1281 } else { 1282 argsp->med.med_caller = md_strdup(utsname.nodename); 1283 } 1284 1285 argsp->med.med_setname = md_strdup(mthap->mtha_setname); 1286 1287 resp = kmem_zalloc(sizeof (med_get_data_res_t), KM_SLEEP); 1288 1289 mtaap->mtaa_mag = MTAA_MAGIC; 1290 mtaap->mtaa_mthap = mthap; 1291 mtaap->mtaa_prog = MED_PROG; 1292 mtaap->mtaa_vers = MED_VERS; 1293 mtaap->mtaa_proc = MED_GET_DATA; 1294 mtaap->mtaa_inproc = xdr_med_args_t; 1295 mtaap->mtaa_in = (caddr_t)argsp; 1296 mtaap->mtaa_outproc = xdr_med_get_data_res_t; 1297 mtaap->mtaa_out = (caddr_t)resp; 1298 mtaap->mtaa_timout = (struct timeval *)&md_med_def_timeout; 1299 } 1300 1301 static void 1302 mtaa_get_free(med_thr_a_args_t *mtaap) 1303 { 1304 /*LINTED*/ 1305 med_args_t *argsp = (med_args_t *)mtaap->mtaa_in; 1306 /*LINTED*/ 1307 med_get_data_res_t *resp = (med_get_data_res_t *)mtaap->mtaa_out; 1308 1309 freestr(argsp->med.med_caller); 1310 freestr(argsp->med.med_setname); 1311 kmem_free(argsp, sizeof (med_args_t)); 1312 1313 if (mtaap->mtaa_flags & MDT_A_OK) 1314 xdr_free(mtaap->mtaa_outproc, mtaap->mtaa_out); 1315 1316 kmem_free(resp, sizeof (med_get_data_res_t)); 1317 } 1318 1319 static int 1320 mtaa_get_err(med_thr_a_args_t *mtaap) 1321 { 1322 /*LINTED*/ 1323 med_get_data_res_t *resp = (med_get_data_res_t *)mtaap->mtaa_out; 1324 1325 if (resp->med_status.med_errno == MDE_MED_NOERROR) { 1326 MAJOR(("get_med_host_data - %s - OK\n\n", mtaap->mtaa_h_nm)); 1327 return (0); 1328 } else { 1329 MAJOR(("get_med_host_data - %s - errno=%d\n\n", 1330 mtaap->mtaa_h_nm, resp->med_status.med_errno)); 1331 return (1); 1332 } 1333 } 1334 1335 static void 1336 mtha_init( 1337 med_thr_t *mtp, 1338 med_thr_h_args_t *mthap, 1339 md_hi_t *mhp, 1340 char *setname, 1341 med_data_t *meddp, 1342 set_t setno, 1343 void (*mtaa_init_func)(med_thr_a_args_t *, 1344 med_thr_h_args_t *), 1345 int (*mtaa_err_func)(med_thr_a_args_t *) 1346 ) 1347 { 1348 int j; 1349 1350 mthap->mtha_mag = MTHA_MAGIC; 1351 mthap->mtha_mtp = mtp; 1352 mthap->mtha_mhp = mhp; 1353 mthap->mtha_setname = md_strdup(setname); 1354 if (meddp) 1355 mthap->mtha_meddp = meddp; 1356 else 1357 mthap->mtha_meddp = NULL; 1358 mthap->mtha_setno = setno; 1359 mthap->mtha_a_cnt = mhp->a_cnt; 1360 mthap->mtha_a_nthr = 0; 1361 1362 mutex_init(&mthap->mtha_a_mx, NULL, MUTEX_DEFAULT, 1363 NULL); 1364 cv_init(&mthap->mtha_a_cv, NULL, CV_DEFAULT, NULL); 1365 1366 j = MIN(mthap->mtha_a_cnt, MAX_HOST_ADDRS) - 1; 1367 for (; j >= 0; j--) { 1368 (*mtaa_init_func)(&mthap->mtha_a_args[j], mthap); 1369 mthap->mtha_a_args[j].mtaa_h_nm = mhp->a_nm[j]; 1370 mthap->mtha_a_args[j].mtaa_h_ip = mhp->a_ip[j]; 1371 mthap->mtha_a_args[j].mtaa_h_flags = mhp->a_flg; 1372 mthap->mtha_a_args[j].mtaa_err_func = mtaa_err_func; 1373 } 1374 } 1375 1376 static void 1377 mtha_free( 1378 med_thr_h_args_t *mthap, 1379 void (*mtaa_free_func)(med_thr_a_args_t *) 1380 ) 1381 { 1382 int j; 1383 1384 freestr(mthap->mtha_setname); 1385 1386 j = MIN(mthap->mtha_a_cnt, MAX_HOST_ADDRS) - 1; 1387 for (; j >= 0; j--) 1388 (*mtaa_free_func)(&mthap->mtha_a_args[j]); 1389 1390 mutex_destroy(&mthap->mtha_a_mx); 1391 cv_destroy(&mthap->mtha_a_cv); 1392 } 1393 1394 static void 1395 med_a_thr(med_thr_a_args_t *mtaap) 1396 { 1397 callb_cpr_t cprinfo; 1398 1399 /* 1400 * Register cpr callback 1401 */ 1402 CALLB_CPR_INIT(&cprinfo, &mtaap->mtaa_mthap->mtha_a_mx, 1403 callb_generic_cpr, "med_a_thr"); 1404 1405 mutex_enter(&mtaap->mtaa_mthap->mtha_a_mx); 1406 if (mtaap->mtaa_mthap->mtha_flags & MDT_H_OK) 1407 goto done; 1408 1409 mutex_exit(&mtaap->mtaa_mthap->mtha_a_mx); 1410 1411 mtaap->mtaa_err = med_net_callrpc( 1412 mtaap->mtaa_h_nm, mtaap->mtaa_h_ip, mtaap->mtaa_h_flags, 1413 mtaap->mtaa_prog, mtaap->mtaa_vers, mtaap->mtaa_proc, 1414 mtaap->mtaa_inproc, mtaap->mtaa_in, 1415 mtaap->mtaa_outproc, mtaap->mtaa_out, 1416 mtaap->mtaa_timout); 1417 1418 mutex_enter(&mtaap->mtaa_mthap->mtha_a_mx); 1419 1420 if (mtaap->mtaa_err) { 1421 MAJOR(("med_net_callrpc(%u, %u, %u) - %s - failed\n\n", 1422 mtaap->mtaa_prog, mtaap->mtaa_vers, mtaap->mtaa_proc, 1423 mtaap->mtaa_h_nm)); 1424 xdr_free(mtaap->mtaa_outproc, mtaap->mtaa_out); 1425 } else { 1426 if ((*mtaap->mtaa_err_func)(mtaap) == 0) { 1427 if (! (mtaap->mtaa_mthap->mtha_flags & MDT_H_OK)) { 1428 mtaap->mtaa_mthap->mtha_flags |= MDT_H_OK; 1429 mtaap->mtaa_flags |= MDT_A_OK; 1430 } else 1431 xdr_free(mtaap->mtaa_outproc, mtaap->mtaa_out); 1432 } else 1433 xdr_free(mtaap->mtaa_outproc, mtaap->mtaa_out); 1434 } 1435 1436 done: 1437 mtaap->mtaa_mthap->mtha_a_nthr--; 1438 cv_signal(&mtaap->mtaa_mthap->mtha_a_cv); 1439 1440 /* 1441 * CALLB_CPR_EXIT will do mutex_exit(&mtaap->mtaa_mthap->mtha_a_mx) 1442 */ 1443 CALLB_CPR_EXIT(&cprinfo); 1444 thread_exit(); 1445 } 1446 1447 static void 1448 med_h_thr(med_thr_h_args_t *mthap) 1449 { 1450 int j; 1451 callb_cpr_t cprinfo; 1452 1453 /* 1454 * Register cpr callback 1455 */ 1456 CALLB_CPR_INIT(&cprinfo, &mthap->mtha_mtp->mt_mx, callb_generic_cpr, 1457 "med_a_thr"); 1458 /* 1459 * Lock mthap->mtha_mtp->mt_mx is held early to avoid releasing the 1460 * locks out of order. 1461 */ 1462 mutex_enter(&mthap->mtha_mtp->mt_mx); 1463 mutex_enter(&mthap->mtha_a_mx); 1464 1465 j = MIN(mthap->mtha_a_cnt, MAX_HOST_ADDRS) - 1; 1466 for (; j >= 0; j--) { 1467 (void) thread_create(NULL, 0, med_a_thr, 1468 &mthap->mtha_a_args[j], 0, &p0, TS_RUN, minclsyspri); 1469 mthap->mtha_a_nthr++; 1470 } 1471 1472 /* 1473 * cpr safe to suspend while waiting for other threads 1474 */ 1475 CALLB_CPR_SAFE_BEGIN(&cprinfo); 1476 while (mthap->mtha_a_nthr > 0) 1477 cv_wait(&mthap->mtha_a_cv, &mthap->mtha_a_mx); 1478 mutex_exit(&mthap->mtha_a_mx); 1479 CALLB_CPR_SAFE_END(&cprinfo, &mthap->mtha_mtp->mt_mx); 1480 1481 1482 mthap->mtha_mtp->mt_nthr--; 1483 cv_signal(&mthap->mtha_mtp->mt_cv); 1484 1485 /* 1486 * set up cpr exit 1487 * CALLB_CPR_EXIT will do mutex_exit(&mtaap->mta_mtp->mt_mx) 1488 */ 1489 CALLB_CPR_EXIT(&cprinfo); 1490 thread_exit(); 1491 } 1492 1493 static med_get_data_res_t * 1494 mtaa_get_resp(med_thr_h_args_t *mthap) 1495 { 1496 med_thr_a_args_t *mtaap; 1497 int j; 1498 1499 j = MIN(mthap->mtha_a_cnt, MAX_HOST_ADDRS) - 1; 1500 for (; j >= 0; j--) { 1501 mtaap = &mthap->mtha_a_args[j]; 1502 if (mtaap->mtaa_flags & MDT_A_OK) 1503 /*LINTED*/ 1504 return ((med_get_data_res_t *)mtaap->mtaa_out); 1505 } 1506 return ((med_get_data_res_t *)NULL); 1507 } 1508 1509 /* 1510 * Public Functions 1511 */ 1512 1513 /* 1514 * initializes med structs, locks, etc 1515 */ 1516 void 1517 med_init(void) 1518 { 1519 int uapi; 1520 1521 TRIVIA(("[med_init")); 1522 1523 for (uapi = 0; uapi < med_addr_tab_nents; uapi++) { 1524 struct med_addr *uap = &med_addr_tab[uapi]; 1525 1526 /* If the protocol is skipped, the mutex is not needed either */ 1527 if (md_med_trans_lst != NULL && 1528 strstr(md_med_trans_lst, uap->ua_kn.knc_proto) == NULL && 1529 strstr(md_med_trans_lst, uap->ua_netid) == NULL) { 1530 uap->ua_flags |= UAFLG_SKIP; 1531 continue; 1532 } 1533 1534 mutex_init(&uap->ua_mutex, NULL, MUTEX_DEFAULT, NULL); 1535 uap->ua_flags |= UAFLG_LOCKINIT; 1536 bzero((caddr_t)&uap->ua_kn.knc_unused, 1537 sizeof (uap->ua_kn.knc_unused)); 1538 } 1539 1540 TRIVIA(("]\n")); 1541 } 1542 1543 /* 1544 * free any med structs, locks, etc 1545 */ 1546 void 1547 med_fini(void) 1548 { 1549 int uapi; 1550 1551 TRIVIA(("[med_fini")); 1552 1553 for (uapi = 0; uapi < med_addr_tab_nents; uapi++) { 1554 struct med_addr *uap = &med_addr_tab[uapi]; 1555 1556 if (uap->ua_flags & UAFLG_LOCKINIT) { 1557 mutex_destroy(&uap->ua_mutex); 1558 uap->ua_flags &= ~UAFLG_LOCKINIT; 1559 } 1560 } 1561 1562 TRIVIA(("]\n")); 1563 } 1564 1565 /* 1566 * Update all the mediators 1567 */ 1568 int 1569 upd_med_hosts( 1570 md_hi_arr_t *mp, 1571 char *setname, 1572 med_data_t *meddp, 1573 char *caller 1574 ) 1575 { 1576 med_thr_t *mtp; 1577 med_thr_h_args_t *mthap; 1578 int i; 1579 int medok = 0; 1580 1581 MAJOR(("upd_med_hosts - called from <%s>\n", NULLSTR(caller))); 1582 1583 /* No mediators, were done */ 1584 if (mp->n_cnt == 0) 1585 return (0); 1586 1587 mtp = kmem_zalloc(sizeof (med_thr_t), KM_SLEEP); 1588 ASSERT(mtp != NULL); 1589 1590 mutex_init(&mtp->mt_mx, NULL, MUTEX_DEFAULT, NULL); 1591 cv_init(&mtp->mt_cv, NULL, CV_DEFAULT, NULL); 1592 mtp->mt_mag = MTH_MAGIC; 1593 1594 mutex_enter(&mtp->mt_mx); 1595 1596 mtp->mt_nthr = 0; 1597 1598 /* Loop through our list of mediator hosts, start a thread per host */ 1599 for (i = 0; i < md_nmedh; i++) { 1600 1601 if (mp->n_lst[i].a_cnt == 0) 1602 continue; 1603 1604 mtp->mt_h_args[i] = kmem_zalloc(sizeof (med_thr_h_args_t), 1605 KM_SLEEP); 1606 mthap = mtp->mt_h_args[i]; 1607 ASSERT(mthap != NULL); 1608 mtha_init(mtp, mthap, &mp->n_lst[i], setname, meddp, 1609 meddp->med_dat_sn, mtaa_upd_init, mtaa_upd_err); 1610 1611 MAJOR(("upd_med_hosts - updating %s\n", 1612 NULLSTR(mp->n_lst[i].a_nm[0]))); 1613 1614 (void) thread_create(NULL, 0, med_h_thr, mthap, 0, &p0, 1615 TS_RUN, minclsyspri); 1616 1617 mtp->mt_nthr++; 1618 } 1619 1620 while (mtp->mt_nthr > 0) 1621 cv_wait(&mtp->mt_cv, &mtp->mt_mx); 1622 1623 mutex_exit(&mtp->mt_mx); 1624 1625 for (i = 0; i < md_nmedh; i++) { 1626 mthap = mtp->mt_h_args[i]; 1627 if (mthap != NULL) { 1628 if (mthap->mtha_flags & MDT_H_OK) 1629 medok++; 1630 mtha_free(mthap, mtaa_upd_free); 1631 kmem_free(mthap, sizeof (med_thr_h_args_t)); 1632 } 1633 } 1634 1635 mutex_destroy(&mtp->mt_mx); 1636 cv_destroy(&mtp->mt_cv); 1637 1638 kmem_free(mtp, sizeof (med_thr_t)); 1639 1640 return (medok); 1641 } 1642 1643 /* 1644 * Get the mediator data. 1645 */ 1646 med_data_lst_t * 1647 get_med_host_data( 1648 md_hi_arr_t *mp, 1649 char *setname, 1650 set_t setno 1651 ) 1652 { 1653 med_thr_t *mtp; 1654 med_thr_h_args_t *mthap; 1655 med_get_data_res_t *resp; 1656 med_data_lst_t *retval = NULL; 1657 int i; 1658 1659 /* No mediators, were done */ 1660 if (mp->n_cnt == 0) 1661 return (NULL); 1662 1663 mtp = kmem_zalloc(sizeof (med_thr_t), KM_SLEEP); 1664 ASSERT(mtp != NULL); 1665 1666 mutex_init(&mtp->mt_mx, NULL, MUTEX_DEFAULT, NULL); 1667 cv_init(&mtp->mt_cv, NULL, CV_DEFAULT, NULL); 1668 1669 mutex_enter(&mtp->mt_mx); 1670 1671 mtp->mt_nthr = 0; 1672 1673 /* Loop through our list of mediator hosts, start a thread per host */ 1674 for (i = 0; i < md_nmedh; i++) { 1675 1676 if (mp->n_lst[i].a_cnt == 0) 1677 continue; 1678 1679 mtp->mt_h_args[i] = kmem_zalloc(sizeof (med_thr_h_args_t), 1680 KM_SLEEP); 1681 mthap = mtp->mt_h_args[i]; 1682 ASSERT(mthap != NULL); 1683 mtha_init(mtp, mthap, &mp->n_lst[i], setname, NULL, setno, 1684 mtaa_get_init, mtaa_get_err); 1685 1686 MAJOR(("get_med_host_data from %s\n", 1687 NULLSTR(mp->n_lst[i].a_nm[0]))); 1688 1689 (void) thread_create(NULL, 0, med_h_thr, mthap, 0, &p0, 1690 TS_RUN, minclsyspri); 1691 1692 mtp->mt_nthr++; 1693 } 1694 1695 while (mtp->mt_nthr > 0) 1696 cv_wait(&mtp->mt_cv, &mtp->mt_mx); 1697 1698 mutex_exit(&mtp->mt_mx); 1699 1700 for (i = 0; i < md_nmedh; i++) { 1701 mthap = mtp->mt_h_args[i]; 1702 if (mthap != NULL) { 1703 if (mthap->mtha_flags & MDT_H_OK) { 1704 resp = mtaa_get_resp(mthap); 1705 ASSERT(resp != NULL); 1706 1707 if (med_ok(setno, &resp->med_data)) 1708 med_adl(&retval, &resp->med_data); 1709 } 1710 mtha_free(mthap, mtaa_get_free); 1711 kmem_free(mthap, sizeof (med_thr_h_args_t)); 1712 } 1713 } 1714 1715 mutex_destroy(&mtp->mt_mx); 1716 cv_destroy(&mtp->mt_cv); 1717 1718 kmem_free(mtp, sizeof (med_thr_t)); 1719 1720 return (retval); 1721 } 1722 1723 int 1724 med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode) 1725 { 1726 md_error_t *ep = &tpp->med_tp_mde; 1727 1728 mdclrerror(ep); 1729 1730 if ((mode & FREAD) == 0) 1731 return (mdsyserror(ep, EACCES)); 1732 1733 tpp->med_tp_nents = med_addr_tab_nents; 1734 tpp->med_tp_setup = md_med_transdevs_set; 1735 1736 return (0); 1737 } 1738 1739 int 1740 med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode) 1741 { 1742 md_error_t *ep = &tpp->med_tp_mde; 1743 int uapi = 0; 1744 1745 mdclrerror(ep); 1746 1747 if ((mode & FREAD) == 0) 1748 return (mdsyserror(ep, EACCES)); 1749 1750 for (uapi = 0; uapi < med_addr_tab_nents; uapi++) { 1751 struct med_addr *uap = &med_addr_tab[uapi]; 1752 1753 (void) strncpy(tpp->med_tp_ents[uapi].med_te_nm, 1754 uap->ua_devname, MED_TE_NM_LEN); 1755 tpp->med_tp_ents[uapi].med_te_dev = 1756 (md_dev64_t)uap->ua_kn.knc_rdev; 1757 } 1758 1759 tpp->med_tp_nents = med_addr_tab_nents; 1760 1761 return (0); 1762 } 1763 1764 int 1765 med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode) 1766 { 1767 md_error_t *ep = &tpp->med_tp_mde; 1768 int uapi = 0; 1769 1770 mdclrerror(ep); 1771 1772 if ((mode & FWRITE) == 0) 1773 return (mdsyserror(ep, EACCES)); 1774 1775 for (uapi = 0; uapi < med_addr_tab_nents; uapi++) { 1776 struct med_addr *uap = &med_addr_tab[uapi]; 1777 1778 mutex_enter(&uap->ua_mutex); 1779 uap->ua_kn.knc_rdev = md_dev64_to_dev( 1780 tpp->med_tp_ents[uapi].med_te_dev); 1781 mutex_exit(&uap->ua_mutex); 1782 } 1783 1784 md_med_transdevs_set = 1; 1785 1786 return (0); 1787 } 1788