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