xref: /onnv-gate/usr/src/uts/common/avs/ns/solaris/nsc_raw.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 #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/debug.h>
28*7836SJohn.Forte@Sun.COM #include <sys/kmem.h>
29*7836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
30*7836SJohn.Forte@Sun.COM #ifndef DS_DDICT
31*7836SJohn.Forte@Sun.COM #include <sys/vnode.h>
32*7836SJohn.Forte@Sun.COM #endif
33*7836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
34*7836SJohn.Forte@Sun.COM #include <sys/open.h>
35*7836SJohn.Forte@Sun.COM #include <sys/file.h>
36*7836SJohn.Forte@Sun.COM #include <sys/cred.h>
37*7836SJohn.Forte@Sun.COM #include <sys/conf.h>
38*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
39*7836SJohn.Forte@Sun.COM #include <sys/uio.h>
40*7836SJohn.Forte@Sun.COM #ifndef DS_DDICT
41*7836SJohn.Forte@Sun.COM #include <sys/pathname.h>	/* for lookupname */
42*7836SJohn.Forte@Sun.COM #endif
43*7836SJohn.Forte@Sun.COM #include <sys/ddi.h>
44*7836SJohn.Forte@Sun.COM #include <sys/sunddi.h>
45*7836SJohn.Forte@Sun.COM #include <sys/sunldi.h>
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM #include <ns/solaris/nsc_thread.h>
48*7836SJohn.Forte@Sun.COM #ifdef DS_DDICT
49*7836SJohn.Forte@Sun.COM #include "../contract.h"
50*7836SJohn.Forte@Sun.COM #endif
51*7836SJohn.Forte@Sun.COM #include "../nsctl.h"
52*7836SJohn.Forte@Sun.COM #include "nskernd.h"
53*7836SJohn.Forte@Sun.COM 
54*7836SJohn.Forte@Sun.COM 
55*7836SJohn.Forte@Sun.COM typedef struct raw_maj {
56*7836SJohn.Forte@Sun.COM 	struct raw_maj	*next;
57*7836SJohn.Forte@Sun.COM 	major_t		major;
58*7836SJohn.Forte@Sun.COM 	struct dev_ops	*devops;
59*7836SJohn.Forte@Sun.COM 	strategy_fn_t	strategy;
60*7836SJohn.Forte@Sun.COM 	int		(*open)(dev_t *, int, int, cred_t *);
61*7836SJohn.Forte@Sun.COM 	int		(*close)(dev_t, int, int, cred_t *);
62*7836SJohn.Forte@Sun.COM 	int		(*ioctl)(dev_t, int, intptr_t, int, cred_t *, int *);
63*7836SJohn.Forte@Sun.COM } raw_maj_t;
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM typedef struct raw_dev {
66*7836SJohn.Forte@Sun.COM 	ldi_handle_t	lh;		/* Solaris layered driver handle */
67*7836SJohn.Forte@Sun.COM 	struct vnode	*vp;		/* vnode of device */
68*7836SJohn.Forte@Sun.COM 	uint64_t	size;		/* size of device in blocks */
69*7836SJohn.Forte@Sun.COM 	raw_maj_t	*major;		/* pointer to major structure */
70*7836SJohn.Forte@Sun.COM 	char		*path;		/* pathname -- kmem_alloc'd */
71*7836SJohn.Forte@Sun.COM 	int		plen;		/* length of kmem_alloc for pathname */
72*7836SJohn.Forte@Sun.COM 	dev_t		rdev;		/* device number */
73*7836SJohn.Forte@Sun.COM 	char		in_use;		/* flag */
74*7836SJohn.Forte@Sun.COM 	int		partition;	/* partition number */
75*7836SJohn.Forte@Sun.COM } raw_dev_t;
76*7836SJohn.Forte@Sun.COM 
77*7836SJohn.Forte@Sun.COM static int fd_hwm = 0;	/* first never used entry in _nsc_raw_files */
78*7836SJohn.Forte@Sun.COM 
79*7836SJohn.Forte@Sun.COM static raw_dev_t *_nsc_raw_files;
80*7836SJohn.Forte@Sun.COM static raw_maj_t *_nsc_raw_majors;
81*7836SJohn.Forte@Sun.COM 
82*7836SJohn.Forte@Sun.COM kmutex_t _nsc_raw_lock;
83*7836SJohn.Forte@Sun.COM 
84*7836SJohn.Forte@Sun.COM int _nsc_raw_flags = 0;				/* required by nsctl */
85*7836SJohn.Forte@Sun.COM static int _nsc_raw_maxdevs;			/* local copy */
86*7836SJohn.Forte@Sun.COM 
87*7836SJohn.Forte@Sun.COM static int _raw_strategy(struct buf *);		/* forward decl */
88*7836SJohn.Forte@Sun.COM 
89*7836SJohn.Forte@Sun.COM static dev_t
ldi_get_dev_t_from_path(char * path)90*7836SJohn.Forte@Sun.COM ldi_get_dev_t_from_path(char *path)
91*7836SJohn.Forte@Sun.COM {
92*7836SJohn.Forte@Sun.COM 	vnode_t	*vp;
93*7836SJohn.Forte@Sun.COM 	dev_t rdev;
94*7836SJohn.Forte@Sun.COM 
95*7836SJohn.Forte@Sun.COM 	/* Validate parameters */
96*7836SJohn.Forte@Sun.COM 	if (path == NULL)
97*7836SJohn.Forte@Sun.COM 		return (NULL);
98*7836SJohn.Forte@Sun.COM 
99*7836SJohn.Forte@Sun.COM 	/* Lookup path */
100*7836SJohn.Forte@Sun.COM 	vp = NULL;
101*7836SJohn.Forte@Sun.COM 	if (lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp))
102*7836SJohn.Forte@Sun.COM 		return (NULL);
103*7836SJohn.Forte@Sun.COM 
104*7836SJohn.Forte@Sun.COM 	/* Validate resulting vnode */
105*7836SJohn.Forte@Sun.COM 	if ((vp) && (vp->v_type == VCHR))
106*7836SJohn.Forte@Sun.COM 		rdev = vp->v_rdev;
107*7836SJohn.Forte@Sun.COM 	else
108*7836SJohn.Forte@Sun.COM 		rdev = (dev_t)NULL;
109*7836SJohn.Forte@Sun.COM 
110*7836SJohn.Forte@Sun.COM 	/* Release vnode */
111*7836SJohn.Forte@Sun.COM 	if (vp)
112*7836SJohn.Forte@Sun.COM 		VN_RELE(vp);
113*7836SJohn.Forte@Sun.COM 
114*7836SJohn.Forte@Sun.COM 	return (rdev);
115*7836SJohn.Forte@Sun.COM }
116*7836SJohn.Forte@Sun.COM 
117*7836SJohn.Forte@Sun.COM int
_nsc_init_raw(int maxdevs)118*7836SJohn.Forte@Sun.COM _nsc_init_raw(int maxdevs)
119*7836SJohn.Forte@Sun.COM {
120*7836SJohn.Forte@Sun.COM 	_nsc_raw_files =
121*7836SJohn.Forte@Sun.COM 	    kmem_zalloc(sizeof (*_nsc_raw_files) * maxdevs, KM_SLEEP);
122*7836SJohn.Forte@Sun.COM 	if (!_nsc_raw_files)
123*7836SJohn.Forte@Sun.COM 		return (ENOMEM);
124*7836SJohn.Forte@Sun.COM 
125*7836SJohn.Forte@Sun.COM 	_nsc_raw_maxdevs = maxdevs;
126*7836SJohn.Forte@Sun.COM 	_nsc_raw_majors = NULL;
127*7836SJohn.Forte@Sun.COM 
128*7836SJohn.Forte@Sun.COM 	mutex_init(&_nsc_raw_lock, NULL, MUTEX_DRIVER, NULL);
129*7836SJohn.Forte@Sun.COM 	return (0);
130*7836SJohn.Forte@Sun.COM }
131*7836SJohn.Forte@Sun.COM 
132*7836SJohn.Forte@Sun.COM 
133*7836SJohn.Forte@Sun.COM void
_nsc_deinit_raw(void)134*7836SJohn.Forte@Sun.COM _nsc_deinit_raw(void)
135*7836SJohn.Forte@Sun.COM {
136*7836SJohn.Forte@Sun.COM 	raw_maj_t *maj = _nsc_raw_majors;
137*7836SJohn.Forte@Sun.COM 	raw_maj_t *next;
138*7836SJohn.Forte@Sun.COM 
139*7836SJohn.Forte@Sun.COM 	/*  Free the memory allocated for strategy pointers */
140*7836SJohn.Forte@Sun.COM 	while (maj != NULL) {
141*7836SJohn.Forte@Sun.COM 		next = maj->next;
142*7836SJohn.Forte@Sun.COM 		kmem_free(maj, sizeof (*maj));
143*7836SJohn.Forte@Sun.COM 		maj = next;
144*7836SJohn.Forte@Sun.COM 	}
145*7836SJohn.Forte@Sun.COM 
146*7836SJohn.Forte@Sun.COM 	mutex_destroy(&_nsc_raw_lock);
147*7836SJohn.Forte@Sun.COM 	kmem_free(_nsc_raw_files, sizeof (*_nsc_raw_files) * _nsc_raw_maxdevs);
148*7836SJohn.Forte@Sun.COM 	_nsc_raw_files = NULL;
149*7836SJohn.Forte@Sun.COM 	_nsc_raw_maxdevs = 0;
150*7836SJohn.Forte@Sun.COM }
151*7836SJohn.Forte@Sun.COM 
152*7836SJohn.Forte@Sun.COM 
153*7836SJohn.Forte@Sun.COM /* must be called with the _nsc_raw_lock held */
154*7836SJohn.Forte@Sun.COM static raw_maj_t *
_raw_get_maj_info(major_t umaj)155*7836SJohn.Forte@Sun.COM _raw_get_maj_info(major_t umaj)
156*7836SJohn.Forte@Sun.COM {
157*7836SJohn.Forte@Sun.COM 	raw_maj_t *maj = _nsc_raw_majors;
158*7836SJohn.Forte@Sun.COM 
159*7836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&_nsc_raw_lock));
160*7836SJohn.Forte@Sun.COM 
161*7836SJohn.Forte@Sun.COM 	/*  Walk through the linked list */
162*7836SJohn.Forte@Sun.COM 	while (maj != NULL) {
163*7836SJohn.Forte@Sun.COM 		if (maj->major == umaj) {
164*7836SJohn.Forte@Sun.COM 			/* Found major number */
165*7836SJohn.Forte@Sun.COM 			break;
166*7836SJohn.Forte@Sun.COM 		}
167*7836SJohn.Forte@Sun.COM 		maj = maj->next;
168*7836SJohn.Forte@Sun.COM 	}
169*7836SJohn.Forte@Sun.COM 
170*7836SJohn.Forte@Sun.COM 	if (maj == NULL) {
171*7836SJohn.Forte@Sun.COM 		struct dev_ops *ops = NULL;
172*7836SJohn.Forte@Sun.COM #ifdef DEBUG
173*7836SJohn.Forte@Sun.COM 		const int maxtry = 5;
174*7836SJohn.Forte@Sun.COM 		int try = maxtry;
175*7836SJohn.Forte@Sun.COM #endif
176*7836SJohn.Forte@Sun.COM 
177*7836SJohn.Forte@Sun.COM 		/*
178*7836SJohn.Forte@Sun.COM 		 * The earlier ldi_open call has locked the driver
179*7836SJohn.Forte@Sun.COM 		 * for this major number into memory, so just index into
180*7836SJohn.Forte@Sun.COM 		 * the devopsp array to get the dev_ops pointer which
181*7836SJohn.Forte@Sun.COM 		 * must be valid.
182*7836SJohn.Forte@Sun.COM 		 */
183*7836SJohn.Forte@Sun.COM 
184*7836SJohn.Forte@Sun.COM 		ops = devopsp[umaj];
185*7836SJohn.Forte@Sun.COM 
186*7836SJohn.Forte@Sun.COM 		if (ops == NULL || ops->devo_cb_ops == NULL) {
187*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
188*7836SJohn.Forte@Sun.COM 			    "nskern: cannot find dev_ops for major %d", umaj);
189*7836SJohn.Forte@Sun.COM 
190*7836SJohn.Forte@Sun.COM 			return (NULL);
191*7836SJohn.Forte@Sun.COM 		}
192*7836SJohn.Forte@Sun.COM 
193*7836SJohn.Forte@Sun.COM #ifdef DEBUG
194*7836SJohn.Forte@Sun.COM 		cmn_err(CE_NOTE,
195*7836SJohn.Forte@Sun.COM 			"nsc_raw: held driver (%d) after %d attempts",
196*7836SJohn.Forte@Sun.COM 			umaj, (maxtry - try));
197*7836SJohn.Forte@Sun.COM #endif /* DEBUG */
198*7836SJohn.Forte@Sun.COM 
199*7836SJohn.Forte@Sun.COM 		maj = kmem_zalloc(sizeof (raw_maj_t), KM_NOSLEEP);
200*7836SJohn.Forte@Sun.COM 		if (!maj) {
201*7836SJohn.Forte@Sun.COM 			return (NULL);
202*7836SJohn.Forte@Sun.COM 		}
203*7836SJohn.Forte@Sun.COM 
204*7836SJohn.Forte@Sun.COM 		maj->strategy = ops->devo_cb_ops->cb_strategy;
205*7836SJohn.Forte@Sun.COM 		maj->ioctl = ops->devo_cb_ops->cb_ioctl;
206*7836SJohn.Forte@Sun.COM 		maj->close = ops->devo_cb_ops->cb_close;
207*7836SJohn.Forte@Sun.COM 		maj->open = ops->devo_cb_ops->cb_open;
208*7836SJohn.Forte@Sun.COM 		maj->major = umaj;
209*7836SJohn.Forte@Sun.COM 		maj->devops = ops;
210*7836SJohn.Forte@Sun.COM 
211*7836SJohn.Forte@Sun.COM 		if (maj->strategy == NULL ||
212*7836SJohn.Forte@Sun.COM 		    maj->strategy == nodev ||
213*7836SJohn.Forte@Sun.COM 		    maj->strategy == nulldev) {
214*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
215*7836SJohn.Forte@Sun.COM 			    "nskern: no strategy function for "
216*7836SJohn.Forte@Sun.COM 			    "disk driver (major %d)",
217*7836SJohn.Forte@Sun.COM 			    umaj);
218*7836SJohn.Forte@Sun.COM 			kmem_free(maj, sizeof (*maj));
219*7836SJohn.Forte@Sun.COM 			return (NULL);
220*7836SJohn.Forte@Sun.COM 		}
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM 		maj->next = _nsc_raw_majors;
223*7836SJohn.Forte@Sun.COM 		_nsc_raw_majors = maj;
224*7836SJohn.Forte@Sun.COM 	}
225*7836SJohn.Forte@Sun.COM 
226*7836SJohn.Forte@Sun.COM 	return (maj);
227*7836SJohn.Forte@Sun.COM }
228*7836SJohn.Forte@Sun.COM 
229*7836SJohn.Forte@Sun.COM 
230*7836SJohn.Forte@Sun.COM /*
231*7836SJohn.Forte@Sun.COM  * nsc_get_strategy returns the strategy function associated with
232*7836SJohn.Forte@Sun.COM  * the major number umaj.  NULL is returned if no strategy is found.
233*7836SJohn.Forte@Sun.COM  */
234*7836SJohn.Forte@Sun.COM strategy_fn_t
nsc_get_strategy(major_t umaj)235*7836SJohn.Forte@Sun.COM nsc_get_strategy(major_t umaj)
236*7836SJohn.Forte@Sun.COM {
237*7836SJohn.Forte@Sun.COM 	raw_maj_t *maj;
238*7836SJohn.Forte@Sun.COM 	strategy_fn_t strategy = NULL;
239*7836SJohn.Forte@Sun.COM 
240*7836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_raw_lock);
241*7836SJohn.Forte@Sun.COM 
242*7836SJohn.Forte@Sun.COM 	for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
243*7836SJohn.Forte@Sun.COM 		if (maj->major == umaj) {
244*7836SJohn.Forte@Sun.COM 			/* Found major number */
245*7836SJohn.Forte@Sun.COM 			strategy = maj->strategy;
246*7836SJohn.Forte@Sun.COM 			break;
247*7836SJohn.Forte@Sun.COM 		}
248*7836SJohn.Forte@Sun.COM 	}
249*7836SJohn.Forte@Sun.COM 
250*7836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_raw_lock);
251*7836SJohn.Forte@Sun.COM 
252*7836SJohn.Forte@Sun.COM 	return (strategy);
253*7836SJohn.Forte@Sun.COM }
254*7836SJohn.Forte@Sun.COM 
255*7836SJohn.Forte@Sun.COM 
256*7836SJohn.Forte@Sun.COM void *
nsc_get_devops(major_t umaj)257*7836SJohn.Forte@Sun.COM nsc_get_devops(major_t umaj)
258*7836SJohn.Forte@Sun.COM {
259*7836SJohn.Forte@Sun.COM 	raw_maj_t *maj;
260*7836SJohn.Forte@Sun.COM 	void *devops = NULL;
261*7836SJohn.Forte@Sun.COM 
262*7836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_raw_lock);
263*7836SJohn.Forte@Sun.COM 
264*7836SJohn.Forte@Sun.COM 	for (maj = _nsc_raw_majors; maj != NULL; maj = maj->next) {
265*7836SJohn.Forte@Sun.COM 		if (maj->major == umaj) {
266*7836SJohn.Forte@Sun.COM 			devops = maj->devops;
267*7836SJohn.Forte@Sun.COM 			break;
268*7836SJohn.Forte@Sun.COM 		}
269*7836SJohn.Forte@Sun.COM 	}
270*7836SJohn.Forte@Sun.COM 
271*7836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_raw_lock);
272*7836SJohn.Forte@Sun.COM 
273*7836SJohn.Forte@Sun.COM 	return (devops);
274*7836SJohn.Forte@Sun.COM }
275*7836SJohn.Forte@Sun.COM 
276*7836SJohn.Forte@Sun.COM 
277*7836SJohn.Forte@Sun.COM /*
278*7836SJohn.Forte@Sun.COM  * _raw_open
279*7836SJohn.Forte@Sun.COM  *
280*7836SJohn.Forte@Sun.COM  * Multiple opens, single close.
281*7836SJohn.Forte@Sun.COM  */
282*7836SJohn.Forte@Sun.COM 
283*7836SJohn.Forte@Sun.COM /* ARGSUSED */
284*7836SJohn.Forte@Sun.COM static int
_raw_open(char * path,int flag,blind_t * cdp,void * iodev)285*7836SJohn.Forte@Sun.COM _raw_open(char *path, int flag, blind_t *cdp, void *iodev)
286*7836SJohn.Forte@Sun.COM {
287*7836SJohn.Forte@Sun.COM 	struct cred *cred;
288*7836SJohn.Forte@Sun.COM 	raw_dev_t *cdi = NULL;
289*7836SJohn.Forte@Sun.COM 	char *spath;
290*7836SJohn.Forte@Sun.COM 	dev_t rdev;
291*7836SJohn.Forte@Sun.COM 	int rc, cd, the_cd;
292*7836SJohn.Forte@Sun.COM 	int plen;
293*7836SJohn.Forte@Sun.COM 	ldi_ident_t	li;
294*7836SJohn.Forte@Sun.COM 
295*7836SJohn.Forte@Sun.COM 	if (proc_nskernd == NULL) {
296*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "nskern: no nskernd daemon running!");
297*7836SJohn.Forte@Sun.COM 		return (ENXIO);
298*7836SJohn.Forte@Sun.COM 	}
299*7836SJohn.Forte@Sun.COM 
300*7836SJohn.Forte@Sun.COM 	if (_nsc_raw_maxdevs == 0) {
301*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "nskern: _raw_open() before _nsc_init_raw()!");
302*7836SJohn.Forte@Sun.COM 		return (ENXIO);
303*7836SJohn.Forte@Sun.COM 	}
304*7836SJohn.Forte@Sun.COM 
305*7836SJohn.Forte@Sun.COM 	plen = strlen(path) + 1;
306*7836SJohn.Forte@Sun.COM 	spath = kmem_alloc(plen, KM_SLEEP);
307*7836SJohn.Forte@Sun.COM 	if (spath == NULL) {
308*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
309*7836SJohn.Forte@Sun.COM 		    "nskern: unable to alloc memory in _raw_open()");
310*7836SJohn.Forte@Sun.COM 		return (ENOMEM);
311*7836SJohn.Forte@Sun.COM 	}
312*7836SJohn.Forte@Sun.COM 
313*7836SJohn.Forte@Sun.COM 	(void) strcpy(spath, path);
314*7836SJohn.Forte@Sun.COM 
315*7836SJohn.Forte@Sun.COM 	/*
316*7836SJohn.Forte@Sun.COM 	 * Lookup the vnode to extract the dev_t info,
317*7836SJohn.Forte@Sun.COM 	 * then release the vnode.
318*7836SJohn.Forte@Sun.COM 	 */
319*7836SJohn.Forte@Sun.COM 	if ((rdev = ldi_get_dev_t_from_path(path)) == 0) {
320*7836SJohn.Forte@Sun.COM 		kmem_free(spath, plen);
321*7836SJohn.Forte@Sun.COM 		return (ENXIO);
322*7836SJohn.Forte@Sun.COM 	}
323*7836SJohn.Forte@Sun.COM 
324*7836SJohn.Forte@Sun.COM 	/*
325*7836SJohn.Forte@Sun.COM 	 * See if this device is already opened
326*7836SJohn.Forte@Sun.COM 	 */
327*7836SJohn.Forte@Sun.COM 
328*7836SJohn.Forte@Sun.COM 	the_cd = -1;
329*7836SJohn.Forte@Sun.COM 
330*7836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_raw_lock);
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	for (cd = 0, cdi = _nsc_raw_files; cd < fd_hwm; cd++, cdi++) {
333*7836SJohn.Forte@Sun.COM 		if (rdev == cdi->rdev) {
334*7836SJohn.Forte@Sun.COM 			the_cd = cd;
335*7836SJohn.Forte@Sun.COM 			break;
336*7836SJohn.Forte@Sun.COM 		} else if (the_cd == -1 && !cdi->in_use)
337*7836SJohn.Forte@Sun.COM 			the_cd = cd;
338*7836SJohn.Forte@Sun.COM 	}
339*7836SJohn.Forte@Sun.COM 
340*7836SJohn.Forte@Sun.COM 	if (the_cd == -1) {
341*7836SJohn.Forte@Sun.COM 		if (fd_hwm < _nsc_raw_maxdevs)
342*7836SJohn.Forte@Sun.COM 			the_cd = fd_hwm++;
343*7836SJohn.Forte@Sun.COM 		else {
344*7836SJohn.Forte@Sun.COM 			mutex_exit(&_nsc_raw_lock);
345*7836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN, "_raw_open: too many open devices");
346*7836SJohn.Forte@Sun.COM 			kmem_free(spath, plen);
347*7836SJohn.Forte@Sun.COM 			return (EIO);
348*7836SJohn.Forte@Sun.COM 		}
349*7836SJohn.Forte@Sun.COM 	}
350*7836SJohn.Forte@Sun.COM 
351*7836SJohn.Forte@Sun.COM 	cdi = &_nsc_raw_files[the_cd];
352*7836SJohn.Forte@Sun.COM 	if (cdi->in_use) {
353*7836SJohn.Forte@Sun.COM 		/* already set up - just return */
354*7836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_raw_lock);
355*7836SJohn.Forte@Sun.COM 		*cdp = (blind_t)cdi->rdev;
356*7836SJohn.Forte@Sun.COM 		kmem_free(spath, plen);
357*7836SJohn.Forte@Sun.COM 		return (0);
358*7836SJohn.Forte@Sun.COM 	}
359*7836SJohn.Forte@Sun.COM 
360*7836SJohn.Forte@Sun.COM 	cdi->partition = -1;
361*7836SJohn.Forte@Sun.COM 	cdi->size = (uint64_t)0;
362*7836SJohn.Forte@Sun.COM 	cdi->rdev = rdev;
363*7836SJohn.Forte@Sun.COM 	cdi->path = spath;
364*7836SJohn.Forte@Sun.COM 	cdi->plen = plen;
365*7836SJohn.Forte@Sun.COM 
366*7836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
367*7836SJohn.Forte@Sun.COM 
368*7836SJohn.Forte@Sun.COM 	/*
369*7836SJohn.Forte@Sun.COM 	 * Layered driver
370*7836SJohn.Forte@Sun.COM 	 *
371*7836SJohn.Forte@Sun.COM 	 * We use xxx_open_by_dev() since this guarantees that a
372*7836SJohn.Forte@Sun.COM 	 * specfs vnode is created and used, not a standard filesystem
373*7836SJohn.Forte@Sun.COM 	 * vnode. This is necessary since in a cluster PXFS will block
374*7836SJohn.Forte@Sun.COM 	 * vnode operations during switchovers, so we have to use the
375*7836SJohn.Forte@Sun.COM 	 * underlying specfs vnode not the PXFS vnode.
376*7836SJohn.Forte@Sun.COM 	 *
377*7836SJohn.Forte@Sun.COM 	 */
378*7836SJohn.Forte@Sun.COM 
379*7836SJohn.Forte@Sun.COM 	if ((rc = ldi_ident_from_dev(cdi->rdev, &li)) == 0) {
380*7836SJohn.Forte@Sun.COM 		rc = ldi_open_by_dev(&cdi->rdev,
381*7836SJohn.Forte@Sun.COM 		    OTYP_BLK, FREAD|FWRITE, cred, &cdi->lh, li);
382*7836SJohn.Forte@Sun.COM 	}
383*7836SJohn.Forte@Sun.COM 	if (rc != 0) {
384*7836SJohn.Forte@Sun.COM 		cdi->lh = NULL;
385*7836SJohn.Forte@Sun.COM 		goto failed;
386*7836SJohn.Forte@Sun.COM 	}
387*7836SJohn.Forte@Sun.COM 
388*7836SJohn.Forte@Sun.COM 	/*
389*7836SJohn.Forte@Sun.COM 	 * grab the major_t related information
390*7836SJohn.Forte@Sun.COM 	 */
391*7836SJohn.Forte@Sun.COM 
392*7836SJohn.Forte@Sun.COM 	cdi->major = _raw_get_maj_info(getmajor(rdev));
393*7836SJohn.Forte@Sun.COM 	if (cdi->major == NULL) {
394*7836SJohn.Forte@Sun.COM 		/* Out of memory */
395*7836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
396*7836SJohn.Forte@Sun.COM 		    "_raw_open: cannot alloc major number structure");
397*7836SJohn.Forte@Sun.COM 
398*7836SJohn.Forte@Sun.COM 		rc = ENOMEM;
399*7836SJohn.Forte@Sun.COM 		goto failed;
400*7836SJohn.Forte@Sun.COM 	}
401*7836SJohn.Forte@Sun.COM 
402*7836SJohn.Forte@Sun.COM 	*cdp = (blind_t)cdi->rdev;
403*7836SJohn.Forte@Sun.COM 	cdi->in_use++;
404*7836SJohn.Forte@Sun.COM 
405*7836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_raw_lock);
406*7836SJohn.Forte@Sun.COM 
407*7836SJohn.Forte@Sun.COM 	return (rc);
408*7836SJohn.Forte@Sun.COM 
409*7836SJohn.Forte@Sun.COM failed:
410*7836SJohn.Forte@Sun.COM 
411*7836SJohn.Forte@Sun.COM 	if (cdi->lh)
412*7836SJohn.Forte@Sun.COM 		(void) ldi_close(cdi->lh, FWRITE|FREAD, cred);
413*7836SJohn.Forte@Sun.COM 
414*7836SJohn.Forte@Sun.COM 	bzero(cdi, sizeof (*cdi));
415*7836SJohn.Forte@Sun.COM 
416*7836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_raw_lock);
417*7836SJohn.Forte@Sun.COM 
418*7836SJohn.Forte@Sun.COM 	kmem_free(spath, plen);
419*7836SJohn.Forte@Sun.COM 	return (rc);
420*7836SJohn.Forte@Sun.COM }
421*7836SJohn.Forte@Sun.COM 
422*7836SJohn.Forte@Sun.COM 
423*7836SJohn.Forte@Sun.COM static int
__raw_get_cd(dev_t fd)424*7836SJohn.Forte@Sun.COM __raw_get_cd(dev_t fd)
425*7836SJohn.Forte@Sun.COM {
426*7836SJohn.Forte@Sun.COM 	int cd;
427*7836SJohn.Forte@Sun.COM 
428*7836SJohn.Forte@Sun.COM 	if (_nsc_raw_maxdevs != 0) {
429*7836SJohn.Forte@Sun.COM 		for (cd = 0; cd < fd_hwm; cd++) {
430*7836SJohn.Forte@Sun.COM 			if (fd == _nsc_raw_files[cd].rdev)
431*7836SJohn.Forte@Sun.COM 				return (cd);
432*7836SJohn.Forte@Sun.COM 		}
433*7836SJohn.Forte@Sun.COM 	}
434*7836SJohn.Forte@Sun.COM 
435*7836SJohn.Forte@Sun.COM 	return (-1);
436*7836SJohn.Forte@Sun.COM }
437*7836SJohn.Forte@Sun.COM 
438*7836SJohn.Forte@Sun.COM 
439*7836SJohn.Forte@Sun.COM /*
440*7836SJohn.Forte@Sun.COM  * _raw_close
441*7836SJohn.Forte@Sun.COM  *
442*7836SJohn.Forte@Sun.COM  * Multiple opens, single close.
443*7836SJohn.Forte@Sun.COM  */
444*7836SJohn.Forte@Sun.COM 
445*7836SJohn.Forte@Sun.COM static int
_raw_close(dev_t fd)446*7836SJohn.Forte@Sun.COM _raw_close(dev_t fd)
447*7836SJohn.Forte@Sun.COM {
448*7836SJohn.Forte@Sun.COM 	struct cred *cred;
449*7836SJohn.Forte@Sun.COM 	raw_dev_t *cdi;
450*7836SJohn.Forte@Sun.COM 	int rc;
451*7836SJohn.Forte@Sun.COM 	int cd;
452*7836SJohn.Forte@Sun.COM 
453*7836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_raw_lock);
454*7836SJohn.Forte@Sun.COM 
455*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use) {
456*7836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_raw_lock);
457*7836SJohn.Forte@Sun.COM 		return (EIO);
458*7836SJohn.Forte@Sun.COM 	}
459*7836SJohn.Forte@Sun.COM 
460*7836SJohn.Forte@Sun.COM 	cdi = &_nsc_raw_files[cd];
461*7836SJohn.Forte@Sun.COM 
462*7836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
463*7836SJohn.Forte@Sun.COM 
464*7836SJohn.Forte@Sun.COM 	rc = ldi_close(cdi->lh, FREAD|FWRITE, cred);
465*7836SJohn.Forte@Sun.COM 	if (rc != 0) {
466*7836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_raw_lock);
467*7836SJohn.Forte@Sun.COM 		return (rc);
468*7836SJohn.Forte@Sun.COM 	}
469*7836SJohn.Forte@Sun.COM 
470*7836SJohn.Forte@Sun.COM 	kmem_free(cdi->path, cdi->plen);
471*7836SJohn.Forte@Sun.COM 
472*7836SJohn.Forte@Sun.COM 	bzero(cdi, sizeof (*cdi));
473*7836SJohn.Forte@Sun.COM 
474*7836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_raw_lock);
475*7836SJohn.Forte@Sun.COM 
476*7836SJohn.Forte@Sun.COM 	return (0);
477*7836SJohn.Forte@Sun.COM }
478*7836SJohn.Forte@Sun.COM 
479*7836SJohn.Forte@Sun.COM 
480*7836SJohn.Forte@Sun.COM /* ARGSUSED */
481*7836SJohn.Forte@Sun.COM static int
_raw_uread(dev_t fd,uio_t * uiop,cred_t * crp)482*7836SJohn.Forte@Sun.COM _raw_uread(dev_t fd, uio_t *uiop, cred_t *crp)
483*7836SJohn.Forte@Sun.COM {
484*7836SJohn.Forte@Sun.COM 	return (physio(_raw_strategy, 0, fd, B_READ, minphys, uiop));
485*7836SJohn.Forte@Sun.COM }
486*7836SJohn.Forte@Sun.COM 
487*7836SJohn.Forte@Sun.COM 
488*7836SJohn.Forte@Sun.COM /* ARGSUSED */
489*7836SJohn.Forte@Sun.COM static int
_raw_uwrite(dev_t fd,uio_t * uiop,cred_t * crp)490*7836SJohn.Forte@Sun.COM _raw_uwrite(dev_t fd, uio_t *uiop, cred_t *crp)
491*7836SJohn.Forte@Sun.COM {
492*7836SJohn.Forte@Sun.COM 	return (physio(_raw_strategy, 0, fd, B_WRITE, minphys, uiop));
493*7836SJohn.Forte@Sun.COM }
494*7836SJohn.Forte@Sun.COM 
495*7836SJohn.Forte@Sun.COM 
496*7836SJohn.Forte@Sun.COM static int
_raw_strategy(struct buf * bp)497*7836SJohn.Forte@Sun.COM _raw_strategy(struct buf *bp)
498*7836SJohn.Forte@Sun.COM {
499*7836SJohn.Forte@Sun.COM 	int cd = __raw_get_cd(bp->b_edev);
500*7836SJohn.Forte@Sun.COM 
501*7836SJohn.Forte@Sun.COM 	if (cd == -1 || _nsc_raw_files[cd].major == NULL) {
502*7836SJohn.Forte@Sun.COM 		bioerror(bp, ENXIO);
503*7836SJohn.Forte@Sun.COM 		biodone(bp);
504*7836SJohn.Forte@Sun.COM 		return (NULL);
505*7836SJohn.Forte@Sun.COM 	}
506*7836SJohn.Forte@Sun.COM 
507*7836SJohn.Forte@Sun.COM 	return ((*_nsc_raw_files[cd].major->strategy)(bp));
508*7836SJohn.Forte@Sun.COM }
509*7836SJohn.Forte@Sun.COM 
510*7836SJohn.Forte@Sun.COM 
511*7836SJohn.Forte@Sun.COM static int
_raw_partsize(dev_t fd,nsc_size_t * rvalp)512*7836SJohn.Forte@Sun.COM _raw_partsize(dev_t fd, nsc_size_t *rvalp)
513*7836SJohn.Forte@Sun.COM {
514*7836SJohn.Forte@Sun.COM 	int cd;
515*7836SJohn.Forte@Sun.COM 
516*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
517*7836SJohn.Forte@Sun.COM 		return (EIO);
518*7836SJohn.Forte@Sun.COM 
519*7836SJohn.Forte@Sun.COM 	*rvalp = (nsc_size_t)_nsc_raw_files[cd].size;
520*7836SJohn.Forte@Sun.COM 	return (0);
521*7836SJohn.Forte@Sun.COM }
522*7836SJohn.Forte@Sun.COM 
523*7836SJohn.Forte@Sun.COM 
524*7836SJohn.Forte@Sun.COM /*
525*7836SJohn.Forte@Sun.COM  * Return largest i/o size.
526*7836SJohn.Forte@Sun.COM  */
527*7836SJohn.Forte@Sun.COM 
528*7836SJohn.Forte@Sun.COM static nsc_size_t nsc_rawmaxfbas = 0;
529*7836SJohn.Forte@Sun.COM /* ARGSUSED */
530*7836SJohn.Forte@Sun.COM static int
_raw_maxfbas(dev_t dev,int flag,nsc_size_t * ptr)531*7836SJohn.Forte@Sun.COM _raw_maxfbas(dev_t dev, int flag, nsc_size_t *ptr)
532*7836SJohn.Forte@Sun.COM {
533*7836SJohn.Forte@Sun.COM 	struct buf *bp;
534*7836SJohn.Forte@Sun.COM 	if (flag == NSC_CACHEBLK)
535*7836SJohn.Forte@Sun.COM 		*ptr = 1;
536*7836SJohn.Forte@Sun.COM 	else {
537*7836SJohn.Forte@Sun.COM 		if (nsc_rawmaxfbas == 0) {
538*7836SJohn.Forte@Sun.COM 			bp = getrbuf(KM_SLEEP);
539*7836SJohn.Forte@Sun.COM 			bp->b_bcount = 4096 * 512;
540*7836SJohn.Forte@Sun.COM 			minphys(bp);
541*7836SJohn.Forte@Sun.COM 			nsc_rawmaxfbas = FBA_NUM(bp->b_bcount);
542*7836SJohn.Forte@Sun.COM 			freerbuf(bp);
543*7836SJohn.Forte@Sun.COM 		}
544*7836SJohn.Forte@Sun.COM 		*ptr = nsc_rawmaxfbas;
545*7836SJohn.Forte@Sun.COM 	}
546*7836SJohn.Forte@Sun.COM 	return (0);
547*7836SJohn.Forte@Sun.COM }
548*7836SJohn.Forte@Sun.COM 
549*7836SJohn.Forte@Sun.COM 
550*7836SJohn.Forte@Sun.COM /*
551*7836SJohn.Forte@Sun.COM  * Control device or system.
552*7836SJohn.Forte@Sun.COM  */
553*7836SJohn.Forte@Sun.COM 
554*7836SJohn.Forte@Sun.COM /* ARGSUSED */
555*7836SJohn.Forte@Sun.COM static int
_raw_control(dev_t dev,int cmd,int * ptr)556*7836SJohn.Forte@Sun.COM _raw_control(dev_t dev, int cmd, int *ptr)
557*7836SJohn.Forte@Sun.COM {
558*7836SJohn.Forte@Sun.COM #ifdef DEBUG
559*7836SJohn.Forte@Sun.COM 	cmn_err(CE_WARN, "unrecognised nsc_control: %x", cmd);
560*7836SJohn.Forte@Sun.COM #endif
561*7836SJohn.Forte@Sun.COM 	return (EINVAL);	/* no control commands understood */
562*7836SJohn.Forte@Sun.COM }
563*7836SJohn.Forte@Sun.COM 
564*7836SJohn.Forte@Sun.COM 
565*7836SJohn.Forte@Sun.COM static int
_raw_get_bsize(dev_t dev,uint64_t * bsizep,int * partitionp)566*7836SJohn.Forte@Sun.COM _raw_get_bsize(dev_t dev, uint64_t *bsizep, int *partitionp)
567*7836SJohn.Forte@Sun.COM {
568*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
569*7836SJohn.Forte@Sun.COM 	struct partition64 *p64 = NULL;
570*7836SJohn.Forte@Sun.COM #endif
571*7836SJohn.Forte@Sun.COM 	struct dk_cinfo *dki_info = NULL;
572*7836SJohn.Forte@Sun.COM 	struct dev_ops *ops;
573*7836SJohn.Forte@Sun.COM 	struct cred *cred;
574*7836SJohn.Forte@Sun.COM 	struct vtoc *vtoc = NULL;
575*7836SJohn.Forte@Sun.COM 	dev_info_t *dip;
576*7836SJohn.Forte@Sun.COM 	raw_dev_t *cdi;
577*7836SJohn.Forte@Sun.COM 	int rc, cd;
578*7836SJohn.Forte@Sun.COM 	int flags;
579*7836SJohn.Forte@Sun.COM 	int rval;
580*7836SJohn.Forte@Sun.COM 
581*7836SJohn.Forte@Sun.COM 	*partitionp = -1;
582*7836SJohn.Forte@Sun.COM 	*bsizep = 0;
583*7836SJohn.Forte@Sun.COM 
584*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(dev)) == -1 || !_nsc_raw_files[cd].in_use)
585*7836SJohn.Forte@Sun.COM 		return (-1);
586*7836SJohn.Forte@Sun.COM 
587*7836SJohn.Forte@Sun.COM 	cdi = &_nsc_raw_files[cd];
588*7836SJohn.Forte@Sun.COM 	ops = cdi->major->devops;
589*7836SJohn.Forte@Sun.COM 
590*7836SJohn.Forte@Sun.COM 	if (ops == NULL) {
591*7836SJohn.Forte@Sun.COM 		return (-1);
592*7836SJohn.Forte@Sun.COM 	}
593*7836SJohn.Forte@Sun.COM 
594*7836SJohn.Forte@Sun.COM 	rc = (*ops->devo_getinfo)(NULL, DDI_INFO_DEVT2DEVINFO,
595*7836SJohn.Forte@Sun.COM 	    (void *)dev, (void **)&dip);
596*7836SJohn.Forte@Sun.COM 
597*7836SJohn.Forte@Sun.COM 	if (rc != DDI_SUCCESS || dip == NULL) {
598*7836SJohn.Forte@Sun.COM 		return (-1);
599*7836SJohn.Forte@Sun.COM 	}
600*7836SJohn.Forte@Sun.COM 
601*7836SJohn.Forte@Sun.COM 	if (!ddi_prop_exists(DDI_DEV_T_ANY, dip,
602*7836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, DDI_KERNEL_IOCTL)) {
603*7836SJohn.Forte@Sun.COM 		return (-1);
604*7836SJohn.Forte@Sun.COM 	}
605*7836SJohn.Forte@Sun.COM 
606*7836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
607*7836SJohn.Forte@Sun.COM 
608*7836SJohn.Forte@Sun.COM 	flags = FKIOCTL | FREAD | FWRITE | DATAMODEL_NATIVE;
609*7836SJohn.Forte@Sun.COM 
610*7836SJohn.Forte@Sun.COM 	dki_info = kmem_alloc(sizeof (*dki_info), KM_SLEEP);
611*7836SJohn.Forte@Sun.COM 
612*7836SJohn.Forte@Sun.COM 	/* DKIOCINFO */
613*7836SJohn.Forte@Sun.COM 	rc = (*cdi->major->ioctl)(dev, DKIOCINFO,
614*7836SJohn.Forte@Sun.COM 	    (intptr_t)dki_info, flags, cred, &rval);
615*7836SJohn.Forte@Sun.COM 
616*7836SJohn.Forte@Sun.COM 	if (rc != 0) {
617*7836SJohn.Forte@Sun.COM 		goto out;
618*7836SJohn.Forte@Sun.COM 	}
619*7836SJohn.Forte@Sun.COM 
620*7836SJohn.Forte@Sun.COM 	/* return partition number */
621*7836SJohn.Forte@Sun.COM 	*partitionp = (int)dki_info->dki_partition;
622*7836SJohn.Forte@Sun.COM 
623*7836SJohn.Forte@Sun.COM 	vtoc = kmem_alloc(sizeof (*vtoc), KM_SLEEP);
624*7836SJohn.Forte@Sun.COM 
625*7836SJohn.Forte@Sun.COM 	/* DKIOCGVTOC */
626*7836SJohn.Forte@Sun.COM 	rc = (*cdi->major->ioctl)(dev, DKIOCGVTOC,
627*7836SJohn.Forte@Sun.COM 	    (intptr_t)vtoc, flags, cred, &rval);
628*7836SJohn.Forte@Sun.COM 
629*7836SJohn.Forte@Sun.COM 	if (rc) {
630*7836SJohn.Forte@Sun.COM 		/* DKIOCGVTOC failed, but there might be an EFI label */
631*7836SJohn.Forte@Sun.COM 		rc = -1;
632*7836SJohn.Forte@Sun.COM 
633*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
634*7836SJohn.Forte@Sun.COM 		/* do we have an EFI partition table? */
635*7836SJohn.Forte@Sun.COM 		p64 = kmem_alloc(sizeof (*p64), KM_SLEEP);
636*7836SJohn.Forte@Sun.COM 		p64->p_partno = (uint_t)*partitionp;
637*7836SJohn.Forte@Sun.COM 
638*7836SJohn.Forte@Sun.COM 		/* DKIOCPARTITION */
639*7836SJohn.Forte@Sun.COM 		rc = (*cdi->major->ioctl)(dev, DKIOCPARTITION,
640*7836SJohn.Forte@Sun.COM 		    (intptr_t)p64, flags, cred, &rval);
641*7836SJohn.Forte@Sun.COM 
642*7836SJohn.Forte@Sun.COM 		if (rc == 0) {
643*7836SJohn.Forte@Sun.COM 			/* found EFI, return size */
644*7836SJohn.Forte@Sun.COM 			*bsizep = (uint64_t)p64->p_size;
645*7836SJohn.Forte@Sun.COM 		} else {
646*7836SJohn.Forte@Sun.COM 			/* both DKIOCGVTOC and DKIOCPARTITION failed - error */
647*7836SJohn.Forte@Sun.COM 			rc = -1;
648*7836SJohn.Forte@Sun.COM 		}
649*7836SJohn.Forte@Sun.COM #endif
650*7836SJohn.Forte@Sun.COM 
651*7836SJohn.Forte@Sun.COM 		goto out;
652*7836SJohn.Forte@Sun.COM 	}
653*7836SJohn.Forte@Sun.COM 
654*7836SJohn.Forte@Sun.COM 	if ((vtoc->v_sanity != VTOC_SANE) ||
655*7836SJohn.Forte@Sun.COM 	    (vtoc->v_version != V_VERSION && vtoc->v_version != 0) ||
656*7836SJohn.Forte@Sun.COM 	    (dki_info->dki_partition > V_NUMPAR)) {
657*7836SJohn.Forte@Sun.COM 		rc = -1;
658*7836SJohn.Forte@Sun.COM 		goto out;
659*7836SJohn.Forte@Sun.COM 	}
660*7836SJohn.Forte@Sun.COM 
661*7836SJohn.Forte@Sun.COM 	*bsizep = (uint64_t)vtoc->v_part[(int)dki_info->dki_partition].p_size;
662*7836SJohn.Forte@Sun.COM 	rc = 0;
663*7836SJohn.Forte@Sun.COM 
664*7836SJohn.Forte@Sun.COM out:
665*7836SJohn.Forte@Sun.COM 	if (dki_info) {
666*7836SJohn.Forte@Sun.COM 		kmem_free(dki_info, sizeof (*dki_info));
667*7836SJohn.Forte@Sun.COM 	}
668*7836SJohn.Forte@Sun.COM 
669*7836SJohn.Forte@Sun.COM 	if (vtoc) {
670*7836SJohn.Forte@Sun.COM 		kmem_free(vtoc, sizeof (*vtoc));
671*7836SJohn.Forte@Sun.COM 	}
672*7836SJohn.Forte@Sun.COM 
673*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
674*7836SJohn.Forte@Sun.COM 	if (p64) {
675*7836SJohn.Forte@Sun.COM 		kmem_free(p64, sizeof (*p64));
676*7836SJohn.Forte@Sun.COM 	}
677*7836SJohn.Forte@Sun.COM #endif
678*7836SJohn.Forte@Sun.COM 
679*7836SJohn.Forte@Sun.COM 	return (rc);
680*7836SJohn.Forte@Sun.COM }
681*7836SJohn.Forte@Sun.COM 
682*7836SJohn.Forte@Sun.COM 
683*7836SJohn.Forte@Sun.COM /*
684*7836SJohn.Forte@Sun.COM  * Ugly, ugly, ugly.
685*7836SJohn.Forte@Sun.COM  *
686*7836SJohn.Forte@Sun.COM  * Some volume managers (Veritas) don't support layered ioctls
687*7836SJohn.Forte@Sun.COM  * (no FKIOCTL support, no DDI_KERNEL_IOCTL property defined) AND
688*7836SJohn.Forte@Sun.COM  * do not support the properties for bdev_Size()/bdev_size().
689*7836SJohn.Forte@Sun.COM  *
690*7836SJohn.Forte@Sun.COM  * If the underlying driver has specified DDI_KERNEL_IOCTL, then we use
691*7836SJohn.Forte@Sun.COM  * the FKIOCTL technique.  Otherwise ...
692*7836SJohn.Forte@Sun.COM  *
693*7836SJohn.Forte@Sun.COM  * The only reliable way to get the partition size, is to bounce the
694*7836SJohn.Forte@Sun.COM  * command through user land (nskernd).
695*7836SJohn.Forte@Sun.COM  *
696*7836SJohn.Forte@Sun.COM  * Then, SunCluster PXFS blocks access at the vnode level to device
697*7836SJohn.Forte@Sun.COM  * nodes during failover / switchover, so a read_vtoc() function call
698*7836SJohn.Forte@Sun.COM  * from user land deadlocks.  So, we end up coming back into the kernel
699*7836SJohn.Forte@Sun.COM  * to go directly to the underlying device driver - that's what
700*7836SJohn.Forte@Sun.COM  * nskern_bsize() is doing below.
701*7836SJohn.Forte@Sun.COM  *
702*7836SJohn.Forte@Sun.COM  * There has to be a better way ...
703*7836SJohn.Forte@Sun.COM  */
704*7836SJohn.Forte@Sun.COM 
705*7836SJohn.Forte@Sun.COM static int
_raw_init_dev(dev_t fd,uint64_t * sizep,int * partitionp)706*7836SJohn.Forte@Sun.COM _raw_init_dev(dev_t fd, uint64_t *sizep, int *partitionp)
707*7836SJohn.Forte@Sun.COM {
708*7836SJohn.Forte@Sun.COM 	struct nskernd *nsk;
709*7836SJohn.Forte@Sun.COM 	int rc, cd;
710*7836SJohn.Forte@Sun.COM 
711*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
712*7836SJohn.Forte@Sun.COM 		return (EIO);
713*7836SJohn.Forte@Sun.COM 
714*7836SJohn.Forte@Sun.COM 	/* try the in-kernel way */
715*7836SJohn.Forte@Sun.COM 
716*7836SJohn.Forte@Sun.COM 	rc = _raw_get_bsize(fd, sizep, partitionp);
717*7836SJohn.Forte@Sun.COM 	if (rc == 0) {
718*7836SJohn.Forte@Sun.COM 		return (0);
719*7836SJohn.Forte@Sun.COM 	}
720*7836SJohn.Forte@Sun.COM 
721*7836SJohn.Forte@Sun.COM 	/* fallback to the the slow way */
722*7836SJohn.Forte@Sun.COM 
723*7836SJohn.Forte@Sun.COM 	nsk = kmem_zalloc(sizeof (*nsk), KM_SLEEP);
724*7836SJohn.Forte@Sun.COM 	nsk->command = NSKERND_BSIZE;
725*7836SJohn.Forte@Sun.COM 	nsk->data1 = (uint64_t)0;
726*7836SJohn.Forte@Sun.COM 	nsk->data2 = (uint64_t)fd;
727*7836SJohn.Forte@Sun.COM 	(void) strncpy(nsk->char1, _nsc_raw_files[cd].path, NSC_MAXPATH);
728*7836SJohn.Forte@Sun.COM 
729*7836SJohn.Forte@Sun.COM 	rc = nskernd_get(nsk);
730*7836SJohn.Forte@Sun.COM 	if (rc == 0) {
731*7836SJohn.Forte@Sun.COM 		*partitionp = (int)nsk->data2;
732*7836SJohn.Forte@Sun.COM 		*sizep = nsk->data1;
733*7836SJohn.Forte@Sun.COM 	}
734*7836SJohn.Forte@Sun.COM 
735*7836SJohn.Forte@Sun.COM 	kmem_free(nsk, sizeof (*nsk));
736*7836SJohn.Forte@Sun.COM 	return (rc < 0 ? EIO : 0);
737*7836SJohn.Forte@Sun.COM }
738*7836SJohn.Forte@Sun.COM 
739*7836SJohn.Forte@Sun.COM 
740*7836SJohn.Forte@Sun.COM static int
_raw_attach_io(dev_t fd)741*7836SJohn.Forte@Sun.COM _raw_attach_io(dev_t fd)
742*7836SJohn.Forte@Sun.COM {
743*7836SJohn.Forte@Sun.COM 	int cd;
744*7836SJohn.Forte@Sun.COM 
745*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
746*7836SJohn.Forte@Sun.COM 		return (EIO);
747*7836SJohn.Forte@Sun.COM 
748*7836SJohn.Forte@Sun.COM 	return (_raw_init_dev(fd, &_nsc_raw_files[cd].size,
749*7836SJohn.Forte@Sun.COM 	    &_nsc_raw_files[cd].partition));
750*7836SJohn.Forte@Sun.COM }
751*7836SJohn.Forte@Sun.COM 
752*7836SJohn.Forte@Sun.COM 
753*7836SJohn.Forte@Sun.COM /*
754*7836SJohn.Forte@Sun.COM  * See the comment above _raw_init_dev().
755*7836SJohn.Forte@Sun.COM  */
756*7836SJohn.Forte@Sun.COM 
757*7836SJohn.Forte@Sun.COM int
nskern_bsize(struct nscioc_bsize * bsize,int * rvp)758*7836SJohn.Forte@Sun.COM nskern_bsize(struct nscioc_bsize *bsize, int *rvp)
759*7836SJohn.Forte@Sun.COM {
760*7836SJohn.Forte@Sun.COM 	struct cred *cred;
761*7836SJohn.Forte@Sun.COM 	raw_dev_t *cdi;
762*7836SJohn.Forte@Sun.COM 	int errno = 0;
763*7836SJohn.Forte@Sun.COM 	int flag;
764*7836SJohn.Forte@Sun.COM 	int cd;
765*7836SJohn.Forte@Sun.COM 
766*7836SJohn.Forte@Sun.COM 	*rvp = 0;
767*7836SJohn.Forte@Sun.COM 
768*7836SJohn.Forte@Sun.COM 	if (bsize == NULL || rvp == NULL)
769*7836SJohn.Forte@Sun.COM 		return (EINVAL);
770*7836SJohn.Forte@Sun.COM 
771*7836SJohn.Forte@Sun.COM 	cd = __raw_get_cd(bsize->raw_fd);
772*7836SJohn.Forte@Sun.COM 	if (cd == -1 || !_nsc_raw_files[cd].in_use)
773*7836SJohn.Forte@Sun.COM 		return (EIO);
774*7836SJohn.Forte@Sun.COM 
775*7836SJohn.Forte@Sun.COM 	cdi = &_nsc_raw_files[cd];
776*7836SJohn.Forte@Sun.COM 	cred = ddi_get_cred();
777*7836SJohn.Forte@Sun.COM 
778*7836SJohn.Forte@Sun.COM 	/*
779*7836SJohn.Forte@Sun.COM 	 * ddi_mmap_get_model() returns the model for this user thread
780*7836SJohn.Forte@Sun.COM 	 * which is what we want - get_udatamodel() is not public.
781*7836SJohn.Forte@Sun.COM 	 */
782*7836SJohn.Forte@Sun.COM 
783*7836SJohn.Forte@Sun.COM 	flag = FREAD | FWRITE | ddi_mmap_get_model();
784*7836SJohn.Forte@Sun.COM 
785*7836SJohn.Forte@Sun.COM 	if (bsize->efi == 0) {
786*7836SJohn.Forte@Sun.COM 		/* DKIOCINFO */
787*7836SJohn.Forte@Sun.COM 		errno = (*cdi->major->ioctl)(bsize->raw_fd,
788*7836SJohn.Forte@Sun.COM 		    DKIOCINFO, (intptr_t)bsize->dki_info, flag, cred, rvp);
789*7836SJohn.Forte@Sun.COM 
790*7836SJohn.Forte@Sun.COM 		if (errno) {
791*7836SJohn.Forte@Sun.COM 			return (errno);
792*7836SJohn.Forte@Sun.COM 		}
793*7836SJohn.Forte@Sun.COM 
794*7836SJohn.Forte@Sun.COM 		/* DKIOCGVTOC */
795*7836SJohn.Forte@Sun.COM 		errno = (*cdi->major->ioctl)(bsize->raw_fd,
796*7836SJohn.Forte@Sun.COM 		    DKIOCGVTOC, (intptr_t)bsize->vtoc, flag, cred, rvp);
797*7836SJohn.Forte@Sun.COM 
798*7836SJohn.Forte@Sun.COM 		if (errno) {
799*7836SJohn.Forte@Sun.COM 			return (errno);
800*7836SJohn.Forte@Sun.COM 		}
801*7836SJohn.Forte@Sun.COM 	} else {
802*7836SJohn.Forte@Sun.COM #ifdef DKIOCPARTITION
803*7836SJohn.Forte@Sun.COM 		/* do we have an EFI partition table? */
804*7836SJohn.Forte@Sun.COM 		errno = (*cdi->major->ioctl)(bsize->raw_fd,
805*7836SJohn.Forte@Sun.COM 		    DKIOCPARTITION, (intptr_t)bsize->p64, flag, cred, rvp);
806*7836SJohn.Forte@Sun.COM 
807*7836SJohn.Forte@Sun.COM 		if (errno) {
808*7836SJohn.Forte@Sun.COM 			return (errno);
809*7836SJohn.Forte@Sun.COM 		}
810*7836SJohn.Forte@Sun.COM #endif
811*7836SJohn.Forte@Sun.COM 	}
812*7836SJohn.Forte@Sun.COM 
813*7836SJohn.Forte@Sun.COM 	return (0);
814*7836SJohn.Forte@Sun.COM }
815*7836SJohn.Forte@Sun.COM 
816*7836SJohn.Forte@Sun.COM 
817*7836SJohn.Forte@Sun.COM /*
818*7836SJohn.Forte@Sun.COM  * Private function for sv to use.
819*7836SJohn.Forte@Sun.COM  */
820*7836SJohn.Forte@Sun.COM int
nskern_partition(dev_t fd,int * partitionp)821*7836SJohn.Forte@Sun.COM nskern_partition(dev_t fd, int *partitionp)
822*7836SJohn.Forte@Sun.COM {
823*7836SJohn.Forte@Sun.COM 	uint64_t size;
824*7836SJohn.Forte@Sun.COM 	int cd, rc;
825*7836SJohn.Forte@Sun.COM 
826*7836SJohn.Forte@Sun.COM 	if ((cd = __raw_get_cd(fd)) == -1 || !_nsc_raw_files[cd].in_use)
827*7836SJohn.Forte@Sun.COM 		return (EIO);
828*7836SJohn.Forte@Sun.COM 
829*7836SJohn.Forte@Sun.COM 	if ((*partitionp = _nsc_raw_files[cd].partition) != -1) {
830*7836SJohn.Forte@Sun.COM 		return (0);
831*7836SJohn.Forte@Sun.COM 	}
832*7836SJohn.Forte@Sun.COM 
833*7836SJohn.Forte@Sun.COM 	rc = _raw_init_dev(fd, &size, partitionp);
834*7836SJohn.Forte@Sun.COM 	if (rc != 0 || *partitionp < 0) {
835*7836SJohn.Forte@Sun.COM 		return (EIO);
836*7836SJohn.Forte@Sun.COM 	}
837*7836SJohn.Forte@Sun.COM 
838*7836SJohn.Forte@Sun.COM 	return (0);
839*7836SJohn.Forte@Sun.COM }
840*7836SJohn.Forte@Sun.COM 
841*7836SJohn.Forte@Sun.COM 
842*7836SJohn.Forte@Sun.COM nsc_def_t _nsc_raw_def[] = {
843*7836SJohn.Forte@Sun.COM 	"Open",		(uintptr_t)_raw_open,		0,
844*7836SJohn.Forte@Sun.COM 	"Close",	(uintptr_t)_raw_close,		0,
845*7836SJohn.Forte@Sun.COM 	"Attach",	(uintptr_t)_raw_attach_io,	0,
846*7836SJohn.Forte@Sun.COM 	"UserRead",	(uintptr_t)_raw_uread,		0,
847*7836SJohn.Forte@Sun.COM 	"UserWrite",	(uintptr_t)_raw_uwrite,		0,
848*7836SJohn.Forte@Sun.COM 	"PartSize",	(uintptr_t)_raw_partsize,	0,
849*7836SJohn.Forte@Sun.COM 	"MaxFbas",	(uintptr_t)_raw_maxfbas,	0,
850*7836SJohn.Forte@Sun.COM 	"Control",	(uintptr_t)_raw_control,	0,
851*7836SJohn.Forte@Sun.COM 	"Provide",	NSC_DEVICE,			0,
852*7836SJohn.Forte@Sun.COM 	0,		0,				0
853*7836SJohn.Forte@Sun.COM };
854