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