xref: /onnv-gate/usr/src/uts/common/avs/ns/rdc/rdc_clnt.c (revision 10715:b905b416f22e)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
229093SRamana.Srikanth@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM /* Network data replicator Client side */
277836SJohn.Forte@Sun.COM 
287836SJohn.Forte@Sun.COM 
297836SJohn.Forte@Sun.COM #include <sys/types.h>
307836SJohn.Forte@Sun.COM #include <sys/debug.h>
317836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
327836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
337836SJohn.Forte@Sun.COM #include <sys/kmem.h>
347836SJohn.Forte@Sun.COM #include <sys/cred.h>
357836SJohn.Forte@Sun.COM #include <sys/byteorder.h>
367836SJohn.Forte@Sun.COM #include <sys/errno.h>
377836SJohn.Forte@Sun.COM 
387836SJohn.Forte@Sun.COM #ifdef _SunOS_2_6
397836SJohn.Forte@Sun.COM /*
407836SJohn.Forte@Sun.COM  * on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
417836SJohn.Forte@Sun.COM  * define enum_t here as it is all we need from rpc/types.h
427836SJohn.Forte@Sun.COM  * anyway and make it look like we included it. Yuck.
437836SJohn.Forte@Sun.COM  */
447836SJohn.Forte@Sun.COM #define	_RPC_TYPES_H
457836SJohn.Forte@Sun.COM typedef int enum_t;
467836SJohn.Forte@Sun.COM #else
477836SJohn.Forte@Sun.COM #ifndef DS_DDICT
487836SJohn.Forte@Sun.COM #include <rpc/types.h>
497836SJohn.Forte@Sun.COM #endif
507836SJohn.Forte@Sun.COM #endif /* _SunOS_2_6 */
517836SJohn.Forte@Sun.COM 
527836SJohn.Forte@Sun.COM #ifndef DS_DDICT
537836SJohn.Forte@Sun.COM #include <rpc/auth.h>
547836SJohn.Forte@Sun.COM #include <rpc/svc.h>
557836SJohn.Forte@Sun.COM #include <rpc/xdr.h>
567836SJohn.Forte@Sun.COM #endif
577836SJohn.Forte@Sun.COM #include <sys/ddi.h>
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
607836SJohn.Forte@Sun.COM #ifdef DS_DDICT
617836SJohn.Forte@Sun.COM #include <sys/nsctl/contract.h>
627836SJohn.Forte@Sun.COM #endif
637836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
647836SJohn.Forte@Sun.COM 
657836SJohn.Forte@Sun.COM #include <sys/sdt.h>		/* dtrace is S10 or later */
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM #include "rdc_io.h"
687836SJohn.Forte@Sun.COM #include "rdc_clnt.h"
697836SJohn.Forte@Sun.COM #include "rdc_bitmap.h"
707836SJohn.Forte@Sun.COM #include "rdc_diskq.h"
717836SJohn.Forte@Sun.COM 
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM kmutex_t rdc_clnt_lock;
747836SJohn.Forte@Sun.COM 
757836SJohn.Forte@Sun.COM #ifdef DEBUG
767836SJohn.Forte@Sun.COM int noflush = 0;
777836SJohn.Forte@Sun.COM #endif
787836SJohn.Forte@Sun.COM 
797836SJohn.Forte@Sun.COM int rdc_rpc_tmout = RDC_CLNT_TMOUT;
807836SJohn.Forte@Sun.COM static void rdc_clnt_free(struct chtab *, CLIENT *);
817836SJohn.Forte@Sun.COM static void _rdc_remote_flush(rdc_aio_t *);
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM void rdc_flush_memq(int index);
847836SJohn.Forte@Sun.COM void rdc_flush_diskq(int index);
857836SJohn.Forte@Sun.COM int rdc_drain_net_queue(int index);
867836SJohn.Forte@Sun.COM void rdc_flusher_thread(int index);
877836SJohn.Forte@Sun.COM int  rdc_diskq_enqueue(rdc_k_info_t *krdc, rdc_aio_t *);
887836SJohn.Forte@Sun.COM void rdc_init_diskq_header(rdc_group_t *grp, dqheader *hd);
897836SJohn.Forte@Sun.COM void rdc_dump_iohdrs(disk_queue *dq);
907836SJohn.Forte@Sun.COM rdc_aio_t *rdc_dequeue(rdc_k_info_t *krdc, int *rc);
917836SJohn.Forte@Sun.COM void rdc_clr_iohdr(rdc_k_info_t *krdc, nsc_off_t qpos);
927836SJohn.Forte@Sun.COM void rdc_close_diskq(rdc_group_t *krdc);
937836SJohn.Forte@Sun.COM 
947836SJohn.Forte@Sun.COM int rdc_writer(int index);
957836SJohn.Forte@Sun.COM 
967836SJohn.Forte@Sun.COM static struct chtab *rdc_chtable = NULL;
977836SJohn.Forte@Sun.COM static int rdc_clnt_toomany;
987836SJohn.Forte@Sun.COM #ifdef DEBUG
997836SJohn.Forte@Sun.COM static int rdc_ooreply;
1007836SJohn.Forte@Sun.COM #endif
1017836SJohn.Forte@Sun.COM 
1027836SJohn.Forte@Sun.COM extern void rdc_fail_diskq(rdc_k_info_t *krdc, int wait, int flag);
1037836SJohn.Forte@Sun.COM extern int _rdc_rsrv_diskq(rdc_group_t *group);
1047836SJohn.Forte@Sun.COM extern void _rdc_rlse_diskq(rdc_group_t *group);
1057836SJohn.Forte@Sun.COM 
1067836SJohn.Forte@Sun.COM static enum clnt_stat
cl_call_sig(struct __client * rh,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp,xdrproc_t xres,caddr_t resp,struct timeval secs)1077836SJohn.Forte@Sun.COM cl_call_sig(struct __client *rh, rpcproc_t proc,
1087836SJohn.Forte@Sun.COM 	    xdrproc_t xargs, caddr_t argsp, xdrproc_t xres,
1097836SJohn.Forte@Sun.COM 	    caddr_t resp, struct timeval secs)
1107836SJohn.Forte@Sun.COM {
1117836SJohn.Forte@Sun.COM 	enum clnt_stat stat;
1127836SJohn.Forte@Sun.COM 	k_sigset_t smask;
1137836SJohn.Forte@Sun.COM 	sigintr(&smask, 0);
1147836SJohn.Forte@Sun.COM 	rh->cl_nosignal = TRUE;
1157836SJohn.Forte@Sun.COM 	stat = ((*(rh)->cl_ops->cl_call)\
1169093SRamana.Srikanth@Sun.COM 	    (rh, proc, xargs, argsp, xres, resp, secs));
1177836SJohn.Forte@Sun.COM 	rh->cl_nosignal = FALSE;
1187836SJohn.Forte@Sun.COM 	sigunintr(&smask);
1197836SJohn.Forte@Sun.COM 	return (stat);
1207836SJohn.Forte@Sun.COM }
1217836SJohn.Forte@Sun.COM 
1227836SJohn.Forte@Sun.COM int
rdc_net_getsize(int index,uint64_t * sizeptr)1237836SJohn.Forte@Sun.COM rdc_net_getsize(int index, uint64_t *sizeptr)
1247836SJohn.Forte@Sun.COM {
1257836SJohn.Forte@Sun.COM 	struct timeval t;
1267836SJohn.Forte@Sun.COM 	int err, size;
1277836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
1287836SJohn.Forte@Sun.COM 	int remote_index = krdc->remote_index;
1297836SJohn.Forte@Sun.COM 
1307836SJohn.Forte@Sun.COM 	*sizeptr = 0;
1317836SJohn.Forte@Sun.COM 	if (krdc->remote_index < 0)
1327836SJohn.Forte@Sun.COM 		return (EINVAL);
1337836SJohn.Forte@Sun.COM 
1347836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
1357836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
1367836SJohn.Forte@Sun.COM 
1377836SJohn.Forte@Sun.COM #ifdef DEBUG
1387836SJohn.Forte@Sun.COM 	if (krdc->intf == NULL)
1397836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
1409093SRamana.Srikanth@Sun.COM 		    "!rdc_net_getsize: null intf for index %d", index);
1417836SJohn.Forte@Sun.COM #endif
1427836SJohn.Forte@Sun.COM 	if (krdc->rpc_version <= RDC_VERSION5) {
1437836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_GETSIZE,
1447836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_int, (char *)&remote_index,
1457836SJohn.Forte@Sun.COM 		    xdr_int, (char *)&size, &t);
1467836SJohn.Forte@Sun.COM 		if (err == 0)
1477836SJohn.Forte@Sun.COM 			*sizeptr = size;
1487836SJohn.Forte@Sun.COM 	} else {
1497836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_GETSIZE6,
1507836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_int, (char *)&remote_index,
1517836SJohn.Forte@Sun.COM 		    xdr_u_longlong_t, (char *)sizeptr, &t);
1527836SJohn.Forte@Sun.COM 	}
1537836SJohn.Forte@Sun.COM 	return (err);
1547836SJohn.Forte@Sun.COM }
1557836SJohn.Forte@Sun.COM 
1567836SJohn.Forte@Sun.COM 
1577836SJohn.Forte@Sun.COM int
rdc_net_state(int index,int options)1587836SJohn.Forte@Sun.COM rdc_net_state(int index, int options)
1597836SJohn.Forte@Sun.COM {
1607836SJohn.Forte@Sun.COM 	struct timeval t;
1617836SJohn.Forte@Sun.COM 	int err;
1627836SJohn.Forte@Sun.COM 	int remote_index = -1;
1637836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[index];
1647836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
1657836SJohn.Forte@Sun.COM 	struct set_state s;
1667836SJohn.Forte@Sun.COM 	struct set_state4 s4;
1677836SJohn.Forte@Sun.COM 	char neta[32], rneta[32];
1687836SJohn.Forte@Sun.COM 	unsigned short *sp;
1697836SJohn.Forte@Sun.COM 
1707836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
1717836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
1727836SJohn.Forte@Sun.COM 
1737836SJohn.Forte@Sun.COM 	if (krdc->rpc_version < RDC_VERSION7) {
1747836SJohn.Forte@Sun.COM 		s4.netaddrlen = urdc->primary.addr.len;
1757836SJohn.Forte@Sun.COM 		s4.rnetaddrlen = urdc->secondary.addr.len;
1767836SJohn.Forte@Sun.COM 		bcopy(urdc->primary.addr.buf, s4.netaddr, s4.netaddrlen);
1777836SJohn.Forte@Sun.COM 		bcopy(urdc->secondary.addr.buf, s4.rnetaddr, s4.rnetaddrlen);
1787836SJohn.Forte@Sun.COM 		(void) strncpy(s4.pfile, urdc->primary.file, RDC_MAXNAMLEN);
1797836SJohn.Forte@Sun.COM 		(void) strncpy(s4.sfile, urdc->secondary.file, RDC_MAXNAMLEN);
1807836SJohn.Forte@Sun.COM 		s4.flag = options;
1817836SJohn.Forte@Sun.COM 
1827836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_STATE,
1837836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_set_state4, (char *)&s4, xdr_int,
1847836SJohn.Forte@Sun.COM 		    (char *)&remote_index, &t);
1857836SJohn.Forte@Sun.COM 	} else {
1867836SJohn.Forte@Sun.COM 		s.netaddrlen = urdc->primary.addr.len;
1877836SJohn.Forte@Sun.COM 		s.rnetaddrlen = urdc->secondary.addr.len;
1887836SJohn.Forte@Sun.COM 		s.netaddr.buf = neta;
1897836SJohn.Forte@Sun.COM 		s.rnetaddr.buf = rneta;
1907836SJohn.Forte@Sun.COM 		bcopy(urdc->primary.addr.buf, s.netaddr.buf, s.netaddrlen);
1917836SJohn.Forte@Sun.COM 		bcopy(urdc->secondary.addr.buf, s.rnetaddr.buf, s.rnetaddrlen);
1927836SJohn.Forte@Sun.COM 		s.netaddr.len = urdc->primary.addr.len;
1937836SJohn.Forte@Sun.COM 		s.rnetaddr.len = urdc->secondary.addr.len;
1947836SJohn.Forte@Sun.COM 		s.netaddr.maxlen = urdc->primary.addr.len;
1957836SJohn.Forte@Sun.COM 		s.rnetaddr.maxlen = urdc->secondary.addr.len;
1967836SJohn.Forte@Sun.COM 		sp = (unsigned short *)s.netaddr.buf;
1977836SJohn.Forte@Sun.COM 		*sp = htons(*sp);
1987836SJohn.Forte@Sun.COM 		sp = (unsigned short *)s.rnetaddr.buf;
1997836SJohn.Forte@Sun.COM 		*sp = htons(*sp);
2007836SJohn.Forte@Sun.COM 		s.pfile = urdc->primary.file;
2017836SJohn.Forte@Sun.COM 		s.sfile = urdc->secondary.file;
2027836SJohn.Forte@Sun.COM 		s.flag = options;
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_STATE,
2057836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_set_state, (char *)&s, xdr_int,
2067836SJohn.Forte@Sun.COM 		    (char *)&remote_index, &t);
2077836SJohn.Forte@Sun.COM 	}
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 	if (err)
2107836SJohn.Forte@Sun.COM 		return (-1);
2117836SJohn.Forte@Sun.COM 	else
2127836SJohn.Forte@Sun.COM 		return (remote_index);
2137836SJohn.Forte@Sun.COM }
2147836SJohn.Forte@Sun.COM 
2157836SJohn.Forte@Sun.COM 
2167836SJohn.Forte@Sun.COM /*
2177836SJohn.Forte@Sun.COM  * rdc_net_getbmap
2187836SJohn.Forte@Sun.COM  * gets the bitmaps from remote side and or's them  with remote bitmap
2197836SJohn.Forte@Sun.COM  */
2207836SJohn.Forte@Sun.COM int
rdc_net_getbmap(int index,int size)2217836SJohn.Forte@Sun.COM rdc_net_getbmap(int index, int size)
2227836SJohn.Forte@Sun.COM {
2237836SJohn.Forte@Sun.COM 	struct timeval t;
2247836SJohn.Forte@Sun.COM 	int err;
2257836SJohn.Forte@Sun.COM 	struct bmap b;
2267836SJohn.Forte@Sun.COM 	struct bmap6 b6;
2277836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
2307836SJohn.Forte@Sun.COM 
2317836SJohn.Forte@Sun.COM 	if (krdc->remote_index < 0)
2327836SJohn.Forte@Sun.COM 		return (EINVAL);
2337836SJohn.Forte@Sun.COM 
2347836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
2357836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
2367836SJohn.Forte@Sun.COM #ifdef DEBUG
2377836SJohn.Forte@Sun.COM 	if (krdc->intf == NULL)
2387836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
2399093SRamana.Srikanth@Sun.COM 		    "!rdc_net_getbmap: null intf for index %d", index);
2407836SJohn.Forte@Sun.COM #endif
2417836SJohn.Forte@Sun.COM 
2427836SJohn.Forte@Sun.COM 	if (krdc->rpc_version <= RDC_VERSION5) {
2437836SJohn.Forte@Sun.COM 		b.cd = krdc->remote_index;
2447836SJohn.Forte@Sun.COM 		b.dual = index;
2457836SJohn.Forte@Sun.COM 		b.size = size;
2467836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_BMAP,
2477836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_bmap, (char *)&b, xdr_int,
2487836SJohn.Forte@Sun.COM 		    (char *)&err, &t);
2497836SJohn.Forte@Sun.COM 
2507836SJohn.Forte@Sun.COM 	} else {
2517836SJohn.Forte@Sun.COM 		b6.cd = krdc->remote_index;
2527836SJohn.Forte@Sun.COM 		b6.dual = index;
2537836SJohn.Forte@Sun.COM 		b6.size = size;
2547836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_BMAP6,
2557836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_bmap6, (char *)&b6, xdr_int,
2567836SJohn.Forte@Sun.COM 		    (char *)&err, &t);
2577836SJohn.Forte@Sun.COM 	}
2587836SJohn.Forte@Sun.COM 	return (err);
2597836SJohn.Forte@Sun.COM }
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM int sndr_proto = 0;
2627836SJohn.Forte@Sun.COM 
2637836SJohn.Forte@Sun.COM /*
2647836SJohn.Forte@Sun.COM  * return state corresponding to rdc_host
2657836SJohn.Forte@Sun.COM  */
2667836SJohn.Forte@Sun.COM int
rdc_net_getstate(rdc_k_info_t * krdc,int * serial_mode,int * use_mirror,int * mirror_down,int network)2677836SJohn.Forte@Sun.COM rdc_net_getstate(rdc_k_info_t *krdc, int *serial_mode, int *use_mirror,
2687836SJohn.Forte@Sun.COM     int *mirror_down, int network)
2697836SJohn.Forte@Sun.COM {
2707836SJohn.Forte@Sun.COM 	int err;
2717836SJohn.Forte@Sun.COM 	struct timeval t;
2727836SJohn.Forte@Sun.COM 	int state;
2737836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2747836SJohn.Forte@Sun.COM 	struct set_state s;
2757836SJohn.Forte@Sun.COM #ifdef sparc
2767836SJohn.Forte@Sun.COM 	struct set_state4 s4;
2777836SJohn.Forte@Sun.COM #endif
2787836SJohn.Forte@Sun.COM 	char neta[32];
2797836SJohn.Forte@Sun.COM 	char rneta[32];
2807836SJohn.Forte@Sun.COM 	unsigned short *sp;
2817836SJohn.Forte@Sun.COM 	char *setp = (char *)&s;
2827836SJohn.Forte@Sun.COM 	xdrproc_t xdr_proc = xdr_set_state;
2837836SJohn.Forte@Sun.COM 
2847836SJohn.Forte@Sun.COM 	if (krdc->lsrv && (krdc->intf == NULL || krdc->intf->if_down) &&
2857836SJohn.Forte@Sun.COM 	    network) /* fail fast */
2867836SJohn.Forte@Sun.COM 		return (-1);
2877836SJohn.Forte@Sun.COM 
2887836SJohn.Forte@Sun.COM 	s.netaddrlen = urdc->primary.addr.len;
2897836SJohn.Forte@Sun.COM 	s.rnetaddrlen = urdc->secondary.addr.len;
2907836SJohn.Forte@Sun.COM 	s.pfile = urdc->primary.file;
2917836SJohn.Forte@Sun.COM 	s.sfile = urdc->secondary.file;
2927836SJohn.Forte@Sun.COM 	s.netaddr.buf = neta;
2937836SJohn.Forte@Sun.COM 	s.rnetaddr.buf = rneta;
2947836SJohn.Forte@Sun.COM 	bcopy(urdc->primary.addr.buf, s.netaddr.buf, s.netaddrlen);
2957836SJohn.Forte@Sun.COM 	bcopy(urdc->secondary.addr.buf, s.rnetaddr.buf, s.rnetaddrlen);
2967836SJohn.Forte@Sun.COM 	sp = (unsigned short *) s.netaddr.buf;
2977836SJohn.Forte@Sun.COM 	*sp = htons(*sp);
2987836SJohn.Forte@Sun.COM 	sp = (unsigned short *) s.rnetaddr.buf;
2997836SJohn.Forte@Sun.COM 	*sp = htons(*sp);
3007836SJohn.Forte@Sun.COM 	s.netaddr.len = urdc->primary.addr.len;
3017836SJohn.Forte@Sun.COM 	s.rnetaddr.len = urdc->secondary.addr.len;
3027836SJohn.Forte@Sun.COM 	s.netaddr.maxlen = urdc->primary.addr.maxlen;
3037836SJohn.Forte@Sun.COM 	s.rnetaddr.maxlen = urdc->secondary.addr.maxlen;
3047836SJohn.Forte@Sun.COM 	s.flag = 0;
3057836SJohn.Forte@Sun.COM 
3067836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
3077836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
3087836SJohn.Forte@Sun.COM 
3097836SJohn.Forte@Sun.COM 	if (sndr_proto)
3107836SJohn.Forte@Sun.COM 		krdc->rpc_version = sndr_proto;
3117836SJohn.Forte@Sun.COM 	else
3127836SJohn.Forte@Sun.COM 		krdc->rpc_version = RDC_VERS_MAX;
3137836SJohn.Forte@Sun.COM 
3147836SJohn.Forte@Sun.COM again:
3157836SJohn.Forte@Sun.COM 	err = rdc_clnt_call(krdc->lsrv, RDCPROC_GETSTATE4, krdc->rpc_version,
3167836SJohn.Forte@Sun.COM 	    xdr_proc, setp, xdr_int, (char *)&state, &t);
3177836SJohn.Forte@Sun.COM 
3187836SJohn.Forte@Sun.COM 	if (err == RPC_PROGVERSMISMATCH && (krdc->rpc_version !=
3199093SRamana.Srikanth@Sun.COM 	    RDC_VERS_MIN)) {
3207836SJohn.Forte@Sun.COM 		if (krdc->rpc_version-- == RDC_VERSION7) {
3217836SJohn.Forte@Sun.COM 			/* set_state struct changed with v7 of protocol */
3227836SJohn.Forte@Sun.COM #ifdef sparc
3237836SJohn.Forte@Sun.COM 			s4.netaddrlen = urdc->primary.addr.len;
3247836SJohn.Forte@Sun.COM 			s4.rnetaddrlen = urdc->secondary.addr.len;
3257836SJohn.Forte@Sun.COM 			bcopy(urdc->primary.addr.buf, s4.netaddr,
3267836SJohn.Forte@Sun.COM 			    s4.netaddrlen);
3277836SJohn.Forte@Sun.COM 			bcopy(urdc->secondary.addr.buf, s4.rnetaddr,
3289093SRamana.Srikanth@Sun.COM 			    s4.rnetaddrlen);
3297836SJohn.Forte@Sun.COM 			(void) strncpy(s4.pfile, urdc->primary.file,
3307836SJohn.Forte@Sun.COM 			    RDC_MAXNAMLEN);
3317836SJohn.Forte@Sun.COM 			(void) strncpy(s4.sfile, urdc->secondary.file,
3327836SJohn.Forte@Sun.COM 			    RDC_MAXNAMLEN);
3337836SJohn.Forte@Sun.COM 			s4.flag = 0;
3347836SJohn.Forte@Sun.COM 			xdr_proc = xdr_set_state4;
3357836SJohn.Forte@Sun.COM 			setp = (char *)&s4;
3367836SJohn.Forte@Sun.COM #else
3377836SJohn.Forte@Sun.COM 			/* x64 can not use protocols < 7 */
3387836SJohn.Forte@Sun.COM 			return (-1);
3397836SJohn.Forte@Sun.COM #endif
3407836SJohn.Forte@Sun.COM 		}
3417836SJohn.Forte@Sun.COM 		goto again;
3427836SJohn.Forte@Sun.COM 	}
3437836SJohn.Forte@Sun.COM #ifdef DEBUG
3449093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!sndr get_state: Protocol ver %d", krdc->rpc_version);
3457836SJohn.Forte@Sun.COM #endif
3467836SJohn.Forte@Sun.COM 
3477836SJohn.Forte@Sun.COM 	if (err) {
3487836SJohn.Forte@Sun.COM 		return (-1);
3497836SJohn.Forte@Sun.COM 	}
3507836SJohn.Forte@Sun.COM 
3517836SJohn.Forte@Sun.COM 	if (state == -1)
3527836SJohn.Forte@Sun.COM 		return (-1);
3537836SJohn.Forte@Sun.COM 
3547836SJohn.Forte@Sun.COM 	if (serial_mode)
3557836SJohn.Forte@Sun.COM 		*serial_mode = (state >> 2) & 1;
3567836SJohn.Forte@Sun.COM 	if (use_mirror)
3577836SJohn.Forte@Sun.COM 		*use_mirror = (state >> 1) & 1;
3587836SJohn.Forte@Sun.COM 	if (mirror_down)
3597836SJohn.Forte@Sun.COM 		*mirror_down = state & 1;
3607836SJohn.Forte@Sun.COM 
3617836SJohn.Forte@Sun.COM 	return (0);
3627836SJohn.Forte@Sun.COM }
3637836SJohn.Forte@Sun.COM 
3647836SJohn.Forte@Sun.COM 
3657836SJohn.Forte@Sun.COM static struct xdr_discrim rdres_discrim[2] = {
3667836SJohn.Forte@Sun.COM 	{ (int)RDC_OK, xdr_readok },
3677836SJohn.Forte@Sun.COM 	{ __dontcare__, NULL_xdrproc_t }
3687836SJohn.Forte@Sun.COM };
3697836SJohn.Forte@Sun.COM 
3707836SJohn.Forte@Sun.COM 
3717836SJohn.Forte@Sun.COM /*
3727836SJohn.Forte@Sun.COM  * Reply from remote read (client side)
3737836SJohn.Forte@Sun.COM  */
3747836SJohn.Forte@Sun.COM static bool_t
xdr_rdresult(XDR * xdrs,readres * rr)3757836SJohn.Forte@Sun.COM xdr_rdresult(XDR *xdrs, readres *rr)
3767836SJohn.Forte@Sun.COM {
3777836SJohn.Forte@Sun.COM 
3787836SJohn.Forte@Sun.COM 	return (xdr_union(xdrs, (enum_t *)&(rr->rr_status),
3799093SRamana.Srikanth@Sun.COM 	    (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void));
3807836SJohn.Forte@Sun.COM }
3817836SJohn.Forte@Sun.COM 
3827836SJohn.Forte@Sun.COM static int
rdc_rrstatus_decode(int status)3837836SJohn.Forte@Sun.COM rdc_rrstatus_decode(int status)
3847836SJohn.Forte@Sun.COM {
3857836SJohn.Forte@Sun.COM 	int ret = 0;
3867836SJohn.Forte@Sun.COM 
3877836SJohn.Forte@Sun.COM 	if (status != RDC_OK) {
3887836SJohn.Forte@Sun.COM 		switch (status) {
3897836SJohn.Forte@Sun.COM 		case RDCERR_NOENT:
3907836SJohn.Forte@Sun.COM 			ret = ENOENT;
3917836SJohn.Forte@Sun.COM 			break;
3927836SJohn.Forte@Sun.COM 		case RDCERR_NOMEM:
3937836SJohn.Forte@Sun.COM 			ret = ENOMEM;
3947836SJohn.Forte@Sun.COM 			break;
3957836SJohn.Forte@Sun.COM 		default:
3967836SJohn.Forte@Sun.COM 			ret = EIO;
3977836SJohn.Forte@Sun.COM 			break;
3987836SJohn.Forte@Sun.COM 		}
3997836SJohn.Forte@Sun.COM 	}
4007836SJohn.Forte@Sun.COM 
4017836SJohn.Forte@Sun.COM 	return (ret);
4027836SJohn.Forte@Sun.COM }
4037836SJohn.Forte@Sun.COM 
4047836SJohn.Forte@Sun.COM 
4057836SJohn.Forte@Sun.COM int
rdc_net_read(int local_index,int remote_index,nsc_buf_t * handle,nsc_off_t fba_pos,nsc_size_t fba_len)4067836SJohn.Forte@Sun.COM rdc_net_read(int local_index, int remote_index, nsc_buf_t *handle,
4077836SJohn.Forte@Sun.COM     nsc_off_t fba_pos, nsc_size_t fba_len)
4087836SJohn.Forte@Sun.COM {
4097836SJohn.Forte@Sun.COM 	struct rdcrdresult rr;
4107836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
4117836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
4127836SJohn.Forte@Sun.COM 	struct rread list;
4137836SJohn.Forte@Sun.COM 	struct rread6 list6;
4147836SJohn.Forte@Sun.COM 	struct timeval t;
4157836SJohn.Forte@Sun.COM 	uchar_t *sv_addr;
4167836SJohn.Forte@Sun.COM 	nsc_vec_t *vec;
4177836SJohn.Forte@Sun.COM 	int rpc_flag;
4187836SJohn.Forte@Sun.COM 	nsc_size_t sv_len;
4197836SJohn.Forte@Sun.COM 	int err;
4207836SJohn.Forte@Sun.COM 	int ret;
4217836SJohn.Forte@Sun.COM 	nsc_size_t len;
4227836SJohn.Forte@Sun.COM 	nsc_size_t maxfbas;
4237836SJohn.Forte@Sun.COM 	int transflag;
4247836SJohn.Forte@Sun.COM 
4257836SJohn.Forte@Sun.COM 	if (handle == NULL)
4267836SJohn.Forte@Sun.COM 		return (EINVAL);
4277836SJohn.Forte@Sun.COM 
4287836SJohn.Forte@Sun.COM 	if (!RDC_HANDLE_LIMITS(handle, fba_pos, fba_len)) {
4297836SJohn.Forte@Sun.COM #ifdef DEBUG
4309093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_read: handle bounds");
4317836SJohn.Forte@Sun.COM #endif
4327836SJohn.Forte@Sun.COM 		return (EINVAL);
4337836SJohn.Forte@Sun.COM 	}
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[local_index];
4367836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[local_index];
4377836SJohn.Forte@Sun.COM 
4387836SJohn.Forte@Sun.COM 	maxfbas = MAX_RDC_FBAS;
4397836SJohn.Forte@Sun.COM 
4407836SJohn.Forte@Sun.COM 	if (krdc->remote_fd && !(rdc_get_vflags(urdc) & RDC_FCAL_FAILED)) {
4417836SJohn.Forte@Sun.COM 		nsc_buf_t *remote_h = NULL;
4427836SJohn.Forte@Sun.COM 		int reserved = 0;
4437836SJohn.Forte@Sun.COM 
4447836SJohn.Forte@Sun.COM 		ret = nsc_reserve(krdc->remote_fd, NSC_MULTI);
4457836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(ret)) {
4467836SJohn.Forte@Sun.COM 			reserved = 1;
4477836SJohn.Forte@Sun.COM 			ret = nsc_alloc_buf(krdc->remote_fd, fba_pos, fba_len,
4487836SJohn.Forte@Sun.COM 			    NSC_RDBUF, &remote_h);
4497836SJohn.Forte@Sun.COM 		}
4507836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(ret)) {
4517836SJohn.Forte@Sun.COM 			ret = nsc_copy(remote_h, handle, fba_pos, fba_pos,
4527836SJohn.Forte@Sun.COM 			    fba_len);
4537836SJohn.Forte@Sun.COM 			if (RDC_SUCCESS(ret)) {
4547836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(remote_h);
4557836SJohn.Forte@Sun.COM 				nsc_release(krdc->remote_fd);
4567836SJohn.Forte@Sun.COM 				return (0);
4577836SJohn.Forte@Sun.COM 			}
4587836SJohn.Forte@Sun.COM 		}
4597836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
4607836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_FCAL_FAILED);
4617836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
4627836SJohn.Forte@Sun.COM 		if (remote_h)
4637836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(remote_h);
4647836SJohn.Forte@Sun.COM 		if (reserved)
4657836SJohn.Forte@Sun.COM 			nsc_release(krdc->remote_fd);
4667836SJohn.Forte@Sun.COM 	}
4677836SJohn.Forte@Sun.COM 
4687836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
4697836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
4707836SJohn.Forte@Sun.COM 
4717836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_VOL_FAILED)
4727836SJohn.Forte@Sun.COM 		rpc_flag = RDC_RREAD_FAIL;
4737836SJohn.Forte@Sun.COM 	else
4747836SJohn.Forte@Sun.COM 		rpc_flag = 0;
4757836SJohn.Forte@Sun.COM 
4767836SJohn.Forte@Sun.COM #ifdef DEBUG
4777836SJohn.Forte@Sun.COM 	if (krdc->intf == NULL)
4787836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
4799093SRamana.Srikanth@Sun.COM 		    "!rdc_net_read: null intf for index %d", local_index);
4807836SJohn.Forte@Sun.COM #endif
4817836SJohn.Forte@Sun.COM 	/*
4827836SJohn.Forte@Sun.COM 	 * switch on proto version.
4837836SJohn.Forte@Sun.COM 	 */
4847836SJohn.Forte@Sun.COM 	len = fba_len;		/* length (FBAs) still to xfer */
4857836SJohn.Forte@Sun.COM 	rr.rr_bufsize = 0;	/* rpc data buffer length (bytes) */
4867836SJohn.Forte@Sun.COM 	rr.rr_data = NULL;	/* rpc data buffer */
4877836SJohn.Forte@Sun.COM 	transflag = rpc_flag | RDC_RREAD_START;	/* setup rpc */
4887836SJohn.Forte@Sun.COM 	if (krdc->rpc_version <= RDC_VERSION5) {
4897836SJohn.Forte@Sun.COM 		ASSERT(fba_pos <= INT32_MAX);
4907836SJohn.Forte@Sun.COM 		list.pos = (int)fba_pos; /* fba position of start of chunk */
4917836SJohn.Forte@Sun.COM 		list.cd = remote_index;	/* remote end cd */
4927836SJohn.Forte@Sun.COM 		/* send setup rpc */
4937836SJohn.Forte@Sun.COM 		list.flag = transflag;
4947836SJohn.Forte@Sun.COM 		ASSERT(len <= INT32_MAX);
4957836SJohn.Forte@Sun.COM 		list.len = (int)len;			/* total fba length */
4967836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ5,
4977836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_rread, (char *)&list, xdr_int,
4987836SJohn.Forte@Sun.COM 		    (char *)&ret, &t);
4997836SJohn.Forte@Sun.COM 
5007836SJohn.Forte@Sun.COM 	} else {
5017836SJohn.Forte@Sun.COM 		list6.pos = fba_pos;	/* fba position of start of chunk */
5027836SJohn.Forte@Sun.COM 		list6.cd = remote_index;	/* remote end cd */
5037836SJohn.Forte@Sun.COM 		/* send setup rpc */
5047836SJohn.Forte@Sun.COM 		list6.flag = transflag;	/* setup rpc */
5057836SJohn.Forte@Sun.COM 		ASSERT(len <= INT32_MAX);
5067836SJohn.Forte@Sun.COM 		list6.len = (int)len;			/* total fba length */
5077836SJohn.Forte@Sun.COM 		err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ6,
5087836SJohn.Forte@Sun.COM 		    krdc->rpc_version, xdr_rread6, (char *)&list6, xdr_int,
5097836SJohn.Forte@Sun.COM 		    (char *)&ret, &t);
5107836SJohn.Forte@Sun.COM 	}
5117836SJohn.Forte@Sun.COM 
5127836SJohn.Forte@Sun.COM 	if (err) {
5137836SJohn.Forte@Sun.COM #ifdef DEBUG
5149093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_read: setup err %d", err);
5157836SJohn.Forte@Sun.COM #endif
5167836SJohn.Forte@Sun.COM 		if (err == RPC_INTR)
5177836SJohn.Forte@Sun.COM 			ret = EINTR;
5187836SJohn.Forte@Sun.COM 		else
5197836SJohn.Forte@Sun.COM 			ret = ENOLINK;
5207836SJohn.Forte@Sun.COM 
5217836SJohn.Forte@Sun.COM 		goto remote_rerror;
5227836SJohn.Forte@Sun.COM 	}
5237836SJohn.Forte@Sun.COM 
5247836SJohn.Forte@Sun.COM 	if (ret == 0) {		/* No valid index from r_net_read */
5257836SJohn.Forte@Sun.COM #ifdef DEBUG
5267836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
5279093SRamana.Srikanth@Sun.COM 		    "!rdc_net_read: no valid index from r_net_read");
5287836SJohn.Forte@Sun.COM #endif
5297836SJohn.Forte@Sun.COM 		return (ENOBUFS);
5307836SJohn.Forte@Sun.COM 	}
5317836SJohn.Forte@Sun.COM 	transflag = rpc_flag | RDC_RREAD_DATA;
5327836SJohn.Forte@Sun.COM 	if (krdc->rpc_version <= RDC_VERSION5) {
5337836SJohn.Forte@Sun.COM 		list.idx = ret;		/* save idx to return to server */
5347836SJohn.Forte@Sun.COM 		list.flag = transflag;
5357836SJohn.Forte@Sun.COM 					/* move onto to data xfer rpcs */
5367836SJohn.Forte@Sun.COM 	} else {
5377836SJohn.Forte@Sun.COM 		list6.idx = ret;	/* save idx to return to server */
5387836SJohn.Forte@Sun.COM 		list6.flag = transflag;
5397836SJohn.Forte@Sun.COM 	}
5407836SJohn.Forte@Sun.COM 
5417836SJohn.Forte@Sun.COM 	/* find starting position in handle */
5427836SJohn.Forte@Sun.COM 
5437836SJohn.Forte@Sun.COM 	vec = handle->sb_vec;
5447836SJohn.Forte@Sun.COM 
5457836SJohn.Forte@Sun.COM 	fba_pos -= handle->sb_pos;
5467836SJohn.Forte@Sun.COM 
5477836SJohn.Forte@Sun.COM 	for (; fba_pos >= FBA_NUM(vec->sv_len); vec++)
5487836SJohn.Forte@Sun.COM 		fba_pos -= FBA_NUM(vec->sv_len);
5497836SJohn.Forte@Sun.COM 
5507836SJohn.Forte@Sun.COM 	sv_addr = vec->sv_addr + FBA_SIZE(fba_pos);	/* data in vector */
5517836SJohn.Forte@Sun.COM 	sv_len = vec->sv_len - FBA_SIZE(fba_pos);	/* bytes in vector */
5527836SJohn.Forte@Sun.COM 
5537836SJohn.Forte@Sun.COM 	while (len) {
5547836SJohn.Forte@Sun.COM 		nsc_size_t translen;
5557836SJohn.Forte@Sun.COM 		if (len > maxfbas) {
5567836SJohn.Forte@Sun.COM 			translen = maxfbas;
5577836SJohn.Forte@Sun.COM 		} else {
5587836SJohn.Forte@Sun.COM 			translen = len;
5597836SJohn.Forte@Sun.COM 		}
5607836SJohn.Forte@Sun.COM 
5617836SJohn.Forte@Sun.COM 		if (FBA_SIZE(translen) > sv_len) {
5627836SJohn.Forte@Sun.COM 			translen = FBA_NUM(sv_len);
5637836SJohn.Forte@Sun.COM 		}
5647836SJohn.Forte@Sun.COM 
5657836SJohn.Forte@Sun.COM 		len -= translen;
5667836SJohn.Forte@Sun.COM 		if (len == 0) {
5677836SJohn.Forte@Sun.COM 			/* last data xfer rpc - tell server to cleanup */
5687836SJohn.Forte@Sun.COM 			transflag |= RDC_RREAD_END;
5697836SJohn.Forte@Sun.COM 		}
5707836SJohn.Forte@Sun.COM 
5717836SJohn.Forte@Sun.COM 		if (!rr.rr_data || (nsc_size_t)rr.rr_bufsize !=
5727836SJohn.Forte@Sun.COM 		    FBA_SIZE(translen)) {
5737836SJohn.Forte@Sun.COM 			if (rr.rr_data)
5747836SJohn.Forte@Sun.COM 				kmem_free(rr.rr_data, rr.rr_bufsize);
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 			ASSERT(FBA_SIZE(translen) <= INT32_MAX);
5777836SJohn.Forte@Sun.COM 			rr.rr_bufsize = FBA_SIZE(translen);
5787836SJohn.Forte@Sun.COM 			rr.rr_data = kmem_alloc(rr.rr_bufsize, KM_NOSLEEP);
5797836SJohn.Forte@Sun.COM 		}
5807836SJohn.Forte@Sun.COM 
5817836SJohn.Forte@Sun.COM 		if (!rr.rr_data) {
5827836SJohn.Forte@Sun.COM 			/* error */
5837836SJohn.Forte@Sun.COM #ifdef DEBUG
5849093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!rdc_net_read: kmem_alloc failed");
5857836SJohn.Forte@Sun.COM #endif
5867836SJohn.Forte@Sun.COM 			return (ENOMEM);
5877836SJohn.Forte@Sun.COM 		}
5887836SJohn.Forte@Sun.COM 
5897836SJohn.Forte@Sun.COM 		/* get data from remote end */
5907836SJohn.Forte@Sun.COM 
5917836SJohn.Forte@Sun.COM #ifdef DEBUG
5927836SJohn.Forte@Sun.COM 		if (krdc->intf == NULL)
5937836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
5949093SRamana.Srikanth@Sun.COM 			    "!rdc_net_read: null intf for index %d",
5957836SJohn.Forte@Sun.COM 			    local_index);
5967836SJohn.Forte@Sun.COM #endif
5977836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
5987836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
5997836SJohn.Forte@Sun.COM 			kstat_runq_enter(KSTAT_IO_PTR(krdc->io_kstats));
6007836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
6017836SJohn.Forte@Sun.COM 		}
6027836SJohn.Forte@Sun.COM 		/*CONSTCOND*/
6037836SJohn.Forte@Sun.COM 		ASSERT(RDC_MAXDATA <= INT32_MAX);
6047836SJohn.Forte@Sun.COM 		ASSERT(translen <= RDC_MAXDATA);
6057836SJohn.Forte@Sun.COM 		if (krdc->rpc_version <= RDC_VERSION5) {
6067836SJohn.Forte@Sun.COM 			list.len = (int)translen;
6077836SJohn.Forte@Sun.COM 			list.flag = transflag;
6087836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ5,
6097836SJohn.Forte@Sun.COM 			    krdc->rpc_version, xdr_rread, (char *)&list,
6107836SJohn.Forte@Sun.COM 			    xdr_rdresult, (char *)&rr, &t);
6117836SJohn.Forte@Sun.COM 		} else {
6127836SJohn.Forte@Sun.COM 			list6.len = (int)translen;
6137836SJohn.Forte@Sun.COM 			list6.flag = transflag;
6147836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ6,
6157836SJohn.Forte@Sun.COM 			    krdc->rpc_version, xdr_rread6, (char *)&list6,
6167836SJohn.Forte@Sun.COM 			    xdr_rdresult, (char *)&rr, &t);
6177836SJohn.Forte@Sun.COM 		}
6187836SJohn.Forte@Sun.COM 
6197836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
6207836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
6217836SJohn.Forte@Sun.COM 			kstat_runq_exit(KSTAT_IO_PTR(krdc->io_kstats));
6227836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
6237836SJohn.Forte@Sun.COM 		}
6247836SJohn.Forte@Sun.COM 
6257836SJohn.Forte@Sun.COM 		if (err) {
6267836SJohn.Forte@Sun.COM #ifdef DEBUG
6279093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!rdc_net_read: rpc err %d", err);
6287836SJohn.Forte@Sun.COM #endif
6297836SJohn.Forte@Sun.COM 			if (err == RPC_INTR) {
6307836SJohn.Forte@Sun.COM 				ret = EINTR;
6317836SJohn.Forte@Sun.COM 			} else {
6327836SJohn.Forte@Sun.COM 				ret = ENOLINK;
6337836SJohn.Forte@Sun.COM 			}
6347836SJohn.Forte@Sun.COM 
6357836SJohn.Forte@Sun.COM 			goto remote_rerror;
6367836SJohn.Forte@Sun.COM 		}
6377836SJohn.Forte@Sun.COM 
6387836SJohn.Forte@Sun.COM 		if (rr.rr_status != RDC_OK) {
6397836SJohn.Forte@Sun.COM 			ret = rdc_rrstatus_decode(rr.rr_status);
6407836SJohn.Forte@Sun.COM 			if (!ret)
6417836SJohn.Forte@Sun.COM 				ret = EIO;
6427836SJohn.Forte@Sun.COM 
6437836SJohn.Forte@Sun.COM 			goto remote_rerror;
6447836SJohn.Forte@Sun.COM 		}
6457836SJohn.Forte@Sun.COM 
6467836SJohn.Forte@Sun.COM 		/* copy into handle */
6477836SJohn.Forte@Sun.COM 
6487836SJohn.Forte@Sun.COM 		bcopy(rr.rr_data, sv_addr, (size_t)rr.rr_bufsize);
6497836SJohn.Forte@Sun.COM 
6507836SJohn.Forte@Sun.COM 		/* update counters */
6517836SJohn.Forte@Sun.COM 
6527836SJohn.Forte@Sun.COM 		sv_addr += rr.rr_bufsize;
6537836SJohn.Forte@Sun.COM 		if (krdc->rpc_version <= RDC_VERSION5) {
6547836SJohn.Forte@Sun.COM 			list.pos += translen;
6557836SJohn.Forte@Sun.COM 		} else {
6567836SJohn.Forte@Sun.COM 			list6.pos += translen;
6577836SJohn.Forte@Sun.COM 		}
6587836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
6597836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->reads++;
6607836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->nread += rr.rr_bufsize;
6617836SJohn.Forte@Sun.COM 		}
6627836SJohn.Forte@Sun.COM 		ASSERT(sv_len <= INT32_MAX);
6637836SJohn.Forte@Sun.COM 		ASSERT(sv_len >= (nsc_size_t)rr.rr_bufsize);
6647836SJohn.Forte@Sun.COM 		sv_len -= rr.rr_bufsize;
6657836SJohn.Forte@Sun.COM 
6667836SJohn.Forte@Sun.COM 		if (sv_len == 0) {
6677836SJohn.Forte@Sun.COM 			/* goto next vector */
6687836SJohn.Forte@Sun.COM 			vec++;
6697836SJohn.Forte@Sun.COM 			sv_addr = vec->sv_addr;
6707836SJohn.Forte@Sun.COM 			sv_len = vec->sv_len;
6717836SJohn.Forte@Sun.COM 		}
6727836SJohn.Forte@Sun.COM 	}
6737836SJohn.Forte@Sun.COM 
6747836SJohn.Forte@Sun.COM 	if (rr.rr_data)
6757836SJohn.Forte@Sun.COM 		kmem_free(rr.rr_data, rr.rr_bufsize);
6767836SJohn.Forte@Sun.COM 
6777836SJohn.Forte@Sun.COM 	return (0);
6787836SJohn.Forte@Sun.COM 
6797836SJohn.Forte@Sun.COM remote_rerror:
6807836SJohn.Forte@Sun.COM 	if (rr.rr_data)
6817836SJohn.Forte@Sun.COM 		kmem_free(rr.rr_data, rr.rr_bufsize);
6827836SJohn.Forte@Sun.COM 
6837836SJohn.Forte@Sun.COM 	return (ret ? ret : ENOLINK);
6847836SJohn.Forte@Sun.COM }
6857836SJohn.Forte@Sun.COM 
6867836SJohn.Forte@Sun.COM /*
6877836SJohn.Forte@Sun.COM  * rdc_net_write
6887836SJohn.Forte@Sun.COM  * Main remote write client side
6897836SJohn.Forte@Sun.COM  * Handles protocol selection as well as requests for remote allocation
6907836SJohn.Forte@Sun.COM  * and data transfer
6917836SJohn.Forte@Sun.COM  * Does local IO for FCAL
6927836SJohn.Forte@Sun.COM  * caller must clear bitmap on success
6937836SJohn.Forte@Sun.COM  */
6947836SJohn.Forte@Sun.COM 
6957836SJohn.Forte@Sun.COM int
rdc_net_write(int local_index,int remote_index,nsc_buf_t * handle,nsc_off_t fba_pos,nsc_size_t fba_len,uint_t aseq,int qpos,netwriteres * netres)6967836SJohn.Forte@Sun.COM rdc_net_write(int local_index, int remote_index, nsc_buf_t *handle,
6977836SJohn.Forte@Sun.COM     nsc_off_t fba_pos, nsc_size_t fba_len, uint_t aseq, int qpos,
6987836SJohn.Forte@Sun.COM     netwriteres *netres)
6997836SJohn.Forte@Sun.COM {
7007836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
7017836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
7027836SJohn.Forte@Sun.COM 	struct timeval t;
7037836SJohn.Forte@Sun.COM 	nsc_vec_t *vec;
7047836SJohn.Forte@Sun.COM 	int sv_len;
7057836SJohn.Forte@Sun.COM 	nsc_off_t fpos;
7067836SJohn.Forte@Sun.COM 	int err;
7077836SJohn.Forte@Sun.COM 	struct netwriteres netret;
7087836SJohn.Forte@Sun.COM 	struct netwriteres *netresptr;
7097836SJohn.Forte@Sun.COM 	struct net_data5 dlist5;
7107836SJohn.Forte@Sun.COM 	struct net_data6 dlist6;
7117836SJohn.Forte@Sun.COM 	int ret;
7127836SJohn.Forte@Sun.COM 	nsc_size_t maxfbas;
7137836SJohn.Forte@Sun.COM 	int transflag;
7147836SJohn.Forte@Sun.COM 	int translen;
7157836SJohn.Forte@Sun.COM 	int transendoblk;
7167836SJohn.Forte@Sun.COM 	char *transptr;
7177836SJohn.Forte@Sun.COM 	int vflags;
7187836SJohn.Forte@Sun.COM 
7197836SJohn.Forte@Sun.COM 	if (handle == NULL)
7207836SJohn.Forte@Sun.COM 		return (EINVAL);
7217836SJohn.Forte@Sun.COM 
7227836SJohn.Forte@Sun.COM 	/* if not a diskq buffer */
7237836SJohn.Forte@Sun.COM 	if ((qpos == -1) && (!RDC_HANDLE_LIMITS(handle, fba_pos, fba_len))) {
7247836SJohn.Forte@Sun.COM #ifdef DEBUG
7259093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_write: handle bounds");
7267836SJohn.Forte@Sun.COM #endif
7277836SJohn.Forte@Sun.COM 		return (EINVAL);
7287836SJohn.Forte@Sun.COM 	}
7297836SJohn.Forte@Sun.COM 
7307836SJohn.Forte@Sun.COM 
7317836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
7327836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
7337836SJohn.Forte@Sun.COM 
7347836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[local_index];
7357836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[local_index];
7367836SJohn.Forte@Sun.COM 
7377836SJohn.Forte@Sun.COM 	maxfbas = MAX_RDC_FBAS;
7387836SJohn.Forte@Sun.COM 
7397836SJohn.Forte@Sun.COM 	/* FCAL IO */
7407836SJohn.Forte@Sun.COM 	if (krdc->remote_fd && !(rdc_get_vflags(urdc) & RDC_FCAL_FAILED)) {
7417836SJohn.Forte@Sun.COM 		nsc_buf_t *remote_h = NULL;
7427836SJohn.Forte@Sun.COM 		int reserved = 0;
7437836SJohn.Forte@Sun.COM 
7447836SJohn.Forte@Sun.COM 		ret = nsc_reserve(krdc->remote_fd, NSC_MULTI);
7457836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(ret)) {
7467836SJohn.Forte@Sun.COM 			reserved = 1;
7477836SJohn.Forte@Sun.COM 			ret = nsc_alloc_buf(krdc->remote_fd, fba_pos, fba_len,
7487836SJohn.Forte@Sun.COM 			    NSC_WRBUF, &remote_h);
7497836SJohn.Forte@Sun.COM 		}
7507836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(ret)) {
7517836SJohn.Forte@Sun.COM 			ret = nsc_copy(handle, remote_h, fba_pos, fba_pos,
7527836SJohn.Forte@Sun.COM 			    fba_len);
7537836SJohn.Forte@Sun.COM 			if (RDC_SUCCESS(ret))
7547836SJohn.Forte@Sun.COM 				ret = nsc_write(remote_h, fba_pos, fba_len, 0);
7557836SJohn.Forte@Sun.COM 			if (RDC_SUCCESS(ret)) {
7567836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(remote_h);
7577836SJohn.Forte@Sun.COM 				nsc_release(krdc->remote_fd);
7587836SJohn.Forte@Sun.COM 				return (0);
7597836SJohn.Forte@Sun.COM 			}
7607836SJohn.Forte@Sun.COM 		}
7617836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
7627836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_FCAL_FAILED);
7637836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
7647836SJohn.Forte@Sun.COM 		if (remote_h)
7657836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(remote_h);
7667836SJohn.Forte@Sun.COM 		if (reserved)
7677836SJohn.Forte@Sun.COM 			nsc_release(krdc->remote_fd);
7687836SJohn.Forte@Sun.COM 	}
7697836SJohn.Forte@Sun.COM 
7707836SJohn.Forte@Sun.COM 	/*
7717836SJohn.Forte@Sun.COM 	 * At this point we must decide which protocol we are using and
7727836SJohn.Forte@Sun.COM 	 * do the right thing
7737836SJohn.Forte@Sun.COM 	 */
7747836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_val = NULL;
7757836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_len = 0;
7767836SJohn.Forte@Sun.COM 	if (netres) {
7777836SJohn.Forte@Sun.COM 		netresptr = netres;
7787836SJohn.Forte@Sun.COM 	} else {
7797836SJohn.Forte@Sun.COM 		netresptr = &netret;
7807836SJohn.Forte@Sun.COM 	}
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 	vflags = rdc_get_vflags(urdc);
7837836SJohn.Forte@Sun.COM 
7847836SJohn.Forte@Sun.COM 	if (vflags & (RDC_VOL_FAILED|RDC_BMP_FAILED))
7857836SJohn.Forte@Sun.COM 		transflag = RDC_RWRITE_FAIL;
7867836SJohn.Forte@Sun.COM 	else
7877836SJohn.Forte@Sun.COM 		transflag = 0;
7887836SJohn.Forte@Sun.COM 
7897836SJohn.Forte@Sun.COM 
7907836SJohn.Forte@Sun.COM #ifdef DEBUG
7917836SJohn.Forte@Sun.COM 	if (krdc->intf == NULL)
7929093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_net_write: null intf for index %d",
7939093SRamana.Srikanth@Sun.COM 		    local_index);
7947836SJohn.Forte@Sun.COM #endif
7957836SJohn.Forte@Sun.COM 
7967836SJohn.Forte@Sun.COM 	vec = handle->sb_vec;
7977836SJohn.Forte@Sun.COM 
7987836SJohn.Forte@Sun.COM 	/*
7997836SJohn.Forte@Sun.COM 	 * find starting position in vector
8007836SJohn.Forte@Sun.COM 	 */
8017836SJohn.Forte@Sun.COM 	if ((qpos == -1) || (handle->sb_user == RDC_NULLBUFREAD))
8027836SJohn.Forte@Sun.COM 		fpos = fba_pos - handle->sb_pos;
8037836SJohn.Forte@Sun.COM 	else
8047836SJohn.Forte@Sun.COM 		fpos = (qpos + 1) - handle->sb_pos;
8057836SJohn.Forte@Sun.COM 
8067836SJohn.Forte@Sun.COM 	for (; fpos >= FBA_NUM(vec->sv_len); vec++)
8077836SJohn.Forte@Sun.COM 		fpos -= FBA_NUM(vec->sv_len);
8087836SJohn.Forte@Sun.COM 	sv_len = vec->sv_len - FBA_SIZE(fpos);	/* bytes in vector */
8097836SJohn.Forte@Sun.COM 	transptr = (char *)vec->sv_addr + FBA_SIZE(fpos);
8107836SJohn.Forte@Sun.COM 
8117836SJohn.Forte@Sun.COM 	if (krdc->rpc_version <= RDC_VERSION5) {
8127836SJohn.Forte@Sun.COM 		dlist5.local_cd = local_index;
8137836SJohn.Forte@Sun.COM 		dlist5.cd = remote_index;
8147836SJohn.Forte@Sun.COM 		ASSERT(fba_len <= INT32_MAX);
8157836SJohn.Forte@Sun.COM 		ASSERT(fba_pos <= INT32_MAX);
8167836SJohn.Forte@Sun.COM 		dlist5.len = (int)fba_len;
8177836SJohn.Forte@Sun.COM 		dlist5.pos = (int)fba_pos;
8187836SJohn.Forte@Sun.COM 		dlist5.idx = -1; /* Starting index */
8197836SJohn.Forte@Sun.COM 		dlist5.flag = transflag;
8207836SJohn.Forte@Sun.COM 		dlist5.seq = aseq;		/* sequence number */
8217836SJohn.Forte@Sun.COM 		dlist5.sfba = (int)fba_pos;	/* starting fba for this xfer */
8227836SJohn.Forte@Sun.COM 	} else {
8237836SJohn.Forte@Sun.COM 		dlist6.local_cd = local_index;
8247836SJohn.Forte@Sun.COM 		dlist6.cd = remote_index;
8257836SJohn.Forte@Sun.COM 		ASSERT(fba_len <= INT32_MAX);
8267836SJohn.Forte@Sun.COM 		dlist6.len = (int)fba_len;
8277836SJohn.Forte@Sun.COM 		dlist6.qpos = qpos;
8287836SJohn.Forte@Sun.COM 		dlist6.pos = fba_pos;
8297836SJohn.Forte@Sun.COM 		dlist6.idx = -1; /* Starting index */
8307836SJohn.Forte@Sun.COM 		dlist6.flag = transflag;
8317836SJohn.Forte@Sun.COM 		dlist6.seq = aseq;		/* sequence number */
8327836SJohn.Forte@Sun.COM 		dlist6.sfba = fba_pos;		/* starting fba for this xfer */
8337836SJohn.Forte@Sun.COM 	}
8347836SJohn.Forte@Sun.COM 
8357836SJohn.Forte@Sun.COM 	transendoblk = 0;
8367836SJohn.Forte@Sun.COM 	while (fba_len) {
8377836SJohn.Forte@Sun.COM 		if (!transptr) {
8387836SJohn.Forte@Sun.COM #ifdef DEBUG
8397836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
8409093SRamana.Srikanth@Sun.COM 			    "!rdc_net_write: walked off end of handle!");
8417836SJohn.Forte@Sun.COM #endif
8427836SJohn.Forte@Sun.COM 			ret = EINVAL;
8437836SJohn.Forte@Sun.COM 			goto remote_error;
8447836SJohn.Forte@Sun.COM 		}
8457836SJohn.Forte@Sun.COM 
8467836SJohn.Forte@Sun.COM 		if (fba_len > maxfbas) {
8477836SJohn.Forte@Sun.COM 			ASSERT(maxfbas <= INT32_MAX);
8487836SJohn.Forte@Sun.COM 			translen = (int)maxfbas;
8497836SJohn.Forte@Sun.COM 		} else {
8507836SJohn.Forte@Sun.COM 			ASSERT(fba_len <= INT32_MAX);
8517836SJohn.Forte@Sun.COM 			translen = (int)fba_len;
8527836SJohn.Forte@Sun.COM 		}
8537836SJohn.Forte@Sun.COM 
8547836SJohn.Forte@Sun.COM 		if (FBA_SIZE(translen) > sv_len) {
8557836SJohn.Forte@Sun.COM 			translen = FBA_NUM(sv_len);
8567836SJohn.Forte@Sun.COM 		}
8577836SJohn.Forte@Sun.COM 
8587836SJohn.Forte@Sun.COM 		fba_len -= translen;
8597836SJohn.Forte@Sun.COM 		if (fba_len == 0) {
8607836SJohn.Forte@Sun.COM 			/* last data xfer - tell server to commit */
8617836SJohn.Forte@Sun.COM 			transendoblk = 1;
8627836SJohn.Forte@Sun.COM 		}
8637836SJohn.Forte@Sun.COM 
8647836SJohn.Forte@Sun.COM 
8657836SJohn.Forte@Sun.COM #ifdef DEBUG
8667836SJohn.Forte@Sun.COM 		if (krdc->intf == NULL)
8677836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
8689093SRamana.Srikanth@Sun.COM 			    "!rdc_net_write: null intf for index %d",
8697836SJohn.Forte@Sun.COM 			    local_index);
8707836SJohn.Forte@Sun.COM #endif
8717836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_netwrite_clntcall_start);
8727836SJohn.Forte@Sun.COM 
8737836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
8747836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
8757836SJohn.Forte@Sun.COM 			kstat_runq_enter(KSTAT_IO_PTR(krdc->io_kstats));
8767836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
8777836SJohn.Forte@Sun.COM 		}
8787836SJohn.Forte@Sun.COM 		if (krdc->rpc_version <= RDC_VERSION5) {
8797836SJohn.Forte@Sun.COM 			ret = 0;
8807836SJohn.Forte@Sun.COM 			dlist5.nfba = translen;
8817836SJohn.Forte@Sun.COM 			dlist5.endoblk = transendoblk;
8827836SJohn.Forte@Sun.COM 			dlist5.data.data_len = FBA_SIZE(translen);
8837836SJohn.Forte@Sun.COM 			dlist5.data.data_val = transptr;
8847836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_WRITE5,
8857836SJohn.Forte@Sun.COM 			    krdc->rpc_version, xdr_net_data5,
8867836SJohn.Forte@Sun.COM 			    (char *)&dlist5, xdr_int,
8877836SJohn.Forte@Sun.COM 			    (char *)&ret, &t);
8887836SJohn.Forte@Sun.COM 			if (ret >= 0) {
8897836SJohn.Forte@Sun.COM 				netresptr->result = 0;
8907836SJohn.Forte@Sun.COM 				netresptr->index = ret;
8917836SJohn.Forte@Sun.COM 			} else {
8927836SJohn.Forte@Sun.COM 				netresptr->result = ret;
8937836SJohn.Forte@Sun.COM 			}
8947836SJohn.Forte@Sun.COM 		} else {
8957836SJohn.Forte@Sun.COM 			netresptr->result = 0;
8967836SJohn.Forte@Sun.COM 			dlist6.nfba = translen;
8977836SJohn.Forte@Sun.COM 			dlist6.endoblk = transendoblk;
8987836SJohn.Forte@Sun.COM 			dlist6.data.data_len = FBA_SIZE(translen);
8997836SJohn.Forte@Sun.COM 			dlist6.data.data_val = transptr;
9007836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_WRITE6,
9017836SJohn.Forte@Sun.COM 			    krdc->rpc_version, xdr_net_data6,
9027836SJohn.Forte@Sun.COM 			    (char *)&dlist6, xdr_netwriteres,
9037836SJohn.Forte@Sun.COM 			    (char *)netresptr, &t);
9047836SJohn.Forte@Sun.COM 		}
9057836SJohn.Forte@Sun.COM 
9067836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
9077836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
9087836SJohn.Forte@Sun.COM 			kstat_runq_exit(KSTAT_IO_PTR(krdc->io_kstats));
9097836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
9107836SJohn.Forte@Sun.COM 		}
9117836SJohn.Forte@Sun.COM 
9127836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_netwrite_clntcall_end);
9137836SJohn.Forte@Sun.COM 		ret = netresptr->result;
9147836SJohn.Forte@Sun.COM 		if (err) {
9157836SJohn.Forte@Sun.COM 			if (err == RPC_INTR)
9167836SJohn.Forte@Sun.COM 				ret = EINTR;
9177836SJohn.Forte@Sun.COM 			else if (err && ret != EPROTO)
9187836SJohn.Forte@Sun.COM 				ret = ENOLINK;
9197836SJohn.Forte@Sun.COM #ifdef DEBUG
9207836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
9219093SRamana.Srikanth@Sun.COM 			    "!rdc_net_write(5): cd %d err %d ret %d",
9229093SRamana.Srikanth@Sun.COM 			    remote_index, err, ret);
9237836SJohn.Forte@Sun.COM #endif
9247836SJohn.Forte@Sun.COM 			goto remote_error;
9257836SJohn.Forte@Sun.COM 		}
9267836SJohn.Forte@Sun.COM 		/* Error from r_net_write5 */
9277836SJohn.Forte@Sun.COM 		if (netresptr->result < 0) {
9287836SJohn.Forte@Sun.COM #ifdef DEBUG
9297836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
9309093SRamana.Srikanth@Sun.COM 			    "!rdc_net_write: r_net_write(5) "
9317836SJohn.Forte@Sun.COM 			    "returned: %d",
9327836SJohn.Forte@Sun.COM 			    -netresptr->result);
9337836SJohn.Forte@Sun.COM #endif
9347836SJohn.Forte@Sun.COM 			ret = -netresptr->result;
9357836SJohn.Forte@Sun.COM 			if (netret.vecdata.vecdata_val)
9367836SJohn.Forte@Sun.COM 				kmem_free(netret.vecdata.vecdata_val,
9377836SJohn.Forte@Sun.COM 				    netret.vecdata.vecdata_len *
9387836SJohn.Forte@Sun.COM 				    sizeof (net_pendvec_t));
9397836SJohn.Forte@Sun.COM 			goto remote_error;
9407836SJohn.Forte@Sun.COM 		} else if (netresptr->index == 0) {
9417836SJohn.Forte@Sun.COM #ifdef DEBUG
9427836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
9439093SRamana.Srikanth@Sun.COM 			    "!rdc_net_write: no valid index from "
9447836SJohn.Forte@Sun.COM 			    "r_net_write(5)");
9457836SJohn.Forte@Sun.COM #endif
9467836SJohn.Forte@Sun.COM 			ret = ENOBUFS;
9477836SJohn.Forte@Sun.COM 			if (netret.vecdata.vecdata_val)
9487836SJohn.Forte@Sun.COM 				kmem_free(netret.vecdata.vecdata_val,
9497836SJohn.Forte@Sun.COM 				    netret.vecdata.vecdata_len *
9507836SJohn.Forte@Sun.COM 				    sizeof (net_pendvec_t));
9517836SJohn.Forte@Sun.COM 			goto remote_error;
9527836SJohn.Forte@Sun.COM 		}
9537836SJohn.Forte@Sun.COM 		if (krdc->rpc_version <= RDC_VERSION5) {
9547836SJohn.Forte@Sun.COM 			dlist5.idx = netresptr->index;
9557836SJohn.Forte@Sun.COM 			dlist5.sfba += dlist5.nfba;
9567836SJohn.Forte@Sun.COM 		} else {
9577836SJohn.Forte@Sun.COM 			dlist6.idx = netresptr->index;
9587836SJohn.Forte@Sun.COM 			dlist6.sfba += dlist6.nfba;
9597836SJohn.Forte@Sun.COM 		}
9607836SJohn.Forte@Sun.COM 		/* update counters */
9617836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
9627836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->writes++;
9637836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->nwritten +=
9649093SRamana.Srikanth@Sun.COM 			    FBA_SIZE(translen);
9657836SJohn.Forte@Sun.COM 		}
9667836SJohn.Forte@Sun.COM 		transptr += FBA_SIZE(translen);
9677836SJohn.Forte@Sun.COM 		sv_len -= FBA_SIZE(translen);
9687836SJohn.Forte@Sun.COM 
9697836SJohn.Forte@Sun.COM 		if (sv_len <= 0) {
9707836SJohn.Forte@Sun.COM 			/* goto next vector */
9717836SJohn.Forte@Sun.COM 			vec++;
9727836SJohn.Forte@Sun.COM 			transptr = (char *)vec->sv_addr;
9737836SJohn.Forte@Sun.COM 			sv_len = vec->sv_len;
9747836SJohn.Forte@Sun.COM 		}
9757836SJohn.Forte@Sun.COM 	}
9767836SJohn.Forte@Sun.COM 	/*
9777836SJohn.Forte@Sun.COM 	 * this can't happen.....
9787836SJohn.Forte@Sun.COM 	 */
9797836SJohn.Forte@Sun.COM 	if (netret.vecdata.vecdata_val)
9807836SJohn.Forte@Sun.COM 		kmem_free(netret.vecdata.vecdata_val,
9817836SJohn.Forte@Sun.COM 		    netret.vecdata.vecdata_len *
9827836SJohn.Forte@Sun.COM 		    sizeof (net_pendvec_t));
9837836SJohn.Forte@Sun.COM 
9847836SJohn.Forte@Sun.COM 	return (0);
9857836SJohn.Forte@Sun.COM 
9867836SJohn.Forte@Sun.COM remote_error:
9877836SJohn.Forte@Sun.COM 	return (ret ? ret : ENOLINK);
9887836SJohn.Forte@Sun.COM }
9897836SJohn.Forte@Sun.COM 
9907836SJohn.Forte@Sun.COM void
rdc_fixlen(rdc_aio_t * aio)9917836SJohn.Forte@Sun.COM rdc_fixlen(rdc_aio_t *aio)
9927836SJohn.Forte@Sun.COM {
9937836SJohn.Forte@Sun.COM 	nsc_vec_t *vecp = aio->qhandle->sb_vec;
9947836SJohn.Forte@Sun.COM 	nsc_size_t len = 0;
9957836SJohn.Forte@Sun.COM 
9967836SJohn.Forte@Sun.COM 	while (vecp->sv_addr) {
9977836SJohn.Forte@Sun.COM 		len += FBA_NUM(vecp->sv_len);
9987836SJohn.Forte@Sun.COM 		vecp++;
9997836SJohn.Forte@Sun.COM 	}
10007836SJohn.Forte@Sun.COM 	aio->qhandle->sb_len = len;
10017836SJohn.Forte@Sun.COM }
10027836SJohn.Forte@Sun.COM 
10037836SJohn.Forte@Sun.COM /*
10047836SJohn.Forte@Sun.COM  * rdc_dump_alloc_bufs_cd
10057836SJohn.Forte@Sun.COM  * Dump allocated buffers (rdc_net_hnd's) for the specified cd.
10067836SJohn.Forte@Sun.COM  * this could be the flusher failing, if so, don't do the delay forever
10077836SJohn.Forte@Sun.COM  * Returns: 0 (success), EAGAIN (caller needs to try again).
10087836SJohn.Forte@Sun.COM  */
10097836SJohn.Forte@Sun.COM int
rdc_dump_alloc_bufs_cd(int index)10107836SJohn.Forte@Sun.COM rdc_dump_alloc_bufs_cd(int index)
10117836SJohn.Forte@Sun.COM {
10127836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
10137836SJohn.Forte@Sun.COM 	rdc_aio_t *aio;
10147836SJohn.Forte@Sun.COM 	net_queue *q;
10157836SJohn.Forte@Sun.COM 	disk_queue *dq;
10167836SJohn.Forte@Sun.COM 	kmutex_t *qlock;
10177836SJohn.Forte@Sun.COM 
10187836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
10197836SJohn.Forte@Sun.COM 
10207836SJohn.Forte@Sun.COM 
10217836SJohn.Forte@Sun.COM 	if (!krdc->c_fd) {
10227836SJohn.Forte@Sun.COM 		/* cannot do anything! */
10237836SJohn.Forte@Sun.COM #ifdef DEBUG
10249093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_dump_alloc_bufs_cd(%d): c_fd NULL",
10257836SJohn.Forte@Sun.COM 		    index);
10267836SJohn.Forte@Sun.COM #endif
10277836SJohn.Forte@Sun.COM 		return (0);
10287836SJohn.Forte@Sun.COM 	}
10297836SJohn.Forte@Sun.COM 	rdc_dump_dsets(index);
10307836SJohn.Forte@Sun.COM 
10317836SJohn.Forte@Sun.COM 	dq = &krdc->group->diskq;
10327836SJohn.Forte@Sun.COM 
10337836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
10347836SJohn.Forte@Sun.COM 		qlock = QLOCK(dq);
10357836SJohn.Forte@Sun.COM 		(void) _rdc_rsrv_diskq(krdc->group);
10367836SJohn.Forte@Sun.COM 	} else {
10377836SJohn.Forte@Sun.COM 		qlock = &krdc->group->ra_queue.net_qlock;
10387836SJohn.Forte@Sun.COM 	}
10397836SJohn.Forte@Sun.COM 
10407836SJohn.Forte@Sun.COM 	/*
10417836SJohn.Forte@Sun.COM 	 * Now dump the async queue anonymous buffers
10427836SJohn.Forte@Sun.COM 	 * if we are a diskq, the we are using the diskq mutex.
10437836SJohn.Forte@Sun.COM 	 * However, we are flushing from diskq to memory queue
10447836SJohn.Forte@Sun.COM 	 * so we now need to grab the memory lock also
10457836SJohn.Forte@Sun.COM 	 */
10467836SJohn.Forte@Sun.COM 
10477836SJohn.Forte@Sun.COM 	q = &krdc->group->ra_queue;
10487836SJohn.Forte@Sun.COM 
10497836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
10507836SJohn.Forte@Sun.COM 		mutex_enter(&q->net_qlock);
10517836SJohn.Forte@Sun.COM 		if (q->qfill_sleeping == RDC_QFILL_AWAKE) {
10527836SJohn.Forte@Sun.COM 			int tries = 5;
10537836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
10547836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
10559093SRamana.Srikanth@Sun.COM 			    "!dumpalloccd sending diskq->memq flush to sleep");
10567836SJohn.Forte@Sun.COM #endif
10577836SJohn.Forte@Sun.COM 			q->qfflags |= RDC_QFILLSLEEP;
10587836SJohn.Forte@Sun.COM 			mutex_exit(&q->net_qlock);
10597836SJohn.Forte@Sun.COM 
10607836SJohn.Forte@Sun.COM 			while (q->qfill_sleeping == RDC_QFILL_AWAKE && tries--)
10617836SJohn.Forte@Sun.COM 				delay(5);
10627836SJohn.Forte@Sun.COM 			mutex_enter(&q->net_qlock);
10637836SJohn.Forte@Sun.COM 		}
10647836SJohn.Forte@Sun.COM 	}
10657836SJohn.Forte@Sun.COM 
10667836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
10677836SJohn.Forte@Sun.COM 
10687836SJohn.Forte@Sun.COM 	while ((q->net_qhead != NULL)) {
10697836SJohn.Forte@Sun.COM 		rdc_k_info_t *tmpkrdc;
10707836SJohn.Forte@Sun.COM 		aio = q->net_qhead;
10717836SJohn.Forte@Sun.COM 		tmpkrdc = &rdc_k_info[aio->index];
10727836SJohn.Forte@Sun.COM 
10737836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(krdc->group)) {
10747836SJohn.Forte@Sun.COM 			aio->qhandle->sb_user--;
10757836SJohn.Forte@Sun.COM 			if (aio->qhandle->sb_user == 0) {
10767836SJohn.Forte@Sun.COM 				rdc_fixlen(aio);
10777836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(aio->qhandle);
10787836SJohn.Forte@Sun.COM 				aio->qhandle = NULL;
10797836SJohn.Forte@Sun.COM 				aio->handle = NULL;
10807836SJohn.Forte@Sun.COM 			}
10817836SJohn.Forte@Sun.COM 		} else {
10827836SJohn.Forte@Sun.COM 			if (aio->handle) {
10837836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(aio->handle);
10847836SJohn.Forte@Sun.COM 				aio->handle = NULL;
10857836SJohn.Forte@Sun.COM 			}
10867836SJohn.Forte@Sun.COM 		}
10877836SJohn.Forte@Sun.COM 
10887836SJohn.Forte@Sun.COM 		if (tmpkrdc->io_kstats && !RDC_IS_DISKQ(krdc->group)) {
10897836SJohn.Forte@Sun.COM 			mutex_enter(tmpkrdc->io_kstats->ks_lock);
10907836SJohn.Forte@Sun.COM 			kstat_waitq_exit(KSTAT_IO_PTR(tmpkrdc->io_kstats));
10917836SJohn.Forte@Sun.COM 			mutex_exit(tmpkrdc->io_kstats->ks_lock);
10927836SJohn.Forte@Sun.COM 		}
10937836SJohn.Forte@Sun.COM 		q->net_qhead = q->net_qhead->next;
10947836SJohn.Forte@Sun.COM 		q->blocks -= aio->len;
10957836SJohn.Forte@Sun.COM 		q->nitems--;
10967836SJohn.Forte@Sun.COM 
10977836SJohn.Forte@Sun.COM 		RDC_CHECK_BIT(tmpkrdc, aio->pos, aio->len);
10987836SJohn.Forte@Sun.COM 
10997836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
11007836SJohn.Forte@Sun.COM 	}
11017836SJohn.Forte@Sun.COM 	q->net_qtail = NULL;
11027836SJohn.Forte@Sun.COM 
11037836SJohn.Forte@Sun.COM 	if (krdc->group->asyncstall) {
11047836SJohn.Forte@Sun.COM 		krdc->group->asyncdis = 1;
11057836SJohn.Forte@Sun.COM 		cv_broadcast(&krdc->group->asyncqcv);
11067836SJohn.Forte@Sun.COM 	}
11077836SJohn.Forte@Sun.COM 	if (krdc->group->sleepq) {
11087836SJohn.Forte@Sun.COM 		rdc_sleepqdiscard(krdc->group);
11097836SJohn.Forte@Sun.COM 	}
11107836SJohn.Forte@Sun.COM 
11117836SJohn.Forte@Sun.COM 	krdc->group->seq = RDC_NEWSEQ;
11127836SJohn.Forte@Sun.COM 	krdc->group->seqack = RDC_NEWSEQ;
11137836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
11147836SJohn.Forte@Sun.COM 		rdc_dump_iohdrs(dq);
11157836SJohn.Forte@Sun.COM 		SET_QNXTIO(dq, QHEAD(dq));
11167836SJohn.Forte@Sun.COM 		SET_QCOALBOUNDS(dq, QHEAD(dq));
11177836SJohn.Forte@Sun.COM 	}
11187836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
11197836SJohn.Forte@Sun.COM 
11207836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
11217836SJohn.Forte@Sun.COM 		mutex_exit(&q->net_qlock);
11227836SJohn.Forte@Sun.COM 		_rdc_rlse_diskq(krdc->group);
11237836SJohn.Forte@Sun.COM 	}
11247836SJohn.Forte@Sun.COM 
11257836SJohn.Forte@Sun.COM 	return (0);
11267836SJohn.Forte@Sun.COM }
11277836SJohn.Forte@Sun.COM 
11287836SJohn.Forte@Sun.COM 
11297836SJohn.Forte@Sun.COM /*
11307836SJohn.Forte@Sun.COM  * rdc_dump_alloc_bufs
11317836SJohn.Forte@Sun.COM  * We have an error on the link
11327836SJohn.Forte@Sun.COM  * Try to dump all of the allocated bufs so we can cleanly recover
11337836SJohn.Forte@Sun.COM  * and not hang
11347836SJohn.Forte@Sun.COM  */
11357836SJohn.Forte@Sun.COM void
rdc_dump_alloc_bufs(rdc_if_t * ip)11367836SJohn.Forte@Sun.COM rdc_dump_alloc_bufs(rdc_if_t *ip)
11377836SJohn.Forte@Sun.COM {
11387836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
11397836SJohn.Forte@Sun.COM 	int repeat;
11407836SJohn.Forte@Sun.COM 	int index;
11417836SJohn.Forte@Sun.COM 
11427836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
11437836SJohn.Forte@Sun.COM 		do {
11447836SJohn.Forte@Sun.COM 			krdc = &rdc_k_info[index];
11457836SJohn.Forte@Sun.COM 			repeat = 0;
11467836SJohn.Forte@Sun.COM 			if (krdc->intf == ip) {
11477836SJohn.Forte@Sun.COM 				if (rdc_dump_alloc_bufs_cd(index) == EAGAIN) {
11487836SJohn.Forte@Sun.COM 					repeat = 1;
11497836SJohn.Forte@Sun.COM 					delay(2);
11507836SJohn.Forte@Sun.COM 				}
11517836SJohn.Forte@Sun.COM 			}
11527836SJohn.Forte@Sun.COM 		} while (repeat);
11537836SJohn.Forte@Sun.COM 	}
11547836SJohn.Forte@Sun.COM }
11557836SJohn.Forte@Sun.COM 
11567836SJohn.Forte@Sun.COM /*
11577836SJohn.Forte@Sun.COM  * returns 1 if the the throttle should throttle, 0 if not.
11587836SJohn.Forte@Sun.COM  */
11597836SJohn.Forte@Sun.COM int
_rdc_diskq_isfull(disk_queue * q,long len)11607836SJohn.Forte@Sun.COM _rdc_diskq_isfull(disk_queue *q, long len)
11617836SJohn.Forte@Sun.COM {
11627836SJohn.Forte@Sun.COM 	/* ---T----H----N--- */
11637836SJohn.Forte@Sun.COM 	mutex_enter(QLOCK(q));
11647836SJohn.Forte@Sun.COM 
11657836SJohn.Forte@Sun.COM 	if (FITSONQ(q, len + 1)) {
11667836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(q));
11677836SJohn.Forte@Sun.COM 		return (0);
11687836SJohn.Forte@Sun.COM 	}
11697836SJohn.Forte@Sun.COM 	mutex_exit(QLOCK(q));
11707836SJohn.Forte@Sun.COM 	return (1);
11717836SJohn.Forte@Sun.COM }
11727836SJohn.Forte@Sun.COM 
11737836SJohn.Forte@Sun.COM void
_rdc_async_throttle(rdc_k_info_t * this,long len)11747836SJohn.Forte@Sun.COM _rdc_async_throttle(rdc_k_info_t *this, long len)
11757836SJohn.Forte@Sun.COM {
11767836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
11777836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
11787836SJohn.Forte@Sun.COM 	int print_msg = 1;
11797836SJohn.Forte@Sun.COM 	int tries = RDC_FUTILE_ATTEMPTS;
11807836SJohn.Forte@Sun.COM 
11817836SJohn.Forte@Sun.COM 	/*
11827836SJohn.Forte@Sun.COM 	 * Throttle entries on queue
11837836SJohn.Forte@Sun.COM 	 */
11847836SJohn.Forte@Sun.COM 
11857836SJohn.Forte@Sun.COM 	/* Need to take the 1-many case into account, checking all sets */
11867836SJohn.Forte@Sun.COM 
11877836SJohn.Forte@Sun.COM 	/* ADD HANDY HUERISTIC HERE TO SLOW DOWN IO */
11887836SJohn.Forte@Sun.COM 	for (krdc = this; /* CSTYLED */; krdc = krdc->many_next) {
11897836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[krdc->index];
11907836SJohn.Forte@Sun.COM 
11917836SJohn.Forte@Sun.COM 		/*
11927836SJohn.Forte@Sun.COM 		 * this may be the last set standing in a one to many setup.
11937836SJohn.Forte@Sun.COM 		 * we may also be stuck in unintercept, after marking
11947836SJohn.Forte@Sun.COM 		 * the volume as not enabled, but have not removed it
11957836SJohn.Forte@Sun.COM 		 * from the many list resulting in an endless loop if
11967836SJohn.Forte@Sun.COM 		 * we just continue here. Lets jump over this stuff
11977836SJohn.Forte@Sun.COM 		 * and check to see if we are the only dude here.
11987836SJohn.Forte@Sun.COM 		 */
11997836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
12007836SJohn.Forte@Sun.COM 			goto thischeck;
12017836SJohn.Forte@Sun.COM 
12027836SJohn.Forte@Sun.COM 		if (IS_ASYNC(urdc) && RDC_IS_MEMQ(krdc->group)) {
12037836SJohn.Forte@Sun.COM 			net_queue *q = &krdc->group->ra_queue;
12047836SJohn.Forte@Sun.COM 			while ((q->blocks + q->inflbls) > urdc->maxqfbas ||
12057836SJohn.Forte@Sun.COM 			    (q->nitems + q->inflitems) > urdc->maxqitems) {
12067836SJohn.Forte@Sun.COM 
12077836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(urdc)) /* disable race */
12087836SJohn.Forte@Sun.COM 					goto thischeck;
12097836SJohn.Forte@Sun.COM 
12107836SJohn.Forte@Sun.COM 				if (!krdc->group->rdc_writer)
12117836SJohn.Forte@Sun.COM 					(void) rdc_writer(krdc->index);
12127836SJohn.Forte@Sun.COM 				delay(2);
12137836SJohn.Forte@Sun.COM 				q->throttle_delay++;
12147836SJohn.Forte@Sun.COM 			}
12157836SJohn.Forte@Sun.COM 		}
12167836SJohn.Forte@Sun.COM 
12177836SJohn.Forte@Sun.COM 		/* do a much more aggressive delay, get disk flush going */
12187836SJohn.Forte@Sun.COM 		if (IS_ASYNC(urdc) && RDC_IS_DISKQ(krdc->group)) {
12197836SJohn.Forte@Sun.COM 			disk_queue *q = &krdc->group->diskq;
12207836SJohn.Forte@Sun.COM 			while ((!IS_QSTATE(q, RDC_QNOBLOCK)) &&
12217836SJohn.Forte@Sun.COM 			    (_rdc_diskq_isfull(q, len)) &&
12227836SJohn.Forte@Sun.COM 			    (!IS_STATE(urdc, RDC_DISKQ_FAILED))) {
12237836SJohn.Forte@Sun.COM 				if (print_msg) {
12249093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!rdc async throttle:"
12257836SJohn.Forte@Sun.COM 					    " disk queue %s full",
12267836SJohn.Forte@Sun.COM 					    &urdc->disk_queue[0]);
12277836SJohn.Forte@Sun.COM 
12287836SJohn.Forte@Sun.COM 					print_msg = 0;
12297836SJohn.Forte@Sun.COM 				}
12307836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(urdc)) /* disable race */
12317836SJohn.Forte@Sun.COM 					goto thischeck;
12327836SJohn.Forte@Sun.COM 
12337836SJohn.Forte@Sun.COM 				if (!krdc->group->rdc_writer)
12347836SJohn.Forte@Sun.COM 					(void) rdc_writer(krdc->index);
12357836SJohn.Forte@Sun.COM 				delay(10);
12367836SJohn.Forte@Sun.COM 				q->throttle_delay += 10;
12377836SJohn.Forte@Sun.COM 
12387836SJohn.Forte@Sun.COM 				if (!(tries--) && IS_STATE(urdc, RDC_QUEUING)) {
12399093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!SNDR: disk queue "
12409093SRamana.Srikanth@Sun.COM 					    "%s full & not flushing. giving up",
12419093SRamana.Srikanth@Sun.COM 					    &urdc->disk_queue[0]);
12429093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!SNDR: %s:%s entering"
12439093SRamana.Srikanth@Sun.COM 					    " logging mode",
12449093SRamana.Srikanth@Sun.COM 					    urdc->secondary.intf,
12459093SRamana.Srikanth@Sun.COM 					    urdc->secondary.file);
12467836SJohn.Forte@Sun.COM 					rdc_fail_diskq(krdc, RDC_WAIT,
12477836SJohn.Forte@Sun.COM 					    RDC_DOLOG | RDC_NOFAIL);
12487836SJohn.Forte@Sun.COM 					mutex_enter(QLOCK(q));
12497836SJohn.Forte@Sun.COM 					cv_broadcast(&q->qfullcv);
12507836SJohn.Forte@Sun.COM 					mutex_exit(QLOCK(q));
12517836SJohn.Forte@Sun.COM 				}
12527836SJohn.Forte@Sun.COM 
12537836SJohn.Forte@Sun.COM 			}
12547836SJohn.Forte@Sun.COM 			if ((IS_QSTATE(q, RDC_QNOBLOCK)) &&
12557836SJohn.Forte@Sun.COM 			    _rdc_diskq_isfull(q, len) &&
12567836SJohn.Forte@Sun.COM 			    !IS_STATE(urdc, RDC_DISKQ_FAILED)) {
12577836SJohn.Forte@Sun.COM 				if (print_msg) {
12589093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!disk queue %s full",
12597836SJohn.Forte@Sun.COM 					    &urdc->disk_queue[0]);
12607836SJohn.Forte@Sun.COM 					print_msg = 0;
12617836SJohn.Forte@Sun.COM 				}
12627836SJohn.Forte@Sun.COM 				rdc_fail_diskq(krdc, RDC_WAIT,
12637836SJohn.Forte@Sun.COM 				    RDC_DOLOG | RDC_NOFAIL);
12647836SJohn.Forte@Sun.COM 				mutex_enter(QLOCK(q));
12657836SJohn.Forte@Sun.COM 				cv_broadcast(&q->qfullcv);
12667836SJohn.Forte@Sun.COM 				mutex_exit(QLOCK(q));
12677836SJohn.Forte@Sun.COM 			}
12687836SJohn.Forte@Sun.COM 		}
12697836SJohn.Forte@Sun.COM 
12707836SJohn.Forte@Sun.COM thischeck:
12717836SJohn.Forte@Sun.COM 		if (krdc->many_next == this)
12727836SJohn.Forte@Sun.COM 			break;
12737836SJohn.Forte@Sun.COM 	}
12747836SJohn.Forte@Sun.COM }
12757836SJohn.Forte@Sun.COM 
12767836SJohn.Forte@Sun.COM int rdc_coalesce = 1;
12777836SJohn.Forte@Sun.COM static int rdc_joins = 0;
12787836SJohn.Forte@Sun.COM 
12797836SJohn.Forte@Sun.COM int
rdc_aio_coalesce(rdc_aio_t * queued,rdc_aio_t * new)12807836SJohn.Forte@Sun.COM rdc_aio_coalesce(rdc_aio_t *queued, rdc_aio_t *new)
12817836SJohn.Forte@Sun.COM {
12827836SJohn.Forte@Sun.COM 	nsc_buf_t *h = NULL;
12837836SJohn.Forte@Sun.COM 	int rc;
12847836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
12857836SJohn.Forte@Sun.COM 	uint_t bitmask;
12867836SJohn.Forte@Sun.COM 
12877836SJohn.Forte@Sun.COM 	if (rdc_coalesce == 0)
12887836SJohn.Forte@Sun.COM 		return (0);		/* don't even try */
12897836SJohn.Forte@Sun.COM 
12907836SJohn.Forte@Sun.COM 	if ((queued == NULL) ||
12917836SJohn.Forte@Sun.COM 	    (queued->handle == NULL) ||
12927836SJohn.Forte@Sun.COM 	    (new->handle == NULL)) {
12937836SJohn.Forte@Sun.COM 		return (0);		/* existing queue is empty */
12947836SJohn.Forte@Sun.COM 	}
12957836SJohn.Forte@Sun.COM 	if (queued->index != new->index || queued->len + new->len >
12967836SJohn.Forte@Sun.COM 	    MAX_RDC_FBAS) {
12977836SJohn.Forte@Sun.COM 		return (0);		/* I/O to big */
12987836SJohn.Forte@Sun.COM 	}
12997836SJohn.Forte@Sun.COM 	if ((queued->pos + queued->len == new->pos) ||
13007836SJohn.Forte@Sun.COM 	    (new->pos + new->len == queued->pos)) {
13017836SJohn.Forte@Sun.COM 		rc = nsc_alloc_abuf(queued->pos, queued->len + new->len, 0,
13027836SJohn.Forte@Sun.COM 		    &h);
13037836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(rc)) {
13047836SJohn.Forte@Sun.COM 			if (h != NULL)
13057836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(h);
13067836SJohn.Forte@Sun.COM 			return (0);		/* couldn't do coalesce */
13077836SJohn.Forte@Sun.COM 		}
13087836SJohn.Forte@Sun.COM 		rc = nsc_copy(queued->handle, h, queued->pos, queued->pos,
13097836SJohn.Forte@Sun.COM 		    queued->len);
13107836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(rc)) {
13117836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(h);
13127836SJohn.Forte@Sun.COM 			return (0);		/* couldn't do coalesce */
13137836SJohn.Forte@Sun.COM 		}
13147836SJohn.Forte@Sun.COM 		rc = nsc_copy(new->handle, h, new->pos, new->pos,
13157836SJohn.Forte@Sun.COM 		    new->len);
13167836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(rc)) {
13177836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(h);
13187836SJohn.Forte@Sun.COM 			return (0);		/* couldn't do coalesce */
13197836SJohn.Forte@Sun.COM 		}
13207836SJohn.Forte@Sun.COM 
13217836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[queued->index];
13227836SJohn.Forte@Sun.COM 
13237836SJohn.Forte@Sun.COM 		RDC_SET_BITMASK(queued->pos, queued->len, &bitmask);
13247836SJohn.Forte@Sun.COM 		RDC_CLR_BITMAP(krdc, queued->pos, queued->len, \
13257836SJohn.Forte@Sun.COM 		    bitmask, RDC_BIT_BUMP);
13267836SJohn.Forte@Sun.COM 
13277836SJohn.Forte@Sun.COM 		RDC_SET_BITMASK(new->pos, new->len, &bitmask);
13287836SJohn.Forte@Sun.COM 		RDC_CLR_BITMAP(krdc, new->pos, new->len, \
13297836SJohn.Forte@Sun.COM 		    bitmask, RDC_BIT_BUMP);
13307836SJohn.Forte@Sun.COM 
13317836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(queued->handle);
13327836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(new->handle);
13337836SJohn.Forte@Sun.COM 		queued->handle = h;
13347836SJohn.Forte@Sun.COM 		queued->len += new->len;
13357836SJohn.Forte@Sun.COM 		bitmask = 0;
13367836SJohn.Forte@Sun.COM 		/*
13377836SJohn.Forte@Sun.COM 		 * bump the ref count back up
13387836SJohn.Forte@Sun.COM 		 */
13397836SJohn.Forte@Sun.COM 
13407836SJohn.Forte@Sun.COM 		RDC_SET_BITMAP(krdc, queued->pos, queued->len, &bitmask);
13417836SJohn.Forte@Sun.COM 		return (1);	/* new I/O succeeds last I/O queued */
13427836SJohn.Forte@Sun.COM 	}
13437836SJohn.Forte@Sun.COM 	return (0);
13447836SJohn.Forte@Sun.COM }
13457836SJohn.Forte@Sun.COM 
13467836SJohn.Forte@Sun.COM int
rdc_memq_enqueue(rdc_k_info_t * krdc,rdc_aio_t * aio)13477836SJohn.Forte@Sun.COM rdc_memq_enqueue(rdc_k_info_t *krdc, rdc_aio_t *aio)
13487836SJohn.Forte@Sun.COM {
13497836SJohn.Forte@Sun.COM 	net_queue *q;
13507836SJohn.Forte@Sun.COM 	rdc_group_t *group;
13517836SJohn.Forte@Sun.COM 
13527836SJohn.Forte@Sun.COM 	group = krdc->group;
13537836SJohn.Forte@Sun.COM 	q = &group->ra_queue;
13547836SJohn.Forte@Sun.COM 
13557836SJohn.Forte@Sun.COM 	mutex_enter(&q->net_qlock);
13567836SJohn.Forte@Sun.COM 
13577836SJohn.Forte@Sun.COM 	if (rdc_aio_coalesce(q->net_qtail, aio)) {
13587836SJohn.Forte@Sun.COM 		rdc_joins++;
13597836SJohn.Forte@Sun.COM 		q->blocks += aio->len;
13607836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
13617836SJohn.Forte@Sun.COM 		goto out;
13627836SJohn.Forte@Sun.COM 	}
13637836SJohn.Forte@Sun.COM 	aio->seq = group->seq++;
13647836SJohn.Forte@Sun.COM 	if (group->seq < aio->seq)
13657836SJohn.Forte@Sun.COM 		group->seq = RDC_NEWSEQ + 1; /* skip magics */
13667836SJohn.Forte@Sun.COM 
13677836SJohn.Forte@Sun.COM 	if (q->net_qhead == NULL) {
13687836SJohn.Forte@Sun.COM 		/* adding to empty q */
13697836SJohn.Forte@Sun.COM 		q->net_qhead = q->net_qtail = aio;
13707836SJohn.Forte@Sun.COM 
13717836SJohn.Forte@Sun.COM #ifdef DEBUG
13727836SJohn.Forte@Sun.COM 		if (q->blocks != 0 || q->nitems != 0) {
13737836SJohn.Forte@Sun.COM 			cmn_err(CE_PANIC,
13749093SRamana.Srikanth@Sun.COM 			    "rdc enqueue: q %p, qhead 0, q blocks %" NSC_SZFMT
13759093SRamana.Srikanth@Sun.COM 			    ", nitems %" NSC_SZFMT,
13769093SRamana.Srikanth@Sun.COM 			    (void *) q, q->blocks, q->nitems);
13777836SJohn.Forte@Sun.COM 		}
13787836SJohn.Forte@Sun.COM #endif
13797836SJohn.Forte@Sun.COM 
13807836SJohn.Forte@Sun.COM 	} else {
13817836SJohn.Forte@Sun.COM 		/* discontiguous, add aio to q tail */
13827836SJohn.Forte@Sun.COM 		q->net_qtail->next = aio;
13837836SJohn.Forte@Sun.COM 		q->net_qtail = aio;
13847836SJohn.Forte@Sun.COM 	}
13857836SJohn.Forte@Sun.COM 
13867836SJohn.Forte@Sun.COM 	q->blocks += aio->len;
13877836SJohn.Forte@Sun.COM 	q->nitems++;
13887836SJohn.Forte@Sun.COM 
13897836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
13907836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
13917836SJohn.Forte@Sun.COM 		kstat_waitq_enter(KSTAT_IO_PTR(krdc->io_kstats));
13927836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
13937836SJohn.Forte@Sun.COM 	}
13947836SJohn.Forte@Sun.COM out:
13957836SJohn.Forte@Sun.COM #ifdef DEBUG
13967836SJohn.Forte@Sun.COM 	/* sum the q and check for sanity */
13977836SJohn.Forte@Sun.COM 	{
13987836SJohn.Forte@Sun.COM 		nsc_size_t qblocks = 0;
13997836SJohn.Forte@Sun.COM 		uint64_t nitems = 0;
14007836SJohn.Forte@Sun.COM 		rdc_aio_t *a;
14017836SJohn.Forte@Sun.COM 
14027836SJohn.Forte@Sun.COM 		for (a = q->net_qhead; a != NULL; a = a->next) {
14037836SJohn.Forte@Sun.COM 			qblocks += a->len;
14047836SJohn.Forte@Sun.COM 			nitems++;
14057836SJohn.Forte@Sun.COM 		}
14067836SJohn.Forte@Sun.COM 
14077836SJohn.Forte@Sun.COM 		if (qblocks != q->blocks || nitems != q->nitems) {
14087836SJohn.Forte@Sun.COM 			cmn_err(CE_PANIC,
14099093SRamana.Srikanth@Sun.COM 			    "rdc enqueue: q %p, q blocks %" NSC_SZFMT " (%"
14109093SRamana.Srikanth@Sun.COM 			    NSC_SZFMT "), nitems %" NSC_SZFMT " (%"
14119093SRamana.Srikanth@Sun.COM 			    NSC_SZFMT ")", (void *) q, q->blocks, qblocks,
14129093SRamana.Srikanth@Sun.COM 			    q->nitems, nitems);
14137836SJohn.Forte@Sun.COM 		}
14147836SJohn.Forte@Sun.COM 	}
14157836SJohn.Forte@Sun.COM #endif
14167836SJohn.Forte@Sun.COM 
14177836SJohn.Forte@Sun.COM 	mutex_exit(&q->net_qlock);
14187836SJohn.Forte@Sun.COM 
14197836SJohn.Forte@Sun.COM 	if (q->nitems > q->nitems_hwm) {
14207836SJohn.Forte@Sun.COM 		q->nitems_hwm = q->nitems;
14217836SJohn.Forte@Sun.COM 	}
14227836SJohn.Forte@Sun.COM 
14237836SJohn.Forte@Sun.COM 	if (q->blocks > q->blocks_hwm) {
14247836SJohn.Forte@Sun.COM 		q->blocks_hwm = q->blocks;
14257836SJohn.Forte@Sun.COM 	}
14267836SJohn.Forte@Sun.COM 
14277836SJohn.Forte@Sun.COM 	if (!krdc->group->rdc_writer)
14287836SJohn.Forte@Sun.COM 		(void) rdc_writer(krdc->index);
14297836SJohn.Forte@Sun.COM 
14307836SJohn.Forte@Sun.COM 	return (0);
14317836SJohn.Forte@Sun.COM }
14327836SJohn.Forte@Sun.COM 
14337836SJohn.Forte@Sun.COM int
_rdc_enqueue_write(rdc_k_info_t * krdc,nsc_off_t pos,nsc_size_t len,int flag,nsc_buf_t * h)14347836SJohn.Forte@Sun.COM _rdc_enqueue_write(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len, int flag,
14357836SJohn.Forte@Sun.COM     nsc_buf_t *h)
14367836SJohn.Forte@Sun.COM {
14377836SJohn.Forte@Sun.COM 	rdc_aio_t *aio;
14387836SJohn.Forte@Sun.COM 	rdc_group_t *group;
14397836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
14407836SJohn.Forte@Sun.COM 	int rc;
14417836SJohn.Forte@Sun.COM 
14427836SJohn.Forte@Sun.COM 	aio = kmem_zalloc(sizeof (*aio), KM_NOSLEEP);
14437836SJohn.Forte@Sun.COM 	if (!aio) {
14447836SJohn.Forte@Sun.COM 		return (ENOMEM);
14457836SJohn.Forte@Sun.COM 	}
14467836SJohn.Forte@Sun.COM 
14477836SJohn.Forte@Sun.COM 	group = krdc->group;
14487836SJohn.Forte@Sun.COM 
14497836SJohn.Forte@Sun.COM 	aio->pos = pos;
14507836SJohn.Forte@Sun.COM 	aio->qpos = -1;
14517836SJohn.Forte@Sun.COM 	aio->len = len;
14527836SJohn.Forte@Sun.COM 	aio->flag = flag;
14537836SJohn.Forte@Sun.COM 	aio->index = krdc->index;
14547836SJohn.Forte@Sun.COM 	aio->handle = h;
14557836SJohn.Forte@Sun.COM 
14567836SJohn.Forte@Sun.COM 	if (group->flags & RDC_MEMQUE) {
14577836SJohn.Forte@Sun.COM 		return (rdc_memq_enqueue(krdc, aio));
14587836SJohn.Forte@Sun.COM 	} else if ((group->flags & RDC_DISKQUE) &&
14597836SJohn.Forte@Sun.COM 	    !IS_STATE(urdc, RDC_DISKQ_FAILED)) {
14607836SJohn.Forte@Sun.COM 		rc = rdc_diskq_enqueue(krdc, aio);
14617836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
14627836SJohn.Forte@Sun.COM 		return (rc);
14637836SJohn.Forte@Sun.COM 	}
14647836SJohn.Forte@Sun.COM 	return (-1); /* keep lint quiet */
14657836SJohn.Forte@Sun.COM }
14667836SJohn.Forte@Sun.COM 
14677836SJohn.Forte@Sun.COM 
14687836SJohn.Forte@Sun.COM 
14697836SJohn.Forte@Sun.COM 
14707836SJohn.Forte@Sun.COM /*
14717836SJohn.Forte@Sun.COM  * Async Network RDC flusher
14727836SJohn.Forte@Sun.COM  */
14737836SJohn.Forte@Sun.COM 
14747836SJohn.Forte@Sun.COM /*
14757836SJohn.Forte@Sun.COM  * don't allow any new writer threads to start if a member of the set
14767836SJohn.Forte@Sun.COM  * is disable pending
14777836SJohn.Forte@Sun.COM  */
14787836SJohn.Forte@Sun.COM int
is_disable_pending(rdc_k_info_t * krdc)14797836SJohn.Forte@Sun.COM is_disable_pending(rdc_k_info_t *krdc)
14807836SJohn.Forte@Sun.COM {
14817836SJohn.Forte@Sun.COM 	rdc_k_info_t *this = krdc;
14827836SJohn.Forte@Sun.COM 	int rc = 0;
14837836SJohn.Forte@Sun.COM 
14847836SJohn.Forte@Sun.COM 	do {
14857836SJohn.Forte@Sun.COM 		if (krdc->type_flag & RDC_DISABLEPEND) {
14867836SJohn.Forte@Sun.COM 			krdc = this;
14877836SJohn.Forte@Sun.COM 			rc = 1;
14887836SJohn.Forte@Sun.COM 			break;
14897836SJohn.Forte@Sun.COM 		}
14907836SJohn.Forte@Sun.COM 		krdc = krdc->group_next;
14917836SJohn.Forte@Sun.COM 
14927836SJohn.Forte@Sun.COM 	} while (krdc != this);
14937836SJohn.Forte@Sun.COM 
14947836SJohn.Forte@Sun.COM 	return (rc);
14957836SJohn.Forte@Sun.COM }
14967836SJohn.Forte@Sun.COM 
14977836SJohn.Forte@Sun.COM /*
14987836SJohn.Forte@Sun.COM  * rdc_writer -- spawn new writer if not running already
14997836SJohn.Forte@Sun.COM  *	called after enqueing the dirty blocks
15007836SJohn.Forte@Sun.COM  */
15017836SJohn.Forte@Sun.COM int
rdc_writer(int index)15027836SJohn.Forte@Sun.COM rdc_writer(int index)
15037836SJohn.Forte@Sun.COM {
15047836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
15057836SJohn.Forte@Sun.COM 	nsthread_t *t;
15067836SJohn.Forte@Sun.COM 	rdc_group_t	*group;
15077836SJohn.Forte@Sun.COM 	kmutex_t	*qlock;
15087836SJohn.Forte@Sun.COM 	int tries;
15097836SJohn.Forte@Sun.COM 	const int MAX_TRIES = 16;
15107836SJohn.Forte@Sun.COM 
15117836SJohn.Forte@Sun.COM 	group = krdc->group;
15127836SJohn.Forte@Sun.COM 
15137836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group))
15147836SJohn.Forte@Sun.COM 		qlock = &group->diskq.disk_qlock;
15157836SJohn.Forte@Sun.COM 	else
15167836SJohn.Forte@Sun.COM 		qlock = &group->ra_queue.net_qlock;
15177836SJohn.Forte@Sun.COM 
15187836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
15197836SJohn.Forte@Sun.COM 
15207836SJohn.Forte@Sun.COM #ifdef DEBUG
15217836SJohn.Forte@Sun.COM 	if (noflush) {
15227836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
15237836SJohn.Forte@Sun.COM 		return (0);
15247836SJohn.Forte@Sun.COM 	}
15257836SJohn.Forte@Sun.COM #endif
15267836SJohn.Forte@Sun.COM 
15277836SJohn.Forte@Sun.COM 	if ((group->rdc_writer) || is_disable_pending(krdc)) {
15287836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
15297836SJohn.Forte@Sun.COM 		return (0);
15307836SJohn.Forte@Sun.COM 	}
15317836SJohn.Forte@Sun.COM 
15327836SJohn.Forte@Sun.COM 	if ((group->rdc_thrnum >= 1) && (group->seqack == RDC_NEWSEQ)) {
15337836SJohn.Forte@Sun.COM 		/*
15347836SJohn.Forte@Sun.COM 		 * We also need to check if we are starting a new
15357836SJohn.Forte@Sun.COM 		 * sequence, and if so don't create a new thread,
15367836SJohn.Forte@Sun.COM 		 * as we must ensure that the start of new sequence
15377836SJohn.Forte@Sun.COM 		 * requests arrives first to re-init the server.
15387836SJohn.Forte@Sun.COM 		 */
15397836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
15407836SJohn.Forte@Sun.COM 		return (0);
15417836SJohn.Forte@Sun.COM 	}
15427836SJohn.Forte@Sun.COM 	/*
15437836SJohn.Forte@Sun.COM 	 * For version 6,
15447836SJohn.Forte@Sun.COM 	 * see if we can fit in another thread.
15457836SJohn.Forte@Sun.COM 	 */
15467836SJohn.Forte@Sun.COM 	group->rdc_thrnum++;
15477836SJohn.Forte@Sun.COM 
15487836SJohn.Forte@Sun.COM 	if (krdc->intf && (krdc->intf->rpc_version >= RDC_VERSION6)) {
15497836SJohn.Forte@Sun.COM 		rdc_u_info_t *urdc = &rdc_u_info[index];
15507836SJohn.Forte@Sun.COM 		if (group->rdc_thrnum >= urdc->asyncthr)
15517836SJohn.Forte@Sun.COM 			group->rdc_writer = 1;
15527836SJohn.Forte@Sun.COM 	} else {
15537836SJohn.Forte@Sun.COM 		group->rdc_writer = 1;
15547836SJohn.Forte@Sun.COM 	}
15557836SJohn.Forte@Sun.COM 
15567836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
15577836SJohn.Forte@Sun.COM 
15587836SJohn.Forte@Sun.COM 
15597836SJohn.Forte@Sun.COM 	/*
15607836SJohn.Forte@Sun.COM 	 * If we got here, we know that we have not exceeded the allowed
15617836SJohn.Forte@Sun.COM 	 * number of async threads for our group.  If we run out of threads
15627836SJohn.Forte@Sun.COM 	 * in _rdc_flset, we add a new thread to the set.
15637836SJohn.Forte@Sun.COM 	 */
15647836SJohn.Forte@Sun.COM 	tries = 0;
15657836SJohn.Forte@Sun.COM 	do {
15667836SJohn.Forte@Sun.COM 		/* first try to grab a thread from the free list */
15677836SJohn.Forte@Sun.COM 		if (t = nst_create(_rdc_flset, rdc_flusher_thread,
15687836SJohn.Forte@Sun.COM 		    (blind_t)(unsigned long)index, 0)) {
15697836SJohn.Forte@Sun.COM 			break;
15707836SJohn.Forte@Sun.COM 		}
15717836SJohn.Forte@Sun.COM 
15727836SJohn.Forte@Sun.COM 		/* that failed; add a thread to the set and try again */
15737836SJohn.Forte@Sun.COM 		if (nst_add_thread(_rdc_flset, 1) != 1) {
15749093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!rdc_writer index %d nst_add_thread "
15757836SJohn.Forte@Sun.COM 			    "error, tries: %d", index, tries);
15767836SJohn.Forte@Sun.COM 			break;
15777836SJohn.Forte@Sun.COM 		}
15787836SJohn.Forte@Sun.COM 	} while (++tries < MAX_TRIES);
15797836SJohn.Forte@Sun.COM 
15807836SJohn.Forte@Sun.COM 	if (tries) {
15817836SJohn.Forte@Sun.COM 		mutex_enter(&group->addthrnumlk);
15827836SJohn.Forte@Sun.COM 		group->rdc_addthrnum += tries;
15837836SJohn.Forte@Sun.COM 		mutex_exit(&group->addthrnumlk);
15847836SJohn.Forte@Sun.COM 	}
15857836SJohn.Forte@Sun.COM 
15867836SJohn.Forte@Sun.COM 	if (t) {
15877836SJohn.Forte@Sun.COM 		return (1);
15887836SJohn.Forte@Sun.COM 	}
15897836SJohn.Forte@Sun.COM 
15909093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!rdc_writer: index %d nst_create error", index);
15917836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
15927836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
15937836SJohn.Forte@Sun.COM 	group->rdc_thrnum--;
15947836SJohn.Forte@Sun.COM 	group->rdc_writer = 0;
15957836SJohn.Forte@Sun.COM 	if ((group->count == 0) && (group->rdc_thrnum == 0)) {
15967836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
15977836SJohn.Forte@Sun.COM 		/*
15987836SJohn.Forte@Sun.COM 		 * Race with remove_from_group while write thread was
15997836SJohn.Forte@Sun.COM 		 * failing to be created.
16007836SJohn.Forte@Sun.COM 		 */
16017836SJohn.Forte@Sun.COM #ifdef DEBUG
16029093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_writer: group being destroyed");
16037836SJohn.Forte@Sun.COM #endif
16047836SJohn.Forte@Sun.COM 		rdc_delgroup(group);
16057836SJohn.Forte@Sun.COM 		krdc->group = NULL;
16067836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
16077836SJohn.Forte@Sun.COM 		return (-1);
16087836SJohn.Forte@Sun.COM 	}
16097836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
16107836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
16117836SJohn.Forte@Sun.COM 	return (-1);
16127836SJohn.Forte@Sun.COM }
16137836SJohn.Forte@Sun.COM 
16147836SJohn.Forte@Sun.COM /*
16157836SJohn.Forte@Sun.COM  * Either we need to flush the
16167836SJohn.Forte@Sun.COM  * kmem (net_queue) queue or the disk (disk_queue)
16177836SJohn.Forte@Sun.COM  * determine which, and do it.
16187836SJohn.Forte@Sun.COM  */
16197836SJohn.Forte@Sun.COM void
rdc_flusher_thread(int index)16207836SJohn.Forte@Sun.COM rdc_flusher_thread(int index)
16217836SJohn.Forte@Sun.COM {
16227836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
16237836SJohn.Forte@Sun.COM 
16247836SJohn.Forte@Sun.COM 	if (krdc->group->flags & RDC_MEMQUE) {
16257836SJohn.Forte@Sun.COM 		rdc_flush_memq(index);
16267836SJohn.Forte@Sun.COM 		return;
16277836SJohn.Forte@Sun.COM 	} else if (krdc->group->flags & RDC_DISKQUE) {
16287836SJohn.Forte@Sun.COM 		rdc_flush_diskq(index);
16297836SJohn.Forte@Sun.COM 		return;
16307836SJohn.Forte@Sun.COM 	} else { /* uh-oh, big time */
16317836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC, "flusher trying to flush unknown queue type");
16327836SJohn.Forte@Sun.COM 	}
16337836SJohn.Forte@Sun.COM 
16347836SJohn.Forte@Sun.COM }
16357836SJohn.Forte@Sun.COM 
16367836SJohn.Forte@Sun.COM void
rdc_flush_memq(int index)16377836SJohn.Forte@Sun.COM rdc_flush_memq(int index)
16387836SJohn.Forte@Sun.COM {
16397836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
16407836SJohn.Forte@Sun.COM 	rdc_aio_t *aio;
16417836SJohn.Forte@Sun.COM 	net_queue *q;
16427836SJohn.Forte@Sun.COM 	int dowork;
16437836SJohn.Forte@Sun.COM 	rdc_group_t *group = krdc->group;
16447836SJohn.Forte@Sun.COM 	if (!group || group->count == 0) {
16457836SJohn.Forte@Sun.COM #ifdef DEBUG
16469093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_memq: no group left!");
16477836SJohn.Forte@Sun.COM #endif
16487836SJohn.Forte@Sun.COM 		return;
16497836SJohn.Forte@Sun.COM 	}
16507836SJohn.Forte@Sun.COM 
16517836SJohn.Forte@Sun.COM 	if (!krdc->c_fd) {
16527836SJohn.Forte@Sun.COM #ifdef DEBUG
16539093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_memq: no c_fd!");
16547836SJohn.Forte@Sun.COM #endif
16557836SJohn.Forte@Sun.COM 		goto thread_death;
16567836SJohn.Forte@Sun.COM 	}
16577836SJohn.Forte@Sun.COM 
16587836SJohn.Forte@Sun.COM #ifdef DEBUG_DISABLE
16597836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
16609093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_memq: DISABLE PENDING!");
16617836SJohn.Forte@Sun.COM 		/*
16627836SJohn.Forte@Sun.COM 		 * Need to continue as we may be trying to flush IO
16637836SJohn.Forte@Sun.COM 		 * while trying to disable or suspend
16647836SJohn.Forte@Sun.COM 		 */
16657836SJohn.Forte@Sun.COM 	}
16667836SJohn.Forte@Sun.COM #endif
16677836SJohn.Forte@Sun.COM 
16687836SJohn.Forte@Sun.COM 	q = &group->ra_queue;
16697836SJohn.Forte@Sun.COM 
16707836SJohn.Forte@Sun.COM 	dowork = 1;
16717836SJohn.Forte@Sun.COM 	/* CONSTCOND */
16727836SJohn.Forte@Sun.COM 	while (dowork) {
16737836SJohn.Forte@Sun.COM 		if (net_exit == ATM_EXIT)
16747836SJohn.Forte@Sun.COM 			break;
16757836SJohn.Forte@Sun.COM 
16767836SJohn.Forte@Sun.COM 		group = krdc->group;
16777836SJohn.Forte@Sun.COM 		if (!group || group->count == 0) {
16787836SJohn.Forte@Sun.COM #ifdef DEBUG
16799093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!rdc_flush_memq: no group left!");
16807836SJohn.Forte@Sun.COM #endif
16817836SJohn.Forte@Sun.COM 			break;
16827836SJohn.Forte@Sun.COM 		}
16837836SJohn.Forte@Sun.COM 
16847836SJohn.Forte@Sun.COM 		mutex_enter(&q->net_qlock);
16857836SJohn.Forte@Sun.COM 		aio = q->net_qhead;
16867836SJohn.Forte@Sun.COM 
16877836SJohn.Forte@Sun.COM 		if (aio == NULL) {
16887836SJohn.Forte@Sun.COM #ifdef DEBUG
16897836SJohn.Forte@Sun.COM 			if (q->nitems != 0 ||
16907836SJohn.Forte@Sun.COM 			    q->blocks != 0 ||
16917836SJohn.Forte@Sun.COM 			    q->net_qtail != 0) {
16927836SJohn.Forte@Sun.COM 				cmn_err(CE_PANIC,
16937836SJohn.Forte@Sun.COM 				    "rdc_flush_memq(1): q %p, q blocks %"
16947836SJohn.Forte@Sun.COM 				    NSC_SZFMT ", nitems %" NSC_SZFMT
16957836SJohn.Forte@Sun.COM 				    ", qhead %p qtail %p",
16967836SJohn.Forte@Sun.COM 				    (void *) q, q->blocks, q->nitems,
16977836SJohn.Forte@Sun.COM 				    (void *) aio, (void *) q->net_qtail);
16987836SJohn.Forte@Sun.COM 			}
16997836SJohn.Forte@Sun.COM #endif
17007836SJohn.Forte@Sun.COM 			mutex_exit(&q->net_qlock);
17017836SJohn.Forte@Sun.COM 			break;
17027836SJohn.Forte@Sun.COM 		}
17037836SJohn.Forte@Sun.COM 
17047836SJohn.Forte@Sun.COM 		/* aio remove from q */
17057836SJohn.Forte@Sun.COM 
17067836SJohn.Forte@Sun.COM 		q->net_qhead = aio->next;
17077836SJohn.Forte@Sun.COM 		aio->next = NULL;
17087836SJohn.Forte@Sun.COM 
17097836SJohn.Forte@Sun.COM 		if (q->net_qtail == aio)
17107836SJohn.Forte@Sun.COM 			q->net_qtail = q->net_qhead;
17117836SJohn.Forte@Sun.COM 
17127836SJohn.Forte@Sun.COM 		q->blocks -= aio->len;
17137836SJohn.Forte@Sun.COM 		q->nitems--;
17147836SJohn.Forte@Sun.COM 
17157836SJohn.Forte@Sun.COM 		/*
17167836SJohn.Forte@Sun.COM 		 * in flight numbers.
17177836SJohn.Forte@Sun.COM 		 */
17187836SJohn.Forte@Sun.COM 		q->inflbls += aio->len;
17197836SJohn.Forte@Sun.COM 		q->inflitems++;
17207836SJohn.Forte@Sun.COM 
17217836SJohn.Forte@Sun.COM #ifdef DEBUG
17227836SJohn.Forte@Sun.COM 		if (q->net_qhead == NULL) {
17237836SJohn.Forte@Sun.COM 			if (q->nitems != 0 ||
17247836SJohn.Forte@Sun.COM 			    q->blocks != 0 ||
17257836SJohn.Forte@Sun.COM 			    q->net_qtail != 0) {
17267836SJohn.Forte@Sun.COM 				cmn_err(CE_PANIC,
17277836SJohn.Forte@Sun.COM 				    "rdc_flush_memq(2): q %p, q blocks %"
17287836SJohn.Forte@Sun.COM 				    NSC_SZFMT ", nitems %" NSC_SZFMT
17297836SJohn.Forte@Sun.COM 				    ", qhead %p qtail %p",
17307836SJohn.Forte@Sun.COM 				    (void *) q, q->blocks, q->nitems,
17317836SJohn.Forte@Sun.COM 				    (void *) q->net_qhead,
17327836SJohn.Forte@Sun.COM 				    (void *) q->net_qtail);
17337836SJohn.Forte@Sun.COM 			}
17347836SJohn.Forte@Sun.COM 		}
17357836SJohn.Forte@Sun.COM 
17367836SJohn.Forte@Sun.COM #ifndef NSC_MULTI_TERABYTE
17377836SJohn.Forte@Sun.COM 		if (q->blocks < 0) {
17387836SJohn.Forte@Sun.COM 			cmn_err(CE_PANIC,
17397836SJohn.Forte@Sun.COM 			    "rdc_flush_memq(3): q %p, q blocks %" NSC_SZFMT
17407836SJohn.Forte@Sun.COM 			    ", nitems %d, qhead %p, qtail %p",
17417836SJohn.Forte@Sun.COM 			    (void *) q, q->blocks, q->nitems,
17427836SJohn.Forte@Sun.COM 			    (void *) q->net_qhead, (void *) q->net_qtail);
17437836SJohn.Forte@Sun.COM 		}
17447836SJohn.Forte@Sun.COM #else
17457836SJohn.Forte@Sun.COM 		/* blocks and nitems are unsigned for NSC_MULTI_TERABYTE */
17467836SJohn.Forte@Sun.COM #endif
17477836SJohn.Forte@Sun.COM #endif
17487836SJohn.Forte@Sun.COM 
17497836SJohn.Forte@Sun.COM 		mutex_exit(&q->net_qlock);
17507836SJohn.Forte@Sun.COM 
17517836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_INIT;
17527836SJohn.Forte@Sun.COM 
17537836SJohn.Forte@Sun.COM 		_rdc_remote_flush(aio);
17547836SJohn.Forte@Sun.COM 
17557836SJohn.Forte@Sun.COM 		mutex_enter(&q->net_qlock);
17567836SJohn.Forte@Sun.COM 		q->inflbls -= aio->len;
17577836SJohn.Forte@Sun.COM 		q->inflitems--;
17587836SJohn.Forte@Sun.COM 		if ((group->seqack == RDC_NEWSEQ) &&
17597836SJohn.Forte@Sun.COM 		    (group->seq != RDC_NEWSEQ + 1)) {
17607836SJohn.Forte@Sun.COM 			if ((q->net_qhead == NULL) ||
17617836SJohn.Forte@Sun.COM 			    (q->net_qhead->seq != RDC_NEWSEQ + 1)) {
17627836SJohn.Forte@Sun.COM 				/*
17637836SJohn.Forte@Sun.COM 				 * We are an old thread, and the
17647836SJohn.Forte@Sun.COM 				 * queue sequence has been reset
17657836SJohn.Forte@Sun.COM 				 * during the network write above.
17667836SJohn.Forte@Sun.COM 				 * As such we mustn't pull another
17677836SJohn.Forte@Sun.COM 				 * job from the queue until the
17687836SJohn.Forte@Sun.COM 				 * first sequence message has been ack'ed.
17697836SJohn.Forte@Sun.COM 				 * Just die instead. Unless this thread
17707836SJohn.Forte@Sun.COM 				 * is the first sequence that has just
17717836SJohn.Forte@Sun.COM 				 * been ack'ed
17727836SJohn.Forte@Sun.COM 				 */
17737836SJohn.Forte@Sun.COM 				dowork = 0;
17747836SJohn.Forte@Sun.COM 			}
17757836SJohn.Forte@Sun.COM 		}
17767836SJohn.Forte@Sun.COM 		mutex_exit(&q->net_qlock);
17777836SJohn.Forte@Sun.COM 
17787836SJohn.Forte@Sun.COM 		if ((aio->iostatus != RDC_IO_DONE) && (group->count)) {
17797836SJohn.Forte@Sun.COM 			rdc_k_info_t *krdctmp = &rdc_k_info[aio->index];
17807836SJohn.Forte@Sun.COM 			if (krdctmp->type_flag & RDC_DISABLEPEND) {
17817836SJohn.Forte@Sun.COM 				kmem_free(aio, sizeof (*aio));
17827836SJohn.Forte@Sun.COM 				goto thread_death;
17837836SJohn.Forte@Sun.COM 			}
17847836SJohn.Forte@Sun.COM 			rdc_group_enter(krdc);
17857836SJohn.Forte@Sun.COM 			ASSERT(krdc->group);
17867836SJohn.Forte@Sun.COM 			rdc_group_log(krdc, RDC_NOFLUSH | RDC_ALLREMOTE,
17879093SRamana.Srikanth@Sun.COM 			    "memq flush aio status not RDC_IO_DONE");
17887836SJohn.Forte@Sun.COM 			rdc_group_exit(krdc);
17897836SJohn.Forte@Sun.COM 			rdc_dump_queue(aio->index);
17907836SJohn.Forte@Sun.COM 		}
17917836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
17927836SJohn.Forte@Sun.COM 
17937836SJohn.Forte@Sun.COM 		if (krdc->remote_index < 0 || !krdc->lsrv || !krdc->intf)
17947836SJohn.Forte@Sun.COM 			break;
17957836SJohn.Forte@Sun.COM 	}
17967836SJohn.Forte@Sun.COM 
17977836SJohn.Forte@Sun.COM thread_death:
17987836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
17997836SJohn.Forte@Sun.COM 	mutex_enter(&group->ra_queue.net_qlock);
18007836SJohn.Forte@Sun.COM 	group->rdc_thrnum--;
18017836SJohn.Forte@Sun.COM 	group->rdc_writer = 0;
18027836SJohn.Forte@Sun.COM 	/*
18037836SJohn.Forte@Sun.COM 	 * all threads must be dead.
18047836SJohn.Forte@Sun.COM 	 */
18057836SJohn.Forte@Sun.COM 	if ((group->count == 0) && (group->rdc_thrnum == 0)) {
18067836SJohn.Forte@Sun.COM 		mutex_exit(&group->ra_queue.net_qlock);
18077836SJohn.Forte@Sun.COM 		/*
18087836SJohn.Forte@Sun.COM 		 * Group now empty, so destroy
18097836SJohn.Forte@Sun.COM 		 * Race with remove_from_group while write thread was running
18107836SJohn.Forte@Sun.COM 		 */
18117836SJohn.Forte@Sun.COM #ifdef DEBUG
18129093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_memq: group being destroyed");
18137836SJohn.Forte@Sun.COM #endif
18147836SJohn.Forte@Sun.COM 		rdc_delgroup(group);
18157836SJohn.Forte@Sun.COM 		krdc->group = NULL;
18167836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
18177836SJohn.Forte@Sun.COM 		return;
18187836SJohn.Forte@Sun.COM 	}
18197836SJohn.Forte@Sun.COM 	mutex_exit(&group->ra_queue.net_qlock);
18207836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
18217836SJohn.Forte@Sun.COM }
18227836SJohn.Forte@Sun.COM 
18237836SJohn.Forte@Sun.COM /*
18247836SJohn.Forte@Sun.COM  * rdc_flush_diskq
18257836SJohn.Forte@Sun.COM  * disk queue flusher
18267836SJohn.Forte@Sun.COM  */
18277836SJohn.Forte@Sun.COM void
rdc_flush_diskq(int index)18287836SJohn.Forte@Sun.COM rdc_flush_diskq(int index)
18297836SJohn.Forte@Sun.COM {
18307836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
18317836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[index];
18327836SJohn.Forte@Sun.COM 	rdc_aio_t *aio = NULL;
18337836SJohn.Forte@Sun.COM 	disk_queue *q;
18347836SJohn.Forte@Sun.COM 	net_queue *nq;
18357836SJohn.Forte@Sun.COM 	int dowork;
18367836SJohn.Forte@Sun.COM 	int rc;
18377836SJohn.Forte@Sun.COM 	rdc_group_t *group = krdc->group;
18387836SJohn.Forte@Sun.COM 
18397836SJohn.Forte@Sun.COM 	if (!group || group->count == 0) {
18407836SJohn.Forte@Sun.COM #ifdef DEBUG
18419093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_diskq: no group left!");
18427836SJohn.Forte@Sun.COM #endif
18437836SJohn.Forte@Sun.COM 		return;
18447836SJohn.Forte@Sun.COM 	}
18457836SJohn.Forte@Sun.COM 
18467836SJohn.Forte@Sun.COM 	if (!krdc->c_fd) {
18477836SJohn.Forte@Sun.COM #ifdef DEBUG
18489093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_diskq: no c_fd!");
18497836SJohn.Forte@Sun.COM #endif
18507836SJohn.Forte@Sun.COM 		return;
18517836SJohn.Forte@Sun.COM 	}
18527836SJohn.Forte@Sun.COM 
18537836SJohn.Forte@Sun.COM #ifdef DEBUG_DISABLE
18547836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
18559093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_diskq: DISABLE PENDING!");
18567836SJohn.Forte@Sun.COM 		/*
18577836SJohn.Forte@Sun.COM 		 * Need to continue as we may be trying to flush IO
18587836SJohn.Forte@Sun.COM 		 * while trying to disable or suspend
18597836SJohn.Forte@Sun.COM 		 */
18607836SJohn.Forte@Sun.COM 	}
18617836SJohn.Forte@Sun.COM #endif
18627836SJohn.Forte@Sun.COM 	q = &group->diskq;
18637836SJohn.Forte@Sun.COM 	nq = &group->ra_queue;
18647836SJohn.Forte@Sun.COM 
18657836SJohn.Forte@Sun.COM 	if (IS_QSTATE(q, RDC_QDISABLEPEND) || IS_STATE(urdc, RDC_LOGGING)) {
18667836SJohn.Forte@Sun.COM #ifdef DEBUG
18679093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!flusher thread death 1 %x", QSTATE(q));
18687836SJohn.Forte@Sun.COM #endif
18697836SJohn.Forte@Sun.COM 		goto thread_death;
18707836SJohn.Forte@Sun.COM 	}
18717836SJohn.Forte@Sun.COM 
18727836SJohn.Forte@Sun.COM 	dowork = 1;
18737836SJohn.Forte@Sun.COM 	/* CONSTCOND */
18747836SJohn.Forte@Sun.COM 	while (dowork) {
18757836SJohn.Forte@Sun.COM 		if (net_exit == ATM_EXIT)
18767836SJohn.Forte@Sun.COM 			break;
18777836SJohn.Forte@Sun.COM 
18787836SJohn.Forte@Sun.COM 		group = krdc->group;
18797836SJohn.Forte@Sun.COM 		if (!group || group->count == 0) {
18807836SJohn.Forte@Sun.COM #ifdef DEBUG
18819093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!rdc_flush_diskq: no group left!");
18827836SJohn.Forte@Sun.COM #endif
18837836SJohn.Forte@Sun.COM 			break;
18847836SJohn.Forte@Sun.COM 		}
18857836SJohn.Forte@Sun.COM 
18867836SJohn.Forte@Sun.COM 		do {
18877836SJohn.Forte@Sun.COM 			rc = 0;
18887836SJohn.Forte@Sun.COM 			if ((IS_STATE(urdc, RDC_LOGGING)) ||
18897836SJohn.Forte@Sun.COM 			    (IS_STATE(urdc, RDC_SYNCING)) ||
18907836SJohn.Forte@Sun.COM 			    (nq->qfflags & RDC_QFILLSLEEP))
18917836SJohn.Forte@Sun.COM 				goto thread_death;
18927836SJohn.Forte@Sun.COM 
18937836SJohn.Forte@Sun.COM 			aio = rdc_dequeue(krdc, &rc);
18947836SJohn.Forte@Sun.COM 
18957836SJohn.Forte@Sun.COM 			if ((IS_STATE(urdc, RDC_LOGGING)) ||
18967836SJohn.Forte@Sun.COM 			    (IS_STATE(urdc, RDC_SYNCING)) ||
18977836SJohn.Forte@Sun.COM 			    (nq->qfflags & RDC_QFILLSLEEP)) {
18987836SJohn.Forte@Sun.COM 				goto thread_death;
18997836SJohn.Forte@Sun.COM 			}
19007836SJohn.Forte@Sun.COM 			if (rc == EAGAIN) {
19017836SJohn.Forte@Sun.COM 				delay(40);
19027836SJohn.Forte@Sun.COM 			}
19037836SJohn.Forte@Sun.COM 
19047836SJohn.Forte@Sun.COM 		} while (rc == EAGAIN);
19057836SJohn.Forte@Sun.COM 
19067836SJohn.Forte@Sun.COM 		if (aio == NULL) {
19077836SJohn.Forte@Sun.COM 			break;
19087836SJohn.Forte@Sun.COM 		}
19097836SJohn.Forte@Sun.COM 
19107836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_INIT;
19117836SJohn.Forte@Sun.COM 
19127836SJohn.Forte@Sun.COM 		mutex_enter(QLOCK(q));
19137836SJohn.Forte@Sun.COM 		q->inflbls += aio->len;
19147836SJohn.Forte@Sun.COM 		q->inflitems++;
19157836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(q));
19167836SJohn.Forte@Sun.COM 
19177836SJohn.Forte@Sun.COM 		_rdc_remote_flush(aio);
19187836SJohn.Forte@Sun.COM 
19197836SJohn.Forte@Sun.COM 		mutex_enter(QLOCK(q));
19207836SJohn.Forte@Sun.COM 		q->inflbls -= aio->len;
19217836SJohn.Forte@Sun.COM 		q->inflitems--;
19227836SJohn.Forte@Sun.COM 
19237836SJohn.Forte@Sun.COM 		if ((group->seqack == RDC_NEWSEQ) &&
19247836SJohn.Forte@Sun.COM 		    (group->seq != RDC_NEWSEQ + 1)) {
19257836SJohn.Forte@Sun.COM 			if ((nq->net_qhead == NULL) ||
19267836SJohn.Forte@Sun.COM 			    (nq->net_qhead->seq != RDC_NEWSEQ + 1)) {
19277836SJohn.Forte@Sun.COM 				/*
19287836SJohn.Forte@Sun.COM 				 * We are an old thread, and the
19297836SJohn.Forte@Sun.COM 				 * queue sequence has been reset
19307836SJohn.Forte@Sun.COM 				 * during the network write above.
19317836SJohn.Forte@Sun.COM 				 * As such we mustn't pull another
19327836SJohn.Forte@Sun.COM 				 * job from the queue until the
19337836SJohn.Forte@Sun.COM 				 * first sequence message has been ack'ed.
19347836SJohn.Forte@Sun.COM 				 * Just die instead. Unless of course,
19357836SJohn.Forte@Sun.COM 				 * this thread is the first sequence that
19367836SJohn.Forte@Sun.COM 				 * has just been ack'ed.
19377836SJohn.Forte@Sun.COM 				 */
19387836SJohn.Forte@Sun.COM 				dowork = 0;
19397836SJohn.Forte@Sun.COM 			}
19407836SJohn.Forte@Sun.COM 		}
19417836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(q));
19427836SJohn.Forte@Sun.COM 
19437836SJohn.Forte@Sun.COM 		if (aio->iostatus == RDC_IO_CANCELLED) {
19447836SJohn.Forte@Sun.COM 			rdc_dump_queue(aio->index);
19457836SJohn.Forte@Sun.COM 			kmem_free(aio, sizeof (*aio));
19467836SJohn.Forte@Sun.COM 			aio = NULL;
19477836SJohn.Forte@Sun.COM 			if (group) { /* seq gets bumped on dequeue */
19487836SJohn.Forte@Sun.COM 				mutex_enter(QLOCK(q));
19497836SJohn.Forte@Sun.COM 				rdc_dump_iohdrs(q);
19507836SJohn.Forte@Sun.COM 				SET_QNXTIO(q, QHEAD(q));
19517836SJohn.Forte@Sun.COM 				SET_QCOALBOUNDS(q, QHEAD(q));
19527836SJohn.Forte@Sun.COM 				group->seq = RDC_NEWSEQ;
19537836SJohn.Forte@Sun.COM 				group->seqack = RDC_NEWSEQ;
19547836SJohn.Forte@Sun.COM 				mutex_exit(QLOCK(q));
19557836SJohn.Forte@Sun.COM 			}
19567836SJohn.Forte@Sun.COM 			break;
19577836SJohn.Forte@Sun.COM 		}
19587836SJohn.Forte@Sun.COM 
19597836SJohn.Forte@Sun.COM 		if ((aio->iostatus != RDC_IO_DONE) && (group->count)) {
19607836SJohn.Forte@Sun.COM 			rdc_k_info_t *krdctmp = &rdc_k_info[aio->index];
19617836SJohn.Forte@Sun.COM 			if (krdctmp->type_flag & RDC_DISABLEPEND) {
19627836SJohn.Forte@Sun.COM 				kmem_free(aio, sizeof (*aio));
19637836SJohn.Forte@Sun.COM 				aio = NULL;
19647836SJohn.Forte@Sun.COM 				goto thread_death;
19657836SJohn.Forte@Sun.COM 			}
19667836SJohn.Forte@Sun.COM 			rdc_group_enter(krdc);
19677836SJohn.Forte@Sun.COM 			rdc_group_log(krdc,
19687836SJohn.Forte@Sun.COM 			    RDC_NOFLUSH | RDC_ALLREMOTE | RDC_QUEUING,
19699093SRamana.Srikanth@Sun.COM 			    "diskq flush aio status not RDC_IO_DONE");
19707836SJohn.Forte@Sun.COM 			rdc_group_exit(krdc);
19717836SJohn.Forte@Sun.COM 			rdc_dump_queue(aio->index);
19727836SJohn.Forte@Sun.COM 		}
19737836SJohn.Forte@Sun.COM 
19747836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
19757836SJohn.Forte@Sun.COM 		aio = NULL;
19767836SJohn.Forte@Sun.COM 
19777836SJohn.Forte@Sun.COM #ifdef DEBUG_DISABLE
19787836SJohn.Forte@Sun.COM 		if (krdc->type_flag & RDC_DISABLEPEND) {
19797836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
19809093SRamana.Srikanth@Sun.COM 			    "!rdc_flush_diskq: DISABLE PENDING after IO!");
19817836SJohn.Forte@Sun.COM 		}
19827836SJohn.Forte@Sun.COM #endif
19837836SJohn.Forte@Sun.COM 		if (krdc->remote_index < 0 || !krdc->lsrv || !krdc->intf)
19847836SJohn.Forte@Sun.COM 			break;
19857836SJohn.Forte@Sun.COM 
19867836SJohn.Forte@Sun.COM 		if (IS_QSTATE(q, RDC_QDISABLEPEND)) {
19877836SJohn.Forte@Sun.COM #ifdef DEBUG
19889093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!flusher thread death 2");
19897836SJohn.Forte@Sun.COM #endif
19907836SJohn.Forte@Sun.COM 			break;
19917836SJohn.Forte@Sun.COM 		}
19927836SJohn.Forte@Sun.COM 	}
19937836SJohn.Forte@Sun.COM thread_death:
19947836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
19957836SJohn.Forte@Sun.COM 	mutex_enter(QLOCK(q));
19967836SJohn.Forte@Sun.COM 	group->rdc_thrnum--;
19977836SJohn.Forte@Sun.COM 	group->rdc_writer = 0;
19987836SJohn.Forte@Sun.COM 
19997836SJohn.Forte@Sun.COM 	if (aio && aio->qhandle) {
20007836SJohn.Forte@Sun.COM 		aio->qhandle->sb_user--;
20017836SJohn.Forte@Sun.COM 		if (aio->qhandle->sb_user == 0) {
20027836SJohn.Forte@Sun.COM 			(void) _rdc_rsrv_diskq(krdc->group);
20037836SJohn.Forte@Sun.COM 			rdc_fixlen(aio);
20047836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->qhandle);
20057836SJohn.Forte@Sun.COM 			aio->qhandle = NULL;
20067836SJohn.Forte@Sun.COM 			aio->handle = NULL;
20077836SJohn.Forte@Sun.COM 			_rdc_rlse_diskq(krdc->group);
20087836SJohn.Forte@Sun.COM 		}
20097836SJohn.Forte@Sun.COM 	}
20107836SJohn.Forte@Sun.COM 	if ((group->count == 0) && (group->rdc_thrnum == 0)) {
20117836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(q));
20127836SJohn.Forte@Sun.COM 		/*
20137836SJohn.Forte@Sun.COM 		 * Group now empty, so destroy
20147836SJohn.Forte@Sun.COM 		 * Race with remove_from_group while write thread was running
20157836SJohn.Forte@Sun.COM 		 */
20167836SJohn.Forte@Sun.COM #ifdef DEBUG
20179093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_flush_diskq: group being destroyed");
20187836SJohn.Forte@Sun.COM #endif
20197836SJohn.Forte@Sun.COM 		mutex_enter(&group->diskqmutex);
20207836SJohn.Forte@Sun.COM 		rdc_close_diskq(group);
20217836SJohn.Forte@Sun.COM 		mutex_exit(&group->diskqmutex);
20227836SJohn.Forte@Sun.COM 		rdc_delgroup(group);
20237836SJohn.Forte@Sun.COM 		krdc->group = NULL;
20247836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
20257836SJohn.Forte@Sun.COM 		return;
20267836SJohn.Forte@Sun.COM 	}
20277836SJohn.Forte@Sun.COM 	mutex_exit(QLOCK(q));
20287836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
20297836SJohn.Forte@Sun.COM }
20307836SJohn.Forte@Sun.COM 
20317836SJohn.Forte@Sun.COM /*
20327836SJohn.Forte@Sun.COM  * _rdc_remote_flush
20337836SJohn.Forte@Sun.COM  * Flush a single block ANON block
20347836SJohn.Forte@Sun.COM  * this function will flush from either the disk queue
20357836SJohn.Forte@Sun.COM  * or the memory queue. The appropriate locks must be
20367836SJohn.Forte@Sun.COM  * taken out etc, etc ...
20377836SJohn.Forte@Sun.COM  */
20387836SJohn.Forte@Sun.COM static void
_rdc_remote_flush(rdc_aio_t * aio)20397836SJohn.Forte@Sun.COM _rdc_remote_flush(rdc_aio_t *aio)
20407836SJohn.Forte@Sun.COM {
20417836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[aio->index];
20427836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[aio->index];
20437836SJohn.Forte@Sun.COM 	disk_queue *q = &krdc->group->diskq;
20447836SJohn.Forte@Sun.COM 	kmutex_t *qlock;
20457836SJohn.Forte@Sun.COM 	rdc_group_t *group;
20467836SJohn.Forte@Sun.COM 	nsc_buf_t *h = NULL;
20477836SJohn.Forte@Sun.COM 	int reserved = 0;
20487836SJohn.Forte@Sun.COM 	int rtype = RDC_RAW;
20497836SJohn.Forte@Sun.COM 	int rc;
20507836SJohn.Forte@Sun.COM 	uint_t maxseq;
20517836SJohn.Forte@Sun.COM 	struct netwriteres netret;
20527836SJohn.Forte@Sun.COM 	int waitq = 1;
20537836SJohn.Forte@Sun.COM 	int vflags;
20547836SJohn.Forte@Sun.COM 
20557836SJohn.Forte@Sun.COM 	group = krdc->group;
20567836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_val = NULL;
20577836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_len = 0;
20587836SJohn.Forte@Sun.COM 
20597836SJohn.Forte@Sun.COM 	/* Where did we get this aio from anyway? */
20607836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
20617836SJohn.Forte@Sun.COM 		qlock = &group->diskq.disk_qlock;
20627836SJohn.Forte@Sun.COM 	} else {
20637836SJohn.Forte@Sun.COM 		qlock = &group->ra_queue.net_qlock;
20647836SJohn.Forte@Sun.COM 	}
20657836SJohn.Forte@Sun.COM 
20667836SJohn.Forte@Sun.COM 	/*
20677836SJohn.Forte@Sun.COM 	 * quench transmission if we are too far ahead of the
20687836SJohn.Forte@Sun.COM 	 * server Q, or it will overflow.
20697836SJohn.Forte@Sun.COM 	 * Must fail all requests while asyncdis is set.
20707836SJohn.Forte@Sun.COM 	 * It will be cleared when the last thread to be discarded
20717836SJohn.Forte@Sun.COM 	 * sets the asyncstall counter to zero.
20727836SJohn.Forte@Sun.COM 	 * Note the thread within rdc_net_write
20737836SJohn.Forte@Sun.COM 	 * also bumps the asyncstall counter.
20747836SJohn.Forte@Sun.COM 	 */
20757836SJohn.Forte@Sun.COM 
20767836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
20777836SJohn.Forte@Sun.COM 	if (group->asyncdis) {
20787836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_CANCELLED;
20797836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
20807836SJohn.Forte@Sun.COM 		goto failed;
20817836SJohn.Forte@Sun.COM 	}
20827836SJohn.Forte@Sun.COM 	/* don't go to sleep if we have gone logging! */
20837836SJohn.Forte@Sun.COM 	vflags = rdc_get_vflags(urdc);
20847836SJohn.Forte@Sun.COM 	if ((vflags & (RDC_BMP_FAILED|RDC_VOL_FAILED|RDC_LOGGING))) {
20857836SJohn.Forte@Sun.COM 		if ((vflags & RDC_LOGGING) && RDC_IS_DISKQ(group))
20867836SJohn.Forte@Sun.COM 			aio->iostatus = RDC_IO_CANCELLED;
20877836SJohn.Forte@Sun.COM 
20887836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
20897836SJohn.Forte@Sun.COM 		goto failed;
20907836SJohn.Forte@Sun.COM 	}
20917836SJohn.Forte@Sun.COM 
20927836SJohn.Forte@Sun.COM 	while (maxseq = group->seqack + RDC_MAXPENDQ + 1,
20937836SJohn.Forte@Sun.COM 	    maxseq = (maxseq < group->seqack) ? maxseq + RDC_NEWSEQ + 1
20947836SJohn.Forte@Sun.COM 	    : maxseq, !RDC_INFRONT(aio->seq, maxseq)) {
20957836SJohn.Forte@Sun.COM 		group->asyncstall++;
20967836SJohn.Forte@Sun.COM 		ASSERT(!IS_STATE(urdc, RDC_LOGGING));
20977836SJohn.Forte@Sun.COM 		cv_wait(&group->asyncqcv, qlock);
20987836SJohn.Forte@Sun.COM 		group->asyncstall--;
20997836SJohn.Forte@Sun.COM 		ASSERT(group->asyncstall >= 0);
21007836SJohn.Forte@Sun.COM 		if (group->asyncdis) {
21017836SJohn.Forte@Sun.COM 			if (group->asyncstall == 0) {
21027836SJohn.Forte@Sun.COM 				group->asyncdis = 0;
21037836SJohn.Forte@Sun.COM 			}
21047836SJohn.Forte@Sun.COM 			aio->iostatus = RDC_IO_CANCELLED;
21057836SJohn.Forte@Sun.COM 			mutex_exit(qlock);
21067836SJohn.Forte@Sun.COM 			goto failed;
21077836SJohn.Forte@Sun.COM 		}
21087836SJohn.Forte@Sun.COM 		/*
21097836SJohn.Forte@Sun.COM 		 * See if we have gone into logging mode
21107836SJohn.Forte@Sun.COM 		 * since sleeping.
21117836SJohn.Forte@Sun.COM 		 */
21127836SJohn.Forte@Sun.COM 		vflags = rdc_get_vflags(urdc);
21137836SJohn.Forte@Sun.COM 		if (vflags & (RDC_BMP_FAILED|RDC_VOL_FAILED|RDC_LOGGING)) {
21147836SJohn.Forte@Sun.COM 			if ((vflags & RDC_LOGGING) && RDC_IS_DISKQ(group))
21157836SJohn.Forte@Sun.COM 				aio->iostatus = RDC_IO_CANCELLED;
21167836SJohn.Forte@Sun.COM 
21177836SJohn.Forte@Sun.COM 			mutex_exit(qlock);
21187836SJohn.Forte@Sun.COM 			goto failed;
21197836SJohn.Forte@Sun.COM 		}
21207836SJohn.Forte@Sun.COM 	}
21217836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
21227836SJohn.Forte@Sun.COM 
21237836SJohn.Forte@Sun.COM 	if ((krdc->io_kstats) && (!RDC_IS_DISKQ(krdc->group))) {
21247836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
21257836SJohn.Forte@Sun.COM 		kstat_waitq_exit(KSTAT_IO_PTR(krdc->io_kstats));
21267836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
21277836SJohn.Forte@Sun.COM 		waitq = 0;
21287836SJohn.Forte@Sun.COM 	}
21297836SJohn.Forte@Sun.COM 
21307836SJohn.Forte@Sun.COM 
21317836SJohn.Forte@Sun.COM 	rc = _rdc_rsrv_devs(krdc, rtype, RDC_INTERNAL);
21327836SJohn.Forte@Sun.COM 	if (rc != 0) {
21337836SJohn.Forte@Sun.COM #ifdef DEBUG
21349093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_rdc_remote_flush: reserve, index %d, rc %d",
21357836SJohn.Forte@Sun.COM 		    aio->index, rc);
21367836SJohn.Forte@Sun.COM #endif
21377836SJohn.Forte@Sun.COM 		goto failed;
21387836SJohn.Forte@Sun.COM 	}
21397836SJohn.Forte@Sun.COM 
21407836SJohn.Forte@Sun.COM 	reserved = 1;
21417836SJohn.Forte@Sun.COM 	/*
21427836SJohn.Forte@Sun.COM 	 * Case where we are multihop and calling with no ANON bufs
21437836SJohn.Forte@Sun.COM 	 * Need to do the read to fill the buf.
21447836SJohn.Forte@Sun.COM 	 */
21457836SJohn.Forte@Sun.COM 	if (!aio->handle) {
21467836SJohn.Forte@Sun.COM 		rc = nsc_alloc_buf(RDC_U_FD(krdc), aio->pos, aio->len,
21479093SRamana.Srikanth@Sun.COM 		    (aio->flag & ~NSC_WRITE) | NSC_READ, &h);
21487836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(rc)) {
21497836SJohn.Forte@Sun.COM #ifdef DEBUG
21507836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
21519093SRamana.Srikanth@Sun.COM 			    "!_rdc_remote_flush: alloc_buf, index %d, pos %"
21527836SJohn.Forte@Sun.COM 			    NSC_SZFMT ", len %" NSC_SZFMT ", rc %d",
21537836SJohn.Forte@Sun.COM 			    aio->index, aio->pos, aio->len, rc);
21547836SJohn.Forte@Sun.COM #endif
21557836SJohn.Forte@Sun.COM 
21567836SJohn.Forte@Sun.COM 			goto failed;
21577836SJohn.Forte@Sun.COM 		}
21587836SJohn.Forte@Sun.COM 		aio->handle = h;
21597836SJohn.Forte@Sun.COM 		aio->handle->sb_user = RDC_NULLBUFREAD;
21607836SJohn.Forte@Sun.COM 	}
21617836SJohn.Forte@Sun.COM 
21627836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
21637836SJohn.Forte@Sun.COM 	if (group->asyncdis) {
21647836SJohn.Forte@Sun.COM 		if (group->asyncstall == 0) {
21657836SJohn.Forte@Sun.COM 			group->asyncdis = 0;
21667836SJohn.Forte@Sun.COM 		}
21677836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_CANCELLED;
21687836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
21697836SJohn.Forte@Sun.COM 		goto failed;
21707836SJohn.Forte@Sun.COM 	}
21717836SJohn.Forte@Sun.COM 	group->asyncstall++;
21727836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
21737836SJohn.Forte@Sun.COM 
21747836SJohn.Forte@Sun.COM 
21757836SJohn.Forte@Sun.COM 	if (krdc->remote_index < 0) {
21767836SJohn.Forte@Sun.COM 		/*
21777836SJohn.Forte@Sun.COM 		 * this should be ok, we are flushing, not rev syncing.
21787836SJohn.Forte@Sun.COM 		 * remote_index could be -1 if we lost a race with
21797836SJohn.Forte@Sun.COM 		 * resume and the flusher trys to flush an io from
21807836SJohn.Forte@Sun.COM 		 * another set that has not resumed
21817836SJohn.Forte@Sun.COM 		 */
21827836SJohn.Forte@Sun.COM 		krdc->remote_index = rdc_net_state(krdc->index, CCIO_SLAVE);
2183*10715SThomas.Atkins@Sun.COM 		DTRACE_PROBE1(remote_index_negative, int, krdc->remote_index);
21847836SJohn.Forte@Sun.COM 
21857836SJohn.Forte@Sun.COM 	}
21867836SJohn.Forte@Sun.COM 
21877836SJohn.Forte@Sun.COM 	/*
21887836SJohn.Forte@Sun.COM 	 * double check for logging, no check in net_write()
21897836SJohn.Forte@Sun.COM 	 * skip the write if you can, otherwise, if logging
21907836SJohn.Forte@Sun.COM 	 * avoid clearing the bit .. you don't know whose bit it may
21917836SJohn.Forte@Sun.COM 	 * also be.
21927836SJohn.Forte@Sun.COM 	 */
21937836SJohn.Forte@Sun.COM 	if (IS_STATE(urdc, RDC_LOGGING) || IS_STATE(urdc, RDC_SYNCING)) {
21947836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_CANCELLED;
21957836SJohn.Forte@Sun.COM 		mutex_enter(qlock);
21967836SJohn.Forte@Sun.COM 		group->asyncstall--;
21977836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
21987836SJohn.Forte@Sun.COM 		goto failed;
21997836SJohn.Forte@Sun.COM 	}
22007836SJohn.Forte@Sun.COM 
22017836SJohn.Forte@Sun.COM 	rc = rdc_net_write(krdc->index, krdc->remote_index,
22027836SJohn.Forte@Sun.COM 	    aio->handle, aio->pos, aio->len, aio->seq, aio->qpos, &netret);
22037836SJohn.Forte@Sun.COM 
22047836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
22057836SJohn.Forte@Sun.COM 	group->asyncstall--;
22067836SJohn.Forte@Sun.COM 	if (group->asyncdis) {
22077836SJohn.Forte@Sun.COM 		if (group->asyncstall == 0) {
22087836SJohn.Forte@Sun.COM 			group->asyncdis = 0;
22097836SJohn.Forte@Sun.COM 		}
22107836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_CANCELLED;
22117836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
22127836SJohn.Forte@Sun.COM 		goto failed;
22137836SJohn.Forte@Sun.COM 	}
22147836SJohn.Forte@Sun.COM 
22157836SJohn.Forte@Sun.COM 	if (IS_STATE(urdc, RDC_LOGGING) || IS_STATE(urdc, RDC_SYNCING)) {
22167836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
22177836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_CANCELLED;
22187836SJohn.Forte@Sun.COM 		goto failed;
22197836SJohn.Forte@Sun.COM 	}
22207836SJohn.Forte@Sun.COM 
22217836SJohn.Forte@Sun.COM 	ASSERT(aio->handle);
22227836SJohn.Forte@Sun.COM 	if (rc != 0) {
22237836SJohn.Forte@Sun.COM #ifdef DEBUG
22247836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
22259093SRamana.Srikanth@Sun.COM 		    "!_rdc_remote_flush: write, index %d, pos %" NSC_SZFMT
22267836SJohn.Forte@Sun.COM 		    ", len %" NSC_SZFMT ", "
22277836SJohn.Forte@Sun.COM 		    "rc %d seq %u group seq %u seqack %u qpos %" NSC_SZFMT,
22287836SJohn.Forte@Sun.COM 		    aio->index, aio->pos, aio->len, rc, aio->seq,
22297836SJohn.Forte@Sun.COM 		    group->seq, group->seqack, aio->qpos);
22307836SJohn.Forte@Sun.COM #endif
22317836SJohn.Forte@Sun.COM 		if (rc == ENOLINK) {
22327836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
22339093SRamana.Srikanth@Sun.COM 			    "!Hard timeout detected (%d sec) "
22347836SJohn.Forte@Sun.COM 			    "on SNDR set %s:%s",
22357836SJohn.Forte@Sun.COM 			    rdc_rpc_tmout, urdc->secondary.intf,
22367836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
22377836SJohn.Forte@Sun.COM 		}
22387836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
22397836SJohn.Forte@Sun.COM 		goto failed;
22407836SJohn.Forte@Sun.COM 	} else {
22417836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_DONE;
22427836SJohn.Forte@Sun.COM 	}
22437836SJohn.Forte@Sun.COM 
22447836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
22457836SJohn.Forte@Sun.COM 		/* free locally alloc'd handle */
22467836SJohn.Forte@Sun.COM 		if (aio->handle->sb_user == RDC_NULLBUFREAD) {
22477836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->handle);
22487836SJohn.Forte@Sun.COM 			aio->handle = NULL;
22497836SJohn.Forte@Sun.COM 		}
22507836SJohn.Forte@Sun.COM 		aio->qhandle->sb_user--;
22517836SJohn.Forte@Sun.COM 		if (aio->qhandle->sb_user == 0) {
22527836SJohn.Forte@Sun.COM 			(void) _rdc_rsrv_diskq(group);
22537836SJohn.Forte@Sun.COM 			rdc_fixlen(aio);
22547836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->qhandle);
22557836SJohn.Forte@Sun.COM 			aio->qhandle = NULL;
22567836SJohn.Forte@Sun.COM 			aio->handle = NULL;
22577836SJohn.Forte@Sun.COM 			_rdc_rlse_diskq(group);
22587836SJohn.Forte@Sun.COM 		}
22597836SJohn.Forte@Sun.COM 
22607836SJohn.Forte@Sun.COM 	} else {
22617836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(aio->handle);
22627836SJohn.Forte@Sun.COM 		aio->handle = NULL;
22637836SJohn.Forte@Sun.COM 	}
22647836SJohn.Forte@Sun.COM 
22657836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
22667836SJohn.Forte@Sun.COM 
22677836SJohn.Forte@Sun.COM 	_rdc_rlse_devs(krdc, rtype);
22687836SJohn.Forte@Sun.COM 
22697836SJohn.Forte@Sun.COM 	if (netret.result == 0) {
22707836SJohn.Forte@Sun.COM 		vflags = rdc_get_vflags(urdc);
22717836SJohn.Forte@Sun.COM 
22727836SJohn.Forte@Sun.COM 		if (!(vflags & (RDC_BMP_FAILED|RDC_VOL_FAILED|RDC_LOGGING))) {
22737836SJohn.Forte@Sun.COM 			RDC_CLR_BITMAP(krdc, aio->pos, aio->len, \
22747836SJohn.Forte@Sun.COM 			    0xffffffff, RDC_BIT_BUMP);
22757836SJohn.Forte@Sun.COM 
22767836SJohn.Forte@Sun.COM 			if (RDC_IS_DISKQ(krdc->group)) {
22777836SJohn.Forte@Sun.COM 				if (!IS_STATE(urdc, RDC_LOGGING)) {
22787836SJohn.Forte@Sun.COM 					/* tell queue data has been flushed */
22797836SJohn.Forte@Sun.COM 					rdc_clr_iohdr(krdc, aio->qpos);
22807836SJohn.Forte@Sun.COM 				} else { /* throw away queue, logging */
22817836SJohn.Forte@Sun.COM 					mutex_enter(qlock);
22827836SJohn.Forte@Sun.COM 					rdc_dump_iohdrs(q);
22837836SJohn.Forte@Sun.COM 					SET_QNXTIO(q, QHEAD(q));
22847836SJohn.Forte@Sun.COM 					SET_QCOALBOUNDS(q, QHEAD(q));
22857836SJohn.Forte@Sun.COM 					mutex_exit(qlock);
22867836SJohn.Forte@Sun.COM 				}
22877836SJohn.Forte@Sun.COM 			}
22887836SJohn.Forte@Sun.COM 		}
22897836SJohn.Forte@Sun.COM 
22907836SJohn.Forte@Sun.COM 		mutex_enter(qlock);
22917836SJohn.Forte@Sun.COM 		/*
22927836SJohn.Forte@Sun.COM 		 * Check to see if the reply has arrived out of
22937836SJohn.Forte@Sun.COM 		 * order, if so don't update seqack.
22947836SJohn.Forte@Sun.COM 		 */
22957836SJohn.Forte@Sun.COM 		if (!RDC_INFRONT(aio->seq, group->seqack)) {
22967836SJohn.Forte@Sun.COM 			group->seqack = aio->seq;
22977836SJohn.Forte@Sun.COM 		}
22987836SJohn.Forte@Sun.COM #ifdef DEBUG
22997836SJohn.Forte@Sun.COM 		else {
23007836SJohn.Forte@Sun.COM 			rdc_ooreply++;
23017836SJohn.Forte@Sun.COM 		}
23027836SJohn.Forte@Sun.COM #endif
23037836SJohn.Forte@Sun.COM 		if (group->asyncstall) {
23047836SJohn.Forte@Sun.COM 			cv_broadcast(&group->asyncqcv);
23057836SJohn.Forte@Sun.COM 		}
23067836SJohn.Forte@Sun.COM 		mutex_exit(qlock);
23077836SJohn.Forte@Sun.COM 	} else if (netret.result < 0) {
23087836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_FAILED;
23097836SJohn.Forte@Sun.COM 	}
23107836SJohn.Forte@Sun.COM 
23117836SJohn.Forte@Sun.COM 	/*
23127836SJohn.Forte@Sun.COM 	 * see if we have any pending async requests we can mark
23137836SJohn.Forte@Sun.COM 	 * as done.
23147836SJohn.Forte@Sun.COM 	 */
23157836SJohn.Forte@Sun.COM 
23167836SJohn.Forte@Sun.COM 	if (netret.vecdata.vecdata_len) {
23177836SJohn.Forte@Sun.COM 		net_pendvec_t *vecp;
23187836SJohn.Forte@Sun.COM 		net_pendvec_t *vecpe;
23197836SJohn.Forte@Sun.COM 		vecp = netret.vecdata.vecdata_val;
23207836SJohn.Forte@Sun.COM 		vecpe = netret.vecdata.vecdata_val + netret.vecdata.vecdata_len;
23217836SJohn.Forte@Sun.COM 		while (vecp < vecpe) {
23227836SJohn.Forte@Sun.COM 			rdc_k_info_t *krdcp = &rdc_k_info[vecp->pindex];
23237836SJohn.Forte@Sun.COM 			rdc_u_info_t *urdcp = &rdc_u_info[vecp->pindex];
23247836SJohn.Forte@Sun.COM 			/*
23257836SJohn.Forte@Sun.COM 			 * we must always still be in the same group.
23267836SJohn.Forte@Sun.COM 			 */
23277836SJohn.Forte@Sun.COM 			ASSERT(krdcp->group == group);
23287836SJohn.Forte@Sun.COM 			vflags = rdc_get_vflags(urdcp);
23297836SJohn.Forte@Sun.COM 
23307836SJohn.Forte@Sun.COM 			if (!(vflags &
23317836SJohn.Forte@Sun.COM 			    (RDC_BMP_FAILED|RDC_VOL_FAILED|RDC_LOGGING))) {
23327836SJohn.Forte@Sun.COM 				RDC_CLR_BITMAP(krdcp, vecp->apos, vecp->alen, \
23337836SJohn.Forte@Sun.COM 				    0xffffffff, RDC_BIT_BUMP);
23347836SJohn.Forte@Sun.COM 				if (RDC_IS_DISKQ(krdcp->group)) {
23357836SJohn.Forte@Sun.COM 					if (!IS_STATE(urdc, RDC_LOGGING)) {
23367836SJohn.Forte@Sun.COM 						/* update queue info */
23377836SJohn.Forte@Sun.COM 						rdc_clr_iohdr(krdc, vecp->qpos);
23387836SJohn.Forte@Sun.COM 					} else { /* we've gone logging */
23397836SJohn.Forte@Sun.COM 						mutex_enter(qlock);
23407836SJohn.Forte@Sun.COM 						rdc_dump_iohdrs(q);
23417836SJohn.Forte@Sun.COM 						SET_QNXTIO(q, QHEAD(q));
23427836SJohn.Forte@Sun.COM 						SET_QCOALBOUNDS(q, QHEAD(q));
23437836SJohn.Forte@Sun.COM 						mutex_exit(qlock);
23447836SJohn.Forte@Sun.COM 					}
23457836SJohn.Forte@Sun.COM 				}
23467836SJohn.Forte@Sun.COM 			}
23477836SJohn.Forte@Sun.COM 
23487836SJohn.Forte@Sun.COM 			/*
23497836SJohn.Forte@Sun.COM 			 * see if we can re-start transmission
23507836SJohn.Forte@Sun.COM 			 */
23517836SJohn.Forte@Sun.COM 			mutex_enter(qlock);
23527836SJohn.Forte@Sun.COM 			if (!RDC_INFRONT(vecp->seq, group->seqack)) {
23537836SJohn.Forte@Sun.COM 				group->seqack = vecp->seq;
23547836SJohn.Forte@Sun.COM 			}
23557836SJohn.Forte@Sun.COM #ifdef DEBUG
23567836SJohn.Forte@Sun.COM 			else {
23577836SJohn.Forte@Sun.COM 				rdc_ooreply++;
23587836SJohn.Forte@Sun.COM 			}
23597836SJohn.Forte@Sun.COM #endif
2360*10715SThomas.Atkins@Sun.COM 			DTRACE_PROBE1(pendvec_return, int, vecp->seq);
23617836SJohn.Forte@Sun.COM 
23627836SJohn.Forte@Sun.COM 			if (group->asyncstall) {
23637836SJohn.Forte@Sun.COM 				cv_broadcast(&group->asyncqcv);
23647836SJohn.Forte@Sun.COM 			}
23657836SJohn.Forte@Sun.COM 			mutex_exit(qlock);
23667836SJohn.Forte@Sun.COM 			vecp++;
23677836SJohn.Forte@Sun.COM 		}
23687836SJohn.Forte@Sun.COM 	}
23697836SJohn.Forte@Sun.COM 	if (netret.vecdata.vecdata_val)
23707836SJohn.Forte@Sun.COM 		kmem_free(netret.vecdata.vecdata_val,
23717836SJohn.Forte@Sun.COM 		    netret.vecdata.vecdata_len * sizeof (net_pendvec_t));
23727836SJohn.Forte@Sun.COM 	return;
23737836SJohn.Forte@Sun.COM failed:
23747836SJohn.Forte@Sun.COM 
23757836SJohn.Forte@Sun.COM 	/* perhaps we have a few threads stuck .. */
23767836SJohn.Forte@Sun.COM 	if (group->asyncstall) {
23777836SJohn.Forte@Sun.COM 		group->asyncdis = 1;
23787836SJohn.Forte@Sun.COM 		cv_broadcast(&group->asyncqcv);
23797836SJohn.Forte@Sun.COM 	}
23807836SJohn.Forte@Sun.COM 	if (netret.vecdata.vecdata_val)
23817836SJohn.Forte@Sun.COM 		kmem_free(netret.vecdata.vecdata_val,
23827836SJohn.Forte@Sun.COM 		    netret.vecdata.vecdata_len * sizeof (net_pendvec_t));
23837836SJohn.Forte@Sun.COM 
23847836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
23857836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
23867836SJohn.Forte@Sun.COM 		/* free locally alloc'd hanlde */
23877836SJohn.Forte@Sun.COM 		if ((aio->handle) &&
23887836SJohn.Forte@Sun.COM 		    (aio->handle->sb_user == RDC_NULLBUFREAD)) {
23897836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->handle);
23907836SJohn.Forte@Sun.COM 			aio->handle = NULL;
23917836SJohn.Forte@Sun.COM 		}
23927836SJohn.Forte@Sun.COM 		aio->qhandle->sb_user--;
23937836SJohn.Forte@Sun.COM 		if (aio->qhandle->sb_user == 0) {
23947836SJohn.Forte@Sun.COM 			(void) _rdc_rsrv_diskq(group);
23957836SJohn.Forte@Sun.COM 			rdc_fixlen(aio);
23967836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->qhandle);
23977836SJohn.Forte@Sun.COM 			aio->qhandle = NULL;
23987836SJohn.Forte@Sun.COM 			aio->handle = NULL;
23997836SJohn.Forte@Sun.COM 			_rdc_rlse_diskq(group);
24007836SJohn.Forte@Sun.COM 		}
24017836SJohn.Forte@Sun.COM 	} else {
24027836SJohn.Forte@Sun.COM 		if (aio->handle) {
24037836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(aio->handle);
24047836SJohn.Forte@Sun.COM 			aio->handle = NULL;
24057836SJohn.Forte@Sun.COM 		}
24067836SJohn.Forte@Sun.COM 	}
24077836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
24087836SJohn.Forte@Sun.COM 
24097836SJohn.Forte@Sun.COM 	if (reserved) {
24107836SJohn.Forte@Sun.COM 		_rdc_rlse_devs(krdc, rtype);
24117836SJohn.Forte@Sun.COM 	}
24127836SJohn.Forte@Sun.COM 
24137836SJohn.Forte@Sun.COM 	if ((waitq && krdc->io_kstats) && (!RDC_IS_DISKQ(krdc->group))) {
24147836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
24157836SJohn.Forte@Sun.COM 		kstat_waitq_exit(KSTAT_IO_PTR(krdc->io_kstats));
24167836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
24177836SJohn.Forte@Sun.COM 	}
24187836SJohn.Forte@Sun.COM 
24197836SJohn.Forte@Sun.COM 	/* make sure that the bit is still set */
24207836SJohn.Forte@Sun.COM 	RDC_CHECK_BIT(krdc, aio->pos, aio->len);
24217836SJohn.Forte@Sun.COM 
24227836SJohn.Forte@Sun.COM 	if (aio->iostatus != RDC_IO_CANCELLED)
24237836SJohn.Forte@Sun.COM 		aio->iostatus = RDC_IO_FAILED;
24247836SJohn.Forte@Sun.COM }
24257836SJohn.Forte@Sun.COM 
24267836SJohn.Forte@Sun.COM 
24277836SJohn.Forte@Sun.COM /*
24287836SJohn.Forte@Sun.COM  * rdc_drain_disk_queue
24297836SJohn.Forte@Sun.COM  * drain the async network queue for the whole group. Bail out if nothing
24307836SJohn.Forte@Sun.COM  * happens in 20 sec
24317836SJohn.Forte@Sun.COM  * returns -1 if it bails before the queues are drained.
24327836SJohn.Forte@Sun.COM  */
24337836SJohn.Forte@Sun.COM #define	NUM_RETRIES	15	/* Number of retries to wait if no progress */
24347836SJohn.Forte@Sun.COM int
rdc_drain_disk_queue(int index)24357836SJohn.Forte@Sun.COM rdc_drain_disk_queue(int index)
24367836SJohn.Forte@Sun.COM {
24377836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
24387836SJohn.Forte@Sun.COM 	volatile rdc_group_t *group;
24397836SJohn.Forte@Sun.COM 	volatile disk_queue *diskq;
24407836SJohn.Forte@Sun.COM 	int threads, counter;
24417836SJohn.Forte@Sun.COM 	long blocks;
24427836SJohn.Forte@Sun.COM 
24437836SJohn.Forte@Sun.COM 	/* Sanity checking */
24447836SJohn.Forte@Sun.COM 	if (index > rdc_max_sets)
24457836SJohn.Forte@Sun.COM 		return (0);
24467836SJohn.Forte@Sun.COM 
24477836SJohn.Forte@Sun.COM 	/*
24487836SJohn.Forte@Sun.COM 	 * If there is no group or diskq configured, we can leave now
24497836SJohn.Forte@Sun.COM 	 */
24507836SJohn.Forte@Sun.COM 	if (!(group = krdc->group) || !(diskq = &group->diskq))
24517836SJohn.Forte@Sun.COM 		return (0);
24527836SJohn.Forte@Sun.COM 
24537836SJohn.Forte@Sun.COM 	/*
24547836SJohn.Forte@Sun.COM 	 * No need to wait if EMPTY and threads are gone
24557836SJohn.Forte@Sun.COM 	 */
24567836SJohn.Forte@Sun.COM 	counter = 0;
24577836SJohn.Forte@Sun.COM 	while (!QEMPTY(diskq) || group->rdc_thrnum) {
24587836SJohn.Forte@Sun.COM 
24597836SJohn.Forte@Sun.COM 		/*
24607836SJohn.Forte@Sun.COM 		 * Capture counters to determine if progress is being made
24617836SJohn.Forte@Sun.COM 		 */
24627836SJohn.Forte@Sun.COM 		blocks = QBLOCKS(diskq);
24637836SJohn.Forte@Sun.COM 		threads = group->rdc_thrnum;
24647836SJohn.Forte@Sun.COM 
24657836SJohn.Forte@Sun.COM 		/*
24667836SJohn.Forte@Sun.COM 		 * Wait
24677836SJohn.Forte@Sun.COM 		 */
24687836SJohn.Forte@Sun.COM 		delay(HZ);
24697836SJohn.Forte@Sun.COM 
24707836SJohn.Forte@Sun.COM 		/*
24717836SJohn.Forte@Sun.COM 		 * Has the group or disk queue gone away while delayed?
24727836SJohn.Forte@Sun.COM 		 */
24737836SJohn.Forte@Sun.COM 		if (!(group = krdc->group) || !(diskq = &group->diskq))
24747836SJohn.Forte@Sun.COM 			return (0);
24757836SJohn.Forte@Sun.COM 
24767836SJohn.Forte@Sun.COM 		/*
24777836SJohn.Forte@Sun.COM 		 * Are we still seeing progress?
24787836SJohn.Forte@Sun.COM 		 */
24797836SJohn.Forte@Sun.COM 		if (blocks == QBLOCKS(diskq) && threads == group->rdc_thrnum) {
24807836SJohn.Forte@Sun.COM 			/*
24817836SJohn.Forte@Sun.COM 			 * No progress seen, increment retry counter
24827836SJohn.Forte@Sun.COM 			 */
24837836SJohn.Forte@Sun.COM 			if (counter++ > NUM_RETRIES) {
24847836SJohn.Forte@Sun.COM 				return (-1);
24857836SJohn.Forte@Sun.COM 			}
24867836SJohn.Forte@Sun.COM 		} else {
24877836SJohn.Forte@Sun.COM 			/*
24887836SJohn.Forte@Sun.COM 			 * Reset counter, as we've made progress
24897836SJohn.Forte@Sun.COM 			 */
24907836SJohn.Forte@Sun.COM 			counter = 0;
24917836SJohn.Forte@Sun.COM 		}
24927836SJohn.Forte@Sun.COM 	}
24937836SJohn.Forte@Sun.COM 
24947836SJohn.Forte@Sun.COM 	return (0);
24957836SJohn.Forte@Sun.COM }
24967836SJohn.Forte@Sun.COM 
24977836SJohn.Forte@Sun.COM /*
24987836SJohn.Forte@Sun.COM  * decide what needs to be drained, disk or core
24997836SJohn.Forte@Sun.COM  * and drain it
25007836SJohn.Forte@Sun.COM  */
25017836SJohn.Forte@Sun.COM int
rdc_drain_queue(int index)25027836SJohn.Forte@Sun.COM rdc_drain_queue(int index)
25037836SJohn.Forte@Sun.COM {
25047836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
25057836SJohn.Forte@Sun.COM 	rdc_group_t *group = krdc->group;
25067836SJohn.Forte@Sun.COM 
25077836SJohn.Forte@Sun.COM 	if (!group)
25087836SJohn.Forte@Sun.COM 		return (0);
25097836SJohn.Forte@Sun.COM 
25107836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group))
25117836SJohn.Forte@Sun.COM 		return (rdc_drain_disk_queue(index));
25127836SJohn.Forte@Sun.COM 	if (RDC_IS_MEMQ(group))
25137836SJohn.Forte@Sun.COM 		return (rdc_drain_net_queue(index));
25147836SJohn.Forte@Sun.COM 	/* oops.. */
25157836SJohn.Forte@Sun.COM #ifdef DEBUG
25169093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!rdc_drain_queue: "
25179093SRamana.Srikanth@Sun.COM 	    "attempting drain of unknown Q type");
25187836SJohn.Forte@Sun.COM #endif
25197836SJohn.Forte@Sun.COM 	return (0);
25207836SJohn.Forte@Sun.COM }
25217836SJohn.Forte@Sun.COM 
25227836SJohn.Forte@Sun.COM /*
25237836SJohn.Forte@Sun.COM  * rdc_drain_net_queue
25247836SJohn.Forte@Sun.COM  * drain the async network queue for the whole group. Bail out if nothing
25257836SJohn.Forte@Sun.COM  * happens in 20 sec
25267836SJohn.Forte@Sun.COM  * returns -1 if it bails before the queues are drained.
25277836SJohn.Forte@Sun.COM  */
25287836SJohn.Forte@Sun.COM int
rdc_drain_net_queue(int index)25297836SJohn.Forte@Sun.COM rdc_drain_net_queue(int index)
25307836SJohn.Forte@Sun.COM {
25317836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
25327836SJohn.Forte@Sun.COM 	volatile net_queue *q;
25337836SJohn.Forte@Sun.COM 	int bail = 20;	/* bail out in about 20 secs */
25347836SJohn.Forte@Sun.COM 	nsc_size_t blocks;
25357836SJohn.Forte@Sun.COM 
25367836SJohn.Forte@Sun.COM 	/* Sanity checking */
25377836SJohn.Forte@Sun.COM 	if (index > rdc_max_sets)
25387836SJohn.Forte@Sun.COM 		return (0);
25397836SJohn.Forte@Sun.COM 	if (!krdc->group)
25407836SJohn.Forte@Sun.COM 		return (0);
25417836SJohn.Forte@Sun.COM 	/* LINTED */
25427836SJohn.Forte@Sun.COM 	if (!(q = &krdc->group->ra_queue))
25437836SJohn.Forte@Sun.COM 		return (0);
25447836SJohn.Forte@Sun.COM 
25457836SJohn.Forte@Sun.COM 	/* CONSTCOND */
25467836SJohn.Forte@Sun.COM 	while (1) {
25477836SJohn.Forte@Sun.COM 
25487836SJohn.Forte@Sun.COM 		if (((volatile rdc_aio_t *)q->net_qhead == NULL) &&
25497836SJohn.Forte@Sun.COM 		    (krdc->group->rdc_thrnum == 0)) {
25507836SJohn.Forte@Sun.COM 			break;
25517836SJohn.Forte@Sun.COM 		}
25527836SJohn.Forte@Sun.COM 
25537836SJohn.Forte@Sun.COM 		blocks = q->blocks;
25547836SJohn.Forte@Sun.COM 
25557836SJohn.Forte@Sun.COM 		q = (volatile net_queue *)&krdc->group->ra_queue;
25567836SJohn.Forte@Sun.COM 
25577836SJohn.Forte@Sun.COM 		if ((blocks == q->blocks) &&
25587836SJohn.Forte@Sun.COM 		    (--bail <= 0)) {
25597836SJohn.Forte@Sun.COM 			break;
25607836SJohn.Forte@Sun.COM 		}
25617836SJohn.Forte@Sun.COM 
25627836SJohn.Forte@Sun.COM 		delay(HZ);
25637836SJohn.Forte@Sun.COM 	}
25647836SJohn.Forte@Sun.COM 
25657836SJohn.Forte@Sun.COM 	if (bail <= 0)
25667836SJohn.Forte@Sun.COM 		return (-1);
25677836SJohn.Forte@Sun.COM 
25687836SJohn.Forte@Sun.COM 	return (0);
25697836SJohn.Forte@Sun.COM }
25707836SJohn.Forte@Sun.COM 
25717836SJohn.Forte@Sun.COM /*
25727836SJohn.Forte@Sun.COM  * rdc_dump_queue
25737836SJohn.Forte@Sun.COM  * We want to release all the blocks currently on the network flushing queue
25747836SJohn.Forte@Sun.COM  * We already have them logged in the bitmap.
25757836SJohn.Forte@Sun.COM  */
25767836SJohn.Forte@Sun.COM void
rdc_dump_queue(int index)25777836SJohn.Forte@Sun.COM rdc_dump_queue(int index)
25787836SJohn.Forte@Sun.COM {
25797836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
25807836SJohn.Forte@Sun.COM 	rdc_aio_t *aio;
25817836SJohn.Forte@Sun.COM 	net_queue *q;
25827836SJohn.Forte@Sun.COM 	rdc_group_t *group;
25837836SJohn.Forte@Sun.COM 	disk_queue *dq;
25847836SJohn.Forte@Sun.COM 	kmutex_t *qlock;
25857836SJohn.Forte@Sun.COM 
25867836SJohn.Forte@Sun.COM 	group = krdc->group;
25877836SJohn.Forte@Sun.COM 
25887836SJohn.Forte@Sun.COM 	q = &group->ra_queue;
25897836SJohn.Forte@Sun.COM 	dq = &group->diskq;
25907836SJohn.Forte@Sun.COM 
25917836SJohn.Forte@Sun.COM 	/*
25927836SJohn.Forte@Sun.COM 	 * gotta have both locks here for diskq
25937836SJohn.Forte@Sun.COM 	 */
25947836SJohn.Forte@Sun.COM 
25957836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
25967836SJohn.Forte@Sun.COM 		mutex_enter(&q->net_qlock);
25977836SJohn.Forte@Sun.COM 		if (q->qfill_sleeping == RDC_QFILL_AWAKE) {
25987836SJohn.Forte@Sun.COM 			int tries = 3;
25997836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
26007836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
26019093SRamana.Srikanth@Sun.COM 			    "!dumpq sending diskq->memq flusher to sleep");
26027836SJohn.Forte@Sun.COM #endif
26037836SJohn.Forte@Sun.COM 			q->qfflags |= RDC_QFILLSLEEP;
26047836SJohn.Forte@Sun.COM 			mutex_exit(&q->net_qlock);
26057836SJohn.Forte@Sun.COM 			while (q->qfill_sleeping == RDC_QFILL_AWAKE && tries--)
26067836SJohn.Forte@Sun.COM 				delay(5);
26077836SJohn.Forte@Sun.COM 			mutex_enter(&q->net_qlock);
26087836SJohn.Forte@Sun.COM 		}
26097836SJohn.Forte@Sun.COM 	}
26107836SJohn.Forte@Sun.COM 
26117836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
26127836SJohn.Forte@Sun.COM 		qlock = &dq->disk_qlock;
26137836SJohn.Forte@Sun.COM 		(void) _rdc_rsrv_diskq(group);
26147836SJohn.Forte@Sun.COM 	} else {
26157836SJohn.Forte@Sun.COM 		qlock = &q->net_qlock;
26167836SJohn.Forte@Sun.COM 	}
26177836SJohn.Forte@Sun.COM 
26187836SJohn.Forte@Sun.COM 	mutex_enter(qlock);
26197836SJohn.Forte@Sun.COM 
26207836SJohn.Forte@Sun.COM 	group->seq = RDC_NEWSEQ;	/* reset the sequence number */
26217836SJohn.Forte@Sun.COM 	group->seqack = RDC_NEWSEQ;
26227836SJohn.Forte@Sun.COM 
26237836SJohn.Forte@Sun.COM 	/* if the q is on disk, dump the q->iohdr chain */
26247836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
26257836SJohn.Forte@Sun.COM 		rdc_dump_iohdrs(dq);
26267836SJohn.Forte@Sun.COM 
26277836SJohn.Forte@Sun.COM 		/* back up the nxtio pointer */
26287836SJohn.Forte@Sun.COM 		SET_QNXTIO(dq, QHEAD(dq));
26297836SJohn.Forte@Sun.COM 		SET_QCOALBOUNDS(dq, QHEAD(dq));
26307836SJohn.Forte@Sun.COM 	}
26317836SJohn.Forte@Sun.COM 
26327836SJohn.Forte@Sun.COM 	while (q->net_qhead) {
26337836SJohn.Forte@Sun.COM 		rdc_k_info_t *tmpkrdc;
26347836SJohn.Forte@Sun.COM 		aio = q->net_qhead;
26357836SJohn.Forte@Sun.COM 		tmpkrdc = &rdc_k_info[aio->index];
26367836SJohn.Forte@Sun.COM 
26377836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(group)) {
26387836SJohn.Forte@Sun.COM 			aio->qhandle->sb_user--;
26397836SJohn.Forte@Sun.COM 			if (aio->qhandle->sb_user == 0) {
26407836SJohn.Forte@Sun.COM 				rdc_fixlen(aio);
26417836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(aio->qhandle);
26427836SJohn.Forte@Sun.COM 				aio->qhandle = NULL;
26437836SJohn.Forte@Sun.COM 				aio->handle = NULL;
26447836SJohn.Forte@Sun.COM 			}
26457836SJohn.Forte@Sun.COM 		} else {
26467836SJohn.Forte@Sun.COM 			if (aio->handle) {
26477836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(aio->handle);
26487836SJohn.Forte@Sun.COM 				aio->handle = NULL;
26497836SJohn.Forte@Sun.COM 			}
26507836SJohn.Forte@Sun.COM 		}
26517836SJohn.Forte@Sun.COM 
26527836SJohn.Forte@Sun.COM 		q->net_qhead = aio->next;
26537836SJohn.Forte@Sun.COM 		RDC_CHECK_BIT(tmpkrdc, aio->pos, aio->len);
26547836SJohn.Forte@Sun.COM 
26557836SJohn.Forte@Sun.COM 		kmem_free(aio, sizeof (*aio));
26567836SJohn.Forte@Sun.COM 		if (tmpkrdc->io_kstats && !RDC_IS_DISKQ(group)) {
26577836SJohn.Forte@Sun.COM 			mutex_enter(tmpkrdc->io_kstats->ks_lock);
26587836SJohn.Forte@Sun.COM 			kstat_waitq_exit(KSTAT_IO_PTR(tmpkrdc->io_kstats));
26597836SJohn.Forte@Sun.COM 			mutex_exit(tmpkrdc->io_kstats->ks_lock);
26607836SJohn.Forte@Sun.COM 		}
26617836SJohn.Forte@Sun.COM 
26627836SJohn.Forte@Sun.COM 	}
26637836SJohn.Forte@Sun.COM 
26647836SJohn.Forte@Sun.COM 	q->net_qtail = NULL;
26657836SJohn.Forte@Sun.COM 	q->blocks = 0;
26667836SJohn.Forte@Sun.COM 	q->nitems = 0;
26677836SJohn.Forte@Sun.COM 
26687836SJohn.Forte@Sun.COM 	/*
26697836SJohn.Forte@Sun.COM 	 * See if we have stalled threads.
26707836SJohn.Forte@Sun.COM 	 */
26717836SJohn.Forte@Sun.COM done:
26727836SJohn.Forte@Sun.COM 	if (group->asyncstall) {
26737836SJohn.Forte@Sun.COM 		group->asyncdis = 1;
26747836SJohn.Forte@Sun.COM 		cv_broadcast(&group->asyncqcv);
26757836SJohn.Forte@Sun.COM 	}
26767836SJohn.Forte@Sun.COM 	mutex_exit(qlock);
26777836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(group)) {
26787836SJohn.Forte@Sun.COM 		mutex_exit(&q->net_qlock);
26797836SJohn.Forte@Sun.COM 		_rdc_rlse_diskq(group);
26807836SJohn.Forte@Sun.COM 	}
26817836SJohn.Forte@Sun.COM 
26827836SJohn.Forte@Sun.COM }
26837836SJohn.Forte@Sun.COM 
26847836SJohn.Forte@Sun.COM 
26857836SJohn.Forte@Sun.COM /*
26867836SJohn.Forte@Sun.COM  * rdc_clnt_get
26877836SJohn.Forte@Sun.COM  * Get a CLIENT handle and cache it
26887836SJohn.Forte@Sun.COM  */
26897836SJohn.Forte@Sun.COM 
26907836SJohn.Forte@Sun.COM static int
rdc_clnt_get(rdc_srv_t * svp,rpcvers_t vers,struct chtab ** rch,CLIENT ** clp)26917836SJohn.Forte@Sun.COM rdc_clnt_get(rdc_srv_t *svp, rpcvers_t vers, struct chtab **rch, CLIENT **clp)
26927836SJohn.Forte@Sun.COM {
26937836SJohn.Forte@Sun.COM 	uint_t	max_msgsize;
26947836SJohn.Forte@Sun.COM 	int	retries;
26957836SJohn.Forte@Sun.COM 	int ret;
26967836SJohn.Forte@Sun.COM 	struct cred		*cred;
26977836SJohn.Forte@Sun.COM 	int num_clnts = 0;
26987836SJohn.Forte@Sun.COM 	register struct chtab *ch;
26997836SJohn.Forte@Sun.COM 	struct chtab **plistp;
27007836SJohn.Forte@Sun.COM 	CLIENT *client = 0;
27017836SJohn.Forte@Sun.COM 
27027836SJohn.Forte@Sun.COM 	if (rch) {
27037836SJohn.Forte@Sun.COM 		*rch = 0;
27047836SJohn.Forte@Sun.COM 	}
27057836SJohn.Forte@Sun.COM 
27067836SJohn.Forte@Sun.COM 	if (clp) {
27077836SJohn.Forte@Sun.COM 		*clp = 0;
27087836SJohn.Forte@Sun.COM 	}
27097836SJohn.Forte@Sun.COM 
27107836SJohn.Forte@Sun.COM 	retries = 6;	/* Never used for COTS in Solaris */
27117836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
27127836SJohn.Forte@Sun.COM 	max_msgsize = RDC_RPC_MAX;
27137836SJohn.Forte@Sun.COM 
27147836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_clnt_lock);
27157836SJohn.Forte@Sun.COM 
27167836SJohn.Forte@Sun.COM 	ch = rdc_chtable;
27177836SJohn.Forte@Sun.COM 	plistp = &rdc_chtable;
27187836SJohn.Forte@Sun.COM 
27197836SJohn.Forte@Sun.COM 	/* find the right ch_list chain */
27207836SJohn.Forte@Sun.COM 
27217836SJohn.Forte@Sun.COM 	for (ch = rdc_chtable; ch != NULL; ch = ch->ch_next) {
27227836SJohn.Forte@Sun.COM 		if (ch->ch_prog == RDC_PROGRAM &&
27237836SJohn.Forte@Sun.COM 		    ch->ch_vers == vers &&
27247836SJohn.Forte@Sun.COM 		    ch->ch_dev == svp->ri_knconf->knc_rdev &&
27257836SJohn.Forte@Sun.COM 		    ch->ch_protofmly != NULL &&
27267836SJohn.Forte@Sun.COM 		    strcmp(ch->ch_protofmly,
27279093SRamana.Srikanth@Sun.COM 		    svp->ri_knconf->knc_protofmly) == 0) {
27287836SJohn.Forte@Sun.COM 			/* found the correct chain to walk */
27297836SJohn.Forte@Sun.COM 			break;
27307836SJohn.Forte@Sun.COM 		}
27317836SJohn.Forte@Sun.COM 		plistp = &ch->ch_next;
27327836SJohn.Forte@Sun.COM 	}
27337836SJohn.Forte@Sun.COM 
27347836SJohn.Forte@Sun.COM 	if (ch != NULL) {
27357836SJohn.Forte@Sun.COM 		/* walk the ch_list and try and find a free client */
27367836SJohn.Forte@Sun.COM 
27377836SJohn.Forte@Sun.COM 		for (num_clnts = 0; ch != NULL; ch = ch->ch_list, num_clnts++) {
27387836SJohn.Forte@Sun.COM 			if (ch->ch_inuse == FALSE) {
27397836SJohn.Forte@Sun.COM 				/* suitable handle to reuse */
27407836SJohn.Forte@Sun.COM 				break;
27417836SJohn.Forte@Sun.COM 			}
27427836SJohn.Forte@Sun.COM 			plistp = &ch->ch_list;
27437836SJohn.Forte@Sun.COM 		}
27447836SJohn.Forte@Sun.COM 	}
27457836SJohn.Forte@Sun.COM 
27467836SJohn.Forte@Sun.COM 	if (ch == NULL && num_clnts >= MAXCLIENTS) {
27477836SJohn.Forte@Sun.COM 		/* alloc a temporary handle and return */
27487836SJohn.Forte@Sun.COM 
27497836SJohn.Forte@Sun.COM 		rdc_clnt_toomany++;
27507836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_clnt_lock);
27517836SJohn.Forte@Sun.COM 
27527836SJohn.Forte@Sun.COM 		ret = clnt_tli_kcreate(svp->ri_knconf, &(svp->ri_addr),
27539093SRamana.Srikanth@Sun.COM 		    RDC_PROGRAM, vers, max_msgsize, retries, cred, &client);
27547836SJohn.Forte@Sun.COM 
27557836SJohn.Forte@Sun.COM 		if (ret != 0) {
27567836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
27579093SRamana.Srikanth@Sun.COM 			    "!rdc_call: tli_kcreate failed %d", ret);
27587836SJohn.Forte@Sun.COM 			return (ret);
27597836SJohn.Forte@Sun.COM 		}
27607836SJohn.Forte@Sun.COM 
27617836SJohn.Forte@Sun.COM 		*rch = 0;
27627836SJohn.Forte@Sun.COM 		*clp = client;
27637836SJohn.Forte@Sun.COM 		(void) CLNT_CONTROL(client, CLSET_PROGRESS, NULL);
27647836SJohn.Forte@Sun.COM 		return (ret);
27657836SJohn.Forte@Sun.COM 	}
27667836SJohn.Forte@Sun.COM 
27677836SJohn.Forte@Sun.COM 	if (ch != NULL) {
27687836SJohn.Forte@Sun.COM 		/* reuse a cached handle */
27697836SJohn.Forte@Sun.COM 
27707836SJohn.Forte@Sun.COM 		ch->ch_inuse = TRUE;
27717836SJohn.Forte@Sun.COM 		ch->ch_timesused++;
27727836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_clnt_lock);
27737836SJohn.Forte@Sun.COM 
27747836SJohn.Forte@Sun.COM 		*rch = ch;
27757836SJohn.Forte@Sun.COM 
27767836SJohn.Forte@Sun.COM 		if (ch->ch_client == NULL) {
27777836SJohn.Forte@Sun.COM 			ret = clnt_tli_kcreate(svp->ri_knconf, &(svp->ri_addr),
27789093SRamana.Srikanth@Sun.COM 			    RDC_PROGRAM, vers, max_msgsize, retries,
27799093SRamana.Srikanth@Sun.COM 			    cred, &ch->ch_client);
27807836SJohn.Forte@Sun.COM 			if (ret != 0) {
27817836SJohn.Forte@Sun.COM 				ch->ch_inuse = FALSE;
27827836SJohn.Forte@Sun.COM 				return (ret);
27837836SJohn.Forte@Sun.COM 			}
27847836SJohn.Forte@Sun.COM 
27857836SJohn.Forte@Sun.COM 			(void) CLNT_CONTROL(ch->ch_client, CLSET_PROGRESS,
27869093SRamana.Srikanth@Sun.COM 			    NULL);
27877836SJohn.Forte@Sun.COM 			*clp = ch->ch_client;
27887836SJohn.Forte@Sun.COM 
27897836SJohn.Forte@Sun.COM 			return (0);
27907836SJohn.Forte@Sun.COM 		} else {
27917836SJohn.Forte@Sun.COM 		/*
27927836SJohn.Forte@Sun.COM 		 * Consecutive calls to CLNT_CALL() on the same client handle
27937836SJohn.Forte@Sun.COM 		 * get the same transaction ID.  We want a new xid per call,
27947836SJohn.Forte@Sun.COM 		 * so we first reinitialise the handle.
27957836SJohn.Forte@Sun.COM 		 */
27967836SJohn.Forte@Sun.COM 			(void) clnt_tli_kinit(ch->ch_client, svp->ri_knconf,
27979093SRamana.Srikanth@Sun.COM 			    &(svp->ri_addr), max_msgsize, retries, cred);
27987836SJohn.Forte@Sun.COM 
27997836SJohn.Forte@Sun.COM 			*clp = ch->ch_client;
28007836SJohn.Forte@Sun.COM 			return (0);
28017836SJohn.Forte@Sun.COM 		}
28027836SJohn.Forte@Sun.COM 	}
28037836SJohn.Forte@Sun.COM 
28047836SJohn.Forte@Sun.COM 	/* create new handle and cache it */
28057836SJohn.Forte@Sun.COM 	ch = (struct chtab *)kmem_zalloc(sizeof (*ch), KM_SLEEP);
28067836SJohn.Forte@Sun.COM 
28077836SJohn.Forte@Sun.COM 	if (ch) {
28087836SJohn.Forte@Sun.COM 		ch->ch_inuse = TRUE;
28097836SJohn.Forte@Sun.COM 		ch->ch_prog = RDC_PROGRAM;
28107836SJohn.Forte@Sun.COM 		ch->ch_vers = vers;
28117836SJohn.Forte@Sun.COM 		ch->ch_dev = svp->ri_knconf->knc_rdev;
28127836SJohn.Forte@Sun.COM 		ch->ch_protofmly = (char *)kmem_zalloc(
28139093SRamana.Srikanth@Sun.COM 		    strlen(svp->ri_knconf->knc_protofmly)+1, KM_SLEEP);
28147836SJohn.Forte@Sun.COM 		if (ch->ch_protofmly)
28157836SJohn.Forte@Sun.COM 			(void) strcpy(ch->ch_protofmly,
28167836SJohn.Forte@Sun.COM 			    svp->ri_knconf->knc_protofmly);
28177836SJohn.Forte@Sun.COM 		*plistp = ch;
28187836SJohn.Forte@Sun.COM 	}
28197836SJohn.Forte@Sun.COM 
28207836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_clnt_lock);
28217836SJohn.Forte@Sun.COM 
28227836SJohn.Forte@Sun.COM 	ret = clnt_tli_kcreate(svp->ri_knconf, &(svp->ri_addr),
28239093SRamana.Srikanth@Sun.COM 	    RDC_PROGRAM, vers, max_msgsize, retries, cred, clp);
28247836SJohn.Forte@Sun.COM 
28257836SJohn.Forte@Sun.COM 	if (ret != 0) {
28267836SJohn.Forte@Sun.COM 		if (ch)
28277836SJohn.Forte@Sun.COM 			ch->ch_inuse = FALSE;
28289093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_call: tli_kcreate failed %d", ret);
28297836SJohn.Forte@Sun.COM 		return (ret);
28307836SJohn.Forte@Sun.COM 	}
28317836SJohn.Forte@Sun.COM 
28327836SJohn.Forte@Sun.COM 	*rch = ch;
28337836SJohn.Forte@Sun.COM 	if (ch)
28347836SJohn.Forte@Sun.COM 		ch->ch_client = *clp;
28357836SJohn.Forte@Sun.COM 
28367836SJohn.Forte@Sun.COM 	(void) CLNT_CONTROL(*clp, CLSET_PROGRESS, NULL);
28377836SJohn.Forte@Sun.COM 
28387836SJohn.Forte@Sun.COM 	return (ret);
28397836SJohn.Forte@Sun.COM }
28407836SJohn.Forte@Sun.COM 
28417836SJohn.Forte@Sun.COM 
28427836SJohn.Forte@Sun.COM long rdc_clnt_count = 0;
28437836SJohn.Forte@Sun.COM 
28447836SJohn.Forte@Sun.COM /*
28457836SJohn.Forte@Sun.COM  * rdc_clnt_call
28467836SJohn.Forte@Sun.COM  * Arguments:
28477836SJohn.Forte@Sun.COM  *	rdc_srv_t *svp - rdc servinfo
28487836SJohn.Forte@Sun.COM  *	rpcproc_t proc; - rpcid
28497836SJohn.Forte@Sun.COM  *	rpcvers_t vers; - protocol version
28507836SJohn.Forte@Sun.COM  *	xdrproc_t xargs;- xdr function
28517836SJohn.Forte@Sun.COM  *	caddr_t argsp;- args to xdr function
28527836SJohn.Forte@Sun.COM  *	xdrproc_t xres;- xdr function
28537836SJohn.Forte@Sun.COM  *	caddr_t resp;- args to xdr function
28547836SJohn.Forte@Sun.COM  *	struct timeval timeout;
28557836SJohn.Forte@Sun.COM  * Performs RPC client call using specific protocol and version
28567836SJohn.Forte@Sun.COM  */
28577836SJohn.Forte@Sun.COM 
28587836SJohn.Forte@Sun.COM int
rdc_clnt_call(rdc_srv_t * svp,rpcproc_t proc,rpcvers_t vers,xdrproc_t xargs,caddr_t argsp,xdrproc_t xres,caddr_t resp,struct timeval * timeout)28597836SJohn.Forte@Sun.COM rdc_clnt_call(rdc_srv_t *svp, rpcproc_t proc, rpcvers_t vers,
28607836SJohn.Forte@Sun.COM 		xdrproc_t xargs, caddr_t argsp,
28617836SJohn.Forte@Sun.COM 		xdrproc_t xres, caddr_t resp, struct timeval *timeout)
28627836SJohn.Forte@Sun.COM {
28637836SJohn.Forte@Sun.COM 	CLIENT *rh = NULL;
28647836SJohn.Forte@Sun.COM 	int err;
28657836SJohn.Forte@Sun.COM 	int tries = 0;
28667836SJohn.Forte@Sun.COM 	struct chtab *ch = NULL;
28677836SJohn.Forte@Sun.COM 
28687836SJohn.Forte@Sun.COM 	err = rdc_clnt_get(svp, vers, &ch, &rh);
28697836SJohn.Forte@Sun.COM 	if (err || !rh)
28707836SJohn.Forte@Sun.COM 		return (err);
28717836SJohn.Forte@Sun.COM 
28727836SJohn.Forte@Sun.COM 	do {
28737836SJohn.Forte@Sun.COM 		DTRACE_PROBE3(rdc_clnt_call_1,
28749093SRamana.Srikanth@Sun.COM 		    CLIENT *, rh, rpcproc_t, proc, xdrproc_t, xargs);
28757836SJohn.Forte@Sun.COM 
28767836SJohn.Forte@Sun.COM 		err = cl_call_sig(rh, proc, xargs, argsp, xres, resp, *timeout);
28777836SJohn.Forte@Sun.COM 
28787836SJohn.Forte@Sun.COM 		DTRACE_PROBE1(rdc_clnt_call_end, int, err);
28797836SJohn.Forte@Sun.COM 
28807836SJohn.Forte@Sun.COM 		switch (err) {
28817836SJohn.Forte@Sun.COM 			case RPC_SUCCESS: /* bail now */
28827836SJohn.Forte@Sun.COM 				goto done;
28837836SJohn.Forte@Sun.COM 			case RPC_INTR:	/* No recovery from this */
28847836SJohn.Forte@Sun.COM 				goto done;
28857836SJohn.Forte@Sun.COM 			case RPC_PROGVERSMISMATCH:
28867836SJohn.Forte@Sun.COM 				goto done;
28877836SJohn.Forte@Sun.COM 			case RPC_TLIERROR:
28887836SJohn.Forte@Sun.COM 				/* fall thru */
28897836SJohn.Forte@Sun.COM 			case RPC_XPRTFAILED:
28907836SJohn.Forte@Sun.COM 				/* Delay here to err on side of caution */
28917836SJohn.Forte@Sun.COM 				/* fall thru */
28927836SJohn.Forte@Sun.COM 			case RPC_VERSMISMATCH:
28937836SJohn.Forte@Sun.COM 
28947836SJohn.Forte@Sun.COM 			default:
28957836SJohn.Forte@Sun.COM 				if (IS_UNRECOVERABLE_RPC(err)) {
28967836SJohn.Forte@Sun.COM 					goto done;
28977836SJohn.Forte@Sun.COM 				}
28987836SJohn.Forte@Sun.COM 				tries++;
28997836SJohn.Forte@Sun.COM 			/*
29007836SJohn.Forte@Sun.COM 			 * The call is in progress (over COTS)
29017836SJohn.Forte@Sun.COM 			 * Try the CLNT_CALL again, but don't
29027836SJohn.Forte@Sun.COM 			 * print a noisy error message
29037836SJohn.Forte@Sun.COM 			 */
29047836SJohn.Forte@Sun.COM 				if (err == RPC_INPROGRESS)
29057836SJohn.Forte@Sun.COM 					break;
29069093SRamana.Srikanth@Sun.COM 				cmn_err(CE_NOTE, "!SNDR client: err %d %s",
29079093SRamana.Srikanth@Sun.COM 				    err, clnt_sperrno(err));
29087836SJohn.Forte@Sun.COM 			}
29097836SJohn.Forte@Sun.COM 	} while (tries && (tries < 2));
29107836SJohn.Forte@Sun.COM done:
29117836SJohn.Forte@Sun.COM 	++rdc_clnt_count;
29127836SJohn.Forte@Sun.COM 	rdc_clnt_free(ch, rh);
29137836SJohn.Forte@Sun.COM 	return (err);
29147836SJohn.Forte@Sun.COM }
29157836SJohn.Forte@Sun.COM 
29167836SJohn.Forte@Sun.COM 
29177836SJohn.Forte@Sun.COM /*
29187836SJohn.Forte@Sun.COM  * Call an rpc from the client side, not caring which protocol is used.
29197836SJohn.Forte@Sun.COM  */
29207836SJohn.Forte@Sun.COM int
rdc_clnt_call_any(rdc_srv_t * svp,rdc_if_t * ip,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp,xdrproc_t xres,caddr_t resp,struct timeval * timeout)29217836SJohn.Forte@Sun.COM rdc_clnt_call_any(rdc_srv_t *svp, rdc_if_t *ip, rpcproc_t proc,
29227836SJohn.Forte@Sun.COM 		xdrproc_t xargs, caddr_t argsp,
29237836SJohn.Forte@Sun.COM 		xdrproc_t xres, caddr_t resp, struct timeval *timeout)
29247836SJohn.Forte@Sun.COM {
29257836SJohn.Forte@Sun.COM 	rpcvers_t vers;
29267836SJohn.Forte@Sun.COM 	int rc;
29277836SJohn.Forte@Sun.COM 
29287836SJohn.Forte@Sun.COM 	if (ip != NULL) {
29297836SJohn.Forte@Sun.COM 		vers = ip->rpc_version;
29307836SJohn.Forte@Sun.COM 	} else {
29317836SJohn.Forte@Sun.COM 		vers = RDC_VERS_MAX;
29327836SJohn.Forte@Sun.COM 	}
29337836SJohn.Forte@Sun.COM 
29347836SJohn.Forte@Sun.COM 	do {
29357836SJohn.Forte@Sun.COM 		rc = rdc_clnt_call(svp, proc, vers, xargs, argsp,
29369093SRamana.Srikanth@Sun.COM 		    xres, resp, timeout);
29377836SJohn.Forte@Sun.COM 
29387836SJohn.Forte@Sun.COM 		if (rc == RPC_PROGVERSMISMATCH) {
29397836SJohn.Forte@Sun.COM 			/*
29407836SJohn.Forte@Sun.COM 			 * Downgrade and try again.
29417836SJohn.Forte@Sun.COM 			 */
29427836SJohn.Forte@Sun.COM 			vers--;
29437836SJohn.Forte@Sun.COM 		}
29447836SJohn.Forte@Sun.COM 	} while ((vers >= RDC_VERS_MIN) && (rc == RPC_PROGVERSMISMATCH));
29457836SJohn.Forte@Sun.COM 
29467836SJohn.Forte@Sun.COM 	if ((rc == 0) && (ip != NULL) && (vers != ip->rpc_version)) {
29477836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_ping_lock);
29487836SJohn.Forte@Sun.COM 		ip->rpc_version = vers;
29497836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_ping_lock);
29507836SJohn.Forte@Sun.COM 	}
29517836SJohn.Forte@Sun.COM 
29527836SJohn.Forte@Sun.COM 	return (rc);
29537836SJohn.Forte@Sun.COM }
29547836SJohn.Forte@Sun.COM 
29557836SJohn.Forte@Sun.COM /*
29567836SJohn.Forte@Sun.COM  * Call an rpc from the client side, starting with protocol specified
29577836SJohn.Forte@Sun.COM  */
29587836SJohn.Forte@Sun.COM int
rdc_clnt_call_walk(rdc_k_info_t * krdc,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp,xdrproc_t xres,caddr_t resp,struct timeval * timeout)29597836SJohn.Forte@Sun.COM rdc_clnt_call_walk(rdc_k_info_t *krdc, rpcproc_t proc, xdrproc_t xargs,
29607836SJohn.Forte@Sun.COM 		caddr_t argsp, xdrproc_t xres, caddr_t resp,
29617836SJohn.Forte@Sun.COM 		struct timeval *timeout)
29627836SJohn.Forte@Sun.COM {
29637836SJohn.Forte@Sun.COM 	int rc;
29647836SJohn.Forte@Sun.COM 	rpcvers_t vers;
29657836SJohn.Forte@Sun.COM 	rdc_srv_t *svp = krdc->lsrv;
29667836SJohn.Forte@Sun.COM 	rdc_if_t *ip = krdc->intf;
29677836SJohn.Forte@Sun.COM 	vers = krdc->rpc_version;
29687836SJohn.Forte@Sun.COM 
29697836SJohn.Forte@Sun.COM 	do {
29707836SJohn.Forte@Sun.COM 		rc = rdc_clnt_call(svp, proc, vers, xargs, argsp,
29719093SRamana.Srikanth@Sun.COM 		    xres, resp, timeout);
29727836SJohn.Forte@Sun.COM 
29737836SJohn.Forte@Sun.COM 		if (rc == RPC_PROGVERSMISMATCH) {
29747836SJohn.Forte@Sun.COM 			/*
29757836SJohn.Forte@Sun.COM 			 * Downgrade and try again.
29767836SJohn.Forte@Sun.COM 			 */
29777836SJohn.Forte@Sun.COM 			vers--;
29787836SJohn.Forte@Sun.COM 		}
29797836SJohn.Forte@Sun.COM 	} while ((vers >= RDC_VERS_MIN) && (rc == RPC_PROGVERSMISMATCH));
29807836SJohn.Forte@Sun.COM 
29817836SJohn.Forte@Sun.COM 	if ((rc == 0) && (ip != NULL) && (vers != ip->rpc_version)) {
29827836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_ping_lock);
29837836SJohn.Forte@Sun.COM 		ip->rpc_version = vers;
29847836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_ping_lock);
29857836SJohn.Forte@Sun.COM 	}
29867836SJohn.Forte@Sun.COM 
29877836SJohn.Forte@Sun.COM 	return (rc);
29887836SJohn.Forte@Sun.COM }
29897836SJohn.Forte@Sun.COM 
29907836SJohn.Forte@Sun.COM /*
29917836SJohn.Forte@Sun.COM  * rdc_clnt_free
29927836SJohn.Forte@Sun.COM  * Free a client structure into the cache, or if this was a temporary
29937836SJohn.Forte@Sun.COM  * handle allocated above MAXCLIENTS, destroy it.
29947836SJohn.Forte@Sun.COM  */
29957836SJohn.Forte@Sun.COM static void
rdc_clnt_free(struct chtab * ch,CLIENT * clp)29967836SJohn.Forte@Sun.COM rdc_clnt_free(struct chtab *ch, CLIENT *clp)
29977836SJohn.Forte@Sun.COM {
29987836SJohn.Forte@Sun.COM 	if (ch != NULL) {
29997836SJohn.Forte@Sun.COM 		/* cached client, just clear inuse flag and return */
30007836SJohn.Forte@Sun.COM 		ASSERT(ch->ch_client == clp);
30017836SJohn.Forte@Sun.COM 		ch->ch_inuse = FALSE;
30027836SJohn.Forte@Sun.COM 		return;
30037836SJohn.Forte@Sun.COM 	}
30047836SJohn.Forte@Sun.COM 
30057836SJohn.Forte@Sun.COM 	/* temporary handle allocated above MAXCLIENTS, so destroy it */
30067836SJohn.Forte@Sun.COM 
30077836SJohn.Forte@Sun.COM 	if (clp->cl_auth) {
30087836SJohn.Forte@Sun.COM 		AUTH_DESTROY(clp->cl_auth);
30097836SJohn.Forte@Sun.COM 		clp->cl_auth = 0;
30107836SJohn.Forte@Sun.COM 	}
30117836SJohn.Forte@Sun.COM 
30127836SJohn.Forte@Sun.COM 	CLNT_DESTROY(clp);
30137836SJohn.Forte@Sun.COM }
30147836SJohn.Forte@Sun.COM 
30157836SJohn.Forte@Sun.COM 
30167836SJohn.Forte@Sun.COM /*
30177836SJohn.Forte@Sun.COM  * _rdc_clnt_destroy
30187836SJohn.Forte@Sun.COM  * Free a chain (ch_list or ch_next) of cached clients
30197836SJohn.Forte@Sun.COM  */
30207836SJohn.Forte@Sun.COM static int
_rdc_clnt_destroy(struct chtab ** p,const int list)30217836SJohn.Forte@Sun.COM _rdc_clnt_destroy(struct chtab **p, const int list)
30227836SJohn.Forte@Sun.COM {
30237836SJohn.Forte@Sun.COM 	struct chtab *ch;
30247836SJohn.Forte@Sun.COM 	int leak = 0;
30257836SJohn.Forte@Sun.COM 
30267836SJohn.Forte@Sun.COM 	if (!p)
30277836SJohn.Forte@Sun.COM 		return (0);
30287836SJohn.Forte@Sun.COM 
30297836SJohn.Forte@Sun.COM 	while (*p != NULL) {
30307836SJohn.Forte@Sun.COM 		ch = *p;
30317836SJohn.Forte@Sun.COM 
30327836SJohn.Forte@Sun.COM 		/*
30337836SJohn.Forte@Sun.COM 		 * unlink from the chain
30347836SJohn.Forte@Sun.COM 		 * - this leaks the client if it was inuse
30357836SJohn.Forte@Sun.COM 		 */
30367836SJohn.Forte@Sun.COM 
30377836SJohn.Forte@Sun.COM 		*p = list ? ch->ch_list : ch->ch_next;
30387836SJohn.Forte@Sun.COM 
30397836SJohn.Forte@Sun.COM 		if (!ch->ch_inuse) {
30407836SJohn.Forte@Sun.COM 			/* unused client - destroy it */
30417836SJohn.Forte@Sun.COM 
30427836SJohn.Forte@Sun.COM 			if (ch->ch_client) {
30437836SJohn.Forte@Sun.COM 				if (ch->ch_client->cl_auth) {
30447836SJohn.Forte@Sun.COM 					AUTH_DESTROY(ch->ch_client->cl_auth);
30457836SJohn.Forte@Sun.COM 					ch->ch_client->cl_auth = 0;
30467836SJohn.Forte@Sun.COM 				}
30477836SJohn.Forte@Sun.COM 
30487836SJohn.Forte@Sun.COM 				CLNT_DESTROY(ch->ch_client);
30497836SJohn.Forte@Sun.COM 				ch->ch_client = 0;
30507836SJohn.Forte@Sun.COM 			}
30517836SJohn.Forte@Sun.COM 
30527836SJohn.Forte@Sun.COM 			if (ch->ch_protofmly)
30537836SJohn.Forte@Sun.COM 				kmem_free(ch->ch_protofmly,
30549093SRamana.Srikanth@Sun.COM 				    strlen(ch->ch_protofmly)+1);
30557836SJohn.Forte@Sun.COM 
30567836SJohn.Forte@Sun.COM 			kmem_free(ch, sizeof (*ch));
30577836SJohn.Forte@Sun.COM 		} else {
30587836SJohn.Forte@Sun.COM 			/* remember client leak */
30597836SJohn.Forte@Sun.COM 			leak++;
30607836SJohn.Forte@Sun.COM 		}
30617836SJohn.Forte@Sun.COM 	}
30627836SJohn.Forte@Sun.COM 
30637836SJohn.Forte@Sun.COM 	return (leak);
30647836SJohn.Forte@Sun.COM }
30657836SJohn.Forte@Sun.COM 
30667836SJohn.Forte@Sun.COM 
30677836SJohn.Forte@Sun.COM /*
30687836SJohn.Forte@Sun.COM  * rdc_clnt_destroy
30697836SJohn.Forte@Sun.COM  * Free client caching table on unconfigure
30707836SJohn.Forte@Sun.COM  */
30717836SJohn.Forte@Sun.COM void
rdc_clnt_destroy(void)30727836SJohn.Forte@Sun.COM rdc_clnt_destroy(void)
30737836SJohn.Forte@Sun.COM {
30747836SJohn.Forte@Sun.COM 	struct chtab *ch;
30757836SJohn.Forte@Sun.COM 	int leak = 0;
30767836SJohn.Forte@Sun.COM 
30777836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_clnt_lock);
30787836SJohn.Forte@Sun.COM 
30797836SJohn.Forte@Sun.COM 	/* destroy each ch_list chain */
30807836SJohn.Forte@Sun.COM 
30817836SJohn.Forte@Sun.COM 	for (ch = rdc_chtable; ch; ch = ch->ch_next) {
30827836SJohn.Forte@Sun.COM 		leak += _rdc_clnt_destroy(&ch->ch_list, 1);
30837836SJohn.Forte@Sun.COM 	}
30847836SJohn.Forte@Sun.COM 
30857836SJohn.Forte@Sun.COM 	/* destroy the main ch_next chain */
30867836SJohn.Forte@Sun.COM 	leak += _rdc_clnt_destroy(&rdc_chtable, 0);
30877836SJohn.Forte@Sun.COM 
30887836SJohn.Forte@Sun.COM 	if (leak) {
30897836SJohn.Forte@Sun.COM 		/* we are about to leak clients */
30907836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
30919093SRamana.Srikanth@Sun.COM 		    "!rdc_clnt_destroy: leaking %d inuse clients", leak);
30927836SJohn.Forte@Sun.COM 	}
30937836SJohn.Forte@Sun.COM 
30947836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_clnt_lock);
30957836SJohn.Forte@Sun.COM }
30967836SJohn.Forte@Sun.COM 
30977836SJohn.Forte@Sun.COM #ifdef	DEBUG
30987836SJohn.Forte@Sun.COM /*
30997836SJohn.Forte@Sun.COM  * Function to send an asynchronous net_data6 request
31007836SJohn.Forte@Sun.COM  * direct to a server to allow the generation of
31017836SJohn.Forte@Sun.COM  * out of order requests for ZatoIchi tests.
31027836SJohn.Forte@Sun.COM  */
31037836SJohn.Forte@Sun.COM int
rdc_async6(void * arg,int mode,int * rvp)31047836SJohn.Forte@Sun.COM rdc_async6(void *arg, int mode, int *rvp)
31057836SJohn.Forte@Sun.COM {
31067836SJohn.Forte@Sun.COM 	int			index;
31077836SJohn.Forte@Sun.COM 	rdc_async6_t		async6;
31087836SJohn.Forte@Sun.COM 	struct net_data6	data6;
31097836SJohn.Forte@Sun.COM 	rdc_k_info_t		*krdc;
31107836SJohn.Forte@Sun.COM 	rdc_u_info_t		*urdc;
31117836SJohn.Forte@Sun.COM 	char			*data;
31127836SJohn.Forte@Sun.COM 	int			datasz;
31137836SJohn.Forte@Sun.COM 	char			*datap;
31147836SJohn.Forte@Sun.COM 	int			rc;
31157836SJohn.Forte@Sun.COM 	struct timeval		t;
31167836SJohn.Forte@Sun.COM 	struct netwriteres	netret;
31177836SJohn.Forte@Sun.COM 	int i;
31187836SJohn.Forte@Sun.COM 
31197836SJohn.Forte@Sun.COM 	rc = 0;
31207836SJohn.Forte@Sun.COM 	*rvp = 0;
31217836SJohn.Forte@Sun.COM 	/*
31227836SJohn.Forte@Sun.COM 	 * copyin the user's arguments.
31237836SJohn.Forte@Sun.COM 	 */
31247836SJohn.Forte@Sun.COM 	if (ddi_copyin(arg, &async6, sizeof (async6), mode) < 0) {
31257836SJohn.Forte@Sun.COM 		return (EFAULT);
31267836SJohn.Forte@Sun.COM 	}
31277836SJohn.Forte@Sun.COM 
31287836SJohn.Forte@Sun.COM 	/*
31297836SJohn.Forte@Sun.COM 	 * search by the secondary host and file.
31307836SJohn.Forte@Sun.COM 	 */
31317836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
31327836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
31337836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
31347836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
31357836SJohn.Forte@Sun.COM 
31367836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
31377836SJohn.Forte@Sun.COM 			continue;
31387836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
31397836SJohn.Forte@Sun.COM 			continue;
31407836SJohn.Forte@Sun.COM 		if (!IS_ASYNC(urdc))
31417836SJohn.Forte@Sun.COM 			continue;
31427836SJohn.Forte@Sun.COM 		if (krdc->rpc_version < RDC_VERSION6)
31437836SJohn.Forte@Sun.COM 			continue;
31447836SJohn.Forte@Sun.COM 
31457836SJohn.Forte@Sun.COM 		if ((strncmp(urdc->secondary.intf, async6.sechost,
31467836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) == 0) &&
31477836SJohn.Forte@Sun.COM 		    (strncmp(urdc->secondary.file, async6.secfile,
31487836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) == 0)) {
31497836SJohn.Forte@Sun.COM 			break;
31507836SJohn.Forte@Sun.COM 		}
31517836SJohn.Forte@Sun.COM 	}
31527836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
31537836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
31547836SJohn.Forte@Sun.COM 		return (ENOENT);
31557836SJohn.Forte@Sun.COM 	}
31567836SJohn.Forte@Sun.COM 
31577836SJohn.Forte@Sun.COM 	if (async6.spos != -1) {
31587836SJohn.Forte@Sun.COM 		if ((async6.spos < async6.pos) ||
31597836SJohn.Forte@Sun.COM 		    ((async6.spos + async6.slen) >
31607836SJohn.Forte@Sun.COM 		    (async6.pos + async6.len))) {
31619093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!Sub task not within range "
31627836SJohn.Forte@Sun.COM 			    "start %d length %d sub start %d sub length %d",
31637836SJohn.Forte@Sun.COM 			    async6.pos, async6.len, async6.spos, async6.slen);
31647836SJohn.Forte@Sun.COM 			return (EIO);
31657836SJohn.Forte@Sun.COM 		}
31667836SJohn.Forte@Sun.COM 	}
31677836SJohn.Forte@Sun.COM 
31687836SJohn.Forte@Sun.COM 	datasz = FBA_SIZE(1);
31697836SJohn.Forte@Sun.COM 	data = kmem_alloc(datasz, KM_SLEEP);
31707836SJohn.Forte@Sun.COM 	datap = data;
31717836SJohn.Forte@Sun.COM 	while (datap < &data[datasz]) {
31727836SJohn.Forte@Sun.COM 		/* LINTED */
31737836SJohn.Forte@Sun.COM 		*datap++ = async6.pat;
31747836SJohn.Forte@Sun.COM 	}
31757836SJohn.Forte@Sun.COM 
31767836SJohn.Forte@Sun.COM 	/*
31777836SJohn.Forte@Sun.COM 	 * Fill in the net databuffer prior to transmission.
31787836SJohn.Forte@Sun.COM 	 */
31797836SJohn.Forte@Sun.COM 
31807836SJohn.Forte@Sun.COM 	data6.local_cd = krdc->index;
31817836SJohn.Forte@Sun.COM 	if (krdc->remote_index == -1) {
31829093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!Remote index not known");
31837836SJohn.Forte@Sun.COM 		kmem_free(data, datasz);
31847836SJohn.Forte@Sun.COM 		return (EIO);
31857836SJohn.Forte@Sun.COM 	} else {
31867836SJohn.Forte@Sun.COM 		data6.cd = krdc->remote_index;
31877836SJohn.Forte@Sun.COM 	}
31887836SJohn.Forte@Sun.COM 	data6.pos = async6.pos;
31897836SJohn.Forte@Sun.COM 	data6.len = async6.len;
31907836SJohn.Forte@Sun.COM 	data6.flag = 0;
31917836SJohn.Forte@Sun.COM 	data6.idx = async6.idx;
31927836SJohn.Forte@Sun.COM 	data6.seq = async6.seq;
31937836SJohn.Forte@Sun.COM 
31947836SJohn.Forte@Sun.COM 	if (async6.spos == -1) {
31957836SJohn.Forte@Sun.COM 		data6.sfba = async6.pos;
31967836SJohn.Forte@Sun.COM 		data6.nfba = async6.len;
31977836SJohn.Forte@Sun.COM 		data6.endoblk = 1;
31987836SJohn.Forte@Sun.COM 
31997836SJohn.Forte@Sun.COM 	} else {
32007836SJohn.Forte@Sun.COM 		data6.sfba = async6.spos;
32017836SJohn.Forte@Sun.COM 		data6.nfba = async6.slen;
32027836SJohn.Forte@Sun.COM 		data6.endoblk = async6.endind;
32037836SJohn.Forte@Sun.COM 	}
32047836SJohn.Forte@Sun.COM 
32057836SJohn.Forte@Sun.COM 	data6.data.data_len = datasz;
32067836SJohn.Forte@Sun.COM 	data6.data.data_val = data;
32077836SJohn.Forte@Sun.COM 
32087836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
32097836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
32107836SJohn.Forte@Sun.COM 
32117836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_val = NULL;
32127836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_len = 0;
32137836SJohn.Forte@Sun.COM 
32147836SJohn.Forte@Sun.COM 
32157836SJohn.Forte@Sun.COM 	rc = rdc_clnt_call(krdc->lsrv, RDCPROC_WRITE6, krdc->rpc_version,
32167836SJohn.Forte@Sun.COM 	    xdr_net_data6, (char *)&data6, xdr_netwriteres, (char *)&netret,
32177836SJohn.Forte@Sun.COM 	    &t);
32187836SJohn.Forte@Sun.COM 
32197836SJohn.Forte@Sun.COM 	kmem_free(data, datasz);
32207836SJohn.Forte@Sun.COM 	if (rc == 0) {
32217836SJohn.Forte@Sun.COM 		if (netret.result < 0) {
32227836SJohn.Forte@Sun.COM 			rc = -netret.result;
32237836SJohn.Forte@Sun.COM 		}
32249093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!async6: seq %u result %d index %d "
32257836SJohn.Forte@Sun.COM 		    "pendcnt %d",
32267836SJohn.Forte@Sun.COM 		    netret.seq, netret.result, netret.index,
32277836SJohn.Forte@Sun.COM 		    netret.vecdata.vecdata_len);
32287836SJohn.Forte@Sun.COM 		for (i = 0; i < netret.vecdata.vecdata_len; i++) {
32297836SJohn.Forte@Sun.COM 			net_pendvec_t pvec;
32307836SJohn.Forte@Sun.COM 			bcopy(netret.vecdata.vecdata_val + i, &pvec,
32317836SJohn.Forte@Sun.COM 			    sizeof (net_pendvec_t));
32329093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!Seq %u pos %llu len %llu",
32337836SJohn.Forte@Sun.COM 			    pvec.seq, (unsigned long long)pvec.apos,
32347836SJohn.Forte@Sun.COM 			    (unsigned long long)pvec.alen);
32357836SJohn.Forte@Sun.COM 		}
32367836SJohn.Forte@Sun.COM 		if (netret.vecdata.vecdata_val)
32377836SJohn.Forte@Sun.COM 			kmem_free(netret.vecdata.vecdata_val,
32387836SJohn.Forte@Sun.COM 			    netret.vecdata.vecdata_len *
32397836SJohn.Forte@Sun.COM 			    sizeof (net_pendvec_t));
32407836SJohn.Forte@Sun.COM 	} else {
32419093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!async6: rpc call failed %d", rc);
32427836SJohn.Forte@Sun.COM 	}
32437836SJohn.Forte@Sun.COM 	*rvp = netret.index;
32447836SJohn.Forte@Sun.COM 	return (rc);
32457836SJohn.Forte@Sun.COM }
32467836SJohn.Forte@Sun.COM 
32477836SJohn.Forte@Sun.COM /*
32487836SJohn.Forte@Sun.COM  * Function to send an net_read6 request
32497836SJohn.Forte@Sun.COM  * direct to a server to allow the generation of
32507836SJohn.Forte@Sun.COM  * read requests.
32517836SJohn.Forte@Sun.COM  */
32527836SJohn.Forte@Sun.COM int
rdc_readgen(void * arg,int mode,int * rvp)32537836SJohn.Forte@Sun.COM rdc_readgen(void *arg, int mode, int *rvp)
32547836SJohn.Forte@Sun.COM {
32557836SJohn.Forte@Sun.COM 	int			index;
32567836SJohn.Forte@Sun.COM 	rdc_readgen_t		readgen;
32577836SJohn.Forte@Sun.COM 	rdc_readgen32_t		readgen32;
32587836SJohn.Forte@Sun.COM 	struct rread6		read6;
32597836SJohn.Forte@Sun.COM 	struct rread		read5;
32607836SJohn.Forte@Sun.COM 	rdc_k_info_t		*krdc;
32617836SJohn.Forte@Sun.COM 	int			ret;
32627836SJohn.Forte@Sun.COM 	struct timeval		t;
32637836SJohn.Forte@Sun.COM 	struct rdcrdresult	rr;
32647836SJohn.Forte@Sun.COM 	int			err;
32657836SJohn.Forte@Sun.COM 
32667836SJohn.Forte@Sun.COM 	*rvp = 0;
32677836SJohn.Forte@Sun.COM 	rr.rr_bufsize = 0;	/* rpc data buffer length (bytes) */
32687836SJohn.Forte@Sun.COM 	rr.rr_data = NULL;	/* rpc data buffer */
32697836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
32707836SJohn.Forte@Sun.COM 		if (ddi_copyin(arg, &readgen32, sizeof (readgen32), mode)) {
32717836SJohn.Forte@Sun.COM 			return (EFAULT);
32727836SJohn.Forte@Sun.COM 		}
32737836SJohn.Forte@Sun.COM 		(void) strncpy(readgen.sechost, readgen32.sechost,
32747836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE);
32757836SJohn.Forte@Sun.COM 		(void) strncpy(readgen.secfile, readgen32.secfile, NSC_MAXPATH);
32767836SJohn.Forte@Sun.COM 		readgen.len = readgen32.len;
32777836SJohn.Forte@Sun.COM 		readgen.pos = readgen32.pos;
32787836SJohn.Forte@Sun.COM 		readgen.idx = readgen32.idx;
32797836SJohn.Forte@Sun.COM 		readgen.flag = readgen32.flag;
32807836SJohn.Forte@Sun.COM 		readgen.data = (void *)(unsigned long)readgen32.data;
32817836SJohn.Forte@Sun.COM 		readgen.rpcversion = readgen32.rpcversion;
32827836SJohn.Forte@Sun.COM 	} else {
32837836SJohn.Forte@Sun.COM 		if (ddi_copyin(arg, &readgen, sizeof (readgen), mode)) {
32847836SJohn.Forte@Sun.COM 			return (EFAULT);
32857836SJohn.Forte@Sun.COM 		}
32867836SJohn.Forte@Sun.COM 	}
32877836SJohn.Forte@Sun.COM 	switch (readgen.rpcversion) {
32887836SJohn.Forte@Sun.COM 	case 5:
32897836SJohn.Forte@Sun.COM 	case 6:
32907836SJohn.Forte@Sun.COM 		break;
32917836SJohn.Forte@Sun.COM 	default:
32927836SJohn.Forte@Sun.COM 		return (EINVAL);
32937836SJohn.Forte@Sun.COM 	}
32947836SJohn.Forte@Sun.COM 
32957836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
32967836SJohn.Forte@Sun.COM 	index = rdc_lookup_byhostdev(readgen.sechost, readgen.secfile);
32977836SJohn.Forte@Sun.COM 	if (index >= 0) {
32987836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
32997836SJohn.Forte@Sun.COM 	}
33007836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
33017836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
33027836SJohn.Forte@Sun.COM 		return (ENODEV);
33037836SJohn.Forte@Sun.COM 	}
33047836SJohn.Forte@Sun.COM 	/*
33057836SJohn.Forte@Sun.COM 	 * we should really call setbusy here.
33067836SJohn.Forte@Sun.COM 	 */
33077836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
33087836SJohn.Forte@Sun.COM 
33097836SJohn.Forte@Sun.COM 	t.tv_sec = rdc_rpc_tmout;
33107836SJohn.Forte@Sun.COM 	t.tv_usec = 0;
33117836SJohn.Forte@Sun.COM 	if (krdc->remote_index == -1) {
33129093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!Remote index not known");
33137836SJohn.Forte@Sun.COM 		ret = EIO;
33147836SJohn.Forte@Sun.COM 		goto out;
33157836SJohn.Forte@Sun.COM 	}
33167836SJohn.Forte@Sun.COM 	if (readgen.rpcversion == 6) {
33177836SJohn.Forte@Sun.COM 		read6.cd = krdc->remote_index;
33187836SJohn.Forte@Sun.COM 		read6.len = readgen.len;
33197836SJohn.Forte@Sun.COM 		read6.pos = readgen.pos;
33207836SJohn.Forte@Sun.COM 		read6.idx = readgen.idx;
33217836SJohn.Forte@Sun.COM 		read6.flag = readgen.flag;
33227836SJohn.Forte@Sun.COM 	} else {
33237836SJohn.Forte@Sun.COM 		read5.cd = krdc->remote_index;
33247836SJohn.Forte@Sun.COM 		read5.len = readgen.len;
33257836SJohn.Forte@Sun.COM 		read5.pos = readgen.pos;
33267836SJohn.Forte@Sun.COM 		read5.idx = readgen.idx;
33277836SJohn.Forte@Sun.COM 		read5.flag = readgen.flag;
33287836SJohn.Forte@Sun.COM 	}
33297836SJohn.Forte@Sun.COM 
33307836SJohn.Forte@Sun.COM 	if (readgen.flag & RDC_RREAD_START) {
33317836SJohn.Forte@Sun.COM 		if (readgen.rpcversion == 6) {
33327836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ6,
33337836SJohn.Forte@Sun.COM 			    RDC_VERSION6, xdr_rread6, (char *)&read6,
33347836SJohn.Forte@Sun.COM 			    xdr_int, (char *)&ret, &t);
33357836SJohn.Forte@Sun.COM 		} else {
33367836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ5,
33377836SJohn.Forte@Sun.COM 			    RDC_VERSION5, xdr_rread, (char *)&read5,
33387836SJohn.Forte@Sun.COM 			    xdr_int, (char *)&ret, &t);
33397836SJohn.Forte@Sun.COM 		}
33407836SJohn.Forte@Sun.COM 		if (err == 0) {
33417836SJohn.Forte@Sun.COM 			*rvp = ret;
33427836SJohn.Forte@Sun.COM 			ret = 0;
33437836SJohn.Forte@Sun.COM 		} else {
33447836SJohn.Forte@Sun.COM 			ret = EPROTO;
33457836SJohn.Forte@Sun.COM 		}
33467836SJohn.Forte@Sun.COM 	} else {
33477836SJohn.Forte@Sun.COM 		if (readgen.rpcversion == 6) {
33487836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ6,
33497836SJohn.Forte@Sun.COM 			    RDC_VERSION6, xdr_rread6, (char *)&read6,
33507836SJohn.Forte@Sun.COM 			    xdr_rdresult, (char *)&rr, &t);
33517836SJohn.Forte@Sun.COM 		} else {
33527836SJohn.Forte@Sun.COM 			err = rdc_clnt_call(krdc->lsrv, RDCPROC_READ5,
33537836SJohn.Forte@Sun.COM 			    RDC_VERSION5, xdr_rread, (char *)&read5,
33547836SJohn.Forte@Sun.COM 			    xdr_rdresult, (char *)&rr, &t);
33557836SJohn.Forte@Sun.COM 		}
33567836SJohn.Forte@Sun.COM 		if (err == 0) {
33577836SJohn.Forte@Sun.COM 			if (rr.rr_status != RDC_OK) {
33587836SJohn.Forte@Sun.COM 				ret = EIO;
33597836SJohn.Forte@Sun.COM 				goto out;
33607836SJohn.Forte@Sun.COM 			}
33617836SJohn.Forte@Sun.COM 			*rvp = rr.rr_bufsize;
33627836SJohn.Forte@Sun.COM 			if (ddi_copyout(rr.rr_data, readgen.data,
33637836SJohn.Forte@Sun.COM 			    rr.rr_bufsize, mode) != 0) {
33647836SJohn.Forte@Sun.COM 				ret = EFAULT;
33657836SJohn.Forte@Sun.COM 				goto out;
33667836SJohn.Forte@Sun.COM 			}
33677836SJohn.Forte@Sun.COM 			ret = 0;
33687836SJohn.Forte@Sun.COM 		} else {
33697836SJohn.Forte@Sun.COM 			ret = EPROTO;
33707836SJohn.Forte@Sun.COM 			goto out;
33717836SJohn.Forte@Sun.COM 		}
33727836SJohn.Forte@Sun.COM 	}
33737836SJohn.Forte@Sun.COM out:
33747836SJohn.Forte@Sun.COM 	if (rr.rr_data) {
33757836SJohn.Forte@Sun.COM 		kmem_free(rr.rr_data, rr.rr_bufsize);
33767836SJohn.Forte@Sun.COM 	}
33777836SJohn.Forte@Sun.COM 	return (ret);
33787836SJohn.Forte@Sun.COM }
33797836SJohn.Forte@Sun.COM 
33807836SJohn.Forte@Sun.COM 
33817836SJohn.Forte@Sun.COM #endif
3382