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