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