4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #include <sys/errno.h>
35 #include <sys/cmn_err.h>
39 /* #include <sys/ddi.h> */
40 /* #include <sys/sunddi.h> */
41 #include <sys/debug.h>
44 #include <sys/pathname.h>
45 #include <sys/netconfig.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
49 #include <rpc/types.h>
52 #include <rpc/clnt_soc.h>
53 #include <rpc/pmap_prot.h> /* PMAPPORT */
55 #include <rpc/rpcb_prot.h>
56 #include <rpc/xdr.h> /* This also gets us htonl() et al. */
59 #include <sys/lvm/mdmed.h>
62 #include <sys/lvm/mdvar.h>
63 #include <sys/lvm/md_mddb.h>
64 #include <sys/lvm/md_crc.h>
65 #include <sys/callb.h>
68 * Flag to turn off the kernel RPC client delay code. This only takes effect
69 * if the route to the remote node is marked as RTF_REJECT and the RPC path
70 * manager has been flushed such that any 'old' path information is no longer
73 static bool_t clset
= TRUE
;
75 extern int md_nmedh
; /* declared in md.c */
76 extern char *md_med_trans_lst
;
77 extern md_set_t md_set
[]; /* declared in md.c */
80 * Structures used only by mediators
82 typedef struct med_thr_a_args
{
87 int (*mtaa_err_func
)(struct med_thr_a_args
*);
88 struct med_thr_h_args
*mtaa_mthap
;
93 xdrproc_t mtaa_inproc
;
95 xdrproc_t mtaa_outproc
;
97 struct timeval
*mtaa_timout
;
101 #define MTAA_MAGIC 0xbadbabed
102 #define MDT_A_OK 0x00000001
104 typedef struct med_thr_h_args
{
108 med_data_t
*mtha_meddp
;
109 struct med_thr
*mtha_mtp
;
113 kcondvar_t mtha_a_cv
;
116 med_thr_a_args_t mtha_a_args
[MAX_HOST_ADDRS
];
119 #define MTHA_MAGIC 0xbadbabee
120 #define MDT_H_OK 0x00000001
122 typedef struct med_thr
{
127 med_thr_h_args_t
*mt_h_args
[MED_MAX_HOSTS
];
130 #define MTH_MAGIC 0xbadbabef
134 static struct timeval btv
;
135 static struct timeval etv
;
137 #define DBGLVL_NONE 0x00000000
138 #define DBGLVL_MAJOR 0x00000100
139 #define DBGLVL_MINOR 0x00000200
140 #define DBGLVL_MINUTE 0x00000400
141 #define DBGLVL_TRIVIA 0x00000800
142 #define DBGLVL_HIDEOUS 0x00001000
144 #define DBGFLG_NONE 0x00000000
145 #define DBGFLG_NOPANIC 0x00000001
146 #define DBGFLG_LVLONLY 0x00000002
147 #define DBGFLG_FIXWOULDPANIC 0x00000004
149 #define DBGFLG_FLAGMASK 0x0000000F
150 #define DBGFLG_LEVELMASK ~DBGFLG_FLAGMASK
152 #define DEBUG_FLAGS (md_medup_failure_dbg & DBGFLG_FLAGMASK)
153 #define DEBUG_LEVEL (md_medup_failure_dbg & DBGFLG_LEVELMASK)
156 unsigned int md_medup_failure_dbg
= DBGLVL_MINOR
| DBGFLG_NONE
;
158 unsigned int md_medup_failure_dbg
= DBGLVL_NONE
| DBGFLG_NONE
;
161 #define DCALL(dbg_level, call) \
163 if (DEBUG_LEVEL != DBGLVL_NONE) { \
164 if (DEBUG_FLAGS & DBGFLG_LVLONLY) { \
165 if (DEBUG_LEVEL & dbg_level) { \
169 if (dbg_level <= DEBUG_LEVEL) { \
176 #define DPRINTF(dbg_level, msg) DCALL(dbg_level, printf msg)
178 #define MAJOR(msg) DPRINTF(DBGLVL_MAJOR, msg)
179 #define MINOR(msg) DPRINTF(DBGLVL_MINOR, msg)
180 #define MINUTE(msg) DPRINTF(DBGLVL_MINUTE, msg)
181 #define TRIVIA(msg) DPRINTF(DBGLVL_TRIVIA, msg)
182 #define HIDEOUS(msg) DPRINTF(DBGLVL_HIDEOUS, msg)
183 #define BSTAMP { uniqtime(&btv); }
185 #define ESTAMP(msg) \
187 time_t esec, eusec; \
191 eusec = etv.tv_usec - btv.tv_usec; \
192 esec = etv.tv_sec - btv.tv_sec; \
197 MINOR(("%s: sec=%ld, usec=%ld\n", msg, esec, eusec)); \
202 #define DCALL(ignored_dbg_level, ignored_routine)
203 #define MAJOR(ignored)
204 #define MINOR(ignored)
205 #define MINUTE(ignored)
206 #define TRIVIA(ignored)
207 #define HIDEOUS(ignored)
209 #define ESTAMP(msg) { }
213 static int md_med_protocol_retry
= 2;
214 static int md_med_transdevs_set
= 0;
217 * Definitions and declarations.
224 struct netbuf addr
; /* Address to this <prog,vers> */
229 * unrecoverable RPC status codes; cf. rfscall()
231 #define MED_IS_UNRECOVERABLE_RPC(s) (((s) == RPC_AUTHERROR) || \
232 ((s) == RPC_CANTENCODEARGS) || \
233 ((s) == RPC_CANTDECODERES) || \
234 ((s) == RPC_VERSMISMATCH) || \
235 ((s) == RPC_PROCUNAVAIL) || \
236 ((s) == RPC_PROGUNAVAIL) || \
237 ((s) == RPC_PROGVERSMISMATCH) || \
238 ((s) == RPC_CANTDECODEARGS))
241 * When trying to contact a portmapper that doesn't speak the version we're
242 * using, we should theoretically get back RPC_PROGVERSMISMATCH.
243 * Unfortunately, some (all?) 4.x hosts return an accept_stat of
244 * PROG_UNAVAIL, which gets mapped to RPC_PROGUNAVAIL, so we have to check
247 #define PMAP_WRONG_VERSION(s) ((s) == RPC_PROGVERSMISMATCH || \
248 (s) == RPC_PROGUNAVAIL)
250 #define NULLSTR(str) (! (str) || *(str) == '\0'? "<null>" : (str))
253 /* Flags used in med_addr (netconfig) table */
255 #define UAFLG_NONE 0x00000000
256 #define UAFLG_SKIP 0x00000001
257 #define UAFLG_ERROR 0x00000002
258 #define UAFLG_RPCERROR 0x00000004
259 #define UAFLG_LOOPBACK 0x00000008
260 #define UAFLG_LOCKINIT 0x00000010
263 * most of this data is static. The mutex protects the changable items:
266 static struct med_addr
{
267 struct knetconfig ua_kn
;
268 char *ua_devname
; /* const */
269 char *ua_netid
; /* const */
275 * The order of the entries in this table is the order in
276 * which we'll try to connect to the user-level daemon.
277 * The final entry must have a NULL ua_devname.
279 * This is basically a tablified version of /etc/netconfig
280 * (with additional entries for loopback TCP and UDP networks
281 * that are missing from the user-level version.)
286 /* semantics protofmly proto, dev_t */
287 { { NC_TPI_CLTS
, NC_INET
, NC_UDP
, NODEV
},
288 /* devname netid flags */
289 "/dev/udp", "udp-loopback", UAFLG_LOOPBACK
293 /* semantics protofmly proto, dev_t */
294 { { NC_TPI_CLTS
, NC_INET
, NC_UDP
, NODEV
},
295 /* devname netid flags */
296 "/dev/udp", "udp", UAFLG_NONE
300 /* semantics protofmly proto, dev_t */
301 { { NC_TPI_COTS_ORD
, NC_INET
, NC_TCP
, NODEV
},
302 /* devname netid flags */
303 "/dev/tcp", "tcp-loopback", UAFLG_LOOPBACK
307 /* semantics protofmly proto, dev_t */
308 { { NC_TPI_COTS_ORD
, NC_INET
, NC_TCP
, NODEV
},
309 /* devname netid flags */
310 "/dev/tcp", "tcp", UAFLG_NONE
314 /* semantics protofmly proto, dev_t */
315 { { NC_TPI_CLTS
, NC_LOOPBACK
, NC_NOPROTO
, NODEV
},
316 /* devname netid flags */
317 "/dev/ticlts", "ticlts", UAFLG_LOOPBACK
321 /* semantics protofmly proto, dev_t */
322 { { NC_TPI_COTS_ORD
, NC_LOOPBACK
, NC_NOPROTO
, NODEV
},
323 /* devname netid flags */
324 "/dev/ticotsord", "ticotsord", UAFLG_LOOPBACK
328 /* semantics protofmly proto, dev_t */
329 { { NC_TPI_COTS
, NC_LOOPBACK
, NC_NOPROTO
, NODEV
},
330 /* devname netid flags */
331 "/dev/ticots", "ticots", UAFLG_LOOPBACK
335 /* The number of entries in the table */
336 int med_addr_tab_nents
= sizeof (med_addr_tab
) / sizeof (med_addr_tab
[0]);
342 /* A useful utility. */
344 med_dup(void *str
, int len
)
346 char *s
= (char *)kmem_zalloc(len
, KM_SLEEP
);
357 * Utilities for manipulating netbuf's.
358 * These utilities are the only knc_protofmly specific functions in the MED.
362 * Utilities to patch a port number (for NC_INET protocols) or a
363 * port name (for NC_LOOPBACK) into a network address.
366 med_put_inet_port(struct netbuf
*addr
, ushort_t port
)
369 * Easy - we always patch an unsigned short on top of an
370 * unsigned short. No changes to addr's len or maxlen are
374 ((struct sockaddr_in
*)(addr
->buf
))->sin_port
= port
;
378 med_put_loopback_port(struct netbuf
*addr
, char *port
)
385 * We must make sure the addr has enough space for us,
386 * patch in `port', and then adjust addr's len and maxlen
387 * to reflect the change.
389 if ((dot
= strchr(addr
->buf
, '.')) == (char *)NULL
) {
390 TRIVIA(("put_loopb_port - malformed loopback addr %s\n",
395 newlen
= (int)((dot
- addr
->buf
+ 1) + strlen(port
));
396 if (newlen
> addr
->maxlen
) {
397 newbuf
= (char *)kmem_zalloc((size_t)newlen
, KM_SLEEP
);
398 (void) bcopy(addr
->buf
, newbuf
, (size_t)addr
->len
);
399 kmem_free(addr
->buf
, (size_t)addr
->maxlen
);
401 addr
->len
= addr
->maxlen
= (uint_t
)newlen
;
402 dot
= strchr(addr
->buf
, '.');
407 (void) strncpy(++dot
, port
, strlen(port
));
412 * Make sure the given netbuf has a maxlen at least as big as the given
416 grow_netbuf(struct netbuf
*nb
, size_t length
)
420 if (nb
->maxlen
>= length
)
423 newbuf
= kmem_zalloc(length
, KM_SLEEP
);
424 bcopy(nb
->buf
, newbuf
, (size_t)nb
->len
);
425 kmem_free(nb
->buf
, (size_t)nb
->maxlen
);
427 nb
->maxlen
= (uint_t
)length
;
431 * Convert a loopback universal address to a loopback transport address.
434 loopb_u2t(const char *ua
, struct netbuf
*addr
)
436 size_t stringlen
= strlen(ua
) + 1;
437 const char *univp
; /* ptr into universal addr */
438 char *transp
; /* ptr into transport addr */
440 /* Make sure the netbuf will be big enough. */
441 if (addr
->maxlen
< stringlen
) {
442 grow_netbuf(addr
, stringlen
);
447 while (*univp
!= NULL
) {
448 if (*univp
== '\\' && *(univp
+1) == '\\') {
451 } else if (*univp
== '\\') {
452 /* octal character */
453 *transp
= (((*(univp
+1) - '0') & 3) << 6) +
454 (((*(univp
+2) - '0') & 7) << 3) +
455 ((*(univp
+3) - '0') & 7);
464 addr
->len
= (uint_t
)(transp
- addr
->buf
);
465 ASSERT(addr
->len
<= addr
->maxlen
);
472 * Taken from libnsl/rpc/pmap_prot.c
475 xdr_md_pmap(xdrs
, regs
)
479 if (xdr_u_int(xdrs
, ®s
->pm_prog
) &&
480 xdr_u_int(xdrs
, ®s
->pm_vers
) &&
481 xdr_u_int(xdrs
, ®s
->pm_prot
))
482 return (xdr_u_int(xdrs
, ®s
->pm_port
));
487 * We need an version of CLNT_DESTROY which also frees the auth structure.
490 med_clnt_destroy(CLIENT
**clp
)
493 if ((*clp
)->cl_auth
) {
494 AUTH_DESTROY((*clp
)->cl_auth
);
495 (*clp
)->cl_auth
= NULL
;
503 * Release this med_client entry.
504 * Do also destroy the entry if there was an error != EINTR,
505 * and mark the entry as not-valid, by setting time=0.
508 med_rel_client(struct med_client
*medc
, int error
)
510 TRIVIA(("rel_client - addr = (%p, %u %u)\n",
511 (void *) medc
->addr
.buf
, medc
->addr
.len
, medc
->addr
.maxlen
));
513 if (1 || error
&& error
!= EINTR
) {
514 TRIVIA(("rel_client - destroying addr = (%p, %u %u)\n",
515 (void *) medc
->addr
.buf
, medc
->addr
.len
,
517 med_clnt_destroy(&medc
->client
);
518 if (medc
->addr
.buf
) {
519 kmem_free(medc
->addr
.buf
, medc
->addr
.maxlen
);
520 medc
->addr
.buf
= NULL
;
526 * Try to get the address for the desired service by using the old
527 * portmapper protocol. Ignores signals.
529 * Returns RPC_UNKNOWNPROTO if the request uses the loopback transport.
530 * Use med_get_rpcb_addr instead.
532 static enum clnt_stat
534 struct knetconfig
*kncfp
,
542 enum clnt_stat status
;
543 CLIENT
*client
= NULL
;
550 * Call rpcbind version 2 or earlier (SunOS portmapper, remote
551 * only) to get an address we can use in an RPC client handle.
552 * We simply obtain a port no. for <prog, vers> and plug it
555 if (strcmp(kncfp
->knc_protofmly
, NC_INET
) == 0) {
556 med_put_inet_port(addr
, htons(PMAPPORT
));
558 TRIVIA(("get_pmap_addr - unsupported protofmly %s\n",
559 kncfp
->knc_protofmly
));
560 status
= RPC_UNKNOWNPROTO
;
564 TRIVIA(("get_pmap_addr - semantics=%u, protofmly=%s, proto=%s\n",
565 kncfp
->knc_semantics
, kncfp
->knc_protofmly
, kncfp
->knc_proto
));
568 * Mask signals for the duration of the handle creation and
569 * RPC call. This allows relatively normal operation with a
570 * signal already posted to our thread.
572 * Any further exit paths from this routine must restore
573 * the original signal mask.
575 sigfillset(&newmask
);
576 sigreplace(&newmask
, &oldmask
);
578 if ((error
= clnt_tli_kcreate(kncfp
, addr
, PMAPPROG
, PMAPVERS
,
579 0, 0, kcred
, &client
)) != RPC_SUCCESS
) {
580 status
= RPC_TLIERROR
;
581 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
582 MINUTE(("get_pmap_addr - kcreate() returned %d\n", error
));
586 if (!CLNT_CONTROL(client
, CLSET_NODELAYONERR
, (char *)&clset
)) {
587 MINUTE(("get_pmap_addr - unable to set CLSET_NODELAYONERR\n"));
590 client
->cl_auth
= authkern_create();
592 parms
.pm_prog
= prog
;
593 parms
.pm_vers
= vers
;
594 if (strcmp(kncfp
->knc_proto
, NC_TCP
) == 0) {
595 parms
.pm_prot
= IPPROTO_TCP
;
597 parms
.pm_prot
= IPPROTO_UDP
;
600 tmo
= md_med_pmap_timeout
;
602 if ((status
= CLNT_CALL(client
, PMAPPROC_GETPORT
,
603 xdr_md_pmap
, (char *)&parms
,
604 xdr_u_short
, (char *)&port
,
605 tmo
)) != RPC_SUCCESS
) {
606 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
607 MINUTE(("get_pmap_addr - CLNT_CALL(GETPORT) returned %d\n",
612 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
614 /* A zero value of port indicates a mapping failure */
616 status
= RPC_PROGNOTREGISTERED
;
617 MINUTE(("get_pmap_addr - program not registered\n"));
621 TRIVIA(("get_pmap_addr - port=%d\n", port
));
622 med_put_inet_port(addr
, ntohs(port
));
626 med_clnt_destroy(&client
);
631 * Try to get the address for the desired service by using the rpcbind
632 * protocol. Ignores signals.
634 static enum clnt_stat
636 struct knetconfig
*kncfp
,
644 enum clnt_stat status
;
647 CLIENT
*client
= NULL
;
653 * Call rpcbind (local or remote) to get an address we can use
654 * in an RPC client handle.
656 tmo
= md_med_pmap_timeout
;
659 parms
.r_addr
= parms
.r_owner
= "";
661 if (strcmp(kncfp
->knc_protofmly
, NC_INET
) == 0) {
662 if (strcmp(kncfp
->knc_proto
, NC_TCP
) == 0) {
663 parms
.r_netid
= "tcp";
665 parms
.r_netid
= "udp";
667 med_put_inet_port(addr
, htons(PMAPPORT
));
668 } else if (strcmp(kncfp
->knc_protofmly
, NC_LOOPBACK
) == 0) {
669 parms
.r_netid
= "ticlts";
670 med_put_loopback_port(addr
, "rpc");
672 "get_rpcb_addr - semantics=%s, protofmly=%s, proto=%s\n",
673 (kncfp
->knc_semantics
== NC_TPI_CLTS
?
674 "NC_TPI_CLTS" : "?"),
675 kncfp
->knc_protofmly
, kncfp
->knc_proto
));
677 TRIVIA(("get_rpcb_addr - unsupported protofmly %s\n",
678 kncfp
->knc_protofmly
));
679 status
= RPC_UNKNOWNPROTO
;
684 * Mask signals for the duration of the handle creation and
685 * RPC calls. This allows relatively normal operation with a
686 * signal already posted to our thread.
688 * Any further exit paths from this routine must restore
689 * the original signal mask.
691 sigfillset(&newmask
);
692 sigreplace(&newmask
, &oldmask
);
694 if ((error
= clnt_tli_kcreate(kncfp
, addr
, RPCBPROG
, RPCBVERS
,
695 0, 0, kcred
, &client
)) != 0) {
696 status
= RPC_TLIERROR
;
697 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
698 MINUTE(("get_rpcb_addr - kcreate() returned %d\n", error
));
702 if (!CLNT_CONTROL(client
, CLSET_NODELAYONERR
, (char *)&clset
)) {
703 MINUTE(("get_rpcb_addr - unable to set CLSET_NODELAYONERR\n"));
706 client
->cl_auth
= authkern_create();
708 if ((status
= CLNT_CALL(client
, RPCBPROC_GETADDR
,
709 xdr_rpcb
, (char *)&parms
, xdr_wrapstring
, (char *)&ua
,
710 tmo
)) != RPC_SUCCESS
) {
711 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
712 MINUTE(("get_rpcb_addr - CLNT_CALL(GETADDR) returned %d\n",
717 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
719 if (ua
== NULL
|| *ua
== NULL
) {
720 status
= RPC_PROGNOTREGISTERED
;
721 MINUTE(("get_rpcb_addr - program not registered\n"));
726 * Convert the universal address to the transport address.
727 * Theoretically, we should call the local rpcbind to translate
728 * from the universal address to the transport address, but it gets
729 * complicated (e.g., there's no direct way to tell rpcbind that we
730 * want an IP address instead of a loopback address). Note that
731 * the transport address is potentially host-specific, so we can't
732 * just ask the remote rpcbind, because it might give us the wrong
735 if (strcmp(kncfp
->knc_protofmly
, NC_INET
) == 0) {
736 port
= rpc_uaddr2port(AF_INET
, ua
);
737 med_put_inet_port(addr
, ntohs(port
));
738 } else if (strcmp(kncfp
->knc_protofmly
, NC_LOOPBACK
) == 0) {
741 /* "can't happen" - should have been checked for above */
742 cmn_err(CE_PANIC
, "med_get_rpcb_addr: bad protocol family");
747 med_clnt_destroy(&client
);
749 xdr_free(xdr_wrapstring
, (char *)&ua
);
754 * Get the RPC client handle to talk to the service at addrp.
756 * RPC_SUCCESS Success.
757 * RPC_RPCBFAILURE Couldn't talk to the remote portmapper (e.g.,
759 * RPC_INTR Caught a signal before we could successfully return.
760 * RPC_TLIERROR Couldn't initialize the handle after talking to the
761 * remote portmapper (shouldn't happen).
763 static enum clnt_stat
765 struct knetconfig
*kncfp
,
766 struct netbuf
*addrp
,
772 enum clnt_stat status
;
778 * Try to get the address from either portmapper or rpcbind.
779 * We check for posted signals after trying and failing to
780 * contact the portmapper since it can take uncomfortably
781 * long for this entire procedure to time out.
784 status
= med_get_pmap_addr(kncfp
, prog
, vers
, addrp
);
785 if (MED_IS_UNRECOVERABLE_RPC(status
) && status
!= RPC_UNKNOWNPROTO
&&
786 ! PMAP_WRONG_VERSION(status
)) {
787 status
= RPC_RPCBFAILURE
;
791 if (status
== RPC_SUCCESS
)
792 ESTAMP("done OK med_get_pmap_addr")
794 ESTAMP("done Not OK med_get_pmap_addr")
796 if (status
!= RPC_SUCCESS
) {
798 status
= med_get_rpcb_addr(kncfp
, prog
, vers
, addrp
);
799 if (status
!= RPC_SUCCESS
) {
800 ESTAMP("done Not OK med_get_rpcb_addr")
802 "get_rpc_handle - can't contact portmapper or rpcbind\n"));
803 status
= RPC_RPCBFAILURE
;
807 ESTAMP("done OK med_get_rpcb_addr")
809 med_clnt_destroy(clientp
);
812 * Mask signals for the duration of the handle creation,
813 * allowing relatively normal operation with a signal
814 * already posted to our thread.
816 * Any further exit paths from this routine must restore
817 * the original signal mask.
819 sigfillset(&newmask
);
820 sigreplace(&newmask
, &oldmask
);
822 if ((error
= clnt_tli_kcreate(kncfp
, addrp
, prog
, vers
,
823 0, 0, kcred
, clientp
)) != 0) {
824 status
= RPC_TLIERROR
;
825 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
826 MINUTE(("get_rpc_handle - kcreate(prog) returned %d\n", error
));
830 if (!CLNT_CONTROL(*clientp
, CLSET_NODELAYONERR
, (char *)&clset
)) {
831 MINUTE(("get_rpc_handle - unable to set CLSET_NODELAYONERR\n"));
834 (*clientp
)->cl_auth
= authkern_create();
836 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
843 * Return a med_client to the <prog,vers>.
844 * The med_client found is marked as in_use.
845 * It is the responsibility of the caller to release the med_client by
846 * calling med_rel_client().
849 * RPC_SUCCESS Success.
850 * RPC_CANTSEND Temporarily cannot send.
851 * RPC_TLIERROR Unspecified TLI error.
852 * RPC_UNKNOWNPROTO kncfp is from an unrecognised protocol family.
853 * RPC_PROGNOTREGISTERED The prog `prog' isn't registered on the server.
854 * RPC_RPCBFAILURE Couldn't contact portmapper on remote host.
855 * Any unsuccessful return codes from CLNT_CALL().
857 static enum clnt_stat
859 struct knetconfig
*kncfp
,
860 struct netbuf
*addrp
,
863 struct med_client
**mcp
866 struct med_client
*med_clnt
= NULL
;
867 enum clnt_stat status
= RPC_SUCCESS
;
869 mutex_enter(&med_lck
);
872 * Create an med_client
874 med_clnt
= kmem_zalloc(sizeof (*med_clnt
), KM_SLEEP
);
875 med_clnt
->client
= NULL
;
876 med_clnt
->prog
= prog
;
877 med_clnt
->vers
= vers
;
878 med_clnt
->addr
.buf
= med_dup(addrp
->buf
, addrp
->maxlen
);
879 med_clnt
->addr
.len
= addrp
->len
;
880 med_clnt
->addr
.maxlen
= addrp
->maxlen
;
882 mutex_exit(&med_lck
);
884 status
= med_get_rpc_handle(kncfp
, &med_clnt
->addr
, prog
, vers
,
888 TRIVIA(("get_client - End: med_clnt=%p status=%d, client=%p\n",
889 (void *)med_clnt
, status
,
890 (med_clnt
? med_clnt
->client
: (void *) -1L)));
892 if (status
== RPC_SUCCESS
) {
897 mutex_enter(&med_lck
);
898 med_rel_client(med_clnt
, EINVAL
);
899 kmem_free(med_clnt
, sizeof (*med_clnt
));
900 mutex_exit(&med_lck
);
909 * Make an RPC call to addr via config.
913 * EIO Couldn't get client handle, timed out, or got unexpected
914 * RPC status within md_med_protocol_retry attempts.
915 * EINVAL Unrecoverable error in RPC call. Causes client handle
917 * EINTR RPC call was interrupted within md_med_protocol_retry attempts.
921 struct knetconfig
*kncfp
,
922 struct netbuf
*addrp
,
930 struct timeval
*timout
933 struct med_client
*med_clnt
= NULL
;
934 enum clnt_stat cl_stat
;
935 int tries
= md_med_protocol_retry
;
940 MINUTE(("med_callrpc - Calling [%u, %u, %u]\n", prog
, vers
, proc
));
942 sigfillset(&newmask
);
946 cl_stat
= med_get_client(kncfp
, addrp
, prog
, vers
, &med_clnt
);
947 if (MED_IS_UNRECOVERABLE_RPC(cl_stat
)) {
950 } else if (cl_stat
!= RPC_SUCCESS
) {
955 ASSERT(med_clnt
!= NULL
);
956 ASSERT(med_clnt
->client
!= NULL
);
958 sigreplace(&newmask
, &oldmask
);
959 cl_stat
= CLNT_CALL(med_clnt
->client
, proc
, inproc
, in
,
960 outproc
, out
, *timout
);
961 sigreplace(&oldmask
, (k_sigset_t
*)NULL
);
966 * Update the timestamp on the client cache entry.
972 MINOR(("med_callrpc - RPC_TIMEDOUT\n"));
975 * We will always time out when timout == 0.
984 if (MED_IS_UNRECOVERABLE_RPC(cl_stat
)) {
992 MINOR(("med_callrpc - RPC cl_stat=%d error=%d\n",
994 if (med_clnt
!= NULL
) {
995 med_rel_client(med_clnt
, error
);
996 kmem_free(med_clnt
, sizeof (*med_clnt
));
1000 * If EIO, loop else we're done.
1007 MINUTE(("med_callrpc - End: error=%d, tries=%d\n", error
, tries
));
1013 * Try various transports to get the rpc call through.
1027 struct timeval
*timout
1031 struct med_addr
*uap
;
1036 ASSERT(h_nm
!= NULL
);
1040 * Loop through our table of transports and try to get the data out.
1042 for (uapi
= 0; uapi
< med_addr_tab_nents
&& ! done
; uapi
++) {
1045 uap
= &med_addr_tab
[uapi
];
1048 * UAFLG_SKIP is used for debugging and by the protocol
1051 if (uap
->ua_flags
& UAFLG_SKIP
) {
1052 MINUTE(("med_net_callrpc - %s - marked \"skip\"\n",
1058 * If we are not talking to this host, we can skip all LOOPBACK
1059 * transport options.
1061 if (! (h_flags
& NMIP_F_LOCAL
) &&
1062 (uap
->ua_flags
& UAFLG_LOOPBACK
))
1065 if (uap
->ua_flags
& UAFLG_ERROR
)
1068 if (uap
->ua_flags
& UAFLG_RPCERROR
)
1071 /* Unknown protocol, skip it */
1072 if (! uap
->ua_kn
.knc_protofmly
) {
1073 MINUTE(("med_net_callrpc - bad protofmly\n"));
1077 if (strcmp(uap
->ua_kn
.knc_protofmly
, NC_LOOPBACK
) == 0) {
1079 * strlen("localhost.") is 10
1081 dst
.len
= dst
.maxlen
= 10;
1082 dst
.buf
= kmem_alloc(dst
.len
, KM_SLEEP
);
1083 (void) strncpy(dst
.buf
, "localhost.", dst
.len
);
1084 } else if (strcmp(uap
->ua_kn
.knc_protofmly
, NC_INET
) == 0) {
1085 struct sockaddr_in
*s
;
1088 * If we have not allocated a buffer for an INET addrs
1089 * or the buffer allocated will not contain an INET
1090 * addr, allocate or re-allocate.
1092 dst
.buf
= kmem_zalloc(sizeof (struct sockaddr_in
),
1094 dst
.maxlen
= sizeof (struct sockaddr_in
);
1098 s
= (struct sockaddr_in
*)dst
.buf
;
1100 /* Initialize the socket */
1101 if (uap
->ua_flags
& UAFLG_LOOPBACK
)
1102 s
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1104 s
->sin_addr
.s_addr
= h_ip
;
1106 s
->sin_family
= AF_INET
;
1109 dst
.len
= dst
.maxlen
;
1111 MINOR(("med_net_callrpc - Trying %s\n", uap
->ua_netid
));
1113 err
= med_callrpc(&uap
->ua_kn
, &dst
, prog
, vers
, proc
, inproc
,
1114 in
, outproc
, out
, timout
);
1117 kmem_free(dst
.buf
, dst
.maxlen
);
1124 MINUTE(("med_net_callrpc - %s failed\n\n",
1129 MINUTE(("med_net_callrpc - %s OK\n\n", uap
->ua_netid
));
1134 * Print a message if we could not reach a host.
1137 cmn_err(CE_WARN
, "%s on host %s not responding", MED_SERVNAME
,
1146 * Validate the mediator data
1149 med_ok(set_t setno
, med_data_t
*meddp
)
1151 /* Not initialized, or not a mediator data record */
1152 if (meddp
->med_dat_mag
!= MED_DATA_MAGIC
)
1155 MINUTE(("Magic OK\n"));
1157 /* Mismatch in revisions */
1158 if (meddp
->med_dat_rev
!= MED_DATA_REV
)
1161 MINUTE(("Revision OK\n"));
1163 /* Not for the right set, this is paranoid */
1164 if (setno
!= meddp
->med_dat_sn
)
1167 MINUTE(("Setno OK\n"));
1169 /* The record checksum is not correct */
1170 if (crcchk(meddp
, &meddp
->med_dat_cks
, sizeof (med_data_t
), NULL
))
1173 MINUTE(("Mediator validated\n"));
1182 med_adl(med_data_lst_t
**meddlpp
, med_data_t
*meddp
)
1185 * Run to the end of the list
1187 for (/* void */; (*meddlpp
!= NULL
); meddlpp
= &(*meddlpp
)->mdl_nx
)
1190 *meddlpp
= (med_data_lst_t
*)kmem_zalloc(sizeof (med_data_lst_t
),
1193 (*meddlpp
)->mdl_med
= (med_data_t
*)med_dup(meddp
, sizeof (med_data_t
));
1197 mtaa_upd_init(med_thr_a_args_t
*mtaap
, med_thr_h_args_t
*mthap
)
1199 med_upd_data_args_t
*argsp
;
1202 argsp
= kmem_zalloc(sizeof (med_upd_data_args_t
), KM_SLEEP
);
1203 argsp
->med
.med_setno
= mthap
->mtha_setno
;
1204 if (MD_MNSET_SETNO(argsp
->med
.med_setno
)) {
1206 * In MN diskset, use a generic nodename, multiowner, in the
1207 * mediator record which allows any node to access mediator
1208 * information. MN diskset reconfig cycle forces consistent
1209 * view of set/node/drive/mediator information across all nodes
1210 * in the MN diskset. This allows the relaxation of
1211 * node name checking in rpc.metamedd for MN disksets.
1213 argsp
->med
.med_caller
= md_strdup(MED_MN_CALLER
);
1215 argsp
->med
.med_caller
= md_strdup(utsname
.nodename
);
1217 argsp
->med
.med_setname
= md_strdup(mthap
->mtha_setname
);
1218 argsp
->med_data
= *mthap
->mtha_meddp
;
1220 resp
= kmem_zalloc(sizeof (med_err_t
), KM_SLEEP
);
1222 mtaap
->mtaa_mag
= MTAA_MAGIC
;
1223 mtaap
->mtaa_mthap
= mthap
;
1224 mtaap
->mtaa_prog
= MED_PROG
;
1225 mtaap
->mtaa_vers
= MED_VERS
;
1226 mtaap
->mtaa_proc
= MED_UPD_DATA
;
1227 mtaap
->mtaa_inproc
= xdr_med_upd_data_args_t
;
1228 mtaap
->mtaa_in
= (caddr_t
)argsp
;
1229 mtaap
->mtaa_outproc
= xdr_med_err_t
;
1230 mtaap
->mtaa_out
= (caddr_t
)resp
;
1231 mtaap
->mtaa_timout
= (struct timeval
*)&md_med_def_timeout
;
1235 mtaa_upd_free(med_thr_a_args_t
*mtaap
)
1237 med_upd_data_args_t
*argsp
= (med_upd_data_args_t
*)mtaap
->mtaa_in
;
1238 med_err_t
*resp
= (med_err_t
*)mtaap
->mtaa_out
;
1240 freestr(argsp
->med
.med_caller
);
1241 freestr(argsp
->med
.med_setname
);
1242 kmem_free(argsp
, sizeof (med_upd_data_args_t
));
1244 if (mtaap
->mtaa_flags
& MDT_A_OK
)
1245 xdr_free(mtaap
->mtaa_outproc
, mtaap
->mtaa_out
);
1247 kmem_free(resp
, sizeof (med_err_t
));
1251 mtaa_upd_err(med_thr_a_args_t
*mtaap
)
1254 med_err_t
*resp
= (med_err_t
*)mtaap
->mtaa_out
;
1256 if (resp
->med_errno
== MDE_MED_NOERROR
) {
1257 MAJOR(("upd_med_hosts - %s - OK\n\n", mtaap
->mtaa_h_nm
));
1260 MAJOR(("upd_med_hosts - %s - errno=%d\n\n", mtaap
->mtaa_h_nm
,
1267 mtaa_get_init(med_thr_a_args_t
*mtaap
, med_thr_h_args_t
*mthap
)
1270 med_get_data_res_t
*resp
;
1272 argsp
= kmem_zalloc(sizeof (med_args_t
), KM_SLEEP
);
1273 argsp
->med
.med_setno
= mthap
->mtha_setno
;
1274 if (MD_MNSET_SETNO(argsp
->med
.med_setno
)) {
1276 * In MN diskset, use a generic nodename, multiowner, in the
1277 * mediator record which allows any node to access mediator
1278 * information. MN diskset reconfig cycle forces consistent
1279 * view of set/node/drive/mediator information across all nodes
1280 * in the MN diskset. This allows the relaxation of
1281 * node name checking in rpc.metamedd for MN disksets.
1283 argsp
->med
.med_caller
= md_strdup(MED_MN_CALLER
);
1285 argsp
->med
.med_caller
= md_strdup(utsname
.nodename
);
1288 argsp
->med
.med_setname
= md_strdup(mthap
->mtha_setname
);
1290 resp
= kmem_zalloc(sizeof (med_get_data_res_t
), KM_SLEEP
);
1292 mtaap
->mtaa_mag
= MTAA_MAGIC
;
1293 mtaap
->mtaa_mthap
= mthap
;
1294 mtaap
->mtaa_prog
= MED_PROG
;
1295 mtaap
->mtaa_vers
= MED_VERS
;
1296 mtaap
->mtaa_proc
= MED_GET_DATA
;
1297 mtaap
->mtaa_inproc
= xdr_med_args_t
;
1298 mtaap
->mtaa_in
= (caddr_t
)argsp
;
1299 mtaap
->mtaa_outproc
= xdr_med_get_data_res_t
;
1300 mtaap
->mtaa_out
= (caddr_t
)resp
;
1301 mtaap
->mtaa_timout
= (struct timeval
*)&md_med_def_timeout
;
1305 mtaa_get_free(med_thr_a_args_t
*mtaap
)
1308 med_args_t
*argsp
= (med_args_t
*)mtaap
->mtaa_in
;
1310 med_get_data_res_t
*resp
= (med_get_data_res_t
*)mtaap
->mtaa_out
;
1312 freestr(argsp
->med
.med_caller
);
1313 freestr(argsp
->med
.med_setname
);
1314 kmem_free(argsp
, sizeof (med_args_t
));
1316 if (mtaap
->mtaa_flags
& MDT_A_OK
)
1317 xdr_free(mtaap
->mtaa_outproc
, mtaap
->mtaa_out
);
1319 kmem_free(resp
, sizeof (med_get_data_res_t
));
1323 mtaa_get_err(med_thr_a_args_t
*mtaap
)
1326 med_get_data_res_t
*resp
= (med_get_data_res_t
*)mtaap
->mtaa_out
;
1328 if (resp
->med_status
.med_errno
== MDE_MED_NOERROR
) {
1329 MAJOR(("get_med_host_data - %s - OK\n\n", mtaap
->mtaa_h_nm
));
1332 MAJOR(("get_med_host_data - %s - errno=%d\n\n",
1333 mtaap
->mtaa_h_nm
, resp
->med_status
.med_errno
));
1341 med_thr_h_args_t
*mthap
,
1346 void (*mtaa_init_func
)(med_thr_a_args_t
*,
1347 med_thr_h_args_t
*),
1348 int (*mtaa_err_func
)(med_thr_a_args_t
*)
1353 mthap
->mtha_mag
= MTHA_MAGIC
;
1354 mthap
->mtha_mtp
= mtp
;
1355 mthap
->mtha_mhp
= mhp
;
1356 mthap
->mtha_setname
= md_strdup(setname
);
1358 mthap
->mtha_meddp
= meddp
;
1360 mthap
->mtha_meddp
= NULL
;
1361 mthap
->mtha_setno
= setno
;
1362 mthap
->mtha_a_cnt
= mhp
->a_cnt
;
1363 mthap
->mtha_a_nthr
= 0;
1365 mutex_init(&mthap
->mtha_a_mx
, NULL
, MUTEX_DEFAULT
,
1367 cv_init(&mthap
->mtha_a_cv
, NULL
, CV_DEFAULT
, NULL
);
1369 j
= MIN(mthap
->mtha_a_cnt
, MAX_HOST_ADDRS
) - 1;
1370 for (; j
>= 0; j
--) {
1371 (*mtaa_init_func
)(&mthap
->mtha_a_args
[j
], mthap
);
1372 mthap
->mtha_a_args
[j
].mtaa_h_nm
= mhp
->a_nm
[j
];
1373 mthap
->mtha_a_args
[j
].mtaa_h_ip
= mhp
->a_ip
[j
];
1374 mthap
->mtha_a_args
[j
].mtaa_h_flags
= mhp
->a_flg
;
1375 mthap
->mtha_a_args
[j
].mtaa_err_func
= mtaa_err_func
;
1381 med_thr_h_args_t
*mthap
,
1382 void (*mtaa_free_func
)(med_thr_a_args_t
*)
1387 freestr(mthap
->mtha_setname
);
1389 j
= MIN(mthap
->mtha_a_cnt
, MAX_HOST_ADDRS
) - 1;
1391 (*mtaa_free_func
)(&mthap
->mtha_a_args
[j
]);
1393 mutex_destroy(&mthap
->mtha_a_mx
);
1394 cv_destroy(&mthap
->mtha_a_cv
);
1398 med_a_thr(med_thr_a_args_t
*mtaap
)
1400 callb_cpr_t cprinfo
;
1403 * Register cpr callback
1405 CALLB_CPR_INIT(&cprinfo
, &mtaap
->mtaa_mthap
->mtha_a_mx
,
1406 callb_generic_cpr
, "med_a_thr");
1408 mutex_enter(&mtaap
->mtaa_mthap
->mtha_a_mx
);
1409 if (mtaap
->mtaa_mthap
->mtha_flags
& MDT_H_OK
)
1412 mutex_exit(&mtaap
->mtaa_mthap
->mtha_a_mx
);
1414 mtaap
->mtaa_err
= med_net_callrpc(
1415 mtaap
->mtaa_h_nm
, mtaap
->mtaa_h_ip
, mtaap
->mtaa_h_flags
,
1416 mtaap
->mtaa_prog
, mtaap
->mtaa_vers
, mtaap
->mtaa_proc
,
1417 mtaap
->mtaa_inproc
, mtaap
->mtaa_in
,
1418 mtaap
->mtaa_outproc
, mtaap
->mtaa_out
,
1419 mtaap
->mtaa_timout
);
1421 mutex_enter(&mtaap
->mtaa_mthap
->mtha_a_mx
);
1423 if (mtaap
->mtaa_err
) {
1424 MAJOR(("med_net_callrpc(%u, %u, %u) - %s - failed\n\n",
1425 mtaap
->mtaa_prog
, mtaap
->mtaa_vers
, mtaap
->mtaa_proc
,
1427 xdr_free(mtaap
->mtaa_outproc
, mtaap
->mtaa_out
);
1429 if ((*mtaap
->mtaa_err_func
)(mtaap
) == 0) {
1430 if (! (mtaap
->mtaa_mthap
->mtha_flags
& MDT_H_OK
)) {
1431 mtaap
->mtaa_mthap
->mtha_flags
|= MDT_H_OK
;
1432 mtaap
->mtaa_flags
|= MDT_A_OK
;
1434 xdr_free(mtaap
->mtaa_outproc
, mtaap
->mtaa_out
);
1436 xdr_free(mtaap
->mtaa_outproc
, mtaap
->mtaa_out
);
1440 mtaap
->mtaa_mthap
->mtha_a_nthr
--;
1441 cv_signal(&mtaap
->mtaa_mthap
->mtha_a_cv
);
1444 * CALLB_CPR_EXIT will do mutex_exit(&mtaap->mtaa_mthap->mtha_a_mx)
1446 CALLB_CPR_EXIT(&cprinfo
);
1451 med_h_thr(med_thr_h_args_t
*mthap
)
1454 callb_cpr_t cprinfo
;
1457 * Register cpr callback
1459 CALLB_CPR_INIT(&cprinfo
, &mthap
->mtha_mtp
->mt_mx
, callb_generic_cpr
,
1462 * Lock mthap->mtha_mtp->mt_mx is held early to avoid releasing the
1463 * locks out of order.
1465 mutex_enter(&mthap
->mtha_mtp
->mt_mx
);
1466 mutex_enter(&mthap
->mtha_a_mx
);
1468 j
= MIN(mthap
->mtha_a_cnt
, MAX_HOST_ADDRS
) - 1;
1469 for (; j
>= 0; j
--) {
1470 (void) thread_create(NULL
, 0, med_a_thr
,
1471 &mthap
->mtha_a_args
[j
], 0, &p0
, TS_RUN
, minclsyspri
);
1472 mthap
->mtha_a_nthr
++;
1476 * cpr safe to suspend while waiting for other threads
1478 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
1479 while (mthap
->mtha_a_nthr
> 0)
1480 cv_wait(&mthap
->mtha_a_cv
, &mthap
->mtha_a_mx
);
1481 mutex_exit(&mthap
->mtha_a_mx
);
1482 CALLB_CPR_SAFE_END(&cprinfo
, &mthap
->mtha_mtp
->mt_mx
);
1485 mthap
->mtha_mtp
->mt_nthr
--;
1486 cv_signal(&mthap
->mtha_mtp
->mt_cv
);
1490 * CALLB_CPR_EXIT will do mutex_exit(&mtaap->mta_mtp->mt_mx)
1492 CALLB_CPR_EXIT(&cprinfo
);
1496 static med_get_data_res_t
*
1497 mtaa_get_resp(med_thr_h_args_t
*mthap
)
1499 med_thr_a_args_t
*mtaap
;
1502 j
= MIN(mthap
->mtha_a_cnt
, MAX_HOST_ADDRS
) - 1;
1503 for (; j
>= 0; j
--) {
1504 mtaap
= &mthap
->mtha_a_args
[j
];
1505 if (mtaap
->mtaa_flags
& MDT_A_OK
)
1507 return ((med_get_data_res_t
*)mtaap
->mtaa_out
);
1509 return ((med_get_data_res_t
*)NULL
);
1517 * initializes med structs, locks, etc
1524 TRIVIA(("[med_init"));
1526 for (uapi
= 0; uapi
< med_addr_tab_nents
; uapi
++) {
1527 struct med_addr
*uap
= &med_addr_tab
[uapi
];
1529 /* If the protocol is skipped, the mutex is not needed either */
1530 if (md_med_trans_lst
!= NULL
&&
1531 strstr(md_med_trans_lst
, uap
->ua_kn
.knc_proto
) == NULL
&&
1532 strstr(md_med_trans_lst
, uap
->ua_netid
) == NULL
) {
1533 uap
->ua_flags
|= UAFLG_SKIP
;
1537 mutex_init(&uap
->ua_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
1538 uap
->ua_flags
|= UAFLG_LOCKINIT
;
1539 bzero((caddr_t
)&uap
->ua_kn
.knc_unused
,
1540 sizeof (uap
->ua_kn
.knc_unused
));
1547 * free any med structs, locks, etc
1554 TRIVIA(("[med_fini"));
1556 for (uapi
= 0; uapi
< med_addr_tab_nents
; uapi
++) {
1557 struct med_addr
*uap
= &med_addr_tab
[uapi
];
1559 if (uap
->ua_flags
& UAFLG_LOCKINIT
) {
1560 mutex_destroy(&uap
->ua_mutex
);
1561 uap
->ua_flags
&= ~UAFLG_LOCKINIT
;
1569 * Update all the mediators
1580 med_thr_h_args_t
*mthap
;
1584 MAJOR(("upd_med_hosts - called from <%s>\n", NULLSTR(caller
)));
1586 /* No mediators, were done */
1590 mtp
= kmem_zalloc(sizeof (med_thr_t
), KM_SLEEP
);
1591 ASSERT(mtp
!= NULL
);
1593 mutex_init(&mtp
->mt_mx
, NULL
, MUTEX_DEFAULT
, NULL
);
1594 cv_init(&mtp
->mt_cv
, NULL
, CV_DEFAULT
, NULL
);
1595 mtp
->mt_mag
= MTH_MAGIC
;
1597 mutex_enter(&mtp
->mt_mx
);
1601 /* Loop through our list of mediator hosts, start a thread per host */
1602 for (i
= 0; i
< md_nmedh
; i
++) {
1604 if (mp
->n_lst
[i
].a_cnt
== 0)
1607 mtp
->mt_h_args
[i
] = kmem_zalloc(sizeof (med_thr_h_args_t
),
1609 mthap
= mtp
->mt_h_args
[i
];
1610 ASSERT(mthap
!= NULL
);
1611 mtha_init(mtp
, mthap
, &mp
->n_lst
[i
], setname
, meddp
,
1612 meddp
->med_dat_sn
, mtaa_upd_init
, mtaa_upd_err
);
1614 MAJOR(("upd_med_hosts - updating %s\n",
1615 NULLSTR(mp
->n_lst
[i
].a_nm
[0])));
1617 (void) thread_create(NULL
, 0, med_h_thr
, mthap
, 0, &p0
,
1618 TS_RUN
, minclsyspri
);
1623 while (mtp
->mt_nthr
> 0)
1624 cv_wait(&mtp
->mt_cv
, &mtp
->mt_mx
);
1626 mutex_exit(&mtp
->mt_mx
);
1628 for (i
= 0; i
< md_nmedh
; i
++) {
1629 mthap
= mtp
->mt_h_args
[i
];
1630 if (mthap
!= NULL
) {
1631 if (mthap
->mtha_flags
& MDT_H_OK
)
1633 mtha_free(mthap
, mtaa_upd_free
);
1634 kmem_free(mthap
, sizeof (med_thr_h_args_t
));
1638 mutex_destroy(&mtp
->mt_mx
);
1639 cv_destroy(&mtp
->mt_cv
);
1641 kmem_free(mtp
, sizeof (med_thr_t
));
1647 * Get the mediator data.
1657 med_thr_h_args_t
*mthap
;
1658 med_get_data_res_t
*resp
;
1659 med_data_lst_t
*retval
= NULL
;
1662 /* No mediators, were done */
1666 mtp
= kmem_zalloc(sizeof (med_thr_t
), KM_SLEEP
);
1667 ASSERT(mtp
!= NULL
);
1669 mutex_init(&mtp
->mt_mx
, NULL
, MUTEX_DEFAULT
, NULL
);
1670 cv_init(&mtp
->mt_cv
, NULL
, CV_DEFAULT
, NULL
);
1672 mutex_enter(&mtp
->mt_mx
);
1676 /* Loop through our list of mediator hosts, start a thread per host */
1677 for (i
= 0; i
< md_nmedh
; i
++) {
1679 if (mp
->n_lst
[i
].a_cnt
== 0)
1682 mtp
->mt_h_args
[i
] = kmem_zalloc(sizeof (med_thr_h_args_t
),
1684 mthap
= mtp
->mt_h_args
[i
];
1685 ASSERT(mthap
!= NULL
);
1686 mtha_init(mtp
, mthap
, &mp
->n_lst
[i
], setname
, NULL
, setno
,
1687 mtaa_get_init
, mtaa_get_err
);
1689 MAJOR(("get_med_host_data from %s\n",
1690 NULLSTR(mp
->n_lst
[i
].a_nm
[0])));
1692 (void) thread_create(NULL
, 0, med_h_thr
, mthap
, 0, &p0
,
1693 TS_RUN
, minclsyspri
);
1698 while (mtp
->mt_nthr
> 0)
1699 cv_wait(&mtp
->mt_cv
, &mtp
->mt_mx
);
1701 mutex_exit(&mtp
->mt_mx
);
1703 for (i
= 0; i
< md_nmedh
; i
++) {
1704 mthap
= mtp
->mt_h_args
[i
];
1705 if (mthap
!= NULL
) {
1706 if (mthap
->mtha_flags
& MDT_H_OK
) {
1707 resp
= mtaa_get_resp(mthap
);
1708 ASSERT(resp
!= NULL
);
1710 if (med_ok(setno
, &resp
->med_data
))
1711 med_adl(&retval
, &resp
->med_data
);
1713 mtha_free(mthap
, mtaa_get_free
);
1714 kmem_free(mthap
, sizeof (med_thr_h_args_t
));
1718 mutex_destroy(&mtp
->mt_mx
);
1719 cv_destroy(&mtp
->mt_cv
);
1721 kmem_free(mtp
, sizeof (med_thr_t
));
1727 med_get_t_size_ioctl(mddb_med_t_parm_t
*tpp
, int mode
)
1729 md_error_t
*ep
= &tpp
->med_tp_mde
;
1733 if ((mode
& FREAD
) == 0)
1734 return (mdsyserror(ep
, EACCES
));
1736 tpp
->med_tp_nents
= med_addr_tab_nents
;
1737 tpp
->med_tp_setup
= md_med_transdevs_set
;
1743 med_get_t_ioctl(mddb_med_t_parm_t
*tpp
, int mode
)
1745 md_error_t
*ep
= &tpp
->med_tp_mde
;
1750 if ((mode
& FREAD
) == 0)
1751 return (mdsyserror(ep
, EACCES
));
1753 for (uapi
= 0; uapi
< med_addr_tab_nents
; uapi
++) {
1754 struct med_addr
*uap
= &med_addr_tab
[uapi
];
1756 (void) strncpy(tpp
->med_tp_ents
[uapi
].med_te_nm
,
1757 uap
->ua_devname
, MED_TE_NM_LEN
);
1758 tpp
->med_tp_ents
[uapi
].med_te_dev
=
1759 (md_dev64_t
)uap
->ua_kn
.knc_rdev
;
1762 tpp
->med_tp_nents
= med_addr_tab_nents
;
1768 med_set_t_ioctl(mddb_med_t_parm_t
*tpp
, int mode
)
1770 md_error_t
*ep
= &tpp
->med_tp_mde
;
1775 if ((mode
& FWRITE
) == 0)
1776 return (mdsyserror(ep
, EACCES
));
1778 for (uapi
= 0; uapi
< med_addr_tab_nents
; uapi
++) {
1779 struct med_addr
*uap
= &med_addr_tab
[uapi
];
1781 mutex_enter(&uap
->ua_mutex
);
1782 uap
->ua_kn
.knc_rdev
= md_dev64_to_dev(
1783 tpp
->med_tp_ents
[uapi
].med_te_dev
);
1784 mutex_exit(&uap
->ua_mutex
);
1787 md_med_transdevs_set
= 1;