xref: /onnv-gate/usr/src/uts/common/avs/ns/rdc/rdc_svc.c (revision 11066:cebb50cbe4f9)
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 /*
277836SJohn.Forte@Sun.COM  * kRPC Server for sndr
287836SJohn.Forte@Sun.COM  */
297836SJohn.Forte@Sun.COM 
307836SJohn.Forte@Sun.COM #include <sys/types.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/conf.h>
367836SJohn.Forte@Sun.COM #include <sys/stream.h>
377836SJohn.Forte@Sun.COM #include <sys/errno.h>
387836SJohn.Forte@Sun.COM 
397836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
407836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
417836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
427836SJohn.Forte@Sun.COM 
437836SJohn.Forte@Sun.COM #ifdef _SunOS_2_6
447836SJohn.Forte@Sun.COM /*
457836SJohn.Forte@Sun.COM  * on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
467836SJohn.Forte@Sun.COM  * define enum_t here as it is all we need from rpc/types.h
477836SJohn.Forte@Sun.COM  * anyway and make it look like we included it. Yuck.
487836SJohn.Forte@Sun.COM  */
497836SJohn.Forte@Sun.COM #define	_RPC_TYPES_H
507836SJohn.Forte@Sun.COM typedef int enum_t;
517836SJohn.Forte@Sun.COM #else
527836SJohn.Forte@Sun.COM #ifndef DS_DDICT
537836SJohn.Forte@Sun.COM #include <rpc/types.h>
547836SJohn.Forte@Sun.COM #endif
557836SJohn.Forte@Sun.COM #endif /* _SunOS_2_6 */
567836SJohn.Forte@Sun.COM 
577836SJohn.Forte@Sun.COM #ifndef DS_DDICT
587836SJohn.Forte@Sun.COM #include <rpc/auth.h>
597836SJohn.Forte@Sun.COM #include <rpc/svc.h>
607836SJohn.Forte@Sun.COM #include <rpc/xdr.h>
617836SJohn.Forte@Sun.COM #endif
627836SJohn.Forte@Sun.COM #include <sys/ddi.h>
637836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
647836SJohn.Forte@Sun.COM #ifdef DS_DDICT
657836SJohn.Forte@Sun.COM #include <sys/nsctl/contract.h>
667836SJohn.Forte@Sun.COM #endif
677836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
687836SJohn.Forte@Sun.COM #include <sys/ncall/ncall.h>
697836SJohn.Forte@Sun.COM 
707836SJohn.Forte@Sun.COM #include <sys/sdt.h>		/* dtrace is S10 or later */
717836SJohn.Forte@Sun.COM 
727836SJohn.Forte@Sun.COM #include "rdc_io.h"
737836SJohn.Forte@Sun.COM #include "rdc_bitmap.h"
747836SJohn.Forte@Sun.COM #include "rdcsrv.h"
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM static rdc_sleepq_t *rdc_newsleepq();
777836SJohn.Forte@Sun.COM static void rdc_delsleepq(rdc_sleepq_t *);
787836SJohn.Forte@Sun.COM static int rdc_sleepq(rdc_group_t *, rdc_sleepq_t *);
797836SJohn.Forte@Sun.COM static int rdc_combywrite(rdc_k_info_t *, nsc_buf_t *);
807836SJohn.Forte@Sun.COM static int rdc_writemaxfba(rdc_k_info_t *, rdc_u_info_t *,
817836SJohn.Forte@Sun.COM     rdc_net_dataset_t *, uint_t, int);
827836SJohn.Forte@Sun.COM static void rdc_setbitind(int *, net_pendvec_t *, rdc_net_dataset_t *, uint_t,
837836SJohn.Forte@Sun.COM     int, int);
847836SJohn.Forte@Sun.COM static void rdc_dopending(rdc_group_t *, netwriteres *);
857836SJohn.Forte@Sun.COM static nsc_vec_t *rdc_dset2vec(rdc_net_dataset_t *);
867836SJohn.Forte@Sun.COM static int rdc_combyread(rdc_k_info_t *, rdc_u_info_t *, nsc_buf_t *);
877836SJohn.Forte@Sun.COM static int rdc_readmaxfba(int, nsc_off_t, nsc_size_t, int);
887836SJohn.Forte@Sun.COM static int rdc_dsetcopy(rdc_net_dataset_t *, nsc_vec_t *, nsc_off_t, nsc_size_t,
897836SJohn.Forte@Sun.COM     char *, int, int);
907836SJohn.Forte@Sun.COM 
917836SJohn.Forte@Sun.COM /* direction for dsetcopy() */
927836SJohn.Forte@Sun.COM #define	COPY_IN		1	/* copy data into the rpc buffer */
937836SJohn.Forte@Sun.COM #define	COPY_OUT	2	/* copy data out of the rpc buffer */
947836SJohn.Forte@Sun.COM 
957836SJohn.Forte@Sun.COM #define	MAX_EINTR_COUNT 1000
967836SJohn.Forte@Sun.COM 
977836SJohn.Forte@Sun.COM static int rdc_rread_slow;
987836SJohn.Forte@Sun.COM static rdcsrv_t rdc_srvtab[];
997836SJohn.Forte@Sun.COM 
1007836SJohn.Forte@Sun.COM #ifdef	DEBUG
1017836SJohn.Forte@Sun.COM static int rdc_netwrite6;
1027836SJohn.Forte@Sun.COM static int rdc_stall0;
1037836SJohn.Forte@Sun.COM static int rdc_sleepcnt;
1047836SJohn.Forte@Sun.COM int rdc_datasetcnt;
1057836SJohn.Forte@Sun.COM #endif
1067836SJohn.Forte@Sun.COM 
1077836SJohn.Forte@Sun.COM 
1087836SJohn.Forte@Sun.COM int
_rdc_sync_event_notify(int operation,char * volume,char * group)1097836SJohn.Forte@Sun.COM _rdc_sync_event_notify(int operation, char *volume, char *group)
1107836SJohn.Forte@Sun.COM {
1117836SJohn.Forte@Sun.COM 	int ack = 0;
1127836SJohn.Forte@Sun.COM 	clock_t time;
1137836SJohn.Forte@Sun.COM 
1147836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_sync_mutex);
1157836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_sync_event.mutex);
1167836SJohn.Forte@Sun.COM 
1177836SJohn.Forte@Sun.COM 	if (rdc_sync_event.daemon_waiting) {
1187836SJohn.Forte@Sun.COM 		rdc_sync_event.daemon_waiting = 0;
1197836SJohn.Forte@Sun.COM 		rdc_sync_event.event = operation;
1207836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_sync_event.master, volume, NSC_MAXPATH);
1217836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_sync_event.group, group, NSC_MAXPATH);
1227836SJohn.Forte@Sun.COM 
1237836SJohn.Forte@Sun.COM 		cv_signal(&rdc_sync_event.cv);
1247836SJohn.Forte@Sun.COM 
1257836SJohn.Forte@Sun.COM 		rdc_sync_event.kernel_waiting = 1;
126*11066Srafael.vanoni@sun.com 		time = cv_reltimedwait_sig(&rdc_sync_event.done_cv,
127*11066Srafael.vanoni@sun.com 		    &rdc_sync_event.mutex, rdc_sync_event_timeout,
128*11066Srafael.vanoni@sun.com 		    TR_CLOCK_TICK);
1297836SJohn.Forte@Sun.COM 		if (time == (clock_t)0 || time == (clock_t)-1) {
1307836SJohn.Forte@Sun.COM 			/* signalled or timed out */
1317836SJohn.Forte@Sun.COM 			ack = 0;
1327836SJohn.Forte@Sun.COM 		} else {
1337836SJohn.Forte@Sun.COM 			if (rdc_sync_event.ack)
1347836SJohn.Forte@Sun.COM 				ack = 1;
1357836SJohn.Forte@Sun.COM 			else
1367836SJohn.Forte@Sun.COM 				ack = -1;
1377836SJohn.Forte@Sun.COM 		}
1387836SJohn.Forte@Sun.COM 	}
1397836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_sync_event.mutex);
1407836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_sync_mutex);
1417836SJohn.Forte@Sun.COM 	return (ack);
1427836SJohn.Forte@Sun.COM }
1437836SJohn.Forte@Sun.COM 
1447836SJohn.Forte@Sun.COM 
1457836SJohn.Forte@Sun.COM int
_rdc_sync_event_wait(void * arg0,void * arg1,int mode,spcs_s_info_t kstatus,int * rvp)1467836SJohn.Forte@Sun.COM _rdc_sync_event_wait(void *arg0, void *arg1, int mode, spcs_s_info_t kstatus,
1477836SJohn.Forte@Sun.COM     int *rvp)
1487836SJohn.Forte@Sun.COM {
1497836SJohn.Forte@Sun.COM 	int rc = 0;
1507836SJohn.Forte@Sun.COM 	static char master[NSC_MAXPATH];
1517836SJohn.Forte@Sun.COM 
1527836SJohn.Forte@Sun.COM 	master[0] = '\0';
1537836SJohn.Forte@Sun.COM 	*rvp = 0;
1547836SJohn.Forte@Sun.COM 	if (ddi_copyin(arg0, master, NSC_MAXPATH, mode))
1557836SJohn.Forte@Sun.COM 		return (EFAULT);
1567836SJohn.Forte@Sun.COM 
1577836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_sync_event.mutex);
1587836SJohn.Forte@Sun.COM 
1597836SJohn.Forte@Sun.COM 	if (rdc_sync_event.kernel_waiting &&
1607836SJohn.Forte@Sun.COM 	    (rdc_sync_event.lbolt - nsc_lbolt() < rdc_sync_event_timeout)) {
1617836SJohn.Forte@Sun.COM 		/* We haven't been away too long */
1627836SJohn.Forte@Sun.COM 		if (master[0])
1637836SJohn.Forte@Sun.COM 			rdc_sync_event.ack = 1;
1647836SJohn.Forte@Sun.COM 		else
1657836SJohn.Forte@Sun.COM 			rdc_sync_event.ack = 0;
1667836SJohn.Forte@Sun.COM 		rdc_sync_event.kernel_waiting = 0;
1677836SJohn.Forte@Sun.COM 		cv_signal(&rdc_sync_event.done_cv);
1687836SJohn.Forte@Sun.COM 	}
1697836SJohn.Forte@Sun.COM 
1707836SJohn.Forte@Sun.COM 	rdc_sync_event.daemon_waiting = 1;
1717836SJohn.Forte@Sun.COM 	if (cv_wait_sig(&rdc_sync_event.cv, &rdc_sync_event.mutex) == 0) {
1727836SJohn.Forte@Sun.COM 		rdc_sync_event.daemon_waiting = 0;
1737836SJohn.Forte@Sun.COM 		rc = EAGAIN;
1747836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, rc);
1757836SJohn.Forte@Sun.COM 	} else {
1767836SJohn.Forte@Sun.COM 		(void) ddi_copyout(rdc_sync_event.master, arg0, NSC_MAXPATH,
1777836SJohn.Forte@Sun.COM 		    mode);
1787836SJohn.Forte@Sun.COM 		(void) ddi_copyout(rdc_sync_event.group, arg1, NSC_MAXPATH,
1797836SJohn.Forte@Sun.COM 		    mode);
1807836SJohn.Forte@Sun.COM 		*rvp = rdc_sync_event.event;
1817836SJohn.Forte@Sun.COM 	}
1827836SJohn.Forte@Sun.COM 	rdc_sync_event.lbolt = nsc_lbolt();
1837836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_sync_event.mutex);
1847836SJohn.Forte@Sun.COM 
1857836SJohn.Forte@Sun.COM 	return (rc);
1867836SJohn.Forte@Sun.COM }
1877836SJohn.Forte@Sun.COM 
1887836SJohn.Forte@Sun.COM 
1897836SJohn.Forte@Sun.COM static int
rdc_allow_sec_sync(rdc_u_info_t * urdc,int option)1907836SJohn.Forte@Sun.COM rdc_allow_sec_sync(rdc_u_info_t *urdc, int option)
1917836SJohn.Forte@Sun.COM {
1927836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
1937836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
1947836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
1957836SJohn.Forte@Sun.COM 
1967836SJohn.Forte@Sun.COM 	if (!IS_MULTI(krdc))
1977836SJohn.Forte@Sun.COM 		return (0);
1987836SJohn.Forte@Sun.COM 
1997836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
2007836SJohn.Forte@Sun.COM 
2017836SJohn.Forte@Sun.COM 	krdc = krdc->multi_next;
2027836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[krdc->index];
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc)) {
2057836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
2067836SJohn.Forte@Sun.COM 		return (0);
2077836SJohn.Forte@Sun.COM 	}
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 	if (option == CCIO_RSYNC) {
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM 		/* Reverse sync */
2127836SJohn.Forte@Sun.COM 
2137836SJohn.Forte@Sun.COM 		if (rdc_get_mflags(urdc) & RDC_RSYNC_NEEDED) {
2147836SJohn.Forte@Sun.COM 			/*
2157836SJohn.Forte@Sun.COM 			 * Reverse sync needed or in progress.
2167836SJohn.Forte@Sun.COM 			 */
2177836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
2187836SJohn.Forte@Sun.COM 			return (-1);
2197836SJohn.Forte@Sun.COM 		}
2207836SJohn.Forte@Sun.COM 	} else {
2217836SJohn.Forte@Sun.COM 		ASSERT(option == CCIO_SLAVE);
2227836SJohn.Forte@Sun.COM 
2237836SJohn.Forte@Sun.COM 		/* Forward sync */
2247836SJohn.Forte@Sun.COM 
2257836SJohn.Forte@Sun.COM 		if (rdc_get_mflags(urdc) & RDC_SLAVE) {
2267836SJohn.Forte@Sun.COM 			/*
2277836SJohn.Forte@Sun.COM 			 * Reverse syncing is bad, as that means that data
2287836SJohn.Forte@Sun.COM 			 * is already flowing to the target of the requested
2297836SJohn.Forte@Sun.COM 			 * sync operation.
2307836SJohn.Forte@Sun.COM 			 */
2317836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
2327836SJohn.Forte@Sun.COM 			return (-1);
2337836SJohn.Forte@Sun.COM 		}
2347836SJohn.Forte@Sun.COM 
2357836SJohn.Forte@Sun.COM 		/*
2367836SJohn.Forte@Sun.COM 		 * Clear "reverse sync needed" on all 1-many volumes.
2377836SJohn.Forte@Sun.COM 		 * The data on them will be updated from the primary of this
2387836SJohn.Forte@Sun.COM 		 * requested sync operation, so the aborted reverse sync need
2397836SJohn.Forte@Sun.COM 		 * not be completed.
2407836SJohn.Forte@Sun.COM 		 */
2417836SJohn.Forte@Sun.COM 
2427836SJohn.Forte@Sun.COM 		if ((rdc_get_mflags(urdc) & RDC_RSYNC_NEEDED) ||
2437836SJohn.Forte@Sun.COM 		    (rdc_get_vflags(urdc) & RDC_VOL_FAILED)) {
2447836SJohn.Forte@Sun.COM 			rdc_clr_mflags(urdc, RDC_RSYNC_NEEDED);
2457836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_VOL_FAILED);
2467836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
2477836SJohn.Forte@Sun.COM 		}
2487836SJohn.Forte@Sun.COM 		if (IS_MANY(krdc)) {
2497836SJohn.Forte@Sun.COM 			for (ktmp = krdc->many_next; ktmp != krdc;
2507836SJohn.Forte@Sun.COM 			    ktmp = ktmp->many_next) {
2517836SJohn.Forte@Sun.COM 				utmp = &rdc_u_info[ktmp->index];
2527836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(utmp))
2537836SJohn.Forte@Sun.COM 					continue;
2547836SJohn.Forte@Sun.COM 				if (rdc_get_mflags(utmp) & RDC_RSYNC_NEEDED) {
2557836SJohn.Forte@Sun.COM 					rdc_clr_mflags(utmp, RDC_RSYNC_NEEDED);
2567836SJohn.Forte@Sun.COM 					rdc_write_state(utmp);
2577836SJohn.Forte@Sun.COM 				}
2587836SJohn.Forte@Sun.COM 			}
2597836SJohn.Forte@Sun.COM 		}
2607836SJohn.Forte@Sun.COM 	}
2617836SJohn.Forte@Sun.COM 
2627836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
2637836SJohn.Forte@Sun.COM 
2647836SJohn.Forte@Sun.COM 	return (0);
2657836SJohn.Forte@Sun.COM }
2667836SJohn.Forte@Sun.COM 
2677836SJohn.Forte@Sun.COM 
2687836SJohn.Forte@Sun.COM /*
2697836SJohn.Forte@Sun.COM  * r_net_null
2707836SJohn.Forte@Sun.COM  * Proc 0 Null action
2717836SJohn.Forte@Sun.COM  */
2727836SJohn.Forte@Sun.COM static void
r_net_null(SVCXPRT * xprt)2737836SJohn.Forte@Sun.COM r_net_null(SVCXPRT *xprt)
2747836SJohn.Forte@Sun.COM {
2757836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_void, 0);
2767836SJohn.Forte@Sun.COM }
2777836SJohn.Forte@Sun.COM 
2787836SJohn.Forte@Sun.COM /*
2797836SJohn.Forte@Sun.COM  * r_net_read
2807836SJohn.Forte@Sun.COM  */
2817836SJohn.Forte@Sun.COM static void
r_net_read(SVCXPRT * xprt)2827836SJohn.Forte@Sun.COM r_net_read(SVCXPRT *xprt)
2837836SJohn.Forte@Sun.COM {
2847836SJohn.Forte@Sun.COM 	readres resp;
2857836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
2867836SJohn.Forte@Sun.COM 	struct rread diskio;
2877836SJohn.Forte@Sun.COM 	char *buffer = NULL;
2887836SJohn.Forte@Sun.COM 	uchar_t *sv_addr;
2897836SJohn.Forte@Sun.COM 	nsc_vec_t *vec;
2907836SJohn.Forte@Sun.COM 	int pos, st;
2917836SJohn.Forte@Sun.COM 	int nocache;
2927836SJohn.Forte@Sun.COM 	int sv_len;
2937836SJohn.Forte@Sun.COM 	nsc_vec_t *vector = NULL;
2947836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset = NULL;
2957836SJohn.Forte@Sun.COM 	int vecsz = 0;
2967836SJohn.Forte@Sun.COM 
2977836SJohn.Forte@Sun.COM 	st = SVC_GETARGS(xprt, xdr_rread, (char *)&diskio);
2987836SJohn.Forte@Sun.COM 	if (!st) {
2997836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_int, (char *)&st);
3007836SJohn.Forte@Sun.COM 		return;
3017836SJohn.Forte@Sun.COM 	}
3027836SJohn.Forte@Sun.COM 	nocache = (diskio.flag & RDC_RREAD_FAIL) ? 0 : NSC_NOCACHE;
3037836SJohn.Forte@Sun.COM 
3047836SJohn.Forte@Sun.COM 	if ((diskio.cd >= rdc_max_sets) || (diskio.cd < 0)) {
3057836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOENT;
3067836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
3077836SJohn.Forte@Sun.COM #ifdef DEBUG
3087836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
3099093SRamana.Srikanth@Sun.COM 		    "!r_net_read: EPROTO cd out or not enabled");
3107836SJohn.Forte@Sun.COM #endif
3117836SJohn.Forte@Sun.COM 		return;
3127836SJohn.Forte@Sun.COM 	}
3137836SJohn.Forte@Sun.COM 
3147836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[diskio.cd];
3157836SJohn.Forte@Sun.COM 
3167836SJohn.Forte@Sun.COM 	if (diskio.flag & RDC_RREAD_START) {
3177836SJohn.Forte@Sun.COM 		/* setup rpc */
3187836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc)) {
3197836SJohn.Forte@Sun.COM 			st = 0;
3207836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&st);
3217836SJohn.Forte@Sun.COM 			return;
3227836SJohn.Forte@Sun.COM 		}
3237836SJohn.Forte@Sun.COM 		st = rdc_readmaxfba(diskio.cd, diskio.pos, diskio.len,
3247836SJohn.Forte@Sun.COM 		    nocache);
3257836SJohn.Forte@Sun.COM 
3267836SJohn.Forte@Sun.COM 		if (!svc_sendreply(xprt, xdr_int, (char *)&st)) {
3277836SJohn.Forte@Sun.COM 			if (st != 0) {
3287836SJohn.Forte@Sun.COM 				rdc_net_dataset_t *dset;
3297836SJohn.Forte@Sun.COM 				if (dset = rdc_net_get_set(diskio.cd, st)) {
3307836SJohn.Forte@Sun.COM 					rdc_net_del_set(diskio.cd, dset);
3317836SJohn.Forte@Sun.COM 				} else {
3329093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE, "!r_net_read: get_set "
3337836SJohn.Forte@Sun.COM 					    "has failed in cleanup");
3347836SJohn.Forte@Sun.COM 				}
3357836SJohn.Forte@Sun.COM 			}
3367836SJohn.Forte@Sun.COM 		}
3377836SJohn.Forte@Sun.COM 		return;
3387836SJohn.Forte@Sun.COM 	}
3397836SJohn.Forte@Sun.COM 
3407836SJohn.Forte@Sun.COM 	/* data rpc */
3417836SJohn.Forte@Sun.COM 
3427836SJohn.Forte@Sun.COM #ifdef DEBUG
3437836SJohn.Forte@Sun.COM 	if ((diskio.flag & RDC_RREAD_DATA) == 0) {
3449093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!r_net_read: received non-DATA rpc! flag %x",
3459093SRamana.Srikanth@Sun.COM 		    diskio.flag);
3467836SJohn.Forte@Sun.COM 	}
3477836SJohn.Forte@Sun.COM #endif
3487836SJohn.Forte@Sun.COM 
3497836SJohn.Forte@Sun.COM 	dset = rdc_net_get_set(diskio.cd, diskio.idx);
3507836SJohn.Forte@Sun.COM 	if (dset) {
3517836SJohn.Forte@Sun.COM 		vector = rdc_dset2vec(dset);
3527836SJohn.Forte@Sun.COM 	}
3537836SJohn.Forte@Sun.COM 	if (vector == NULL) {
3547836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOMEM;
3557836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
3567836SJohn.Forte@Sun.COM 		goto cleanup;
3577836SJohn.Forte@Sun.COM 	}
3587836SJohn.Forte@Sun.COM 	vecsz = (dset->nitems + 1) * sizeof (nsc_vec_t);
3597836SJohn.Forte@Sun.COM 
3607836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc)) {
3617836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOENT;
3627836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
3637836SJohn.Forte@Sun.COM 		goto cleanup;
3647836SJohn.Forte@Sun.COM 	}
3657836SJohn.Forte@Sun.COM 	resp.rr_status = RDC_OK;
3667836SJohn.Forte@Sun.COM 
3677836SJohn.Forte@Sun.COM 	/* find place in vector */
3687836SJohn.Forte@Sun.COM 	vec = vector;
3697836SJohn.Forte@Sun.COM 	pos = diskio.pos - dset->pos;
3707836SJohn.Forte@Sun.COM 
3717836SJohn.Forte@Sun.COM 	for (; pos >= FBA_NUM(vec->sv_len); vec++)
3727836SJohn.Forte@Sun.COM 		pos -= FBA_NUM(vec->sv_len);
3737836SJohn.Forte@Sun.COM 
3747836SJohn.Forte@Sun.COM 	sv_addr = vec->sv_addr + FBA_SIZE(pos);
3757836SJohn.Forte@Sun.COM 	sv_len = vec->sv_len - FBA_SIZE(pos);
3767836SJohn.Forte@Sun.COM 
3777836SJohn.Forte@Sun.COM 	/*
3787836SJohn.Forte@Sun.COM 	 * IF the data is in a single sb_vec entry
3797836SJohn.Forte@Sun.COM 	 * THEN
3807836SJohn.Forte@Sun.COM 	 *	we can just point to that
3817836SJohn.Forte@Sun.COM 	 * ELSE
3827836SJohn.Forte@Sun.COM 	 *	we have to alloc a local buffer,
3837836SJohn.Forte@Sun.COM 	 *	copy the data in and the point to
3847836SJohn.Forte@Sun.COM 	 *	the local buffer.
3857836SJohn.Forte@Sun.COM 	 */
3867836SJohn.Forte@Sun.COM 
3877836SJohn.Forte@Sun.COM 	if (sv_len >= FBA_SIZE(diskio.len)) {
3887836SJohn.Forte@Sun.COM 		/* fast */
3897836SJohn.Forte@Sun.COM 		resp.rr_data = (char *)sv_addr;
3907836SJohn.Forte@Sun.COM 		resp.rr_bufsize = FBA_SIZE(diskio.len);
3917836SJohn.Forte@Sun.COM 	} else {
3927836SJohn.Forte@Sun.COM 		/* slow */
3937836SJohn.Forte@Sun.COM 		rdc_rread_slow++;	/* rough count */
3947836SJohn.Forte@Sun.COM 		resp.rr_bufsize = FBA_SIZE(diskio.len);
3957836SJohn.Forte@Sun.COM 		buffer = kmem_alloc(resp.rr_bufsize, KM_NOSLEEP);
3967836SJohn.Forte@Sun.COM 		if (!buffer) {
3977836SJohn.Forte@Sun.COM 			resp.rr_status = RDCERR_NOMEM;
3987836SJohn.Forte@Sun.COM 		} else {
3997836SJohn.Forte@Sun.COM 			resp.rr_data = buffer;
4007836SJohn.Forte@Sun.COM 			if (!rdc_dsetcopy(dset, vector, diskio.pos, diskio.len,
4017836SJohn.Forte@Sun.COM 			    resp.rr_data, resp.rr_bufsize, COPY_IN)) {
4027836SJohn.Forte@Sun.COM 				resp.rr_status = RDCERR_NOMEM; /* ??? */
4037836SJohn.Forte@Sun.COM 			}
4047836SJohn.Forte@Sun.COM 		}
4057836SJohn.Forte@Sun.COM 	}
4067836SJohn.Forte@Sun.COM 
4077836SJohn.Forte@Sun.COM 	st = svc_sendreply(xprt, xdr_readres, (char *)&resp); /* send data */
4087836SJohn.Forte@Sun.COM 
4097836SJohn.Forte@Sun.COM cleanup:
4107836SJohn.Forte@Sun.COM 
4117836SJohn.Forte@Sun.COM 	if (dset) {
4127836SJohn.Forte@Sun.COM 		if (!st ||
4137836SJohn.Forte@Sun.COM 		    (diskio.flag & RDC_RREAD_END) ||
4147836SJohn.Forte@Sun.COM 		    (resp.rr_status != RDC_OK)) {
4157836SJohn.Forte@Sun.COM 			/*
4167836SJohn.Forte@Sun.COM 			 * RPC reply failed, OR
4177836SJohn.Forte@Sun.COM 			 * Last RPC for this IO operation, OR
4187836SJohn.Forte@Sun.COM 			 * We are failing this IO operation.
4197836SJohn.Forte@Sun.COM 			 *
4207836SJohn.Forte@Sun.COM 			 * Do cleanup.
4217836SJohn.Forte@Sun.COM 			 */
4227836SJohn.Forte@Sun.COM 			rdc_net_del_set(diskio.cd, dset);
4237836SJohn.Forte@Sun.COM 		} else {
4247836SJohn.Forte@Sun.COM 			rdc_net_put_set(diskio.cd, dset);
4257836SJohn.Forte@Sun.COM 		}
4267836SJohn.Forte@Sun.COM 	}
4277836SJohn.Forte@Sun.COM 
4287836SJohn.Forte@Sun.COM 	if (buffer)
4297836SJohn.Forte@Sun.COM 		kmem_free(buffer, resp.rr_bufsize);
4307836SJohn.Forte@Sun.COM 	if (vector) {
4317836SJohn.Forte@Sun.COM 		kmem_free(vector, vecsz);
4327836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-vecsz);
4337836SJohn.Forte@Sun.COM 	}
4347836SJohn.Forte@Sun.COM }
4357836SJohn.Forte@Sun.COM 
4367836SJohn.Forte@Sun.COM /*
4377836SJohn.Forte@Sun.COM  * r_net_read (v6)
4387836SJohn.Forte@Sun.COM  */
4397836SJohn.Forte@Sun.COM static void
r_net_read6(SVCXPRT * xprt)4407836SJohn.Forte@Sun.COM r_net_read6(SVCXPRT *xprt)
4417836SJohn.Forte@Sun.COM {
4427836SJohn.Forte@Sun.COM 	readres resp;
4437836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
4447836SJohn.Forte@Sun.COM 	struct rread6 diskio;
4457836SJohn.Forte@Sun.COM 	char *buffer = NULL;
4467836SJohn.Forte@Sun.COM 	uchar_t *sv_addr;
4477836SJohn.Forte@Sun.COM 	nsc_vec_t *vec;
4487836SJohn.Forte@Sun.COM 	int pos, st;
4497836SJohn.Forte@Sun.COM 	int nocache;
4507836SJohn.Forte@Sun.COM 	int sv_len;
4517836SJohn.Forte@Sun.COM 	nsc_vec_t *vector = NULL;
4527836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset = NULL;
4537836SJohn.Forte@Sun.COM 	int vecsz = 0;
4547836SJohn.Forte@Sun.COM 
4557836SJohn.Forte@Sun.COM 	st = SVC_GETARGS(xprt, xdr_rread6, (char *)&diskio);
4567836SJohn.Forte@Sun.COM 	if (!st) {
4577836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_int, (char *)&st);
4587836SJohn.Forte@Sun.COM 		return;
4597836SJohn.Forte@Sun.COM 	}
4607836SJohn.Forte@Sun.COM 	nocache = (diskio.flag & RDC_RREAD_FAIL) ? 0 : NSC_NOCACHE;
4617836SJohn.Forte@Sun.COM 
4627836SJohn.Forte@Sun.COM 	if ((diskio.cd >= rdc_max_sets) || (diskio.cd < 0)) {
4637836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOENT;
4647836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
4657836SJohn.Forte@Sun.COM #ifdef DEBUG
4669093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_read6: EPROTO cd out or not enabled");
4677836SJohn.Forte@Sun.COM #endif
4687836SJohn.Forte@Sun.COM 		return;
4697836SJohn.Forte@Sun.COM 	}
4707836SJohn.Forte@Sun.COM 
4717836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[diskio.cd];
4727836SJohn.Forte@Sun.COM 
4737836SJohn.Forte@Sun.COM 	if (diskio.flag & RDC_RREAD_START) {
4747836SJohn.Forte@Sun.COM 		/* setup rpc */
4757836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc)) {
4767836SJohn.Forte@Sun.COM 			st = 0;
4777836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&st);
4787836SJohn.Forte@Sun.COM 			return;
4797836SJohn.Forte@Sun.COM 		}
4807836SJohn.Forte@Sun.COM 		st = rdc_readmaxfba(diskio.cd, diskio.pos, diskio.len,
4817836SJohn.Forte@Sun.COM 		    nocache);
4827836SJohn.Forte@Sun.COM 
4837836SJohn.Forte@Sun.COM 		if (!svc_sendreply(xprt, xdr_int, (char *)&st)) {
4847836SJohn.Forte@Sun.COM 			if (st != 0) {
4857836SJohn.Forte@Sun.COM 				rdc_net_dataset_t *dset;
4867836SJohn.Forte@Sun.COM 				if (dset = rdc_net_get_set(diskio.cd, st)) {
4877836SJohn.Forte@Sun.COM 					rdc_net_del_set(diskio.cd, dset);
4887836SJohn.Forte@Sun.COM 				} else {
4899093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE, "!read6: get_set "
4907836SJohn.Forte@Sun.COM 					    "has failed in cleanup");
4917836SJohn.Forte@Sun.COM 				}
4927836SJohn.Forte@Sun.COM 			}
4937836SJohn.Forte@Sun.COM 		}
4947836SJohn.Forte@Sun.COM 		return;
4957836SJohn.Forte@Sun.COM 	}
4967836SJohn.Forte@Sun.COM 
4977836SJohn.Forte@Sun.COM 	/* data rpc */
4987836SJohn.Forte@Sun.COM 
4997836SJohn.Forte@Sun.COM #ifdef DEBUG
5007836SJohn.Forte@Sun.COM 	if ((diskio.flag & RDC_RREAD_DATA) == 0) {
5019093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!read6: received non-DATA rpc! flag %x",
5029093SRamana.Srikanth@Sun.COM 		    diskio.flag);
5037836SJohn.Forte@Sun.COM 	}
5047836SJohn.Forte@Sun.COM #endif
5057836SJohn.Forte@Sun.COM 
5067836SJohn.Forte@Sun.COM 	dset = rdc_net_get_set(diskio.cd, diskio.idx);
5077836SJohn.Forte@Sun.COM 	if (dset) {
5087836SJohn.Forte@Sun.COM 		vector = rdc_dset2vec(dset);
5097836SJohn.Forte@Sun.COM 	}
5107836SJohn.Forte@Sun.COM 	if (vector == NULL) {
5117836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOMEM;
5127836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
5137836SJohn.Forte@Sun.COM 		goto cleanup;
5147836SJohn.Forte@Sun.COM 	}
5157836SJohn.Forte@Sun.COM 	vecsz = (dset->nitems + 1) * sizeof (nsc_vec_t);
5167836SJohn.Forte@Sun.COM 
5177836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc)) {
5187836SJohn.Forte@Sun.COM 		resp.rr_status = RDCERR_NOENT;
5197836SJohn.Forte@Sun.COM 		(void) svc_sendreply(xprt, xdr_readres, (char *)&resp);
5207836SJohn.Forte@Sun.COM 		goto cleanup;
5217836SJohn.Forte@Sun.COM 	}
5227836SJohn.Forte@Sun.COM 	resp.rr_status = RDC_OK;
5237836SJohn.Forte@Sun.COM 
5247836SJohn.Forte@Sun.COM 	/* find place in vector */
5257836SJohn.Forte@Sun.COM 	vec = vector;
5267836SJohn.Forte@Sun.COM 	pos = diskio.pos - dset->pos;
5277836SJohn.Forte@Sun.COM 
5287836SJohn.Forte@Sun.COM 	for (; pos >= FBA_NUM(vec->sv_len); vec++)
5297836SJohn.Forte@Sun.COM 		pos -= FBA_NUM(vec->sv_len);
5307836SJohn.Forte@Sun.COM 
5317836SJohn.Forte@Sun.COM 	sv_addr = vec->sv_addr + FBA_SIZE(pos);
5327836SJohn.Forte@Sun.COM 	sv_len = vec->sv_len - FBA_SIZE(pos);
5337836SJohn.Forte@Sun.COM 
5347836SJohn.Forte@Sun.COM 	/*
5357836SJohn.Forte@Sun.COM 	 * IF the data is in a single sb_vec entry
5367836SJohn.Forte@Sun.COM 	 * THEN
5377836SJohn.Forte@Sun.COM 	 *	we can just point to that
5387836SJohn.Forte@Sun.COM 	 * ELSE
5397836SJohn.Forte@Sun.COM 	 *	we have to alloc a local buffer,
5407836SJohn.Forte@Sun.COM 	 *	copy the data in and the point to
5417836SJohn.Forte@Sun.COM 	 *	the local buffer.
5427836SJohn.Forte@Sun.COM 	 */
5437836SJohn.Forte@Sun.COM 
5447836SJohn.Forte@Sun.COM 	if (sv_len >= FBA_SIZE(diskio.len)) {
5457836SJohn.Forte@Sun.COM 		/* fast */
5467836SJohn.Forte@Sun.COM 		resp.rr_data = (char *)sv_addr;
5477836SJohn.Forte@Sun.COM 		resp.rr_bufsize = FBA_SIZE(diskio.len);
5487836SJohn.Forte@Sun.COM 	} else {
5497836SJohn.Forte@Sun.COM 		/* slow */
5507836SJohn.Forte@Sun.COM 		rdc_rread_slow++;	/* rough count */
5517836SJohn.Forte@Sun.COM 		resp.rr_bufsize = FBA_SIZE(diskio.len);
5527836SJohn.Forte@Sun.COM 		buffer = kmem_alloc(resp.rr_bufsize, KM_NOSLEEP);
5537836SJohn.Forte@Sun.COM 		if (!buffer) {
5547836SJohn.Forte@Sun.COM 			resp.rr_status = RDCERR_NOMEM;
5557836SJohn.Forte@Sun.COM 		} else {
5567836SJohn.Forte@Sun.COM 			resp.rr_data = buffer;
5577836SJohn.Forte@Sun.COM 			if (!rdc_dsetcopy(dset, vector, diskio.pos, diskio.len,
5587836SJohn.Forte@Sun.COM 			    resp.rr_data, resp.rr_bufsize, COPY_IN)) {
5597836SJohn.Forte@Sun.COM 				resp.rr_status = RDCERR_NOMEM; /* ??? */
5607836SJohn.Forte@Sun.COM 			}
5617836SJohn.Forte@Sun.COM 		}
5627836SJohn.Forte@Sun.COM 	}
5637836SJohn.Forte@Sun.COM 
5647836SJohn.Forte@Sun.COM 	st = svc_sendreply(xprt, xdr_readres, (char *)&resp); /* send data */
5657836SJohn.Forte@Sun.COM 
5667836SJohn.Forte@Sun.COM cleanup:
5677836SJohn.Forte@Sun.COM 
5687836SJohn.Forte@Sun.COM 	if (dset) {
5697836SJohn.Forte@Sun.COM 		if (!st ||
5707836SJohn.Forte@Sun.COM 		    (diskio.flag & RDC_RREAD_END) ||
5717836SJohn.Forte@Sun.COM 		    (resp.rr_status != RDC_OK)) {
5727836SJohn.Forte@Sun.COM 			/*
5737836SJohn.Forte@Sun.COM 			 * RPC reply failed, OR
5747836SJohn.Forte@Sun.COM 			 * Last RPC for this IO operation, OR
5757836SJohn.Forte@Sun.COM 			 * We are failing this IO operation.
5767836SJohn.Forte@Sun.COM 			 *
5777836SJohn.Forte@Sun.COM 			 * Do cleanup.
5787836SJohn.Forte@Sun.COM 			 */
5797836SJohn.Forte@Sun.COM 			rdc_net_del_set(diskio.cd, dset);
5807836SJohn.Forte@Sun.COM 		} else {
5817836SJohn.Forte@Sun.COM 			rdc_net_put_set(diskio.cd, dset);
5827836SJohn.Forte@Sun.COM 		}
5837836SJohn.Forte@Sun.COM 	}
5847836SJohn.Forte@Sun.COM 
5857836SJohn.Forte@Sun.COM 	if (buffer)
5867836SJohn.Forte@Sun.COM 		kmem_free(buffer, resp.rr_bufsize);
5877836SJohn.Forte@Sun.COM 	if (vector) {
5887836SJohn.Forte@Sun.COM 		kmem_free(vector, vecsz);
5897836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-vecsz);
5907836SJohn.Forte@Sun.COM 	}
5917836SJohn.Forte@Sun.COM }
5927836SJohn.Forte@Sun.COM 
5937836SJohn.Forte@Sun.COM /*
5947836SJohn.Forte@Sun.COM  * r_net_write (Version 5)
5957836SJohn.Forte@Sun.COM  * 0 reply indicates error
5967836SJohn.Forte@Sun.COM  * >0 reply indicates a net handle index
5977836SJohn.Forte@Sun.COM  * <0 reply indicates errno
5987836SJohn.Forte@Sun.COM  * ret net handle index
5997836SJohn.Forte@Sun.COM  * ret2 general error
6007836SJohn.Forte@Sun.COM  * ret3 multi-hop errors (never returned)
6017836SJohn.Forte@Sun.COM  */
6027836SJohn.Forte@Sun.COM static void
r_net_write5(SVCXPRT * xprt)6037836SJohn.Forte@Sun.COM r_net_write5(SVCXPRT *xprt)
6047836SJohn.Forte@Sun.COM {
6057836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
6067836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
6077836SJohn.Forte@Sun.COM 	struct net_data5 diskio;
6087836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
6097836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *ditem;
6107836SJohn.Forte@Sun.COM 	int nocache;
6117836SJohn.Forte@Sun.COM 	int ret = 0;
6127836SJohn.Forte@Sun.COM 	int ret2 = 0;
6137836SJohn.Forte@Sun.COM 	int st;
6147836SJohn.Forte@Sun.COM 
6157836SJohn.Forte@Sun.COM 	krdc = NULL;
6167836SJohn.Forte@Sun.COM 	diskio.data.data_val = kmem_alloc(RDC_MAXDATA, KM_NOSLEEP);
6177836SJohn.Forte@Sun.COM 
6187836SJohn.Forte@Sun.COM 	if (!diskio.data.data_val) {
6197836SJohn.Forte@Sun.COM 		ret2 = ENOMEM;
6207836SJohn.Forte@Sun.COM 		goto out;
6217836SJohn.Forte@Sun.COM 	}
6227836SJohn.Forte@Sun.COM 	RDC_DSMEMUSE(RDC_MAXDATA);
6237836SJohn.Forte@Sun.COM 	st = SVC_GETARGS(xprt, xdr_net_data5, (char *)&diskio);
6247836SJohn.Forte@Sun.COM 	if (!st) {
6257836SJohn.Forte@Sun.COM 		ret2 = ENOMEM;
6267836SJohn.Forte@Sun.COM #ifdef DEBUG
6279093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_write5:SVC_GETARGS failed: st %d", st);
6287836SJohn.Forte@Sun.COM #endif
6297836SJohn.Forte@Sun.COM 		goto out;
6307836SJohn.Forte@Sun.COM 	}
6317836SJohn.Forte@Sun.COM 	if ((diskio.cd >= rdc_max_sets) || (diskio.cd < 0)) {
6327836SJohn.Forte@Sun.COM 		ret2 = EPROTO;
6337836SJohn.Forte@Sun.COM #ifdef DEBUG
6349093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_write6: EPROTO cd out or not enabled");
6357836SJohn.Forte@Sun.COM #endif
6367836SJohn.Forte@Sun.COM 		goto out;
6377836SJohn.Forte@Sun.COM 	}
6387836SJohn.Forte@Sun.COM 
6397836SJohn.Forte@Sun.COM 	nocache = (diskio.flag & RDC_RWRITE_FAIL) ? 0 : NSC_NOCACHE;
6407836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[diskio.cd];
6417836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[diskio.cd];
6427836SJohn.Forte@Sun.COM 
6437836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc) || IS_STATE(urdc, RDC_LOGGING)) {
6447836SJohn.Forte@Sun.COM 		ret2 = EPROTO;
6457836SJohn.Forte@Sun.COM #ifdef DEBUG
6469093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_write6: cd logging / not enabled (%x)",
6477836SJohn.Forte@Sun.COM 		    rdc_get_vflags(urdc));
6487836SJohn.Forte@Sun.COM #endif
6497836SJohn.Forte@Sun.COM 		krdc = NULL; /* so we don't try to unqueue kstat entry */
6507836SJohn.Forte@Sun.COM 		goto out;
6517836SJohn.Forte@Sun.COM 	}
6527836SJohn.Forte@Sun.COM 
6537836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
6547836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
6557836SJohn.Forte@Sun.COM 		kstat_runq_enter(KSTAT_IO_PTR(krdc->io_kstats));
6567836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
6577836SJohn.Forte@Sun.COM 	}
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM 
6607836SJohn.Forte@Sun.COM 	/* -1 index says allocate a buffer */
6617836SJohn.Forte@Sun.COM 	if (diskio.idx < 0) {
6627836SJohn.Forte@Sun.COM 		dset = rdc_net_add_set(diskio.cd);
6637836SJohn.Forte@Sun.COM 		if (dset == NULL) {
6647836SJohn.Forte@Sun.COM #ifdef DEBUG
6659093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!r_net_write5: "
6669093SRamana.Srikanth@Sun.COM 			    "failed to add dataset");
6677836SJohn.Forte@Sun.COM #endif
6687836SJohn.Forte@Sun.COM 			ret2 = EIO;
6697836SJohn.Forte@Sun.COM 			goto out;
6707836SJohn.Forte@Sun.COM 		} else {
6717836SJohn.Forte@Sun.COM 			ret = dset->id;
6727836SJohn.Forte@Sun.COM 			dset->pos = diskio.pos;
6737836SJohn.Forte@Sun.COM 			dset->fbalen = diskio.len;
6747836SJohn.Forte@Sun.COM 			diskio.idx = ret;
6757836SJohn.Forte@Sun.COM 		}
6767836SJohn.Forte@Sun.COM 		ditem = kmem_alloc(sizeof (rdc_net_dataitem_t), KM_NOSLEEP);
6777836SJohn.Forte@Sun.COM 		if (ditem == NULL) {
6787836SJohn.Forte@Sun.COM 			ret2 = ENOMEM;
6797836SJohn.Forte@Sun.COM 			goto out;
6807836SJohn.Forte@Sun.COM 		}
6817836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(sizeof (rdc_net_dataitem_t));
6827836SJohn.Forte@Sun.COM 		/*
6837836SJohn.Forte@Sun.COM 		 * If this is a single transfer, then we don't
6847836SJohn.Forte@Sun.COM 		 * need to allocate any memory for the data,
6857836SJohn.Forte@Sun.COM 		 * just point the ditem data pointer to the
6867836SJohn.Forte@Sun.COM 		 * existing buffer.
6877836SJohn.Forte@Sun.COM 		 */
6887836SJohn.Forte@Sun.COM 		ditem->next = NULL;
6897836SJohn.Forte@Sun.COM 		if (diskio.endoblk) {
6907836SJohn.Forte@Sun.COM 			ditem->dptr = diskio.data.data_val;
6917836SJohn.Forte@Sun.COM 			/*
6927836SJohn.Forte@Sun.COM 			 * So we don't free it twice.
6937836SJohn.Forte@Sun.COM 			 */
6947836SJohn.Forte@Sun.COM 			diskio.data.data_val = NULL;
6957836SJohn.Forte@Sun.COM 			ditem->len = diskio.data.data_len;
6967836SJohn.Forte@Sun.COM 			ditem->mlen = RDC_MAXDATA;
6977836SJohn.Forte@Sun.COM 		} else {
6987836SJohn.Forte@Sun.COM 			/*
6997836SJohn.Forte@Sun.COM 			 * Allocate the memory for the complete
7007836SJohn.Forte@Sun.COM 			 * transfer.
7017836SJohn.Forte@Sun.COM 			 */
7027836SJohn.Forte@Sun.COM 			ditem->dptr = kmem_alloc(FBA_SIZE(diskio.len),
7037836SJohn.Forte@Sun.COM 			    KM_NOSLEEP);
7047836SJohn.Forte@Sun.COM 			if (ditem->dptr == NULL) {
7057836SJohn.Forte@Sun.COM 				ret2 = ENOMEM;
7067836SJohn.Forte@Sun.COM 				goto out;
7077836SJohn.Forte@Sun.COM 			}
7087836SJohn.Forte@Sun.COM 			RDC_DSMEMUSE(FBA_SIZE(diskio.len));
7097836SJohn.Forte@Sun.COM 			ditem->len = FBA_SIZE(diskio.len);
7107836SJohn.Forte@Sun.COM 			ditem->mlen = ditem->len;
7117836SJohn.Forte@Sun.COM 
7127836SJohn.Forte@Sun.COM 			/*
7137836SJohn.Forte@Sun.COM 			 * Copy the data to the new buffer.
7147836SJohn.Forte@Sun.COM 			 */
7157836SJohn.Forte@Sun.COM 			ASSERT(diskio.data.data_len == FBA_SIZE(diskio.nfba));
7167836SJohn.Forte@Sun.COM 			bcopy(diskio.data.data_val, ditem->dptr,
7177836SJohn.Forte@Sun.COM 			    diskio.data.data_len);
7187836SJohn.Forte@Sun.COM 			/*
7197836SJohn.Forte@Sun.COM 			 * free the old data buffer.
7207836SJohn.Forte@Sun.COM 			 */
7217836SJohn.Forte@Sun.COM 			kmem_free(diskio.data.data_val, RDC_MAXDATA);
7227836SJohn.Forte@Sun.COM 			RDC_DSMEMUSE(-RDC_MAXDATA);
7237836SJohn.Forte@Sun.COM 			diskio.data.data_val = NULL;
7247836SJohn.Forte@Sun.COM 		}
7257836SJohn.Forte@Sun.COM 		dset->head = ditem;
7267836SJohn.Forte@Sun.COM 		dset->tail = ditem;
7277836SJohn.Forte@Sun.COM 		dset->nitems++;
7287836SJohn.Forte@Sun.COM 	} else {
7297836SJohn.Forte@Sun.COM 		ret = diskio.idx;
7307836SJohn.Forte@Sun.COM 		dset = rdc_net_get_set(diskio.cd, diskio.idx);
7317836SJohn.Forte@Sun.COM 		if (dset == NULL) {
7327836SJohn.Forte@Sun.COM 			ret2 = EPROTO;
7337836SJohn.Forte@Sun.COM #ifdef DEBUG
7347836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
7359093SRamana.Srikanth@Sun.COM 			    "!r_net_write5: net_get_set failed cd %d idx %d",
7367836SJohn.Forte@Sun.COM 			    diskio.cd, diskio.idx);
7377836SJohn.Forte@Sun.COM #endif
7387836SJohn.Forte@Sun.COM 			goto out;
7397836SJohn.Forte@Sun.COM 		}
7407836SJohn.Forte@Sun.COM 		/*
7417836SJohn.Forte@Sun.COM 		 * We have to copy the data from the rpc buffer
7427836SJohn.Forte@Sun.COM 		 * to the data in ditem.
7437836SJohn.Forte@Sun.COM 		 */
7447836SJohn.Forte@Sun.COM 		ditem = dset->head;
7457836SJohn.Forte@Sun.COM 		bcopy(diskio.data.data_val, (char *)ditem->dptr +
7467836SJohn.Forte@Sun.COM 		    FBA_SIZE(diskio.sfba - diskio.pos), diskio.data.data_len);
7477836SJohn.Forte@Sun.COM 
7487836SJohn.Forte@Sun.COM 		kmem_free(diskio.data.data_val, RDC_MAXDATA);
7497836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-RDC_MAXDATA);
7507836SJohn.Forte@Sun.COM 		diskio.data.data_val = NULL;
7517836SJohn.Forte@Sun.COM 	}
7527836SJohn.Forte@Sun.COM 	ASSERT(dset);
7537836SJohn.Forte@Sun.COM 
7547836SJohn.Forte@Sun.COM 	if (diskio.endoblk) {
7557836SJohn.Forte@Sun.COM 		ret2 = rdc_writemaxfba(krdc, urdc, dset, diskio.seq, nocache);
7567836SJohn.Forte@Sun.COM 		rdc_net_del_set(diskio.cd, dset);
7577836SJohn.Forte@Sun.COM 		dset = NULL;
7587836SJohn.Forte@Sun.COM 	}
7597836SJohn.Forte@Sun.COM out:
7607836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(ret2)) {
7617836SJohn.Forte@Sun.COM 		if (ret2 > 0)
7627836SJohn.Forte@Sun.COM 			ret2 = -ret2;
7637836SJohn.Forte@Sun.COM 		DTRACE_PROBE1(rdc_svcwrite5_err_ret2, int, ret2);
7647836SJohn.Forte@Sun.COM 		st = svc_sendreply(xprt, xdr_int, (char *)&ret2);
7657836SJohn.Forte@Sun.COM 	} else
7667836SJohn.Forte@Sun.COM 		st = svc_sendreply(xprt, xdr_int, (char *)&ret);
7677836SJohn.Forte@Sun.COM 
7687836SJohn.Forte@Sun.COM 	if (krdc && krdc->io_kstats && ret2 != ENOMEM) {
7697836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
7707836SJohn.Forte@Sun.COM 		kstat_runq_exit(KSTAT_IO_PTR(krdc->io_kstats));
7717836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
7727836SJohn.Forte@Sun.COM 	}
7737836SJohn.Forte@Sun.COM 	/*
7747836SJohn.Forte@Sun.COM 	 * On Error we must cleanup.
7757836SJohn.Forte@Sun.COM 	 * If we have a handle, free it.
7767836SJohn.Forte@Sun.COM 	 * If we have a network handle, free it.
7777836SJohn.Forte@Sun.COM 	 */
7787836SJohn.Forte@Sun.COM 	if (!st || !RDC_SUCCESS(ret2)) {
7797836SJohn.Forte@Sun.COM #ifdef DEBUG
7809093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!r_net_write5 error case? st %x ret %d",
7819093SRamana.Srikanth@Sun.COM 		    st, ret2);
7827836SJohn.Forte@Sun.COM #endif
7837836SJohn.Forte@Sun.COM 		if (dset) {
7847836SJohn.Forte@Sun.COM 			rdc_net_del_set(diskio.cd, dset);
7857836SJohn.Forte@Sun.COM 		}
7867836SJohn.Forte@Sun.COM 
7877836SJohn.Forte@Sun.COM 	} else {
7887836SJohn.Forte@Sun.COM 		if (dset) {
7897836SJohn.Forte@Sun.COM 			rdc_net_put_set(diskio.cd, dset);
7907836SJohn.Forte@Sun.COM 		}
7917836SJohn.Forte@Sun.COM 	}
7927836SJohn.Forte@Sun.COM 	if (diskio.data.data_val) {
7937836SJohn.Forte@Sun.COM 		kmem_free(diskio.data.data_val, RDC_MAXDATA);
7947836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-RDC_MAXDATA);
7957836SJohn.Forte@Sun.COM 	}
7967836SJohn.Forte@Sun.COM }
7977836SJohn.Forte@Sun.COM 
7987836SJohn.Forte@Sun.COM /*
7997836SJohn.Forte@Sun.COM  * r_net_write (Version 6)
8007836SJohn.Forte@Sun.COM  * index 0 = error, or net handle index.
8017836SJohn.Forte@Sun.COM  * result = 0 , ok.
8027836SJohn.Forte@Sun.COM  * result = 1, pending write.
8037836SJohn.Forte@Sun.COM  * result < 0 error, and is the -errno.
8047836SJohn.Forte@Sun.COM  * ret net handle index.
8057836SJohn.Forte@Sun.COM  * ret2 general error.
8067836SJohn.Forte@Sun.COM  */
8077836SJohn.Forte@Sun.COM static void
r_net_write6(SVCXPRT * xprt)8087836SJohn.Forte@Sun.COM r_net_write6(SVCXPRT *xprt)
8097836SJohn.Forte@Sun.COM {
8107836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
8117836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
8127836SJohn.Forte@Sun.COM 	rdc_group_t *group;
8137836SJohn.Forte@Sun.COM 	struct net_data6 diskio;
8147836SJohn.Forte@Sun.COM 	struct netwriteres netret;
8157836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
8167836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *ditem;
8177836SJohn.Forte@Sun.COM 	int ret = 0;
8187836SJohn.Forte@Sun.COM 	int ret2 = 0;
8197836SJohn.Forte@Sun.COM 	int st;
8207836SJohn.Forte@Sun.COM 	int nocache;
8217836SJohn.Forte@Sun.COM 
8227836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_val = NULL;
8237836SJohn.Forte@Sun.COM 	netret.vecdata.vecdata_len = 0;
8247836SJohn.Forte@Sun.COM 	dset = NULL;
8257836SJohn.Forte@Sun.COM 	krdc = NULL;
8267836SJohn.Forte@Sun.COM 	diskio.data.data_val = kmem_alloc(RDC_MAXDATA, KM_NOSLEEP);
8277836SJohn.Forte@Sun.COM 
8287836SJohn.Forte@Sun.COM 	if (!diskio.data.data_val) {
8297836SJohn.Forte@Sun.COM 		ret2 = ENOMEM;
8307836SJohn.Forte@Sun.COM 		goto out;
8317836SJohn.Forte@Sun.COM 	}
8327836SJohn.Forte@Sun.COM 	RDC_DSMEMUSE(RDC_MAXDATA);
8337836SJohn.Forte@Sun.COM 	st = SVC_GETARGS(xprt, xdr_net_data6, (char *)&diskio);
8347836SJohn.Forte@Sun.COM 	if (!st) {
8357836SJohn.Forte@Sun.COM 		ret2 = ENOMEM;
8367836SJohn.Forte@Sun.COM #ifdef DEBUG
8377836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
8389093SRamana.Srikanth@Sun.COM 		    "!r_net_write6:SVC_GETARGS failed: st  %d", st);
8397836SJohn.Forte@Sun.COM #endif
8407836SJohn.Forte@Sun.COM 		goto out;
8417836SJohn.Forte@Sun.COM 	}
8427836SJohn.Forte@Sun.COM 
8437836SJohn.Forte@Sun.COM 	if ((diskio.cd >= rdc_max_sets) || (diskio.cd < 0)) {
8447836SJohn.Forte@Sun.COM 		ret2 = EPROTO;
8457836SJohn.Forte@Sun.COM #ifdef DEBUG
8469093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_write6: EPROTO cd out or not enabled");
8477836SJohn.Forte@Sun.COM #endif
8487836SJohn.Forte@Sun.COM 		goto out;
8497836SJohn.Forte@Sun.COM 	}
8507836SJohn.Forte@Sun.COM 
8517836SJohn.Forte@Sun.COM 	nocache = (diskio.flag & RDC_RWRITE_FAIL) ? 0 : NSC_NOCACHE;
8527836SJohn.Forte@Sun.COM 	netret.seq = diskio.seq;
8537836SJohn.Forte@Sun.COM 
8547836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[diskio.cd];
8557836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[diskio.cd];
8567836SJohn.Forte@Sun.COM 
8577836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc) || IS_STATE(urdc, RDC_LOGGING)) {
8587836SJohn.Forte@Sun.COM 		ret2 = EPROTO;
8597836SJohn.Forte@Sun.COM #ifdef DEBUG
8607836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
8619093SRamana.Srikanth@Sun.COM 		    "!r_net_write6: cd logging or not enabled (%x)",
8627836SJohn.Forte@Sun.COM 		    rdc_get_vflags(urdc));
8637836SJohn.Forte@Sun.COM #endif
8647836SJohn.Forte@Sun.COM 		krdc = NULL; /* so we don't try to unqueue kstat entry */
8657836SJohn.Forte@Sun.COM 		goto out;
8667836SJohn.Forte@Sun.COM 	}
8677836SJohn.Forte@Sun.COM 
8687836SJohn.Forte@Sun.COM 	group = krdc->group;
8697836SJohn.Forte@Sun.COM 	if (group == NULL) {
8707836SJohn.Forte@Sun.COM 		ret2 = EIO;
8717836SJohn.Forte@Sun.COM #ifdef DEBUG
8727836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
8739093SRamana.Srikanth@Sun.COM 		    "!r_net_write6: No group structure for set %s:%s",
8747836SJohn.Forte@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file);
8757836SJohn.Forte@Sun.COM #endif
8767836SJohn.Forte@Sun.COM 		krdc = NULL; /* so we don't try to unqueue kstat entry */
8777836SJohn.Forte@Sun.COM 		goto out;
8787836SJohn.Forte@Sun.COM 	}
8797836SJohn.Forte@Sun.COM 
8807836SJohn.Forte@Sun.COM #ifdef DEBUG
8817836SJohn.Forte@Sun.COM 	if (rdc_netwrite6) {
8827836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
8839093SRamana.Srikanth@Sun.COM 		    "!r_net_write6: idx %d seq %u current seq %u pos %llu "
8847836SJohn.Forte@Sun.COM 		    "len %d sfba %llu nfba %d endoblk %d",
8857836SJohn.Forte@Sun.COM 		    diskio.idx, diskio.seq, group->seq,
8867836SJohn.Forte@Sun.COM 		    (unsigned long long)diskio.pos, diskio.len,
8877836SJohn.Forte@Sun.COM 		    (unsigned long long)diskio.sfba, diskio.nfba,
8887836SJohn.Forte@Sun.COM 		    diskio.endoblk);
8897836SJohn.Forte@Sun.COM 	}
8907836SJohn.Forte@Sun.COM #endif
8917836SJohn.Forte@Sun.COM 
8927836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
8937836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
8947836SJohn.Forte@Sun.COM 		kstat_runq_enter(KSTAT_IO_PTR(krdc->io_kstats));
8957836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
8967836SJohn.Forte@Sun.COM 	}
8977836SJohn.Forte@Sun.COM 
8987836SJohn.Forte@Sun.COM 	/* -1 index says allocate a net dataset */
8997836SJohn.Forte@Sun.COM 	if (diskio.idx < 0) {
9007836SJohn.Forte@Sun.COM 		dset = rdc_net_add_set(diskio.cd);
9017836SJohn.Forte@Sun.COM 		if (dset == NULL) {
9027836SJohn.Forte@Sun.COM #ifdef DEBUG
9037836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
9049093SRamana.Srikanth@Sun.COM 			    "!r_net_write6: failed to add dataset");
9057836SJohn.Forte@Sun.COM #endif
9067836SJohn.Forte@Sun.COM 			ret2 = EIO;
9077836SJohn.Forte@Sun.COM 			goto out;
9087836SJohn.Forte@Sun.COM 		} else {
9097836SJohn.Forte@Sun.COM 			ret = dset->id;
9107836SJohn.Forte@Sun.COM 			dset->pos = (nsc_off_t)diskio.pos; /* 64bit! */
9117836SJohn.Forte@Sun.COM 			dset->fbalen = diskio.len;
9127836SJohn.Forte@Sun.COM 			diskio.idx = ret;
9137836SJohn.Forte@Sun.COM 		}
9147836SJohn.Forte@Sun.COM 		ditem = kmem_alloc(sizeof (rdc_net_dataitem_t), KM_NOSLEEP);
9157836SJohn.Forte@Sun.COM 		if (ditem == NULL) {
9167836SJohn.Forte@Sun.COM 			ret2 = ENOMEM;
9177836SJohn.Forte@Sun.COM 			goto out;
9187836SJohn.Forte@Sun.COM 		}
9197836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(sizeof (rdc_net_dataitem_t));
9207836SJohn.Forte@Sun.COM 		/*
9217836SJohn.Forte@Sun.COM 		 * If this is a single transfer, then we don't
9227836SJohn.Forte@Sun.COM 		 * need to allocate any memory for the data,
9237836SJohn.Forte@Sun.COM 		 * just point the ditem data pointer to the
9247836SJohn.Forte@Sun.COM 		 * existing buffer.
9257836SJohn.Forte@Sun.COM 		 */
9267836SJohn.Forte@Sun.COM 		ditem->next = NULL;
9277836SJohn.Forte@Sun.COM 		if (diskio.endoblk) {
9287836SJohn.Forte@Sun.COM 			ditem->dptr = diskio.data.data_val;
9297836SJohn.Forte@Sun.COM 			/*
9307836SJohn.Forte@Sun.COM 			 * So we don't free it twice.
9317836SJohn.Forte@Sun.COM 			 */
9327836SJohn.Forte@Sun.COM 			diskio.data.data_val = NULL;
9337836SJohn.Forte@Sun.COM 			ditem->len = diskio.data.data_len;
9347836SJohn.Forte@Sun.COM 			ditem->mlen = RDC_MAXDATA;
9357836SJohn.Forte@Sun.COM 		} else {
9367836SJohn.Forte@Sun.COM 			/*
9377836SJohn.Forte@Sun.COM 			 * Allocate the memory for the complete
9387836SJohn.Forte@Sun.COM 			 * transfer.
9397836SJohn.Forte@Sun.COM 			 */
9407836SJohn.Forte@Sun.COM 			ditem->dptr = kmem_alloc(FBA_SIZE(diskio.len),
9417836SJohn.Forte@Sun.COM 			    KM_NOSLEEP);
9427836SJohn.Forte@Sun.COM 			if (ditem->dptr == NULL) {
9437836SJohn.Forte@Sun.COM 				ret2 = ENOMEM;
9447836SJohn.Forte@Sun.COM 				goto out;
9457836SJohn.Forte@Sun.COM 			}
9467836SJohn.Forte@Sun.COM 			RDC_DSMEMUSE(FBA_SIZE(diskio.len));
9477836SJohn.Forte@Sun.COM 			ditem->len = FBA_SIZE(diskio.len);
9487836SJohn.Forte@Sun.COM 			ditem->mlen = ditem->len;
9497836SJohn.Forte@Sun.COM 
9507836SJohn.Forte@Sun.COM 			/*
9517836SJohn.Forte@Sun.COM 			 * Copy the data to the new buffer.
9527836SJohn.Forte@Sun.COM 			 */
9537836SJohn.Forte@Sun.COM 			ASSERT(diskio.data.data_len == FBA_SIZE(diskio.nfba));
9547836SJohn.Forte@Sun.COM 			bcopy(diskio.data.data_val, ditem->dptr,
9557836SJohn.Forte@Sun.COM 			    diskio.data.data_len);
9567836SJohn.Forte@Sun.COM 			/*
9577836SJohn.Forte@Sun.COM 			 * free the old data buffer.
9587836SJohn.Forte@Sun.COM 			 */
9597836SJohn.Forte@Sun.COM 			kmem_free(diskio.data.data_val, RDC_MAXDATA);
9607836SJohn.Forte@Sun.COM 			RDC_DSMEMUSE(-RDC_MAXDATA);
9617836SJohn.Forte@Sun.COM 			diskio.data.data_val = NULL;
9627836SJohn.Forte@Sun.COM 		}
9637836SJohn.Forte@Sun.COM 		dset->head = ditem;
9647836SJohn.Forte@Sun.COM 		dset->tail = ditem;
9657836SJohn.Forte@Sun.COM 		dset->nitems++;
9667836SJohn.Forte@Sun.COM 	} else {
9677836SJohn.Forte@Sun.COM 		ret = diskio.idx;
9687836SJohn.Forte@Sun.COM 		dset = rdc_net_get_set(diskio.cd, diskio.idx);
9697836SJohn.Forte@Sun.COM 		if (dset == NULL) {
9707836SJohn.Forte@Sun.COM 			ret2 = EPROTO;
9717836SJohn.Forte@Sun.COM #ifdef DEBUG
9727836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
9739093SRamana.Srikanth@Sun.COM 			    "!r_net_write6: net_get_set failed cd %d idx %d "
9747836SJohn.Forte@Sun.COM 			    "packet sequence %u expected seq %u",
9757836SJohn.Forte@Sun.COM 			    diskio.cd, diskio.idx, diskio.seq, group->seq);
9767836SJohn.Forte@Sun.COM #endif
9777836SJohn.Forte@Sun.COM 			goto out;
9787836SJohn.Forte@Sun.COM 		}
9797836SJohn.Forte@Sun.COM 		/*
9807836SJohn.Forte@Sun.COM 		 * We have to copy the data from the rpc buffer
9817836SJohn.Forte@Sun.COM 		 * to the data in ditem.
9827836SJohn.Forte@Sun.COM 		 */
9837836SJohn.Forte@Sun.COM 		ditem = dset->head;
9847836SJohn.Forte@Sun.COM 		bcopy(diskio.data.data_val, (char *)ditem->dptr +
9857836SJohn.Forte@Sun.COM 		    FBA_SIZE(diskio.sfba - diskio.pos), diskio.data.data_len);
9867836SJohn.Forte@Sun.COM 
9877836SJohn.Forte@Sun.COM 		kmem_free(diskio.data.data_val, RDC_MAXDATA);
9887836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-RDC_MAXDATA);
9897836SJohn.Forte@Sun.COM 		diskio.data.data_val = NULL;
9907836SJohn.Forte@Sun.COM 	}
9917836SJohn.Forte@Sun.COM 	ASSERT(dset);
9927836SJohn.Forte@Sun.COM 
9937836SJohn.Forte@Sun.COM 	if (diskio.endoblk) {
9947836SJohn.Forte@Sun.COM #ifdef DEBUG
9957836SJohn.Forte@Sun.COM 		if (diskio.seq == (RDC_NEWSEQ + 1)) {
9967836SJohn.Forte@Sun.COM 			rdc_stallzero(2);
9977836SJohn.Forte@Sun.COM 		}
9987836SJohn.Forte@Sun.COM #endif
9997836SJohn.Forte@Sun.COM 		if (diskio.seq == RDC_NEWSEQ) {
10007836SJohn.Forte@Sun.COM 			/*
10017836SJohn.Forte@Sun.COM 			 * magic marker, start of sequence.
10027836SJohn.Forte@Sun.COM 			 */
10037836SJohn.Forte@Sun.COM 			mutex_enter(&group->ra_queue.net_qlock);
10047836SJohn.Forte@Sun.COM 			/*
10057836SJohn.Forte@Sun.COM 			 * see if some threads are stuck.
10067836SJohn.Forte@Sun.COM 			 */
10077836SJohn.Forte@Sun.COM 			if (group->sleepq) {
10087836SJohn.Forte@Sun.COM 				rdc_sleepqdiscard(group);
10097836SJohn.Forte@Sun.COM 			}
10107836SJohn.Forte@Sun.COM 			group->seqack = RDC_NEWSEQ;
10117836SJohn.Forte@Sun.COM 			mutex_exit(&group->ra_queue.net_qlock);
10127836SJohn.Forte@Sun.COM 		}
10137836SJohn.Forte@Sun.COM 
10147836SJohn.Forte@Sun.COM 		if ((diskio.seq != RDC_NOSEQ) && (diskio.seq != RDC_NEWSEQ)) {
10157836SJohn.Forte@Sun.COM 			/*
10167836SJohn.Forte@Sun.COM 			 * see if we are allowed through here to
10177836SJohn.Forte@Sun.COM 			 * do the write, or if we have to q the
10187836SJohn.Forte@Sun.COM 			 * request and send back a pending reply.
10197836SJohn.Forte@Sun.COM 			 */
10207836SJohn.Forte@Sun.COM 			mutex_enter(&group->ra_queue.net_qlock);
10217836SJohn.Forte@Sun.COM 			if (diskio.seq != group->seq) {
10227836SJohn.Forte@Sun.COM 				rdc_sleepq_t	*sq;
10237836SJohn.Forte@Sun.COM 				int maxseq;
10247836SJohn.Forte@Sun.COM 
10257836SJohn.Forte@Sun.COM 				/*
10267836SJohn.Forte@Sun.COM 				 * Check that we have room.
10277836SJohn.Forte@Sun.COM 				 */
10287836SJohn.Forte@Sun.COM 				maxseq = group->seqack + RDC_MAXPENDQ + 1;
10297836SJohn.Forte@Sun.COM 				if (maxseq < group->seqack) {
10307836SJohn.Forte@Sun.COM 					/*
10317836SJohn.Forte@Sun.COM 					 * skip magic values.
10327836SJohn.Forte@Sun.COM 					 */
10337836SJohn.Forte@Sun.COM 					maxseq += RDC_NEWSEQ + 1;
10347836SJohn.Forte@Sun.COM 				}
10357836SJohn.Forte@Sun.COM 				if (!RDC_INFRONT(diskio.seq, maxseq)) {
10367836SJohn.Forte@Sun.COM #ifdef	DEBUG
10379093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!net_write6: Queue "
10387836SJohn.Forte@Sun.COM 					    "size %d exceeded seqack %u "
10397836SJohn.Forte@Sun.COM 					    "this seq %u maxseq %u seq %u",
10407836SJohn.Forte@Sun.COM 					    RDC_MAXPENDQ, group->seqack,
10417836SJohn.Forte@Sun.COM 					    diskio.seq, maxseq, group->seq);
10427836SJohn.Forte@Sun.COM #endif
104310715SThomas.Atkins@Sun.COM 				DTRACE_PROBE2(qsize_exceeded, int, diskio.seq,
104410715SThomas.Atkins@Sun.COM 				    int, maxseq);
10457836SJohn.Forte@Sun.COM 					if (!(rdc_get_vflags(urdc) &
10467836SJohn.Forte@Sun.COM 					    RDC_VOL_FAILED)) {
10477836SJohn.Forte@Sun.COM 						rdc_many_enter(krdc);
10487836SJohn.Forte@Sun.COM 						rdc_set_flags(urdc,
10497836SJohn.Forte@Sun.COM 						    RDC_VOL_FAILED);
10507836SJohn.Forte@Sun.COM 						rdc_many_exit(krdc);
10517836SJohn.Forte@Sun.COM 						rdc_write_state(urdc);
10527836SJohn.Forte@Sun.COM 					}
10537836SJohn.Forte@Sun.COM 					ret2 = EIO;
10547836SJohn.Forte@Sun.COM 					rdc_sleepqdiscard(group);
10557836SJohn.Forte@Sun.COM 					group->seq = RDC_NEWSEQ;
10567836SJohn.Forte@Sun.COM 					group->seqack = RDC_NEWSEQ;
10577836SJohn.Forte@Sun.COM 					mutex_exit(&group->ra_queue.net_qlock);
10587836SJohn.Forte@Sun.COM 					goto out;
10597836SJohn.Forte@Sun.COM 				}
10607836SJohn.Forte@Sun.COM 
10617836SJohn.Forte@Sun.COM 				sq = rdc_newsleepq();
10627836SJohn.Forte@Sun.COM 				sq->seq = diskio.seq;
10637836SJohn.Forte@Sun.COM 				sq->sindex = diskio.cd;
10647836SJohn.Forte@Sun.COM 				sq->pindex = diskio.local_cd;
10657836SJohn.Forte@Sun.COM 				sq->idx = diskio.idx;
10667836SJohn.Forte@Sun.COM 				sq->qpos = diskio.qpos;
10677836SJohn.Forte@Sun.COM 				sq->nocache = nocache;
10687836SJohn.Forte@Sun.COM 				if (rdc_sleepq(group, sq)) {
10697836SJohn.Forte@Sun.COM 					ret2 = EIO;
10707836SJohn.Forte@Sun.COM 					group->seq = RDC_NEWSEQ;
10717836SJohn.Forte@Sun.COM 					group->seqack = RDC_NEWSEQ;
10727836SJohn.Forte@Sun.COM 					rdc_sleepqdiscard(group);
10737836SJohn.Forte@Sun.COM 					mutex_exit(&group->ra_queue.net_qlock);
10747836SJohn.Forte@Sun.COM 					goto out;
10757836SJohn.Forte@Sun.COM 				}
10767836SJohn.Forte@Sun.COM 				rdc_net_put_set(diskio.cd, dset);
10777836SJohn.Forte@Sun.COM 				dset = NULL;
10787836SJohn.Forte@Sun.COM 				if (krdc->io_kstats) {
10797836SJohn.Forte@Sun.COM 					mutex_enter(krdc->io_kstats->ks_lock);
10807836SJohn.Forte@Sun.COM 					kstat_waitq_enter(KSTAT_IO_PTR(krdc->
10817836SJohn.Forte@Sun.COM 					    io_kstats));
10827836SJohn.Forte@Sun.COM 					mutex_exit(krdc->io_kstats->ks_lock);
10837836SJohn.Forte@Sun.COM 				}
10847836SJohn.Forte@Sun.COM 				mutex_exit(&group->ra_queue.net_qlock);
10857836SJohn.Forte@Sun.COM 				/*
10867836SJohn.Forte@Sun.COM 				 * pending state.
10877836SJohn.Forte@Sun.COM 				 */
10887836SJohn.Forte@Sun.COM 				netret.result = 1;
10897836SJohn.Forte@Sun.COM 				netret.index = diskio.idx;
10907836SJohn.Forte@Sun.COM 				st = svc_sendreply(xprt, xdr_netwriteres,
10917836SJohn.Forte@Sun.COM 				    (char *)&netret);
10927836SJohn.Forte@Sun.COM 				if (krdc->io_kstats && ret2 != ENOMEM) {
10937836SJohn.Forte@Sun.COM 					mutex_enter(krdc->io_kstats->ks_lock);
10947836SJohn.Forte@Sun.COM 					kstat_runq_exit(KSTAT_IO_PTR(
10957836SJohn.Forte@Sun.COM 					    krdc->io_kstats));
10967836SJohn.Forte@Sun.COM 					mutex_exit(krdc->io_kstats->ks_lock);
10977836SJohn.Forte@Sun.COM 				}
10987836SJohn.Forte@Sun.COM 				return;
10997836SJohn.Forte@Sun.COM 			}
11007836SJohn.Forte@Sun.COM 			mutex_exit(&group->ra_queue.net_qlock);
11017836SJohn.Forte@Sun.COM 		}
11027836SJohn.Forte@Sun.COM 
11037836SJohn.Forte@Sun.COM 		ret2 = rdc_writemaxfba(krdc, urdc, dset, diskio.seq, nocache);
11047836SJohn.Forte@Sun.COM 		rdc_net_del_set(diskio.cd, dset);
11057836SJohn.Forte@Sun.COM 		dset = NULL;
11067836SJohn.Forte@Sun.COM #ifdef	DEBUG
11077836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(ret2)) {
11089093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!r_net_write6: writemaxfba failed %d",
11097836SJohn.Forte@Sun.COM 			    ret2);
11107836SJohn.Forte@Sun.COM 		}
11117836SJohn.Forte@Sun.COM #endif
11127836SJohn.Forte@Sun.COM 		if (diskio.seq != RDC_NOSEQ) {
11137836SJohn.Forte@Sun.COM 			mutex_enter(&group->ra_queue.net_qlock);
11147836SJohn.Forte@Sun.COM 			group->seq = diskio.seq + 1;
11157836SJohn.Forte@Sun.COM 			if (group->seq < diskio.seq)
11167836SJohn.Forte@Sun.COM 				group->seq = RDC_NEWSEQ + 1;
11177836SJohn.Forte@Sun.COM 			if (group->sleepq &&
11187836SJohn.Forte@Sun.COM 			    (group->sleepq->seq == group->seq)) {
11197836SJohn.Forte@Sun.COM 				rdc_dopending(group, &netret);
11207836SJohn.Forte@Sun.COM 			}
11217836SJohn.Forte@Sun.COM 			group->seqack = group->seq;
11227836SJohn.Forte@Sun.COM 			mutex_exit(&group->ra_queue.net_qlock);
11237836SJohn.Forte@Sun.COM 		}
11247836SJohn.Forte@Sun.COM 	}
11257836SJohn.Forte@Sun.COM out:
11267836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(ret2)) {
11277836SJohn.Forte@Sun.COM 		DTRACE_PROBE1(rdc_svcwrite6_err_ret2, int, ret2);
11287836SJohn.Forte@Sun.COM 		netret.result = -ret2;
11297836SJohn.Forte@Sun.COM 	} else {
11307836SJohn.Forte@Sun.COM 		netret.result = 0;
11317836SJohn.Forte@Sun.COM 		netret.index = ret;
11327836SJohn.Forte@Sun.COM 	}
11337836SJohn.Forte@Sun.COM 	st = svc_sendreply(xprt, xdr_netwriteres, (char *)&netret);
11347836SJohn.Forte@Sun.COM 	if (netret.vecdata.vecdata_val) {
11357836SJohn.Forte@Sun.COM 		kmem_free(netret.vecdata.vecdata_val,
11367836SJohn.Forte@Sun.COM 		    netret.vecdata.vecdata_len * sizeof (net_pendvec_t));
11377836SJohn.Forte@Sun.COM 	}
11387836SJohn.Forte@Sun.COM 	if (krdc && krdc->io_kstats && ret2 != ENOMEM) {
11397836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
11407836SJohn.Forte@Sun.COM 		kstat_runq_exit(KSTAT_IO_PTR(krdc->io_kstats));
11417836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
11427836SJohn.Forte@Sun.COM 	}
11437836SJohn.Forte@Sun.COM 	/*
11447836SJohn.Forte@Sun.COM 	 * On Error we must cleanup.
11457836SJohn.Forte@Sun.COM 	 * If we have a handle, free it.
11467836SJohn.Forte@Sun.COM 	 * If we have a network handle, free it.
11477836SJohn.Forte@Sun.COM 	 * If we hold the main nsc buffer, free it.
11487836SJohn.Forte@Sun.COM 	 */
11497836SJohn.Forte@Sun.COM 	if (!st || !RDC_SUCCESS(ret2)) {
11507836SJohn.Forte@Sun.COM #ifdef DEBUG
11519093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!r_net_write6 error st %x ret %d seq %u",
11527836SJohn.Forte@Sun.COM 		    st, ret2, diskio.seq);
11537836SJohn.Forte@Sun.COM #endif
11547836SJohn.Forte@Sun.COM 		if (dset) {
11557836SJohn.Forte@Sun.COM 			rdc_net_del_set(diskio.cd, dset);
11567836SJohn.Forte@Sun.COM 		}
11577836SJohn.Forte@Sun.COM 	} else {
11587836SJohn.Forte@Sun.COM 		if (dset) {
11597836SJohn.Forte@Sun.COM 			rdc_net_put_set(diskio.cd, dset);
11607836SJohn.Forte@Sun.COM 		}
11617836SJohn.Forte@Sun.COM 	}
11627836SJohn.Forte@Sun.COM 	if (diskio.data.data_val) {
11637836SJohn.Forte@Sun.COM 		kmem_free(diskio.data.data_val, RDC_MAXDATA);
11647836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-RDC_MAXDATA);
11657836SJohn.Forte@Sun.COM 	}
11667836SJohn.Forte@Sun.COM }
11677836SJohn.Forte@Sun.COM 
11687836SJohn.Forte@Sun.COM /*
11697836SJohn.Forte@Sun.COM  * r_net_ping4
11707836SJohn.Forte@Sun.COM  *
11717836SJohn.Forte@Sun.COM  * received on the primary.
11727836SJohn.Forte@Sun.COM  */
11737836SJohn.Forte@Sun.COM static void
r_net_ping4(SVCXPRT * xprt,struct svc_req * req)11747836SJohn.Forte@Sun.COM r_net_ping4(SVCXPRT *xprt, struct svc_req *req)
11757836SJohn.Forte@Sun.COM {
11767836SJohn.Forte@Sun.COM 	struct rdc_ping6 ping;
11777836SJohn.Forte@Sun.COM 	int e, ret = 0;
11787836SJohn.Forte@Sun.COM 	rdc_if_t *ip;
11797836SJohn.Forte@Sun.COM 
11807836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_rdc_ping6, (char *)&ping);
11817836SJohn.Forte@Sun.COM 	if (e) {
11827836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_ping_lock);
11837836SJohn.Forte@Sun.COM 
11847836SJohn.Forte@Sun.COM 		/* update specified interface */
11857836SJohn.Forte@Sun.COM 
11867836SJohn.Forte@Sun.COM 		for (ip = rdc_if_top; ip; ip = ip->next) {
11877836SJohn.Forte@Sun.COM 			if ((bcmp(ping.p_ifaddr, ip->ifaddr.buf,
11889093SRamana.Srikanth@Sun.COM 			    RDC_MAXADDR) == 0) &&
11897836SJohn.Forte@Sun.COM 			    (bcmp(ping.s_ifaddr, ip->r_ifaddr.buf,
11909093SRamana.Srikanth@Sun.COM 			    RDC_MAXADDR) == 0)) {
11917836SJohn.Forte@Sun.COM 				ip->new_pulse++;
11927836SJohn.Forte@Sun.COM 				ip->deadness = 1;
11937836SJohn.Forte@Sun.COM 
11947836SJohn.Forte@Sun.COM 				/* Update the rpc protocol version to use */
11957836SJohn.Forte@Sun.COM 
11967836SJohn.Forte@Sun.COM 				ip->rpc_version = req->rq_vers;
11977836SJohn.Forte@Sun.COM 				break;
11987836SJohn.Forte@Sun.COM 			}
11997836SJohn.Forte@Sun.COM 		}
12007836SJohn.Forte@Sun.COM 
12017836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_ping_lock);
12027836SJohn.Forte@Sun.COM 	} else {
12037836SJohn.Forte@Sun.COM 		svcerr_decode(xprt);
12047836SJohn.Forte@Sun.COM #ifdef DEBUG
12059093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!SNDR: couldn't get ping4 arguments");
12067836SJohn.Forte@Sun.COM #endif
12077836SJohn.Forte@Sun.COM 	}
12087836SJohn.Forte@Sun.COM 
12097836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
12107836SJohn.Forte@Sun.COM }
12117836SJohn.Forte@Sun.COM 
12127836SJohn.Forte@Sun.COM /*
12137836SJohn.Forte@Sun.COM  * r_net_ping7
12147836SJohn.Forte@Sun.COM  *
12157836SJohn.Forte@Sun.COM  * received on the primary.
12167836SJohn.Forte@Sun.COM  */
12177836SJohn.Forte@Sun.COM static void
r_net_ping7(SVCXPRT * xprt,struct svc_req * req)12187836SJohn.Forte@Sun.COM r_net_ping7(SVCXPRT *xprt, struct svc_req *req)
12197836SJohn.Forte@Sun.COM {
12207836SJohn.Forte@Sun.COM 	struct rdc_ping ping;
12217836SJohn.Forte@Sun.COM 	int e, ret = 0;
12227836SJohn.Forte@Sun.COM 	rdc_if_t *ip;
12237836SJohn.Forte@Sun.COM 	unsigned short *sp;
12247836SJohn.Forte@Sun.COM 
12257836SJohn.Forte@Sun.COM 	bzero(&ping, sizeof (struct rdc_ping));
12267836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_rdc_ping, (char *)&ping);
12277836SJohn.Forte@Sun.COM 	if (e) {
12287836SJohn.Forte@Sun.COM 		sp = (unsigned short *)ping.p_ifaddr.buf;
12297836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
12307836SJohn.Forte@Sun.COM 		sp = (unsigned short *)ping.s_ifaddr.buf;
12317836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
12327836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_ping_lock);
12337836SJohn.Forte@Sun.COM 
12347836SJohn.Forte@Sun.COM 		/* update specified interface */
12357836SJohn.Forte@Sun.COM 
12367836SJohn.Forte@Sun.COM 		for (ip = rdc_if_top; ip; ip = ip->next) {
12377836SJohn.Forte@Sun.COM 			if ((bcmp(ping.p_ifaddr.buf, ip->ifaddr.buf,
12389093SRamana.Srikanth@Sun.COM 			    ping.p_ifaddr.len) == 0) &&
12397836SJohn.Forte@Sun.COM 			    (bcmp(ping.s_ifaddr.buf, ip->r_ifaddr.buf,
12409093SRamana.Srikanth@Sun.COM 			    ping.s_ifaddr.len) == 0)) {
12417836SJohn.Forte@Sun.COM 				ip->new_pulse++;
12427836SJohn.Forte@Sun.COM 				ip->deadness = 1;
12437836SJohn.Forte@Sun.COM 
12447836SJohn.Forte@Sun.COM 				/* Update the rpc protocol version to use */
12457836SJohn.Forte@Sun.COM 
12467836SJohn.Forte@Sun.COM 				ip->rpc_version = req->rq_vers;
12477836SJohn.Forte@Sun.COM 				break;
12487836SJohn.Forte@Sun.COM 			}
12497836SJohn.Forte@Sun.COM 		}
12507836SJohn.Forte@Sun.COM 
12517836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_ping_lock);
12527836SJohn.Forte@Sun.COM 	} else {
12537836SJohn.Forte@Sun.COM 		svcerr_decode(xprt);
12547836SJohn.Forte@Sun.COM #ifdef DEBUG
12559093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!SNDR: couldn't get ping7 arguments");
12567836SJohn.Forte@Sun.COM #endif
12577836SJohn.Forte@Sun.COM 	}
12587836SJohn.Forte@Sun.COM 
12597836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
12607836SJohn.Forte@Sun.COM }
12617836SJohn.Forte@Sun.COM 
12627836SJohn.Forte@Sun.COM 
12637836SJohn.Forte@Sun.COM /*
12647836SJohn.Forte@Sun.COM  * r_net_bmap (v5)
12657836SJohn.Forte@Sun.COM  * WARNING acts as both client and server
12667836SJohn.Forte@Sun.COM  */
12677836SJohn.Forte@Sun.COM static void
r_net_bmap(SVCXPRT * xprt)12687836SJohn.Forte@Sun.COM r_net_bmap(SVCXPRT *xprt)
12697836SJohn.Forte@Sun.COM {
12707836SJohn.Forte@Sun.COM 	int e, ret = EINVAL;
12717836SJohn.Forte@Sun.COM 	struct bmap b;
12727836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
12737836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
12747836SJohn.Forte@Sun.COM 	struct bmap6 b6;
12757836SJohn.Forte@Sun.COM 
12767836SJohn.Forte@Sun.COM 
12777836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_bmap, (char *)&b);
12787836SJohn.Forte@Sun.COM 	if (e == TRUE) {
12797836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[b.cd];
12807836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[b.cd];
12817836SJohn.Forte@Sun.COM 		if (b.cd >= 0 && b.cd < rdc_max_sets && IS_ENABLED(urdc) &&
12827836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_DISABLEPEND) == 0)) {
12837836SJohn.Forte@Sun.COM 			krdc->rpc_version = RDC_VERSION5;
12847836SJohn.Forte@Sun.COM 			b6.cd = b.cd;
12857836SJohn.Forte@Sun.COM 			b6.dual = b.dual;
12867836SJohn.Forte@Sun.COM 			b6.size = b.size;
12877836SJohn.Forte@Sun.COM 			ret = RDC_SEND_BITMAP(&b6);
12887836SJohn.Forte@Sun.COM 		}
12897836SJohn.Forte@Sun.COM 	}
12907836SJohn.Forte@Sun.COM 
12917836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
12927836SJohn.Forte@Sun.COM }
12937836SJohn.Forte@Sun.COM 
12947836SJohn.Forte@Sun.COM /*
12957836SJohn.Forte@Sun.COM  * r_net_bmap (v6)
12967836SJohn.Forte@Sun.COM  * WARNING acts as both client and server
12977836SJohn.Forte@Sun.COM  */
12987836SJohn.Forte@Sun.COM static void
r_net_bmap6(SVCXPRT * xprt)12997836SJohn.Forte@Sun.COM r_net_bmap6(SVCXPRT *xprt)
13007836SJohn.Forte@Sun.COM {
13017836SJohn.Forte@Sun.COM 	int e, ret = EINVAL;
13027836SJohn.Forte@Sun.COM 	struct bmap6 b;
13037836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
13047836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
13057836SJohn.Forte@Sun.COM 
13067836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_bmap6, (char *)&b);
13077836SJohn.Forte@Sun.COM 	if (e == TRUE) {
13087836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[b.cd];
13097836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[b.cd];
13107836SJohn.Forte@Sun.COM 		if (b.cd >= 0 && b.cd < rdc_max_sets && IS_ENABLED(urdc) &&
13117836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_DISABLEPEND) == 0)) {
13127836SJohn.Forte@Sun.COM 			krdc->rpc_version = RDC_VERSION6;
13137836SJohn.Forte@Sun.COM 			ret = RDC_SEND_BITMAP(&b);
13147836SJohn.Forte@Sun.COM 		}
13157836SJohn.Forte@Sun.COM 	}
13167836SJohn.Forte@Sun.COM 	/*
13177836SJohn.Forte@Sun.COM 	 * If the bitmap send has succeeded, clear it.
13187836SJohn.Forte@Sun.COM 	 */
13197836SJohn.Forte@Sun.COM 	if (ret == 0) {
13207836SJohn.Forte@Sun.COM #ifdef DEBUG
13219093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!Bitmap clear in r_net_bmap6");
13227836SJohn.Forte@Sun.COM #endif
13237836SJohn.Forte@Sun.COM 		RDC_ZERO_BITMAP(krdc);
13247836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
13257836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_CLR_AFTERSYNC);
13267836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
13277836SJohn.Forte@Sun.COM 	}
13287836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
13297836SJohn.Forte@Sun.COM }
13307836SJohn.Forte@Sun.COM 
13317836SJohn.Forte@Sun.COM /*
13327836SJohn.Forte@Sun.COM  * r_net_bdata
13337836SJohn.Forte@Sun.COM  */
13347836SJohn.Forte@Sun.COM static void
r_net_bdata(SVCXPRT * xprt)13357836SJohn.Forte@Sun.COM r_net_bdata(SVCXPRT *xprt)
13367836SJohn.Forte@Sun.COM {
13377836SJohn.Forte@Sun.COM 	struct net_bdata bd;
13387836SJohn.Forte@Sun.COM 	struct net_bdata6 bd6;
13397836SJohn.Forte@Sun.COM 	int e, ret = -1;
13407836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
13417836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
13427836SJohn.Forte@Sun.COM 
13437836SJohn.Forte@Sun.COM 	/*
13447836SJohn.Forte@Sun.COM 	 * We have to convert it to the internal form here,
13457836SJohn.Forte@Sun.COM 	 * net_data6, when we know that we will have to convert
13467836SJohn.Forte@Sun.COM 	 * it back to the v5 variant for transmission.
13477836SJohn.Forte@Sun.COM 	 */
13487836SJohn.Forte@Sun.COM 
13497836SJohn.Forte@Sun.COM 	bd.data.data_val = kmem_alloc(BMAP_BLKSIZE, KM_NOSLEEP);
13507836SJohn.Forte@Sun.COM 	if (bd.data.data_val == NULL)
13517836SJohn.Forte@Sun.COM 		goto out;
13527836SJohn.Forte@Sun.COM 
13537836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_net_bdata, (char *)&bd);
13547836SJohn.Forte@Sun.COM 	if (e == TRUE) {
13557836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[bd.cd];
13567836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[bd.cd];
13577836SJohn.Forte@Sun.COM 		if (bd.cd >= 0 && bd.cd < rdc_max_sets && IS_ENABLED(urdc) &&
13587836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_DISABLEPEND) == 0)) {
13597836SJohn.Forte@Sun.COM 			bd6.cd = bd.cd;
13607836SJohn.Forte@Sun.COM 			bd6.offset = bd.offset;
13617836SJohn.Forte@Sun.COM 			bd6.size = bd.size;
13627836SJohn.Forte@Sun.COM 			bd6.data.data_len = bd.data.data_len;
13637836SJohn.Forte@Sun.COM 			bd6.data.data_val = bd.data.data_val;
13647836SJohn.Forte@Sun.COM 			ret = RDC_OR_BITMAP(&bd6);
13657836SJohn.Forte@Sun.COM 		}
13667836SJohn.Forte@Sun.COM 	}
13677836SJohn.Forte@Sun.COM 	kmem_free(bd.data.data_val, BMAP_BLKSIZE);
13687836SJohn.Forte@Sun.COM out:
13697836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
13707836SJohn.Forte@Sun.COM }
13717836SJohn.Forte@Sun.COM 
13727836SJohn.Forte@Sun.COM /*
13737836SJohn.Forte@Sun.COM  * r_net_bdata v6
13747836SJohn.Forte@Sun.COM  */
13757836SJohn.Forte@Sun.COM static void
r_net_bdata6(SVCXPRT * xprt)13767836SJohn.Forte@Sun.COM r_net_bdata6(SVCXPRT *xprt)
13777836SJohn.Forte@Sun.COM {
13787836SJohn.Forte@Sun.COM 	struct net_bdata6 bd;
13797836SJohn.Forte@Sun.COM 	int e, ret = -1;
13807836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
13817836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
13827836SJohn.Forte@Sun.COM 
13837836SJohn.Forte@Sun.COM 	/*
13847836SJohn.Forte@Sun.COM 	 * just allocate the bigger block, regardless of < V7
13857836SJohn.Forte@Sun.COM 	 * bd.size will dictate how much we lor into our bitmap
13867836SJohn.Forte@Sun.COM 	 * the other option would be write r_net_bdata7 that is identical
13877836SJohn.Forte@Sun.COM 	 * to this function, but a V7 alloc.
13887836SJohn.Forte@Sun.COM 	 */
13897836SJohn.Forte@Sun.COM 	bd.data.data_val = kmem_alloc(BMAP_BLKSIZEV7, KM_NOSLEEP);
13907836SJohn.Forte@Sun.COM 	if (bd.data.data_val == NULL)
13917836SJohn.Forte@Sun.COM 		goto out;
13927836SJohn.Forte@Sun.COM 
13937836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_net_bdata6, (char *)&bd);
13947836SJohn.Forte@Sun.COM 	if (e == TRUE) {
13957836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[bd.cd];
13967836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[bd.cd];
13977836SJohn.Forte@Sun.COM 		if (bd.cd >= 0 && bd.cd < rdc_max_sets && IS_ENABLED(urdc) &&
13987836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_DISABLEPEND) == 0))
13997836SJohn.Forte@Sun.COM 			ret = RDC_OR_BITMAP(&bd);
14007836SJohn.Forte@Sun.COM 	}
14017836SJohn.Forte@Sun.COM 	/*
14027836SJohn.Forte@Sun.COM 	 * Write the merged bitmap.
14037836SJohn.Forte@Sun.COM 	 */
14047836SJohn.Forte@Sun.COM 	if ((ret == 0) && bd.endoblk && (krdc->bitmap_write > 0)) {
14057836SJohn.Forte@Sun.COM #ifdef DEBUG
14069093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!r_net_bdata6: Written bitmap for %s:%s",
14077836SJohn.Forte@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file);
14087836SJohn.Forte@Sun.COM #endif
14097836SJohn.Forte@Sun.COM 		ret = rdc_write_bitmap(krdc);
14107836SJohn.Forte@Sun.COM 	}
14117836SJohn.Forte@Sun.COM 	kmem_free(bd.data.data_val, BMAP_BLKSIZEV7);
14127836SJohn.Forte@Sun.COM out:
14137836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
14147836SJohn.Forte@Sun.COM }
14157836SJohn.Forte@Sun.COM 
14167836SJohn.Forte@Sun.COM /*
14177836SJohn.Forte@Sun.COM  * r_net_getsize (v5)
14187836SJohn.Forte@Sun.COM  */
14197836SJohn.Forte@Sun.COM static void
r_net_getsize(SVCXPRT * xprt)14207836SJohn.Forte@Sun.COM r_net_getsize(SVCXPRT *xprt)
14217836SJohn.Forte@Sun.COM {
14227836SJohn.Forte@Sun.COM 	int e, ret = -1, index;
14237836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
14247836SJohn.Forte@Sun.COM 
14257836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_int, (char *)&index);
14267836SJohn.Forte@Sun.COM 	if (e) {
14277836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
14287836SJohn.Forte@Sun.COM 		if (IS_VALID_INDEX(index) && ((krdc->type_flag &
14297836SJohn.Forte@Sun.COM 		    RDC_DISABLEPEND) == 0))
14307836SJohn.Forte@Sun.COM 			ret = mirror_getsize(index);
14317836SJohn.Forte@Sun.COM 	}
14327836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
14337836SJohn.Forte@Sun.COM }
14347836SJohn.Forte@Sun.COM 
14357836SJohn.Forte@Sun.COM /*
14367836SJohn.Forte@Sun.COM  * r_net_getsize (v6)
14377836SJohn.Forte@Sun.COM  */
14387836SJohn.Forte@Sun.COM static void
r_net_getsize6(SVCXPRT * xprt)14397836SJohn.Forte@Sun.COM r_net_getsize6(SVCXPRT *xprt)
14407836SJohn.Forte@Sun.COM {
14417836SJohn.Forte@Sun.COM 	int e, index;
14427836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
14437836SJohn.Forte@Sun.COM 	uint64_t ret;
14447836SJohn.Forte@Sun.COM 
14457836SJohn.Forte@Sun.COM 	/*
14467836SJohn.Forte@Sun.COM 	 * small change in semantics here, as we can't return
14477836SJohn.Forte@Sun.COM 	 * -1 over the wire anymore.
14487836SJohn.Forte@Sun.COM 	 */
14497836SJohn.Forte@Sun.COM 	ret = 0;
14507836SJohn.Forte@Sun.COM 
14517836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_int, (char *)&index);
14527836SJohn.Forte@Sun.COM 	if (e) {
14537836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
14547836SJohn.Forte@Sun.COM 		if (IS_VALID_INDEX(index) && ((krdc->type_flag &
14557836SJohn.Forte@Sun.COM 		    RDC_DISABLEPEND) == 0))
14567836SJohn.Forte@Sun.COM 			ret = mirror_getsize(index);
14577836SJohn.Forte@Sun.COM 	}
14587836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_u_longlong_t, (char *)&ret);
14597836SJohn.Forte@Sun.COM }
14607836SJohn.Forte@Sun.COM 
14617836SJohn.Forte@Sun.COM 
14627836SJohn.Forte@Sun.COM /*
14637836SJohn.Forte@Sun.COM  * r_net_state4
14647836SJohn.Forte@Sun.COM  */
14657836SJohn.Forte@Sun.COM static void
r_net_state4(SVCXPRT * xprt)14667836SJohn.Forte@Sun.COM r_net_state4(SVCXPRT *xprt)
14677836SJohn.Forte@Sun.COM {
14687836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
14697836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
14707836SJohn.Forte@Sun.COM 	struct set_state4 state;
14717836SJohn.Forte@Sun.COM 	rdc_set_t rdc_set;
14727836SJohn.Forte@Sun.COM 	int e, index = -1;
14737836SJohn.Forte@Sun.COM 	int options;
14747836SJohn.Forte@Sun.COM 	int log = 0;
14757836SJohn.Forte@Sun.COM 	int done = 0;
14767836SJohn.Forte@Sun.COM 	int slave = 0;
14777836SJohn.Forte@Sun.COM 	int rev_sync = 0;
14787836SJohn.Forte@Sun.COM 
14797836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_set_state4, (char *)&state);
14807836SJohn.Forte@Sun.COM 	if (e) {
14817836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.primary.addr));
14827836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.secondary.addr));
14837836SJohn.Forte@Sun.COM 		bcopy(state.netaddr, rdc_set.primary.addr.buf,
14847836SJohn.Forte@Sun.COM 		    state.netaddrlen);
14857836SJohn.Forte@Sun.COM 		bcopy(state.rnetaddr, rdc_set.secondary.addr.buf,
14867836SJohn.Forte@Sun.COM 		    state.rnetaddrlen);
14877836SJohn.Forte@Sun.COM 		rdc_set.primary.addr.len = state.netaddrlen;
14887836SJohn.Forte@Sun.COM 		rdc_set.secondary.addr.len = state.rnetaddrlen;
14897836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.file, state.pfile,
14907836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
14917836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.secondary.file, state.sfile,
14927836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
14937836SJohn.Forte@Sun.COM 		options = state.flag;
14947836SJohn.Forte@Sun.COM 		index = rdc_lookup_byaddr(&rdc_set);
14957836SJohn.Forte@Sun.COM 
14967836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
14977836SJohn.Forte@Sun.COM 
14987836SJohn.Forte@Sun.COM 		if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
14997836SJohn.Forte@Sun.COM #ifdef DEBUG
15007836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
15019093SRamana.Srikanth@Sun.COM 			    "!r_net_state: no index or disable pending");
15027836SJohn.Forte@Sun.COM #endif
15037836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
15047836SJohn.Forte@Sun.COM 			return;
15057836SJohn.Forte@Sun.COM 		}
15067836SJohn.Forte@Sun.COM 
15077836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
15087836SJohn.Forte@Sun.COM 
15097836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc)) {
15107836SJohn.Forte@Sun.COM 			index = -1;
15117836SJohn.Forte@Sun.COM #ifdef DEBUG
15129093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!r_net_state: set not enabled ");
15137836SJohn.Forte@Sun.COM #endif
15147836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
15157836SJohn.Forte@Sun.COM 			return;
15167836SJohn.Forte@Sun.COM 		}
15177836SJohn.Forte@Sun.COM 
15187836SJohn.Forte@Sun.COM 		if (krdc->lsrv == NULL) {
15199093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!r_net_state: no valid svp\n");
15207836SJohn.Forte@Sun.COM 			index = -1;
15217836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
15227836SJohn.Forte@Sun.COM 			return;
15237836SJohn.Forte@Sun.COM 		}
15247836SJohn.Forte@Sun.COM 		if (!krdc || !krdc->group) {
15257836SJohn.Forte@Sun.COM #ifdef DEBUG
15267836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
15279093SRamana.Srikanth@Sun.COM 			    "!r_net_state: no valid krdc %p\n", (void*)krdc);
15287836SJohn.Forte@Sun.COM #endif
15297836SJohn.Forte@Sun.COM 			index = -1;
15307836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
15317836SJohn.Forte@Sun.COM 			return;
15327836SJohn.Forte@Sun.COM 		}
15337836SJohn.Forte@Sun.COM 
15347836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
15357836SJohn.Forte@Sun.COM 		if (krdc->type_flag & RDC_DISABLEPEND) {
15367836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
15377836SJohn.Forte@Sun.COM 			index = -1;
15387836SJohn.Forte@Sun.COM #ifdef DEBUG
15399093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!r_net_state: disable pending");
15407836SJohn.Forte@Sun.COM #endif
15417836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
15427836SJohn.Forte@Sun.COM 			return;
15437836SJohn.Forte@Sun.COM 		}
15447836SJohn.Forte@Sun.COM 		set_busy(krdc);
15457836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
15467836SJohn.Forte@Sun.COM 
15477836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
15487836SJohn.Forte@Sun.COM 
15497836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY)
15507836SJohn.Forte@Sun.COM 			krdc->intf = rdc_add_to_if(krdc->lsrv,
15517836SJohn.Forte@Sun.COM 			    &(urdc->primary.addr), &(urdc->secondary.addr), 1);
15527836SJohn.Forte@Sun.COM 		else
15537836SJohn.Forte@Sun.COM 			krdc->intf = rdc_add_to_if(krdc->lsrv,
15547836SJohn.Forte@Sun.COM 			    &(urdc->secondary.addr), &(urdc->primary.addr), 0);
15557836SJohn.Forte@Sun.COM 
15567836SJohn.Forte@Sun.COM 		if (options & CCIO_SLAVE) {
15577836SJohn.Forte@Sun.COM 			/*
15587836SJohn.Forte@Sun.COM 			 * mark that the bitmap needs clearing.
15597836SJohn.Forte@Sun.COM 			 */
15607836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
15617836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_CLR_AFTERSYNC);
15627836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
15637836SJohn.Forte@Sun.COM 
15647836SJohn.Forte@Sun.COM 			/* Starting forward sync */
15657836SJohn.Forte@Sun.COM 			if (urdc->volume_size == 0)
15667836SJohn.Forte@Sun.COM 				rdc_get_details(krdc);
15677836SJohn.Forte@Sun.COM 			if (urdc->volume_size == 0) {
15687836SJohn.Forte@Sun.COM 				index = -1;
15697836SJohn.Forte@Sun.COM 				goto out;
15707836SJohn.Forte@Sun.COM 			}
15717836SJohn.Forte@Sun.COM 			if (krdc->dcio_bitmap == NULL) {
15727836SJohn.Forte@Sun.COM 				if (rdc_resume_bitmap(krdc) < 0) {
15737836SJohn.Forte@Sun.COM 					index = -1;
15747836SJohn.Forte@Sun.COM 					goto out;
15757836SJohn.Forte@Sun.COM 				}
15767836SJohn.Forte@Sun.COM 			}
15777836SJohn.Forte@Sun.COM 			if (rdc_allow_sec_sync(urdc, CCIO_SLAVE) < 0) {
15787836SJohn.Forte@Sun.COM 				index = -1;
15797836SJohn.Forte@Sun.COM 				goto out;
15807836SJohn.Forte@Sun.COM 			}
15817836SJohn.Forte@Sun.COM 			rdc_dump_dsets(index);
15827836SJohn.Forte@Sun.COM 			slave = 1;
15837836SJohn.Forte@Sun.COM 		} else if (options & CCIO_RSYNC) {
15847836SJohn.Forte@Sun.COM 			/*
15857836SJohn.Forte@Sun.COM 			 * mark that the bitmap needs clearing.
15867836SJohn.Forte@Sun.COM 			 */
15877836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
15887836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_CLR_AFTERSYNC);
15897836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
15907836SJohn.Forte@Sun.COM 
15917836SJohn.Forte@Sun.COM 			/* Starting reverse sync */
15927836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & (RDC_SYNC_NEEDED |
15937836SJohn.Forte@Sun.COM 			    RDC_VOL_FAILED | RDC_BMP_FAILED)) {
15947836SJohn.Forte@Sun.COM 				index = -1;
15957836SJohn.Forte@Sun.COM 				goto out;
15967836SJohn.Forte@Sun.COM 			}
15977836SJohn.Forte@Sun.COM 			if (rdc_allow_sec_sync(urdc, CCIO_RSYNC) < 0) {
15987836SJohn.Forte@Sun.COM 				index = -1;
15997836SJohn.Forte@Sun.COM 				goto out;
16007836SJohn.Forte@Sun.COM 			}
16017836SJohn.Forte@Sun.COM 			rdc_dump_dsets(index);
16027836SJohn.Forte@Sun.COM 			rev_sync = 1;
16037836SJohn.Forte@Sun.COM 		} else if (options & CCIO_DONE) {
16047836SJohn.Forte@Sun.COM 			/* Sync completed OK */
16057836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SYNC_NEEDED)
16067836SJohn.Forte@Sun.COM 				done = 1;	/* forward sync complete */
16077836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
16087836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_SYNCING | RDC_SYNC_NEEDED);
16097836SJohn.Forte@Sun.COM 			rdc_clr_mflags(urdc, RDC_SLAVE | RDC_RSYNC_NEEDED);
16107836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
16117836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
16127836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_CLR_AFTERSYNC) {
16137836SJohn.Forte@Sun.COM 				RDC_ZERO_BITMAP(krdc);
16147836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
16157836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_CLR_AFTERSYNC);
16167836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
16177836SJohn.Forte@Sun.COM 			}
16187836SJohn.Forte@Sun.COM 		} else if (options & CCIO_ENABLELOG) {
16197836SJohn.Forte@Sun.COM 			/* Sync aborted or logging started */
16207836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
16217836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_SYNCING);
16227836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
16237836SJohn.Forte@Sun.COM 				rdc_clr_mflags(urdc, RDC_SLAVE);
16247836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
16257836SJohn.Forte@Sun.COM 			}
16267836SJohn.Forte@Sun.COM 			log = 1;
16277836SJohn.Forte@Sun.COM 		}
16287836SJohn.Forte@Sun.COM out:
16297836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
16307836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.primary.addr));
16317836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.secondary.addr));
16327836SJohn.Forte@Sun.COM 
16337836SJohn.Forte@Sun.COM 		if (slave) {
16347836SJohn.Forte@Sun.COM 			if (_rdc_sync_event_notify(RDC_SYNC_START,
16357836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name) >= 0) {
16367836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
16377836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_LOGGING);
16387836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
16397836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_VOL_FAILED);
16407836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc,
16417836SJohn.Forte@Sun.COM 				    RDC_SYNCING | RDC_SYNC_NEEDED);
16427836SJohn.Forte@Sun.COM 				rdc_set_mflags(urdc, RDC_SLAVE);
16437836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
16447836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
16457836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
16467836SJohn.Forte@Sun.COM 			} else {
16477836SJohn.Forte@Sun.COM 				index = -1;
16487836SJohn.Forte@Sun.COM 			}
16497836SJohn.Forte@Sun.COM 		} else if (rev_sync) {
16507836SJohn.Forte@Sun.COM 			/* Check to see if volume is mounted */
16517836SJohn.Forte@Sun.COM 			if (_rdc_sync_event_notify(RDC_RSYNC_START,
16527836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name) >= 0) {
16537836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
16547836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_LOGGING);
16557836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_SYNCING);
16567836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
16577836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
16587836SJohn.Forte@Sun.COM 			} else {
16597836SJohn.Forte@Sun.COM 				index = -1;
16607836SJohn.Forte@Sun.COM 			}
16617836SJohn.Forte@Sun.COM 		} else if (done) {
16627836SJohn.Forte@Sun.COM 
16637836SJohn.Forte@Sun.COM 			/*
16647836SJohn.Forte@Sun.COM 			 * special case...
16657836SJohn.Forte@Sun.COM 			 * if this set is in a group, then sndrsyncd will
16667836SJohn.Forte@Sun.COM 			 * make sure that all sets in the group are REP
16677836SJohn.Forte@Sun.COM 			 * before updating the config to "update", telling
16687836SJohn.Forte@Sun.COM 			 * sndrsyncd that it is ok to take anther snapshot
16697836SJohn.Forte@Sun.COM 			 * on a following sync. The important part about
16707836SJohn.Forte@Sun.COM 			 * the whole thing is that syncd needs kernel stats.
16717836SJohn.Forte@Sun.COM 			 * however, this thread must set the set busy to
16727836SJohn.Forte@Sun.COM 			 * avoid disables. since this is the only
16737836SJohn.Forte@Sun.COM 			 * sync_event_notify() that will cause a status
16747836SJohn.Forte@Sun.COM 			 * call back into the kernel, and we will not be
16757836SJohn.Forte@Sun.COM 			 * accessing the group structure, we have to wakeup now
16767836SJohn.Forte@Sun.COM 			 */
16777836SJohn.Forte@Sun.COM 
16787836SJohn.Forte@Sun.COM 			mutex_enter(&rdc_conf_lock);
16797836SJohn.Forte@Sun.COM 			wakeup_busy(krdc);
16807836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
16817836SJohn.Forte@Sun.COM 
16827836SJohn.Forte@Sun.COM 			(void) _rdc_sync_event_notify(RDC_SYNC_DONE,
16837836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name);
16847836SJohn.Forte@Sun.COM 		}
16857836SJohn.Forte@Sun.COM 	}
16867836SJohn.Forte@Sun.COM 
16877836SJohn.Forte@Sun.COM 	if (!done) {
16887836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
16897836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
16907836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
16917836SJohn.Forte@Sun.COM 	}
16927836SJohn.Forte@Sun.COM 
16937836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&index);
16947836SJohn.Forte@Sun.COM 	if (log) {
16957836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
16967836SJohn.Forte@Sun.COM 		rdc_group_log(krdc, RDC_NOFLUSH | RDC_OTHERREMOTE,
16979093SRamana.Srikanth@Sun.COM 		    "Sync aborted or logging started");
16987836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
16997836SJohn.Forte@Sun.COM 	}
17007836SJohn.Forte@Sun.COM }
17017836SJohn.Forte@Sun.COM 
17027836SJohn.Forte@Sun.COM 
17037836SJohn.Forte@Sun.COM /*
17047836SJohn.Forte@Sun.COM  * r_net_state
17057836SJohn.Forte@Sun.COM  */
17067836SJohn.Forte@Sun.COM static void
r_net_state(SVCXPRT * xprt)17077836SJohn.Forte@Sun.COM r_net_state(SVCXPRT *xprt)
17087836SJohn.Forte@Sun.COM {
17097836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
17107836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
17117836SJohn.Forte@Sun.COM 	struct set_state state;
17127836SJohn.Forte@Sun.COM 	rdc_set_t rdc_set;
17137836SJohn.Forte@Sun.COM 	int e, index = -1;
17147836SJohn.Forte@Sun.COM 	int options;
17157836SJohn.Forte@Sun.COM 	int log = 0;
17167836SJohn.Forte@Sun.COM 	int done = 0;
17177836SJohn.Forte@Sun.COM 	int slave = 0;
17187836SJohn.Forte@Sun.COM 	int rev_sync = 0;
17197836SJohn.Forte@Sun.COM 	unsigned short *sp;
17207836SJohn.Forte@Sun.COM 
17217836SJohn.Forte@Sun.COM 	bzero(&state, sizeof (struct set_state));
17227836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_set_state, (char *)&state);
17237836SJohn.Forte@Sun.COM 	if (e) {
17247836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.primary.addr));
17257836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.secondary.addr));
17267836SJohn.Forte@Sun.COM 		sp = (unsigned short *)(state.netaddr.buf);
17277836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
17287836SJohn.Forte@Sun.COM 		bcopy(state.netaddr.buf, rdc_set.primary.addr.buf,
17297836SJohn.Forte@Sun.COM 		    state.netaddrlen);
17307836SJohn.Forte@Sun.COM 		sp = (unsigned short *)(state.rnetaddr.buf);
17317836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
17327836SJohn.Forte@Sun.COM 		bcopy(state.rnetaddr.buf, rdc_set.secondary.addr.buf,
17337836SJohn.Forte@Sun.COM 		    state.rnetaddrlen);
17347836SJohn.Forte@Sun.COM 		rdc_set.primary.addr.len = state.netaddrlen;
17357836SJohn.Forte@Sun.COM 		rdc_set.secondary.addr.len = state.rnetaddrlen;
17367836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.file, state.pfile,
17377836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
17387836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.secondary.file, state.sfile,
17397836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
17407836SJohn.Forte@Sun.COM 		options = state.flag;
17417836SJohn.Forte@Sun.COM 		index = rdc_lookup_byaddr(&rdc_set);
17427836SJohn.Forte@Sun.COM 
17437836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
17447836SJohn.Forte@Sun.COM 
17457836SJohn.Forte@Sun.COM 		if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
17467836SJohn.Forte@Sun.COM #ifdef DEBUG
17477836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
17489093SRamana.Srikanth@Sun.COM 			    "!r_net_state: no index or disable pending");
17497836SJohn.Forte@Sun.COM #endif
17507836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
17517836SJohn.Forte@Sun.COM 			return;
17527836SJohn.Forte@Sun.COM 		}
17537836SJohn.Forte@Sun.COM 
17547836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
17557836SJohn.Forte@Sun.COM 
17567836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc)) {
17577836SJohn.Forte@Sun.COM 			index = -1;
17587836SJohn.Forte@Sun.COM #ifdef DEBUG
17599093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!r_net_state: set not enabled ");
17607836SJohn.Forte@Sun.COM #endif
17617836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
17627836SJohn.Forte@Sun.COM 			return;
17637836SJohn.Forte@Sun.COM 		}
17647836SJohn.Forte@Sun.COM 
17657836SJohn.Forte@Sun.COM 		if (krdc->lsrv == NULL) {
17669093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!r_net_state: no valid svp\n");
17677836SJohn.Forte@Sun.COM 			index = -1;
17687836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
17697836SJohn.Forte@Sun.COM 			return;
17707836SJohn.Forte@Sun.COM 		}
17717836SJohn.Forte@Sun.COM 		if (!krdc || !krdc->group) {
17727836SJohn.Forte@Sun.COM #ifdef DEBUG
17737836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE,
17749093SRamana.Srikanth@Sun.COM 			    "!r_net_state: no valid krdc %p\n", (void*)krdc);
17757836SJohn.Forte@Sun.COM #endif
17767836SJohn.Forte@Sun.COM 			index = -1;
17777836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
17787836SJohn.Forte@Sun.COM 			return;
17797836SJohn.Forte@Sun.COM 		}
17807836SJohn.Forte@Sun.COM 
17817836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
17827836SJohn.Forte@Sun.COM 		if (krdc->type_flag & RDC_DISABLEPEND) {
17837836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
17847836SJohn.Forte@Sun.COM 			index = -1;
17857836SJohn.Forte@Sun.COM #ifdef DEBUG
17869093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!r_net_state: disable pending");
17877836SJohn.Forte@Sun.COM #endif
17887836SJohn.Forte@Sun.COM 			(void) svc_sendreply(xprt, xdr_int, (char *)&index);
17897836SJohn.Forte@Sun.COM 			return;
17907836SJohn.Forte@Sun.COM 		}
17917836SJohn.Forte@Sun.COM 		set_busy(krdc);
17927836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
17937836SJohn.Forte@Sun.COM 
17947836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
17957836SJohn.Forte@Sun.COM 
17967836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY)
17977836SJohn.Forte@Sun.COM 			krdc->intf = rdc_add_to_if(krdc->lsrv,
17987836SJohn.Forte@Sun.COM 			    &(urdc->primary.addr), &(urdc->secondary.addr), 1);
17997836SJohn.Forte@Sun.COM 		else
18007836SJohn.Forte@Sun.COM 			krdc->intf = rdc_add_to_if(krdc->lsrv,
18017836SJohn.Forte@Sun.COM 			    &(urdc->secondary.addr), &(urdc->primary.addr), 0);
18027836SJohn.Forte@Sun.COM 
18037836SJohn.Forte@Sun.COM 		if (options & CCIO_SLAVE) {
18047836SJohn.Forte@Sun.COM 			/*
18057836SJohn.Forte@Sun.COM 			 * mark that the bitmap needs clearing.
18067836SJohn.Forte@Sun.COM 			 */
18077836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
18087836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_CLR_AFTERSYNC);
18097836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
18107836SJohn.Forte@Sun.COM 
18117836SJohn.Forte@Sun.COM 			/* Starting forward sync */
18127836SJohn.Forte@Sun.COM 			if (urdc->volume_size == 0)
18137836SJohn.Forte@Sun.COM 				rdc_get_details(krdc);
18147836SJohn.Forte@Sun.COM 			if (urdc->volume_size == 0) {
18157836SJohn.Forte@Sun.COM 				index = -1;
18167836SJohn.Forte@Sun.COM 				goto out;
18177836SJohn.Forte@Sun.COM 			}
18187836SJohn.Forte@Sun.COM 			if (krdc->dcio_bitmap == NULL) {
18197836SJohn.Forte@Sun.COM 				if (rdc_resume_bitmap(krdc) < 0) {
18207836SJohn.Forte@Sun.COM 					index = -1;
18217836SJohn.Forte@Sun.COM 					goto out;
18227836SJohn.Forte@Sun.COM 				}
18237836SJohn.Forte@Sun.COM 			}
18247836SJohn.Forte@Sun.COM 			if (rdc_allow_sec_sync(urdc, CCIO_SLAVE) < 0) {
18257836SJohn.Forte@Sun.COM 				index = -1;
18267836SJohn.Forte@Sun.COM 				goto out;
18277836SJohn.Forte@Sun.COM 			}
18287836SJohn.Forte@Sun.COM 			rdc_dump_dsets(index);
18297836SJohn.Forte@Sun.COM 			slave = 1;
18307836SJohn.Forte@Sun.COM 		} else if (options & CCIO_RSYNC) {
18317836SJohn.Forte@Sun.COM 			/*
18327836SJohn.Forte@Sun.COM 			 * mark that the bitmap needs clearing.
18337836SJohn.Forte@Sun.COM 			 */
18347836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
18357836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_CLR_AFTERSYNC);
18367836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
18377836SJohn.Forte@Sun.COM 
18387836SJohn.Forte@Sun.COM 			/* Starting reverse sync */
18397836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & (RDC_SYNC_NEEDED |
18407836SJohn.Forte@Sun.COM 			    RDC_VOL_FAILED | RDC_BMP_FAILED)) {
18417836SJohn.Forte@Sun.COM 				index = -1;
18427836SJohn.Forte@Sun.COM 				goto out;
18437836SJohn.Forte@Sun.COM 			}
18447836SJohn.Forte@Sun.COM 			if (rdc_allow_sec_sync(urdc, CCIO_RSYNC) < 0) {
18457836SJohn.Forte@Sun.COM 				index = -1;
18467836SJohn.Forte@Sun.COM 				goto out;
18477836SJohn.Forte@Sun.COM 			}
18487836SJohn.Forte@Sun.COM 			rdc_dump_dsets(index);
18497836SJohn.Forte@Sun.COM 			rev_sync = 1;
18507836SJohn.Forte@Sun.COM 		} else if (options & CCIO_DONE) {
18517836SJohn.Forte@Sun.COM 			/* Sync completed OK */
18527836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SYNC_NEEDED)
18537836SJohn.Forte@Sun.COM 				done = 1;	/* forward sync complete */
18547836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
18557836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_SYNCING | RDC_SYNC_NEEDED);
18567836SJohn.Forte@Sun.COM 			rdc_clr_mflags(urdc, RDC_SLAVE | RDC_RSYNC_NEEDED);
18577836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
18587836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
18597836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_CLR_AFTERSYNC) {
18607836SJohn.Forte@Sun.COM 				RDC_ZERO_BITMAP(krdc);
18617836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
18627836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_CLR_AFTERSYNC);
18637836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
18647836SJohn.Forte@Sun.COM 			}
18657836SJohn.Forte@Sun.COM 		} else if (options & CCIO_ENABLELOG) {
18667836SJohn.Forte@Sun.COM 			/* Sync aborted or logging started */
18677836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
18687836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_SYNCING);
18697836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
18707836SJohn.Forte@Sun.COM 				rdc_clr_mflags(urdc, RDC_SLAVE);
18717836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
18727836SJohn.Forte@Sun.COM 			}
18737836SJohn.Forte@Sun.COM 			log = 1;
18747836SJohn.Forte@Sun.COM 		}
18757836SJohn.Forte@Sun.COM out:
18767836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
18777836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.primary.addr));
18787836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.secondary.addr));
18797836SJohn.Forte@Sun.COM 
18807836SJohn.Forte@Sun.COM 		if (slave) {
18817836SJohn.Forte@Sun.COM 			if (_rdc_sync_event_notify(RDC_SYNC_START,
18827836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name) >= 0) {
18837836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
18847836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_LOGGING);
18857836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
18867836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_VOL_FAILED);
18877836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc,
18887836SJohn.Forte@Sun.COM 				    RDC_SYNCING | RDC_SYNC_NEEDED);
18897836SJohn.Forte@Sun.COM 				rdc_set_mflags(urdc, RDC_SLAVE);
18907836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
18917836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
18927836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
18937836SJohn.Forte@Sun.COM 			} else {
18947836SJohn.Forte@Sun.COM 				index = -1;
18957836SJohn.Forte@Sun.COM 			}
18967836SJohn.Forte@Sun.COM 		} else if (rev_sync) {
18977836SJohn.Forte@Sun.COM 			/* Check to see if volume is mounted */
18987836SJohn.Forte@Sun.COM 			if (_rdc_sync_event_notify(RDC_RSYNC_START,
18997836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name) >= 0) {
19007836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
19017836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_LOGGING);
19027836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_SYNCING);
19037836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
19047836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
19057836SJohn.Forte@Sun.COM 			} else {
19067836SJohn.Forte@Sun.COM 				index = -1;
19077836SJohn.Forte@Sun.COM 			}
19087836SJohn.Forte@Sun.COM 		} else if (done) {
19097836SJohn.Forte@Sun.COM 
19107836SJohn.Forte@Sun.COM 			/*
19117836SJohn.Forte@Sun.COM 			 * special case...
19127836SJohn.Forte@Sun.COM 			 * if this set is in a group, then sndrsyncd will
19137836SJohn.Forte@Sun.COM 			 * make sure that all sets in the group are REP
19147836SJohn.Forte@Sun.COM 			 * before updating the config to "update", telling
19157836SJohn.Forte@Sun.COM 			 * sndrsyncd that it is ok to take anther snapshot
19167836SJohn.Forte@Sun.COM 			 * on a following sync. The important part about
19177836SJohn.Forte@Sun.COM 			 * the whole thing is that syncd needs kernel stats.
19187836SJohn.Forte@Sun.COM 			 * however, this thread must set the set busy to
19197836SJohn.Forte@Sun.COM 			 * avoid disables. since this is the only
19207836SJohn.Forte@Sun.COM 			 * sync_event_notify() that will cause a status
19217836SJohn.Forte@Sun.COM 			 * call back into the kernel, and we will not be
19227836SJohn.Forte@Sun.COM 			 * accessing the group structure, we have to wakeup now
19237836SJohn.Forte@Sun.COM 			 */
19247836SJohn.Forte@Sun.COM 
19257836SJohn.Forte@Sun.COM 			mutex_enter(&rdc_conf_lock);
19267836SJohn.Forte@Sun.COM 			wakeup_busy(krdc);
19277836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
19287836SJohn.Forte@Sun.COM 
19297836SJohn.Forte@Sun.COM 			(void) _rdc_sync_event_notify(RDC_SYNC_DONE,
19307836SJohn.Forte@Sun.COM 			    urdc->secondary.file, urdc->group_name);
19317836SJohn.Forte@Sun.COM 		}
19327836SJohn.Forte@Sun.COM 	}
19337836SJohn.Forte@Sun.COM 
19347836SJohn.Forte@Sun.COM 	if (!done) {
19357836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
19367836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
19377836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
19387836SJohn.Forte@Sun.COM 	}
19397836SJohn.Forte@Sun.COM 
19407836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&index);
19417836SJohn.Forte@Sun.COM 	if (log) {
19427836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
19437836SJohn.Forte@Sun.COM 		rdc_group_log(krdc, RDC_NOFLUSH | RDC_OTHERREMOTE,
19449093SRamana.Srikanth@Sun.COM 		    "Sync aborted or logging started");
19457836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
19467836SJohn.Forte@Sun.COM 	}
19477836SJohn.Forte@Sun.COM 	free_rdc_netbuf(&(state.netaddr));
19487836SJohn.Forte@Sun.COM 	free_rdc_netbuf(&(state.rnetaddr));
19497836SJohn.Forte@Sun.COM }
19507836SJohn.Forte@Sun.COM 
19517836SJohn.Forte@Sun.COM /*
19527836SJohn.Forte@Sun.COM  * r_net_getstate4
19537836SJohn.Forte@Sun.COM  * Return our state to client
19547836SJohn.Forte@Sun.COM  */
19557836SJohn.Forte@Sun.COM static void
r_net_getstate4(SVCXPRT * xprt,struct svc_req * req)19567836SJohn.Forte@Sun.COM r_net_getstate4(SVCXPRT *xprt, struct svc_req *req)
19577836SJohn.Forte@Sun.COM {
19587836SJohn.Forte@Sun.COM 	int e, ret = -1, index = -1;
19597836SJohn.Forte@Sun.COM 	struct set_state4 state;
19607836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
19617836SJohn.Forte@Sun.COM 	rdc_set_t rdc_set;
19627836SJohn.Forte@Sun.COM 
19637836SJohn.Forte@Sun.COM 	bzero(&state, sizeof (struct set_state));
19647836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_set_state4, (char *)&state);
19657836SJohn.Forte@Sun.COM 	if (e) {
19667836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.primary.addr));
19677836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.secondary.addr));
19687836SJohn.Forte@Sun.COM 		bcopy(state.netaddr, rdc_set.primary.addr.buf,
19697836SJohn.Forte@Sun.COM 		    state.netaddrlen);
19707836SJohn.Forte@Sun.COM 		bcopy(state.rnetaddr, rdc_set.secondary.addr.buf,
19717836SJohn.Forte@Sun.COM 		    state.rnetaddrlen);
19727836SJohn.Forte@Sun.COM 		rdc_set.primary.addr.len = state.netaddrlen;
19737836SJohn.Forte@Sun.COM 		rdc_set.secondary.addr.len = state.rnetaddrlen;
19747836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.file, state.pfile,
19757836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
19767836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.secondary.file, state.sfile,
19777836SJohn.Forte@Sun.COM 		    RDC_MAXNAMLEN);
19787836SJohn.Forte@Sun.COM 		index = rdc_lookup_byaddr(&rdc_set);
19797836SJohn.Forte@Sun.COM 		if (index >= 0) {
19807836SJohn.Forte@Sun.COM 			urdc = &rdc_u_info[index];
19817836SJohn.Forte@Sun.COM 
19827836SJohn.Forte@Sun.COM 			ret = 0;
19837836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SYNCING)
19847836SJohn.Forte@Sun.COM 				ret |= 4;
19857836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SLAVE)
19867836SJohn.Forte@Sun.COM 				ret |= 2;
19877836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_LOGGING)
19887836SJohn.Forte@Sun.COM 				ret |= 1;
19897836SJohn.Forte@Sun.COM 			rdc_set_if_vers(urdc, req->rq_vers);
19907836SJohn.Forte@Sun.COM 		}
19917836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.primary.addr));
19927836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.secondary.addr));
19937836SJohn.Forte@Sun.COM 	}
19947836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
19957836SJohn.Forte@Sun.COM }
19967836SJohn.Forte@Sun.COM 
19977836SJohn.Forte@Sun.COM /*
19987836SJohn.Forte@Sun.COM  * r_net_getstate7
19997836SJohn.Forte@Sun.COM  * Return our state to client
20007836SJohn.Forte@Sun.COM  */
20017836SJohn.Forte@Sun.COM static void
r_net_getstate7(SVCXPRT * xprt,struct svc_req * req)20027836SJohn.Forte@Sun.COM r_net_getstate7(SVCXPRT *xprt, struct svc_req *req)
20037836SJohn.Forte@Sun.COM {
20047836SJohn.Forte@Sun.COM 	int e, ret = -1, index = -1;
20057836SJohn.Forte@Sun.COM 	struct set_state state;
20067836SJohn.Forte@Sun.COM 	char pstr[RDC_MAXNAMLEN];
20077836SJohn.Forte@Sun.COM 	char sstr[RDC_MAXNAMLEN];
20087836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
20097836SJohn.Forte@Sun.COM 	rdc_set_t rdc_set;
20107836SJohn.Forte@Sun.COM 	unsigned short *sp;
20117836SJohn.Forte@Sun.COM 
20127836SJohn.Forte@Sun.COM 	bzero(&state, sizeof (struct set_state));
20137836SJohn.Forte@Sun.COM 	state.pfile = pstr;
20147836SJohn.Forte@Sun.COM 	state.sfile = sstr;
20157836SJohn.Forte@Sun.COM 
20167836SJohn.Forte@Sun.COM 	e = SVC_GETARGS(xprt, xdr_set_state, (char *)&state);
20177836SJohn.Forte@Sun.COM 	if (e) {
20187836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.primary.addr));
20197836SJohn.Forte@Sun.COM 		init_rdc_netbuf(&(rdc_set.secondary.addr));
20207836SJohn.Forte@Sun.COM 		sp = (unsigned short *)(state.netaddr.buf);
20217836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
20227836SJohn.Forte@Sun.COM 		bcopy(state.netaddr.buf, rdc_set.primary.addr.buf,
20237836SJohn.Forte@Sun.COM 		    state.netaddrlen);
20247836SJohn.Forte@Sun.COM 		sp = (unsigned short *)(state.rnetaddr.buf);
20257836SJohn.Forte@Sun.COM 		*sp = ntohs(*sp);
20267836SJohn.Forte@Sun.COM 		bcopy(state.rnetaddr.buf, rdc_set.secondary.addr.buf,
20277836SJohn.Forte@Sun.COM 		    state.rnetaddrlen);
20287836SJohn.Forte@Sun.COM 		rdc_set.primary.addr.len = state.netaddrlen;
20297836SJohn.Forte@Sun.COM 		rdc_set.secondary.addr.len = state.rnetaddrlen;
20307836SJohn.Forte@Sun.COM 		/*
20317836SJohn.Forte@Sun.COM 		 * strncpy(rdc_set.primary.file, state.pfile, RDC_MAXNAMLEN);
20327836SJohn.Forte@Sun.COM 		 * strncpy(rdc_set.secondary.file, state.sfile, RDC_MAXNAMLEN);
20337836SJohn.Forte@Sun.COM 		 */
20347836SJohn.Forte@Sun.COM 		bcopy(state.pfile, rdc_set.primary.file, RDC_MAXNAMLEN);
20357836SJohn.Forte@Sun.COM 		bcopy(state.sfile, rdc_set.secondary.file, RDC_MAXNAMLEN);
20367836SJohn.Forte@Sun.COM 		index = rdc_lookup_byaddr(&rdc_set);
20377836SJohn.Forte@Sun.COM 		if (index >= 0) {
20387836SJohn.Forte@Sun.COM 			urdc = &rdc_u_info[index];
20397836SJohn.Forte@Sun.COM 
20407836SJohn.Forte@Sun.COM 			ret = 0;
20417836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SYNCING)
20427836SJohn.Forte@Sun.COM 				ret |= 4;
20437836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_SLAVE)
20447836SJohn.Forte@Sun.COM 				ret |= 2;
20457836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_LOGGING)
20467836SJohn.Forte@Sun.COM 				ret |= 1;
20477836SJohn.Forte@Sun.COM 			rdc_set_if_vers(urdc, req->rq_vers);
20487836SJohn.Forte@Sun.COM 		}
20497836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.primary.addr));
20507836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&(rdc_set.secondary.addr));
20517836SJohn.Forte@Sun.COM 	}
20527836SJohn.Forte@Sun.COM 	(void) svc_sendreply(xprt, xdr_int, (char *)&ret);
20537836SJohn.Forte@Sun.COM }
20547836SJohn.Forte@Sun.COM 
20557836SJohn.Forte@Sun.COM /*
20567836SJohn.Forte@Sun.COM  * copy from/to a dset/vector combination to a network xdr buffer.
20577836SJohn.Forte@Sun.COM  */
20587836SJohn.Forte@Sun.COM static int
rdc_dsetcopy(rdc_net_dataset_t * dset,nsc_vec_t * invec,nsc_off_t fba_pos,nsc_size_t fba_len,char * bdata,int blen,int dir)20597836SJohn.Forte@Sun.COM rdc_dsetcopy(rdc_net_dataset_t *dset, nsc_vec_t *invec, nsc_off_t fba_pos,
20607836SJohn.Forte@Sun.COM     nsc_size_t fba_len, char *bdata, int blen, int dir)
20617836SJohn.Forte@Sun.COM {
20627836SJohn.Forte@Sun.COM 	nsc_vec_t *vec;
20637836SJohn.Forte@Sun.COM 	uchar_t *sv_addr;
20647836SJohn.Forte@Sun.COM 	uchar_t *data;
20657836SJohn.Forte@Sun.COM 	int sv_len;
20667836SJohn.Forte@Sun.COM 	nsc_off_t fpos;
20677836SJohn.Forte@Sun.COM 	int len;
20687836SJohn.Forte@Sun.COM 	int n;
20697836SJohn.Forte@Sun.COM 
20707836SJohn.Forte@Sun.COM 	if (!bdata || !dset || !invec) {
20717836SJohn.Forte@Sun.COM #ifdef DEBUG
20727836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
20739093SRamana.Srikanth@Sun.COM 		    "!rdc: dsetcopy: parameters failed bdata %p, dset %p "
20749093SRamana.Srikanth@Sun.COM 		    "invec %p", (void *)bdata, (void *)dset, (void *)invec);
20757836SJohn.Forte@Sun.COM #endif
20767836SJohn.Forte@Sun.COM 		return (FALSE);
20777836SJohn.Forte@Sun.COM 	}
20787836SJohn.Forte@Sun.COM 
20797836SJohn.Forte@Sun.COM 	if (fba_len > MAX_RDC_FBAS ||
20807836SJohn.Forte@Sun.COM 	    (dir != COPY_IN && dir != COPY_OUT)) {
20817836SJohn.Forte@Sun.COM #ifdef DEBUG
20827836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
20839093SRamana.Srikanth@Sun.COM 		    "!rdc: dsetcopy: params failed fba_len %" NSC_SZFMT
20847836SJohn.Forte@Sun.COM 		    " fba_pos %" NSC_SZFMT ", dir %d", fba_len, fba_pos, dir);
20857836SJohn.Forte@Sun.COM #endif
20867836SJohn.Forte@Sun.COM 		return (FALSE);
20877836SJohn.Forte@Sun.COM 	}
20887836SJohn.Forte@Sun.COM 
20897836SJohn.Forte@Sun.COM 	data = (uchar_t *)bdata;	/* pointer to data in rpc */
20907836SJohn.Forte@Sun.COM 	len = FBA_SIZE(fba_len);	/* length of this transfer in bytes */
20917836SJohn.Forte@Sun.COM 	fpos = fba_pos;			/* start fba offset within buffer */
20927836SJohn.Forte@Sun.COM 
20937836SJohn.Forte@Sun.COM 	if (!len) {
20947836SJohn.Forte@Sun.COM #ifdef DEBUG
20959093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc: dsetcopy: len = 0");
20967836SJohn.Forte@Sun.COM #endif
20977836SJohn.Forte@Sun.COM 		return (FALSE);
20987836SJohn.Forte@Sun.COM 	}
20997836SJohn.Forte@Sun.COM 
21007836SJohn.Forte@Sun.COM 	if (len != blen) {
21017836SJohn.Forte@Sun.COM #ifdef DEBUG
21029093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc:dsetcopy: len %d != blen %d", len, blen);
21037836SJohn.Forte@Sun.COM #endif
21047836SJohn.Forte@Sun.COM 		if (len > blen)
21057836SJohn.Forte@Sun.COM 			len = blen;
21067836SJohn.Forte@Sun.COM 	}
21077836SJohn.Forte@Sun.COM 
21087836SJohn.Forte@Sun.COM 	if (!RDC_DSET_LIMITS(dset, fba_pos, fba_len)) {
21097836SJohn.Forte@Sun.COM 		/* should never happen */
21107836SJohn.Forte@Sun.COM #ifdef DEBUG
21117836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
21129093SRamana.Srikanth@Sun.COM 		    "!rdc: dsetcopy: handle limits pos %" NSC_SZFMT " (%"
21137836SJohn.Forte@Sun.COM 		    NSC_SZFMT ") len %" NSC_SZFMT " (%" NSC_SZFMT ")",
21149093SRamana.Srikanth@Sun.COM 		    fba_pos, dset->pos, fba_len, dset->fbalen);
21157836SJohn.Forte@Sun.COM #endif
21167836SJohn.Forte@Sun.COM 		return (FALSE);	/* Don't overrun handle */
21177836SJohn.Forte@Sun.COM 	}
21187836SJohn.Forte@Sun.COM 
21197836SJohn.Forte@Sun.COM 	vec = invec;
21207836SJohn.Forte@Sun.COM 	fpos -= dset->pos;
21217836SJohn.Forte@Sun.COM 
21227836SJohn.Forte@Sun.COM 	/* find starting position in vector */
21237836SJohn.Forte@Sun.COM 
21247836SJohn.Forte@Sun.COM 	for (; fpos >= FBA_NUM(vec->sv_len); vec++)
21257836SJohn.Forte@Sun.COM 		fpos -= FBA_NUM(vec->sv_len);
21267836SJohn.Forte@Sun.COM 
21277836SJohn.Forte@Sun.COM 	/*
21287836SJohn.Forte@Sun.COM 	 * Copy data
21297836SJohn.Forte@Sun.COM 	 */
21307836SJohn.Forte@Sun.COM 
21317836SJohn.Forte@Sun.COM 	sv_addr = vec->sv_addr + FBA_SIZE(fpos);
21327836SJohn.Forte@Sun.COM 	sv_len = vec->sv_len - FBA_SIZE(fpos);
21337836SJohn.Forte@Sun.COM 
21347836SJohn.Forte@Sun.COM 	while (len) {
21357836SJohn.Forte@Sun.COM 		if (!sv_addr)	/* end of vec - how did this happen? */
21367836SJohn.Forte@Sun.COM 			break;
21377836SJohn.Forte@Sun.COM 
21387836SJohn.Forte@Sun.COM 		n = min(sv_len, len);
21397836SJohn.Forte@Sun.COM 
21407836SJohn.Forte@Sun.COM 		if (dir == COPY_OUT)
21417836SJohn.Forte@Sun.COM 			bcopy(data, sv_addr, (size_t)n);
21427836SJohn.Forte@Sun.COM 		else
21437836SJohn.Forte@Sun.COM 			bcopy(sv_addr, data, (size_t)n);
21447836SJohn.Forte@Sun.COM 
21457836SJohn.Forte@Sun.COM 		sv_len -= n;
21467836SJohn.Forte@Sun.COM 		len -= n;
21477836SJohn.Forte@Sun.COM 
21487836SJohn.Forte@Sun.COM 		sv_addr += n;
21497836SJohn.Forte@Sun.COM 		data += n;
21507836SJohn.Forte@Sun.COM 
21517836SJohn.Forte@Sun.COM 		if (sv_len <= 0) {
21527836SJohn.Forte@Sun.COM 			/* goto next vector */
21537836SJohn.Forte@Sun.COM 			vec++;
21547836SJohn.Forte@Sun.COM 			sv_addr = vec->sv_addr;
21557836SJohn.Forte@Sun.COM 			sv_len = vec->sv_len;
21567836SJohn.Forte@Sun.COM 		}
21577836SJohn.Forte@Sun.COM 	}
21587836SJohn.Forte@Sun.COM 
21597836SJohn.Forte@Sun.COM 	return (TRUE);
21607836SJohn.Forte@Sun.COM }
21617836SJohn.Forte@Sun.COM 
21627836SJohn.Forte@Sun.COM 
21637836SJohn.Forte@Sun.COM /*
21647836SJohn.Forte@Sun.COM  * rdc_start_server
21657836SJohn.Forte@Sun.COM  * Starts the kRPC server for rdc. Uses tli file descriptor passed down
21667836SJohn.Forte@Sun.COM  * from user level rdc server.
21677836SJohn.Forte@Sun.COM  *
21687836SJohn.Forte@Sun.COM  * Returns: 0 or errno (NOT unistat!).
21697836SJohn.Forte@Sun.COM  */
21707836SJohn.Forte@Sun.COM int
rdc_start_server(struct rdc_svc_args * args,int mode)21717836SJohn.Forte@Sun.COM rdc_start_server(struct rdc_svc_args *args, int mode)
21727836SJohn.Forte@Sun.COM {
21737836SJohn.Forte@Sun.COM 	file_t *fp;
21747836SJohn.Forte@Sun.COM 	int ret;
21757836SJohn.Forte@Sun.COM 	struct cred *cred;
21767836SJohn.Forte@Sun.COM 	STRUCT_HANDLE(rdc_svc_args, rs);
21777836SJohn.Forte@Sun.COM 
21787836SJohn.Forte@Sun.COM 	STRUCT_SET_HANDLE(rs, mode, args);
21797836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
21807836SJohn.Forte@Sun.COM 	if (drv_priv(cred) != 0)
21817836SJohn.Forte@Sun.COM 		return (EPERM);
21827836SJohn.Forte@Sun.COM 	fp = getf(STRUCT_FGET(rs, fd));
21837836SJohn.Forte@Sun.COM 	if (fp == NULL) {
21847836SJohn.Forte@Sun.COM #ifdef DEBUG
21859093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_start_server fd %d, fp %p", args->fd,
21869093SRamana.Srikanth@Sun.COM 		    (void *) fp);
21877836SJohn.Forte@Sun.COM #endif
21887836SJohn.Forte@Sun.COM 		return (EBADF);
21897836SJohn.Forte@Sun.COM 	}
21907836SJohn.Forte@Sun.COM 
21917836SJohn.Forte@Sun.COM 	ret = rdcsrv_load(fp, rdc_srvtab, args, mode);
21927836SJohn.Forte@Sun.COM 
21937836SJohn.Forte@Sun.COM 	releasef(STRUCT_FGET(rs, fd));
21947836SJohn.Forte@Sun.COM 	return (ret);
21957836SJohn.Forte@Sun.COM }
21967836SJohn.Forte@Sun.COM 
21977836SJohn.Forte@Sun.COM /*
21987836SJohn.Forte@Sun.COM  * Allocate a new sleepq element.
21997836SJohn.Forte@Sun.COM  */
22007836SJohn.Forte@Sun.COM 
22017836SJohn.Forte@Sun.COM static rdc_sleepq_t *
rdc_newsleepq()22027836SJohn.Forte@Sun.COM rdc_newsleepq()
22037836SJohn.Forte@Sun.COM {
22047836SJohn.Forte@Sun.COM 	rdc_sleepq_t	*sq;
22057836SJohn.Forte@Sun.COM 
22067836SJohn.Forte@Sun.COM 	sq = kmem_alloc(sizeof (rdc_sleepq_t), KM_SLEEP);
22077836SJohn.Forte@Sun.COM 	sq->next = NULL;
22087836SJohn.Forte@Sun.COM #ifdef DEBUG
22097836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_cntlock);
22107836SJohn.Forte@Sun.COM 	rdc_sleepcnt++;
22117836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_cntlock);
22127836SJohn.Forte@Sun.COM #endif
22137836SJohn.Forte@Sun.COM 	return (sq);
22147836SJohn.Forte@Sun.COM }
22157836SJohn.Forte@Sun.COM 
22167836SJohn.Forte@Sun.COM /*
22177836SJohn.Forte@Sun.COM  * free memory/resources used by a sleepq element.
22187836SJohn.Forte@Sun.COM  */
22197836SJohn.Forte@Sun.COM static void
rdc_delsleepq(rdc_sleepq_t * sq)22207836SJohn.Forte@Sun.COM rdc_delsleepq(rdc_sleepq_t *sq)
22217836SJohn.Forte@Sun.COM {
22227836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
22237836SJohn.Forte@Sun.COM 
22247836SJohn.Forte@Sun.COM 	if (sq->idx != -1) {
22257836SJohn.Forte@Sun.COM 		dset = rdc_net_get_set(sq->sindex, sq->idx);
22267836SJohn.Forte@Sun.COM 		if (dset) {
22277836SJohn.Forte@Sun.COM 			rdc_net_del_set(sq->sindex, dset);
22287836SJohn.Forte@Sun.COM 		}
22297836SJohn.Forte@Sun.COM 	}
22307836SJohn.Forte@Sun.COM 	kmem_free(sq, sizeof (rdc_sleepq_t));
22317836SJohn.Forte@Sun.COM #ifdef DEBUG
22327836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_cntlock);
22337836SJohn.Forte@Sun.COM 	rdc_sleepcnt--;
22347836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_cntlock);
22357836SJohn.Forte@Sun.COM #endif
22367836SJohn.Forte@Sun.COM }
22377836SJohn.Forte@Sun.COM 
22387836SJohn.Forte@Sun.COM 
22397836SJohn.Forte@Sun.COM /*
22407836SJohn.Forte@Sun.COM  * skip down the sleep q and insert the sleep request
22417836SJohn.Forte@Sun.COM  * in ascending order. Return 0 on success, 1 on failure.
22427836SJohn.Forte@Sun.COM  */
22437836SJohn.Forte@Sun.COM static int
rdc_sleepq(rdc_group_t * group,rdc_sleepq_t * sq)22447836SJohn.Forte@Sun.COM rdc_sleepq(rdc_group_t *group, rdc_sleepq_t *sq)
22457836SJohn.Forte@Sun.COM {
22467836SJohn.Forte@Sun.COM 	rdc_sleepq_t *findsq;
22477836SJohn.Forte@Sun.COM 
22487836SJohn.Forte@Sun.COM 
22497836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&group->ra_queue.net_qlock));
22507836SJohn.Forte@Sun.COM 	if (group->sleepq == NULL) {
22517836SJohn.Forte@Sun.COM 		group->sleepq = sq;
22527836SJohn.Forte@Sun.COM 	} else {
22537836SJohn.Forte@Sun.COM 		if (sq->seq == group->sleepq->seq) {
22549093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!rdc_sleepq: Attempt to "
22557836SJohn.Forte@Sun.COM 			    "add duplicate request to queue %d", sq->seq);
22567836SJohn.Forte@Sun.COM 			return (1);
22577836SJohn.Forte@Sun.COM 		}
22587836SJohn.Forte@Sun.COM 		if (RDC_INFRONT(sq->seq, group->sleepq->seq)) {
22597836SJohn.Forte@Sun.COM 			sq->next = group->sleepq;
22607836SJohn.Forte@Sun.COM 			group->sleepq = sq;
22617836SJohn.Forte@Sun.COM 		} else {
22627836SJohn.Forte@Sun.COM 			findsq = group->sleepq;
22637836SJohn.Forte@Sun.COM 
22647836SJohn.Forte@Sun.COM 			while (findsq->next) {
22657836SJohn.Forte@Sun.COM 				if (sq->seq == findsq->next->seq) {
22669093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!rdc_sleepq: "
22677836SJohn.Forte@Sun.COM 					    "Attempt to add duplicate "
22687836SJohn.Forte@Sun.COM 					    "request to queue %d", sq->seq);
22697836SJohn.Forte@Sun.COM 					return (1);
22707836SJohn.Forte@Sun.COM 				}
22717836SJohn.Forte@Sun.COM 				if (RDC_INFRONT(sq->seq, findsq->next->seq)) {
22727836SJohn.Forte@Sun.COM 					sq->next = findsq->next;
22737836SJohn.Forte@Sun.COM 					findsq->next = sq;
22747836SJohn.Forte@Sun.COM 					break;
22757836SJohn.Forte@Sun.COM 				}
22767836SJohn.Forte@Sun.COM 				findsq = findsq->next;
22777836SJohn.Forte@Sun.COM 			}
22787836SJohn.Forte@Sun.COM 			if (findsq->next == NULL)
22797836SJohn.Forte@Sun.COM 				findsq->next = sq;
22807836SJohn.Forte@Sun.COM 		}
22817836SJohn.Forte@Sun.COM 	}
22827836SJohn.Forte@Sun.COM 	return (0);
22837836SJohn.Forte@Sun.COM }
22847836SJohn.Forte@Sun.COM 
22857836SJohn.Forte@Sun.COM /*
22867836SJohn.Forte@Sun.COM  * run down the sleep q and discard all the sleepq elements.
22877836SJohn.Forte@Sun.COM  */
22887836SJohn.Forte@Sun.COM void
rdc_sleepqdiscard(rdc_group_t * group)22897836SJohn.Forte@Sun.COM rdc_sleepqdiscard(rdc_group_t *group)
22907836SJohn.Forte@Sun.COM {
22917836SJohn.Forte@Sun.COM 	rdc_sleepq_t *sq;
22927836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
22937836SJohn.Forte@Sun.COM 
22947836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&group->ra_queue.net_qlock));
22957836SJohn.Forte@Sun.COM 	sq = group->sleepq;
22967836SJohn.Forte@Sun.COM 
22977836SJohn.Forte@Sun.COM 	while (sq) {
22987836SJohn.Forte@Sun.COM 		rdc_sleepq_t *dsq;
22997836SJohn.Forte@Sun.COM 
23007836SJohn.Forte@Sun.COM 		dsq = sq;
23017836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[dsq->sindex];
23027836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
23037836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
23047836SJohn.Forte@Sun.COM 			kstat_waitq_exit(KSTAT_IO_PTR(krdc->io_kstats));
23057836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
23067836SJohn.Forte@Sun.COM 		}
23077836SJohn.Forte@Sun.COM 		sq = sq->next;
23087836SJohn.Forte@Sun.COM 		rdc_delsleepq(dsq);
23097836SJohn.Forte@Sun.COM 	}
23107836SJohn.Forte@Sun.COM 	group->sleepq = NULL;
23117836SJohn.Forte@Sun.COM }
23127836SJohn.Forte@Sun.COM 
23137836SJohn.Forte@Sun.COM /*
23147836SJohn.Forte@Sun.COM  * split any write requests down to maxfba sized chunks.
23157836SJohn.Forte@Sun.COM  */
23167836SJohn.Forte@Sun.COM /*ARGSUSED*/
23177836SJohn.Forte@Sun.COM static int
rdc_writemaxfba(rdc_k_info_t * krdc,rdc_u_info_t * urdc,rdc_net_dataset_t * dset,uint_t seq,int nocache)23187836SJohn.Forte@Sun.COM rdc_writemaxfba(rdc_k_info_t *krdc, rdc_u_info_t *urdc,
23197836SJohn.Forte@Sun.COM     rdc_net_dataset_t *dset, uint_t seq, int nocache)
23207836SJohn.Forte@Sun.COM {
23217836SJohn.Forte@Sun.COM 	int len;
23227836SJohn.Forte@Sun.COM 	int ret;
23237836SJohn.Forte@Sun.COM 	nsc_vec_t vector[2];
23247836SJohn.Forte@Sun.COM 	nsc_buf_t *handle;
23257836SJohn.Forte@Sun.COM 	int reserved;
23267836SJohn.Forte@Sun.COM 	int rtype;
23277836SJohn.Forte@Sun.COM 	nsc_size_t mfba;
23287836SJohn.Forte@Sun.COM 	nsc_size_t wsize;
23297836SJohn.Forte@Sun.COM 	nsc_off_t pos;
23307836SJohn.Forte@Sun.COM 	int eintr_count;
23317836SJohn.Forte@Sun.COM 	unsigned char *daddr;
23327836SJohn.Forte@Sun.COM 	int kstat_len;
23337836SJohn.Forte@Sun.COM 
23347836SJohn.Forte@Sun.COM 	kstat_len = len = dset->fbalen;
23357836SJohn.Forte@Sun.COM 	ret = 0;
23367836SJohn.Forte@Sun.COM 	handle = NULL;
23377836SJohn.Forte@Sun.COM 	reserved = 0;
23387836SJohn.Forte@Sun.COM 	rtype = RDC_RAW;
23397836SJohn.Forte@Sun.COM 
23407836SJohn.Forte@Sun.COM 	ASSERT(dset->nitems == 1);
23417836SJohn.Forte@Sun.COM 
23427836SJohn.Forte@Sun.COM 	eintr_count = 0;
23437836SJohn.Forte@Sun.COM 	do {
23447836SJohn.Forte@Sun.COM 		ret = _rdc_rsrv_devs(krdc, rtype, RDC_INTERNAL);
23457836SJohn.Forte@Sun.COM 		if (ret == EINTR) {
23467836SJohn.Forte@Sun.COM 			++eintr_count;
23477836SJohn.Forte@Sun.COM 			delay(2);
23487836SJohn.Forte@Sun.COM 		}
23497836SJohn.Forte@Sun.COM 	} while ((ret == EINTR) && (eintr_count < MAX_EINTR_COUNT));
23507836SJohn.Forte@Sun.COM 	if (ret != 0) {
23517836SJohn.Forte@Sun.COM #ifdef DEBUG
23529093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_writemaxfba: reserve devs "
23537836SJohn.Forte@Sun.COM 		    "failed %d", ret);
23547836SJohn.Forte@Sun.COM #endif
23557836SJohn.Forte@Sun.COM 		goto out;
23567836SJohn.Forte@Sun.COM 
23577836SJohn.Forte@Sun.COM 	}
23587836SJohn.Forte@Sun.COM 	reserved = 1;
23597836SJohn.Forte@Sun.COM 	/*
23607836SJohn.Forte@Sun.COM 	 * Perhaps we should cache mfba.
23617836SJohn.Forte@Sun.COM 	 */
23627836SJohn.Forte@Sun.COM 	ret = nsc_maxfbas(RDC_U_FD(krdc), 0, &mfba);
23637836SJohn.Forte@Sun.COM 	if (ret != 0) {
23647836SJohn.Forte@Sun.COM #ifdef DEBUG
23659093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_writemaxfba: msc_maxfbas failed %d",
23667836SJohn.Forte@Sun.COM 		    ret);
23677836SJohn.Forte@Sun.COM #endif
23687836SJohn.Forte@Sun.COM 		goto out;
23697836SJohn.Forte@Sun.COM 	}
23707836SJohn.Forte@Sun.COM 
23717836SJohn.Forte@Sun.COM 	ASSERT(urdc->volume_size != 0);
23727836SJohn.Forte@Sun.COM 	if (dset->pos + len > urdc->volume_size) {
23737836SJohn.Forte@Sun.COM 		/* should never happen */
23747836SJohn.Forte@Sun.COM 		/*
23757836SJohn.Forte@Sun.COM 		 * also need to trim down the vector
23767836SJohn.Forte@Sun.COM 		 * sizes.
23777836SJohn.Forte@Sun.COM 		 */
23787836SJohn.Forte@Sun.COM 		kstat_len = len = urdc->volume_size - dset->pos;
23797836SJohn.Forte@Sun.COM 		dset->head->len -= FBA_SIZE(len);
23807836SJohn.Forte@Sun.COM 		ASSERT(dset->head->len > 0);
23817836SJohn.Forte@Sun.COM 	}
23827836SJohn.Forte@Sun.COM 	daddr = dset->head->dptr;
23837836SJohn.Forte@Sun.COM 	pos = dset->pos;
23847836SJohn.Forte@Sun.COM 	vector[1].sv_addr = NULL;
23857836SJohn.Forte@Sun.COM 	vector[1].sv_len = 0;
23867836SJohn.Forte@Sun.COM 
23877836SJohn.Forte@Sun.COM 	while (len > 0) {
23887836SJohn.Forte@Sun.COM 		wsize = min((nsc_size_t)len, mfba);
23897836SJohn.Forte@Sun.COM 		vector[0].sv_addr = daddr;
23907836SJohn.Forte@Sun.COM 		vector[0].sv_len = FBA_SIZE(wsize);
23917836SJohn.Forte@Sun.COM 
23927836SJohn.Forte@Sun.COM 		if (handle) {
23937836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(handle);
23947836SJohn.Forte@Sun.COM 			handle = NULL;
23957836SJohn.Forte@Sun.COM 		}
23967836SJohn.Forte@Sun.COM 		ret = nsc_alloc_buf(RDC_U_FD(krdc), pos, wsize,
23977836SJohn.Forte@Sun.COM 		    NSC_WRBUF|NSC_NODATA|nocache, &handle);
23987836SJohn.Forte@Sun.COM 		if (ret != 0) {
23997836SJohn.Forte@Sun.COM #ifdef DEBUG
24009093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!rdc_writemaxfba: "
24017836SJohn.Forte@Sun.COM 			    "nsc_alloc (d1) buf failed %d at "
24027836SJohn.Forte@Sun.COM 			    "pos %" NSC_SZFMT " len %" NSC_SZFMT,
24037836SJohn.Forte@Sun.COM 			    ret, pos, wsize);
24047836SJohn.Forte@Sun.COM #endif
24057836SJohn.Forte@Sun.COM 			goto out;
24067836SJohn.Forte@Sun.COM 		}
24077836SJohn.Forte@Sun.COM 		handle->sb_vec = &vector[0];
24087836SJohn.Forte@Sun.COM 		ret = rdc_combywrite(krdc, handle);
24097836SJohn.Forte@Sun.COM 		if (ret != 0) {
24107836SJohn.Forte@Sun.COM #ifdef DEBUG
24119093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!rdc_writemaxfba: "
24127836SJohn.Forte@Sun.COM 			    "write failed (d1) %d offset %" NSC_SZFMT " "
24137836SJohn.Forte@Sun.COM 			    "length %" NSC_SZFMT, ret, pos, wsize);
24147836SJohn.Forte@Sun.COM #endif
24157836SJohn.Forte@Sun.COM 			goto out;
24167836SJohn.Forte@Sun.COM 		}
24177836SJohn.Forte@Sun.COM 		pos += wsize;
24187836SJohn.Forte@Sun.COM 		len -= wsize;
24197836SJohn.Forte@Sun.COM 		daddr += FBA_SIZE(wsize);
24207836SJohn.Forte@Sun.COM 	}
24217836SJohn.Forte@Sun.COM out:
24227836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(ret)) {
24237836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_VOL_FAILED)) {
24247836SJohn.Forte@Sun.COM 			ASSERT(!(rdc_get_vflags(urdc) &
24257836SJohn.Forte@Sun.COM 			    RDC_PRIMARY));
24267836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
24277836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_SYNC_NEEDED);
24287836SJohn.Forte@Sun.COM 			rdc_set_flags_log(urdc, RDC_VOL_FAILED,
24297836SJohn.Forte@Sun.COM 			    "svc write failed");
24307836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
24317836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
24327836SJohn.Forte@Sun.COM 		}
24337836SJohn.Forte@Sun.COM 	} else {
24347836SJohn.Forte@Sun.COM 		/* success */
24357836SJohn.Forte@Sun.COM #ifdef	DEBUG
24367836SJohn.Forte@Sun.COM 		if (rdc_netwrite6) {
24377836SJohn.Forte@Sun.COM 			/*
24387836SJohn.Forte@Sun.COM 			 * This string is used in the ZatoIchi MASNDR
24397836SJohn.Forte@Sun.COM 			 * tests, if you change this, update the test.
24407836SJohn.Forte@Sun.COM 			 */
24419093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!writemaxfba: Write "
24427836SJohn.Forte@Sun.COM 			    "sequence %u", seq);
24437836SJohn.Forte@Sun.COM 		}
24447836SJohn.Forte@Sun.COM #endif
24457836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
24467836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->writes++;
24477836SJohn.Forte@Sun.COM 			KSTAT_IO_PTR(krdc->io_kstats)->nwritten +=
24489093SRamana.Srikanth@Sun.COM 			    FBA_SIZE(kstat_len);
24497836SJohn.Forte@Sun.COM 		}
24507836SJohn.Forte@Sun.COM 	}
24517836SJohn.Forte@Sun.COM 	if (handle)
24527836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(handle);
24537836SJohn.Forte@Sun.COM 	if (reserved)
24547836SJohn.Forte@Sun.COM 		_rdc_rlse_devs(krdc, rtype);
24557836SJohn.Forte@Sun.COM 	return (ret);
24567836SJohn.Forte@Sun.COM }
24577836SJohn.Forte@Sun.COM 
24587836SJohn.Forte@Sun.COM static int
rdc_combywrite(rdc_k_info_t * krdc,nsc_buf_t * handle)24597836SJohn.Forte@Sun.COM rdc_combywrite(rdc_k_info_t *krdc, nsc_buf_t *handle)
24607836SJohn.Forte@Sun.COM {
24617836SJohn.Forte@Sun.COM 	int rsync;
24627836SJohn.Forte@Sun.COM 	int ret;
24637836SJohn.Forte@Sun.COM 	int multiret;
24647836SJohn.Forte@Sun.COM 
24657836SJohn.Forte@Sun.COM 	rsync = -1;
24667836SJohn.Forte@Sun.COM 	ret = 0;
24677836SJohn.Forte@Sun.COM 	/* Handle multihop I/O even on error */
24687836SJohn.Forte@Sun.COM 	if (IS_MULTI(krdc)) {
24697836SJohn.Forte@Sun.COM 		rdc_k_info_t *ktmp;
24707836SJohn.Forte@Sun.COM 		rdc_u_info_t *utmp;
24717836SJohn.Forte@Sun.COM 
24727836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
24737836SJohn.Forte@Sun.COM 		/*
24747836SJohn.Forte@Sun.COM 		 * Find a target primary that is enabled,
24757836SJohn.Forte@Sun.COM 		 * taking account of the fact that this
24767836SJohn.Forte@Sun.COM 		 * could be a multihop secondary
24777836SJohn.Forte@Sun.COM 		 * connected to a 1-to-many primary.
24787836SJohn.Forte@Sun.COM 		 */
24797836SJohn.Forte@Sun.COM 		ktmp = krdc->multi_next;
24807836SJohn.Forte@Sun.COM 		if (ktmp == NULL) {
24817836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
24827836SJohn.Forte@Sun.COM 			goto multi_done;
24837836SJohn.Forte@Sun.COM 		}
24847836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[ktmp->index];
24857836SJohn.Forte@Sun.COM 		do {
24867836SJohn.Forte@Sun.COM 			if ((rdc_get_vflags(utmp) & RDC_PRIMARY)
24877836SJohn.Forte@Sun.COM 			    /* CSTYLED */
24887836SJohn.Forte@Sun.COM 			    && IS_ENABLED(utmp))
24897836SJohn.Forte@Sun.COM 				break;
24907836SJohn.Forte@Sun.COM 
24917836SJohn.Forte@Sun.COM 			ktmp = ktmp->many_next;
24927836SJohn.Forte@Sun.COM 			utmp = &rdc_u_info[ktmp->index];
24937836SJohn.Forte@Sun.COM 		} while (ktmp != krdc->multi_next);
24947836SJohn.Forte@Sun.COM 
24957836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(utmp) & RDC_PRIMARY) ||
24967836SJohn.Forte@Sun.COM 		    !IS_ENABLED(utmp)) {
24977836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
24987836SJohn.Forte@Sun.COM 			goto multi_done;
24997836SJohn.Forte@Sun.COM 		}
25007836SJohn.Forte@Sun.COM 
25017836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
25027836SJohn.Forte@Sun.COM 		rsync = (rdc_get_mflags(utmp) & RDC_SLAVE);
25037836SJohn.Forte@Sun.COM 		if (!rsync) {
25047836SJohn.Forte@Sun.COM 			/* normal case - local io first */
25057836SJohn.Forte@Sun.COM 			ret = nsc_write(handle, handle->sb_pos, handle->sb_len,
25067836SJohn.Forte@Sun.COM 			    0);
25077836SJohn.Forte@Sun.COM 		}
25087836SJohn.Forte@Sun.COM 		multiret = _rdc_multi_write(handle, handle->sb_pos,
25097836SJohn.Forte@Sun.COM 		    handle->sb_len, 0, ktmp);
25107836SJohn.Forte@Sun.COM 		if (!RDC_SUCCESS(multiret)) {
25117836SJohn.Forte@Sun.COM #ifdef DEBUG
25129093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!combywrite: "
25137836SJohn.Forte@Sun.COM 			    "rdc_multi_write failed "
25147836SJohn.Forte@Sun.COM 			    "status %d ret %d",
25157836SJohn.Forte@Sun.COM 			    handle->sb_error, multiret);
25167836SJohn.Forte@Sun.COM #endif
25177836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(utmp) &
25187836SJohn.Forte@Sun.COM 			    RDC_VOL_FAILED)) {
25197836SJohn.Forte@Sun.COM 				rdc_many_enter(ktmp);
25207836SJohn.Forte@Sun.COM 				if (rdc_get_vflags(utmp) &
25217836SJohn.Forte@Sun.COM 				    RDC_PRIMARY) {
25227836SJohn.Forte@Sun.COM 					rdc_set_mflags(utmp,
25237836SJohn.Forte@Sun.COM 					    RDC_RSYNC_NEEDED);
25247836SJohn.Forte@Sun.COM 				} else {
25257836SJohn.Forte@Sun.COM 					rdc_set_flags(utmp,
25267836SJohn.Forte@Sun.COM 					    RDC_SYNC_NEEDED);
25277836SJohn.Forte@Sun.COM 				}
25287836SJohn.Forte@Sun.COM 				rdc_set_flags(utmp,
25297836SJohn.Forte@Sun.COM 				    RDC_VOL_FAILED);
25307836SJohn.Forte@Sun.COM 				rdc_many_exit(ktmp);
25317836SJohn.Forte@Sun.COM 				rdc_write_state(utmp);
25327836SJohn.Forte@Sun.COM 			}
25337836SJohn.Forte@Sun.COM 		}
25347836SJohn.Forte@Sun.COM 	}
25357836SJohn.Forte@Sun.COM 
25367836SJohn.Forte@Sun.COM multi_done:
25377836SJohn.Forte@Sun.COM 	if (rsync != 0) {
25387836SJohn.Forte@Sun.COM 		/*
25397836SJohn.Forte@Sun.COM 		 * Either:
25407836SJohn.Forte@Sun.COM 		 * reverse sync in progress and so we
25417836SJohn.Forte@Sun.COM 		 * need to do the local io after the
25427836SJohn.Forte@Sun.COM 		 * (multihop) secondary io.
25437836SJohn.Forte@Sun.COM 		 * Or:
25447836SJohn.Forte@Sun.COM 		 * no multihop and this is the only io
25457836SJohn.Forte@Sun.COM 		 * required.
25467836SJohn.Forte@Sun.COM 		 */
25477836SJohn.Forte@Sun.COM 		ret = nsc_write(handle, handle->sb_pos, handle->sb_len, 0);
25487836SJohn.Forte@Sun.COM 
25497836SJohn.Forte@Sun.COM 	}
25507836SJohn.Forte@Sun.COM 	return (ret);
25517836SJohn.Forte@Sun.COM }
25527836SJohn.Forte@Sun.COM /*
25537836SJohn.Forte@Sun.COM  * set the pos and len values in the piggyback reply.
25547836SJohn.Forte@Sun.COM  */
25557836SJohn.Forte@Sun.COM static void
rdc_setbitind(int * pendcnt,net_pendvec_t * pvec,rdc_net_dataset_t * dset,uint_t seq,int pindex,int qpos)25567836SJohn.Forte@Sun.COM rdc_setbitind(int *pendcnt, net_pendvec_t *pvec, rdc_net_dataset_t *dset,
25577836SJohn.Forte@Sun.COM     uint_t seq, int pindex, int qpos)
25587836SJohn.Forte@Sun.COM {
25597836SJohn.Forte@Sun.COM 	int pc;
25607836SJohn.Forte@Sun.COM 	ASSERT(*pendcnt < RDC_MAXPENDQ);
25617836SJohn.Forte@Sun.COM 
25627836SJohn.Forte@Sun.COM 	pc = *pendcnt;
25637836SJohn.Forte@Sun.COM 	pvec[pc].seq = seq;
25647836SJohn.Forte@Sun.COM 	pvec[pc].apos = dset->pos;
25657836SJohn.Forte@Sun.COM 	pvec[pc].qpos = qpos;
25667836SJohn.Forte@Sun.COM 	pvec[pc].alen = dset->fbalen;
25677836SJohn.Forte@Sun.COM 	pvec[pc].pindex = pindex;
25687836SJohn.Forte@Sun.COM 	*pendcnt = pc + 1;
256910715SThomas.Atkins@Sun.COM 	DTRACE_PROBE1(pvec_reply, int, seq);
25707836SJohn.Forte@Sun.COM }
25717836SJohn.Forte@Sun.COM 
25727836SJohn.Forte@Sun.COM /*
25737836SJohn.Forte@Sun.COM  * Enters with group->ra_queue.net_qlock held.
25747836SJohn.Forte@Sun.COM  * Tries to construct the return status data for
25757836SJohn.Forte@Sun.COM  * all the pending requests in the sleepq that it can
25767836SJohn.Forte@Sun.COM  * satisfy.
25777836SJohn.Forte@Sun.COM  */
25787836SJohn.Forte@Sun.COM static void
rdc_dopending(rdc_group_t * group,netwriteres * netretp)25797836SJohn.Forte@Sun.COM rdc_dopending(rdc_group_t *group, netwriteres *netretp)
25807836SJohn.Forte@Sun.COM {
25817836SJohn.Forte@Sun.COM 	int pendcnt;
25827836SJohn.Forte@Sun.COM 	net_pendvec_t *pendvec;
25837836SJohn.Forte@Sun.COM 	rdc_sleepq_t *sq;
25847836SJohn.Forte@Sun.COM 	int ret;
25857836SJohn.Forte@Sun.COM 	int pendsz;
25867836SJohn.Forte@Sun.COM 
25877836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&group->ra_queue.net_qlock));
25887836SJohn.Forte@Sun.COM 
25897836SJohn.Forte@Sun.COM 	pendcnt = 0;
25907836SJohn.Forte@Sun.COM 	pendsz = RDC_MAXPENDQ * sizeof (net_pendvec_t);
25917836SJohn.Forte@Sun.COM 	pendvec = kmem_alloc(pendsz, KM_SLEEP);
25927836SJohn.Forte@Sun.COM 
25937836SJohn.Forte@Sun.COM 	/*
25947836SJohn.Forte@Sun.COM 	 * now look at the Q of pending tasks, attempt
25957836SJohn.Forte@Sun.COM 	 * to write any that have been waiting for
25967836SJohn.Forte@Sun.COM 	 * me to complete my write, and piggyback
25977836SJohn.Forte@Sun.COM 	 * their results in my reply, by setiing pendcnt
25987836SJohn.Forte@Sun.COM 	 * to the number of extra requests sucessfully
25997836SJohn.Forte@Sun.COM 	 * processed.
26007836SJohn.Forte@Sun.COM 	 */
26017836SJohn.Forte@Sun.COM 	while (group->sleepq && group->sleepq->seq == group->seq) {
26027836SJohn.Forte@Sun.COM 		rdc_k_info_t		*krdc;
26037836SJohn.Forte@Sun.COM 		rdc_u_info_t		*urdc;
26047836SJohn.Forte@Sun.COM 		struct rdc_net_dataset	*dset;
26057836SJohn.Forte@Sun.COM 
26067836SJohn.Forte@Sun.COM 		sq = group->sleepq;
26077836SJohn.Forte@Sun.COM 		group->sleepq = sq->next;
26087836SJohn.Forte@Sun.COM 		mutex_exit(&group->ra_queue.net_qlock);
26097836SJohn.Forte@Sun.COM 
26107836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[sq->sindex];
26117836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[sq->sindex];
26127836SJohn.Forte@Sun.COM 		if (krdc->io_kstats) {
26137836SJohn.Forte@Sun.COM 			mutex_enter(krdc->io_kstats->ks_lock);
26147836SJohn.Forte@Sun.COM 			kstat_waitq_exit(KSTAT_IO_PTR(krdc->io_kstats));
26157836SJohn.Forte@Sun.COM 			mutex_exit(krdc->io_kstats->ks_lock);
26167836SJohn.Forte@Sun.COM 		}
26177836SJohn.Forte@Sun.COM 
26187836SJohn.Forte@Sun.COM 		dset = rdc_net_get_set(sq->sindex, sq->idx);
26197836SJohn.Forte@Sun.COM 		if (dset == NULL) {
26207836SJohn.Forte@Sun.COM #ifdef	DEBUG
26219093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!pending: %s:%s rdc_net_get_set "
26227836SJohn.Forte@Sun.COM 			    "failed", urdc->secondary.intf,
26237836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
26247836SJohn.Forte@Sun.COM #endif
26257836SJohn.Forte@Sun.COM 			/*
26267836SJohn.Forte@Sun.COM 			 * as we failed to get the pointer, there
26277836SJohn.Forte@Sun.COM 			 * is no point expecting the cleanup
26287836SJohn.Forte@Sun.COM 			 * code in rdc_delsleepq() to get it
26297836SJohn.Forte@Sun.COM 			 * either.
26307836SJohn.Forte@Sun.COM 			 */
26317836SJohn.Forte@Sun.COM 			sq->idx = -1;
26327836SJohn.Forte@Sun.COM 			goto cleansq;
26337836SJohn.Forte@Sun.COM 		}
26347836SJohn.Forte@Sun.COM 		sq->idx = -1;	/* marked as cleaned up */
26357836SJohn.Forte@Sun.COM 
26367836SJohn.Forte@Sun.COM 		ret = rdc_writemaxfba(krdc, urdc, dset, sq->seq, sq->nocache);
26377836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(ret)) {
26387836SJohn.Forte@Sun.COM 			rdc_setbitind(&pendcnt, pendvec, dset,
26397836SJohn.Forte@Sun.COM 			    sq->seq, sq->pindex, sq->qpos);
26407836SJohn.Forte@Sun.COM 		} else {
26419093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!dopending: Write of pending "
26427836SJohn.Forte@Sun.COM 			    "asynchronous task failed, with "
26437836SJohn.Forte@Sun.COM 			    "sequence number %u for SNDR set %s:%s",
26447836SJohn.Forte@Sun.COM 			    sq->seq, urdc->secondary.intf,
26457836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
26467836SJohn.Forte@Sun.COM 		}
26477836SJohn.Forte@Sun.COM 		rdc_net_del_set(sq->sindex, dset);
26487836SJohn.Forte@Sun.COM cleansq:
26497836SJohn.Forte@Sun.COM 		mutex_enter(&group->ra_queue.net_qlock);
26507836SJohn.Forte@Sun.COM 		group->seq = sq->seq + 1;
26517836SJohn.Forte@Sun.COM 		if (group->seq < sq->seq)
26527836SJohn.Forte@Sun.COM 			group->seq = RDC_NEWSEQ + 1;
26537836SJohn.Forte@Sun.COM 		rdc_delsleepq(sq);
26547836SJohn.Forte@Sun.COM 	}
26557836SJohn.Forte@Sun.COM 	mutex_exit(&group->ra_queue.net_qlock);
26567836SJohn.Forte@Sun.COM 	if (pendcnt) {
26577836SJohn.Forte@Sun.COM 		int vecsz;
26587836SJohn.Forte@Sun.COM #ifdef DEBUG
26597836SJohn.Forte@Sun.COM 		if (rdc_netwrite6) {
26609093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!packing pend, count %d", pendcnt);
26617836SJohn.Forte@Sun.COM 		}
26627836SJohn.Forte@Sun.COM #endif
26637836SJohn.Forte@Sun.COM 		vecsz = pendcnt * sizeof (net_pendvec_t);
26647836SJohn.Forte@Sun.COM 		netretp->vecdata.vecdata_val =
26657836SJohn.Forte@Sun.COM 		    kmem_alloc(vecsz, KM_SLEEP);
26667836SJohn.Forte@Sun.COM 		netretp->vecdata.vecdata_len = pendcnt;
26677836SJohn.Forte@Sun.COM 		bcopy(pendvec, netretp->vecdata.vecdata_val, vecsz);
26687836SJohn.Forte@Sun.COM 	}
26697836SJohn.Forte@Sun.COM 	kmem_free(pendvec, pendsz);
26707836SJohn.Forte@Sun.COM 	mutex_enter(&group->ra_queue.net_qlock);
26717836SJohn.Forte@Sun.COM }
26727836SJohn.Forte@Sun.COM 
26737836SJohn.Forte@Sun.COM /*
26747836SJohn.Forte@Sun.COM  * Take the dset and allocate and fill in the vector.
26757836SJohn.Forte@Sun.COM  */
26767836SJohn.Forte@Sun.COM static nsc_vec_t *
rdc_dset2vec(rdc_net_dataset_t * dset)26777836SJohn.Forte@Sun.COM rdc_dset2vec(rdc_net_dataset_t *dset)
26787836SJohn.Forte@Sun.COM {
26797836SJohn.Forte@Sun.COM 	nsc_vec_t *vecret;
26807836SJohn.Forte@Sun.COM 	int i;
26817836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *ditem;
26827836SJohn.Forte@Sun.COM 
26837836SJohn.Forte@Sun.COM 	ASSERT(dset->nitems > 0);
26847836SJohn.Forte@Sun.COM 	ASSERT(dset->head);
26857836SJohn.Forte@Sun.COM 	ASSERT(dset->tail);
26867836SJohn.Forte@Sun.COM 
26877836SJohn.Forte@Sun.COM 	vecret = kmem_alloc((dset->nitems + 1) * sizeof (nsc_vec_t),
26887836SJohn.Forte@Sun.COM 	    KM_NOSLEEP);
26897836SJohn.Forte@Sun.COM 	if (vecret == NULL) {
26907836SJohn.Forte@Sun.COM 		return (NULL);
26917836SJohn.Forte@Sun.COM 	}
26927836SJohn.Forte@Sun.COM 	RDC_DSMEMUSE((dset->nitems + 1) * sizeof (nsc_vec_t));
26937836SJohn.Forte@Sun.COM 	ditem = dset->head;
26947836SJohn.Forte@Sun.COM 	for (i = 0; i < dset->nitems; i++) {
26957836SJohn.Forte@Sun.COM 		ASSERT(ditem);
26967836SJohn.Forte@Sun.COM 		vecret[i].sv_addr = ditem->dptr;
26977836SJohn.Forte@Sun.COM 		vecret[i].sv_len = ditem->len;
26987836SJohn.Forte@Sun.COM 		ditem = ditem->next;
26997836SJohn.Forte@Sun.COM 	}
27007836SJohn.Forte@Sun.COM 	/*
27017836SJohn.Forte@Sun.COM 	 * Null terminate.
27027836SJohn.Forte@Sun.COM 	 */
27037836SJohn.Forte@Sun.COM 	vecret[i].sv_addr = NULL;
27047836SJohn.Forte@Sun.COM 	vecret[i].sv_len = 0;
27057836SJohn.Forte@Sun.COM 	/*
27067836SJohn.Forte@Sun.COM 	 * Check the list and count matches.
27077836SJohn.Forte@Sun.COM 	 */
27087836SJohn.Forte@Sun.COM 	ASSERT(ditem == NULL);
27097836SJohn.Forte@Sun.COM 	return (vecret);
27107836SJohn.Forte@Sun.COM }
27117836SJohn.Forte@Sun.COM 
27127836SJohn.Forte@Sun.COM /*
27137836SJohn.Forte@Sun.COM  * Split the local read into maxfba sized chunks.
27147836SJohn.Forte@Sun.COM  * Returns 0 on an error, or a valid idx on success.
27157836SJohn.Forte@Sun.COM  */
27167836SJohn.Forte@Sun.COM static int
rdc_readmaxfba(int cd,nsc_off_t pos,nsc_size_t fbalen,int nocache)27177836SJohn.Forte@Sun.COM rdc_readmaxfba(int cd, nsc_off_t pos, nsc_size_t fbalen, int nocache)
27187836SJohn.Forte@Sun.COM {
27197836SJohn.Forte@Sun.COM 	int idx;
27207836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
27217836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
27227836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
27237836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *ditem;
27247836SJohn.Forte@Sun.COM 	int rtype;
27257836SJohn.Forte@Sun.COM 	nsc_buf_t *handle;
27267836SJohn.Forte@Sun.COM 	nsc_vec_t veclist[2];
27277836SJohn.Forte@Sun.COM 	int ret;
27287836SJohn.Forte@Sun.COM 	int reserved;
27297836SJohn.Forte@Sun.COM 	nsc_size_t fbaleft;
27307836SJohn.Forte@Sun.COM 	nsc_size_t mfba;
27317836SJohn.Forte@Sun.COM 	nsc_off_t fba;
27327836SJohn.Forte@Sun.COM 	nsc_off_t spos;
27337836SJohn.Forte@Sun.COM 	int eintr_count;
27347836SJohn.Forte@Sun.COM 
27357836SJohn.Forte@Sun.COM 	handle = NULL;
27367836SJohn.Forte@Sun.COM 	idx = 0; /* error status */
27377836SJohn.Forte@Sun.COM 	dset = NULL;
27387836SJohn.Forte@Sun.COM 	ditem = NULL;
27397836SJohn.Forte@Sun.COM 	reserved = 0;
27407836SJohn.Forte@Sun.COM 	ret = 0;
27417836SJohn.Forte@Sun.COM 	mfba = 0;
27427836SJohn.Forte@Sun.COM 
27437836SJohn.Forte@Sun.COM 	rtype = RDC_RAW;
27447836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[cd];
27457836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[cd];
27467836SJohn.Forte@Sun.COM 
27477836SJohn.Forte@Sun.COM 	eintr_count = 0;
27487836SJohn.Forte@Sun.COM 	do {
27497836SJohn.Forte@Sun.COM 		ret = _rdc_rsrv_devs(krdc, rtype, RDC_INTERNAL);
27507836SJohn.Forte@Sun.COM 		if (ret == EINTR) {
27517836SJohn.Forte@Sun.COM 			++eintr_count;
27527836SJohn.Forte@Sun.COM 			delay(2);
27537836SJohn.Forte@Sun.COM 		}
27547836SJohn.Forte@Sun.COM 	} while ((ret == EINTR) && (eintr_count < MAX_EINTR_COUNT));
27557836SJohn.Forte@Sun.COM 	if (ret != 0) {
27567836SJohn.Forte@Sun.COM #ifdef DEBUG
27579093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!readmaxfba: reserve failed on set %s:%s %d",
27587836SJohn.Forte@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file,
27597836SJohn.Forte@Sun.COM 		    ret);
27607836SJohn.Forte@Sun.COM #endif
27617836SJohn.Forte@Sun.COM 		goto out;
27627836SJohn.Forte@Sun.COM 	}
27637836SJohn.Forte@Sun.COM 	reserved = 1;
27647836SJohn.Forte@Sun.COM 	/*
27657836SJohn.Forte@Sun.COM 	 * create a dataset that we can hang all the buffers from.
27667836SJohn.Forte@Sun.COM 	 */
27677836SJohn.Forte@Sun.COM 	dset = rdc_net_add_set(cd);
27687836SJohn.Forte@Sun.COM 	if (dset == NULL) {
27697836SJohn.Forte@Sun.COM #ifdef DEBUG
27709093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!readmaxfba: Unable to allocate dset on set "
27717836SJohn.Forte@Sun.COM 		    "%s:%s", urdc->secondary.intf, urdc->secondary.file);
27727836SJohn.Forte@Sun.COM #endif
27737836SJohn.Forte@Sun.COM 		goto out;
27747836SJohn.Forte@Sun.COM 	}
27757836SJohn.Forte@Sun.COM 	dset->pos = pos;
27767836SJohn.Forte@Sun.COM 	dset->fbalen = fbalen;
27777836SJohn.Forte@Sun.COM 	ret = nsc_maxfbas(RDC_U_FD(krdc), 0, &mfba);
27787836SJohn.Forte@Sun.COM 	if (ret != 0) {
27797836SJohn.Forte@Sun.COM #ifdef DEBUG
27809093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!readmaxfba: msc_maxfbas failed on set %s:%s "
27817836SJohn.Forte@Sun.COM 		    "%d", urdc->secondary.intf,	urdc->secondary.file, ret);
27827836SJohn.Forte@Sun.COM #endif
27837836SJohn.Forte@Sun.COM 		goto out;
27847836SJohn.Forte@Sun.COM 	}
27857836SJohn.Forte@Sun.COM 	spos = pos;
27867836SJohn.Forte@Sun.COM 	fbaleft = fbalen;
27877836SJohn.Forte@Sun.COM 	veclist[1].sv_addr = NULL;
27887836SJohn.Forte@Sun.COM 	veclist[1].sv_len = 0;
27897836SJohn.Forte@Sun.COM 
27907836SJohn.Forte@Sun.COM 	while (fbaleft > 0) {
27917836SJohn.Forte@Sun.COM 		fba = min(mfba, fbaleft);
27927836SJohn.Forte@Sun.COM 		if (handle) {
27937836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(handle);
27947836SJohn.Forte@Sun.COM 			handle = NULL;
27957836SJohn.Forte@Sun.COM 		}
27967836SJohn.Forte@Sun.COM 		ret = nsc_alloc_buf(RDC_U_FD(krdc), spos, fba,
27977836SJohn.Forte@Sun.COM 		    nocache|NSC_NODATA, &handle);
27987836SJohn.Forte@Sun.COM 		if (ret != 0) {
27997836SJohn.Forte@Sun.COM #ifdef DEBUG
28009093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!readmaxfba: alloc failed on set"
28017836SJohn.Forte@Sun.COM 			    "%s:%s %d", urdc->secondary.intf,
28027836SJohn.Forte@Sun.COM 			    urdc->secondary.file, ret);
28037836SJohn.Forte@Sun.COM #endif
28047836SJohn.Forte@Sun.COM 			goto out;
28057836SJohn.Forte@Sun.COM 		}
28067836SJohn.Forte@Sun.COM 		ditem = kmem_alloc(sizeof (rdc_net_dataitem_t), KM_NOSLEEP);
28077836SJohn.Forte@Sun.COM 		if (ditem == NULL) {
28087836SJohn.Forte@Sun.COM 			goto out;
28097836SJohn.Forte@Sun.COM 		}
28107836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(sizeof (rdc_net_dataitem_t));
28117836SJohn.Forte@Sun.COM 		ditem->len = FBA_SIZE(fba);
28127836SJohn.Forte@Sun.COM 		ditem->mlen = ditem->len;
28137836SJohn.Forte@Sun.COM 		ditem->dptr = kmem_alloc(ditem->len, KM_SLEEP);
28147836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(ditem->len);
28157836SJohn.Forte@Sun.COM 		ditem->next = NULL;
28167836SJohn.Forte@Sun.COM 		/*
28177836SJohn.Forte@Sun.COM 		 * construct a vector list
28187836SJohn.Forte@Sun.COM 		 */
28197836SJohn.Forte@Sun.COM 		veclist[0].sv_addr = ditem->dptr;
28207836SJohn.Forte@Sun.COM 		veclist[0].sv_len = ditem->len;
28217836SJohn.Forte@Sun.COM 		handle->sb_vec = veclist;
28227836SJohn.Forte@Sun.COM 		ret = rdc_combyread(krdc, urdc, handle);
28237836SJohn.Forte@Sun.COM 		if (ret != 0) {
28247836SJohn.Forte@Sun.COM 			goto out;
28257836SJohn.Forte@Sun.COM 		}
28267836SJohn.Forte@Sun.COM 		/*
28277836SJohn.Forte@Sun.COM 		 * place on linked list.
28287836SJohn.Forte@Sun.COM 		 */
28297836SJohn.Forte@Sun.COM 		dset->nitems++;
28307836SJohn.Forte@Sun.COM 		if (dset->head == NULL) {
28317836SJohn.Forte@Sun.COM 			dset->head = ditem;
28327836SJohn.Forte@Sun.COM 			dset->tail = ditem;
28337836SJohn.Forte@Sun.COM 		} else {
28347836SJohn.Forte@Sun.COM 			dset->tail->next = ditem;
28357836SJohn.Forte@Sun.COM 			dset->tail = ditem;
28367836SJohn.Forte@Sun.COM 		}
28377836SJohn.Forte@Sun.COM 		/*
28387836SJohn.Forte@Sun.COM 		 * now its linked, clear this so its not freed twice.
28397836SJohn.Forte@Sun.COM 		 */
28407836SJohn.Forte@Sun.COM 		ditem = NULL;
28417836SJohn.Forte@Sun.COM 		fbaleft -= fba;
28427836SJohn.Forte@Sun.COM 		spos += fba;
28437836SJohn.Forte@Sun.COM 	}
28447836SJohn.Forte@Sun.COM 	/*
28457836SJohn.Forte@Sun.COM 	 * all the reads have worked, store the results.
28467836SJohn.Forte@Sun.COM 	 */
28477836SJohn.Forte@Sun.COM 	idx = dset->id;
28487836SJohn.Forte@Sun.COM 	rdc_net_put_set(cd, dset);
28497836SJohn.Forte@Sun.COM 	dset = NULL;
28507836SJohn.Forte@Sun.COM out:
28517836SJohn.Forte@Sun.COM 	if (handle)
28527836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(handle);
28537836SJohn.Forte@Sun.COM 	if (reserved)
28547836SJohn.Forte@Sun.COM 		_rdc_rlse_devs(krdc, rtype);
28557836SJohn.Forte@Sun.COM 	if (dset)
28567836SJohn.Forte@Sun.COM 		rdc_net_del_set(cd, dset);
28577836SJohn.Forte@Sun.COM 	if (ditem) {
28587836SJohn.Forte@Sun.COM 		kmem_free(ditem->dptr, ditem->mlen);
28597836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-ditem->mlen);
28607836SJohn.Forte@Sun.COM 		kmem_free(ditem, sizeof (*ditem));
28617836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-sizeof (*ditem));
28627836SJohn.Forte@Sun.COM 	}
28637836SJohn.Forte@Sun.COM 	return (idx);
28647836SJohn.Forte@Sun.COM }
28657836SJohn.Forte@Sun.COM 
28667836SJohn.Forte@Sun.COM 
28677836SJohn.Forte@Sun.COM /*
28687836SJohn.Forte@Sun.COM  * perform both a local read, and if multihop, a remote read.
28697836SJohn.Forte@Sun.COM  * return 0 on success, or errno on failure.
28707836SJohn.Forte@Sun.COM  */
28717836SJohn.Forte@Sun.COM static int
rdc_combyread(rdc_k_info_t * krdc,rdc_u_info_t * urdc,nsc_buf_t * handle)28727836SJohn.Forte@Sun.COM rdc_combyread(rdc_k_info_t *krdc, rdc_u_info_t *urdc, nsc_buf_t *handle)
28737836SJohn.Forte@Sun.COM {
28747836SJohn.Forte@Sun.COM 	int ret;
28757836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
28767836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
28777836SJohn.Forte@Sun.COM 
28787836SJohn.Forte@Sun.COM 	/*
28797836SJohn.Forte@Sun.COM 	 * read it.
28807836SJohn.Forte@Sun.COM 	 */
28817836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
28827836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
28837836SJohn.Forte@Sun.COM 		kstat_runq_enter(KSTAT_IO_PTR(krdc->io_kstats));
28847836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
28857836SJohn.Forte@Sun.COM 	}
28867836SJohn.Forte@Sun.COM 
28877836SJohn.Forte@Sun.COM 	ret = nsc_read(handle, handle->sb_pos, handle->sb_len, NSC_READ);
28887836SJohn.Forte@Sun.COM 
28897836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
28907836SJohn.Forte@Sun.COM 		mutex_enter(krdc->io_kstats->ks_lock);
28917836SJohn.Forte@Sun.COM 		kstat_runq_exit(KSTAT_IO_PTR(krdc->io_kstats));
28927836SJohn.Forte@Sun.COM 		mutex_exit(krdc->io_kstats->ks_lock);
28937836SJohn.Forte@Sun.COM 	}
28947836SJohn.Forte@Sun.COM 
28957836SJohn.Forte@Sun.COM 	if (ret != 0) {
28967836SJohn.Forte@Sun.COM #ifdef DEBUG
28979093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!combyread: read failed on set %s:%s %d",
28987836SJohn.Forte@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file, ret);
28997836SJohn.Forte@Sun.COM #endif
29007836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_VOL_FAILED)) {
29017836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
29027836SJohn.Forte@Sun.COM 			rdc_set_mflags(urdc, RDC_RSYNC_NEEDED);
29037836SJohn.Forte@Sun.COM 			rdc_set_flags_log(urdc, RDC_VOL_FAILED,
29047836SJohn.Forte@Sun.COM 			    "comby read failed");
29057836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
29067836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
29077836SJohn.Forte@Sun.COM 		}
29087836SJohn.Forte@Sun.COM 		goto out;
29097836SJohn.Forte@Sun.COM 	}
29107836SJohn.Forte@Sun.COM 	if (IS_MULTI(krdc) && (ktmp = krdc->multi_next) &&
29117836SJohn.Forte@Sun.COM 	    (utmp = &rdc_u_info[ktmp->index]) &&
29127836SJohn.Forte@Sun.COM 	    IS_ENABLED(utmp) &&
29137836SJohn.Forte@Sun.COM 	    (rdc_get_mflags(utmp) & RDC_RSYNC_NEEDED)) {
29147836SJohn.Forte@Sun.COM 		ret = _rdc_remote_read(ktmp, handle, handle->sb_pos,
29157836SJohn.Forte@Sun.COM 		    handle->sb_len, NSC_READ);
29167836SJohn.Forte@Sun.COM 		/*
29177836SJohn.Forte@Sun.COM 		 * Set NSC_MIXED so
29187836SJohn.Forte@Sun.COM 		 * that the cache will throw away this
29197836SJohn.Forte@Sun.COM 		 * buffer when we free it since we have
29207836SJohn.Forte@Sun.COM 		 * combined data from multiple sources
29217836SJohn.Forte@Sun.COM 		 * into a single buffer.
29227836SJohn.Forte@Sun.COM 		 * Currently we don't use the cache for
29237836SJohn.Forte@Sun.COM 		 * data volumes, so comment this out.
29247836SJohn.Forte@Sun.COM 		 * handle->sb_flag |= NSC_MIXED;
29257836SJohn.Forte@Sun.COM 		 */
29267836SJohn.Forte@Sun.COM 		if (ret != 0) {
29277836SJohn.Forte@Sun.COM #ifdef DEBUG
29289093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!combyread: remote read failed on "
29297836SJohn.Forte@Sun.COM 			    "set %s:%s %d", utmp->secondary.intf,
29307836SJohn.Forte@Sun.COM 			    utmp->secondary.file, ret);
29317836SJohn.Forte@Sun.COM #endif
29327836SJohn.Forte@Sun.COM 			goto out;
29337836SJohn.Forte@Sun.COM 		}
29347836SJohn.Forte@Sun.COM 	}
29357836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
29367836SJohn.Forte@Sun.COM 		KSTAT_IO_PTR(krdc->io_kstats)->reads++;
29377836SJohn.Forte@Sun.COM 		KSTAT_IO_PTR(krdc->io_kstats)->nread +=
29387836SJohn.Forte@Sun.COM 		    FBA_SIZE(handle->sb_len);
29397836SJohn.Forte@Sun.COM 	}
29407836SJohn.Forte@Sun.COM out:
29417836SJohn.Forte@Sun.COM 	return (ret);
29427836SJohn.Forte@Sun.COM }
29437836SJohn.Forte@Sun.COM 
29447836SJohn.Forte@Sun.COM 
29457836SJohn.Forte@Sun.COM /*
29467836SJohn.Forte@Sun.COM  * remove and free all the collected dsets for this set.
29477836SJohn.Forte@Sun.COM  */
29487836SJohn.Forte@Sun.COM void
rdc_dump_dsets(int index)29497836SJohn.Forte@Sun.COM rdc_dump_dsets(int index)
29507836SJohn.Forte@Sun.COM {
29517836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
29527836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
29537836SJohn.Forte@Sun.COM 
29547836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
29557836SJohn.Forte@Sun.COM tloop:
29567836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->dc_sleep);
29577836SJohn.Forte@Sun.COM 	while ((dset = krdc->net_dataset) != NULL) {
29587836SJohn.Forte@Sun.COM 		if (dset->inuse) {
29597836SJohn.Forte@Sun.COM 			/*
29607836SJohn.Forte@Sun.COM 			 * for the dset to be in use, the
29617836SJohn.Forte@Sun.COM 			 * service routine r_net_write6() must
29627836SJohn.Forte@Sun.COM 			 * be active with it. It will free
29637836SJohn.Forte@Sun.COM 			 * it eventually.
29647836SJohn.Forte@Sun.COM 			 */
29657836SJohn.Forte@Sun.COM 			mutex_exit(&krdc->dc_sleep);
29667836SJohn.Forte@Sun.COM 			delay(5);
29677836SJohn.Forte@Sun.COM 			goto tloop;
29687836SJohn.Forte@Sun.COM 		}
29697836SJohn.Forte@Sun.COM 		/*
29707836SJohn.Forte@Sun.COM 		 * free it.
29717836SJohn.Forte@Sun.COM 		 */
29727836SJohn.Forte@Sun.COM 		rdc_net_free_set(krdc, dset);
29737836SJohn.Forte@Sun.COM 	}
29747836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->dc_sleep);
29757836SJohn.Forte@Sun.COM }
29767836SJohn.Forte@Sun.COM 
29777836SJohn.Forte@Sun.COM #ifdef	DEBUG
29787836SJohn.Forte@Sun.COM void
rdc_stallzero(int flag)29797836SJohn.Forte@Sun.COM rdc_stallzero(int flag)
29807836SJohn.Forte@Sun.COM {
29817836SJohn.Forte@Sun.COM 	static int init = 0;
29827836SJohn.Forte@Sun.COM 	static kcondvar_t cv;
29837836SJohn.Forte@Sun.COM 	static kmutex_t mu;
29847836SJohn.Forte@Sun.COM 
29857836SJohn.Forte@Sun.COM 	if (init == 0) {
29867836SJohn.Forte@Sun.COM 		cv_init(&cv, NULL, CV_DRIVER, NULL);
29877836SJohn.Forte@Sun.COM 		mutex_init(&mu, NULL, MUTEX_DRIVER, NULL);
29887836SJohn.Forte@Sun.COM 		init = 1;
29897836SJohn.Forte@Sun.COM 	}
29907836SJohn.Forte@Sun.COM 
29917836SJohn.Forte@Sun.COM 	mutex_enter(&mu);
29927836SJohn.Forte@Sun.COM 	switch (flag) {
29937836SJohn.Forte@Sun.COM 	case 0:
29947836SJohn.Forte@Sun.COM 		rdc_stall0 = 0;
29957836SJohn.Forte@Sun.COM 		cv_signal(&cv);
29967836SJohn.Forte@Sun.COM 		break;
29977836SJohn.Forte@Sun.COM 	case 1:
29987836SJohn.Forte@Sun.COM 		rdc_stall0 = 1;
29997836SJohn.Forte@Sun.COM 		break;
30007836SJohn.Forte@Sun.COM 	case 2:
30017836SJohn.Forte@Sun.COM 		while (rdc_stall0 == 1)
30027836SJohn.Forte@Sun.COM 			cv_wait(&cv, &mu);
30037836SJohn.Forte@Sun.COM 		break;
30047836SJohn.Forte@Sun.COM 	default:
30057836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC, "Bad flag value passed to rdc_stallzero");
30067836SJohn.Forte@Sun.COM 		break;
30077836SJohn.Forte@Sun.COM 	}
30087836SJohn.Forte@Sun.COM 	mutex_exit(&mu);
30097836SJohn.Forte@Sun.COM }
30107836SJohn.Forte@Sun.COM #endif
30117836SJohn.Forte@Sun.COM 
30127836SJohn.Forte@Sun.COM /*
30137836SJohn.Forte@Sun.COM  * RDC protocol version 5
30147836SJohn.Forte@Sun.COM  */
30157836SJohn.Forte@Sun.COM static rdc_disptab_t rdc_disptab5[] =
30167836SJohn.Forte@Sun.COM {
30177836SJohn.Forte@Sun.COM 	/* PROC			Idempotent */
30187836SJohn.Forte@Sun.COM 	{ r_net_null,		FALSE },
30197836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30207836SJohn.Forte@Sun.COM 	{ r_net_getsize,	FALSE },
30217836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30227836SJohn.Forte@Sun.COM 	{ r_net_write5,		TRUE },
30237836SJohn.Forte@Sun.COM 	{ r_net_read,		FALSE },
30247836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30257836SJohn.Forte@Sun.COM 	{ r_net_state4,		FALSE },
30267836SJohn.Forte@Sun.COM 	{ r_net_ping4,		FALSE },
30277836SJohn.Forte@Sun.COM 	{ r_net_bmap,		FALSE },
30287836SJohn.Forte@Sun.COM 	{ r_net_bdata,		FALSE },
30297836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30307836SJohn.Forte@Sun.COM 	{ r_net_getstate4,	FALSE }
30317836SJohn.Forte@Sun.COM };
30327836SJohn.Forte@Sun.COM 
30337836SJohn.Forte@Sun.COM /*
30347836SJohn.Forte@Sun.COM  * RDC protocol version 6
30357836SJohn.Forte@Sun.COM  */
30367836SJohn.Forte@Sun.COM static rdc_disptab_t rdc_disptab6[] =
30377836SJohn.Forte@Sun.COM {
30387836SJohn.Forte@Sun.COM 	/* PROC			Idempotent */
30397836SJohn.Forte@Sun.COM 	{ r_net_null,		FALSE },
30407836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30417836SJohn.Forte@Sun.COM 	{ r_net_getsize6,	FALSE },
30427836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30437836SJohn.Forte@Sun.COM 	{ r_net_write6,		TRUE },
30447836SJohn.Forte@Sun.COM 	{ r_net_read6,		FALSE },
30457836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30467836SJohn.Forte@Sun.COM 	{ r_net_state4,		FALSE },
30477836SJohn.Forte@Sun.COM 	{ r_net_ping4,		FALSE },
30487836SJohn.Forte@Sun.COM 	{ r_net_bmap6,		FALSE },
30497836SJohn.Forte@Sun.COM 	{ r_net_bdata6,		FALSE },
30507836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30517836SJohn.Forte@Sun.COM 	{ r_net_getstate4,	FALSE }
30527836SJohn.Forte@Sun.COM };
30537836SJohn.Forte@Sun.COM 
30547836SJohn.Forte@Sun.COM /*
30557836SJohn.Forte@Sun.COM  * RDC protocol version 7
30567836SJohn.Forte@Sun.COM  */
30577836SJohn.Forte@Sun.COM static rdc_disptab_t rdc_disptab7[] =
30587836SJohn.Forte@Sun.COM {
30597836SJohn.Forte@Sun.COM 	/* PROC			Idempotent */
30607836SJohn.Forte@Sun.COM 	{ r_net_null,		FALSE },
30617836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30627836SJohn.Forte@Sun.COM 	{ r_net_getsize6,	FALSE },
30637836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30647836SJohn.Forte@Sun.COM 	{ r_net_write6,		TRUE },
30657836SJohn.Forte@Sun.COM 	{ r_net_read6,		FALSE },
30667836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30677836SJohn.Forte@Sun.COM 	{ r_net_state,		FALSE },
30687836SJohn.Forte@Sun.COM 	{ r_net_ping7,		FALSE },
30697836SJohn.Forte@Sun.COM 	{ r_net_bmap6,		FALSE },
30707836SJohn.Forte@Sun.COM 	{ r_net_bdata6,		FALSE },
30717836SJohn.Forte@Sun.COM 	{ rdcsrv_noproc,	FALSE },
30727836SJohn.Forte@Sun.COM 	{ r_net_getstate7,	FALSE }
30737836SJohn.Forte@Sun.COM };
30747836SJohn.Forte@Sun.COM 
30757836SJohn.Forte@Sun.COM static rdcsrv_t rdc_srvtab[] = {
30767836SJohn.Forte@Sun.COM 	{ rdc_disptab5, sizeof (rdc_disptab5) / sizeof (*rdc_disptab5) },
30777836SJohn.Forte@Sun.COM 	{ rdc_disptab6, sizeof (rdc_disptab6) / sizeof (*rdc_disptab6) },
30787836SJohn.Forte@Sun.COM 	{ rdc_disptab7, sizeof (rdc_disptab7) / sizeof (*rdc_disptab7) }
30797836SJohn.Forte@Sun.COM };
30807836SJohn.Forte@Sun.COM 
30817836SJohn.Forte@Sun.COM bool_t
rdc_xdr_netbuf(XDR * xdrs,struct netbuf * objp)30827836SJohn.Forte@Sun.COM rdc_xdr_netbuf(XDR *xdrs, struct netbuf *objp)
30837836SJohn.Forte@Sun.COM {
30847836SJohn.Forte@Sun.COM 	/*
30857836SJohn.Forte@Sun.COM 	 * If we're decoding and the caller has already allocated a buffer,
30867836SJohn.Forte@Sun.COM 	 * throw away maxlen, since it doesn't apply to the caller's
30877836SJohn.Forte@Sun.COM 	 * buffer.  xdr_bytes will return an error if the buffer isn't big
30887836SJohn.Forte@Sun.COM 	 * enough.
30897836SJohn.Forte@Sun.COM 	 */
30907836SJohn.Forte@Sun.COM 	if (xdrs->x_op == XDR_DECODE && objp->buf != NULL) {
30917836SJohn.Forte@Sun.COM 		uint_t maxlen;
30927836SJohn.Forte@Sun.COM 
30937836SJohn.Forte@Sun.COM 		if (!xdr_u_int(xdrs, &maxlen))
30947836SJohn.Forte@Sun.COM 			return (FALSE);
30957836SJohn.Forte@Sun.COM 	} else {
30967836SJohn.Forte@Sun.COM 		if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen))
30977836SJohn.Forte@Sun.COM 			return (FALSE);
30987836SJohn.Forte@Sun.COM 	}
30997836SJohn.Forte@Sun.COM 	return (xdr_bytes(xdrs, (char **)&(objp->buf),
31007836SJohn.Forte@Sun.COM 	    (uint_t *)&(objp->len), objp->maxlen));
31017836SJohn.Forte@Sun.COM }
3102