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 <machine/atomic.h> 65 66 #include <vm/vm.h> 67 #include <vm/vm_extern.h> 68 #include <vm/vm_object.h> 69 #include <vm/vnode_pager.h> 70 71 #if 0 72 #define UNIONFS_INTERNAL_DEBUG(msg, args...) printf(msg, ## args) 73 #define UNIONFS_IDBG_RENAME 74 #else 75 #define UNIONFS_INTERNAL_DEBUG(msg, args...) 76 #endif 77 78 #define KASSERT_UNIONFS_VNODE(vp) \ 79 KASSERT(((vp)->v_op == &unionfs_vnodeops), \ 80 ("unionfs: it is not unionfs-vnode")) 81 82 static int 83 unionfs_lookup(struct vop_cachedlookup_args *ap) 84 { 85 struct unionfs_node *dunp; 86 struct vnode *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp; 87 struct vattr va; 88 struct componentname *cnp; 89 struct thread *td; 90 u_long nameiop; 91 u_long cnflags, cnflagsbk; 92 int iswhiteout; 93 int lockflag; 94 int error , uerror, lerror; 95 96 iswhiteout = 0; 97 lockflag = 0; 98 error = uerror = lerror = ENOENT; 99 cnp = ap->a_cnp; 100 nameiop = cnp->cn_nameiop; 101 cnflags = cnp->cn_flags; 102 dvp = ap->a_dvp; 103 dunp = VTOUNIONFS(dvp); 104 udvp = dunp->un_uppervp; 105 ldvp = dunp->un_lowervp; 106 vp = uvp = lvp = NULLVP; 107 td = curthread; 108 *(ap->a_vpp) = NULLVP; 109 110 UNIONFS_INTERNAL_DEBUG( 111 "unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n", 112 nameiop, cnflags, cnp->cn_nameptr); 113 114 if (dvp->v_type != VDIR) 115 return (ENOTDIR); 116 117 /* 118 * If read-only and op is not LOOKUP, will return EROFS. 119 */ 120 if ((cnflags & ISLASTCN) && 121 (dvp->v_mount->mnt_flag & MNT_RDONLY) && 122 LOOKUP != nameiop) 123 return (EROFS); 124 125 /* 126 * lookup dotdot 127 */ 128 if (cnflags & ISDOTDOT) { 129 if (LOOKUP != nameiop && udvp == NULLVP) 130 return (EROFS); 131 132 if (udvp != NULLVP) { 133 dtmpvp = udvp; 134 if (ldvp != NULLVP) 135 VOP_UNLOCK(ldvp); 136 } 137 else 138 dtmpvp = ldvp; 139 140 error = VOP_LOOKUP(dtmpvp, &vp, cnp); 141 142 if (dtmpvp == udvp && ldvp != NULLVP) { 143 VOP_UNLOCK(udvp); 144 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 145 } 146 147 if (error == 0) { 148 /* 149 * Exchange lock and reference from vp to 150 * dunp->un_dvp. vp is upper/lower vnode, but it 151 * will need to return the unionfs vnode. 152 */ 153 if (nameiop == DELETE || nameiop == RENAME || 154 (cnp->cn_lkflags & LK_TYPE_MASK)) 155 VOP_UNLOCK(vp); 156 vrele(vp); 157 158 VOP_UNLOCK(dvp); 159 *(ap->a_vpp) = dunp->un_dvp; 160 vref(dunp->un_dvp); 161 162 if (nameiop == DELETE || nameiop == RENAME) 163 vn_lock(dunp->un_dvp, LK_EXCLUSIVE | LK_RETRY); 164 else if (cnp->cn_lkflags & LK_TYPE_MASK) 165 vn_lock(dunp->un_dvp, cnp->cn_lkflags | 166 LK_RETRY); 167 168 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 169 } else if (error == ENOENT && (cnflags & MAKEENTRY) != 0) 170 cache_enter(dvp, NULLVP, cnp); 171 172 goto unionfs_lookup_return; 173 } 174 175 /* 176 * lookup upper layer 177 */ 178 if (udvp != NULLVP) { 179 uerror = VOP_LOOKUP(udvp, &uvp, cnp); 180 181 if (uerror == 0) { 182 if (udvp == uvp) { /* is dot */ 183 vrele(uvp); 184 *(ap->a_vpp) = dvp; 185 vref(dvp); 186 187 error = uerror; 188 goto unionfs_lookup_return; 189 } 190 if (nameiop == DELETE || nameiop == RENAME || 191 (cnp->cn_lkflags & LK_TYPE_MASK)) 192 VOP_UNLOCK(uvp); 193 } 194 195 /* check whiteout */ 196 if (uerror == ENOENT || uerror == EJUSTRETURN) 197 if (cnp->cn_flags & ISWHITEOUT) 198 iswhiteout = 1; /* don't lookup lower */ 199 if (iswhiteout == 0 && ldvp != NULLVP) 200 if (!VOP_GETATTR(udvp, &va, cnp->cn_cred) && 201 (va.va_flags & OPAQUE)) 202 iswhiteout = 1; /* don't lookup lower */ 203 #if 0 204 UNIONFS_INTERNAL_DEBUG( 205 "unionfs_lookup: debug: whiteout=%d, path=%s\n", 206 iswhiteout, cnp->cn_nameptr); 207 #endif 208 } 209 210 /* 211 * lookup lower layer 212 */ 213 if (ldvp != NULLVP && !(cnflags & DOWHITEOUT) && iswhiteout == 0) { 214 /* always op is LOOKUP */ 215 cnp->cn_nameiop = LOOKUP; 216 cnflagsbk = cnp->cn_flags; 217 cnp->cn_flags = cnflags; 218 219 lerror = VOP_LOOKUP(ldvp, &lvp, cnp); 220 221 cnp->cn_nameiop = nameiop; 222 if (udvp != NULLVP && (uerror == 0 || uerror == EJUSTRETURN)) 223 cnp->cn_flags = cnflagsbk; 224 225 if (lerror == 0) { 226 if (ldvp == lvp) { /* is dot */ 227 if (uvp != NULLVP) 228 vrele(uvp); /* no need? */ 229 vrele(lvp); 230 *(ap->a_vpp) = dvp; 231 vref(dvp); 232 233 UNIONFS_INTERNAL_DEBUG( 234 "unionfs_lookup: leave (%d)\n", lerror); 235 236 return (lerror); 237 } 238 if (cnp->cn_lkflags & LK_TYPE_MASK) 239 VOP_UNLOCK(lvp); 240 } 241 } 242 243 /* 244 * check lookup result 245 */ 246 if (uvp == NULLVP && lvp == NULLVP) { 247 error = (udvp != NULLVP ? uerror : lerror); 248 goto unionfs_lookup_return; 249 } 250 251 /* 252 * check vnode type 253 */ 254 if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) { 255 vrele(lvp); 256 lvp = NULLVP; 257 } 258 259 /* 260 * check shadow dir 261 */ 262 if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP && 263 lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR && 264 !(dvp->v_mount->mnt_flag & MNT_RDONLY) && 265 (1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) { 266 /* get unionfs vnode in order to create a new shadow dir. */ 267 error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp, 268 cnp); 269 if (error != 0) 270 goto unionfs_lookup_cleanup; 271 272 if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK)) 273 VOP_UNLOCK(vp); 274 if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) { 275 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 276 lockflag = 1; 277 } 278 error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount), 279 udvp, VTOUNIONFS(vp), cnp, td); 280 if (lockflag != 0) 281 VOP_UNLOCK(vp); 282 if (error != 0) { 283 UNIONFSDEBUG( 284 "unionfs_lookup: Unable to create shadow dir."); 285 if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) 286 vput(vp); 287 else 288 vrele(vp); 289 goto unionfs_lookup_cleanup; 290 } 291 if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED) 292 vn_lock(vp, LK_SHARED | LK_RETRY); 293 } 294 /* 295 * get unionfs vnode. 296 */ 297 else { 298 if (uvp != NULLVP) 299 error = uerror; 300 else 301 error = lerror; 302 if (error != 0) 303 goto unionfs_lookup_cleanup; 304 /* 305 * get socket vnode. 306 */ 307 if (uvp != NULLVP && uvp->v_type == VSOCK) { 308 vp = uvp; 309 vref(vp); 310 if (cnp->cn_lkflags & LK_TYPE_MASK) 311 vn_lock(vp, cnp->cn_lkflags | LK_RETRY); 312 } 313 else if (lvp != NULLVP && lvp->v_type == VSOCK) { 314 vp = lvp; 315 vref(vp); 316 if (cnp->cn_lkflags & LK_TYPE_MASK) 317 vn_lock(vp, cnp->cn_lkflags | LK_RETRY); 318 } 319 /* 320 * get unionfs vnode. 321 */ 322 else 323 error = unionfs_nodeget(dvp->v_mount, uvp, lvp, 324 dvp, &vp, cnp); 325 if (error != 0) { 326 UNIONFSDEBUG( 327 "unionfs_lookup: Unable to create unionfs vnode."); 328 goto unionfs_lookup_cleanup; 329 } 330 if ((nameiop == DELETE || nameiop == RENAME) && 331 (cnp->cn_lkflags & LK_TYPE_MASK) == 0) 332 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 333 } 334 335 *(ap->a_vpp) = vp; 336 337 if ((cnflags & MAKEENTRY) && vp->v_type != VSOCK) 338 cache_enter(dvp, vp, cnp); 339 340 unionfs_lookup_cleanup: 341 if (uvp != NULLVP) 342 vrele(uvp); 343 if (lvp != NULLVP) 344 vrele(lvp); 345 346 if (error == ENOENT && (cnflags & MAKEENTRY) != 0) 347 cache_enter(dvp, NULLVP, cnp); 348 349 unionfs_lookup_return: 350 351 /* Ensure subsequent vnops will get a valid pathname buffer. */ 352 if (nameiop != LOOKUP && (error == 0 || error == EJUSTRETURN)) 353 cnp->cn_flags |= SAVENAME; 354 355 UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error); 356 357 return (error); 358 } 359 360 static int 361 unionfs_create(struct vop_create_args *ap) 362 { 363 struct unionfs_node *dunp; 364 struct componentname *cnp; 365 struct vnode *udvp; 366 struct vnode *vp; 367 int error; 368 369 UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n"); 370 371 KASSERT_UNIONFS_VNODE(ap->a_dvp); 372 373 dunp = VTOUNIONFS(ap->a_dvp); 374 cnp = ap->a_cnp; 375 udvp = dunp->un_uppervp; 376 error = EROFS; 377 378 if (udvp != NULLVP) { 379 error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap); 380 if (error != 0) 381 goto unionfs_create_abort; 382 383 if (vp->v_type == VSOCK) 384 *(ap->a_vpp) = vp; 385 else { 386 VOP_UNLOCK(vp); 387 error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, 388 ap->a_dvp, ap->a_vpp, cnp); 389 vrele(vp); 390 } 391 } 392 393 unionfs_create_abort: 394 UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error); 395 396 return (error); 397 } 398 399 static int 400 unionfs_whiteout(struct vop_whiteout_args *ap) 401 { 402 struct unionfs_node *dunp; 403 struct componentname *cnp; 404 struct vnode *udvp; 405 int error; 406 407 UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: enter\n"); 408 409 KASSERT_UNIONFS_VNODE(ap->a_dvp); 410 411 dunp = VTOUNIONFS(ap->a_dvp); 412 cnp = ap->a_cnp; 413 udvp = dunp->un_uppervp; 414 error = EOPNOTSUPP; 415 416 if (udvp != NULLVP) { 417 switch (ap->a_flags) { 418 case CREATE: 419 case DELETE: 420 case LOOKUP: 421 error = VOP_WHITEOUT(udvp, cnp, ap->a_flags); 422 break; 423 default: 424 error = EINVAL; 425 break; 426 } 427 } 428 429 UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: leave (%d)\n", error); 430 431 return (error); 432 } 433 434 static int 435 unionfs_mknod(struct vop_mknod_args *ap) 436 { 437 struct unionfs_node *dunp; 438 struct componentname *cnp; 439 struct vnode *udvp; 440 struct vnode *vp; 441 int error; 442 443 UNIONFS_INTERNAL_DEBUG("unionfs_mknod: enter\n"); 444 445 KASSERT_UNIONFS_VNODE(ap->a_dvp); 446 447 dunp = VTOUNIONFS(ap->a_dvp); 448 cnp = ap->a_cnp; 449 udvp = dunp->un_uppervp; 450 error = EROFS; 451 452 if (udvp != NULLVP) { 453 error = VOP_MKNOD(udvp, &vp, cnp, ap->a_vap); 454 if (error != 0) 455 goto unionfs_mknod_abort; 456 457 if (vp->v_type == VSOCK) 458 *(ap->a_vpp) = vp; 459 else { 460 VOP_UNLOCK(vp); 461 error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, 462 ap->a_dvp, ap->a_vpp, cnp); 463 vrele(vp); 464 } 465 } 466 467 unionfs_mknod_abort: 468 UNIONFS_INTERNAL_DEBUG("unionfs_mknod: leave (%d)\n", error); 469 470 return (error); 471 } 472 473 static int 474 unionfs_open(struct vop_open_args *ap) 475 { 476 struct unionfs_node *unp; 477 struct unionfs_node_status *unsp; 478 struct vnode *uvp; 479 struct vnode *lvp; 480 struct vnode *targetvp; 481 struct ucred *cred; 482 struct thread *td; 483 int error; 484 485 UNIONFS_INTERNAL_DEBUG("unionfs_open: enter\n"); 486 487 KASSERT_UNIONFS_VNODE(ap->a_vp); 488 489 error = 0; 490 unp = VTOUNIONFS(ap->a_vp); 491 uvp = unp->un_uppervp; 492 lvp = unp->un_lowervp; 493 targetvp = NULLVP; 494 cred = ap->a_cred; 495 td = ap->a_td; 496 497 unionfs_get_node_status(unp, td, &unsp); 498 499 if (unsp->uns_lower_opencnt > 0 || unsp->uns_upper_opencnt > 0) { 500 /* vnode is already opend. */ 501 if (unsp->uns_upper_opencnt > 0) 502 targetvp = uvp; 503 else 504 targetvp = lvp; 505 506 if (targetvp == lvp && 507 (ap->a_mode & FWRITE) && lvp->v_type == VREG) 508 targetvp = NULLVP; 509 } 510 if (targetvp == NULLVP) { 511 if (uvp == NULLVP) { 512 if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) { 513 error = unionfs_copyfile(unp, 514 !(ap->a_mode & O_TRUNC), cred, td); 515 if (error != 0) 516 goto unionfs_open_abort; 517 targetvp = uvp = unp->un_uppervp; 518 } else 519 targetvp = lvp; 520 } else 521 targetvp = uvp; 522 } 523 524 error = VOP_OPEN(targetvp, ap->a_mode, cred, td, ap->a_fp); 525 if (error == 0) { 526 if (targetvp == uvp) { 527 if (uvp->v_type == VDIR && lvp != NULLVP && 528 unsp->uns_lower_opencnt <= 0) { 529 /* open lower for readdir */ 530 error = VOP_OPEN(lvp, FREAD, cred, td, NULL); 531 if (error != 0) { 532 VOP_CLOSE(uvp, ap->a_mode, cred, td); 533 goto unionfs_open_abort; 534 } 535 unsp->uns_node_flag |= UNS_OPENL_4_READDIR; 536 unsp->uns_lower_opencnt++; 537 } 538 unsp->uns_upper_opencnt++; 539 } else { 540 unsp->uns_lower_opencnt++; 541 unsp->uns_lower_openmode = ap->a_mode; 542 } 543 ap->a_vp->v_object = targetvp->v_object; 544 } 545 546 unionfs_open_abort: 547 if (error != 0) 548 unionfs_tryrem_node_status(unp, unsp); 549 550 UNIONFS_INTERNAL_DEBUG("unionfs_open: leave (%d)\n", error); 551 552 return (error); 553 } 554 555 static int 556 unionfs_close(struct vop_close_args *ap) 557 { 558 struct unionfs_node *unp; 559 struct unionfs_node_status *unsp; 560 struct ucred *cred; 561 struct thread *td; 562 struct vnode *vp; 563 struct vnode *ovp; 564 int error; 565 int locked; 566 567 UNIONFS_INTERNAL_DEBUG("unionfs_close: enter\n"); 568 569 KASSERT_UNIONFS_VNODE(ap->a_vp); 570 571 locked = 0; 572 vp = ap->a_vp; 573 unp = VTOUNIONFS(vp); 574 cred = ap->a_cred; 575 td = ap->a_td; 576 577 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 578 if (vn_lock(vp, LK_UPGRADE) != 0) 579 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 580 locked = 1; 581 } 582 unionfs_get_node_status(unp, td, &unsp); 583 584 if (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0) { 585 #ifdef DIAGNOSTIC 586 printf("unionfs_close: warning: open count is 0\n"); 587 #endif 588 if (unp->un_uppervp != NULLVP) 589 ovp = unp->un_uppervp; 590 else 591 ovp = unp->un_lowervp; 592 } else if (unsp->uns_upper_opencnt > 0) 593 ovp = unp->un_uppervp; 594 else 595 ovp = unp->un_lowervp; 596 597 error = VOP_CLOSE(ovp, ap->a_fflag, cred, td); 598 599 if (error != 0) 600 goto unionfs_close_abort; 601 602 vp->v_object = ovp->v_object; 603 604 if (ovp == unp->un_uppervp) { 605 unsp->uns_upper_opencnt--; 606 if (unsp->uns_upper_opencnt == 0) { 607 if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) { 608 VOP_CLOSE(unp->un_lowervp, FREAD, cred, td); 609 unsp->uns_node_flag &= ~UNS_OPENL_4_READDIR; 610 unsp->uns_lower_opencnt--; 611 } 612 if (unsp->uns_lower_opencnt > 0) 613 vp->v_object = unp->un_lowervp->v_object; 614 } 615 } else 616 unsp->uns_lower_opencnt--; 617 618 unionfs_close_abort: 619 unionfs_tryrem_node_status(unp, unsp); 620 621 if (locked != 0) 622 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 623 624 UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error); 625 626 return (error); 627 } 628 629 /* 630 * Check the access mode toward shadow file/dir. 631 */ 632 static int 633 unionfs_check_corrected_access(accmode_t accmode, struct vattr *va, 634 struct ucred *cred) 635 { 636 uid_t uid; /* upper side vnode's uid */ 637 gid_t gid; /* upper side vnode's gid */ 638 u_short vmode; /* upper side vnode's mode */ 639 u_short mask; 640 641 mask = 0; 642 uid = va->va_uid; 643 gid = va->va_gid; 644 vmode = va->va_mode; 645 646 /* check owner */ 647 if (cred->cr_uid == uid) { 648 if (accmode & VEXEC) 649 mask |= S_IXUSR; 650 if (accmode & VREAD) 651 mask |= S_IRUSR; 652 if (accmode & VWRITE) 653 mask |= S_IWUSR; 654 return ((vmode & mask) == mask ? 0 : EACCES); 655 } 656 657 /* check group */ 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 vnode *udvp; 1353 struct vnode *uvp; 1354 struct vattr va; 1355 int error; 1356 int lkflags; 1357 1358 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n"); 1359 1360 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1361 1362 error = EROFS; 1363 dunp = VTOUNIONFS(ap->a_dvp); 1364 cnp = ap->a_cnp; 1365 lkflags = cnp->cn_lkflags; 1366 udvp = dunp->un_uppervp; 1367 1368 if (udvp != NULLVP) { 1369 /* check opaque */ 1370 if (!(cnp->cn_flags & ISWHITEOUT)) { 1371 error = VOP_GETATTR(udvp, &va, cnp->cn_cred); 1372 if (error != 0) 1373 return (error); 1374 if ((va.va_flags & OPAQUE) != 0) 1375 cnp->cn_flags |= ISWHITEOUT; 1376 } 1377 1378 if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { 1379 VOP_UNLOCK(uvp); 1380 cnp->cn_lkflags = LK_EXCLUSIVE; 1381 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1382 ap->a_dvp, ap->a_vpp, cnp); 1383 cnp->cn_lkflags = lkflags; 1384 vrele(uvp); 1385 } 1386 } 1387 1388 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error); 1389 1390 return (error); 1391 } 1392 1393 static int 1394 unionfs_rmdir(struct vop_rmdir_args *ap) 1395 { 1396 struct unionfs_node *dunp; 1397 struct unionfs_node *unp; 1398 struct unionfs_mount *ump; 1399 struct componentname *cnp; 1400 struct thread *td; 1401 struct vnode *udvp; 1402 struct vnode *uvp; 1403 struct vnode *lvp; 1404 int error; 1405 1406 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n"); 1407 1408 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1409 KASSERT_UNIONFS_VNODE(ap->a_vp); 1410 1411 error = 0; 1412 dunp = VTOUNIONFS(ap->a_dvp); 1413 unp = VTOUNIONFS(ap->a_vp); 1414 cnp = ap->a_cnp; 1415 td = curthread; 1416 udvp = dunp->un_uppervp; 1417 uvp = unp->un_uppervp; 1418 lvp = unp->un_lowervp; 1419 1420 if (udvp == NULLVP) 1421 return (EROFS); 1422 1423 if (udvp == uvp) 1424 return (EOPNOTSUPP); 1425 1426 if (uvp != NULLVP) { 1427 if (lvp != NULLVP) { 1428 error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td); 1429 if (error != 0) 1430 return (error); 1431 } 1432 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 1433 if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP) 1434 cnp->cn_flags |= DOWHITEOUT; 1435 /* 1436 * The relookup path will need to relock the parent dvp and 1437 * possibly the vp as well. Locking is expected to be done 1438 * in parent->child order; drop the lock on vp to avoid LOR 1439 * and potential recursion on vp's lock. 1440 * vp is expected to remain referenced during VOP_RMDIR(), 1441 * so vref/vrele should not be necessary here. 1442 */ 1443 VOP_UNLOCK(ap->a_vp); 1444 VNPASS(vrefcnt(ap->a_vp) > 0, ap->a_vp); 1445 error = unionfs_relookup_for_delete(ap->a_dvp, cnp, td); 1446 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1447 if (error == 0 && VN_IS_DOOMED(uvp)) 1448 error = ENOENT; 1449 if (error == 0) 1450 error = VOP_RMDIR(udvp, uvp, cnp); 1451 } else if (lvp != NULLVP) 1452 error = unionfs_mkwhiteout(udvp, cnp, td, 1453 unp->un_path, unp->un_pathlen); 1454 1455 if (error == 0) { 1456 cache_purge(ap->a_dvp); 1457 cache_purge(ap->a_vp); 1458 } 1459 1460 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error); 1461 1462 return (error); 1463 } 1464 1465 static int 1466 unionfs_symlink(struct vop_symlink_args *ap) 1467 { 1468 struct unionfs_node *dunp; 1469 struct componentname *cnp; 1470 struct vnode *udvp; 1471 struct vnode *uvp; 1472 int error; 1473 int lkflags; 1474 1475 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n"); 1476 1477 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1478 1479 error = EROFS; 1480 dunp = VTOUNIONFS(ap->a_dvp); 1481 cnp = ap->a_cnp; 1482 lkflags = cnp->cn_lkflags; 1483 udvp = dunp->un_uppervp; 1484 1485 if (udvp != NULLVP) { 1486 error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); 1487 if (error == 0) { 1488 VOP_UNLOCK(uvp); 1489 cnp->cn_lkflags = LK_EXCLUSIVE; 1490 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1491 ap->a_dvp, ap->a_vpp, cnp); 1492 cnp->cn_lkflags = lkflags; 1493 vrele(uvp); 1494 } 1495 } 1496 1497 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error); 1498 1499 return (error); 1500 } 1501 1502 static int 1503 unionfs_readdir(struct vop_readdir_args *ap) 1504 { 1505 struct unionfs_node *unp; 1506 struct unionfs_node_status *unsp; 1507 struct uio *uio; 1508 struct vnode *vp; 1509 struct vnode *uvp; 1510 struct vnode *lvp; 1511 struct thread *td; 1512 struct vattr va; 1513 1514 uint64_t *cookies_bk; 1515 int error; 1516 int eofflag; 1517 int locked; 1518 int ncookies_bk; 1519 int uio_offset_bk; 1520 1521 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n"); 1522 1523 KASSERT_UNIONFS_VNODE(ap->a_vp); 1524 1525 error = 0; 1526 eofflag = 0; 1527 locked = 0; 1528 uio_offset_bk = 0; 1529 uio = ap->a_uio; 1530 uvp = NULLVP; 1531 lvp = NULLVP; 1532 td = uio->uio_td; 1533 ncookies_bk = 0; 1534 cookies_bk = NULL; 1535 1536 vp = ap->a_vp; 1537 if (vp->v_type != VDIR) 1538 return (ENOTDIR); 1539 1540 /* check the open count. unionfs needs to open before readdir. */ 1541 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 1542 if (vn_lock(vp, LK_UPGRADE) != 0) 1543 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1544 locked = 1; 1545 } 1546 unp = VTOUNIONFS(vp); 1547 if (unp == NULL) 1548 error = EBADF; 1549 else { 1550 uvp = unp->un_uppervp; 1551 lvp = unp->un_lowervp; 1552 unionfs_get_node_status(unp, td, &unsp); 1553 if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || 1554 (lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { 1555 unionfs_tryrem_node_status(unp, unsp); 1556 error = EBADF; 1557 } 1558 } 1559 if (locked) 1560 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 1561 if (error != 0) 1562 goto unionfs_readdir_exit; 1563 1564 /* check opaque */ 1565 if (uvp != NULLVP && lvp != NULLVP) { 1566 if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0) 1567 goto unionfs_readdir_exit; 1568 if (va.va_flags & OPAQUE) 1569 lvp = NULLVP; 1570 } 1571 1572 /* upper only */ 1573 if (uvp != NULLVP && lvp == NULLVP) { 1574 error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag, 1575 ap->a_ncookies, ap->a_cookies); 1576 unsp->uns_readdir_status = 0; 1577 1578 goto unionfs_readdir_exit; 1579 } 1580 1581 /* lower only */ 1582 if (uvp == NULLVP && lvp != NULLVP) { 1583 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1584 ap->a_ncookies, ap->a_cookies); 1585 unsp->uns_readdir_status = 2; 1586 1587 goto unionfs_readdir_exit; 1588 } 1589 1590 /* 1591 * readdir upper and lower 1592 */ 1593 KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp")); 1594 KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp")); 1595 if (uio->uio_offset == 0) 1596 unsp->uns_readdir_status = 0; 1597 1598 if (unsp->uns_readdir_status == 0) { 1599 /* read upper */ 1600 error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag, 1601 ap->a_ncookies, ap->a_cookies); 1602 1603 if (error != 0 || eofflag == 0) 1604 goto unionfs_readdir_exit; 1605 unsp->uns_readdir_status = 1; 1606 1607 /* 1608 * UFS(and other FS) needs size of uio_resid larger than 1609 * DIRBLKSIZ. 1610 * size of DIRBLKSIZ equals DEV_BSIZE. 1611 * (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h) 1612 */ 1613 if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1))) 1614 goto unionfs_readdir_exit; 1615 1616 /* 1617 * Backup cookies. 1618 * It prepares to readdir in lower. 1619 */ 1620 if (ap->a_ncookies != NULL) { 1621 ncookies_bk = *(ap->a_ncookies); 1622 *(ap->a_ncookies) = 0; 1623 } 1624 if (ap->a_cookies != NULL) { 1625 cookies_bk = *(ap->a_cookies); 1626 *(ap->a_cookies) = NULL; 1627 } 1628 } 1629 1630 /* initialize for readdir in lower */ 1631 if (unsp->uns_readdir_status == 1) { 1632 unsp->uns_readdir_status = 2; 1633 /* 1634 * Backup uio_offset. See the comment after the 1635 * VOP_READDIR call on the lower layer. 1636 */ 1637 uio_offset_bk = uio->uio_offset; 1638 uio->uio_offset = 0; 1639 } 1640 1641 if (lvp == NULLVP) { 1642 error = EBADF; 1643 goto unionfs_readdir_exit; 1644 } 1645 /* read lower */ 1646 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1647 ap->a_ncookies, ap->a_cookies); 1648 1649 /* 1650 * We can't return an uio_offset of 0: this would trigger an 1651 * infinite loop, because the next call to unionfs_readdir would 1652 * always restart with the upper layer (uio_offset == 0) and 1653 * always return some data. 1654 * 1655 * This happens when the lower layer root directory is removed. 1656 * (A root directory deleting of unionfs should not be permitted. 1657 * But current VFS can not do it.) 1658 */ 1659 if (uio->uio_offset == 0) 1660 uio->uio_offset = uio_offset_bk; 1661 1662 if (cookies_bk != NULL) { 1663 /* merge cookies */ 1664 int size; 1665 uint64_t *newcookies, *pos; 1666 1667 size = *(ap->a_ncookies) + ncookies_bk; 1668 newcookies = (uint64_t *) malloc(size * sizeof(*newcookies), 1669 M_TEMP, M_WAITOK); 1670 pos = newcookies; 1671 1672 memcpy(pos, cookies_bk, ncookies_bk * sizeof(*newcookies)); 1673 pos += ncookies_bk; 1674 memcpy(pos, *(ap->a_cookies), 1675 *(ap->a_ncookies) * sizeof(*newcookies)); 1676 free(cookies_bk, M_TEMP); 1677 free(*(ap->a_cookies), M_TEMP); 1678 *(ap->a_ncookies) = size; 1679 *(ap->a_cookies) = newcookies; 1680 } 1681 1682 unionfs_readdir_exit: 1683 if (error != 0 && ap->a_eofflag != NULL) 1684 *(ap->a_eofflag) = 1; 1685 1686 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error); 1687 1688 return (error); 1689 } 1690 1691 static int 1692 unionfs_readlink(struct vop_readlink_args *ap) 1693 { 1694 struct unionfs_node *unp; 1695 struct vnode *vp; 1696 int error; 1697 1698 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n"); 1699 1700 KASSERT_UNIONFS_VNODE(ap->a_vp); 1701 1702 unp = VTOUNIONFS(ap->a_vp); 1703 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 1704 1705 error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); 1706 1707 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error); 1708 1709 return (error); 1710 } 1711 1712 static int 1713 unionfs_getwritemount(struct vop_getwritemount_args *ap) 1714 { 1715 struct vnode *uvp; 1716 struct vnode *vp; 1717 int error; 1718 1719 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n"); 1720 1721 error = 0; 1722 vp = ap->a_vp; 1723 1724 if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY)) 1725 return (EACCES); 1726 1727 KASSERT_UNIONFS_VNODE(vp); 1728 1729 uvp = UNIONFSVPTOUPPERVP(vp); 1730 if (uvp == NULLVP && VREG == vp->v_type) 1731 uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp); 1732 1733 if (uvp != NULLVP) 1734 error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); 1735 else { 1736 VI_LOCK(vp); 1737 if (vp->v_holdcnt == 0) 1738 error = EOPNOTSUPP; 1739 else 1740 error = EACCES; 1741 VI_UNLOCK(vp); 1742 } 1743 1744 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error); 1745 1746 return (error); 1747 } 1748 1749 static int 1750 unionfs_inactive(struct vop_inactive_args *ap) 1751 { 1752 ap->a_vp->v_object = NULL; 1753 vrecycle(ap->a_vp); 1754 return (0); 1755 } 1756 1757 static int 1758 unionfs_reclaim(struct vop_reclaim_args *ap) 1759 { 1760 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */ 1761 1762 unionfs_noderem(ap->a_vp); 1763 1764 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */ 1765 1766 return (0); 1767 } 1768 1769 static int 1770 unionfs_print(struct vop_print_args *ap) 1771 { 1772 struct unionfs_node *unp; 1773 /* struct unionfs_node_status *unsp; */ 1774 1775 unp = VTOUNIONFS(ap->a_vp); 1776 /* unionfs_get_node_status(unp, curthread, &unsp); */ 1777 1778 printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n", 1779 ap->a_vp, unp->un_uppervp, unp->un_lowervp); 1780 /* 1781 printf("unionfs opencnt: uppervp=%d, lowervp=%d\n", 1782 unsp->uns_upper_opencnt, unsp->uns_lower_opencnt); 1783 */ 1784 1785 if (unp->un_uppervp != NULLVP) 1786 vn_printf(unp->un_uppervp, "unionfs: upper "); 1787 if (unp->un_lowervp != NULLVP) 1788 vn_printf(unp->un_lowervp, "unionfs: lower "); 1789 1790 return (0); 1791 } 1792 1793 static int 1794 unionfs_islocked(struct vop_islocked_args *ap) 1795 { 1796 struct unionfs_node *unp; 1797 1798 KASSERT_UNIONFS_VNODE(ap->a_vp); 1799 1800 unp = VTOUNIONFS(ap->a_vp); 1801 if (unp == NULL) 1802 return (vop_stdislocked(ap)); 1803 1804 if (unp->un_uppervp != NULLVP) 1805 return (VOP_ISLOCKED(unp->un_uppervp)); 1806 if (unp->un_lowervp != NULLVP) 1807 return (VOP_ISLOCKED(unp->un_lowervp)); 1808 return (vop_stdislocked(ap)); 1809 } 1810 1811 static int 1812 unionfs_get_llt_revlock(struct vnode *vp, int flags) 1813 { 1814 int revlock; 1815 1816 revlock = 0; 1817 1818 switch (flags & LK_TYPE_MASK) { 1819 case LK_SHARED: 1820 if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) 1821 revlock = LK_UPGRADE; 1822 else 1823 revlock = LK_RELEASE; 1824 break; 1825 case LK_EXCLUSIVE: 1826 case LK_UPGRADE: 1827 revlock = LK_RELEASE; 1828 break; 1829 case LK_DOWNGRADE: 1830 revlock = LK_UPGRADE; 1831 break; 1832 default: 1833 break; 1834 } 1835 1836 return (revlock); 1837 } 1838 1839 /* 1840 * The state of an acquired lock is adjusted similarly to 1841 * the time of error generating. 1842 * flags: LK_RELEASE or LK_UPGRADE 1843 */ 1844 static void 1845 unionfs_revlock(struct vnode *vp, int flags) 1846 { 1847 if (flags & LK_RELEASE) 1848 VOP_UNLOCK_FLAGS(vp, flags); 1849 else { 1850 /* UPGRADE */ 1851 if (vn_lock(vp, flags) != 0) 1852 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1853 } 1854 } 1855 1856 static int 1857 unionfs_lock(struct vop_lock1_args *ap) 1858 { 1859 struct mount *mp; 1860 struct unionfs_mount *ump; 1861 struct unionfs_node *unp; 1862 struct vnode *vp; 1863 struct vnode *uvp; 1864 struct vnode *lvp; 1865 int error; 1866 int flags; 1867 int revlock; 1868 int interlock; 1869 int uhold; 1870 1871 KASSERT_UNIONFS_VNODE(ap->a_vp); 1872 1873 /* 1874 * TODO: rework the unionfs locking scheme. 1875 * It's not guaranteed to be safe to blindly lock two vnodes on 1876 * different mounts as is done here. Further, the entanglement 1877 * of locking both vnodes with the various options that can be 1878 * passed to VOP_LOCK() makes this code hard to reason about. 1879 * Instead, consider locking only the upper vnode, or the lower 1880 * vnode is the upper is not present, and taking separate measures 1881 * to lock both vnodes in the few cases when that is needed. 1882 */ 1883 error = 0; 1884 interlock = 1; 1885 uhold = 0; 1886 flags = ap->a_flags; 1887 vp = ap->a_vp; 1888 1889 if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK)) 1890 return (VOP_UNLOCK_FLAGS(vp, flags | LK_RELEASE)); 1891 1892 if ((flags & LK_INTERLOCK) == 0) 1893 VI_LOCK(vp); 1894 1895 mp = vp->v_mount; 1896 if (mp == NULL) 1897 goto unionfs_lock_null_vnode; 1898 1899 ump = MOUNTTOUNIONFSMOUNT(mp); 1900 unp = VTOUNIONFS(vp); 1901 if (ump == NULL || unp == NULL) 1902 goto unionfs_lock_null_vnode; 1903 lvp = unp->un_lowervp; 1904 uvp = unp->un_uppervp; 1905 1906 if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0) 1907 panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); 1908 1909 if ((vp->v_iflag & VI_OWEINACT) != 0) 1910 flags |= LK_NOWAIT; 1911 1912 /* 1913 * Sometimes, lower or upper is already exclusive locked. 1914 * (ex. vfs_domount: mounted vnode is already locked.) 1915 */ 1916 if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE && 1917 vp == ump->um_rootvp) 1918 flags |= LK_CANRECURSE; 1919 1920 if (lvp != NULLVP) { 1921 if (uvp != NULLVP && flags & LK_UPGRADE) { 1922 /* 1923 * Share Lock is once released and a deadlock is 1924 * avoided. 1925 */ 1926 vholdnz(uvp); 1927 uhold = 1; 1928 VOP_UNLOCK(uvp); 1929 unp = VTOUNIONFS(vp); 1930 if (unp == NULL) { 1931 /* vnode is released. */ 1932 VI_UNLOCK(vp); 1933 VOP_UNLOCK(lvp); 1934 vdrop(uvp); 1935 return (EBUSY); 1936 } 1937 } 1938 VI_LOCK_FLAGS(lvp, MTX_DUPOK); 1939 flags |= LK_INTERLOCK; 1940 vholdl(lvp); 1941 1942 VI_UNLOCK(vp); 1943 ap->a_flags &= ~LK_INTERLOCK; 1944 1945 error = VOP_LOCK(lvp, flags); 1946 1947 VI_LOCK(vp); 1948 unp = VTOUNIONFS(vp); 1949 if (unp == NULL) { 1950 /* vnode is released. */ 1951 VI_UNLOCK(vp); 1952 if (error == 0) 1953 VOP_UNLOCK(lvp); 1954 vdrop(lvp); 1955 if (uhold != 0) 1956 vdrop(uvp); 1957 return (vop_stdlock(ap)); 1958 } 1959 } 1960 1961 if (error == 0 && uvp != NULLVP) { 1962 if (uhold && flags & LK_UPGRADE) { 1963 flags &= ~LK_TYPE_MASK; 1964 flags |= LK_EXCLUSIVE; 1965 } 1966 VI_LOCK_FLAGS(uvp, MTX_DUPOK); 1967 flags |= LK_INTERLOCK; 1968 if (uhold == 0) { 1969 vholdl(uvp); 1970 uhold = 1; 1971 } 1972 1973 VI_UNLOCK(vp); 1974 ap->a_flags &= ~LK_INTERLOCK; 1975 1976 error = VOP_LOCK(uvp, flags); 1977 1978 VI_LOCK(vp); 1979 unp = VTOUNIONFS(vp); 1980 if (unp == NULL) { 1981 /* vnode is released. */ 1982 VI_UNLOCK(vp); 1983 if (error == 0) 1984 VOP_UNLOCK(uvp); 1985 vdrop(uvp); 1986 if (lvp != NULLVP) { 1987 VOP_UNLOCK(lvp); 1988 vdrop(lvp); 1989 } 1990 return (vop_stdlock(ap)); 1991 } 1992 if (error != 0 && lvp != NULLVP) { 1993 /* rollback */ 1994 VI_UNLOCK(vp); 1995 unionfs_revlock(lvp, revlock); 1996 interlock = 0; 1997 } 1998 } 1999 2000 if (interlock) 2001 VI_UNLOCK(vp); 2002 if (lvp != NULLVP) 2003 vdrop(lvp); 2004 if (uhold != 0) 2005 vdrop(uvp); 2006 2007 return (error); 2008 2009 unionfs_lock_null_vnode: 2010 ap->a_flags |= LK_INTERLOCK; 2011 return (vop_stdlock(ap)); 2012 } 2013 2014 static int 2015 unionfs_unlock(struct vop_unlock_args *ap) 2016 { 2017 struct vnode *vp; 2018 struct vnode *lvp; 2019 struct vnode *uvp; 2020 struct unionfs_node *unp; 2021 int error; 2022 int uhold; 2023 2024 KASSERT_UNIONFS_VNODE(ap->a_vp); 2025 2026 error = 0; 2027 uhold = 0; 2028 vp = ap->a_vp; 2029 2030 unp = VTOUNIONFS(vp); 2031 if (unp == NULL) 2032 goto unionfs_unlock_null_vnode; 2033 lvp = unp->un_lowervp; 2034 uvp = unp->un_uppervp; 2035 2036 if (lvp != NULLVP) { 2037 vholdnz(lvp); 2038 error = VOP_UNLOCK(lvp); 2039 } 2040 2041 if (error == 0 && uvp != NULLVP) { 2042 vholdnz(uvp); 2043 uhold = 1; 2044 error = VOP_UNLOCK(uvp); 2045 } 2046 2047 if (lvp != NULLVP) 2048 vdrop(lvp); 2049 if (uhold != 0) 2050 vdrop(uvp); 2051 2052 return error; 2053 2054 unionfs_unlock_null_vnode: 2055 return (vop_stdunlock(ap)); 2056 } 2057 2058 static int 2059 unionfs_pathconf(struct vop_pathconf_args *ap) 2060 { 2061 struct unionfs_node *unp; 2062 struct vnode *vp; 2063 2064 KASSERT_UNIONFS_VNODE(ap->a_vp); 2065 2066 unp = VTOUNIONFS(ap->a_vp); 2067 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2068 2069 return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval)); 2070 } 2071 2072 static int 2073 unionfs_advlock(struct vop_advlock_args *ap) 2074 { 2075 struct unionfs_node *unp; 2076 struct unionfs_node_status *unsp; 2077 struct vnode *vp; 2078 struct vnode *uvp; 2079 struct thread *td; 2080 int error; 2081 2082 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n"); 2083 2084 KASSERT_UNIONFS_VNODE(ap->a_vp); 2085 2086 vp = ap->a_vp; 2087 td = curthread; 2088 2089 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2090 2091 unp = VTOUNIONFS(ap->a_vp); 2092 uvp = unp->un_uppervp; 2093 2094 if (uvp == NULLVP) { 2095 error = unionfs_copyfile(unp, 1, td->td_ucred, td); 2096 if (error != 0) 2097 goto unionfs_advlock_abort; 2098 uvp = unp->un_uppervp; 2099 2100 unionfs_get_node_status(unp, td, &unsp); 2101 if (unsp->uns_lower_opencnt > 0) { 2102 /* try reopen the vnode */ 2103 error = VOP_OPEN(uvp, unsp->uns_lower_openmode, 2104 td->td_ucred, td, NULL); 2105 if (error) 2106 goto unionfs_advlock_abort; 2107 unsp->uns_upper_opencnt++; 2108 VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, 2109 td->td_ucred, td); 2110 unsp->uns_lower_opencnt--; 2111 } else 2112 unionfs_tryrem_node_status(unp, unsp); 2113 } 2114 2115 VOP_UNLOCK(vp); 2116 2117 error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); 2118 2119 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2120 2121 return error; 2122 2123 unionfs_advlock_abort: 2124 VOP_UNLOCK(vp); 2125 2126 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2127 2128 return error; 2129 } 2130 2131 static int 2132 unionfs_strategy(struct vop_strategy_args *ap) 2133 { 2134 struct unionfs_node *unp; 2135 struct vnode *vp; 2136 2137 KASSERT_UNIONFS_VNODE(ap->a_vp); 2138 2139 unp = VTOUNIONFS(ap->a_vp); 2140 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2141 2142 #ifdef DIAGNOSTIC 2143 if (vp == NULLVP) 2144 panic("unionfs_strategy: nullvp"); 2145 2146 if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp) 2147 panic("unionfs_strategy: writing to lowervp"); 2148 #endif 2149 2150 return (VOP_STRATEGY(vp, ap->a_bp)); 2151 } 2152 2153 static int 2154 unionfs_getacl(struct vop_getacl_args *ap) 2155 { 2156 struct unionfs_node *unp; 2157 struct vnode *vp; 2158 int error; 2159 2160 KASSERT_UNIONFS_VNODE(ap->a_vp); 2161 2162 unp = VTOUNIONFS(ap->a_vp); 2163 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2164 2165 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n"); 2166 2167 error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2168 2169 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error); 2170 2171 return (error); 2172 } 2173 2174 static int 2175 unionfs_setacl(struct vop_setacl_args *ap) 2176 { 2177 struct unionfs_node *unp; 2178 struct vnode *uvp; 2179 struct vnode *lvp; 2180 struct thread *td; 2181 int error; 2182 2183 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n"); 2184 2185 KASSERT_UNIONFS_VNODE(ap->a_vp); 2186 2187 error = EROFS; 2188 unp = VTOUNIONFS(ap->a_vp); 2189 uvp = unp->un_uppervp; 2190 lvp = unp->un_lowervp; 2191 td = ap->a_td; 2192 2193 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2194 return (EROFS); 2195 2196 if (uvp == NULLVP && lvp->v_type == VREG) { 2197 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2198 return (error); 2199 uvp = unp->un_uppervp; 2200 } 2201 2202 if (uvp != NULLVP) 2203 error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td); 2204 2205 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error); 2206 2207 return (error); 2208 } 2209 2210 static int 2211 unionfs_aclcheck(struct vop_aclcheck_args *ap) 2212 { 2213 struct unionfs_node *unp; 2214 struct vnode *vp; 2215 int error; 2216 2217 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n"); 2218 2219 KASSERT_UNIONFS_VNODE(ap->a_vp); 2220 2221 unp = VTOUNIONFS(ap->a_vp); 2222 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2223 2224 error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2225 2226 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error); 2227 2228 return (error); 2229 } 2230 2231 static int 2232 unionfs_openextattr(struct vop_openextattr_args *ap) 2233 { 2234 struct unionfs_node *unp; 2235 struct vnode *vp; 2236 struct vnode *tvp; 2237 int error; 2238 2239 KASSERT_UNIONFS_VNODE(ap->a_vp); 2240 2241 vp = ap->a_vp; 2242 unp = VTOUNIONFS(vp); 2243 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2244 2245 if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) || 2246 (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) 2247 return (EBUSY); 2248 2249 error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); 2250 2251 if (error == 0) { 2252 if (vn_lock(vp, LK_UPGRADE) != 0) 2253 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2254 if (tvp == unp->un_uppervp) 2255 unp->un_flag |= UNIONFS_OPENEXTU; 2256 else 2257 unp->un_flag |= UNIONFS_OPENEXTL; 2258 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2259 } 2260 2261 return (error); 2262 } 2263 2264 static int 2265 unionfs_closeextattr(struct vop_closeextattr_args *ap) 2266 { 2267 struct unionfs_node *unp; 2268 struct vnode *vp; 2269 struct vnode *tvp; 2270 int error; 2271 2272 KASSERT_UNIONFS_VNODE(ap->a_vp); 2273 2274 vp = ap->a_vp; 2275 unp = VTOUNIONFS(vp); 2276 tvp = NULLVP; 2277 2278 if (unp->un_flag & UNIONFS_OPENEXTU) 2279 tvp = unp->un_uppervp; 2280 else if (unp->un_flag & UNIONFS_OPENEXTL) 2281 tvp = unp->un_lowervp; 2282 2283 if (tvp == NULLVP) 2284 return (EOPNOTSUPP); 2285 2286 error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); 2287 2288 if (error == 0) { 2289 if (vn_lock(vp, LK_UPGRADE) != 0) 2290 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2291 if (tvp == unp->un_uppervp) 2292 unp->un_flag &= ~UNIONFS_OPENEXTU; 2293 else 2294 unp->un_flag &= ~UNIONFS_OPENEXTL; 2295 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2296 } 2297 2298 return (error); 2299 } 2300 2301 static int 2302 unionfs_getextattr(struct vop_getextattr_args *ap) 2303 { 2304 struct unionfs_node *unp; 2305 struct vnode *vp; 2306 2307 KASSERT_UNIONFS_VNODE(ap->a_vp); 2308 2309 unp = VTOUNIONFS(ap->a_vp); 2310 vp = NULLVP; 2311 2312 if (unp->un_flag & UNIONFS_OPENEXTU) 2313 vp = unp->un_uppervp; 2314 else if (unp->un_flag & UNIONFS_OPENEXTL) 2315 vp = unp->un_lowervp; 2316 2317 if (vp == NULLVP) 2318 return (EOPNOTSUPP); 2319 2320 return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name, 2321 ap->a_uio, ap->a_size, ap->a_cred, ap->a_td)); 2322 } 2323 2324 static int 2325 unionfs_setextattr(struct vop_setextattr_args *ap) 2326 { 2327 struct unionfs_node *unp; 2328 struct vnode *uvp; 2329 struct vnode *lvp; 2330 struct vnode *ovp; 2331 struct ucred *cred; 2332 struct thread *td; 2333 int error; 2334 2335 KASSERT_UNIONFS_VNODE(ap->a_vp); 2336 2337 error = EROFS; 2338 unp = VTOUNIONFS(ap->a_vp); 2339 uvp = unp->un_uppervp; 2340 lvp = unp->un_lowervp; 2341 ovp = NULLVP; 2342 cred = ap->a_cred; 2343 td = ap->a_td; 2344 2345 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n", 2346 unp->un_flag); 2347 2348 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2349 return (EROFS); 2350 2351 if (unp->un_flag & UNIONFS_OPENEXTU) 2352 ovp = unp->un_uppervp; 2353 else if (unp->un_flag & UNIONFS_OPENEXTL) 2354 ovp = unp->un_lowervp; 2355 2356 if (ovp == NULLVP) 2357 return (EOPNOTSUPP); 2358 2359 if (ovp == lvp && lvp->v_type == VREG) { 2360 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2361 if (uvp == NULLVP && 2362 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2363 unionfs_setextattr_reopen: 2364 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2365 VOP_OPENEXTATTR(lvp, cred, td)) { 2366 #ifdef DIAGNOSTIC 2367 panic("unionfs: VOP_OPENEXTATTR failed"); 2368 #endif 2369 unp->un_flag &= ~UNIONFS_OPENEXTL; 2370 } 2371 goto unionfs_setextattr_abort; 2372 } 2373 uvp = unp->un_uppervp; 2374 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2375 goto unionfs_setextattr_reopen; 2376 unp->un_flag &= ~UNIONFS_OPENEXTL; 2377 unp->un_flag |= UNIONFS_OPENEXTU; 2378 ovp = uvp; 2379 } 2380 2381 if (ovp == uvp) 2382 error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2383 ap->a_uio, cred, td); 2384 2385 unionfs_setextattr_abort: 2386 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error); 2387 2388 return (error); 2389 } 2390 2391 static int 2392 unionfs_listextattr(struct vop_listextattr_args *ap) 2393 { 2394 struct unionfs_node *unp; 2395 struct vnode *vp; 2396 2397 KASSERT_UNIONFS_VNODE(ap->a_vp); 2398 2399 unp = VTOUNIONFS(ap->a_vp); 2400 vp = NULLVP; 2401 2402 if (unp->un_flag & UNIONFS_OPENEXTU) 2403 vp = unp->un_uppervp; 2404 else if (unp->un_flag & UNIONFS_OPENEXTL) 2405 vp = unp->un_lowervp; 2406 2407 if (vp == NULLVP) 2408 return (EOPNOTSUPP); 2409 2410 return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio, 2411 ap->a_size, ap->a_cred, ap->a_td)); 2412 } 2413 2414 static int 2415 unionfs_deleteextattr(struct vop_deleteextattr_args *ap) 2416 { 2417 struct unionfs_node *unp; 2418 struct vnode *uvp; 2419 struct vnode *lvp; 2420 struct vnode *ovp; 2421 struct ucred *cred; 2422 struct thread *td; 2423 int error; 2424 2425 KASSERT_UNIONFS_VNODE(ap->a_vp); 2426 2427 error = EROFS; 2428 unp = VTOUNIONFS(ap->a_vp); 2429 uvp = unp->un_uppervp; 2430 lvp = unp->un_lowervp; 2431 ovp = NULLVP; 2432 cred = ap->a_cred; 2433 td = ap->a_td; 2434 2435 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n", 2436 unp->un_flag); 2437 2438 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2439 return (EROFS); 2440 2441 if (unp->un_flag & UNIONFS_OPENEXTU) 2442 ovp = unp->un_uppervp; 2443 else if (unp->un_flag & UNIONFS_OPENEXTL) 2444 ovp = unp->un_lowervp; 2445 2446 if (ovp == NULLVP) 2447 return (EOPNOTSUPP); 2448 2449 if (ovp == lvp && lvp->v_type == VREG) { 2450 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2451 if (uvp == NULLVP && 2452 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2453 unionfs_deleteextattr_reopen: 2454 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2455 VOP_OPENEXTATTR(lvp, cred, td)) { 2456 #ifdef DIAGNOSTIC 2457 panic("unionfs: VOP_OPENEXTATTR failed"); 2458 #endif 2459 unp->un_flag &= ~UNIONFS_OPENEXTL; 2460 } 2461 goto unionfs_deleteextattr_abort; 2462 } 2463 uvp = unp->un_uppervp; 2464 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2465 goto unionfs_deleteextattr_reopen; 2466 unp->un_flag &= ~UNIONFS_OPENEXTL; 2467 unp->un_flag |= UNIONFS_OPENEXTU; 2468 ovp = uvp; 2469 } 2470 2471 if (ovp == uvp) 2472 error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2473 ap->a_cred, ap->a_td); 2474 2475 unionfs_deleteextattr_abort: 2476 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error); 2477 2478 return (error); 2479 } 2480 2481 static int 2482 unionfs_setlabel(struct vop_setlabel_args *ap) 2483 { 2484 struct unionfs_node *unp; 2485 struct vnode *uvp; 2486 struct vnode *lvp; 2487 struct thread *td; 2488 int error; 2489 2490 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n"); 2491 2492 KASSERT_UNIONFS_VNODE(ap->a_vp); 2493 2494 error = EROFS; 2495 unp = VTOUNIONFS(ap->a_vp); 2496 uvp = unp->un_uppervp; 2497 lvp = unp->un_lowervp; 2498 td = ap->a_td; 2499 2500 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2501 return (EROFS); 2502 2503 if (uvp == NULLVP && lvp->v_type == VREG) { 2504 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2505 return (error); 2506 uvp = unp->un_uppervp; 2507 } 2508 2509 if (uvp != NULLVP) 2510 error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td); 2511 2512 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error); 2513 2514 return (error); 2515 } 2516 2517 static int 2518 unionfs_vptofh(struct vop_vptofh_args *ap) 2519 { 2520 return (EOPNOTSUPP); 2521 } 2522 2523 static int 2524 unionfs_add_writecount(struct vop_add_writecount_args *ap) 2525 { 2526 struct vnode *tvp, *vp; 2527 struct unionfs_node *unp; 2528 int error, writerefs; 2529 2530 vp = ap->a_vp; 2531 unp = VTOUNIONFS(vp); 2532 tvp = unp->un_uppervp; 2533 KASSERT(tvp != NULL, 2534 ("%s: adding write ref without upper vnode", __func__)); 2535 error = VOP_ADD_WRITECOUNT(tvp, ap->a_inc); 2536 if (error != 0) 2537 return (error); 2538 /* 2539 * We need to track the write refs we've passed to the underlying 2540 * vnodes so that we can undo them in case we are forcibly unmounted. 2541 */ 2542 writerefs = atomic_fetchadd_int(&vp->v_writecount, ap->a_inc); 2543 /* text refs are bypassed to lowervp */ 2544 VNASSERT(writerefs >= 0, vp, 2545 ("%s: invalid write count %d", __func__, writerefs)); 2546 VNASSERT(writerefs + ap->a_inc >= 0, vp, 2547 ("%s: invalid write count inc %d + %d", __func__, 2548 writerefs, ap->a_inc)); 2549 return (0); 2550 } 2551 2552 static int 2553 unionfs_vput_pair(struct vop_vput_pair_args *ap) 2554 { 2555 struct mount *mp; 2556 struct vnode *dvp, *vp, **vpp, *lvp, *ldvp, *uvp, *udvp, *tempvp; 2557 struct unionfs_node *dunp, *unp; 2558 int error, res; 2559 2560 dvp = ap->a_dvp; 2561 vpp = ap->a_vpp; 2562 vp = NULLVP; 2563 lvp = NULLVP; 2564 uvp = NULLVP; 2565 unp = NULL; 2566 2567 dunp = VTOUNIONFS(dvp); 2568 udvp = dunp->un_uppervp; 2569 ldvp = dunp->un_lowervp; 2570 2571 /* 2572 * Underlying vnodes should be locked because the encompassing unionfs 2573 * node is locked, but will not be referenced, as the reference will 2574 * only be on the unionfs node. Reference them now so that the vput()s 2575 * performed by VOP_VPUT_PAIR() will have a reference to drop. 2576 */ 2577 if (udvp != NULLVP) 2578 vref(udvp); 2579 if (ldvp != NULLVP) 2580 vref(ldvp); 2581 2582 if (vpp != NULL) 2583 vp = *vpp; 2584 2585 if (vp != NULLVP) { 2586 unp = VTOUNIONFS(vp); 2587 uvp = unp->un_uppervp; 2588 lvp = unp->un_lowervp; 2589 if (uvp != NULLVP) 2590 vref(uvp); 2591 if (lvp != NULLVP) 2592 vref(lvp); 2593 2594 /* 2595 * If we're being asked to return a locked child vnode, then 2596 * we may need to create a replacement vnode in case the 2597 * original is reclaimed while the lock is dropped. In that 2598 * case we'll need to ensure the mount and the underlying 2599 * vnodes aren't also recycled during that window. 2600 */ 2601 if (!ap->a_unlock_vp) { 2602 vhold(vp); 2603 if (uvp != NULLVP) 2604 vhold(uvp); 2605 if (lvp != NULLVP) 2606 vhold(lvp); 2607 mp = vp->v_mount; 2608 vfs_ref(mp); 2609 } 2610 } 2611 2612 /* 2613 * TODO: Because unionfs_lock() locks both the lower and upper vnodes 2614 * (if available), we must also call VOP_VPUT_PAIR() on both the lower 2615 * and upper parent/child pairs. If unionfs_lock() is reworked to lock 2616 * only a single vnode, this code will need to change to also only 2617 * operate on one vnode pair. 2618 */ 2619 ASSERT_VOP_LOCKED(ldvp, __func__); 2620 ASSERT_VOP_LOCKED(udvp, __func__); 2621 ASSERT_VOP_LOCKED(lvp, __func__); 2622 ASSERT_VOP_LOCKED(uvp, __func__); 2623 2624 KASSERT(lvp == NULLVP || ldvp != NULLVP, 2625 ("%s: NULL ldvp with non-NULL lvp", __func__)); 2626 if (ldvp != NULLVP) 2627 res = VOP_VPUT_PAIR(ldvp, lvp != NULLVP ? &lvp : NULL, true); 2628 KASSERT(uvp == NULLVP || udvp != NULLVP, 2629 ("%s: NULL udvp with non-NULL uvp", __func__)); 2630 if (udvp != NULLVP) 2631 res = VOP_VPUT_PAIR(udvp, uvp != NULLVP ? &uvp : NULL, true); 2632 2633 ASSERT_VOP_UNLOCKED(ldvp, __func__); 2634 ASSERT_VOP_UNLOCKED(udvp, __func__); 2635 ASSERT_VOP_UNLOCKED(lvp, __func__); 2636 ASSERT_VOP_UNLOCKED(uvp, __func__); 2637 2638 /* 2639 * VOP_VPUT_PAIR() dropped the references we added to the underlying 2640 * vnodes, now drop the caller's reference to the unionfs vnodes. 2641 */ 2642 if (vp != NULLVP && ap->a_unlock_vp) 2643 vrele(vp); 2644 vrele(dvp); 2645 2646 if (vp == NULLVP || ap->a_unlock_vp) 2647 return (res); 2648 2649 /* 2650 * We're being asked to return a locked vnode. At this point, the 2651 * underlying vnodes have been unlocked, so vp may have been reclaimed. 2652 */ 2653 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2654 if (vp->v_data == NULL && vfs_busy(mp, MBF_NOWAIT) == 0) { 2655 vput(vp); 2656 error = unionfs_nodeget(mp, uvp, lvp, dvp, &tempvp, NULL); 2657 if (error == 0) { 2658 vn_lock(tempvp, LK_EXCLUSIVE | LK_RETRY); 2659 *vpp = tempvp; 2660 } else 2661 vget(vp, LK_EXCLUSIVE | LK_RETRY); 2662 vfs_unbusy(mp); 2663 } 2664 if (lvp != NULLVP) 2665 vdrop(lvp); 2666 if (uvp != NULLVP) 2667 vdrop(uvp); 2668 vdrop(vp); 2669 vfs_rel(mp); 2670 2671 return (res); 2672 } 2673 2674 static int 2675 unionfs_set_text(struct vop_set_text_args *ap) 2676 { 2677 struct vnode *tvp; 2678 struct unionfs_node *unp; 2679 int error; 2680 2681 /* 2682 * We assume text refs are managed against lvp/uvp through the 2683 * executable mapping backed by its VM object. We therefore don't 2684 * need to track leased text refs in the case of a forcible unmount. 2685 */ 2686 unp = VTOUNIONFS(ap->a_vp); 2687 ASSERT_VOP_LOCKED(ap->a_vp, __func__); 2688 tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; 2689 error = VOP_SET_TEXT(tvp); 2690 return (error); 2691 } 2692 2693 static int 2694 unionfs_unset_text(struct vop_unset_text_args *ap) 2695 { 2696 struct vnode *tvp; 2697 struct unionfs_node *unp; 2698 2699 ASSERT_VOP_LOCKED(ap->a_vp, __func__); 2700 unp = VTOUNIONFS(ap->a_vp); 2701 tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; 2702 VOP_UNSET_TEXT_CHECKED(tvp); 2703 return (0); 2704 } 2705 2706 struct vop_vector unionfs_vnodeops = { 2707 .vop_default = &default_vnodeops, 2708 2709 .vop_access = unionfs_access, 2710 .vop_aclcheck = unionfs_aclcheck, 2711 .vop_advlock = unionfs_advlock, 2712 .vop_bmap = VOP_EOPNOTSUPP, 2713 .vop_cachedlookup = unionfs_lookup, 2714 .vop_close = unionfs_close, 2715 .vop_closeextattr = unionfs_closeextattr, 2716 .vop_create = unionfs_create, 2717 .vop_deleteextattr = unionfs_deleteextattr, 2718 .vop_fsync = unionfs_fsync, 2719 .vop_getacl = unionfs_getacl, 2720 .vop_getattr = unionfs_getattr, 2721 .vop_getextattr = unionfs_getextattr, 2722 .vop_getwritemount = unionfs_getwritemount, 2723 .vop_inactive = unionfs_inactive, 2724 .vop_need_inactive = vop_stdneed_inactive, 2725 .vop_islocked = unionfs_islocked, 2726 .vop_ioctl = unionfs_ioctl, 2727 .vop_link = unionfs_link, 2728 .vop_listextattr = unionfs_listextattr, 2729 .vop_lock1 = unionfs_lock, 2730 .vop_lookup = vfs_cache_lookup, 2731 .vop_mkdir = unionfs_mkdir, 2732 .vop_mknod = unionfs_mknod, 2733 .vop_open = unionfs_open, 2734 .vop_openextattr = unionfs_openextattr, 2735 .vop_pathconf = unionfs_pathconf, 2736 .vop_poll = unionfs_poll, 2737 .vop_print = unionfs_print, 2738 .vop_read = unionfs_read, 2739 .vop_readdir = unionfs_readdir, 2740 .vop_readlink = unionfs_readlink, 2741 .vop_reclaim = unionfs_reclaim, 2742 .vop_remove = unionfs_remove, 2743 .vop_rename = unionfs_rename, 2744 .vop_rmdir = unionfs_rmdir, 2745 .vop_setacl = unionfs_setacl, 2746 .vop_setattr = unionfs_setattr, 2747 .vop_setextattr = unionfs_setextattr, 2748 .vop_setlabel = unionfs_setlabel, 2749 .vop_strategy = unionfs_strategy, 2750 .vop_symlink = unionfs_symlink, 2751 .vop_unlock = unionfs_unlock, 2752 .vop_whiteout = unionfs_whiteout, 2753 .vop_write = unionfs_write, 2754 .vop_vptofh = unionfs_vptofh, 2755 .vop_add_writecount = unionfs_add_writecount, 2756 .vop_vput_pair = unionfs_vput_pair, 2757 .vop_set_text = unionfs_set_text, 2758 .vop_unset_text = unionfs_unset_text, 2759 }; 2760 VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops); 2761