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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/errno.h> 32 #include <sys/vnode.h> 33 #include <sys/vfs.h> 34 #include <sys/uio.h> 35 #include <sys/cred.h> 36 #include <sys/pathname.h> 37 #include <sys/debug.h> 38 #include <sys/fs/lofs_node.h> 39 #include <sys/fs/lofs_info.h> 40 #include <fs/fs_subr.h> 41 #include <vm/as.h> 42 #include <vm/seg.h> 43 44 #define IS_ZONEDEVFS(vp) \ 45 (vtoli((vp)->v_vfsp)->li_flag & LO_ZONEDEVFS) 46 47 /* 48 * These are the vnode ops routines which implement the vnode interface to 49 * the looped-back file system. These routines just take their parameters, 50 * and then calling the appropriate real vnode routine(s) to do the work. 51 */ 52 53 static int 54 lo_open(vnode_t **vpp, int flag, struct cred *cr) 55 { 56 vnode_t *vp = *vpp; 57 vnode_t *rvp; 58 vnode_t *oldvp; 59 int error; 60 61 #ifdef LODEBUG 62 lo_dprint(4, "lo_open vp %p cnt=%d realvp %p cnt=%d\n", 63 vp, vp->v_count, realvp(vp), realvp(vp)->v_count); 64 #endif 65 66 oldvp = vp; 67 vp = rvp = realvp(vp); 68 /* 69 * Need to hold new reference to vp since VOP_OPEN() may 70 * decide to release it. 71 */ 72 VN_HOLD(vp); 73 error = VOP_OPEN(&rvp, flag, cr); 74 75 if (!error && rvp != vp) { 76 /* 77 * the FS which we called should have released the 78 * new reference on vp 79 */ 80 *vpp = makelonode(rvp, vtoli(oldvp->v_vfsp), 0); 81 if (IS_DEVVP(*vpp)) { 82 vnode_t *svp; 83 84 svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 85 VN_RELE(*vpp); 86 if (svp == NULL) 87 error = ENOSYS; 88 else 89 *vpp = svp; 90 } 91 VN_RELE(oldvp); 92 } else { 93 ASSERT(rvp->v_count > 1); 94 VN_RELE(rvp); 95 } 96 97 return (error); 98 } 99 100 static int 101 lo_close( 102 vnode_t *vp, 103 int flag, 104 int count, 105 offset_t offset, 106 struct cred *cr) 107 { 108 #ifdef LODEBUG 109 lo_dprint(4, "lo_close vp %p realvp %p\n", vp, realvp(vp)); 110 #endif 111 vp = realvp(vp); 112 return (VOP_CLOSE(vp, flag, count, offset, cr)); 113 } 114 115 static int 116 lo_read(vnode_t *vp, struct uio *uiop, int ioflag, struct cred *cr, 117 caller_context_t *ct) 118 { 119 #ifdef LODEBUG 120 lo_dprint(4, "lo_read vp %p realvp %p\n", vp, realvp(vp)); 121 #endif 122 vp = realvp(vp); 123 return (VOP_READ(vp, uiop, ioflag, cr, ct)); 124 } 125 126 static int 127 lo_write(vnode_t *vp, struct uio *uiop, int ioflag, struct cred *cr, 128 caller_context_t *ct) 129 { 130 #ifdef LODEBUG 131 lo_dprint(4, "lo_write vp %p realvp %p\n", vp, realvp(vp)); 132 #endif 133 vp = realvp(vp); 134 return (VOP_WRITE(vp, uiop, ioflag, cr, ct)); 135 } 136 137 static int 138 lo_ioctl( 139 vnode_t *vp, 140 int cmd, 141 intptr_t arg, 142 int flag, 143 struct cred *cr, 144 int *rvalp) 145 { 146 #ifdef LODEBUG 147 lo_dprint(4, "lo_ioctl vp %p realvp %p\n", vp, realvp(vp)); 148 #endif 149 vp = realvp(vp); 150 return (VOP_IOCTL(vp, cmd, arg, flag, cr, rvalp)); 151 } 152 153 static int 154 lo_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr) 155 { 156 vp = realvp(vp); 157 return (VOP_SETFL(vp, oflags, nflags, cr)); 158 } 159 160 static int 161 lo_getattr( 162 vnode_t *vp, 163 struct vattr *vap, 164 int flags, 165 struct cred *cr) 166 { 167 int error; 168 169 #ifdef LODEBUG 170 lo_dprint(4, "lo_getattr vp %p realvp %p\n", vp, realvp(vp)); 171 #endif 172 if (error = VOP_GETATTR(realvp(vp), vap, flags, cr)) 173 return (error); 174 175 /* 176 * In zonedevfs mode, we pull a nasty trick; we make sure that 177 * the dev_t does *not* reflect the underlying device, so that 178 * no renames can occur to or from the /dev hierarchy. 179 */ 180 if (IS_ZONEDEVFS(vp)) { 181 vap->va_fsid = expldev(vp->v_vfsp->vfs_fsid.val[0]); 182 } 183 184 return (0); 185 } 186 187 static int 188 lo_setattr( 189 vnode_t *vp, 190 struct vattr *vap, 191 int flags, 192 struct cred *cr, 193 caller_context_t *ct) 194 { 195 #ifdef LODEBUG 196 lo_dprint(4, "lo_setattr vp %p realvp %p\n", vp, realvp(vp)); 197 #endif 198 if (IS_ZONEDEVFS(vp) && !IS_DEVVP(vp)) { 199 return (EACCES); 200 } 201 vp = realvp(vp); 202 return (VOP_SETATTR(vp, vap, flags, cr, ct)); 203 } 204 205 static int 206 lo_access(vnode_t *vp, int mode, int flags, struct cred *cr) 207 { 208 #ifdef LODEBUG 209 lo_dprint(4, "lo_access vp %p realvp %p\n", vp, realvp(vp)); 210 #endif 211 if (mode & VWRITE) { 212 if (vp->v_type == VREG && vn_is_readonly(vp)) 213 return (EROFS); 214 if (IS_ZONEDEVFS(vp) && !IS_DEVVP(vp)) 215 return (EACCES); 216 } 217 vp = realvp(vp); 218 return (VOP_ACCESS(vp, mode, flags, cr)); 219 } 220 221 static int 222 lo_fsync(vnode_t *vp, int syncflag, struct cred *cr) 223 { 224 #ifdef LODEBUG 225 lo_dprint(4, "lo_fsync vp %p realvp %p\n", vp, realvp(vp)); 226 #endif 227 vp = realvp(vp); 228 return (VOP_FSYNC(vp, syncflag, cr)); 229 } 230 231 /*ARGSUSED*/ 232 static void 233 lo_inactive(vnode_t *vp, struct cred *cr) 234 { 235 #ifdef LODEBUG 236 lo_dprint(4, "lo_inactive %p, realvp %p\n", vp, realvp(vp)); 237 #endif 238 freelonode(vtol(vp)); 239 } 240 241 /* ARGSUSED */ 242 static int 243 lo_fid(vnode_t *vp, struct fid *fidp) 244 { 245 #ifdef LODEBUG 246 lo_dprint(4, "lo_fid %p, realvp %p\n", vp, realvp(vp)); 247 #endif 248 vp = realvp(vp); 249 return (VOP_FID(vp, fidp)); 250 } 251 252 /* 253 * Given a vnode of lofs type, lookup nm name and 254 * return a shadow vnode (of lofs type) of the 255 * real vnode found. 256 * 257 * Due to the nature of lofs, there is a potential 258 * looping in path traversal. 259 * 260 * starting from the mount point of an lofs; 261 * a loop is defined to be a traversal path 262 * where the mount point or the real vnode of 263 * the root of this lofs is encountered twice. 264 * Once at the start of traversal and second 265 * when the looping is found. 266 * 267 * When a loop is encountered, a shadow of the 268 * covered vnode is returned to stop the looping. 269 * 270 * This normally works, but with the advent of 271 * the new automounter, returning the shadow of the 272 * covered vnode (autonode, in this case) does not 273 * stop the loop. Because further lookup on this 274 * lonode will cause the autonode to call lo_lookup() 275 * on the lonode covering it. 276 * 277 * example "/net/jurassic/net/jurassic" is a loop. 278 * returning the shadow of the autonode corresponding to 279 * "/net/jurassic/net/jurassic" will not terminate the 280 * loop. To solve this problem we allow the loop to go 281 * through one more level component lookup. Whichever 282 * directory is then looked up in "/net/jurassic/net/jurassic" 283 * the vnode returned is the vnode covered by the autonode 284 * "net" and this will terminate the loop. 285 * 286 * Lookup for dot dot has to be dealt with separately. 287 * It will be nice to have a "one size fits all" kind 288 * of solution, so that we don't have so many ifs statement 289 * in the lo_lookup() to handle dotdot. But, since 290 * there are so many special cases to handle different 291 * kinds looping above, we need special codes to handle 292 * dotdot lookup as well. 293 */ 294 static int 295 lo_lookup( 296 vnode_t *dvp, 297 char *nm, 298 vnode_t **vpp, 299 struct pathname *pnp, 300 int flags, 301 vnode_t *rdir, 302 struct cred *cr) 303 { 304 vnode_t *vp = NULL, *tvp = NULL, *nonlovp; 305 int error, is_indirectloop; 306 vnode_t *realdvp = realvp(dvp); 307 struct loinfo *li = vtoli(dvp->v_vfsp); 308 int looping = 0; 309 int autoloop = 0; 310 int doingdotdot = 0; 311 int nosub = 0; 312 int mkflag = 0; 313 314 /* 315 * If name is empty and no XATTR flags are set, then return 316 * dvp (empty name == lookup "."). If an XATTR flag is set 317 * then we need to call VOP_LOOKUP to get the xattr dir. 318 */ 319 if (nm[0] == '\0' && ! (flags & (CREATE_XATTR_DIR|LOOKUP_XATTR))) { 320 VN_HOLD(dvp); 321 *vpp = dvp; 322 return (0); 323 } 324 325 if (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0') { 326 doingdotdot++; 327 /* 328 * Handle ".." out of mounted filesystem 329 */ 330 while ((realdvp->v_flag & VROOT) && realdvp != rootdir) { 331 realdvp = realdvp->v_vfsp->vfs_vnodecovered; 332 ASSERT(realdvp != NULL); 333 } 334 } 335 336 *vpp = NULL; /* default(error) case */ 337 338 /* 339 * Do the normal lookup 340 */ 341 if (error = VOP_LOOKUP(realdvp, nm, &vp, pnp, flags, rdir, cr)) { 342 vp = NULL; 343 goto out; 344 } 345 346 /* 347 * We do this check here to avoid returning a stale file handle to the 348 * caller. 349 */ 350 if (nm[0] == '.' && nm[1] == '\0') { 351 ASSERT(vp == realdvp); 352 VN_HOLD(dvp); 353 VN_RELE(vp); 354 *vpp = dvp; 355 return (0); 356 } 357 358 if (doingdotdot) { 359 if ((vtol(dvp))->lo_looping & LO_LOOPING) { 360 vfs_t *vfsp; 361 362 error = vn_vfswlock_wait(realdvp); 363 if (error) 364 goto out; 365 vfsp = vn_mountedvfs(realdvp); 366 /* 367 * In the standard case if the looping flag is set and 368 * performing dotdot we would be returning from a 369 * covered vnode, implying vfsp could not be null. The 370 * exceptions being if we have looping and overlay 371 * mounts or looping and covered file systems. 372 */ 373 if (vfsp == NULL) { 374 /* 375 * Overlay mount or covered file system, 376 * so just make the shadow node. 377 */ 378 vn_vfsunlock(realdvp); 379 *vpp = makelonode(vp, li, 0); 380 (vtol(*vpp))->lo_looping |= LO_LOOPING; 381 return (0); 382 } 383 /* 384 * When looping get the actual found vnode 385 * instead of the vnode covered. 386 * Here we have to hold the lock for realdvp 387 * since an unmount during the traversal to the 388 * root vnode would turn *vfsp into garbage 389 * which would be fatal. 390 */ 391 vfs_lock_wait(vfsp); 392 vn_vfsunlock(realdvp); 393 394 error = VFS_ROOT(vfsp, &tvp); 395 396 vfs_unlock(vfsp); 397 if (error) 398 goto out; 399 if ((tvp == li->li_rootvp) && (vp == realvp(tvp))) { 400 /* 401 * we're back at the real vnode 402 * of the rootvp 403 * 404 * return the rootvp 405 * Ex: /mnt/mnt/.. 406 * where / has been lofs-mounted 407 * onto /mnt. Return the lofs 408 * node mounted at /mnt. 409 */ 410 *vpp = tvp; 411 VN_RELE(vp); 412 return (0); 413 } else { 414 /* 415 * We are returning from a covered 416 * node whose vfs_mountedhere is 417 * not pointing to vfs of the current 418 * root vnode. 419 * This is a condn where in we 420 * returned a covered node say Zc 421 * but Zc is not the cover of current 422 * root. 423 * i.e.., if X is the root vnode 424 * lookup(Zc,"..") is taking us to 425 * X. 426 * Ex: /net/X/net/X/Y 427 * 428 * If LO_AUTOLOOP (autofs/lofs looping detected) 429 * has been set then we are encountering the 430 * cover of Y (Y being any directory vnode 431 * under /net/X/net/X/). 432 * When performing a dotdot set the 433 * returned vp to the vnode covered 434 * by the mounted lofs, ie /net/X/net/X 435 */ 436 VN_RELE(tvp); 437 if ((vtol(dvp))->lo_looping & LO_AUTOLOOP) { 438 VN_RELE(vp); 439 vp = li->li_rootvp; 440 vp = vp->v_vfsp->vfs_vnodecovered; 441 VN_HOLD(vp); 442 *vpp = makelonode(vp, li, 0); 443 (vtol(*vpp))->lo_looping |= LO_LOOPING; 444 return (0); 445 } 446 } 447 } else { 448 /* 449 * No frills just make the shadow node. 450 */ 451 *vpp = makelonode(vp, li, 0); 452 return (0); 453 } 454 } 455 456 nosub = (vtoli(dvp->v_vfsp)->li_flag & LO_NOSUB); 457 458 /* 459 * If this vnode is mounted on, then we 460 * traverse to the vnode which is the root of 461 * the mounted file system. 462 */ 463 if (!nosub && (error = traverse(&vp))) 464 goto out; 465 466 /* 467 * Make a lnode for the real vnode. 468 */ 469 if (vp->v_type != VDIR || nosub) { 470 *vpp = makelonode(vp, li, 0); 471 if (IS_DEVVP(*vpp)) { 472 vnode_t *svp; 473 474 svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 475 VN_RELE(*vpp); 476 if (svp == NULL) 477 error = ENOSYS; 478 else 479 *vpp = svp; 480 } 481 return (error); 482 } 483 484 /* 485 * if the found vnode (vp) is not of type lofs 486 * then we're just going to make a shadow of that 487 * vp and get out. 488 * 489 * If the found vnode (vp) is of lofs type, and 490 * we're not doing dotdot, check if we are 491 * looping. 492 */ 493 if (!doingdotdot && vfs_matchops(vp->v_vfsp, lo_vfsops)) { 494 /* 495 * Check if we're looping, i.e. 496 * vp equals the root vp of the lofs, directly 497 * or indirectly, return the covered node. 498 */ 499 500 if (!((vtol(dvp))->lo_looping & LO_LOOPING)) { 501 if (vp == li->li_rootvp) { 502 /* 503 * Direct looping condn. 504 * Ex:- X is / mounted directory so lookup of 505 * /X/X is a direct looping condn. 506 */ 507 tvp = vp; 508 vp = vp->v_vfsp->vfs_vnodecovered; 509 VN_HOLD(vp); 510 VN_RELE(tvp); 511 looping++; 512 } else { 513 /* 514 * Indirect looping can be defined as 515 * real lookup returning rootvp of the current 516 * tree in any level of recursion. 517 * 518 * This check is useful if there are multiple 519 * levels of lofs indirections. Suppose vnode X 520 * in the current lookup has as its real vnode 521 * another lofs node. Y = realvp(X) Y should be 522 * a lofs node for the check to continue or Y 523 * is not the rootvp of X. 524 * Ex:- say X and Y are two vnodes 525 * say real(Y) is X and real(X) is Z 526 * parent vnode for X and Y is Z 527 * lookup(Y,"path") say we are looking for Y 528 * again under Y and we have to return Yc. 529 * but the lookup of Y under Y doesnot return 530 * Y the root vnode again here is why. 531 * 1. lookup(Y,"path of Y") will go to 532 * 2. lookup(real(Y),"path of Y") and then to 533 * 3. lookup(real(X),"path of Y"). 534 * and now what lookup level 1 sees is the 535 * outcome of 2 but the vnode Y is due to 536 * lookup(Z,"path of Y") so we have to skip 537 * intermediate levels to find if in any level 538 * there is a looping. 539 */ 540 is_indirectloop = 0; 541 nonlovp = vp; 542 while ( 543 vfs_matchops(nonlovp->v_vfsp, lo_vfsops) && 544 !(is_indirectloop)) { 545 if (li->li_rootvp == nonlovp) { 546 is_indirectloop++; 547 break; 548 } 549 nonlovp = realvp(nonlovp); 550 } 551 552 if (is_indirectloop) { 553 VN_RELE(vp); 554 vp = nonlovp; 555 vp = vp->v_vfsp->vfs_vnodecovered; 556 VN_HOLD(vp); 557 looping++; 558 } 559 } 560 } else { 561 /* 562 * come here only because of the interaction between 563 * the autofs and lofs. 564 * 565 * Lookup of "/net/X/net/X" will return a shadow of 566 * an autonode X_a which we call X_l. 567 * 568 * Lookup of anything under X_l, will trigger a call to 569 * auto_lookup(X_a,nm) which will eventually call 570 * lo_lookup(X_lr,nm) where X_lr is the root vnode of 571 * the current lofs. 572 * 573 * We come here only when we are called with X_l as dvp 574 * and look for something underneath. 575 * 576 * Now that an autofs/lofs looping condition has been 577 * identified any directory vnode contained within 578 * dvp will be set to the vnode covered by the 579 * mounted autofs. Thus all directories within dvp 580 * will appear empty hence teminating the looping. 581 * The LO_AUTOLOOP flag is set on the returned lonode 582 * to indicate the termination of the autofs/lofs 583 * looping. This is required for the correct behaviour 584 * when performing a dotdot. 585 */ 586 realdvp = realvp(dvp); 587 while (vfs_matchops(realdvp->v_vfsp, lo_vfsops)) { 588 realdvp = realvp(realdvp); 589 } 590 591 error = VFS_ROOT(realdvp->v_vfsp, &tvp); 592 if (error) 593 goto out; 594 /* 595 * tvp now contains the rootvp of the vfs of the 596 * real vnode of dvp. The directory vnode vp is set 597 * to the covered vnode to terminate looping. No 598 * distinction is made between any vp as all directory 599 * vnodes contained in dvp are returned as the covered 600 * vnode. 601 */ 602 VN_RELE(vp); 603 vp = tvp; /* this is an autonode */ 604 605 /* 606 * Need to find the covered vnode 607 */ 608 vp = vp->v_vfsp->vfs_vnodecovered; 609 ASSERT(vp); 610 VN_HOLD(vp); 611 VN_RELE(tvp); 612 /* 613 * Force the creation of a new lnode even if the hash 614 * table contains a lnode that references this vnode. 615 */ 616 mkflag = LOF_FORCE; 617 autoloop++; 618 } 619 } 620 *vpp = makelonode(vp, li, mkflag); 621 622 if ((looping) || 623 (((vtol(dvp))->lo_looping & LO_LOOPING) && !doingdotdot)) { 624 (vtol(*vpp))->lo_looping |= LO_LOOPING; 625 } 626 627 if (autoloop) { 628 (vtol(*vpp))->lo_looping |= LO_AUTOLOOP; 629 } 630 631 out: 632 if (error != 0 && vp != NULL) 633 VN_RELE(vp); 634 #ifdef LODEBUG 635 lo_dprint(4, 636 "lo_lookup dvp %x realdvp %x nm '%s' newvp %x real vp %x error %d\n", 637 dvp, realvp(dvp), nm, *vpp, vp, error); 638 #endif 639 return (error); 640 } 641 642 /*ARGSUSED*/ 643 static int 644 lo_create( 645 vnode_t *dvp, 646 char *nm, 647 struct vattr *va, 648 enum vcexcl exclusive, 649 int mode, 650 vnode_t **vpp, 651 struct cred *cr, 652 int flag) 653 { 654 int error; 655 vnode_t *vp = NULL; 656 657 #ifdef LODEBUG 658 lo_dprint(4, "lo_create vp %p realvp %p\n", dvp, realvp(dvp)); 659 #endif 660 if (*nm == '\0') { 661 ASSERT(vpp && dvp == *vpp); 662 vp = realvp(*vpp); 663 } 664 665 if (IS_ZONEDEVFS(dvp)) { 666 /* Is this truly a create? If so, fail */ 667 if (*vpp == NULL) 668 return (EACCES); 669 670 /* Is this an open of a non-special for writing? If so, fail */ 671 if (*vpp != NULL && (mode & VWRITE) && !IS_DEVVP(*vpp)) 672 return (EACCES); 673 } 674 675 error = VOP_CREATE(realvp(dvp), nm, va, exclusive, mode, &vp, cr, flag); 676 if (!error) { 677 *vpp = makelonode(vp, vtoli(dvp->v_vfsp), 0); 678 if (IS_DEVVP(*vpp)) { 679 vnode_t *svp; 680 681 svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 682 VN_RELE(*vpp); 683 if (svp == NULL) 684 error = ENOSYS; 685 else 686 *vpp = svp; 687 } 688 } 689 return (error); 690 } 691 692 static int 693 lo_remove(vnode_t *dvp, char *nm, struct cred *cr) 694 { 695 #ifdef LODEBUG 696 lo_dprint(4, "lo_remove vp %p realvp %p\n", dvp, realvp(dvp)); 697 #endif 698 if (IS_ZONEDEVFS(dvp)) 699 return (EACCES); 700 dvp = realvp(dvp); 701 return (VOP_REMOVE(dvp, nm, cr)); 702 } 703 704 static int 705 lo_link(vnode_t *tdvp, vnode_t *vp, char *tnm, struct cred *cr) 706 { 707 #ifdef LODEBUG 708 lo_dprint(4, "lo_link vp %p realvp %p\n", vp, realvp(vp)); 709 #endif 710 while (vn_matchops(vp, lo_vnodeops)) { 711 if (IS_ZONEDEVFS(vp)) 712 return (EACCES); 713 vp = realvp(vp); 714 } 715 while (vn_matchops(tdvp, lo_vnodeops)) { 716 if (IS_ZONEDEVFS(tdvp)) 717 return (EACCES); 718 tdvp = realvp(tdvp); 719 } 720 if (vp->v_vfsp != tdvp->v_vfsp) 721 return (EXDEV); 722 return (VOP_LINK(tdvp, vp, tnm, cr)); 723 } 724 725 static int 726 lo_rename( 727 vnode_t *odvp, 728 char *onm, 729 vnode_t *ndvp, 730 char *nnm, 731 struct cred *cr) 732 { 733 vnode_t *tnvp; 734 735 #ifdef LODEBUG 736 lo_dprint(4, "lo_rename vp %p realvp %p\n", odvp, realvp(odvp)); 737 #endif 738 if (IS_ZONEDEVFS(odvp)) 739 return (EACCES); 740 /* 741 * We need to make sure we're not trying to remove a mount point for a 742 * filesystem mounted on top of lofs, which only we know about. 743 */ 744 if (vn_matchops(ndvp, lo_vnodeops)) /* Not our problem. */ 745 goto rename; 746 if (VOP_LOOKUP(ndvp, nnm, &tnvp, NULL, 0, NULL, cr) != 0) 747 goto rename; 748 if (tnvp->v_type != VDIR) { 749 VN_RELE(tnvp); 750 goto rename; 751 } 752 if (vn_mountedvfs(tnvp)) { 753 VN_RELE(tnvp); 754 return (EBUSY); 755 } 756 VN_RELE(tnvp); 757 rename: 758 /* 759 * Since the case we're dealing with above can happen at any layer in 760 * the stack of lofs filesystems, we need to recurse down the stack, 761 * checking to see if there are any instances of a filesystem mounted on 762 * top of lofs. In order to keep on using the lofs version of 763 * VOP_RENAME(), we make sure that while the target directory is of type 764 * lofs, the source directory (the one used for getting the fs-specific 765 * version of VOP_RENAME()) is also of type lofs. 766 */ 767 if (vn_matchops(ndvp, lo_vnodeops)) { 768 if (IS_ZONEDEVFS(ndvp)) 769 return (EACCES); 770 ndvp = realvp(ndvp); /* Check the next layer */ 771 } else { 772 /* 773 * We can go fast here 774 */ 775 while (vn_matchops(odvp, lo_vnodeops)) { 776 if (IS_ZONEDEVFS(odvp)) 777 return (EACCES); 778 odvp = realvp(odvp); 779 } 780 if (odvp->v_vfsp != ndvp->v_vfsp) 781 return (EXDEV); 782 } 783 return (VOP_RENAME(odvp, onm, ndvp, nnm, cr)); 784 } 785 786 static int 787 lo_mkdir( 788 vnode_t *dvp, 789 char *nm, 790 struct vattr *va, 791 vnode_t **vpp, 792 struct cred *cr) 793 { 794 int error; 795 796 #ifdef LODEBUG 797 lo_dprint(4, "lo_mkdir vp %p realvp %p\n", dvp, realvp(dvp)); 798 #endif 799 if (IS_ZONEDEVFS(dvp)) 800 return (EACCES); 801 error = VOP_MKDIR(realvp(dvp), nm, va, vpp, cr); 802 if (!error) 803 *vpp = makelonode(*vpp, vtoli(dvp->v_vfsp), 0); 804 return (error); 805 } 806 807 static int 808 lo_realvp(vnode_t *vp, vnode_t **vpp) 809 { 810 #ifdef LODEBUG 811 lo_dprint(4, "lo_realvp %p\n", vp); 812 #endif 813 while (vn_matchops(vp, lo_vnodeops)) 814 vp = realvp(vp); 815 816 if (VOP_REALVP(vp, vpp) != 0) 817 *vpp = vp; 818 return (0); 819 } 820 821 static int 822 lo_rmdir( 823 vnode_t *dvp, 824 char *nm, 825 vnode_t *cdir, 826 struct cred *cr) 827 { 828 vnode_t *rvp = cdir; 829 830 #ifdef LODEBUG 831 lo_dprint(4, "lo_rmdir vp %p realvp %p\n", dvp, realvp(dvp)); 832 #endif 833 if (IS_ZONEDEVFS(dvp)) 834 return (EACCES); 835 /* if cdir is lofs vnode ptr get its real vnode ptr */ 836 if (vn_matchops(dvp, vn_getops(rvp))) 837 (void) lo_realvp(cdir, &rvp); 838 dvp = realvp(dvp); 839 return (VOP_RMDIR(dvp, nm, rvp, cr)); 840 } 841 842 static int 843 lo_symlink( 844 vnode_t *dvp, 845 char *lnm, 846 struct vattr *tva, 847 char *tnm, 848 struct cred *cr) 849 { 850 #ifdef LODEBUG 851 lo_dprint(4, "lo_symlink vp %p realvp %p\n", dvp, realvp(dvp)); 852 #endif 853 if (IS_ZONEDEVFS(dvp)) 854 return (EACCES); 855 dvp = realvp(dvp); 856 return (VOP_SYMLINK(dvp, lnm, tva, tnm, cr)); 857 } 858 859 static int 860 lo_readlink(vnode_t *vp, struct uio *uiop, struct cred *cr) 861 { 862 vp = realvp(vp); 863 return (VOP_READLINK(vp, uiop, cr)); 864 } 865 866 static int 867 lo_readdir(vnode_t *vp, struct uio *uiop, struct cred *cr, int *eofp) 868 { 869 #ifdef LODEBUG 870 lo_dprint(4, "lo_readdir vp %p realvp %p\n", vp, realvp(vp)); 871 #endif 872 vp = realvp(vp); 873 return (VOP_READDIR(vp, uiop, cr, eofp)); 874 } 875 876 static int 877 lo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct) 878 { 879 vp = realvp(vp); 880 return (VOP_RWLOCK(vp, write_lock, ct)); 881 } 882 883 static void 884 lo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct) 885 { 886 vp = realvp(vp); 887 VOP_RWUNLOCK(vp, write_lock, ct); 888 } 889 890 static int 891 lo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp) 892 { 893 vp = realvp(vp); 894 return (VOP_SEEK(vp, ooff, noffp)); 895 } 896 897 static int 898 lo_cmp(vnode_t *vp1, vnode_t *vp2) 899 { 900 while (vn_matchops(vp1, lo_vnodeops)) 901 vp1 = realvp(vp1); 902 while (vn_matchops(vp2, lo_vnodeops)) 903 vp2 = realvp(vp2); 904 return (VOP_CMP(vp1, vp2)); 905 } 906 907 static int 908 lo_frlock( 909 vnode_t *vp, 910 int cmd, 911 struct flock64 *bfp, 912 int flag, 913 offset_t offset, 914 struct flk_callback *flk_cbp, 915 cred_t *cr) 916 { 917 vp = realvp(vp); 918 return (VOP_FRLOCK(vp, cmd, bfp, flag, offset, flk_cbp, cr)); 919 } 920 921 static int 922 lo_space( 923 vnode_t *vp, 924 int cmd, 925 struct flock64 *bfp, 926 int flag, 927 offset_t offset, 928 struct cred *cr, 929 caller_context_t *ct) 930 { 931 vp = realvp(vp); 932 return (VOP_SPACE(vp, cmd, bfp, flag, offset, cr, ct)); 933 } 934 935 static int 936 lo_getpage( 937 vnode_t *vp, 938 offset_t off, 939 size_t len, 940 uint_t *prot, 941 struct page *parr[], 942 size_t psz, 943 struct seg *seg, 944 caddr_t addr, 945 enum seg_rw rw, 946 struct cred *cr) 947 { 948 vp = realvp(vp); 949 return (VOP_GETPAGE(vp, off, len, prot, parr, psz, seg, addr, rw, cr)); 950 } 951 952 static int 953 lo_putpage(vnode_t *vp, offset_t off, size_t len, int flags, struct cred *cr) 954 { 955 vp = realvp(vp); 956 return (VOP_PUTPAGE(vp, off, len, flags, cr)); 957 } 958 959 static int 960 lo_map( 961 vnode_t *vp, 962 offset_t off, 963 struct as *as, 964 caddr_t *addrp, 965 size_t len, 966 uchar_t prot, 967 uchar_t maxprot, 968 uint_t flags, 969 struct cred *cr) 970 { 971 vp = realvp(vp); 972 return (VOP_MAP(vp, off, as, addrp, len, prot, maxprot, flags, cr)); 973 } 974 975 static int 976 lo_addmap( 977 vnode_t *vp, 978 offset_t off, 979 struct as *as, 980 caddr_t addr, 981 size_t len, 982 uchar_t prot, 983 uchar_t maxprot, 984 uint_t flags, 985 struct cred *cr) 986 { 987 vp = realvp(vp); 988 return (VOP_ADDMAP(vp, off, as, addr, len, prot, maxprot, flags, cr)); 989 } 990 991 static int 992 lo_delmap( 993 vnode_t *vp, 994 offset_t off, 995 struct as *as, 996 caddr_t addr, 997 size_t len, 998 uint_t prot, 999 uint_t maxprot, 1000 uint_t flags, 1001 struct cred *cr) 1002 { 1003 vp = realvp(vp); 1004 return (VOP_DELMAP(vp, off, as, addr, len, prot, maxprot, flags, cr)); 1005 } 1006 1007 static int 1008 lo_poll( 1009 vnode_t *vp, 1010 short events, 1011 int anyyet, 1012 short *reventsp, 1013 struct pollhead **phpp) 1014 { 1015 vp = realvp(vp); 1016 return (VOP_POLL(vp, events, anyyet, reventsp, phpp)); 1017 } 1018 1019 static int 1020 lo_dump(vnode_t *vp, caddr_t addr, int bn, int count) 1021 { 1022 vp = realvp(vp); 1023 return (VOP_DUMP(vp, addr, bn, count)); 1024 } 1025 1026 static int 1027 lo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, struct cred *cr) 1028 { 1029 vp = realvp(vp); 1030 return (VOP_PATHCONF(vp, cmd, valp, cr)); 1031 } 1032 1033 static int 1034 lo_pageio( 1035 vnode_t *vp, 1036 struct page *pp, 1037 u_offset_t io_off, 1038 size_t io_len, 1039 int flags, 1040 cred_t *cr) 1041 { 1042 vp = realvp(vp); 1043 return (VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr)); 1044 } 1045 1046 static void 1047 lo_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr) 1048 { 1049 vp = realvp(vp); 1050 if (vp != NULL && vp != &kvp) 1051 VOP_DISPOSE(vp, pp, fl, dn, cr); 1052 } 1053 1054 static int 1055 lo_setsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr) 1056 { 1057 if (vn_is_readonly(vp)) 1058 return (EROFS); 1059 vp = realvp(vp); 1060 return (VOP_SETSECATTR(vp, secattr, flags, cr)); 1061 } 1062 1063 static int 1064 lo_getsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr) 1065 { 1066 vp = realvp(vp); 1067 return (VOP_GETSECATTR(vp, secattr, flags, cr)); 1068 } 1069 1070 static int 1071 lo_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr) 1072 { 1073 vp = realvp(vp); 1074 return (VOP_SHRLOCK(vp, cmd, shr, flag, cr)); 1075 } 1076 1077 /* 1078 * Loopback vnode operations vector. 1079 */ 1080 1081 struct vnodeops *lo_vnodeops; 1082 1083 const fs_operation_def_t lo_vnodeops_template[] = { 1084 VOPNAME_OPEN, lo_open, 1085 VOPNAME_CLOSE, lo_close, 1086 VOPNAME_READ, lo_read, 1087 VOPNAME_WRITE, lo_write, 1088 VOPNAME_IOCTL, lo_ioctl, 1089 VOPNAME_SETFL, lo_setfl, 1090 VOPNAME_GETATTR, lo_getattr, 1091 VOPNAME_SETATTR, lo_setattr, 1092 VOPNAME_ACCESS, lo_access, 1093 VOPNAME_LOOKUP, lo_lookup, 1094 VOPNAME_CREATE, lo_create, 1095 VOPNAME_REMOVE, lo_remove, 1096 VOPNAME_LINK, lo_link, 1097 VOPNAME_RENAME, lo_rename, 1098 VOPNAME_MKDIR, lo_mkdir, 1099 VOPNAME_RMDIR, lo_rmdir, 1100 VOPNAME_READDIR, lo_readdir, 1101 VOPNAME_SYMLINK, lo_symlink, 1102 VOPNAME_READLINK, lo_readlink, 1103 VOPNAME_FSYNC, lo_fsync, 1104 VOPNAME_INACTIVE, (fs_generic_func_p) lo_inactive, 1105 VOPNAME_FID, lo_fid, 1106 VOPNAME_RWLOCK, lo_rwlock, 1107 VOPNAME_RWUNLOCK, (fs_generic_func_p) lo_rwunlock, 1108 VOPNAME_SEEK, lo_seek, 1109 VOPNAME_CMP, lo_cmp, 1110 VOPNAME_FRLOCK, lo_frlock, 1111 VOPNAME_SPACE, lo_space, 1112 VOPNAME_REALVP, lo_realvp, 1113 VOPNAME_GETPAGE, lo_getpage, 1114 VOPNAME_PUTPAGE, lo_putpage, 1115 VOPNAME_MAP, (fs_generic_func_p) lo_map, 1116 VOPNAME_ADDMAP, (fs_generic_func_p) lo_addmap, 1117 VOPNAME_DELMAP, lo_delmap, 1118 VOPNAME_POLL, (fs_generic_func_p) lo_poll, 1119 VOPNAME_DUMP, lo_dump, 1120 VOPNAME_DUMPCTL, fs_error, /* XXX - why? */ 1121 VOPNAME_PATHCONF, lo_pathconf, 1122 VOPNAME_PAGEIO, lo_pageio, 1123 VOPNAME_DISPOSE, (fs_generic_func_p) lo_dispose, 1124 VOPNAME_SETSECATTR, lo_setsecattr, 1125 VOPNAME_GETSECATTR, lo_getsecattr, 1126 VOPNAME_SHRLOCK, lo_shrlock, 1127 NULL, NULL 1128 }; 1129