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