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