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