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