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