xref: /onnv-gate/usr/src/uts/common/avs/ns/rdc/rdc_io.c (revision 9093:cd587b0bd19c)
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 /*
22*9093SRamana.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 #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
287836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
297836SJohn.Forte@Sun.COM #include <sys/kmem.h>
307836SJohn.Forte@Sun.COM #include <sys/conf.h>
317836SJohn.Forte@Sun.COM #include <sys/errno.h>
327836SJohn.Forte@Sun.COM 
337836SJohn.Forte@Sun.COM #ifdef _SunOS_5_6
347836SJohn.Forte@Sun.COM /*
357836SJohn.Forte@Sun.COM  * on 2.6 both dki_lock.h and rpc/types.h define bool_t so we
367836SJohn.Forte@Sun.COM  * define enum_t here as it is all we need from rpc/types.h
377836SJohn.Forte@Sun.COM  * anyway and make it look like we included it. Yuck.
387836SJohn.Forte@Sun.COM  */
397836SJohn.Forte@Sun.COM #define	_RPC_TYPES_H
407836SJohn.Forte@Sun.COM typedef int enum_t;
417836SJohn.Forte@Sun.COM #else
427836SJohn.Forte@Sun.COM #ifndef DS_DDICT
437836SJohn.Forte@Sun.COM #include <rpc/types.h>
447836SJohn.Forte@Sun.COM #endif
457836SJohn.Forte@Sun.COM #endif /* _SunOS_5_6 */
467836SJohn.Forte@Sun.COM 
477836SJohn.Forte@Sun.COM #include <sys/ddi.h>
487836SJohn.Forte@Sun.COM 
497836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
507836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
517836SJohn.Forte@Sun.COM 
527836SJohn.Forte@Sun.COM #include <sys/sdt.h>		/* dtrace is S10 or later */
537836SJohn.Forte@Sun.COM 
547836SJohn.Forte@Sun.COM #include "rdc_io.h"
557836SJohn.Forte@Sun.COM #include "rdc_bitmap.h"
567836SJohn.Forte@Sun.COM #include "rdc_update.h"
577836SJohn.Forte@Sun.COM #include "rdc_ioctl.h"
587836SJohn.Forte@Sun.COM #include "rdcsrv.h"
597836SJohn.Forte@Sun.COM #include "rdc_diskq.h"
607836SJohn.Forte@Sun.COM 
617836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
627836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
637836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
647836SJohn.Forte@Sun.COM 
657836SJohn.Forte@Sun.COM volatile int net_exit;
667836SJohn.Forte@Sun.COM nsc_size_t MAX_RDC_FBAS;
677836SJohn.Forte@Sun.COM 
687836SJohn.Forte@Sun.COM #ifdef DEBUG
697836SJohn.Forte@Sun.COM int RDC_MAX_SYNC_THREADS = 8;
707836SJohn.Forte@Sun.COM int rdc_maxthreads_last = 8;
717836SJohn.Forte@Sun.COM #endif
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM kmutex_t rdc_ping_lock;		/* Ping lock */
747836SJohn.Forte@Sun.COM static kmutex_t net_blk_lock;
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM /*
777836SJohn.Forte@Sun.COM  * rdc_conf_lock is used as a global device configuration lock.
787836SJohn.Forte@Sun.COM  * It is also used by enable/resume and disable/suspend code to ensure that
797836SJohn.Forte@Sun.COM  * the transition of an rdc set between configured and unconfigured is
807836SJohn.Forte@Sun.COM  * atomic.
817836SJohn.Forte@Sun.COM  *
827836SJohn.Forte@Sun.COM  * krdc->group->lock is used to protect state changes of a configured rdc
837836SJohn.Forte@Sun.COM  * set (e.g. changes to urdc->flags), such as enabled to disabled and vice
847836SJohn.Forte@Sun.COM  * versa.
857836SJohn.Forte@Sun.COM  *
867836SJohn.Forte@Sun.COM  * rdc_many_lock is also used to protect changes in group membership. A group
877836SJohn.Forte@Sun.COM  * linked list cannot change while this lock is held. The many list and the
887836SJohn.Forte@Sun.COM  * multi-hop list are both protected by rdc_many_lock.
897836SJohn.Forte@Sun.COM  */
907836SJohn.Forte@Sun.COM kmutex_t rdc_conf_lock;
917836SJohn.Forte@Sun.COM kmutex_t rdc_many_lock;			/* Many/multi-list lock */
927836SJohn.Forte@Sun.COM 
937836SJohn.Forte@Sun.COM static kmutex_t rdc_net_hnd_id_lock;	/* Network handle id lock */
947836SJohn.Forte@Sun.COM int rdc_debug = 0;
957836SJohn.Forte@Sun.COM int rdc_debug_sleep = 0;
967836SJohn.Forte@Sun.COM 
977836SJohn.Forte@Sun.COM static int rdc_net_hnd_id = 1;
987836SJohn.Forte@Sun.COM 
997836SJohn.Forte@Sun.COM extern kmutex_t rdc_clnt_lock;
1007836SJohn.Forte@Sun.COM 
1017836SJohn.Forte@Sun.COM static void rdc_ditemsfree(rdc_net_dataset_t *);
1027836SJohn.Forte@Sun.COM void rdc_clnt_destroy(void);
1037836SJohn.Forte@Sun.COM 
1047836SJohn.Forte@Sun.COM rdc_k_info_t *rdc_k_info;
1057836SJohn.Forte@Sun.COM rdc_u_info_t *rdc_u_info;
1067836SJohn.Forte@Sun.COM 
1077836SJohn.Forte@Sun.COM unsigned long rdc_async_timeout;
1087836SJohn.Forte@Sun.COM 
1097836SJohn.Forte@Sun.COM nsc_size_t rdc_maxthres_queue = RDC_MAXTHRES_QUEUE;
1107836SJohn.Forte@Sun.COM int rdc_max_qitems = RDC_MAX_QITEMS;
1117836SJohn.Forte@Sun.COM int rdc_asyncthr = RDC_ASYNCTHR;
1127836SJohn.Forte@Sun.COM static nsc_svc_t *rdc_volume_update;
1137836SJohn.Forte@Sun.COM static int rdc_prealloc_handle = 1;
1147836SJohn.Forte@Sun.COM 
1157836SJohn.Forte@Sun.COM extern int _rdc_rsrv_diskq(rdc_group_t *group);
1167836SJohn.Forte@Sun.COM extern void _rdc_rlse_diskq(rdc_group_t *group);
1177836SJohn.Forte@Sun.COM 
1187836SJohn.Forte@Sun.COM /*
1197836SJohn.Forte@Sun.COM  * Forward declare all statics that are used before defined
1207836SJohn.Forte@Sun.COM  * to enforce parameter checking
1217836SJohn.Forte@Sun.COM  *
1227836SJohn.Forte@Sun.COM  * Some (if not all) of these could be removed if the code were reordered
1237836SJohn.Forte@Sun.COM  */
1247836SJohn.Forte@Sun.COM 
1257836SJohn.Forte@Sun.COM static void rdc_volume_update_svc(intptr_t);
1267836SJohn.Forte@Sun.COM static void halt_sync(rdc_k_info_t *krdc);
1277836SJohn.Forte@Sun.COM void rdc_kstat_create(int index);
1287836SJohn.Forte@Sun.COM void rdc_kstat_delete(int index);
1297836SJohn.Forte@Sun.COM static int rdc_checkforbitmap(int, nsc_off_t);
1307836SJohn.Forte@Sun.COM static int rdc_installbitmap(int, void *, int, nsc_off_t, int, int *, int);
1317836SJohn.Forte@Sun.COM static rdc_group_t *rdc_newgroup();
1327836SJohn.Forte@Sun.COM 
1337836SJohn.Forte@Sun.COM int rdc_enable_diskq(rdc_k_info_t *krdc);
1347836SJohn.Forte@Sun.COM void rdc_close_diskq(rdc_group_t *group);
1357836SJohn.Forte@Sun.COM int rdc_suspend_diskq(rdc_k_info_t *krdc);
1367836SJohn.Forte@Sun.COM int rdc_resume_diskq(rdc_k_info_t *krdc);
1377836SJohn.Forte@Sun.COM void rdc_init_diskq_header(rdc_group_t *grp, dqheader *header);
1387836SJohn.Forte@Sun.COM void rdc_fail_diskq(rdc_k_info_t *krdc, int wait, int dolog);
1397836SJohn.Forte@Sun.COM void rdc_unfail_diskq(rdc_k_info_t *krdc);
1407836SJohn.Forte@Sun.COM void rdc_unintercept_diskq(rdc_group_t *grp);
1417836SJohn.Forte@Sun.COM int rdc_stamp_diskq(rdc_k_info_t *krdc, int rsrvd, int flags);
1427836SJohn.Forte@Sun.COM void rdc_qfiller_thr(rdc_k_info_t *krdc);
1437836SJohn.Forte@Sun.COM 
1447836SJohn.Forte@Sun.COM nstset_t *_rdc_ioset;
1457836SJohn.Forte@Sun.COM nstset_t *_rdc_flset;
1467836SJohn.Forte@Sun.COM 
1477836SJohn.Forte@Sun.COM /*
1487836SJohn.Forte@Sun.COM  * RDC threadset tunables
1497836SJohn.Forte@Sun.COM  */
1507836SJohn.Forte@Sun.COM int rdc_threads = 64;		/* default number of threads */
1517836SJohn.Forte@Sun.COM int rdc_threads_inc = 8;	/* increment for changing the size of the set */
1527836SJohn.Forte@Sun.COM 
1537836SJohn.Forte@Sun.COM /*
1547836SJohn.Forte@Sun.COM  * Private threadset manipulation variables
1557836SJohn.Forte@Sun.COM  */
1567836SJohn.Forte@Sun.COM static int rdc_threads_hysteresis = 2;
1577836SJohn.Forte@Sun.COM 				/* hysteresis for threadset resizing */
1587836SJohn.Forte@Sun.COM static int rdc_sets_active;	/* number of sets currently enabled */
1597836SJohn.Forte@Sun.COM 
1607836SJohn.Forte@Sun.COM #ifdef DEBUG
1617836SJohn.Forte@Sun.COM kmutex_t rdc_cntlock;
1627836SJohn.Forte@Sun.COM #endif
1637836SJohn.Forte@Sun.COM 
1647836SJohn.Forte@Sun.COM /*
1657836SJohn.Forte@Sun.COM  * rdc_thread_deconfigure - rdc is being deconfigured, stop any
1667836SJohn.Forte@Sun.COM  * thread activity.
1677836SJohn.Forte@Sun.COM  *
1687836SJohn.Forte@Sun.COM  * Inherently single-threaded by the Solaris module unloading code.
1697836SJohn.Forte@Sun.COM  */
1707836SJohn.Forte@Sun.COM static void
rdc_thread_deconfigure(void)1717836SJohn.Forte@Sun.COM rdc_thread_deconfigure(void)
1727836SJohn.Forte@Sun.COM {
1737836SJohn.Forte@Sun.COM 	nst_destroy(_rdc_ioset);
1747836SJohn.Forte@Sun.COM 	_rdc_ioset = NULL;
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM 	nst_destroy(_rdc_flset);
1777836SJohn.Forte@Sun.COM 	_rdc_flset = NULL;
1787836SJohn.Forte@Sun.COM 
1797836SJohn.Forte@Sun.COM 	nst_destroy(sync_info.rdc_syncset);
1807836SJohn.Forte@Sun.COM 	sync_info.rdc_syncset = NULL;
1817836SJohn.Forte@Sun.COM }
1827836SJohn.Forte@Sun.COM 
1837836SJohn.Forte@Sun.COM /*
1847836SJohn.Forte@Sun.COM  * rdc_thread_configure - rdc is being configured, initialize the
1857836SJohn.Forte@Sun.COM  * threads we need for flushing aync volumes.
1867836SJohn.Forte@Sun.COM  *
1877836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
1887836SJohn.Forte@Sun.COM  */
1897836SJohn.Forte@Sun.COM static int
rdc_thread_configure(void)1907836SJohn.Forte@Sun.COM rdc_thread_configure(void)
1917836SJohn.Forte@Sun.COM {
1927836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
1937836SJohn.Forte@Sun.COM 
1947836SJohn.Forte@Sun.COM 	if ((_rdc_ioset = nst_init("rdc_thr", rdc_threads)) == NULL)
1957836SJohn.Forte@Sun.COM 		return (EINVAL);
1967836SJohn.Forte@Sun.COM 
1977836SJohn.Forte@Sun.COM 	if ((_rdc_flset = nst_init("rdc_flushthr", 2)) == NULL)
1987836SJohn.Forte@Sun.COM 		return (EINVAL);
1997836SJohn.Forte@Sun.COM 
2007836SJohn.Forte@Sun.COM 	if ((sync_info.rdc_syncset =
2017836SJohn.Forte@Sun.COM 	    nst_init("rdc_syncthr", RDC_MAX_SYNC_THREADS)) == NULL)
2027836SJohn.Forte@Sun.COM 		return (EINVAL);
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 	return (0);
2057836SJohn.Forte@Sun.COM }
2067836SJohn.Forte@Sun.COM 
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM /*
2097836SJohn.Forte@Sun.COM  * rdc_thread_tune - called to tune the size of the rdc threadset.
2107836SJohn.Forte@Sun.COM  *
2117836SJohn.Forte@Sun.COM  * Called from the config code when an rdc_set has been enabled or disabled.
2127836SJohn.Forte@Sun.COM  * 'sets' is the increment to the number of active rdc_sets.
2137836SJohn.Forte@Sun.COM  *
2147836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
2157836SJohn.Forte@Sun.COM  */
2167836SJohn.Forte@Sun.COM static void
rdc_thread_tune(int sets)2177836SJohn.Forte@Sun.COM rdc_thread_tune(int sets)
2187836SJohn.Forte@Sun.COM {
2197836SJohn.Forte@Sun.COM 	int incr = (sets > 0) ? 1 : -1;
2207836SJohn.Forte@Sun.COM 	int change = 0;
2217836SJohn.Forte@Sun.COM 	int nthreads;
2227836SJohn.Forte@Sun.COM 
2237836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
2247836SJohn.Forte@Sun.COM 
2257836SJohn.Forte@Sun.COM 	if (sets < 0)
2267836SJohn.Forte@Sun.COM 		sets = -sets;
2277836SJohn.Forte@Sun.COM 
2287836SJohn.Forte@Sun.COM 	while (sets--) {
2297836SJohn.Forte@Sun.COM 		nthreads = nst_nthread(_rdc_ioset);
2307836SJohn.Forte@Sun.COM 		rdc_sets_active += incr;
2317836SJohn.Forte@Sun.COM 
2327836SJohn.Forte@Sun.COM 		if (rdc_sets_active >= nthreads)
2337836SJohn.Forte@Sun.COM 			change += nst_add_thread(_rdc_ioset, rdc_threads_inc);
2347836SJohn.Forte@Sun.COM 		else if ((rdc_sets_active <
2357836SJohn.Forte@Sun.COM 		    (nthreads - (rdc_threads_inc + rdc_threads_hysteresis))) &&
2367836SJohn.Forte@Sun.COM 		    ((nthreads - rdc_threads_inc) >= rdc_threads))
2377836SJohn.Forte@Sun.COM 			change -= nst_del_thread(_rdc_ioset, rdc_threads_inc);
2387836SJohn.Forte@Sun.COM 	}
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM #ifdef DEBUG
2417836SJohn.Forte@Sun.COM 	if (change) {
242*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_thread_tune: "
243*9093SRamana.Srikanth@Sun.COM 		    "nsets %d, nthreads %d, nthreads change %d",
244*9093SRamana.Srikanth@Sun.COM 		    rdc_sets_active, nst_nthread(_rdc_ioset), change);
2457836SJohn.Forte@Sun.COM 	}
2467836SJohn.Forte@Sun.COM #endif
2477836SJohn.Forte@Sun.COM }
2487836SJohn.Forte@Sun.COM 
2497836SJohn.Forte@Sun.COM 
2507836SJohn.Forte@Sun.COM /*
2517836SJohn.Forte@Sun.COM  * _rdc_unload() - cache is being unloaded,
2527836SJohn.Forte@Sun.COM  * deallocate any dual copy structures allocated during cache
2537836SJohn.Forte@Sun.COM  * loading.
2547836SJohn.Forte@Sun.COM  */
2557836SJohn.Forte@Sun.COM void
_rdc_unload(void)2567836SJohn.Forte@Sun.COM _rdc_unload(void)
2577836SJohn.Forte@Sun.COM {
2587836SJohn.Forte@Sun.COM 	int i;
2597836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM 	if (rdc_volume_update) {
2627836SJohn.Forte@Sun.COM 		(void) nsc_unregister_svc(rdc_volume_update);
2637836SJohn.Forte@Sun.COM 		rdc_volume_update = NULL;
2647836SJohn.Forte@Sun.COM 	}
2657836SJohn.Forte@Sun.COM 
2667836SJohn.Forte@Sun.COM 	rdc_thread_deconfigure();
2677836SJohn.Forte@Sun.COM 
2687836SJohn.Forte@Sun.COM 	if (rdc_k_info != NULL) {
2697836SJohn.Forte@Sun.COM 		for (i = 0; i < rdc_max_sets; i++) {
2707836SJohn.Forte@Sun.COM 			krdc = &rdc_k_info[i];
2717836SJohn.Forte@Sun.COM 			mutex_destroy(&krdc->dc_sleep);
2727836SJohn.Forte@Sun.COM 			mutex_destroy(&krdc->bmapmutex);
2737836SJohn.Forte@Sun.COM 			mutex_destroy(&krdc->kstat_mutex);
2747836SJohn.Forte@Sun.COM 			mutex_destroy(&krdc->bmp_kstat_mutex);
2757836SJohn.Forte@Sun.COM 			mutex_destroy(&krdc->syncbitmutex);
2767836SJohn.Forte@Sun.COM 			cv_destroy(&krdc->busycv);
2777836SJohn.Forte@Sun.COM 			cv_destroy(&krdc->closingcv);
2787836SJohn.Forte@Sun.COM 			cv_destroy(&krdc->haltcv);
2797836SJohn.Forte@Sun.COM 			cv_destroy(&krdc->synccv);
2807836SJohn.Forte@Sun.COM 		}
2817836SJohn.Forte@Sun.COM 	}
2827836SJohn.Forte@Sun.COM 
2837836SJohn.Forte@Sun.COM 	mutex_destroy(&sync_info.lock);
2847836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_ping_lock);
2857836SJohn.Forte@Sun.COM 	mutex_destroy(&net_blk_lock);
2867836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_conf_lock);
2877836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_many_lock);
2887836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_net_hnd_id_lock);
2897836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_clnt_lock);
2907836SJohn.Forte@Sun.COM #ifdef DEBUG
2917836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_cntlock);
2927836SJohn.Forte@Sun.COM #endif
2937836SJohn.Forte@Sun.COM 	net_exit = ATM_EXIT;
2947836SJohn.Forte@Sun.COM 
2957836SJohn.Forte@Sun.COM 	if (rdc_k_info != NULL)
2967836SJohn.Forte@Sun.COM 		kmem_free(rdc_k_info, sizeof (*rdc_k_info) * rdc_max_sets);
2977836SJohn.Forte@Sun.COM 	if (rdc_u_info != NULL)
2987836SJohn.Forte@Sun.COM 		kmem_free(rdc_u_info, sizeof (*rdc_u_info) * rdc_max_sets);
2997836SJohn.Forte@Sun.COM 	rdc_k_info = NULL;
3007836SJohn.Forte@Sun.COM 	rdc_u_info = NULL;
3017836SJohn.Forte@Sun.COM 	rdc_max_sets = 0;
3027836SJohn.Forte@Sun.COM }
3037836SJohn.Forte@Sun.COM 
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM /*
3067836SJohn.Forte@Sun.COM  * _rdc_load() - rdc is being loaded, Allocate anything
3077836SJohn.Forte@Sun.COM  * that will be needed while the cache is loaded but doesn't really
3087836SJohn.Forte@Sun.COM  * depend on configuration parameters.
3097836SJohn.Forte@Sun.COM  *
3107836SJohn.Forte@Sun.COM  */
3117836SJohn.Forte@Sun.COM int
_rdc_load(void)3127836SJohn.Forte@Sun.COM _rdc_load(void)
3137836SJohn.Forte@Sun.COM {
3147836SJohn.Forte@Sun.COM 	int i;
3157836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
3167836SJohn.Forte@Sun.COM 
3177836SJohn.Forte@Sun.COM 	mutex_init(&rdc_ping_lock, NULL, MUTEX_DRIVER, NULL);
3187836SJohn.Forte@Sun.COM 	mutex_init(&net_blk_lock, NULL, MUTEX_DRIVER, NULL);
3197836SJohn.Forte@Sun.COM 	mutex_init(&rdc_conf_lock, NULL, MUTEX_DRIVER, NULL);
3207836SJohn.Forte@Sun.COM 	mutex_init(&rdc_many_lock, NULL, MUTEX_DRIVER, NULL);
3217836SJohn.Forte@Sun.COM 	mutex_init(&rdc_net_hnd_id_lock, NULL, MUTEX_DRIVER, NULL);
3227836SJohn.Forte@Sun.COM 	mutex_init(&rdc_clnt_lock, NULL, MUTEX_DRIVER, NULL);
3237836SJohn.Forte@Sun.COM 	mutex_init(&sync_info.lock, NULL, MUTEX_DRIVER, NULL);
3247836SJohn.Forte@Sun.COM 
3257836SJohn.Forte@Sun.COM #ifdef DEBUG
3267836SJohn.Forte@Sun.COM 	mutex_init(&rdc_cntlock, NULL, MUTEX_DRIVER, NULL);
3277836SJohn.Forte@Sun.COM #endif
3287836SJohn.Forte@Sun.COM 
3297836SJohn.Forte@Sun.COM 	if ((i = nsc_max_devices()) < rdc_max_sets)
3307836SJohn.Forte@Sun.COM 		rdc_max_sets = i;
3317836SJohn.Forte@Sun.COM 	/* following case for partial installs that may fail */
3327836SJohn.Forte@Sun.COM 	if (!rdc_max_sets)
3337836SJohn.Forte@Sun.COM 		rdc_max_sets = 1024;
3347836SJohn.Forte@Sun.COM 
3357836SJohn.Forte@Sun.COM 	rdc_k_info = kmem_zalloc(sizeof (*rdc_k_info) * rdc_max_sets, KM_SLEEP);
3367836SJohn.Forte@Sun.COM 	if (!rdc_k_info)
3377836SJohn.Forte@Sun.COM 		return (ENOMEM);
3387836SJohn.Forte@Sun.COM 
3397836SJohn.Forte@Sun.COM 	rdc_u_info = kmem_zalloc(sizeof (*rdc_u_info) * rdc_max_sets, KM_SLEEP);
3407836SJohn.Forte@Sun.COM 	if (!rdc_u_info) {
3417836SJohn.Forte@Sun.COM 		kmem_free(rdc_k_info, sizeof (*rdc_k_info) * rdc_max_sets);
3427836SJohn.Forte@Sun.COM 		return (ENOMEM);
3437836SJohn.Forte@Sun.COM 	}
3447836SJohn.Forte@Sun.COM 
3457836SJohn.Forte@Sun.COM 	net_exit = ATM_NONE;
3467836SJohn.Forte@Sun.COM 	for (i = 0; i < rdc_max_sets; i++) {
3477836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[i];
3487836SJohn.Forte@Sun.COM 		bzero(krdc, sizeof (*krdc));
3497836SJohn.Forte@Sun.COM 		krdc->index = i;
3507836SJohn.Forte@Sun.COM 		mutex_init(&krdc->dc_sleep, NULL, MUTEX_DRIVER, NULL);
3517836SJohn.Forte@Sun.COM 		mutex_init(&krdc->bmapmutex, NULL, MUTEX_DRIVER, NULL);
3527836SJohn.Forte@Sun.COM 		mutex_init(&krdc->kstat_mutex, NULL, MUTEX_DRIVER, NULL);
3537836SJohn.Forte@Sun.COM 		mutex_init(&krdc->bmp_kstat_mutex, NULL, MUTEX_DRIVER, NULL);
3547836SJohn.Forte@Sun.COM 		mutex_init(&krdc->syncbitmutex, NULL, MUTEX_DRIVER, NULL);
3557836SJohn.Forte@Sun.COM 		cv_init(&krdc->busycv, NULL, CV_DRIVER, NULL);
3567836SJohn.Forte@Sun.COM 		cv_init(&krdc->closingcv, NULL, CV_DRIVER, NULL);
3577836SJohn.Forte@Sun.COM 		cv_init(&krdc->haltcv, NULL, CV_DRIVER, NULL);
3587836SJohn.Forte@Sun.COM 		cv_init(&krdc->synccv, NULL, CV_DRIVER, NULL);
3597836SJohn.Forte@Sun.COM 	}
3607836SJohn.Forte@Sun.COM 
3617836SJohn.Forte@Sun.COM 	rdc_volume_update = nsc_register_svc("RDCVolumeUpdated",
362*9093SRamana.Srikanth@Sun.COM 	    rdc_volume_update_svc);
3637836SJohn.Forte@Sun.COM 
3647836SJohn.Forte@Sun.COM 	return (0);
3657836SJohn.Forte@Sun.COM }
3667836SJohn.Forte@Sun.COM 
3677836SJohn.Forte@Sun.COM static void
rdc_u_init(rdc_u_info_t * urdc)3687836SJohn.Forte@Sun.COM rdc_u_init(rdc_u_info_t *urdc)
3697836SJohn.Forte@Sun.COM {
3707836SJohn.Forte@Sun.COM 	const int index = (int)(urdc - &rdc_u_info[0]);
3717836SJohn.Forte@Sun.COM 
3727836SJohn.Forte@Sun.COM 	if (urdc->secondary.addr.maxlen)
3737836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&urdc->secondary.addr);
3747836SJohn.Forte@Sun.COM 	if (urdc->primary.addr.maxlen)
3757836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&urdc->primary.addr);
3767836SJohn.Forte@Sun.COM 
3777836SJohn.Forte@Sun.COM 	bzero(urdc, sizeof (rdc_u_info_t));
3787836SJohn.Forte@Sun.COM 
3797836SJohn.Forte@Sun.COM 	urdc->index = index;
3807836SJohn.Forte@Sun.COM 	urdc->maxqfbas = rdc_maxthres_queue;
3817836SJohn.Forte@Sun.COM 	urdc->maxqitems = rdc_max_qitems;
3827836SJohn.Forte@Sun.COM 	urdc->asyncthr = rdc_asyncthr;
3837836SJohn.Forte@Sun.COM }
3847836SJohn.Forte@Sun.COM 
3857836SJohn.Forte@Sun.COM /*
3867836SJohn.Forte@Sun.COM  * _rdc_configure() - cache is being configured.
3877836SJohn.Forte@Sun.COM  *
3887836SJohn.Forte@Sun.COM  * Initialize dual copy structures
3897836SJohn.Forte@Sun.COM  */
3907836SJohn.Forte@Sun.COM int
_rdc_configure(void)3917836SJohn.Forte@Sun.COM _rdc_configure(void)
3927836SJohn.Forte@Sun.COM {
3937836SJohn.Forte@Sun.COM 	int index;
3947836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
3957836SJohn.Forte@Sun.COM 
3967836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
3977836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
3987836SJohn.Forte@Sun.COM 
3997836SJohn.Forte@Sun.COM 		krdc->remote_index = -1;
4007836SJohn.Forte@Sun.COM 		krdc->dcio_bitmap = NULL;
4017836SJohn.Forte@Sun.COM 		krdc->bitmap_ref = NULL;
4027836SJohn.Forte@Sun.COM 		krdc->bitmap_size = 0;
4037836SJohn.Forte@Sun.COM 		krdc->bitmap_write = 0;
4047836SJohn.Forte@Sun.COM 		krdc->disk_status = 0;
4057836SJohn.Forte@Sun.COM 		krdc->many_next = krdc;
4067836SJohn.Forte@Sun.COM 
4077836SJohn.Forte@Sun.COM 		rdc_u_init(&rdc_u_info[index]);
4087836SJohn.Forte@Sun.COM 	}
4097836SJohn.Forte@Sun.COM 
4107836SJohn.Forte@Sun.COM 	rdc_async_timeout = 120 * HZ;   /* Seconds * HZ */
4117836SJohn.Forte@Sun.COM 	MAX_RDC_FBAS = FBA_LEN(RDC_MAXDATA);
4127836SJohn.Forte@Sun.COM 	if (net_exit != ATM_INIT) {
4137836SJohn.Forte@Sun.COM 		net_exit = ATM_INIT;
4147836SJohn.Forte@Sun.COM 		return (0);
4157836SJohn.Forte@Sun.COM 	}
4167836SJohn.Forte@Sun.COM 	return (0);
4177836SJohn.Forte@Sun.COM }
4187836SJohn.Forte@Sun.COM 
4197836SJohn.Forte@Sun.COM /*
4207836SJohn.Forte@Sun.COM  * _rdc_deconfigure - rdc is being deconfigured, shut down any
4217836SJohn.Forte@Sun.COM  * dual copy operations and return to an unconfigured state.
4227836SJohn.Forte@Sun.COM  */
4237836SJohn.Forte@Sun.COM void
_rdc_deconfigure(void)4247836SJohn.Forte@Sun.COM _rdc_deconfigure(void)
4257836SJohn.Forte@Sun.COM {
4267836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
4277836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
4287836SJohn.Forte@Sun.COM 	int index;
4297836SJohn.Forte@Sun.COM 
4307836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
4317836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
4327836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
4337836SJohn.Forte@Sun.COM 
4347836SJohn.Forte@Sun.COM 		krdc->remote_index = -1;
4357836SJohn.Forte@Sun.COM 		krdc->dcio_bitmap = NULL;
4367836SJohn.Forte@Sun.COM 		krdc->bitmap_ref = NULL;
4377836SJohn.Forte@Sun.COM 		krdc->bitmap_size = 0;
4387836SJohn.Forte@Sun.COM 		krdc->bitmap_write = 0;
4397836SJohn.Forte@Sun.COM 		krdc->disk_status = 0;
4407836SJohn.Forte@Sun.COM 		krdc->many_next = krdc;
4417836SJohn.Forte@Sun.COM 
4427836SJohn.Forte@Sun.COM 		if (urdc->primary.addr.maxlen)
4437836SJohn.Forte@Sun.COM 			free_rdc_netbuf(&(urdc->primary.addr));
4447836SJohn.Forte@Sun.COM 
4457836SJohn.Forte@Sun.COM 		if (urdc->secondary.addr.maxlen)
4467836SJohn.Forte@Sun.COM 			free_rdc_netbuf(&(urdc->secondary.addr));
4477836SJohn.Forte@Sun.COM 
4487836SJohn.Forte@Sun.COM 		bzero(urdc, sizeof (rdc_u_info_t));
4497836SJohn.Forte@Sun.COM 		urdc->index = index;
4507836SJohn.Forte@Sun.COM 	}
4517836SJohn.Forte@Sun.COM 	net_exit = ATM_EXIT;
4527836SJohn.Forte@Sun.COM 	rdc_clnt_destroy();
4537836SJohn.Forte@Sun.COM 
4547836SJohn.Forte@Sun.COM }
4557836SJohn.Forte@Sun.COM 
4567836SJohn.Forte@Sun.COM 
4577836SJohn.Forte@Sun.COM /*
4587836SJohn.Forte@Sun.COM  * Lock primitives, containing checks that lock ordering isn't broken
4597836SJohn.Forte@Sun.COM  */
4607836SJohn.Forte@Sun.COM /*ARGSUSED*/
4617836SJohn.Forte@Sun.COM void
rdc_many_enter(rdc_k_info_t * krdc)4627836SJohn.Forte@Sun.COM rdc_many_enter(rdc_k_info_t *krdc)
4637836SJohn.Forte@Sun.COM {
4647836SJohn.Forte@Sun.COM 	ASSERT(!MUTEX_HELD(&krdc->bmapmutex));
4657836SJohn.Forte@Sun.COM 
4667836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_many_lock);
4677836SJohn.Forte@Sun.COM }
4687836SJohn.Forte@Sun.COM 
4697836SJohn.Forte@Sun.COM /* ARGSUSED */
4707836SJohn.Forte@Sun.COM void
rdc_many_exit(rdc_k_info_t * krdc)4717836SJohn.Forte@Sun.COM rdc_many_exit(rdc_k_info_t *krdc)
4727836SJohn.Forte@Sun.COM {
4737836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_many_lock);
4747836SJohn.Forte@Sun.COM }
4757836SJohn.Forte@Sun.COM 
4767836SJohn.Forte@Sun.COM void
rdc_group_enter(rdc_k_info_t * krdc)4777836SJohn.Forte@Sun.COM rdc_group_enter(rdc_k_info_t *krdc)
4787836SJohn.Forte@Sun.COM {
4797836SJohn.Forte@Sun.COM 	ASSERT(!MUTEX_HELD(&rdc_many_lock));
4807836SJohn.Forte@Sun.COM 	ASSERT(!MUTEX_HELD(&rdc_conf_lock));
4817836SJohn.Forte@Sun.COM 	ASSERT(!MUTEX_HELD(&krdc->bmapmutex));
4827836SJohn.Forte@Sun.COM 
4837836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->group->lock);
4847836SJohn.Forte@Sun.COM }
4857836SJohn.Forte@Sun.COM 
4867836SJohn.Forte@Sun.COM void
rdc_group_exit(rdc_k_info_t * krdc)4877836SJohn.Forte@Sun.COM rdc_group_exit(rdc_k_info_t *krdc)
4887836SJohn.Forte@Sun.COM {
4897836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->group->lock);
4907836SJohn.Forte@Sun.COM }
4917836SJohn.Forte@Sun.COM 
4927836SJohn.Forte@Sun.COM /*
4937836SJohn.Forte@Sun.COM  * Suspend and disable operations use this function to wait until it is safe
4947836SJohn.Forte@Sun.COM  * to do continue, without trashing data structures used by other ioctls.
4957836SJohn.Forte@Sun.COM  */
4967836SJohn.Forte@Sun.COM static void
wait_busy(rdc_k_info_t * krdc)4977836SJohn.Forte@Sun.COM wait_busy(rdc_k_info_t *krdc)
4987836SJohn.Forte@Sun.COM {
4997836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
5007836SJohn.Forte@Sun.COM 
5017836SJohn.Forte@Sun.COM 	while (krdc->busy_count > 0)
5027836SJohn.Forte@Sun.COM 		cv_wait(&krdc->busycv, &rdc_conf_lock);
5037836SJohn.Forte@Sun.COM }
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 
5067836SJohn.Forte@Sun.COM /*
5077836SJohn.Forte@Sun.COM  * Other ioctls use this function to hold off disable and suspend.
5087836SJohn.Forte@Sun.COM  */
5097836SJohn.Forte@Sun.COM void
set_busy(rdc_k_info_t * krdc)5107836SJohn.Forte@Sun.COM set_busy(rdc_k_info_t *krdc)
5117836SJohn.Forte@Sun.COM {
5127836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
5137836SJohn.Forte@Sun.COM 
5147836SJohn.Forte@Sun.COM 	wait_busy(krdc);
5157836SJohn.Forte@Sun.COM 
5167836SJohn.Forte@Sun.COM 	krdc->busy_count++;
5177836SJohn.Forte@Sun.COM }
5187836SJohn.Forte@Sun.COM 
5197836SJohn.Forte@Sun.COM 
5207836SJohn.Forte@Sun.COM /*
5217836SJohn.Forte@Sun.COM  * Other ioctls use this function to allow disable and suspend to continue.
5227836SJohn.Forte@Sun.COM  */
5237836SJohn.Forte@Sun.COM void
wakeup_busy(rdc_k_info_t * krdc)5247836SJohn.Forte@Sun.COM wakeup_busy(rdc_k_info_t *krdc)
5257836SJohn.Forte@Sun.COM {
5267836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
5277836SJohn.Forte@Sun.COM 
5287836SJohn.Forte@Sun.COM 	if (krdc->busy_count <= 0)
5297836SJohn.Forte@Sun.COM 		return;
5307836SJohn.Forte@Sun.COM 
5317836SJohn.Forte@Sun.COM 	krdc->busy_count--;
5327836SJohn.Forte@Sun.COM 	cv_broadcast(&krdc->busycv);
5337836SJohn.Forte@Sun.COM }
5347836SJohn.Forte@Sun.COM 
5357836SJohn.Forte@Sun.COM 
5367836SJohn.Forte@Sun.COM /*
5377836SJohn.Forte@Sun.COM  * Remove the rdc set from its group, and destroy the group if no longer in
5387836SJohn.Forte@Sun.COM  * use.
5397836SJohn.Forte@Sun.COM  */
5407836SJohn.Forte@Sun.COM static void
remove_from_group(rdc_k_info_t * krdc)5417836SJohn.Forte@Sun.COM remove_from_group(rdc_k_info_t *krdc)
5427836SJohn.Forte@Sun.COM {
5437836SJohn.Forte@Sun.COM 	rdc_k_info_t *p;
5447836SJohn.Forte@Sun.COM 	rdc_group_t *group;
5457836SJohn.Forte@Sun.COM 
5467836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
5477836SJohn.Forte@Sun.COM 
5487836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
5497836SJohn.Forte@Sun.COM 	group = krdc->group;
5507836SJohn.Forte@Sun.COM 
5517836SJohn.Forte@Sun.COM 	group->count--;
5527836SJohn.Forte@Sun.COM 
5537836SJohn.Forte@Sun.COM 	/*
5547836SJohn.Forte@Sun.COM 	 * lock queue while looking at thrnum
5557836SJohn.Forte@Sun.COM 	 */
5567836SJohn.Forte@Sun.COM 	mutex_enter(&group->ra_queue.net_qlock);
5577836SJohn.Forte@Sun.COM 	if ((group->rdc_thrnum == 0) && (group->count == 0)) {
5587836SJohn.Forte@Sun.COM 
5597836SJohn.Forte@Sun.COM 		/*
5607836SJohn.Forte@Sun.COM 		 * Assure the we've stopped and the flusher thread has not
5617836SJohn.Forte@Sun.COM 		 * fallen back to sleep
5627836SJohn.Forte@Sun.COM 		 */
5637836SJohn.Forte@Sun.COM 		if (krdc->group->ra_queue.qfill_sleeping != RDC_QFILL_DEAD) {
5647836SJohn.Forte@Sun.COM 			group->ra_queue.qfflags |= RDC_QFILLSTOP;
5657836SJohn.Forte@Sun.COM 			while (krdc->group->ra_queue.qfflags & RDC_QFILLSTOP) {
5667836SJohn.Forte@Sun.COM 				if (krdc->group->ra_queue.qfill_sleeping ==
5677836SJohn.Forte@Sun.COM 				    RDC_QFILL_ASLEEP)
5687836SJohn.Forte@Sun.COM 					cv_broadcast(&group->ra_queue.qfcv);
5697836SJohn.Forte@Sun.COM 				mutex_exit(&group->ra_queue.net_qlock);
5707836SJohn.Forte@Sun.COM 				delay(2);
5717836SJohn.Forte@Sun.COM 				mutex_enter(&group->ra_queue.net_qlock);
5727836SJohn.Forte@Sun.COM 			}
5737836SJohn.Forte@Sun.COM 		}
5747836SJohn.Forte@Sun.COM 		mutex_exit(&group->ra_queue.net_qlock);
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 		mutex_enter(&group->diskqmutex);
5777836SJohn.Forte@Sun.COM 		rdc_close_diskq(group);
5787836SJohn.Forte@Sun.COM 		mutex_exit(&group->diskqmutex);
5797836SJohn.Forte@Sun.COM 		rdc_delgroup(group);
5807836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
5817836SJohn.Forte@Sun.COM 		krdc->group = NULL;
5827836SJohn.Forte@Sun.COM 		return;
5837836SJohn.Forte@Sun.COM 	}
5847836SJohn.Forte@Sun.COM 	mutex_exit(&group->ra_queue.net_qlock);
5857836SJohn.Forte@Sun.COM 	/*
5867836SJohn.Forte@Sun.COM 	 * Always clear the group field.
5877836SJohn.Forte@Sun.COM 	 * no, you need it set in rdc_flush_memq().
5887836SJohn.Forte@Sun.COM 	 * to call rdc_group_log()
5897836SJohn.Forte@Sun.COM 	 * krdc->group = NULL;
5907836SJohn.Forte@Sun.COM 	 */
5917836SJohn.Forte@Sun.COM 
5927836SJohn.Forte@Sun.COM 	/* Take this rdc structure off the group list */
5937836SJohn.Forte@Sun.COM 
5947836SJohn.Forte@Sun.COM 	for (p = krdc->group_next; p->group_next != krdc; p = p->group_next)
5957836SJohn.Forte@Sun.COM 	;
5967836SJohn.Forte@Sun.COM 	p->group_next = krdc->group_next;
5977836SJohn.Forte@Sun.COM 
5987836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
5997836SJohn.Forte@Sun.COM }
6007836SJohn.Forte@Sun.COM 
6017836SJohn.Forte@Sun.COM 
6027836SJohn.Forte@Sun.COM /*
6037836SJohn.Forte@Sun.COM  * Add the rdc set to its group, setting up a new group if it's the first one.
6047836SJohn.Forte@Sun.COM  */
6057836SJohn.Forte@Sun.COM static int
add_to_group(rdc_k_info_t * krdc,int options,int cmd)6067836SJohn.Forte@Sun.COM add_to_group(rdc_k_info_t *krdc, int options, int cmd)
6077836SJohn.Forte@Sun.COM {
6087836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
6097836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
6107836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
6117836SJohn.Forte@Sun.COM 	int index;
6127836SJohn.Forte@Sun.COM 	rdc_group_t *group;
6137836SJohn.Forte@Sun.COM 	int rc = 0;
6147836SJohn.Forte@Sun.COM 	nsthread_t *trc;
6157836SJohn.Forte@Sun.COM 
6167836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
6177836SJohn.Forte@Sun.COM 
6187836SJohn.Forte@Sun.COM 	/*
6197836SJohn.Forte@Sun.COM 	 * Look for matching group name, primary host name and secondary
6207836SJohn.Forte@Sun.COM 	 * host name.
6217836SJohn.Forte@Sun.COM 	 */
6227836SJohn.Forte@Sun.COM 
6237836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
6247836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
6257836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[index];
6267836SJohn.Forte@Sun.COM 		ktmp = &rdc_k_info[index];
6277836SJohn.Forte@Sun.COM 
6287836SJohn.Forte@Sun.COM 		if (urdc->group_name[0] == 0)
6297836SJohn.Forte@Sun.COM 			break;
6307836SJohn.Forte@Sun.COM 
6317836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(ktmp))
6327836SJohn.Forte@Sun.COM 			continue;
6337836SJohn.Forte@Sun.COM 
6347836SJohn.Forte@Sun.COM 		if (strncmp(utmp->group_name, urdc->group_name,
6357836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) != 0)
6367836SJohn.Forte@Sun.COM 			continue;
6377836SJohn.Forte@Sun.COM 		if (strncmp(utmp->primary.intf, urdc->primary.intf,
6387836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0) {
6397836SJohn.Forte@Sun.COM 			/* Same group name, different primary interface */
6407836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
6417836SJohn.Forte@Sun.COM 			return (-1);
6427836SJohn.Forte@Sun.COM 		}
6437836SJohn.Forte@Sun.COM 		if (strncmp(utmp->secondary.intf, urdc->secondary.intf,
6447836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0) {
6457836SJohn.Forte@Sun.COM 			/* Same group name, different secondary interface */
6467836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
6477836SJohn.Forte@Sun.COM 			return (-1);
6487836SJohn.Forte@Sun.COM 		}
6497836SJohn.Forte@Sun.COM 
6507836SJohn.Forte@Sun.COM 		/* Group already exists, so add this set to the group */
6517836SJohn.Forte@Sun.COM 
6527836SJohn.Forte@Sun.COM 		if (((options & RDC_OPT_ASYNC) == 0) &&
6537836SJohn.Forte@Sun.COM 		    ((ktmp->type_flag & RDC_ASYNCMODE) != 0)) {
6547836SJohn.Forte@Sun.COM 			/* Must be same mode as existing group members */
6557836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
6567836SJohn.Forte@Sun.COM 			return (-1);
6577836SJohn.Forte@Sun.COM 		}
6587836SJohn.Forte@Sun.COM 		if (((options & RDC_OPT_ASYNC) != 0) &&
6597836SJohn.Forte@Sun.COM 		    ((ktmp->type_flag & RDC_ASYNCMODE) == 0)) {
6607836SJohn.Forte@Sun.COM 			/* Must be same mode as existing group members */
6617836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
6627836SJohn.Forte@Sun.COM 			return (-1);
6637836SJohn.Forte@Sun.COM 		}
6647836SJohn.Forte@Sun.COM 
6657836SJohn.Forte@Sun.COM 		/* cannont reconfigure existing group into new queue this way */
6667836SJohn.Forte@Sun.COM 		if ((cmd != RDC_CMD_RESUME) &&
6677836SJohn.Forte@Sun.COM 		    !RDC_IS_DISKQ(ktmp->group) && urdc->disk_queue[0] != '\0') {
6687836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
6697836SJohn.Forte@Sun.COM 			return (RDC_EQNOADD);
6707836SJohn.Forte@Sun.COM 		}
6717836SJohn.Forte@Sun.COM 
6727836SJohn.Forte@Sun.COM 		ktmp->group->count++;
6737836SJohn.Forte@Sun.COM 		krdc->group = ktmp->group;
6747836SJohn.Forte@Sun.COM 		krdc->group_next = ktmp->group_next;
6757836SJohn.Forte@Sun.COM 		ktmp->group_next = krdc;
6767836SJohn.Forte@Sun.COM 
6777836SJohn.Forte@Sun.COM 		urdc->autosync = utmp->autosync;	/* Same as rest */
6787836SJohn.Forte@Sun.COM 
6797836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->disk_queue, utmp->disk_queue, NSC_MAXPATH);
6807836SJohn.Forte@Sun.COM 
6817836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
6827836SJohn.Forte@Sun.COM 		return (0);
6837836SJohn.Forte@Sun.COM 	}
6847836SJohn.Forte@Sun.COM 
6857836SJohn.Forte@Sun.COM 	/* This must be a new group */
6867836SJohn.Forte@Sun.COM 	group = rdc_newgroup();
6877836SJohn.Forte@Sun.COM 	krdc->group = group;
6887836SJohn.Forte@Sun.COM 	krdc->group_next = krdc;
6897836SJohn.Forte@Sun.COM 	urdc->autosync = -1;	/* Unknown */
6907836SJohn.Forte@Sun.COM 
6917836SJohn.Forte@Sun.COM 	/*
6927836SJohn.Forte@Sun.COM 	 * Tune the thread set by one for each thread created
6937836SJohn.Forte@Sun.COM 	 */
6947836SJohn.Forte@Sun.COM 	rdc_thread_tune(1);
6957836SJohn.Forte@Sun.COM 
6967836SJohn.Forte@Sun.COM 	trc = nst_create(_rdc_ioset, rdc_qfiller_thr, (void *)krdc, NST_SLEEP);
6977836SJohn.Forte@Sun.COM 	if (trc == NULL) {
6987836SJohn.Forte@Sun.COM 		rc = -1;
699*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!unable to create queue filler daemon");
7007836SJohn.Forte@Sun.COM 		goto fail;
7017836SJohn.Forte@Sun.COM 	}
7027836SJohn.Forte@Sun.COM 
7037836SJohn.Forte@Sun.COM 	if (urdc->disk_queue[0] == '\0') {
7047836SJohn.Forte@Sun.COM 		krdc->group->flags |= RDC_MEMQUE;
7057836SJohn.Forte@Sun.COM 	} else {
7067836SJohn.Forte@Sun.COM 		krdc->group->flags |= RDC_DISKQUE;
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM 		/* XXX check here for resume or enable and act accordingly */
7097836SJohn.Forte@Sun.COM 
7107836SJohn.Forte@Sun.COM 		if (cmd == RDC_CMD_RESUME) {
7117836SJohn.Forte@Sun.COM 			rc = rdc_resume_diskq(krdc);
7127836SJohn.Forte@Sun.COM 
7137836SJohn.Forte@Sun.COM 		} else if (cmd == RDC_CMD_ENABLE) {
7147836SJohn.Forte@Sun.COM 			rc = rdc_enable_diskq(krdc);
7157836SJohn.Forte@Sun.COM 			if ((rc == RDC_EQNOADD) && (cmd != RDC_CMD_ENABLE)) {
716*9093SRamana.Srikanth@Sun.COM 				cmn_err(CE_WARN, "!disk queue %s enable failed,"
7177836SJohn.Forte@Sun.COM 				    " enabling memory queue",
7187836SJohn.Forte@Sun.COM 				    urdc->disk_queue);
7197836SJohn.Forte@Sun.COM 				krdc->group->flags &= ~RDC_DISKQUE;
7207836SJohn.Forte@Sun.COM 				krdc->group->flags |= RDC_MEMQUE;
7217836SJohn.Forte@Sun.COM 				bzero(urdc->disk_queue, NSC_MAXPATH);
7227836SJohn.Forte@Sun.COM 			}
7237836SJohn.Forte@Sun.COM 		}
7247836SJohn.Forte@Sun.COM 	}
7257836SJohn.Forte@Sun.COM fail:
7267836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
7277836SJohn.Forte@Sun.COM 	return (rc);
7287836SJohn.Forte@Sun.COM }
7297836SJohn.Forte@Sun.COM 
7307836SJohn.Forte@Sun.COM 
7317836SJohn.Forte@Sun.COM /*
7327836SJohn.Forte@Sun.COM  * Move the set to a new group if possible
7337836SJohn.Forte@Sun.COM  */
7347836SJohn.Forte@Sun.COM static int
change_group(rdc_k_info_t * krdc,int options)7357836SJohn.Forte@Sun.COM change_group(rdc_k_info_t *krdc, int options)
7367836SJohn.Forte@Sun.COM {
7377836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
7387836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
7397836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
7407836SJohn.Forte@Sun.COM 	rdc_k_info_t *next;
7417836SJohn.Forte@Sun.COM 	char tmpq[NSC_MAXPATH];
7427836SJohn.Forte@Sun.COM 	int index;
7437836SJohn.Forte@Sun.COM 	int rc = -1;
7447836SJohn.Forte@Sun.COM 	rdc_group_t *group, *old_group;
7457836SJohn.Forte@Sun.COM 	nsthread_t *trc;
7467836SJohn.Forte@Sun.COM 
7477836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
7487836SJohn.Forte@Sun.COM 
7497836SJohn.Forte@Sun.COM 	/*
7507836SJohn.Forte@Sun.COM 	 * Look for matching group name, primary host name and secondary
7517836SJohn.Forte@Sun.COM 	 * host name.
7527836SJohn.Forte@Sun.COM 	 */
7537836SJohn.Forte@Sun.COM 
7547836SJohn.Forte@Sun.COM 	bzero(&tmpq, sizeof (tmpq));
7557836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
7567836SJohn.Forte@Sun.COM 
7577836SJohn.Forte@Sun.COM 	old_group = krdc->group;
7587836SJohn.Forte@Sun.COM 	next = krdc->group_next;
7597836SJohn.Forte@Sun.COM 
7607836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(old_group)) { /* can't keep your own queue */
7617836SJohn.Forte@Sun.COM 		(void) strncpy(tmpq, urdc->disk_queue, NSC_MAXPATH);
7627836SJohn.Forte@Sun.COM 		bzero(urdc->disk_queue, sizeof (urdc->disk_queue));
7637836SJohn.Forte@Sun.COM 	}
7647836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
7657836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[index];
7667836SJohn.Forte@Sun.COM 		ktmp = &rdc_k_info[index];
7677836SJohn.Forte@Sun.COM 
7687836SJohn.Forte@Sun.COM 		if (ktmp == krdc)
7697836SJohn.Forte@Sun.COM 			continue;
7707836SJohn.Forte@Sun.COM 
7717836SJohn.Forte@Sun.COM 		if (urdc->group_name[0] == 0)
7727836SJohn.Forte@Sun.COM 			break;
7737836SJohn.Forte@Sun.COM 
7747836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(ktmp))
7757836SJohn.Forte@Sun.COM 			continue;
7767836SJohn.Forte@Sun.COM 
7777836SJohn.Forte@Sun.COM 		if (strncmp(utmp->group_name, urdc->group_name,
7787836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) != 0)
7797836SJohn.Forte@Sun.COM 			continue;
7807836SJohn.Forte@Sun.COM 		if (strncmp(utmp->primary.intf, urdc->primary.intf,
7817836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0)
7827836SJohn.Forte@Sun.COM 			goto bad;
7837836SJohn.Forte@Sun.COM 		if (strncmp(utmp->secondary.intf, urdc->secondary.intf,
7847836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0)
7857836SJohn.Forte@Sun.COM 			goto bad;
7867836SJohn.Forte@Sun.COM 
7877836SJohn.Forte@Sun.COM 		/* Group already exists, so add this set to the group */
7887836SJohn.Forte@Sun.COM 
7897836SJohn.Forte@Sun.COM 		if (((options & RDC_OPT_ASYNC) == 0) &&
7907836SJohn.Forte@Sun.COM 		    ((ktmp->type_flag & RDC_ASYNCMODE) != 0)) {
7917836SJohn.Forte@Sun.COM 			/* Must be same mode as existing group members */
7927836SJohn.Forte@Sun.COM 			goto bad;
7937836SJohn.Forte@Sun.COM 		}
7947836SJohn.Forte@Sun.COM 		if (((options & RDC_OPT_ASYNC) != 0) &&
7957836SJohn.Forte@Sun.COM 		    ((ktmp->type_flag & RDC_ASYNCMODE) == 0)) {
7967836SJohn.Forte@Sun.COM 			/* Must be same mode as existing group members */
7977836SJohn.Forte@Sun.COM 			goto bad;
7987836SJohn.Forte@Sun.COM 		}
7997836SJohn.Forte@Sun.COM 
8007836SJohn.Forte@Sun.COM 		ktmp->group->count++;
8017836SJohn.Forte@Sun.COM 		krdc->group = ktmp->group;
8027836SJohn.Forte@Sun.COM 		krdc->group_next = ktmp->group_next;
8037836SJohn.Forte@Sun.COM 		ktmp->group_next = krdc;
8047836SJohn.Forte@Sun.COM 		bzero(urdc->disk_queue, sizeof (urdc->disk_queue));
8057836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->disk_queue, utmp->disk_queue, NSC_MAXPATH);
8067836SJohn.Forte@Sun.COM 
8077836SJohn.Forte@Sun.COM 		goto good;
8087836SJohn.Forte@Sun.COM 	}
8097836SJohn.Forte@Sun.COM 
8107836SJohn.Forte@Sun.COM 	/* This must be a new group */
8117836SJohn.Forte@Sun.COM 	group = rdc_newgroup();
8127836SJohn.Forte@Sun.COM 	krdc->group = group;
8137836SJohn.Forte@Sun.COM 	krdc->group_next = krdc;
8147836SJohn.Forte@Sun.COM 
8157836SJohn.Forte@Sun.COM 	trc = nst_create(_rdc_ioset, rdc_qfiller_thr, (void *)krdc, NST_SLEEP);
8167836SJohn.Forte@Sun.COM 	if (trc == NULL) {
8177836SJohn.Forte@Sun.COM 		rc = -1;
818*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!unable to create queue filler daemon");
8197836SJohn.Forte@Sun.COM 		goto bad;
8207836SJohn.Forte@Sun.COM 	}
8217836SJohn.Forte@Sun.COM 
8227836SJohn.Forte@Sun.COM 	if (urdc->disk_queue[0] == 0) {
8237836SJohn.Forte@Sun.COM 		krdc->group->flags |= RDC_MEMQUE;
8247836SJohn.Forte@Sun.COM 	} else {
8257836SJohn.Forte@Sun.COM 		krdc->group->flags |= RDC_DISKQUE;
8267836SJohn.Forte@Sun.COM 		if ((rc = rdc_enable_diskq(krdc)) < 0)
8277836SJohn.Forte@Sun.COM 			goto bad;
8287836SJohn.Forte@Sun.COM 	}
8297836SJohn.Forte@Sun.COM good:
8307836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_ASYNC) {
8317836SJohn.Forte@Sun.COM 		krdc->type_flag |= RDC_ASYNCMODE;
8327836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_ASYNC);
8337836SJohn.Forte@Sun.COM 	} else {
8347836SJohn.Forte@Sun.COM 		krdc->type_flag &= ~RDC_ASYNCMODE;
8357836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_ASYNC);
8367836SJohn.Forte@Sun.COM 	}
8377836SJohn.Forte@Sun.COM 
8387836SJohn.Forte@Sun.COM 	old_group->count--;
8397836SJohn.Forte@Sun.COM 	if (!old_group->rdc_writer && old_group->count == 0) {
8407836SJohn.Forte@Sun.COM 		/* Group now empty, so destroy */
8417836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(old_group)) {
8427836SJohn.Forte@Sun.COM 			rdc_unintercept_diskq(old_group);
8437836SJohn.Forte@Sun.COM 			mutex_enter(&old_group->diskqmutex);
8447836SJohn.Forte@Sun.COM 			rdc_close_diskq(old_group);
8457836SJohn.Forte@Sun.COM 			mutex_exit(&old_group->diskqmutex);
8467836SJohn.Forte@Sun.COM 		}
8477836SJohn.Forte@Sun.COM 
8487836SJohn.Forte@Sun.COM 		mutex_enter(&old_group->ra_queue.net_qlock);
8497836SJohn.Forte@Sun.COM 
8507836SJohn.Forte@Sun.COM 		/*
8517836SJohn.Forte@Sun.COM 		 * Assure the we've stopped and the flusher thread has not
8527836SJohn.Forte@Sun.COM 		 * fallen back to sleep
8537836SJohn.Forte@Sun.COM 		 */
8547836SJohn.Forte@Sun.COM 		if (old_group->ra_queue.qfill_sleeping != RDC_QFILL_DEAD) {
8557836SJohn.Forte@Sun.COM 			old_group->ra_queue.qfflags |= RDC_QFILLSTOP;
8567836SJohn.Forte@Sun.COM 			while (old_group->ra_queue.qfflags & RDC_QFILLSTOP) {
8577836SJohn.Forte@Sun.COM 				if (old_group->ra_queue.qfill_sleeping ==
8587836SJohn.Forte@Sun.COM 				    RDC_QFILL_ASLEEP)
8597836SJohn.Forte@Sun.COM 					cv_broadcast(&old_group->ra_queue.qfcv);
8607836SJohn.Forte@Sun.COM 				mutex_exit(&old_group->ra_queue.net_qlock);
8617836SJohn.Forte@Sun.COM 				delay(2);
8627836SJohn.Forte@Sun.COM 				mutex_enter(&old_group->ra_queue.net_qlock);
8637836SJohn.Forte@Sun.COM 			}
8647836SJohn.Forte@Sun.COM 		}
8657836SJohn.Forte@Sun.COM 		mutex_exit(&old_group->ra_queue.net_qlock);
8667836SJohn.Forte@Sun.COM 
8677836SJohn.Forte@Sun.COM 		rdc_delgroup(old_group);
8687836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
8697836SJohn.Forte@Sun.COM 		return (0);
8707836SJohn.Forte@Sun.COM 	}
8717836SJohn.Forte@Sun.COM 
8727836SJohn.Forte@Sun.COM 	/* Take this rdc structure off the old group list */
8737836SJohn.Forte@Sun.COM 
8747836SJohn.Forte@Sun.COM 	for (ktmp = next; ktmp->group_next != krdc; ktmp = ktmp->group_next)
8757836SJohn.Forte@Sun.COM 	;
8767836SJohn.Forte@Sun.COM 	ktmp->group_next = next;
8777836SJohn.Forte@Sun.COM 
8787836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
8797836SJohn.Forte@Sun.COM 	return (0);
8807836SJohn.Forte@Sun.COM 
8817836SJohn.Forte@Sun.COM bad:
8827836SJohn.Forte@Sun.COM 	/* Leave existing group status alone */
8837836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->disk_queue, tmpq, NSC_MAXPATH);
8847836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
8857836SJohn.Forte@Sun.COM 	return (rc);
8867836SJohn.Forte@Sun.COM }
8877836SJohn.Forte@Sun.COM 
8887836SJohn.Forte@Sun.COM 
8897836SJohn.Forte@Sun.COM /*
8907836SJohn.Forte@Sun.COM  * Set flags for an rdc set, setting the group flags as necessary.
8917836SJohn.Forte@Sun.COM  */
8927836SJohn.Forte@Sun.COM void
rdc_set_flags(rdc_u_info_t * urdc,int flags)8937836SJohn.Forte@Sun.COM rdc_set_flags(rdc_u_info_t *urdc, int flags)
8947836SJohn.Forte@Sun.COM {
8957836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
8967836SJohn.Forte@Sun.COM 	int vflags, sflags, bflags, ssflags;
8977836SJohn.Forte@Sun.COM 
8987836SJohn.Forte@Sun.COM 	DTRACE_PROBE2(rdc_set_flags, int, krdc->index, int, flags);
8997836SJohn.Forte@Sun.COM 	vflags = flags & RDC_VFLAGS;
9007836SJohn.Forte@Sun.COM 	sflags = flags & RDC_SFLAGS;
9017836SJohn.Forte@Sun.COM 	bflags = flags & RDC_BFLAGS;
9027836SJohn.Forte@Sun.COM 	ssflags = flags & RDC_SYNC_STATE_FLAGS;
9037836SJohn.Forte@Sun.COM 
9047836SJohn.Forte@Sun.COM 	if (vflags) {
9057836SJohn.Forte@Sun.COM 		/* normal volume flags */
9067836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&rdc_conf_lock) ||
9077836SJohn.Forte@Sun.COM 		    MUTEX_HELD(&krdc->group->lock));
9087836SJohn.Forte@Sun.COM 		if (ssflags)
9097836SJohn.Forte@Sun.COM 			mutex_enter(&krdc->bmapmutex);
9107836SJohn.Forte@Sun.COM 
9117836SJohn.Forte@Sun.COM 		urdc->flags |= vflags;
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 		if (ssflags)
9147836SJohn.Forte@Sun.COM 			mutex_exit(&krdc->bmapmutex);
9157836SJohn.Forte@Sun.COM 	}
9167836SJohn.Forte@Sun.COM 
9177836SJohn.Forte@Sun.COM 	if (sflags) {
9187836SJohn.Forte@Sun.COM 		/* Sync state flags that are protected by a different lock */
9197836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&rdc_many_lock));
9207836SJohn.Forte@Sun.COM 		urdc->sync_flags |= sflags;
9217836SJohn.Forte@Sun.COM 	}
9227836SJohn.Forte@Sun.COM 
9237836SJohn.Forte@Sun.COM 	if (bflags) {
9247836SJohn.Forte@Sun.COM 		/* Bmap state flags that are protected by a different lock */
9257836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&krdc->bmapmutex));
9267836SJohn.Forte@Sun.COM 		urdc->bmap_flags |= bflags;
9277836SJohn.Forte@Sun.COM 	}
9287836SJohn.Forte@Sun.COM 
9297836SJohn.Forte@Sun.COM }
9307836SJohn.Forte@Sun.COM 
9317836SJohn.Forte@Sun.COM 
9327836SJohn.Forte@Sun.COM /*
9337836SJohn.Forte@Sun.COM  * Clear flags for an rdc set, clearing the group flags as necessary.
9347836SJohn.Forte@Sun.COM  */
9357836SJohn.Forte@Sun.COM void
rdc_clr_flags(rdc_u_info_t * urdc,int flags)9367836SJohn.Forte@Sun.COM rdc_clr_flags(rdc_u_info_t *urdc, int flags)
9377836SJohn.Forte@Sun.COM {
9387836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
9397836SJohn.Forte@Sun.COM 	int vflags, sflags, bflags;
9407836SJohn.Forte@Sun.COM 
9417836SJohn.Forte@Sun.COM 	DTRACE_PROBE2(rdc_clr_flags, int, krdc->index, int, flags);
9427836SJohn.Forte@Sun.COM 	vflags = flags & RDC_VFLAGS;
9437836SJohn.Forte@Sun.COM 	sflags = flags & RDC_SFLAGS;
9447836SJohn.Forte@Sun.COM 	bflags = flags & RDC_BFLAGS;
9457836SJohn.Forte@Sun.COM 
9467836SJohn.Forte@Sun.COM 	if (vflags) {
9477836SJohn.Forte@Sun.COM 		/* normal volume flags */
9487836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&rdc_conf_lock) ||
9497836SJohn.Forte@Sun.COM 		    MUTEX_HELD(&krdc->group->lock));
9507836SJohn.Forte@Sun.COM 		urdc->flags &= ~vflags;
9517836SJohn.Forte@Sun.COM 
9527836SJohn.Forte@Sun.COM 	}
9537836SJohn.Forte@Sun.COM 
9547836SJohn.Forte@Sun.COM 	if (sflags) {
9557836SJohn.Forte@Sun.COM 		/* Sync state flags that are protected by a different lock */
9567836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&rdc_many_lock));
9577836SJohn.Forte@Sun.COM 		urdc->sync_flags &= ~sflags;
9587836SJohn.Forte@Sun.COM 	}
9597836SJohn.Forte@Sun.COM 
9607836SJohn.Forte@Sun.COM 	if (bflags) {
9617836SJohn.Forte@Sun.COM 		/* Bmap state flags that are protected by a different lock */
9627836SJohn.Forte@Sun.COM 		ASSERT(MUTEX_HELD(&krdc->bmapmutex));
9637836SJohn.Forte@Sun.COM 		urdc->bmap_flags &= ~bflags;
9647836SJohn.Forte@Sun.COM 	}
9657836SJohn.Forte@Sun.COM }
9667836SJohn.Forte@Sun.COM 
9677836SJohn.Forte@Sun.COM 
9687836SJohn.Forte@Sun.COM /*
9697836SJohn.Forte@Sun.COM  * Get the flags for an rdc set.
9707836SJohn.Forte@Sun.COM  */
9717836SJohn.Forte@Sun.COM int
rdc_get_vflags(rdc_u_info_t * urdc)9727836SJohn.Forte@Sun.COM rdc_get_vflags(rdc_u_info_t *urdc)
9737836SJohn.Forte@Sun.COM {
9747836SJohn.Forte@Sun.COM 	return (urdc->flags | urdc->sync_flags | urdc->bmap_flags);
9757836SJohn.Forte@Sun.COM }
9767836SJohn.Forte@Sun.COM 
9777836SJohn.Forte@Sun.COM 
9787836SJohn.Forte@Sun.COM /*
9797836SJohn.Forte@Sun.COM  * Initialise flags for an rdc set.
9807836SJohn.Forte@Sun.COM  */
9817836SJohn.Forte@Sun.COM static void
rdc_init_flags(rdc_u_info_t * urdc)9827836SJohn.Forte@Sun.COM rdc_init_flags(rdc_u_info_t *urdc)
9837836SJohn.Forte@Sun.COM {
9847836SJohn.Forte@Sun.COM 	urdc->flags = 0;
9857836SJohn.Forte@Sun.COM 	urdc->mflags = 0;
9867836SJohn.Forte@Sun.COM 	urdc->sync_flags = 0;
9877836SJohn.Forte@Sun.COM 	urdc->bmap_flags = 0;
9887836SJohn.Forte@Sun.COM }
9897836SJohn.Forte@Sun.COM 
9907836SJohn.Forte@Sun.COM 
9917836SJohn.Forte@Sun.COM /*
9927836SJohn.Forte@Sun.COM  * Set flags for a many group.
9937836SJohn.Forte@Sun.COM  */
9947836SJohn.Forte@Sun.COM void
rdc_set_mflags(rdc_u_info_t * urdc,int flags)9957836SJohn.Forte@Sun.COM rdc_set_mflags(rdc_u_info_t *urdc, int flags)
9967836SJohn.Forte@Sun.COM {
9977836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
9987836SJohn.Forte@Sun.COM 	rdc_k_info_t *this = krdc;
9997836SJohn.Forte@Sun.COM 
10007836SJohn.Forte@Sun.COM 	ASSERT(!(flags & ~RDC_MFLAGS));
10017836SJohn.Forte@Sun.COM 
10027836SJohn.Forte@Sun.COM 	if (flags == 0)
10037836SJohn.Forte@Sun.COM 		return;
10047836SJohn.Forte@Sun.COM 
10057836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_many_lock));
10067836SJohn.Forte@Sun.COM 
10077836SJohn.Forte@Sun.COM 	rdc_set_flags(urdc, flags);	/* set flags on local urdc */
10087836SJohn.Forte@Sun.COM 
10097836SJohn.Forte@Sun.COM 	urdc->mflags |= flags;
10107836SJohn.Forte@Sun.COM 	for (krdc = krdc->many_next; krdc != this; krdc = krdc->many_next) {
10117836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[krdc->index];
10127836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
10137836SJohn.Forte@Sun.COM 			continue;
10147836SJohn.Forte@Sun.COM 		urdc->mflags |= flags;
10157836SJohn.Forte@Sun.COM 	}
10167836SJohn.Forte@Sun.COM }
10177836SJohn.Forte@Sun.COM 
10187836SJohn.Forte@Sun.COM 
10197836SJohn.Forte@Sun.COM /*
10207836SJohn.Forte@Sun.COM  * Clear flags for a many group.
10217836SJohn.Forte@Sun.COM  */
10227836SJohn.Forte@Sun.COM void
rdc_clr_mflags(rdc_u_info_t * urdc,int flags)10237836SJohn.Forte@Sun.COM rdc_clr_mflags(rdc_u_info_t *urdc, int flags)
10247836SJohn.Forte@Sun.COM {
10257836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
10267836SJohn.Forte@Sun.COM 	rdc_k_info_t *this = krdc;
10277836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
10287836SJohn.Forte@Sun.COM 
10297836SJohn.Forte@Sun.COM 	ASSERT(!(flags & ~RDC_MFLAGS));
10307836SJohn.Forte@Sun.COM 
10317836SJohn.Forte@Sun.COM 	if (flags == 0)
10327836SJohn.Forte@Sun.COM 		return;
10337836SJohn.Forte@Sun.COM 
10347836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_many_lock));
10357836SJohn.Forte@Sun.COM 
10367836SJohn.Forte@Sun.COM 	rdc_clr_flags(urdc, flags);	/* clear flags on local urdc */
10377836SJohn.Forte@Sun.COM 
10387836SJohn.Forte@Sun.COM 	/*
10397836SJohn.Forte@Sun.COM 	 * We must maintain the mflags based on the set of flags for
10407836SJohn.Forte@Sun.COM 	 * all the urdc's that are chained up.
10417836SJohn.Forte@Sun.COM 	 */
10427836SJohn.Forte@Sun.COM 
10437836SJohn.Forte@Sun.COM 	/*
10447836SJohn.Forte@Sun.COM 	 * First look through all the urdc's and remove bits from
10457836SJohn.Forte@Sun.COM 	 * the 'flags' variable that are in use elsewhere.
10467836SJohn.Forte@Sun.COM 	 */
10477836SJohn.Forte@Sun.COM 
10487836SJohn.Forte@Sun.COM 	for (krdc = krdc->many_next; krdc != this; krdc = krdc->many_next) {
10497836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[krdc->index];
10507836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(utmp))
10517836SJohn.Forte@Sun.COM 			continue;
10527836SJohn.Forte@Sun.COM 		flags &= ~(rdc_get_vflags(utmp) & RDC_MFLAGS);
10537836SJohn.Forte@Sun.COM 		if (flags == 0)
10547836SJohn.Forte@Sun.COM 			break;
10557836SJohn.Forte@Sun.COM 	}
10567836SJohn.Forte@Sun.COM 
10577836SJohn.Forte@Sun.COM 	/*
10587836SJohn.Forte@Sun.COM 	 * Now clear flags as necessary.
10597836SJohn.Forte@Sun.COM 	 */
10607836SJohn.Forte@Sun.COM 
10617836SJohn.Forte@Sun.COM 	if (flags != 0) {
10627836SJohn.Forte@Sun.COM 		urdc->mflags &= ~flags;
10637836SJohn.Forte@Sun.COM 		for (krdc = krdc->many_next; krdc != this;
10647836SJohn.Forte@Sun.COM 		    krdc = krdc->many_next) {
10657836SJohn.Forte@Sun.COM 			utmp = &rdc_u_info[krdc->index];
10667836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(utmp))
10677836SJohn.Forte@Sun.COM 				continue;
10687836SJohn.Forte@Sun.COM 			utmp->mflags &= ~flags;
10697836SJohn.Forte@Sun.COM 		}
10707836SJohn.Forte@Sun.COM 	}
10717836SJohn.Forte@Sun.COM }
10727836SJohn.Forte@Sun.COM 
10737836SJohn.Forte@Sun.COM 
10747836SJohn.Forte@Sun.COM int
rdc_get_mflags(rdc_u_info_t * urdc)10757836SJohn.Forte@Sun.COM rdc_get_mflags(rdc_u_info_t *urdc)
10767836SJohn.Forte@Sun.COM {
10777836SJohn.Forte@Sun.COM 	return (urdc->mflags);
10787836SJohn.Forte@Sun.COM }
10797836SJohn.Forte@Sun.COM 
10807836SJohn.Forte@Sun.COM 
10817836SJohn.Forte@Sun.COM void
rdc_set_flags_log(rdc_u_info_t * urdc,int flags,char * why)10827836SJohn.Forte@Sun.COM rdc_set_flags_log(rdc_u_info_t *urdc, int flags, char *why)
10837836SJohn.Forte@Sun.COM {
10847836SJohn.Forte@Sun.COM 	DTRACE_PROBE2(rdc_set_flags_log, int, urdc->index, int, flags);
10857836SJohn.Forte@Sun.COM 
10867836SJohn.Forte@Sun.COM 	rdc_set_flags(urdc, flags);
10877836SJohn.Forte@Sun.COM 
10887836SJohn.Forte@Sun.COM 	if (why == NULL)
10897836SJohn.Forte@Sun.COM 		return;
10907836SJohn.Forte@Sun.COM 
10917836SJohn.Forte@Sun.COM 	if (flags & RDC_LOGGING)
1092*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!sndr: %s:%s entered logging mode: %s",
1093*9093SRamana.Srikanth@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file, why);
10947836SJohn.Forte@Sun.COM 	if (flags & RDC_VOL_FAILED)
1095*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!sndr: %s:%s volume failed: %s",
1096*9093SRamana.Srikanth@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file, why);
10977836SJohn.Forte@Sun.COM 	if (flags & RDC_BMP_FAILED)
1098*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!sndr: %s:%s bitmap failed: %s",
1099*9093SRamana.Srikanth@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file, why);
11007836SJohn.Forte@Sun.COM }
11017836SJohn.Forte@Sun.COM /*
11027836SJohn.Forte@Sun.COM  * rdc_lor(source, dest, len)
11037836SJohn.Forte@Sun.COM  * logically OR memory pointed to by source and dest, copying result into dest.
11047836SJohn.Forte@Sun.COM  */
11057836SJohn.Forte@Sun.COM void
rdc_lor(const uchar_t * source,uchar_t * dest,int len)11067836SJohn.Forte@Sun.COM rdc_lor(const uchar_t *source, uchar_t *dest, int len)
11077836SJohn.Forte@Sun.COM {
11087836SJohn.Forte@Sun.COM 	int i;
11097836SJohn.Forte@Sun.COM 
11107836SJohn.Forte@Sun.COM 	if (source == NULL)
11117836SJohn.Forte@Sun.COM 		return;
11127836SJohn.Forte@Sun.COM 
11137836SJohn.Forte@Sun.COM 	for (i = 0; i < len; i++)
11147836SJohn.Forte@Sun.COM 		*dest++ |= *source++;
11157836SJohn.Forte@Sun.COM }
11167836SJohn.Forte@Sun.COM 
11177836SJohn.Forte@Sun.COM 
11187836SJohn.Forte@Sun.COM static int
check_filesize(int index,spcs_s_info_t kstatus)11197836SJohn.Forte@Sun.COM check_filesize(int index, spcs_s_info_t kstatus)
11207836SJohn.Forte@Sun.COM {
11217836SJohn.Forte@Sun.COM 	uint64_t remote_size;
11227836SJohn.Forte@Sun.COM 	char tmp1[16], tmp2[16];
11237836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[index];
11247836SJohn.Forte@Sun.COM 	int status;
11257836SJohn.Forte@Sun.COM 
11267836SJohn.Forte@Sun.COM 	status = rdc_net_getsize(index, &remote_size);
11277836SJohn.Forte@Sun.COM 	if (status) {
11287836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(status, tmp1, sizeof (tmp1), 0);
11297836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EGETSIZE, urdc->secondary.intf,
11307836SJohn.Forte@Sun.COM 		    urdc->secondary.file, tmp1);
11317836SJohn.Forte@Sun.COM 		(void) rdc_net_state(index, CCIO_ENABLELOG);
11327836SJohn.Forte@Sun.COM 		return (RDC_EGETSIZE);
11337836SJohn.Forte@Sun.COM 	}
11347836SJohn.Forte@Sun.COM 	if (remote_size < (unsigned long long)urdc->volume_size) {
11357836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
11367836SJohn.Forte@Sun.COM 		    urdc->volume_size, tmp1, sizeof (tmp1), 0);
11377836SJohn.Forte@Sun.COM 		/*
11387836SJohn.Forte@Sun.COM 		 * Cheat, and covert to int, until we have
11397836SJohn.Forte@Sun.COM 		 * spcs_s_unsignedlonginttostring().
11407836SJohn.Forte@Sun.COM 		 */
11417836SJohn.Forte@Sun.COM 		status = (int)remote_size;
11427836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(status, tmp2, sizeof (tmp2), 0);
11437836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ESIZE, urdc->primary.intf,
11447836SJohn.Forte@Sun.COM 		    urdc->primary.file, tmp1, urdc->secondary.intf,
11457836SJohn.Forte@Sun.COM 		    urdc->secondary.file, tmp2);
11467836SJohn.Forte@Sun.COM 		(void) rdc_net_state(index, CCIO_ENABLELOG);
11477836SJohn.Forte@Sun.COM 		return (RDC_ESIZE);
11487836SJohn.Forte@Sun.COM 	}
11497836SJohn.Forte@Sun.COM 	return (0);
11507836SJohn.Forte@Sun.COM }
11517836SJohn.Forte@Sun.COM 
11527836SJohn.Forte@Sun.COM 
11537836SJohn.Forte@Sun.COM static void
rdc_volume_update_svc(intptr_t arg)11547836SJohn.Forte@Sun.COM rdc_volume_update_svc(intptr_t arg)
11557836SJohn.Forte@Sun.COM {
11567836SJohn.Forte@Sun.COM 	rdc_update_t *update = (rdc_update_t *)arg;
11577836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
11587836SJohn.Forte@Sun.COM 	rdc_k_info_t *this;
11597836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
11607836SJohn.Forte@Sun.COM 	struct net_bdata6 bd;
11617836SJohn.Forte@Sun.COM 	int index;
11627836SJohn.Forte@Sun.COM 	int rc;
11637836SJohn.Forte@Sun.COM 
11647836SJohn.Forte@Sun.COM #ifdef DEBUG_IIUPDATE
1165*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR received update request for %s",
1166*9093SRamana.Srikanth@Sun.COM 	    update->volume);
11677836SJohn.Forte@Sun.COM #endif
11687836SJohn.Forte@Sun.COM 
11697836SJohn.Forte@Sun.COM 	if ((update->protocol != RDC_SVC_ONRETURN) &&
11707836SJohn.Forte@Sun.COM 	    (update->protocol != RDC_SVC_VOL_ENABLED)) {
11717836SJohn.Forte@Sun.COM 		/* don't understand what the client intends to do */
11727836SJohn.Forte@Sun.COM 		update->denied = 1;
11737836SJohn.Forte@Sun.COM 		spcs_s_add(update->status, RDC_EVERSION);
11747836SJohn.Forte@Sun.COM 		return;
11757836SJohn.Forte@Sun.COM 	}
11767836SJohn.Forte@Sun.COM 
11777836SJohn.Forte@Sun.COM 	index = rdc_lookup_enabled(update->volume, 0);
11787836SJohn.Forte@Sun.COM 	if (index < 0)
11797836SJohn.Forte@Sun.COM 		return;
11807836SJohn.Forte@Sun.COM 
11817836SJohn.Forte@Sun.COM 	/*
11827836SJohn.Forte@Sun.COM 	 * warn II that this volume is in use by sndr so
11837836SJohn.Forte@Sun.COM 	 * II can validate the sizes of the master vs shadow
11847836SJohn.Forte@Sun.COM 	 * and avoid trouble later down the line with
11857836SJohn.Forte@Sun.COM 	 * size mis-matches between urdc->volume_size and
11867836SJohn.Forte@Sun.COM 	 * what is returned from nsc_partsize() which may
11877836SJohn.Forte@Sun.COM 	 * be the size of the master when replicating the shadow
11887836SJohn.Forte@Sun.COM 	 */
11897836SJohn.Forte@Sun.COM 	if (update->protocol == RDC_SVC_VOL_ENABLED) {
11907836SJohn.Forte@Sun.COM 		if (index >= 0)
11917836SJohn.Forte@Sun.COM 			update->denied = 1;
11927836SJohn.Forte@Sun.COM 		return;
11937836SJohn.Forte@Sun.COM 	}
11947836SJohn.Forte@Sun.COM 
11957836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
11967836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
11977836SJohn.Forte@Sun.COM 	this = krdc;
11987836SJohn.Forte@Sun.COM 
11997836SJohn.Forte@Sun.COM 	do {
12007836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_LOGGING)) {
12017836SJohn.Forte@Sun.COM #ifdef DEBUG_IIUPDATE
1202*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!SNDR refused update request for %s",
12037836SJohn.Forte@Sun.COM 		    update->volume);
12047836SJohn.Forte@Sun.COM #endif
12057836SJohn.Forte@Sun.COM 		update->denied = 1;
12067836SJohn.Forte@Sun.COM 		spcs_s_add(update->status, RDC_EMIRRORUP);
12077836SJohn.Forte@Sun.COM 		return;
12087836SJohn.Forte@Sun.COM 		}
12097836SJohn.Forte@Sun.COM 		/* 1->many - all must be logging */
12107836SJohn.Forte@Sun.COM 		if (IS_MANY(krdc) && IS_STATE(urdc, RDC_PRIMARY)) {
12117836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
12127836SJohn.Forte@Sun.COM 			for (krdc = krdc->many_next; krdc != this;
1213*9093SRamana.Srikanth@Sun.COM 			    krdc = krdc->many_next) {
12147836SJohn.Forte@Sun.COM 				urdc = &rdc_u_info[krdc->index];
12157836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(urdc))
12167836SJohn.Forte@Sun.COM 					continue;
12177836SJohn.Forte@Sun.COM 				break;
12187836SJohn.Forte@Sun.COM 			}
12197836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
12207836SJohn.Forte@Sun.COM 		}
12217836SJohn.Forte@Sun.COM 	} while (krdc != this);
12227836SJohn.Forte@Sun.COM 
12237836SJohn.Forte@Sun.COM #ifdef DEBUG_IIUPDATE
1224*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR allowed update request for %s", update->volume);
12257836SJohn.Forte@Sun.COM #endif
12267836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[krdc->index];
12277836SJohn.Forte@Sun.COM 	do {
12287836SJohn.Forte@Sun.COM 
12297836SJohn.Forte@Sun.COM 		bd.size = min(krdc->bitmap_size, (nsc_size_t)update->size);
12307836SJohn.Forte@Sun.COM 		bd.data.data_val = (char *)update->bitmap;
12317836SJohn.Forte@Sun.COM 		bd.offset = 0;
12327836SJohn.Forte@Sun.COM 		bd.cd = index;
12337836SJohn.Forte@Sun.COM 
12347836SJohn.Forte@Sun.COM 		if ((rc = RDC_OR_BITMAP(&bd)) != 0) {
12357836SJohn.Forte@Sun.COM 			update->denied = 1;
12367836SJohn.Forte@Sun.COM 			spcs_s_add(update->status, rc);
12377836SJohn.Forte@Sun.COM 			return;
12387836SJohn.Forte@Sun.COM 		}
12397836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
12407836SJohn.Forte@Sun.COM 		urdc->bits_set = RDC_COUNT_BITMAP(krdc);
12417836SJohn.Forte@Sun.COM 		if (IS_MANY(krdc) && IS_STATE(urdc, RDC_PRIMARY)) {
12427836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
12437836SJohn.Forte@Sun.COM 			for (krdc = krdc->many_next; krdc != this;
1244*9093SRamana.Srikanth@Sun.COM 			    krdc = krdc->many_next) {
12457836SJohn.Forte@Sun.COM 				index = krdc->index;
12467836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(urdc))
12477836SJohn.Forte@Sun.COM 					continue;
12487836SJohn.Forte@Sun.COM 				break;
12497836SJohn.Forte@Sun.COM 			}
12507836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
12517836SJohn.Forte@Sun.COM 		}
12527836SJohn.Forte@Sun.COM 	} while (krdc != this);
12537836SJohn.Forte@Sun.COM 
12547836SJohn.Forte@Sun.COM 
12557836SJohn.Forte@Sun.COM 	/* II (or something else) has updated us, so no need for a sync */
12567836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & (RDC_SYNC_NEEDED | RDC_RSYNC_NEEDED)) {
12577836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
12587836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_SYNC_NEEDED | RDC_RSYNC_NEEDED);
12597836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
12607836SJohn.Forte@Sun.COM 	}
12617836SJohn.Forte@Sun.COM 
12627836SJohn.Forte@Sun.COM 	if (krdc->bitmap_write > 0)
12637836SJohn.Forte@Sun.COM 		(void) rdc_write_bitmap(krdc);
12647836SJohn.Forte@Sun.COM }
12657836SJohn.Forte@Sun.COM 
12667836SJohn.Forte@Sun.COM 
12677836SJohn.Forte@Sun.COM /*
12687836SJohn.Forte@Sun.COM  * rdc_check()
12697836SJohn.Forte@Sun.COM  *
12707836SJohn.Forte@Sun.COM  * Return 0 if the set is configured, enabled and the supplied
12717836SJohn.Forte@Sun.COM  * addressing information matches the in-kernel config, otherwise
12727836SJohn.Forte@Sun.COM  * return 1.
12737836SJohn.Forte@Sun.COM  */
12747836SJohn.Forte@Sun.COM static int
rdc_check(rdc_k_info_t * krdc,rdc_set_t * rdc_set)12757836SJohn.Forte@Sun.COM rdc_check(rdc_k_info_t *krdc, rdc_set_t *rdc_set)
12767836SJohn.Forte@Sun.COM {
12777836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
12787836SJohn.Forte@Sun.COM 
12797836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&krdc->group->lock));
12807836SJohn.Forte@Sun.COM 
12817836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc))
12827836SJohn.Forte@Sun.COM 		return (1);
12837836SJohn.Forte@Sun.COM 
12847836SJohn.Forte@Sun.COM 	if (strncmp(urdc->primary.file, rdc_set->primary.file,
12857836SJohn.Forte@Sun.COM 	    NSC_MAXPATH) != 0) {
12867836SJohn.Forte@Sun.COM #ifdef DEBUG
1287*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_check: primary file mismatch %s vs %s",
12887836SJohn.Forte@Sun.COM 		    urdc->primary.file, rdc_set->primary.file);
12897836SJohn.Forte@Sun.COM #endif
12907836SJohn.Forte@Sun.COM 		return (1);
12917836SJohn.Forte@Sun.COM 	}
12927836SJohn.Forte@Sun.COM 
12937836SJohn.Forte@Sun.COM 	if (rdc_set->primary.addr.len != 0 &&
12947836SJohn.Forte@Sun.COM 	    bcmp(urdc->primary.addr.buf, rdc_set->primary.addr.buf,
12957836SJohn.Forte@Sun.COM 	    urdc->primary.addr.len) != 0) {
12967836SJohn.Forte@Sun.COM #ifdef DEBUG
1297*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_check: primary address mismatch for %s",
12987836SJohn.Forte@Sun.COM 		    urdc->primary.file);
12997836SJohn.Forte@Sun.COM #endif
13007836SJohn.Forte@Sun.COM 		return (1);
13017836SJohn.Forte@Sun.COM 	}
13027836SJohn.Forte@Sun.COM 
13037836SJohn.Forte@Sun.COM 	if (strncmp(urdc->secondary.file, rdc_set->secondary.file,
13047836SJohn.Forte@Sun.COM 	    NSC_MAXPATH) != 0) {
13057836SJohn.Forte@Sun.COM #ifdef DEBUG
1306*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_check: secondary file mismatch %s vs %s",
13077836SJohn.Forte@Sun.COM 		    urdc->secondary.file, rdc_set->secondary.file);
13087836SJohn.Forte@Sun.COM #endif
13097836SJohn.Forte@Sun.COM 		return (1);
13107836SJohn.Forte@Sun.COM 	}
13117836SJohn.Forte@Sun.COM 
13127836SJohn.Forte@Sun.COM 	if (rdc_set->secondary.addr.len != 0 &&
13137836SJohn.Forte@Sun.COM 	    bcmp(urdc->secondary.addr.buf, rdc_set->secondary.addr.buf,
13147836SJohn.Forte@Sun.COM 	    urdc->secondary.addr.len) != 0) {
13157836SJohn.Forte@Sun.COM #ifdef DEBUG
1316*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_check: secondary addr mismatch for %s",
13177836SJohn.Forte@Sun.COM 		    urdc->secondary.file);
13187836SJohn.Forte@Sun.COM #endif
13197836SJohn.Forte@Sun.COM 		return (1);
13207836SJohn.Forte@Sun.COM 	}
13217836SJohn.Forte@Sun.COM 
13227836SJohn.Forte@Sun.COM 	return (0);
13237836SJohn.Forte@Sun.COM }
13247836SJohn.Forte@Sun.COM 
13257836SJohn.Forte@Sun.COM 
13267836SJohn.Forte@Sun.COM /*
13277836SJohn.Forte@Sun.COM  * Lookup enabled sets for a bitmap match
13287836SJohn.Forte@Sun.COM  */
13297836SJohn.Forte@Sun.COM 
13307836SJohn.Forte@Sun.COM int
rdc_lookup_bitmap(char * pathname)13317836SJohn.Forte@Sun.COM rdc_lookup_bitmap(char *pathname)
13327836SJohn.Forte@Sun.COM {
13337836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
13347836SJohn.Forte@Sun.COM #ifdef DEBUG
13357836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
13367836SJohn.Forte@Sun.COM #endif
13377836SJohn.Forte@Sun.COM 	int index;
13387836SJohn.Forte@Sun.COM 
13397836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
13407836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
13417836SJohn.Forte@Sun.COM #ifdef DEBUG
13427836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
13437836SJohn.Forte@Sun.COM #endif
13447836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
13457836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
13467836SJohn.Forte@Sun.COM 
13477836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
13487836SJohn.Forte@Sun.COM 			continue;
13497836SJohn.Forte@Sun.COM 
13507836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
13517836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->primary.bitmap,
13527836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
13537836SJohn.Forte@Sun.COM 				return (index);
13547836SJohn.Forte@Sun.COM 		} else {
13557836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->secondary.bitmap,
13567836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
13577836SJohn.Forte@Sun.COM 				return (index);
13587836SJohn.Forte@Sun.COM 		}
13597836SJohn.Forte@Sun.COM 	}
13607836SJohn.Forte@Sun.COM 
13617836SJohn.Forte@Sun.COM 	return (-1);
13627836SJohn.Forte@Sun.COM }
13637836SJohn.Forte@Sun.COM 
13647836SJohn.Forte@Sun.COM 
13657836SJohn.Forte@Sun.COM /*
13667836SJohn.Forte@Sun.COM  * Translate a pathname to index into rdc_k_info[].
13677836SJohn.Forte@Sun.COM  * Returns first match that is enabled.
13687836SJohn.Forte@Sun.COM  */
13697836SJohn.Forte@Sun.COM 
13707836SJohn.Forte@Sun.COM int
rdc_lookup_enabled(char * pathname,int allow_disabling)13717836SJohn.Forte@Sun.COM rdc_lookup_enabled(char *pathname, int allow_disabling)
13727836SJohn.Forte@Sun.COM {
13737836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
13747836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
13757836SJohn.Forte@Sun.COM 	int index;
13767836SJohn.Forte@Sun.COM 
13777836SJohn.Forte@Sun.COM restart:
13787836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
13797836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
13807836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
13817836SJohn.Forte@Sun.COM 
13827836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
13837836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
13847836SJohn.Forte@Sun.COM 
13857836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
13867836SJohn.Forte@Sun.COM 			continue;
13877836SJohn.Forte@Sun.COM 
13887836SJohn.Forte@Sun.COM 		if (allow_disabling == 0 && krdc->type_flag & RDC_UNREGISTER)
13897836SJohn.Forte@Sun.COM 			continue;
13907836SJohn.Forte@Sun.COM 
13917836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
13927836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->primary.file,
13937836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
13947836SJohn.Forte@Sun.COM 				return (index);
13957836SJohn.Forte@Sun.COM 		} else {
13967836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->secondary.file,
13977836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
13987836SJohn.Forte@Sun.COM 				return (index);
13997836SJohn.Forte@Sun.COM 		}
14007836SJohn.Forte@Sun.COM 	}
14017836SJohn.Forte@Sun.COM 
14027836SJohn.Forte@Sun.COM 	if (allow_disabling == 0) {
14037836SJohn.Forte@Sun.COM 		/* None found, or only a disabling one found, so try again */
14047836SJohn.Forte@Sun.COM 		allow_disabling = 1;
14057836SJohn.Forte@Sun.COM 		goto restart;
14067836SJohn.Forte@Sun.COM 	}
14077836SJohn.Forte@Sun.COM 
14087836SJohn.Forte@Sun.COM 	return (-1);
14097836SJohn.Forte@Sun.COM }
14107836SJohn.Forte@Sun.COM 
14117836SJohn.Forte@Sun.COM 
14127836SJohn.Forte@Sun.COM /*
14137836SJohn.Forte@Sun.COM  * Translate a pathname to index into rdc_k_info[].
14147836SJohn.Forte@Sun.COM  * Returns first match that is configured.
14157836SJohn.Forte@Sun.COM  *
14167836SJohn.Forte@Sun.COM  * Used by enable & resume code.
14177836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
14187836SJohn.Forte@Sun.COM  */
14197836SJohn.Forte@Sun.COM 
14207836SJohn.Forte@Sun.COM int
rdc_lookup_configured(char * pathname)14217836SJohn.Forte@Sun.COM rdc_lookup_configured(char *pathname)
14227836SJohn.Forte@Sun.COM {
14237836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
14247836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
14257836SJohn.Forte@Sun.COM 	int index;
14267836SJohn.Forte@Sun.COM 
14277836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
14287836SJohn.Forte@Sun.COM 
14297836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
14307836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
14317836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
14327836SJohn.Forte@Sun.COM 
14337836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
14347836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
14357836SJohn.Forte@Sun.COM 
14367836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
14377836SJohn.Forte@Sun.COM 			continue;
14387836SJohn.Forte@Sun.COM 
14397836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
14407836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->primary.file,
14417836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
14427836SJohn.Forte@Sun.COM 				return (index);
14437836SJohn.Forte@Sun.COM 		} else {
14447836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->secondary.file,
14457836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
14467836SJohn.Forte@Sun.COM 				return (index);
14477836SJohn.Forte@Sun.COM 		}
14487836SJohn.Forte@Sun.COM 	}
14497836SJohn.Forte@Sun.COM 
14507836SJohn.Forte@Sun.COM 	return (-1);
14517836SJohn.Forte@Sun.COM }
14527836SJohn.Forte@Sun.COM 
14537836SJohn.Forte@Sun.COM 
14547836SJohn.Forte@Sun.COM /*
14557836SJohn.Forte@Sun.COM  * Looks up a configured set with matching secondary interface:volume
14567836SJohn.Forte@Sun.COM  * to check for illegal many-to-one volume configs.  To be used during
14577836SJohn.Forte@Sun.COM  * enable and resume processing.
14587836SJohn.Forte@Sun.COM  *
14597836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
14607836SJohn.Forte@Sun.COM  */
14617836SJohn.Forte@Sun.COM 
14627836SJohn.Forte@Sun.COM static int
rdc_lookup_many2one(rdc_set_t * rdc_set)14637836SJohn.Forte@Sun.COM rdc_lookup_many2one(rdc_set_t *rdc_set)
14647836SJohn.Forte@Sun.COM {
14657836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
14667836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
14677836SJohn.Forte@Sun.COM 	int index;
14687836SJohn.Forte@Sun.COM 
14697836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
14707836SJohn.Forte@Sun.COM 
14717836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
14727836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
14737836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
14747836SJohn.Forte@Sun.COM 
14757836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
14767836SJohn.Forte@Sun.COM 			continue;
14777836SJohn.Forte@Sun.COM 
14787836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.file,
14797836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file, NSC_MAXPATH) != 0)
14807836SJohn.Forte@Sun.COM 			continue;
14817836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.intf,
14827836SJohn.Forte@Sun.COM 		    rdc_set->secondary.intf, MAX_RDC_HOST_SIZE) != 0)
14837836SJohn.Forte@Sun.COM 			continue;
14847836SJohn.Forte@Sun.COM 
14857836SJohn.Forte@Sun.COM 		break;
14867836SJohn.Forte@Sun.COM 	}
14877836SJohn.Forte@Sun.COM 
14887836SJohn.Forte@Sun.COM 	if (index < rdc_max_sets)
14897836SJohn.Forte@Sun.COM 		return (index);
14907836SJohn.Forte@Sun.COM 	else
14917836SJohn.Forte@Sun.COM 		return (-1);
14927836SJohn.Forte@Sun.COM }
14937836SJohn.Forte@Sun.COM 
14947836SJohn.Forte@Sun.COM 
14957836SJohn.Forte@Sun.COM /*
14967836SJohn.Forte@Sun.COM  * Looks up an rdc set to check if it is already configured, to be used from
14977836SJohn.Forte@Sun.COM  * functions called from the config ioctl where the interface names can be
14987836SJohn.Forte@Sun.COM  * used for comparison.
14997836SJohn.Forte@Sun.COM  *
15007836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
15017836SJohn.Forte@Sun.COM  */
15027836SJohn.Forte@Sun.COM 
15037836SJohn.Forte@Sun.COM int
rdc_lookup_byname(rdc_set_t * rdc_set)15047836SJohn.Forte@Sun.COM rdc_lookup_byname(rdc_set_t *rdc_set)
15057836SJohn.Forte@Sun.COM {
15067836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
15077836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
15087836SJohn.Forte@Sun.COM 	int index;
15097836SJohn.Forte@Sun.COM 
15107836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
15117836SJohn.Forte@Sun.COM 
15127836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
15137836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
15147836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
15157836SJohn.Forte@Sun.COM 
15167836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
15177836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
15187836SJohn.Forte@Sun.COM 
15197836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
15207836SJohn.Forte@Sun.COM 			continue;
15217836SJohn.Forte@Sun.COM 
15227836SJohn.Forte@Sun.COM 		if (strncmp(urdc->primary.file, rdc_set->primary.file,
15237836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) != 0)
15247836SJohn.Forte@Sun.COM 			continue;
15257836SJohn.Forte@Sun.COM 		if (strncmp(urdc->primary.intf, rdc_set->primary.intf,
15267836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0)
15277836SJohn.Forte@Sun.COM 			continue;
15287836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.file, rdc_set->secondary.file,
15297836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) != 0)
15307836SJohn.Forte@Sun.COM 			continue;
15317836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.intf, rdc_set->secondary.intf,
15327836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0)
15337836SJohn.Forte@Sun.COM 			continue;
15347836SJohn.Forte@Sun.COM 
15357836SJohn.Forte@Sun.COM 		break;
15367836SJohn.Forte@Sun.COM 	}
15377836SJohn.Forte@Sun.COM 
15387836SJohn.Forte@Sun.COM 	if (index < rdc_max_sets)
15397836SJohn.Forte@Sun.COM 		return (index);
15407836SJohn.Forte@Sun.COM 	else
15417836SJohn.Forte@Sun.COM 		return (-1);
15427836SJohn.Forte@Sun.COM }
15437836SJohn.Forte@Sun.COM 
15447836SJohn.Forte@Sun.COM /*
15457836SJohn.Forte@Sun.COM  * Looks up a secondary hostname and device, to be used from
15467836SJohn.Forte@Sun.COM  * functions called from the config ioctl where the interface names can be
15477836SJohn.Forte@Sun.COM  * used for comparison.
15487836SJohn.Forte@Sun.COM  *
15497836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
15507836SJohn.Forte@Sun.COM  */
15517836SJohn.Forte@Sun.COM 
15527836SJohn.Forte@Sun.COM int
rdc_lookup_byhostdev(char * intf,char * file)15537836SJohn.Forte@Sun.COM rdc_lookup_byhostdev(char *intf, char *file)
15547836SJohn.Forte@Sun.COM {
15557836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
15567836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
15577836SJohn.Forte@Sun.COM 	int index;
15587836SJohn.Forte@Sun.COM 
15597836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
15607836SJohn.Forte@Sun.COM 
15617836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
15627836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
15637836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
15647836SJohn.Forte@Sun.COM 
15657836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
15667836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
15677836SJohn.Forte@Sun.COM 
15687836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
15697836SJohn.Forte@Sun.COM 			continue;
15707836SJohn.Forte@Sun.COM 
15717836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.file, file,
15727836SJohn.Forte@Sun.COM 		    NSC_MAXPATH) != 0)
15737836SJohn.Forte@Sun.COM 			continue;
15747836SJohn.Forte@Sun.COM 		if (strncmp(urdc->secondary.intf, intf,
15757836SJohn.Forte@Sun.COM 		    MAX_RDC_HOST_SIZE) != 0)
15767836SJohn.Forte@Sun.COM 			continue;
15777836SJohn.Forte@Sun.COM 		break;
15787836SJohn.Forte@Sun.COM 	}
15797836SJohn.Forte@Sun.COM 
15807836SJohn.Forte@Sun.COM 	if (index < rdc_max_sets)
15817836SJohn.Forte@Sun.COM 		return (index);
15827836SJohn.Forte@Sun.COM 	else
15837836SJohn.Forte@Sun.COM 		return (-1);
15847836SJohn.Forte@Sun.COM }
15857836SJohn.Forte@Sun.COM 
15867836SJohn.Forte@Sun.COM 
15877836SJohn.Forte@Sun.COM /*
15887836SJohn.Forte@Sun.COM  * Looks up an rdc set to see if it is currently enabled, to be used on the
15897836SJohn.Forte@Sun.COM  * server so that the interface addresses must be used for comparison, as
15907836SJohn.Forte@Sun.COM  * the interface names may differ from those used on the client.
15917836SJohn.Forte@Sun.COM  *
15927836SJohn.Forte@Sun.COM  */
15937836SJohn.Forte@Sun.COM 
15947836SJohn.Forte@Sun.COM int
rdc_lookup_byaddr(rdc_set_t * rdc_set)15957836SJohn.Forte@Sun.COM rdc_lookup_byaddr(rdc_set_t *rdc_set)
15967836SJohn.Forte@Sun.COM {
15977836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
15987836SJohn.Forte@Sun.COM #ifdef DEBUG
15997836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
16007836SJohn.Forte@Sun.COM #endif
16017836SJohn.Forte@Sun.COM 	int index;
16027836SJohn.Forte@Sun.COM 
16037836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
16047836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
16057836SJohn.Forte@Sun.COM #ifdef DEBUG
16067836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
16077836SJohn.Forte@Sun.COM #endif
16087836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
16097836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
16107836SJohn.Forte@Sun.COM 
16117836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
16127836SJohn.Forte@Sun.COM 			continue;
16137836SJohn.Forte@Sun.COM 
16147836SJohn.Forte@Sun.COM 		if (strcmp(urdc->primary.file, rdc_set->primary.file) != 0)
16157836SJohn.Forte@Sun.COM 			continue;
16167836SJohn.Forte@Sun.COM 
16177836SJohn.Forte@Sun.COM 		if (strcmp(urdc->secondary.file, rdc_set->secondary.file) != 0)
16187836SJohn.Forte@Sun.COM 			continue;
16197836SJohn.Forte@Sun.COM 
16207836SJohn.Forte@Sun.COM 		if (bcmp(urdc->primary.addr.buf, rdc_set->primary.addr.buf,
16217836SJohn.Forte@Sun.COM 		    urdc->primary.addr.len) != 0) {
16227836SJohn.Forte@Sun.COM 			continue;
16237836SJohn.Forte@Sun.COM 		}
16247836SJohn.Forte@Sun.COM 
16257836SJohn.Forte@Sun.COM 		if (bcmp(urdc->secondary.addr.buf, rdc_set->secondary.addr.buf,
16267836SJohn.Forte@Sun.COM 		    urdc->secondary.addr.len) != 0) {
16277836SJohn.Forte@Sun.COM 			continue;
16287836SJohn.Forte@Sun.COM 		}
16297836SJohn.Forte@Sun.COM 
16307836SJohn.Forte@Sun.COM 		break;
16317836SJohn.Forte@Sun.COM 	}
16327836SJohn.Forte@Sun.COM 
16337836SJohn.Forte@Sun.COM 	if (index < rdc_max_sets)
16347836SJohn.Forte@Sun.COM 		return (index);
16357836SJohn.Forte@Sun.COM 	else
16367836SJohn.Forte@Sun.COM 		return (-1);
16377836SJohn.Forte@Sun.COM }
16387836SJohn.Forte@Sun.COM 
16397836SJohn.Forte@Sun.COM 
16407836SJohn.Forte@Sun.COM /*
16417836SJohn.Forte@Sun.COM  * Return index of first multihop or 1-to-many
16427836SJohn.Forte@Sun.COM  * Behavior controlled by setting ismany.
16437836SJohn.Forte@Sun.COM  * ismany TRUE (one-to-many)
16447836SJohn.Forte@Sun.COM  * ismany FALSE (multihops)
16457836SJohn.Forte@Sun.COM  *
16467836SJohn.Forte@Sun.COM  */
16477836SJohn.Forte@Sun.COM static int
rdc_lookup_multimany(rdc_k_info_t * krdc,const int ismany)16487836SJohn.Forte@Sun.COM rdc_lookup_multimany(rdc_k_info_t *krdc, const int ismany)
16497836SJohn.Forte@Sun.COM {
16507836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
16517836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
16527836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
16537836SJohn.Forte@Sun.COM 	char *pathname;
16547836SJohn.Forte@Sun.COM 	int index;
16557836SJohn.Forte@Sun.COM 	int role;
16567836SJohn.Forte@Sun.COM 
16577836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
16587836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_many_lock));
16597836SJohn.Forte@Sun.COM 
16607836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
16617836SJohn.Forte@Sun.COM 		/* this host is the primary of the krdc set */
16627836SJohn.Forte@Sun.COM 		pathname = urdc->primary.file;
16637836SJohn.Forte@Sun.COM 		if (ismany) {
16647836SJohn.Forte@Sun.COM 			/*
16657836SJohn.Forte@Sun.COM 			 * 1-many sets are linked by primary :
16667836SJohn.Forte@Sun.COM 			 * look for matching primary on this host
16677836SJohn.Forte@Sun.COM 			 */
16687836SJohn.Forte@Sun.COM 			role = RDC_PRIMARY;
16697836SJohn.Forte@Sun.COM 		} else {
16707836SJohn.Forte@Sun.COM 			/*
16717836SJohn.Forte@Sun.COM 			 * multihop sets link primary to secondary :
16727836SJohn.Forte@Sun.COM 			 * look for matching secondary on this host
16737836SJohn.Forte@Sun.COM 			 */
16747836SJohn.Forte@Sun.COM 			role = 0;
16757836SJohn.Forte@Sun.COM 		}
16767836SJohn.Forte@Sun.COM 	} else {
16777836SJohn.Forte@Sun.COM 		/* this host is the secondary of the krdc set */
16787836SJohn.Forte@Sun.COM 		pathname = urdc->secondary.file;
16797836SJohn.Forte@Sun.COM 		if (ismany) {
16807836SJohn.Forte@Sun.COM 			/*
16817836SJohn.Forte@Sun.COM 			 * 1-many sets are linked by primary, so if
16827836SJohn.Forte@Sun.COM 			 * this host is the secondary of the set this
16837836SJohn.Forte@Sun.COM 			 * cannot require 1-many linkage.
16847836SJohn.Forte@Sun.COM 			 */
16857836SJohn.Forte@Sun.COM 			return (-1);
16867836SJohn.Forte@Sun.COM 		} else {
16877836SJohn.Forte@Sun.COM 			/*
16887836SJohn.Forte@Sun.COM 			 * multihop sets link primary to secondary :
16897836SJohn.Forte@Sun.COM 			 * look for matching primary on this host
16907836SJohn.Forte@Sun.COM 			 */
16917836SJohn.Forte@Sun.COM 			role = RDC_PRIMARY;
16927836SJohn.Forte@Sun.COM 		}
16937836SJohn.Forte@Sun.COM 	}
16947836SJohn.Forte@Sun.COM 
16957836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
16967836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[index];
16977836SJohn.Forte@Sun.COM 		ktmp = &rdc_k_info[index];
16987836SJohn.Forte@Sun.COM 
16997836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(ktmp)) {
17007836SJohn.Forte@Sun.COM 			continue;
17017836SJohn.Forte@Sun.COM 		}
17027836SJohn.Forte@Sun.COM 
17037836SJohn.Forte@Sun.COM 		if (role == RDC_PRIMARY) {
17047836SJohn.Forte@Sun.COM 			/*
17057836SJohn.Forte@Sun.COM 			 * Find a primary that is this host and is not
17067836SJohn.Forte@Sun.COM 			 * krdc but shares the same data volume as krdc.
17077836SJohn.Forte@Sun.COM 			 */
17087836SJohn.Forte@Sun.COM 			if ((rdc_get_vflags(utmp) & RDC_PRIMARY) &&
1709*9093SRamana.Srikanth@Sun.COM 			    strncmp(utmp->primary.file, pathname,
1710*9093SRamana.Srikanth@Sun.COM 			    NSC_MAXPATH) == 0 && (krdc != ktmp)) {
17117836SJohn.Forte@Sun.COM 				break;
17127836SJohn.Forte@Sun.COM 			}
17137836SJohn.Forte@Sun.COM 		} else {
17147836SJohn.Forte@Sun.COM 			/*
17157836SJohn.Forte@Sun.COM 			 * Find a secondary that is this host and is not
17167836SJohn.Forte@Sun.COM 			 * krdc but shares the same data volume as krdc.
17177836SJohn.Forte@Sun.COM 			 */
17187836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(utmp) & RDC_PRIMARY) &&
1719*9093SRamana.Srikanth@Sun.COM 			    strncmp(utmp->secondary.file, pathname,
1720*9093SRamana.Srikanth@Sun.COM 			    NSC_MAXPATH) == 0 && (krdc != ktmp)) {
17217836SJohn.Forte@Sun.COM 				break;
17227836SJohn.Forte@Sun.COM 			}
17237836SJohn.Forte@Sun.COM 		}
17247836SJohn.Forte@Sun.COM 	}
17257836SJohn.Forte@Sun.COM 
17267836SJohn.Forte@Sun.COM 	if (index < rdc_max_sets)
17277836SJohn.Forte@Sun.COM 		return (index);
17287836SJohn.Forte@Sun.COM 	else
17297836SJohn.Forte@Sun.COM 		return (-1);
17307836SJohn.Forte@Sun.COM }
17317836SJohn.Forte@Sun.COM 
17327836SJohn.Forte@Sun.COM /*
17337836SJohn.Forte@Sun.COM  * Returns secondary match that is configured.
17347836SJohn.Forte@Sun.COM  *
17357836SJohn.Forte@Sun.COM  * Used by enable & resume code.
17367836SJohn.Forte@Sun.COM  * Must be called with rdc_conf_lock held.
17377836SJohn.Forte@Sun.COM  */
17387836SJohn.Forte@Sun.COM 
17397836SJohn.Forte@Sun.COM static int
rdc_lookup_secondary(char * pathname)17407836SJohn.Forte@Sun.COM rdc_lookup_secondary(char *pathname)
17417836SJohn.Forte@Sun.COM {
17427836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
17437836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
17447836SJohn.Forte@Sun.COM 	int index;
17457836SJohn.Forte@Sun.COM 
17467836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
17477836SJohn.Forte@Sun.COM 
17487836SJohn.Forte@Sun.COM 	for (index = 0; index < rdc_max_sets; index++) {
17497836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[index];
17507836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
17517836SJohn.Forte@Sun.COM 
17527836SJohn.Forte@Sun.COM 		ASSERT(krdc->index == index);
17537836SJohn.Forte@Sun.COM 		ASSERT(urdc->index == index);
17547836SJohn.Forte@Sun.COM 
17557836SJohn.Forte@Sun.COM 		if (!IS_CONFIGURED(krdc))
17567836SJohn.Forte@Sun.COM 			continue;
17577836SJohn.Forte@Sun.COM 
17587836SJohn.Forte@Sun.COM 		if (!IS_STATE(urdc, RDC_PRIMARY)) {
17597836SJohn.Forte@Sun.COM 			if (strncmp(pathname, urdc->secondary.file,
17607836SJohn.Forte@Sun.COM 			    NSC_MAXPATH) == 0)
17617836SJohn.Forte@Sun.COM 			return (index);
17627836SJohn.Forte@Sun.COM 		}
17637836SJohn.Forte@Sun.COM 	}
17647836SJohn.Forte@Sun.COM 
17657836SJohn.Forte@Sun.COM 	return (-1);
17667836SJohn.Forte@Sun.COM }
17677836SJohn.Forte@Sun.COM 
17687836SJohn.Forte@Sun.COM 
17697836SJohn.Forte@Sun.COM static nsc_fd_t *
rdc_open_direct(rdc_k_info_t * krdc)17707836SJohn.Forte@Sun.COM rdc_open_direct(rdc_k_info_t *krdc)
17717836SJohn.Forte@Sun.COM {
17727836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
17737836SJohn.Forte@Sun.COM 	int rc;
17747836SJohn.Forte@Sun.COM 
17757836SJohn.Forte@Sun.COM 	if (krdc->remote_fd == NULL)
17767836SJohn.Forte@Sun.COM 		krdc->remote_fd = nsc_open(urdc->direct_file,
17777836SJohn.Forte@Sun.COM 		    NSC_RDCHR_ID|NSC_DEVICE|NSC_RDWR, 0, 0, &rc);
17787836SJohn.Forte@Sun.COM 	return (krdc->remote_fd);
17797836SJohn.Forte@Sun.COM }
17807836SJohn.Forte@Sun.COM 
17817836SJohn.Forte@Sun.COM static void
rdc_close_direct(rdc_k_info_t * krdc)17827836SJohn.Forte@Sun.COM rdc_close_direct(rdc_k_info_t *krdc)
17837836SJohn.Forte@Sun.COM {
17847836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
17857836SJohn.Forte@Sun.COM 
17867836SJohn.Forte@Sun.COM 	urdc->direct_file[0] = 0;
17877836SJohn.Forte@Sun.COM 	if (krdc->remote_fd) {
17887836SJohn.Forte@Sun.COM 		if (nsc_close(krdc->remote_fd) == 0) {
17897836SJohn.Forte@Sun.COM 			krdc->remote_fd = NULL;
17907836SJohn.Forte@Sun.COM 		}
17917836SJohn.Forte@Sun.COM 	}
17927836SJohn.Forte@Sun.COM }
17937836SJohn.Forte@Sun.COM 
17947836SJohn.Forte@Sun.COM 
17957836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
17967836SJohn.Forte@Sun.COM static void
print_many(rdc_k_info_t * start)17977836SJohn.Forte@Sun.COM print_many(rdc_k_info_t *start)
17987836SJohn.Forte@Sun.COM {
17997836SJohn.Forte@Sun.COM 	rdc_k_info_t *p = start;
18007836SJohn.Forte@Sun.COM 	rdc_u_info_t *q = &rdc_u_info[p->index];
18017836SJohn.Forte@Sun.COM 
18027836SJohn.Forte@Sun.COM 	do {
1803*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_CONT, "!krdc %p, %s %s (many_nxt %p multi_nxt %p)\n",
1804*9093SRamana.Srikanth@Sun.COM 		    p, q->primary.file, q->secondary.file, p->many_next,
1805*9093SRamana.Srikanth@Sun.COM 		    p->multi_next);
18067836SJohn.Forte@Sun.COM 		delay(10);
18077836SJohn.Forte@Sun.COM 		p = p->many_next;
18087836SJohn.Forte@Sun.COM 		q = &rdc_u_info[p->index];
18097836SJohn.Forte@Sun.COM 	} while (p && p != start);
18107836SJohn.Forte@Sun.COM }
18117836SJohn.Forte@Sun.COM #endif /* DEBUG_MANY */
18127836SJohn.Forte@Sun.COM 
18137836SJohn.Forte@Sun.COM 
18147836SJohn.Forte@Sun.COM static int
add_to_multi(rdc_k_info_t * krdc)18157836SJohn.Forte@Sun.COM add_to_multi(rdc_k_info_t *krdc)
18167836SJohn.Forte@Sun.COM {
18177836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
18187836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
18197836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
18207836SJohn.Forte@Sun.COM 	int mindex;
18217836SJohn.Forte@Sun.COM 	int domulti;
18227836SJohn.Forte@Sun.COM 
18237836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[krdc->index];
18247836SJohn.Forte@Sun.COM 
18257836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
18267836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_many_lock));
18277836SJohn.Forte@Sun.COM 
18287836SJohn.Forte@Sun.COM 	/* Now find companion krdc */
18297836SJohn.Forte@Sun.COM 	mindex = rdc_lookup_multimany(krdc, FALSE);
18307836SJohn.Forte@Sun.COM 
18317836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
18327836SJohn.Forte@Sun.COM 	cmn_err(CE_NOTE,
1833*9093SRamana.Srikanth@Sun.COM 	    "!add_to_multi: lookup_multimany: mindex %d prim %s sec %s",
1834*9093SRamana.Srikanth@Sun.COM 	    mindex, urdc->primary.file, urdc->secondary.file);
18357836SJohn.Forte@Sun.COM #endif
18367836SJohn.Forte@Sun.COM 
18377836SJohn.Forte@Sun.COM 	if (mindex >= 0) {
18387836SJohn.Forte@Sun.COM 		ktmp = &rdc_k_info[mindex];
18397836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[mindex];
18407836SJohn.Forte@Sun.COM 
18417836SJohn.Forte@Sun.COM 		domulti = 1;
18427836SJohn.Forte@Sun.COM 
18437836SJohn.Forte@Sun.COM 		if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
18447836SJohn.Forte@Sun.COM 		    ktmp->multi_next != NULL) {
18457836SJohn.Forte@Sun.COM 			/*
18467836SJohn.Forte@Sun.COM 			 * We are adding a new primary to a many
18477836SJohn.Forte@Sun.COM 			 * group that is the target of a multihop, just
18487836SJohn.Forte@Sun.COM 			 * ignore it since we are linked in elsewhere.
18497836SJohn.Forte@Sun.COM 			 */
18507836SJohn.Forte@Sun.COM 			domulti = 0;
18517836SJohn.Forte@Sun.COM 		}
18527836SJohn.Forte@Sun.COM 
18537836SJohn.Forte@Sun.COM 		if (domulti) {
18547836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
18557836SJohn.Forte@Sun.COM 				/* Is previous leg using direct file I/O? */
18567836SJohn.Forte@Sun.COM 				if (utmp->direct_file[0] != 0) {
18577836SJohn.Forte@Sun.COM 					/* It is, so cannot proceed */
18587836SJohn.Forte@Sun.COM 					return (-1);
18597836SJohn.Forte@Sun.COM 				}
18607836SJohn.Forte@Sun.COM 			} else {
18617836SJohn.Forte@Sun.COM 				/* Is this leg using direct file I/O? */
18627836SJohn.Forte@Sun.COM 				if (urdc->direct_file[0] != 0) {
18637836SJohn.Forte@Sun.COM 					/* It is, so cannot proceed */
18647836SJohn.Forte@Sun.COM 					return (-1);
18657836SJohn.Forte@Sun.COM 				}
18667836SJohn.Forte@Sun.COM 			}
18677836SJohn.Forte@Sun.COM 			krdc->multi_next = ktmp;
18687836SJohn.Forte@Sun.COM 			ktmp->multi_next = krdc;
18697836SJohn.Forte@Sun.COM 		}
18707836SJohn.Forte@Sun.COM 	} else {
18717836SJohn.Forte@Sun.COM 		krdc->multi_next = NULL;
18727836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
1873*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!add_to_multi: NULL multi_next index %d",
1874*9093SRamana.Srikanth@Sun.COM 		    krdc->index);
18757836SJohn.Forte@Sun.COM #endif
18767836SJohn.Forte@Sun.COM 	}
18777836SJohn.Forte@Sun.COM 
18787836SJohn.Forte@Sun.COM 	return (0);
18797836SJohn.Forte@Sun.COM }
18807836SJohn.Forte@Sun.COM 
18817836SJohn.Forte@Sun.COM 
18827836SJohn.Forte@Sun.COM /*
18837836SJohn.Forte@Sun.COM  * Add a new set to the circular list of 1-to-many primaries and chain
18847836SJohn.Forte@Sun.COM  * up any multihop as well.
18857836SJohn.Forte@Sun.COM  */
18867836SJohn.Forte@Sun.COM static int
add_to_many(rdc_k_info_t * krdc)18877836SJohn.Forte@Sun.COM add_to_many(rdc_k_info_t *krdc)
18887836SJohn.Forte@Sun.COM {
18897836SJohn.Forte@Sun.COM 	rdc_k_info_t *okrdc;
18907836SJohn.Forte@Sun.COM 	int oindex;
18917836SJohn.Forte@Sun.COM 
18927836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
18937836SJohn.Forte@Sun.COM 
18947836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
18957836SJohn.Forte@Sun.COM 
18967836SJohn.Forte@Sun.COM 	if (add_to_multi(krdc) < 0) {
18977836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
18987836SJohn.Forte@Sun.COM 		return (-1);
18997836SJohn.Forte@Sun.COM 	}
19007836SJohn.Forte@Sun.COM 
19017836SJohn.Forte@Sun.COM 	oindex = rdc_lookup_multimany(krdc, TRUE);
19027836SJohn.Forte@Sun.COM 	if (oindex < 0) {
19037836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
19047836SJohn.Forte@Sun.COM 		print_many(krdc);
19057836SJohn.Forte@Sun.COM #endif
19067836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
19077836SJohn.Forte@Sun.COM 		return (0);
19087836SJohn.Forte@Sun.COM 	}
19097836SJohn.Forte@Sun.COM 
19107836SJohn.Forte@Sun.COM 	okrdc = &rdc_k_info[oindex];
19117836SJohn.Forte@Sun.COM 
19127836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
19137836SJohn.Forte@Sun.COM 	print_many(okrdc);
19147836SJohn.Forte@Sun.COM #endif
19157836SJohn.Forte@Sun.COM 	krdc->many_next = okrdc->many_next;
19167836SJohn.Forte@Sun.COM 	okrdc->many_next = krdc;
19177836SJohn.Forte@Sun.COM 
19187836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
19197836SJohn.Forte@Sun.COM 	print_many(okrdc);
19207836SJohn.Forte@Sun.COM #endif
19217836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
19227836SJohn.Forte@Sun.COM 	return (0);
19237836SJohn.Forte@Sun.COM }
19247836SJohn.Forte@Sun.COM 
19257836SJohn.Forte@Sun.COM 
19267836SJohn.Forte@Sun.COM /*
19277836SJohn.Forte@Sun.COM  * Remove a set from the circular list of 1-to-many primaries.
19287836SJohn.Forte@Sun.COM  */
19297836SJohn.Forte@Sun.COM static void
remove_from_many(rdc_k_info_t * old)19307836SJohn.Forte@Sun.COM remove_from_many(rdc_k_info_t *old)
19317836SJohn.Forte@Sun.COM {
19327836SJohn.Forte@Sun.COM 	rdc_u_info_t *uold = &rdc_u_info[old->index];
19337836SJohn.Forte@Sun.COM 	rdc_k_info_t *p, *q;
19347836SJohn.Forte@Sun.COM 
19357836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_conf_lock));
19367836SJohn.Forte@Sun.COM 
19377836SJohn.Forte@Sun.COM 	rdc_many_enter(old);
19387836SJohn.Forte@Sun.COM 
19397836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
1940*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!rdc: before remove_from_many");
19417836SJohn.Forte@Sun.COM 	print_many(old);
19427836SJohn.Forte@Sun.COM #endif
19437836SJohn.Forte@Sun.COM 
19447836SJohn.Forte@Sun.COM 	if (old->many_next == old) {
19457836SJohn.Forte@Sun.COM 		/* remove from multihop */
19467836SJohn.Forte@Sun.COM 		if ((q = old->multi_next) != NULL) {
19477836SJohn.Forte@Sun.COM 			ASSERT(q->multi_next == old);
19487836SJohn.Forte@Sun.COM 			q->multi_next = NULL;
19497836SJohn.Forte@Sun.COM 			old->multi_next = NULL;
19507836SJohn.Forte@Sun.COM 		}
19517836SJohn.Forte@Sun.COM 
19527836SJohn.Forte@Sun.COM 		rdc_many_exit(old);
19537836SJohn.Forte@Sun.COM 		return;
19547836SJohn.Forte@Sun.COM 	}
19557836SJohn.Forte@Sun.COM 
19567836SJohn.Forte@Sun.COM 	/* search */
19577836SJohn.Forte@Sun.COM 	for (p = old->many_next; p->many_next != old; p = p->many_next)
19587836SJohn.Forte@Sun.COM 	;
19597836SJohn.Forte@Sun.COM 
19607836SJohn.Forte@Sun.COM 	p->many_next = old->many_next;
19617836SJohn.Forte@Sun.COM 	old->many_next = old;
19627836SJohn.Forte@Sun.COM 
19637836SJohn.Forte@Sun.COM 	if ((q = old->multi_next) != NULL) {
19647836SJohn.Forte@Sun.COM 		/*
19657836SJohn.Forte@Sun.COM 		 * old was part of a multihop, so switch multi pointers
19667836SJohn.Forte@Sun.COM 		 * to someone remaining on the many chain
19677836SJohn.Forte@Sun.COM 		 */
19687836SJohn.Forte@Sun.COM 		ASSERT(p->multi_next == NULL);
19697836SJohn.Forte@Sun.COM 
19707836SJohn.Forte@Sun.COM 		q->multi_next = p;
19717836SJohn.Forte@Sun.COM 		p->multi_next = q;
19727836SJohn.Forte@Sun.COM 		old->multi_next = NULL;
19737836SJohn.Forte@Sun.COM 	}
19747836SJohn.Forte@Sun.COM 
19757836SJohn.Forte@Sun.COM #ifdef DEBUG_MANY
19767836SJohn.Forte@Sun.COM 	if (p == old) {
1977*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc: after remove_from_many empty");
19787836SJohn.Forte@Sun.COM 	} else {
1979*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc: after remove_from_many");
19807836SJohn.Forte@Sun.COM 		print_many(p);
19817836SJohn.Forte@Sun.COM 	}
19827836SJohn.Forte@Sun.COM #endif
19837836SJohn.Forte@Sun.COM 
19847836SJohn.Forte@Sun.COM 	rdc_clr_mflags(&rdc_u_info[p->index],
19857836SJohn.Forte@Sun.COM 	    (rdc_get_vflags(uold) & RDC_MFLAGS));
19867836SJohn.Forte@Sun.COM 
19877836SJohn.Forte@Sun.COM 	rdc_many_exit(old);
19887836SJohn.Forte@Sun.COM }
19897836SJohn.Forte@Sun.COM 
19907836SJohn.Forte@Sun.COM 
19917836SJohn.Forte@Sun.COM static int
_rdc_enable(rdc_set_t * rdc_set,int options,spcs_s_info_t kstatus)19927836SJohn.Forte@Sun.COM _rdc_enable(rdc_set_t *rdc_set, int options, spcs_s_info_t kstatus)
19937836SJohn.Forte@Sun.COM {
19947836SJohn.Forte@Sun.COM 	int index;
19957836SJohn.Forte@Sun.COM 	char *rhost;
19967836SJohn.Forte@Sun.COM 	struct netbuf *addrp;
19977836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
19987836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
19997836SJohn.Forte@Sun.COM 	rdc_srv_t *svp = NULL;
20007836SJohn.Forte@Sun.COM 	char *local_file;
20017836SJohn.Forte@Sun.COM 	char *local_bitmap;
20027836SJohn.Forte@Sun.COM 	char *diskq;
20037836SJohn.Forte@Sun.COM 	int rc;
20047836SJohn.Forte@Sun.COM 	nsc_size_t maxfbas;
20057836SJohn.Forte@Sun.COM 	rdc_group_t *grp;
20067836SJohn.Forte@Sun.COM 
20077836SJohn.Forte@Sun.COM 	if ((rdc_set->primary.intf[0] == 0) ||
20087836SJohn.Forte@Sun.COM 	    (rdc_set->primary.addr.len == 0) ||
20097836SJohn.Forte@Sun.COM 	    (rdc_set->primary.file[0] == 0) ||
20107836SJohn.Forte@Sun.COM 	    (rdc_set->primary.bitmap[0] == 0) ||
20117836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.intf[0] == 0) ||
20127836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.addr.len == 0) ||
20137836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.file[0] == 0) ||
20147836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.bitmap[0] == 0)) {
20157836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEMPTY);
20167836SJohn.Forte@Sun.COM 		return (RDC_EEMPTY);
20177836SJohn.Forte@Sun.COM 	}
20187836SJohn.Forte@Sun.COM 
20197836SJohn.Forte@Sun.COM 	/* Next check there aren't any enabled rdc sets which match. */
20207836SJohn.Forte@Sun.COM 
20217836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
20227836SJohn.Forte@Sun.COM 
20237836SJohn.Forte@Sun.COM 	if (rdc_lookup_byname(rdc_set) >= 0) {
20247836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20257836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EENABLED, rdc_set->primary.intf,
20267836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
20277836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
20287836SJohn.Forte@Sun.COM 		return (RDC_EENABLED);
20297836SJohn.Forte@Sun.COM 	}
20307836SJohn.Forte@Sun.COM 
20317836SJohn.Forte@Sun.COM 	if (rdc_lookup_many2one(rdc_set) >= 0) {
20327836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20337836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EMANY2ONE, rdc_set->primary.intf,
20347836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
20357836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
20367836SJohn.Forte@Sun.COM 		return (RDC_EMANY2ONE);
20377836SJohn.Forte@Sun.COM 	}
20387836SJohn.Forte@Sun.COM 
20397836SJohn.Forte@Sun.COM 	if (rdc_set->netconfig->knc_proto == NULL) {
20407836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20417836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETCONFIG);
20427836SJohn.Forte@Sun.COM 		return (RDC_ENETCONFIG);
20437836SJohn.Forte@Sun.COM 	}
20447836SJohn.Forte@Sun.COM 
20457836SJohn.Forte@Sun.COM 	if (rdc_set->primary.addr.len == 0) {
20467836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20477836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETBUF, rdc_set->primary.file);
20487836SJohn.Forte@Sun.COM 		return (RDC_ENETBUF);
20497836SJohn.Forte@Sun.COM 	}
20507836SJohn.Forte@Sun.COM 
20517836SJohn.Forte@Sun.COM 	if (rdc_set->secondary.addr.len == 0) {
20527836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20537836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETBUF, rdc_set->secondary.file);
20547836SJohn.Forte@Sun.COM 		return (RDC_ENETBUF);
20557836SJohn.Forte@Sun.COM 	}
20567836SJohn.Forte@Sun.COM 
20577836SJohn.Forte@Sun.COM 	/* Check that the local data volume isn't in use as a bitmap */
20587836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
20597836SJohn.Forte@Sun.COM 		local_file = rdc_set->primary.file;
20607836SJohn.Forte@Sun.COM 	else
20617836SJohn.Forte@Sun.COM 		local_file = rdc_set->secondary.file;
20627836SJohn.Forte@Sun.COM 	if (rdc_lookup_bitmap(local_file) >= 0) {
20637836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20647836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EVOLINUSE, local_file);
20657836SJohn.Forte@Sun.COM 		return (RDC_EVOLINUSE);
20667836SJohn.Forte@Sun.COM 	}
20677836SJohn.Forte@Sun.COM 
20687836SJohn.Forte@Sun.COM 	/* check that the secondary data volume isn't in use */
20697836SJohn.Forte@Sun.COM 	if (!(options & RDC_OPT_PRIMARY)) {
20707836SJohn.Forte@Sun.COM 		local_file = rdc_set->secondary.file;
20717836SJohn.Forte@Sun.COM 		if (rdc_lookup_secondary(local_file) >= 0) {
20727836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
20737836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EVOLINUSE, local_file);
20747836SJohn.Forte@Sun.COM 			return (RDC_EVOLINUSE);
20757836SJohn.Forte@Sun.COM 		}
20767836SJohn.Forte@Sun.COM 	}
20777836SJohn.Forte@Sun.COM 
20787836SJohn.Forte@Sun.COM 	/* check that the local data vol is not in use as a diskqueue */
20797836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY) {
20807836SJohn.Forte@Sun.COM 		if (rdc_lookup_diskq(rdc_set->primary.file) >= 0) {
20817836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
20827836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus,
20837836SJohn.Forte@Sun.COM 			    RDC_EVOLINUSE, rdc_set->primary.file);
20847836SJohn.Forte@Sun.COM 			return (RDC_EVOLINUSE);
20857836SJohn.Forte@Sun.COM 		}
20867836SJohn.Forte@Sun.COM 	}
20877836SJohn.Forte@Sun.COM 
20887836SJohn.Forte@Sun.COM 	/* Check that the bitmap isn't in use as a data volume */
20897836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
20907836SJohn.Forte@Sun.COM 		local_bitmap = rdc_set->primary.bitmap;
20917836SJohn.Forte@Sun.COM 	else
20927836SJohn.Forte@Sun.COM 		local_bitmap = rdc_set->secondary.bitmap;
20937836SJohn.Forte@Sun.COM 	if (rdc_lookup_configured(local_bitmap) >= 0) {
20947836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
20957836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBMPINUSE, local_bitmap);
20967836SJohn.Forte@Sun.COM 		return (RDC_EBMPINUSE);
20977836SJohn.Forte@Sun.COM 	}
20987836SJohn.Forte@Sun.COM 
20997836SJohn.Forte@Sun.COM 	/* Check that the bitmap isn't already in use as a bitmap */
21007836SJohn.Forte@Sun.COM 	if (rdc_lookup_bitmap(local_bitmap) >= 0) {
21017836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
21027836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBMPINUSE, local_bitmap);
21037836SJohn.Forte@Sun.COM 		return (RDC_EBMPINUSE);
21047836SJohn.Forte@Sun.COM 	}
21057836SJohn.Forte@Sun.COM 
21067836SJohn.Forte@Sun.COM 	/* check that the diskq (if here) is not in use */
21077836SJohn.Forte@Sun.COM 	diskq = rdc_set->disk_queue;
21087836SJohn.Forte@Sun.COM 	if (diskq[0] && rdc_diskq_inuse(rdc_set, diskq)) {
21097836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
21107836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EDISKQINUSE, diskq);
21117836SJohn.Forte@Sun.COM 		return (RDC_EDISKQINUSE);
21127836SJohn.Forte@Sun.COM 	}
21137836SJohn.Forte@Sun.COM 
21147836SJohn.Forte@Sun.COM 
21157836SJohn.Forte@Sun.COM 	/* Set urdc->volume_size */
21167836SJohn.Forte@Sun.COM 	index = rdc_dev_open(rdc_set, options);
21177836SJohn.Forte@Sun.COM 	if (index < 0) {
21187836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
21197836SJohn.Forte@Sun.COM 		if (options & RDC_OPT_PRIMARY)
21207836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EOPEN, rdc_set->primary.intf,
21217836SJohn.Forte@Sun.COM 			    rdc_set->primary.file);
21227836SJohn.Forte@Sun.COM 		else
21237836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EOPEN, rdc_set->secondary.intf,
21247836SJohn.Forte@Sun.COM 			    rdc_set->secondary.file);
21257836SJohn.Forte@Sun.COM 		return (RDC_EOPEN);
21267836SJohn.Forte@Sun.COM 	}
21277836SJohn.Forte@Sun.COM 
21287836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
21297836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
21307836SJohn.Forte@Sun.COM 
21317836SJohn.Forte@Sun.COM 	/* copy relevant parts of rdc_set to urdc field by field */
21327836SJohn.Forte@Sun.COM 
21337836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.intf, rdc_set->primary.intf,
21347836SJohn.Forte@Sun.COM 	    MAX_RDC_HOST_SIZE);
21357836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.intf, rdc_set->secondary.intf,
21367836SJohn.Forte@Sun.COM 	    MAX_RDC_HOST_SIZE);
21377836SJohn.Forte@Sun.COM 
21387836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->group_name, rdc_set->group_name, NSC_MAXPATH);
21397836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->disk_queue, rdc_set->disk_queue, NSC_MAXPATH);
21407836SJohn.Forte@Sun.COM 
21417836SJohn.Forte@Sun.COM 	dup_rdc_netbuf(&rdc_set->primary.addr, &urdc->primary.addr);
21427836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.file, rdc_set->primary.file, NSC_MAXPATH);
21437836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.bitmap, rdc_set->primary.bitmap,
21447836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
21457836SJohn.Forte@Sun.COM 
21467836SJohn.Forte@Sun.COM 	dup_rdc_netbuf(&rdc_set->secondary.addr, &urdc->secondary.addr);
21477836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.file, rdc_set->secondary.file,
21487836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
21497836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.bitmap, rdc_set->secondary.bitmap,
21507836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
21517836SJohn.Forte@Sun.COM 
21527836SJohn.Forte@Sun.COM 	urdc->setid = rdc_set->setid;
21537836SJohn.Forte@Sun.COM 
21547836SJohn.Forte@Sun.COM 	/*
21557836SJohn.Forte@Sun.COM 	 * before we try to add to group, or create one, check out
21567836SJohn.Forte@Sun.COM 	 * if we are doing the wrong thing with the diskq
21577836SJohn.Forte@Sun.COM 	 */
21587836SJohn.Forte@Sun.COM 
21597836SJohn.Forte@Sun.COM 	if (urdc->disk_queue[0] && (options & RDC_OPT_SYNC)) {
21607836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
21617836SJohn.Forte@Sun.COM 		rdc_dev_close(krdc);
21627836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EQWRONGMODE);
21637836SJohn.Forte@Sun.COM 		return (RDC_EQWRONGMODE);
21647836SJohn.Forte@Sun.COM 	}
21657836SJohn.Forte@Sun.COM 
21667836SJohn.Forte@Sun.COM 	if ((rc = add_to_group(krdc, options, RDC_CMD_ENABLE)) != 0) {
21677836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
21687836SJohn.Forte@Sun.COM 		rdc_dev_close(krdc);
21697836SJohn.Forte@Sun.COM 		if (rc == RDC_EQNOADD) {
21707836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EQNOADD, rdc_set->disk_queue);
21717836SJohn.Forte@Sun.COM 			return (RDC_EQNOADD);
21727836SJohn.Forte@Sun.COM 		} else {
21737836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EGROUP,
21747836SJohn.Forte@Sun.COM 			    rdc_set->primary.intf, rdc_set->primary.file,
21757836SJohn.Forte@Sun.COM 			    rdc_set->secondary.intf, rdc_set->secondary.file,
21767836SJohn.Forte@Sun.COM 			    rdc_set->group_name);
21777836SJohn.Forte@Sun.COM 			return (RDC_EGROUP);
21787836SJohn.Forte@Sun.COM 		}
21797836SJohn.Forte@Sun.COM 	}
21807836SJohn.Forte@Sun.COM 
21817836SJohn.Forte@Sun.COM 	/*
21827836SJohn.Forte@Sun.COM 	 * maxfbas was set in rdc_dev_open as primary's maxfbas.
21837836SJohn.Forte@Sun.COM 	 * If diskq's maxfbas is smaller, then use diskq's.
21847836SJohn.Forte@Sun.COM 	 */
21857836SJohn.Forte@Sun.COM 	grp = krdc->group;
21867836SJohn.Forte@Sun.COM 	if (grp && RDC_IS_DISKQ(grp) && (grp->diskqfd != 0)) {
21877836SJohn.Forte@Sun.COM 		rc = _rdc_rsrv_diskq(grp);
21887836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(rc)) {
21897836SJohn.Forte@Sun.COM 			rc = nsc_maxfbas(grp->diskqfd, 0, &maxfbas);
21907836SJohn.Forte@Sun.COM 			if (rc == 0) {
21917836SJohn.Forte@Sun.COM #ifdef DEBUG
21927836SJohn.Forte@Sun.COM 				if (krdc->maxfbas != maxfbas)
2193*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE,
2194*9093SRamana.Srikanth@Sun.COM 					    "!_rdc_enable: diskq maxfbas = %"
2195*9093SRamana.Srikanth@Sun.COM 					    NSC_SZFMT ", primary maxfbas = %"
2196*9093SRamana.Srikanth@Sun.COM 					    NSC_SZFMT, maxfbas, krdc->maxfbas);
21977836SJohn.Forte@Sun.COM #endif
21987836SJohn.Forte@Sun.COM 				krdc->maxfbas = min(krdc->maxfbas, maxfbas);
21997836SJohn.Forte@Sun.COM 			} else {
22007836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
2201*9093SRamana.Srikanth@Sun.COM 				    "!_rdc_enable: diskq maxfbas failed (%d)",
22027836SJohn.Forte@Sun.COM 				    rc);
22037836SJohn.Forte@Sun.COM 			}
22047836SJohn.Forte@Sun.COM 			_rdc_rlse_diskq(grp);
22057836SJohn.Forte@Sun.COM 		} else {
22067836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
2207*9093SRamana.Srikanth@Sun.COM 			    "!_rdc_enable: diskq reserve failed (%d)", rc);
22087836SJohn.Forte@Sun.COM 		}
22097836SJohn.Forte@Sun.COM 	}
22107836SJohn.Forte@Sun.COM 
22117836SJohn.Forte@Sun.COM 	rdc_init_flags(urdc);
22127836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->direct_file, rdc_set->direct_file, NSC_MAXPATH);
22137836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_PRIMARY) && rdc_set->direct_file[0]) {
22147836SJohn.Forte@Sun.COM 		if (rdc_open_direct(krdc) == NULL)
22157836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_FCAL_FAILED);
22167836SJohn.Forte@Sun.COM 	}
22177836SJohn.Forte@Sun.COM 
22187836SJohn.Forte@Sun.COM 	krdc->many_next = krdc;
22197836SJohn.Forte@Sun.COM 
22207836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag == 0);
22217836SJohn.Forte@Sun.COM 	krdc->type_flag = RDC_CONFIGURED;
22227836SJohn.Forte@Sun.COM 
22237836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
22247836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_PRIMARY);
22257836SJohn.Forte@Sun.COM 
22267836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_ASYNC)
22277836SJohn.Forte@Sun.COM 		krdc->type_flag |= RDC_ASYNCMODE;
22287836SJohn.Forte@Sun.COM 
22297836SJohn.Forte@Sun.COM 	set_busy(krdc);
22307836SJohn.Forte@Sun.COM 	urdc->syshostid = rdc_set->syshostid;
22317836SJohn.Forte@Sun.COM 
22327836SJohn.Forte@Sun.COM 	if (add_to_many(krdc) < 0) {
22337836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
22347836SJohn.Forte@Sun.COM 
22357836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
22367836SJohn.Forte@Sun.COM 
22377836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EMULTI);
22387836SJohn.Forte@Sun.COM 		rc = RDC_EMULTI;
22397836SJohn.Forte@Sun.COM 		goto fail;
22407836SJohn.Forte@Sun.COM 	}
22417836SJohn.Forte@Sun.COM 
22427836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
22437836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
22447836SJohn.Forte@Sun.COM 
22457836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
22467836SJohn.Forte@Sun.COM 
22477836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
22487836SJohn.Forte@Sun.COM 
22497836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
22507836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
22517836SJohn.Forte@Sun.COM 
22527836SJohn.Forte@Sun.COM 	/*
22537836SJohn.Forte@Sun.COM 	 * The rdc set is configured but not yet enabled. Other operations must
22547836SJohn.Forte@Sun.COM 	 * ignore this set until it is enabled.
22557836SJohn.Forte@Sun.COM 	 */
22567836SJohn.Forte@Sun.COM 
22577836SJohn.Forte@Sun.COM 	urdc->sync_pos = 0;
22587836SJohn.Forte@Sun.COM 
22597836SJohn.Forte@Sun.COM 	if (rdc_set->maxqfbas > 0)
22607836SJohn.Forte@Sun.COM 		urdc->maxqfbas = rdc_set->maxqfbas;
22617836SJohn.Forte@Sun.COM 	else
22627836SJohn.Forte@Sun.COM 		urdc->maxqfbas = rdc_maxthres_queue;
22637836SJohn.Forte@Sun.COM 
22647836SJohn.Forte@Sun.COM 	if (rdc_set->maxqitems > 0)
22657836SJohn.Forte@Sun.COM 		urdc->maxqitems = rdc_set->maxqitems;
22667836SJohn.Forte@Sun.COM 	else
22677836SJohn.Forte@Sun.COM 		urdc->maxqitems = rdc_max_qitems;
22687836SJohn.Forte@Sun.COM 
22697836SJohn.Forte@Sun.COM 	if (rdc_set->asyncthr > 0)
22707836SJohn.Forte@Sun.COM 		urdc->asyncthr = rdc_set->asyncthr;
22717836SJohn.Forte@Sun.COM 	else
22727836SJohn.Forte@Sun.COM 		urdc->asyncthr = rdc_asyncthr;
22737836SJohn.Forte@Sun.COM 
22747836SJohn.Forte@Sun.COM 	if (urdc->autosync == -1) {
22757836SJohn.Forte@Sun.COM 		/* Still unknown */
22767836SJohn.Forte@Sun.COM 		if (rdc_set->autosync > 0)
22777836SJohn.Forte@Sun.COM 			urdc->autosync = 1;
22787836SJohn.Forte@Sun.COM 		else
22797836SJohn.Forte@Sun.COM 			urdc->autosync = 0;
22807836SJohn.Forte@Sun.COM 	}
22817836SJohn.Forte@Sun.COM 
22827836SJohn.Forte@Sun.COM 	urdc->netconfig = rdc_set->netconfig;
22837836SJohn.Forte@Sun.COM 
22847836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY) {
22857836SJohn.Forte@Sun.COM 		rhost = rdc_set->secondary.intf;
22867836SJohn.Forte@Sun.COM 		addrp = &rdc_set->secondary.addr;
22877836SJohn.Forte@Sun.COM 	} else {
22887836SJohn.Forte@Sun.COM 		rhost = rdc_set->primary.intf;
22897836SJohn.Forte@Sun.COM 		addrp = &rdc_set->primary.addr;
22907836SJohn.Forte@Sun.COM 	}
22917836SJohn.Forte@Sun.COM 
22927836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_ASYNC)
22937836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_ASYNC);
22947836SJohn.Forte@Sun.COM 
22957836SJohn.Forte@Sun.COM 	svp = rdc_create_svinfo(rhost, addrp, urdc->netconfig);
22967836SJohn.Forte@Sun.COM 	if (svp == NULL) {
22977836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, ENOMEM);
22987836SJohn.Forte@Sun.COM 		rc = ENOMEM;
22997836SJohn.Forte@Sun.COM 		goto fail;
23007836SJohn.Forte@Sun.COM 	}
23017836SJohn.Forte@Sun.COM 	urdc->netconfig = NULL;		/* This will be no good soon */
23027836SJohn.Forte@Sun.COM 
23037836SJohn.Forte@Sun.COM 	rdc_kstat_create(index);
23047836SJohn.Forte@Sun.COM 
23057836SJohn.Forte@Sun.COM 	/* Don't set krdc->intf here */
23067836SJohn.Forte@Sun.COM 
23077836SJohn.Forte@Sun.COM 	if (rdc_enable_bitmap(krdc, options & RDC_OPT_SETBMP) < 0)
23087836SJohn.Forte@Sun.COM 		goto bmpfail;
23097836SJohn.Forte@Sun.COM 
23107836SJohn.Forte@Sun.COM 	RDC_ZERO_BITREF(krdc);
23117836SJohn.Forte@Sun.COM 	if (krdc->lsrv == NULL)
23127836SJohn.Forte@Sun.COM 		krdc->lsrv = svp;
23137836SJohn.Forte@Sun.COM 	else {
23147836SJohn.Forte@Sun.COM #ifdef DEBUG
2315*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_rdc_enable: krdc->lsrv already set: %p",
2316*9093SRamana.Srikanth@Sun.COM 		    (void *) krdc->lsrv);
23177836SJohn.Forte@Sun.COM #endif
23187836SJohn.Forte@Sun.COM 		rdc_destroy_svinfo(svp);
23197836SJohn.Forte@Sun.COM 	}
23207836SJohn.Forte@Sun.COM 	svp = NULL;
23217836SJohn.Forte@Sun.COM 
23227836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
23237836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
23247836SJohn.Forte@Sun.COM 
23257836SJohn.Forte@Sun.COM 	/* And finally */
23267836SJohn.Forte@Sun.COM 
23277836SJohn.Forte@Sun.COM 	krdc->remote_index = -1;
23287836SJohn.Forte@Sun.COM 	/* Should we set the whole group logging? */
23297836SJohn.Forte@Sun.COM 	rdc_set_flags(urdc, RDC_ENABLED | RDC_LOGGING);
23307836SJohn.Forte@Sun.COM 
23317836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
23327836SJohn.Forte@Sun.COM 
23337836SJohn.Forte@Sun.COM 	if (rdc_intercept(krdc) != 0) {
23347836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
23357836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_ENABLED);
23367836SJohn.Forte@Sun.COM 		if (options & RDC_OPT_PRIMARY)
23377836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EREGISTER, urdc->primary.file);
23387836SJohn.Forte@Sun.COM 		else
23397836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EREGISTER,
23407836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
23417836SJohn.Forte@Sun.COM #ifdef DEBUG
2342*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!nsc_register_path failed %s",
23437836SJohn.Forte@Sun.COM 		    urdc->primary.file);
23447836SJohn.Forte@Sun.COM #endif
23457836SJohn.Forte@Sun.COM 		rc = RDC_EREGISTER;
23467836SJohn.Forte@Sun.COM 		goto bmpfail;
23477836SJohn.Forte@Sun.COM 	}
23487836SJohn.Forte@Sun.COM #ifdef DEBUG
2349*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR: enabled %s %s", urdc->primary.file,
23507836SJohn.Forte@Sun.COM 	    urdc->secondary.file);
23517836SJohn.Forte@Sun.COM #endif
23527836SJohn.Forte@Sun.COM 
23537836SJohn.Forte@Sun.COM 	rdc_write_state(urdc);
23547836SJohn.Forte@Sun.COM 
23557836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
23567836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
23577836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
23587836SJohn.Forte@Sun.COM 
23597836SJohn.Forte@Sun.COM 	return (0);
23607836SJohn.Forte@Sun.COM 
23617836SJohn.Forte@Sun.COM bmpfail:
23627836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
23637836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBITMAP, rdc_set->primary.bitmap);
23647836SJohn.Forte@Sun.COM 	else
23657836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBITMAP, rdc_set->secondary.bitmap);
23667836SJohn.Forte@Sun.COM 	rc = RDC_EBITMAP;
23677836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_ENABLED) {
23687836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
23697836SJohn.Forte@Sun.COM 		(void) rdc_unintercept(krdc);
23707836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
23717836SJohn.Forte@Sun.COM 	}
23727836SJohn.Forte@Sun.COM 
23737836SJohn.Forte@Sun.COM fail:
23747836SJohn.Forte@Sun.COM 	rdc_kstat_delete(index);
23757836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
23767836SJohn.Forte@Sun.COM 	if (krdc->intf) {
23777836SJohn.Forte@Sun.COM 		rdc_if_t *ip = krdc->intf;
23787836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
23797836SJohn.Forte@Sun.COM 		krdc->intf = NULL;
23807836SJohn.Forte@Sun.COM 		rdc_remove_from_if(ip);
23817836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
23827836SJohn.Forte@Sun.COM 	}
23837836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
23847836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
23857836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
23867836SJohn.Forte@Sun.COM 
23877836SJohn.Forte@Sun.COM 	rdc_dev_close(krdc);
23887836SJohn.Forte@Sun.COM 	rdc_close_direct(krdc);
23897836SJohn.Forte@Sun.COM 	rdc_destroy_svinfo(svp);
23907836SJohn.Forte@Sun.COM 
23917836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
23927836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
23937836SJohn.Forte@Sun.COM 
23947836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
23957836SJohn.Forte@Sun.COM 
23967836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
23977836SJohn.Forte@Sun.COM 
23987836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
23997836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
24007836SJohn.Forte@Sun.COM 
24017836SJohn.Forte@Sun.COM 	remove_from_group(krdc);
24027836SJohn.Forte@Sun.COM 
24037836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) || IS_MULTI(krdc))
24047836SJohn.Forte@Sun.COM 		remove_from_many(krdc);
24057836SJohn.Forte@Sun.COM 
24067836SJohn.Forte@Sun.COM 	rdc_u_init(urdc);
24077836SJohn.Forte@Sun.COM 
24087836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_CONFIGURED);
24097836SJohn.Forte@Sun.COM 	krdc->type_flag = 0;
24107836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
24117836SJohn.Forte@Sun.COM 
24127836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
24137836SJohn.Forte@Sun.COM 
24147836SJohn.Forte@Sun.COM 	return (rc);
24157836SJohn.Forte@Sun.COM }
24167836SJohn.Forte@Sun.COM 
24177836SJohn.Forte@Sun.COM static int
rdc_enable(rdc_config_t * uparms,spcs_s_info_t kstatus)24187836SJohn.Forte@Sun.COM rdc_enable(rdc_config_t *uparms, spcs_s_info_t kstatus)
24197836SJohn.Forte@Sun.COM {
24207836SJohn.Forte@Sun.COM 	int rc;
24217836SJohn.Forte@Sun.COM 	char itmp[10];
24227836SJohn.Forte@Sun.COM 
24237836SJohn.Forte@Sun.COM 	if (!(uparms->options & RDC_OPT_SYNC) &&
24247836SJohn.Forte@Sun.COM 	    !(uparms->options & RDC_OPT_ASYNC)) {
24257836SJohn.Forte@Sun.COM 		rc = RDC_EEINVAL;
24267836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
24277836SJohn.Forte@Sun.COM 		    uparms->options, itmp, sizeof (itmp), 1);
24287836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEINVAL, itmp);
24297836SJohn.Forte@Sun.COM 		goto done;
24307836SJohn.Forte@Sun.COM 	}
24317836SJohn.Forte@Sun.COM 
24327836SJohn.Forte@Sun.COM 	if (!(uparms->options & RDC_OPT_PRIMARY) &&
24337836SJohn.Forte@Sun.COM 	    !(uparms->options & RDC_OPT_SECONDARY)) {
24347836SJohn.Forte@Sun.COM 		rc = RDC_EEINVAL;
24357836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
24367836SJohn.Forte@Sun.COM 		    uparms->options, itmp, sizeof (itmp), 1);
24377836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEINVAL, itmp);
24387836SJohn.Forte@Sun.COM 		goto done;
24397836SJohn.Forte@Sun.COM 	}
24407836SJohn.Forte@Sun.COM 
24417836SJohn.Forte@Sun.COM 	if (!(uparms->options & RDC_OPT_SETBMP) &&
24427836SJohn.Forte@Sun.COM 	    !(uparms->options & RDC_OPT_CLRBMP)) {
24437836SJohn.Forte@Sun.COM 		rc = RDC_EEINVAL;
24447836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
24457836SJohn.Forte@Sun.COM 		    uparms->options, itmp, sizeof (itmp), 1);
24467836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEINVAL, itmp);
24477836SJohn.Forte@Sun.COM 		goto done;
24487836SJohn.Forte@Sun.COM 	}
24497836SJohn.Forte@Sun.COM 
24507836SJohn.Forte@Sun.COM 	rc = _rdc_enable(uparms->rdc_set, uparms->options, kstatus);
24517836SJohn.Forte@Sun.COM done:
24527836SJohn.Forte@Sun.COM 	return (rc);
24537836SJohn.Forte@Sun.COM }
24547836SJohn.Forte@Sun.COM 
24557836SJohn.Forte@Sun.COM /* ARGSUSED */
24567836SJohn.Forte@Sun.COM static int
_rdc_disable(rdc_k_info_t * krdc,rdc_config_t * uap,spcs_s_info_t kstatus)24577836SJohn.Forte@Sun.COM _rdc_disable(rdc_k_info_t *krdc, rdc_config_t *uap, spcs_s_info_t kstatus)
24587836SJohn.Forte@Sun.COM {
24597836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
24607836SJohn.Forte@Sun.COM 	rdc_if_t *ip;
24617836SJohn.Forte@Sun.COM 	int index = krdc->index;
24627836SJohn.Forte@Sun.COM 	disk_queue *q;
24637836SJohn.Forte@Sun.COM 	rdc_set_t *rdc_set = uap->rdc_set;
24647836SJohn.Forte@Sun.COM 
24657836SJohn.Forte@Sun.COM 	ASSERT(krdc->group != NULL);
24667836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
24677836SJohn.Forte@Sun.COM #ifdef DEBUG
24687836SJohn.Forte@Sun.COM 	ASSERT(rdc_check(krdc, rdc_set) == 0);
24697836SJohn.Forte@Sun.COM #else
24707836SJohn.Forte@Sun.COM 	if (((uap->options & RDC_OPT_FORCE_DISABLE) == 0) &&
24717836SJohn.Forte@Sun.COM 	    rdc_check(krdc, rdc_set)) {
24727836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
24737836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
24747836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
24757836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
24767836SJohn.Forte@Sun.COM 	}
24777836SJohn.Forte@Sun.COM #endif
24787836SJohn.Forte@Sun.COM 
24797836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
24807836SJohn.Forte@Sun.COM 		halt_sync(krdc);
24817836SJohn.Forte@Sun.COM 		ASSERT(IS_ENABLED(urdc));
24827836SJohn.Forte@Sun.COM 	}
24837836SJohn.Forte@Sun.COM 	q = &krdc->group->diskq;
24847836SJohn.Forte@Sun.COM 
24857836SJohn.Forte@Sun.COM 	if (IS_ASYNC(urdc) && RDC_IS_DISKQ(krdc->group) &&
24867836SJohn.Forte@Sun.COM 	    ((!IS_STATE(urdc, RDC_LOGGING)) && (!QEMPTY(q)))) {
24877836SJohn.Forte@Sun.COM 		krdc->type_flag &= ~RDC_DISABLEPEND;
24887836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
24897836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EQNOTEMPTY, urdc->disk_queue);
24907836SJohn.Forte@Sun.COM 		return (RDC_EQNOTEMPTY);
24917836SJohn.Forte@Sun.COM 	}
24927836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
24937836SJohn.Forte@Sun.COM 	(void) rdc_unintercept(krdc);
24947836SJohn.Forte@Sun.COM 
24957836SJohn.Forte@Sun.COM #ifdef DEBUG
2496*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR: disabled %s %s", urdc->primary.file,
24977836SJohn.Forte@Sun.COM 	    urdc->secondary.file);
24987836SJohn.Forte@Sun.COM #endif
24997836SJohn.Forte@Sun.COM 
25007836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
25017836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
25027836SJohn.Forte@Sun.COM 
25037836SJohn.Forte@Sun.COM 	/*
25047836SJohn.Forte@Sun.COM 	 * No new io can come in through the io provider.
25057836SJohn.Forte@Sun.COM 	 * Wait for the async flusher to finish.
25067836SJohn.Forte@Sun.COM 	 */
25077836SJohn.Forte@Sun.COM 
25087836SJohn.Forte@Sun.COM 	if (IS_ASYNC(urdc) && !RDC_IS_DISKQ(krdc->group)) {
25097836SJohn.Forte@Sun.COM 		int tries = 2; /* in case of hopelessly stuck flusher threads */
25107836SJohn.Forte@Sun.COM #ifdef DEBUG
25117836SJohn.Forte@Sun.COM 		net_queue *qp = &krdc->group->ra_queue;
25127836SJohn.Forte@Sun.COM #endif
25137836SJohn.Forte@Sun.COM 		do {
25147836SJohn.Forte@Sun.COM 			if (!krdc->group->rdc_writer)
25157836SJohn.Forte@Sun.COM 				(void) rdc_writer(krdc->index);
25167836SJohn.Forte@Sun.COM 
25177836SJohn.Forte@Sun.COM 			(void) rdc_drain_queue(krdc->index);
25187836SJohn.Forte@Sun.COM 
25197836SJohn.Forte@Sun.COM 		} while (krdc->group->rdc_writer && tries--);
25207836SJohn.Forte@Sun.COM 
25217836SJohn.Forte@Sun.COM 		/* ok, force it to happen... */
25227836SJohn.Forte@Sun.COM 		if (rdc_drain_queue(krdc->index) != 0) {
25237836SJohn.Forte@Sun.COM 			do {
25247836SJohn.Forte@Sun.COM 				mutex_enter(&krdc->group->ra_queue.net_qlock);
25257836SJohn.Forte@Sun.COM 				krdc->group->asyncdis = 1;
25267836SJohn.Forte@Sun.COM 				cv_broadcast(&krdc->group->asyncqcv);
25277836SJohn.Forte@Sun.COM 				mutex_exit(&krdc->group->ra_queue.net_qlock);
25287836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
2529*9093SRamana.Srikanth@Sun.COM 				    "!SNDR: async I/O pending and not flushed "
2530*9093SRamana.Srikanth@Sun.COM 				    "for %s during disable",
25317836SJohn.Forte@Sun.COM 				    urdc->primary.file);
25327836SJohn.Forte@Sun.COM #ifdef DEBUG
25337836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
2534*9093SRamana.Srikanth@Sun.COM 				    "!nitems: %" NSC_SZFMT " nblocks: %"
2535*9093SRamana.Srikanth@Sun.COM 				    NSC_SZFMT " head: 0x%p tail: 0x%p",
2536*9093SRamana.Srikanth@Sun.COM 				    qp->nitems, qp->blocks,
2537*9093SRamana.Srikanth@Sun.COM 				    (void *)qp->net_qhead,
2538*9093SRamana.Srikanth@Sun.COM 				    (void *)qp->net_qtail);
25397836SJohn.Forte@Sun.COM #endif
25407836SJohn.Forte@Sun.COM 			} while (krdc->group->rdc_thrnum > 0);
25417836SJohn.Forte@Sun.COM 		}
25427836SJohn.Forte@Sun.COM 	}
25437836SJohn.Forte@Sun.COM 
25447836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
25457836SJohn.Forte@Sun.COM 	ip = krdc->intf;
25467836SJohn.Forte@Sun.COM 	krdc->intf = 0;
25477836SJohn.Forte@Sun.COM 
25487836SJohn.Forte@Sun.COM 	if (ip) {
25497836SJohn.Forte@Sun.COM 		rdc_remove_from_if(ip);
25507836SJohn.Forte@Sun.COM 	}
25517836SJohn.Forte@Sun.COM 
25527836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
25537836SJohn.Forte@Sun.COM 
25547836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
25557836SJohn.Forte@Sun.COM 
25567836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
25577836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
25587836SJohn.Forte@Sun.COM 
25597836SJohn.Forte@Sun.COM 	/* Must not hold group lock during this function */
25607836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
25617836SJohn.Forte@Sun.COM 	while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
25627836SJohn.Forte@Sun.COM 		delay(2);
25637836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
25647836SJohn.Forte@Sun.COM 
25657836SJohn.Forte@Sun.COM 	(void) rdc_clear_state(krdc);
25667836SJohn.Forte@Sun.COM 
25677836SJohn.Forte@Sun.COM 	rdc_free_bitmap(krdc, RDC_CMD_DISABLE);
25687836SJohn.Forte@Sun.COM 	rdc_close_bitmap(krdc);
25697836SJohn.Forte@Sun.COM 
25707836SJohn.Forte@Sun.COM 	rdc_dev_close(krdc);
25717836SJohn.Forte@Sun.COM 	rdc_close_direct(krdc);
25727836SJohn.Forte@Sun.COM 
25737836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
25747836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
25757836SJohn.Forte@Sun.COM 
25767836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
25777836SJohn.Forte@Sun.COM 
25787836SJohn.Forte@Sun.COM 	/*
25797836SJohn.Forte@Sun.COM 	 * we should now unregister the queue, with no conflicting
25807836SJohn.Forte@Sun.COM 	 * locks held. This is the last(only) member of the group
25817836SJohn.Forte@Sun.COM 	 */
25827836SJohn.Forte@Sun.COM 	if (krdc->group && RDC_IS_DISKQ(krdc->group) &&
25837836SJohn.Forte@Sun.COM 	    krdc->group->count == 1) { /* stop protecting queue */
25847836SJohn.Forte@Sun.COM 		rdc_unintercept_diskq(krdc->group);
25857836SJohn.Forte@Sun.COM 	}
25867836SJohn.Forte@Sun.COM 
25877836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
25887836SJohn.Forte@Sun.COM 
25897836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
25907836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
25917836SJohn.Forte@Sun.COM 
25927836SJohn.Forte@Sun.COM 	wait_busy(krdc);
25937836SJohn.Forte@Sun.COM 
25947836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) || IS_MULTI(krdc))
25957836SJohn.Forte@Sun.COM 		remove_from_many(krdc);
25967836SJohn.Forte@Sun.COM 
25977836SJohn.Forte@Sun.COM 	remove_from_group(krdc);
25987836SJohn.Forte@Sun.COM 
25997836SJohn.Forte@Sun.COM 	krdc->remote_index = -1;
26007836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_CONFIGURED);
26017836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_DISABLEPEND);
26027836SJohn.Forte@Sun.COM 	krdc->type_flag = 0;
26037836SJohn.Forte@Sun.COM #ifdef	DEBUG
26047836SJohn.Forte@Sun.COM 	if (krdc->dcio_bitmap)
2605*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_rdc_disable: possible mem leak, "
26067836SJohn.Forte@Sun.COM 		    "dcio_bitmap");
26077836SJohn.Forte@Sun.COM #endif
26087836SJohn.Forte@Sun.COM 	krdc->dcio_bitmap = NULL;
26097836SJohn.Forte@Sun.COM 	krdc->bitmap_ref = NULL;
26107836SJohn.Forte@Sun.COM 	krdc->bitmap_size = 0;
26117836SJohn.Forte@Sun.COM 	krdc->maxfbas = 0;
26127836SJohn.Forte@Sun.COM 	krdc->bitmap_write = 0;
26137836SJohn.Forte@Sun.COM 	krdc->disk_status = 0;
26147836SJohn.Forte@Sun.COM 	rdc_destroy_svinfo(krdc->lsrv);
26157836SJohn.Forte@Sun.COM 	krdc->lsrv = NULL;
26167836SJohn.Forte@Sun.COM 	krdc->multi_next = NULL;
26177836SJohn.Forte@Sun.COM 
26187836SJohn.Forte@Sun.COM 	rdc_u_init(urdc);
26197836SJohn.Forte@Sun.COM 
26207836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
26217836SJohn.Forte@Sun.COM 	rdc_kstat_delete(index);
26227836SJohn.Forte@Sun.COM 
26237836SJohn.Forte@Sun.COM 	return (0);
26247836SJohn.Forte@Sun.COM }
26257836SJohn.Forte@Sun.COM 
26267836SJohn.Forte@Sun.COM static int
rdc_disable(rdc_config_t * uparms,spcs_s_info_t kstatus)26277836SJohn.Forte@Sun.COM rdc_disable(rdc_config_t *uparms, spcs_s_info_t kstatus)
26287836SJohn.Forte@Sun.COM {
26297836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
26307836SJohn.Forte@Sun.COM 	int index;
26317836SJohn.Forte@Sun.COM 	int rc;
26327836SJohn.Forte@Sun.COM 
26337836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
26347836SJohn.Forte@Sun.COM 
26357836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
26367836SJohn.Forte@Sun.COM 	if (index >= 0)
26377836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
26387836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
26397836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
26407836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
26417836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
26427836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
26437836SJohn.Forte@Sun.COM 	}
26447836SJohn.Forte@Sun.COM 
26457836SJohn.Forte@Sun.COM 	krdc->type_flag |= RDC_DISABLEPEND;
26467836SJohn.Forte@Sun.COM 	wait_busy(krdc);
26477836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
26487836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
26497836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
26507836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
26517836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
26527836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
26537836SJohn.Forte@Sun.COM 	}
26547836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
26557836SJohn.Forte@Sun.COM 
26567836SJohn.Forte@Sun.COM 	rc = _rdc_disable(krdc, uparms, kstatus);
26577836SJohn.Forte@Sun.COM 	return (rc);
26587836SJohn.Forte@Sun.COM }
26597836SJohn.Forte@Sun.COM 
26607836SJohn.Forte@Sun.COM 
26617836SJohn.Forte@Sun.COM /*
26627836SJohn.Forte@Sun.COM  * Checks whether the state of one of the other sets in the 1-many or
26637836SJohn.Forte@Sun.COM  * multi-hop config should prevent a sync from starting on this one.
26647836SJohn.Forte@Sun.COM  * Return NULL if no just cause or impediment is found, otherwise return
26657836SJohn.Forte@Sun.COM  * a pointer to the offending set.
26667836SJohn.Forte@Sun.COM  */
26677836SJohn.Forte@Sun.COM static rdc_u_info_t *
rdc_allow_pri_sync(rdc_u_info_t * urdc,int options)26687836SJohn.Forte@Sun.COM rdc_allow_pri_sync(rdc_u_info_t *urdc, int options)
26697836SJohn.Forte@Sun.COM {
26707836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
26717836SJohn.Forte@Sun.COM 	rdc_k_info_t *ktmp;
26727836SJohn.Forte@Sun.COM 	rdc_u_info_t *utmp;
26737836SJohn.Forte@Sun.COM 	rdc_k_info_t *kmulti = NULL;
26747836SJohn.Forte@Sun.COM 
26757836SJohn.Forte@Sun.COM 	ASSERT(rdc_get_vflags(urdc) & RDC_PRIMARY);
26767836SJohn.Forte@Sun.COM 
26777836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
26787836SJohn.Forte@Sun.COM 
26797836SJohn.Forte@Sun.COM 	/*
26807836SJohn.Forte@Sun.COM 	 * In the reverse sync case we need to check the previous leg of
26817836SJohn.Forte@Sun.COM 	 * the multi-hop config. The link to that set can be from any of
26827836SJohn.Forte@Sun.COM 	 * the 1-many list, so as we go through we keep an eye open for it.
26837836SJohn.Forte@Sun.COM 	 */
26847836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_REVERSE) && (IS_MULTI(krdc))) {
26857836SJohn.Forte@Sun.COM 		/* This set links to the first leg */
26867836SJohn.Forte@Sun.COM 		ktmp = krdc->multi_next;
26877836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[ktmp->index];
26887836SJohn.Forte@Sun.COM 		if (IS_ENABLED(utmp))
26897836SJohn.Forte@Sun.COM 			kmulti = ktmp;
26907836SJohn.Forte@Sun.COM 	}
26917836SJohn.Forte@Sun.COM 
26927836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc)) {
26937836SJohn.Forte@Sun.COM 		for (ktmp = krdc->many_next; ktmp != krdc;
26947836SJohn.Forte@Sun.COM 		    ktmp = ktmp->many_next) {
26957836SJohn.Forte@Sun.COM 			utmp = &rdc_u_info[ktmp->index];
26967836SJohn.Forte@Sun.COM 
26977836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(utmp))
26987836SJohn.Forte@Sun.COM 				continue;
26997836SJohn.Forte@Sun.COM 
27007836SJohn.Forte@Sun.COM 			if (options & RDC_OPT_FORWARD) {
27017836SJohn.Forte@Sun.COM 				/*
27027836SJohn.Forte@Sun.COM 				 * Reverse sync needed is bad, as it means a
27037836SJohn.Forte@Sun.COM 				 * reverse sync in progress or started and
27047836SJohn.Forte@Sun.COM 				 * didn't complete, so this primary volume
27057836SJohn.Forte@Sun.COM 				 * is not consistent. So we shouldn't copy
27067836SJohn.Forte@Sun.COM 				 * it to its secondary.
27077836SJohn.Forte@Sun.COM 				 */
27087836SJohn.Forte@Sun.COM 				if (rdc_get_mflags(utmp) & RDC_RSYNC_NEEDED) {
27097836SJohn.Forte@Sun.COM 					rdc_many_exit(krdc);
27107836SJohn.Forte@Sun.COM 					return (utmp);
27117836SJohn.Forte@Sun.COM 				}
27127836SJohn.Forte@Sun.COM 			} else {
27137836SJohn.Forte@Sun.COM 				/* Reverse, so see if we need to spot kmulti */
27147836SJohn.Forte@Sun.COM 				if ((kmulti == NULL) && (IS_MULTI(ktmp))) {
27157836SJohn.Forte@Sun.COM 					/* This set links to the first leg */
27167836SJohn.Forte@Sun.COM 					kmulti = ktmp->multi_next;
27177836SJohn.Forte@Sun.COM 					if (!IS_ENABLED(
27187836SJohn.Forte@Sun.COM 					    &rdc_u_info[kmulti->index]))
27197836SJohn.Forte@Sun.COM 						kmulti = NULL;
27207836SJohn.Forte@Sun.COM 				}
27217836SJohn.Forte@Sun.COM 
27227836SJohn.Forte@Sun.COM 				/*
27237836SJohn.Forte@Sun.COM 				 * Non-logging is bad, as the bitmap will
27247836SJohn.Forte@Sun.COM 				 * be updated with the bits for this sync.
27257836SJohn.Forte@Sun.COM 				 */
27267836SJohn.Forte@Sun.COM 				if (!(rdc_get_vflags(utmp) & RDC_LOGGING)) {
27277836SJohn.Forte@Sun.COM 					rdc_many_exit(krdc);
27287836SJohn.Forte@Sun.COM 					return (utmp);
27297836SJohn.Forte@Sun.COM 				}
27307836SJohn.Forte@Sun.COM 			}
27317836SJohn.Forte@Sun.COM 		}
27327836SJohn.Forte@Sun.COM 	}
27337836SJohn.Forte@Sun.COM 
27347836SJohn.Forte@Sun.COM 	if (kmulti) {
27357836SJohn.Forte@Sun.COM 		utmp = &rdc_u_info[kmulti->index];
27367836SJohn.Forte@Sun.COM 		ktmp = kmulti;	/* In case we decide we do need to use ktmp */
27377836SJohn.Forte@Sun.COM 
27387836SJohn.Forte@Sun.COM 		ASSERT(options & RDC_OPT_REVERSE);
27397836SJohn.Forte@Sun.COM 
27407836SJohn.Forte@Sun.COM 		if (IS_REPLICATING(utmp)) {
27417836SJohn.Forte@Sun.COM 			/*
27427836SJohn.Forte@Sun.COM 			 * Replicating is bad as data is already flowing to
27437836SJohn.Forte@Sun.COM 			 * the target of the requested sync operation.
27447836SJohn.Forte@Sun.COM 			 */
27457836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
27467836SJohn.Forte@Sun.COM 			return (utmp);
27477836SJohn.Forte@Sun.COM 		}
27487836SJohn.Forte@Sun.COM 
27497836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(utmp) & RDC_SYNCING) {
27507836SJohn.Forte@Sun.COM 			/*
27517836SJohn.Forte@Sun.COM 			 * Forward sync in progress is bad, as data is
27527836SJohn.Forte@Sun.COM 			 * already flowing to the target of the requested
27537836SJohn.Forte@Sun.COM 			 * sync operation.
27547836SJohn.Forte@Sun.COM 			 * Reverse sync in progress is bad, as the primary
27557836SJohn.Forte@Sun.COM 			 * has already decided which data to copy.
27567836SJohn.Forte@Sun.COM 			 */
27577836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
27587836SJohn.Forte@Sun.COM 			return (utmp);
27597836SJohn.Forte@Sun.COM 		}
27607836SJohn.Forte@Sun.COM 
27617836SJohn.Forte@Sun.COM 		/*
27627836SJohn.Forte@Sun.COM 		 * Clear the "sync needed" flags, as the multi-hop secondary
27637836SJohn.Forte@Sun.COM 		 * will be updated via this requested sync operation, so does
27647836SJohn.Forte@Sun.COM 		 * not need to complete its aborted forward sync.
27657836SJohn.Forte@Sun.COM 		 */
27667836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(utmp) & RDC_SYNC_NEEDED)
27677836SJohn.Forte@Sun.COM 			rdc_clr_flags(utmp, RDC_SYNC_NEEDED);
27687836SJohn.Forte@Sun.COM 	}
27697836SJohn.Forte@Sun.COM 
27707836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) && (options & RDC_OPT_REVERSE)) {
27717836SJohn.Forte@Sun.COM 		for (ktmp = krdc->many_next; ktmp != krdc;
27727836SJohn.Forte@Sun.COM 		    ktmp = ktmp->many_next) {
27737836SJohn.Forte@Sun.COM 			utmp = &rdc_u_info[ktmp->index];
27747836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(utmp))
27757836SJohn.Forte@Sun.COM 				continue;
27767836SJohn.Forte@Sun.COM 
27777836SJohn.Forte@Sun.COM 			/*
27787836SJohn.Forte@Sun.COM 			 * Clear any "reverse sync needed" flags, as the
27797836SJohn.Forte@Sun.COM 			 * volume will be updated via this requested
27807836SJohn.Forte@Sun.COM 			 * sync operation, so does not need to complete
27817836SJohn.Forte@Sun.COM 			 * its aborted reverse sync.
27827836SJohn.Forte@Sun.COM 			 */
27837836SJohn.Forte@Sun.COM 			if (rdc_get_mflags(utmp) & RDC_RSYNC_NEEDED)
27847836SJohn.Forte@Sun.COM 				rdc_clr_mflags(utmp, RDC_RSYNC_NEEDED);
27857836SJohn.Forte@Sun.COM 		}
27867836SJohn.Forte@Sun.COM 	}
27877836SJohn.Forte@Sun.COM 
27887836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
27897836SJohn.Forte@Sun.COM 
27907836SJohn.Forte@Sun.COM 	return (NULL);
27917836SJohn.Forte@Sun.COM }
27927836SJohn.Forte@Sun.COM 
27937836SJohn.Forte@Sun.COM static void
_rdc_sync_wrthr(void * thrinfo)27947836SJohn.Forte@Sun.COM _rdc_sync_wrthr(void *thrinfo)
27957836SJohn.Forte@Sun.COM {
27967836SJohn.Forte@Sun.COM 	rdc_syncthr_t *syncinfo = (rdc_syncthr_t *)thrinfo;
27977836SJohn.Forte@Sun.COM 	nsc_buf_t *handle = NULL;
27987836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = syncinfo->krdc;
27997836SJohn.Forte@Sun.COM 	int rc;
28007836SJohn.Forte@Sun.COM 	int tries = 0;
28017836SJohn.Forte@Sun.COM 
2802*9093SRamana.Srikanth@Sun.COM 	DTRACE_PROBE2(rdc_sync_loop_netwrite_start, int, krdc->index,
2803*9093SRamana.Srikanth@Sun.COM 	    nsc_buf_t *, handle);
28047836SJohn.Forte@Sun.COM 
28057836SJohn.Forte@Sun.COM retry:
28067836SJohn.Forte@Sun.COM 	rc = nsc_alloc_buf(RDC_U_FD(krdc), syncinfo->offset, syncinfo->len,
28077836SJohn.Forte@Sun.COM 	    NSC_READ | NSC_NOCACHE, &handle);
28087836SJohn.Forte@Sun.COM 
28097836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(rc) || krdc->remote_index < 0) {
28107836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_sync_wrthr_alloc_buf_err);
28117836SJohn.Forte@Sun.COM 		goto failed;
28127836SJohn.Forte@Sun.COM 	}
28137836SJohn.Forte@Sun.COM 
28147836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
28157836SJohn.Forte@Sun.COM 	if ((krdc->disk_status == 1) || (krdc->dcio_bitmap == NULL)) {
28167836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
28177836SJohn.Forte@Sun.COM 		goto failed;
28187836SJohn.Forte@Sun.COM 	}
28197836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
28207836SJohn.Forte@Sun.COM 
28217836SJohn.Forte@Sun.COM 	if ((rc = rdc_net_write(krdc->index, krdc->remote_index, handle,
28227836SJohn.Forte@Sun.COM 	    handle->sb_pos, handle->sb_len, RDC_NOSEQ, RDC_NOQUE, NULL)) > 0) {
28237836SJohn.Forte@Sun.COM 		rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
28247836SJohn.Forte@Sun.COM 
28257836SJohn.Forte@Sun.COM 		/*
28267836SJohn.Forte@Sun.COM 		 * The following is to handle
28277836SJohn.Forte@Sun.COM 		 * the case where the secondary side
28287836SJohn.Forte@Sun.COM 		 * has thrown our buffer handle token away in a
28297836SJohn.Forte@Sun.COM 		 * attempt to preserve its health on restart
28307836SJohn.Forte@Sun.COM 		 */
28317836SJohn.Forte@Sun.COM 		if ((rc == EPROTO) && (tries < 3)) {
28327836SJohn.Forte@Sun.COM 			(void) nsc_free_buf(handle);
28337836SJohn.Forte@Sun.COM 			handle = NULL;
28347836SJohn.Forte@Sun.COM 			tries++;
28357836SJohn.Forte@Sun.COM 			delay(HZ >> 2);
28367836SJohn.Forte@Sun.COM 			goto retry;
28377836SJohn.Forte@Sun.COM 		}
28387836SJohn.Forte@Sun.COM 
28397836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_sync_wrthr_remote_write_err);
2840*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_sync_wrthr: remote write failed (%d) "
28417836SJohn.Forte@Sun.COM 		    "0x%x", rc, rdc_get_vflags(urdc));
28427836SJohn.Forte@Sun.COM 
28437836SJohn.Forte@Sun.COM 		goto failed;
28447836SJohn.Forte@Sun.COM 	}
28457836SJohn.Forte@Sun.COM 	(void) nsc_free_buf(handle);
28467836SJohn.Forte@Sun.COM 	handle = NULL;
28477836SJohn.Forte@Sun.COM 
28487836SJohn.Forte@Sun.COM 	return;
28497836SJohn.Forte@Sun.COM failed:
28507836SJohn.Forte@Sun.COM 	(void) nsc_free_buf(handle);
28517836SJohn.Forte@Sun.COM 	syncinfo->status->offset = syncinfo->offset;
28527836SJohn.Forte@Sun.COM }
28537836SJohn.Forte@Sun.COM 
28547836SJohn.Forte@Sun.COM /*
28557836SJohn.Forte@Sun.COM  * see above comments on _rdc_sync_wrthr
28567836SJohn.Forte@Sun.COM  */
28577836SJohn.Forte@Sun.COM static void
_rdc_sync_rdthr(void * thrinfo)28587836SJohn.Forte@Sun.COM _rdc_sync_rdthr(void *thrinfo)
28597836SJohn.Forte@Sun.COM {
28607836SJohn.Forte@Sun.COM 	rdc_syncthr_t *syncinfo = (rdc_syncthr_t *)thrinfo;
28617836SJohn.Forte@Sun.COM 	nsc_buf_t *handle = NULL;
28627836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = syncinfo->krdc;
28637836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
28647836SJohn.Forte@Sun.COM 	int rc;
28657836SJohn.Forte@Sun.COM 
28667836SJohn.Forte@Sun.COM 	rc = nsc_alloc_buf(RDC_U_FD(krdc), syncinfo->offset, syncinfo->len,
28677836SJohn.Forte@Sun.COM 	    NSC_WRITE | NSC_WRTHRU | NSC_NOCACHE, &handle);
28687836SJohn.Forte@Sun.COM 
28697836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(rc) || krdc->remote_index < 0) {
28707836SJohn.Forte@Sun.COM 		goto failed;
28717836SJohn.Forte@Sun.COM 	}
28727836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
28737836SJohn.Forte@Sun.COM 	if ((krdc->disk_status == 1) || (krdc->dcio_bitmap == NULL)) {
28747836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
28757836SJohn.Forte@Sun.COM 		goto failed;
28767836SJohn.Forte@Sun.COM 	}
28777836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
28787836SJohn.Forte@Sun.COM 
28797836SJohn.Forte@Sun.COM 	rc = rdc_net_read(krdc->index, krdc->remote_index, handle,
28807836SJohn.Forte@Sun.COM 	    handle->sb_pos, handle->sb_len);
28817836SJohn.Forte@Sun.COM 
28827836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(rc)) {
2883*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_sync_rdthr: remote read failed(%d)", rc);
28847836SJohn.Forte@Sun.COM 		goto failed;
28857836SJohn.Forte@Sun.COM 	}
28867836SJohn.Forte@Sun.COM 	if (!IS_STATE(urdc, RDC_FULL))
28877836SJohn.Forte@Sun.COM 		rdc_set_bitmap_many(krdc, handle->sb_pos, handle->sb_len);
28887836SJohn.Forte@Sun.COM 
28897836SJohn.Forte@Sun.COM 	rc = nsc_write(handle, handle->sb_pos, handle->sb_len, 0);
28907836SJohn.Forte@Sun.COM 
28917836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(rc)) {
28927836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
28937836SJohn.Forte@Sun.COM 		rdc_set_flags_log(urdc, RDC_VOL_FAILED, "nsc_write failed");
28947836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
28957836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
28967836SJohn.Forte@Sun.COM 		goto failed;
28977836SJohn.Forte@Sun.COM 	}
28987836SJohn.Forte@Sun.COM 
28997836SJohn.Forte@Sun.COM 	(void) nsc_free_buf(handle);
29007836SJohn.Forte@Sun.COM 	handle = NULL;
29017836SJohn.Forte@Sun.COM 
29027836SJohn.Forte@Sun.COM 	return;
29037836SJohn.Forte@Sun.COM failed:
29047836SJohn.Forte@Sun.COM 	(void) nsc_free_buf(handle);
29057836SJohn.Forte@Sun.COM 	syncinfo->status->offset = syncinfo->offset;
29067836SJohn.Forte@Sun.COM }
29077836SJohn.Forte@Sun.COM 
29087836SJohn.Forte@Sun.COM /*
29097836SJohn.Forte@Sun.COM  * _rdc_sync_wrthr
29107836SJohn.Forte@Sun.COM  * sync loop write thread
29117836SJohn.Forte@Sun.COM  * if there are avail threads, we have not
29127836SJohn.Forte@Sun.COM  * used up the pipe, so the sync loop will, if
29137836SJohn.Forte@Sun.COM  * possible use these to multithread the write/read
29147836SJohn.Forte@Sun.COM  */
29157836SJohn.Forte@Sun.COM void
_rdc_sync_thread(void * thrinfo)29167836SJohn.Forte@Sun.COM _rdc_sync_thread(void *thrinfo)
29177836SJohn.Forte@Sun.COM {
29187836SJohn.Forte@Sun.COM 	rdc_syncthr_t *syncinfo = (rdc_syncthr_t *)thrinfo;
29197836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = syncinfo->krdc;
29207836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
29217836SJohn.Forte@Sun.COM 	rdc_thrsync_t *sync = &krdc->syncs;
29227836SJohn.Forte@Sun.COM 	uint_t bitmask;
29237836SJohn.Forte@Sun.COM 	int rc;
29247836SJohn.Forte@Sun.COM 
29257836SJohn.Forte@Sun.COM 	rc = _rdc_rsrv_devs(krdc, RDC_RAW, RDC_INTERNAL);
29267836SJohn.Forte@Sun.COM 	if (!RDC_SUCCESS(rc))
29277836SJohn.Forte@Sun.COM 		goto failed;
29287836SJohn.Forte@Sun.COM 
29297836SJohn.Forte@Sun.COM 	if (IS_STATE(urdc, RDC_SLAVE))
29307836SJohn.Forte@Sun.COM 		_rdc_sync_rdthr(thrinfo);
29317836SJohn.Forte@Sun.COM 	else
29327836SJohn.Forte@Sun.COM 		_rdc_sync_wrthr(thrinfo);
29337836SJohn.Forte@Sun.COM 
29347836SJohn.Forte@Sun.COM 	_rdc_rlse_devs(krdc, RDC_RAW);
29357836SJohn.Forte@Sun.COM 
29367836SJohn.Forte@Sun.COM 	if (krdc->dcio_bitmap == NULL) {
29377836SJohn.Forte@Sun.COM #ifdef DEBUG
2938*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!_rdc_sync_wrthr: NULL bitmap");
29397836SJohn.Forte@Sun.COM #else
29407836SJohn.Forte@Sun.COM 	/*EMPTY*/
29417836SJohn.Forte@Sun.COM #endif
29427836SJohn.Forte@Sun.COM 	} else if (syncinfo->status->offset < 0) {
29437836SJohn.Forte@Sun.COM 
29447836SJohn.Forte@Sun.COM 		RDC_SET_BITMASK(syncinfo->offset, syncinfo->len, &bitmask);
29457836SJohn.Forte@Sun.COM 		RDC_CLR_BITMAP(krdc, syncinfo->offset, syncinfo->len, \
29467836SJohn.Forte@Sun.COM 		    bitmask, RDC_BIT_FORCE);
29477836SJohn.Forte@Sun.COM 	}
29487836SJohn.Forte@Sun.COM 
29497836SJohn.Forte@Sun.COM failed:
29507836SJohn.Forte@Sun.COM 	/*
29517836SJohn.Forte@Sun.COM 	 * done with this, get rid of it.
29527836SJohn.Forte@Sun.COM 	 * the status is not freed, it should still be a status chain
29537836SJohn.Forte@Sun.COM 	 * that _rdc_sync() has the head of
29547836SJohn.Forte@Sun.COM 	 */
29557836SJohn.Forte@Sun.COM 	kmem_free(syncinfo, sizeof (*syncinfo));
29567836SJohn.Forte@Sun.COM 
29577836SJohn.Forte@Sun.COM 	/*
29587836SJohn.Forte@Sun.COM 	 * decrement the global sync thread num
29597836SJohn.Forte@Sun.COM 	 */
29607836SJohn.Forte@Sun.COM 	mutex_enter(&sync_info.lock);
29617836SJohn.Forte@Sun.COM 	sync_info.active_thr--;
29627836SJohn.Forte@Sun.COM 	/* LINTED */
29637836SJohn.Forte@Sun.COM 	RDC_AVAIL_THR_TUNE(sync_info);
29647836SJohn.Forte@Sun.COM 	mutex_exit(&sync_info.lock);
29657836SJohn.Forte@Sun.COM 
29667836SJohn.Forte@Sun.COM 	/*
29677836SJohn.Forte@Sun.COM 	 * krdc specific stuff
29687836SJohn.Forte@Sun.COM 	 */
29697836SJohn.Forte@Sun.COM 	mutex_enter(&sync->lock);
29707836SJohn.Forte@Sun.COM 	sync->complete++;
29717836SJohn.Forte@Sun.COM 	cv_broadcast(&sync->cv);
29727836SJohn.Forte@Sun.COM 	mutex_exit(&sync->lock);
29737836SJohn.Forte@Sun.COM }
29747836SJohn.Forte@Sun.COM 
29757836SJohn.Forte@Sun.COM int
_rdc_setup_syncthr(rdc_syncthr_t ** synthr,nsc_off_t offset,nsc_size_t len,rdc_k_info_t * krdc,sync_status_t * stats)29767836SJohn.Forte@Sun.COM _rdc_setup_syncthr(rdc_syncthr_t **synthr, nsc_off_t offset,
29777836SJohn.Forte@Sun.COM     nsc_size_t len, rdc_k_info_t *krdc, sync_status_t *stats)
29787836SJohn.Forte@Sun.COM {
29797836SJohn.Forte@Sun.COM 	rdc_syncthr_t *tmp;
29807836SJohn.Forte@Sun.COM 	/* alloc here, free in the sync thread */
29817836SJohn.Forte@Sun.COM 	tmp =
29827836SJohn.Forte@Sun.COM 	    (rdc_syncthr_t *)kmem_zalloc(sizeof (rdc_syncthr_t), KM_NOSLEEP);
29837836SJohn.Forte@Sun.COM 
29847836SJohn.Forte@Sun.COM 	if (tmp == NULL)
29857836SJohn.Forte@Sun.COM 		return (-1);
29867836SJohn.Forte@Sun.COM 	tmp->offset = offset;
29877836SJohn.Forte@Sun.COM 	tmp->len = len;
29887836SJohn.Forte@Sun.COM 	tmp->status = stats;
29897836SJohn.Forte@Sun.COM 	tmp->krdc = krdc;
29907836SJohn.Forte@Sun.COM 
29917836SJohn.Forte@Sun.COM 	*synthr = tmp;
29927836SJohn.Forte@Sun.COM 	return (0);
29937836SJohn.Forte@Sun.COM }
29947836SJohn.Forte@Sun.COM 
29957836SJohn.Forte@Sun.COM sync_status_t *
_rdc_new_sync_status()29967836SJohn.Forte@Sun.COM _rdc_new_sync_status()
29977836SJohn.Forte@Sun.COM {
29987836SJohn.Forte@Sun.COM 	sync_status_t *s;
29997836SJohn.Forte@Sun.COM 
30007836SJohn.Forte@Sun.COM 	s = (sync_status_t *)kmem_zalloc(sizeof (*s), KM_NOSLEEP);
30017836SJohn.Forte@Sun.COM 	s->offset = -1;
30027836SJohn.Forte@Sun.COM 	return (s);
30037836SJohn.Forte@Sun.COM }
30047836SJohn.Forte@Sun.COM 
30057836SJohn.Forte@Sun.COM void
_rdc_free_sync_status(sync_status_t * status)30067836SJohn.Forte@Sun.COM _rdc_free_sync_status(sync_status_t *status)
30077836SJohn.Forte@Sun.COM {
30087836SJohn.Forte@Sun.COM 	sync_status_t *s;
30097836SJohn.Forte@Sun.COM 
30107836SJohn.Forte@Sun.COM 	while (status) {
30117836SJohn.Forte@Sun.COM 		s = status->next;
30127836SJohn.Forte@Sun.COM 		kmem_free(status, sizeof (*status));
30137836SJohn.Forte@Sun.COM 		status = s;
30147836SJohn.Forte@Sun.COM 	}
30157836SJohn.Forte@Sun.COM }
30167836SJohn.Forte@Sun.COM int
_rdc_sync_status_ok(sync_status_t * status,int * offset)30177836SJohn.Forte@Sun.COM _rdc_sync_status_ok(sync_status_t *status, int *offset)
30187836SJohn.Forte@Sun.COM {
30197836SJohn.Forte@Sun.COM #ifdef DEBUG_SYNCSTATUS
30207836SJohn.Forte@Sun.COM 	int i = 0;
30217836SJohn.Forte@Sun.COM #endif
30227836SJohn.Forte@Sun.COM 	while (status) {
30237836SJohn.Forte@Sun.COM 		if (status->offset >= 0) {
30247836SJohn.Forte@Sun.COM 			*offset = status->offset;
30257836SJohn.Forte@Sun.COM 			return (-1);
30267836SJohn.Forte@Sun.COM 		}
30277836SJohn.Forte@Sun.COM 		status = status->next;
30287836SJohn.Forte@Sun.COM #ifdef DEBUG_SYNCSTATUS
30297836SJohn.Forte@Sun.COM 		i++;
30307836SJohn.Forte@Sun.COM #endif
30317836SJohn.Forte@Sun.COM 	}
30327836SJohn.Forte@Sun.COM #ifdef DEBUGSYNCSTATUS
3033*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!rdc_sync_status_ok: checked %d statuses", i);
30347836SJohn.Forte@Sun.COM #endif
30357836SJohn.Forte@Sun.COM 	return (0);
30367836SJohn.Forte@Sun.COM }
30377836SJohn.Forte@Sun.COM 
30387836SJohn.Forte@Sun.COM int mtsync = 1;
30397836SJohn.Forte@Sun.COM /*
30407836SJohn.Forte@Sun.COM  * _rdc_sync() : rdc sync loop
30417836SJohn.Forte@Sun.COM  *
30427836SJohn.Forte@Sun.COM  */
30437836SJohn.Forte@Sun.COM static void
_rdc_sync(rdc_k_info_t * krdc)30447836SJohn.Forte@Sun.COM _rdc_sync(rdc_k_info_t *krdc)
30457836SJohn.Forte@Sun.COM {
30467836SJohn.Forte@Sun.COM 	nsc_size_t size = 0;
30477836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
30487836SJohn.Forte@Sun.COM 	int rtype;
30497836SJohn.Forte@Sun.COM 	int sts;
30507836SJohn.Forte@Sun.COM 	int reserved = 0;
30517836SJohn.Forte@Sun.COM 	nsc_buf_t *alloc_h = NULL;
30527836SJohn.Forte@Sun.COM 	nsc_buf_t *handle = NULL;
30537836SJohn.Forte@Sun.COM 	nsc_off_t mask;
30547836SJohn.Forte@Sun.COM 	nsc_size_t maxbit;
30557836SJohn.Forte@Sun.COM 	nsc_size_t len;
30567836SJohn.Forte@Sun.COM 	nsc_off_t offset = 0;
30577836SJohn.Forte@Sun.COM 	int sync_completed = 0;
30587836SJohn.Forte@Sun.COM 	int tries = 0;
30597836SJohn.Forte@Sun.COM 	int rc;
30607836SJohn.Forte@Sun.COM 	int queuing = 0;
30617836SJohn.Forte@Sun.COM 	uint_t bitmask;
30627836SJohn.Forte@Sun.COM 	sync_status_t *ss, *sync_status = NULL;
30637836SJohn.Forte@Sun.COM 	rdc_thrsync_t *sync = &krdc->syncs;
30647836SJohn.Forte@Sun.COM 	rdc_syncthr_t *syncinfo;
30657836SJohn.Forte@Sun.COM 	nsthread_t *trc = NULL;
30667836SJohn.Forte@Sun.COM 
30677836SJohn.Forte@Sun.COM 	if (IS_STATE(urdc, RDC_QUEUING) && !IS_STATE(urdc, RDC_FULL)) {
30687836SJohn.Forte@Sun.COM 		/* flusher is handling the sync in the update case */
30697836SJohn.Forte@Sun.COM 		queuing = 1;
30707836SJohn.Forte@Sun.COM 		goto sync_done;
30717836SJohn.Forte@Sun.COM 	}
30727836SJohn.Forte@Sun.COM 
30737836SJohn.Forte@Sun.COM 	/*
30747836SJohn.Forte@Sun.COM 	 * Main sync/resync loop
30757836SJohn.Forte@Sun.COM 	 */
30767836SJohn.Forte@Sun.COM 	DTRACE_PROBE(rdc_sync_loop_start);
30777836SJohn.Forte@Sun.COM 
30787836SJohn.Forte@Sun.COM 	rtype = RDC_RAW;
30797836SJohn.Forte@Sun.COM 	sts = _rdc_rsrv_devs(krdc, rtype, RDC_INTERNAL);
30807836SJohn.Forte@Sun.COM 
30817836SJohn.Forte@Sun.COM 	DTRACE_PROBE(rdc_sync_loop_rsrv);
30827836SJohn.Forte@Sun.COM 
30837836SJohn.Forte@Sun.COM 	if (sts != 0)
30847836SJohn.Forte@Sun.COM 		goto failed_noincr;
30857836SJohn.Forte@Sun.COM 
30867836SJohn.Forte@Sun.COM 	reserved = 1;
30877836SJohn.Forte@Sun.COM 
30887836SJohn.Forte@Sun.COM 	/*
30897836SJohn.Forte@Sun.COM 	 * pre-allocate a handle if we can - speeds up the sync.
30907836SJohn.Forte@Sun.COM 	 */
30917836SJohn.Forte@Sun.COM 
30927836SJohn.Forte@Sun.COM 	if (rdc_prealloc_handle) {
30937836SJohn.Forte@Sun.COM 		alloc_h = nsc_alloc_handle(RDC_U_FD(krdc), NULL, NULL, NULL);
30947836SJohn.Forte@Sun.COM #ifdef DEBUG
30957836SJohn.Forte@Sun.COM 		if (!alloc_h) {
30967836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
3097*9093SRamana.Srikanth@Sun.COM 			    "!rdc sync: failed to pre-alloc handle");
30987836SJohn.Forte@Sun.COM 		}
30997836SJohn.Forte@Sun.COM #endif
31007836SJohn.Forte@Sun.COM 	} else {
31017836SJohn.Forte@Sun.COM 		alloc_h = NULL;
31027836SJohn.Forte@Sun.COM 	}
31037836SJohn.Forte@Sun.COM 
31047836SJohn.Forte@Sun.COM 	ASSERT(urdc->volume_size != 0);
31057836SJohn.Forte@Sun.COM 	size = urdc->volume_size;
31067836SJohn.Forte@Sun.COM 	mask = ~(LOG_TO_FBA_NUM(1) - 1);
31077836SJohn.Forte@Sun.COM 	maxbit = FBA_TO_LOG_NUM(size - 1);
31087836SJohn.Forte@Sun.COM 
31097836SJohn.Forte@Sun.COM 	/*
31107836SJohn.Forte@Sun.COM 	 * as this while loop can also move data, it is counted as a
31117836SJohn.Forte@Sun.COM 	 * sync loop thread
31127836SJohn.Forte@Sun.COM 	 */
31137836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
31147836SJohn.Forte@Sun.COM 	rdc_clr_flags(urdc, RDC_LOGGING);
31157836SJohn.Forte@Sun.COM 	rdc_set_flags(urdc, RDC_SYNCING);
31167836SJohn.Forte@Sun.COM 	krdc->group->synccount++;
31177836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
31187836SJohn.Forte@Sun.COM 	mutex_enter(&sync_info.lock);
31197836SJohn.Forte@Sun.COM 	sync_info.active_thr++;
31207836SJohn.Forte@Sun.COM 	/* LINTED */
31217836SJohn.Forte@Sun.COM 	RDC_AVAIL_THR_TUNE(sync_info);
31227836SJohn.Forte@Sun.COM 	mutex_exit(&sync_info.lock);
31237836SJohn.Forte@Sun.COM 
31247836SJohn.Forte@Sun.COM 	while (offset < size) {
31257836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
31267836SJohn.Forte@Sun.COM 		ASSERT(krdc->aux_state & RDC_AUXSYNCIP);
31277836SJohn.Forte@Sun.COM 		if (krdc->disk_status == 1 || krdc->dcio_bitmap == NULL) {
31287836SJohn.Forte@Sun.COM 			rdc_group_exit(krdc);
31297836SJohn.Forte@Sun.COM 			if (krdc->disk_status == 1) {
31307836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_disk_status_err);
31317836SJohn.Forte@Sun.COM 			} else {
31327836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_dcio_bitmap_err);
31337836SJohn.Forte@Sun.COM 			}
31347836SJohn.Forte@Sun.COM 			goto failed;		/* halt sync */
31357836SJohn.Forte@Sun.COM 		}
31367836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
31377836SJohn.Forte@Sun.COM 
31387836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_FULL)) {
31397836SJohn.Forte@Sun.COM 			mutex_enter(&krdc->syncbitmutex);
31407836SJohn.Forte@Sun.COM 			krdc->syncbitpos = FBA_TO_LOG_NUM(offset);
31417836SJohn.Forte@Sun.COM 			len = 0;
31427836SJohn.Forte@Sun.COM 
31437836SJohn.Forte@Sun.COM 			/* skip unnecessary chunks */
31447836SJohn.Forte@Sun.COM 
31457836SJohn.Forte@Sun.COM 			while (krdc->syncbitpos <= maxbit &&
31467836SJohn.Forte@Sun.COM 			    !RDC_BIT_ISSET(krdc, krdc->syncbitpos)) {
31477836SJohn.Forte@Sun.COM 				offset += LOG_TO_FBA_NUM(1);
31487836SJohn.Forte@Sun.COM 				krdc->syncbitpos++;
31497836SJohn.Forte@Sun.COM 			}
31507836SJohn.Forte@Sun.COM 
31517836SJohn.Forte@Sun.COM 			/* check for boundary */
31527836SJohn.Forte@Sun.COM 
31537836SJohn.Forte@Sun.COM 			if (offset >= size) {
31547836SJohn.Forte@Sun.COM 				mutex_exit(&krdc->syncbitmutex);
31557836SJohn.Forte@Sun.COM 				goto sync_done;
31567836SJohn.Forte@Sun.COM 			}
31577836SJohn.Forte@Sun.COM 
31587836SJohn.Forte@Sun.COM 			/* find maximal length we can transfer */
31597836SJohn.Forte@Sun.COM 
31607836SJohn.Forte@Sun.COM 			while (krdc->syncbitpos <= maxbit &&
31617836SJohn.Forte@Sun.COM 			    RDC_BIT_ISSET(krdc, krdc->syncbitpos)) {
31627836SJohn.Forte@Sun.COM 				len += LOG_TO_FBA_NUM(1);
31637836SJohn.Forte@Sun.COM 				krdc->syncbitpos++;
31647836SJohn.Forte@Sun.COM 				/* we can only read maxfbas anyways */
31657836SJohn.Forte@Sun.COM 				if (len >= krdc->maxfbas)
31667836SJohn.Forte@Sun.COM 					break;
31677836SJohn.Forte@Sun.COM 			}
31687836SJohn.Forte@Sun.COM 
31697836SJohn.Forte@Sun.COM 			len = min(len, (size - offset));
31707836SJohn.Forte@Sun.COM 
31717836SJohn.Forte@Sun.COM 		} else {
31727836SJohn.Forte@Sun.COM 			len = size - offset;
31737836SJohn.Forte@Sun.COM 		}
31747836SJohn.Forte@Sun.COM 
31757836SJohn.Forte@Sun.COM 		/* truncate to the io provider limit */
31767836SJohn.Forte@Sun.COM 		ASSERT(krdc->maxfbas != 0);
31777836SJohn.Forte@Sun.COM 		len = min(len, krdc->maxfbas);
31787836SJohn.Forte@Sun.COM 
31797836SJohn.Forte@Sun.COM 		if (len > LOG_TO_FBA_NUM(1)) {
31807836SJohn.Forte@Sun.COM 			/*
31817836SJohn.Forte@Sun.COM 			 * If the update is larger than a bitmap chunk,
31827836SJohn.Forte@Sun.COM 			 * then truncate to a whole number of bitmap
31837836SJohn.Forte@Sun.COM 			 * chunks.
31847836SJohn.Forte@Sun.COM 			 *
31857836SJohn.Forte@Sun.COM 			 * If the update is smaller than a bitmap
31867836SJohn.Forte@Sun.COM 			 * chunk, this must be the last write.
31877836SJohn.Forte@Sun.COM 			 */
31887836SJohn.Forte@Sun.COM 			len &= mask;
31897836SJohn.Forte@Sun.COM 		}
31907836SJohn.Forte@Sun.COM 
31917836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_FULL)) {
31927836SJohn.Forte@Sun.COM 			krdc->syncbitpos = FBA_TO_LOG_NUM(offset + len);
31937836SJohn.Forte@Sun.COM 			mutex_exit(&krdc->syncbitmutex);
31947836SJohn.Forte@Sun.COM 		}
31957836SJohn.Forte@Sun.COM 
31967836SJohn.Forte@Sun.COM 		/*
31977836SJohn.Forte@Sun.COM 		 * Find out if we can reserve a thread here ...
31987836SJohn.Forte@Sun.COM 		 * note: skip the mutex for the first check, if the number
31997836SJohn.Forte@Sun.COM 		 * is up there, why bother even grabbing the mutex to
32007836SJohn.Forte@Sun.COM 		 * only realize that we can't have a thread anyways
32017836SJohn.Forte@Sun.COM 		 */
32027836SJohn.Forte@Sun.COM 
32037836SJohn.Forte@Sun.COM 		if (mtsync && sync_info.active_thr < RDC_MAX_SYNC_THREADS) {
32047836SJohn.Forte@Sun.COM 
32057836SJohn.Forte@Sun.COM 			mutex_enter(&sync_info.lock);
32067836SJohn.Forte@Sun.COM 			if (sync_info.avail_thr >= 1) {
32077836SJohn.Forte@Sun.COM 				if (sync_status == NULL) {
32087836SJohn.Forte@Sun.COM 					ss = sync_status =
32097836SJohn.Forte@Sun.COM 					    _rdc_new_sync_status();
32107836SJohn.Forte@Sun.COM 				} else {
32117836SJohn.Forte@Sun.COM 					ss = ss->next = _rdc_new_sync_status();
32127836SJohn.Forte@Sun.COM 				}
32137836SJohn.Forte@Sun.COM 				if (ss == NULL) {
32147836SJohn.Forte@Sun.COM 					mutex_exit(&sync_info.lock);
32157836SJohn.Forte@Sun.COM #ifdef DEBUG
3216*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!rdc_sync: can't "
3217*9093SRamana.Srikanth@Sun.COM 					    "allocate status for mt sync");
32187836SJohn.Forte@Sun.COM #endif
32197836SJohn.Forte@Sun.COM 					goto retry;
32207836SJohn.Forte@Sun.COM 				}
32217836SJohn.Forte@Sun.COM 				/*
32227836SJohn.Forte@Sun.COM 				 * syncinfo protected by sync_info lock but
32237836SJohn.Forte@Sun.COM 				 * not part of the sync_info structure
32247836SJohn.Forte@Sun.COM 				 * be careful if moving
32257836SJohn.Forte@Sun.COM 				 */
32267836SJohn.Forte@Sun.COM 				if (_rdc_setup_syncthr(&syncinfo,
32277836SJohn.Forte@Sun.COM 				    offset, len, krdc, ss) < 0) {
32287836SJohn.Forte@Sun.COM 					_rdc_free_sync_status(ss);
32297836SJohn.Forte@Sun.COM 				}
32307836SJohn.Forte@Sun.COM 
32317836SJohn.Forte@Sun.COM 				trc = nst_create(sync_info.rdc_syncset,
32327836SJohn.Forte@Sun.COM 				    _rdc_sync_thread, syncinfo, NST_SLEEP);
32337836SJohn.Forte@Sun.COM 
32347836SJohn.Forte@Sun.COM 				if (trc == NULL) {
32357836SJohn.Forte@Sun.COM 					mutex_exit(&sync_info.lock);
32367836SJohn.Forte@Sun.COM #ifdef DEBUG
3237*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE, "!rdc_sync: unable to "
3238*9093SRamana.Srikanth@Sun.COM 					    "mt sync");
32397836SJohn.Forte@Sun.COM #endif
32407836SJohn.Forte@Sun.COM 					_rdc_free_sync_status(ss);
32417836SJohn.Forte@Sun.COM 					kmem_free(syncinfo, sizeof (*syncinfo));
32427836SJohn.Forte@Sun.COM 					syncinfo = NULL;
32437836SJohn.Forte@Sun.COM 					goto retry;
32447836SJohn.Forte@Sun.COM 				} else {
32457836SJohn.Forte@Sun.COM 					mutex_enter(&sync->lock);
32467836SJohn.Forte@Sun.COM 					sync->threads++;
32477836SJohn.Forte@Sun.COM 					mutex_exit(&sync->lock);
32487836SJohn.Forte@Sun.COM 				}
32497836SJohn.Forte@Sun.COM 
32507836SJohn.Forte@Sun.COM 				sync_info.active_thr++;
32517836SJohn.Forte@Sun.COM 				/* LINTED */
32527836SJohn.Forte@Sun.COM 				RDC_AVAIL_THR_TUNE(sync_info);
32537836SJohn.Forte@Sun.COM 
32547836SJohn.Forte@Sun.COM 				mutex_exit(&sync_info.lock);
32557836SJohn.Forte@Sun.COM 				goto threaded;
32567836SJohn.Forte@Sun.COM 			}
32577836SJohn.Forte@Sun.COM 			mutex_exit(&sync_info.lock);
32587836SJohn.Forte@Sun.COM 		}
32597836SJohn.Forte@Sun.COM retry:
32607836SJohn.Forte@Sun.COM 		handle = alloc_h;
32617836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_sync_loop_allocbuf_start);
32627836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_SLAVE)
32637836SJohn.Forte@Sun.COM 			sts = nsc_alloc_buf(RDC_U_FD(krdc), offset, len,
32647836SJohn.Forte@Sun.COM 			    NSC_WRITE | NSC_WRTHRU | NSC_NOCACHE, &handle);
32657836SJohn.Forte@Sun.COM 		else
32667836SJohn.Forte@Sun.COM 			sts = nsc_alloc_buf(RDC_U_FD(krdc), offset, len,
32677836SJohn.Forte@Sun.COM 			    NSC_READ | NSC_NOCACHE, &handle);
32687836SJohn.Forte@Sun.COM 
32697836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_sync_loop_allocbuf_end);
32707836SJohn.Forte@Sun.COM 		if (sts > 0) {
32717836SJohn.Forte@Sun.COM 			if (handle && handle != alloc_h) {
32727836SJohn.Forte@Sun.COM 				(void) nsc_free_buf(handle);
32737836SJohn.Forte@Sun.COM 			}
32747836SJohn.Forte@Sun.COM 
32757836SJohn.Forte@Sun.COM 			handle = NULL;
32767836SJohn.Forte@Sun.COM 			DTRACE_PROBE(rdc_sync_loop_allocbuf_err);
32777836SJohn.Forte@Sun.COM 			goto failed;
32787836SJohn.Forte@Sun.COM 		}
32797836SJohn.Forte@Sun.COM 
32807836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_SLAVE) {
32817836SJohn.Forte@Sun.COM 			/* overwrite buffer with remote data */
32827836SJohn.Forte@Sun.COM 			sts = rdc_net_read(krdc->index, krdc->remote_index,
32837836SJohn.Forte@Sun.COM 			    handle, handle->sb_pos, handle->sb_len);
32847836SJohn.Forte@Sun.COM 
32857836SJohn.Forte@Sun.COM 			if (!RDC_SUCCESS(sts)) {
32867836SJohn.Forte@Sun.COM #ifdef DEBUG
32877836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
3288*9093SRamana.Srikanth@Sun.COM 				    "!rdc sync: remote read failed (%d)", sts);
32897836SJohn.Forte@Sun.COM #endif
32907836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_remote_read_err);
32917836SJohn.Forte@Sun.COM 				goto failed;
32927836SJohn.Forte@Sun.COM 			}
32937836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(urdc) & RDC_FULL))
32947836SJohn.Forte@Sun.COM 				rdc_set_bitmap_many(krdc, handle->sb_pos,
32957836SJohn.Forte@Sun.COM 				    handle->sb_len);
32967836SJohn.Forte@Sun.COM 
32977836SJohn.Forte@Sun.COM 			/* commit locally */
32987836SJohn.Forte@Sun.COM 
32997836SJohn.Forte@Sun.COM 			sts = nsc_write(handle, handle->sb_pos,
3300*9093SRamana.Srikanth@Sun.COM 			    handle->sb_len, 0);
33017836SJohn.Forte@Sun.COM 
33027836SJohn.Forte@Sun.COM 			if (!RDC_SUCCESS(sts)) {
33037836SJohn.Forte@Sun.COM 				/* reverse sync needed already set */
33047836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
33057836SJohn.Forte@Sun.COM 				rdc_set_flags_log(urdc, RDC_VOL_FAILED,
33067836SJohn.Forte@Sun.COM 				    "write failed during sync");
33077836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
33087836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
33097836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_nsc_write_err);
33107836SJohn.Forte@Sun.COM 				goto failed;
33117836SJohn.Forte@Sun.COM 			}
33127836SJohn.Forte@Sun.COM 		} else {
33137836SJohn.Forte@Sun.COM 			/* send local data to remote */
33147836SJohn.Forte@Sun.COM 			DTRACE_PROBE2(rdc_sync_loop_netwrite_start,
3315*9093SRamana.Srikanth@Sun.COM 			    int, krdc->index, nsc_buf_t *, handle);
33167836SJohn.Forte@Sun.COM 
33177836SJohn.Forte@Sun.COM 			if ((sts = rdc_net_write(krdc->index,
33187836SJohn.Forte@Sun.COM 			    krdc->remote_index, handle, handle->sb_pos,
33197836SJohn.Forte@Sun.COM 			    handle->sb_len, RDC_NOSEQ, RDC_NOQUE, NULL)) > 0) {
33207836SJohn.Forte@Sun.COM 
33217836SJohn.Forte@Sun.COM 				/*
33227836SJohn.Forte@Sun.COM 				 * The following is to handle
33237836SJohn.Forte@Sun.COM 				 * the case where the secondary side
33247836SJohn.Forte@Sun.COM 				 * has thrown our buffer handle token away in a
33257836SJohn.Forte@Sun.COM 				 * attempt to preserve its health on restart
33267836SJohn.Forte@Sun.COM 				 */
33277836SJohn.Forte@Sun.COM 				if ((sts == EPROTO) && (tries < 3)) {
33287836SJohn.Forte@Sun.COM 					(void) nsc_free_buf(handle);
33297836SJohn.Forte@Sun.COM 					handle = NULL;
33307836SJohn.Forte@Sun.COM 					tries++;
33317836SJohn.Forte@Sun.COM 					delay(HZ >> 2);
33327836SJohn.Forte@Sun.COM 					goto retry;
33337836SJohn.Forte@Sun.COM 				}
33347836SJohn.Forte@Sun.COM #ifdef DEBUG
33357836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
3336*9093SRamana.Srikanth@Sun.COM 				    "!rdc sync: remote write failed (%d) 0x%x",
33377836SJohn.Forte@Sun.COM 				    sts, rdc_get_vflags(urdc));
33387836SJohn.Forte@Sun.COM #endif
33397836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_netwrite_err);
33407836SJohn.Forte@Sun.COM 				goto failed;
33417836SJohn.Forte@Sun.COM 			}
33427836SJohn.Forte@Sun.COM 			DTRACE_PROBE(rdc_sync_loop_netwrite_end);
33437836SJohn.Forte@Sun.COM 		}
33447836SJohn.Forte@Sun.COM 
33457836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(handle);
33467836SJohn.Forte@Sun.COM 		handle = NULL;
33477836SJohn.Forte@Sun.COM 
33487836SJohn.Forte@Sun.COM 		if (krdc->dcio_bitmap == NULL) {
33497836SJohn.Forte@Sun.COM #ifdef DEBUG
3350*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_NOTE, "!_rdc_sync: NULL bitmap");
33517836SJohn.Forte@Sun.COM #else
33527836SJohn.Forte@Sun.COM 		;
33537836SJohn.Forte@Sun.COM 		/*EMPTY*/
33547836SJohn.Forte@Sun.COM #endif
33557836SJohn.Forte@Sun.COM 		} else {
33567836SJohn.Forte@Sun.COM 
33577836SJohn.Forte@Sun.COM 			RDC_SET_BITMASK(offset, len, &bitmask);
33587836SJohn.Forte@Sun.COM 			RDC_CLR_BITMAP(krdc, offset, len, bitmask, \
3359*9093SRamana.Srikanth@Sun.COM 			    RDC_BIT_FORCE);
33607836SJohn.Forte@Sun.COM 			ASSERT(!IS_ASYNC(urdc));
33617836SJohn.Forte@Sun.COM 		}
33627836SJohn.Forte@Sun.COM 
33637836SJohn.Forte@Sun.COM 		/*
33647836SJohn.Forte@Sun.COM 		 * Only release/reserve if someone is waiting
33657836SJohn.Forte@Sun.COM 		 */
33667836SJohn.Forte@Sun.COM 		if (krdc->devices->id_release || nsc_waiting(RDC_U_FD(krdc))) {
33677836SJohn.Forte@Sun.COM 			DTRACE_PROBE(rdc_sync_loop_rlse_start);
33687836SJohn.Forte@Sun.COM 			if (alloc_h) {
33697836SJohn.Forte@Sun.COM 				(void) nsc_free_handle(alloc_h);
33707836SJohn.Forte@Sun.COM 				alloc_h = NULL;
33717836SJohn.Forte@Sun.COM 			}
33727836SJohn.Forte@Sun.COM 
33737836SJohn.Forte@Sun.COM 			_rdc_rlse_devs(krdc, rtype);
33747836SJohn.Forte@Sun.COM 			reserved = 0;
33757836SJohn.Forte@Sun.COM 			delay(2);
33767836SJohn.Forte@Sun.COM 
33777836SJohn.Forte@Sun.COM 			rtype = RDC_RAW;
33787836SJohn.Forte@Sun.COM 			sts = _rdc_rsrv_devs(krdc, rtype, RDC_INTERNAL);
33797836SJohn.Forte@Sun.COM 			if (sts != 0) {
33807836SJohn.Forte@Sun.COM 				handle = NULL;
33817836SJohn.Forte@Sun.COM 				DTRACE_PROBE(rdc_sync_loop_rdc_rsrv_err);
33827836SJohn.Forte@Sun.COM 				goto failed;
33837836SJohn.Forte@Sun.COM 			}
33847836SJohn.Forte@Sun.COM 
33857836SJohn.Forte@Sun.COM 			reserved = 1;
33867836SJohn.Forte@Sun.COM 
33877836SJohn.Forte@Sun.COM 			if (rdc_prealloc_handle) {
33887836SJohn.Forte@Sun.COM 				alloc_h = nsc_alloc_handle(RDC_U_FD(krdc),
3389*9093SRamana.Srikanth@Sun.COM 				    NULL, NULL, NULL);
33907836SJohn.Forte@Sun.COM #ifdef DEBUG
33917836SJohn.Forte@Sun.COM 				if (!alloc_h) {
3392*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_WARN, "!rdc_sync: "
3393*9093SRamana.Srikanth@Sun.COM 					    "failed to pre-alloc handle");
33947836SJohn.Forte@Sun.COM 				}
33957836SJohn.Forte@Sun.COM #endif
33967836SJohn.Forte@Sun.COM 			}
33977836SJohn.Forte@Sun.COM 			DTRACE_PROBE(rdc_sync_loop_rlse_end);
33987836SJohn.Forte@Sun.COM 		}
33997836SJohn.Forte@Sun.COM threaded:
34007836SJohn.Forte@Sun.COM 		offset += len;
34017836SJohn.Forte@Sun.COM 		urdc->sync_pos = offset;
34027836SJohn.Forte@Sun.COM 	}
34037836SJohn.Forte@Sun.COM 
34047836SJohn.Forte@Sun.COM sync_done:
34057836SJohn.Forte@Sun.COM 	sync_completed = 1;
34067836SJohn.Forte@Sun.COM 
34077836SJohn.Forte@Sun.COM failed:
34087836SJohn.Forte@Sun.COM 	krdc->group->synccount--;
34097836SJohn.Forte@Sun.COM failed_noincr:
34107836SJohn.Forte@Sun.COM 	mutex_enter(&sync->lock);
34117836SJohn.Forte@Sun.COM 	while (sync->complete != sync->threads) {
34127836SJohn.Forte@Sun.COM 		cv_wait(&sync->cv, &sync->lock);
34137836SJohn.Forte@Sun.COM 	}
34147836SJohn.Forte@Sun.COM 	sync->complete = 0;
34157836SJohn.Forte@Sun.COM 	sync->threads = 0;
34167836SJohn.Forte@Sun.COM 	mutex_exit(&sync->lock);
34177836SJohn.Forte@Sun.COM 
34187836SJohn.Forte@Sun.COM 	/*
34197836SJohn.Forte@Sun.COM 	 * if sync_completed is 0 here,
34207836SJohn.Forte@Sun.COM 	 * we know that the main sync thread failed anyway
34217836SJohn.Forte@Sun.COM 	 * so just free the statuses and fail
34227836SJohn.Forte@Sun.COM 	 */
34237836SJohn.Forte@Sun.COM 	if (sync_completed && (_rdc_sync_status_ok(sync_status, &rc) < 0)) {
34247836SJohn.Forte@Sun.COM 		urdc->sync_pos = rc;
34257836SJohn.Forte@Sun.COM 		sync_completed = 0; /* at least 1 thread failed */
34267836SJohn.Forte@Sun.COM 	}
34277836SJohn.Forte@Sun.COM 
34287836SJohn.Forte@Sun.COM 	_rdc_free_sync_status(sync_status);
34297836SJohn.Forte@Sun.COM 
34307836SJohn.Forte@Sun.COM 	/*
34317836SJohn.Forte@Sun.COM 	 * we didn't increment, we didn't even sync,
34327836SJohn.Forte@Sun.COM 	 * so don't dec sync_info.active_thr
34337836SJohn.Forte@Sun.COM 	 */
34347836SJohn.Forte@Sun.COM 	if (!queuing) {
34357836SJohn.Forte@Sun.COM 		mutex_enter(&sync_info.lock);
34367836SJohn.Forte@Sun.COM 		sync_info.active_thr--;
34377836SJohn.Forte@Sun.COM 		/* LINTED */
34387836SJohn.Forte@Sun.COM 		RDC_AVAIL_THR_TUNE(sync_info);
34397836SJohn.Forte@Sun.COM 		mutex_exit(&sync_info.lock);
34407836SJohn.Forte@Sun.COM 	}
34417836SJohn.Forte@Sun.COM 
34427836SJohn.Forte@Sun.COM 	if (handle) {
34437836SJohn.Forte@Sun.COM 		(void) nsc_free_buf(handle);
34447836SJohn.Forte@Sun.COM 	}
34457836SJohn.Forte@Sun.COM 
34467836SJohn.Forte@Sun.COM 	if (alloc_h) {
34477836SJohn.Forte@Sun.COM 		(void) nsc_free_handle(alloc_h);
34487836SJohn.Forte@Sun.COM 	}
34497836SJohn.Forte@Sun.COM 
34507836SJohn.Forte@Sun.COM 	if (reserved) {
34517836SJohn.Forte@Sun.COM 		_rdc_rlse_devs(krdc, rtype);
34527836SJohn.Forte@Sun.COM 	}
34537836SJohn.Forte@Sun.COM 
34547836SJohn.Forte@Sun.COM notstarted:
34557836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
34567836SJohn.Forte@Sun.COM 	ASSERT(krdc->aux_state & RDC_AUXSYNCIP);
34577836SJohn.Forte@Sun.COM 	if (IS_STATE(urdc, RDC_QUEUING))
34587836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_QUEUING);
34597836SJohn.Forte@Sun.COM 
34607836SJohn.Forte@Sun.COM 	if (sync_completed) {
34617836SJohn.Forte@Sun.COM 		(void) rdc_net_state(krdc->index, CCIO_DONE);
34627836SJohn.Forte@Sun.COM 	} else {
34637836SJohn.Forte@Sun.COM 		(void) rdc_net_state(krdc->index, CCIO_ENABLELOG);
34647836SJohn.Forte@Sun.COM 	}
34657836SJohn.Forte@Sun.COM 
34667836SJohn.Forte@Sun.COM 	rdc_clr_flags(urdc, RDC_SYNCING);
34677836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_SLAVE) {
34687836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
34697836SJohn.Forte@Sun.COM 		rdc_clr_mflags(urdc, RDC_SLAVE);
34707836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
34717836SJohn.Forte@Sun.COM 	}
34727836SJohn.Forte@Sun.COM 	if (krdc->type_flag & RDC_ASYNCMODE)
34737836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_ASYNC);
34747836SJohn.Forte@Sun.COM 	if (sync_completed) {
34757836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
34767836SJohn.Forte@Sun.COM 		rdc_clr_mflags(urdc, RDC_RSYNC_NEEDED);
34777836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
34787836SJohn.Forte@Sun.COM 	} else {
34797836SJohn.Forte@Sun.COM 		krdc->remote_index = -1;
34807836SJohn.Forte@Sun.COM 		rdc_set_flags_log(urdc, RDC_LOGGING, "sync failed to complete");
34817836SJohn.Forte@Sun.COM 	}
34827836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
34837836SJohn.Forte@Sun.COM 	rdc_write_state(urdc);
34847836SJohn.Forte@Sun.COM 
34857836SJohn.Forte@Sun.COM 	mutex_enter(&net_blk_lock);
34867836SJohn.Forte@Sun.COM 	if (sync_completed)
34877836SJohn.Forte@Sun.COM 		krdc->sync_done = RDC_COMPLETED;
34887836SJohn.Forte@Sun.COM 	else
34897836SJohn.Forte@Sun.COM 		krdc->sync_done = RDC_FAILED;
34907836SJohn.Forte@Sun.COM 	cv_broadcast(&krdc->synccv);
34917836SJohn.Forte@Sun.COM 	mutex_exit(&net_blk_lock);
34927836SJohn.Forte@Sun.COM 
34937836SJohn.Forte@Sun.COM }
34947836SJohn.Forte@Sun.COM 
34957836SJohn.Forte@Sun.COM 
34967836SJohn.Forte@Sun.COM static int
rdc_sync(rdc_config_t * uparms,spcs_s_info_t kstatus)34977836SJohn.Forte@Sun.COM rdc_sync(rdc_config_t *uparms, spcs_s_info_t kstatus)
34987836SJohn.Forte@Sun.COM {
34997836SJohn.Forte@Sun.COM 	rdc_set_t *rdc_set = uparms->rdc_set;
35007836SJohn.Forte@Sun.COM 	int options = uparms->options;
35017836SJohn.Forte@Sun.COM 	int rc = 0;
35027836SJohn.Forte@Sun.COM 	int busy = 0;
35037836SJohn.Forte@Sun.COM 	int index;
35047836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
35057836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
35067836SJohn.Forte@Sun.COM 	rdc_k_info_t *kmulti;
35077836SJohn.Forte@Sun.COM 	rdc_u_info_t *umulti;
35087836SJohn.Forte@Sun.COM 	rdc_group_t *group;
35097836SJohn.Forte@Sun.COM 	rdc_srv_t *svp;
35107836SJohn.Forte@Sun.COM 	int sm, um, md;
35117836SJohn.Forte@Sun.COM 	int sync_completed = 0;
35127836SJohn.Forte@Sun.COM 	int thrcount;
35137836SJohn.Forte@Sun.COM 
35147836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
35157836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(rdc_set);
35167836SJohn.Forte@Sun.COM 	if (index >= 0)
35177836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
35187836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
35197836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
35207836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
35217836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
35227836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
35237836SJohn.Forte@Sun.COM 		goto notstarted;
35247836SJohn.Forte@Sun.COM 	}
35257836SJohn.Forte@Sun.COM 
35267836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
35277836SJohn.Forte@Sun.COM 	group = krdc->group;
35287836SJohn.Forte@Sun.COM 	set_busy(krdc);
35297836SJohn.Forte@Sun.COM 	busy = 1;
35307836SJohn.Forte@Sun.COM 	if ((krdc->type_flag == 0) || (krdc->type_flag & RDC_DISABLEPEND)) {
35317836SJohn.Forte@Sun.COM 		/* A resume or enable failed  or we raced with a teardown */
35327836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
35337836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
35347836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
35357836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
35367836SJohn.Forte@Sun.COM 		goto notstarted;
35377836SJohn.Forte@Sun.COM 	}
35387836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
35397836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
35407836SJohn.Forte@Sun.COM 
35417836SJohn.Forte@Sun.COM 	if (!IS_STATE(urdc, RDC_LOGGING)) {
35427836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ESETNOTLOGGING, urdc->secondary.intf,
35437836SJohn.Forte@Sun.COM 		    urdc->secondary.file);
3544*9093SRamana.Srikanth@Sun.COM 		rc = RDC_ENOTLOGGING;
3545*9093SRamana.Srikanth@Sun.COM 		goto notstarted_unlock;
35467836SJohn.Forte@Sun.COM 	}
35477836SJohn.Forte@Sun.COM 
35487836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, rdc_set)) {
35497836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
35507836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
35517836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
35527836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
35537836SJohn.Forte@Sun.COM 	}
35547836SJohn.Forte@Sun.COM 
35557836SJohn.Forte@Sun.COM 	if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
35567836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENOTPRIMARY, rdc_set->primary.intf,
35577836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
35587836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
35597836SJohn.Forte@Sun.COM 		rc = RDC_ENOTPRIMARY;
35607836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
35617836SJohn.Forte@Sun.COM 	}
35627836SJohn.Forte@Sun.COM 
35637836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_REVERSE) && (IS_STATE(urdc, RDC_QUEUING))) {
35647836SJohn.Forte@Sun.COM 		/*
35657836SJohn.Forte@Sun.COM 		 * cannot reverse sync when queuing, need to go logging first
35667836SJohn.Forte@Sun.COM 		 */
35677836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EQNORSYNC, rdc_set->primary.intf,
35687836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
35697836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
3570*9093SRamana.Srikanth@Sun.COM 		rc = RDC_EQNORSYNC;
3571*9093SRamana.Srikanth@Sun.COM 		goto notstarted_unlock;
35727836SJohn.Forte@Sun.COM 	}
35737836SJohn.Forte@Sun.COM 
35747836SJohn.Forte@Sun.COM 	svp = krdc->lsrv;
35757836SJohn.Forte@Sun.COM 	krdc->intf = rdc_add_to_if(svp, &(urdc->primary.addr),
35767836SJohn.Forte@Sun.COM 	    &(urdc->secondary.addr), 1);
35777836SJohn.Forte@Sun.COM 
35787836SJohn.Forte@Sun.COM 	if (!krdc->intf) {
35797836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EADDTOIF, urdc->primary.intf,
35807836SJohn.Forte@Sun.COM 		    urdc->secondary.intf);
35817836SJohn.Forte@Sun.COM 		rc = RDC_EADDTOIF;
35827836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
35837836SJohn.Forte@Sun.COM 	}
35847836SJohn.Forte@Sun.COM 
35857836SJohn.Forte@Sun.COM 	if (urdc->volume_size == 0) {
35867836SJohn.Forte@Sun.COM 		/* Implies reserve failed when previous resume was done */
35877836SJohn.Forte@Sun.COM 		rdc_get_details(krdc);
35887836SJohn.Forte@Sun.COM 	}
35897836SJohn.Forte@Sun.COM 	if (urdc->volume_size == 0) {
35907836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENOBMAP);
35917836SJohn.Forte@Sun.COM 		rc = RDC_ENOBMAP;
35927836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
35937836SJohn.Forte@Sun.COM 	}
35947836SJohn.Forte@Sun.COM 
35957836SJohn.Forte@Sun.COM 	if (krdc->dcio_bitmap == NULL) {
35967836SJohn.Forte@Sun.COM 		if (rdc_resume_bitmap(krdc) < 0) {
35977836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_ENOBMAP);
35987836SJohn.Forte@Sun.COM 			rc = RDC_ENOBMAP;
35997836SJohn.Forte@Sun.COM 			goto notstarted_unlock;
36007836SJohn.Forte@Sun.COM 		}
36017836SJohn.Forte@Sun.COM 	}
36027836SJohn.Forte@Sun.COM 
36037836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_BMP_FAILED) && (krdc->bitmapfd)) {
36047836SJohn.Forte@Sun.COM 		if (rdc_reset_bitmap(krdc)) {
36057836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EBITMAP);
36067836SJohn.Forte@Sun.COM 			rc = RDC_EBITMAP;
36077836SJohn.Forte@Sun.COM 			goto notstarted_unlock;
36087836SJohn.Forte@Sun.COM 		}
36097836SJohn.Forte@Sun.COM 	}
36107836SJohn.Forte@Sun.COM 
36117836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) || IS_MULTI(krdc)) {
36127836SJohn.Forte@Sun.COM 		rdc_u_info_t *ubad;
36137836SJohn.Forte@Sun.COM 
36147836SJohn.Forte@Sun.COM 		if ((ubad = rdc_allow_pri_sync(urdc, options)) != NULL) {
36157836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_ESTATE,
36167836SJohn.Forte@Sun.COM 			    ubad->primary.intf, ubad->primary.file,
36177836SJohn.Forte@Sun.COM 			    ubad->secondary.intf, ubad->secondary.file);
36187836SJohn.Forte@Sun.COM 			rc = RDC_ESTATE;
36197836SJohn.Forte@Sun.COM 			goto notstarted_unlock;
36207836SJohn.Forte@Sun.COM 		}
36217836SJohn.Forte@Sun.COM 	}
36227836SJohn.Forte@Sun.COM 
36237836SJohn.Forte@Sun.COM 	/*
36247836SJohn.Forte@Sun.COM 	 * there is a small window where _rdc_sync is still
36257836SJohn.Forte@Sun.COM 	 * running, but has cleared the RDC_SYNCING flag.
36267836SJohn.Forte@Sun.COM 	 * Use aux_state which is only cleared
36277836SJohn.Forte@Sun.COM 	 * after _rdc_sync had done its 'death' broadcast.
36287836SJohn.Forte@Sun.COM 	 */
36297836SJohn.Forte@Sun.COM 	if (krdc->aux_state & RDC_AUXSYNCIP) {
36307836SJohn.Forte@Sun.COM #ifdef DEBUG
36317836SJohn.Forte@Sun.COM 		if (!rdc_get_vflags(urdc) & RDC_SYNCING) {
3632*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!rdc_sync: "
36337836SJohn.Forte@Sun.COM 			    "RDC_AUXSYNCIP set, SYNCING off");
36347836SJohn.Forte@Sun.COM 		}
36357836SJohn.Forte@Sun.COM #endif
36367836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ESYNCING, rdc_set->primary.file);
36377836SJohn.Forte@Sun.COM 		rc = RDC_ESYNCING;
36387836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36397836SJohn.Forte@Sun.COM 	}
36407836SJohn.Forte@Sun.COM 	if (krdc->disk_status == 1) {
36417836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ESYNCING, rdc_set->primary.file);
36427836SJohn.Forte@Sun.COM 		rc = RDC_ESYNCING;
36437836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36447836SJohn.Forte@Sun.COM 	}
36457836SJohn.Forte@Sun.COM 
36467836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_FORWARD) &&
36477836SJohn.Forte@Sun.COM 	    (rdc_get_mflags(urdc) & RDC_RSYNC_NEEDED)) {
36487836SJohn.Forte@Sun.COM 		/* cannot forward sync if a reverse sync is needed */
36497836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ERSYNCNEEDED, rdc_set->primary.intf,
36507836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
36517836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
36527836SJohn.Forte@Sun.COM 		rc = RDC_ERSYNCNEEDED;
36537836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36547836SJohn.Forte@Sun.COM 	}
36557836SJohn.Forte@Sun.COM 
36567836SJohn.Forte@Sun.COM 	urdc->sync_pos = 0;
36577836SJohn.Forte@Sun.COM 
36587836SJohn.Forte@Sun.COM 	/* Check if the rdc set is accessible on the remote node */
36597836SJohn.Forte@Sun.COM 	if (rdc_net_getstate(krdc, &sm, &um, &md, FALSE) < 0) {
36607836SJohn.Forte@Sun.COM 		/*
36617836SJohn.Forte@Sun.COM 		 * Remote end may be inaccessible, or the rdc set is not
36627836SJohn.Forte@Sun.COM 		 * enabled at the remote end.
36637836SJohn.Forte@Sun.COM 		 */
36647836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ECONNOPEN, urdc->secondary.intf,
36657836SJohn.Forte@Sun.COM 		    urdc->secondary.file);
36667836SJohn.Forte@Sun.COM 		rc = RDC_ECONNOPEN;
36677836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36687836SJohn.Forte@Sun.COM 	}
36697836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_REVERSE)
36707836SJohn.Forte@Sun.COM 		krdc->remote_index = rdc_net_state(index, CCIO_RSYNC);
36717836SJohn.Forte@Sun.COM 	else
36727836SJohn.Forte@Sun.COM 		krdc->remote_index = rdc_net_state(index, CCIO_SLAVE);
36737836SJohn.Forte@Sun.COM 	if (krdc->remote_index < 0) {
36747836SJohn.Forte@Sun.COM 		/*
36757836SJohn.Forte@Sun.COM 		 * Remote note probably not in a valid state to be synced,
36767836SJohn.Forte@Sun.COM 		 * as the state was fetched OK above.
36777836SJohn.Forte@Sun.COM 		 */
36787836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ERSTATE, urdc->secondary.intf,
36797836SJohn.Forte@Sun.COM 		    urdc->secondary.file, urdc->primary.intf,
36807836SJohn.Forte@Sun.COM 		    urdc->primary.file);
36817836SJohn.Forte@Sun.COM 		rc = RDC_ERSTATE;
36827836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36837836SJohn.Forte@Sun.COM 	}
36847836SJohn.Forte@Sun.COM 
36857836SJohn.Forte@Sun.COM 	rc = check_filesize(index, kstatus);
36867836SJohn.Forte@Sun.COM 	if (rc != 0) {
36877836SJohn.Forte@Sun.COM 		(void) rdc_net_state(krdc->index, CCIO_ENABLELOG);
36887836SJohn.Forte@Sun.COM 		goto notstarted_unlock;
36897836SJohn.Forte@Sun.COM 	}
36907836SJohn.Forte@Sun.COM 
36917836SJohn.Forte@Sun.COM 	krdc->sync_done = 0;
36927836SJohn.Forte@Sun.COM 
36937836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->bmapmutex);
36947836SJohn.Forte@Sun.COM 	krdc->aux_state |= RDC_AUXSYNCIP;
36957836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->bmapmutex);
36967836SJohn.Forte@Sun.COM 
36977836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_REVERSE) {
36987836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
36997836SJohn.Forte@Sun.COM 		rdc_set_mflags(urdc, RDC_SLAVE | RDC_RSYNC_NEEDED);
37007836SJohn.Forte@Sun.COM 		mutex_enter(&krdc->bmapmutex);
37017836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_VOL_FAILED);
37027836SJohn.Forte@Sun.COM 		mutex_exit(&krdc->bmapmutex);
37037836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
37047836SJohn.Forte@Sun.COM 		/* LINTED */
37057836SJohn.Forte@Sun.COM 		if (kmulti = krdc->multi_next) {
37067836SJohn.Forte@Sun.COM 			umulti = &rdc_u_info[kmulti->index];
37077836SJohn.Forte@Sun.COM 			if (IS_ENABLED(umulti) && (rdc_get_vflags(umulti) &
37087836SJohn.Forte@Sun.COM 			    (RDC_VOL_FAILED | RDC_SYNC_NEEDED))) {
37097836SJohn.Forte@Sun.COM 				rdc_clr_flags(umulti, RDC_SYNC_NEEDED);
37107836SJohn.Forte@Sun.COM 				rdc_clr_flags(umulti, RDC_VOL_FAILED);
37117836SJohn.Forte@Sun.COM 				rdc_write_state(umulti);
37127836SJohn.Forte@Sun.COM 			}
37137836SJohn.Forte@Sun.COM 		}
37147836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
37157836SJohn.Forte@Sun.COM 	} else {
37167836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_FCAL_FAILED);
37177836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
37187836SJohn.Forte@Sun.COM 	}
37197836SJohn.Forte@Sun.COM 
37207836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_UPDATE) {
37217836SJohn.Forte@Sun.COM 		ASSERT(urdc->volume_size != 0);
37227836SJohn.Forte@Sun.COM 		if (rdc_net_getbmap(index,
37237836SJohn.Forte@Sun.COM 		    BMAP_LOG_BYTES(urdc->volume_size)) > 0) {
37247836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_ENOBMAP);
37257836SJohn.Forte@Sun.COM 			rc = RDC_ENOBMAP;
37267836SJohn.Forte@Sun.COM 
37277836SJohn.Forte@Sun.COM 			(void) rdc_net_state(index, CCIO_ENABLELOG);
37287836SJohn.Forte@Sun.COM 
37297836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_SYNCING);
37307836SJohn.Forte@Sun.COM 			if (options & RDC_OPT_REVERSE) {
37317836SJohn.Forte@Sun.COM 				rdc_many_enter(krdc);
37327836SJohn.Forte@Sun.COM 				rdc_clr_mflags(urdc, RDC_SLAVE);
37337836SJohn.Forte@Sun.COM 				rdc_many_exit(krdc);
37347836SJohn.Forte@Sun.COM 			}
37357836SJohn.Forte@Sun.COM 			if (krdc->type_flag & RDC_ASYNCMODE)
37367836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_ASYNC);
37377836SJohn.Forte@Sun.COM 			krdc->remote_index = -1;
37387836SJohn.Forte@Sun.COM 			rdc_set_flags_log(urdc, RDC_LOGGING,
3739*9093SRamana.Srikanth@Sun.COM 			    "failed to read remote bitmap");
37407836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
37417836SJohn.Forte@Sun.COM 			goto failed;
37427836SJohn.Forte@Sun.COM 		}
37437836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_FULL);
37447836SJohn.Forte@Sun.COM 	} else {
37457836SJohn.Forte@Sun.COM 		/*
37467836SJohn.Forte@Sun.COM 		 * This is a full sync (not an update sync), mark the
37477836SJohn.Forte@Sun.COM 		 * entire bitmap dirty
37487836SJohn.Forte@Sun.COM 		 */
37497836SJohn.Forte@Sun.COM 		(void) RDC_FILL_BITMAP(krdc, FALSE);
37507836SJohn.Forte@Sun.COM 
37517836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_FULL);
37527836SJohn.Forte@Sun.COM 	}
37537836SJohn.Forte@Sun.COM 
37547836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
37557836SJohn.Forte@Sun.COM 
37567836SJohn.Forte@Sun.COM 	/*
37577836SJohn.Forte@Sun.COM 	 * allow diskq->memq flusher to wake up
37587836SJohn.Forte@Sun.COM 	 */
37597836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->group->ra_queue.net_qlock);
37607836SJohn.Forte@Sun.COM 	krdc->group->ra_queue.qfflags &= ~RDC_QFILLSLEEP;
37617836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->group->ra_queue.net_qlock);
37627836SJohn.Forte@Sun.COM 
37637836SJohn.Forte@Sun.COM 	/*
37647836SJohn.Forte@Sun.COM 	 * if this is a full sync on a non-diskq set or
37657836SJohn.Forte@Sun.COM 	 * a diskq set that has failed, clear the async flag
37667836SJohn.Forte@Sun.COM 	 */
37677836SJohn.Forte@Sun.COM 	if (krdc->type_flag & RDC_ASYNCMODE) {
37687836SJohn.Forte@Sun.COM 		if ((!(options & RDC_OPT_UPDATE)) ||
37697836SJohn.Forte@Sun.COM 		    (!RDC_IS_DISKQ(krdc->group)) ||
37707836SJohn.Forte@Sun.COM 		    (!(IS_STATE(urdc, RDC_QUEUING)))) {
37717836SJohn.Forte@Sun.COM 			/* full syncs, or core queue are synchronous */
37727836SJohn.Forte@Sun.COM 			rdc_group_enter(krdc);
37737836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_ASYNC);
37747836SJohn.Forte@Sun.COM 			rdc_group_exit(krdc);
37757836SJohn.Forte@Sun.COM 		}
37767836SJohn.Forte@Sun.COM 
37777836SJohn.Forte@Sun.COM 		/*
37787836SJohn.Forte@Sun.COM 		 * if the queue failed because it was full, lets see
37797836SJohn.Forte@Sun.COM 		 * if we can restart it. After _rdc_sync() is done
37807836SJohn.Forte@Sun.COM 		 * the modes will switch and we will begin disk
37817836SJohn.Forte@Sun.COM 		 * queuing again. NOTE: this should only be called
37827836SJohn.Forte@Sun.COM 		 * once per group, as it clears state for all group
37837836SJohn.Forte@Sun.COM 		 * members, also clears the async flag for all members
37847836SJohn.Forte@Sun.COM 		 */
37857836SJohn.Forte@Sun.COM 		if (IS_STATE(urdc, RDC_DISKQ_FAILED)) {
37867836SJohn.Forte@Sun.COM 			rdc_unfail_diskq(krdc);
37877836SJohn.Forte@Sun.COM 		} else {
37887836SJohn.Forte@Sun.COM 		/* don't add insult to injury by flushing a dead queue */
37897836SJohn.Forte@Sun.COM 
37907836SJohn.Forte@Sun.COM 			/*
37917836SJohn.Forte@Sun.COM 			 * if we are updating, and a diskq and
37927836SJohn.Forte@Sun.COM 			 * the async thread isn't active, start
37937836SJohn.Forte@Sun.COM 			 * it up.
37947836SJohn.Forte@Sun.COM 			 */
37957836SJohn.Forte@Sun.COM 			if ((options & RDC_OPT_UPDATE) &&
37967836SJohn.Forte@Sun.COM 			    (IS_STATE(urdc, RDC_QUEUING))) {
37977836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
37987836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_SYNCING);
37997836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
38007836SJohn.Forte@Sun.COM 				mutex_enter(&krdc->group->ra_queue.net_qlock);
38017836SJohn.Forte@Sun.COM 				if (krdc->group->ra_queue.qfill_sleeping ==
38027836SJohn.Forte@Sun.COM 				    RDC_QFILL_ASLEEP)
38037836SJohn.Forte@Sun.COM 					cv_broadcast(&group->ra_queue.qfcv);
38047836SJohn.Forte@Sun.COM 				mutex_exit(&krdc->group->ra_queue.net_qlock);
38057836SJohn.Forte@Sun.COM 				thrcount = urdc->asyncthr;
38067836SJohn.Forte@Sun.COM 				while ((thrcount-- > 0) &&
38077836SJohn.Forte@Sun.COM 				    !krdc->group->rdc_writer) {
38087836SJohn.Forte@Sun.COM 					(void) rdc_writer(krdc->index);
38097836SJohn.Forte@Sun.COM 				}
38107836SJohn.Forte@Sun.COM 			}
38117836SJohn.Forte@Sun.COM 		}
38127836SJohn.Forte@Sun.COM 	}
38137836SJohn.Forte@Sun.COM 
38147836SJohn.Forte@Sun.COM 	/*
38157836SJohn.Forte@Sun.COM 	 * For a reverse sync, merge the current bitmap with all other sets
38167836SJohn.Forte@Sun.COM 	 * that share this volume.
38177836SJohn.Forte@Sun.COM 	 */
38187836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_REVERSE) {
38197836SJohn.Forte@Sun.COM retry_many:
38207836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
38217836SJohn.Forte@Sun.COM 		if (IS_MANY(krdc)) {
38227836SJohn.Forte@Sun.COM 			rdc_k_info_t *kmany;
38237836SJohn.Forte@Sun.COM 			rdc_u_info_t *umany;
38247836SJohn.Forte@Sun.COM 
38257836SJohn.Forte@Sun.COM 			for (kmany = krdc->many_next; kmany != krdc;
38267836SJohn.Forte@Sun.COM 			    kmany = kmany->many_next) {
38277836SJohn.Forte@Sun.COM 				umany = &rdc_u_info[kmany->index];
38287836SJohn.Forte@Sun.COM 				if (!IS_ENABLED(umany))
38297836SJohn.Forte@Sun.COM 					continue;
38307836SJohn.Forte@Sun.COM 				ASSERT(umany->flags & RDC_PRIMARY);
38317836SJohn.Forte@Sun.COM 
38327836SJohn.Forte@Sun.COM 				if (!mutex_tryenter(&kmany->group->lock)) {
38337836SJohn.Forte@Sun.COM 					rdc_many_exit(krdc);
38347836SJohn.Forte@Sun.COM 					/* May merge more than once */
38357836SJohn.Forte@Sun.COM 					goto retry_many;
38367836SJohn.Forte@Sun.COM 				}
38377836SJohn.Forte@Sun.COM 				rdc_merge_bitmaps(krdc, kmany);
38387836SJohn.Forte@Sun.COM 				mutex_exit(&kmany->group->lock);
38397836SJohn.Forte@Sun.COM 			}
38407836SJohn.Forte@Sun.COM 		}
38417836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
38427836SJohn.Forte@Sun.COM 
38437836SJohn.Forte@Sun.COM retry_multi:
38447836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
38457836SJohn.Forte@Sun.COM 		if (IS_MULTI(krdc)) {
38467836SJohn.Forte@Sun.COM 			rdc_k_info_t *kmulti = krdc->multi_next;
38477836SJohn.Forte@Sun.COM 			rdc_u_info_t *umulti = &rdc_u_info[kmulti->index];
38487836SJohn.Forte@Sun.COM 
38497836SJohn.Forte@Sun.COM 			if (IS_ENABLED(umulti)) {
38507836SJohn.Forte@Sun.COM 				ASSERT(!(umulti->flags & RDC_PRIMARY));
38517836SJohn.Forte@Sun.COM 
38527836SJohn.Forte@Sun.COM 				if (!mutex_tryenter(&kmulti->group->lock)) {
38537836SJohn.Forte@Sun.COM 					rdc_many_exit(krdc);
38547836SJohn.Forte@Sun.COM 					goto retry_multi;
38557836SJohn.Forte@Sun.COM 				}
38567836SJohn.Forte@Sun.COM 				rdc_merge_bitmaps(krdc, kmulti);
38577836SJohn.Forte@Sun.COM 				mutex_exit(&kmulti->group->lock);
38587836SJohn.Forte@Sun.COM 			}
38597836SJohn.Forte@Sun.COM 		}
38607836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
38617836SJohn.Forte@Sun.COM 	}
38627836SJohn.Forte@Sun.COM 
38637836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
38647836SJohn.Forte@Sun.COM 
38657836SJohn.Forte@Sun.COM 	if (krdc->bitmap_write == 0) {
38667836SJohn.Forte@Sun.COM 		if (rdc_write_bitmap_fill(krdc) >= 0)
38677836SJohn.Forte@Sun.COM 			krdc->bitmap_write = -1;
38687836SJohn.Forte@Sun.COM 	}
38697836SJohn.Forte@Sun.COM 
38707836SJohn.Forte@Sun.COM 	if (krdc->bitmap_write > 0)
38717836SJohn.Forte@Sun.COM 		(void) rdc_write_bitmap(krdc);
38727836SJohn.Forte@Sun.COM 
38737836SJohn.Forte@Sun.COM 	urdc->bits_set = RDC_COUNT_BITMAP(krdc);
38747836SJohn.Forte@Sun.COM 
38757836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
38767836SJohn.Forte@Sun.COM 
38777836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_REVERSE) {
38787836SJohn.Forte@Sun.COM 		(void) _rdc_sync_event_notify(RDC_SYNC_START,
38797836SJohn.Forte@Sun.COM 		    urdc->primary.file, urdc->group_name);
38807836SJohn.Forte@Sun.COM 	}
38817836SJohn.Forte@Sun.COM 
38827836SJohn.Forte@Sun.COM 	/* Now set off the sync itself */
38837836SJohn.Forte@Sun.COM 
38847836SJohn.Forte@Sun.COM 	mutex_enter(&net_blk_lock);
38857836SJohn.Forte@Sun.COM 	if (nsc_create_process(
38867836SJohn.Forte@Sun.COM 	    (void (*)(void *))_rdc_sync, (void *)krdc, FALSE)) {
38877836SJohn.Forte@Sun.COM 		mutex_exit(&net_blk_lock);
38887836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENOPROC);
38897836SJohn.Forte@Sun.COM 		/*
38907836SJohn.Forte@Sun.COM 		 * We used to just return here,
38917836SJohn.Forte@Sun.COM 		 * but we need to clear the AUXSYNCIP bit
38927836SJohn.Forte@Sun.COM 		 * and there is a very small chance that
38937836SJohn.Forte@Sun.COM 		 * someone may be waiting on the disk_status flag.
38947836SJohn.Forte@Sun.COM 		 */
38957836SJohn.Forte@Sun.COM 		rc = RDC_ENOPROC;
38967836SJohn.Forte@Sun.COM 		/*
38977836SJohn.Forte@Sun.COM 		 * need the group lock held at failed.
38987836SJohn.Forte@Sun.COM 		 */
38997836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
39007836SJohn.Forte@Sun.COM 		goto failed;
39017836SJohn.Forte@Sun.COM 	}
39027836SJohn.Forte@Sun.COM 
39037836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
39047836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
39057836SJohn.Forte@Sun.COM 	busy = 0;
39067836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
39077836SJohn.Forte@Sun.COM 
39087836SJohn.Forte@Sun.COM 	while (krdc->sync_done == 0)
39097836SJohn.Forte@Sun.COM 		cv_wait(&krdc->synccv, &net_blk_lock);
39107836SJohn.Forte@Sun.COM 	mutex_exit(&net_blk_lock);
39117836SJohn.Forte@Sun.COM 
39127836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
39137836SJohn.Forte@Sun.COM 
39147836SJohn.Forte@Sun.COM 	if (krdc->sync_done == RDC_FAILED) {
39157836SJohn.Forte@Sun.COM 		char siztmp1[16];
39167836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
39177836SJohn.Forte@Sun.COM 		    urdc->sync_pos, siztmp1, sizeof (siztmp1),
39187836SJohn.Forte@Sun.COM 		    0);
39197836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EFAIL, siztmp1);
39207836SJohn.Forte@Sun.COM 		rc = RDC_EFAIL;
39217836SJohn.Forte@Sun.COM 	} else
39227836SJohn.Forte@Sun.COM 		sync_completed = 1;
39237836SJohn.Forte@Sun.COM 
39247836SJohn.Forte@Sun.COM failed:
39257836SJohn.Forte@Sun.COM 	/*
39267836SJohn.Forte@Sun.COM 	 * We use this flag now to make halt_sync() wait for
39277836SJohn.Forte@Sun.COM 	 * us to terminate and let us take the group lock.
39287836SJohn.Forte@Sun.COM 	 */
39297836SJohn.Forte@Sun.COM 	krdc->aux_state &= ~RDC_AUXSYNCIP;
39307836SJohn.Forte@Sun.COM 	if (krdc->disk_status == 1) {
39317836SJohn.Forte@Sun.COM 		krdc->disk_status = 0;
39327836SJohn.Forte@Sun.COM 		cv_broadcast(&krdc->haltcv);
39337836SJohn.Forte@Sun.COM 	}
39347836SJohn.Forte@Sun.COM 
39357836SJohn.Forte@Sun.COM notstarted_unlock:
39367836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
39377836SJohn.Forte@Sun.COM 
39387836SJohn.Forte@Sun.COM 	if (sync_completed && (options & RDC_OPT_REVERSE)) {
39397836SJohn.Forte@Sun.COM 		(void) _rdc_sync_event_notify(RDC_SYNC_DONE,
39407836SJohn.Forte@Sun.COM 		    urdc->primary.file, urdc->group_name);
39417836SJohn.Forte@Sun.COM 	}
39427836SJohn.Forte@Sun.COM 
39437836SJohn.Forte@Sun.COM notstarted:
39447836SJohn.Forte@Sun.COM 	if (busy) {
39457836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
39467836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
39477836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
39487836SJohn.Forte@Sun.COM 	}
39497836SJohn.Forte@Sun.COM 
39507836SJohn.Forte@Sun.COM 	return (rc);
39517836SJohn.Forte@Sun.COM }
39527836SJohn.Forte@Sun.COM 
39537836SJohn.Forte@Sun.COM /* ARGSUSED */
39547836SJohn.Forte@Sun.COM static int
_rdc_suspend(rdc_k_info_t * krdc,rdc_set_t * rdc_set,spcs_s_info_t kstatus)39557836SJohn.Forte@Sun.COM _rdc_suspend(rdc_k_info_t *krdc, rdc_set_t *rdc_set, spcs_s_info_t kstatus)
39567836SJohn.Forte@Sun.COM {
39577836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
39587836SJohn.Forte@Sun.COM 	rdc_if_t *ip;
39597836SJohn.Forte@Sun.COM 	int index = krdc->index;
39607836SJohn.Forte@Sun.COM 
39617836SJohn.Forte@Sun.COM 	ASSERT(krdc->group != NULL);
39627836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
39637836SJohn.Forte@Sun.COM #ifdef DEBUG
39647836SJohn.Forte@Sun.COM 	ASSERT(rdc_check(krdc, rdc_set) == 0);
39657836SJohn.Forte@Sun.COM #else
39667836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, rdc_set)) {
39677836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
39687836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
39697836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
39707836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
39717836SJohn.Forte@Sun.COM 	}
39727836SJohn.Forte@Sun.COM #endif
39737836SJohn.Forte@Sun.COM 
39747836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
39757836SJohn.Forte@Sun.COM 		halt_sync(krdc);
39767836SJohn.Forte@Sun.COM 		ASSERT(IS_ENABLED(urdc));
39777836SJohn.Forte@Sun.COM 	}
39787836SJohn.Forte@Sun.COM 
39797836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
39807836SJohn.Forte@Sun.COM 	(void) rdc_unintercept(krdc);
39817836SJohn.Forte@Sun.COM 
39827836SJohn.Forte@Sun.COM #ifdef DEBUG
3983*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR: suspended %s %s", urdc->primary.file,
39847836SJohn.Forte@Sun.COM 	    urdc->secondary.file);
39857836SJohn.Forte@Sun.COM #endif
39867836SJohn.Forte@Sun.COM 
39877836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
39887836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
39897836SJohn.Forte@Sun.COM 
39907836SJohn.Forte@Sun.COM 
39917836SJohn.Forte@Sun.COM 	if (IS_ASYNC(urdc) && !RDC_IS_DISKQ(krdc->group)) {
39927836SJohn.Forte@Sun.COM 		int tries = 2; /* in case of possibly stuck flusher threads */
39937836SJohn.Forte@Sun.COM #ifdef DEBUG
39947836SJohn.Forte@Sun.COM 		net_queue *qp = &krdc->group->ra_queue;
39957836SJohn.Forte@Sun.COM #endif
39967836SJohn.Forte@Sun.COM 		do {
39977836SJohn.Forte@Sun.COM 			if (!krdc->group->rdc_writer)
39987836SJohn.Forte@Sun.COM 				(void) rdc_writer(krdc->index);
39997836SJohn.Forte@Sun.COM 
40007836SJohn.Forte@Sun.COM 			(void) rdc_drain_queue(krdc->index);
40017836SJohn.Forte@Sun.COM 
40027836SJohn.Forte@Sun.COM 		} while (krdc->group->rdc_writer && tries--);
40037836SJohn.Forte@Sun.COM 
40047836SJohn.Forte@Sun.COM 		/* ok, force it to happen... */
40057836SJohn.Forte@Sun.COM 		if (rdc_drain_queue(krdc->index) != 0) {
40067836SJohn.Forte@Sun.COM 			do {
40077836SJohn.Forte@Sun.COM 				mutex_enter(&krdc->group->ra_queue.net_qlock);
40087836SJohn.Forte@Sun.COM 				krdc->group->asyncdis = 1;
40097836SJohn.Forte@Sun.COM 				cv_broadcast(&krdc->group->asyncqcv);
40107836SJohn.Forte@Sun.COM 				mutex_exit(&krdc->group->ra_queue.net_qlock);
40117836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
4012*9093SRamana.Srikanth@Sun.COM 				    "!SNDR: async I/O pending and not flushed "
4013*9093SRamana.Srikanth@Sun.COM 				    "for %s during suspend",
40147836SJohn.Forte@Sun.COM 				    urdc->primary.file);
40157836SJohn.Forte@Sun.COM #ifdef DEBUG
40167836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
4017*9093SRamana.Srikanth@Sun.COM 				    "!nitems: %" NSC_SZFMT " nblocks: %"
4018*9093SRamana.Srikanth@Sun.COM 				    NSC_SZFMT " head: 0x%p tail: 0x%p",
4019*9093SRamana.Srikanth@Sun.COM 				    qp->nitems, qp->blocks,
4020*9093SRamana.Srikanth@Sun.COM 				    (void *)qp->net_qhead,
4021*9093SRamana.Srikanth@Sun.COM 				    (void *)qp->net_qtail);
40227836SJohn.Forte@Sun.COM #endif
40237836SJohn.Forte@Sun.COM 			} while (krdc->group->rdc_thrnum > 0);
40247836SJohn.Forte@Sun.COM 		}
40257836SJohn.Forte@Sun.COM 	}
40267836SJohn.Forte@Sun.COM 
40277836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
40287836SJohn.Forte@Sun.COM 	ip = krdc->intf;
40297836SJohn.Forte@Sun.COM 	krdc->intf = 0;
40307836SJohn.Forte@Sun.COM 
40317836SJohn.Forte@Sun.COM 	if (ip) {
40327836SJohn.Forte@Sun.COM 		rdc_remove_from_if(ip);
40337836SJohn.Forte@Sun.COM 	}
40347836SJohn.Forte@Sun.COM 
40357836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
40367836SJohn.Forte@Sun.COM 
40377836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
40387836SJohn.Forte@Sun.COM 
40397836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
40407836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
40417836SJohn.Forte@Sun.COM 
40427836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
40437836SJohn.Forte@Sun.COM 	/* Must not hold group lock during this function */
40447836SJohn.Forte@Sun.COM 	while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
40457836SJohn.Forte@Sun.COM 		delay(2);
40467836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
40477836SJohn.Forte@Sun.COM 
40487836SJohn.Forte@Sun.COM 	/* Don't rdc_clear_state, unlike _rdc_disable */
40497836SJohn.Forte@Sun.COM 
40507836SJohn.Forte@Sun.COM 	rdc_free_bitmap(krdc, RDC_CMD_SUSPEND);
40517836SJohn.Forte@Sun.COM 	rdc_close_bitmap(krdc);
40527836SJohn.Forte@Sun.COM 
40537836SJohn.Forte@Sun.COM 	rdc_dev_close(krdc);
40547836SJohn.Forte@Sun.COM 	rdc_close_direct(krdc);
40557836SJohn.Forte@Sun.COM 
40567836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
40577836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
40587836SJohn.Forte@Sun.COM 
40597836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
40607836SJohn.Forte@Sun.COM 
40617836SJohn.Forte@Sun.COM 	/*
40627836SJohn.Forte@Sun.COM 	 * we should now unregister the queue, with no conflicting
40637836SJohn.Forte@Sun.COM 	 * locks held. This is the last(only) member of the group
40647836SJohn.Forte@Sun.COM 	 */
40657836SJohn.Forte@Sun.COM 	if (krdc->group && RDC_IS_DISKQ(krdc->group) &&
40667836SJohn.Forte@Sun.COM 	    krdc->group->count == 1) { /* stop protecting queue */
40677836SJohn.Forte@Sun.COM 		rdc_unintercept_diskq(krdc->group);
40687836SJohn.Forte@Sun.COM 	}
40697836SJohn.Forte@Sun.COM 
40707836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
40717836SJohn.Forte@Sun.COM 
40727836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
40737836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
40747836SJohn.Forte@Sun.COM 
40757836SJohn.Forte@Sun.COM 	wait_busy(krdc);
40767836SJohn.Forte@Sun.COM 
40777836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) || IS_MULTI(krdc))
40787836SJohn.Forte@Sun.COM 		remove_from_many(krdc);
40797836SJohn.Forte@Sun.COM 
40807836SJohn.Forte@Sun.COM 	remove_from_group(krdc);
40817836SJohn.Forte@Sun.COM 
40827836SJohn.Forte@Sun.COM 	krdc->remote_index = -1;
40837836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_CONFIGURED);
40847836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_DISABLEPEND);
40857836SJohn.Forte@Sun.COM 	krdc->type_flag = 0;
40867836SJohn.Forte@Sun.COM #ifdef	DEBUG
40877836SJohn.Forte@Sun.COM 	if (krdc->dcio_bitmap)
4088*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_rdc_suspend: possible mem leak, "
40897836SJohn.Forte@Sun.COM 		    "dcio_bitmap");
40907836SJohn.Forte@Sun.COM #endif
40917836SJohn.Forte@Sun.COM 	krdc->dcio_bitmap = NULL;
40927836SJohn.Forte@Sun.COM 	krdc->bitmap_ref = NULL;
40937836SJohn.Forte@Sun.COM 	krdc->bitmap_size = 0;
40947836SJohn.Forte@Sun.COM 	krdc->maxfbas = 0;
40957836SJohn.Forte@Sun.COM 	krdc->bitmap_write = 0;
40967836SJohn.Forte@Sun.COM 	krdc->disk_status = 0;
40977836SJohn.Forte@Sun.COM 	rdc_destroy_svinfo(krdc->lsrv);
40987836SJohn.Forte@Sun.COM 	krdc->lsrv = NULL;
40997836SJohn.Forte@Sun.COM 	krdc->multi_next = NULL;
41007836SJohn.Forte@Sun.COM 
41017836SJohn.Forte@Sun.COM 	rdc_u_init(urdc);
41027836SJohn.Forte@Sun.COM 
41037836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
41047836SJohn.Forte@Sun.COM 	rdc_kstat_delete(index);
41057836SJohn.Forte@Sun.COM 	return (0);
41067836SJohn.Forte@Sun.COM }
41077836SJohn.Forte@Sun.COM 
41087836SJohn.Forte@Sun.COM static int
rdc_suspend(rdc_config_t * uparms,spcs_s_info_t kstatus)41097836SJohn.Forte@Sun.COM rdc_suspend(rdc_config_t *uparms, spcs_s_info_t kstatus)
41107836SJohn.Forte@Sun.COM {
41117836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
41127836SJohn.Forte@Sun.COM 	int index;
41137836SJohn.Forte@Sun.COM 	int rc;
41147836SJohn.Forte@Sun.COM 
41157836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
41167836SJohn.Forte@Sun.COM 
41177836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
41187836SJohn.Forte@Sun.COM 	if (index >= 0)
41197836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
41207836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
41217836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41227836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
41237836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
41247836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
41257836SJohn.Forte@Sun.COM 	}
41267836SJohn.Forte@Sun.COM 
41277836SJohn.Forte@Sun.COM 	krdc->type_flag |= RDC_DISABLEPEND;
41287836SJohn.Forte@Sun.COM 	wait_busy(krdc);
41297836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
41307836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
41317836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41327836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
41337836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
41347836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
41357836SJohn.Forte@Sun.COM 	}
41367836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
41377836SJohn.Forte@Sun.COM 
41387836SJohn.Forte@Sun.COM 	rc = _rdc_suspend(krdc, uparms->rdc_set, kstatus);
41397836SJohn.Forte@Sun.COM 	return (rc);
41407836SJohn.Forte@Sun.COM }
41417836SJohn.Forte@Sun.COM 
41427836SJohn.Forte@Sun.COM static int
_rdc_resume(rdc_set_t * rdc_set,int options,spcs_s_info_t kstatus)41437836SJohn.Forte@Sun.COM _rdc_resume(rdc_set_t *rdc_set, int options, spcs_s_info_t kstatus)
41447836SJohn.Forte@Sun.COM {
41457836SJohn.Forte@Sun.COM 	int index;
41467836SJohn.Forte@Sun.COM 	char *rhost;
41477836SJohn.Forte@Sun.COM 	struct netbuf *addrp;
41487836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
41497836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
41507836SJohn.Forte@Sun.COM 	rdc_srv_t *svp = NULL;
41517836SJohn.Forte@Sun.COM 	char *local_file;
41527836SJohn.Forte@Sun.COM 	char *local_bitmap;
41537836SJohn.Forte@Sun.COM 	int rc, rc1;
41547836SJohn.Forte@Sun.COM 	nsc_size_t maxfbas;
41557836SJohn.Forte@Sun.COM 	rdc_group_t *grp;
41567836SJohn.Forte@Sun.COM 
41577836SJohn.Forte@Sun.COM 	if ((rdc_set->primary.intf[0] == 0) ||
41587836SJohn.Forte@Sun.COM 	    (rdc_set->primary.addr.len == 0) ||
41597836SJohn.Forte@Sun.COM 	    (rdc_set->primary.file[0] == 0) ||
41607836SJohn.Forte@Sun.COM 	    (rdc_set->primary.bitmap[0] == 0) ||
41617836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.intf[0] == 0) ||
41627836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.addr.len == 0) ||
41637836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.file[0] == 0) ||
41647836SJohn.Forte@Sun.COM 	    (rdc_set->secondary.bitmap[0] == 0)) {
41657836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEMPTY);
41667836SJohn.Forte@Sun.COM 		return (RDC_EEMPTY);
41677836SJohn.Forte@Sun.COM 	}
41687836SJohn.Forte@Sun.COM 
41697836SJohn.Forte@Sun.COM 	/* Next check there aren't any enabled rdc sets which match. */
41707836SJohn.Forte@Sun.COM 
41717836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
41727836SJohn.Forte@Sun.COM 
41737836SJohn.Forte@Sun.COM 	if (rdc_lookup_byname(rdc_set) >= 0) {
41747836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41757836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EENABLED, rdc_set->primary.intf,
41767836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
41777836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
41787836SJohn.Forte@Sun.COM 		return (RDC_EENABLED);
41797836SJohn.Forte@Sun.COM 	}
41807836SJohn.Forte@Sun.COM 
41817836SJohn.Forte@Sun.COM 	if (rdc_lookup_many2one(rdc_set) >= 0) {
41827836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41837836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EMANY2ONE, rdc_set->primary.intf,
41847836SJohn.Forte@Sun.COM 		    rdc_set->primary.file, rdc_set->secondary.intf,
41857836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
41867836SJohn.Forte@Sun.COM 		return (RDC_EMANY2ONE);
41877836SJohn.Forte@Sun.COM 	}
41887836SJohn.Forte@Sun.COM 
41897836SJohn.Forte@Sun.COM 	if (rdc_set->netconfig->knc_proto == NULL) {
41907836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41917836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETCONFIG);
41927836SJohn.Forte@Sun.COM 		return (RDC_ENETCONFIG);
41937836SJohn.Forte@Sun.COM 	}
41947836SJohn.Forte@Sun.COM 
41957836SJohn.Forte@Sun.COM 	if (rdc_set->primary.addr.len == 0) {
41967836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
41977836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETBUF, rdc_set->primary.file);
41987836SJohn.Forte@Sun.COM 		return (RDC_ENETBUF);
41997836SJohn.Forte@Sun.COM 	}
42007836SJohn.Forte@Sun.COM 
42017836SJohn.Forte@Sun.COM 	if (rdc_set->secondary.addr.len == 0) {
42027836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42037836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENETBUF, rdc_set->secondary.file);
42047836SJohn.Forte@Sun.COM 		return (RDC_ENETBUF);
42057836SJohn.Forte@Sun.COM 	}
42067836SJohn.Forte@Sun.COM 
42077836SJohn.Forte@Sun.COM 	/* Check that the local data volume isn't in use as a bitmap */
42087836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
42097836SJohn.Forte@Sun.COM 		local_file = rdc_set->primary.file;
42107836SJohn.Forte@Sun.COM 	else
42117836SJohn.Forte@Sun.COM 		local_file = rdc_set->secondary.file;
42127836SJohn.Forte@Sun.COM 	if (rdc_lookup_bitmap(local_file) >= 0) {
42137836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42147836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EVOLINUSE, local_file);
42157836SJohn.Forte@Sun.COM 		return (RDC_EVOLINUSE);
42167836SJohn.Forte@Sun.COM 	}
42177836SJohn.Forte@Sun.COM 
42187836SJohn.Forte@Sun.COM 	/* check that the secondary data volume isn't in use */
42197836SJohn.Forte@Sun.COM 	if (!(options & RDC_OPT_PRIMARY)) {
42207836SJohn.Forte@Sun.COM 		local_file = rdc_set->secondary.file;
42217836SJohn.Forte@Sun.COM 		if (rdc_lookup_secondary(local_file) >= 0) {
42227836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
42237836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EVOLINUSE, local_file);
42247836SJohn.Forte@Sun.COM 			return (RDC_EVOLINUSE);
42257836SJohn.Forte@Sun.COM 		}
42267836SJohn.Forte@Sun.COM 	}
42277836SJohn.Forte@Sun.COM 
42287836SJohn.Forte@Sun.COM 	/* Check that the bitmap isn't in use as a data volume */
42297836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
42307836SJohn.Forte@Sun.COM 		local_bitmap = rdc_set->primary.bitmap;
42317836SJohn.Forte@Sun.COM 	else
42327836SJohn.Forte@Sun.COM 		local_bitmap = rdc_set->secondary.bitmap;
42337836SJohn.Forte@Sun.COM 	if (rdc_lookup_configured(local_bitmap) >= 0) {
42347836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42357836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBMPINUSE, local_bitmap);
42367836SJohn.Forte@Sun.COM 		return (RDC_EBMPINUSE);
42377836SJohn.Forte@Sun.COM 	}
42387836SJohn.Forte@Sun.COM 
42397836SJohn.Forte@Sun.COM 	/* Check that the bitmap isn't already in use as a bitmap */
42407836SJohn.Forte@Sun.COM 	if (rdc_lookup_bitmap(local_bitmap) >= 0) {
42417836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42427836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBMPINUSE, local_bitmap);
42437836SJohn.Forte@Sun.COM 		return (RDC_EBMPINUSE);
42447836SJohn.Forte@Sun.COM 	}
42457836SJohn.Forte@Sun.COM 
42467836SJohn.Forte@Sun.COM 	/* Set urdc->volume_size */
42477836SJohn.Forte@Sun.COM 	index = rdc_dev_open(rdc_set, options);
42487836SJohn.Forte@Sun.COM 	if (index < 0) {
42497836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42507836SJohn.Forte@Sun.COM 		if (options & RDC_OPT_PRIMARY)
42517836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EOPEN, rdc_set->primary.intf,
42527836SJohn.Forte@Sun.COM 			    rdc_set->primary.file);
42537836SJohn.Forte@Sun.COM 		else
42547836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EOPEN, rdc_set->secondary.intf,
42557836SJohn.Forte@Sun.COM 			    rdc_set->secondary.file);
42567836SJohn.Forte@Sun.COM 		return (RDC_EOPEN);
42577836SJohn.Forte@Sun.COM 	}
42587836SJohn.Forte@Sun.COM 
42597836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
42607836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
42617836SJohn.Forte@Sun.COM 
42627836SJohn.Forte@Sun.COM 	/* copy relevant parts of rdc_set to urdc field by field */
42637836SJohn.Forte@Sun.COM 
42647836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.intf, rdc_set->primary.intf,
42657836SJohn.Forte@Sun.COM 	    MAX_RDC_HOST_SIZE);
42667836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.intf, rdc_set->secondary.intf,
42677836SJohn.Forte@Sun.COM 	    MAX_RDC_HOST_SIZE);
42687836SJohn.Forte@Sun.COM 
42697836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->group_name, rdc_set->group_name, NSC_MAXPATH);
42707836SJohn.Forte@Sun.COM 
42717836SJohn.Forte@Sun.COM 	dup_rdc_netbuf(&rdc_set->primary.addr, &urdc->primary.addr);
42727836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.file, rdc_set->primary.file, NSC_MAXPATH);
42737836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->primary.bitmap, rdc_set->primary.bitmap,
42747836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
42757836SJohn.Forte@Sun.COM 
42767836SJohn.Forte@Sun.COM 	dup_rdc_netbuf(&rdc_set->secondary.addr, &urdc->secondary.addr);
42777836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.file, rdc_set->secondary.file,
42787836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
42797836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->secondary.bitmap, rdc_set->secondary.bitmap,
42807836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
42817836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->disk_queue, rdc_set->disk_queue, NSC_MAXPATH);
42827836SJohn.Forte@Sun.COM 	urdc->setid = rdc_set->setid;
42837836SJohn.Forte@Sun.COM 
42847836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_SYNC) && urdc->disk_queue[0]) {
42857836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
42867836SJohn.Forte@Sun.COM 		rdc_dev_close(krdc);
42877836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EQWRONGMODE);
42887836SJohn.Forte@Sun.COM 		return (RDC_EQWRONGMODE);
42897836SJohn.Forte@Sun.COM 	}
42907836SJohn.Forte@Sun.COM 
42917836SJohn.Forte@Sun.COM 	/*
42927836SJohn.Forte@Sun.COM 	 * init flags now so that state left by failures in add_to_group()
42937836SJohn.Forte@Sun.COM 	 * are preserved.
42947836SJohn.Forte@Sun.COM 	 */
42957836SJohn.Forte@Sun.COM 	rdc_init_flags(urdc);
42967836SJohn.Forte@Sun.COM 
42977836SJohn.Forte@Sun.COM 	if ((rc1 = add_to_group(krdc, options, RDC_CMD_RESUME)) != 0) {
42987836SJohn.Forte@Sun.COM 		if (rc1 == RDC_EQNOADD) { /* something went wrong with queue */
42997836SJohn.Forte@Sun.COM 			rdc_fail_diskq(krdc, RDC_WAIT, RDC_NOLOG);
43007836SJohn.Forte@Sun.COM 			/* don't return a failure here, continue with resume */
43017836SJohn.Forte@Sun.COM 
43027836SJohn.Forte@Sun.COM 		} else { /* some other group add failure */
43037836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
43047836SJohn.Forte@Sun.COM 			rdc_dev_close(krdc);
43057836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EGROUP,
43067836SJohn.Forte@Sun.COM 			    rdc_set->primary.intf, rdc_set->primary.file,
43077836SJohn.Forte@Sun.COM 			    rdc_set->secondary.intf, rdc_set->secondary.file,
43087836SJohn.Forte@Sun.COM 			    rdc_set->group_name);
43097836SJohn.Forte@Sun.COM 			return (RDC_EGROUP);
43107836SJohn.Forte@Sun.COM 		}
43117836SJohn.Forte@Sun.COM 	}
43127836SJohn.Forte@Sun.COM 
43137836SJohn.Forte@Sun.COM 	/*
43147836SJohn.Forte@Sun.COM 	 * maxfbas was set in rdc_dev_open as primary's maxfbas.
43157836SJohn.Forte@Sun.COM 	 * If diskq's maxfbas is smaller, then use diskq's.
43167836SJohn.Forte@Sun.COM 	 */
43177836SJohn.Forte@Sun.COM 	grp = krdc->group;
43187836SJohn.Forte@Sun.COM 	if (grp && RDC_IS_DISKQ(grp) && (grp->diskqfd != 0)) {
43197836SJohn.Forte@Sun.COM 		rc = _rdc_rsrv_diskq(grp);
43207836SJohn.Forte@Sun.COM 		if (RDC_SUCCESS(rc)) {
43217836SJohn.Forte@Sun.COM 			rc = nsc_maxfbas(grp->diskqfd, 0, &maxfbas);
43227836SJohn.Forte@Sun.COM 			if (rc == 0) {
43237836SJohn.Forte@Sun.COM #ifdef DEBUG
43247836SJohn.Forte@Sun.COM 				if (krdc->maxfbas != maxfbas)
4325*9093SRamana.Srikanth@Sun.COM 					cmn_err(CE_NOTE,
4326*9093SRamana.Srikanth@Sun.COM 					    "!_rdc_resume: diskq maxfbas = %"
4327*9093SRamana.Srikanth@Sun.COM 					    NSC_SZFMT ", primary maxfbas = %"
4328*9093SRamana.Srikanth@Sun.COM 					    NSC_SZFMT, maxfbas, krdc->maxfbas);
43297836SJohn.Forte@Sun.COM #endif
4330*9093SRamana.Srikanth@Sun.COM 					krdc->maxfbas = min(krdc->maxfbas,
4331*9093SRamana.Srikanth@Sun.COM 					    maxfbas);
43327836SJohn.Forte@Sun.COM 			} else {
43337836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
4334*9093SRamana.Srikanth@Sun.COM 				    "!_rdc_resume: diskq maxfbas failed (%d)",
43357836SJohn.Forte@Sun.COM 				    rc);
43367836SJohn.Forte@Sun.COM 			}
43377836SJohn.Forte@Sun.COM 			_rdc_rlse_diskq(grp);
43387836SJohn.Forte@Sun.COM 		} else {
43397836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
4340*9093SRamana.Srikanth@Sun.COM 			    "!_rdc_resume: diskq reserve failed (%d)", rc);
43417836SJohn.Forte@Sun.COM 		}
43427836SJohn.Forte@Sun.COM 	}
43437836SJohn.Forte@Sun.COM 
43447836SJohn.Forte@Sun.COM 	(void) strncpy(urdc->direct_file, rdc_set->direct_file, NSC_MAXPATH);
43457836SJohn.Forte@Sun.COM 	if ((options & RDC_OPT_PRIMARY) && rdc_set->direct_file[0]) {
43467836SJohn.Forte@Sun.COM 		if (rdc_open_direct(krdc) == NULL)
43477836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_FCAL_FAILED);
43487836SJohn.Forte@Sun.COM 	}
43497836SJohn.Forte@Sun.COM 
43507836SJohn.Forte@Sun.COM 	krdc->many_next = krdc;
43517836SJohn.Forte@Sun.COM 
43527836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag == 0);
43537836SJohn.Forte@Sun.COM 	krdc->type_flag = RDC_CONFIGURED;
43547836SJohn.Forte@Sun.COM 
43557836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
43567836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_PRIMARY);
43577836SJohn.Forte@Sun.COM 
43587836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_ASYNC)
43597836SJohn.Forte@Sun.COM 		krdc->type_flag |= RDC_ASYNCMODE;
43607836SJohn.Forte@Sun.COM 
43617836SJohn.Forte@Sun.COM 	set_busy(krdc);
43627836SJohn.Forte@Sun.COM 
43637836SJohn.Forte@Sun.COM 	urdc->syshostid = rdc_set->syshostid;
43647836SJohn.Forte@Sun.COM 
43657836SJohn.Forte@Sun.COM 	if (add_to_many(krdc) < 0) {
43667836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
43677836SJohn.Forte@Sun.COM 
43687836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
43697836SJohn.Forte@Sun.COM 
43707836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EMULTI);
43717836SJohn.Forte@Sun.COM 		rc = RDC_EMULTI;
43727836SJohn.Forte@Sun.COM 		goto fail;
43737836SJohn.Forte@Sun.COM 	}
43747836SJohn.Forte@Sun.COM 
43757836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
43767836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
43777836SJohn.Forte@Sun.COM 
43787836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
43797836SJohn.Forte@Sun.COM 
43807836SJohn.Forte@Sun.COM 	if (urdc->volume_size == 0) {
43817836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
43827836SJohn.Forte@Sun.COM 		if (options & RDC_OPT_PRIMARY)
43837836SJohn.Forte@Sun.COM 			rdc_set_mflags(urdc, RDC_RSYNC_NEEDED);
43847836SJohn.Forte@Sun.COM 		else
43857836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_SYNC_NEEDED);
43867836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_VOL_FAILED);
43877836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
43887836SJohn.Forte@Sun.COM 	}
43897836SJohn.Forte@Sun.COM 
43907836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
43917836SJohn.Forte@Sun.COM 
43927836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
43937836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
43947836SJohn.Forte@Sun.COM 
43957836SJohn.Forte@Sun.COM 	/*
43967836SJohn.Forte@Sun.COM 	 * The rdc set is configured but not yet enabled. Other operations must
43977836SJohn.Forte@Sun.COM 	 * ignore this set until it is enabled.
43987836SJohn.Forte@Sun.COM 	 */
43997836SJohn.Forte@Sun.COM 
44007836SJohn.Forte@Sun.COM 	urdc->sync_pos = 0;
44017836SJohn.Forte@Sun.COM 
44027836SJohn.Forte@Sun.COM 	/* Set tunable defaults, we'll pick up tunables from the header later */
44037836SJohn.Forte@Sun.COM 
44047836SJohn.Forte@Sun.COM 	urdc->maxqfbas = rdc_maxthres_queue;
44057836SJohn.Forte@Sun.COM 	urdc->maxqitems = rdc_max_qitems;
44067836SJohn.Forte@Sun.COM 	urdc->autosync = 0;
44077836SJohn.Forte@Sun.COM 	urdc->asyncthr = rdc_asyncthr;
44087836SJohn.Forte@Sun.COM 
44097836SJohn.Forte@Sun.COM 	urdc->netconfig = rdc_set->netconfig;
44107836SJohn.Forte@Sun.COM 
44117836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY) {
44127836SJohn.Forte@Sun.COM 		rhost = rdc_set->secondary.intf;
44137836SJohn.Forte@Sun.COM 		addrp = &rdc_set->secondary.addr;
44147836SJohn.Forte@Sun.COM 	} else {
44157836SJohn.Forte@Sun.COM 		rhost = rdc_set->primary.intf;
44167836SJohn.Forte@Sun.COM 		addrp = &rdc_set->primary.addr;
44177836SJohn.Forte@Sun.COM 	}
44187836SJohn.Forte@Sun.COM 
44197836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_ASYNC)
44207836SJohn.Forte@Sun.COM 		rdc_set_flags(urdc, RDC_ASYNC);
44217836SJohn.Forte@Sun.COM 
44227836SJohn.Forte@Sun.COM 	svp = rdc_create_svinfo(rhost, addrp, urdc->netconfig);
44237836SJohn.Forte@Sun.COM 	if (svp == NULL) {
44247836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, ENOMEM);
44257836SJohn.Forte@Sun.COM 		rc = ENOMEM;
44267836SJohn.Forte@Sun.COM 		goto fail;
44277836SJohn.Forte@Sun.COM 	}
44287836SJohn.Forte@Sun.COM 
44297836SJohn.Forte@Sun.COM 	urdc->netconfig = NULL;		/* This will be no good soon */
44307836SJohn.Forte@Sun.COM 
44317836SJohn.Forte@Sun.COM 	/* Don't set krdc->intf here */
44327836SJohn.Forte@Sun.COM 	rdc_kstat_create(index);
44337836SJohn.Forte@Sun.COM 
44347836SJohn.Forte@Sun.COM 	/* if the bitmap resume isn't clean, it will clear queuing flag */
44357836SJohn.Forte@Sun.COM 
44367836SJohn.Forte@Sun.COM 	(void) rdc_resume_bitmap(krdc);
44377836SJohn.Forte@Sun.COM 
44387836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
44397836SJohn.Forte@Sun.COM 		disk_queue *q = &krdc->group->diskq;
44407836SJohn.Forte@Sun.COM 		if ((rc1 == RDC_EQNOADD) ||
44417836SJohn.Forte@Sun.COM 		    IS_QSTATE(q, RDC_QBADRESUME)) {
44427836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_QUEUING);
44437836SJohn.Forte@Sun.COM 			RDC_ZERO_BITREF(krdc);
44447836SJohn.Forte@Sun.COM 		}
44457836SJohn.Forte@Sun.COM 	}
44467836SJohn.Forte@Sun.COM 
44477836SJohn.Forte@Sun.COM 	if (krdc->lsrv == NULL)
44487836SJohn.Forte@Sun.COM 		krdc->lsrv = svp;
44497836SJohn.Forte@Sun.COM 	else {
44507836SJohn.Forte@Sun.COM #ifdef DEBUG
4451*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_rdc_resume: krdc->lsrv already set: %p",
4452*9093SRamana.Srikanth@Sun.COM 		    (void *) krdc->lsrv);
44537836SJohn.Forte@Sun.COM #endif
44547836SJohn.Forte@Sun.COM 		rdc_destroy_svinfo(svp);
44557836SJohn.Forte@Sun.COM 	}
44567836SJohn.Forte@Sun.COM 	svp = NULL;
44577836SJohn.Forte@Sun.COM 
44587836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
44597836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
44607836SJohn.Forte@Sun.COM 
44617836SJohn.Forte@Sun.COM 	/* And finally */
44627836SJohn.Forte@Sun.COM 
44637836SJohn.Forte@Sun.COM 	krdc->remote_index = -1;
44647836SJohn.Forte@Sun.COM 
44657836SJohn.Forte@Sun.COM 	/* Should we set the whole group logging? */
44667836SJohn.Forte@Sun.COM 	rdc_set_flags(urdc, RDC_ENABLED | RDC_LOGGING);
44677836SJohn.Forte@Sun.COM 
44687836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
44697836SJohn.Forte@Sun.COM 
44707836SJohn.Forte@Sun.COM 	if (rdc_intercept(krdc) != 0) {
44717836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
44727836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_ENABLED);
44737836SJohn.Forte@Sun.COM 		if (options & RDC_OPT_PRIMARY)
44747836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EREGISTER, urdc->primary.file);
44757836SJohn.Forte@Sun.COM 		else
44767836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EREGISTER,
44777836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
44787836SJohn.Forte@Sun.COM #ifdef DEBUG
4479*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!nsc_register_path failed %s",
44807836SJohn.Forte@Sun.COM 		    urdc->primary.file);
44817836SJohn.Forte@Sun.COM #endif
44827836SJohn.Forte@Sun.COM 		rc = RDC_EREGISTER;
44837836SJohn.Forte@Sun.COM 		goto bmpfail;
44847836SJohn.Forte@Sun.COM 	}
44857836SJohn.Forte@Sun.COM #ifdef DEBUG
4486*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SNDR: resumed %s %s", urdc->primary.file,
44877836SJohn.Forte@Sun.COM 	    urdc->secondary.file);
44887836SJohn.Forte@Sun.COM #endif
44897836SJohn.Forte@Sun.COM 
44907836SJohn.Forte@Sun.COM 	rdc_write_state(urdc);
44917836SJohn.Forte@Sun.COM 
44927836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
44937836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
44947836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
44957836SJohn.Forte@Sun.COM 
44967836SJohn.Forte@Sun.COM 	return (0);
44977836SJohn.Forte@Sun.COM 
44987836SJohn.Forte@Sun.COM bmpfail:
44997836SJohn.Forte@Sun.COM 	if (options & RDC_OPT_PRIMARY)
45007836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBITMAP, urdc->primary.bitmap);
45017836SJohn.Forte@Sun.COM 	else
45027836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBITMAP, urdc->secondary.bitmap);
45037836SJohn.Forte@Sun.COM 	rc = RDC_EBITMAP;
45047836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_ENABLED) {
45057836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
45067836SJohn.Forte@Sun.COM 		(void) rdc_unintercept(krdc);
45077836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
45087836SJohn.Forte@Sun.COM 	}
45097836SJohn.Forte@Sun.COM 
45107836SJohn.Forte@Sun.COM fail:
45117836SJohn.Forte@Sun.COM 	rdc_kstat_delete(index);
45127836SJohn.Forte@Sun.COM 	/* Don't unset krdc->intf here, unlike _rdc_enable */
45137836SJohn.Forte@Sun.COM 
45147836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
45157836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
45167836SJohn.Forte@Sun.COM 
45177836SJohn.Forte@Sun.COM 	rdc_dev_close(krdc);
45187836SJohn.Forte@Sun.COM 	rdc_close_direct(krdc);
45197836SJohn.Forte@Sun.COM 	rdc_destroy_svinfo(svp);
45207836SJohn.Forte@Sun.COM 
45217836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
45227836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
45237836SJohn.Forte@Sun.COM 
45247836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
45257836SJohn.Forte@Sun.COM 
45267836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
45277836SJohn.Forte@Sun.COM 
45287836SJohn.Forte@Sun.COM 	/* Configured but not enabled */
45297836SJohn.Forte@Sun.COM 	ASSERT(IS_CONFIGURED(krdc) && !IS_ENABLED(urdc));
45307836SJohn.Forte@Sun.COM 
45317836SJohn.Forte@Sun.COM 	remove_from_group(krdc);
45327836SJohn.Forte@Sun.COM 
45337836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc) || IS_MULTI(krdc))
45347836SJohn.Forte@Sun.COM 		remove_from_many(krdc);
45357836SJohn.Forte@Sun.COM 
45367836SJohn.Forte@Sun.COM 	rdc_u_init(urdc);
45377836SJohn.Forte@Sun.COM 
45387836SJohn.Forte@Sun.COM 	ASSERT(krdc->type_flag & RDC_CONFIGURED);
45397836SJohn.Forte@Sun.COM 	krdc->type_flag = 0;
45407836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
45417836SJohn.Forte@Sun.COM 
45427836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
45437836SJohn.Forte@Sun.COM 
45447836SJohn.Forte@Sun.COM 	return (rc);
45457836SJohn.Forte@Sun.COM }
45467836SJohn.Forte@Sun.COM 
45477836SJohn.Forte@Sun.COM static int
rdc_resume(rdc_config_t * uparms,spcs_s_info_t kstatus)45487836SJohn.Forte@Sun.COM rdc_resume(rdc_config_t *uparms, spcs_s_info_t kstatus)
45497836SJohn.Forte@Sun.COM {
45507836SJohn.Forte@Sun.COM 	char itmp[10];
45517836SJohn.Forte@Sun.COM 	int rc;
45527836SJohn.Forte@Sun.COM 
45537836SJohn.Forte@Sun.COM 	if (!(uparms->options & RDC_OPT_SYNC) &&
45547836SJohn.Forte@Sun.COM 	    !(uparms->options & RDC_OPT_ASYNC)) {
45557836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
45567836SJohn.Forte@Sun.COM 		    uparms->options, itmp, sizeof (itmp), 1);
45577836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEINVAL, itmp);
45587836SJohn.Forte@Sun.COM 		rc = RDC_EEINVAL;
45597836SJohn.Forte@Sun.COM 		goto done;
45607836SJohn.Forte@Sun.COM 	}
45617836SJohn.Forte@Sun.COM 
45627836SJohn.Forte@Sun.COM 	if (!(uparms->options & RDC_OPT_PRIMARY) &&
45637836SJohn.Forte@Sun.COM 	    !(uparms->options & RDC_OPT_SECONDARY)) {
45647836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
45657836SJohn.Forte@Sun.COM 		    uparms->options, itmp, sizeof (itmp), 1);
45667836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EEINVAL, itmp);
45677836SJohn.Forte@Sun.COM 		rc = RDC_EEINVAL;
45687836SJohn.Forte@Sun.COM 		goto done;
45697836SJohn.Forte@Sun.COM 	}
45707836SJohn.Forte@Sun.COM 
45717836SJohn.Forte@Sun.COM 	rc = _rdc_resume(uparms->rdc_set, uparms->options, kstatus);
45727836SJohn.Forte@Sun.COM done:
45737836SJohn.Forte@Sun.COM 	return (rc);
45747836SJohn.Forte@Sun.COM }
45757836SJohn.Forte@Sun.COM 
45767836SJohn.Forte@Sun.COM /*
45777836SJohn.Forte@Sun.COM  * if rdc_group_log is called because a volume has failed,
45787836SJohn.Forte@Sun.COM  * we must disgard the queue to preserve write ordering.
45797836SJohn.Forte@Sun.COM  * later perhaps, we can keep queuing, but we would have to
45807836SJohn.Forte@Sun.COM  * rewrite the i/o path to acommodate that. currently, if there
45817836SJohn.Forte@Sun.COM  * is a volume failure, the buffers are satisfied remotely and
45827836SJohn.Forte@Sun.COM  * there is no way to satisfy them from the current diskq config
45837836SJohn.Forte@Sun.COM  * phew, if we do that.. it will be difficult
45847836SJohn.Forte@Sun.COM  */
45857836SJohn.Forte@Sun.COM int
rdc_can_queue(rdc_k_info_t * krdc)45867836SJohn.Forte@Sun.COM rdc_can_queue(rdc_k_info_t *krdc)
45877836SJohn.Forte@Sun.COM {
45887836SJohn.Forte@Sun.COM 	rdc_k_info_t *p;
45897836SJohn.Forte@Sun.COM 	rdc_u_info_t *q;
45907836SJohn.Forte@Sun.COM 
45917836SJohn.Forte@Sun.COM 	for (p = krdc->group_next; ; p = p->group_next) {
45927836SJohn.Forte@Sun.COM 		q = &rdc_u_info[p->index];
45937836SJohn.Forte@Sun.COM 		if (IS_STATE(q, RDC_VOL_FAILED))
45947836SJohn.Forte@Sun.COM 			return (0);
45957836SJohn.Forte@Sun.COM 		if (p == krdc)
45967836SJohn.Forte@Sun.COM 			break;
45977836SJohn.Forte@Sun.COM 	}
45987836SJohn.Forte@Sun.COM 	return (1);
45997836SJohn.Forte@Sun.COM }
46007836SJohn.Forte@Sun.COM 
46017836SJohn.Forte@Sun.COM /*
46027836SJohn.Forte@Sun.COM  * wait here, until all in flight async i/o's have either
46037836SJohn.Forte@Sun.COM  * finished or failed. Avoid the race with r_net_state()
46047836SJohn.Forte@Sun.COM  * which tells remote end to log.
46057836SJohn.Forte@Sun.COM  */
46067836SJohn.Forte@Sun.COM void
rdc_inflwait(rdc_group_t * grp)46077836SJohn.Forte@Sun.COM rdc_inflwait(rdc_group_t *grp)
46087836SJohn.Forte@Sun.COM {
46097836SJohn.Forte@Sun.COM 	int bail = RDC_CLNT_TMOUT * 2; /* to include retries */
46107836SJohn.Forte@Sun.COM 	volatile int *inflitems;
46117836SJohn.Forte@Sun.COM 
46127836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(grp))
46137836SJohn.Forte@Sun.COM 		inflitems = (&(grp->diskq.inflitems));
46147836SJohn.Forte@Sun.COM 	else
46157836SJohn.Forte@Sun.COM 		inflitems = (&(grp->ra_queue.inflitems));
46167836SJohn.Forte@Sun.COM 
46177836SJohn.Forte@Sun.COM 	while (*inflitems && (--bail > 0))
46187836SJohn.Forte@Sun.COM 		delay(HZ);
46197836SJohn.Forte@Sun.COM }
46207836SJohn.Forte@Sun.COM 
46217836SJohn.Forte@Sun.COM void
rdc_group_log(rdc_k_info_t * krdc,int flag,char * why)46227836SJohn.Forte@Sun.COM rdc_group_log(rdc_k_info_t *krdc, int flag, char *why)
46237836SJohn.Forte@Sun.COM {
46247836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
46257836SJohn.Forte@Sun.COM 	rdc_k_info_t *p;
46267836SJohn.Forte@Sun.COM 	rdc_u_info_t *q;
46277836SJohn.Forte@Sun.COM 	int do_group;
46287836SJohn.Forte@Sun.COM 	int sm, um, md;
46297836SJohn.Forte@Sun.COM 	disk_queue *dq;
46307836SJohn.Forte@Sun.COM 
46317836SJohn.Forte@Sun.COM 	void (*flag_op)(rdc_u_info_t *urdc, int flag);
46327836SJohn.Forte@Sun.COM 
46337836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&krdc->group->lock));
46347836SJohn.Forte@Sun.COM 
46357836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc))
46367836SJohn.Forte@Sun.COM 		return;
46377836SJohn.Forte@Sun.COM 
46387836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
46397836SJohn.Forte@Sun.COM 
46407836SJohn.Forte@Sun.COM 	if ((flag & RDC_QUEUING) && (!IS_STATE(urdc, RDC_SYNCING)) &&
46417836SJohn.Forte@Sun.COM 	    (rdc_can_queue(krdc))) {
46427836SJohn.Forte@Sun.COM 		flag_op = rdc_set_flags; /* keep queuing, link error */
46437836SJohn.Forte@Sun.COM 		flag &= ~RDC_FLUSH;
46447836SJohn.Forte@Sun.COM 	} else {
46457836SJohn.Forte@Sun.COM 		flag_op = rdc_clr_flags; /* stop queuing, user request */
46467836SJohn.Forte@Sun.COM 	}
46477836SJohn.Forte@Sun.COM 
46487836SJohn.Forte@Sun.COM 	do_group = 1;
46497836SJohn.Forte@Sun.COM 	if (!(rdc_get_vflags(urdc) & RDC_PRIMARY))
46507836SJohn.Forte@Sun.COM 		do_group = 0;
46517836SJohn.Forte@Sun.COM 	else if ((urdc->group_name[0] == 0) ||
46527836SJohn.Forte@Sun.COM 	    (rdc_get_vflags(urdc) & RDC_LOGGING) ||
46537836SJohn.Forte@Sun.COM 	    (rdc_get_vflags(urdc) & RDC_SYNCING))
46547836SJohn.Forte@Sun.COM 		do_group = 0;
46557836SJohn.Forte@Sun.COM 	if (do_group) {
46567836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
46577836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
46587836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(q))
46597836SJohn.Forte@Sun.COM 				continue;
46607836SJohn.Forte@Sun.COM 			if ((rdc_get_vflags(q) & RDC_LOGGING) ||
46617836SJohn.Forte@Sun.COM 			    (rdc_get_vflags(q) & RDC_SYNCING)) {
46627836SJohn.Forte@Sun.COM 				do_group = 0;
46637836SJohn.Forte@Sun.COM 				break;
46647836SJohn.Forte@Sun.COM 			}
46657836SJohn.Forte@Sun.COM 		}
46667836SJohn.Forte@Sun.COM 	}
46677836SJohn.Forte@Sun.COM 	if (!do_group && (flag & RDC_FORCE_GROUP))
46687836SJohn.Forte@Sun.COM 		do_group = 1;
46697836SJohn.Forte@Sun.COM 
46707836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
46717836SJohn.Forte@Sun.COM 	dq = &krdc->group->diskq;
46727836SJohn.Forte@Sun.COM 	if (do_group) {
46737836SJohn.Forte@Sun.COM #ifdef DEBUG
4674*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!SNDR:Group point-in-time for grp: %s %s:%s",
46757836SJohn.Forte@Sun.COM 		    urdc->group_name, urdc->primary.intf, urdc->secondary.intf);
46767836SJohn.Forte@Sun.COM #endif
46777836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_diskq_group_PIT);
46787836SJohn.Forte@Sun.COM 
46797836SJohn.Forte@Sun.COM 		/* Set group logging at the same PIT under rdc_many_lock */
46807836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
46817836SJohn.Forte@Sun.COM 		rdc_set_flags_log(urdc, RDC_LOGGING, why);
46827836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(krdc->group))
46837836SJohn.Forte@Sun.COM 			flag_op(urdc, RDC_QUEUING);
46847836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
46857836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
46867836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(q))
46877836SJohn.Forte@Sun.COM 				continue;
46887836SJohn.Forte@Sun.COM 			rdc_set_flags_log(q, RDC_LOGGING,
4689*9093SRamana.Srikanth@Sun.COM 			    "consistency group member following leader");
46907836SJohn.Forte@Sun.COM 			if (RDC_IS_DISKQ(p->group))
46917836SJohn.Forte@Sun.COM 				flag_op(q, RDC_QUEUING);
46927836SJohn.Forte@Sun.COM 		}
46937836SJohn.Forte@Sun.COM 
46947836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
46957836SJohn.Forte@Sun.COM 
46967836SJohn.Forte@Sun.COM 		/*
46977836SJohn.Forte@Sun.COM 		 * This can cause the async threads to fail,
46987836SJohn.Forte@Sun.COM 		 * which in turn will call rdc_group_log()
46997836SJohn.Forte@Sun.COM 		 * again. Release the lock and re-aquire.
47007836SJohn.Forte@Sun.COM 		 */
47017836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
47027836SJohn.Forte@Sun.COM 
47037836SJohn.Forte@Sun.COM 		while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
47047836SJohn.Forte@Sun.COM 			delay(2);
47057836SJohn.Forte@Sun.COM 		if (!RDC_IS_DISKQ(krdc->group))
47067836SJohn.Forte@Sun.COM 			RDC_ZERO_BITREF(krdc);
47077836SJohn.Forte@Sun.COM 
47087836SJohn.Forte@Sun.COM 		rdc_inflwait(krdc->group);
47097836SJohn.Forte@Sun.COM 
47107836SJohn.Forte@Sun.COM 		/*
47117836SJohn.Forte@Sun.COM 		 * a little lazy, but neat. recall dump_alloc_bufs to
47127836SJohn.Forte@Sun.COM 		 * ensure that the queue pointers & seq are reset properly
47137836SJohn.Forte@Sun.COM 		 * after we have waited for inflight stuff
47147836SJohn.Forte@Sun.COM 		 */
47157836SJohn.Forte@Sun.COM 		while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
47167836SJohn.Forte@Sun.COM 			delay(2);
47177836SJohn.Forte@Sun.COM 
47187836SJohn.Forte@Sun.COM 		rdc_group_enter(krdc);
47197836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(krdc->group) && (!(flag & RDC_QUEUING))) {
47207836SJohn.Forte@Sun.COM 			/* fail or user request */
47217836SJohn.Forte@Sun.COM 			RDC_ZERO_BITREF(krdc);
47227836SJohn.Forte@Sun.COM 			mutex_enter(&krdc->group->diskq.disk_qlock);
47237836SJohn.Forte@Sun.COM 			rdc_init_diskq_header(krdc->group,
47247836SJohn.Forte@Sun.COM 			    &krdc->group->diskq.disk_hdr);
47257836SJohn.Forte@Sun.COM 			SET_QNXTIO(dq, QHEAD(dq));
47267836SJohn.Forte@Sun.COM 			mutex_exit(&krdc->group->diskq.disk_qlock);
47277836SJohn.Forte@Sun.COM 		}
47287836SJohn.Forte@Sun.COM 
47297836SJohn.Forte@Sun.COM 		if (flag & RDC_ALLREMOTE) {
47307836SJohn.Forte@Sun.COM 			/* Tell other node to start logging */
47317836SJohn.Forte@Sun.COM 			if (krdc->lsrv && krdc->intf && !krdc->intf->if_down)
47327836SJohn.Forte@Sun.COM 				(void) rdc_net_state(krdc->index,
47337836SJohn.Forte@Sun.COM 				    CCIO_ENABLELOG);
47347836SJohn.Forte@Sun.COM 		}
47357836SJohn.Forte@Sun.COM 
47367836SJohn.Forte@Sun.COM 		if (flag & (RDC_ALLREMOTE | RDC_OTHERREMOTE)) {
47377836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
47387836SJohn.Forte@Sun.COM 			for (p = krdc->group_next; p != krdc;
47397836SJohn.Forte@Sun.COM 			    p = p->group_next) {
47407836SJohn.Forte@Sun.COM 				if (p->lsrv && krdc->intf &&
47417836SJohn.Forte@Sun.COM 				    !krdc->intf->if_down) {
47427836SJohn.Forte@Sun.COM 					(void) rdc_net_state(p->index,
4743*9093SRamana.Srikanth@Sun.COM 					    CCIO_ENABLELOG);
47447836SJohn.Forte@Sun.COM 				}
47457836SJohn.Forte@Sun.COM 			}
47467836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
47477836SJohn.Forte@Sun.COM 		}
47487836SJohn.Forte@Sun.COM 
47497836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
47507836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
47517836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
47527836SJohn.Forte@Sun.COM 			if (!IS_ENABLED(q))
47537836SJohn.Forte@Sun.COM 				continue;
47547836SJohn.Forte@Sun.COM 			rdc_write_state(q);
47557836SJohn.Forte@Sun.COM 		}
47567836SJohn.Forte@Sun.COM 	} else {
47577836SJohn.Forte@Sun.COM 		/* No point in time is possible, just deal with single set */
47587836SJohn.Forte@Sun.COM 
47597836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
47607836SJohn.Forte@Sun.COM 			halt_sync(krdc);
47617836SJohn.Forte@Sun.COM 		} else {
47627836SJohn.Forte@Sun.COM 			if (rdc_net_getstate(krdc, &sm, &um, &md, TRUE) < 0) {
47637836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_SYNCING);
47647836SJohn.Forte@Sun.COM 				rdc_set_flags_log(urdc, RDC_LOGGING,
47657836SJohn.Forte@Sun.COM 				    "failed to read remote state");
47667836SJohn.Forte@Sun.COM 
47677836SJohn.Forte@Sun.COM 				rdc_write_state(urdc);
47687836SJohn.Forte@Sun.COM 				while (rdc_dump_alloc_bufs_cd(krdc->index)
47697836SJohn.Forte@Sun.COM 				    == EAGAIN)
47707836SJohn.Forte@Sun.COM 					delay(2);
47717836SJohn.Forte@Sun.COM 				if ((RDC_IS_DISKQ(krdc->group)) &&
4772*9093SRamana.Srikanth@Sun.COM 				    (!(flag & RDC_QUEUING))) { /* fail! */
47737836SJohn.Forte@Sun.COM 					mutex_enter(QLOCK(dq));
47747836SJohn.Forte@Sun.COM 					rdc_init_diskq_header(krdc->group,
47757836SJohn.Forte@Sun.COM 					    &krdc->group->diskq.disk_hdr);
47767836SJohn.Forte@Sun.COM 					SET_QNXTIO(dq, QHEAD(dq));
47777836SJohn.Forte@Sun.COM 					mutex_exit(QLOCK(dq));
47787836SJohn.Forte@Sun.COM 				}
47797836SJohn.Forte@Sun.COM 
47807836SJohn.Forte@Sun.COM 				return;
47817836SJohn.Forte@Sun.COM 			}
47827836SJohn.Forte@Sun.COM 		}
47837836SJohn.Forte@Sun.COM 
47847836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_SYNCING)
47857836SJohn.Forte@Sun.COM 			return;
47867836SJohn.Forte@Sun.COM 
47877836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(krdc->group))
47887836SJohn.Forte@Sun.COM 			flag_op(urdc, RDC_QUEUING);
47897836SJohn.Forte@Sun.COM 
47907836SJohn.Forte@Sun.COM 		if ((RDC_IS_DISKQ(krdc->group)) &&
4791*9093SRamana.Srikanth@Sun.COM 		    (!(flag & RDC_QUEUING))) { /* fail! */
47927836SJohn.Forte@Sun.COM 			RDC_ZERO_BITREF(krdc);
47937836SJohn.Forte@Sun.COM 			mutex_enter(QLOCK(dq));
47947836SJohn.Forte@Sun.COM 			rdc_init_diskq_header(krdc->group,
47957836SJohn.Forte@Sun.COM 			    &krdc->group->diskq.disk_hdr);
47967836SJohn.Forte@Sun.COM 			SET_QNXTIO(dq, QHEAD(dq));
47977836SJohn.Forte@Sun.COM 			mutex_exit(QLOCK(dq));
47987836SJohn.Forte@Sun.COM 		}
47997836SJohn.Forte@Sun.COM 
48007836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_LOGGING)) {
48017836SJohn.Forte@Sun.COM 			rdc_set_flags_log(urdc, RDC_LOGGING, why);
48027836SJohn.Forte@Sun.COM 
48037836SJohn.Forte@Sun.COM 			rdc_write_state(urdc);
48047836SJohn.Forte@Sun.COM 
48057836SJohn.Forte@Sun.COM 			while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
48067836SJohn.Forte@Sun.COM 				delay(2);
48077836SJohn.Forte@Sun.COM 			if (!RDC_IS_DISKQ(krdc->group))
48087836SJohn.Forte@Sun.COM 				RDC_ZERO_BITREF(krdc);
48097836SJohn.Forte@Sun.COM 
48107836SJohn.Forte@Sun.COM 			rdc_inflwait(krdc->group);
48117836SJohn.Forte@Sun.COM 			/*
48127836SJohn.Forte@Sun.COM 			 * a little lazy, but neat. recall dump_alloc_bufs to
48137836SJohn.Forte@Sun.COM 			 * ensure that the queue pointers & seq are reset
48147836SJohn.Forte@Sun.COM 			 * properly after we have waited for inflight stuff
48157836SJohn.Forte@Sun.COM 			 */
48167836SJohn.Forte@Sun.COM 			while (rdc_dump_alloc_bufs_cd(krdc->index) == EAGAIN)
48177836SJohn.Forte@Sun.COM 				delay(2);
48187836SJohn.Forte@Sun.COM 
48197836SJohn.Forte@Sun.COM 			if (flag & RDC_ALLREMOTE) {
48207836SJohn.Forte@Sun.COM 				/* Tell other node to start logging */
48217836SJohn.Forte@Sun.COM 				if (krdc->lsrv && krdc->intf &&
48227836SJohn.Forte@Sun.COM 				    !krdc->intf->if_down) {
48237836SJohn.Forte@Sun.COM 					(void) rdc_net_state(krdc->index,
48247836SJohn.Forte@Sun.COM 					    CCIO_ENABLELOG);
48257836SJohn.Forte@Sun.COM 				}
48267836SJohn.Forte@Sun.COM 			}
48277836SJohn.Forte@Sun.COM 		}
48287836SJohn.Forte@Sun.COM 	}
48297836SJohn.Forte@Sun.COM 	/*
48307836SJohn.Forte@Sun.COM 	 * just in case any threads were in flight during log cleanup
48317836SJohn.Forte@Sun.COM 	 */
48327836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
48337836SJohn.Forte@Sun.COM 		mutex_enter(QLOCK(dq));
48347836SJohn.Forte@Sun.COM 		cv_broadcast(&dq->qfullcv);
48357836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(dq));
48367836SJohn.Forte@Sun.COM 	}
48377836SJohn.Forte@Sun.COM }
48387836SJohn.Forte@Sun.COM 
48397836SJohn.Forte@Sun.COM static int
_rdc_log(rdc_k_info_t * krdc,rdc_set_t * rdc_set,spcs_s_info_t kstatus)48407836SJohn.Forte@Sun.COM _rdc_log(rdc_k_info_t *krdc, rdc_set_t *rdc_set, spcs_s_info_t kstatus)
48417836SJohn.Forte@Sun.COM {
48427836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
48437836SJohn.Forte@Sun.COM 	rdc_srv_t *svp;
48447836SJohn.Forte@Sun.COM 
48457836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
48467836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, rdc_set)) {
48477836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
48487836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
48497836SJohn.Forte@Sun.COM 		    rdc_set->secondary.file);
48507836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
48517836SJohn.Forte@Sun.COM 	}
48527836SJohn.Forte@Sun.COM 
48537836SJohn.Forte@Sun.COM 	svp = krdc->lsrv;
48547836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
48557836SJohn.Forte@Sun.COM 		krdc->intf = rdc_add_to_if(svp, &(urdc->primary.addr),
48567836SJohn.Forte@Sun.COM 		    &(urdc->secondary.addr), 1);
48577836SJohn.Forte@Sun.COM 	else
48587836SJohn.Forte@Sun.COM 		krdc->intf = rdc_add_to_if(svp, &(urdc->secondary.addr),
48597836SJohn.Forte@Sun.COM 		    &(urdc->primary.addr), 0);
48607836SJohn.Forte@Sun.COM 
48617836SJohn.Forte@Sun.COM 	if (!krdc->intf) {
48627836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
48637836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EADDTOIF, urdc->primary.intf,
48647836SJohn.Forte@Sun.COM 		    urdc->secondary.intf);
48657836SJohn.Forte@Sun.COM 		return (RDC_EADDTOIF);
48667836SJohn.Forte@Sun.COM 	}
48677836SJohn.Forte@Sun.COM 
48687836SJohn.Forte@Sun.COM 	rdc_group_log(krdc, RDC_FLUSH | RDC_ALLREMOTE, NULL);
48697836SJohn.Forte@Sun.COM 
48707836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_SYNCING) {
48717836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
48727836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ESYNCING, urdc->primary.file);
48737836SJohn.Forte@Sun.COM 		return (RDC_ESYNCING);
48747836SJohn.Forte@Sun.COM 	}
48757836SJohn.Forte@Sun.COM 
48767836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
48777836SJohn.Forte@Sun.COM 
48787836SJohn.Forte@Sun.COM 	return (0);
48797836SJohn.Forte@Sun.COM }
48807836SJohn.Forte@Sun.COM 
48817836SJohn.Forte@Sun.COM static int
rdc_log(rdc_config_t * uparms,spcs_s_info_t kstatus)48827836SJohn.Forte@Sun.COM rdc_log(rdc_config_t *uparms, spcs_s_info_t kstatus)
48837836SJohn.Forte@Sun.COM {
48847836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
48857836SJohn.Forte@Sun.COM 	int rc = 0;
48867836SJohn.Forte@Sun.COM 	int index;
48877836SJohn.Forte@Sun.COM 
48887836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
48897836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
48907836SJohn.Forte@Sun.COM 	if (index >= 0)
48917836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
48927836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
48937836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
48947836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
48957836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
48967836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
48977836SJohn.Forte@Sun.COM 	}
48987836SJohn.Forte@Sun.COM 
48997836SJohn.Forte@Sun.COM 	set_busy(krdc);
49007836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
49017836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
49027836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
49037836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49047836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
49057836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
49067836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
49077836SJohn.Forte@Sun.COM 	}
49087836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
49097836SJohn.Forte@Sun.COM 
49107836SJohn.Forte@Sun.COM 	rc = _rdc_log(krdc, uparms->rdc_set, kstatus);
49117836SJohn.Forte@Sun.COM 
49127836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
49137836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
49147836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
49157836SJohn.Forte@Sun.COM 
49167836SJohn.Forte@Sun.COM 	return (rc);
49177836SJohn.Forte@Sun.COM }
49187836SJohn.Forte@Sun.COM 
49197836SJohn.Forte@Sun.COM 
49207836SJohn.Forte@Sun.COM static int
rdc_wait(rdc_config_t * uparms,spcs_s_info_t kstatus)49217836SJohn.Forte@Sun.COM rdc_wait(rdc_config_t *uparms, spcs_s_info_t kstatus)
49227836SJohn.Forte@Sun.COM {
49237836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
49247836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
49257836SJohn.Forte@Sun.COM 	int index;
49267836SJohn.Forte@Sun.COM 	int need_check = 0;
49277836SJohn.Forte@Sun.COM 
49287836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
49297836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
49307836SJohn.Forte@Sun.COM 	if (index >= 0)
49317836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
49327836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
49337836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49347836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
49357836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
49367836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
49377836SJohn.Forte@Sun.COM 	}
49387836SJohn.Forte@Sun.COM 
49397836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
49407836SJohn.Forte@Sun.COM 	if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
49417836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49427836SJohn.Forte@Sun.COM 		return (0);
49437836SJohn.Forte@Sun.COM 	}
49447836SJohn.Forte@Sun.COM 
49457836SJohn.Forte@Sun.COM 	set_busy(krdc);
49467836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
49477836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
49487836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
49497836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49507836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
49517836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
49527836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
49537836SJohn.Forte@Sun.COM 	}
49547836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
49557836SJohn.Forte@Sun.COM 
49567836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
49577836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
49587836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
49597836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
49607836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
49617836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49627836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
49637836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
49647836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
49657836SJohn.Forte@Sun.COM 	}
49667836SJohn.Forte@Sun.COM 
49677836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & (RDC_SYNCING | RDC_PRIMARY)) !=
49687836SJohn.Forte@Sun.COM 	    (RDC_SYNCING | RDC_PRIMARY)) {
49697836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
49707836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
49717836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
49727836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
49737836SJohn.Forte@Sun.COM 		return (0);
49747836SJohn.Forte@Sun.COM 	}
49757836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_SYNCING) {
49767836SJohn.Forte@Sun.COM 		need_check = 1;
49777836SJohn.Forte@Sun.COM 	}
49787836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
49797836SJohn.Forte@Sun.COM 
49807836SJohn.Forte@Sun.COM 	mutex_enter(&net_blk_lock);
49817836SJohn.Forte@Sun.COM 
49827836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
49837836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
49847836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
49857836SJohn.Forte@Sun.COM 
49867836SJohn.Forte@Sun.COM 	(void) cv_wait_sig(&krdc->synccv, &net_blk_lock);
49877836SJohn.Forte@Sun.COM 
49887836SJohn.Forte@Sun.COM 	mutex_exit(&net_blk_lock);
49897836SJohn.Forte@Sun.COM 	if (need_check) {
49907836SJohn.Forte@Sun.COM 		if (krdc->sync_done == RDC_COMPLETED) {
49917836SJohn.Forte@Sun.COM 			return (0);
49927836SJohn.Forte@Sun.COM 		} else if (krdc->sync_done == RDC_FAILED) {
49937836SJohn.Forte@Sun.COM 			return (EIO);
49947836SJohn.Forte@Sun.COM 		}
49957836SJohn.Forte@Sun.COM 	}
49967836SJohn.Forte@Sun.COM 	return (0);
49977836SJohn.Forte@Sun.COM }
49987836SJohn.Forte@Sun.COM 
49997836SJohn.Forte@Sun.COM 
50007836SJohn.Forte@Sun.COM static int
rdc_health(rdc_config_t * uparms,spcs_s_info_t kstatus,int * rvp)50017836SJohn.Forte@Sun.COM rdc_health(rdc_config_t *uparms, spcs_s_info_t kstatus, int *rvp)
50027836SJohn.Forte@Sun.COM {
50037836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
50047836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
50057836SJohn.Forte@Sun.COM 	int rc = 0;
50067836SJohn.Forte@Sun.COM 	int index;
50077836SJohn.Forte@Sun.COM 
50087836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
50097836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
50107836SJohn.Forte@Sun.COM 	if (index >= 0)
50117836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
50127836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
50137836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
50147836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50157836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50167836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
50177836SJohn.Forte@Sun.COM 	}
50187836SJohn.Forte@Sun.COM 
50197836SJohn.Forte@Sun.COM 	set_busy(krdc);
50207836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
50217836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
50227836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
50237836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
50247836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50257836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50267836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
50277836SJohn.Forte@Sun.COM 	}
50287836SJohn.Forte@Sun.COM 
50297836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
50307836SJohn.Forte@Sun.COM 
50317836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
50327836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
50337836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
50347836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50357836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50367836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
50377836SJohn.Forte@Sun.COM 		goto done;
50387836SJohn.Forte@Sun.COM 	}
50397836SJohn.Forte@Sun.COM 
50407836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
50417836SJohn.Forte@Sun.COM 	if (rdc_isactive_if(&(urdc->primary.addr), &(urdc->secondary.addr)))
50427836SJohn.Forte@Sun.COM 		*rvp = RDC_ACTIVE;
50437836SJohn.Forte@Sun.COM 	else
50447836SJohn.Forte@Sun.COM 		*rvp = RDC_INACTIVE;
50457836SJohn.Forte@Sun.COM 
50467836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
50477836SJohn.Forte@Sun.COM 
50487836SJohn.Forte@Sun.COM done:
50497836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
50507836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
50517836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
50527836SJohn.Forte@Sun.COM 
50537836SJohn.Forte@Sun.COM 	return (rc);
50547836SJohn.Forte@Sun.COM }
50557836SJohn.Forte@Sun.COM 
50567836SJohn.Forte@Sun.COM 
50577836SJohn.Forte@Sun.COM static int
rdc_reconfig(rdc_config_t * uparms,spcs_s_info_t kstatus)50587836SJohn.Forte@Sun.COM rdc_reconfig(rdc_config_t *uparms, spcs_s_info_t kstatus)
50597836SJohn.Forte@Sun.COM {
50607836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
50617836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
50627836SJohn.Forte@Sun.COM 	int rc = -2;
50637836SJohn.Forte@Sun.COM 	int index;
50647836SJohn.Forte@Sun.COM 
50657836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
50667836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
50677836SJohn.Forte@Sun.COM 	if (index >= 0)
50687836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
50697836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
50707836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
50717836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50727836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50737836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
50747836SJohn.Forte@Sun.COM 	}
50757836SJohn.Forte@Sun.COM 
50767836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
50777836SJohn.Forte@Sun.COM 	set_busy(krdc);
50787836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
50797836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
50807836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
50817836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
50827836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50837836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50847836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
50857836SJohn.Forte@Sun.COM 	}
50867836SJohn.Forte@Sun.COM 
50877836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
50887836SJohn.Forte@Sun.COM 
50897836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
50907836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
50917836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
50927836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
50937836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
50947836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
50957836SJohn.Forte@Sun.COM 		goto done;
50967836SJohn.Forte@Sun.COM 	}
50977836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_BMP_FAILED) && (krdc->bitmapfd))
50987836SJohn.Forte@Sun.COM 		(void) rdc_reset_bitmap(krdc);
50997836SJohn.Forte@Sun.COM 
51007836SJohn.Forte@Sun.COM 	/* Move to a new bitmap if necessary */
51017836SJohn.Forte@Sun.COM 	if (strncmp(urdc->primary.bitmap, uparms->rdc_set->primary.bitmap,
51027836SJohn.Forte@Sun.COM 	    NSC_MAXPATH) != 0) {
51037836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
51047836SJohn.Forte@Sun.COM 			rc = rdc_move_bitmap(krdc,
51057836SJohn.Forte@Sun.COM 			    uparms->rdc_set->primary.bitmap);
51067836SJohn.Forte@Sun.COM 		} else {
51077836SJohn.Forte@Sun.COM 			(void) strncpy(urdc->primary.bitmap,
51087836SJohn.Forte@Sun.COM 			    uparms->rdc_set->primary.bitmap, NSC_MAXPATH);
51097836SJohn.Forte@Sun.COM 			/* simulate a succesful rdc_move_bitmap */
51107836SJohn.Forte@Sun.COM 			rc = 0;
51117836SJohn.Forte@Sun.COM 		}
51127836SJohn.Forte@Sun.COM 	}
51137836SJohn.Forte@Sun.COM 	if (strncmp(urdc->secondary.bitmap, uparms->rdc_set->secondary.bitmap,
51147836SJohn.Forte@Sun.COM 	    NSC_MAXPATH) != 0) {
51157836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
51167836SJohn.Forte@Sun.COM 			(void) strncpy(urdc->secondary.bitmap,
51177836SJohn.Forte@Sun.COM 			    uparms->rdc_set->secondary.bitmap, NSC_MAXPATH);
51187836SJohn.Forte@Sun.COM 			/* simulate a succesful rdc_move_bitmap */
51197836SJohn.Forte@Sun.COM 			rc = 0;
51207836SJohn.Forte@Sun.COM 		} else {
51217836SJohn.Forte@Sun.COM 			rc = rdc_move_bitmap(krdc,
51227836SJohn.Forte@Sun.COM 			    uparms->rdc_set->secondary.bitmap);
51237836SJohn.Forte@Sun.COM 		}
51247836SJohn.Forte@Sun.COM 	}
51257836SJohn.Forte@Sun.COM 	if (rc == -1) {
51267836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
51277836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EBMPRECONFIG,
51287836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.intf,
51297836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
51307836SJohn.Forte@Sun.COM 		rc = RDC_EBMPRECONFIG;
51317836SJohn.Forte@Sun.COM 		goto done;
51327836SJohn.Forte@Sun.COM 	}
51337836SJohn.Forte@Sun.COM 
51347836SJohn.Forte@Sun.COM 	/*
51357836SJohn.Forte@Sun.COM 	 * At this point we fail any other type of reconfig
51367836SJohn.Forte@Sun.COM 	 * if not in logging mode and we did not do a bitmap reconfig
51377836SJohn.Forte@Sun.COM 	 */
51387836SJohn.Forte@Sun.COM 
51397836SJohn.Forte@Sun.COM 	if (!(rdc_get_vflags(urdc) & RDC_LOGGING) && rc == -2) {
51407836SJohn.Forte@Sun.COM 		/* no other changes possible unless logging */
51417836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
51427836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_ENOTLOGGING,
51437836SJohn.Forte@Sun.COM 		    uparms->rdc_set->primary.intf,
51447836SJohn.Forte@Sun.COM 		    uparms->rdc_set->primary.file,
51457836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.intf,
51467836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
51477836SJohn.Forte@Sun.COM 		rc = RDC_ENOTLOGGING;
51487836SJohn.Forte@Sun.COM 		goto done;
51497836SJohn.Forte@Sun.COM 	}
51507836SJohn.Forte@Sun.COM 	rc = 0;
51517836SJohn.Forte@Sun.COM 	/* Change direct file if necessary */
51527836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
51537836SJohn.Forte@Sun.COM 	    strncmp(urdc->direct_file, uparms->rdc_set->direct_file,
51547836SJohn.Forte@Sun.COM 	    NSC_MAXPATH)) {
51557836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_LOGGING)) {
51567836SJohn.Forte@Sun.COM 			rdc_group_exit(krdc);
51577836SJohn.Forte@Sun.COM 			goto notlogging;
51587836SJohn.Forte@Sun.COM 		}
51597836SJohn.Forte@Sun.COM 		rdc_close_direct(krdc);
51607836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->direct_file, uparms->rdc_set->direct_file,
51617836SJohn.Forte@Sun.COM 		    NSC_MAXPATH);
51627836SJohn.Forte@Sun.COM 
51637836SJohn.Forte@Sun.COM 		if (urdc->direct_file[0]) {
51647836SJohn.Forte@Sun.COM 			if (rdc_open_direct(krdc) == NULL)
51657836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_FCAL_FAILED);
51667836SJohn.Forte@Sun.COM 			else
51677836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_FCAL_FAILED);
51687836SJohn.Forte@Sun.COM 		}
51697836SJohn.Forte@Sun.COM 	}
51707836SJohn.Forte@Sun.COM 
51717836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
51727836SJohn.Forte@Sun.COM 
51737836SJohn.Forte@Sun.COM 	/* Change group if necessary */
51747836SJohn.Forte@Sun.COM 	if (strncmp(urdc->group_name, uparms->rdc_set->group_name,
51757836SJohn.Forte@Sun.COM 	    NSC_MAXPATH) != 0) {
51767836SJohn.Forte@Sun.COM 		char orig_group[NSC_MAXPATH];
51777836SJohn.Forte@Sun.COM 		if (!(rdc_get_vflags(urdc) & RDC_LOGGING))
51787836SJohn.Forte@Sun.COM 			goto notlogging;
51797836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
51807836SJohn.Forte@Sun.COM 
51817836SJohn.Forte@Sun.COM 		(void) strncpy(orig_group, urdc->group_name, NSC_MAXPATH);
51827836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->group_name, uparms->rdc_set->group_name,
51837836SJohn.Forte@Sun.COM 		    NSC_MAXPATH);
51847836SJohn.Forte@Sun.COM 
51857836SJohn.Forte@Sun.COM 		rc = change_group(krdc, uparms->options);
51867836SJohn.Forte@Sun.COM 		if (rc == RDC_EQNOADD) {
51877836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
51887836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EQNOADD,
51897836SJohn.Forte@Sun.COM 			    uparms->rdc_set->disk_queue);
51907836SJohn.Forte@Sun.COM 			goto done;
51917836SJohn.Forte@Sun.COM 		} else if (rc < 0) {
51927836SJohn.Forte@Sun.COM 			(void) strncpy(urdc->group_name, orig_group,
51937836SJohn.Forte@Sun.COM 			    NSC_MAXPATH);
51947836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
51957836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EGROUP,
5196*9093SRamana.Srikanth@Sun.COM 			    urdc->primary.intf, urdc->primary.file,
5197*9093SRamana.Srikanth@Sun.COM 			    urdc->secondary.intf, urdc->secondary.file,
5198*9093SRamana.Srikanth@Sun.COM 			    uparms->rdc_set->group_name);
51997836SJohn.Forte@Sun.COM 			rc = RDC_EGROUP;
52007836SJohn.Forte@Sun.COM 			goto done;
52017836SJohn.Forte@Sun.COM 		}
52027836SJohn.Forte@Sun.COM 
52037836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
52047836SJohn.Forte@Sun.COM 
52057836SJohn.Forte@Sun.COM 		if (rc >= 0) {
52067836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(urdc) & RDC_LOGGING))
52077836SJohn.Forte@Sun.COM 				goto notlogging;
52087836SJohn.Forte@Sun.COM 			if (uparms->options & RDC_OPT_ASYNC) {
52097836SJohn.Forte@Sun.COM 				mutex_enter(&rdc_conf_lock);
52107836SJohn.Forte@Sun.COM 				krdc->type_flag |= RDC_ASYNCMODE;
52117836SJohn.Forte@Sun.COM 				mutex_exit(&rdc_conf_lock);
52127836SJohn.Forte@Sun.COM 				if (uparms->options & RDC_OPT_PRIMARY)
52137836SJohn.Forte@Sun.COM 					krdc->bitmap_ref =
52147836SJohn.Forte@Sun.COM 					    (uchar_t *)kmem_zalloc(
52157836SJohn.Forte@Sun.COM 					    (krdc->bitmap_size * BITS_IN_BYTE *
52167836SJohn.Forte@Sun.COM 					    BMAP_REF_PREF_SIZE), KM_SLEEP);
52177836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
52187836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_ASYNC);
52197836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
52207836SJohn.Forte@Sun.COM 			} else {
52217836SJohn.Forte@Sun.COM 				mutex_enter(&rdc_conf_lock);
52227836SJohn.Forte@Sun.COM 				krdc->type_flag &= ~RDC_ASYNCMODE;
52237836SJohn.Forte@Sun.COM 				mutex_exit(&rdc_conf_lock);
52247836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
52257836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_ASYNC);
52267836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
52277836SJohn.Forte@Sun.COM 				if (krdc->bitmap_ref) {
52287836SJohn.Forte@Sun.COM 					kmem_free(krdc->bitmap_ref,
52297836SJohn.Forte@Sun.COM 					    (krdc->bitmap_size * BITS_IN_BYTE *
52307836SJohn.Forte@Sun.COM 					    BMAP_REF_PREF_SIZE));
52317836SJohn.Forte@Sun.COM 					krdc->bitmap_ref = NULL;
52327836SJohn.Forte@Sun.COM 				}
52337836SJohn.Forte@Sun.COM 			}
52347836SJohn.Forte@Sun.COM 		}
52357836SJohn.Forte@Sun.COM 	} else {
52367836SJohn.Forte@Sun.COM 		if ((((uparms->options & RDC_OPT_ASYNC) == 0) &&
52377836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_ASYNCMODE) != 0)) ||
52387836SJohn.Forte@Sun.COM 		    (((uparms->options & RDC_OPT_ASYNC) != 0) &&
52397836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_ASYNCMODE) == 0))) {
52407836SJohn.Forte@Sun.COM 			if (!(rdc_get_vflags(urdc) & RDC_LOGGING))
52417836SJohn.Forte@Sun.COM 				goto notlogging;
52427836SJohn.Forte@Sun.COM 
52437836SJohn.Forte@Sun.COM 			if (krdc->group->count > 1) {
52447836SJohn.Forte@Sun.COM 				spcs_s_add(kstatus, RDC_EGROUPMODE);
52457836SJohn.Forte@Sun.COM 				rc = RDC_EGROUPMODE;
52467836SJohn.Forte@Sun.COM 				goto done;
52477836SJohn.Forte@Sun.COM 			}
52487836SJohn.Forte@Sun.COM 		}
52497836SJohn.Forte@Sun.COM 
52507836SJohn.Forte@Sun.COM 		/* Switch sync/async if necessary */
52517836SJohn.Forte@Sun.COM 		if (krdc->group->count == 1) {
52527836SJohn.Forte@Sun.COM 			/* Only member of group. Can change sync/async */
52537836SJohn.Forte@Sun.COM 			if (((uparms->options & RDC_OPT_ASYNC) == 0) &&
52547836SJohn.Forte@Sun.COM 			    ((krdc->type_flag & RDC_ASYNCMODE) != 0)) {
52557836SJohn.Forte@Sun.COM 				if (!(rdc_get_vflags(urdc) & RDC_LOGGING))
52567836SJohn.Forte@Sun.COM 					goto notlogging;
52577836SJohn.Forte@Sun.COM 				/* switch to sync */
52587836SJohn.Forte@Sun.COM 				mutex_enter(&rdc_conf_lock);
52597836SJohn.Forte@Sun.COM 				krdc->type_flag &= ~RDC_ASYNCMODE;
52607836SJohn.Forte@Sun.COM 				if (RDC_IS_DISKQ(krdc->group)) {
52617836SJohn.Forte@Sun.COM 					krdc->group->flags &= ~RDC_DISKQUE;
52627836SJohn.Forte@Sun.COM 					krdc->group->flags |= RDC_MEMQUE;
52637836SJohn.Forte@Sun.COM 					rdc_unintercept_diskq(krdc->group);
52647836SJohn.Forte@Sun.COM 					mutex_enter(&krdc->group->diskqmutex);
52657836SJohn.Forte@Sun.COM 					rdc_close_diskq(krdc->group);
52667836SJohn.Forte@Sun.COM 					mutex_exit(&krdc->group->diskqmutex);
52677836SJohn.Forte@Sun.COM 					bzero(&urdc->disk_queue,
52687836SJohn.Forte@Sun.COM 					    sizeof (urdc->disk_queue));
52697836SJohn.Forte@Sun.COM 				}
52707836SJohn.Forte@Sun.COM 				mutex_exit(&rdc_conf_lock);
52717836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
52727836SJohn.Forte@Sun.COM 				rdc_clr_flags(urdc, RDC_ASYNC);
52737836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
52747836SJohn.Forte@Sun.COM 				if (krdc->bitmap_ref) {
52757836SJohn.Forte@Sun.COM 					kmem_free(krdc->bitmap_ref,
52767836SJohn.Forte@Sun.COM 					    (krdc->bitmap_size * BITS_IN_BYTE *
52777836SJohn.Forte@Sun.COM 					    BMAP_REF_PREF_SIZE));
52787836SJohn.Forte@Sun.COM 					krdc->bitmap_ref = NULL;
52797836SJohn.Forte@Sun.COM 				}
52807836SJohn.Forte@Sun.COM 			} else if (((uparms->options & RDC_OPT_ASYNC) != 0) &&
52817836SJohn.Forte@Sun.COM 			    ((krdc->type_flag & RDC_ASYNCMODE) == 0)) {
52827836SJohn.Forte@Sun.COM 				if (!(rdc_get_vflags(urdc) & RDC_LOGGING))
52837836SJohn.Forte@Sun.COM 					goto notlogging;
52847836SJohn.Forte@Sun.COM 				/* switch to async */
52857836SJohn.Forte@Sun.COM 				mutex_enter(&rdc_conf_lock);
52867836SJohn.Forte@Sun.COM 				krdc->type_flag |= RDC_ASYNCMODE;
52877836SJohn.Forte@Sun.COM 				mutex_exit(&rdc_conf_lock);
52887836SJohn.Forte@Sun.COM 				if (uparms->options & RDC_OPT_PRIMARY)
52897836SJohn.Forte@Sun.COM 					krdc->bitmap_ref =
52907836SJohn.Forte@Sun.COM 					    (uchar_t *)kmem_zalloc(
52917836SJohn.Forte@Sun.COM 					    (krdc->bitmap_size * BITS_IN_BYTE *
52927836SJohn.Forte@Sun.COM 					    BMAP_REF_PREF_SIZE), KM_SLEEP);
52937836SJohn.Forte@Sun.COM 				rdc_group_enter(krdc);
52947836SJohn.Forte@Sun.COM 				rdc_set_flags(urdc, RDC_ASYNC);
52957836SJohn.Forte@Sun.COM 				rdc_group_exit(krdc);
52967836SJohn.Forte@Sun.COM 			}
52977836SJohn.Forte@Sun.COM 		}
52987836SJohn.Forte@Sun.COM 	}
52997836SJohn.Forte@Sun.COM 	/* Reverse concept of primary and secondary */
53007836SJohn.Forte@Sun.COM 	if ((uparms->options & RDC_OPT_REVERSE_ROLE) != 0) {
53017836SJohn.Forte@Sun.COM 		rdc_set_t rdc_set;
53027836SJohn.Forte@Sun.COM 		struct netbuf paddr, saddr;
53037836SJohn.Forte@Sun.COM 
53047836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
53057836SJohn.Forte@Sun.COM 
53067836SJohn.Forte@Sun.COM 		/*
53077836SJohn.Forte@Sun.COM 		 * Disallow role reversal for advanced configurations
53087836SJohn.Forte@Sun.COM 		 */
53097836SJohn.Forte@Sun.COM 
53107836SJohn.Forte@Sun.COM 		if (IS_MANY(krdc) || IS_MULTI(krdc)) {
53117836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
5312*9093SRamana.Srikanth@Sun.COM 			spcs_s_add(kstatus, RDC_EMASTER, urdc->primary.intf,
5313*9093SRamana.Srikanth@Sun.COM 			    urdc->primary.file, urdc->secondary.intf,
5314*9093SRamana.Srikanth@Sun.COM 			    urdc->secondary.file);
53157836SJohn.Forte@Sun.COM 			return (RDC_EMASTER);
53167836SJohn.Forte@Sun.COM 		}
53177836SJohn.Forte@Sun.COM 		bzero((void *) &rdc_set, sizeof (rdc_set_t));
53187836SJohn.Forte@Sun.COM 		dup_rdc_netbuf(&urdc->primary.addr, &saddr);
53197836SJohn.Forte@Sun.COM 		dup_rdc_netbuf(&urdc->secondary.addr, &paddr);
53207836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&urdc->primary.addr);
53217836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&urdc->secondary.addr);
53227836SJohn.Forte@Sun.COM 		dup_rdc_netbuf(&saddr, &urdc->secondary.addr);
53237836SJohn.Forte@Sun.COM 		dup_rdc_netbuf(&paddr, &urdc->primary.addr);
53247836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&paddr);
53257836SJohn.Forte@Sun.COM 		free_rdc_netbuf(&saddr);
53267836SJohn.Forte@Sun.COM 		/* copy primary parts of urdc to rdc_set field by field */
53277836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.intf, urdc->primary.intf,
5328*9093SRamana.Srikanth@Sun.COM 		    MAX_RDC_HOST_SIZE);
53297836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.file, urdc->primary.file,
53307836SJohn.Forte@Sun.COM 		    NSC_MAXPATH);
53317836SJohn.Forte@Sun.COM 		(void) strncpy(rdc_set.primary.bitmap, urdc->primary.bitmap,
5332*9093SRamana.Srikanth@Sun.COM 		    NSC_MAXPATH);
53337836SJohn.Forte@Sun.COM 
53347836SJohn.Forte@Sun.COM 		/* Now overwrite urdc primary */
53357836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->primary.intf, urdc->secondary.intf,
5336*9093SRamana.Srikanth@Sun.COM 		    MAX_RDC_HOST_SIZE);
53377836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->primary.file, urdc->secondary.file,
5338*9093SRamana.Srikanth@Sun.COM 		    NSC_MAXPATH);
53397836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->primary.bitmap, urdc->secondary.bitmap,
5340*9093SRamana.Srikanth@Sun.COM 		    NSC_MAXPATH);
53417836SJohn.Forte@Sun.COM 
53427836SJohn.Forte@Sun.COM 		/* Now ovwewrite urdc secondary */
53437836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->secondary.intf, rdc_set.primary.intf,
5344*9093SRamana.Srikanth@Sun.COM 		    MAX_RDC_HOST_SIZE);
53457836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->secondary.file, rdc_set.primary.file,
5346*9093SRamana.Srikanth@Sun.COM 		    NSC_MAXPATH);
53477836SJohn.Forte@Sun.COM 		(void) strncpy(urdc->secondary.bitmap, rdc_set.primary.bitmap,
5348*9093SRamana.Srikanth@Sun.COM 		    NSC_MAXPATH);
53497836SJohn.Forte@Sun.COM 
53507836SJohn.Forte@Sun.COM 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
53517836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_PRIMARY);
53527836SJohn.Forte@Sun.COM 			if (krdc->intf) {
53537836SJohn.Forte@Sun.COM 				krdc->intf->issecondary = 1;
53547836SJohn.Forte@Sun.COM 				krdc->intf->isprimary = 0;
53557836SJohn.Forte@Sun.COM 				krdc->intf->if_down = 1;
53567836SJohn.Forte@Sun.COM 			}
53577836SJohn.Forte@Sun.COM 		} else {
53587836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_PRIMARY);
53597836SJohn.Forte@Sun.COM 			if (krdc->intf) {
53607836SJohn.Forte@Sun.COM 				krdc->intf->issecondary = 0;
53617836SJohn.Forte@Sun.COM 				krdc->intf->isprimary = 1;
53627836SJohn.Forte@Sun.COM 				krdc->intf->if_down = 1;
53637836SJohn.Forte@Sun.COM 			}
53647836SJohn.Forte@Sun.COM 		}
53657836SJohn.Forte@Sun.COM 
53667836SJohn.Forte@Sun.COM 		if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
53677836SJohn.Forte@Sun.COM 		    ((krdc->type_flag & RDC_ASYNCMODE) != 0)) {
53687836SJohn.Forte@Sun.COM 			if (!krdc->bitmap_ref)
53697836SJohn.Forte@Sun.COM 				krdc->bitmap_ref =
53707836SJohn.Forte@Sun.COM 				    (uchar_t *)kmem_zalloc((krdc->bitmap_size *
53717836SJohn.Forte@Sun.COM 				    BITS_IN_BYTE * BMAP_REF_PREF_SIZE),
53727836SJohn.Forte@Sun.COM 				    KM_SLEEP);
53737836SJohn.Forte@Sun.COM 			if (krdc->bitmap_ref == NULL) {
53747836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
5375*9093SRamana.Srikanth@Sun.COM 				    "!rdc_reconfig: bitmap_ref alloc %"
53767836SJohn.Forte@Sun.COM 				    NSC_SZFMT " failed",
53777836SJohn.Forte@Sun.COM 				    krdc->bitmap_size * BITS_IN_BYTE *
53787836SJohn.Forte@Sun.COM 				    BMAP_REF_PREF_SIZE);
53797836SJohn.Forte@Sun.COM 				mutex_exit(&rdc_conf_lock);
53807836SJohn.Forte@Sun.COM 				return (-1);
53817836SJohn.Forte@Sun.COM 			}
53827836SJohn.Forte@Sun.COM 		}
53837836SJohn.Forte@Sun.COM 
53847836SJohn.Forte@Sun.COM 		if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
5385*9093SRamana.Srikanth@Sun.COM 		    (rdc_get_vflags(urdc) & RDC_SYNC_NEEDED)) {
53867836SJohn.Forte@Sun.COM 			/* Primary, so reverse sync needed */
53877836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
53887836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_SYNC_NEEDED);
53897836SJohn.Forte@Sun.COM 			rdc_set_mflags(urdc, RDC_RSYNC_NEEDED);
53907836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
53917836SJohn.Forte@Sun.COM 		} else if (rdc_get_vflags(urdc) & RDC_RSYNC_NEEDED) {
53927836SJohn.Forte@Sun.COM 			/* Secondary, so forward sync needed */
53937836SJohn.Forte@Sun.COM 			rdc_many_enter(krdc);
53947836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_RSYNC_NEEDED);
53957836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_SYNC_NEEDED);
53967836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
53977836SJohn.Forte@Sun.COM 		}
53987836SJohn.Forte@Sun.COM 
53997836SJohn.Forte@Sun.COM 		/*
54007836SJohn.Forte@Sun.COM 		 * rewrite bitmap header
54017836SJohn.Forte@Sun.COM 		 */
54027836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
54037836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
54047836SJohn.Forte@Sun.COM 	}
54057836SJohn.Forte@Sun.COM 
54067836SJohn.Forte@Sun.COM done:
54077836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
54087836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
54097836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
54107836SJohn.Forte@Sun.COM 
54117836SJohn.Forte@Sun.COM 	return (rc);
54127836SJohn.Forte@Sun.COM 
54137836SJohn.Forte@Sun.COM notlogging:
54147836SJohn.Forte@Sun.COM 	/* no other changes possible unless logging */
54157836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
54167836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
54177836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
54187836SJohn.Forte@Sun.COM 	spcs_s_add(kstatus, RDC_ENOTLOGGING, urdc->primary.intf,
54197836SJohn.Forte@Sun.COM 	    urdc->primary.file, urdc->secondary.intf,
54207836SJohn.Forte@Sun.COM 	    urdc->secondary.file);
54217836SJohn.Forte@Sun.COM 	return (RDC_ENOTLOGGING);
54227836SJohn.Forte@Sun.COM }
54237836SJohn.Forte@Sun.COM 
54247836SJohn.Forte@Sun.COM static int
rdc_reset(rdc_config_t * uparms,spcs_s_info_t kstatus)54257836SJohn.Forte@Sun.COM rdc_reset(rdc_config_t *uparms, spcs_s_info_t kstatus)
54267836SJohn.Forte@Sun.COM {
54277836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
54287836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
54297836SJohn.Forte@Sun.COM 	int rc = 0;
54307836SJohn.Forte@Sun.COM 	int index;
54317836SJohn.Forte@Sun.COM 	int cleared_error = 0;
54327836SJohn.Forte@Sun.COM 
54337836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
54347836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
54357836SJohn.Forte@Sun.COM 	if (index >= 0)
54367836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
54377836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
54387836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
54397836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
54407836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
54417836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
54427836SJohn.Forte@Sun.COM 	}
54437836SJohn.Forte@Sun.COM 
54447836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
54457836SJohn.Forte@Sun.COM 	set_busy(krdc);
54467836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
54477836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
54487836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
54497836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
54507836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
54517836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
54527836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
54537836SJohn.Forte@Sun.COM 	}
54547836SJohn.Forte@Sun.COM 
54557836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
54567836SJohn.Forte@Sun.COM 
54577836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
54587836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
54597836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
54607836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
54617836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
54627836SJohn.Forte@Sun.COM 		goto done;
54637836SJohn.Forte@Sun.COM 	}
54647836SJohn.Forte@Sun.COM 
54657836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_BMP_FAILED) && (krdc->bitmapfd)) {
54667836SJohn.Forte@Sun.COM 		if (rdc_reset_bitmap(krdc) == 0)
54677836SJohn.Forte@Sun.COM 			cleared_error++;
54687836SJohn.Forte@Sun.COM 	}
54697836SJohn.Forte@Sun.COM 
54707836SJohn.Forte@Sun.COM 	/* Fix direct file if necessary */
54717836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_PRIMARY) && urdc->direct_file[0]) {
54727836SJohn.Forte@Sun.COM 		if (rdc_open_direct(krdc) == NULL)
54737836SJohn.Forte@Sun.COM 			rdc_set_flags(urdc, RDC_FCAL_FAILED);
54747836SJohn.Forte@Sun.COM 		else {
54757836SJohn.Forte@Sun.COM 			rdc_clr_flags(urdc, RDC_FCAL_FAILED);
54767836SJohn.Forte@Sun.COM 			cleared_error++;
54777836SJohn.Forte@Sun.COM 		}
54787836SJohn.Forte@Sun.COM 	}
54797836SJohn.Forte@Sun.COM 
54807836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_VOL_FAILED)) {
54817836SJohn.Forte@Sun.COM 		rdc_many_enter(krdc);
54827836SJohn.Forte@Sun.COM 		rdc_clr_flags(urdc, RDC_VOL_FAILED);
54837836SJohn.Forte@Sun.COM 		cleared_error++;
54847836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
54857836SJohn.Forte@Sun.COM 	}
54867836SJohn.Forte@Sun.COM 
54877836SJohn.Forte@Sun.COM 	if (cleared_error) {
54887836SJohn.Forte@Sun.COM 		/* cleared an error so we should be in logging mode */
54897836SJohn.Forte@Sun.COM 		rdc_set_flags_log(urdc, RDC_LOGGING, "set reset");
54907836SJohn.Forte@Sun.COM 	}
54917836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
54927836SJohn.Forte@Sun.COM 
54937836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_DISKQ_FAILED))
54947836SJohn.Forte@Sun.COM 		rdc_unfail_diskq(krdc);
54957836SJohn.Forte@Sun.COM 
54967836SJohn.Forte@Sun.COM done:
54977836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
54987836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
54997836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
55007836SJohn.Forte@Sun.COM 
55017836SJohn.Forte@Sun.COM 	return (rc);
55027836SJohn.Forte@Sun.COM }
55037836SJohn.Forte@Sun.COM 
55047836SJohn.Forte@Sun.COM 
55057836SJohn.Forte@Sun.COM static int
rdc_tunable(rdc_config_t * uparms,spcs_s_info_t kstatus)55067836SJohn.Forte@Sun.COM rdc_tunable(rdc_config_t *uparms, spcs_s_info_t kstatus)
55077836SJohn.Forte@Sun.COM {
55087836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
55097836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
55107836SJohn.Forte@Sun.COM 	rdc_k_info_t *p;
55117836SJohn.Forte@Sun.COM 	rdc_u_info_t *q;
55127836SJohn.Forte@Sun.COM 	int rc = 0;
55137836SJohn.Forte@Sun.COM 	int index;
55147836SJohn.Forte@Sun.COM 
55157836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
55167836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
55177836SJohn.Forte@Sun.COM 	if (index >= 0)
55187836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
55197836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
55207836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
55217836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
55227836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
55237836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
55247836SJohn.Forte@Sun.COM 	}
55257836SJohn.Forte@Sun.COM 
55267836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
55277836SJohn.Forte@Sun.COM 	set_busy(krdc);
55287836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
55297836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
55307836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
55317836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
55327836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
55337836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
55347836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
55357836SJohn.Forte@Sun.COM 	}
55367836SJohn.Forte@Sun.COM 
55377836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
55387836SJohn.Forte@Sun.COM 
55397836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
55407836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
55417836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
55427836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
55437836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
55447836SJohn.Forte@Sun.COM 		goto done;
55457836SJohn.Forte@Sun.COM 	}
55467836SJohn.Forte@Sun.COM 
55477836SJohn.Forte@Sun.COM 	if (uparms->rdc_set->maxqfbas > 0) {
55487836SJohn.Forte@Sun.COM 		urdc->maxqfbas = uparms->rdc_set->maxqfbas;
55497836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
55507836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
55517836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
55527836SJohn.Forte@Sun.COM 			q->maxqfbas = urdc->maxqfbas;
55537836SJohn.Forte@Sun.COM 			rdc_write_state(q);
55547836SJohn.Forte@Sun.COM 		}
55557836SJohn.Forte@Sun.COM 	}
55567836SJohn.Forte@Sun.COM 
55577836SJohn.Forte@Sun.COM 	if (uparms->rdc_set->maxqitems > 0) {
55587836SJohn.Forte@Sun.COM 		urdc->maxqitems = uparms->rdc_set->maxqitems;
55597836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
55607836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
55617836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
55627836SJohn.Forte@Sun.COM 			q->maxqitems = urdc->maxqitems;
55637836SJohn.Forte@Sun.COM 			rdc_write_state(q);
55647836SJohn.Forte@Sun.COM 		}
55657836SJohn.Forte@Sun.COM 	}
55667836SJohn.Forte@Sun.COM 
55677836SJohn.Forte@Sun.COM 	if (uparms->options & RDC_OPT_SET_QNOBLOCK) {
55687836SJohn.Forte@Sun.COM 		disk_queue *que;
55697836SJohn.Forte@Sun.COM 
55707836SJohn.Forte@Sun.COM 		if (!RDC_IS_DISKQ(krdc->group)) {
55717836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EQNOQUEUE, urdc->primary.intf,
55727836SJohn.Forte@Sun.COM 			    urdc->primary.file, urdc->secondary.intf,
55737836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
55747836SJohn.Forte@Sun.COM 			rc = RDC_EQNOQUEUE;
55757836SJohn.Forte@Sun.COM 			goto done;
55767836SJohn.Forte@Sun.COM 		}
55777836SJohn.Forte@Sun.COM 
55787836SJohn.Forte@Sun.COM 		que = &krdc->group->diskq;
55797836SJohn.Forte@Sun.COM 		mutex_enter(QLOCK(que));
55807836SJohn.Forte@Sun.COM 		SET_QSTATE(que, RDC_QNOBLOCK);
55817836SJohn.Forte@Sun.COM 		/* queue will fail if this fails */
55827836SJohn.Forte@Sun.COM 		(void) rdc_stamp_diskq(krdc, 0, RDC_GROUP_LOCKED);
55837836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(que));
55847836SJohn.Forte@Sun.COM 
55857836SJohn.Forte@Sun.COM 	}
55867836SJohn.Forte@Sun.COM 
55877836SJohn.Forte@Sun.COM 	if (uparms->options & RDC_OPT_CLR_QNOBLOCK) {
55887836SJohn.Forte@Sun.COM 		disk_queue *que;
55897836SJohn.Forte@Sun.COM 
55907836SJohn.Forte@Sun.COM 		if (!RDC_IS_DISKQ(krdc->group)) {
55917836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_EQNOQUEUE, urdc->primary.intf,
55927836SJohn.Forte@Sun.COM 			    urdc->primary.file, urdc->secondary.intf,
55937836SJohn.Forte@Sun.COM 			    urdc->secondary.file);
55947836SJohn.Forte@Sun.COM 			rc = RDC_EQNOQUEUE;
55957836SJohn.Forte@Sun.COM 			goto done;
55967836SJohn.Forte@Sun.COM 		}
55977836SJohn.Forte@Sun.COM 		que = &krdc->group->diskq;
55987836SJohn.Forte@Sun.COM 		mutex_enter(QLOCK(que));
55997836SJohn.Forte@Sun.COM 		CLR_QSTATE(que, RDC_QNOBLOCK);
56007836SJohn.Forte@Sun.COM 		/* queue will fail if this fails */
56017836SJohn.Forte@Sun.COM 		(void) rdc_stamp_diskq(krdc, 0, RDC_GROUP_LOCKED);
56027836SJohn.Forte@Sun.COM 		mutex_exit(QLOCK(que));
56037836SJohn.Forte@Sun.COM 
56047836SJohn.Forte@Sun.COM 	}
56057836SJohn.Forte@Sun.COM 	if (uparms->rdc_set->asyncthr > 0) {
56067836SJohn.Forte@Sun.COM 		urdc->asyncthr = uparms->rdc_set->asyncthr;
56077836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
56087836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
56097836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
56107836SJohn.Forte@Sun.COM 			q->asyncthr = urdc->asyncthr;
56117836SJohn.Forte@Sun.COM 			rdc_write_state(q);
56127836SJohn.Forte@Sun.COM 		}
56137836SJohn.Forte@Sun.COM 	}
56147836SJohn.Forte@Sun.COM 
56157836SJohn.Forte@Sun.COM 	if (uparms->rdc_set->autosync >= 0) {
56167836SJohn.Forte@Sun.COM 		if (uparms->rdc_set->autosync == 0)
56177836SJohn.Forte@Sun.COM 			urdc->autosync = 0;
56187836SJohn.Forte@Sun.COM 		else
56197836SJohn.Forte@Sun.COM 			urdc->autosync = 1;
56207836SJohn.Forte@Sun.COM 
56217836SJohn.Forte@Sun.COM 		rdc_write_state(urdc);
56227836SJohn.Forte@Sun.COM 
56237836SJohn.Forte@Sun.COM 		/* Changed autosync, so update rest of the group */
56247836SJohn.Forte@Sun.COM 
56257836SJohn.Forte@Sun.COM 		for (p = krdc->group_next; p != krdc; p = p->group_next) {
56267836SJohn.Forte@Sun.COM 			q = &rdc_u_info[p->index];
56277836SJohn.Forte@Sun.COM 			q->autosync = urdc->autosync;
56287836SJohn.Forte@Sun.COM 			rdc_write_state(q);
56297836SJohn.Forte@Sun.COM 		}
56307836SJohn.Forte@Sun.COM 	}
56317836SJohn.Forte@Sun.COM 
56327836SJohn.Forte@Sun.COM done:
56337836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
56347836SJohn.Forte@Sun.COM 
56357836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
56367836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
56377836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
56387836SJohn.Forte@Sun.COM 
56397836SJohn.Forte@Sun.COM 	return (rc);
56407836SJohn.Forte@Sun.COM }
56417836SJohn.Forte@Sun.COM 
56427836SJohn.Forte@Sun.COM /*
56437836SJohn.Forte@Sun.COM  * Yet another standard thing that is not standard ...
56447836SJohn.Forte@Sun.COM  */
56457836SJohn.Forte@Sun.COM #ifndef offsetof
56467836SJohn.Forte@Sun.COM #define	offsetof(s, m)	((size_t)(&((s *)0)->m))
56477836SJohn.Forte@Sun.COM #endif
56487836SJohn.Forte@Sun.COM 
56497836SJohn.Forte@Sun.COM static int
rdc_status(void * arg,int mode,rdc_config_t * uparms,spcs_s_info_t kstatus)56507836SJohn.Forte@Sun.COM rdc_status(void *arg, int mode, rdc_config_t *uparms, spcs_s_info_t kstatus)
56517836SJohn.Forte@Sun.COM {
56527836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
56537836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
56547836SJohn.Forte@Sun.COM 	disk_queue *dqp;
56557836SJohn.Forte@Sun.COM 	int rc = 0;
56567836SJohn.Forte@Sun.COM 	int index;
56577836SJohn.Forte@Sun.COM 	char *ptr;
56587836SJohn.Forte@Sun.COM 	extern int rdc_status_copy32(const void *, void *, size_t, int);
56597836SJohn.Forte@Sun.COM 
56607836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
56617836SJohn.Forte@Sun.COM 	index = rdc_lookup_byname(uparms->rdc_set);
56627836SJohn.Forte@Sun.COM 	if (index >= 0)
56637836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
56647836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
56657836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
56667836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
56677836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
56687836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
56697836SJohn.Forte@Sun.COM 	}
56707836SJohn.Forte@Sun.COM 
56717836SJohn.Forte@Sun.COM 	set_busy(krdc);
56727836SJohn.Forte@Sun.COM 	if (krdc->type_flag == 0) {
56737836SJohn.Forte@Sun.COM 		/* A resume or enable failed */
56747836SJohn.Forte@Sun.COM 		wakeup_busy(krdc);
56757836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
56767836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
56777836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
56787836SJohn.Forte@Sun.COM 		return (RDC_EALREADY);
56797836SJohn.Forte@Sun.COM 	}
56807836SJohn.Forte@Sun.COM 
56817836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
56827836SJohn.Forte@Sun.COM 
56837836SJohn.Forte@Sun.COM 	rdc_group_enter(krdc);
56847836SJohn.Forte@Sun.COM 	if (rdc_check(krdc, uparms->rdc_set)) {
56857836SJohn.Forte@Sun.COM 		rdc_group_exit(krdc);
56867836SJohn.Forte@Sun.COM 		spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
56877836SJohn.Forte@Sun.COM 		    uparms->rdc_set->secondary.file);
56887836SJohn.Forte@Sun.COM 		rc = RDC_EALREADY;
56897836SJohn.Forte@Sun.COM 		goto done;
56907836SJohn.Forte@Sun.COM 	}
56917836SJohn.Forte@Sun.COM 
56927836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
56937836SJohn.Forte@Sun.COM 
56947836SJohn.Forte@Sun.COM 	/*
56957836SJohn.Forte@Sun.COM 	 * sneak out qstate in urdc->flags
56967836SJohn.Forte@Sun.COM 	 * this is harmless because it's value is not used
56977836SJohn.Forte@Sun.COM 	 * in urdc->flags. the real qstate is kept in
56987836SJohn.Forte@Sun.COM 	 * group->diskq->disk_hdr.h.state
56997836SJohn.Forte@Sun.COM 	 */
57007836SJohn.Forte@Sun.COM 	if (RDC_IS_DISKQ(krdc->group)) {
57017836SJohn.Forte@Sun.COM 		dqp = &krdc->group->diskq;
57027836SJohn.Forte@Sun.COM 		if (IS_QSTATE(dqp, RDC_QNOBLOCK))
57037836SJohn.Forte@Sun.COM 		urdc->flags |= RDC_QNOBLOCK;
57047836SJohn.Forte@Sun.COM 	}
57057836SJohn.Forte@Sun.COM 
57067836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
57077836SJohn.Forte@Sun.COM 		ptr = (char *)arg + offsetof(struct rdc_config32, rdc_set);
57087836SJohn.Forte@Sun.COM 		rc = rdc_status_copy32(urdc, ptr, sizeof (struct rdc_set32),
57097836SJohn.Forte@Sun.COM 		    mode);
57107836SJohn.Forte@Sun.COM 	} else {
57117836SJohn.Forte@Sun.COM 		ptr = (char *)arg + offsetof(struct rdc_config, rdc_set);
57127836SJohn.Forte@Sun.COM 		rc = ddi_copyout(urdc, ptr, sizeof (struct rdc_set), mode);
57137836SJohn.Forte@Sun.COM 	}
57147836SJohn.Forte@Sun.COM 	/* clear out qstate from flags */
57157836SJohn.Forte@Sun.COM 	urdc->flags &= ~RDC_QNOBLOCK;
57167836SJohn.Forte@Sun.COM 
57177836SJohn.Forte@Sun.COM 	if (rc)
57187836SJohn.Forte@Sun.COM 		rc = EFAULT;
57197836SJohn.Forte@Sun.COM 
57207836SJohn.Forte@Sun.COM 	rdc_group_exit(krdc);
57217836SJohn.Forte@Sun.COM done:
57227836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
57237836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
57247836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
57257836SJohn.Forte@Sun.COM 
57267836SJohn.Forte@Sun.COM 	return (rc);
57277836SJohn.Forte@Sun.COM }
57287836SJohn.Forte@Sun.COM 
57297836SJohn.Forte@Sun.COM /*
57307836SJohn.Forte@Sun.COM  * Overwrite the bitmap with one supplied by the
57317836SJohn.Forte@Sun.COM  * user.
57327836SJohn.Forte@Sun.COM  * Copy into all bitmaps that are tracking this volume.
57337836SJohn.Forte@Sun.COM  */
57347836SJohn.Forte@Sun.COM 
57357836SJohn.Forte@Sun.COM int
rdc_bitmapset(int op,char * sechost,char * secdev,void * bmapaddr,int bmapsz,nsc_off_t off,int mode)57367836SJohn.Forte@Sun.COM rdc_bitmapset(int op, char *sechost, char *secdev, void *bmapaddr, int bmapsz,
57377836SJohn.Forte@Sun.COM     nsc_off_t off, int mode)
57387836SJohn.Forte@Sun.COM {
57397836SJohn.Forte@Sun.COM 	int rc;
57407836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
57417836SJohn.Forte@Sun.COM 	int *indexvec;
57427836SJohn.Forte@Sun.COM 	int index;
57437836SJohn.Forte@Sun.COM 	int indexit;
57447836SJohn.Forte@Sun.COM 	kmutex_t **grouplocks;
57457836SJohn.Forte@Sun.COM 	int i;
57467836SJohn.Forte@Sun.COM 	int groupind;
57477836SJohn.Forte@Sun.COM 
57487836SJohn.Forte@Sun.COM 	if (off % FBA_SIZE(1)) {
57497836SJohn.Forte@Sun.COM 		/* Must be modulo FBA */
5750*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!bitmapset: Offset is not on an FBA "
5751*9093SRamana.Srikanth@Sun.COM 		    "boundary %llu", (unsigned long long)off);
57527836SJohn.Forte@Sun.COM 		return (EINVAL);
57537836SJohn.Forte@Sun.COM 	}
57547836SJohn.Forte@Sun.COM 	if (bmapsz % FBA_SIZE(1)) {
57557836SJohn.Forte@Sun.COM 		/* Must be modulo FBA */
5756*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!bitmapset: Size is not on an FBA "
57577836SJohn.Forte@Sun.COM 		    "boundary %d", bmapsz);
57587836SJohn.Forte@Sun.COM 		return (EINVAL);
57597836SJohn.Forte@Sun.COM 	}
57607836SJohn.Forte@Sun.COM 
57617836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
57627836SJohn.Forte@Sun.COM 	index = rdc_lookup_byhostdev(sechost, secdev);
57637836SJohn.Forte@Sun.COM 	if (index >= 0) {
57647836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[index];
57657836SJohn.Forte@Sun.COM 	}
57667836SJohn.Forte@Sun.COM 	if (index < 0 || (krdc->type_flag & RDC_DISABLEPEND)) {
57677836SJohn.Forte@Sun.COM 		rc = ENODEV;
57687836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
57697836SJohn.Forte@Sun.COM 		return (rc);
57707836SJohn.Forte@Sun.COM 	}
57717836SJohn.Forte@Sun.COM 	indexvec = kmem_alloc(rdc_max_sets * sizeof (int), KM_SLEEP);
57727836SJohn.Forte@Sun.COM 	grouplocks = kmem_alloc(rdc_max_sets * sizeof (kmutex_t *), KM_SLEEP);
57737836SJohn.Forte@Sun.COM 
57747836SJohn.Forte@Sun.COM 	/*
57757836SJohn.Forte@Sun.COM 	 * I now have this set, and I want to take the group
57767836SJohn.Forte@Sun.COM 	 * lock on it, and all the group locks of all the
57777836SJohn.Forte@Sun.COM 	 * sets on the many and multi-hop links.
57787836SJohn.Forte@Sun.COM 	 * I have to take the many lock while traversing the
57797836SJohn.Forte@Sun.COM 	 * many/multi links.
57807836SJohn.Forte@Sun.COM 	 * I think I also need to set the busy count on this
57817836SJohn.Forte@Sun.COM 	 * set, otherwise when I drop the conf_lock, what
57827836SJohn.Forte@Sun.COM 	 * will stop some other process from coming in and
57837836SJohn.Forte@Sun.COM 	 * issuing a disable?
57847836SJohn.Forte@Sun.COM 	 */
57857836SJohn.Forte@Sun.COM 	set_busy(krdc);
57867836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
57877836SJohn.Forte@Sun.COM 
57887836SJohn.Forte@Sun.COM retrylock:
57897836SJohn.Forte@Sun.COM 	groupind = 0;
57907836SJohn.Forte@Sun.COM 	indexit = 0;
57917836SJohn.Forte@Sun.COM 	rdc_many_enter(krdc);
57927836SJohn.Forte@Sun.COM 	/*
57937836SJohn.Forte@Sun.COM 	 * Take this initial sets group lock first.
57947836SJohn.Forte@Sun.COM 	 */
57957836SJohn.Forte@Sun.COM 	if (!mutex_tryenter(&krdc->group->lock)) {
57967836SJohn.Forte@Sun.COM 		rdc_many_exit(krdc);
57977836SJohn.Forte@Sun.COM 		goto retrylock;
57987836SJohn.Forte@Sun.COM 	}
57997836SJohn.Forte@Sun.COM 
58007836SJohn.Forte@Sun.COM 	grouplocks[groupind] = &krdc->group->lock;
58017836SJohn.Forte@Sun.COM 	groupind++;
58027836SJohn.Forte@Sun.COM 
58037836SJohn.Forte@Sun.COM 	rc = rdc_checkforbitmap(index, off + bmapsz);
58047836SJohn.Forte@Sun.COM 	if (rc) {
58057836SJohn.Forte@Sun.COM 		goto done;
58067836SJohn.Forte@Sun.COM 	}
58077836SJohn.Forte@Sun.COM 	indexvec[indexit] = index;
58087836SJohn.Forte@Sun.COM 	indexit++;
58097836SJohn.Forte@Sun.COM 	if (IS_MANY(krdc)) {
58107836SJohn.Forte@Sun.COM 		rdc_k_info_t *ktmp;
58117836SJohn.Forte@Sun.COM 
58127836SJohn.Forte@Sun.COM 		for (ktmp = krdc->many_next; ktmp != krdc;
58137836SJohn.Forte@Sun.COM 		    ktmp =  ktmp->many_next) {
58147836SJohn.Forte@Sun.COM 			/*
58157836SJohn.Forte@Sun.COM 			 * attempt to take the group lock,
58167836SJohn.Forte@Sun.COM 			 * if we don't already have it.
58177836SJohn.Forte@Sun.COM 			 */
58187836SJohn.Forte@Sun.COM 			if (ktmp->group == NULL) {
58197836SJohn.Forte@Sun.COM 				rc = ENODEV;
58207836SJohn.Forte@Sun.COM 				goto done;
58217836SJohn.Forte@Sun.COM 			}
58227836SJohn.Forte@Sun.COM 			for (i = 0; i < groupind; i++) {
58237836SJohn.Forte@Sun.COM 				if (grouplocks[i] == &ktmp->group->lock)
58247836SJohn.Forte@Sun.COM 					/* already have the group lock */
58257836SJohn.Forte@Sun.COM 					break;
58267836SJohn.Forte@Sun.COM 			}
58277836SJohn.Forte@Sun.COM 			/*
58287836SJohn.Forte@Sun.COM 			 * didn't find our lock in our collection,
58297836SJohn.Forte@Sun.COM 			 * attempt to take group lock.
58307836SJohn.Forte@Sun.COM 			 */
58317836SJohn.Forte@Sun.COM 			if (i >= groupind) {
58327836SJohn.Forte@Sun.COM 				if (!mutex_tryenter(&ktmp->group->lock)) {
58337836SJohn.Forte@Sun.COM 					for (i = 0; i < groupind; i++) {
58347836SJohn.Forte@Sun.COM 						mutex_exit(grouplocks[i]);
58357836SJohn.Forte@Sun.COM 					}
58367836SJohn.Forte@Sun.COM 					rdc_many_exit(krdc);
58377836SJohn.Forte@Sun.COM 					goto retrylock;
58387836SJohn.Forte@Sun.COM 				}
58397836SJohn.Forte@Sun.COM 				grouplocks[groupind] = &ktmp->group->lock;
58407836SJohn.Forte@Sun.COM 				groupind++;
58417836SJohn.Forte@Sun.COM 			}
58427836SJohn.Forte@Sun.COM 			rc = rdc_checkforbitmap(ktmp->index, off + bmapsz);
58437836SJohn.Forte@Sun.COM 			if (rc == 0) {
58447836SJohn.Forte@Sun.COM 				indexvec[indexit] = ktmp->index;
58457836SJohn.Forte@Sun.COM 				indexit++;
58467836SJohn.Forte@Sun.COM 			} else {
58477836SJohn.Forte@Sun.COM 				goto done;
58487836SJohn.Forte@Sun.COM 			}
58497836SJohn.Forte@Sun.COM 		}
58507836SJohn.Forte@Sun.COM 	}
58517836SJohn.Forte@Sun.COM 	if (IS_MULTI(krdc)) {
58527836SJohn.Forte@Sun.COM 		rdc_k_info_t *kmulti = krdc->multi_next;
58537836SJohn.Forte@Sun.COM 
58547836SJohn.Forte@Sun.COM 		if (kmulti->group == NULL) {
58557836SJohn.Forte@Sun.COM 			rc = ENODEV;
58567836SJohn.Forte@Sun.COM 			goto done;
58577836SJohn.Forte@Sun.COM 		}
58587836SJohn.Forte@Sun.COM 		/*
58597836SJohn.Forte@Sun.COM 		 * This can't be in our group already.
58607836SJohn.Forte@Sun.COM 		 */
58617836SJohn.Forte@Sun.COM 		if (!mutex_tryenter(&kmulti->group->lock)) {
58627836SJohn.Forte@Sun.COM 			for (i = 0; i < groupind; i++) {
58637836SJohn.Forte@Sun.COM 				mutex_exit(grouplocks[i]);
58647836SJohn.Forte@Sun.COM 			}
58657836SJohn.Forte@Sun.COM 			rdc_many_exit(krdc);
58667836SJohn.Forte@Sun.COM 			goto retrylock;
58677836SJohn.Forte@Sun.COM 		}
58687836SJohn.Forte@Sun.COM 		grouplocks[groupind] = &kmulti->group->lock;
58697836SJohn.Forte@Sun.COM 		groupind++;
58707836SJohn.Forte@Sun.COM 
58717836SJohn.Forte@Sun.COM 		rc = rdc_checkforbitmap(kmulti->index, off + bmapsz);
58727836SJohn.Forte@Sun.COM 		if (rc == 0) {
58737836SJohn.Forte@Sun.COM 			indexvec[indexit] = kmulti->index;
58747836SJohn.Forte@Sun.COM 			indexit++;
58757836SJohn.Forte@Sun.COM 		} else {
58767836SJohn.Forte@Sun.COM 			goto done;
58777836SJohn.Forte@Sun.COM 		}
58787836SJohn.Forte@Sun.COM 	}
58797836SJohn.Forte@Sun.COM 	rc = rdc_installbitmap(op, bmapaddr, bmapsz, off, mode, indexvec,
58807836SJohn.Forte@Sun.COM 	    indexit);
58817836SJohn.Forte@Sun.COM done:
58827836SJohn.Forte@Sun.COM 	for (i = 0; i < groupind; i++) {
58837836SJohn.Forte@Sun.COM 		mutex_exit(grouplocks[i]);
58847836SJohn.Forte@Sun.COM 	}
58857836SJohn.Forte@Sun.COM 	rdc_many_exit(krdc);
58867836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
58877836SJohn.Forte@Sun.COM 	wakeup_busy(krdc);
58887836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
58897836SJohn.Forte@Sun.COM 	kmem_free(indexvec, rdc_max_sets * sizeof (int));
58907836SJohn.Forte@Sun.COM 	kmem_free(grouplocks, rdc_max_sets * sizeof (kmutex_t *));
58917836SJohn.Forte@Sun.COM 	return (rc);
58927836SJohn.Forte@Sun.COM }
58937836SJohn.Forte@Sun.COM 
58947836SJohn.Forte@Sun.COM static int
rdc_checkforbitmap(int index,nsc_off_t limit)58957836SJohn.Forte@Sun.COM rdc_checkforbitmap(int index, nsc_off_t limit)
58967836SJohn.Forte@Sun.COM {
58977836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
58987836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
58997836SJohn.Forte@Sun.COM 
59007836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
59017836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
59027836SJohn.Forte@Sun.COM 
59037836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc)) {
59047836SJohn.Forte@Sun.COM 		return (EIO);
59057836SJohn.Forte@Sun.COM 	}
59067836SJohn.Forte@Sun.COM 	if (!(rdc_get_vflags(urdc) & RDC_LOGGING)) {
59077836SJohn.Forte@Sun.COM 		return (ENXIO);
59087836SJohn.Forte@Sun.COM 	}
59097836SJohn.Forte@Sun.COM 	if (krdc->dcio_bitmap == NULL) {
5910*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!checkforbitmap: No bitmap for set (%s:%s)",
5911*9093SRamana.Srikanth@Sun.COM 		    urdc->secondary.intf, urdc->secondary.file);
59127836SJohn.Forte@Sun.COM 		return (ENOENT);
59137836SJohn.Forte@Sun.COM 	}
59147836SJohn.Forte@Sun.COM 	if (limit > krdc->bitmap_size) {
5915*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!checkbitmap: Bitmap exceeded, "
59167836SJohn.Forte@Sun.COM 		    "incore %" NSC_SZFMT " user supplied %" NSC_SZFMT
5917*9093SRamana.Srikanth@Sun.COM 		    " for set (%s:%s)", krdc->bitmap_size,
5918*9093SRamana.Srikanth@Sun.COM 		    limit, urdc->secondary.intf, urdc->secondary.file);
59197836SJohn.Forte@Sun.COM 		return (ENOSPC);
59207836SJohn.Forte@Sun.COM 	}
59217836SJohn.Forte@Sun.COM 	return (0);
59227836SJohn.Forte@Sun.COM }
59237836SJohn.Forte@Sun.COM 
59247836SJohn.Forte@Sun.COM 
59257836SJohn.Forte@Sun.COM 
59267836SJohn.Forte@Sun.COM /*
59277836SJohn.Forte@Sun.COM  * Copy the user supplied bitmap to this set.
59287836SJohn.Forte@Sun.COM  */
59297836SJohn.Forte@Sun.COM static int
rdc_installbitmap(int op,void * bmapaddr,int bmapsz,nsc_off_t off,int mode,int * vec,int veccnt)59307836SJohn.Forte@Sun.COM rdc_installbitmap(int op, void *bmapaddr, int bmapsz,
59317836SJohn.Forte@Sun.COM     nsc_off_t off, int mode, int *vec, int veccnt)
59327836SJohn.Forte@Sun.COM {
59337836SJohn.Forte@Sun.COM 	int rc;
59347836SJohn.Forte@Sun.COM 	nsc_off_t sfba;
59357836SJohn.Forte@Sun.COM 	nsc_off_t efba;
59367836SJohn.Forte@Sun.COM 	nsc_off_t fba;
59377836SJohn.Forte@Sun.COM 	void *ormem = NULL;
59387836SJohn.Forte@Sun.COM 	int len;
59397836SJohn.Forte@Sun.COM 	int left;
59407836SJohn.Forte@Sun.COM 	int copied;
59417836SJohn.Forte@Sun.COM 	int index;
59427836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
59437836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
59447836SJohn.Forte@Sun.COM 
59457836SJohn.Forte@Sun.COM 	rc = 0;
59467836SJohn.Forte@Sun.COM 	ormem = kmem_alloc(RDC_MAXDATA, KM_SLEEP);
59477836SJohn.Forte@Sun.COM 	left = bmapsz;
59487836SJohn.Forte@Sun.COM 	copied = 0;
59497836SJohn.Forte@Sun.COM 	while (left > 0) {
59507836SJohn.Forte@Sun.COM 		if (left > RDC_MAXDATA) {
59517836SJohn.Forte@Sun.COM 			len = RDC_MAXDATA;
59527836SJohn.Forte@Sun.COM 		} else {
59537836SJohn.Forte@Sun.COM 			len = left;
59547836SJohn.Forte@Sun.COM 		}
59557836SJohn.Forte@Sun.COM 		if (ddi_copyin((char *)bmapaddr + copied, ormem,
59567836SJohn.Forte@Sun.COM 		    len, mode)) {
5957*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!installbitmap: Copyin failed");
59587836SJohn.Forte@Sun.COM 			rc = EFAULT;
59597836SJohn.Forte@Sun.COM 			goto out;
59607836SJohn.Forte@Sun.COM 		}
59617836SJohn.Forte@Sun.COM 		sfba = FBA_NUM(off + copied);
59627836SJohn.Forte@Sun.COM 		efba = FBA_NUM(off + copied + len);
59637836SJohn.Forte@Sun.COM 		for (index = 0; index < veccnt; index++) {
59647836SJohn.Forte@Sun.COM 			krdc = &rdc_k_info[vec[index]];
59657836SJohn.Forte@Sun.COM 			urdc = &rdc_u_info[vec[index]];
59667836SJohn.Forte@Sun.COM 
59677836SJohn.Forte@Sun.COM 			mutex_enter(&krdc->bmapmutex);
59687836SJohn.Forte@Sun.COM 			if (op == RDC_BITMAPSET) {
59697836SJohn.Forte@Sun.COM 				bcopy(ormem, krdc->dcio_bitmap + off + copied,
59707836SJohn.Forte@Sun.COM 				    len);
59717836SJohn.Forte@Sun.COM 			} else {
59727836SJohn.Forte@Sun.COM 				rdc_lor(ormem,
59737836SJohn.Forte@Sun.COM 				    krdc->dcio_bitmap + off + copied, len);
59747836SJohn.Forte@Sun.COM 			}
59757836SJohn.Forte@Sun.COM 			/*
59767836SJohn.Forte@Sun.COM 			 * Maybe this should be just done once outside of
59777836SJohn.Forte@Sun.COM 			 * the the loop? (Less work, but leaves a window
59787836SJohn.Forte@Sun.COM 			 * where the bits_set doesn't match the bitmap).
59797836SJohn.Forte@Sun.COM 			 */
59807836SJohn.Forte@Sun.COM 			urdc->bits_set = RDC_COUNT_BITMAP(krdc);
59817836SJohn.Forte@Sun.COM 			mutex_exit(&krdc->bmapmutex);
59827836SJohn.Forte@Sun.COM 			if (krdc->bitmap_write > 0) {
59837836SJohn.Forte@Sun.COM 				for (fba = sfba; fba < efba; fba++) {
59847836SJohn.Forte@Sun.COM 					if (rc = rdc_write_bitmap_fba(krdc,
59857836SJohn.Forte@Sun.COM 					    fba)) {
59867836SJohn.Forte@Sun.COM 
59877836SJohn.Forte@Sun.COM 						cmn_err(CE_WARN,
5988*9093SRamana.Srikanth@Sun.COM 						    "!installbitmap: "
59897836SJohn.Forte@Sun.COM 						    "write_bitmap_fba failed "
59907836SJohn.Forte@Sun.COM 						    "on fba number %" NSC_SZFMT
5991*9093SRamana.Srikanth@Sun.COM 						    " set %s:%s", fba,
59927836SJohn.Forte@Sun.COM 						    urdc->secondary.intf,
59937836SJohn.Forte@Sun.COM 						    urdc->secondary.file);
59947836SJohn.Forte@Sun.COM 						goto out;
59957836SJohn.Forte@Sun.COM 					}
59967836SJohn.Forte@Sun.COM 				}
59977836SJohn.Forte@Sun.COM 			}
59987836SJohn.Forte@Sun.COM 		}
59997836SJohn.Forte@Sun.COM 		copied += len;
60007836SJohn.Forte@Sun.COM 		left -= len;
60017836SJohn.Forte@Sun.COM 	}
60027836SJohn.Forte@Sun.COM out:
60037836SJohn.Forte@Sun.COM 	kmem_free(ormem, RDC_MAXDATA);
60047836SJohn.Forte@Sun.COM 	return (rc);
60057836SJohn.Forte@Sun.COM }
60067836SJohn.Forte@Sun.COM 
60077836SJohn.Forte@Sun.COM /*
60087836SJohn.Forte@Sun.COM  * _rdc_config
60097836SJohn.Forte@Sun.COM  */
60107836SJohn.Forte@Sun.COM int
_rdc_config(void * arg,int mode,spcs_s_info_t kstatus,int * rvp)60117836SJohn.Forte@Sun.COM _rdc_config(void *arg, int mode, spcs_s_info_t kstatus, int *rvp)
60127836SJohn.Forte@Sun.COM {
60137836SJohn.Forte@Sun.COM 	int rc = 0;
60147836SJohn.Forte@Sun.COM 	struct netbuf fsvaddr, tsvaddr;
60157836SJohn.Forte@Sun.COM 	struct knetconfig *knconf;
60167836SJohn.Forte@Sun.COM 	char *p = NULL, *pf = NULL;
60177836SJohn.Forte@Sun.COM 	struct rdc_config *uap;
60187836SJohn.Forte@Sun.COM 	STRUCT_DECL(knetconfig, knconf_tmp);
60197836SJohn.Forte@Sun.COM 	STRUCT_DECL(rdc_config, uparms);
60207836SJohn.Forte@Sun.COM 	int enable, disable;
60217836SJohn.Forte@Sun.COM 	int cmd;
60227836SJohn.Forte@Sun.COM 
60237836SJohn.Forte@Sun.COM 
60247836SJohn.Forte@Sun.COM 	STRUCT_HANDLE(rdc_set, rs);
60257836SJohn.Forte@Sun.COM 	STRUCT_HANDLE(rdc_addr, pa);
60267836SJohn.Forte@Sun.COM 	STRUCT_HANDLE(rdc_addr, sa);
60277836SJohn.Forte@Sun.COM 
60287836SJohn.Forte@Sun.COM 	STRUCT_INIT(uparms, mode);
60297836SJohn.Forte@Sun.COM 
60307836SJohn.Forte@Sun.COM 	bzero(STRUCT_BUF(uparms), STRUCT_SIZE(uparms));
60317836SJohn.Forte@Sun.COM 	bzero(&fsvaddr, sizeof (fsvaddr));
60327836SJohn.Forte@Sun.COM 	bzero(&tsvaddr, sizeof (tsvaddr));
60337836SJohn.Forte@Sun.COM 
60347836SJohn.Forte@Sun.COM 	knconf = NULL;
60357836SJohn.Forte@Sun.COM 
60367836SJohn.Forte@Sun.COM 	if (ddi_copyin(arg, STRUCT_BUF(uparms), STRUCT_SIZE(uparms), mode)) {
60377836SJohn.Forte@Sun.COM 		return (EFAULT);
60387836SJohn.Forte@Sun.COM 	}
60397836SJohn.Forte@Sun.COM 
60407836SJohn.Forte@Sun.COM 	STRUCT_SET_HANDLE(rs, mode, STRUCT_FGETP(uparms, rdc_set));
60417836SJohn.Forte@Sun.COM 	STRUCT_SET_HANDLE(pa, mode, STRUCT_FADDR(rs, primary));
60427836SJohn.Forte@Sun.COM 	STRUCT_SET_HANDLE(sa, mode, STRUCT_FADDR(rs, secondary));
60437836SJohn.Forte@Sun.COM 	cmd = STRUCT_FGET(uparms, command);
60447836SJohn.Forte@Sun.COM 	if (cmd == RDC_CMD_ENABLE || cmd == RDC_CMD_RESUME) {
60457836SJohn.Forte@Sun.COM 		fsvaddr.len = STRUCT_FGET(pa, addr.len);
60467836SJohn.Forte@Sun.COM 		fsvaddr.maxlen = STRUCT_FGET(pa, addr.maxlen);
60477836SJohn.Forte@Sun.COM 		fsvaddr.buf =  kmem_zalloc(fsvaddr.len, KM_SLEEP);
60487836SJohn.Forte@Sun.COM 
60497836SJohn.Forte@Sun.COM 		if (ddi_copyin(STRUCT_FGETP(pa, addr.buf),
6050*9093SRamana.Srikanth@Sun.COM 		    fsvaddr.buf, fsvaddr.len, mode)) {
60517836SJohn.Forte@Sun.COM 			kmem_free(fsvaddr.buf, fsvaddr.len);
60527836SJohn.Forte@Sun.COM #ifdef DEBUG
6053*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!copyin failed primary.addr 2");
60547836SJohn.Forte@Sun.COM #endif
60557836SJohn.Forte@Sun.COM 			return (EFAULT);
60567836SJohn.Forte@Sun.COM 		}
60577836SJohn.Forte@Sun.COM 
60587836SJohn.Forte@Sun.COM 
60597836SJohn.Forte@Sun.COM 		tsvaddr.len = STRUCT_FGET(sa, addr.len);
60607836SJohn.Forte@Sun.COM 		tsvaddr.maxlen = STRUCT_FGET(sa, addr.maxlen);
60617836SJohn.Forte@Sun.COM 		tsvaddr.buf =  kmem_zalloc(tsvaddr.len, KM_SLEEP);
60627836SJohn.Forte@Sun.COM 
60637836SJohn.Forte@Sun.COM 		if (ddi_copyin(STRUCT_FGETP(sa, addr.buf),
6064*9093SRamana.Srikanth@Sun.COM 		    tsvaddr.buf, tsvaddr.len, mode)) {
60657836SJohn.Forte@Sun.COM #ifdef DEBUG
6066*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!copyin failed secondary addr");
60677836SJohn.Forte@Sun.COM #endif
60687836SJohn.Forte@Sun.COM 			kmem_free(fsvaddr.buf, fsvaddr.len);
60697836SJohn.Forte@Sun.COM 			kmem_free(tsvaddr.buf, tsvaddr.len);
60707836SJohn.Forte@Sun.COM 			return (EFAULT);
60717836SJohn.Forte@Sun.COM 		}
60727836SJohn.Forte@Sun.COM 	} else {
60737836SJohn.Forte@Sun.COM 		fsvaddr.len = 0;
60747836SJohn.Forte@Sun.COM 		fsvaddr.maxlen = 0;
60757836SJohn.Forte@Sun.COM 		fsvaddr.buf =  kmem_zalloc(fsvaddr.len, KM_SLEEP);
60767836SJohn.Forte@Sun.COM 		tsvaddr.len = 0;
60777836SJohn.Forte@Sun.COM 		tsvaddr.maxlen = 0;
60787836SJohn.Forte@Sun.COM 		tsvaddr.buf =  kmem_zalloc(tsvaddr.len, KM_SLEEP);
60797836SJohn.Forte@Sun.COM 	}
60807836SJohn.Forte@Sun.COM 
60817836SJohn.Forte@Sun.COM 	if (STRUCT_FGETP(uparms, rdc_set->netconfig) != NULL) {
60827836SJohn.Forte@Sun.COM 		STRUCT_INIT(knconf_tmp, mode);
60837836SJohn.Forte@Sun.COM 		knconf = kmem_zalloc(sizeof (*knconf), KM_SLEEP);
60847836SJohn.Forte@Sun.COM 		if (ddi_copyin(STRUCT_FGETP(uparms, rdc_set->netconfig),
60857836SJohn.Forte@Sun.COM 		    STRUCT_BUF(knconf_tmp), STRUCT_SIZE(knconf_tmp), mode)) {
60867836SJohn.Forte@Sun.COM #ifdef DEBUG
6087*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!copyin failed netconfig");
60887836SJohn.Forte@Sun.COM #endif
60897836SJohn.Forte@Sun.COM 			kmem_free(fsvaddr.buf, fsvaddr.len);
60907836SJohn.Forte@Sun.COM 			kmem_free(tsvaddr.buf, tsvaddr.len);
60917836SJohn.Forte@Sun.COM 			kmem_free(knconf, sizeof (*knconf));
60927836SJohn.Forte@Sun.COM 			return (EFAULT);
60937836SJohn.Forte@Sun.COM 		}
60947836SJohn.Forte@Sun.COM 
60957836SJohn.Forte@Sun.COM 		knconf->knc_semantics = STRUCT_FGET(knconf_tmp, knc_semantics);
60967836SJohn.Forte@Sun.COM 		knconf->knc_protofmly = STRUCT_FGETP(knconf_tmp, knc_protofmly);
60977836SJohn.Forte@Sun.COM 		knconf->knc_proto = STRUCT_FGETP(knconf_tmp, knc_proto);
60987836SJohn.Forte@Sun.COM 
60997836SJohn.Forte@Sun.COM #ifndef _SunOS_5_6
61007836SJohn.Forte@Sun.COM 		if ((mode & DATAMODEL_LP64) == 0) {
61017836SJohn.Forte@Sun.COM 			knconf->knc_rdev =
61027836SJohn.Forte@Sun.COM 			    expldev(STRUCT_FGET(knconf_tmp, knc_rdev));
61037836SJohn.Forte@Sun.COM 		} else {
61047836SJohn.Forte@Sun.COM #endif
61057836SJohn.Forte@Sun.COM 			knconf->knc_rdev = STRUCT_FGET(knconf_tmp, knc_rdev);
61067836SJohn.Forte@Sun.COM #ifndef _SunOS_5_6
61077836SJohn.Forte@Sun.COM 		}
61087836SJohn.Forte@Sun.COM #endif
61097836SJohn.Forte@Sun.COM 
61107836SJohn.Forte@Sun.COM 		pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
61117836SJohn.Forte@Sun.COM 		p = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
61127836SJohn.Forte@Sun.COM 		rc = ddi_copyin(knconf->knc_protofmly, pf, KNC_STRSIZE, mode);
61137836SJohn.Forte@Sun.COM 		if (rc) {
61147836SJohn.Forte@Sun.COM #ifdef DEBUG
6115*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!copyin failed parms protofmly");
61167836SJohn.Forte@Sun.COM #endif
61177836SJohn.Forte@Sun.COM 			rc = EFAULT;
61187836SJohn.Forte@Sun.COM 			goto out;
61197836SJohn.Forte@Sun.COM 		}
61207836SJohn.Forte@Sun.COM 		rc = ddi_copyin(knconf->knc_proto, p, KNC_STRSIZE, mode);
61217836SJohn.Forte@Sun.COM 		if (rc) {
61227836SJohn.Forte@Sun.COM #ifdef DEBUG
6123*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!copyin failed parms proto");
61247836SJohn.Forte@Sun.COM #endif
61257836SJohn.Forte@Sun.COM 			rc = EFAULT;
61267836SJohn.Forte@Sun.COM 			goto out;
61277836SJohn.Forte@Sun.COM 		}
61287836SJohn.Forte@Sun.COM 		knconf->knc_protofmly = pf;
61297836SJohn.Forte@Sun.COM 		knconf->knc_proto = p;
61307836SJohn.Forte@Sun.COM 	} /* !NULL netconfig */
61317836SJohn.Forte@Sun.COM 
61327836SJohn.Forte@Sun.COM 	uap = kmem_alloc(sizeof (*uap), KM_SLEEP);
61337836SJohn.Forte@Sun.COM 
61347836SJohn.Forte@Sun.COM 	/* copy relevant parts of rdc_config to uap field by field */
61357836SJohn.Forte@Sun.COM 
61367836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].primary.intf, STRUCT_FGETP(pa, intf),
6137*9093SRamana.Srikanth@Sun.COM 	    MAX_RDC_HOST_SIZE);
61387836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].primary.file, STRUCT_FGETP(pa, file),
6139*9093SRamana.Srikanth@Sun.COM 	    NSC_MAXPATH);
61407836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].primary.bitmap, STRUCT_FGETP(pa, bitmap),
6141*9093SRamana.Srikanth@Sun.COM 	    NSC_MAXPATH);
61427836SJohn.Forte@Sun.COM 	uap->rdc_set[0].netconfig = knconf;
61437836SJohn.Forte@Sun.COM 	uap->rdc_set[0].flags = STRUCT_FGET(uparms, rdc_set->flags);
61447836SJohn.Forte@Sun.COM 	uap->rdc_set[0].index = STRUCT_FGET(uparms, rdc_set->index);
61457836SJohn.Forte@Sun.COM 	uap->rdc_set[0].setid = STRUCT_FGET(uparms, rdc_set->setid);
61467836SJohn.Forte@Sun.COM 	uap->rdc_set[0].sync_pos = STRUCT_FGET(uparms, rdc_set->sync_pos);
61477836SJohn.Forte@Sun.COM 	uap->rdc_set[0].volume_size = STRUCT_FGET(uparms, rdc_set->volume_size);
61487836SJohn.Forte@Sun.COM 	uap->rdc_set[0].bits_set = STRUCT_FGET(uparms, rdc_set->bits_set);
61497836SJohn.Forte@Sun.COM 	uap->rdc_set[0].autosync = STRUCT_FGET(uparms, rdc_set->autosync);
61507836SJohn.Forte@Sun.COM 	uap->rdc_set[0].maxqfbas = STRUCT_FGET(uparms, rdc_set->maxqfbas);
61517836SJohn.Forte@Sun.COM 	uap->rdc_set[0].maxqitems = STRUCT_FGET(uparms, rdc_set->maxqitems);
61527836SJohn.Forte@Sun.COM 	uap->rdc_set[0].asyncthr = STRUCT_FGET(uparms, rdc_set->asyncthr);
61537836SJohn.Forte@Sun.COM 	uap->rdc_set[0].syshostid = STRUCT_FGET(uparms, rdc_set->syshostid);
61547836SJohn.Forte@Sun.COM 	uap->rdc_set[0].primary.addr = fsvaddr;		/* struct copy */
61557836SJohn.Forte@Sun.COM 	uap->rdc_set[0].secondary.addr = tsvaddr;	/* struct copy */
61567836SJohn.Forte@Sun.COM 
61577836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].secondary.intf, STRUCT_FGETP(sa, intf),
6158*9093SRamana.Srikanth@Sun.COM 	    MAX_RDC_HOST_SIZE);
61597836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].secondary.file, STRUCT_FGETP(sa, file),
6160*9093SRamana.Srikanth@Sun.COM 	    NSC_MAXPATH);
61617836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].secondary.bitmap,
6162*9093SRamana.Srikanth@Sun.COM 	    STRUCT_FGETP(sa, bitmap), NSC_MAXPATH);
61637836SJohn.Forte@Sun.COM 
61647836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].direct_file,
6165*9093SRamana.Srikanth@Sun.COM 	    STRUCT_FGETP(rs, direct_file), NSC_MAXPATH);
61667836SJohn.Forte@Sun.COM 
61677836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].group_name, STRUCT_FGETP(rs, group_name),
61687836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
61697836SJohn.Forte@Sun.COM 
61707836SJohn.Forte@Sun.COM 	(void) strncpy(uap->rdc_set[0].disk_queue, STRUCT_FGETP(rs, disk_queue),
61717836SJohn.Forte@Sun.COM 	    NSC_MAXPATH);
61727836SJohn.Forte@Sun.COM 
61737836SJohn.Forte@Sun.COM 	uap->command = STRUCT_FGET(uparms, command);
61747836SJohn.Forte@Sun.COM 	uap->options = STRUCT_FGET(uparms, options);
61757836SJohn.Forte@Sun.COM 
61767836SJohn.Forte@Sun.COM 	enable = (uap->command == RDC_CMD_ENABLE ||
6177*9093SRamana.Srikanth@Sun.COM 	    uap->command == RDC_CMD_RESUME);
61787836SJohn.Forte@Sun.COM 	disable = (uap->command == RDC_CMD_DISABLE ||
6179*9093SRamana.Srikanth@Sun.COM 	    uap->command == RDC_CMD_SUSPEND);
61807836SJohn.Forte@Sun.COM 
61817836SJohn.Forte@Sun.COM 	/*
61827836SJohn.Forte@Sun.COM 	 * Initialise the threadset if it has not already been done.
61837836SJohn.Forte@Sun.COM 	 *
61847836SJohn.Forte@Sun.COM 	 * This has to be done now, not in rdcattach(), because
61857836SJohn.Forte@Sun.COM 	 * rdcattach() can be called before nskernd is running (eg.
61867836SJohn.Forte@Sun.COM 	 * boot -r) in which case the nst_init() would fail and hence
61877836SJohn.Forte@Sun.COM 	 * the attach would fail.
61887836SJohn.Forte@Sun.COM 	 *
61897836SJohn.Forte@Sun.COM 	 * Threadset creation is locked by the rdc_conf_lock,
61907836SJohn.Forte@Sun.COM 	 * destruction is inherently single threaded as it is done in
61917836SJohn.Forte@Sun.COM 	 * _rdc_unload() which must be the last thing performed by
61927836SJohn.Forte@Sun.COM 	 * rdcdetach().
61937836SJohn.Forte@Sun.COM 	 */
61947836SJohn.Forte@Sun.COM 
61957836SJohn.Forte@Sun.COM 	if (enable && _rdc_ioset == NULL) {
61967836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
61977836SJohn.Forte@Sun.COM 
61987836SJohn.Forte@Sun.COM 		if (_rdc_ioset == NULL) {
61997836SJohn.Forte@Sun.COM 			rc = rdc_thread_configure();
62007836SJohn.Forte@Sun.COM 		}
62017836SJohn.Forte@Sun.COM 
62027836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
62037836SJohn.Forte@Sun.COM 
62047836SJohn.Forte@Sun.COM 		if (rc || _rdc_ioset == NULL) {
62057836SJohn.Forte@Sun.COM 			spcs_s_add(kstatus, RDC_ENOTHREADS);
62067836SJohn.Forte@Sun.COM 			rc = RDC_ENOTHREADS;
62077836SJohn.Forte@Sun.COM 			goto outuap;
62087836SJohn.Forte@Sun.COM 		}
62097836SJohn.Forte@Sun.COM 	}
62107836SJohn.Forte@Sun.COM 	switch (uap->command) {
62117836SJohn.Forte@Sun.COM 	case RDC_CMD_ENABLE:
62127836SJohn.Forte@Sun.COM 		rc = rdc_enable(uap, kstatus);
62137836SJohn.Forte@Sun.COM 		break;
62147836SJohn.Forte@Sun.COM 	case RDC_CMD_DISABLE:
62157836SJohn.Forte@Sun.COM 		rc = rdc_disable(uap, kstatus);
62167836SJohn.Forte@Sun.COM 		break;
62177836SJohn.Forte@Sun.COM 	case RDC_CMD_COPY:
62187836SJohn.Forte@Sun.COM 		rc = rdc_sync(uap, kstatus);
62197836SJohn.Forte@Sun.COM 		break;
62207836SJohn.Forte@Sun.COM 	case RDC_CMD_LOG:
62217836SJohn.Forte@Sun.COM 		rc = rdc_log(uap, kstatus);
62227836SJohn.Forte@Sun.COM 		break;
62237836SJohn.Forte@Sun.COM 	case RDC_CMD_RECONFIG:
62247836SJohn.Forte@Sun.COM 		rc = rdc_reconfig(uap, kstatus);
62257836SJohn.Forte@Sun.COM 		break;
62267836SJohn.Forte@Sun.COM 	case RDC_CMD_RESUME:
62277836SJohn.Forte@Sun.COM 		rc = rdc_resume(uap, kstatus);
62287836SJohn.Forte@Sun.COM 		break;
62297836SJohn.Forte@Sun.COM 	case RDC_CMD_SUSPEND:
62307836SJohn.Forte@Sun.COM 		rc = rdc_suspend(uap, kstatus);
62317836SJohn.Forte@Sun.COM 		break;
62327836SJohn.Forte@Sun.COM 	case RDC_CMD_TUNABLE:
62337836SJohn.Forte@Sun.COM 		rc = rdc_tunable(uap, kstatus);
62347836SJohn.Forte@Sun.COM 		break;
62357836SJohn.Forte@Sun.COM 	case RDC_CMD_WAIT:
62367836SJohn.Forte@Sun.COM 		rc = rdc_wait(uap, kstatus);
62377836SJohn.Forte@Sun.COM 		break;
62387836SJohn.Forte@Sun.COM 	case RDC_CMD_HEALTH:
62397836SJohn.Forte@Sun.COM 		rc = rdc_health(uap, kstatus, rvp);
62407836SJohn.Forte@Sun.COM 		break;
62417836SJohn.Forte@Sun.COM 	case RDC_CMD_STATUS:
62427836SJohn.Forte@Sun.COM 		rc = rdc_status(arg, mode, uap, kstatus);
62437836SJohn.Forte@Sun.COM 		break;
62447836SJohn.Forte@Sun.COM 	case RDC_CMD_RESET:
62457836SJohn.Forte@Sun.COM 		rc = rdc_reset(uap, kstatus);
62467836SJohn.Forte@Sun.COM 		break;
62477836SJohn.Forte@Sun.COM 	case RDC_CMD_ADDQ:
62487836SJohn.Forte@Sun.COM 		rc = rdc_add_diskq(uap, kstatus);
62497836SJohn.Forte@Sun.COM 		break;
62507836SJohn.Forte@Sun.COM 	case RDC_CMD_REMQ:
62517836SJohn.Forte@Sun.COM 		if ((rc = rdc_rem_diskq(uap, kstatus)) != 0)
62527836SJohn.Forte@Sun.COM 			break;
62537836SJohn.Forte@Sun.COM 		/* FALLTHRU */
62547836SJohn.Forte@Sun.COM 	case RDC_CMD_KILLQ:
62557836SJohn.Forte@Sun.COM 		rc = rdc_kill_diskq(uap, kstatus);
62567836SJohn.Forte@Sun.COM 		break;
62577836SJohn.Forte@Sun.COM 	case RDC_CMD_INITQ:
62587836SJohn.Forte@Sun.COM 		rc = rdc_init_diskq(uap, kstatus);
62597836SJohn.Forte@Sun.COM 		break;
62607836SJohn.Forte@Sun.COM 
62617836SJohn.Forte@Sun.COM 	default:
62627836SJohn.Forte@Sun.COM 		rc = EINVAL;
62637836SJohn.Forte@Sun.COM 		break;
62647836SJohn.Forte@Sun.COM 	}
62657836SJohn.Forte@Sun.COM 
62667836SJohn.Forte@Sun.COM 	/*
62677836SJohn.Forte@Sun.COM 	 * Tune the threadset size after a successful rdc_set addition
62687836SJohn.Forte@Sun.COM 	 * or removal.
62697836SJohn.Forte@Sun.COM 	 */
62707836SJohn.Forte@Sun.COM 	if ((enable || disable) && rc == 0) {
62717836SJohn.Forte@Sun.COM 		mutex_enter(&rdc_conf_lock);
62727836SJohn.Forte@Sun.COM 		rdc_thread_tune(enable ? 2 : -2);
62737836SJohn.Forte@Sun.COM 		mutex_exit(&rdc_conf_lock);
62747836SJohn.Forte@Sun.COM 	}
62757836SJohn.Forte@Sun.COM outuap:
62767836SJohn.Forte@Sun.COM 	kmem_free(uap, sizeof (*uap));
62777836SJohn.Forte@Sun.COM out:
62787836SJohn.Forte@Sun.COM 	kmem_free(fsvaddr.buf, fsvaddr.len);
62797836SJohn.Forte@Sun.COM 	kmem_free(tsvaddr.buf, tsvaddr.len);
62807836SJohn.Forte@Sun.COM 	if (pf)
62817836SJohn.Forte@Sun.COM 		kmem_free(pf, KNC_STRSIZE);
62827836SJohn.Forte@Sun.COM 	if (p)
62837836SJohn.Forte@Sun.COM 		kmem_free(p, KNC_STRSIZE);
62847836SJohn.Forte@Sun.COM 	if (knconf)
62857836SJohn.Forte@Sun.COM 		kmem_free(knconf, sizeof (*knconf));
62867836SJohn.Forte@Sun.COM 	return (rc);
62877836SJohn.Forte@Sun.COM }
62887836SJohn.Forte@Sun.COM 
62897836SJohn.Forte@Sun.COM 
62907836SJohn.Forte@Sun.COM /*
62917836SJohn.Forte@Sun.COM  * krdc->group->lock held on entry to halt_sync()
62927836SJohn.Forte@Sun.COM  */
62937836SJohn.Forte@Sun.COM static void
halt_sync(rdc_k_info_t * krdc)62947836SJohn.Forte@Sun.COM halt_sync(rdc_k_info_t *krdc)
62957836SJohn.Forte@Sun.COM {
62967836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
62977836SJohn.Forte@Sun.COM 
62987836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&krdc->group->lock));
62997836SJohn.Forte@Sun.COM 	ASSERT(IS_ENABLED(urdc));
63007836SJohn.Forte@Sun.COM 
63017836SJohn.Forte@Sun.COM 	/*
63027836SJohn.Forte@Sun.COM 	 * If a sync is in progress, halt it
63037836SJohn.Forte@Sun.COM 	 */
63047836SJohn.Forte@Sun.COM 	if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
63057836SJohn.Forte@Sun.COM 	    (krdc->aux_state & RDC_AUXSYNCIP)) {
63067836SJohn.Forte@Sun.COM 		krdc->disk_status = 1;
63077836SJohn.Forte@Sun.COM 
63087836SJohn.Forte@Sun.COM 		while (krdc->disk_status == 1) {
63097836SJohn.Forte@Sun.COM 			if (cv_wait_sig(&krdc->haltcv, &krdc->group->lock) == 0)
63107836SJohn.Forte@Sun.COM 				break;
63117836SJohn.Forte@Sun.COM 		}
63127836SJohn.Forte@Sun.COM 	}
63137836SJohn.Forte@Sun.COM }
63147836SJohn.Forte@Sun.COM 
63157836SJohn.Forte@Sun.COM /*
63167836SJohn.Forte@Sun.COM  * return size in blocks
63177836SJohn.Forte@Sun.COM  */
63187836SJohn.Forte@Sun.COM uint64_t
mirror_getsize(int index)63197836SJohn.Forte@Sun.COM mirror_getsize(int index)
63207836SJohn.Forte@Sun.COM {
63217836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
63227836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
63237836SJohn.Forte@Sun.COM 	int rc, rs;
63247836SJohn.Forte@Sun.COM 	nsc_size_t size;
63257836SJohn.Forte@Sun.COM 
63267836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
63277836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
63287836SJohn.Forte@Sun.COM 
63297836SJohn.Forte@Sun.COM 	rc = _rdc_rsrv_devs(krdc, RDC_RAW, RDC_INTERNAL);
63307836SJohn.Forte@Sun.COM 	rs = nsc_partsize(RDC_U_FD(krdc), &size);
63317836SJohn.Forte@Sun.COM 	urdc->volume_size = size;
63327836SJohn.Forte@Sun.COM 	if (rc == 0)
63337836SJohn.Forte@Sun.COM 		_rdc_rlse_devs(krdc, RDC_RAW);
63347836SJohn.Forte@Sun.COM 
63357836SJohn.Forte@Sun.COM 	return (rs == 0 ? urdc->volume_size : 0);
63367836SJohn.Forte@Sun.COM }
63377836SJohn.Forte@Sun.COM 
63387836SJohn.Forte@Sun.COM 
63397836SJohn.Forte@Sun.COM /*
63407836SJohn.Forte@Sun.COM  * Create a new dataset for this transfer, and add it to the list
63417836SJohn.Forte@Sun.COM  * of datasets via the net_dataset pointer in the krdc.
63427836SJohn.Forte@Sun.COM  */
63437836SJohn.Forte@Sun.COM rdc_net_dataset_t *
rdc_net_add_set(int index)63447836SJohn.Forte@Sun.COM rdc_net_add_set(int index)
63457836SJohn.Forte@Sun.COM {
63467836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
63477836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
63487836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
63497836SJohn.Forte@Sun.COM 
63507836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
6351*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_add_set: bad index %d", index);
63527836SJohn.Forte@Sun.COM 		return (NULL);
63537836SJohn.Forte@Sun.COM 	}
63547836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
63557836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[index];
63567836SJohn.Forte@Sun.COM 
63577836SJohn.Forte@Sun.COM 	dset = kmem_alloc(sizeof (*dset), KM_NOSLEEP);
63587836SJohn.Forte@Sun.COM 	if (dset == NULL) {
6359*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_add_set: kmem_alloc failed");
63607836SJohn.Forte@Sun.COM 		return (NULL);
63617836SJohn.Forte@Sun.COM 	}
63627836SJohn.Forte@Sun.COM 	RDC_DSMEMUSE(sizeof (*dset));
63637836SJohn.Forte@Sun.COM 	dset->inuse = 1;
63647836SJohn.Forte@Sun.COM 	dset->nitems = 0;
63657836SJohn.Forte@Sun.COM 	dset->delpend = 0;
63667836SJohn.Forte@Sun.COM 	dset->head = NULL;
63677836SJohn.Forte@Sun.COM 	dset->tail = NULL;
63687836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->dc_sleep);
63697836SJohn.Forte@Sun.COM 
63707836SJohn.Forte@Sun.COM 	if (!IS_ENABLED(urdc)) {
63717836SJohn.Forte@Sun.COM 		/* raced with a disable command */
63727836SJohn.Forte@Sun.COM 		kmem_free(dset, sizeof (*dset));
63737836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-sizeof (*dset));
63747836SJohn.Forte@Sun.COM 		mutex_exit(&krdc->dc_sleep);
63757836SJohn.Forte@Sun.COM 		return (NULL);
63767836SJohn.Forte@Sun.COM 	}
63777836SJohn.Forte@Sun.COM 	/*
63787836SJohn.Forte@Sun.COM 	 * Shared the id generator, (and the locks).
63797836SJohn.Forte@Sun.COM 	 */
63807836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_net_hnd_id_lock);
63817836SJohn.Forte@Sun.COM 	if (++rdc_net_hnd_id == 0)
63827836SJohn.Forte@Sun.COM 		rdc_net_hnd_id = 1;
63837836SJohn.Forte@Sun.COM 	dset->id = rdc_net_hnd_id;
63847836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_net_hnd_id_lock);
63857836SJohn.Forte@Sun.COM 
63867836SJohn.Forte@Sun.COM #ifdef DEBUG
63877836SJohn.Forte@Sun.COM 	if (krdc->net_dataset != NULL) {
63887836SJohn.Forte@Sun.COM 		rdc_net_dataset_t *dset2;
63897836SJohn.Forte@Sun.COM 		for (dset2 = krdc->net_dataset; dset2; dset2 = dset2->next) {
63907836SJohn.Forte@Sun.COM 			if (dset2->id == dset->id) {
63917836SJohn.Forte@Sun.COM 				cmn_err(CE_PANIC,
6392*9093SRamana.Srikanth@Sun.COM 				    "rdc_net_add_set duplicate id %p:%d %p:%d",
63937836SJohn.Forte@Sun.COM 				    (void *)dset, dset->id,
63947836SJohn.Forte@Sun.COM 				    (void *)dset2, dset2->id);
63957836SJohn.Forte@Sun.COM 			}
63967836SJohn.Forte@Sun.COM 		}
63977836SJohn.Forte@Sun.COM 	}
63987836SJohn.Forte@Sun.COM #endif
63997836SJohn.Forte@Sun.COM 	dset->next = krdc->net_dataset;
64007836SJohn.Forte@Sun.COM 	krdc->net_dataset = dset;
64017836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->dc_sleep);
64027836SJohn.Forte@Sun.COM 
64037836SJohn.Forte@Sun.COM 	return (dset);
64047836SJohn.Forte@Sun.COM }
64057836SJohn.Forte@Sun.COM 
64067836SJohn.Forte@Sun.COM /*
64077836SJohn.Forte@Sun.COM  * fetch the previously added dataset.
64087836SJohn.Forte@Sun.COM  */
64097836SJohn.Forte@Sun.COM rdc_net_dataset_t *
rdc_net_get_set(int index,int id)64107836SJohn.Forte@Sun.COM rdc_net_get_set(int index, int id)
64117836SJohn.Forte@Sun.COM {
64127836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
64137836SJohn.Forte@Sun.COM 	rdc_net_dataset_t *dset;
64147836SJohn.Forte@Sun.COM 
64157836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
6416*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_get_set: bad index %d", index);
64177836SJohn.Forte@Sun.COM 		return (NULL);
64187836SJohn.Forte@Sun.COM 	}
64197836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
64207836SJohn.Forte@Sun.COM 
64217836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->dc_sleep);
64227836SJohn.Forte@Sun.COM 
64237836SJohn.Forte@Sun.COM 	dset = krdc->net_dataset;
64247836SJohn.Forte@Sun.COM 	while (dset && (dset->id != id))
64257836SJohn.Forte@Sun.COM 		dset = dset->next;
64267836SJohn.Forte@Sun.COM 
64277836SJohn.Forte@Sun.COM 	if (dset) {
64287836SJohn.Forte@Sun.COM 		dset->inuse++;
64297836SJohn.Forte@Sun.COM 	}
64307836SJohn.Forte@Sun.COM 
64317836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->dc_sleep);
64327836SJohn.Forte@Sun.COM 	return (dset);
64337836SJohn.Forte@Sun.COM }
64347836SJohn.Forte@Sun.COM 
64357836SJohn.Forte@Sun.COM /*
64367836SJohn.Forte@Sun.COM  * Decrement the inuse counter. Data may be freed.
64377836SJohn.Forte@Sun.COM  */
64387836SJohn.Forte@Sun.COM void
rdc_net_put_set(int index,rdc_net_dataset_t * dset)64397836SJohn.Forte@Sun.COM rdc_net_put_set(int index, rdc_net_dataset_t *dset)
64407836SJohn.Forte@Sun.COM {
64417836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
64427836SJohn.Forte@Sun.COM 
64437836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
6444*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_put_set: bad index %d", index);
64457836SJohn.Forte@Sun.COM 		return;
64467836SJohn.Forte@Sun.COM 	}
64477836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
64487836SJohn.Forte@Sun.COM 
64497836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->dc_sleep);
64507836SJohn.Forte@Sun.COM 	dset->inuse--;
64517836SJohn.Forte@Sun.COM 	ASSERT(dset->inuse >= 0);
64527836SJohn.Forte@Sun.COM 	if ((dset->inuse == 0) && (dset->delpend)) {
64537836SJohn.Forte@Sun.COM 		rdc_net_free_set(krdc, dset);
64547836SJohn.Forte@Sun.COM 	}
64557836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->dc_sleep);
64567836SJohn.Forte@Sun.COM }
64577836SJohn.Forte@Sun.COM 
64587836SJohn.Forte@Sun.COM /*
64597836SJohn.Forte@Sun.COM  * Mark that we are finished with this set. Decrement inuse
64607836SJohn.Forte@Sun.COM  * counter, mark as needing deletion, and
64617836SJohn.Forte@Sun.COM  * remove from linked list.
64627836SJohn.Forte@Sun.COM  */
64637836SJohn.Forte@Sun.COM void
rdc_net_del_set(int index,rdc_net_dataset_t * dset)64647836SJohn.Forte@Sun.COM rdc_net_del_set(int index, rdc_net_dataset_t *dset)
64657836SJohn.Forte@Sun.COM {
64667836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
64677836SJohn.Forte@Sun.COM 
64687836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
6469*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_net_del_set: bad index %d", index);
64707836SJohn.Forte@Sun.COM 		return;
64717836SJohn.Forte@Sun.COM 	}
64727836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
64737836SJohn.Forte@Sun.COM 
64747836SJohn.Forte@Sun.COM 	mutex_enter(&krdc->dc_sleep);
64757836SJohn.Forte@Sun.COM 	dset->inuse--;
64767836SJohn.Forte@Sun.COM 	ASSERT(dset->inuse >= 0);
64777836SJohn.Forte@Sun.COM 	dset->delpend = 1;
64787836SJohn.Forte@Sun.COM 	if (dset->inuse == 0) {
64797836SJohn.Forte@Sun.COM 		rdc_net_free_set(krdc, dset);
64807836SJohn.Forte@Sun.COM 	}
64817836SJohn.Forte@Sun.COM 	mutex_exit(&krdc->dc_sleep);
64827836SJohn.Forte@Sun.COM }
64837836SJohn.Forte@Sun.COM 
64847836SJohn.Forte@Sun.COM /*
64857836SJohn.Forte@Sun.COM  * free all the memory associated with this set, and remove from
64867836SJohn.Forte@Sun.COM  * list.
64877836SJohn.Forte@Sun.COM  * Enters and exits with dc_sleep lock held.
64887836SJohn.Forte@Sun.COM  */
64897836SJohn.Forte@Sun.COM 
64907836SJohn.Forte@Sun.COM void
rdc_net_free_set(rdc_k_info_t * krdc,rdc_net_dataset_t * dset)64917836SJohn.Forte@Sun.COM rdc_net_free_set(rdc_k_info_t *krdc, rdc_net_dataset_t *dset)
64927836SJohn.Forte@Sun.COM {
64937836SJohn.Forte@Sun.COM 	rdc_net_dataset_t **dsetp;
64947836SJohn.Forte@Sun.COM #ifdef DEBUG
64957836SJohn.Forte@Sun.COM 	int found = 0;
64967836SJohn.Forte@Sun.COM #endif
64977836SJohn.Forte@Sun.COM 
64987836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&krdc->dc_sleep));
64997836SJohn.Forte@Sun.COM 	ASSERT(dset);
65007836SJohn.Forte@Sun.COM 	for (dsetp = &krdc->net_dataset; *dsetp; dsetp = &((*dsetp)->next)) {
65017836SJohn.Forte@Sun.COM 		if (*dsetp == dset) {
65027836SJohn.Forte@Sun.COM 			*dsetp = dset->next;
65037836SJohn.Forte@Sun.COM #ifdef DEBUG
65047836SJohn.Forte@Sun.COM 			found = 1;
65057836SJohn.Forte@Sun.COM #endif
65067836SJohn.Forte@Sun.COM 			break;
65077836SJohn.Forte@Sun.COM 		}
65087836SJohn.Forte@Sun.COM 	}
65097836SJohn.Forte@Sun.COM 
65107836SJohn.Forte@Sun.COM #ifdef DEBUG
65117836SJohn.Forte@Sun.COM 	if (found == 0) {
6512*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!rdc_net_free_set: Unable to find "
65137836SJohn.Forte@Sun.COM 		    "dataset 0x%p in krdc list", (void *)dset);
65147836SJohn.Forte@Sun.COM 	}
65157836SJohn.Forte@Sun.COM #endif
65167836SJohn.Forte@Sun.COM 	/*
65177836SJohn.Forte@Sun.COM 	 * unlinked from list. Free all the data
65187836SJohn.Forte@Sun.COM 	 */
65197836SJohn.Forte@Sun.COM 	rdc_ditemsfree(dset);
65207836SJohn.Forte@Sun.COM 	/*
65217836SJohn.Forte@Sun.COM 	 * free my core.
65227836SJohn.Forte@Sun.COM 	 */
65237836SJohn.Forte@Sun.COM 	kmem_free(dset, sizeof (*dset));
65247836SJohn.Forte@Sun.COM 	RDC_DSMEMUSE(-sizeof (*dset));
65257836SJohn.Forte@Sun.COM }
65267836SJohn.Forte@Sun.COM 
65277836SJohn.Forte@Sun.COM 
65287836SJohn.Forte@Sun.COM /*
65297836SJohn.Forte@Sun.COM  * Free all the dataitems and the data it points to.
65307836SJohn.Forte@Sun.COM  */
65317836SJohn.Forte@Sun.COM static void
rdc_ditemsfree(rdc_net_dataset_t * dset)65327836SJohn.Forte@Sun.COM rdc_ditemsfree(rdc_net_dataset_t *dset)
65337836SJohn.Forte@Sun.COM {
65347836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *ditem;
65357836SJohn.Forte@Sun.COM 	rdc_net_dataitem_t *nitem;
65367836SJohn.Forte@Sun.COM 
65377836SJohn.Forte@Sun.COM 	ditem = dset->head;
65387836SJohn.Forte@Sun.COM 
65397836SJohn.Forte@Sun.COM 	while (ditem) {
65407836SJohn.Forte@Sun.COM 		nitem = ditem->next;
65417836SJohn.Forte@Sun.COM 		kmem_free(ditem->dptr, ditem->mlen);
65427836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-ditem->mlen);
65437836SJohn.Forte@Sun.COM 		dset->nitems--;
65447836SJohn.Forte@Sun.COM 		kmem_free(ditem, sizeof (*ditem));
65457836SJohn.Forte@Sun.COM 		RDC_DSMEMUSE(-sizeof (*ditem));
65467836SJohn.Forte@Sun.COM 		ditem = nitem;
65477836SJohn.Forte@Sun.COM 	}
65487836SJohn.Forte@Sun.COM 	ASSERT(dset->nitems == 0);
65497836SJohn.Forte@Sun.COM }
65507836SJohn.Forte@Sun.COM 
65517836SJohn.Forte@Sun.COM /*
65527836SJohn.Forte@Sun.COM  * allocate and initialize a rdc_aio_t
65537836SJohn.Forte@Sun.COM  */
65547836SJohn.Forte@Sun.COM rdc_aio_t *
rdc_aio_tbuf_get(void * n,void * h,int pos,int len,int flag,int index,int s)65557836SJohn.Forte@Sun.COM rdc_aio_tbuf_get(void *n, void *h, int pos, int len, int flag, int index, int s)
65567836SJohn.Forte@Sun.COM {
65577836SJohn.Forte@Sun.COM 	rdc_aio_t *p;
65587836SJohn.Forte@Sun.COM 
65597836SJohn.Forte@Sun.COM 	p = kmem_zalloc(sizeof (rdc_aio_t), KM_NOSLEEP);
65607836SJohn.Forte@Sun.COM 	if (p == NULL) {
65617836SJohn.Forte@Sun.COM #ifdef DEBUG
6562*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!_rdcaiotbufget: kmem_alloc failed bp aio");
65637836SJohn.Forte@Sun.COM #endif
65647836SJohn.Forte@Sun.COM 		return (NULL);
65657836SJohn.Forte@Sun.COM 	} else {
65667836SJohn.Forte@Sun.COM 		p->next = n; /* overload */
65677836SJohn.Forte@Sun.COM 		p->handle = h;
65687836SJohn.Forte@Sun.COM 		p->pos = pos;
65697836SJohn.Forte@Sun.COM 		p->qpos = -1;
65707836SJohn.Forte@Sun.COM 		p->len = len;
65717836SJohn.Forte@Sun.COM 		p->flag = flag;
65727836SJohn.Forte@Sun.COM 		p->index = index;
65737836SJohn.Forte@Sun.COM 		p->iostatus = s; /* overload */
65747836SJohn.Forte@Sun.COM 		/* set up seq later, in case thr create fails */
65757836SJohn.Forte@Sun.COM 	}
65767836SJohn.Forte@Sun.COM 	return (p);
65777836SJohn.Forte@Sun.COM }
65787836SJohn.Forte@Sun.COM 
65797836SJohn.Forte@Sun.COM /*
65807836SJohn.Forte@Sun.COM  * rdc_aio_buf_get
65817836SJohn.Forte@Sun.COM  * get an aio_buf
65827836SJohn.Forte@Sun.COM  */
65837836SJohn.Forte@Sun.COM aio_buf_t *
rdc_aio_buf_get(rdc_buf_t * h,int index)65847836SJohn.Forte@Sun.COM rdc_aio_buf_get(rdc_buf_t *h, int index)
65857836SJohn.Forte@Sun.COM {
65867836SJohn.Forte@Sun.COM 	aio_buf_t *p;
65877836SJohn.Forte@Sun.COM 
65887836SJohn.Forte@Sun.COM 	if (index >= rdc_max_sets) {
6589*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc: rdc_aio_buf_get bad index %x", index);
65907836SJohn.Forte@Sun.COM 		return (NULL);
65917836SJohn.Forte@Sun.COM 	}
65927836SJohn.Forte@Sun.COM 
65937836SJohn.Forte@Sun.COM 	mutex_enter(&h->aio_lock);
65947836SJohn.Forte@Sun.COM 
65957836SJohn.Forte@Sun.COM 	p = h->rdc_anon;
65967836SJohn.Forte@Sun.COM 	while (p && (p->kindex != index))
65977836SJohn.Forte@Sun.COM 		p = p->next;
65987836SJohn.Forte@Sun.COM 
65997836SJohn.Forte@Sun.COM 	mutex_exit(&h->aio_lock);
66007836SJohn.Forte@Sun.COM 	return (p);
66017836SJohn.Forte@Sun.COM }
66027836SJohn.Forte@Sun.COM 
66037836SJohn.Forte@Sun.COM /*
66047836SJohn.Forte@Sun.COM  * rdc_aio_buf_del
66057836SJohn.Forte@Sun.COM  * delete a aio_buf
66067836SJohn.Forte@Sun.COM  */
66077836SJohn.Forte@Sun.COM void
rdc_aio_buf_del(rdc_buf_t * h,rdc_k_info_t * krdc)66087836SJohn.Forte@Sun.COM rdc_aio_buf_del(rdc_buf_t *h, rdc_k_info_t *krdc)
66097836SJohn.Forte@Sun.COM {
66107836SJohn.Forte@Sun.COM 	aio_buf_t *p, **pp;
66117836SJohn.Forte@Sun.COM 
66127836SJohn.Forte@Sun.COM 	mutex_enter(&h->aio_lock);
66137836SJohn.Forte@Sun.COM 
66147836SJohn.Forte@Sun.COM 	p = NULL;
66157836SJohn.Forte@Sun.COM 	for (pp = &h->rdc_anon; *pp; pp = &((*pp)->next)) {
66167836SJohn.Forte@Sun.COM 		if ((*pp)->kindex == krdc->index) {
66177836SJohn.Forte@Sun.COM 			p = *pp;
66187836SJohn.Forte@Sun.COM 			break;
66197836SJohn.Forte@Sun.COM 		}
66207836SJohn.Forte@Sun.COM 	}
66217836SJohn.Forte@Sun.COM 
66227836SJohn.Forte@Sun.COM 	if (p) {
66237836SJohn.Forte@Sun.COM 		*pp = p->next;
66247836SJohn.Forte@Sun.COM 		kmem_free(p, sizeof (*p));
66257836SJohn.Forte@Sun.COM 	}
66267836SJohn.Forte@Sun.COM 	mutex_exit(&h->aio_lock);
66277836SJohn.Forte@Sun.COM }
66287836SJohn.Forte@Sun.COM 
66297836SJohn.Forte@Sun.COM /*
66307836SJohn.Forte@Sun.COM  * rdc_aio_buf_add
66317836SJohn.Forte@Sun.COM  * Add a aio_buf.
66327836SJohn.Forte@Sun.COM  */
66337836SJohn.Forte@Sun.COM aio_buf_t *
rdc_aio_buf_add(int index,rdc_buf_t * h)66347836SJohn.Forte@Sun.COM rdc_aio_buf_add(int index, rdc_buf_t *h)
66357836SJohn.Forte@Sun.COM {
66367836SJohn.Forte@Sun.COM 	aio_buf_t *p;
66377836SJohn.Forte@Sun.COM 
66387836SJohn.Forte@Sun.COM 	p = kmem_zalloc(sizeof (*p), KM_NOSLEEP);
66397836SJohn.Forte@Sun.COM 	if (p == NULL) {
6640*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_aio_buf_add: kmem_alloc failed");
66417836SJohn.Forte@Sun.COM 		return (NULL);
66427836SJohn.Forte@Sun.COM 	}
66437836SJohn.Forte@Sun.COM 
66447836SJohn.Forte@Sun.COM 	p->rdc_abufp = NULL;
66457836SJohn.Forte@Sun.COM 	p->kindex = index;
66467836SJohn.Forte@Sun.COM 
66477836SJohn.Forte@Sun.COM 	mutex_enter(&h->aio_lock);
66487836SJohn.Forte@Sun.COM 	p->next = h->rdc_anon;
66497836SJohn.Forte@Sun.COM 	h->rdc_anon = p;
66507836SJohn.Forte@Sun.COM 	mutex_exit(&h->aio_lock);
66517836SJohn.Forte@Sun.COM 	return (p);
66527836SJohn.Forte@Sun.COM }
66537836SJohn.Forte@Sun.COM 
66547836SJohn.Forte@Sun.COM /*
66557836SJohn.Forte@Sun.COM  * kmemalloc a new group structure and setup the common
66567836SJohn.Forte@Sun.COM  * fields.
66577836SJohn.Forte@Sun.COM  */
66587836SJohn.Forte@Sun.COM static rdc_group_t *
rdc_newgroup()66597836SJohn.Forte@Sun.COM rdc_newgroup()
66607836SJohn.Forte@Sun.COM {
66617836SJohn.Forte@Sun.COM 	rdc_group_t *group;
66627836SJohn.Forte@Sun.COM 
66637836SJohn.Forte@Sun.COM 	group = kmem_zalloc(sizeof (rdc_group_t), KM_SLEEP);
66647836SJohn.Forte@Sun.COM 	group->diskq.lastio = kmem_zalloc(sizeof (rdc_aio_t), KM_SLEEP);
66657836SJohn.Forte@Sun.COM 	group->count = 1;
66667836SJohn.Forte@Sun.COM 	group->seq = RDC_NEWSEQ;
66677836SJohn.Forte@Sun.COM 	group->seqack = RDC_NEWSEQ;
66687836SJohn.Forte@Sun.COM 	mutex_init(&group->lock, NULL, MUTEX_DRIVER, NULL);
66697836SJohn.Forte@Sun.COM 	mutex_init(&group->ra_queue.net_qlock, NULL, MUTEX_DRIVER, NULL);
66707836SJohn.Forte@Sun.COM 	mutex_init(&group->diskqmutex, NULL, MUTEX_DRIVER, NULL);
66717836SJohn.Forte@Sun.COM 	mutex_init(&group->diskq.disk_qlock, NULL, MUTEX_DRIVER, NULL);
66727836SJohn.Forte@Sun.COM 	mutex_init(&group->diskq.head_lock, NULL, MUTEX_DRIVER, NULL);
66737836SJohn.Forte@Sun.COM 	mutex_init(&group->addthrnumlk, NULL, MUTEX_DRIVER, NULL);
66747836SJohn.Forte@Sun.COM 	cv_init(&group->unregistercv, NULL, CV_DRIVER, NULL);
66757836SJohn.Forte@Sun.COM 	cv_init(&group->asyncqcv, NULL, CV_DRIVER, NULL);
66767836SJohn.Forte@Sun.COM 	cv_init(&group->diskq.busycv, NULL, CV_DRIVER, NULL);
66777836SJohn.Forte@Sun.COM 	cv_init(&group->diskq.qfullcv, NULL, CV_DRIVER, NULL);
66787836SJohn.Forte@Sun.COM 	cv_init(&group->ra_queue.qfcv, NULL, CV_DRIVER, NULL);
66797836SJohn.Forte@Sun.COM 	group->ra_queue.qfill_sleeping = RDC_QFILL_DEAD;
66807836SJohn.Forte@Sun.COM 	group->diskq.busycnt = 0;
66817836SJohn.Forte@Sun.COM 	ASSERT(group->synccount == 0);		/* group was kmem_zalloc'ed */
66827836SJohn.Forte@Sun.COM 
66837836SJohn.Forte@Sun.COM 	/*
66847836SJohn.Forte@Sun.COM 	 * add default number of threads to the flusher thread set, plus
66857836SJohn.Forte@Sun.COM 	 * one extra thread for the disk queue flusher
66867836SJohn.Forte@Sun.COM 	 */
66877836SJohn.Forte@Sun.COM 	if (nst_add_thread(_rdc_flset, 3) != 3)
6688*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_newgroup: nst_add_thread failed");
66897836SJohn.Forte@Sun.COM 
66907836SJohn.Forte@Sun.COM 	return (group);
66917836SJohn.Forte@Sun.COM }
66927836SJohn.Forte@Sun.COM 
66937836SJohn.Forte@Sun.COM void
rdc_delgroup(rdc_group_t * group)66947836SJohn.Forte@Sun.COM rdc_delgroup(rdc_group_t *group)
66957836SJohn.Forte@Sun.COM {
66967836SJohn.Forte@Sun.COM 
66977836SJohn.Forte@Sun.COM 	ASSERT(group->asyncstall == 0);
66987836SJohn.Forte@Sun.COM 	ASSERT(group->rdc_thrnum == 0);
66997836SJohn.Forte@Sun.COM 	ASSERT(group->count == 0);
67007836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&rdc_many_lock));
67017836SJohn.Forte@Sun.COM 
67027836SJohn.Forte@Sun.COM 	mutex_enter(&group->ra_queue.net_qlock);
67037836SJohn.Forte@Sun.COM 	rdc_sleepqdiscard(group);
67047836SJohn.Forte@Sun.COM 	mutex_exit(&group->ra_queue.net_qlock);
67057836SJohn.Forte@Sun.COM 
67067836SJohn.Forte@Sun.COM 	/* try to remove flusher threads that this group added to _rdc_flset */
67077836SJohn.Forte@Sun.COM 	if (nst_del_thread(_rdc_flset, group->rdc_addthrnum + 3) !=
67087836SJohn.Forte@Sun.COM 	    group->rdc_addthrnum + 3)
6709*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!rdc_delgroup: nst_del_thread failed");
67107836SJohn.Forte@Sun.COM 
67117836SJohn.Forte@Sun.COM 	mutex_destroy(&group->lock);
67127836SJohn.Forte@Sun.COM 	mutex_destroy(&group->ra_queue.net_qlock);
67137836SJohn.Forte@Sun.COM 	mutex_destroy(&group->diskqmutex);
67147836SJohn.Forte@Sun.COM 	mutex_destroy(&group->diskq.disk_qlock);
67157836SJohn.Forte@Sun.COM 	mutex_destroy(&group->diskq.head_lock);
67167836SJohn.Forte@Sun.COM 	mutex_destroy(&group->addthrnumlk);
67177836SJohn.Forte@Sun.COM 	cv_destroy(&group->unregistercv);
67187836SJohn.Forte@Sun.COM 	cv_destroy(&group->asyncqcv);
67197836SJohn.Forte@Sun.COM 	cv_destroy(&group->diskq.busycv);
67207836SJohn.Forte@Sun.COM 	cv_destroy(&group->diskq.qfullcv);
67217836SJohn.Forte@Sun.COM 	cv_destroy(&group->ra_queue.qfcv);
67227836SJohn.Forte@Sun.COM 	kmem_free(group->diskq.lastio, sizeof (rdc_aio_t));
67237836SJohn.Forte@Sun.COM 	kmem_free(group, sizeof (rdc_group_t));
67247836SJohn.Forte@Sun.COM }
6725