1 /* $OpenBSD: tmpfs_vnops.c,v 1.55 2024/05/13 11:17:41 semarie 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(cnp->cn_flags & HASBUF); 696 697 if (vp->v_type == VDIR) { 698 error = EPERM; 699 goto out; 700 } 701 702 dnode = VP_TO_TMPFS_NODE(dvp); 703 node = VP_TO_TMPFS_NODE(vp); 704 705 /* Files marked as immutable or append-only cannot be deleted. */ 706 if (node->tn_flags & (IMMUTABLE | APPEND)) { 707 error = EPERM; 708 goto out; 709 } 710 711 /* 712 * Likewise, files residing on directories marked as append-only cannot 713 * be deleted. 714 */ 715 if (dnode->tn_flags & APPEND) { 716 error = EPERM; 717 goto out; 718 } 719 720 /* Lookup the directory entry (check the cached hint first). */ 721 de = tmpfs_dir_cached(node); 722 if (de == NULL) { 723 de = tmpfs_dir_lookup(dnode, cnp); 724 } 725 726 KASSERT(de && de->td_node == node); 727 728 /* 729 * Remove the entry from the directory (drops the link count) and 730 * destroy it. 731 * Note: the inode referred by it will not be destroyed 732 * until the vnode is reclaimed/recycled. 733 */ 734 tmpfs_dir_detach(dnode, de); 735 tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de); 736 if (node->tn_links > 0) { 737 /* We removed a hard link. */ 738 tmpfs_update(node, TMPFS_NODE_CHANGED); 739 } 740 error = 0; 741 out: 742 pool_put(&namei_pool, cnp->cn_pnbuf); 743 return error; 744 } 745 746 /* 747 * tmpfs_link: create a hard link. 748 */ 749 int 750 tmpfs_link(void *v) 751 { 752 struct vop_link_args /* { 753 struct vnode *a_dvp; 754 struct vnode *a_vp; 755 struct componentname *a_cnp; 756 } */ *ap = v; 757 struct vnode *dvp = ap->a_dvp; 758 struct vnode *vp = ap->a_vp; 759 struct componentname *cnp = ap->a_cnp; 760 tmpfs_node_t *dnode, *node; 761 tmpfs_dirent_t *de; 762 int error; 763 764 KASSERT(VOP_ISLOCKED(dvp)); 765 KASSERT(dvp != vp); 766 767 dnode = VP_TO_TMPFS_DIR(dvp); 768 node = VP_TO_TMPFS_NODE(vp); 769 770 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 771 772 /* Check for maximum number of links limit. */ 773 if (node->tn_links == LINK_MAX) { 774 error = EMLINK; 775 goto out; 776 } 777 KASSERT(node->tn_links < LINK_MAX); 778 779 /* We cannot create links of files marked immutable or append-only. */ 780 if (node->tn_flags & (IMMUTABLE | APPEND)) { 781 error = EPERM; 782 goto out; 783 } 784 785 if (TMPFS_DIRSEQ_FULL(dnode)) { 786 error = ENOSPC; 787 goto out; 788 } 789 790 /* Allocate a new directory entry to represent the inode. */ 791 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), 792 cnp->cn_nameptr, cnp->cn_namelen, &de); 793 if (error) { 794 goto out; 795 } 796 797 /* 798 * Insert the entry into the directory. 799 * It will increase the inode link count. 800 */ 801 tmpfs_dir_attach(dnode, de, node); 802 803 /* Update the timestamps and trigger the event. */ 804 if (node->tn_vnode) { 805 VN_KNOTE(node->tn_vnode, NOTE_LINK); 806 } 807 tmpfs_update(node, TMPFS_NODE_CHANGED); 808 error = 0; 809 out: 810 pool_put(&namei_pool, cnp->cn_pnbuf); 811 VOP_UNLOCK(vp); 812 vput(dvp); 813 return error; 814 } 815 816 int 817 tmpfs_mkdir(void *v) 818 { 819 struct vop_mkdir_args /* { 820 struct vnode *a_dvp; 821 struct vnode **a_vpp; 822 struct componentname *a_cnp; 823 struct vattr *a_vap; 824 } */ *ap = v; 825 struct vnode *dvp = ap->a_dvp; 826 struct vnode **vpp = ap->a_vpp; 827 struct componentname *cnp = ap->a_cnp; 828 struct vattr *vap = ap->a_vap; 829 int error; 830 831 KASSERT(vap->va_type == VDIR); 832 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 833 vput(dvp); 834 return error; 835 } 836 837 int 838 tmpfs_rmdir(void *v) 839 { 840 struct vop_rmdir_args /* { 841 struct vnode *a_dvp; 842 struct vnode *a_vp; 843 struct componentname *a_cnp; 844 } */ *ap = v; 845 struct vnode *dvp = ap->a_dvp; 846 struct vnode *vp = ap->a_vp; 847 struct componentname *cnp = ap->a_cnp; 848 tmpfs_mount_t *tmp = VFS_TO_TMPFS(dvp->v_mount); 849 tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp); 850 tmpfs_node_t *node = VP_TO_TMPFS_DIR(vp); 851 tmpfs_dirent_t *de; 852 int error = 0; 853 854 KASSERT(VOP_ISLOCKED(dvp)); 855 KASSERT(VOP_ISLOCKED(vp)); 856 KASSERT(cnp->cn_flags & HASBUF); 857 858 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' && 859 cnp->cn_nameptr[1] == '.') { 860 error = ENOTEMPTY; 861 goto out; 862 } 863 864 KASSERT(node->tn_spec.tn_dir.tn_parent == dnode); 865 866 /* 867 * Directories with more than two entries ('.' and '..') cannot be 868 * removed. 869 */ 870 if (node->tn_size > 0) { 871 KASSERT(error == 0); 872 TAILQ_FOREACH(de, &node->tn_spec.tn_dir.tn_dir, td_entries) { 873 error = ENOTEMPTY; 874 break; 875 } 876 if (error) 877 goto out; 878 } 879 880 /* Lookup the directory entry (check the cached hint first). */ 881 de = tmpfs_dir_cached(node); 882 if (de == NULL) 883 de = tmpfs_dir_lookup(dnode, cnp); 884 885 KASSERT(de && de->td_node == node); 886 887 /* Check flags to see if we are allowed to remove the directory. */ 888 if (dnode->tn_flags & APPEND || node->tn_flags & (IMMUTABLE | APPEND)) { 889 error = EPERM; 890 goto out; 891 } 892 893 /* Decrement the link count for the virtual '.' entry. */ 894 node->tn_links--; 895 tmpfs_update(node, TMPFS_NODE_STATUSALL); 896 897 /* Detach the directory entry from the directory. */ 898 tmpfs_dir_detach(dnode, de); 899 900 /* Purge the cache for parent. */ 901 cache_purge(dvp); 902 903 /* 904 * Destroy the directory entry. 905 * Note: the inode referred by it will not be destroyed 906 * until the vnode is reclaimed. 907 */ 908 tmpfs_free_dirent(tmp, de); 909 KASSERT(TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir) == NULL); 910 911 KASSERT(node->tn_links == 0); 912 out: 913 pool_put(&namei_pool, cnp->cn_pnbuf); 914 /* Release the nodes. */ 915 vput(dvp); 916 vput(vp); 917 return error; 918 } 919 920 int 921 tmpfs_symlink(void *v) 922 { 923 struct vop_symlink_args /* { 924 struct vnode *a_dvp; 925 struct vnode **a_vpp; 926 struct componentname *a_cnp; 927 struct vattr *a_vap; 928 char *a_target; 929 } */ *ap = v; 930 struct vnode *dvp = ap->a_dvp; 931 struct vnode **vpp = ap->a_vpp; 932 struct componentname *cnp = ap->a_cnp; 933 struct vattr *vap = ap->a_vap; 934 char *target = ap->a_target; 935 int error; 936 937 KASSERT(vap->va_type == 0); 938 vap->va_type = VLNK; 939 940 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, target); 941 vput(dvp); 942 if (error == 0) 943 vput(*vpp); 944 945 return error; 946 } 947 948 int 949 tmpfs_readdir(void *v) 950 { 951 struct vop_readdir_args /* { 952 struct vnode *a_vp; 953 struct uio *a_uio; 954 kauth_cred_t a_cred; 955 int *a_eofflag; 956 } */ *ap = v; 957 struct vnode *vp = ap->a_vp; 958 struct uio *uio = ap->a_uio; 959 int *eofflag = ap->a_eofflag; 960 tmpfs_node_t *node; 961 int error; 962 963 KASSERT(VOP_ISLOCKED(vp)); 964 965 /* This operation only makes sense on directory nodes. */ 966 if (vp->v_type != VDIR) { 967 return ENOTDIR; 968 } 969 node = VP_TO_TMPFS_DIR(vp); 970 /* 971 * Retrieve the directory entries, unless it is being destroyed. 972 */ 973 if (node->tn_links) { 974 error = tmpfs_dir_getdents(node, uio); 975 } else { 976 error = 0; 977 } 978 979 if (eofflag != NULL) { 980 *eofflag = !error && uio->uio_offset == TMPFS_DIRSEQ_EOF; 981 } 982 return error; 983 } 984 985 int 986 tmpfs_readlink(void *v) 987 { 988 struct vop_readlink_args /* { 989 struct vnode *a_vp; 990 struct uio *a_uio; 991 kauth_cred_t a_cred; 992 } */ *ap = v; 993 struct vnode *vp = ap->a_vp; 994 struct uio *uio = ap->a_uio; 995 tmpfs_node_t *node; 996 int error; 997 998 KASSERT(VOP_ISLOCKED(vp)); 999 KASSERT(uio->uio_offset == 0); 1000 KASSERT(vp->v_type == VLNK); 1001 1002 node = VP_TO_TMPFS_NODE(vp); 1003 error = uiomove(node->tn_spec.tn_lnk.tn_link, 1004 MIN((size_t)node->tn_size, uio->uio_resid), uio); 1005 1006 if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) 1007 tmpfs_update(node, TMPFS_NODE_ACCESSED); 1008 1009 return error; 1010 } 1011 1012 int 1013 tmpfs_inactive(void *v) 1014 { 1015 struct vop_inactive_args /* { 1016 struct vnode *a_vp; 1017 int *a_recycle; 1018 } */ *ap = v; 1019 struct vnode *vp = ap->a_vp; 1020 tmpfs_node_t *node; 1021 1022 KASSERT(VOP_ISLOCKED(vp)); 1023 1024 node = VP_TO_TMPFS_NODE(vp); 1025 1026 if (vp->v_type == VREG && tmpfs_uio_cached(node)) 1027 tmpfs_uio_uncache(node); 1028 1029 VOP_UNLOCK(vp); 1030 1031 /* 1032 * If we are done with the node, reclaim it so that it can be reused 1033 * immediately. 1034 */ 1035 if (node->tn_links == 0) 1036 vrecycle(vp, curproc); 1037 1038 return 0; 1039 } 1040 1041 int 1042 tmpfs_reclaim(void *v) 1043 { 1044 struct vop_reclaim_args /* { 1045 struct vnode *a_vp; 1046 } */ *ap = v; 1047 struct vnode *vp = ap->a_vp; 1048 tmpfs_mount_t *tmp = VFS_TO_TMPFS(vp->v_mount); 1049 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1050 int racing; 1051 1052 /* Disassociate inode from vnode. */ 1053 rw_enter_write(&node->tn_nlock); 1054 node->tn_vnode = NULL; 1055 vp->v_data = NULL; 1056 /* Check if tmpfs_vnode_get() is racing with us. */ 1057 racing = TMPFS_NODE_RECLAIMING(node); 1058 rw_exit_write(&node->tn_nlock); 1059 1060 cache_purge(vp); 1061 1062 /* 1063 * If inode is not referenced, i.e. no links, then destroy it. 1064 * Note: if racing - inode is about to get a new vnode, leave it. 1065 */ 1066 if (node->tn_links == 0 && !racing) { 1067 tmpfs_free_node(tmp, node); 1068 } 1069 return 0; 1070 } 1071 1072 int 1073 tmpfs_pathconf(void *v) 1074 { 1075 struct vop_pathconf_args /* { 1076 struct vnode *a_vp; 1077 int a_name; 1078 register_t *a_retval; 1079 } */ *ap = v; 1080 const int name = ap->a_name; 1081 register_t *retval = ap->a_retval; 1082 int error = 0; 1083 1084 switch (name) { 1085 case _PC_LINK_MAX: 1086 *retval = LINK_MAX; 1087 break; 1088 case _PC_NAME_MAX: 1089 *retval = TMPFS_MAXNAMLEN; 1090 break; 1091 case _PC_CHOWN_RESTRICTED: 1092 *retval = 1; 1093 break; 1094 case _PC_NO_TRUNC: 1095 *retval = 1; 1096 break; 1097 case _PC_FILESIZEBITS: 1098 *retval = 64; 1099 break; 1100 case _PC_TIMESTAMP_RESOLUTION: 1101 *retval = 1; 1102 break; 1103 default: 1104 error = EINVAL; 1105 } 1106 return error; 1107 } 1108 1109 int 1110 tmpfs_advlock(void *v) 1111 { 1112 struct vop_advlock_args /* { 1113 struct vnode *a_vp; 1114 void * a_id; 1115 int a_op; 1116 struct flock *a_fl; 1117 int a_flags; 1118 } */ *ap = v; 1119 struct vnode *vp = ap->a_vp; 1120 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1121 1122 return lf_advlock(&node->tn_lockf, node->tn_size, ap->a_id, ap->a_op, 1123 ap->a_fl, ap->a_flags); 1124 } 1125 1126 int 1127 tmpfs_print(void *v) 1128 { 1129 struct vop_print_args /* { 1130 struct vnode *a_vp; 1131 } */ *ap = v; 1132 struct vnode *vp = ap->a_vp; 1133 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 1134 1135 printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n" 1136 "\tmode 0%o, owner %d, group %d, size %lld", 1137 node, node->tn_flags, node->tn_links, node->tn_mode, node->tn_uid, 1138 node->tn_gid, node->tn_size); 1139 #ifdef FIFO 1140 if (vp->v_type == VFIFO) 1141 fifo_printinfo(vp); 1142 #endif 1143 printf("\n"); 1144 return 0; 1145 } 1146 1147 /* a null op */ 1148 int 1149 tmpfs_bwrite(void *v) 1150 { 1151 return 0; 1152 } 1153 1154 int 1155 tmpfs_strategy(void *v) 1156 { 1157 return EOPNOTSUPP; 1158 } 1159 1160 int 1161 tmpfs_ioctl(void *v) 1162 { 1163 return ENOTTY; 1164 } 1165 1166 int 1167 tmpfs_lock(void *v) 1168 { 1169 struct vop_lock_args *ap = v; 1170 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1171 1172 return rrw_enter(&tnp->tn_vlock, ap->a_flags & LK_RWFLAGS); 1173 } 1174 1175 int 1176 tmpfs_unlock(void *v) 1177 { 1178 struct vop_unlock_args *ap = v; 1179 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1180 1181 rrw_exit(&tnp->tn_vlock); 1182 return 0; 1183 } 1184 1185 int 1186 tmpfs_islocked(void *v) 1187 { 1188 struct vop_islocked_args *ap = v; 1189 tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp); 1190 1191 return rrw_status(&tnp->tn_vlock); 1192 } 1193 1194 /* 1195 * tmpfs_rename: rename routine, the hairiest system call, with the 1196 * insane API. 1197 * 1198 * Arguments: fdvp (from-parent vnode), fvp (from-leaf), tdvp (to-parent) 1199 * and tvp (to-leaf), if exists (NULL if not). 1200 * 1201 * => Caller holds a reference on fdvp and fvp, they are unlocked. 1202 * Note: fdvp and fvp can refer to the same object (i.e. when it is root). 1203 * 1204 * => Both tdvp and tvp are referenced and locked. It is our responsibility 1205 * to release the references and unlock them (or destroy). 1206 */ 1207 1208 /* 1209 * First, some forward declarations of subroutines. 1210 */ 1211 1212 int tmpfs_sane_rename(struct vnode *, struct componentname *, 1213 struct vnode *, struct componentname *, struct ucred *, int); 1214 int tmpfs_rename_enter(struct mount *, struct tmpfs_mount *, 1215 struct ucred *, 1216 struct vnode *, struct tmpfs_node *, struct componentname *, 1217 struct tmpfs_dirent **, struct vnode **, 1218 struct vnode *, struct tmpfs_node *, struct componentname *, 1219 struct tmpfs_dirent **, struct vnode **); 1220 int tmpfs_rename_enter_common(struct mount *, struct tmpfs_mount *, 1221 struct ucred *, 1222 struct vnode *, struct tmpfs_node *, 1223 struct componentname *, struct tmpfs_dirent **, struct vnode **, 1224 struct componentname *, struct tmpfs_dirent **, struct vnode **); 1225 int tmpfs_rename_enter_separate(struct mount *, struct tmpfs_mount *, 1226 struct ucred *, 1227 struct vnode *, struct tmpfs_node *, struct componentname *, 1228 struct tmpfs_dirent **, struct vnode **, 1229 struct vnode *, struct tmpfs_node *, struct componentname *, 1230 struct tmpfs_dirent **, struct vnode **); 1231 void tmpfs_rename_exit(struct tmpfs_mount *, 1232 struct vnode *, struct vnode *, struct vnode *, struct vnode *); 1233 int tmpfs_rename_lock_directory(struct vnode *, struct tmpfs_node *); 1234 int tmpfs_rename_genealogy(struct tmpfs_node *, struct tmpfs_node *, 1235 struct tmpfs_node **); 1236 int tmpfs_rename_lock(struct mount *, struct ucred *, int, 1237 struct vnode *, struct tmpfs_node *, struct componentname *, int, 1238 struct tmpfs_dirent **, struct vnode **, 1239 struct vnode *, struct tmpfs_node *, struct componentname *, int, 1240 struct tmpfs_dirent **, struct vnode **); 1241 void tmpfs_rename_attachdetach(struct tmpfs_mount *, 1242 struct vnode *, struct tmpfs_dirent *, struct vnode *, 1243 struct vnode *, struct tmpfs_dirent *, struct vnode *); 1244 int tmpfs_do_remove(struct tmpfs_mount *, struct vnode *, 1245 struct tmpfs_node *, struct tmpfs_dirent *, struct vnode *, struct ucred *); 1246 int tmpfs_rename_check_possible(struct tmpfs_node *, 1247 struct tmpfs_node *, struct tmpfs_node *, struct tmpfs_node *); 1248 int tmpfs_rename_check_permitted(struct ucred *, 1249 struct tmpfs_node *, struct tmpfs_node *, 1250 struct tmpfs_node *, struct tmpfs_node *); 1251 int tmpfs_remove_check_possible(struct tmpfs_node *, 1252 struct tmpfs_node *); 1253 int tmpfs_remove_check_permitted(struct ucred *, 1254 struct tmpfs_node *, struct tmpfs_node *); 1255 int tmpfs_check_sticky(struct ucred *, 1256 struct tmpfs_node *, struct tmpfs_node *); 1257 void tmpfs_rename_cache_purge(struct vnode *, struct vnode *, struct vnode *, 1258 struct vnode *); 1259 void tmpfs_rename_abort(void *); 1260 1261 int 1262 tmpfs_rename(void *v) 1263 { 1264 struct vop_rename_args /* { 1265 struct vnode *a_fdvp; 1266 struct vnode *a_fvp; 1267 struct componentname *a_fcnp; 1268 struct vnode *a_tdvp; 1269 struct vnode *a_tvp; 1270 struct componentname *a_tcnp; 1271 } */ *ap = v; 1272 struct vnode *fdvp = ap->a_fdvp; 1273 struct vnode *fvp = ap->a_fvp; 1274 struct componentname *fcnp = ap->a_fcnp; 1275 struct vnode *tdvp = ap->a_tdvp; 1276 struct vnode *tvp = ap->a_tvp; 1277 struct componentname *tcnp = ap->a_tcnp; 1278 struct ucred *cred; 1279 int error; 1280 1281 KASSERT(fdvp != NULL); 1282 KASSERT(fvp != NULL); 1283 KASSERT(fcnp != NULL); 1284 KASSERT(fcnp->cn_nameptr != NULL); 1285 KASSERT(tdvp != NULL); 1286 KASSERT(tcnp != NULL); 1287 KASSERT(fcnp->cn_nameptr != NULL); 1288 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1289 /* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */ 1290 KASSERT(fdvp->v_type == VDIR); 1291 KASSERT(tdvp->v_type == VDIR); 1292 KASSERT(fcnp->cn_flags & HASBUF); 1293 KASSERT(tcnp->cn_flags & HASBUF); 1294 1295 cred = fcnp->cn_cred; 1296 KASSERT(tcnp->cn_cred == cred); 1297 1298 /* 1299 * Check for cross-device rename. 1300 * Also don't allow renames of mount points. 1301 */ 1302 if (fvp->v_mount != tdvp->v_mount || 1303 fdvp->v_mount != fvp->v_mount || 1304 (tvp != NULL && (fvp->v_mount != tvp->v_mount))) { 1305 tmpfs_rename_abort(v); 1306 return EXDEV; 1307 } 1308 1309 /* 1310 * Can't check the locks on these until we know they're on 1311 * the same FS, as not all FS do locking the same way. 1312 */ 1313 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1314 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1315 1316 /* 1317 * Reject renaming '.' and '..'. 1318 */ 1319 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1320 (fcnp->cn_namelen == 2 && fcnp->cn_nameptr[0] == '.' && 1321 fcnp->cn_nameptr[1] == '.')) { 1322 tmpfs_rename_abort(v); 1323 return EINVAL; 1324 } 1325 1326 /* 1327 * Sanitize our world from the VFS insanity. Unlock the target 1328 * directory and node, which are locked. Release the children, 1329 * which are referenced. Check for rename("x", "y/."), which 1330 * it is our responsibility to reject, not the caller's. (But 1331 * the caller does reject rename("x/.", "y"). Go figure.) 1332 */ 1333 1334 VOP_UNLOCK(tdvp); 1335 if ((tvp != NULL) && (tvp != tdvp)) 1336 VOP_UNLOCK(tvp); 1337 1338 vrele(fvp); 1339 if (tvp != NULL) 1340 vrele(tvp); 1341 1342 if (tvp == tdvp) { 1343 error = EINVAL; 1344 goto out; 1345 } 1346 1347 error = tmpfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, 0); 1348 1349 out: /* 1350 * All done, whether with success or failure. Release the 1351 * directory nodes now, as the caller expects from the VFS 1352 * protocol. 1353 */ 1354 vrele(fdvp); 1355 vrele(tdvp); 1356 1357 return error; 1358 } 1359 1360 /* 1361 * tmpfs_sane_rename: rename routine, the hairiest system call, with 1362 * the sane API. 1363 * 1364 * Arguments: 1365 * 1366 * . fdvp (from directory vnode), 1367 * . fcnp (from component name), 1368 * . tdvp (to directory vnode), and 1369 * . tcnp (to component name). 1370 * 1371 * fdvp and tdvp must be referenced and unlocked. 1372 */ 1373 int 1374 tmpfs_sane_rename(struct vnode *fdvp, struct componentname *fcnp, 1375 struct vnode *tdvp, struct componentname *tcnp, struct ucred *cred, 1376 int posixly_correct) 1377 { 1378 struct mount *mount; 1379 struct tmpfs_mount *tmpfs; 1380 struct tmpfs_node *fdnode, *tdnode; 1381 struct tmpfs_dirent *fde, *tde; 1382 struct vnode *fvp, *tvp; 1383 char *newname; 1384 int error; 1385 1386 KASSERT(fdvp != NULL); 1387 KASSERT(fcnp != NULL); 1388 KASSERT(tdvp != NULL); 1389 KASSERT(tcnp != NULL); 1390 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1391 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 1392 KASSERT(fdvp->v_type == VDIR); 1393 KASSERT(tdvp->v_type == VDIR); 1394 KASSERT(fdvp->v_mount == tdvp->v_mount); 1395 KASSERT((fcnp->cn_flags & ISDOTDOT) == 0); 1396 KASSERT((tcnp->cn_flags & ISDOTDOT) == 0); 1397 KASSERT((fcnp->cn_namelen != 1) || (fcnp->cn_nameptr[0] != '.')); 1398 KASSERT((tcnp->cn_namelen != 1) || (tcnp->cn_nameptr[0] != '.')); 1399 KASSERT((fcnp->cn_namelen != 2) || (fcnp->cn_nameptr[0] != '.') || 1400 (fcnp->cn_nameptr[1] != '.')); 1401 KASSERT((tcnp->cn_namelen != 2) || (tcnp->cn_nameptr[0] != '.') || 1402 (tcnp->cn_nameptr[1] != '.')); 1403 1404 /* 1405 * Pull out the tmpfs data structures. 1406 */ 1407 fdnode = VP_TO_TMPFS_NODE(fdvp); 1408 tdnode = VP_TO_TMPFS_NODE(tdvp); 1409 KASSERT(fdnode != NULL); 1410 KASSERT(tdnode != NULL); 1411 KASSERT(fdnode->tn_vnode == fdvp); 1412 KASSERT(tdnode->tn_vnode == tdvp); 1413 KASSERT(fdnode->tn_type == VDIR); 1414 KASSERT(tdnode->tn_type == VDIR); 1415 1416 mount = fdvp->v_mount; 1417 KASSERT(mount != NULL); 1418 KASSERT(mount == tdvp->v_mount); 1419 /* XXX How can we be sure this stays true? (Not that you're 1420 * likely to mount a tmpfs read-only...) */ 1421 KASSERT((mount->mnt_flag & MNT_RDONLY) == 0); 1422 tmpfs = VFS_TO_TMPFS(mount); 1423 KASSERT(tmpfs != NULL); 1424 1425 /* 1426 * Decide whether we need a new name, and allocate memory for 1427 * it if so. Do this before locking anything or taking 1428 * destructive actions so that we can back out safely and sleep 1429 * safely. XXX Is sleeping an issue here? Can this just be 1430 * moved into tmpfs_rename_attachdetach? 1431 */ 1432 if (tmpfs_strname_neqlen(fcnp, tcnp)) { 1433 newname = tmpfs_strname_alloc(tmpfs, tcnp->cn_namelen); 1434 if (newname == NULL) { 1435 error = ENOSPC; 1436 goto out_unlocked; 1437 } 1438 } else { 1439 newname = NULL; 1440 } 1441 1442 /* 1443 * Lock and look up everything. GCC is not very clever. 1444 */ 1445 fde = tde = NULL; 1446 fvp = tvp = NULL; 1447 error = tmpfs_rename_enter(mount, tmpfs, cred, 1448 fdvp, fdnode, fcnp, &fde, &fvp, 1449 tdvp, tdnode, tcnp, &tde, &tvp); 1450 if (error) 1451 goto out_unlocked; 1452 1453 /* 1454 * Check that everything is locked and looks right. 1455 */ 1456 KASSERT(fde != NULL); 1457 KASSERT(fvp != NULL); 1458 KASSERT(fde->td_node != NULL); 1459 KASSERT(fde->td_node->tn_vnode == fvp); 1460 KASSERT(fde->td_node->tn_type == fvp->v_type); 1461 KASSERT((tde == NULL) == (tvp == NULL)); 1462 KASSERT((tde == NULL) || (tde->td_node != NULL)); 1463 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp)); 1464 KASSERT((tde == NULL) || (tde->td_node->tn_type == tvp->v_type)); 1465 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1466 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1467 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1468 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1469 1470 /* 1471 * If the source and destination are the same object, we need 1472 * only at most delete the source entry. 1473 */ 1474 if (fvp == tvp) { 1475 KASSERT(tvp != NULL); 1476 if (fde->td_node->tn_type == VDIR) { 1477 /* XXX How can this possibly happen? */ 1478 error = EINVAL; 1479 goto out_locked; 1480 } 1481 if (!posixly_correct && (fde != tde)) { 1482 /* XXX Doesn't work because of locking. 1483 * error = VOP_REMOVE(fdvp, fvp); 1484 */ 1485 error = tmpfs_do_remove(tmpfs, fdvp, fdnode, fde, fvp, 1486 cred); 1487 if (error) 1488 goto out_locked; 1489 } 1490 goto success; 1491 } 1492 KASSERT(fde != tde); 1493 KASSERT(fvp != tvp); 1494 1495 /* 1496 * If the target exists, refuse to rename a directory over a 1497 * non-directory or vice versa, or to clobber a non-empty 1498 * directory. 1499 */ 1500 if (tvp != NULL) { 1501 KASSERT(tde != NULL); 1502 KASSERT(tde->td_node != NULL); 1503 if (fvp->v_type == VDIR && tvp->v_type == VDIR) 1504 error = ((tde->td_node->tn_size > 0)? ENOTEMPTY : 0); 1505 else if (fvp->v_type == VDIR && tvp->v_type != VDIR) 1506 error = ENOTDIR; 1507 else if (fvp->v_type != VDIR && tvp->v_type == VDIR) 1508 error = EISDIR; 1509 else 1510 error = 0; 1511 if (error) 1512 goto out_locked; 1513 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR)); 1514 } 1515 1516 /* 1517 * Authorize the rename. 1518 */ 1519 error = tmpfs_rename_check_possible(fdnode, fde->td_node, 1520 tdnode, (tde? tde->td_node : NULL)); 1521 if (error) 1522 goto out_locked; 1523 error = tmpfs_rename_check_permitted(cred, fdnode, fde->td_node, 1524 tdnode, (tde? tde->td_node : NULL)); 1525 if (error) 1526 goto out_locked; 1527 1528 /* 1529 * Everything is hunky-dory. Shuffle the directory entries. 1530 */ 1531 tmpfs_rename_attachdetach(tmpfs, fdvp, fde, fvp, tdvp, tde, tvp); 1532 1533 /* 1534 * Update the directory entry's name necessary, and flag 1535 * metadata updates. A memory allocation failure here is not 1536 * OK because we've already committed some changes that we 1537 * can't back out at this point, and we have things locked so 1538 * we can't sleep, hence the early allocation above. 1539 */ 1540 if (newname != NULL) { 1541 KASSERT(tcnp->cn_namelen <= TMPFS_MAXNAMLEN); 1542 1543 tmpfs_strname_free(tmpfs, fde->td_name, fde->td_namelen); 1544 fde->td_namelen = (uint16_t)tcnp->cn_namelen; 1545 (void)memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen); 1546 /* Commit newname and don't free it on the way out. */ 1547 fde->td_name = newname; 1548 newname = NULL; 1549 1550 tmpfs_update(fde->td_node, TMPFS_NODE_CHANGED); 1551 tmpfs_update(tdnode, TMPFS_NODE_MODIFIED); 1552 } 1553 1554 success: 1555 VN_KNOTE(fvp, NOTE_RENAME); 1556 tmpfs_rename_cache_purge(fdvp, fvp, tdvp, tvp); 1557 error = 0; 1558 1559 out_locked: 1560 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp); 1561 1562 out_unlocked: 1563 /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 1564 /* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 1565 /* KASSERT((fvp == NULL) || (VOP_ISLOCKED(fvp) != LK_EXCLUSIVE)); */ 1566 /* KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */ 1567 1568 if (newname != NULL) 1569 tmpfs_strname_free(tmpfs, newname, tcnp->cn_namelen); 1570 1571 return error; 1572 } 1573 1574 /* 1575 * Look up fcnp in fdnode/fdvp and store its directory entry in fde_ret 1576 * and the associated vnode in fvp_ret; fail if not found. Look up 1577 * tcnp in tdnode/tdvp and store its directory entry in tde_ret and the 1578 * associated vnode in tvp_ret; store null instead if not found. Fail 1579 * if anything has been mounted on any of the nodes involved. 1580 * 1581 * fdvp and tdvp must be referenced. 1582 * 1583 * On entry, nothing is locked. 1584 * 1585 * On success, everything is locked, and *fvp_ret, and *tvp_ret if 1586 * nonnull, are referenced. The only pairs of vnodes that may be 1587 * identical are {fdvp, tdvp} and {fvp, tvp}. 1588 * 1589 * On failure, everything remains as was. 1590 * 1591 * Locking everything including the source and target nodes is 1592 * necessary to make sure that, e.g., link count updates are OK. The 1593 * locking order is, in general, ancestor-first, matching the order you 1594 * need to use to look up a descendant anyway. 1595 */ 1596 int 1597 tmpfs_rename_enter(struct mount *mount, struct tmpfs_mount *tmpfs, 1598 struct ucred *cred, 1599 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp, 1600 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1601 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp, 1602 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1603 { 1604 int error; 1605 1606 KASSERT(mount != NULL); 1607 KASSERT(tmpfs != NULL); 1608 KASSERT(fdvp != NULL); 1609 KASSERT(fdnode != NULL); 1610 KASSERT(fcnp != NULL); 1611 KASSERT(fde_ret != NULL); 1612 KASSERT(fvp_ret != NULL); 1613 KASSERT(tdvp != NULL); 1614 KASSERT(tdnode != NULL); 1615 KASSERT(tcnp != NULL); 1616 KASSERT(tde_ret != NULL); 1617 KASSERT(tvp_ret != NULL); 1618 KASSERT(fdnode->tn_vnode == fdvp); 1619 KASSERT(tdnode->tn_vnode == tdvp); 1620 KASSERT(fdnode->tn_type == VDIR); 1621 KASSERT(tdnode->tn_type == VDIR); 1622 1623 if (fdvp == tdvp) { 1624 KASSERT(fdnode == tdnode); 1625 error = tmpfs_rename_enter_common(mount, tmpfs, cred, fdvp, 1626 fdnode, fcnp, fde_ret, fvp_ret, tcnp, tde_ret, tvp_ret); 1627 } else { 1628 KASSERT(fdnode != tdnode); 1629 error = tmpfs_rename_enter_separate(mount, tmpfs, cred, 1630 fdvp, fdnode, fcnp, fde_ret, fvp_ret, 1631 tdvp, tdnode, tcnp, tde_ret, tvp_ret); 1632 } 1633 1634 if (error) 1635 return error; 1636 1637 KASSERT(*fde_ret != NULL); 1638 KASSERT(*fvp_ret != NULL); 1639 KASSERT((*tde_ret == NULL) == (*tvp_ret == NULL)); 1640 KASSERT((*tde_ret == NULL) || ((*tde_ret)->td_node != NULL)); 1641 KASSERT((*tde_ret == NULL) || 1642 ((*tde_ret)->td_node->tn_vnode == *tvp_ret)); 1643 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1644 KASSERT(VOP_ISLOCKED(*fvp_ret) == LK_EXCLUSIVE); 1645 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1646 KASSERT((*tvp_ret == NULL) || 1647 (VOP_ISLOCKED(*tvp_ret) == LK_EXCLUSIVE)); 1648 KASSERT(*fvp_ret != fdvp); 1649 KASSERT(*fvp_ret != tdvp); 1650 KASSERT(*tvp_ret != fdvp); 1651 KASSERT(*tvp_ret != tdvp); 1652 return 0; 1653 } 1654 1655 /* 1656 * Lock and look up with a common source/target directory. 1657 */ 1658 int 1659 tmpfs_rename_enter_common(struct mount *mount, struct tmpfs_mount *tmpfs, 1660 struct ucred *cred, 1661 struct vnode *dvp, struct tmpfs_node *dnode, 1662 struct componentname *fcnp, 1663 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1664 struct componentname *tcnp, 1665 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1666 { 1667 struct tmpfs_dirent *fde, *tde; 1668 struct vnode *fvp, *tvp; 1669 int error; 1670 1671 error = tmpfs_rename_lock_directory(dvp, dnode); 1672 if (error) 1673 goto fail0; 1674 1675 /* Did we lose a race with mount? */ 1676 if (dvp->v_mountedhere != NULL) { 1677 error = EBUSY; 1678 goto fail1; 1679 } 1680 1681 /* Make sure the caller may read the directory. */ 1682 error = VOP_ACCESS(dvp, VEXEC, cred, curproc); 1683 if (error) 1684 goto fail1; 1685 1686 /* 1687 * The order in which we lock the source and target nodes is 1688 * irrelevant because there can only be one rename on this 1689 * directory in flight at a time, and we have it locked. 1690 */ 1691 1692 fde = tmpfs_dir_lookup(dnode, fcnp); 1693 if (fde == NULL) { 1694 error = ENOENT; 1695 goto fail1; 1696 } 1697 1698 KASSERT(fde->td_node != NULL); 1699 /* We ruled out `.' earlier. */ 1700 KASSERT(fde->td_node != dnode); 1701 /* We ruled out `..' earlier. */ 1702 KASSERT(fde->td_node != dnode->tn_spec.tn_dir.tn_parent); 1703 rw_enter_write(&fde->td_node->tn_nlock); 1704 error = tmpfs_vnode_get(mount, fde->td_node, &fvp); 1705 if (error) 1706 goto fail1; 1707 KASSERT(fvp != NULL); 1708 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1709 KASSERT(fvp != dvp); 1710 KASSERT(fvp->v_mount == mount); 1711 1712 /* Refuse to rename a mount point. */ 1713 if ((fvp->v_type == VDIR) && (fvp->v_mountedhere != NULL)) { 1714 error = EBUSY; 1715 goto fail2; 1716 } 1717 1718 tde = tmpfs_dir_lookup(dnode, tcnp); 1719 if (tde == NULL) { 1720 tvp = NULL; 1721 } else { 1722 KASSERT(tde->td_node != NULL); 1723 /* We ruled out `.' earlier. */ 1724 KASSERT(tde->td_node != dnode); 1725 /* We ruled out `..' earlier. */ 1726 KASSERT(tde->td_node != dnode->tn_spec.tn_dir.tn_parent); 1727 if (tde->td_node != fde->td_node) { 1728 rw_enter_write(&tde->td_node->tn_nlock); 1729 error = tmpfs_vnode_get(mount, tde->td_node, &tvp); 1730 if (error) 1731 goto fail2; 1732 KASSERT(tvp->v_mount == mount); 1733 /* Refuse to rename over a mount point. */ 1734 if ((tvp->v_type == VDIR) && 1735 (tvp->v_mountedhere != NULL)) { 1736 error = EBUSY; 1737 goto fail3; 1738 } 1739 } else { 1740 tvp = fvp; 1741 vref(tvp); 1742 } 1743 KASSERT(tvp != NULL); 1744 KASSERT(VOP_ISLOCKED(tvp) == LK_EXCLUSIVE); 1745 } 1746 KASSERT(tvp != dvp); 1747 1748 *fde_ret = fde; 1749 *fvp_ret = fvp; 1750 *tde_ret = tde; 1751 *tvp_ret = tvp; 1752 return 0; 1753 1754 fail3: if (tvp != NULL) { 1755 if (tvp != fvp) 1756 vput(tvp); 1757 else 1758 vrele(tvp); 1759 } 1760 1761 fail2: vput(fvp); 1762 fail1: VOP_UNLOCK(dvp); 1763 fail0: return error; 1764 } 1765 1766 /* 1767 * Lock and look up with separate source and target directories. 1768 */ 1769 int 1770 tmpfs_rename_enter_separate(struct mount *mount, struct tmpfs_mount *tmpfs, 1771 struct ucred *cred, 1772 struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp, 1773 struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret, 1774 struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp, 1775 struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret) 1776 { 1777 struct tmpfs_node *intermediate_node; 1778 struct tmpfs_dirent *fde, *tde; 1779 struct vnode *fvp, *tvp; 1780 int error; 1781 1782 KASSERT(fdvp != tdvp); 1783 KASSERT(fdnode != tdnode); 1784 1785 #if 0 /* XXX */ 1786 mutex_enter(&tmpfs->tm_rename_lock); 1787 #endif 1788 1789 error = tmpfs_rename_genealogy(fdnode, tdnode, &intermediate_node); 1790 if (error) 1791 goto fail; 1792 1793 /* 1794 * intermediate_node == NULL means fdnode is not an ancestor of 1795 * tdnode. 1796 */ 1797 if (intermediate_node == NULL) 1798 error = tmpfs_rename_lock(mount, cred, ENOTEMPTY, 1799 tdvp, tdnode, tcnp, 1, &tde, &tvp, 1800 fdvp, fdnode, fcnp, 0, &fde, &fvp); 1801 else 1802 error = tmpfs_rename_lock(mount, cred, EINVAL, 1803 fdvp, fdnode, fcnp, 0, &fde, &fvp, 1804 tdvp, tdnode, tcnp, 1, &tde, &tvp); 1805 if (error) 1806 goto fail; 1807 1808 KASSERT(fde != NULL); 1809 KASSERT(fde->td_node != NULL); 1810 1811 /* 1812 * Reject rename("foo/bar", "foo/bar/baz/quux/zot"). 1813 */ 1814 if (fde->td_node == intermediate_node) { 1815 tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp); 1816 return EINVAL; 1817 } 1818 1819 *fde_ret = fde; 1820 *fvp_ret = fvp; 1821 *tde_ret = tde; 1822 *tvp_ret = tvp; 1823 return 0; 1824 1825 fail: 1826 #if 0 /* XXX */ 1827 mutex_exit(&tmpfs->tm_rename_lock); 1828 #endif 1829 return error; 1830 } 1831 1832 /* 1833 * Unlock everything we locked for rename. 1834 * 1835 * fdvp and tdvp must be referenced. 1836 * 1837 * On entry, everything is locked, and fvp and tvp referenced. 1838 * 1839 * On exit, everything is unlocked, and fvp and tvp are released. 1840 */ 1841 void 1842 tmpfs_rename_exit(struct tmpfs_mount *tmpfs, 1843 struct vnode *fdvp, struct vnode *fvp, 1844 struct vnode *tdvp, struct vnode *tvp) 1845 { 1846 1847 KASSERT(tmpfs != NULL); 1848 KASSERT(fdvp != NULL); 1849 KASSERT(fvp != NULL); 1850 KASSERT(fdvp != fvp); 1851 KASSERT(fdvp != tvp); 1852 KASSERT(tdvp != tvp); 1853 KASSERT(tdvp != fvp); 1854 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1855 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1856 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1857 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1858 1859 if (tvp != NULL) { 1860 if (tvp != fvp) 1861 vput(tvp); 1862 else 1863 vrele(tvp); 1864 } 1865 VOP_UNLOCK(tdvp); 1866 vput(fvp); 1867 if (fdvp != tdvp) 1868 VOP_UNLOCK(fdvp); 1869 1870 #if 0 /* XXX */ 1871 if (fdvp != tdvp) 1872 mutex_exit(&tmpfs->tm_rename_lock); 1873 #endif 1874 } 1875 1876 /* 1877 * Lock a directory, but fail if it has been rmdir'd. 1878 * 1879 * vp must be referenced. 1880 */ 1881 int 1882 tmpfs_rename_lock_directory(struct vnode *vp, struct tmpfs_node *node) 1883 { 1884 1885 KASSERT(vp != NULL); 1886 KASSERT(node != NULL); 1887 KASSERT(node->tn_vnode == vp); 1888 KASSERT(node->tn_type == VDIR); 1889 1890 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1891 if (node->tn_spec.tn_dir.tn_parent == NULL) { 1892 VOP_UNLOCK(vp); 1893 return ENOENT; 1894 } 1895 1896 return 0; 1897 } 1898 1899 /* 1900 * Analyze the genealogy of the source and target nodes. 1901 * 1902 * On success, stores in *intermediate_node_ret either the child of 1903 * fdnode of which tdnode is a descendant, or null if tdnode is not a 1904 * descendant of fdnode at all. 1905 * 1906 * fdnode and tdnode must be unlocked and referenced. The file 1907 * system's rename lock must also be held, to exclude concurrent 1908 * changes to the file system's genealogy other than rmdir. 1909 * 1910 * XXX This causes an extra lock/unlock of tdnode in the case when 1911 * we're just about to lock it again before locking anything else. 1912 * However, changing that requires reorganizing the code to make it 1913 * even more horrifically obscure. 1914 */ 1915 int 1916 tmpfs_rename_genealogy(struct tmpfs_node *fdnode, struct tmpfs_node *tdnode, 1917 struct tmpfs_node **intermediate_node_ret) 1918 { 1919 struct tmpfs_node *node = tdnode, *parent; 1920 int error; 1921 1922 KASSERT(fdnode != NULL); 1923 KASSERT(tdnode != NULL); 1924 KASSERT(fdnode != tdnode); 1925 KASSERT(intermediate_node_ret != NULL); 1926 1927 KASSERT(fdnode->tn_vnode != NULL); 1928 KASSERT(tdnode->tn_vnode != NULL); 1929 KASSERT(fdnode->tn_type == VDIR); 1930 KASSERT(tdnode->tn_type == VDIR); 1931 1932 /* 1933 * We need to provisionally lock tdnode->tn_vnode to keep rmdir 1934 * from deleting it -- or any ancestor -- at an inopportune 1935 * moment. 1936 */ 1937 error = tmpfs_rename_lock_directory(tdnode->tn_vnode, tdnode); 1938 if (error) 1939 return error; 1940 1941 for (;;) { 1942 parent = node->tn_spec.tn_dir.tn_parent; 1943 KASSERT(parent != NULL); 1944 KASSERT(parent->tn_type == VDIR); 1945 1946 /* Did we hit the root without finding fdnode? */ 1947 if (parent == node) { 1948 *intermediate_node_ret = NULL; 1949 break; 1950 } 1951 1952 /* Did we find that fdnode is an ancestor? */ 1953 if (parent == fdnode) { 1954 *intermediate_node_ret = node; 1955 break; 1956 } 1957 1958 /* Neither -- keep ascending the family tree. */ 1959 node = parent; 1960 } 1961 1962 VOP_UNLOCK(tdnode->tn_vnode); 1963 return 0; 1964 } 1965 1966 /* 1967 * Lock directories a and b, which must be distinct, and look up and 1968 * lock nodes a and b. Do a first and then b. Directory b may not be 1969 * an ancestor of directory a, although directory a may be an ancestor 1970 * of directory b. Fail with overlap_error if node a is directory b. 1971 * Neither componentname may be `.' or `..'. 1972 * 1973 * a_dvp and b_dvp must be referenced. 1974 * 1975 * On entry, a_dvp and b_dvp are unlocked. 1976 * 1977 * On success, 1978 * . a_dvp and b_dvp are locked, 1979 * . *a_dirent_ret is filled with a directory entry whose node is 1980 * locked and referenced, 1981 * . *b_vp_ret is filled with the corresponding vnode, 1982 * . *b_dirent_ret is filled either with null or with a directory entry 1983 * whose node is locked and referenced, 1984 * . *b_vp is filled either with null or with the corresponding vnode, 1985 * and 1986 * . the only pair of vnodes that may be identical is a_vp and b_vp. 1987 * 1988 * On failure, a_dvp and b_dvp are left unlocked, and *a_dirent_ret, 1989 * *a_vp, *b_dirent_ret, and *b_vp are left alone. 1990 */ 1991 int 1992 tmpfs_rename_lock(struct mount *mount, struct ucred *cred, int overlap_error, 1993 struct vnode *a_dvp, struct tmpfs_node *a_dnode, 1994 struct componentname *a_cnp, int a_missing_ok, 1995 struct tmpfs_dirent **a_dirent_ret, struct vnode **a_vp_ret, 1996 struct vnode *b_dvp, struct tmpfs_node *b_dnode, 1997 struct componentname *b_cnp, int b_missing_ok, 1998 struct tmpfs_dirent **b_dirent_ret, struct vnode **b_vp_ret) 1999 { 2000 struct tmpfs_dirent *a_dirent, *b_dirent; 2001 struct vnode *a_vp, *b_vp; 2002 int error; 2003 2004 KASSERT(a_dvp != NULL); 2005 KASSERT(a_dnode != NULL); 2006 KASSERT(a_cnp != NULL); 2007 KASSERT(a_dirent_ret != NULL); 2008 KASSERT(a_vp_ret != NULL); 2009 KASSERT(b_dvp != NULL); 2010 KASSERT(b_dnode != NULL); 2011 KASSERT(b_cnp != NULL); 2012 KASSERT(b_dirent_ret != NULL); 2013 KASSERT(b_vp_ret != NULL); 2014 KASSERT(a_dvp != b_dvp); 2015 KASSERT(a_dnode != b_dnode); 2016 KASSERT(a_dnode->tn_vnode == a_dvp); 2017 KASSERT(b_dnode->tn_vnode == b_dvp); 2018 KASSERT(a_dnode->tn_type == VDIR); 2019 KASSERT(b_dnode->tn_type == VDIR); 2020 KASSERT(a_missing_ok != b_missing_ok); 2021 2022 error = tmpfs_rename_lock_directory(a_dvp, a_dnode); 2023 if (error) 2024 goto fail0; 2025 2026 /* Did we lose a race with mount? */ 2027 if (a_dvp->v_mountedhere != NULL) { 2028 error = EBUSY; 2029 goto fail1; 2030 } 2031 2032 /* Make sure the caller may read the directory. */ 2033 error = VOP_ACCESS(a_dvp, VEXEC, cred, curproc); 2034 if (error) 2035 goto fail1; 2036 2037 a_dirent = tmpfs_dir_lookup(a_dnode, a_cnp); 2038 if (a_dirent != NULL) { 2039 KASSERT(a_dirent->td_node != NULL); 2040 /* We ruled out `.' earlier. */ 2041 KASSERT(a_dirent->td_node != a_dnode); 2042 /* We ruled out `..' earlier. */ 2043 KASSERT(a_dirent->td_node != 2044 a_dnode->tn_spec.tn_dir.tn_parent); 2045 if (a_dirent->td_node == b_dnode) { 2046 error = overlap_error; 2047 goto fail1; 2048 } 2049 rw_enter_write(&a_dirent->td_node->tn_nlock); 2050 error = tmpfs_vnode_get(mount, a_dirent->td_node, &a_vp); 2051 if (error) 2052 goto fail1; 2053 KASSERT(a_vp->v_mount == mount); 2054 /* Refuse to rename (over) a mount point. */ 2055 if ((a_vp->v_type == VDIR) && (a_vp->v_mountedhere != NULL)) { 2056 error = EBUSY; 2057 goto fail2; 2058 } 2059 } else if (!a_missing_ok) { 2060 error = ENOENT; 2061 goto fail1; 2062 } else { 2063 a_vp = NULL; 2064 } 2065 KASSERT(a_vp != a_dvp); 2066 KASSERT(a_vp != b_dvp); 2067 2068 error = tmpfs_rename_lock_directory(b_dvp, b_dnode); 2069 if (error) 2070 goto fail2; 2071 2072 /* Did we lose a race with mount? */ 2073 if (b_dvp->v_mountedhere != NULL) { 2074 error = EBUSY; 2075 goto fail3; 2076 } 2077 2078 /* Make sure the caller may read the directory. */ 2079 error = VOP_ACCESS(b_dvp, VEXEC, cred, curproc); 2080 if (error) 2081 goto fail3; 2082 2083 b_dirent = tmpfs_dir_lookup(b_dnode, b_cnp); 2084 if (b_dirent != NULL) { 2085 KASSERT(b_dirent->td_node != NULL); 2086 /* We ruled out `.' earlier. */ 2087 KASSERT(b_dirent->td_node != b_dnode); 2088 /* We ruled out `..' earlier. */ 2089 KASSERT(b_dirent->td_node != 2090 b_dnode->tn_spec.tn_dir.tn_parent); 2091 /* b is not an ancestor of a. */ 2092 KASSERT(b_dirent->td_node != a_dnode); 2093 /* But the source and target nodes might be the same. */ 2094 if ((a_dirent == NULL) || 2095 (a_dirent->td_node != b_dirent->td_node)) { 2096 rw_enter_write(&b_dirent->td_node->tn_nlock); 2097 error = tmpfs_vnode_get(mount, b_dirent->td_node, 2098 &b_vp); 2099 if (error) 2100 goto fail3; 2101 KASSERT(b_vp->v_mount == mount); 2102 KASSERT(a_vp != b_vp); 2103 /* Refuse to rename (over) a mount point. */ 2104 if ((b_vp->v_type == VDIR) && 2105 (b_vp->v_mountedhere != NULL)) { 2106 error = EBUSY; 2107 goto fail4; 2108 } 2109 } else { 2110 b_vp = a_vp; 2111 vref(b_vp); 2112 } 2113 } else if (!b_missing_ok) { 2114 error = ENOENT; 2115 goto fail3; 2116 } else { 2117 b_vp = NULL; 2118 } 2119 KASSERT(b_vp != a_dvp); 2120 KASSERT(b_vp != b_dvp); 2121 2122 KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE); 2123 KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE); 2124 KASSERT(a_missing_ok || (a_dirent != NULL)); 2125 KASSERT(a_missing_ok || (a_dirent->td_node != NULL)); 2126 KASSERT(b_missing_ok || (b_dirent != NULL)); 2127 KASSERT(b_missing_ok || (b_dirent->td_node != NULL)); 2128 KASSERT((a_dirent == NULL) || (a_dirent->td_node != NULL)); 2129 KASSERT((a_dirent == NULL) || (a_dirent->td_node->tn_vnode == a_vp)); 2130 KASSERT((b_dirent == NULL) || (b_dirent->td_node != NULL)); 2131 KASSERT((b_dirent == NULL) || (b_dirent->td_node->tn_vnode == b_vp)); 2132 KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE)); 2133 KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE)); 2134 2135 *a_dirent_ret = a_dirent; 2136 *b_dirent_ret = b_dirent; 2137 *a_vp_ret = a_vp; 2138 *b_vp_ret = b_vp; 2139 return 0; 2140 2141 fail4: if (b_vp != NULL) { 2142 KASSERT(VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE); 2143 if (b_vp != a_vp) 2144 vput(b_vp); 2145 else 2146 vrele(a_vp); 2147 } 2148 2149 fail3: KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE); 2150 VOP_UNLOCK(b_dvp); 2151 2152 fail2: if (a_vp != NULL) { 2153 KASSERT(VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE); 2154 vput(a_vp); 2155 } 2156 2157 fail1: KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE); 2158 VOP_UNLOCK(a_dvp); 2159 2160 fail0: /* KASSERT(VOP_ISLOCKED(a_dvp) != LK_EXCLUSIVE); */ 2161 /* KASSERT(VOP_ISLOCKED(b_dvp) != LK_EXCLUSIVE); */ 2162 /* KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) != LK_EXCLUSIVE)); */ 2163 /* KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) != LK_EXCLUSIVE)); */ 2164 return error; 2165 } 2166 2167 /* 2168 * Shuffle the directory entries to move fvp from the directory fdvp 2169 * into the directory tdvp. fde is fvp's directory entry in fdvp. If 2170 * we are overwriting a target node, it is tvp, and tde is its 2171 * directory entry in tdvp. 2172 * 2173 * fdvp, fvp, tdvp, and tvp must all be locked and referenced. 2174 */ 2175 void 2176 tmpfs_rename_attachdetach(struct tmpfs_mount *tmpfs, 2177 struct vnode *fdvp, struct tmpfs_dirent *fde, struct vnode *fvp, 2178 struct vnode *tdvp, struct tmpfs_dirent *tde, struct vnode *tvp) 2179 { 2180 2181 KASSERT(tmpfs != NULL); 2182 KASSERT(fdvp != NULL); 2183 KASSERT(fde != NULL); 2184 KASSERT(fvp != NULL); 2185 KASSERT(tdvp != NULL); 2186 KASSERT(fde->td_node != NULL); 2187 KASSERT(fde->td_node->tn_vnode == fvp); 2188 KASSERT((tde == NULL) == (tvp == NULL)); 2189 KASSERT((tde == NULL) || (tde->td_node != NULL)); 2190 KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp)); 2191 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 2192 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 2193 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 2194 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 2195 2196 /* 2197 * If we are moving from one directory to another, detach the 2198 * source entry and reattach it to the target directory. 2199 */ 2200 if (fdvp != tdvp) { 2201 /* tmpfs_dir_detach clobbers fde->td_node, so save it. */ 2202 struct tmpfs_node *fnode = fde->td_node; 2203 tmpfs_node_t *fdnode = VP_TO_TMPFS_DIR(fdvp); 2204 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp); 2205 tmpfs_dir_detach(fdnode, fde); 2206 tmpfs_dir_attach(tdnode, fde, fnode); 2207 } else if (tvp == NULL) { 2208 /* 2209 * We are changing the directory. tmpfs_dir_attach and 2210 * tmpfs_dir_detach note the events for us, but for 2211 * this case we don't call them, so we must note the 2212 * event explicitly. 2213 */ 2214 VN_KNOTE(fdvp, NOTE_WRITE); 2215 } 2216 2217 /* 2218 * If we are replacing an existing target entry, delete it. 2219 */ 2220 if (tde != NULL) { 2221 tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp); 2222 KASSERT(tvp != NULL); 2223 KASSERT(tde->td_node != NULL); 2224 KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR)); 2225 if (tde->td_node->tn_type == VDIR) { 2226 KASSERT(tde->td_node->tn_size == 0); 2227 KASSERT(tde->td_node->tn_links == 2); 2228 /* Decrement the extra link count for `.' so 2229 * the vnode will be recycled when released. */ 2230 tde->td_node->tn_links--; 2231 } 2232 tmpfs_dir_detach(tdnode, tde); 2233 tmpfs_free_dirent(tmpfs, tde); 2234 } 2235 } 2236 2237 /* 2238 * Remove the entry de for the non-directory vp from the directory dvp. 2239 * 2240 * Everything must be locked and referenced. 2241 */ 2242 int 2243 tmpfs_do_remove(struct tmpfs_mount *tmpfs, struct vnode *dvp, 2244 struct tmpfs_node *dnode, struct tmpfs_dirent *de, struct vnode *vp, 2245 struct ucred *cred) 2246 { 2247 int error; 2248 2249 KASSERT(tmpfs != NULL); 2250 KASSERT(dvp != NULL); 2251 KASSERT(dnode != NULL); 2252 KASSERT(de != NULL); 2253 KASSERT(vp != NULL); 2254 KASSERT(dnode->tn_vnode == dvp); 2255 KASSERT(de->td_node != NULL); 2256 KASSERT(de->td_node->tn_vnode == vp); 2257 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 2258 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2259 2260 error = tmpfs_remove_check_possible(dnode, de->td_node); 2261 if (error) 2262 return error; 2263 2264 error = tmpfs_remove_check_permitted(cred, dnode, de->td_node); 2265 if (error) 2266 return error; 2267 2268 /* 2269 * If not root and directory is sticky, check for permission on 2270 * directory or on file. This implements append-only directories. 2271 */ 2272 if ((dnode->tn_mode & S_ISTXT) != 0) 2273 if (cred->cr_uid != 0 && cred->cr_uid != dnode->tn_uid && 2274 cred->cr_uid != de->td_node->tn_uid) 2275 return EPERM; 2276 2277 tmpfs_dir_detach(dnode, de); 2278 tmpfs_free_dirent(tmpfs, de); 2279 2280 return 0; 2281 } 2282 2283 /* 2284 * Check whether a rename is possible independent of credentials. 2285 * 2286 * Everything must be locked and referenced. 2287 */ 2288 int 2289 tmpfs_rename_check_possible( 2290 struct tmpfs_node *fdnode, struct tmpfs_node *fnode, 2291 struct tmpfs_node *tdnode, struct tmpfs_node *tnode) 2292 { 2293 2294 KASSERT(fdnode != NULL); 2295 KASSERT(fnode != NULL); 2296 KASSERT(tdnode != NULL); 2297 KASSERT(fdnode != fnode); 2298 KASSERT(tdnode != tnode); 2299 KASSERT(fnode != tnode); 2300 KASSERT(fdnode->tn_vnode != NULL); 2301 KASSERT(fnode->tn_vnode != NULL); 2302 KASSERT(tdnode->tn_vnode != NULL); 2303 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL)); 2304 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE); 2305 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE); 2306 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE); 2307 KASSERT((tnode == NULL) || 2308 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE)); 2309 2310 /* 2311 * If fdnode is immutable, we can't write to it. If fdnode is 2312 * append-only, the only change we can make is to add entries 2313 * to it. If fnode is immutable, we can't change the links to 2314 * it. If fnode is append-only...well, this is what UFS does. 2315 */ 2316 if ((fdnode->tn_flags | fnode->tn_flags) & (IMMUTABLE | APPEND)) 2317 return EPERM; 2318 2319 /* 2320 * If tdnode is immutable, we can't write to it. If tdnode is 2321 * append-only, we can add entries, but we can't change 2322 * existing entries. 2323 */ 2324 if (tdnode->tn_flags & (IMMUTABLE | (tnode? APPEND : 0))) 2325 return EPERM; 2326 2327 /* 2328 * If tnode is immutable, we can't replace links to it. If 2329 * tnode is append-only...well, this is what UFS does. 2330 */ 2331 if (tnode != NULL) { 2332 KASSERT(tnode != NULL); 2333 if ((tnode->tn_flags & (IMMUTABLE | APPEND)) != 0) 2334 return EPERM; 2335 } 2336 2337 return 0; 2338 } 2339 2340 /* 2341 * Check whether a rename is permitted given our credentials. 2342 * 2343 * Everything must be locked and referenced. 2344 */ 2345 int 2346 tmpfs_rename_check_permitted(struct ucred *cred, 2347 struct tmpfs_node *fdnode, struct tmpfs_node *fnode, 2348 struct tmpfs_node *tdnode, struct tmpfs_node *tnode) 2349 { 2350 int error; 2351 2352 KASSERT(fdnode != NULL); 2353 KASSERT(fnode != NULL); 2354 KASSERT(tdnode != NULL); 2355 KASSERT(fdnode != fnode); 2356 KASSERT(tdnode != tnode); 2357 KASSERT(fnode != tnode); 2358 KASSERT(fdnode->tn_vnode != NULL); 2359 KASSERT(fnode->tn_vnode != NULL); 2360 KASSERT(tdnode->tn_vnode != NULL); 2361 KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL)); 2362 KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE); 2363 KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE); 2364 KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE); 2365 KASSERT((tnode == NULL) || 2366 (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE)); 2367 2368 /* 2369 * We need to remove or change an entry in the source directory. 2370 */ 2371 error = VOP_ACCESS(fdnode->tn_vnode, VWRITE, cred, curproc); 2372 if (error) 2373 return error; 2374 2375 /* 2376 * If we are changing directories, then we need to write to the 2377 * target directory to add or change an entry. Also, if fnode 2378 * is a directory, we need to write to it to change its `..' 2379 * entry. 2380 */ 2381 if (fdnode != tdnode) { 2382 error = VOP_ACCESS(tdnode->tn_vnode, VWRITE, cred, curproc); 2383 if (error) 2384 return error; 2385 if (fnode->tn_type == VDIR) { 2386 error = VOP_ACCESS(fnode->tn_vnode, VWRITE, cred, 2387 curproc); 2388 if (error) 2389 return error; 2390 } 2391 } 2392 2393 error = tmpfs_check_sticky(cred, fdnode, fnode); 2394 if (error) 2395 return error; 2396 2397 if (TMPFS_DIRSEQ_FULL(tdnode)) 2398 return (ENOSPC); 2399 2400 error = tmpfs_check_sticky(cred, tdnode, tnode); 2401 if (error) 2402 return error; 2403 2404 return 0; 2405 } 2406 2407 /* 2408 * Check whether removing node's entry in dnode is possible independent 2409 * of credentials. 2410 * 2411 * Everything must be locked and referenced. 2412 */ 2413 int 2414 tmpfs_remove_check_possible(struct tmpfs_node *dnode, struct tmpfs_node *node) 2415 { 2416 2417 KASSERT(dnode != NULL); 2418 KASSERT(dnode->tn_vnode != NULL); 2419 KASSERT(node != NULL); 2420 KASSERT(dnode != node); 2421 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2422 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE); 2423 2424 /* 2425 * We want to delete the entry. If dnode is immutable, we 2426 * can't write to it to delete the entry. If dnode is 2427 * append-only, the only change we can make is to add entries, 2428 * so we can't delete entries. If node is immutable, we can't 2429 * change the links to it, so we can't delete the entry. If 2430 * node is append-only...well, this is what UFS does. 2431 */ 2432 if ((dnode->tn_flags | node->tn_flags) & (IMMUTABLE | APPEND)) 2433 return EPERM; 2434 2435 return 0; 2436 } 2437 2438 /* 2439 * Check whether removing node's entry in dnode is permitted given our 2440 * credentials. 2441 * 2442 * Everything must be locked and referenced. 2443 */ 2444 int 2445 tmpfs_remove_check_permitted(struct ucred *cred, 2446 struct tmpfs_node *dnode, struct tmpfs_node *node) 2447 { 2448 int error; 2449 2450 KASSERT(dnode != NULL); 2451 KASSERT(dnode->tn_vnode != NULL); 2452 KASSERT(node != NULL); 2453 KASSERT(dnode != node); 2454 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2455 KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE); 2456 2457 /* 2458 * Check whether we are permitted to write to the source 2459 * directory in order to delete an entry from it. 2460 */ 2461 error = VOP_ACCESS(dnode->tn_vnode, VWRITE, cred, curproc); 2462 if (error) 2463 return error; 2464 2465 error = tmpfs_check_sticky(cred, dnode, node); 2466 if (error) 2467 return error; 2468 2469 return 0; 2470 } 2471 2472 /* 2473 * Check whether we may change an entry in a sticky directory. If the 2474 * directory is sticky, the user must own either the directory or, if 2475 * it exists, the node, in order to change the entry. 2476 * 2477 * Everything must be locked and referenced. 2478 */ 2479 int 2480 tmpfs_check_sticky(struct ucred *cred, 2481 struct tmpfs_node *dnode, struct tmpfs_node *node) 2482 { 2483 2484 KASSERT(dnode != NULL); 2485 KASSERT(dnode->tn_vnode != NULL); 2486 KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE); 2487 KASSERT((node == NULL) || (node->tn_vnode != NULL)); 2488 KASSERT((node == NULL) || 2489 (VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE)); 2490 2491 if (node == NULL) 2492 return 0; 2493 2494 if (dnode->tn_mode & S_ISTXT) { 2495 if (cred->cr_uid != 0 && 2496 cred->cr_uid != dnode->tn_uid && 2497 cred->cr_uid != node->tn_uid) 2498 return EPERM; 2499 } 2500 2501 return 0; 2502 } 2503 2504 void 2505 tmpfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp, 2506 struct vnode *tdvp, struct vnode *tvp) 2507 { 2508 2509 KASSERT(fdvp != NULL); 2510 KASSERT(fvp != NULL); 2511 KASSERT(tdvp != NULL); 2512 KASSERT(fdvp != fvp); 2513 KASSERT(fdvp != tvp); 2514 KASSERT(tdvp != fvp); 2515 KASSERT(tdvp != tvp); 2516 KASSERT(fvp != tvp); 2517 KASSERT(fdvp->v_type == VDIR); 2518 KASSERT(tdvp->v_type == VDIR); 2519 2520 /* 2521 * XXX What actually needs to be purged? 2522 */ 2523 2524 cache_purge(fdvp); 2525 2526 if (fvp->v_type == VDIR) 2527 cache_purge(fvp); 2528 2529 if (tdvp != fdvp) 2530 cache_purge(tdvp); 2531 2532 if ((tvp != NULL) && (tvp->v_type == VDIR)) 2533 cache_purge(tvp); 2534 } 2535 2536 void 2537 tmpfs_rename_abort(void *v) 2538 { 2539 struct vop_rename_args *ap = v; 2540 struct vnode *fdvp = ap->a_fdvp; 2541 struct vnode *fvp = ap->a_fvp; 2542 struct componentname *fcnp = ap->a_fcnp; 2543 struct vnode *tdvp = ap->a_tdvp; 2544 struct vnode *tvp = ap->a_tvp; 2545 struct componentname *tcnp = ap->a_tcnp; 2546 2547 VOP_ABORTOP(tdvp, tcnp); 2548 if (tdvp == tvp) 2549 vrele(tdvp); 2550 else 2551 vput(tdvp); 2552 if (tvp != NULL) 2553 vput(tvp); 2554 VOP_ABORTOP(fdvp, fcnp); 2555 vrele(fdvp); 2556 vrele(fvp); 2557 } 2558 2559 void filt_tmpfsdetach(struct knote *kn); 2560 int filt_tmpfsread(struct knote *kn, long hint); 2561 int filt_tmpfswrite(struct knote *kn, long hint); 2562 int filt_tmpfsvnode(struct knote *kn, long hint); 2563 2564 const struct filterops tmpfsread_filtops = { 2565 .f_flags = FILTEROP_ISFD, 2566 .f_attach = NULL, 2567 .f_detach = filt_tmpfsdetach, 2568 .f_event = filt_tmpfsread, 2569 }; 2570 2571 const struct filterops tmpfswrite_filtops = { 2572 .f_flags = FILTEROP_ISFD, 2573 .f_attach = NULL, 2574 .f_detach = filt_tmpfsdetach, 2575 .f_event = filt_tmpfswrite, 2576 }; 2577 2578 const struct filterops tmpfsvnode_filtops = { 2579 .f_flags = FILTEROP_ISFD, 2580 .f_attach = NULL, 2581 .f_detach = filt_tmpfsdetach, 2582 .f_event = filt_tmpfsvnode, 2583 }; 2584 2585 int 2586 tmpfs_kqfilter(void *v) 2587 { 2588 struct vop_kqfilter_args *ap = v; 2589 struct vnode *vp = ap->a_vp; 2590 struct knote *kn = ap->a_kn; 2591 2592 switch (kn->kn_filter) { 2593 case EVFILT_READ: 2594 kn->kn_fop = &tmpfsread_filtops; 2595 break; 2596 case EVFILT_WRITE: 2597 kn->kn_fop = &tmpfswrite_filtops; 2598 break; 2599 case EVFILT_VNODE: 2600 kn->kn_fop = &tmpfsvnode_filtops; 2601 break; 2602 default: 2603 return (EINVAL); 2604 } 2605 2606 kn->kn_hook = (caddr_t)vp; 2607 2608 klist_insert_locked(&vp->v_klist, kn); 2609 2610 return (0); 2611 } 2612 2613 void 2614 filt_tmpfsdetach(struct knote *kn) 2615 { 2616 struct vnode *vp = (struct vnode *)kn->kn_hook; 2617 2618 klist_remove_locked(&vp->v_klist, kn); 2619 } 2620 2621 int 2622 filt_tmpfsread(struct knote *kn, long hint) 2623 { 2624 struct vnode *vp = (struct vnode *)kn->kn_hook; 2625 tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp); 2626 2627 /* 2628 * filesystem is gone, so set the EOF flag and schedule 2629 * the knote for deletion. 2630 */ 2631 if (hint == NOTE_REVOKE) { 2632 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2633 return (1); 2634 } 2635 2636 kn->kn_data = node->tn_size - foffset(kn->kn_fp); 2637 if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { 2638 kn->kn_fflags |= NOTE_EOF; 2639 return (1); 2640 } 2641 2642 if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) 2643 return (1); 2644 2645 return (kn->kn_data != 0); 2646 } 2647 2648 int 2649 filt_tmpfswrite(struct knote *kn, long hint) 2650 { 2651 /* 2652 * filesystem is gone, so set the EOF flag and schedule 2653 * the knote for deletion. 2654 */ 2655 if (hint == NOTE_REVOKE) { 2656 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2657 return (1); 2658 } 2659 2660 kn->kn_data = 0; 2661 return (1); 2662 } 2663 2664 int 2665 filt_tmpfsvnode(struct knote *kn, long hint) 2666 { 2667 if (kn->kn_sfflags & hint) 2668 kn->kn_fflags |= hint; 2669 if (hint == NOTE_REVOKE) { 2670 kn->kn_flags |= EV_EOF; 2671 return (1); 2672 } 2673 return (kn->kn_fflags != 0); 2674 } 2675