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); 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); 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); 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); 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 uid_t uid; /* upper side vnode's uid */ 635 gid_t gid; /* upper side vnode's gid */ 636 u_short vmode; /* upper side vnode's mode */ 637 u_short mask; 638 639 mask = 0; 640 uid = va->va_uid; 641 gid = va->va_gid; 642 vmode = va->va_mode; 643 644 /* check owner */ 645 if (cred->cr_uid == uid) { 646 if (accmode & VEXEC) 647 mask |= S_IXUSR; 648 if (accmode & VREAD) 649 mask |= S_IRUSR; 650 if (accmode & VWRITE) 651 mask |= S_IWUSR; 652 return ((vmode & mask) == mask ? 0 : EACCES); 653 } 654 655 /* check group */ 656 if (groupmember(gid, cred)) { 657 if (accmode & VEXEC) 658 mask |= S_IXGRP; 659 if (accmode & VREAD) 660 mask |= S_IRGRP; 661 if (accmode & VWRITE) 662 mask |= S_IWGRP; 663 return ((vmode & mask) == mask ? 0 : EACCES); 664 } 665 666 /* check other */ 667 if (accmode & VEXEC) 668 mask |= S_IXOTH; 669 if (accmode & VREAD) 670 mask |= S_IROTH; 671 if (accmode & VWRITE) 672 mask |= S_IWOTH; 673 674 return ((vmode & mask) == mask ? 0 : EACCES); 675 } 676 677 static int 678 unionfs_access(struct vop_access_args *ap) 679 { 680 struct unionfs_mount *ump; 681 struct unionfs_node *unp; 682 struct vnode *uvp; 683 struct vnode *lvp; 684 struct thread *td; 685 struct vattr va; 686 accmode_t accmode; 687 int error; 688 689 UNIONFS_INTERNAL_DEBUG("unionfs_access: enter\n"); 690 691 KASSERT_UNIONFS_VNODE(ap->a_vp); 692 693 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 694 unp = VTOUNIONFS(ap->a_vp); 695 uvp = unp->un_uppervp; 696 lvp = unp->un_lowervp; 697 td = ap->a_td; 698 accmode = ap->a_accmode; 699 error = EACCES; 700 701 if ((accmode & VWRITE) && 702 (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) { 703 switch (ap->a_vp->v_type) { 704 case VREG: 705 case VDIR: 706 case VLNK: 707 return (EROFS); 708 default: 709 break; 710 } 711 } 712 713 if (uvp != NULLVP) { 714 error = VOP_ACCESS(uvp, accmode, ap->a_cred, td); 715 716 UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error); 717 718 return (error); 719 } 720 721 if (lvp != NULLVP) { 722 if (accmode & VWRITE) { 723 if (ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY) { 724 switch (ap->a_vp->v_type) { 725 case VREG: 726 case VDIR: 727 case VLNK: 728 return (EROFS); 729 default: 730 break; 731 } 732 } else if (ap->a_vp->v_type == VREG || 733 ap->a_vp->v_type == VDIR) { 734 /* check shadow file/dir */ 735 if (ump->um_copymode != UNIONFS_TRANSPARENT) { 736 error = unionfs_create_uppervattr(ump, 737 lvp, &va, ap->a_cred, td); 738 if (error != 0) 739 return (error); 740 741 error = unionfs_check_corrected_access( 742 accmode, &va, ap->a_cred); 743 if (error != 0) 744 return (error); 745 } 746 } 747 accmode &= ~(VWRITE | VAPPEND); 748 accmode |= VREAD; /* will copy to upper */ 749 } 750 error = VOP_ACCESS(lvp, accmode, ap->a_cred, td); 751 } 752 753 UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error); 754 755 return (error); 756 } 757 758 static int 759 unionfs_getattr(struct vop_getattr_args *ap) 760 { 761 struct unionfs_node *unp; 762 struct unionfs_mount *ump; 763 struct vnode *uvp; 764 struct vnode *lvp; 765 struct thread *td; 766 struct vattr va; 767 int error; 768 769 UNIONFS_INTERNAL_DEBUG("unionfs_getattr: enter\n"); 770 771 KASSERT_UNIONFS_VNODE(ap->a_vp); 772 773 unp = VTOUNIONFS(ap->a_vp); 774 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 775 uvp = unp->un_uppervp; 776 lvp = unp->un_lowervp; 777 td = curthread; 778 779 if (uvp != NULLVP) { 780 if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0) 781 ap->a_vap->va_fsid = 782 ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 783 784 UNIONFS_INTERNAL_DEBUG( 785 "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n", 786 ap->a_vap->va_mode, ap->a_vap->va_uid, 787 ap->a_vap->va_gid, error); 788 789 return (error); 790 } 791 792 error = VOP_GETATTR(lvp, ap->a_vap, ap->a_cred); 793 794 if (error == 0 && !(ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY)) { 795 /* correct the attr toward shadow file/dir. */ 796 if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) { 797 unionfs_create_uppervattr_core(ump, ap->a_vap, &va, td); 798 ap->a_vap->va_mode = va.va_mode; 799 ap->a_vap->va_uid = va.va_uid; 800 ap->a_vap->va_gid = va.va_gid; 801 } 802 } 803 804 if (error == 0) 805 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 806 807 UNIONFS_INTERNAL_DEBUG( 808 "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n", 809 ap->a_vap->va_mode, ap->a_vap->va_uid, ap->a_vap->va_gid, error); 810 811 return (error); 812 } 813 814 static int 815 unionfs_setattr(struct vop_setattr_args *ap) 816 { 817 struct unionfs_node *unp; 818 struct vnode *uvp; 819 struct vnode *lvp; 820 struct thread *td; 821 struct vattr *vap; 822 int error; 823 824 UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n"); 825 826 KASSERT_UNIONFS_VNODE(ap->a_vp); 827 828 error = EROFS; 829 unp = VTOUNIONFS(ap->a_vp); 830 uvp = unp->un_uppervp; 831 lvp = unp->un_lowervp; 832 td = curthread; 833 vap = ap->a_vap; 834 835 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && 836 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 837 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 838 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) 839 return (EROFS); 840 841 if (uvp == NULLVP && lvp->v_type == VREG) { 842 error = unionfs_copyfile(unp, (vap->va_size != 0), 843 ap->a_cred, td); 844 if (error != 0) 845 return (error); 846 uvp = unp->un_uppervp; 847 } 848 849 if (uvp != NULLVP) 850 error = VOP_SETATTR(uvp, vap, ap->a_cred); 851 852 UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error); 853 854 return (error); 855 } 856 857 static int 858 unionfs_read(struct vop_read_args *ap) 859 { 860 struct unionfs_node *unp; 861 struct vnode *tvp; 862 int error; 863 864 /* UNIONFS_INTERNAL_DEBUG("unionfs_read: enter\n"); */ 865 866 KASSERT_UNIONFS_VNODE(ap->a_vp); 867 868 unp = VTOUNIONFS(ap->a_vp); 869 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 870 871 error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); 872 873 /* UNIONFS_INTERNAL_DEBUG("unionfs_read: leave (%d)\n", error); */ 874 875 return (error); 876 } 877 878 static int 879 unionfs_write(struct vop_write_args *ap) 880 { 881 struct unionfs_node *unp; 882 struct vnode *tvp; 883 int error; 884 885 /* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */ 886 887 KASSERT_UNIONFS_VNODE(ap->a_vp); 888 889 unp = VTOUNIONFS(ap->a_vp); 890 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 891 892 error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred); 893 894 /* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */ 895 896 return (error); 897 } 898 899 static int 900 unionfs_ioctl(struct vop_ioctl_args *ap) 901 { 902 struct unionfs_node *unp; 903 struct unionfs_node_status *unsp; 904 struct vnode *ovp; 905 int error; 906 907 UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: enter\n"); 908 909 KASSERT_UNIONFS_VNODE(ap->a_vp); 910 911 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 912 unp = VTOUNIONFS(ap->a_vp); 913 unionfs_get_node_status(unp, ap->a_td, &unsp); 914 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 915 unionfs_tryrem_node_status(unp, unsp); 916 VOP_UNLOCK(ap->a_vp); 917 918 if (ovp == NULLVP) 919 return (EBADF); 920 921 error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag, 922 ap->a_cred, ap->a_td); 923 924 UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error); 925 926 return (error); 927 } 928 929 static int 930 unionfs_poll(struct vop_poll_args *ap) 931 { 932 struct unionfs_node *unp; 933 struct unionfs_node_status *unsp; 934 struct vnode *ovp; 935 936 KASSERT_UNIONFS_VNODE(ap->a_vp); 937 938 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 939 unp = VTOUNIONFS(ap->a_vp); 940 unionfs_get_node_status(unp, ap->a_td, &unsp); 941 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 942 unionfs_tryrem_node_status(unp, unsp); 943 VOP_UNLOCK(ap->a_vp); 944 945 if (ovp == NULLVP) 946 return (EBADF); 947 948 return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td)); 949 } 950 951 static int 952 unionfs_fsync(struct vop_fsync_args *ap) 953 { 954 struct unionfs_node *unp; 955 struct unionfs_node_status *unsp; 956 struct vnode *ovp; 957 958 KASSERT_UNIONFS_VNODE(ap->a_vp); 959 960 unp = VTOUNIONFS(ap->a_vp); 961 unionfs_get_node_status(unp, ap->a_td, &unsp); 962 ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); 963 unionfs_tryrem_node_status(unp, unsp); 964 965 if (ovp == NULLVP) 966 return (EBADF); 967 968 return (VOP_FSYNC(ovp, ap->a_waitfor, ap->a_td)); 969 } 970 971 static int 972 unionfs_remove(struct vop_remove_args *ap) 973 { 974 char *path; 975 struct unionfs_node *dunp; 976 struct unionfs_node *unp; 977 struct unionfs_mount *ump; 978 struct vnode *udvp; 979 struct vnode *uvp; 980 struct vnode *lvp; 981 struct vnode *vp; 982 struct componentname *cnp; 983 struct componentname cn; 984 struct thread *td; 985 int error; 986 int pathlen; 987 988 UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n"); 989 990 KASSERT_UNIONFS_VNODE(ap->a_dvp); 991 992 error = 0; 993 dunp = VTOUNIONFS(ap->a_dvp); 994 udvp = dunp->un_uppervp; 995 cnp = ap->a_cnp; 996 td = curthread; 997 998 if (ap->a_vp->v_op != &unionfs_vnodeops) { 999 if (ap->a_vp->v_type != VSOCK) 1000 return (EINVAL); 1001 ump = NULL; 1002 vp = uvp = lvp = NULLVP; 1003 /* search vnode */ 1004 VOP_UNLOCK(ap->a_vp); 1005 error = unionfs_relookup(udvp, &vp, cnp, &cn, td, 1006 cnp->cn_nameptr, cnp->cn_namelen, DELETE); 1007 if (error != 0 && error != ENOENT) { 1008 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1009 return (error); 1010 } 1011 1012 if (error == 0 && vp == ap->a_vp) { 1013 /* target vnode in upper */ 1014 uvp = vp; 1015 vrele(vp); 1016 } else { 1017 /* target vnode in lower */ 1018 if (vp != NULLVP) { 1019 if (udvp == vp) 1020 vrele(vp); 1021 else 1022 vput(vp); 1023 } 1024 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1025 lvp = ap->a_vp; 1026 } 1027 path = cnp->cn_nameptr; 1028 pathlen = cnp->cn_namelen; 1029 } else { 1030 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 1031 unp = VTOUNIONFS(ap->a_vp); 1032 uvp = unp->un_uppervp; 1033 lvp = unp->un_lowervp; 1034 path = unp->un_path; 1035 pathlen = unp->un_pathlen; 1036 } 1037 1038 if (udvp == NULLVP) 1039 return (EROFS); 1040 1041 if (uvp != NULLVP) { 1042 /* 1043 * XXX: if the vnode type is VSOCK, it will create whiteout 1044 * after remove. 1045 */ 1046 if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS || 1047 lvp != NULLVP) 1048 cnp->cn_flags |= DOWHITEOUT; 1049 error = VOP_REMOVE(udvp, uvp, cnp); 1050 } else if (lvp != NULLVP) 1051 error = unionfs_mkwhiteout(udvp, cnp, td, path, pathlen); 1052 1053 UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error); 1054 1055 return (error); 1056 } 1057 1058 static int 1059 unionfs_link(struct vop_link_args *ap) 1060 { 1061 struct unionfs_node *dunp; 1062 struct unionfs_node *unp; 1063 struct vnode *udvp; 1064 struct vnode *uvp; 1065 struct componentname *cnp; 1066 struct thread *td; 1067 int error; 1068 int needrelookup; 1069 1070 UNIONFS_INTERNAL_DEBUG("unionfs_link: enter\n"); 1071 1072 KASSERT_UNIONFS_VNODE(ap->a_tdvp); 1073 KASSERT_UNIONFS_VNODE(ap->a_vp); 1074 1075 error = 0; 1076 needrelookup = 0; 1077 dunp = VTOUNIONFS(ap->a_tdvp); 1078 unp = NULL; 1079 udvp = dunp->un_uppervp; 1080 uvp = NULLVP; 1081 cnp = ap->a_cnp; 1082 td = curthread; 1083 1084 if (udvp == NULLVP) 1085 return (EROFS); 1086 1087 if (ap->a_vp->v_op != &unionfs_vnodeops) 1088 uvp = ap->a_vp; 1089 else { 1090 unp = VTOUNIONFS(ap->a_vp); 1091 1092 if (unp->un_uppervp == NULLVP) { 1093 if (ap->a_vp->v_type != VREG) 1094 return (EOPNOTSUPP); 1095 1096 error = unionfs_copyfile(unp, 1, cnp->cn_cred, td); 1097 if (error != 0) 1098 return (error); 1099 needrelookup = 1; 1100 } 1101 uvp = unp->un_uppervp; 1102 } 1103 1104 if (needrelookup != 0) 1105 error = unionfs_relookup_for_create(ap->a_tdvp, cnp, td); 1106 1107 if (error == 0) 1108 error = VOP_LINK(udvp, uvp, cnp); 1109 1110 UNIONFS_INTERNAL_DEBUG("unionfs_link: leave (%d)\n", error); 1111 1112 return (error); 1113 } 1114 1115 static int 1116 unionfs_rename(struct vop_rename_args *ap) 1117 { 1118 struct vnode *fdvp; 1119 struct vnode *fvp; 1120 struct componentname *fcnp; 1121 struct vnode *tdvp; 1122 struct vnode *tvp; 1123 struct componentname *tcnp; 1124 struct vnode *ltdvp; 1125 struct vnode *ltvp; 1126 struct thread *td; 1127 1128 /* rename target vnodes */ 1129 struct vnode *rfdvp; 1130 struct vnode *rfvp; 1131 struct vnode *rtdvp; 1132 struct vnode *rtvp; 1133 1134 struct unionfs_mount *ump; 1135 struct unionfs_node *unp; 1136 int error; 1137 int needrelookup; 1138 1139 UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n"); 1140 1141 error = 0; 1142 fdvp = ap->a_fdvp; 1143 fvp = ap->a_fvp; 1144 fcnp = ap->a_fcnp; 1145 tdvp = ap->a_tdvp; 1146 tvp = ap->a_tvp; 1147 tcnp = ap->a_tcnp; 1148 ltdvp = NULLVP; 1149 ltvp = NULLVP; 1150 td = curthread; 1151 rfdvp = fdvp; 1152 rfvp = fvp; 1153 rtdvp = tdvp; 1154 rtvp = tvp; 1155 needrelookup = 0; 1156 1157 #ifdef DIAGNOSTIC 1158 if (!(fcnp->cn_flags & HASBUF) || !(tcnp->cn_flags & HASBUF)) 1159 panic("unionfs_rename: no name"); 1160 #endif 1161 1162 /* check for cross device rename */ 1163 if (fvp->v_mount != tdvp->v_mount || 1164 (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) { 1165 if (fvp->v_op != &unionfs_vnodeops) 1166 error = ENODEV; 1167 else 1168 error = EXDEV; 1169 goto unionfs_rename_abort; 1170 } 1171 1172 /* Renaming a file to itself has no effect. */ 1173 if (fvp == tvp) 1174 goto unionfs_rename_abort; 1175 1176 /* 1177 * from/to vnode is unionfs node. 1178 */ 1179 1180 KASSERT_UNIONFS_VNODE(fdvp); 1181 KASSERT_UNIONFS_VNODE(fvp); 1182 KASSERT_UNIONFS_VNODE(tdvp); 1183 if (tvp != NULLVP) 1184 KASSERT_UNIONFS_VNODE(tvp); 1185 1186 unp = VTOUNIONFS(fdvp); 1187 #ifdef UNIONFS_IDBG_RENAME 1188 UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n", 1189 fdvp, unp->un_uppervp, unp->un_lowervp); 1190 #endif 1191 if (unp->un_uppervp == NULLVP) { 1192 error = ENODEV; 1193 goto unionfs_rename_abort; 1194 } 1195 rfdvp = unp->un_uppervp; 1196 vref(rfdvp); 1197 1198 unp = VTOUNIONFS(fvp); 1199 #ifdef UNIONFS_IDBG_RENAME 1200 UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n", 1201 fvp, unp->un_uppervp, unp->un_lowervp); 1202 #endif 1203 ump = MOUNTTOUNIONFSMOUNT(fvp->v_mount); 1204 if (unp->un_uppervp == NULLVP) { 1205 switch (fvp->v_type) { 1206 case VREG: 1207 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1208 goto unionfs_rename_abort; 1209 error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td); 1210 VOP_UNLOCK(fvp); 1211 if (error != 0) 1212 goto unionfs_rename_abort; 1213 break; 1214 case VDIR: 1215 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) 1216 goto unionfs_rename_abort; 1217 error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td); 1218 VOP_UNLOCK(fvp); 1219 if (error != 0) 1220 goto unionfs_rename_abort; 1221 break; 1222 default: 1223 error = ENODEV; 1224 goto unionfs_rename_abort; 1225 } 1226 1227 needrelookup = 1; 1228 } 1229 1230 if (unp->un_lowervp != NULLVP) 1231 fcnp->cn_flags |= DOWHITEOUT; 1232 rfvp = unp->un_uppervp; 1233 vref(rfvp); 1234 1235 unp = VTOUNIONFS(tdvp); 1236 #ifdef UNIONFS_IDBG_RENAME 1237 UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n", 1238 tdvp, unp->un_uppervp, unp->un_lowervp); 1239 #endif 1240 if (unp->un_uppervp == NULLVP) { 1241 error = ENODEV; 1242 goto unionfs_rename_abort; 1243 } 1244 rtdvp = unp->un_uppervp; 1245 ltdvp = unp->un_lowervp; 1246 vref(rtdvp); 1247 1248 if (tdvp == tvp) { 1249 rtvp = rtdvp; 1250 vref(rtvp); 1251 } else if (tvp != NULLVP) { 1252 unp = VTOUNIONFS(tvp); 1253 #ifdef UNIONFS_IDBG_RENAME 1254 UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n", 1255 tvp, unp->un_uppervp, unp->un_lowervp); 1256 #endif 1257 if (unp->un_uppervp == NULLVP) 1258 rtvp = NULLVP; 1259 else { 1260 if (tvp->v_type == VDIR) { 1261 error = EINVAL; 1262 goto unionfs_rename_abort; 1263 } 1264 rtvp = unp->un_uppervp; 1265 ltvp = unp->un_lowervp; 1266 vref(rtvp); 1267 } 1268 } 1269 1270 if (rfvp == rtvp) 1271 goto unionfs_rename_abort; 1272 1273 if (needrelookup != 0) { 1274 if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0) 1275 goto unionfs_rename_abort; 1276 error = unionfs_relookup_for_delete(fdvp, fcnp, td); 1277 VOP_UNLOCK(fdvp); 1278 if (error != 0) 1279 goto unionfs_rename_abort; 1280 1281 /* Lock of tvp is canceled in order to avoid recursive lock. */ 1282 if (tvp != NULLVP && tvp != tdvp) 1283 VOP_UNLOCK(tvp); 1284 error = unionfs_relookup_for_rename(tdvp, tcnp, td); 1285 if (tvp != NULLVP && tvp != tdvp) 1286 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); 1287 if (error != 0) 1288 goto unionfs_rename_abort; 1289 } 1290 1291 error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp); 1292 1293 if (error == 0) { 1294 if (rtvp != NULLVP && rtvp->v_type == VDIR) 1295 cache_purge(tdvp); 1296 if (fvp->v_type == VDIR && fdvp != tdvp) 1297 cache_purge(fdvp); 1298 } 1299 1300 if (ltdvp != NULLVP) 1301 VOP_UNLOCK(ltdvp); 1302 if (tdvp != rtdvp) 1303 vrele(tdvp); 1304 if (ltvp != NULLVP) 1305 VOP_UNLOCK(ltvp); 1306 if (tvp != rtvp && tvp != NULLVP) { 1307 if (rtvp == NULLVP) 1308 vput(tvp); 1309 else 1310 vrele(tvp); 1311 } 1312 if (fdvp != rfdvp) 1313 vrele(fdvp); 1314 if (fvp != rfvp) 1315 vrele(fvp); 1316 1317 UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); 1318 1319 return (error); 1320 1321 unionfs_rename_abort: 1322 vput(tdvp); 1323 if (tdvp != rtdvp) 1324 vrele(rtdvp); 1325 if (tvp != NULLVP) { 1326 if (tdvp != tvp) 1327 vput(tvp); 1328 else 1329 vrele(tvp); 1330 } 1331 if (tvp != rtvp && rtvp != NULLVP) 1332 vrele(rtvp); 1333 if (fdvp != rfdvp) 1334 vrele(rfdvp); 1335 if (fvp != rfvp) 1336 vrele(rfvp); 1337 vrele(fdvp); 1338 vrele(fvp); 1339 1340 UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error); 1341 1342 return (error); 1343 } 1344 1345 static int 1346 unionfs_mkdir(struct vop_mkdir_args *ap) 1347 { 1348 struct unionfs_node *dunp; 1349 struct componentname *cnp; 1350 struct vnode *udvp; 1351 struct vnode *uvp; 1352 struct vattr va; 1353 int error; 1354 int lkflags; 1355 1356 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n"); 1357 1358 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1359 1360 error = EROFS; 1361 dunp = VTOUNIONFS(ap->a_dvp); 1362 cnp = ap->a_cnp; 1363 lkflags = cnp->cn_lkflags; 1364 udvp = dunp->un_uppervp; 1365 1366 if (udvp != NULLVP) { 1367 /* check opaque */ 1368 if (!(cnp->cn_flags & ISWHITEOUT)) { 1369 error = VOP_GETATTR(udvp, &va, cnp->cn_cred); 1370 if (error != 0) 1371 return (error); 1372 if ((va.va_flags & OPAQUE) != 0) 1373 cnp->cn_flags |= ISWHITEOUT; 1374 } 1375 1376 if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { 1377 VOP_UNLOCK(uvp); 1378 cnp->cn_lkflags = LK_EXCLUSIVE; 1379 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1380 ap->a_dvp, ap->a_vpp, cnp); 1381 cnp->cn_lkflags = lkflags; 1382 vrele(uvp); 1383 } 1384 } 1385 1386 UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error); 1387 1388 return (error); 1389 } 1390 1391 static int 1392 unionfs_rmdir(struct vop_rmdir_args *ap) 1393 { 1394 struct unionfs_node *dunp; 1395 struct unionfs_node *unp; 1396 struct unionfs_mount *ump; 1397 struct componentname *cnp; 1398 struct thread *td; 1399 struct vnode *udvp; 1400 struct vnode *uvp; 1401 struct vnode *lvp; 1402 int error; 1403 1404 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n"); 1405 1406 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1407 KASSERT_UNIONFS_VNODE(ap->a_vp); 1408 1409 error = 0; 1410 dunp = VTOUNIONFS(ap->a_dvp); 1411 unp = VTOUNIONFS(ap->a_vp); 1412 cnp = ap->a_cnp; 1413 td = curthread; 1414 udvp = dunp->un_uppervp; 1415 uvp = unp->un_uppervp; 1416 lvp = unp->un_lowervp; 1417 1418 if (udvp == NULLVP) 1419 return (EROFS); 1420 1421 if (udvp == uvp) 1422 return (EOPNOTSUPP); 1423 1424 if (uvp != NULLVP) { 1425 if (lvp != NULLVP) { 1426 error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td); 1427 if (error != 0) 1428 return (error); 1429 } 1430 ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); 1431 if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP) 1432 cnp->cn_flags |= DOWHITEOUT; 1433 /* 1434 * The relookup path will need to relock the parent dvp and 1435 * possibly the vp as well. Locking is expected to be done 1436 * in parent->child order; drop the lock on vp to avoid LOR 1437 * and potential recursion on vp's lock. 1438 * vp is expected to remain referenced during VOP_RMDIR(), 1439 * so vref/vrele should not be necessary here. 1440 */ 1441 VOP_UNLOCK(ap->a_vp); 1442 VNPASS(vrefcnt(ap->a_vp) > 0, ap->a_vp); 1443 error = unionfs_relookup_for_delete(ap->a_dvp, cnp, td); 1444 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 1445 if (error == 0 && VN_IS_DOOMED(uvp)) 1446 error = ENOENT; 1447 if (error == 0) 1448 error = VOP_RMDIR(udvp, uvp, cnp); 1449 } else if (lvp != NULLVP) 1450 error = unionfs_mkwhiteout(udvp, cnp, td, 1451 unp->un_path, unp->un_pathlen); 1452 1453 if (error == 0) { 1454 cache_purge(ap->a_dvp); 1455 cache_purge(ap->a_vp); 1456 } 1457 1458 UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error); 1459 1460 return (error); 1461 } 1462 1463 static int 1464 unionfs_symlink(struct vop_symlink_args *ap) 1465 { 1466 struct unionfs_node *dunp; 1467 struct componentname *cnp; 1468 struct vnode *udvp; 1469 struct vnode *uvp; 1470 int error; 1471 int lkflags; 1472 1473 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n"); 1474 1475 KASSERT_UNIONFS_VNODE(ap->a_dvp); 1476 1477 error = EROFS; 1478 dunp = VTOUNIONFS(ap->a_dvp); 1479 cnp = ap->a_cnp; 1480 lkflags = cnp->cn_lkflags; 1481 udvp = dunp->un_uppervp; 1482 1483 if (udvp != NULLVP) { 1484 error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); 1485 if (error == 0) { 1486 VOP_UNLOCK(uvp); 1487 cnp->cn_lkflags = LK_EXCLUSIVE; 1488 error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, 1489 ap->a_dvp, ap->a_vpp, cnp); 1490 cnp->cn_lkflags = lkflags; 1491 vrele(uvp); 1492 } 1493 } 1494 1495 UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error); 1496 1497 return (error); 1498 } 1499 1500 static int 1501 unionfs_readdir(struct vop_readdir_args *ap) 1502 { 1503 struct unionfs_node *unp; 1504 struct unionfs_node_status *unsp; 1505 struct uio *uio; 1506 struct vnode *vp; 1507 struct vnode *uvp; 1508 struct vnode *lvp; 1509 struct thread *td; 1510 struct vattr va; 1511 1512 uint64_t *cookies_bk; 1513 int error; 1514 int eofflag; 1515 int locked; 1516 int ncookies_bk; 1517 int uio_offset_bk; 1518 1519 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n"); 1520 1521 KASSERT_UNIONFS_VNODE(ap->a_vp); 1522 1523 error = 0; 1524 eofflag = 0; 1525 locked = 0; 1526 uio_offset_bk = 0; 1527 uio = ap->a_uio; 1528 uvp = NULLVP; 1529 lvp = NULLVP; 1530 td = uio->uio_td; 1531 ncookies_bk = 0; 1532 cookies_bk = NULL; 1533 1534 vp = ap->a_vp; 1535 if (vp->v_type != VDIR) 1536 return (ENOTDIR); 1537 1538 /* check the open count. unionfs needs to open before readdir. */ 1539 if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { 1540 if (vn_lock(vp, LK_UPGRADE) != 0) 1541 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1542 locked = 1; 1543 } 1544 unp = VTOUNIONFS(vp); 1545 if (unp == NULL) 1546 error = EBADF; 1547 else { 1548 uvp = unp->un_uppervp; 1549 lvp = unp->un_lowervp; 1550 unionfs_get_node_status(unp, td, &unsp); 1551 if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || 1552 (lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { 1553 unionfs_tryrem_node_status(unp, unsp); 1554 error = EBADF; 1555 } 1556 } 1557 if (locked) 1558 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 1559 if (error != 0) 1560 goto unionfs_readdir_exit; 1561 1562 /* check opaque */ 1563 if (uvp != NULLVP && lvp != NULLVP) { 1564 if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0) 1565 goto unionfs_readdir_exit; 1566 if (va.va_flags & OPAQUE) 1567 lvp = NULLVP; 1568 } 1569 1570 /* upper only */ 1571 if (uvp != NULLVP && lvp == NULLVP) { 1572 error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag, 1573 ap->a_ncookies, ap->a_cookies); 1574 unsp->uns_readdir_status = 0; 1575 1576 goto unionfs_readdir_exit; 1577 } 1578 1579 /* lower only */ 1580 if (uvp == NULLVP && lvp != NULLVP) { 1581 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1582 ap->a_ncookies, ap->a_cookies); 1583 unsp->uns_readdir_status = 2; 1584 1585 goto unionfs_readdir_exit; 1586 } 1587 1588 /* 1589 * readdir upper and lower 1590 */ 1591 KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp")); 1592 KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp")); 1593 if (uio->uio_offset == 0) 1594 unsp->uns_readdir_status = 0; 1595 1596 if (unsp->uns_readdir_status == 0) { 1597 /* read upper */ 1598 error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag, 1599 ap->a_ncookies, ap->a_cookies); 1600 1601 if (error != 0 || eofflag == 0) 1602 goto unionfs_readdir_exit; 1603 unsp->uns_readdir_status = 1; 1604 1605 /* 1606 * UFS(and other FS) needs size of uio_resid larger than 1607 * DIRBLKSIZ. 1608 * size of DIRBLKSIZ equals DEV_BSIZE. 1609 * (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h) 1610 */ 1611 if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1))) 1612 goto unionfs_readdir_exit; 1613 1614 /* 1615 * Backup cookies. 1616 * It prepares to readdir in lower. 1617 */ 1618 if (ap->a_ncookies != NULL) { 1619 ncookies_bk = *(ap->a_ncookies); 1620 *(ap->a_ncookies) = 0; 1621 } 1622 if (ap->a_cookies != NULL) { 1623 cookies_bk = *(ap->a_cookies); 1624 *(ap->a_cookies) = NULL; 1625 } 1626 } 1627 1628 /* initialize for readdir in lower */ 1629 if (unsp->uns_readdir_status == 1) { 1630 unsp->uns_readdir_status = 2; 1631 /* 1632 * Backup uio_offset. See the comment after the 1633 * VOP_READDIR call on the lower layer. 1634 */ 1635 uio_offset_bk = uio->uio_offset; 1636 uio->uio_offset = 0; 1637 } 1638 1639 if (lvp == NULLVP) { 1640 error = EBADF; 1641 goto unionfs_readdir_exit; 1642 } 1643 /* read lower */ 1644 error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag, 1645 ap->a_ncookies, ap->a_cookies); 1646 1647 /* 1648 * We can't return an uio_offset of 0: this would trigger an 1649 * infinite loop, because the next call to unionfs_readdir would 1650 * always restart with the upper layer (uio_offset == 0) and 1651 * always return some data. 1652 * 1653 * This happens when the lower layer root directory is removed. 1654 * (A root directory deleting of unionfs should not be permitted. 1655 * But current VFS can not do it.) 1656 */ 1657 if (uio->uio_offset == 0) 1658 uio->uio_offset = uio_offset_bk; 1659 1660 if (cookies_bk != NULL) { 1661 /* merge cookies */ 1662 int size; 1663 uint64_t *newcookies, *pos; 1664 1665 size = *(ap->a_ncookies) + ncookies_bk; 1666 newcookies = (uint64_t *) malloc(size * sizeof(*newcookies), 1667 M_TEMP, M_WAITOK); 1668 pos = newcookies; 1669 1670 memcpy(pos, cookies_bk, ncookies_bk * sizeof(*newcookies)); 1671 pos += ncookies_bk; 1672 memcpy(pos, *(ap->a_cookies), 1673 *(ap->a_ncookies) * sizeof(*newcookies)); 1674 free(cookies_bk, M_TEMP); 1675 free(*(ap->a_cookies), M_TEMP); 1676 *(ap->a_ncookies) = size; 1677 *(ap->a_cookies) = newcookies; 1678 } 1679 1680 unionfs_readdir_exit: 1681 if (error != 0 && ap->a_eofflag != NULL) 1682 *(ap->a_eofflag) = 1; 1683 1684 UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error); 1685 1686 return (error); 1687 } 1688 1689 static int 1690 unionfs_readlink(struct vop_readlink_args *ap) 1691 { 1692 struct unionfs_node *unp; 1693 struct vnode *vp; 1694 int error; 1695 1696 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n"); 1697 1698 KASSERT_UNIONFS_VNODE(ap->a_vp); 1699 1700 unp = VTOUNIONFS(ap->a_vp); 1701 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 1702 1703 error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); 1704 1705 UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error); 1706 1707 return (error); 1708 } 1709 1710 static int 1711 unionfs_getwritemount(struct vop_getwritemount_args *ap) 1712 { 1713 struct vnode *uvp; 1714 struct vnode *vp; 1715 int error; 1716 1717 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n"); 1718 1719 error = 0; 1720 vp = ap->a_vp; 1721 1722 if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY)) 1723 return (EACCES); 1724 1725 KASSERT_UNIONFS_VNODE(vp); 1726 1727 uvp = UNIONFSVPTOUPPERVP(vp); 1728 if (uvp == NULLVP && VREG == vp->v_type) 1729 uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp); 1730 1731 if (uvp != NULLVP) 1732 error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp); 1733 else { 1734 VI_LOCK(vp); 1735 if (vp->v_holdcnt == 0) 1736 error = EOPNOTSUPP; 1737 else 1738 error = EACCES; 1739 VI_UNLOCK(vp); 1740 } 1741 1742 UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error); 1743 1744 return (error); 1745 } 1746 1747 static int 1748 unionfs_inactive(struct vop_inactive_args *ap) 1749 { 1750 ap->a_vp->v_object = NULL; 1751 vrecycle(ap->a_vp); 1752 return (0); 1753 } 1754 1755 static int 1756 unionfs_reclaim(struct vop_reclaim_args *ap) 1757 { 1758 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */ 1759 1760 unionfs_noderem(ap->a_vp); 1761 1762 /* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */ 1763 1764 return (0); 1765 } 1766 1767 static int 1768 unionfs_print(struct vop_print_args *ap) 1769 { 1770 struct unionfs_node *unp; 1771 /* struct unionfs_node_status *unsp; */ 1772 1773 unp = VTOUNIONFS(ap->a_vp); 1774 /* unionfs_get_node_status(unp, curthread, &unsp); */ 1775 1776 printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n", 1777 ap->a_vp, unp->un_uppervp, unp->un_lowervp); 1778 /* 1779 printf("unionfs opencnt: uppervp=%d, lowervp=%d\n", 1780 unsp->uns_upper_opencnt, unsp->uns_lower_opencnt); 1781 */ 1782 1783 if (unp->un_uppervp != NULLVP) 1784 vn_printf(unp->un_uppervp, "unionfs: upper "); 1785 if (unp->un_lowervp != NULLVP) 1786 vn_printf(unp->un_lowervp, "unionfs: lower "); 1787 1788 return (0); 1789 } 1790 1791 static int 1792 unionfs_islocked(struct vop_islocked_args *ap) 1793 { 1794 struct unionfs_node *unp; 1795 1796 KASSERT_UNIONFS_VNODE(ap->a_vp); 1797 1798 unp = VTOUNIONFS(ap->a_vp); 1799 if (unp == NULL) 1800 return (vop_stdislocked(ap)); 1801 1802 if (unp->un_uppervp != NULLVP) 1803 return (VOP_ISLOCKED(unp->un_uppervp)); 1804 if (unp->un_lowervp != NULLVP) 1805 return (VOP_ISLOCKED(unp->un_lowervp)); 1806 return (vop_stdislocked(ap)); 1807 } 1808 1809 static int 1810 unionfs_get_llt_revlock(struct vnode *vp, int flags) 1811 { 1812 int revlock; 1813 1814 revlock = 0; 1815 1816 switch (flags & LK_TYPE_MASK) { 1817 case LK_SHARED: 1818 if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) 1819 revlock = LK_UPGRADE; 1820 else 1821 revlock = LK_RELEASE; 1822 break; 1823 case LK_EXCLUSIVE: 1824 case LK_UPGRADE: 1825 revlock = LK_RELEASE; 1826 break; 1827 case LK_DOWNGRADE: 1828 revlock = LK_UPGRADE; 1829 break; 1830 default: 1831 break; 1832 } 1833 1834 return (revlock); 1835 } 1836 1837 /* 1838 * The state of an acquired lock is adjusted similarly to 1839 * the time of error generating. 1840 * flags: LK_RELEASE or LK_UPGRADE 1841 */ 1842 static void 1843 unionfs_revlock(struct vnode *vp, int flags) 1844 { 1845 if (flags & LK_RELEASE) 1846 VOP_UNLOCK_FLAGS(vp, flags); 1847 else { 1848 /* UPGRADE */ 1849 if (vn_lock(vp, flags) != 0) 1850 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1851 } 1852 } 1853 1854 static int 1855 unionfs_lock(struct vop_lock1_args *ap) 1856 { 1857 struct mount *mp; 1858 struct unionfs_mount *ump; 1859 struct unionfs_node *unp; 1860 struct vnode *vp; 1861 struct vnode *uvp; 1862 struct vnode *lvp; 1863 int error; 1864 int flags; 1865 int revlock; 1866 int interlock; 1867 int uhold; 1868 1869 KASSERT_UNIONFS_VNODE(ap->a_vp); 1870 1871 /* 1872 * TODO: rework the unionfs locking scheme. 1873 * It's not guaranteed to be safe to blindly lock two vnodes on 1874 * different mounts as is done here. Further, the entanglement 1875 * of locking both vnodes with the various options that can be 1876 * passed to VOP_LOCK() makes this code hard to reason about. 1877 * Instead, consider locking only the upper vnode, or the lower 1878 * vnode is the upper is not present, and taking separate measures 1879 * to lock both vnodes in the few cases when that is needed. 1880 */ 1881 error = 0; 1882 interlock = 1; 1883 uhold = 0; 1884 flags = ap->a_flags; 1885 vp = ap->a_vp; 1886 1887 if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK)) 1888 return (VOP_UNLOCK_FLAGS(vp, flags | LK_RELEASE)); 1889 1890 if ((flags & LK_INTERLOCK) == 0) 1891 VI_LOCK(vp); 1892 1893 mp = vp->v_mount; 1894 if (mp == NULL) 1895 goto unionfs_lock_null_vnode; 1896 1897 ump = MOUNTTOUNIONFSMOUNT(mp); 1898 unp = VTOUNIONFS(vp); 1899 if (ump == NULL || unp == NULL) 1900 goto unionfs_lock_null_vnode; 1901 lvp = unp->un_lowervp; 1902 uvp = unp->un_uppervp; 1903 1904 if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0) 1905 panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); 1906 1907 if ((vp->v_iflag & VI_OWEINACT) != 0) 1908 flags |= LK_NOWAIT; 1909 1910 /* 1911 * Sometimes, lower or upper is already exclusive locked. 1912 * (ex. vfs_domount: mounted vnode is already locked.) 1913 */ 1914 if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE && 1915 vp == ump->um_rootvp) 1916 flags |= LK_CANRECURSE; 1917 1918 if (lvp != NULLVP) { 1919 if (uvp != NULLVP && flags & LK_UPGRADE) { 1920 /* 1921 * Share Lock is once released and a deadlock is 1922 * avoided. 1923 */ 1924 vholdnz(uvp); 1925 uhold = 1; 1926 VOP_UNLOCK(uvp); 1927 unp = VTOUNIONFS(vp); 1928 if (unp == NULL) { 1929 /* vnode is released. */ 1930 VI_UNLOCK(vp); 1931 VOP_UNLOCK(lvp); 1932 vdrop(uvp); 1933 return (EBUSY); 1934 } 1935 } 1936 VI_LOCK_FLAGS(lvp, MTX_DUPOK); 1937 flags |= LK_INTERLOCK; 1938 vholdl(lvp); 1939 1940 VI_UNLOCK(vp); 1941 ap->a_flags &= ~LK_INTERLOCK; 1942 1943 error = VOP_LOCK(lvp, flags); 1944 1945 VI_LOCK(vp); 1946 unp = VTOUNIONFS(vp); 1947 if (unp == NULL) { 1948 /* vnode is released. */ 1949 VI_UNLOCK(vp); 1950 if (error == 0) 1951 VOP_UNLOCK(lvp); 1952 vdrop(lvp); 1953 if (uhold != 0) 1954 vdrop(uvp); 1955 return (vop_stdlock(ap)); 1956 } 1957 } 1958 1959 if (error == 0 && uvp != NULLVP) { 1960 if (uhold && flags & LK_UPGRADE) { 1961 flags &= ~LK_TYPE_MASK; 1962 flags |= LK_EXCLUSIVE; 1963 } 1964 VI_LOCK_FLAGS(uvp, MTX_DUPOK); 1965 flags |= LK_INTERLOCK; 1966 if (uhold == 0) { 1967 vholdl(uvp); 1968 uhold = 1; 1969 } 1970 1971 VI_UNLOCK(vp); 1972 ap->a_flags &= ~LK_INTERLOCK; 1973 1974 error = VOP_LOCK(uvp, flags); 1975 1976 VI_LOCK(vp); 1977 unp = VTOUNIONFS(vp); 1978 if (unp == NULL) { 1979 /* vnode is released. */ 1980 VI_UNLOCK(vp); 1981 if (error == 0) 1982 VOP_UNLOCK(uvp); 1983 vdrop(uvp); 1984 if (lvp != NULLVP) { 1985 VOP_UNLOCK(lvp); 1986 vdrop(lvp); 1987 } 1988 return (vop_stdlock(ap)); 1989 } 1990 if (error != 0 && lvp != NULLVP) { 1991 /* rollback */ 1992 VI_UNLOCK(vp); 1993 unionfs_revlock(lvp, revlock); 1994 interlock = 0; 1995 } 1996 } 1997 1998 if (interlock) 1999 VI_UNLOCK(vp); 2000 if (lvp != NULLVP) 2001 vdrop(lvp); 2002 if (uhold != 0) 2003 vdrop(uvp); 2004 2005 return (error); 2006 2007 unionfs_lock_null_vnode: 2008 ap->a_flags |= LK_INTERLOCK; 2009 return (vop_stdlock(ap)); 2010 } 2011 2012 static int 2013 unionfs_unlock(struct vop_unlock_args *ap) 2014 { 2015 struct vnode *vp; 2016 struct vnode *lvp; 2017 struct vnode *uvp; 2018 struct unionfs_node *unp; 2019 int error; 2020 int uhold; 2021 2022 KASSERT_UNIONFS_VNODE(ap->a_vp); 2023 2024 error = 0; 2025 uhold = 0; 2026 vp = ap->a_vp; 2027 2028 unp = VTOUNIONFS(vp); 2029 if (unp == NULL) 2030 goto unionfs_unlock_null_vnode; 2031 lvp = unp->un_lowervp; 2032 uvp = unp->un_uppervp; 2033 2034 if (lvp != NULLVP) { 2035 vholdnz(lvp); 2036 error = VOP_UNLOCK(lvp); 2037 } 2038 2039 if (error == 0 && uvp != NULLVP) { 2040 vholdnz(uvp); 2041 uhold = 1; 2042 error = VOP_UNLOCK(uvp); 2043 } 2044 2045 if (lvp != NULLVP) 2046 vdrop(lvp); 2047 if (uhold != 0) 2048 vdrop(uvp); 2049 2050 return error; 2051 2052 unionfs_unlock_null_vnode: 2053 return (vop_stdunlock(ap)); 2054 } 2055 2056 static int 2057 unionfs_pathconf(struct vop_pathconf_args *ap) 2058 { 2059 struct unionfs_node *unp; 2060 struct vnode *vp; 2061 2062 KASSERT_UNIONFS_VNODE(ap->a_vp); 2063 2064 unp = VTOUNIONFS(ap->a_vp); 2065 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2066 2067 return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval)); 2068 } 2069 2070 static int 2071 unionfs_advlock(struct vop_advlock_args *ap) 2072 { 2073 struct unionfs_node *unp; 2074 struct unionfs_node_status *unsp; 2075 struct vnode *vp; 2076 struct vnode *uvp; 2077 struct thread *td; 2078 int error; 2079 2080 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n"); 2081 2082 KASSERT_UNIONFS_VNODE(ap->a_vp); 2083 2084 vp = ap->a_vp; 2085 td = curthread; 2086 2087 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2088 2089 unp = VTOUNIONFS(ap->a_vp); 2090 uvp = unp->un_uppervp; 2091 2092 if (uvp == NULLVP) { 2093 error = unionfs_copyfile(unp, 1, td->td_ucred, td); 2094 if (error != 0) 2095 goto unionfs_advlock_abort; 2096 uvp = unp->un_uppervp; 2097 2098 unionfs_get_node_status(unp, td, &unsp); 2099 if (unsp->uns_lower_opencnt > 0) { 2100 /* try reopen the vnode */ 2101 error = VOP_OPEN(uvp, unsp->uns_lower_openmode, 2102 td->td_ucred, td, NULL); 2103 if (error) 2104 goto unionfs_advlock_abort; 2105 unsp->uns_upper_opencnt++; 2106 VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, 2107 td->td_ucred, td); 2108 unsp->uns_lower_opencnt--; 2109 } else 2110 unionfs_tryrem_node_status(unp, unsp); 2111 } 2112 2113 VOP_UNLOCK(vp); 2114 2115 error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); 2116 2117 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2118 2119 return error; 2120 2121 unionfs_advlock_abort: 2122 VOP_UNLOCK(vp); 2123 2124 UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); 2125 2126 return error; 2127 } 2128 2129 static int 2130 unionfs_strategy(struct vop_strategy_args *ap) 2131 { 2132 struct unionfs_node *unp; 2133 struct vnode *vp; 2134 2135 KASSERT_UNIONFS_VNODE(ap->a_vp); 2136 2137 unp = VTOUNIONFS(ap->a_vp); 2138 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2139 2140 #ifdef DIAGNOSTIC 2141 if (vp == NULLVP) 2142 panic("unionfs_strategy: nullvp"); 2143 2144 if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp) 2145 panic("unionfs_strategy: writing to lowervp"); 2146 #endif 2147 2148 return (VOP_STRATEGY(vp, ap->a_bp)); 2149 } 2150 2151 static int 2152 unionfs_getacl(struct vop_getacl_args *ap) 2153 { 2154 struct unionfs_node *unp; 2155 struct vnode *vp; 2156 int error; 2157 2158 KASSERT_UNIONFS_VNODE(ap->a_vp); 2159 2160 unp = VTOUNIONFS(ap->a_vp); 2161 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2162 2163 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n"); 2164 2165 error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2166 2167 UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error); 2168 2169 return (error); 2170 } 2171 2172 static int 2173 unionfs_setacl(struct vop_setacl_args *ap) 2174 { 2175 struct unionfs_node *unp; 2176 struct vnode *uvp; 2177 struct vnode *lvp; 2178 struct thread *td; 2179 int error; 2180 2181 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n"); 2182 2183 KASSERT_UNIONFS_VNODE(ap->a_vp); 2184 2185 error = EROFS; 2186 unp = VTOUNIONFS(ap->a_vp); 2187 uvp = unp->un_uppervp; 2188 lvp = unp->un_lowervp; 2189 td = ap->a_td; 2190 2191 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2192 return (EROFS); 2193 2194 if (uvp == NULLVP && lvp->v_type == VREG) { 2195 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2196 return (error); 2197 uvp = unp->un_uppervp; 2198 } 2199 2200 if (uvp != NULLVP) 2201 error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td); 2202 2203 UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error); 2204 2205 return (error); 2206 } 2207 2208 static int 2209 unionfs_aclcheck(struct vop_aclcheck_args *ap) 2210 { 2211 struct unionfs_node *unp; 2212 struct vnode *vp; 2213 int error; 2214 2215 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n"); 2216 2217 KASSERT_UNIONFS_VNODE(ap->a_vp); 2218 2219 unp = VTOUNIONFS(ap->a_vp); 2220 vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2221 2222 error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td); 2223 2224 UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error); 2225 2226 return (error); 2227 } 2228 2229 static int 2230 unionfs_openextattr(struct vop_openextattr_args *ap) 2231 { 2232 struct unionfs_node *unp; 2233 struct vnode *vp; 2234 struct vnode *tvp; 2235 int error; 2236 2237 KASSERT_UNIONFS_VNODE(ap->a_vp); 2238 2239 vp = ap->a_vp; 2240 unp = VTOUNIONFS(vp); 2241 tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); 2242 2243 if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) || 2244 (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) 2245 return (EBUSY); 2246 2247 error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); 2248 2249 if (error == 0) { 2250 if (vn_lock(vp, LK_UPGRADE) != 0) 2251 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2252 if (tvp == unp->un_uppervp) 2253 unp->un_flag |= UNIONFS_OPENEXTU; 2254 else 2255 unp->un_flag |= UNIONFS_OPENEXTL; 2256 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2257 } 2258 2259 return (error); 2260 } 2261 2262 static int 2263 unionfs_closeextattr(struct vop_closeextattr_args *ap) 2264 { 2265 struct unionfs_node *unp; 2266 struct vnode *vp; 2267 struct vnode *tvp; 2268 int error; 2269 2270 KASSERT_UNIONFS_VNODE(ap->a_vp); 2271 2272 vp = ap->a_vp; 2273 unp = VTOUNIONFS(vp); 2274 tvp = NULLVP; 2275 2276 if (unp->un_flag & UNIONFS_OPENEXTU) 2277 tvp = unp->un_uppervp; 2278 else if (unp->un_flag & UNIONFS_OPENEXTL) 2279 tvp = unp->un_lowervp; 2280 2281 if (tvp == NULLVP) 2282 return (EOPNOTSUPP); 2283 2284 error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); 2285 2286 if (error == 0) { 2287 if (vn_lock(vp, LK_UPGRADE) != 0) 2288 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2289 if (tvp == unp->un_uppervp) 2290 unp->un_flag &= ~UNIONFS_OPENEXTU; 2291 else 2292 unp->un_flag &= ~UNIONFS_OPENEXTL; 2293 vn_lock(vp, LK_DOWNGRADE | LK_RETRY); 2294 } 2295 2296 return (error); 2297 } 2298 2299 static int 2300 unionfs_getextattr(struct vop_getextattr_args *ap) 2301 { 2302 struct unionfs_node *unp; 2303 struct vnode *vp; 2304 2305 KASSERT_UNIONFS_VNODE(ap->a_vp); 2306 2307 unp = VTOUNIONFS(ap->a_vp); 2308 vp = NULLVP; 2309 2310 if (unp->un_flag & UNIONFS_OPENEXTU) 2311 vp = unp->un_uppervp; 2312 else if (unp->un_flag & UNIONFS_OPENEXTL) 2313 vp = unp->un_lowervp; 2314 2315 if (vp == NULLVP) 2316 return (EOPNOTSUPP); 2317 2318 return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name, 2319 ap->a_uio, ap->a_size, ap->a_cred, ap->a_td)); 2320 } 2321 2322 static int 2323 unionfs_setextattr(struct vop_setextattr_args *ap) 2324 { 2325 struct unionfs_node *unp; 2326 struct vnode *uvp; 2327 struct vnode *lvp; 2328 struct vnode *ovp; 2329 struct ucred *cred; 2330 struct thread *td; 2331 int error; 2332 2333 KASSERT_UNIONFS_VNODE(ap->a_vp); 2334 2335 error = EROFS; 2336 unp = VTOUNIONFS(ap->a_vp); 2337 uvp = unp->un_uppervp; 2338 lvp = unp->un_lowervp; 2339 ovp = NULLVP; 2340 cred = ap->a_cred; 2341 td = ap->a_td; 2342 2343 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n", 2344 unp->un_flag); 2345 2346 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2347 return (EROFS); 2348 2349 if (unp->un_flag & UNIONFS_OPENEXTU) 2350 ovp = unp->un_uppervp; 2351 else if (unp->un_flag & UNIONFS_OPENEXTL) 2352 ovp = unp->un_lowervp; 2353 2354 if (ovp == NULLVP) 2355 return (EOPNOTSUPP); 2356 2357 if (ovp == lvp && lvp->v_type == VREG) { 2358 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2359 if (uvp == NULLVP && 2360 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2361 unionfs_setextattr_reopen: 2362 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2363 VOP_OPENEXTATTR(lvp, cred, td)) { 2364 #ifdef DIAGNOSTIC 2365 panic("unionfs: VOP_OPENEXTATTR failed"); 2366 #endif 2367 unp->un_flag &= ~UNIONFS_OPENEXTL; 2368 } 2369 goto unionfs_setextattr_abort; 2370 } 2371 uvp = unp->un_uppervp; 2372 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2373 goto unionfs_setextattr_reopen; 2374 unp->un_flag &= ~UNIONFS_OPENEXTL; 2375 unp->un_flag |= UNIONFS_OPENEXTU; 2376 ovp = uvp; 2377 } 2378 2379 if (ovp == uvp) 2380 error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2381 ap->a_uio, cred, td); 2382 2383 unionfs_setextattr_abort: 2384 UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error); 2385 2386 return (error); 2387 } 2388 2389 static int 2390 unionfs_listextattr(struct vop_listextattr_args *ap) 2391 { 2392 struct unionfs_node *unp; 2393 struct vnode *vp; 2394 2395 KASSERT_UNIONFS_VNODE(ap->a_vp); 2396 2397 unp = VTOUNIONFS(ap->a_vp); 2398 vp = NULLVP; 2399 2400 if (unp->un_flag & UNIONFS_OPENEXTU) 2401 vp = unp->un_uppervp; 2402 else if (unp->un_flag & UNIONFS_OPENEXTL) 2403 vp = unp->un_lowervp; 2404 2405 if (vp == NULLVP) 2406 return (EOPNOTSUPP); 2407 2408 return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio, 2409 ap->a_size, ap->a_cred, ap->a_td)); 2410 } 2411 2412 static int 2413 unionfs_deleteextattr(struct vop_deleteextattr_args *ap) 2414 { 2415 struct unionfs_node *unp; 2416 struct vnode *uvp; 2417 struct vnode *lvp; 2418 struct vnode *ovp; 2419 struct ucred *cred; 2420 struct thread *td; 2421 int error; 2422 2423 KASSERT_UNIONFS_VNODE(ap->a_vp); 2424 2425 error = EROFS; 2426 unp = VTOUNIONFS(ap->a_vp); 2427 uvp = unp->un_uppervp; 2428 lvp = unp->un_lowervp; 2429 ovp = NULLVP; 2430 cred = ap->a_cred; 2431 td = ap->a_td; 2432 2433 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n", 2434 unp->un_flag); 2435 2436 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2437 return (EROFS); 2438 2439 if (unp->un_flag & UNIONFS_OPENEXTU) 2440 ovp = unp->un_uppervp; 2441 else if (unp->un_flag & UNIONFS_OPENEXTL) 2442 ovp = unp->un_lowervp; 2443 2444 if (ovp == NULLVP) 2445 return (EOPNOTSUPP); 2446 2447 if (ovp == lvp && lvp->v_type == VREG) { 2448 VOP_CLOSEEXTATTR(lvp, 0, cred, td); 2449 if (uvp == NULLVP && 2450 (error = unionfs_copyfile(unp, 1, cred, td)) != 0) { 2451 unionfs_deleteextattr_reopen: 2452 if ((unp->un_flag & UNIONFS_OPENEXTL) && 2453 VOP_OPENEXTATTR(lvp, cred, td)) { 2454 #ifdef DIAGNOSTIC 2455 panic("unionfs: VOP_OPENEXTATTR failed"); 2456 #endif 2457 unp->un_flag &= ~UNIONFS_OPENEXTL; 2458 } 2459 goto unionfs_deleteextattr_abort; 2460 } 2461 uvp = unp->un_uppervp; 2462 if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0) 2463 goto unionfs_deleteextattr_reopen; 2464 unp->un_flag &= ~UNIONFS_OPENEXTL; 2465 unp->un_flag |= UNIONFS_OPENEXTU; 2466 ovp = uvp; 2467 } 2468 2469 if (ovp == uvp) 2470 error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name, 2471 ap->a_cred, ap->a_td); 2472 2473 unionfs_deleteextattr_abort: 2474 UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error); 2475 2476 return (error); 2477 } 2478 2479 static int 2480 unionfs_setlabel(struct vop_setlabel_args *ap) 2481 { 2482 struct unionfs_node *unp; 2483 struct vnode *uvp; 2484 struct vnode *lvp; 2485 struct thread *td; 2486 int error; 2487 2488 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n"); 2489 2490 KASSERT_UNIONFS_VNODE(ap->a_vp); 2491 2492 error = EROFS; 2493 unp = VTOUNIONFS(ap->a_vp); 2494 uvp = unp->un_uppervp; 2495 lvp = unp->un_lowervp; 2496 td = ap->a_td; 2497 2498 if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 2499 return (EROFS); 2500 2501 if (uvp == NULLVP && lvp->v_type == VREG) { 2502 if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0) 2503 return (error); 2504 uvp = unp->un_uppervp; 2505 } 2506 2507 if (uvp != NULLVP) 2508 error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td); 2509 2510 UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error); 2511 2512 return (error); 2513 } 2514 2515 static int 2516 unionfs_vptofh(struct vop_vptofh_args *ap) 2517 { 2518 return (EOPNOTSUPP); 2519 } 2520 2521 static int 2522 unionfs_add_writecount(struct vop_add_writecount_args *ap) 2523 { 2524 struct vnode *tvp, *vp; 2525 struct unionfs_node *unp; 2526 int error; 2527 2528 vp = ap->a_vp; 2529 unp = VTOUNIONFS(vp); 2530 tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp; 2531 VI_LOCK(vp); 2532 /* text refs are bypassed to lowervp */ 2533 VNASSERT(vp->v_writecount >= 0, vp, ("wrong null writecount")); 2534 VNASSERT(vp->v_writecount + ap->a_inc >= 0, vp, 2535 ("wrong writecount inc %d", ap->a_inc)); 2536 if (tvp != NULL) 2537 error = VOP_ADD_WRITECOUNT(tvp, ap->a_inc); 2538 else if (vp->v_writecount < 0) 2539 error = ETXTBSY; 2540 else 2541 error = 0; 2542 if (error == 0) 2543 vp->v_writecount += ap->a_inc; 2544 VI_UNLOCK(vp); 2545 return (error); 2546 } 2547 2548 static int 2549 unionfs_vput_pair(struct vop_vput_pair_args *ap) 2550 { 2551 struct mount *mp; 2552 struct vnode *dvp, *vp, **vpp, *lvp, *ldvp, *uvp, *udvp, *tempvp; 2553 struct unionfs_node *dunp, *unp; 2554 int error, res; 2555 2556 dvp = ap->a_dvp; 2557 vpp = ap->a_vpp; 2558 vp = NULLVP; 2559 lvp = NULLVP; 2560 uvp = NULLVP; 2561 unp = NULL; 2562 2563 dunp = VTOUNIONFS(dvp); 2564 udvp = dunp->un_uppervp; 2565 ldvp = dunp->un_lowervp; 2566 2567 /* 2568 * Underlying vnodes should be locked because the encompassing unionfs 2569 * node is locked, but will not be referenced, as the reference will 2570 * only be on the unionfs node. Reference them now so that the vput()s 2571 * performed by VOP_VPUT_PAIR() will have a reference to drop. 2572 */ 2573 if (udvp != NULLVP) 2574 vref(udvp); 2575 if (ldvp != NULLVP) 2576 vref(ldvp); 2577 2578 if (vpp != NULL) 2579 vp = *vpp; 2580 2581 if (vp != NULLVP) { 2582 unp = VTOUNIONFS(vp); 2583 uvp = unp->un_uppervp; 2584 lvp = unp->un_lowervp; 2585 if (uvp != NULLVP) 2586 vref(uvp); 2587 if (lvp != NULLVP) 2588 vref(lvp); 2589 2590 /* 2591 * If we're being asked to return a locked child vnode, then 2592 * we may need to create a replacement vnode in case the 2593 * original is reclaimed while the lock is dropped. In that 2594 * case we'll need to ensure the mount and the underlying 2595 * vnodes aren't also recycled during that window. 2596 */ 2597 if (!ap->a_unlock_vp) { 2598 vhold(vp); 2599 if (uvp != NULLVP) 2600 vhold(uvp); 2601 if (lvp != NULLVP) 2602 vhold(lvp); 2603 mp = vp->v_mount; 2604 vfs_ref(mp); 2605 } 2606 } 2607 2608 /* 2609 * TODO: Because unionfs_lock() locks both the lower and upper vnodes 2610 * (if available), we must also call VOP_VPUT_PAIR() on both the lower 2611 * and upper parent/child pairs. If unionfs_lock() is reworked to lock 2612 * only a single vnode, this code will need to change to also only 2613 * operate on one vnode pair. 2614 */ 2615 ASSERT_VOP_LOCKED(ldvp, __func__); 2616 ASSERT_VOP_LOCKED(udvp, __func__); 2617 ASSERT_VOP_LOCKED(lvp, __func__); 2618 ASSERT_VOP_LOCKED(uvp, __func__); 2619 2620 KASSERT(lvp == NULLVP || ldvp != NULLVP, 2621 ("%s: NULL ldvp with non-NULL lvp", __func__)); 2622 if (ldvp != NULLVP) 2623 res = VOP_VPUT_PAIR(ldvp, lvp != NULLVP ? &lvp : NULL, true); 2624 KASSERT(uvp == NULLVP || udvp != NULLVP, 2625 ("%s: NULL udvp with non-NULL uvp", __func__)); 2626 if (udvp != NULLVP) 2627 res = VOP_VPUT_PAIR(udvp, uvp != NULLVP ? &uvp : NULL, true); 2628 2629 ASSERT_VOP_UNLOCKED(ldvp, __func__); 2630 ASSERT_VOP_UNLOCKED(udvp, __func__); 2631 ASSERT_VOP_UNLOCKED(lvp, __func__); 2632 ASSERT_VOP_UNLOCKED(uvp, __func__); 2633 2634 /* 2635 * VOP_VPUT_PAIR() dropped the references we added to the underlying 2636 * vnodes, now drop the caller's reference to the unionfs vnodes. 2637 */ 2638 if (vp != NULLVP && ap->a_unlock_vp) 2639 vrele(vp); 2640 vrele(dvp); 2641 2642 if (vp == NULLVP || ap->a_unlock_vp) 2643 return (res); 2644 2645 /* 2646 * We're being asked to return a locked vnode. At this point, the 2647 * underlying vnodes have been unlocked, so vp may have been reclaimed. 2648 */ 2649 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2650 if (vp->v_data == NULL && vfs_busy(mp, MBF_NOWAIT) == 0) { 2651 vput(vp); 2652 error = unionfs_nodeget(mp, uvp, lvp, dvp, &tempvp, NULL); 2653 if (error == 0) { 2654 vn_lock(tempvp, LK_EXCLUSIVE | LK_RETRY); 2655 *vpp = tempvp; 2656 } else 2657 vget(vp, LK_EXCLUSIVE | LK_RETRY); 2658 vfs_unbusy(mp); 2659 } 2660 if (lvp != NULLVP) 2661 vdrop(lvp); 2662 if (uvp != NULLVP) 2663 vdrop(uvp); 2664 vdrop(vp); 2665 vfs_rel(mp); 2666 2667 return (res); 2668 } 2669 2670 struct vop_vector unionfs_vnodeops = { 2671 .vop_default = &default_vnodeops, 2672 2673 .vop_access = unionfs_access, 2674 .vop_aclcheck = unionfs_aclcheck, 2675 .vop_advlock = unionfs_advlock, 2676 .vop_bmap = VOP_EOPNOTSUPP, 2677 .vop_cachedlookup = unionfs_lookup, 2678 .vop_close = unionfs_close, 2679 .vop_closeextattr = unionfs_closeextattr, 2680 .vop_create = unionfs_create, 2681 .vop_deleteextattr = unionfs_deleteextattr, 2682 .vop_fsync = unionfs_fsync, 2683 .vop_getacl = unionfs_getacl, 2684 .vop_getattr = unionfs_getattr, 2685 .vop_getextattr = unionfs_getextattr, 2686 .vop_getwritemount = unionfs_getwritemount, 2687 .vop_inactive = unionfs_inactive, 2688 .vop_need_inactive = vop_stdneed_inactive, 2689 .vop_islocked = unionfs_islocked, 2690 .vop_ioctl = unionfs_ioctl, 2691 .vop_link = unionfs_link, 2692 .vop_listextattr = unionfs_listextattr, 2693 .vop_lock1 = unionfs_lock, 2694 .vop_lookup = vfs_cache_lookup, 2695 .vop_mkdir = unionfs_mkdir, 2696 .vop_mknod = unionfs_mknod, 2697 .vop_open = unionfs_open, 2698 .vop_openextattr = unionfs_openextattr, 2699 .vop_pathconf = unionfs_pathconf, 2700 .vop_poll = unionfs_poll, 2701 .vop_print = unionfs_print, 2702 .vop_read = unionfs_read, 2703 .vop_readdir = unionfs_readdir, 2704 .vop_readlink = unionfs_readlink, 2705 .vop_reclaim = unionfs_reclaim, 2706 .vop_remove = unionfs_remove, 2707 .vop_rename = unionfs_rename, 2708 .vop_rmdir = unionfs_rmdir, 2709 .vop_setacl = unionfs_setacl, 2710 .vop_setattr = unionfs_setattr, 2711 .vop_setextattr = unionfs_setextattr, 2712 .vop_setlabel = unionfs_setlabel, 2713 .vop_strategy = unionfs_strategy, 2714 .vop_symlink = unionfs_symlink, 2715 .vop_unlock = unionfs_unlock, 2716 .vop_whiteout = unionfs_whiteout, 2717 .vop_write = unionfs_write, 2718 .vop_vptofh = unionfs_vptofh, 2719 .vop_add_writecount = unionfs_add_writecount, 2720 .vop_vput_pair = unionfs_vput_pair, 2721 }; 2722 VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops); 2723