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