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