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