1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1994 Jan-Simon Pendry 5 * Copyright (c) 1994 6 * The Regents of the University of California. All rights reserved. 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 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)union_subr.c 8.20 (Berkeley) 5/20/95 38 * $FreeBSD$ 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/ktr.h> 45 #include <sys/lock.h> 46 #include <sys/mutex.h> 47 #include <sys/malloc.h> 48 #include <sys/mount.h> 49 #include <sys/namei.h> 50 #include <sys/proc.h> 51 #include <sys/vnode.h> 52 #include <sys/dirent.h> 53 #include <sys/fcntl.h> 54 #include <sys/filedesc.h> 55 #include <sys/stat.h> 56 #include <sys/resourcevar.h> 57 58 #include <security/mac/mac_framework.h> 59 60 #include <vm/uma.h> 61 62 #include <fs/unionfs/union.h> 63 64 #define NUNIONFSNODECACHE 16 65 66 static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table"); 67 MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part"); 68 MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part"); 69 70 /* 71 * Initialize 72 */ 73 int 74 unionfs_init(struct vfsconf *vfsp) 75 { 76 UNIONFSDEBUG("unionfs_init\n"); /* printed during system boot */ 77 return (0); 78 } 79 80 /* 81 * Uninitialize 82 */ 83 int 84 unionfs_uninit(struct vfsconf *vfsp) 85 { 86 return (0); 87 } 88 89 static struct unionfs_node_hashhead * 90 unionfs_get_hashhead(struct vnode *dvp, char *path) 91 { 92 int count; 93 char hash; 94 struct unionfs_node *unp; 95 96 hash = 0; 97 unp = VTOUNIONFS(dvp); 98 if (path != NULL) { 99 for (count = 0; path[count]; count++) 100 hash += path[count]; 101 } 102 103 return (&(unp->un_hashtbl[hash & (unp->un_hashmask)])); 104 } 105 106 /* 107 * Get the cached vnode. 108 */ 109 static struct vnode * 110 unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp, 111 struct vnode *dvp, char *path) 112 { 113 struct unionfs_node_hashhead *hd; 114 struct unionfs_node *unp; 115 struct vnode *vp; 116 117 KASSERT((uvp == NULLVP || uvp->v_type == VDIR), 118 ("unionfs_get_cached_vnode: v_type != VDIR")); 119 KASSERT((lvp == NULLVP || lvp->v_type == VDIR), 120 ("unionfs_get_cached_vnode: v_type != VDIR")); 121 122 VI_LOCK(dvp); 123 hd = unionfs_get_hashhead(dvp, path); 124 LIST_FOREACH(unp, hd, un_hash) { 125 if (!strcmp(unp->un_path, path)) { 126 vp = UNIONFSTOV(unp); 127 VI_LOCK_FLAGS(vp, MTX_DUPOK); 128 VI_UNLOCK(dvp); 129 vp->v_iflag &= ~VI_OWEINACT; 130 if (VN_IS_DOOMED(vp) || 131 ((vp->v_iflag & VI_DOINGINACT) != 0)) { 132 VI_UNLOCK(vp); 133 vp = NULLVP; 134 } else 135 VI_UNLOCK(vp); 136 return (vp); 137 } 138 } 139 VI_UNLOCK(dvp); 140 141 return (NULLVP); 142 } 143 144 /* 145 * Add the new vnode into cache. 146 */ 147 static struct vnode * 148 unionfs_ins_cached_vnode(struct unionfs_node *uncp, 149 struct vnode *dvp, char *path) 150 { 151 struct unionfs_node_hashhead *hd; 152 struct unionfs_node *unp; 153 struct vnode *vp; 154 155 KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR), 156 ("unionfs_ins_cached_vnode: v_type != VDIR")); 157 KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR), 158 ("unionfs_ins_cached_vnode: v_type != VDIR")); 159 160 VI_LOCK(dvp); 161 hd = unionfs_get_hashhead(dvp, path); 162 LIST_FOREACH(unp, hd, un_hash) { 163 if (!strcmp(unp->un_path, path)) { 164 vp = UNIONFSTOV(unp); 165 VI_LOCK_FLAGS(vp, MTX_DUPOK); 166 vp->v_iflag &= ~VI_OWEINACT; 167 if (VN_IS_DOOMED(vp) || 168 ((vp->v_iflag & VI_DOINGINACT) != 0)) { 169 LIST_INSERT_HEAD(hd, uncp, un_hash); 170 VI_UNLOCK(vp); 171 vp = NULLVP; 172 } else 173 VI_UNLOCK(vp); 174 VI_UNLOCK(dvp); 175 return (vp); 176 } 177 } 178 179 LIST_INSERT_HEAD(hd, uncp, un_hash); 180 VI_UNLOCK(dvp); 181 182 return (NULLVP); 183 } 184 185 /* 186 * Remove the vnode. 187 */ 188 static void 189 unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp) 190 { 191 KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node")); 192 KASSERT((dvp != NULLVP), 193 ("unionfs_rem_cached_vnode: null parent vnode")); 194 KASSERT((unp->un_hash.le_prev != NULL), 195 ("unionfs_rem_cached_vnode: null hash")); 196 197 VI_LOCK(dvp); 198 LIST_REMOVE(unp, un_hash); 199 unp->un_hash.le_next = NULL; 200 unp->un_hash.le_prev = NULL; 201 VI_UNLOCK(dvp); 202 } 203 204 /* 205 * Make a new or get existing unionfs node. 206 * 207 * uppervp and lowervp should be unlocked. Because if new unionfs vnode is 208 * locked, uppervp or lowervp is locked too. In order to prevent dead lock, 209 * you should not lock plurality simultaneously. 210 */ 211 int 212 unionfs_nodeget(struct mount *mp, struct vnode *uppervp, 213 struct vnode *lowervp, struct vnode *dvp, 214 struct vnode **vpp, struct componentname *cnp, 215 struct thread *td) 216 { 217 struct unionfs_mount *ump; 218 struct unionfs_node *unp; 219 struct vnode *vp; 220 int error; 221 int lkflags; 222 enum vtype vt; 223 char *path; 224 225 ump = MOUNTTOUNIONFSMOUNT(mp); 226 lkflags = (cnp ? cnp->cn_lkflags : 0); 227 path = (cnp ? cnp->cn_nameptr : NULL); 228 *vpp = NULLVP; 229 230 if (uppervp == NULLVP && lowervp == NULLVP) 231 panic("unionfs_nodeget: upper and lower is null"); 232 233 vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type); 234 235 /* If it has no ISLASTCN flag, path check is skipped. */ 236 if (cnp && !(cnp->cn_flags & ISLASTCN)) 237 path = NULL; 238 239 /* check the cache */ 240 if (path != NULL && dvp != NULLVP && vt == VDIR) { 241 vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path); 242 if (vp != NULLVP) { 243 vref(vp); 244 *vpp = vp; 245 goto unionfs_nodeget_out; 246 } 247 } 248 249 if ((uppervp == NULLVP || ump->um_uppervp != uppervp) || 250 (lowervp == NULLVP || ump->um_lowervp != lowervp)) { 251 /* dvp will be NULLVP only in case of root vnode. */ 252 if (dvp == NULLVP) 253 return (EINVAL); 254 } 255 unp = malloc(sizeof(struct unionfs_node), 256 M_UNIONFSNODE, M_WAITOK | M_ZERO); 257 258 error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp); 259 if (error != 0) { 260 free(unp, M_UNIONFSNODE); 261 return (error); 262 } 263 error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */ 264 if (error != 0) { 265 free(unp, M_UNIONFSNODE); 266 return (error); 267 } 268 if (dvp != NULLVP) 269 vref(dvp); 270 if (uppervp != NULLVP) 271 vref(uppervp); 272 if (lowervp != NULLVP) 273 vref(lowervp); 274 275 if (vt == VDIR) 276 unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH, 277 &(unp->un_hashmask)); 278 279 unp->un_vnode = vp; 280 unp->un_uppervp = uppervp; 281 unp->un_lowervp = lowervp; 282 unp->un_dvp = dvp; 283 if (uppervp != NULLVP) 284 vp->v_vnlock = uppervp->v_vnlock; 285 else 286 vp->v_vnlock = lowervp->v_vnlock; 287 288 if (path != NULL) { 289 unp->un_path = (char *) 290 malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO); 291 bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen); 292 unp->un_path[cnp->cn_namelen] = '\0'; 293 } 294 vp->v_type = vt; 295 vp->v_data = unp; 296 297 if ((uppervp != NULLVP && ump->um_uppervp == uppervp) && 298 (lowervp != NULLVP && ump->um_lowervp == lowervp)) 299 vp->v_vflag |= VV_ROOT; 300 301 if (path != NULL && dvp != NULLVP && vt == VDIR) 302 *vpp = unionfs_ins_cached_vnode(unp, dvp, path); 303 if ((*vpp) != NULLVP) { 304 if (dvp != NULLVP) 305 vrele(dvp); 306 if (uppervp != NULLVP) 307 vrele(uppervp); 308 if (lowervp != NULLVP) 309 vrele(lowervp); 310 311 unp->un_uppervp = NULLVP; 312 unp->un_lowervp = NULLVP; 313 unp->un_dvp = NULLVP; 314 vrele(vp); 315 vp = *vpp; 316 vref(vp); 317 } else 318 *vpp = vp; 319 320 unionfs_nodeget_out: 321 if (lkflags & LK_TYPE_MASK) 322 vn_lock(vp, lkflags | LK_RETRY); 323 324 return (0); 325 } 326 327 /* 328 * Clean up the unionfs node. 329 */ 330 void 331 unionfs_noderem(struct vnode *vp, struct thread *td) 332 { 333 int count; 334 struct unionfs_node *unp, *unp_t1, *unp_t2; 335 struct unionfs_node_hashhead *hd; 336 struct unionfs_node_status *unsp, *unsp_tmp; 337 struct vnode *lvp; 338 struct vnode *uvp; 339 struct vnode *dvp; 340 341 /* 342 * Use the interlock to protect the clearing of v_data to 343 * prevent faults in unionfs_lock(). 344 */ 345 VI_LOCK(vp); 346 unp = VTOUNIONFS(vp); 347 lvp = unp->un_lowervp; 348 uvp = unp->un_uppervp; 349 dvp = unp->un_dvp; 350 unp->un_lowervp = unp->un_uppervp = NULLVP; 351 vp->v_vnlock = &(vp->v_lock); 352 vp->v_data = NULL; 353 vp->v_object = NULL; 354 if (vp->v_writecount > 0) { 355 if (uvp != NULL) 356 VOP_ADD_WRITECOUNT(uvp, -vp->v_writecount); 357 else if (lvp != NULL) 358 VOP_ADD_WRITECOUNT(lvp, -vp->v_writecount); 359 } else if (vp->v_writecount < 0) 360 vp->v_writecount = 0; 361 VI_UNLOCK(vp); 362 363 if (lvp != NULLVP) 364 VOP_UNLOCK(lvp, LK_RELEASE); 365 if (uvp != NULLVP) 366 VOP_UNLOCK(uvp, LK_RELEASE); 367 368 if (dvp != NULLVP && unp->un_hash.le_prev != NULL) 369 unionfs_rem_cached_vnode(unp, dvp); 370 371 if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0) 372 panic("the lock for deletion is unacquirable."); 373 374 if (lvp != NULLVP) 375 vrele(lvp); 376 if (uvp != NULLVP) 377 vrele(uvp); 378 if (dvp != NULLVP) { 379 vrele(dvp); 380 unp->un_dvp = NULLVP; 381 } 382 if (unp->un_path != NULL) { 383 free(unp->un_path, M_UNIONFSPATH); 384 unp->un_path = NULL; 385 } 386 387 if (unp->un_hashtbl != NULL) { 388 for (count = 0; count <= unp->un_hashmask; count++) { 389 hd = unp->un_hashtbl + count; 390 LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) { 391 LIST_REMOVE(unp_t1, un_hash); 392 unp_t1->un_hash.le_next = NULL; 393 unp_t1->un_hash.le_prev = NULL; 394 } 395 } 396 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask); 397 } 398 399 LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) { 400 LIST_REMOVE(unsp, uns_list); 401 free(unsp, M_TEMP); 402 } 403 free(unp, M_UNIONFSNODE); 404 } 405 406 /* 407 * Get the unionfs node status. 408 * You need exclusive lock this vnode. 409 */ 410 void 411 unionfs_get_node_status(struct unionfs_node *unp, struct thread *td, 412 struct unionfs_node_status **unspp) 413 { 414 struct unionfs_node_status *unsp; 415 pid_t pid = td->td_proc->p_pid; 416 417 KASSERT(NULL != unspp, ("null pointer")); 418 ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status"); 419 420 LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { 421 if (unsp->uns_pid == pid) { 422 *unspp = unsp; 423 return; 424 } 425 } 426 427 /* create a new unionfs node status */ 428 unsp = malloc(sizeof(struct unionfs_node_status), 429 M_TEMP, M_WAITOK | M_ZERO); 430 431 unsp->uns_pid = pid; 432 LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); 433 434 *unspp = unsp; 435 } 436 437 /* 438 * Remove the unionfs node status, if you can. 439 * You need exclusive lock this vnode. 440 */ 441 void 442 unionfs_tryrem_node_status(struct unionfs_node *unp, 443 struct unionfs_node_status *unsp) 444 { 445 KASSERT(NULL != unsp, ("null pointer")); 446 ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status"); 447 448 if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt) 449 return; 450 451 LIST_REMOVE(unsp, uns_list); 452 free(unsp, M_TEMP); 453 } 454 455 /* 456 * Create upper node attr. 457 */ 458 void 459 unionfs_create_uppervattr_core(struct unionfs_mount *ump, 460 struct vattr *lva, 461 struct vattr *uva, 462 struct thread *td) 463 { 464 VATTR_NULL(uva); 465 uva->va_type = lva->va_type; 466 uva->va_atime = lva->va_atime; 467 uva->va_mtime = lva->va_mtime; 468 uva->va_ctime = lva->va_ctime; 469 470 switch (ump->um_copymode) { 471 case UNIONFS_TRANSPARENT: 472 uva->va_mode = lva->va_mode; 473 uva->va_uid = lva->va_uid; 474 uva->va_gid = lva->va_gid; 475 break; 476 case UNIONFS_MASQUERADE: 477 if (ump->um_uid == lva->va_uid) { 478 uva->va_mode = lva->va_mode & 077077; 479 uva->va_mode |= (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile) & 0700; 480 uva->va_uid = lva->va_uid; 481 uva->va_gid = lva->va_gid; 482 } else { 483 uva->va_mode = (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile); 484 uva->va_uid = ump->um_uid; 485 uva->va_gid = ump->um_gid; 486 } 487 break; 488 default: /* UNIONFS_TRADITIONAL */ 489 uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask; 490 uva->va_uid = ump->um_uid; 491 uva->va_gid = ump->um_gid; 492 break; 493 } 494 } 495 496 /* 497 * Create upper node attr. 498 */ 499 int 500 unionfs_create_uppervattr(struct unionfs_mount *ump, 501 struct vnode *lvp, 502 struct vattr *uva, 503 struct ucred *cred, 504 struct thread *td) 505 { 506 int error; 507 struct vattr lva; 508 509 if ((error = VOP_GETATTR(lvp, &lva, cred))) 510 return (error); 511 512 unionfs_create_uppervattr_core(ump, &lva, uva, td); 513 514 return (error); 515 } 516 517 /* 518 * relookup 519 * 520 * dvp should be locked on entry and will be locked on return. 521 * 522 * If an error is returned, *vpp will be invalid, otherwise it will hold a 523 * locked, referenced vnode. If *vpp == dvp then remember that only one 524 * LK_EXCLUSIVE lock is held. 525 */ 526 int 527 unionfs_relookup(struct vnode *dvp, struct vnode **vpp, 528 struct componentname *cnp, struct componentname *cn, 529 struct thread *td, char *path, int pathlen, u_long nameiop) 530 { 531 int error; 532 533 cn->cn_namelen = pathlen; 534 cn->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 535 bcopy(path, cn->cn_pnbuf, pathlen); 536 cn->cn_pnbuf[pathlen] = '\0'; 537 538 cn->cn_nameiop = nameiop; 539 cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN); 540 cn->cn_lkflags = LK_EXCLUSIVE; 541 cn->cn_thread = td; 542 cn->cn_cred = cnp->cn_cred; 543 544 cn->cn_nameptr = cn->cn_pnbuf; 545 546 if (nameiop == DELETE) 547 cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART)); 548 else if (RENAME == nameiop) 549 cn->cn_flags |= (cnp->cn_flags & SAVESTART); 550 else if (nameiop == CREATE) 551 cn->cn_flags |= NOCACHE; 552 553 vref(dvp); 554 VOP_UNLOCK(dvp, LK_RELEASE); 555 556 if ((error = relookup(dvp, vpp, cn))) { 557 uma_zfree(namei_zone, cn->cn_pnbuf); 558 cn->cn_flags &= ~HASBUF; 559 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 560 } else 561 vrele(dvp); 562 563 return (error); 564 } 565 566 /* 567 * relookup for CREATE namei operation. 568 * 569 * dvp is unionfs vnode. dvp should be locked. 570 * 571 * If it called 'unionfs_copyfile' function by unionfs_link etc, 572 * VOP_LOOKUP information is broken. 573 * So it need relookup in order to create link etc. 574 */ 575 int 576 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp, 577 struct thread *td) 578 { 579 int error; 580 struct vnode *udvp; 581 struct vnode *vp; 582 struct componentname cn; 583 584 udvp = UNIONFSVPTOUPPERVP(dvp); 585 vp = NULLVP; 586 587 error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, 588 strlen(cnp->cn_nameptr), CREATE); 589 if (error) 590 return (error); 591 592 if (vp != NULLVP) { 593 if (udvp == vp) 594 vrele(vp); 595 else 596 vput(vp); 597 598 error = EEXIST; 599 } 600 601 if (cn.cn_flags & HASBUF) { 602 uma_zfree(namei_zone, cn.cn_pnbuf); 603 cn.cn_flags &= ~HASBUF; 604 } 605 606 if (!error) { 607 cn.cn_flags |= (cnp->cn_flags & HASBUF); 608 cnp->cn_flags = cn.cn_flags; 609 } 610 611 return (error); 612 } 613 614 /* 615 * relookup for DELETE namei operation. 616 * 617 * dvp is unionfs vnode. dvp should be locked. 618 */ 619 int 620 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp, 621 struct thread *td) 622 { 623 int error; 624 struct vnode *udvp; 625 struct vnode *vp; 626 struct componentname cn; 627 628 udvp = UNIONFSVPTOUPPERVP(dvp); 629 vp = NULLVP; 630 631 error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, 632 strlen(cnp->cn_nameptr), DELETE); 633 if (error) 634 return (error); 635 636 if (vp == NULLVP) 637 error = ENOENT; 638 else { 639 if (udvp == vp) 640 vrele(vp); 641 else 642 vput(vp); 643 } 644 645 if (cn.cn_flags & HASBUF) { 646 uma_zfree(namei_zone, cn.cn_pnbuf); 647 cn.cn_flags &= ~HASBUF; 648 } 649 650 if (!error) { 651 cn.cn_flags |= (cnp->cn_flags & HASBUF); 652 cnp->cn_flags = cn.cn_flags; 653 } 654 655 return (error); 656 } 657 658 /* 659 * relookup for RENAME namei operation. 660 * 661 * dvp is unionfs vnode. dvp should be locked. 662 */ 663 int 664 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp, 665 struct thread *td) 666 { 667 int error; 668 struct vnode *udvp; 669 struct vnode *vp; 670 struct componentname cn; 671 672 udvp = UNIONFSVPTOUPPERVP(dvp); 673 vp = NULLVP; 674 675 error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, 676 strlen(cnp->cn_nameptr), RENAME); 677 if (error) 678 return (error); 679 680 if (vp != NULLVP) { 681 if (udvp == vp) 682 vrele(vp); 683 else 684 vput(vp); 685 } 686 687 if (cn.cn_flags & HASBUF) { 688 uma_zfree(namei_zone, cn.cn_pnbuf); 689 cn.cn_flags &= ~HASBUF; 690 } 691 692 if (!error) { 693 cn.cn_flags |= (cnp->cn_flags & HASBUF); 694 cnp->cn_flags = cn.cn_flags; 695 } 696 697 return (error); 698 699 } 700 701 /* 702 * Update the unionfs_node. 703 * 704 * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the 705 * uvp's lock and lower's lock will be unlocked. 706 */ 707 static void 708 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp, 709 struct thread *td) 710 { 711 unsigned count, lockrec; 712 struct vnode *vp; 713 struct vnode *lvp; 714 struct vnode *dvp; 715 716 vp = UNIONFSTOV(unp); 717 lvp = unp->un_lowervp; 718 ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update"); 719 dvp = unp->un_dvp; 720 721 /* 722 * lock update 723 */ 724 VI_LOCK(vp); 725 unp->un_uppervp = uvp; 726 vp->v_vnlock = uvp->v_vnlock; 727 VI_UNLOCK(vp); 728 lockrec = lvp->v_vnlock->lk_recurse; 729 for (count = 0; count < lockrec; count++) 730 vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY); 731 732 /* 733 * cache update 734 */ 735 if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) { 736 static struct unionfs_node_hashhead *hd; 737 738 VI_LOCK(dvp); 739 hd = unionfs_get_hashhead(dvp, unp->un_path); 740 LIST_REMOVE(unp, un_hash); 741 LIST_INSERT_HEAD(hd, unp, un_hash); 742 VI_UNLOCK(dvp); 743 } 744 } 745 746 /* 747 * Create a new shadow dir. 748 * 749 * udvp should be locked on entry and will be locked on return. 750 * 751 * If no error returned, unp will be updated. 752 */ 753 int 754 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp, 755 struct unionfs_node *unp, struct componentname *cnp, 756 struct thread *td) 757 { 758 int error; 759 struct vnode *lvp; 760 struct vnode *uvp; 761 struct vattr va; 762 struct vattr lva; 763 struct componentname cn; 764 struct mount *mp; 765 struct ucred *cred; 766 struct ucred *credbk; 767 struct uidinfo *rootinfo; 768 769 if (unp->un_uppervp != NULLVP) 770 return (EEXIST); 771 772 lvp = unp->un_lowervp; 773 uvp = NULLVP; 774 credbk = cnp->cn_cred; 775 776 /* Authority change to root */ 777 rootinfo = uifind((uid_t)0); 778 cred = crdup(cnp->cn_cred); 779 /* 780 * The calls to chgproccnt() are needed to compensate for change_ruid() 781 * calling chgproccnt(). 782 */ 783 chgproccnt(cred->cr_ruidinfo, 1, 0); 784 change_euid(cred, rootinfo); 785 change_ruid(cred, rootinfo); 786 change_svuid(cred, (uid_t)0); 787 uifree(rootinfo); 788 cnp->cn_cred = cred; 789 790 memset(&cn, 0, sizeof(cn)); 791 792 if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) 793 goto unionfs_mkshadowdir_abort; 794 795 if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, td, cnp->cn_nameptr, cnp->cn_namelen, CREATE))) 796 goto unionfs_mkshadowdir_abort; 797 if (uvp != NULLVP) { 798 if (udvp == uvp) 799 vrele(uvp); 800 else 801 vput(uvp); 802 803 error = EEXIST; 804 goto unionfs_mkshadowdir_free_out; 805 } 806 807 if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH))) 808 goto unionfs_mkshadowdir_free_out; 809 unionfs_create_uppervattr_core(ump, &lva, &va, td); 810 811 error = VOP_MKDIR(udvp, &uvp, &cn, &va); 812 813 if (!error) { 814 unionfs_node_update(unp, uvp, td); 815 816 /* 817 * XXX The bug which cannot set uid/gid was corrected. 818 * Ignore errors. 819 */ 820 va.va_type = VNON; 821 VOP_SETATTR(uvp, &va, cn.cn_cred); 822 } 823 vn_finished_write(mp); 824 825 unionfs_mkshadowdir_free_out: 826 if (cn.cn_flags & HASBUF) { 827 uma_zfree(namei_zone, cn.cn_pnbuf); 828 cn.cn_flags &= ~HASBUF; 829 } 830 831 unionfs_mkshadowdir_abort: 832 cnp->cn_cred = credbk; 833 chgproccnt(cred->cr_ruidinfo, -1, 0); 834 crfree(cred); 835 836 return (error); 837 } 838 839 /* 840 * Create a new whiteout. 841 * 842 * dvp should be locked on entry and will be locked on return. 843 */ 844 int 845 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, 846 struct thread *td, char *path) 847 { 848 int error; 849 struct vnode *wvp; 850 struct componentname cn; 851 struct mount *mp; 852 853 if (path == NULL) 854 path = cnp->cn_nameptr; 855 856 wvp = NULLVP; 857 if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, td, path, strlen(path), CREATE))) 858 return (error); 859 if (wvp != NULLVP) { 860 if (cn.cn_flags & HASBUF) { 861 uma_zfree(namei_zone, cn.cn_pnbuf); 862 cn.cn_flags &= ~HASBUF; 863 } 864 if (dvp == wvp) 865 vrele(wvp); 866 else 867 vput(wvp); 868 869 return (EEXIST); 870 } 871 872 if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH))) 873 goto unionfs_mkwhiteout_free_out; 874 error = VOP_WHITEOUT(dvp, &cn, CREATE); 875 876 vn_finished_write(mp); 877 878 unionfs_mkwhiteout_free_out: 879 if (cn.cn_flags & HASBUF) { 880 uma_zfree(namei_zone, cn.cn_pnbuf); 881 cn.cn_flags &= ~HASBUF; 882 } 883 884 return (error); 885 } 886 887 /* 888 * Create a new vnode for create a new shadow file. 889 * 890 * If an error is returned, *vpp will be invalid, otherwise it will hold a 891 * locked, referenced and opened vnode. 892 * 893 * unp is never updated. 894 */ 895 static int 896 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp, 897 struct unionfs_node *unp, struct vattr *uvap, 898 struct thread *td) 899 { 900 struct unionfs_mount *ump; 901 struct vnode *vp; 902 struct vnode *lvp; 903 struct ucred *cred; 904 struct vattr lva; 905 int fmode; 906 int error; 907 struct componentname cn; 908 909 ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); 910 vp = NULLVP; 911 lvp = unp->un_lowervp; 912 cred = td->td_ucred; 913 fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); 914 error = 0; 915 916 if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0) 917 return (error); 918 unionfs_create_uppervattr_core(ump, &lva, uvap, td); 919 920 if (unp->un_path == NULL) 921 panic("unionfs: un_path is null"); 922 923 cn.cn_namelen = strlen(unp->un_path); 924 cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 925 bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1); 926 cn.cn_nameiop = CREATE; 927 cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN); 928 cn.cn_lkflags = LK_EXCLUSIVE; 929 cn.cn_thread = td; 930 cn.cn_cred = cred; 931 cn.cn_nameptr = cn.cn_pnbuf; 932 933 vref(udvp); 934 if ((error = relookup(udvp, &vp, &cn)) != 0) 935 goto unionfs_vn_create_on_upper_free_out2; 936 vrele(udvp); 937 938 if (vp != NULLVP) { 939 if (vp == udvp) 940 vrele(vp); 941 else 942 vput(vp); 943 error = EEXIST; 944 goto unionfs_vn_create_on_upper_free_out1; 945 } 946 947 if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0) 948 goto unionfs_vn_create_on_upper_free_out1; 949 950 if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) { 951 vput(vp); 952 goto unionfs_vn_create_on_upper_free_out1; 953 } 954 error = VOP_ADD_WRITECOUNT(vp, 1); 955 CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d", __func__, vp, 956 vp->v_writecount); 957 if (error == 0) { 958 *vpp = vp; 959 } else { 960 VOP_CLOSE(vp, fmode, cred, td); 961 } 962 963 unionfs_vn_create_on_upper_free_out1: 964 VOP_UNLOCK(udvp, LK_RELEASE); 965 966 unionfs_vn_create_on_upper_free_out2: 967 if (cn.cn_flags & HASBUF) { 968 uma_zfree(namei_zone, cn.cn_pnbuf); 969 cn.cn_flags &= ~HASBUF; 970 } 971 972 return (error); 973 } 974 975 /* 976 * Copy from lvp to uvp. 977 * 978 * lvp and uvp should be locked and opened on entry and will be locked and 979 * opened on return. 980 */ 981 static int 982 unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp, 983 struct ucred *cred, struct thread *td) 984 { 985 int error; 986 off_t offset; 987 int count; 988 int bufoffset; 989 char *buf; 990 struct uio uio; 991 struct iovec iov; 992 993 error = 0; 994 memset(&uio, 0, sizeof(uio)); 995 996 uio.uio_td = td; 997 uio.uio_segflg = UIO_SYSSPACE; 998 uio.uio_offset = 0; 999 1000 buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK); 1001 1002 while (error == 0) { 1003 offset = uio.uio_offset; 1004 1005 uio.uio_iov = &iov; 1006 uio.uio_iovcnt = 1; 1007 iov.iov_base = buf; 1008 iov.iov_len = MAXBSIZE; 1009 uio.uio_resid = iov.iov_len; 1010 uio.uio_rw = UIO_READ; 1011 1012 if ((error = VOP_READ(lvp, &uio, 0, cred)) != 0) 1013 break; 1014 if ((count = MAXBSIZE - uio.uio_resid) == 0) 1015 break; 1016 1017 bufoffset = 0; 1018 while (bufoffset < count) { 1019 uio.uio_iov = &iov; 1020 uio.uio_iovcnt = 1; 1021 iov.iov_base = buf + bufoffset; 1022 iov.iov_len = count - bufoffset; 1023 uio.uio_offset = offset + bufoffset; 1024 uio.uio_resid = iov.iov_len; 1025 uio.uio_rw = UIO_WRITE; 1026 1027 if ((error = VOP_WRITE(uvp, &uio, 0, cred)) != 0) 1028 break; 1029 1030 bufoffset += (count - bufoffset) - uio.uio_resid; 1031 } 1032 1033 uio.uio_offset = offset + bufoffset; 1034 } 1035 1036 free(buf, M_TEMP); 1037 1038 return (error); 1039 } 1040 1041 /* 1042 * Copy file from lower to upper. 1043 * 1044 * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to 1045 * docopy. 1046 * 1047 * If no error returned, unp will be updated. 1048 */ 1049 int 1050 unionfs_copyfile(struct unionfs_node *unp, int docopy, struct ucred *cred, 1051 struct thread *td) 1052 { 1053 int error; 1054 struct mount *mp; 1055 struct vnode *udvp; 1056 struct vnode *lvp; 1057 struct vnode *uvp; 1058 struct vattr uva; 1059 1060 lvp = unp->un_lowervp; 1061 uvp = NULLVP; 1062 1063 if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY)) 1064 return (EROFS); 1065 if (unp->un_dvp == NULLVP) 1066 return (EINVAL); 1067 if (unp->un_uppervp != NULLVP) 1068 return (EEXIST); 1069 udvp = VTOUNIONFS(unp->un_dvp)->un_uppervp; 1070 if (udvp == NULLVP) 1071 return (EROFS); 1072 if ((udvp->v_mount->mnt_flag & MNT_RDONLY)) 1073 return (EROFS); 1074 1075 error = VOP_ACCESS(lvp, VREAD, cred, td); 1076 if (error != 0) 1077 return (error); 1078 1079 if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)) != 0) 1080 return (error); 1081 error = unionfs_vn_create_on_upper(&uvp, udvp, unp, &uva, td); 1082 if (error != 0) { 1083 vn_finished_write(mp); 1084 return (error); 1085 } 1086 1087 if (docopy != 0) { 1088 error = VOP_OPEN(lvp, FREAD, cred, td, NULL); 1089 if (error == 0) { 1090 error = unionfs_copyfile_core(lvp, uvp, cred, td); 1091 VOP_CLOSE(lvp, FREAD, cred, td); 1092 } 1093 } 1094 VOP_CLOSE(uvp, FWRITE, cred, td); 1095 VOP_ADD_WRITECOUNT_CHECKED(uvp, -1); 1096 CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d", __func__, uvp, 1097 uvp->v_writecount); 1098 1099 vn_finished_write(mp); 1100 1101 if (error == 0) { 1102 /* Reset the attributes. Ignore errors. */ 1103 uva.va_type = VNON; 1104 VOP_SETATTR(uvp, &uva, cred); 1105 } 1106 1107 unionfs_node_update(unp, uvp, td); 1108 1109 return (error); 1110 } 1111 1112 /* 1113 * It checks whether vp can rmdir. (check empty) 1114 * 1115 * vp is unionfs vnode. 1116 * vp should be locked. 1117 */ 1118 int 1119 unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td) 1120 { 1121 int error; 1122 int eofflag; 1123 int lookuperr; 1124 struct vnode *uvp; 1125 struct vnode *lvp; 1126 struct vnode *tvp; 1127 struct vattr va; 1128 struct componentname cn; 1129 /* 1130 * The size of buf needs to be larger than DIRBLKSIZ. 1131 */ 1132 char buf[256 * 6]; 1133 struct dirent *dp; 1134 struct dirent *edp; 1135 struct uio uio; 1136 struct iovec iov; 1137 1138 ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir"); 1139 1140 eofflag = 0; 1141 uvp = UNIONFSVPTOUPPERVP(vp); 1142 lvp = UNIONFSVPTOLOWERVP(vp); 1143 1144 /* check opaque */ 1145 if ((error = VOP_GETATTR(uvp, &va, cred)) != 0) 1146 return (error); 1147 if (va.va_flags & OPAQUE) 1148 return (0); 1149 1150 /* open vnode */ 1151 #ifdef MAC 1152 if ((error = mac_vnode_check_open(cred, vp, VEXEC|VREAD)) != 0) 1153 return (error); 1154 #endif 1155 if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0) 1156 return (error); 1157 if ((error = VOP_OPEN(vp, FREAD, cred, td, NULL)) != 0) 1158 return (error); 1159 1160 uio.uio_rw = UIO_READ; 1161 uio.uio_segflg = UIO_SYSSPACE; 1162 uio.uio_td = td; 1163 uio.uio_offset = 0; 1164 1165 #ifdef MAC 1166 error = mac_vnode_check_readdir(td->td_ucred, lvp); 1167 #endif 1168 while (!error && !eofflag) { 1169 iov.iov_base = buf; 1170 iov.iov_len = sizeof(buf); 1171 uio.uio_iov = &iov; 1172 uio.uio_iovcnt = 1; 1173 uio.uio_resid = iov.iov_len; 1174 1175 error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL); 1176 if (error != 0) 1177 break; 1178 if (eofflag == 0 && uio.uio_resid == sizeof(buf)) { 1179 #ifdef DIAGNOSTIC 1180 panic("bad readdir response from lower FS."); 1181 #endif 1182 break; 1183 } 1184 1185 edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid]; 1186 for (dp = (struct dirent*)buf; !error && dp < edp; 1187 dp = (struct dirent*)((caddr_t)dp + dp->d_reclen)) { 1188 if (dp->d_type == DT_WHT || dp->d_fileno == 0 || 1189 (dp->d_namlen == 1 && dp->d_name[0] == '.') || 1190 (dp->d_namlen == 2 && !bcmp(dp->d_name, "..", 2))) 1191 continue; 1192 1193 cn.cn_namelen = dp->d_namlen; 1194 cn.cn_pnbuf = NULL; 1195 cn.cn_nameptr = dp->d_name; 1196 cn.cn_nameiop = LOOKUP; 1197 cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN); 1198 cn.cn_lkflags = LK_EXCLUSIVE; 1199 cn.cn_thread = td; 1200 cn.cn_cred = cred; 1201 1202 /* 1203 * check entry in lower. 1204 * Sometimes, readdir function returns 1205 * wrong entry. 1206 */ 1207 lookuperr = VOP_LOOKUP(lvp, &tvp, &cn); 1208 1209 if (!lookuperr) 1210 vput(tvp); 1211 else 1212 continue; /* skip entry */ 1213 1214 /* 1215 * check entry 1216 * If it has no exist/whiteout entry in upper, 1217 * directory is not empty. 1218 */ 1219 cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN); 1220 lookuperr = VOP_LOOKUP(uvp, &tvp, &cn); 1221 1222 if (!lookuperr) 1223 vput(tvp); 1224 1225 /* ignore exist or whiteout entry */ 1226 if (!lookuperr || 1227 (lookuperr == ENOENT && (cn.cn_flags & ISWHITEOUT))) 1228 continue; 1229 1230 error = ENOTEMPTY; 1231 } 1232 } 1233 1234 /* close vnode */ 1235 VOP_CLOSE(vp, FREAD, cred, td); 1236 1237 return (error); 1238 } 1239 1240 #ifdef DIAGNOSTIC 1241 1242 struct vnode * 1243 unionfs_checkuppervp(struct vnode *vp, char *fil, int lno) 1244 { 1245 struct unionfs_node *unp; 1246 1247 unp = VTOUNIONFS(vp); 1248 1249 #ifdef notyet 1250 if (vp->v_op != unionfs_vnodeop_p) { 1251 printf("unionfs_checkuppervp: on non-unionfs-node.\n"); 1252 #ifdef KDB 1253 kdb_enter(KDB_WHY_UNIONFS, 1254 "unionfs_checkuppervp: on non-unionfs-node.\n"); 1255 #endif 1256 panic("unionfs_checkuppervp"); 1257 } 1258 #endif 1259 return (unp->un_uppervp); 1260 } 1261 1262 struct vnode * 1263 unionfs_checklowervp(struct vnode *vp, char *fil, int lno) 1264 { 1265 struct unionfs_node *unp; 1266 1267 unp = VTOUNIONFS(vp); 1268 1269 #ifdef notyet 1270 if (vp->v_op != unionfs_vnodeop_p) { 1271 printf("unionfs_checklowervp: on non-unionfs-node.\n"); 1272 #ifdef KDB 1273 kdb_enter(KDB_WHY_UNIONFS, 1274 "unionfs_checklowervp: on non-unionfs-node.\n"); 1275 #endif 1276 panic("unionfs_checklowervp"); 1277 } 1278 #endif 1279 return (unp->un_lowervp); 1280 } 1281 #endif 1282