e8be50cfa9af696e773ab648968b668589205ce1
[dragonfly.git] / sys / vfs / tmpfs / tmpfs_vnops.c
1 /*-
2  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
7  * 2005 program.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $
31  */
32
33 /*
34  * tmpfs vnode interface.
35  */
36
37 #include <sys/kernel.h>
38 #include <sys/kern_syscall.h>
39 #include <sys/param.h>
40 #include <sys/fcntl.h>
41 #include <sys/lockf.h>
42 #include <sys/priv.h>
43 #include <sys/proc.h>
44 #include <sys/resourcevar.h>
45 #include <sys/sched.h>
46 #include <sys/stat.h>
47 #include <sys/systm.h>
48 #include <sys/unistd.h>
49 #include <sys/vfsops.h>
50 #include <sys/vnode.h>
51 #include <sys/mountctl.h>
52
53 #include <vm/vm.h>
54 #include <vm/vm_object.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_pager.h>
57 #include <vm/swap_pager.h>
58
59 #include <sys/buf2.h>
60
61 #include <vfs/fifofs/fifo.h>
62 #include <vfs/tmpfs/tmpfs_vnops.h>
63 #include <vfs/tmpfs/tmpfs.h>
64
65 MALLOC_DECLARE(M_TMPFS);
66
67 static void tmpfs_strategy_done(struct bio *bio);
68
69 static __inline
70 void
71 tmpfs_knote(struct vnode *vp, int flags)
72 {
73         if (flags)
74                 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags);
75 }
76
77
78 /* --------------------------------------------------------------------- */
79
80 static int
81 tmpfs_nresolve(struct vop_nresolve_args *v)
82 {
83         struct vnode *dvp = v->a_dvp;
84         struct vnode *vp = NULL;
85         struct namecache *ncp = v->a_nch->ncp;
86         struct tmpfs_node *tnode;
87
88         int error;
89         struct tmpfs_dirent *de;
90         struct tmpfs_node *dnode;
91
92         dnode = VP_TO_TMPFS_DIR(dvp);
93
94         de = tmpfs_dir_lookup(dnode, NULL, ncp);
95         if (de == NULL) {
96                 error = ENOENT;
97         } else {
98                 /*
99                  * Allocate a vnode for the node we found.
100                  */
101                 tnode = de->td_node;
102                 error = tmpfs_alloc_vp(dvp->v_mount, tnode,
103                                        LK_EXCLUSIVE | LK_RETRY, &vp);
104                 if (error)
105                         goto out;
106                 KKASSERT(vp);
107         }
108
109 out:
110         /*
111          * Store the result of this lookup in the cache.  Avoid this if the
112          * request was for creation, as it does not improve timings on
113          * emprical tests.
114          */
115         if (vp) {
116                 vn_unlock(vp);
117                 cache_setvp(v->a_nch, vp);
118                 vrele(vp);
119         } else if (error == ENOENT) {
120                 cache_setvp(v->a_nch, NULL);
121         }
122         return error;
123 }
124
125 static int
126 tmpfs_nlookupdotdot(struct vop_nlookupdotdot_args *v)
127 {
128         struct vnode *dvp = v->a_dvp;
129         struct vnode **vpp = v->a_vpp;
130         struct tmpfs_node *dnode = VP_TO_TMPFS_NODE(dvp);
131         struct ucred *cred = v->a_cred;
132         int error;
133
134         *vpp = NULL;
135         /* Check accessibility of requested node as a first step. */
136         error = VOP_ACCESS(dvp, VEXEC, cred);
137         if (error != 0)
138                 return error;
139
140         if (dnode->tn_dir.tn_parent != NULL) {
141                 /* Allocate a new vnode on the matching entry. */
142                 error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent,
143                     LK_EXCLUSIVE | LK_RETRY, vpp);
144
145                 if (*vpp)
146                         vn_unlock(*vpp);
147         }
148
149         return (*vpp == NULL) ? ENOENT : 0;
150 }
151
152 /* --------------------------------------------------------------------- */
153
154 static int
155 tmpfs_ncreate(struct vop_ncreate_args *v)
156 {
157         struct vnode *dvp = v->a_dvp;
158         struct vnode **vpp = v->a_vpp;
159         struct namecache *ncp = v->a_nch->ncp;
160         struct vattr *vap = v->a_vap;
161         struct ucred *cred = v->a_cred;
162         int error;
163
164         KKASSERT(vap->va_type == VREG || vap->va_type == VSOCK);
165
166         error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL);
167         if (error == 0) {
168                 cache_setunresolved(v->a_nch);
169                 cache_setvp(v->a_nch, *vpp);
170                 tmpfs_knote(dvp, NOTE_WRITE);
171         }
172
173         return error;
174 }
175 /* --------------------------------------------------------------------- */
176
177 static int
178 tmpfs_nmknod(struct vop_nmknod_args *v)
179 {
180         struct vnode *dvp = v->a_dvp;
181         struct vnode **vpp = v->a_vpp;
182         struct namecache *ncp = v->a_nch->ncp;
183         struct vattr *vap = v->a_vap;
184         struct ucred *cred = v->a_cred;
185         int error;
186
187         if (vap->va_type != VBLK && vap->va_type != VCHR &&
188             vap->va_type != VFIFO)
189                 return EINVAL;
190
191         error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL);
192         if (error == 0) {
193                 cache_setunresolved(v->a_nch);
194                 cache_setvp(v->a_nch, *vpp);
195                 tmpfs_knote(dvp, NOTE_WRITE);
196         }
197
198         return error;
199 }
200
201 /* --------------------------------------------------------------------- */
202
203 static int
204 tmpfs_open(struct vop_open_args *v)
205 {
206         struct vnode *vp = v->a_vp;
207         int mode = v->a_mode;
208
209         int error;
210         struct tmpfs_node *node;
211
212         node = VP_TO_TMPFS_NODE(vp);
213
214         /* The file is still active but all its names have been removed
215          * (e.g. by a "rmdir $(pwd)").  It cannot be opened any more as
216          * it is about to die. */
217         if (node->tn_links < 1)
218                 return (ENOENT);
219
220         /* If the file is marked append-only, deny write requests. */
221         if ((node->tn_flags & APPEND) &&
222             (mode & (FWRITE | O_APPEND)) == FWRITE) {
223                 error = EPERM;
224         } else {
225                 return (vop_stdopen(v));
226         }
227         return error;
228 }
229
230 /* --------------------------------------------------------------------- */
231
232 static int
233 tmpfs_close(struct vop_close_args *v)
234 {
235         struct vnode *vp = v->a_vp;
236         struct tmpfs_node *node;
237
238         node = VP_TO_TMPFS_NODE(vp);
239
240         if (node->tn_links > 0) {
241                 /* Update node times.  No need to do it if the node has
242                  * been deleted, because it will vanish after we return. */
243                 tmpfs_update(vp);
244         }
245
246         return vop_stdclose(v);
247 }
248
249 /* --------------------------------------------------------------------- */
250
251 int
252 tmpfs_access(struct vop_access_args *v)
253 {
254         struct vnode *vp = v->a_vp;
255         int error;
256         struct tmpfs_node *node;
257
258         node = VP_TO_TMPFS_NODE(vp);
259
260         switch (vp->v_type) {
261         case VDIR:
262                 /* FALLTHROUGH */
263         case VLNK:
264                 /* FALLTHROUGH */
265         case VREG:
266                 if ((v->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
267                         error = EROFS;
268                         goto out;
269                 }
270                 break;
271
272         case VBLK:
273                 /* FALLTHROUGH */
274         case VCHR:
275                 /* FALLTHROUGH */
276         case VSOCK:
277                 /* FALLTHROUGH */
278         case VFIFO:
279                 break;
280
281         default:
282                 error = EINVAL;
283                 goto out;
284         }
285
286         if ((v->a_mode & VWRITE) && (node->tn_flags & IMMUTABLE)) {
287                 error = EPERM;
288                 goto out;
289         }
290
291         error = vop_helper_access(v, node->tn_uid, node->tn_gid, node->tn_mode, 0);
292
293 out:
294
295         return error;
296 }
297
298 /* --------------------------------------------------------------------- */
299
300 int
301 tmpfs_getattr(struct vop_getattr_args *v)
302 {
303         struct vnode *vp = v->a_vp;
304         struct vattr *vap = v->a_vap;
305         struct tmpfs_node *node;
306
307         node = VP_TO_TMPFS_NODE(vp);
308
309         lwkt_gettoken(&vp->v_mount->mnt_token);
310         tmpfs_update(vp);
311
312         vap->va_type = vp->v_type;
313         vap->va_mode = node->tn_mode;
314         vap->va_nlink = node->tn_links;
315         vap->va_uid = node->tn_uid;
316         vap->va_gid = node->tn_gid;
317         vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
318         vap->va_fileid = node->tn_id;
319         vap->va_size = node->tn_size;
320         vap->va_blocksize = PAGE_SIZE;
321         vap->va_atime.tv_sec = node->tn_atime;
322         vap->va_atime.tv_nsec = node->tn_atimensec;
323         vap->va_mtime.tv_sec = node->tn_mtime;
324         vap->va_mtime.tv_nsec = node->tn_mtimensec;
325         vap->va_ctime.tv_sec = node->tn_ctime;
326         vap->va_ctime.tv_nsec = node->tn_ctimensec;
327         vap->va_gen = node->tn_gen;
328         vap->va_flags = node->tn_flags;
329         if (vp->v_type == VBLK || vp->v_type == VCHR)
330         {
331                 vap->va_rmajor = umajor(node->tn_rdev);
332                 vap->va_rminor = uminor(node->tn_rdev);
333         }
334         vap->va_bytes = round_page(node->tn_size);
335         vap->va_filerev = 0;
336
337         lwkt_reltoken(&vp->v_mount->mnt_token);
338
339         return 0;
340 }
341
342 /* --------------------------------------------------------------------- */
343
344 int
345 tmpfs_setattr(struct vop_setattr_args *v)
346 {
347         struct vnode *vp = v->a_vp;
348         struct vattr *vap = v->a_vap;
349         struct ucred *cred = v->a_cred;
350         struct tmpfs_node *node = VP_TO_TMPFS_NODE(vp);
351         int error = 0;
352         int kflags = 0;
353
354         if (error == 0 && (vap->va_flags != VNOVAL)) {
355                 error = tmpfs_chflags(vp, vap->va_flags, cred);
356                 kflags |= NOTE_ATTRIB;
357         }
358
359         if (error == 0 && (vap->va_size != VNOVAL)) {
360                 if (vap->va_size > node->tn_size)
361                         kflags |= NOTE_WRITE | NOTE_EXTEND;
362                 else
363                         kflags |= NOTE_WRITE;
364                 error = tmpfs_chsize(vp, vap->va_size, cred);
365         }
366
367         if (error == 0 && (vap->va_uid != (uid_t)VNOVAL ||
368                            vap->va_gid != (gid_t)VNOVAL)) {
369                 error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred);
370                 kflags |= NOTE_ATTRIB;
371         }
372
373         if (error == 0 && (vap->va_mode != (mode_t)VNOVAL)) {
374                 error = tmpfs_chmod(vp, vap->va_mode, cred);
375                 kflags |= NOTE_ATTRIB;
376         }
377
378         if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&
379             vap->va_atime.tv_nsec != VNOVAL) ||
380             (vap->va_mtime.tv_sec != VNOVAL &&
381             vap->va_mtime.tv_nsec != VNOVAL) )) {
382                 error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,
383                                       vap->va_vaflags, cred);
384                 kflags |= NOTE_ATTRIB;
385         }
386
387         /* Update the node times.  We give preference to the error codes
388          * generated by this function rather than the ones that may arise
389          * from tmpfs_update. */
390         tmpfs_update(vp);
391         tmpfs_knote(vp, kflags);
392
393         return error;
394 }
395
396 /* --------------------------------------------------------------------- */
397
398 /*
399  * fsync is usually a NOP, but we must take action when unmounting or
400  * when recycling.
401  */
402 static int
403 tmpfs_fsync(struct vop_fsync_args *v)
404 {
405         struct tmpfs_mount *tmp;
406         struct tmpfs_node *node;
407         struct vnode *vp = v->a_vp;
408
409         tmp = VFS_TO_TMPFS(vp->v_mount);
410         node = VP_TO_TMPFS_NODE(vp);
411
412         tmpfs_update(vp);
413         if (vp->v_type == VREG) {
414                 if (vp->v_flag & VRECLAIMED) {
415                         if (node->tn_links == 0)
416                                 tmpfs_truncate(vp, 0);
417                         else
418                                 vfsync(v->a_vp, v->a_waitfor, 1, NULL, NULL);
419                 }
420         }
421         return 0;
422 }
423
424 /* --------------------------------------------------------------------- */
425
426 static int
427 tmpfs_read (struct vop_read_args *ap)
428 {
429         struct buf *bp;
430         struct vnode *vp = ap->a_vp;
431         struct uio *uio = ap->a_uio;
432         struct tmpfs_node *node;
433         off_t base_offset;
434         size_t offset;
435         size_t len;
436         int error;
437
438         error = 0;
439         if (uio->uio_resid == 0) {
440                 return error;
441         }
442
443         node = VP_TO_TMPFS_NODE(vp);
444
445         if (uio->uio_offset < 0)
446                 return (EINVAL);
447         if (vp->v_type != VREG)
448                 return (EINVAL);
449
450         while (uio->uio_resid > 0 && uio->uio_offset < node->tn_size) {
451                 /*
452                  * Use buffer cache I/O (via tmpfs_strategy)
453                  */
454                 offset = (size_t)uio->uio_offset & BMASK;
455                 base_offset = (off_t)uio->uio_offset - offset;
456                 bp = getcacheblk(vp, base_offset, BSIZE);
457                 if (bp == NULL)
458                 {
459                         lwkt_gettoken(&vp->v_mount->mnt_token);
460                         error = bread(vp, base_offset, BSIZE, &bp);
461                         if (error) {
462                                 brelse(bp);
463                                 lwkt_reltoken(&vp->v_mount->mnt_token);
464                                 kprintf("tmpfs_read bread error %d\n", error);
465                                 break;
466                         }
467                         lwkt_reltoken(&vp->v_mount->mnt_token);
468                 }
469
470                 /*
471                  * Figure out how many bytes we can actually copy this loop.
472                  */
473                 len = BSIZE - offset;
474                 if (len > uio->uio_resid)
475                         len = uio->uio_resid;
476                 if (len > node->tn_size - uio->uio_offset)
477                         len = (size_t)(node->tn_size - uio->uio_offset);
478
479                 error = uiomove((char *)bp->b_data + offset, len, uio);
480                 bqrelse(bp);
481                 if (error) {
482                         kprintf("tmpfs_read uiomove error %d\n", error);
483                         break;
484                 }
485         }
486
487         TMPFS_NODE_LOCK(node);
488         node->tn_status |= TMPFS_NODE_ACCESSED;
489         TMPFS_NODE_UNLOCK(node);
490
491         return(error);
492 }
493
494 static int
495 tmpfs_write (struct vop_write_args *ap)
496 {
497         struct buf *bp;
498         struct vnode *vp = ap->a_vp;
499         struct uio *uio = ap->a_uio;
500         struct thread *td = uio->uio_td;
501         struct tmpfs_node *node;
502         boolean_t extended;
503         off_t oldsize;
504         int error;
505         off_t base_offset;
506         size_t offset;
507         size_t len;
508         struct rlimit limit;
509         int trivial = 0;
510         int kflags = 0;
511
512         error = 0;
513         if (uio->uio_resid == 0) {
514                 return error;
515         }
516
517         node = VP_TO_TMPFS_NODE(vp);
518
519         if (vp->v_type != VREG)
520                 return (EINVAL);
521
522         lwkt_gettoken(&vp->v_mount->mnt_token);
523
524         oldsize = node->tn_size;
525         if (ap->a_ioflag & IO_APPEND)
526                 uio->uio_offset = node->tn_size;
527
528         /*
529          * Check for illegal write offsets.
530          */
531         if (uio->uio_offset + uio->uio_resid >
532           VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) {
533                 lwkt_reltoken(&vp->v_mount->mnt_token);
534                 return (EFBIG);
535         }
536
537         if (vp->v_type == VREG && td != NULL) {
538                 error = kern_getrlimit(RLIMIT_FSIZE, &limit);
539                 if (error != 0) {
540                         lwkt_reltoken(&vp->v_mount->mnt_token);
541                         return error;
542                 }
543                 if (uio->uio_offset + uio->uio_resid > limit.rlim_cur) {
544                         ksignal(td->td_proc, SIGXFSZ);
545                         lwkt_reltoken(&vp->v_mount->mnt_token);
546                         return (EFBIG);
547                 }
548         }
549
550
551         /*
552          * Extend the file's size if necessary
553          */
554         extended = ((uio->uio_offset + uio->uio_resid) > node->tn_size);
555
556         while (uio->uio_resid > 0) {
557                 /*
558                  * Use buffer cache I/O (via tmpfs_strategy)
559                  */
560                 offset = (size_t)uio->uio_offset & BMASK;
561                 base_offset = (off_t)uio->uio_offset - offset;
562                 len = BSIZE - offset;
563                 if (len > uio->uio_resid)
564                         len = uio->uio_resid;
565
566                 if ((uio->uio_offset + len) > node->tn_size) {
567                         trivial = (uio->uio_offset <= node->tn_size);
568                         error = tmpfs_reg_resize(vp, uio->uio_offset + len,  trivial);
569                         if (error)
570                                 break;
571                 }
572
573                 /*
574                  * Read to fill in any gaps.  Theoretically we could
575                  * optimize this if the write covers the entire buffer
576                  * and is not a UIO_NOCOPY write, however this can lead
577                  * to a security violation exposing random kernel memory
578                  * (whatever junk was in the backing VM pages before).
579                  *
580                  * So just use bread() to do the right thing.
581                  */
582                 error = bread(vp, base_offset, BSIZE, &bp);
583                 error = uiomove((char *)bp->b_data + offset, len, uio);
584                 if (error) {
585                         kprintf("tmpfs_write uiomove error %d\n", error);
586                         brelse(bp);
587                         break;
588                 }
589
590                 if (uio->uio_offset > node->tn_size) {
591                         node->tn_size = uio->uio_offset;
592                         kflags |= NOTE_EXTEND;
593                 }
594                 kflags |= NOTE_WRITE;
595
596                 /*
597                  * Always try to flush the page if the request is coming
598                  * from the pageout daemon (IO_ASYNC), else buwrite() the
599                  * buffer.
600                  *
601                  * buwrite() dirties the underlying VM pages instead of
602                  * dirtying the buffer, releasing the buffer as a clean
603                  * buffer.  This allows tmpfs to use essentially all
604                  * available memory to cache file data.  If we used bdwrite()
605                  * the buffer cache would wind up flushing the data to
606                  * swap too quickly.
607                  */
608                 bp->b_flags |= B_AGE;
609                 if (ap->a_ioflag & IO_ASYNC) {
610                         bawrite(bp);
611                 } else {
612                         buwrite(bp);
613                 }
614
615                 if (bp->b_error) {
616                         kprintf("tmpfs_write bwrite error %d\n", bp->b_error);
617                         break;
618                 }
619         }
620
621         if (error) {
622                 if (extended) {
623                         (void)tmpfs_reg_resize(vp, oldsize, trivial);
624                         kflags &= ~NOTE_EXTEND;
625                 }
626                 goto done;
627         }
628
629         /*
630          * Currently we don't set the mtime on files modified via mmap()
631          * because we can't tell the difference between those modifications
632          * and an attempt by the pageout daemon to flush tmpfs pages to
633          * swap.
634          *
635          * This is because in order to defer flushes as long as possible
636          * buwrite() works by marking the underlying VM pages dirty in
637          * order to be able to dispose of the buffer cache buffer without
638          * flushing it.
639          */
640         TMPFS_NODE_LOCK(node);
641         if (uio->uio_segflg != UIO_NOCOPY)
642                 node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED;
643         if (extended)
644                 node->tn_status |= TMPFS_NODE_CHANGED;
645
646         if (node->tn_mode & (S_ISUID | S_ISGID)) {
647                 if (priv_check_cred(ap->a_cred, PRIV_VFS_RETAINSUGID, 0))
648                         node->tn_mode &= ~(S_ISUID | S_ISGID);
649         }
650         TMPFS_NODE_UNLOCK(node);
651 done:
652
653         tmpfs_knote(vp, kflags);
654
655
656         lwkt_reltoken(&vp->v_mount->mnt_token);
657         return(error);
658 }
659
660 static int
661 tmpfs_advlock (struct vop_advlock_args *ap)
662 {
663         struct tmpfs_node *node;
664         struct vnode *vp = ap->a_vp;
665
666         node = VP_TO_TMPFS_NODE(vp);
667
668         return (lf_advlock(ap, &node->tn_advlock, node->tn_size));
669 }
670
671 /*
672  * The strategy function is typically only called when memory pressure
673  * forces the system to attempt to pageout pages.  It can also be called
674  * by [n]vtruncbuf() when a truncation cuts a page in half.  Normal write
675  * operations
676  */
677 static int
678 tmpfs_strategy(struct vop_strategy_args *ap)
679 {
680         struct bio *bio = ap->a_bio;
681         struct bio *nbio;
682         struct buf *bp = bio->bio_buf;
683         struct vnode *vp = ap->a_vp;
684         struct tmpfs_node *node;
685         vm_object_t uobj;
686         vm_page_t m;
687         int i;
688
689         if (vp->v_type != VREG) {
690                 bp->b_resid = bp->b_bcount;
691                 bp->b_flags |= B_ERROR | B_INVAL;
692                 bp->b_error = EINVAL;
693                 biodone(bio);
694                 return(0);
695         }
696
697         lwkt_gettoken(&vp->v_mount->mnt_token);
698         node = VP_TO_TMPFS_NODE(vp);
699
700         uobj = node->tn_reg.tn_aobj;
701
702         /*
703          * Don't bother flushing to swap if there is no swap, just
704          * ensure that the pages are marked as needing a commit (still).
705          */
706         if (bp->b_cmd == BUF_CMD_WRITE && vm_swap_size == 0) {
707                 for (i = 0; i < bp->b_xio.xio_npages; ++i) {
708                         m = bp->b_xio.xio_pages[i];
709                         vm_page_need_commit(m);
710                 }
711                 bp->b_resid = 0;
712                 bp->b_error = 0;
713                 biodone(bio);
714         } else {
715                 nbio = push_bio(bio);
716                 nbio->bio_done = tmpfs_strategy_done;
717                 nbio->bio_offset = bio->bio_offset;
718                 swap_pager_strategy(uobj, nbio);
719         }
720
721         lwkt_reltoken(&vp->v_mount->mnt_token);
722         return 0;
723 }
724
725 /*
726  * If we were unable to commit the pages to swap make sure they are marked
727  * as needing a commit (again).  If we were, clear the flag to allow the
728  * pages to be freed.
729  */
730 static void
731 tmpfs_strategy_done(struct bio *bio)
732 {
733         struct buf *bp;
734         vm_page_t m;
735         int i;
736
737         bp = bio->bio_buf;
738
739         if (bp->b_flags & B_ERROR) {
740                 bp->b_flags &= ~B_ERROR;
741                 bp->b_error = 0;
742                 bp->b_resid = 0;
743                 for (i = 0; i < bp->b_xio.xio_npages; ++i) {
744                         m = bp->b_xio.xio_pages[i];
745                         vm_page_need_commit(m);
746                 }
747         } else {
748                 for (i = 0; i < bp->b_xio.xio_npages; ++i) {
749                         m = bp->b_xio.xio_pages[i];
750                         vm_page_clear_commit(m);
751                 }
752         }
753         bio = pop_bio(bio);
754         biodone(bio);
755 }
756
757 static int
758 tmpfs_bmap(struct vop_bmap_args *ap)
759 {
760         if (ap->a_doffsetp != NULL)
761                 *ap->a_doffsetp = ap->a_loffset;
762         if (ap->a_runp != NULL)
763                 *ap->a_runp = 0;
764         if (ap->a_runb != NULL)
765                 *ap->a_runb = 0;
766
767         return 0;
768 }
769
770 /* --------------------------------------------------------------------- */
771
772 static int
773 tmpfs_nremove(struct vop_nremove_args *v)
774 {
775         struct vnode *dvp = v->a_dvp;
776         struct namecache *ncp = v->a_nch->ncp;
777         struct vnode *vp;
778         int error;
779         struct tmpfs_dirent *de;
780         struct tmpfs_mount *tmp;
781         struct tmpfs_node *dnode;
782         struct tmpfs_node *node;
783
784         /*
785          * We have to acquire the vp from v->a_nch because we will likely
786          * unresolve the namecache entry, and a vrele/vput is needed to
787          * trigger the tmpfs_inactive/tmpfs_reclaim sequence.
788          *
789          * We have to use vget to clear any inactive state on the vnode,
790          * otherwise the vnode may remain inactive and thus tmpfs_inactive
791          * will not get called when we release it.
792          */
793         error = cache_vget(v->a_nch, v->a_cred, LK_SHARED, &vp);
794         KKASSERT(error == 0);
795         vn_unlock(vp);
796
797         if (vp->v_type == VDIR) {
798                 error = EISDIR;
799                 goto out;
800         }
801
802         dnode = VP_TO_TMPFS_DIR(dvp);
803         node = VP_TO_TMPFS_NODE(vp);
804         tmp = VFS_TO_TMPFS(vp->v_mount);
805         de = tmpfs_dir_lookup(dnode, node, ncp);
806         if (de == NULL) {
807                 error = ENOENT;
808                 goto out;
809         }
810
811         /* Files marked as immutable or append-only cannot be deleted. */
812         if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
813             (dnode->tn_flags & APPEND)) {
814                 error = EPERM;
815                 goto out;
816         }
817
818         /* Remove the entry from the directory; as it is a file, we do not
819          * have to change the number of hard links of the directory. */
820         tmpfs_dir_detach(dnode, de);
821
822         /* Free the directory entry we just deleted.  Note that the node
823          * referred by it will not be removed until the vnode is really
824          * reclaimed. */
825         tmpfs_free_dirent(tmp, de);
826
827         if (node->tn_links > 0) {
828                 TMPFS_NODE_LOCK(node);
829                 node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
830                         TMPFS_NODE_MODIFIED;
831                 TMPFS_NODE_UNLOCK(node);
832         }
833
834         cache_setunresolved(v->a_nch);
835         cache_setvp(v->a_nch, NULL);
836         tmpfs_knote(vp, NOTE_DELETE);
837         /*cache_inval_vp(vp, CINV_DESTROY);*/
838         tmpfs_knote(dvp, NOTE_WRITE);
839         error = 0;
840
841 out:
842         vrele(vp);
843
844         return error;
845 }
846
847 /* --------------------------------------------------------------------- */
848
849 static int
850 tmpfs_nlink(struct vop_nlink_args *v)
851 {
852         struct vnode *dvp = v->a_dvp;
853         struct vnode *vp = v->a_vp;
854         struct namecache *ncp = v->a_nch->ncp;
855         struct tmpfs_dirent *de;
856         struct tmpfs_node *node;
857         struct tmpfs_node *dnode;
858         int error;
859
860         KKASSERT(dvp != vp); /* XXX When can this be false? */
861
862         node = VP_TO_TMPFS_NODE(vp);
863         dnode = VP_TO_TMPFS_NODE(dvp);
864
865         /* XXX: Why aren't the following two tests done by the caller? */
866
867         /* Hard links of directories are forbidden. */
868         if (vp->v_type == VDIR) {
869                 error = EPERM;
870                 goto out;
871         }
872
873         /* Cannot create cross-device links. */
874         if (dvp->v_mount != vp->v_mount) {
875                 error = EXDEV;
876                 goto out;
877         }
878
879         /* Ensure that we do not overflow the maximum number of links imposed
880          * by the system. */
881         KKASSERT(node->tn_links <= LINK_MAX);
882         if (node->tn_links == LINK_MAX) {
883                 error = EMLINK;
884                 goto out;
885         }
886
887         /* We cannot create links of files marked immutable or append-only. */
888         if (node->tn_flags & (IMMUTABLE | APPEND)) {
889                 error = EPERM;
890                 goto out;
891         }
892
893         /* Allocate a new directory entry to represent the node. */
894         error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node,
895             ncp->nc_name, ncp->nc_nlen, &de);
896         if (error != 0)
897                 goto out;
898
899         /* Insert the new directory entry into the appropriate directory. */
900         tmpfs_dir_attach(dnode, de);
901
902         /* vp link count has changed, so update node times. */
903
904         TMPFS_NODE_LOCK(node);
905         node->tn_status |= TMPFS_NODE_CHANGED;
906         TMPFS_NODE_UNLOCK(node);
907         tmpfs_update(vp);
908
909         tmpfs_knote(vp, NOTE_LINK);
910         cache_setunresolved(v->a_nch);
911         cache_setvp(v->a_nch, vp);
912         tmpfs_knote(dvp, NOTE_WRITE);
913         error = 0;
914
915 out:
916         return error;
917 }
918
919 /* --------------------------------------------------------------------- */
920
921 static int
922 tmpfs_nrename(struct vop_nrename_args *v)
923 {
924         struct vnode *fdvp = v->a_fdvp;
925         struct namecache *fncp = v->a_fnch->ncp;
926         struct vnode *fvp = fncp->nc_vp;
927         struct vnode *tdvp = v->a_tdvp;
928         struct namecache *tncp = v->a_tnch->ncp;
929         struct vnode *tvp;
930         struct tmpfs_dirent *de;
931         struct tmpfs_mount *tmp;
932         struct tmpfs_node *fdnode;
933         struct tmpfs_node *fnode;
934         struct tmpfs_node *tnode;
935         struct tmpfs_node *tdnode;
936         char *newname;
937         char *oldname;
938         int error;
939
940         /*
941          * Because tvp can get overwritten we have to vget it instead of
942          * just vref or use it, otherwise it's VINACTIVE flag may not get
943          * cleared and the node won't get destroyed.
944          */
945         error = cache_vget(v->a_tnch, v->a_cred, LK_SHARED, &tvp);
946         if (error == 0) {
947                 tnode = VP_TO_TMPFS_NODE(tvp);
948                 vn_unlock(tvp);
949         } else {
950                 tnode = NULL;
951         }
952
953         /* Disallow cross-device renames.
954          * XXX Why isn't this done by the caller? */
955         if (fvp->v_mount != tdvp->v_mount ||
956             (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
957                 error = EXDEV;
958                 goto out;
959         }
960
961         tmp = VFS_TO_TMPFS(tdvp->v_mount);
962         tdnode = VP_TO_TMPFS_DIR(tdvp);
963
964         /* If source and target are the same file, there is nothing to do. */
965         if (fvp == tvp) {
966                 error = 0;
967                 goto out;
968         }
969
970         fdnode = VP_TO_TMPFS_DIR(fdvp);
971         fnode = VP_TO_TMPFS_NODE(fvp);
972         de = tmpfs_dir_lookup(fdnode, fnode, fncp);
973
974         /* Avoid manipulating '.' and '..' entries. */
975         if (de == NULL) {
976                 error = ENOENT;
977                 goto out_locked;
978         }
979         KKASSERT(de->td_node == fnode);
980
981         /*
982          * If replacing an entry in the target directory and that entry
983          * is a directory, it must be empty.
984          *
985          * Kern_rename gurantees the destination to be a directory
986          * if the source is one (it does?).
987          */
988         if (tvp != NULL) {
989                 KKASSERT(tnode != NULL);
990
991                 if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
992                     (tdnode->tn_flags & (APPEND | IMMUTABLE))) {
993                         error = EPERM;
994                         goto out_locked;
995                 }
996
997                 if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
998                         if (tnode->tn_size > 0) {
999                                 error = ENOTEMPTY;
1000                                 goto out_locked;
1001                         }
1002                 } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
1003                         error = ENOTDIR;
1004                         goto out_locked;
1005                 } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
1006                         error = EISDIR;
1007                         goto out_locked;
1008                 } else {
1009                         KKASSERT(fnode->tn_type != VDIR &&
1010                                 tnode->tn_type != VDIR);
1011                 }
1012         }
1013
1014         if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
1015             (fdnode->tn_flags & (APPEND | IMMUTABLE))) {
1016                 error = EPERM;
1017                 goto out_locked;
1018         }
1019
1020         /*
1021          * Ensure that we have enough memory to hold the new name, if it
1022          * has to be changed.
1023          */
1024         if (fncp->nc_nlen != tncp->nc_nlen ||
1025             bcmp(fncp->nc_name, tncp->nc_name, fncp->nc_nlen) != 0) {
1026                 newname = kmalloc(tncp->nc_nlen + 1, tmp->tm_name_zone, 
1027                                   M_WAITOK | M_NULLOK);
1028                 if (newname == NULL) {
1029                         error = ENOSPC;
1030                         goto out_locked;
1031                 }
1032                 bcopy(tncp->nc_name, newname, tncp->nc_nlen);
1033                 newname[tncp->nc_nlen] = '\0';
1034         } else {
1035                 newname = NULL;
1036         }
1037
1038         /*
1039          * Unlink entry from source directory.  Note that the kernel has
1040          * already checked for illegal recursion cases (renaming a directory
1041          * into a subdirectory of itself).
1042          */
1043         if (fdnode != tdnode)
1044                 tmpfs_dir_detach(fdnode, de);
1045
1046         /*
1047          * Handle any name change.  Swap with newname, we will
1048          * deallocate it at the end.
1049          */
1050         if (newname != NULL) {
1051 #if 0
1052                 TMPFS_NODE_LOCK(fnode);
1053                 fnode->tn_status |= TMPFS_NODE_CHANGED;
1054                 TMPFS_NODE_UNLOCK(fnode);
1055 #endif
1056                 oldname = de->td_name;
1057                 de->td_name = newname;
1058                 de->td_namelen = (uint16_t)tncp->nc_nlen;
1059                 newname = oldname;
1060         }
1061
1062         /*
1063          * Link entry to target directory.  If the entry
1064          * represents a directory move the parent linkage
1065          * as well.
1066          */
1067         if (fdnode != tdnode) {
1068                 if (de->td_node->tn_type == VDIR) {
1069                         TMPFS_VALIDATE_DIR(fnode);
1070
1071                         TMPFS_NODE_LOCK(tdnode);
1072                         tdnode->tn_links++;
1073                         tdnode->tn_status |= TMPFS_NODE_MODIFIED;
1074                         TMPFS_NODE_UNLOCK(tdnode);
1075
1076                         TMPFS_NODE_LOCK(fnode);
1077                         fnode->tn_dir.tn_parent = tdnode;
1078                         fnode->tn_status |= TMPFS_NODE_CHANGED;
1079                         TMPFS_NODE_UNLOCK(fnode);
1080
1081                         TMPFS_NODE_LOCK(fdnode);
1082                         fdnode->tn_links--;
1083                         fdnode->tn_status |= TMPFS_NODE_MODIFIED;
1084                         TMPFS_NODE_UNLOCK(fdnode);
1085                 }
1086                 tmpfs_dir_attach(tdnode, de);
1087         } else {
1088                 TMPFS_NODE_LOCK(tdnode);
1089                 tdnode->tn_status |= TMPFS_NODE_MODIFIED;
1090                 TMPFS_NODE_UNLOCK(tdnode);
1091         }
1092
1093         /*
1094          * If we are overwriting an entry, we have to remove the old one
1095          * from the target directory.
1096          */
1097         if (tvp != NULL) {
1098                 /* Remove the old entry from the target directory. */
1099                 de = tmpfs_dir_lookup(tdnode, tnode, tncp);
1100                 tmpfs_dir_detach(tdnode, de);
1101                 tmpfs_knote(tdnode->tn_vnode, NOTE_DELETE);
1102
1103                 /*
1104                  * Free the directory entry we just deleted.  Note that the
1105                  * node referred by it will not be removed until the vnode is
1106                  * really reclaimed.
1107                  */
1108                 tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de);
1109                 /*cache_inval_vp(tvp, CINV_DESTROY);*/
1110         }
1111
1112         /*
1113          * Finish up
1114          */
1115         if (newname) {
1116                 kfree(newname, tmp->tm_name_zone);
1117                 newname = NULL;
1118         }
1119         cache_rename(v->a_fnch, v->a_tnch);
1120         tmpfs_knote(v->a_fdvp, NOTE_WRITE);
1121         tmpfs_knote(v->a_tdvp, NOTE_WRITE);
1122         if (fnode->tn_vnode)
1123                 tmpfs_knote(fnode->tn_vnode, NOTE_RENAME);
1124         error = 0;
1125
1126 out_locked:
1127         ;
1128
1129 out:
1130         if (tvp)
1131                 vrele(tvp);
1132
1133         return error;
1134 }
1135
1136 /* --------------------------------------------------------------------- */
1137
1138 static int
1139 tmpfs_nmkdir(struct vop_nmkdir_args *v)
1140 {
1141         struct vnode *dvp = v->a_dvp;
1142         struct vnode **vpp = v->a_vpp;
1143         struct namecache *ncp = v->a_nch->ncp;
1144         struct vattr *vap = v->a_vap;
1145         struct ucred *cred = v->a_cred;
1146         int error;
1147
1148         KKASSERT(vap->va_type == VDIR);
1149
1150         error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, NULL);
1151         if (error == 0) {
1152                 cache_setunresolved(v->a_nch);
1153                 cache_setvp(v->a_nch, *vpp);
1154                 tmpfs_knote(dvp, NOTE_WRITE | NOTE_LINK);
1155         }
1156
1157         return error;
1158 }
1159
1160 /* --------------------------------------------------------------------- */
1161
1162 static int
1163 tmpfs_nrmdir(struct vop_nrmdir_args *v)
1164 {
1165         struct vnode *dvp = v->a_dvp;
1166         struct namecache *ncp = v->a_nch->ncp;
1167         struct vnode *vp;
1168         struct tmpfs_dirent *de;
1169         struct tmpfs_mount *tmp;
1170         struct tmpfs_node *dnode;
1171         struct tmpfs_node *node;
1172         int error;
1173
1174         /*
1175          * We have to acquire the vp from v->a_nch because we will likely
1176          * unresolve the namecache entry, and a vrele/vput is needed to
1177          * trigger the tmpfs_inactive/tmpfs_reclaim sequence.
1178          *
1179          * We have to use vget to clear any inactive state on the vnode,
1180          * otherwise the vnode may remain inactive and thus tmpfs_inactive
1181          * will not get called when we release it.
1182          */
1183         error = cache_vget(v->a_nch, v->a_cred, LK_SHARED, &vp);
1184         KKASSERT(error == 0);
1185         vn_unlock(vp);
1186
1187         /*
1188          * Prevalidate so we don't hit an assertion later
1189          */
1190         if (vp->v_type != VDIR) {
1191                 error = ENOTDIR;
1192                 goto out;
1193         }
1194
1195         tmp = VFS_TO_TMPFS(dvp->v_mount);
1196         dnode = VP_TO_TMPFS_DIR(dvp);
1197         node = VP_TO_TMPFS_DIR(vp);
1198
1199         /* Directories with more than two entries ('.' and '..') cannot be
1200          * removed. */
1201          if (node->tn_size > 0) {
1202                  error = ENOTEMPTY;
1203                  goto out;
1204          }
1205
1206         if ((dnode->tn_flags & APPEND)
1207             || (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1208                 error = EPERM;
1209                 goto out;
1210         }
1211
1212         /* This invariant holds only if we are not trying to remove "..".
1213           * We checked for that above so this is safe now. */
1214         KKASSERT(node->tn_dir.tn_parent == dnode);
1215
1216         /* Get the directory entry associated with node (vp).  This was
1217          * filled by tmpfs_lookup while looking up the entry. */
1218         de = tmpfs_dir_lookup(dnode, node, ncp);
1219         KKASSERT(TMPFS_DIRENT_MATCHES(de,
1220             ncp->nc_name,
1221             ncp->nc_nlen));
1222
1223         /* Check flags to see if we are allowed to remove the directory. */
1224         if ((dnode->tn_flags & APPEND) ||
1225             node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) {
1226                 error = EPERM;
1227                 goto out;
1228         }
1229
1230
1231         /* Detach the directory entry from the directory (dnode). */
1232         tmpfs_dir_detach(dnode, de);
1233
1234         /* No vnode should be allocated for this entry from this point */
1235         TMPFS_NODE_LOCK(node);
1236         TMPFS_ASSERT_ELOCKED(node);
1237         TMPFS_NODE_LOCK(dnode);
1238         TMPFS_ASSERT_ELOCKED(dnode);
1239
1240 #if 0
1241         /* handled by tmpfs_free_node */
1242         KKASSERT(node->tn_links > 0);
1243         node->tn_links--;
1244         node->tn_dir.tn_parent = NULL;
1245 #endif
1246         node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
1247             TMPFS_NODE_MODIFIED;
1248
1249 #if 0
1250         /* handled by tmpfs_free_node */
1251         KKASSERT(dnode->tn_links > 0);
1252         dnode->tn_links--;
1253 #endif
1254         dnode->tn_status |= TMPFS_NODE_ACCESSED | \
1255             TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED;
1256
1257         TMPFS_NODE_UNLOCK(dnode);
1258         TMPFS_NODE_UNLOCK(node);
1259
1260         /* Free the directory entry we just deleted.  Note that the node
1261          * referred by it will not be removed until the vnode is really
1262          * reclaimed. */
1263         tmpfs_free_dirent(tmp, de);
1264
1265         /* Release the deleted vnode (will destroy the node, notify
1266          * interested parties and clean it from the cache). */
1267
1268         TMPFS_NODE_LOCK(dnode);
1269         dnode->tn_status |= TMPFS_NODE_CHANGED;
1270         TMPFS_NODE_UNLOCK(dnode);
1271         tmpfs_update(dvp);
1272
1273         cache_setunresolved(v->a_nch);
1274         cache_setvp(v->a_nch, NULL);
1275         /*cache_inval_vp(vp, CINV_DESTROY);*/
1276         tmpfs_knote(dvp, NOTE_WRITE | NOTE_LINK);
1277         error = 0;
1278
1279 out:
1280         vrele(vp);
1281
1282         return error;
1283 }
1284
1285 /* --------------------------------------------------------------------- */
1286
1287 static int
1288 tmpfs_nsymlink(struct vop_nsymlink_args *v)
1289 {
1290         struct vnode *dvp = v->a_dvp;
1291         struct vnode **vpp = v->a_vpp;
1292         struct namecache *ncp = v->a_nch->ncp;
1293         struct vattr *vap = v->a_vap;
1294         struct ucred *cred = v->a_cred;
1295         char *target = v->a_target;
1296         int error;
1297
1298         vap->va_type = VLNK;
1299         error = tmpfs_alloc_file(dvp, vpp, vap, ncp, cred, target);
1300         if (error == 0) {
1301                 tmpfs_knote(*vpp, NOTE_WRITE);
1302                 cache_setunresolved(v->a_nch);
1303                 cache_setvp(v->a_nch, *vpp);
1304         }
1305
1306         return error;
1307 }
1308
1309 /* --------------------------------------------------------------------- */
1310
1311 static int
1312 tmpfs_readdir(struct vop_readdir_args *v)
1313 {
1314         struct vnode *vp = v->a_vp;
1315         struct uio *uio = v->a_uio;
1316         int *eofflag = v->a_eofflag;
1317         off_t **cookies = v->a_cookies;
1318         int *ncookies = v->a_ncookies;
1319         struct tmpfs_mount *tmp;
1320         int error;
1321         off_t startoff;
1322         off_t cnt = 0;
1323         struct tmpfs_node *node;
1324
1325         /* This operation only makes sense on directory nodes. */
1326         if (vp->v_type != VDIR)
1327                 return ENOTDIR;
1328
1329         tmp = VFS_TO_TMPFS(vp->v_mount);
1330         node = VP_TO_TMPFS_DIR(vp);
1331         startoff = uio->uio_offset;
1332
1333         if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) {
1334                 error = tmpfs_dir_getdotdent(node, uio);
1335                 if (error != 0)
1336                         goto outok;
1337                 cnt++;
1338         }
1339
1340         if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
1341                 error = tmpfs_dir_getdotdotdent(tmp, node, uio);
1342                 if (error != 0)
1343                         goto outok;
1344                 cnt++;
1345         }
1346
1347         error = tmpfs_dir_getdents(node, uio, &cnt);
1348
1349 outok:
1350         KKASSERT(error >= -1);
1351
1352         if (error == -1)
1353                 error = 0;
1354
1355         if (eofflag != NULL)
1356                 *eofflag =
1357                     (error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
1358
1359         /* Update NFS-related variables. */
1360         if (error == 0 && cookies != NULL && ncookies != NULL) {
1361                 off_t i;
1362                 off_t off = startoff;
1363                 struct tmpfs_dirent *de = NULL;
1364
1365                 *ncookies = cnt;
1366                 *cookies = kmalloc(cnt * sizeof(off_t), M_TEMP, M_WAITOK);
1367
1368                 for (i = 0; i < cnt; i++) {
1369                         KKASSERT(off != TMPFS_DIRCOOKIE_EOF);
1370                         if (off == TMPFS_DIRCOOKIE_DOT) {
1371                                 off = TMPFS_DIRCOOKIE_DOTDOT;
1372                         } else {
1373                                 if (off == TMPFS_DIRCOOKIE_DOTDOT) {
1374                                         de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
1375                                 } else if (de != NULL) {
1376                                         de = TAILQ_NEXT(de, td_entries);
1377                                 } else {
1378                                         de = tmpfs_dir_lookupbycookie(node,
1379                                             off);
1380                                         KKASSERT(de != NULL);
1381                                         de = TAILQ_NEXT(de, td_entries);
1382                                 }
1383                                 if (de == NULL)
1384                                         off = TMPFS_DIRCOOKIE_EOF;
1385                                 else
1386                                         off = tmpfs_dircookie(de);
1387                         }
1388
1389                         (*cookies)[i] = off;
1390                 }
1391                 KKASSERT(uio->uio_offset == off);
1392         }
1393
1394         return error;
1395 }
1396
1397 /* --------------------------------------------------------------------- */
1398
1399 static int
1400 tmpfs_readlink(struct vop_readlink_args *v)
1401 {
1402         struct vnode *vp = v->a_vp;
1403         struct uio *uio = v->a_uio;
1404
1405         int error;
1406         struct tmpfs_node *node;
1407
1408         KKASSERT(uio->uio_offset == 0);
1409         KKASSERT(vp->v_type == VLNK);
1410
1411         node = VP_TO_TMPFS_NODE(vp);
1412
1413         error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid),
1414             uio);
1415         TMPFS_NODE_LOCK(node);
1416         node->tn_status |= TMPFS_NODE_ACCESSED;
1417         TMPFS_NODE_UNLOCK(node);
1418
1419         return error;
1420 }
1421
1422 /* --------------------------------------------------------------------- */
1423
1424 static int
1425 tmpfs_inactive(struct vop_inactive_args *v)
1426 {
1427         struct vnode *vp = v->a_vp;
1428         struct tmpfs_node *node;
1429
1430         node = VP_TO_TMPFS_NODE(vp);
1431
1432         /*
1433          * Degenerate case
1434          */
1435         if (node == NULL) {
1436                 vrecycle(vp);
1437                 return(0);
1438         }
1439
1440         /*
1441          * Get rid of unreferenced deleted vnodes sooner rather than
1442          * later so the data memory can be recovered immediately.
1443          *
1444          * We must truncate the vnode to prevent the normal reclamation
1445          * path from flushing the data for the removed file to disk.
1446          */
1447         TMPFS_NODE_LOCK(node);
1448         if ((node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0 &&
1449             (node->tn_links == 0 ||
1450              (node->tn_links == 1 && node->tn_type == VDIR &&
1451               node->tn_dir.tn_parent)))
1452         {
1453                 node->tn_vpstate = TMPFS_VNODE_DOOMED;
1454                 TMPFS_NODE_UNLOCK(node);
1455                 if (node->tn_type == VREG)
1456                         tmpfs_truncate(vp, 0);
1457                 vrecycle(vp);
1458         } else {
1459                 TMPFS_NODE_UNLOCK(node);
1460         }
1461
1462         return 0;
1463 }
1464
1465 /* --------------------------------------------------------------------- */
1466
1467 int
1468 tmpfs_reclaim(struct vop_reclaim_args *v)
1469 {
1470         struct vnode *vp = v->a_vp;
1471         struct tmpfs_mount *tmp;
1472         struct tmpfs_node *node;
1473
1474         node = VP_TO_TMPFS_NODE(vp);
1475         tmp = VFS_TO_TMPFS(vp->v_mount);
1476
1477         tmpfs_free_vp(vp);
1478
1479         /*
1480          * If the node referenced by this vnode was deleted by the
1481          * user, we must free its associated data structures now that
1482          * the vnode is being reclaimed.
1483          *
1484          * Directories have an extra link ref.
1485          */
1486         TMPFS_NODE_LOCK(node);
1487         if ((node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0 &&
1488             (node->tn_links == 0 ||
1489              (node->tn_links == 1 && node->tn_type == VDIR &&
1490               node->tn_dir.tn_parent)))
1491         {
1492                 node->tn_vpstate = TMPFS_VNODE_DOOMED;
1493                 tmpfs_free_node(tmp, node);
1494                 /* eats the lock */
1495         } else {
1496                 TMPFS_NODE_UNLOCK(node);
1497         }
1498
1499         KKASSERT(vp->v_data == NULL);
1500         return 0;
1501 }
1502
1503 /* --------------------------------------------------------------------- */ 
1504
1505 static int 
1506 tmpfs_mountctl(struct vop_mountctl_args *ap) 
1507
1508         struct tmpfs_mount *tmp; 
1509         struct mount *mp; 
1510         int rc; 
1511
1512         switch (ap->a_op) { 
1513         case (MOUNTCTL_SET_EXPORT): 
1514                 mp = ap->a_head.a_ops->head.vv_mount; 
1515                 tmp = (struct tmpfs_mount *) mp->mnt_data; 
1516  
1517                 if (ap->a_ctllen != sizeof(struct export_args)) 
1518                         rc = (EINVAL); 
1519                 else 
1520                         rc = vfs_export(mp, &tmp->tm_export, 
1521                                         (const struct export_args *) ap->a_ctl); 
1522                 break; 
1523         default: 
1524                 rc = vop_stdmountctl(ap); 
1525                 break; 
1526         } 
1527         return (rc); 
1528
1529
1530 /* --------------------------------------------------------------------- */
1531
1532 static int
1533 tmpfs_print(struct vop_print_args *v)
1534 {
1535         struct vnode *vp = v->a_vp;
1536
1537         struct tmpfs_node *node;
1538
1539         node = VP_TO_TMPFS_NODE(vp);
1540
1541         kprintf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n",
1542             node, node->tn_flags, node->tn_links);
1543         kprintf("\tmode 0%o, owner %d, group %d, size %ju, status 0x%x\n",
1544             node->tn_mode, node->tn_uid, node->tn_gid,
1545             (uintmax_t)node->tn_size, node->tn_status);
1546
1547         if (vp->v_type == VFIFO)
1548                 fifo_printinfo(vp);
1549
1550         kprintf("\n");
1551
1552         return 0;
1553 }
1554
1555 /* --------------------------------------------------------------------- */
1556
1557 static int
1558 tmpfs_pathconf(struct vop_pathconf_args *v)
1559 {
1560         int name = v->a_name;
1561         register_t *retval = v->a_retval;
1562
1563         int error;
1564
1565         error = 0;
1566
1567         switch (name) {
1568         case _PC_LINK_MAX:
1569                 *retval = LINK_MAX;
1570                 break;
1571
1572         case _PC_NAME_MAX:
1573                 *retval = NAME_MAX;
1574                 break;
1575
1576         case _PC_PATH_MAX:
1577                 *retval = PATH_MAX;
1578                 break;
1579
1580         case _PC_PIPE_BUF:
1581                 *retval = PIPE_BUF;
1582                 break;
1583
1584         case _PC_CHOWN_RESTRICTED:
1585                 *retval = 1;
1586                 break;
1587
1588         case _PC_NO_TRUNC:
1589                 *retval = 1;
1590                 break;
1591
1592         case _PC_SYNC_IO:
1593                 *retval = 1;
1594                 break;
1595
1596         case _PC_FILESIZEBITS:
1597                 *retval = 0; /* XXX Don't know which value should I return. */
1598                 break;
1599
1600         default:
1601                 error = EINVAL;
1602         }
1603
1604         return error;
1605 }
1606
1607 /************************************************************************
1608  *                          KQFILTER OPS                                *
1609  ************************************************************************/
1610
1611 static void filt_tmpfsdetach(struct knote *kn);
1612 static int filt_tmpfsread(struct knote *kn, long hint);
1613 static int filt_tmpfswrite(struct knote *kn, long hint);
1614 static int filt_tmpfsvnode(struct knote *kn, long hint);
1615
1616 static struct filterops tmpfsread_filtops =
1617         { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfsread };
1618 static struct filterops tmpfswrite_filtops =
1619         { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfswrite };
1620 static struct filterops tmpfsvnode_filtops =
1621         { FILTEROP_ISFD, NULL, filt_tmpfsdetach, filt_tmpfsvnode };
1622
1623 static int
1624 tmpfs_kqfilter (struct vop_kqfilter_args *ap)
1625 {
1626         struct vnode *vp = ap->a_vp;
1627         struct knote *kn = ap->a_kn;
1628
1629         switch (kn->kn_filter) {
1630         case EVFILT_READ:
1631                 kn->kn_fop = &tmpfsread_filtops;
1632                 break;
1633         case EVFILT_WRITE:
1634                 kn->kn_fop = &tmpfswrite_filtops;
1635                 break;
1636         case EVFILT_VNODE:
1637                 kn->kn_fop = &tmpfsvnode_filtops;
1638                 break;
1639         default:
1640                 return (EOPNOTSUPP);
1641         }
1642
1643         kn->kn_hook = (caddr_t)vp;
1644
1645         knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1646
1647         return(0);
1648 }
1649
1650 static void
1651 filt_tmpfsdetach(struct knote *kn)
1652 {
1653         struct vnode *vp = (void *)kn->kn_hook;
1654
1655         knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1656 }
1657
1658 static int
1659 filt_tmpfsread(struct knote *kn, long hint)
1660 {
1661         struct vnode *vp = (void *)kn->kn_hook;
1662         struct tmpfs_node *node = VP_TO_TMPFS_NODE(vp);
1663         off_t off;
1664
1665         if (hint == NOTE_REVOKE) {
1666                 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1667                 return(1);
1668         }
1669
1670         /*
1671          * Interlock against MP races when performing this function.
1672          */
1673         lwkt_gettoken(&vp->v_mount->mnt_token);
1674         off = node->tn_size - kn->kn_fp->f_offset;
1675         kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1676         if (kn->kn_sfflags & NOTE_OLDAPI) {
1677                 lwkt_reltoken(&vp->v_mount->mnt_token);
1678                 return(1);
1679         }
1680
1681         if (kn->kn_data == 0) {
1682                 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1683         }
1684         lwkt_reltoken(&vp->v_mount->mnt_token);
1685         return (kn->kn_data != 0);
1686 }
1687
1688 static int
1689 filt_tmpfswrite(struct knote *kn, long hint)
1690 {
1691         if (hint == NOTE_REVOKE)
1692                 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1693         kn->kn_data = 0;
1694         return (1);
1695 }
1696
1697 static int
1698 filt_tmpfsvnode(struct knote *kn, long hint)
1699 {
1700         if (kn->kn_sfflags & hint)
1701                 kn->kn_fflags |= hint;
1702         if (hint == NOTE_REVOKE) {
1703                 kn->kn_flags |= (EV_EOF | EV_NODATA);
1704                 return (1);
1705         }
1706         return (kn->kn_fflags != 0);
1707 }
1708
1709
1710 /* --------------------------------------------------------------------- */
1711
1712 /*
1713  * vnode operations vector used for files stored in a tmpfs file system.
1714  */
1715 struct vop_ops tmpfs_vnode_vops = {
1716         .vop_default =                  vop_defaultop,
1717         .vop_getpages =                 vop_stdgetpages,
1718         .vop_putpages =                 vop_stdputpages,
1719         .vop_ncreate =                  tmpfs_ncreate,
1720         .vop_nresolve =                 tmpfs_nresolve,
1721         .vop_nlookupdotdot =            tmpfs_nlookupdotdot,
1722         .vop_nmknod =                   tmpfs_nmknod,
1723         .vop_open =                     tmpfs_open,
1724         .vop_close =                    tmpfs_close,
1725         .vop_access =                   tmpfs_access,
1726         .vop_getattr =                  tmpfs_getattr,
1727         .vop_setattr =                  tmpfs_setattr,
1728         .vop_read =                     tmpfs_read,
1729         .vop_write =                    tmpfs_write,
1730         .vop_fsync =                    tmpfs_fsync,
1731         .vop_mountctl =                 tmpfs_mountctl,
1732         .vop_nremove =                  tmpfs_nremove,
1733         .vop_nlink =                    tmpfs_nlink,
1734         .vop_nrename =                  tmpfs_nrename,
1735         .vop_nmkdir =                   tmpfs_nmkdir,
1736         .vop_nrmdir =                   tmpfs_nrmdir,
1737         .vop_nsymlink =                 tmpfs_nsymlink,
1738         .vop_readdir =                  tmpfs_readdir,
1739         .vop_readlink =                 tmpfs_readlink,
1740         .vop_inactive =                 tmpfs_inactive,
1741         .vop_reclaim =                  tmpfs_reclaim,
1742         .vop_print =                    tmpfs_print,
1743         .vop_pathconf =                 tmpfs_pathconf,
1744         .vop_bmap =                     tmpfs_bmap,
1745         .vop_strategy =                 tmpfs_strategy,
1746         .vop_advlock =                  tmpfs_advlock,
1747         .vop_kqfilter =                 tmpfs_kqfilter
1748 };