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