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