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