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