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