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