1 /*- 2 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code 7 * 2005 program. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ 31 */ 32 33 /* 34 * tmpfs vnode interface. 35 */ 36 37 #include <sys/kernel.h> 38 #include <sys/kern_syscall.h> 39 #include <sys/param.h> 40 #include <sys/fcntl.h> 41 #include <sys/lockf.h> 42 #include <sys/priv.h> 43 #include <sys/proc.h> 44 #include <sys/resourcevar.h> 45 #include <sys/sched.h> 46 #include <sys/stat.h> 47 #include <sys/systm.h> 48 #include <sys/unistd.h> 49 #include <sys/vfsops.h> 50 #include <sys/vnode.h> 51 52 #include <sys/mplock2.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_object.h> 56 #include <vm/vm_page.h> 57 #include <vm/vm_pager.h> 58 #include <vm/swap_pager.h> 59 60 #include <vfs/fifofs/fifo.h> 61 #include <vfs/tmpfs/tmpfs_vnops.h> 62 #include <vfs/tmpfs/tmpfs.h> 63 64 MALLOC_DECLARE(M_TMPFS); 65 66 static __inline 67 void 68 tmpfs_knote(struct vnode *vp, int flags) 69 { 70 if (flags) 71 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); 72 } 73 74 75 /* --------------------------------------------------------------------- */ 76 77 static int 78 tmpfs_nresolve(struct vop_nresolve_args *v) 79 { 80 struct vnode *dvp = v->a_dvp; 81 struct vnode *vp = NULL; 82 struct namecache *ncp = v->a_nch->ncp; 83 struct tmpfs_node *tnode; 84 85 int error; 86 struct tmpfs_dirent *de; 87 struct tmpfs_node *dnode; 88 89 dnode = VP_TO_TMPFS_DIR(dvp); 90 91 de = tmpfs_dir_lookup(dnode, NULL, ncp); 92 if (de == NULL) { 93 error = ENOENT; 94 } else { 95 /* 96 * Allocate a vnode for the node we found. 97 */ 98 tnode = de->td_node; 99 error = tmpfs_alloc_vp(dvp->v_mount, tnode, 100 LK_EXCLUSIVE | LK_RETRY, &vp); 101 if (error) 102 goto out; 103 KKASSERT(vp); 104 } 105 106 out: 107 /* 108 * Store the result of this lookup in the cache. Avoid this if the 109 * request was for creation, as it does not improve timings on 110 * emprical tests. 111 */ 112 if (vp) { 113 vn_unlock(vp); 114 cache_setvp(v->a_nch, vp); 115 vrele(vp); 116 } else if (error == ENOENT) { 117 cache_setvp(v->a_nch, NULL); 118 } 119 return error; 120 } 121 122 static int 123 tmpfs_nlookupdotdot(struct vop_nlookupdotdot_args *v) 124 { 125 struct vnode *dvp = v->a_dvp; 126 struct vnode **vpp = v->a_vpp; 127 struct tmpfs_node *dnode = VP_TO_TMPFS_NODE(dvp); 128 struct ucred *cred = v->a_cred; 129 int error; 130 131 *vpp = NULL; 132 /* Check accessibility of requested node as a first step. */ 133 error = VOP_ACCESS(dvp, VEXEC, cred); 134 if (error != 0) 135 return error; 136 137 if (dnode->tn_dir.tn_parent != NULL) { 138 /* Allocate a new vnode on the matching entry. */ 139 error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent, 140 LK_EXCLUSIVE | LK_RETRY, vpp); 141 142 if (*vpp) 143 vn_unlock(*vpp); 144 } 145 146 return (*vpp == NULL) ? ENOENT : 0; 147 } 148 149 /* --------------------------------------------------------------------- */ 150 151 static int 152 tmpfs_ncreate(struct vop_ncreate_args *v) 153 { 154 struct vnode *dvp = v->a_dvp; 155 struct vnode **vpp = v->a_vpp; 156 struct namecache *ncp = v->a_nch->ncp; 157 struct vattr *vap = v->a_vap; 158 struct ucred *cred = v->a_cred; 159 int error; 160 161 KKASSERT(vap->va_type == VREG || vap->va_type == VSOCK); 162 163 error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL); 164 if (error == 0) { 165 cache_setunresolved(v->a_nch); 166 cache_setvp(v->a_nch, *vpp); 167 tmpfs_knote(dvp, NOTE_WRITE); 168 } 169 170 return error; 171 } 172 /* --------------------------------------------------------------------- */ 173 174 static int 175 tmpfs_nmknod(struct vop_nmknod_args *v) 176 { 177 struct vnode *dvp = v->a_dvp; 178 struct vnode **vpp = v->a_vpp; 179 struct namecache *ncp = v->a_nch->ncp; 180 struct vattr *vap = v->a_vap; 181 struct ucred *cred = v->a_cred; 182 int error; 183 184 if (vap->va_type != VBLK && vap->va_type != VCHR && 185 vap->va_type != VFIFO) 186 return EINVAL; 187 188 error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL); 189 if (error == 0) { 190 cache_setunresolved(v->a_nch); 191 cache_setvp(v->a_nch, *vpp); 192 tmpfs_knote(dvp, NOTE_WRITE); 193 } 194 195 return error; 196 } 197 198 /* --------------------------------------------------------------------- */ 199 200 static int 201 tmpfs_open(struct vop_open_args *v) 202 { 203 struct vnode *vp = v->a_vp; 204 int mode = v->a_mode; 205 206 int error; 207 struct tmpfs_node *node; 208 209 node = VP_TO_TMPFS_NODE(vp); 210 211 /* The file is still active but all its names have been removed 212 * (e.g. by a "rmdir $(pwd)"). It cannot be opened any more as 213 * it is about to die. */ 214 if (node->tn_links < 1) 215 return (ENOENT); 216 217 /* If the file is marked append-only, deny write requests. */ 218 if ((node->tn_flags & APPEND) && 219 (mode & (FWRITE | O_APPEND)) == FWRITE) { 220 error = EPERM; 221 } else { 222 return (vop_stdopen(v)); 223 } 224 return error; 225 } 226 227 /* --------------------------------------------------------------------- */ 228 229 static int 230 tmpfs_close(struct vop_close_args *v) 231 { 232 struct vnode *vp = v->a_vp; 233 struct tmpfs_node *node; 234 235 node = VP_TO_TMPFS_NODE(vp); 236 237 if (node->tn_links > 0) { 238 /* Update node times. No need to do it if the node has 239 * been deleted, because it will vanish after we return. */ 240 tmpfs_update(vp); 241 } 242 243 return vop_stdclose(v); 244 } 245 246 /* --------------------------------------------------------------------- */ 247 248 int 249 tmpfs_access(struct vop_access_args *v) 250 { 251 struct vnode *vp = v->a_vp; 252 int error; 253 struct tmpfs_node *node; 254 255 node = VP_TO_TMPFS_NODE(vp); 256 257 switch (vp->v_type) { 258 case VDIR: 259 /* FALLTHROUGH */ 260 case VLNK: 261 /* FALLTHROUGH */ 262 case VREG: 263 if ((v->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 264 error = EROFS; 265 goto out; 266 } 267 break; 268 269 case VBLK: 270 /* FALLTHROUGH */ 271 case VCHR: 272 /* FALLTHROUGH */ 273 case VSOCK: 274 /* FALLTHROUGH */ 275 case VFIFO: 276 break; 277 278 default: 279 error = EINVAL; 280 goto out; 281 } 282 283 if ((v->a_mode & VWRITE) && (node->tn_flags & IMMUTABLE)) { 284 error = EPERM; 285 goto out; 286 } 287 288 error = vop_helper_access(v, node->tn_uid, node->tn_gid, node->tn_mode, 0); 289 290 out: 291 292 return error; 293 } 294 295 /* --------------------------------------------------------------------- */ 296 297 int 298 tmpfs_getattr(struct vop_getattr_args *v) 299 { 300 struct vnode *vp = v->a_vp; 301 struct vattr *vap = v->a_vap; 302 struct tmpfs_node *node; 303 304 node = VP_TO_TMPFS_NODE(vp); 305 306 tmpfs_update(vp); 307 308 vap->va_type = vp->v_type; 309 vap->va_mode = node->tn_mode; 310 vap->va_nlink = node->tn_links; 311 vap->va_uid = node->tn_uid; 312 vap->va_gid = node->tn_gid; 313 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 314 vap->va_fileid = node->tn_id; 315 vap->va_size = node->tn_size; 316 vap->va_blocksize = PAGE_SIZE; 317 vap->va_atime.tv_sec = node->tn_atime; 318 vap->va_atime.tv_nsec = node->tn_atimensec; 319 vap->va_mtime.tv_sec = node->tn_mtime; 320 vap->va_mtime.tv_nsec = node->tn_mtimensec; 321 vap->va_ctime.tv_sec = node->tn_ctime; 322 vap->va_ctime.tv_nsec = node->tn_ctimensec; 323 vap->va_gen = node->tn_gen; 324 vap->va_flags = node->tn_flags; 325 if (vp->v_type == VBLK || vp->v_type == VCHR) 326 { 327 vap->va_rmajor = umajor(node->tn_rdev); 328 vap->va_rminor = uminor(node->tn_rdev); 329 } 330 vap->va_bytes = round_page(node->tn_size); 331 vap->va_filerev = 0; 332 333 return 0; 334 } 335 336 /* --------------------------------------------------------------------- */ 337 338 int 339 tmpfs_setattr(struct vop_setattr_args *v) 340 { 341 struct vnode *vp = v->a_vp; 342 struct vattr *vap = v->a_vap; 343 struct ucred *cred = v->a_cred; 344 struct tmpfs_node *node = VP_TO_TMPFS_NODE(vp); 345 int error = 0; 346 int kflags = 0; 347 348 if (error == 0 && (vap->va_flags != VNOVAL)) { 349 error = tmpfs_chflags(vp, vap->va_flags, cred); 350 kflags |= NOTE_ATTRIB; 351 } 352 353 if (error == 0 && (vap->va_size != VNOVAL)) { 354 if (vap->va_size > node->tn_size) 355 kflags |= NOTE_WRITE | NOTE_EXTEND; 356 else 357 kflags |= NOTE_WRITE; 358 error = tmpfs_chsize(vp, vap->va_size, cred); 359 } 360 361 if (error == 0 && (vap->va_uid != (uid_t)VNOVAL || 362 vap->va_gid != (gid_t)VNOVAL)) { 363 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred); 364 kflags |= NOTE_ATTRIB; 365 } 366 367 if (error == 0 && (vap->va_mode != (mode_t)VNOVAL)) { 368 error = tmpfs_chmod(vp, vap->va_mode, cred); 369 kflags |= NOTE_ATTRIB; 370 } 371 372 if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL && 373 vap->va_atime.tv_nsec != VNOVAL) || 374 (vap->va_mtime.tv_sec != VNOVAL && 375 vap->va_mtime.tv_nsec != VNOVAL) )) { 376 error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime, 377 vap->va_vaflags, cred); 378 kflags |= NOTE_ATTRIB; 379 } 380 381 /* Update the node times. We give preference to the error codes 382 * generated by this function rather than the ones that may arise 383 * from tmpfs_update. */ 384 tmpfs_update(vp); 385 tmpfs_knote(vp, kflags); 386 387 return error; 388 } 389 390 /* --------------------------------------------------------------------- */ 391 392 /* 393 * fsync is usually a NOP, but we must take action when unmounting or 394 * when recycling. 395 */ 396 static int 397 tmpfs_fsync(struct vop_fsync_args *v) 398 { 399 struct tmpfs_mount *tmp; 400 struct tmpfs_node *node; 401 struct vnode *vp = v->a_vp; 402 403 tmp = VFS_TO_TMPFS(vp->v_mount); 404 node = VP_TO_TMPFS_NODE(vp); 405 406 tmpfs_update(vp); 407 if (vp->v_type == VREG) { 408 if (vp->v_flag & VRECLAIMED) { 409 if (node->tn_links == 0) 410 tmpfs_truncate(vp, 0); 411 else 412 vfsync(v->a_vp, v->a_waitfor, 1, NULL, NULL); 413 } 414 } 415 return 0; 416 } 417 418 /* --------------------------------------------------------------------- */ 419 420 static int 421 tmpfs_read (struct vop_read_args *ap) 422 { 423 struct buf *bp; 424 struct vnode *vp = ap->a_vp; 425 struct uio *uio = ap->a_uio; 426 struct tmpfs_node *node; 427 off_t base_offset; 428 size_t offset; 429 size_t len; 430 int got_mplock; 431 int error; 432 433 error = 0; 434 if (uio->uio_resid == 0) { 435 return error; 436 } 437 438 node = VP_TO_TMPFS_NODE(vp); 439 440 if (uio->uio_offset < 0) 441 return (EINVAL); 442 if (vp->v_type != VREG) 443 return (EINVAL); 444 445 #ifdef SMP 446 if(curthread->td_mpcount) 447 got_mplock = -1; 448 else 449 got_mplock = 0; 450 #else 451 got_mplock = -1; 452 #endif 453 454 while (uio->uio_resid > 0 && uio->uio_offset < node->tn_size) { 455 /* 456 * Use buffer cache I/O (via tmpfs_strategy) 457 */ 458 offset = (size_t)uio->uio_offset & BMASK; 459 base_offset = (off_t)uio->uio_offset - offset; 460 bp = getcacheblk(vp, base_offset); 461 if (bp == NULL) 462 { 463 if (got_mplock == 0) { 464 got_mplock = 1; 465 get_mplock(); 466 } 467 468 error = bread(vp, base_offset, BSIZE, &bp); 469 if (error) { 470 brelse(bp); 471 kprintf("tmpfs_read bread error %d\n", error); 472 break; 473 } 474 } 475 476 if (got_mplock == 0) { 477 got_mplock = 1; 478 get_mplock(); 479 } 480 481 /* 482 * Figure out how many bytes we can actually copy this loop. 483 */ 484 len = BSIZE - offset; 485 if (len > uio->uio_resid) 486 len = uio->uio_resid; 487 if (len > node->tn_size - uio->uio_offset) 488 len = (size_t)(node->tn_size - uio->uio_offset); 489 490 error = uiomove((char *)bp->b_data + offset, len, uio); 491 bqrelse(bp); 492 if (error) { 493 kprintf("tmpfs_read uiomove error %d\n", error); 494 break; 495 } 496 } 497 498 if (got_mplock > 0) 499 rel_mplock(); 500 501 TMPFS_NODE_LOCK(node); 502 node->tn_status |= TMPFS_NODE_ACCESSED; 503 TMPFS_NODE_UNLOCK(node); 504 505 return(error); 506 } 507 508 static int 509 tmpfs_write (struct vop_write_args *ap) 510 { 511 struct buf *bp; 512 struct vnode *vp = ap->a_vp; 513 struct uio *uio = ap->a_uio; 514 struct thread *td = uio->uio_td; 515 struct tmpfs_node *node; 516 boolean_t extended; 517 off_t oldsize; 518 int error; 519 off_t base_offset; 520 size_t offset; 521 size_t len; 522 struct rlimit limit; 523 int got_mplock; 524 int trivial = 0; 525 int kflags = 0; 526 527 error = 0; 528 if (uio->uio_resid == 0) { 529 return error; 530 } 531 532 node = VP_TO_TMPFS_NODE(vp); 533 534 if (vp->v_type != VREG) 535 return (EINVAL); 536 537 oldsize = node->tn_size; 538 if (ap->a_ioflag & IO_APPEND) 539 uio->uio_offset = node->tn_size; 540 541 /* 542 * Check for illegal write offsets. 543 */ 544 if (uio->uio_offset + uio->uio_resid > 545 VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) 546 return (EFBIG); 547 548 if (vp->v_type == VREG && td != NULL) { 549 error = kern_getrlimit(RLIMIT_FSIZE, &limit); 550 if (error != 0) 551 return error; 552 if (uio->uio_offset + uio->uio_resid > limit.rlim_cur) { 553 ksignal(td->td_proc, SIGXFSZ); 554 return (EFBIG); 555 } 556 } 557 558 559 /* 560 * Extend the file's size if necessary 561 */ 562 extended = ((uio->uio_offset + uio->uio_resid) > node->tn_size); 563 564 #ifdef SMP 565 if (curthread->td_mpcount) { 566 got_mplock = -1; 567 } else { 568 got_mplock = 1; 569 get_mplock(); 570 } 571 #else 572 got_mplock = -1; 573 #endif 574 while (uio->uio_resid > 0) { 575 /* 576 * Use buffer cache I/O (via tmpfs_strategy) 577 */ 578 offset = (size_t)uio->uio_offset & BMASK; 579 base_offset = (off_t)uio->uio_offset - offset; 580 len = BSIZE - offset; 581 if (len > uio->uio_resid) 582 len = uio->uio_resid; 583 584 if ((uio->uio_offset + len) > node->tn_size) { 585 trivial = (uio->uio_offset <= node->tn_size); 586 error = tmpfs_reg_resize(vp, uio->uio_offset + len, trivial); 587 if (error) 588 break; 589 } 590 591 /* 592 * Read to fill in any gaps. Theoretically we could 593 * optimize this if the write covers the entire buffer 594 * and is not a UIO_NOCOPY write, however this can lead 595 * to a security violation exposing random kernel memory 596 * (whatever junk was in the backing VM pages before). 597 * 598 * So just use bread() to do the right thing. 599 */ 600 error = bread(vp, base_offset, BSIZE, &bp); 601 error = uiomove((char *)bp->b_data + offset, len, uio); 602 if (error) { 603 kprintf("tmpfs_write uiomove error %d\n", error); 604 brelse(bp); 605 break; 606 } 607 608 if (uio->uio_offset > node->tn_size) { 609 node->tn_size = uio->uio_offset; 610 kflags |= NOTE_EXTEND; 611 } 612 kflags |= NOTE_WRITE; 613 614 /* 615 * The data has been loaded into the buffer, write it out. 616 * 617 * We want tmpfs to be able to use all available ram, not 618 * just the buffer cache, so if not explicitly paging we 619 * use buwrite() to leave the buffer clean but mark all the 620 * VM pages valid+dirty. 621 * 622 * When the kernel is paging, either via normal pageout 623 * operation or when cleaning the object during a recycle, 624 * the underlying VM pages are going to get thrown away 625 * so we MUST write them to swap. 626 * 627 * XXX unfortunately this catches msync() system calls too 628 * for the moment. 629 */ 630 if (vm_swap_size == 0) { 631 /* 632 * if swap isn't configured yet, force a buwrite() to 633 * avoid problems further down the line, due to flushing 634 * to swap. 635 */ 636 buwrite(bp); 637 } else { 638 if (ap->a_ioflag & IO_SYNC) { 639 bwrite(bp); 640 } else if ((ap->a_ioflag & IO_ASYNC) || 641 (uio->uio_segflg == UIO_NOCOPY)) { 642 bawrite(bp); 643 } else { 644 buwrite(bp); 645 } 646 } 647 648 if (bp->b_error) { 649 kprintf("tmpfs_write bwrite error %d\n", bp->b_error); 650 break; 651 } 652 } 653 654 if (got_mplock > 0) 655 rel_mplock(); 656 657 if (error) { 658 if (extended) { 659 (void)tmpfs_reg_resize(vp, oldsize, trivial); 660 kflags &= ~NOTE_EXTEND; 661 } 662 goto done; 663 } 664 665 TMPFS_NODE_LOCK(node); 666 node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | 667 (extended? TMPFS_NODE_CHANGED : 0); 668 669 if (node->tn_mode & (S_ISUID | S_ISGID)) { 670 if (priv_check_cred(ap->a_cred, PRIV_VFS_RETAINSUGID, 0)) 671 node->tn_mode &= ~(S_ISUID | S_ISGID); 672 } 673 TMPFS_NODE_UNLOCK(node); 674 done: 675 676 tmpfs_knote(vp, kflags); 677 return(error); 678 } 679 680 static int 681 tmpfs_advlock (struct vop_advlock_args *ap) 682 { 683 struct tmpfs_node *node; 684 struct vnode *vp = ap->a_vp; 685 686 node = VP_TO_TMPFS_NODE(vp); 687 688 return (lf_advlock(ap, &node->tn_advlock, node->tn_size)); 689 } 690 691 static int 692 tmpfs_strategy(struct vop_strategy_args *ap) 693 { 694 struct bio *bio = ap->a_bio; 695 struct buf *bp = bio->bio_buf; 696 struct vnode *vp = ap->a_vp; 697 struct tmpfs_node *node; 698 vm_object_t uobj; 699 700 if (vp->v_type != VREG) { 701 bp->b_resid = bp->b_bcount; 702 bp->b_flags |= B_ERROR | B_INVAL; 703 bp->b_error = EINVAL; 704 biodone(bio); 705 return(0); 706 } 707 708 node = VP_TO_TMPFS_NODE(vp); 709 710 uobj = node->tn_reg.tn_aobj; 711 712 /* 713 * Call swap_pager_strategy to read or write between the VM 714 * object and the buffer cache. 715 */ 716 swap_pager_strategy(uobj, bio); 717 718 return 0; 719 } 720 721 static int 722 tmpfs_bmap(struct vop_bmap_args *ap) 723 { 724 if (ap->a_doffsetp != NULL) 725 *ap->a_doffsetp = ap->a_loffset; 726 if (ap->a_runp != NULL) 727 *ap->a_runp = 0; 728 if (ap->a_runb != NULL) 729 *ap->a_runb = 0; 730 731 return 0; 732 } 733 734 /* --------------------------------------------------------------------- */ 735 736 static int 737 tmpfs_nremove(struct vop_nremove_args *v) 738 { 739 struct vnode *dvp = v->a_dvp; 740 struct namecache *ncp = v->a_nch->ncp; 741 struct vnode *vp; 742 int error; 743 struct tmpfs_dirent *de; 744 struct tmpfs_mount *tmp; 745 struct tmpfs_node *dnode; 746 struct tmpfs_node *node; 747 748 /* 749 * We have to acquire the vp from v->a_nch because 750 * we will likely unresolve the namecache entry, and 751 * a vrele is needed to trigger the tmpfs_inactive/tmpfs_reclaim 752 * sequence to recover space from the file. 753 */ 754 error = cache_vref(v->a_nch, v->a_cred, &vp); 755 KKASSERT(error == 0); 756 757 if (vp->v_type == VDIR) { 758 error = EISDIR; 759 goto out; 760 } 761 762 dnode = VP_TO_TMPFS_DIR(dvp); 763 node = VP_TO_TMPFS_NODE(vp); 764 tmp = VFS_TO_TMPFS(vp->v_mount); 765 de = tmpfs_dir_lookup(dnode, node, ncp); 766 if (de == NULL) { 767 error = ENOENT; 768 goto out; 769 } 770 771 /* Files marked as immutable or append-only cannot be deleted. */ 772 if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 773 (dnode->tn_flags & APPEND)) { 774 error = EPERM; 775 goto out; 776 } 777 778 /* Remove the entry from the directory; as it is a file, we do not 779 * have to change the number of hard links of the directory. */ 780 tmpfs_dir_detach(dnode, de); 781 782 /* Free the directory entry we just deleted. Note that the node 783 * referred by it will not be removed until the vnode is really 784 * reclaimed. */ 785 tmpfs_free_dirent(tmp, de); 786 787 if (node->tn_links > 0) { 788 TMPFS_NODE_LOCK(node); 789 node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ 790 TMPFS_NODE_MODIFIED; 791 TMPFS_NODE_UNLOCK(node); 792 } 793 794 cache_setunresolved(v->a_nch); 795 cache_setvp(v->a_nch, NULL); 796 tmpfs_knote(vp, NOTE_DELETE); 797 /*cache_inval_vp(vp, CINV_DESTROY);*/ 798 tmpfs_knote(dvp, NOTE_WRITE); 799 error = 0; 800 801 out: 802 vrele(vp); 803 804 return error; 805 } 806 807 /* --------------------------------------------------------------------- */ 808 809 static int 810 tmpfs_nlink(struct vop_nlink_args *v) 811 { 812 struct vnode *dvp = v->a_dvp; 813 struct vnode *vp = v->a_vp; 814 struct namecache *ncp = v->a_nch->ncp; 815 struct tmpfs_dirent *de; 816 struct tmpfs_node *node; 817 struct tmpfs_node *dnode; 818 int error; 819 820 KKASSERT(dvp != vp); /* XXX When can this be false? */ 821 822 node = VP_TO_TMPFS_NODE(vp); 823 dnode = VP_TO_TMPFS_NODE(dvp); 824 825 /* XXX: Why aren't the following two tests done by the caller? */ 826 827 /* Hard links of directories are forbidden. */ 828 if (vp->v_type == VDIR) { 829 error = EPERM; 830 goto out; 831 } 832 833 /* Cannot create cross-device links. */ 834 if (dvp->v_mount != vp->v_mount) { 835 error = EXDEV; 836 goto out; 837 } 838 839 /* Ensure that we do not overflow the maximum number of links imposed 840 * by the system. */ 841 KKASSERT(node->tn_links <= LINK_MAX); 842 if (node->tn_links == LINK_MAX) { 843 error = EMLINK; 844 goto out; 845 } 846 847 /* We cannot create links of files marked immutable or append-only. */ 848 if (node->tn_flags & (IMMUTABLE | APPEND)) { 849 error = EPERM; 850 goto out; 851 } 852 853 /* Allocate a new directory entry to represent the node. */ 854 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node, 855 ncp->nc_name, ncp->nc_nlen, &de); 856 if (error != 0) 857 goto out; 858 859 /* Insert the new directory entry into the appropriate directory. */ 860 tmpfs_dir_attach(dnode, de); 861 862 /* vp link count has changed, so update node times. */ 863 864 TMPFS_NODE_LOCK(node); 865 node->tn_status |= TMPFS_NODE_CHANGED; 866 TMPFS_NODE_UNLOCK(node); 867 tmpfs_update(vp); 868 869 tmpfs_knote(vp, NOTE_LINK); 870 cache_setunresolved(v->a_nch); 871 cache_setvp(v->a_nch, vp); 872 tmpfs_knote(dvp, NOTE_WRITE); 873 error = 0; 874 875 out: 876 return error; 877 } 878 879 /* --------------------------------------------------------------------- */ 880 881 static int 882 tmpfs_nrename(struct vop_nrename_args *v) 883 { 884 struct vnode *fdvp = v->a_fdvp; 885 struct namecache *fncp = v->a_fnch->ncp; 886 struct vnode *fvp = fncp->nc_vp; 887 struct vnode *tdvp = v->a_tdvp; 888 struct namecache *tncp = v->a_tnch->ncp; 889 struct vnode *tvp = tncp->nc_vp; 890 struct tmpfs_dirent *de; 891 struct tmpfs_mount *tmp; 892 struct tmpfs_node *fdnode; 893 struct tmpfs_node *fnode; 894 struct tmpfs_node *tnode; 895 struct tmpfs_node *tdnode; 896 char *newname; 897 char *oldname; 898 int error; 899 900 tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); 901 902 /* Disallow cross-device renames. 903 * XXX Why isn't this done by the caller? */ 904 if (fvp->v_mount != tdvp->v_mount || 905 (tvp != NULL && fvp->v_mount != tvp->v_mount)) { 906 error = EXDEV; 907 goto out; 908 } 909 910 tmp = VFS_TO_TMPFS(tdvp->v_mount); 911 tdnode = VP_TO_TMPFS_DIR(tdvp); 912 913 /* If source and target are the same file, there is nothing to do. */ 914 if (fvp == tvp) { 915 error = 0; 916 goto out; 917 } 918 919 fdnode = VP_TO_TMPFS_DIR(fdvp); 920 fnode = VP_TO_TMPFS_NODE(fvp); 921 de = tmpfs_dir_lookup(fdnode, fnode, fncp); 922 923 /* Avoid manipulating '.' and '..' entries. */ 924 if (de == NULL) { 925 error = ENOENT; 926 goto out_locked; 927 } 928 KKASSERT(de->td_node == fnode); 929 930 /* 931 * If replacing an entry in the target directory and that entry 932 * is a directory, it must be empty. 933 * 934 * Kern_rename gurantees the destination to be a directory 935 * if the source is one (it does?). 936 */ 937 if (tvp != NULL) { 938 KKASSERT(tnode != NULL); 939 940 if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 941 (tdnode->tn_flags & (APPEND | IMMUTABLE))) { 942 error = EPERM; 943 goto out_locked; 944 } 945 946 if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) { 947 if (tnode->tn_size > 0) { 948 error = ENOTEMPTY; 949 goto out_locked; 950 } 951 } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) { 952 error = ENOTDIR; 953 goto out_locked; 954 } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) { 955 error = EISDIR; 956 goto out_locked; 957 } else { 958 KKASSERT(fnode->tn_type != VDIR && 959 tnode->tn_type != VDIR); 960 } 961 } 962 963 if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 964 (fdnode->tn_flags & (APPEND | IMMUTABLE))) { 965 error = EPERM; 966 goto out_locked; 967 } 968 969 /* 970 * Ensure that we have enough memory to hold the new name, if it 971 * has to be changed. 972 */ 973 if (fncp->nc_nlen != tncp->nc_nlen || 974 bcmp(fncp->nc_name, tncp->nc_name, fncp->nc_nlen) != 0) { 975 newname = kmalloc(tncp->nc_nlen + 1, tmp->tm_name_zone, 976 M_WAITOK | M_NULLOK); 977 if (newname == NULL) { 978 error = ENOSPC; 979 goto out_locked; 980 } 981 bcopy(tncp->nc_name, newname, tncp->nc_nlen); 982 newname[tncp->nc_nlen] = '\0'; 983 } else { 984 newname = NULL; 985 } 986 987 /* 988 * Unlink entry from source directory. Note that the kernel has 989 * already checked for illegal recursion cases (renaming a directory 990 * into a subdirectory of itself). 991 */ 992 if (fdnode != tdnode) 993 tmpfs_dir_detach(fdnode, de); 994 995 /* 996 * Handle any name change. Swap with newname, we will 997 * deallocate it at the end. 998 */ 999 if (newname != NULL) { 1000 #if 0 1001 TMPFS_NODE_LOCK(fnode); 1002 fnode->tn_status |= TMPFS_NODE_CHANGED; 1003 TMPFS_NODE_UNLOCK(fnode); 1004 #endif 1005 oldname = de->td_name; 1006 de->td_name = newname; 1007 de->td_namelen = (uint16_t)tncp->nc_nlen; 1008 newname = oldname; 1009 } 1010 1011 /* 1012 * Link entry to target directory. If the entry 1013 * represents a directory move the parent linkage 1014 * as well. 1015 */ 1016 if (fdnode != tdnode) { 1017 if (de->td_node->tn_type == VDIR) { 1018 TMPFS_VALIDATE_DIR(fnode); 1019 1020 TMPFS_NODE_LOCK(tdnode); 1021 tdnode->tn_links++; 1022 tdnode->tn_status |= TMPFS_NODE_MODIFIED; 1023 TMPFS_NODE_UNLOCK(tdnode); 1024 1025 TMPFS_NODE_LOCK(fnode); 1026 fnode->tn_dir.tn_parent = tdnode; 1027 fnode->tn_status |= TMPFS_NODE_CHANGED; 1028 TMPFS_NODE_UNLOCK(fnode); 1029 1030 TMPFS_NODE_LOCK(fdnode); 1031 fdnode->tn_links--; 1032 fdnode->tn_status |= TMPFS_NODE_MODIFIED; 1033 TMPFS_NODE_UNLOCK(fdnode); 1034 } 1035 tmpfs_dir_attach(tdnode, de); 1036 } else { 1037 TMPFS_NODE_LOCK(tdnode); 1038 tdnode->tn_status |= TMPFS_NODE_MODIFIED; 1039 TMPFS_NODE_UNLOCK(tdnode); 1040 } 1041 1042 /* 1043 * If we are overwriting an entry, we have to remove the old one 1044 * from the target directory. 1045 */ 1046 if (tvp != NULL) { 1047 /* Remove the old entry from the target directory. */ 1048 de = tmpfs_dir_lookup(tdnode, tnode, tncp); 1049 tmpfs_dir_detach(tdnode, de); 1050 tmpfs_knote(tdnode->tn_vnode, NOTE_DELETE); 1051 1052 /* 1053 * Free the directory entry we just deleted. Note that the 1054 * node referred by it will not be removed until the vnode is 1055 * really reclaimed. 1056 */ 1057 tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de); 1058 /*cache_inval_vp(tvp, CINV_DESTROY);*/ 1059 } 1060 1061 /* 1062 * Finish up 1063 */ 1064 if (newname) { 1065 kfree(newname, tmp->tm_name_zone); 1066 newname = NULL; 1067 } 1068 cache_rename(v->a_fnch, v->a_tnch); 1069 tmpfs_knote(v->a_fdvp, NOTE_WRITE); 1070 tmpfs_knote(v->a_tdvp, NOTE_WRITE); 1071 if (fnode->tn_vnode) 1072 tmpfs_knote(fnode->tn_vnode, NOTE_RENAME); 1073 error = 0; 1074 1075 out_locked: 1076 ; 1077 1078 out: 1079 /* Release target nodes. */ 1080 /* XXX: I don't understand when tdvp can be the same as tvp, but 1081 * other code takes care of this... */ 1082 if (tdvp == tvp) 1083 vrele(tdvp); 1084 1085 return error; 1086 } 1087 1088 /* --------------------------------------------------------------------- */ 1089 1090 static int 1091 tmpfs_nmkdir(struct vop_nmkdir_args *v) 1092 { 1093 struct vnode *dvp = v->a_dvp; 1094 struct vnode **vpp = v->a_vpp; 1095 struct namecache *ncp = v->a_nch->ncp; 1096 struct vattr *vap = v->a_vap; 1097 struct ucred *cred = v->a_cred; 1098 int error; 1099 1100 KKASSERT(vap->va_type == VDIR); 1101 1102 error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL); 1103 if (error == 0) { 1104 cache_setunresolved(v->a_nch); 1105 cache_setvp(v->a_nch, *vpp); 1106 tmpfs_knote(dvp, NOTE_WRITE | NOTE_LINK); 1107 } 1108 1109 return error; 1110 } 1111 1112 /* --------------------------------------------------------------------- */ 1113 1114 static int 1115 tmpfs_nrmdir(struct vop_nrmdir_args *v) 1116 { 1117 struct vnode *dvp = v->a_dvp; 1118 struct namecache *ncp = v->a_nch->ncp; 1119 struct vnode *vp; 1120 struct tmpfs_dirent *de; 1121 struct tmpfs_mount *tmp; 1122 struct tmpfs_node *dnode; 1123 struct tmpfs_node *node; 1124 int error; 1125 1126 /* 1127 * We have to acquire the vp from v->a_nch because 1128 * we will likely unresolve the namecache entry, and 1129 * a vrele is needed to trigger the tmpfs_inactive/tmpfs_reclaim 1130 * sequence. 1131 */ 1132 error = cache_vref(v->a_nch, v->a_cred, &vp); 1133 KKASSERT(error == 0); 1134 1135 /* 1136 * Prevalidate so we don't hit an assertion later 1137 */ 1138 if (vp->v_type != VDIR) { 1139 error = ENOTDIR; 1140 goto out; 1141 } 1142 1143 tmp = VFS_TO_TMPFS(dvp->v_mount); 1144 dnode = VP_TO_TMPFS_DIR(dvp); 1145 node = VP_TO_TMPFS_DIR(vp); 1146 1147 /* Directories with more than two entries ('.' and '..') cannot be 1148 * removed. */ 1149 if (node->tn_size > 0) { 1150 error = ENOTEMPTY; 1151 goto out; 1152 } 1153 1154 if ((dnode->tn_flags & APPEND) 1155 || (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) { 1156 error = EPERM; 1157 goto out; 1158 } 1159 1160 /* This invariant holds only if we are not trying to remove "..". 1161 * We checked for that above so this is safe now. */ 1162 KKASSERT(node->tn_dir.tn_parent == dnode); 1163 1164 /* Get the directory entry associated with node (vp). This was 1165 * filled by tmpfs_lookup while looking up the entry. */ 1166 de = tmpfs_dir_lookup(dnode, node, ncp); 1167 KKASSERT(TMPFS_DIRENT_MATCHES(de, 1168 ncp->nc_name, 1169 ncp->nc_nlen)); 1170 1171 /* Check flags to see if we are allowed to remove the directory. */ 1172 if ((dnode->tn_flags & APPEND) || 1173 node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) { 1174 error = EPERM; 1175 goto out; 1176 } 1177 1178 1179 /* Detach the directory entry from the directory (dnode). */ 1180 tmpfs_dir_detach(dnode, de); 1181 1182 /* No vnode should be allocated for this entry from this point */ 1183 TMPFS_NODE_LOCK(node); 1184 TMPFS_ASSERT_ELOCKED(node); 1185 TMPFS_NODE_LOCK(dnode); 1186 TMPFS_ASSERT_ELOCKED(dnode); 1187 1188 #if 0 1189 /* handled by tmpfs_free_node */ 1190 KKASSERT(node->tn_links > 0); 1191 node->tn_links--; 1192 node->tn_dir.tn_parent = NULL; 1193 #endif 1194 node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ 1195 TMPFS_NODE_MODIFIED; 1196 1197 #if 0 1198 /* handled by tmpfs_free_node */ 1199 KKASSERT(dnode->tn_links > 0); 1200 dnode->tn_links--; 1201 #endif 1202 dnode->tn_status |= TMPFS_NODE_ACCESSED | \ 1203 TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; 1204 1205 TMPFS_NODE_UNLOCK(dnode); 1206 TMPFS_NODE_UNLOCK(node); 1207 1208 /* Free the directory entry we just deleted. Note that the node 1209 * referred by it will not be removed until the vnode is really 1210 * reclaimed. */ 1211 tmpfs_free_dirent(tmp, de); 1212 1213 /* Release the deleted vnode (will destroy the node, notify 1214 * interested parties and clean it from the cache). */ 1215 1216 TMPFS_NODE_LOCK(dnode); 1217 dnode->tn_status |= TMPFS_NODE_CHANGED; 1218 TMPFS_NODE_UNLOCK(dnode); 1219 tmpfs_update(dvp); 1220 1221 cache_setunresolved(v->a_nch); 1222 cache_setvp(v->a_nch, NULL); 1223 /*cache_inval_vp(vp, CINV_DESTROY);*/ 1224 tmpfs_knote(dvp, NOTE_WRITE | NOTE_LINK); 1225 error = 0; 1226 1227 out: 1228 vrele(vp); 1229 1230 return error; 1231 } 1232 1233 /* --------------------------------------------------------------------- */ 1234 1235 static int 1236 tmpfs_nsymlink(struct vop_nsymlink_args *v) 1237 { 1238 struct vnode *dvp = v->a_dvp; 1239 struct vnode **vpp = v->a_vpp; 1240 struct namecache *ncp = v->a_nch->ncp; 1241 struct vattr *vap = v->a_vap; 1242 struct ucred *cred = v->a_cred; 1243 char *target = v->a_target; 1244 int error; 1245 1246 vap->va_type = VLNK; 1247 error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, target); 1248 if (error == 0) { 1249 tmpfs_knote(*vpp, NOTE_WRITE); 1250 cache_setunresolved(v->a_nch); 1251 cache_setvp(v->a_nch, *vpp); 1252 } 1253 1254 return error; 1255 } 1256 1257 /* --------------------------------------------------------------------- */ 1258 1259 static int 1260 tmpfs_readdir(struct vop_readdir_args *v) 1261 { 1262 struct vnode *vp = v->a_vp; 1263 struct uio *uio = v->a_uio; 1264 int *eofflag = v->a_eofflag; 1265 off_t **cookies = v->a_cookies; 1266 int *ncookies = v->a_ncookies; 1267 struct tmpfs_mount *tmp; 1268 int error; 1269 off_t startoff; 1270 off_t cnt = 0; 1271 struct tmpfs_node *node; 1272 1273 /* This operation only makes sense on directory nodes. */ 1274 if (vp->v_type != VDIR) 1275 return ENOTDIR; 1276 1277 tmp = VFS_TO_TMPFS(vp->v_mount); 1278 node = VP_TO_TMPFS_DIR(vp); 1279 startoff = uio->uio_offset; 1280 1281 if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) { 1282 error = tmpfs_dir_getdotdent(node, uio); 1283 if (error != 0) 1284 goto outok; 1285 cnt++; 1286 } 1287 1288 if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) { 1289 error = tmpfs_dir_getdotdotdent(tmp, node, uio); 1290 if (error != 0) 1291 goto outok; 1292 cnt++; 1293 } 1294 1295 error = tmpfs_dir_getdents(node, uio, &cnt); 1296 1297 outok: 1298 KKASSERT(error >= -1); 1299 1300 if (error == -1) 1301 error = 0; 1302 1303 if (eofflag != NULL) 1304 *eofflag = 1305 (error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF); 1306 1307 /* Update NFS-related variables. */ 1308 if (error == 0 && cookies != NULL && ncookies != NULL) { 1309 off_t i; 1310 off_t off = startoff; 1311 struct tmpfs_dirent *de = NULL; 1312 1313 *ncookies = cnt; 1314 *cookies = kmalloc(cnt * sizeof(off_t), M_TEMP, M_WAITOK); 1315 1316 for (i = 0; i < cnt; i++) { 1317 KKASSERT(off != TMPFS_DIRCOOKIE_EOF); 1318 if (off == TMPFS_DIRCOOKIE_DOT) { 1319 off = TMPFS_DIRCOOKIE_DOTDOT; 1320 } else { 1321 if (off == TMPFS_DIRCOOKIE_DOTDOT) { 1322 de = TAILQ_FIRST(&node->tn_dir.tn_dirhead); 1323 } else if (de != NULL) { 1324 de = TAILQ_NEXT(de, td_entries); 1325 } else { 1326 de = tmpfs_dir_lookupbycookie(node, 1327 off); 1328 KKASSERT(de != NULL); 1329 de = TAILQ_NEXT(de, td_entries); 1330 } 1331 if (de == NULL) 1332 off = TMPFS_DIRCOOKIE_EOF; 1333 else 1334 off = tmpfs_dircookie(de); 1335 } 1336 1337 (*cookies)[i] = off; 1338 } 1339 KKASSERT(uio->uio_offset == off); 1340 } 1341 1342 return error; 1343 } 1344 1345 /* --------------------------------------------------------------------- */ 1346 1347 static int 1348 tmpfs_readlink(struct vop_readlink_args *v) 1349 { 1350 struct vnode *vp = v->a_vp; 1351 struct uio *uio = v->a_uio; 1352 1353 int error; 1354 struct tmpfs_node *node; 1355 1356 KKASSERT(uio->uio_offset == 0); 1357 KKASSERT(vp->v_type == VLNK); 1358 1359 node = VP_TO_TMPFS_NODE(vp); 1360 1361 error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid), 1362 uio); 1363 TMPFS_NODE_LOCK(node); 1364 node->tn_status |= TMPFS_NODE_ACCESSED; 1365 TMPFS_NODE_UNLOCK(node); 1366 1367 return error; 1368 } 1369 1370 /* --------------------------------------------------------------------- */ 1371 1372 static int 1373 tmpfs_inactive(struct vop_inactive_args *v) 1374 { 1375 struct vnode *vp = v->a_vp; 1376 1377 struct tmpfs_node *node; 1378 1379 node = VP_TO_TMPFS_NODE(vp); 1380 1381 /* 1382 * Get rid of unreferenced deleted vnodes sooner rather than 1383 * later so the data memory can be recovered immediately. 1384 * 1385 * We must truncate the vnode to prevent the normal reclamation 1386 * path from flushing the data for the removed file to disk. 1387 */ 1388 TMPFS_NODE_LOCK(node); 1389 if ((node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0 && 1390 (node->tn_links == 0 || 1391 (node->tn_links == 1 && node->tn_type == VDIR && 1392 node->tn_dir.tn_parent))) 1393 { 1394 node->tn_vpstate = TMPFS_VNODE_DOOMED; 1395 TMPFS_NODE_UNLOCK(node); 1396 if (node->tn_type == VREG) 1397 tmpfs_truncate(vp, 0); 1398 vrecycle(vp); 1399 } else { 1400 TMPFS_NODE_UNLOCK(node); 1401 } 1402 1403 return 0; 1404 } 1405 1406 /* --------------------------------------------------------------------- */ 1407 1408 int 1409 tmpfs_reclaim(struct vop_reclaim_args *v) 1410 { 1411 struct vnode *vp = v->a_vp; 1412 struct tmpfs_mount *tmp; 1413 struct tmpfs_node *node; 1414 1415 node = VP_TO_TMPFS_NODE(vp); 1416 tmp = VFS_TO_TMPFS(vp->v_mount); 1417 1418 tmpfs_free_vp(vp); 1419 1420 /* 1421 * If the node referenced by this vnode was deleted by the 1422 * user, we must free its associated data structures now that 1423 * the vnode is being reclaimed. 1424 * 1425 * Directories have an extra link ref. 1426 */ 1427 TMPFS_NODE_LOCK(node); 1428 if ((node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0 && 1429 (node->tn_links == 0 || 1430 (node->tn_links == 1 && node->tn_type == VDIR && 1431 node->tn_dir.tn_parent))) 1432 { 1433 node->tn_vpstate = TMPFS_VNODE_DOOMED; 1434 tmpfs_free_node(tmp, node); 1435 /* eats the lock */ 1436 } else { 1437 TMPFS_NODE_UNLOCK(node); 1438 } 1439 1440 KKASSERT(vp->v_data == NULL); 1441 return 0; 1442 } 1443 1444 /* --------------------------------------------------------------------- */ 1445 1446 static int 1447 tmpfs_print(struct vop_print_args *v) 1448 { 1449 struct vnode *vp = v->a_vp; 1450 1451 struct tmpfs_node *node; 1452 1453 node = VP_TO_TMPFS_NODE(vp); 1454 1455 kprintf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n", 1456 node, node->tn_flags, node->tn_links); 1457 kprintf("\tmode 0%o, owner %d, group %d, size %ju, status 0x%x\n", 1458 node->tn_mode, node->tn_uid, node->tn_gid, 1459 (uintmax_t)node->tn_size, node->tn_status); 1460 1461 if (vp->v_type == VFIFO) 1462 fifo_printinfo(vp); 1463 1464 kprintf("\n"); 1465 1466 return 0; 1467 } 1468 1469 /* --------------------------------------------------------------------- */ 1470 1471 static int 1472 tmpfs_pathconf(struct vop_pathconf_args *v) 1473 { 1474 int name = v->a_name; 1475 register_t *retval = v->a_retval; 1476 1477 int error; 1478 1479 error = 0; 1480 1481 switch (name) { 1482 case _PC_LINK_MAX: 1483 *retval = LINK_MAX; 1484 break; 1485 1486 case _PC_NAME_MAX: 1487 *retval = NAME_MAX; 1488 break; 1489 1490 case _PC_PATH_MAX: 1491 *retval = PATH_MAX; 1492 break; 1493 1494 case _PC_PIPE_BUF: 1495 *retval = PIPE_BUF; 1496 break; 1497 1498 case _PC_CHOWN_RESTRICTED: 1499 *retval = 1; 1500 break; 1501 1502 case _PC_NO_TRUNC: 1503 *retval = 1; 1504 break; 1505 1506 case _PC_SYNC_IO: 1507 *retval = 1; 1508 break; 1509 1510 case _PC_FILESIZEBITS: 1511 *retval = 0; /* XXX Don't know which value should I return. */ 1512 break; 1513 1514 default: 1515 error = EINVAL; 1516 } 1517 1518 return error; 1519 } 1520 1521 /************************************************************************ 1522 * KQFILTER OPS * 1523 ************************************************************************/ 1524 1525 static void filt_tmpfsdetach(struct knote *kn); 1526 static int filt_tmpfsread(struct knote *kn, long hint); 1527 static int filt_tmpfswrite(struct knote *kn, long hint); 1528 static int filt_tmpfsvnode(struct knote *kn, long hint); 1529 1530 static struct filterops tmpfsread_filtops = 1531 { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfsread }; 1532 static struct filterops tmpfswrite_filtops = 1533 { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfswrite }; 1534 static struct filterops tmpfsvnode_filtops = 1535 { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfsvnode }; 1536 1537 static int 1538 tmpfs_kqfilter (struct vop_kqfilter_args *ap) 1539 { 1540 struct vnode *vp = ap->a_vp; 1541 struct knote *kn = ap->a_kn; 1542 1543 switch (kn->kn_filter) { 1544 case EVFILT_READ: 1545 kn->kn_fop = &tmpfsread_filtops; 1546 break; 1547 case EVFILT_WRITE: 1548 kn->kn_fop = &tmpfswrite_filtops; 1549 break; 1550 case EVFILT_VNODE: 1551 kn->kn_fop = &tmpfsvnode_filtops; 1552 break; 1553 default: 1554 return (EOPNOTSUPP); 1555 } 1556 1557 kn->kn_hook = (caddr_t)vp; 1558 1559 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1560 1561 return(0); 1562 } 1563 1564 static void 1565 filt_tmpfsdetach(struct knote *kn) 1566 { 1567 struct vnode *vp = (void *)kn->kn_hook; 1568 1569 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1570 } 1571 1572 static int 1573 filt_tmpfsread(struct knote *kn, long hint) 1574 { 1575 struct vnode *vp = (void *)kn->kn_hook; 1576 struct tmpfs_node *node = VP_TO_TMPFS_NODE(vp); 1577 off_t off; 1578 1579 if (hint == NOTE_REVOKE) { 1580 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 1581 return(1); 1582 } 1583 off = node->tn_size - kn->kn_fp->f_offset; 1584 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1585 if (kn->kn_sfflags & NOTE_OLDAPI) 1586 return(1); 1587 1588 /* 1589 * Handle possible MP race interlock on filter check/write 1590 */ 1591 if (kn->kn_data == 0) { 1592 get_mplock(); 1593 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1594 rel_mplock(); 1595 } 1596 return (kn->kn_data != 0); 1597 } 1598 1599 static int 1600 filt_tmpfswrite(struct knote *kn, long hint) 1601 { 1602 if (hint == NOTE_REVOKE) 1603 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 1604 kn->kn_data = 0; 1605 return (1); 1606 } 1607 1608 static int 1609 filt_tmpfsvnode(struct knote *kn, long hint) 1610 { 1611 if (kn->kn_sfflags & hint) 1612 kn->kn_fflags |= hint; 1613 if (hint == NOTE_REVOKE) { 1614 kn->kn_flags |= EV_EOF; 1615 return (1); 1616 } 1617 return (kn->kn_fflags != 0); 1618 } 1619 1620 1621 /* --------------------------------------------------------------------- */ 1622 1623 /* 1624 * vnode operations vector used for files stored in a tmpfs file system. 1625 */ 1626 struct vop_ops tmpfs_vnode_vops = { 1627 .vop_default = vop_defaultop, 1628 .vop_getpages = vop_stdgetpages, 1629 .vop_putpages = vop_stdputpages, 1630 .vop_ncreate = tmpfs_ncreate, 1631 .vop_nresolve = tmpfs_nresolve, 1632 .vop_nlookupdotdot = tmpfs_nlookupdotdot, 1633 .vop_nmknod = tmpfs_nmknod, 1634 .vop_open = tmpfs_open, 1635 .vop_close = tmpfs_close, 1636 .vop_access = tmpfs_access, 1637 .vop_getattr = tmpfs_getattr, 1638 .vop_setattr = tmpfs_setattr, 1639 .vop_read = tmpfs_read, 1640 .vop_write = tmpfs_write, 1641 .vop_fsync = tmpfs_fsync, 1642 .vop_nremove = tmpfs_nremove, 1643 .vop_nlink = tmpfs_nlink, 1644 .vop_nrename = tmpfs_nrename, 1645 .vop_nmkdir = tmpfs_nmkdir, 1646 .vop_nrmdir = tmpfs_nrmdir, 1647 .vop_nsymlink = tmpfs_nsymlink, 1648 .vop_readdir = tmpfs_readdir, 1649 .vop_readlink = tmpfs_readlink, 1650 .vop_inactive = tmpfs_inactive, 1651 .vop_reclaim = tmpfs_reclaim, 1652 .vop_print = tmpfs_print, 1653 .vop_pathconf = tmpfs_pathconf, 1654 .vop_bmap = tmpfs_bmap, 1655 .vop_strategy = tmpfs_strategy, 1656 .vop_advlock = tmpfs_advlock, 1657 .vop_kqfilter = tmpfs_kqfilter 1658 }; 1659