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_vfsrlock_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 error = VFS_ROOT(vfsp, &tvp); 392 vn_vfsunlock(realdvp); 393 394 if (error) 395 goto out; 396 397 if ((tvp == li->li_rootvp) && (vp == realvp(tvp))) { 398 /* 399 * we're back at the real vnode 400 * of the rootvp 401 * 402 * return the rootvp 403 * Ex: /mnt/mnt/.. 404 * where / has been lofs-mounted 405 * onto /mnt. Return the lofs 406 * node mounted at /mnt. 407 */ 408 *vpp = tvp; 409 VN_RELE(vp); 410 return (0); 411 } else { 412 /* 413 * We are returning from a covered 414 * node whose vfs_mountedhere is 415 * not pointing to vfs of the current 416 * root vnode. 417 * This is a condn where in we 418 * returned a covered node say Zc 419 * but Zc is not the cover of current 420 * root. 421 * i.e.., if X is the root vnode 422 * lookup(Zc,"..") is taking us to 423 * X. 424 * Ex: /net/X/net/X/Y 425 * 426 * If LO_AUTOLOOP (autofs/lofs looping detected) 427 * has been set then we are encountering the 428 * cover of Y (Y being any directory vnode 429 * under /net/X/net/X/). 430 * When performing a dotdot set the 431 * returned vp to the vnode covered 432 * by the mounted lofs, ie /net/X/net/X 433 */ 434 VN_RELE(tvp); 435 if ((vtol(dvp))->lo_looping & LO_AUTOLOOP) { 436 VN_RELE(vp); 437 vp = li->li_rootvp; 438 vp = vp->v_vfsp->vfs_vnodecovered; 439 VN_HOLD(vp); 440 *vpp = makelonode(vp, li, 0); 441 (vtol(*vpp))->lo_looping |= LO_LOOPING; 442 return (0); 443 } 444 } 445 } else { 446 /* 447 * No frills just make the shadow node. 448 */ 449 *vpp = makelonode(vp, li, 0); 450 return (0); 451 } 452 } 453 454 nosub = (vtoli(dvp->v_vfsp)->li_flag & LO_NOSUB); 455 456 /* 457 * If this vnode is mounted on, then we 458 * traverse to the vnode which is the root of 459 * the mounted file system. 460 */ 461 if (!nosub && (error = traverse(&vp))) 462 goto out; 463 464 /* 465 * Make a lnode for the real vnode. 466 */ 467 if (vp->v_type != VDIR || nosub) { 468 *vpp = makelonode(vp, li, 0); 469 if (IS_DEVVP(*vpp)) { 470 vnode_t *svp; 471 472 svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 473 VN_RELE(*vpp); 474 if (svp == NULL) 475 error = ENOSYS; 476 else 477 *vpp = svp; 478 } 479 return (error); 480 } 481 482 /* 483 * if the found vnode (vp) is not of type lofs 484 * then we're just going to make a shadow of that 485 * vp and get out. 486 * 487 * If the found vnode (vp) is of lofs type, and 488 * we're not doing dotdot, check if we are 489 * looping. 490 */ 491 if (!doingdotdot && vfs_matchops(vp->v_vfsp, lo_vfsops)) { 492 /* 493 * Check if we're looping, i.e. 494 * vp equals the root vp of the lofs, directly 495 * or indirectly, return the covered node. 496 */ 497 498 if (!((vtol(dvp))->lo_looping & LO_LOOPING)) { 499 if (vp == li->li_rootvp) { 500 /* 501 * Direct looping condn. 502 * Ex:- X is / mounted directory so lookup of 503 * /X/X is a direct looping condn. 504 */ 505 tvp = vp; 506 vp = vp->v_vfsp->vfs_vnodecovered; 507 VN_HOLD(vp); 508 VN_RELE(tvp); 509 looping++; 510 } else { 511 /* 512 * Indirect looping can be defined as 513 * real lookup returning rootvp of the current 514 * tree in any level of recursion. 515 * 516 * This check is useful if there are multiple 517 * levels of lofs indirections. Suppose vnode X 518 * in the current lookup has as its real vnode 519 * another lofs node. Y = realvp(X) Y should be 520 * a lofs node for the check to continue or Y 521 * is not the rootvp of X. 522 * Ex:- say X and Y are two vnodes 523 * say real(Y) is X and real(X) is Z 524 * parent vnode for X and Y is Z 525 * lookup(Y,"path") say we are looking for Y 526 * again under Y and we have to return Yc. 527 * but the lookup of Y under Y doesnot return 528 * Y the root vnode again here is why. 529 * 1. lookup(Y,"path of Y") will go to 530 * 2. lookup(real(Y),"path of Y") and then to 531 * 3. lookup(real(X),"path of Y"). 532 * and now what lookup level 1 sees is the 533 * outcome of 2 but the vnode Y is due to 534 * lookup(Z,"path of Y") so we have to skip 535 * intermediate levels to find if in any level 536 * there is a looping. 537 */ 538 is_indirectloop = 0; 539 nonlovp = vp; 540 while ( 541 vfs_matchops(nonlovp->v_vfsp, lo_vfsops) && 542 !(is_indirectloop)) { 543 if (li->li_rootvp == nonlovp) { 544 is_indirectloop++; 545 break; 546 } 547 nonlovp = realvp(nonlovp); 548 } 549 550 if (is_indirectloop) { 551 VN_RELE(vp); 552 vp = nonlovp; 553 vp = vp->v_vfsp->vfs_vnodecovered; 554 VN_HOLD(vp); 555 looping++; 556 } 557 } 558 } else { 559 /* 560 * come here only because of the interaction between 561 * the autofs and lofs. 562 * 563 * Lookup of "/net/X/net/X" will return a shadow of 564 * an autonode X_a which we call X_l. 565 * 566 * Lookup of anything under X_l, will trigger a call to 567 * auto_lookup(X_a,nm) which will eventually call 568 * lo_lookup(X_lr,nm) where X_lr is the root vnode of 569 * the current lofs. 570 * 571 * We come here only when we are called with X_l as dvp 572 * and look for something underneath. 573 * 574 * Now that an autofs/lofs looping condition has been 575 * identified any directory vnode contained within 576 * dvp will be set to the vnode covered by the 577 * mounted autofs. Thus all directories within dvp 578 * will appear empty hence teminating the looping. 579 * The LO_AUTOLOOP flag is set on the returned lonode 580 * to indicate the termination of the autofs/lofs 581 * looping. This is required for the correct behaviour 582 * when performing a dotdot. 583 */ 584 realdvp = realvp(dvp); 585 while (vfs_matchops(realdvp->v_vfsp, lo_vfsops)) { 586 realdvp = realvp(realdvp); 587 } 588 589 error = VFS_ROOT(realdvp->v_vfsp, &tvp); 590 if (error) 591 goto out; 592 /* 593 * tvp now contains the rootvp of the vfs of the 594 * real vnode of dvp. The directory vnode vp is set 595 * to the covered vnode to terminate looping. No 596 * distinction is made between any vp as all directory 597 * vnodes contained in dvp are returned as the covered 598 * vnode. 599 */ 600 VN_RELE(vp); 601 vp = tvp; /* this is an autonode */ 602 603 /* 604 * Need to find the covered vnode 605 */ 606 vp = vp->v_vfsp->vfs_vnodecovered; 607 ASSERT(vp); 608 VN_HOLD(vp); 609 VN_RELE(tvp); 610 /* 611 * Force the creation of a new lnode even if the hash 612 * table contains a lnode that references this vnode. 613 */ 614 mkflag = LOF_FORCE; 615 autoloop++; 616 } 617 } 618 *vpp = makelonode(vp, li, mkflag); 619 620 if ((looping) || 621 (((vtol(dvp))->lo_looping & LO_LOOPING) && !doingdotdot)) { 622 (vtol(*vpp))->lo_looping |= LO_LOOPING; 623 } 624 625 if (autoloop) { 626 (vtol(*vpp))->lo_looping |= LO_AUTOLOOP; 627 } 628 629 out: 630 if (error != 0 && vp != NULL) 631 VN_RELE(vp); 632 #ifdef LODEBUG 633 lo_dprint(4, 634 "lo_lookup dvp %x realdvp %x nm '%s' newvp %x real vp %x error %d\n", 635 dvp, realvp(dvp), nm, *vpp, vp, error); 636 #endif 637 return (error); 638 } 639 640 /*ARGSUSED*/ 641 static int 642 lo_create( 643 vnode_t *dvp, 644 char *nm, 645 struct vattr *va, 646 enum vcexcl exclusive, 647 int mode, 648 vnode_t **vpp, 649 struct cred *cr, 650 int flag) 651 { 652 int error; 653 vnode_t *vp = NULL; 654 655 #ifdef LODEBUG 656 lo_dprint(4, "lo_create vp %p realvp %p\n", dvp, realvp(dvp)); 657 #endif 658 if (*nm == '\0') { 659 ASSERT(vpp && dvp == *vpp); 660 vp = realvp(*vpp); 661 } 662 663 if (IS_ZONEDEVFS(dvp)) { 664 /* Is this truly a create? If so, fail */ 665 if (*vpp == NULL) 666 return (EACCES); 667 668 /* Is this an open of a non-special for writing? If so, fail */ 669 if (*vpp != NULL && (mode & VWRITE) && !IS_DEVVP(*vpp)) 670 return (EACCES); 671 } 672 673 error = VOP_CREATE(realvp(dvp), nm, va, exclusive, mode, &vp, cr, flag); 674 if (!error) { 675 *vpp = makelonode(vp, vtoli(dvp->v_vfsp), 0); 676 if (IS_DEVVP(*vpp)) { 677 vnode_t *svp; 678 679 svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); 680 VN_RELE(*vpp); 681 if (svp == NULL) 682 error = ENOSYS; 683 else 684 *vpp = svp; 685 } 686 } 687 return (error); 688 } 689 690 static int 691 lo_remove(vnode_t *dvp, char *nm, struct cred *cr) 692 { 693 #ifdef LODEBUG 694 lo_dprint(4, "lo_remove vp %p realvp %p\n", dvp, realvp(dvp)); 695 #endif 696 if (IS_ZONEDEVFS(dvp)) 697 return (EACCES); 698 dvp = realvp(dvp); 699 return (VOP_REMOVE(dvp, nm, cr)); 700 } 701 702 static int 703 lo_link(vnode_t *tdvp, vnode_t *vp, char *tnm, struct cred *cr) 704 { 705 #ifdef LODEBUG 706 lo_dprint(4, "lo_link vp %p realvp %p\n", vp, realvp(vp)); 707 #endif 708 while (vn_matchops(vp, lo_vnodeops)) { 709 if (IS_ZONEDEVFS(vp)) 710 return (EACCES); 711 vp = realvp(vp); 712 } 713 while (vn_matchops(tdvp, lo_vnodeops)) { 714 if (IS_ZONEDEVFS(tdvp)) 715 return (EACCES); 716 tdvp = realvp(tdvp); 717 } 718 if (vp->v_vfsp != tdvp->v_vfsp) 719 return (EXDEV); 720 return (VOP_LINK(tdvp, vp, tnm, cr)); 721 } 722 723 static int 724 lo_rename( 725 vnode_t *odvp, 726 char *onm, 727 vnode_t *ndvp, 728 char *nnm, 729 struct cred *cr) 730 { 731 vnode_t *tnvp; 732 733 #ifdef LODEBUG 734 lo_dprint(4, "lo_rename vp %p realvp %p\n", odvp, realvp(odvp)); 735 #endif 736 if (IS_ZONEDEVFS(odvp)) 737 return (EACCES); 738 /* 739 * We need to make sure we're not trying to remove a mount point for a 740 * filesystem mounted on top of lofs, which only we know about. 741 */ 742 if (vn_matchops(ndvp, lo_vnodeops)) /* Not our problem. */ 743 goto rename; 744 if (VOP_LOOKUP(ndvp, nnm, &tnvp, NULL, 0, NULL, cr) != 0) 745 goto rename; 746 if (tnvp->v_type != VDIR) { 747 VN_RELE(tnvp); 748 goto rename; 749 } 750 if (vn_mountedvfs(tnvp)) { 751 VN_RELE(tnvp); 752 return (EBUSY); 753 } 754 VN_RELE(tnvp); 755 rename: 756 /* 757 * Since the case we're dealing with above can happen at any layer in 758 * the stack of lofs filesystems, we need to recurse down the stack, 759 * checking to see if there are any instances of a filesystem mounted on 760 * top of lofs. In order to keep on using the lofs version of 761 * VOP_RENAME(), we make sure that while the target directory is of type 762 * lofs, the source directory (the one used for getting the fs-specific 763 * version of VOP_RENAME()) is also of type lofs. 764 */ 765 if (vn_matchops(ndvp, lo_vnodeops)) { 766 if (IS_ZONEDEVFS(ndvp)) 767 return (EACCES); 768 ndvp = realvp(ndvp); /* Check the next layer */ 769 } else { 770 /* 771 * We can go fast here 772 */ 773 while (vn_matchops(odvp, lo_vnodeops)) { 774 if (IS_ZONEDEVFS(odvp)) 775 return (EACCES); 776 odvp = realvp(odvp); 777 } 778 if (odvp->v_vfsp != ndvp->v_vfsp) 779 return (EXDEV); 780 } 781 return (VOP_RENAME(odvp, onm, ndvp, nnm, cr)); 782 } 783 784 static int 785 lo_mkdir( 786 vnode_t *dvp, 787 char *nm, 788 struct vattr *va, 789 vnode_t **vpp, 790 struct cred *cr) 791 { 792 int error; 793 794 #ifdef LODEBUG 795 lo_dprint(4, "lo_mkdir vp %p realvp %p\n", dvp, realvp(dvp)); 796 #endif 797 if (IS_ZONEDEVFS(dvp)) 798 return (EACCES); 799 error = VOP_MKDIR(realvp(dvp), nm, va, vpp, cr); 800 if (!error) 801 *vpp = makelonode(*vpp, vtoli(dvp->v_vfsp), 0); 802 return (error); 803 } 804 805 static int 806 lo_realvp(vnode_t *vp, vnode_t **vpp) 807 { 808 #ifdef LODEBUG 809 lo_dprint(4, "lo_realvp %p\n", vp); 810 #endif 811 while (vn_matchops(vp, lo_vnodeops)) 812 vp = realvp(vp); 813 814 if (VOP_REALVP(vp, vpp) != 0) 815 *vpp = vp; 816 return (0); 817 } 818 819 static int 820 lo_rmdir( 821 vnode_t *dvp, 822 char *nm, 823 vnode_t *cdir, 824 struct cred *cr) 825 { 826 vnode_t *rvp = cdir; 827 828 #ifdef LODEBUG 829 lo_dprint(4, "lo_rmdir vp %p realvp %p\n", dvp, realvp(dvp)); 830 #endif 831 if (IS_ZONEDEVFS(dvp)) 832 return (EACCES); 833 /* if cdir is lofs vnode ptr get its real vnode ptr */ 834 if (vn_matchops(dvp, vn_getops(rvp))) 835 (void) lo_realvp(cdir, &rvp); 836 dvp = realvp(dvp); 837 return (VOP_RMDIR(dvp, nm, rvp, cr)); 838 } 839 840 static int 841 lo_symlink( 842 vnode_t *dvp, 843 char *lnm, 844 struct vattr *tva, 845 char *tnm, 846 struct cred *cr) 847 { 848 #ifdef LODEBUG 849 lo_dprint(4, "lo_symlink vp %p realvp %p\n", dvp, realvp(dvp)); 850 #endif 851 if (IS_ZONEDEVFS(dvp)) 852 return (EACCES); 853 dvp = realvp(dvp); 854 return (VOP_SYMLINK(dvp, lnm, tva, tnm, cr)); 855 } 856 857 static int 858 lo_readlink(vnode_t *vp, struct uio *uiop, struct cred *cr) 859 { 860 vp = realvp(vp); 861 return (VOP_READLINK(vp, uiop, cr)); 862 } 863 864 static int 865 lo_readdir(vnode_t *vp, struct uio *uiop, struct cred *cr, int *eofp) 866 { 867 #ifdef LODEBUG 868 lo_dprint(4, "lo_readdir vp %p realvp %p\n", vp, realvp(vp)); 869 #endif 870 vp = realvp(vp); 871 return (VOP_READDIR(vp, uiop, cr, eofp)); 872 } 873 874 static int 875 lo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct) 876 { 877 vp = realvp(vp); 878 return (VOP_RWLOCK(vp, write_lock, ct)); 879 } 880 881 static void 882 lo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct) 883 { 884 vp = realvp(vp); 885 VOP_RWUNLOCK(vp, write_lock, ct); 886 } 887 888 static int 889 lo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp) 890 { 891 vp = realvp(vp); 892 return (VOP_SEEK(vp, ooff, noffp)); 893 } 894 895 static int 896 lo_cmp(vnode_t *vp1, vnode_t *vp2) 897 { 898 while (vn_matchops(vp1, lo_vnodeops)) 899 vp1 = realvp(vp1); 900 while (vn_matchops(vp2, lo_vnodeops)) 901 vp2 = realvp(vp2); 902 return (VOP_CMP(vp1, vp2)); 903 } 904 905 static int 906 lo_frlock( 907 vnode_t *vp, 908 int cmd, 909 struct flock64 *bfp, 910 int flag, 911 offset_t offset, 912 struct flk_callback *flk_cbp, 913 cred_t *cr) 914 { 915 vp = realvp(vp); 916 return (VOP_FRLOCK(vp, cmd, bfp, flag, offset, flk_cbp, cr)); 917 } 918 919 static int 920 lo_space( 921 vnode_t *vp, 922 int cmd, 923 struct flock64 *bfp, 924 int flag, 925 offset_t offset, 926 struct cred *cr, 927 caller_context_t *ct) 928 { 929 vp = realvp(vp); 930 return (VOP_SPACE(vp, cmd, bfp, flag, offset, cr, ct)); 931 } 932 933 static int 934 lo_getpage( 935 vnode_t *vp, 936 offset_t off, 937 size_t len, 938 uint_t *prot, 939 struct page *parr[], 940 size_t psz, 941 struct seg *seg, 942 caddr_t addr, 943 enum seg_rw rw, 944 struct cred *cr) 945 { 946 vp = realvp(vp); 947 return (VOP_GETPAGE(vp, off, len, prot, parr, psz, seg, addr, rw, cr)); 948 } 949 950 static int 951 lo_putpage(vnode_t *vp, offset_t off, size_t len, int flags, struct cred *cr) 952 { 953 vp = realvp(vp); 954 return (VOP_PUTPAGE(vp, off, len, flags, cr)); 955 } 956 957 static int 958 lo_map( 959 vnode_t *vp, 960 offset_t off, 961 struct as *as, 962 caddr_t *addrp, 963 size_t len, 964 uchar_t prot, 965 uchar_t maxprot, 966 uint_t flags, 967 struct cred *cr) 968 { 969 vp = realvp(vp); 970 return (VOP_MAP(vp, off, as, addrp, len, prot, maxprot, flags, cr)); 971 } 972 973 static int 974 lo_addmap( 975 vnode_t *vp, 976 offset_t off, 977 struct as *as, 978 caddr_t addr, 979 size_t len, 980 uchar_t prot, 981 uchar_t maxprot, 982 uint_t flags, 983 struct cred *cr) 984 { 985 vp = realvp(vp); 986 return (VOP_ADDMAP(vp, off, as, addr, len, prot, maxprot, flags, cr)); 987 } 988 989 static int 990 lo_delmap( 991 vnode_t *vp, 992 offset_t off, 993 struct as *as, 994 caddr_t addr, 995 size_t len, 996 uint_t prot, 997 uint_t maxprot, 998 uint_t flags, 999 struct cred *cr) 1000 { 1001 vp = realvp(vp); 1002 return (VOP_DELMAP(vp, off, as, addr, len, prot, maxprot, flags, cr)); 1003 } 1004 1005 static int 1006 lo_poll( 1007 vnode_t *vp, 1008 short events, 1009 int anyyet, 1010 short *reventsp, 1011 struct pollhead **phpp) 1012 { 1013 vp = realvp(vp); 1014 return (VOP_POLL(vp, events, anyyet, reventsp, phpp)); 1015 } 1016 1017 static int 1018 lo_dump(vnode_t *vp, caddr_t addr, int bn, int count) 1019 { 1020 vp = realvp(vp); 1021 return (VOP_DUMP(vp, addr, bn, count)); 1022 } 1023 1024 static int 1025 lo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, struct cred *cr) 1026 { 1027 vp = realvp(vp); 1028 return (VOP_PATHCONF(vp, cmd, valp, cr)); 1029 } 1030 1031 static int 1032 lo_pageio( 1033 vnode_t *vp, 1034 struct page *pp, 1035 u_offset_t io_off, 1036 size_t io_len, 1037 int flags, 1038 cred_t *cr) 1039 { 1040 vp = realvp(vp); 1041 return (VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr)); 1042 } 1043 1044 static void 1045 lo_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr) 1046 { 1047 vp = realvp(vp); 1048 if (vp != NULL && vp != &kvp) 1049 VOP_DISPOSE(vp, pp, fl, dn, cr); 1050 } 1051 1052 static int 1053 lo_setsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr) 1054 { 1055 if (vn_is_readonly(vp)) 1056 return (EROFS); 1057 vp = realvp(vp); 1058 return (VOP_SETSECATTR(vp, secattr, flags, cr)); 1059 } 1060 1061 static int 1062 lo_getsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr) 1063 { 1064 vp = realvp(vp); 1065 return (VOP_GETSECATTR(vp, secattr, flags, cr)); 1066 } 1067 1068 static int 1069 lo_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr) 1070 { 1071 vp = realvp(vp); 1072 return (VOP_SHRLOCK(vp, cmd, shr, flag, cr)); 1073 } 1074 1075 /* 1076 * Loopback vnode operations vector. 1077 */ 1078 1079 struct vnodeops *lo_vnodeops; 1080 1081 const fs_operation_def_t lo_vnodeops_template[] = { 1082 VOPNAME_OPEN, lo_open, 1083 VOPNAME_CLOSE, lo_close, 1084 VOPNAME_READ, lo_read, 1085 VOPNAME_WRITE, lo_write, 1086 VOPNAME_IOCTL, lo_ioctl, 1087 VOPNAME_SETFL, lo_setfl, 1088 VOPNAME_GETATTR, lo_getattr, 1089 VOPNAME_SETATTR, lo_setattr, 1090 VOPNAME_ACCESS, lo_access, 1091 VOPNAME_LOOKUP, lo_lookup, 1092 VOPNAME_CREATE, lo_create, 1093 VOPNAME_REMOVE, lo_remove, 1094 VOPNAME_LINK, lo_link, 1095 VOPNAME_RENAME, lo_rename, 1096 VOPNAME_MKDIR, lo_mkdir, 1097 VOPNAME_RMDIR, lo_rmdir, 1098 VOPNAME_READDIR, lo_readdir, 1099 VOPNAME_SYMLINK, lo_symlink, 1100 VOPNAME_READLINK, lo_readlink, 1101 VOPNAME_FSYNC, lo_fsync, 1102 VOPNAME_INACTIVE, (fs_generic_func_p) lo_inactive, 1103 VOPNAME_FID, lo_fid, 1104 VOPNAME_RWLOCK, lo_rwlock, 1105 VOPNAME_RWUNLOCK, (fs_generic_func_p) lo_rwunlock, 1106 VOPNAME_SEEK, lo_seek, 1107 VOPNAME_CMP, lo_cmp, 1108 VOPNAME_FRLOCK, lo_frlock, 1109 VOPNAME_SPACE, lo_space, 1110 VOPNAME_REALVP, lo_realvp, 1111 VOPNAME_GETPAGE, lo_getpage, 1112 VOPNAME_PUTPAGE, lo_putpage, 1113 VOPNAME_MAP, (fs_generic_func_p) lo_map, 1114 VOPNAME_ADDMAP, (fs_generic_func_p) lo_addmap, 1115 VOPNAME_DELMAP, lo_delmap, 1116 VOPNAME_POLL, (fs_generic_func_p) lo_poll, 1117 VOPNAME_DUMP, lo_dump, 1118 VOPNAME_DUMPCTL, fs_error, /* XXX - why? */ 1119 VOPNAME_PATHCONF, lo_pathconf, 1120 VOPNAME_PAGEIO, lo_pageio, 1121 VOPNAME_DISPOSE, (fs_generic_func_p) lo_dispose, 1122 VOPNAME_SETSECATTR, lo_setsecattr, 1123 VOPNAME_GETSECATTR, lo_getsecattr, 1124 VOPNAME_SHRLOCK, lo_shrlock, 1125 NULL, NULL 1126 }; 1127