98f677e7ebc7d73761664c792532594599b57761
[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.22 2004/11/12 00:09:24 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/kernel.h>
48 #include <sys/lock.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/unistd.h>
52 #include <sys/vnode.h>
53 #include <sys/namei.h>
54 #include <sys/nlookup.h>
55 #include <sys/poll.h>
56
57 #include <machine/limits.h>
58
59 #include <vm/vm.h>
60 #include <vm/vm_object.h>
61 #include <vm/vm_page.h>
62 #include <vm/vm_pager.h>
63 #include <vm/vnode_pager.h>
64
65 static int      vop_nolookup (struct vop_lookup_args *);
66 static int      vop_nostrategy (struct vop_strategy_args *);
67
68 /*
69  * This vnode table stores what we want to do if the filesystem doesn't
70  * implement a particular VOP.
71  *
72  * If there is no specific entry here, we will return EOPNOTSUPP.
73  */
74 struct vop_ops *default_vnode_vops;
75 static struct vnodeopv_entry_desc default_vnodeop_entries[] = {
76         { &vop_default_desc,            vop_eopnotsupp },
77         { &vop_advlock_desc,            vop_einval },
78         { &vop_bwrite_desc,             (void *) vop_stdbwrite },
79         { &vop_close_desc,              vop_null },
80         { &vop_createvobject_desc,      (void *) vop_stdcreatevobject },
81         { &vop_destroyvobject_desc,     (void *) vop_stddestroyvobject },
82         { &vop_fsync_desc,              vop_null },
83         { &vop_getvobject_desc,         (void *) vop_stdgetvobject },
84         { &vop_ioctl_desc,              vop_enotty },
85         { &vop_islocked_desc,           (void *) vop_stdislocked },
86         { &vop_lease_desc,              vop_null },
87         { &vop_lock_desc,               (void *) vop_stdlock },
88         { &vop_mmap_desc,               vop_einval },
89         { &vop_lookup_desc,             (void *) vop_nolookup },
90         { &vop_open_desc,               vop_null },
91         { &vop_pathconf_desc,           vop_einval },
92         { &vop_poll_desc,               (void *) vop_nopoll },
93         { &vop_readlink_desc,           vop_einval },
94         { &vop_reallocblks_desc,        vop_eopnotsupp },
95         { &vop_revoke_desc,             (void *) vop_stdrevoke },
96         { &vop_strategy_desc,           (void *) vop_nostrategy },
97         { &vop_unlock_desc,             (void *) vop_stdunlock },
98         { &vop_getacl_desc,             vop_eopnotsupp },
99         { &vop_setacl_desc,             vop_eopnotsupp },
100         { &vop_aclcheck_desc,           vop_eopnotsupp },
101         { &vop_getextattr_desc,         vop_eopnotsupp },
102         { &vop_setextattr_desc,         vop_eopnotsupp },
103         { &vop_nresolve_desc,           (void *) vop_compat_nresolve },
104         { &vop_nlookupdotdot_desc,      (void *) vop_compat_nlookupdotdot },
105         { &vop_ncreate_desc,            (void *) vop_compat_ncreate },
106         { &vop_nmkdir_desc,             (void *) vop_compat_nmkdir },
107         { &vop_nmknod_desc,             (void *) vop_compat_nmknod },
108         { &vop_nlink_desc,              (void *) vop_compat_nlink },
109         { &vop_nsymlink_desc,           (void *) vop_compat_nsymlink },
110         { &vop_nwhiteout_desc,          (void *) vop_compat_nwhiteout },
111         { &vop_nremove_desc,            (void *) vop_compat_nremove },
112         { &vop_nrmdir_desc,             (void *) vop_compat_nrmdir },
113         { &vop_nrename_desc,            (void *) vop_compat_nrename },
114         { NULL, NULL }
115 };
116
117 static struct vnodeopv_desc default_vnodeop_opv_desc =
118         { &default_vnode_vops, default_vnodeop_entries };
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_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_lookup() always returns vp locked.  dvp may or may not be
228          * left locked depending on CNP_PDIRUNLOCK.
229          */
230         error = vop_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_lookup() always returns vp locked.  dvp may or may not be
300          * left locked depending on CNP_PDIRUNLOCK.
301          */
302         error = vop_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_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_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                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
376                 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
377                 if (error == 0) {
378                         cache_setunresolved(ncp);
379                         cache_setvp(ncp, *ap->a_vpp);
380                 }
381         } else {
382                 if (error == 0) {
383                         vput(*ap->a_vpp);
384                         *ap->a_vpp = NULL;
385                         error = EEXIST;
386                 }
387                 KKASSERT(*ap->a_vpp == NULL);
388         }
389         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
390                 VOP_UNLOCK(dvp, 0, td);
391         vrele(dvp);
392         return (error);
393 }
394
395 /*
396  * vop_compat_nmkdir { struct namecache *a_ncp,         XXX STOPGAP FUNCTION
397  *                      struct vnode *a_vpp,
398  *                      struct ucred *a_cred,
399  *                      struct vattr *a_vap }
400  *
401  * Create a directory as specified by a_vap.  Compatibility requires us to
402  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
403  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
404  */
405 int
406 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
407 {
408         struct thread *td = curthread;
409         struct componentname cnp;
410         struct namecache *ncp;
411         struct vnode *dvp;
412         int error;
413
414         /*
415          * Sanity checks, get a locked directory vnode.
416          */
417         ncp = ap->a_ncp;                /* locked namecache node */
418         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
419                 return(EPERM);
420         if (ncp->nc_parent == NULL)
421                 return(EPERM);
422         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
423                 return(EPERM);
424
425         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
426                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
427                         ncp, ncp->nc_name);
428                 return(EAGAIN);
429         }
430
431         /*
432          * Setup the cnp for a traditional vop_lookup() call.  The lookup
433          * caches all information required to create the entry in the
434          * directory inode.  We expect a return code of EJUSTRETURN for
435          * the CREATE case.  The cnp must simulated a saved-name situation.
436          */
437         bzero(&cnp, sizeof(cnp));
438         cnp.cn_nameiop = NAMEI_CREATE;
439         cnp.cn_flags = CNP_LOCKPARENT;
440         cnp.cn_nameptr = ncp->nc_name;
441         cnp.cn_namelen = ncp->nc_nlen;
442         cnp.cn_cred = ap->a_cred;
443         cnp.cn_td = td;
444         *ap->a_vpp = NULL;
445
446         error = vop_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
447
448         /*
449          * EJUSTRETURN should be returned for this case, which means that
450          * the VFS has setup the directory inode for the create.  The dvp we
451          * passed in is expected to remain in a locked state.
452          *
453          * If the VOP_OLD_MKDIR is successful we are responsible for updating
454          * the cache state of the locked ncp that was passed to us.
455          */
456         if (error == EJUSTRETURN) {
457                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
458                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
459                 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
460                 if (error == 0) {
461                         cache_setunresolved(ncp);
462                         cache_setvp(ncp, *ap->a_vpp);
463                 }
464         } else {
465                 if (error == 0) {
466                         vput(*ap->a_vpp);
467                         *ap->a_vpp = NULL;
468                         error = EEXIST;
469                 }
470                 KKASSERT(*ap->a_vpp == NULL);
471         }
472         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
473                 VOP_UNLOCK(dvp, 0, td);
474         vrele(dvp);
475         return (error);
476 }
477
478 /*
479  * vop_compat_nmknod { struct namecache *a_ncp,         XXX STOPGAP FUNCTION
480  *                      struct vnode *a_vpp,
481  *                      struct ucred *a_cred,
482  *                      struct vattr *a_vap }
483  *
484  * Create a device or fifo node as specified by a_vap.  Compatibility requires
485  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
486  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
487  */
488 int
489 vop_compat_nmknod(struct vop_nmknod_args *ap)
490 {
491         struct thread *td = curthread;
492         struct componentname cnp;
493         struct namecache *ncp;
494         struct vnode *dvp;
495         int error;
496
497         /*
498          * Sanity checks, get a locked directory vnode.
499          */
500         ncp = ap->a_ncp;                /* locked namecache node */
501         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
502                 return(EPERM);
503         if (ncp->nc_parent == NULL)
504                 return(EPERM);
505         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
506                 return(EPERM);
507
508         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
509                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
510                         ncp, ncp->nc_name);
511                 return(EAGAIN);
512         }
513
514         /*
515          * Setup the cnp for a traditional vop_lookup() call.  The lookup
516          * caches all information required to create the entry in the
517          * directory inode.  We expect a return code of EJUSTRETURN for
518          * the CREATE case.  The cnp must simulated a saved-name situation.
519          */
520         bzero(&cnp, sizeof(cnp));
521         cnp.cn_nameiop = NAMEI_CREATE;
522         cnp.cn_flags = CNP_LOCKPARENT;
523         cnp.cn_nameptr = ncp->nc_name;
524         cnp.cn_namelen = ncp->nc_nlen;
525         cnp.cn_cred = ap->a_cred;
526         cnp.cn_td = td;
527         *ap->a_vpp = NULL;
528
529         error = vop_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
530
531         /*
532          * EJUSTRETURN should be returned for this case, which means that
533          * the VFS has setup the directory inode for the create.  The dvp we
534          * passed in is expected to remain in a locked state.
535          *
536          * If the VOP_OLD_MKNOD is successful we are responsible for updating
537          * the cache state of the locked ncp that was passed to us.
538          */
539         if (error == EJUSTRETURN) {
540                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
541                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
542                 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
543                 if (error == 0) {
544                         cache_setunresolved(ncp);
545                         cache_setvp(ncp, *ap->a_vpp);
546                 }
547         } else {
548                 if (error == 0) {
549                         vput(*ap->a_vpp);
550                         *ap->a_vpp = NULL;
551                         error = EEXIST;
552                 }
553                 KKASSERT(*ap->a_vpp == NULL);
554         }
555         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
556                 VOP_UNLOCK(dvp, 0, td);
557         vrele(dvp);
558         return (error);
559 }
560
561 /*
562  * vop_compat_nlink { struct namecache *a_ncp,  XXX STOPGAP FUNCTION
563  *                      struct vnode *a_vp,
564  *                      struct ucred *a_cred }
565  *
566  * The passed vp is locked and represents the source.  The passed ncp is
567  * locked and represents the target to create.
568  */
569 int
570 vop_compat_nlink(struct vop_nlink_args *ap)
571 {
572         struct thread *td = curthread;
573         struct componentname cnp;
574         struct namecache *ncp;
575         struct vnode *dvp;
576         struct vnode *tvp;
577         int error;
578
579         /*
580          * Sanity checks, get a locked directory vnode.
581          */
582         ncp = ap->a_ncp;                /* locked namecache node */
583         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
584                 return(EPERM);
585         if (ncp->nc_parent == NULL)
586                 return(EPERM);
587         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
588                 return(EPERM);
589
590         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
591                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
592                         ncp, ncp->nc_name);
593                 return(EAGAIN);
594         }
595
596         /*
597          * Setup the cnp for a traditional vop_lookup() call.  The lookup
598          * caches all information required to create the entry in the
599          * directory inode.  We expect a return code of EJUSTRETURN for
600          * the CREATE case.  The cnp must simulated a saved-name situation.
601          */
602         bzero(&cnp, sizeof(cnp));
603         cnp.cn_nameiop = NAMEI_CREATE;
604         cnp.cn_flags = CNP_LOCKPARENT;
605         cnp.cn_nameptr = ncp->nc_name;
606         cnp.cn_namelen = ncp->nc_nlen;
607         cnp.cn_cred = ap->a_cred;
608         cnp.cn_td = td;
609
610         tvp = NULL;
611         error = vop_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
612
613         /*
614          * EJUSTRETURN should be returned for this case, which means that
615          * the VFS has setup the directory inode for the create.  The dvp we
616          * passed in is expected to remain in a locked state.
617          *
618          * If the VOP_OLD_LINK is successful we are responsible for updating
619          * the cache state of the locked ncp that was passed to us.
620          */
621         if (error == EJUSTRETURN) {
622                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
623                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
624                 VOP_LEASE(ap->a_vp, td, ap->a_cred, LEASE_WRITE);
625                 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
626                 if (error == 0) {
627                         cache_setunresolved(ncp);
628                         cache_setvp(ncp, ap->a_vp);
629                 }
630         } else {
631                 if (error == 0) {
632                         vput(tvp);
633                         error = EEXIST;
634                 }
635         }
636         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
637                 VOP_UNLOCK(dvp, 0, td);
638         vrele(dvp);
639         return (error);
640 }
641
642 int
643 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
644 {
645         struct thread *td = curthread;
646         struct componentname cnp;
647         struct namecache *ncp;
648         struct vnode *dvp;
649         struct vnode *vp;
650         int error;
651
652         /*
653          * Sanity checks, get a locked directory vnode.
654          */
655         *ap->a_vpp = NULL;
656         ncp = ap->a_ncp;                /* locked namecache node */
657         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
658                 return(EPERM);
659         if (ncp->nc_parent == NULL)
660                 return(EPERM);
661         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
662                 return(EPERM);
663
664         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
665                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
666                         ncp, ncp->nc_name);
667                 return(EAGAIN);
668         }
669
670         /*
671          * Setup the cnp for a traditional vop_lookup() call.  The lookup
672          * caches all information required to create the entry in the
673          * directory inode.  We expect a return code of EJUSTRETURN for
674          * the CREATE case.  The cnp must simulated a saved-name situation.
675          */
676         bzero(&cnp, sizeof(cnp));
677         cnp.cn_nameiop = NAMEI_CREATE;
678         cnp.cn_flags = CNP_LOCKPARENT;
679         cnp.cn_nameptr = ncp->nc_name;
680         cnp.cn_namelen = ncp->nc_nlen;
681         cnp.cn_cred = ap->a_cred;
682         cnp.cn_td = td;
683
684         vp = NULL;
685         error = vop_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
686
687         /*
688          * EJUSTRETURN should be returned for this case, which means that
689          * the VFS has setup the directory inode for the create.  The dvp we
690          * passed in is expected to remain in a locked state.
691          *
692          * If the VOP_OLD_SYMLINK is successful we are responsible for updating
693          * the cache state of the locked ncp that was passed to us.
694          */
695         if (error == EJUSTRETURN) {
696                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
697                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
698                 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
699                 if (error == 0) {
700                         cache_setunresolved(ncp);
701                         cache_setvp(ncp, vp);
702                         *ap->a_vpp = vp;
703                 }
704         } else {
705                 if (error == 0) {
706                         vput(vp);
707                         vp = NULL;
708                         error = EEXIST;
709                 }
710                 KKASSERT(vp == NULL);
711         }
712         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
713                 VOP_UNLOCK(dvp, 0, td);
714         vrele(dvp);
715         return (error);
716 }
717
718 /*
719  * vop_compat_nwhiteout { struct namecache *a_ncp,      XXX STOPGAP FUNCTION
720  *                        struct ucred *a_cred,
721  *                        int a_flags }
722  *
723  * Issie a whiteout operation (create, lookup, or delete).  Compatibility 
724  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 
725  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
726  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
727  * no lookup is necessary.
728  */
729 int
730 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
731 {
732         struct thread *td = curthread;
733         struct componentname cnp;
734         struct namecache *ncp;
735         struct vnode *dvp;
736         struct vnode *vp;
737         int error;
738
739         /*
740          * Sanity checks, get a locked directory vnode.
741          */
742         ncp = ap->a_ncp;                /* locked namecache node */
743         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
744                 return(EPERM);
745         if (ncp->nc_parent == NULL)
746                 return(EPERM);
747         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
748                 return(EPERM);
749
750         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
751                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
752                         ncp, ncp->nc_name);
753                 return(EAGAIN);
754         }
755
756         /*
757          * Setup the cnp for a traditional vop_lookup() call.  The lookup
758          * caches all information required to create the entry in the
759          * directory inode.  We expect a return code of EJUSTRETURN for
760          * the CREATE case.  The cnp must simulated a saved-name situation.
761          */
762         bzero(&cnp, sizeof(cnp));
763         cnp.cn_nameiop = ap->a_flags;
764         cnp.cn_flags = CNP_LOCKPARENT;
765         cnp.cn_nameptr = ncp->nc_name;
766         cnp.cn_namelen = ncp->nc_nlen;
767         cnp.cn_cred = ap->a_cred;
768         cnp.cn_td = td;
769
770         vp = NULL;
771
772         /*
773          * EJUSTRETURN should be returned for the CREATE or DELETE cases.
774          * The VFS has setup the directory inode for the create.  The dvp we
775          * passed in is expected to remain in a locked state.
776          *
777          * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
778          * the cache state of the locked ncp that was passed to us.
779          */
780         switch(ap->a_flags) {
781         case NAMEI_DELETE:
782                 cnp.cn_flags |= CNP_DOWHITEOUT;
783                 /* fall through */
784         case NAMEI_CREATE:
785                 error = vop_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
786                 if (error == EJUSTRETURN) {
787                         KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
788                         VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
789                         error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
790                         if (error == 0)
791                                 cache_setunresolved(ncp);
792                 } else {
793                         if (error == 0) {
794                                 vput(vp);
795                                 vp = NULL;
796                                 error = EEXIST;
797                         }
798                         KKASSERT(vp == NULL);
799                 }
800                 break;
801         case NAMEI_LOOKUP:
802                 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
803                 break;
804         default:
805                 error = EINVAL;
806                 break;
807         }
808         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
809                 VOP_UNLOCK(dvp, 0, td);
810         vrele(dvp);
811         return (error);
812 }
813
814
815 /*
816  * vop_compat_nremove { struct namecache *a_ncp,        XXX STOPGAP FUNCTION
817  *                        struct ucred *a_cred }
818  */
819 int
820 vop_compat_nremove(struct vop_nremove_args *ap)
821 {
822         struct thread *td = curthread;
823         struct componentname cnp;
824         struct namecache *ncp;
825         struct vnode *dvp;
826         struct vnode *vp;
827         int error;
828
829         /*
830          * Sanity checks, get a locked directory vnode.
831          */
832         ncp = ap->a_ncp;                /* locked namecache node */
833         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
834                 return(EPERM);
835         if (ncp->nc_parent == NULL)
836                 return(EPERM);
837         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
838                 return(EPERM);
839
840         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
841                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
842                         ncp, ncp->nc_name);
843                 return(EAGAIN);
844         }
845
846         /*
847          * Setup the cnp for a traditional vop_lookup() call.  The lookup
848          * caches all information required to delete the entry in the
849          * directory inode.  We expect a return code of 0 for the DELETE
850          * case (meaning that a vp has been found).  The cnp must simulated
851          * a saved-name situation.
852          */
853         bzero(&cnp, sizeof(cnp));
854         cnp.cn_nameiop = NAMEI_DELETE;
855         cnp.cn_flags = CNP_LOCKPARENT;
856         cnp.cn_nameptr = ncp->nc_name;
857         cnp.cn_namelen = ncp->nc_nlen;
858         cnp.cn_cred = ap->a_cred;
859         cnp.cn_td = td;
860
861         /*
862          * The vnode must be a directory and must not represent the
863          * current directory.
864          */
865         vp = NULL;
866         error = vop_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
867         if (error == 0 && vp->v_type == VDIR)
868                 error = EPERM;
869         if (error == 0) {
870                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
871                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
872                 VOP_LEASE(vp, td, ap->a_cred, LEASE_WRITE);
873                 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
874                 if (error == 0) {
875                         cache_setunresolved(ncp);
876                         cache_setvp(ncp, NULL);
877                 }
878         }
879         if (vp) {
880                 if (dvp == vp)
881                         vrele(vp);
882                 else    
883                         vput(vp);
884         }
885         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
886                 VOP_UNLOCK(dvp, 0, td);
887         vrele(dvp);
888         return (error);
889 }
890
891 /*
892  * vop_compat_nrmdir { struct namecache *a_ncp,         XXX STOPGAP FUNCTION
893  *                        struct ucred *a_cred }
894  */
895 int
896 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
897 {
898         struct thread *td = curthread;
899         struct componentname cnp;
900         struct namecache *ncp;
901         struct vnode *dvp;
902         struct vnode *vp;
903         int error;
904
905         /*
906          * Sanity checks, get a locked directory vnode.
907          */
908         ncp = ap->a_ncp;                /* locked namecache node */
909         if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
910                 return(EPERM);
911         if (ncp->nc_parent == NULL)
912                 return(EPERM);
913         if ((dvp = ncp->nc_parent->nc_vp) == NULL)
914                 return(EPERM);
915
916         if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
917                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
918                         ncp, ncp->nc_name);
919                 return(EAGAIN);
920         }
921
922         /*
923          * Setup the cnp for a traditional vop_lookup() call.  The lookup
924          * caches all information required to delete the entry in the
925          * directory inode.  We expect a return code of 0 for the DELETE
926          * case (meaning that a vp has been found).  The cnp must simulated
927          * a saved-name situation.
928          */
929         bzero(&cnp, sizeof(cnp));
930         cnp.cn_nameiop = NAMEI_DELETE;
931         cnp.cn_flags = CNP_LOCKPARENT;
932         cnp.cn_nameptr = ncp->nc_name;
933         cnp.cn_namelen = ncp->nc_nlen;
934         cnp.cn_cred = ap->a_cred;
935         cnp.cn_td = td;
936
937         /*
938          * The vnode must be a directory and must not represent the
939          * current directory.
940          */
941         vp = NULL;
942         error = vop_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
943         if (error == 0 && vp->v_type != VDIR)
944                 error = ENOTDIR;
945         if (error == 0 && vp == dvp)
946                 error = EINVAL;
947         if (error == 0 && (vp->v_flag & VROOT))
948                 error = EBUSY;
949         if (error == 0) {
950                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
951                 VOP_LEASE(dvp, td, ap->a_cred, LEASE_WRITE);
952                 VOP_LEASE(vp, td, ap->a_cred, LEASE_WRITE);
953                 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
954
955                 /*
956                  * Note that this invalidation will cause any process
957                  * currently CD'd into the directory being removed to be
958                  * disconnected from the topology and not be able to ".."
959                  * back out.
960                  */
961                 if (error == 0)
962                         cache_inval(ncp, CINV_SELF|CINV_PARENT);
963         }
964         if (vp) {
965                 if (dvp == vp)
966                         vrele(vp);
967                 else    
968                         vput(vp);
969         }
970         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
971                 VOP_UNLOCK(dvp, 0, td);
972         vrele(dvp);
973         return (error);
974 }
975
976 /*
977  * vop_compat_nrename { struct namecache *a_fncp,       XXX STOPGAP FUNCTION
978  *                      struct namecache *a_tncp,
979  *                      struct ucred *a_cred }
980  *
981  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
982  * the source directory and vnode be unlocked and the target directory and
983  * vnode (if it exists) be locked.  All arguments will be vrele'd and 
984  * the targets will also be unlocked regardless of the return code.
985  */
986 int
987 vop_compat_nrename(struct vop_nrename_args *ap)
988 {
989         struct thread *td = curthread;
990         struct componentname fcnp;
991         struct componentname tcnp;
992         struct namecache *fncp;
993         struct namecache *tncp;
994         struct vnode *fdvp, *fvp;
995         struct vnode *tdvp, *tvp;
996         int error;
997
998         /*
999          * Sanity checks, get referenced vnodes representing the source.
1000          */
1001         fncp = ap->a_fncp;              /* locked namecache node */
1002         if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
1003                 return(EPERM);
1004         if (fncp->nc_parent == NULL)
1005                 return(EPERM);
1006         if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
1007                 return(EPERM);
1008
1009         /*
1010          * Temporarily lock the source directory and lookup in DELETE mode to
1011          * check permissions.  XXX delete permissions should have been
1012          * checked by nlookup(), we need to add NLC_DELETE for delete
1013          * checking.  It is unclear whether VFS's require the directory setup
1014          * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
1015          * since it isn't locked and since UFS always does a relookup of
1016          * the source, it is believed that the only side effect that matters
1017          * is the permissions check.
1018          */
1019         if ((error = vget(fdvp, LK_EXCLUSIVE, td)) != 0) {
1020                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1021                         fncp, fncp->nc_name);
1022                 return(EAGAIN);
1023         }
1024
1025         bzero(&fcnp, sizeof(fcnp));
1026         fcnp.cn_nameiop = NAMEI_DELETE;
1027         fcnp.cn_flags = CNP_LOCKPARENT;
1028         fcnp.cn_nameptr = fncp->nc_name;
1029         fcnp.cn_namelen = fncp->nc_nlen;
1030         fcnp.cn_cred = ap->a_cred;
1031         fcnp.cn_td = td;
1032
1033         /*
1034          * note: vop_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
1035          * fvp.
1036          */
1037         fvp = NULL;
1038         error = vop_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
1039         if (error == 0 && (fvp->v_flag & VROOT)) {
1040                 vput(fvp);      /* as if vop_lookup had failed */
1041                 error = EBUSY;
1042         }
1043         if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1044                 fcnp.cn_flags |= CNP_PDIRUNLOCK;
1045                 VOP_UNLOCK(fdvp, 0, td);
1046         }
1047         if (error) {
1048                 vrele(fdvp);
1049                 return (error);
1050         }
1051         VOP_UNLOCK(fvp, 0, td);
1052
1053         /*
1054          * fdvp and fvp are now referenced and unlocked.
1055          *
1056          * Get a locked directory vnode for the target and lookup the target
1057          * in CREATE mode so it places the required information in the
1058          * directory inode.
1059          */
1060         tncp = ap->a_tncp;              /* locked namecache node */
1061         if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
1062                 error = EPERM;
1063         if (tncp->nc_parent == NULL)
1064                 error = EPERM;
1065         if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
1066                 error = EPERM;
1067         if (error) {
1068                 vrele(fdvp);
1069                 vrele(fvp);
1070                 return (error);
1071         }
1072         if ((error = vget(tdvp, LK_EXCLUSIVE, td)) != 0) {
1073                 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1074                         tncp, tncp->nc_name);
1075                 vrele(fdvp);
1076                 vrele(fvp);
1077                 return(EAGAIN);
1078         }
1079
1080         /*
1081          * Setup the cnp for a traditional vop_lookup() call.  The lookup
1082          * caches all information required to create the entry in the
1083          * target directory inode.
1084          */
1085         bzero(&tcnp, sizeof(tcnp));
1086         tcnp.cn_nameiop = NAMEI_RENAME;
1087         tcnp.cn_flags = CNP_LOCKPARENT;
1088         tcnp.cn_nameptr = tncp->nc_name;
1089         tcnp.cn_namelen = tncp->nc_nlen;
1090         tcnp.cn_cred = ap->a_cred;
1091         tcnp.cn_td = td;
1092
1093         tvp = NULL;
1094         error = vop_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1095
1096         if (error == EJUSTRETURN) {
1097                 /*
1098                  * Target does not exist.  tvp should be NULL.
1099                  */
1100                 KKASSERT(tvp == NULL);
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 if (error == 0) {
1108                 /*
1109                  * Target exists.  VOP_OLD_RENAME should correctly delete the
1110                  * target.
1111                  */
1112                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1113                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1114                 if (error == 0) {
1115                         cache_rename(fncp, tncp);
1116                         cache_setvp(tncp, fvp);
1117                 }
1118         } else {
1119                 vrele(fdvp);
1120                 vrele(fvp);
1121                 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1122                         vrele(tdvp);
1123                 else
1124                         vput(tdvp);
1125         }
1126         return (error);
1127 }
1128
1129 static int
1130 vop_nolookup(ap)
1131         struct vop_lookup_args /* {
1132                 struct vnode *a_dvp;
1133                 struct vnode **a_vpp;
1134                 struct componentname *a_cnp;
1135         } */ *ap;
1136 {
1137
1138         *ap->a_vpp = NULL;
1139         return (ENOTDIR);
1140 }
1141
1142 /*
1143  *      vop_nostrategy:
1144  *
1145  *      Strategy routine for VFS devices that have none.
1146  *
1147  *      B_ERROR and B_INVAL must be cleared prior to calling any strategy
1148  *      routine.  Typically this is done for a B_READ strategy call.  Typically
1149  *      B_INVAL is assumed to already be clear prior to a write and should not
1150  *      be cleared manually unless you just made the buffer invalid.  B_ERROR
1151  *      should be cleared either way.
1152  */
1153
1154 static int
1155 vop_nostrategy (struct vop_strategy_args *ap)
1156 {
1157         printf("No strategy for buffer at %p\n", ap->a_bp);
1158         vprint("", ap->a_vp);
1159         vprint("", ap->a_bp->b_vp);
1160         ap->a_bp->b_flags |= B_ERROR;
1161         ap->a_bp->b_error = EOPNOTSUPP;
1162         biodone(ap->a_bp);
1163         return (EOPNOTSUPP);
1164 }
1165
1166 int
1167 vop_stdpathconf(ap)
1168         struct vop_pathconf_args /* {
1169         struct vnode *a_vp;
1170         int a_name;
1171         int *a_retval;
1172         } */ *ap;
1173 {
1174
1175         switch (ap->a_name) {
1176                 case _PC_LINK_MAX:
1177                         *ap->a_retval = LINK_MAX;
1178                         return (0);
1179                 case _PC_MAX_CANON:
1180                         *ap->a_retval = MAX_CANON;
1181                         return (0);
1182                 case _PC_MAX_INPUT:
1183                         *ap->a_retval = MAX_INPUT;
1184                         return (0);
1185                 case _PC_PIPE_BUF:
1186                         *ap->a_retval = PIPE_BUF;
1187                         return (0);
1188                 case _PC_CHOWN_RESTRICTED:
1189                         *ap->a_retval = 1;
1190                         return (0);
1191                 case _PC_VDISABLE:
1192                         *ap->a_retval = _POSIX_VDISABLE;
1193                         return (0);
1194                 default:
1195                         return (EINVAL);
1196         }
1197         /* NOTREACHED */
1198 }
1199
1200 /*
1201  * Standard lock.  The lock is recursive-capable only if the lock was
1202  * initialized with LK_CANRECURSE or that flag is passed in a_flags.
1203  */
1204 int
1205 vop_stdlock(ap)
1206         struct vop_lock_args /* {
1207                 struct vnode *a_vp;
1208                 int a_flags;
1209                 struct proc *a_p;
1210         } */ *ap;
1211 {               
1212         int error;
1213
1214 #ifndef DEBUG_LOCKS
1215         error = lockmgr(&ap->a_vp->v_lock, ap->a_flags, NULL, ap->a_td);
1216 #else
1217         error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags,
1218                         NULL, ap->a_td,
1219                         "vop_stdlock", ap->a_vp->filename, ap->a_vp->line);
1220 #endif
1221         return(error);
1222 }
1223
1224 int
1225 vop_stdunlock(ap)
1226         struct vop_unlock_args /* {
1227                 struct vnode *a_vp;
1228                 int a_flags;
1229                 struct thread *a_td;
1230         } */ *ap;
1231 {
1232         int error;
1233
1234         error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE,
1235                         NULL, ap->a_td);
1236         return(error);
1237 }
1238
1239 int
1240 vop_stdislocked(ap)
1241         struct vop_islocked_args /* {
1242                 struct vnode *a_vp;
1243                 struct thread *a_td;
1244         } */ *ap;
1245 {
1246         return (lockstatus(&ap->a_vp->v_lock, ap->a_td));
1247 }
1248
1249 /*
1250  * Return true for select/poll.
1251  */
1252 int
1253 vop_nopoll(ap)
1254         struct vop_poll_args /* {
1255                 struct vnode *a_vp;
1256                 int  a_events;
1257                 struct ucred *a_cred;
1258                 struct proc *a_p;
1259         } */ *ap;
1260 {
1261         /*
1262          * Return true for read/write.  If the user asked for something
1263          * special, return POLLNVAL, so that clients have a way of
1264          * determining reliably whether or not the extended
1265          * functionality is present without hard-coding knowledge
1266          * of specific filesystem implementations.
1267          */
1268         if (ap->a_events & ~POLLSTANDARD)
1269                 return (POLLNVAL);
1270
1271         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1272 }
1273
1274 /*
1275  * Implement poll for local filesystems that support it.
1276  */
1277 int
1278 vop_stdpoll(ap)
1279         struct vop_poll_args /* {
1280                 struct vnode *a_vp;
1281                 int  a_events;
1282                 struct ucred *a_cred;
1283                 struct thread *a_td;
1284         } */ *ap;
1285 {
1286         if (ap->a_events & ~POLLSTANDARD)
1287                 return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
1288         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1289 }
1290
1291 int
1292 vop_stdbwrite(ap)
1293         struct vop_bwrite_args *ap;
1294 {
1295         return (bwrite(ap->a_bp));
1296 }
1297
1298 int
1299 vop_stdcreatevobject(ap)
1300         struct vop_createvobject_args /* {
1301                 struct vnode *a_vp;
1302                 struct proc *a_td;
1303         } */ *ap;
1304 {
1305         struct vnode *vp = ap->a_vp;
1306         struct thread *td = ap->a_td;
1307         struct vattr vat;
1308         vm_object_t object;
1309         int error = 0;
1310
1311         if (!vn_isdisk(vp, NULL) && vn_canvmio(vp) == FALSE)
1312                 return (0);
1313
1314 retry:
1315         if ((object = vp->v_object) == NULL) {
1316                 if (vp->v_type == VREG || vp->v_type == VDIR) {
1317                         if ((error = VOP_GETATTR(vp, &vat, td)) != 0)
1318                                 goto retn;
1319                         object = vnode_pager_alloc(vp, vat.va_size, 0, 0);
1320                 } else if (vp->v_rdev && dev_is_good(vp->v_rdev)) {
1321                         /*
1322                          * XXX v_rdev uses NULL/non-NULL instead of NODEV
1323                          *
1324                          * This simply allocates the biggest object possible
1325                          * for a disk vnode.  This should be fixed, but doesn't
1326                          * cause any problems (yet).
1327                          */
1328                         object = vnode_pager_alloc(vp, IDX_TO_OFF(INT_MAX), 0, 0);
1329                 } else {
1330                         goto retn;
1331                 }
1332                 /*
1333                  * Dereference the reference we just created.  This assumes
1334                  * that the object is associated with the vp.
1335                  */
1336                 object->ref_count--;
1337                 vp->v_usecount--;
1338         } else {
1339                 if (object->flags & OBJ_DEAD) {
1340                         VOP_UNLOCK(vp, 0, td);
1341                         tsleep(object, 0, "vodead", 0);
1342                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1343                         goto retry;
1344                 }
1345         }
1346
1347         KASSERT(vp->v_object != NULL, ("vfs_object_create: NULL object"));
1348         vp->v_flag |= VOBJBUF;
1349
1350 retn:
1351         return (error);
1352 }
1353
1354 int
1355 vop_stddestroyvobject(ap)
1356         struct vop_destroyvobject_args /* {
1357                 struct vnode *vp;
1358         } */ *ap;
1359 {
1360         struct vnode *vp = ap->a_vp;
1361         vm_object_t obj = vp->v_object;
1362
1363         if (vp->v_object == NULL)
1364                 return (0);
1365
1366         if (obj->ref_count == 0) {
1367                 /*
1368                  * vclean() may be called twice. The first time
1369                  * removes the primary reference to the object,
1370                  * the second time goes one further and is a
1371                  * special-case to terminate the object.
1372                  *
1373                  * don't double-terminate the object.
1374                  */
1375                 if ((obj->flags & OBJ_DEAD) == 0)
1376                         vm_object_terminate(obj);
1377         } else {
1378                 /*
1379                  * Woe to the process that tries to page now :-).
1380                  */
1381                 vm_pager_deallocate(obj);
1382         }
1383         return (0);
1384 }
1385
1386 /*
1387  * Return the underlying VM object.  This routine may be called with or
1388  * without the vnode interlock held.  If called without, the returned
1389  * object is not guarenteed to be valid.  The syncer typically gets the
1390  * object without holding the interlock in order to quickly test whether
1391  * it might be dirty before going heavy-weight.  vm_object's use zalloc
1392  * and thus stable-storage, so this is safe.
1393  */
1394 int
1395 vop_stdgetvobject(ap)
1396         struct vop_getvobject_args /* {
1397                 struct vnode *vp;
1398                 struct vm_object **objpp;
1399         } */ *ap;
1400 {
1401         struct vnode *vp = ap->a_vp;
1402         struct vm_object **objpp = ap->a_objpp;
1403
1404         if (objpp)
1405                 *objpp = vp->v_object;
1406         return (vp->v_object ? 0 : EINVAL);
1407 }
1408
1409 /* 
1410  * vfs default ops
1411  * used to fill the vfs fucntion table to get reasonable default return values.
1412  */
1413 int 
1414 vfs_stdmount(struct mount *mp, char *path, caddr_t data,
1415         struct nlookupdata *nd, struct thread *td)
1416 {
1417         return (0);
1418 }
1419
1420 int     
1421 vfs_stdunmount(struct mount *mp, int mntflags, struct thread *td)
1422 {
1423         return (0);
1424 }
1425
1426 int     
1427 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1428 {
1429         return (EOPNOTSUPP);
1430 }
1431
1432 int     
1433 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct thread *td)
1434 {
1435         return (EOPNOTSUPP);
1436 }
1437
1438 int
1439 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1440 {
1441         return (EOPNOTSUPP);
1442 }
1443
1444 int     
1445 vfs_stdstart(struct mount *mp, int flags, struct thread *td)
1446 {
1447         return (0);
1448 }
1449
1450 int     
1451 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1452         caddr_t arg, struct thread *td)
1453 {
1454         return (EOPNOTSUPP);
1455 }
1456
1457 int     
1458 vfs_stdsync(struct mount *mp, int waitfor, struct thread *td)
1459 {
1460         return (0);
1461 }
1462
1463 int     
1464 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
1465 {
1466         return (EOPNOTSUPP);
1467 }
1468
1469 int     
1470 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1471 {
1472         return (EOPNOTSUPP);
1473 }
1474
1475 int 
1476 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1477         struct ucred **credanonp)
1478 {
1479         return (EOPNOTSUPP);
1480 }
1481
1482 int
1483 vfs_stdinit(struct vfsconf *vfsp)
1484 {
1485         return (0);
1486 }
1487
1488 int
1489 vfs_stduninit(struct vfsconf *vfsp)
1490 {
1491         return(0);
1492 }
1493
1494 int
1495 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1496         caddr_t arg, struct thread *td)
1497 {
1498         return(EOPNOTSUPP);
1499 }
1500
1501 /* end of vfs default ops */