1 /*- 2 * Copyright (c) 1994 Jan-Simon Pendry 3 * Copyright (c) 1994 4 * The Regents of the University of California. All rights reserved. 5 * Copyright (c) 2005, 2006 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc. 6 * Copyright (c) 2006 Daichi Goto <daichi@freebsd.org> 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)union_subr.c 8.20 (Berkeley) 5/20/95 36 * $FreeBSD: src/sys/fs/unionfs/union_subr.c,v 1.99 2008/01/24 12:34:27 attilio Exp $ 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/mutex.h> 44 #include <sys/malloc.h> 45 #include <sys/mount.h> 46 #include <sys/namei.h> 47 #include <sys/proc.h> 48 #include <sys/vnode.h> 49 #include <sys/dirent.h> 50 #include <sys/fcntl.h> 51 #include <sys/filedesc.h> 52 #include <sys/stat.h> 53 #include <sys/kauth.h> 54 #include <sys/resourcevar.h> 55 56 #include <fs/unionfs/unionfs.h> 57 58 MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part"); 59 60 /* 61 * Make a new or get existing unionfs node. 62 * 63 * uppervp and lowervp should be unlocked. Because if new unionfs vnode is 64 * locked, uppervp or lowervp is locked too. In order to prevent dead lock, 65 * you should not lock plurality simultaneously. 66 */ 67 int 68 unionfs_nodeget(struct mount *mp, struct vnode *uppervp, 69 struct vnode *lowervp, struct vnode *dvp, 70 struct vnode **vpp, struct componentname *cnp) 71 { 72 struct unionfs_mount *ump; 73 struct unionfs_node *unp; 74 struct vnode *vp; 75 int error; 76 const char *path; 77 78 ump = MOUNTTOUNIONFSMOUNT(mp); 79 path = (cnp ? cnp->cn_nameptr : NULL); 80 81 if (uppervp == NULLVP && lowervp == NULLVP) 82 panic("unionfs_nodeget: upper and lower is null"); 83 84 /* If it has no ISLASTCN flag, path check is skipped. */ 85 if (cnp && !(cnp->cn_flags & ISLASTCN)) 86 path = NULL; 87 88 if ((uppervp == NULLVP || ump->um_uppervp != uppervp) || 89 (lowervp == NULLVP || ump->um_lowervp != lowervp)) { 90 if (dvp == NULLVP) 91 return (EINVAL); 92 } 93 94 unp = kmem_zalloc(sizeof(*unp), KM_SLEEP); 95 if (unp == NULL) 96 return (ENOMEM); 97 error = getnewvnode(VT_UNION, mp, unionfs_vnodeop_p, &vp); 98 if (error != 0) { 99 kmem_free(unp, sizeof(*unp)); 100 return (error); 101 } 102 if (dvp != NULLVP) 103 vref(dvp); 104 if (uppervp != NULLVP) 105 vref(uppervp); 106 if (lowervp != NULLVP) 107 vref(lowervp); 108 109 unp->un_vnode = vp; 110 unp->un_uppervp = uppervp; 111 unp->un_lowervp = lowervp; 112 unp->un_dvp = dvp; 113 114 if (path != NULL) { 115 unp->un_path = (char *) 116 malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO); 117 memcpy(unp->un_path, cnp->cn_nameptr, cnp->cn_namelen); 118 unp->un_path[cnp->cn_namelen] = '\0'; 119 } 120 vp->v_type = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type); 121 vp->v_data = unp; 122 uvm_vnp_setsize(vp, 0); 123 124 if ((uppervp != NULLVP && ump->um_uppervp == uppervp) && 125 (lowervp != NULLVP && ump->um_lowervp == lowervp)) 126 vp->v_vflag |= VV_ROOT; 127 128 *vpp = vp; 129 130 return (0); 131 } 132 133 /* 134 * Clean up the unionfs node. 135 */ 136 void 137 unionfs_noderem(struct vnode *vp) 138 { 139 struct unionfs_mount *ump; 140 struct unionfs_node *unp; 141 struct unionfs_node_status *unsp; 142 struct vnode *lvp; 143 struct vnode *uvp; 144 145 ump = MOUNTTOUNIONFSMOUNT(vp->v_mount); 146 147 /* 148 * Use the interlock to protect the clearing of v_data to 149 * prevent faults in unionfs_lock(). 150 */ 151 unp = VTOUNIONFS(vp); 152 lvp = unp->un_lowervp; 153 uvp = unp->un_uppervp; 154 unp->un_lowervp = unp->un_uppervp = NULLVP; 155 vp->v_data = NULL; 156 157 if (lvp != NULLVP) 158 vrele(lvp); 159 if (uvp != NULLVP) 160 vrele(uvp); 161 if (unp->un_dvp != NULLVP) { 162 vrele(unp->un_dvp); 163 unp->un_dvp = NULLVP; 164 } 165 if (unp->un_path) { 166 free(unp->un_path, M_UNIONFSPATH); 167 unp->un_path = NULL; 168 } 169 170 while ((unsp = LIST_FIRST(&(unp->un_unshead))) != NULL) { 171 LIST_REMOVE(unsp, uns_list); 172 free(unsp, M_TEMP); 173 } 174 kmem_free(unp, sizeof(*unp)); 175 } 176 177 /* 178 * Get the unionfs node status. 179 * You need exclusive lock this vnode. 180 */ 181 void 182 unionfs_get_node_status(struct unionfs_node *unp, 183 struct unionfs_node_status **unspp) 184 { 185 struct unionfs_node_status *unsp; 186 pid_t pid; 187 lwpid_t lid; 188 189 KASSERT(NULL != unspp); 190 KASSERT(VOP_ISLOCKED(UNIONFSTOV(unp)) == LK_EXCLUSIVE); 191 192 pid = curproc->p_pid; 193 lid = curlwp->l_lid; 194 195 LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) { 196 if (unsp->uns_pid == pid && unsp->uns_lid == lid) { 197 *unspp = unsp; 198 return; 199 } 200 } 201 202 /* create a new unionfs node status */ 203 unsp = kmem_zalloc(sizeof(*unsp), KM_SLEEP); 204 unsp->uns_pid = pid; 205 unsp->uns_lid = lid; 206 LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list); 207 208 *unspp = unsp; 209 } 210 211 /* 212 * Remove the unionfs node status, if you can. 213 * You need exclusive lock this vnode. 214 */ 215 void 216 unionfs_tryrem_node_status(struct unionfs_node *unp, 217 struct unionfs_node_status *unsp) 218 { 219 KASSERT(NULL != unsp); 220 KASSERT(VOP_ISLOCKED(UNIONFSTOV(unp)) == LK_EXCLUSIVE); 221 222 if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt) 223 return; 224 225 LIST_REMOVE(unsp, uns_list); 226 kmem_free(unsp, sizeof(*unsp)); 227 } 228 229 /* 230 * Create upper node attr. 231 */ 232 void 233 unionfs_create_uppervattr_core(struct unionfs_mount *ump, 234 struct vattr *lva, 235 struct vattr *uva) 236 { 237 vattr_null(uva); 238 uva->va_type = lva->va_type; 239 uva->va_atime = lva->va_atime; 240 uva->va_mtime = lva->va_mtime; 241 uva->va_ctime = lva->va_ctime; 242 243 switch (ump->um_copymode) { 244 case UNIONFS_TRANSPARENT: 245 uva->va_mode = lva->va_mode; 246 uva->va_uid = lva->va_uid; 247 uva->va_gid = lva->va_gid; 248 break; 249 case UNIONFS_MASQUERADE: 250 if (ump->um_uid == lva->va_uid) { 251 uva->va_mode = lva->va_mode & 077077; 252 uva->va_mode |= (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile) & 0700; 253 uva->va_uid = lva->va_uid; 254 uva->va_gid = lva->va_gid; 255 } else { 256 uva->va_mode = (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile); 257 uva->va_uid = ump->um_uid; 258 uva->va_gid = ump->um_gid; 259 } 260 break; 261 default: /* UNIONFS_TRADITIONAL */ 262 uva->va_mode = 0777 & ~curproc->p_cwdi->cwdi_cmask; 263 uva->va_uid = ump->um_uid; 264 uva->va_gid = ump->um_gid; 265 break; 266 } 267 } 268 269 /* 270 * Create upper node attr. 271 */ 272 int 273 unionfs_create_uppervattr(struct unionfs_mount *ump, 274 struct vnode *lvp, 275 struct vattr *uva, 276 kauth_cred_t cred) 277 { 278 int error; 279 struct vattr lva; 280 281 if ((error = VOP_GETATTR(lvp, &lva, cred))) 282 return (error); 283 284 unionfs_create_uppervattr_core(ump, &lva, uva); 285 286 return (error); 287 } 288 289 /* 290 * relookup 291 * 292 * dvp should be locked on entry and will be locked on return. 293 * 294 * If an error is returned, *vpp will be invalid, otherwise it will hold a 295 * locked, referenced vnode. If *vpp == dvp then remember that only one 296 * LK_EXCLUSIVE lock is held. 297 */ 298 static int 299 unionfs_relookup(struct vnode *dvp, struct vnode **vpp, 300 struct componentname *cnp, struct componentname *cn, 301 char **pnbuf_ret, 302 const char *path, int pathlen, u_long nameiop) 303 { 304 int error; 305 char *pnbuf; 306 307 cn->cn_namelen = pathlen; 308 pnbuf = PNBUF_GET(); 309 memcpy(pnbuf, path, pathlen); 310 pnbuf[pathlen] = '\0'; 311 312 cn->cn_nameiop = nameiop; 313 cn->cn_flags = (LOCKPARENT | LOCKLEAF | ISLASTCN); 314 cn->cn_cred = cnp->cn_cred; 315 316 cn->cn_nameptr = pnbuf; 317 cn->cn_consume = cnp->cn_consume; 318 319 if (nameiop == DELETE) 320 cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART)); 321 else if (RENAME == nameiop) 322 cn->cn_flags |= (cnp->cn_flags & SAVESTART); 323 324 vref(dvp); 325 VOP_UNLOCK(dvp); 326 327 if ((error = relookup(dvp, vpp, cn))) { 328 PNBUF_PUT(pnbuf); 329 *pnbuf_ret = NULL; 330 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 331 } else { 332 *pnbuf_ret = pnbuf; 333 vrele(dvp); 334 } 335 336 return (error); 337 } 338 339 /* 340 * relookup for CREATE namei operation. 341 * 342 * dvp is unionfs vnode. dvp should be locked. 343 * 344 * If it called 'unionfs_copyfile' function by unionfs_link etc, 345 * VOP_LOOKUP information is broken. 346 * So it need relookup in order to create link etc. 347 */ 348 int 349 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp) 350 { 351 int error; 352 struct vnode *udvp; 353 struct vnode *vp; 354 struct componentname cn; 355 char *pnbuf; 356 357 udvp = UNIONFSVPTOUPPERVP(dvp); 358 vp = NULLVP; 359 360 error = unionfs_relookup(udvp, &vp, cnp, &cn, &pnbuf, 361 cnp->cn_nameptr, 362 strlen(cnp->cn_nameptr), CREATE); 363 if (error) 364 return (error); 365 366 if (vp != NULLVP) { 367 if (udvp == vp) 368 vrele(vp); 369 else 370 vput(vp); 371 372 error = EEXIST; 373 } 374 375 PNBUF_PUT(pnbuf); 376 377 if (!error) { 378 cnp->cn_flags = cn.cn_flags; 379 } 380 381 return (error); 382 } 383 384 /* 385 * relookup for DELETE namei operation. 386 * 387 * dvp is unionfs vnode. dvp should be locked. 388 */ 389 int 390 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp) 391 { 392 int error; 393 struct vnode *udvp; 394 struct vnode *vp; 395 struct componentname cn; 396 char *pnbuf; 397 398 udvp = UNIONFSVPTOUPPERVP(dvp); 399 vp = NULLVP; 400 401 error = unionfs_relookup(udvp, &vp, cnp, &cn, &pnbuf, cnp->cn_nameptr, 402 strlen(cnp->cn_nameptr), DELETE); 403 if (error) 404 return (error); 405 406 if (vp == NULLVP) 407 error = ENOENT; 408 else { 409 if (udvp == vp) 410 vrele(vp); 411 else 412 vput(vp); 413 } 414 415 PNBUF_PUT(pnbuf); 416 417 if (!error) { 418 cnp->cn_flags = cn.cn_flags; 419 } 420 421 return (error); 422 } 423 424 /* 425 * relookup for RENAME namei operation. 426 * 427 * dvp is unionfs vnode. dvp should be locked. 428 */ 429 int 430 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp) 431 { 432 int error; 433 struct vnode *udvp; 434 struct vnode *vp; 435 struct componentname cn; 436 char *pnbuf; 437 438 udvp = UNIONFSVPTOUPPERVP(dvp); 439 vp = NULLVP; 440 441 error = unionfs_relookup(udvp, &vp, cnp, &cn, &pnbuf, cnp->cn_nameptr, 442 strlen(cnp->cn_nameptr), RENAME); 443 if (error) 444 return (error); 445 446 if (vp != NULLVP) { 447 if (udvp == vp) 448 vrele(vp); 449 else 450 vput(vp); 451 } 452 453 PNBUF_PUT(pnbuf); 454 455 if (!error) { 456 cnp->cn_flags = cn.cn_flags; 457 } 458 459 return (error); 460 461 } 462 463 /* 464 * Update the unionfs_node. 465 * 466 * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the 467 * uvp's lock and lower's lock will be unlocked. 468 */ 469 static void 470 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp) 471 { 472 struct vnode *vp; 473 struct vnode *lvp; 474 475 vp = UNIONFSTOV(unp); 476 lvp = unp->un_lowervp; 477 478 /* 479 * lock update 480 */ 481 mutex_enter(&vp->v_interlock); 482 unp->un_uppervp = uvp; 483 KASSERT(VOP_ISLOCKED(lvp) == LK_EXCLUSIVE); 484 mutex_exit(&vp->v_interlock); 485 } 486 487 /* 488 * Create a new shadow dir. 489 * 490 * udvp should be locked on entry and will be locked on return. 491 * 492 * If no error returned, unp will be updated. 493 */ 494 int 495 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp, 496 struct unionfs_node *unp, struct componentname *cnp) 497 { 498 int error; 499 struct vnode *lvp; 500 struct vnode *uvp; 501 struct vattr va; 502 struct vattr lva; 503 struct componentname cn; 504 char *pnbuf; 505 506 if (unp->un_uppervp != NULLVP) 507 return (EEXIST); 508 509 lvp = unp->un_lowervp; 510 uvp = NULLVP; 511 512 memset(&cn, 0, sizeof(cn)); 513 514 if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) 515 goto unionfs_mkshadowdir_abort; 516 517 if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, &pnbuf, 518 cnp->cn_nameptr, cnp->cn_namelen, CREATE))) 519 goto unionfs_mkshadowdir_abort; 520 if (uvp != NULLVP) { 521 if (udvp == uvp) 522 vrele(uvp); 523 else 524 vput(uvp); 525 526 error = EEXIST; 527 goto unionfs_mkshadowdir_free_out; 528 } 529 530 unionfs_create_uppervattr_core(ump, &lva, &va); 531 532 error = VOP_MKDIR(udvp, &uvp, &cn, &va); 533 534 if (!error) { 535 unionfs_node_update(unp, uvp); 536 537 /* 538 * XXX The bug which cannot set uid/gid was corrected. 539 * Ignore errors. XXXNETBSD Why is this done as root? 540 */ 541 va.va_type = VNON; 542 VOP_SETATTR(uvp, &va, lwp0.l_cred); 543 } 544 545 unionfs_mkshadowdir_free_out: 546 PNBUF_PUT(pnbuf); 547 548 unionfs_mkshadowdir_abort: 549 550 return (error); 551 } 552 553 /* 554 * Create a new whiteout. 555 * 556 * dvp should be locked on entry and will be locked on return. 557 */ 558 int 559 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, const char *path) 560 { 561 int error; 562 struct vnode *wvp; 563 struct componentname cn; 564 char *pnbuf; 565 566 if (path == NULL) 567 path = cnp->cn_nameptr; 568 569 wvp = NULLVP; 570 if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, &pnbuf, 571 path, strlen(path), CREATE))) 572 return (error); 573 if (wvp != NULLVP) { 574 PNBUF_PUT(pnbuf); 575 if (dvp == wvp) 576 vrele(wvp); 577 else 578 vput(wvp); 579 580 return (EEXIST); 581 } 582 583 PNBUF_PUT(pnbuf); 584 585 return (error); 586 } 587 588 /* 589 * Create a new vnode for create a new shadow file. 590 * 591 * If an error is returned, *vpp will be invalid, otherwise it will hold a 592 * locked, referenced and opened vnode. 593 * 594 * unp is never updated. 595 */ 596 static int 597 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp, 598 struct unionfs_node *unp, struct vattr *uvap) 599 { 600 struct unionfs_mount *ump; 601 struct vnode *vp; 602 struct vnode *lvp; 603 kauth_cred_t cred; 604 struct vattr lva; 605 int fmode; 606 int error; 607 struct componentname cn; 608 char *pnbuf; 609 610 ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); 611 vp = NULLVP; 612 lvp = unp->un_lowervp; 613 cred = kauth_cred_get(); 614 fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); 615 error = 0; 616 617 if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0) 618 return (error); 619 unionfs_create_uppervattr_core(ump, &lva, uvap); 620 621 if (unp->un_path == NULL) 622 panic("unionfs: un_path is null"); 623 624 cn.cn_namelen = strlen(unp->un_path); 625 pnbuf = PNBUF_GET(); 626 memcpy(pnbuf, unp->un_path, cn.cn_namelen + 1); 627 cn.cn_nameiop = CREATE; 628 cn.cn_flags = (LOCKPARENT | LOCKLEAF | ISLASTCN); 629 cn.cn_cred = cred; 630 cn.cn_nameptr = pnbuf; 631 cn.cn_consume = 0; 632 633 vref(udvp); 634 if ((error = relookup(udvp, &vp, &cn)) != 0) 635 goto unionfs_vn_create_on_upper_free_out2; 636 vrele(udvp); 637 638 if (vp != NULLVP) { 639 if (vp == udvp) 640 vrele(vp); 641 else 642 vput(vp); 643 error = EEXIST; 644 goto unionfs_vn_create_on_upper_free_out1; 645 } 646 647 if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0) 648 goto unionfs_vn_create_on_upper_free_out1; 649 650 if ((error = VOP_OPEN(vp, fmode, cred)) != 0) { 651 vput(vp); 652 goto unionfs_vn_create_on_upper_free_out1; 653 } 654 vp->v_writecount++; 655 *vpp = vp; 656 657 unionfs_vn_create_on_upper_free_out1: 658 VOP_UNLOCK(udvp); 659 660 unionfs_vn_create_on_upper_free_out2: 661 PNBUF_PUT(pnbuf); 662 663 return (error); 664 } 665 666 /* 667 * Copy from lvp to uvp. 668 * 669 * lvp and uvp should be locked and opened on entry and will be locked and 670 * opened on return. 671 */ 672 static int 673 unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp, 674 kauth_cred_t cred) 675 { 676 int error; 677 off_t offset; 678 int count; 679 int bufoffset; 680 char *buf; 681 struct uio uio; 682 struct iovec iov; 683 684 error = 0; 685 memset(&uio, 0, sizeof(uio)); 686 UIO_SETUP_SYSSPACE(&uio); 687 uio.uio_offset = 0; 688 689 buf = kmem_alloc(MAXBSIZE, KM_SLEEP); 690 if (buf == NULL) 691 return ENOMEM; 692 693 while (error == 0) { 694 offset = uio.uio_offset; 695 696 uio.uio_iov = &iov; 697 uio.uio_iovcnt = 1; 698 iov.iov_base = buf; 699 iov.iov_len = MAXBSIZE; 700 uio.uio_resid = iov.iov_len; 701 uio.uio_rw = UIO_READ; 702 703 if ((error = VOP_READ(lvp, &uio, 0, cred)) != 0) 704 break; 705 if ((count = MAXBSIZE - uio.uio_resid) == 0) 706 break; 707 708 bufoffset = 0; 709 while (bufoffset < count) { 710 uio.uio_iov = &iov; 711 uio.uio_iovcnt = 1; 712 iov.iov_base = buf + bufoffset; 713 iov.iov_len = count - bufoffset; 714 uio.uio_offset = offset + bufoffset; 715 uio.uio_resid = iov.iov_len; 716 uio.uio_rw = UIO_WRITE; 717 718 if ((error = VOP_WRITE(uvp, &uio, 0, cred)) != 0) 719 break; 720 721 bufoffset += (count - bufoffset) - uio.uio_resid; 722 } 723 724 uio.uio_offset = offset + bufoffset; 725 } 726 727 kmem_free(buf, MAXBSIZE); 728 729 return (error); 730 } 731 732 /* 733 * Copy file from lower to upper. 734 * 735 * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to 736 * docopy. 737 * 738 * If no error returned, unp will be updated. 739 */ 740 int 741 unionfs_copyfile(struct unionfs_node *unp, int docopy, kauth_cred_t cred) 742 { 743 int error; 744 struct vnode *udvp; 745 struct vnode *lvp; 746 struct vnode *uvp; 747 struct vattr uva; 748 749 lvp = unp->un_lowervp; 750 uvp = NULLVP; 751 752 if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY)) 753 return (EROFS); 754 if (unp->un_dvp == NULLVP) 755 return (EINVAL); 756 if (unp->un_uppervp != NULLVP) 757 return (EEXIST); 758 udvp = VTOUNIONFS(unp->un_dvp)->un_uppervp; 759 if (udvp == NULLVP) 760 return (EROFS); 761 if ((udvp->v_mount->mnt_flag & MNT_RDONLY)) 762 return (EROFS); 763 764 error = VOP_ACCESS(lvp, VREAD, cred); 765 if (error != 0) 766 return (error); 767 768 error = unionfs_vn_create_on_upper(&uvp, udvp, unp, &uva); 769 if (error != 0) 770 return (error); 771 772 if (docopy != 0) { 773 error = VOP_OPEN(lvp, FREAD, cred); 774 if (error == 0) { 775 error = unionfs_copyfile_core(lvp, uvp, cred); 776 VOP_CLOSE(lvp, FREAD, cred); 777 } 778 } 779 VOP_CLOSE(uvp, FWRITE, cred); 780 uvp->v_writecount--; 781 782 if (error == 0) { 783 /* Reset the attributes. Ignore errors. */ 784 uva.va_type = VNON; 785 VOP_SETATTR(uvp, &uva, cred); 786 } 787 788 unionfs_node_update(unp, uvp); 789 790 return (error); 791 } 792 793 /* 794 * It checks whether vp can rmdir. (check empty) 795 * 796 * vp is unionfs vnode. 797 * vp should be locked. 798 */ 799 int 800 unionfs_check_rmdir(struct vnode *vp, kauth_cred_t cred) 801 { 802 int error; 803 int eofflag; 804 int lookuperr; 805 struct vnode *uvp; 806 struct vnode *lvp; 807 struct vnode *tvp; 808 struct vattr va; 809 struct componentname cn; 810 /* 811 * The size of buf needs to be larger than DIRBLKSIZ. 812 */ 813 char buf[256 * 6]; 814 struct dirent *dp; 815 struct dirent *edp; 816 struct uio uio; 817 struct iovec iov; 818 819 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 820 821 eofflag = 0; 822 uvp = UNIONFSVPTOUPPERVP(vp); 823 lvp = UNIONFSVPTOLOWERVP(vp); 824 825 /* check opaque */ 826 if ((error = VOP_GETATTR(uvp, &va, cred)) != 0) 827 return (error); 828 if (va.va_flags & OPAQUE) 829 return (0); 830 831 /* open vnode */ 832 if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred)) != 0) 833 return (error); 834 if ((error = VOP_OPEN(vp, FREAD, cred)) != 0) 835 return (error); 836 837 UIO_SETUP_SYSSPACE(&uio); 838 uio.uio_rw = UIO_READ; 839 uio.uio_offset = 0; 840 841 while (!error && !eofflag) { 842 iov.iov_base = buf; 843 iov.iov_len = sizeof(buf); 844 uio.uio_iov = &iov; 845 uio.uio_iovcnt = 1; 846 uio.uio_resid = iov.iov_len; 847 848 error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL); 849 if (error) 850 break; 851 852 edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid]; 853 for (dp = (struct dirent*)buf; !error && dp < edp; 854 dp = (struct dirent*)((char *)dp + dp->d_reclen)) { 855 if (dp->d_type == DT_WHT || 856 (dp->d_namlen == 1 && dp->d_name[0] == '.') || 857 (dp->d_namlen == 2 && !memcmp(dp->d_name, "..", 2))) 858 continue; 859 860 cn.cn_namelen = dp->d_namlen; 861 cn.cn_nameptr = dp->d_name; 862 cn.cn_nameiop = LOOKUP; 863 cn.cn_flags = (LOCKPARENT | LOCKLEAF | RDONLY | ISLASTCN); 864 cn.cn_cred = cred; 865 cn.cn_consume = 0; 866 867 /* 868 * check entry in lower. 869 * Sometimes, readdir function returns 870 * wrong entry. 871 */ 872 lookuperr = VOP_LOOKUP(lvp, &tvp, &cn); 873 874 if (!lookuperr) 875 vput(tvp); 876 else 877 continue; /* skip entry */ 878 879 /* 880 * check entry 881 * If it has no exist/whiteout entry in upper, 882 * directory is not empty. 883 */ 884 cn.cn_flags = (LOCKPARENT | LOCKLEAF | RDONLY | ISLASTCN); 885 lookuperr = VOP_LOOKUP(uvp, &tvp, &cn); 886 887 if (!lookuperr) 888 vput(tvp); 889 890 /* ignore exist or whiteout entry */ 891 if (!lookuperr || 892 (lookuperr == ENOENT && (cn.cn_flags & ISWHITEOUT))) 893 continue; 894 895 error = ENOTEMPTY; 896 } 897 } 898 899 /* close vnode */ 900 VOP_CLOSE(vp, FREAD, cred); 901 902 return (error); 903 } 904 905 #ifdef DIAGNOSTIC 906 907 struct vnode * 908 unionfs_checkuppervp(struct vnode *vp, const char *fil, int lno) 909 { 910 struct unionfs_node *unp; 911 912 unp = VTOUNIONFS(vp); 913 914 #ifdef notyet 915 if (vp->v_op != unionfs_vnodeop_p) { 916 printf("unionfs_checkuppervp: on non-unionfs-node.\n"); 917 #ifdef KDB 918 kdb_enter(KDB_WHY_UNIONFS, 919 "unionfs_checkuppervp: on non-unionfs-node.\n"); 920 #endif 921 panic("unionfs_checkuppervp"); 922 }; 923 #endif 924 return (unp->un_uppervp); 925 } 926 927 struct vnode * 928 unionfs_checklowervp(struct vnode *vp, const char *fil, int lno) 929 { 930 struct unionfs_node *unp; 931 932 unp = VTOUNIONFS(vp); 933 934 #ifdef notyet 935 if (vp->v_op != unionfs_vnodeop_p) { 936 printf("unionfs_checklowervp: on non-unionfs-node.\n"); 937 #ifdef KDB 938 kdb_enter(KDB_WHY_UNIONFS, 939 "unionfs_checklowervp: on non-unionfs-node.\n"); 940 #endif 941 panic("unionfs_checklowervp"); 942 }; 943 #endif 944 return (unp->un_lowervp); 945 } 946 #endif 947