xref: /titanic_53/usr/src/uts/common/fs/fem.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/mutex.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <sys/fem.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #define	NNODES_DEFAULT	8	/* Default number of nodes in a fem_list */
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  * fl_ntob(n) - Fem_list: number of nodes to bytes
47*7c478bd9Sstevel@tonic-gate  * Given the number of nodes in a fem_list return the size, in bytes,
48*7c478bd9Sstevel@tonic-gate  * of the fem_list structure.
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate #define	fl_ntob(n)	(sizeof (struct fem_list) + \
51*7c478bd9Sstevel@tonic-gate 			((n) - 1) * sizeof (struct fem_node))
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate typedef enum {
54*7c478bd9Sstevel@tonic-gate 	FEMTYPE_NULL,	/* Uninitialized */
55*7c478bd9Sstevel@tonic-gate 	FEMTYPE_VNODE,
56*7c478bd9Sstevel@tonic-gate 	FEMTYPE_VFS,
57*7c478bd9Sstevel@tonic-gate 	FEMTYPE_NTYPES
58*7c478bd9Sstevel@tonic-gate } femtype_t;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #define	FEM_HEAD(_t) femtype[(_t)].head.fn_op.anon
61*7c478bd9Sstevel@tonic-gate #define	FEM_GUARD(_t) femtype[(_t)].guard
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static struct fem_type_info {
64*7c478bd9Sstevel@tonic-gate 	struct fem_node		head;
65*7c478bd9Sstevel@tonic-gate 	struct fem_node		guard;
66*7c478bd9Sstevel@tonic-gate 	femop_t			*errf;
67*7c478bd9Sstevel@tonic-gate }	femtype[FEMTYPE_NTYPES];
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate  * For each type, two tables - the translation offset definition, which
72*7c478bd9Sstevel@tonic-gate  * is used by fs_build_vector to layout the operation(s) vector; and the
73*7c478bd9Sstevel@tonic-gate  * guard_operation_vector which protects from stack under-run.
74*7c478bd9Sstevel@tonic-gate  */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate int fem_err();
77*7c478bd9Sstevel@tonic-gate int fsem_err();
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate #define	_FEMOPDEF(name, member)  \
81*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_##name, offsetof(fem_t, vsop_##member), NULL, fem_err }
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate static fs_operation_trans_def_t	fem_opdef[] = {
84*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(OPEN,		open),
85*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(CLOSE,	close),
86*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(READ,		read),
87*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(WRITE,	write),
88*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(IOCTL,	ioctl),
89*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SETFL,	setfl),
90*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(GETATTR,	getattr),
91*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SETATTR,	setattr),
92*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(ACCESS,	access),
93*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(LOOKUP,	lookup),
94*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(CREATE,	create),
95*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(REMOVE,	remove),
96*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(LINK,		link),
97*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(RENAME,	rename),
98*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(MKDIR,	mkdir),
99*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(RMDIR,	rmdir),
100*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(READDIR,	readdir),
101*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SYMLINK,	symlink),
102*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(READLINK,	readlink),
103*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(FSYNC,	fsync),
104*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(INACTIVE,	inactive),
105*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(FID,		fid),
106*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(RWLOCK,	rwlock),
107*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(RWUNLOCK,	rwunlock),
108*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SEEK,		seek),
109*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(CMP,		cmp),
110*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(FRLOCK,	frlock),
111*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SPACE,	space),
112*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(REALVP,	realvp),
113*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(GETPAGE,	getpage),
114*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(PUTPAGE,	putpage),
115*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(MAP,		map),
116*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(ADDMAP,	addmap),
117*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(DELMAP,	delmap),
118*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(POLL,		poll),
119*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(DUMP,		dump),
120*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(PATHCONF,	pathconf),
121*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(PAGEIO,	pageio),
122*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(DUMPCTL,	dumpctl),
123*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(DISPOSE,	dispose),
124*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SETSECATTR,	setsecattr),
125*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(GETSECATTR,	getsecattr),
126*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(SHRLOCK,	shrlock),
127*7c478bd9Sstevel@tonic-gate 	_FEMOPDEF(VNEVENT,	vnevent),
128*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, NULL, NULL }
129*7c478bd9Sstevel@tonic-gate };
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate #define	_FEMGUARD(name, ignore)  \
133*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_##name, (femop_t *)fem_err }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate static struct fs_operation_def fem_guard_ops[] = {
136*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(OPEN,		open),
137*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(CLOSE,	close),
138*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(READ,		read),
139*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(WRITE,	write),
140*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(IOCTL,	ioctl),
141*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SETFL,	setfl),
142*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(GETATTR,	getattr),
143*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SETATTR,	setattr),
144*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(ACCESS,	access),
145*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(LOOKUP,	lookup),
146*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(CREATE,	create),
147*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(REMOVE,	remove),
148*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(LINK,		link),
149*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(RENAME,	rename),
150*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(MKDIR,	mkdir),
151*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(RMDIR,	rmdir),
152*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(READDIR,	readdir),
153*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SYMLINK,	symlink),
154*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(READLINK,	readlink),
155*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(FSYNC,	fsync),
156*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(INACTIVE,	inactive),
157*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(FID,		fid),
158*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(RWLOCK,	rwlock),
159*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(RWUNLOCK,	rwunlock),
160*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SEEK,		seek),
161*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(CMP,		cmp),
162*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(FRLOCK,	frlock),
163*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SPACE,	space),
164*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(REALVP,	realvp),
165*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(GETPAGE,	getpage),
166*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(PUTPAGE,	putpage),
167*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(MAP,		map),
168*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(ADDMAP,	addmap),
169*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(DELMAP,	delmap),
170*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(POLL,		poll),
171*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(DUMP,		dump),
172*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(PATHCONF,	pathconf),
173*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(PAGEIO,	pageio),
174*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(DUMPCTL,	dumpctl),
175*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(DISPOSE,	dispose),
176*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SETSECATTR,	setsecattr),
177*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(GETSECATTR,	getsecattr),
178*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(SHRLOCK,	shrlock),
179*7c478bd9Sstevel@tonic-gate 	_FEMGUARD(VNEVENT,	vnevent),
180*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
181*7c478bd9Sstevel@tonic-gate };
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate #define	_FSEMOPDEF(name, member)  \
185*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_##name, offsetof(fsem_t, vfsop_##member), NULL, fsem_err }
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate static fs_operation_trans_def_t fsem_opdef[] = {
188*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(MOUNT, 	mount),
189*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(UNMOUNT,	unmount),
190*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(ROOT,	root),
191*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(STATVFS,	statvfs),
192*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(SYNC,	sync),
193*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(VGET,	vget),
194*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(MOUNTROOT,	mountroot),
195*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(FREEVFS,	freevfs),
196*7c478bd9Sstevel@tonic-gate 	_FSEMOPDEF(VNSTATE,	vnstate),
197*7c478bd9Sstevel@tonic-gate 	{ NULL, 0, NULL, NULL }
198*7c478bd9Sstevel@tonic-gate };
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate #define	_FSEMGUARD(name, ignore)  \
201*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_##name, (femop_t *)fsem_err }
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate static struct fs_operation_def fsem_guard_ops[] = {
204*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(MOUNT, 	mount),
205*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(UNMOUNT,	unmount),
206*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(ROOT,	root),
207*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(STATVFS,	statvfs),
208*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(SYNC,	sync),
209*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(VGET,	vget),
210*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(MOUNTROOT,	mountroot),
211*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(FREEVFS,	freevfs),
212*7c478bd9Sstevel@tonic-gate 	_FSEMGUARD(VNSTATE,	vnstate),
213*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL}
214*7c478bd9Sstevel@tonic-gate };
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * vsop_find, vfsop_find -
219*7c478bd9Sstevel@tonic-gate  *
220*7c478bd9Sstevel@tonic-gate  * These macros descend the stack until they find either a basic
221*7c478bd9Sstevel@tonic-gate  * vnode/vfs operation [ indicated by a null fn_available ] or a
222*7c478bd9Sstevel@tonic-gate  * stacked item where this method is non-null [_vsop].
223*7c478bd9Sstevel@tonic-gate  *
224*7c478bd9Sstevel@tonic-gate  * The DEBUG one is written with a single function which manually applies
225*7c478bd9Sstevel@tonic-gate  * the structure offsets.  It can have additional debugging support.
226*7c478bd9Sstevel@tonic-gate  */
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate #ifndef DEBUG
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate #define	vsop_find(ap, func, funct, arg0, _vop, _vsop) \
231*7c478bd9Sstevel@tonic-gate for (;;) { \
232*7c478bd9Sstevel@tonic-gate 	if ((ap)->fa_fnode->fn_available == NULL) { \
233*7c478bd9Sstevel@tonic-gate 		*(func) = (funct (*)())((ap)->fa_fnode->fn_op.vnode->_vop); \
234*7c478bd9Sstevel@tonic-gate 		*(arg0) = (void *)(ap)->fa_vnode.vp; \
235*7c478bd9Sstevel@tonic-gate 		break;	\
236*7c478bd9Sstevel@tonic-gate 	} else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fem->_vsop))\
237*7c478bd9Sstevel@tonic-gate 		    != NULL) { \
238*7c478bd9Sstevel@tonic-gate 		*(arg0) = (void *) (ap); \
239*7c478bd9Sstevel@tonic-gate 		break;	\
240*7c478bd9Sstevel@tonic-gate 	} else { \
241*7c478bd9Sstevel@tonic-gate 		(ap)->fa_fnode--; \
242*7c478bd9Sstevel@tonic-gate 	} \
243*7c478bd9Sstevel@tonic-gate } \
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate #define	vfsop_find(ap, func, funct, arg0, _vop, _vsop) \
246*7c478bd9Sstevel@tonic-gate for (;;) { \
247*7c478bd9Sstevel@tonic-gate 	if ((ap)->fa_fnode->fn_available == NULL) { \
248*7c478bd9Sstevel@tonic-gate 		*(func) = (funct (*)())((ap)->fa_fnode->fn_op.vfs->_vop); \
249*7c478bd9Sstevel@tonic-gate 		*(arg0) = (void *)(ap)->fa_vnode.vp; \
250*7c478bd9Sstevel@tonic-gate 		break; \
251*7c478bd9Sstevel@tonic-gate 	} else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fsem->_vsop))\
252*7c478bd9Sstevel@tonic-gate 		    != NULL) { \
253*7c478bd9Sstevel@tonic-gate 		*(arg0) = (void *) (ap); \
254*7c478bd9Sstevel@tonic-gate 		break; \
255*7c478bd9Sstevel@tonic-gate 	} else { \
256*7c478bd9Sstevel@tonic-gate 		(ap)->fa_fnode--; \
257*7c478bd9Sstevel@tonic-gate 	} \
258*7c478bd9Sstevel@tonic-gate } \
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate #else
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate #define	vsop_find(ap, func, funct, arg0, _vop, _vsop) \
263*7c478bd9Sstevel@tonic-gate 	*(arg0) = _op_find((ap), (void **)(func), \
264*7c478bd9Sstevel@tonic-gate 			offsetof(vnodeops_t, _vop), offsetof(fem_t, _vsop))
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate #define	vfsop_find(ap, func, funct, arg0, _fop, _fsop) \
267*7c478bd9Sstevel@tonic-gate 	*(arg0) = _op_find((ap), (void **)(func), \
268*7c478bd9Sstevel@tonic-gate 			offsetof(vfsops_t, _fop), offsetof(fsem_t, _fsop))
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate static void *
271*7c478bd9Sstevel@tonic-gate _op_find(femarg_t *ap, void **fp, int offs0, int offs1)
272*7c478bd9Sstevel@tonic-gate {
273*7c478bd9Sstevel@tonic-gate 	void *ptr;
274*7c478bd9Sstevel@tonic-gate 	for (;;) {
275*7c478bd9Sstevel@tonic-gate 		struct fem_node	*fnod = ap->fa_fnode;
276*7c478bd9Sstevel@tonic-gate 		if (fnod->fn_available == NULL) {
277*7c478bd9Sstevel@tonic-gate 			*fp = *(void **)((char *)fnod->fn_op.anon + offs0);
278*7c478bd9Sstevel@tonic-gate 			ptr = (void *)(ap->fa_vnode.anon);
279*7c478bd9Sstevel@tonic-gate 			break;
280*7c478bd9Sstevel@tonic-gate 		} else if ((*fp = *(void **)((char *)fnod->fn_op.anon+offs1))
281*7c478bd9Sstevel@tonic-gate 			!= NULL) {
282*7c478bd9Sstevel@tonic-gate 			ptr = (void *)(ap);
283*7c478bd9Sstevel@tonic-gate 			break;
284*7c478bd9Sstevel@tonic-gate 		} else {
285*7c478bd9Sstevel@tonic-gate 			ap->fa_fnode--;
286*7c478bd9Sstevel@tonic-gate 		}
287*7c478bd9Sstevel@tonic-gate 	}
288*7c478bd9Sstevel@tonic-gate 	return (ptr);
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate #endif
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate static fem_t *
293*7c478bd9Sstevel@tonic-gate fem_alloc()
294*7c478bd9Sstevel@tonic-gate {
295*7c478bd9Sstevel@tonic-gate 	fem_t	*p;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	p = (fem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
298*7c478bd9Sstevel@tonic-gate 	return (p);
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate void
302*7c478bd9Sstevel@tonic-gate fem_free(fem_t *p)
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate 	kmem_free(p, sizeof (*p));
305*7c478bd9Sstevel@tonic-gate }
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate static fsem_t *
308*7c478bd9Sstevel@tonic-gate fsem_alloc()
309*7c478bd9Sstevel@tonic-gate {
310*7c478bd9Sstevel@tonic-gate 	fsem_t	*p;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	p = (fsem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
313*7c478bd9Sstevel@tonic-gate 	return (p);
314*7c478bd9Sstevel@tonic-gate }
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate void
317*7c478bd9Sstevel@tonic-gate fsem_free(fsem_t *p)
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	kmem_free(p, sizeof (*p));
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate /*
324*7c478bd9Sstevel@tonic-gate  * fem_get, fem_release - manage reference counts on the stack.
325*7c478bd9Sstevel@tonic-gate  *
326*7c478bd9Sstevel@tonic-gate  * The list of monitors can be updated while operations are in
327*7c478bd9Sstevel@tonic-gate  * progress on the object.
328*7c478bd9Sstevel@tonic-gate  *
329*7c478bd9Sstevel@tonic-gate  * The reference count facilitates this by counting the number of
330*7c478bd9Sstevel@tonic-gate  * current accessors, and deconstructing the list when it is exhausted.
331*7c478bd9Sstevel@tonic-gate  *
332*7c478bd9Sstevel@tonic-gate  * fem_lock() is required to:
333*7c478bd9Sstevel@tonic-gate  *	look at femh_list
334*7c478bd9Sstevel@tonic-gate  *	update what femh_list points to
335*7c478bd9Sstevel@tonic-gate  *	update femh_list
336*7c478bd9Sstevel@tonic-gate  *	increase femh_list->feml_refc.
337*7c478bd9Sstevel@tonic-gate  *
338*7c478bd9Sstevel@tonic-gate  * the feml_refc can decrement without holding the lock;
339*7c478bd9Sstevel@tonic-gate  * when feml_refc becomes zero, the list is destroyed.
340*7c478bd9Sstevel@tonic-gate  *
341*7c478bd9Sstevel@tonic-gate  */
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate static struct fem_list *
344*7c478bd9Sstevel@tonic-gate fem_lock(struct fem_head *fp)
345*7c478bd9Sstevel@tonic-gate {
346*7c478bd9Sstevel@tonic-gate 	struct fem_list	*sp = NULL;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	ASSERT(fp != NULL);
349*7c478bd9Sstevel@tonic-gate 	mutex_enter(&fp->femh_lock);
350*7c478bd9Sstevel@tonic-gate 	sp = fp->femh_list;
351*7c478bd9Sstevel@tonic-gate 	return (sp);
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate static void
355*7c478bd9Sstevel@tonic-gate fem_unlock(struct fem_head *fp)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	ASSERT(fp != NULL);
358*7c478bd9Sstevel@tonic-gate 	mutex_exit(&fp->femh_lock);
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate  * Addref can only be called while its head->lock is held.
363*7c478bd9Sstevel@tonic-gate  */
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate static void
366*7c478bd9Sstevel@tonic-gate fem_addref(struct fem_list *sp)
367*7c478bd9Sstevel@tonic-gate {
368*7c478bd9Sstevel@tonic-gate 	atomic_add_32(&sp->feml_refc, 1);
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate static void
372*7c478bd9Sstevel@tonic-gate fem_delref(struct fem_list *sp)
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	(void) atomic_add_32_nv(&sp->feml_refc, -1);
375*7c478bd9Sstevel@tonic-gate }
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate static struct fem_list *
378*7c478bd9Sstevel@tonic-gate fem_get(struct fem_head *fp)
379*7c478bd9Sstevel@tonic-gate {
380*7c478bd9Sstevel@tonic-gate 	struct fem_list *sp = NULL;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	if (fp != NULL) {
383*7c478bd9Sstevel@tonic-gate 		if ((sp = fem_lock(fp)) != NULL) {
384*7c478bd9Sstevel@tonic-gate 			fem_addref(sp);
385*7c478bd9Sstevel@tonic-gate 		}
386*7c478bd9Sstevel@tonic-gate 		fem_unlock(fp);
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 	return (sp);
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate static void
392*7c478bd9Sstevel@tonic-gate fem_release(struct fem_list *sp)
393*7c478bd9Sstevel@tonic-gate {
394*7c478bd9Sstevel@tonic-gate 	int	i;
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	if (sp->feml_refc != 0) {
397*7c478bd9Sstevel@tonic-gate 		fem_delref(sp);
398*7c478bd9Sstevel@tonic-gate 	}
399*7c478bd9Sstevel@tonic-gate 	if (sp->feml_refc == 0) {
400*7c478bd9Sstevel@tonic-gate 		/*
401*7c478bd9Sstevel@tonic-gate 		 * Before freeing the list, we need to release the
402*7c478bd9Sstevel@tonic-gate 		 * caller-provided data.
403*7c478bd9Sstevel@tonic-gate 		 */
404*7c478bd9Sstevel@tonic-gate 		for (i = sp->feml_tos; i > 0; i--) {
405*7c478bd9Sstevel@tonic-gate 			struct fem_node *fnp = &sp->feml_nodes[i];
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 			if (fnp->fn_av_rele)
408*7c478bd9Sstevel@tonic-gate 				(*(fnp->fn_av_rele))(fnp->fn_available);
409*7c478bd9Sstevel@tonic-gate 		}
410*7c478bd9Sstevel@tonic-gate 		kmem_free(sp, fl_ntob(sp->feml_ssize));
411*7c478bd9Sstevel@tonic-gate 	}
412*7c478bd9Sstevel@tonic-gate }
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate /*
416*7c478bd9Sstevel@tonic-gate  * These are the 'head' operations which perform the interposition.
417*7c478bd9Sstevel@tonic-gate  *
418*7c478bd9Sstevel@tonic-gate  * This set must be 1:1, onto with the (vnodeops, vfsos).
419*7c478bd9Sstevel@tonic-gate  *
420*7c478bd9Sstevel@tonic-gate  * If there is a desire to globally disable interposition for a particular
421*7c478bd9Sstevel@tonic-gate  * method, the corresponding 'head' routine should unearth the base method
422*7c478bd9Sstevel@tonic-gate  * and invoke it directly rather than bypassing the function.
423*7c478bd9Sstevel@tonic-gate  *
424*7c478bd9Sstevel@tonic-gate  * All the functions are virtually the same, save for names, types & args.
425*7c478bd9Sstevel@tonic-gate  *  1. get a reference to the monitor stack for this object.
426*7c478bd9Sstevel@tonic-gate  *  2. store the top of stack into the femarg structure.
427*7c478bd9Sstevel@tonic-gate  *  3. store the basic object (vnode *, vnode **, vfs *) in the femarg struc.
428*7c478bd9Sstevel@tonic-gate  *  4. invoke the "top" method for this object.
429*7c478bd9Sstevel@tonic-gate  *  5. release the reference to the monitor stack.
430*7c478bd9Sstevel@tonic-gate  *
431*7c478bd9Sstevel@tonic-gate  */
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate static int
434*7c478bd9Sstevel@tonic-gate vhead_open(vnode_t **vpp, int mode, cred_t *cr)
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
437*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
438*7c478bd9Sstevel@tonic-gate 	int		(*func)();
439*7c478bd9Sstevel@tonic-gate 	void		*arg0;
440*7c478bd9Sstevel@tonic-gate 	int		errc;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock((*vpp)->v_femhead)) == NULL) {
443*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) ((*vpp)->v_op->vop_open);
444*7c478bd9Sstevel@tonic-gate 		arg0 = (void *)vpp;
445*7c478bd9Sstevel@tonic-gate 		fem_unlock((*vpp)->v_femhead);
446*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, mode, cr);
447*7c478bd9Sstevel@tonic-gate 	} else {
448*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
449*7c478bd9Sstevel@tonic-gate 		fem_unlock((*vpp)->v_femhead);
450*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vpp = vpp;
451*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
452*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_open, vsop_open);
453*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, mode, cr);
454*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 	return (errc);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate static int
460*7c478bd9Sstevel@tonic-gate vhead_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
461*7c478bd9Sstevel@tonic-gate {
462*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
463*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
464*7c478bd9Sstevel@tonic-gate 	int		(*func)();
465*7c478bd9Sstevel@tonic-gate 	void		*arg0;
466*7c478bd9Sstevel@tonic-gate 	int		errc;
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
469*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_close);
470*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
471*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
472*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, flag, count, offset, cr);
473*7c478bd9Sstevel@tonic-gate 	} else {
474*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
475*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
476*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
477*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
478*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_close, vsop_close);
479*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, flag, count, offset, cr);
480*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
481*7c478bd9Sstevel@tonic-gate 	}
482*7c478bd9Sstevel@tonic-gate 	return (errc);
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate static int
486*7c478bd9Sstevel@tonic-gate vhead_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
487*7c478bd9Sstevel@tonic-gate 	struct caller_context *ct)
488*7c478bd9Sstevel@tonic-gate {
489*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
490*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
491*7c478bd9Sstevel@tonic-gate 	int		(*func)();
492*7c478bd9Sstevel@tonic-gate 	void		*arg0;
493*7c478bd9Sstevel@tonic-gate 	int		errc;
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
496*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_read);
497*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
498*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
499*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
500*7c478bd9Sstevel@tonic-gate 	} else {
501*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
502*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
503*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
504*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
505*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_read, vsop_read);
506*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
507*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
508*7c478bd9Sstevel@tonic-gate 	}
509*7c478bd9Sstevel@tonic-gate 	return (errc);
510*7c478bd9Sstevel@tonic-gate }
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate static int
513*7c478bd9Sstevel@tonic-gate vhead_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
514*7c478bd9Sstevel@tonic-gate 	struct caller_context *ct)
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
517*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
518*7c478bd9Sstevel@tonic-gate 	int		(*func)();
519*7c478bd9Sstevel@tonic-gate 	void		*arg0;
520*7c478bd9Sstevel@tonic-gate 	int		errc;
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
523*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_write);
524*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
525*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
526*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
527*7c478bd9Sstevel@tonic-gate 	} else {
528*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
529*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
530*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
531*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
532*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_write, vsop_write);
533*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
534*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
535*7c478bd9Sstevel@tonic-gate 	}
536*7c478bd9Sstevel@tonic-gate 	return (errc);
537*7c478bd9Sstevel@tonic-gate }
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate static int
540*7c478bd9Sstevel@tonic-gate vhead_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
541*7c478bd9Sstevel@tonic-gate 	int *rvalp)
542*7c478bd9Sstevel@tonic-gate {
543*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
544*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
545*7c478bd9Sstevel@tonic-gate 	int		(*func)();
546*7c478bd9Sstevel@tonic-gate 	void		*arg0;
547*7c478bd9Sstevel@tonic-gate 	int		errc;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
550*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_ioctl);
551*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
552*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
553*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, arg, flag, cr, rvalp);
554*7c478bd9Sstevel@tonic-gate 	} else {
555*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
556*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
557*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
558*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
559*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_ioctl, vsop_ioctl);
560*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, arg, flag, cr, rvalp);
561*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 	return (errc);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate static int
567*7c478bd9Sstevel@tonic-gate vhead_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
570*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
571*7c478bd9Sstevel@tonic-gate 	int		(*func)();
572*7c478bd9Sstevel@tonic-gate 	void		*arg0;
573*7c478bd9Sstevel@tonic-gate 	int		errc;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
576*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_setfl);
577*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
578*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
579*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, oflags, nflags, cr);
580*7c478bd9Sstevel@tonic-gate 	} else {
581*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
582*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
583*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
584*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
585*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_setfl, vsop_setfl);
586*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, oflags, nflags, cr);
587*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
588*7c478bd9Sstevel@tonic-gate 	}
589*7c478bd9Sstevel@tonic-gate 	return (errc);
590*7c478bd9Sstevel@tonic-gate }
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate static int
593*7c478bd9Sstevel@tonic-gate vhead_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
594*7c478bd9Sstevel@tonic-gate {
595*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
596*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
597*7c478bd9Sstevel@tonic-gate 	int		(*func)();
598*7c478bd9Sstevel@tonic-gate 	void		*arg0;
599*7c478bd9Sstevel@tonic-gate 	int		errc;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
602*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_getattr);
603*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
604*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
605*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vap, flags, cr);
606*7c478bd9Sstevel@tonic-gate 	} else {
607*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
608*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
609*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
610*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
611*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_getattr,
612*7c478bd9Sstevel@tonic-gate 			vsop_getattr);
613*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vap, flags, cr);
614*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
615*7c478bd9Sstevel@tonic-gate 	}
616*7c478bd9Sstevel@tonic-gate 	return (errc);
617*7c478bd9Sstevel@tonic-gate }
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate static int
620*7c478bd9Sstevel@tonic-gate vhead_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
621*7c478bd9Sstevel@tonic-gate 	caller_context_t *ct)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
624*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
625*7c478bd9Sstevel@tonic-gate 	int		(*func)();
626*7c478bd9Sstevel@tonic-gate 	void		*arg0;
627*7c478bd9Sstevel@tonic-gate 	int		errc;
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
630*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_setattr);
631*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
632*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
633*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vap, flags, cr, ct);
634*7c478bd9Sstevel@tonic-gate 	} else {
635*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
636*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
637*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
638*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
639*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_setattr,
640*7c478bd9Sstevel@tonic-gate 			vsop_setattr);
641*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vap, flags, cr, ct);
642*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
643*7c478bd9Sstevel@tonic-gate 	}
644*7c478bd9Sstevel@tonic-gate 	return (errc);
645*7c478bd9Sstevel@tonic-gate }
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate static int
648*7c478bd9Sstevel@tonic-gate vhead_access(vnode_t *vp, int mode, int flags, cred_t *cr)
649*7c478bd9Sstevel@tonic-gate {
650*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
651*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
652*7c478bd9Sstevel@tonic-gate 	int		(*func)();
653*7c478bd9Sstevel@tonic-gate 	void		*arg0;
654*7c478bd9Sstevel@tonic-gate 	int		errc;
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
657*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_access);
658*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
659*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
660*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, mode, flags, cr);
661*7c478bd9Sstevel@tonic-gate 	} else {
662*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
663*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
664*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
665*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
666*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_access,
667*7c478bd9Sstevel@tonic-gate 			vsop_access);
668*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, mode, flags, cr);
669*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 	return (errc);
672*7c478bd9Sstevel@tonic-gate }
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate static int
675*7c478bd9Sstevel@tonic-gate vhead_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
676*7c478bd9Sstevel@tonic-gate 	int flags, vnode_t *rdir, cred_t *cr)
677*7c478bd9Sstevel@tonic-gate {
678*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
679*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
680*7c478bd9Sstevel@tonic-gate 	int		(*func)();
681*7c478bd9Sstevel@tonic-gate 	void		*arg0;
682*7c478bd9Sstevel@tonic-gate 	int		errc;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
685*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_lookup);
686*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
687*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
688*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr);
689*7c478bd9Sstevel@tonic-gate 	} else {
690*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
691*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
692*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
693*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
694*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_lookup,
695*7c478bd9Sstevel@tonic-gate 			vsop_lookup);
696*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr);
697*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
698*7c478bd9Sstevel@tonic-gate 	}
699*7c478bd9Sstevel@tonic-gate 	return (errc);
700*7c478bd9Sstevel@tonic-gate }
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate static int
703*7c478bd9Sstevel@tonic-gate vhead_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl,
704*7c478bd9Sstevel@tonic-gate 	int mode, vnode_t **vpp, cred_t *cr, int flag)
705*7c478bd9Sstevel@tonic-gate {
706*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
707*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
708*7c478bd9Sstevel@tonic-gate 	int		(*func)();
709*7c478bd9Sstevel@tonic-gate 	void		*arg0;
710*7c478bd9Sstevel@tonic-gate 	int		errc;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
713*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_create);
714*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
715*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
716*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag);
717*7c478bd9Sstevel@tonic-gate 	} else {
718*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
719*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
720*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
721*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
722*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_create,
723*7c478bd9Sstevel@tonic-gate 			vsop_create);
724*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag);
725*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
726*7c478bd9Sstevel@tonic-gate 	}
727*7c478bd9Sstevel@tonic-gate 	return (errc);
728*7c478bd9Sstevel@tonic-gate }
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate static int
731*7c478bd9Sstevel@tonic-gate vhead_remove(vnode_t *dvp, char *nm, cred_t *cr)
732*7c478bd9Sstevel@tonic-gate {
733*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
734*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
735*7c478bd9Sstevel@tonic-gate 	int		(*func)();
736*7c478bd9Sstevel@tonic-gate 	void		*arg0;
737*7c478bd9Sstevel@tonic-gate 	int		errc;
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
740*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_remove);
741*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
742*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
743*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, cr);
744*7c478bd9Sstevel@tonic-gate 	} else {
745*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
746*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
747*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
748*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
749*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_remove,
750*7c478bd9Sstevel@tonic-gate 			vsop_remove);
751*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, cr);
752*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
753*7c478bd9Sstevel@tonic-gate 	}
754*7c478bd9Sstevel@tonic-gate 	return (errc);
755*7c478bd9Sstevel@tonic-gate }
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate static int
758*7c478bd9Sstevel@tonic-gate vhead_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr)
759*7c478bd9Sstevel@tonic-gate {
760*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
761*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
762*7c478bd9Sstevel@tonic-gate 	int		(*func)();
763*7c478bd9Sstevel@tonic-gate 	void		*arg0;
764*7c478bd9Sstevel@tonic-gate 	int		errc;
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(tdvp->v_femhead)) == NULL) {
767*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (tdvp->v_op->vop_link);
768*7c478bd9Sstevel@tonic-gate 		arg0 = tdvp;
769*7c478bd9Sstevel@tonic-gate 		fem_unlock(tdvp->v_femhead);
770*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, svp, tnm, cr);
771*7c478bd9Sstevel@tonic-gate 	} else {
772*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
773*7c478bd9Sstevel@tonic-gate 		fem_unlock(tdvp->v_femhead);
774*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = tdvp;
775*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
776*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_link, vsop_link);
777*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, svp, tnm, cr);
778*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
779*7c478bd9Sstevel@tonic-gate 	}
780*7c478bd9Sstevel@tonic-gate 	return (errc);
781*7c478bd9Sstevel@tonic-gate }
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate static int
784*7c478bd9Sstevel@tonic-gate vhead_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
785*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
786*7c478bd9Sstevel@tonic-gate {
787*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
788*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
789*7c478bd9Sstevel@tonic-gate 	int		(*func)();
790*7c478bd9Sstevel@tonic-gate 	void		*arg0;
791*7c478bd9Sstevel@tonic-gate 	int		errc;
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(sdvp->v_femhead)) == NULL) {
794*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (sdvp->v_op->vop_rename);
795*7c478bd9Sstevel@tonic-gate 		arg0 = sdvp;
796*7c478bd9Sstevel@tonic-gate 		fem_unlock(sdvp->v_femhead);
797*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, snm, tdvp, tnm, cr);
798*7c478bd9Sstevel@tonic-gate 	} else {
799*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
800*7c478bd9Sstevel@tonic-gate 		fem_unlock(sdvp->v_femhead);
801*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = sdvp;
802*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
803*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_rename,
804*7c478bd9Sstevel@tonic-gate 			vsop_rename);
805*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, snm, tdvp, tnm, cr);
806*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
807*7c478bd9Sstevel@tonic-gate 	}
808*7c478bd9Sstevel@tonic-gate 	return (errc);
809*7c478bd9Sstevel@tonic-gate }
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate static int
812*7c478bd9Sstevel@tonic-gate vhead_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp,
813*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
814*7c478bd9Sstevel@tonic-gate {
815*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
816*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
817*7c478bd9Sstevel@tonic-gate 	int		(*func)();
818*7c478bd9Sstevel@tonic-gate 	void		*arg0;
819*7c478bd9Sstevel@tonic-gate 	int		errc;
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
822*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_mkdir);
823*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
824*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
825*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, dirname, vap, vpp, cr);
826*7c478bd9Sstevel@tonic-gate 	} else {
827*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
828*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
829*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
830*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
831*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_mkdir, vsop_mkdir);
832*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, dirname, vap, vpp, cr);
833*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
834*7c478bd9Sstevel@tonic-gate 	}
835*7c478bd9Sstevel@tonic-gate 	return (errc);
836*7c478bd9Sstevel@tonic-gate }
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate static int
839*7c478bd9Sstevel@tonic-gate vhead_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr)
840*7c478bd9Sstevel@tonic-gate {
841*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
842*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
843*7c478bd9Sstevel@tonic-gate 	int		(*func)();
844*7c478bd9Sstevel@tonic-gate 	void		*arg0;
845*7c478bd9Sstevel@tonic-gate 	int		errc;
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
848*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_rmdir);
849*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
850*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
851*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, cdir, cr);
852*7c478bd9Sstevel@tonic-gate 	} else {
853*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
854*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
855*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
856*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
857*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_rmdir, vsop_rmdir);
858*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, nm, cdir, cr);
859*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
860*7c478bd9Sstevel@tonic-gate 	}
861*7c478bd9Sstevel@tonic-gate 	return (errc);
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate static int
865*7c478bd9Sstevel@tonic-gate vhead_readdir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp)
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
868*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
869*7c478bd9Sstevel@tonic-gate 	int		(*func)();
870*7c478bd9Sstevel@tonic-gate 	void		*arg0;
871*7c478bd9Sstevel@tonic-gate 	int		errc;
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
874*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_readdir);
875*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
876*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
877*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, cr, eofp);
878*7c478bd9Sstevel@tonic-gate 	} else {
879*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
880*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
881*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
882*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
883*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_readdir,
884*7c478bd9Sstevel@tonic-gate 			vsop_readdir);
885*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, cr, eofp);
886*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
887*7c478bd9Sstevel@tonic-gate 	}
888*7c478bd9Sstevel@tonic-gate 	return (errc);
889*7c478bd9Sstevel@tonic-gate }
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate static int
892*7c478bd9Sstevel@tonic-gate vhead_symlink(vnode_t *dvp, char *linkname, vattr_t *vap, char *target,
893*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
894*7c478bd9Sstevel@tonic-gate {
895*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
896*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
897*7c478bd9Sstevel@tonic-gate 	int		(*func)();
898*7c478bd9Sstevel@tonic-gate 	void		*arg0;
899*7c478bd9Sstevel@tonic-gate 	int		errc;
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
902*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (dvp->v_op->vop_symlink);
903*7c478bd9Sstevel@tonic-gate 		arg0 = dvp;
904*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
905*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, linkname, vap, target, cr);
906*7c478bd9Sstevel@tonic-gate 	} else {
907*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
908*7c478bd9Sstevel@tonic-gate 		fem_unlock(dvp->v_femhead);
909*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = dvp;
910*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
911*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_symlink,
912*7c478bd9Sstevel@tonic-gate 			vsop_symlink);
913*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, linkname, vap, target, cr);
914*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
915*7c478bd9Sstevel@tonic-gate 	}
916*7c478bd9Sstevel@tonic-gate 	return (errc);
917*7c478bd9Sstevel@tonic-gate }
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate static int
920*7c478bd9Sstevel@tonic-gate vhead_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr)
921*7c478bd9Sstevel@tonic-gate {
922*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
923*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
924*7c478bd9Sstevel@tonic-gate 	int		(*func)();
925*7c478bd9Sstevel@tonic-gate 	void		*arg0;
926*7c478bd9Sstevel@tonic-gate 	int		errc;
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
929*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_readlink);
930*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
931*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
932*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, cr);
933*7c478bd9Sstevel@tonic-gate 	} else {
934*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
935*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
936*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
937*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
938*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_readlink,
939*7c478bd9Sstevel@tonic-gate 			vsop_readlink);
940*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, uiop, cr);
941*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
942*7c478bd9Sstevel@tonic-gate 	}
943*7c478bd9Sstevel@tonic-gate 	return (errc);
944*7c478bd9Sstevel@tonic-gate }
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate static int
947*7c478bd9Sstevel@tonic-gate vhead_fsync(vnode_t *vp, int syncflag, cred_t *cr)
948*7c478bd9Sstevel@tonic-gate {
949*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
950*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
951*7c478bd9Sstevel@tonic-gate 	int		(*func)();
952*7c478bd9Sstevel@tonic-gate 	void		*arg0;
953*7c478bd9Sstevel@tonic-gate 	int		errc;
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
956*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_fsync);
957*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
958*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
959*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, syncflag, cr);
960*7c478bd9Sstevel@tonic-gate 	} else {
961*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
962*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
963*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
964*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
965*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_fsync, vsop_fsync);
966*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, syncflag, cr);
967*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
968*7c478bd9Sstevel@tonic-gate 	}
969*7c478bd9Sstevel@tonic-gate 	return (errc);
970*7c478bd9Sstevel@tonic-gate }
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate static void
973*7c478bd9Sstevel@tonic-gate vhead_inactive(vnode_t *vp, cred_t *cr)
974*7c478bd9Sstevel@tonic-gate {
975*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
976*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
977*7c478bd9Sstevel@tonic-gate 	void		(*func)();
978*7c478bd9Sstevel@tonic-gate 	void		*arg0;
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
981*7c478bd9Sstevel@tonic-gate 		func = (void (*)()) (vp->v_op->vop_inactive);
982*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
983*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
984*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, cr);
985*7c478bd9Sstevel@tonic-gate 	} else {
986*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
987*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
988*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
989*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
990*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, void, &arg0, vop_inactive,
991*7c478bd9Sstevel@tonic-gate 			vsop_inactive);
992*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, cr);
993*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
994*7c478bd9Sstevel@tonic-gate 	}
995*7c478bd9Sstevel@tonic-gate }
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate static int
998*7c478bd9Sstevel@tonic-gate vhead_fid(vnode_t *vp, fid_t *fidp)
999*7c478bd9Sstevel@tonic-gate {
1000*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1001*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1002*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1003*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1004*7c478bd9Sstevel@tonic-gate 	int		errc;
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1007*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_fid);
1008*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1009*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1010*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, fidp);
1011*7c478bd9Sstevel@tonic-gate 	} else {
1012*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1013*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1014*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1015*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1016*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_fid, vsop_fid);
1017*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, fidp);
1018*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1019*7c478bd9Sstevel@tonic-gate 	}
1020*7c478bd9Sstevel@tonic-gate 	return (errc);
1021*7c478bd9Sstevel@tonic-gate }
1022*7c478bd9Sstevel@tonic-gate 
1023*7c478bd9Sstevel@tonic-gate static int
1024*7c478bd9Sstevel@tonic-gate vhead_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1025*7c478bd9Sstevel@tonic-gate {
1026*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1027*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1028*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1029*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1030*7c478bd9Sstevel@tonic-gate 	int		errc;
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1033*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_rwlock);
1034*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1035*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1036*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, write_lock, ct);
1037*7c478bd9Sstevel@tonic-gate 	} else {
1038*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1039*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1040*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1041*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1042*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_rwlock,
1043*7c478bd9Sstevel@tonic-gate 			vsop_rwlock);
1044*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, write_lock, ct);
1045*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1046*7c478bd9Sstevel@tonic-gate 	}
1047*7c478bd9Sstevel@tonic-gate 	return (errc);
1048*7c478bd9Sstevel@tonic-gate }
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate static void
1051*7c478bd9Sstevel@tonic-gate vhead_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1052*7c478bd9Sstevel@tonic-gate {
1053*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1054*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1055*7c478bd9Sstevel@tonic-gate 	void		(*func)();
1056*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1059*7c478bd9Sstevel@tonic-gate 		func = (void (*)()) (vp->v_op->vop_rwunlock);
1060*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1061*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1062*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, write_lock, ct);
1063*7c478bd9Sstevel@tonic-gate 	} else {
1064*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1065*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1066*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1067*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1068*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, void, &arg0, vop_rwunlock,
1069*7c478bd9Sstevel@tonic-gate 			vsop_rwunlock);
1070*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, write_lock, ct);
1071*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1072*7c478bd9Sstevel@tonic-gate 	}
1073*7c478bd9Sstevel@tonic-gate }
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate static int
1076*7c478bd9Sstevel@tonic-gate vhead_seek(vnode_t *vp, offset_t ooff, offset_t *noffp)
1077*7c478bd9Sstevel@tonic-gate {
1078*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1079*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1080*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1081*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1082*7c478bd9Sstevel@tonic-gate 	int		errc;
1083*7c478bd9Sstevel@tonic-gate 
1084*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1085*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_seek);
1086*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1087*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1088*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, ooff, noffp);
1089*7c478bd9Sstevel@tonic-gate 	} else {
1090*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1091*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1092*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1093*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1094*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_seek, vsop_seek);
1095*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, ooff, noffp);
1096*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1097*7c478bd9Sstevel@tonic-gate 	}
1098*7c478bd9Sstevel@tonic-gate 	return (errc);
1099*7c478bd9Sstevel@tonic-gate }
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate static int
1102*7c478bd9Sstevel@tonic-gate vhead_cmp(vnode_t *vp1, vnode_t *vp2)
1103*7c478bd9Sstevel@tonic-gate {
1104*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1105*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1106*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1107*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1108*7c478bd9Sstevel@tonic-gate 	int		errc;
1109*7c478bd9Sstevel@tonic-gate 
1110*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp1->v_femhead)) == NULL) {
1111*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp1->v_op->vop_cmp);
1112*7c478bd9Sstevel@tonic-gate 		arg0 = vp1;
1113*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp1->v_femhead);
1114*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vp2);
1115*7c478bd9Sstevel@tonic-gate 	} else {
1116*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1117*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp1->v_femhead);
1118*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp1;
1119*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1120*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_cmp, vsop_cmp);
1121*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vp2);
1122*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1123*7c478bd9Sstevel@tonic-gate 	}
1124*7c478bd9Sstevel@tonic-gate 	return (errc);
1125*7c478bd9Sstevel@tonic-gate }
1126*7c478bd9Sstevel@tonic-gate 
1127*7c478bd9Sstevel@tonic-gate static int
1128*7c478bd9Sstevel@tonic-gate vhead_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1129*7c478bd9Sstevel@tonic-gate 	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr)
1130*7c478bd9Sstevel@tonic-gate {
1131*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1132*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1133*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1134*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1135*7c478bd9Sstevel@tonic-gate 	int		errc;
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1138*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_frlock);
1139*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1140*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1141*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr);
1142*7c478bd9Sstevel@tonic-gate 	} else {
1143*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1144*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1145*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1146*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1147*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_frlock,
1148*7c478bd9Sstevel@tonic-gate 			vsop_frlock);
1149*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr);
1150*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1151*7c478bd9Sstevel@tonic-gate 	}
1152*7c478bd9Sstevel@tonic-gate 	return (errc);
1153*7c478bd9Sstevel@tonic-gate }
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate static int
1156*7c478bd9Sstevel@tonic-gate vhead_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1157*7c478bd9Sstevel@tonic-gate 	offset_t offset, cred_t *cr, caller_context_t *ct)
1158*7c478bd9Sstevel@tonic-gate {
1159*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1160*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1161*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1162*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1163*7c478bd9Sstevel@tonic-gate 	int		errc;
1164*7c478bd9Sstevel@tonic-gate 
1165*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1166*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_space);
1167*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1168*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1169*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1170*7c478bd9Sstevel@tonic-gate 	} else {
1171*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1172*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1173*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1174*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1175*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_space, vsop_space);
1176*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1177*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1178*7c478bd9Sstevel@tonic-gate 	}
1179*7c478bd9Sstevel@tonic-gate 	return (errc);
1180*7c478bd9Sstevel@tonic-gate }
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate static int
1183*7c478bd9Sstevel@tonic-gate vhead_realvp(vnode_t *vp, vnode_t **vpp)
1184*7c478bd9Sstevel@tonic-gate {
1185*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1186*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1187*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1188*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1189*7c478bd9Sstevel@tonic-gate 	int		errc;
1190*7c478bd9Sstevel@tonic-gate 
1191*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1192*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_realvp);
1193*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1194*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1195*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vpp);
1196*7c478bd9Sstevel@tonic-gate 	} else {
1197*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1198*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1199*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1200*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1201*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_realvp,
1202*7c478bd9Sstevel@tonic-gate 			vsop_realvp);
1203*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vpp);
1204*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1205*7c478bd9Sstevel@tonic-gate 	}
1206*7c478bd9Sstevel@tonic-gate 	return (errc);
1207*7c478bd9Sstevel@tonic-gate }
1208*7c478bd9Sstevel@tonic-gate 
1209*7c478bd9Sstevel@tonic-gate static int
1210*7c478bd9Sstevel@tonic-gate vhead_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
1211*7c478bd9Sstevel@tonic-gate 	struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
1212*7c478bd9Sstevel@tonic-gate 	enum seg_rw rw, cred_t *cr)
1213*7c478bd9Sstevel@tonic-gate {
1214*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1215*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1216*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1217*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1218*7c478bd9Sstevel@tonic-gate 	int		errc;
1219*7c478bd9Sstevel@tonic-gate 
1220*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1221*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_getpage);
1222*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1223*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1224*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1225*7c478bd9Sstevel@tonic-gate 			addr, rw, cr);
1226*7c478bd9Sstevel@tonic-gate 	} else {
1227*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1228*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1229*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1230*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1231*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_getpage,
1232*7c478bd9Sstevel@tonic-gate 			vsop_getpage);
1233*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1234*7c478bd9Sstevel@tonic-gate 			addr, rw, cr);
1235*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1236*7c478bd9Sstevel@tonic-gate 	}
1237*7c478bd9Sstevel@tonic-gate 	return (errc);
1238*7c478bd9Sstevel@tonic-gate }
1239*7c478bd9Sstevel@tonic-gate 
1240*7c478bd9Sstevel@tonic-gate static int
1241*7c478bd9Sstevel@tonic-gate vhead_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr)
1242*7c478bd9Sstevel@tonic-gate {
1243*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1244*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1245*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1246*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1247*7c478bd9Sstevel@tonic-gate 	int		errc;
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1250*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_putpage);
1251*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1252*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1253*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, len, flags, cr);
1254*7c478bd9Sstevel@tonic-gate 	} else {
1255*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1256*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1257*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1258*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1259*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_putpage,
1260*7c478bd9Sstevel@tonic-gate 			vsop_putpage);
1261*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, len, flags, cr);
1262*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1263*7c478bd9Sstevel@tonic-gate 	}
1264*7c478bd9Sstevel@tonic-gate 	return (errc);
1265*7c478bd9Sstevel@tonic-gate }
1266*7c478bd9Sstevel@tonic-gate 
1267*7c478bd9Sstevel@tonic-gate static int
1268*7c478bd9Sstevel@tonic-gate vhead_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
1269*7c478bd9Sstevel@tonic-gate 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1270*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
1271*7c478bd9Sstevel@tonic-gate {
1272*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1273*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1274*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1275*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1276*7c478bd9Sstevel@tonic-gate 	int		errc;
1277*7c478bd9Sstevel@tonic-gate 
1278*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1279*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_map);
1280*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1281*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1282*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1283*7c478bd9Sstevel@tonic-gate 			flags, cr);
1284*7c478bd9Sstevel@tonic-gate 	} else {
1285*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1286*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1287*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1288*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1289*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_map, vsop_map);
1290*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1291*7c478bd9Sstevel@tonic-gate 			flags, cr);
1292*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1293*7c478bd9Sstevel@tonic-gate 	}
1294*7c478bd9Sstevel@tonic-gate 	return (errc);
1295*7c478bd9Sstevel@tonic-gate }
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate static int
1298*7c478bd9Sstevel@tonic-gate vhead_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1299*7c478bd9Sstevel@tonic-gate 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1300*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
1301*7c478bd9Sstevel@tonic-gate {
1302*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1303*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1304*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1305*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1306*7c478bd9Sstevel@tonic-gate 	int		errc;
1307*7c478bd9Sstevel@tonic-gate 
1308*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1309*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_addmap);
1310*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1311*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1312*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1313*7c478bd9Sstevel@tonic-gate 			flags, cr);
1314*7c478bd9Sstevel@tonic-gate 	} else {
1315*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1316*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1317*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1318*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1319*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_addmap,
1320*7c478bd9Sstevel@tonic-gate 			vsop_addmap);
1321*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1322*7c478bd9Sstevel@tonic-gate 			flags, cr);
1323*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1324*7c478bd9Sstevel@tonic-gate 	}
1325*7c478bd9Sstevel@tonic-gate 	return (errc);
1326*7c478bd9Sstevel@tonic-gate }
1327*7c478bd9Sstevel@tonic-gate 
1328*7c478bd9Sstevel@tonic-gate static int
1329*7c478bd9Sstevel@tonic-gate vhead_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1330*7c478bd9Sstevel@tonic-gate 	size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr)
1331*7c478bd9Sstevel@tonic-gate {
1332*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1333*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1334*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1335*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1336*7c478bd9Sstevel@tonic-gate 	int		errc;
1337*7c478bd9Sstevel@tonic-gate 
1338*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1339*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_delmap);
1340*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1341*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1342*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1343*7c478bd9Sstevel@tonic-gate 			flags, cr);
1344*7c478bd9Sstevel@tonic-gate 	} else {
1345*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1346*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1347*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1348*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1349*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_delmap,
1350*7c478bd9Sstevel@tonic-gate 			vsop_delmap);
1351*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1352*7c478bd9Sstevel@tonic-gate 			flags, cr);
1353*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1354*7c478bd9Sstevel@tonic-gate 	}
1355*7c478bd9Sstevel@tonic-gate 	return (errc);
1356*7c478bd9Sstevel@tonic-gate }
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate static int
1359*7c478bd9Sstevel@tonic-gate vhead_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
1360*7c478bd9Sstevel@tonic-gate 	struct pollhead **phpp)
1361*7c478bd9Sstevel@tonic-gate {
1362*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1363*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1364*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1365*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1366*7c478bd9Sstevel@tonic-gate 	int		errc;
1367*7c478bd9Sstevel@tonic-gate 
1368*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1369*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_poll);
1370*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1371*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1372*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, events, anyyet, reventsp, phpp);
1373*7c478bd9Sstevel@tonic-gate 	} else {
1374*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1375*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1376*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1377*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1378*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_poll, vsop_poll);
1379*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, events, anyyet, reventsp, phpp);
1380*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1381*7c478bd9Sstevel@tonic-gate 	}
1382*7c478bd9Sstevel@tonic-gate 	return (errc);
1383*7c478bd9Sstevel@tonic-gate }
1384*7c478bd9Sstevel@tonic-gate 
1385*7c478bd9Sstevel@tonic-gate static int
1386*7c478bd9Sstevel@tonic-gate vhead_dump(vnode_t *vp, caddr_t addr, int lbdn, int dblks)
1387*7c478bd9Sstevel@tonic-gate {
1388*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1389*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1390*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1391*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1392*7c478bd9Sstevel@tonic-gate 	int		errc;
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1395*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_dump);
1396*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1397*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1398*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, addr, lbdn, dblks);
1399*7c478bd9Sstevel@tonic-gate 	} else {
1400*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1401*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1402*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1403*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1404*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_dump, vsop_dump);
1405*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, addr, lbdn, dblks);
1406*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1407*7c478bd9Sstevel@tonic-gate 	}
1408*7c478bd9Sstevel@tonic-gate 	return (errc);
1409*7c478bd9Sstevel@tonic-gate }
1410*7c478bd9Sstevel@tonic-gate 
1411*7c478bd9Sstevel@tonic-gate static int
1412*7c478bd9Sstevel@tonic-gate vhead_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr)
1413*7c478bd9Sstevel@tonic-gate {
1414*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1415*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1416*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1417*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1418*7c478bd9Sstevel@tonic-gate 	int		errc;
1419*7c478bd9Sstevel@tonic-gate 
1420*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1421*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_pathconf);
1422*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1423*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1424*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, valp, cr);
1425*7c478bd9Sstevel@tonic-gate 	} else {
1426*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1427*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1428*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1429*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1430*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_pathconf,
1431*7c478bd9Sstevel@tonic-gate 			vsop_pathconf);
1432*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, valp, cr);
1433*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1434*7c478bd9Sstevel@tonic-gate 	}
1435*7c478bd9Sstevel@tonic-gate 	return (errc);
1436*7c478bd9Sstevel@tonic-gate }
1437*7c478bd9Sstevel@tonic-gate 
1438*7c478bd9Sstevel@tonic-gate static int
1439*7c478bd9Sstevel@tonic-gate vhead_pageio(vnode_t *vp, struct page *pp, u_offset_t io_off,
1440*7c478bd9Sstevel@tonic-gate 	size_t io_len, int flags, cred_t *cr)
1441*7c478bd9Sstevel@tonic-gate {
1442*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1443*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1444*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1445*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1446*7c478bd9Sstevel@tonic-gate 	int		errc;
1447*7c478bd9Sstevel@tonic-gate 
1448*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1449*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_pageio);
1450*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1451*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1452*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr);
1453*7c478bd9Sstevel@tonic-gate 	} else {
1454*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1455*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1456*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1457*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1458*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_pageio,
1459*7c478bd9Sstevel@tonic-gate 			vsop_pageio);
1460*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr);
1461*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1462*7c478bd9Sstevel@tonic-gate 	}
1463*7c478bd9Sstevel@tonic-gate 	return (errc);
1464*7c478bd9Sstevel@tonic-gate }
1465*7c478bd9Sstevel@tonic-gate 
1466*7c478bd9Sstevel@tonic-gate static int
1467*7c478bd9Sstevel@tonic-gate vhead_dumpctl(vnode_t *vp, int action, int *blkp)
1468*7c478bd9Sstevel@tonic-gate {
1469*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1470*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1471*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1472*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1473*7c478bd9Sstevel@tonic-gate 	int		errc;
1474*7c478bd9Sstevel@tonic-gate 
1475*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1476*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_dumpctl);
1477*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1478*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1479*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, action, blkp);
1480*7c478bd9Sstevel@tonic-gate 	} else {
1481*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1482*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1483*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1484*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1485*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_dumpctl,
1486*7c478bd9Sstevel@tonic-gate 			vsop_dumpctl);
1487*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, action, blkp);
1488*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1489*7c478bd9Sstevel@tonic-gate 	}
1490*7c478bd9Sstevel@tonic-gate 	return (errc);
1491*7c478bd9Sstevel@tonic-gate }
1492*7c478bd9Sstevel@tonic-gate 
1493*7c478bd9Sstevel@tonic-gate static void
1494*7c478bd9Sstevel@tonic-gate vhead_dispose(vnode_t *vp, struct page *pp, int flag, int dn, cred_t *cr)
1495*7c478bd9Sstevel@tonic-gate {
1496*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1497*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1498*7c478bd9Sstevel@tonic-gate 	void		(*func)();
1499*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1500*7c478bd9Sstevel@tonic-gate 
1501*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1502*7c478bd9Sstevel@tonic-gate 		func = (void (*)()) (vp->v_op->vop_dispose);
1503*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1504*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1505*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, pp, flag, dn, cr);
1506*7c478bd9Sstevel@tonic-gate 	} else {
1507*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1508*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1509*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1510*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1511*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, void, &arg0, vop_dispose,
1512*7c478bd9Sstevel@tonic-gate 			vsop_dispose);
1513*7c478bd9Sstevel@tonic-gate 		(*func)(arg0, pp, flag, dn, cr);
1514*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1515*7c478bd9Sstevel@tonic-gate 	}
1516*7c478bd9Sstevel@tonic-gate }
1517*7c478bd9Sstevel@tonic-gate 
1518*7c478bd9Sstevel@tonic-gate static int
1519*7c478bd9Sstevel@tonic-gate vhead_setsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr)
1520*7c478bd9Sstevel@tonic-gate {
1521*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1522*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1523*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1524*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1525*7c478bd9Sstevel@tonic-gate 	int		errc;
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1528*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_setsecattr);
1529*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1530*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1531*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vsap, flag, cr);
1532*7c478bd9Sstevel@tonic-gate 	} else {
1533*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1534*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1535*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1536*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1537*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_setsecattr,
1538*7c478bd9Sstevel@tonic-gate 			vsop_setsecattr);
1539*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vsap, flag, cr);
1540*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1541*7c478bd9Sstevel@tonic-gate 	}
1542*7c478bd9Sstevel@tonic-gate 	return (errc);
1543*7c478bd9Sstevel@tonic-gate }
1544*7c478bd9Sstevel@tonic-gate 
1545*7c478bd9Sstevel@tonic-gate static int
1546*7c478bd9Sstevel@tonic-gate vhead_getsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr)
1547*7c478bd9Sstevel@tonic-gate {
1548*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1549*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1550*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1551*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1552*7c478bd9Sstevel@tonic-gate 	int		errc;
1553*7c478bd9Sstevel@tonic-gate 
1554*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1555*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_getsecattr);
1556*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1557*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1558*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vsap, flag, cr);
1559*7c478bd9Sstevel@tonic-gate 	} else {
1560*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1561*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1562*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1563*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1564*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_getsecattr,
1565*7c478bd9Sstevel@tonic-gate 			vsop_getsecattr);
1566*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vsap, flag, cr);
1567*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1568*7c478bd9Sstevel@tonic-gate 	}
1569*7c478bd9Sstevel@tonic-gate 	return (errc);
1570*7c478bd9Sstevel@tonic-gate }
1571*7c478bd9Sstevel@tonic-gate 
1572*7c478bd9Sstevel@tonic-gate static int
1573*7c478bd9Sstevel@tonic-gate vhead_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag,
1574*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
1575*7c478bd9Sstevel@tonic-gate {
1576*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1577*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1578*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1579*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1580*7c478bd9Sstevel@tonic-gate 	int		errc;
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1583*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_shrlock);
1584*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1585*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1586*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, shr, flag, cr);
1587*7c478bd9Sstevel@tonic-gate 	} else {
1588*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1589*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1590*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1591*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1592*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_shrlock,
1593*7c478bd9Sstevel@tonic-gate 			vsop_shrlock);
1594*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, cmd, shr, flag, cr);
1595*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1596*7c478bd9Sstevel@tonic-gate 	}
1597*7c478bd9Sstevel@tonic-gate 	return (errc);
1598*7c478bd9Sstevel@tonic-gate }
1599*7c478bd9Sstevel@tonic-gate 
1600*7c478bd9Sstevel@tonic-gate static int
1601*7c478bd9Sstevel@tonic-gate vhead_vnevent(vnode_t *vp, vnevent_t vnevent)
1602*7c478bd9Sstevel@tonic-gate {
1603*7c478bd9Sstevel@tonic-gate 	femarg_t	farg;
1604*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1605*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1606*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1607*7c478bd9Sstevel@tonic-gate 	int		errc;
1608*7c478bd9Sstevel@tonic-gate 
1609*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1610*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) (vp->v_op->vop_vnevent);
1611*7c478bd9Sstevel@tonic-gate 		arg0 = vp;
1612*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1613*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vnevent);
1614*7c478bd9Sstevel@tonic-gate 	} else {
1615*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1616*7c478bd9Sstevel@tonic-gate 		fem_unlock(vp->v_femhead);
1617*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vp = vp;
1618*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1619*7c478bd9Sstevel@tonic-gate 		vsop_find(&farg, &func, int, &arg0, vop_vnevent,
1620*7c478bd9Sstevel@tonic-gate 			vsop_vnevent);
1621*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vnevent);
1622*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1623*7c478bd9Sstevel@tonic-gate 	}
1624*7c478bd9Sstevel@tonic-gate 	return (errc);
1625*7c478bd9Sstevel@tonic-gate }
1626*7c478bd9Sstevel@tonic-gate 
1627*7c478bd9Sstevel@tonic-gate static int
1628*7c478bd9Sstevel@tonic-gate fshead_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
1629*7c478bd9Sstevel@tonic-gate {
1630*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1631*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1632*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1633*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1634*7c478bd9Sstevel@tonic-gate 	int		errc;
1635*7c478bd9Sstevel@tonic-gate 
1636*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1637*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_mount;
1638*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1639*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, mvp, uap, cr);
1640*7c478bd9Sstevel@tonic-gate 	} else {
1641*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1642*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1643*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1644*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1645*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_mount,
1646*7c478bd9Sstevel@tonic-gate 			vfsop_mount);
1647*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, mvp, uap, cr);
1648*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1649*7c478bd9Sstevel@tonic-gate 	}
1650*7c478bd9Sstevel@tonic-gate 	return (errc);
1651*7c478bd9Sstevel@tonic-gate }
1652*7c478bd9Sstevel@tonic-gate 
1653*7c478bd9Sstevel@tonic-gate static int
1654*7c478bd9Sstevel@tonic-gate fshead_unmount(vfs_t *vfsp, int flag, cred_t *cr)
1655*7c478bd9Sstevel@tonic-gate {
1656*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1657*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1658*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1659*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1660*7c478bd9Sstevel@tonic-gate 	int		errc;
1661*7c478bd9Sstevel@tonic-gate 
1662*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1663*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_unmount;
1664*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1665*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, flag, cr);
1666*7c478bd9Sstevel@tonic-gate 	} else {
1667*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1668*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1669*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1670*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1671*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_unmount,
1672*7c478bd9Sstevel@tonic-gate 			vfsop_unmount);
1673*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, flag, cr);
1674*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1675*7c478bd9Sstevel@tonic-gate 	}
1676*7c478bd9Sstevel@tonic-gate 	return (errc);
1677*7c478bd9Sstevel@tonic-gate }
1678*7c478bd9Sstevel@tonic-gate 
1679*7c478bd9Sstevel@tonic-gate static int
1680*7c478bd9Sstevel@tonic-gate fshead_root(vfs_t *vfsp, vnode_t **vpp)
1681*7c478bd9Sstevel@tonic-gate {
1682*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1683*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1684*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1685*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1686*7c478bd9Sstevel@tonic-gate 	int		errc;
1687*7c478bd9Sstevel@tonic-gate 
1688*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1689*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_root;
1690*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1691*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, vpp);
1692*7c478bd9Sstevel@tonic-gate 	} else {
1693*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1694*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1695*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1696*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1697*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_root, vfsop_root);
1698*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vpp);
1699*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1700*7c478bd9Sstevel@tonic-gate 	}
1701*7c478bd9Sstevel@tonic-gate 	return (errc);
1702*7c478bd9Sstevel@tonic-gate }
1703*7c478bd9Sstevel@tonic-gate 
1704*7c478bd9Sstevel@tonic-gate static int
1705*7c478bd9Sstevel@tonic-gate fshead_statvfs(vfs_t *vfsp, statvfs64_t *sp)
1706*7c478bd9Sstevel@tonic-gate {
1707*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1708*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1709*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1710*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1711*7c478bd9Sstevel@tonic-gate 	int		errc;
1712*7c478bd9Sstevel@tonic-gate 
1713*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1714*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_statvfs;
1715*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1716*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, sp);
1717*7c478bd9Sstevel@tonic-gate 	} else {
1718*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1719*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1720*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1721*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1722*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_statvfs,
1723*7c478bd9Sstevel@tonic-gate 			vfsop_statvfs);
1724*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, sp);
1725*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1726*7c478bd9Sstevel@tonic-gate 	}
1727*7c478bd9Sstevel@tonic-gate 	return (errc);
1728*7c478bd9Sstevel@tonic-gate }
1729*7c478bd9Sstevel@tonic-gate 
1730*7c478bd9Sstevel@tonic-gate static int
1731*7c478bd9Sstevel@tonic-gate fshead_sync(vfs_t *vfsp, short flag, cred_t *cr)
1732*7c478bd9Sstevel@tonic-gate {
1733*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1734*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1735*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1736*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1737*7c478bd9Sstevel@tonic-gate 	int		errc;
1738*7c478bd9Sstevel@tonic-gate 
1739*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1740*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_sync;
1741*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1742*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, flag, cr);
1743*7c478bd9Sstevel@tonic-gate 	} else {
1744*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1745*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1746*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1747*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1748*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_sync, vfsop_sync);
1749*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, flag, cr);
1750*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1751*7c478bd9Sstevel@tonic-gate 	}
1752*7c478bd9Sstevel@tonic-gate 	return (errc);
1753*7c478bd9Sstevel@tonic-gate }
1754*7c478bd9Sstevel@tonic-gate 
1755*7c478bd9Sstevel@tonic-gate static int
1756*7c478bd9Sstevel@tonic-gate fshead_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
1757*7c478bd9Sstevel@tonic-gate {
1758*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1759*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1760*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1761*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1762*7c478bd9Sstevel@tonic-gate 	int		errc;
1763*7c478bd9Sstevel@tonic-gate 
1764*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1765*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_vget;
1766*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1767*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, vpp, fidp);
1768*7c478bd9Sstevel@tonic-gate 	} else {
1769*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1770*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1771*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1772*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1773*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_vget, vfsop_vget);
1774*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vpp, fidp);
1775*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1776*7c478bd9Sstevel@tonic-gate 	}
1777*7c478bd9Sstevel@tonic-gate 	return (errc);
1778*7c478bd9Sstevel@tonic-gate }
1779*7c478bd9Sstevel@tonic-gate 
1780*7c478bd9Sstevel@tonic-gate static int
1781*7c478bd9Sstevel@tonic-gate fshead_mountroot(vfs_t *vfsp, enum whymountroot reason)
1782*7c478bd9Sstevel@tonic-gate {
1783*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1784*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1785*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1786*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1787*7c478bd9Sstevel@tonic-gate 	int		errc;
1788*7c478bd9Sstevel@tonic-gate 
1789*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1790*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_mountroot;
1791*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1792*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, reason);
1793*7c478bd9Sstevel@tonic-gate 	} else {
1794*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1795*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1796*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1797*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1798*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_mountroot,
1799*7c478bd9Sstevel@tonic-gate 			vfsop_mountroot);
1800*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, reason);
1801*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1802*7c478bd9Sstevel@tonic-gate 	}
1803*7c478bd9Sstevel@tonic-gate 	return (errc);
1804*7c478bd9Sstevel@tonic-gate }
1805*7c478bd9Sstevel@tonic-gate 
1806*7c478bd9Sstevel@tonic-gate static void
1807*7c478bd9Sstevel@tonic-gate fshead_freevfs(vfs_t *vfsp)
1808*7c478bd9Sstevel@tonic-gate {
1809*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1810*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1811*7c478bd9Sstevel@tonic-gate 	void		(*func)();
1812*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1813*7c478bd9Sstevel@tonic-gate 
1814*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1815*7c478bd9Sstevel@tonic-gate 		func = (void (*)()) vfsp->vfs_op->vfs_freevfs;
1816*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1817*7c478bd9Sstevel@tonic-gate 		(*func)(vfsp);
1818*7c478bd9Sstevel@tonic-gate 	} else {
1819*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1820*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1821*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1822*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1823*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, void, &arg0, vfs_freevfs,
1824*7c478bd9Sstevel@tonic-gate 			vfsop_freevfs);
1825*7c478bd9Sstevel@tonic-gate 		(*func)(arg0);
1826*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1827*7c478bd9Sstevel@tonic-gate 	}
1828*7c478bd9Sstevel@tonic-gate }
1829*7c478bd9Sstevel@tonic-gate 
1830*7c478bd9Sstevel@tonic-gate static int
1831*7c478bd9Sstevel@tonic-gate fshead_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
1832*7c478bd9Sstevel@tonic-gate {
1833*7c478bd9Sstevel@tonic-gate 	fsemarg_t	farg;
1834*7c478bd9Sstevel@tonic-gate 	struct fem_list	*femsp;
1835*7c478bd9Sstevel@tonic-gate 	int		(*func)();
1836*7c478bd9Sstevel@tonic-gate 	void		*arg0;
1837*7c478bd9Sstevel@tonic-gate 	int		errc;
1838*7c478bd9Sstevel@tonic-gate 
1839*7c478bd9Sstevel@tonic-gate 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1840*7c478bd9Sstevel@tonic-gate 		func = (int (*)()) vfsp->vfs_op->vfs_vnstate;
1841*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1842*7c478bd9Sstevel@tonic-gate 		errc = (*func)(vfsp, vp, nstate);
1843*7c478bd9Sstevel@tonic-gate 	} else {
1844*7c478bd9Sstevel@tonic-gate 		fem_addref(femsp);
1845*7c478bd9Sstevel@tonic-gate 		fem_unlock(vfsp->vfs_femhead);
1846*7c478bd9Sstevel@tonic-gate 		farg.fa_vnode.vfsp = vfsp;
1847*7c478bd9Sstevel@tonic-gate 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1848*7c478bd9Sstevel@tonic-gate 		vfsop_find(&farg, &func, int, &arg0, vfs_vnstate,
1849*7c478bd9Sstevel@tonic-gate 			vfsop_vnstate);
1850*7c478bd9Sstevel@tonic-gate 		errc = (*func)(arg0, vp, nstate);
1851*7c478bd9Sstevel@tonic-gate 		fem_release(femsp);
1852*7c478bd9Sstevel@tonic-gate 	}
1853*7c478bd9Sstevel@tonic-gate 	return (errc);
1854*7c478bd9Sstevel@tonic-gate }
1855*7c478bd9Sstevel@tonic-gate 
1856*7c478bd9Sstevel@tonic-gate 
1857*7c478bd9Sstevel@tonic-gate /*
1858*7c478bd9Sstevel@tonic-gate  * specification table for the vhead vnode operations.
1859*7c478bd9Sstevel@tonic-gate  * It is an error for any operations to be missing.
1860*7c478bd9Sstevel@tonic-gate  */
1861*7c478bd9Sstevel@tonic-gate 
1862*7c478bd9Sstevel@tonic-gate static struct fs_operation_def fhead_vn_spec[] = {
1863*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_OPEN, (femop_t *)vhead_open },
1864*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_CLOSE, (femop_t *)vhead_close },
1865*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_READ, (femop_t *)vhead_read },
1866*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_WRITE, (femop_t *)vhead_write },
1867*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_IOCTL, (femop_t *)vhead_ioctl },
1868*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SETFL, (femop_t *)vhead_setfl },
1869*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_GETATTR, (femop_t *)vhead_getattr },
1870*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SETATTR, (femop_t *)vhead_setattr },
1871*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_ACCESS, (femop_t *)vhead_access },
1872*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_LOOKUP, (femop_t *)vhead_lookup },
1873*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_CREATE, (femop_t *)vhead_create },
1874*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_REMOVE, (femop_t *)vhead_remove },
1875*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_LINK, (femop_t *)vhead_link },
1876*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_RENAME, (femop_t *)vhead_rename },
1877*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_MKDIR, (femop_t *)vhead_mkdir },
1878*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_RMDIR, (femop_t *)vhead_rmdir },
1879*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_READDIR, (femop_t *)vhead_readdir },
1880*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SYMLINK, (femop_t *)vhead_symlink },
1881*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_READLINK, (femop_t *)vhead_readlink },
1882*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_FSYNC, (femop_t *)vhead_fsync },
1883*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_INACTIVE, (femop_t *)vhead_inactive },
1884*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_FID, (femop_t *)vhead_fid },
1885*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_RWLOCK, (femop_t *)vhead_rwlock },
1886*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_RWUNLOCK, (femop_t *)vhead_rwunlock },
1887*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SEEK, (femop_t *)vhead_seek },
1888*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_CMP, (femop_t *)vhead_cmp },
1889*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_FRLOCK, (femop_t *)vhead_frlock },
1890*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SPACE, (femop_t *)vhead_space },
1891*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_REALVP, (femop_t *)vhead_realvp },
1892*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_GETPAGE, (femop_t *)vhead_getpage },
1893*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_PUTPAGE, (femop_t *)vhead_putpage },
1894*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_MAP, (femop_t *)vhead_map },
1895*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_ADDMAP, (femop_t *)vhead_addmap },
1896*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_DELMAP, (femop_t *)vhead_delmap },
1897*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_POLL, (femop_t *)vhead_poll },
1898*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_DUMP, (femop_t *)vhead_dump },
1899*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_PATHCONF, (femop_t *)vhead_pathconf },
1900*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_PAGEIO, (femop_t *)vhead_pageio },
1901*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_DUMPCTL, (femop_t *)vhead_dumpctl },
1902*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_DISPOSE, (femop_t *)vhead_dispose },
1903*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SETSECATTR, (femop_t *)vhead_setsecattr },
1904*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_GETSECATTR, (femop_t *)vhead_getsecattr },
1905*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_SHRLOCK, (femop_t *)vhead_shrlock },
1906*7c478bd9Sstevel@tonic-gate 	{ VOPNAME_VNEVENT, (femop_t *)vhead_vnevent },
1907*7c478bd9Sstevel@tonic-gate 	{	NULL,	NULL	}
1908*7c478bd9Sstevel@tonic-gate };
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate /*
1911*7c478bd9Sstevel@tonic-gate  * specification table for the vfshead vnode operations.
1912*7c478bd9Sstevel@tonic-gate  * It is an error for any operations to be missing.
1913*7c478bd9Sstevel@tonic-gate  */
1914*7c478bd9Sstevel@tonic-gate 
1915*7c478bd9Sstevel@tonic-gate static struct fs_operation_def fshead_vfs_spec[]  = {
1916*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_MOUNT, (femop_t *)fshead_mount },
1917*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_UNMOUNT, (femop_t *)fshead_unmount },
1918*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_ROOT, (femop_t *)fshead_root },
1919*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_STATVFS, (femop_t *)fshead_statvfs },
1920*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_SYNC, (femop_t *)fshead_sync },
1921*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_VGET, (femop_t *)fshead_vget },
1922*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_MOUNTROOT, (femop_t *)fshead_mountroot },
1923*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_FREEVFS, (femop_t *)fshead_freevfs },
1924*7c478bd9Sstevel@tonic-gate 	{ VFSNAME_VNSTATE, (femop_t *)fshead_vnstate },
1925*7c478bd9Sstevel@tonic-gate 	{	NULL,	NULL	}
1926*7c478bd9Sstevel@tonic-gate };
1927*7c478bd9Sstevel@tonic-gate 
1928*7c478bd9Sstevel@tonic-gate /*
1929*7c478bd9Sstevel@tonic-gate  * This set of routines transfer control to the next stacked monitor.
1930*7c478bd9Sstevel@tonic-gate  *
1931*7c478bd9Sstevel@tonic-gate  * Each routine is identical except for naming, types and arguments.
1932*7c478bd9Sstevel@tonic-gate  *
1933*7c478bd9Sstevel@tonic-gate  * The basic steps are:
1934*7c478bd9Sstevel@tonic-gate  * 1.  Decrease the stack pointer by one.
1935*7c478bd9Sstevel@tonic-gate  * 2.  If the current item is a base operation (vnode, vfs), goto 5.
1936*7c478bd9Sstevel@tonic-gate  * 3.  If the current item does not have a corresponding operation, goto 1
1937*7c478bd9Sstevel@tonic-gate  * 4.  Return by invoking the current item with the argument handle.
1938*7c478bd9Sstevel@tonic-gate  * 5.  Return by invoking the base operation with the base object.
1939*7c478bd9Sstevel@tonic-gate  *
1940*7c478bd9Sstevel@tonic-gate  * for each classification, there needs to be at least one "next" operation
1941*7c478bd9Sstevel@tonic-gate  * for each "head"operation.
1942*7c478bd9Sstevel@tonic-gate  *
1943*7c478bd9Sstevel@tonic-gate  */
1944*7c478bd9Sstevel@tonic-gate 
1945*7c478bd9Sstevel@tonic-gate int
1946*7c478bd9Sstevel@tonic-gate vnext_open(femarg_t *vf, int mode, cred_t *cr)
1947*7c478bd9Sstevel@tonic-gate {
1948*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
1949*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
1950*7c478bd9Sstevel@tonic-gate 
1951*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
1952*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
1953*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_open, vsop_open);
1954*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
1955*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
1956*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, mode, cr));
1957*7c478bd9Sstevel@tonic-gate }
1958*7c478bd9Sstevel@tonic-gate 
1959*7c478bd9Sstevel@tonic-gate int
1960*7c478bd9Sstevel@tonic-gate vnext_close(femarg_t *vf, int flag, int count, offset_t offset, cred_t *cr)
1961*7c478bd9Sstevel@tonic-gate {
1962*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
1963*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
1964*7c478bd9Sstevel@tonic-gate 
1965*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
1966*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
1967*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_close, vsop_close);
1968*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
1969*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
1970*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, flag, count, offset, cr));
1971*7c478bd9Sstevel@tonic-gate }
1972*7c478bd9Sstevel@tonic-gate 
1973*7c478bd9Sstevel@tonic-gate int
1974*7c478bd9Sstevel@tonic-gate vnext_read(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
1975*7c478bd9Sstevel@tonic-gate 	struct caller_context *ct)
1976*7c478bd9Sstevel@tonic-gate {
1977*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
1978*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
1979*7c478bd9Sstevel@tonic-gate 
1980*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
1981*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
1982*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_read, vsop_read);
1983*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
1984*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
1985*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, uiop, ioflag, cr, ct));
1986*7c478bd9Sstevel@tonic-gate }
1987*7c478bd9Sstevel@tonic-gate 
1988*7c478bd9Sstevel@tonic-gate int
1989*7c478bd9Sstevel@tonic-gate vnext_write(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
1990*7c478bd9Sstevel@tonic-gate 	struct caller_context *ct)
1991*7c478bd9Sstevel@tonic-gate {
1992*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
1993*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
1994*7c478bd9Sstevel@tonic-gate 
1995*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
1996*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
1997*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_write, vsop_write);
1998*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
1999*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2000*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, uiop, ioflag, cr, ct));
2001*7c478bd9Sstevel@tonic-gate }
2002*7c478bd9Sstevel@tonic-gate 
2003*7c478bd9Sstevel@tonic-gate int
2004*7c478bd9Sstevel@tonic-gate vnext_ioctl(femarg_t *vf, int cmd, intptr_t arg, int flag, cred_t *cr,
2005*7c478bd9Sstevel@tonic-gate 	int *rvalp)
2006*7c478bd9Sstevel@tonic-gate {
2007*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2008*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2009*7c478bd9Sstevel@tonic-gate 
2010*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2011*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2012*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_ioctl, vsop_ioctl);
2013*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2014*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2015*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, cmd, arg, flag, cr, rvalp));
2016*7c478bd9Sstevel@tonic-gate }
2017*7c478bd9Sstevel@tonic-gate 
2018*7c478bd9Sstevel@tonic-gate int
2019*7c478bd9Sstevel@tonic-gate vnext_setfl(femarg_t *vf, int oflags, int nflags, cred_t *cr)
2020*7c478bd9Sstevel@tonic-gate {
2021*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2022*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2023*7c478bd9Sstevel@tonic-gate 
2024*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2025*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2026*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_setfl, vsop_setfl);
2027*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2028*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2029*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, oflags, nflags, cr));
2030*7c478bd9Sstevel@tonic-gate }
2031*7c478bd9Sstevel@tonic-gate 
2032*7c478bd9Sstevel@tonic-gate int
2033*7c478bd9Sstevel@tonic-gate vnext_getattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr)
2034*7c478bd9Sstevel@tonic-gate {
2035*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2036*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2037*7c478bd9Sstevel@tonic-gate 
2038*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2039*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2040*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_getattr, vsop_getattr);
2041*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2042*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2043*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vap, flags, cr));
2044*7c478bd9Sstevel@tonic-gate }
2045*7c478bd9Sstevel@tonic-gate 
2046*7c478bd9Sstevel@tonic-gate int
2047*7c478bd9Sstevel@tonic-gate vnext_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
2048*7c478bd9Sstevel@tonic-gate 	caller_context_t *ct)
2049*7c478bd9Sstevel@tonic-gate {
2050*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2051*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2052*7c478bd9Sstevel@tonic-gate 
2053*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2054*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2055*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_setattr, vsop_setattr);
2056*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2057*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2058*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vap, flags, cr, ct));
2059*7c478bd9Sstevel@tonic-gate }
2060*7c478bd9Sstevel@tonic-gate 
2061*7c478bd9Sstevel@tonic-gate int
2062*7c478bd9Sstevel@tonic-gate vnext_access(femarg_t *vf, int mode, int flags, cred_t *cr)
2063*7c478bd9Sstevel@tonic-gate {
2064*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2065*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2066*7c478bd9Sstevel@tonic-gate 
2067*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2068*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2069*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_access, vsop_access);
2070*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2071*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2072*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, mode, flags, cr));
2073*7c478bd9Sstevel@tonic-gate }
2074*7c478bd9Sstevel@tonic-gate 
2075*7c478bd9Sstevel@tonic-gate int
2076*7c478bd9Sstevel@tonic-gate vnext_lookup(femarg_t *vf, char *nm, vnode_t **vpp, pathname_t *pnp,
2077*7c478bd9Sstevel@tonic-gate 	int flags, vnode_t *rdir, cred_t *cr)
2078*7c478bd9Sstevel@tonic-gate {
2079*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2080*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2081*7c478bd9Sstevel@tonic-gate 
2082*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2083*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2084*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_lookup, vsop_lookup);
2085*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2086*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2087*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, nm, vpp, pnp, flags, rdir, cr));
2088*7c478bd9Sstevel@tonic-gate }
2089*7c478bd9Sstevel@tonic-gate 
2090*7c478bd9Sstevel@tonic-gate int
2091*7c478bd9Sstevel@tonic-gate vnext_create(femarg_t *vf, char *name, vattr_t *vap, vcexcl_t excl,
2092*7c478bd9Sstevel@tonic-gate 	int mode, vnode_t **vpp, cred_t *cr, int flag)
2093*7c478bd9Sstevel@tonic-gate {
2094*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2095*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2096*7c478bd9Sstevel@tonic-gate 
2097*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2098*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2099*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_create, vsop_create);
2100*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2101*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2102*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, name, vap, excl, mode, vpp, cr, flag));
2103*7c478bd9Sstevel@tonic-gate }
2104*7c478bd9Sstevel@tonic-gate 
2105*7c478bd9Sstevel@tonic-gate int
2106*7c478bd9Sstevel@tonic-gate vnext_remove(femarg_t *vf, char *nm, cred_t *cr)
2107*7c478bd9Sstevel@tonic-gate {
2108*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2109*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2110*7c478bd9Sstevel@tonic-gate 
2111*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2112*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2113*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_remove, vsop_remove);
2114*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2115*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2116*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, nm, cr));
2117*7c478bd9Sstevel@tonic-gate }
2118*7c478bd9Sstevel@tonic-gate 
2119*7c478bd9Sstevel@tonic-gate int
2120*7c478bd9Sstevel@tonic-gate vnext_link(femarg_t *vf, vnode_t *svp, char *tnm, cred_t *cr)
2121*7c478bd9Sstevel@tonic-gate {
2122*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2123*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2124*7c478bd9Sstevel@tonic-gate 
2125*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2126*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2127*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_link, vsop_link);
2128*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2129*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2130*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, svp, tnm, cr));
2131*7c478bd9Sstevel@tonic-gate }
2132*7c478bd9Sstevel@tonic-gate 
2133*7c478bd9Sstevel@tonic-gate int
2134*7c478bd9Sstevel@tonic-gate vnext_rename(femarg_t *vf, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr)
2135*7c478bd9Sstevel@tonic-gate {
2136*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2137*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2138*7c478bd9Sstevel@tonic-gate 
2139*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2140*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2141*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_rename, vsop_rename);
2142*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2143*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2144*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, snm, tdvp, tnm, cr));
2145*7c478bd9Sstevel@tonic-gate }
2146*7c478bd9Sstevel@tonic-gate 
2147*7c478bd9Sstevel@tonic-gate int
2148*7c478bd9Sstevel@tonic-gate vnext_mkdir(femarg_t *vf, char *dirname, vattr_t *vap, vnode_t **vpp,
2149*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2150*7c478bd9Sstevel@tonic-gate {
2151*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2152*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2153*7c478bd9Sstevel@tonic-gate 
2154*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2155*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2156*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_mkdir, vsop_mkdir);
2157*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2158*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2159*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, dirname, vap, vpp, cr));
2160*7c478bd9Sstevel@tonic-gate }
2161*7c478bd9Sstevel@tonic-gate 
2162*7c478bd9Sstevel@tonic-gate int
2163*7c478bd9Sstevel@tonic-gate vnext_rmdir(femarg_t *vf, char *nm, vnode_t *cdir, cred_t *cr)
2164*7c478bd9Sstevel@tonic-gate {
2165*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2166*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2167*7c478bd9Sstevel@tonic-gate 
2168*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2169*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2170*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_rmdir, vsop_rmdir);
2171*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2172*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2173*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, nm, cdir, cr));
2174*7c478bd9Sstevel@tonic-gate }
2175*7c478bd9Sstevel@tonic-gate 
2176*7c478bd9Sstevel@tonic-gate int
2177*7c478bd9Sstevel@tonic-gate vnext_readdir(femarg_t *vf, uio_t *uiop, cred_t *cr, int *eofp)
2178*7c478bd9Sstevel@tonic-gate {
2179*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2180*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2181*7c478bd9Sstevel@tonic-gate 
2182*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2183*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2184*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_readdir, vsop_readdir);
2185*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2186*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2187*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, uiop, cr, eofp));
2188*7c478bd9Sstevel@tonic-gate }
2189*7c478bd9Sstevel@tonic-gate 
2190*7c478bd9Sstevel@tonic-gate int
2191*7c478bd9Sstevel@tonic-gate vnext_symlink(femarg_t *vf, char *linkname, vattr_t *vap, char *target,
2192*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2193*7c478bd9Sstevel@tonic-gate {
2194*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2195*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2196*7c478bd9Sstevel@tonic-gate 
2197*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2198*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2199*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_symlink, vsop_symlink);
2200*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2201*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2202*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, linkname, vap, target, cr));
2203*7c478bd9Sstevel@tonic-gate }
2204*7c478bd9Sstevel@tonic-gate 
2205*7c478bd9Sstevel@tonic-gate int
2206*7c478bd9Sstevel@tonic-gate vnext_readlink(femarg_t *vf, uio_t *uiop, cred_t *cr)
2207*7c478bd9Sstevel@tonic-gate {
2208*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2209*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2210*7c478bd9Sstevel@tonic-gate 
2211*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2212*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2213*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_readlink, vsop_readlink);
2214*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2215*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2216*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, uiop, cr));
2217*7c478bd9Sstevel@tonic-gate }
2218*7c478bd9Sstevel@tonic-gate 
2219*7c478bd9Sstevel@tonic-gate int
2220*7c478bd9Sstevel@tonic-gate vnext_fsync(femarg_t *vf, int syncflag, cred_t *cr)
2221*7c478bd9Sstevel@tonic-gate {
2222*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2223*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2224*7c478bd9Sstevel@tonic-gate 
2225*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2226*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2227*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_fsync, vsop_fsync);
2228*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2229*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2230*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, syncflag, cr));
2231*7c478bd9Sstevel@tonic-gate }
2232*7c478bd9Sstevel@tonic-gate 
2233*7c478bd9Sstevel@tonic-gate void
2234*7c478bd9Sstevel@tonic-gate vnext_inactive(femarg_t *vf, cred_t *cr)
2235*7c478bd9Sstevel@tonic-gate {
2236*7c478bd9Sstevel@tonic-gate 	void (*func)() = NULL;
2237*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2238*7c478bd9Sstevel@tonic-gate 
2239*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2240*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2241*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, void, &arg0, vop_inactive, vsop_inactive);
2242*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2243*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2244*7c478bd9Sstevel@tonic-gate 	(*func)(arg0, cr);
2245*7c478bd9Sstevel@tonic-gate }
2246*7c478bd9Sstevel@tonic-gate 
2247*7c478bd9Sstevel@tonic-gate int
2248*7c478bd9Sstevel@tonic-gate vnext_fid(femarg_t *vf, fid_t *fidp)
2249*7c478bd9Sstevel@tonic-gate {
2250*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2251*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2252*7c478bd9Sstevel@tonic-gate 
2253*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2254*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2255*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_fid, vsop_fid);
2256*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2257*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2258*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, fidp));
2259*7c478bd9Sstevel@tonic-gate }
2260*7c478bd9Sstevel@tonic-gate 
2261*7c478bd9Sstevel@tonic-gate int
2262*7c478bd9Sstevel@tonic-gate vnext_rwlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2263*7c478bd9Sstevel@tonic-gate {
2264*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2265*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2266*7c478bd9Sstevel@tonic-gate 
2267*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2268*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2269*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_rwlock, vsop_rwlock);
2270*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2271*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2272*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, write_lock, ct));
2273*7c478bd9Sstevel@tonic-gate }
2274*7c478bd9Sstevel@tonic-gate 
2275*7c478bd9Sstevel@tonic-gate void
2276*7c478bd9Sstevel@tonic-gate vnext_rwunlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2277*7c478bd9Sstevel@tonic-gate {
2278*7c478bd9Sstevel@tonic-gate 	void (*func)() = NULL;
2279*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2280*7c478bd9Sstevel@tonic-gate 
2281*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2282*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2283*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, void, &arg0, vop_rwunlock, vsop_rwunlock);
2284*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2285*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2286*7c478bd9Sstevel@tonic-gate 	(*func)(arg0, write_lock, ct);
2287*7c478bd9Sstevel@tonic-gate }
2288*7c478bd9Sstevel@tonic-gate 
2289*7c478bd9Sstevel@tonic-gate int
2290*7c478bd9Sstevel@tonic-gate vnext_seek(femarg_t *vf, offset_t ooff, offset_t *noffp)
2291*7c478bd9Sstevel@tonic-gate {
2292*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2293*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2294*7c478bd9Sstevel@tonic-gate 
2295*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2296*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2297*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_seek, vsop_seek);
2298*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2299*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2300*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, ooff, noffp));
2301*7c478bd9Sstevel@tonic-gate }
2302*7c478bd9Sstevel@tonic-gate 
2303*7c478bd9Sstevel@tonic-gate int
2304*7c478bd9Sstevel@tonic-gate vnext_cmp(femarg_t *vf, vnode_t *vp2)
2305*7c478bd9Sstevel@tonic-gate {
2306*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2307*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2308*7c478bd9Sstevel@tonic-gate 
2309*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2310*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2311*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_cmp, vsop_cmp);
2312*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2313*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2314*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vp2));
2315*7c478bd9Sstevel@tonic-gate }
2316*7c478bd9Sstevel@tonic-gate 
2317*7c478bd9Sstevel@tonic-gate int
2318*7c478bd9Sstevel@tonic-gate vnext_frlock(femarg_t *vf, int cmd, struct flock64 *bfp, int flag,
2319*7c478bd9Sstevel@tonic-gate 	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr)
2320*7c478bd9Sstevel@tonic-gate {
2321*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2322*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2323*7c478bd9Sstevel@tonic-gate 
2324*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2325*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2326*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_frlock, vsop_frlock);
2327*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2328*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2329*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr));
2330*7c478bd9Sstevel@tonic-gate }
2331*7c478bd9Sstevel@tonic-gate 
2332*7c478bd9Sstevel@tonic-gate int
2333*7c478bd9Sstevel@tonic-gate vnext_space(femarg_t *vf, int cmd, struct flock64 *bfp, int flag,
2334*7c478bd9Sstevel@tonic-gate 	offset_t offset, cred_t *cr, caller_context_t *ct)
2335*7c478bd9Sstevel@tonic-gate {
2336*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2337*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2338*7c478bd9Sstevel@tonic-gate 
2339*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2340*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2341*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_space, vsop_space);
2342*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2343*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2344*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, cmd, bfp, flag, offset, cr, ct));
2345*7c478bd9Sstevel@tonic-gate }
2346*7c478bd9Sstevel@tonic-gate 
2347*7c478bd9Sstevel@tonic-gate int
2348*7c478bd9Sstevel@tonic-gate vnext_realvp(femarg_t *vf, vnode_t **vpp)
2349*7c478bd9Sstevel@tonic-gate {
2350*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2351*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2354*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2355*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_realvp, vsop_realvp);
2356*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2357*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2358*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vpp));
2359*7c478bd9Sstevel@tonic-gate }
2360*7c478bd9Sstevel@tonic-gate 
2361*7c478bd9Sstevel@tonic-gate int
2362*7c478bd9Sstevel@tonic-gate vnext_getpage(femarg_t *vf, offset_t off, size_t len, uint_t *protp,
2363*7c478bd9Sstevel@tonic-gate 	struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
2364*7c478bd9Sstevel@tonic-gate 	enum seg_rw rw, cred_t *cr)
2365*7c478bd9Sstevel@tonic-gate {
2366*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2367*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2368*7c478bd9Sstevel@tonic-gate 
2369*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2370*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2371*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_getpage, vsop_getpage);
2372*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2373*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2374*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, off, len, protp, plarr, plsz, seg, addr, rw,
2375*7c478bd9Sstevel@tonic-gate 			cr));
2376*7c478bd9Sstevel@tonic-gate }
2377*7c478bd9Sstevel@tonic-gate 
2378*7c478bd9Sstevel@tonic-gate int
2379*7c478bd9Sstevel@tonic-gate vnext_putpage(femarg_t *vf, offset_t off, size_t len, int flags,
2380*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2381*7c478bd9Sstevel@tonic-gate {
2382*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2383*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2384*7c478bd9Sstevel@tonic-gate 
2385*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2386*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2387*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_putpage, vsop_putpage);
2388*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2389*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2390*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, off, len, flags, cr));
2391*7c478bd9Sstevel@tonic-gate }
2392*7c478bd9Sstevel@tonic-gate 
2393*7c478bd9Sstevel@tonic-gate int
2394*7c478bd9Sstevel@tonic-gate vnext_map(femarg_t *vf, offset_t off, struct as *as, caddr_t *addrp,
2395*7c478bd9Sstevel@tonic-gate 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
2396*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2397*7c478bd9Sstevel@tonic-gate {
2398*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2399*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2400*7c478bd9Sstevel@tonic-gate 
2401*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2402*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2403*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_map, vsop_map);
2404*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2405*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2406*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, off, as, addrp, len, prot, maxprot, flags,
2407*7c478bd9Sstevel@tonic-gate 			cr));
2408*7c478bd9Sstevel@tonic-gate }
2409*7c478bd9Sstevel@tonic-gate 
2410*7c478bd9Sstevel@tonic-gate int
2411*7c478bd9Sstevel@tonic-gate vnext_addmap(femarg_t *vf, offset_t off, struct as *as, caddr_t addr,
2412*7c478bd9Sstevel@tonic-gate 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
2413*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2414*7c478bd9Sstevel@tonic-gate {
2415*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2416*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2417*7c478bd9Sstevel@tonic-gate 
2418*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2419*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2420*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_addmap, vsop_addmap);
2421*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2422*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2423*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags, cr));
2424*7c478bd9Sstevel@tonic-gate }
2425*7c478bd9Sstevel@tonic-gate 
2426*7c478bd9Sstevel@tonic-gate int
2427*7c478bd9Sstevel@tonic-gate vnext_delmap(femarg_t *vf, offset_t off, struct as *as, caddr_t addr,
2428*7c478bd9Sstevel@tonic-gate 	size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr)
2429*7c478bd9Sstevel@tonic-gate {
2430*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2431*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2432*7c478bd9Sstevel@tonic-gate 
2433*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2434*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2435*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_delmap, vsop_delmap);
2436*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2437*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2438*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags, cr));
2439*7c478bd9Sstevel@tonic-gate }
2440*7c478bd9Sstevel@tonic-gate 
2441*7c478bd9Sstevel@tonic-gate int
2442*7c478bd9Sstevel@tonic-gate vnext_poll(femarg_t *vf, short events, int anyyet, short *reventsp,
2443*7c478bd9Sstevel@tonic-gate 	struct pollhead **phpp)
2444*7c478bd9Sstevel@tonic-gate {
2445*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2446*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2447*7c478bd9Sstevel@tonic-gate 
2448*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2449*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2450*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_poll, vsop_poll);
2451*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2452*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2453*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, events, anyyet, reventsp, phpp));
2454*7c478bd9Sstevel@tonic-gate }
2455*7c478bd9Sstevel@tonic-gate 
2456*7c478bd9Sstevel@tonic-gate int
2457*7c478bd9Sstevel@tonic-gate vnext_dump(femarg_t *vf, caddr_t addr, int lbdn, int dblks)
2458*7c478bd9Sstevel@tonic-gate {
2459*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2460*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2461*7c478bd9Sstevel@tonic-gate 
2462*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2463*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2464*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_dump, vsop_dump);
2465*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2466*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2467*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, addr, lbdn, dblks));
2468*7c478bd9Sstevel@tonic-gate }
2469*7c478bd9Sstevel@tonic-gate 
2470*7c478bd9Sstevel@tonic-gate int
2471*7c478bd9Sstevel@tonic-gate vnext_pathconf(femarg_t *vf, int cmd, ulong_t *valp, cred_t *cr)
2472*7c478bd9Sstevel@tonic-gate {
2473*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2474*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2475*7c478bd9Sstevel@tonic-gate 
2476*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2477*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2478*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_pathconf, vsop_pathconf);
2479*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2480*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2481*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, cmd, valp, cr));
2482*7c478bd9Sstevel@tonic-gate }
2483*7c478bd9Sstevel@tonic-gate 
2484*7c478bd9Sstevel@tonic-gate int
2485*7c478bd9Sstevel@tonic-gate vnext_pageio(femarg_t *vf, struct page *pp, u_offset_t io_off,
2486*7c478bd9Sstevel@tonic-gate 	size_t io_len, int flags, cred_t *cr)
2487*7c478bd9Sstevel@tonic-gate {
2488*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2489*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2490*7c478bd9Sstevel@tonic-gate 
2491*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2492*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2493*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_pageio, vsop_pageio);
2494*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2495*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2496*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, pp, io_off, io_len, flags, cr));
2497*7c478bd9Sstevel@tonic-gate }
2498*7c478bd9Sstevel@tonic-gate 
2499*7c478bd9Sstevel@tonic-gate int
2500*7c478bd9Sstevel@tonic-gate vnext_dumpctl(femarg_t *vf, int action, int *blkp)
2501*7c478bd9Sstevel@tonic-gate {
2502*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2503*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2504*7c478bd9Sstevel@tonic-gate 
2505*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2506*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2507*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_dumpctl, vsop_dumpctl);
2508*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2509*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2510*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, action, blkp));
2511*7c478bd9Sstevel@tonic-gate }
2512*7c478bd9Sstevel@tonic-gate 
2513*7c478bd9Sstevel@tonic-gate void
2514*7c478bd9Sstevel@tonic-gate vnext_dispose(femarg_t *vf, struct page *pp, int flag, int dn, cred_t *cr)
2515*7c478bd9Sstevel@tonic-gate {
2516*7c478bd9Sstevel@tonic-gate 	void (*func)() = NULL;
2517*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2518*7c478bd9Sstevel@tonic-gate 
2519*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2520*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2521*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, void, &arg0, vop_dispose, vsop_dispose);
2522*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2523*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2524*7c478bd9Sstevel@tonic-gate 	(*func)(arg0, pp, flag, dn, cr);
2525*7c478bd9Sstevel@tonic-gate }
2526*7c478bd9Sstevel@tonic-gate 
2527*7c478bd9Sstevel@tonic-gate int
2528*7c478bd9Sstevel@tonic-gate vnext_setsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr)
2529*7c478bd9Sstevel@tonic-gate {
2530*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2531*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2532*7c478bd9Sstevel@tonic-gate 
2533*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2534*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2535*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_setsecattr, vsop_setsecattr);
2536*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2537*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2538*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vsap, flag, cr));
2539*7c478bd9Sstevel@tonic-gate }
2540*7c478bd9Sstevel@tonic-gate 
2541*7c478bd9Sstevel@tonic-gate int
2542*7c478bd9Sstevel@tonic-gate vnext_getsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr)
2543*7c478bd9Sstevel@tonic-gate {
2544*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2545*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2546*7c478bd9Sstevel@tonic-gate 
2547*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2548*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2549*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_getsecattr, vsop_getsecattr);
2550*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2551*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2552*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vsap, flag, cr));
2553*7c478bd9Sstevel@tonic-gate }
2554*7c478bd9Sstevel@tonic-gate 
2555*7c478bd9Sstevel@tonic-gate int
2556*7c478bd9Sstevel@tonic-gate vnext_shrlock(femarg_t *vf, int cmd, struct shrlock *shr, int flag,
2557*7c478bd9Sstevel@tonic-gate 	cred_t *cr)
2558*7c478bd9Sstevel@tonic-gate {
2559*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2560*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2561*7c478bd9Sstevel@tonic-gate 
2562*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2563*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2564*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_shrlock, vsop_shrlock);
2565*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2566*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2567*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, cmd, shr, flag, cr));
2568*7c478bd9Sstevel@tonic-gate }
2569*7c478bd9Sstevel@tonic-gate 
2570*7c478bd9Sstevel@tonic-gate int
2571*7c478bd9Sstevel@tonic-gate vnext_vnevent(femarg_t *vf, vnevent_t vnevent)
2572*7c478bd9Sstevel@tonic-gate {
2573*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2574*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2575*7c478bd9Sstevel@tonic-gate 
2576*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2577*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2578*7c478bd9Sstevel@tonic-gate 	vsop_find(vf, &func, int, &arg0, vop_vnevent, vsop_vnevent);
2579*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2580*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2581*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vnevent));
2582*7c478bd9Sstevel@tonic-gate }
2583*7c478bd9Sstevel@tonic-gate 
2584*7c478bd9Sstevel@tonic-gate int
2585*7c478bd9Sstevel@tonic-gate vfsnext_mount(fsemarg_t *vf, vnode_t *mvp, struct mounta *uap, cred_t *cr)
2586*7c478bd9Sstevel@tonic-gate {
2587*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2588*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2589*7c478bd9Sstevel@tonic-gate 
2590*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2591*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2592*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_mount, vfsop_mount);
2593*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2594*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2595*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, mvp, uap, cr));
2596*7c478bd9Sstevel@tonic-gate }
2597*7c478bd9Sstevel@tonic-gate 
2598*7c478bd9Sstevel@tonic-gate int
2599*7c478bd9Sstevel@tonic-gate vfsnext_unmount(fsemarg_t *vf, int flag, cred_t *cr)
2600*7c478bd9Sstevel@tonic-gate {
2601*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2602*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2603*7c478bd9Sstevel@tonic-gate 
2604*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2605*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2606*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_unmount, vfsop_unmount);
2607*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2608*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2609*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, flag, cr));
2610*7c478bd9Sstevel@tonic-gate }
2611*7c478bd9Sstevel@tonic-gate 
2612*7c478bd9Sstevel@tonic-gate int
2613*7c478bd9Sstevel@tonic-gate vfsnext_root(fsemarg_t *vf, vnode_t **vpp)
2614*7c478bd9Sstevel@tonic-gate {
2615*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2616*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2617*7c478bd9Sstevel@tonic-gate 
2618*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2619*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2620*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_root, vfsop_root);
2621*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2622*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2623*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vpp));
2624*7c478bd9Sstevel@tonic-gate }
2625*7c478bd9Sstevel@tonic-gate 
2626*7c478bd9Sstevel@tonic-gate int
2627*7c478bd9Sstevel@tonic-gate vfsnext_statvfs(fsemarg_t *vf, statvfs64_t *sp)
2628*7c478bd9Sstevel@tonic-gate {
2629*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2630*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2631*7c478bd9Sstevel@tonic-gate 
2632*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2633*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2634*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_statvfs, vfsop_statvfs);
2635*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2636*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2637*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, sp));
2638*7c478bd9Sstevel@tonic-gate }
2639*7c478bd9Sstevel@tonic-gate 
2640*7c478bd9Sstevel@tonic-gate int
2641*7c478bd9Sstevel@tonic-gate vfsnext_sync(fsemarg_t *vf, short flag, cred_t *cr)
2642*7c478bd9Sstevel@tonic-gate {
2643*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2644*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2645*7c478bd9Sstevel@tonic-gate 
2646*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2647*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2648*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_sync, vfsop_sync);
2649*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2650*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2651*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, flag, cr));
2652*7c478bd9Sstevel@tonic-gate }
2653*7c478bd9Sstevel@tonic-gate 
2654*7c478bd9Sstevel@tonic-gate int
2655*7c478bd9Sstevel@tonic-gate vfsnext_vget(fsemarg_t *vf, vnode_t **vpp, fid_t *fidp)
2656*7c478bd9Sstevel@tonic-gate {
2657*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2658*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2659*7c478bd9Sstevel@tonic-gate 
2660*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2661*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2662*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_vget, vfsop_vget);
2663*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2664*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2665*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vpp, fidp));
2666*7c478bd9Sstevel@tonic-gate }
2667*7c478bd9Sstevel@tonic-gate 
2668*7c478bd9Sstevel@tonic-gate int
2669*7c478bd9Sstevel@tonic-gate vfsnext_mountroot(fsemarg_t *vf, enum whymountroot reason)
2670*7c478bd9Sstevel@tonic-gate {
2671*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2672*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2673*7c478bd9Sstevel@tonic-gate 
2674*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2675*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2676*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_mountroot, vfsop_mountroot);
2677*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2678*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2679*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, reason));
2680*7c478bd9Sstevel@tonic-gate }
2681*7c478bd9Sstevel@tonic-gate 
2682*7c478bd9Sstevel@tonic-gate void
2683*7c478bd9Sstevel@tonic-gate vfsnext_freevfs(fsemarg_t *vf)
2684*7c478bd9Sstevel@tonic-gate {
2685*7c478bd9Sstevel@tonic-gate 	void (*func)() = NULL;
2686*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2687*7c478bd9Sstevel@tonic-gate 
2688*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2689*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2690*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, void, &arg0, vfs_freevfs, vfsop_freevfs);
2691*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2692*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2693*7c478bd9Sstevel@tonic-gate 	(*func)(arg0);
2694*7c478bd9Sstevel@tonic-gate }
2695*7c478bd9Sstevel@tonic-gate 
2696*7c478bd9Sstevel@tonic-gate int
2697*7c478bd9Sstevel@tonic-gate vfsnext_vnstate(fsemarg_t *vf, vnode_t *vp, vntrans_t nstate)
2698*7c478bd9Sstevel@tonic-gate {
2699*7c478bd9Sstevel@tonic-gate 	int (*func)() = NULL;
2700*7c478bd9Sstevel@tonic-gate 	void *arg0 = NULL;
2701*7c478bd9Sstevel@tonic-gate 
2702*7c478bd9Sstevel@tonic-gate 	ASSERT(vf != NULL);
2703*7c478bd9Sstevel@tonic-gate 	vf->fa_fnode--;
2704*7c478bd9Sstevel@tonic-gate 	vfsop_find(vf, &func, int, &arg0, vfs_vnstate, vfsop_vnstate);
2705*7c478bd9Sstevel@tonic-gate 	ASSERT(func != NULL);
2706*7c478bd9Sstevel@tonic-gate 	ASSERT(arg0 != NULL);
2707*7c478bd9Sstevel@tonic-gate 	return ((*func)(arg0, vp, nstate));
2708*7c478bd9Sstevel@tonic-gate }
2709*7c478bd9Sstevel@tonic-gate 
2710*7c478bd9Sstevel@tonic-gate 
2711*7c478bd9Sstevel@tonic-gate /*
2712*7c478bd9Sstevel@tonic-gate  * Create a new fem_head and associate with the vnode.
2713*7c478bd9Sstevel@tonic-gate  * To keep the unaugmented vnode access path lock free, we spin
2714*7c478bd9Sstevel@tonic-gate  * update this - create a new one, then try and install it. If
2715*7c478bd9Sstevel@tonic-gate  * we fail to install, release the old one and pretend we succeeded.
2716*7c478bd9Sstevel@tonic-gate  */
2717*7c478bd9Sstevel@tonic-gate 
2718*7c478bd9Sstevel@tonic-gate static struct fem_head *
2719*7c478bd9Sstevel@tonic-gate new_femhead(struct fem_head **hp)
2720*7c478bd9Sstevel@tonic-gate {
2721*7c478bd9Sstevel@tonic-gate 	struct fem_head	*head;
2722*7c478bd9Sstevel@tonic-gate 
2723*7c478bd9Sstevel@tonic-gate 	head = kmem_alloc(sizeof (*head), KM_SLEEP);
2724*7c478bd9Sstevel@tonic-gate 	mutex_init(&head->femh_lock, NULL, MUTEX_DEFAULT, NULL);
2725*7c478bd9Sstevel@tonic-gate 	head->femh_list = NULL;
2726*7c478bd9Sstevel@tonic-gate 	if (casptr(hp, NULL, head) != NULL) {
2727*7c478bd9Sstevel@tonic-gate 		kmem_free(head, sizeof (*head));
2728*7c478bd9Sstevel@tonic-gate 		head = *hp;
2729*7c478bd9Sstevel@tonic-gate 	}
2730*7c478bd9Sstevel@tonic-gate 	return (head);
2731*7c478bd9Sstevel@tonic-gate }
2732*7c478bd9Sstevel@tonic-gate 
2733*7c478bd9Sstevel@tonic-gate /*
2734*7c478bd9Sstevel@tonic-gate  * Create a fem_list.  The fem_list that gets returned is in a
2735*7c478bd9Sstevel@tonic-gate  * very rudimentary state and MUST NOT be used until it's initialized
2736*7c478bd9Sstevel@tonic-gate  * (usually by femlist_construct() or fem_dup_list()).  The refcount
2737*7c478bd9Sstevel@tonic-gate  * and size is set properly and top-of-stack is set to the "guard" node
2738*7c478bd9Sstevel@tonic-gate  * just to be consistent.
2739*7c478bd9Sstevel@tonic-gate  *
2740*7c478bd9Sstevel@tonic-gate  * If anyone were to accidentally trying to run on this fem_list before
2741*7c478bd9Sstevel@tonic-gate  * it's initialized then the system would likely panic trying to defererence
2742*7c478bd9Sstevel@tonic-gate  * the (NULL) fn_op pointer.
2743*7c478bd9Sstevel@tonic-gate  *
2744*7c478bd9Sstevel@tonic-gate  */
2745*7c478bd9Sstevel@tonic-gate static struct fem_list *
2746*7c478bd9Sstevel@tonic-gate femlist_create(int numnodes)
2747*7c478bd9Sstevel@tonic-gate {
2748*7c478bd9Sstevel@tonic-gate 	struct fem_list	*sp;
2749*7c478bd9Sstevel@tonic-gate 
2750*7c478bd9Sstevel@tonic-gate 	sp = kmem_alloc(fl_ntob(numnodes), KM_SLEEP);
2751*7c478bd9Sstevel@tonic-gate 	sp->feml_refc  = 1;
2752*7c478bd9Sstevel@tonic-gate 	sp->feml_ssize = numnodes;
2753*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[0] = FEM_GUARD(FEMTYPE_NULL);
2754*7c478bd9Sstevel@tonic-gate 	sp->feml_tos = 0;
2755*7c478bd9Sstevel@tonic-gate 	return (sp);
2756*7c478bd9Sstevel@tonic-gate }
2757*7c478bd9Sstevel@tonic-gate 
2758*7c478bd9Sstevel@tonic-gate /*
2759*7c478bd9Sstevel@tonic-gate  * Construct a new femlist.
2760*7c478bd9Sstevel@tonic-gate  * The list is constructed with the appropriate type of guard to
2761*7c478bd9Sstevel@tonic-gate  * anchor it, and inserts the original ops.
2762*7c478bd9Sstevel@tonic-gate  */
2763*7c478bd9Sstevel@tonic-gate 
2764*7c478bd9Sstevel@tonic-gate static struct fem_list *
2765*7c478bd9Sstevel@tonic-gate femlist_construct(void *baseops, int type, int numnodes)
2766*7c478bd9Sstevel@tonic-gate {
2767*7c478bd9Sstevel@tonic-gate 	struct fem_list	*sp;
2768*7c478bd9Sstevel@tonic-gate 
2769*7c478bd9Sstevel@tonic-gate 	sp = femlist_create(numnodes);
2770*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[0] = FEM_GUARD(type);
2771*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[1].fn_op.anon = baseops;
2772*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[1].fn_available = NULL;
2773*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[1].fn_av_hold = NULL;
2774*7c478bd9Sstevel@tonic-gate 	sp->feml_nodes[1].fn_av_rele = NULL;
2775*7c478bd9Sstevel@tonic-gate 	sp->feml_tos = 1;
2776*7c478bd9Sstevel@tonic-gate 	return (sp);
2777*7c478bd9Sstevel@tonic-gate }
2778*7c478bd9Sstevel@tonic-gate 
2779*7c478bd9Sstevel@tonic-gate /*
2780*7c478bd9Sstevel@tonic-gate  * Duplicate a list.  Copy the original list to the clone.
2781*7c478bd9Sstevel@tonic-gate  *
2782*7c478bd9Sstevel@tonic-gate  * NOTE: The caller must have the fem_head for the lists locked.
2783*7c478bd9Sstevel@tonic-gate  * Assuming the appropriate lock is held and the caller has done the
2784*7c478bd9Sstevel@tonic-gate  * math right, the clone list should be big enough to old the original.
2785*7c478bd9Sstevel@tonic-gate  */
2786*7c478bd9Sstevel@tonic-gate 
2787*7c478bd9Sstevel@tonic-gate static void
2788*7c478bd9Sstevel@tonic-gate fem_dup_list(struct fem_list *orig, struct fem_list *clone)
2789*7c478bd9Sstevel@tonic-gate {
2790*7c478bd9Sstevel@tonic-gate 	int		i;
2791*7c478bd9Sstevel@tonic-gate 
2792*7c478bd9Sstevel@tonic-gate 	ASSERT(clone->feml_ssize >= orig->feml_ssize);
2793*7c478bd9Sstevel@tonic-gate 
2794*7c478bd9Sstevel@tonic-gate 	bcopy(orig->feml_nodes, clone->feml_nodes,
2795*7c478bd9Sstevel@tonic-gate 		sizeof (orig->feml_nodes[0]) * orig->feml_ssize);
2796*7c478bd9Sstevel@tonic-gate 	clone->feml_tos = orig->feml_tos;
2797*7c478bd9Sstevel@tonic-gate 	/*
2798*7c478bd9Sstevel@tonic-gate 	 * Now that we've copied the old list (orig) to the new list (clone),
2799*7c478bd9Sstevel@tonic-gate 	 * we need to walk the new list and put another hold on fn_available.
2800*7c478bd9Sstevel@tonic-gate 	 */
2801*7c478bd9Sstevel@tonic-gate 	for (i = clone->feml_tos; i > 0; i--) {
2802*7c478bd9Sstevel@tonic-gate 		struct fem_node *fnp = &clone->feml_nodes[i];
2803*7c478bd9Sstevel@tonic-gate 
2804*7c478bd9Sstevel@tonic-gate 		if (fnp->fn_av_hold)
2805*7c478bd9Sstevel@tonic-gate 			(*(fnp->fn_av_hold))(fnp->fn_available);
2806*7c478bd9Sstevel@tonic-gate 	}
2807*7c478bd9Sstevel@tonic-gate }
2808*7c478bd9Sstevel@tonic-gate 
2809*7c478bd9Sstevel@tonic-gate 
2810*7c478bd9Sstevel@tonic-gate static int
2811*7c478bd9Sstevel@tonic-gate fem_push_node(
2812*7c478bd9Sstevel@tonic-gate 	struct fem_head **hp,
2813*7c478bd9Sstevel@tonic-gate 	void **baseops,
2814*7c478bd9Sstevel@tonic-gate 	int type,
2815*7c478bd9Sstevel@tonic-gate 	struct fem_node *nnode,
2816*7c478bd9Sstevel@tonic-gate 	femhow_t how)
2817*7c478bd9Sstevel@tonic-gate {
2818*7c478bd9Sstevel@tonic-gate 	struct fem_head	*hd;
2819*7c478bd9Sstevel@tonic-gate 	struct fem_list	*list;
2820*7c478bd9Sstevel@tonic-gate 	void		*oldops;
2821*7c478bd9Sstevel@tonic-gate 	int		retry;
2822*7c478bd9Sstevel@tonic-gate 	int		error = 0;
2823*7c478bd9Sstevel@tonic-gate 	int		i;
2824*7c478bd9Sstevel@tonic-gate 
2825*7c478bd9Sstevel@tonic-gate 	/* Validate the node */
2826*7c478bd9Sstevel@tonic-gate 	if ((nnode->fn_op.anon == NULL) || (nnode->fn_available == NULL)) {
2827*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2828*7c478bd9Sstevel@tonic-gate 	}
2829*7c478bd9Sstevel@tonic-gate 
2830*7c478bd9Sstevel@tonic-gate 	if ((hd = *hp) == NULL) { /* construct a proto-list */
2831*7c478bd9Sstevel@tonic-gate 		hd = new_femhead(hp);
2832*7c478bd9Sstevel@tonic-gate 	}
2833*7c478bd9Sstevel@tonic-gate 	/*
2834*7c478bd9Sstevel@tonic-gate 	 * RULE: once a femhead has been pushed onto a object, it cannot be
2835*7c478bd9Sstevel@tonic-gate 	 * removed until the object is destroyed.  It can be deactivated by
2836*7c478bd9Sstevel@tonic-gate 	 * placing the original 'object operations' onto the object, which
2837*7c478bd9Sstevel@tonic-gate 	 * will ignore the femhead.
2838*7c478bd9Sstevel@tonic-gate 	 * The loop will exist when the femh_list has space to push a monitor
2839*7c478bd9Sstevel@tonic-gate 	 * onto it.
2840*7c478bd9Sstevel@tonic-gate 	 */
2841*7c478bd9Sstevel@tonic-gate 	do {
2842*7c478bd9Sstevel@tonic-gate 		retry = 1;
2843*7c478bd9Sstevel@tonic-gate 		list = fem_lock(hd);
2844*7c478bd9Sstevel@tonic-gate 		oldops = *baseops;
2845*7c478bd9Sstevel@tonic-gate 
2846*7c478bd9Sstevel@tonic-gate 		if (list != NULL) {
2847*7c478bd9Sstevel@tonic-gate 			if (list->feml_tos+1 < list->feml_ssize) {
2848*7c478bd9Sstevel@tonic-gate 				retry = 0;
2849*7c478bd9Sstevel@tonic-gate 			} else {
2850*7c478bd9Sstevel@tonic-gate 				struct fem_list	*olist = list;
2851*7c478bd9Sstevel@tonic-gate 
2852*7c478bd9Sstevel@tonic-gate 				fem_addref(olist);
2853*7c478bd9Sstevel@tonic-gate 				fem_unlock(hd);
2854*7c478bd9Sstevel@tonic-gate 				list = femlist_create(olist->feml_ssize * 2);
2855*7c478bd9Sstevel@tonic-gate 				(void) fem_lock(hd);
2856*7c478bd9Sstevel@tonic-gate 				if (hd->femh_list == olist) {
2857*7c478bd9Sstevel@tonic-gate 					if (list->feml_ssize <=
2858*7c478bd9Sstevel@tonic-gate 							olist->feml_ssize) {
2859*7c478bd9Sstevel@tonic-gate 						/*
2860*7c478bd9Sstevel@tonic-gate 						 * We have a new list, but it
2861*7c478bd9Sstevel@tonic-gate 						 * is too small to hold the
2862*7c478bd9Sstevel@tonic-gate 						 * original contents plus the
2863*7c478bd9Sstevel@tonic-gate 						 * one to push.  Release the
2864*7c478bd9Sstevel@tonic-gate 						 * new list and start over.
2865*7c478bd9Sstevel@tonic-gate 						 */
2866*7c478bd9Sstevel@tonic-gate 						fem_release(list);
2867*7c478bd9Sstevel@tonic-gate 						fem_unlock(hd);
2868*7c478bd9Sstevel@tonic-gate 					} else {
2869*7c478bd9Sstevel@tonic-gate 						/*
2870*7c478bd9Sstevel@tonic-gate 						 * Life is good:  Our new list
2871*7c478bd9Sstevel@tonic-gate 						 * is big enough to hold the
2872*7c478bd9Sstevel@tonic-gate 						 * original list (olist) + 1.
2873*7c478bd9Sstevel@tonic-gate 						 */
2874*7c478bd9Sstevel@tonic-gate 						fem_dup_list(olist, list);
2875*7c478bd9Sstevel@tonic-gate 						/* orphan this list */
2876*7c478bd9Sstevel@tonic-gate 						hd->femh_list = list;
2877*7c478bd9Sstevel@tonic-gate 						fem_delref(olist);
2878*7c478bd9Sstevel@tonic-gate 						retry = 0;
2879*7c478bd9Sstevel@tonic-gate 					}
2880*7c478bd9Sstevel@tonic-gate 				} else {
2881*7c478bd9Sstevel@tonic-gate 					/* concurrent update, retry */
2882*7c478bd9Sstevel@tonic-gate 					fem_release(list);
2883*7c478bd9Sstevel@tonic-gate 					fem_unlock(hd);
2884*7c478bd9Sstevel@tonic-gate 				}
2885*7c478bd9Sstevel@tonic-gate 				/* remove the reference we added above */
2886*7c478bd9Sstevel@tonic-gate 				fem_release(olist);
2887*7c478bd9Sstevel@tonic-gate 			}
2888*7c478bd9Sstevel@tonic-gate 		} else {
2889*7c478bd9Sstevel@tonic-gate 			fem_unlock(hd);
2890*7c478bd9Sstevel@tonic-gate 			list = femlist_construct(oldops, type, NNODES_DEFAULT);
2891*7c478bd9Sstevel@tonic-gate 			(void) fem_lock(hd);
2892*7c478bd9Sstevel@tonic-gate 			if (hd->femh_list != NULL || *baseops != oldops) {
2893*7c478bd9Sstevel@tonic-gate 				/* concurrent update, retry */
2894*7c478bd9Sstevel@tonic-gate 				fem_release(list);
2895*7c478bd9Sstevel@tonic-gate 				fem_unlock(hd);
2896*7c478bd9Sstevel@tonic-gate 			} else {
2897*7c478bd9Sstevel@tonic-gate 				hd->femh_list = list;
2898*7c478bd9Sstevel@tonic-gate 				*baseops = FEM_HEAD(type);
2899*7c478bd9Sstevel@tonic-gate 				retry = 0;
2900*7c478bd9Sstevel@tonic-gate 			}
2901*7c478bd9Sstevel@tonic-gate 		}
2902*7c478bd9Sstevel@tonic-gate 	} while (retry);
2903*7c478bd9Sstevel@tonic-gate 
2904*7c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owner(&hd->femh_lock) == curthread);
2905*7c478bd9Sstevel@tonic-gate 	ASSERT(list->feml_tos+1 < list->feml_ssize);
2906*7c478bd9Sstevel@tonic-gate 
2907*7c478bd9Sstevel@tonic-gate 	/*
2908*7c478bd9Sstevel@tonic-gate 	 * The presence of "how" will modify the behavior of how/if
2909*7c478bd9Sstevel@tonic-gate 	 * nodes are pushed.  If it's FORCE, then we can skip
2910*7c478bd9Sstevel@tonic-gate 	 * all the checks and push it on.
2911*7c478bd9Sstevel@tonic-gate 	 */
2912*7c478bd9Sstevel@tonic-gate 	if (how != FORCE) {
2913*7c478bd9Sstevel@tonic-gate 		/* Start at the top and work our way down */
2914*7c478bd9Sstevel@tonic-gate 		for (i = list->feml_tos; i > 0; i--) {
2915*7c478bd9Sstevel@tonic-gate 			void *fn_av = list->feml_nodes[i].fn_available;
2916*7c478bd9Sstevel@tonic-gate 			void *fn_op = list->feml_nodes[i].fn_op.anon;
2917*7c478bd9Sstevel@tonic-gate 
2918*7c478bd9Sstevel@tonic-gate 			/*
2919*7c478bd9Sstevel@tonic-gate 			 * OPARGUNIQ means that this node should not
2920*7c478bd9Sstevel@tonic-gate 			 * be pushed on if a node with the same op/avail
2921*7c478bd9Sstevel@tonic-gate 			 * combination exists.  This situation returns
2922*7c478bd9Sstevel@tonic-gate 			 * EBUSY.
2923*7c478bd9Sstevel@tonic-gate 			 *
2924*7c478bd9Sstevel@tonic-gate 			 * OPUNIQ means that this node should not be
2925*7c478bd9Sstevel@tonic-gate 			 * pushed on if a node with the same op exists.
2926*7c478bd9Sstevel@tonic-gate 			 * This situation also returns EBUSY.
2927*7c478bd9Sstevel@tonic-gate 			 */
2928*7c478bd9Sstevel@tonic-gate 			switch (how) {
2929*7c478bd9Sstevel@tonic-gate 
2930*7c478bd9Sstevel@tonic-gate 			case OPUNIQ:
2931*7c478bd9Sstevel@tonic-gate 				if (fn_op == nnode->fn_op.anon) {
2932*7c478bd9Sstevel@tonic-gate 					error = EBUSY;
2933*7c478bd9Sstevel@tonic-gate 				}
2934*7c478bd9Sstevel@tonic-gate 				break;
2935*7c478bd9Sstevel@tonic-gate 
2936*7c478bd9Sstevel@tonic-gate 			case OPARGUNIQ:
2937*7c478bd9Sstevel@tonic-gate 				if ((fn_op == nnode->fn_op.anon) &&
2938*7c478bd9Sstevel@tonic-gate 				    (fn_av == nnode->fn_available)) {
2939*7c478bd9Sstevel@tonic-gate 					error = EBUSY;
2940*7c478bd9Sstevel@tonic-gate 				}
2941*7c478bd9Sstevel@tonic-gate 				break;
2942*7c478bd9Sstevel@tonic-gate 
2943*7c478bd9Sstevel@tonic-gate 			default:
2944*7c478bd9Sstevel@tonic-gate 				error = EINVAL;	/* Unexpected value */
2945*7c478bd9Sstevel@tonic-gate 				break;
2946*7c478bd9Sstevel@tonic-gate 			}
2947*7c478bd9Sstevel@tonic-gate 
2948*7c478bd9Sstevel@tonic-gate 			if (error)
2949*7c478bd9Sstevel@tonic-gate 				break;
2950*7c478bd9Sstevel@tonic-gate 		}
2951*7c478bd9Sstevel@tonic-gate 	}
2952*7c478bd9Sstevel@tonic-gate 
2953*7c478bd9Sstevel@tonic-gate 	if (error == 0) {
2954*7c478bd9Sstevel@tonic-gate 		/*
2955*7c478bd9Sstevel@tonic-gate 		 * If no errors, slap the node on the list.
2956*7c478bd9Sstevel@tonic-gate 		 * Note: The following is a structure copy.
2957*7c478bd9Sstevel@tonic-gate 		 */
2958*7c478bd9Sstevel@tonic-gate 		list->feml_nodes[++(list->feml_tos)] = *nnode;
2959*7c478bd9Sstevel@tonic-gate 	}
2960*7c478bd9Sstevel@tonic-gate 
2961*7c478bd9Sstevel@tonic-gate 	fem_unlock(hd);
2962*7c478bd9Sstevel@tonic-gate 	return (error);
2963*7c478bd9Sstevel@tonic-gate }
2964*7c478bd9Sstevel@tonic-gate 
2965*7c478bd9Sstevel@tonic-gate /*
2966*7c478bd9Sstevel@tonic-gate  * Remove a node by copying the list above it down a notch.
2967*7c478bd9Sstevel@tonic-gate  * If the list is busy, replace it with an idle one and work
2968*7c478bd9Sstevel@tonic-gate  * upon it.
2969*7c478bd9Sstevel@tonic-gate  * A node matches if the opset matches and the datap matches or is
2970*7c478bd9Sstevel@tonic-gate  * null.
2971*7c478bd9Sstevel@tonic-gate  */
2972*7c478bd9Sstevel@tonic-gate 
2973*7c478bd9Sstevel@tonic-gate static int
2974*7c478bd9Sstevel@tonic-gate remove_node(struct fem_list *sp, void **baseops, void *opset, void *datap)
2975*7c478bd9Sstevel@tonic-gate {
2976*7c478bd9Sstevel@tonic-gate 	int	i;
2977*7c478bd9Sstevel@tonic-gate 	struct fem_node	*fn;
2978*7c478bd9Sstevel@tonic-gate 
2979*7c478bd9Sstevel@tonic-gate 	for (i = sp->feml_tos; i > 0; i--) {
2980*7c478bd9Sstevel@tonic-gate 		fn = sp->feml_nodes+i;
2981*7c478bd9Sstevel@tonic-gate 		if (fn->fn_op.anon == opset &&
2982*7c478bd9Sstevel@tonic-gate 		    (fn->fn_available == datap || datap == NULL)) {
2983*7c478bd9Sstevel@tonic-gate 			break;
2984*7c478bd9Sstevel@tonic-gate 		}
2985*7c478bd9Sstevel@tonic-gate 	}
2986*7c478bd9Sstevel@tonic-gate 	if (i == 0) {
2987*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2988*7c478bd9Sstevel@tonic-gate 	}
2989*7c478bd9Sstevel@tonic-gate 
2990*7c478bd9Sstevel@tonic-gate 	/*
2991*7c478bd9Sstevel@tonic-gate 	 * At this point we have a node in-hand (*fn) that we are about
2992*7c478bd9Sstevel@tonic-gate 	 * to remove by overwriting it and adjusting the stack.  This is
2993*7c478bd9Sstevel@tonic-gate 	 * our last chance to do anything with this node so we do the
2994*7c478bd9Sstevel@tonic-gate 	 * release on the arg.
2995*7c478bd9Sstevel@tonic-gate 	 */
2996*7c478bd9Sstevel@tonic-gate 	if (fn->fn_av_rele)
2997*7c478bd9Sstevel@tonic-gate 		(*(fn->fn_av_rele))(fn->fn_available);
2998*7c478bd9Sstevel@tonic-gate 
2999*7c478bd9Sstevel@tonic-gate 	while (i++ < sp->feml_tos) {
3000*7c478bd9Sstevel@tonic-gate 		sp->feml_nodes[i-1] = sp->feml_nodes[i];
3001*7c478bd9Sstevel@tonic-gate 	}
3002*7c478bd9Sstevel@tonic-gate 	if (--(sp->feml_tos) == 1) { /* Empty, restore ops */
3003*7c478bd9Sstevel@tonic-gate 		*baseops = sp->feml_nodes[1].fn_op.anon;
3004*7c478bd9Sstevel@tonic-gate 	}
3005*7c478bd9Sstevel@tonic-gate 	return (0);
3006*7c478bd9Sstevel@tonic-gate }
3007*7c478bd9Sstevel@tonic-gate 
3008*7c478bd9Sstevel@tonic-gate static int
3009*7c478bd9Sstevel@tonic-gate fem_remove_node(struct fem_head *fh, void **baseops, void *opset, void *datap)
3010*7c478bd9Sstevel@tonic-gate {
3011*7c478bd9Sstevel@tonic-gate 	struct fem_list *sp;
3012*7c478bd9Sstevel@tonic-gate 	int		error;
3013*7c478bd9Sstevel@tonic-gate 	int		retry;
3014*7c478bd9Sstevel@tonic-gate 
3015*7c478bd9Sstevel@tonic-gate 	if (fh == NULL) {
3016*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
3017*7c478bd9Sstevel@tonic-gate 	}
3018*7c478bd9Sstevel@tonic-gate 
3019*7c478bd9Sstevel@tonic-gate 	do {
3020*7c478bd9Sstevel@tonic-gate 		retry = 0;
3021*7c478bd9Sstevel@tonic-gate 		if ((sp = fem_lock(fh)) == NULL) {
3022*7c478bd9Sstevel@tonic-gate 			fem_unlock(fh);
3023*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
3024*7c478bd9Sstevel@tonic-gate 		} else if (sp->feml_refc == 1) {
3025*7c478bd9Sstevel@tonic-gate 			error = remove_node(sp, baseops, opset, datap);
3026*7c478bd9Sstevel@tonic-gate 			if (sp->feml_tos == 1) {
3027*7c478bd9Sstevel@tonic-gate 				/*
3028*7c478bd9Sstevel@tonic-gate 				 * The top-of-stack was decremented by
3029*7c478bd9Sstevel@tonic-gate 				 * remove_node().  If it got down to 1,
3030*7c478bd9Sstevel@tonic-gate 				 * then the base ops were replaced and we
3031*7c478bd9Sstevel@tonic-gate 				 * call fem_release() which will free the
3032*7c478bd9Sstevel@tonic-gate 				 * fem_list.
3033*7c478bd9Sstevel@tonic-gate 				 */
3034*7c478bd9Sstevel@tonic-gate 				fem_release(sp);
3035*7c478bd9Sstevel@tonic-gate 				fh->femh_list = NULL;
3036*7c478bd9Sstevel@tonic-gate 				/* XXX - Do we need a membar_producer() call? */
3037*7c478bd9Sstevel@tonic-gate 			}
3038*7c478bd9Sstevel@tonic-gate 			fem_unlock(fh);
3039*7c478bd9Sstevel@tonic-gate 		} else {
3040*7c478bd9Sstevel@tonic-gate 			/* busy - install a new one without this monitor */
3041*7c478bd9Sstevel@tonic-gate 			struct fem_list *nsp;	/* New fem_list being cloned */
3042*7c478bd9Sstevel@tonic-gate 
3043*7c478bd9Sstevel@tonic-gate 			fem_addref(sp);
3044*7c478bd9Sstevel@tonic-gate 			fem_unlock(fh);
3045*7c478bd9Sstevel@tonic-gate 			nsp = femlist_create(sp->feml_ssize);
3046*7c478bd9Sstevel@tonic-gate 			if (fem_lock(fh) == sp) {
3047*7c478bd9Sstevel@tonic-gate 				/*
3048*7c478bd9Sstevel@tonic-gate 				 * We popped out of the lock, created a
3049*7c478bd9Sstevel@tonic-gate 				 * list, then relocked.  If we're in here
3050*7c478bd9Sstevel@tonic-gate 				 * then the fem_head points to the same list
3051*7c478bd9Sstevel@tonic-gate 				 * it started with.
3052*7c478bd9Sstevel@tonic-gate 				 */
3053*7c478bd9Sstevel@tonic-gate 				fem_dup_list(sp, nsp);
3054*7c478bd9Sstevel@tonic-gate 				error = remove_node(nsp, baseops, opset, datap);
3055*7c478bd9Sstevel@tonic-gate 				if (error != 0) {
3056*7c478bd9Sstevel@tonic-gate 					fem_release(nsp);
3057*7c478bd9Sstevel@tonic-gate 				} else if (nsp->feml_tos == 1) {
3058*7c478bd9Sstevel@tonic-gate 					/* New list now empty, tear it down */
3059*7c478bd9Sstevel@tonic-gate 					fem_release(nsp);
3060*7c478bd9Sstevel@tonic-gate 					fh->femh_list = NULL;
3061*7c478bd9Sstevel@tonic-gate 				} else {
3062*7c478bd9Sstevel@tonic-gate 					fh->femh_list = nsp;
3063*7c478bd9Sstevel@tonic-gate 				}
3064*7c478bd9Sstevel@tonic-gate 				fem_delref(sp);
3065*7c478bd9Sstevel@tonic-gate 			} else {
3066*7c478bd9Sstevel@tonic-gate 				/* List changed while locked, try again... */
3067*7c478bd9Sstevel@tonic-gate 				fem_release(nsp);
3068*7c478bd9Sstevel@tonic-gate 				retry = 1;
3069*7c478bd9Sstevel@tonic-gate 			}
3070*7c478bd9Sstevel@tonic-gate 			fem_release(sp);
3071*7c478bd9Sstevel@tonic-gate 			fem_unlock(fh);
3072*7c478bd9Sstevel@tonic-gate 		}
3073*7c478bd9Sstevel@tonic-gate 	} while (retry);
3074*7c478bd9Sstevel@tonic-gate 	return (error);
3075*7c478bd9Sstevel@tonic-gate }
3076*7c478bd9Sstevel@tonic-gate 
3077*7c478bd9Sstevel@tonic-gate 
3078*7c478bd9Sstevel@tonic-gate /*
3079*7c478bd9Sstevel@tonic-gate  * perform operation on each element until one returns non zero
3080*7c478bd9Sstevel@tonic-gate  */
3081*7c478bd9Sstevel@tonic-gate static int
3082*7c478bd9Sstevel@tonic-gate fem_walk_list(
3083*7c478bd9Sstevel@tonic-gate 	struct fem_list *sp,
3084*7c478bd9Sstevel@tonic-gate 	int (*f)(struct fem_node *, void *, void *),
3085*7c478bd9Sstevel@tonic-gate 	void *mon,
3086*7c478bd9Sstevel@tonic-gate 	void *arg)
3087*7c478bd9Sstevel@tonic-gate {
3088*7c478bd9Sstevel@tonic-gate 	int	i;
3089*7c478bd9Sstevel@tonic-gate 
3090*7c478bd9Sstevel@tonic-gate 	ASSERT(sp != NULL);
3091*7c478bd9Sstevel@tonic-gate 	for (i = sp->feml_tos; i > 0; i--) {
3092*7c478bd9Sstevel@tonic-gate 		if ((*f)(sp->feml_nodes+i, mon, arg) != 0) {
3093*7c478bd9Sstevel@tonic-gate 			break;
3094*7c478bd9Sstevel@tonic-gate 		}
3095*7c478bd9Sstevel@tonic-gate 	}
3096*7c478bd9Sstevel@tonic-gate 	return (i);
3097*7c478bd9Sstevel@tonic-gate }
3098*7c478bd9Sstevel@tonic-gate 
3099*7c478bd9Sstevel@tonic-gate /*
3100*7c478bd9Sstevel@tonic-gate  * companion comparison functions.
3101*7c478bd9Sstevel@tonic-gate  */
3102*7c478bd9Sstevel@tonic-gate static int
3103*7c478bd9Sstevel@tonic-gate fem_compare_mon(struct fem_node *n, void *mon, void *arg)
3104*7c478bd9Sstevel@tonic-gate {
3105*7c478bd9Sstevel@tonic-gate 	return ((n->fn_op.anon == mon) && (n->fn_available == arg));
3106*7c478bd9Sstevel@tonic-gate }
3107*7c478bd9Sstevel@tonic-gate 
3108*7c478bd9Sstevel@tonic-gate /*
3109*7c478bd9Sstevel@tonic-gate  * VNODE interposition.
3110*7c478bd9Sstevel@tonic-gate  */
3111*7c478bd9Sstevel@tonic-gate 
3112*7c478bd9Sstevel@tonic-gate int
3113*7c478bd9Sstevel@tonic-gate fem_create(char *name, const struct fs_operation_def *templ,
3114*7c478bd9Sstevel@tonic-gate     fem_t **actual)
3115*7c478bd9Sstevel@tonic-gate {
3116*7c478bd9Sstevel@tonic-gate 	int	unused_ops = 0;
3117*7c478bd9Sstevel@tonic-gate 	int	e;
3118*7c478bd9Sstevel@tonic-gate 	fem_t	*newf;
3119*7c478bd9Sstevel@tonic-gate 
3120*7c478bd9Sstevel@tonic-gate 	newf = fem_alloc();
3121*7c478bd9Sstevel@tonic-gate 	newf->name = name;
3122*7c478bd9Sstevel@tonic-gate 	newf->templ = templ;
3123*7c478bd9Sstevel@tonic-gate 
3124*7c478bd9Sstevel@tonic-gate 	e =  fs_build_vector(newf, &unused_ops, fem_opdef, templ);
3125*7c478bd9Sstevel@tonic-gate 	if (e != 0) {
3126*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
3127*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "fem_create: error %d building vector", e);
3128*7c478bd9Sstevel@tonic-gate #endif
3129*7c478bd9Sstevel@tonic-gate 		fem_free(newf);
3130*7c478bd9Sstevel@tonic-gate 	} else {
3131*7c478bd9Sstevel@tonic-gate 		*actual = newf;
3132*7c478bd9Sstevel@tonic-gate 	}
3133*7c478bd9Sstevel@tonic-gate 	return (e);
3134*7c478bd9Sstevel@tonic-gate }
3135*7c478bd9Sstevel@tonic-gate 
3136*7c478bd9Sstevel@tonic-gate int
3137*7c478bd9Sstevel@tonic-gate fem_install(
3138*7c478bd9Sstevel@tonic-gate 	vnode_t *vp,		/* Vnode on which monitor is being installed */
3139*7c478bd9Sstevel@tonic-gate 	fem_t *mon,		/* Monitor operations being installed */
3140*7c478bd9Sstevel@tonic-gate 	void *arg,		/* Opaque data used by monitor */
3141*7c478bd9Sstevel@tonic-gate 	femhow_t how,		/* Installation control */
3142*7c478bd9Sstevel@tonic-gate 	void (*arg_hold)(void *),	/* Hold routine for "arg" */
3143*7c478bd9Sstevel@tonic-gate 	void (*arg_rele)(void *))	/* Release routine for "arg" */
3144*7c478bd9Sstevel@tonic-gate {
3145*7c478bd9Sstevel@tonic-gate 	int	error;
3146*7c478bd9Sstevel@tonic-gate 	struct fem_node	nnode;
3147*7c478bd9Sstevel@tonic-gate 
3148*7c478bd9Sstevel@tonic-gate 	nnode.fn_available = arg;
3149*7c478bd9Sstevel@tonic-gate 	nnode.fn_op.fem = mon;
3150*7c478bd9Sstevel@tonic-gate 	nnode.fn_av_hold = arg_hold;
3151*7c478bd9Sstevel@tonic-gate 	nnode.fn_av_rele = arg_rele;
3152*7c478bd9Sstevel@tonic-gate 	/*
3153*7c478bd9Sstevel@tonic-gate 	 * If we have a non-NULL hold function, do the hold right away.
3154*7c478bd9Sstevel@tonic-gate 	 * The release is done in remove_node().
3155*7c478bd9Sstevel@tonic-gate 	 */
3156*7c478bd9Sstevel@tonic-gate 	if (arg_hold)
3157*7c478bd9Sstevel@tonic-gate 		(*arg_hold)(arg);
3158*7c478bd9Sstevel@tonic-gate 
3159*7c478bd9Sstevel@tonic-gate 	error = fem_push_node(&vp->v_femhead, (void **)&vp->v_op, FEMTYPE_VNODE,
3160*7c478bd9Sstevel@tonic-gate 			&nnode, how);
3161*7c478bd9Sstevel@tonic-gate 
3162*7c478bd9Sstevel@tonic-gate 	/* If there was an error then the monitor wasn't pushed */
3163*7c478bd9Sstevel@tonic-gate 	if (error && arg_rele)
3164*7c478bd9Sstevel@tonic-gate 		(*arg_rele)(arg);
3165*7c478bd9Sstevel@tonic-gate 
3166*7c478bd9Sstevel@tonic-gate 	return (error);
3167*7c478bd9Sstevel@tonic-gate }
3168*7c478bd9Sstevel@tonic-gate 
3169*7c478bd9Sstevel@tonic-gate int
3170*7c478bd9Sstevel@tonic-gate fem_is_installed(vnode_t *v, fem_t *mon, void *arg)
3171*7c478bd9Sstevel@tonic-gate {
3172*7c478bd9Sstevel@tonic-gate 	int	e;
3173*7c478bd9Sstevel@tonic-gate 	struct fem_list	*fl;
3174*7c478bd9Sstevel@tonic-gate 
3175*7c478bd9Sstevel@tonic-gate 	fl = fem_get(v->v_femhead);
3176*7c478bd9Sstevel@tonic-gate 	if (fl != NULL) {
3177*7c478bd9Sstevel@tonic-gate 		e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
3178*7c478bd9Sstevel@tonic-gate 		fem_release(fl);
3179*7c478bd9Sstevel@tonic-gate 		return (e);
3180*7c478bd9Sstevel@tonic-gate 	}
3181*7c478bd9Sstevel@tonic-gate 	return (0);
3182*7c478bd9Sstevel@tonic-gate }
3183*7c478bd9Sstevel@tonic-gate 
3184*7c478bd9Sstevel@tonic-gate int
3185*7c478bd9Sstevel@tonic-gate fem_uninstall(vnode_t *v, fem_t *mon, void *arg)
3186*7c478bd9Sstevel@tonic-gate {
3187*7c478bd9Sstevel@tonic-gate 	int	e;
3188*7c478bd9Sstevel@tonic-gate 	e = fem_remove_node(v->v_femhead, (void **)&v->v_op,
3189*7c478bd9Sstevel@tonic-gate 			(void *)mon, arg);
3190*7c478bd9Sstevel@tonic-gate 	return (e);
3191*7c478bd9Sstevel@tonic-gate }
3192*7c478bd9Sstevel@tonic-gate 
3193*7c478bd9Sstevel@tonic-gate void
3194*7c478bd9Sstevel@tonic-gate fem_setvnops(vnode_t *v, vnodeops_t *newops)
3195*7c478bd9Sstevel@tonic-gate {
3196*7c478bd9Sstevel@tonic-gate 	vnodeops_t	*r;
3197*7c478bd9Sstevel@tonic-gate 
3198*7c478bd9Sstevel@tonic-gate 	ASSERT(v != NULL);
3199*7c478bd9Sstevel@tonic-gate 	ASSERT(newops != NULL);
3200*7c478bd9Sstevel@tonic-gate 
3201*7c478bd9Sstevel@tonic-gate 	do {
3202*7c478bd9Sstevel@tonic-gate 		r = v->v_op;
3203*7c478bd9Sstevel@tonic-gate 		membar_consumer();
3204*7c478bd9Sstevel@tonic-gate 		if (v->v_femhead != NULL) {
3205*7c478bd9Sstevel@tonic-gate 			struct fem_list	*fl;
3206*7c478bd9Sstevel@tonic-gate 			if ((fl = fem_lock(v->v_femhead)) != NULL) {
3207*7c478bd9Sstevel@tonic-gate 				fl->feml_nodes[1].fn_op.vnode = newops;
3208*7c478bd9Sstevel@tonic-gate 				fem_unlock(v->v_femhead);
3209*7c478bd9Sstevel@tonic-gate 				return;
3210*7c478bd9Sstevel@tonic-gate 			}
3211*7c478bd9Sstevel@tonic-gate 			fem_unlock(v->v_femhead);
3212*7c478bd9Sstevel@tonic-gate 		}
3213*7c478bd9Sstevel@tonic-gate 	} while (casptr(&v->v_op, r, newops) != r);
3214*7c478bd9Sstevel@tonic-gate }
3215*7c478bd9Sstevel@tonic-gate 
3216*7c478bd9Sstevel@tonic-gate vnodeops_t *
3217*7c478bd9Sstevel@tonic-gate fem_getvnops(vnode_t *v)
3218*7c478bd9Sstevel@tonic-gate {
3219*7c478bd9Sstevel@tonic-gate 	vnodeops_t	*r;
3220*7c478bd9Sstevel@tonic-gate 
3221*7c478bd9Sstevel@tonic-gate 	ASSERT(v != NULL);
3222*7c478bd9Sstevel@tonic-gate 
3223*7c478bd9Sstevel@tonic-gate 	r = v->v_op;
3224*7c478bd9Sstevel@tonic-gate 	membar_consumer();
3225*7c478bd9Sstevel@tonic-gate 	if (v->v_femhead != NULL) {
3226*7c478bd9Sstevel@tonic-gate 		struct fem_list	*fl;
3227*7c478bd9Sstevel@tonic-gate 		if ((fl = fem_lock(v->v_femhead)) != NULL) {
3228*7c478bd9Sstevel@tonic-gate 			r = fl->feml_nodes[1].fn_op.vnode;
3229*7c478bd9Sstevel@tonic-gate 		}
3230*7c478bd9Sstevel@tonic-gate 		fem_unlock(v->v_femhead);
3231*7c478bd9Sstevel@tonic-gate 	}
3232*7c478bd9Sstevel@tonic-gate 	return (r);
3233*7c478bd9Sstevel@tonic-gate }
3234*7c478bd9Sstevel@tonic-gate 
3235*7c478bd9Sstevel@tonic-gate 
3236*7c478bd9Sstevel@tonic-gate /*
3237*7c478bd9Sstevel@tonic-gate  * VFS interposition
3238*7c478bd9Sstevel@tonic-gate  */
3239*7c478bd9Sstevel@tonic-gate int
3240*7c478bd9Sstevel@tonic-gate fsem_create(char *name, const struct fs_operation_def *templ,
3241*7c478bd9Sstevel@tonic-gate     fsem_t **actual)
3242*7c478bd9Sstevel@tonic-gate {
3243*7c478bd9Sstevel@tonic-gate 	int	unused_ops = 0;
3244*7c478bd9Sstevel@tonic-gate 	int	e;
3245*7c478bd9Sstevel@tonic-gate 	fsem_t	*newv;
3246*7c478bd9Sstevel@tonic-gate 
3247*7c478bd9Sstevel@tonic-gate 	newv = fsem_alloc();
3248*7c478bd9Sstevel@tonic-gate 	newv->name = (const char *)name;
3249*7c478bd9Sstevel@tonic-gate 	newv->templ = templ;
3250*7c478bd9Sstevel@tonic-gate 
3251*7c478bd9Sstevel@tonic-gate 	e = fs_build_vector(newv, &unused_ops, fsem_opdef, templ);
3252*7c478bd9Sstevel@tonic-gate 	if (e != 0) {
3253*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
3254*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "fsem_create: error %d building vector", e);
3255*7c478bd9Sstevel@tonic-gate #endif
3256*7c478bd9Sstevel@tonic-gate 		fsem_free(newv);
3257*7c478bd9Sstevel@tonic-gate 	} else {
3258*7c478bd9Sstevel@tonic-gate 		*actual = newv;
3259*7c478bd9Sstevel@tonic-gate 	}
3260*7c478bd9Sstevel@tonic-gate 	return (e);
3261*7c478bd9Sstevel@tonic-gate }
3262*7c478bd9Sstevel@tonic-gate 
3263*7c478bd9Sstevel@tonic-gate /*
3264*7c478bd9Sstevel@tonic-gate  * These need to be re-written, but there should be more common bits.
3265*7c478bd9Sstevel@tonic-gate  */
3266*7c478bd9Sstevel@tonic-gate 
3267*7c478bd9Sstevel@tonic-gate int
3268*7c478bd9Sstevel@tonic-gate fsem_is_installed(struct vfs *v, fsem_t *mon, void *arg)
3269*7c478bd9Sstevel@tonic-gate {
3270*7c478bd9Sstevel@tonic-gate 	struct fem_list	*fl;
3271*7c478bd9Sstevel@tonic-gate 
3272*7c478bd9Sstevel@tonic-gate 	fl = fem_get(v->vfs_femhead);
3273*7c478bd9Sstevel@tonic-gate 	if (fl != NULL) {
3274*7c478bd9Sstevel@tonic-gate 		int	e;
3275*7c478bd9Sstevel@tonic-gate 		e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
3276*7c478bd9Sstevel@tonic-gate 		fem_release(fl);
3277*7c478bd9Sstevel@tonic-gate 		return (e);
3278*7c478bd9Sstevel@tonic-gate 	}
3279*7c478bd9Sstevel@tonic-gate 	return (0);
3280*7c478bd9Sstevel@tonic-gate }
3281*7c478bd9Sstevel@tonic-gate 
3282*7c478bd9Sstevel@tonic-gate int
3283*7c478bd9Sstevel@tonic-gate fsem_install(
3284*7c478bd9Sstevel@tonic-gate 	struct vfs *vfsp,	/* VFS on which monitor is being installed */
3285*7c478bd9Sstevel@tonic-gate 	fsem_t *mon,		/* Monitor operations being installed */
3286*7c478bd9Sstevel@tonic-gate 	void *arg,		/* Opaque data used by monitor */
3287*7c478bd9Sstevel@tonic-gate 	femhow_t how,		/* Installation control */
3288*7c478bd9Sstevel@tonic-gate 	void (*arg_hold)(void *),	/* Hold routine for "arg" */
3289*7c478bd9Sstevel@tonic-gate 	void (*arg_rele)(void *))	/* Release routine for "arg" */
3290*7c478bd9Sstevel@tonic-gate {
3291*7c478bd9Sstevel@tonic-gate 	int	error;
3292*7c478bd9Sstevel@tonic-gate 	struct fem_node	nnode;
3293*7c478bd9Sstevel@tonic-gate 
3294*7c478bd9Sstevel@tonic-gate 	nnode.fn_available = arg;
3295*7c478bd9Sstevel@tonic-gate 	nnode.fn_op.fsem = mon;
3296*7c478bd9Sstevel@tonic-gate 	nnode.fn_av_hold = arg_hold;
3297*7c478bd9Sstevel@tonic-gate 	nnode.fn_av_rele = arg_rele;
3298*7c478bd9Sstevel@tonic-gate 	/*
3299*7c478bd9Sstevel@tonic-gate 	 * If we have a non-NULL hold function, do the hold right away.
3300*7c478bd9Sstevel@tonic-gate 	 * The release is done in remove_node().
3301*7c478bd9Sstevel@tonic-gate 	 */
3302*7c478bd9Sstevel@tonic-gate 	if (arg_hold)
3303*7c478bd9Sstevel@tonic-gate 		(*arg_hold)(arg);
3304*7c478bd9Sstevel@tonic-gate 
3305*7c478bd9Sstevel@tonic-gate 	error = fem_push_node(&vfsp->vfs_femhead, (void **)&vfsp->vfs_op,
3306*7c478bd9Sstevel@tonic-gate 			FEMTYPE_VFS, &nnode, how);
3307*7c478bd9Sstevel@tonic-gate 
3308*7c478bd9Sstevel@tonic-gate 	/* If there was an error then the monitor wasn't pushed */
3309*7c478bd9Sstevel@tonic-gate 	if (error && arg_rele)
3310*7c478bd9Sstevel@tonic-gate 		(*arg_rele)(arg);
3311*7c478bd9Sstevel@tonic-gate 
3312*7c478bd9Sstevel@tonic-gate 	return (error);
3313*7c478bd9Sstevel@tonic-gate }
3314*7c478bd9Sstevel@tonic-gate 
3315*7c478bd9Sstevel@tonic-gate int
3316*7c478bd9Sstevel@tonic-gate fsem_uninstall(struct vfs *v, fsem_t *mon, void *arg)
3317*7c478bd9Sstevel@tonic-gate {
3318*7c478bd9Sstevel@tonic-gate 	int	e;
3319*7c478bd9Sstevel@tonic-gate 	e = fem_remove_node(v->vfs_femhead, (void **)&v->vfs_op,
3320*7c478bd9Sstevel@tonic-gate 			(void *)mon, arg);
3321*7c478bd9Sstevel@tonic-gate 	return (e);
3322*7c478bd9Sstevel@tonic-gate }
3323*7c478bd9Sstevel@tonic-gate 
3324*7c478bd9Sstevel@tonic-gate void
3325*7c478bd9Sstevel@tonic-gate fsem_setvfsops(vfs_t *v, vfsops_t *newops)
3326*7c478bd9Sstevel@tonic-gate {
3327*7c478bd9Sstevel@tonic-gate 	vfsops_t	*r;
3328*7c478bd9Sstevel@tonic-gate 
3329*7c478bd9Sstevel@tonic-gate 	ASSERT(v != NULL);
3330*7c478bd9Sstevel@tonic-gate 	ASSERT(newops != NULL);
3331*7c478bd9Sstevel@tonic-gate 
3332*7c478bd9Sstevel@tonic-gate 	do {
3333*7c478bd9Sstevel@tonic-gate 		r = v->vfs_op;
3334*7c478bd9Sstevel@tonic-gate 		membar_consumer();
3335*7c478bd9Sstevel@tonic-gate 		if (v->vfs_femhead != NULL) {
3336*7c478bd9Sstevel@tonic-gate 			struct fem_list	*fl;
3337*7c478bd9Sstevel@tonic-gate 			if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
3338*7c478bd9Sstevel@tonic-gate 				fl->feml_nodes[1].fn_op.vfs = newops;
3339*7c478bd9Sstevel@tonic-gate 				fem_unlock(v->vfs_femhead);
3340*7c478bd9Sstevel@tonic-gate 				return;
3341*7c478bd9Sstevel@tonic-gate 			}
3342*7c478bd9Sstevel@tonic-gate 			fem_unlock(v->vfs_femhead);
3343*7c478bd9Sstevel@tonic-gate 		}
3344*7c478bd9Sstevel@tonic-gate 	} while (casptr(&v->vfs_op, r, newops) != r);
3345*7c478bd9Sstevel@tonic-gate }
3346*7c478bd9Sstevel@tonic-gate 
3347*7c478bd9Sstevel@tonic-gate vfsops_t *
3348*7c478bd9Sstevel@tonic-gate fsem_getvfsops(vfs_t *v)
3349*7c478bd9Sstevel@tonic-gate {
3350*7c478bd9Sstevel@tonic-gate 	vfsops_t	*r;
3351*7c478bd9Sstevel@tonic-gate 
3352*7c478bd9Sstevel@tonic-gate 	ASSERT(v != NULL);
3353*7c478bd9Sstevel@tonic-gate 
3354*7c478bd9Sstevel@tonic-gate 	r = v->vfs_op;
3355*7c478bd9Sstevel@tonic-gate 	membar_consumer();
3356*7c478bd9Sstevel@tonic-gate 	if (v->vfs_femhead != NULL) {
3357*7c478bd9Sstevel@tonic-gate 		struct fem_list	*fl;
3358*7c478bd9Sstevel@tonic-gate 		if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
3359*7c478bd9Sstevel@tonic-gate 			r = fl->feml_nodes[1].fn_op.vfs;
3360*7c478bd9Sstevel@tonic-gate 		}
3361*7c478bd9Sstevel@tonic-gate 		fem_unlock(v->vfs_femhead);
3362*7c478bd9Sstevel@tonic-gate 	}
3363*7c478bd9Sstevel@tonic-gate 	return (r);
3364*7c478bd9Sstevel@tonic-gate }
3365*7c478bd9Sstevel@tonic-gate 
3366*7c478bd9Sstevel@tonic-gate /*
3367*7c478bd9Sstevel@tonic-gate  * Setup FEM.
3368*7c478bd9Sstevel@tonic-gate  */
3369*7c478bd9Sstevel@tonic-gate void
3370*7c478bd9Sstevel@tonic-gate fem_init()
3371*7c478bd9Sstevel@tonic-gate {
3372*7c478bd9Sstevel@tonic-gate 	struct fem_type_info   *fi;
3373*7c478bd9Sstevel@tonic-gate 
3374*7c478bd9Sstevel@tonic-gate 	/*
3375*7c478bd9Sstevel@tonic-gate 	 * This femtype is only used for fem_list creation so we only
3376*7c478bd9Sstevel@tonic-gate 	 * need the "guard" to be initialized so that feml_tos has
3377*7c478bd9Sstevel@tonic-gate 	 * some rudimentary meaning.  A fem_list must not be used until
3378*7c478bd9Sstevel@tonic-gate 	 * it has been initialized (either via femlist_construct() or
3379*7c478bd9Sstevel@tonic-gate 	 * fem_dup_list()).  Anything that tries to use this fem_list
3380*7c478bd9Sstevel@tonic-gate 	 * before it's actually initialized would panic the system as
3381*7c478bd9Sstevel@tonic-gate 	 * soon as "fn_op" (NULL) is dereferenced.
3382*7c478bd9Sstevel@tonic-gate 	 */
3383*7c478bd9Sstevel@tonic-gate 	fi = femtype + FEMTYPE_NULL;
3384*7c478bd9Sstevel@tonic-gate 	fi->errf = fem_err;
3385*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_available = (void *)&fi->guard;
3386*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_hold = NULL;
3387*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_rele = NULL;
3388*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_op.anon = NULL;
3389*7c478bd9Sstevel@tonic-gate 
3390*7c478bd9Sstevel@tonic-gate 	fi = femtype + FEMTYPE_VNODE;
3391*7c478bd9Sstevel@tonic-gate 	fi->errf = fem_err;
3392*7c478bd9Sstevel@tonic-gate 	fi->head.fn_available = NULL;
3393*7c478bd9Sstevel@tonic-gate 	fi->head.fn_av_hold = NULL;
3394*7c478bd9Sstevel@tonic-gate 	fi->head.fn_av_rele = NULL;
3395*7c478bd9Sstevel@tonic-gate 	(void) vn_make_ops("fem-head", fhead_vn_spec, &fi->head.fn_op.vnode);
3396*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_available = (void *)&fi->guard;
3397*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_hold = NULL;
3398*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_rele = NULL;
3399*7c478bd9Sstevel@tonic-gate 	(void) fem_create("fem-guard", fem_guard_ops, &fi->guard.fn_op.fem);
3400*7c478bd9Sstevel@tonic-gate 
3401*7c478bd9Sstevel@tonic-gate 	fi = femtype + FEMTYPE_VFS;
3402*7c478bd9Sstevel@tonic-gate 	fi->errf = fsem_err;
3403*7c478bd9Sstevel@tonic-gate 	fi->head.fn_available = NULL;
3404*7c478bd9Sstevel@tonic-gate 	fi->head.fn_av_hold = NULL;
3405*7c478bd9Sstevel@tonic-gate 	fi->head.fn_av_rele = NULL;
3406*7c478bd9Sstevel@tonic-gate 	(void) vfs_makefsops(fshead_vfs_spec, &fi->head.fn_op.vfs);
3407*7c478bd9Sstevel@tonic-gate 
3408*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_available = (void *)&fi->guard;
3409*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_hold = NULL;
3410*7c478bd9Sstevel@tonic-gate 	fi->guard.fn_av_rele = NULL;
3411*7c478bd9Sstevel@tonic-gate 	(void) fsem_create("fem-guard", fsem_guard_ops, &fi->guard.fn_op.fsem);
3412*7c478bd9Sstevel@tonic-gate }
3413*7c478bd9Sstevel@tonic-gate 
3414*7c478bd9Sstevel@tonic-gate 
3415*7c478bd9Sstevel@tonic-gate int
3416*7c478bd9Sstevel@tonic-gate fem_err()
3417*7c478bd9Sstevel@tonic-gate {
3418*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_PANIC, "fem/vnode operations corrupt");
3419*7c478bd9Sstevel@tonic-gate 	return (0);
3420*7c478bd9Sstevel@tonic-gate }
3421*7c478bd9Sstevel@tonic-gate 
3422*7c478bd9Sstevel@tonic-gate int
3423*7c478bd9Sstevel@tonic-gate fsem_err()
3424*7c478bd9Sstevel@tonic-gate {
3425*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_PANIC, "fem/vfs operations corrupt");
3426*7c478bd9Sstevel@tonic-gate 	return (0);
3427*7c478bd9Sstevel@tonic-gate }
3428