1 /* 2 * Copyright (c) 1992, 1993, 1994 The Regents of the University of California. 3 * Copyright (c) 1992, 1993, 1994 Jan-Simon Pendry. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)union_vnops.c 8.9 (Berkeley) 04/29/94 12 */ 13 14 #include <sys/param.h> 15 #include <sys/systm.h> 16 #include <sys/proc.h> 17 #include <sys/file.h> 18 #include <sys/time.h> 19 #include <sys/types.h> 20 #include <sys/vnode.h> 21 #include <sys/mount.h> 22 #include <sys/namei.h> 23 #include <sys/malloc.h> 24 #include <sys/buf.h> 25 #include <sys/queue.h> 26 #include <miscfs/union/union.h> 27 28 #define FIXUP(un) { \ 29 if (((un)->un_flags & UN_ULOCK) == 0) { \ 30 union_fixup(un); \ 31 } \ 32 } 33 34 static void 35 union_fixup(un) 36 struct union_node *un; 37 { 38 39 VOP_LOCK(un->un_uppervp); 40 un->un_flags |= UN_ULOCK; 41 } 42 43 static int 44 union_lookup1(udvp, dvpp, vpp, cnp) 45 struct vnode *udvp; 46 struct vnode **dvpp; 47 struct vnode **vpp; 48 struct componentname *cnp; 49 { 50 int error; 51 struct vnode *tdvp; 52 struct vnode *dvp; 53 struct mount *mp; 54 55 dvp = *dvpp; 56 57 /* 58 * If stepping up the directory tree, check for going 59 * back across the mount point, in which case do what 60 * lookup would do by stepping back down the mount 61 * hierarchy. 62 */ 63 if (cnp->cn_flags & ISDOTDOT) { 64 while ((dvp != udvp) && (dvp->v_flag & VROOT)) { 65 /* 66 * Don't do the NOCROSSMOUNT check 67 * at this level. By definition, 68 * union fs deals with namespaces, not 69 * filesystems. 70 */ 71 tdvp = dvp; 72 *dvpp = dvp = dvp->v_mount->mnt_vnodecovered; 73 vput(tdvp); 74 VREF(dvp); 75 VOP_LOCK(dvp); 76 } 77 } 78 79 error = VOP_LOOKUP(dvp, &tdvp, cnp); 80 if (error) 81 return (error); 82 83 /* 84 * The parent directory will have been unlocked, unless lookup 85 * found the last component. In which case, re-lock the node 86 * here to allow it to be unlocked again (phew) in union_lookup. 87 */ 88 if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN)) 89 VOP_LOCK(dvp); 90 91 dvp = tdvp; 92 93 /* 94 * Lastly check if the current node is a mount point in 95 * which case walk up the mount hierarchy making sure not to 96 * bump into the root of the mount tree (ie. dvp != udvp). 97 */ 98 while (dvp != udvp && (dvp->v_type == VDIR) && 99 (mp = dvp->v_mountedhere)) { 100 101 if (mp->mnt_flag & MNT_MLOCK) { 102 mp->mnt_flag |= MNT_MWAIT; 103 sleep((caddr_t) mp, PVFS); 104 continue; 105 } 106 107 if (error = VFS_ROOT(mp, &tdvp)) { 108 vput(dvp); 109 return (error); 110 } 111 112 vput(dvp); 113 dvp = tdvp; 114 } 115 116 *vpp = dvp; 117 return (0); 118 } 119 120 int 121 union_lookup(ap) 122 struct vop_lookup_args /* { 123 struct vnodeop_desc *a_desc; 124 struct vnode *a_dvp; 125 struct vnode **a_vpp; 126 struct componentname *a_cnp; 127 } */ *ap; 128 { 129 int error; 130 int uerror, lerror; 131 struct vnode *uppervp, *lowervp; 132 struct vnode *upperdvp, *lowerdvp; 133 struct vnode *dvp = ap->a_dvp; 134 struct union_node *dun = VTOUNION(dvp); 135 struct componentname *cnp = ap->a_cnp; 136 int lockparent = cnp->cn_flags & LOCKPARENT; 137 int rdonly = cnp->cn_flags & RDONLY; 138 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount); 139 struct ucred *saved_cred; 140 141 cnp->cn_flags |= LOCKPARENT; 142 143 upperdvp = dun->un_uppervp; 144 lowerdvp = dun->un_lowervp; 145 uppervp = NULLVP; 146 lowervp = NULLVP; 147 148 /* 149 * do the lookup in the upper level. 150 * if that level comsumes additional pathnames, 151 * then assume that something special is going 152 * on and just return that vnode. 153 */ 154 if (upperdvp != NULLVP) { 155 FIXUP(dun); 156 uerror = union_lookup1(um->um_uppervp, &upperdvp, 157 &uppervp, cnp); 158 /*if (uppervp == upperdvp) 159 dun->un_flags |= UN_KLOCK;*/ 160 161 if (cnp->cn_consume != 0) { 162 *ap->a_vpp = uppervp; 163 if (!lockparent) 164 cnp->cn_flags &= ~LOCKPARENT; 165 return (uerror); 166 } 167 } else { 168 uerror = ENOENT; 169 } 170 171 /* 172 * in a similar way to the upper layer, do the lookup 173 * in the lower layer. this time, if there is some 174 * component magic going on, then vput whatever we got 175 * back from the upper layer and return the lower vnode 176 * instead. 177 */ 178 if (lowerdvp != NULLVP) { 179 int nameiop; 180 181 VOP_LOCK(lowerdvp); 182 183 /* 184 * Only do a LOOKUP on the bottom node, since 185 * we won't be making changes to it anyway. 186 */ 187 nameiop = cnp->cn_nameiop; 188 cnp->cn_nameiop = LOOKUP; 189 if (um->um_op == UNMNT_BELOW) { 190 saved_cred = cnp->cn_cred; 191 cnp->cn_cred = um->um_cred; 192 } 193 lerror = union_lookup1(um->um_lowervp, &lowerdvp, 194 &lowervp, cnp); 195 if (um->um_op == UNMNT_BELOW) 196 cnp->cn_cred = saved_cred; 197 cnp->cn_nameiop = nameiop; 198 199 if (lowervp != lowerdvp) 200 VOP_UNLOCK(lowerdvp); 201 202 if (cnp->cn_consume != 0) { 203 if (uppervp != NULLVP) { 204 if (uppervp == upperdvp) 205 vrele(uppervp); 206 else 207 vput(uppervp); 208 uppervp = NULLVP; 209 } 210 *ap->a_vpp = lowervp; 211 if (!lockparent) 212 cnp->cn_flags &= ~LOCKPARENT; 213 return (lerror); 214 } 215 } else { 216 lerror = ENOENT; 217 } 218 219 if (!lockparent) 220 cnp->cn_flags &= ~LOCKPARENT; 221 222 /* 223 * at this point, we have uerror and lerror indicating 224 * possible errors with the lookups in the upper and lower 225 * layers. additionally, uppervp and lowervp are (locked) 226 * references to existing vnodes in the upper and lower layers. 227 * 228 * there are now three cases to consider. 229 * 1. if both layers returned an error, then return whatever 230 * error the upper layer generated. 231 * 232 * 2. if the top layer failed and the bottom layer succeeded 233 * then two subcases occur. 234 * a. the bottom vnode is not a directory, in which 235 * case just return a new union vnode referencing 236 * an empty top layer and the existing bottom layer. 237 * b. the bottom vnode is a directory, in which case 238 * create a new directory in the top-level and 239 * continue as in case 3. 240 * 241 * 3. if the top layer succeeded then return a new union 242 * vnode referencing whatever the new top layer and 243 * whatever the bottom layer returned. 244 */ 245 246 *ap->a_vpp = NULLVP; 247 248 /* case 1. */ 249 if ((uerror != 0) && (lerror != 0)) { 250 return (uerror); 251 } 252 253 /* case 2. */ 254 if (uerror != 0 /* && (lerror == 0) */ ) { 255 if (lowervp->v_type == VDIR) { /* case 2b. */ 256 dun->un_flags &= ~UN_ULOCK; 257 VOP_UNLOCK(upperdvp); 258 uerror = union_mkshadow(um, upperdvp, cnp, &uppervp); 259 VOP_LOCK(upperdvp); 260 dun->un_flags |= UN_ULOCK; 261 262 if (uerror) { 263 if (lowervp != NULLVP) { 264 vput(lowervp); 265 lowervp = NULLVP; 266 } 267 return (uerror); 268 } 269 } 270 } 271 272 if (lowervp != NULLVP) 273 VOP_UNLOCK(lowervp); 274 275 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, 276 uppervp, lowervp); 277 278 if (error) { 279 if (uppervp != NULLVP) 280 vput(uppervp); 281 if (lowervp != NULLVP) 282 vrele(lowervp); 283 } else { 284 if (*ap->a_vpp != dvp) 285 if (!lockparent || !(cnp->cn_flags & ISLASTCN)) 286 VOP_UNLOCK(dvp); 287 } 288 289 return (error); 290 } 291 292 int 293 union_create(ap) 294 struct vop_create_args /* { 295 struct vnode *a_dvp; 296 struct vnode **a_vpp; 297 struct componentname *a_cnp; 298 struct vattr *a_vap; 299 } */ *ap; 300 { 301 struct union_node *un = VTOUNION(ap->a_dvp); 302 struct vnode *dvp = un->un_uppervp; 303 304 if (dvp != NULLVP) { 305 int error; 306 struct vnode *vp; 307 308 FIXUP(un); 309 310 VREF(dvp); 311 un->un_flags |= UN_KLOCK; 312 vput(ap->a_dvp); 313 error = VOP_CREATE(dvp, &vp, ap->a_cnp, ap->a_vap); 314 if (error) 315 return (error); 316 317 error = union_allocvp( 318 ap->a_vpp, 319 ap->a_dvp->v_mount, 320 ap->a_dvp, 321 NULLVP, 322 ap->a_cnp, 323 vp, 324 NULLVP); 325 if (error) 326 vput(vp); 327 return (error); 328 } 329 330 vput(ap->a_dvp); 331 return (EROFS); 332 } 333 334 int 335 union_mknod(ap) 336 struct vop_mknod_args /* { 337 struct vnode *a_dvp; 338 struct vnode **a_vpp; 339 struct componentname *a_cnp; 340 struct vattr *a_vap; 341 } */ *ap; 342 { 343 struct union_node *un = VTOUNION(ap->a_dvp); 344 struct vnode *dvp = un->un_uppervp; 345 346 if (dvp != NULLVP) { 347 int error; 348 struct vnode *vp; 349 350 FIXUP(un); 351 352 VREF(dvp); 353 un->un_flags |= UN_KLOCK; 354 vput(ap->a_dvp); 355 error = VOP_MKNOD(dvp, &vp, ap->a_cnp, ap->a_vap); 356 if (error) 357 return (error); 358 359 if (vp != NULLVP) { 360 error = union_allocvp( 361 ap->a_vpp, 362 ap->a_dvp->v_mount, 363 ap->a_dvp, 364 NULLVP, 365 ap->a_cnp, 366 vp, 367 NULLVP); 368 if (error) 369 vput(vp); 370 } 371 return (error); 372 } 373 374 vput(ap->a_dvp); 375 return (EROFS); 376 } 377 378 int 379 union_open(ap) 380 struct vop_open_args /* { 381 struct vnodeop_desc *a_desc; 382 struct vnode *a_vp; 383 int a_mode; 384 struct ucred *a_cred; 385 struct proc *a_p; 386 } */ *ap; 387 { 388 struct union_node *un = VTOUNION(ap->a_vp); 389 struct vnode *tvp; 390 int mode = ap->a_mode; 391 struct ucred *cred = ap->a_cred; 392 struct proc *p = ap->a_p; 393 int error; 394 395 /* 396 * If there is an existing upper vp then simply open that. 397 */ 398 tvp = un->un_uppervp; 399 if (tvp == NULLVP) { 400 /* 401 * If the lower vnode is being opened for writing, then 402 * copy the file contents to the upper vnode and open that, 403 * otherwise can simply open the lower vnode. 404 */ 405 tvp = un->un_lowervp; 406 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) { 407 struct vnode *vp; 408 int i; 409 410 /* 411 * Open the named file in the upper layer. Note that 412 * the file may have come into existence *since* the 413 * lookup was done, since the upper layer may really 414 * be a loopback mount of some other filesystem... 415 * so open the file with exclusive create and barf if 416 * it already exists. 417 * XXX - perhaps should re-lookup the node (once more 418 * with feeling) and simply open that. Who knows. 419 */ 420 error = union_vn_create(&vp, un, p); 421 if (error) 422 return (error); 423 424 /* at this point, uppervp is locked */ 425 union_newupper(un, vp); 426 un->un_flags |= UN_ULOCK; 427 428 /* 429 * Now, if the file is being opened with truncation, 430 * then the (new) upper vnode is ready to fly, 431 * otherwise the data from the lower vnode must be 432 * copied to the upper layer first. This only works 433 * for regular files (check is made above). 434 */ 435 if ((mode & O_TRUNC) == 0) { 436 /* 437 * XXX - should not ignore errors 438 * from VOP_CLOSE 439 */ 440 VOP_LOCK(tvp); 441 error = VOP_OPEN(tvp, FREAD, cred, p); 442 if (error == 0) { 443 error = union_copyfile(p, cred, 444 tvp, un->un_uppervp); 445 VOP_UNLOCK(tvp); 446 (void) VOP_CLOSE(tvp, FREAD); 447 } else { 448 VOP_UNLOCK(tvp); 449 } 450 451 #ifdef UNION_DIAGNOSTIC 452 if (!error) 453 uprintf("union: copied up %s\n", 454 un->un_path); 455 #endif 456 } 457 458 un->un_flags &= ~UN_ULOCK; 459 VOP_UNLOCK(un->un_uppervp); 460 union_vn_close(un->un_uppervp, FWRITE, cred, p); 461 VOP_LOCK(un->un_uppervp); 462 un->un_flags |= UN_ULOCK; 463 464 /* 465 * Subsequent IOs will go to the top layer, so 466 * call close on the lower vnode and open on the 467 * upper vnode to ensure that the filesystem keeps 468 * its references counts right. This doesn't do 469 * the right thing with (cred) and (FREAD) though. 470 * Ignoring error returns is not righ, either. 471 */ 472 for (i = 0; i < un->un_openl; i++) { 473 (void) VOP_CLOSE(tvp, FREAD); 474 (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p); 475 } 476 un->un_openl = 0; 477 478 if (error == 0) 479 error = VOP_OPEN(un->un_uppervp, mode, cred, p); 480 return (error); 481 } 482 483 /* 484 * Just open the lower vnode 485 */ 486 un->un_openl++; 487 VOP_LOCK(tvp); 488 error = VOP_OPEN(tvp, mode, cred, p); 489 VOP_UNLOCK(tvp); 490 491 return (error); 492 } 493 494 FIXUP(un); 495 496 error = VOP_OPEN(tvp, mode, cred, p); 497 498 return (error); 499 } 500 501 int 502 union_close(ap) 503 struct vop_close_args /* { 504 struct vnode *a_vp; 505 int a_fflag; 506 struct ucred *a_cred; 507 struct proc *a_p; 508 } */ *ap; 509 { 510 struct union_node *un = VTOUNION(ap->a_vp); 511 struct vnode *vp; 512 513 if (un->un_uppervp != NULLVP) { 514 vp = un->un_uppervp; 515 } else { 516 #ifdef UNION_DIAGNOSTIC 517 if (un->un_openl <= 0) 518 panic("union: un_openl cnt"); 519 #endif 520 --un->un_openl; 521 vp = un->un_lowervp; 522 } 523 524 return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p)); 525 } 526 527 /* 528 * Check access permission on the union vnode. 529 * The access check being enforced is to check 530 * against both the underlying vnode, and any 531 * copied vnode. This ensures that no additional 532 * file permissions are given away simply because 533 * the user caused an implicit file copy. 534 */ 535 int 536 union_access(ap) 537 struct vop_access_args /* { 538 struct vnodeop_desc *a_desc; 539 struct vnode *a_vp; 540 int a_mode; 541 struct ucred *a_cred; 542 struct proc *a_p; 543 } */ *ap; 544 { 545 struct union_node *un = VTOUNION(ap->a_vp); 546 int error = EACCES; 547 struct vnode *vp; 548 549 if ((vp = un->un_uppervp) != NULLVP) { 550 FIXUP(un); 551 return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p)); 552 } 553 554 if ((vp = un->un_lowervp) != NULLVP) { 555 VOP_LOCK(vp); 556 error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p); 557 if (error == 0) { 558 struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount); 559 560 if (um->um_op == UNMNT_BELOW) 561 error = VOP_ACCESS(vp, ap->a_mode, 562 um->um_cred, ap->a_p); 563 } 564 VOP_UNLOCK(vp); 565 if (error) 566 return (error); 567 } 568 569 return (error); 570 } 571 572 /* 573 * We handle getattr only to change the fsid. 574 */ 575 int 576 union_getattr(ap) 577 struct vop_getattr_args /* { 578 struct vnode *a_vp; 579 struct vattr *a_vap; 580 struct ucred *a_cred; 581 struct proc *a_p; 582 } */ *ap; 583 { 584 int error; 585 struct union_node *un = VTOUNION(ap->a_vp); 586 struct vnode *vp = un->un_uppervp; 587 struct vattr *vap; 588 struct vattr va; 589 590 591 /* 592 * Some programs walk the filesystem hierarchy by counting 593 * links to directories to avoid stat'ing all the time. 594 * This means the link count on directories needs to be "correct". 595 * The only way to do that is to call getattr on both layers 596 * and fix up the link count. The link count will not necessarily 597 * be accurate but will be large enough to defeat the tree walkers. 598 */ 599 600 vap = ap->a_vap; 601 602 vp = un->un_uppervp; 603 if (vp != NULLVP) { 604 /* 605 * It's not clear whether VOP_GETATTR is to be 606 * called with the vnode locked or not. stat() calls 607 * it with (vp) locked, and fstat calls it with 608 * (vp) unlocked. 609 * In the mean time, compensate here by checking 610 * the union_node's lock flag. 611 */ 612 if (un->un_flags & UN_LOCKED) 613 FIXUP(un); 614 615 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 616 if (error) 617 return (error); 618 } 619 620 if (vp == NULLVP) { 621 vp = un->un_lowervp; 622 } else if (vp->v_type == VDIR) { 623 vp = un->un_lowervp; 624 vap = &va; 625 } else { 626 vp = NULLVP; 627 } 628 629 if (vp != NULLVP) { 630 VOP_LOCK(vp); 631 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 632 VOP_UNLOCK(vp); 633 if (error) 634 return (error); 635 } 636 637 if ((vap != ap->a_vap) && (vap->va_type == VDIR)) 638 ap->a_vap->va_nlink += vap->va_nlink; 639 640 vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 641 return (0); 642 } 643 644 int 645 union_setattr(ap) 646 struct vop_setattr_args /* { 647 struct vnode *a_vp; 648 struct vattr *a_vap; 649 struct ucred *a_cred; 650 struct proc *a_p; 651 } */ *ap; 652 { 653 struct union_node *un = VTOUNION(ap->a_vp); 654 int error; 655 656 /* 657 * Handle case of truncating lower object to zero size, 658 * by creating a zero length upper object. This is to 659 * handle the case of open with O_TRUNC and O_CREAT. 660 */ 661 if ((un->un_uppervp == NULLVP) && 662 /* assert(un->un_lowervp != NULLVP) */ 663 (un->un_lowervp->v_type == VREG) && 664 (ap->a_vap->va_size == 0)) { 665 struct vnode *vp; 666 667 error = union_vn_create(&vp, un, ap->a_p); 668 if (error) 669 return (error); 670 671 /* at this point, uppervp is locked */ 672 union_newupper(un, vp); 673 674 VOP_UNLOCK(vp); 675 union_vn_close(un->un_uppervp, FWRITE, ap->a_cred, ap->a_p); 676 VOP_LOCK(vp); 677 un->un_flags |= UN_ULOCK; 678 } 679 680 /* 681 * Try to set attributes in upper layer, 682 * otherwise return read-only filesystem error. 683 */ 684 if (un->un_uppervp != NULLVP) { 685 FIXUP(un); 686 error = VOP_SETATTR(un->un_uppervp, ap->a_vap, 687 ap->a_cred, ap->a_p); 688 } else { 689 error = EROFS; 690 } 691 692 return (error); 693 } 694 695 int 696 union_read(ap) 697 struct vop_read_args /* { 698 struct vnode *a_vp; 699 struct uio *a_uio; 700 int a_ioflag; 701 struct ucred *a_cred; 702 } */ *ap; 703 { 704 int error; 705 struct vnode *vp = OTHERVP(ap->a_vp); 706 int dolock = (vp == LOWERVP(ap->a_vp)); 707 708 if (dolock) 709 VOP_LOCK(vp); 710 else 711 FIXUP(VTOUNION(ap->a_vp)); 712 error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 713 if (dolock) 714 VOP_UNLOCK(vp); 715 716 return (error); 717 } 718 719 int 720 union_write(ap) 721 struct vop_read_args /* { 722 struct vnode *a_vp; 723 struct uio *a_uio; 724 int a_ioflag; 725 struct ucred *a_cred; 726 } */ *ap; 727 { 728 int error; 729 struct vnode *vp = OTHERVP(ap->a_vp); 730 int dolock = (vp == LOWERVP(ap->a_vp)); 731 732 if (dolock) 733 VOP_LOCK(vp); 734 else 735 FIXUP(VTOUNION(ap->a_vp)); 736 error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 737 if (dolock) 738 VOP_UNLOCK(vp); 739 740 return (error); 741 } 742 743 int 744 union_ioctl(ap) 745 struct vop_ioctl_args /* { 746 struct vnode *a_vp; 747 int a_command; 748 caddr_t a_data; 749 int a_fflag; 750 struct ucred *a_cred; 751 struct proc *a_p; 752 } */ *ap; 753 { 754 755 return (VOP_IOCTL(OTHERVP(ap->a_vp), ap->a_command, ap->a_data, 756 ap->a_fflag, ap->a_cred, ap->a_p)); 757 } 758 759 int 760 union_select(ap) 761 struct vop_select_args /* { 762 struct vnode *a_vp; 763 int a_which; 764 int a_fflags; 765 struct ucred *a_cred; 766 struct proc *a_p; 767 } */ *ap; 768 { 769 770 return (VOP_SELECT(OTHERVP(ap->a_vp), ap->a_which, ap->a_fflags, 771 ap->a_cred, ap->a_p)); 772 } 773 774 int 775 union_mmap(ap) 776 struct vop_mmap_args /* { 777 struct vnode *a_vp; 778 int a_fflags; 779 struct ucred *a_cred; 780 struct proc *a_p; 781 } */ *ap; 782 { 783 784 return (VOP_MMAP(OTHERVP(ap->a_vp), ap->a_fflags, 785 ap->a_cred, ap->a_p)); 786 } 787 788 int 789 union_fsync(ap) 790 struct vop_fsync_args /* { 791 struct vnode *a_vp; 792 struct ucred *a_cred; 793 int a_waitfor; 794 struct proc *a_p; 795 } */ *ap; 796 { 797 int error = 0; 798 struct vnode *targetvp = OTHERVP(ap->a_vp); 799 800 if (targetvp != NULLVP) { 801 int dolock = (targetvp == LOWERVP(ap->a_vp)); 802 803 if (dolock) 804 VOP_LOCK(targetvp); 805 else 806 FIXUP(VTOUNION(ap->a_vp)); 807 error = VOP_FSYNC(targetvp, ap->a_cred, 808 ap->a_waitfor, ap->a_p); 809 if (dolock) 810 VOP_UNLOCK(targetvp); 811 } 812 813 return (error); 814 } 815 816 int 817 union_seek(ap) 818 struct vop_seek_args /* { 819 struct vnode *a_vp; 820 off_t a_oldoff; 821 off_t a_newoff; 822 struct ucred *a_cred; 823 } */ *ap; 824 { 825 826 return (VOP_SEEK(OTHERVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred)); 827 } 828 829 int 830 union_remove(ap) 831 struct vop_remove_args /* { 832 struct vnode *a_dvp; 833 struct vnode *a_vp; 834 struct componentname *a_cnp; 835 } */ *ap; 836 { 837 int error; 838 struct union_node *dun = VTOUNION(ap->a_dvp); 839 struct union_node *un = VTOUNION(ap->a_vp); 840 841 if (dun->un_uppervp != NULLVP && un->un_uppervp != NULLVP) { 842 struct vnode *dvp = dun->un_uppervp; 843 struct vnode *vp = un->un_uppervp; 844 845 FIXUP(dun); 846 VREF(dvp); 847 dun->un_flags |= UN_KLOCK; 848 vput(ap->a_dvp); 849 FIXUP(un); 850 VREF(vp); 851 un->un_flags |= UN_KLOCK; 852 vput(ap->a_vp); 853 854 error = VOP_REMOVE(dvp, vp, ap->a_cnp); 855 if (!error) 856 union_removed_upper(un); 857 858 /* 859 * XXX: should create a whiteout here 860 */ 861 } else { 862 /* 863 * XXX: should create a whiteout here 864 */ 865 vput(ap->a_dvp); 866 vput(ap->a_vp); 867 error = EROFS; 868 } 869 870 return (error); 871 } 872 873 int 874 union_link(ap) 875 struct vop_link_args /* { 876 struct vnode *a_vp; 877 struct vnode *a_tdvp; 878 struct componentname *a_cnp; 879 } */ *ap; 880 { 881 int error; 882 struct union_node *dun = VTOUNION(ap->a_vp); 883 struct union_node *un = VTOUNION(ap->a_tdvp); 884 885 if (dun->un_uppervp != NULLVP && un->un_uppervp != NULLVP) { 886 struct vnode *dvp = dun->un_uppervp; 887 struct vnode *vp = un->un_uppervp; 888 889 FIXUP(dun); 890 VREF(dvp); 891 dun->un_flags |= UN_KLOCK; 892 vput(ap->a_vp); 893 FIXUP(un); 894 VREF(vp); 895 vrele(ap->a_tdvp); 896 897 error = VOP_LINK(dvp, vp, ap->a_cnp); 898 } else { 899 /* 900 * XXX: perhaps could copy to upper layer 901 * and do the link there. 902 */ 903 vput(ap->a_vp); 904 vrele(ap->a_tdvp); 905 error = EROFS; 906 } 907 908 return (error); 909 } 910 911 int 912 union_rename(ap) 913 struct vop_rename_args /* { 914 struct vnode *a_fdvp; 915 struct vnode *a_fvp; 916 struct componentname *a_fcnp; 917 struct vnode *a_tdvp; 918 struct vnode *a_tvp; 919 struct componentname *a_tcnp; 920 } */ *ap; 921 { 922 int error; 923 924 struct vnode *fdvp = ap->a_fdvp; 925 struct vnode *fvp = ap->a_fvp; 926 struct vnode *tdvp = ap->a_tdvp; 927 struct vnode *tvp = ap->a_tvp; 928 929 if (fdvp->v_op == union_vnodeop_p) { /* always true */ 930 struct union_node *un = VTOUNION(fdvp); 931 if (un->un_uppervp == NULLVP) { 932 error = EROFS; 933 goto bad; 934 } 935 936 fdvp = un->un_uppervp; 937 VREF(fdvp); 938 vrele(ap->a_fdvp); 939 } 940 941 if (fvp->v_op == union_vnodeop_p) { /* always true */ 942 struct union_node *un = VTOUNION(fvp); 943 if (un->un_uppervp == NULLVP) { 944 error = EROFS; 945 goto bad; 946 } 947 948 fvp = un->un_uppervp; 949 VREF(fvp); 950 vrele(ap->a_fvp); 951 } 952 953 if (tdvp->v_op == union_vnodeop_p) { 954 struct union_node *un = VTOUNION(tdvp); 955 if (un->un_uppervp == NULLVP) { 956 /* 957 * this should never happen in normal 958 * operation but might if there was 959 * a problem creating the top-level shadow 960 * directory. 961 */ 962 error = EROFS; 963 goto bad; 964 } 965 966 tdvp = un->un_uppervp; 967 VREF(tdvp); 968 un->un_flags |= UN_KLOCK; 969 vput(ap->a_tdvp); 970 } 971 972 if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) { 973 struct union_node *un = VTOUNION(tvp); 974 975 tvp = un->un_uppervp; 976 if (tvp != NULLVP) { 977 VREF(tvp); 978 un->un_flags |= UN_KLOCK; 979 } 980 vput(ap->a_tvp); 981 } 982 983 return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp)); 984 985 bad: 986 vrele(fdvp); 987 vrele(fvp); 988 vput(tdvp); 989 if (tvp != NULLVP) 990 vput(tvp); 991 992 return (error); 993 } 994 995 int 996 union_mkdir(ap) 997 struct vop_mkdir_args /* { 998 struct vnode *a_dvp; 999 struct vnode **a_vpp; 1000 struct componentname *a_cnp; 1001 struct vattr *a_vap; 1002 } */ *ap; 1003 { 1004 struct union_node *un = VTOUNION(ap->a_dvp); 1005 struct vnode *dvp = un->un_uppervp; 1006 1007 if (dvp != NULLVP) { 1008 int error; 1009 struct vnode *vp; 1010 1011 FIXUP(un); 1012 VREF(dvp); 1013 un->un_flags |= UN_KLOCK; 1014 vput(ap->a_dvp); 1015 error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap); 1016 if (error) 1017 return (error); 1018 1019 error = union_allocvp( 1020 ap->a_vpp, 1021 ap->a_dvp->v_mount, 1022 ap->a_dvp, 1023 NULLVP, 1024 ap->a_cnp, 1025 vp, 1026 NULLVP); 1027 if (error) 1028 vput(vp); 1029 return (error); 1030 } 1031 1032 vput(ap->a_dvp); 1033 return (EROFS); 1034 } 1035 1036 int 1037 union_rmdir(ap) 1038 struct vop_rmdir_args /* { 1039 struct vnode *a_dvp; 1040 struct vnode *a_vp; 1041 struct componentname *a_cnp; 1042 } */ *ap; 1043 { 1044 int error; 1045 struct union_node *dun = VTOUNION(ap->a_dvp); 1046 struct union_node *un = VTOUNION(ap->a_vp); 1047 1048 if (dun->un_uppervp != NULLVP && un->un_uppervp != NULLVP) { 1049 struct vnode *dvp = dun->un_uppervp; 1050 struct vnode *vp = un->un_uppervp; 1051 1052 FIXUP(dun); 1053 VREF(dvp); 1054 dun->un_flags |= UN_KLOCK; 1055 vput(ap->a_dvp); 1056 FIXUP(un); 1057 VREF(vp); 1058 un->un_flags |= UN_KLOCK; 1059 vput(ap->a_vp); 1060 1061 error = VOP_RMDIR(dvp, vp, ap->a_cnp); 1062 if (!error) 1063 union_removed_upper(un); 1064 1065 /* 1066 * XXX: should create a whiteout here 1067 */ 1068 } else { 1069 /* 1070 * XXX: should create a whiteout here 1071 */ 1072 vput(ap->a_dvp); 1073 vput(ap->a_vp); 1074 error = EROFS; 1075 } 1076 1077 return (error); 1078 } 1079 1080 int 1081 union_symlink(ap) 1082 struct vop_symlink_args /* { 1083 struct vnode *a_dvp; 1084 struct vnode **a_vpp; 1085 struct componentname *a_cnp; 1086 struct vattr *a_vap; 1087 char *a_target; 1088 } */ *ap; 1089 { 1090 struct union_node *un = VTOUNION(ap->a_dvp); 1091 struct vnode *dvp = un->un_uppervp; 1092 1093 if (dvp != NULLVP) { 1094 int error; 1095 struct vnode *vp; 1096 struct mount *mp = ap->a_dvp->v_mount; 1097 1098 FIXUP(un); 1099 VREF(dvp); 1100 un->un_flags |= UN_KLOCK; 1101 vput(ap->a_dvp); 1102 error = VOP_SYMLINK(dvp, &vp, ap->a_cnp, 1103 ap->a_vap, ap->a_target); 1104 *ap->a_vpp = NULLVP; 1105 return (error); 1106 } 1107 1108 vput(ap->a_dvp); 1109 return (EROFS); 1110 } 1111 1112 /* 1113 * union_readdir works in concert with getdirentries and 1114 * readdir(3) to provide a list of entries in the unioned 1115 * directories. getdirentries is responsible for walking 1116 * down the union stack. readdir(3) is responsible for 1117 * eliminating duplicate names from the returned data stream. 1118 */ 1119 int 1120 union_readdir(ap) 1121 struct vop_readdir_args /* { 1122 struct vnodeop_desc *a_desc; 1123 struct vnode *a_vp; 1124 struct uio *a_uio; 1125 struct ucred *a_cred; 1126 } */ *ap; 1127 { 1128 int error = 0; 1129 struct union_node *un = VTOUNION(ap->a_vp); 1130 1131 if (un->un_uppervp != NULLVP) { 1132 FIXUP(un); 1133 error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred); 1134 } 1135 1136 return (error); 1137 } 1138 1139 int 1140 union_readlink(ap) 1141 struct vop_readlink_args /* { 1142 struct vnode *a_vp; 1143 struct uio *a_uio; 1144 struct ucred *a_cred; 1145 } */ *ap; 1146 { 1147 int error; 1148 struct vnode *vp = OTHERVP(ap->a_vp); 1149 int dolock = (vp == LOWERVP(ap->a_vp)); 1150 1151 if (dolock) 1152 VOP_LOCK(vp); 1153 else 1154 FIXUP(VTOUNION(ap->a_vp)); 1155 error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); 1156 if (dolock) 1157 VOP_UNLOCK(vp); 1158 1159 return (error); 1160 } 1161 1162 int 1163 union_abortop(ap) 1164 struct vop_abortop_args /* { 1165 struct vnode *a_dvp; 1166 struct componentname *a_cnp; 1167 } */ *ap; 1168 { 1169 int error; 1170 struct vnode *vp = OTHERVP(ap->a_dvp); 1171 struct union_node *un = VTOUNION(ap->a_dvp); 1172 int islocked = un->un_flags & UN_LOCKED; 1173 int dolock = (vp == LOWERVP(ap->a_dvp)); 1174 1175 if (islocked) { 1176 if (dolock) 1177 VOP_LOCK(vp); 1178 else 1179 FIXUP(VTOUNION(ap->a_dvp)); 1180 } 1181 error = VOP_ABORTOP(vp, ap->a_cnp); 1182 if (islocked && dolock) 1183 VOP_UNLOCK(vp); 1184 1185 return (error); 1186 } 1187 1188 int 1189 union_inactive(ap) 1190 struct vop_inactive_args /* { 1191 struct vnode *a_vp; 1192 } */ *ap; 1193 { 1194 struct union_node *un = VTOUNION(ap->a_vp); 1195 1196 /* 1197 * Do nothing (and _don't_ bypass). 1198 * Wait to vrele lowervp until reclaim, 1199 * so that until then our union_node is in the 1200 * cache and reusable. 1201 * 1202 * NEEDSWORK: Someday, consider inactive'ing 1203 * the lowervp and then trying to reactivate it 1204 * with capabilities (v_id) 1205 * like they do in the name lookup cache code. 1206 * That's too much work for now. 1207 */ 1208 1209 #ifdef UNION_DIAGNOSTIC 1210 if (un->un_flags & UN_LOCKED) 1211 panic("union: inactivating locked node"); 1212 if (un->un_flags & UN_ULOCK) 1213 panic("union: inactivating w/locked upper node"); 1214 #endif 1215 1216 if ((un->un_flags & UN_CACHED) == 0) 1217 vgone(ap->a_vp); 1218 1219 return (0); 1220 } 1221 1222 int 1223 union_reclaim(ap) 1224 struct vop_reclaim_args /* { 1225 struct vnode *a_vp; 1226 } */ *ap; 1227 { 1228 1229 union_freevp(ap->a_vp); 1230 1231 return (0); 1232 } 1233 1234 int 1235 union_lock(ap) 1236 struct vop_lock_args *ap; 1237 { 1238 struct vnode *vp = ap->a_vp; 1239 struct union_node *un; 1240 1241 start: 1242 while (vp->v_flag & VXLOCK) { 1243 vp->v_flag |= VXWANT; 1244 sleep((caddr_t)vp, PINOD); 1245 } 1246 1247 un = VTOUNION(vp); 1248 1249 if (un->un_uppervp != NULLVP) { 1250 if ((un->un_flags & UN_ULOCK) == 0) { 1251 un->un_flags |= UN_ULOCK; 1252 VOP_LOCK(un->un_uppervp); 1253 } 1254 #ifdef DIAGNOSTIC 1255 if (un->un_flags & UN_KLOCK) 1256 panic("union: dangling upper lock"); 1257 #endif 1258 } 1259 1260 if (un->un_flags & UN_LOCKED) { 1261 #ifdef DIAGNOSTIC 1262 if (curproc && un->un_pid == curproc->p_pid && 1263 un->un_pid > -1 && curproc->p_pid > -1) 1264 panic("union: locking against myself"); 1265 #endif 1266 un->un_flags |= UN_WANT; 1267 sleep((caddr_t) &un->un_flags, PINOD); 1268 goto start; 1269 } 1270 1271 #ifdef DIAGNOSTIC 1272 if (curproc) 1273 un->un_pid = curproc->p_pid; 1274 else 1275 un->un_pid = -1; 1276 #endif 1277 1278 un->un_flags |= UN_LOCKED; 1279 return (0); 1280 } 1281 1282 int 1283 union_unlock(ap) 1284 struct vop_lock_args *ap; 1285 { 1286 struct union_node *un = VTOUNION(ap->a_vp); 1287 1288 #ifdef DIAGNOSTIC 1289 if ((un->un_flags & UN_LOCKED) == 0) 1290 panic("union: unlock unlocked node"); 1291 if (curproc && un->un_pid != curproc->p_pid && 1292 curproc->p_pid > -1 && un->un_pid > -1) 1293 panic("union: unlocking other process's union node"); 1294 #endif 1295 1296 un->un_flags &= ~UN_LOCKED; 1297 1298 if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK) 1299 VOP_UNLOCK(un->un_uppervp); 1300 1301 un->un_flags &= ~(UN_ULOCK|UN_KLOCK); 1302 1303 if (un->un_flags & UN_WANT) { 1304 un->un_flags &= ~UN_WANT; 1305 wakeup((caddr_t) &un->un_flags); 1306 } 1307 1308 #ifdef DIAGNOSTIC 1309 un->un_pid = 0; 1310 #endif 1311 1312 return (0); 1313 } 1314 1315 int 1316 union_bmap(ap) 1317 struct vop_bmap_args /* { 1318 struct vnode *a_vp; 1319 daddr_t a_bn; 1320 struct vnode **a_vpp; 1321 daddr_t *a_bnp; 1322 int *a_runp; 1323 } */ *ap; 1324 { 1325 int error; 1326 struct vnode *vp = OTHERVP(ap->a_vp); 1327 int dolock = (vp == LOWERVP(ap->a_vp)); 1328 1329 if (dolock) 1330 VOP_LOCK(vp); 1331 else 1332 FIXUP(VTOUNION(ap->a_vp)); 1333 error = VOP_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp); 1334 if (dolock) 1335 VOP_UNLOCK(vp); 1336 1337 return (error); 1338 } 1339 1340 int 1341 union_print(ap) 1342 struct vop_print_args /* { 1343 struct vnode *a_vp; 1344 } */ *ap; 1345 { 1346 struct vnode *vp = ap->a_vp; 1347 1348 printf("\ttag VT_UNION, vp=%x, uppervp=%x, lowervp=%x\n", 1349 vp, UPPERVP(vp), LOWERVP(vp)); 1350 return (0); 1351 } 1352 1353 int 1354 union_islocked(ap) 1355 struct vop_islocked_args /* { 1356 struct vnode *a_vp; 1357 } */ *ap; 1358 { 1359 1360 return ((VTOUNION(ap->a_vp)->un_flags & UN_LOCKED) ? 1 : 0); 1361 } 1362 1363 int 1364 union_pathconf(ap) 1365 struct vop_pathconf_args /* { 1366 struct vnode *a_vp; 1367 int a_name; 1368 int *a_retval; 1369 } */ *ap; 1370 { 1371 int error; 1372 struct vnode *vp = OTHERVP(ap->a_vp); 1373 int dolock = (vp == LOWERVP(ap->a_vp)); 1374 1375 if (dolock) 1376 VOP_LOCK(vp); 1377 else 1378 FIXUP(VTOUNION(ap->a_vp)); 1379 error = VOP_PATHCONF(vp, ap->a_name, ap->a_retval); 1380 if (dolock) 1381 VOP_UNLOCK(vp); 1382 1383 return (error); 1384 } 1385 1386 int 1387 union_advlock(ap) 1388 struct vop_advlock_args /* { 1389 struct vnode *a_vp; 1390 caddr_t a_id; 1391 int a_op; 1392 struct flock *a_fl; 1393 int a_flags; 1394 } */ *ap; 1395 { 1396 1397 return (VOP_ADVLOCK(OTHERVP(ap->a_vp), ap->a_id, ap->a_op, 1398 ap->a_fl, ap->a_flags)); 1399 } 1400 1401 1402 /* 1403 * XXX - vop_strategy must be hand coded because it has no 1404 * vnode in its arguments. 1405 * This goes away with a merged VM/buffer cache. 1406 */ 1407 int 1408 union_strategy(ap) 1409 struct vop_strategy_args /* { 1410 struct buf *a_bp; 1411 } */ *ap; 1412 { 1413 struct buf *bp = ap->a_bp; 1414 int error; 1415 struct vnode *savedvp; 1416 1417 savedvp = bp->b_vp; 1418 bp->b_vp = OTHERVP(bp->b_vp); 1419 1420 #ifdef DIAGNOSTIC 1421 if (bp->b_vp == NULLVP) 1422 panic("union_strategy: nil vp"); 1423 if (((bp->b_flags & B_READ) == 0) && 1424 (bp->b_vp == LOWERVP(savedvp))) 1425 panic("union_strategy: writing to lowervp"); 1426 #endif 1427 1428 error = VOP_STRATEGY(bp); 1429 bp->b_vp = savedvp; 1430 1431 return (error); 1432 } 1433 1434 /* 1435 * Global vfs data structures 1436 */ 1437 int (**union_vnodeop_p)(); 1438 struct vnodeopv_entry_desc union_vnodeop_entries[] = { 1439 { &vop_default_desc, vn_default_error }, 1440 { &vop_lookup_desc, union_lookup }, /* lookup */ 1441 { &vop_create_desc, union_create }, /* create */ 1442 { &vop_mknod_desc, union_mknod }, /* mknod */ 1443 { &vop_open_desc, union_open }, /* open */ 1444 { &vop_close_desc, union_close }, /* close */ 1445 { &vop_access_desc, union_access }, /* access */ 1446 { &vop_getattr_desc, union_getattr }, /* getattr */ 1447 { &vop_setattr_desc, union_setattr }, /* setattr */ 1448 { &vop_read_desc, union_read }, /* read */ 1449 { &vop_write_desc, union_write }, /* write */ 1450 { &vop_ioctl_desc, union_ioctl }, /* ioctl */ 1451 { &vop_select_desc, union_select }, /* select */ 1452 { &vop_mmap_desc, union_mmap }, /* mmap */ 1453 { &vop_fsync_desc, union_fsync }, /* fsync */ 1454 { &vop_seek_desc, union_seek }, /* seek */ 1455 { &vop_remove_desc, union_remove }, /* remove */ 1456 { &vop_link_desc, union_link }, /* link */ 1457 { &vop_rename_desc, union_rename }, /* rename */ 1458 { &vop_mkdir_desc, union_mkdir }, /* mkdir */ 1459 { &vop_rmdir_desc, union_rmdir }, /* rmdir */ 1460 { &vop_symlink_desc, union_symlink }, /* symlink */ 1461 { &vop_readdir_desc, union_readdir }, /* readdir */ 1462 { &vop_readlink_desc, union_readlink }, /* readlink */ 1463 { &vop_abortop_desc, union_abortop }, /* abortop */ 1464 { &vop_inactive_desc, union_inactive }, /* inactive */ 1465 { &vop_reclaim_desc, union_reclaim }, /* reclaim */ 1466 { &vop_lock_desc, union_lock }, /* lock */ 1467 { &vop_unlock_desc, union_unlock }, /* unlock */ 1468 { &vop_bmap_desc, union_bmap }, /* bmap */ 1469 { &vop_strategy_desc, union_strategy }, /* strategy */ 1470 { &vop_print_desc, union_print }, /* print */ 1471 { &vop_islocked_desc, union_islocked }, /* islocked */ 1472 { &vop_pathconf_desc, union_pathconf }, /* pathconf */ 1473 { &vop_advlock_desc, union_advlock }, /* advlock */ 1474 #ifdef notdef 1475 { &vop_blkatoff_desc, union_blkatoff }, /* blkatoff */ 1476 { &vop_valloc_desc, union_valloc }, /* valloc */ 1477 { &vop_vfree_desc, union_vfree }, /* vfree */ 1478 { &vop_truncate_desc, union_truncate }, /* truncate */ 1479 { &vop_update_desc, union_update }, /* update */ 1480 { &vop_bwrite_desc, union_bwrite }, /* bwrite */ 1481 #endif 1482 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1483 }; 1484 struct vnodeopv_desc union_vnodeop_opv_desc = 1485 { &union_vnodeop_p, union_vnodeop_entries }; 1486