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