kernel - Refactor GETATTR_QUICK() -> GETATTR_LITE()
[dragonfly.git] / sys / kern / vfs_default.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed
6  * to Berkeley by John Heidemann of the UCLA Ficus project.
7  *
8  * The statvfs->statfs conversion code was contributed to the DragonFly
9  * Project by Joerg Sonnenberger <joerg@bec.de>.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
36  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
37  */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/buf.h>
42 #include <sys/conf.h>
43 #include <sys/fcntl.h>
44 #include <sys/file.h>
45 #include <sys/kernel.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/unistd.h>
50 #include <sys/vnode.h>
51 #include <sys/namei.h>
52 #include <sys/mountctl.h>
53 #include <sys/vfs_quota.h>
54
55 #include <machine/limits.h>
56
57 #include <vm/vm.h>
58 #include <vm/vm_object.h>
59 #include <vm/vm_page.h>
60 #include <vm/vm_pager.h>
61 #include <vm/vnode_pager.h>
62
63 static int      vop_nolookup (struct vop_old_lookup_args *);
64 static int      vop_nostrategy (struct vop_strategy_args *);
65
66 /*
67  * This vnode table stores what we want to do if the filesystem doesn't
68  * implement a particular VOP.
69  *
70  * If there is no specific entry here, we will return EOPNOTSUPP.
71  */
72 struct vop_ops default_vnode_vops = {
73         .vop_default            = vop_eopnotsupp,
74         .vop_advlock            = (void *)vop_einval,
75         .vop_fsync              = (void *)vop_null,
76         .vop_ioctl              = (void *)vop_enotty,
77         .vop_mmap               = (void *)vop_einval,
78         .vop_old_lookup         = vop_nolookup,
79         .vop_open               = vop_stdopen,
80         .vop_close              = vop_stdclose,
81         .vop_getattr_lite       = vop_stdgetattr_lite,
82         .vop_pathconf           = vop_stdpathconf,
83         .vop_readlink           = (void *)vop_einval,
84         .vop_reallocblks        = (void *)vop_eopnotsupp,
85         .vop_strategy           = vop_nostrategy,
86         .vop_getacl             = (void *)vop_eopnotsupp,
87         .vop_setacl             = (void *)vop_eopnotsupp,
88         .vop_aclcheck           = (void *)vop_eopnotsupp,
89         .vop_getextattr         = (void *)vop_eopnotsupp,
90         .vop_setextattr         = (void *)vop_eopnotsupp,
91         .vop_markatime          = vop_stdmarkatime,
92         .vop_nresolve           = vop_compat_nresolve,
93         .vop_nlookupdotdot      = vop_compat_nlookupdotdot,
94         .vop_ncreate            = vop_compat_ncreate,
95         .vop_nmkdir             = vop_compat_nmkdir,
96         .vop_nmknod             = vop_compat_nmknod,
97         .vop_nlink              = vop_compat_nlink,
98         .vop_nsymlink           = vop_compat_nsymlink,
99         .vop_nwhiteout          = vop_compat_nwhiteout,
100         .vop_nremove            = vop_compat_nremove,
101         .vop_nrmdir             = vop_compat_nrmdir,
102         .vop_nrename            = vop_compat_nrename,
103         .vop_mountctl           = vop_stdmountctl
104 };
105
106 VNODEOP_SET(default_vnode_vops);
107
108 int
109 vop_eopnotsupp(struct vop_generic_args *ap)
110 {
111         return (EOPNOTSUPP);
112 }
113
114 int
115 vop_ebadf(struct vop_generic_args *ap)
116 {
117         return (EBADF);
118 }
119
120 int
121 vop_enotty(struct vop_generic_args *ap)
122 {
123         return (ENOTTY);
124 }
125
126 int
127 vop_einval(struct vop_generic_args *ap)
128 {
129         return (EINVAL);
130 }
131
132 int
133 vop_stdmarkatime(struct vop_markatime_args *ap)
134 {
135         return (EOPNOTSUPP);
136 }
137
138 int
139 vop_null(struct vop_generic_args *ap)
140 {
141         return (0);
142 }
143
144 int
145 vop_defaultop(struct vop_generic_args *ap)
146 {
147         return (VOCALL(&default_vnode_vops, ap));
148 }
149
150 /*
151  * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
152  * XXX STOPGAP FUNCTION
153  *
154  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
155  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
156  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a 
157  * vop_old_lookup() and does appropriate translations.
158  *
159  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
160  * VFSs will support this VOP and this routine can be removed, since
161  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
162  * API.
163  *
164  * A locked ncp is passed in to be resolved.  The NCP is resolved by
165  * figuring out the vnode (if any) and calling cache_setvp() to attach the
166  * vnode to the entry.  If the entry represents a non-existant node then
167  * cache_setvp() is called with a NULL vnode to resolve the entry into a
168  * negative cache entry.  No vnode locks are retained and the
169  * ncp is left locked on return.
170  *
171  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
172  *
173  * There is a potential directory and vnode interlock.   The lock order
174  * requirement is: namecache, governing directory, resolved vnode.
175  */
176 int
177 vop_compat_nresolve(struct vop_nresolve_args *ap)
178 {
179         int error;
180         struct vnode *dvp;
181         struct vnode *vp;
182         struct nchandle *nch;
183         struct namecache *ncp;
184         struct componentname cnp;
185
186         nch = ap->a_nch;        /* locked namecache node */
187         ncp = nch->ncp;
188         dvp = ap->a_dvp;
189
190         /*
191          * UFS currently stores all sorts of side effects, including a loop
192          * variable, in the directory inode.  That needs to be fixed and the
193          * other VFS's audited before we can switch to LK_SHARED.
194          */
195         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
196                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
197                         ncp, ncp->nc_name);
198                 return(EAGAIN);
199         }
200
201         bzero(&cnp, sizeof(cnp));
202         cnp.cn_nameiop = NAMEI_LOOKUP;
203         cnp.cn_flags = 0;
204         cnp.cn_nameptr = ncp->nc_name;
205         cnp.cn_namelen = ncp->nc_nlen;
206         cnp.cn_cred = ap->a_cred;
207         cnp.cn_td = curthread; /* XXX */
208
209         /*
210          * vop_old_lookup() always returns vp locked.  dvp may or may not be
211          * left locked depending on CNP_PDIRUNLOCK.
212          */
213         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
214         if (error == 0)
215                 vn_unlock(vp);
216         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
217                 vn_unlock(dvp);
218         if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
219                 /* was resolved by another process while we were unlocked */
220                 if (error == 0)
221                         vrele(vp);
222         } else if (error == 0) {
223                 KKASSERT(vp != NULL);
224                 cache_setvp(nch, vp);
225                 vrele(vp);
226         } else if (error == ENOENT) {
227                 KKASSERT(vp == NULL);
228                 if (cnp.cn_flags & CNP_ISWHITEOUT)
229                         ncp->nc_flag |= NCF_WHITEOUT;
230                 cache_setvp(nch, NULL);
231         }
232         vrele(dvp);
233         return (error);
234 }
235
236 /*
237  * vop_compat_nlookupdotdot { struct vnode *a_dvp,
238  *                      struct vnode **a_vpp,
239  *                      struct ucred *a_cred }
240  *
241  * Lookup the vnode representing the parent directory of the specified
242  * directory vnode.  a_dvp should not be locked.  If no error occurs *a_vpp
243  * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
244  *
245  * This function is designed to aid NFS server-side operations and is
246  * used by cache_fromdvp() to create a consistent, connected namecache
247  * topology.
248  *
249  * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
250  * code out from their *_lookup() and create *_nlookupdotdot().  Then as time
251  * permits VFSs will implement the remaining *_n*() calls and finally get
252  * rid of their *_lookup() call.
253  */
254 int
255 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
256 {
257         struct componentname cnp;
258         int error;
259
260         /*
261          * UFS currently stores all sorts of side effects, including a loop
262          * variable, in the directory inode.  That needs to be fixed and the
263          * other VFS's audited before we can switch to LK_SHARED.
264          */
265         *ap->a_vpp = NULL;
266         if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
267                 return (error);
268         if (ap->a_dvp->v_type != VDIR) {
269                 vput(ap->a_dvp);
270                 return (ENOTDIR);
271         }
272
273         bzero(&cnp, sizeof(cnp));
274         cnp.cn_nameiop = NAMEI_LOOKUP;
275         cnp.cn_flags = CNP_ISDOTDOT;
276         cnp.cn_nameptr = "..";
277         cnp.cn_namelen = 2;
278         cnp.cn_cred = ap->a_cred;
279         cnp.cn_td = curthread; /* XXX */
280
281         /*
282          * vop_old_lookup() always returns vp locked.  dvp may or may not be
283          * left locked depending on CNP_PDIRUNLOCK.
284          *
285          * (*vpp) will be returned locked if no error occured, which is the
286          * state we want.
287          */
288         error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
289         if (cnp.cn_flags & CNP_PDIRUNLOCK)
290                 vrele(ap->a_dvp);
291         else
292                 vput(ap->a_dvp);
293         return (error);
294 }
295
296 /*
297  * vop_compat_ncreate { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
298  *                      struct vnode *a_dvp,
299  *                      struct vnode **a_vpp,
300  *                      struct ucred *a_cred,
301  *                      struct vattr *a_vap }
302  *
303  * Create a file as specified by a_vap.  Compatibility requires us to issue
304  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
305  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
306  */
307 int
308 vop_compat_ncreate(struct vop_ncreate_args *ap)
309 {
310         struct thread *td = curthread;
311         struct componentname cnp;
312         struct nchandle *nch;
313         struct namecache *ncp;
314         struct vnode *dvp;
315         int error;
316
317         /*
318          * Sanity checks, get a locked directory vnode.
319          */
320         nch = ap->a_nch;                /* locked namecache node */
321         dvp = ap->a_dvp;
322         ncp = nch->ncp;
323
324         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
325                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
326                         ncp, ncp->nc_name);
327                 return(EAGAIN);
328         }
329
330         /*
331          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
332          * caches all information required to create the entry in the
333          * directory inode.  We expect a return code of EJUSTRETURN for
334          * the CREATE case.  The cnp must simulated a saved-name situation.
335          */
336         bzero(&cnp, sizeof(cnp));
337         cnp.cn_nameiop = NAMEI_CREATE;
338         cnp.cn_flags = CNP_LOCKPARENT;
339         cnp.cn_nameptr = ncp->nc_name;
340         cnp.cn_namelen = ncp->nc_nlen;
341         cnp.cn_cred = ap->a_cred;
342         cnp.cn_td = td;
343         *ap->a_vpp = NULL;
344
345         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
346
347         /*
348          * EJUSTRETURN should be returned for this case, which means that
349          * the VFS has setup the directory inode for the create.  The dvp we
350          * passed in is expected to remain in a locked state.
351          *
352          * If the VOP_OLD_CREATE is successful we are responsible for updating
353          * the cache state of the locked ncp that was passed to us.
354          */
355         if (error == EJUSTRETURN) {
356                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
357                 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
358                 if (error == 0) {
359                         cache_setunresolved(nch);
360                         cache_setvp(nch, *ap->a_vpp);
361                 }
362         } else {
363                 if (error == 0) {
364                         vput(*ap->a_vpp);
365                         *ap->a_vpp = NULL;
366                         error = EEXIST;
367                 }
368                 KKASSERT(*ap->a_vpp == NULL);
369         }
370         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
371                 vn_unlock(dvp);
372         vrele(dvp);
373         return (error);
374 }
375
376 /*
377  * vop_compat_nmkdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
378  *                      struct vnode *a_dvp,
379  *                      struct vnode **a_vpp,
380  *                      struct ucred *a_cred,
381  *                      struct vattr *a_vap }
382  *
383  * Create a directory as specified by a_vap.  Compatibility requires us to
384  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
385  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
386  */
387 int
388 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
389 {
390         struct thread *td = curthread;
391         struct componentname cnp;
392         struct nchandle *nch;
393         struct namecache *ncp;
394         struct vnode *dvp;
395         int error;
396
397         /*
398          * Sanity checks, get a locked directory vnode.
399          */
400         nch = ap->a_nch;                /* locked namecache node */
401         ncp = nch->ncp;
402         dvp = ap->a_dvp;
403         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
404                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
405                         ncp, ncp->nc_name);
406                 return(EAGAIN);
407         }
408
409         /*
410          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
411          * caches all information required to create the entry in the
412          * directory inode.  We expect a return code of EJUSTRETURN for
413          * the CREATE case.  The cnp must simulated a saved-name situation.
414          */
415         bzero(&cnp, sizeof(cnp));
416         cnp.cn_nameiop = NAMEI_CREATE;
417         cnp.cn_flags = CNP_LOCKPARENT;
418         cnp.cn_nameptr = ncp->nc_name;
419         cnp.cn_namelen = ncp->nc_nlen;
420         cnp.cn_cred = ap->a_cred;
421         cnp.cn_td = td;
422         *ap->a_vpp = NULL;
423
424         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
425
426         /*
427          * EJUSTRETURN should be returned for this case, which means that
428          * the VFS has setup the directory inode for the create.  The dvp we
429          * passed in is expected to remain in a locked state.
430          *
431          * If the VOP_OLD_MKDIR is successful we are responsible for updating
432          * the cache state of the locked ncp that was passed to us.
433          */
434         if (error == EJUSTRETURN) {
435                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
436                 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
437                 if (error == 0) {
438                         cache_setunresolved(nch);
439                         cache_setvp(nch, *ap->a_vpp);
440                 }
441         } else {
442                 if (error == 0) {
443                         vput(*ap->a_vpp);
444                         *ap->a_vpp = NULL;
445                         error = EEXIST;
446                 }
447                 KKASSERT(*ap->a_vpp == NULL);
448         }
449         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
450                 vn_unlock(dvp);
451         vrele(dvp);
452         return (error);
453 }
454
455 /*
456  * vop_compat_nmknod { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
457  *                      struct vnode *a_dvp,
458  *                      struct vnode **a_vpp,
459  *                      struct ucred *a_cred,
460  *                      struct vattr *a_vap }
461  *
462  * Create a device or fifo node as specified by a_vap.  Compatibility requires
463  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
464  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
465  */
466 int
467 vop_compat_nmknod(struct vop_nmknod_args *ap)
468 {
469         struct thread *td = curthread;
470         struct componentname cnp;
471         struct nchandle *nch;
472         struct namecache *ncp;
473         struct vnode *dvp;
474         int error;
475
476         /*
477          * Sanity checks, get a locked directory vnode.
478          */
479         nch = ap->a_nch;                /* locked namecache node */
480         ncp = nch->ncp;
481         dvp = ap->a_dvp;
482
483         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
484                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
485                         ncp, ncp->nc_name);
486                 return(EAGAIN);
487         }
488
489         /*
490          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
491          * caches all information required to create the entry in the
492          * directory inode.  We expect a return code of EJUSTRETURN for
493          * the CREATE case.  The cnp must simulated a saved-name situation.
494          */
495         bzero(&cnp, sizeof(cnp));
496         cnp.cn_nameiop = NAMEI_CREATE;
497         cnp.cn_flags = CNP_LOCKPARENT;
498         cnp.cn_nameptr = ncp->nc_name;
499         cnp.cn_namelen = ncp->nc_nlen;
500         cnp.cn_cred = ap->a_cred;
501         cnp.cn_td = td;
502         *ap->a_vpp = NULL;
503
504         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
505
506         /*
507          * EJUSTRETURN should be returned for this case, which means that
508          * the VFS has setup the directory inode for the create.  The dvp we
509          * passed in is expected to remain in a locked state.
510          *
511          * If the VOP_OLD_MKNOD is successful we are responsible for updating
512          * the cache state of the locked ncp that was passed to us.
513          */
514         if (error == EJUSTRETURN) {
515                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
516                 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
517                 if (error == 0) {
518                         cache_setunresolved(nch);
519                         cache_setvp(nch, *ap->a_vpp);
520                 }
521         } else {
522                 if (error == 0) {
523                         vput(*ap->a_vpp);
524                         *ap->a_vpp = NULL;
525                         error = EEXIST;
526                 }
527                 KKASSERT(*ap->a_vpp == NULL);
528         }
529         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
530                 vn_unlock(dvp);
531         vrele(dvp);
532         return (error);
533 }
534
535 /*
536  * vop_compat_nlink { struct nchandle *a_nch,   XXX STOPGAP FUNCTION
537  *                      struct vnode *a_dvp,
538  *                      struct vnode *a_vp,
539  *                      struct ucred *a_cred }
540  *
541  * The passed vp is locked and represents the source.  The passed ncp is
542  * locked and represents the target to create.
543  */
544 int
545 vop_compat_nlink(struct vop_nlink_args *ap)
546 {
547         struct thread *td = curthread;
548         struct componentname cnp;
549         struct nchandle *nch;
550         struct namecache *ncp;
551         struct vnode *dvp;
552         struct vnode *tvp;
553         int error;
554
555         /*
556          * Sanity checks, get a locked directory vnode.
557          */
558         nch = ap->a_nch;                /* locked namecache node */
559         ncp = nch->ncp;
560         dvp = ap->a_dvp;
561
562         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
563                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
564                         ncp, ncp->nc_name);
565                 return(EAGAIN);
566         }
567
568         /*
569          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
570          * caches all information required to create the entry in the
571          * directory inode.  We expect a return code of EJUSTRETURN for
572          * the CREATE case.  The cnp must simulated a saved-name situation.
573          *
574          * It should not be possible for there to be a vnode collision
575          * between the source vp and target (name lookup).  However NFS
576          * clients racing each other can cause NFS to alias the same vnode
577          * across several names without the rest of the system knowing it.
578          * Use CNP_NOTVP to avoid a panic in this situation.
579          */
580         bzero(&cnp, sizeof(cnp));
581         cnp.cn_nameiop = NAMEI_CREATE;
582         cnp.cn_flags = CNP_LOCKPARENT | CNP_NOTVP;
583         cnp.cn_nameptr = ncp->nc_name;
584         cnp.cn_namelen = ncp->nc_nlen;
585         cnp.cn_cred = ap->a_cred;
586         cnp.cn_td = td;
587         cnp.cn_notvp = ap->a_vp;
588
589         tvp = NULL;
590         error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
591
592         /*
593          * EJUSTRETURN should be returned for this case, which means that
594          * the VFS has setup the directory inode for the create.  The dvp we
595          * passed in is expected to remain in a locked state.
596          *
597          * If the VOP_OLD_LINK is successful we are responsible for updating
598          * the cache state of the locked ncp that was passed to us.
599          */
600         if (error == EJUSTRETURN) {
601                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
602                 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
603                 if (error == 0) {
604                         cache_setunresolved(nch);
605                         cache_setvp(nch, ap->a_vp);
606                 }
607         } else {
608                 if (error == 0) {
609                         vput(tvp);
610                         error = EEXIST;
611                 }
612         }
613         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
614                 vn_unlock(dvp);
615         vrele(dvp);
616         return (error);
617 }
618
619 int
620 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
621 {
622         struct thread *td = curthread;
623         struct componentname cnp;
624         struct nchandle *nch;
625         struct namecache *ncp;
626         struct vnode *dvp;
627         struct vnode *vp;
628         int error;
629
630         /*
631          * Sanity checks, get a locked directory vnode.
632          */
633         *ap->a_vpp = NULL;
634         nch = ap->a_nch;                /* locked namecache node */
635         ncp = nch->ncp;
636         dvp = ap->a_dvp;
637
638         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
639                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
640                         ncp, ncp->nc_name);
641                 return(EAGAIN);
642         }
643
644         /*
645          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
646          * caches all information required to create the entry in the
647          * directory inode.  We expect a return code of EJUSTRETURN for
648          * the CREATE case.  The cnp must simulated a saved-name situation.
649          */
650         bzero(&cnp, sizeof(cnp));
651         cnp.cn_nameiop = NAMEI_CREATE;
652         cnp.cn_flags = CNP_LOCKPARENT;
653         cnp.cn_nameptr = ncp->nc_name;
654         cnp.cn_namelen = ncp->nc_nlen;
655         cnp.cn_cred = ap->a_cred;
656         cnp.cn_td = td;
657
658         vp = NULL;
659         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
660
661         /*
662          * EJUSTRETURN should be returned for this case, which means that
663          * the VFS has setup the directory inode for the create.  The dvp we
664          * passed in is expected to remain in a locked state.
665          *
666          * If the VOP_OLD_SYMLINK is successful we are responsible for updating
667          * the cache state of the locked ncp that was passed to us.
668          */
669         if (error == EJUSTRETURN) {
670                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
671                 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
672                 if (error == 0) {
673                         cache_setunresolved(nch);
674                         cache_setvp(nch, vp);
675                         *ap->a_vpp = vp;
676                 }
677         } else {
678                 if (error == 0) {
679                         vput(vp);
680                         vp = NULL;
681                         error = EEXIST;
682                 }
683                 KKASSERT(vp == NULL);
684         }
685         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
686                 vn_unlock(dvp);
687         vrele(dvp);
688         return (error);
689 }
690
691 /*
692  * vop_compat_nwhiteout { struct nchandle *a_nch,       XXX STOPGAP FUNCTION
693  *                        struct vnode *a_dvp,
694  *                        struct ucred *a_cred,
695  *                        int a_flags }
696  *
697  * Issie a whiteout operation (create, lookup, or delete).  Compatibility 
698  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 
699  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
700  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
701  * no lookup is necessary.
702  */
703 int
704 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
705 {
706         struct thread *td = curthread;
707         struct componentname cnp;
708         struct nchandle *nch;
709         struct namecache *ncp;
710         struct vnode *dvp;
711         struct vnode *vp;
712         int error;
713
714         /*
715          * Sanity checks, get a locked directory vnode.
716          */
717         nch = ap->a_nch;                /* locked namecache node */
718         ncp = nch->ncp;
719         dvp = ap->a_dvp;
720
721         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
722                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
723                         ncp, ncp->nc_name);
724                 return(EAGAIN);
725         }
726
727         /*
728          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
729          * caches all information required to create the entry in the
730          * directory inode.  We expect a return code of EJUSTRETURN for
731          * the CREATE case.  The cnp must simulated a saved-name situation.
732          */
733         bzero(&cnp, sizeof(cnp));
734         cnp.cn_nameiop = ap->a_flags;
735         cnp.cn_flags = CNP_LOCKPARENT;
736         cnp.cn_nameptr = ncp->nc_name;
737         cnp.cn_namelen = ncp->nc_nlen;
738         cnp.cn_cred = ap->a_cred;
739         cnp.cn_td = td;
740
741         vp = NULL;
742
743         /*
744          * EJUSTRETURN should be returned for the CREATE or DELETE cases.
745          * The VFS has setup the directory inode for the create.  The dvp we
746          * passed in is expected to remain in a locked state.
747          *
748          * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
749          * the cache state of the locked ncp that was passed to us.
750          */
751         switch(ap->a_flags) {
752         case NAMEI_DELETE:
753                 cnp.cn_flags |= CNP_DOWHITEOUT;
754                 /* fall through */
755         case NAMEI_CREATE:
756                 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
757                 if (error == EJUSTRETURN) {
758                         KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
759                         error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
760                         if (error == 0)
761                                 cache_setunresolved(nch);
762                 } else {
763                         if (error == 0) {
764                                 vput(vp);
765                                 vp = NULL;
766                                 error = EEXIST;
767                         }
768                         KKASSERT(vp == NULL);
769                 }
770                 break;
771         case NAMEI_LOOKUP:
772                 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
773                 break;
774         default:
775                 error = EINVAL;
776                 break;
777         }
778         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
779                 vn_unlock(dvp);
780         vrele(dvp);
781         return (error);
782 }
783
784
785 /*
786  * vop_compat_nremove { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
787  *                      struct vnode *a_dvp,
788  *                      struct ucred *a_cred }
789  */
790 int
791 vop_compat_nremove(struct vop_nremove_args *ap)
792 {
793         struct thread *td = curthread;
794         struct componentname cnp;
795         struct nchandle *nch;
796         struct namecache *ncp;
797         struct vnode *dvp;
798         struct vnode *vp;
799         int error;
800
801         /*
802          * Sanity checks, get a locked directory vnode.
803          */
804         nch = ap->a_nch;                /* locked namecache node */
805         ncp = nch->ncp;
806         dvp = ap->a_dvp;
807
808         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
809                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
810                         ncp, ncp->nc_name);
811                 return(EAGAIN);
812         }
813
814         /*
815          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
816          * caches all information required to delete the entry in the
817          * directory inode.  We expect a return code of 0 for the DELETE
818          * case (meaning that a vp has been found).  The cnp must simulated
819          * a saved-name situation.
820          */
821         bzero(&cnp, sizeof(cnp));
822         cnp.cn_nameiop = NAMEI_DELETE;
823         cnp.cn_flags = CNP_LOCKPARENT;
824         cnp.cn_nameptr = ncp->nc_name;
825         cnp.cn_namelen = ncp->nc_nlen;
826         cnp.cn_cred = ap->a_cred;
827         cnp.cn_td = td;
828
829         /*
830          * The vnode must be a directory and must not represent the
831          * current directory.
832          */
833         vp = NULL;
834         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
835         if (error == 0 && vp->v_type == VDIR)
836                 error = EPERM;
837         if (error == 0) {
838                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
839                 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
840                 if (error == 0)
841                         cache_unlink(nch);
842         }
843         if (vp) {
844                 if (dvp == vp)
845                         vrele(vp);
846                 else    
847                         vput(vp);
848         }
849         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
850                 vn_unlock(dvp);
851         vrele(dvp);
852         return (error);
853 }
854
855 /*
856  * vop_compat_nrmdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
857  *                     struct vnode *dvp,
858  *                     struct ucred *a_cred }
859  */
860 int
861 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
862 {
863         struct thread *td = curthread;
864         struct componentname cnp;
865         struct nchandle *nch;
866         struct namecache *ncp;
867         struct vnode *dvp;
868         struct vnode *vp;
869         int error;
870
871         /*
872          * Sanity checks, get a locked directory vnode.
873          */
874         nch = ap->a_nch;                /* locked namecache node */
875         ncp = nch->ncp;
876         dvp = ap->a_dvp;
877
878         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
879                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
880                         ncp, ncp->nc_name);
881                 return(EAGAIN);
882         }
883
884         /*
885          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
886          * caches all information required to delete the entry in the
887          * directory inode.  We expect a return code of 0 for the DELETE
888          * case (meaning that a vp has been found).  The cnp must simulated
889          * a saved-name situation.
890          */
891         bzero(&cnp, sizeof(cnp));
892         cnp.cn_nameiop = NAMEI_DELETE;
893         cnp.cn_flags = CNP_LOCKPARENT;
894         cnp.cn_nameptr = ncp->nc_name;
895         cnp.cn_namelen = ncp->nc_nlen;
896         cnp.cn_cred = ap->a_cred;
897         cnp.cn_td = td;
898
899         /*
900          * The vnode must be a directory and must not represent the
901          * current directory.
902          */
903         vp = NULL;
904         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
905         if (error == 0 && vp->v_type != VDIR)
906                 error = ENOTDIR;
907         if (error == 0 && vp == dvp)
908                 error = EINVAL;
909         if (error == 0 && (vp->v_flag & VROOT))
910                 error = EBUSY;
911         if (error == 0) {
912                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
913                 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
914
915                 /*
916                  * Note that this invalidation will cause any process
917                  * currently CD'd into the directory being removed to be
918                  * disconnected from the topology and not be able to ".."
919                  * back out.
920                  */
921                 if (error == 0) {
922                         cache_inval(nch, CINV_DESTROY);
923                         cache_inval_vp(vp, CINV_DESTROY);
924                 }
925         }
926         if (vp) {
927                 if (dvp == vp)
928                         vrele(vp);
929                 else    
930                         vput(vp);
931         }
932         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
933                 vn_unlock(dvp);
934         vrele(dvp);
935         return (error);
936 }
937
938 /*
939  * vop_compat_nrename { struct nchandle *a_fnch,        XXX STOPGAP FUNCTION
940  *                      struct nchandle *a_tnch,
941  *                      struct ucred *a_cred }
942  *
943  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
944  * the source directory and vnode be unlocked and the target directory and
945  * vnode (if it exists) be locked.  All arguments will be vrele'd and 
946  * the targets will also be unlocked regardless of the return code.
947  */
948 int
949 vop_compat_nrename(struct vop_nrename_args *ap)
950 {
951         struct thread *td = curthread;
952         struct componentname fcnp;
953         struct componentname tcnp;
954         struct nchandle *fnch;
955         struct nchandle *tnch;
956         struct namecache *fncp;
957         struct namecache *tncp;
958         struct vnode *fdvp, *fvp;
959         struct vnode *tdvp, *tvp;
960         int error;
961
962         /*
963          * Sanity checks, get referenced vnodes representing the source.
964          */
965         fnch = ap->a_fnch;              /* locked namecache node */
966         fncp = fnch->ncp;
967         fdvp = ap->a_fdvp;
968
969         /*
970          * Temporarily lock the source directory and lookup in DELETE mode to
971          * check permissions.  XXX delete permissions should have been
972          * checked by nlookup(), we need to add NLC_DELETE for delete
973          * checking.  It is unclear whether VFS's require the directory setup
974          * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
975          * since it isn't locked and since UFS always does a relookup of
976          * the source, it is believed that the only side effect that matters
977          * is the permissions check.
978          */
979         if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
980                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
981                         fncp, fncp->nc_name);
982                 return(EAGAIN);
983         }
984
985         bzero(&fcnp, sizeof(fcnp));
986         fcnp.cn_nameiop = NAMEI_DELETE;
987         fcnp.cn_flags = CNP_LOCKPARENT;
988         fcnp.cn_nameptr = fncp->nc_name;
989         fcnp.cn_namelen = fncp->nc_nlen;
990         fcnp.cn_cred = ap->a_cred;
991         fcnp.cn_td = td;
992
993         /*
994          * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
995          * fvp.
996          */
997         fvp = NULL;
998         error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
999         if (error == 0 && (fvp->v_flag & VROOT)) {
1000                 vput(fvp);      /* as if vop_old_lookup had failed */
1001                 error = EBUSY;
1002         }
1003         if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1004                 fcnp.cn_flags |= CNP_PDIRUNLOCK;
1005                 vn_unlock(fdvp);
1006         }
1007         if (error) {
1008                 vrele(fdvp);
1009                 return (error);
1010         }
1011         vn_unlock(fvp);
1012
1013         /*
1014          * fdvp and fvp are now referenced and unlocked.
1015          *
1016          * Get a locked directory vnode for the target and lookup the target
1017          * in CREATE mode so it places the required information in the
1018          * directory inode.
1019          */
1020         tnch = ap->a_tnch;              /* locked namecache node */
1021         tncp = tnch->ncp;
1022         tdvp = ap->a_tdvp;
1023         if (error) {
1024                 vrele(fdvp);
1025                 vrele(fvp);
1026                 return (error);
1027         }
1028         if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
1029                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1030                         tncp, tncp->nc_name);
1031                 vrele(fdvp);
1032                 vrele(fvp);
1033                 return(EAGAIN);
1034         }
1035
1036         /*
1037          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
1038          * caches all information required to create the entry in the
1039          * target directory inode.
1040          */
1041         bzero(&tcnp, sizeof(tcnp));
1042         tcnp.cn_nameiop = NAMEI_RENAME;
1043         tcnp.cn_flags = CNP_LOCKPARENT;
1044         tcnp.cn_nameptr = tncp->nc_name;
1045         tcnp.cn_namelen = tncp->nc_nlen;
1046         tcnp.cn_cred = ap->a_cred;
1047         tcnp.cn_td = td;
1048
1049         tvp = NULL;
1050         error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1051
1052         if (error == EJUSTRETURN) {
1053                 /*
1054                  * Target does not exist.  tvp should be NULL.
1055                  */
1056                 KKASSERT(tvp == NULL);
1057                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1058                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1059                 if (error == 0)
1060                         cache_rename(fnch, tnch);
1061         } else if (error == 0) {
1062                 /*
1063                  * Target exists.  VOP_OLD_RENAME should correctly delete the
1064                  * target.
1065                  */
1066                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1067                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1068                 if (error == 0)
1069                         cache_rename(fnch, tnch);
1070         } else {
1071                 vrele(fdvp);
1072                 vrele(fvp);
1073                 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1074                         vrele(tdvp);
1075                 else
1076                         vput(tdvp);
1077         }
1078         return (error);
1079 }
1080
1081 static int
1082 vop_nolookup(struct vop_old_lookup_args *ap)
1083 {
1084
1085         *ap->a_vpp = NULL;
1086         return (ENOTDIR);
1087 }
1088
1089 /*
1090  *      vop_nostrategy:
1091  *
1092  *      Strategy routine for VFS devices that have none.
1093  *
1094  *      B_ERROR and B_INVAL must be cleared prior to calling any strategy
1095  *      routine.  Typically this is done for a BUF_CMD_READ strategy call.
1096  *      Typically B_INVAL is assumed to already be clear prior to a write
1097  *      and should not be cleared manually unless you just made the buffer
1098  *      invalid.  B_ERROR should be cleared either way.
1099  */
1100
1101 static int
1102 vop_nostrategy (struct vop_strategy_args *ap)
1103 {
1104         kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1105         vprint("", ap->a_vp);
1106         ap->a_bio->bio_buf->b_flags |= B_ERROR;
1107         ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1108         biodone(ap->a_bio);
1109         return (EOPNOTSUPP);
1110 }
1111
1112 int
1113 vop_stdpathconf(struct vop_pathconf_args *ap)
1114 {
1115         int error = 0;
1116
1117         switch (ap->a_name) {
1118         case _PC_CHOWN_RESTRICTED:
1119                 *ap->a_retval = _POSIX_CHOWN_RESTRICTED;
1120                 break;
1121         case _PC_LINK_MAX:
1122                 *ap->a_retval = LINK_MAX;
1123                 break;
1124         case _PC_MAX_CANON:
1125                 *ap->a_retval = MAX_CANON;
1126                 break;
1127         case _PC_MAX_INPUT:
1128                 *ap->a_retval = MAX_INPUT;
1129                 break;
1130         case _PC_NAME_MAX:
1131                 *ap->a_retval = NAME_MAX;
1132                 break;
1133         case _PC_NO_TRUNC:
1134                 *ap->a_retval = _POSIX_NO_TRUNC;
1135                 break;
1136         case _PC_PATH_MAX:
1137                 *ap->a_retval = PATH_MAX;
1138                 break;
1139         case _PC_PIPE_BUF:
1140                 *ap->a_retval = PIPE_BUF;
1141                 break;
1142         case _PC_VDISABLE:
1143                 *ap->a_retval = _POSIX_VDISABLE;
1144                 break;
1145         default:
1146                 error = EINVAL;
1147                 break;
1148         }
1149         return (error);
1150 }
1151
1152 /*
1153  * Standard open.
1154  *
1155  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
1156  *
1157  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1158  */
1159 int
1160 vop_stdopen(struct vop_open_args *ap)
1161 {
1162         struct vnode *vp = ap->a_vp;
1163         struct file *fp;
1164
1165         if ((fp = ap->a_fp) != NULL) {
1166                 switch(vp->v_type) {
1167                 case VFIFO:
1168                         fp->f_type = DTYPE_FIFO;
1169                         break;
1170                 default:
1171                         fp->f_type = DTYPE_VNODE;
1172                         break;
1173                 }
1174                 /* retain flags not to be copied */
1175                 fp->f_flag = (fp->f_flag & ~FMASK) | (ap->a_mode & FMASK);
1176                 fp->f_ops = &vnode_fileops;
1177                 fp->f_data = vp;
1178                 vref(vp);
1179         }
1180         if (ap->a_mode & FWRITE)
1181                 atomic_add_int(&vp->v_writecount, 1);
1182         KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1183         atomic_add_int(&vp->v_opencount, 1);
1184         return (0);
1185 }
1186
1187 /*
1188  * Standard close.
1189  *
1190  * (struct vnode *a_vp, int a_fflag)
1191  *
1192  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
1193  *
1194  * v_lastwrite_ts is used to record the timestamp that should be used to
1195  * set the file mtime for any asynchronously flushed pages modified via
1196  * mmap(), which can occur after the last close().
1197  */
1198 int
1199 vop_stdclose(struct vop_close_args *ap)
1200 {
1201         struct vnode *vp = ap->a_vp;
1202
1203         KASSERT(vp->v_opencount > 0,
1204                 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x",
1205                 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
1206         if (ap->a_fflag & FWRITE) {
1207                 KASSERT(vp->v_writecount > 0,
1208                         ("VOP_STDCLOSE: BAD WRITECOUNT %p %d",
1209                         vp, vp->v_writecount));
1210                 atomic_add_int(&vp->v_writecount, -1);
1211         }
1212         atomic_add_int(&vp->v_opencount, -1);
1213         return (0);
1214 }
1215
1216 /*
1217  * Standard getattr_lite
1218  *
1219  * Just calls getattr
1220  */
1221 int
1222 vop_stdgetattr_lite(struct vop_getattr_lite_args *ap)
1223 {
1224         struct vattr va;
1225         struct vattr_lite *lvap;
1226         int error;
1227
1228         error = VOP_GETATTR(ap->a_vp, &va);
1229         if (__predict_true(error == 0)) {
1230                 lvap = ap->a_lvap;
1231                 lvap->va_type = va.va_type;
1232                 lvap->va_nlink = va.va_nlink;
1233                 lvap->va_mode = va.va_mode;
1234                 lvap->va_uid = va.va_uid;
1235                 lvap->va_gid = va.va_gid;
1236                 lvap->va_size = va.va_size;
1237                 lvap->va_flags = va.va_flags;
1238         }
1239         return error;
1240 }
1241
1242 /*
1243  * Implement standard getpages and putpages.  All filesystems must use
1244  * the buffer cache to back regular files.
1245  */
1246 int
1247 vop_stdgetpages(struct vop_getpages_args *ap)
1248 {
1249         struct mount *mp;
1250         int error;
1251
1252         if ((mp = ap->a_vp->v_mount) != NULL) {
1253                 error = vnode_pager_generic_getpages(
1254                                 ap->a_vp, ap->a_m, ap->a_count,
1255                                 ap->a_reqpage, ap->a_seqaccess);
1256         } else {
1257                 error = VM_PAGER_BAD;
1258         }
1259         return (error);
1260 }
1261
1262 int
1263 vop_stdputpages(struct vop_putpages_args *ap)
1264 {
1265         struct mount *mp;
1266         int error;
1267
1268         if ((mp = ap->a_vp->v_mount) != NULL) {
1269                 error = vnode_pager_generic_putpages(
1270                                 ap->a_vp, ap->a_m, ap->a_count,
1271                                 ap->a_flags, ap->a_rtvals);
1272         } else {
1273                 error = VM_PAGER_BAD;
1274         }
1275         return (error);
1276 }
1277
1278 int
1279 vop_stdnoread(struct vop_read_args *ap)
1280 {
1281         return (EINVAL);
1282 }
1283
1284 int
1285 vop_stdnowrite(struct vop_write_args *ap)
1286 {
1287         return (EINVAL);
1288 }
1289
1290 /* 
1291  * vfs default ops
1292  * used to fill the vfs fucntion table to get reasonable default return values.
1293  */
1294 int
1295 vop_stdmountctl(struct vop_mountctl_args *ap)
1296 {
1297
1298         struct mount *mp;
1299         int error = 0;
1300
1301         mp = ap->a_head.a_ops->head.vv_mount;
1302
1303         switch(ap->a_op) {
1304         case MOUNTCTL_MOUNTFLAGS:
1305                 /*
1306                  * Get a string buffer with all the mount flags
1307                  * names comman separated.
1308                  * mount(2) will use this information.
1309                  */
1310                 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
1311                                             ap->a_buf, ap->a_buflen, &error);
1312                 break;
1313         case MOUNTCTL_INSTALL_VFS_JOURNAL:
1314         case MOUNTCTL_RESTART_VFS_JOURNAL:
1315         case MOUNTCTL_REMOVE_VFS_JOURNAL:
1316         case MOUNTCTL_RESYNC_VFS_JOURNAL:
1317         case MOUNTCTL_STATUS_VFS_JOURNAL:
1318                 error = journal_mountctl(ap);
1319                 break;
1320         default:
1321                 error = EOPNOTSUPP;
1322                 break;
1323         }
1324         return (error);
1325 }
1326
1327 int     
1328 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1329 {
1330         return (EOPNOTSUPP);
1331 }
1332
1333 int     
1334 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1335 {
1336         return (EOPNOTSUPP);
1337 }
1338
1339 /*
1340  * If the VFS does not implement statvfs, then call statfs and convert
1341  * the values.  This code was taken from libc's __cvtstatvfs() function,
1342  * contributed by Joerg Sonnenberger.
1343  */
1344 int     
1345 vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
1346 {
1347         struct statfs *in;
1348         int error;
1349
1350         in = &mp->mnt_stat;
1351         error = VFS_STATFS(mp, in, cred);
1352         if (error == 0) {
1353                 bzero(sbp, sizeof(*sbp));
1354
1355                 sbp->f_bsize = in->f_bsize;
1356                 sbp->f_frsize = in->f_bsize;
1357                 sbp->f_blocks = in->f_blocks;
1358                 sbp->f_bfree = in->f_bfree;
1359                 sbp->f_bavail = in->f_bavail;
1360                 sbp->f_files = in->f_files;
1361                 sbp->f_ffree = in->f_ffree;
1362
1363                 /*
1364                  * XXX
1365                  * This field counts the number of available inodes to non-root
1366                  * users, but this information is not available via statfs.
1367                  * Just ignore this issue by returning the total number 
1368                  * instead.
1369                  */
1370                 sbp->f_favail = in->f_ffree;
1371
1372                 /*
1373                  * XXX
1374                  * This field has a different meaning for statfs and statvfs.
1375                  * For the former it is the cookie exported for NFS and not
1376                  * intended for normal userland use.
1377                  */
1378                 sbp->f_fsid = 0;
1379
1380                 sbp->f_flag = 0;
1381                 if (in->f_flags & MNT_RDONLY)
1382                         sbp->f_flag |= ST_RDONLY;
1383                 if (in->f_flags & MNT_NOSUID)
1384                         sbp->f_flag |= ST_NOSUID;
1385                 sbp->f_namemax = 0;
1386                 sbp->f_owner = in->f_owner;
1387                 /*
1388                  * XXX
1389                  * statfs contains the type as string, statvfs expects it as
1390                  * enumeration.
1391                  */
1392                 sbp->f_type = 0;
1393
1394                 sbp->f_syncreads = in->f_syncreads;
1395                 sbp->f_syncwrites = in->f_syncwrites;
1396                 sbp->f_asyncreads = in->f_asyncreads;
1397                 sbp->f_asyncwrites = in->f_asyncwrites;
1398         }
1399         return (error);
1400 }
1401
1402 int
1403 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1404 {
1405         return (EOPNOTSUPP);
1406 }
1407
1408 int     
1409 vfs_stdstart(struct mount *mp, int flags)
1410 {
1411         return (0);
1412 }
1413
1414 int     
1415 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1416         caddr_t arg, struct ucred *cred)
1417 {
1418         return (EOPNOTSUPP);
1419 }
1420
1421 int     
1422 vfs_stdsync(struct mount *mp, int waitfor)
1423 {
1424         return (0);
1425 }
1426
1427 int
1428 vfs_stdnosync(struct mount *mp, int waitfor)
1429 {
1430         return (EOPNOTSUPP);
1431 }
1432
1433 int     
1434 vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
1435 {
1436         return (EOPNOTSUPP);
1437 }
1438
1439 int     
1440 vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
1441               struct fid *fhp, struct vnode **vpp)
1442 {
1443         return (EOPNOTSUPP);
1444 }
1445
1446 int 
1447 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1448         struct ucred **credanonp)
1449 {
1450         return (EOPNOTSUPP);
1451 }
1452
1453 int
1454 vfs_stdinit(struct vfsconf *vfsp)
1455 {
1456         return (0);
1457 }
1458
1459 int
1460 vfs_stduninit(struct vfsconf *vfsp)
1461 {
1462         return(0);
1463 }
1464
1465 int
1466 vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
1467                  int attrnamespace, const char *attrname,
1468                  struct ucred *cred)
1469 {
1470         return(EOPNOTSUPP);
1471 }
1472
1473 #define ACCOUNTING_NB_FSTYPES 7
1474
1475 static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
1476         "ext2fs", "hammer", "mfs", "ntfs", "null", "tmpfs", "ufs" };
1477
1478 int
1479 vfs_stdac_init(struct mount *mp)
1480 {
1481         const char* fs_type;
1482         int i, fstype_ok = 0;
1483
1484         /* is mounted fs type one we want to do some accounting for ? */
1485         for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1486                 fs_type = accounting_fstypes[i];
1487                 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1488                                         sizeof(mp->mnt_stat)) == 0) {
1489                         fstype_ok = 1;
1490                         break;
1491                 }
1492         }
1493         if (fstype_ok == 0)
1494                 return (0);
1495
1496         vq_init(mp);
1497         return (0);
1498 }
1499
1500 void
1501 vfs_stdac_done(struct mount *mp)
1502 {
1503         vq_done(mp);
1504 }
1505
1506 void
1507 vfs_stdncpgen_set(struct mount *mp, struct namecache *ncp)
1508 {
1509 }
1510
1511 int
1512 vfs_stdncpgen_test(struct mount *mp, struct namecache *ncp)
1513 {
1514         return 0;
1515 }
1516
1517 int
1518 vfs_stdmodifying(struct mount *mp)
1519 {
1520         if (mp->mnt_flag & MNT_RDONLY)
1521                 return EROFS;
1522         return 0;
1523 }
1524 /* end of vfs default ops */