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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/atomic.h>
29 #include <sys/mutex.h>
30 #include <sys/errno.h>
31 #include <sys/param.h>
32 #include <sys/sysmacros.h>
33 #include <sys/systm.h>
34 #include <sys/cmn_err.h>
35 #include <sys/debug.h>
39 #include <sys/vnode.h>
40 #include <sys/vfs_opreg.h>
42 #define NNODES_DEFAULT 8 /* Default number of nodes in a fem_list */
44 * fl_ntob(n) - Fem_list: number of nodes to bytes
45 * Given the number of nodes in a fem_list return the size, in bytes,
46 * of the fem_list structure.
48 #define fl_ntob(n) (sizeof (struct fem_list) + \
49 ((n) - 1) * sizeof (struct fem_node))
52 FEMTYPE_NULL
, /* Uninitialized */
58 #define FEM_HEAD(_t) femtype[(_t)].head.fn_op.anon
59 #define FEM_GUARD(_t) femtype[(_t)].guard
61 static struct fem_type_info
{
63 struct fem_node guard
;
65 } femtype
[FEMTYPE_NTYPES
];
69 * For each type, two tables - the translation offset definition, which
70 * is used by fs_build_vector to layout the operation(s) vector; and the
71 * guard_operation_vector which protects from stack under-run.
78 #define _FEMOPDEF(name, member) \
79 { VOPNAME_##name, offsetof(fem_t, femop_##member), NULL }
81 static fs_operation_trans_def_t fem_opdef
[] = {
82 _FEMOPDEF(OPEN
, open
),
83 _FEMOPDEF(CLOSE
, close
),
84 _FEMOPDEF(READ
, read
),
85 _FEMOPDEF(WRITE
, write
),
86 _FEMOPDEF(IOCTL
, ioctl
),
87 _FEMOPDEF(SETFL
, setfl
),
88 _FEMOPDEF(GETATTR
, getattr
),
89 _FEMOPDEF(SETATTR
, setattr
),
90 _FEMOPDEF(ACCESS
, access
),
91 _FEMOPDEF(LOOKUP
, lookup
),
92 _FEMOPDEF(CREATE
, create
),
93 _FEMOPDEF(REMOVE
, remove
),
94 _FEMOPDEF(LINK
, link
),
95 _FEMOPDEF(RENAME
, rename
),
96 _FEMOPDEF(MKDIR
, mkdir
),
97 _FEMOPDEF(RMDIR
, rmdir
),
98 _FEMOPDEF(READDIR
, readdir
),
99 _FEMOPDEF(SYMLINK
, symlink
),
100 _FEMOPDEF(READLINK
, readlink
),
101 _FEMOPDEF(FSYNC
, fsync
),
102 _FEMOPDEF(INACTIVE
, inactive
),
104 _FEMOPDEF(RWLOCK
, rwlock
),
105 _FEMOPDEF(RWUNLOCK
, rwunlock
),
106 _FEMOPDEF(SEEK
, seek
),
108 _FEMOPDEF(FRLOCK
, frlock
),
109 _FEMOPDEF(SPACE
, space
),
110 _FEMOPDEF(REALVP
, realvp
),
111 _FEMOPDEF(GETPAGE
, getpage
),
112 _FEMOPDEF(PUTPAGE
, putpage
),
114 _FEMOPDEF(ADDMAP
, addmap
),
115 _FEMOPDEF(DELMAP
, delmap
),
116 _FEMOPDEF(POLL
, poll
),
117 _FEMOPDEF(DUMP
, dump
),
118 _FEMOPDEF(PATHCONF
, pathconf
),
119 _FEMOPDEF(PAGEIO
, pageio
),
120 _FEMOPDEF(DUMPCTL
, dumpctl
),
121 _FEMOPDEF(DISPOSE
, dispose
),
122 _FEMOPDEF(SETSECATTR
, setsecattr
),
123 _FEMOPDEF(GETSECATTR
, getsecattr
),
124 _FEMOPDEF(SHRLOCK
, shrlock
),
125 _FEMOPDEF(VNEVENT
, vnevent
),
126 _FEMOPDEF(REQZCBUF
, reqzcbuf
),
127 _FEMOPDEF(RETZCBUF
, retzcbuf
),
132 #define _FEMGUARD(name, ignore) \
133 { VOPNAME_##name, (femop_t *)fem_err }
135 static struct fs_operation_def fem_guard_ops
[] = {
136 _FEMGUARD(OPEN
, open
),
137 _FEMGUARD(CLOSE
, close
),
138 _FEMGUARD(READ
, read
),
139 _FEMGUARD(WRITE
, write
),
140 _FEMGUARD(IOCTL
, ioctl
),
141 _FEMGUARD(SETFL
, setfl
),
142 _FEMGUARD(GETATTR
, getattr
),
143 _FEMGUARD(SETATTR
, setattr
),
144 _FEMGUARD(ACCESS
, access
),
145 _FEMGUARD(LOOKUP
, lookup
),
146 _FEMGUARD(CREATE
, create
),
147 _FEMGUARD(REMOVE
, remove
),
148 _FEMGUARD(LINK
, link
),
149 _FEMGUARD(RENAME
, rename
),
150 _FEMGUARD(MKDIR
, mkdir
),
151 _FEMGUARD(RMDIR
, rmdir
),
152 _FEMGUARD(READDIR
, readdir
),
153 _FEMGUARD(SYMLINK
, symlink
),
154 _FEMGUARD(READLINK
, readlink
),
155 _FEMGUARD(FSYNC
, fsync
),
156 _FEMGUARD(INACTIVE
, inactive
),
158 _FEMGUARD(RWLOCK
, rwlock
),
159 _FEMGUARD(RWUNLOCK
, rwunlock
),
160 _FEMGUARD(SEEK
, seek
),
162 _FEMGUARD(FRLOCK
, frlock
),
163 _FEMGUARD(SPACE
, space
),
164 _FEMGUARD(REALVP
, realvp
),
165 _FEMGUARD(GETPAGE
, getpage
),
166 _FEMGUARD(PUTPAGE
, putpage
),
168 _FEMGUARD(ADDMAP
, addmap
),
169 _FEMGUARD(DELMAP
, delmap
),
170 _FEMGUARD(POLL
, poll
),
171 _FEMGUARD(DUMP
, dump
),
172 _FEMGUARD(PATHCONF
, pathconf
),
173 _FEMGUARD(PAGEIO
, pageio
),
174 _FEMGUARD(DUMPCTL
, dumpctl
),
175 _FEMGUARD(DISPOSE
, dispose
),
176 _FEMGUARD(SETSECATTR
, setsecattr
),
177 _FEMGUARD(GETSECATTR
, getsecattr
),
178 _FEMGUARD(SHRLOCK
, shrlock
),
179 _FEMGUARD(VNEVENT
, vnevent
),
180 _FEMGUARD(REQZCBUF
, reqzcbuf
),
181 _FEMGUARD(RETZCBUF
, retzcbuf
),
186 #define _FSEMOPDEF(name, member) \
187 { VFSNAME_##name, offsetof(fsem_t, fsemop_##member), NULL }
189 static fs_operation_trans_def_t fsem_opdef
[] = {
190 _FSEMOPDEF(MOUNT
, mount
),
191 _FSEMOPDEF(UNMOUNT
, unmount
),
192 _FSEMOPDEF(ROOT
, root
),
193 _FSEMOPDEF(STATVFS
, statvfs
),
194 _FSEMOPDEF(SYNC
, sync
),
195 _FSEMOPDEF(VGET
, vget
),
196 _FSEMOPDEF(MOUNTROOT
, mountroot
),
197 _FSEMOPDEF(FREEVFS
, freevfs
),
198 _FSEMOPDEF(VNSTATE
, vnstate
),
202 #define _FSEMGUARD(name, ignore) \
203 { VFSNAME_##name, (femop_t *)fsem_err }
205 static struct fs_operation_def fsem_guard_ops
[] = {
206 _FSEMGUARD(MOUNT
, mount
),
207 _FSEMGUARD(UNMOUNT
, unmount
),
208 _FSEMGUARD(ROOT
, root
),
209 _FSEMGUARD(STATVFS
, statvfs
),
210 _FSEMGUARD(SYNC
, sync
),
211 _FSEMGUARD(VGET
, vget
),
212 _FSEMGUARD(MOUNTROOT
, mountroot
),
213 _FSEMGUARD(FREEVFS
, freevfs
),
214 _FSEMGUARD(VNSTATE
, vnstate
),
220 * vsop_find, vfsop_find -
222 * These macros descend the stack until they find either a basic
223 * vnode/vfs operation [ indicated by a null fn_available ] or a
224 * stacked item where this method is non-null [_vsop].
226 * The DEBUG one is written with a single function which manually applies
227 * the structure offsets. It can have additional debugging support.
232 #define vsop_find(ap, func, funct, arg0, _vop, _vsop) \
234 if ((ap)->fa_fnode->fn_available == NULL) { \
235 *(func) = (funct (*)())((ap)->fa_fnode->fn_op.vnode->_vop); \
236 *(arg0) = (void *)(ap)->fa_vnode.vp; \
238 } else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fem->_vsop))\
240 *(arg0) = (void *) (ap); \
247 #define vfsop_find(ap, func, funct, arg0, _vop, _vsop) \
249 if ((ap)->fa_fnode->fn_available == NULL) { \
250 *(func) = (funct (*)())((ap)->fa_fnode->fn_op.vfs->_vop); \
251 *(arg0) = (void *)(ap)->fa_vnode.vp; \
253 } else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fsem->_vsop))\
255 *(arg0) = (void *) (ap); \
264 #define vsop_find(ap, func, funct, arg0, _vop, _vsop) \
265 *(arg0) = _op_find((ap), (void **)(func), \
266 offsetof(vnodeops_t, _vop), offsetof(fem_t, _vsop))
268 #define vfsop_find(ap, func, funct, arg0, _fop, _fsop) \
269 *(arg0) = _op_find((ap), (void **)(func), \
270 offsetof(vfsops_t, _fop), offsetof(fsem_t, _fsop))
273 _op_find(femarg_t
*ap
, void **fp
, int offs0
, int offs1
)
277 struct fem_node
*fnod
= ap
->fa_fnode
;
278 if (fnod
->fn_available
== NULL
) {
279 *fp
= *(void **)((char *)fnod
->fn_op
.anon
+ offs0
);
280 ptr
= (void *)(ap
->fa_vnode
.anon
);
282 } else if ((*fp
= *(void **)((char *)fnod
->fn_op
.anon
+offs1
))
299 p
= (fem_t
*)kmem_alloc(sizeof (*p
), KM_SLEEP
);
306 kmem_free(p
, sizeof (*p
));
314 p
= (fsem_t
*)kmem_alloc(sizeof (*p
), KM_SLEEP
);
321 kmem_free(p
, sizeof (*p
));
326 * fem_get, fem_release - manage reference counts on the stack.
328 * The list of monitors can be updated while operations are in
329 * progress on the object.
331 * The reference count facilitates this by counting the number of
332 * current accessors, and deconstructing the list when it is exhausted.
334 * fem_lock() is required to:
336 * update what femh_list points to
338 * increase femh_list->feml_refc.
340 * the feml_refc can decrement without holding the lock;
341 * when feml_refc becomes zero, the list is destroyed.
345 static struct fem_list
*
346 fem_lock(struct fem_head
*fp
)
348 struct fem_list
*sp
= NULL
;
351 mutex_enter(&fp
->femh_lock
);
357 fem_unlock(struct fem_head
*fp
)
360 mutex_exit(&fp
->femh_lock
);
364 * Addref can only be called while its head->lock is held.
368 fem_addref(struct fem_list
*sp
)
370 atomic_inc_32(&sp
->feml_refc
);
374 fem_delref(struct fem_list
*sp
)
376 return (atomic_dec_32_nv(&sp
->feml_refc
));
379 static struct fem_list
*
380 fem_get(struct fem_head
*fp
)
382 struct fem_list
*sp
= NULL
;
385 if ((sp
= fem_lock(fp
)) != NULL
) {
394 fem_release(struct fem_list
*sp
)
398 ASSERT(sp
->feml_refc
!= 0);
399 if (fem_delref(sp
) == 0) {
401 * Before freeing the list, we need to release the
402 * caller-provided data.
404 for (i
= sp
->feml_tos
; i
> 0; i
--) {
405 struct fem_node
*fnp
= &sp
->feml_nodes
[i
];
408 (*(fnp
->fn_av_rele
))(fnp
->fn_available
);
410 kmem_free(sp
, fl_ntob(sp
->feml_ssize
));
416 * These are the 'head' operations which perform the interposition.
418 * This set must be 1:1, onto with the (vnodeops, vfsos).
420 * If there is a desire to globally disable interposition for a particular
421 * method, the corresponding 'head' routine should unearth the base method
422 * and invoke it directly rather than bypassing the function.
424 * All the functions are virtually the same, save for names, types & args.
425 * 1. get a reference to the monitor stack for this object.
426 * 2. store the top of stack into the femarg structure.
427 * 3. store the basic object (vnode *, vnode **, vfs *) in the femarg struc.
428 * 4. invoke the "top" method for this object.
429 * 5. release the reference to the monitor stack.
434 vhead_open(vnode_t
**vpp
, int mode
, cred_t
*cr
, caller_context_t
*ct
)
437 struct fem_list
*femsp
;
442 if ((femsp
= fem_lock((*vpp
)->v_femhead
)) == NULL
) {
443 func
= (int (*)()) ((*vpp
)->v_op
->vop_open
);
445 fem_unlock((*vpp
)->v_femhead
);
446 errc
= (*func
)(arg0
, mode
, cr
, ct
);
449 fem_unlock((*vpp
)->v_femhead
);
450 farg
.fa_vnode
.vpp
= vpp
;
451 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
452 vsop_find(&farg
, &func
, int, &arg0
, vop_open
, femop_open
);
453 errc
= (*func
)(arg0
, mode
, cr
, ct
);
460 vhead_close(vnode_t
*vp
, int flag
, int count
, offset_t offset
, cred_t
*cr
,
461 caller_context_t
*ct
)
464 struct fem_list
*femsp
;
469 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
470 func
= (int (*)()) (vp
->v_op
->vop_close
);
472 fem_unlock(vp
->v_femhead
);
473 errc
= (*func
)(arg0
, flag
, count
, offset
, cr
, ct
);
476 fem_unlock(vp
->v_femhead
);
477 farg
.fa_vnode
.vp
= vp
;
478 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
479 vsop_find(&farg
, &func
, int, &arg0
, vop_close
, femop_close
);
480 errc
= (*func
)(arg0
, flag
, count
, offset
, cr
, ct
);
487 vhead_read(vnode_t
*vp
, uio_t
*uiop
, int ioflag
, cred_t
*cr
,
488 caller_context_t
*ct
)
491 struct fem_list
*femsp
;
496 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
497 func
= (int (*)()) (vp
->v_op
->vop_read
);
499 fem_unlock(vp
->v_femhead
);
500 errc
= (*func
)(arg0
, uiop
, ioflag
, cr
, ct
);
503 fem_unlock(vp
->v_femhead
);
504 farg
.fa_vnode
.vp
= vp
;
505 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
506 vsop_find(&farg
, &func
, int, &arg0
, vop_read
, femop_read
);
507 errc
= (*func
)(arg0
, uiop
, ioflag
, cr
, ct
);
514 vhead_write(vnode_t
*vp
, uio_t
*uiop
, int ioflag
, cred_t
*cr
,
515 caller_context_t
*ct
)
518 struct fem_list
*femsp
;
523 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
524 func
= (int (*)()) (vp
->v_op
->vop_write
);
526 fem_unlock(vp
->v_femhead
);
527 errc
= (*func
)(arg0
, uiop
, ioflag
, cr
, ct
);
530 fem_unlock(vp
->v_femhead
);
531 farg
.fa_vnode
.vp
= vp
;
532 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
533 vsop_find(&farg
, &func
, int, &arg0
, vop_write
, femop_write
);
534 errc
= (*func
)(arg0
, uiop
, ioflag
, cr
, ct
);
541 vhead_ioctl(vnode_t
*vp
, int cmd
, intptr_t arg
, int flag
, cred_t
*cr
,
542 int *rvalp
, caller_context_t
*ct
)
545 struct fem_list
*femsp
;
550 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
551 func
= (int (*)()) (vp
->v_op
->vop_ioctl
);
553 fem_unlock(vp
->v_femhead
);
554 errc
= (*func
)(arg0
, cmd
, arg
, flag
, cr
, rvalp
, ct
);
557 fem_unlock(vp
->v_femhead
);
558 farg
.fa_vnode
.vp
= vp
;
559 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
560 vsop_find(&farg
, &func
, int, &arg0
, vop_ioctl
, femop_ioctl
);
561 errc
= (*func
)(arg0
, cmd
, arg
, flag
, cr
, rvalp
, ct
);
568 vhead_setfl(vnode_t
*vp
, int oflags
, int nflags
, cred_t
*cr
,
569 caller_context_t
*ct
)
572 struct fem_list
*femsp
;
577 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
578 func
= (int (*)()) (vp
->v_op
->vop_setfl
);
580 fem_unlock(vp
->v_femhead
);
581 errc
= (*func
)(arg0
, oflags
, nflags
, cr
, ct
);
584 fem_unlock(vp
->v_femhead
);
585 farg
.fa_vnode
.vp
= vp
;
586 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
587 vsop_find(&farg
, &func
, int, &arg0
, vop_setfl
, femop_setfl
);
588 errc
= (*func
)(arg0
, oflags
, nflags
, cr
, ct
);
595 vhead_getattr(vnode_t
*vp
, vattr_t
*vap
, int flags
, cred_t
*cr
,
596 caller_context_t
*ct
)
599 struct fem_list
*femsp
;
604 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
605 func
= (int (*)()) (vp
->v_op
->vop_getattr
);
607 fem_unlock(vp
->v_femhead
);
608 errc
= (*func
)(arg0
, vap
, flags
, cr
, ct
);
611 fem_unlock(vp
->v_femhead
);
612 farg
.fa_vnode
.vp
= vp
;
613 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
614 vsop_find(&farg
, &func
, int, &arg0
, vop_getattr
,
616 errc
= (*func
)(arg0
, vap
, flags
, cr
, ct
);
623 vhead_setattr(vnode_t
*vp
, vattr_t
*vap
, int flags
, cred_t
*cr
,
624 caller_context_t
*ct
)
627 struct fem_list
*femsp
;
632 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
633 func
= (int (*)()) (vp
->v_op
->vop_setattr
);
635 fem_unlock(vp
->v_femhead
);
636 errc
= (*func
)(arg0
, vap
, flags
, cr
, ct
);
639 fem_unlock(vp
->v_femhead
);
640 farg
.fa_vnode
.vp
= vp
;
641 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
642 vsop_find(&farg
, &func
, int, &arg0
, vop_setattr
,
644 errc
= (*func
)(arg0
, vap
, flags
, cr
, ct
);
651 vhead_access(vnode_t
*vp
, int mode
, int flags
, cred_t
*cr
,
652 caller_context_t
*ct
)
655 struct fem_list
*femsp
;
660 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
661 func
= (int (*)()) (vp
->v_op
->vop_access
);
663 fem_unlock(vp
->v_femhead
);
664 errc
= (*func
)(arg0
, mode
, flags
, cr
, ct
);
667 fem_unlock(vp
->v_femhead
);
668 farg
.fa_vnode
.vp
= vp
;
669 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
670 vsop_find(&farg
, &func
, int, &arg0
, vop_access
,
672 errc
= (*func
)(arg0
, mode
, flags
, cr
, ct
);
679 vhead_lookup(vnode_t
*dvp
, char *nm
, vnode_t
**vpp
, pathname_t
*pnp
,
680 int flags
, vnode_t
*rdir
, cred_t
*cr
, caller_context_t
*ct
,
681 int *direntflags
, pathname_t
*realpnp
)
684 struct fem_list
*femsp
;
689 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
690 func
= (int (*)()) (dvp
->v_op
->vop_lookup
);
692 fem_unlock(dvp
->v_femhead
);
693 errc
= (*func
)(arg0
, nm
, vpp
, pnp
, flags
, rdir
, cr
, ct
,
694 direntflags
, realpnp
);
697 fem_unlock(dvp
->v_femhead
);
698 farg
.fa_vnode
.vp
= dvp
;
699 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
700 vsop_find(&farg
, &func
, int, &arg0
, vop_lookup
,
702 errc
= (*func
)(arg0
, nm
, vpp
, pnp
, flags
, rdir
, cr
, ct
,
703 direntflags
, realpnp
);
710 vhead_create(vnode_t
*dvp
, char *name
, vattr_t
*vap
, vcexcl_t excl
,
711 int mode
, vnode_t
**vpp
, cred_t
*cr
, int flag
, caller_context_t
*ct
,
715 struct fem_list
*femsp
;
720 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
721 func
= (int (*)()) (dvp
->v_op
->vop_create
);
723 fem_unlock(dvp
->v_femhead
);
724 errc
= (*func
)(arg0
, name
, vap
, excl
, mode
, vpp
, cr
, flag
,
728 fem_unlock(dvp
->v_femhead
);
729 farg
.fa_vnode
.vp
= dvp
;
730 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
731 vsop_find(&farg
, &func
, int, &arg0
, vop_create
,
733 errc
= (*func
)(arg0
, name
, vap
, excl
, mode
, vpp
, cr
, flag
,
741 vhead_remove(vnode_t
*dvp
, char *nm
, cred_t
*cr
, caller_context_t
*ct
,
745 struct fem_list
*femsp
;
750 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
751 func
= (int (*)()) (dvp
->v_op
->vop_remove
);
753 fem_unlock(dvp
->v_femhead
);
754 errc
= (*func
)(arg0
, nm
, cr
, ct
, flags
);
757 fem_unlock(dvp
->v_femhead
);
758 farg
.fa_vnode
.vp
= dvp
;
759 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
760 vsop_find(&farg
, &func
, int, &arg0
, vop_remove
,
762 errc
= (*func
)(arg0
, nm
, cr
, ct
, flags
);
769 vhead_link(vnode_t
*tdvp
, vnode_t
*svp
, char *tnm
, cred_t
*cr
,
770 caller_context_t
*ct
, int flags
)
773 struct fem_list
*femsp
;
778 if ((femsp
= fem_lock(tdvp
->v_femhead
)) == NULL
) {
779 func
= (int (*)()) (tdvp
->v_op
->vop_link
);
781 fem_unlock(tdvp
->v_femhead
);
782 errc
= (*func
)(arg0
, svp
, tnm
, cr
, ct
, flags
);
785 fem_unlock(tdvp
->v_femhead
);
786 farg
.fa_vnode
.vp
= tdvp
;
787 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
788 vsop_find(&farg
, &func
, int, &arg0
, vop_link
, femop_link
);
789 errc
= (*func
)(arg0
, svp
, tnm
, cr
, ct
, flags
);
796 vhead_rename(vnode_t
*sdvp
, char *snm
, vnode_t
*tdvp
, char *tnm
,
797 cred_t
*cr
, caller_context_t
*ct
, int flags
)
800 struct fem_list
*femsp
;
805 if ((femsp
= fem_lock(sdvp
->v_femhead
)) == NULL
) {
806 func
= (int (*)()) (sdvp
->v_op
->vop_rename
);
808 fem_unlock(sdvp
->v_femhead
);
809 errc
= (*func
)(arg0
, snm
, tdvp
, tnm
, cr
, ct
, flags
);
812 fem_unlock(sdvp
->v_femhead
);
813 farg
.fa_vnode
.vp
= sdvp
;
814 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
815 vsop_find(&farg
, &func
, int, &arg0
, vop_rename
,
817 errc
= (*func
)(arg0
, snm
, tdvp
, tnm
, cr
, ct
, flags
);
824 vhead_mkdir(vnode_t
*dvp
, char *dirname
, vattr_t
*vap
, vnode_t
**vpp
,
825 cred_t
*cr
, caller_context_t
*ct
, int flags
, vsecattr_t
*vsecp
)
828 struct fem_list
*femsp
;
833 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
834 func
= (int (*)()) (dvp
->v_op
->vop_mkdir
);
836 fem_unlock(dvp
->v_femhead
);
837 errc
= (*func
)(arg0
, dirname
, vap
, vpp
, cr
, ct
, flags
, vsecp
);
840 fem_unlock(dvp
->v_femhead
);
841 farg
.fa_vnode
.vp
= dvp
;
842 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
843 vsop_find(&farg
, &func
, int, &arg0
, vop_mkdir
, femop_mkdir
);
844 errc
= (*func
)(arg0
, dirname
, vap
, vpp
, cr
, ct
, flags
, vsecp
);
851 vhead_rmdir(vnode_t
*dvp
, char *nm
, vnode_t
*cdir
, cred_t
*cr
,
852 caller_context_t
*ct
, int flags
)
855 struct fem_list
*femsp
;
860 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
861 func
= (int (*)()) (dvp
->v_op
->vop_rmdir
);
863 fem_unlock(dvp
->v_femhead
);
864 errc
= (*func
)(arg0
, nm
, cdir
, cr
, ct
, flags
);
867 fem_unlock(dvp
->v_femhead
);
868 farg
.fa_vnode
.vp
= dvp
;
869 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
870 vsop_find(&farg
, &func
, int, &arg0
, vop_rmdir
, femop_rmdir
);
871 errc
= (*func
)(arg0
, nm
, cdir
, cr
, ct
, flags
);
878 vhead_readdir(vnode_t
*vp
, uio_t
*uiop
, cred_t
*cr
, int *eofp
,
879 caller_context_t
*ct
, int flags
)
882 struct fem_list
*femsp
;
887 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
888 func
= (int (*)()) (vp
->v_op
->vop_readdir
);
890 fem_unlock(vp
->v_femhead
);
891 errc
= (*func
)(arg0
, uiop
, cr
, eofp
, ct
, flags
);
894 fem_unlock(vp
->v_femhead
);
895 farg
.fa_vnode
.vp
= vp
;
896 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
897 vsop_find(&farg
, &func
, int, &arg0
, vop_readdir
,
899 errc
= (*func
)(arg0
, uiop
, cr
, eofp
, ct
, flags
);
906 vhead_symlink(vnode_t
*dvp
, char *linkname
, vattr_t
*vap
, char *target
,
907 cred_t
*cr
, caller_context_t
*ct
, int flags
)
910 struct fem_list
*femsp
;
915 if ((femsp
= fem_lock(dvp
->v_femhead
)) == NULL
) {
916 func
= (int (*)()) (dvp
->v_op
->vop_symlink
);
918 fem_unlock(dvp
->v_femhead
);
919 errc
= (*func
)(arg0
, linkname
, vap
, target
, cr
, ct
, flags
);
922 fem_unlock(dvp
->v_femhead
);
923 farg
.fa_vnode
.vp
= dvp
;
924 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
925 vsop_find(&farg
, &func
, int, &arg0
, vop_symlink
,
927 errc
= (*func
)(arg0
, linkname
, vap
, target
, cr
, ct
, flags
);
934 vhead_readlink(vnode_t
*vp
, uio_t
*uiop
, cred_t
*cr
, caller_context_t
*ct
)
937 struct fem_list
*femsp
;
942 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
943 func
= (int (*)()) (vp
->v_op
->vop_readlink
);
945 fem_unlock(vp
->v_femhead
);
946 errc
= (*func
)(arg0
, uiop
, cr
, ct
);
949 fem_unlock(vp
->v_femhead
);
950 farg
.fa_vnode
.vp
= vp
;
951 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
952 vsop_find(&farg
, &func
, int, &arg0
, vop_readlink
,
954 errc
= (*func
)(arg0
, uiop
, cr
, ct
);
961 vhead_fsync(vnode_t
*vp
, int syncflag
, cred_t
*cr
, caller_context_t
*ct
)
964 struct fem_list
*femsp
;
969 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
970 func
= (int (*)()) (vp
->v_op
->vop_fsync
);
972 fem_unlock(vp
->v_femhead
);
973 errc
= (*func
)(arg0
, syncflag
, cr
, ct
);
976 fem_unlock(vp
->v_femhead
);
977 farg
.fa_vnode
.vp
= vp
;
978 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
979 vsop_find(&farg
, &func
, int, &arg0
, vop_fsync
, femop_fsync
);
980 errc
= (*func
)(arg0
, syncflag
, cr
, ct
);
987 vhead_inactive(vnode_t
*vp
, cred_t
*cr
, caller_context_t
*ct
)
990 struct fem_list
*femsp
;
994 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
995 func
= (void (*)()) (vp
->v_op
->vop_inactive
);
997 fem_unlock(vp
->v_femhead
);
998 (*func
)(arg0
, cr
, ct
);
1001 fem_unlock(vp
->v_femhead
);
1002 farg
.fa_vnode
.vp
= vp
;
1003 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1004 vsop_find(&farg
, &func
, void, &arg0
, vop_inactive
,
1006 (*func
)(arg0
, cr
, ct
);
1012 vhead_fid(vnode_t
*vp
, fid_t
*fidp
, caller_context_t
*ct
)
1015 struct fem_list
*femsp
;
1020 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1021 func
= (int (*)()) (vp
->v_op
->vop_fid
);
1023 fem_unlock(vp
->v_femhead
);
1024 errc
= (*func
)(arg0
, fidp
, ct
);
1027 fem_unlock(vp
->v_femhead
);
1028 farg
.fa_vnode
.vp
= vp
;
1029 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1030 vsop_find(&farg
, &func
, int, &arg0
, vop_fid
, femop_fid
);
1031 errc
= (*func
)(arg0
, fidp
, ct
);
1038 vhead_rwlock(vnode_t
*vp
, int write_lock
, caller_context_t
*ct
)
1041 struct fem_list
*femsp
;
1046 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1047 func
= (int (*)()) (vp
->v_op
->vop_rwlock
);
1049 fem_unlock(vp
->v_femhead
);
1050 errc
= (*func
)(arg0
, write_lock
, ct
);
1053 fem_unlock(vp
->v_femhead
);
1054 farg
.fa_vnode
.vp
= vp
;
1055 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1056 vsop_find(&farg
, &func
, int, &arg0
, vop_rwlock
,
1058 errc
= (*func
)(arg0
, write_lock
, ct
);
1065 vhead_rwunlock(vnode_t
*vp
, int write_lock
, caller_context_t
*ct
)
1068 struct fem_list
*femsp
;
1072 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1073 func
= (void (*)()) (vp
->v_op
->vop_rwunlock
);
1075 fem_unlock(vp
->v_femhead
);
1076 (*func
)(arg0
, write_lock
, ct
);
1079 fem_unlock(vp
->v_femhead
);
1080 farg
.fa_vnode
.vp
= vp
;
1081 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1082 vsop_find(&farg
, &func
, void, &arg0
, vop_rwunlock
,
1084 (*func
)(arg0
, write_lock
, ct
);
1090 vhead_seek(vnode_t
*vp
, offset_t ooff
, offset_t
*noffp
, caller_context_t
*ct
)
1093 struct fem_list
*femsp
;
1098 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1099 func
= (int (*)()) (vp
->v_op
->vop_seek
);
1101 fem_unlock(vp
->v_femhead
);
1102 errc
= (*func
)(arg0
, ooff
, noffp
, ct
);
1105 fem_unlock(vp
->v_femhead
);
1106 farg
.fa_vnode
.vp
= vp
;
1107 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1108 vsop_find(&farg
, &func
, int, &arg0
, vop_seek
, femop_seek
);
1109 errc
= (*func
)(arg0
, ooff
, noffp
, ct
);
1116 vhead_cmp(vnode_t
*vp1
, vnode_t
*vp2
, caller_context_t
*ct
)
1119 struct fem_list
*femsp
;
1124 if ((femsp
= fem_lock(vp1
->v_femhead
)) == NULL
) {
1125 func
= (int (*)()) (vp1
->v_op
->vop_cmp
);
1127 fem_unlock(vp1
->v_femhead
);
1128 errc
= (*func
)(arg0
, vp2
, ct
);
1131 fem_unlock(vp1
->v_femhead
);
1132 farg
.fa_vnode
.vp
= vp1
;
1133 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1134 vsop_find(&farg
, &func
, int, &arg0
, vop_cmp
, femop_cmp
);
1135 errc
= (*func
)(arg0
, vp2
, ct
);
1142 vhead_frlock(vnode_t
*vp
, int cmd
, struct flock64
*bfp
, int flag
,
1143 offset_t offset
, struct flk_callback
*flk_cbp
, cred_t
*cr
,
1144 caller_context_t
*ct
)
1147 struct fem_list
*femsp
;
1152 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1153 func
= (int (*)()) (vp
->v_op
->vop_frlock
);
1155 fem_unlock(vp
->v_femhead
);
1156 errc
= (*func
)(arg0
, cmd
, bfp
, flag
, offset
, flk_cbp
, cr
, ct
);
1159 fem_unlock(vp
->v_femhead
);
1160 farg
.fa_vnode
.vp
= vp
;
1161 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1162 vsop_find(&farg
, &func
, int, &arg0
, vop_frlock
,
1164 errc
= (*func
)(arg0
, cmd
, bfp
, flag
, offset
, flk_cbp
, cr
, ct
);
1171 vhead_space(vnode_t
*vp
, int cmd
, struct flock64
*bfp
, int flag
,
1172 offset_t offset
, cred_t
*cr
, caller_context_t
*ct
)
1175 struct fem_list
*femsp
;
1180 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1181 func
= (int (*)()) (vp
->v_op
->vop_space
);
1183 fem_unlock(vp
->v_femhead
);
1184 errc
= (*func
)(arg0
, cmd
, bfp
, flag
, offset
, cr
, ct
);
1187 fem_unlock(vp
->v_femhead
);
1188 farg
.fa_vnode
.vp
= vp
;
1189 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1190 vsop_find(&farg
, &func
, int, &arg0
, vop_space
, femop_space
);
1191 errc
= (*func
)(arg0
, cmd
, bfp
, flag
, offset
, cr
, ct
);
1198 vhead_realvp(vnode_t
*vp
, vnode_t
**vpp
, caller_context_t
*ct
)
1201 struct fem_list
*femsp
;
1206 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1207 func
= (int (*)()) (vp
->v_op
->vop_realvp
);
1209 fem_unlock(vp
->v_femhead
);
1210 errc
= (*func
)(arg0
, vpp
, ct
);
1213 fem_unlock(vp
->v_femhead
);
1214 farg
.fa_vnode
.vp
= vp
;
1215 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1216 vsop_find(&farg
, &func
, int, &arg0
, vop_realvp
,
1218 errc
= (*func
)(arg0
, vpp
, ct
);
1225 vhead_getpage(vnode_t
*vp
, offset_t off
, size_t len
, uint_t
*protp
,
1226 struct page
**plarr
, size_t plsz
, struct seg
*seg
, caddr_t addr
,
1227 enum seg_rw rw
, cred_t
*cr
, caller_context_t
*ct
)
1230 struct fem_list
*femsp
;
1235 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1236 func
= (int (*)()) (vp
->v_op
->vop_getpage
);
1238 fem_unlock(vp
->v_femhead
);
1239 errc
= (*func
)(arg0
, off
, len
, protp
, plarr
, plsz
, seg
,
1243 fem_unlock(vp
->v_femhead
);
1244 farg
.fa_vnode
.vp
= vp
;
1245 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1246 vsop_find(&farg
, &func
, int, &arg0
, vop_getpage
,
1248 errc
= (*func
)(arg0
, off
, len
, protp
, plarr
, plsz
, seg
,
1256 vhead_putpage(vnode_t
*vp
, offset_t off
, size_t len
, int flags
, cred_t
*cr
,
1257 caller_context_t
*ct
)
1260 struct fem_list
*femsp
;
1265 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1266 func
= (int (*)()) (vp
->v_op
->vop_putpage
);
1268 fem_unlock(vp
->v_femhead
);
1269 errc
= (*func
)(arg0
, off
, len
, flags
, cr
, ct
);
1272 fem_unlock(vp
->v_femhead
);
1273 farg
.fa_vnode
.vp
= vp
;
1274 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1275 vsop_find(&farg
, &func
, int, &arg0
, vop_putpage
,
1277 errc
= (*func
)(arg0
, off
, len
, flags
, cr
, ct
);
1284 vhead_map(vnode_t
*vp
, offset_t off
, struct as
*as
, caddr_t
*addrp
,
1285 size_t len
, uchar_t prot
, uchar_t maxprot
, uint_t flags
,
1286 cred_t
*cr
, caller_context_t
*ct
)
1289 struct fem_list
*femsp
;
1294 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1295 func
= (int (*)()) (vp
->v_op
->vop_map
);
1297 fem_unlock(vp
->v_femhead
);
1298 errc
= (*func
)(arg0
, off
, as
, addrp
, len
, prot
, maxprot
,
1302 fem_unlock(vp
->v_femhead
);
1303 farg
.fa_vnode
.vp
= vp
;
1304 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1305 vsop_find(&farg
, &func
, int, &arg0
, vop_map
, femop_map
);
1306 errc
= (*func
)(arg0
, off
, as
, addrp
, len
, prot
, maxprot
,
1314 vhead_addmap(vnode_t
*vp
, offset_t off
, struct as
*as
, caddr_t addr
,
1315 size_t len
, uchar_t prot
, uchar_t maxprot
, uint_t flags
,
1316 cred_t
*cr
, caller_context_t
*ct
)
1319 struct fem_list
*femsp
;
1324 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1325 func
= (int (*)()) (vp
->v_op
->vop_addmap
);
1327 fem_unlock(vp
->v_femhead
);
1328 errc
= (*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
,
1332 fem_unlock(vp
->v_femhead
);
1333 farg
.fa_vnode
.vp
= vp
;
1334 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1335 vsop_find(&farg
, &func
, int, &arg0
, vop_addmap
,
1337 errc
= (*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
,
1345 vhead_delmap(vnode_t
*vp
, offset_t off
, struct as
*as
, caddr_t addr
,
1346 size_t len
, uint_t prot
, uint_t maxprot
, uint_t flags
, cred_t
*cr
,
1347 caller_context_t
*ct
)
1350 struct fem_list
*femsp
;
1355 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1356 func
= (int (*)()) (vp
->v_op
->vop_delmap
);
1358 fem_unlock(vp
->v_femhead
);
1359 errc
= (*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
,
1363 fem_unlock(vp
->v_femhead
);
1364 farg
.fa_vnode
.vp
= vp
;
1365 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1366 vsop_find(&farg
, &func
, int, &arg0
, vop_delmap
,
1368 errc
= (*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
,
1376 vhead_poll(vnode_t
*vp
, short events
, int anyyet
, short *reventsp
,
1377 struct pollhead
**phpp
, caller_context_t
*ct
)
1380 struct fem_list
*femsp
;
1385 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1386 func
= (int (*)()) (vp
->v_op
->vop_poll
);
1388 fem_unlock(vp
->v_femhead
);
1389 errc
= (*func
)(arg0
, events
, anyyet
, reventsp
, phpp
, ct
);
1392 fem_unlock(vp
->v_femhead
);
1393 farg
.fa_vnode
.vp
= vp
;
1394 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1395 vsop_find(&farg
, &func
, int, &arg0
, vop_poll
, femop_poll
);
1396 errc
= (*func
)(arg0
, events
, anyyet
, reventsp
, phpp
, ct
);
1403 vhead_dump(vnode_t
*vp
, caddr_t addr
, offset_t lbdn
, offset_t dblks
,
1404 caller_context_t
*ct
)
1407 struct fem_list
*femsp
;
1412 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1413 func
= (int (*)()) (vp
->v_op
->vop_dump
);
1415 fem_unlock(vp
->v_femhead
);
1416 errc
= (*func
)(arg0
, addr
, lbdn
, dblks
, ct
);
1419 fem_unlock(vp
->v_femhead
);
1420 farg
.fa_vnode
.vp
= vp
;
1421 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1422 vsop_find(&farg
, &func
, int, &arg0
, vop_dump
, femop_dump
);
1423 errc
= (*func
)(arg0
, addr
, lbdn
, dblks
, ct
);
1430 vhead_pathconf(vnode_t
*vp
, int cmd
, ulong_t
*valp
, cred_t
*cr
,
1431 caller_context_t
*ct
)
1434 struct fem_list
*femsp
;
1439 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1440 func
= (int (*)()) (vp
->v_op
->vop_pathconf
);
1442 fem_unlock(vp
->v_femhead
);
1443 errc
= (*func
)(arg0
, cmd
, valp
, cr
, ct
);
1446 fem_unlock(vp
->v_femhead
);
1447 farg
.fa_vnode
.vp
= vp
;
1448 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1449 vsop_find(&farg
, &func
, int, &arg0
, vop_pathconf
,
1451 errc
= (*func
)(arg0
, cmd
, valp
, cr
, ct
);
1458 vhead_pageio(vnode_t
*vp
, struct page
*pp
, uoff_t io_off
,
1459 size_t io_len
, int flags
, cred_t
*cr
, caller_context_t
*ct
)
1462 struct fem_list
*femsp
;
1467 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1468 func
= (int (*)()) (vp
->v_op
->vop_pageio
);
1470 fem_unlock(vp
->v_femhead
);
1471 errc
= (*func
)(arg0
, pp
, io_off
, io_len
, flags
, cr
, ct
);
1474 fem_unlock(vp
->v_femhead
);
1475 farg
.fa_vnode
.vp
= vp
;
1476 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1477 vsop_find(&farg
, &func
, int, &arg0
, vop_pageio
,
1479 errc
= (*func
)(arg0
, pp
, io_off
, io_len
, flags
, cr
, ct
);
1486 vhead_dumpctl(vnode_t
*vp
, int action
, offset_t
*blkp
, caller_context_t
*ct
)
1489 struct fem_list
*femsp
;
1494 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1495 func
= (int (*)()) (vp
->v_op
->vop_dumpctl
);
1497 fem_unlock(vp
->v_femhead
);
1498 errc
= (*func
)(arg0
, action
, blkp
, ct
);
1501 fem_unlock(vp
->v_femhead
);
1502 farg
.fa_vnode
.vp
= vp
;
1503 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1504 vsop_find(&farg
, &func
, int, &arg0
, vop_dumpctl
,
1506 errc
= (*func
)(arg0
, action
, blkp
, ct
);
1513 vhead_dispose(vnode_t
*vp
, struct page
*pp
, int flag
, int dn
, cred_t
*cr
,
1514 caller_context_t
*ct
)
1517 struct fem_list
*femsp
;
1521 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1522 func
= (void (*)()) (vp
->v_op
->vop_dispose
);
1524 fem_unlock(vp
->v_femhead
);
1525 (*func
)(arg0
, pp
, flag
, dn
, cr
, ct
);
1528 fem_unlock(vp
->v_femhead
);
1529 farg
.fa_vnode
.vp
= vp
;
1530 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1531 vsop_find(&farg
, &func
, void, &arg0
, vop_dispose
,
1533 (*func
)(arg0
, pp
, flag
, dn
, cr
, ct
);
1539 vhead_setsecattr(vnode_t
*vp
, vsecattr_t
*vsap
, int flag
, cred_t
*cr
,
1540 caller_context_t
*ct
)
1543 struct fem_list
*femsp
;
1548 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1549 func
= (int (*)()) (vp
->v_op
->vop_setsecattr
);
1551 fem_unlock(vp
->v_femhead
);
1552 errc
= (*func
)(arg0
, vsap
, flag
, cr
, ct
);
1555 fem_unlock(vp
->v_femhead
);
1556 farg
.fa_vnode
.vp
= vp
;
1557 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1558 vsop_find(&farg
, &func
, int, &arg0
, vop_setsecattr
,
1560 errc
= (*func
)(arg0
, vsap
, flag
, cr
, ct
);
1567 vhead_getsecattr(vnode_t
*vp
, vsecattr_t
*vsap
, int flag
, cred_t
*cr
,
1568 caller_context_t
*ct
)
1571 struct fem_list
*femsp
;
1576 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1577 func
= (int (*)()) (vp
->v_op
->vop_getsecattr
);
1579 fem_unlock(vp
->v_femhead
);
1580 errc
= (*func
)(arg0
, vsap
, flag
, cr
, ct
);
1583 fem_unlock(vp
->v_femhead
);
1584 farg
.fa_vnode
.vp
= vp
;
1585 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1586 vsop_find(&farg
, &func
, int, &arg0
, vop_getsecattr
,
1588 errc
= (*func
)(arg0
, vsap
, flag
, cr
, ct
);
1595 vhead_shrlock(vnode_t
*vp
, int cmd
, struct shrlock
*shr
, int flag
,
1596 cred_t
*cr
, caller_context_t
*ct
)
1599 struct fem_list
*femsp
;
1604 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1605 func
= (int (*)()) (vp
->v_op
->vop_shrlock
);
1607 fem_unlock(vp
->v_femhead
);
1608 errc
= (*func
)(arg0
, cmd
, shr
, flag
, cr
, ct
);
1611 fem_unlock(vp
->v_femhead
);
1612 farg
.fa_vnode
.vp
= vp
;
1613 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1614 vsop_find(&farg
, &func
, int, &arg0
, vop_shrlock
,
1616 errc
= (*func
)(arg0
, cmd
, shr
, flag
, cr
, ct
);
1623 vhead_vnevent(vnode_t
*vp
, vnevent_t vnevent
, vnode_t
*dvp
, char *cname
,
1624 caller_context_t
*ct
)
1627 struct fem_list
*femsp
;
1632 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1633 func
= (int (*)()) (vp
->v_op
->vop_vnevent
);
1635 fem_unlock(vp
->v_femhead
);
1636 errc
= (*func
)(arg0
, vnevent
, dvp
, cname
, ct
);
1639 fem_unlock(vp
->v_femhead
);
1640 farg
.fa_vnode
.vp
= vp
;
1641 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1642 vsop_find(&farg
, &func
, int, &arg0
, vop_vnevent
,
1644 errc
= (*func
)(arg0
, vnevent
, dvp
, cname
, ct
);
1651 vhead_reqzcbuf(vnode_t
*vp
, enum uio_rw ioflag
, xuio_t
*xuiop
, cred_t
*cr
,
1652 caller_context_t
*ct
)
1655 struct fem_list
*femsp
;
1660 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1661 func
= (int (*)()) (vp
->v_op
->vop_reqzcbuf
);
1663 fem_unlock(vp
->v_femhead
);
1664 errc
= (*func
)(arg0
, ioflag
, xuiop
, cr
, ct
);
1667 fem_unlock(vp
->v_femhead
);
1668 farg
.fa_vnode
.vp
= vp
;
1669 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1670 vsop_find(&farg
, &func
, int, &arg0
, vop_reqzcbuf
,
1672 errc
= (*func
)(arg0
, ioflag
, xuiop
, cr
, ct
);
1679 vhead_retzcbuf(vnode_t
*vp
, xuio_t
*xuiop
, cred_t
*cr
, caller_context_t
*ct
)
1682 struct fem_list
*femsp
;
1687 if ((femsp
= fem_lock(vp
->v_femhead
)) == NULL
) {
1688 func
= (int (*)()) (vp
->v_op
->vop_retzcbuf
);
1690 fem_unlock(vp
->v_femhead
);
1691 errc
= (*func
)(arg0
, xuiop
, cr
, ct
);
1694 fem_unlock(vp
->v_femhead
);
1695 farg
.fa_vnode
.vp
= vp
;
1696 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1697 vsop_find(&farg
, &func
, int, &arg0
, vop_retzcbuf
,
1699 errc
= (*func
)(arg0
, xuiop
, cr
, ct
);
1706 fshead_mount(vfs_t
*vfsp
, vnode_t
*mvp
, struct mounta
*uap
, cred_t
*cr
)
1709 struct fem_list
*femsp
;
1714 ASSERT(vfsp
->vfs_implp
);
1716 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1717 func
= (int (*)()) vfsp
->vfs_op
->vfs_mount
;
1718 fem_unlock(vfsp
->vfs_femhead
);
1719 errc
= (*func
)(vfsp
, mvp
, uap
, cr
);
1722 fem_unlock(vfsp
->vfs_femhead
);
1723 farg
.fa_vnode
.vfsp
= vfsp
;
1724 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1725 vfsop_find(&farg
, &func
, int, &arg0
, vfs_mount
,
1727 errc
= (*func
)(arg0
, mvp
, uap
, cr
);
1734 fshead_unmount(vfs_t
*vfsp
, int flag
, cred_t
*cr
)
1737 struct fem_list
*femsp
;
1742 ASSERT(vfsp
->vfs_implp
);
1744 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1745 func
= (int (*)()) vfsp
->vfs_op
->vfs_unmount
;
1746 fem_unlock(vfsp
->vfs_femhead
);
1747 errc
= (*func
)(vfsp
, flag
, cr
);
1750 fem_unlock(vfsp
->vfs_femhead
);
1751 farg
.fa_vnode
.vfsp
= vfsp
;
1752 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1753 vfsop_find(&farg
, &func
, int, &arg0
, vfs_unmount
,
1755 errc
= (*func
)(arg0
, flag
, cr
);
1762 fshead_root(vfs_t
*vfsp
, vnode_t
**vpp
)
1765 struct fem_list
*femsp
;
1770 ASSERT(vfsp
->vfs_implp
);
1772 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1773 func
= (int (*)()) vfsp
->vfs_op
->vfs_root
;
1774 fem_unlock(vfsp
->vfs_femhead
);
1775 errc
= (*func
)(vfsp
, vpp
);
1778 fem_unlock(vfsp
->vfs_femhead
);
1779 farg
.fa_vnode
.vfsp
= vfsp
;
1780 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1781 vfsop_find(&farg
, &func
, int, &arg0
, vfs_root
, fsemop_root
);
1782 errc
= (*func
)(arg0
, vpp
);
1789 fshead_statvfs(vfs_t
*vfsp
, statvfs64_t
*sp
)
1792 struct fem_list
*femsp
;
1797 ASSERT(vfsp
->vfs_implp
);
1799 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1800 func
= (int (*)()) vfsp
->vfs_op
->vfs_statvfs
;
1801 fem_unlock(vfsp
->vfs_femhead
);
1802 errc
= (*func
)(vfsp
, sp
);
1805 fem_unlock(vfsp
->vfs_femhead
);
1806 farg
.fa_vnode
.vfsp
= vfsp
;
1807 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1808 vfsop_find(&farg
, &func
, int, &arg0
, vfs_statvfs
,
1810 errc
= (*func
)(arg0
, sp
);
1817 fshead_sync(vfs_t
*vfsp
, short flag
, cred_t
*cr
)
1820 struct fem_list
*femsp
;
1825 ASSERT(vfsp
->vfs_implp
);
1827 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1828 func
= (int (*)()) vfsp
->vfs_op
->vfs_sync
;
1829 fem_unlock(vfsp
->vfs_femhead
);
1830 errc
= (*func
)(vfsp
, flag
, cr
);
1833 fem_unlock(vfsp
->vfs_femhead
);
1834 farg
.fa_vnode
.vfsp
= vfsp
;
1835 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1836 vfsop_find(&farg
, &func
, int, &arg0
, vfs_sync
, fsemop_sync
);
1837 errc
= (*func
)(arg0
, flag
, cr
);
1844 fshead_vget(vfs_t
*vfsp
, vnode_t
**vpp
, fid_t
*fidp
)
1847 struct fem_list
*femsp
;
1852 ASSERT(vfsp
->vfs_implp
);
1854 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1855 func
= (int (*)()) vfsp
->vfs_op
->vfs_vget
;
1856 fem_unlock(vfsp
->vfs_femhead
);
1857 errc
= (*func
)(vfsp
, vpp
, fidp
);
1860 fem_unlock(vfsp
->vfs_femhead
);
1861 farg
.fa_vnode
.vfsp
= vfsp
;
1862 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1863 vfsop_find(&farg
, &func
, int, &arg0
, vfs_vget
, fsemop_vget
);
1864 errc
= (*func
)(arg0
, vpp
, fidp
);
1871 fshead_mountroot(vfs_t
*vfsp
, enum whymountroot reason
)
1874 struct fem_list
*femsp
;
1879 ASSERT(vfsp
->vfs_implp
);
1881 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1882 func
= (int (*)()) vfsp
->vfs_op
->vfs_mountroot
;
1883 fem_unlock(vfsp
->vfs_femhead
);
1884 errc
= (*func
)(vfsp
, reason
);
1887 fem_unlock(vfsp
->vfs_femhead
);
1888 farg
.fa_vnode
.vfsp
= vfsp
;
1889 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1890 vfsop_find(&farg
, &func
, int, &arg0
, vfs_mountroot
,
1892 errc
= (*func
)(arg0
, reason
);
1899 fshead_freevfs(vfs_t
*vfsp
)
1902 struct fem_list
*femsp
;
1906 ASSERT(vfsp
->vfs_implp
);
1908 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1909 func
= (void (*)()) vfsp
->vfs_op
->vfs_freevfs
;
1910 fem_unlock(vfsp
->vfs_femhead
);
1914 fem_unlock(vfsp
->vfs_femhead
);
1915 farg
.fa_vnode
.vfsp
= vfsp
;
1916 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1917 vfsop_find(&farg
, &func
, void, &arg0
, vfs_freevfs
,
1925 fshead_vnstate(vfs_t
*vfsp
, vnode_t
*vp
, vntrans_t nstate
)
1928 struct fem_list
*femsp
;
1933 ASSERT(vfsp
->vfs_implp
);
1935 if ((femsp
= fem_lock(vfsp
->vfs_femhead
)) == NULL
) {
1936 func
= (int (*)()) vfsp
->vfs_op
->vfs_vnstate
;
1937 fem_unlock(vfsp
->vfs_femhead
);
1938 errc
= (*func
)(vfsp
, vp
, nstate
);
1941 fem_unlock(vfsp
->vfs_femhead
);
1942 farg
.fa_vnode
.vfsp
= vfsp
;
1943 farg
.fa_fnode
= femsp
->feml_nodes
+ femsp
->feml_tos
;
1944 vfsop_find(&farg
, &func
, int, &arg0
, vfs_vnstate
,
1946 errc
= (*func
)(arg0
, vp
, nstate
);
1954 * specification table for the vhead vnode operations.
1955 * It is an error for any operations to be missing.
1958 static struct fs_operation_def fhead_vn_spec
[] = {
1959 { VOPNAME_OPEN
, (femop_t
*)vhead_open
},
1960 { VOPNAME_CLOSE
, (femop_t
*)vhead_close
},
1961 { VOPNAME_READ
, (femop_t
*)vhead_read
},
1962 { VOPNAME_WRITE
, (femop_t
*)vhead_write
},
1963 { VOPNAME_IOCTL
, (femop_t
*)vhead_ioctl
},
1964 { VOPNAME_SETFL
, (femop_t
*)vhead_setfl
},
1965 { VOPNAME_GETATTR
, (femop_t
*)vhead_getattr
},
1966 { VOPNAME_SETATTR
, (femop_t
*)vhead_setattr
},
1967 { VOPNAME_ACCESS
, (femop_t
*)vhead_access
},
1968 { VOPNAME_LOOKUP
, (femop_t
*)vhead_lookup
},
1969 { VOPNAME_CREATE
, (femop_t
*)vhead_create
},
1970 { VOPNAME_REMOVE
, (femop_t
*)vhead_remove
},
1971 { VOPNAME_LINK
, (femop_t
*)vhead_link
},
1972 { VOPNAME_RENAME
, (femop_t
*)vhead_rename
},
1973 { VOPNAME_MKDIR
, (femop_t
*)vhead_mkdir
},
1974 { VOPNAME_RMDIR
, (femop_t
*)vhead_rmdir
},
1975 { VOPNAME_READDIR
, (femop_t
*)vhead_readdir
},
1976 { VOPNAME_SYMLINK
, (femop_t
*)vhead_symlink
},
1977 { VOPNAME_READLINK
, (femop_t
*)vhead_readlink
},
1978 { VOPNAME_FSYNC
, (femop_t
*)vhead_fsync
},
1979 { VOPNAME_INACTIVE
, (femop_t
*)vhead_inactive
},
1980 { VOPNAME_FID
, (femop_t
*)vhead_fid
},
1981 { VOPNAME_RWLOCK
, (femop_t
*)vhead_rwlock
},
1982 { VOPNAME_RWUNLOCK
, (femop_t
*)vhead_rwunlock
},
1983 { VOPNAME_SEEK
, (femop_t
*)vhead_seek
},
1984 { VOPNAME_CMP
, (femop_t
*)vhead_cmp
},
1985 { VOPNAME_FRLOCK
, (femop_t
*)vhead_frlock
},
1986 { VOPNAME_SPACE
, (femop_t
*)vhead_space
},
1987 { VOPNAME_REALVP
, (femop_t
*)vhead_realvp
},
1988 { VOPNAME_GETPAGE
, (femop_t
*)vhead_getpage
},
1989 { VOPNAME_PUTPAGE
, (femop_t
*)vhead_putpage
},
1990 { VOPNAME_MAP
, (femop_t
*)vhead_map
},
1991 { VOPNAME_ADDMAP
, (femop_t
*)vhead_addmap
},
1992 { VOPNAME_DELMAP
, (femop_t
*)vhead_delmap
},
1993 { VOPNAME_POLL
, (femop_t
*)vhead_poll
},
1994 { VOPNAME_DUMP
, (femop_t
*)vhead_dump
},
1995 { VOPNAME_PATHCONF
, (femop_t
*)vhead_pathconf
},
1996 { VOPNAME_PAGEIO
, (femop_t
*)vhead_pageio
},
1997 { VOPNAME_DUMPCTL
, (femop_t
*)vhead_dumpctl
},
1998 { VOPNAME_DISPOSE
, (femop_t
*)vhead_dispose
},
1999 { VOPNAME_SETSECATTR
, (femop_t
*)vhead_setsecattr
},
2000 { VOPNAME_GETSECATTR
, (femop_t
*)vhead_getsecattr
},
2001 { VOPNAME_SHRLOCK
, (femop_t
*)vhead_shrlock
},
2002 { VOPNAME_VNEVENT
, (femop_t
*)vhead_vnevent
},
2003 { VOPNAME_REQZCBUF
, (femop_t
*)vhead_reqzcbuf
},
2004 { VOPNAME_RETZCBUF
, (femop_t
*)vhead_retzcbuf
},
2009 * specification table for the vfshead vnode operations.
2010 * It is an error for any operations to be missing.
2013 static struct fs_operation_def fshead_vfs_spec
[] = {
2014 { VFSNAME_MOUNT
, (femop_t
*)fshead_mount
},
2015 { VFSNAME_UNMOUNT
, (femop_t
*)fshead_unmount
},
2016 { VFSNAME_ROOT
, (femop_t
*)fshead_root
},
2017 { VFSNAME_STATVFS
, (femop_t
*)fshead_statvfs
},
2018 { VFSNAME_SYNC
, (femop_t
*)fshead_sync
},
2019 { VFSNAME_VGET
, (femop_t
*)fshead_vget
},
2020 { VFSNAME_MOUNTROOT
, (femop_t
*)fshead_mountroot
},
2021 { VFSNAME_FREEVFS
, (femop_t
*)fshead_freevfs
},
2022 { VFSNAME_VNSTATE
, (femop_t
*)fshead_vnstate
},
2027 * This set of routines transfer control to the next stacked monitor.
2029 * Each routine is identical except for naming, types and arguments.
2031 * The basic steps are:
2032 * 1. Decrease the stack pointer by one.
2033 * 2. If the current item is a base operation (vnode, vfs), goto 5.
2034 * 3. If the current item does not have a corresponding operation, goto 1
2035 * 4. Return by invoking the current item with the argument handle.
2036 * 5. Return by invoking the base operation with the base object.
2038 * for each classification, there needs to be at least one "next" operation
2039 * for each "head"operation.
2044 vnext_open(femarg_t
*vf
, int mode
, cred_t
*cr
, caller_context_t
*ct
)
2046 int (*func
)() = NULL
;
2051 vsop_find(vf
, &func
, int, &arg0
, vop_open
, femop_open
);
2052 ASSERT(func
!= NULL
);
2053 ASSERT(arg0
!= NULL
);
2054 return ((*func
)(arg0
, mode
, cr
, ct
));
2058 vnext_close(femarg_t
*vf
, int flag
, int count
, offset_t offset
, cred_t
*cr
,
2059 caller_context_t
*ct
)
2061 int (*func
)() = NULL
;
2066 vsop_find(vf
, &func
, int, &arg0
, vop_close
, femop_close
);
2067 ASSERT(func
!= NULL
);
2068 ASSERT(arg0
!= NULL
);
2069 return ((*func
)(arg0
, flag
, count
, offset
, cr
, ct
));
2073 vnext_read(femarg_t
*vf
, uio_t
*uiop
, int ioflag
, cred_t
*cr
,
2074 caller_context_t
*ct
)
2076 int (*func
)() = NULL
;
2081 vsop_find(vf
, &func
, int, &arg0
, vop_read
, femop_read
);
2082 ASSERT(func
!= NULL
);
2083 ASSERT(arg0
!= NULL
);
2084 return ((*func
)(arg0
, uiop
, ioflag
, cr
, ct
));
2088 vnext_write(femarg_t
*vf
, uio_t
*uiop
, int ioflag
, cred_t
*cr
,
2089 caller_context_t
*ct
)
2091 int (*func
)() = NULL
;
2096 vsop_find(vf
, &func
, int, &arg0
, vop_write
, femop_write
);
2097 ASSERT(func
!= NULL
);
2098 ASSERT(arg0
!= NULL
);
2099 return ((*func
)(arg0
, uiop
, ioflag
, cr
, ct
));
2103 vnext_ioctl(femarg_t
*vf
, int cmd
, intptr_t arg
, int flag
, cred_t
*cr
,
2104 int *rvalp
, caller_context_t
*ct
)
2106 int (*func
)() = NULL
;
2111 vsop_find(vf
, &func
, int, &arg0
, vop_ioctl
, femop_ioctl
);
2112 ASSERT(func
!= NULL
);
2113 ASSERT(arg0
!= NULL
);
2114 return ((*func
)(arg0
, cmd
, arg
, flag
, cr
, rvalp
, ct
));
2118 vnext_setfl(femarg_t
*vf
, int oflags
, int nflags
, cred_t
*cr
,
2119 caller_context_t
*ct
)
2121 int (*func
)() = NULL
;
2126 vsop_find(vf
, &func
, int, &arg0
, vop_setfl
, femop_setfl
);
2127 ASSERT(func
!= NULL
);
2128 ASSERT(arg0
!= NULL
);
2129 return ((*func
)(arg0
, oflags
, nflags
, cr
, ct
));
2133 vnext_getattr(femarg_t
*vf
, vattr_t
*vap
, int flags
, cred_t
*cr
,
2134 caller_context_t
*ct
)
2136 int (*func
)() = NULL
;
2141 vsop_find(vf
, &func
, int, &arg0
, vop_getattr
, femop_getattr
);
2142 ASSERT(func
!= NULL
);
2143 ASSERT(arg0
!= NULL
);
2144 return ((*func
)(arg0
, vap
, flags
, cr
, ct
));
2148 vnext_setattr(femarg_t
*vf
, vattr_t
*vap
, int flags
, cred_t
*cr
,
2149 caller_context_t
*ct
)
2151 int (*func
)() = NULL
;
2156 vsop_find(vf
, &func
, int, &arg0
, vop_setattr
, femop_setattr
);
2157 ASSERT(func
!= NULL
);
2158 ASSERT(arg0
!= NULL
);
2159 return ((*func
)(arg0
, vap
, flags
, cr
, ct
));
2163 vnext_access(femarg_t
*vf
, int mode
, int flags
, cred_t
*cr
,
2164 caller_context_t
*ct
)
2166 int (*func
)() = NULL
;
2171 vsop_find(vf
, &func
, int, &arg0
, vop_access
, femop_access
);
2172 ASSERT(func
!= NULL
);
2173 ASSERT(arg0
!= NULL
);
2174 return ((*func
)(arg0
, mode
, flags
, cr
, ct
));
2178 vnext_lookup(femarg_t
*vf
, char *nm
, vnode_t
**vpp
, pathname_t
*pnp
,
2179 int flags
, vnode_t
*rdir
, cred_t
*cr
, caller_context_t
*ct
,
2180 int *direntflags
, pathname_t
*realpnp
)
2182 int (*func
)() = NULL
;
2187 vsop_find(vf
, &func
, int, &arg0
, vop_lookup
, femop_lookup
);
2188 ASSERT(func
!= NULL
);
2189 ASSERT(arg0
!= NULL
);
2190 return ((*func
)(arg0
, nm
, vpp
, pnp
, flags
, rdir
, cr
, ct
,
2191 direntflags
, realpnp
));
2195 vnext_create(femarg_t
*vf
, char *name
, vattr_t
*vap
, vcexcl_t excl
,
2196 int mode
, vnode_t
**vpp
, cred_t
*cr
, int flag
, caller_context_t
*ct
,
2199 int (*func
)() = NULL
;
2204 vsop_find(vf
, &func
, int, &arg0
, vop_create
, femop_create
);
2205 ASSERT(func
!= NULL
);
2206 ASSERT(arg0
!= NULL
);
2207 return ((*func
)(arg0
, name
, vap
, excl
, mode
, vpp
, cr
, flag
, ct
, vsecp
));
2211 vnext_remove(femarg_t
*vf
, char *nm
, cred_t
*cr
, caller_context_t
*ct
,
2214 int (*func
)() = NULL
;
2219 vsop_find(vf
, &func
, int, &arg0
, vop_remove
, femop_remove
);
2220 ASSERT(func
!= NULL
);
2221 ASSERT(arg0
!= NULL
);
2222 return ((*func
)(arg0
, nm
, cr
, ct
, flags
));
2226 vnext_link(femarg_t
*vf
, vnode_t
*svp
, char *tnm
, cred_t
*cr
,
2227 caller_context_t
*ct
, int flags
)
2229 int (*func
)() = NULL
;
2234 vsop_find(vf
, &func
, int, &arg0
, vop_link
, femop_link
);
2235 ASSERT(func
!= NULL
);
2236 ASSERT(arg0
!= NULL
);
2237 return ((*func
)(arg0
, svp
, tnm
, cr
, ct
, flags
));
2241 vnext_rename(femarg_t
*vf
, char *snm
, vnode_t
*tdvp
, char *tnm
, cred_t
*cr
,
2242 caller_context_t
*ct
, int flags
)
2244 int (*func
)() = NULL
;
2249 vsop_find(vf
, &func
, int, &arg0
, vop_rename
, femop_rename
);
2250 ASSERT(func
!= NULL
);
2251 ASSERT(arg0
!= NULL
);
2252 return ((*func
)(arg0
, snm
, tdvp
, tnm
, cr
, ct
, flags
));
2256 vnext_mkdir(femarg_t
*vf
, char *dirname
, vattr_t
*vap
, vnode_t
**vpp
,
2257 cred_t
*cr
, caller_context_t
*ct
, int flags
, vsecattr_t
*vsecp
)
2259 int (*func
)() = NULL
;
2264 vsop_find(vf
, &func
, int, &arg0
, vop_mkdir
, femop_mkdir
);
2265 ASSERT(func
!= NULL
);
2266 ASSERT(arg0
!= NULL
);
2267 return ((*func
)(arg0
, dirname
, vap
, vpp
, cr
, ct
, flags
, vsecp
));
2271 vnext_rmdir(femarg_t
*vf
, char *nm
, vnode_t
*cdir
, cred_t
*cr
,
2272 caller_context_t
*ct
, int flags
)
2274 int (*func
)() = NULL
;
2279 vsop_find(vf
, &func
, int, &arg0
, vop_rmdir
, femop_rmdir
);
2280 ASSERT(func
!= NULL
);
2281 ASSERT(arg0
!= NULL
);
2282 return ((*func
)(arg0
, nm
, cdir
, cr
, ct
, flags
));
2286 vnext_readdir(femarg_t
*vf
, uio_t
*uiop
, cred_t
*cr
, int *eofp
,
2287 caller_context_t
*ct
, int flags
)
2289 int (*func
)() = NULL
;
2294 vsop_find(vf
, &func
, int, &arg0
, vop_readdir
, femop_readdir
);
2295 ASSERT(func
!= NULL
);
2296 ASSERT(arg0
!= NULL
);
2297 return ((*func
)(arg0
, uiop
, cr
, eofp
, ct
, flags
));
2301 vnext_symlink(femarg_t
*vf
, char *linkname
, vattr_t
*vap
, char *target
,
2302 cred_t
*cr
, caller_context_t
*ct
, int flags
)
2304 int (*func
)() = NULL
;
2309 vsop_find(vf
, &func
, int, &arg0
, vop_symlink
, femop_symlink
);
2310 ASSERT(func
!= NULL
);
2311 ASSERT(arg0
!= NULL
);
2312 return ((*func
)(arg0
, linkname
, vap
, target
, cr
, ct
, flags
));
2316 vnext_readlink(femarg_t
*vf
, uio_t
*uiop
, cred_t
*cr
, caller_context_t
*ct
)
2318 int (*func
)() = NULL
;
2323 vsop_find(vf
, &func
, int, &arg0
, vop_readlink
, femop_readlink
);
2324 ASSERT(func
!= NULL
);
2325 ASSERT(arg0
!= NULL
);
2326 return ((*func
)(arg0
, uiop
, cr
, ct
));
2330 vnext_fsync(femarg_t
*vf
, int syncflag
, cred_t
*cr
, caller_context_t
*ct
)
2332 int (*func
)() = NULL
;
2337 vsop_find(vf
, &func
, int, &arg0
, vop_fsync
, femop_fsync
);
2338 ASSERT(func
!= NULL
);
2339 ASSERT(arg0
!= NULL
);
2340 return ((*func
)(arg0
, syncflag
, cr
, ct
));
2344 vnext_inactive(femarg_t
*vf
, cred_t
*cr
, caller_context_t
*ct
)
2346 void (*func
)() = NULL
;
2351 vsop_find(vf
, &func
, void, &arg0
, vop_inactive
, femop_inactive
);
2352 ASSERT(func
!= NULL
);
2353 ASSERT(arg0
!= NULL
);
2354 (*func
)(arg0
, cr
, ct
);
2358 vnext_fid(femarg_t
*vf
, fid_t
*fidp
, caller_context_t
*ct
)
2360 int (*func
)() = NULL
;
2365 vsop_find(vf
, &func
, int, &arg0
, vop_fid
, femop_fid
);
2366 ASSERT(func
!= NULL
);
2367 ASSERT(arg0
!= NULL
);
2368 return ((*func
)(arg0
, fidp
, ct
));
2372 vnext_rwlock(femarg_t
*vf
, int write_lock
, caller_context_t
*ct
)
2374 int (*func
)() = NULL
;
2379 vsop_find(vf
, &func
, int, &arg0
, vop_rwlock
, femop_rwlock
);
2380 ASSERT(func
!= NULL
);
2381 ASSERT(arg0
!= NULL
);
2382 return ((*func
)(arg0
, write_lock
, ct
));
2386 vnext_rwunlock(femarg_t
*vf
, int write_lock
, caller_context_t
*ct
)
2388 void (*func
)() = NULL
;
2393 vsop_find(vf
, &func
, void, &arg0
, vop_rwunlock
, femop_rwunlock
);
2394 ASSERT(func
!= NULL
);
2395 ASSERT(arg0
!= NULL
);
2396 (*func
)(arg0
, write_lock
, ct
);
2400 vnext_seek(femarg_t
*vf
, offset_t ooff
, offset_t
*noffp
, caller_context_t
*ct
)
2402 int (*func
)() = NULL
;
2407 vsop_find(vf
, &func
, int, &arg0
, vop_seek
, femop_seek
);
2408 ASSERT(func
!= NULL
);
2409 ASSERT(arg0
!= NULL
);
2410 return ((*func
)(arg0
, ooff
, noffp
, ct
));
2414 vnext_cmp(femarg_t
*vf
, vnode_t
*vp2
, caller_context_t
*ct
)
2416 int (*func
)() = NULL
;
2421 vsop_find(vf
, &func
, int, &arg0
, vop_cmp
, femop_cmp
);
2422 ASSERT(func
!= NULL
);
2423 ASSERT(arg0
!= NULL
);
2424 return ((*func
)(arg0
, vp2
, ct
));
2428 vnext_frlock(femarg_t
*vf
, int cmd
, struct flock64
*bfp
, int flag
,
2429 offset_t offset
, struct flk_callback
*flk_cbp
, cred_t
*cr
,
2430 caller_context_t
*ct
)
2432 int (*func
)() = NULL
;
2437 vsop_find(vf
, &func
, int, &arg0
, vop_frlock
, femop_frlock
);
2438 ASSERT(func
!= NULL
);
2439 ASSERT(arg0
!= NULL
);
2440 return ((*func
)(arg0
, cmd
, bfp
, flag
, offset
, flk_cbp
, cr
, ct
));
2444 vnext_space(femarg_t
*vf
, int cmd
, struct flock64
*bfp
, int flag
,
2445 offset_t offset
, cred_t
*cr
, caller_context_t
*ct
)
2447 int (*func
)() = NULL
;
2452 vsop_find(vf
, &func
, int, &arg0
, vop_space
, femop_space
);
2453 ASSERT(func
!= NULL
);
2454 ASSERT(arg0
!= NULL
);
2455 return ((*func
)(arg0
, cmd
, bfp
, flag
, offset
, cr
, ct
));
2459 vnext_realvp(femarg_t
*vf
, vnode_t
**vpp
, caller_context_t
*ct
)
2461 int (*func
)() = NULL
;
2466 vsop_find(vf
, &func
, int, &arg0
, vop_realvp
, femop_realvp
);
2467 ASSERT(func
!= NULL
);
2468 ASSERT(arg0
!= NULL
);
2469 return ((*func
)(arg0
, vpp
, ct
));
2473 vnext_getpage(femarg_t
*vf
, offset_t off
, size_t len
, uint_t
*protp
,
2474 struct page
**plarr
, size_t plsz
, struct seg
*seg
, caddr_t addr
,
2475 enum seg_rw rw
, cred_t
*cr
, caller_context_t
*ct
)
2477 int (*func
)() = NULL
;
2482 vsop_find(vf
, &func
, int, &arg0
, vop_getpage
, femop_getpage
);
2483 ASSERT(func
!= NULL
);
2484 ASSERT(arg0
!= NULL
);
2485 return ((*func
)(arg0
, off
, len
, protp
, plarr
, plsz
, seg
, addr
, rw
,
2490 vnext_putpage(femarg_t
*vf
, offset_t off
, size_t len
, int flags
,
2491 cred_t
*cr
, caller_context_t
*ct
)
2493 int (*func
)() = NULL
;
2498 vsop_find(vf
, &func
, int, &arg0
, vop_putpage
, femop_putpage
);
2499 ASSERT(func
!= NULL
);
2500 ASSERT(arg0
!= NULL
);
2501 return ((*func
)(arg0
, off
, len
, flags
, cr
, ct
));
2505 vnext_map(femarg_t
*vf
, offset_t off
, struct as
*as
, caddr_t
*addrp
,
2506 size_t len
, uchar_t prot
, uchar_t maxprot
, uint_t flags
,
2507 cred_t
*cr
, caller_context_t
*ct
)
2509 int (*func
)() = NULL
;
2514 vsop_find(vf
, &func
, int, &arg0
, vop_map
, femop_map
);
2515 ASSERT(func
!= NULL
);
2516 ASSERT(arg0
!= NULL
);
2517 return ((*func
)(arg0
, off
, as
, addrp
, len
, prot
, maxprot
, flags
,
2522 vnext_addmap(femarg_t
*vf
, offset_t off
, struct as
*as
, caddr_t addr
,
2523 size_t len
, uchar_t prot
, uchar_t maxprot
, uint_t flags
,
2524 cred_t
*cr
, caller_context_t
*ct
)
2526 int (*func
)() = NULL
;
2531 vsop_find(vf
, &func
, int, &arg0
, vop_addmap
, femop_addmap
);
2532 ASSERT(func
!= NULL
);
2533 ASSERT(arg0
!= NULL
);
2534 return ((*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
, flags
,
2539 vnext_delmap(femarg_t
*vf
, offset_t off
, struct as
*as
, caddr_t addr
,
2540 size_t len
, uint_t prot
, uint_t maxprot
, uint_t flags
,
2541 cred_t
*cr
, caller_context_t
*ct
)
2543 int (*func
)() = NULL
;
2548 vsop_find(vf
, &func
, int, &arg0
, vop_delmap
, femop_delmap
);
2549 ASSERT(func
!= NULL
);
2550 ASSERT(arg0
!= NULL
);
2551 return ((*func
)(arg0
, off
, as
, addr
, len
, prot
, maxprot
, flags
,
2556 vnext_poll(femarg_t
*vf
, short events
, int anyyet
, short *reventsp
,
2557 struct pollhead
**phpp
, caller_context_t
*ct
)
2559 int (*func
)() = NULL
;
2564 vsop_find(vf
, &func
, int, &arg0
, vop_poll
, femop_poll
);
2565 ASSERT(func
!= NULL
);
2566 ASSERT(arg0
!= NULL
);
2567 return ((*func
)(arg0
, events
, anyyet
, reventsp
, phpp
, ct
));
2571 vnext_dump(femarg_t
*vf
, caddr_t addr
, offset_t lbdn
, offset_t dblks
,
2572 caller_context_t
*ct
)
2574 int (*func
)() = NULL
;
2579 vsop_find(vf
, &func
, int, &arg0
, vop_dump
, femop_dump
);
2580 ASSERT(func
!= NULL
);
2581 ASSERT(arg0
!= NULL
);
2582 return ((*func
)(arg0
, addr
, lbdn
, dblks
, ct
));
2586 vnext_pathconf(femarg_t
*vf
, int cmd
, ulong_t
*valp
, cred_t
*cr
,
2587 caller_context_t
*ct
)
2589 int (*func
)() = NULL
;
2594 vsop_find(vf
, &func
, int, &arg0
, vop_pathconf
, femop_pathconf
);
2595 ASSERT(func
!= NULL
);
2596 ASSERT(arg0
!= NULL
);
2597 return ((*func
)(arg0
, cmd
, valp
, cr
, ct
));
2601 vnext_pageio(femarg_t
*vf
, struct page
*pp
, uoff_t io_off
,
2602 size_t io_len
, int flags
, cred_t
*cr
, caller_context_t
*ct
)
2604 int (*func
)() = NULL
;
2609 vsop_find(vf
, &func
, int, &arg0
, vop_pageio
, femop_pageio
);
2610 ASSERT(func
!= NULL
);
2611 ASSERT(arg0
!= NULL
);
2612 return ((*func
)(arg0
, pp
, io_off
, io_len
, flags
, cr
, ct
));
2616 vnext_dumpctl(femarg_t
*vf
, int action
, offset_t
*blkp
, caller_context_t
*ct
)
2618 int (*func
)() = NULL
;
2623 vsop_find(vf
, &func
, int, &arg0
, vop_dumpctl
, femop_dumpctl
);
2624 ASSERT(func
!= NULL
);
2625 ASSERT(arg0
!= NULL
);
2626 return ((*func
)(arg0
, action
, blkp
, ct
));
2630 vnext_dispose(femarg_t
*vf
, struct page
*pp
, int flag
, int dn
, cred_t
*cr
,
2631 caller_context_t
*ct
)
2633 void (*func
)() = NULL
;
2638 vsop_find(vf
, &func
, void, &arg0
, vop_dispose
, femop_dispose
);
2639 ASSERT(func
!= NULL
);
2640 ASSERT(arg0
!= NULL
);
2641 (*func
)(arg0
, pp
, flag
, dn
, cr
, ct
);
2645 vnext_setsecattr(femarg_t
*vf
, vsecattr_t
*vsap
, int flag
, cred_t
*cr
,
2646 caller_context_t
*ct
)
2648 int (*func
)() = NULL
;
2653 vsop_find(vf
, &func
, int, &arg0
, vop_setsecattr
, femop_setsecattr
);
2654 ASSERT(func
!= NULL
);
2655 ASSERT(arg0
!= NULL
);
2656 return ((*func
)(arg0
, vsap
, flag
, cr
, ct
));
2660 vnext_getsecattr(femarg_t
*vf
, vsecattr_t
*vsap
, int flag
, cred_t
*cr
,
2661 caller_context_t
*ct
)
2663 int (*func
)() = NULL
;
2668 vsop_find(vf
, &func
, int, &arg0
, vop_getsecattr
, femop_getsecattr
);
2669 ASSERT(func
!= NULL
);
2670 ASSERT(arg0
!= NULL
);
2671 return ((*func
)(arg0
, vsap
, flag
, cr
, ct
));
2675 vnext_shrlock(femarg_t
*vf
, int cmd
, struct shrlock
*shr
, int flag
,
2676 cred_t
*cr
, caller_context_t
*ct
)
2678 int (*func
)() = NULL
;
2683 vsop_find(vf
, &func
, int, &arg0
, vop_shrlock
, femop_shrlock
);
2684 ASSERT(func
!= NULL
);
2685 ASSERT(arg0
!= NULL
);
2686 return ((*func
)(arg0
, cmd
, shr
, flag
, cr
, ct
));
2690 vnext_vnevent(femarg_t
*vf
, vnevent_t vnevent
, vnode_t
*dvp
, char *cname
,
2691 caller_context_t
*ct
)
2693 int (*func
)() = NULL
;
2698 vsop_find(vf
, &func
, int, &arg0
, vop_vnevent
, femop_vnevent
);
2699 ASSERT(func
!= NULL
);
2700 ASSERT(arg0
!= NULL
);
2701 return ((*func
)(arg0
, vnevent
, dvp
, cname
, ct
));
2705 vnext_reqzcbuf(femarg_t
*vf
, enum uio_rw ioflag
, xuio_t
*xuiop
, cred_t
*cr
,
2706 caller_context_t
*ct
)
2708 int (*func
)() = NULL
;
2713 vsop_find(vf
, &func
, int, &arg0
, vop_reqzcbuf
, femop_reqzcbuf
);
2714 ASSERT(func
!= NULL
);
2715 ASSERT(arg0
!= NULL
);
2716 return ((*func
)(arg0
, ioflag
, xuiop
, cr
, ct
));
2720 vnext_retzcbuf(femarg_t
*vf
, xuio_t
*xuiop
, cred_t
*cr
, caller_context_t
*ct
)
2722 int (*func
)() = NULL
;
2727 vsop_find(vf
, &func
, int, &arg0
, vop_retzcbuf
, femop_retzcbuf
);
2728 ASSERT(func
!= NULL
);
2729 ASSERT(arg0
!= NULL
);
2730 return ((*func
)(arg0
, xuiop
, cr
, ct
));
2734 vfsnext_mount(fsemarg_t
*vf
, vnode_t
*mvp
, struct mounta
*uap
, cred_t
*cr
)
2736 int (*func
)() = NULL
;
2741 vfsop_find(vf
, &func
, int, &arg0
, vfs_mount
, fsemop_mount
);
2742 ASSERT(func
!= NULL
);
2743 ASSERT(arg0
!= NULL
);
2744 return ((*func
)(arg0
, mvp
, uap
, cr
));
2748 vfsnext_unmount(fsemarg_t
*vf
, int flag
, cred_t
*cr
)
2750 int (*func
)() = NULL
;
2755 vfsop_find(vf
, &func
, int, &arg0
, vfs_unmount
, fsemop_unmount
);
2756 ASSERT(func
!= NULL
);
2757 ASSERT(arg0
!= NULL
);
2758 return ((*func
)(arg0
, flag
, cr
));
2762 vfsnext_root(fsemarg_t
*vf
, vnode_t
**vpp
)
2764 int (*func
)() = NULL
;
2769 vfsop_find(vf
, &func
, int, &arg0
, vfs_root
, fsemop_root
);
2770 ASSERT(func
!= NULL
);
2771 ASSERT(arg0
!= NULL
);
2772 return ((*func
)(arg0
, vpp
));
2776 vfsnext_statvfs(fsemarg_t
*vf
, statvfs64_t
*sp
)
2778 int (*func
)() = NULL
;
2783 vfsop_find(vf
, &func
, int, &arg0
, vfs_statvfs
, fsemop_statvfs
);
2784 ASSERT(func
!= NULL
);
2785 ASSERT(arg0
!= NULL
);
2786 return ((*func
)(arg0
, sp
));
2790 vfsnext_sync(fsemarg_t
*vf
, short flag
, cred_t
*cr
)
2792 int (*func
)() = NULL
;
2797 vfsop_find(vf
, &func
, int, &arg0
, vfs_sync
, fsemop_sync
);
2798 ASSERT(func
!= NULL
);
2799 ASSERT(arg0
!= NULL
);
2800 return ((*func
)(arg0
, flag
, cr
));
2804 vfsnext_vget(fsemarg_t
*vf
, vnode_t
**vpp
, fid_t
*fidp
)
2806 int (*func
)() = NULL
;
2811 vfsop_find(vf
, &func
, int, &arg0
, vfs_vget
, fsemop_vget
);
2812 ASSERT(func
!= NULL
);
2813 ASSERT(arg0
!= NULL
);
2814 return ((*func
)(arg0
, vpp
, fidp
));
2818 vfsnext_mountroot(fsemarg_t
*vf
, enum whymountroot reason
)
2820 int (*func
)() = NULL
;
2825 vfsop_find(vf
, &func
, int, &arg0
, vfs_mountroot
, fsemop_mountroot
);
2826 ASSERT(func
!= NULL
);
2827 ASSERT(arg0
!= NULL
);
2828 return ((*func
)(arg0
, reason
));
2832 vfsnext_freevfs(fsemarg_t
*vf
)
2834 void (*func
)() = NULL
;
2839 vfsop_find(vf
, &func
, void, &arg0
, vfs_freevfs
, fsemop_freevfs
);
2840 ASSERT(func
!= NULL
);
2841 ASSERT(arg0
!= NULL
);
2846 vfsnext_vnstate(fsemarg_t
*vf
, vnode_t
*vp
, vntrans_t nstate
)
2848 int (*func
)() = NULL
;
2853 vfsop_find(vf
, &func
, int, &arg0
, vfs_vnstate
, fsemop_vnstate
);
2854 ASSERT(func
!= NULL
);
2855 ASSERT(arg0
!= NULL
);
2856 return ((*func
)(arg0
, vp
, nstate
));
2861 * Create a new fem_head and associate with the vnode.
2862 * To keep the unaugmented vnode access path lock free, we spin
2863 * update this - create a new one, then try and install it. If
2864 * we fail to install, release the old one and pretend we succeeded.
2867 static struct fem_head
*
2868 new_femhead(struct fem_head
**hp
)
2870 struct fem_head
*head
;
2872 head
= kmem_alloc(sizeof (*head
), KM_SLEEP
);
2873 mutex_init(&head
->femh_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
2874 head
->femh_list
= NULL
;
2875 if (atomic_cas_ptr(hp
, NULL
, head
) != NULL
) {
2876 kmem_free(head
, sizeof (*head
));
2883 * Create a fem_list. The fem_list that gets returned is in a
2884 * very rudimentary state and MUST NOT be used until it's initialized
2885 * (usually by femlist_construct() or fem_dup_list()). The refcount
2886 * and size is set properly and top-of-stack is set to the "guard" node
2887 * just to be consistent.
2889 * If anyone were to accidentally trying to run on this fem_list before
2890 * it's initialized then the system would likely panic trying to defererence
2891 * the (NULL) fn_op pointer.
2894 static struct fem_list
*
2895 femlist_create(int numnodes
)
2897 struct fem_list
*sp
;
2899 sp
= kmem_alloc(fl_ntob(numnodes
), KM_SLEEP
);
2901 sp
->feml_ssize
= numnodes
;
2902 sp
->feml_nodes
[0] = FEM_GUARD(FEMTYPE_NULL
);
2908 * Construct a new femlist.
2909 * The list is constructed with the appropriate type of guard to
2910 * anchor it, and inserts the original ops.
2913 static struct fem_list
*
2914 femlist_construct(void *baseops
, int type
, int numnodes
)
2916 struct fem_list
*sp
;
2918 sp
= femlist_create(numnodes
);
2919 sp
->feml_nodes
[0] = FEM_GUARD(type
);
2920 sp
->feml_nodes
[1].fn_op
.anon
= baseops
;
2921 sp
->feml_nodes
[1].fn_available
= NULL
;
2922 sp
->feml_nodes
[1].fn_av_hold
= NULL
;
2923 sp
->feml_nodes
[1].fn_av_rele
= NULL
;
2929 * Duplicate a list. Copy the original list to the clone.
2931 * NOTE: The caller must have the fem_head for the lists locked.
2932 * Assuming the appropriate lock is held and the caller has done the
2933 * math right, the clone list should be big enough to old the original.
2937 fem_dup_list(struct fem_list
*orig
, struct fem_list
*clone
)
2941 ASSERT(clone
->feml_ssize
>= orig
->feml_ssize
);
2943 bcopy(orig
->feml_nodes
, clone
->feml_nodes
,
2944 sizeof (orig
->feml_nodes
[0]) * orig
->feml_ssize
);
2945 clone
->feml_tos
= orig
->feml_tos
;
2947 * Now that we've copied the old list (orig) to the new list (clone),
2948 * we need to walk the new list and put another hold on fn_available.
2950 for (i
= clone
->feml_tos
; i
> 0; i
--) {
2951 struct fem_node
*fnp
= &clone
->feml_nodes
[i
];
2953 if (fnp
->fn_av_hold
)
2954 (*(fnp
->fn_av_hold
))(fnp
->fn_available
);
2961 struct fem_head
**hp
,
2964 struct fem_node
*nnode
,
2967 struct fem_head
*hd
;
2968 struct fem_list
*list
;
2974 /* Validate the node */
2975 if ((nnode
->fn_op
.anon
== NULL
) || (nnode
->fn_available
== NULL
)) {
2979 if ((hd
= *hp
) == NULL
) { /* construct a proto-list */
2980 hd
= new_femhead(hp
);
2983 * RULE: once a femhead has been pushed onto a object, it cannot be
2984 * removed until the object is destroyed. It can be deactivated by
2985 * placing the original 'object operations' onto the object, which
2986 * will ignore the femhead.
2987 * The loop will exist when the femh_list has space to push a monitor
2992 list
= fem_lock(hd
);
2996 if (list
->feml_tos
+1 < list
->feml_ssize
) {
2999 struct fem_list
*olist
= list
;
3003 list
= femlist_create(olist
->feml_ssize
* 2);
3004 (void) fem_lock(hd
);
3005 if (hd
->femh_list
== olist
) {
3006 if (list
->feml_ssize
<=
3007 olist
->feml_ssize
) {
3009 * We have a new list, but it
3010 * is too small to hold the
3011 * original contents plus the
3012 * one to push. Release the
3013 * new list and start over.
3019 * Life is good: Our new list
3020 * is big enough to hold the
3021 * original list (olist) + 1.
3023 fem_dup_list(olist
, list
);
3024 /* orphan this list */
3025 hd
->femh_list
= list
;
3026 (void) fem_delref(olist
);
3030 /* concurrent update, retry */
3034 /* remove the reference we added above */
3039 list
= femlist_construct(oldops
, type
, NNODES_DEFAULT
);
3040 (void) fem_lock(hd
);
3041 if (hd
->femh_list
!= NULL
|| *baseops
!= oldops
) {
3042 /* concurrent update, retry */
3046 hd
->femh_list
= list
;
3047 *baseops
= FEM_HEAD(type
);
3053 ASSERT(mutex_owner(&hd
->femh_lock
) == curthread
);
3054 ASSERT(list
->feml_tos
+1 < list
->feml_ssize
);
3057 * The presence of "how" will modify the behavior of how/if
3058 * nodes are pushed. If it's FORCE, then we can skip
3059 * all the checks and push it on.
3062 /* Start at the top and work our way down */
3063 for (i
= list
->feml_tos
; i
> 0; i
--) {
3064 void *fn_av
= list
->feml_nodes
[i
].fn_available
;
3065 void *fn_op
= list
->feml_nodes
[i
].fn_op
.anon
;
3068 * OPARGUNIQ means that this node should not
3069 * be pushed on if a node with the same op/avail
3070 * combination exists. This situation returns
3073 * OPUNIQ means that this node should not be
3074 * pushed on if a node with the same op exists.
3075 * This situation also returns EBUSY.
3080 if (fn_op
== nnode
->fn_op
.anon
) {
3086 if ((fn_op
== nnode
->fn_op
.anon
) &&
3087 (fn_av
== nnode
->fn_available
)) {
3093 error
= EINVAL
; /* Unexpected value */
3104 * If no errors, slap the node on the list.
3105 * Note: The following is a structure copy.
3107 list
->feml_nodes
[++(list
->feml_tos
)] = *nnode
;
3115 * Remove a node by copying the list above it down a notch.
3116 * If the list is busy, replace it with an idle one and work
3118 * A node matches if the opset matches and the datap matches or is
3123 remove_node(struct fem_list
*sp
, void **baseops
, void *opset
, void *datap
)
3126 struct fem_node
*fn
;
3128 for (i
= sp
->feml_tos
; i
> 0; i
--) {
3129 fn
= sp
->feml_nodes
+i
;
3130 if (fn
->fn_op
.anon
== opset
&&
3131 (fn
->fn_available
== datap
|| datap
== NULL
)) {
3140 * At this point we have a node in-hand (*fn) that we are about
3141 * to remove by overwriting it and adjusting the stack. This is
3142 * our last chance to do anything with this node so we do the
3143 * release on the arg.
3146 (*(fn
->fn_av_rele
))(fn
->fn_available
);
3148 while (i
++ < sp
->feml_tos
) {
3149 sp
->feml_nodes
[i
-1] = sp
->feml_nodes
[i
];
3151 if (--(sp
->feml_tos
) == 1) { /* Empty, restore ops */
3152 *baseops
= sp
->feml_nodes
[1].fn_op
.anon
;
3158 fem_remove_node(struct fem_head
*fh
, void **baseops
, void *opset
, void *datap
)
3160 struct fem_list
*sp
;
3170 if ((sp
= fem_lock(fh
)) == NULL
) {
3173 } else if (sp
->feml_refc
== 1) {
3174 error
= remove_node(sp
, baseops
, opset
, datap
);
3175 if (sp
->feml_tos
== 1) {
3177 * The top-of-stack was decremented by
3178 * remove_node(). If it got down to 1,
3179 * then the base ops were replaced and we
3180 * call fem_release() which will free the
3184 fh
->femh_list
= NULL
;
3185 /* XXX - Do we need a membar_producer() call? */
3189 /* busy - install a new one without this monitor */
3190 struct fem_list
*nsp
; /* New fem_list being cloned */
3194 nsp
= femlist_create(sp
->feml_ssize
);
3195 if (fem_lock(fh
) == sp
) {
3197 * We popped out of the lock, created a
3198 * list, then relocked. If we're in here
3199 * then the fem_head points to the same list
3202 fem_dup_list(sp
, nsp
);
3203 error
= remove_node(nsp
, baseops
, opset
, datap
);
3206 } else if (nsp
->feml_tos
== 1) {
3207 /* New list now empty, tear it down */
3209 fh
->femh_list
= NULL
;
3211 fh
->femh_list
= nsp
;
3213 (void) fem_delref(sp
);
3215 /* List changed while locked, try again... */
3220 * If error is set, then we tried to remove a node
3221 * from the list, but failed. This means that we
3222 * will still be using this list so don't release it.
3234 * perform operation on each element until one returns non zero
3238 struct fem_list
*sp
,
3239 int (*f
)(struct fem_node
*, void *, void *),
3246 for (i
= sp
->feml_tos
; i
> 0; i
--) {
3247 if ((*f
)(sp
->feml_nodes
+i
, mon
, arg
) != 0) {
3255 * companion comparison functions.
3258 fem_compare_mon(struct fem_node
*n
, void *mon
, void *arg
)
3260 return ((n
->fn_op
.anon
== mon
) && (n
->fn_available
== arg
));
3264 * VNODE interposition.
3268 fem_create(char *name
, const struct fs_operation_def
*templ
,
3277 newf
->templ
= templ
;
3279 e
= fs_build_vector(newf
, &unused_ops
, fem_opdef
, templ
);
3282 cmn_err(CE_WARN
, "fem_create: error %d building vector", e
);
3293 vnode_t
*vp
, /* Vnode on which monitor is being installed */
3294 fem_t
*mon
, /* Monitor operations being installed */
3295 void *arg
, /* Opaque data used by monitor */
3296 femhow_t how
, /* Installation control */
3297 void (*arg_hold
)(void *), /* Hold routine for "arg" */
3298 void (*arg_rele
)(void *)) /* Release routine for "arg" */
3301 struct fem_node nnode
;
3303 nnode
.fn_available
= arg
;
3304 nnode
.fn_op
.fem
= mon
;
3305 nnode
.fn_av_hold
= arg_hold
;
3306 nnode
.fn_av_rele
= arg_rele
;
3308 * If we have a non-NULL hold function, do the hold right away.
3309 * The release is done in remove_node().
3314 error
= fem_push_node(&vp
->v_femhead
, (void **)&vp
->v_op
, FEMTYPE_VNODE
,
3317 /* If there was an error then the monitor wasn't pushed */
3318 if (error
&& arg_rele
)
3325 fem_is_installed(vnode_t
*v
, fem_t
*mon
, void *arg
)
3328 struct fem_list
*fl
;
3330 fl
= fem_get(v
->v_femhead
);
3332 e
= fem_walk_list(fl
, fem_compare_mon
, (void *)mon
, arg
);
3340 fem_uninstall(vnode_t
*v
, fem_t
*mon
, void *arg
)
3343 e
= fem_remove_node(v
->v_femhead
, (void **)&v
->v_op
,
3349 fem_setvnops(vnode_t
*v
, vnodeops_t
*newops
)
3354 ASSERT(newops
!= NULL
);
3359 if (v
->v_femhead
!= NULL
) {
3360 struct fem_list
*fl
;
3361 if ((fl
= fem_lock(v
->v_femhead
)) != NULL
) {
3362 fl
->feml_nodes
[1].fn_op
.vnode
= newops
;
3363 fem_unlock(v
->v_femhead
);
3366 fem_unlock(v
->v_femhead
);
3368 } while (atomic_cas_ptr(&v
->v_op
, r
, newops
) != r
);
3372 fem_getvnops(vnode_t
*v
)
3380 if (v
->v_femhead
!= NULL
) {
3381 struct fem_list
*fl
;
3382 if ((fl
= fem_lock(v
->v_femhead
)) != NULL
) {
3383 r
= fl
->feml_nodes
[1].fn_op
.vnode
;
3385 fem_unlock(v
->v_femhead
);
3395 fsem_create(char *name
, const struct fs_operation_def
*templ
,
3402 newv
= fsem_alloc();
3403 newv
->name
= (const char *)name
;
3404 newv
->templ
= templ
;
3406 e
= fs_build_vector(newv
, &unused_ops
, fsem_opdef
, templ
);
3409 cmn_err(CE_WARN
, "fsem_create: error %d building vector", e
);
3419 * These need to be re-written, but there should be more common bits.
3423 fsem_is_installed(struct vfs
*v
, fsem_t
*mon
, void *arg
)
3425 struct fem_list
*fl
;
3427 if (v
->vfs_implp
== NULL
)
3430 fl
= fem_get(v
->vfs_femhead
);
3433 e
= fem_walk_list(fl
, fem_compare_mon
, (void *)mon
, arg
);
3442 struct vfs
*vfsp
, /* VFS on which monitor is being installed */
3443 fsem_t
*mon
, /* Monitor operations being installed */
3444 void *arg
, /* Opaque data used by monitor */
3445 femhow_t how
, /* Installation control */
3446 void (*arg_hold
)(void *), /* Hold routine for "arg" */
3447 void (*arg_rele
)(void *)) /* Release routine for "arg" */
3450 struct fem_node nnode
;
3452 /* If this vfs hasn't been properly initialized, fail the install */
3453 if (vfsp
->vfs_implp
== NULL
)
3456 nnode
.fn_available
= arg
;
3457 nnode
.fn_op
.fsem
= mon
;
3458 nnode
.fn_av_hold
= arg_hold
;
3459 nnode
.fn_av_rele
= arg_rele
;
3461 * If we have a non-NULL hold function, do the hold right away.
3462 * The release is done in remove_node().
3467 error
= fem_push_node(&vfsp
->vfs_femhead
, (void **)&vfsp
->vfs_op
,
3468 FEMTYPE_VFS
, &nnode
, how
);
3470 /* If there was an error then the monitor wasn't pushed */
3471 if (error
&& arg_rele
)
3478 fsem_uninstall(struct vfs
*v
, fsem_t
*mon
, void *arg
)
3482 if (v
->vfs_implp
== NULL
)
3485 e
= fem_remove_node(v
->vfs_femhead
, (void **)&v
->vfs_op
,
3491 fsem_setvfsops(vfs_t
*v
, vfsops_t
*newops
)
3496 ASSERT(newops
!= NULL
);
3497 ASSERT(v
->vfs_implp
);
3502 if (v
->vfs_femhead
!= NULL
) {
3503 struct fem_list
*fl
;
3504 if ((fl
= fem_lock(v
->vfs_femhead
)) != NULL
) {
3505 fl
->feml_nodes
[1].fn_op
.vfs
= newops
;
3506 fem_unlock(v
->vfs_femhead
);
3509 fem_unlock(v
->vfs_femhead
);
3511 } while (atomic_cas_ptr(&v
->vfs_op
, r
, newops
) != r
);
3515 fsem_getvfsops(vfs_t
*v
)
3520 ASSERT(v
->vfs_implp
);
3524 if (v
->vfs_femhead
!= NULL
) {
3525 struct fem_list
*fl
;
3526 if ((fl
= fem_lock(v
->vfs_femhead
)) != NULL
) {
3527 r
= fl
->feml_nodes
[1].fn_op
.vfs
;
3529 fem_unlock(v
->vfs_femhead
);
3540 struct fem_type_info
*fi
;
3543 * This femtype is only used for fem_list creation so we only
3544 * need the "guard" to be initialized so that feml_tos has
3545 * some rudimentary meaning. A fem_list must not be used until
3546 * it has been initialized (either via femlist_construct() or
3547 * fem_dup_list()). Anything that tries to use this fem_list
3548 * before it's actually initialized would panic the system as
3549 * soon as "fn_op" (NULL) is dereferenced.
3551 fi
= femtype
+ FEMTYPE_NULL
;
3553 fi
->guard
.fn_available
= (void *)&fi
->guard
;
3554 fi
->guard
.fn_av_hold
= NULL
;
3555 fi
->guard
.fn_av_rele
= NULL
;
3556 fi
->guard
.fn_op
.anon
= NULL
;
3558 fi
= femtype
+ FEMTYPE_VNODE
;
3560 fi
->head
.fn_available
= NULL
;
3561 fi
->head
.fn_av_hold
= NULL
;
3562 fi
->head
.fn_av_rele
= NULL
;
3563 (void) vn_make_ops("fem-head", fhead_vn_spec
, &fi
->head
.fn_op
.vnode
);
3564 fi
->guard
.fn_available
= (void *)&fi
->guard
;
3565 fi
->guard
.fn_av_hold
= NULL
;
3566 fi
->guard
.fn_av_rele
= NULL
;
3567 (void) fem_create("fem-guard", fem_guard_ops
, &fi
->guard
.fn_op
.fem
);
3569 fi
= femtype
+ FEMTYPE_VFS
;
3570 fi
->errf
= fsem_err
;
3571 fi
->head
.fn_available
= NULL
;
3572 fi
->head
.fn_av_hold
= NULL
;
3573 fi
->head
.fn_av_rele
= NULL
;
3574 (void) vfs_makefsops(fshead_vfs_spec
, &fi
->head
.fn_op
.vfs
);
3576 fi
->guard
.fn_available
= (void *)&fi
->guard
;
3577 fi
->guard
.fn_av_hold
= NULL
;
3578 fi
->guard
.fn_av_rele
= NULL
;
3579 (void) fsem_create("fem-guard", fsem_guard_ops
, &fi
->guard
.fn_op
.fsem
);
3586 cmn_err(CE_PANIC
, "fem/vnode operations corrupt");
3593 cmn_err(CE_PANIC
, "fem/vfs operations corrupt");