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