1 /* $OpenBSD: tmpfs_vnops.c,v 1.52 2022/06/26 05:20:42 visa Exp $ */ 2 /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */ 3 4 /* 5 * Copyright (c) 2005, 2006, 2007, 2012 The NetBSD Foundation, Inc. 6 * Copyright (c) 2013 Pedro Martelletto 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code 11 * 2005 program, and by Taylor R Campbell. 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 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * tmpfs vnode interface. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/fcntl.h> 42 #include <sys/event.h> 43 #include <sys/namei.h> 44 #include <sys/stat.h> 45 #include <sys/uio.h> 46 #include <sys/unistd.h> 47 #include <sys/vnode.h> 48 #include <sys/lockf.h> 49 #include <sys/file.h> 50 51 #include <miscfs/fifofs/fifo.h> 52 #include <tmpfs/tmpfs_vnops.h> 53 #include <tmpfs/tmpfs.h> 54 55 int tmpfs_kqfilter(void *v); 56 57 /* 58 * vnode operations vector used for files stored in a tmpfs file system. 59 */ 60 const struct vops tmpfs_vops = { 61 .vop_lookup = tmpfs_lookup, 62 .vop_create = tmpfs_create, 63 .vop_mknod = tmpfs_mknod, 64 .vop_open = tmpfs_open, 65 .vop_close = tmpfs_close, 66 .vop_access = tmpfs_access, 67 .vop_getattr = tmpfs_getattr, 68 .vop_setattr = tmpfs_setattr, 69 .vop_read = tmpfs_read, 70 .vop_write = tmpfs_write, 71 .vop_ioctl = tmpfs_ioctl, 72 .vop_kqfilter = tmpfs_kqfilter, 73 .vop_revoke = vop_generic_revoke, 74 .vop_fsync = tmpfs_fsync, 75 .vop_remove = tmpfs_remove, 76 .vop_link = tmpfs_link, 77 .vop_rename = tmpfs_rename, 78 .vop_mkdir = tmpfs_mkdir, 79 .vop_rmdir = tmpfs_rmdir, 80 .vop_symlink = tmpfs_symlink, 81 .vop_readdir = tmpfs_readdir, 82 .vop_readlink = tmpfs_readlink, 83 .vop_abortop = vop_generic_abortop, 84 .vop_inactive = tmpfs_inactive, 85 .vop_reclaim = tmpfs_reclaim, 86 .vop_lock = tmpfs_lock, 87 .vop_unlock = tmpfs_unlock, 88 .vop_bmap = vop_generic_bmap, 89 .vop_strategy = tmpfs_strategy, 90 .vop_print = tmpfs_print, 91 .vop_islocked = tmpfs_islocked, 92 .vop_pathconf = tmpfs_pathconf, 93 .vop_advlock = tmpfs_advlock, 94 .vop_bwrite = tmpfs_bwrite, 95 }; 96 97 /* 98 * tmpfs_lookup: path name traversal routine. 99 * 100 * Arguments: dvp (directory being searched), vpp (result), 101 * cnp (component name - path). 102 * 103 * => Caller holds a reference and lock on dvp. 104 * => We return looked-up vnode (vpp) locked, with a reference held. 105 */ 106 int 107 tmpfs_lookup(void *v) 108 { 109 struct vop_lookup_args /* { 110 struct vnode *a_dvp; 111 struct vnode **a_vpp; 112 struct componentname *a_cnp; 113 } */ *ap = v; 114 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp; 115 struct componentname *cnp = ap->a_cnp; 116 struct ucred *cred = cnp->cn_cred; 117 const int lastcn = (cnp->cn_flags & ISLASTCN) != 0; 118 const int lockparent = (cnp->cn_flags & LOCKPARENT) != 0; 119 tmpfs_node_t *dnode, *tnode; 120 tmpfs_dirent_t *de; 121 int cachefound; 122 int error; 123 124 KASSERT(VOP_ISLOCKED(dvp)); 125 126 dnode = VP_TO_TMPFS_DIR(dvp); 127 cnp->cn_flags &= ~PDIRUNLOCK; 128 *vpp = NULL; 129 130 /* Check accessibility of directory. */ 131 error = VOP_ACCESS(dvp, VEXEC, cred, curproc); 132 if (error) { 133 goto out; 134 } 135 136 /* 137 * If requesting the last path component on a read-only file system 138 * with a write operation, deny it. 139 */ 140 if (lastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) != 0 && 141 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 142 error = EROFS; 143 goto out; 144 } 145 146 /* 147 * Avoid doing a linear scan of the directory if the requested 148 * directory/name couple is already in the cache. 149 */ 150 cachefound = cache_lookup(dvp, vpp, cnp); 151 if (cachefound == ENOENT /* && *vpp == NULLVP */) 152 return ENOENT; /* Negative cache hit. */ 153 else if (cachefound != -1) 154 return 0; /* Found in cache. */ 155 156 if (cnp->cn_flags & ISDOTDOT) { 157 tmpfs_node_t *pnode; 158 159 /* 160 * Lookup of ".." case. 161 */ 162 if (lastcn) { 163 if (cnp->cn_nameiop == RENAME) { 164 error = EINVAL; 165 goto out; 166 } 167 if (cnp->cn_nameiop == DELETE) { 168 /* Keep the name for tmpfs_rmdir(). */ 169 cnp->cn_flags |= SAVENAME; 170 } 171 } 172 KASSERT(dnode->tn_type == VDIR); 173 pnode = dnode->tn_spec.tn_dir.tn_parent; 174 if (pnode == NULL) { 175 error = ENOENT; 176 goto out; 177 } 178 179 /* 180 * Lock the parent tn_nlock before releasing the vnode lock, 181 * and thus prevents parent from disappearing. 182 */ 183 rw_enter_write(&pnode->tn_nlock); 184 VOP_UNLOCK(dvp); 185 186 /* 187 * Get a vnode of the '..' entry and re-acquire the lock. 188 * Release the tn_nlock. 189 */ 190 error = tmpfs_vnode_get(dvp->v_mount, pnode, vpp); 191 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 192 goto out; 193 194 } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 195 /* 196 * Lookup of "." case. 197 */ 198 if (lastcn && cnp->cn_nameiop == RENAME) { 199 error = EISDIR; 200 goto out; 201 } 202 vref(dvp); 203 *vpp = dvp; 204 error = 0; 205 goto done; 206 } 207 208 /* 209 * Other lookup cases: perform directory scan. 210 */ 211 de = tmpfs_dir_lookup(dnode, cnp); 212 if (de == NULL) { 213 /* 214 * The entry was not found in the directory. This is valid 215 * if we are creating or renaming an entry and are working 216 * on the last component of the path name. 217 */ 218 if (lastcn && (cnp->cn_nameiop == CREATE || 219 cnp->cn_nameiop == RENAME)) { 220 error = VOP_ACCESS(dvp, VWRITE, cred, curproc); 221 if (error) { 222 goto out; 223 } 224 /* 225 * We are creating an entry in the file system, so 226 * save its name for further use by tmpfs_create(). 227 */ 228 cnp->cn_flags |= SAVENAME; 229 error = EJUSTRETURN; 230 } else { 231 error = ENOENT; 232 } 233 goto done; 234 } 235 236 tnode = de->td_node; 237 238 /* 239 * If it is not the last path component and found a non-directory 240 * or non-link entry (which may itself be pointing to a directory), 241 * raise an error. 242 */ 243 if (!lastcn && tnode->tn_type != VDIR && tnode->tn_type != VLNK) { 244 error = ENOTDIR; 245 goto out; 246 } 247 248 /* Check the permissions. */ 249 if (lastcn && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 250 error = VOP_ACCESS(dvp, VWRITE, cred, curproc); 251 if (error) 252 goto out; 253 254 /* 255 * If not root and directory is sticky, check for permission 256 * on directory or on file. This implements append-only 257 * directories. 258 */ 259 if ((dnode->tn_mode & S_ISTXT) != 0) { 260 if (cred->cr_uid != 0 && 261 cred->cr_uid != dnode->tn_uid && 262 cred->cr_uid != tnode->tn_uid) { 263 error = EPERM; 264 goto out; 265 } 266 } 267 268 /* 269 * XXX pedro: We might need cn_nameptr later in tmpfs_remove() 270 * or tmpfs_rmdir() for a tmpfs_dir_lookup(). We should really 271 * get rid of SAVENAME at some point. 272 */ 273 if (cnp->cn_nameiop == DELETE) 274 cnp->cn_flags |= SAVENAME; 275 } 276 277 /* Get a vnode for the matching entry. */ 278 rw_enter_write(&tnode->tn_nlock); 279 error = tmpfs_vnode_get(dvp->v_mount, tnode, vpp); 280 done: 281 /* 282 * Cache the result, unless request was for creation (as it does 283 * not improve the performance). 284 */ 285 if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) { 286 cache_enter(dvp, *vpp, cnp); 287 } 288 out: 289 /* 290 * If (1) we succeeded, (2) found a distinct vnode != .. to return and (3) 291 * were either explicitly told to keep the parent locked or are in the 292 * middle of a lookup, unlock the parent vnode. 293 */ 294 if ((error == 0 || error == EJUSTRETURN) && /* (1) */ 295 (*vpp != dvp || (cnp->cn_flags & ISDOTDOT)) && /* (2) */ 296 (!lockparent || !lastcn)) { /* (3) */ 297 VOP_UNLOCK(dvp); 298 cnp->cn_flags |= PDIRUNLOCK; 299 } else 300 KASSERT(VOP_ISLOCKED(dvp)); 301 302 KASSERT((*vpp && VOP_ISLOCKED(*vpp)) || error); 303 304 return error; 305 } 306 307 int 308 tmpfs_create(void *v) 309 { 310 struct vop_create_args /* { 311 struct vnode *a_dvp; 312 struct vnode **a_vpp; 313 struct componentname *a_cnp; 314 struct vattr *a_vap; 315 } */ *ap = v; 316 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp; 317 struct componentname *cnp = ap->a_cnp; 318 struct vattr *vap = ap->a_vap; 319 320 KASSERT(VOP_ISLOCKED(dvp)); 321 KASSERT(cnp->cn_flags & HASBUF); 322 KASSERT(vap->va_type == VREG || vap->va_type == VSOCK); 323 return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 324 } 325 326 int 327 tmpfs_mknod(void *v) 328 { 329 struct vop_mknod_args /* { 330 struct vnode *a_dvp; 331 struct vnode **a_vpp; 332 struct componentname *a_cnp; 333 struct vattr *a_vap; 334 } */ *ap = v; 335 struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp; 336 struct componentname *cnp = ap->a_cnp; 337 struct vattr *vap = ap->a_vap; 338 enum vtype vt = vap->va_type; 339 int error; 340 341 if (vt != VBLK && vt != VCHR && vt != VFIFO) 342 return EINVAL; 343 344 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 345 346 if (error == 0) 347 vput(*vpp); 348 349 return error; 350 } 351 352 int 353 tmpfs_open(void *v) 354 { 355 struct vop_open_args /* { 356 struct vnode *a_vp; 357 int a_mode; 358 kauth_cred_t a_cred; 359 } */ *ap = v; 360 struct vnode *vp = ap->a_vp; 361 mode_t mode = ap->a_mode; 362 tmpfs_node_t *node; 363 364 KASSERT(VOP_ISLOCKED(vp)); 365 366 node = VP_TO_TMPFS_NODE(vp); 367 if (node->tn_links < 1) { 368 /* 369 * The file is still active, but all its names have been 370 * removed (e.g. by a "rmdir $(pwd)"). It cannot be opened 371 * any more, as it is about to be destroyed. 372 */ 373 return ENOENT; 374 } 375 376 /* If the file is marked append-only, deny write requests. */ 377 if ((node->tn_flags & APPEND) != 0 && 378 (mode & (FWRITE | O_APPEND)) == FWRITE) { 379 return EPERM; 380 } 381 return 0; 382 } 383 384 int 385 tmpfs_close(void *v) 386 { 387 #ifdef DIAGNOSTIC 388 struct vop_close_args /* { 389 struct vnode *a_vp; 390 int a_fflag; 391 kauth_cred_t a_cred; 392 } */ *ap = v; 393 struct vnode *vp = ap->a_vp; 394 395 KASSERT(VOP_ISLOCKED(vp)); 396 #endif 397 return 0; 398 } 399 400 int 401 tmpfs_access(void *v) 402 { 403 struct vop_access_args /* { 404 struct vnode *a_vp; 405 int a_mode; 406 kauth_cred_t a_cred; 407 } */ *ap = v; 408 struct vnode *vp = ap->a_vp; 409 mode_t mode = ap->a_mode; 410 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 411 const int writing = (mode & VWRITE) != 0; 412 413 KASSERT(VOP_ISLOCKED(vp)); 414 415 /* Possible? */ 416 switch (vp->v_type) { 417 case VDIR: 418 case VLNK: 419 case VREG: 420 if (writing && (vp->v_mount->mnt_flag & MNT_RDONLY) != 0) { 421 return EROFS; 422 } 423 break; 424 case VBLK: 425 case VCHR: 426 case VSOCK: 427 case VFIFO: 428 break; 429 default: 430 return EINVAL; 431 } 432 if (writing && (node->tn_flags & IMMUTABLE) != 0) { 433 return EPERM; 434 } 435 436 return (vaccess(vp->v_type, node->tn_mode, node->tn_uid, node->tn_gid, 437 mode, ap->a_cred)); 438 } 439 440 int 441 tmpfs_getattr(void *v) 442 { 443 struct vop_getattr_args /* { 444 struct vnode *a_vp; 445 struct vattr *a_vap; 446 kauth_cred_t a_cred; 447 } */ *ap = v; 448 struct vnode *vp = ap->a_vp; 449 struct vattr *vap = ap->a_vap; 450 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 451 452 vattr_null(vap); 453 454 vap->va_type = vp->v_type; 455 vap->va_mode = node->tn_mode; 456 vap->va_nlink = node->tn_links; 457 vap->va_uid = node->tn_uid; 458 vap->va_gid = node->tn_gid; 459 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 460 vap->va_fileid = node->tn_id; 461 vap->va_size = node->tn_size; 462 vap->va_blocksize = PAGE_SIZE; 463 vap->va_atime = node->tn_atime; 464 vap->va_mtime = node->tn_mtime; 465 vap->va_ctime = node->tn_ctime; 466 /* vap->va_birthtime = node->tn_birthtime; */ 467 vap->va_gen = TMPFS_NODE_GEN(node); 468 vap->va_flags = node->tn_flags; 469 vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? 470 node->tn_spec.tn_dev.tn_rdev : VNOVAL; 471 vap->va_bytes = round_page(node->tn_size); 472 vap->va_filerev = VNOVAL; 473 vap->va_vaflags = 0; 474 vap->va_spare = VNOVAL; /* XXX */ 475 476 return 0; 477 } 478 479 #define GOODTIME(tv) ((tv)->tv_nsec != VNOVAL) 480 /* XXX Should this operation be atomic? I think it should, but code in 481 * XXX other places (e.g., ufs) doesn't seem to be... */ 482 int 483 tmpfs_setattr(void *v) 484 { 485 struct vop_setattr_args /* { 486 struct vnode *a_vp; 487 struct vattr *a_vap; 488 kauth_cred_t a_cred; 489 } */ *ap = v; 490 struct vnode *vp = ap->a_vp; 491 struct vattr *vap = ap->a_vap; 492 struct ucred *cred = ap->a_cred; 493 struct proc *p = curproc; 494 int error = 0; 495 496 KASSERT(VOP_ISLOCKED(vp)); 497 498 /* Abort if any unsettable attribute is given. */ 499 if (vap->va_type != VNON || vap->va_nlink != VNOVAL || 500 vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL || 501 vap->va_blocksize != VNOVAL || GOODTIME(&vap->va_ctime) || 502 vap->va_gen != VNOVAL || vap->va_rdev != VNOVAL || 503 vap->va_bytes != VNOVAL) { 504 return EINVAL; 505 } 506 if (error == 0 && (vap->va_flags != VNOVAL)) 507 error = tmpfs_chflags(vp, vap->va_flags, cred, p); 508 509 if (error == 0 && (vap->va_size != VNOVAL)) 510 error = tmpfs_chsize(vp, vap->va_size, cred, p); 511 512 if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL)) 513 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, p); 514 515 if (error == 0 && (vap->va_mode != VNOVAL)) 516 error = tmpfs_chmod(vp, vap->va_mode, cred, p); 517 518 if (error == 0 && ((vap->va_vaflags & VA_UTIMES_CHANGE) 519 || GOODTIME(&vap->va_atime) 520 || GOODTIME(&vap->va_mtime))) 521 error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime, 522 vap->va_vaflags, cred, p); 523 524 return error; 525 } 526 527 int 528 tmpfs_read(void *v) 529 { 530 struct vop_read_args /* { 531 struct vnode *a_vp; 532 struct uio *a_uio; 533 int a_ioflag; 534 struct ucred *a_cred; 535 } */ *ap = v; 536 struct vnode *vp = ap->a_vp; 537 struct uio *uio = ap->a_uio; 538 /* const int ioflag = ap->a_ioflag; */ 539 tmpfs_node_t *node; 540 int error; 541 542 KASSERT(VOP_ISLOCKED(vp)); 543 544 if (vp->v_type != VREG) { 545 return EISDIR; 546 } 547 if (uio->uio_offset < 0) { 548 return EINVAL; 549 } 550 if (uio->uio_resid == 0) 551 return 0; 552 553 node = VP_TO_TMPFS_NODE(vp); 554 error = 0; 555 556 while (error == 0 && uio->uio_resid > 0) { 557 vsize_t len; 558 559 if (node->tn_size <= uio->uio_offset) { 560 break; 561 } 562 len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid); 563 if (len == 0) { 564 break; 565 } 566 error = tmpfs_uiomove(node, uio, len); 567 } 568 569 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) 570 tmpfs_update(node, TMPFS_NODE_ACCESSED); 571 572 return error; 573 } 574 575 int 576 tmpfs_write(void *v) 577 { 578 struct vop_write_args /* { 579 struct vnode *a_vp; 580 struct uio *a_uio; 581 int a_ioflag; 582 kauth_cred_t a_cred; 583 } */ *ap = v; 584 struct vnode *vp = ap->a_vp; 585 struct uio *uio = ap->a_uio; 586 const int ioflag = ap->a_ioflag; 587 tmpfs_node_t *node; 588 off_t oldsize; 589 ssize_t overrun; 590 int extended; 591 int error; 592 593 KASSERT(VOP_ISLOCKED(vp)); 594 595 node = VP_TO_TMPFS_NODE(vp); 596 oldsize = node->tn_size; 597 598 if (vp->v_type != VREG) 599 return (EINVAL); 600 601 if (uio->uio_resid == 0) 602 return (0); 603 604 if (ioflag & IO_APPEND) { 605 uio->uio_offset = node->tn_size; 606 } 607 608 if (uio->uio_offset < 0 || 609 (u_int64_t)uio->uio_offset + uio->uio_resid > LLONG_MAX) 610 return (EFBIG); 611 612 /* do the filesize rlimit check */ 613 if ((error = vn_fsizechk(vp, uio, ioflag, &overrun))) 614 return (error); 615 616 extended = uio->uio_offset + uio->uio_resid > node->tn_size; 617 if (extended) { 618 error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid); 619 if (error) 620 goto out; 621 } 622 623 error = 0; 624 while (error == 0 && uio->uio_resid > 0) { 625 vsize_t len; 626 uvm_vnp_uncache(vp); 627 len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid); 628 if (len == 0) { 629 break; 630 } 631 error = tmpfs_uiomove(node, uio, len); 632 } 633 if (error) { 634 (void)tmpfs_reg_resize(vp, oldsize); 635 } 636 637 tmpfs_update(node, TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED); 638 if (extended) 639 VN_KNOTE(vp, NOTE_WRITE | NOTE_EXTEND); 640 else 641 VN_KNOTE(vp, NOTE_WRITE); 642 out: 643 if (error) { 644 KASSERT(oldsize == node->tn_size); 645 } else { 646 KASSERT(uio->uio_resid == 0); 647 648 /* correct the result for writes clamped by vn_fsizechk() */ 649 uio->uio_resid += overrun; 650 651 } 652 return error; 653 } 654 655 int 656 tmpfs_fsync(void *v) 657 { 658 #ifdef DIAGNOSTIC 659 struct vop_fsync_args /* { 660 struct vnode *a_vp; 661 struct ucred *a_cred; 662 int a_flags; 663 off_t a_offlo; 664 off_t a_offhi; 665 struct lwp *a_l; 666 } */ *ap = v; 667 struct vnode *vp = ap->a_vp; 668 669 /* Nothing to do. Just update. */ 670 KASSERT(VOP_ISLOCKED(vp)); 671 #endif 672 return 0; 673 } 674 675 /* 676 * tmpfs_remove: unlink a file. 677 * 678 * => Both directory (dvp) and file (vp) are locked. 679 * => We unlock and drop the reference on both. 680 */ 681 int 682 tmpfs_remove(void *v) 683 { 684 struct vop_remove_args /* { 685 struct vnode *a_dvp; 686 struct vnode *a_vp; 687 struct componentname *a_cnp; 688 } */ *ap = v; 689 struct vnode *dvp = ap->a_dvp, *vp = ap->a_vp; 690 struct componentname *cnp = ap->a_cnp; 691 tmpfs_node_t *dnode, *node; 692 tmpfs_dirent_t *de; 693 int error; 694 695 KASSERT(VOP_ISLOCKED(dvp)); 696 KASSERT(VOP_ISLOCKED(vp)); 697 KASSERT(cnp->cn_flags & HASBUF); 698 699 if (vp->v_type == VDIR) { 700 error = EPERM; 701 goto out; 702 } 703 704 dnode = VP_TO_TMPFS_NODE(dvp); 705 node = VP_TO_TMPFS_NODE(vp); 706 707 /* Files marked as immutable or append-only cannot be deleted. */ 708 if (node->tn_flags & (IMMUTABLE | APPEND)) { 709 error = EPERM; 710 goto out; 711 } 712 713 /* 714 * Likewise, files residing on directories marked as append-only cannot 715 * be deleted. 716 */ 717 if (dnode->tn_flags & APPEND) { 718 error = EPERM; 719 goto out; 720 } 721 722 /* Lookup the directory entry (check the cached hint first). */ 723 de = tmpfs_dir_cached(node); 724 if (de == NULL) { 725 de = tmpfs_dir_lookup(dnode, cnp); 726 } 727 728 KASSERT(de && de->td_node == node); 729 730 /* 731 * Remove the entry from the directory (drops the link count) and 732 * destroy it. 733 * Note: the inode referred by it will not be destroyed 734 * until the vnode is reclaimed/recycled. 735 */ 736 tmpfs_dir_detach(dnode, de); 737 tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de); 738 if (node->tn_links > 0) { 739 /* We removed a hard link. */ 740 tmpfs_update(node, TMPFS_NODE_CHANGED); 741 } 742 error = 0; 743 out: 744 pool_put(&namei_pool, cnp->cn_pnbuf); 745 /* Drop the references and unlock the vnodes. */ 746 vput(vp); 747 if (dvp == vp) { 748 vrele(dvp); 749 } else { 750 vput(dvp); 751 } 752 return error; 753 } 754 755 /* 756 * tmpfs_link: create a hard link. 757 */ 758 int 759 tmpfs_link(void *v) 760 { 761 struct vop_link_args /* { 762 struct vnode *a_dvp; 763 struct vnode *a_vp; 764 struct componentname *a_cnp; 765 } */ *ap = v; 766 struct vnode *dvp = ap->a_dvp; 767 struct vnode *vp = ap->a_vp; 768 struct componentname *cnp = ap->a_cnp; 769 tmpfs_node_t *dnode, *node; 770 tmpfs_dirent_t *de; 771 int error; 772 773 KASSERT(VOP_ISLOCKED(dvp)); 774 775 if (vp->v_type == VDIR) { 776 VOP_ABORTOP(dvp, cnp); 777 vput(dvp); 778 return EPERM; 779 } 780 781 KASSERT(dvp != vp); 782 783 if (dvp->v_mount != vp->v_mount) { 784 VOP_ABORTOP(dvp, cnp); 785 vput(dvp); 786 return EXDEV; 787 } 788 789 dnode = VP_TO_TMPFS_DIR(dvp); 790 node = VP_TO_TMPFS_NODE(vp); 791 792 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 793 794 /* Check for maximum number of links limit. */ 795 if (node->tn_links == LINK_MAX) { 796 error = EMLINK; 797 goto out; 798 } 799 KASSERT(node->tn_links < LINK_MAX); 800 801 /* We cannot create links of files marked immutable or append-only. */ 802 if (node->tn_flags & (IMMUTABLE | APPEND)) { 803 error = EPERM; 804 goto out; 805 } 806 807 if (TMPFS_DIRSEQ_FULL(dnode)) { 808 error = ENOSPC; 809 goto out; 810 } 811 812 /* Allocate a new directory entry to represent the inode. */ 813 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), 814 cnp->cn_nameptr, cnp->cn_namelen, &de); 815 if (error) { 816 goto out; 817 } 818 819 /* 820 * Insert the entry into the directory. 821 * It will increase the inode link count. 822 */ 823 tmpfs_dir_attach(dnode, de, node); 824 825 /* Update the timestamps and trigger the event. */ 826 if (node->tn_vnode) { 827 VN_KNOTE(node->tn_vnode, NOTE_LINK); 828 } 829 tmpfs_update(node, TMPFS_NODE_CHANGED); 830 error = 0; 831 out: 832 pool_put(&namei_pool, cnp->cn_pnbuf); 833 VOP_UNLOCK(vp); 834 vput(dvp); 835 return error; 836 } 837 838 int 839 tmpfs_mkdir(void *v) 840 { 841 struct vop_mkdir_args /* { 842 struct vnode *a_dvp; 843 struct vnode **a_vpp; 844 struct componentname *a_cnp; 845 struct vattr *a_vap; 846 } */ *ap = v; 847 struct vnode *dvp = ap->a_dvp; 848 struct vnode **vpp = ap->a_vpp; 849 struct componentname *cnp = ap->a_cnp; 850 struct vattr *vap = ap->a_vap; 851 int error; 852 853 KASSERT(vap->va_type == VDIR); 854 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 855 vput(dvp); 856 return error; 857 } 858 859 int 860 tmpfs_rmdir(void *v) 861 { 862 struct vop_rmdir_args /* { 863 struct vnode *a_dvp; 864 struct vnode *a_vp; 865 struct componentname *a_cnp; 866 } */ *ap = v; 867 struct vnode *dvp = ap->a_dvp; 868 struct vnode *vp = ap->a_vp; 869 struct componentname *cnp = ap->a_cnp; 870 tmpfs_mount_t *tmp = VFS_TO_TMPFS(dvp->v_mount); 871 tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp); 872 tmpfs_node_t *node = VP_TO_TMPFS_DIR(vp); 873 tmpfs_dirent_t *de; 874 int error = 0; 875 876 KASSERT(VOP_ISLOCKED(dvp)); 877 KASSERT(VOP_ISLOCKED(vp)); 878 KASSERT(cnp->cn_flags & HASBUF); 879 880 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' && 881 cnp->cn_nameptr[1] == '.') { 882 error = ENOTEMPTY; 883 goto out; 884 } 885 886 KASSERT(node->tn_spec.tn_dir.tn_parent == dnode); 887 888 /* 889 * Directories with more than two entries ('.' and '..') cannot be 890 * removed. 891 */ 892 if (node->tn_size > 0) { 893 KASSERT(error == 0); 894 TAILQ_FOREACH(de, &node->tn_spec.tn_dir.tn_dir, td_entries) { 895 error = ENOTEMPTY; 896 break; 897 } 898 if (error) 899 goto out; 900 } 901 902 /* Lookup the directory entry (check the cached hint first). */ 903 de = tmpfs_dir_cached(node); 904 if (de == NULL) 905 de = tmpfs_dir_lookup(dnode, cnp); 906 907 KASSERT(de && de->td_node == node); 908 909 /* Check flags to see if we are allowed to remove the directory. */ 910 if (dnode->tn_flags & APPEND || node->tn_flags & (IMMUTABLE | APPEND)) { 911 error = EPERM; 912 goto out; 913 } 914 915 /* Decrement the link count for the virtual '.' entry. */ 916 node->tn_links--; 917 tmpfs_update(node, TMPFS_NODE_STATUSALL); 918 919 /* Detach the directory entry from the directory. */ 920 tmpfs_dir_detach(dnode, de); 921 922 /* Purge the cache for parent. */ 923 cache_purge(dvp); 924 925 /* 926 * Destroy the directory entry. 927 * Note: the inode referred by it will not be destroyed 928 * until the vnode is reclaimed. 929 */ 930 tmpfs_free_dirent(tmp, de); 931 KASSERT(TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir) == NULL); 932 933 KASSERT(node->tn_links == 0); 934 out: 935 pool_put(&namei_pool, cnp->cn_pnbuf); 936 /* Release the nodes. */ 937 vput(dvp); 938 vput(vp); 939 return error; 940 } 941 942 int 943 tmpfs_symlink(void *v) 944 { 945 struct vop_symlink_args /* { 946 struct vnode *a_dvp; 947 struct vnode **a_vpp; 948 struct componentname *a_cnp; 949 struct vattr *a_vap; 950 char *a_target; 951 } */ *ap = v; 952 struct vnode *dvp = ap->a_dvp; 953 struct vnode **vpp = ap->a_vpp; 954 struct componentname *cnp = ap->a_cnp; 955 struct vattr *vap = ap->a_vap; 956 char *target = ap->a_target; 957 int error; 958 959 KASSERT(vap->va_type == 0); 960 vap->va_type = VLNK; 961 962 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, target); 963 vput(dvp); 964 if (error == 0) 965 vput(*vpp); 966 967 return error; 968 } 969 970 int 971 tmpfs_readdir(void *v) 972 { 973 struct vop_readdir_args /* { 974 struct vnode *a_vp; 975 struct uio *a_uio; 976 kauth_cred_t a_cred; 977 int *a_eofflag; 978 } */ *ap = v; 979 struct vnode *vp = ap->a_vp; 980 struct uio *uio = ap->a_uio; 981 int *eofflag = ap->a_eofflag; 982 tmpfs_node_t *node; 983 int error; 984 985 KASSERT(VOP_ISLOCKED(vp)); 986 987 /* This operation only makes sense on directory nodes. */ 988 if (vp->v_type != VDIR) { 989 return ENOTDIR; 990 } 991 node = VP_TO_TMPFS_DIR(vp); 992 /* 993 * Retrieve the directory entries, unless it is being destroyed. 994 */ 995 if (node->tn_links) { 996 error = tmpfs_dir_getdents(node, uio); 997 } else { 998 error = 0; 999 } 1000 1001 if (eofflag != NULL) { 1002 *eofflag = !error && uio->uio_offset == TMPFS_DIRSEQ_EOF; 1003 } 1004 return error; 1005 } 1006 1007 int 1008 tmpfs_readlink(void *v) 1009 { 1010 struct vop_readlink_args /* { 1011 struct vnode *a_vp; 1012 struct uio *a_uio; 1013 kauth_cred_t a_cred; 1014 } */ *ap = v; 1015 struct vnode *vp = ap->a_vp; 1016 struct uio *uio = ap->a_uio; 1017 tmpfs_node_t *node; 1018 int error; 1019 1020 KASSERT(VOP_ISLOCKED(vp)); 1021 KASSERT(uio->uio_offset == 0); 1022 KASSERT(vp->v_type == VLNK); 1023 1024 node = VP_TO_TMPFS_NODE(vp); 1025 error = uiomove(node->tn_spec.tn_lnk.tn_link, 1026 MIN((size_t)node->tn_size, uio->uio_resid), uio); 1027 1028 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) 1029 tmpfs_update(node, TMPFS_NODE_ACCESSED); 1030 1031 return error; 1032 } 1033 1034 int 1035 tmpfs_inactive(void *v) 1036 { 1037 struct vop_inactive_args /* { 1038 struct vnode *a_vp; 1039 int *a_recycle; 1040 } */ *ap = v; 1041 struct vnode *vp = ap->a_vp; 1042 tmpfs_node_t *node; 1043 1044 KASSERT(VOP_ISLOCKED(vp)); 1045 1046 node = VP_TO_TMPFS_NODE(vp); 1047 1048 if (vp->v_type == VREG && tmpfs_uio_cached(node)) 1049 tmpfs_uio_uncache(node); 1050 1051 VOP_UNLOCK(vp); 1052 1053 /* 1054 * If we are done with the node, reclaim it so that it can be reused 1055 * immediately. 1056 */ 1057 if (node->tn_links == 0) 1058 vrecycle(vp, curproc); 1059 1060 return 0; 1061 } 1062 1063 int 1064 tmpfs_reclaim(void *v) 1065 { 1066 struct vop_reclaim_args /* { 1067 struct vnode *a_vp; 1068 } */ *ap = v; 1069 struct vnode *vp = ap->a_vp; 1070 tmpfs_mount_t *tmp = VFS_TO_TMPFS(vp->v_mount); 1071 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1072 int racing; 1073 1074 /* Disassociate inode from vnode. */ 1075 rw_enter_write(&node->tn_nlock); 1076 node->tn_vnode = NULL; 1077 vp->v_data = NULL; 1078 /* Check if tmpfs_vnode_get() is racing with us. */ 1079 racing = TMPFS_NODE_RECLAIMING(node); 1080 rw_exit_write(&node->tn_nlock); 1081 1082 cache_purge(vp); 1083 1084 /* 1085 * If inode is not referenced, i.e. no links, then destroy it. 1086 * Note: if racing - inode is about to get a new vnode, leave it. 1087 */ 1088 if (node->tn_links == 0 && !racing) { 1089 tmpfs_free_node(tmp, node); 1090 } 1091 return 0; 1092 } 1093 1094 int 1095 tmpfs_pathconf(void *v) 1096 { 1097 struct vop_pathconf_args /* { 1098 struct vnode *a_vp; 1099 int a_name; 1100 register_t *a_retval; 1101 } */ *ap = v; 1102 const int name = ap->a_name; 1103 register_t *retval = ap->a_retval; 1104 int error = 0; 1105 1106 switch (name) { 1107 case _PC_LINK_MAX: 1108 *retval = LINK_MAX; 1109 break; 1110 case _PC_NAME_MAX: 1111 *retval = TMPFS_MAXNAMLEN; 1112 break; 1113 case _PC_CHOWN_RESTRICTED: 1114 *retval = 1; 1115 break; 1116 case _PC_NO_TRUNC: 1117 *retval = 1; 1118 break; 1119 case _PC_FILESIZEBITS: 1120 *retval = 64; 1121 break; 1122 case _PC_TIMESTAMP_RESOLUTION: 1123 *retval = 1; 1124 break; 1125 default: 1126 error = EINVAL; 1127 } 1128 return error; 1129 } 1130 1131 int 1132 tmpfs_advlock(void *v) 1133 { 1134 struct vop_advlock_args /* { 1135 struct vnode *a_vp; 1136 void * a_id; 1137 int a_op; 1138 struct flock *a_fl; 1139 int a_flags; 1140 } */ *ap = v; 1141 struct vnode *vp = ap->a_vp; 1142 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1143 1144 return lf_advlock(&node->tn_lockf, node->tn_size, ap->a_id, ap->a_op, 1145 ap->a_fl, ap->a_flags); 1146 } 1147 1148 int 1149 tmpfs_print(void *v) 1150 { 1151 struct vop_print_args /* { 1152 struct vnode *a_vp; 1153 } */ *ap = v; 1154 struct vnode *vp = ap->a_vp; 1155 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1156 1157 printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n" 1158 "\tmode 0%o, owner %d, group %d, size %lld", 1159 node, node->tn_flags, node->tn_links, node->tn_mode, node->tn_uid, 1160 node->tn_gid, node->tn_size); 1161 #ifdef FIFO 1162 if (vp->v_type == VFIFO) 1163 fifo_printinfo(vp); 1164 #endif 1165 printf("\n"); 1166 return 0; 1167 } 1168 1169 /* a null op */ 1170 int 1171 tmpfs_bwrite(void *v) 1172 { 1173 return 0; 1174 } 1175 1176 int 1177 tmpfs_strategy(void *v) 1178 { 1179 return EOPNOTSUPP; 1180 } 1181 1182 int 1183 tmpfs_ioctl(void *v) 1184 { 1185 return ENOTTY; 1186 } 1187 1188 int 1189 tmpfs_lock(void *v) 1190 { 1191 struct vop_lock_args *ap = v; 1192 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1193 1194 return rrw_enter(&tnp->tn_vlock, ap->a_flags & LK_RWFLAGS); 1195 } 1196 1197 int 1198 tmpfs_unlock(void *v) 1199 { 1200 struct vop_unlock_args *ap = v; 1201 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1202 1203 rrw_exit(&tnp->tn_vlock); 1204 return 0; 1205 } 1206 1207 int 1208 tmpfs_islocked(void *v) 1209 { 1210 struct vop_islocked_args *ap = v; 1211 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1212 1213 return rrw_status(&tnp->tn_vlock); 1214 } 1215 1216 /* 1217 * tmpfs_rename: rename routine, the hairiest system call, with the 1218 * insane API. 1219 * 1220 * Arguments: fdvp (from-parent vnode), fvp (from-leaf), tdvp (to-parent) 1221 * and tvp (to-leaf), if exists (NULL if not). 1222 * 1223 * => Caller holds a reference on fdvp and fvp, they are unlocked. 1224 * Note: fdvp and fvp can refer to the same object (i.e. when it is root). 1225 * 1226 * => Both tdvp and tvp are referenced and locked. It is our responsibility 1227 * to release the references and unlock them (or destroy). 1228 */ 1229 1230 /* 1231 * First, some forward declarations of subroutines. 1232 */ 1233 1234 int tmpfs_sane_rename(struct vnode *, struct componentname *, 1235 struct vnode *, struct componentname *, struct ucred *, int); 1236 int tmpfs_rename_enter(struct mount *, struct tmpfs_mount *, 1237 struct ucred *, 1238 struct vnode *, struct tmpfs_node *, struct componentname *, 1239 struct tmpfs_dirent **, struct vnode **, 1240 struct vnode *, struct tmpfs_node *, struct componentname *, 1241 struct tmpfs_dirent **, struct vnode **); 1242 int tmpfs_rename_enter_common(struct mount *, struct tmpfs_mount *, 1243 struct ucred *, 1244 struct vnode *, struct tmpfs_node *, 1245 struct componentname *, struct tmpfs_dirent **, struct vnode **, 1246 struct componentname *, struct tmpfs_dirent **, struct vnode **); 1247 int tmpfs_rename_enter_separate(struct mount *, struct tmpfs_mount *, 1248 struct ucred *, 1249 struct vnode *, struct tmpfs_node *, struct componentname *, 1250 struct tmpfs_dirent **, struct vnode **, 1251 struct vnode *, struct tmpfs_node *, struct componentname *, 1252 struct tmpfs_dirent **, struct vnode **); 1253 void tmpfs_rename_exit(struct tmpfs_mount *, 1254 struct vnode *, struct vnode *, struct vnode *, struct vnode *); 1255 int tmpfs_rename_lock_directory(struct vnode *, struct tmpfs_node *); 1256 int tmpfs_rename_genealogy(struct tmpfs_node *, struct tmpfs_node *, 1257 struct tmpfs_node **); 1258 int tmpfs_rename_lock(struct mount *, struct ucred *, int, 1259 struct vnode *, struct tmpfs_node *, struct componentname *, int, 1260 struct tmpfs_dirent **, struct vnode **, 1261 struct vnode *, struct tmpfs_node *, struct componentname *, int, 1262 struct tmpfs_dirent **, struct vnode **); 1263 void tmpfs_rename_attachdetach(struct tmpfs_mount *, 1264 struct vnode *, struct tmpfs_dirent *, struct vnode *, 1265 struct vnode *, struct tmpfs_dirent *, struct vnode *); 1266 int tmpfs_do_remove(struct tmpfs_mount *, struct vnode *, 1267 struct tmpfs_node *, struct tmpfs_dirent *, struct vnode *, struct ucred *); 1268 int tmpfs_rename_check_possible(struct tmpfs_node *, 1269 struct tmpfs_node *, struct tmpfs_node *, struct tmpfs_node *); 1270 int tmpfs_rename_check_permitted(struct ucred *, 1271 struct tmpfs_node *, struct tmpfs_node *, 1272 struct tmpfs_node *, struct tmpfs_node *); 1273 int tmpfs_remove_check_possible(struct tmpfs_node *, 1274 struct tmpfs_node *); 1275 int tmpfs_remove_check_permitted(struct ucred *, 1276 struct tmpfs_node *, struct tmpfs_node *); 1277 int tmpfs_check_sticky(struct ucred *, 1278 struct tmpfs_node *, struct tmpfs_node *); 1279 void tmpfs_rename_cache_purge(struct vnode *, struct vnode *, struct vnode *, 1280 struct vnode *); 1281 void tmpfs_rename_abort(void *); 1282 1283 int 1284 tmpfs_rename(void *v) 1285 { 1286 struct vop_rename_args /* { 1287 struct vnode *a_fdvp; 1288 struct vnode *a_fvp; 1289 struct componentname *a_fcnp; 1290 struct vnode *a_tdvp; 1291 struct vnode *a_tvp; 1292 struct componentname *a_tcnp; 1293 } */ *ap = v; 1294 struct vnode *fdvp = ap->a_fdvp; 1295 struct vnode *fvp = ap->a_fvp; 1296 struct componentname *fcnp = ap->a_fcnp; 1297 struct vnode *tdvp = ap->a_tdvp; 1298 struct vnode *tvp = ap->a_tvp; 1299 struct componentname *tcnp = ap->a_tcnp; 1300 struct ucred *cred; 1301 int error; 1302 1303 KASSERT(fdvp != NULL); 1304 KASSERT(fvp != NULL); 1305 KASSERT(fcnp != NULL); 1306 KASSERT(fcnp->cn_nameptr != NULL); 1307 KASSERT(tdvp != NULL); 1308 KASSERT(tcnp != NULL); 1309 KASSERT(fcnp->cn_nameptr != NULL); 1310 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1311 /* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */ 1312 KASSERT(fdvp->v_type == VDIR); 1313 KASSERT(tdvp->v_type == VDIR); 1314 KASSERT(fcnp->cn_flags & HASBUF); 1315 KASSERT(tcnp->cn_flags & HASBUF); 1316 1317 cred = fcnp->cn_cred; 1318 KASSERT(tcnp->cn_cred == cred); 1319 1320 /* 1321 * Check for cross-device rename. 1322 * Also don't allow renames of mount points. 1323 */ 1324 if (fvp->v_mount != tdvp->v_mount || 1325 fdvp->v_mount != fvp->v_mount || 1326 (tvp != NULL && (fvp->v_mount != tvp->v_mount))) { 1327 tmpfs_rename_abort(v); 1328 return EXDEV; 1329 } 1330 1331 /* 1332 * Can't check the locks on these until we know they're on 1333 * the same FS, as not all FS do locking the same way. 1334 */ 1335 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1336 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1337 1338 /* 1339 * Reject renaming '.' and '..'. 1340 */ 1341 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1342 (fcnp->cn_namelen == 2 && fcnp->cn_nameptr[0] == '.' && 1343 fcnp->cn_nameptr[1] == '.')) { 1344 tmpfs_rename_abort(v); 1345 return EINVAL; 1346 } 1347 1348 /* 1349 * Sanitize our world from the VFS insanity. Unlock the target 1350 * directory and node, which are locked. Release the children, 1351 * which are referenced. Check for rename("x", "y/."), which 1352 * it is our responsibility to reject, not the caller's. (But 1353 * the caller does reject rename("x/.", "y"). Go figure.) 1354 */ 1355 1356 VOP_UNLOCK(tdvp); 1357 if ((tvp != NULL) && (tvp != tdvp)) 1358 VOP_UNLOCK(tvp); 1359 1360 vrele(fvp); 1361 if (tvp != NULL) 1362 vrele(tvp); 1363 1364 if (tvp == tdvp) { 1365 error = EINVAL; 1366 goto out; 1367 } 1368 1369 error = tmpfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, 0); 1370 1371 out: /* 1372 * All done, whether with success or failure. Release the 1373 * directory nodes now, as the caller expects from the VFS 1374 * protocol. 1375 */ 1376 vrele(fdvp); 1377 vrele(tdvp); 1378 1379 return error; 1380 } 1381 1382 /* 1383 * tmpfs_sane_rename: rename routine, the hairiest system call, with 1384 * the sane API. 1385 * 1386 * Arguments: 1387 * 1388 * . fdvp (from directory vnode), 1389 * . fcnp (from component name), 1390 * . tdvp (to directory vnode), and 1391 * . tcnp (to component name). 1392 * 1393 * fdvp and tdvp must be referenced and unlocked. 1394 */ 1395 int 1396 tmpfs_sane_rename(struct vnode *fdvp, struct componentname *fcnp, 1397 struct vnode *tdvp, struct componentname *tcnp, struct ucred *cred, 1398 int posixly_correct) 1399 { 1400 struct mount *mount; 1401 struct tmpfs_mount *tmpfs; 1402 struct tmpfs_node *fdnode, *tdnode; 1403 struct tmpfs_dirent *fde, *tde; 1404 struct vnode *fvp, *tvp; 1405 char *newname; 1406 int error; 1407 1408 KASSERT(fdvp != NULL); 1409 KASSERT(fcnp != NULL); 1410 KASSERT(tdvp != NULL); 1411 KASSERT(tcnp != NULL); 1412 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1413 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 1414 KASSERT(fdvp->v_type == VDIR); 1415 KASSERT(tdvp->v_type == VDIR); 1416 KASSERT(fdvp->v_mount == tdvp->v_mount); 1417 KASSERT((fcnp->cn_flags & ISDOTDOT) == 0); 1418 KASSERT((tcnp->cn_flags & ISDOTDOT) == 0); 1419 KASSERT((fcnp->cn_namelen != 1) || (fcnp->cn_nameptr[0] != '.')); 1420 KASSERT((tcnp->cn_namelen != 1) || (tcnp->cn_nameptr[0] != '.')); 1421 KASSERT((fcnp->cn_namelen != 2) || (fcnp->cn_nameptr[0] != '.') || 1422 (fcnp->cn_nameptr[1] != '.')); 1423 KASSERT((tcnp->cn_namelen != 2) || (tcnp->cn_nameptr[0] != '.') || 1424 (tcnp->cn_nameptr[1] != '.')); 1425 1426 /* 1427 * Pull out the tmpfs data structures. 1428 */ 1429 fdnode = VP_TO_TMPFS_NODE(fdvp); 1430 tdnode = VP_TO_TMPFS_NODE(tdvp); 1431 KASSERT(fdnode != NULL); 1432 KASSERT(tdnode != NULL); 1433 KASSERT(fdnode->tn_vnode == fdvp); 1434 KASSERT(tdnode->tn_vnode == tdvp); 1435 KASSERT(fdnode->tn_type == VDIR); 1436 KASSERT(tdnode->tn_type == VDIR); 1437 1438 mount = fdvp->v_mount; 1439 KASSERT(mount != NULL); 1440 KASSERT(mount == tdvp->v_mount); 1441 /* XXX How can we be sure this stays true? (Not that you're 1442 * likely to mount a tmpfs read-only...) */ 1443 KASSERT((mount->mnt_flag & MNT_RDONLY) == 0); 1444 tmpfs = VFS_TO_TMPFS(mount); 1445 KASSERT(tmpfs != NULL); 1446 1447 /* 1448 * Decide whether we need a new name, and allocate memory for 1449 * it if so. Do this before locking anything or taking 1450 * destructive actions so that we can back out safely and sleep 1451 * safely. XXX Is sleeping an issue here? Can this just be 1452 * moved into tmpfs_rename_attachdetach? 1453 */ 1454 if (tmpfs_strname_neqlen(fcnp, tcnp)) { 1455 newname = tmpfs_strname_alloc(tmpfs, tcnp->cn_namelen); 1456 if (newname == NULL) { 1457 error = ENOSPC; 1458 goto out_unlocked; 1459 } 1460 } else { 1461 newname = NULL; 1462 } 1463 1464 /* 1465 * Lock and look up everything. GCC is not very clever. 1466 */ 1467 fde = tde = NULL; 1468 fvp = tvp = NULL; 1469 error = tmpfs_rename_enter(mount, tmpfs, cred, 1470 fdvp, fdnode, fcnp, &fde, &fvp, 1471 tdvp, tdnode, tcnp, &tde, &tvp); 1472 if (error) 1473 goto out_unlocked; 1474 1475 /* 1476 * Check that everything is locked and looks right. 1477 */ 1478 KASSERT(fde != NULL); 1479 KASSERT(fvp != NULL); 1480 KASSERT(fde->td_node != NULL); 1481 KASSERT(fde->td_node->tn_vnode == fvp); 1482 KASSERT(fde->td_node->tn_type == fvp->v_type); 1483 KASSERT((tde == NULL) == (tvp == NULL)); 1484 KASSERT((tde == NULL) || (tde->td_node != NULL)); 1485 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp)); 1486 KASSERT((tde == NULL) || (tde->td_node->tn_type == tvp->v_type)); 1487 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1488 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1489 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1490 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1491 1492 /* 1493 * If the source and destination are the same object, we need 1494 * only at most delete the source entry. 1495 */ 1496 if (fvp == tvp) { 1497 KASSERT(tvp != NULL); 1498 if (fde->td_node->tn_type == VDIR) { 1499 /* XXX How can this possibly happen? */ 1500 error = EINVAL; 1501 goto out_locked; 1502 } 1503 if (!posixly_correct && (fde != tde)) { 1504 /* XXX Doesn't work because of locking. 1505 * error = VOP_REMOVE(fdvp, fvp); 1506 */ 1507 error = tmpfs_do_remove(tmpfs, fdvp, fdnode, fde, fvp, 1508 cred); 1509 if (error) 1510 goto out_locked; 1511 } 1512 goto success; 1513 } 1514 KASSERT(fde != tde); 1515 KASSERT(fvp != tvp); 1516 1517 /* 1518 * If the target exists, refuse to rename a directory over a 1519 * non-directory or vice versa, or to clobber a non-empty 1520 * directory. 1521 */ 1522 if (tvp != NULL) { 1523 KASSERT(tde != NULL); 1524 KASSERT(tde->td_node != NULL); 1525 if (fvp->v_type == VDIR && tvp->v_type == VDIR) 1526 error = ((tde->td_node->tn_size > 0)? ENOTEMPTY : 0); 1527 else if (fvp->v_type == VDIR && tvp->v_type != VDIR) 1528 error = ENOTDIR; 1529 else if (fvp->v_type != VDIR && tvp->v_type == VDIR) 1530 error = EISDIR; 1531 else 1532 error = 0; 1533 if (error) 1534 goto out_locked; 1535 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR)); 1536 } 1537 1538 /* 1539 * Authorize the rename. 1540 */ 1541 error = tmpfs_rename_check_possible(fdnode, fde->td_node, 1542 tdnode, (tde? tde->td_node : NULL)); 1543 if (error) 1544 goto out_locked; 1545 error = tmpfs_rename_check_permitted(cred, fdnode, fde->td_node, 1546 tdnode, (tde? tde->td_node : NULL)); 1547 if (error) 1548 goto out_locked; 1549 1550 /* 1551 * Everything is hunky-dory. Shuffle the directory entries. 1552 */ 1553 tmpfs_rename_attachdetach(tmpfs, fdvp, fde, fvp, tdvp, tde, tvp); 1554 1555 /* 1556 * Update the directory entry's name necessary, and flag 1557 * metadata updates. A memory allocation failure here is not 1558 * OK because we've already committed some changes that we 1559 * can't back out at this point, and we have things locked so 1560 * we can't sleep, hence the early allocation above. 1561 */ 1562 if (newname != NULL) { 1563 KASSERT(tcnp->cn_namelen <= TMPFS_MAXNAMLEN); 1564 1565 tmpfs_strname_free(tmpfs, fde->td_name, fde->td_namelen); 1566 fde->td_namelen = (uint16_t)tcnp->cn_namelen; 1567 (void)memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen); 1568 /* Commit newname and don't free it on the way out. */ 1569 fde->td_name = newname; 1570 newname = NULL; 1571 1572 tmpfs_update(fde->td_node, TMPFS_NODE_CHANGED); 1573 tmpfs_update(tdnode, TMPFS_NODE_MODIFIED); 1574 } 1575 1576 success: 1577 VN_KNOTE(fvp, NOTE_RENAME); 1578 tmpfs_rename_cache_purge(fdvp, fvp, tdvp, tvp); 1579 error = 0; 1580 1581 out_locked: 1582 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp); 1583 1584 out_unlocked: 1585 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1586 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 1587 /* KASSERT((fvp == NULL) || (VOP_ISLOCKED(fvp) != LK_EXCLUSIVE)); */ 1588 /* KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */ 1589 1590 if (newname != NULL) 1591 tmpfs_strname_free(tmpfs, newname, tcnp->cn_namelen); 1592 1593 return error; 1594 } 1595 1596 /* 1597 * Look up fcnp in fdnode/fdvp and store its directory entry in fde_ret 1598 * and the associated vnode in fvp_ret; fail if not found. Look up 1599 * tcnp in tdnode/tdvp and store its directory entry in tde_ret and the 1600 * associated vnode in tvp_ret; store null instead if not found. Fail 1601 * if anything has been mounted on any of the nodes involved. 1602 * 1603 * fdvp and tdvp must be referenced. 1604 * 1605 * On entry, nothing is locked. 1606 * 1607 * On success, everything is locked, and *fvp_ret, and *tvp_ret if 1608 * nonnull, are referenced. The only pairs of vnodes that may be 1609 * identical are {fdvp, tdvp} and {fvp, tvp}. 1610 * 1611 * On failure, everything remains as was. 1612 * 1613 * Locking everything including the source and target nodes is 1614 * necessary to make sure that, e.g., link count updates are OK. The 1615 * locking order is, in general, ancestor-first, matching the order you 1616 * need to use to look up a descendant anyway. 1617 */ 1618 int 1619 tmpfs_rename_enter(struct mount *mount, struct tmpfs_mount *tmpfs, 1620 struct ucred *cred, 1621 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp, 1622 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1623 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp, 1624 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1625 { 1626 int error; 1627 1628 KASSERT(mount != NULL); 1629 KASSERT(tmpfs != NULL); 1630 KASSERT(fdvp != NULL); 1631 KASSERT(fdnode != NULL); 1632 KASSERT(fcnp != NULL); 1633 KASSERT(fde_ret != NULL); 1634 KASSERT(fvp_ret != NULL); 1635 KASSERT(tdvp != NULL); 1636 KASSERT(tdnode != NULL); 1637 KASSERT(tcnp != NULL); 1638 KASSERT(tde_ret != NULL); 1639 KASSERT(tvp_ret != NULL); 1640 KASSERT(fdnode->tn_vnode == fdvp); 1641 KASSERT(tdnode->tn_vnode == tdvp); 1642 KASSERT(fdnode->tn_type == VDIR); 1643 KASSERT(tdnode->tn_type == VDIR); 1644 1645 if (fdvp == tdvp) { 1646 KASSERT(fdnode == tdnode); 1647 error = tmpfs_rename_enter_common(mount, tmpfs, cred, fdvp, 1648 fdnode, fcnp, fde_ret, fvp_ret, tcnp, tde_ret, tvp_ret); 1649 } else { 1650 KASSERT(fdnode != tdnode); 1651 error = tmpfs_rename_enter_separate(mount, tmpfs, cred, 1652 fdvp, fdnode, fcnp, fde_ret, fvp_ret, 1653 tdvp, tdnode, tcnp, tde_ret, tvp_ret); 1654 } 1655 1656 if (error) 1657 return error; 1658 1659 KASSERT(*fde_ret != NULL); 1660 KASSERT(*fvp_ret != NULL); 1661 KASSERT((*tde_ret == NULL) == (*tvp_ret == NULL)); 1662 KASSERT((*tde_ret == NULL) || ((*tde_ret)->td_node != NULL)); 1663 KASSERT((*tde_ret == NULL) || 1664 ((*tde_ret)->td_node->tn_vnode == *tvp_ret)); 1665 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1666 KASSERT(VOP_ISLOCKED(*fvp_ret) == LK_EXCLUSIVE); 1667 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1668 KASSERT((*tvp_ret == NULL) || 1669 (VOP_ISLOCKED(*tvp_ret) == LK_EXCLUSIVE)); 1670 KASSERT(*fvp_ret != fdvp); 1671 KASSERT(*fvp_ret != tdvp); 1672 KASSERT(*tvp_ret != fdvp); 1673 KASSERT(*tvp_ret != tdvp); 1674 return 0; 1675 } 1676 1677 /* 1678 * Lock and look up with a common source/target directory. 1679 */ 1680 int 1681 tmpfs_rename_enter_common(struct mount *mount, struct tmpfs_mount *tmpfs, 1682 struct ucred *cred, 1683 struct vnode *dvp, struct tmpfs_node *dnode, 1684 struct componentname *fcnp, 1685 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1686 struct componentname *tcnp, 1687 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1688 { 1689 struct tmpfs_dirent *fde, *tde; 1690 struct vnode *fvp, *tvp; 1691 int error; 1692 1693 error = tmpfs_rename_lock_directory(dvp, dnode); 1694 if (error) 1695 goto fail0; 1696 1697 /* Did we lose a race with mount? */ 1698 if (dvp->v_mountedhere != NULL) { 1699 error = EBUSY; 1700 goto fail1; 1701 } 1702 1703 /* Make sure the caller may read the directory. */ 1704 error = VOP_ACCESS(dvp, VEXEC, cred, curproc); 1705 if (error) 1706 goto fail1; 1707 1708 /* 1709 * The order in which we lock the source and target nodes is 1710 * irrelevant because there can only be one rename on this 1711 * directory in flight at a time, and we have it locked. 1712 */ 1713 1714 fde = tmpfs_dir_lookup(dnode, fcnp); 1715 if (fde == NULL) { 1716 error = ENOENT; 1717 goto fail1; 1718 } 1719 1720 KASSERT(fde->td_node != NULL); 1721 /* We ruled out `.' earlier. */ 1722 KASSERT(fde->td_node != dnode); 1723 /* We ruled out `..' earlier. */ 1724 KASSERT(fde->td_node != dnode->tn_spec.tn_dir.tn_parent); 1725 rw_enter_write(&fde->td_node->tn_nlock); 1726 error = tmpfs_vnode_get(mount, fde->td_node, &fvp); 1727 if (error) 1728 goto fail1; 1729 KASSERT(fvp != NULL); 1730 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1731 KASSERT(fvp != dvp); 1732 KASSERT(fvp->v_mount == mount); 1733 1734 /* Refuse to rename a mount point. */ 1735 if ((fvp->v_type == VDIR) && (fvp->v_mountedhere != NULL)) { 1736 error = EBUSY; 1737 goto fail2; 1738 } 1739 1740 tde = tmpfs_dir_lookup(dnode, tcnp); 1741 if (tde == NULL) { 1742 tvp = NULL; 1743 } else { 1744 KASSERT(tde->td_node != NULL); 1745 /* We ruled out `.' earlier. */ 1746 KASSERT(tde->td_node != dnode); 1747 /* We ruled out `..' earlier. */ 1748 KASSERT(tde->td_node != dnode->tn_spec.tn_dir.tn_parent); 1749 if (tde->td_node != fde->td_node) { 1750 rw_enter_write(&tde->td_node->tn_nlock); 1751 error = tmpfs_vnode_get(mount, tde->td_node, &tvp); 1752 if (error) 1753 goto fail2; 1754 KASSERT(tvp->v_mount == mount); 1755 /* Refuse to rename over a mount point. */ 1756 if ((tvp->v_type == VDIR) && 1757 (tvp->v_mountedhere != NULL)) { 1758 error = EBUSY; 1759 goto fail3; 1760 } 1761 } else { 1762 tvp = fvp; 1763 vref(tvp); 1764 } 1765 KASSERT(tvp != NULL); 1766 KASSERT(VOP_ISLOCKED(tvp) == LK_EXCLUSIVE); 1767 } 1768 KASSERT(tvp != dvp); 1769 1770 *fde_ret = fde; 1771 *fvp_ret = fvp; 1772 *tde_ret = tde; 1773 *tvp_ret = tvp; 1774 return 0; 1775 1776 fail3: if (tvp != NULL) { 1777 if (tvp != fvp) 1778 vput(tvp); 1779 else 1780 vrele(tvp); 1781 } 1782 1783 fail2: vput(fvp); 1784 fail1: VOP_UNLOCK(dvp); 1785 fail0: return error; 1786 } 1787 1788 /* 1789 * Lock and look up with separate source and target directories. 1790 */ 1791 int 1792 tmpfs_rename_enter_separate(struct mount *mount, struct tmpfs_mount *tmpfs, 1793 struct ucred *cred, 1794 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp, 1795 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1796 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp, 1797 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1798 { 1799 struct tmpfs_node *intermediate_node; 1800 struct tmpfs_dirent *fde, *tde; 1801 struct vnode *fvp, *tvp; 1802 int error; 1803 1804 KASSERT(fdvp != tdvp); 1805 KASSERT(fdnode != tdnode); 1806 1807 #if 0 /* XXX */ 1808 mutex_enter(&tmpfs->tm_rename_lock); 1809 #endif 1810 1811 error = tmpfs_rename_genealogy(fdnode, tdnode, &intermediate_node); 1812 if (error) 1813 goto fail; 1814 1815 /* 1816 * intermediate_node == NULL means fdnode is not an ancestor of 1817 * tdnode. 1818 */ 1819 if (intermediate_node == NULL) 1820 error = tmpfs_rename_lock(mount, cred, ENOTEMPTY, 1821 tdvp, tdnode, tcnp, 1, &tde, &tvp, 1822 fdvp, fdnode, fcnp, 0, &fde, &fvp); 1823 else 1824 error = tmpfs_rename_lock(mount, cred, EINVAL, 1825 fdvp, fdnode, fcnp, 0, &fde, &fvp, 1826 tdvp, tdnode, tcnp, 1, &tde, &tvp); 1827 if (error) 1828 goto fail; 1829 1830 KASSERT(fde != NULL); 1831 KASSERT(fde->td_node != NULL); 1832 1833 /* 1834 * Reject rename("foo/bar", "foo/bar/baz/quux/zot"). 1835 */ 1836 if (fde->td_node == intermediate_node) { 1837 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp); 1838 return EINVAL; 1839 } 1840 1841 *fde_ret = fde; 1842 *fvp_ret = fvp; 1843 *tde_ret = tde; 1844 *tvp_ret = tvp; 1845 return 0; 1846 1847 fail: 1848 #if 0 /* XXX */ 1849 mutex_exit(&tmpfs->tm_rename_lock); 1850 #endif 1851 return error; 1852 } 1853 1854 /* 1855 * Unlock everything we locked for rename. 1856 * 1857 * fdvp and tdvp must be referenced. 1858 * 1859 * On entry, everything is locked, and fvp and tvp referenced. 1860 * 1861 * On exit, everything is unlocked, and fvp and tvp are released. 1862 */ 1863 void 1864 tmpfs_rename_exit(struct tmpfs_mount *tmpfs, 1865 struct vnode *fdvp, struct vnode *fvp, 1866 struct vnode *tdvp, struct vnode *tvp) 1867 { 1868 1869 KASSERT(tmpfs != NULL); 1870 KASSERT(fdvp != NULL); 1871 KASSERT(fvp != NULL); 1872 KASSERT(fdvp != fvp); 1873 KASSERT(fdvp != tvp); 1874 KASSERT(tdvp != tvp); 1875 KASSERT(tdvp != fvp); 1876 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1877 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1878 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1879 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1880 1881 if (tvp != NULL) { 1882 if (tvp != fvp) 1883 vput(tvp); 1884 else 1885 vrele(tvp); 1886 } 1887 VOP_UNLOCK(tdvp); 1888 vput(fvp); 1889 if (fdvp != tdvp) 1890 VOP_UNLOCK(fdvp); 1891 1892 #if 0 /* XXX */ 1893 if (fdvp != tdvp) 1894 mutex_exit(&tmpfs->tm_rename_lock); 1895 #endif 1896 } 1897 1898 /* 1899 * Lock a directory, but fail if it has been rmdir'd. 1900 * 1901 * vp must be referenced. 1902 */ 1903 int 1904 tmpfs_rename_lock_directory(struct vnode *vp, struct tmpfs_node *node) 1905 { 1906 1907 KASSERT(vp != NULL); 1908 KASSERT(node != NULL); 1909 KASSERT(node->tn_vnode == vp); 1910 KASSERT(node->tn_type == VDIR); 1911 1912 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1913 if (node->tn_spec.tn_dir.tn_parent == NULL) { 1914 VOP_UNLOCK(vp); 1915 return ENOENT; 1916 } 1917 1918 return 0; 1919 } 1920 1921 /* 1922 * Analyze the genealogy of the source and target nodes. 1923 * 1924 * On success, stores in *intermediate_node_ret either the child of 1925 * fdnode of which tdnode is a descendant, or null if tdnode is not a 1926 * descendant of fdnode at all. 1927 * 1928 * fdnode and tdnode must be unlocked and referenced. The file 1929 * system's rename lock must also be held, to exclude concurrent 1930 * changes to the file system's genealogy other than rmdir. 1931 * 1932 * XXX This causes an extra lock/unlock of tdnode in the case when 1933 * we're just about to lock it again before locking anything else. 1934 * However, changing that requires reorganizing the code to make it 1935 * even more horrifically obscure. 1936 */ 1937 int 1938 tmpfs_rename_genealogy(struct tmpfs_node *fdnode, struct tmpfs_node *tdnode, 1939 struct tmpfs_node **intermediate_node_ret) 1940 { 1941 struct tmpfs_node *node = tdnode, *parent; 1942 int error; 1943 1944 KASSERT(fdnode != NULL); 1945 KASSERT(tdnode != NULL); 1946 KASSERT(fdnode != tdnode); 1947 KASSERT(intermediate_node_ret != NULL); 1948 1949 KASSERT(fdnode->tn_vnode != NULL); 1950 KASSERT(tdnode->tn_vnode != NULL); 1951 KASSERT(fdnode->tn_type == VDIR); 1952 KASSERT(tdnode->tn_type == VDIR); 1953 1954 /* 1955 * We need to provisionally lock tdnode->tn_vnode to keep rmdir 1956 * from deleting it -- or any ancestor -- at an inopportune 1957 * moment. 1958 */ 1959 error = tmpfs_rename_lock_directory(tdnode->tn_vnode, tdnode); 1960 if (error) 1961 return error; 1962 1963 for (;;) { 1964 parent = node->tn_spec.tn_dir.tn_parent; 1965 KASSERT(parent != NULL); 1966 KASSERT(parent->tn_type == VDIR); 1967 1968 /* Did we hit the root without finding fdnode? */ 1969 if (parent == node) { 1970 *intermediate_node_ret = NULL; 1971 break; 1972 } 1973 1974 /* Did we find that fdnode is an ancestor? */ 1975 if (parent == fdnode) { 1976 *intermediate_node_ret = node; 1977 break; 1978 } 1979 1980 /* Neither -- keep ascending the family tree. */ 1981 node = parent; 1982 } 1983 1984 VOP_UNLOCK(tdnode->tn_vnode); 1985 return 0; 1986 } 1987 1988 /* 1989 * Lock directories a and b, which must be distinct, and look up and 1990 * lock nodes a and b. Do a first and then b. Directory b may not be 1991 * an ancestor of directory a, although directory a may be an ancestor 1992 * of directory b. Fail with overlap_error if node a is directory b. 1993 * Neither componentname may be `.' or `..'. 1994 * 1995 * a_dvp and b_dvp must be referenced. 1996 * 1997 * On entry, a_dvp and b_dvp are unlocked. 1998 * 1999 * On success, 2000 * . a_dvp and b_dvp are locked, 2001 * . *a_dirent_ret is filled with a directory entry whose node is 2002 * locked and referenced, 2003 * . *b_vp_ret is filled with the corresponding vnode, 2004 * . *b_dirent_ret is filled either with null or with a directory entry 2005 * whose node is locked and referenced, 2006 * . *b_vp is filled either with null or with the corresponding vnode, 2007 * and 2008 * . the only pair of vnodes that may be identical is a_vp and b_vp. 2009 * 2010 * On failure, a_dvp and b_dvp are left unlocked, and *a_dirent_ret, 2011 * *a_vp, *b_dirent_ret, and *b_vp are left alone. 2012 */ 2013 int 2014 tmpfs_rename_lock(struct mount *mount, struct ucred *cred, int overlap_error, 2015 struct vnode *a_dvp, struct tmpfs_node *a_dnode, 2016 struct componentname *a_cnp, int a_missing_ok, 2017 struct tmpfs_dirent **a_dirent_ret, struct vnode **a_vp_ret, 2018 struct vnode *b_dvp, struct tmpfs_node *b_dnode, 2019 struct componentname *b_cnp, int b_missing_ok, 2020 struct tmpfs_dirent **b_dirent_ret, struct vnode **b_vp_ret) 2021 { 2022 struct tmpfs_dirent *a_dirent, *b_dirent; 2023 struct vnode *a_vp, *b_vp; 2024 int error; 2025 2026 KASSERT(a_dvp != NULL); 2027 KASSERT(a_dnode != NULL); 2028 KASSERT(a_cnp != NULL); 2029 KASSERT(a_dirent_ret != NULL); 2030 KASSERT(a_vp_ret != NULL); 2031 KASSERT(b_dvp != NULL); 2032 KASSERT(b_dnode != NULL); 2033 KASSERT(b_cnp != NULL); 2034 KASSERT(b_dirent_ret != NULL); 2035 KASSERT(b_vp_ret != NULL); 2036 KASSERT(a_dvp != b_dvp); 2037 KASSERT(a_dnode != b_dnode); 2038 KASSERT(a_dnode->tn_vnode == a_dvp); 2039 KASSERT(b_dnode->tn_vnode == b_dvp); 2040 KASSERT(a_dnode->tn_type == VDIR); 2041 KASSERT(b_dnode->tn_type == VDIR); 2042 KASSERT(a_missing_ok != b_missing_ok); 2043 2044 error = tmpfs_rename_lock_directory(a_dvp, a_dnode); 2045 if (error) 2046 goto fail0; 2047 2048 /* Did we lose a race with mount? */ 2049 if (a_dvp->v_mountedhere != NULL) { 2050 error = EBUSY; 2051 goto fail1; 2052 } 2053 2054 /* Make sure the caller may read the directory. */ 2055 error = VOP_ACCESS(a_dvp, VEXEC, cred, curproc); 2056 if (error) 2057 goto fail1; 2058 2059 a_dirent = tmpfs_dir_lookup(a_dnode, a_cnp); 2060 if (a_dirent != NULL) { 2061 KASSERT(a_dirent->td_node != NULL); 2062 /* We ruled out `.' earlier. */ 2063 KASSERT(a_dirent->td_node != a_dnode); 2064 /* We ruled out `..' earlier. */ 2065 KASSERT(a_dirent->td_node != 2066 a_dnode->tn_spec.tn_dir.tn_parent); 2067 if (a_dirent->td_node == b_dnode) { 2068 error = overlap_error; 2069 goto fail1; 2070 } 2071 rw_enter_write(&a_dirent->td_node->tn_nlock); 2072 error = tmpfs_vnode_get(mount, a_dirent->td_node, &a_vp); 2073 if (error) 2074 goto fail1; 2075 KASSERT(a_vp->v_mount == mount); 2076 /* Refuse to rename (over) a mount point. */ 2077 if ((a_vp->v_type == VDIR) && (a_vp->v_mountedhere != NULL)) { 2078 error = EBUSY; 2079 goto fail2; 2080 } 2081 } else if (!a_missing_ok) { 2082 error = ENOENT; 2083 goto fail1; 2084 } else { 2085 a_vp = NULL; 2086 } 2087 KASSERT(a_vp != a_dvp); 2088 KASSERT(a_vp != b_dvp); 2089 2090 error = tmpfs_rename_lock_directory(b_dvp, b_dnode); 2091 if (error) 2092 goto fail2; 2093 2094 /* Did we lose a race with mount? */ 2095 if (b_dvp->v_mountedhere != NULL) { 2096 error = EBUSY; 2097 goto fail3; 2098 } 2099 2100 /* Make sure the caller may read the directory. */ 2101 error = VOP_ACCESS(b_dvp, VEXEC, cred, curproc); 2102 if (error) 2103 goto fail3; 2104 2105 b_dirent = tmpfs_dir_lookup(b_dnode, b_cnp); 2106 if (b_dirent != NULL) { 2107 KASSERT(b_dirent->td_node != NULL); 2108 /* We ruled out `.' earlier. */ 2109 KASSERT(b_dirent->td_node != b_dnode); 2110 /* We ruled out `..' earlier. */ 2111 KASSERT(b_dirent->td_node != 2112 b_dnode->tn_spec.tn_dir.tn_parent); 2113 /* b is not an ancestor of a. */ 2114 KASSERT(b_dirent->td_node != a_dnode); 2115 /* But the source and target nodes might be the same. */ 2116 if ((a_dirent == NULL) || 2117 (a_dirent->td_node != b_dirent->td_node)) { 2118 rw_enter_write(&b_dirent->td_node->tn_nlock); 2119 error = tmpfs_vnode_get(mount, b_dirent->td_node, 2120 &b_vp); 2121 if (error) 2122 goto fail3; 2123 KASSERT(b_vp->v_mount == mount); 2124 KASSERT(a_vp != b_vp); 2125 /* Refuse to rename (over) a mount point. */ 2126 if ((b_vp->v_type == VDIR) && 2127 (b_vp->v_mountedhere != NULL)) { 2128 error = EBUSY; 2129 goto fail4; 2130 } 2131 } else { 2132 b_vp = a_vp; 2133 vref(b_vp); 2134 } 2135 } else if (!b_missing_ok) { 2136 error = ENOENT; 2137 goto fail3; 2138 } else { 2139 b_vp = NULL; 2140 } 2141 KASSERT(b_vp != a_dvp); 2142 KASSERT(b_vp != b_dvp); 2143 2144 KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE); 2145 KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE); 2146 KASSERT(a_missing_ok || (a_dirent != NULL)); 2147 KASSERT(a_missing_ok || (a_dirent->td_node != NULL)); 2148 KASSERT(b_missing_ok || (b_dirent != NULL)); 2149 KASSERT(b_missing_ok || (b_dirent->td_node != NULL)); 2150 KASSERT((a_dirent == NULL) || (a_dirent->td_node != NULL)); 2151 KASSERT((a_dirent == NULL) || (a_dirent->td_node->tn_vnode == a_vp)); 2152 KASSERT((b_dirent == NULL) || (b_dirent->td_node != NULL)); 2153 KASSERT((b_dirent == NULL) || (b_dirent->td_node->tn_vnode == b_vp)); 2154 KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE)); 2155 KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE)); 2156 2157 *a_dirent_ret = a_dirent; 2158 *b_dirent_ret = b_dirent; 2159 *a_vp_ret = a_vp; 2160 *b_vp_ret = b_vp; 2161 return 0; 2162 2163 fail4: if (b_vp != NULL) { 2164 KASSERT(VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE); 2165 if (b_vp != a_vp) 2166 vput(b_vp); 2167 else 2168 vrele(a_vp); 2169 } 2170 2171 fail3: KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE); 2172 VOP_UNLOCK(b_dvp); 2173 2174 fail2: if (a_vp != NULL) { 2175 KASSERT(VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE); 2176 vput(a_vp); 2177 } 2178 2179 fail1: KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE); 2180 VOP_UNLOCK(a_dvp); 2181 2182 fail0: /* KASSERT(VOP_ISLOCKED(a_dvp) != LK_EXCLUSIVE); */ 2183 /* KASSERT(VOP_ISLOCKED(b_dvp) != LK_EXCLUSIVE); */ 2184 /* KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) != LK_EXCLUSIVE)); */ 2185 /* KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) != LK_EXCLUSIVE)); */ 2186 return error; 2187 } 2188 2189 /* 2190 * Shuffle the directory entries to move fvp from the directory fdvp 2191 * into the directory tdvp. fde is fvp's directory entry in fdvp. If 2192 * we are overwriting a target node, it is tvp, and tde is its 2193 * directory entry in tdvp. 2194 * 2195 * fdvp, fvp, tdvp, and tvp must all be locked and referenced. 2196 */ 2197 void 2198 tmpfs_rename_attachdetach(struct tmpfs_mount *tmpfs, 2199 struct vnode *fdvp, struct tmpfs_dirent *fde, struct vnode *fvp, 2200 struct vnode *tdvp, struct tmpfs_dirent *tde, struct vnode *tvp) 2201 { 2202 2203 KASSERT(tmpfs != NULL); 2204 KASSERT(fdvp != NULL); 2205 KASSERT(fde != NULL); 2206 KASSERT(fvp != NULL); 2207 KASSERT(tdvp != NULL); 2208 KASSERT(fde->td_node != NULL); 2209 KASSERT(fde->td_node->tn_vnode == fvp); 2210 KASSERT((tde == NULL) == (tvp == NULL)); 2211 KASSERT((tde == NULL) || (tde->td_node != NULL)); 2212 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp)); 2213 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 2214 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 2215 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 2216 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 2217 2218 /* 2219 * If we are moving from one directory to another, detach the 2220 * source entry and reattach it to the target directory. 2221 */ 2222 if (fdvp != tdvp) { 2223 /* tmpfs_dir_detach clobbers fde->td_node, so save it. */ 2224 struct tmpfs_node *fnode = fde->td_node; 2225 tmpfs_node_t *fdnode = VP_TO_TMPFS_DIR(fdvp); 2226 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp); 2227 tmpfs_dir_detach(fdnode, fde); 2228 tmpfs_dir_attach(tdnode, fde, fnode); 2229 } else if (tvp == NULL) { 2230 /* 2231 * We are changing the directory. tmpfs_dir_attach and 2232 * tmpfs_dir_detach note the events for us, but for 2233 * this case we don't call them, so we must note the 2234 * event explicitly. 2235 */ 2236 VN_KNOTE(fdvp, NOTE_WRITE); 2237 } 2238 2239 /* 2240 * If we are replacing an existing target entry, delete it. 2241 */ 2242 if (tde != NULL) { 2243 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp); 2244 KASSERT(tvp != NULL); 2245 KASSERT(tde->td_node != NULL); 2246 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR)); 2247 if (tde->td_node->tn_type == VDIR) { 2248 KASSERT(tde->td_node->tn_size == 0); 2249 KASSERT(tde->td_node->tn_links == 2); 2250 /* Decrement the extra link count for `.' so 2251 * the vnode will be recycled when released. */ 2252 tde->td_node->tn_links--; 2253 } 2254 tmpfs_dir_detach(tdnode, tde); 2255 tmpfs_free_dirent(tmpfs, tde); 2256 } 2257 } 2258 2259 /* 2260 * Remove the entry de for the non-directory vp from the directory dvp. 2261 * 2262 * Everything must be locked and referenced. 2263 */ 2264 int 2265 tmpfs_do_remove(struct tmpfs_mount *tmpfs, struct vnode *dvp, 2266 struct tmpfs_node *dnode, struct tmpfs_dirent *de, struct vnode *vp, 2267 struct ucred *cred) 2268 { 2269 int error; 2270 2271 KASSERT(tmpfs != NULL); 2272 KASSERT(dvp != NULL); 2273 KASSERT(dnode != NULL); 2274 KASSERT(de != NULL); 2275 KASSERT(vp != NULL); 2276 KASSERT(dnode->tn_vnode == dvp); 2277 KASSERT(de->td_node != NULL); 2278 KASSERT(de->td_node->tn_vnode == vp); 2279 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 2280 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2281 2282 error = tmpfs_remove_check_possible(dnode, de->td_node); 2283 if (error) 2284 return error; 2285 2286 error = tmpfs_remove_check_permitted(cred, dnode, de->td_node); 2287 if (error) 2288 return error; 2289 2290 /* 2291 * If not root and directory is sticky, check for permission on 2292 * directory or on file. This implements append-only directories. 2293 */ 2294 if ((dnode->tn_mode & S_ISTXT) != 0) 2295 if (cred->cr_uid != 0 && cred->cr_uid != dnode->tn_uid && 2296 cred->cr_uid != de->td_node->tn_uid) 2297 return EPERM; 2298 2299 tmpfs_dir_detach(dnode, de); 2300 tmpfs_free_dirent(tmpfs, de); 2301 2302 return 0; 2303 } 2304 2305 /* 2306 * Check whether a rename is possible independent of credentials. 2307 * 2308 * Everything must be locked and referenced. 2309 */ 2310 int 2311 tmpfs_rename_check_possible( 2312 struct tmpfs_node *fdnode, struct tmpfs_node *fnode, 2313 struct tmpfs_node *tdnode, struct tmpfs_node *tnode) 2314 { 2315 2316 KASSERT(fdnode != NULL); 2317 KASSERT(fnode != NULL); 2318 KASSERT(tdnode != NULL); 2319 KASSERT(fdnode != fnode); 2320 KASSERT(tdnode != tnode); 2321 KASSERT(fnode != tnode); 2322 KASSERT(fdnode->tn_vnode != NULL); 2323 KASSERT(fnode->tn_vnode != NULL); 2324 KASSERT(tdnode->tn_vnode != NULL); 2325 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL)); 2326 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE); 2327 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE); 2328 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE); 2329 KASSERT((tnode == NULL) || 2330 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE)); 2331 2332 /* 2333 * If fdnode is immutable, we can't write to it. If fdnode is 2334 * append-only, the only change we can make is to add entries 2335 * to it. If fnode is immutable, we can't change the links to 2336 * it. If fnode is append-only...well, this is what UFS does. 2337 */ 2338 if ((fdnode->tn_flags | fnode->tn_flags) & (IMMUTABLE | APPEND)) 2339 return EPERM; 2340 2341 /* 2342 * If tdnode is immutable, we can't write to it. If tdnode is 2343 * append-only, we can add entries, but we can't change 2344 * existing entries. 2345 */ 2346 if (tdnode->tn_flags & (IMMUTABLE | (tnode? APPEND : 0))) 2347 return EPERM; 2348 2349 /* 2350 * If tnode is immutable, we can't replace links to it. If 2351 * tnode is append-only...well, this is what UFS does. 2352 */ 2353 if (tnode != NULL) { 2354 KASSERT(tnode != NULL); 2355 if ((tnode->tn_flags & (IMMUTABLE | APPEND)) != 0) 2356 return EPERM; 2357 } 2358 2359 return 0; 2360 } 2361 2362 /* 2363 * Check whether a rename is permitted given our credentials. 2364 * 2365 * Everything must be locked and referenced. 2366 */ 2367 int 2368 tmpfs_rename_check_permitted(struct ucred *cred, 2369 struct tmpfs_node *fdnode, struct tmpfs_node *fnode, 2370 struct tmpfs_node *tdnode, struct tmpfs_node *tnode) 2371 { 2372 int error; 2373 2374 KASSERT(fdnode != NULL); 2375 KASSERT(fnode != NULL); 2376 KASSERT(tdnode != NULL); 2377 KASSERT(fdnode != fnode); 2378 KASSERT(tdnode != tnode); 2379 KASSERT(fnode != tnode); 2380 KASSERT(fdnode->tn_vnode != NULL); 2381 KASSERT(fnode->tn_vnode != NULL); 2382 KASSERT(tdnode->tn_vnode != NULL); 2383 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL)); 2384 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE); 2385 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE); 2386 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE); 2387 KASSERT((tnode == NULL) || 2388 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE)); 2389 2390 /* 2391 * We need to remove or change an entry in the source directory. 2392 */ 2393 error = VOP_ACCESS(fdnode->tn_vnode, VWRITE, cred, curproc); 2394 if (error) 2395 return error; 2396 2397 /* 2398 * If we are changing directories, then we need to write to the 2399 * target directory to add or change an entry. Also, if fnode 2400 * is a directory, we need to write to it to change its `..' 2401 * entry. 2402 */ 2403 if (fdnode != tdnode) { 2404 error = VOP_ACCESS(tdnode->tn_vnode, VWRITE, cred, curproc); 2405 if (error) 2406 return error; 2407 if (fnode->tn_type == VDIR) { 2408 error = VOP_ACCESS(fnode->tn_vnode, VWRITE, cred, 2409 curproc); 2410 if (error) 2411 return error; 2412 } 2413 } 2414 2415 error = tmpfs_check_sticky(cred, fdnode, fnode); 2416 if (error) 2417 return error; 2418 2419 if (TMPFS_DIRSEQ_FULL(tdnode)) 2420 return (ENOSPC); 2421 2422 error = tmpfs_check_sticky(cred, tdnode, tnode); 2423 if (error) 2424 return error; 2425 2426 return 0; 2427 } 2428 2429 /* 2430 * Check whether removing node's entry in dnode is possible independent 2431 * of credentials. 2432 * 2433 * Everything must be locked and referenced. 2434 */ 2435 int 2436 tmpfs_remove_check_possible(struct tmpfs_node *dnode, struct tmpfs_node *node) 2437 { 2438 2439 KASSERT(dnode != NULL); 2440 KASSERT(dnode->tn_vnode != NULL); 2441 KASSERT(node != NULL); 2442 KASSERT(dnode != node); 2443 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2444 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE); 2445 2446 /* 2447 * We want to delete the entry. If dnode is immutable, we 2448 * can't write to it to delete the entry. If dnode is 2449 * append-only, the only change we can make is to add entries, 2450 * so we can't delete entries. If node is immutable, we can't 2451 * change the links to it, so we can't delete the entry. If 2452 * node is append-only...well, this is what UFS does. 2453 */ 2454 if ((dnode->tn_flags | node->tn_flags) & (IMMUTABLE | APPEND)) 2455 return EPERM; 2456 2457 return 0; 2458 } 2459 2460 /* 2461 * Check whether removing node's entry in dnode is permitted given our 2462 * credentials. 2463 * 2464 * Everything must be locked and referenced. 2465 */ 2466 int 2467 tmpfs_remove_check_permitted(struct ucred *cred, 2468 struct tmpfs_node *dnode, struct tmpfs_node *node) 2469 { 2470 int error; 2471 2472 KASSERT(dnode != NULL); 2473 KASSERT(dnode->tn_vnode != NULL); 2474 KASSERT(node != NULL); 2475 KASSERT(dnode != node); 2476 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2477 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE); 2478 2479 /* 2480 * Check whether we are permitted to write to the source 2481 * directory in order to delete an entry from it. 2482 */ 2483 error = VOP_ACCESS(dnode->tn_vnode, VWRITE, cred, curproc); 2484 if (error) 2485 return error; 2486 2487 error = tmpfs_check_sticky(cred, dnode, node); 2488 if (error) 2489 return error; 2490 2491 return 0; 2492 } 2493 2494 /* 2495 * Check whether we may change an entry in a sticky directory. If the 2496 * directory is sticky, the user must own either the directory or, if 2497 * it exists, the node, in order to change the entry. 2498 * 2499 * Everything must be locked and referenced. 2500 */ 2501 int 2502 tmpfs_check_sticky(struct ucred *cred, 2503 struct tmpfs_node *dnode, struct tmpfs_node *node) 2504 { 2505 2506 KASSERT(dnode != NULL); 2507 KASSERT(dnode->tn_vnode != NULL); 2508 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2509 KASSERT((node == NULL) || (node->tn_vnode != NULL)); 2510 KASSERT((node == NULL) || 2511 (VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE)); 2512 2513 if (node == NULL) 2514 return 0; 2515 2516 if (dnode->tn_mode & S_ISTXT) { 2517 if (cred->cr_uid != 0 && 2518 cred->cr_uid != dnode->tn_uid && 2519 cred->cr_uid != node->tn_uid) 2520 return EPERM; 2521 } 2522 2523 return 0; 2524 } 2525 2526 void 2527 tmpfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp, 2528 struct vnode *tdvp, struct vnode *tvp) 2529 { 2530 2531 KASSERT(fdvp != NULL); 2532 KASSERT(fvp != NULL); 2533 KASSERT(tdvp != NULL); 2534 KASSERT(fdvp != fvp); 2535 KASSERT(fdvp != tvp); 2536 KASSERT(tdvp != fvp); 2537 KASSERT(tdvp != tvp); 2538 KASSERT(fvp != tvp); 2539 KASSERT(fdvp->v_type == VDIR); 2540 KASSERT(tdvp->v_type == VDIR); 2541 2542 /* 2543 * XXX What actually needs to be purged? 2544 */ 2545 2546 cache_purge(fdvp); 2547 2548 if (fvp->v_type == VDIR) 2549 cache_purge(fvp); 2550 2551 if (tdvp != fdvp) 2552 cache_purge(tdvp); 2553 2554 if ((tvp != NULL) && (tvp->v_type == VDIR)) 2555 cache_purge(tvp); 2556 } 2557 2558 void 2559 tmpfs_rename_abort(void *v) 2560 { 2561 struct vop_rename_args *ap = v; 2562 struct vnode *fdvp = ap->a_fdvp; 2563 struct vnode *fvp = ap->a_fvp; 2564 struct componentname *fcnp = ap->a_fcnp; 2565 struct vnode *tdvp = ap->a_tdvp; 2566 struct vnode *tvp = ap->a_tvp; 2567 struct componentname *tcnp = ap->a_tcnp; 2568 2569 VOP_ABORTOP(tdvp, tcnp); 2570 if (tdvp == tvp) 2571 vrele(tdvp); 2572 else 2573 vput(tdvp); 2574 if (tvp != NULL) 2575 vput(tvp); 2576 VOP_ABORTOP(fdvp, fcnp); 2577 vrele(fdvp); 2578 vrele(fvp); 2579 } 2580 2581 void filt_tmpfsdetach(struct knote *kn); 2582 int filt_tmpfsread(struct knote *kn, long hint); 2583 int filt_tmpfswrite(struct knote *kn, long hint); 2584 int filt_tmpfsvnode(struct knote *kn, long hint); 2585 2586 const struct filterops tmpfsread_filtops = { 2587 .f_flags = FILTEROP_ISFD, 2588 .f_attach = NULL, 2589 .f_detach = filt_tmpfsdetach, 2590 .f_event = filt_tmpfsread, 2591 }; 2592 2593 const struct filterops tmpfswrite_filtops = { 2594 .f_flags = FILTEROP_ISFD, 2595 .f_attach = NULL, 2596 .f_detach = filt_tmpfsdetach, 2597 .f_event = filt_tmpfswrite, 2598 }; 2599 2600 const struct filterops tmpfsvnode_filtops = { 2601 .f_flags = FILTEROP_ISFD, 2602 .f_attach = NULL, 2603 .f_detach = filt_tmpfsdetach, 2604 .f_event = filt_tmpfsvnode, 2605 }; 2606 2607 int 2608 tmpfs_kqfilter(void *v) 2609 { 2610 struct vop_kqfilter_args *ap = v; 2611 struct vnode *vp = ap->a_vp; 2612 struct knote *kn = ap->a_kn; 2613 2614 switch (kn->kn_filter) { 2615 case EVFILT_READ: 2616 kn->kn_fop = &tmpfsread_filtops; 2617 break; 2618 case EVFILT_WRITE: 2619 kn->kn_fop = &tmpfswrite_filtops; 2620 break; 2621 case EVFILT_VNODE: 2622 kn->kn_fop = &tmpfsvnode_filtops; 2623 break; 2624 default: 2625 return (EINVAL); 2626 } 2627 2628 kn->kn_hook = (caddr_t)vp; 2629 2630 klist_insert_locked(&vp->v_selectinfo.si_note, kn); 2631 2632 return (0); 2633 } 2634 2635 void 2636 filt_tmpfsdetach(struct knote *kn) 2637 { 2638 struct vnode *vp = (struct vnode *)kn->kn_hook; 2639 2640 klist_remove_locked(&vp->v_selectinfo.si_note, kn); 2641 } 2642 2643 int 2644 filt_tmpfsread(struct knote *kn, long hint) 2645 { 2646 struct vnode *vp = (struct vnode *)kn->kn_hook; 2647 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 2648 2649 /* 2650 * filesystem is gone, so set the EOF flag and schedule 2651 * the knote for deletion. 2652 */ 2653 if (hint == NOTE_REVOKE) { 2654 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2655 return (1); 2656 } 2657 2658 kn->kn_data = node->tn_size - foffset(kn->kn_fp); 2659 if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { 2660 kn->kn_fflags |= NOTE_EOF; 2661 return (1); 2662 } 2663 2664 if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) 2665 return (1); 2666 2667 return (kn->kn_data != 0); 2668 } 2669 2670 int 2671 filt_tmpfswrite(struct knote *kn, long hint) 2672 { 2673 /* 2674 * filesystem is gone, so set the EOF flag and schedule 2675 * the knote for deletion. 2676 */ 2677 if (hint == NOTE_REVOKE) { 2678 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2679 return (1); 2680 } 2681 2682 kn->kn_data = 0; 2683 return (1); 2684 } 2685 2686 int 2687 filt_tmpfsvnode(struct knote *kn, long hint) 2688 { 2689 if (kn->kn_sfflags & hint) 2690 kn->kn_fflags |= hint; 2691 if (hint == NOTE_REVOKE) { 2692 kn->kn_flags |= EV_EOF; 2693 return (1); 2694 } 2695 return (kn->kn_fflags != 0); 2696 } 2697