xref: /onnv-gate/usr/src/uts/common/io/lvm/md/md_med.c (revision 7387:0b3a92e31fd8)
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 *
med_dup(void * str,int len)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
med_put_inet_port(struct netbuf * addr,ushort_t port)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
med_put_loopback_port(struct netbuf * addr,char * port)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
grow_netbuf(struct netbuf * nb,size_t length)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
loopb_u2t(const char * ua,struct netbuf * addr)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
xdr_md_pmap(xdrs,regs)470 xdr_md_pmap(xdrs, regs)
471 	XDR *xdrs;
472 	struct pmap *regs;
473 {
474 	if (xdr_u_int(xdrs, &regs->pm_prog) &&
475 		xdr_u_int(xdrs, &regs->pm_vers) &&
476 		xdr_u_int(xdrs, &regs->pm_prot))
477 		return (xdr_u_int(xdrs, &regs->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
med_clnt_destroy(CLIENT ** clp)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
med_rel_client(struct med_client * medc,int error)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
med_get_pmap_addr(struct knetconfig * kncfp,rpcprog_t prog,rpcvers_t vers,struct netbuf * addr)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
med_get_rpcb_addr(struct knetconfig * kncfp,rpcprog_t prog,rpcvers_t vers,struct netbuf * addr)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
med_get_rpc_handle(struct knetconfig * kncfp,struct netbuf * addrp,rpcprog_t prog,rpcvers_t vers,CLIENT ** clientp)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
med_get_client(struct knetconfig * kncfp,struct netbuf * addrp,rpcprog_t prog,rpcvers_t vers,struct med_client ** mcp)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
med_callrpc(struct knetconfig * kncfp,struct netbuf * addrp,rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t inproc,caddr_t in,xdrproc_t outproc,caddr_t out,struct timeval * timout)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
med_net_callrpc(char * h_nm,in_addr_t h_ip,uint_t h_flags,rpcprog_t prog,rpcvers_t vers,rpcproc_t proc,xdrproc_t inproc,caddr_t in,xdrproc_t outproc,caddr_t out,struct timeval * timout)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
med_ok(set_t setno,med_data_t * meddp)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
med_adl(med_data_lst_t ** meddlpp,med_data_t * meddp)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
mtaa_upd_init(med_thr_a_args_t * mtaap,med_thr_h_args_t * mthap)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
mtaa_upd_free(med_thr_a_args_t * mtaap)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
mtaa_upd_err(med_thr_a_args_t * mtaap)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
mtaa_get_init(med_thr_a_args_t * mtaap,med_thr_h_args_t * mthap)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
mtaa_get_free(med_thr_a_args_t * mtaap)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
mtaa_get_err(med_thr_a_args_t * mtaap)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
mtha_init(med_thr_t * mtp,med_thr_h_args_t * mthap,md_hi_t * mhp,char * setname,med_data_t * meddp,set_t setno,void (* mtaa_init_func)(med_thr_a_args_t *,med_thr_h_args_t *),int (* mtaa_err_func)(med_thr_a_args_t *))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
mtha_free(med_thr_h_args_t * mthap,void (* mtaa_free_func)(med_thr_a_args_t *))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
med_a_thr(med_thr_a_args_t * mtaap)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
med_h_thr(med_thr_h_args_t * mthap)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 *
mtaa_get_resp(med_thr_h_args_t * mthap)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
med_init(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
med_fini(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
upd_med_hosts(md_hi_arr_t * mp,char * setname,med_data_t * meddp,char * caller)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 *
get_med_host_data(md_hi_arr_t * mp,char * setname,set_t setno)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
med_get_t_size_ioctl(mddb_med_t_parm_t * tpp,int mode)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
med_get_t_ioctl(mddb_med_t_parm_t * tpp,int mode)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
med_set_t_ioctl(mddb_med_t_parm_t * tpp,int mode)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