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