1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry. 5 * Copyright (c) 1992, 1993, 1994, 1995 6 * The Regents of the University of California. 7 * Copyright (c) 2005, 2006, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc. 8 * Copyright (c) 2006, 2012 Daichi Goto <daichi@freebsd.org> 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * Jan-Simon Pendry. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95 39 * $FreeBSD$ 40 * 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/conf.h> 46 #include <sys/kernel.h> 47 #include <sys/lock.h> 48 #include <sys/malloc.h> 49 #include <sys/mount.h> 50 #include <sys/mutex.h> 51 #include <sys/namei.h> 52 #include <sys/sysctl.h> 53 #include <sys/vnode.h> 54 #include <sys/kdb.h> 55 #include <sys/fcntl.h> 56 #include <sys/stat.h> 57 #include <sys/dirent.h> 58 #include <sys/proc.h> 59 #include <sys/bio.h> 60 #include <sys/buf.h> 61 62 #include <fs/unionfs/union.h> 63 64 #include <vm/vm.h> 65 #include <vm/vm_extern.h> 66 #include <vm/vm_object.h> 67 #include <vm/vnode_pager.h> 68 69 #if 0 70 #define UNIONFS_INTERNAL_DEBUG(msg, args...) printf(msg, ## args) 71 #define UNIONFS_IDBG_RENAME 72 #else 73 #define UNIONFS_INTERNAL_DEBUG(msg, args...) 74 #endif 75 76 #define KASSERT_UNIONFS_VNODE(vp) \ 77 KASSERT(((vp)->v_op == &unionfs_vnodeops), \ 78 ("unionfs: it is not unionfs-vnode")) 79 80 static int 81 unionfs_lookup(struct vop_cachedlookup_args *ap) 82 { 83 struct unionfs_node *dunp; 84 struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp; 85 struct vattr va; 86 struct componentname *cnp; 87 struct thread *td; 88 u_long nameiop; 89 u_long cnflags, cnflagsbk; 90 int iswhiteout; 91 int lockflag; 92 int error , uerror, lerror; 93 94 iswhiteout = 0; 95 lockflag = 0; 96 error = uerror = lerror = ENOENT; 97 cnp = ap->a_cnp; 98 nameiop = cnp->cn_nameiop; 99 cnflags = cnp->cn_flags; 100 dvp = ap->a_dvp; 101 dunp = VTOUNIONFS(dvp); 102 udvp = dunp->un_uppervp; 103 ldvp = dunp->un_lowervp; 104 vp = uvp = lvp = NULLVP; 105 td = curthread; 106 *(ap->a_vpp) = NULLVP; 107 108 UNIONFS_INTERNAL_DEBUG( 109 "unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n", 110 nameiop, cnflags, cnp->cn_nameptr); 111 112 if (dvp->v_type != VDIR) 113 return (ENOTDIR); 114 115 /* 116 * If read-only and op is not LOOKUP, will return EROFS. 117 */ 118 if ((cnflags & ISLASTCN) && 119 (dvp->v_mount->mnt_flag & MNT_RDONLY) && 120 LOOKUP != nameiop) 121 return (EROFS); 122 123 /* 124 * lookup dotdot 125 */ 126 if (cnflags & ISDOTDOT) { 127 if (LOOKUP != nameiop && udvp == NULLVP) 128 return (EROFS); 129 130 if (udvp != NULLVP) { 131 dtmpvp = udvp; 132 if (ldvp != NULLVP) 133 VOP_UNLOCK(ldvp); 134 } 135 else 136 dtmpvp = ldvp; 137 138 error = VOP_LOOKUP(dtmpvp, &vp, cnp); 139 140 if (dtmpvp == udvp && ldvp != NULLVP) { 141 VOP_UNLOCK(udvp); 142 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 143 } 144 145 if (error == 0) { 146 /* 147 * Exchange lock and reference from vp to 148 * dunp->un_dvp. vp is upper/lower vnode, but it 149 * will need to return the unionfs vnode. 150 */ 151 if (nameiop == DELETE || nameiop == RENAME || 152 (cnp->cn_lkflags & LK_TYPE_MASK)) 153 VOP_UNLOCK(vp); 154 vrele(vp); 155 156 VOP_UNLOCK(dvp); 157 *(ap->a_vpp) = dunp->un_dvp; 158 vref(dunp->un_dvp); 159 160 if (nameiop == DELETE || nameiop == RENAME) 161 vn_lock(dunp->un_dvp, LK_EXCLUSIVE | LK_RETRY); 162 else if (cnp->cn_lkflags & LK_TYPE_MASK) 163 vn_lock(dunp->un_dvp, cnp->cn_lkflags | 164 LK_RETRY); 165 166 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 167 } else if (error == ENOENT && (cnflags & MAKEENTRY) != 0) 168 cache_enter(dvp, NULLVP, cnp); 169 170 goto unionfs_lookup_return; 171 } 172 173 /* 174 * lookup upper layer 175 */ 176 if (udvp != NULLVP) { 177 uerror = VOP_LOOKUP(udvp, &uvp, cnp); 178 179 if (uerror == 0) { 180 if (udvp == uvp) { /* is dot */ 181 vrele(uvp); 182 *(ap->a_vpp) = dvp; 183 vref(dvp); 184 185 error = uerror; 186 goto unionfs_lookup_return; 187 } 188 if (nameiop == DELETE || nameiop == RENAME || 189 (cnp->cn_lkflags & LK_TYPE_MASK)) 190 VOP_UNLOCK(uvp); 191 } 192 193 /* check whiteout */ 194 if (uerror == ENOENT || uerror == EJUSTRETURN) 195 if (cnp->cn_flags & ISWHITEOUT) 196 iswhiteout = 1; /* don't lookup lower */ 197 if (iswhiteout == 0 && ldvp != NULLVP) 198 if (!VOP_GETATTR(udvp, &va, cnp->cn_cred) && 199 (va.va_flags & OPAQUE)) 200 iswhiteout = 1; /* don't lookup lower */ 201 #if 0 202 UNIONFS_INTERNAL_DEBUG( 203 "unionfs_lookup: debug: whiteout=%d, path=%s\n", 204 iswhiteout, cnp->cn_nameptr); 205 #endif 206 } 207 208 /* 209 * lookup lower layer 210 */ 211 if (ldvp != NULLVP && !(cnflags & DOWHITEOUT) && iswhiteout == 0) { 212 /* always op is LOOKUP */ 213 cnp->cn_nameiop = LOOKUP; 214 cnflagsbk = cnp->cn_flags; 215 cnp->cn_flags = cnflags; 216 217 lerror = VOP_LOOKUP(ldvp, &lvp, cnp); 218 219 cnp->cn_nameiop = nameiop; 220 if (udvp != NULLVP && (uerror == 0 || uerror == EJUSTRETURN)) 221 cnp->cn_flags = cnflagsbk; 222 223 if (lerror == 0) { 224 if (ldvp == lvp) { /* is dot */ 225 if (uvp != NULLVP) 226 vrele(uvp); /* no need? */ 227 vrele(lvp); 228 *(ap->a_vpp) = dvp; 229 vref(dvp); 230 231 UNIONFS_INTERNAL_DEBUG( 232 "unionfs_lookup: leave (%d)\n", lerror); 233 234 return (lerror); 235 } 236 if (cnp->cn_lkflags & LK_TYPE_MASK) 237 VOP_UNLOCK(lvp); 238 } 239 } 240 241 /* 242 * check lookup result 243 */ 244 if (uvp == NULLVP && lvp == NULLVP) { 245 error = (udvp != NULLVP ? uerror : lerror); 246 goto unionfs_lookup_return; 247 } 248 249 /* 250 * check vnode type 251 */ 252 if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) { 253 vrele(lvp); 254 lvp = NULLVP; 255 } 256 257 /* 258 * check shadow dir 259 */ 260 if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP && 261 lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR && 262 !(dvp->v_mount->mnt_flag & MNT_RDONLY) && 263 (1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) { 264 /* get unionfs vnode in order to create a new shadow dir. */ 265 error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp, 266 cnp, td); 267 if (error != 0) 268 goto unionfs_lookup_cleanup; 269 270 if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK)) 271 VOP_UNLOCK(vp); 272 if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) { 273 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 274 lockflag = 1; 275 } 276 error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount), 277 udvp, VTOUNIONFS(vp), cnp, td); 278 if (lockflag != 0) 279 VOP_UNLOCK(vp); 280 if (error != 0) { 281 UNIONFSDEBUG( 282 "unionfs_lookup: Unable to create shadow dir."); 283 if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) 284 vput(vp); 285 else 286 vrele(vp); 287 goto unionfs_lookup_cleanup; 288 } 289 if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED) 290 vn_lock(vp, LK_SHARED | LK_RETRY); 291 } 292 /* 293 * get unionfs vnode. 294 */ 295 else { 296 if (uvp != NULLVP) 297 error = uerror; 298 else 299 error = lerror; 300 if (error != 0) 301 goto unionfs_lookup_cleanup; 302 /* 303 * get socket vnode. 304 */ 305 if (uvp != NULLVP && uvp->v_type == VSOCK) { 306 vp = uvp; 307 vref(vp); 308 if (cnp->cn_lkflags & LK_TYPE_MASK) 309 vn_lock(vp, cnp->cn_lkflags | LK_RETRY); 310 } 311 else if (lvp != NULLVP && lvp->v_type == VSOCK) { 312 vp = lvp; 313 vref(vp); 314 if (cnp->cn_lkflags & LK_TYPE_MASK) 315 vn_lock(vp, cnp->cn_lkflags | LK_RETRY); 316 } 317 /* 318 * get unionfs vnode. 319 */ 320 else 321 error = unionfs_nodeget(dvp->v_mount, uvp, lvp, 322 dvp, &vp, cnp, td); 323 if (error != 0) { 324 UNIONFSDEBUG( 325 "unionfs_lookup: Unable to create unionfs vnode."); 326 goto unionfs_lookup_cleanup; 327 } 328 if ((nameiop == DELETE || nameiop == RENAME) && 329 (cnp->cn_lkflags & LK_TYPE_MASK) == 0) 330 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 331 } 332 333 *(ap->a_vpp) = vp; 334 335 if ((cnflags & MAKEENTRY) && vp->v_type != VSOCK) 336 cache_enter(dvp, vp, cnp); 337 338 unionfs_lookup_cleanup: 339 if (uvp != NULLVP) 340 vrele(uvp); 341 if (lvp != NULLVP) 342 vrele(lvp); 343 344 if (error == ENOENT && (cnflags & MAKEENTRY) != 0) 345 cache_enter(dvp, NULLVP, cnp); 346 347 unionfs_lookup_return: 348 349 /* Ensure subsequent vnops will get a valid pathname buffer. */ 350 if (nameiop != LOOKUP && (error == 0 || error == EJUSTRETURN)) 351 cnp->cn_flags |= SAVENAME; 352 353 UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error); 354 355 return (error); 356 } 357 358 static int 359 unionfs_create(struct vop_create_args *ap) 360 { 361 struct unionfs_node *dunp; 362 struct componentname *cnp; 363 struct vnode *udvp; 364 struct vnode *vp; 365 int error; 366 367 UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n"); 368 369 KASSERT_UNIONFS_VNODE(ap->a_dvp); 370 371 dunp = VTOUNIONFS(ap->a_dvp); 372 cnp = ap->a_cnp; 373 udvp = dunp->un_uppervp; 374 error = EROFS; 375 376 if (udvp != NULLVP) { 377 error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap); 378 if (error != 0) 379 goto unionfs_create_abort; 380 381 if (vp->v_type == VSOCK) 382 *(ap->a_vpp) = vp; 383 else { 384 VOP_UNLOCK(vp); 385 error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, 386 ap->a_dvp, ap->a_vpp, cnp, curthread); 387 vrele(vp); 388 } 389 } 390 391 unionfs_create_abort: 392 UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error); 393 394 return (error); 395 } 396 397 static int 398 unionfs_whiteout(struct vop_whiteout_args *ap) 399 { 400 struct unionfs_node *dunp; 401 struct componentname *cnp; 402 struct vnode *udvp; 403 int error; 404 405 UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: enter\n"); 406 407 KASSERT_UNIONFS_VNODE(ap->a_dvp); 408 409 dunp = VTOUNIONFS(ap->a_dvp); 410 cnp = ap->a_cnp; 411 udvp = dunp->un_uppervp; 412 error = EOPNOTSUPP; 413 414 if (udvp != NULLVP) { 415 switch (ap->a_flags) { 416 case CREATE: 417 case DELETE: 418 case LOOKUP: 419 error = VOP_WHITEOUT(udvp, cnp, ap->a_flags); 420 break; 421 default: 422 error = EINVAL; 423 break; 424 } 425 } 426 427 UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: leave (%d)\n", error); 428 429 return (error); 430 } 431 432 static int 433 unionfs_mknod(struct vop_mknod_args *ap) 434 { 435 struct unionfs_node *dunp; 436 struct componentname *cnp; 437 struct vnode *udvp; 438 struct vnode *vp; 439 int error; 440 441 UNIONFS_INTERNAL_DEBUG("unionfs_mknod: enter\n"); 442 443 KASSERT_UNIONFS_VNODE(ap->a_dvp); 444 445 dunp = VTOUNIONFS(ap->a_dvp); 446 cnp = ap->a_cnp; 447 udvp = dunp->un_uppervp; 448 error = EROFS; 449 450 if (udvp != NULLVP) { 451 error = VOP_MKNOD(udvp, &vp, cnp, ap->a_vap); 452 if (error != 0) 453 goto unionfs_mknod_abort; 454 455 if (vp->v_type == VSOCK) 456 *(ap->a_vpp) = vp; 457 else { 458 VOP_UNLOCK(vp); 459 error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, 460 ap->a_dvp, ap->a_vpp, cnp, curthread); 461 vrele(vp); 462 } 463 } 464 465 unionfs_mknod_abort: 466 UNIONFS_INTERNAL_DEBUG("unionfs_mknod: leave (%d)\n", error); 467 468 return (error); 469 } 470 471 static int 472 unionfs_open(struct vop_open_args *ap) 473 { 474 struct unionfs_node *unp; 475 struct unionfs_node_status *unsp; 476 struct vnode *uvp; 477 struct vnode *lvp; 478 struct vnode *targetvp; 479 struct ucred *cred; 480 struct thread *td; 481 int error; 482 483 UNIONFS_INTERNAL_DEBUG("unionfs_open: enter\n"); 484 485 KASSERT_UNIONFS_VNODE(ap->a_vp); 486 487 error = 0; 488 unp = VTOUNIONFS(ap->a_vp); 489 uvp = unp->un_uppervp; 490 lvp = unp->un_lowervp; 491 targetvp = NULLVP; 492 cred = ap->a_cred; 493 td = ap->a_td; 494 495 unionfs_get_node_status(unp, td, &unsp); 496 497 if (unsp->uns_lower_opencnt > 0 || unsp->uns_upper_opencnt > 0) { 498 /* vnode is already opend. */ 499 if (unsp->uns_upper_opencnt > 0) 500 targetvp = uvp; 501 else 502 targetvp = lvp; 503 504 if (targetvp == lvp && 505 (ap->a_mode & FWRITE) && lvp->v_type == VREG) 506 targetvp = NULLVP; 507 } 508 if (targetvp == NULLVP) { 509 if (uvp == NULLVP) { 510 if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) { 511 error = unionfs_copyfile(unp, 512 !(ap->a_mode & O_TRUNC), cred, td); 513 if (error != 0) 514 goto unionfs_open_abort; 515 targetvp = uvp = unp->un_uppervp; 516 } else 517 targetvp = lvp; 518 } else 519 targetvp = uvp; 520 } 521 522 error = VOP_OPEN(targetvp, ap->a_mode, cred, td, ap->a_fp); 523 if (error == 0) { 524 if (targetvp == uvp) { 525 if (uvp->v_type == VDIR && lvp != NULLVP && 526 unsp->uns_lower_opencnt <= 0) { 527 /* open lower for readdir */ 528 error = VOP_OPEN(lvp, FREAD, cred, td, NULL); 529 if (error != 0) { 530 VOP_CLOSE(uvp, ap->a_mode, cred, td); 531 goto unionfs_open_abort; 532 } 533 unsp->uns_node_flag |= UNS_OPENL_4_READDIR; 534 unsp->uns_lower_opencnt++; 535 } 536 unsp->uns_upper_opencnt++; 537 } else { 538 unsp->uns_lower_opencnt++; 539 unsp->uns_lower_openmode = ap->a_mode; 540 } 541 ap->a_vp->v_object = targetvp->v_object; 542 } 543 544 unionfs_open_abort: 545 if (error != 0) 546 unionfs_tryrem_node_status(unp, unsp); 547 548 UNIONFS_INTERNAL_DEBUG("unionfs_open: leave (%d)\n", error); 549 550 return (error); 551 } 552 553 static int 554 unionfs_close(struct vop_close_args *ap) 555 { 556 struct unionfs_node *unp; 557 struct unionfs_node_status *unsp; 558 struct ucred *cred; 559 struct thread *td; 560 struct vnode *vp; 561 struct vnode *ovp; 562 int error; 563 int locked; 564 565 UNIONFS_INTERNAL_DEBUG("unionfs_close: enter\n"); 566 567 KASSERT_UNIONFS_VNODE(ap->a_vp); 568 569 locked = 0; 570 vp = ap->a_vp; 571 unp = VTOUNIONFS(vp); 572 cred = ap->a_cred; 573 td = ap->a_td; 574 575 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 576 if (vn_lock(vp, LK_UPGRADE) != 0) 577 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 578 locked = 1; 579 } 580 unionfs_get_node_status(unp, td, &unsp); 581 582 if (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0) { 583 #ifdef DIAGNOSTIC 584 printf("unionfs_close: warning: open count is 0\n"); 585 #endif 586 if (unp->un_uppervp != NULLVP) 587 ovp = unp->un_uppervp; 588 else 589 ovp = unp->un_lowervp; 590 } else if (unsp->uns_upper_opencnt > 0) 591 ovp = unp->un_uppervp; 592 else 593 ovp = unp->un_lowervp; 594 595 error = VOP_CLOSE(ovp, ap->a_fflag, cred, td); 596 597 if (error != 0) 598 goto unionfs_close_abort; 599 600 vp->v_object = ovp->v_object; 601 602 if (ovp == unp->un_uppervp) { 603 unsp->uns_upper_opencnt--; 604 if (unsp->uns_upper_opencnt == 0) { 605 if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) { 606 VOP_CLOSE(unp->un_lowervp, FREAD, cred, td); 607 unsp->uns_node_flag &= ~UNS_OPENL_4_READDIR; 608 unsp->uns_lower_opencnt--; 609 } 610 if (unsp->uns_lower_opencnt > 0) 611 vp->v_object = unp->un_lowervp->v_object; 612 } 613 } else 614 unsp->uns_lower_opencnt--; 615 616 unionfs_close_abort: 617 unionfs_tryrem_node_status(unp, unsp); 618 619 if (locked != 0) 620 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 621 622 UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error); 623 624 return (error); 625 } 626 627 /* 628 * Check the access mode toward shadow file/dir. 629 */ 630 static int 631 unionfs_check_corrected_access(accmode_t accmode, struct vattr *va, 632 struct ucred *cred) 633 { 634 int count; 635 uid_t uid; /* upper side vnode's uid */ 636 gid_t gid; /* upper side vnode's gid */ 637 u_short vmode; /* upper side vnode's mode */ 638 u_short mask; 639 640 mask = 0; 641 uid = va->va_uid; 642 gid = va->va_gid; 643 vmode = va->va_mode; 644 645 /* check owner */ 646 if (cred->cr_uid == uid) { 647 if (accmode & VEXEC) 648 mask |= S_IXUSR; 649 if (accmode & VREAD) 650 mask |= S_IRUSR; 651 if (accmode & VWRITE) 652 mask |= S_IWUSR; 653 return ((vmode & mask) == mask ? 0 : EACCES); 654 } 655 656 /* check group */ 657 count = 0; 658 if (groupmember(gid, cred)) { 659 if (accmode & VEXEC) 660 mask |= S_IXGRP; 661 if (accmode & VREAD) 662 mask |= S_IRGRP; 663 if (accmode & VWRITE) 664 mask |= S_IWGRP; 665 return ((vmode & mask) == mask ? 0 : EACCES); 666 } 667 668 /* check other */ 669 if (accmode & VEXEC) 670 mask |= S_IXOTH; 671 if (accmode & VREAD) 672 mask |= S_IROTH; 673 if (accmode & VWRITE) 674 mask |= S_IWOTH; 675 676 return ((vmode & mask) == mask ? 0 : EACCES); 677 } 678 679 static int 680 unionfs_access(struct vop_access_args *ap) 681 { 682 struct unionfs_mount *ump; 683 struct unionfs_node *unp; 684 struct vnode *uvp; 685 struct vnode *lvp; 686 struct thread *td; 687 struct vattr va; 688 accmode_t accmode; 689 int error; 690 691 UNIONFS_INTERNAL_DEBUG("unionfs_access: enter\n"); 692 693 KASSERT_UNIONFS_VNODE(ap->a_vp); 694 695 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 696 unp = VTOUNIONFS(ap->a_vp); 697 uvp = unp->un_uppervp; 698 lvp = unp->un_lowervp; 699 td = ap->a_td; 700 accmode = ap->a_accmode; 701 error = EACCES; 702 703 if ((accmode & VWRITE) && 704 (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) { 705 switch (ap->a_vp->v_type) { 706 case VREG: 707 case VDIR: 708 case VLNK: 709 return (EROFS); 710 default: 711 break; 712 } 713 } 714 715 if (uvp != NULLVP) { 716 error = VOP_ACCESS(uvp, accmode, ap->a_cred, td); 717 718 UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error); 719 720 return (error); 721 } 722 723 if (lvp != NULLVP) { 724 if (accmode & VWRITE) { 725 if (ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY) { 726 switch (ap->a_vp->v_type) { 727 case VREG: 728 case VDIR: 729 case VLNK: 730 return (EROFS); 731 default: 732 break; 733 } 734 } else if (ap->a_vp->v_type == VREG || 735 ap->a_vp->v_type == VDIR) { 736 /* check shadow file/dir */ 737 if (ump->um_copymode != UNIONFS_TRANSPARENT) { 738 error = unionfs_create_uppervattr(ump, 739 lvp, &va, ap->a_cred, td); 740 if (error != 0) 741 return (error); 742 743 error = unionfs_check_corrected_access( 744 accmode, &va, ap->a_cred); 745 if (error != 0) 746 return (error); 747 } 748 } 749 accmode &= ~(VWRITE | VAPPEND); 750 accmode |= VREAD; /* will copy to upper */ 751 } 752 error = VOP_ACCESS(lvp, accmode, ap->a_cred, td); 753 } 754 755 UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error); 756 757 return (error); 758 } 759 760 static int 761 unionfs_getattr(struct vop_getattr_args *ap) 762 { 763 struct unionfs_node *unp; 764 struct unionfs_mount *ump; 765 struct vnode *uvp; 766 struct vnode *lvp; 767 struct thread *td; 768 struct vattr va; 769 int error; 770 771 UNIONFS_INTERNAL_DEBUG("unionfs_getattr: enter\n"); 772 773 KASSERT_UNIONFS_VNODE(ap->a_vp); 774 775 unp = VTOUNIONFS(ap->a_vp); 776 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 777 uvp = unp->un_uppervp; 778 lvp = unp->un_lowervp; 779 td = curthread; 780 781 if (uvp != NULLVP) { 782 if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0) 783 ap->a_vap->va_fsid = 784 ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 785 786 UNIONFS_INTERNAL_DEBUG( 787 "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n", 788 ap->a_vap->va_mode, ap->a_vap->va_uid, 789 ap->a_vap->va_gid, error); 790 791 return (error); 792 } 793 794 error = VOP_GETATTR(lvp, ap->a_vap, ap->a_cred); 795 796 if (error == 0 && !(ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY)) { 797 /* correct the attr toward shadow file/dir. */ 798 if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) { 799 unionfs_create_uppervattr_core(ump, ap->a_vap, &va, td); 800 ap->a_vap->va_mode = va.va_mode; 801 ap->a_vap->va_uid = va.va_uid; 802 ap->a_vap->va_gid = va.va_gid; 803 } 804 } 805 806 if (error == 0) 807 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 808 809 UNIONFS_INTERNAL_DEBUG( 810 "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n", 811 ap->a_vap->va_mode, ap->a_vap->va_uid, ap->a_vap->va_gid, error); 812 813 return (error); 814 } 815 816 static int 817 unionfs_setattr(struct vop_setattr_args *ap) 818 { 819 struct unionfs_node *unp; 820 struct vnode *uvp; 821 struct vnode *lvp; 822 struct thread *td; 823 struct vattr *vap; 824 int error; 825 826 UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n"); 827 828 KASSERT_UNIONFS_VNODE(ap->a_vp); 829 830 error = EROFS; 831 unp = VTOUNIONFS(ap->a_vp); 832 uvp = unp->un_uppervp; 833 lvp = unp->un_lowervp; 834 td = curthread; 835 vap = ap->a_vap; 836 837 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && 838 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 839 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 840 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) 841 return (EROFS); 842 843 if (uvp == NULLVP && lvp->v_type == VREG) { 844 error = unionfs_copyfile(unp, (vap->va_size != 0), 845 ap->a_cred, td); 846 if (error != 0) 847 return (error); 848 uvp = unp->un_uppervp; 849 } 850 851 if (uvp != NULLVP) 852 error = VOP_SETATTR(uvp, vap, ap->a_cred); 853 854 UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error); 855 856 return (error); 857 } 858 859 static int 860 unionfs_read(struct vop_read_args *ap) 861 { 862 struct unionfs_node *unp; 863 struct vnode *tvp; 864 int error; 865 866 /* UNIONFS_INTERNAL_DEBUG("unionfs_read: enter\n"); */ 867 868 KASSERT_UNIONFS_VNODE(ap->a_vp); 869 870 unp = VTOUNIONFS(ap->a_vp); 871 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 872 873 error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); 874 875 /* UNIONFS_INTERNAL_DEBUG("unionfs_read: leave (%d)\n", error); */ 876 877 return (error); 878 } 879 880 static int 881 unionfs_write(struct vop_write_args *ap) 882 { 883 struct unionfs_node *unp; 884 struct vnode *tvp; 885 int error; 886 887 /* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */ 888 889 KASSERT_UNIONFS_VNODE(ap->a_vp); 890 891 unp = VTOUNIONFS(ap->a_vp); 892 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 893 894 error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); 895 896 /* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */ 897 898 return (error); 899 } 900 901 static int 902 unionfs_ioctl(struct vop_ioctl_args *ap) 903 { 904 struct unionfs_node *unp; 905 struct unionfs_node_status *unsp; 906 struct vnode *ovp; 907 int error; 908 909 UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: enter\n"); 910 911 KASSERT_UNIONFS_VNODE(ap->a_vp); 912 913 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 914 unp = VTOUNIONFS(ap->a_vp); 915 unionfs_get_node_status(unp, ap->a_td, &unsp); 916 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 917 unionfs_tryrem_node_status(unp, unsp); 918 VOP_UNLOCK(ap->a_vp); 919 920 if (ovp == NULLVP) 921 return (EBADF); 922 923 error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag, 924 ap->a_cred, ap->a_td); 925 926 UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error); 927 928 return (error); 929 } 930 931 static int 932 unionfs_poll(struct vop_poll_args *ap) 933 { 934 struct unionfs_node *unp; 935 struct unionfs_node_status *unsp; 936 struct vnode *ovp; 937 938 KASSERT_UNIONFS_VNODE(ap->a_vp); 939 940 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 941 unp = VTOUNIONFS(ap->a_vp); 942 unionfs_get_node_status(unp, ap->a_td, &unsp); 943 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 944 unionfs_tryrem_node_status(unp, unsp); 945 VOP_UNLOCK(ap->a_vp); 946 947 if (ovp == NULLVP) 948 return (EBADF); 949 950 return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td)); 951 } 952 953 static int 954 unionfs_fsync(struct vop_fsync_args *ap) 955 { 956 struct unionfs_node *unp; 957 struct unionfs_node_status *unsp; 958 struct vnode *ovp; 959 960 KASSERT_UNIONFS_VNODE(ap->a_vp); 961 962 unp = VTOUNIONFS(ap->a_vp); 963 unionfs_get_node_status(unp, ap->a_td, &unsp); 964 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 965 unionfs_tryrem_node_status(unp, unsp); 966 967 if (ovp == NULLVP) 968 return (EBADF); 969 970 return (VOP_FSYNC(ovp, ap->a_waitfor, ap->a_td)); 971 } 972 973 static int 974 unionfs_remove(struct vop_remove_args *ap) 975 { 976 char *path; 977 struct unionfs_node *dunp; 978 struct unionfs_node *unp; 979 struct unionfs_mount *ump; 980 struct vnode *udvp; 981 struct vnode *uvp; 982 struct vnode *lvp; 983 struct vnode *vp; 984 struct componentname *cnp; 985 struct componentname cn; 986 struct thread *td; 987 int error; 988 int pathlen; 989 990 UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n"); 991 992 KASSERT_UNIONFS_VNODE(ap->a_dvp); 993 994 error = 0; 995 dunp = VTOUNIONFS(ap->a_dvp); 996 udvp = dunp->un_uppervp; 997 cnp = ap->a_cnp; 998 td = curthread; 999 1000 if (ap->a_vp->v_op != &unionfs_vnodeops) { 1001 if (ap->a_vp->v_type != VSOCK) 1002 return (EINVAL); 1003 ump = NULL; 1004 vp = uvp = lvp = NULLVP; 1005 /* search vnode */ 1006 VOP_UNLOCK(ap->a_vp); 1007 error = unionfs_relookup(udvp, &vp, cnp, &cn, td, 1008 cnp->cn_nameptr, cnp->cn_namelen, DELETE); 1009 if (error != 0 && error != ENOENT) { 1010 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1011 return (error); 1012 } 1013 1014 if (error == 0 && vp == ap->a_vp) { 1015 /* target vnode in upper */ 1016 uvp = vp; 1017 vrele(vp); 1018 } else { 1019 /* target vnode in lower */ 1020 if (vp != NULLVP) { 1021 if (udvp == vp) 1022 vrele(vp); 1023 else 1024 vput(vp); 1025 } 1026 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1027 lvp = ap->a_vp; 1028 } 1029 path = cnp->cn_nameptr; 1030 pathlen = cnp->cn_namelen; 1031 } else { 1032 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 1033 unp = VTOUNIONFS(ap->a_vp); 1034 uvp = unp->un_uppervp; 1035 lvp = unp->un_lowervp; 1036 path = unp->un_path; 1037 pathlen = unp->un_pathlen; 1038 } 1039 1040 if (udvp == NULLVP) 1041 return (EROFS); 1042 1043 if (uvp != NULLVP) { 1044 /* 1045 * XXX: if the vnode type is VSOCK, it will create whiteout 1046 * after remove. 1047 */ 1048 if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS || 1049 lvp != NULLVP) 1050 cnp->cn_flags |= DOWHITEOUT; 1051 error = VOP_REMOVE(udvp, uvp, cnp); 1052 } else if (lvp != NULLVP) 1053 error = unionfs_mkwhiteout(udvp, cnp, td, path, pathlen); 1054 1055 UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error); 1056 1057 return (error); 1058 } 1059 1060 static int 1061 unionfs_link(struct vop_link_args *ap) 1062 { 1063 struct unionfs_node *dunp; 1064 struct unionfs_node *unp; 1065 struct vnode *udvp; 1066 struct vnode *uvp; 1067 struct componentname *cnp; 1068 struct thread *td; 1069 int error; 1070 int needrelookup; 1071 1072 UNIONFS_INTERNAL_DEBUG("unionfs_link: enter\n"); 1073 1074 KASSERT_UNIONFS_VNODE(ap->a_tdvp); 1075 KASSERT_UNIONFS_VNODE(ap->a_vp); 1076 1077 error = 0; 1078 needrelookup = 0; 1079 dunp = VTOUNIONFS(ap->a_tdvp); 1080 unp = NULL; 1081 udvp = dunp->un_uppervp; 1082 uvp = NULLVP; 1083 cnp = ap->a_cnp; 1084 td = curthread; 1085 1086 if (udvp == NULLVP) 1087 return (EROFS); 1088 1089 if (ap->a_vp->v_op != &unionfs_vnodeops) 1090 uvp = ap->a_vp; 1091 else { 1092 unp = VTOUNIONFS(ap->a_vp); 1093 1094 if (unp->un_uppervp == NULLVP) { 1095 if (ap->a_vp->v_type != VREG) 1096 return (EOPNOTSUPP); 1097 1098 error = unionfs_copyfile(unp, 1, cnp->cn_cred, td); 1099 if (error != 0) 1100 return (error); 1101 needrelookup = 1; 1102 } 1103 uvp = unp->un_uppervp; 1104 } 1105 1106 if (needrelookup != 0) 1107 error = unionfs_relookup_for_create(ap->a_tdvp, cnp, td); 1108 1109 if (error == 0) 1110 error = VOP_LINK(udvp, uvp, cnp); 1111 1112 UNIONFS_INTERNAL_DEBUG("unionfs_link: leave (%d)\n", error); 1113 1114 return (error); 1115 } 1116 1117 static int 1118 unionfs_rename(struct vop_rename_args *ap) 1119 { 1120 struct vnode *fdvp; 1121 struct vnode *fvp; 1122 struct componentname *fcnp; 1123 struct vnode *tdvp; 1124 struct vnode *tvp; 1125 struct componentname *tcnp; 1126 struct vnode *ltdvp; 1127 struct vnode *ltvp; 1128 struct thread *td; 1129 1130 /* rename target vnodes */ 1131 struct vnode *rfdvp; 1132 struct vnode *rfvp; 1133 struct vnode *rtdvp; 1134 struct vnode *rtvp; 1135 1136 struct unionfs_mount *ump; 1137 struct unionfs_node *unp; 1138 int error; 1139 int needrelookup; 1140 1141 UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n"); 1142 1143 error = 0; 1144 fdvp = ap->a_fdvp; 1145 fvp = ap->a_fvp; 1146 fcnp = ap->a_fcnp; 1147 tdvp = ap->a_tdvp; 1148 tvp = ap->a_tvp; 1149 tcnp = ap->a_tcnp; 1150 ltdvp = NULLVP; 1151 ltvp = NULLVP; 1152 td = curthread; 1153 rfdvp = fdvp; 1154 rfvp = fvp; 1155 rtdvp = tdvp; 1156 rtvp = tvp; 1157 needrelookup = 0; 1158 1159 #ifdef DIAGNOSTIC 1160 if (!(fcnp->cn_flags & HASBUF) || !(tcnp->cn_flags & HASBUF)) 1161 panic("unionfs_rename: no name"); 1162 #endif 1163 1164 /* check for cross device rename */ 1165 if (fvp->v_mount != tdvp->v_mount || 1166 (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) { 1167 if (fvp->v_op != &unionfs_vnodeops) 1168 error = ENODEV; 1169 else 1170 error = EXDEV; 1171 goto unionfs_rename_abort; 1172 } 1173 1174 /* Renaming a file to itself has no effect. */ 1175 if (fvp == tvp) 1176 goto unionfs_rename_abort; 1177 1178 /* 1179 * from/to vnode is unionfs node. 1180 */ 1181 1182 KASSERT_UNIONFS_VNODE(fdvp); 1183 KASSERT_UNIONFS_VNODE(fvp); 1184 KASSERT_UNIONFS_VNODE(tdvp); 1185 if (tvp != NULLVP) 1186 KASSERT_UNIONFS_VNODE(tvp); 1187 1188 unp = VTOUNIONFS(fdvp); 1189 #ifdef UNIONFS_IDBG_RENAME 1190 UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n", 1191 fdvp, unp->un_uppervp, unp->un_lowervp); 1192 #endif 1193 if (unp->un_uppervp == NULLVP) { 1194 error = ENODEV; 1195 goto unionfs_rename_abort; 1196 } 1197 rfdvp = unp->un_uppervp; 1198 vref(rfdvp); 1199 1200 unp = VTOUNIONFS(fvp); 1201 #ifdef UNIONFS_IDBG_RENAME 1202 UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n", 1203 fvp, unp->un_uppervp, unp->un_lowervp); 1204 #endif 1205 ump = MOUNTTOUNIONFSMOUNT(fvp->v_mount); 1206 if (unp->un_uppervp == NULLVP) { 1207 switch (fvp->v_type) { 1208 case VREG: 1209 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1210 goto unionfs_rename_abort; 1211 error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td); 1212 VOP_UNLOCK(fvp); 1213 if (error != 0) 1214 goto unionfs_rename_abort; 1215 break; 1216 case VDIR: 1217 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1218 goto unionfs_rename_abort; 1219 error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td); 1220 VOP_UNLOCK(fvp); 1221 if (error != 0) 1222 goto unionfs_rename_abort; 1223 break; 1224 default: 1225 error = ENODEV; 1226 goto unionfs_rename_abort; 1227 } 1228 1229 needrelookup = 1; 1230 } 1231 1232 if (unp->un_lowervp != NULLVP) 1233 fcnp->cn_flags |= DOWHITEOUT; 1234 rfvp = unp->un_uppervp; 1235 vref(rfvp); 1236 1237 unp = VTOUNIONFS(tdvp); 1238 #ifdef UNIONFS_IDBG_RENAME 1239 UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n", 1240 tdvp, unp->un_uppervp, unp->un_lowervp); 1241 #endif 1242 if (unp->un_uppervp == NULLVP) { 1243 error = ENODEV; 1244 goto unionfs_rename_abort; 1245 } 1246 rtdvp = unp->un_uppervp; 1247 ltdvp = unp->un_lowervp; 1248 vref(rtdvp); 1249 1250 if (tdvp == tvp) { 1251 rtvp = rtdvp; 1252 vref(rtvp); 1253 } else if (tvp != NULLVP) { 1254 unp = VTOUNIONFS(tvp); 1255 #ifdef UNIONFS_IDBG_RENAME 1256 UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n", 1257 tvp, unp->un_uppervp, unp->un_lowervp); 1258 #endif 1259 if (unp->un_uppervp == NULLVP) 1260 rtvp = NULLVP; 1261 else { 1262 if (tvp->v_type == VDIR) { 1263 error = EINVAL; 1264 goto unionfs_rename_abort; 1265 } 1266 rtvp = unp->un_uppervp; 1267 ltvp = unp->un_lowervp; 1268 vref(rtvp); 1269 } 1270 } 1271 1272 if (rfvp == rtvp) 1273 goto unionfs_rename_abort; 1274 1275 if (needrelookup != 0) { 1276 if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0) 1277 goto unionfs_rename_abort; 1278 error = unionfs_relookup_for_delete(fdvp, fcnp, td); 1279 VOP_UNLOCK(fdvp); 1280 if (error != 0) 1281 goto unionfs_rename_abort; 1282 1283 /* Lock of tvp is canceled in order to avoid recursive lock. */ 1284 if (tvp != NULLVP && tvp != tdvp) 1285 VOP_UNLOCK(tvp); 1286 error = unionfs_relookup_for_rename(tdvp, tcnp, td); 1287 if (tvp != NULLVP && tvp != tdvp) 1288 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); 1289 if (error != 0) 1290 goto unionfs_rename_abort; 1291 } 1292 1293 error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp); 1294 1295 if (error == 0) { 1296 if (rtvp != NULLVP && rtvp->v_type == VDIR) 1297 cache_purge(tdvp); 1298 if (fvp->v_type == VDIR && fdvp != tdvp) 1299 cache_purge(fdvp); 1300 } 1301 1302 if (ltdvp != NULLVP) 1303 VOP_UNLOCK(ltdvp); 1304 if (tdvp != rtdvp) 1305 vrele(tdvp); 1306 if (ltvp != NULLVP) 1307 VOP_UNLOCK(ltvp); 1308 if (tvp != rtvp && tvp != NULLVP) { 1309 if (rtvp == NULLVP) 1310 vput(tvp); 1311 else 1312 vrele(tvp); 1313 } 1314 if (fdvp != rfdvp) 1315 vrele(fdvp); 1316 if (fvp != rfvp) 1317 vrele(fvp); 1318 1319 UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); 1320 1321 return (error); 1322 1323 unionfs_rename_abort: 1324 vput(tdvp); 1325 if (tdvp != rtdvp) 1326 vrele(rtdvp); 1327 if (tvp != NULLVP) { 1328 if (tdvp != tvp) 1329 vput(tvp); 1330 else 1331 vrele(tvp); 1332 } 1333 if (tvp != rtvp && rtvp != NULLVP) 1334 vrele(rtvp); 1335 if (fdvp != rfdvp) 1336 vrele(rfdvp); 1337 if (fvp != rfvp) 1338 vrele(rfvp); 1339 vrele(fdvp); 1340 vrele(fvp); 1341 1342 UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); 1343 1344 return (error); 1345 } 1346 1347 static int 1348 unionfs_mkdir(struct vop_mkdir_args *ap) 1349 { 1350 struct unionfs_node *dunp; 1351 struct componentname *cnp; 1352 struct thread *td; 1353 struct vnode *udvp; 1354 struct vnode *uvp; 1355 struct vattr va; 1356 int error; 1357 int lkflags; 1358 1359 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n"); 1360 1361 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1362 1363 error = EROFS; 1364 dunp = VTOUNIONFS(ap->a_dvp); 1365 cnp = ap->a_cnp; 1366 lkflags = cnp->cn_lkflags; 1367 td = curthread; 1368 udvp = dunp->un_uppervp; 1369 1370 if (udvp != NULLVP) { 1371 /* check opaque */ 1372 if (!(cnp->cn_flags & ISWHITEOUT)) { 1373 error = VOP_GETATTR(udvp, &va, cnp->cn_cred); 1374 if (error != 0) 1375 return (error); 1376 if ((va.va_flags & OPAQUE) != 0) 1377 cnp->cn_flags |= ISWHITEOUT; 1378 } 1379 1380 if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { 1381 VOP_UNLOCK(uvp); 1382 cnp->cn_lkflags = LK_EXCLUSIVE; 1383 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1384 ap->a_dvp, ap->a_vpp, cnp, td); 1385 cnp->cn_lkflags = lkflags; 1386 vrele(uvp); 1387 } 1388 } 1389 1390 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error); 1391 1392 return (error); 1393 } 1394 1395 static int 1396 unionfs_rmdir(struct vop_rmdir_args *ap) 1397 { 1398 struct unionfs_node *dunp; 1399 struct unionfs_node *unp; 1400 struct unionfs_mount *ump; 1401 struct componentname *cnp; 1402 struct thread *td; 1403 struct vnode *udvp; 1404 struct vnode *uvp; 1405 struct vnode *lvp; 1406 int error; 1407 1408 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n"); 1409 1410 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1411 KASSERT_UNIONFS_VNODE(ap->a_vp); 1412 1413 error = 0; 1414 dunp = VTOUNIONFS(ap->a_dvp); 1415 unp = VTOUNIONFS(ap->a_vp); 1416 cnp = ap->a_cnp; 1417 td = curthread; 1418 udvp = dunp->un_uppervp; 1419 uvp = unp->un_uppervp; 1420 lvp = unp->un_lowervp; 1421 1422 if (udvp == NULLVP) 1423 return (EROFS); 1424 1425 if (udvp == uvp) 1426 return (EOPNOTSUPP); 1427 1428 if (uvp != NULLVP) { 1429 if (lvp != NULLVP) { 1430 error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td); 1431 if (error != 0) 1432 return (error); 1433 } 1434 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 1435 if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP) 1436 cnp->cn_flags |= DOWHITEOUT; 1437 /* 1438 * The relookup path will need to relock the parent dvp and 1439 * possibly the vp as well. Locking is expected to be done 1440 * in parent->child order; drop the lock on vp to avoid LOR 1441 * and potential recursion on vp's lock. 1442 * vp is expected to remain referenced during VOP_RMDIR(), 1443 * so vref/vrele should not be necessary here. 1444 */ 1445 VOP_UNLOCK(ap->a_vp); 1446 VNPASS(vrefcnt(ap->a_vp) > 0, ap->a_vp); 1447 error = unionfs_relookup_for_delete(ap->a_dvp, cnp, td); 1448 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1449 if (error == 0 && VN_IS_DOOMED(uvp)) 1450 error = ENOENT; 1451 if (error == 0) 1452 error = VOP_RMDIR(udvp, uvp, cnp); 1453 } else if (lvp != NULLVP) 1454 error = unionfs_mkwhiteout(udvp, cnp, td, 1455 unp->un_path, unp->un_pathlen); 1456 1457 if (error == 0) { 1458 cache_purge(ap->a_dvp); 1459 cache_purge(ap->a_vp); 1460 } 1461 1462 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error); 1463 1464 return (error); 1465 } 1466 1467 static int 1468 unionfs_symlink(struct vop_symlink_args *ap) 1469 { 1470 struct unionfs_node *dunp; 1471 struct componentname *cnp; 1472 struct thread *td; 1473 struct vnode *udvp; 1474 struct vnode *uvp; 1475 int error; 1476 int lkflags; 1477 1478 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n"); 1479 1480 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1481 1482 error = EROFS; 1483 dunp = VTOUNIONFS(ap->a_dvp); 1484 cnp = ap->a_cnp; 1485 lkflags = cnp->cn_lkflags; 1486 td = curthread; 1487 udvp = dunp->un_uppervp; 1488 1489 if (udvp != NULLVP) { 1490 error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); 1491 if (error == 0) { 1492 VOP_UNLOCK(uvp); 1493 cnp->cn_lkflags = LK_EXCLUSIVE; 1494 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1495 ap->a_dvp, ap->a_vpp, cnp, td); 1496 cnp->cn_lkflags = lkflags; 1497 vrele(uvp); 1498 } 1499 } 1500 1501 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error); 1502 1503 return (error); 1504 } 1505 1506 static int 1507 unionfs_readdir(struct vop_readdir_args *ap) 1508 { 1509 struct unionfs_node *unp; 1510 struct unionfs_node_status *unsp; 1511 struct uio *uio; 1512 struct vnode *vp; 1513 struct vnode *uvp; 1514 struct vnode *lvp; 1515 struct thread *td; 1516 struct vattr va; 1517 1518 u_long *cookies_bk; 1519 int error; 1520 int eofflag; 1521 int locked; 1522 int ncookies_bk; 1523 int uio_offset_bk; 1524 1525 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n"); 1526 1527 KASSERT_UNIONFS_VNODE(ap->a_vp); 1528 1529 error = 0; 1530 eofflag = 0; 1531 locked = 0; 1532 uio_offset_bk = 0; 1533 uio = ap->a_uio; 1534 uvp = NULLVP; 1535 lvp = NULLVP; 1536 td = uio->uio_td; 1537 ncookies_bk = 0; 1538 cookies_bk = NULL; 1539 1540 vp = ap->a_vp; 1541 if (vp->v_type != VDIR) 1542 return (ENOTDIR); 1543 1544 /* check the open count. unionfs needs to open before readdir. */ 1545 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 1546 if (vn_lock(vp, LK_UPGRADE) != 0) 1547 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1548 locked = 1; 1549 } 1550 unp = VTOUNIONFS(vp); 1551 if (unp == NULL) 1552 error = EBADF; 1553 else { 1554 uvp = unp->un_uppervp; 1555 lvp = unp->un_lowervp; 1556 unionfs_get_node_status(unp, td, &unsp); 1557 if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || 1558 (lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { 1559 unionfs_tryrem_node_status(unp, unsp); 1560 error = EBADF; 1561 } 1562 } 1563 if (locked) 1564 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 1565 if (error != 0) 1566 goto unionfs_readdir_exit; 1567 1568 /* check opaque */ 1569 if (uvp != NULLVP && lvp != NULLVP) { 1570 if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0) 1571 goto unionfs_readdir_exit; 1572 if (va.va_flags & OPAQUE) 1573 lvp = NULLVP; 1574 } 1575 1576 /* upper only */ 1577 if (uvp != NULLVP && lvp == NULLVP) { 1578 error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag, 1579 ap->a_ncookies, ap->a_cookies); 1580 unsp->uns_readdir_status = 0; 1581 1582 goto unionfs_readdir_exit; 1583 } 1584 1585 /* lower only */ 1586 if (uvp == NULLVP && lvp != NULLVP) { 1587 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1588 ap->a_ncookies, ap->a_cookies); 1589 unsp->uns_readdir_status = 2; 1590 1591 goto unionfs_readdir_exit; 1592 } 1593 1594 /* 1595 * readdir upper and lower 1596 */ 1597 KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp")); 1598 KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp")); 1599 if (uio->uio_offset == 0) 1600 unsp->uns_readdir_status = 0; 1601 1602 if (unsp->uns_readdir_status == 0) { 1603 /* read upper */ 1604 error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag, 1605 ap->a_ncookies, ap->a_cookies); 1606 1607 if (error != 0 || eofflag == 0) 1608 goto unionfs_readdir_exit; 1609 unsp->uns_readdir_status = 1; 1610 1611 /* 1612 * UFS(and other FS) needs size of uio_resid larger than 1613 * DIRBLKSIZ. 1614 * size of DIRBLKSIZ equals DEV_BSIZE. 1615 * (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h) 1616 */ 1617 if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1))) 1618 goto unionfs_readdir_exit; 1619 1620 /* 1621 * Backup cookies. 1622 * It prepares to readdir in lower. 1623 */ 1624 if (ap->a_ncookies != NULL) { 1625 ncookies_bk = *(ap->a_ncookies); 1626 *(ap->a_ncookies) = 0; 1627 } 1628 if (ap->a_cookies != NULL) { 1629 cookies_bk = *(ap->a_cookies); 1630 *(ap->a_cookies) = NULL; 1631 } 1632 } 1633 1634 /* initialize for readdir in lower */ 1635 if (unsp->uns_readdir_status == 1) { 1636 unsp->uns_readdir_status = 2; 1637 /* 1638 * Backup uio_offset. See the comment after the 1639 * VOP_READDIR call on the lower layer. 1640 */ 1641 uio_offset_bk = uio->uio_offset; 1642 uio->uio_offset = 0; 1643 } 1644 1645 if (lvp == NULLVP) { 1646 error = EBADF; 1647 goto unionfs_readdir_exit; 1648 } 1649 /* read lower */ 1650 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1651 ap->a_ncookies, ap->a_cookies); 1652 1653 /* 1654 * We can't return an uio_offset of 0: this would trigger an 1655 * infinite loop, because the next call to unionfs_readdir would 1656 * always restart with the upper layer (uio_offset == 0) and 1657 * always return some data. 1658 * 1659 * This happens when the lower layer root directory is removed. 1660 * (A root directory deleting of unionfs should not be permitted. 1661 * But current VFS can not do it.) 1662 */ 1663 if (uio->uio_offset == 0) 1664 uio->uio_offset = uio_offset_bk; 1665 1666 if (cookies_bk != NULL) { 1667 /* merge cookies */ 1668 int size; 1669 u_long *newcookies, *pos; 1670 1671 size = *(ap->a_ncookies) + ncookies_bk; 1672 newcookies = (u_long *) malloc(size * sizeof(u_long), 1673 M_TEMP, M_WAITOK); 1674 pos = newcookies; 1675 1676 memcpy(pos, cookies_bk, ncookies_bk * sizeof(u_long)); 1677 pos += ncookies_bk; 1678 memcpy(pos, *(ap->a_cookies), 1679 *(ap->a_ncookies) * sizeof(u_long)); 1680 free(cookies_bk, M_TEMP); 1681 free(*(ap->a_cookies), M_TEMP); 1682 *(ap->a_ncookies) = size; 1683 *(ap->a_cookies) = newcookies; 1684 } 1685 1686 unionfs_readdir_exit: 1687 if (error != 0 && ap->a_eofflag != NULL) 1688 *(ap->a_eofflag) = 1; 1689 1690 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error); 1691 1692 return (error); 1693 } 1694 1695 static int 1696 unionfs_readlink(struct vop_readlink_args *ap) 1697 { 1698 struct unionfs_node *unp; 1699 struct vnode *vp; 1700 int error; 1701 1702 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n"); 1703 1704 KASSERT_UNIONFS_VNODE(ap->a_vp); 1705 1706 unp = VTOUNIONFS(ap->a_vp); 1707 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 1708 1709 error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); 1710 1711 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error); 1712 1713 return (error); 1714 } 1715 1716 static int 1717 unionfs_getwritemount(struct vop_getwritemount_args *ap) 1718 { 1719 struct vnode *uvp; 1720 struct vnode *vp; 1721 int error; 1722 1723 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n"); 1724 1725 error = 0; 1726 vp = ap->a_vp; 1727 1728 if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY)) 1729 return (EACCES); 1730 1731 KASSERT_UNIONFS_VNODE(vp); 1732 1733 uvp = UNIONFSVPTOUPPERVP(vp); 1734 if (uvp == NULLVP && VREG == vp->v_type) 1735 uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp); 1736 1737 if (uvp != NULLVP) 1738 error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); 1739 else { 1740 VI_LOCK(vp); 1741 if (vp->v_holdcnt == 0) 1742 error = EOPNOTSUPP; 1743 else 1744 error = EACCES; 1745 VI_UNLOCK(vp); 1746 } 1747 1748 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error); 1749 1750 return (error); 1751 } 1752 1753 static int 1754 unionfs_inactive(struct vop_inactive_args *ap) 1755 { 1756 ap->a_vp->v_object = NULL; 1757 vrecycle(ap->a_vp); 1758 return (0); 1759 } 1760 1761 static int 1762 unionfs_reclaim(struct vop_reclaim_args *ap) 1763 { 1764 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */ 1765 1766 unionfs_noderem(ap->a_vp, curthread); 1767 1768 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */ 1769 1770 return (0); 1771 } 1772 1773 static int 1774 unionfs_print(struct vop_print_args *ap) 1775 { 1776 struct unionfs_node *unp; 1777 /* struct unionfs_node_status *unsp; */ 1778 1779 unp = VTOUNIONFS(ap->a_vp); 1780 /* unionfs_get_node_status(unp, curthread, &unsp); */ 1781 1782 printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n", 1783 ap->a_vp, unp->un_uppervp, unp->un_lowervp); 1784 /* 1785 printf("unionfs opencnt: uppervp=%d, lowervp=%d\n", 1786 unsp->uns_upper_opencnt, unsp->uns_lower_opencnt); 1787 */ 1788 1789 if (unp->un_uppervp != NULLVP) 1790 vn_printf(unp->un_uppervp, "unionfs: upper "); 1791 if (unp->un_lowervp != NULLVP) 1792 vn_printf(unp->un_lowervp, "unionfs: lower "); 1793 1794 return (0); 1795 } 1796 1797 static int 1798 unionfs_islocked(struct vop_islocked_args *ap) 1799 { 1800 struct unionfs_node *unp; 1801 1802 KASSERT_UNIONFS_VNODE(ap->a_vp); 1803 1804 unp = VTOUNIONFS(ap->a_vp); 1805 if (unp == NULL) 1806 return (vop_stdislocked(ap)); 1807 1808 if (unp->un_uppervp != NULLVP) 1809 return (VOP_ISLOCKED(unp->un_uppervp)); 1810 if (unp->un_lowervp != NULLVP) 1811 return (VOP_ISLOCKED(unp->un_lowervp)); 1812 return (vop_stdislocked(ap)); 1813 } 1814 1815 static int 1816 unionfs_get_llt_revlock(struct vnode *vp, int flags) 1817 { 1818 int revlock; 1819 1820 revlock = 0; 1821 1822 switch (flags & LK_TYPE_MASK) { 1823 case LK_SHARED: 1824 if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) 1825 revlock = LK_UPGRADE; 1826 else 1827 revlock = LK_RELEASE; 1828 break; 1829 case LK_EXCLUSIVE: 1830 case LK_UPGRADE: 1831 revlock = LK_RELEASE; 1832 break; 1833 case LK_DOWNGRADE: 1834 revlock = LK_UPGRADE; 1835 break; 1836 default: 1837 break; 1838 } 1839 1840 return (revlock); 1841 } 1842 1843 /* 1844 * The state of an acquired lock is adjusted similarly to 1845 * the time of error generating. 1846 * flags: LK_RELEASE or LK_UPGRADE 1847 */ 1848 static void 1849 unionfs_revlock(struct vnode *vp, int flags) 1850 { 1851 if (flags & LK_RELEASE) 1852 VOP_UNLOCK_FLAGS(vp, flags); 1853 else { 1854 /* UPGRADE */ 1855 if (vn_lock(vp, flags) != 0) 1856 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1857 } 1858 } 1859 1860 static int 1861 unionfs_lock(struct vop_lock1_args *ap) 1862 { 1863 struct mount *mp; 1864 struct unionfs_mount *ump; 1865 struct unionfs_node *unp; 1866 struct vnode *vp; 1867 struct vnode *uvp; 1868 struct vnode *lvp; 1869 int error; 1870 int flags; 1871 int revlock; 1872 int interlock; 1873 int uhold; 1874 1875 KASSERT_UNIONFS_VNODE(ap->a_vp); 1876 1877 error = 0; 1878 interlock = 1; 1879 uhold = 0; 1880 flags = ap->a_flags; 1881 vp = ap->a_vp; 1882 1883 if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK)) 1884 return (VOP_UNLOCK_FLAGS(vp, flags | LK_RELEASE)); 1885 1886 if ((flags & LK_INTERLOCK) == 0) 1887 VI_LOCK(vp); 1888 1889 mp = vp->v_mount; 1890 if (mp == NULL) 1891 goto unionfs_lock_null_vnode; 1892 1893 ump = MOUNTTOUNIONFSMOUNT(mp); 1894 unp = VTOUNIONFS(vp); 1895 if (ump == NULL || unp == NULL) 1896 goto unionfs_lock_null_vnode; 1897 lvp = unp->un_lowervp; 1898 uvp = unp->un_uppervp; 1899 1900 if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0) 1901 panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); 1902 1903 if ((vp->v_iflag & VI_OWEINACT) != 0) 1904 flags |= LK_NOWAIT; 1905 1906 /* 1907 * Sometimes, lower or upper is already exclusive locked. 1908 * (ex. vfs_domount: mounted vnode is already locked.) 1909 */ 1910 if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE && 1911 vp == ump->um_rootvp) 1912 flags |= LK_CANRECURSE; 1913 1914 if (lvp != NULLVP) { 1915 if (uvp != NULLVP && flags & LK_UPGRADE) { 1916 /* 1917 * Share Lock is once released and a deadlock is 1918 * avoided. 1919 */ 1920 vholdnz(uvp); 1921 uhold = 1; 1922 VOP_UNLOCK(uvp); 1923 unp = VTOUNIONFS(vp); 1924 if (unp == NULL) { 1925 /* vnode is released. */ 1926 VI_UNLOCK(vp); 1927 VOP_UNLOCK(lvp); 1928 vdrop(uvp); 1929 return (EBUSY); 1930 } 1931 } 1932 VI_LOCK_FLAGS(lvp, MTX_DUPOK); 1933 flags |= LK_INTERLOCK; 1934 vholdl(lvp); 1935 1936 VI_UNLOCK(vp); 1937 ap->a_flags &= ~LK_INTERLOCK; 1938 1939 error = VOP_LOCK(lvp, flags); 1940 1941 VI_LOCK(vp); 1942 unp = VTOUNIONFS(vp); 1943 if (unp == NULL) { 1944 /* vnode is released. */ 1945 VI_UNLOCK(vp); 1946 if (error == 0) 1947 VOP_UNLOCK(lvp); 1948 vdrop(lvp); 1949 if (uhold != 0) 1950 vdrop(uvp); 1951 return (vop_stdlock(ap)); 1952 } 1953 } 1954 1955 if (error == 0 && uvp != NULLVP) { 1956 if (uhold && flags & LK_UPGRADE) { 1957 flags &= ~LK_TYPE_MASK; 1958 flags |= LK_EXCLUSIVE; 1959 } 1960 VI_LOCK_FLAGS(uvp, MTX_DUPOK); 1961 flags |= LK_INTERLOCK; 1962 if (uhold == 0) { 1963 vholdl(uvp); 1964 uhold = 1; 1965 } 1966 1967 VI_UNLOCK(vp); 1968 ap->a_flags &= ~LK_INTERLOCK; 1969 1970 error = VOP_LOCK(uvp, flags); 1971 1972 VI_LOCK(vp); 1973 unp = VTOUNIONFS(vp); 1974 if (unp == NULL) { 1975 /* vnode is released. */ 1976 VI_UNLOCK(vp); 1977 if (error == 0) 1978 VOP_UNLOCK(uvp); 1979 vdrop(uvp); 1980 if (lvp != NULLVP) { 1981 VOP_UNLOCK(lvp); 1982 vdrop(lvp); 1983 } 1984 return (vop_stdlock(ap)); 1985 } 1986 if (error != 0 && lvp != NULLVP) { 1987 /* rollback */ 1988 VI_UNLOCK(vp); 1989 unionfs_revlock(lvp, revlock); 1990 interlock = 0; 1991 } 1992 } 1993 1994 if (interlock) 1995 VI_UNLOCK(vp); 1996 if (lvp != NULLVP) 1997 vdrop(lvp); 1998 if (uhold != 0) 1999 vdrop(uvp); 2000 2001 return (error); 2002 2003 unionfs_lock_null_vnode: 2004 ap->a_flags |= LK_INTERLOCK; 2005 return (vop_stdlock(ap)); 2006 } 2007 2008 static int 2009 unionfs_unlock(struct vop_unlock_args *ap) 2010 { 2011 struct vnode *vp; 2012 struct vnode *lvp; 2013 struct vnode *uvp; 2014 struct unionfs_node *unp; 2015 int error; 2016 int uhold; 2017 2018 KASSERT_UNIONFS_VNODE(ap->a_vp); 2019 2020 error = 0; 2021 uhold = 0; 2022 vp = ap->a_vp; 2023 2024 unp = VTOUNIONFS(vp); 2025 if (unp == NULL) 2026 goto unionfs_unlock_null_vnode; 2027 lvp = unp->un_lowervp; 2028 uvp = unp->un_uppervp; 2029 2030 if (lvp != NULLVP) { 2031 vholdnz(lvp); 2032 error = VOP_UNLOCK(lvp); 2033 } 2034 2035 if (error == 0 && uvp != NULLVP) { 2036 vholdnz(uvp); 2037 uhold = 1; 2038 error = VOP_UNLOCK(uvp); 2039 } 2040 2041 if (lvp != NULLVP) 2042 vdrop(lvp); 2043 if (uhold != 0) 2044 vdrop(uvp); 2045 2046 return error; 2047 2048 unionfs_unlock_null_vnode: 2049 return (vop_stdunlock(ap)); 2050 } 2051 2052 static int 2053 unionfs_pathconf(struct vop_pathconf_args *ap) 2054 { 2055 struct unionfs_node *unp; 2056 struct vnode *vp; 2057 2058 KASSERT_UNIONFS_VNODE(ap->a_vp); 2059 2060 unp = VTOUNIONFS(ap->a_vp); 2061 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2062 2063 return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval)); 2064 } 2065 2066 static int 2067 unionfs_advlock(struct vop_advlock_args *ap) 2068 { 2069 struct unionfs_node *unp; 2070 struct unionfs_node_status *unsp; 2071 struct vnode *vp; 2072 struct vnode *uvp; 2073 struct thread *td; 2074 int error; 2075 2076 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n"); 2077 2078 KASSERT_UNIONFS_VNODE(ap->a_vp); 2079 2080 vp = ap->a_vp; 2081 td = curthread; 2082 2083 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2084 2085 unp = VTOUNIONFS(ap->a_vp); 2086 uvp = unp->un_uppervp; 2087 2088 if (uvp == NULLVP) { 2089 error = unionfs_copyfile(unp, 1, td->td_ucred, td); 2090 if (error != 0) 2091 goto unionfs_advlock_abort; 2092 uvp = unp->un_uppervp; 2093 2094 unionfs_get_node_status(unp, td, &unsp); 2095 if (unsp->uns_lower_opencnt > 0) { 2096 /* try reopen the vnode */ 2097 error = VOP_OPEN(uvp, unsp->uns_lower_openmode, 2098 td->td_ucred, td, NULL); 2099 if (error) 2100 goto unionfs_advlock_abort; 2101 unsp->uns_upper_opencnt++; 2102 VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, 2103 td->td_ucred, td); 2104 unsp->uns_lower_opencnt--; 2105 } else 2106 unionfs_tryrem_node_status(unp, unsp); 2107 } 2108 2109 VOP_UNLOCK(vp); 2110 2111 error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); 2112 2113 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2114 2115 return error; 2116 2117 unionfs_advlock_abort: 2118 VOP_UNLOCK(vp); 2119 2120 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2121 2122 return error; 2123 } 2124 2125 static int 2126 unionfs_strategy(struct vop_strategy_args *ap) 2127 { 2128 struct unionfs_node *unp; 2129 struct vnode *vp; 2130 2131 KASSERT_UNIONFS_VNODE(ap->a_vp); 2132 2133 unp = VTOUNIONFS(ap->a_vp); 2134 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2135 2136 #ifdef DIAGNOSTIC 2137 if (vp == NULLVP) 2138 panic("unionfs_strategy: nullvp"); 2139 2140 if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp) 2141 panic("unionfs_strategy: writing to lowervp"); 2142 #endif 2143 2144 return (VOP_STRATEGY(vp, ap->a_bp)); 2145 } 2146 2147 static int 2148 unionfs_getacl(struct vop_getacl_args *ap) 2149 { 2150 struct unionfs_node *unp; 2151 struct vnode *vp; 2152 int error; 2153 2154 KASSERT_UNIONFS_VNODE(ap->a_vp); 2155 2156 unp = VTOUNIONFS(ap->a_vp); 2157 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2158 2159 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n"); 2160 2161 error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2162 2163 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error); 2164 2165 return (error); 2166 } 2167 2168 static int 2169 unionfs_setacl(struct vop_setacl_args *ap) 2170 { 2171 struct unionfs_node *unp; 2172 struct vnode *uvp; 2173 struct vnode *lvp; 2174 struct thread *td; 2175 int error; 2176 2177 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n"); 2178 2179 KASSERT_UNIONFS_VNODE(ap->a_vp); 2180 2181 error = EROFS; 2182 unp = VTOUNIONFS(ap->a_vp); 2183 uvp = unp->un_uppervp; 2184 lvp = unp->un_lowervp; 2185 td = ap->a_td; 2186 2187 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2188 return (EROFS); 2189 2190 if (uvp == NULLVP && lvp->v_type == VREG) { 2191 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2192 return (error); 2193 uvp = unp->un_uppervp; 2194 } 2195 2196 if (uvp != NULLVP) 2197 error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td); 2198 2199 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error); 2200 2201 return (error); 2202 } 2203 2204 static int 2205 unionfs_aclcheck(struct vop_aclcheck_args *ap) 2206 { 2207 struct unionfs_node *unp; 2208 struct vnode *vp; 2209 int error; 2210 2211 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n"); 2212 2213 KASSERT_UNIONFS_VNODE(ap->a_vp); 2214 2215 unp = VTOUNIONFS(ap->a_vp); 2216 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2217 2218 error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2219 2220 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error); 2221 2222 return (error); 2223 } 2224 2225 static int 2226 unionfs_openextattr(struct vop_openextattr_args *ap) 2227 { 2228 struct unionfs_node *unp; 2229 struct vnode *vp; 2230 struct vnode *tvp; 2231 int error; 2232 2233 KASSERT_UNIONFS_VNODE(ap->a_vp); 2234 2235 vp = ap->a_vp; 2236 unp = VTOUNIONFS(vp); 2237 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2238 2239 if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) || 2240 (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) 2241 return (EBUSY); 2242 2243 error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); 2244 2245 if (error == 0) { 2246 if (vn_lock(vp, LK_UPGRADE) != 0) 2247 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2248 if (tvp == unp->un_uppervp) 2249 unp->un_flag |= UNIONFS_OPENEXTU; 2250 else 2251 unp->un_flag |= UNIONFS_OPENEXTL; 2252 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2253 } 2254 2255 return (error); 2256 } 2257 2258 static int 2259 unionfs_closeextattr(struct vop_closeextattr_args *ap) 2260 { 2261 struct unionfs_node *unp; 2262 struct vnode *vp; 2263 struct vnode *tvp; 2264 int error; 2265 2266 KASSERT_UNIONFS_VNODE(ap->a_vp); 2267 2268 vp = ap->a_vp; 2269 unp = VTOUNIONFS(vp); 2270 tvp = NULLVP; 2271 2272 if (unp->un_flag & UNIONFS_OPENEXTU) 2273 tvp = unp->un_uppervp; 2274 else if (unp->un_flag & UNIONFS_OPENEXTL) 2275 tvp = unp->un_lowervp; 2276 2277 if (tvp == NULLVP) 2278 return (EOPNOTSUPP); 2279 2280 error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); 2281 2282 if (error == 0) { 2283 if (vn_lock(vp, LK_UPGRADE) != 0) 2284 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2285 if (tvp == unp->un_uppervp) 2286 unp->un_flag &= ~UNIONFS_OPENEXTU; 2287 else 2288 unp->un_flag &= ~UNIONFS_OPENEXTL; 2289 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2290 } 2291 2292 return (error); 2293 } 2294 2295 static int 2296 unionfs_getextattr(struct vop_getextattr_args *ap) 2297 { 2298 struct unionfs_node *unp; 2299 struct vnode *vp; 2300 2301 KASSERT_UNIONFS_VNODE(ap->a_vp); 2302 2303 unp = VTOUNIONFS(ap->a_vp); 2304 vp = NULLVP; 2305 2306 if (unp->un_flag & UNIONFS_OPENEXTU) 2307 vp = unp->un_uppervp; 2308 else if (unp->un_flag & UNIONFS_OPENEXTL) 2309 vp = unp->un_lowervp; 2310 2311 if (vp == NULLVP) 2312 return (EOPNOTSUPP); 2313 2314 return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name, 2315 ap->a_uio, ap->a_size, ap->a_cred, ap->a_td)); 2316 } 2317 2318 static int 2319 unionfs_setextattr(struct vop_setextattr_args *ap) 2320 { 2321 struct unionfs_node *unp; 2322 struct vnode *uvp; 2323 struct vnode *lvp; 2324 struct vnode *ovp; 2325 struct ucred *cred; 2326 struct thread *td; 2327 int error; 2328 2329 KASSERT_UNIONFS_VNODE(ap->a_vp); 2330 2331 error = EROFS; 2332 unp = VTOUNIONFS(ap->a_vp); 2333 uvp = unp->un_uppervp; 2334 lvp = unp->un_lowervp; 2335 ovp = NULLVP; 2336 cred = ap->a_cred; 2337 td = ap->a_td; 2338 2339 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n", 2340 unp->un_flag); 2341 2342 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2343 return (EROFS); 2344 2345 if (unp->un_flag & UNIONFS_OPENEXTU) 2346 ovp = unp->un_uppervp; 2347 else if (unp->un_flag & UNIONFS_OPENEXTL) 2348 ovp = unp->un_lowervp; 2349 2350 if (ovp == NULLVP) 2351 return (EOPNOTSUPP); 2352 2353 if (ovp == lvp && lvp->v_type == VREG) { 2354 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2355 if (uvp == NULLVP && 2356 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2357 unionfs_setextattr_reopen: 2358 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2359 VOP_OPENEXTATTR(lvp, cred, td)) { 2360 #ifdef DIAGNOSTIC 2361 panic("unionfs: VOP_OPENEXTATTR failed"); 2362 #endif 2363 unp->un_flag &= ~UNIONFS_OPENEXTL; 2364 } 2365 goto unionfs_setextattr_abort; 2366 } 2367 uvp = unp->un_uppervp; 2368 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2369 goto unionfs_setextattr_reopen; 2370 unp->un_flag &= ~UNIONFS_OPENEXTL; 2371 unp->un_flag |= UNIONFS_OPENEXTU; 2372 ovp = uvp; 2373 } 2374 2375 if (ovp == uvp) 2376 error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2377 ap->a_uio, cred, td); 2378 2379 unionfs_setextattr_abort: 2380 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error); 2381 2382 return (error); 2383 } 2384 2385 static int 2386 unionfs_listextattr(struct vop_listextattr_args *ap) 2387 { 2388 struct unionfs_node *unp; 2389 struct vnode *vp; 2390 2391 KASSERT_UNIONFS_VNODE(ap->a_vp); 2392 2393 unp = VTOUNIONFS(ap->a_vp); 2394 vp = NULLVP; 2395 2396 if (unp->un_flag & UNIONFS_OPENEXTU) 2397 vp = unp->un_uppervp; 2398 else if (unp->un_flag & UNIONFS_OPENEXTL) 2399 vp = unp->un_lowervp; 2400 2401 if (vp == NULLVP) 2402 return (EOPNOTSUPP); 2403 2404 return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio, 2405 ap->a_size, ap->a_cred, ap->a_td)); 2406 } 2407 2408 static int 2409 unionfs_deleteextattr(struct vop_deleteextattr_args *ap) 2410 { 2411 struct unionfs_node *unp; 2412 struct vnode *uvp; 2413 struct vnode *lvp; 2414 struct vnode *ovp; 2415 struct ucred *cred; 2416 struct thread *td; 2417 int error; 2418 2419 KASSERT_UNIONFS_VNODE(ap->a_vp); 2420 2421 error = EROFS; 2422 unp = VTOUNIONFS(ap->a_vp); 2423 uvp = unp->un_uppervp; 2424 lvp = unp->un_lowervp; 2425 ovp = NULLVP; 2426 cred = ap->a_cred; 2427 td = ap->a_td; 2428 2429 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n", 2430 unp->un_flag); 2431 2432 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2433 return (EROFS); 2434 2435 if (unp->un_flag & UNIONFS_OPENEXTU) 2436 ovp = unp->un_uppervp; 2437 else if (unp->un_flag & UNIONFS_OPENEXTL) 2438 ovp = unp->un_lowervp; 2439 2440 if (ovp == NULLVP) 2441 return (EOPNOTSUPP); 2442 2443 if (ovp == lvp && lvp->v_type == VREG) { 2444 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2445 if (uvp == NULLVP && 2446 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2447 unionfs_deleteextattr_reopen: 2448 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2449 VOP_OPENEXTATTR(lvp, cred, td)) { 2450 #ifdef DIAGNOSTIC 2451 panic("unionfs: VOP_OPENEXTATTR failed"); 2452 #endif 2453 unp->un_flag &= ~UNIONFS_OPENEXTL; 2454 } 2455 goto unionfs_deleteextattr_abort; 2456 } 2457 uvp = unp->un_uppervp; 2458 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2459 goto unionfs_deleteextattr_reopen; 2460 unp->un_flag &= ~UNIONFS_OPENEXTL; 2461 unp->un_flag |= UNIONFS_OPENEXTU; 2462 ovp = uvp; 2463 } 2464 2465 if (ovp == uvp) 2466 error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2467 ap->a_cred, ap->a_td); 2468 2469 unionfs_deleteextattr_abort: 2470 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error); 2471 2472 return (error); 2473 } 2474 2475 static int 2476 unionfs_setlabel(struct vop_setlabel_args *ap) 2477 { 2478 struct unionfs_node *unp; 2479 struct vnode *uvp; 2480 struct vnode *lvp; 2481 struct thread *td; 2482 int error; 2483 2484 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n"); 2485 2486 KASSERT_UNIONFS_VNODE(ap->a_vp); 2487 2488 error = EROFS; 2489 unp = VTOUNIONFS(ap->a_vp); 2490 uvp = unp->un_uppervp; 2491 lvp = unp->un_lowervp; 2492 td = ap->a_td; 2493 2494 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2495 return (EROFS); 2496 2497 if (uvp == NULLVP && lvp->v_type == VREG) { 2498 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2499 return (error); 2500 uvp = unp->un_uppervp; 2501 } 2502 2503 if (uvp != NULLVP) 2504 error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td); 2505 2506 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error); 2507 2508 return (error); 2509 } 2510 2511 static int 2512 unionfs_vptofh(struct vop_vptofh_args *ap) 2513 { 2514 return (EOPNOTSUPP); 2515 } 2516 2517 static int 2518 unionfs_add_writecount(struct vop_add_writecount_args *ap) 2519 { 2520 struct vnode *tvp, *vp; 2521 struct unionfs_node *unp; 2522 int error; 2523 2524 vp = ap->a_vp; 2525 unp = VTOUNIONFS(vp); 2526 tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; 2527 VI_LOCK(vp); 2528 /* text refs are bypassed to lowervp */ 2529 VNASSERT(vp->v_writecount >= 0, vp, ("wrong null writecount")); 2530 VNASSERT(vp->v_writecount + ap->a_inc >= 0, vp, 2531 ("wrong writecount inc %d", ap->a_inc)); 2532 if (tvp != NULL) 2533 error = VOP_ADD_WRITECOUNT(tvp, ap->a_inc); 2534 else if (vp->v_writecount < 0) 2535 error = ETXTBSY; 2536 else 2537 error = 0; 2538 if (error == 0) 2539 vp->v_writecount += ap->a_inc; 2540 VI_UNLOCK(vp); 2541 return (error); 2542 } 2543 2544 struct vop_vector unionfs_vnodeops = { 2545 .vop_default = &default_vnodeops, 2546 2547 .vop_access = unionfs_access, 2548 .vop_aclcheck = unionfs_aclcheck, 2549 .vop_advlock = unionfs_advlock, 2550 .vop_bmap = VOP_EOPNOTSUPP, 2551 .vop_cachedlookup = unionfs_lookup, 2552 .vop_close = unionfs_close, 2553 .vop_closeextattr = unionfs_closeextattr, 2554 .vop_create = unionfs_create, 2555 .vop_deleteextattr = unionfs_deleteextattr, 2556 .vop_fsync = unionfs_fsync, 2557 .vop_getacl = unionfs_getacl, 2558 .vop_getattr = unionfs_getattr, 2559 .vop_getextattr = unionfs_getextattr, 2560 .vop_getwritemount = unionfs_getwritemount, 2561 .vop_inactive = unionfs_inactive, 2562 .vop_need_inactive = vop_stdneed_inactive, 2563 .vop_islocked = unionfs_islocked, 2564 .vop_ioctl = unionfs_ioctl, 2565 .vop_link = unionfs_link, 2566 .vop_listextattr = unionfs_listextattr, 2567 .vop_lock1 = unionfs_lock, 2568 .vop_lookup = vfs_cache_lookup, 2569 .vop_mkdir = unionfs_mkdir, 2570 .vop_mknod = unionfs_mknod, 2571 .vop_open = unionfs_open, 2572 .vop_openextattr = unionfs_openextattr, 2573 .vop_pathconf = unionfs_pathconf, 2574 .vop_poll = unionfs_poll, 2575 .vop_print = unionfs_print, 2576 .vop_read = unionfs_read, 2577 .vop_readdir = unionfs_readdir, 2578 .vop_readlink = unionfs_readlink, 2579 .vop_reclaim = unionfs_reclaim, 2580 .vop_remove = unionfs_remove, 2581 .vop_rename = unionfs_rename, 2582 .vop_rmdir = unionfs_rmdir, 2583 .vop_setacl = unionfs_setacl, 2584 .vop_setattr = unionfs_setattr, 2585 .vop_setextattr = unionfs_setextattr, 2586 .vop_setlabel = unionfs_setlabel, 2587 .vop_strategy = unionfs_strategy, 2588 .vop_symlink = unionfs_symlink, 2589 .vop_unlock = unionfs_unlock, 2590 .vop_whiteout = unionfs_whiteout, 2591 .vop_write = unionfs_write, 2592 .vop_vptofh = unionfs_vptofh, 2593 .vop_add_writecount = unionfs_add_writecount, 2594 }; 2595 VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops); 2596