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