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