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