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