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