Home | History | Annotate | Download | only in fs
      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 *
    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 *
    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
    304 fem_free(fem_t *p)
    305 {
    306 	kmem_free(p, sizeof (*p));
    307 }
    308 
    309 static fsem_t *
    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
    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 *
    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
    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
    368 fem_addref(struct fem_list *sp)
    369 {
    370 	atomic_add_32(&sp->feml_refc, 1);
    371 }
    372 
    373 static uint32_t
    374 fem_delref(struct fem_list *sp)
    375 {
    376 	return (atomic_add_32_nv(&sp->feml_refc, -1));
    377 }
    378 
    379 static struct fem_list *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 void
    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 }
   1010 
   1011 static int
   1012 vhead_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
   1013 {
   1014 	femarg_t	farg;
   1015 	struct fem_list	*femsp;
   1016 	int		(*func)();
   1017 	void		*arg0;
   1018 	int		errc;
   1019 
   1020 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1021 		func = (int (*)()) (vp->v_op->vop_fid);
   1022 		arg0 = vp;
   1023 		fem_unlock(vp->v_femhead);
   1024 		errc = (*func)(arg0, fidp, ct);
   1025 	} else {
   1026 		fem_addref(femsp);
   1027 		fem_unlock(vp->v_femhead);
   1028 		farg.fa_vnode.vp = vp;
   1029 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1030 		vsop_find(&farg, &func, int, &arg0, vop_fid, femop_fid);
   1031 		errc = (*func)(arg0, fidp, ct);
   1032 		fem_release(femsp);
   1033 	}
   1034 	return (errc);
   1035 }
   1036 
   1037 static int
   1038 vhead_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
   1039 {
   1040 	femarg_t	farg;
   1041 	struct fem_list	*femsp;
   1042 	int		(*func)();
   1043 	void		*arg0;
   1044 	int		errc;
   1045 
   1046 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1047 		func = (int (*)()) (vp->v_op->vop_rwlock);
   1048 		arg0 = vp;
   1049 		fem_unlock(vp->v_femhead);
   1050 		errc = (*func)(arg0, write_lock, ct);
   1051 	} else {
   1052 		fem_addref(femsp);
   1053 		fem_unlock(vp->v_femhead);
   1054 		farg.fa_vnode.vp = vp;
   1055 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1056 		vsop_find(&farg, &func, int, &arg0, vop_rwlock,
   1057 		    femop_rwlock);
   1058 		errc = (*func)(arg0, write_lock, ct);
   1059 		fem_release(femsp);
   1060 	}
   1061 	return (errc);
   1062 }
   1063 
   1064 static void
   1065 vhead_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
   1066 {
   1067 	femarg_t	farg;
   1068 	struct fem_list	*femsp;
   1069 	void		(*func)();
   1070 	void		*arg0;
   1071 
   1072 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1073 		func = (void (*)()) (vp->v_op->vop_rwunlock);
   1074 		arg0 = vp;
   1075 		fem_unlock(vp->v_femhead);
   1076 		(*func)(arg0, write_lock, ct);
   1077 	} else {
   1078 		fem_addref(femsp);
   1079 		fem_unlock(vp->v_femhead);
   1080 		farg.fa_vnode.vp = vp;
   1081 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1082 		vsop_find(&farg, &func, void, &arg0, vop_rwunlock,
   1083 		    femop_rwunlock);
   1084 		(*func)(arg0, write_lock, ct);
   1085 		fem_release(femsp);
   1086 	}
   1087 }
   1088 
   1089 static int
   1090 vhead_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
   1091 {
   1092 	femarg_t	farg;
   1093 	struct fem_list	*femsp;
   1094 	int		(*func)();
   1095 	void		*arg0;
   1096 	int		errc;
   1097 
   1098 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1099 		func = (int (*)()) (vp->v_op->vop_seek);
   1100 		arg0 = vp;
   1101 		fem_unlock(vp->v_femhead);
   1102 		errc = (*func)(arg0, ooff, noffp, ct);
   1103 	} else {
   1104 		fem_addref(femsp);
   1105 		fem_unlock(vp->v_femhead);
   1106 		farg.fa_vnode.vp = vp;
   1107 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1108 		vsop_find(&farg, &func, int, &arg0, vop_seek, femop_seek);
   1109 		errc = (*func)(arg0, ooff, noffp, ct);
   1110 		fem_release(femsp);
   1111 	}
   1112 	return (errc);
   1113 }
   1114 
   1115 static int
   1116 vhead_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
   1117 {
   1118 	femarg_t	farg;
   1119 	struct fem_list	*femsp;
   1120 	int		(*func)();
   1121 	void		*arg0;
   1122 	int		errc;
   1123 
   1124 	if ((femsp = fem_lock(vp1->v_femhead)) == NULL) {
   1125 		func = (int (*)()) (vp1->v_op->vop_cmp);
   1126 		arg0 = vp1;
   1127 		fem_unlock(vp1->v_femhead);
   1128 		errc = (*func)(arg0, vp2, ct);
   1129 	} else {
   1130 		fem_addref(femsp);
   1131 		fem_unlock(vp1->v_femhead);
   1132 		farg.fa_vnode.vp = vp1;
   1133 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1134 		vsop_find(&farg, &func, int, &arg0, vop_cmp, femop_cmp);
   1135 		errc = (*func)(arg0, vp2, ct);
   1136 		fem_release(femsp);
   1137 	}
   1138 	return (errc);
   1139 }
   1140 
   1141 static int
   1142 vhead_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
   1143 	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
   1144 	caller_context_t *ct)
   1145 {
   1146 	femarg_t	farg;
   1147 	struct fem_list	*femsp;
   1148 	int		(*func)();
   1149 	void		*arg0;
   1150 	int		errc;
   1151 
   1152 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1153 		func = (int (*)()) (vp->v_op->vop_frlock);
   1154 		arg0 = vp;
   1155 		fem_unlock(vp->v_femhead);
   1156 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
   1157 	} else {
   1158 		fem_addref(femsp);
   1159 		fem_unlock(vp->v_femhead);
   1160 		farg.fa_vnode.vp = vp;
   1161 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1162 		vsop_find(&farg, &func, int, &arg0, vop_frlock,
   1163 		    femop_frlock);
   1164 		errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
   1165 		fem_release(femsp);
   1166 	}
   1167 	return (errc);
   1168 }
   1169 
   1170 static int
   1171 vhead_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
   1172 	offset_t offset, cred_t *cr, caller_context_t *ct)
   1173 {
   1174 	femarg_t	farg;
   1175 	struct fem_list	*femsp;
   1176 	int		(*func)();
   1177 	void		*arg0;
   1178 	int		errc;
   1179 
   1180 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1181 		func = (int (*)()) (vp->v_op->vop_space);
   1182 		arg0 = vp;
   1183 		fem_unlock(vp->v_femhead);
   1184 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
   1185 	} else {
   1186 		fem_addref(femsp);
   1187 		fem_unlock(vp->v_femhead);
   1188 		farg.fa_vnode.vp = vp;
   1189 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1190 		vsop_find(&farg, &func, int, &arg0, vop_space, femop_space);
   1191 		errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
   1192 		fem_release(femsp);
   1193 	}
   1194 	return (errc);
   1195 }
   1196 
   1197 static int
   1198 vhead_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
   1199 {
   1200 	femarg_t	farg;
   1201 	struct fem_list	*femsp;
   1202 	int		(*func)();
   1203 	void		*arg0;
   1204 	int		errc;
   1205 
   1206 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1207 		func = (int (*)()) (vp->v_op->vop_realvp);
   1208 		arg0 = vp;
   1209 		fem_unlock(vp->v_femhead);
   1210 		errc = (*func)(arg0, vpp, ct);
   1211 	} else {
   1212 		fem_addref(femsp);
   1213 		fem_unlock(vp->v_femhead);
   1214 		farg.fa_vnode.vp = vp;
   1215 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1216 		vsop_find(&farg, &func, int, &arg0, vop_realvp,
   1217 		    femop_realvp);
   1218 		errc = (*func)(arg0, vpp, ct);
   1219 		fem_release(femsp);
   1220 	}
   1221 	return (errc);
   1222 }
   1223 
   1224 static int
   1225 vhead_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
   1226 	struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
   1227 	enum seg_rw rw, cred_t *cr, caller_context_t *ct)
   1228 {
   1229 	femarg_t	farg;
   1230 	struct fem_list	*femsp;
   1231 	int		(*func)();
   1232 	void		*arg0;
   1233 	int		errc;
   1234 
   1235 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1236 		func = (int (*)()) (vp->v_op->vop_getpage);
   1237 		arg0 = vp;
   1238 		fem_unlock(vp->v_femhead);
   1239 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
   1240 		    addr, rw, cr, ct);
   1241 	} else {
   1242 		fem_addref(femsp);
   1243 		fem_unlock(vp->v_femhead);
   1244 		farg.fa_vnode.vp = vp;
   1245 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1246 		vsop_find(&farg, &func, int, &arg0, vop_getpage,
   1247 		    femop_getpage);
   1248 		errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
   1249 		    addr, rw, cr, ct);
   1250 		fem_release(femsp);
   1251 	}
   1252 	return (errc);
   1253 }
   1254 
   1255 static int
   1256 vhead_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
   1257 	caller_context_t *ct)
   1258 {
   1259 	femarg_t	farg;
   1260 	struct fem_list	*femsp;
   1261 	int		(*func)();
   1262 	void		*arg0;
   1263 	int		errc;
   1264 
   1265 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1266 		func = (int (*)()) (vp->v_op->vop_putpage);
   1267 		arg0 = vp;
   1268 		fem_unlock(vp->v_femhead);
   1269 		errc = (*func)(arg0, off, len, flags, cr, ct);
   1270 	} else {
   1271 		fem_addref(femsp);
   1272 		fem_unlock(vp->v_femhead);
   1273 		farg.fa_vnode.vp = vp;
   1274 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1275 		vsop_find(&farg, &func, int, &arg0, vop_putpage,
   1276 		    femop_putpage);
   1277 		errc = (*func)(arg0, off, len, flags, cr, ct);
   1278 		fem_release(femsp);
   1279 	}
   1280 	return (errc);
   1281 }
   1282 
   1283 static int
   1284 vhead_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
   1285 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
   1286 	cred_t *cr, caller_context_t *ct)
   1287 {
   1288 	femarg_t	farg;
   1289 	struct fem_list	*femsp;
   1290 	int		(*func)();
   1291 	void		*arg0;
   1292 	int		errc;
   1293 
   1294 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1295 		func = (int (*)()) (vp->v_op->vop_map);
   1296 		arg0 = vp;
   1297 		fem_unlock(vp->v_femhead);
   1298 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
   1299 		    flags, cr, ct);
   1300 	} else {
   1301 		fem_addref(femsp);
   1302 		fem_unlock(vp->v_femhead);
   1303 		farg.fa_vnode.vp = vp;
   1304 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1305 		vsop_find(&farg, &func, int, &arg0, vop_map, femop_map);
   1306 		errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
   1307 		    flags, cr, ct);
   1308 		fem_release(femsp);
   1309 	}
   1310 	return (errc);
   1311 }
   1312 
   1313 static int
   1314 vhead_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
   1315 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
   1316 	cred_t *cr, caller_context_t *ct)
   1317 {
   1318 	femarg_t	farg;
   1319 	struct fem_list	*femsp;
   1320 	int		(*func)();
   1321 	void		*arg0;
   1322 	int		errc;
   1323 
   1324 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1325 		func = (int (*)()) (vp->v_op->vop_addmap);
   1326 		arg0 = vp;
   1327 		fem_unlock(vp->v_femhead);
   1328 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
   1329 		    flags, cr, ct);
   1330 	} else {
   1331 		fem_addref(femsp);
   1332 		fem_unlock(vp->v_femhead);
   1333 		farg.fa_vnode.vp = vp;
   1334 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1335 		vsop_find(&farg, &func, int, &arg0, vop_addmap,
   1336 		    femop_addmap);
   1337 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
   1338 		    flags, cr, ct);
   1339 		fem_release(femsp);
   1340 	}
   1341 	return (errc);
   1342 }
   1343 
   1344 static int
   1345 vhead_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
   1346 	size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
   1347 	caller_context_t *ct)
   1348 {
   1349 	femarg_t	farg;
   1350 	struct fem_list	*femsp;
   1351 	int		(*func)();
   1352 	void		*arg0;
   1353 	int		errc;
   1354 
   1355 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1356 		func = (int (*)()) (vp->v_op->vop_delmap);
   1357 		arg0 = vp;
   1358 		fem_unlock(vp->v_femhead);
   1359 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
   1360 		    flags, cr, ct);
   1361 	} else {
   1362 		fem_addref(femsp);
   1363 		fem_unlock(vp->v_femhead);
   1364 		farg.fa_vnode.vp = vp;
   1365 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1366 		vsop_find(&farg, &func, int, &arg0, vop_delmap,
   1367 		    femop_delmap);
   1368 		errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
   1369 		    flags, cr, ct);
   1370 		fem_release(femsp);
   1371 	}
   1372 	return (errc);
   1373 }
   1374 
   1375 static int
   1376 vhead_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
   1377 	struct pollhead **phpp, caller_context_t *ct)
   1378 {
   1379 	femarg_t	farg;
   1380 	struct fem_list	*femsp;
   1381 	int		(*func)();
   1382 	void		*arg0;
   1383 	int		errc;
   1384 
   1385 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1386 		func = (int (*)()) (vp->v_op->vop_poll);
   1387 		arg0 = vp;
   1388 		fem_unlock(vp->v_femhead);
   1389 		errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
   1390 	} else {
   1391 		fem_addref(femsp);
   1392 		fem_unlock(vp->v_femhead);
   1393 		farg.fa_vnode.vp = vp;
   1394 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1395 		vsop_find(&farg, &func, int, &arg0, vop_poll, femop_poll);
   1396 		errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
   1397 		fem_release(femsp);
   1398 	}
   1399 	return (errc);
   1400 }
   1401 
   1402 static int
   1403 vhead_dump(vnode_t *vp, caddr_t addr, offset_t lbdn, offset_t dblks,
   1404     caller_context_t *ct)
   1405 {
   1406 	femarg_t	farg;
   1407 	struct fem_list	*femsp;
   1408 	int		(*func)();
   1409 	void		*arg0;
   1410 	int		errc;
   1411 
   1412 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1413 		func = (int (*)()) (vp->v_op->vop_dump);
   1414 		arg0 = vp;
   1415 		fem_unlock(vp->v_femhead);
   1416 		errc = (*func)(arg0, addr, lbdn, dblks, ct);
   1417 	} else {
   1418 		fem_addref(femsp);
   1419 		fem_unlock(vp->v_femhead);
   1420 		farg.fa_vnode.vp = vp;
   1421 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1422 		vsop_find(&farg, &func, int, &arg0, vop_dump, femop_dump);
   1423 		errc = (*func)(arg0, addr, lbdn, dblks, ct);
   1424 		fem_release(femsp);
   1425 	}
   1426 	return (errc);
   1427 }
   1428 
   1429 static int
   1430 vhead_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
   1431 	caller_context_t *ct)
   1432 {
   1433 	femarg_t	farg;
   1434 	struct fem_list	*femsp;
   1435 	int		(*func)();
   1436 	void		*arg0;
   1437 	int		errc;
   1438 
   1439 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1440 		func = (int (*)()) (vp->v_op->vop_pathconf);
   1441 		arg0 = vp;
   1442 		fem_unlock(vp->v_femhead);
   1443 		errc = (*func)(arg0, cmd, valp, cr, ct);
   1444 	} else {
   1445 		fem_addref(femsp);
   1446 		fem_unlock(vp->v_femhead);
   1447 		farg.fa_vnode.vp = vp;
   1448 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1449 		vsop_find(&farg, &func, int, &arg0, vop_pathconf,
   1450 		    femop_pathconf);
   1451 		errc = (*func)(arg0, cmd, valp, cr, ct);
   1452 		fem_release(femsp);
   1453 	}
   1454 	return (errc);
   1455 }
   1456 
   1457 static int
   1458 vhead_pageio(vnode_t *vp, struct page *pp, u_offset_t io_off,
   1459 	size_t io_len, int flags, cred_t *cr, caller_context_t *ct)
   1460 {
   1461 	femarg_t	farg;
   1462 	struct fem_list	*femsp;
   1463 	int		(*func)();
   1464 	void		*arg0;
   1465 	int		errc;
   1466 
   1467 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1468 		func = (int (*)()) (vp->v_op->vop_pageio);
   1469 		arg0 = vp;
   1470 		fem_unlock(vp->v_femhead);
   1471 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
   1472 	} else {
   1473 		fem_addref(femsp);
   1474 		fem_unlock(vp->v_femhead);
   1475 		farg.fa_vnode.vp = vp;
   1476 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1477 		vsop_find(&farg, &func, int, &arg0, vop_pageio,
   1478 		    femop_pageio);
   1479 		errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
   1480 		fem_release(femsp);
   1481 	}
   1482 	return (errc);
   1483 }
   1484 
   1485 static int
   1486 vhead_dumpctl(vnode_t *vp, int action, offset_t *blkp, caller_context_t *ct)
   1487 {
   1488 	femarg_t	farg;
   1489 	struct fem_list	*femsp;
   1490 	int		(*func)();
   1491 	void		*arg0;
   1492 	int		errc;
   1493 
   1494 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1495 		func = (int (*)()) (vp->v_op->vop_dumpctl);
   1496 		arg0 = vp;
   1497 		fem_unlock(vp->v_femhead);
   1498 		errc = (*func)(arg0, action, blkp, ct);
   1499 	} else {
   1500 		fem_addref(femsp);
   1501 		fem_unlock(vp->v_femhead);
   1502 		farg.fa_vnode.vp = vp;
   1503 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1504 		vsop_find(&farg, &func, int, &arg0, vop_dumpctl,
   1505 		    femop_dumpctl);
   1506 		errc = (*func)(arg0, action, blkp, ct);
   1507 		fem_release(femsp);
   1508 	}
   1509 	return (errc);
   1510 }
   1511 
   1512 static void
   1513 vhead_dispose(vnode_t *vp, struct page *pp, int flag, int dn, cred_t *cr,
   1514 	caller_context_t *ct)
   1515 {
   1516 	femarg_t	farg;
   1517 	struct fem_list	*femsp;
   1518 	void		(*func)();
   1519 	void		*arg0;
   1520 
   1521 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1522 		func = (void (*)()) (vp->v_op->vop_dispose);
   1523 		arg0 = vp;
   1524 		fem_unlock(vp->v_femhead);
   1525 		(*func)(arg0, pp, flag, dn, cr, ct);
   1526 	} else {
   1527 		fem_addref(femsp);
   1528 		fem_unlock(vp->v_femhead);
   1529 		farg.fa_vnode.vp = vp;
   1530 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1531 		vsop_find(&farg, &func, void, &arg0, vop_dispose,
   1532 		    femop_dispose);
   1533 		(*func)(arg0, pp, flag, dn, cr, ct);
   1534 		fem_release(femsp);
   1535 	}
   1536 }
   1537 
   1538 static int
   1539 vhead_setsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
   1540 	caller_context_t *ct)
   1541 {
   1542 	femarg_t	farg;
   1543 	struct fem_list	*femsp;
   1544 	int		(*func)();
   1545 	void		*arg0;
   1546 	int		errc;
   1547 
   1548 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1549 		func = (int (*)()) (vp->v_op->vop_setsecattr);
   1550 		arg0 = vp;
   1551 		fem_unlock(vp->v_femhead);
   1552 		errc = (*func)(arg0, vsap, flag, cr, ct);
   1553 	} else {
   1554 		fem_addref(femsp);
   1555 		fem_unlock(vp->v_femhead);
   1556 		farg.fa_vnode.vp = vp;
   1557 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1558 		vsop_find(&farg, &func, int, &arg0, vop_setsecattr,
   1559 		    femop_setsecattr);
   1560 		errc = (*func)(arg0, vsap, flag, cr, ct);
   1561 		fem_release(femsp);
   1562 	}
   1563 	return (errc);
   1564 }
   1565 
   1566 static int
   1567 vhead_getsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
   1568 	caller_context_t *ct)
   1569 {
   1570 	femarg_t	farg;
   1571 	struct fem_list	*femsp;
   1572 	int		(*func)();
   1573 	void		*arg0;
   1574 	int		errc;
   1575 
   1576 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1577 		func = (int (*)()) (vp->v_op->vop_getsecattr);
   1578 		arg0 = vp;
   1579 		fem_unlock(vp->v_femhead);
   1580 		errc = (*func)(arg0, vsap, flag, cr, ct);
   1581 	} else {
   1582 		fem_addref(femsp);
   1583 		fem_unlock(vp->v_femhead);
   1584 		farg.fa_vnode.vp = vp;
   1585 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1586 		vsop_find(&farg, &func, int, &arg0, vop_getsecattr,
   1587 		    femop_getsecattr);
   1588 		errc = (*func)(arg0, vsap, flag, cr, ct);
   1589 		fem_release(femsp);
   1590 	}
   1591 	return (errc);
   1592 }
   1593 
   1594 static int
   1595 vhead_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag,
   1596 	cred_t *cr, caller_context_t *ct)
   1597 {
   1598 	femarg_t	farg;
   1599 	struct fem_list	*femsp;
   1600 	int		(*func)();
   1601 	void		*arg0;
   1602 	int		errc;
   1603 
   1604 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1605 		func = (int (*)()) (vp->v_op->vop_shrlock);
   1606 		arg0 = vp;
   1607 		fem_unlock(vp->v_femhead);
   1608 		errc = (*func)(arg0, cmd, shr, flag, cr, ct);
   1609 	} else {
   1610 		fem_addref(femsp);
   1611 		fem_unlock(vp->v_femhead);
   1612 		farg.fa_vnode.vp = vp;
   1613 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1614 		vsop_find(&farg, &func, int, &arg0, vop_shrlock,
   1615 		    femop_shrlock);
   1616 		errc = (*func)(arg0, cmd, shr, flag, cr, ct);
   1617 		fem_release(femsp);
   1618 	}
   1619 	return (errc);
   1620 }
   1621 
   1622 static int
   1623 vhead_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *cname,
   1624     caller_context_t *ct)
   1625 {
   1626 	femarg_t	farg;
   1627 	struct fem_list	*femsp;
   1628 	int		(*func)();
   1629 	void		*arg0;
   1630 	int		errc;
   1631 
   1632 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1633 		func = (int (*)()) (vp->v_op->vop_vnevent);
   1634 		arg0 = vp;
   1635 		fem_unlock(vp->v_femhead);
   1636 		errc = (*func)(arg0, vnevent, dvp, cname, ct);
   1637 	} else {
   1638 		fem_addref(femsp);
   1639 		fem_unlock(vp->v_femhead);
   1640 		farg.fa_vnode.vp = vp;
   1641 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1642 		vsop_find(&farg, &func, int, &arg0, vop_vnevent,
   1643 		    femop_vnevent);
   1644 		errc = (*func)(arg0, vnevent, dvp, cname, ct);
   1645 		fem_release(femsp);
   1646 	}
   1647 	return (errc);
   1648 }
   1649 
   1650 static int
   1651 vhead_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuiop, cred_t *cr,
   1652     caller_context_t *ct)
   1653 {
   1654 	femarg_t	farg;
   1655 	struct fem_list	*femsp;
   1656 	int		(*func)();
   1657 	void		*arg0;
   1658 	int		errc;
   1659 
   1660 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1661 		func = (int (*)()) (vp->v_op->vop_reqzcbuf);
   1662 		arg0 = vp;
   1663 		fem_unlock(vp->v_femhead);
   1664 		errc = (*func)(arg0, ioflag, xuiop, cr, ct);
   1665 	} else {
   1666 		fem_addref(femsp);
   1667 		fem_unlock(vp->v_femhead);
   1668 		farg.fa_vnode.vp = vp;
   1669 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1670 		vsop_find(&farg, &func, int, &arg0, vop_reqzcbuf,
   1671 		    femop_reqzcbuf);
   1672 		errc = (*func)(arg0, ioflag, xuiop, cr, ct);
   1673 		fem_release(femsp);
   1674 	}
   1675 	return (errc);
   1676 }
   1677 
   1678 static int
   1679 vhead_retzcbuf(vnode_t *vp, xuio_t *xuiop, cred_t *cr, caller_context_t *ct)
   1680 {
   1681 	femarg_t	farg;
   1682 	struct fem_list	*femsp;
   1683 	int		(*func)();
   1684 	void		*arg0;
   1685 	int		errc;
   1686 
   1687 	if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
   1688 		func = (int (*)()) (vp->v_op->vop_retzcbuf);
   1689 		arg0 = vp;
   1690 		fem_unlock(vp->v_femhead);
   1691 		errc = (*func)(arg0, xuiop, cr, ct);
   1692 	} else {
   1693 		fem_addref(femsp);
   1694 		fem_unlock(vp->v_femhead);
   1695 		farg.fa_vnode.vp = vp;
   1696 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1697 		vsop_find(&farg, &func, int, &arg0, vop_retzcbuf,
   1698 		    femop_retzcbuf);
   1699 		errc = (*func)(arg0, xuiop, cr, ct);
   1700 		fem_release(femsp);
   1701 	}
   1702 	return (errc);
   1703 }
   1704 
   1705 static int
   1706 fshead_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
   1707 {
   1708 	fsemarg_t	farg;
   1709 	struct fem_list	*femsp;
   1710 	int		(*func)();
   1711 	void		*arg0;
   1712 	int		errc;
   1713 
   1714 	ASSERT(vfsp->vfs_implp);
   1715 
   1716 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1717 		func = (int (*)()) vfsp->vfs_op->vfs_mount;
   1718 		fem_unlock(vfsp->vfs_femhead);
   1719 		errc = (*func)(vfsp, mvp, uap, cr);
   1720 	} else {
   1721 		fem_addref(femsp);
   1722 		fem_unlock(vfsp->vfs_femhead);
   1723 		farg.fa_vnode.vfsp = vfsp;
   1724 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1725 		vfsop_find(&farg, &func, int, &arg0, vfs_mount,
   1726 		    fsemop_mount);
   1727 		errc = (*func)(arg0, mvp, uap, cr);
   1728 		fem_release(femsp);
   1729 	}
   1730 	return (errc);
   1731 }
   1732 
   1733 static int
   1734 fshead_unmount(vfs_t *vfsp, int flag, cred_t *cr)
   1735 {
   1736 	fsemarg_t	farg;
   1737 	struct fem_list	*femsp;
   1738 	int		(*func)();
   1739 	void		*arg0;
   1740 	int		errc;
   1741 
   1742 	ASSERT(vfsp->vfs_implp);
   1743 
   1744 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1745 		func = (int (*)()) vfsp->vfs_op->vfs_unmount;
   1746 		fem_unlock(vfsp->vfs_femhead);
   1747 		errc = (*func)(vfsp, flag, cr);
   1748 	} else {
   1749 		fem_addref(femsp);
   1750 		fem_unlock(vfsp->vfs_femhead);
   1751 		farg.fa_vnode.vfsp = vfsp;
   1752 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1753 		vfsop_find(&farg, &func, int, &arg0, vfs_unmount,
   1754 		    fsemop_unmount);
   1755 		errc = (*func)(arg0, flag, cr);
   1756 		fem_release(femsp);
   1757 	}
   1758 	return (errc);
   1759 }
   1760 
   1761 static int
   1762 fshead_root(vfs_t *vfsp, vnode_t **vpp)
   1763 {
   1764 	fsemarg_t	farg;
   1765 	struct fem_list	*femsp;
   1766 	int		(*func)();
   1767 	void		*arg0;
   1768 	int		errc;
   1769 
   1770 	ASSERT(vfsp->vfs_implp);
   1771 
   1772 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1773 		func = (int (*)()) vfsp->vfs_op->vfs_root;
   1774 		fem_unlock(vfsp->vfs_femhead);
   1775 		errc = (*func)(vfsp, vpp);
   1776 	} else {
   1777 		fem_addref(femsp);
   1778 		fem_unlock(vfsp->vfs_femhead);
   1779 		farg.fa_vnode.vfsp = vfsp;
   1780 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1781 		vfsop_find(&farg, &func, int, &arg0, vfs_root, fsemop_root);
   1782 		errc = (*func)(arg0, vpp);
   1783 		fem_release(femsp);
   1784 	}
   1785 	return (errc);
   1786 }
   1787 
   1788 static int
   1789 fshead_statvfs(vfs_t *vfsp, statvfs64_t *sp)
   1790 {
   1791 	fsemarg_t	farg;
   1792 	struct fem_list	*femsp;
   1793 	int		(*func)();
   1794 	void		*arg0;
   1795 	int		errc;
   1796 
   1797 	ASSERT(vfsp->vfs_implp);
   1798 
   1799 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1800 		func = (int (*)()) vfsp->vfs_op->vfs_statvfs;
   1801 		fem_unlock(vfsp->vfs_femhead);
   1802 		errc = (*func)(vfsp, sp);
   1803 	} else {
   1804 		fem_addref(femsp);
   1805 		fem_unlock(vfsp->vfs_femhead);
   1806 		farg.fa_vnode.vfsp = vfsp;
   1807 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1808 		vfsop_find(&farg, &func, int, &arg0, vfs_statvfs,
   1809 		    fsemop_statvfs);
   1810 		errc = (*func)(arg0, sp);
   1811 		fem_release(femsp);
   1812 	}
   1813 	return (errc);
   1814 }
   1815 
   1816 static int
   1817 fshead_sync(vfs_t *vfsp, short flag, cred_t *cr)
   1818 {
   1819 	fsemarg_t	farg;
   1820 	struct fem_list	*femsp;
   1821 	int		(*func)();
   1822 	void		*arg0;
   1823 	int		errc;
   1824 
   1825 	ASSERT(vfsp->vfs_implp);
   1826 
   1827 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1828 		func = (int (*)()) vfsp->vfs_op->vfs_sync;
   1829 		fem_unlock(vfsp->vfs_femhead);
   1830 		errc = (*func)(vfsp, flag, cr);
   1831 	} else {
   1832 		fem_addref(femsp);
   1833 		fem_unlock(vfsp->vfs_femhead);
   1834 		farg.fa_vnode.vfsp = vfsp;
   1835 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1836 		vfsop_find(&farg, &func, int, &arg0, vfs_sync, fsemop_sync);
   1837 		errc = (*func)(arg0, flag, cr);
   1838 		fem_release(femsp);
   1839 	}
   1840 	return (errc);
   1841 }
   1842 
   1843 static int
   1844 fshead_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
   1845 {
   1846 	fsemarg_t	farg;
   1847 	struct fem_list	*femsp;
   1848 	int		(*func)();
   1849 	void		*arg0;
   1850 	int		errc;
   1851 
   1852 	ASSERT(vfsp->vfs_implp);
   1853 
   1854 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1855 		func = (int (*)()) vfsp->vfs_op->vfs_vget;
   1856 		fem_unlock(vfsp->vfs_femhead);
   1857 		errc = (*func)(vfsp, vpp, fidp);
   1858 	} else {
   1859 		fem_addref(femsp);
   1860 		fem_unlock(vfsp->vfs_femhead);
   1861 		farg.fa_vnode.vfsp = vfsp;
   1862 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1863 		vfsop_find(&farg, &func, int, &arg0, vfs_vget, fsemop_vget);
   1864 		errc = (*func)(arg0, vpp, fidp);
   1865 		fem_release(femsp);
   1866 	}
   1867 	return (errc);
   1868 }
   1869 
   1870 static int
   1871 fshead_mountroot(vfs_t *vfsp, enum whymountroot reason)
   1872 {
   1873 	fsemarg_t	farg;
   1874 	struct fem_list	*femsp;
   1875 	int		(*func)();
   1876 	void		*arg0;
   1877 	int		errc;
   1878 
   1879 	ASSERT(vfsp->vfs_implp);
   1880 
   1881 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1882 		func = (int (*)()) vfsp->vfs_op->vfs_mountroot;
   1883 		fem_unlock(vfsp->vfs_femhead);
   1884 		errc = (*func)(vfsp, reason);
   1885 	} else {
   1886 		fem_addref(femsp);
   1887 		fem_unlock(vfsp->vfs_femhead);
   1888 		farg.fa_vnode.vfsp = vfsp;
   1889 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1890 		vfsop_find(&farg, &func, int, &arg0, vfs_mountroot,
   1891 		    fsemop_mountroot);
   1892 		errc = (*func)(arg0, reason);
   1893 		fem_release(femsp);
   1894 	}
   1895 	return (errc);
   1896 }
   1897 
   1898 static void
   1899 fshead_freevfs(vfs_t *vfsp)
   1900 {
   1901 	fsemarg_t	farg;
   1902 	struct fem_list	*femsp;
   1903 	void		(*func)();
   1904 	void		*arg0;
   1905 
   1906 	ASSERT(vfsp->vfs_implp);
   1907 
   1908 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1909 		func = (void (*)()) vfsp->vfs_op->vfs_freevfs;
   1910 		fem_unlock(vfsp->vfs_femhead);
   1911 		(*func)(vfsp);
   1912 	} else {
   1913 		fem_addref(femsp);
   1914 		fem_unlock(vfsp->vfs_femhead);
   1915 		farg.fa_vnode.vfsp = vfsp;
   1916 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1917 		vfsop_find(&farg, &func, void, &arg0, vfs_freevfs,
   1918 		    fsemop_freevfs);
   1919 		(*func)(arg0);
   1920 		fem_release(femsp);
   1921 	}
   1922 }
   1923 
   1924 static int
   1925 fshead_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
   1926 {
   1927 	fsemarg_t	farg;
   1928 	struct fem_list	*femsp;
   1929 	int		(*func)();
   1930 	void		*arg0;
   1931 	int		errc;
   1932 
   1933 	ASSERT(vfsp->vfs_implp);
   1934 
   1935 	if ((femsp = fem_lock(vfsp->vfs_femhead)) == NULL) {
   1936 		func = (int (*)()) vfsp->vfs_op->vfs_vnstate;
   1937 		fem_unlock(vfsp->vfs_femhead);
   1938 		errc = (*func)(vfsp, vp, nstate);
   1939 	} else {
   1940 		fem_addref(femsp);
   1941 		fem_unlock(vfsp->vfs_femhead);
   1942 		farg.fa_vnode.vfsp = vfsp;
   1943 		farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
   1944 		vfsop_find(&farg, &func, int, &arg0, vfs_vnstate,
   1945 		    fsemop_vnstate);
   1946 		errc = (*func)(arg0, vp, nstate);
   1947 		fem_release(femsp);
   1948 	}
   1949 	return (errc);
   1950 }
   1951 
   1952 
   1953 /*
   1954  * specification table for the vhead vnode operations.
   1955  * It is an error for any operations to be missing.
   1956  */
   1957 
   1958 static struct fs_operation_def fhead_vn_spec[] = {
   1959 	{ VOPNAME_OPEN, (femop_t *)vhead_open },
   1960 	{ VOPNAME_CLOSE, (femop_t *)vhead_close },
   1961 	{ VOPNAME_READ, (femop_t *)vhead_read },
   1962 	{ VOPNAME_WRITE, (femop_t *)vhead_write },
   1963 	{ VOPNAME_IOCTL, (femop_t *)vhead_ioctl },
   1964 	{ VOPNAME_SETFL, (femop_t *)vhead_setfl },
   1965 	{ VOPNAME_GETATTR, (femop_t *)vhead_getattr },
   1966 	{ VOPNAME_SETATTR, (femop_t *)vhead_setattr },
   1967 	{ VOPNAME_ACCESS, (femop_t *)vhead_access },
   1968 	{ VOPNAME_LOOKUP, (femop_t *)vhead_lookup },
   1969 	{ VOPNAME_CREATE, (femop_t *)vhead_create },
   1970 	{ VOPNAME_REMOVE, (femop_t *)vhead_remove },
   1971 	{ VOPNAME_LINK, (femop_t *)vhead_link },
   1972 	{ VOPNAME_RENAME, (femop_t *)vhead_rename },
   1973 	{ VOPNAME_MKDIR, (femop_t *)vhead_mkdir },
   1974 	{ VOPNAME_RMDIR, (femop_t *)vhead_rmdir },
   1975 	{ VOPNAME_READDIR, (femop_t *)vhead_readdir },
   1976 	{ VOPNAME_SYMLINK, (femop_t *)vhead_symlink },
   1977 	{ VOPNAME_READLINK, (femop_t *)vhead_readlink },
   1978 	{ VOPNAME_FSYNC, (femop_t *)vhead_fsync },
   1979 	{ VOPNAME_INACTIVE, (femop_t *)vhead_inactive },
   1980 	{ VOPNAME_FID, (femop_t *)vhead_fid },
   1981 	{ VOPNAME_RWLOCK, (femop_t *)vhead_rwlock },
   1982 	{ VOPNAME_RWUNLOCK, (femop_t *)vhead_rwunlock },
   1983 	{ VOPNAME_SEEK, (femop_t *)vhead_seek },
   1984 	{ VOPNAME_CMP, (femop_t *)vhead_cmp },
   1985 	{ VOPNAME_FRLOCK, (femop_t *)vhead_frlock },
   1986 	{ VOPNAME_SPACE, (femop_t *)vhead_space },
   1987 	{ VOPNAME_REALVP, (femop_t *)vhead_realvp },
   1988 	{ VOPNAME_GETPAGE, (femop_t *)vhead_getpage },
   1989 	{ VOPNAME_PUTPAGE, (femop_t *)vhead_putpage },
   1990 	{ VOPNAME_MAP, (femop_t *)vhead_map },
   1991 	{ VOPNAME_ADDMAP, (femop_t *)vhead_addmap },
   1992 	{ VOPNAME_DELMAP, (femop_t *)vhead_delmap },
   1993 	{ VOPNAME_POLL, (femop_t *)vhead_poll },
   1994 	{ VOPNAME_DUMP, (femop_t *)vhead_dump },
   1995 	{ VOPNAME_PATHCONF, (femop_t *)vhead_pathconf },
   1996 	{ VOPNAME_PAGEIO, (femop_t *)vhead_pageio },
   1997 	{ VOPNAME_DUMPCTL, (femop_t *)vhead_dumpctl },
   1998 	{ VOPNAME_DISPOSE, (femop_t *)vhead_dispose },
   1999 	{ VOPNAME_SETSECATTR, (femop_t *)vhead_setsecattr },
   2000 	{ VOPNAME_GETSECATTR, (femop_t *)vhead_getsecattr },
   2001 	{ VOPNAME_SHRLOCK, (femop_t *)vhead_shrlock },
   2002 	{ VOPNAME_VNEVENT, (femop_t *)vhead_vnevent },
   2003 	{ VOPNAME_REQZCBUF, (femop_t *)vhead_reqzcbuf },
   2004 	{ VOPNAME_RETZCBUF, (femop_t *)vhead_retzcbuf },
   2005 	{	NULL,	NULL	}
   2006 };
   2007 
   2008 /*
   2009  * specification table for the vfshead vnode operations.
   2010  * It is an error for any operations to be missing.
   2011  */
   2012 
   2013 static struct fs_operation_def fshead_vfs_spec[]  = {
   2014 	{ VFSNAME_MOUNT, (femop_t *)fshead_mount },
   2015 	{ VFSNAME_UNMOUNT, (femop_t *)fshead_unmount },
   2016 	{ VFSNAME_ROOT, (femop_t *)fshead_root },
   2017 	{ VFSNAME_STATVFS, (femop_t *)fshead_statvfs },
   2018 	{ VFSNAME_SYNC, (femop_t *)fshead_sync },
   2019 	{ VFSNAME_VGET, (femop_t *)fshead_vget },
   2020 	{ VFSNAME_MOUNTROOT, (femop_t *)fshead_mountroot },
   2021 	{ VFSNAME_FREEVFS, (femop_t *)fshead_freevfs },
   2022 	{ VFSNAME_VNSTATE, (femop_t *)fshead_vnstate },
   2023 	{	NULL,	NULL	}
   2024 };
   2025 
   2026 /*
   2027  * This set of routines transfer control to the next stacked monitor.
   2028  *
   2029  * Each routine is identical except for naming, types and arguments.
   2030  *
   2031  * The basic steps are:
   2032  * 1.  Decrease the stack pointer by one.
   2033  * 2.  If the current item is a base operation (vnode, vfs), goto 5.
   2034  * 3.  If the current item does not have a corresponding operation, goto 1
   2035  * 4.  Return by invoking the current item with the argument handle.
   2036  * 5.  Return by invoking the base operation with the base object.
   2037  *
   2038  * for each classification, there needs to be at least one "next" operation
   2039  * for each "head"operation.
   2040  *
   2041  */
   2042 
   2043 int
   2044 vnext_open(femarg_t *vf, int mode, cred_t *cr, caller_context_t *ct)
   2045 {
   2046 	int (*func)() = NULL;
   2047 	void *arg0 = NULL;
   2048 
   2049 	ASSERT(vf != NULL);
   2050 	vf->fa_fnode--;
   2051 	vsop_find(vf, &func, int, &arg0, vop_open, femop_open);
   2052 	ASSERT(func != NULL);
   2053 	ASSERT(arg0 != NULL);
   2054 	return ((*func)(arg0, mode, cr, ct));
   2055 }
   2056 
   2057 int
   2058 vnext_close(femarg_t *vf, int flag, int count, offset_t offset, cred_t *cr,
   2059 	caller_context_t *ct)
   2060 {
   2061 	int (*func)() = NULL;
   2062 	void *arg0 = NULL;
   2063 
   2064 	ASSERT(vf != NULL);
   2065 	vf->fa_fnode--;
   2066 	vsop_find(vf, &func, int, &arg0, vop_close, femop_close);
   2067 	ASSERT(func != NULL);
   2068 	ASSERT(arg0 != NULL);
   2069 	return ((*func)(arg0, flag, count, offset, cr, ct));
   2070 }
   2071 
   2072 int
   2073 vnext_read(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
   2074 	caller_context_t *ct)
   2075 {
   2076 	int (*func)() = NULL;
   2077 	void *arg0 = NULL;
   2078 
   2079 	ASSERT(vf != NULL);
   2080 	vf->fa_fnode--;
   2081 	vsop_find(vf, &func, int, &arg0, vop_read, femop_read);
   2082 	ASSERT(func != NULL);
   2083 	ASSERT(arg0 != NULL);
   2084 	return ((*func)(arg0, uiop, ioflag, cr, ct));
   2085 }
   2086 
   2087 int
   2088 vnext_write(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
   2089 	caller_context_t *ct)
   2090 {
   2091 	int (*func)() = NULL;
   2092 	void *arg0 = NULL;
   2093 
   2094 	ASSERT(vf != NULL);
   2095 	vf->fa_fnode--;
   2096 	vsop_find(vf, &func, int, &arg0, vop_write, femop_write);
   2097 	ASSERT(func != NULL);
   2098 	ASSERT(arg0 != NULL);
   2099 	return ((*func)(arg0, uiop, ioflag, cr, ct));
   2100 }
   2101 
   2102 int
   2103 vnext_ioctl(femarg_t *vf, int cmd, intptr_t arg, int flag, cred_t *cr,
   2104 	int *rvalp, caller_context_t *ct)
   2105 {
   2106 	int (*func)() = NULL;
   2107 	void *arg0 = NULL;
   2108 
   2109 	ASSERT(vf != NULL);
   2110 	vf->fa_fnode--;
   2111 	vsop_find(vf, &func, int, &arg0, vop_ioctl, femop_ioctl);
   2112 	ASSERT(func != NULL);
   2113 	ASSERT(arg0 != NULL);
   2114 	return ((*func)(arg0, cmd, arg, flag, cr, rvalp, ct));
   2115 }
   2116 
   2117 int
   2118 vnext_setfl(femarg_t *vf, int oflags, int nflags, cred_t *cr,
   2119 	caller_context_t *ct)
   2120 {
   2121 	int (*func)() = NULL;
   2122 	void *arg0 = NULL;
   2123 
   2124 	ASSERT(vf != NULL);
   2125 	vf->fa_fnode--;
   2126 	vsop_find(vf, &func, int, &arg0, vop_setfl, femop_setfl);
   2127 	ASSERT(func != NULL);
   2128 	ASSERT(arg0 != NULL);
   2129 	return ((*func)(arg0, oflags, nflags, cr, ct));
   2130 }
   2131 
   2132 int
   2133 vnext_getattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
   2134 	caller_context_t *ct)
   2135 {
   2136 	int (*func)() = NULL;
   2137 	void *arg0 = NULL;
   2138 
   2139 	ASSERT(vf != NULL);
   2140 	vf->fa_fnode--;
   2141 	vsop_find(vf, &func, int, &arg0, vop_getattr, femop_getattr);
   2142 	ASSERT(func != NULL);
   2143 	ASSERT(arg0 != NULL);
   2144 	return ((*func)(arg0, vap, flags, cr, ct));
   2145 }
   2146 
   2147 int
   2148 vnext_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
   2149 	caller_context_t *ct)
   2150 {
   2151 	int (*func)() = NULL;
   2152 	void *arg0 = NULL;
   2153 
   2154 	ASSERT(vf != NULL);
   2155 	vf->fa_fnode--;
   2156 	vsop_find(vf, &func, int, &arg0, vop_setattr, femop_setattr);
   2157 	ASSERT(func != NULL);
   2158 	ASSERT(arg0 != NULL);
   2159 	return ((*func)(arg0, vap, flags, cr, ct));
   2160 }
   2161 
   2162 int
   2163 vnext_access(femarg_t *vf, int mode, int flags, cred_t *cr,
   2164 	caller_context_t *ct)
   2165 {
   2166 	int (*func)() = NULL;
   2167 	void *arg0 = NULL;
   2168 
   2169 	ASSERT(vf != NULL);
   2170 	vf->fa_fnode--;
   2171 	vsop_find(vf, &func, int, &arg0, vop_access, femop_access);
   2172 	ASSERT(func != NULL);
   2173 	ASSERT(arg0 != NULL);
   2174 	return ((*func)(arg0, mode, flags, cr, ct));
   2175 }
   2176 
   2177 int
   2178 vnext_lookup(femarg_t *vf, char *nm, vnode_t **vpp, pathname_t *pnp,
   2179 	int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
   2180 	int *direntflags, pathname_t *realpnp)
   2181 {
   2182 	int (*func)() = NULL;
   2183 	void *arg0 = NULL;
   2184 
   2185 	ASSERT(vf != NULL);
   2186 	vf->fa_fnode--;
   2187 	vsop_find(vf, &func, int, &arg0, vop_lookup, femop_lookup);
   2188 	ASSERT(func != NULL);
   2189 	ASSERT(arg0 != NULL);
   2190 	return ((*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
   2191 	    direntflags, realpnp));
   2192 }
   2193 
   2194 int
   2195 vnext_create(femarg_t *vf, char *name, vattr_t *vap, vcexcl_t excl,
   2196 	int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
   2197 	vsecattr_t *vsecp)
   2198 {
   2199 	int (*func)() = NULL;
   2200 	void *arg0 = NULL;
   2201 
   2202 	ASSERT(vf != NULL);
   2203 	vf->fa_fnode--;
   2204 	vsop_find(vf, &func, int, &arg0, vop_create, femop_create);
   2205 	ASSERT(func != NULL);
   2206 	ASSERT(arg0 != NULL);
   2207 	return ((*func)(arg0, name, vap, excl, mode, vpp, cr, flag, ct, vsecp));
   2208 }
   2209 
   2210 int
   2211 vnext_remove(femarg_t *vf, char *nm, cred_t *cr, caller_context_t *ct,
   2212 	int flags)
   2213 {
   2214 	int (*func)() = NULL;
   2215 	void *arg0 = NULL;
   2216 
   2217 	ASSERT(vf != NULL);
   2218 	vf->fa_fnode--;
   2219 	vsop_find(vf, &func, int, &arg0, vop_remove, femop_remove);
   2220 	ASSERT(func != NULL);
   2221 	ASSERT(arg0 != NULL);
   2222 	return ((*func)(arg0, nm, cr, ct, flags));
   2223 }
   2224 
   2225 int
   2226 vnext_link(femarg_t *vf, vnode_t *svp, char *tnm, cred_t *cr,
   2227 	caller_context_t *ct, int flags)
   2228 {
   2229 	int (*func)() = NULL;
   2230 	void *arg0 = NULL;
   2231 
   2232 	ASSERT(vf != NULL);
   2233 	vf->fa_fnode--;
   2234 	vsop_find(vf, &func, int, &arg0, vop_link, femop_link);
   2235 	ASSERT(func != NULL);
   2236 	ASSERT(arg0 != NULL);
   2237 	return ((*func)(arg0, svp, tnm, cr, ct, flags));
   2238 }
   2239 
   2240 int
   2241 vnext_rename(femarg_t *vf, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
   2242 	caller_context_t *ct, int flags)
   2243 {
   2244 	int (*func)() = NULL;
   2245 	void *arg0 = NULL;
   2246 
   2247 	ASSERT(vf != NULL);
   2248 	vf->fa_fnode--;
   2249 	vsop_find(vf, &func, int, &arg0, vop_rename, femop_rename);
   2250 	ASSERT(func != NULL);
   2251 	ASSERT(arg0 != NULL);
   2252 	return ((*func)(arg0, snm, tdvp, tnm, cr, ct, flags));
   2253 }
   2254 
   2255 int
   2256 vnext_mkdir(femarg_t *vf, char *dirname, vattr_t *vap, vnode_t **vpp,
   2257 	cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
   2258 {
   2259 	int (*func)() = NULL;
   2260 	void *arg0 = NULL;
   2261 
   2262 	ASSERT(vf != NULL);
   2263 	vf->fa_fnode--;
   2264 	vsop_find(vf, &func, int, &arg0, vop_mkdir, femop_mkdir);
   2265 	ASSERT(func != NULL);
   2266 	ASSERT(arg0 != NULL);
   2267 	return ((*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp));
   2268 }
   2269 
   2270 int
   2271 vnext_rmdir(femarg_t *vf, char *nm, vnode_t *cdir, cred_t *cr,
   2272 	caller_context_t *ct, int flags)
   2273 {
   2274 	int (*func)() = NULL;
   2275 	void *arg0 = NULL;
   2276 
   2277 	ASSERT(vf != NULL);
   2278 	vf->fa_fnode--;
   2279 	vsop_find(vf, &func, int, &arg0, vop_rmdir, femop_rmdir);
   2280 	ASSERT(func != NULL);
   2281 	ASSERT(arg0 != NULL);
   2282 	return ((*func)(arg0, nm, cdir, cr, ct, flags));
   2283 }
   2284 
   2285 int
   2286 vnext_readdir(femarg_t *vf, uio_t *uiop, cred_t *cr, int *eofp,
   2287 	caller_context_t *ct, int flags)
   2288 {
   2289 	int (*func)() = NULL;
   2290 	void *arg0 = NULL;
   2291 
   2292 	ASSERT(vf != NULL);
   2293 	vf->fa_fnode--;
   2294 	vsop_find(vf, &func, int, &arg0, vop_readdir, femop_readdir);
   2295 	ASSERT(func != NULL);
   2296 	ASSERT(arg0 != NULL);
   2297 	return ((*func)(arg0, uiop, cr, eofp, ct, flags));
   2298 }
   2299 
   2300 int
   2301 vnext_symlink(femarg_t *vf, char *linkname, vattr_t *vap, char *target,
   2302 	cred_t *cr, caller_context_t *ct, int flags)
   2303 {
   2304 	int (*func)() = NULL;
   2305 	void *arg0 = NULL;
   2306 
   2307 	ASSERT(vf != NULL);
   2308 	vf->fa_fnode--;
   2309 	vsop_find(vf, &func, int, &arg0, vop_symlink, femop_symlink);
   2310 	ASSERT(func != NULL);
   2311 	ASSERT(arg0 != NULL);
   2312 	return ((*func)(arg0, linkname, vap, target, cr, ct, flags));
   2313 }
   2314 
   2315 int
   2316 vnext_readlink(femarg_t *vf, uio_t *uiop, cred_t *cr, caller_context_t *ct)
   2317 {
   2318 	int (*func)() = NULL;
   2319 	void *arg0 = NULL;
   2320 
   2321 	ASSERT(vf != NULL);
   2322 	vf->fa_fnode--;
   2323 	vsop_find(vf, &func, int, &arg0, vop_readlink, femop_readlink);
   2324 	ASSERT(func != NULL);
   2325 	ASSERT(arg0 != NULL);
   2326 	return ((*func)(arg0, uiop, cr, ct));
   2327 }
   2328 
   2329 int
   2330 vnext_fsync(femarg_t *vf, int syncflag, cred_t *cr, caller_context_t *ct)
   2331 {
   2332 	int (*func)() = NULL;
   2333 	void *arg0 = NULL;
   2334 
   2335 	ASSERT(vf != NULL);
   2336 	vf->fa_fnode--;
   2337 	vsop_find(vf, &func, int, &arg0, vop_fsync, femop_fsync);
   2338 	ASSERT(func != NULL);
   2339 	ASSERT(arg0 != NULL);
   2340 	return ((*func)(arg0, syncflag, cr, ct));
   2341 }
   2342 
   2343 void
   2344 vnext_inactive(femarg_t *vf, cred_t *cr, caller_context_t *ct)
   2345 {
   2346 	void (*func)() = NULL;
   2347 	void *arg0 = NULL;
   2348 
   2349 	ASSERT(vf != NULL);
   2350 	vf->fa_fnode--;
   2351 	vsop_find(vf, &func, void, &arg0, vop_inactive, femop_inactive);
   2352 	ASSERT(func != NULL);
   2353 	ASSERT(arg0 != NULL);
   2354 	(*func)(arg0, cr, ct);
   2355 }
   2356 
   2357 int
   2358 vnext_fid(femarg_t *vf, fid_t *fidp, caller_context_t *ct)
   2359 {
   2360 	int (*func)() = NULL;
   2361 	void *arg0 = NULL;
   2362 
   2363 	ASSERT(vf != NULL);
   2364 	vf->fa_fnode--;
   2365 	vsop_find(vf, &func, int, &arg0, vop_fid, femop_fid);
   2366 	ASSERT(func != NULL);
   2367 	ASSERT(arg0 != NULL);
   2368 	return ((*func)(arg0, fidp, ct));
   2369 }
   2370 
   2371 int
   2372 vnext_rwlock(femarg_t *vf, int write_lock, caller_context_t *ct)
   2373 {
   2374 	int (*func)() = NULL;
   2375 	void *arg0 = NULL;
   2376 
   2377 	ASSERT(vf != NULL);
   2378 	vf->fa_fnode--;
   2379 	vsop_find(vf, &func, int, &arg0, vop_rwlock, femop_rwlock);
   2380 	ASSERT(func != NULL);
   2381 	ASSERT(arg0 != NULL);
   2382 	return ((*func)(arg0, write_lock, ct));
   2383 }
   2384 
   2385 void
   2386 vnext_rwunlock(femarg_t *vf, int write_lock, caller_context_t *ct)
   2387 {
   2388 	void (*func)() = NULL;
   2389 	void *arg0 = NULL;
   2390 
   2391 	ASSERT(vf != NULL);
   2392 	vf->fa_fnode--;
   2393 	vsop_find(vf, &func, void, &arg0, vop_rwunlock, femop_rwunlock);
   2394 	ASSERT(func != NULL);
   2395 	ASSERT(arg0 != NULL);
   2396 	(*func)(arg0, write_lock, ct);
   2397 }
   2398 
   2399 int
   2400 vnext_seek(femarg_t *vf, offset_t ooff, offset_t *noffp, caller_context_t *ct)
   2401 {
   2402 	int (*func)() = NULL;
   2403 	void *arg0 = NULL;
   2404 
   2405 	ASSERT(vf != NULL);
   2406 	vf->fa_fnode--;
   2407 	vsop_find(vf, &func, int, &arg0, vop_seek, femop_seek);
   2408 	ASSERT(func != NULL);
   2409 	ASSERT(arg0 != NULL);
   2410 	return ((*func)(arg0, ooff, noffp, ct));
   2411 }
   2412 
   2413 int
   2414 vnext_cmp(femarg_t *vf, vnode_t *vp2, caller_context_t *ct)
   2415 {
   2416 	int (*func)() = NULL;
   2417 	void *arg0 = NULL;
   2418 
   2419 	ASSERT(vf != NULL);
   2420 	vf->fa_fnode--;
   2421 	vsop_find(vf, &func, int, &arg0, vop_cmp, femop_cmp);
   2422 	ASSERT(func != NULL);
   2423 	ASSERT(arg0 != NULL);
   2424 	return ((*func)(arg0, vp2, ct));
   2425 }
   2426 
   2427 int
   2428 vnext_frlock(femarg_t *vf, int cmd, struct flock64 *bfp, int flag,
   2429 	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
   2430 	caller_context_t *ct)
   2431 {
   2432 	int (*func)() = NULL;
   2433 	void *arg0 = NULL;
   2434 
   2435 	ASSERT(vf != NULL);
   2436 	vf->fa_fnode--;
   2437 	vsop_find(vf, &func, int, &arg0, vop_frlock, femop_frlock);
   2438 	ASSERT(func != NULL);
   2439 	ASSERT(arg0 != NULL);
   2440 	return ((*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct));
   2441 }
   2442 
   2443 int
   2444 vnext_space(femarg_t *vf, int cmd, struct flock64 *bfp, int flag,
   2445 	offset_t offset, cred_t *cr, caller_context_t *ct)
   2446 {
   2447 	int (*func)() = NULL;
   2448 	void *arg0 = NULL;
   2449 
   2450 	ASSERT(vf != NULL);
   2451 	vf->fa_fnode--;
   2452 	vsop_find(vf, &func, int, &arg0, vop_space, femop_space);
   2453 	ASSERT(func != NULL);
   2454 	ASSERT(arg0 != NULL);
   2455 	return ((*func)(arg0, cmd, bfp, flag, offset, cr, ct));
   2456 }
   2457 
   2458 int
   2459 vnext_realvp(femarg_t *vf, vnode_t **vpp, caller_context_t *ct)
   2460 {
   2461 	int (*func)() = NULL;
   2462 	void *arg0 = NULL;
   2463 
   2464 	ASSERT(vf != NULL);
   2465 	vf->fa_fnode--;
   2466 	vsop_find(vf, &func, int, &arg0, vop_realvp, femop_realvp);
   2467 	ASSERT(func != NULL);
   2468 	ASSERT(arg0 != NULL);
   2469 	return ((*func)(arg0, vpp, ct));
   2470 }
   2471 
   2472 int
   2473 vnext_getpage(femarg_t *vf, offset_t off, size_t len, uint_t *protp,
   2474 	struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
   2475 	enum seg_rw rw, cred_t *cr, caller_context_t *ct)
   2476 {
   2477 	int (*func)() = NULL;
   2478 	void *arg0 = NULL;
   2479 
   2480 	ASSERT(vf != NULL);
   2481 	vf->fa_fnode--;
   2482 	vsop_find(vf, &func, int, &arg0, vop_getpage, femop_getpage);
   2483 	ASSERT(func != NULL);
   2484 	ASSERT(arg0 != NULL);
   2485 	return ((*func)(arg0, off, len, protp, plarr, plsz, seg, addr, rw,
   2486 	    cr, ct));
   2487 }
   2488 
   2489 int
   2490 vnext_putpage(femarg_t *vf, offset_t off, size_t len, int flags,
   2491 	cred_t *cr, caller_context_t *ct)
   2492 {
   2493 	int (*func)() = NULL;
   2494 	void *arg0 = NULL;
   2495 
   2496 	ASSERT(vf != NULL);
   2497 	vf->fa_fnode--;
   2498 	vsop_find(vf, &func, int, &arg0, vop_putpage, femop_putpage);
   2499 	ASSERT(func != NULL);
   2500 	ASSERT(arg0 != NULL);
   2501 	return ((*func)(arg0, off, len, flags, cr, ct));
   2502 }
   2503 
   2504 int
   2505 vnext_map(femarg_t *vf, offset_t off, struct as *as, caddr_t *addrp,
   2506 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
   2507 	cred_t *cr, caller_context_t *ct)
   2508 {
   2509 	int (*func)() = NULL;
   2510 	void *arg0 = NULL;
   2511 
   2512 	ASSERT(vf != NULL);
   2513 	vf->fa_fnode--;
   2514 	vsop_find(vf, &func, int, &arg0, vop_map, femop_map);
   2515 	ASSERT(func != NULL);
   2516 	ASSERT(arg0 != NULL);
   2517 	return ((*func)(arg0, off, as, addrp, len, prot, maxprot, flags,
   2518 	    cr, ct));
   2519 }
   2520 
   2521 int
   2522 vnext_addmap(femarg_t *vf, offset_t off, struct as *as, caddr_t addr,
   2523 	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
   2524 	cred_t *cr, caller_context_t *ct)
   2525 {
   2526 	int (*func)() = NULL;
   2527 	void *arg0 = NULL;
   2528 
   2529 	ASSERT(vf != NULL);
   2530 	vf->fa_fnode--;
   2531 	vsop_find(vf, &func, int, &arg0, vop_addmap, femop_addmap);
   2532 	ASSERT(func != NULL);
   2533 	ASSERT(arg0 != NULL);
   2534 	return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags,
   2535 	    cr, ct));
   2536 }
   2537 
   2538 int
   2539 vnext_delmap(femarg_t *vf, offset_t off, struct as *as, caddr_t addr,
   2540 	size_t len, uint_t prot, uint_t maxprot, uint_t flags,
   2541 	cred_t *cr, caller_context_t *ct)
   2542 {
   2543 	int (*func)() = NULL;
   2544 	void *arg0 = NULL;
   2545 
   2546 	ASSERT(vf != NULL);
   2547 	vf->fa_fnode--;
   2548 	vsop_find(vf, &func, int, &arg0, vop_delmap, femop_delmap);
   2549 	ASSERT(func != NULL);
   2550 	ASSERT(arg0 != NULL);
   2551 	return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags,
   2552 	    cr, ct));
   2553 }
   2554 
   2555 int
   2556 vnext_poll(femarg_t *vf, short events, int anyyet, short *reventsp,
   2557 	struct pollhead **phpp, caller_context_t *ct)
   2558 {
   2559 	int (*func)() = NULL;
   2560 	void *arg0 = NULL;
   2561 
   2562 	ASSERT(vf != NULL);
   2563 	vf->fa_fnode--;
   2564 	vsop_find(vf, &func, int, &arg0, vop_poll, femop_poll);
   2565 	ASSERT(func != NULL);
   2566 	ASSERT(arg0 != NULL);
   2567 	return ((*func)(arg0, events, anyyet, reventsp, phpp, ct));
   2568 }
   2569 
   2570 int
   2571 vnext_dump(femarg_t *vf, caddr_t addr, offset_t lbdn, offset_t dblks,
   2572 	caller_context_t *ct)
   2573 {
   2574 	int (*func)() = NULL;
   2575 	void *arg0 = NULL;
   2576 
   2577 	ASSERT(vf != NULL);
   2578 	vf->fa_fnode--;
   2579 	vsop_find(vf, &func, int, &arg0, vop_dump, femop_dump);
   2580 	ASSERT(func != NULL);
   2581 	ASSERT(arg0 != NULL);
   2582 	return ((*func)(arg0, addr, lbdn, dblks, ct));
   2583 }
   2584 
   2585 int
   2586 vnext_pathconf(femarg_t *vf, int cmd, ulong_t *valp, cred_t *cr,
   2587 	caller_context_t *ct)
   2588 {
   2589 	int (*func)() = NULL;
   2590 	void *arg0 = NULL;
   2591 
   2592 	ASSERT(vf != NULL);
   2593 	vf->fa_fnode--;
   2594 	vsop_find(vf, &func, int, &arg0, vop_pathconf, femop_pathconf);
   2595 	ASSERT(func != NULL);
   2596 	ASSERT(arg0 != NULL);
   2597 	return ((*func)(arg0, cmd, valp, cr, ct));
   2598 }
   2599 
   2600 int
   2601 vnext_pageio(femarg_t *vf, struct page *pp, u_offset_t io_off,
   2602 	size_t io_len, int flags, cred_t *cr, caller_context_t *ct)
   2603 {
   2604 	int (*func)() = NULL;
   2605 	void *arg0 = NULL;
   2606 
   2607 	ASSERT(vf != NULL);
   2608 	vf->fa_fnode--;
   2609 	vsop_find(vf, &func, int, &arg0, vop_pageio, femop_pageio);
   2610 	ASSERT(func != NULL);
   2611 	ASSERT(arg0 != NULL);
   2612 	return ((*func)(arg0, pp, io_off, io_len, flags, cr, ct));
   2613 }
   2614 
   2615 int
   2616 vnext_dumpctl(femarg_t *vf, int action, offset_t *blkp, caller_context_t *ct)
   2617 {
   2618 	int (*func)() = NULL;
   2619 	void *arg0 = NULL;
   2620 
   2621 	ASSERT(vf != NULL);
   2622 	vf->fa_fnode--;
   2623 	vsop_find(vf, &func, int, &arg0, vop_dumpctl, femop_dumpctl);
   2624 	ASSERT(func != NULL);
   2625 	ASSERT(arg0 != NULL);
   2626 	return ((*func)(arg0, action, blkp, ct));
   2627 }
   2628 
   2629 void
   2630 vnext_dispose(femarg_t *vf, struct page *pp, int flag, int dn, cred_t *cr,
   2631 	caller_context_t *ct)
   2632 {
   2633 	void (*func)() = NULL;
   2634 	void *arg0 = NULL;
   2635 
   2636 	ASSERT(vf != NULL);
   2637 	vf->fa_fnode--;
   2638 	vsop_find(vf, &func, void, &arg0, vop_dispose, femop_dispose);
   2639 	ASSERT(func != NULL);
   2640 	ASSERT(arg0 != NULL);
   2641 	(*func)(arg0, pp, flag, dn, cr, ct);
   2642 }
   2643 
   2644 int
   2645 vnext_setsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr,
   2646 	caller_context_t *ct)
   2647 {
   2648 	int (*func)() = NULL;
   2649 	void *arg0 = NULL;
   2650 
   2651 	ASSERT(vf != NULL);
   2652 	vf->fa_fnode--;
   2653 	vsop_find(vf, &func, int, &arg0, vop_setsecattr, femop_setsecattr);
   2654 	ASSERT(func != NULL);
   2655 	ASSERT(arg0 != NULL);
   2656 	return ((*func)(arg0, vsap, flag, cr, ct));
   2657 }
   2658 
   2659 int
   2660 vnext_getsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr,
   2661 	caller_context_t *ct)
   2662 {
   2663 	int (*func)() = NULL;
   2664 	void *arg0 = NULL;
   2665 
   2666 	ASSERT(vf != NULL);
   2667 	vf->fa_fnode--;
   2668 	vsop_find(vf, &func, int, &arg0, vop_getsecattr, femop_getsecattr);
   2669 	ASSERT(func != NULL);
   2670 	ASSERT(arg0 != NULL);
   2671 	return ((*func)(arg0, vsap, flag, cr, ct));
   2672 }
   2673 
   2674 int
   2675 vnext_shrlock(femarg_t *vf, int cmd, struct shrlock *shr, int flag,
   2676 	cred_t *cr, caller_context_t *ct)
   2677 {
   2678 	int (*func)() = NULL;
   2679 	void *arg0 = NULL;
   2680 
   2681 	ASSERT(vf != NULL);
   2682 	vf->fa_fnode--;
   2683 	vsop_find(vf, &func, int, &arg0, vop_shrlock, femop_shrlock);
   2684 	ASSERT(func != NULL);
   2685 	ASSERT(arg0 != NULL);
   2686 	return ((*func)(arg0, cmd, shr, flag, cr, ct));
   2687 }
   2688 
   2689 int
   2690 vnext_vnevent(femarg_t *vf, vnevent_t vnevent, vnode_t *dvp, char *cname,
   2691     caller_context_t *ct)
   2692 {
   2693 	int (*func)() = NULL;
   2694 	void *arg0 = NULL;
   2695 
   2696 	ASSERT(vf != NULL);
   2697 	vf->fa_fnode--;
   2698 	vsop_find(vf, &func, int, &arg0, vop_vnevent, femop_vnevent);
   2699 	ASSERT(func != NULL);
   2700 	ASSERT(arg0 != NULL);
   2701 	return ((*func)(arg0, vnevent, dvp, cname, ct));
   2702 }
   2703 
   2704 int
   2705 vnext_reqzcbuf(femarg_t *vf, enum uio_rw ioflag, xuio_t *xuiop, cred_t *cr,
   2706     caller_context_t *ct)
   2707 {
   2708 	int (*func)() = NULL;
   2709 	void *arg0 = NULL;
   2710 
   2711 	ASSERT(vf != NULL);
   2712 	vf->fa_fnode--;
   2713 	vsop_find(vf, &func, int, &arg0, vop_reqzcbuf, femop_reqzcbuf);
   2714 	ASSERT(func != NULL);
   2715 	ASSERT(arg0 != NULL);
   2716 	return ((*func)(arg0, ioflag, xuiop, cr, ct));
   2717 }
   2718 
   2719 int
   2720 vnext_retzcbuf(femarg_t *vf, xuio_t *xuiop, cred_t *cr, caller_context_t *ct)
   2721 {
   2722 	int (*func)() = NULL;
   2723 	void *arg0 = NULL;
   2724 
   2725 	ASSERT(vf != NULL);
   2726 	vf->fa_fnode--;
   2727 	vsop_find(vf, &func, int, &arg0, vop_retzcbuf, femop_retzcbuf);
   2728 	ASSERT(func != NULL);
   2729 	ASSERT(arg0 != NULL);
   2730 	return ((*func)(arg0, xuiop, cr, ct));
   2731 }
   2732 
   2733 int
   2734 vfsnext_mount(fsemarg_t *vf, vnode_t *mvp, struct mounta *uap, cred_t *cr)
   2735 {
   2736 	int (*func)() = NULL;
   2737 	void *arg0 = NULL;
   2738 
   2739 	ASSERT(vf != NULL);
   2740 	vf->fa_fnode--;
   2741 	vfsop_find(vf, &func, int, &arg0, vfs_mount, fsemop_mount);
   2742 	ASSERT(func != NULL);
   2743 	ASSERT(arg0 != NULL);
   2744 	return ((*func)(arg0, mvp, uap, cr));
   2745 }
   2746 
   2747 int
   2748 vfsnext_unmount(fsemarg_t *vf, int flag, cred_t *cr)
   2749 {
   2750 	int (*func)() = NULL;
   2751 	void *arg0 = NULL;
   2752 
   2753 	ASSERT(vf != NULL);
   2754 	vf->fa_fnode--;
   2755 	vfsop_find(vf, &func, int, &arg0, vfs_unmount, fsemop_unmount);
   2756 	ASSERT(func != NULL);
   2757 	ASSERT(arg0 != NULL);
   2758 	return ((*func)(arg0, flag, cr));
   2759 }
   2760 
   2761 int
   2762 vfsnext_root(fsemarg_t *vf, vnode_t **vpp)
   2763 {
   2764 	int (*func)() = NULL;
   2765 	void *arg0 = NULL;
   2766 
   2767 	ASSERT(vf != NULL);
   2768 	vf->fa_fnode--;
   2769 	vfsop_find(vf, &func, int, &arg0, vfs_root, fsemop_root);
   2770 	ASSERT(func != NULL);
   2771 	ASSERT(arg0 != NULL);
   2772 	return ((*func)(arg0, vpp));
   2773 }
   2774 
   2775 int
   2776 vfsnext_statvfs(fsemarg_t *vf, statvfs64_t *sp)
   2777 {
   2778 	int (*func)() = NULL;
   2779 	void *arg0 = NULL;
   2780 
   2781 	ASSERT(vf != NULL);
   2782 	vf->fa_fnode--;
   2783 	vfsop_find(vf, &func, int, &arg0, vfs_statvfs, fsemop_statvfs);
   2784 	ASSERT(func != NULL);
   2785 	ASSERT(arg0 != NULL);
   2786 	return ((*func)(arg0, sp));
   2787 }
   2788 
   2789 int
   2790 vfsnext_sync(fsemarg_t *vf, short flag, cred_t *cr)
   2791 {
   2792 	int (*func)() = NULL;
   2793 	void *arg0 = NULL;
   2794 
   2795 	ASSERT(vf != NULL);
   2796 	vf->fa_fnode--;
   2797 	vfsop_find(vf, &func, int, &arg0, vfs_sync, fsemop_sync);
   2798 	ASSERT(func != NULL);
   2799 	ASSERT(arg0 != NULL);
   2800 	return ((*func)(arg0, flag, cr));
   2801 }
   2802 
   2803 int
   2804 vfsnext_vget(fsemarg_t *vf, vnode_t **vpp, fid_t *fidp)
   2805 {
   2806 	int (*func)() = NULL;
   2807 	void *arg0 = NULL;
   2808 
   2809 	ASSERT(vf != NULL);
   2810 	vf->fa_fnode--;
   2811 	vfsop_find(vf, &func, int, &arg0, vfs_vget, fsemop_vget);
   2812 	ASSERT(func != NULL);
   2813 	ASSERT(arg0 != NULL);
   2814 	return ((*func)(arg0, vpp, fidp));
   2815 }
   2816 
   2817 int
   2818 vfsnext_mountroot(fsemarg_t *vf, enum whymountroot reason)
   2819 {
   2820 	int (*func)() = NULL;
   2821 	void *arg0 = NULL;
   2822 
   2823 	ASSERT(vf != NULL);
   2824 	vf->fa_fnode--;
   2825 	vfsop_find(vf, &func, int, &arg0, vfs_mountroot, fsemop_mountroot);
   2826 	ASSERT(func != NULL);
   2827 	ASSERT(arg0 != NULL);
   2828 	return ((*func)(arg0, reason));
   2829 }
   2830 
   2831 void
   2832 vfsnext_freevfs(fsemarg_t *vf)
   2833 {
   2834 	void (*func)() = NULL;
   2835 	void *arg0 = NULL;
   2836 
   2837 	ASSERT(vf != NULL);
   2838 	vf->fa_fnode--;
   2839 	vfsop_find(vf, &func, void, &arg0, vfs_freevfs, fsemop_freevfs);
   2840 	ASSERT(func != NULL);
   2841 	ASSERT(arg0 != NULL);
   2842 	(*func)(arg0);
   2843 }
   2844 
   2845 int
   2846 vfsnext_vnstate(fsemarg_t *vf, vnode_t *vp, vntrans_t nstate)
   2847 {
   2848 	int (*func)() = NULL;
   2849 	void *arg0 = NULL;
   2850 
   2851 	ASSERT(vf != NULL);
   2852 	vf->fa_fnode--;
   2853 	vfsop_find(vf, &func, int, &arg0, vfs_vnstate, fsemop_vnstate);
   2854 	ASSERT(func != NULL);
   2855 	ASSERT(arg0 != NULL);
   2856 	return ((*func)(arg0, vp, nstate));
   2857 }
   2858 
   2859 
   2860 /*
   2861  * Create a new fem_head and associate with the vnode.
   2862  * To keep the unaugmented vnode access path lock free, we spin
   2863  * update this - create a new one, then try and install it. If
   2864  * we fail to install, release the old one and pretend we succeeded.
   2865  */
   2866 
   2867 static struct fem_head *
   2868 new_femhead(struct fem_head **hp)
   2869 {
   2870 	struct fem_head	*head;
   2871 
   2872 	head = kmem_alloc(sizeof (*head), KM_SLEEP);
   2873 	mutex_init(&head->femh_lock, NULL, MUTEX_DEFAULT, NULL);
   2874 	head->femh_list = NULL;
   2875 	if (casptr(hp, NULL, head) != NULL) {
   2876 		kmem_free(head, sizeof (*head));
   2877 		head = *hp;
   2878 	}
   2879 	return (head);
   2880 }
   2881 
   2882 /*
   2883  * Create a fem_list.  The fem_list that gets returned is in a
   2884  * very rudimentary state and MUST NOT be used until it's initialized
   2885  * (usually by femlist_construct() or fem_dup_list()).  The refcount
   2886  * and size is set properly and top-of-stack is set to the "guard" node
   2887  * just to be consistent.
   2888  *
   2889  * If anyone were to accidentally trying to run on this fem_list before
   2890  * it's initialized then the system would likely panic trying to defererence
   2891  * the (NULL) fn_op pointer.
   2892  *
   2893  */
   2894 static struct fem_list *
   2895 femlist_create(int numnodes)
   2896 {
   2897 	struct fem_list	*sp;
   2898 
   2899 	sp = kmem_alloc(fl_ntob(numnodes), KM_SLEEP);
   2900 	sp->feml_refc  = 1;
   2901 	sp->feml_ssize = numnodes;
   2902 	sp->feml_nodes[0] = FEM_GUARD(FEMTYPE_NULL);
   2903 	sp->feml_tos = 0;
   2904 	return (sp);
   2905 }
   2906 
   2907 /*
   2908  * Construct a new femlist.
   2909  * The list is constructed with the appropriate type of guard to
   2910  * anchor it, and inserts the original ops.
   2911  */
   2912 
   2913 static struct fem_list *
   2914 femlist_construct(void *baseops, int type, int numnodes)
   2915 {
   2916 	struct fem_list	*sp;
   2917 
   2918 	sp = femlist_create(numnodes);
   2919 	sp->feml_nodes[0] = FEM_GUARD(type);
   2920 	sp->feml_nodes[1].fn_op.anon = baseops;
   2921 	sp->feml_nodes[1].fn_available = NULL;
   2922 	sp->feml_nodes[1].fn_av_hold = NULL;
   2923 	sp->feml_nodes[1].fn_av_rele = NULL;
   2924 	sp->feml_tos = 1;
   2925 	return (sp);
   2926 }
   2927 
   2928 /*
   2929  * Duplicate a list.  Copy the original list to the clone.
   2930  *
   2931  * NOTE: The caller must have the fem_head for the lists locked.
   2932  * Assuming the appropriate lock is held and the caller has done the
   2933  * math right, the clone list should be big enough to old the original.
   2934  */
   2935 
   2936 static void
   2937 fem_dup_list(struct fem_list *orig, struct fem_list *clone)
   2938 {
   2939 	int		i;
   2940 
   2941 	ASSERT(clone->feml_ssize >= orig->feml_ssize);
   2942 
   2943 	bcopy(orig->feml_nodes, clone->feml_nodes,
   2944 	    sizeof (orig->feml_nodes[0]) * orig->feml_ssize);
   2945 	clone->feml_tos = orig->feml_tos;
   2946 	/*
   2947 	 * Now that we've copied the old list (orig) to the new list (clone),
   2948 	 * we need to walk the new list and put another hold on fn_available.
   2949 	 */
   2950 	for (i = clone->feml_tos; i > 0; i--) {
   2951 		struct fem_node *fnp = &clone->feml_nodes[i];
   2952 
   2953 		if (fnp->fn_av_hold)
   2954 			(*(fnp->fn_av_hold))(fnp->fn_available);
   2955 	}
   2956 }
   2957 
   2958 
   2959 static int
   2960 fem_push_node(
   2961 	struct fem_head **hp,
   2962 	void **baseops,
   2963 	int type,
   2964 	struct fem_node *nnode,
   2965 	femhow_t how)
   2966 {
   2967 	struct fem_head	*hd;
   2968 	struct fem_list	*list;
   2969 	void		*oldops;
   2970 	int		retry;
   2971 	int		error = 0;
   2972 	int		i;
   2973 
   2974 	/* Validate the node */
   2975 	if ((nnode->fn_op.anon == NULL) || (nnode->fn_available == NULL)) {
   2976 		return (EINVAL);
   2977 	}
   2978 
   2979 	if ((hd = *hp) == NULL) { /* construct a proto-list */
   2980 		hd = new_femhead(hp);
   2981 	}
   2982 	/*
   2983 	 * RULE: once a femhead has been pushed onto a object, it cannot be
   2984 	 * removed until the object is destroyed.  It can be deactivated by
   2985 	 * placing the original 'object operations' onto the object, which
   2986 	 * will ignore the femhead.
   2987 	 * The loop will exist when the femh_list has space to push a monitor
   2988 	 * onto it.
   2989 	 */
   2990 	do {
   2991 		retry = 1;
   2992 		list = fem_lock(hd);
   2993 		oldops = *baseops;
   2994 
   2995 		if (list != NULL) {
   2996 			if (list->feml_tos+1 < list->feml_ssize) {
   2997 				retry = 0;
   2998 			} else {
   2999 				struct fem_list	*olist = list;
   3000 
   3001 				fem_addref(olist);
   3002 				fem_unlock(hd);
   3003 				list = femlist_create(olist->feml_ssize * 2);
   3004 				(void) fem_lock(hd);
   3005 				if (hd->femh_list == olist) {
   3006 					if (list->feml_ssize <=
   3007 					    olist->feml_ssize) {
   3008 						/*
   3009 						 * We have a new list, but it
   3010 						 * is too small to hold the
   3011 						 * original contents plus the
   3012 						 * one to push.  Release the
   3013 						 * new list and start over.
   3014 						 */
   3015 						fem_release(list);
   3016 						fem_unlock(hd);
   3017 					} else {
   3018 						/*
   3019 						 * Life is good:  Our new list
   3020 						 * is big enough to hold the
   3021 						 * original list (olist) + 1.
   3022 						 */
   3023 						fem_dup_list(olist, list);
   3024 						/* orphan this list */
   3025 						hd->femh_list = list;
   3026 						(void) fem_delref(olist);
   3027 						retry = 0;
   3028 					}
   3029 				} else {
   3030 					/* concurrent update, retry */
   3031 					fem_release(list);
   3032 					fem_unlock(hd);
   3033 				}
   3034 				/* remove the reference we added above */
   3035 				fem_release(olist);
   3036 			}
   3037 		} else {
   3038 			fem_unlock(hd);
   3039 			list = femlist_construct(oldops, type, NNODES_DEFAULT);
   3040 			(void) fem_lock(hd);
   3041 			if (hd->femh_list != NULL || *baseops != oldops) {
   3042 				/* concurrent update, retry */
   3043 				fem_release(list);
   3044 				fem_unlock(hd);
   3045 			} else {
   3046 				hd->femh_list = list;
   3047 				*baseops = FEM_HEAD(type);
   3048 				retry = 0;
   3049 			}
   3050 		}
   3051 	} while (retry);
   3052 
   3053 	ASSERT(mutex_owner(&hd->femh_lock) == curthread);
   3054 	ASSERT(list->feml_tos+1 < list->feml_ssize);
   3055 
   3056 	/*
   3057 	 * The presence of "how" will modify the behavior of how/if
   3058 	 * nodes are pushed.  If it's FORCE, then we can skip
   3059 	 * all the checks and push it on.
   3060 	 */
   3061 	if (how != FORCE) {
   3062 		/* Start at the top and work our way down */
   3063 		for (i = list->feml_tos; i > 0; i--) {
   3064 			void *fn_av = list->feml_nodes[i].fn_available;
   3065 			void *fn_op = list->feml_nodes[i].fn_op.anon;
   3066 
   3067 			/*
   3068 			 * OPARGUNIQ means that this node should not
   3069 			 * be pushed on if a node with the same op/avail
   3070 			 * combination exists.  This situation returns
   3071 			 * EBUSY.
   3072 			 *
   3073 			 * OPUNIQ means that this node should not be
   3074 			 * pushed on if a node with the same op exists.
   3075 			 * This situation also returns EBUSY.
   3076 			 */
   3077 			switch (how) {
   3078 
   3079 			case OPUNIQ:
   3080 				if (fn_op == nnode->fn_op.anon) {
   3081 					error = EBUSY;
   3082 				}
   3083 				break;
   3084 
   3085 			case OPARGUNIQ:
   3086 				if ((fn_op == nnode->fn_op.anon) &&
   3087 				    (fn_av == nnode->fn_available)) {
   3088 					error = EBUSY;
   3089 				}
   3090 				break;
   3091 
   3092 			default:
   3093 				error = EINVAL;	/* Unexpected value */
   3094 				break;
   3095 			}
   3096 
   3097 			if (error)
   3098 				break;
   3099 		}
   3100 	}
   3101 
   3102 	if (error == 0) {
   3103 		/*
   3104 		 * If no errors, slap the node on the list.
   3105 		 * Note: The following is a structure copy.
   3106 		 */
   3107 		list->feml_nodes[++(list->feml_tos)] = *nnode;
   3108 	}
   3109 
   3110 	fem_unlock(hd);
   3111 	return (error);
   3112 }
   3113 
   3114 /*
   3115  * Remove a node by copying the list above it down a notch.
   3116  * If the list is busy, replace it with an idle one and work
   3117  * upon it.
   3118  * A node matches if the opset matches and the datap matches or is
   3119  * null.
   3120  */
   3121 
   3122 static int
   3123 remove_node(struct fem_list *sp, void **baseops, void *opset, void *datap)
   3124 {
   3125 	int	i;
   3126 	struct fem_node	*fn;
   3127 
   3128 	for (i = sp->feml_tos; i > 0; i--) {
   3129 		fn = sp->feml_nodes+i;
   3130 		if (fn->fn_op.anon == opset &&
   3131 		    (fn->fn_available == datap || datap == NULL)) {
   3132 			break;
   3133 		}
   3134 	}
   3135 	if (i == 0) {
   3136 		return (EINVAL);
   3137 	}
   3138 
   3139 	/*
   3140 	 * At this point we have a node in-hand (*fn) that we are about
   3141 	 * to remove by overwriting it and adjusting the stack.  This is
   3142 	 * our last chance to do anything with this node so we do the
   3143 	 * release on the arg.
   3144 	 */
   3145 	if (fn->fn_av_rele)
   3146 		(*(fn->fn_av_rele))(fn->fn_available);
   3147 
   3148 	while (i++ < sp->feml_tos) {
   3149 		sp->feml_nodes[i-1] = sp->feml_nodes[i];
   3150 	}
   3151 	if (--(sp->feml_tos) == 1) { /* Empty, restore ops */
   3152 		*baseops = sp->feml_nodes[1].fn_op.anon;
   3153 	}
   3154 	return (0);
   3155 }
   3156 
   3157 static int
   3158 fem_remove_node(struct fem_head *fh, void **baseops, void *opset, void *datap)
   3159 {
   3160 	struct fem_list *sp;
   3161 	int		error = 0;
   3162 	int		retry;
   3163 
   3164 	if (fh == NULL) {
   3165 		return (EINVAL);
   3166 	}
   3167 
   3168 	do {
   3169 		retry = 0;
   3170 		if ((sp = fem_lock(fh)) == NULL) {
   3171 			fem_unlock(fh);
   3172 			error = EINVAL;
   3173 		} else if (sp->feml_refc == 1) {
   3174 			error = remove_node(sp, baseops, opset, datap);
   3175 			if (sp->feml_tos == 1) {
   3176 				/*
   3177 				 * The top-of-stack was decremented by
   3178 				 * remove_node().  If it got down to 1,
   3179 				 * then the base ops were replaced and we
   3180 				 * call fem_release() which will free the
   3181 				 * fem_list.
   3182 				 */
   3183 				fem_release(sp);
   3184 				fh->femh_list = NULL;
   3185 				/* XXX - Do we need a membar_producer() call? */
   3186 			}
   3187 			fem_unlock(fh);
   3188 		} else {
   3189 			/* busy - install a new one without this monitor */
   3190 			struct fem_list *nsp;	/* New fem_list being cloned */
   3191 
   3192 			fem_addref(sp);
   3193 			fem_unlock(fh);
   3194 			nsp = femlist_create(sp->feml_ssize);
   3195 			if (fem_lock(fh) == sp) {
   3196 				/*
   3197 				 * We popped out of the lock, created a
   3198 				 * list, then relocked.  If we're in here
   3199 				 * then the fem_head points to the same list
   3200 				 * it started with.
   3201 				 */
   3202 				fem_dup_list(sp, nsp);
   3203 				error = remove_node(nsp, baseops, opset, datap);
   3204 				if (error != 0) {
   3205 					fem_release(nsp);
   3206 				} else if (nsp->feml_tos == 1) {
   3207 					/* New list now empty, tear it down */
   3208 					fem_release(nsp);
   3209 					fh->femh_list = NULL;
   3210 				} else {
   3211 					fh->femh_list = nsp;
   3212 				}
   3213 				(void) fem_delref(sp);
   3214 			} else {
   3215 				/* List changed while locked, try again... */
   3216 				fem_release(nsp);
   3217 				retry = 1;
   3218 			}
   3219 			/*
   3220 			 * If error is set, then we tried to remove a node
   3221 			 * from the list, but failed.  This means that we
   3222 			 * will still be using this list so don't release it.
   3223 			 */
   3224 			if (error == 0)
   3225 				fem_release(sp);
   3226 			fem_unlock(fh);
   3227 		}
   3228 	} while (retry);
   3229 	return (error);
   3230 }
   3231 
   3232 
   3233 /*
   3234  * perform operation on each element until one returns non zero
   3235  */
   3236 static int
   3237 fem_walk_list(
   3238 	struct fem_list *sp,
   3239 	int (*f)(struct fem_node *, void *, void *),
   3240 	void *mon,
   3241 	void *arg)
   3242 {
   3243 	int	i;
   3244 
   3245 	ASSERT(sp != NULL);
   3246 	for (i = sp->feml_tos; i > 0; i--) {
   3247 		if ((*f)(sp->feml_nodes+i, mon, arg) != 0) {
   3248 			break;
   3249 		}
   3250 	}
   3251 	return (i);
   3252 }
   3253 
   3254 /*
   3255  * companion comparison functions.
   3256  */
   3257 static int
   3258 fem_compare_mon(struct fem_node *n, void *mon, void *arg)
   3259 {
   3260 	return ((n->fn_op.anon == mon) && (n->fn_available == arg));
   3261 }
   3262 
   3263 /*
   3264  * VNODE interposition.
   3265  */
   3266 
   3267 int
   3268 fem_create(char *name, const struct fs_operation_def *templ,
   3269     fem_t **actual)
   3270 {
   3271 	int	unused_ops = 0;
   3272 	int	e;
   3273 	fem_t	*newf;
   3274 
   3275 	newf = fem_alloc();
   3276 	newf->name = name;
   3277 	newf->templ = templ;
   3278 
   3279 	e =  fs_build_vector(newf, &unused_ops, fem_opdef, templ);
   3280 	if (e != 0) {
   3281 #ifdef DEBUG
   3282 		cmn_err(CE_WARN, "fem_create: error %d building vector", e);
   3283 #endif
   3284 		fem_free(newf);
   3285 	} else {
   3286 		*actual = newf;
   3287 	}
   3288 	return (e);
   3289 }
   3290 
   3291 int
   3292 fem_install(
   3293 	vnode_t *vp,		/* Vnode on which monitor is being installed */
   3294 	fem_t *mon,		/* Monitor operations being installed */
   3295 	void *arg,		/* Opaque data used by monitor */
   3296 	femhow_t how,		/* Installation control */
   3297 	void (*arg_hold)(void *),	/* Hold routine for "arg" */
   3298 	void (*arg_rele)(void *))	/* Release routine for "arg" */
   3299 {
   3300 	int	error;
   3301 	struct fem_node	nnode;
   3302 
   3303 	nnode.fn_available = arg;
   3304 	nnode.fn_op.fem = mon;
   3305 	nnode.fn_av_hold = arg_hold;
   3306 	nnode.fn_av_rele = arg_rele;
   3307 	/*
   3308 	 * If we have a non-NULL hold function, do the hold right away.
   3309 	 * The release is done in remove_node().
   3310 	 */
   3311 	if (arg_hold)
   3312 		(*arg_hold)(arg);
   3313 
   3314 	error = fem_push_node(&vp->v_femhead, (void **)&vp->v_op, FEMTYPE_VNODE,
   3315 	    &nnode, how);
   3316 
   3317 	/* If there was an error then the monitor wasn't pushed */
   3318 	if (error && arg_rele)
   3319 		(*arg_rele)(arg);
   3320 
   3321 	return (error);
   3322 }
   3323 
   3324 int
   3325 fem_is_installed(vnode_t *v, fem_t *mon, void *arg)
   3326 {
   3327 	int	e;
   3328 	struct fem_list	*fl;
   3329 
   3330 	fl = fem_get(v->v_femhead);
   3331 	if (fl != NULL) {
   3332 		e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
   3333 		fem_release(fl);
   3334 		return (e);
   3335 	}
   3336 	return (0);
   3337 }
   3338 
   3339 int
   3340 fem_uninstall(vnode_t *v, fem_t *mon, void *arg)
   3341 {
   3342 	int	e;
   3343 	e = fem_remove_node(v->v_femhead, (void **)&v->v_op,
   3344 	    (void *)mon, arg);
   3345 	return (e);
   3346 }
   3347 
   3348 void
   3349 fem_setvnops(vnode_t *v, vnodeops_t *newops)
   3350 {
   3351 	vnodeops_t	*r;
   3352 
   3353 	ASSERT(v != NULL);
   3354 	ASSERT(newops != NULL);
   3355 
   3356 	do {
   3357 		r = v->v_op;
   3358 		membar_consumer();
   3359 		if (v->v_femhead != NULL) {
   3360 			struct fem_list	*fl;
   3361 			if ((fl = fem_lock(v->v_femhead)) != NULL) {
   3362 				fl->feml_nodes[1].fn_op.vnode = newops;
   3363 				fem_unlock(v->v_femhead);
   3364 				return;
   3365 			}
   3366 			fem_unlock(v->v_femhead);
   3367 		}
   3368 	} while (casptr(&v->v_op, r, newops) != r);
   3369 }
   3370 
   3371 vnodeops_t *
   3372 fem_getvnops(vnode_t *v)
   3373 {
   3374 	vnodeops_t	*r;
   3375 
   3376 	ASSERT(v != NULL);
   3377 
   3378 	r = v->v_op;
   3379 	membar_consumer();
   3380 	if (v->v_femhead != NULL) {
   3381 		struct fem_list	*fl;
   3382 		if ((fl = fem_lock(v->v_femhead)) != NULL) {
   3383 			r = fl->feml_nodes[1].fn_op.vnode;
   3384 		}
   3385 		fem_unlock(v->v_femhead);
   3386 	}
   3387 	return (r);
   3388 }
   3389 
   3390 
   3391 /*
   3392  * VFS interposition
   3393  */
   3394 int
   3395 fsem_create(char *name, const struct fs_operation_def *templ,
   3396     fsem_t **actual)
   3397 {
   3398 	int	unused_ops = 0;
   3399 	int	e;
   3400 	fsem_t	*newv;
   3401 
   3402 	newv = fsem_alloc();
   3403 	newv->name = (const char *)name;
   3404 	newv->templ = templ;
   3405 
   3406 	e = fs_build_vector(newv, &unused_ops, fsem_opdef, templ);
   3407 	if (e != 0) {
   3408 #ifdef DEBUG
   3409 		cmn_err(CE_WARN, "fsem_create: error %d building vector", e);
   3410 #endif
   3411 		fsem_free(newv);
   3412 	} else {
   3413 		*actual = newv;
   3414 	}
   3415 	return (e);
   3416 }
   3417 
   3418 /*
   3419  * These need to be re-written, but there should be more common bits.
   3420  */
   3421 
   3422 int
   3423 fsem_is_installed(struct vfs *v, fsem_t *mon, void *arg)
   3424 {
   3425 	struct fem_list	*fl;
   3426 
   3427 	if (v->vfs_implp == NULL)
   3428 		return (0);
   3429 
   3430 	fl = fem_get(v->vfs_femhead);
   3431 	if (fl != NULL) {
   3432 		int	e;
   3433 		e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
   3434 		fem_release(fl);
   3435 		return (e);
   3436 	}
   3437 	return (0);
   3438 }
   3439 
   3440 int
   3441 fsem_install(
   3442 	struct vfs *vfsp,	/* VFS on which monitor is being installed */
   3443 	fsem_t *mon,		/* Monitor operations being installed */
   3444 	void *arg,		/* Opaque data used by monitor */
   3445 	femhow_t how,		/* Installation control */
   3446 	void (*arg_hold)(void *),	/* Hold routine for "arg" */
   3447 	void (*arg_rele)(void *))	/* Release routine for "arg" */
   3448 {
   3449 	int	error;
   3450 	struct fem_node	nnode;
   3451 
   3452 	/* If this vfs hasn't been properly initialized, fail the install */
   3453 	if (vfsp->vfs_implp == NULL)
   3454 		return (EINVAL);
   3455 
   3456 	nnode.fn_available = arg;
   3457 	nnode.fn_op.fsem = mon;
   3458 	nnode.fn_av_hold = arg_hold;
   3459 	nnode.fn_av_rele = arg_rele;
   3460 	/*
   3461 	 * If we have a non-NULL hold function, do the hold right away.
   3462 	 * The release is done in remove_node().
   3463 	 */
   3464 	if (arg_hold)
   3465 		(*arg_hold)(arg);
   3466 
   3467 	error = fem_push_node(&vfsp->vfs_femhead, (void **)&vfsp->vfs_op,
   3468 	    FEMTYPE_VFS, &nnode, how);
   3469 
   3470 	/* If there was an error then the monitor wasn't pushed */
   3471 	if (error && arg_rele)
   3472 		(*arg_rele)(arg);
   3473 
   3474 	return (error);
   3475 }
   3476 
   3477 int
   3478 fsem_uninstall(struct vfs *v, fsem_t *mon, void *arg)
   3479 {
   3480 	int	e;
   3481 
   3482 	if (v->vfs_implp == NULL)
   3483 		return (EINVAL);
   3484 
   3485 	e = fem_remove_node(v->vfs_femhead, (void **)&v->vfs_op,
   3486 	    (void *)mon, arg);
   3487 	return (e);
   3488 }
   3489 
   3490 void
   3491 fsem_setvfsops(vfs_t *v, vfsops_t *newops)
   3492 {
   3493 	vfsops_t	*r;
   3494 
   3495 	ASSERT(v != NULL);
   3496 	ASSERT(newops != NULL);
   3497 	ASSERT(v->vfs_implp);
   3498 
   3499 	do {
   3500 		r = v->vfs_op;
   3501 		membar_consumer();
   3502 		if (v->vfs_femhead != NULL) {
   3503 			struct fem_list	*fl;
   3504 			if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
   3505 				fl->feml_nodes[1].fn_op.vfs = newops;
   3506 				fem_unlock(v->vfs_femhead);
   3507 				return;
   3508 			}
   3509 			fem_unlock(v->vfs_femhead);
   3510 		}
   3511 	} while (casptr(&v->vfs_op, r, newops) != r);
   3512 }
   3513 
   3514 vfsops_t *
   3515 fsem_getvfsops(vfs_t *v)
   3516 {
   3517 	vfsops_t	*r;
   3518 
   3519 	ASSERT(v != NULL);
   3520 	ASSERT(v->vfs_implp);
   3521 
   3522 	r = v->vfs_op;
   3523 	membar_consumer();
   3524 	if (v->vfs_femhead != NULL) {
   3525 		struct fem_list	*fl;
   3526 		if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
   3527 			r = fl->feml_nodes[1].fn_op.vfs;
   3528 		}
   3529 		fem_unlock(v->vfs_femhead);
   3530 	}
   3531 	return (r);
   3532 }
   3533 
   3534 /*
   3535  * Setup FEM.
   3536  */
   3537 void
   3538 fem_init()
   3539 {
   3540 	struct fem_type_info   *fi;
   3541 
   3542 	/*
   3543 	 * This femtype is only used for fem_list creation so we only
   3544 	 * need the "guard" to be initialized so that feml_tos has
   3545 	 * some rudimentary meaning.  A fem_list must not be used until
   3546 	 * it has been initialized (either via femlist_construct() or
   3547 	 * fem_dup_list()).  Anything that tries to use this fem_list
   3548 	 * before it's actually initialized would panic the system as
   3549 	 * soon as "fn_op" (NULL) is dereferenced.
   3550 	 */
   3551 	fi = femtype + FEMTYPE_NULL;
   3552 	fi->errf = fem_err;
   3553 	fi->guard.fn_available = (void *)&fi->guard;
   3554 	fi->guard.fn_av_hold = NULL;
   3555 	fi->guard.fn_av_rele = NULL;
   3556 	fi->guard.fn_op.anon = NULL;
   3557 
   3558 	fi = femtype + FEMTYPE_VNODE;
   3559 	fi->errf = fem_err;
   3560 	fi->head.fn_available = NULL;
   3561 	fi->head.fn_av_hold = NULL;
   3562 	fi->head.fn_av_rele = NULL;
   3563 	(void) vn_make_ops("fem-head", fhead_vn_spec, &fi->head.fn_op.vnode);
   3564 	fi->guard.fn_available = (void *)&fi->guard;
   3565 	fi->guard.fn_av_hold = NULL;
   3566 	fi->guard.fn_av_rele = NULL;
   3567 	(void) fem_create("fem-guard", fem_guard_ops, &fi->guard.fn_op.fem);
   3568 
   3569 	fi = femtype + FEMTYPE_VFS;
   3570 	fi->errf = fsem_err;
   3571 	fi->head.fn_available = NULL;
   3572 	fi->head.fn_av_hold = NULL;
   3573 	fi->head.fn_av_rele = NULL;
   3574 	(void) vfs_makefsops(fshead_vfs_spec, &fi->head.fn_op.vfs);
   3575 
   3576 	fi->guard.fn_available = (void *)&fi->guard;
   3577 	fi->guard.fn_av_hold = NULL;
   3578 	fi->guard.fn_av_rele = NULL;
   3579 	(void) fsem_create("fem-guard", fsem_guard_ops, &fi->guard.fn_op.fsem);
   3580 }
   3581 
   3582 
   3583 int
   3584 fem_err()
   3585 {
   3586 	cmn_err(CE_PANIC, "fem/vnode operations corrupt");
   3587 	return (0);
   3588 }
   3589 
   3590 int
   3591 fsem_err()
   3592 {
   3593 	cmn_err(CE_PANIC, "fem/vfs operations corrupt");
   3594 	return (0);
   3595 }
   3596