1 /* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5 * 6 * Copyright (c) 2005, 2006 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 * tmpfs vnode interface. 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/fcntl.h> 45 #include <sys/file.h> 46 #include <sys/limits.h> 47 #include <sys/lockf.h> 48 #include <sys/lock.h> 49 #include <sys/mount.h> 50 #include <sys/namei.h> 51 #include <sys/priv.h> 52 #include <sys/proc.h> 53 #include <sys/rwlock.h> 54 #include <sys/sched.h> 55 #include <sys/stat.h> 56 #include <sys/sysctl.h> 57 #include <sys/unistd.h> 58 #include <sys/vnode.h> 59 #include <sys/smr.h> 60 #include <security/audit/audit.h> 61 #include <security/mac/mac_framework.h> 62 63 #include <vm/vm.h> 64 #include <vm/vm_param.h> 65 #include <vm/vm_object.h> 66 67 #include <fs/tmpfs/tmpfs_vnops.h> 68 #include <fs/tmpfs/tmpfs.h> 69 70 SYSCTL_DECL(_vfs_tmpfs); 71 VFS_SMR_DECLARE; 72 73 static volatile int tmpfs_rename_restarts; 74 SYSCTL_INT(_vfs_tmpfs, OID_AUTO, rename_restarts, CTLFLAG_RD, 75 __DEVOLATILE(int *, &tmpfs_rename_restarts), 0, 76 "Times rename had to restart due to lock contention"); 77 78 static int 79 tmpfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags, 80 struct vnode **rvp) 81 { 82 83 return (tmpfs_alloc_vp(mp, arg, lkflags, rvp)); 84 } 85 86 static int 87 tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) 88 { 89 struct tmpfs_dirent *de; 90 struct tmpfs_node *dnode, *pnode; 91 struct tmpfs_mount *tm; 92 int error; 93 94 dnode = VP_TO_TMPFS_DIR(dvp); 95 *vpp = NULLVP; 96 97 /* Check accessibility of requested node as a first step. */ 98 error = vn_dir_check_exec(dvp, cnp); 99 if (error != 0) 100 goto out; 101 102 /* We cannot be requesting the parent directory of the root node. */ 103 MPASS(IMPLIES(dnode->tn_type == VDIR && 104 dnode->tn_dir.tn_parent == dnode, 105 !(cnp->cn_flags & ISDOTDOT))); 106 107 TMPFS_ASSERT_LOCKED(dnode); 108 if (dnode->tn_dir.tn_parent == NULL) { 109 error = ENOENT; 110 goto out; 111 } 112 if (cnp->cn_flags & ISDOTDOT) { 113 tm = VFS_TO_TMPFS(dvp->v_mount); 114 pnode = dnode->tn_dir.tn_parent; 115 tmpfs_ref_node(pnode); 116 error = vn_vget_ino_gen(dvp, tmpfs_vn_get_ino_alloc, 117 pnode, cnp->cn_lkflags, vpp); 118 tmpfs_free_node(tm, pnode); 119 if (error != 0) 120 goto out; 121 } else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 122 VREF(dvp); 123 *vpp = dvp; 124 error = 0; 125 } else { 126 de = tmpfs_dir_lookup(dnode, NULL, cnp); 127 if (de != NULL && de->td_node == NULL) 128 cnp->cn_flags |= ISWHITEOUT; 129 if (de == NULL || de->td_node == NULL) { 130 /* 131 * The entry was not found in the directory. 132 * This is OK if we are creating or renaming an 133 * entry and are working on the last component of 134 * the path name. 135 */ 136 if ((cnp->cn_flags & ISLASTCN) && 137 (cnp->cn_nameiop == CREATE || \ 138 cnp->cn_nameiop == RENAME || 139 (cnp->cn_nameiop == DELETE && 140 cnp->cn_flags & DOWHITEOUT && 141 cnp->cn_flags & ISWHITEOUT))) { 142 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, 143 cnp->cn_thread); 144 if (error != 0) 145 goto out; 146 147 /* 148 * Keep the component name in the buffer for 149 * future uses. 150 */ 151 cnp->cn_flags |= SAVENAME; 152 153 error = EJUSTRETURN; 154 } else 155 error = ENOENT; 156 } else { 157 struct tmpfs_node *tnode; 158 159 /* 160 * The entry was found, so get its associated 161 * tmpfs_node. 162 */ 163 tnode = de->td_node; 164 165 /* 166 * If we are not at the last path component and 167 * found a non-directory or non-link entry (which 168 * may itself be pointing to a directory), raise 169 * an error. 170 */ 171 if ((tnode->tn_type != VDIR && 172 tnode->tn_type != VLNK) && 173 !(cnp->cn_flags & ISLASTCN)) { 174 error = ENOTDIR; 175 goto out; 176 } 177 178 /* 179 * If we are deleting or renaming the entry, keep 180 * track of its tmpfs_dirent so that it can be 181 * easily deleted later. 182 */ 183 if ((cnp->cn_flags & ISLASTCN) && 184 (cnp->cn_nameiop == DELETE || 185 cnp->cn_nameiop == RENAME)) { 186 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, 187 cnp->cn_thread); 188 if (error != 0) 189 goto out; 190 191 /* Allocate a new vnode on the matching entry. */ 192 error = tmpfs_alloc_vp(dvp->v_mount, tnode, 193 cnp->cn_lkflags, vpp); 194 if (error != 0) 195 goto out; 196 197 if ((dnode->tn_mode & S_ISTXT) && 198 VOP_ACCESS(dvp, VADMIN, cnp->cn_cred, 199 cnp->cn_thread) && VOP_ACCESS(*vpp, VADMIN, 200 cnp->cn_cred, cnp->cn_thread)) { 201 error = EPERM; 202 vput(*vpp); 203 *vpp = NULL; 204 goto out; 205 } 206 cnp->cn_flags |= SAVENAME; 207 } else { 208 error = tmpfs_alloc_vp(dvp->v_mount, tnode, 209 cnp->cn_lkflags, vpp); 210 if (error != 0) 211 goto out; 212 } 213 } 214 } 215 216 /* 217 * Store the result of this lookup in the cache. Avoid this if the 218 * request was for creation, as it does not improve timings on 219 * emprical tests. 220 */ 221 if ((cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp)) 222 cache_enter(dvp, *vpp, cnp); 223 224 out: 225 /* 226 * If there were no errors, *vpp cannot be null and it must be 227 * locked. 228 */ 229 MPASS(IFF(error == 0, *vpp != NULLVP && VOP_ISLOCKED(*vpp))); 230 231 return (error); 232 } 233 234 static int 235 tmpfs_cached_lookup(struct vop_cachedlookup_args *v) 236 { 237 238 return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp)); 239 } 240 241 static int 242 tmpfs_lookup(struct vop_lookup_args *v) 243 { 244 245 return (tmpfs_lookup1(v->a_dvp, v->a_vpp, v->a_cnp)); 246 } 247 248 static int 249 tmpfs_create(struct vop_create_args *v) 250 { 251 struct vnode *dvp = v->a_dvp; 252 struct vnode **vpp = v->a_vpp; 253 struct componentname *cnp = v->a_cnp; 254 struct vattr *vap = v->a_vap; 255 int error; 256 257 MPASS(vap->va_type == VREG || vap->va_type == VSOCK); 258 259 error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 260 if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0 && tmpfs_use_nc(dvp)) 261 cache_enter(dvp, *vpp, cnp); 262 return (error); 263 } 264 265 static int 266 tmpfs_mknod(struct vop_mknod_args *v) 267 { 268 struct vnode *dvp = v->a_dvp; 269 struct vnode **vpp = v->a_vpp; 270 struct componentname *cnp = v->a_cnp; 271 struct vattr *vap = v->a_vap; 272 273 if (vap->va_type != VBLK && vap->va_type != VCHR && 274 vap->va_type != VFIFO) 275 return EINVAL; 276 277 return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 278 } 279 280 struct fileops tmpfs_fnops; 281 282 static int 283 tmpfs_open(struct vop_open_args *v) 284 { 285 struct vnode *vp; 286 struct tmpfs_node *node; 287 struct file *fp; 288 int error, mode; 289 290 vp = v->a_vp; 291 mode = v->a_mode; 292 node = VP_TO_TMPFS_NODE(vp); 293 294 /* 295 * The file is still active but all its names have been removed 296 * (e.g. by a "rmdir $(pwd)"). It cannot be opened any more as 297 * it is about to die. 298 */ 299 if (node->tn_links < 1) 300 return (ENOENT); 301 302 /* If the file is marked append-only, deny write requests. */ 303 if (node->tn_flags & APPEND && (mode & (FWRITE | O_APPEND)) == FWRITE) 304 error = EPERM; 305 else { 306 error = 0; 307 /* For regular files, the call below is nop. */ 308 KASSERT(vp->v_type != VREG || (node->tn_reg.tn_aobj->flags & 309 OBJ_DEAD) == 0, ("dead object")); 310 vnode_create_vobject(vp, node->tn_size, v->a_td); 311 } 312 313 fp = v->a_fp; 314 MPASS(fp == NULL || fp->f_data == NULL); 315 if (error == 0 && fp != NULL && vp->v_type == VREG) { 316 tmpfs_ref_node(node); 317 finit_vnode(fp, mode, node, &tmpfs_fnops); 318 } 319 320 return (error); 321 } 322 323 static int 324 tmpfs_close(struct vop_close_args *v) 325 { 326 struct vnode *vp = v->a_vp; 327 328 /* Update node times. */ 329 tmpfs_update(vp); 330 331 return (0); 332 } 333 334 int 335 tmpfs_fo_close(struct file *fp, struct thread *td) 336 { 337 struct tmpfs_node *node; 338 339 node = fp->f_data; 340 if (node != NULL) { 341 MPASS(node->tn_type == VREG); 342 tmpfs_free_node(node->tn_reg.tn_tmp, node); 343 } 344 return (vnops.fo_close(fp, td)); 345 } 346 347 /* 348 * VOP_FPLOOKUP_VEXEC routines are subject to special circumstances, see 349 * the comment above cache_fplookup for details. 350 */ 351 int 352 tmpfs_fplookup_vexec(struct vop_fplookup_vexec_args *v) 353 { 354 struct vnode *vp; 355 struct tmpfs_node *node; 356 struct ucred *cred; 357 mode_t all_x, mode; 358 359 vp = v->a_vp; 360 node = VP_TO_TMPFS_NODE_SMR(vp); 361 if (__predict_false(node == NULL)) 362 return (EAGAIN); 363 364 all_x = S_IXUSR | S_IXGRP | S_IXOTH; 365 mode = atomic_load_short(&node->tn_mode); 366 if (__predict_true((mode & all_x) == all_x)) 367 return (0); 368 369 cred = v->a_cred; 370 return (vaccess_vexec_smr(mode, node->tn_uid, node->tn_gid, cred)); 371 } 372 373 int 374 tmpfs_access(struct vop_access_args *v) 375 { 376 struct vnode *vp = v->a_vp; 377 accmode_t accmode = v->a_accmode; 378 struct ucred *cred = v->a_cred; 379 mode_t all_x = S_IXUSR | S_IXGRP | S_IXOTH; 380 int error; 381 struct tmpfs_node *node; 382 383 MPASS(VOP_ISLOCKED(vp)); 384 385 node = VP_TO_TMPFS_NODE(vp); 386 387 /* 388 * Common case path lookup. 389 */ 390 if (__predict_true(accmode == VEXEC && (node->tn_mode & all_x) == all_x)) 391 return (0); 392 393 switch (vp->v_type) { 394 case VDIR: 395 /* FALLTHROUGH */ 396 case VLNK: 397 /* FALLTHROUGH */ 398 case VREG: 399 if (accmode & VWRITE && vp->v_mount->mnt_flag & MNT_RDONLY) { 400 error = EROFS; 401 goto out; 402 } 403 break; 404 405 case VBLK: 406 /* FALLTHROUGH */ 407 case VCHR: 408 /* FALLTHROUGH */ 409 case VSOCK: 410 /* FALLTHROUGH */ 411 case VFIFO: 412 break; 413 414 default: 415 error = EINVAL; 416 goto out; 417 } 418 419 if (accmode & VWRITE && node->tn_flags & IMMUTABLE) { 420 error = EPERM; 421 goto out; 422 } 423 424 error = vaccess(vp->v_type, node->tn_mode, node->tn_uid, node->tn_gid, 425 accmode, cred); 426 427 out: 428 MPASS(VOP_ISLOCKED(vp)); 429 430 return (error); 431 } 432 433 int 434 tmpfs_stat(struct vop_stat_args *v) 435 { 436 struct vnode *vp = v->a_vp; 437 struct stat *sb = v->a_sb; 438 vm_object_t obj; 439 struct tmpfs_node *node; 440 int error; 441 442 node = VP_TO_TMPFS_NODE(vp); 443 444 tmpfs_update_getattr(vp); 445 446 error = vop_stat_helper_pre(v); 447 if (__predict_false(error)) 448 return (error); 449 450 sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; 451 sb->st_ino = node->tn_id; 452 sb->st_mode = node->tn_mode | VTTOIF(vp->v_type); 453 sb->st_nlink = node->tn_links; 454 sb->st_uid = node->tn_uid; 455 sb->st_gid = node->tn_gid; 456 sb->st_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? 457 node->tn_rdev : NODEV; 458 sb->st_size = node->tn_size; 459 sb->st_atim.tv_sec = node->tn_atime.tv_sec; 460 sb->st_atim.tv_nsec = node->tn_atime.tv_nsec; 461 sb->st_mtim.tv_sec = node->tn_mtime.tv_sec; 462 sb->st_mtim.tv_nsec = node->tn_mtime.tv_nsec; 463 sb->st_ctim.tv_sec = node->tn_ctime.tv_sec; 464 sb->st_ctim.tv_nsec = node->tn_ctime.tv_nsec; 465 sb->st_birthtim.tv_sec = node->tn_birthtime.tv_sec; 466 sb->st_birthtim.tv_nsec = node->tn_birthtime.tv_nsec; 467 sb->st_blksize = PAGE_SIZE; 468 sb->st_flags = node->tn_flags; 469 sb->st_gen = node->tn_gen; 470 if (vp->v_type == VREG) { 471 obj = node->tn_reg.tn_aobj; 472 sb->st_blocks = (u_quad_t)obj->resident_page_count * PAGE_SIZE; 473 } else 474 sb->st_blocks = node->tn_size; 475 sb->st_blocks /= S_BLKSIZE; 476 return (vop_stat_helper_post(v, error)); 477 } 478 479 int 480 tmpfs_getattr(struct vop_getattr_args *v) 481 { 482 struct vnode *vp = v->a_vp; 483 struct vattr *vap = v->a_vap; 484 vm_object_t obj; 485 struct tmpfs_node *node; 486 487 node = VP_TO_TMPFS_NODE(vp); 488 489 tmpfs_update_getattr(vp); 490 491 vap->va_type = vp->v_type; 492 vap->va_mode = node->tn_mode; 493 vap->va_nlink = node->tn_links; 494 vap->va_uid = node->tn_uid; 495 vap->va_gid = node->tn_gid; 496 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 497 vap->va_fileid = node->tn_id; 498 vap->va_size = node->tn_size; 499 vap->va_blocksize = PAGE_SIZE; 500 vap->va_atime = node->tn_atime; 501 vap->va_mtime = node->tn_mtime; 502 vap->va_ctime = node->tn_ctime; 503 vap->va_birthtime = node->tn_birthtime; 504 vap->va_gen = node->tn_gen; 505 vap->va_flags = node->tn_flags; 506 vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ? 507 node->tn_rdev : NODEV; 508 if (vp->v_type == VREG) { 509 obj = node->tn_reg.tn_aobj; 510 vap->va_bytes = (u_quad_t)obj->resident_page_count * PAGE_SIZE; 511 } else 512 vap->va_bytes = node->tn_size; 513 vap->va_filerev = 0; 514 515 return 0; 516 } 517 518 int 519 tmpfs_setattr(struct vop_setattr_args *v) 520 { 521 struct vnode *vp = v->a_vp; 522 struct vattr *vap = v->a_vap; 523 struct ucred *cred = v->a_cred; 524 struct thread *td = curthread; 525 526 int error; 527 528 MPASS(VOP_ISLOCKED(vp)); 529 ASSERT_VOP_IN_SEQC(vp); 530 531 error = 0; 532 533 /* Abort if any unsettable attribute is given. */ 534 if (vap->va_type != VNON || 535 vap->va_nlink != VNOVAL || 536 vap->va_fsid != VNOVAL || 537 vap->va_fileid != VNOVAL || 538 vap->va_blocksize != VNOVAL || 539 vap->va_gen != VNOVAL || 540 vap->va_rdev != VNOVAL || 541 vap->va_bytes != VNOVAL) 542 error = EINVAL; 543 544 if (error == 0 && (vap->va_flags != VNOVAL)) 545 error = tmpfs_chflags(vp, vap->va_flags, cred, td); 546 547 if (error == 0 && (vap->va_size != VNOVAL)) 548 error = tmpfs_chsize(vp, vap->va_size, cred, td); 549 550 if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL)) 551 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, td); 552 553 if (error == 0 && (vap->va_mode != (mode_t)VNOVAL)) 554 error = tmpfs_chmod(vp, vap->va_mode, cred, td); 555 556 if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL && 557 vap->va_atime.tv_nsec != VNOVAL) || 558 (vap->va_mtime.tv_sec != VNOVAL && 559 vap->va_mtime.tv_nsec != VNOVAL) || 560 (vap->va_birthtime.tv_sec != VNOVAL && 561 vap->va_birthtime.tv_nsec != VNOVAL))) 562 error = tmpfs_chtimes(vp, vap, cred, td); 563 564 /* 565 * Update the node times. We give preference to the error codes 566 * generated by this function rather than the ones that may arise 567 * from tmpfs_update. 568 */ 569 tmpfs_update(vp); 570 571 MPASS(VOP_ISLOCKED(vp)); 572 573 return error; 574 } 575 576 static int 577 tmpfs_read(struct vop_read_args *v) 578 { 579 struct vnode *vp; 580 struct uio *uio; 581 struct tmpfs_node *node; 582 583 vp = v->a_vp; 584 if (vp->v_type != VREG) 585 return (EISDIR); 586 uio = v->a_uio; 587 if (uio->uio_offset < 0) 588 return (EINVAL); 589 node = VP_TO_TMPFS_NODE(vp); 590 tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node); 591 return (uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio)); 592 } 593 594 static int 595 tmpfs_read_pgcache(struct vop_read_pgcache_args *v) 596 { 597 struct vnode *vp; 598 struct tmpfs_node *node; 599 vm_object_t object; 600 off_t size; 601 int error; 602 603 vp = v->a_vp; 604 VNPASS((vn_irflag_read(vp) & VIRF_PGREAD) != 0, vp); 605 606 if (v->a_uio->uio_offset < 0) 607 return (EINVAL); 608 609 error = EJUSTRETURN; 610 vfs_smr_enter(); 611 612 node = VP_TO_TMPFS_NODE_SMR(vp); 613 if (node == NULL) 614 goto out_smr; 615 MPASS(node->tn_type == VREG); 616 MPASS(node->tn_refcount >= 1); 617 object = node->tn_reg.tn_aobj; 618 if (object == NULL) 619 goto out_smr; 620 621 MPASS((object->flags & (OBJ_ANON | OBJ_DEAD | OBJ_TMPFS_NODE)) == 622 OBJ_TMPFS_NODE); 623 if (!VN_IS_DOOMED(vp)) { 624 /* size cannot become shorter due to rangelock. */ 625 size = node->tn_size; 626 tmpfs_set_accessed(node->tn_reg.tn_tmp, node); 627 vfs_smr_exit(); 628 error = uiomove_object(object, size, v->a_uio); 629 return (error); 630 } 631 out_smr: 632 vfs_smr_exit(); 633 return (error); 634 } 635 636 static int 637 tmpfs_write(struct vop_write_args *v) 638 { 639 struct vnode *vp; 640 struct uio *uio; 641 struct tmpfs_node *node; 642 off_t oldsize; 643 int error, ioflag; 644 mode_t newmode; 645 646 vp = v->a_vp; 647 uio = v->a_uio; 648 ioflag = v->a_ioflag; 649 error = 0; 650 node = VP_TO_TMPFS_NODE(vp); 651 oldsize = node->tn_size; 652 653 if (uio->uio_offset < 0 || vp->v_type != VREG) 654 return (EINVAL); 655 if (uio->uio_resid == 0) 656 return (0); 657 if (ioflag & IO_APPEND) 658 uio->uio_offset = node->tn_size; 659 if (uio->uio_offset + uio->uio_resid > 660 VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) 661 return (EFBIG); 662 if (vn_rlimit_fsize(vp, uio, uio->uio_td)) 663 return (EFBIG); 664 if (uio->uio_offset + uio->uio_resid > node->tn_size) { 665 error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid, 666 FALSE); 667 if (error != 0) 668 goto out; 669 } 670 671 error = uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio); 672 node->tn_status |= TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED; 673 node->tn_accessed = true; 674 if (node->tn_mode & (S_ISUID | S_ISGID)) { 675 if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID)) { 676 newmode = node->tn_mode & ~(S_ISUID | S_ISGID); 677 vn_seqc_write_begin(vp); 678 atomic_store_short(&node->tn_mode, newmode); 679 vn_seqc_write_end(vp); 680 } 681 } 682 if (error != 0) 683 (void)tmpfs_reg_resize(vp, oldsize, TRUE); 684 685 out: 686 MPASS(IMPLIES(error == 0, uio->uio_resid == 0)); 687 MPASS(IMPLIES(error != 0, oldsize == node->tn_size)); 688 689 return (error); 690 } 691 692 static int 693 tmpfs_fsync(struct vop_fsync_args *v) 694 { 695 struct vnode *vp = v->a_vp; 696 697 MPASS(VOP_ISLOCKED(vp)); 698 699 tmpfs_check_mtime(vp); 700 tmpfs_update(vp); 701 702 return 0; 703 } 704 705 static int 706 tmpfs_remove(struct vop_remove_args *v) 707 { 708 struct vnode *dvp = v->a_dvp; 709 struct vnode *vp = v->a_vp; 710 711 int error; 712 struct tmpfs_dirent *de; 713 struct tmpfs_mount *tmp; 714 struct tmpfs_node *dnode; 715 struct tmpfs_node *node; 716 717 MPASS(VOP_ISLOCKED(dvp)); 718 MPASS(VOP_ISLOCKED(vp)); 719 720 if (vp->v_type == VDIR) { 721 error = EISDIR; 722 goto out; 723 } 724 725 dnode = VP_TO_TMPFS_DIR(dvp); 726 node = VP_TO_TMPFS_NODE(vp); 727 tmp = VFS_TO_TMPFS(vp->v_mount); 728 de = tmpfs_dir_lookup(dnode, node, v->a_cnp); 729 MPASS(de != NULL); 730 731 /* Files marked as immutable or append-only cannot be deleted. */ 732 if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) || 733 (dnode->tn_flags & APPEND)) { 734 error = EPERM; 735 goto out; 736 } 737 738 /* Remove the entry from the directory; as it is a file, we do not 739 * have to change the number of hard links of the directory. */ 740 tmpfs_dir_detach(dvp, de); 741 if (v->a_cnp->cn_flags & DOWHITEOUT) 742 tmpfs_dir_whiteout_add(dvp, v->a_cnp); 743 744 /* Free the directory entry we just deleted. Note that the node 745 * referred by it will not be removed until the vnode is really 746 * reclaimed. */ 747 tmpfs_free_dirent(tmp, de); 748 749 node->tn_status |= TMPFS_NODE_CHANGED; 750 node->tn_accessed = true; 751 error = 0; 752 753 out: 754 return (error); 755 } 756 757 static int 758 tmpfs_link(struct vop_link_args *v) 759 { 760 struct vnode *dvp = v->a_tdvp; 761 struct vnode *vp = v->a_vp; 762 struct componentname *cnp = v->a_cnp; 763 764 int error; 765 struct tmpfs_dirent *de; 766 struct tmpfs_node *node; 767 768 MPASS(VOP_ISLOCKED(dvp)); 769 MPASS(cnp->cn_flags & HASBUF); 770 MPASS(dvp != vp); /* XXX When can this be false? */ 771 node = VP_TO_TMPFS_NODE(vp); 772 773 /* Ensure that we do not overflow the maximum number of links imposed 774 * by the system. */ 775 MPASS(node->tn_links <= TMPFS_LINK_MAX); 776 if (node->tn_links == TMPFS_LINK_MAX) { 777 error = EMLINK; 778 goto out; 779 } 780 781 /* We cannot create links of files marked immutable or append-only. */ 782 if (node->tn_flags & (IMMUTABLE | APPEND)) { 783 error = EPERM; 784 goto out; 785 } 786 787 /* Allocate a new directory entry to represent the node. */ 788 error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node, 789 cnp->cn_nameptr, cnp->cn_namelen, &de); 790 if (error != 0) 791 goto out; 792 793 /* Insert the new directory entry into the appropriate directory. */ 794 if (cnp->cn_flags & ISWHITEOUT) 795 tmpfs_dir_whiteout_remove(dvp, cnp); 796 tmpfs_dir_attach(dvp, de); 797 798 /* vp link count has changed, so update node times. */ 799 node->tn_status |= TMPFS_NODE_CHANGED; 800 tmpfs_update(vp); 801 802 error = 0; 803 804 out: 805 return error; 806 } 807 808 /* 809 * We acquire all but fdvp locks using non-blocking acquisitions. If we 810 * fail to acquire any lock in the path we will drop all held locks, 811 * acquire the new lock in a blocking fashion, and then release it and 812 * restart the rename. This acquire/release step ensures that we do not 813 * spin on a lock waiting for release. On error release all vnode locks 814 * and decrement references the way tmpfs_rename() would do. 815 */ 816 static int 817 tmpfs_rename_relock(struct vnode *fdvp, struct vnode **fvpp, 818 struct vnode *tdvp, struct vnode **tvpp, 819 struct componentname *fcnp, struct componentname *tcnp) 820 { 821 struct vnode *nvp; 822 struct mount *mp; 823 struct tmpfs_dirent *de; 824 int error, restarts = 0; 825 826 VOP_UNLOCK(tdvp); 827 if (*tvpp != NULL && *tvpp != tdvp) 828 VOP_UNLOCK(*tvpp); 829 mp = fdvp->v_mount; 830 831 relock: 832 restarts += 1; 833 error = vn_lock(fdvp, LK_EXCLUSIVE); 834 if (error) 835 goto releout; 836 if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { 837 VOP_UNLOCK(fdvp); 838 error = vn_lock(tdvp, LK_EXCLUSIVE); 839 if (error) 840 goto releout; 841 VOP_UNLOCK(tdvp); 842 goto relock; 843 } 844 /* 845 * Re-resolve fvp to be certain it still exists and fetch the 846 * correct vnode. 847 */ 848 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(fdvp), NULL, fcnp); 849 if (de == NULL) { 850 VOP_UNLOCK(fdvp); 851 VOP_UNLOCK(tdvp); 852 if ((fcnp->cn_flags & ISDOTDOT) != 0 || 853 (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')) 854 error = EINVAL; 855 else 856 error = ENOENT; 857 goto releout; 858 } 859 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE | LK_NOWAIT, &nvp); 860 if (error != 0) { 861 VOP_UNLOCK(fdvp); 862 VOP_UNLOCK(tdvp); 863 if (error != EBUSY) 864 goto releout; 865 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, &nvp); 866 if (error != 0) 867 goto releout; 868 VOP_UNLOCK(nvp); 869 /* 870 * Concurrent rename race. 871 */ 872 if (nvp == tdvp) { 873 vrele(nvp); 874 error = EINVAL; 875 goto releout; 876 } 877 vrele(*fvpp); 878 *fvpp = nvp; 879 goto relock; 880 } 881 vrele(*fvpp); 882 *fvpp = nvp; 883 VOP_UNLOCK(*fvpp); 884 /* 885 * Re-resolve tvp and acquire the vnode lock if present. 886 */ 887 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(tdvp), NULL, tcnp); 888 /* 889 * If tvp disappeared we just carry on. 890 */ 891 if (de == NULL && *tvpp != NULL) { 892 vrele(*tvpp); 893 *tvpp = NULL; 894 } 895 /* 896 * Get the tvp ino if the lookup succeeded. We may have to restart 897 * if the non-blocking acquire fails. 898 */ 899 if (de != NULL) { 900 nvp = NULL; 901 error = tmpfs_alloc_vp(mp, de->td_node, 902 LK_EXCLUSIVE | LK_NOWAIT, &nvp); 903 if (*tvpp != NULL) 904 vrele(*tvpp); 905 *tvpp = nvp; 906 if (error != 0) { 907 VOP_UNLOCK(fdvp); 908 VOP_UNLOCK(tdvp); 909 if (error != EBUSY) 910 goto releout; 911 error = tmpfs_alloc_vp(mp, de->td_node, LK_EXCLUSIVE, 912 &nvp); 913 if (error != 0) 914 goto releout; 915 VOP_UNLOCK(nvp); 916 /* 917 * fdvp contains fvp, thus tvp (=fdvp) is not empty. 918 */ 919 if (nvp == fdvp) { 920 error = ENOTEMPTY; 921 goto releout; 922 } 923 goto relock; 924 } 925 } 926 tmpfs_rename_restarts += restarts; 927 928 return (0); 929 930 releout: 931 vrele(fdvp); 932 vrele(*fvpp); 933 vrele(tdvp); 934 if (*tvpp != NULL) 935 vrele(*tvpp); 936 tmpfs_rename_restarts += restarts; 937 938 return (error); 939 } 940 941 static int 942 tmpfs_rename(struct vop_rename_args *v) 943 { 944 struct vnode *fdvp = v->a_fdvp; 945 struct vnode *fvp = v->a_fvp; 946 struct componentname *fcnp = v->a_fcnp; 947 struct vnode *tdvp = v->a_tdvp; 948 struct vnode *tvp = v->a_tvp; 949 struct componentname *tcnp = v->a_tcnp; 950 char *newname; 951 struct tmpfs_dirent *de; 952 struct tmpfs_mount *tmp; 953 struct tmpfs_node *fdnode; 954 struct tmpfs_node *fnode; 955 struct tmpfs_node *tnode; 956 struct tmpfs_node *tdnode; 957 int error; 958 bool want_seqc_end; 959 960 MPASS(VOP_ISLOCKED(tdvp)); 961 MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); 962 MPASS(fcnp->cn_flags & HASBUF); 963 MPASS(tcnp->cn_flags & HASBUF); 964 965 want_seqc_end = false; 966 967 /* 968 * Disallow cross-device renames. 969 * XXX Why isn't this done by the caller? 970 */ 971 if (fvp->v_mount != tdvp->v_mount || 972 (tvp != NULL && fvp->v_mount != tvp->v_mount)) { 973 error = EXDEV; 974 goto out; 975 } 976 977 /* If source and target are the same file, there is nothing to do. */ 978 if (fvp == tvp) { 979 error = 0; 980 goto out; 981 } 982 983 /* 984 * If we need to move the directory between entries, lock the 985 * source so that we can safely operate on it. 986 */ 987 if (fdvp != tdvp && fdvp != tvp) { 988 if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { 989 error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp, 990 fcnp, tcnp); 991 if (error != 0) 992 return (error); 993 ASSERT_VOP_ELOCKED(fdvp, 994 "tmpfs_rename: fdvp not locked"); 995 ASSERT_VOP_ELOCKED(tdvp, 996 "tmpfs_rename: tdvp not locked"); 997 if (tvp != NULL) 998 ASSERT_VOP_ELOCKED(tvp, 999 "tmpfs_rename: tvp not locked"); 1000 if (fvp == tvp) { 1001 error = 0; 1002 goto out_locked; 1003 } 1004 } 1005 } 1006 1007 if (tvp != NULL) 1008 vn_seqc_write_begin(tvp); 1009 vn_seqc_write_begin(tdvp); 1010 vn_seqc_write_begin(fvp); 1011 vn_seqc_write_begin(fdvp); 1012 want_seqc_end = true; 1013 1014 tmp = VFS_TO_TMPFS(tdvp->v_mount); 1015 tdnode = VP_TO_TMPFS_DIR(tdvp); 1016 tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); 1017 fdnode = VP_TO_TMPFS_DIR(fdvp); 1018 fnode = VP_TO_TMPFS_NODE(fvp); 1019 de = tmpfs_dir_lookup(fdnode, fnode, fcnp); 1020 1021 /* 1022 * Entry can disappear before we lock fdvp, 1023 * also avoid manipulating '.' and '..' entries. 1024 */ 1025 if (de == NULL) { 1026 if ((fcnp->cn_flags & ISDOTDOT) != 0 || 1027 (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')) 1028 error = EINVAL; 1029 else 1030 error = ENOENT; 1031 goto out_locked; 1032 } 1033 MPASS(de->td_node == fnode); 1034 1035 /* 1036 * If re-naming a directory to another preexisting directory 1037 * ensure that the target directory is empty so that its 1038 * removal causes no side effects. 1039 * Kern_rename guarantees the destination to be a directory 1040 * if the source is one. 1041 */ 1042 if (tvp != NULL) { 1043 MPASS(tnode != NULL); 1044 1045 if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 1046 (tdnode->tn_flags & (APPEND | IMMUTABLE))) { 1047 error = EPERM; 1048 goto out_locked; 1049 } 1050 1051 if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) { 1052 if (tnode->tn_size > 0) { 1053 error = ENOTEMPTY; 1054 goto out_locked; 1055 } 1056 } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) { 1057 error = ENOTDIR; 1058 goto out_locked; 1059 } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) { 1060 error = EISDIR; 1061 goto out_locked; 1062 } else { 1063 MPASS(fnode->tn_type != VDIR && 1064 tnode->tn_type != VDIR); 1065 } 1066 } 1067 1068 if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) 1069 || (fdnode->tn_flags & (APPEND | IMMUTABLE))) { 1070 error = EPERM; 1071 goto out_locked; 1072 } 1073 1074 /* 1075 * Ensure that we have enough memory to hold the new name, if it 1076 * has to be changed. 1077 */ 1078 if (fcnp->cn_namelen != tcnp->cn_namelen || 1079 bcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) { 1080 newname = malloc(tcnp->cn_namelen, M_TMPFSNAME, M_WAITOK); 1081 } else 1082 newname = NULL; 1083 1084 /* 1085 * If the node is being moved to another directory, we have to do 1086 * the move. 1087 */ 1088 if (fdnode != tdnode) { 1089 /* 1090 * In case we are moving a directory, we have to adjust its 1091 * parent to point to the new parent. 1092 */ 1093 if (de->td_node->tn_type == VDIR) { 1094 struct tmpfs_node *n; 1095 1096 /* 1097 * Ensure the target directory is not a child of the 1098 * directory being moved. Otherwise, we'd end up 1099 * with stale nodes. 1100 */ 1101 n = tdnode; 1102 /* 1103 * TMPFS_LOCK guaranties that no nodes are freed while 1104 * traversing the list. Nodes can only be marked as 1105 * removed: tn_parent == NULL. 1106 */ 1107 TMPFS_LOCK(tmp); 1108 TMPFS_NODE_LOCK(n); 1109 while (n != n->tn_dir.tn_parent) { 1110 struct tmpfs_node *parent; 1111 1112 if (n == fnode) { 1113 TMPFS_NODE_UNLOCK(n); 1114 TMPFS_UNLOCK(tmp); 1115 error = EINVAL; 1116 if (newname != NULL) 1117 free(newname, M_TMPFSNAME); 1118 goto out_locked; 1119 } 1120 parent = n->tn_dir.tn_parent; 1121 TMPFS_NODE_UNLOCK(n); 1122 if (parent == NULL) { 1123 n = NULL; 1124 break; 1125 } 1126 TMPFS_NODE_LOCK(parent); 1127 if (parent->tn_dir.tn_parent == NULL) { 1128 TMPFS_NODE_UNLOCK(parent); 1129 n = NULL; 1130 break; 1131 } 1132 n = parent; 1133 } 1134 TMPFS_UNLOCK(tmp); 1135 if (n == NULL) { 1136 error = EINVAL; 1137 if (newname != NULL) 1138 free(newname, M_TMPFSNAME); 1139 goto out_locked; 1140 } 1141 TMPFS_NODE_UNLOCK(n); 1142 1143 /* Adjust the parent pointer. */ 1144 TMPFS_VALIDATE_DIR(fnode); 1145 TMPFS_NODE_LOCK(de->td_node); 1146 de->td_node->tn_dir.tn_parent = tdnode; 1147 TMPFS_NODE_UNLOCK(de->td_node); 1148 1149 /* 1150 * As a result of changing the target of the '..' 1151 * entry, the link count of the source and target 1152 * directories has to be adjusted. 1153 */ 1154 TMPFS_NODE_LOCK(tdnode); 1155 TMPFS_ASSERT_LOCKED(tdnode); 1156 tdnode->tn_links++; 1157 TMPFS_NODE_UNLOCK(tdnode); 1158 1159 TMPFS_NODE_LOCK(fdnode); 1160 TMPFS_ASSERT_LOCKED(fdnode); 1161 fdnode->tn_links--; 1162 TMPFS_NODE_UNLOCK(fdnode); 1163 } 1164 } 1165 1166 /* 1167 * Do the move: just remove the entry from the source directory 1168 * and insert it into the target one. 1169 */ 1170 tmpfs_dir_detach(fdvp, de); 1171 1172 if (fcnp->cn_flags & DOWHITEOUT) 1173 tmpfs_dir_whiteout_add(fdvp, fcnp); 1174 if (tcnp->cn_flags & ISWHITEOUT) 1175 tmpfs_dir_whiteout_remove(tdvp, tcnp); 1176 1177 /* 1178 * If the name has changed, we need to make it effective by changing 1179 * it in the directory entry. 1180 */ 1181 if (newname != NULL) { 1182 MPASS(tcnp->cn_namelen <= MAXNAMLEN); 1183 1184 free(de->ud.td_name, M_TMPFSNAME); 1185 de->ud.td_name = newname; 1186 tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen); 1187 1188 fnode->tn_status |= TMPFS_NODE_CHANGED; 1189 tdnode->tn_status |= TMPFS_NODE_MODIFIED; 1190 } 1191 1192 /* 1193 * If we are overwriting an entry, we have to remove the old one 1194 * from the target directory. 1195 */ 1196 if (tvp != NULL) { 1197 struct tmpfs_dirent *tde; 1198 1199 /* Remove the old entry from the target directory. */ 1200 tde = tmpfs_dir_lookup(tdnode, tnode, tcnp); 1201 tmpfs_dir_detach(tdvp, tde); 1202 1203 /* 1204 * Free the directory entry we just deleted. Note that the 1205 * node referred by it will not be removed until the vnode is 1206 * really reclaimed. 1207 */ 1208 tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde); 1209 } 1210 1211 tmpfs_dir_attach(tdvp, de); 1212 1213 if (tmpfs_use_nc(fvp)) { 1214 cache_vop_rename(fdvp, fvp, tdvp, tvp, fcnp, tcnp); 1215 } 1216 1217 error = 0; 1218 1219 out_locked: 1220 if (fdvp != tdvp && fdvp != tvp) 1221 VOP_UNLOCK(fdvp); 1222 1223 out: 1224 if (want_seqc_end) { 1225 if (tvp != NULL) 1226 vn_seqc_write_end(tvp); 1227 vn_seqc_write_end(tdvp); 1228 vn_seqc_write_end(fvp); 1229 vn_seqc_write_end(fdvp); 1230 } 1231 1232 /* 1233 * Release target nodes. 1234 * XXX: I don't understand when tdvp can be the same as tvp, but 1235 * other code takes care of this... 1236 */ 1237 if (tdvp == tvp) 1238 vrele(tdvp); 1239 else 1240 vput(tdvp); 1241 if (tvp != NULL) 1242 vput(tvp); 1243 1244 /* Release source nodes. */ 1245 vrele(fdvp); 1246 vrele(fvp); 1247 1248 return (error); 1249 } 1250 1251 static int 1252 tmpfs_mkdir(struct vop_mkdir_args *v) 1253 { 1254 struct vnode *dvp = v->a_dvp; 1255 struct vnode **vpp = v->a_vpp; 1256 struct componentname *cnp = v->a_cnp; 1257 struct vattr *vap = v->a_vap; 1258 1259 MPASS(vap->va_type == VDIR); 1260 1261 return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL); 1262 } 1263 1264 static int 1265 tmpfs_rmdir(struct vop_rmdir_args *v) 1266 { 1267 struct vnode *dvp = v->a_dvp; 1268 struct vnode *vp = v->a_vp; 1269 1270 int error; 1271 struct tmpfs_dirent *de; 1272 struct tmpfs_mount *tmp; 1273 struct tmpfs_node *dnode; 1274 struct tmpfs_node *node; 1275 1276 MPASS(VOP_ISLOCKED(dvp)); 1277 MPASS(VOP_ISLOCKED(vp)); 1278 1279 tmp = VFS_TO_TMPFS(dvp->v_mount); 1280 dnode = VP_TO_TMPFS_DIR(dvp); 1281 node = VP_TO_TMPFS_DIR(vp); 1282 1283 /* Directories with more than two entries ('.' and '..') cannot be 1284 * removed. */ 1285 if (node->tn_size > 0) { 1286 error = ENOTEMPTY; 1287 goto out; 1288 } 1289 1290 if ((dnode->tn_flags & APPEND) 1291 || (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) { 1292 error = EPERM; 1293 goto out; 1294 } 1295 1296 /* This invariant holds only if we are not trying to remove "..". 1297 * We checked for that above so this is safe now. */ 1298 MPASS(node->tn_dir.tn_parent == dnode); 1299 1300 /* Get the directory entry associated with node (vp). This was 1301 * filled by tmpfs_lookup while looking up the entry. */ 1302 de = tmpfs_dir_lookup(dnode, node, v->a_cnp); 1303 MPASS(TMPFS_DIRENT_MATCHES(de, 1304 v->a_cnp->cn_nameptr, 1305 v->a_cnp->cn_namelen)); 1306 1307 /* Check flags to see if we are allowed to remove the directory. */ 1308 if ((dnode->tn_flags & APPEND) != 0 || 1309 (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) != 0) { 1310 error = EPERM; 1311 goto out; 1312 } 1313 1314 /* Detach the directory entry from the directory (dnode). */ 1315 tmpfs_dir_detach(dvp, de); 1316 if (v->a_cnp->cn_flags & DOWHITEOUT) 1317 tmpfs_dir_whiteout_add(dvp, v->a_cnp); 1318 1319 /* No vnode should be allocated for this entry from this point */ 1320 TMPFS_NODE_LOCK(node); 1321 node->tn_links--; 1322 node->tn_dir.tn_parent = NULL; 1323 node->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; 1324 node->tn_accessed = true; 1325 1326 TMPFS_NODE_UNLOCK(node); 1327 1328 TMPFS_NODE_LOCK(dnode); 1329 dnode->tn_links--; 1330 dnode->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; 1331 dnode->tn_accessed = true; 1332 TMPFS_NODE_UNLOCK(dnode); 1333 1334 if (tmpfs_use_nc(dvp)) { 1335 cache_vop_rmdir(dvp, vp); 1336 } 1337 1338 /* Free the directory entry we just deleted. Note that the node 1339 * referred by it will not be removed until the vnode is really 1340 * reclaimed. */ 1341 tmpfs_free_dirent(tmp, de); 1342 1343 /* Release the deleted vnode (will destroy the node, notify 1344 * interested parties and clean it from the cache). */ 1345 1346 dnode->tn_status |= TMPFS_NODE_CHANGED; 1347 tmpfs_update(dvp); 1348 1349 error = 0; 1350 1351 out: 1352 return error; 1353 } 1354 1355 static int 1356 tmpfs_symlink(struct vop_symlink_args *v) 1357 { 1358 struct vnode *dvp = v->a_dvp; 1359 struct vnode **vpp = v->a_vpp; 1360 struct componentname *cnp = v->a_cnp; 1361 struct vattr *vap = v->a_vap; 1362 const char *target = v->a_target; 1363 1364 #ifdef notyet /* XXX FreeBSD BUG: kern_symlink is not setting VLNK */ 1365 MPASS(vap->va_type == VLNK); 1366 #else 1367 vap->va_type = VLNK; 1368 #endif 1369 1370 return tmpfs_alloc_file(dvp, vpp, vap, cnp, target); 1371 } 1372 1373 static int 1374 tmpfs_readdir(struct vop_readdir_args *va) 1375 { 1376 struct vnode *vp; 1377 struct uio *uio; 1378 struct tmpfs_mount *tm; 1379 struct tmpfs_node *node; 1380 u_long **cookies; 1381 int *eofflag, *ncookies; 1382 ssize_t startresid; 1383 int error, maxcookies; 1384 1385 vp = va->a_vp; 1386 uio = va->a_uio; 1387 eofflag = va->a_eofflag; 1388 cookies = va->a_cookies; 1389 ncookies = va->a_ncookies; 1390 1391 /* This operation only makes sense on directory nodes. */ 1392 if (vp->v_type != VDIR) 1393 return ENOTDIR; 1394 1395 maxcookies = 0; 1396 node = VP_TO_TMPFS_DIR(vp); 1397 tm = VFS_TO_TMPFS(vp->v_mount); 1398 1399 startresid = uio->uio_resid; 1400 1401 /* Allocate cookies for NFS and compat modules. */ 1402 if (cookies != NULL && ncookies != NULL) { 1403 maxcookies = howmany(node->tn_size, 1404 sizeof(struct tmpfs_dirent)) + 2; 1405 *cookies = malloc(maxcookies * sizeof(**cookies), M_TEMP, 1406 M_WAITOK); 1407 *ncookies = 0; 1408 } 1409 1410 if (cookies == NULL) 1411 error = tmpfs_dir_getdents(tm, node, uio, 0, NULL, NULL); 1412 else 1413 error = tmpfs_dir_getdents(tm, node, uio, maxcookies, *cookies, 1414 ncookies); 1415 1416 /* Buffer was filled without hitting EOF. */ 1417 if (error == EJUSTRETURN) 1418 error = (uio->uio_resid != startresid) ? 0 : EINVAL; 1419 1420 if (error != 0 && cookies != NULL && ncookies != NULL) { 1421 free(*cookies, M_TEMP); 1422 *cookies = NULL; 1423 *ncookies = 0; 1424 } 1425 1426 if (eofflag != NULL) 1427 *eofflag = 1428 (error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF); 1429 1430 return error; 1431 } 1432 1433 static int 1434 tmpfs_readlink(struct vop_readlink_args *v) 1435 { 1436 struct vnode *vp = v->a_vp; 1437 struct uio *uio = v->a_uio; 1438 1439 int error; 1440 struct tmpfs_node *node; 1441 1442 MPASS(uio->uio_offset == 0); 1443 MPASS(vp->v_type == VLNK); 1444 1445 node = VP_TO_TMPFS_NODE(vp); 1446 1447 error = uiomove(node->tn_link_target, MIN(node->tn_size, uio->uio_resid), 1448 uio); 1449 tmpfs_set_accessed(VFS_TO_TMPFS(vp->v_mount), node); 1450 1451 return (error); 1452 } 1453 1454 /* 1455 * VOP_FPLOOKUP_SYMLINK routines are subject to special circumstances, see 1456 * the comment above cache_fplookup for details. 1457 * 1458 * Check tmpfs_alloc_node for tmpfs-specific synchronisation notes. 1459 */ 1460 static int 1461 tmpfs_fplookup_symlink(struct vop_fplookup_symlink_args *v) 1462 { 1463 struct vnode *vp; 1464 struct tmpfs_node *node; 1465 char *symlink; 1466 1467 vp = v->a_vp; 1468 node = VP_TO_TMPFS_NODE_SMR(vp); 1469 atomic_thread_fence_acq(); 1470 if (__predict_false(node == NULL)) 1471 return (EAGAIN); 1472 if (!atomic_load_char(&node->tn_link_smr)) 1473 return (EAGAIN); 1474 symlink = atomic_load_ptr(&node->tn_link_target); 1475 if (symlink == NULL) 1476 return (EAGAIN); 1477 1478 return (cache_symlink_resolve(v->a_fpl, symlink, node->tn_size)); 1479 } 1480 1481 static int 1482 tmpfs_inactive(struct vop_inactive_args *v) 1483 { 1484 struct vnode *vp; 1485 struct tmpfs_node *node; 1486 1487 vp = v->a_vp; 1488 node = VP_TO_TMPFS_NODE(vp); 1489 if (node->tn_links == 0) 1490 vrecycle(vp); 1491 else 1492 tmpfs_check_mtime(vp); 1493 return (0); 1494 } 1495 1496 static int 1497 tmpfs_need_inactive(struct vop_need_inactive_args *ap) 1498 { 1499 struct vnode *vp; 1500 struct tmpfs_node *node; 1501 struct vm_object *obj; 1502 1503 vp = ap->a_vp; 1504 node = VP_TO_TMPFS_NODE(vp); 1505 if (node->tn_links == 0) 1506 goto need; 1507 if (vp->v_type == VREG) { 1508 obj = vp->v_object; 1509 if (obj->generation != obj->cleangeneration) 1510 goto need; 1511 } 1512 return (0); 1513 need: 1514 return (1); 1515 } 1516 1517 int 1518 tmpfs_reclaim(struct vop_reclaim_args *v) 1519 { 1520 struct vnode *vp; 1521 struct tmpfs_mount *tmp; 1522 struct tmpfs_node *node; 1523 bool unlock, tm_locked; 1524 1525 vp = v->a_vp; 1526 node = VP_TO_TMPFS_NODE(vp); 1527 tmp = VFS_TO_TMPFS(vp->v_mount); 1528 tm_locked = false; 1529 1530 if (vp->v_type == VREG) 1531 tmpfs_destroy_vobject(vp, node->tn_reg.tn_aobj); 1532 vp->v_object = NULL; 1533 1534 relock: 1535 TMPFS_NODE_LOCK(node); 1536 if (!tm_locked && node->tn_links == 0 && 1537 (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0) { 1538 TMPFS_NODE_UNLOCK(node); 1539 TMPFS_LOCK(tmp); 1540 tm_locked = true; 1541 goto relock; 1542 } 1543 tmpfs_free_vp(vp); 1544 1545 /* 1546 * If the node referenced by this vnode was deleted by the user, 1547 * we must free its associated data structures (now that the vnode 1548 * is being reclaimed). 1549 */ 1550 if (node->tn_links == 0 && 1551 (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0) { 1552 MPASS(tm_locked); 1553 node->tn_vpstate = TMPFS_VNODE_DOOMED; 1554 unlock = !tmpfs_free_node_locked(tmp, node, true); 1555 } else { 1556 unlock = true; 1557 } 1558 1559 if (unlock) { 1560 TMPFS_NODE_UNLOCK(node); 1561 if (tm_locked) 1562 TMPFS_UNLOCK(tmp); 1563 } 1564 1565 MPASS(vp->v_data == NULL); 1566 return (0); 1567 } 1568 1569 int 1570 tmpfs_print(struct vop_print_args *v) 1571 { 1572 struct vnode *vp = v->a_vp; 1573 1574 struct tmpfs_node *node; 1575 1576 node = VP_TO_TMPFS_NODE(vp); 1577 1578 printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%lx, links %jd\n", 1579 node, node->tn_flags, (uintmax_t)node->tn_links); 1580 printf("\tmode 0%o, owner %d, group %d, size %jd, status 0x%x\n", 1581 node->tn_mode, node->tn_uid, node->tn_gid, 1582 (intmax_t)node->tn_size, node->tn_status); 1583 1584 if (vp->v_type == VFIFO) 1585 fifo_printinfo(vp); 1586 1587 printf("\n"); 1588 1589 return 0; 1590 } 1591 1592 int 1593 tmpfs_pathconf(struct vop_pathconf_args *v) 1594 { 1595 struct vnode *vp = v->a_vp; 1596 int name = v->a_name; 1597 long *retval = v->a_retval; 1598 1599 int error; 1600 1601 error = 0; 1602 1603 switch (name) { 1604 case _PC_LINK_MAX: 1605 *retval = TMPFS_LINK_MAX; 1606 break; 1607 1608 case _PC_NAME_MAX: 1609 *retval = NAME_MAX; 1610 break; 1611 1612 case _PC_PIPE_BUF: 1613 if (vp->v_type == VDIR || vp->v_type == VFIFO) 1614 *retval = PIPE_BUF; 1615 else 1616 error = EINVAL; 1617 break; 1618 1619 case _PC_CHOWN_RESTRICTED: 1620 *retval = 1; 1621 break; 1622 1623 case _PC_NO_TRUNC: 1624 *retval = 1; 1625 break; 1626 1627 case _PC_SYNC_IO: 1628 *retval = 1; 1629 break; 1630 1631 case _PC_FILESIZEBITS: 1632 *retval = 64; 1633 break; 1634 1635 default: 1636 error = vop_stdpathconf(v); 1637 } 1638 1639 return error; 1640 } 1641 1642 static int 1643 tmpfs_vptofh(struct vop_vptofh_args *ap) 1644 /* 1645 vop_vptofh { 1646 IN struct vnode *a_vp; 1647 IN struct fid *a_fhp; 1648 }; 1649 */ 1650 { 1651 struct tmpfs_fid_data tfd; 1652 struct tmpfs_node *node; 1653 struct fid *fhp; 1654 1655 node = VP_TO_TMPFS_NODE(ap->a_vp); 1656 fhp = ap->a_fhp; 1657 fhp->fid_len = sizeof(tfd); 1658 1659 /* 1660 * Copy into fid_data from the stack to avoid unaligned pointer use. 1661 * See the comment in sys/mount.h on struct fid for details. 1662 */ 1663 tfd.tfd_id = node->tn_id; 1664 tfd.tfd_gen = node->tn_gen; 1665 memcpy(fhp->fid_data, &tfd, fhp->fid_len); 1666 1667 return (0); 1668 } 1669 1670 static int 1671 tmpfs_whiteout(struct vop_whiteout_args *ap) 1672 { 1673 struct vnode *dvp = ap->a_dvp; 1674 struct componentname *cnp = ap->a_cnp; 1675 struct tmpfs_dirent *de; 1676 1677 switch (ap->a_flags) { 1678 case LOOKUP: 1679 return (0); 1680 case CREATE: 1681 de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp); 1682 if (de != NULL) 1683 return (de->td_node == NULL ? 0 : EEXIST); 1684 return (tmpfs_dir_whiteout_add(dvp, cnp)); 1685 case DELETE: 1686 tmpfs_dir_whiteout_remove(dvp, cnp); 1687 return (0); 1688 default: 1689 panic("tmpfs_whiteout: unknown op"); 1690 } 1691 } 1692 1693 static int 1694 tmpfs_vptocnp_dir(struct tmpfs_node *tn, struct tmpfs_node *tnp, 1695 struct tmpfs_dirent **pde) 1696 { 1697 struct tmpfs_dir_cursor dc; 1698 struct tmpfs_dirent *de; 1699 1700 for (de = tmpfs_dir_first(tnp, &dc); de != NULL; 1701 de = tmpfs_dir_next(tnp, &dc)) { 1702 if (de->td_node == tn) { 1703 *pde = de; 1704 return (0); 1705 } 1706 } 1707 return (ENOENT); 1708 } 1709 1710 static int 1711 tmpfs_vptocnp_fill(struct vnode *vp, struct tmpfs_node *tn, 1712 struct tmpfs_node *tnp, char *buf, size_t *buflen, struct vnode **dvp) 1713 { 1714 struct tmpfs_dirent *de; 1715 int error, i; 1716 1717 error = vn_vget_ino_gen(vp, tmpfs_vn_get_ino_alloc, tnp, LK_SHARED, 1718 dvp); 1719 if (error != 0) 1720 return (error); 1721 error = tmpfs_vptocnp_dir(tn, tnp, &de); 1722 if (error == 0) { 1723 i = *buflen; 1724 i -= de->td_namelen; 1725 if (i < 0) { 1726 error = ENOMEM; 1727 } else { 1728 bcopy(de->ud.td_name, buf + i, de->td_namelen); 1729 *buflen = i; 1730 } 1731 } 1732 if (error == 0) { 1733 if (vp != *dvp) 1734 VOP_UNLOCK(*dvp); 1735 } else { 1736 if (vp != *dvp) 1737 vput(*dvp); 1738 else 1739 vrele(vp); 1740 } 1741 return (error); 1742 } 1743 1744 static int 1745 tmpfs_vptocnp(struct vop_vptocnp_args *ap) 1746 { 1747 struct vnode *vp, **dvp; 1748 struct tmpfs_node *tn, *tnp, *tnp1; 1749 struct tmpfs_dirent *de; 1750 struct tmpfs_mount *tm; 1751 char *buf; 1752 size_t *buflen; 1753 int error; 1754 1755 vp = ap->a_vp; 1756 dvp = ap->a_vpp; 1757 buf = ap->a_buf; 1758 buflen = ap->a_buflen; 1759 1760 tm = VFS_TO_TMPFS(vp->v_mount); 1761 tn = VP_TO_TMPFS_NODE(vp); 1762 if (tn->tn_type == VDIR) { 1763 tnp = tn->tn_dir.tn_parent; 1764 if (tnp == NULL) 1765 return (ENOENT); 1766 tmpfs_ref_node(tnp); 1767 error = tmpfs_vptocnp_fill(vp, tn, tn->tn_dir.tn_parent, buf, 1768 buflen, dvp); 1769 tmpfs_free_node(tm, tnp); 1770 return (error); 1771 } 1772 restart: 1773 TMPFS_LOCK(tm); 1774 restart_locked: 1775 LIST_FOREACH_SAFE(tnp, &tm->tm_nodes_used, tn_entries, tnp1) { 1776 if (tnp->tn_type != VDIR) 1777 continue; 1778 TMPFS_NODE_LOCK(tnp); 1779 tmpfs_ref_node(tnp); 1780 1781 /* 1782 * tn_vnode cannot be instantiated while we hold the 1783 * node lock, so the directory cannot be changed while 1784 * we iterate over it. Do this to avoid instantiating 1785 * vnode for directories which cannot point to our 1786 * node. 1787 */ 1788 error = tnp->tn_vnode == NULL ? tmpfs_vptocnp_dir(tn, tnp, 1789 &de) : 0; 1790 1791 if (error == 0) { 1792 TMPFS_NODE_UNLOCK(tnp); 1793 TMPFS_UNLOCK(tm); 1794 error = tmpfs_vptocnp_fill(vp, tn, tnp, buf, buflen, 1795 dvp); 1796 if (error == 0) { 1797 tmpfs_free_node(tm, tnp); 1798 return (0); 1799 } 1800 if (VN_IS_DOOMED(vp)) { 1801 tmpfs_free_node(tm, tnp); 1802 return (ENOENT); 1803 } 1804 TMPFS_LOCK(tm); 1805 TMPFS_NODE_LOCK(tnp); 1806 } 1807 if (tmpfs_free_node_locked(tm, tnp, false)) { 1808 goto restart; 1809 } else { 1810 KASSERT(tnp->tn_refcount > 0, 1811 ("node %p refcount zero", tnp)); 1812 if (tnp->tn_attached) { 1813 tnp1 = LIST_NEXT(tnp, tn_entries); 1814 TMPFS_NODE_UNLOCK(tnp); 1815 } else { 1816 TMPFS_NODE_UNLOCK(tnp); 1817 goto restart_locked; 1818 } 1819 } 1820 } 1821 TMPFS_UNLOCK(tm); 1822 return (ENOENT); 1823 } 1824 1825 /* 1826 * Vnode operations vector used for files stored in a tmpfs file system. 1827 */ 1828 struct vop_vector tmpfs_vnodeop_entries = { 1829 .vop_default = &default_vnodeops, 1830 .vop_lookup = vfs_cache_lookup, 1831 .vop_cachedlookup = tmpfs_cached_lookup, 1832 .vop_create = tmpfs_create, 1833 .vop_mknod = tmpfs_mknod, 1834 .vop_open = tmpfs_open, 1835 .vop_close = tmpfs_close, 1836 .vop_fplookup_vexec = tmpfs_fplookup_vexec, 1837 .vop_fplookup_symlink = tmpfs_fplookup_symlink, 1838 .vop_access = tmpfs_access, 1839 .vop_stat = tmpfs_stat, 1840 .vop_getattr = tmpfs_getattr, 1841 .vop_setattr = tmpfs_setattr, 1842 .vop_read = tmpfs_read, 1843 .vop_read_pgcache = tmpfs_read_pgcache, 1844 .vop_write = tmpfs_write, 1845 .vop_fsync = tmpfs_fsync, 1846 .vop_remove = tmpfs_remove, 1847 .vop_link = tmpfs_link, 1848 .vop_rename = tmpfs_rename, 1849 .vop_mkdir = tmpfs_mkdir, 1850 .vop_rmdir = tmpfs_rmdir, 1851 .vop_symlink = tmpfs_symlink, 1852 .vop_readdir = tmpfs_readdir, 1853 .vop_readlink = tmpfs_readlink, 1854 .vop_inactive = tmpfs_inactive, 1855 .vop_need_inactive = tmpfs_need_inactive, 1856 .vop_reclaim = tmpfs_reclaim, 1857 .vop_print = tmpfs_print, 1858 .vop_pathconf = tmpfs_pathconf, 1859 .vop_vptofh = tmpfs_vptofh, 1860 .vop_whiteout = tmpfs_whiteout, 1861 .vop_bmap = VOP_EOPNOTSUPP, 1862 .vop_vptocnp = tmpfs_vptocnp, 1863 .vop_lock1 = vop_lock, 1864 .vop_unlock = vop_unlock, 1865 .vop_islocked = vop_islocked, 1866 }; 1867 VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_entries); 1868 1869 /* 1870 * Same vector for mounts which do not use namecache. 1871 */ 1872 struct vop_vector tmpfs_vnodeop_nonc_entries = { 1873 .vop_default = &tmpfs_vnodeop_entries, 1874 .vop_lookup = tmpfs_lookup, 1875 }; 1876 VFS_VOP_VECTOR_REGISTER(tmpfs_vnodeop_nonc_entries); 1877