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