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