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