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