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