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