1 /* $NetBSD: tmpfs_subr.c,v 1.35 2007/07/09 21:10:50 ad Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5 * 6 * Copyright (c) 2005 The NetBSD Foundation, Inc. 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. 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 * Efficient memory file system supporting functions. 37 */ 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/dirent.h> 44 #include <sys/fnv_hash.h> 45 #include <sys/lock.h> 46 #include <sys/limits.h> 47 #include <sys/mount.h> 48 #include <sys/namei.h> 49 #include <sys/priv.h> 50 #include <sys/proc.h> 51 #include <sys/random.h> 52 #include <sys/rwlock.h> 53 #include <sys/stat.h> 54 #include <sys/sysctl.h> 55 #include <sys/vnode.h> 56 #include <sys/vmmeter.h> 57 58 #include <vm/vm.h> 59 #include <vm/vm_param.h> 60 #include <vm/vm_object.h> 61 #include <vm/vm_page.h> 62 #include <vm/vm_pageout.h> 63 #include <vm/vm_pager.h> 64 #include <vm/vm_extern.h> 65 #include <vm/swap_pager.h> 66 67 #include <fs/tmpfs/tmpfs.h> 68 #include <fs/tmpfs/tmpfs_fifoops.h> 69 #include <fs/tmpfs/tmpfs_vnops.h> 70 71 SYSCTL_NODE(_vfs, OID_AUTO, tmpfs, CTLFLAG_RW, 0, "tmpfs file system"); 72 73 static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED; 74 75 static uma_zone_t tmpfs_dirent_pool; 76 static uma_zone_t tmpfs_node_pool; 77 78 static int 79 tmpfs_node_ctor(void *mem, int size, void *arg, int flags) 80 { 81 struct tmpfs_node *node; 82 83 node = mem; 84 node->tn_gen++; 85 node->tn_size = 0; 86 node->tn_status = 0; 87 node->tn_flags = 0; 88 node->tn_links = 0; 89 node->tn_vnode = NULL; 90 node->tn_vpstate = 0; 91 return (0); 92 } 93 94 static void 95 tmpfs_node_dtor(void *mem, int size, void *arg) 96 { 97 struct tmpfs_node *node; 98 99 node = mem; 100 node->tn_type = VNON; 101 } 102 103 static int 104 tmpfs_node_init(void *mem, int size, int flags) 105 { 106 struct tmpfs_node *node; 107 108 node = mem; 109 node->tn_id = 0; 110 mtx_init(&node->tn_interlock, "tmpfsni", NULL, MTX_DEF); 111 node->tn_gen = arc4random(); 112 return (0); 113 } 114 115 static void 116 tmpfs_node_fini(void *mem, int size) 117 { 118 struct tmpfs_node *node; 119 120 node = mem; 121 mtx_destroy(&node->tn_interlock); 122 } 123 124 void 125 tmpfs_subr_init(void) 126 { 127 tmpfs_dirent_pool = uma_zcreate("TMPFS dirent", 128 sizeof(struct tmpfs_dirent), NULL, NULL, NULL, NULL, 129 UMA_ALIGN_PTR, 0); 130 tmpfs_node_pool = uma_zcreate("TMPFS node", 131 sizeof(struct tmpfs_node), tmpfs_node_ctor, tmpfs_node_dtor, 132 tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, 0); 133 } 134 135 void 136 tmpfs_subr_uninit(void) 137 { 138 uma_zdestroy(tmpfs_node_pool); 139 uma_zdestroy(tmpfs_dirent_pool); 140 } 141 142 static int 143 sysctl_mem_reserved(SYSCTL_HANDLER_ARGS) 144 { 145 int error; 146 long pages, bytes; 147 148 pages = *(long *)arg1; 149 bytes = pages * PAGE_SIZE; 150 151 error = sysctl_handle_long(oidp, &bytes, 0, req); 152 if (error || !req->newptr) 153 return (error); 154 155 pages = bytes / PAGE_SIZE; 156 if (pages < TMPFS_PAGES_MINRESERVED) 157 return (EINVAL); 158 159 *(long *)arg1 = pages; 160 return (0); 161 } 162 163 SYSCTL_PROC(_vfs_tmpfs, OID_AUTO, memory_reserved, 164 CTLTYPE_LONG|CTLFLAG_MPSAFE|CTLFLAG_RW, &tmpfs_pages_reserved, 0, 165 sysctl_mem_reserved, "L", 166 "Amount of available memory and swap below which tmpfs growth stops"); 167 168 static __inline int tmpfs_dirtree_cmp(struct tmpfs_dirent *a, 169 struct tmpfs_dirent *b); 170 RB_PROTOTYPE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp); 171 172 size_t 173 tmpfs_mem_avail(void) 174 { 175 vm_ooffset_t avail; 176 177 avail = swap_pager_avail + vm_free_count() - tmpfs_pages_reserved; 178 if (__predict_false(avail < 0)) 179 avail = 0; 180 return (avail); 181 } 182 183 size_t 184 tmpfs_pages_used(struct tmpfs_mount *tmp) 185 { 186 const size_t node_size = sizeof(struct tmpfs_node) + 187 sizeof(struct tmpfs_dirent); 188 size_t meta_pages; 189 190 meta_pages = howmany((uintmax_t)tmp->tm_nodes_inuse * node_size, 191 PAGE_SIZE); 192 return (meta_pages + tmp->tm_pages_used); 193 } 194 195 static size_t 196 tmpfs_pages_check_avail(struct tmpfs_mount *tmp, size_t req_pages) 197 { 198 if (tmpfs_mem_avail() < req_pages) 199 return (0); 200 201 if (tmp->tm_pages_max != ULONG_MAX && 202 tmp->tm_pages_max < req_pages + tmpfs_pages_used(tmp)) 203 return (0); 204 205 return (1); 206 } 207 208 void 209 tmpfs_ref_node(struct tmpfs_node *node) 210 { 211 212 TMPFS_NODE_LOCK(node); 213 tmpfs_ref_node_locked(node); 214 TMPFS_NODE_UNLOCK(node); 215 } 216 217 void 218 tmpfs_ref_node_locked(struct tmpfs_node *node) 219 { 220 221 TMPFS_NODE_ASSERT_LOCKED(node); 222 KASSERT(node->tn_refcount > 0, ("node %p zero refcount", node)); 223 KASSERT(node->tn_refcount < UINT_MAX, ("node %p refcount %u", node, 224 node->tn_refcount)); 225 node->tn_refcount++; 226 } 227 228 /* 229 * Allocates a new node of type 'type' inside the 'tmp' mount point, with 230 * its owner set to 'uid', its group to 'gid' and its mode set to 'mode', 231 * using the credentials of the process 'p'. 232 * 233 * If the node type is set to 'VDIR', then the parent parameter must point 234 * to the parent directory of the node being created. It may only be NULL 235 * while allocating the root node. 236 * 237 * If the node type is set to 'VBLK' or 'VCHR', then the rdev parameter 238 * specifies the device the node represents. 239 * 240 * If the node type is set to 'VLNK', then the parameter target specifies 241 * the file name of the target file for the symbolic link that is being 242 * created. 243 * 244 * Note that new nodes are retrieved from the available list if it has 245 * items or, if it is empty, from the node pool as long as there is enough 246 * space to create them. 247 * 248 * Returns zero on success or an appropriate error code on failure. 249 */ 250 int 251 tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *tmp, enum vtype type, 252 uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *parent, 253 const char *target, dev_t rdev, struct tmpfs_node **node) 254 { 255 struct tmpfs_node *nnode; 256 vm_object_t obj; 257 258 /* If the root directory of the 'tmp' file system is not yet 259 * allocated, this must be the request to do it. */ 260 MPASS(IMPLIES(tmp->tm_root == NULL, parent == NULL && type == VDIR)); 261 262 MPASS(IFF(type == VLNK, target != NULL)); 263 MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); 264 265 if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max) 266 return (ENOSPC); 267 if (tmpfs_pages_check_avail(tmp, 1) == 0) 268 return (ENOSPC); 269 270 if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) { 271 /* 272 * When a new tmpfs node is created for fully 273 * constructed mount point, there must be a parent 274 * node, which vnode is locked exclusively. As 275 * consequence, if the unmount is executing in 276 * parallel, vflush() cannot reclaim the parent vnode. 277 * Due to this, the check for MNTK_UNMOUNT flag is not 278 * racy: if we did not see MNTK_UNMOUNT flag, then tmp 279 * cannot be destroyed until node construction is 280 * finished and the parent vnode unlocked. 281 * 282 * Tmpfs does not need to instantiate new nodes during 283 * unmount. 284 */ 285 return (EBUSY); 286 } 287 if ((mp->mnt_kern_flag & MNT_RDONLY) != 0) 288 return (EROFS); 289 290 nnode = uma_zalloc_arg(tmpfs_node_pool, tmp, M_WAITOK); 291 292 /* Generic initialization. */ 293 nnode->tn_type = type; 294 vfs_timestamp(&nnode->tn_atime); 295 nnode->tn_birthtime = nnode->tn_ctime = nnode->tn_mtime = 296 nnode->tn_atime; 297 nnode->tn_uid = uid; 298 nnode->tn_gid = gid; 299 nnode->tn_mode = mode; 300 nnode->tn_id = alloc_unr64(&tmp->tm_ino_unr); 301 nnode->tn_refcount = 1; 302 303 /* Type-specific initialization. */ 304 switch (nnode->tn_type) { 305 case VBLK: 306 case VCHR: 307 nnode->tn_rdev = rdev; 308 break; 309 310 case VDIR: 311 RB_INIT(&nnode->tn_dir.tn_dirhead); 312 LIST_INIT(&nnode->tn_dir.tn_dupindex); 313 MPASS(parent != nnode); 314 MPASS(IMPLIES(parent == NULL, tmp->tm_root == NULL)); 315 nnode->tn_dir.tn_parent = (parent == NULL) ? nnode : parent; 316 nnode->tn_dir.tn_readdir_lastn = 0; 317 nnode->tn_dir.tn_readdir_lastp = NULL; 318 nnode->tn_links++; 319 TMPFS_NODE_LOCK(nnode->tn_dir.tn_parent); 320 nnode->tn_dir.tn_parent->tn_links++; 321 TMPFS_NODE_UNLOCK(nnode->tn_dir.tn_parent); 322 break; 323 324 case VFIFO: 325 /* FALLTHROUGH */ 326 case VSOCK: 327 break; 328 329 case VLNK: 330 MPASS(strlen(target) < MAXPATHLEN); 331 nnode->tn_size = strlen(target); 332 nnode->tn_link = malloc(nnode->tn_size, M_TMPFSNAME, 333 M_WAITOK); 334 memcpy(nnode->tn_link, target, nnode->tn_size); 335 break; 336 337 case VREG: 338 obj = nnode->tn_reg.tn_aobj = 339 vm_pager_allocate(OBJT_SWAP, NULL, 0, VM_PROT_DEFAULT, 0, 340 NULL /* XXXKIB - tmpfs needs swap reservation */); 341 VM_OBJECT_WLOCK(obj); 342 /* OBJ_TMPFS is set together with the setting of vp->v_object */ 343 vm_object_set_flag(obj, OBJ_TMPFS_NODE); 344 VM_OBJECT_WUNLOCK(obj); 345 break; 346 347 default: 348 panic("tmpfs_alloc_node: type %p %d", nnode, 349 (int)nnode->tn_type); 350 } 351 352 TMPFS_LOCK(tmp); 353 LIST_INSERT_HEAD(&tmp->tm_nodes_used, nnode, tn_entries); 354 nnode->tn_attached = true; 355 tmp->tm_nodes_inuse++; 356 tmp->tm_refcount++; 357 TMPFS_UNLOCK(tmp); 358 359 *node = nnode; 360 return (0); 361 } 362 363 /* 364 * Destroys the node pointed to by node from the file system 'tmp'. 365 * If the node references a directory, no entries are allowed. 366 */ 367 void 368 tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) 369 { 370 371 TMPFS_LOCK(tmp); 372 TMPFS_NODE_LOCK(node); 373 if (!tmpfs_free_node_locked(tmp, node, false)) { 374 TMPFS_NODE_UNLOCK(node); 375 TMPFS_UNLOCK(tmp); 376 } 377 } 378 379 bool 380 tmpfs_free_node_locked(struct tmpfs_mount *tmp, struct tmpfs_node *node, 381 bool detach) 382 { 383 vm_object_t uobj; 384 385 TMPFS_MP_ASSERT_LOCKED(tmp); 386 TMPFS_NODE_ASSERT_LOCKED(node); 387 KASSERT(node->tn_refcount > 0, ("node %p refcount zero", node)); 388 389 node->tn_refcount--; 390 if (node->tn_attached && (detach || node->tn_refcount == 0)) { 391 MPASS(tmp->tm_nodes_inuse > 0); 392 tmp->tm_nodes_inuse--; 393 LIST_REMOVE(node, tn_entries); 394 node->tn_attached = false; 395 } 396 if (node->tn_refcount > 0) 397 return (false); 398 399 #ifdef INVARIANTS 400 MPASS(node->tn_vnode == NULL); 401 MPASS((node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0); 402 #endif 403 TMPFS_NODE_UNLOCK(node); 404 TMPFS_UNLOCK(tmp); 405 406 switch (node->tn_type) { 407 case VBLK: 408 /* FALLTHROUGH */ 409 case VCHR: 410 /* FALLTHROUGH */ 411 case VDIR: 412 /* FALLTHROUGH */ 413 case VFIFO: 414 /* FALLTHROUGH */ 415 case VSOCK: 416 break; 417 418 case VLNK: 419 free(node->tn_link, M_TMPFSNAME); 420 break; 421 422 case VREG: 423 uobj = node->tn_reg.tn_aobj; 424 if (uobj != NULL) { 425 if (uobj->size != 0) 426 atomic_subtract_long(&tmp->tm_pages_used, uobj->size); 427 KASSERT((uobj->flags & OBJ_TMPFS) == 0, 428 ("leaked OBJ_TMPFS node %p vm_obj %p", node, uobj)); 429 vm_object_deallocate(uobj); 430 } 431 break; 432 433 default: 434 panic("tmpfs_free_node: type %p %d", node, (int)node->tn_type); 435 } 436 437 uma_zfree(tmpfs_node_pool, node); 438 TMPFS_LOCK(tmp); 439 tmpfs_free_tmp(tmp); 440 return (true); 441 } 442 443 static __inline uint32_t 444 tmpfs_dirent_hash(const char *name, u_int len) 445 { 446 uint32_t hash; 447 448 hash = fnv_32_buf(name, len, FNV1_32_INIT + len) & TMPFS_DIRCOOKIE_MASK; 449 #ifdef TMPFS_DEBUG_DIRCOOKIE_DUP 450 hash &= 0xf; 451 #endif 452 if (hash < TMPFS_DIRCOOKIE_MIN) 453 hash += TMPFS_DIRCOOKIE_MIN; 454 455 return (hash); 456 } 457 458 static __inline off_t 459 tmpfs_dirent_cookie(struct tmpfs_dirent *de) 460 { 461 if (de == NULL) 462 return (TMPFS_DIRCOOKIE_EOF); 463 464 MPASS(de->td_cookie >= TMPFS_DIRCOOKIE_MIN); 465 466 return (de->td_cookie); 467 } 468 469 static __inline boolean_t 470 tmpfs_dirent_dup(struct tmpfs_dirent *de) 471 { 472 return ((de->td_cookie & TMPFS_DIRCOOKIE_DUP) != 0); 473 } 474 475 static __inline boolean_t 476 tmpfs_dirent_duphead(struct tmpfs_dirent *de) 477 { 478 return ((de->td_cookie & TMPFS_DIRCOOKIE_DUPHEAD) != 0); 479 } 480 481 void 482 tmpfs_dirent_init(struct tmpfs_dirent *de, const char *name, u_int namelen) 483 { 484 de->td_hash = de->td_cookie = tmpfs_dirent_hash(name, namelen); 485 memcpy(de->ud.td_name, name, namelen); 486 de->td_namelen = namelen; 487 } 488 489 /* 490 * Allocates a new directory entry for the node node with a name of name. 491 * The new directory entry is returned in *de. 492 * 493 * The link count of node is increased by one to reflect the new object 494 * referencing it. 495 * 496 * Returns zero on success or an appropriate error code on failure. 497 */ 498 int 499 tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, 500 const char *name, u_int len, struct tmpfs_dirent **de) 501 { 502 struct tmpfs_dirent *nde; 503 504 nde = uma_zalloc(tmpfs_dirent_pool, M_WAITOK); 505 nde->td_node = node; 506 if (name != NULL) { 507 nde->ud.td_name = malloc(len, M_TMPFSNAME, M_WAITOK); 508 tmpfs_dirent_init(nde, name, len); 509 } else 510 nde->td_namelen = 0; 511 if (node != NULL) 512 node->tn_links++; 513 514 *de = nde; 515 516 return 0; 517 } 518 519 /* 520 * Frees a directory entry. It is the caller's responsibility to destroy 521 * the node referenced by it if needed. 522 * 523 * The link count of node is decreased by one to reflect the removal of an 524 * object that referenced it. This only happens if 'node_exists' is true; 525 * otherwise the function will not access the node referred to by the 526 * directory entry, as it may already have been released from the outside. 527 */ 528 void 529 tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de) 530 { 531 struct tmpfs_node *node; 532 533 node = de->td_node; 534 if (node != NULL) { 535 MPASS(node->tn_links > 0); 536 node->tn_links--; 537 } 538 if (!tmpfs_dirent_duphead(de) && de->ud.td_name != NULL) 539 free(de->ud.td_name, M_TMPFSNAME); 540 uma_zfree(tmpfs_dirent_pool, de); 541 } 542 543 void 544 tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj) 545 { 546 547 ASSERT_VOP_ELOCKED(vp, "tmpfs_destroy_vobject"); 548 if (vp->v_type != VREG || obj == NULL) 549 return; 550 551 VM_OBJECT_WLOCK(obj); 552 VI_LOCK(vp); 553 vm_object_clear_flag(obj, OBJ_TMPFS); 554 obj->un_pager.swp.swp_tmpfs = NULL; 555 if (vp->v_writecount < 0) 556 vp->v_writecount = 0; 557 VI_UNLOCK(vp); 558 VM_OBJECT_WUNLOCK(obj); 559 } 560 561 /* 562 * Need to clear v_object for insmntque failure. 563 */ 564 static void 565 tmpfs_insmntque_dtr(struct vnode *vp, void *dtr_arg) 566 { 567 568 tmpfs_destroy_vobject(vp, vp->v_object); 569 vp->v_object = NULL; 570 vp->v_data = NULL; 571 vp->v_op = &dead_vnodeops; 572 vgone(vp); 573 vput(vp); 574 } 575 576 /* 577 * Allocates a new vnode for the node node or returns a new reference to 578 * an existing one if the node had already a vnode referencing it. The 579 * resulting locked vnode is returned in *vpp. 580 * 581 * Returns zero on success or an appropriate error code on failure. 582 */ 583 int 584 tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag, 585 struct vnode **vpp) 586 { 587 struct vnode *vp; 588 struct tmpfs_mount *tm; 589 vm_object_t object; 590 int error; 591 592 error = 0; 593 tm = VFS_TO_TMPFS(mp); 594 TMPFS_NODE_LOCK(node); 595 tmpfs_ref_node_locked(node); 596 loop: 597 TMPFS_NODE_ASSERT_LOCKED(node); 598 if ((vp = node->tn_vnode) != NULL) { 599 MPASS((node->tn_vpstate & TMPFS_VNODE_DOOMED) == 0); 600 VI_LOCK(vp); 601 if ((node->tn_type == VDIR && node->tn_dir.tn_parent == NULL) || 602 (VN_IS_DOOMED(vp) && 603 (lkflag & LK_NOWAIT) != 0)) { 604 VI_UNLOCK(vp); 605 TMPFS_NODE_UNLOCK(node); 606 error = ENOENT; 607 vp = NULL; 608 goto out; 609 } 610 if (VN_IS_DOOMED(vp)) { 611 VI_UNLOCK(vp); 612 node->tn_vpstate |= TMPFS_VNODE_WRECLAIM; 613 while ((node->tn_vpstate & TMPFS_VNODE_WRECLAIM) != 0) { 614 msleep(&node->tn_vnode, TMPFS_NODE_MTX(node), 615 0, "tmpfsE", 0); 616 } 617 goto loop; 618 } 619 TMPFS_NODE_UNLOCK(node); 620 error = vget(vp, lkflag | LK_INTERLOCK, curthread); 621 if (error == ENOENT) { 622 TMPFS_NODE_LOCK(node); 623 goto loop; 624 } 625 if (error != 0) { 626 vp = NULL; 627 goto out; 628 } 629 630 /* 631 * Make sure the vnode is still there after 632 * getting the interlock to avoid racing a free. 633 */ 634 if (node->tn_vnode == NULL || node->tn_vnode != vp) { 635 vput(vp); 636 TMPFS_NODE_LOCK(node); 637 goto loop; 638 } 639 640 goto out; 641 } 642 643 if ((node->tn_vpstate & TMPFS_VNODE_DOOMED) || 644 (node->tn_type == VDIR && node->tn_dir.tn_parent == NULL)) { 645 TMPFS_NODE_UNLOCK(node); 646 error = ENOENT; 647 vp = NULL; 648 goto out; 649 } 650 651 /* 652 * otherwise lock the vp list while we call getnewvnode 653 * since that can block. 654 */ 655 if (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) { 656 node->tn_vpstate |= TMPFS_VNODE_WANT; 657 error = msleep((caddr_t) &node->tn_vpstate, 658 TMPFS_NODE_MTX(node), 0, "tmpfs_alloc_vp", 0); 659 if (error != 0) 660 goto out; 661 goto loop; 662 } else 663 node->tn_vpstate |= TMPFS_VNODE_ALLOCATING; 664 665 TMPFS_NODE_UNLOCK(node); 666 667 /* Get a new vnode and associate it with our node. */ 668 error = getnewvnode("tmpfs", mp, VFS_TO_TMPFS(mp)->tm_nonc ? 669 &tmpfs_vnodeop_nonc_entries : &tmpfs_vnodeop_entries, &vp); 670 if (error != 0) 671 goto unlock; 672 MPASS(vp != NULL); 673 674 /* lkflag is ignored, the lock is exclusive */ 675 (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 676 677 vp->v_data = node; 678 vp->v_type = node->tn_type; 679 680 /* Type-specific initialization. */ 681 switch (node->tn_type) { 682 case VBLK: 683 /* FALLTHROUGH */ 684 case VCHR: 685 /* FALLTHROUGH */ 686 case VLNK: 687 /* FALLTHROUGH */ 688 case VSOCK: 689 break; 690 case VFIFO: 691 vp->v_op = &tmpfs_fifoop_entries; 692 break; 693 case VREG: 694 object = node->tn_reg.tn_aobj; 695 VM_OBJECT_WLOCK(object); 696 VI_LOCK(vp); 697 KASSERT(vp->v_object == NULL, ("Not NULL v_object in tmpfs")); 698 vp->v_object = object; 699 object->un_pager.swp.swp_tmpfs = vp; 700 vm_object_set_flag(object, OBJ_TMPFS); 701 VI_UNLOCK(vp); 702 VM_OBJECT_WUNLOCK(object); 703 break; 704 case VDIR: 705 MPASS(node->tn_dir.tn_parent != NULL); 706 if (node->tn_dir.tn_parent == node) 707 vp->v_vflag |= VV_ROOT; 708 break; 709 710 default: 711 panic("tmpfs_alloc_vp: type %p %d", node, (int)node->tn_type); 712 } 713 if (vp->v_type != VFIFO) 714 VN_LOCK_ASHARE(vp); 715 716 error = insmntque1(vp, mp, tmpfs_insmntque_dtr, NULL); 717 if (error != 0) 718 vp = NULL; 719 720 unlock: 721 TMPFS_NODE_LOCK(node); 722 723 MPASS(node->tn_vpstate & TMPFS_VNODE_ALLOCATING); 724 node->tn_vpstate &= ~TMPFS_VNODE_ALLOCATING; 725 node->tn_vnode = vp; 726 727 if (node->tn_vpstate & TMPFS_VNODE_WANT) { 728 node->tn_vpstate &= ~TMPFS_VNODE_WANT; 729 TMPFS_NODE_UNLOCK(node); 730 wakeup((caddr_t) &node->tn_vpstate); 731 } else 732 TMPFS_NODE_UNLOCK(node); 733 734 out: 735 if (error == 0) { 736 *vpp = vp; 737 738 #ifdef INVARIANTS 739 MPASS(*vpp != NULL && VOP_ISLOCKED(*vpp)); 740 TMPFS_NODE_LOCK(node); 741 MPASS(*vpp == node->tn_vnode); 742 TMPFS_NODE_UNLOCK(node); 743 #endif 744 } 745 tmpfs_free_node(tm, node); 746 747 return (error); 748 } 749 750 /* 751 * Destroys the association between the vnode vp and the node it 752 * references. 753 */ 754 void 755 tmpfs_free_vp(struct vnode *vp) 756 { 757 struct tmpfs_node *node; 758 759 node = VP_TO_TMPFS_NODE(vp); 760 761 TMPFS_NODE_ASSERT_LOCKED(node); 762 node->tn_vnode = NULL; 763 if ((node->tn_vpstate & TMPFS_VNODE_WRECLAIM) != 0) 764 wakeup(&node->tn_vnode); 765 node->tn_vpstate &= ~TMPFS_VNODE_WRECLAIM; 766 vp->v_data = NULL; 767 } 768 769 /* 770 * Allocates a new file of type 'type' and adds it to the parent directory 771 * 'dvp'; this addition is done using the component name given in 'cnp'. 772 * The ownership of the new file is automatically assigned based on the 773 * credentials of the caller (through 'cnp'), the group is set based on 774 * the parent directory and the mode is determined from the 'vap' argument. 775 * If successful, *vpp holds a vnode to the newly created file and zero 776 * is returned. Otherwise *vpp is NULL and the function returns an 777 * appropriate error code. 778 */ 779 int 780 tmpfs_alloc_file(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, 781 struct componentname *cnp, const char *target) 782 { 783 int error; 784 struct tmpfs_dirent *de; 785 struct tmpfs_mount *tmp; 786 struct tmpfs_node *dnode; 787 struct tmpfs_node *node; 788 struct tmpfs_node *parent; 789 790 ASSERT_VOP_ELOCKED(dvp, "tmpfs_alloc_file"); 791 MPASS(cnp->cn_flags & HASBUF); 792 793 tmp = VFS_TO_TMPFS(dvp->v_mount); 794 dnode = VP_TO_TMPFS_DIR(dvp); 795 *vpp = NULL; 796 797 /* If the entry we are creating is a directory, we cannot overflow 798 * the number of links of its parent, because it will get a new 799 * link. */ 800 if (vap->va_type == VDIR) { 801 /* Ensure that we do not overflow the maximum number of links 802 * imposed by the system. */ 803 MPASS(dnode->tn_links <= TMPFS_LINK_MAX); 804 if (dnode->tn_links == TMPFS_LINK_MAX) { 805 return (EMLINK); 806 } 807 808 parent = dnode; 809 MPASS(parent != NULL); 810 } else 811 parent = NULL; 812 813 /* Allocate a node that represents the new file. */ 814 error = tmpfs_alloc_node(dvp->v_mount, tmp, vap->va_type, 815 cnp->cn_cred->cr_uid, dnode->tn_gid, vap->va_mode, parent, 816 target, vap->va_rdev, &node); 817 if (error != 0) 818 return (error); 819 820 /* Allocate a directory entry that points to the new file. */ 821 error = tmpfs_alloc_dirent(tmp, node, cnp->cn_nameptr, cnp->cn_namelen, 822 &de); 823 if (error != 0) { 824 tmpfs_free_node(tmp, node); 825 return (error); 826 } 827 828 /* Allocate a vnode for the new file. */ 829 error = tmpfs_alloc_vp(dvp->v_mount, node, LK_EXCLUSIVE, vpp); 830 if (error != 0) { 831 tmpfs_free_dirent(tmp, de); 832 tmpfs_free_node(tmp, node); 833 return (error); 834 } 835 836 /* Now that all required items are allocated, we can proceed to 837 * insert the new node into the directory, an operation that 838 * cannot fail. */ 839 if (cnp->cn_flags & ISWHITEOUT) 840 tmpfs_dir_whiteout_remove(dvp, cnp); 841 tmpfs_dir_attach(dvp, de); 842 return (0); 843 } 844 845 struct tmpfs_dirent * 846 tmpfs_dir_first(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc) 847 { 848 struct tmpfs_dirent *de; 849 850 de = RB_MIN(tmpfs_dir, &dnode->tn_dir.tn_dirhead); 851 dc->tdc_tree = de; 852 if (de != NULL && tmpfs_dirent_duphead(de)) 853 de = LIST_FIRST(&de->ud.td_duphead); 854 dc->tdc_current = de; 855 856 return (dc->tdc_current); 857 } 858 859 struct tmpfs_dirent * 860 tmpfs_dir_next(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc) 861 { 862 struct tmpfs_dirent *de; 863 864 MPASS(dc->tdc_tree != NULL); 865 if (tmpfs_dirent_dup(dc->tdc_current)) { 866 dc->tdc_current = LIST_NEXT(dc->tdc_current, uh.td_dup.entries); 867 if (dc->tdc_current != NULL) 868 return (dc->tdc_current); 869 } 870 dc->tdc_tree = dc->tdc_current = RB_NEXT(tmpfs_dir, 871 &dnode->tn_dir.tn_dirhead, dc->tdc_tree); 872 if ((de = dc->tdc_current) != NULL && tmpfs_dirent_duphead(de)) { 873 dc->tdc_current = LIST_FIRST(&de->ud.td_duphead); 874 MPASS(dc->tdc_current != NULL); 875 } 876 877 return (dc->tdc_current); 878 } 879 880 /* Lookup directory entry in RB-Tree. Function may return duphead entry. */ 881 static struct tmpfs_dirent * 882 tmpfs_dir_xlookup_hash(struct tmpfs_node *dnode, uint32_t hash) 883 { 884 struct tmpfs_dirent *de, dekey; 885 886 dekey.td_hash = hash; 887 de = RB_FIND(tmpfs_dir, &dnode->tn_dir.tn_dirhead, &dekey); 888 return (de); 889 } 890 891 /* Lookup directory entry by cookie, initialize directory cursor accordingly. */ 892 static struct tmpfs_dirent * 893 tmpfs_dir_lookup_cookie(struct tmpfs_node *node, off_t cookie, 894 struct tmpfs_dir_cursor *dc) 895 { 896 struct tmpfs_dir *dirhead = &node->tn_dir.tn_dirhead; 897 struct tmpfs_dirent *de, dekey; 898 899 MPASS(cookie >= TMPFS_DIRCOOKIE_MIN); 900 901 if (cookie == node->tn_dir.tn_readdir_lastn && 902 (de = node->tn_dir.tn_readdir_lastp) != NULL) { 903 /* Protect against possible race, tn_readdir_last[pn] 904 * may be updated with only shared vnode lock held. */ 905 if (cookie == tmpfs_dirent_cookie(de)) 906 goto out; 907 } 908 909 if ((cookie & TMPFS_DIRCOOKIE_DUP) != 0) { 910 LIST_FOREACH(de, &node->tn_dir.tn_dupindex, 911 uh.td_dup.index_entries) { 912 MPASS(tmpfs_dirent_dup(de)); 913 if (de->td_cookie == cookie) 914 goto out; 915 /* dupindex list is sorted. */ 916 if (de->td_cookie < cookie) { 917 de = NULL; 918 goto out; 919 } 920 } 921 MPASS(de == NULL); 922 goto out; 923 } 924 925 if ((cookie & TMPFS_DIRCOOKIE_MASK) != cookie) { 926 de = NULL; 927 } else { 928 dekey.td_hash = cookie; 929 /* Recover if direntry for cookie was removed */ 930 de = RB_NFIND(tmpfs_dir, dirhead, &dekey); 931 } 932 dc->tdc_tree = de; 933 dc->tdc_current = de; 934 if (de != NULL && tmpfs_dirent_duphead(de)) { 935 dc->tdc_current = LIST_FIRST(&de->ud.td_duphead); 936 MPASS(dc->tdc_current != NULL); 937 } 938 return (dc->tdc_current); 939 940 out: 941 dc->tdc_tree = de; 942 dc->tdc_current = de; 943 if (de != NULL && tmpfs_dirent_dup(de)) 944 dc->tdc_tree = tmpfs_dir_xlookup_hash(node, 945 de->td_hash); 946 return (dc->tdc_current); 947 } 948 949 /* 950 * Looks for a directory entry in the directory represented by node. 951 * 'cnp' describes the name of the entry to look for. Note that the . 952 * and .. components are not allowed as they do not physically exist 953 * within directories. 954 * 955 * Returns a pointer to the entry when found, otherwise NULL. 956 */ 957 struct tmpfs_dirent * 958 tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f, 959 struct componentname *cnp) 960 { 961 struct tmpfs_dir_duphead *duphead; 962 struct tmpfs_dirent *de; 963 uint32_t hash; 964 965 MPASS(IMPLIES(cnp->cn_namelen == 1, cnp->cn_nameptr[0] != '.')); 966 MPASS(IMPLIES(cnp->cn_namelen == 2, !(cnp->cn_nameptr[0] == '.' && 967 cnp->cn_nameptr[1] == '.'))); 968 TMPFS_VALIDATE_DIR(node); 969 970 hash = tmpfs_dirent_hash(cnp->cn_nameptr, cnp->cn_namelen); 971 de = tmpfs_dir_xlookup_hash(node, hash); 972 if (de != NULL && tmpfs_dirent_duphead(de)) { 973 duphead = &de->ud.td_duphead; 974 LIST_FOREACH(de, duphead, uh.td_dup.entries) { 975 if (TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr, 976 cnp->cn_namelen)) 977 break; 978 } 979 } else if (de != NULL) { 980 if (!TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr, 981 cnp->cn_namelen)) 982 de = NULL; 983 } 984 if (de != NULL && f != NULL && de->td_node != f) 985 de = NULL; 986 987 return (de); 988 } 989 990 /* 991 * Attach duplicate-cookie directory entry nde to dnode and insert to dupindex 992 * list, allocate new cookie value. 993 */ 994 static void 995 tmpfs_dir_attach_dup(struct tmpfs_node *dnode, 996 struct tmpfs_dir_duphead *duphead, struct tmpfs_dirent *nde) 997 { 998 struct tmpfs_dir_duphead *dupindex; 999 struct tmpfs_dirent *de, *pde; 1000 1001 dupindex = &dnode->tn_dir.tn_dupindex; 1002 de = LIST_FIRST(dupindex); 1003 if (de == NULL || de->td_cookie < TMPFS_DIRCOOKIE_DUP_MAX) { 1004 if (de == NULL) 1005 nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN; 1006 else 1007 nde->td_cookie = de->td_cookie + 1; 1008 MPASS(tmpfs_dirent_dup(nde)); 1009 LIST_INSERT_HEAD(dupindex, nde, uh.td_dup.index_entries); 1010 LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries); 1011 return; 1012 } 1013 1014 /* 1015 * Cookie numbers are near exhaustion. Scan dupindex list for unused 1016 * numbers. dupindex list is sorted in descending order. Keep it so 1017 * after inserting nde. 1018 */ 1019 while (1) { 1020 pde = de; 1021 de = LIST_NEXT(de, uh.td_dup.index_entries); 1022 if (de == NULL && pde->td_cookie != TMPFS_DIRCOOKIE_DUP_MIN) { 1023 /* 1024 * Last element of the index doesn't have minimal cookie 1025 * value, use it. 1026 */ 1027 nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN; 1028 LIST_INSERT_AFTER(pde, nde, uh.td_dup.index_entries); 1029 LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries); 1030 return; 1031 } else if (de == NULL) { 1032 /* 1033 * We are so lucky have 2^30 hash duplicates in single 1034 * directory :) Return largest possible cookie value. 1035 * It should be fine except possible issues with 1036 * VOP_READDIR restart. 1037 */ 1038 nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MAX; 1039 LIST_INSERT_HEAD(dupindex, nde, 1040 uh.td_dup.index_entries); 1041 LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries); 1042 return; 1043 } 1044 if (de->td_cookie + 1 == pde->td_cookie || 1045 de->td_cookie >= TMPFS_DIRCOOKIE_DUP_MAX) 1046 continue; /* No hole or invalid cookie. */ 1047 nde->td_cookie = de->td_cookie + 1; 1048 MPASS(tmpfs_dirent_dup(nde)); 1049 MPASS(pde->td_cookie > nde->td_cookie); 1050 MPASS(nde->td_cookie > de->td_cookie); 1051 LIST_INSERT_BEFORE(de, nde, uh.td_dup.index_entries); 1052 LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries); 1053 return; 1054 } 1055 } 1056 1057 /* 1058 * Attaches the directory entry de to the directory represented by vp. 1059 * Note that this does not change the link count of the node pointed by 1060 * the directory entry, as this is done by tmpfs_alloc_dirent. 1061 */ 1062 void 1063 tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de) 1064 { 1065 struct tmpfs_node *dnode; 1066 struct tmpfs_dirent *xde, *nde; 1067 1068 ASSERT_VOP_ELOCKED(vp, __func__); 1069 MPASS(de->td_namelen > 0); 1070 MPASS(de->td_hash >= TMPFS_DIRCOOKIE_MIN); 1071 MPASS(de->td_cookie == de->td_hash); 1072 1073 dnode = VP_TO_TMPFS_DIR(vp); 1074 dnode->tn_dir.tn_readdir_lastn = 0; 1075 dnode->tn_dir.tn_readdir_lastp = NULL; 1076 1077 MPASS(!tmpfs_dirent_dup(de)); 1078 xde = RB_INSERT(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de); 1079 if (xde != NULL && tmpfs_dirent_duphead(xde)) 1080 tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de); 1081 else if (xde != NULL) { 1082 /* 1083 * Allocate new duphead. Swap xde with duphead to avoid 1084 * adding/removing elements with the same hash. 1085 */ 1086 MPASS(!tmpfs_dirent_dup(xde)); 1087 tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), NULL, NULL, 0, 1088 &nde); 1089 /* *nde = *xde; XXX gcc 4.2.1 may generate invalid code. */ 1090 memcpy(nde, xde, sizeof(*xde)); 1091 xde->td_cookie |= TMPFS_DIRCOOKIE_DUPHEAD; 1092 LIST_INIT(&xde->ud.td_duphead); 1093 xde->td_namelen = 0; 1094 xde->td_node = NULL; 1095 tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, nde); 1096 tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de); 1097 } 1098 dnode->tn_size += sizeof(struct tmpfs_dirent); 1099 dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ 1100 TMPFS_NODE_MODIFIED; 1101 tmpfs_update(vp); 1102 } 1103 1104 /* 1105 * Detaches the directory entry de from the directory represented by vp. 1106 * Note that this does not change the link count of the node pointed by 1107 * the directory entry, as this is done by tmpfs_free_dirent. 1108 */ 1109 void 1110 tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de) 1111 { 1112 struct tmpfs_mount *tmp; 1113 struct tmpfs_dir *head; 1114 struct tmpfs_node *dnode; 1115 struct tmpfs_dirent *xde; 1116 1117 ASSERT_VOP_ELOCKED(vp, __func__); 1118 1119 dnode = VP_TO_TMPFS_DIR(vp); 1120 head = &dnode->tn_dir.tn_dirhead; 1121 dnode->tn_dir.tn_readdir_lastn = 0; 1122 dnode->tn_dir.tn_readdir_lastp = NULL; 1123 1124 if (tmpfs_dirent_dup(de)) { 1125 /* Remove duphead if de was last entry. */ 1126 if (LIST_NEXT(de, uh.td_dup.entries) == NULL) { 1127 xde = tmpfs_dir_xlookup_hash(dnode, de->td_hash); 1128 MPASS(tmpfs_dirent_duphead(xde)); 1129 } else 1130 xde = NULL; 1131 LIST_REMOVE(de, uh.td_dup.entries); 1132 LIST_REMOVE(de, uh.td_dup.index_entries); 1133 if (xde != NULL) { 1134 if (LIST_EMPTY(&xde->ud.td_duphead)) { 1135 RB_REMOVE(tmpfs_dir, head, xde); 1136 tmp = VFS_TO_TMPFS(vp->v_mount); 1137 MPASS(xde->td_node == NULL); 1138 tmpfs_free_dirent(tmp, xde); 1139 } 1140 } 1141 de->td_cookie = de->td_hash; 1142 } else 1143 RB_REMOVE(tmpfs_dir, head, de); 1144 1145 dnode->tn_size -= sizeof(struct tmpfs_dirent); 1146 dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ 1147 TMPFS_NODE_MODIFIED; 1148 tmpfs_update(vp); 1149 } 1150 1151 void 1152 tmpfs_dir_destroy(struct tmpfs_mount *tmp, struct tmpfs_node *dnode) 1153 { 1154 struct tmpfs_dirent *de, *dde, *nde; 1155 1156 RB_FOREACH_SAFE(de, tmpfs_dir, &dnode->tn_dir.tn_dirhead, nde) { 1157 RB_REMOVE(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de); 1158 /* Node may already be destroyed. */ 1159 de->td_node = NULL; 1160 if (tmpfs_dirent_duphead(de)) { 1161 while ((dde = LIST_FIRST(&de->ud.td_duphead)) != NULL) { 1162 LIST_REMOVE(dde, uh.td_dup.entries); 1163 dde->td_node = NULL; 1164 tmpfs_free_dirent(tmp, dde); 1165 } 1166 } 1167 tmpfs_free_dirent(tmp, de); 1168 } 1169 } 1170 1171 /* 1172 * Helper function for tmpfs_readdir. Creates a '.' entry for the given 1173 * directory and returns it in the uio space. The function returns 0 1174 * on success, -1 if there was not enough space in the uio structure to 1175 * hold the directory entry or an appropriate error code if another 1176 * error happens. 1177 */ 1178 static int 1179 tmpfs_dir_getdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, 1180 struct uio *uio) 1181 { 1182 int error; 1183 struct dirent dent; 1184 1185 TMPFS_VALIDATE_DIR(node); 1186 MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOT); 1187 1188 dent.d_fileno = node->tn_id; 1189 dent.d_type = DT_DIR; 1190 dent.d_namlen = 1; 1191 dent.d_name[0] = '.'; 1192 dent.d_reclen = GENERIC_DIRSIZ(&dent); 1193 dirent_terminate(&dent); 1194 1195 if (dent.d_reclen > uio->uio_resid) 1196 error = EJUSTRETURN; 1197 else 1198 error = uiomove(&dent, dent.d_reclen, uio); 1199 1200 tmpfs_set_status(tm, node, TMPFS_NODE_ACCESSED); 1201 1202 return (error); 1203 } 1204 1205 /* 1206 * Helper function for tmpfs_readdir. Creates a '..' entry for the given 1207 * directory and returns it in the uio space. The function returns 0 1208 * on success, -1 if there was not enough space in the uio structure to 1209 * hold the directory entry or an appropriate error code if another 1210 * error happens. 1211 */ 1212 static int 1213 tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, 1214 struct uio *uio) 1215 { 1216 struct tmpfs_node *parent; 1217 struct dirent dent; 1218 int error; 1219 1220 TMPFS_VALIDATE_DIR(node); 1221 MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT); 1222 1223 /* 1224 * Return ENOENT if the current node is already removed. 1225 */ 1226 TMPFS_ASSERT_LOCKED(node); 1227 parent = node->tn_dir.tn_parent; 1228 if (parent == NULL) 1229 return (ENOENT); 1230 1231 TMPFS_NODE_LOCK(parent); 1232 dent.d_fileno = parent->tn_id; 1233 TMPFS_NODE_UNLOCK(parent); 1234 1235 dent.d_type = DT_DIR; 1236 dent.d_namlen = 2; 1237 dent.d_name[0] = '.'; 1238 dent.d_name[1] = '.'; 1239 dent.d_reclen = GENERIC_DIRSIZ(&dent); 1240 dirent_terminate(&dent); 1241 1242 if (dent.d_reclen > uio->uio_resid) 1243 error = EJUSTRETURN; 1244 else 1245 error = uiomove(&dent, dent.d_reclen, uio); 1246 1247 tmpfs_set_status(tm, node, TMPFS_NODE_ACCESSED); 1248 1249 return (error); 1250 } 1251 1252 /* 1253 * Helper function for tmpfs_readdir. Returns as much directory entries 1254 * as can fit in the uio space. The read starts at uio->uio_offset. 1255 * The function returns 0 on success, -1 if there was not enough space 1256 * in the uio structure to hold the directory entry or an appropriate 1257 * error code if another error happens. 1258 */ 1259 int 1260 tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node, 1261 struct uio *uio, int maxcookies, u_long *cookies, int *ncookies) 1262 { 1263 struct tmpfs_dir_cursor dc; 1264 struct tmpfs_dirent *de; 1265 off_t off; 1266 int error; 1267 1268 TMPFS_VALIDATE_DIR(node); 1269 1270 off = 0; 1271 1272 /* 1273 * Lookup the node from the current offset. The starting offset of 1274 * 0 will lookup both '.' and '..', and then the first real entry, 1275 * or EOF if there are none. Then find all entries for the dir that 1276 * fit into the buffer. Once no more entries are found (de == NULL), 1277 * the offset is set to TMPFS_DIRCOOKIE_EOF, which will cause the next 1278 * call to return 0. 1279 */ 1280 switch (uio->uio_offset) { 1281 case TMPFS_DIRCOOKIE_DOT: 1282 error = tmpfs_dir_getdotdent(tm, node, uio); 1283 if (error != 0) 1284 return (error); 1285 uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; 1286 if (cookies != NULL) 1287 cookies[(*ncookies)++] = off = uio->uio_offset; 1288 /* FALLTHROUGH */ 1289 case TMPFS_DIRCOOKIE_DOTDOT: 1290 error = tmpfs_dir_getdotdotdent(tm, node, uio); 1291 if (error != 0) 1292 return (error); 1293 de = tmpfs_dir_first(node, &dc); 1294 uio->uio_offset = tmpfs_dirent_cookie(de); 1295 if (cookies != NULL) 1296 cookies[(*ncookies)++] = off = uio->uio_offset; 1297 /* EOF. */ 1298 if (de == NULL) 1299 return (0); 1300 break; 1301 case TMPFS_DIRCOOKIE_EOF: 1302 return (0); 1303 default: 1304 de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc); 1305 if (de == NULL) 1306 return (EINVAL); 1307 if (cookies != NULL) 1308 off = tmpfs_dirent_cookie(de); 1309 } 1310 1311 /* Read as much entries as possible; i.e., until we reach the end of 1312 * the directory or we exhaust uio space. */ 1313 do { 1314 struct dirent d; 1315 1316 /* Create a dirent structure representing the current 1317 * tmpfs_node and fill it. */ 1318 if (de->td_node == NULL) { 1319 d.d_fileno = 1; 1320 d.d_type = DT_WHT; 1321 } else { 1322 d.d_fileno = de->td_node->tn_id; 1323 switch (de->td_node->tn_type) { 1324 case VBLK: 1325 d.d_type = DT_BLK; 1326 break; 1327 1328 case VCHR: 1329 d.d_type = DT_CHR; 1330 break; 1331 1332 case VDIR: 1333 d.d_type = DT_DIR; 1334 break; 1335 1336 case VFIFO: 1337 d.d_type = DT_FIFO; 1338 break; 1339 1340 case VLNK: 1341 d.d_type = DT_LNK; 1342 break; 1343 1344 case VREG: 1345 d.d_type = DT_REG; 1346 break; 1347 1348 case VSOCK: 1349 d.d_type = DT_SOCK; 1350 break; 1351 1352 default: 1353 panic("tmpfs_dir_getdents: type %p %d", 1354 de->td_node, (int)de->td_node->tn_type); 1355 } 1356 } 1357 d.d_namlen = de->td_namelen; 1358 MPASS(de->td_namelen < sizeof(d.d_name)); 1359 (void)memcpy(d.d_name, de->ud.td_name, de->td_namelen); 1360 d.d_reclen = GENERIC_DIRSIZ(&d); 1361 dirent_terminate(&d); 1362 1363 /* Stop reading if the directory entry we are treating is 1364 * bigger than the amount of data that can be returned. */ 1365 if (d.d_reclen > uio->uio_resid) { 1366 error = EJUSTRETURN; 1367 break; 1368 } 1369 1370 /* Copy the new dirent structure into the output buffer and 1371 * advance pointers. */ 1372 error = uiomove(&d, d.d_reclen, uio); 1373 if (error == 0) { 1374 de = tmpfs_dir_next(node, &dc); 1375 if (cookies != NULL) { 1376 off = tmpfs_dirent_cookie(de); 1377 MPASS(*ncookies < maxcookies); 1378 cookies[(*ncookies)++] = off; 1379 } 1380 } 1381 } while (error == 0 && uio->uio_resid > 0 && de != NULL); 1382 1383 /* Skip setting off when using cookies as it is already done above. */ 1384 if (cookies == NULL) 1385 off = tmpfs_dirent_cookie(de); 1386 1387 /* Update the offset and cache. */ 1388 uio->uio_offset = off; 1389 node->tn_dir.tn_readdir_lastn = off; 1390 node->tn_dir.tn_readdir_lastp = de; 1391 1392 tmpfs_set_status(tm, node, TMPFS_NODE_ACCESSED); 1393 return error; 1394 } 1395 1396 int 1397 tmpfs_dir_whiteout_add(struct vnode *dvp, struct componentname *cnp) 1398 { 1399 struct tmpfs_dirent *de; 1400 int error; 1401 1402 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(dvp->v_mount), NULL, 1403 cnp->cn_nameptr, cnp->cn_namelen, &de); 1404 if (error != 0) 1405 return (error); 1406 tmpfs_dir_attach(dvp, de); 1407 return (0); 1408 } 1409 1410 void 1411 tmpfs_dir_whiteout_remove(struct vnode *dvp, struct componentname *cnp) 1412 { 1413 struct tmpfs_dirent *de; 1414 1415 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp); 1416 MPASS(de != NULL && de->td_node == NULL); 1417 tmpfs_dir_detach(dvp, de); 1418 tmpfs_free_dirent(VFS_TO_TMPFS(dvp->v_mount), de); 1419 } 1420 1421 /* 1422 * Resizes the aobj associated with the regular file pointed to by 'vp' to the 1423 * size 'newsize'. 'vp' must point to a vnode that represents a regular file. 1424 * 'newsize' must be positive. 1425 * 1426 * Returns zero on success or an appropriate error code on failure. 1427 */ 1428 int 1429 tmpfs_reg_resize(struct vnode *vp, off_t newsize, boolean_t ignerr) 1430 { 1431 struct tmpfs_mount *tmp; 1432 struct tmpfs_node *node; 1433 vm_object_t uobj; 1434 vm_page_t m; 1435 vm_pindex_t idx, newpages, oldpages; 1436 off_t oldsize; 1437 int base, rv; 1438 1439 MPASS(vp->v_type == VREG); 1440 MPASS(newsize >= 0); 1441 1442 node = VP_TO_TMPFS_NODE(vp); 1443 uobj = node->tn_reg.tn_aobj; 1444 tmp = VFS_TO_TMPFS(vp->v_mount); 1445 1446 /* 1447 * Convert the old and new sizes to the number of pages needed to 1448 * store them. It may happen that we do not need to do anything 1449 * because the last allocated page can accommodate the change on 1450 * its own. 1451 */ 1452 oldsize = node->tn_size; 1453 oldpages = OFF_TO_IDX(oldsize + PAGE_MASK); 1454 MPASS(oldpages == uobj->size); 1455 newpages = OFF_TO_IDX(newsize + PAGE_MASK); 1456 1457 if (__predict_true(newpages == oldpages && newsize >= oldsize)) { 1458 node->tn_size = newsize; 1459 return (0); 1460 } 1461 1462 if (newpages > oldpages && 1463 tmpfs_pages_check_avail(tmp, newpages - oldpages) == 0) 1464 return (ENOSPC); 1465 1466 VM_OBJECT_WLOCK(uobj); 1467 if (newsize < oldsize) { 1468 /* 1469 * Zero the truncated part of the last page. 1470 */ 1471 base = newsize & PAGE_MASK; 1472 if (base != 0) { 1473 idx = OFF_TO_IDX(newsize); 1474 retry: 1475 m = vm_page_grab(uobj, idx, VM_ALLOC_NOCREAT); 1476 if (m != NULL) { 1477 MPASS(vm_page_all_valid(m)); 1478 } else if (vm_pager_has_page(uobj, idx, NULL, NULL)) { 1479 m = vm_page_alloc(uobj, idx, VM_ALLOC_NORMAL | 1480 VM_ALLOC_WAITFAIL); 1481 if (m == NULL) 1482 goto retry; 1483 vm_object_pip_add(uobj, 1); 1484 VM_OBJECT_WUNLOCK(uobj); 1485 rv = vm_pager_get_pages(uobj, &m, 1, NULL, 1486 NULL); 1487 VM_OBJECT_WLOCK(uobj); 1488 vm_object_pip_wakeup(uobj); 1489 if (rv == VM_PAGER_OK) { 1490 /* 1491 * Since the page was not resident, 1492 * and therefore not recently 1493 * accessed, immediately enqueue it 1494 * for asynchronous laundering. The 1495 * current operation is not regarded 1496 * as an access. 1497 */ 1498 vm_page_launder(m); 1499 } else { 1500 vm_page_free(m); 1501 if (ignerr) 1502 m = NULL; 1503 else { 1504 VM_OBJECT_WUNLOCK(uobj); 1505 return (EIO); 1506 } 1507 } 1508 } 1509 if (m != NULL) { 1510 pmap_zero_page_area(m, base, PAGE_SIZE - base); 1511 vm_page_set_dirty(m); 1512 vm_page_xunbusy(m); 1513 } 1514 } 1515 1516 /* 1517 * Release any swap space and free any whole pages. 1518 */ 1519 if (newpages < oldpages) { 1520 swap_pager_freespace(uobj, newpages, oldpages - 1521 newpages); 1522 vm_object_page_remove(uobj, newpages, 0, 0); 1523 } 1524 } 1525 uobj->size = newpages; 1526 VM_OBJECT_WUNLOCK(uobj); 1527 1528 atomic_add_long(&tmp->tm_pages_used, newpages - oldpages); 1529 1530 node->tn_size = newsize; 1531 return (0); 1532 } 1533 1534 void 1535 tmpfs_check_mtime(struct vnode *vp) 1536 { 1537 struct tmpfs_node *node; 1538 struct vm_object *obj; 1539 1540 ASSERT_VOP_ELOCKED(vp, "check_mtime"); 1541 if (vp->v_type != VREG) 1542 return; 1543 obj = vp->v_object; 1544 KASSERT((obj->flags & (OBJ_TMPFS_NODE | OBJ_TMPFS)) == 1545 (OBJ_TMPFS_NODE | OBJ_TMPFS), ("non-tmpfs obj")); 1546 /* unlocked read */ 1547 if (obj->generation != obj->cleangeneration) { 1548 VM_OBJECT_WLOCK(obj); 1549 if (obj->generation != obj->cleangeneration) { 1550 obj->cleangeneration = obj->generation; 1551 node = VP_TO_TMPFS_NODE(vp); 1552 node->tn_status |= TMPFS_NODE_MODIFIED | 1553 TMPFS_NODE_CHANGED; 1554 } 1555 VM_OBJECT_WUNLOCK(obj); 1556 } 1557 } 1558 1559 /* 1560 * Change flags of the given vnode. 1561 * Caller should execute tmpfs_update on vp after a successful execution. 1562 * The vnode must be locked on entry and remain locked on exit. 1563 */ 1564 int 1565 tmpfs_chflags(struct vnode *vp, u_long flags, struct ucred *cred, 1566 struct thread *p) 1567 { 1568 int error; 1569 struct tmpfs_node *node; 1570 1571 ASSERT_VOP_ELOCKED(vp, "chflags"); 1572 1573 node = VP_TO_TMPFS_NODE(vp); 1574 1575 if ((flags & ~(SF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_NOUNLINK | 1576 UF_APPEND | UF_ARCHIVE | UF_HIDDEN | UF_IMMUTABLE | UF_NODUMP | 1577 UF_NOUNLINK | UF_OFFLINE | UF_OPAQUE | UF_READONLY | UF_REPARSE | 1578 UF_SPARSE | UF_SYSTEM)) != 0) 1579 return (EOPNOTSUPP); 1580 1581 /* Disallow this operation if the file system is mounted read-only. */ 1582 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1583 return EROFS; 1584 1585 /* 1586 * Callers may only modify the file flags on objects they 1587 * have VADMIN rights for. 1588 */ 1589 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 1590 return (error); 1591 /* 1592 * Unprivileged processes are not permitted to unset system 1593 * flags, or modify flags if any system flags are set. 1594 */ 1595 if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS)) { 1596 if (node->tn_flags & 1597 (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { 1598 error = securelevel_gt(cred, 0); 1599 if (error) 1600 return (error); 1601 } 1602 } else { 1603 if (node->tn_flags & 1604 (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || 1605 ((flags ^ node->tn_flags) & SF_SETTABLE)) 1606 return (EPERM); 1607 } 1608 node->tn_flags = flags; 1609 node->tn_status |= TMPFS_NODE_CHANGED; 1610 1611 ASSERT_VOP_ELOCKED(vp, "chflags2"); 1612 1613 return (0); 1614 } 1615 1616 /* 1617 * Change access mode on the given vnode. 1618 * Caller should execute tmpfs_update on vp after a successful execution. 1619 * The vnode must be locked on entry and remain locked on exit. 1620 */ 1621 int 1622 tmpfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct thread *p) 1623 { 1624 int error; 1625 struct tmpfs_node *node; 1626 1627 ASSERT_VOP_ELOCKED(vp, "chmod"); 1628 1629 node = VP_TO_TMPFS_NODE(vp); 1630 1631 /* Disallow this operation if the file system is mounted read-only. */ 1632 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1633 return EROFS; 1634 1635 /* Immutable or append-only files cannot be modified, either. */ 1636 if (node->tn_flags & (IMMUTABLE | APPEND)) 1637 return EPERM; 1638 1639 /* 1640 * To modify the permissions on a file, must possess VADMIN 1641 * for that file. 1642 */ 1643 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 1644 return (error); 1645 1646 /* 1647 * Privileged processes may set the sticky bit on non-directories, 1648 * as well as set the setgid bit on a file with a group that the 1649 * process is not a member of. 1650 */ 1651 if (vp->v_type != VDIR && (mode & S_ISTXT)) { 1652 if (priv_check_cred(cred, PRIV_VFS_STICKYFILE)) 1653 return (EFTYPE); 1654 } 1655 if (!groupmember(node->tn_gid, cred) && (mode & S_ISGID)) { 1656 error = priv_check_cred(cred, PRIV_VFS_SETGID); 1657 if (error) 1658 return (error); 1659 } 1660 1661 1662 node->tn_mode &= ~ALLPERMS; 1663 node->tn_mode |= mode & ALLPERMS; 1664 1665 node->tn_status |= TMPFS_NODE_CHANGED; 1666 1667 ASSERT_VOP_ELOCKED(vp, "chmod2"); 1668 1669 return (0); 1670 } 1671 1672 /* 1673 * Change ownership of the given vnode. At least one of uid or gid must 1674 * be different than VNOVAL. If one is set to that value, the attribute 1675 * is unchanged. 1676 * Caller should execute tmpfs_update on vp after a successful execution. 1677 * The vnode must be locked on entry and remain locked on exit. 1678 */ 1679 int 1680 tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, 1681 struct thread *p) 1682 { 1683 int error; 1684 struct tmpfs_node *node; 1685 uid_t ouid; 1686 gid_t ogid; 1687 1688 ASSERT_VOP_ELOCKED(vp, "chown"); 1689 1690 node = VP_TO_TMPFS_NODE(vp); 1691 1692 /* Assign default values if they are unknown. */ 1693 MPASS(uid != VNOVAL || gid != VNOVAL); 1694 if (uid == VNOVAL) 1695 uid = node->tn_uid; 1696 if (gid == VNOVAL) 1697 gid = node->tn_gid; 1698 MPASS(uid != VNOVAL && gid != VNOVAL); 1699 1700 /* Disallow this operation if the file system is mounted read-only. */ 1701 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1702 return EROFS; 1703 1704 /* Immutable or append-only files cannot be modified, either. */ 1705 if (node->tn_flags & (IMMUTABLE | APPEND)) 1706 return EPERM; 1707 1708 /* 1709 * To modify the ownership of a file, must possess VADMIN for that 1710 * file. 1711 */ 1712 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 1713 return (error); 1714 1715 /* 1716 * To change the owner of a file, or change the group of a file to a 1717 * group of which we are not a member, the caller must have 1718 * privilege. 1719 */ 1720 if ((uid != node->tn_uid || 1721 (gid != node->tn_gid && !groupmember(gid, cred))) && 1722 (error = priv_check_cred(cred, PRIV_VFS_CHOWN))) 1723 return (error); 1724 1725 ogid = node->tn_gid; 1726 ouid = node->tn_uid; 1727 1728 node->tn_uid = uid; 1729 node->tn_gid = gid; 1730 1731 node->tn_status |= TMPFS_NODE_CHANGED; 1732 1733 if ((node->tn_mode & (S_ISUID | S_ISGID)) && (ouid != uid || ogid != gid)) { 1734 if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID)) 1735 node->tn_mode &= ~(S_ISUID | S_ISGID); 1736 } 1737 1738 ASSERT_VOP_ELOCKED(vp, "chown2"); 1739 1740 return (0); 1741 } 1742 1743 /* 1744 * Change size of the given vnode. 1745 * Caller should execute tmpfs_update on vp after a successful execution. 1746 * The vnode must be locked on entry and remain locked on exit. 1747 */ 1748 int 1749 tmpfs_chsize(struct vnode *vp, u_quad_t size, struct ucred *cred, 1750 struct thread *p) 1751 { 1752 int error; 1753 struct tmpfs_node *node; 1754 1755 ASSERT_VOP_ELOCKED(vp, "chsize"); 1756 1757 node = VP_TO_TMPFS_NODE(vp); 1758 1759 /* Decide whether this is a valid operation based on the file type. */ 1760 error = 0; 1761 switch (vp->v_type) { 1762 case VDIR: 1763 return EISDIR; 1764 1765 case VREG: 1766 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1767 return EROFS; 1768 break; 1769 1770 case VBLK: 1771 /* FALLTHROUGH */ 1772 case VCHR: 1773 /* FALLTHROUGH */ 1774 case VFIFO: 1775 /* Allow modifications of special files even if in the file 1776 * system is mounted read-only (we are not modifying the 1777 * files themselves, but the objects they represent). */ 1778 return 0; 1779 1780 default: 1781 /* Anything else is unsupported. */ 1782 return EOPNOTSUPP; 1783 } 1784 1785 /* Immutable or append-only files cannot be modified, either. */ 1786 if (node->tn_flags & (IMMUTABLE | APPEND)) 1787 return EPERM; 1788 1789 error = tmpfs_truncate(vp, size); 1790 /* tmpfs_truncate will raise the NOTE_EXTEND and NOTE_ATTRIB kevents 1791 * for us, as will update tn_status; no need to do that here. */ 1792 1793 ASSERT_VOP_ELOCKED(vp, "chsize2"); 1794 1795 return (error); 1796 } 1797 1798 /* 1799 * Change access and modification times of the given vnode. 1800 * Caller should execute tmpfs_update on vp after a successful execution. 1801 * The vnode must be locked on entry and remain locked on exit. 1802 */ 1803 int 1804 tmpfs_chtimes(struct vnode *vp, struct vattr *vap, 1805 struct ucred *cred, struct thread *l) 1806 { 1807 int error; 1808 struct tmpfs_node *node; 1809 1810 ASSERT_VOP_ELOCKED(vp, "chtimes"); 1811 1812 node = VP_TO_TMPFS_NODE(vp); 1813 1814 /* Disallow this operation if the file system is mounted read-only. */ 1815 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1816 return EROFS; 1817 1818 /* Immutable or append-only files cannot be modified, either. */ 1819 if (node->tn_flags & (IMMUTABLE | APPEND)) 1820 return EPERM; 1821 1822 error = vn_utimes_perm(vp, vap, cred, l); 1823 if (error != 0) 1824 return (error); 1825 1826 if (vap->va_atime.tv_sec != VNOVAL) 1827 node->tn_status |= TMPFS_NODE_ACCESSED; 1828 1829 if (vap->va_mtime.tv_sec != VNOVAL) 1830 node->tn_status |= TMPFS_NODE_MODIFIED; 1831 1832 if (vap->va_birthtime.tv_sec != VNOVAL) 1833 node->tn_status |= TMPFS_NODE_MODIFIED; 1834 1835 tmpfs_itimes(vp, &vap->va_atime, &vap->va_mtime); 1836 1837 if (vap->va_birthtime.tv_sec != VNOVAL) 1838 node->tn_birthtime = vap->va_birthtime; 1839 ASSERT_VOP_ELOCKED(vp, "chtimes2"); 1840 1841 return (0); 1842 } 1843 1844 void 1845 tmpfs_set_status(struct tmpfs_mount *tm, struct tmpfs_node *node, int status) 1846 { 1847 1848 if ((node->tn_status & status) == status || tm->tm_ronly) 1849 return; 1850 TMPFS_NODE_LOCK(node); 1851 node->tn_status |= status; 1852 TMPFS_NODE_UNLOCK(node); 1853 } 1854 1855 /* Sync timestamps */ 1856 void 1857 tmpfs_itimes(struct vnode *vp, const struct timespec *acc, 1858 const struct timespec *mod) 1859 { 1860 struct tmpfs_node *node; 1861 struct timespec now; 1862 1863 ASSERT_VOP_LOCKED(vp, "tmpfs_itimes"); 1864 node = VP_TO_TMPFS_NODE(vp); 1865 1866 if ((node->tn_status & (TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | 1867 TMPFS_NODE_CHANGED)) == 0) 1868 return; 1869 1870 vfs_timestamp(&now); 1871 TMPFS_NODE_LOCK(node); 1872 if (node->tn_status & TMPFS_NODE_ACCESSED) { 1873 if (acc == NULL) 1874 acc = &now; 1875 node->tn_atime = *acc; 1876 } 1877 if (node->tn_status & TMPFS_NODE_MODIFIED) { 1878 if (mod == NULL) 1879 mod = &now; 1880 node->tn_mtime = *mod; 1881 } 1882 if (node->tn_status & TMPFS_NODE_CHANGED) 1883 node->tn_ctime = now; 1884 node->tn_status &= ~(TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | 1885 TMPFS_NODE_CHANGED); 1886 TMPFS_NODE_UNLOCK(node); 1887 1888 /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */ 1889 random_harvest_queue(node, sizeof(*node), RANDOM_FS_ATIME); 1890 } 1891 1892 int 1893 tmpfs_truncate(struct vnode *vp, off_t length) 1894 { 1895 int error; 1896 struct tmpfs_node *node; 1897 1898 node = VP_TO_TMPFS_NODE(vp); 1899 1900 if (length < 0) { 1901 error = EINVAL; 1902 goto out; 1903 } 1904 1905 if (node->tn_size == length) { 1906 error = 0; 1907 goto out; 1908 } 1909 1910 if (length > VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) 1911 return (EFBIG); 1912 1913 error = tmpfs_reg_resize(vp, length, FALSE); 1914 if (error == 0) 1915 node->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; 1916 1917 out: 1918 tmpfs_update(vp); 1919 1920 return (error); 1921 } 1922 1923 static __inline int 1924 tmpfs_dirtree_cmp(struct tmpfs_dirent *a, struct tmpfs_dirent *b) 1925 { 1926 if (a->td_hash > b->td_hash) 1927 return (1); 1928 else if (a->td_hash < b->td_hash) 1929 return (-1); 1930 return (0); 1931 } 1932 1933 RB_GENERATE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp); 1934