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