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