xref: /illumos-gate/usr/src/uts/common/fs/fem.c (revision c6f039c7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/atomic.h>
28 #include <sys/kmem.h>
29 #include <sys/mutex.h>
30 #include <sys/errno.h>
31 #include <sys/param.h>
32 #include <sys/sysmacros.h>
33 #include <sys/systm.h>
34 #include <sys/cmn_err.h>
35 #include <sys/debug.h>
36 
37 #include <sys/fem.h>
38 #include <sys/vfs.h>
39 #include <sys/vnode.h>
40 #include <sys/vfs_opreg.h>
41 
42 #define	NNODES_DEFAULT	8	/* Default number of nodes in a fem_list */
43 /*
44  * fl_ntob(n) - Fem_list: number of nodes to bytes
45  * Given the number of nodes in a fem_list return the size, in bytes,
46  * of the fem_list structure.
47  */
48 #define	fl_ntob(n)	(sizeof (struct fem_list) + \
49 			((n) - 1) * sizeof (struct fem_node))
50 
51 typedef enum {
52 	FEMTYPE_NULL,	/* Uninitialized */
53 	FEMTYPE_VNODE,
54 	FEMTYPE_VFS,
55 	FEMTYPE_NTYPES
56 } femtype_t;
57 
58 #define	FEM_HEAD(_t) femtype[(_t)].head.fn_op.anon
59 #define	FEM_GUARD(_t) femtype[(_t)].guard
60 
61 static struct fem_type_info {
62 	struct fem_node		head;
63 	struct fem_node		guard;
64 	femop_t			*errf;
65 }	femtype[FEMTYPE_NTYPES];
66 
67 
68 /*
69  * For each type, two tables - the translation offset definition, which
70  * is used by fs_build_vector to layout the operation(s) vector; and the
71  * guard_operation_vector which protects from stack under-run.
72  */
73 
74 int fem_err();
75 int fsem_err();
76 
77 
78 #define	_FEMOPDEF(name, member)  \
79 	{ VOPNAME_##name, offsetof(fem_t, femop_##member), NULL, fem_err }
80 
81 static fs_operation_trans_def_t	fem_opdef[] = {
82 	_FEMOPDEF(OPEN,		open),
83 	_FEMOPDEF(CLOSE,	close),
84 	_FEMOPDEF(READ,		read),
85 	_FEMOPDEF(WRITE,	write),
86 	_FEMOPDEF(IOCTL,	ioctl),
87 	_FEMOPDEF(SETFL,	setfl),
88 	_FEMOPDEF(GETATTR,	getattr),
89 	_FEMOPDEF(SETATTR,	setattr),
90 	_FEMOPDEF(ACCESS,	access),
91 	_FEMOPDEF(LOOKUP,	lookup),
92 	_FEMOPDEF(CREATE,	create),
93 	_FEMOPDEF(REMOVE,	remove),
94 	_FEMOPDEF(LINK,		link),
95 	_FEMOPDEF(RENAME,	rename),
96 	_FEMOPDEF(MKDIR,	mkdir),
97 	_FEMOPDEF(RMDIR,	rmdir),
98 	_FEMOPDEF(READDIR,	readdir),
99 	_FEMOPDEF(SYMLINK,	symlink),
100 	_FEMOPDEF(READLINK,	readlink),
101 	_FEMOPDEF(FSYNC,	fsync),
102 	_FEMOPDEF(INACTIVE,	inactive),
103 	_FEMOPDEF(FID,		fid),
104 	_FEMOPDEF(RWLOCK,	rwlock),
105 	_FEMOPDEF(RWUNLOCK,	rwunlock),
106 	_FEMOPDEF(SEEK,		seek),
107 	_FEMOPDEF(CMP,		cmp),
108 	_FEMOPDEF(FRLOCK,	frlock),
109 	_FEMOPDEF(SPACE,	space),
110 	_FEMOPDEF(REALVP,	realvp),
111 	_FEMOPDEF(GETPAGE,	getpage),
112 	_FEMOPDEF(PUTPAGE,	putpage),
113 	_FEMOPDEF(MAP,		map),
114 	_FEMOPDEF(ADDMAP,	addmap),
115 	_FEMOPDEF(DELMAP,	delmap),
116 	_FEMOPDEF(POLL,		poll),
117 	_FEMOPDEF(DUMP,		dump),
118 	_FEMOPDEF(PATHCONF,	pathconf),
119 	_FEMOPDEF(PAGEIO,	pageio),
120 	_FEMOPDEF(DUMPCTL,	dumpctl),
121 	_FEMOPDEF(DISPOSE,	dispose),
122 	_FEMOPDEF(SETSECATTR,	setsecattr),
123 	_FEMOPDEF(GETSECATTR,	getsecattr),
124 	_FEMOPDEF(SHRLOCK,	shrlock),
125 	_FEMOPDEF(VNEVENT,	vnevent),
126 	_FEMOPDEF(REQZCBUF,	reqzcbuf),
127 	_FEMOPDEF(RETZCBUF,	retzcbuf),
128 	{ NULL, 0, NULL, NULL }
129 };
130 
131 
132 #define	_FEMGUARD(name, ignore)  \
133 	{ VOPNAME_##name, (femop_t *)fem_err }
134 
135 static struct fs_operation_def fem_guard_ops[] = {
136 	_FEMGUARD(OPEN,		open),
137 	_FEMGUARD(CLOSE,	close),
138 	_FEMGUARD(READ,		read),
139 	_FEMGUARD(WRITE,	write),
140 	_FEMGUARD(IOCTL,	ioctl),
141 	_FEMGUARD(SETFL,	setfl),
142 	_FEMGUARD(GETATTR,	getattr),
143 	_FEMGUARD(SETATTR,	setattr),
144 	_FEMGUARD(ACCESS,	access),
145 	_FEMGUARD(LOOKUP,	lookup),
146 	_FEMGUARD(CREATE,	create),
147 	_FEMGUARD(REMOVE,	remove),
148 	_FEMGUARD(LINK,		link),
149 	_FEMGUARD(RENAME,	rename),
150 	_FEMGUARD(MKDIR,	mkdir),
151 	_FEMGUARD(RMDIR,	rmdir),
152 	_FEMGUARD(READDIR,	readdir),
153 	_FEMGUARD(SYMLINK,	symlink),
154 	_FEMGUARD(READLINK,	readlink),
155 	_FEMGUARD(FSYNC,	fsync),
156 	_FEMGUARD(INACTIVE,	inactive),
157 	_FEMGUARD(FID,		fid),
158 	_FEMGUARD(RWLOCK,	rwlock),
159 	_FEMGUARD(RWUNLOCK,	rwunlock),
160 	_FEMGUARD(SEEK,		seek),
161 	_FEMGUARD(CMP,		cmp),
162 	_FEMGUARD(FRLOCK,	frlock),
163 	_FEMGUARD(SPACE,	space),
164 	_FEMGUARD(REALVP,	realvp),
165 	_FEMGUARD(GETPAGE,	getpage),
166 	_FEMGUARD(PUTPAGE,	putpage),
167 	_FEMGUARD(MAP,		map),
168 	_FEMGUARD(ADDMAP,	addmap),
169 	_FEMGUARD(DELMAP,	delmap),
170 	_FEMGUARD(POLL,		poll),
171 	_FEMGUARD(DUMP,		dump),
172 	_FEMGUARD(PATHCONF,	pathconf),
173 	_FEMGUARD(PAGEIO,	pageio),
174 	_FEMGUARD(DUMPCTL,	dumpctl),
175 	_FEMGUARD(DISPOSE,	dispose),
176 	_FEMGUARD(SETSECATTR,	setsecattr),
177 	_FEMGUARD(GETSECATTR,	getsecattr),
178 	_FEMGUARD(SHRLOCK,	shrlock),
179 	_FEMGUARD(VNEVENT,	vnevent),
180 	_FEMGUARD(REQZCBUF,	reqzcbuf),
181 	_FEMGUARD(RETZCBUF,	retzcbuf),
182 	{ NULL, NULL }
183 };
184 
185 
186 #define	_FSEMOPDEF(name, member)  \
187 	{ VFSNAME_##name, offsetof(fsem_t, fsemop_##member), NULL, fsem_err }
188 
189 static fs_operation_trans_def_t fsem_opdef[] = {
190 	_FSEMOPDEF(MOUNT,	mount),
191 	_FSEMOPDEF(UNMOUNT,	unmount),
192 	_FSEMOPDEF(ROOT,	root),
193 	_FSEMOPDEF(STATVFS,	statvfs),
194 	_FSEMOPDEF(SYNC,	sync),
195 	_FSEMOPDEF(VGET,	vget),
196 	_FSEMOPDEF(MOUNTROOT,	mountroot),
197 	_FSEMOPDEF(FREEVFS,	freevfs),
198 	_FSEMOPDEF(VNSTATE,	vnstate),
199 	{ NULL, 0, NULL, NULL }
200 };
201 
202 #define	_FSEMGUARD(name, ignore)  \
203 	{ VFSNAME_##name, (femop_t *)fsem_err }
204 
205 static struct fs_operation_def fsem_guard_ops[] = {
206 	_FSEMGUARD(MOUNT,	mount),
207 	_FSEMGUARD(UNMOUNT,	unmount),
208 	_FSEMGUARD(ROOT,	root),
209 	_FSEMGUARD(STATVFS,	statvfs),
210 	_FSEMGUARD(SYNC,	sync),
211 	_FSEMGUARD(VGET,	vget),
212 	_FSEMGUARD(MOUNTROOT,	mountroot),
213 	_FSEMGUARD(FREEVFS,	freevfs),
214 	_FSEMGUARD(VNSTATE,	vnstate),
215 	{ NULL, NULL}
216 };
217 
218 
219 /*
220  * vsop_find, vfsop_find -
221  *
222  * These macros descend the stack until they find either a basic
223  * vnode/vfs operation [ indicated by a null fn_available ] or a
224  * stacked item where this method is non-null [_vsop].
225  *
226  * The DEBUG one is written with a single function which manually applies
227  * the structure offsets.  It can have additional debugging support.
228  */
229 
230 #ifndef DEBUG
231 
232 #define	vsop_find(ap, func, funct, arg0, _vop, _vsop) \
233 for (;;) { \
234 	if ((ap)->fa_fnode->fn_available == NULL) { \
235 		*(func) = (funct (*)())((ap)->fa_fnode->fn_op.vnode->_vop); \
236 		*(arg0) = (void *)(ap)->fa_vnode.vp; \
237 		break;	\
238 	} else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fem->_vsop))\
239 		    != NULL) { \
240 		*(arg0) = (void *) (ap); \
241 		break;	\
242 	} else { \
243 		(ap)->fa_fnode--; \
244 	} \
245 } \
246 
247 #define	vfsop_find(ap, func, funct, arg0, _vop, _vsop) \
248 for (;;) { \
249 	if ((ap)->fa_fnode->fn_available == NULL) { \
250 		*(func) = (funct (*)())((ap)->fa_fnode->fn_op.vfs->_vop); \
251 		*(arg0) = (void *)(ap)->fa_vnode.vp; \
252 		break; \
253 	} else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fsem->_vsop))\
254 		    != NULL) { \
255 		*(arg0) = (void *) (ap); \
256 		break; \
257 	} else { \
258 		(ap)->fa_fnode--; \
259 	} \
260 } \
261 
262 #else
263 
264 #define	vsop_find(ap, func, funct, arg0, _vop, _vsop) \
265 	*(arg0) = _op_find((ap), (void **)(func), \
266 			offsetof(vnodeops_t, _vop), offsetof(fem_t, _vsop))
267 
268 #define	vfsop_find(ap, func, funct, arg0, _fop, _fsop) \
269 	*(arg0) = _op_find((ap), (void **)(func), \
270 			offsetof(vfsops_t, _fop), offsetof(fsem_t, _fsop))
271 
272 static void *
_op_find(femarg_t * ap,void ** fp,int offs0,int offs1)273 _op_find(femarg_t *ap, void **fp, int offs0, int offs1)
274 {
275 	void *ptr;
276 	for (;;) {
277 		struct fem_node	*fnod = ap->fa_fnode;
278 		if (fnod->fn_available == NULL) {
279 			*fp = *(void **)((char *)fnod->fn_op.anon + offs0);
280 			ptr = (void *)(ap->fa_vnode.anon);
281 			break;
282 		} else if ((*fp = *(void **)((char *)fnod->fn_op.anon+offs1))
283 		    != NULL) {
284 			ptr = (void *)(ap);
285 			break;
286 		} else {
287 			ap->fa_fnode--;
288 		}
289 	}
290 	return (ptr);
291 }
292 #endif
293 
294 static fem_t *
fem_alloc()295 fem_alloc()
296 {
297 	fem_t	*p;
298 
299 	p = (fem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
300 	return (p);
301 }
302 
303 void
fem_free(fem_t * p)304 fem_free(fem_t *p)
305 {
306 	kmem_free(p, sizeof (*p));
307 }
308 
309 static fsem_t *
fsem_alloc()310 fsem_alloc()
311 {
312 	fsem_t	*p;
313 
314 	p = (fsem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
315 	return (p);
316 }
317 
318 void
fsem_free(fsem_t * p)319 fsem_free(fsem_t *p)
320 {
321 	kmem_free(p, sizeof (*p));
322 }
323 
324 
325 /*
326  * fem_get, fem_release - manage reference counts on the stack.
327  *
328  * The list of monitors can be updated while operations are in
329  * progress on the object.
330  *
331  * The reference count facilitates this by counting the number of
332  * current accessors, and deconstructing the list when it is exhausted.
333  *
334  * fem_lock() is required to:
335  *	look at femh_list
336  *	update what femh_list points to
337  *	update femh_list
338  *	increase femh_list->feml_refc.
339  *
340  * the feml_refc can decrement without holding the lock;
341  * when feml_refc becomes zero, the list is destroyed.
342  *
343  */
344 
345 static struct fem_list *
fem_lock(struct fem_head * fp)346 fem_lock(struct fem_head *fp)
347 {
348 	struct fem_list	*sp = NULL;
349 
350 	ASSERT(fp != NULL);
351 	mutex_enter(&fp->femh_lock);
352 	sp = fp->femh_list;
353 	return (sp);
354 }
355 
356 static void
fem_unlock(struct fem_head * fp)357 fem_unlock(struct fem_head *fp)
358 {
359 	ASSERT(fp != NULL);
360 	mutex_exit(&fp->femh_lock);
361 }
362 
363 /*
364  * Addref can only be called while its head->lock is held.
365  */
366 
367 static void
fem_addref(struct fem_list * sp)368 fem_addref(struct fem_list *sp)
369 {
370 	atomic_inc_32(&sp->feml_refc);
371 }
372 
373 static uint32_t
fem_delref(struct fem_list * sp)374 fem_delref(struct fem_list *sp)
375 {
376 	return (atomic_dec_32_nv(&sp->feml_refc));
377 }
378 
379 static struct fem_list *
fem_get(struct fem_head * fp)380 fem_get(struct fem_head *fp)
381 {
382 	struct fem_list *sp = NULL;
383 
384 	if (fp != NULL) {
385 		if ((sp = fem_lock(fp)) != NULL) {
386 			fem_addref(sp);
387 		}
388 		fem_unlock(fp);
389 	}
390 	return (sp);
391 }
392 
393 static void
fem_release(struct fem_list * sp)394 fem_release(struct fem_list *sp)
395 {
396 	int	i;
397 
398 	ASSERT(sp->feml_refc != 0);
399 	if (fem_delref(sp) == 0) {
400 		/*
401 		 * Before freeing the list, we need to release the
402 		 * caller-provided data.
403 		 */
404 		for (i = sp->feml_tos; i > 0; i--) {
405 			struct fem_node *fnp = &sp->feml_nodes[i];
406 
407 			if (fnp->fn_av_rele)
408 				(*(fnp->fn_av_rele))(fnp->fn_available);
409 		}
410 		kmem_free(sp, fl_ntob(sp->feml_ssize));
411 	}
412 }
413 
414 
415 /*
416  * These are the 'head' operations which perform the interposition.
417  *
418  * This set must be 1:1, onto with the (vnodeops, vfsos).
419  *
420  * If there is a desire to globally disable interposition for a particular
421  * method, the corresponding 'head' routine should unearth the base method
422  * and invoke it directly rather than bypassing the function.
423  *
424  * All the functions are virtually the same, save for names, types & args.
425  *  1. get a reference to the monitor stack for this object.
426  *  2. store the top of stack into the femarg structure.
427  *  3. store the basic object (vnode *, vnode **, vfs *) in the femarg struc.
428  *  4. invoke the "top" method for this object.
429  *  5. release the reference to the monitor stack.
430  *
431  */
432 
433 static int
vhead_open(vnode_t ** vpp,int mode,cred_t * cr,caller_context_t * ct)434 vhead_open(vnode_t **vpp, int mode, cred_t *cr, caller_context_t *ct)
435 {
436 	femarg_t	farg;
437 	struct fem_list	*femsp;
438 	int		(*func)();
439 	void		*arg0;
440 	int		errc;
441 
442 	if ((femsp = fem_lock((*vpp)->v_femhead)) == NULL) {
443 		func = (int (*)()) ((*vpp)->v_op->vop_open);
444 		arg0 = (void *)vpp;
445 		fem_unlock((*vpp)->v_femhead);
446 		errc = (*func)(arg0, mode, cr, ct);
447 	} else {
448 		fem_addref(femsp);
449 		fem_unlock((*vpp)->v_femhead);
450 		farg.fa_vnode.vpp = vpp;
451 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
452 		vsop_find(&farg, &func, int, &arg0, vop_open, femop_open);
453 		errc = (*func)(arg0, mode, cr, ct);
454 		fem_release(femsp);
455 	}
456 	return (errc);
457 }
458 
459 static int
vhead_close(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)460 vhead_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
461     caller_context_t *ct)
462 {
463 	femarg_t	farg;
464 	struct fem_list	*femsp;
465 	int		(*func)();
466 	void		*arg0;
467 	int		errc;
468 
469 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
470 		func = (int (*)()) (vp->v_op->vop_close);
471 		arg0 = vp;
472 		fem_unlock(vp->v_femhead);
473 		errc = (*func)(arg0, flag, count, offset, cr, ct);
474 	} else {
475 		fem_addref(femsp);
476 		fem_unlock(vp->v_femhead);
477 		farg.fa_vnode.vp = vp;
478 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
479 		vsop_find(&farg, &func, int, &arg0, vop_close, femop_close);
480 		errc = (*func)(arg0, flag, count, offset, cr, ct);
481 		fem_release(femsp);
482 	}
483 	return (errc);
484 }
485 
486 static int
vhead_read(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)487 vhead_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
488     caller_context_t *ct)
489 {
490 	femarg_t	farg;
491 	struct fem_list	*femsp;
492 	int		(*func)();
493 	void		*arg0;
494 	int		errc;
495 
496 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
497 		func = (int (*)()) (vp->v_op->vop_read);
498 		arg0 = vp;
499 		fem_unlock(vp->v_femhead);
500 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
501 	} else {
502 		fem_addref(femsp);
503 		fem_unlock(vp->v_femhead);
504 		farg.fa_vnode.vp = vp;
505 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
506 		vsop_find(&farg, &func, int, &arg0, vop_read, femop_read);
507 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
508 		fem_release(femsp);
509 	}
510 	return (errc);
511 }
512 
513 static int
vhead_write(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)514 vhead_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
515     caller_context_t *ct)
516 {
517 	femarg_t	farg;
518 	struct fem_list	*femsp;
519 	int		(*func)();
520 	void		*arg0;
521 	int		errc;
522 
523 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
524 		func = (int (*)()) (vp->v_op->vop_write);
525 		arg0 = vp;
526 		fem_unlock(vp->v_femhead);
527 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
528 	} else {
529 		fem_addref(femsp);
530 		fem_unlock(vp->v_femhead);
531 		farg.fa_vnode.vp = vp;
532 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
533 		vsop_find(&farg, &func, int, &arg0, vop_write, femop_write);
534 		errc = (*func)(arg0, uiop, ioflag, cr, ct);
535 		fem_release(femsp);
536 	}
537 	return (errc);
538 }
539 
540 static int
vhead_ioctl(vnode_t * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)541 vhead_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
542     int *rvalp, caller_context_t *ct)
543 {
544 	femarg_t	farg;
545 	struct fem_list	*femsp;
546 	int		(*func)();
547 	void		*arg0;
548 	int		errc;
549 
550 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
551 		func = (int (*)()) (vp->v_op->vop_ioctl);
552 		arg0 = vp;
553 		fem_unlock(vp->v_femhead);
554 		errc = (*func)(arg0, cmd, arg, flag, cr, rvalp, ct);
555 	} else {
556 		fem_addref(femsp);
557 		fem_unlock(vp->v_femhead);
558 		farg.fa_vnode.vp = vp;
559 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
560 		vsop_find(&farg, &func, int, &arg0, vop_ioctl, femop_ioctl);
561 		errc = (*func)(arg0, cmd, arg, flag, cr, rvalp, ct);
562 		fem_release(femsp);
563 	}
564 	return (errc);
565 }
566 
567 static int
vhead_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)568 vhead_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr,
569     caller_context_t *ct)
570 {
571 	femarg_t	farg;
572 	struct fem_list	*femsp;
573 	int		(*func)();
574 	void		*arg0;
575 	int		errc;
576 
577 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
578 		func = (int (*)()) (vp->v_op->vop_setfl);
579 		arg0 = vp;
580 		fem_unlock(vp->v_femhead);
581 		errc = (*func)(arg0, oflags, nflags, cr, ct);
582 	} else {
583 		fem_addref(femsp);
584 		fem_unlock(vp->v_femhead);
585 		farg.fa_vnode.vp = vp;
586 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
587 		vsop_find(&farg, &func, int, &arg0, vop_setfl, femop_setfl);
588 		errc = (*func)(arg0, oflags, nflags, cr, ct);
589 		fem_release(femsp);
590 	}
591 	return (errc);
592 }
593 
594 static int
vhead_getattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)595 vhead_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
596     caller_context_t *ct)
597 {
598 	femarg_t	farg;
599 	struct fem_list	*femsp;
600 	int		(*func)();
601 	void		*arg0;
602 	int		errc;
603 
604 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
605 		func = (int (*)()) (vp->v_op->vop_getattr);
606 		arg0 = vp;
607 		fem_unlock(vp->v_femhead);
608 		errc = (*func)(arg0, vap, flags, cr, ct);
609 	} else {
610 		fem_addref(femsp);
611 		fem_unlock(vp->v_femhead);
612 		farg.fa_vnode.vp = vp;
613 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
614 		vsop_find(&farg, &func, int, &arg0, vop_getattr,
615 		    femop_getattr);
616 		errc = (*func)(arg0, vap, flags, cr, ct);
617 		fem_release(femsp);
618 	}
619 	return (errc);
620 }
621 
622 static int
vhead_setattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)623 vhead_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
624     caller_context_t *ct)
625 {
626 	femarg_t	farg;
627 	struct fem_list	*femsp;
628 	int		(*func)();
629 	void		*arg0;
630 	int		errc;
631 
632 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
633 		func = (int (*)()) (vp->v_op->vop_setattr);
634 		arg0 = vp;
635 		fem_unlock(vp->v_femhead);
636 		errc = (*func)(arg0, vap, flags, cr, ct);
637 	} else {
638 		fem_addref(femsp);
639 		fem_unlock(vp->v_femhead);
640 		farg.fa_vnode.vp = vp;
641 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
642 		vsop_find(&farg, &func, int, &arg0, vop_setattr,
643 		    femop_setattr);
644 		errc = (*func)(arg0, vap, flags, cr, ct);
645 		fem_release(femsp);
646 	}
647 	return (errc);
648 }
649 
650 static int
vhead_access(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)651 vhead_access(vnode_t *vp, int mode, int flags, cred_t *cr,
652     caller_context_t *ct)
653 {
654 	femarg_t	farg;
655 	struct fem_list	*femsp;
656 	int		(*func)();
657 	void		*arg0;
658 	int		errc;
659 
660 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
661 		func = (int (*)()) (vp->v_op->vop_access);
662 		arg0 = vp;
663 		fem_unlock(vp->v_femhead);
664 		errc = (*func)(arg0, mode, flags, cr, ct);
665 	} else {
666 		fem_addref(femsp);
667 		fem_unlock(vp->v_femhead);
668 		farg.fa_vnode.vp = vp;
669 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
670 		vsop_find(&farg, &func, int, &arg0, vop_access,
671 		    femop_access);
672 		errc = (*func)(arg0, mode, flags, cr, ct);
673 		fem_release(femsp);
674 	}
675 	return (errc);
676 }
677 
678 static int
vhead_lookup(vnode_t * dvp,char * nm,vnode_t ** vpp,pathname_t * pnp,int flags,vnode_t * rdir,cred_t * cr,caller_context_t * ct,int * direntflags,pathname_t * realpnp)679 vhead_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
680     int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
681     int *direntflags, pathname_t *realpnp)
682 {
683 	femarg_t	farg;
684 	struct fem_list	*femsp;
685 	int		(*func)();
686 	void		*arg0;
687 	int		errc;
688 
689 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
690 		func = (int (*)()) (dvp->v_op->vop_lookup);
691 		arg0 = dvp;
692 		fem_unlock(dvp->v_femhead);
693 		errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
694 		    direntflags, realpnp);
695 	} else {
696 		fem_addref(femsp);
697 		fem_unlock(dvp->v_femhead);
698 		farg.fa_vnode.vp = dvp;
699 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
700 		vsop_find(&farg, &func, int, &arg0, vop_lookup,
701 		    femop_lookup);
702 		errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
703 		    direntflags, realpnp);
704 		fem_release(femsp);
705 	}
706 	return (errc);
707 }
708 
709 static int
vhead_create(vnode_t * dvp,char * name,vattr_t * vap,vcexcl_t excl,int mode,vnode_t ** vpp,cred_t * cr,int flag,caller_context_t * ct,vsecattr_t * vsecp)710 vhead_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl,
711     int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
712     vsecattr_t *vsecp)
713 {
714 	femarg_t	farg;
715 	struct fem_list	*femsp;
716 	int		(*func)();
717 	void		*arg0;
718 	int		errc;
719 
720 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
721 		func = (int (*)()) (dvp->v_op->vop_create);
722 		arg0 = dvp;
723 		fem_unlock(dvp->v_femhead);
724 		errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag,
725 		    ct, vsecp);
726 	} else {
727 		fem_addref(femsp);
728 		fem_unlock(dvp->v_femhead);
729 		farg.fa_vnode.vp = dvp;
730 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
731 		vsop_find(&farg, &func, int, &arg0, vop_create,
732 		    femop_create);
733 		errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag,
734 		    ct, vsecp);
735 		fem_release(femsp);
736 	}
737 	return (errc);
738 }
739 
740 static int
vhead_remove(vnode_t * dvp,char * nm,cred_t * cr,caller_context_t * ct,int flags)741 vhead_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
742     int flags)
743 {
744 	femarg_t	farg;
745 	struct fem_list	*femsp;
746 	int		(*func)();
747 	void		*arg0;
748 	int		errc;
749 
750 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
751 		func = (int (*)()) (dvp->v_op->vop_remove);
752 		arg0 = dvp;
753 		fem_unlock(dvp->v_femhead);
754 		errc = (*func)(arg0, nm, cr, ct, flags);
755 	} else {
756 		fem_addref(femsp);
757 		fem_unlock(dvp->v_femhead);
758 		farg.fa_vnode.vp = dvp;
759 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
760 		vsop_find(&farg, &func, int, &arg0, vop_remove,
761 		    femop_remove);
762 		errc = (*func)(arg0, nm, cr, ct, flags);
763 		fem_release(femsp);
764 	}
765 	return (errc);
766 }
767 
768 static int
vhead_link(vnode_t * tdvp,vnode_t * svp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)769 vhead_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
770     caller_context_t *ct, int flags)
771 {
772 	femarg_t	farg;
773 	struct fem_list	*femsp;
774 	int		(*func)();
775 	void		*arg0;
776 	int		errc;
777 
778 	if ((femsp = fem_lock(tdvp->v_femhead)) == NULL) {
779 		func = (int (*)()) (tdvp->v_op->vop_link);
780 		arg0 = tdvp;
781 		fem_unlock(tdvp->v_femhead);
782 		errc = (*func)(arg0, svp, tnm, cr, ct, flags);
783 	} else {
784 		fem_addref(femsp);
785 		fem_unlock(tdvp->v_femhead);
786 		farg.fa_vnode.vp = tdvp;
787 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
788 		vsop_find(&farg, &func, int, &arg0, vop_link, femop_link);
789 		errc = (*func)(arg0, svp, tnm, cr, ct, flags);
790 		fem_release(femsp);
791 	}
792 	return (errc);
793 }
794 
795 static int
vhead_rename(vnode_t * sdvp,char * snm,vnode_t * tdvp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)796 vhead_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
797     cred_t *cr, caller_context_t *ct, int flags)
798 {
799 	femarg_t	farg;
800 	struct fem_list	*femsp;
801 	int		(*func)();
802 	void		*arg0;
803 	int		errc;
804 
805 	if ((femsp = fem_lock(sdvp->v_femhead)) == NULL) {
806 		func = (int (*)()) (sdvp->v_op->vop_rename);
807 		arg0 = sdvp;
808 		fem_unlock(sdvp->v_femhead);
809 		errc = (*func)(arg0, snm, tdvp, tnm, cr, ct, flags);
810 	} else {
811 		fem_addref(femsp);
812 		fem_unlock(sdvp->v_femhead);
813 		farg.fa_vnode.vp = sdvp;
814 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
815 		vsop_find(&farg, &func, int, &arg0, vop_rename,
816 		    femop_rename);
817 		errc = (*func)(arg0, snm, tdvp, tnm, cr, ct, flags);
818 		fem_release(femsp);
819 	}
820 	return (errc);
821 }
822 
823 static int
vhead_mkdir(vnode_t * dvp,char * dirname,vattr_t * vap,vnode_t ** vpp,cred_t * cr,caller_context_t * ct,int flags,vsecattr_t * vsecp)824 vhead_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp,
825     cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
826 {
827 	femarg_t	farg;
828 	struct fem_list	*femsp;
829 	int		(*func)();
830 	void		*arg0;
831 	int		errc;
832 
833 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
834 		func = (int (*)()) (dvp->v_op->vop_mkdir);
835 		arg0 = dvp;
836 		fem_unlock(dvp->v_femhead);
837 		errc = (*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp);
838 	} else {
839 		fem_addref(femsp);
840 		fem_unlock(dvp->v_femhead);
841 		farg.fa_vnode.vp = dvp;
842 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
843 		vsop_find(&farg, &func, int, &arg0, vop_mkdir, femop_mkdir);
844 		errc = (*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp);
845 		fem_release(femsp);
846 	}
847 	return (errc);
848 }
849 
850 static int
vhead_rmdir(vnode_t * dvp,char * nm,vnode_t * cdir,cred_t * cr,caller_context_t * ct,int flags)851 vhead_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
852     caller_context_t *ct, int flags)
853 {
854 	femarg_t	farg;
855 	struct fem_list	*femsp;
856 	int		(*func)();
857 	void		*arg0;
858 	int		errc;
859 
860 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
861 		func = (int (*)()) (dvp->v_op->vop_rmdir);
862 		arg0 = dvp;
863 		fem_unlock(dvp->v_femhead);
864 		errc = (*func)(arg0, nm, cdir, cr, ct, flags);
865 	} else {
866 		fem_addref(femsp);
867 		fem_unlock(dvp->v_femhead);
868 		farg.fa_vnode.vp = dvp;
869 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
870 		vsop_find(&farg, &func, int, &arg0, vop_rmdir, femop_rmdir);
871 		errc = (*func)(arg0, nm, cdir, cr, ct, flags);
872 		fem_release(femsp);
873 	}
874 	return (errc);
875 }
876 
877 static int
vhead_readdir(vnode_t * vp,uio_t * uiop,cred_t * cr,int * eofp,caller_context_t * ct,int flags)878 vhead_readdir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
879     caller_context_t *ct, int flags)
880 {
881 	femarg_t	farg;
882 	struct fem_list	*femsp;
883 	int		(*func)();
884 	void		*arg0;
885 	int		errc;
886 
887 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
888 		func = (int (*)()) (vp->v_op->vop_readdir);
889 		arg0 = vp;
890 		fem_unlock(vp->v_femhead);
891 		errc = (*func)(arg0, uiop, cr, eofp, ct, flags);
892 	} else {
893 		fem_addref(femsp);
894 		fem_unlock(vp->v_femhead);
895 		farg.fa_vnode.vp = vp;
896 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
897 		vsop_find(&farg, &func, int, &arg0, vop_readdir,
898 		    femop_readdir);
899 		errc = (*func)(arg0, uiop, cr, eofp, ct, flags);
900 		fem_release(femsp);
901 	}
902 	return (errc);
903 }
904 
905 static int
vhead_symlink(vnode_t * dvp,char * linkname,vattr_t * vap,char * target,cred_t * cr,caller_context_t * ct,int flags)906 vhead_symlink(vnode_t *dvp, char *linkname, vattr_t *vap, char *target,
907     cred_t *cr, caller_context_t *ct, int flags)
908 {
909 	femarg_t	farg;
910 	struct fem_list	*femsp;
911 	int		(*func)();
912 	void		*arg0;
913 	int		errc;
914 
915 	if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
916 		func = (int (*)()) (dvp->v_op->vop_symlink);
917 		arg0 = dvp;
918 		fem_unlock(dvp->v_femhead);
919 		errc = (*func)(arg0, linkname, vap, target, cr, ct, flags);
920 	} else {
921 		fem_addref(femsp);
922 		fem_unlock(dvp->v_femhead);
923 		farg.fa_vnode.vp = dvp;
924 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
925 		vsop_find(&farg, &func, int, &arg0, vop_symlink,
926 		    femop_symlink);
927 		errc = (*func)(arg0, linkname, vap, target, cr, ct, flags);
928 		fem_release(femsp);
929 	}
930 	return (errc);
931 }
932 
933 static int
vhead_readlink(vnode_t * vp,uio_t * uiop,cred_t * cr,caller_context_t * ct)934 vhead_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
935 {
936 	femarg_t	farg;
937 	struct fem_list	*femsp;
938 	int		(*func)();
939 	void		*arg0;
940 	int		errc;
941 
942 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
943 		func = (int (*)()) (vp->v_op->vop_readlink);
944 		arg0 = vp;
945 		fem_unlock(vp->v_femhead);
946 		errc = (*func)(arg0, uiop, cr, ct);
947 	} else {
948 		fem_addref(femsp);
949 		fem_unlock(vp->v_femhead);
950 		farg.fa_vnode.vp = vp;
951 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
952 		vsop_find(&farg, &func, int, &arg0, vop_readlink,
953 		    femop_readlink);
954 		errc = (*func)(arg0, uiop, cr, ct);
955 		fem_release(femsp);
956 	}
957 	return (errc);
958 }
959 
960 static int
vhead_fsync(vnode_t * vp,int syncflag,cred_t * cr,caller_context_t * ct)961 vhead_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
962 {
963 	femarg_t	farg;
964 	struct fem_list	*femsp;
965 	int		(*func)();
966 	void		*arg0;
967 	int		errc;
968 
969 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
970 		func = (int (*)()) (vp->v_op->vop_fsync);
971 		arg0 = vp;
972 		fem_unlock(vp->v_femhead);
973 		errc = (*func)(arg0, syncflag, cr, ct);
974 	} else {
975 		fem_addref(femsp);
976 		fem_unlock(vp->v_femhead);
977 		farg.fa_vnode.vp = vp;
978 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
979 		vsop_find(&farg, &func, int, &arg0, vop_fsync, femop_fsync);
980 		errc = (*func)(arg0, syncflag, cr, ct);
981 		fem_release(femsp);
982 	}
983 	return (errc);
984 }
985 
986 static int
vhead_inactive(vnode_t * vp,cred_t * cr,caller_context_t * ct)987 vhead_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
988 {
989 	femarg_t	farg;
990 	struct fem_list	*femsp;
991 	void		(*func)();
992 	void		*arg0;
993 
994 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
995 		func = (void (*)()) (vp->v_op->vop_inactive);
996 		arg0 = vp;
997 		fem_unlock(vp->v_femhead);
998 		(*func)(arg0, cr, ct);
999 	} else {
1000 		fem_addref(femsp);
1001 		fem_unlock(vp->v_femhead);
1002 		farg.fa_vnode.vp = vp;
1003 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1004 		vsop_find(&farg, &func, void, &arg0, vop_inactive,
1005 		    femop_inactive);
1006 		(*func)(arg0, cr, ct);
1007 		fem_release(femsp);
1008 	}
1009 	return (0);
1010 }
1011 
1012 static int
vhead_fid(vnode_t * vp,fid_t * fidp,caller_context_t * ct)1013 vhead_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
1014 {
1015 	femarg_t	farg;
1016 	struct fem_list	*femsp;
1017 	int		(*func)();
1018 	void		*arg0;
1019 	int		errc;
1020 
1021 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1022 		func = (int (*)()) (vp->v_op->vop_fid);
1023 		arg0 = vp;
1024 		fem_unlock(vp->v_femhead);
1025 		errc = (*func)(arg0, fidp, ct);
1026 	} else {
1027 		fem_addref(femsp);
1028 		fem_unlock(vp->v_femhead);
1029 		farg.fa_vnode.vp = vp;
1030 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1031 		vsop_find(&farg, &func, int, &arg0, vop_fid, femop_fid);
1032 		errc = (*func)(arg0, fidp, ct);
1033 		fem_release(femsp);
1034 	}
1035 	return (errc);
1036 }
1037 
1038 static int
vhead_rwlock(vnode_t * vp,int write_lock,caller_context_t * ct)1039 vhead_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1040 {
1041 	femarg_t	farg;
1042 	struct fem_list	*femsp;
1043 	int		(*func)();
1044 	void		*arg0;
1045 	int		errc;
1046 
1047 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1048 		func = (int (*)()) (vp->v_op->vop_rwlock);
1049 		arg0 = vp;
1050 		fem_unlock(vp->v_femhead);
1051 		errc = (*func)(arg0, write_lock, ct);
1052 	} else {
1053 		fem_addref(femsp);
1054 		fem_unlock(vp->v_femhead);
1055 		farg.fa_vnode.vp = vp;
1056 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1057 		vsop_find(&farg, &func, int, &arg0, vop_rwlock,
1058 		    femop_rwlock);
1059 		errc = (*func)(arg0, write_lock, ct);
1060 		fem_release(femsp);
1061 	}
1062 	return (errc);
1063 }
1064 
1065 static int
vhead_rwunlock(vnode_t * vp,int write_lock,caller_context_t * ct)1066 vhead_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1067 {
1068 	femarg_t	farg;
1069 	struct fem_list	*femsp;
1070 	void		(*func)();
1071 	void		*arg0;
1072 
1073 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1074 		func = (void (*)()) (vp->v_op->vop_rwunlock);
1075 		arg0 = vp;
1076 		fem_unlock(vp->v_femhead);
1077 		(*func)(arg0, write_lock, ct);
1078 	} else {
1079 		fem_addref(femsp);
1080 		fem_unlock(vp->v_femhead);
1081 		farg.fa_vnode.vp = vp;
1082 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1083 		vsop_find(&farg, &func, void, &arg0, vop_rwunlock,
1084 		    femop_rwunlock);
1085 		(*func)(arg0, write_lock, ct);
1086 		fem_release(femsp);
1087 	}
1088 	return (0);
1089 }
1090 
1091 static int
vhead_seek(vnode_t * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)1092 vhead_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
1093 {
1094 	femarg_t	farg;
1095 	struct fem_list	*femsp;
1096 	int		(*func)();
1097 	void		*arg0;
1098 	int		errc;
1099 
1100 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1101 		func = (int (*)()) (vp->v_op->vop_seek);
1102 		arg0 = vp;
1103 		fem_unlock(vp->v_femhead);
1104 		errc = (*func)(arg0, ooff, noffp, ct);
1105 	} else {
1106 		fem_addref(femsp);
1107 		fem_unlock(vp->v_femhead);
1108 		farg.fa_vnode.vp = vp;
1109 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1110 		vsop_find(&farg, &func, int, &arg0, vop_seek, femop_seek);
1111 		errc = (*func)(arg0, ooff, noffp, ct);
1112 		fem_release(femsp);
1113 	}
1114 	return (errc);
1115 }
1116 
1117 static int
vhead_cmp(vnode_t * vp1,vnode_t * vp2,caller_context_t * ct)1118 vhead_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
1119 {
1120 	femarg_t	farg;
1121 	struct fem_list	*femsp;
1122 	int		(*func)();
1123 	void		*arg0;
1124 	int		errc;
1125 
1126 	if ((femsp = fem_lock(vp1->v_femhead)) == NULL) {
1127 		func = (int (*)()) (vp1->v_op->vop_cmp);
1128 		arg0 = vp1;
1129 		fem_unlock(vp1->v_femhead);
1130 		errc = (*func)(arg0, vp2, ct);
1131 	} else {
1132 		fem_addref(femsp);
1133 		fem_unlock(vp1->v_femhead);
1134 		farg.fa_vnode.vp = vp1;
1135 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1136 		vsop_find(&farg, &func, int, &arg0, vop_cmp, femop_cmp);
1137 		errc = (*func)(arg0, vp2, ct);
1138 		fem_release(femsp);
1139 	}
1140 	return (errc);
1141 }
1142 
1143 static int
vhead_frlock(vnode_t * vp,int cmd,struct flock64 * bfp,int flag,offset_t offset,struct flk_callback * flk_cbp,cred_t * cr,caller_context_t * ct)1144 vhead_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1145     offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
1146     caller_context_t *ct)
1147 {
1148 	femarg_t	farg;
1149 	struct fem_list	*femsp;
1150 	int		(*func)();
1151 	void		*arg0;
1152 	int		errc;
1153 
1154 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1155 		func = (int (*)()) (vp->v_op->vop_frlock);
1156 		arg0 = vp;
1157 		fem_unlock(vp->v_femhead);
1158 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
1159 	} else {
1160 		fem_addref(femsp);
1161 		fem_unlock(vp->v_femhead);
1162 		farg.fa_vnode.vp = vp;
1163 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1164 		vsop_find(&farg, &func, int, &arg0, vop_frlock,
1165 		    femop_frlock);
1166 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
1167 		fem_release(femsp);
1168 	}
1169 	return (errc);
1170 }
1171 
1172 static int
vhead_space(vnode_t * vp,int cmd,struct flock64 * bfp,int flag,offset_t offset,cred_t * cr,caller_context_t * ct)1173 vhead_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1174     offset_t offset, cred_t *cr, caller_context_t *ct)
1175 {
1176 	femarg_t	farg;
1177 	struct fem_list	*femsp;
1178 	int		(*func)();
1179 	void		*arg0;
1180 	int		errc;
1181 
1182 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1183 		func = (int (*)()) (vp->v_op->vop_space);
1184 		arg0 = vp;
1185 		fem_unlock(vp->v_femhead);
1186 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1187 	} else {
1188 		fem_addref(femsp);
1189 		fem_unlock(vp->v_femhead);
1190 		farg.fa_vnode.vp = vp;
1191 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1192 		vsop_find(&farg, &func, int, &arg0, vop_space, femop_space);
1193 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1194 		fem_release(femsp);
1195 	}
1196 	return (errc);
1197 }
1198 
1199 static int
vhead_realvp(vnode_t * vp,vnode_t ** vpp,caller_context_t * ct)1200 vhead_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
1201 {
1202 	femarg_t	farg;
1203 	struct fem_list	*femsp;
1204 	int		(*func)();
1205 	void		*arg0;
1206 	int		errc;
1207 
1208 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1209 		func = (int (*)()) (vp->v_op->vop_realvp);
1210 		arg0 = vp;
1211 		fem_unlock(vp->v_femhead);
1212 		errc = (*func)(arg0, vpp, ct);
1213 	} else {
1214 		fem_addref(femsp);
1215 		fem_unlock(vp->v_femhead);
1216 		farg.fa_vnode.vp = vp;
1217 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1218 		vsop_find(&farg, &func, int, &arg0, vop_realvp,
1219 		    femop_realvp);
1220 		errc = (*func)(arg0, vpp, ct);
1221 		fem_release(femsp);
1222 	}
1223 	return (errc);
1224 }
1225 
1226 static int
vhead_getpage(vnode_t * vp,offset_t off,size_t len,uint_t * protp,struct page ** plarr,size_t plsz,struct seg * seg,caddr_t addr,enum seg_rw rw,cred_t * cr,caller_context_t * ct)1227 vhead_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
1228     struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
1229     enum seg_rw rw, cred_t *cr, caller_context_t *ct)
1230 {
1231 	femarg_t	farg;
1232 	struct fem_list	*femsp;
1233 	int		(*func)();
1234 	void		*arg0;
1235 	int		errc;
1236 
1237 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1238 		func = (int (*)()) (vp->v_op->vop_getpage);
1239 		arg0 = vp;
1240 		fem_unlock(vp->v_femhead);
1241 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1242 		    addr, rw, cr, ct);
1243 	} else {
1244 		fem_addref(femsp);
1245 		fem_unlock(vp->v_femhead);
1246 		farg.fa_vnode.vp = vp;
1247 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1248 		vsop_find(&farg, &func, int, &arg0, vop_getpage,
1249 		    femop_getpage);
1250 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1251 		    addr, rw, cr, ct);
1252 		fem_release(femsp);
1253 	}
1254 	return (errc);
1255 }
1256 
1257 static int
vhead_putpage(vnode_t * vp,offset_t off,size_t len,int flags,cred_t * cr,caller_context_t * ct)1258 vhead_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
1259     caller_context_t *ct)
1260 {
1261 	femarg_t	farg;
1262 	struct fem_list	*femsp;
1263 	int		(*func)();
1264 	void		*arg0;
1265 	int		errc;
1266 
1267 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1268 		func = (int (*)()) (vp->v_op->vop_putpage);
1269 		arg0 = vp;
1270 		fem_unlock(vp->v_femhead);
1271 		errc = (*func)(arg0, off, len, flags, cr, ct);
1272 	} else {
1273 		fem_addref(femsp);
1274 		fem_unlock(vp->v_femhead);
1275 		farg.fa_vnode.vp = vp;
1276 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1277 		vsop_find(&farg, &func, int, &arg0, vop_putpage,
1278 		    femop_putpage);
1279 		errc = (*func)(arg0, off, len, flags, cr, ct);
1280 		fem_release(femsp);
1281 	}
1282 	return (errc);
1283 }
1284 
1285 static int
vhead_map(vnode_t * vp,offset_t off,struct as * as,caddr_t * addrp,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)1286 vhead_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
1287     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1288     cred_t *cr, caller_context_t *ct)
1289 {
1290 	femarg_t	farg;
1291 	struct fem_list	*femsp;
1292 	int		(*func)();
1293 	void		*arg0;
1294 	int		errc;
1295 
1296 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1297 		func = (int (*)()) (vp->v_op->vop_map);
1298 		arg0 = vp;
1299 		fem_unlock(vp->v_femhead);
1300 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1301 		    flags, cr, ct);
1302 	} else {
1303 		fem_addref(femsp);
1304 		fem_unlock(vp->v_femhead);
1305 		farg.fa_vnode.vp = vp;
1306 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1307 		vsop_find(&farg, &func, int, &arg0, vop_map, femop_map);
1308 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1309 		    flags, cr, ct);
1310 		fem_release(femsp);
1311 	}
1312 	return (errc);
1313 }
1314 
1315 static int
vhead_addmap(vnode_t * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)1316 vhead_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1317     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1318     cred_t *cr, caller_context_t *ct)
1319 {
1320 	femarg_t	farg;
1321 	struct fem_list	*femsp;
1322 	int		(*func)();
1323 	void		*arg0;
1324 	int		errc;
1325 
1326 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1327 		func = (int (*)()) (vp->v_op->vop_addmap);
1328 		arg0 = vp;
1329 		fem_unlock(vp->v_femhead);
1330 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1331 		    flags, cr, ct);
1332 	} else {
1333 		fem_addref(femsp);
1334 		fem_unlock(vp->v_femhead);
1335 		farg.fa_vnode.vp = vp;
1336 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1337 		vsop_find(&farg, &func, int, &arg0, vop_addmap,
1338 		    femop_addmap);
1339 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1340 		    flags, cr, ct);
1341 		fem_release(femsp);
1342 	}
1343 	return (errc);
1344 }
1345 
1346 static int
vhead_delmap(vnode_t * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uint_t prot,uint_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)1347 vhead_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1348     size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
1349     caller_context_t *ct)
1350 {
1351 	femarg_t	farg;
1352 	struct fem_list	*femsp;
1353 	int		(*func)();
1354 	void		*arg0;
1355 	int		errc;
1356 
1357 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1358 		func = (int (*)()) (vp->v_op->vop_delmap);
1359 		arg0 = vp;
1360 		fem_unlock(vp->v_femhead);
1361 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1362 		    flags, cr, ct);
1363 	} else {
1364 		fem_addref(femsp);
1365 		fem_unlock(vp->v_femhead);
1366 		farg.fa_vnode.vp = vp;
1367 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1368 		vsop_find(&farg, &func, int, &arg0, vop_delmap,
1369 		    femop_delmap);
1370 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1371 		    flags, cr, ct);
1372 		fem_release(femsp);
1373 	}
1374 	return (errc);
1375 }
1376 
1377 static int
vhead_poll(vnode_t * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)1378 vhead_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
1379     struct pollhead **phpp, caller_context_t *ct)
1380 {
1381 	femarg_t	farg;
1382 	struct fem_list	*femsp;
1383 	int		(*func)();
1384 	void		*arg0;
1385 	int		errc;
1386 
1387 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1388 		func = (int (*)()) (vp->v_op->vop_poll);
1389 		arg0 = vp;
1390 		fem_unlock(vp->v_femhead);
1391 		errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
1392 	} else {
1393 		fem_addref(femsp);
1394 		fem_unlock(vp->v_femhead);
1395 		farg.fa_vnode.vp = vp;
1396 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1397 		vsop_find(&farg, &func, int, &arg0, vop_poll, femop_poll);
1398 		errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
1399 		fem_release(femsp);
1400 	}
1401 	return (errc);
1402 }
1403 
1404 static int
vhead_dump(vnode_t * vp,caddr_t addr,offset_t lbdn,offset_t dblks,caller_context_t * ct)1405 vhead_dump(vnode_t *vp, caddr_t addr, offset_t lbdn, offset_t dblks,
1406     caller_context_t *ct)
1407 {
1408 	femarg_t	farg;
1409 	struct fem_list	*femsp;
1410 	int		(*func)();
1411 	void		*arg0;
1412 	int		errc;
1413 
1414 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1415 		func = (int (*)()) (vp->v_op->vop_dump);
1416 		arg0 = vp;
1417 		fem_unlock(vp->v_femhead);
1418 		errc = (*func)(arg0, addr, lbdn, dblks, ct);
1419 	} else {
1420 		fem_addref(femsp);
1421 		fem_unlock(vp->v_femhead);
1422 		farg.fa_vnode.vp = vp;
1423 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1424 		vsop_find(&farg, &func, int, &arg0, vop_dump, femop_dump);
1425 		errc = (*func)(arg0, addr, lbdn, dblks, ct);
1426 		fem_release(femsp);
1427 	}
1428 	return (errc);
1429 }
1430 
1431 static int
vhead_pathconf(vnode_t * vp,int cmd,ulong_t * valp,cred_t * cr,caller_context_t * ct)1432 vhead_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
1433     caller_context_t *ct)
1434 {
1435 	femarg_t	farg;
1436 	struct fem_list	*femsp;
1437 	int		(*func)();
1438 	void		*arg0;
1439 	int		errc;
1440 
1441 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1442 		func = (int (*)()) (vp->v_op->vop_pathconf);
1443 		arg0 = vp;
1444 		fem_unlock(vp->v_femhead);
1445 		errc = (*func)(arg0, cmd, valp, cr, ct);
1446 	} else {
1447 		fem_addref(femsp);
1448 		fem_unlock(vp->v_femhead);
1449 		farg.fa_vnode.vp = vp;
1450 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1451 		vsop_find(&farg, &func, int, &arg0, vop_pathconf,
1452 		    femop_pathconf);
1453 		errc = (*func)(arg0, cmd, valp, cr, ct);
1454 		fem_release(femsp);
1455 	}
1456 	return (errc);
1457 }
1458 
1459 static int
vhead_pageio(vnode_t * vp,struct page * pp,u_offset_t io_off,size_t io_len,int flags,cred_t * cr,caller_context_t * ct)1460 vhead_pageio(vnode_t *vp, struct page *pp, u_offset_t io_off,
1461     size_t io_len, int flags, cred_t *cr, caller_context_t *ct)
1462 {
1463 	femarg_t	farg;
1464 	struct fem_list	*femsp;
1465 	int		(*func)();
1466 	void		*arg0;
1467 	int		errc;
1468 
1469 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1470 		func = (int (*)()) (vp->v_op->vop_pageio);
1471 		arg0 = vp;
1472 		fem_unlock(vp->v_femhead);
1473 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
1474 	} else {
1475 		fem_addref(femsp);
1476 		fem_unlock(vp->v_femhead);
1477 		farg.fa_vnode.vp = vp;
1478 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1479 		vsop_find(&farg, &func, int, &arg0, vop_pageio,
1480 		    femop_pageio);
1481 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
1482 		fem_release(femsp);
1483 	}
1484 	return (errc);
1485 }
1486 
1487 static int
vhead_dumpctl(vnode_t * vp,int action,offset_t * blkp,caller_context_t * ct)1488 vhead_dumpctl(vnode_t *vp, int action, offset_t *blkp, caller_context_t *ct)
1489 {
1490 	femarg_t	farg;
1491 	struct fem_list	*femsp;
1492 	int		(*func)();
1493 	void		*arg0;
1494 	int		errc;
1495 
1496 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1497 		func = (int (*)()) (vp->v_op->vop_dumpctl);
1498 		arg0 = vp;
1499 		fem_unlock(vp->v_femhead);
1500 		errc = (*func)(arg0, action, blkp, ct);
1501 	} else {
1502 		fem_addref(femsp);
1503 		fem_unlock(vp->v_femhead);
1504 		farg.fa_vnode.vp = vp;
1505 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1506 		vsop_find(&farg, &func, int, &arg0, vop_dumpctl,
1507 		    femop_dumpctl);
1508 		errc = (*func)(arg0, action, blkp, ct);
1509 		fem_release(femsp);
1510 	}
1511 	return (errc);
1512 }
1513 
1514 static int
vhead_dispose(vnode_t * vp,struct page * pp,int flag,int dn,cred_t * cr,caller_context_t * ct)1515 vhead_dispose(vnode_t *vp, struct page *pp, int flag, int dn, cred_t *cr,
1516     caller_context_t *ct)
1517 {
1518 	femarg_t	farg;
1519 	struct fem_list	*femsp;
1520 	void		(*func)();
1521 	void		*arg0;
1522 
1523 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1524 		func = (void (*)()) (vp->v_op->vop_dispose);
1525 		arg0 = vp;
1526 		fem_unlock(vp->v_femhead);
1527 		(*func)(arg0, pp, flag, dn, cr, ct);
1528 	} else {
1529 		fem_addref(femsp);
1530 		fem_unlock(vp->v_femhead);
1531 		farg.fa_vnode.vp = vp;
1532 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1533 		vsop_find(&farg, &func, void, &arg0, vop_dispose,
1534 		    femop_dispose);
1535 		(*func)(arg0, pp, flag, dn, cr, ct);
1536 		fem_release(femsp);
1537 	}
1538 	return (0);
1539 }
1540 
1541 static int
vhead_setsecattr(vnode_t * vp,vsecattr_t * vsap,int flag,cred_t * cr,caller_context_t * ct)1542 vhead_setsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
1543     caller_context_t *ct)
1544 {
1545 	femarg_t	farg;
1546 	struct fem_list	*femsp;
1547 	int		(*func)();
1548 	void		*arg0;
1549 	int		errc;
1550 
1551 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1552 		func = (int (*)()) (vp->v_op->vop_setsecattr);
1553 		arg0 = vp;
1554 		fem_unlock(vp->v_femhead);
1555 		errc = (*func)(arg0, vsap, flag, cr, ct);
1556 	} else {
1557 		fem_addref(femsp);
1558 		fem_unlock(vp->v_femhead);
1559 		farg.fa_vnode.vp = vp;
1560 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1561 		vsop_find(&farg, &func, int, &arg0, vop_setsecattr,
1562 		    femop_setsecattr);
1563 		errc = (*func)(arg0, vsap, flag, cr, ct);
1564 		fem_release(femsp);
1565 	}
1566 	return (errc);
1567 }
1568 
1569 static int
vhead_getsecattr(vnode_t * vp,vsecattr_t * vsap,int flag,cred_t * cr,caller_context_t * ct)1570 vhead_getsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
1571     caller_context_t *ct)
1572 {
1573 	femarg_t	farg;
1574 	struct fem_list	*femsp;
1575 	int		(*func)();
1576 	void		*arg0;
1577 	int		errc;
1578 
1579 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1580 		func = (int (*)()) (vp->v_op->vop_getsecattr);
1581 		arg0 = vp;
1582 		fem_unlock(vp->v_femhead);
1583 		errc = (*func)(arg0, vsap, flag, cr, ct);
1584 	} else {
1585 		fem_addref(femsp);
1586 		fem_unlock(vp->v_femhead);
1587 		farg.fa_vnode.vp = vp;
1588 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1589 		vsop_find(&farg, &func, int, &arg0, vop_getsecattr,
1590 		    femop_getsecattr);
1591 		errc = (*func)(arg0, vsap, flag, cr, ct);
1592 		fem_release(femsp);
1593 	}
1594 	return (errc);
1595 }
1596 
1597 static int
vhead_shrlock(vnode_t * vp,int cmd,struct shrlock * shr,int flag,cred_t * cr,caller_context_t * ct)1598 vhead_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag,
1599     cred_t *cr, caller_context_t *ct)
1600 {
1601 	femarg_t	farg;
1602 	struct fem_list	*femsp;
1603 	int		(*func)();
1604 	void		*arg0;
1605 	int		errc;
1606 
1607 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1608 		func = (int (*)()) (vp->v_op->vop_shrlock);
1609 		arg0 = vp;
1610 		fem_unlock(vp->v_femhead);
1611 		errc = (*func)(arg0, cmd, shr, flag, cr, ct);
1612 	} else {
1613 		fem_addref(femsp);
1614 		fem_unlock(vp->v_femhead);
1615 		farg.fa_vnode.vp = vp;
1616 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1617 		vsop_find(&farg, &func, int, &arg0, vop_shrlock,
1618 		    femop_shrlock);
1619 		errc = (*func)(arg0, cmd, shr, flag, cr, ct);
1620 		fem_release(femsp);
1621 	}
1622 	return (errc);
1623 }
1624 
1625 static int
vhead_vnevent(vnode_t * vp,vnevent_t vnevent,vnode_t * dvp,char * cname,caller_context_t * ct)1626 vhead_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *cname,
1627     caller_context_t *ct)
1628 {
1629 	femarg_t	farg;
1630 	struct fem_list	*femsp;
1631 	int		(*func)();
1632 	void		*arg0;
1633 	int		errc;
1634 
1635 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1636 		func = (int (*)()) (vp->v_op->vop_vnevent);
1637 		arg0 = vp;
1638 		fem_unlock(vp->v_femhead);
1639 		errc = (*func)(arg0, vnevent, dvp, cname, ct);
1640 	} else {
1641 		fem_addref(femsp);
1642 		fem_unlock(vp->v_femhead);
1643 		farg.fa_vnode.vp = vp;
1644 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1645 		vsop_find(&farg, &func, int, &arg0, vop_vnevent,
1646 		    femop_vnevent);
1647 		errc = (*func)(arg0, vnevent, dvp, cname, ct);
1648 		fem_release(femsp);
1649 	}
1650 	return (errc);
1651 }
1652 
1653 static int
vhead_reqzcbuf(vnode_t * vp,enum uio_rw ioflag,xuio_t * xuiop,cred_t * cr,caller_context_t * ct)1654 vhead_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuiop, cred_t *cr,
1655     caller_context_t *ct)
1656 {
1657 	femarg_t	farg;
1658 	struct fem_list	*femsp;
1659 	int		(*func)();
1660 	void		*arg0;
1661 	int		errc;
1662 
1663 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1664 		func = (int (*)()) (vp->v_op->vop_reqzcbuf);
1665 		arg0 = vp;
1666 		fem_unlock(vp->v_femhead);
1667 		errc = (*func)(arg0, ioflag, xuiop, cr, ct);
1668 	} else {
1669 		fem_addref(femsp);
1670 		fem_unlock(vp->v_femhead);
1671 		farg.fa_vnode.vp = vp;
1672 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1673 		vsop_find(&farg, &func, int, &arg0, vop_reqzcbuf,
1674 		    femop_reqzcbuf);
1675 		errc = (*func)(arg0, ioflag, xuiop, cr, ct);
1676 		fem_release(femsp);
1677 	}
1678 	return (errc);
1679 }
1680 
1681 static int
vhead_retzcbuf(vnode_t * vp,xuio_t * xuiop,cred_t * cr,caller_context_t * ct)1682 vhead_retzcbuf(vnode_t *vp, xuio_t *xuiop, cred_t *cr, caller_context_t *ct)
1683 {
1684 	femarg_t	farg;
1685 	struct fem_list	*femsp;
1686 	int		(*func)();
1687 	void		*arg0;
1688 	int		errc;
1689 
1690 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1691 		func = (int (*)()) (vp->v_op->vop_retzcbuf);
1692 		arg0 = vp;
1693 		fem_unlock(vp->v_femhead);
1694 		errc = (*func)(arg0, xuiop, cr, ct);
1695 	} else {
1696 		fem_addref(femsp);
1697 		fem_unlock(vp->v_femhead);
1698 		farg.fa_vnode.vp = vp;
1699 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1700 		vsop_find(&farg, &func, int, &arg0, vop_retzcbuf,
1701 		    femop_retzcbuf);
1702 		errc = (*func)(arg0, xuiop, cr, ct);
1703 		fem_release(femsp);
1704 	}
1705 	return (errc);
1706 }
1707 
1708 static int
fshead_mount(vfs_t * vfsp,vnode_t * mvp,struct mounta * uap,cred_t * cr)1709 fshead_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
1710 {
1711 	fsemarg_t	farg;
1712 	struct fem_list	*femsp;
1713 	int		(*func)();
1714 	void		*arg0;
1715 	int		errc;
1716 
1717 	ASSERT(vfsp->vfs_implp);
1718 
1719 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1720 		func = (int (*)()) vfsp->vfs_op->vfs_mount;
1721 		fem_unlock(vfsp->vfs_femhead);
1722 		errc = (*func)(vfsp, mvp, uap, cr);
1723 	} else {
1724 		fem_addref(femsp);
1725 		fem_unlock(vfsp->vfs_femhead);
1726 		farg.fa_vnode.vfsp = vfsp;
1727 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1728 		vfsop_find(&farg, &func, int, &arg0, vfs_mount,
1729 		    fsemop_mount);
1730 		errc = (*func)(arg0, mvp, uap, cr);
1731 		fem_release(femsp);
1732 	}
1733 	return (errc);
1734 }
1735 
1736 static int
fshead_unmount(vfs_t * vfsp,int flag,cred_t * cr)1737 fshead_unmount(vfs_t *vfsp, int flag, cred_t *cr)
1738 {
1739 	fsemarg_t	farg;
1740 	struct fem_list	*femsp;
1741 	int		(*func)();
1742 	void		*arg0;
1743 	int		errc;
1744 
1745 	ASSERT(vfsp->vfs_implp);
1746 
1747 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1748 		func = (int (*)()) vfsp->vfs_op->vfs_unmount;
1749 		fem_unlock(vfsp->vfs_femhead);
1750 		errc = (*func)(vfsp, flag, cr);
1751 	} else {
1752 		fem_addref(femsp);
1753 		fem_unlock(vfsp->vfs_femhead);
1754 		farg.fa_vnode.vfsp = vfsp;
1755 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1756 		vfsop_find(&farg, &func, int, &arg0, vfs_unmount,
1757 		    fsemop_unmount);
1758 		errc = (*func)(arg0, flag, cr);
1759 		fem_release(femsp);
1760 	}
1761 	return (errc);
1762 }
1763 
1764 static int
fshead_root(vfs_t * vfsp,vnode_t ** vpp)1765 fshead_root(vfs_t *vfsp, vnode_t **vpp)
1766 {
1767 	fsemarg_t	farg;
1768 	struct fem_list	*femsp;
1769 	int		(*func)();
1770 	void		*arg0;
1771 	int		errc;
1772 
1773 	ASSERT(vfsp->vfs_implp);
1774 
1775 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1776 		func = (int (*)()) vfsp->vfs_op->vfs_root;
1777 		fem_unlock(vfsp->vfs_femhead);
1778 		errc = (*func)(vfsp, vpp);
1779 	} else {
1780 		fem_addref(femsp);
1781 		fem_unlock(vfsp->vfs_femhead);
1782 		farg.fa_vnode.vfsp = vfsp;
1783 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1784 		vfsop_find(&farg, &func, int, &arg0, vfs_root, fsemop_root);
1785 		errc = (*func)(arg0, vpp);
1786 		fem_release(femsp);
1787 	}
1788 	return (errc);
1789 }
1790 
1791 static int
fshead_statvfs(vfs_t * vfsp,statvfs64_t * sp)1792 fshead_statvfs(vfs_t *vfsp, statvfs64_t *sp)
1793 {
1794 	fsemarg_t	farg;
1795 	struct fem_list	*femsp;
1796 	int		(*func)();
1797 	void		*arg0;
1798 	int		errc;
1799 
1800 	ASSERT(vfsp->vfs_implp);
1801 
1802 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1803 		func = (int (*)()) vfsp->vfs_op->vfs_statvfs;
1804 		fem_unlock(vfsp->vfs_femhead);
1805 		errc = (*func)(vfsp, sp);
1806 	} else {
1807 		fem_addref(femsp);
1808 		fem_unlock(vfsp->vfs_femhead);
1809 		farg.fa_vnode.vfsp = vfsp;
1810 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1811 		vfsop_find(&farg, &func, int, &arg0, vfs_statvfs,
1812 		    fsemop_statvfs);
1813 		errc = (*func)(arg0, sp);
1814 		fem_release(femsp);
1815 	}
1816 	return (errc);
1817 }
1818 
1819 static int
fshead_sync(vfs_t * vfsp,short flag,cred_t * cr)1820 fshead_sync(vfs_t *vfsp, short flag, cred_t *cr)
1821 {
1822 	fsemarg_t	farg;
1823 	struct fem_list	*femsp;
1824 	int		(*func)();
1825 	void		*arg0;
1826 	int		errc;
1827 
1828 	ASSERT(vfsp->vfs_implp);
1829 
1830 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1831 		func = (int (*)()) vfsp->vfs_op->vfs_sync;
1832 		fem_unlock(vfsp->vfs_femhead);
1833 		errc = (*func)(vfsp, flag, cr);
1834 	} else {
1835 		fem_addref(femsp);
1836 		fem_unlock(vfsp->vfs_femhead);
1837 		farg.fa_vnode.vfsp = vfsp;
1838 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1839 		vfsop_find(&farg, &func, int, &arg0, vfs_sync, fsemop_sync);
1840 		errc = (*func)(arg0, flag, cr);
1841 		fem_release(femsp);
1842 	}
1843 	return (errc);
1844 }
1845 
1846 static int
fshead_vget(vfs_t * vfsp,vnode_t ** vpp,fid_t * fidp)1847 fshead_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
1848 {
1849 	fsemarg_t	farg;
1850 	struct fem_list	*femsp;
1851 	int		(*func)();
1852 	void		*arg0;
1853 	int		errc;
1854 
1855 	ASSERT(vfsp->vfs_implp);
1856 
1857 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1858 		func = (int (*)()) vfsp->vfs_op->vfs_vget;
1859 		fem_unlock(vfsp->vfs_femhead);
1860 		errc = (*func)(vfsp, vpp, fidp);
1861 	} else {
1862 		fem_addref(femsp);
1863 		fem_unlock(vfsp->vfs_femhead);
1864 		farg.fa_vnode.vfsp = vfsp;
1865 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1866 		vfsop_find(&farg, &func, int, &arg0, vfs_vget, fsemop_vget);
1867 		errc = (*func)(arg0, vpp, fidp);
1868 		fem_release(femsp);
1869 	}
1870 	return (errc);
1871 }
1872 
1873 static int
fshead_mountroot(vfs_t * vfsp,enum whymountroot reason)1874 fshead_mountroot(vfs_t *vfsp, enum whymountroot reason)
1875 {
1876 	fsemarg_t	farg;
1877 	struct fem_list	*femsp;
1878 	int		(*func)();
1879 	void		*arg0;
1880 	int		errc;
1881 
1882 	ASSERT(vfsp->vfs_implp);
1883 
1884 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1885 		func = (int (*)()) vfsp->vfs_op->vfs_mountroot;
1886 		fem_unlock(vfsp->vfs_femhead);
1887 		errc = (*func)(vfsp, reason);
1888 	} else {
1889 		fem_addref(femsp);
1890 		fem_unlock(vfsp->vfs_femhead);
1891 		farg.fa_vnode.vfsp = vfsp;
1892 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1893 		vfsop_find(&farg, &func, int, &arg0, vfs_mountroot,
1894 		    fsemop_mountroot);
1895 		errc = (*func)(arg0, reason);
1896 		fem_release(femsp);
1897 	}
1898 	return (errc);
1899 }
1900 
1901 static int
fshead_freevfs(vfs_t * vfsp)1902 fshead_freevfs(vfs_t *vfsp)
1903 {
1904 	fsemarg_t	farg;
1905 	struct fem_list	*femsp;
1906 	void		(*func)();
1907 	void		*arg0;
1908 
1909 	ASSERT(vfsp->vfs_implp);
1910 
1911 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1912 		func = (void (*)()) vfsp->vfs_op->vfs_freevfs;
1913 		fem_unlock(vfsp->vfs_femhead);
1914 		(*func)(vfsp);
1915 	} else {
1916 		fem_addref(femsp);
1917 		fem_unlock(vfsp->vfs_femhead);
1918 		farg.fa_vnode.vfsp = vfsp;
1919 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1920 		vfsop_find(&farg, &func, void, &arg0, vfs_freevfs,
1921 		    fsemop_freevfs);
1922 		(*func)(arg0);
1923 		fem_release(femsp);
1924 	}
1925 	return (0);
1926 }
1927 
1928 static int
fshead_vnstate(vfs_t * vfsp,vnode_t * vp,vntrans_t nstate)1929 fshead_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
1930 {
1931 	fsemarg_t	farg;
1932 	struct fem_list	*femsp;
1933 	int		(*func)();
1934 	void		*arg0;
1935 	int		errc;
1936 
1937 	ASSERT(vfsp->vfs_implp);
1938 
1939 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
1940 		func = (int (*)()) vfsp->vfs_op->vfs_vnstate;
1941 		fem_unlock(vfsp->vfs_femhead);
1942 		errc = (*func)(vfsp, vp, nstate);
1943 	} else {
1944 		fem_addref(femsp);
1945 		fem_unlock(vfsp->vfs_femhead);
1946 		farg.fa_vnode.vfsp = vfsp;
1947 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1948 		vfsop_find(&farg, &func, int, &arg0, vfs_vnstate,
1949 		    fsemop_vnstate);
1950 		errc = (*func)(arg0, vp, nstate);
1951 		fem_release(femsp);
1952 	}
1953 	return (errc);
1954 }
1955 
1956 
1957 /*
1958  * specification table for the vhead vnode operations.
1959  * It is an error for any operations to be missing.
1960  */
1961 
1962 static struct fs_operation_def fhead_vn_spec[] = {
1963 	{ VOPNAME_OPEN, (femop_t *)vhead_open },
1964 	{ VOPNAME_CLOSE, (femop_t *)vhead_close },
1965 	{ VOPNAME_READ, (femop_t *)vhead_read },
1966 	{ VOPNAME_WRITE, (femop_t *)vhead_write },
1967 	{ VOPNAME_IOCTL, (femop_t *)vhead_ioctl },
1968 	{ VOPNAME_SETFL, (femop_t *)vhead_setfl },
1969 	{ VOPNAME_GETATTR, (femop_t *)vhead_getattr },
1970 	{ VOPNAME_SETATTR, (femop_t *)vhead_setattr },
1971 	{ VOPNAME_ACCESS, (femop_t *)vhead_access },
1972 	{ VOPNAME_LOOKUP, (femop_t *)vhead_lookup },
1973 	{ VOPNAME_CREATE, (femop_t *)vhead_create },
1974 	{ VOPNAME_REMOVE, (femop_t *)vhead_remove },
1975 	{ VOPNAME_LINK, (femop_t *)vhead_link },
1976 	{ VOPNAME_RENAME, (femop_t *)vhead_rename },
1977 	{ VOPNAME_MKDIR, (femop_t *)vhead_mkdir },
1978 	{ VOPNAME_RMDIR, (femop_t *)vhead_rmdir },
1979 	{ VOPNAME_READDIR, (femop_t *)vhead_readdir },
1980 	{ VOPNAME_SYMLINK, (femop_t *)vhead_symlink },
1981 	{ VOPNAME_READLINK, (femop_t *)vhead_readlink },
1982 	{ VOPNAME_FSYNC, (femop_t *)vhead_fsync },
1983 	{ VOPNAME_INACTIVE, (femop_t *)vhead_inactive },
1984 	{ VOPNAME_FID, (femop_t *)vhead_fid },
1985 	{ VOPNAME_RWLOCK, (femop_t *)vhead_rwlock },
1986 	{ VOPNAME_RWUNLOCK, (femop_t *)vhead_rwunlock },
1987 	{ VOPNAME_SEEK, (femop_t *)vhead_seek },
1988 	{ VOPNAME_CMP, (femop_t *)vhead_cmp },
1989 	{ VOPNAME_FRLOCK, (femop_t *)vhead_frlock },
1990 	{ VOPNAME_SPACE, (femop_t *)vhead_space },
1991 	{ VOPNAME_REALVP, (femop_t *)vhead_realvp },
1992 	{ VOPNAME_GETPAGE, (femop_t *)vhead_getpage },
1993 	{ VOPNAME_PUTPAGE, (femop_t *)vhead_putpage },
1994 	{ VOPNAME_MAP, (femop_t *)vhead_map },
1995 	{ VOPNAME_ADDMAP, (femop_t *)vhead_addmap },
1996 	{ VOPNAME_DELMAP, (femop_t *)vhead_delmap },
1997 	{ VOPNAME_POLL, (femop_t *)vhead_poll },
1998 	{ VOPNAME_DUMP, (femop_t *)vhead_dump },
1999 	{ VOPNAME_PATHCONF, (femop_t *)vhead_pathconf },
2000 	{ VOPNAME_PAGEIO, (femop_t *)vhead_pageio },
2001 	{ VOPNAME_DUMPCTL, (femop_t *)vhead_dumpctl },
2002 	{ VOPNAME_DISPOSE, (femop_t *)vhead_dispose },
2003 	{ VOPNAME_SETSECATTR, (femop_t *)vhead_setsecattr },
2004 	{ VOPNAME_GETSECATTR, (femop_t *)vhead_getsecattr },
2005 	{ VOPNAME_SHRLOCK, (femop_t *)vhead_shrlock },
2006 	{ VOPNAME_VNEVENT, (femop_t *)vhead_vnevent },
2007 	{ VOPNAME_REQZCBUF, (femop_t *)vhead_reqzcbuf },
2008 	{ VOPNAME_RETZCBUF, (femop_t *)vhead_retzcbuf },
2009 	{	NULL,	NULL	}
2010 };
2011 
2012 /*
2013  * specification table for the vfshead vnode operations.
2014  * It is an error for any operations to be missing.
2015  */
2016 
2017 static struct fs_operation_def fshead_vfs_spec[]  = {
2018 	{ VFSNAME_MOUNT, (femop_t *)fshead_mount },
2019 	{ VFSNAME_UNMOUNT, (femop_t *)fshead_unmount },
2020 	{ VFSNAME_ROOT, (femop_t *)fshead_root },
2021 	{ VFSNAME_STATVFS, (femop_t *)fshead_statvfs },
2022 	{ VFSNAME_SYNC, (femop_t *)fshead_sync },
2023 	{ VFSNAME_VGET, (femop_t *)fshead_vget },
2024 	{ VFSNAME_MOUNTROOT, (femop_t *)fshead_mountroot },
2025 	{ VFSNAME_FREEVFS, (femop_t *)fshead_freevfs },
2026 	{ VFSNAME_VNSTATE, (femop_t *)fshead_vnstate },
2027 	{	NULL,	NULL	}
2028 };
2029 
2030 /*
2031  * This set of routines transfer control to the next stacked monitor.
2032  *
2033  * Each routine is identical except for naming, types and arguments.
2034  *
2035  * The basic steps are:
2036  * 1.  Decrease the stack pointer by one.
2037  * 2.  If the current item is a base operation (vnode, vfs), goto 5.
2038  * 3.  If the current item does not have a corresponding operation, goto 1
2039  * 4.  Return by invoking the current item with the argument handle.
2040  * 5.  Return by invoking the base operation with the base object.
2041  *
2042  * for each classification, there needs to be at least one "next" operation
2043  * for each "head"operation.
2044  *
2045  */
2046 
2047 int
vnext_open(femarg_t * vf,int mode,cred_t * cr,caller_context_t * ct)2048 vnext_open(femarg_t *vf, int mode, cred_t *cr, caller_context_t *ct)
2049 {
2050 	int (*func)() = NULL;
2051 	void *arg0 = NULL;
2052 
2053 	ASSERT(vf != NULL);
2054 	vf->fa_fnode--;
2055 	vsop_find(vf, &func, int, &arg0, vop_open, femop_open);
2056 	ASSERT(func != NULL);
2057 	ASSERT(arg0 != NULL);
2058 	return ((*func)(arg0, mode, cr, ct));
2059 }
2060 
2061 int
vnext_close(femarg_t * vf,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)2062 vnext_close(femarg_t *vf, int flag, int count, offset_t offset, cred_t *cr,
2063     caller_context_t *ct)
2064 {
2065 	int (*func)() = NULL;
2066 	void *arg0 = NULL;
2067 
2068 	ASSERT(vf != NULL);
2069 	vf->fa_fnode--;
2070 	vsop_find(vf, &func, int, &arg0, vop_close, femop_close);
2071 	ASSERT(func != NULL);
2072 	ASSERT(arg0 != NULL);
2073 	return ((*func)(arg0, flag, count, offset, cr, ct));
2074 }
2075 
2076 int
vnext_read(femarg_t * vf,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)2077 vnext_read(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
2078     caller_context_t *ct)
2079 {
2080 	int (*func)() = NULL;
2081 	void *arg0 = NULL;
2082 
2083 	ASSERT(vf != NULL);
2084 	vf->fa_fnode--;
2085 	vsop_find(vf, &func, int, &arg0, vop_read, femop_read);
2086 	ASSERT(func != NULL);
2087 	ASSERT(arg0 != NULL);
2088 	return ((*func)(arg0, uiop, ioflag, cr, ct));
2089 }
2090 
2091 int
vnext_write(femarg_t * vf,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)2092 vnext_write(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
2093     caller_context_t *ct)
2094 {
2095 	int (*func)() = NULL;
2096 	void *arg0 = NULL;
2097 
2098 	ASSERT(vf != NULL);
2099 	vf->fa_fnode--;
2100 	vsop_find(vf, &func, int, &arg0, vop_write, femop_write);
2101 	ASSERT(func != NULL);
2102 	ASSERT(arg0 != NULL);
2103 	return ((*func)(arg0, uiop, ioflag, cr, ct));
2104 }
2105 
2106 int
vnext_ioctl(femarg_t * vf,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)2107 vnext_ioctl(femarg_t *vf, int cmd, intptr_t arg, int flag, cred_t *cr,
2108     int *rvalp, caller_context_t *ct)
2109 {
2110 	int (*func)() = NULL;
2111 	void *arg0 = NULL;
2112 
2113 	ASSERT(vf != NULL);
2114 	vf->fa_fnode--;
2115 	vsop_find(vf, &func, int, &arg0, vop_ioctl, femop_ioctl);
2116 	ASSERT(func != NULL);
2117 	ASSERT(arg0 != NULL);
2118 	return ((*func)(arg0, cmd, arg, flag, cr, rvalp, ct));
2119 }
2120 
2121 int
vnext_setfl(femarg_t * vf,int oflags,int nflags,cred_t * cr,caller_context_t * ct)2122 vnext_setfl(femarg_t *vf, int oflags, int nflags, cred_t *cr,
2123     caller_context_t *ct)
2124 {
2125 	int (*func)() = NULL;
2126 	void *arg0 = NULL;
2127 
2128 	ASSERT(vf != NULL);
2129 	vf->fa_fnode--;
2130 	vsop_find(vf, &func, int, &arg0, vop_setfl, femop_setfl);
2131 	ASSERT(func != NULL);
2132 	ASSERT(arg0 != NULL);
2133 	return ((*func)(arg0, oflags, nflags, cr, ct));
2134 }
2135 
2136 int
vnext_getattr(femarg_t * vf,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)2137 vnext_getattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
2138     caller_context_t *ct)
2139 {
2140 	int (*func)() = NULL;
2141 	void *arg0 = NULL;
2142 
2143 	ASSERT(vf != NULL);
2144 	vf->fa_fnode--;
2145 	vsop_find(vf, &func, int, &arg0, vop_getattr, femop_getattr);
2146 	ASSERT(func != NULL);
2147 	ASSERT(arg0 != NULL);
2148 	return ((*func)(arg0, vap, flags, cr, ct));
2149 }
2150 
2151 int
vnext_setattr(femarg_t * vf,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)2152 vnext_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
2153     caller_context_t *ct)
2154 {
2155 	int (*func)() = NULL;
2156 	void *arg0 = NULL;
2157 
2158 	ASSERT(vf != NULL);
2159 	vf->fa_fnode--;
2160 	vsop_find(vf, &func, int, &arg0, vop_setattr, femop_setattr);
2161 	ASSERT(func != NULL);
2162 	ASSERT(arg0 != NULL);
2163 	return ((*func)(arg0, vap, flags, cr, ct));
2164 }
2165 
2166 int
vnext_access(femarg_t * vf,int mode,int flags,cred_t * cr,caller_context_t * ct)2167 vnext_access(femarg_t *vf, int mode, int flags, cred_t *cr,
2168     caller_context_t *ct)
2169 {
2170 	int (*func)() = NULL;
2171 	void *arg0 = NULL;
2172 
2173 	ASSERT(vf != NULL);
2174 	vf->fa_fnode--;
2175 	vsop_find(vf, &func, int, &arg0, vop_access, femop_access);
2176 	ASSERT(func != NULL);
2177 	ASSERT(arg0 != NULL);
2178 	return ((*func)(arg0, mode, flags, cr, ct));
2179 }
2180 
2181 int
vnext_lookup(femarg_t * vf,char * nm,vnode_t ** vpp,pathname_t * pnp,int flags,vnode_t * rdir,cred_t * cr,caller_context_t * ct,int * direntflags,pathname_t * realpnp)2182 vnext_lookup(femarg_t *vf, char *nm, vnode_t **vpp, pathname_t *pnp,
2183     int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
2184     int *direntflags, pathname_t *realpnp)
2185 {
2186 	int (*func)() = NULL;
2187 	void *arg0 = NULL;
2188 
2189 	ASSERT(vf != NULL);
2190 	vf->fa_fnode--;
2191 	vsop_find(vf, &func, int, &arg0, vop_lookup, femop_lookup);
2192 	ASSERT(func != NULL);
2193 	ASSERT(arg0 != NULL);
2194 	return ((*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
2195 	    direntflags, realpnp));
2196 }
2197 
2198 int
vnext_create(femarg_t * vf,char * name,vattr_t * vap,vcexcl_t excl,int mode,vnode_t ** vpp,cred_t * cr,int flag,caller_context_t * ct,vsecattr_t * vsecp)2199 vnext_create(femarg_t *vf, char *name, vattr_t *vap, vcexcl_t excl,
2200     int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
2201     vsecattr_t *vsecp)
2202 {
2203 	int (*func)() = NULL;
2204 	void *arg0 = NULL;
2205 
2206 	ASSERT(vf != NULL);
2207 	vf->fa_fnode--;
2208 	vsop_find(vf, &func, int, &arg0, vop_create, femop_create);
2209 	ASSERT(func != NULL);
2210 	ASSERT(arg0 != NULL);
2211 	return ((*func)(arg0, name, vap, excl, mode, vpp, cr, flag, ct, vsecp));
2212 }
2213 
2214 int
vnext_remove(femarg_t * vf,char * nm,cred_t * cr,caller_context_t * ct,int flags)2215 vnext_remove(femarg_t *vf, char *nm, cred_t *cr, caller_context_t *ct,
2216     int flags)
2217 {
2218 	int (*func)() = NULL;
2219 	void *arg0 = NULL;
2220 
2221 	ASSERT(vf != NULL);
2222 	vf->fa_fnode--;
2223 	vsop_find(vf, &func, int, &arg0, vop_remove, femop_remove);
2224 	ASSERT(func != NULL);
2225 	ASSERT(arg0 != NULL);
2226 	return ((*func)(arg0, nm, cr, ct, flags));
2227 }
2228 
2229 int
vnext_link(femarg_t * vf,vnode_t * svp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)2230 vnext_link(femarg_t *vf, vnode_t *svp, char *tnm, cred_t *cr,
2231     caller_context_t *ct, int flags)
2232 {
2233 	int (*func)() = NULL;
2234 	void *arg0 = NULL;
2235 
2236 	ASSERT(vf != NULL);
2237 	vf->fa_fnode--;
2238 	vsop_find(vf, &func, int, &arg0, vop_link, femop_link);
2239 	ASSERT(func != NULL);
2240 	ASSERT(arg0 != NULL);
2241 	return ((*func)(arg0, svp, tnm, cr, ct, flags));
2242 }
2243 
2244 int
vnext_rename(femarg_t * vf,char * snm,vnode_t * tdvp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)2245 vnext_rename(femarg_t *vf, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
2246     caller_context_t *ct, int flags)
2247 {
2248 	int (*func)() = NULL;
2249 	void *arg0 = NULL;
2250 
2251 	ASSERT(vf != NULL);
2252 	vf->fa_fnode--;
2253 	vsop_find(vf, &func, int, &arg0, vop_rename, femop_rename);
2254 	ASSERT(func != NULL);
2255 	ASSERT(arg0 != NULL);
2256 	return ((*func)(arg0, snm, tdvp, tnm, cr, ct, flags));
2257 }
2258 
2259 int
vnext_mkdir(femarg_t * vf,char * dirname,vattr_t * vap,vnode_t ** vpp,cred_t * cr,caller_context_t * ct,int flags,vsecattr_t * vsecp)2260 vnext_mkdir(femarg_t *vf, char *dirname, vattr_t *vap, vnode_t **vpp,
2261     cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2262 {
2263 	int (*func)() = NULL;
2264 	void *arg0 = NULL;
2265 
2266 	ASSERT(vf != NULL);
2267 	vf->fa_fnode--;
2268 	vsop_find(vf, &func, int, &arg0, vop_mkdir, femop_mkdir);
2269 	ASSERT(func != NULL);
2270 	ASSERT(arg0 != NULL);
2271 	return ((*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp));
2272 }
2273 
2274 int
vnext_rmdir(femarg_t * vf,char * nm,vnode_t * cdir,cred_t * cr,caller_context_t * ct,int flags)2275 vnext_rmdir(femarg_t *vf, char *nm, vnode_t *cdir, cred_t *cr,
2276     caller_context_t *ct, int flags)
2277 {
2278 	int (*func)() = NULL;
2279 	void *arg0 = NULL;
2280 
2281 	ASSERT(vf != NULL);
2282 	vf->fa_fnode--;
2283 	vsop_find(vf, &func, int, &arg0, vop_rmdir, femop_rmdir);
2284 	ASSERT(func != NULL);
2285 	ASSERT(arg0 != NULL);
2286 	return ((*func)(arg0, nm, cdir, cr, ct, flags));
2287 }
2288 
2289 int
vnext_readdir(femarg_t * vf,uio_t * uiop,cred_t * cr,int * eofp,caller_context_t * ct,int flags)2290 vnext_readdir(femarg_t *vf, uio_t *uiop, cred_t *cr, int *eofp,
2291     caller_context_t *ct, int flags)
2292 {
2293 	int (*func)() = NULL;
2294 	void *arg0 = NULL;
2295 
2296 	ASSERT(vf != NULL);
2297 	vf->fa_fnode--;
2298 	vsop_find(vf, &func, int, &arg0, vop_readdir, femop_readdir);
2299 	ASSERT(func != NULL);
2300 	ASSERT(arg0 != NULL);
2301 	return ((*func)(arg0, uiop, cr, eofp, ct, flags));
2302 }
2303 
2304 int
vnext_symlink(femarg_t * vf,char * linkname,vattr_t * vap,char * target,cred_t * cr,caller_context_t * ct,int flags)2305 vnext_symlink(femarg_t *vf, char *linkname, vattr_t *vap, char *target,
2306     cred_t *cr, caller_context_t *ct, int flags)
2307 {
2308 	int (*func)() = NULL;
2309 	void *arg0 = NULL;
2310 
2311 	ASSERT(vf != NULL);
2312 	vf->fa_fnode--;
2313 	vsop_find(vf, &func, int, &arg0, vop_symlink, femop_symlink);
2314 	ASSERT(func != NULL);
2315 	ASSERT(arg0 != NULL);
2316 	return ((*func)(arg0, linkname, vap, target, cr, ct, flags));
2317 }
2318 
2319 int
vnext_readlink(femarg_t * vf,uio_t * uiop,cred_t * cr,caller_context_t * ct)2320 vnext_readlink(femarg_t *vf, uio_t *uiop, cred_t *cr, caller_context_t *ct)
2321 {
2322 	int (*func)() = NULL;
2323 	void *arg0 = NULL;
2324 
2325 	ASSERT(vf != NULL);
2326 	vf->fa_fnode--;
2327 	vsop_find(vf, &func, int, &arg0, vop_readlink, femop_readlink);
2328 	ASSERT(func != NULL);
2329 	ASSERT(arg0 != NULL);
2330 	return ((*func)(arg0, uiop, cr, ct));
2331 }
2332 
2333 int
vnext_fsync(femarg_t * vf,int syncflag,cred_t * cr,caller_context_t * ct)2334 vnext_fsync(femarg_t *vf, int syncflag, cred_t *cr, caller_context_t *ct)
2335 {
2336 	int (*func)() = NULL;
2337 	void *arg0 = NULL;
2338 
2339 	ASSERT(vf != NULL);
2340 	vf->fa_fnode--;
2341 	vsop_find(vf, &func, int, &arg0, vop_fsync, femop_fsync);
2342 	ASSERT(func != NULL);
2343 	ASSERT(arg0 != NULL);
2344 	return ((*func)(arg0, syncflag, cr, ct));
2345 }
2346 
2347 void
vnext_inactive(femarg_t * vf,cred_t * cr,caller_context_t * ct)2348 vnext_inactive(femarg_t *vf, cred_t *cr, caller_context_t *ct)
2349 {
2350 	void (*func)() = NULL;
2351 	void *arg0 = NULL;
2352 
2353 	ASSERT(vf != NULL);
2354 	vf->fa_fnode--;
2355 	vsop_find(vf, &func, void, &arg0, vop_inactive, femop_inactive);
2356 	ASSERT(func != NULL);
2357 	ASSERT(arg0 != NULL);
2358 	(*func)(arg0, cr, ct);
2359 }
2360 
2361 int
vnext_fid(femarg_t * vf,fid_t * fidp,caller_context_t * ct)2362 vnext_fid(femarg_t *vf, fid_t *fidp, caller_context_t *ct)
2363 {
2364 	int (*func)() = NULL;
2365 	void *arg0 = NULL;
2366 
2367 	ASSERT(vf != NULL);
2368 	vf->fa_fnode--;
2369 	vsop_find(vf, &func, int, &arg0, vop_fid, femop_fid);
2370 	ASSERT(func != NULL);
2371 	ASSERT(arg0 != NULL);
2372 	return ((*func)(arg0, fidp, ct));
2373 }
2374 
2375 int
vnext_rwlock(femarg_t * vf,int write_lock,caller_context_t * ct)2376 vnext_rwlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2377 {
2378 	int (*func)() = NULL;
2379 	void *arg0 = NULL;
2380 
2381 	ASSERT(vf != NULL);
2382 	vf->fa_fnode--;
2383 	vsop_find(vf, &func, int, &arg0, vop_rwlock, femop_rwlock);
2384 	ASSERT(func != NULL);
2385 	ASSERT(arg0 != NULL);
2386 	return ((*func)(arg0, write_lock, ct));
2387 }
2388 
2389 void
vnext_rwunlock(femarg_t * vf,int write_lock,caller_context_t * ct)2390 vnext_rwunlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2391 {
2392 	void (*func)() = NULL;
2393 	void *arg0 = NULL;
2394 
2395 	ASSERT(vf != NULL);
2396 	vf->fa_fnode--;
2397 	vsop_find(vf, &