xref: /openbsd-src/sys/tmpfs/tmpfs_vnops.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: tmpfs_vnops.c,v 1.51 2021/12/11 09:28:26 visa Exp $	*/
2 /*	$NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $	*/
3 
4 /*
5  * Copyright (c) 2005, 2006, 2007, 2012 The NetBSD Foundation, Inc.
6  * Copyright (c) 2013 Pedro Martelletto
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, and by Taylor R Campbell.
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 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/fcntl.h>
42 #include <sys/event.h>
43 #include <sys/namei.h>
44 #include <sys/stat.h>
45 #include <sys/uio.h>
46 #include <sys/unistd.h>
47 #include <sys/vnode.h>
48 #include <sys/lockf.h>
49 #include <sys/poll.h>
50 #include <sys/file.h>
51 
52 #include <miscfs/fifofs/fifo.h>
53 #include <tmpfs/tmpfs_vnops.h>
54 #include <tmpfs/tmpfs.h>
55 
56 int tmpfs_kqfilter(void *v);
57 
58 /*
59  * vnode operations vector used for files stored in a tmpfs file system.
60  */
61 const struct vops tmpfs_vops = {
62 	.vop_lookup	= tmpfs_lookup,
63 	.vop_create	= tmpfs_create,
64 	.vop_mknod	= tmpfs_mknod,
65 	.vop_open	= tmpfs_open,
66 	.vop_close	= tmpfs_close,
67 	.vop_access	= tmpfs_access,
68 	.vop_getattr	= tmpfs_getattr,
69 	.vop_setattr	= tmpfs_setattr,
70 	.vop_read	= tmpfs_read,
71 	.vop_write	= tmpfs_write,
72 	.vop_ioctl	= tmpfs_ioctl,
73 	.vop_poll	= tmpfs_poll,
74 	.vop_kqfilter	= tmpfs_kqfilter,
75 	.vop_revoke	= vop_generic_revoke,
76 	.vop_fsync	= tmpfs_fsync,
77 	.vop_remove	= tmpfs_remove,
78 	.vop_link	= tmpfs_link,
79 	.vop_rename	= tmpfs_rename,
80 	.vop_mkdir	= tmpfs_mkdir,
81 	.vop_rmdir	= tmpfs_rmdir,
82 	.vop_symlink	= tmpfs_symlink,
83 	.vop_readdir	= tmpfs_readdir,
84 	.vop_readlink	= tmpfs_readlink,
85 	.vop_abortop	= vop_generic_abortop,
86 	.vop_inactive	= tmpfs_inactive,
87 	.vop_reclaim	= tmpfs_reclaim,
88 	.vop_lock	= tmpfs_lock,
89 	.vop_unlock	= tmpfs_unlock,
90 	.vop_bmap	= vop_generic_bmap,
91 	.vop_strategy	= tmpfs_strategy,
92 	.vop_print	= tmpfs_print,
93 	.vop_islocked	= tmpfs_islocked,
94 	.vop_pathconf	= tmpfs_pathconf,
95 	.vop_advlock	= tmpfs_advlock,
96 	.vop_bwrite	= tmpfs_bwrite,
97 };
98 
99 /*
100  * tmpfs_lookup: path name traversal routine.
101  *
102  * Arguments: dvp (directory being searched), vpp (result),
103  * cnp (component name - path).
104  *
105  * => Caller holds a reference and lock on dvp.
106  * => We return looked-up vnode (vpp) locked, with a reference held.
107  */
108 int
109 tmpfs_lookup(void *v)
110 {
111 	struct vop_lookup_args /* {
112 		struct vnode *a_dvp;
113 		struct vnode **a_vpp;
114 		struct componentname *a_cnp;
115 	} */ *ap = v;
116 	struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
117 	struct componentname *cnp = ap->a_cnp;
118 	struct ucred *cred = cnp->cn_cred;
119 	const int lastcn = (cnp->cn_flags & ISLASTCN) != 0;
120 	const int lockparent = (cnp->cn_flags & LOCKPARENT) != 0;
121 	tmpfs_node_t *dnode, *tnode;
122 	tmpfs_dirent_t *de;
123 	int cachefound;
124 	int error;
125 
126 	KASSERT(VOP_ISLOCKED(dvp));
127 
128 	dnode = VP_TO_TMPFS_DIR(dvp);
129 	cnp->cn_flags &= ~PDIRUNLOCK;
130 	*vpp = NULL;
131 
132 	/* Check accessibility of directory. */
133 	error = VOP_ACCESS(dvp, VEXEC, cred, curproc);
134 	if (error) {
135 		goto out;
136 	}
137 
138 	/*
139 	 * If requesting the last path component on a read-only file system
140 	 * with a write operation, deny it.
141 	 */
142 	if (lastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) != 0 &&
143 	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
144 		error = EROFS;
145 		goto out;
146 	}
147 
148 	/*
149 	 * Avoid doing a linear scan of the directory if the requested
150 	 * directory/name couple is already in the cache.
151 	 */
152 	cachefound = cache_lookup(dvp, vpp, cnp);
153 	if (cachefound == ENOENT /* && *vpp == NULLVP */)
154 		return ENOENT; /* Negative cache hit. */
155 	else if (cachefound != -1)
156 		return 0; /* Found in cache. */
157 
158 	if (cnp->cn_flags & ISDOTDOT) {
159 		tmpfs_node_t *pnode;
160 
161 		/*
162 		 * Lookup of ".." case.
163 		 */
164 		if (lastcn) {
165 			if (cnp->cn_nameiop == RENAME) {
166 				error = EINVAL;
167 				goto out;
168 			}
169 			if (cnp->cn_nameiop == DELETE) {
170 				/* Keep the name for tmpfs_rmdir(). */
171 				cnp->cn_flags |= SAVENAME;
172 			}
173 		}
174 		KASSERT(dnode->tn_type == VDIR);
175 		pnode = dnode->tn_spec.tn_dir.tn_parent;
176 		if (pnode == NULL) {
177 			error = ENOENT;
178 			goto out;
179 		}
180 
181 		/*
182 		 * Lock the parent tn_nlock before releasing the vnode lock,
183 		 * and thus prevents parent from disappearing.
184 		 */
185 		rw_enter_write(&pnode->tn_nlock);
186 		VOP_UNLOCK(dvp);
187 
188 		/*
189 		 * Get a vnode of the '..' entry and re-acquire the lock.
190 		 * Release the tn_nlock.
191 		 */
192 		error = tmpfs_vnode_get(dvp->v_mount, pnode, vpp);
193 		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
194 		goto out;
195 
196 	} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
197 		/*
198 		 * Lookup of "." case.
199 		 */
200 		if (lastcn && cnp->cn_nameiop == RENAME) {
201 			error = EISDIR;
202 			goto out;
203 		}
204 		vref(dvp);
205 		*vpp = dvp;
206 		error = 0;
207 		goto done;
208 	}
209 
210 	/*
211 	 * Other lookup cases: perform directory scan.
212 	 */
213 	de = tmpfs_dir_lookup(dnode, cnp);
214 	if (de == NULL) {
215 		/*
216 		 * The entry was not found in the directory.  This is valid
217 		 * if we are creating or renaming an entry and are working
218 		 * on the last component of the path name.
219 		 */
220 		if (lastcn && (cnp->cn_nameiop == CREATE ||
221 		    cnp->cn_nameiop == RENAME)) {
222 			error = VOP_ACCESS(dvp, VWRITE, cred, curproc);
223 			if (error) {
224 				goto out;
225 			}
226 			/*
227 			 * We are creating an entry in the file system, so
228 			 * save its name for further use by tmpfs_create().
229 			 */
230 			cnp->cn_flags |= SAVENAME;
231 			error = EJUSTRETURN;
232 		} else {
233 			error = ENOENT;
234 		}
235 		goto done;
236 	}
237 
238 	tnode = de->td_node;
239 
240 	/*
241 	 * If it is not the last path component and found a non-directory
242 	 * or non-link entry (which may itself be pointing to a directory),
243 	 * raise an error.
244 	 */
245 	if (!lastcn && tnode->tn_type != VDIR && tnode->tn_type != VLNK) {
246 		error = ENOTDIR;
247 		goto out;
248 	}
249 
250 	/* Check the permissions. */
251 	if (lastcn && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
252 		error = VOP_ACCESS(dvp, VWRITE, cred, curproc);
253 		if (error)
254 			goto out;
255 
256 		/*
257 		 * If not root and directory is sticky, check for permission
258 		 * on directory or on file. This implements append-only
259 		 * directories.
260 		 */
261 		if ((dnode->tn_mode & S_ISTXT) != 0) {
262 			if (cred->cr_uid != 0 &&
263 			    cred->cr_uid != dnode->tn_uid &&
264 			    cred->cr_uid != tnode->tn_uid) {
265 				error = EPERM;
266 				goto out;
267 			}
268 		}
269 
270 		/*
271 		 * XXX pedro: We might need cn_nameptr later in tmpfs_remove()
272 		 * or tmpfs_rmdir() for a tmpfs_dir_lookup(). We should really
273 		 * get rid of SAVENAME at some point.
274 		 */
275 		if (cnp->cn_nameiop == DELETE)
276 			cnp->cn_flags |= SAVENAME;
277 	}
278 
279 	/* Get a vnode for the matching entry. */
280 	rw_enter_write(&tnode->tn_nlock);
281 	error = tmpfs_vnode_get(dvp->v_mount, tnode, vpp);
282 done:
283 	/*
284 	 * Cache the result, unless request was for creation (as it does
285 	 * not improve the performance).
286 	 */
287 	if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
288 		cache_enter(dvp, *vpp, cnp);
289 	}
290 out:
291 	/*
292 	 * If (1) we succeeded, (2) found a distinct vnode != .. to return and (3)
293 	 * were either explicitly told to keep the parent locked or are in the
294 	 * middle of a lookup, unlock the parent vnode.
295 	 */
296 	if ((error == 0 || error == EJUSTRETURN) && /* (1) */
297 	    (*vpp != dvp || (cnp->cn_flags & ISDOTDOT))  && /* (2) */
298 	    (!lockparent || !lastcn)) {		    /* (3) */
299 		VOP_UNLOCK(dvp);
300 		cnp->cn_flags |= PDIRUNLOCK;
301 	} else
302 		KASSERT(VOP_ISLOCKED(dvp));
303 
304 	KASSERT((*vpp && VOP_ISLOCKED(*vpp)) || error);
305 
306 	return error;
307 }
308 
309 int
310 tmpfs_create(void *v)
311 {
312 	struct vop_create_args /* {
313 		struct vnode		*a_dvp;
314 		struct vnode		**a_vpp;
315 		struct componentname	*a_cnp;
316 		struct vattr		*a_vap;
317 	} */ *ap = v;
318 	struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
319 	struct componentname *cnp = ap->a_cnp;
320 	struct vattr *vap = ap->a_vap;
321 
322 	KASSERT(VOP_ISLOCKED(dvp));
323 	KASSERT(cnp->cn_flags & HASBUF);
324 	KASSERT(vap->va_type == VREG || vap->va_type == VSOCK);
325 	return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
326 }
327 
328 int
329 tmpfs_mknod(void *v)
330 {
331 	struct vop_mknod_args /* {
332 		struct vnode		*a_dvp;
333 		struct vnode		**a_vpp;
334 		struct componentname	*a_cnp;
335 		struct vattr		*a_vap;
336 	} */ *ap = v;
337 	struct vnode *dvp = ap->a_dvp, **vpp = ap->a_vpp;
338 	struct componentname *cnp = ap->a_cnp;
339 	struct vattr *vap = ap->a_vap;
340 	enum vtype vt = vap->va_type;
341 	int error;
342 
343 	if (vt != VBLK && vt != VCHR && vt != VFIFO)
344 		return EINVAL;
345 
346 	error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
347 
348 	if (error == 0)
349 		vput(*vpp);
350 
351 	return error;
352 }
353 
354 int
355 tmpfs_open(void *v)
356 {
357 	struct vop_open_args /* {
358 		struct vnode	*a_vp;
359 		int		a_mode;
360 		kauth_cred_t	a_cred;
361 	} */ *ap = v;
362 	struct vnode *vp = ap->a_vp;
363 	mode_t mode = ap->a_mode;
364 	tmpfs_node_t *node;
365 
366 	KASSERT(VOP_ISLOCKED(vp));
367 
368 	node = VP_TO_TMPFS_NODE(vp);
369 	if (node->tn_links < 1) {
370 		/*
371 		 * The file is still active, but all its names have been
372 		 * removed (e.g. by a "rmdir $(pwd)").  It cannot be opened
373 		 * any more, as it is about to be destroyed.
374 		 */
375 		return ENOENT;
376 	}
377 
378 	/* If the file is marked append-only, deny write requests. */
379 	if ((node->tn_flags & APPEND) != 0 &&
380 	    (mode & (FWRITE | O_APPEND)) == FWRITE) {
381 		return EPERM;
382 	}
383 	return 0;
384 }
385 
386 int
387 tmpfs_close(void *v)
388 {
389 #ifdef DIAGNOSTIC
390 	struct vop_close_args /* {
391 		struct vnode	*a_vp;
392 		int		a_fflag;
393 		kauth_cred_t	a_cred;
394 	} */ *ap = v;
395 	struct vnode *vp = ap->a_vp;
396 
397 	KASSERT(VOP_ISLOCKED(vp));
398 #endif
399 	return 0;
400 }
401 
402 int
403 tmpfs_access(void *v)
404 {
405 	struct vop_access_args /* {
406 		struct vnode	*a_vp;
407 		int		a_mode;
408 		kauth_cred_t	a_cred;
409 	} */ *ap = v;
410 	struct vnode *vp = ap->a_vp;
411 	mode_t mode = ap->a_mode;
412 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
413 	const int writing = (mode & VWRITE) != 0;
414 
415 	KASSERT(VOP_ISLOCKED(vp));
416 
417 	/* Possible? */
418 	switch (vp->v_type) {
419 	case VDIR:
420 	case VLNK:
421 	case VREG:
422 		if (writing && (vp->v_mount->mnt_flag & MNT_RDONLY) != 0) {
423 			return EROFS;
424 		}
425 		break;
426 	case VBLK:
427 	case VCHR:
428 	case VSOCK:
429 	case VFIFO:
430 		break;
431 	default:
432 		return EINVAL;
433 	}
434 	if (writing && (node->tn_flags & IMMUTABLE) != 0) {
435 		return EPERM;
436 	}
437 
438 	return (vaccess(vp->v_type, node->tn_mode, node->tn_uid, node->tn_gid,
439 	    mode, ap->a_cred));
440 }
441 
442 int
443 tmpfs_getattr(void *v)
444 {
445 	struct vop_getattr_args /* {
446 		struct vnode	*a_vp;
447 		struct vattr	*a_vap;
448 		kauth_cred_t	a_cred;
449 	} */ *ap = v;
450 	struct vnode *vp = ap->a_vp;
451 	struct vattr *vap = ap->a_vap;
452 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
453 
454 	vattr_null(vap);
455 
456 	vap->va_type = vp->v_type;
457 	vap->va_mode = node->tn_mode;
458 	vap->va_nlink = node->tn_links;
459 	vap->va_uid = node->tn_uid;
460 	vap->va_gid = node->tn_gid;
461 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
462 	vap->va_fileid = node->tn_id;
463 	vap->va_size = node->tn_size;
464 	vap->va_blocksize = PAGE_SIZE;
465 	vap->va_atime = node->tn_atime;
466 	vap->va_mtime = node->tn_mtime;
467 	vap->va_ctime = node->tn_ctime;
468 	/* vap->va_birthtime = node->tn_birthtime; */
469 	vap->va_gen = TMPFS_NODE_GEN(node);
470 	vap->va_flags = node->tn_flags;
471 	vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
472 	    node->tn_spec.tn_dev.tn_rdev : VNOVAL;
473 	vap->va_bytes = round_page(node->tn_size);
474 	vap->va_filerev = VNOVAL;
475 	vap->va_vaflags = 0;
476 	vap->va_spare = VNOVAL; /* XXX */
477 
478 	return 0;
479 }
480 
481 #define GOODTIME(tv)	((tv)->tv_nsec != VNOVAL)
482 /* XXX Should this operation be atomic?  I think it should, but code in
483  * XXX other places (e.g., ufs) doesn't seem to be... */
484 int
485 tmpfs_setattr(void *v)
486 {
487 	struct vop_setattr_args /* {
488 		struct vnode	*a_vp;
489 		struct vattr	*a_vap;
490 		kauth_cred_t	a_cred;
491 	} */ *ap = v;
492 	struct vnode *vp = ap->a_vp;
493 	struct vattr *vap = ap->a_vap;
494 	struct ucred *cred = ap->a_cred;
495 	struct proc *p = curproc;
496 	int error = 0;
497 
498 	KASSERT(VOP_ISLOCKED(vp));
499 
500 	/* Abort if any unsettable attribute is given. */
501 	if (vap->va_type != VNON || vap->va_nlink != VNOVAL ||
502 	    vap->va_fsid != VNOVAL || vap->va_fileid != VNOVAL ||
503 	    vap->va_blocksize != VNOVAL || GOODTIME(&vap->va_ctime) ||
504 	    vap->va_gen != VNOVAL || vap->va_rdev != VNOVAL ||
505 	    vap->va_bytes != VNOVAL) {
506 		return EINVAL;
507 	}
508 	if (error == 0 && (vap->va_flags != VNOVAL))
509 		error = tmpfs_chflags(vp, vap->va_flags, cred, p);
510 
511 	if (error == 0 && (vap->va_size != VNOVAL))
512 		error = tmpfs_chsize(vp, vap->va_size, cred, p);
513 
514 	if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL))
515 		error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
516 
517 	if (error == 0 && (vap->va_mode != VNOVAL))
518 		error = tmpfs_chmod(vp, vap->va_mode, cred, p);
519 
520 	if (error == 0 && ((vap->va_vaflags & VA_UTIMES_CHANGE)
521 	    || GOODTIME(&vap->va_atime)
522 	    || GOODTIME(&vap->va_mtime)))
523 		error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,
524 		    vap->va_vaflags, cred, p);
525 
526 	return error;
527 }
528 
529 int
530 tmpfs_read(void *v)
531 {
532 	struct vop_read_args /* {
533 		struct vnode *a_vp;
534 		struct uio *a_uio;
535 		int a_ioflag;
536 		struct ucred *a_cred;
537 	} */ *ap = v;
538 	struct vnode *vp = ap->a_vp;
539 	struct uio *uio = ap->a_uio;
540 	/* const int ioflag = ap->a_ioflag; */
541 	tmpfs_node_t *node;
542 	int error;
543 
544 	KASSERT(VOP_ISLOCKED(vp));
545 
546 	if (vp->v_type != VREG) {
547 		return EISDIR;
548 	}
549 	if (uio->uio_offset < 0) {
550 		return EINVAL;
551 	}
552 	if (uio->uio_resid == 0)
553 		return 0;
554 
555 	node = VP_TO_TMPFS_NODE(vp);
556 	error = 0;
557 
558 	while (error == 0 && uio->uio_resid > 0) {
559 		vsize_t len;
560 
561 		if (node->tn_size <= uio->uio_offset) {
562 			break;
563 		}
564 		len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);
565 		if (len == 0) {
566 			break;
567 		}
568 		error = tmpfs_uiomove(node, uio, len);
569 	}
570 
571 	if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
572 		tmpfs_update(node, TMPFS_NODE_ACCESSED);
573 
574 	return error;
575 }
576 
577 int
578 tmpfs_write(void *v)
579 {
580 	struct vop_write_args /* {
581 		struct vnode	*a_vp;
582 		struct uio	*a_uio;
583 		int		a_ioflag;
584 		kauth_cred_t	a_cred;
585 	} */ *ap = v;
586 	struct vnode *vp = ap->a_vp;
587 	struct uio *uio = ap->a_uio;
588 	const int ioflag = ap->a_ioflag;
589 	tmpfs_node_t *node;
590 	off_t oldsize;
591 	ssize_t overrun;
592 	int extended;
593 	int error;
594 
595 	KASSERT(VOP_ISLOCKED(vp));
596 
597 	node = VP_TO_TMPFS_NODE(vp);
598 	oldsize = node->tn_size;
599 
600 	if (vp->v_type != VREG)
601 		return (EINVAL);
602 
603 	if (uio->uio_resid == 0)
604 		return (0);
605 
606 	if (ioflag & IO_APPEND) {
607 		uio->uio_offset = node->tn_size;
608 	}
609 
610 	if (uio->uio_offset < 0 ||
611 	    (u_int64_t)uio->uio_offset + uio->uio_resid > LLONG_MAX)
612 		return (EFBIG);
613 
614 	/* do the filesize rlimit check */
615 	if ((error = vn_fsizechk(vp, uio, ioflag, &overrun)))
616 		return (error);
617 
618 	extended = uio->uio_offset + uio->uio_resid > node->tn_size;
619 	if (extended) {
620 		error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid);
621 		if (error)
622 			goto out;
623 	}
624 
625 	error = 0;
626 	while (error == 0 && uio->uio_resid > 0) {
627 		vsize_t len;
628 		uvm_vnp_uncache(vp);
629 		len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);
630 		if (len == 0) {
631 			break;
632 		}
633 		error = tmpfs_uiomove(node, uio, len);
634 	}
635 	if (error) {
636 		(void)tmpfs_reg_resize(vp, oldsize);
637 	}
638 
639 	tmpfs_update(node, TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED);
640 	if (extended)
641 		VN_KNOTE(vp, NOTE_WRITE | NOTE_EXTEND);
642 	else
643 		VN_KNOTE(vp, NOTE_WRITE);
644 out:
645 	if (error) {
646 		KASSERT(oldsize == node->tn_size);
647 	} else {
648 		KASSERT(uio->uio_resid == 0);
649 
650 		/* correct the result for writes clamped by vn_fsizechk() */
651 		uio->uio_resid += overrun;
652 
653 	}
654 	return error;
655 }
656 
657 int
658 tmpfs_fsync(void *v)
659 {
660 #ifdef DIAGNOSTIC
661 	struct vop_fsync_args /* {
662 		struct vnode *a_vp;
663 		struct ucred *a_cred;
664 		int a_flags;
665 		off_t a_offlo;
666 		off_t a_offhi;
667 		struct lwp *a_l;
668 	} */ *ap = v;
669 	struct vnode *vp = ap->a_vp;
670 
671 	/* Nothing to do.  Just update. */
672 	KASSERT(VOP_ISLOCKED(vp));
673 #endif
674 	return 0;
675 }
676 
677 /*
678  * tmpfs_remove: unlink a file.
679  *
680  * => Both directory (dvp) and file (vp) are locked.
681  * => We unlock and drop the reference on both.
682  */
683 int
684 tmpfs_remove(void *v)
685 {
686 	struct vop_remove_args /* {
687 		struct vnode *a_dvp;
688 		struct vnode *a_vp;
689 		struct componentname *a_cnp;
690 	} */ *ap = v;
691 	struct vnode *dvp = ap->a_dvp, *vp = ap->a_vp;
692 	struct componentname *cnp = ap->a_cnp;
693 	tmpfs_node_t *dnode, *node;
694 	tmpfs_dirent_t *de;
695 	int error;
696 
697 	KASSERT(VOP_ISLOCKED(dvp));
698 	KASSERT(VOP_ISLOCKED(vp));
699 	KASSERT(cnp->cn_flags & HASBUF);
700 
701 	if (vp->v_type == VDIR) {
702 		error = EPERM;
703 		goto out;
704 	}
705 
706 	dnode = VP_TO_TMPFS_NODE(dvp);
707 	node = VP_TO_TMPFS_NODE(vp);
708 
709 	/* Files marked as immutable or append-only cannot be deleted. */
710 	if (node->tn_flags & (IMMUTABLE | APPEND)) {
711 		error = EPERM;
712 		goto out;
713 	}
714 
715 	/*
716 	 * Likewise, files residing on directories marked as append-only cannot
717 	 * be deleted.
718 	 */
719 	if (dnode->tn_flags & APPEND) {
720 		error = EPERM;
721 		goto out;
722 	}
723 
724 	/* Lookup the directory entry (check the cached hint first). */
725 	de = tmpfs_dir_cached(node);
726 	if (de == NULL) {
727 		de = tmpfs_dir_lookup(dnode, cnp);
728 	}
729 
730 	KASSERT(de && de->td_node == node);
731 
732 	/*
733 	 * Remove the entry from the directory (drops the link count) and
734 	 * destroy it.
735 	 * Note: the inode referred by it will not be destroyed
736 	 * until the vnode is reclaimed/recycled.
737 	 */
738 	tmpfs_dir_detach(dnode, de);
739 	tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
740 	if (node->tn_links > 0)  {
741 		/* We removed a hard link. */
742 		tmpfs_update(node, TMPFS_NODE_CHANGED);
743 	}
744 	error = 0;
745 out:
746 	pool_put(&namei_pool, cnp->cn_pnbuf);
747 	/* Drop the references and unlock the vnodes. */
748 	vput(vp);
749 	if (dvp == vp) {
750 		vrele(dvp);
751 	} else {
752 		vput(dvp);
753 	}
754 	return error;
755 }
756 
757 /*
758  * tmpfs_link: create a hard link.
759  */
760 int
761 tmpfs_link(void *v)
762 {
763 	struct vop_link_args /* {
764 		struct vnode *a_dvp;
765 		struct vnode *a_vp;
766 		struct componentname *a_cnp;
767 	} */ *ap = v;
768 	struct vnode *dvp = ap->a_dvp;
769 	struct vnode *vp = ap->a_vp;
770 	struct componentname *cnp = ap->a_cnp;
771 	tmpfs_node_t *dnode, *node;
772 	tmpfs_dirent_t *de;
773 	int error;
774 
775 	KASSERT(VOP_ISLOCKED(dvp));
776 
777 	if (vp->v_type == VDIR) {
778 		VOP_ABORTOP(dvp, cnp);
779 		vput(dvp);
780 		return EPERM;
781 	}
782 
783 	KASSERT(dvp != vp);
784 
785 	if (dvp->v_mount != vp->v_mount) {
786 		VOP_ABORTOP(dvp, cnp);
787 		vput(dvp);
788 		return EXDEV;
789 	}
790 
791 	dnode = VP_TO_TMPFS_DIR(dvp);
792 	node = VP_TO_TMPFS_NODE(vp);
793 
794 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
795 
796 	/* Check for maximum number of links limit. */
797 	if (node->tn_links == LINK_MAX) {
798 		error = EMLINK;
799 		goto out;
800 	}
801 	KASSERT(node->tn_links < LINK_MAX);
802 
803 	/* We cannot create links of files marked immutable or append-only. */
804 	if (node->tn_flags & (IMMUTABLE | APPEND)) {
805 		error = EPERM;
806 		goto out;
807 	}
808 
809 	if (TMPFS_DIRSEQ_FULL(dnode)) {
810 		error = ENOSPC;
811 		goto out;
812 	}
813 
814 	/* Allocate a new directory entry to represent the inode. */
815 	error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount),
816 	    cnp->cn_nameptr, cnp->cn_namelen, &de);
817 	if (error) {
818 		goto out;
819 	}
820 
821 	/*
822 	 * Insert the entry into the directory.
823 	 * It will increase the inode link count.
824 	 */
825 	tmpfs_dir_attach(dnode, de, node);
826 
827 	/* Update the timestamps and trigger the event. */
828 	if (node->tn_vnode) {
829 		VN_KNOTE(node->tn_vnode, NOTE_LINK);
830 	}
831 	tmpfs_update(node, TMPFS_NODE_CHANGED);
832 	error = 0;
833 out:
834 	pool_put(&namei_pool, cnp->cn_pnbuf);
835 	VOP_UNLOCK(vp);
836 	vput(dvp);
837 	return error;
838 }
839 
840 int
841 tmpfs_mkdir(void *v)
842 {
843 	struct vop_mkdir_args /* {
844 		struct vnode		*a_dvp;
845 		struct vnode		**a_vpp;
846 		struct componentname	*a_cnp;
847 		struct vattr		*a_vap;
848 	} */ *ap = v;
849 	struct vnode *dvp = ap->a_dvp;
850 	struct vnode **vpp = ap->a_vpp;
851 	struct componentname *cnp = ap->a_cnp;
852 	struct vattr *vap = ap->a_vap;
853 	int error;
854 
855 	KASSERT(vap->va_type == VDIR);
856 	error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
857 	vput(dvp);
858 	return error;
859 }
860 
861 int
862 tmpfs_rmdir(void *v)
863 {
864 	struct vop_rmdir_args /* {
865 		struct vnode		*a_dvp;
866 		struct vnode		*a_vp;
867 		struct componentname	*a_cnp;
868 	} */ *ap = v;
869 	struct vnode *dvp = ap->a_dvp;
870 	struct vnode *vp = ap->a_vp;
871 	struct componentname *cnp = ap->a_cnp;
872 	tmpfs_mount_t *tmp = VFS_TO_TMPFS(dvp->v_mount);
873 	tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp);
874 	tmpfs_node_t *node = VP_TO_TMPFS_DIR(vp);
875 	tmpfs_dirent_t *de;
876 	int error = 0;
877 
878 	KASSERT(VOP_ISLOCKED(dvp));
879 	KASSERT(VOP_ISLOCKED(vp));
880 	KASSERT(cnp->cn_flags & HASBUF);
881 
882 	if (cnp->cn_namelen == 2 && cnp->cn_nameptr[0] == '.' &&
883 	    cnp->cn_nameptr[1] == '.') {
884 		error = ENOTEMPTY;
885 		goto out;
886 	}
887 
888 	KASSERT(node->tn_spec.tn_dir.tn_parent == dnode);
889 
890 	/*
891 	 * Directories with more than two entries ('.' and '..') cannot be
892 	 * removed.
893 	 */
894 	if (node->tn_size > 0) {
895 		KASSERT(error == 0);
896 		TAILQ_FOREACH(de, &node->tn_spec.tn_dir.tn_dir, td_entries) {
897 			error = ENOTEMPTY;
898 			break;
899 		}
900 		if (error)
901 			goto out;
902 	}
903 
904 	/* Lookup the directory entry (check the cached hint first). */
905 	de = tmpfs_dir_cached(node);
906 	if (de == NULL)
907 		de = tmpfs_dir_lookup(dnode, cnp);
908 
909 	KASSERT(de && de->td_node == node);
910 
911 	/* Check flags to see if we are allowed to remove the directory. */
912 	if (dnode->tn_flags & APPEND || node->tn_flags & (IMMUTABLE | APPEND)) {
913 		error = EPERM;
914 		goto out;
915 	}
916 
917 	/* Decrement the link count for the virtual '.' entry. */
918 	node->tn_links--;
919 	tmpfs_update(node, TMPFS_NODE_STATUSALL);
920 
921 	/* Detach the directory entry from the directory. */
922 	tmpfs_dir_detach(dnode, de);
923 
924 	/* Purge the cache for parent. */
925 	cache_purge(dvp);
926 
927 	/*
928 	 * Destroy the directory entry.
929 	 * Note: the inode referred by it will not be destroyed
930 	 * until the vnode is reclaimed.
931 	 */
932 	tmpfs_free_dirent(tmp, de);
933 	KASSERT(TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir) == NULL);
934 
935 	KASSERT(node->tn_links == 0);
936 out:
937 	pool_put(&namei_pool, cnp->cn_pnbuf);
938 	/* Release the nodes. */
939 	vput(dvp);
940 	vput(vp);
941 	return error;
942 }
943 
944 int
945 tmpfs_symlink(void *v)
946 {
947 	struct vop_symlink_args /* {
948 		struct vnode		*a_dvp;
949 		struct vnode		**a_vpp;
950 		struct componentname	*a_cnp;
951 		struct vattr		*a_vap;
952 		char			*a_target;
953 	} */ *ap = v;
954 	struct vnode *dvp = ap->a_dvp;
955 	struct vnode **vpp = ap->a_vpp;
956 	struct componentname *cnp = ap->a_cnp;
957 	struct vattr *vap = ap->a_vap;
958 	char *target = ap->a_target;
959 	int error;
960 
961 	KASSERT(vap->va_type == 0);
962 	vap->va_type = VLNK;
963 
964 	error = tmpfs_alloc_file(dvp, vpp, vap, cnp, target);
965 	vput(dvp);
966 	if (error == 0)
967 		vput(*vpp);
968 
969 	return error;
970 }
971 
972 int
973 tmpfs_readdir(void *v)
974 {
975 	struct vop_readdir_args /* {
976 		struct vnode	*a_vp;
977 		struct uio	*a_uio;
978 		kauth_cred_t	a_cred;
979 		int		*a_eofflag;
980 	} */ *ap = v;
981 	struct vnode *vp = ap->a_vp;
982 	struct uio *uio = ap->a_uio;
983 	int *eofflag = ap->a_eofflag;
984 	tmpfs_node_t *node;
985 	int error;
986 
987 	KASSERT(VOP_ISLOCKED(vp));
988 
989 	/* This operation only makes sense on directory nodes. */
990 	if (vp->v_type != VDIR) {
991 		return ENOTDIR;
992 	}
993 	node = VP_TO_TMPFS_DIR(vp);
994 	/*
995 	 * Retrieve the directory entries, unless it is being destroyed.
996 	 */
997 	if (node->tn_links) {
998 		error = tmpfs_dir_getdents(node, uio);
999 	} else {
1000 		error = 0;
1001 	}
1002 
1003 	if (eofflag != NULL) {
1004 		*eofflag = !error && uio->uio_offset == TMPFS_DIRSEQ_EOF;
1005 	}
1006 	return error;
1007 }
1008 
1009 int
1010 tmpfs_readlink(void *v)
1011 {
1012 	struct vop_readlink_args /* {
1013 		struct vnode	*a_vp;
1014 		struct uio	*a_uio;
1015 		kauth_cred_t	a_cred;
1016 	} */ *ap = v;
1017 	struct vnode *vp = ap->a_vp;
1018 	struct uio *uio = ap->a_uio;
1019 	tmpfs_node_t *node;
1020 	int error;
1021 
1022 	KASSERT(VOP_ISLOCKED(vp));
1023 	KASSERT(uio->uio_offset == 0);
1024 	KASSERT(vp->v_type == VLNK);
1025 
1026 	node = VP_TO_TMPFS_NODE(vp);
1027 	error = uiomove(node->tn_spec.tn_lnk.tn_link,
1028 	    MIN((size_t)node->tn_size, uio->uio_resid), uio);
1029 
1030 	if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
1031 		tmpfs_update(node, TMPFS_NODE_ACCESSED);
1032 
1033 	return error;
1034 }
1035 
1036 int
1037 tmpfs_inactive(void *v)
1038 {
1039 	struct vop_inactive_args /* {
1040 		struct vnode *a_vp;
1041 		int *a_recycle;
1042 	} */ *ap = v;
1043 	struct vnode *vp = ap->a_vp;
1044 	tmpfs_node_t *node;
1045 
1046 	KASSERT(VOP_ISLOCKED(vp));
1047 
1048 	node = VP_TO_TMPFS_NODE(vp);
1049 
1050 	if (vp->v_type == VREG && tmpfs_uio_cached(node))
1051 		tmpfs_uio_uncache(node);
1052 
1053 	VOP_UNLOCK(vp);
1054 
1055 	/*
1056 	 * If we are done with the node, reclaim it so that it can be reused
1057 	 * immediately.
1058 	 */
1059 	if (node->tn_links == 0)
1060 		vrecycle(vp, curproc);
1061 
1062 	return 0;
1063 }
1064 
1065 int
1066 tmpfs_reclaim(void *v)
1067 {
1068 	struct vop_reclaim_args /* {
1069 		struct vnode *a_vp;
1070 	} */ *ap = v;
1071 	struct vnode *vp = ap->a_vp;
1072 	tmpfs_mount_t *tmp = VFS_TO_TMPFS(vp->v_mount);
1073 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1074 	int racing;
1075 
1076 	/* Disassociate inode from vnode. */
1077 	rw_enter_write(&node->tn_nlock);
1078 	node->tn_vnode = NULL;
1079 	vp->v_data = NULL;
1080 	/* Check if tmpfs_vnode_get() is racing with us. */
1081 	racing = TMPFS_NODE_RECLAIMING(node);
1082 	rw_exit_write(&node->tn_nlock);
1083 
1084 	cache_purge(vp);
1085 
1086 	/*
1087 	 * If inode is not referenced, i.e. no links, then destroy it.
1088 	 * Note: if racing - inode is about to get a new vnode, leave it.
1089 	 */
1090 	if (node->tn_links == 0 && !racing) {
1091 		tmpfs_free_node(tmp, node);
1092 	}
1093 	return 0;
1094 }
1095 
1096 int
1097 tmpfs_pathconf(void *v)
1098 {
1099 	struct vop_pathconf_args /* {
1100 		struct vnode	*a_vp;
1101 		int		a_name;
1102 		register_t	*a_retval;
1103 	} */ *ap = v;
1104 	const int name = ap->a_name;
1105 	register_t *retval = ap->a_retval;
1106 	int error = 0;
1107 
1108 	switch (name) {
1109 	case _PC_LINK_MAX:
1110 		*retval = LINK_MAX;
1111 		break;
1112 	case _PC_NAME_MAX:
1113 		*retval = TMPFS_MAXNAMLEN;
1114 		break;
1115 	case _PC_CHOWN_RESTRICTED:
1116 		*retval = 1;
1117 		break;
1118 	case _PC_NO_TRUNC:
1119 		*retval = 1;
1120 		break;
1121 	case _PC_FILESIZEBITS:
1122 		*retval = 64;
1123 		break;
1124 	case _PC_TIMESTAMP_RESOLUTION:
1125 		*retval = 1;
1126 		break;
1127 	default:
1128 		error = EINVAL;
1129 	}
1130 	return error;
1131 }
1132 
1133 int
1134 tmpfs_advlock(void *v)
1135 {
1136 	struct vop_advlock_args /* {
1137 		struct vnode	*a_vp;
1138 		void *		a_id;
1139 		int		a_op;
1140 		struct flock	*a_fl;
1141 		int		a_flags;
1142 	} */ *ap = v;
1143 	struct vnode *vp = ap->a_vp;
1144 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1145 
1146 	return lf_advlock(&node->tn_lockf, node->tn_size, ap->a_id, ap->a_op,
1147 	    ap->a_fl, ap->a_flags);
1148 }
1149 
1150 int
1151 tmpfs_print(void *v)
1152 {
1153 	struct vop_print_args /* {
1154 		struct vnode	*a_vp;
1155 	} */ *ap = v;
1156 	struct vnode *vp = ap->a_vp;
1157 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
1158 
1159 	printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n"
1160 	    "\tmode 0%o, owner %d, group %d, size %lld",
1161 	    node, node->tn_flags, node->tn_links, node->tn_mode, node->tn_uid,
1162 	    node->tn_gid, node->tn_size);
1163 #ifdef FIFO
1164 	if (vp->v_type == VFIFO)
1165 		fifo_printinfo(vp);
1166 #endif
1167 	printf("\n");
1168 	return 0;
1169 }
1170 
1171 /* a null op */
1172 int
1173 tmpfs_bwrite(void *v)
1174 {
1175 	return 0;
1176 }
1177 
1178 int
1179 tmpfs_poll(void *v)
1180 {
1181 	struct vop_poll_args *ap = v;
1182 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1183 }
1184 
1185 int
1186 tmpfs_strategy(void *v)
1187 {
1188 	return EOPNOTSUPP;
1189 }
1190 
1191 int
1192 tmpfs_ioctl(void *v)
1193 {
1194 	return ENOTTY;
1195 }
1196 
1197 int
1198 tmpfs_lock(void *v)
1199 {
1200 	struct vop_lock_args *ap = v;
1201 	tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1202 
1203 	return rrw_enter(&tnp->tn_vlock, ap->a_flags & LK_RWFLAGS);
1204 }
1205 
1206 int
1207 tmpfs_unlock(void *v)
1208 {
1209 	struct vop_unlock_args *ap = v;
1210 	tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1211 
1212 	rrw_exit(&tnp->tn_vlock);
1213 	return 0;
1214 }
1215 
1216 int
1217 tmpfs_islocked(void *v)
1218 {
1219 	struct vop_islocked_args *ap = v;
1220 	tmpfs_node_t *tnp = VP_TO_TMPFS_NODE(ap->a_vp);
1221 
1222 	return rrw_status(&tnp->tn_vlock);
1223 }
1224 
1225 /*
1226  * tmpfs_rename: rename routine, the hairiest system call, with the
1227  * insane API.
1228  *
1229  * Arguments: fdvp (from-parent vnode), fvp (from-leaf), tdvp (to-parent)
1230  * and tvp (to-leaf), if exists (NULL if not).
1231  *
1232  * => Caller holds a reference on fdvp and fvp, they are unlocked.
1233  *    Note: fdvp and fvp can refer to the same object (i.e. when it is root).
1234  *
1235  * => Both tdvp and tvp are referenced and locked.  It is our responsibility
1236  *    to release the references and unlock them (or destroy).
1237  */
1238 
1239 /*
1240  * First, some forward declarations of subroutines.
1241  */
1242 
1243 int tmpfs_sane_rename(struct vnode *, struct componentname *,
1244     struct vnode *, struct componentname *, struct ucred *, int);
1245 int tmpfs_rename_enter(struct mount *, struct tmpfs_mount *,
1246     struct ucred *,
1247     struct vnode *, struct tmpfs_node *, struct componentname *,
1248     struct tmpfs_dirent **, struct vnode **,
1249     struct vnode *, struct tmpfs_node *, struct componentname *,
1250     struct tmpfs_dirent **, struct vnode **);
1251 int tmpfs_rename_enter_common(struct mount *, struct tmpfs_mount *,
1252     struct ucred *,
1253     struct vnode *, struct tmpfs_node *,
1254     struct componentname *, struct tmpfs_dirent **, struct vnode **,
1255     struct componentname *, struct tmpfs_dirent **, struct vnode **);
1256 int tmpfs_rename_enter_separate(struct mount *, struct tmpfs_mount *,
1257     struct ucred *,
1258     struct vnode *, struct tmpfs_node *, struct componentname *,
1259     struct tmpfs_dirent **, struct vnode **,
1260     struct vnode *, struct tmpfs_node *, struct componentname *,
1261     struct tmpfs_dirent **, struct vnode **);
1262 void tmpfs_rename_exit(struct tmpfs_mount *,
1263     struct vnode *, struct vnode *, struct vnode *, struct vnode *);
1264 int tmpfs_rename_lock_directory(struct vnode *, struct tmpfs_node *);
1265 int tmpfs_rename_genealogy(struct tmpfs_node *, struct tmpfs_node *,
1266     struct tmpfs_node **);
1267 int tmpfs_rename_lock(struct mount *, struct ucred *, int,
1268     struct vnode *, struct tmpfs_node *, struct componentname *, int,
1269     struct tmpfs_dirent **, struct vnode **,
1270     struct vnode *, struct tmpfs_node *, struct componentname *, int,
1271     struct tmpfs_dirent **, struct vnode **);
1272 void tmpfs_rename_attachdetach(struct tmpfs_mount *,
1273     struct vnode *, struct tmpfs_dirent *, struct vnode *,
1274     struct vnode *, struct tmpfs_dirent *, struct vnode *);
1275 int tmpfs_do_remove(struct tmpfs_mount *, struct vnode *,
1276     struct tmpfs_node *, struct tmpfs_dirent *, struct vnode *, struct ucred *);
1277 int tmpfs_rename_check_possible(struct tmpfs_node *,
1278     struct tmpfs_node *, struct tmpfs_node *, struct tmpfs_node *);
1279 int tmpfs_rename_check_permitted(struct ucred *,
1280     struct tmpfs_node *, struct tmpfs_node *,
1281     struct tmpfs_node *, struct tmpfs_node *);
1282 int tmpfs_remove_check_possible(struct tmpfs_node *,
1283     struct tmpfs_node *);
1284 int tmpfs_remove_check_permitted(struct ucred *,
1285     struct tmpfs_node *, struct tmpfs_node *);
1286 int tmpfs_check_sticky(struct ucred *,
1287     struct tmpfs_node *, struct tmpfs_node *);
1288 void tmpfs_rename_cache_purge(struct vnode *, struct vnode *, struct vnode *,
1289     struct vnode *);
1290 void tmpfs_rename_abort(void *);
1291 
1292 int
1293 tmpfs_rename(void *v)
1294 {
1295 	struct vop_rename_args  /* {
1296 		struct vnode		*a_fdvp;
1297 		struct vnode		*a_fvp;
1298 		struct componentname	*a_fcnp;
1299 		struct vnode		*a_tdvp;
1300 		struct vnode		*a_tvp;
1301 		struct componentname	*a_tcnp;
1302 	} */ *ap = v;
1303 	struct vnode *fdvp = ap->a_fdvp;
1304 	struct vnode *fvp = ap->a_fvp;
1305 	struct componentname *fcnp = ap->a_fcnp;
1306 	struct vnode *tdvp = ap->a_tdvp;
1307 	struct vnode *tvp = ap->a_tvp;
1308 	struct componentname *tcnp = ap->a_tcnp;
1309 	struct ucred *cred;
1310 	int error;
1311 
1312 	KASSERT(fdvp != NULL);
1313 	KASSERT(fvp != NULL);
1314 	KASSERT(fcnp != NULL);
1315 	KASSERT(fcnp->cn_nameptr != NULL);
1316 	KASSERT(tdvp != NULL);
1317 	KASSERT(tcnp != NULL);
1318 	KASSERT(fcnp->cn_nameptr != NULL);
1319 	/* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1320 	/* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
1321 	KASSERT(fdvp->v_type == VDIR);
1322 	KASSERT(tdvp->v_type == VDIR);
1323 	KASSERT(fcnp->cn_flags & HASBUF);
1324 	KASSERT(tcnp->cn_flags & HASBUF);
1325 
1326 	cred = fcnp->cn_cred;
1327 	KASSERT(tcnp->cn_cred == cred);
1328 
1329 	/*
1330 	 * Check for cross-device rename.
1331 	 * Also don't allow renames of mount points.
1332 	 */
1333 	if (fvp->v_mount != tdvp->v_mount ||
1334 	    fdvp->v_mount != fvp->v_mount ||
1335 	    (tvp != NULL && (fvp->v_mount != tvp->v_mount))) {
1336 	    	tmpfs_rename_abort(v);
1337 		return EXDEV;
1338 	}
1339 
1340 	/*
1341 	 * Can't check the locks on these until we know they're on
1342 	 * the same FS, as not all FS do locking the same way.
1343 	 */
1344 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1345 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1346 
1347 	/*
1348 	 * Reject renaming '.' and '..'.
1349 	 */
1350 	if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1351 	    (fcnp->cn_namelen == 2 && fcnp->cn_nameptr[0] == '.' &&
1352 	    fcnp->cn_nameptr[1] == '.')) {
1353 		tmpfs_rename_abort(v);
1354 		return EINVAL;
1355 	}
1356 
1357 	/*
1358 	 * Sanitize our world from the VFS insanity.  Unlock the target
1359 	 * directory and node, which are locked.  Release the children,
1360 	 * which are referenced.  Check for rename("x", "y/."), which
1361 	 * it is our responsibility to reject, not the caller's.  (But
1362 	 * the caller does reject rename("x/.", "y").  Go figure.)
1363 	 */
1364 
1365 	VOP_UNLOCK(tdvp);
1366 	if ((tvp != NULL) && (tvp != tdvp))
1367 		VOP_UNLOCK(tvp);
1368 
1369 	vrele(fvp);
1370 	if (tvp != NULL)
1371 		vrele(tvp);
1372 
1373 	if (tvp == tdvp) {
1374 		error = EINVAL;
1375 		goto out;
1376 	}
1377 
1378 	error = tmpfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, 0);
1379 
1380 out:	/*
1381 	 * All done, whether with success or failure.  Release the
1382 	 * directory nodes now, as the caller expects from the VFS
1383 	 * protocol.
1384 	 */
1385 	vrele(fdvp);
1386 	vrele(tdvp);
1387 
1388 	return error;
1389 }
1390 
1391 /*
1392  * tmpfs_sane_rename: rename routine, the hairiest system call, with
1393  * the sane API.
1394  *
1395  * Arguments:
1396  *
1397  * . fdvp (from directory vnode),
1398  * . fcnp (from component name),
1399  * . tdvp (to directory vnode), and
1400  * . tcnp (to component name).
1401  *
1402  * fdvp and tdvp must be referenced and unlocked.
1403  */
1404 int
1405 tmpfs_sane_rename(struct vnode *fdvp, struct componentname *fcnp,
1406     struct vnode *tdvp, struct componentname *tcnp, struct ucred *cred,
1407     int posixly_correct)
1408 {
1409 	struct mount *mount;
1410 	struct tmpfs_mount *tmpfs;
1411 	struct tmpfs_node *fdnode, *tdnode;
1412 	struct tmpfs_dirent *fde, *tde;
1413 	struct vnode *fvp, *tvp;
1414 	char *newname;
1415 	int error;
1416 
1417 	KASSERT(fdvp != NULL);
1418 	KASSERT(fcnp != NULL);
1419 	KASSERT(tdvp != NULL);
1420 	KASSERT(tcnp != NULL);
1421 	/* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1422 	/* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
1423 	KASSERT(fdvp->v_type == VDIR);
1424 	KASSERT(tdvp->v_type == VDIR);
1425 	KASSERT(fdvp->v_mount == tdvp->v_mount);
1426 	KASSERT((fcnp->cn_flags & ISDOTDOT) == 0);
1427 	KASSERT((tcnp->cn_flags & ISDOTDOT) == 0);
1428 	KASSERT((fcnp->cn_namelen != 1) || (fcnp->cn_nameptr[0] != '.'));
1429 	KASSERT((tcnp->cn_namelen != 1) || (tcnp->cn_nameptr[0] != '.'));
1430 	KASSERT((fcnp->cn_namelen != 2) || (fcnp->cn_nameptr[0] != '.') ||
1431 	    (fcnp->cn_nameptr[1] != '.'));
1432 	KASSERT((tcnp->cn_namelen != 2) || (tcnp->cn_nameptr[0] != '.') ||
1433 	    (tcnp->cn_nameptr[1] != '.'));
1434 
1435 	/*
1436 	 * Pull out the tmpfs data structures.
1437 	 */
1438 	fdnode = VP_TO_TMPFS_NODE(fdvp);
1439 	tdnode = VP_TO_TMPFS_NODE(tdvp);
1440 	KASSERT(fdnode != NULL);
1441 	KASSERT(tdnode != NULL);
1442 	KASSERT(fdnode->tn_vnode == fdvp);
1443 	KASSERT(tdnode->tn_vnode == tdvp);
1444 	KASSERT(fdnode->tn_type == VDIR);
1445 	KASSERT(tdnode->tn_type == VDIR);
1446 
1447 	mount = fdvp->v_mount;
1448 	KASSERT(mount != NULL);
1449 	KASSERT(mount == tdvp->v_mount);
1450 	/* XXX How can we be sure this stays true?  (Not that you're
1451 	 * likely to mount a tmpfs read-only...)  */
1452 	KASSERT((mount->mnt_flag & MNT_RDONLY) == 0);
1453 	tmpfs = VFS_TO_TMPFS(mount);
1454 	KASSERT(tmpfs != NULL);
1455 
1456 	/*
1457 	 * Decide whether we need a new name, and allocate memory for
1458 	 * it if so.  Do this before locking anything or taking
1459 	 * destructive actions so that we can back out safely and sleep
1460 	 * safely.  XXX Is sleeping an issue here?  Can this just be
1461 	 * moved into tmpfs_rename_attachdetach?
1462 	 */
1463 	if (tmpfs_strname_neqlen(fcnp, tcnp)) {
1464 		newname = tmpfs_strname_alloc(tmpfs, tcnp->cn_namelen);
1465 		if (newname == NULL) {
1466 			error = ENOSPC;
1467 			goto out_unlocked;
1468 		}
1469 	} else {
1470 		newname = NULL;
1471 	}
1472 
1473 	/*
1474 	 * Lock and look up everything.  GCC is not very clever.
1475 	 */
1476 	fde = tde = NULL;
1477 	fvp = tvp = NULL;
1478 	error = tmpfs_rename_enter(mount, tmpfs, cred,
1479 	    fdvp, fdnode, fcnp, &fde, &fvp,
1480 	    tdvp, tdnode, tcnp, &tde, &tvp);
1481 	if (error)
1482 		goto out_unlocked;
1483 
1484 	/*
1485 	 * Check that everything is locked and looks right.
1486 	 */
1487 	KASSERT(fde != NULL);
1488 	KASSERT(fvp != NULL);
1489 	KASSERT(fde->td_node != NULL);
1490 	KASSERT(fde->td_node->tn_vnode == fvp);
1491 	KASSERT(fde->td_node->tn_type == fvp->v_type);
1492 	KASSERT((tde == NULL) == (tvp == NULL));
1493 	KASSERT((tde == NULL) || (tde->td_node != NULL));
1494 	KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp));
1495 	KASSERT((tde == NULL) || (tde->td_node->tn_type == tvp->v_type));
1496 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1497 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1498 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1499 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1500 
1501 	/*
1502 	 * If the source and destination are the same object, we need
1503 	 * only at most delete the source entry.
1504 	 */
1505 	if (fvp == tvp) {
1506 		KASSERT(tvp != NULL);
1507 		if (fde->td_node->tn_type == VDIR) {
1508 			/* XXX How can this possibly happen?  */
1509 			error = EINVAL;
1510 			goto out_locked;
1511 		}
1512 		if (!posixly_correct && (fde != tde)) {
1513 			/* XXX Doesn't work because of locking.
1514 			 * error = VOP_REMOVE(fdvp, fvp);
1515 			 */
1516 			error = tmpfs_do_remove(tmpfs, fdvp, fdnode, fde, fvp,
1517 			    cred);
1518 			if (error)
1519 				goto out_locked;
1520 		}
1521 		goto success;
1522 	}
1523 	KASSERT(fde != tde);
1524 	KASSERT(fvp != tvp);
1525 
1526 	/*
1527 	 * If the target exists, refuse to rename a directory over a
1528 	 * non-directory or vice versa, or to clobber a non-empty
1529 	 * directory.
1530 	 */
1531 	if (tvp != NULL) {
1532 		KASSERT(tde != NULL);
1533 		KASSERT(tde->td_node != NULL);
1534 		if (fvp->v_type == VDIR && tvp->v_type == VDIR)
1535 			error = ((tde->td_node->tn_size > 0)? ENOTEMPTY : 0);
1536 		else if (fvp->v_type == VDIR && tvp->v_type != VDIR)
1537 			error = ENOTDIR;
1538 		else if (fvp->v_type != VDIR && tvp->v_type == VDIR)
1539 			error = EISDIR;
1540 		else
1541 			error = 0;
1542 		if (error)
1543 			goto out_locked;
1544 		KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
1545 	}
1546 
1547 	/*
1548 	 * Authorize the rename.
1549 	 */
1550 	error = tmpfs_rename_check_possible(fdnode, fde->td_node,
1551 	    tdnode, (tde? tde->td_node : NULL));
1552 	if (error)
1553 		goto out_locked;
1554 	error = tmpfs_rename_check_permitted(cred, fdnode, fde->td_node,
1555 	    tdnode, (tde? tde->td_node : NULL));
1556 	if (error)
1557 		goto out_locked;
1558 
1559 	/*
1560 	 * Everything is hunky-dory.  Shuffle the directory entries.
1561 	 */
1562 	tmpfs_rename_attachdetach(tmpfs, fdvp, fde, fvp, tdvp, tde, tvp);
1563 
1564 	/*
1565 	 * Update the directory entry's name necessary, and flag
1566 	 * metadata updates.  A memory allocation failure here is not
1567 	 * OK because we've already committed some changes that we
1568 	 * can't back out at this point, and we have things locked so
1569 	 * we can't sleep, hence the early allocation above.
1570 	 */
1571 	if (newname != NULL) {
1572 		KASSERT(tcnp->cn_namelen <= TMPFS_MAXNAMLEN);
1573 
1574 		tmpfs_strname_free(tmpfs, fde->td_name, fde->td_namelen);
1575 		fde->td_namelen = (uint16_t)tcnp->cn_namelen;
1576 		(void)memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen);
1577 		/* Commit newname and don't free it on the way out.  */
1578 		fde->td_name = newname;
1579 		newname = NULL;
1580 
1581 		tmpfs_update(fde->td_node, TMPFS_NODE_CHANGED);
1582 		tmpfs_update(tdnode, TMPFS_NODE_MODIFIED);
1583 	}
1584 
1585 success:
1586 	VN_KNOTE(fvp, NOTE_RENAME);
1587 	tmpfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
1588 	error = 0;
1589 
1590 out_locked:
1591 	tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp);
1592 
1593 out_unlocked:
1594 	/* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
1595 	/* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
1596 	/* KASSERT((fvp == NULL) || (VOP_ISLOCKED(fvp) != LK_EXCLUSIVE)); */
1597 	/* KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */
1598 
1599 	if (newname != NULL)
1600 		tmpfs_strname_free(tmpfs, newname, tcnp->cn_namelen);
1601 
1602 	return error;
1603 }
1604 
1605 /*
1606  * Look up fcnp in fdnode/fdvp and store its directory entry in fde_ret
1607  * and the associated vnode in fvp_ret; fail if not found.  Look up
1608  * tcnp in tdnode/tdvp and store its directory entry in tde_ret and the
1609  * associated vnode in tvp_ret; store null instead if not found.  Fail
1610  * if anything has been mounted on any of the nodes involved.
1611  *
1612  * fdvp and tdvp must be referenced.
1613  *
1614  * On entry, nothing is locked.
1615  *
1616  * On success, everything is locked, and *fvp_ret, and *tvp_ret if
1617  * nonnull, are referenced.  The only pairs of vnodes that may be
1618  * identical are {fdvp, tdvp} and {fvp, tvp}.
1619  *
1620  * On failure, everything remains as was.
1621  *
1622  * Locking everything including the source and target nodes is
1623  * necessary to make sure that, e.g., link count updates are OK.  The
1624  * locking order is, in general, ancestor-first, matching the order you
1625  * need to use to look up a descendant anyway.
1626  */
1627 int
1628 tmpfs_rename_enter(struct mount *mount, struct tmpfs_mount *tmpfs,
1629     struct ucred *cred,
1630     struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp,
1631     struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1632     struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp,
1633     struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1634 {
1635 	int error;
1636 
1637 	KASSERT(mount != NULL);
1638 	KASSERT(tmpfs != NULL);
1639 	KASSERT(fdvp != NULL);
1640 	KASSERT(fdnode != NULL);
1641 	KASSERT(fcnp != NULL);
1642 	KASSERT(fde_ret != NULL);
1643 	KASSERT(fvp_ret != NULL);
1644 	KASSERT(tdvp != NULL);
1645 	KASSERT(tdnode != NULL);
1646 	KASSERT(tcnp != NULL);
1647 	KASSERT(tde_ret != NULL);
1648 	KASSERT(tvp_ret != NULL);
1649 	KASSERT(fdnode->tn_vnode == fdvp);
1650 	KASSERT(tdnode->tn_vnode == tdvp);
1651 	KASSERT(fdnode->tn_type == VDIR);
1652 	KASSERT(tdnode->tn_type == VDIR);
1653 
1654 	if (fdvp == tdvp) {
1655 		KASSERT(fdnode == tdnode);
1656 		error = tmpfs_rename_enter_common(mount, tmpfs, cred, fdvp,
1657 		    fdnode, fcnp, fde_ret, fvp_ret, tcnp, tde_ret, tvp_ret);
1658 	} else {
1659 		KASSERT(fdnode != tdnode);
1660 		error = tmpfs_rename_enter_separate(mount, tmpfs, cred,
1661 		    fdvp, fdnode, fcnp, fde_ret, fvp_ret,
1662 		    tdvp, tdnode, tcnp, tde_ret, tvp_ret);
1663 	}
1664 
1665 	if (error)
1666 		return error;
1667 
1668 	KASSERT(*fde_ret != NULL);
1669 	KASSERT(*fvp_ret != NULL);
1670 	KASSERT((*tde_ret == NULL) == (*tvp_ret == NULL));
1671 	KASSERT((*tde_ret == NULL) || ((*tde_ret)->td_node != NULL));
1672 	KASSERT((*tde_ret == NULL) ||
1673 	    ((*tde_ret)->td_node->tn_vnode == *tvp_ret));
1674 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1675 	KASSERT(VOP_ISLOCKED(*fvp_ret) == LK_EXCLUSIVE);
1676 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1677 	KASSERT((*tvp_ret == NULL) ||
1678 	    (VOP_ISLOCKED(*tvp_ret) == LK_EXCLUSIVE));
1679 	KASSERT(*fvp_ret != fdvp);
1680 	KASSERT(*fvp_ret != tdvp);
1681 	KASSERT(*tvp_ret != fdvp);
1682 	KASSERT(*tvp_ret != tdvp);
1683 	return 0;
1684 }
1685 
1686 /*
1687  * Lock and look up with a common source/target directory.
1688  */
1689 int
1690 tmpfs_rename_enter_common(struct mount *mount, struct tmpfs_mount *tmpfs,
1691     struct ucred *cred,
1692     struct vnode *dvp, struct tmpfs_node *dnode,
1693     struct componentname *fcnp,
1694     struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1695     struct componentname *tcnp,
1696     struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1697 {
1698 	struct tmpfs_dirent *fde, *tde;
1699 	struct vnode *fvp, *tvp;
1700 	int error;
1701 
1702 	error = tmpfs_rename_lock_directory(dvp, dnode);
1703 	if (error)
1704 		goto fail0;
1705 
1706 	/* Did we lose a race with mount?  */
1707 	if (dvp->v_mountedhere != NULL) {
1708 		error = EBUSY;
1709 		goto fail1;
1710 	}
1711 
1712 	/* Make sure the caller may read the directory.  */
1713 	error = VOP_ACCESS(dvp, VEXEC, cred, curproc);
1714 	if (error)
1715 		goto fail1;
1716 
1717 	/*
1718 	 * The order in which we lock the source and target nodes is
1719 	 * irrelevant because there can only be one rename on this
1720 	 * directory in flight at a time, and we have it locked.
1721 	 */
1722 
1723 	fde = tmpfs_dir_lookup(dnode, fcnp);
1724 	if (fde == NULL) {
1725 		error = ENOENT;
1726 		goto fail1;
1727 	}
1728 
1729 	KASSERT(fde->td_node != NULL);
1730 	/* We ruled out `.' earlier.  */
1731 	KASSERT(fde->td_node != dnode);
1732 	/* We ruled out `..' earlier.  */
1733 	KASSERT(fde->td_node != dnode->tn_spec.tn_dir.tn_parent);
1734 	rw_enter_write(&fde->td_node->tn_nlock);
1735 	error = tmpfs_vnode_get(mount, fde->td_node, &fvp);
1736 	if (error)
1737 		goto fail1;
1738 	KASSERT(fvp != NULL);
1739 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1740 	KASSERT(fvp != dvp);
1741 	KASSERT(fvp->v_mount == mount);
1742 
1743 	/* Refuse to rename a mount point.  */
1744 	if ((fvp->v_type == VDIR) && (fvp->v_mountedhere != NULL)) {
1745 		error = EBUSY;
1746 		goto fail2;
1747 	}
1748 
1749 	tde = tmpfs_dir_lookup(dnode, tcnp);
1750 	if (tde == NULL) {
1751 		tvp = NULL;
1752 	} else {
1753 		KASSERT(tde->td_node != NULL);
1754 		/* We ruled out `.' earlier.  */
1755 		KASSERT(tde->td_node != dnode);
1756 		/* We ruled out `..' earlier.  */
1757 		KASSERT(tde->td_node != dnode->tn_spec.tn_dir.tn_parent);
1758 		if (tde->td_node != fde->td_node) {
1759 			rw_enter_write(&tde->td_node->tn_nlock);
1760 			error = tmpfs_vnode_get(mount, tde->td_node, &tvp);
1761 			if (error)
1762 				goto fail2;
1763 			KASSERT(tvp->v_mount == mount);
1764 			/* Refuse to rename over a mount point.  */
1765 			if ((tvp->v_type == VDIR) &&
1766 			    (tvp->v_mountedhere != NULL)) {
1767 				error = EBUSY;
1768 				goto fail3;
1769 			}
1770 		} else {
1771 			tvp = fvp;
1772 			vref(tvp);
1773 		}
1774 		KASSERT(tvp != NULL);
1775 		KASSERT(VOP_ISLOCKED(tvp) == LK_EXCLUSIVE);
1776 	}
1777 	KASSERT(tvp != dvp);
1778 
1779 	*fde_ret = fde;
1780 	*fvp_ret = fvp;
1781 	*tde_ret = tde;
1782 	*tvp_ret = tvp;
1783 	return 0;
1784 
1785 fail3:	if (tvp != NULL) {
1786 		if (tvp != fvp)
1787 			vput(tvp);
1788 		else
1789 			vrele(tvp);
1790 	}
1791 
1792 fail2:	vput(fvp);
1793 fail1:	VOP_UNLOCK(dvp);
1794 fail0:	return error;
1795 }
1796 
1797 /*
1798  * Lock and look up with separate source and target directories.
1799  */
1800 int
1801 tmpfs_rename_enter_separate(struct mount *mount, struct tmpfs_mount *tmpfs,
1802     struct ucred *cred,
1803     struct vnode *fdvp, struct tmpfs_node *fdnode, struct componentname *fcnp,
1804     struct tmpfs_dirent **fde_ret, struct vnode **fvp_ret,
1805     struct vnode *tdvp, struct tmpfs_node *tdnode, struct componentname *tcnp,
1806     struct tmpfs_dirent **tde_ret, struct vnode **tvp_ret)
1807 {
1808 	struct tmpfs_node *intermediate_node;
1809 	struct tmpfs_dirent *fde, *tde;
1810 	struct vnode *fvp, *tvp;
1811 	int error;
1812 
1813 	KASSERT(fdvp != tdvp);
1814 	KASSERT(fdnode != tdnode);
1815 
1816 #if 0				/* XXX */
1817 	mutex_enter(&tmpfs->tm_rename_lock);
1818 #endif
1819 
1820 	error = tmpfs_rename_genealogy(fdnode, tdnode, &intermediate_node);
1821 	if (error)
1822 		goto fail;
1823 
1824 	/*
1825 	 * intermediate_node == NULL means fdnode is not an ancestor of
1826 	 * tdnode.
1827 	 */
1828 	if (intermediate_node == NULL)
1829 		error = tmpfs_rename_lock(mount, cred, ENOTEMPTY,
1830 		    tdvp, tdnode, tcnp, 1, &tde, &tvp,
1831 		    fdvp, fdnode, fcnp, 0, &fde, &fvp);
1832 	else
1833 		error = tmpfs_rename_lock(mount, cred, EINVAL,
1834 		    fdvp, fdnode, fcnp, 0, &fde, &fvp,
1835 		    tdvp, tdnode, tcnp, 1, &tde, &tvp);
1836 	if (error)
1837 		goto fail;
1838 
1839 	KASSERT(fde != NULL);
1840 	KASSERT(fde->td_node != NULL);
1841 
1842 	/*
1843 	 * Reject rename("foo/bar", "foo/bar/baz/quux/zot").
1844 	 */
1845 	if (fde->td_node == intermediate_node) {
1846 		tmpfs_rename_exit(tmpfs, fdvp, fvp, tdvp, tvp);
1847 		return EINVAL;
1848 	}
1849 
1850 	*fde_ret = fde;
1851 	*fvp_ret = fvp;
1852 	*tde_ret = tde;
1853 	*tvp_ret = tvp;
1854 	return 0;
1855 
1856 fail:
1857 #if 0				/* XXX */
1858 	mutex_exit(&tmpfs->tm_rename_lock);
1859 #endif
1860 	return error;
1861 }
1862 
1863 /*
1864  * Unlock everything we locked for rename.
1865  *
1866  * fdvp and tdvp must be referenced.
1867  *
1868  * On entry, everything is locked, and fvp and tvp referenced.
1869  *
1870  * On exit, everything is unlocked, and fvp and tvp are released.
1871  */
1872 void
1873 tmpfs_rename_exit(struct tmpfs_mount *tmpfs,
1874     struct vnode *fdvp, struct vnode *fvp,
1875     struct vnode *tdvp, struct vnode *tvp)
1876 {
1877 
1878 	KASSERT(tmpfs != NULL);
1879 	KASSERT(fdvp != NULL);
1880 	KASSERT(fvp != NULL);
1881 	KASSERT(fdvp != fvp);
1882 	KASSERT(fdvp != tvp);
1883 	KASSERT(tdvp != tvp);
1884 	KASSERT(tdvp != fvp);
1885 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1886 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1887 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1888 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1889 
1890 	if (tvp != NULL) {
1891 		if (tvp != fvp)
1892 			vput(tvp);
1893 		else
1894 			vrele(tvp);
1895 	}
1896 	VOP_UNLOCK(tdvp);
1897 	vput(fvp);
1898 	if (fdvp != tdvp)
1899 		VOP_UNLOCK(fdvp);
1900 
1901 #if 0				/* XXX */
1902 	if (fdvp != tdvp)
1903 		mutex_exit(&tmpfs->tm_rename_lock);
1904 #endif
1905 }
1906 
1907 /*
1908  * Lock a directory, but fail if it has been rmdir'd.
1909  *
1910  * vp must be referenced.
1911  */
1912 int
1913 tmpfs_rename_lock_directory(struct vnode *vp, struct tmpfs_node *node)
1914 {
1915 
1916 	KASSERT(vp != NULL);
1917 	KASSERT(node != NULL);
1918 	KASSERT(node->tn_vnode == vp);
1919 	KASSERT(node->tn_type == VDIR);
1920 
1921 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1922 	if (node->tn_spec.tn_dir.tn_parent == NULL) {
1923 		VOP_UNLOCK(vp);
1924 		return ENOENT;
1925 	}
1926 
1927 	return 0;
1928 }
1929 
1930 /*
1931  * Analyze the genealogy of the source and target nodes.
1932  *
1933  * On success, stores in *intermediate_node_ret either the child of
1934  * fdnode of which tdnode is a descendant, or null if tdnode is not a
1935  * descendant of fdnode at all.
1936  *
1937  * fdnode and tdnode must be unlocked and referenced.  The file
1938  * system's rename lock must also be held, to exclude concurrent
1939  * changes to the file system's genealogy other than rmdir.
1940  *
1941  * XXX This causes an extra lock/unlock of tdnode in the case when
1942  * we're just about to lock it again before locking anything else.
1943  * However, changing that requires reorganizing the code to make it
1944  * even more horrifically obscure.
1945  */
1946 int
1947 tmpfs_rename_genealogy(struct tmpfs_node *fdnode, struct tmpfs_node *tdnode,
1948     struct tmpfs_node **intermediate_node_ret)
1949 {
1950 	struct tmpfs_node *node = tdnode, *parent;
1951 	int error;
1952 
1953 	KASSERT(fdnode != NULL);
1954 	KASSERT(tdnode != NULL);
1955 	KASSERT(fdnode != tdnode);
1956 	KASSERT(intermediate_node_ret != NULL);
1957 
1958 	KASSERT(fdnode->tn_vnode != NULL);
1959 	KASSERT(tdnode->tn_vnode != NULL);
1960 	KASSERT(fdnode->tn_type == VDIR);
1961 	KASSERT(tdnode->tn_type == VDIR);
1962 
1963 	/*
1964 	 * We need to provisionally lock tdnode->tn_vnode to keep rmdir
1965 	 * from deleting it -- or any ancestor -- at an inopportune
1966 	 * moment.
1967 	 */
1968 	error = tmpfs_rename_lock_directory(tdnode->tn_vnode, tdnode);
1969 	if (error)
1970 		return error;
1971 
1972 	for (;;) {
1973 		parent = node->tn_spec.tn_dir.tn_parent;
1974 		KASSERT(parent != NULL);
1975 		KASSERT(parent->tn_type == VDIR);
1976 
1977 		/* Did we hit the root without finding fdnode?  */
1978 		if (parent == node) {
1979 			*intermediate_node_ret = NULL;
1980 			break;
1981 		}
1982 
1983 		/* Did we find that fdnode is an ancestor?  */
1984 		if (parent == fdnode) {
1985 			*intermediate_node_ret = node;
1986 			break;
1987 		}
1988 
1989 		/* Neither -- keep ascending the family tree.  */
1990 		node = parent;
1991 	}
1992 
1993 	VOP_UNLOCK(tdnode->tn_vnode);
1994 	return 0;
1995 }
1996 
1997 /*
1998  * Lock directories a and b, which must be distinct, and look up and
1999  * lock nodes a and b.  Do a first and then b.  Directory b may not be
2000  * an ancestor of directory a, although directory a may be an ancestor
2001  * of directory b.  Fail with overlap_error if node a is directory b.
2002  * Neither componentname may be `.' or `..'.
2003  *
2004  * a_dvp and b_dvp must be referenced.
2005  *
2006  * On entry, a_dvp and b_dvp are unlocked.
2007  *
2008  * On success,
2009  * . a_dvp and b_dvp are locked,
2010  * . *a_dirent_ret is filled with a directory entry whose node is
2011  *     locked and referenced,
2012  * . *b_vp_ret is filled with the corresponding vnode,
2013  * . *b_dirent_ret is filled either with null or with a directory entry
2014  *     whose node is locked and referenced,
2015  * . *b_vp is filled either with null or with the corresponding vnode,
2016  *     and
2017  * . the only pair of vnodes that may be identical is a_vp and b_vp.
2018  *
2019  * On failure, a_dvp and b_dvp are left unlocked, and *a_dirent_ret,
2020  * *a_vp, *b_dirent_ret, and *b_vp are left alone.
2021  */
2022 int
2023 tmpfs_rename_lock(struct mount *mount, struct ucred *cred, int overlap_error,
2024     struct vnode *a_dvp, struct tmpfs_node *a_dnode,
2025     struct componentname *a_cnp, int a_missing_ok,
2026     struct tmpfs_dirent **a_dirent_ret, struct vnode **a_vp_ret,
2027     struct vnode *b_dvp, struct tmpfs_node *b_dnode,
2028     struct componentname *b_cnp, int b_missing_ok,
2029     struct tmpfs_dirent **b_dirent_ret, struct vnode **b_vp_ret)
2030 {
2031 	struct tmpfs_dirent *a_dirent, *b_dirent;
2032 	struct vnode *a_vp, *b_vp;
2033 	int error;
2034 
2035 	KASSERT(a_dvp != NULL);
2036 	KASSERT(a_dnode != NULL);
2037 	KASSERT(a_cnp != NULL);
2038 	KASSERT(a_dirent_ret != NULL);
2039 	KASSERT(a_vp_ret != NULL);
2040 	KASSERT(b_dvp != NULL);
2041 	KASSERT(b_dnode != NULL);
2042 	KASSERT(b_cnp != NULL);
2043 	KASSERT(b_dirent_ret != NULL);
2044 	KASSERT(b_vp_ret != NULL);
2045 	KASSERT(a_dvp != b_dvp);
2046 	KASSERT(a_dnode != b_dnode);
2047 	KASSERT(a_dnode->tn_vnode == a_dvp);
2048 	KASSERT(b_dnode->tn_vnode == b_dvp);
2049 	KASSERT(a_dnode->tn_type == VDIR);
2050 	KASSERT(b_dnode->tn_type == VDIR);
2051 	KASSERT(a_missing_ok != b_missing_ok);
2052 
2053 	error = tmpfs_rename_lock_directory(a_dvp, a_dnode);
2054 	if (error)
2055 		goto fail0;
2056 
2057 	/* Did we lose a race with mount?  */
2058 	if (a_dvp->v_mountedhere != NULL) {
2059 		error = EBUSY;
2060 		goto fail1;
2061 	}
2062 
2063 	/* Make sure the caller may read the directory.  */
2064 	error = VOP_ACCESS(a_dvp, VEXEC, cred, curproc);
2065 	if (error)
2066 		goto fail1;
2067 
2068 	a_dirent = tmpfs_dir_lookup(a_dnode, a_cnp);
2069 	if (a_dirent != NULL) {
2070 		KASSERT(a_dirent->td_node != NULL);
2071 		/* We ruled out `.' earlier.  */
2072 		KASSERT(a_dirent->td_node != a_dnode);
2073 		/* We ruled out `..' earlier.  */
2074 		KASSERT(a_dirent->td_node !=
2075 		    a_dnode->tn_spec.tn_dir.tn_parent);
2076 		if (a_dirent->td_node == b_dnode) {
2077 			error = overlap_error;
2078 			goto fail1;
2079 		}
2080 		rw_enter_write(&a_dirent->td_node->tn_nlock);
2081 		error = tmpfs_vnode_get(mount, a_dirent->td_node, &a_vp);
2082 		if (error)
2083 			goto fail1;
2084 		KASSERT(a_vp->v_mount == mount);
2085 		/* Refuse to rename (over) a mount point.  */
2086 		if ((a_vp->v_type == VDIR) && (a_vp->v_mountedhere != NULL)) {
2087 			error = EBUSY;
2088 			goto fail2;
2089 		}
2090 	} else if (!a_missing_ok) {
2091 		error = ENOENT;
2092 		goto fail1;
2093 	} else {
2094 		a_vp = NULL;
2095 	}
2096 	KASSERT(a_vp != a_dvp);
2097 	KASSERT(a_vp != b_dvp);
2098 
2099 	error = tmpfs_rename_lock_directory(b_dvp, b_dnode);
2100 	if (error)
2101 		goto fail2;
2102 
2103 	/* Did we lose a race with mount?  */
2104 	if (b_dvp->v_mountedhere != NULL) {
2105 		error = EBUSY;
2106 		goto fail3;
2107 	}
2108 
2109 	/* Make sure the caller may read the directory.  */
2110 	error = VOP_ACCESS(b_dvp, VEXEC, cred, curproc);
2111 	if (error)
2112 		goto fail3;
2113 
2114 	b_dirent = tmpfs_dir_lookup(b_dnode, b_cnp);
2115 	if (b_dirent != NULL) {
2116 		KASSERT(b_dirent->td_node != NULL);
2117 		/* We ruled out `.' earlier.  */
2118 		KASSERT(b_dirent->td_node != b_dnode);
2119 		/* We ruled out `..' earlier.  */
2120 		KASSERT(b_dirent->td_node !=
2121 		    b_dnode->tn_spec.tn_dir.tn_parent);
2122 		/* b is not an ancestor of a.  */
2123 		KASSERT(b_dirent->td_node != a_dnode);
2124 		/* But the source and target nodes might be the same.  */
2125 		if ((a_dirent == NULL) ||
2126 		    (a_dirent->td_node != b_dirent->td_node)) {
2127 			rw_enter_write(&b_dirent->td_node->tn_nlock);
2128 			error = tmpfs_vnode_get(mount, b_dirent->td_node,
2129 			    &b_vp);
2130 			if (error)
2131 				goto fail3;
2132 			KASSERT(b_vp->v_mount == mount);
2133 			KASSERT(a_vp != b_vp);
2134 			/* Refuse to rename (over) a mount point.  */
2135 			if ((b_vp->v_type == VDIR) &&
2136 			    (b_vp->v_mountedhere != NULL)) {
2137 				error = EBUSY;
2138 				goto fail4;
2139 			}
2140 		} else {
2141 			b_vp = a_vp;
2142 			vref(b_vp);
2143 		}
2144 	} else if (!b_missing_ok) {
2145 		error = ENOENT;
2146 		goto fail3;
2147 	} else {
2148 		b_vp = NULL;
2149 	}
2150 	KASSERT(b_vp != a_dvp);
2151 	KASSERT(b_vp != b_dvp);
2152 
2153 	KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE);
2154 	KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE);
2155 	KASSERT(a_missing_ok || (a_dirent != NULL));
2156 	KASSERT(a_missing_ok || (a_dirent->td_node != NULL));
2157 	KASSERT(b_missing_ok || (b_dirent != NULL));
2158 	KASSERT(b_missing_ok || (b_dirent->td_node != NULL));
2159 	KASSERT((a_dirent == NULL) || (a_dirent->td_node != NULL));
2160 	KASSERT((a_dirent == NULL) || (a_dirent->td_node->tn_vnode == a_vp));
2161 	KASSERT((b_dirent == NULL) || (b_dirent->td_node != NULL));
2162 	KASSERT((b_dirent == NULL) || (b_dirent->td_node->tn_vnode == b_vp));
2163 	KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE));
2164 	KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE));
2165 
2166 	*a_dirent_ret = a_dirent;
2167 	*b_dirent_ret = b_dirent;
2168 	*a_vp_ret = a_vp;
2169 	*b_vp_ret = b_vp;
2170 	return 0;
2171 
2172 fail4:	if (b_vp != NULL) {
2173 		KASSERT(VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE);
2174 		if (b_vp != a_vp)
2175 			vput(b_vp);
2176 		else
2177 			vrele(a_vp);
2178 	}
2179 
2180 fail3:	KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE);
2181 	VOP_UNLOCK(b_dvp);
2182 
2183 fail2:	if (a_vp != NULL) {
2184 		KASSERT(VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE);
2185 		vput(a_vp);
2186 	}
2187 
2188 fail1:	KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE);
2189 	VOP_UNLOCK(a_dvp);
2190 
2191 fail0:	/* KASSERT(VOP_ISLOCKED(a_dvp) != LK_EXCLUSIVE); */
2192 	/* KASSERT(VOP_ISLOCKED(b_dvp) != LK_EXCLUSIVE); */
2193 	/* KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) != LK_EXCLUSIVE)); */
2194 	/* KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) != LK_EXCLUSIVE)); */
2195 	return error;
2196 }
2197 
2198 /*
2199  * Shuffle the directory entries to move fvp from the directory fdvp
2200  * into the directory tdvp.  fde is fvp's directory entry in fdvp.  If
2201  * we are overwriting a target node, it is tvp, and tde is its
2202  * directory entry in tdvp.
2203  *
2204  * fdvp, fvp, tdvp, and tvp must all be locked and referenced.
2205  */
2206 void
2207 tmpfs_rename_attachdetach(struct tmpfs_mount *tmpfs,
2208     struct vnode *fdvp, struct tmpfs_dirent *fde, struct vnode *fvp,
2209     struct vnode *tdvp, struct tmpfs_dirent *tde, struct vnode *tvp)
2210 {
2211 
2212 	KASSERT(tmpfs != NULL);
2213 	KASSERT(fdvp != NULL);
2214 	KASSERT(fde != NULL);
2215 	KASSERT(fvp != NULL);
2216 	KASSERT(tdvp != NULL);
2217 	KASSERT(fde->td_node != NULL);
2218 	KASSERT(fde->td_node->tn_vnode == fvp);
2219 	KASSERT((tde == NULL) == (tvp == NULL));
2220 	KASSERT((tde == NULL) || (tde->td_node != NULL));
2221 	KASSERT((tde == NULL) || (tde->td_node->tn_vnode == tvp));
2222 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
2223 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
2224 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
2225 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
2226 
2227 	/*
2228 	 * If we are moving from one directory to another, detach the
2229 	 * source entry and reattach it to the target directory.
2230 	 */
2231 	if (fdvp != tdvp) {
2232 		/* tmpfs_dir_detach clobbers fde->td_node, so save it.  */
2233 		struct tmpfs_node *fnode = fde->td_node;
2234 		tmpfs_node_t *fdnode = VP_TO_TMPFS_DIR(fdvp);
2235 		tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
2236 		tmpfs_dir_detach(fdnode, fde);
2237 		tmpfs_dir_attach(tdnode, fde, fnode);
2238 	} else if (tvp == NULL) {
2239 		/*
2240 		 * We are changing the directory.  tmpfs_dir_attach and
2241 		 * tmpfs_dir_detach note the events for us, but for
2242 		 * this case we don't call them, so we must note the
2243 		 * event explicitly.
2244 		 */
2245 		VN_KNOTE(fdvp, NOTE_WRITE);
2246 	}
2247 
2248 	/*
2249 	 * If we are replacing an existing target entry, delete it.
2250 	 */
2251 	if (tde != NULL) {
2252 		tmpfs_node_t *tdnode = VP_TO_TMPFS_DIR(tdvp);
2253 		KASSERT(tvp != NULL);
2254 		KASSERT(tde->td_node != NULL);
2255 		KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
2256 		if (tde->td_node->tn_type == VDIR) {
2257 			KASSERT(tde->td_node->tn_size == 0);
2258 			KASSERT(tde->td_node->tn_links == 2);
2259 			/* Decrement the extra link count for `.' so
2260 			 * the vnode will be recycled when released.  */
2261 			tde->td_node->tn_links--;
2262 		}
2263 		tmpfs_dir_detach(tdnode, tde);
2264 		tmpfs_free_dirent(tmpfs, tde);
2265 	}
2266 }
2267 
2268 /*
2269  * Remove the entry de for the non-directory vp from the directory dvp.
2270  *
2271  * Everything must be locked and referenced.
2272  */
2273 int
2274 tmpfs_do_remove(struct tmpfs_mount *tmpfs, struct vnode *dvp,
2275     struct tmpfs_node *dnode, struct tmpfs_dirent *de, struct vnode *vp,
2276     struct ucred *cred)
2277 {
2278 	int error;
2279 
2280 	KASSERT(tmpfs != NULL);
2281 	KASSERT(dvp != NULL);
2282 	KASSERT(dnode != NULL);
2283 	KASSERT(de != NULL);
2284 	KASSERT(vp != NULL);
2285 	KASSERT(dnode->tn_vnode == dvp);
2286 	KASSERT(de->td_node != NULL);
2287 	KASSERT(de->td_node->tn_vnode == vp);
2288 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
2289 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
2290 
2291 	error = tmpfs_remove_check_possible(dnode, de->td_node);
2292 	if (error)
2293 		return error;
2294 
2295 	error = tmpfs_remove_check_permitted(cred, dnode, de->td_node);
2296 	if (error)
2297 		return error;
2298 
2299 	/*
2300 	 * If not root and directory is sticky, check for permission on
2301 	 * directory or on file. This implements append-only directories.
2302 	 */
2303 	if ((dnode->tn_mode & S_ISTXT) != 0)
2304 		if (cred->cr_uid != 0 && cred->cr_uid != dnode->tn_uid &&
2305 		    cred->cr_uid != de->td_node->tn_uid)
2306 			return EPERM;
2307 
2308 	tmpfs_dir_detach(dnode, de);
2309 	tmpfs_free_dirent(tmpfs, de);
2310 
2311 	return 0;
2312 }
2313 
2314 /*
2315  * Check whether a rename is possible independent of credentials.
2316  *
2317  * Everything must be locked and referenced.
2318  */
2319 int
2320 tmpfs_rename_check_possible(
2321     struct tmpfs_node *fdnode, struct tmpfs_node *fnode,
2322     struct tmpfs_node *tdnode, struct tmpfs_node *tnode)
2323 {
2324 
2325 	KASSERT(fdnode != NULL);
2326 	KASSERT(fnode != NULL);
2327 	KASSERT(tdnode != NULL);
2328 	KASSERT(fdnode != fnode);
2329 	KASSERT(tdnode != tnode);
2330 	KASSERT(fnode != tnode);
2331 	KASSERT(fdnode->tn_vnode != NULL);
2332 	KASSERT(fnode->tn_vnode != NULL);
2333 	KASSERT(tdnode->tn_vnode != NULL);
2334 	KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL));
2335 	KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE);
2336 	KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE);
2337 	KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE);
2338 	KASSERT((tnode == NULL) ||
2339 	    (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE));
2340 
2341 	/*
2342 	 * If fdnode is immutable, we can't write to it.  If fdnode is
2343 	 * append-only, the only change we can make is to add entries
2344 	 * to it.  If fnode is immutable, we can't change the links to
2345 	 * it.  If fnode is append-only...well, this is what UFS does.
2346 	 */
2347 	if ((fdnode->tn_flags | fnode->tn_flags) & (IMMUTABLE | APPEND))
2348 		return EPERM;
2349 
2350 	/*
2351 	 * If tdnode is immutable, we can't write to it.  If tdnode is
2352 	 * append-only, we can add entries, but we can't change
2353 	 * existing entries.
2354 	 */
2355 	if (tdnode->tn_flags & (IMMUTABLE | (tnode? APPEND : 0)))
2356 		return EPERM;
2357 
2358 	/*
2359 	 * If tnode is immutable, we can't replace links to it.  If
2360 	 * tnode is append-only...well, this is what UFS does.
2361 	 */
2362 	if (tnode != NULL) {
2363 		KASSERT(tnode != NULL);
2364 		if ((tnode->tn_flags & (IMMUTABLE | APPEND)) != 0)
2365 			return EPERM;
2366 	}
2367 
2368 	return 0;
2369 }
2370 
2371 /*
2372  * Check whether a rename is permitted given our credentials.
2373  *
2374  * Everything must be locked and referenced.
2375  */
2376 int
2377 tmpfs_rename_check_permitted(struct ucred *cred,
2378     struct tmpfs_node *fdnode, struct tmpfs_node *fnode,
2379     struct tmpfs_node *tdnode, struct tmpfs_node *tnode)
2380 {
2381 	int error;
2382 
2383 	KASSERT(fdnode != NULL);
2384 	KASSERT(fnode != NULL);
2385 	KASSERT(tdnode != NULL);
2386 	KASSERT(fdnode != fnode);
2387 	KASSERT(tdnode != tnode);
2388 	KASSERT(fnode != tnode);
2389 	KASSERT(fdnode->tn_vnode != NULL);
2390 	KASSERT(fnode->tn_vnode != NULL);
2391 	KASSERT(tdnode->tn_vnode != NULL);
2392 	KASSERT((tnode == NULL) || (tnode->tn_vnode != NULL));
2393 	KASSERT(VOP_ISLOCKED(fdnode->tn_vnode) == LK_EXCLUSIVE);
2394 	KASSERT(VOP_ISLOCKED(fnode->tn_vnode) == LK_EXCLUSIVE);
2395 	KASSERT(VOP_ISLOCKED(tdnode->tn_vnode) == LK_EXCLUSIVE);
2396 	KASSERT((tnode == NULL) ||
2397 	    (VOP_ISLOCKED(tnode->tn_vnode) == LK_EXCLUSIVE));
2398 
2399 	/*
2400 	 * We need to remove or change an entry in the source directory.
2401 	 */
2402 	error = VOP_ACCESS(fdnode->tn_vnode, VWRITE, cred, curproc);
2403 	if (error)
2404 		return error;
2405 
2406 	/*
2407 	 * If we are changing directories, then we need to write to the
2408 	 * target directory to add or change an entry.  Also, if fnode
2409 	 * is a directory, we need to write to it to change its `..'
2410 	 * entry.
2411 	 */
2412 	if (fdnode != tdnode) {
2413 		error = VOP_ACCESS(tdnode->tn_vnode, VWRITE, cred, curproc);
2414 		if (error)
2415 			return error;
2416 		if (fnode->tn_type == VDIR) {
2417 			error = VOP_ACCESS(fnode->tn_vnode, VWRITE, cred,
2418 			    curproc);
2419 			if (error)
2420 				return error;
2421 		}
2422 	}
2423 
2424 	error = tmpfs_check_sticky(cred, fdnode, fnode);
2425 	if (error)
2426 		return error;
2427 
2428 	if (TMPFS_DIRSEQ_FULL(tdnode))
2429 		return (ENOSPC);
2430 
2431 	error = tmpfs_check_sticky(cred, tdnode, tnode);
2432 	if (error)
2433 		return error;
2434 
2435 	return 0;
2436 }
2437 
2438 /*
2439  * Check whether removing node's entry in dnode is possible independent
2440  * of credentials.
2441  *
2442  * Everything must be locked and referenced.
2443  */
2444 int
2445 tmpfs_remove_check_possible(struct tmpfs_node *dnode, struct tmpfs_node *node)
2446 {
2447 
2448 	KASSERT(dnode != NULL);
2449 	KASSERT(dnode->tn_vnode != NULL);
2450 	KASSERT(node != NULL);
2451 	KASSERT(dnode != node);
2452 	KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2453 	KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE);
2454 
2455 	/*
2456 	 * We want to delete the entry.  If dnode is immutable, we
2457 	 * can't write to it to delete the entry.  If dnode is
2458 	 * append-only, the only change we can make is to add entries,
2459 	 * so we can't delete entries.  If node is immutable, we can't
2460 	 * change the links to it, so we can't delete the entry.  If
2461 	 * node is append-only...well, this is what UFS does.
2462 	 */
2463 	if ((dnode->tn_flags | node->tn_flags) & (IMMUTABLE | APPEND))
2464 		return EPERM;
2465 
2466 	return 0;
2467 }
2468 
2469 /*
2470  * Check whether removing node's entry in dnode is permitted given our
2471  * credentials.
2472  *
2473  * Everything must be locked and referenced.
2474  */
2475 int
2476 tmpfs_remove_check_permitted(struct ucred *cred,
2477     struct tmpfs_node *dnode, struct tmpfs_node *node)
2478 {
2479 	int error;
2480 
2481 	KASSERT(dnode != NULL);
2482 	KASSERT(dnode->tn_vnode != NULL);
2483 	KASSERT(node != NULL);
2484 	KASSERT(dnode != node);
2485 	KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2486 	KASSERT(VOP_ISLOCKED(node->tn_vnode) == LK_EXCLUSIVE);
2487 
2488 	/*
2489 	 * Check whether we are permitted to write to the source
2490 	 * directory in order to delete an entry from it.
2491 	 */
2492 	error = VOP_ACCESS(dnode->tn_vnode, VWRITE, cred, curproc);
2493 	if (error)
2494 		return error;
2495 
2496 	error = tmpfs_check_sticky(cred, dnode, node);
2497 	if (error)
2498 		return error;
2499 
2500 	return 0;
2501 }
2502 
2503 /*
2504  * Check whether we may change an entry in a sticky directory.  If the
2505  * directory is sticky, the user must own either the directory or, if
2506  * it exists, the node, in order to change the entry.
2507  *
2508  * Everything must be locked and referenced.
2509  */
2510 int
2511 tmpfs_check_sticky(struct ucred *cred,
2512     struct tmpfs_node *dnode, struct tmpfs_node *node)
2513 {
2514 
2515 	KASSERT(dnode != NULL);
2516 	KASSERT(dnode->tn_vnode != NULL);
2517 	KASSERT(VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE);
2518 	KASSERT((node == NULL) || (node->tn_vnode != NULL));
2519 	KASSERT((node == NULL) ||
2520 	    (VOP_ISLOCKED(dnode->tn_vnode) == LK_EXCLUSIVE));
2521 
2522 	if (node == NULL)
2523 		return 0;
2524 
2525 	if (dnode->tn_mode & S_ISTXT) {
2526 		if (cred->cr_uid != 0 &&
2527 		    cred->cr_uid != dnode->tn_uid &&
2528 		    cred->cr_uid != node->tn_uid)
2529 			return EPERM;
2530 	}
2531 
2532 	return 0;
2533 }
2534 
2535 void
2536 tmpfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp,
2537     struct vnode *tdvp, struct vnode *tvp)
2538 {
2539 
2540 	KASSERT(fdvp != NULL);
2541 	KASSERT(fvp != NULL);
2542 	KASSERT(tdvp != NULL);
2543 	KASSERT(fdvp != fvp);
2544 	KASSERT(fdvp != tvp);
2545 	KASSERT(tdvp != fvp);
2546 	KASSERT(tdvp != tvp);
2547 	KASSERT(fvp != tvp);
2548 	KASSERT(fdvp->v_type == VDIR);
2549 	KASSERT(tdvp->v_type == VDIR);
2550 
2551 	/*
2552 	 * XXX What actually needs to be purged?
2553 	 */
2554 
2555 	cache_purge(fdvp);
2556 
2557 	if (fvp->v_type == VDIR)
2558 		cache_purge(fvp);
2559 
2560 	if (tdvp != fdvp)
2561 		cache_purge(tdvp);
2562 
2563 	if ((tvp != NULL) && (tvp->v_type == VDIR))
2564 		cache_purge(tvp);
2565 }
2566 
2567 void
2568 tmpfs_rename_abort(void *v)
2569 {
2570 	struct vop_rename_args *ap = v;
2571 	struct vnode *fdvp = ap->a_fdvp;
2572 	struct vnode *fvp = ap->a_fvp;
2573 	struct componentname *fcnp = ap->a_fcnp;
2574 	struct vnode *tdvp = ap->a_tdvp;
2575 	struct vnode *tvp = ap->a_tvp;
2576 	struct componentname *tcnp = ap->a_tcnp;
2577 
2578 	VOP_ABORTOP(tdvp, tcnp);
2579 	if (tdvp == tvp)
2580 		vrele(tdvp);
2581 	else
2582 		vput(tdvp);
2583 	if (tvp != NULL)
2584 		vput(tvp);
2585 	VOP_ABORTOP(fdvp, fcnp);
2586 	vrele(fdvp);
2587 	vrele(fvp);
2588 }
2589 
2590 void filt_tmpfsdetach(struct knote *kn);
2591 int filt_tmpfsread(struct knote *kn, long hint);
2592 int filt_tmpfswrite(struct knote *kn, long hint);
2593 int filt_tmpfsvnode(struct knote *kn, long hint);
2594 
2595 const struct filterops tmpfsread_filtops = {
2596 	.f_flags	= FILTEROP_ISFD,
2597 	.f_attach	= NULL,
2598 	.f_detach	= filt_tmpfsdetach,
2599 	.f_event	= filt_tmpfsread,
2600 };
2601 
2602 const struct filterops tmpfswrite_filtops = {
2603 	.f_flags	= FILTEROP_ISFD,
2604 	.f_attach	= NULL,
2605 	.f_detach	= filt_tmpfsdetach,
2606 	.f_event	= filt_tmpfswrite,
2607 };
2608 
2609 const struct filterops tmpfsvnode_filtops = {
2610 	.f_flags	= FILTEROP_ISFD,
2611 	.f_attach	= NULL,
2612 	.f_detach	= filt_tmpfsdetach,
2613 	.f_event	= filt_tmpfsvnode,
2614 };
2615 
2616 int
2617 tmpfs_kqfilter(void *v)
2618 {
2619 	struct vop_kqfilter_args *ap = v;
2620 	struct vnode *vp = ap->a_vp;
2621 	struct knote *kn = ap->a_kn;
2622 
2623 	switch (kn->kn_filter) {
2624 	case EVFILT_READ:
2625 		kn->kn_fop = &tmpfsread_filtops;
2626 		break;
2627 	case EVFILT_WRITE:
2628 		kn->kn_fop = &tmpfswrite_filtops;
2629 		break;
2630 	case EVFILT_VNODE:
2631 		kn->kn_fop = &tmpfsvnode_filtops;
2632 		break;
2633 	default:
2634 		return (EINVAL);
2635 	}
2636 
2637 	kn->kn_hook = (caddr_t)vp;
2638 
2639 	klist_insert_locked(&vp->v_selectinfo.si_note, kn);
2640 
2641 	return (0);
2642 }
2643 
2644 void
2645 filt_tmpfsdetach(struct knote *kn)
2646 {
2647 	struct vnode *vp = (struct vnode *)kn->kn_hook;
2648 
2649 	klist_remove_locked(&vp->v_selectinfo.si_note, kn);
2650 }
2651 
2652 int
2653 filt_tmpfsread(struct knote *kn, long hint)
2654 {
2655 	struct vnode *vp = (struct vnode *)kn->kn_hook;
2656 	tmpfs_node_t *node = VP_TO_TMPFS_NODE(vp);
2657 
2658 	/*
2659 	 * filesystem is gone, so set the EOF flag and schedule
2660 	 * the knote for deletion.
2661 	 */
2662 	if (hint == NOTE_REVOKE) {
2663 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2664 		return (1);
2665 	}
2666 
2667 	kn->kn_data = node->tn_size - foffset(kn->kn_fp);
2668 	if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) {
2669 		kn->kn_fflags |= NOTE_EOF;
2670 		return (1);
2671 	}
2672 
2673 	if (kn->kn_flags & (__EV_POLL | __EV_SELECT))
2674 		return (1);
2675 
2676 	return (kn->kn_data != 0);
2677 }
2678 
2679 int
2680 filt_tmpfswrite(struct knote *kn, long hint)
2681 {
2682 	/*
2683 	 * filesystem is gone, so set the EOF flag and schedule
2684 	 * the knote for deletion.
2685 	 */
2686 	if (hint == NOTE_REVOKE) {
2687 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2688 		return (1);
2689 	}
2690 
2691 	kn->kn_data = 0;
2692 	return (1);
2693 }
2694 
2695 int
2696 filt_tmpfsvnode(struct knote *kn, long hint)
2697 {
2698 	if (kn->kn_sfflags & hint)
2699 		kn->kn_fflags |= hint;
2700 	if (hint == NOTE_REVOKE) {
2701 		kn->kn_flags |= EV_EOF;
2702 		return (1);
2703 	}
2704 	return (kn->kn_fflags != 0);
2705 }
2706