Fix a stack overflow due to recursion. When the namecache must invalidate
[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.44 2006/10/26 02:27:19 dillon Exp $
41  */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 #include <sys/conf.h>
47 #include <sys/fcntl.h>
48 #include <sys/file.h>
49 #include <sys/kernel.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/mount.h>
53 #include <sys/unistd.h>
54 #include <sys/vnode.h>
55 #include <sys/namei.h>
56 #include <sys/nlookup.h>
57 #include <sys/poll.h>
58 #include <sys/mountctl.h>
59
60 #include <machine/limits.h>
61
62 #include <vm/vm.h>
63 #include <vm/vm_object.h>
64 #include <vm/vm_page.h>
65 #include <vm/vm_pager.h>
66 #include <vm/vnode_pager.h>
67
68 static int      vop_nolookup (struct vop_old_lookup_args *);
69 static int      vop_nostrategy (struct vop_strategy_args *);
70
71 /*
72  * This vnode table stores what we want to do if the filesystem doesn't
73  * implement a particular VOP.
74  *
75  * If there is no specific entry here, we will return EOPNOTSUPP.
76  */
77 struct vop_ops default_vnode_vops = {
78         .vop_default            = vop_eopnotsupp,
79         .vop_advlock            = (void *)vop_einval,
80         .vop_fsync              = (void *)vop_null,
81         .vop_ioctl              = (void *)vop_enotty,
82         .vop_mmap               = (void *)vop_einval,
83         .vop_old_lookup         = vop_nolookup,
84         .vop_open               = vop_stdopen,
85         .vop_close              = vop_stdclose,
86         .vop_pathconf           = (void *)vop_einval,
87         .vop_poll               = vop_nopoll,
88         .vop_readlink           = (void *)vop_einval,
89         .vop_reallocblks        = (void *)vop_eopnotsupp,
90         .vop_revoke             = vop_stdrevoke,
91         .vop_strategy           = vop_nostrategy,
92         .vop_getacl             = (void *)vop_eopnotsupp,
93         .vop_setacl             = (void *)vop_eopnotsupp,
94         .vop_aclcheck           = (void *)vop_eopnotsupp,
95         .vop_getextattr         = (void *)vop_eopnotsupp,
96         .vop_setextattr         = (void *)vop_eopnotsupp,
97         .vop_nresolve           = vop_compat_nresolve,
98         .vop_nlookupdotdot      = vop_compat_nlookupdotdot,
99         .vop_ncreate            = vop_compat_ncreate,
100         .vop_nmkdir             = vop_compat_nmkdir,
101         .vop_nmknod             = vop_compat_nmknod,
102         .vop_nlink              = vop_compat_nlink,
103         .vop_nsymlink           = vop_compat_nsymlink,
104         .vop_nwhiteout          = vop_compat_nwhiteout,
105         .vop_nremove            = vop_compat_nremove,
106         .vop_nrmdir             = vop_compat_nrmdir,
107         .vop_nrename            = vop_compat_nrename,
108         .vop_mountctl           = journal_mountctl
109 };
110
111 VNODEOP_SET(default_vnode_vops);
112
113 int
114 vop_eopnotsupp(struct vop_generic_args *ap)
115 {
116         return (EOPNOTSUPP);
117 }
118
119 int
120 vop_ebadf(struct vop_generic_args *ap)
121 {
122         return (EBADF);
123 }
124
125 int
126 vop_enotty(struct vop_generic_args *ap)
127 {
128         return (ENOTTY);
129 }
130
131 int
132 vop_einval(struct vop_generic_args *ap)
133 {
134         return (EINVAL);
135 }
136
137 int
138 vop_null(struct vop_generic_args *ap)
139 {
140         return (0);
141 }
142
143 int
144 vop_defaultop(struct vop_generic_args *ap)
145 {
146         return (VOCALL(&default_vnode_vops, ap));
147 }
148
149 int
150 vop_panic(struct vop_generic_args *ap)
151 {
152         panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
153 }
154
155 /*
156  * vop_compat_resolve { struct namecache *a_ncp }       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 namecache *ncp;
187         struct componentname cnp;
188
189         ncp = ap->a_ncp;        /* locked namecache node */
190         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
191                 return(EPERM);
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                 printf("[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(ncp, 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(ncp, 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 namecache *a_ncp,        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 namecache *ncp;
318         struct vnode *dvp;
319         int error;
320
321         /*
322          * Sanity checks, get a locked directory vnode.
323          */
324         ncp = ap->a_ncp;                /* locked namecache node */
325         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
326                 return(EPERM);
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                 printf("[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(ncp);
368                         cache_setvp(ncp, *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 namecache *a_ncp,         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 namecache *ncp;
400         struct vnode *dvp;
401         int error;
402
403         /*
404          * Sanity checks, get a locked directory vnode.
405          */
406         ncp = ap->a_ncp;                /* locked namecache node */
407         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
408                 return(EPERM);
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                 printf("[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(ncp);
450                         cache_setvp(ncp, *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 namecache *a_ncp,         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 namecache *ncp;
482         struct vnode *dvp;
483         int error;
484
485         /*
486          * Sanity checks, get a locked directory vnode.
487          */
488         ncp = ap->a_ncp;                /* locked namecache node */
489         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
490                 return(EPERM);
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                 printf("[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(ncp);
532                         cache_setvp(ncp, *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 namecache *a_ncp,  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 namecache *ncp;
562         struct vnode *dvp;
563         struct vnode *tvp;
564         int error;
565
566         /*
567          * Sanity checks, get a locked directory vnode.
568          */
569         ncp = ap->a_ncp;                /* locked namecache node */
570         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
571                 return(EPERM);
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                 printf("[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(ncp);
613                         cache_setvp(ncp, 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 namecache *ncp;
633         struct vnode *dvp;
634         struct vnode *vp;
635         int error;
636
637         /*
638          * Sanity checks, get a locked directory vnode.
639          */
640         *ap->a_vpp = NULL;
641         ncp = ap->a_ncp;                /* locked namecache node */
642         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
643                 return(EPERM);
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                 printf("[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(ncp);
685                         cache_setvp(ncp, 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 namecache *a_ncp,      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 namecache *ncp;
719         struct vnode *dvp;
720         struct vnode *vp;
721         int error;
722
723         /*
724          * Sanity checks, get a locked directory vnode.
725          */
726         ncp = ap->a_ncp;                /* locked namecache node */
727         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
728                 return(EPERM);
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                 printf("[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(ncp);
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 namecache *a_ncp,        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 namecache *ncp;
808         struct vnode *dvp;
809         struct vnode *vp;
810         int error;
811
812         /*
813          * Sanity checks, get a locked directory vnode.
814          */
815         ncp = ap->a_ncp;                /* locked namecache node */
816         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
817                 return(EPERM);
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                 printf("[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(ncp);
857                         cache_setvp(ncp, 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 namecache *a_ncp,         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 namecache *ncp;
883         struct vnode *dvp;
884         struct vnode *vp;
885         int error;
886
887         /*
888          * Sanity checks, get a locked directory vnode.
889          */
890         ncp = ap->a_ncp;                /* locked namecache node */
891         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
892                 return(EPERM);
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                 printf("[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(ncp, 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 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                 vn_unlock(fdvp);
1028         }
1029         if (error) {
1030                 vrele(fdvp);
1031                 return (error);
1032         }
1033         vn_unlock(fvp);
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  * Return true for select/poll.
1242  */
1243 int
1244 vop_nopoll(ap)
1245         struct vop_poll_args /* {
1246                 struct vnode *a_vp;
1247                 int  a_events;
1248                 struct ucred *a_cred;
1249                 struct proc *a_p;
1250         } */ *ap;
1251 {
1252         /*
1253          * Return true for read/write.  If the user asked for something
1254          * special, return POLLNVAL, so that clients have a way of
1255          * determining reliably whether or not the extended
1256          * functionality is present without hard-coding knowledge
1257          * of specific filesystem implementations.
1258          */
1259         if (ap->a_events & ~POLLSTANDARD)
1260                 return (POLLNVAL);
1261
1262         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1263 }
1264
1265 /*
1266  * Implement poll for local filesystems that support it.
1267  */
1268 int
1269 vop_stdpoll(ap)
1270         struct vop_poll_args /* {
1271                 struct vnode *a_vp;
1272                 int  a_events;
1273                 struct ucred *a_cred;
1274         } */ *ap;
1275 {
1276         if (ap->a_events & ~POLLSTANDARD)
1277                 return (vn_pollrecord(ap->a_vp, ap->a_events));
1278         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1279 }
1280
1281 /* 
1282  * vfs default ops
1283  * used to fill the vfs fucntion table to get reasonable default return values.
1284  */
1285 int 
1286 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
1287 {
1288         return (0);
1289 }
1290
1291 int     
1292 vfs_stdunmount(struct mount *mp, int mntflags)
1293 {
1294         return (0);
1295 }
1296
1297 int     
1298 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1299 {
1300         return (EOPNOTSUPP);
1301 }
1302
1303 int     
1304 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1305 {
1306         return (EOPNOTSUPP);
1307 }
1308
1309 int
1310 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1311 {
1312         return (EOPNOTSUPP);
1313 }
1314
1315 int     
1316 vfs_stdstart(struct mount *mp, int flags)
1317 {
1318         return (0);
1319 }
1320
1321 int     
1322 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1323         caddr_t arg, struct ucred *cred)
1324 {
1325         return (EOPNOTSUPP);
1326 }
1327
1328 int     
1329 vfs_stdsync(struct mount *mp, int waitfor)
1330 {
1331         return (0);
1332 }
1333
1334 int
1335 vfs_stdnosync(struct mount *mp, int waitfor)
1336 {
1337         return (EOPNOTSUPP);
1338 }
1339
1340 int     
1341 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
1342 {
1343         return (EOPNOTSUPP);
1344 }
1345
1346 int     
1347 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1348 {
1349         return (EOPNOTSUPP);
1350 }
1351
1352 int 
1353 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1354         struct ucred **credanonp)
1355 {
1356         return (EOPNOTSUPP);
1357 }
1358
1359 int
1360 vfs_stdinit(struct vfsconf *vfsp)
1361 {
1362         return (0);
1363 }
1364
1365 int
1366 vfs_stduninit(struct vfsconf *vfsp)
1367 {
1368         return(0);
1369 }
1370
1371 int
1372 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1373         caddr_t arg, struct ucred *cred)
1374 {
1375         return(EOPNOTSUPP);
1376 }
1377
1378 /* end of vfs default ops */