uts: make emu10k non-verbose
[unleashed.git] / kernel / fs / fem.c
blob5ab43f8b14ff77e0fd2289f8fbf946b6578ba374
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
28 #include <sys/kmem.h>
29 #include <sys/mutex.h>
30 #include <sys/errno.h>
31 #include <sys/param.h>
32 #include <sys/sysmacros.h>
33 #include <sys/systm.h>
34 #include <sys/cmn_err.h>
35 #include <sys/debug.h>
37 #include <sys/fem.h>
38 #include <sys/vfs.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))
51 typedef enum {
52 FEMTYPE_NULL, /* Uninitialized */
53 FEMTYPE_VNODE,
54 FEMTYPE_VFS,
55 FEMTYPE_NTYPES
56 } femtype_t;
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 {
62 struct fem_node head;
63 struct fem_node guard;
64 femop_t *errf;
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.
74 int fem_err();
75 int fsem_err();
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),
103 _FEMOPDEF(FID, fid),
104 _FEMOPDEF(RWLOCK, rwlock),
105 _FEMOPDEF(RWUNLOCK, rwunlock),
106 _FEMOPDEF(SEEK, seek),
107 _FEMOPDEF(CMP, cmp),
108 _FEMOPDEF(FRLOCK, frlock),
109 _FEMOPDEF(SPACE, space),
110 _FEMOPDEF(REALVP, realvp),
111 _FEMOPDEF(GETPAGE, getpage),
112 _FEMOPDEF(PUTPAGE, putpage),
113 _FEMOPDEF(MAP, map),
114 _FEMOPDEF(ADDMAP, addmap),
115 _FEMOPDEF(DELMAP, delmap),
116 _FEMOPDEF(POLL, poll),
117 _FEMOPDEF(DUMP, dump),
118 _FEMOPDEF(PATHCONF, pathconf),
119 _FEMOPDEF(PAGEIO, pageio),
120 _FEMOPDEF(DUMPCTL, dumpctl),
121 _FEMOPDEF(DISPOSE, dispose),
122 _FEMOPDEF(SETSECATTR, setsecattr),
123 _FEMOPDEF(GETSECATTR, getsecattr),
124 _FEMOPDEF(SHRLOCK, shrlock),
125 _FEMOPDEF(VNEVENT, vnevent),
126 _FEMOPDEF(REQZCBUF, reqzcbuf),
127 _FEMOPDEF(RETZCBUF, retzcbuf),
128 { NULL, 0, NULL }
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),
157 _FEMGUARD(FID, fid),
158 _FEMGUARD(RWLOCK, rwlock),
159 _FEMGUARD(RWUNLOCK, rwunlock),
160 _FEMGUARD(SEEK, seek),
161 _FEMGUARD(CMP, cmp),
162 _FEMGUARD(FRLOCK, frlock),
163 _FEMGUARD(SPACE, space),
164 _FEMGUARD(REALVP, realvp),
165 _FEMGUARD(GETPAGE, getpage),
166 _FEMGUARD(PUTPAGE, putpage),
167 _FEMGUARD(MAP, map),
168 _FEMGUARD(ADDMAP, addmap),
169 _FEMGUARD(DELMAP, delmap),
170 _FEMGUARD(POLL, poll),
171 _FEMGUARD(DUMP, dump),
172 _FEMGUARD(PATHCONF, pathconf),
173 _FEMGUARD(PAGEIO, pageio),
174 _FEMGUARD(DUMPCTL, dumpctl),
175 _FEMGUARD(DISPOSE, dispose),
176 _FEMGUARD(SETSECATTR, setsecattr),
177 _FEMGUARD(GETSECATTR, getsecattr),
178 _FEMGUARD(SHRLOCK, shrlock),
179 _FEMGUARD(VNEVENT, vnevent),
180 _FEMGUARD(REQZCBUF, reqzcbuf),
181 _FEMGUARD(RETZCBUF, retzcbuf),
182 { NULL, NULL }
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),
199 { NULL, 0, NULL }
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),
215 { NULL, NULL}
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.
230 #ifndef DEBUG
232 #define vsop_find(ap, func, funct, arg0, _vop, _vsop) \
233 for (;;) { \
234 if ((ap)->fa_fnode->fn_available == NULL) { \
235 *(func) = (funct (*)())((ap)->fa_fnode->fn_op.vnode->_vop); \
236 *(arg0) = (void *)(ap)->fa_vnode.vp; \
237 break; \
238 } else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fem->_vsop))\
239 != NULL) { \
240 *(arg0) = (void *) (ap); \
241 break; \
242 } else { \
243 (ap)->fa_fnode--; \
247 #define vfsop_find(ap, func, funct, arg0, _vop, _vsop) \
248 for (;;) { \
249 if ((ap)->fa_fnode->fn_available == NULL) { \
250 *(func) = (funct (*)())((ap)->fa_fnode->fn_op.vfs->_vop); \
251 *(arg0) = (void *)(ap)->fa_vnode.vp; \
252 break; \
253 } else if ((*(func) = (funct (*)())((ap)->fa_fnode->fn_op.fsem->_vsop))\
254 != NULL) { \
255 *(arg0) = (void *) (ap); \
256 break; \
257 } else { \
258 (ap)->fa_fnode--; \
262 #else
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))
272 static void *
273 _op_find(femarg_t *ap, void **fp, int offs0, int offs1)
275 void *ptr;
276 for (;;) {
277 struct fem_node *fnod = ap->fa_fnode;
278 if (fnod->fn_available == NULL) {
279 *fp = *(void **)((char *)fnod->fn_op.anon + offs0);
280 ptr = (void *)(ap->fa_vnode.anon);
281 break;
282 } else if ((*fp = *(void **)((char *)fnod->fn_op.anon+offs1))
283 != NULL) {
284 ptr = (void *)(ap);
285 break;
286 } else {
287 ap->fa_fnode--;
290 return (ptr);
292 #endif
294 static fem_t *
295 fem_alloc()
297 fem_t *p;
299 p = (fem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
300 return (p);
303 void
304 fem_free(fem_t *p)
306 kmem_free(p, sizeof (*p));
309 static fsem_t *
310 fsem_alloc()
312 fsem_t *p;
314 p = (fsem_t *)kmem_alloc(sizeof (*p), KM_SLEEP);
315 return (p);
318 void
319 fsem_free(fsem_t *p)
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:
335 * look at femh_list
336 * update what femh_list points to
337 * update femh_list
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;
350 ASSERT(fp != NULL);
351 mutex_enter(&fp->femh_lock);
352 sp = fp->femh_list;
353 return (sp);
356 static void
357 fem_unlock(struct fem_head *fp)
359 ASSERT(fp != NULL);
360 mutex_exit(&fp->femh_lock);
364 * Addref can only be called while its head->lock is held.
367 static void
368 fem_addref(struct fem_list *sp)
370 atomic_inc_32(&sp->feml_refc);
373 static uint32_t
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;
384 if (fp != NULL) {
385 if ((sp = fem_lock(fp)) != NULL) {
386 fem_addref(sp);
388 fem_unlock(fp);
390 return (sp);
393 static void
394 fem_release(struct fem_list *sp)
396 int i;
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];
407 if (fnp->fn_av_rele)
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.
433 static int
434 vhead_open(vnode_t **vpp, int mode, cred_t *cr, caller_context_t *ct)
436 femarg_t farg;
437 struct fem_list *femsp;
438 int (*func)();
439 void *arg0;
440 int errc;
442 if ((femsp = fem_lock((*vpp)->v_femhead)) == NULL) {
443 func = (int (*)()) ((*vpp)->v_op->vop_open);
444 arg0 = (void *)vpp;
445 fem_unlock((*vpp)->v_femhead);
446 errc = (*func)(arg0, mode, cr, ct);
447 } else {
448 fem_addref(femsp);
449 fem_unlock((*vpp)->v_femhead);
450 farg.fa_vnode.vpp = vpp;
451 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
452 vsop_find(&farg, &func, int, &arg0, vop_open, femop_open);
453 errc = (*func)(arg0, mode, cr, ct);
454 fem_release(femsp);
456 return (errc);
459 static int
460 vhead_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
461 caller_context_t *ct)
463 femarg_t farg;
464 struct fem_list *femsp;
465 int (*func)();
466 void *arg0;
467 int errc;
469 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
470 func = (int (*)()) (vp->v_op->vop_close);
471 arg0 = vp;
472 fem_unlock(vp->v_femhead);
473 errc = (*func)(arg0, flag, count, offset, cr, ct);
474 } else {
475 fem_addref(femsp);
476 fem_unlock(vp->v_femhead);
477 farg.fa_vnode.vp = vp;
478 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
479 vsop_find(&farg, &func, int, &arg0, vop_close, femop_close);
480 errc = (*func)(arg0, flag, count, offset, cr, ct);
481 fem_release(femsp);
483 return (errc);
486 static int
487 vhead_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
488 caller_context_t *ct)
490 femarg_t farg;
491 struct fem_list *femsp;
492 int (*func)();
493 void *arg0;
494 int errc;
496 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
497 func = (int (*)()) (vp->v_op->vop_read);
498 arg0 = vp;
499 fem_unlock(vp->v_femhead);
500 errc = (*func)(arg0, uiop, ioflag, cr, ct);
501 } else {
502 fem_addref(femsp);
503 fem_unlock(vp->v_femhead);
504 farg.fa_vnode.vp = vp;
505 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
506 vsop_find(&farg, &func, int, &arg0, vop_read, femop_read);
507 errc = (*func)(arg0, uiop, ioflag, cr, ct);
508 fem_release(femsp);
510 return (errc);
513 static int
514 vhead_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
515 caller_context_t *ct)
517 femarg_t farg;
518 struct fem_list *femsp;
519 int (*func)();
520 void *arg0;
521 int errc;
523 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
524 func = (int (*)()) (vp->v_op->vop_write);
525 arg0 = vp;
526 fem_unlock(vp->v_femhead);
527 errc = (*func)(arg0, uiop, ioflag, cr, ct);
528 } else {
529 fem_addref(femsp);
530 fem_unlock(vp->v_femhead);
531 farg.fa_vnode.vp = vp;
532 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
533 vsop_find(&farg, &func, int, &arg0, vop_write, femop_write);
534 errc = (*func)(arg0, uiop, ioflag, cr, ct);
535 fem_release(femsp);
537 return (errc);
540 static int
541 vhead_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
542 int *rvalp, caller_context_t *ct)
544 femarg_t farg;
545 struct fem_list *femsp;
546 int (*func)();
547 void *arg0;
548 int errc;
550 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
551 func = (int (*)()) (vp->v_op->vop_ioctl);
552 arg0 = vp;
553 fem_unlock(vp->v_femhead);
554 errc = (*func)(arg0, cmd, arg, flag, cr, rvalp, ct);
555 } else {
556 fem_addref(femsp);
557 fem_unlock(vp->v_femhead);
558 farg.fa_vnode.vp = vp;
559 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
560 vsop_find(&farg, &func, int, &arg0, vop_ioctl, femop_ioctl);
561 errc = (*func)(arg0, cmd, arg, flag, cr, rvalp, ct);
562 fem_release(femsp);
564 return (errc);
567 static int
568 vhead_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr,
569 caller_context_t *ct)
571 femarg_t farg;
572 struct fem_list *femsp;
573 int (*func)();
574 void *arg0;
575 int errc;
577 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
578 func = (int (*)()) (vp->v_op->vop_setfl);
579 arg0 = vp;
580 fem_unlock(vp->v_femhead);
581 errc = (*func)(arg0, oflags, nflags, cr, ct);
582 } else {
583 fem_addref(femsp);
584 fem_unlock(vp->v_femhead);
585 farg.fa_vnode.vp = vp;
586 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
587 vsop_find(&farg, &func, int, &arg0, vop_setfl, femop_setfl);
588 errc = (*func)(arg0, oflags, nflags, cr, ct);
589 fem_release(femsp);
591 return (errc);
594 static int
595 vhead_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
596 caller_context_t *ct)
598 femarg_t farg;
599 struct fem_list *femsp;
600 int (*func)();
601 void *arg0;
602 int errc;
604 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
605 func = (int (*)()) (vp->v_op->vop_getattr);
606 arg0 = vp;
607 fem_unlock(vp->v_femhead);
608 errc = (*func)(arg0, vap, flags, cr, ct);
609 } else {
610 fem_addref(femsp);
611 fem_unlock(vp->v_femhead);
612 farg.fa_vnode.vp = vp;
613 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
614 vsop_find(&farg, &func, int, &arg0, vop_getattr,
615 femop_getattr);
616 errc = (*func)(arg0, vap, flags, cr, ct);
617 fem_release(femsp);
619 return (errc);
622 static int
623 vhead_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
624 caller_context_t *ct)
626 femarg_t farg;
627 struct fem_list *femsp;
628 int (*func)();
629 void *arg0;
630 int errc;
632 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
633 func = (int (*)()) (vp->v_op->vop_setattr);
634 arg0 = vp;
635 fem_unlock(vp->v_femhead);
636 errc = (*func)(arg0, vap, flags, cr, ct);
637 } else {
638 fem_addref(femsp);
639 fem_unlock(vp->v_femhead);
640 farg.fa_vnode.vp = vp;
641 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
642 vsop_find(&farg, &func, int, &arg0, vop_setattr,
643 femop_setattr);
644 errc = (*func)(arg0, vap, flags, cr, ct);
645 fem_release(femsp);
647 return (errc);
650 static int
651 vhead_access(vnode_t *vp, int mode, int flags, cred_t *cr,
652 caller_context_t *ct)
654 femarg_t farg;
655 struct fem_list *femsp;
656 int (*func)();
657 void *arg0;
658 int errc;
660 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
661 func = (int (*)()) (vp->v_op->vop_access);
662 arg0 = vp;
663 fem_unlock(vp->v_femhead);
664 errc = (*func)(arg0, mode, flags, cr, ct);
665 } else {
666 fem_addref(femsp);
667 fem_unlock(vp->v_femhead);
668 farg.fa_vnode.vp = vp;
669 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
670 vsop_find(&farg, &func, int, &arg0, vop_access,
671 femop_access);
672 errc = (*func)(arg0, mode, flags, cr, ct);
673 fem_release(femsp);
675 return (errc);
678 static int
679 vhead_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
680 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
681 int *direntflags, pathname_t *realpnp)
683 femarg_t farg;
684 struct fem_list *femsp;
685 int (*func)();
686 void *arg0;
687 int errc;
689 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
690 func = (int (*)()) (dvp->v_op->vop_lookup);
691 arg0 = dvp;
692 fem_unlock(dvp->v_femhead);
693 errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
694 direntflags, realpnp);
695 } else {
696 fem_addref(femsp);
697 fem_unlock(dvp->v_femhead);
698 farg.fa_vnode.vp = dvp;
699 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
700 vsop_find(&farg, &func, int, &arg0, vop_lookup,
701 femop_lookup);
702 errc = (*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
703 direntflags, realpnp);
704 fem_release(femsp);
706 return (errc);
709 static int
710 vhead_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl,
711 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
712 vsecattr_t *vsecp)
714 femarg_t farg;
715 struct fem_list *femsp;
716 int (*func)();
717 void *arg0;
718 int errc;
720 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
721 func = (int (*)()) (dvp->v_op->vop_create);
722 arg0 = dvp;
723 fem_unlock(dvp->v_femhead);
724 errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag,
725 ct, vsecp);
726 } else {
727 fem_addref(femsp);
728 fem_unlock(dvp->v_femhead);
729 farg.fa_vnode.vp = dvp;
730 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
731 vsop_find(&farg, &func, int, &arg0, vop_create,
732 femop_create);
733 errc = (*func)(arg0, name, vap, excl, mode, vpp, cr, flag,
734 ct, vsecp);
735 fem_release(femsp);
737 return (errc);
740 static int
741 vhead_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
742 int flags)
744 femarg_t farg;
745 struct fem_list *femsp;
746 int (*func)();
747 void *arg0;
748 int errc;
750 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
751 func = (int (*)()) (dvp->v_op->vop_remove);
752 arg0 = dvp;
753 fem_unlock(dvp->v_femhead);
754 errc = (*func)(arg0, nm, cr, ct, flags);
755 } else {
756 fem_addref(femsp);
757 fem_unlock(dvp->v_femhead);
758 farg.fa_vnode.vp = dvp;
759 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
760 vsop_find(&farg, &func, int, &arg0, vop_remove,
761 femop_remove);
762 errc = (*func)(arg0, nm, cr, ct, flags);
763 fem_release(femsp);
765 return (errc);
768 static int
769 vhead_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
770 caller_context_t *ct, int flags)
772 femarg_t farg;
773 struct fem_list *femsp;
774 int (*func)();
775 void *arg0;
776 int errc;
778 if ((femsp = fem_lock(tdvp->v_femhead)) == NULL) {
779 func = (int (*)()) (tdvp->v_op->vop_link);
780 arg0 = tdvp;
781 fem_unlock(tdvp->v_femhead);
782 errc = (*func)(arg0, svp, tnm, cr, ct, flags);
783 } else {
784 fem_addref(femsp);
785 fem_unlock(tdvp->v_femhead);
786 farg.fa_vnode.vp = tdvp;
787 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
788 vsop_find(&farg, &func, int, &arg0, vop_link, femop_link);
789 errc = (*func)(arg0, svp, tnm, cr, ct, flags);
790 fem_release(femsp);
792 return (errc);
795 static int
796 vhead_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
797 cred_t *cr, caller_context_t *ct, int flags)
799 femarg_t farg;
800 struct fem_list *femsp;
801 int (*func)();
802 void *arg0;
803 int errc;
805 if ((femsp = fem_lock(sdvp->v_femhead)) == NULL) {
806 func = (int (*)()) (sdvp->v_op->vop_rename);
807 arg0 = sdvp;
808 fem_unlock(sdvp->v_femhead);
809 errc = (*func)(arg0, snm, tdvp, tnm, cr, ct, flags);
810 } else {
811 fem_addref(femsp);
812 fem_unlock(sdvp->v_femhead);
813 farg.fa_vnode.vp = sdvp;
814 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
815 vsop_find(&farg, &func, int, &arg0, vop_rename,
816 femop_rename);
817 errc = (*func)(arg0, snm, tdvp, tnm, cr, ct, flags);
818 fem_release(femsp);
820 return (errc);
823 static int
824 vhead_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp,
825 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
827 femarg_t farg;
828 struct fem_list *femsp;
829 int (*func)();
830 void *arg0;
831 int errc;
833 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
834 func = (int (*)()) (dvp->v_op->vop_mkdir);
835 arg0 = dvp;
836 fem_unlock(dvp->v_femhead);
837 errc = (*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp);
838 } else {
839 fem_addref(femsp);
840 fem_unlock(dvp->v_femhead);
841 farg.fa_vnode.vp = dvp;
842 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
843 vsop_find(&farg, &func, int, &arg0, vop_mkdir, femop_mkdir);
844 errc = (*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp);
845 fem_release(femsp);
847 return (errc);
850 static int
851 vhead_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
852 caller_context_t *ct, int flags)
854 femarg_t farg;
855 struct fem_list *femsp;
856 int (*func)();
857 void *arg0;
858 int errc;
860 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
861 func = (int (*)()) (dvp->v_op->vop_rmdir);
862 arg0 = dvp;
863 fem_unlock(dvp->v_femhead);
864 errc = (*func)(arg0, nm, cdir, cr, ct, flags);
865 } else {
866 fem_addref(femsp);
867 fem_unlock(dvp->v_femhead);
868 farg.fa_vnode.vp = dvp;
869 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
870 vsop_find(&farg, &func, int, &arg0, vop_rmdir, femop_rmdir);
871 errc = (*func)(arg0, nm, cdir, cr, ct, flags);
872 fem_release(femsp);
874 return (errc);
877 static int
878 vhead_readdir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
879 caller_context_t *ct, int flags)
881 femarg_t farg;
882 struct fem_list *femsp;
883 int (*func)();
884 void *arg0;
885 int errc;
887 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
888 func = (int (*)()) (vp->v_op->vop_readdir);
889 arg0 = vp;
890 fem_unlock(vp->v_femhead);
891 errc = (*func)(arg0, uiop, cr, eofp, ct, flags);
892 } else {
893 fem_addref(femsp);
894 fem_unlock(vp->v_femhead);
895 farg.fa_vnode.vp = vp;
896 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
897 vsop_find(&farg, &func, int, &arg0, vop_readdir,
898 femop_readdir);
899 errc = (*func)(arg0, uiop, cr, eofp, ct, flags);
900 fem_release(femsp);
902 return (errc);
905 static int
906 vhead_symlink(vnode_t *dvp, char *linkname, vattr_t *vap, char *target,
907 cred_t *cr, caller_context_t *ct, int flags)
909 femarg_t farg;
910 struct fem_list *femsp;
911 int (*func)();
912 void *arg0;
913 int errc;
915 if ((femsp = fem_lock(dvp->v_femhead)) == NULL) {
916 func = (int (*)()) (dvp->v_op->vop_symlink);
917 arg0 = dvp;
918 fem_unlock(dvp->v_femhead);
919 errc = (*func)(arg0, linkname, vap, target, cr, ct, flags);
920 } else {
921 fem_addref(femsp);
922 fem_unlock(dvp->v_femhead);
923 farg.fa_vnode.vp = dvp;
924 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
925 vsop_find(&farg, &func, int, &arg0, vop_symlink,
926 femop_symlink);
927 errc = (*func)(arg0, linkname, vap, target, cr, ct, flags);
928 fem_release(femsp);
930 return (errc);
933 static int
934 vhead_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
936 femarg_t farg;
937 struct fem_list *femsp;
938 int (*func)();
939 void *arg0;
940 int errc;
942 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
943 func = (int (*)()) (vp->v_op->vop_readlink);
944 arg0 = vp;
945 fem_unlock(vp->v_femhead);
946 errc = (*func)(arg0, uiop, cr, ct);
947 } else {
948 fem_addref(femsp);
949 fem_unlock(vp->v_femhead);
950 farg.fa_vnode.vp = vp;
951 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
952 vsop_find(&farg, &func, int, &arg0, vop_readlink,
953 femop_readlink);
954 errc = (*func)(arg0, uiop, cr, ct);
955 fem_release(femsp);
957 return (errc);
960 static int
961 vhead_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
963 femarg_t farg;
964 struct fem_list *femsp;
965 int (*func)();
966 void *arg0;
967 int errc;
969 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
970 func = (int (*)()) (vp->v_op->vop_fsync);
971 arg0 = vp;
972 fem_unlock(vp->v_femhead);
973 errc = (*func)(arg0, syncflag, cr, ct);
974 } else {
975 fem_addref(femsp);
976 fem_unlock(vp->v_femhead);
977 farg.fa_vnode.vp = vp;
978 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
979 vsop_find(&farg, &func, int, &arg0, vop_fsync, femop_fsync);
980 errc = (*func)(arg0, syncflag, cr, ct);
981 fem_release(femsp);
983 return (errc);
986 static void
987 vhead_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
989 femarg_t farg;
990 struct fem_list *femsp;
991 void (*func)();
992 void *arg0;
994 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
995 func = (void (*)()) (vp->v_op->vop_inactive);
996 arg0 = vp;
997 fem_unlock(vp->v_femhead);
998 (*func)(arg0, cr, ct);
999 } else {
1000 fem_addref(femsp);
1001 fem_unlock(vp->v_femhead);
1002 farg.fa_vnode.vp = vp;
1003 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1004 vsop_find(&farg, &func, void, &arg0, vop_inactive,
1005 femop_inactive);
1006 (*func)(arg0, cr, ct);
1007 fem_release(femsp);
1011 static int
1012 vhead_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
1014 femarg_t farg;
1015 struct fem_list *femsp;
1016 int (*func)();
1017 void *arg0;
1018 int errc;
1020 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1021 func = (int (*)()) (vp->v_op->vop_fid);
1022 arg0 = vp;
1023 fem_unlock(vp->v_femhead);
1024 errc = (*func)(arg0, fidp, ct);
1025 } else {
1026 fem_addref(femsp);
1027 fem_unlock(vp->v_femhead);
1028 farg.fa_vnode.vp = vp;
1029 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1030 vsop_find(&farg, &func, int, &arg0, vop_fid, femop_fid);
1031 errc = (*func)(arg0, fidp, ct);
1032 fem_release(femsp);
1034 return (errc);
1037 static int
1038 vhead_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1040 femarg_t farg;
1041 struct fem_list *femsp;
1042 int (*func)();
1043 void *arg0;
1044 int errc;
1046 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1047 func = (int (*)()) (vp->v_op->vop_rwlock);
1048 arg0 = vp;
1049 fem_unlock(vp->v_femhead);
1050 errc = (*func)(arg0, write_lock, ct);
1051 } else {
1052 fem_addref(femsp);
1053 fem_unlock(vp->v_femhead);
1054 farg.fa_vnode.vp = vp;
1055 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1056 vsop_find(&farg, &func, int, &arg0, vop_rwlock,
1057 femop_rwlock);
1058 errc = (*func)(arg0, write_lock, ct);
1059 fem_release(femsp);
1061 return (errc);
1064 static void
1065 vhead_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1067 femarg_t farg;
1068 struct fem_list *femsp;
1069 void (*func)();
1070 void *arg0;
1072 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1073 func = (void (*)()) (vp->v_op->vop_rwunlock);
1074 arg0 = vp;
1075 fem_unlock(vp->v_femhead);
1076 (*func)(arg0, write_lock, ct);
1077 } else {
1078 fem_addref(femsp);
1079 fem_unlock(vp->v_femhead);
1080 farg.fa_vnode.vp = vp;
1081 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1082 vsop_find(&farg, &func, void, &arg0, vop_rwunlock,
1083 femop_rwunlock);
1084 (*func)(arg0, write_lock, ct);
1085 fem_release(femsp);
1089 static int
1090 vhead_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
1092 femarg_t farg;
1093 struct fem_list *femsp;
1094 int (*func)();
1095 void *arg0;
1096 int errc;
1098 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1099 func = (int (*)()) (vp->v_op->vop_seek);
1100 arg0 = vp;
1101 fem_unlock(vp->v_femhead);
1102 errc = (*func)(arg0, ooff, noffp, ct);
1103 } else {
1104 fem_addref(femsp);
1105 fem_unlock(vp->v_femhead);
1106 farg.fa_vnode.vp = vp;
1107 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1108 vsop_find(&farg, &func, int, &arg0, vop_seek, femop_seek);
1109 errc = (*func)(arg0, ooff, noffp, ct);
1110 fem_release(femsp);
1112 return (errc);
1115 static int
1116 vhead_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
1118 femarg_t farg;
1119 struct fem_list *femsp;
1120 int (*func)();
1121 void *arg0;
1122 int errc;
1124 if ((femsp = fem_lock(vp1->v_femhead)) == NULL) {
1125 func = (int (*)()) (vp1->v_op->vop_cmp);
1126 arg0 = vp1;
1127 fem_unlock(vp1->v_femhead);
1128 errc = (*func)(arg0, vp2, ct);
1129 } else {
1130 fem_addref(femsp);
1131 fem_unlock(vp1->v_femhead);
1132 farg.fa_vnode.vp = vp1;
1133 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1134 vsop_find(&farg, &func, int, &arg0, vop_cmp, femop_cmp);
1135 errc = (*func)(arg0, vp2, ct);
1136 fem_release(femsp);
1138 return (errc);
1141 static int
1142 vhead_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1143 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
1144 caller_context_t *ct)
1146 femarg_t farg;
1147 struct fem_list *femsp;
1148 int (*func)();
1149 void *arg0;
1150 int errc;
1152 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1153 func = (int (*)()) (vp->v_op->vop_frlock);
1154 arg0 = vp;
1155 fem_unlock(vp->v_femhead);
1156 errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
1157 } else {
1158 fem_addref(femsp);
1159 fem_unlock(vp->v_femhead);
1160 farg.fa_vnode.vp = vp;
1161 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1162 vsop_find(&farg, &func, int, &arg0, vop_frlock,
1163 femop_frlock);
1164 errc = (*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct);
1165 fem_release(femsp);
1167 return (errc);
1170 static int
1171 vhead_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
1172 offset_t offset, cred_t *cr, caller_context_t *ct)
1174 femarg_t farg;
1175 struct fem_list *femsp;
1176 int (*func)();
1177 void *arg0;
1178 int errc;
1180 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1181 func = (int (*)()) (vp->v_op->vop_space);
1182 arg0 = vp;
1183 fem_unlock(vp->v_femhead);
1184 errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1185 } else {
1186 fem_addref(femsp);
1187 fem_unlock(vp->v_femhead);
1188 farg.fa_vnode.vp = vp;
1189 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1190 vsop_find(&farg, &func, int, &arg0, vop_space, femop_space);
1191 errc = (*func)(arg0, cmd, bfp, flag, offset, cr, ct);
1192 fem_release(femsp);
1194 return (errc);
1197 static int
1198 vhead_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
1200 femarg_t farg;
1201 struct fem_list *femsp;
1202 int (*func)();
1203 void *arg0;
1204 int errc;
1206 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1207 func = (int (*)()) (vp->v_op->vop_realvp);
1208 arg0 = vp;
1209 fem_unlock(vp->v_femhead);
1210 errc = (*func)(arg0, vpp, ct);
1211 } else {
1212 fem_addref(femsp);
1213 fem_unlock(vp->v_femhead);
1214 farg.fa_vnode.vp = vp;
1215 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1216 vsop_find(&farg, &func, int, &arg0, vop_realvp,
1217 femop_realvp);
1218 errc = (*func)(arg0, vpp, ct);
1219 fem_release(femsp);
1221 return (errc);
1224 static int
1225 vhead_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
1226 struct page **plarr, size_t plsz, struct seg *seg, caddr_t addr,
1227 enum seg_rw rw, cred_t *cr, caller_context_t *ct)
1229 femarg_t farg;
1230 struct fem_list *femsp;
1231 int (*func)();
1232 void *arg0;
1233 int errc;
1235 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1236 func = (int (*)()) (vp->v_op->vop_getpage);
1237 arg0 = vp;
1238 fem_unlock(vp->v_femhead);
1239 errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1240 addr, rw, cr, ct);
1241 } else {
1242 fem_addref(femsp);
1243 fem_unlock(vp->v_femhead);
1244 farg.fa_vnode.vp = vp;
1245 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1246 vsop_find(&farg, &func, int, &arg0, vop_getpage,
1247 femop_getpage);
1248 errc = (*func)(arg0, off, len, protp, plarr, plsz, seg,
1249 addr, rw, cr, ct);
1250 fem_release(femsp);
1252 return (errc);
1255 static int
1256 vhead_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
1257 caller_context_t *ct)
1259 femarg_t farg;
1260 struct fem_list *femsp;
1261 int (*func)();
1262 void *arg0;
1263 int errc;
1265 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1266 func = (int (*)()) (vp->v_op->vop_putpage);
1267 arg0 = vp;
1268 fem_unlock(vp->v_femhead);
1269 errc = (*func)(arg0, off, len, flags, cr, ct);
1270 } else {
1271 fem_addref(femsp);
1272 fem_unlock(vp->v_femhead);
1273 farg.fa_vnode.vp = vp;
1274 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1275 vsop_find(&farg, &func, int, &arg0, vop_putpage,
1276 femop_putpage);
1277 errc = (*func)(arg0, off, len, flags, cr, ct);
1278 fem_release(femsp);
1280 return (errc);
1283 static int
1284 vhead_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
1285 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1286 cred_t *cr, caller_context_t *ct)
1288 femarg_t farg;
1289 struct fem_list *femsp;
1290 int (*func)();
1291 void *arg0;
1292 int errc;
1294 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1295 func = (int (*)()) (vp->v_op->vop_map);
1296 arg0 = vp;
1297 fem_unlock(vp->v_femhead);
1298 errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1299 flags, cr, ct);
1300 } else {
1301 fem_addref(femsp);
1302 fem_unlock(vp->v_femhead);
1303 farg.fa_vnode.vp = vp;
1304 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1305 vsop_find(&farg, &func, int, &arg0, vop_map, femop_map);
1306 errc = (*func)(arg0, off, as, addrp, len, prot, maxprot,
1307 flags, cr, ct);
1308 fem_release(femsp);
1310 return (errc);
1313 static int
1314 vhead_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1315 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
1316 cred_t *cr, caller_context_t *ct)
1318 femarg_t farg;
1319 struct fem_list *femsp;
1320 int (*func)();
1321 void *arg0;
1322 int errc;
1324 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1325 func = (int (*)()) (vp->v_op->vop_addmap);
1326 arg0 = vp;
1327 fem_unlock(vp->v_femhead);
1328 errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1329 flags, cr, ct);
1330 } else {
1331 fem_addref(femsp);
1332 fem_unlock(vp->v_femhead);
1333 farg.fa_vnode.vp = vp;
1334 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1335 vsop_find(&farg, &func, int, &arg0, vop_addmap,
1336 femop_addmap);
1337 errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1338 flags, cr, ct);
1339 fem_release(femsp);
1341 return (errc);
1344 static int
1345 vhead_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
1346 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
1347 caller_context_t *ct)
1349 femarg_t farg;
1350 struct fem_list *femsp;
1351 int (*func)();
1352 void *arg0;
1353 int errc;
1355 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1356 func = (int (*)()) (vp->v_op->vop_delmap);
1357 arg0 = vp;
1358 fem_unlock(vp->v_femhead);
1359 errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1360 flags, cr, ct);
1361 } else {
1362 fem_addref(femsp);
1363 fem_unlock(vp->v_femhead);
1364 farg.fa_vnode.vp = vp;
1365 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1366 vsop_find(&farg, &func, int, &arg0, vop_delmap,
1367 femop_delmap);
1368 errc = (*func)(arg0, off, as, addr, len, prot, maxprot,
1369 flags, cr, ct);
1370 fem_release(femsp);
1372 return (errc);
1375 static int
1376 vhead_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
1377 struct pollhead **phpp, caller_context_t *ct)
1379 femarg_t farg;
1380 struct fem_list *femsp;
1381 int (*func)();
1382 void *arg0;
1383 int errc;
1385 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1386 func = (int (*)()) (vp->v_op->vop_poll);
1387 arg0 = vp;
1388 fem_unlock(vp->v_femhead);
1389 errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
1390 } else {
1391 fem_addref(femsp);
1392 fem_unlock(vp->v_femhead);
1393 farg.fa_vnode.vp = vp;
1394 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1395 vsop_find(&farg, &func, int, &arg0, vop_poll, femop_poll);
1396 errc = (*func)(arg0, events, anyyet, reventsp, phpp, ct);
1397 fem_release(femsp);
1399 return (errc);
1402 static int
1403 vhead_dump(vnode_t *vp, caddr_t addr, offset_t lbdn, offset_t dblks,
1404 caller_context_t *ct)
1406 femarg_t farg;
1407 struct fem_list *femsp;
1408 int (*func)();
1409 void *arg0;
1410 int errc;
1412 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1413 func = (int (*)()) (vp->v_op->vop_dump);
1414 arg0 = vp;
1415 fem_unlock(vp->v_femhead);
1416 errc = (*func)(arg0, addr, lbdn, dblks, ct);
1417 } else {
1418 fem_addref(femsp);
1419 fem_unlock(vp->v_femhead);
1420 farg.fa_vnode.vp = vp;
1421 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1422 vsop_find(&farg, &func, int, &arg0, vop_dump, femop_dump);
1423 errc = (*func)(arg0, addr, lbdn, dblks, ct);
1424 fem_release(femsp);
1426 return (errc);
1429 static int
1430 vhead_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
1431 caller_context_t *ct)
1433 femarg_t farg;
1434 struct fem_list *femsp;
1435 int (*func)();
1436 void *arg0;
1437 int errc;
1439 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1440 func = (int (*)()) (vp->v_op->vop_pathconf);
1441 arg0 = vp;
1442 fem_unlock(vp->v_femhead);
1443 errc = (*func)(arg0, cmd, valp, cr, ct);
1444 } else {
1445 fem_addref(femsp);
1446 fem_unlock(vp->v_femhead);
1447 farg.fa_vnode.vp = vp;
1448 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1449 vsop_find(&farg, &func, int, &arg0, vop_pathconf,
1450 femop_pathconf);
1451 errc = (*func)(arg0, cmd, valp, cr, ct);
1452 fem_release(femsp);
1454 return (errc);
1457 static int
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)
1461 femarg_t farg;
1462 struct fem_list *femsp;
1463 int (*func)();
1464 void *arg0;
1465 int errc;
1467 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1468 func = (int (*)()) (vp->v_op->vop_pageio);
1469 arg0 = vp;
1470 fem_unlock(vp->v_femhead);
1471 errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
1472 } else {
1473 fem_addref(femsp);
1474 fem_unlock(vp->v_femhead);
1475 farg.fa_vnode.vp = vp;
1476 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1477 vsop_find(&farg, &func, int, &arg0, vop_pageio,
1478 femop_pageio);
1479 errc = (*func)(arg0, pp, io_off, io_len, flags, cr, ct);
1480 fem_release(femsp);
1482 return (errc);
1485 static int
1486 vhead_dumpctl(vnode_t *vp, int action, offset_t *blkp, caller_context_t *ct)
1488 femarg_t farg;
1489 struct fem_list *femsp;
1490 int (*func)();
1491 void *arg0;
1492 int errc;
1494 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1495 func = (int (*)()) (vp->v_op->vop_dumpctl);
1496 arg0 = vp;
1497 fem_unlock(vp->v_femhead);
1498 errc = (*func)(arg0, action, blkp, ct);
1499 } else {
1500 fem_addref(femsp);
1501 fem_unlock(vp->v_femhead);
1502 farg.fa_vnode.vp = vp;
1503 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1504 vsop_find(&farg, &func, int, &arg0, vop_dumpctl,
1505 femop_dumpctl);
1506 errc = (*func)(arg0, action, blkp, ct);
1507 fem_release(femsp);
1509 return (errc);
1512 static void
1513 vhead_dispose(vnode_t *vp, struct page *pp, int flag, int dn, cred_t *cr,
1514 caller_context_t *ct)
1516 femarg_t farg;
1517 struct fem_list *femsp;
1518 void (*func)();
1519 void *arg0;
1521 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1522 func = (void (*)()) (vp->v_op->vop_dispose);
1523 arg0 = vp;
1524 fem_unlock(vp->v_femhead);
1525 (*func)(arg0, pp, flag, dn, cr, ct);
1526 } else {
1527 fem_addref(femsp);
1528 fem_unlock(vp->v_femhead);
1529 farg.fa_vnode.vp = vp;
1530 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1531 vsop_find(&farg, &func, void, &arg0, vop_dispose,
1532 femop_dispose);
1533 (*func)(arg0, pp, flag, dn, cr, ct);
1534 fem_release(femsp);
1538 static int
1539 vhead_setsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
1540 caller_context_t *ct)
1542 femarg_t farg;
1543 struct fem_list *femsp;
1544 int (*func)();
1545 void *arg0;
1546 int errc;
1548 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1549 func = (int (*)()) (vp->v_op->vop_setsecattr);
1550 arg0 = vp;
1551 fem_unlock(vp->v_femhead);
1552 errc = (*func)(arg0, vsap, flag, cr, ct);
1553 } else {
1554 fem_addref(femsp);
1555 fem_unlock(vp->v_femhead);
1556 farg.fa_vnode.vp = vp;
1557 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1558 vsop_find(&farg, &func, int, &arg0, vop_setsecattr,
1559 femop_setsecattr);
1560 errc = (*func)(arg0, vsap, flag, cr, ct);
1561 fem_release(femsp);
1563 return (errc);
1566 static int
1567 vhead_getsecattr(vnode_t *vp, vsecattr_t *vsap, int flag, cred_t *cr,
1568 caller_context_t *ct)
1570 femarg_t farg;
1571 struct fem_list *femsp;
1572 int (*func)();
1573 void *arg0;
1574 int errc;
1576 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1577 func = (int (*)()) (vp->v_op->vop_getsecattr);
1578 arg0 = vp;
1579 fem_unlock(vp->v_femhead);
1580 errc = (*func)(arg0, vsap, flag, cr, ct);
1581 } else {
1582 fem_addref(femsp);
1583 fem_unlock(vp->v_femhead);
1584 farg.fa_vnode.vp = vp;
1585 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1586 vsop_find(&farg, &func, int, &arg0, vop_getsecattr,
1587 femop_getsecattr);
1588 errc = (*func)(arg0, vsap, flag, cr, ct);
1589 fem_release(femsp);
1591 return (errc);
1594 static int
1595 vhead_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag,
1596 cred_t *cr, caller_context_t *ct)
1598 femarg_t farg;
1599 struct fem_list *femsp;
1600 int (*func)();
1601 void *arg0;
1602 int errc;
1604 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1605 func = (int (*)()) (vp->v_op->vop_shrlock);
1606 arg0 = vp;
1607 fem_unlock(vp->v_femhead);
1608 errc = (*func)(arg0, cmd, shr, flag, cr, ct);
1609 } else {
1610 fem_addref(femsp);
1611 fem_unlock(vp->v_femhead);
1612 farg.fa_vnode.vp = vp;
1613 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1614 vsop_find(&farg, &func, int, &arg0, vop_shrlock,
1615 femop_shrlock);
1616 errc = (*func)(arg0, cmd, shr, flag, cr, ct);
1617 fem_release(femsp);
1619 return (errc);
1622 static int
1623 vhead_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *cname,
1624 caller_context_t *ct)
1626 femarg_t farg;
1627 struct fem_list *femsp;
1628 int (*func)();
1629 void *arg0;
1630 int errc;
1632 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1633 func = (int (*)()) (vp->v_op->vop_vnevent);
1634 arg0 = vp;
1635 fem_unlock(vp->v_femhead);
1636 errc = (*func)(arg0, vnevent, dvp, cname, ct);
1637 } else {
1638 fem_addref(femsp);
1639 fem_unlock(vp->v_femhead);
1640 farg.fa_vnode.vp = vp;
1641 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1642 vsop_find(&farg, &func, int, &arg0, vop_vnevent,
1643 femop_vnevent);
1644 errc = (*func)(arg0, vnevent, dvp, cname, ct);
1645 fem_release(femsp);
1647 return (errc);
1650 static int
1651 vhead_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuiop, cred_t *cr,
1652 caller_context_t *ct)
1654 femarg_t farg;
1655 struct fem_list *femsp;
1656 int (*func)();
1657 void *arg0;
1658 int errc;
1660 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1661 func = (int (*)()) (vp->v_op->vop_reqzcbuf);
1662 arg0 = vp;
1663 fem_unlock(vp->v_femhead);
1664 errc = (*func)(arg0, ioflag, xuiop, cr, ct);
1665 } else {
1666 fem_addref(femsp);
1667 fem_unlock(vp->v_femhead);
1668 farg.fa_vnode.vp = vp;
1669 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1670 vsop_find(&farg, &func, int, &arg0, vop_reqzcbuf,
1671 femop_reqzcbuf);
1672 errc = (*func)(arg0, ioflag, xuiop, cr, ct);
1673 fem_release(femsp);
1675 return (errc);
1678 static int
1679 vhead_retzcbuf(vnode_t *vp, xuio_t *xuiop, cred_t *cr, caller_context_t *ct)
1681 femarg_t farg;
1682 struct fem_list *femsp;
1683 int (*func)();
1684 void *arg0;
1685 int errc;
1687 if ((femsp = fem_lock(vp->v_femhead)) == NULL) {
1688 func = (int (*)()) (vp->v_op->vop_retzcbuf);
1689 arg0 = vp;
1690 fem_unlock(vp->v_femhead);
1691 errc = (*func)(arg0, xuiop, cr, ct);
1692 } else {
1693 fem_addref(femsp);
1694 fem_unlock(vp->v_femhead);
1695 farg.fa_vnode.vp = vp;
1696 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1697 vsop_find(&farg, &func, int, &arg0, vop_retzcbuf,
1698 femop_retzcbuf);
1699 errc = (*func)(arg0, xuiop, cr, ct);
1700 fem_release(femsp);
1702 return (errc);
1705 static int
1706 fshead_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
1708 fsemarg_t farg;
1709 struct fem_list *femsp;
1710 int (*func)();
1711 void *arg0;
1712 int errc;
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);
1720 } else {
1721 fem_addref(femsp);
1722 fem_unlock(vfsp->vfs_femhead);
1723 farg.fa_vnode.vfsp = vfsp;
1724 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1725 vfsop_find(&farg, &func, int, &arg0, vfs_mount,
1726 fsemop_mount);
1727 errc = (*func)(arg0, mvp, uap, cr);
1728 fem_release(femsp);
1730 return (errc);
1733 static int
1734 fshead_unmount(vfs_t *vfsp, int flag, cred_t *cr)
1736 fsemarg_t farg;
1737 struct fem_list *femsp;
1738 int (*func)();
1739 void *arg0;
1740 int errc;
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);
1748 } else {
1749 fem_addref(femsp);
1750 fem_unlock(vfsp->vfs_femhead);
1751 farg.fa_vnode.vfsp = vfsp;
1752 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1753 vfsop_find(&farg, &func, int, &arg0, vfs_unmount,
1754 fsemop_unmount);
1755 errc = (*func)(arg0, flag, cr);
1756 fem_release(femsp);
1758 return (errc);
1761 static int
1762 fshead_root(vfs_t *vfsp, vnode_t **vpp)
1764 fsemarg_t farg;
1765 struct fem_list *femsp;
1766 int (*func)();
1767 void *arg0;
1768 int errc;
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);
1776 } else {
1777 fem_addref(femsp);
1778 fem_unlock(vfsp->vfs_femhead);
1779 farg.fa_vnode.vfsp = vfsp;
1780 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1781 vfsop_find(&farg, &func, int, &arg0, vfs_root, fsemop_root);
1782 errc = (*func)(arg0, vpp);
1783 fem_release(femsp);
1785 return (errc);
1788 static int
1789 fshead_statvfs(vfs_t *vfsp, statvfs64_t *sp)
1791 fsemarg_t farg;
1792 struct fem_list *femsp;
1793 int (*func)();
1794 void *arg0;
1795 int errc;
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);
1803 } else {
1804 fem_addref(femsp);
1805 fem_unlock(vfsp->vfs_femhead);
1806 farg.fa_vnode.vfsp = vfsp;
1807 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1808 vfsop_find(&farg, &func, int, &arg0, vfs_statvfs,
1809 fsemop_statvfs);
1810 errc = (*func)(arg0, sp);
1811 fem_release(femsp);
1813 return (errc);
1816 static int
1817 fshead_sync(vfs_t *vfsp, short flag, cred_t *cr)
1819 fsemarg_t farg;
1820 struct fem_list *femsp;
1821 int (*func)();
1822 void *arg0;
1823 int errc;
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);
1831 } else {
1832 fem_addref(femsp);
1833 fem_unlock(vfsp->vfs_femhead);
1834 farg.fa_vnode.vfsp = vfsp;
1835 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1836 vfsop_find(&farg, &func, int, &arg0, vfs_sync, fsemop_sync);
1837 errc = (*func)(arg0, flag, cr);
1838 fem_release(femsp);
1840 return (errc);
1843 static int
1844 fshead_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
1846 fsemarg_t farg;
1847 struct fem_list *femsp;
1848 int (*func)();
1849 void *arg0;
1850 int errc;
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);
1858 } else {
1859 fem_addref(femsp);
1860 fem_unlock(vfsp->vfs_femhead);
1861 farg.fa_vnode.vfsp = vfsp;
1862 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1863 vfsop_find(&farg, &func, int, &arg0, vfs_vget, fsemop_vget);
1864 errc = (*func)(arg0, vpp, fidp);
1865 fem_release(femsp);
1867 return (errc);
1870 static int
1871 fshead_mountroot(vfs_t *vfsp, enum whymountroot reason)
1873 fsemarg_t farg;
1874 struct fem_list *femsp;
1875 int (*func)();
1876 void *arg0;
1877 int errc;
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);
1885 } else {
1886 fem_addref(femsp);
1887 fem_unlock(vfsp->vfs_femhead);
1888 farg.fa_vnode.vfsp = vfsp;
1889 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1890 vfsop_find(&farg, &func, int, &arg0, vfs_mountroot,
1891 fsemop_mountroot);
1892 errc = (*func)(arg0, reason);
1893 fem_release(femsp);
1895 return (errc);
1898 static void
1899 fshead_freevfs(vfs_t *vfsp)
1901 fsemarg_t farg;
1902 struct fem_list *femsp;
1903 void (*func)();
1904 void *arg0;
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);
1911 (*func)(vfsp);
1912 } else {
1913 fem_addref(femsp);
1914 fem_unlock(vfsp->vfs_femhead);
1915 farg.fa_vnode.vfsp = vfsp;
1916 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1917 vfsop_find(&farg, &func, void, &arg0, vfs_freevfs,
1918 fsemop_freevfs);
1919 (*func)(arg0);
1920 fem_release(femsp);
1924 static int
1925 fshead_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
1927 fsemarg_t farg;
1928 struct fem_list *femsp;
1929 int (*func)();
1930 void *arg0;
1931 int errc;
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);
1939 } else {
1940 fem_addref(femsp);
1941 fem_unlock(vfsp->vfs_femhead);
1942 farg.fa_vnode.vfsp = vfsp;
1943 farg.fa_fnode = femsp->feml_nodes + femsp->feml_tos;
1944 vfsop_find(&farg, &func, int, &arg0, vfs_vnstate,
1945 fsemop_vnstate);
1946 errc = (*func)(arg0, vp, nstate);
1947 fem_release(femsp);
1949 return (errc);
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 },
2005 { NULL, NULL }
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 },
2023 { NULL, NULL }
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;
2047 void *arg0 = NULL;
2049 ASSERT(vf != NULL);
2050 vf->fa_fnode--;
2051 vsop_find(vf, &func, int, &arg0, vop_open, femop_open);
2052 ASSERT(func != NULL);
2053 ASSERT(arg0 != NULL);
2054 return ((*func)(arg0, mode, cr, ct));
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;
2062 void *arg0 = NULL;
2064 ASSERT(vf != NULL);
2065 vf->fa_fnode--;
2066 vsop_find(vf, &func, int, &arg0, vop_close, femop_close);
2067 ASSERT(func != NULL);
2068 ASSERT(arg0 != NULL);
2069 return ((*func)(arg0, flag, count, offset, cr, ct));
2073 vnext_read(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
2074 caller_context_t *ct)
2076 int (*func)() = NULL;
2077 void *arg0 = NULL;
2079 ASSERT(vf != NULL);
2080 vf->fa_fnode--;
2081 vsop_find(vf, &func, int, &arg0, vop_read, femop_read);
2082 ASSERT(func != NULL);
2083 ASSERT(arg0 != NULL);
2084 return ((*func)(arg0, uiop, ioflag, cr, ct));
2088 vnext_write(femarg_t *vf, uio_t *uiop, int ioflag, cred_t *cr,
2089 caller_context_t *ct)
2091 int (*func)() = NULL;
2092 void *arg0 = NULL;
2094 ASSERT(vf != NULL);
2095 vf->fa_fnode--;
2096 vsop_find(vf, &func, int, &arg0, vop_write, femop_write);
2097 ASSERT(func != NULL);
2098 ASSERT(arg0 != NULL);
2099 return ((*func)(arg0, uiop, ioflag, cr, ct));
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;
2107 void *arg0 = NULL;
2109 ASSERT(vf != NULL);
2110 vf->fa_fnode--;
2111 vsop_find(vf, &func, int, &arg0, vop_ioctl, femop_ioctl);
2112 ASSERT(func != NULL);
2113 ASSERT(arg0 != NULL);
2114 return ((*func)(arg0, cmd, arg, flag, cr, rvalp, ct));
2118 vnext_setfl(femarg_t *vf, int oflags, int nflags, cred_t *cr,
2119 caller_context_t *ct)
2121 int (*func)() = NULL;
2122 void *arg0 = NULL;
2124 ASSERT(vf != NULL);
2125 vf->fa_fnode--;
2126 vsop_find(vf, &func, int, &arg0, vop_setfl, femop_setfl);
2127 ASSERT(func != NULL);
2128 ASSERT(arg0 != NULL);
2129 return ((*func)(arg0, oflags, nflags, cr, ct));
2133 vnext_getattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
2134 caller_context_t *ct)
2136 int (*func)() = NULL;
2137 void *arg0 = NULL;
2139 ASSERT(vf != NULL);
2140 vf->fa_fnode--;
2141 vsop_find(vf, &func, int, &arg0, vop_getattr, femop_getattr);
2142 ASSERT(func != NULL);
2143 ASSERT(arg0 != NULL);
2144 return ((*func)(arg0, vap, flags, cr, ct));
2148 vnext_setattr(femarg_t *vf, vattr_t *vap, int flags, cred_t *cr,
2149 caller_context_t *ct)
2151 int (*func)() = NULL;
2152 void *arg0 = NULL;
2154 ASSERT(vf != NULL);
2155 vf->fa_fnode--;
2156 vsop_find(vf, &func, int, &arg0, vop_setattr, femop_setattr);
2157 ASSERT(func != NULL);
2158 ASSERT(arg0 != NULL);
2159 return ((*func)(arg0, vap, flags, cr, ct));
2163 vnext_access(femarg_t *vf, int mode, int flags, cred_t *cr,
2164 caller_context_t *ct)
2166 int (*func)() = NULL;
2167 void *arg0 = NULL;
2169 ASSERT(vf != NULL);
2170 vf->fa_fnode--;
2171 vsop_find(vf, &func, int, &arg0, vop_access, femop_access);
2172 ASSERT(func != NULL);
2173 ASSERT(arg0 != NULL);
2174 return ((*func)(arg0, mode, flags, cr, ct));
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;
2183 void *arg0 = NULL;
2185 ASSERT(vf != NULL);
2186 vf->fa_fnode--;
2187 vsop_find(vf, &func, int, &arg0, vop_lookup, femop_lookup);
2188 ASSERT(func != NULL);
2189 ASSERT(arg0 != NULL);
2190 return ((*func)(arg0, nm, vpp, pnp, flags, rdir, cr, ct,
2191 direntflags, realpnp));
2195 vnext_create(femarg_t *vf, char *name, vattr_t *vap, vcexcl_t excl,
2196 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
2197 vsecattr_t *vsecp)
2199 int (*func)() = NULL;
2200 void *arg0 = NULL;
2202 ASSERT(vf != NULL);
2203 vf->fa_fnode--;
2204 vsop_find(vf, &func, int, &arg0, vop_create, femop_create);
2205 ASSERT(func != NULL);
2206 ASSERT(arg0 != NULL);
2207 return ((*func)(arg0, name, vap, excl, mode, vpp, cr, flag, ct, vsecp));
2211 vnext_remove(femarg_t *vf, char *nm, cred_t *cr, caller_context_t *ct,
2212 int flags)
2214 int (*func)() = NULL;
2215 void *arg0 = NULL;
2217 ASSERT(vf != NULL);
2218 vf->fa_fnode--;
2219 vsop_find(vf, &func, int, &arg0, vop_remove, femop_remove);
2220 ASSERT(func != NULL);
2221 ASSERT(arg0 != NULL);
2222 return ((*func)(arg0, nm, cr, ct, flags));
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;
2230 void *arg0 = NULL;
2232 ASSERT(vf != NULL);
2233 vf->fa_fnode--;
2234 vsop_find(vf, &func, int, &arg0, vop_link, femop_link);
2235 ASSERT(func != NULL);
2236 ASSERT(arg0 != NULL);
2237 return ((*func)(arg0, svp, tnm, cr, ct, flags));
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;
2245 void *arg0 = NULL;
2247 ASSERT(vf != NULL);
2248 vf->fa_fnode--;
2249 vsop_find(vf, &func, int, &arg0, vop_rename, femop_rename);
2250 ASSERT(func != NULL);
2251 ASSERT(arg0 != NULL);
2252 return ((*func)(arg0, snm, tdvp, tnm, cr, ct, flags));
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;
2260 void *arg0 = NULL;
2262 ASSERT(vf != NULL);
2263 vf->fa_fnode--;
2264 vsop_find(vf, &func, int, &arg0, vop_mkdir, femop_mkdir);
2265 ASSERT(func != NULL);
2266 ASSERT(arg0 != NULL);
2267 return ((*func)(arg0, dirname, vap, vpp, cr, ct, flags, vsecp));
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;
2275 void *arg0 = NULL;
2277 ASSERT(vf != NULL);
2278 vf->fa_fnode--;
2279 vsop_find(vf, &func, int, &arg0, vop_rmdir, femop_rmdir);
2280 ASSERT(func != NULL);
2281 ASSERT(arg0 != NULL);
2282 return ((*func)(arg0, nm, cdir, cr, ct, flags));
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;
2290 void *arg0 = NULL;
2292 ASSERT(vf != NULL);
2293 vf->fa_fnode--;
2294 vsop_find(vf, &func, int, &arg0, vop_readdir, femop_readdir);
2295 ASSERT(func != NULL);
2296 ASSERT(arg0 != NULL);
2297 return ((*func)(arg0, uiop, cr, eofp, ct, flags));
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;
2305 void *arg0 = NULL;
2307 ASSERT(vf != NULL);
2308 vf->fa_fnode--;
2309 vsop_find(vf, &func, int, &arg0, vop_symlink, femop_symlink);
2310 ASSERT(func != NULL);
2311 ASSERT(arg0 != NULL);
2312 return ((*func)(arg0, linkname, vap, target, cr, ct, flags));
2316 vnext_readlink(femarg_t *vf, uio_t *uiop, cred_t *cr, caller_context_t *ct)
2318 int (*func)() = NULL;
2319 void *arg0 = NULL;
2321 ASSERT(vf != NULL);
2322 vf->fa_fnode--;
2323 vsop_find(vf, &func, int, &arg0, vop_readlink, femop_readlink);
2324 ASSERT(func != NULL);
2325 ASSERT(arg0 != NULL);
2326 return ((*func)(arg0, uiop, cr, ct));
2330 vnext_fsync(femarg_t *vf, int syncflag, cred_t *cr, caller_context_t *ct)
2332 int (*func)() = NULL;
2333 void *arg0 = NULL;
2335 ASSERT(vf != NULL);
2336 vf->fa_fnode--;
2337 vsop_find(vf, &func, int, &arg0, vop_fsync, femop_fsync);
2338 ASSERT(func != NULL);
2339 ASSERT(arg0 != NULL);
2340 return ((*func)(arg0, syncflag, cr, ct));
2343 void
2344 vnext_inactive(femarg_t *vf, cred_t *cr, caller_context_t *ct)
2346 void (*func)() = NULL;
2347 void *arg0 = NULL;
2349 ASSERT(vf != NULL);
2350 vf->fa_fnode--;
2351 vsop_find(vf, &func, void, &arg0, vop_inactive, femop_inactive);
2352 ASSERT(func != NULL);
2353 ASSERT(arg0 != NULL);
2354 (*func)(arg0, cr, ct);
2358 vnext_fid(femarg_t *vf, fid_t *fidp, caller_context_t *ct)
2360 int (*func)() = NULL;
2361 void *arg0 = NULL;
2363 ASSERT(vf != NULL);
2364 vf->fa_fnode--;
2365 vsop_find(vf, &func, int, &arg0, vop_fid, femop_fid);
2366 ASSERT(func != NULL);
2367 ASSERT(arg0 != NULL);
2368 return ((*func)(arg0, fidp, ct));
2372 vnext_rwlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2374 int (*func)() = NULL;
2375 void *arg0 = NULL;
2377 ASSERT(vf != NULL);
2378 vf->fa_fnode--;
2379 vsop_find(vf, &func, int, &arg0, vop_rwlock, femop_rwlock);
2380 ASSERT(func != NULL);
2381 ASSERT(arg0 != NULL);
2382 return ((*func)(arg0, write_lock, ct));
2385 void
2386 vnext_rwunlock(femarg_t *vf, int write_lock, caller_context_t *ct)
2388 void (*func)() = NULL;
2389 void *arg0 = NULL;
2391 ASSERT(vf != NULL);
2392 vf->fa_fnode--;
2393 vsop_find(vf, &func, void, &arg0, vop_rwunlock, femop_rwunlock);
2394 ASSERT(func != NULL);
2395 ASSERT(arg0 != NULL);
2396 (*func)(arg0, write_lock, ct);
2400 vnext_seek(femarg_t *vf, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2402 int (*func)() = NULL;
2403 void *arg0 = NULL;
2405 ASSERT(vf != NULL);
2406 vf->fa_fnode--;
2407 vsop_find(vf, &func, int, &arg0, vop_seek, femop_seek);
2408 ASSERT(func != NULL);
2409 ASSERT(arg0 != NULL);
2410 return ((*func)(arg0, ooff, noffp, ct));
2414 vnext_cmp(femarg_t *vf, vnode_t *vp2, caller_context_t *ct)
2416 int (*func)() = NULL;
2417 void *arg0 = NULL;
2419 ASSERT(vf != NULL);
2420 vf->fa_fnode--;
2421 vsop_find(vf, &func, int, &arg0, vop_cmp, femop_cmp);
2422 ASSERT(func != NULL);
2423 ASSERT(arg0 != NULL);
2424 return ((*func)(arg0, vp2, ct));
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;
2433 void *arg0 = NULL;
2435 ASSERT(vf != NULL);
2436 vf->fa_fnode--;
2437 vsop_find(vf, &func, int, &arg0, vop_frlock, femop_frlock);
2438 ASSERT(func != NULL);
2439 ASSERT(arg0 != NULL);
2440 return ((*func)(arg0, cmd, bfp, flag, offset, flk_cbp, cr, ct));
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;
2448 void *arg0 = NULL;
2450 ASSERT(vf != NULL);
2451 vf->fa_fnode--;
2452 vsop_find(vf, &func, int, &arg0, vop_space, femop_space);
2453 ASSERT(func != NULL);
2454 ASSERT(arg0 != NULL);
2455 return ((*func)(arg0, cmd, bfp, flag, offset, cr, ct));
2459 vnext_realvp(femarg_t *vf, vnode_t **vpp, caller_context_t *ct)
2461 int (*func)() = NULL;
2462 void *arg0 = NULL;
2464 ASSERT(vf != NULL);
2465 vf->fa_fnode--;
2466 vsop_find(vf, &func, int, &arg0, vop_realvp, femop_realvp);
2467 ASSERT(func != NULL);
2468 ASSERT(arg0 != NULL);
2469 return ((*func)(arg0, vpp, ct));
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;
2478 void *arg0 = NULL;
2480 ASSERT(vf != NULL);
2481 vf->fa_fnode--;
2482 vsop_find(vf, &func, int, &arg0, vop_getpage, femop_getpage);
2483 ASSERT(func != NULL);
2484 ASSERT(arg0 != NULL);
2485 return ((*func)(arg0, off, len, protp, plarr, plsz, seg, addr, rw,
2486 cr, ct));
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;
2494 void *arg0 = NULL;
2496 ASSERT(vf != NULL);
2497 vf->fa_fnode--;
2498 vsop_find(vf, &func, int, &arg0, vop_putpage, femop_putpage);
2499 ASSERT(func != NULL);
2500 ASSERT(arg0 != NULL);
2501 return ((*func)(arg0, off, len, flags, cr, ct));
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;
2510 void *arg0 = NULL;
2512 ASSERT(vf != NULL);
2513 vf->fa_fnode--;
2514 vsop_find(vf, &func, int, &arg0, vop_map, femop_map);
2515 ASSERT(func != NULL);
2516 ASSERT(arg0 != NULL);
2517 return ((*func)(arg0, off, as, addrp, len, prot, maxprot, flags,
2518 cr, ct));
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;
2527 void *arg0 = NULL;
2529 ASSERT(vf != NULL);
2530 vf->fa_fnode--;
2531 vsop_find(vf, &func, int, &arg0, vop_addmap, femop_addmap);
2532 ASSERT(func != NULL);
2533 ASSERT(arg0 != NULL);
2534 return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags,
2535 cr, ct));
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;
2544 void *arg0 = NULL;
2546 ASSERT(vf != NULL);
2547 vf->fa_fnode--;
2548 vsop_find(vf, &func, int, &arg0, vop_delmap, femop_delmap);
2549 ASSERT(func != NULL);
2550 ASSERT(arg0 != NULL);
2551 return ((*func)(arg0, off, as, addr, len, prot, maxprot, flags,
2552 cr, ct));
2556 vnext_poll(femarg_t *vf, short events, int anyyet, short *reventsp,
2557 struct pollhead **phpp, caller_context_t *ct)
2559 int (*func)() = NULL;
2560 void *arg0 = NULL;
2562 ASSERT(vf != NULL);
2563 vf->fa_fnode--;
2564 vsop_find(vf, &func, int, &arg0, vop_poll, femop_poll);
2565 ASSERT(func != NULL);
2566 ASSERT(arg0 != NULL);
2567 return ((*func)(arg0, events, anyyet, reventsp, phpp, ct));
2571 vnext_dump(femarg_t *vf, caddr_t addr, offset_t lbdn, offset_t dblks,
2572 caller_context_t *ct)
2574 int (*func)() = NULL;
2575 void *arg0 = NULL;
2577 ASSERT(vf != NULL);
2578 vf->fa_fnode--;
2579 vsop_find(vf, &func, int, &arg0, vop_dump, femop_dump);
2580 ASSERT(func != NULL);
2581 ASSERT(arg0 != NULL);
2582 return ((*func)(arg0, addr, lbdn, dblks, ct));
2586 vnext_pathconf(femarg_t *vf, int cmd, ulong_t *valp, cred_t *cr,
2587 caller_context_t *ct)
2589 int (*func)() = NULL;
2590 void *arg0 = NULL;
2592 ASSERT(vf != NULL);
2593 vf->fa_fnode--;
2594 vsop_find(vf, &func, int, &arg0, vop_pathconf, femop_pathconf);
2595 ASSERT(func != NULL);
2596 ASSERT(arg0 != NULL);
2597 return ((*func)(arg0, cmd, valp, cr, ct));
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;
2605 void *arg0 = NULL;
2607 ASSERT(vf != NULL);
2608 vf->fa_fnode--;
2609 vsop_find(vf, &func, int, &arg0, vop_pageio, femop_pageio);
2610 ASSERT(func != NULL);
2611 ASSERT(arg0 != NULL);
2612 return ((*func)(arg0, pp, io_off, io_len, flags, cr, ct));
2616 vnext_dumpctl(femarg_t *vf, int action, offset_t *blkp, caller_context_t *ct)
2618 int (*func)() = NULL;
2619 void *arg0 = NULL;
2621 ASSERT(vf != NULL);
2622 vf->fa_fnode--;
2623 vsop_find(vf, &func, int, &arg0, vop_dumpctl, femop_dumpctl);
2624 ASSERT(func != NULL);
2625 ASSERT(arg0 != NULL);
2626 return ((*func)(arg0, action, blkp, ct));
2629 void
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;
2634 void *arg0 = NULL;
2636 ASSERT(vf != NULL);
2637 vf->fa_fnode--;
2638 vsop_find(vf, &func, void, &arg0, vop_dispose, femop_dispose);
2639 ASSERT(func != NULL);
2640 ASSERT(arg0 != NULL);
2641 (*func)(arg0, pp, flag, dn, cr, ct);
2645 vnext_setsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr,
2646 caller_context_t *ct)
2648 int (*func)() = NULL;
2649 void *arg0 = NULL;
2651 ASSERT(vf != NULL);
2652 vf->fa_fnode--;
2653 vsop_find(vf, &func, int, &arg0, vop_setsecattr, femop_setsecattr);
2654 ASSERT(func != NULL);
2655 ASSERT(arg0 != NULL);
2656 return ((*func)(arg0, vsap, flag, cr, ct));
2660 vnext_getsecattr(femarg_t *vf, vsecattr_t *vsap, int flag, cred_t *cr,
2661 caller_context_t *ct)
2663 int (*func)() = NULL;
2664 void *arg0 = NULL;
2666 ASSERT(vf != NULL);
2667 vf->fa_fnode--;
2668 vsop_find(vf, &func, int, &arg0, vop_getsecattr, femop_getsecattr);
2669 ASSERT(func != NULL);
2670 ASSERT(arg0 != NULL);
2671 return ((*func)(arg0, vsap, flag, cr, ct));
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;
2679 void *arg0 = NULL;
2681 ASSERT(vf != NULL);
2682 vf->fa_fnode--;
2683 vsop_find(vf, &func, int, &arg0, vop_shrlock, femop_shrlock);
2684 ASSERT(func != NULL);
2685 ASSERT(arg0 != NULL);
2686 return ((*func)(arg0, cmd, shr, flag, cr, ct));
2690 vnext_vnevent(femarg_t *vf, vnevent_t vnevent, vnode_t *dvp, char *cname,
2691 caller_context_t *ct)
2693 int (*func)() = NULL;
2694 void *arg0 = NULL;
2696 ASSERT(vf != NULL);
2697 vf->fa_fnode--;
2698 vsop_find(vf, &func, int, &arg0, vop_vnevent, femop_vnevent);
2699 ASSERT(func != NULL);
2700 ASSERT(arg0 != NULL);
2701 return ((*func)(arg0, vnevent, dvp, cname, ct));
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;
2709 void *arg0 = NULL;
2711 ASSERT(vf != NULL);
2712 vf->fa_fnode--;
2713 vsop_find(vf, &func, int, &arg0, vop_reqzcbuf, femop_reqzcbuf);
2714 ASSERT(func != NULL);
2715 ASSERT(arg0 != NULL);
2716 return ((*func)(arg0, ioflag, xuiop, cr, ct));
2720 vnext_retzcbuf(femarg_t *vf, xuio_t *xuiop, cred_t *cr, caller_context_t *ct)
2722 int (*func)() = NULL;
2723 void *arg0 = NULL;
2725 ASSERT(vf != NULL);
2726 vf->fa_fnode--;
2727 vsop_find(vf, &func, int, &arg0, vop_retzcbuf, femop_retzcbuf);
2728 ASSERT(func != NULL);
2729 ASSERT(arg0 != NULL);
2730 return ((*func)(arg0, xuiop, cr, ct));
2734 vfsnext_mount(fsemarg_t *vf, vnode_t *mvp, struct mounta *uap, cred_t *cr)
2736 int (*func)() = NULL;
2737 void *arg0 = NULL;
2739 ASSERT(vf != NULL);
2740 vf->fa_fnode--;
2741 vfsop_find(vf, &func, int, &arg0, vfs_mount, fsemop_mount);
2742 ASSERT(func != NULL);
2743 ASSERT(arg0 != NULL);
2744 return ((*func)(arg0, mvp, uap, cr));
2748 vfsnext_unmount(fsemarg_t *vf, int flag, cred_t *cr)
2750 int (*func)() = NULL;
2751 void *arg0 = NULL;
2753 ASSERT(vf != NULL);
2754 vf->fa_fnode--;
2755 vfsop_find(vf, &func, int, &arg0, vfs_unmount, fsemop_unmount);
2756 ASSERT(func != NULL);
2757 ASSERT(arg0 != NULL);
2758 return ((*func)(arg0, flag, cr));
2762 vfsnext_root(fsemarg_t *vf, vnode_t **vpp)
2764 int (*func)() = NULL;
2765 void *arg0 = NULL;
2767 ASSERT(vf != NULL);
2768 vf->fa_fnode--;
2769 vfsop_find(vf, &func, int, &arg0, vfs_root, fsemop_root);
2770 ASSERT(func != NULL);
2771 ASSERT(arg0 != NULL);
2772 return ((*func)(arg0, vpp));
2776 vfsnext_statvfs(fsemarg_t *vf, statvfs64_t *sp)
2778 int (*func)() = NULL;
2779 void *arg0 = NULL;
2781 ASSERT(vf != NULL);
2782 vf->fa_fnode--;
2783 vfsop_find(vf, &func, int, &arg0, vfs_statvfs, fsemop_statvfs);
2784 ASSERT(func != NULL);
2785 ASSERT(arg0 != NULL);
2786 return ((*func)(arg0, sp));
2790 vfsnext_sync(fsemarg_t *vf, short flag, cred_t *cr)
2792 int (*func)() = NULL;
2793 void *arg0 = NULL;
2795 ASSERT(vf != NULL);
2796 vf->fa_fnode--;
2797 vfsop_find(vf, &func, int, &arg0, vfs_sync, fsemop_sync);
2798 ASSERT(func != NULL);
2799 ASSERT(arg0 != NULL);
2800 return ((*func)(arg0, flag, cr));
2804 vfsnext_vget(fsemarg_t *vf, vnode_t **vpp, fid_t *fidp)
2806 int (*func)() = NULL;
2807 void *arg0 = NULL;
2809 ASSERT(vf != NULL);
2810 vf->fa_fnode--;
2811 vfsop_find(vf, &func, int, &arg0, vfs_vget, fsemop_vget);
2812 ASSERT(func != NULL);
2813 ASSERT(arg0 != NULL);
2814 return ((*func)(arg0, vpp, fidp));
2818 vfsnext_mountroot(fsemarg_t *vf, enum whymountroot reason)
2820 int (*func)() = NULL;
2821 void *arg0 = NULL;
2823 ASSERT(vf != NULL);
2824 vf->fa_fnode--;
2825 vfsop_find(vf, &func, int, &arg0, vfs_mountroot, fsemop_mountroot);
2826 ASSERT(func != NULL);
2827 ASSERT(arg0 != NULL);
2828 return ((*func)(arg0, reason));
2831 void
2832 vfsnext_freevfs(fsemarg_t *vf)
2834 void (*func)() = NULL;
2835 void *arg0 = NULL;
2837 ASSERT(vf != NULL);
2838 vf->fa_fnode--;
2839 vfsop_find(vf, &func, void, &arg0, vfs_freevfs, fsemop_freevfs);
2840 ASSERT(func != NULL);
2841 ASSERT(arg0 != NULL);
2842 (*func)(arg0);
2846 vfsnext_vnstate(fsemarg_t *vf, vnode_t *vp, vntrans_t nstate)
2848 int (*func)() = NULL;
2849 void *arg0 = NULL;
2851 ASSERT(vf != NULL);
2852 vf->fa_fnode--;
2853 vfsop_find(vf, &func, int, &arg0, vfs_vnstate, fsemop_vnstate);
2854 ASSERT(func != NULL);
2855 ASSERT(arg0 != NULL);
2856 return ((*func)(arg0, vp, nstate));
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));
2877 head = *hp;
2879 return (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);
2900 sp->feml_refc = 1;
2901 sp->feml_ssize = numnodes;
2902 sp->feml_nodes[0] = FEM_GUARD(FEMTYPE_NULL);
2903 sp->feml_tos = 0;
2904 return (sp);
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;
2924 sp->feml_tos = 1;
2925 return (sp);
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.
2936 static void
2937 fem_dup_list(struct fem_list *orig, struct fem_list *clone)
2939 int i;
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);
2959 static int
2960 fem_push_node(
2961 struct fem_head **hp,
2962 void **baseops,
2963 int type,
2964 struct fem_node *nnode,
2965 femhow_t how)
2967 struct fem_head *hd;
2968 struct fem_list *list;
2969 void *oldops;
2970 int retry;
2971 int error = 0;
2972 int i;
2974 /* Validate the node */
2975 if ((nnode->fn_op.anon == NULL) || (nnode->fn_available == NULL)) {
2976 return (EINVAL);
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
2988 * onto it.
2990 do {
2991 retry = 1;
2992 list = fem_lock(hd);
2993 oldops = *baseops;
2995 if (list != NULL) {
2996 if (list->feml_tos+1 < list->feml_ssize) {
2997 retry = 0;
2998 } else {
2999 struct fem_list *olist = list;
3001 fem_addref(olist);
3002 fem_unlock(hd);
3003 list = femlist_create(olist->feml_ssize * 2);
3004 (void) fem_lock(hd);
3005 if (hd->femh_list == olist) {
3006 if (list->feml_ssize <=
3007 olist->feml_ssize) {
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.
3015 fem_release(list);
3016 fem_unlock(hd);
3017 } else {
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);
3027 retry = 0;
3029 } else {
3030 /* concurrent update, retry */
3031 fem_release(list);
3032 fem_unlock(hd);
3034 /* remove the reference we added above */
3035 fem_release(olist);
3037 } else {
3038 fem_unlock(hd);
3039 list = femlist_construct(oldops, type, NNODES_DEFAULT);
3040 (void) fem_lock(hd);
3041 if (hd->femh_list != NULL || *baseops != oldops) {
3042 /* concurrent update, retry */
3043 fem_release(list);
3044 fem_unlock(hd);
3045 } else {
3046 hd->femh_list = list;
3047 *baseops = FEM_HEAD(type);
3048 retry = 0;
3051 } while (retry);
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.
3061 if (how != FORCE) {
3062 /* Start at the top and work our way down */
3063 for (i = list->feml_tos; i > 0; i--) {
3064 void *fn_av = list->feml_nodes[i].fn_available;
3065 void *fn_op = list->feml_nodes[i].fn_op.anon;
3068 * OPARGUNIQ means that this node should not
3069 * be pushed on if a node with the same op/avail
3070 * combination exists. This situation returns
3071 * EBUSY.
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.
3077 switch (how) {
3079 case OPUNIQ:
3080 if (fn_op == nnode->fn_op.anon) {
3081 error = EBUSY;
3083 break;
3085 case OPARGUNIQ:
3086 if ((fn_op == nnode->fn_op.anon) &&
3087 (fn_av == nnode->fn_available)) {
3088 error = EBUSY;
3090 break;
3092 default:
3093 error = EINVAL; /* Unexpected value */
3094 break;
3097 if (error)
3098 break;
3102 if (error == 0) {
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;
3110 fem_unlock(hd);
3111 return (error);
3115 * Remove a node by copying the list above it down a notch.
3116 * If the list is busy, replace it with an idle one and work
3117 * upon it.
3118 * A node matches if the opset matches and the datap matches or is
3119 * null.
3122 static int
3123 remove_node(struct fem_list *sp, void **baseops, void *opset, void *datap)
3125 int i;
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)) {
3132 break;
3135 if (i == 0) {
3136 return (EINVAL);
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.
3145 if (fn->fn_av_rele)
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;
3154 return (0);
3157 static int
3158 fem_remove_node(struct fem_head *fh, void **baseops, void *opset, void *datap)
3160 struct fem_list *sp;
3161 int error = 0;
3162 int retry;
3164 if (fh == NULL) {
3165 return (EINVAL);
3168 do {
3169 retry = 0;
3170 if ((sp = fem_lock(fh)) == NULL) {
3171 fem_unlock(fh);
3172 error = EINVAL;
3173 } else if (sp->feml_refc == 1) {
3174 error = remove_node(sp, baseops, opset, datap);
3175 if (sp->feml_tos == 1) {
3177 * The top-of-stack was decremented by
3178 * remove_node(). If it got down to 1,
3179 * then the base ops were replaced and we
3180 * call fem_release() which will free the
3181 * fem_list.
3183 fem_release(sp);
3184 fh->femh_list = NULL;
3185 /* XXX - Do we need a membar_producer() call? */
3187 fem_unlock(fh);
3188 } else {
3189 /* busy - install a new one without this monitor */
3190 struct fem_list *nsp; /* New fem_list being cloned */
3192 fem_addref(sp);
3193 fem_unlock(fh);
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
3200 * it started with.
3202 fem_dup_list(sp, nsp);
3203 error = remove_node(nsp, baseops, opset, datap);
3204 if (error != 0) {
3205 fem_release(nsp);
3206 } else if (nsp->feml_tos == 1) {
3207 /* New list now empty, tear it down */
3208 fem_release(nsp);
3209 fh->femh_list = NULL;
3210 } else {
3211 fh->femh_list = nsp;
3213 (void) fem_delref(sp);
3214 } else {
3215 /* List changed while locked, try again... */
3216 fem_release(nsp);
3217 retry = 1;
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.
3224 if (error == 0)
3225 fem_release(sp);
3226 fem_unlock(fh);
3228 } while (retry);
3229 return (error);
3234 * perform operation on each element until one returns non zero
3236 static int
3237 fem_walk_list(
3238 struct fem_list *sp,
3239 int (*f)(struct fem_node *, void *, void *),
3240 void *mon,
3241 void *arg)
3243 int i;
3245 ASSERT(sp != NULL);
3246 for (i = sp->feml_tos; i > 0; i--) {
3247 if ((*f)(sp->feml_nodes+i, mon, arg) != 0) {
3248 break;
3251 return (i);
3255 * companion comparison functions.
3257 static int
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,
3269 fem_t **actual)
3271 int unused_ops = 0;
3272 int e;
3273 fem_t *newf;
3275 newf = fem_alloc();
3276 newf->name = name;
3277 newf->templ = templ;
3279 e = fs_build_vector(newf, &unused_ops, fem_opdef, templ);
3280 if (e != 0) {
3281 #ifdef DEBUG
3282 cmn_err(CE_WARN, "fem_create: error %d building vector", e);
3283 #endif
3284 fem_free(newf);
3285 } else {
3286 *actual = newf;
3288 return (e);
3292 fem_install(
3293 vnode_t *vp, /* Vnode on which monitor is being installed */
3294 fem_t *mon, /* Monitor operations being installed */
3295 void *arg, /* Opaque data used by monitor */
3296 femhow_t how, /* Installation control */
3297 void (*arg_hold)(void *), /* Hold routine for "arg" */
3298 void (*arg_rele)(void *)) /* Release routine for "arg" */
3300 int error;
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().
3311 if (arg_hold)
3312 (*arg_hold)(arg);
3314 error = fem_push_node(&vp->v_femhead, (void **)&vp->v_op, FEMTYPE_VNODE,
3315 &nnode, how);
3317 /* If there was an error then the monitor wasn't pushed */
3318 if (error && arg_rele)
3319 (*arg_rele)(arg);
3321 return (error);
3325 fem_is_installed(vnode_t *v, fem_t *mon, void *arg)
3327 int e;
3328 struct fem_list *fl;
3330 fl = fem_get(v->v_femhead);
3331 if (fl != NULL) {
3332 e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
3333 fem_release(fl);
3334 return (e);
3336 return (0);
3340 fem_uninstall(vnode_t *v, fem_t *mon, void *arg)
3342 int e;
3343 e = fem_remove_node(v->v_femhead, (void **)&v->v_op,
3344 (void *)mon, arg);
3345 return (e);
3348 void
3349 fem_setvnops(vnode_t *v, vnodeops_t *newops)
3351 vnodeops_t *r;
3353 ASSERT(v != NULL);
3354 ASSERT(newops != NULL);
3356 do {
3357 r = v->v_op;
3358 membar_consumer();
3359 if (v->v_femhead != NULL) {
3360 struct fem_list *fl;
3361 if ((fl = fem_lock(v->v_femhead)) != NULL) {
3362 fl->feml_nodes[1].fn_op.vnode = newops;
3363 fem_unlock(v->v_femhead);
3364 return;
3366 fem_unlock(v->v_femhead);
3368 } while (atomic_cas_ptr(&v->v_op, r, newops) != r);
3371 vnodeops_t *
3372 fem_getvnops(vnode_t *v)
3374 vnodeops_t *r;
3376 ASSERT(v != NULL);
3378 r = v->v_op;
3379 membar_consumer();
3380 if (v->v_femhead != NULL) {
3381 struct fem_list *fl;
3382 if ((fl = fem_lock(v->v_femhead)) != NULL) {
3383 r = fl->feml_nodes[1].fn_op.vnode;
3385 fem_unlock(v->v_femhead);
3387 return (r);
3392 * VFS interposition
3395 fsem_create(char *name, const struct fs_operation_def *templ,
3396 fsem_t **actual)
3398 int unused_ops = 0;
3399 int e;
3400 fsem_t *newv;
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);
3407 if (e != 0) {
3408 #ifdef DEBUG
3409 cmn_err(CE_WARN, "fsem_create: error %d building vector", e);
3410 #endif
3411 fsem_free(newv);
3412 } else {
3413 *actual = newv;
3415 return (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)
3428 return (0);
3430 fl = fem_get(v->vfs_femhead);
3431 if (fl != NULL) {
3432 int e;
3433 e = fem_walk_list(fl, fem_compare_mon, (void *)mon, arg);
3434 fem_release(fl);
3435 return (e);
3437 return (0);
3441 fsem_install(
3442 struct vfs *vfsp, /* VFS on which monitor is being installed */
3443 fsem_t *mon, /* Monitor operations being installed */
3444 void *arg, /* Opaque data used by monitor */
3445 femhow_t how, /* Installation control */
3446 void (*arg_hold)(void *), /* Hold routine for "arg" */
3447 void (*arg_rele)(void *)) /* Release routine for "arg" */
3449 int error;
3450 struct fem_node nnode;
3452 /* If this vfs hasn't been properly initialized, fail the install */
3453 if (vfsp->vfs_implp == NULL)
3454 return (EINVAL);
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().
3464 if (arg_hold)
3465 (*arg_hold)(arg);
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)
3472 (*arg_rele)(arg);
3474 return (error);
3478 fsem_uninstall(struct vfs *v, fsem_t *mon, void *arg)
3480 int e;
3482 if (v->vfs_implp == NULL)
3483 return (EINVAL);
3485 e = fem_remove_node(v->vfs_femhead, (void **)&v->vfs_op,
3486 (void *)mon, arg);
3487 return (e);
3490 void
3491 fsem_setvfsops(vfs_t *v, vfsops_t *newops)
3493 vfsops_t *r;
3495 ASSERT(v != NULL);
3496 ASSERT(newops != NULL);
3497 ASSERT(v->vfs_implp);
3499 do {
3500 r = v->vfs_op;
3501 membar_consumer();
3502 if (v->vfs_femhead != NULL) {
3503 struct fem_list *fl;
3504 if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
3505 fl->feml_nodes[1].fn_op.vfs = newops;
3506 fem_unlock(v->vfs_femhead);
3507 return;
3509 fem_unlock(v->vfs_femhead);
3511 } while (atomic_cas_ptr(&v->vfs_op, r, newops) != r);
3514 vfsops_t *
3515 fsem_getvfsops(vfs_t *v)
3517 vfsops_t *r;
3519 ASSERT(v != NULL);
3520 ASSERT(v->vfs_implp);
3522 r = v->vfs_op;
3523 membar_consumer();
3524 if (v->vfs_femhead != NULL) {
3525 struct fem_list *fl;
3526 if ((fl = fem_lock(v->vfs_femhead)) != NULL) {
3527 r = fl->feml_nodes[1].fn_op.vfs;
3529 fem_unlock(v->vfs_femhead);
3531 return (r);
3535 * Setup FEM.
3537 void
3538 fem_init()
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;
3552 fi->errf = fem_err;
3553 fi->guard.fn_available = (void *)&fi->guard;
3554 fi->guard.fn_av_hold = NULL;
3555 fi->guard.fn_av_rele = NULL;
3556 fi->guard.fn_op.anon = NULL;
3558 fi = femtype + FEMTYPE_VNODE;
3559 fi->errf = fem_err;
3560 fi->head.fn_available = NULL;
3561 fi->head.fn_av_hold = NULL;
3562 fi->head.fn_av_rele = NULL;
3563 (void) vn_make_ops("fem-head", fhead_vn_spec, &fi->head.fn_op.vnode);
3564 fi->guard.fn_available = (void *)&fi->guard;
3565 fi->guard.fn_av_hold = NULL;
3566 fi->guard.fn_av_rele = NULL;
3567 (void) fem_create("fem-guard", fem_guard_ops, &fi->guard.fn_op.fem);
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);
3584 fem_err()
3586 cmn_err(CE_PANIC, "fem/vnode operations corrupt");
3587 return (0);
3591 fsem_err()
3593 cmn_err(CE_PANIC, "fem/vfs operations corrupt");
3594 return (0);