xref: /onnv-gate/usr/src/uts/common/avs/ns/rdc/rdc.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #define	_RDC_
27*7836SJohn.Forte@Sun.COM #include <sys/types.h>
28*7836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
29*7836SJohn.Forte@Sun.COM #include <sys/kmem.h>
30*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
31*7836SJohn.Forte@Sun.COM #include <sys/conf.h>
32*7836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
33*7836SJohn.Forte@Sun.COM #include <sys/modctl.h>
34*7836SJohn.Forte@Sun.COM #include <sys/cred.h>
35*7836SJohn.Forte@Sun.COM #include <sys/ddi.h>
36*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
37*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
38*7836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
39*7836SJohn.Forte@Sun.COM 
40*7836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
41*7836SJohn.Forte@Sun.COM #ifdef DS_DDICT
42*7836SJohn.Forte@Sun.COM #include "../contract.h"
43*7836SJohn.Forte@Sun.COM #endif
44*7836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
45*7836SJohn.Forte@Sun.COM #include <sys/nsctl/nsvers.h>
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM #include <sys/sdt.h>		/* dtrace is S10 or later */
48*7836SJohn.Forte@Sun.COM 
49*7836SJohn.Forte@Sun.COM #include "rdc.h"
50*7836SJohn.Forte@Sun.COM #include "rdc_io.h"
51*7836SJohn.Forte@Sun.COM #include "rdc_bitmap.h"
52*7836SJohn.Forte@Sun.COM #include "rdc_ioctl.h"
53*7836SJohn.Forte@Sun.COM #include "rdcsrv.h"
54*7836SJohn.Forte@Sun.COM #include "rdc_diskq.h"
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM #define	DIDINIT		0x01
57*7836SJohn.Forte@Sun.COM #define	DIDNODES	0x02
58*7836SJohn.Forte@Sun.COM #define	DIDCONFIG	0x04
59*7836SJohn.Forte@Sun.COM 
60*7836SJohn.Forte@Sun.COM static int rdcopen(dev_t *devp, int flag, int otyp, cred_t *crp);
61*7836SJohn.Forte@Sun.COM static int rdcclose(dev_t dev, int flag, int otyp, cred_t *crp);
62*7836SJohn.Forte@Sun.COM static int rdcprint(dev_t dev, char *str);
63*7836SJohn.Forte@Sun.COM static int rdcioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp,
64*7836SJohn.Forte@Sun.COM 	int *rvp);
65*7836SJohn.Forte@Sun.COM static int rdcattach(dev_info_t *dip, ddi_attach_cmd_t cmd);
66*7836SJohn.Forte@Sun.COM static int rdcdetach(dev_info_t *dip, ddi_detach_cmd_t cmd);
67*7836SJohn.Forte@Sun.COM static int rdcgetinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
68*7836SJohn.Forte@Sun.COM 	void **result);
69*7836SJohn.Forte@Sun.COM #ifdef	DEBUG
70*7836SJohn.Forte@Sun.COM static int rdc_clrkstat(void *);
71*7836SJohn.Forte@Sun.COM #endif
72*7836SJohn.Forte@Sun.COM 
73*7836SJohn.Forte@Sun.COM /*
74*7836SJohn.Forte@Sun.COM  * kstat interface
75*7836SJohn.Forte@Sun.COM  */
76*7836SJohn.Forte@Sun.COM static kstat_t *sndr_kstats;
77*7836SJohn.Forte@Sun.COM 
78*7836SJohn.Forte@Sun.COM int sndr_info_stats_update(kstat_t *ksp, int rw);
79*7836SJohn.Forte@Sun.COM 
80*7836SJohn.Forte@Sun.COM static sndr_m_stats_t sndr_info_stats = {
81*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_MAXSETS,			KSTAT_DATA_ULONG},
82*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_MAXFBAS,			KSTAT_DATA_ULONG},
83*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_RPC_TIMEOUT,		KSTAT_DATA_ULONG},
84*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_HEALTH_THRES,		KSTAT_DATA_ULONG},
85*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_BITMAP_WRITES,		KSTAT_DATA_ULONG},
86*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_CLNT_COTS_CALLS,		KSTAT_DATA_ULONG},
87*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_CLNT_CLTS_CALLS,		KSTAT_DATA_ULONG},
88*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_SVC_COTS_CALLS,		KSTAT_DATA_ULONG},
89*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_SVC_CLTS_CALLS,		KSTAT_DATA_ULONG},
90*7836SJohn.Forte@Sun.COM 	{RDC_MKSTAT_BITMAP_REF_DELAY,		KSTAT_DATA_ULONG}
91*7836SJohn.Forte@Sun.COM };
92*7836SJohn.Forte@Sun.COM 
93*7836SJohn.Forte@Sun.COM int rdc_info_stats_update(kstat_t *ksp, int rw);
94*7836SJohn.Forte@Sun.COM 
95*7836SJohn.Forte@Sun.COM static rdc_info_stats_t rdc_info_stats = {
96*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_FLAGS,		KSTAT_DATA_ULONG},
97*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_SYNCFLAGS,		KSTAT_DATA_ULONG},
98*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_BMPFLAGS,		KSTAT_DATA_ULONG},
99*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_SYNCPOS,		KSTAT_DATA_ULONG},
100*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_VOLSIZE,		KSTAT_DATA_ULONG},
101*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_BITSSET,		KSTAT_DATA_ULONG},
102*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_AUTOSYNC,		KSTAT_DATA_ULONG},
103*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_MAXQFBAS,		KSTAT_DATA_ULONG},
104*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_MAXQITEMS,		KSTAT_DATA_ULONG},
105*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_FILE,		KSTAT_DATA_STRING},
106*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_SECFILE,		KSTAT_DATA_STRING},
107*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_BITMAP,		KSTAT_DATA_STRING},
108*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_PRIMARY_HOST,	KSTAT_DATA_STRING},
109*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_SECONDARY_HOST,	KSTAT_DATA_STRING},
110*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_TYPE_FLAG,		KSTAT_DATA_ULONG},
111*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_BMP_SIZE,		KSTAT_DATA_ULONG},
112*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_DISK_STATUS,	KSTAT_DATA_ULONG},
113*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_IF_DOWN,		KSTAT_DATA_ULONG},
114*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_IF_RPC_VERSION,	KSTAT_DATA_ULONG},
115*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_ASYNC_BLOCK_HWM,	KSTAT_DATA_ULONG},
116*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_ASYNC_ITEM_HWM,	KSTAT_DATA_ULONG},
117*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_ASYNC_THROTTLE_DELAY,	KSTAT_DATA_ULONG},
118*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_ASYNC_ITEMS,	KSTAT_DATA_ULONG},
119*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_ASYNC_BLOCKS,	KSTAT_DATA_ULONG},
120*7836SJohn.Forte@Sun.COM 	{RDC_IKSTAT_QUEUE_TYPE,		KSTAT_DATA_CHAR}
121*7836SJohn.Forte@Sun.COM };
122*7836SJohn.Forte@Sun.COM 
123*7836SJohn.Forte@Sun.COM static struct cb_ops rdc_cb_ops = {
124*7836SJohn.Forte@Sun.COM 	rdcopen,
125*7836SJohn.Forte@Sun.COM 	rdcclose,
126*7836SJohn.Forte@Sun.COM 	nulldev,		/* no strategy */
127*7836SJohn.Forte@Sun.COM 	rdcprint,
128*7836SJohn.Forte@Sun.COM 	nodev,			/* no dump */
129*7836SJohn.Forte@Sun.COM 	nodev,			/* no read */
130*7836SJohn.Forte@Sun.COM 	nodev,			/* no write */
131*7836SJohn.Forte@Sun.COM 	rdcioctl,
132*7836SJohn.Forte@Sun.COM 	nodev,			/* no devmap */
133*7836SJohn.Forte@Sun.COM 	nodev,			/* no mmap */
134*7836SJohn.Forte@Sun.COM 	nodev,			/* no segmap */
135*7836SJohn.Forte@Sun.COM 	nochpoll,
136*7836SJohn.Forte@Sun.COM 	ddi_prop_op,
137*7836SJohn.Forte@Sun.COM 	NULL,			/* not STREAMS */
138*7836SJohn.Forte@Sun.COM 	D_NEW | D_MP | D_64BIT,
139*7836SJohn.Forte@Sun.COM 	CB_REV,
140*7836SJohn.Forte@Sun.COM 	nodev,			/* no aread */
141*7836SJohn.Forte@Sun.COM 	nodev,			/* no awrite */
142*7836SJohn.Forte@Sun.COM };
143*7836SJohn.Forte@Sun.COM 
144*7836SJohn.Forte@Sun.COM static struct dev_ops rdc_ops = {
145*7836SJohn.Forte@Sun.COM 	DEVO_REV,
146*7836SJohn.Forte@Sun.COM 	0,
147*7836SJohn.Forte@Sun.COM 	rdcgetinfo,
148*7836SJohn.Forte@Sun.COM 	nulldev,		/* identify */
149*7836SJohn.Forte@Sun.COM 	nulldev,		/* probe */
150*7836SJohn.Forte@Sun.COM 	rdcattach,
151*7836SJohn.Forte@Sun.COM 	rdcdetach,
152*7836SJohn.Forte@Sun.COM 	nodev,			/* no reset */
153*7836SJohn.Forte@Sun.COM 	&rdc_cb_ops,
154*7836SJohn.Forte@Sun.COM 	(struct bus_ops *)NULL
155*7836SJohn.Forte@Sun.COM };
156*7836SJohn.Forte@Sun.COM 
157*7836SJohn.Forte@Sun.COM static struct modldrv rdc_ldrv = {
158*7836SJohn.Forte@Sun.COM 	&mod_driverops,
159*7836SJohn.Forte@Sun.COM 	"nws:Remote Mirror:" ISS_VERSION_STR,
160*7836SJohn.Forte@Sun.COM 	&rdc_ops
161*7836SJohn.Forte@Sun.COM };
162*7836SJohn.Forte@Sun.COM 
163*7836SJohn.Forte@Sun.COM static struct modlinkage rdc_modlinkage = {
164*7836SJohn.Forte@Sun.COM 	MODREV_1,
165*7836SJohn.Forte@Sun.COM 	&rdc_ldrv,
166*7836SJohn.Forte@Sun.COM 	NULL
167*7836SJohn.Forte@Sun.COM };
168*7836SJohn.Forte@Sun.COM 
169*7836SJohn.Forte@Sun.COM const	int sndr_major_rev = ISS_VERSION_MAJ;
170*7836SJohn.Forte@Sun.COM const	int sndr_minor_rev = ISS_VERSION_MIN;
171*7836SJohn.Forte@Sun.COM const	int sndr_micro_rev = ISS_VERSION_MIC;
172*7836SJohn.Forte@Sun.COM const	int sndr_baseline_rev = ISS_VERSION_NUM;
173*7836SJohn.Forte@Sun.COM static	char sndr_version[16];
174*7836SJohn.Forte@Sun.COM 
175*7836SJohn.Forte@Sun.COM static void *rdc_dip;
176*7836SJohn.Forte@Sun.COM 
177*7836SJohn.Forte@Sun.COM extern int _rdc_init_dev();
178*7836SJohn.Forte@Sun.COM extern void _rdc_deinit_dev();
179*7836SJohn.Forte@Sun.COM extern void rdc_link_down_free();
180*7836SJohn.Forte@Sun.COM 
181*7836SJohn.Forte@Sun.COM int rdc_bitmap_mode;
182*7836SJohn.Forte@Sun.COM int rdc_auto_sync;
183*7836SJohn.Forte@Sun.COM int rdc_max_sets;
184*7836SJohn.Forte@Sun.COM extern int rdc_health_thres;
185*7836SJohn.Forte@Sun.COM 
186*7836SJohn.Forte@Sun.COM static const char rdc_built[] = "@(#) rdc: built " __TIME__ " " __DATE__;
187*7836SJohn.Forte@Sun.COM 
188*7836SJohn.Forte@Sun.COM kmutex_t rdc_sync_mutex;
189*7836SJohn.Forte@Sun.COM rdc_sync_event_t rdc_sync_event;
190*7836SJohn.Forte@Sun.COM clock_t rdc_sync_event_timeout;
191*7836SJohn.Forte@Sun.COM 
192*7836SJohn.Forte@Sun.COM static void
193*7836SJohn.Forte@Sun.COM rdc_sync_event_init()
194*7836SJohn.Forte@Sun.COM {
195*7836SJohn.Forte@Sun.COM 	mutex_init(&rdc_sync_mutex, NULL, MUTEX_DRIVER, NULL);
196*7836SJohn.Forte@Sun.COM 	mutex_init(&rdc_sync_event.mutex, NULL, MUTEX_DRIVER, NULL);
197*7836SJohn.Forte@Sun.COM 	cv_init(&rdc_sync_event.cv, NULL, CV_DRIVER, NULL);
198*7836SJohn.Forte@Sun.COM 	cv_init(&rdc_sync_event.done_cv, NULL, CV_DRIVER, NULL);
199*7836SJohn.Forte@Sun.COM 	rdc_sync_event.master[0] = 0;
200*7836SJohn.Forte@Sun.COM 	rdc_sync_event.lbolt = (clock_t)0;
201*7836SJohn.Forte@Sun.COM 	rdc_sync_event_timeout = RDC_SYNC_EVENT_TIMEOUT;
202*7836SJohn.Forte@Sun.COM }
203*7836SJohn.Forte@Sun.COM 
204*7836SJohn.Forte@Sun.COM 
205*7836SJohn.Forte@Sun.COM static void
206*7836SJohn.Forte@Sun.COM rdc_sync_event_destroy()
207*7836SJohn.Forte@Sun.COM {
208*7836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_sync_mutex);
209*7836SJohn.Forte@Sun.COM 	mutex_destroy(&rdc_sync_event.mutex);
210*7836SJohn.Forte@Sun.COM 	cv_destroy(&rdc_sync_event.cv);
211*7836SJohn.Forte@Sun.COM 	cv_destroy(&rdc_sync_event.done_cv);
212*7836SJohn.Forte@Sun.COM }
213*7836SJohn.Forte@Sun.COM 
214*7836SJohn.Forte@Sun.COM 
215*7836SJohn.Forte@Sun.COM 
216*7836SJohn.Forte@Sun.COM int
217*7836SJohn.Forte@Sun.COM _init(void)
218*7836SJohn.Forte@Sun.COM {
219*7836SJohn.Forte@Sun.COM 	return (mod_install(&rdc_modlinkage));
220*7836SJohn.Forte@Sun.COM }
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM int
223*7836SJohn.Forte@Sun.COM _fini(void)
224*7836SJohn.Forte@Sun.COM {
225*7836SJohn.Forte@Sun.COM 	return (mod_remove(&rdc_modlinkage));
226*7836SJohn.Forte@Sun.COM }
227*7836SJohn.Forte@Sun.COM 
228*7836SJohn.Forte@Sun.COM int
229*7836SJohn.Forte@Sun.COM _info(struct modinfo *modinfop)
230*7836SJohn.Forte@Sun.COM {
231*7836SJohn.Forte@Sun.COM 	return (mod_info(&rdc_modlinkage, modinfop));
232*7836SJohn.Forte@Sun.COM }
233*7836SJohn.Forte@Sun.COM 
234*7836SJohn.Forte@Sun.COM static int
235*7836SJohn.Forte@Sun.COM rdcattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
236*7836SJohn.Forte@Sun.COM {
237*7836SJohn.Forte@Sun.COM 	intptr_t flags;
238*7836SJohn.Forte@Sun.COM 	int instance;
239*7836SJohn.Forte@Sun.COM 	int i;
240*7836SJohn.Forte@Sun.COM 
241*7836SJohn.Forte@Sun.COM 	/*CONSTCOND*/
242*7836SJohn.Forte@Sun.COM 	ASSERT(sizeof (u_longlong_t) == 8);
243*7836SJohn.Forte@Sun.COM 
244*7836SJohn.Forte@Sun.COM 	if (cmd != DDI_ATTACH)
245*7836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
246*7836SJohn.Forte@Sun.COM 
247*7836SJohn.Forte@Sun.COM 	cmn_err(CE_CONT, "!%s\n", rdc_built);
248*7836SJohn.Forte@Sun.COM 
249*7836SJohn.Forte@Sun.COM 	(void) strncpy(sndr_version, _VERSION_, sizeof (sndr_version));
250*7836SJohn.Forte@Sun.COM 
251*7836SJohn.Forte@Sun.COM #ifdef DEBUG
252*7836SJohn.Forte@Sun.COM 	cmn_err(CE_NOTE, "SNDR: initializing version %d.%d  %s", sndr_major_rev,
253*7836SJohn.Forte@Sun.COM 		sndr_minor_rev, sndr_version);
254*7836SJohn.Forte@Sun.COM #endif
255*7836SJohn.Forte@Sun.COM 	instance = ddi_get_instance(dip);
256*7836SJohn.Forte@Sun.COM 	rdc_dip = dip;
257*7836SJohn.Forte@Sun.COM 
258*7836SJohn.Forte@Sun.COM 	flags = 0;
259*7836SJohn.Forte@Sun.COM 
260*7836SJohn.Forte@Sun.COM 	rdc_sync_event_init();
261*7836SJohn.Forte@Sun.COM 
262*7836SJohn.Forte@Sun.COM 	/*
263*7836SJohn.Forte@Sun.COM 	 * rdc_max_sets must be set before calling _rdc_load().
264*7836SJohn.Forte@Sun.COM 	 */
265*7836SJohn.Forte@Sun.COM 
266*7836SJohn.Forte@Sun.COM 	rdc_max_sets = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
267*7836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "rdc_max_sets", 64);
268*7836SJohn.Forte@Sun.COM 
269*7836SJohn.Forte@Sun.COM 	if (_rdc_init_dev()) {
270*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "rdc: _rdc_init_dev failed");
271*7836SJohn.Forte@Sun.COM 		goto out;
272*7836SJohn.Forte@Sun.COM 	}
273*7836SJohn.Forte@Sun.COM 	flags |= DIDINIT;
274*7836SJohn.Forte@Sun.COM 
275*7836SJohn.Forte@Sun.COM 	if (_rdc_load() != 0) {
276*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "rdc: _rdc_load failed");
277*7836SJohn.Forte@Sun.COM 		goto out;
278*7836SJohn.Forte@Sun.COM 	}
279*7836SJohn.Forte@Sun.COM 
280*7836SJohn.Forte@Sun.COM 	if (_rdc_configure()) {
281*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "rdc: _rdc_configure failed");
282*7836SJohn.Forte@Sun.COM 		goto out;
283*7836SJohn.Forte@Sun.COM 	}
284*7836SJohn.Forte@Sun.COM 	flags |= DIDCONFIG;
285*7836SJohn.Forte@Sun.COM 
286*7836SJohn.Forte@Sun.COM 	if (ddi_create_minor_node(dip, "rdc", S_IFCHR, instance, DDI_PSEUDO, 0)
287*7836SJohn.Forte@Sun.COM 		    != DDI_SUCCESS) {
288*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "rdc: could not create node.");
289*7836SJohn.Forte@Sun.COM 		goto out;
290*7836SJohn.Forte@Sun.COM 	}
291*7836SJohn.Forte@Sun.COM 	flags |= DIDNODES;
292*7836SJohn.Forte@Sun.COM 
293*7836SJohn.Forte@Sun.COM 	rdc_bitmap_mode = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
294*7836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
295*7836SJohn.Forte@Sun.COM 	    "rdc_bitmap_mode", 0);
296*7836SJohn.Forte@Sun.COM 
297*7836SJohn.Forte@Sun.COM 	switch (rdc_bitmap_mode) {
298*7836SJohn.Forte@Sun.COM 	case RDC_BMP_AUTO:		/* 0 */
299*7836SJohn.Forte@Sun.COM 		break;
300*7836SJohn.Forte@Sun.COM 	case RDC_BMP_ALWAYS:		/* 1 */
301*7836SJohn.Forte@Sun.COM #ifdef DEBUG
302*7836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE, "SNDR bitmap mode override");
303*7836SJohn.Forte@Sun.COM 		cmn_err(CE_CONT,
304*7836SJohn.Forte@Sun.COM 			"SNDR: bitmaps will be written for every write I/O\n");
305*7836SJohn.Forte@Sun.COM #endif
306*7836SJohn.Forte@Sun.COM 		break;
307*7836SJohn.Forte@Sun.COM 	case RDC_BMP_NEVER:		/* 2 */
308*7836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE, "SNDR bitmap mode override");
309*7836SJohn.Forte@Sun.COM 		cmn_err(CE_CONT,
310*7836SJohn.Forte@Sun.COM 			"SNDR: bitmaps will only be written on shutdown\n");
311*7836SJohn.Forte@Sun.COM 		break;
312*7836SJohn.Forte@Sun.COM 	default:			/* unknown */
313*7836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
314*7836SJohn.Forte@Sun.COM 			"SNDR: unknown bitmap mode %d - autodetecting mode",
315*7836SJohn.Forte@Sun.COM 			rdc_bitmap_mode);
316*7836SJohn.Forte@Sun.COM 		rdc_bitmap_mode = RDC_BMP_AUTO;
317*7836SJohn.Forte@Sun.COM 		break;
318*7836SJohn.Forte@Sun.COM 	}
319*7836SJohn.Forte@Sun.COM 
320*7836SJohn.Forte@Sun.COM 	rdc_bitmap_init();
321*7836SJohn.Forte@Sun.COM 
322*7836SJohn.Forte@Sun.COM 	rdc_auto_sync = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
323*7836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
324*7836SJohn.Forte@Sun.COM 	    "rdc_auto_sync", 0);
325*7836SJohn.Forte@Sun.COM 
326*7836SJohn.Forte@Sun.COM 	i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
327*7836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
328*7836SJohn.Forte@Sun.COM 	    "rdc_health_thres", RDC_HEALTH_THRESHOLD);
329*7836SJohn.Forte@Sun.COM 	if (i >= RDC_MIN_HEALTH_THRES)
330*7836SJohn.Forte@Sun.COM 		rdc_health_thres = i;
331*7836SJohn.Forte@Sun.COM 	else
332*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "value rdc_heath_thres from rdc.conf ignored "
333*7836SJohn.Forte@Sun.COM 		    "as it is smaller than the min value of %d",
334*7836SJohn.Forte@Sun.COM 		    RDC_MIN_HEALTH_THRES);
335*7836SJohn.Forte@Sun.COM 
336*7836SJohn.Forte@Sun.COM 	ddi_set_driver_private(dip, (caddr_t)flags);
337*7836SJohn.Forte@Sun.COM 	ddi_report_dev(dip);
338*7836SJohn.Forte@Sun.COM 
339*7836SJohn.Forte@Sun.COM 	sndr_kstats = kstat_create(RDC_KSTAT_MODULE, 0,
340*7836SJohn.Forte@Sun.COM 	    RDC_KSTAT_MINFO, RDC_KSTAT_CLASS, KSTAT_TYPE_NAMED,
341*7836SJohn.Forte@Sun.COM 	    sizeof (sndr_m_stats_t) / sizeof (kstat_named_t),
342*7836SJohn.Forte@Sun.COM 	    KSTAT_FLAG_VIRTUAL);
343*7836SJohn.Forte@Sun.COM 
344*7836SJohn.Forte@Sun.COM 	if (sndr_kstats) {
345*7836SJohn.Forte@Sun.COM 		sndr_kstats->ks_data = &sndr_info_stats;
346*7836SJohn.Forte@Sun.COM 		sndr_kstats->ks_update = sndr_info_stats_update;
347*7836SJohn.Forte@Sun.COM 		sndr_kstats->ks_private = &rdc_k_info[0];
348*7836SJohn.Forte@Sun.COM 		kstat_install(sndr_kstats);
349*7836SJohn.Forte@Sun.COM 	} else
350*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN, "SNDR: module kstats failed");
351*7836SJohn.Forte@Sun.COM 
352*7836SJohn.Forte@Sun.COM 	return (DDI_SUCCESS);
353*7836SJohn.Forte@Sun.COM 
354*7836SJohn.Forte@Sun.COM out:
355*7836SJohn.Forte@Sun.COM 	DTRACE_PROBE(rdc_attach_failed);
356*7836SJohn.Forte@Sun.COM 	ddi_set_driver_private(dip, (caddr_t)flags);
357*7836SJohn.Forte@Sun.COM 	(void) rdcdetach(dip, DDI_DETACH);
358*7836SJohn.Forte@Sun.COM 	return (DDI_FAILURE);
359*7836SJohn.Forte@Sun.COM }
360*7836SJohn.Forte@Sun.COM 
361*7836SJohn.Forte@Sun.COM static int
362*7836SJohn.Forte@Sun.COM rdcdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
363*7836SJohn.Forte@Sun.COM {
364*7836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
365*7836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
366*7836SJohn.Forte@Sun.COM 	int rdcd;
367*7836SJohn.Forte@Sun.COM 	intptr_t flags;
368*7836SJohn.Forte@Sun.COM 
369*7836SJohn.Forte@Sun.COM 
370*7836SJohn.Forte@Sun.COM 	if (cmd != DDI_DETACH) {
371*7836SJohn.Forte@Sun.COM 		DTRACE_PROBE(rdc_detach_unknown_cmd);
372*7836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
373*7836SJohn.Forte@Sun.COM 	}
374*7836SJohn.Forte@Sun.COM 
375*7836SJohn.Forte@Sun.COM 	if (rdc_k_info == NULL || rdc_u_info == NULL)
376*7836SJohn.Forte@Sun.COM 		goto cleanup;
377*7836SJohn.Forte@Sun.COM 
378*7836SJohn.Forte@Sun.COM 	mutex_enter(&rdc_conf_lock);
379*7836SJohn.Forte@Sun.COM 
380*7836SJohn.Forte@Sun.COM 	for (rdcd = 0; rdcd < rdc_max_sets; rdcd++) {
381*7836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[rdcd];
382*7836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[rdcd];
383*7836SJohn.Forte@Sun.COM 
384*7836SJohn.Forte@Sun.COM 		if (IS_ENABLED(urdc) || krdc->devices) {
385*7836SJohn.Forte@Sun.COM #ifdef DEBUG
386*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
387*7836SJohn.Forte@Sun.COM 			    "!rdc: cannot detach, rdcd %d still in use", rdcd);
388*7836SJohn.Forte@Sun.COM #endif
389*7836SJohn.Forte@Sun.COM 			mutex_exit(&rdc_conf_lock);
390*7836SJohn.Forte@Sun.COM 			DTRACE_PROBE(rdc_detach_err_busy);
391*7836SJohn.Forte@Sun.COM 			return (DDI_FAILURE);
392*7836SJohn.Forte@Sun.COM 		}
393*7836SJohn.Forte@Sun.COM 	}
394*7836SJohn.Forte@Sun.COM 
395*7836SJohn.Forte@Sun.COM 	mutex_exit(&rdc_conf_lock);
396*7836SJohn.Forte@Sun.COM 
397*7836SJohn.Forte@Sun.COM cleanup:
398*7836SJohn.Forte@Sun.COM 	flags = (intptr_t)ddi_get_driver_private(dip);
399*7836SJohn.Forte@Sun.COM 
400*7836SJohn.Forte@Sun.COM 	if (flags & DIDNODES)
401*7836SJohn.Forte@Sun.COM 		ddi_remove_minor_node(dip, NULL);
402*7836SJohn.Forte@Sun.COM 
403*7836SJohn.Forte@Sun.COM 	if (sndr_kstats) {
404*7836SJohn.Forte@Sun.COM 		kstat_delete(sndr_kstats);
405*7836SJohn.Forte@Sun.COM 	}
406*7836SJohn.Forte@Sun.COM 	if (flags & DIDINIT)
407*7836SJohn.Forte@Sun.COM 		_rdc_deinit_dev();
408*7836SJohn.Forte@Sun.COM 
409*7836SJohn.Forte@Sun.COM 	if (flags & DIDCONFIG) {
410*7836SJohn.Forte@Sun.COM 		(void) _rdc_deconfigure();
411*7836SJohn.Forte@Sun.COM 		(void) _rdc_unload();
412*7836SJohn.Forte@Sun.COM 		rdcsrv_unload();
413*7836SJohn.Forte@Sun.COM 	}
414*7836SJohn.Forte@Sun.COM 
415*7836SJohn.Forte@Sun.COM 	rdc_sync_event_destroy();
416*7836SJohn.Forte@Sun.COM 	rdc_link_down_free();
417*7836SJohn.Forte@Sun.COM 
418*7836SJohn.Forte@Sun.COM 	rdc_dip = NULL;
419*7836SJohn.Forte@Sun.COM 	return (DDI_SUCCESS);
420*7836SJohn.Forte@Sun.COM }
421*7836SJohn.Forte@Sun.COM 
422*7836SJohn.Forte@Sun.COM /* ARGSUSED */
423*7836SJohn.Forte@Sun.COM static int
424*7836SJohn.Forte@Sun.COM rdcgetinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
425*7836SJohn.Forte@Sun.COM {
426*7836SJohn.Forte@Sun.COM 	int rc = DDI_FAILURE;
427*7836SJohn.Forte@Sun.COM 
428*7836SJohn.Forte@Sun.COM 	switch (infocmd) {
429*7836SJohn.Forte@Sun.COM 
430*7836SJohn.Forte@Sun.COM 	case DDI_INFO_DEVT2DEVINFO:
431*7836SJohn.Forte@Sun.COM 		*result = rdc_dip;
432*7836SJohn.Forte@Sun.COM 		rc = DDI_SUCCESS;
433*7836SJohn.Forte@Sun.COM 		break;
434*7836SJohn.Forte@Sun.COM 
435*7836SJohn.Forte@Sun.COM 	case DDI_INFO_DEVT2INSTANCE:
436*7836SJohn.Forte@Sun.COM 		/* We only have a single instance */
437*7836SJohn.Forte@Sun.COM 		*result = 0;
438*7836SJohn.Forte@Sun.COM 		rc = DDI_SUCCESS;
439*7836SJohn.Forte@Sun.COM 		break;
440*7836SJohn.Forte@Sun.COM 
441*7836SJohn.Forte@Sun.COM 	default:
442*7836SJohn.Forte@Sun.COM 		break;
443*7836SJohn.Forte@Sun.COM 	}
444*7836SJohn.Forte@Sun.COM 
445*7836SJohn.Forte@Sun.COM 	return (rc);
446*7836SJohn.Forte@Sun.COM }
447*7836SJohn.Forte@Sun.COM 
448*7836SJohn.Forte@Sun.COM 
449*7836SJohn.Forte@Sun.COM /* ARGSUSED */
450*7836SJohn.Forte@Sun.COM 
451*7836SJohn.Forte@Sun.COM static int
452*7836SJohn.Forte@Sun.COM rdcopen(dev_t *devp, int flag, int otyp, cred_t *crp)
453*7836SJohn.Forte@Sun.COM {
454*7836SJohn.Forte@Sun.COM 	return (0);
455*7836SJohn.Forte@Sun.COM }
456*7836SJohn.Forte@Sun.COM 
457*7836SJohn.Forte@Sun.COM 
458*7836SJohn.Forte@Sun.COM /* ARGSUSED */
459*7836SJohn.Forte@Sun.COM 
460*7836SJohn.Forte@Sun.COM static int
461*7836SJohn.Forte@Sun.COM rdcclose(dev_t dev, int flag, int otyp, cred_t *crp)
462*7836SJohn.Forte@Sun.COM {
463*7836SJohn.Forte@Sun.COM 	return (0);
464*7836SJohn.Forte@Sun.COM }
465*7836SJohn.Forte@Sun.COM 
466*7836SJohn.Forte@Sun.COM /* ARGSUSED */
467*7836SJohn.Forte@Sun.COM 
468*7836SJohn.Forte@Sun.COM static int
469*7836SJohn.Forte@Sun.COM rdcprint(dev_t dev, char *str)
470*7836SJohn.Forte@Sun.COM {
471*7836SJohn.Forte@Sun.COM 	int instance = 0;
472*7836SJohn.Forte@Sun.COM 
473*7836SJohn.Forte@Sun.COM 	cmn_err(CE_WARN, "rdc%d: %s", instance, str);
474*7836SJohn.Forte@Sun.COM 	return (0);
475*7836SJohn.Forte@Sun.COM }
476*7836SJohn.Forte@Sun.COM 
477*7836SJohn.Forte@Sun.COM 
478*7836SJohn.Forte@Sun.COM static int
479*7836SJohn.Forte@Sun.COM convert_ioctl_args(int cmd, intptr_t arg, int mode, _rdc_ioctl_t *args)
480*7836SJohn.Forte@Sun.COM {
481*7836SJohn.Forte@Sun.COM 	_rdc_ioctl32_t args32;
482*7836SJohn.Forte@Sun.COM 
483*7836SJohn.Forte@Sun.COM 	if (ddi_copyin((void *)arg, &args32, sizeof (_rdc_ioctl32_t), mode))
484*7836SJohn.Forte@Sun.COM 		return (EFAULT);
485*7836SJohn.Forte@Sun.COM 
486*7836SJohn.Forte@Sun.COM 	bzero((void *)args, sizeof (_rdc_ioctl_t));
487*7836SJohn.Forte@Sun.COM 
488*7836SJohn.Forte@Sun.COM 	switch (cmd) {
489*7836SJohn.Forte@Sun.COM 	case RDC_CONFIG:
490*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* _rdc_config_t * */
491*7836SJohn.Forte@Sun.COM 		args->arg1 = (uint32_t)args32.arg1; /* pointer */
492*7836SJohn.Forte@Sun.COM 		args->arg2 = (uint32_t)args32.arg2; /* size */
493*7836SJohn.Forte@Sun.COM 		args->ustatus = (spcs_s_info_t)args32.ustatus;
494*7836SJohn.Forte@Sun.COM 		break;
495*7836SJohn.Forte@Sun.COM 
496*7836SJohn.Forte@Sun.COM 	case RDC_STATUS:
497*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* pointer */
498*7836SJohn.Forte@Sun.COM 		args->ustatus = (spcs_s_info_t)args32.ustatus;
499*7836SJohn.Forte@Sun.COM 		break;
500*7836SJohn.Forte@Sun.COM 
501*7836SJohn.Forte@Sun.COM 	case RDC_ENABLE_SVR:
502*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* _rdc_svc_args *  */
503*7836SJohn.Forte@Sun.COM 		break;
504*7836SJohn.Forte@Sun.COM 
505*7836SJohn.Forte@Sun.COM 	case RDC_VERSION:
506*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* _rdc_version_t *  */
507*7836SJohn.Forte@Sun.COM 		args->ustatus = (spcs_s_info_t)args32.ustatus;
508*7836SJohn.Forte@Sun.COM 		break;
509*7836SJohn.Forte@Sun.COM 
510*7836SJohn.Forte@Sun.COM 	case RDC_SYNC_EVENT:
511*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* char *  */
512*7836SJohn.Forte@Sun.COM 		args->arg1 = (uint32_t)args32.arg1; /* char *  */
513*7836SJohn.Forte@Sun.COM 		args->ustatus = (spcs_s_info_t)args32.ustatus;
514*7836SJohn.Forte@Sun.COM 		break;
515*7836SJohn.Forte@Sun.COM 
516*7836SJohn.Forte@Sun.COM 	case RDC_LINK_DOWN:
517*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* char *  */
518*7836SJohn.Forte@Sun.COM 		args->ustatus = (spcs_s_info_t)args32.ustatus;
519*7836SJohn.Forte@Sun.COM 		break;
520*7836SJohn.Forte@Sun.COM 	case RDC_POOL_CREATE:
521*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* svcpool_args *  */
522*7836SJohn.Forte@Sun.COM 		break;
523*7836SJohn.Forte@Sun.COM 	case RDC_POOL_WAIT:
524*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* int */
525*7836SJohn.Forte@Sun.COM 		break;
526*7836SJohn.Forte@Sun.COM 	case RDC_POOL_RUN:
527*7836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* int */
528*7836SJohn.Forte@Sun.COM 		break;
529*7836SJohn.Forte@Sun.COM 
530*7836SJohn.Forte@Sun.COM 	default:
531*7836SJohn.Forte@Sun.COM 		return (EINVAL);
532*7836SJohn.Forte@Sun.COM 	}
533*7836SJohn.Forte@Sun.COM 
534*7836SJohn.Forte@Sun.COM 	return (0);
535*7836SJohn.Forte@Sun.COM }
536*7836SJohn.Forte@Sun.COM 
537*7836SJohn.Forte@Sun.COM 
538*7836SJohn.Forte@Sun.COM /*
539*7836SJohn.Forte@Sun.COM  * Yet another standard thing that is not standard ...
540*7836SJohn.Forte@Sun.COM  */
541*7836SJohn.Forte@Sun.COM #ifndef	offsetof
542*7836SJohn.Forte@Sun.COM #define	offsetof(s, m)	((size_t)(&((s *)0)->m))
543*7836SJohn.Forte@Sun.COM #endif
544*7836SJohn.Forte@Sun.COM 
545*7836SJohn.Forte@Sun.COM /*
546*7836SJohn.Forte@Sun.COM  * Build a 32bit rdc_set structure and copyout to the user level.
547*7836SJohn.Forte@Sun.COM  */
548*7836SJohn.Forte@Sun.COM int
549*7836SJohn.Forte@Sun.COM rdc_status_copy32(const void *arg, void *usetp, size_t size, int mode)
550*7836SJohn.Forte@Sun.COM {
551*7836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = (rdc_u_info_t *)arg;
552*7836SJohn.Forte@Sun.COM 	struct rdc_set32 set32;
553*7836SJohn.Forte@Sun.COM 	size_t tailsize;
554*7836SJohn.Forte@Sun.COM #ifdef DEBUG
555*7836SJohn.Forte@Sun.COM 	size_t tailsize32;
556*7836SJohn.Forte@Sun.COM #endif
557*7836SJohn.Forte@Sun.COM 
558*7836SJohn.Forte@Sun.COM 	bzero(&set32, sizeof (set32));
559*7836SJohn.Forte@Sun.COM 
560*7836SJohn.Forte@Sun.COM 	tailsize = sizeof (struct rdc_addr32) -
561*7836SJohn.Forte@Sun.COM 		offsetof(struct rdc_addr32, intf);
562*7836SJohn.Forte@Sun.COM 
563*7836SJohn.Forte@Sun.COM 	/* primary address structure, avoiding netbuf */
564*7836SJohn.Forte@Sun.COM 	bcopy(&urdc->primary.intf[0], &set32.primary.intf[0], tailsize);
565*7836SJohn.Forte@Sun.COM 
566*7836SJohn.Forte@Sun.COM 	/* secondary address structure, avoiding netbuf */
567*7836SJohn.Forte@Sun.COM 	bcopy(&urdc->secondary.intf[0], &set32.secondary.intf[0], tailsize);
568*7836SJohn.Forte@Sun.COM 
569*7836SJohn.Forte@Sun.COM 	/*
570*7836SJohn.Forte@Sun.COM 	 * the rest, avoiding netconfig
571*7836SJohn.Forte@Sun.COM 	 * note: the tail must be the same size in both structures
572*7836SJohn.Forte@Sun.COM 	 */
573*7836SJohn.Forte@Sun.COM 	tailsize = sizeof (struct rdc_set) - offsetof(struct rdc_set, flags);
574*7836SJohn.Forte@Sun.COM #ifdef DEBUG
575*7836SJohn.Forte@Sun.COM 	/*
576*7836SJohn.Forte@Sun.COM 	 * ASSERT is calling for debug reason, and tailsize32 is only declared
577*7836SJohn.Forte@Sun.COM 	 * for ASSERT, put them under debug to avoid lint warning.
578*7836SJohn.Forte@Sun.COM 	 */
579*7836SJohn.Forte@Sun.COM 	tailsize32 = sizeof (struct rdc_set32) -
580*7836SJohn.Forte@Sun.COM 		offsetof(struct rdc_set32, flags);
581*7836SJohn.Forte@Sun.COM 	ASSERT(tailsize == tailsize32);
582*7836SJohn.Forte@Sun.COM #endif
583*7836SJohn.Forte@Sun.COM 
584*7836SJohn.Forte@Sun.COM 	bcopy(&urdc->flags, &set32.flags, tailsize);
585*7836SJohn.Forte@Sun.COM 
586*7836SJohn.Forte@Sun.COM 	/* copyout to user level */
587*7836SJohn.Forte@Sun.COM 	return (ddi_copyout(&set32, usetp, size, mode));
588*7836SJohn.Forte@Sun.COM }
589*7836SJohn.Forte@Sun.COM 
590*7836SJohn.Forte@Sun.COM 
591*7836SJohn.Forte@Sun.COM /*
592*7836SJohn.Forte@Sun.COM  * Status ioctl.
593*7836SJohn.Forte@Sun.COM  */
594*7836SJohn.Forte@Sun.COM static int
595*7836SJohn.Forte@Sun.COM rdcstatus(_rdc_ioctl_t *args, int mode)
596*7836SJohn.Forte@Sun.COM {
597*7836SJohn.Forte@Sun.COM 	int (*copyout)(const void *, void *, size_t, int);
598*7836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc;
599*7836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
600*7836SJohn.Forte@Sun.COM 	disk_queue *dqp;
601*7836SJohn.Forte@Sun.COM 	char *usetp;			/* pointer to user rdc_set structure */
602*7836SJohn.Forte@Sun.COM 	size_t size;			/* sizeof user rdc_set structure */
603*7836SJohn.Forte@Sun.COM 	int32_t *maxsetsp;		/* address of status->maxsets; */
604*7836SJohn.Forte@Sun.COM 	int nset, max, i, j;
605*7836SJohn.Forte@Sun.COM 
606*7836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
607*7836SJohn.Forte@Sun.COM 		struct rdc_status32 status32;
608*7836SJohn.Forte@Sun.COM 
609*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args->arg0, &status32,
610*7836SJohn.Forte@Sun.COM 		    sizeof (status32), mode)) {
611*7836SJohn.Forte@Sun.COM 			return (EFAULT);
612*7836SJohn.Forte@Sun.COM 		}
613*7836SJohn.Forte@Sun.COM 
614*7836SJohn.Forte@Sun.COM 		usetp = ((char *)args->arg0) +
615*7836SJohn.Forte@Sun.COM 		    offsetof(struct rdc_status32, rdc_set);
616*7836SJohn.Forte@Sun.COM 		maxsetsp = (int32_t *)((char *)args->arg0 +
617*7836SJohn.Forte@Sun.COM 		    offsetof(struct rdc_status32, maxsets));
618*7836SJohn.Forte@Sun.COM 		nset = status32.nset;
619*7836SJohn.Forte@Sun.COM 
620*7836SJohn.Forte@Sun.COM 		size = sizeof (struct rdc_set32);
621*7836SJohn.Forte@Sun.COM 		copyout = rdc_status_copy32;
622*7836SJohn.Forte@Sun.COM 	} else {
623*7836SJohn.Forte@Sun.COM 		struct rdc_status status;
624*7836SJohn.Forte@Sun.COM 
625*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args->arg0, &status,
626*7836SJohn.Forte@Sun.COM 		    sizeof (status), mode)) {
627*7836SJohn.Forte@Sun.COM 			return (EFAULT);
628*7836SJohn.Forte@Sun.COM 		}
629*7836SJohn.Forte@Sun.COM 
630*7836SJohn.Forte@Sun.COM 		usetp = ((char *)args->arg0) +
631*7836SJohn.Forte@Sun.COM 		    offsetof(struct rdc_status, rdc_set);
632*7836SJohn.Forte@Sun.COM 		maxsetsp = (int32_t *)((char *)args->arg0 +
633*7836SJohn.Forte@Sun.COM 		    offsetof(struct rdc_status, maxsets));
634*7836SJohn.Forte@Sun.COM 		nset = status.nset;
635*7836SJohn.Forte@Sun.COM 
636*7836SJohn.Forte@Sun.COM 		size = sizeof (struct rdc_set);
637*7836SJohn.Forte@Sun.COM 		copyout = ddi_copyout;
638*7836SJohn.Forte@Sun.COM 	}
639*7836SJohn.Forte@Sun.COM 
640*7836SJohn.Forte@Sun.COM 	max = min(nset, rdc_max_sets);
641*7836SJohn.Forte@Sun.COM 
642*7836SJohn.Forte@Sun.COM 	for (i = 0, j = 0; i < max; i++) {
643*7836SJohn.Forte@Sun.COM 		urdc = &rdc_u_info[i];
644*7836SJohn.Forte@Sun.COM 		krdc = &rdc_k_info[i];
645*7836SJohn.Forte@Sun.COM 
646*7836SJohn.Forte@Sun.COM 		if (!IS_ENABLED(urdc))
647*7836SJohn.Forte@Sun.COM 			continue;
648*7836SJohn.Forte@Sun.COM 
649*7836SJohn.Forte@Sun.COM 		/*
650*7836SJohn.Forte@Sun.COM 		 * sneak out qstate in urdc->flags
651*7836SJohn.Forte@Sun.COM 		 * this is harmless because it's value is not used
652*7836SJohn.Forte@Sun.COM 		 * in urdc->flags. the real qstate is kept in
653*7836SJohn.Forte@Sun.COM 		 * group->diskq->disk_hdr.h.state
654*7836SJohn.Forte@Sun.COM 		 */
655*7836SJohn.Forte@Sun.COM 		if (RDC_IS_DISKQ(krdc->group)) {
656*7836SJohn.Forte@Sun.COM 			dqp = &krdc->group->diskq;
657*7836SJohn.Forte@Sun.COM 			if (IS_QSTATE(dqp, RDC_QNOBLOCK))
658*7836SJohn.Forte@Sun.COM 				urdc->flags |= RDC_QNOBLOCK;
659*7836SJohn.Forte@Sun.COM 		}
660*7836SJohn.Forte@Sun.COM 
661*7836SJohn.Forte@Sun.COM 		j++;
662*7836SJohn.Forte@Sun.COM 		if ((*copyout)(urdc, usetp, size, mode) != 0)
663*7836SJohn.Forte@Sun.COM 			return (EFAULT);
664*7836SJohn.Forte@Sun.COM 
665*7836SJohn.Forte@Sun.COM 		urdc->flags &= ~RDC_QNOBLOCK; /* clear qstate */
666*7836SJohn.Forte@Sun.COM 		usetp += size;
667*7836SJohn.Forte@Sun.COM 	}
668*7836SJohn.Forte@Sun.COM 
669*7836SJohn.Forte@Sun.COM 	/* copyout rdc_max_sets value */
670*7836SJohn.Forte@Sun.COM 
671*7836SJohn.Forte@Sun.COM 	if (ddi_copyout(&rdc_max_sets, maxsetsp, sizeof (*maxsetsp), mode) != 0)
672*7836SJohn.Forte@Sun.COM 		return (EFAULT);
673*7836SJohn.Forte@Sun.COM 
674*7836SJohn.Forte@Sun.COM 	/* copyout number of sets manipulated */
675*7836SJohn.Forte@Sun.COM 
676*7836SJohn.Forte@Sun.COM 	/*CONSTCOND*/
677*7836SJohn.Forte@Sun.COM 	ASSERT(offsetof(struct rdc_status32, nset) == 0);
678*7836SJohn.Forte@Sun.COM 	/*CONSTCOND*/
679*7836SJohn.Forte@Sun.COM 	ASSERT(offsetof(struct rdc_status, nset) == 0);
680*7836SJohn.Forte@Sun.COM 
681*7836SJohn.Forte@Sun.COM 	return (ddi_copyout(&j, (void *)args->arg0, sizeof (int), mode));
682*7836SJohn.Forte@Sun.COM }
683*7836SJohn.Forte@Sun.COM 
684*7836SJohn.Forte@Sun.COM 
685*7836SJohn.Forte@Sun.COM /* ARGSUSED */
686*7836SJohn.Forte@Sun.COM 
687*7836SJohn.Forte@Sun.COM static int
688*7836SJohn.Forte@Sun.COM rdcioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
689*7836SJohn.Forte@Sun.COM {
690*7836SJohn.Forte@Sun.COM 	spcs_s_info_t kstatus = NULL;
691*7836SJohn.Forte@Sun.COM 	_rdc_ioctl_t args;
692*7836SJohn.Forte@Sun.COM 	int error;
693*7836SJohn.Forte@Sun.COM 	int rc = 0;
694*7836SJohn.Forte@Sun.COM 
695*7836SJohn.Forte@Sun.COM 	if (cmd != RDC_STATUS) {
696*7836SJohn.Forte@Sun.COM 		if ((error = drv_priv(crp)) != 0)
697*7836SJohn.Forte@Sun.COM 			return (error);
698*7836SJohn.Forte@Sun.COM 	}
699*7836SJohn.Forte@Sun.COM #ifdef	DEBUG
700*7836SJohn.Forte@Sun.COM 	if (cmd == RDC_ASYNC6) {
701*7836SJohn.Forte@Sun.COM 		rc = rdc_async6((void *)arg, mode, rvp);
702*7836SJohn.Forte@Sun.COM 		return (rc);
703*7836SJohn.Forte@Sun.COM 	}
704*7836SJohn.Forte@Sun.COM 
705*7836SJohn.Forte@Sun.COM 	if (cmd == RDC_CLRKSTAT) {
706*7836SJohn.Forte@Sun.COM 		rc = rdc_clrkstat((void *)arg);
707*7836SJohn.Forte@Sun.COM 		return (rc);
708*7836SJohn.Forte@Sun.COM 	}
709*7836SJohn.Forte@Sun.COM 
710*7836SJohn.Forte@Sun.COM 	if (cmd == RDC_STALL0) {
711*7836SJohn.Forte@Sun.COM 		if (((int)arg > 1) || ((int)arg < 0))
712*7836SJohn.Forte@Sun.COM 			return (EINVAL);
713*7836SJohn.Forte@Sun.COM 		rdc_stallzero((int)arg);
714*7836SJohn.Forte@Sun.COM 		return (0);
715*7836SJohn.Forte@Sun.COM 	}
716*7836SJohn.Forte@Sun.COM 	if (cmd == RDC_READGEN) {
717*7836SJohn.Forte@Sun.COM 		rc = rdc_readgen((void *)arg, mode, rvp);
718*7836SJohn.Forte@Sun.COM 		return (rc);
719*7836SJohn.Forte@Sun.COM 	}
720*7836SJohn.Forte@Sun.COM #endif
721*7836SJohn.Forte@Sun.COM 	if (cmd == RDC_BITMAPOP) {
722*7836SJohn.Forte@Sun.COM 		rdc_bitmap_op_t bmop;
723*7836SJohn.Forte@Sun.COM 		rdc_bitmap_op32_t bmop32;
724*7836SJohn.Forte@Sun.COM 
725*7836SJohn.Forte@Sun.COM 		if (ddi_model_convert_from(mode & FMODELS)
726*7836SJohn.Forte@Sun.COM 		    == DDI_MODEL_ILP32) {
727*7836SJohn.Forte@Sun.COM 			if (ddi_copyin((void *)arg, &bmop32, sizeof (bmop32),
728*7836SJohn.Forte@Sun.COM 			    mode))
729*7836SJohn.Forte@Sun.COM 				return (EFAULT);
730*7836SJohn.Forte@Sun.COM 			bmop.offset = bmop32.offset;
731*7836SJohn.Forte@Sun.COM 			bmop.op = bmop32.op;
732*7836SJohn.Forte@Sun.COM 			(void) strncpy(bmop.sechost, bmop32.sechost,
733*7836SJohn.Forte@Sun.COM 			    MAX_RDC_HOST_SIZE);
734*7836SJohn.Forte@Sun.COM 			(void) strncpy(bmop.secfile, bmop32.secfile,
735*7836SJohn.Forte@Sun.COM 			    NSC_MAXPATH);
736*7836SJohn.Forte@Sun.COM 			bmop.len = bmop32.len;
737*7836SJohn.Forte@Sun.COM 			bmop.addr = (unsigned long)bmop32.addr;
738*7836SJohn.Forte@Sun.COM 		} else {
739*7836SJohn.Forte@Sun.COM 			if (ddi_copyin((void *)arg, &bmop, sizeof (bmop),
740*7836SJohn.Forte@Sun.COM 			    mode))
741*7836SJohn.Forte@Sun.COM 				return (EFAULT);
742*7836SJohn.Forte@Sun.COM 		}
743*7836SJohn.Forte@Sun.COM 		rc = rdc_bitmapset(bmop.op, bmop.sechost, bmop.secfile,
744*7836SJohn.Forte@Sun.COM 		    (void *)bmop.addr, bmop.len, bmop.offset, mode);
745*7836SJohn.Forte@Sun.COM 		return (rc);
746*7836SJohn.Forte@Sun.COM 	}
747*7836SJohn.Forte@Sun.COM 
748*7836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
749*7836SJohn.Forte@Sun.COM 		if ((rc = convert_ioctl_args(cmd, arg, mode, &args)) != 0)
750*7836SJohn.Forte@Sun.COM 			return (rc);
751*7836SJohn.Forte@Sun.COM 	} else {
752*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, &args,
753*7836SJohn.Forte@Sun.COM 		    sizeof (_rdc_ioctl_t), mode)) {
754*7836SJohn.Forte@Sun.COM 			return (EFAULT);
755*7836SJohn.Forte@Sun.COM 		}
756*7836SJohn.Forte@Sun.COM 	}
757*7836SJohn.Forte@Sun.COM 
758*7836SJohn.Forte@Sun.COM 	kstatus = spcs_s_kcreate();
759*7836SJohn.Forte@Sun.COM 	if (!kstatus) {
760*7836SJohn.Forte@Sun.COM 		return (ENOMEM);
761*7836SJohn.Forte@Sun.COM 	}
762*7836SJohn.Forte@Sun.COM 
763*7836SJohn.Forte@Sun.COM 
764*7836SJohn.Forte@Sun.COM 	switch (cmd) {
765*7836SJohn.Forte@Sun.COM 
766*7836SJohn.Forte@Sun.COM 	case RDC_POOL_CREATE: {
767*7836SJohn.Forte@Sun.COM 		struct svcpool_args p;
768*7836SJohn.Forte@Sun.COM 
769*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, &p, sizeof (p), mode)) {
770*7836SJohn.Forte@Sun.COM 			spcs_s_kfree(kstatus);
771*7836SJohn.Forte@Sun.COM 			return (EFAULT);
772*7836SJohn.Forte@Sun.COM 		}
773*7836SJohn.Forte@Sun.COM 		error = svc_pool_create(&p);
774*7836SJohn.Forte@Sun.COM 
775*7836SJohn.Forte@Sun.COM 		break;
776*7836SJohn.Forte@Sun.COM 	}
777*7836SJohn.Forte@Sun.COM 	case RDC_POOL_WAIT: {
778*7836SJohn.Forte@Sun.COM 		int id;
779*7836SJohn.Forte@Sun.COM 
780*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, &id, sizeof (id), mode)) {
781*7836SJohn.Forte@Sun.COM 			spcs_s_kfree(kstatus);
782*7836SJohn.Forte@Sun.COM 			return (EFAULT);
783*7836SJohn.Forte@Sun.COM 		}
784*7836SJohn.Forte@Sun.COM 
785*7836SJohn.Forte@Sun.COM 		error = svc_wait(id);
786*7836SJohn.Forte@Sun.COM 		break;
787*7836SJohn.Forte@Sun.COM 	}
788*7836SJohn.Forte@Sun.COM 	case RDC_POOL_RUN: {
789*7836SJohn.Forte@Sun.COM 		int id;
790*7836SJohn.Forte@Sun.COM 
791*7836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, &id, sizeof (id), mode)) {
792*7836SJohn.Forte@Sun.COM 			spcs_s_kfree(kstatus);
793*7836SJohn.Forte@Sun.COM 			return (EFAULT);
794*7836SJohn.Forte@Sun.COM 		}
795*7836SJohn.Forte@Sun.COM 		error = svc_do_run(id);
796*7836SJohn.Forte@Sun.COM 		break;
797*7836SJohn.Forte@Sun.COM 	}
798*7836SJohn.Forte@Sun.COM 	case RDC_ENABLE_SVR:
799*7836SJohn.Forte@Sun.COM 		{
800*7836SJohn.Forte@Sun.COM 			STRUCT_DECL(rdc_svc_args, parms);
801*7836SJohn.Forte@Sun.COM 
802*7836SJohn.Forte@Sun.COM 			STRUCT_INIT(parms, mode);
803*7836SJohn.Forte@Sun.COM 			/* Only used by sndrd which does not use unistat */
804*7836SJohn.Forte@Sun.COM 
805*7836SJohn.Forte@Sun.COM 			if (ddi_copyin((void *)args.arg0, STRUCT_BUF(parms),
806*7836SJohn.Forte@Sun.COM 			    STRUCT_SIZE(parms), mode)) {
807*7836SJohn.Forte@Sun.COM 				spcs_s_kfree(kstatus);
808*7836SJohn.Forte@Sun.COM 				return (EFAULT);
809*7836SJohn.Forte@Sun.COM 			}
810*7836SJohn.Forte@Sun.COM 			rc = rdc_start_server(STRUCT_BUF(parms), mode);
811*7836SJohn.Forte@Sun.COM 		}
812*7836SJohn.Forte@Sun.COM 		break;
813*7836SJohn.Forte@Sun.COM 
814*7836SJohn.Forte@Sun.COM 	case RDC_STATUS:
815*7836SJohn.Forte@Sun.COM 		rc = rdcstatus(&args, mode);
816*7836SJohn.Forte@Sun.COM 		break;
817*7836SJohn.Forte@Sun.COM 
818*7836SJohn.Forte@Sun.COM 	case RDC_CONFIG:
819*7836SJohn.Forte@Sun.COM 		rc = _rdc_config((void *)args.arg0, mode, kstatus, rvp);
820*7836SJohn.Forte@Sun.COM 		spcs_s_copyoutf(&kstatus, args.ustatus);
821*7836SJohn.Forte@Sun.COM 		return (rc);
822*7836SJohn.Forte@Sun.COM 
823*7836SJohn.Forte@Sun.COM 	case RDC_VERSION:
824*7836SJohn.Forte@Sun.COM 		{
825*7836SJohn.Forte@Sun.COM 			STRUCT_DECL(rdc_version, parms);
826*7836SJohn.Forte@Sun.COM 
827*7836SJohn.Forte@Sun.COM 			STRUCT_INIT(parms, mode);
828*7836SJohn.Forte@Sun.COM 
829*7836SJohn.Forte@Sun.COM 			STRUCT_FSET(parms, major, sndr_major_rev);
830*7836SJohn.Forte@Sun.COM 			STRUCT_FSET(parms, minor, sndr_minor_rev);
831*7836SJohn.Forte@Sun.COM 			STRUCT_FSET(parms, micro, sndr_micro_rev);
832*7836SJohn.Forte@Sun.COM 			STRUCT_FSET(parms, baseline, sndr_baseline_rev);
833*7836SJohn.Forte@Sun.COM 
834*7836SJohn.Forte@Sun.COM 			if (ddi_copyout(STRUCT_BUF(parms), (void *)args.arg0,
835*7836SJohn.Forte@Sun.COM 				STRUCT_SIZE(parms), mode)) {
836*7836SJohn.Forte@Sun.COM 				spcs_s_kfree(kstatus);
837*7836SJohn.Forte@Sun.COM 				return (EFAULT);
838*7836SJohn.Forte@Sun.COM 			}
839*7836SJohn.Forte@Sun.COM 			break;
840*7836SJohn.Forte@Sun.COM 		}
841*7836SJohn.Forte@Sun.COM 
842*7836SJohn.Forte@Sun.COM 	case RDC_LINK_DOWN:
843*7836SJohn.Forte@Sun.COM 		/* char *host from user */
844*7836SJohn.Forte@Sun.COM 		rc = _rdc_link_down((void *)args.arg0, mode, kstatus, rvp);
845*7836SJohn.Forte@Sun.COM 		spcs_s_copyoutf(&kstatus, args.ustatus);
846*7836SJohn.Forte@Sun.COM 
847*7836SJohn.Forte@Sun.COM 		return (rc);
848*7836SJohn.Forte@Sun.COM 
849*7836SJohn.Forte@Sun.COM 	case RDC_SYNC_EVENT:
850*7836SJohn.Forte@Sun.COM 		rc = _rdc_sync_event_wait((void *)args.arg0, (void *)args.arg1,
851*7836SJohn.Forte@Sun.COM 		    mode, kstatus, rvp);
852*7836SJohn.Forte@Sun.COM 		spcs_s_copyoutf(&kstatus, args.ustatus);
853*7836SJohn.Forte@Sun.COM 
854*7836SJohn.Forte@Sun.COM 		return (rc);
855*7836SJohn.Forte@Sun.COM 
856*7836SJohn.Forte@Sun.COM 
857*7836SJohn.Forte@Sun.COM 	default:
858*7836SJohn.Forte@Sun.COM 		rc = EINVAL;
859*7836SJohn.Forte@Sun.COM 		break;
860*7836SJohn.Forte@Sun.COM 	}
861*7836SJohn.Forte@Sun.COM 
862*7836SJohn.Forte@Sun.COM 	spcs_s_kfree(kstatus);
863*7836SJohn.Forte@Sun.COM 	return (rc);
864*7836SJohn.Forte@Sun.COM }
865*7836SJohn.Forte@Sun.COM 
866*7836SJohn.Forte@Sun.COM int
867*7836SJohn.Forte@Sun.COM sndr_info_stats_update(kstat_t *ksp, int rw)
868*7836SJohn.Forte@Sun.COM {
869*7836SJohn.Forte@Sun.COM 	extern int rdc_rpc_tmout;
870*7836SJohn.Forte@Sun.COM 	extern int rdc_health_thres;
871*7836SJohn.Forte@Sun.COM 	extern int rdc_bitmap_delay;
872*7836SJohn.Forte@Sun.COM 	extern long rdc_clnt_count;
873*7836SJohn.Forte@Sun.COM 	extern long rdc_svc_count;
874*7836SJohn.Forte@Sun.COM 	sndr_m_stats_t	*info_stats;
875*7836SJohn.Forte@Sun.COM 	rdc_k_info_t	*krdc;
876*7836SJohn.Forte@Sun.COM 
877*7836SJohn.Forte@Sun.COM 	info_stats = (sndr_m_stats_t *)(ksp->ks_data);
878*7836SJohn.Forte@Sun.COM 	krdc = (rdc_k_info_t *)(ksp->ks_private);
879*7836SJohn.Forte@Sun.COM 
880*7836SJohn.Forte@Sun.COM 	/* no writes currently allowed */
881*7836SJohn.Forte@Sun.COM 
882*7836SJohn.Forte@Sun.COM 	if (rw == KSTAT_WRITE) {
883*7836SJohn.Forte@Sun.COM 		return (EACCES);
884*7836SJohn.Forte@Sun.COM 	}
885*7836SJohn.Forte@Sun.COM 
886*7836SJohn.Forte@Sun.COM 	/* default to READ */
887*7836SJohn.Forte@Sun.COM 	info_stats->m_maxsets.value.ul = rdc_max_sets;
888*7836SJohn.Forte@Sun.COM 	info_stats->m_maxfbas.value.ul = krdc->maxfbas;
889*7836SJohn.Forte@Sun.COM 	info_stats->m_rpc_timeout.value.ul = rdc_rpc_tmout;
890*7836SJohn.Forte@Sun.COM 	info_stats->m_health_thres.value.ul = rdc_health_thres;
891*7836SJohn.Forte@Sun.COM 	info_stats->m_bitmap_writes.value.ul = krdc->bitmap_write;
892*7836SJohn.Forte@Sun.COM 	info_stats->m_bitmap_ref_delay.value.ul = rdc_bitmap_delay;
893*7836SJohn.Forte@Sun.COM 
894*7836SJohn.Forte@Sun.COM 	/* clts counters not implemented yet */
895*7836SJohn.Forte@Sun.COM 	info_stats->m_clnt_cots_calls.value.ul = rdc_clnt_count;
896*7836SJohn.Forte@Sun.COM 	info_stats->m_clnt_clts_calls.value.ul = 0;
897*7836SJohn.Forte@Sun.COM 	info_stats->m_svc_cots_calls.value.ul = rdc_svc_count;
898*7836SJohn.Forte@Sun.COM 	info_stats->m_svc_clts_calls.value.ul = 0;
899*7836SJohn.Forte@Sun.COM 
900*7836SJohn.Forte@Sun.COM 	return (0);
901*7836SJohn.Forte@Sun.COM }
902*7836SJohn.Forte@Sun.COM 
903*7836SJohn.Forte@Sun.COM /*
904*7836SJohn.Forte@Sun.COM  * copy tailsize-1 bytes of tail of s to s1.
905*7836SJohn.Forte@Sun.COM  */
906*7836SJohn.Forte@Sun.COM void
907*7836SJohn.Forte@Sun.COM rdc_str_tail_cpy(char *s1, char *s, size_t tailsize)
908*7836SJohn.Forte@Sun.COM {
909*7836SJohn.Forte@Sun.COM 	/* To avoid un-terminated string, max size is 16 - 1 */
910*7836SJohn.Forte@Sun.COM 	ssize_t offset = strlen(s) - (tailsize - 1);
911*7836SJohn.Forte@Sun.COM 
912*7836SJohn.Forte@Sun.COM 	offset = (offset > 0) ? offset : 0;
913*7836SJohn.Forte@Sun.COM 
914*7836SJohn.Forte@Sun.COM 	/* ensure it's null terminated */
915*7836SJohn.Forte@Sun.COM 	(void) strlcpy(s1, (const char *)(s + offset), tailsize);
916*7836SJohn.Forte@Sun.COM }
917*7836SJohn.Forte@Sun.COM 
918*7836SJohn.Forte@Sun.COM int
919*7836SJohn.Forte@Sun.COM rdc_info_stats_update(kstat_t *ksp, int rw)
920*7836SJohn.Forte@Sun.COM {
921*7836SJohn.Forte@Sun.COM 	rdc_info_stats_t	*rdc_info_stats;
922*7836SJohn.Forte@Sun.COM 	rdc_k_info_t		*krdc;
923*7836SJohn.Forte@Sun.COM 	rdc_u_info_t		*urdc;
924*7836SJohn.Forte@Sun.COM 
925*7836SJohn.Forte@Sun.COM 	rdc_info_stats = (rdc_info_stats_t *)(ksp->ks_data);
926*7836SJohn.Forte@Sun.COM 	krdc = (rdc_k_info_t *)(ksp->ks_private);
927*7836SJohn.Forte@Sun.COM 	urdc = &rdc_u_info[krdc->index];
928*7836SJohn.Forte@Sun.COM 
929*7836SJohn.Forte@Sun.COM 	/* no writes currently allowed */
930*7836SJohn.Forte@Sun.COM 
931*7836SJohn.Forte@Sun.COM 	if (rw == KSTAT_WRITE) {
932*7836SJohn.Forte@Sun.COM 		return (EACCES);
933*7836SJohn.Forte@Sun.COM 	}
934*7836SJohn.Forte@Sun.COM 
935*7836SJohn.Forte@Sun.COM 	/* default to READ */
936*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_flags.value.ul = urdc->flags;
937*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_syncflags.value.ul =
938*7836SJohn.Forte@Sun.COM 	    urdc->sync_flags;
939*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_bmpflags.value.ul =
940*7836SJohn.Forte@Sun.COM 	    urdc->bmap_flags;
941*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_syncpos.value.ul =
942*7836SJohn.Forte@Sun.COM 	    urdc->sync_pos;
943*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_volsize.value.ul =
944*7836SJohn.Forte@Sun.COM 	    urdc->volume_size;
945*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_bits_set.value.ul =
946*7836SJohn.Forte@Sun.COM 	    urdc->bits_set;
947*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_autosync.value.ul =
948*7836SJohn.Forte@Sun.COM 	    urdc->autosync;
949*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_maxqfbas.value.ul =
950*7836SJohn.Forte@Sun.COM 	    urdc->maxqfbas;
951*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_maxqitems.value.ul =
952*7836SJohn.Forte@Sun.COM 	    urdc->maxqitems;
953*7836SJohn.Forte@Sun.COM 
954*7836SJohn.Forte@Sun.COM 	kstat_named_setstr(&rdc_info_stats->s_primary_vol,
955*7836SJohn.Forte@Sun.COM 			urdc->primary.file);
956*7836SJohn.Forte@Sun.COM 
957*7836SJohn.Forte@Sun.COM 	kstat_named_setstr(&rdc_info_stats->s_secondary_vol,
958*7836SJohn.Forte@Sun.COM 			urdc->secondary.file);
959*7836SJohn.Forte@Sun.COM 
960*7836SJohn.Forte@Sun.COM 	if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
961*7836SJohn.Forte@Sun.COM 		kstat_named_setstr(&rdc_info_stats->s_bitmap,
962*7836SJohn.Forte@Sun.COM 				urdc->primary.bitmap);
963*7836SJohn.Forte@Sun.COM 	} else {
964*7836SJohn.Forte@Sun.COM 		kstat_named_setstr(&rdc_info_stats->s_bitmap,
965*7836SJohn.Forte@Sun.COM 				urdc->secondary.bitmap);
966*7836SJohn.Forte@Sun.COM 	}
967*7836SJohn.Forte@Sun.COM 
968*7836SJohn.Forte@Sun.COM 	kstat_named_setstr(&rdc_info_stats->s_primary_intf,
969*7836SJohn.Forte@Sun.COM 			urdc->primary.intf);
970*7836SJohn.Forte@Sun.COM 
971*7836SJohn.Forte@Sun.COM 	kstat_named_setstr(&rdc_info_stats->s_secondary_intf,
972*7836SJohn.Forte@Sun.COM 			urdc->secondary.intf);
973*7836SJohn.Forte@Sun.COM 
974*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_type_flag.value.ul = krdc->type_flag;
975*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_bitmap_size.value.ul = krdc->bitmap_size;
976*7836SJohn.Forte@Sun.COM 	rdc_info_stats->s_disk_status.value.ul = krdc->disk_status;
977*7836SJohn.Forte@Sun.COM 
978*7836SJohn.Forte@Sun.COM 	if (krdc->intf) {
979*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_if_if_down.value.ul = krdc->intf->if_down;
980*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_if_rpc_version.value.ul =
981*7836SJohn.Forte@Sun.COM 		    krdc->intf->rpc_version;
982*7836SJohn.Forte@Sun.COM 	}
983*7836SJohn.Forte@Sun.COM 
984*7836SJohn.Forte@Sun.COM 	/* the type can change without disable/re-enable so... */
985*7836SJohn.Forte@Sun.COM 	bzero(rdc_info_stats->s_aqueue_type.value.c, KSTAT_DATA_CHAR_LEN);
986*7836SJohn.Forte@Sun.COM 	if (RDC_IS_MEMQ(krdc->group)) {
987*7836SJohn.Forte@Sun.COM 		(void) strcpy(rdc_info_stats->s_aqueue_type.value.c, "memory");
988*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_blk_hwm.value.ul =
989*7836SJohn.Forte@Sun.COM 			krdc->group->ra_queue.blocks_hwm;
990*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_itm_hwm.value.ul =
991*7836SJohn.Forte@Sun.COM 			krdc->group->ra_queue.nitems_hwm;
992*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_throttle.value.ul =
993*7836SJohn.Forte@Sun.COM 			krdc->group->ra_queue.throttle_delay;
994*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_items.value.ul =
995*7836SJohn.Forte@Sun.COM 			krdc->group->ra_queue.nitems;
996*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_blocks.value.ul =
997*7836SJohn.Forte@Sun.COM 			krdc->group->ra_queue.blocks;
998*7836SJohn.Forte@Sun.COM 
999*7836SJohn.Forte@Sun.COM 	} else if (RDC_IS_DISKQ(krdc->group)) {
1000*7836SJohn.Forte@Sun.COM 		disk_queue *q = &krdc->group->diskq;
1001*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_blk_hwm.value.ul =
1002*7836SJohn.Forte@Sun.COM 			krdc->group->diskq.blocks_hwm;
1003*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_itm_hwm.value.ul =
1004*7836SJohn.Forte@Sun.COM 			krdc->group->diskq.nitems_hwm;
1005*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_throttle.value.ul =
1006*7836SJohn.Forte@Sun.COM 			krdc->group->diskq.throttle_delay;
1007*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_items.value.ul = QNITEMS(q);
1008*7836SJohn.Forte@Sun.COM 		rdc_info_stats->s_aqueue_blocks.value.ul = QBLOCKS(q);
1009*7836SJohn.Forte@Sun.COM 		(void) strcpy(rdc_info_stats->s_aqueue_type.value.c, "disk");
1010*7836SJohn.Forte@Sun.COM 	}
1011*7836SJohn.Forte@Sun.COM 
1012*7836SJohn.Forte@Sun.COM 	return (0);
1013*7836SJohn.Forte@Sun.COM }
1014*7836SJohn.Forte@Sun.COM 
1015*7836SJohn.Forte@Sun.COM void
1016*7836SJohn.Forte@Sun.COM rdc_kstat_create(int index)
1017*7836SJohn.Forte@Sun.COM {
1018*7836SJohn.Forte@Sun.COM 	int j = index;
1019*7836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
1020*7836SJohn.Forte@Sun.COM 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1021*7836SJohn.Forte@Sun.COM 	size_t varsize;
1022*7836SJohn.Forte@Sun.COM 
1023*7836SJohn.Forte@Sun.COM 	if (!krdc->set_kstats) {
1024*7836SJohn.Forte@Sun.COM 		krdc->set_kstats = kstat_create(RDC_KSTAT_MODULE, j,
1025*7836SJohn.Forte@Sun.COM 		    RDC_KSTAT_INFO, RDC_KSTAT_CLASS, KSTAT_TYPE_NAMED,
1026*7836SJohn.Forte@Sun.COM 		    sizeof (rdc_info_stats_t) / sizeof (kstat_named_t),
1027*7836SJohn.Forte@Sun.COM 		    KSTAT_FLAG_VIRTUAL);
1028*7836SJohn.Forte@Sun.COM #ifdef DEBUG
1029*7836SJohn.Forte@Sun.COM 		if (!krdc->set_kstats)
1030*7836SJohn.Forte@Sun.COM 			cmn_err(CE_NOTE, "krdc:u_kstat null");
1031*7836SJohn.Forte@Sun.COM #endif
1032*7836SJohn.Forte@Sun.COM 
1033*7836SJohn.Forte@Sun.COM 		if (krdc->set_kstats) {
1034*7836SJohn.Forte@Sun.COM 			/* calculate exact size of KSTAT_DATA_STRINGs */
1035*7836SJohn.Forte@Sun.COM 			varsize = strlen(urdc->primary.file) + 1
1036*7836SJohn.Forte@Sun.COM 				+ strlen(urdc->secondary.file) + 1
1037*7836SJohn.Forte@Sun.COM 				+ strlen(urdc->primary.intf) + 1
1038*7836SJohn.Forte@Sun.COM 				+ strlen(urdc->secondary.intf) + 1;
1039*7836SJohn.Forte@Sun.COM 			if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1040*7836SJohn.Forte@Sun.COM 				varsize += strlen(urdc->primary.bitmap) + 1;
1041*7836SJohn.Forte@Sun.COM 			} else {
1042*7836SJohn.Forte@Sun.COM 				varsize += strlen(urdc->secondary.bitmap) + 1;
1043*7836SJohn.Forte@Sun.COM 			}
1044*7836SJohn.Forte@Sun.COM 
1045*7836SJohn.Forte@Sun.COM 			krdc->set_kstats->ks_data_size += varsize;
1046*7836SJohn.Forte@Sun.COM 			krdc->set_kstats->ks_data = &rdc_info_stats;
1047*7836SJohn.Forte@Sun.COM 			krdc->set_kstats->ks_update = rdc_info_stats_update;
1048*7836SJohn.Forte@Sun.COM 			krdc->set_kstats->ks_private = &rdc_k_info[j];
1049*7836SJohn.Forte@Sun.COM 			kstat_install(krdc->set_kstats);
1050*7836SJohn.Forte@Sun.COM 		} else
1051*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN, "SNDR: k-kstats failed");
1052*7836SJohn.Forte@Sun.COM 	}
1053*7836SJohn.Forte@Sun.COM 
1054*7836SJohn.Forte@Sun.COM 	krdc->io_kstats = kstat_create(RDC_KSTAT_MODULE, j, NULL,
1055*7836SJohn.Forte@Sun.COM 				"disk", KSTAT_TYPE_IO, 1, 0);
1056*7836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
1057*7836SJohn.Forte@Sun.COM 		krdc->io_kstats->ks_lock = &krdc->kstat_mutex;
1058*7836SJohn.Forte@Sun.COM 		kstat_install(krdc->io_kstats);
1059*7836SJohn.Forte@Sun.COM 	}
1060*7836SJohn.Forte@Sun.COM 	krdc->bmp_kstats = kstat_create("sndrbmp", j, NULL,
1061*7836SJohn.Forte@Sun.COM 				"disk", KSTAT_TYPE_IO, 1, 0);
1062*7836SJohn.Forte@Sun.COM 	if (krdc->bmp_kstats) {
1063*7836SJohn.Forte@Sun.COM 		krdc->bmp_kstats->ks_lock = &krdc->bmp_kstat_mutex;
1064*7836SJohn.Forte@Sun.COM 		kstat_install(krdc->bmp_kstats);
1065*7836SJohn.Forte@Sun.COM 	}
1066*7836SJohn.Forte@Sun.COM }
1067*7836SJohn.Forte@Sun.COM 
1068*7836SJohn.Forte@Sun.COM void
1069*7836SJohn.Forte@Sun.COM rdc_kstat_delete(int index)
1070*7836SJohn.Forte@Sun.COM {
1071*7836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc = &rdc_k_info[index];
1072*7836SJohn.Forte@Sun.COM 
1073*7836SJohn.Forte@Sun.COM 	if (krdc->set_kstats) {
1074*7836SJohn.Forte@Sun.COM 		kstat_delete(krdc->set_kstats);
1075*7836SJohn.Forte@Sun.COM 		krdc->set_kstats = NULL;
1076*7836SJohn.Forte@Sun.COM 	}
1077*7836SJohn.Forte@Sun.COM 
1078*7836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
1079*7836SJohn.Forte@Sun.COM 		kstat_delete(krdc->io_kstats);
1080*7836SJohn.Forte@Sun.COM 		krdc->io_kstats = NULL;
1081*7836SJohn.Forte@Sun.COM 	}
1082*7836SJohn.Forte@Sun.COM 	if (krdc->bmp_kstats) {
1083*7836SJohn.Forte@Sun.COM 		kstat_delete(krdc->bmp_kstats);
1084*7836SJohn.Forte@Sun.COM 		krdc->bmp_kstats = NULL;
1085*7836SJohn.Forte@Sun.COM 	}
1086*7836SJohn.Forte@Sun.COM }
1087*7836SJohn.Forte@Sun.COM 
1088*7836SJohn.Forte@Sun.COM #ifdef	DEBUG
1089*7836SJohn.Forte@Sun.COM /*
1090*7836SJohn.Forte@Sun.COM  * Reset the io_kstat structure of the krdc specified
1091*7836SJohn.Forte@Sun.COM  * by the arg index.
1092*7836SJohn.Forte@Sun.COM  */
1093*7836SJohn.Forte@Sun.COM static int
1094*7836SJohn.Forte@Sun.COM rdc_clrkstat(void *arg)
1095*7836SJohn.Forte@Sun.COM {
1096*7836SJohn.Forte@Sun.COM 	int index;
1097*7836SJohn.Forte@Sun.COM 	rdc_k_info_t *krdc;
1098*7836SJohn.Forte@Sun.COM 
1099*7836SJohn.Forte@Sun.COM 	index = (int)(unsigned long)arg;
1100*7836SJohn.Forte@Sun.COM 	if ((index < 0) || (index >= rdc_max_sets)) {
1101*7836SJohn.Forte@Sun.COM 		return (EINVAL);
1102*7836SJohn.Forte@Sun.COM 	}
1103*7836SJohn.Forte@Sun.COM 	krdc = &rdc_k_info[index];
1104*7836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
1105*7836SJohn.Forte@Sun.COM 		kstat_delete(krdc->io_kstats);
1106*7836SJohn.Forte@Sun.COM 		krdc->io_kstats = NULL;
1107*7836SJohn.Forte@Sun.COM 	} else {
1108*7836SJohn.Forte@Sun.COM 		return (EINVAL);
1109*7836SJohn.Forte@Sun.COM 	}
1110*7836SJohn.Forte@Sun.COM 	krdc->io_kstats = kstat_create(RDC_KSTAT_MODULE, index, NULL,
1111*7836SJohn.Forte@Sun.COM 				"disk", KSTAT_TYPE_IO, 1, 0);
1112*7836SJohn.Forte@Sun.COM 	if (krdc->io_kstats) {
1113*7836SJohn.Forte@Sun.COM 		krdc->io_kstats->ks_lock = &krdc->kstat_mutex;
1114*7836SJohn.Forte@Sun.COM 		kstat_install(krdc->io_kstats);
1115*7836SJohn.Forte@Sun.COM 	} else {
1116*7836SJohn.Forte@Sun.COM 		return (EINVAL);
1117*7836SJohn.Forte@Sun.COM 	}
1118*7836SJohn.Forte@Sun.COM 	/*
1119*7836SJohn.Forte@Sun.COM 	 * clear the high water marks and throttle.
1120*7836SJohn.Forte@Sun.COM 	 */
1121*7836SJohn.Forte@Sun.COM 	if (krdc->group) {
1122*7836SJohn.Forte@Sun.COM 		krdc->group->ra_queue.nitems_hwm = 0;
1123*7836SJohn.Forte@Sun.COM 		krdc->group->ra_queue.blocks_hwm = 0;
1124*7836SJohn.Forte@Sun.COM 		krdc->group->ra_queue.throttle_delay = 0;
1125*7836SJohn.Forte@Sun.COM 	}
1126*7836SJohn.Forte@Sun.COM 	return (0);
1127*7836SJohn.Forte@Sun.COM }
1128*7836SJohn.Forte@Sun.COM #endif
1129