39 */ 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/proc.h> 44#include <sys/fcntl.h> 45#include <sys/stat.h> 46#include <sys/kernel.h> 47#include <sys/vnode.h> 48#include <sys/mount.h> 49#include <sys/namei.h> 50#include <sys/malloc.h> 51#include <sys/buf.h> 52#include <sys/lock.h> 53#include <miscfs/union/union.h> 54 55#define FIXUP(un, p) { \ 56 if (((un)->un_flags & UN_ULOCK) == 0) { \ 57 union_fixup(un, p); \ 58 } \ 59} 60 61static int union_abortop __P((struct vop_abortop_args *ap)); 62static int union_access __P((struct vop_access_args *ap)); 63static int union_advlock __P((struct vop_advlock_args *ap)); 64static int union_bmap __P((struct vop_bmap_args *ap)); 65static int union_close __P((struct vop_close_args *ap)); 66static int union_create __P((struct vop_create_args *ap)); 67static void union_fixup __P((struct union_node *un, struct proc *p)); 68static int union_fsync __P((struct vop_fsync_args *ap)); 69static int union_getattr __P((struct vop_getattr_args *ap)); 70static int union_inactive __P((struct vop_inactive_args *ap)); 71static int union_ioctl __P((struct vop_ioctl_args *ap)); 72static int union_islocked __P((struct vop_islocked_args *ap)); 73static int union_lease __P((struct vop_lease_args *ap)); 74static int union_link __P((struct vop_link_args *ap)); 75static int union_lock __P((struct vop_lock_args *ap)); 76static int union_lookup __P((struct vop_lookup_args *ap)); 77static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvpp, 78 struct vnode **vpp, 79 struct componentname *cnp)); 80static int union_mkdir __P((struct vop_mkdir_args *ap)); 81static int union_mknod __P((struct vop_mknod_args *ap)); 82static int union_mmap __P((struct vop_mmap_args *ap)); 83static int union_open __P((struct vop_open_args *ap)); 84static int union_pathconf __P((struct vop_pathconf_args *ap)); 85static int union_print __P((struct vop_print_args *ap)); 86static int union_read __P((struct vop_read_args *ap)); 87static int union_readdir __P((struct vop_readdir_args *ap)); 88static int union_readlink __P((struct vop_readlink_args *ap)); 89static int union_reclaim __P((struct vop_reclaim_args *ap)); 90static int union_remove __P((struct vop_remove_args *ap)); 91static int union_rename __P((struct vop_rename_args *ap)); 92static int union_revoke __P((struct vop_revoke_args *ap)); 93static int union_rmdir __P((struct vop_rmdir_args *ap)); 94static int union_poll __P((struct vop_poll_args *ap)); 95static int union_setattr __P((struct vop_setattr_args *ap)); 96static int union_strategy __P((struct vop_strategy_args *ap)); 97static int union_symlink __P((struct vop_symlink_args *ap)); 98static int union_unlock __P((struct vop_unlock_args *ap)); 99static int union_whiteout __P((struct vop_whiteout_args *ap)); 100static int union_write __P((struct vop_read_args *ap)); 101 102static void 103union_fixup(un, p) 104 struct union_node *un; 105 struct proc *p; 106{ 107 108 vn_lock(un->un_uppervp, LK_EXCLUSIVE | LK_RETRY, p); 109 un->un_flags |= UN_ULOCK; 110} 111 112static int 113union_lookup1(udvp, dvpp, vpp, cnp) 114 struct vnode *udvp; 115 struct vnode **dvpp; 116 struct vnode **vpp; 117 struct componentname *cnp; 118{ 119 int error; 120 struct proc *p = cnp->cn_proc; 121 struct vnode *tdvp; 122 struct vnode *dvp; 123 struct mount *mp; 124 125 dvp = *dvpp; 126 127 /* 128 * If stepping up the directory tree, check for going 129 * back across the mount point, in which case do what 130 * lookup would do by stepping back down the mount 131 * hierarchy. 132 */ 133 if (cnp->cn_flags & ISDOTDOT) { 134 while ((dvp != udvp) && (dvp->v_flag & VROOT)) { 135 /* 136 * Don't do the NOCROSSMOUNT check 137 * at this level. By definition, 138 * union fs deals with namespaces, not 139 * filesystems. 140 */ 141 tdvp = dvp; 142 *dvpp = dvp = dvp->v_mount->mnt_vnodecovered; 143 vput(tdvp); 144 VREF(dvp); 145 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 146 } 147 } 148 149 error = VOP_LOOKUP(dvp, &tdvp, cnp); 150 if (error) 151 return (error); 152 153 /* 154 * The parent directory will have been unlocked, unless lookup 155 * found the last component. In which case, re-lock the node 156 * here to allow it to be unlocked again (phew) in union_lookup. 157 */ 158 if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN)) 159 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 160 161 dvp = tdvp; 162 163 /* 164 * Lastly check if the current node is a mount point in 165 * which case walk up the mount hierarchy making sure not to 166 * bump into the root of the mount tree (ie. dvp != udvp). 167 */ 168 while (dvp != udvp && (dvp->v_type == VDIR) && 169 (mp = dvp->v_mountedhere)) { 170 171 if (vfs_busy(mp, 0, 0, p)) 172 continue; 173 174 error = VFS_ROOT(mp, &tdvp); 175 vfs_unbusy(mp, p); 176 if (error) { 177 vput(dvp); 178 return (error); 179 } 180 181 vput(dvp); 182 dvp = tdvp; 183 } 184 185 *vpp = dvp; 186 return (0); 187} 188 189static int 190union_lookup(ap) 191 struct vop_lookup_args /* { 192 struct vnodeop_desc *a_desc; 193 struct vnode *a_dvp; 194 struct vnode **a_vpp; 195 struct componentname *a_cnp; 196 } */ *ap; 197{ 198 int error; 199 int uerror, lerror; 200 struct vnode *uppervp, *lowervp; 201 struct vnode *upperdvp, *lowerdvp; 202 struct vnode *dvp = ap->a_dvp; 203 struct union_node *dun = VTOUNION(dvp); 204 struct componentname *cnp = ap->a_cnp; 205 struct proc *p = cnp->cn_proc; 206 int lockparent = cnp->cn_flags & LOCKPARENT; 207 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount); 208 struct ucred *saved_cred; 209 int iswhiteout; 210 struct vattr va; 211 212 213 /* 214 * Disallow write attemps to the filesystem mounted read-only. 215 */ 216 if ((cnp->cn_flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 217 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 218 return (EROFS); 219 220#ifdef notyet 221 if (cnp->cn_namelen == 3 && 222 cnp->cn_nameptr[2] == '.' && 223 cnp->cn_nameptr[1] == '.' && 224 cnp->cn_nameptr[0] == '.') { 225 dvp = *ap->a_vpp = LOWERVP(ap->a_dvp); 226 if (dvp == NULLVP) 227 return (ENOENT); 228 VREF(dvp); 229 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 230 if (!lockparent || !(cnp->cn_flags & ISLASTCN)) 231 VOP_UNLOCK(ap->a_dvp, 0, p); 232 return (0); 233 } 234#endif 235 236 cnp->cn_flags |= LOCKPARENT; 237 238 upperdvp = dun->un_uppervp; 239 lowerdvp = dun->un_lowervp; 240 uppervp = NULLVP; 241 lowervp = NULLVP; 242 iswhiteout = 0; 243 244 if (cnp->cn_flags & ISDOTDOT) { 245 if (upperdvp != NULL) 246 VREF(upperdvp); 247 if (lowerdvp != NULL) 248 VREF(lowerdvp); 249 } 250 251 /* 252 * do the lookup in the upper level. 253 * if that level comsumes additional pathnames, 254 * then assume that something special is going 255 * on and just return that vnode. 256 */ 257 if (upperdvp != NULLVP) { 258 FIXUP(dun, p); 259 /* 260 * If we're doing `..' in the underlying filesystem, 261 * we must drop our lock on the union node before 262 * going up the tree in the lower file system--if we block 263 * on the lowervp lock, and that's held by someone else 264 * coming down the tree and who's waiting for our lock, 265 * we would be hosed. 266 */ 267 if (cnp->cn_flags & ISDOTDOT) { 268 /* retain lock on underlying VP: */ 269 dun->un_flags |= UN_KLOCK; 270 VOP_UNLOCK(dvp, 0, p); 271 } 272 uerror = union_lookup1(um->um_uppervp, &upperdvp, 273 &uppervp, cnp); 274 /* 275 * Disallow write attemps to the filesystem mounted read-only. 276 */ 277 if (uerror == EJUSTRETURN && (cnp->cn_flags & ISLASTCN) && 278 (dvp->v_mount->mnt_flag & MNT_RDONLY) && 279 (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) { 280 if (!lockparent) 281 cnp->cn_flags &= ~LOCKPARENT; 282 return (EROFS); 283 } 284 285 if (cnp->cn_flags & ISDOTDOT) { 286 if (dun->un_uppervp == upperdvp) { 287 /* 288 * We got the underlying bugger back locked... 289 * now take back the union node lock. Since we 290 * hold the uppervp lock, we can diddle union 291 * locking flags at will. :) 292 */ 293 dun->un_flags |= UN_ULOCK; 294 } 295 /* 296 * If upperdvp got swapped out, it means we did 297 * some mount point magic, and we do not have 298 * dun->un_uppervp locked currently--so we get it 299 * locked here (don't set the UN_ULOCK flag). 300 */ 301 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 302 } 303 304 /*if (uppervp == upperdvp) 305 dun->un_flags |= UN_KLOCK;*/ 306 307 if (cnp->cn_consume != 0) { 308 *ap->a_vpp = uppervp; 309 if (!lockparent) 310 cnp->cn_flags &= ~LOCKPARENT; 311 error = uerror; 312 goto out; 313 } 314 if (uerror == ENOENT || uerror == EJUSTRETURN) { 315 if (cnp->cn_flags & ISWHITEOUT) { 316 iswhiteout = 1; 317 } else if (lowerdvp != NULLVP) { 318 lerror = VOP_GETATTR(upperdvp, &va, 319 cnp->cn_cred, cnp->cn_proc); 320 if (lerror == 0 && (va.va_flags & OPAQUE)) 321 iswhiteout = 1; 322 } 323 } 324 } else { 325 uerror = ENOENT; 326 } 327 328 /* 329 * in a similar way to the upper layer, do the lookup 330 * in the lower layer. this time, if there is some 331 * component magic going on, then vput whatever we got 332 * back from the upper layer and return the lower vnode 333 * instead. 334 */ 335 if (lowerdvp != NULLVP && !iswhiteout) { 336 int nameiop; 337 338 vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p); 339 340 /* 341 * Only do a LOOKUP on the bottom node, since 342 * we won't be making changes to it anyway. 343 */ 344 nameiop = cnp->cn_nameiop; 345 cnp->cn_nameiop = LOOKUP; 346 if (um->um_op == UNMNT_BELOW) { 347 saved_cred = cnp->cn_cred; 348 cnp->cn_cred = um->um_cred; 349 } 350 /* 351 * We shouldn't have to worry about locking interactions 352 * between the lower layer and our union layer (w.r.t. 353 * `..' processing) because we don't futz with lowervp 354 * locks in the union-node instantiation code path. 355 */ 356 lerror = union_lookup1(um->um_lowervp, &lowerdvp, 357 &lowervp, cnp); 358 if (um->um_op == UNMNT_BELOW) 359 cnp->cn_cred = saved_cred; 360 cnp->cn_nameiop = nameiop; 361 362 if (lowervp != lowerdvp) 363 VOP_UNLOCK(lowerdvp, 0, p); 364 365 if (cnp->cn_consume != 0 || lerror == EACCES) { 366 if (lerror == EACCES) 367 lowervp = NULLVP; 368 if (uppervp != NULLVP) { 369 if (uppervp == upperdvp) 370 vrele(uppervp); 371 else 372 vput(uppervp); 373 uppervp = NULLVP; 374 } 375 *ap->a_vpp = lowervp; 376 if (!lockparent) 377 cnp->cn_flags &= ~LOCKPARENT; 378 error = lerror; 379 goto out; 380 } 381 } else { 382 lerror = ENOENT; 383 if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) { 384 lowervp = LOWERVP(dun->un_pvp); 385 if (lowervp != NULLVP) { 386 VREF(lowervp); 387 vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p); 388 lerror = 0; 389 } 390 } 391 } 392 393 if (!lockparent) 394 cnp->cn_flags &= ~LOCKPARENT; 395 396 /* 397 * at this point, we have uerror and lerror indicating 398 * possible errors with the lookups in the upper and lower 399 * layers. additionally, uppervp and lowervp are (locked) 400 * references to existing vnodes in the upper and lower layers. 401 * 402 * there are now three cases to consider. 403 * 1. if both layers returned an error, then return whatever 404 * error the upper layer generated. 405 * 406 * 2. if the top layer failed and the bottom layer succeeded 407 * then two subcases occur. 408 * a. the bottom vnode is not a directory, in which 409 * case just return a new union vnode referencing 410 * an empty top layer and the existing bottom layer. 411 * b. the bottom vnode is a directory, in which case 412 * create a new directory in the top-level and 413 * continue as in case 3. 414 * 415 * 3. if the top layer succeeded then return a new union 416 * vnode referencing whatever the new top layer and 417 * whatever the bottom layer returned. 418 */ 419 420 *ap->a_vpp = NULLVP; 421 422 /* case 1. */ 423 if ((uerror != 0) && (lerror != 0)) { 424 error = uerror; 425 goto out; 426 } 427 428 /* case 2. */ 429 if (uerror != 0 /* && (lerror == 0) */ ) { 430 if (lowervp->v_type == VDIR) { /* case 2b. */ 431 dun->un_flags &= ~UN_ULOCK; 432 VOP_UNLOCK(upperdvp, 0, p); 433 uerror = union_mkshadow(um, upperdvp, cnp, &uppervp); 434 vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY, p); 435 dun->un_flags |= UN_ULOCK; 436 437 if (uerror) { 438 if (lowervp != NULLVP) { 439 vput(lowervp); 440 lowervp = NULLVP; 441 } 442 error = uerror; 443 goto out; 444 } 445 } 446 } 447 448 if (lowervp != NULLVP) 449 VOP_UNLOCK(lowervp, 0, p); 450 451 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, 452 uppervp, lowervp, 1); 453 454 if (error) { 455 if (uppervp != NULLVP) 456 vput(uppervp); 457 if (lowervp != NULLVP) 458 vrele(lowervp); 459 } else { 460 if (*ap->a_vpp != dvp) 461 if (!lockparent || !(cnp->cn_flags & ISLASTCN)) 462 VOP_UNLOCK(dvp, 0, p); 463#ifdef DIAGNOSTIC 464 if (cnp->cn_namelen == 1 && 465 cnp->cn_nameptr[0] == '.' && 466 *ap->a_vpp != dvp) { 467 panic("union_lookup returning . (%p) not same as startdir (%p)", 468 ap->a_vpp, dvp); 469 } 470#endif 471 } 472 473out: 474 if (cnp->cn_flags & ISDOTDOT) { 475 if (upperdvp != NULL) 476 vrele(upperdvp); 477 if (lowerdvp != NULL) 478 vrele(lowerdvp); 479 } 480 481 return (error); 482} 483 484static int 485union_create(ap) 486 struct vop_create_args /* { 487 struct vnode *a_dvp; 488 struct vnode **a_vpp; 489 struct componentname *a_cnp; 490 struct vattr *a_vap; 491 } */ *ap; 492{ 493 struct union_node *dun = VTOUNION(ap->a_dvp); 494 struct vnode *dvp = dun->un_uppervp; 495 struct componentname *cnp = ap->a_cnp; 496 struct proc *p = cnp->cn_proc; 497 498 if (dvp != NULLVP) { 499 struct vnode *vp; 500 struct mount *mp; 501 int error; 502 503 FIXUP(dun, p); 504 505 dun->un_flags |= UN_KLOCK; 506 VOP_UNLOCK(ap->a_dvp, 0, p); 507 error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap); 508 if (error) { 509 dun->un_flags |= UN_ULOCK; 510 return (error); 511 } 512 513 mp = ap->a_dvp->v_mount; 514 VOP_UNLOCK(dvp, 0, p); 515 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp, 516 NULLVP, 1); 517 if (error) 518 vput(vp); 519 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 520 return (error); 521 } 522 523 return (EROFS); 524} 525 526static int 527union_whiteout(ap) 528 struct vop_whiteout_args /* { 529 struct vnode *a_dvp; 530 struct componentname *a_cnp; 531 int a_flags; 532 } */ *ap; 533{ 534 struct union_node *un = VTOUNION(ap->a_dvp); 535 struct componentname *cnp = ap->a_cnp; 536 struct proc *p = cnp->cn_proc; 537 538 if (un->un_uppervp == NULLVP) 539 return (EOPNOTSUPP); 540 541 FIXUP(un, p); 542 return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags)); 543} 544 545static int 546union_mknod(ap) 547 struct vop_mknod_args /* { 548 struct vnode *a_dvp; 549 struct vnode **a_vpp; 550 struct componentname *a_cnp; 551 struct vattr *a_vap; 552 } */ *ap; 553{ 554 struct union_node *dun = VTOUNION(ap->a_dvp); 555 struct vnode *dvp = dun->un_uppervp; 556 struct componentname *cnp = ap->a_cnp; 557 struct proc *p = cnp->cn_proc; 558 559 if (dvp != NULLVP) { 560 struct vnode *vp; 561 struct mount *mp; 562 int error; 563 564 FIXUP(dun, p); 565 566 dun->un_flags |= UN_KLOCK; 567 VOP_UNLOCK(ap->a_dvp, 0, p); 568 error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap); 569 if (error) { 570 dun->un_flags |= UN_ULOCK; 571 return (error); 572 } 573 574 if (vp != NULLVP) { 575 mp = ap->a_dvp->v_mount; 576 VOP_UNLOCK(dvp, 0, p); 577 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, 578 cnp, vp, NULLVP, 1); 579 if (error) 580 vput(vp); 581 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 582 } else { 583 dun->un_flags |= UN_ULOCK; 584 } 585 return (error); 586 } 587 588 return (EROFS); 589} 590 591static int 592union_open(ap) 593 struct vop_open_args /* { 594 struct vnodeop_desc *a_desc; 595 struct vnode *a_vp; 596 int a_mode; 597 struct ucred *a_cred; 598 struct proc *a_p; 599 } */ *ap; 600{ 601 struct union_node *un = VTOUNION(ap->a_vp); 602 struct vnode *tvp; 603 int mode = ap->a_mode; 604 struct ucred *cred = ap->a_cred; 605 struct proc *p = ap->a_p; 606 int error; 607 608 /* 609 * If there is an existing upper vp then simply open that. 610 */ 611 tvp = un->un_uppervp; 612 if (tvp == NULLVP) { 613 /* 614 * If the lower vnode is being opened for writing, then 615 * copy the file contents to the upper vnode and open that, 616 * otherwise can simply open the lower vnode. 617 */ 618 tvp = un->un_lowervp; 619 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) { 620 error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p); 621 if (error == 0) 622 error = VOP_OPEN(un->un_uppervp, mode, cred, p); 623 return (error); 624 } 625 626 /* 627 * Just open the lower vnode 628 */ 629 un->un_openl++; 630 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); 631 error = VOP_OPEN(tvp, mode, cred, p); 632 VOP_UNLOCK(tvp, 0, p); 633 634 return (error); 635 } 636 637 FIXUP(un, p); 638 639 error = VOP_OPEN(tvp, mode, cred, p); 640 641 return (error); 642} 643 644static int 645union_close(ap) 646 struct vop_close_args /* { 647 struct vnode *a_vp; 648 int a_fflag; 649 struct ucred *a_cred; 650 struct proc *a_p; 651 } */ *ap; 652{ 653 struct union_node *un = VTOUNION(ap->a_vp); 654 struct vnode *vp; 655 656 if ((vp = un->un_uppervp) == NULLVP) { 657#ifdef UNION_DIAGNOSTIC 658 if (un->un_openl <= 0) 659 panic("union: un_openl cnt"); 660#endif 661 --un->un_openl; 662 vp = un->un_lowervp; 663 } 664 665 ap->a_vp = vp; 666 return (VCALL(vp, VOFFSET(vop_close), ap)); 667} 668 669/* 670 * Check access permission on the union vnode. 671 * The access check being enforced is to check 672 * against both the underlying vnode, and any 673 * copied vnode. This ensures that no additional 674 * file permissions are given away simply because 675 * the user caused an implicit file copy. 676 */ 677static int 678union_access(ap) 679 struct vop_access_args /* { 680 struct vnodeop_desc *a_desc; 681 struct vnode *a_vp; 682 int a_mode; 683 struct ucred *a_cred; 684 struct proc *a_p; 685 } */ *ap; 686{ 687 struct union_node *un = VTOUNION(ap->a_vp); 688 struct proc *p = ap->a_p; 689 int error = EACCES; 690 struct vnode *vp; 691 struct vnode *savedvp; 692 693 /* 694 * Disallow write attempts on filesystems mounted read-only. 695 */ 696 if (ap->a_mode & VWRITE && (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) { 697 switch (ap->a_vp->v_type) { 698 case VREG: case VDIR: case VLNK: 699 return (EROFS); 700 } 701 } 702 if ((vp = un->un_uppervp) != NULLVP) { 703 FIXUP(un, p); 704 ap->a_vp = vp; 705 return (VCALL(vp, VOFFSET(vop_access), ap)); 706 } 707 708 if ((vp = un->un_lowervp) != NULLVP) { 709 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 710 savedvp = ap->a_vp; 711 ap->a_vp = vp; 712 error = VCALL(vp, VOFFSET(vop_access), ap); 713 if (error == 0) { 714 struct union_mount *um = MOUNTTOUNIONMOUNT(savedvp->v_mount); 715 716 if (um->um_op == UNMNT_BELOW) { 717 ap->a_cred = um->um_cred; 718 error = VCALL(vp, VOFFSET(vop_access), ap); 719 } 720 } 721 VOP_UNLOCK(vp, 0, p); 722 if (error) 723 return (error); 724 } 725 726 return (error); 727} 728 729/* 730 * We handle getattr only to change the fsid and 731 * track object sizes 732 */ 733static int 734union_getattr(ap) 735 struct vop_getattr_args /* { 736 struct vnode *a_vp; 737 struct vattr *a_vap; 738 struct ucred *a_cred; 739 struct proc *a_p; 740 } */ *ap; 741{ 742 int error; 743 struct union_node *un = VTOUNION(ap->a_vp); 744 struct vnode *vp = un->un_uppervp; 745 struct proc *p = ap->a_p; 746 struct vattr *vap; 747 struct vattr va; 748 749 750 /* 751 * Some programs walk the filesystem hierarchy by counting 752 * links to directories to avoid stat'ing all the time. 753 * This means the link count on directories needs to be "correct". 754 * The only way to do that is to call getattr on both layers 755 * and fix up the link count. The link count will not necessarily 756 * be accurate but will be large enough to defeat the tree walkers. 757 */ 758 759 vap = ap->a_vap; 760 761 vp = un->un_uppervp; 762 if (vp != NULLVP) { 763 /* 764 * It's not clear whether VOP_GETATTR is to be 765 * called with the vnode locked or not. stat() calls 766 * it with (vp) locked, and fstat calls it with 767 * (vp) unlocked. 768 * In the mean time, compensate here by checking 769 * the union_node's lock flag. 770 */ 771 if (un->un_flags & UN_LOCKED) 772 FIXUP(un, p); 773 774 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 775 if (error) 776 return (error); 777 union_newsize(ap->a_vp, vap->va_size, VNOVAL); 778 } 779 780 if (vp == NULLVP) { 781 vp = un->un_lowervp; 782 } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) { 783 vp = un->un_lowervp; 784 vap = &va; 785 } else { 786 vp = NULLVP; 787 } 788 789 if (vp != NULLVP) { 790 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 791 if (error) 792 return (error); 793 union_newsize(ap->a_vp, VNOVAL, vap->va_size); 794 } 795 796 if ((vap != ap->a_vap) && (vap->va_type == VDIR)) 797 ap->a_vap->va_nlink += vap->va_nlink; 798 799 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 800 return (0); 801} 802 803static int 804union_setattr(ap) 805 struct vop_setattr_args /* { 806 struct vnode *a_vp; 807 struct vattr *a_vap; 808 struct ucred *a_cred; 809 struct proc *a_p; 810 } */ *ap; 811{ 812 struct union_node *un = VTOUNION(ap->a_vp); 813 struct proc *p = ap->a_p; 814 struct vattr *vap = ap->a_vap; 815 int error; 816 817 /* 818 * Disallow write attempts on filesystems mounted read-only. 819 */ 820 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && 821 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 822 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 823 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) 824 return (EROFS); 825 826 /* 827 * Handle case of truncating lower object to zero size, 828 * by creating a zero length upper object. This is to 829 * handle the case of open with O_TRUNC and O_CREAT. 830 */ 831 if ((un->un_uppervp == NULLVP) && 832 /* assert(un->un_lowervp != NULLVP) */ 833 (un->un_lowervp->v_type == VREG)) { 834 error = union_copyup(un, (ap->a_vap->va_size != 0), 835 ap->a_cred, ap->a_p); 836 if (error) 837 return (error); 838 } 839 840 /* 841 * Try to set attributes in upper layer, 842 * otherwise return read-only filesystem error. 843 */ 844 if (un->un_uppervp != NULLVP) { 845 FIXUP(un, p); 846 error = VOP_SETATTR(un->un_uppervp, ap->a_vap, 847 ap->a_cred, ap->a_p); 848 if ((error == 0) && (ap->a_vap->va_size != VNOVAL)) 849 union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL); 850 } else { 851 error = EROFS; 852 } 853 854 return (error); 855} 856 857static int 858union_read(ap) 859 struct vop_read_args /* { 860 struct vnode *a_vp; 861 struct uio *a_uio; 862 int a_ioflag; 863 struct ucred *a_cred; 864 } */ *ap; 865{ 866 int error; 867 struct proc *p = ap->a_uio->uio_procp; 868 struct vnode *vp = OTHERVP(ap->a_vp); 869 int dolock = (vp == LOWERVP(ap->a_vp)); 870 871 if (dolock) 872 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 873 else 874 FIXUP(VTOUNION(ap->a_vp), p); 875 error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 876 if (dolock) 877 VOP_UNLOCK(vp, 0, p); 878 879 /* 880 * XXX 881 * perhaps the size of the underlying object has changed under 882 * our feet. take advantage of the offset information present 883 * in the uio structure. 884 */ 885 if (error == 0) { 886 struct union_node *un = VTOUNION(ap->a_vp); 887 off_t cur = ap->a_uio->uio_offset; 888 889 if (vp == un->un_uppervp) { 890 if (cur > un->un_uppersz) 891 union_newsize(ap->a_vp, cur, VNOVAL); 892 } else { 893 if (cur > un->un_lowersz) 894 union_newsize(ap->a_vp, VNOVAL, cur); 895 } 896 } 897 898 return (error); 899} 900 901static int 902union_write(ap) 903 struct vop_read_args /* { 904 struct vnode *a_vp; 905 struct uio *a_uio; 906 int a_ioflag; 907 struct ucred *a_cred; 908 } */ *ap; 909{ 910 int error; 911 struct vnode *vp; 912 struct union_node *un = VTOUNION(ap->a_vp); 913 struct proc *p = ap->a_uio->uio_procp; 914 915 vp = UPPERVP(ap->a_vp); 916 if (vp == NULLVP) 917 panic("union: missing upper layer in write"); 918 919 FIXUP(un, p); 920 error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 921 922 /* 923 * the size of the underlying object may be changed by the 924 * write. 925 */ 926 if (error == 0) { 927 off_t cur = ap->a_uio->uio_offset; 928 929 if (cur > un->un_uppersz) 930 union_newsize(ap->a_vp, cur, VNOVAL); 931 } 932 933 return (error); 934} 935 936static int 937union_lease(ap) 938 struct vop_lease_args /* { 939 struct vnode *a_vp; 940 struct proc *a_p; 941 struct ucred *a_cred; 942 int a_flag; 943 } */ *ap; 944{ 945 register struct vnode *ovp = OTHERVP(ap->a_vp); 946 947 ap->a_vp = ovp; 948 return (VCALL(ovp, VOFFSET(vop_lease), ap)); 949} 950 951static int 952union_ioctl(ap) 953 struct vop_ioctl_args /* { 954 struct vnode *a_vp; 955 int a_command; 956 caddr_t a_data; 957 int a_fflag; 958 struct ucred *a_cred; 959 struct proc *a_p; 960 } */ *ap; 961{ 962 register struct vnode *ovp = OTHERVP(ap->a_vp); 963 964 ap->a_vp = ovp; 965 return (VCALL(ovp, VOFFSET(vop_ioctl), ap)); 966} 967 968static int 969union_poll(ap) 970 struct vop_poll_args /* { 971 struct vnode *a_vp; 972 int a_events; 973 struct ucred *a_cred; 974 struct proc *a_p; 975 } */ *ap; 976{ 977 register struct vnode *ovp = OTHERVP(ap->a_vp); 978 979 ap->a_vp = ovp; 980 return (VCALL(ovp, VOFFSET(vop_poll), ap)); 981} 982 983static int 984union_revoke(ap) 985 struct vop_revoke_args /* { 986 struct vnode *a_vp; 987 int a_flags; 988 struct proc *a_p; 989 } */ *ap; 990{ 991 struct vnode *vp = ap->a_vp; 992 993 if (UPPERVP(vp)) 994 VOP_REVOKE(UPPERVP(vp), ap->a_flags); 995 if (LOWERVP(vp)) 996 VOP_REVOKE(LOWERVP(vp), ap->a_flags); 997 vgone(vp); 998 return (0); 999} 1000 1001static int 1002union_mmap(ap) 1003 struct vop_mmap_args /* { 1004 struct vnode *a_vp; 1005 int a_fflags; 1006 struct ucred *a_cred; 1007 struct proc *a_p; 1008 } */ *ap; 1009{ 1010 register struct vnode *ovp = OTHERVP(ap->a_vp); 1011 1012 ap->a_vp = ovp; 1013 return (VCALL(ovp, VOFFSET(vop_mmap), ap)); 1014} 1015 1016static int 1017union_fsync(ap) 1018 struct vop_fsync_args /* { 1019 struct vnode *a_vp; 1020 struct ucred *a_cred; 1021 int a_waitfor; 1022 struct proc *a_p; 1023 } */ *ap; 1024{ 1025 int error = 0; 1026 struct proc *p = ap->a_p; 1027 struct vnode *targetvp = OTHERVP(ap->a_vp); 1028 struct union_node *un; 1029 1030 if (targetvp != NULLVP) { 1031 int dolock = (targetvp == LOWERVP(ap->a_vp)); 1032 1033 un = VTOUNION(ap->a_vp); 1034 if (dolock) 1035 vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p); 1036 else { 1037 un = VTOUNION(ap->a_vp); 1038 if ((un->un_flags & UN_ULOCK) == 0 && 1039 targetvp->v_data != NULL && 1040 ((struct lock *)targetvp->v_data)->lk_lockholder 1041 == curproc->p_pid && 1042 VOP_ISLOCKED(targetvp) != 0) 1043 return 0; /* XXX */ 1044 1045 FIXUP(un, p); 1046 } 1047 1048 error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p); 1049 if (dolock) 1050 VOP_UNLOCK(targetvp, 0, p); 1051 } 1052 1053 return (error); 1054} 1055 1056static int 1057union_remove(ap) 1058 struct vop_remove_args /* { 1059 struct vnode *a_dvp; 1060 struct vnode *a_vp; 1061 struct componentname *a_cnp; 1062 } */ *ap; 1063{ 1064 struct union_node *dun = VTOUNION(ap->a_dvp); 1065 struct union_node *un = VTOUNION(ap->a_vp); 1066 struct componentname *cnp = ap->a_cnp; 1067 struct proc *p = cnp->cn_proc; 1068 int error; 1069 1070 if (dun->un_uppervp == NULLVP) 1071 panic("union remove: null upper vnode"); 1072 1073 if (un->un_uppervp != NULLVP) { 1074 struct vnode *dvp = dun->un_uppervp; 1075 struct vnode *vp = un->un_uppervp; 1076 1077 FIXUP(dun, p); 1078 dun->un_flags |= UN_KLOCK; 1079 VOP_UNLOCK(ap->a_dvp, 0, p); 1080 FIXUP(un, p); 1081 un->un_flags |= UN_KLOCK; 1082 VOP_UNLOCK(ap->a_vp, 0, p); 1083 1084 if (union_dowhiteout(un, cnp->cn_cred, p)) 1085 cnp->cn_flags |= DOWHITEOUT; 1086 error = VOP_REMOVE(dvp, vp, cnp); 1087#if 0 1088 /* XXX */ 1089 if (!error) 1090 union_removed_upper(un); 1091#endif 1092 dun->un_flags |= UN_ULOCK; 1093 un->un_flags |= UN_ULOCK; 1094 } else { 1095 FIXUP(dun, p); 1096 error = union_mkwhiteout( 1097 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount), 1098 dun->un_uppervp, ap->a_cnp, un->un_path); 1099 } 1100 1101 return (error); 1102} 1103 1104static int 1105union_link(ap) 1106 struct vop_link_args /* { 1107 struct vnode *a_tdvp; 1108 struct vnode *a_vp; 1109 struct componentname *a_cnp; 1110 } */ *ap; 1111{ 1112 struct componentname *cnp = ap->a_cnp; 1113 struct proc *p = cnp->cn_proc; 1114 struct union_node *dun = VTOUNION(ap->a_tdvp); 1115 struct vnode *vp; 1116 struct vnode *tdvp; 1117 int error = 0; 1118 1119 1120 if (ap->a_tdvp->v_op != ap->a_vp->v_op) { 1121 vp = ap->a_vp; 1122 } else { 1123 struct union_node *tun = VTOUNION(ap->a_vp); 1124 if (tun->un_uppervp == NULLVP) { 1125 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 1126 if (dun->un_uppervp == tun->un_dirvp) { 1127 dun->un_flags &= ~UN_ULOCK; 1128 VOP_UNLOCK(dun->un_uppervp, 0, p); 1129 } 1130 error = union_copyup(tun, 1, cnp->cn_cred, p); 1131 if (dun->un_uppervp == tun->un_dirvp) { 1132 vn_lock(dun->un_uppervp, 1133 LK_EXCLUSIVE | LK_RETRY, p); 1134 dun->un_flags |= UN_ULOCK; 1135 } 1136 VOP_UNLOCK(ap->a_vp, 0, p); 1137 } 1138 vp = tun->un_uppervp; 1139 } 1140 1141 tdvp = dun->un_uppervp; 1142 if (tdvp == NULLVP) 1143 error = EROFS; 1144 1145 if (error) 1146 return (error); 1147 1148 FIXUP(dun, p); 1149 dun->un_flags |= UN_KLOCK; 1150 VOP_UNLOCK(ap->a_tdvp, 0, p); 1151 1152 error = VOP_LINK(tdvp, vp, cnp); 1153 1154 dun->un_flags |= UN_ULOCK; 1155 1156 return (error); 1157} 1158 1159static int 1160union_rename(ap) 1161 struct vop_rename_args /* { 1162 struct vnode *a_fdvp; 1163 struct vnode *a_fvp; 1164 struct componentname *a_fcnp; 1165 struct vnode *a_tdvp; 1166 struct vnode *a_tvp; 1167 struct componentname *a_tcnp; 1168 } */ *ap; 1169{ 1170 int error; 1171 1172 struct vnode *fdvp = ap->a_fdvp; 1173 struct vnode *fvp = ap->a_fvp; 1174 struct vnode *tdvp = ap->a_tdvp; 1175 struct vnode *tvp = ap->a_tvp; 1176 1177 if (fdvp->v_op == union_vnodeop_p) { /* always true */ 1178 struct union_node *un = VTOUNION(fdvp); 1179 if (un->un_uppervp == NULLVP) { 1180 /* 1181 * this should never happen in normal 1182 * operation but might if there was 1183 * a problem creating the top-level shadow 1184 * directory. 1185 */ 1186 error = EXDEV; 1187 goto bad; 1188 } 1189 1190 fdvp = un->un_uppervp; 1191 VREF(fdvp); 1192 vrele(ap->a_fdvp); 1193 } 1194 1195 if (fvp->v_op == union_vnodeop_p) { /* always true */ 1196 struct union_node *un = VTOUNION(fvp); 1197 if (un->un_uppervp == NULLVP) { 1198 /* XXX: should do a copyup */ 1199 error = EXDEV; 1200 goto bad; 1201 } 1202 1203 if (un->un_lowervp != NULLVP) 1204 ap->a_fcnp->cn_flags |= DOWHITEOUT; 1205 1206 fvp = un->un_uppervp; 1207 VREF(fvp); 1208 vrele(ap->a_fvp); 1209 } 1210 1211 if (tdvp->v_op == union_vnodeop_p) { 1212 struct union_node *un = VTOUNION(tdvp); 1213 if (un->un_uppervp == NULLVP) { 1214 /* 1215 * this should never happen in normal 1216 * operation but might if there was 1217 * a problem creating the top-level shadow 1218 * directory. 1219 */ 1220 error = EXDEV; 1221 goto bad; 1222 } 1223 1224 tdvp = un->un_uppervp; 1225 VREF(tdvp); 1226 un->un_flags |= UN_KLOCK; 1227 vput(ap->a_tdvp); 1228 } 1229 1230 if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) { 1231 struct union_node *un = VTOUNION(tvp); 1232 1233 tvp = un->un_uppervp; 1234 if (tvp != NULLVP) { 1235 VREF(tvp); 1236 un->un_flags |= UN_KLOCK; 1237 } 1238 vput(ap->a_tvp); 1239 } 1240 1241 return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp)); 1242 1243bad: 1244 vrele(fdvp); 1245 vrele(fvp); 1246 vput(tdvp); 1247 if (tvp != NULLVP) 1248 vput(tvp); 1249 1250 return (error); 1251} 1252 1253static int 1254union_mkdir(ap) 1255 struct vop_mkdir_args /* { 1256 struct vnode *a_dvp; 1257 struct vnode **a_vpp; 1258 struct componentname *a_cnp; 1259 struct vattr *a_vap; 1260 } */ *ap; 1261{ 1262 struct union_node *dun = VTOUNION(ap->a_dvp); 1263 struct vnode *dvp = dun->un_uppervp; 1264 struct componentname *cnp = ap->a_cnp; 1265 struct proc *p = cnp->cn_proc; 1266 1267 if (dvp != NULLVP) { 1268 struct vnode *vp; 1269 int error; 1270 1271 FIXUP(dun, p); 1272 dun->un_flags |= UN_KLOCK; 1273 VOP_UNLOCK(ap->a_dvp, 0, p); 1274 error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap); 1275 if (error) { 1276 dun->un_flags |= UN_ULOCK; 1277 return (error); 1278 } 1279 1280 VOP_UNLOCK(dvp, 0, p); 1281 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp, 1282 NULLVP, cnp, vp, NULLVP, 1); 1283 if (error) 1284 vput(vp); 1285 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 1286 1287 return (error); 1288 } 1289 1290 return (EROFS); 1291} 1292 1293static int 1294union_rmdir(ap) 1295 struct vop_rmdir_args /* { 1296 struct vnode *a_dvp; 1297 struct vnode *a_vp; 1298 struct componentname *a_cnp; 1299 } */ *ap; 1300{ 1301 struct union_node *dun = VTOUNION(ap->a_dvp); 1302 struct union_node *un = VTOUNION(ap->a_vp); 1303 struct componentname *cnp = ap->a_cnp; 1304 struct proc *p = cnp->cn_proc; 1305 int error; 1306 1307 if (dun->un_uppervp == NULLVP) 1308 panic("union rmdir: null upper vnode"); 1309 1310 if (un->un_uppervp != NULLVP) { 1311 struct vnode *dvp = dun->un_uppervp; 1312 struct vnode *vp = un->un_uppervp; 1313 1314 FIXUP(dun, p); 1315 dun->un_flags |= UN_KLOCK; 1316 VOP_UNLOCK(ap->a_dvp, 0, p); 1317 FIXUP(un, p); 1318 un->un_flags |= UN_KLOCK; 1319 VOP_UNLOCK(ap->a_vp, 0, p); 1320 1321 if (union_dowhiteout(un, cnp->cn_cred, p)) 1322 cnp->cn_flags |= DOWHITEOUT; 1323 error = VOP_RMDIR(dvp, vp, ap->a_cnp); 1324#if 0 1325 /* XXX */ 1326 if (!error) 1327 union_removed_upper(un); 1328#endif 1329 dun->un_flags |= UN_ULOCK; 1330 un->un_flags |= UN_ULOCK; 1331 } else { 1332 FIXUP(dun, p); 1333 error = union_mkwhiteout( 1334 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount), 1335 dun->un_uppervp, ap->a_cnp, un->un_path); 1336 } 1337 1338 return (error); 1339} 1340 1341static int 1342union_symlink(ap) 1343 struct vop_symlink_args /* { 1344 struct vnode *a_dvp; 1345 struct vnode **a_vpp; 1346 struct componentname *a_cnp; 1347 struct vattr *a_vap; 1348 char *a_target; 1349 } */ *ap; 1350{ 1351 struct union_node *dun = VTOUNION(ap->a_dvp); 1352 struct vnode *dvp = dun->un_uppervp; 1353 struct componentname *cnp = ap->a_cnp; 1354 struct proc *p = cnp->cn_proc; 1355 1356 if (dvp != NULLVP) { 1357 struct vnode *vp; 1358 int error; 1359 1360 FIXUP(dun, p); 1361 dun->un_flags |= UN_KLOCK; 1362 VOP_UNLOCK(ap->a_dvp, 0, p); 1363 error = VOP_SYMLINK(dvp, &vp, cnp, ap->a_vap, ap->a_target); 1364 dun->un_flags |= UN_ULOCK; 1365 *ap->a_vpp = NULLVP; 1366 return (error); 1367 } 1368 1369 return (EROFS); 1370} 1371 1372/* 1373 * union_readdir works in concert with getdirentries and 1374 * readdir(3) to provide a list of entries in the unioned 1375 * directories. getdirentries is responsible for walking 1376 * down the union stack. readdir(3) is responsible for 1377 * eliminating duplicate names from the returned data stream. 1378 */ 1379static int 1380union_readdir(ap) 1381 struct vop_readdir_args /* { 1382 struct vnode *a_vp; 1383 struct uio *a_uio; 1384 struct ucred *a_cred; 1385 int *a_eofflag; 1386 u_long *a_cookies; 1387 int a_ncookies; 1388 } */ *ap; 1389{ 1390 struct union_node *un = VTOUNION(ap->a_vp); 1391 struct vnode *uvp = un->un_uppervp; 1392 struct proc *p = ap->a_uio->uio_procp; 1393 1394 if (uvp == NULLVP) 1395 return (0); 1396 1397 FIXUP(un, p); 1398 ap->a_vp = uvp; 1399 return (VCALL(uvp, VOFFSET(vop_readdir), ap)); 1400} 1401 1402static int 1403union_readlink(ap) 1404 struct vop_readlink_args /* { 1405 struct vnode *a_vp; 1406 struct uio *a_uio; 1407 struct ucred *a_cred; 1408 } */ *ap; 1409{ 1410 int error; 1411 struct uio *uio = ap->a_uio; 1412 struct proc *p = uio->uio_procp; 1413 struct vnode *vp = OTHERVP(ap->a_vp); 1414 int dolock = (vp == LOWERVP(ap->a_vp)); 1415 1416 if (dolock) 1417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1418 else 1419 FIXUP(VTOUNION(ap->a_vp), p); 1420 ap->a_vp = vp; 1421 error = VCALL(vp, VOFFSET(vop_readlink), ap); 1422 if (dolock) 1423 VOP_UNLOCK(vp, 0, p); 1424 1425 return (error); 1426} 1427 1428static int 1429union_abortop(ap) 1430 struct vop_abortop_args /* { 1431 struct vnode *a_dvp; 1432 struct componentname *a_cnp; 1433 } */ *ap; 1434{ 1435 int error; 1436 struct componentname *cnp = ap->a_cnp; 1437 struct proc *p = cnp->cn_proc; 1438 struct vnode *vp = OTHERVP(ap->a_dvp); 1439 struct union_node *un = VTOUNION(ap->a_dvp); 1440 int islocked = un->un_flags & UN_LOCKED; 1441 int dolock = (vp == LOWERVP(ap->a_dvp)); 1442 1443 if (islocked) { 1444 if (dolock) 1445 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1446 else 1447 FIXUP(VTOUNION(ap->a_dvp), p); 1448 } 1449 ap->a_dvp = vp; 1450 error = VCALL(vp, VOFFSET(vop_abortop), ap); 1451 if (islocked && dolock) 1452 VOP_UNLOCK(vp, 0, p); 1453 1454 return (error); 1455} 1456 1457static int 1458union_inactive(ap) 1459 struct vop_inactive_args /* { 1460 struct vnode *a_vp; 1461 struct proc *a_p; 1462 } */ *ap; 1463{ 1464 struct vnode *vp = ap->a_vp; 1465 struct proc *p = ap->a_p; 1466 struct union_node *un = VTOUNION(vp); 1467 struct vnode **vpp; 1468 1469 /* 1470 * Do nothing (and _don't_ bypass). 1471 * Wait to vrele lowervp until reclaim, 1472 * so that until then our union_node is in the 1473 * cache and reusable. 1474 * 1475 * NEEDSWORK: Someday, consider inactive'ing 1476 * the lowervp and then trying to reactivate it 1477 * with capabilities (v_id) 1478 * like they do in the name lookup cache code. 1479 * That's too much work for now. 1480 */ 1481 1482 if (un->un_dircache != 0) { 1483 for (vpp = un->un_dircache; *vpp != NULLVP; vpp++) 1484 vrele(*vpp); 1485 free(un->un_dircache, M_TEMP); 1486 un->un_dircache = 0; 1487 } 1488 1489 VOP_UNLOCK(vp, 0, p); 1490 1491 if ((un->un_flags & UN_CACHED) == 0) 1492 vgone(vp); 1493 1494 return (0); 1495} 1496 1497static int 1498union_reclaim(ap) 1499 struct vop_reclaim_args /* { 1500 struct vnode *a_vp; 1501 } */ *ap; 1502{ 1503 1504 union_freevp(ap->a_vp); 1505 1506 return (0); 1507} 1508 1509static int 1510union_lock(ap) 1511 struct vop_lock_args *ap; 1512{ 1513 struct vnode *vp = ap->a_vp; 1514 struct proc *p = ap->a_p; 1515 int flags = ap->a_flags; 1516 struct union_node *un; 1517 int error; 1518 1519 vop_nolock(ap); 1520 /* 1521 * Need to do real lockmgr-style locking here. 1522 * in the mean time, draining won't work quite right, 1523 * which could lead to a few race conditions. 1524 * the following test was here, but is not quite right, we 1525 * still need to take the lock: 1526 if ((flags & LK_TYPE_MASK) == LK_DRAIN) 1527 return (0); 1528 */ 1529 flags &= ~LK_INTERLOCK; 1530 1531start: 1532 un = VTOUNION(vp); 1533 1534 if (un->un_uppervp != NULLVP) { 1535 if (((un->un_flags & UN_ULOCK) == 0) && 1536 (vp->v_usecount != 0)) { 1537 error = vn_lock(un->un_uppervp, flags, p); 1538 if (error) 1539 return (error); 1540 un->un_flags |= UN_ULOCK; 1541 } 1542#ifdef DIAGNOSTIC 1543 if (un->un_flags & UN_KLOCK) { 1544 vprint("dangling upper lock", vp); 1545 panic("union: dangling upper lock"); 1546 } 1547#endif 1548 } 1549 1550 if (un->un_flags & UN_LOCKED) { 1551#ifdef DIAGNOSTIC 1552 if (curproc && un->un_pid == curproc->p_pid && 1553 un->un_pid > -1 && curproc->p_pid > -1) 1554 panic("union: locking against myself"); 1555#endif 1556 un->un_flags |= UN_WANT; 1557 tsleep((caddr_t)&un->un_flags, PINOD, "unionlk2", 0); 1558 goto start; 1559 } 1560 1561#ifdef DIAGNOSTIC 1562 if (curproc) 1563 un->un_pid = curproc->p_pid; 1564 else 1565 un->un_pid = -1; 1566#endif 1567 1568 un->un_flags |= UN_LOCKED; 1569 return (0); 1570} 1571 1572/* 1573 * When operations want to vput() a union node yet retain a lock on 1574 * the upper vnode (say, to do some further operations like link(), 1575 * mkdir(), ...), they set UN_KLOCK on the union node, then call 1576 * vput() which calls VOP_UNLOCK() and comes here. union_unlock() 1577 * unlocks the union node (leaving the upper vnode alone), clears the 1578 * KLOCK flag, and then returns to vput(). The caller then does whatever 1579 * is left to do with the upper vnode, and ensures that it gets unlocked. 1580 * 1581 * If UN_KLOCK isn't set, then the upper vnode is unlocked here. 1582 */ 1583static int 1584union_unlock(ap) 1585 struct vop_unlock_args /* { 1586 struct vnode *a_vp; 1587 int a_flags; 1588 struct proc *a_p; 1589 } */ *ap; 1590{ 1591 struct union_node *un = VTOUNION(ap->a_vp); 1592 struct proc *p = ap->a_p; 1593 1594#ifdef DIAGNOSTIC 1595 if ((un->un_flags & UN_LOCKED) == 0) 1596 panic("union: unlock unlocked node"); 1597 if (curproc && un->un_pid != curproc->p_pid && 1598 curproc->p_pid > -1 && un->un_pid > -1) 1599 panic("union: unlocking other process's union node"); 1600#endif 1601 1602 un->un_flags &= ~UN_LOCKED; 1603 1604 if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK) 1605 VOP_UNLOCK(un->un_uppervp, 0, p); 1606 1607 un->un_flags &= ~(UN_ULOCK|UN_KLOCK); 1608 1609 if (un->un_flags & UN_WANT) { 1610 un->un_flags &= ~UN_WANT; 1611 wakeup((caddr_t) &un->un_flags); 1612 } 1613 1614#ifdef DIAGNOSTIC 1615 un->un_pid = 0; 1616#endif 1617 vop_nounlock(ap); 1618 1619 return (0); 1620} 1621 1622static int 1623union_bmap(ap) 1624 struct vop_bmap_args /* { 1625 struct vnode *a_vp; 1626 daddr_t a_bn; 1627 struct vnode **a_vpp; 1628 daddr_t *a_bnp; 1629 int *a_runp; 1630 int *a_runb; 1631 } */ *ap; 1632{ 1633 int error; 1634 struct proc *p = curproc; /* XXX */ 1635 struct vnode *vp = OTHERVP(ap->a_vp); 1636 int dolock = (vp == LOWERVP(ap->a_vp)); 1637 1638 if (dolock) 1639 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1640 else 1641 FIXUP(VTOUNION(ap->a_vp), p); 1642 ap->a_vp = vp; 1643 error = VCALL(vp, VOFFSET(vop_bmap), ap); 1644 if (dolock) 1645 VOP_UNLOCK(vp, 0, p); 1646 1647 return (error); 1648} 1649 1650static int 1651union_print(ap) 1652 struct vop_print_args /* { 1653 struct vnode *a_vp; 1654 } */ *ap; 1655{ 1656 struct vnode *vp = ap->a_vp; 1657 1658 printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n", 1659 vp, UPPERVP(vp), LOWERVP(vp)); 1660 if (UPPERVP(vp) != NULLVP) 1661 vprint("union: upper", UPPERVP(vp)); 1662 if (LOWERVP(vp) != NULLVP) 1663 vprint("union: lower", LOWERVP(vp)); 1664 1665 return (0); 1666} 1667 1668static int 1669union_islocked(ap) 1670 struct vop_islocked_args /* { 1671 struct vnode *a_vp; 1672 } */ *ap; 1673{ 1674 1675 return ((VTOUNION(ap->a_vp)->un_flags & UN_LOCKED) ? 1 : 0); 1676} 1677 1678static int 1679union_pathconf(ap) 1680 struct vop_pathconf_args /* { 1681 struct vnode *a_vp; 1682 int a_name; 1683 int *a_retval; 1684 } */ *ap; 1685{ 1686 int error; 1687 struct proc *p = curproc; /* XXX */ 1688 struct vnode *vp = OTHERVP(ap->a_vp); 1689 int dolock = (vp == LOWERVP(ap->a_vp)); 1690 1691 if (dolock) 1692 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1693 else 1694 FIXUP(VTOUNION(ap->a_vp), p); 1695 ap->a_vp = vp; 1696 error = VCALL(vp, VOFFSET(vop_pathconf), ap); 1697 if (dolock) 1698 VOP_UNLOCK(vp, 0, p); 1699 1700 return (error); 1701} 1702 1703static int 1704union_advlock(ap) 1705 struct vop_advlock_args /* { 1706 struct vnode *a_vp; 1707 caddr_t a_id; 1708 int a_op; 1709 struct flock *a_fl; 1710 int a_flags; 1711 } */ *ap; 1712{ 1713 register struct vnode *ovp = OTHERVP(ap->a_vp); 1714 1715 ap->a_vp = ovp; 1716 return (VCALL(ovp, VOFFSET(vop_advlock), ap)); 1717} 1718 1719 1720/* 1721 * XXX - vop_strategy must be hand coded because it has no 1722 * vnode in its arguments. 1723 * This goes away with a merged VM/buffer cache. 1724 */ 1725static int 1726union_strategy(ap) 1727 struct vop_strategy_args /* {
| 39 */ 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/proc.h> 44#include <sys/fcntl.h> 45#include <sys/stat.h> 46#include <sys/kernel.h> 47#include <sys/vnode.h> 48#include <sys/mount.h> 49#include <sys/namei.h> 50#include <sys/malloc.h> 51#include <sys/buf.h> 52#include <sys/lock.h> 53#include <miscfs/union/union.h> 54 55#define FIXUP(un, p) { \ 56 if (((un)->un_flags & UN_ULOCK) == 0) { \ 57 union_fixup(un, p); \ 58 } \ 59} 60 61static int union_abortop __P((struct vop_abortop_args *ap)); 62static int union_access __P((struct vop_access_args *ap)); 63static int union_advlock __P((struct vop_advlock_args *ap)); 64static int union_bmap __P((struct vop_bmap_args *ap)); 65static int union_close __P((struct vop_close_args *ap)); 66static int union_create __P((struct vop_create_args *ap)); 67static void union_fixup __P((struct union_node *un, struct proc *p)); 68static int union_fsync __P((struct vop_fsync_args *ap)); 69static int union_getattr __P((struct vop_getattr_args *ap)); 70static int union_inactive __P((struct vop_inactive_args *ap)); 71static int union_ioctl __P((struct vop_ioctl_args *ap)); 72static int union_islocked __P((struct vop_islocked_args *ap)); 73static int union_lease __P((struct vop_lease_args *ap)); 74static int union_link __P((struct vop_link_args *ap)); 75static int union_lock __P((struct vop_lock_args *ap)); 76static int union_lookup __P((struct vop_lookup_args *ap)); 77static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvpp, 78 struct vnode **vpp, 79 struct componentname *cnp)); 80static int union_mkdir __P((struct vop_mkdir_args *ap)); 81static int union_mknod __P((struct vop_mknod_args *ap)); 82static int union_mmap __P((struct vop_mmap_args *ap)); 83static int union_open __P((struct vop_open_args *ap)); 84static int union_pathconf __P((struct vop_pathconf_args *ap)); 85static int union_print __P((struct vop_print_args *ap)); 86static int union_read __P((struct vop_read_args *ap)); 87static int union_readdir __P((struct vop_readdir_args *ap)); 88static int union_readlink __P((struct vop_readlink_args *ap)); 89static int union_reclaim __P((struct vop_reclaim_args *ap)); 90static int union_remove __P((struct vop_remove_args *ap)); 91static int union_rename __P((struct vop_rename_args *ap)); 92static int union_revoke __P((struct vop_revoke_args *ap)); 93static int union_rmdir __P((struct vop_rmdir_args *ap)); 94static int union_poll __P((struct vop_poll_args *ap)); 95static int union_setattr __P((struct vop_setattr_args *ap)); 96static int union_strategy __P((struct vop_strategy_args *ap)); 97static int union_symlink __P((struct vop_symlink_args *ap)); 98static int union_unlock __P((struct vop_unlock_args *ap)); 99static int union_whiteout __P((struct vop_whiteout_args *ap)); 100static int union_write __P((struct vop_read_args *ap)); 101 102static void 103union_fixup(un, p) 104 struct union_node *un; 105 struct proc *p; 106{ 107 108 vn_lock(un->un_uppervp, LK_EXCLUSIVE | LK_RETRY, p); 109 un->un_flags |= UN_ULOCK; 110} 111 112static int 113union_lookup1(udvp, dvpp, vpp, cnp) 114 struct vnode *udvp; 115 struct vnode **dvpp; 116 struct vnode **vpp; 117 struct componentname *cnp; 118{ 119 int error; 120 struct proc *p = cnp->cn_proc; 121 struct vnode *tdvp; 122 struct vnode *dvp; 123 struct mount *mp; 124 125 dvp = *dvpp; 126 127 /* 128 * If stepping up the directory tree, check for going 129 * back across the mount point, in which case do what 130 * lookup would do by stepping back down the mount 131 * hierarchy. 132 */ 133 if (cnp->cn_flags & ISDOTDOT) { 134 while ((dvp != udvp) && (dvp->v_flag & VROOT)) { 135 /* 136 * Don't do the NOCROSSMOUNT check 137 * at this level. By definition, 138 * union fs deals with namespaces, not 139 * filesystems. 140 */ 141 tdvp = dvp; 142 *dvpp = dvp = dvp->v_mount->mnt_vnodecovered; 143 vput(tdvp); 144 VREF(dvp); 145 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 146 } 147 } 148 149 error = VOP_LOOKUP(dvp, &tdvp, cnp); 150 if (error) 151 return (error); 152 153 /* 154 * The parent directory will have been unlocked, unless lookup 155 * found the last component. In which case, re-lock the node 156 * here to allow it to be unlocked again (phew) in union_lookup. 157 */ 158 if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN)) 159 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 160 161 dvp = tdvp; 162 163 /* 164 * Lastly check if the current node is a mount point in 165 * which case walk up the mount hierarchy making sure not to 166 * bump into the root of the mount tree (ie. dvp != udvp). 167 */ 168 while (dvp != udvp && (dvp->v_type == VDIR) && 169 (mp = dvp->v_mountedhere)) { 170 171 if (vfs_busy(mp, 0, 0, p)) 172 continue; 173 174 error = VFS_ROOT(mp, &tdvp); 175 vfs_unbusy(mp, p); 176 if (error) { 177 vput(dvp); 178 return (error); 179 } 180 181 vput(dvp); 182 dvp = tdvp; 183 } 184 185 *vpp = dvp; 186 return (0); 187} 188 189static int 190union_lookup(ap) 191 struct vop_lookup_args /* { 192 struct vnodeop_desc *a_desc; 193 struct vnode *a_dvp; 194 struct vnode **a_vpp; 195 struct componentname *a_cnp; 196 } */ *ap; 197{ 198 int error; 199 int uerror, lerror; 200 struct vnode *uppervp, *lowervp; 201 struct vnode *upperdvp, *lowerdvp; 202 struct vnode *dvp = ap->a_dvp; 203 struct union_node *dun = VTOUNION(dvp); 204 struct componentname *cnp = ap->a_cnp; 205 struct proc *p = cnp->cn_proc; 206 int lockparent = cnp->cn_flags & LOCKPARENT; 207 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount); 208 struct ucred *saved_cred; 209 int iswhiteout; 210 struct vattr va; 211 212 213 /* 214 * Disallow write attemps to the filesystem mounted read-only. 215 */ 216 if ((cnp->cn_flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 217 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 218 return (EROFS); 219 220#ifdef notyet 221 if (cnp->cn_namelen == 3 && 222 cnp->cn_nameptr[2] == '.' && 223 cnp->cn_nameptr[1] == '.' && 224 cnp->cn_nameptr[0] == '.') { 225 dvp = *ap->a_vpp = LOWERVP(ap->a_dvp); 226 if (dvp == NULLVP) 227 return (ENOENT); 228 VREF(dvp); 229 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 230 if (!lockparent || !(cnp->cn_flags & ISLASTCN)) 231 VOP_UNLOCK(ap->a_dvp, 0, p); 232 return (0); 233 } 234#endif 235 236 cnp->cn_flags |= LOCKPARENT; 237 238 upperdvp = dun->un_uppervp; 239 lowerdvp = dun->un_lowervp; 240 uppervp = NULLVP; 241 lowervp = NULLVP; 242 iswhiteout = 0; 243 244 if (cnp->cn_flags & ISDOTDOT) { 245 if (upperdvp != NULL) 246 VREF(upperdvp); 247 if (lowerdvp != NULL) 248 VREF(lowerdvp); 249 } 250 251 /* 252 * do the lookup in the upper level. 253 * if that level comsumes additional pathnames, 254 * then assume that something special is going 255 * on and just return that vnode. 256 */ 257 if (upperdvp != NULLVP) { 258 FIXUP(dun, p); 259 /* 260 * If we're doing `..' in the underlying filesystem, 261 * we must drop our lock on the union node before 262 * going up the tree in the lower file system--if we block 263 * on the lowervp lock, and that's held by someone else 264 * coming down the tree and who's waiting for our lock, 265 * we would be hosed. 266 */ 267 if (cnp->cn_flags & ISDOTDOT) { 268 /* retain lock on underlying VP: */ 269 dun->un_flags |= UN_KLOCK; 270 VOP_UNLOCK(dvp, 0, p); 271 } 272 uerror = union_lookup1(um->um_uppervp, &upperdvp, 273 &uppervp, cnp); 274 /* 275 * Disallow write attemps to the filesystem mounted read-only. 276 */ 277 if (uerror == EJUSTRETURN && (cnp->cn_flags & ISLASTCN) && 278 (dvp->v_mount->mnt_flag & MNT_RDONLY) && 279 (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) { 280 if (!lockparent) 281 cnp->cn_flags &= ~LOCKPARENT; 282 return (EROFS); 283 } 284 285 if (cnp->cn_flags & ISDOTDOT) { 286 if (dun->un_uppervp == upperdvp) { 287 /* 288 * We got the underlying bugger back locked... 289 * now take back the union node lock. Since we 290 * hold the uppervp lock, we can diddle union 291 * locking flags at will. :) 292 */ 293 dun->un_flags |= UN_ULOCK; 294 } 295 /* 296 * If upperdvp got swapped out, it means we did 297 * some mount point magic, and we do not have 298 * dun->un_uppervp locked currently--so we get it 299 * locked here (don't set the UN_ULOCK flag). 300 */ 301 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 302 } 303 304 /*if (uppervp == upperdvp) 305 dun->un_flags |= UN_KLOCK;*/ 306 307 if (cnp->cn_consume != 0) { 308 *ap->a_vpp = uppervp; 309 if (!lockparent) 310 cnp->cn_flags &= ~LOCKPARENT; 311 error = uerror; 312 goto out; 313 } 314 if (uerror == ENOENT || uerror == EJUSTRETURN) { 315 if (cnp->cn_flags & ISWHITEOUT) { 316 iswhiteout = 1; 317 } else if (lowerdvp != NULLVP) { 318 lerror = VOP_GETATTR(upperdvp, &va, 319 cnp->cn_cred, cnp->cn_proc); 320 if (lerror == 0 && (va.va_flags & OPAQUE)) 321 iswhiteout = 1; 322 } 323 } 324 } else { 325 uerror = ENOENT; 326 } 327 328 /* 329 * in a similar way to the upper layer, do the lookup 330 * in the lower layer. this time, if there is some 331 * component magic going on, then vput whatever we got 332 * back from the upper layer and return the lower vnode 333 * instead. 334 */ 335 if (lowerdvp != NULLVP && !iswhiteout) { 336 int nameiop; 337 338 vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p); 339 340 /* 341 * Only do a LOOKUP on the bottom node, since 342 * we won't be making changes to it anyway. 343 */ 344 nameiop = cnp->cn_nameiop; 345 cnp->cn_nameiop = LOOKUP; 346 if (um->um_op == UNMNT_BELOW) { 347 saved_cred = cnp->cn_cred; 348 cnp->cn_cred = um->um_cred; 349 } 350 /* 351 * We shouldn't have to worry about locking interactions 352 * between the lower layer and our union layer (w.r.t. 353 * `..' processing) because we don't futz with lowervp 354 * locks in the union-node instantiation code path. 355 */ 356 lerror = union_lookup1(um->um_lowervp, &lowerdvp, 357 &lowervp, cnp); 358 if (um->um_op == UNMNT_BELOW) 359 cnp->cn_cred = saved_cred; 360 cnp->cn_nameiop = nameiop; 361 362 if (lowervp != lowerdvp) 363 VOP_UNLOCK(lowerdvp, 0, p); 364 365 if (cnp->cn_consume != 0 || lerror == EACCES) { 366 if (lerror == EACCES) 367 lowervp = NULLVP; 368 if (uppervp != NULLVP) { 369 if (uppervp == upperdvp) 370 vrele(uppervp); 371 else 372 vput(uppervp); 373 uppervp = NULLVP; 374 } 375 *ap->a_vpp = lowervp; 376 if (!lockparent) 377 cnp->cn_flags &= ~LOCKPARENT; 378 error = lerror; 379 goto out; 380 } 381 } else { 382 lerror = ENOENT; 383 if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) { 384 lowervp = LOWERVP(dun->un_pvp); 385 if (lowervp != NULLVP) { 386 VREF(lowervp); 387 vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p); 388 lerror = 0; 389 } 390 } 391 } 392 393 if (!lockparent) 394 cnp->cn_flags &= ~LOCKPARENT; 395 396 /* 397 * at this point, we have uerror and lerror indicating 398 * possible errors with the lookups in the upper and lower 399 * layers. additionally, uppervp and lowervp are (locked) 400 * references to existing vnodes in the upper and lower layers. 401 * 402 * there are now three cases to consider. 403 * 1. if both layers returned an error, then return whatever 404 * error the upper layer generated. 405 * 406 * 2. if the top layer failed and the bottom layer succeeded 407 * then two subcases occur. 408 * a. the bottom vnode is not a directory, in which 409 * case just return a new union vnode referencing 410 * an empty top layer and the existing bottom layer. 411 * b. the bottom vnode is a directory, in which case 412 * create a new directory in the top-level and 413 * continue as in case 3. 414 * 415 * 3. if the top layer succeeded then return a new union 416 * vnode referencing whatever the new top layer and 417 * whatever the bottom layer returned. 418 */ 419 420 *ap->a_vpp = NULLVP; 421 422 /* case 1. */ 423 if ((uerror != 0) && (lerror != 0)) { 424 error = uerror; 425 goto out; 426 } 427 428 /* case 2. */ 429 if (uerror != 0 /* && (lerror == 0) */ ) { 430 if (lowervp->v_type == VDIR) { /* case 2b. */ 431 dun->un_flags &= ~UN_ULOCK; 432 VOP_UNLOCK(upperdvp, 0, p); 433 uerror = union_mkshadow(um, upperdvp, cnp, &uppervp); 434 vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY, p); 435 dun->un_flags |= UN_ULOCK; 436 437 if (uerror) { 438 if (lowervp != NULLVP) { 439 vput(lowervp); 440 lowervp = NULLVP; 441 } 442 error = uerror; 443 goto out; 444 } 445 } 446 } 447 448 if (lowervp != NULLVP) 449 VOP_UNLOCK(lowervp, 0, p); 450 451 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, 452 uppervp, lowervp, 1); 453 454 if (error) { 455 if (uppervp != NULLVP) 456 vput(uppervp); 457 if (lowervp != NULLVP) 458 vrele(lowervp); 459 } else { 460 if (*ap->a_vpp != dvp) 461 if (!lockparent || !(cnp->cn_flags & ISLASTCN)) 462 VOP_UNLOCK(dvp, 0, p); 463#ifdef DIAGNOSTIC 464 if (cnp->cn_namelen == 1 && 465 cnp->cn_nameptr[0] == '.' && 466 *ap->a_vpp != dvp) { 467 panic("union_lookup returning . (%p) not same as startdir (%p)", 468 ap->a_vpp, dvp); 469 } 470#endif 471 } 472 473out: 474 if (cnp->cn_flags & ISDOTDOT) { 475 if (upperdvp != NULL) 476 vrele(upperdvp); 477 if (lowerdvp != NULL) 478 vrele(lowerdvp); 479 } 480 481 return (error); 482} 483 484static int 485union_create(ap) 486 struct vop_create_args /* { 487 struct vnode *a_dvp; 488 struct vnode **a_vpp; 489 struct componentname *a_cnp; 490 struct vattr *a_vap; 491 } */ *ap; 492{ 493 struct union_node *dun = VTOUNION(ap->a_dvp); 494 struct vnode *dvp = dun->un_uppervp; 495 struct componentname *cnp = ap->a_cnp; 496 struct proc *p = cnp->cn_proc; 497 498 if (dvp != NULLVP) { 499 struct vnode *vp; 500 struct mount *mp; 501 int error; 502 503 FIXUP(dun, p); 504 505 dun->un_flags |= UN_KLOCK; 506 VOP_UNLOCK(ap->a_dvp, 0, p); 507 error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap); 508 if (error) { 509 dun->un_flags |= UN_ULOCK; 510 return (error); 511 } 512 513 mp = ap->a_dvp->v_mount; 514 VOP_UNLOCK(dvp, 0, p); 515 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp, 516 NULLVP, 1); 517 if (error) 518 vput(vp); 519 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 520 return (error); 521 } 522 523 return (EROFS); 524} 525 526static int 527union_whiteout(ap) 528 struct vop_whiteout_args /* { 529 struct vnode *a_dvp; 530 struct componentname *a_cnp; 531 int a_flags; 532 } */ *ap; 533{ 534 struct union_node *un = VTOUNION(ap->a_dvp); 535 struct componentname *cnp = ap->a_cnp; 536 struct proc *p = cnp->cn_proc; 537 538 if (un->un_uppervp == NULLVP) 539 return (EOPNOTSUPP); 540 541 FIXUP(un, p); 542 return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags)); 543} 544 545static int 546union_mknod(ap) 547 struct vop_mknod_args /* { 548 struct vnode *a_dvp; 549 struct vnode **a_vpp; 550 struct componentname *a_cnp; 551 struct vattr *a_vap; 552 } */ *ap; 553{ 554 struct union_node *dun = VTOUNION(ap->a_dvp); 555 struct vnode *dvp = dun->un_uppervp; 556 struct componentname *cnp = ap->a_cnp; 557 struct proc *p = cnp->cn_proc; 558 559 if (dvp != NULLVP) { 560 struct vnode *vp; 561 struct mount *mp; 562 int error; 563 564 FIXUP(dun, p); 565 566 dun->un_flags |= UN_KLOCK; 567 VOP_UNLOCK(ap->a_dvp, 0, p); 568 error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap); 569 if (error) { 570 dun->un_flags |= UN_ULOCK; 571 return (error); 572 } 573 574 if (vp != NULLVP) { 575 mp = ap->a_dvp->v_mount; 576 VOP_UNLOCK(dvp, 0, p); 577 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, 578 cnp, vp, NULLVP, 1); 579 if (error) 580 vput(vp); 581 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 582 } else { 583 dun->un_flags |= UN_ULOCK; 584 } 585 return (error); 586 } 587 588 return (EROFS); 589} 590 591static int 592union_open(ap) 593 struct vop_open_args /* { 594 struct vnodeop_desc *a_desc; 595 struct vnode *a_vp; 596 int a_mode; 597 struct ucred *a_cred; 598 struct proc *a_p; 599 } */ *ap; 600{ 601 struct union_node *un = VTOUNION(ap->a_vp); 602 struct vnode *tvp; 603 int mode = ap->a_mode; 604 struct ucred *cred = ap->a_cred; 605 struct proc *p = ap->a_p; 606 int error; 607 608 /* 609 * If there is an existing upper vp then simply open that. 610 */ 611 tvp = un->un_uppervp; 612 if (tvp == NULLVP) { 613 /* 614 * If the lower vnode is being opened for writing, then 615 * copy the file contents to the upper vnode and open that, 616 * otherwise can simply open the lower vnode. 617 */ 618 tvp = un->un_lowervp; 619 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) { 620 error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p); 621 if (error == 0) 622 error = VOP_OPEN(un->un_uppervp, mode, cred, p); 623 return (error); 624 } 625 626 /* 627 * Just open the lower vnode 628 */ 629 un->un_openl++; 630 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); 631 error = VOP_OPEN(tvp, mode, cred, p); 632 VOP_UNLOCK(tvp, 0, p); 633 634 return (error); 635 } 636 637 FIXUP(un, p); 638 639 error = VOP_OPEN(tvp, mode, cred, p); 640 641 return (error); 642} 643 644static int 645union_close(ap) 646 struct vop_close_args /* { 647 struct vnode *a_vp; 648 int a_fflag; 649 struct ucred *a_cred; 650 struct proc *a_p; 651 } */ *ap; 652{ 653 struct union_node *un = VTOUNION(ap->a_vp); 654 struct vnode *vp; 655 656 if ((vp = un->un_uppervp) == NULLVP) { 657#ifdef UNION_DIAGNOSTIC 658 if (un->un_openl <= 0) 659 panic("union: un_openl cnt"); 660#endif 661 --un->un_openl; 662 vp = un->un_lowervp; 663 } 664 665 ap->a_vp = vp; 666 return (VCALL(vp, VOFFSET(vop_close), ap)); 667} 668 669/* 670 * Check access permission on the union vnode. 671 * The access check being enforced is to check 672 * against both the underlying vnode, and any 673 * copied vnode. This ensures that no additional 674 * file permissions are given away simply because 675 * the user caused an implicit file copy. 676 */ 677static int 678union_access(ap) 679 struct vop_access_args /* { 680 struct vnodeop_desc *a_desc; 681 struct vnode *a_vp; 682 int a_mode; 683 struct ucred *a_cred; 684 struct proc *a_p; 685 } */ *ap; 686{ 687 struct union_node *un = VTOUNION(ap->a_vp); 688 struct proc *p = ap->a_p; 689 int error = EACCES; 690 struct vnode *vp; 691 struct vnode *savedvp; 692 693 /* 694 * Disallow write attempts on filesystems mounted read-only. 695 */ 696 if (ap->a_mode & VWRITE && (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) { 697 switch (ap->a_vp->v_type) { 698 case VREG: case VDIR: case VLNK: 699 return (EROFS); 700 } 701 } 702 if ((vp = un->un_uppervp) != NULLVP) { 703 FIXUP(un, p); 704 ap->a_vp = vp; 705 return (VCALL(vp, VOFFSET(vop_access), ap)); 706 } 707 708 if ((vp = un->un_lowervp) != NULLVP) { 709 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 710 savedvp = ap->a_vp; 711 ap->a_vp = vp; 712 error = VCALL(vp, VOFFSET(vop_access), ap); 713 if (error == 0) { 714 struct union_mount *um = MOUNTTOUNIONMOUNT(savedvp->v_mount); 715 716 if (um->um_op == UNMNT_BELOW) { 717 ap->a_cred = um->um_cred; 718 error = VCALL(vp, VOFFSET(vop_access), ap); 719 } 720 } 721 VOP_UNLOCK(vp, 0, p); 722 if (error) 723 return (error); 724 } 725 726 return (error); 727} 728 729/* 730 * We handle getattr only to change the fsid and 731 * track object sizes 732 */ 733static int 734union_getattr(ap) 735 struct vop_getattr_args /* { 736 struct vnode *a_vp; 737 struct vattr *a_vap; 738 struct ucred *a_cred; 739 struct proc *a_p; 740 } */ *ap; 741{ 742 int error; 743 struct union_node *un = VTOUNION(ap->a_vp); 744 struct vnode *vp = un->un_uppervp; 745 struct proc *p = ap->a_p; 746 struct vattr *vap; 747 struct vattr va; 748 749 750 /* 751 * Some programs walk the filesystem hierarchy by counting 752 * links to directories to avoid stat'ing all the time. 753 * This means the link count on directories needs to be "correct". 754 * The only way to do that is to call getattr on both layers 755 * and fix up the link count. The link count will not necessarily 756 * be accurate but will be large enough to defeat the tree walkers. 757 */ 758 759 vap = ap->a_vap; 760 761 vp = un->un_uppervp; 762 if (vp != NULLVP) { 763 /* 764 * It's not clear whether VOP_GETATTR is to be 765 * called with the vnode locked or not. stat() calls 766 * it with (vp) locked, and fstat calls it with 767 * (vp) unlocked. 768 * In the mean time, compensate here by checking 769 * the union_node's lock flag. 770 */ 771 if (un->un_flags & UN_LOCKED) 772 FIXUP(un, p); 773 774 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 775 if (error) 776 return (error); 777 union_newsize(ap->a_vp, vap->va_size, VNOVAL); 778 } 779 780 if (vp == NULLVP) { 781 vp = un->un_lowervp; 782 } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) { 783 vp = un->un_lowervp; 784 vap = &va; 785 } else { 786 vp = NULLVP; 787 } 788 789 if (vp != NULLVP) { 790 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); 791 if (error) 792 return (error); 793 union_newsize(ap->a_vp, VNOVAL, vap->va_size); 794 } 795 796 if ((vap != ap->a_vap) && (vap->va_type == VDIR)) 797 ap->a_vap->va_nlink += vap->va_nlink; 798 799 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 800 return (0); 801} 802 803static int 804union_setattr(ap) 805 struct vop_setattr_args /* { 806 struct vnode *a_vp; 807 struct vattr *a_vap; 808 struct ucred *a_cred; 809 struct proc *a_p; 810 } */ *ap; 811{ 812 struct union_node *un = VTOUNION(ap->a_vp); 813 struct proc *p = ap->a_p; 814 struct vattr *vap = ap->a_vap; 815 int error; 816 817 /* 818 * Disallow write attempts on filesystems mounted read-only. 819 */ 820 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && 821 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 822 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 823 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) 824 return (EROFS); 825 826 /* 827 * Handle case of truncating lower object to zero size, 828 * by creating a zero length upper object. This is to 829 * handle the case of open with O_TRUNC and O_CREAT. 830 */ 831 if ((un->un_uppervp == NULLVP) && 832 /* assert(un->un_lowervp != NULLVP) */ 833 (un->un_lowervp->v_type == VREG)) { 834 error = union_copyup(un, (ap->a_vap->va_size != 0), 835 ap->a_cred, ap->a_p); 836 if (error) 837 return (error); 838 } 839 840 /* 841 * Try to set attributes in upper layer, 842 * otherwise return read-only filesystem error. 843 */ 844 if (un->un_uppervp != NULLVP) { 845 FIXUP(un, p); 846 error = VOP_SETATTR(un->un_uppervp, ap->a_vap, 847 ap->a_cred, ap->a_p); 848 if ((error == 0) && (ap->a_vap->va_size != VNOVAL)) 849 union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL); 850 } else { 851 error = EROFS; 852 } 853 854 return (error); 855} 856 857static int 858union_read(ap) 859 struct vop_read_args /* { 860 struct vnode *a_vp; 861 struct uio *a_uio; 862 int a_ioflag; 863 struct ucred *a_cred; 864 } */ *ap; 865{ 866 int error; 867 struct proc *p = ap->a_uio->uio_procp; 868 struct vnode *vp = OTHERVP(ap->a_vp); 869 int dolock = (vp == LOWERVP(ap->a_vp)); 870 871 if (dolock) 872 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 873 else 874 FIXUP(VTOUNION(ap->a_vp), p); 875 error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 876 if (dolock) 877 VOP_UNLOCK(vp, 0, p); 878 879 /* 880 * XXX 881 * perhaps the size of the underlying object has changed under 882 * our feet. take advantage of the offset information present 883 * in the uio structure. 884 */ 885 if (error == 0) { 886 struct union_node *un = VTOUNION(ap->a_vp); 887 off_t cur = ap->a_uio->uio_offset; 888 889 if (vp == un->un_uppervp) { 890 if (cur > un->un_uppersz) 891 union_newsize(ap->a_vp, cur, VNOVAL); 892 } else { 893 if (cur > un->un_lowersz) 894 union_newsize(ap->a_vp, VNOVAL, cur); 895 } 896 } 897 898 return (error); 899} 900 901static int 902union_write(ap) 903 struct vop_read_args /* { 904 struct vnode *a_vp; 905 struct uio *a_uio; 906 int a_ioflag; 907 struct ucred *a_cred; 908 } */ *ap; 909{ 910 int error; 911 struct vnode *vp; 912 struct union_node *un = VTOUNION(ap->a_vp); 913 struct proc *p = ap->a_uio->uio_procp; 914 915 vp = UPPERVP(ap->a_vp); 916 if (vp == NULLVP) 917 panic("union: missing upper layer in write"); 918 919 FIXUP(un, p); 920 error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); 921 922 /* 923 * the size of the underlying object may be changed by the 924 * write. 925 */ 926 if (error == 0) { 927 off_t cur = ap->a_uio->uio_offset; 928 929 if (cur > un->un_uppersz) 930 union_newsize(ap->a_vp, cur, VNOVAL); 931 } 932 933 return (error); 934} 935 936static int 937union_lease(ap) 938 struct vop_lease_args /* { 939 struct vnode *a_vp; 940 struct proc *a_p; 941 struct ucred *a_cred; 942 int a_flag; 943 } */ *ap; 944{ 945 register struct vnode *ovp = OTHERVP(ap->a_vp); 946 947 ap->a_vp = ovp; 948 return (VCALL(ovp, VOFFSET(vop_lease), ap)); 949} 950 951static int 952union_ioctl(ap) 953 struct vop_ioctl_args /* { 954 struct vnode *a_vp; 955 int a_command; 956 caddr_t a_data; 957 int a_fflag; 958 struct ucred *a_cred; 959 struct proc *a_p; 960 } */ *ap; 961{ 962 register struct vnode *ovp = OTHERVP(ap->a_vp); 963 964 ap->a_vp = ovp; 965 return (VCALL(ovp, VOFFSET(vop_ioctl), ap)); 966} 967 968static int 969union_poll(ap) 970 struct vop_poll_args /* { 971 struct vnode *a_vp; 972 int a_events; 973 struct ucred *a_cred; 974 struct proc *a_p; 975 } */ *ap; 976{ 977 register struct vnode *ovp = OTHERVP(ap->a_vp); 978 979 ap->a_vp = ovp; 980 return (VCALL(ovp, VOFFSET(vop_poll), ap)); 981} 982 983static int 984union_revoke(ap) 985 struct vop_revoke_args /* { 986 struct vnode *a_vp; 987 int a_flags; 988 struct proc *a_p; 989 } */ *ap; 990{ 991 struct vnode *vp = ap->a_vp; 992 993 if (UPPERVP(vp)) 994 VOP_REVOKE(UPPERVP(vp), ap->a_flags); 995 if (LOWERVP(vp)) 996 VOP_REVOKE(LOWERVP(vp), ap->a_flags); 997 vgone(vp); 998 return (0); 999} 1000 1001static int 1002union_mmap(ap) 1003 struct vop_mmap_args /* { 1004 struct vnode *a_vp; 1005 int a_fflags; 1006 struct ucred *a_cred; 1007 struct proc *a_p; 1008 } */ *ap; 1009{ 1010 register struct vnode *ovp = OTHERVP(ap->a_vp); 1011 1012 ap->a_vp = ovp; 1013 return (VCALL(ovp, VOFFSET(vop_mmap), ap)); 1014} 1015 1016static int 1017union_fsync(ap) 1018 struct vop_fsync_args /* { 1019 struct vnode *a_vp; 1020 struct ucred *a_cred; 1021 int a_waitfor; 1022 struct proc *a_p; 1023 } */ *ap; 1024{ 1025 int error = 0; 1026 struct proc *p = ap->a_p; 1027 struct vnode *targetvp = OTHERVP(ap->a_vp); 1028 struct union_node *un; 1029 1030 if (targetvp != NULLVP) { 1031 int dolock = (targetvp == LOWERVP(ap->a_vp)); 1032 1033 un = VTOUNION(ap->a_vp); 1034 if (dolock) 1035 vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p); 1036 else { 1037 un = VTOUNION(ap->a_vp); 1038 if ((un->un_flags & UN_ULOCK) == 0 && 1039 targetvp->v_data != NULL && 1040 ((struct lock *)targetvp->v_data)->lk_lockholder 1041 == curproc->p_pid && 1042 VOP_ISLOCKED(targetvp) != 0) 1043 return 0; /* XXX */ 1044 1045 FIXUP(un, p); 1046 } 1047 1048 error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p); 1049 if (dolock) 1050 VOP_UNLOCK(targetvp, 0, p); 1051 } 1052 1053 return (error); 1054} 1055 1056static int 1057union_remove(ap) 1058 struct vop_remove_args /* { 1059 struct vnode *a_dvp; 1060 struct vnode *a_vp; 1061 struct componentname *a_cnp; 1062 } */ *ap; 1063{ 1064 struct union_node *dun = VTOUNION(ap->a_dvp); 1065 struct union_node *un = VTOUNION(ap->a_vp); 1066 struct componentname *cnp = ap->a_cnp; 1067 struct proc *p = cnp->cn_proc; 1068 int error; 1069 1070 if (dun->un_uppervp == NULLVP) 1071 panic("union remove: null upper vnode"); 1072 1073 if (un->un_uppervp != NULLVP) { 1074 struct vnode *dvp = dun->un_uppervp; 1075 struct vnode *vp = un->un_uppervp; 1076 1077 FIXUP(dun, p); 1078 dun->un_flags |= UN_KLOCK; 1079 VOP_UNLOCK(ap->a_dvp, 0, p); 1080 FIXUP(un, p); 1081 un->un_flags |= UN_KLOCK; 1082 VOP_UNLOCK(ap->a_vp, 0, p); 1083 1084 if (union_dowhiteout(un, cnp->cn_cred, p)) 1085 cnp->cn_flags |= DOWHITEOUT; 1086 error = VOP_REMOVE(dvp, vp, cnp); 1087#if 0 1088 /* XXX */ 1089 if (!error) 1090 union_removed_upper(un); 1091#endif 1092 dun->un_flags |= UN_ULOCK; 1093 un->un_flags |= UN_ULOCK; 1094 } else { 1095 FIXUP(dun, p); 1096 error = union_mkwhiteout( 1097 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount), 1098 dun->un_uppervp, ap->a_cnp, un->un_path); 1099 } 1100 1101 return (error); 1102} 1103 1104static int 1105union_link(ap) 1106 struct vop_link_args /* { 1107 struct vnode *a_tdvp; 1108 struct vnode *a_vp; 1109 struct componentname *a_cnp; 1110 } */ *ap; 1111{ 1112 struct componentname *cnp = ap->a_cnp; 1113 struct proc *p = cnp->cn_proc; 1114 struct union_node *dun = VTOUNION(ap->a_tdvp); 1115 struct vnode *vp; 1116 struct vnode *tdvp; 1117 int error = 0; 1118 1119 1120 if (ap->a_tdvp->v_op != ap->a_vp->v_op) { 1121 vp = ap->a_vp; 1122 } else { 1123 struct union_node *tun = VTOUNION(ap->a_vp); 1124 if (tun->un_uppervp == NULLVP) { 1125 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 1126 if (dun->un_uppervp == tun->un_dirvp) { 1127 dun->un_flags &= ~UN_ULOCK; 1128 VOP_UNLOCK(dun->un_uppervp, 0, p); 1129 } 1130 error = union_copyup(tun, 1, cnp->cn_cred, p); 1131 if (dun->un_uppervp == tun->un_dirvp) { 1132 vn_lock(dun->un_uppervp, 1133 LK_EXCLUSIVE | LK_RETRY, p); 1134 dun->un_flags |= UN_ULOCK; 1135 } 1136 VOP_UNLOCK(ap->a_vp, 0, p); 1137 } 1138 vp = tun->un_uppervp; 1139 } 1140 1141 tdvp = dun->un_uppervp; 1142 if (tdvp == NULLVP) 1143 error = EROFS; 1144 1145 if (error) 1146 return (error); 1147 1148 FIXUP(dun, p); 1149 dun->un_flags |= UN_KLOCK; 1150 VOP_UNLOCK(ap->a_tdvp, 0, p); 1151 1152 error = VOP_LINK(tdvp, vp, cnp); 1153 1154 dun->un_flags |= UN_ULOCK; 1155 1156 return (error); 1157} 1158 1159static int 1160union_rename(ap) 1161 struct vop_rename_args /* { 1162 struct vnode *a_fdvp; 1163 struct vnode *a_fvp; 1164 struct componentname *a_fcnp; 1165 struct vnode *a_tdvp; 1166 struct vnode *a_tvp; 1167 struct componentname *a_tcnp; 1168 } */ *ap; 1169{ 1170 int error; 1171 1172 struct vnode *fdvp = ap->a_fdvp; 1173 struct vnode *fvp = ap->a_fvp; 1174 struct vnode *tdvp = ap->a_tdvp; 1175 struct vnode *tvp = ap->a_tvp; 1176 1177 if (fdvp->v_op == union_vnodeop_p) { /* always true */ 1178 struct union_node *un = VTOUNION(fdvp); 1179 if (un->un_uppervp == NULLVP) { 1180 /* 1181 * this should never happen in normal 1182 * operation but might if there was 1183 * a problem creating the top-level shadow 1184 * directory. 1185 */ 1186 error = EXDEV; 1187 goto bad; 1188 } 1189 1190 fdvp = un->un_uppervp; 1191 VREF(fdvp); 1192 vrele(ap->a_fdvp); 1193 } 1194 1195 if (fvp->v_op == union_vnodeop_p) { /* always true */ 1196 struct union_node *un = VTOUNION(fvp); 1197 if (un->un_uppervp == NULLVP) { 1198 /* XXX: should do a copyup */ 1199 error = EXDEV; 1200 goto bad; 1201 } 1202 1203 if (un->un_lowervp != NULLVP) 1204 ap->a_fcnp->cn_flags |= DOWHITEOUT; 1205 1206 fvp = un->un_uppervp; 1207 VREF(fvp); 1208 vrele(ap->a_fvp); 1209 } 1210 1211 if (tdvp->v_op == union_vnodeop_p) { 1212 struct union_node *un = VTOUNION(tdvp); 1213 if (un->un_uppervp == NULLVP) { 1214 /* 1215 * this should never happen in normal 1216 * operation but might if there was 1217 * a problem creating the top-level shadow 1218 * directory. 1219 */ 1220 error = EXDEV; 1221 goto bad; 1222 } 1223 1224 tdvp = un->un_uppervp; 1225 VREF(tdvp); 1226 un->un_flags |= UN_KLOCK; 1227 vput(ap->a_tdvp); 1228 } 1229 1230 if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) { 1231 struct union_node *un = VTOUNION(tvp); 1232 1233 tvp = un->un_uppervp; 1234 if (tvp != NULLVP) { 1235 VREF(tvp); 1236 un->un_flags |= UN_KLOCK; 1237 } 1238 vput(ap->a_tvp); 1239 } 1240 1241 return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp)); 1242 1243bad: 1244 vrele(fdvp); 1245 vrele(fvp); 1246 vput(tdvp); 1247 if (tvp != NULLVP) 1248 vput(tvp); 1249 1250 return (error); 1251} 1252 1253static int 1254union_mkdir(ap) 1255 struct vop_mkdir_args /* { 1256 struct vnode *a_dvp; 1257 struct vnode **a_vpp; 1258 struct componentname *a_cnp; 1259 struct vattr *a_vap; 1260 } */ *ap; 1261{ 1262 struct union_node *dun = VTOUNION(ap->a_dvp); 1263 struct vnode *dvp = dun->un_uppervp; 1264 struct componentname *cnp = ap->a_cnp; 1265 struct proc *p = cnp->cn_proc; 1266 1267 if (dvp != NULLVP) { 1268 struct vnode *vp; 1269 int error; 1270 1271 FIXUP(dun, p); 1272 dun->un_flags |= UN_KLOCK; 1273 VOP_UNLOCK(ap->a_dvp, 0, p); 1274 error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap); 1275 if (error) { 1276 dun->un_flags |= UN_ULOCK; 1277 return (error); 1278 } 1279 1280 VOP_UNLOCK(dvp, 0, p); 1281 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp, 1282 NULLVP, cnp, vp, NULLVP, 1); 1283 if (error) 1284 vput(vp); 1285 vn_lock(ap->a_dvp, LK_EXCLUSIVE| LK_RETRY, p); 1286 1287 return (error); 1288 } 1289 1290 return (EROFS); 1291} 1292 1293static int 1294union_rmdir(ap) 1295 struct vop_rmdir_args /* { 1296 struct vnode *a_dvp; 1297 struct vnode *a_vp; 1298 struct componentname *a_cnp; 1299 } */ *ap; 1300{ 1301 struct union_node *dun = VTOUNION(ap->a_dvp); 1302 struct union_node *un = VTOUNION(ap->a_vp); 1303 struct componentname *cnp = ap->a_cnp; 1304 struct proc *p = cnp->cn_proc; 1305 int error; 1306 1307 if (dun->un_uppervp == NULLVP) 1308 panic("union rmdir: null upper vnode"); 1309 1310 if (un->un_uppervp != NULLVP) { 1311 struct vnode *dvp = dun->un_uppervp; 1312 struct vnode *vp = un->un_uppervp; 1313 1314 FIXUP(dun, p); 1315 dun->un_flags |= UN_KLOCK; 1316 VOP_UNLOCK(ap->a_dvp, 0, p); 1317 FIXUP(un, p); 1318 un->un_flags |= UN_KLOCK; 1319 VOP_UNLOCK(ap->a_vp, 0, p); 1320 1321 if (union_dowhiteout(un, cnp->cn_cred, p)) 1322 cnp->cn_flags |= DOWHITEOUT; 1323 error = VOP_RMDIR(dvp, vp, ap->a_cnp); 1324#if 0 1325 /* XXX */ 1326 if (!error) 1327 union_removed_upper(un); 1328#endif 1329 dun->un_flags |= UN_ULOCK; 1330 un->un_flags |= UN_ULOCK; 1331 } else { 1332 FIXUP(dun, p); 1333 error = union_mkwhiteout( 1334 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount), 1335 dun->un_uppervp, ap->a_cnp, un->un_path); 1336 } 1337 1338 return (error); 1339} 1340 1341static int 1342union_symlink(ap) 1343 struct vop_symlink_args /* { 1344 struct vnode *a_dvp; 1345 struct vnode **a_vpp; 1346 struct componentname *a_cnp; 1347 struct vattr *a_vap; 1348 char *a_target; 1349 } */ *ap; 1350{ 1351 struct union_node *dun = VTOUNION(ap->a_dvp); 1352 struct vnode *dvp = dun->un_uppervp; 1353 struct componentname *cnp = ap->a_cnp; 1354 struct proc *p = cnp->cn_proc; 1355 1356 if (dvp != NULLVP) { 1357 struct vnode *vp; 1358 int error; 1359 1360 FIXUP(dun, p); 1361 dun->un_flags |= UN_KLOCK; 1362 VOP_UNLOCK(ap->a_dvp, 0, p); 1363 error = VOP_SYMLINK(dvp, &vp, cnp, ap->a_vap, ap->a_target); 1364 dun->un_flags |= UN_ULOCK; 1365 *ap->a_vpp = NULLVP; 1366 return (error); 1367 } 1368 1369 return (EROFS); 1370} 1371 1372/* 1373 * union_readdir works in concert with getdirentries and 1374 * readdir(3) to provide a list of entries in the unioned 1375 * directories. getdirentries is responsible for walking 1376 * down the union stack. readdir(3) is responsible for 1377 * eliminating duplicate names from the returned data stream. 1378 */ 1379static int 1380union_readdir(ap) 1381 struct vop_readdir_args /* { 1382 struct vnode *a_vp; 1383 struct uio *a_uio; 1384 struct ucred *a_cred; 1385 int *a_eofflag; 1386 u_long *a_cookies; 1387 int a_ncookies; 1388 } */ *ap; 1389{ 1390 struct union_node *un = VTOUNION(ap->a_vp); 1391 struct vnode *uvp = un->un_uppervp; 1392 struct proc *p = ap->a_uio->uio_procp; 1393 1394 if (uvp == NULLVP) 1395 return (0); 1396 1397 FIXUP(un, p); 1398 ap->a_vp = uvp; 1399 return (VCALL(uvp, VOFFSET(vop_readdir), ap)); 1400} 1401 1402static int 1403union_readlink(ap) 1404 struct vop_readlink_args /* { 1405 struct vnode *a_vp; 1406 struct uio *a_uio; 1407 struct ucred *a_cred; 1408 } */ *ap; 1409{ 1410 int error; 1411 struct uio *uio = ap->a_uio; 1412 struct proc *p = uio->uio_procp; 1413 struct vnode *vp = OTHERVP(ap->a_vp); 1414 int dolock = (vp == LOWERVP(ap->a_vp)); 1415 1416 if (dolock) 1417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1418 else 1419 FIXUP(VTOUNION(ap->a_vp), p); 1420 ap->a_vp = vp; 1421 error = VCALL(vp, VOFFSET(vop_readlink), ap); 1422 if (dolock) 1423 VOP_UNLOCK(vp, 0, p); 1424 1425 return (error); 1426} 1427 1428static int 1429union_abortop(ap) 1430 struct vop_abortop_args /* { 1431 struct vnode *a_dvp; 1432 struct componentname *a_cnp; 1433 } */ *ap; 1434{ 1435 int error; 1436 struct componentname *cnp = ap->a_cnp; 1437 struct proc *p = cnp->cn_proc; 1438 struct vnode *vp = OTHERVP(ap->a_dvp); 1439 struct union_node *un = VTOUNION(ap->a_dvp); 1440 int islocked = un->un_flags & UN_LOCKED; 1441 int dolock = (vp == LOWERVP(ap->a_dvp)); 1442 1443 if (islocked) { 1444 if (dolock) 1445 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1446 else 1447 FIXUP(VTOUNION(ap->a_dvp), p); 1448 } 1449 ap->a_dvp = vp; 1450 error = VCALL(vp, VOFFSET(vop_abortop), ap); 1451 if (islocked && dolock) 1452 VOP_UNLOCK(vp, 0, p); 1453 1454 return (error); 1455} 1456 1457static int 1458union_inactive(ap) 1459 struct vop_inactive_args /* { 1460 struct vnode *a_vp; 1461 struct proc *a_p; 1462 } */ *ap; 1463{ 1464 struct vnode *vp = ap->a_vp; 1465 struct proc *p = ap->a_p; 1466 struct union_node *un = VTOUNION(vp); 1467 struct vnode **vpp; 1468 1469 /* 1470 * Do nothing (and _don't_ bypass). 1471 * Wait to vrele lowervp until reclaim, 1472 * so that until then our union_node is in the 1473 * cache and reusable. 1474 * 1475 * NEEDSWORK: Someday, consider inactive'ing 1476 * the lowervp and then trying to reactivate it 1477 * with capabilities (v_id) 1478 * like they do in the name lookup cache code. 1479 * That's too much work for now. 1480 */ 1481 1482 if (un->un_dircache != 0) { 1483 for (vpp = un->un_dircache; *vpp != NULLVP; vpp++) 1484 vrele(*vpp); 1485 free(un->un_dircache, M_TEMP); 1486 un->un_dircache = 0; 1487 } 1488 1489 VOP_UNLOCK(vp, 0, p); 1490 1491 if ((un->un_flags & UN_CACHED) == 0) 1492 vgone(vp); 1493 1494 return (0); 1495} 1496 1497static int 1498union_reclaim(ap) 1499 struct vop_reclaim_args /* { 1500 struct vnode *a_vp; 1501 } */ *ap; 1502{ 1503 1504 union_freevp(ap->a_vp); 1505 1506 return (0); 1507} 1508 1509static int 1510union_lock(ap) 1511 struct vop_lock_args *ap; 1512{ 1513 struct vnode *vp = ap->a_vp; 1514 struct proc *p = ap->a_p; 1515 int flags = ap->a_flags; 1516 struct union_node *un; 1517 int error; 1518 1519 vop_nolock(ap); 1520 /* 1521 * Need to do real lockmgr-style locking here. 1522 * in the mean time, draining won't work quite right, 1523 * which could lead to a few race conditions. 1524 * the following test was here, but is not quite right, we 1525 * still need to take the lock: 1526 if ((flags & LK_TYPE_MASK) == LK_DRAIN) 1527 return (0); 1528 */ 1529 flags &= ~LK_INTERLOCK; 1530 1531start: 1532 un = VTOUNION(vp); 1533 1534 if (un->un_uppervp != NULLVP) { 1535 if (((un->un_flags & UN_ULOCK) == 0) && 1536 (vp->v_usecount != 0)) { 1537 error = vn_lock(un->un_uppervp, flags, p); 1538 if (error) 1539 return (error); 1540 un->un_flags |= UN_ULOCK; 1541 } 1542#ifdef DIAGNOSTIC 1543 if (un->un_flags & UN_KLOCK) { 1544 vprint("dangling upper lock", vp); 1545 panic("union: dangling upper lock"); 1546 } 1547#endif 1548 } 1549 1550 if (un->un_flags & UN_LOCKED) { 1551#ifdef DIAGNOSTIC 1552 if (curproc && un->un_pid == curproc->p_pid && 1553 un->un_pid > -1 && curproc->p_pid > -1) 1554 panic("union: locking against myself"); 1555#endif 1556 un->un_flags |= UN_WANT; 1557 tsleep((caddr_t)&un->un_flags, PINOD, "unionlk2", 0); 1558 goto start; 1559 } 1560 1561#ifdef DIAGNOSTIC 1562 if (curproc) 1563 un->un_pid = curproc->p_pid; 1564 else 1565 un->un_pid = -1; 1566#endif 1567 1568 un->un_flags |= UN_LOCKED; 1569 return (0); 1570} 1571 1572/* 1573 * When operations want to vput() a union node yet retain a lock on 1574 * the upper vnode (say, to do some further operations like link(), 1575 * mkdir(), ...), they set UN_KLOCK on the union node, then call 1576 * vput() which calls VOP_UNLOCK() and comes here. union_unlock() 1577 * unlocks the union node (leaving the upper vnode alone), clears the 1578 * KLOCK flag, and then returns to vput(). The caller then does whatever 1579 * is left to do with the upper vnode, and ensures that it gets unlocked. 1580 * 1581 * If UN_KLOCK isn't set, then the upper vnode is unlocked here. 1582 */ 1583static int 1584union_unlock(ap) 1585 struct vop_unlock_args /* { 1586 struct vnode *a_vp; 1587 int a_flags; 1588 struct proc *a_p; 1589 } */ *ap; 1590{ 1591 struct union_node *un = VTOUNION(ap->a_vp); 1592 struct proc *p = ap->a_p; 1593 1594#ifdef DIAGNOSTIC 1595 if ((un->un_flags & UN_LOCKED) == 0) 1596 panic("union: unlock unlocked node"); 1597 if (curproc && un->un_pid != curproc->p_pid && 1598 curproc->p_pid > -1 && un->un_pid > -1) 1599 panic("union: unlocking other process's union node"); 1600#endif 1601 1602 un->un_flags &= ~UN_LOCKED; 1603 1604 if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK) 1605 VOP_UNLOCK(un->un_uppervp, 0, p); 1606 1607 un->un_flags &= ~(UN_ULOCK|UN_KLOCK); 1608 1609 if (un->un_flags & UN_WANT) { 1610 un->un_flags &= ~UN_WANT; 1611 wakeup((caddr_t) &un->un_flags); 1612 } 1613 1614#ifdef DIAGNOSTIC 1615 un->un_pid = 0; 1616#endif 1617 vop_nounlock(ap); 1618 1619 return (0); 1620} 1621 1622static int 1623union_bmap(ap) 1624 struct vop_bmap_args /* { 1625 struct vnode *a_vp; 1626 daddr_t a_bn; 1627 struct vnode **a_vpp; 1628 daddr_t *a_bnp; 1629 int *a_runp; 1630 int *a_runb; 1631 } */ *ap; 1632{ 1633 int error; 1634 struct proc *p = curproc; /* XXX */ 1635 struct vnode *vp = OTHERVP(ap->a_vp); 1636 int dolock = (vp == LOWERVP(ap->a_vp)); 1637 1638 if (dolock) 1639 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1640 else 1641 FIXUP(VTOUNION(ap->a_vp), p); 1642 ap->a_vp = vp; 1643 error = VCALL(vp, VOFFSET(vop_bmap), ap); 1644 if (dolock) 1645 VOP_UNLOCK(vp, 0, p); 1646 1647 return (error); 1648} 1649 1650static int 1651union_print(ap) 1652 struct vop_print_args /* { 1653 struct vnode *a_vp; 1654 } */ *ap; 1655{ 1656 struct vnode *vp = ap->a_vp; 1657 1658 printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n", 1659 vp, UPPERVP(vp), LOWERVP(vp)); 1660 if (UPPERVP(vp) != NULLVP) 1661 vprint("union: upper", UPPERVP(vp)); 1662 if (LOWERVP(vp) != NULLVP) 1663 vprint("union: lower", LOWERVP(vp)); 1664 1665 return (0); 1666} 1667 1668static int 1669union_islocked(ap) 1670 struct vop_islocked_args /* { 1671 struct vnode *a_vp; 1672 } */ *ap; 1673{ 1674 1675 return ((VTOUNION(ap->a_vp)->un_flags & UN_LOCKED) ? 1 : 0); 1676} 1677 1678static int 1679union_pathconf(ap) 1680 struct vop_pathconf_args /* { 1681 struct vnode *a_vp; 1682 int a_name; 1683 int *a_retval; 1684 } */ *ap; 1685{ 1686 int error; 1687 struct proc *p = curproc; /* XXX */ 1688 struct vnode *vp = OTHERVP(ap->a_vp); 1689 int dolock = (vp == LOWERVP(ap->a_vp)); 1690 1691 if (dolock) 1692 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1693 else 1694 FIXUP(VTOUNION(ap->a_vp), p); 1695 ap->a_vp = vp; 1696 error = VCALL(vp, VOFFSET(vop_pathconf), ap); 1697 if (dolock) 1698 VOP_UNLOCK(vp, 0, p); 1699 1700 return (error); 1701} 1702 1703static int 1704union_advlock(ap) 1705 struct vop_advlock_args /* { 1706 struct vnode *a_vp; 1707 caddr_t a_id; 1708 int a_op; 1709 struct flock *a_fl; 1710 int a_flags; 1711 } */ *ap; 1712{ 1713 register struct vnode *ovp = OTHERVP(ap->a_vp); 1714 1715 ap->a_vp = ovp; 1716 return (VCALL(ovp, VOFFSET(vop_advlock), ap)); 1717} 1718 1719 1720/* 1721 * XXX - vop_strategy must be hand coded because it has no 1722 * vnode in its arguments. 1723 * This goes away with a merged VM/buffer cache. 1724 */ 1725static int 1726union_strategy(ap) 1727 struct vop_strategy_args /* {
|
1747 bp->b_vp = savedvp; 1748 1749 return (error); 1750} 1751 1752/* 1753 * Global vfs data structures 1754 */ 1755vop_t **union_vnodeop_p; 1756static struct vnodeopv_entry_desc union_vnodeop_entries[] = { 1757 { &vop_default_desc, (vop_t *) vop_defaultop }, 1758 { &vop_abortop_desc, (vop_t *) union_abortop }, 1759 { &vop_access_desc, (vop_t *) union_access }, 1760 { &vop_advlock_desc, (vop_t *) union_advlock }, 1761 { &vop_bmap_desc, (vop_t *) union_bmap }, 1762 { &vop_close_desc, (vop_t *) union_close }, 1763 { &vop_create_desc, (vop_t *) union_create }, 1764 { &vop_fsync_desc, (vop_t *) union_fsync }, 1765 { &vop_getattr_desc, (vop_t *) union_getattr }, 1766 { &vop_inactive_desc, (vop_t *) union_inactive }, 1767 { &vop_ioctl_desc, (vop_t *) union_ioctl }, 1768 { &vop_islocked_desc, (vop_t *) union_islocked }, 1769 { &vop_lease_desc, (vop_t *) union_lease }, 1770 { &vop_link_desc, (vop_t *) union_link }, 1771 { &vop_lock_desc, (vop_t *) union_lock }, 1772 { &vop_lookup_desc, (vop_t *) union_lookup }, 1773 { &vop_mkdir_desc, (vop_t *) union_mkdir }, 1774 { &vop_mknod_desc, (vop_t *) union_mknod }, 1775 { &vop_mmap_desc, (vop_t *) union_mmap }, 1776 { &vop_open_desc, (vop_t *) union_open }, 1777 { &vop_pathconf_desc, (vop_t *) union_pathconf }, 1778 { &vop_poll_desc, (vop_t *) union_poll }, 1779 { &vop_print_desc, (vop_t *) union_print }, 1780 { &vop_read_desc, (vop_t *) union_read }, 1781 { &vop_readdir_desc, (vop_t *) union_readdir }, 1782 { &vop_readlink_desc, (vop_t *) union_readlink }, 1783 { &vop_reclaim_desc, (vop_t *) union_reclaim }, 1784 { &vop_remove_desc, (vop_t *) union_remove }, 1785 { &vop_rename_desc, (vop_t *) union_rename }, 1786 { &vop_revoke_desc, (vop_t *) union_revoke }, 1787 { &vop_rmdir_desc, (vop_t *) union_rmdir }, 1788 { &vop_setattr_desc, (vop_t *) union_setattr }, 1789 { &vop_strategy_desc, (vop_t *) union_strategy }, 1790 { &vop_symlink_desc, (vop_t *) union_symlink }, 1791 { &vop_unlock_desc, (vop_t *) union_unlock }, 1792 { &vop_whiteout_desc, (vop_t *) union_whiteout }, 1793 { &vop_write_desc, (vop_t *) union_write }, 1794 { NULL, NULL } 1795}; 1796static struct vnodeopv_desc union_vnodeop_opv_desc = 1797 { &union_vnodeop_p, union_vnodeop_entries }; 1798 1799VNODEOP_SET(union_vnodeop_opv_desc);
| 1748 bp->b_vp = savedvp; 1749 1750 return (error); 1751} 1752 1753/* 1754 * Global vfs data structures 1755 */ 1756vop_t **union_vnodeop_p; 1757static struct vnodeopv_entry_desc union_vnodeop_entries[] = { 1758 { &vop_default_desc, (vop_t *) vop_defaultop }, 1759 { &vop_abortop_desc, (vop_t *) union_abortop }, 1760 { &vop_access_desc, (vop_t *) union_access }, 1761 { &vop_advlock_desc, (vop_t *) union_advlock }, 1762 { &vop_bmap_desc, (vop_t *) union_bmap }, 1763 { &vop_close_desc, (vop_t *) union_close }, 1764 { &vop_create_desc, (vop_t *) union_create }, 1765 { &vop_fsync_desc, (vop_t *) union_fsync }, 1766 { &vop_getattr_desc, (vop_t *) union_getattr }, 1767 { &vop_inactive_desc, (vop_t *) union_inactive }, 1768 { &vop_ioctl_desc, (vop_t *) union_ioctl }, 1769 { &vop_islocked_desc, (vop_t *) union_islocked }, 1770 { &vop_lease_desc, (vop_t *) union_lease }, 1771 { &vop_link_desc, (vop_t *) union_link }, 1772 { &vop_lock_desc, (vop_t *) union_lock }, 1773 { &vop_lookup_desc, (vop_t *) union_lookup }, 1774 { &vop_mkdir_desc, (vop_t *) union_mkdir }, 1775 { &vop_mknod_desc, (vop_t *) union_mknod }, 1776 { &vop_mmap_desc, (vop_t *) union_mmap }, 1777 { &vop_open_desc, (vop_t *) union_open }, 1778 { &vop_pathconf_desc, (vop_t *) union_pathconf }, 1779 { &vop_poll_desc, (vop_t *) union_poll }, 1780 { &vop_print_desc, (vop_t *) union_print }, 1781 { &vop_read_desc, (vop_t *) union_read }, 1782 { &vop_readdir_desc, (vop_t *) union_readdir }, 1783 { &vop_readlink_desc, (vop_t *) union_readlink }, 1784 { &vop_reclaim_desc, (vop_t *) union_reclaim }, 1785 { &vop_remove_desc, (vop_t *) union_remove }, 1786 { &vop_rename_desc, (vop_t *) union_rename }, 1787 { &vop_revoke_desc, (vop_t *) union_revoke }, 1788 { &vop_rmdir_desc, (vop_t *) union_rmdir }, 1789 { &vop_setattr_desc, (vop_t *) union_setattr }, 1790 { &vop_strategy_desc, (vop_t *) union_strategy }, 1791 { &vop_symlink_desc, (vop_t *) union_symlink }, 1792 { &vop_unlock_desc, (vop_t *) union_unlock }, 1793 { &vop_whiteout_desc, (vop_t *) union_whiteout }, 1794 { &vop_write_desc, (vop_t *) union_write }, 1795 { NULL, NULL } 1796}; 1797static struct vnodeopv_desc union_vnodeop_opv_desc = 1798 { &union_vnodeop_p, union_vnodeop_entries }; 1799 1800VNODEOP_SET(union_vnodeop_opv_desc);
|