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