Merge branch 'vendor/MPC'
[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  * The statvfs->statfs conversion code was contributed to the DragonFly
9  * Project by Joerg Sonnenberger <joerg@bec.de>.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
40  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
41  */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 #include <sys/conf.h>
47 #include <sys/fcntl.h>
48 #include <sys/file.h>
49 #include <sys/kernel.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/mount.h>
53 #include <sys/unistd.h>
54 #include <sys/vnode.h>
55 #include <sys/namei.h>
56 #include <sys/nlookup.h>
57 #include <sys/mountctl.h>
58 #include <sys/vfs_quota.h>
59
60 #include <machine/limits.h>
61
62 #include <vm/vm.h>
63 #include <vm/vm_object.h>
64 #include <vm/vm_page.h>
65 #include <vm/vm_pager.h>
66 #include <vm/vnode_pager.h>
67
68 static int      vop_nolookup (struct vop_old_lookup_args *);
69 static int      vop_nostrategy (struct vop_strategy_args *);
70
71 /*
72  * This vnode table stores what we want to do if the filesystem doesn't
73  * implement a particular VOP.
74  *
75  * If there is no specific entry here, we will return EOPNOTSUPP.
76  */
77 struct vop_ops default_vnode_vops = {
78         .vop_default            = vop_eopnotsupp,
79         .vop_advlock            = (void *)vop_einval,
80         .vop_fsync              = (void *)vop_null,
81         .vop_ioctl              = (void *)vop_enotty,
82         .vop_mmap               = (void *)vop_einval,
83         .vop_old_lookup         = vop_nolookup,
84         .vop_open               = vop_stdopen,
85         .vop_close              = vop_stdclose,
86         .vop_pathconf           = vop_stdpathconf,
87         .vop_readlink           = (void *)vop_einval,
88         .vop_reallocblks        = (void *)vop_eopnotsupp,
89         .vop_strategy           = vop_nostrategy,
90         .vop_getacl             = (void *)vop_eopnotsupp,
91         .vop_setacl             = (void *)vop_eopnotsupp,
92         .vop_aclcheck           = (void *)vop_eopnotsupp,
93         .vop_getextattr         = (void *)vop_eopnotsupp,
94         .vop_setextattr         = (void *)vop_eopnotsupp,
95         .vop_markatime          = vop_stdmarkatime,
96         .vop_nresolve           = vop_compat_nresolve,
97         .vop_nlookupdotdot      = vop_compat_nlookupdotdot,
98         .vop_ncreate            = vop_compat_ncreate,
99         .vop_nmkdir             = vop_compat_nmkdir,
100         .vop_nmknod             = vop_compat_nmknod,
101         .vop_nlink              = vop_compat_nlink,
102         .vop_nsymlink           = vop_compat_nsymlink,
103         .vop_nwhiteout          = vop_compat_nwhiteout,
104         .vop_nremove            = vop_compat_nremove,
105         .vop_nrmdir             = vop_compat_nrmdir,
106         .vop_nrename            = vop_compat_nrename,
107         .vop_mountctl           = vop_stdmountctl
108 };
109
110 VNODEOP_SET(default_vnode_vops);
111
112 int
113 vop_eopnotsupp(struct vop_generic_args *ap)
114 {
115         return (EOPNOTSUPP);
116 }
117
118 int
119 vop_ebadf(struct vop_generic_args *ap)
120 {
121         return (EBADF);
122 }
123
124 int
125 vop_enotty(struct vop_generic_args *ap)
126 {
127         return (ENOTTY);
128 }
129
130 int
131 vop_einval(struct vop_generic_args *ap)
132 {
133         return (EINVAL);
134 }
135
136 int
137 vop_stdmarkatime(struct vop_markatime_args *ap)
138 {
139         return (EOPNOTSUPP);
140 }
141
142 int
143 vop_null(struct vop_generic_args *ap)
144 {
145         return (0);
146 }
147
148 int
149 vop_defaultop(struct vop_generic_args *ap)
150 {
151         return (VOCALL(&default_vnode_vops, ap));
152 }
153
154 int
155 vop_panic(struct vop_generic_args *ap)
156 {
157         panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
158 }
159
160 /*
161  * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
162  * XXX STOPGAP FUNCTION
163  *
164  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
165  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
166  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a 
167  * vop_old_lookup() and does appropriate translations.
168  *
169  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
170  * VFSs will support this VOP and this routine can be removed, since
171  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
172  * API.
173  *
174  * A locked ncp is passed in to be resolved.  The NCP is resolved by
175  * figuring out the vnode (if any) and calling cache_setvp() to attach the
176  * vnode to the entry.  If the entry represents a non-existant node then
177  * cache_setvp() is called with a NULL vnode to resolve the entry into a
178  * negative cache entry.  No vnode locks are retained and the
179  * ncp is left locked on return.
180  *
181  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
182  *
183  * There is a potential directory and vnode interlock.   The lock order
184  * requirement is: namecache, governing directory, resolved vnode.
185  */
186 int
187 vop_compat_nresolve(struct vop_nresolve_args *ap)
188 {
189         int error;
190         struct vnode *dvp;
191         struct vnode *vp;
192         struct nchandle *nch;
193         struct namecache *ncp;
194         struct componentname cnp;
195
196         nch = ap->a_nch;        /* locked namecache node */
197         ncp = nch->ncp;
198         dvp = ap->a_dvp;
199
200         /*
201          * UFS currently stores all sorts of side effects, including a loop
202          * variable, in the directory inode.  That needs to be fixed and the
203          * other VFS's audited before we can switch to LK_SHARED.
204          */
205         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
206                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
207                         ncp, ncp->nc_name);
208                 return(EAGAIN);
209         }
210
211         bzero(&cnp, sizeof(cnp));
212         cnp.cn_nameiop = NAMEI_LOOKUP;
213         cnp.cn_flags = 0;
214         cnp.cn_nameptr = ncp->nc_name;
215         cnp.cn_namelen = ncp->nc_nlen;
216         cnp.cn_cred = ap->a_cred;
217         cnp.cn_td = curthread; /* XXX */
218
219         /*
220          * vop_old_lookup() always returns vp locked.  dvp may or may not be
221          * left locked depending on CNP_PDIRUNLOCK.
222          */
223         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
224         if (error == 0)
225                 vn_unlock(vp);
226         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
227                 vn_unlock(dvp);
228         if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
229                 /* was resolved by another process while we were unlocked */
230                 if (error == 0)
231                         vrele(vp);
232         } else if (error == 0) {
233                 KKASSERT(vp != NULL);
234                 cache_setvp(nch, vp);
235                 vrele(vp);
236         } else if (error == ENOENT) {
237                 KKASSERT(vp == NULL);
238                 if (cnp.cn_flags & CNP_ISWHITEOUT)
239                         ncp->nc_flag |= NCF_WHITEOUT;
240                 cache_setvp(nch, NULL);
241         }
242         vrele(dvp);
243         return (error);
244 }
245
246 /*
247  * vop_compat_nlookupdotdot { struct vnode *a_dvp,
248  *                      struct vnode **a_vpp,
249  *                      struct ucred *a_cred }
250  *
251  * Lookup the vnode representing the parent directory of the specified
252  * directory vnode.  a_dvp should not be locked.  If no error occurs *a_vpp
253  * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
254  *
255  * This function is designed to aid NFS server-side operations and is
256  * used by cache_fromdvp() to create a consistent, connected namecache
257  * topology.
258  *
259  * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
260  * code out from their *_lookup() and create *_nlookupdotdot().  Then as time
261  * permits VFSs will implement the remaining *_n*() calls and finally get
262  * rid of their *_lookup() call.
263  */
264 int
265 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
266 {
267         struct componentname cnp;
268         int error;
269
270         /*
271          * UFS currently stores all sorts of side effects, including a loop
272          * variable, in the directory inode.  That needs to be fixed and the
273          * other VFS's audited before we can switch to LK_SHARED.
274          */
275         *ap->a_vpp = NULL;
276         if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
277                 return (error);
278         if (ap->a_dvp->v_type != VDIR) {
279                 vput(ap->a_dvp);
280                 return (ENOTDIR);
281         }
282
283         bzero(&cnp, sizeof(cnp));
284         cnp.cn_nameiop = NAMEI_LOOKUP;
285         cnp.cn_flags = CNP_ISDOTDOT;
286         cnp.cn_nameptr = "..";
287         cnp.cn_namelen = 2;
288         cnp.cn_cred = ap->a_cred;
289         cnp.cn_td = curthread; /* XXX */
290
291         /*
292          * vop_old_lookup() always returns vp locked.  dvp may or may not be
293          * left locked depending on CNP_PDIRUNLOCK.
294          *
295          * (*vpp) will be returned locked if no error occured, which is the
296          * state we want.
297          */
298         error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
299         if (cnp.cn_flags & CNP_PDIRUNLOCK)
300                 vrele(ap->a_dvp);
301         else
302                 vput(ap->a_dvp);
303         return (error);
304 }
305
306 /*
307  * vop_compat_ncreate { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
308  *                      struct vnode *a_dvp,
309  *                      struct vnode **a_vpp,
310  *                      struct ucred *a_cred,
311  *                      struct vattr *a_vap }
312  *
313  * Create a file as specified by a_vap.  Compatibility requires us to issue
314  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
315  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
316  */
317 int
318 vop_compat_ncreate(struct vop_ncreate_args *ap)
319 {
320         struct thread *td = curthread;
321         struct componentname cnp;
322         struct nchandle *nch;
323         struct namecache *ncp;
324         struct vnode *dvp;
325         int error;
326
327         /*
328          * Sanity checks, get a locked directory vnode.
329          */
330         nch = ap->a_nch;                /* locked namecache node */
331         dvp = ap->a_dvp;
332         ncp = nch->ncp;
333
334         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
335                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
336                         ncp, ncp->nc_name);
337                 return(EAGAIN);
338         }
339
340         /*
341          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
342          * caches all information required to create the entry in the
343          * directory inode.  We expect a return code of EJUSTRETURN for
344          * the CREATE case.  The cnp must simulated a saved-name situation.
345          */
346         bzero(&cnp, sizeof(cnp));
347         cnp.cn_nameiop = NAMEI_CREATE;
348         cnp.cn_flags = CNP_LOCKPARENT;
349         cnp.cn_nameptr = ncp->nc_name;
350         cnp.cn_namelen = ncp->nc_nlen;
351         cnp.cn_cred = ap->a_cred;
352         cnp.cn_td = td;
353         *ap->a_vpp = NULL;
354
355         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
356
357         /*
358          * EJUSTRETURN should be returned for this case, which means that
359          * the VFS has setup the directory inode for the create.  The dvp we
360          * passed in is expected to remain in a locked state.
361          *
362          * If the VOP_OLD_CREATE is successful we are responsible for updating
363          * the cache state of the locked ncp that was passed to us.
364          */
365         if (error == EJUSTRETURN) {
366                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
367                 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
368                 if (error == 0) {
369                         cache_setunresolved(nch);
370                         cache_setvp(nch, *ap->a_vpp);
371                 }
372         } else {
373                 if (error == 0) {
374                         vput(*ap->a_vpp);
375                         *ap->a_vpp = NULL;
376                         error = EEXIST;
377                 }
378                 KKASSERT(*ap->a_vpp == NULL);
379         }
380         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
381                 vn_unlock(dvp);
382         vrele(dvp);
383         return (error);
384 }
385
386 /*
387  * vop_compat_nmkdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
388  *                      struct vnode *a_dvp,
389  *                      struct vnode **a_vpp,
390  *                      struct ucred *a_cred,
391  *                      struct vattr *a_vap }
392  *
393  * Create a directory as specified by a_vap.  Compatibility requires us to
394  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
395  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
396  */
397 int
398 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
399 {
400         struct thread *td = curthread;
401         struct componentname cnp;
402         struct nchandle *nch;
403         struct namecache *ncp;
404         struct vnode *dvp;
405         int error;
406
407         /*
408          * Sanity checks, get a locked directory vnode.
409          */
410         nch = ap->a_nch;                /* locked namecache node */
411         ncp = nch->ncp;
412         dvp = ap->a_dvp;
413         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
414                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
415                         ncp, ncp->nc_name);
416                 return(EAGAIN);
417         }
418
419         /*
420          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
421          * caches all information required to create the entry in the
422          * directory inode.  We expect a return code of EJUSTRETURN for
423          * the CREATE case.  The cnp must simulated a saved-name situation.
424          */
425         bzero(&cnp, sizeof(cnp));
426         cnp.cn_nameiop = NAMEI_CREATE;
427         cnp.cn_flags = CNP_LOCKPARENT;
428         cnp.cn_nameptr = ncp->nc_name;
429         cnp.cn_namelen = ncp->nc_nlen;
430         cnp.cn_cred = ap->a_cred;
431         cnp.cn_td = td;
432         *ap->a_vpp = NULL;
433
434         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
435
436         /*
437          * EJUSTRETURN should be returned for this case, which means that
438          * the VFS has setup the directory inode for the create.  The dvp we
439          * passed in is expected to remain in a locked state.
440          *
441          * If the VOP_OLD_MKDIR is successful we are responsible for updating
442          * the cache state of the locked ncp that was passed to us.
443          */
444         if (error == EJUSTRETURN) {
445                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
446                 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
447                 if (error == 0) {
448                         cache_setunresolved(nch);
449                         cache_setvp(nch, *ap->a_vpp);
450                 }
451         } else {
452                 if (error == 0) {
453                         vput(*ap->a_vpp);
454                         *ap->a_vpp = NULL;
455                         error = EEXIST;
456                 }
457                 KKASSERT(*ap->a_vpp == NULL);
458         }
459         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
460                 vn_unlock(dvp);
461         vrele(dvp);
462         return (error);
463 }
464
465 /*
466  * vop_compat_nmknod { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
467  *                      struct vnode *a_dvp,
468  *                      struct vnode **a_vpp,
469  *                      struct ucred *a_cred,
470  *                      struct vattr *a_vap }
471  *
472  * Create a device or fifo node as specified by a_vap.  Compatibility requires
473  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
474  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
475  */
476 int
477 vop_compat_nmknod(struct vop_nmknod_args *ap)
478 {
479         struct thread *td = curthread;
480         struct componentname cnp;
481         struct nchandle *nch;
482         struct namecache *ncp;
483         struct vnode *dvp;
484         int error;
485
486         /*
487          * Sanity checks, get a locked directory vnode.
488          */
489         nch = ap->a_nch;                /* locked namecache node */
490         ncp = nch->ncp;
491         dvp = ap->a_dvp;
492
493         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
494                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
495                         ncp, ncp->nc_name);
496                 return(EAGAIN);
497         }
498
499         /*
500          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
501          * caches all information required to create the entry in the
502          * directory inode.  We expect a return code of EJUSTRETURN for
503          * the CREATE case.  The cnp must simulated a saved-name situation.
504          */
505         bzero(&cnp, sizeof(cnp));
506         cnp.cn_nameiop = NAMEI_CREATE;
507         cnp.cn_flags = CNP_LOCKPARENT;
508         cnp.cn_nameptr = ncp->nc_name;
509         cnp.cn_namelen = ncp->nc_nlen;
510         cnp.cn_cred = ap->a_cred;
511         cnp.cn_td = td;
512         *ap->a_vpp = NULL;
513
514         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
515
516         /*
517          * EJUSTRETURN should be returned for this case, which means that
518          * the VFS has setup the directory inode for the create.  The dvp we
519          * passed in is expected to remain in a locked state.
520          *
521          * If the VOP_OLD_MKNOD is successful we are responsible for updating
522          * the cache state of the locked ncp that was passed to us.
523          */
524         if (error == EJUSTRETURN) {
525                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
526                 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
527                 if (error == 0) {
528                         cache_setunresolved(nch);
529                         cache_setvp(nch, *ap->a_vpp);
530                 }
531         } else {
532                 if (error == 0) {
533                         vput(*ap->a_vpp);
534                         *ap->a_vpp = NULL;
535                         error = EEXIST;
536                 }
537                 KKASSERT(*ap->a_vpp == NULL);
538         }
539         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
540                 vn_unlock(dvp);
541         vrele(dvp);
542         return (error);
543 }
544
545 /*
546  * vop_compat_nlink { struct nchandle *a_nch,   XXX STOPGAP FUNCTION
547  *                      struct vnode *a_dvp,
548  *                      struct vnode *a_vp,
549  *                      struct ucred *a_cred }
550  *
551  * The passed vp is locked and represents the source.  The passed ncp is
552  * locked and represents the target to create.
553  */
554 int
555 vop_compat_nlink(struct vop_nlink_args *ap)
556 {
557         struct thread *td = curthread;
558         struct componentname cnp;
559         struct nchandle *nch;
560         struct namecache *ncp;
561         struct vnode *dvp;
562         struct vnode *tvp;
563         int error;
564
565         /*
566          * Sanity checks, get a locked directory vnode.
567          */
568         nch = ap->a_nch;                /* locked namecache node */
569         ncp = nch->ncp;
570         dvp = ap->a_dvp;
571
572         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
573                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
574                         ncp, ncp->nc_name);
575                 return(EAGAIN);
576         }
577
578         /*
579          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
580          * caches all information required to create the entry in the
581          * directory inode.  We expect a return code of EJUSTRETURN for
582          * the CREATE case.  The cnp must simulated a saved-name situation.
583          */
584         bzero(&cnp, sizeof(cnp));
585         cnp.cn_nameiop = NAMEI_CREATE;
586         cnp.cn_flags = CNP_LOCKPARENT;
587         cnp.cn_nameptr = ncp->nc_name;
588         cnp.cn_namelen = ncp->nc_nlen;
589         cnp.cn_cred = ap->a_cred;
590         cnp.cn_td = td;
591
592         tvp = NULL;
593         error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
594
595         /*
596          * EJUSTRETURN should be returned for this case, which means that
597          * the VFS has setup the directory inode for the create.  The dvp we
598          * passed in is expected to remain in a locked state.
599          *
600          * If the VOP_OLD_LINK is successful we are responsible for updating
601          * the cache state of the locked ncp that was passed to us.
602          */
603         if (error == EJUSTRETURN) {
604                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
605                 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
606                 if (error == 0) {
607                         cache_setunresolved(nch);
608                         cache_setvp(nch, ap->a_vp);
609                 }
610         } else {
611                 if (error == 0) {
612                         vput(tvp);
613                         error = EEXIST;
614                 }
615         }
616         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
617                 vn_unlock(dvp);
618         vrele(dvp);
619         return (error);
620 }
621
622 int
623 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
624 {
625         struct thread *td = curthread;
626         struct componentname cnp;
627         struct nchandle *nch;
628         struct namecache *ncp;
629         struct vnode *dvp;
630         struct vnode *vp;
631         int error;
632
633         /*
634          * Sanity checks, get a locked directory vnode.
635          */
636         *ap->a_vpp = NULL;
637         nch = ap->a_nch;                /* locked namecache node */
638         ncp = nch->ncp;
639         dvp = ap->a_dvp;
640
641         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
642                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
643                         ncp, ncp->nc_name);
644                 return(EAGAIN);
645         }
646
647         /*
648          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
649          * caches all information required to create the entry in the
650          * directory inode.  We expect a return code of EJUSTRETURN for
651          * the CREATE case.  The cnp must simulated a saved-name situation.
652          */
653         bzero(&cnp, sizeof(cnp));
654         cnp.cn_nameiop = NAMEI_CREATE;
655         cnp.cn_flags = CNP_LOCKPARENT;
656         cnp.cn_nameptr = ncp->nc_name;
657         cnp.cn_namelen = ncp->nc_nlen;
658         cnp.cn_cred = ap->a_cred;
659         cnp.cn_td = td;
660
661         vp = NULL;
662         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
663
664         /*
665          * EJUSTRETURN should be returned for this case, which means that
666          * the VFS has setup the directory inode for the create.  The dvp we
667          * passed in is expected to remain in a locked state.
668          *
669          * If the VOP_OLD_SYMLINK is successful we are responsible for updating
670          * the cache state of the locked ncp that was passed to us.
671          */
672         if (error == EJUSTRETURN) {
673                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
674                 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
675                 if (error == 0) {
676                         cache_setunresolved(nch);
677                         cache_setvp(nch, vp);
678                         *ap->a_vpp = vp;
679                 }
680         } else {
681                 if (error == 0) {
682                         vput(vp);
683                         vp = NULL;
684                         error = EEXIST;
685                 }
686                 KKASSERT(vp == NULL);
687         }
688         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
689                 vn_unlock(dvp);
690         vrele(dvp);
691         return (error);
692 }
693
694 /*
695  * vop_compat_nwhiteout { struct nchandle *a_nch,       XXX STOPGAP FUNCTION
696  *                        struct vnode *a_dvp,
697  *                        struct ucred *a_cred,
698  *                        int a_flags }
699  *
700  * Issie a whiteout operation (create, lookup, or delete).  Compatibility 
701  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 
702  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
703  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
704  * no lookup is necessary.
705  */
706 int
707 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
708 {
709         struct thread *td = curthread;
710         struct componentname cnp;
711         struct nchandle *nch;
712         struct namecache *ncp;
713         struct vnode *dvp;
714         struct vnode *vp;
715         int error;
716
717         /*
718          * Sanity checks, get a locked directory vnode.
719          */
720         nch = ap->a_nch;                /* locked namecache node */
721         ncp = nch->ncp;
722         dvp = ap->a_dvp;
723
724         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
725                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
726                         ncp, ncp->nc_name);
727                 return(EAGAIN);
728         }
729
730         /*
731          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
732          * caches all information required to create the entry in the
733          * directory inode.  We expect a return code of EJUSTRETURN for
734          * the CREATE case.  The cnp must simulated a saved-name situation.
735          */
736         bzero(&cnp, sizeof(cnp));
737         cnp.cn_nameiop = ap->a_flags;
738         cnp.cn_flags = CNP_LOCKPARENT;
739         cnp.cn_nameptr = ncp->nc_name;
740         cnp.cn_namelen = ncp->nc_nlen;
741         cnp.cn_cred = ap->a_cred;
742         cnp.cn_td = td;
743
744         vp = NULL;
745
746         /*
747          * EJUSTRETURN should be returned for the CREATE or DELETE cases.
748          * The VFS has setup the directory inode for the create.  The dvp we
749          * passed in is expected to remain in a locked state.
750          *
751          * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
752          * the cache state of the locked ncp that was passed to us.
753          */
754         switch(ap->a_flags) {
755         case NAMEI_DELETE:
756                 cnp.cn_flags |= CNP_DOWHITEOUT;
757                 /* fall through */
758         case NAMEI_CREATE:
759                 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
760                 if (error == EJUSTRETURN) {
761                         KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
762                         error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
763                         if (error == 0)
764                                 cache_setunresolved(nch);
765                 } else {
766                         if (error == 0) {
767                                 vput(vp);
768                                 vp = NULL;
769                                 error = EEXIST;
770                         }
771                         KKASSERT(vp == NULL);
772                 }
773                 break;
774         case NAMEI_LOOKUP:
775                 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
776                 break;
777         default:
778                 error = EINVAL;
779                 break;
780         }
781         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
782                 vn_unlock(dvp);
783         vrele(dvp);
784         return (error);
785 }
786
787
788 /*
789  * vop_compat_nremove { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
790  *                      struct vnode *a_dvp,
791  *                      struct ucred *a_cred }
792  */
793 int
794 vop_compat_nremove(struct vop_nremove_args *ap)
795 {
796         struct thread *td = curthread;
797         struct componentname cnp;
798         struct nchandle *nch;
799         struct namecache *ncp;
800         struct vnode *dvp;
801         struct vnode *vp;
802         int error;
803
804         /*
805          * Sanity checks, get a locked directory vnode.
806          */
807         nch = ap->a_nch;                /* locked namecache node */
808         ncp = nch->ncp;
809         dvp = ap->a_dvp;
810
811         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
812                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
813                         ncp, ncp->nc_name);
814                 return(EAGAIN);
815         }
816
817         /*
818          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
819          * caches all information required to delete the entry in the
820          * directory inode.  We expect a return code of 0 for the DELETE
821          * case (meaning that a vp has been found).  The cnp must simulated
822          * a saved-name situation.
823          */
824         bzero(&cnp, sizeof(cnp));
825         cnp.cn_nameiop = NAMEI_DELETE;
826         cnp.cn_flags = CNP_LOCKPARENT;
827         cnp.cn_nameptr = ncp->nc_name;
828         cnp.cn_namelen = ncp->nc_nlen;
829         cnp.cn_cred = ap->a_cred;
830         cnp.cn_td = td;
831
832         /*
833          * The vnode must be a directory and must not represent the
834          * current directory.
835          */
836         vp = NULL;
837         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
838         if (error == 0 && vp->v_type == VDIR)
839                 error = EPERM;
840         if (error == 0) {
841                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
842                 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
843                 if (error == 0)
844                         cache_unlink(nch);
845         }
846         if (vp) {
847                 if (dvp == vp)
848                         vrele(vp);
849                 else    
850                         vput(vp);
851         }
852         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
853                 vn_unlock(dvp);
854         vrele(dvp);
855         return (error);
856 }
857
858 /*
859  * vop_compat_nrmdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
860  *                     struct vnode *dvp,
861  *                     struct ucred *a_cred }
862  */
863 int
864 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
865 {
866         struct thread *td = curthread;
867         struct componentname cnp;
868         struct nchandle *nch;
869         struct namecache *ncp;
870         struct vnode *dvp;
871         struct vnode *vp;
872         int error;
873
874         /*
875          * Sanity checks, get a locked directory vnode.
876          */
877         nch = ap->a_nch;                /* locked namecache node */
878         ncp = nch->ncp;
879         dvp = ap->a_dvp;
880
881         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
882                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
883                         ncp, ncp->nc_name);
884                 return(EAGAIN);
885         }
886
887         /*
888          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
889          * caches all information required to delete the entry in the
890          * directory inode.  We expect a return code of 0 for the DELETE
891          * case (meaning that a vp has been found).  The cnp must simulated
892          * a saved-name situation.
893          */
894         bzero(&cnp, sizeof(cnp));
895         cnp.cn_nameiop = NAMEI_DELETE;
896         cnp.cn_flags = CNP_LOCKPARENT;
897         cnp.cn_nameptr = ncp->nc_name;
898         cnp.cn_namelen = ncp->nc_nlen;
899         cnp.cn_cred = ap->a_cred;
900         cnp.cn_td = td;
901
902         /*
903          * The vnode must be a directory and must not represent the
904          * current directory.
905          */
906         vp = NULL;
907         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
908         if (error == 0 && vp->v_type != VDIR)
909                 error = ENOTDIR;
910         if (error == 0 && vp == dvp)
911                 error = EINVAL;
912         if (error == 0 && (vp->v_flag & VROOT))
913                 error = EBUSY;
914         if (error == 0) {
915                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
916                 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
917
918                 /*
919                  * Note that this invalidation will cause any process
920                  * currently CD'd into the directory being removed to be
921                  * disconnected from the topology and not be able to ".."
922                  * back out.
923                  */
924                 if (error == 0) {
925                         cache_inval(nch, CINV_DESTROY);
926                         cache_inval_vp(vp, CINV_DESTROY);
927                 }
928         }
929         if (vp) {
930                 if (dvp == vp)
931                         vrele(vp);
932                 else    
933                         vput(vp);
934         }
935         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
936                 vn_unlock(dvp);
937         vrele(dvp);
938         return (error);
939 }
940
941 /*
942  * vop_compat_nrename { struct nchandle *a_fnch,        XXX STOPGAP FUNCTION
943  *                      struct nchandle *a_tnch,
944  *                      struct ucred *a_cred }
945  *
946  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
947  * the source directory and vnode be unlocked and the target directory and
948  * vnode (if it exists) be locked.  All arguments will be vrele'd and 
949  * the targets will also be unlocked regardless of the return code.
950  */
951 int
952 vop_compat_nrename(struct vop_nrename_args *ap)
953 {
954         struct thread *td = curthread;
955         struct componentname fcnp;
956         struct componentname tcnp;
957         struct nchandle *fnch;
958         struct nchandle *tnch;
959         struct namecache *fncp;
960         struct namecache *tncp;
961         struct vnode *fdvp, *fvp;
962         struct vnode *tdvp, *tvp;
963         int error;
964
965         /*
966          * Sanity checks, get referenced vnodes representing the source.
967          */
968         fnch = ap->a_fnch;              /* locked namecache node */
969         fncp = fnch->ncp;
970         fdvp = ap->a_fdvp;
971
972         /*
973          * Temporarily lock the source directory and lookup in DELETE mode to
974          * check permissions.  XXX delete permissions should have been
975          * checked by nlookup(), we need to add NLC_DELETE for delete
976          * checking.  It is unclear whether VFS's require the directory setup
977          * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
978          * since it isn't locked and since UFS always does a relookup of
979          * the source, it is believed that the only side effect that matters
980          * is the permissions check.
981          */
982         if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
983                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
984                         fncp, fncp->nc_name);
985                 return(EAGAIN);
986         }
987
988         bzero(&fcnp, sizeof(fcnp));
989         fcnp.cn_nameiop = NAMEI_DELETE;
990         fcnp.cn_flags = CNP_LOCKPARENT;
991         fcnp.cn_nameptr = fncp->nc_name;
992         fcnp.cn_namelen = fncp->nc_nlen;
993         fcnp.cn_cred = ap->a_cred;
994         fcnp.cn_td = td;
995
996         /*
997          * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
998          * fvp.
999          */
1000         fvp = NULL;
1001         error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
1002         if (error == 0 && (fvp->v_flag & VROOT)) {
1003                 vput(fvp);      /* as if vop_old_lookup had failed */
1004                 error = EBUSY;
1005         }
1006         if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1007                 fcnp.cn_flags |= CNP_PDIRUNLOCK;
1008                 vn_unlock(fdvp);
1009         }
1010         if (error) {
1011                 vrele(fdvp);
1012                 return (error);
1013         }
1014         vn_unlock(fvp);
1015
1016         /*
1017          * fdvp and fvp are now referenced and unlocked.
1018          *
1019          * Get a locked directory vnode for the target and lookup the target
1020          * in CREATE mode so it places the required information in the
1021          * directory inode.
1022          */
1023         tnch = ap->a_tnch;              /* locked namecache node */
1024         tncp = tnch->ncp;
1025         tdvp = ap->a_tdvp;
1026         if (error) {
1027                 vrele(fdvp);
1028                 vrele(fvp);
1029                 return (error);
1030         }
1031         if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
1032                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1033                         tncp, tncp->nc_name);
1034                 vrele(fdvp);
1035                 vrele(fvp);
1036                 return(EAGAIN);
1037         }
1038
1039         /*
1040          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
1041          * caches all information required to create the entry in the
1042          * target directory inode.
1043          */
1044         bzero(&tcnp, sizeof(tcnp));
1045         tcnp.cn_nameiop = NAMEI_RENAME;
1046         tcnp.cn_flags = CNP_LOCKPARENT;
1047         tcnp.cn_nameptr = tncp->nc_name;
1048         tcnp.cn_namelen = tncp->nc_nlen;
1049         tcnp.cn_cred = ap->a_cred;
1050         tcnp.cn_td = td;
1051
1052         tvp = NULL;
1053         error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1054
1055         if (error == EJUSTRETURN) {
1056                 /*
1057                  * Target does not exist.  tvp should be NULL.
1058                  */
1059                 KKASSERT(tvp == NULL);
1060                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1061                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1062                 if (error == 0)
1063                         cache_rename(fnch, tnch);
1064         } else if (error == 0) {
1065                 /*
1066                  * Target exists.  VOP_OLD_RENAME should correctly delete the
1067                  * target.
1068                  */
1069                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1070                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1071                 if (error == 0)
1072                         cache_rename(fnch, tnch);
1073         } else {
1074                 vrele(fdvp);
1075                 vrele(fvp);
1076                 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1077                         vrele(tdvp);
1078                 else
1079                         vput(tdvp);
1080         }
1081         return (error);
1082 }
1083
1084 static int
1085 vop_nolookup(struct vop_old_lookup_args *ap)
1086 {
1087
1088         *ap->a_vpp = NULL;
1089         return (ENOTDIR);
1090 }
1091
1092 /*
1093  *      vop_nostrategy:
1094  *
1095  *      Strategy routine for VFS devices that have none.
1096  *
1097  *      B_ERROR and B_INVAL must be cleared prior to calling any strategy
1098  *      routine.  Typically this is done for a BUF_CMD_READ strategy call.
1099  *      Typically B_INVAL is assumed to already be clear prior to a write
1100  *      and should not be cleared manually unless you just made the buffer
1101  *      invalid.  B_ERROR should be cleared either way.
1102  */
1103
1104 static int
1105 vop_nostrategy (struct vop_strategy_args *ap)
1106 {
1107         kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1108         vprint("", ap->a_vp);
1109         ap->a_bio->bio_buf->b_flags |= B_ERROR;
1110         ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1111         biodone(ap->a_bio);
1112         return (EOPNOTSUPP);
1113 }
1114
1115 int
1116 vop_stdpathconf(struct vop_pathconf_args *ap)
1117 {
1118         int error = 0;
1119
1120         switch (ap->a_name) {
1121         case _PC_LINK_MAX:
1122                 *ap->a_retval = LINK_MAX;
1123                 break;
1124         case _PC_NAME_MAX:
1125                 *ap->a_retval = NAME_MAX;
1126                 break;
1127         case _PC_PATH_MAX:
1128                 *ap->a_retval = PATH_MAX;
1129                 break;
1130         case _PC_MAX_CANON:
1131                 *ap->a_retval = MAX_CANON;
1132                 break;
1133         case _PC_MAX_INPUT:
1134                 *ap->a_retval = MAX_INPUT;
1135                 break;
1136         case _PC_PIPE_BUF:
1137                 *ap->a_retval = PIPE_BUF;
1138                 break;
1139         case _PC_CHOWN_RESTRICTED:
1140                 *ap->a_retval = 1;
1141                 break;
1142         case _PC_NO_TRUNC:
1143                 *ap->a_retval = 1;
1144                 break;
1145         case _PC_VDISABLE:
1146                 *ap->a_retval = _POSIX_VDISABLE;
1147                 break;
1148         default:
1149                 error = EINVAL;
1150                 break;
1151         }
1152         return (error);
1153 }
1154
1155 /*
1156  * Standard open.
1157  *
1158  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
1159  *
1160  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1161  */
1162 int
1163 vop_stdopen(struct vop_open_args *ap)
1164 {
1165         struct vnode *vp = ap->a_vp;
1166         struct file *fp;
1167
1168         if ((fp = ap->a_fp) != NULL) {
1169                 switch(vp->v_type) {
1170                 case VFIFO:
1171                         fp->f_type = DTYPE_FIFO;
1172                         break;
1173                 default:
1174                         fp->f_type = DTYPE_VNODE;
1175                         break;
1176                 }
1177                 fp->f_flag = ap->a_mode & FMASK;
1178                 fp->f_ops = &vnode_fileops;
1179                 fp->f_data = vp;
1180                 vref(vp);
1181         }
1182         if (ap->a_mode & FWRITE)
1183                 ++vp->v_writecount;
1184         KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1185         ++vp->v_opencount;
1186         return (0);
1187 }
1188
1189 /*
1190  * Standard close.
1191  *
1192  * (struct vnode *a_vp, int a_fflag)
1193  *
1194  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
1195  */
1196 int
1197 vop_stdclose(struct vop_close_args *ap)
1198 {
1199         struct vnode *vp = ap->a_vp;
1200
1201         KASSERT(vp->v_opencount > 0,
1202                 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x",
1203                 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
1204         if (ap->a_fflag & FWRITE) {
1205                 KASSERT(vp->v_writecount > 0,
1206                         ("VOP_STDCLOSE: BAD WRITECOUNT %p %d",
1207                         vp, vp->v_writecount));
1208                 --vp->v_writecount;
1209         }
1210         --vp->v_opencount;
1211         return (0);
1212 }
1213
1214 /*
1215  * Implement standard getpages and putpages.  All filesystems must use
1216  * the buffer cache to back regular files.
1217  */
1218 int
1219 vop_stdgetpages(struct vop_getpages_args *ap)
1220 {
1221         struct mount *mp;
1222         int error;
1223
1224         if ((mp = ap->a_vp->v_mount) != NULL) {
1225                 error = vnode_pager_generic_getpages(
1226                                 ap->a_vp, ap->a_m, ap->a_count,
1227                                 ap->a_reqpage, ap->a_seqaccess);
1228         } else {
1229                 error = VM_PAGER_BAD;
1230         }
1231         return (error);
1232 }
1233
1234 int
1235 vop_stdputpages(struct vop_putpages_args *ap)
1236 {
1237         struct mount *mp;
1238         int error;
1239
1240         if ((mp = ap->a_vp->v_mount) != NULL) {
1241                 error = vnode_pager_generic_putpages(
1242                                 ap->a_vp, ap->a_m, ap->a_count,
1243                                 ap->a_sync, ap->a_rtvals);
1244         } else {
1245                 error = VM_PAGER_BAD;
1246         }
1247         return (error);
1248 }
1249
1250 int
1251 vop_stdnoread(struct vop_read_args *ap)
1252 {
1253         return (EINVAL);
1254 }
1255
1256 int
1257 vop_stdnowrite(struct vop_write_args *ap)
1258 {
1259         return (EINVAL);
1260 }
1261
1262 /* 
1263  * vfs default ops
1264  * used to fill the vfs fucntion table to get reasonable default return values.
1265  */
1266 int 
1267 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
1268 {
1269         return (0);
1270 }
1271
1272 int     
1273 vfs_stdunmount(struct mount *mp, int mntflags)
1274 {
1275         return (0);
1276 }
1277
1278 int
1279 vop_stdmountctl(struct vop_mountctl_args *ap)
1280 {
1281
1282         struct mount *mp;
1283         int error = 0;
1284
1285         mp = ap->a_head.a_ops->head.vv_mount;
1286
1287         switch(ap->a_op) {
1288         case MOUNTCTL_MOUNTFLAGS:
1289                 /*
1290                  * Get a string buffer with all the mount flags
1291                  * names comman separated.
1292                  * mount(2) will use this information.
1293                  */
1294                 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
1295                                             ap->a_buf, ap->a_buflen, &error);
1296                 break;
1297         case MOUNTCTL_INSTALL_VFS_JOURNAL:
1298         case MOUNTCTL_RESTART_VFS_JOURNAL:
1299         case MOUNTCTL_REMOVE_VFS_JOURNAL:
1300         case MOUNTCTL_RESYNC_VFS_JOURNAL:
1301         case MOUNTCTL_STATUS_VFS_JOURNAL:
1302                 error = journal_mountctl(ap);
1303                 break;
1304         default:
1305                 error = EOPNOTSUPP;
1306                 break;
1307         }
1308         return (error);
1309 }
1310
1311 int     
1312 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1313 {
1314         return (EOPNOTSUPP);
1315 }
1316
1317 int     
1318 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1319 {
1320         return (EOPNOTSUPP);
1321 }
1322
1323 /*
1324  * If the VFS does not implement statvfs, then call statfs and convert
1325  * the values.  This code was taken from libc's __cvtstatvfs() function,
1326  * contributed by Joerg Sonnenberger.
1327  */
1328 int     
1329 vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
1330 {
1331         struct statfs *in;
1332         int error;
1333
1334         in = &mp->mnt_stat;
1335         error = VFS_STATFS(mp, in, cred);
1336         if (error == 0) {
1337                 bzero(sbp, sizeof(*sbp));
1338
1339                 sbp->f_bsize = in->f_bsize;
1340                 sbp->f_frsize = in->f_bsize;
1341                 sbp->f_blocks = in->f_blocks;
1342                 sbp->f_bfree = in->f_bfree;
1343                 sbp->f_bavail = in->f_bavail;
1344                 sbp->f_files = in->f_files;
1345                 sbp->f_ffree = in->f_ffree;
1346
1347                 /*
1348                  * XXX
1349                  * This field counts the number of available inodes to non-root
1350                  * users, but this information is not available via statfs.
1351                  * Just ignore this issue by returning the total number 
1352                  * instead.
1353                  */
1354                 sbp->f_favail = in->f_ffree;
1355
1356                 /*
1357                  * XXX
1358                  * This field has a different meaning for statfs and statvfs.
1359                  * For the former it is the cookie exported for NFS and not
1360                  * intended for normal userland use.
1361                  */
1362                 sbp->f_fsid = 0;
1363
1364                 sbp->f_flag = 0;
1365                 if (in->f_flags & MNT_RDONLY)
1366                         sbp->f_flag |= ST_RDONLY;
1367                 if (in->f_flags & MNT_NOSUID)
1368                         sbp->f_flag |= ST_NOSUID;
1369                 sbp->f_namemax = 0;
1370                 sbp->f_owner = in->f_owner;
1371                 /*
1372                  * XXX
1373                  * statfs contains the type as string, statvfs expects it as
1374                  * enumeration.
1375                  */
1376                 sbp->f_type = 0;
1377
1378                 sbp->f_syncreads = in->f_syncreads;
1379                 sbp->f_syncwrites = in->f_syncwrites;
1380                 sbp->f_asyncreads = in->f_asyncreads;
1381                 sbp->f_asyncwrites = in->f_asyncwrites;
1382         }
1383         return (error);
1384 }
1385
1386 int
1387 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1388 {
1389         return (EOPNOTSUPP);
1390 }
1391
1392 int     
1393 vfs_stdstart(struct mount *mp, int flags)
1394 {
1395         return (0);
1396 }
1397
1398 int     
1399 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1400         caddr_t arg, struct ucred *cred)
1401 {
1402         return (EOPNOTSUPP);
1403 }
1404
1405 int     
1406 vfs_stdsync(struct mount *mp, int waitfor)
1407 {
1408         return (0);
1409 }
1410
1411 int
1412 vfs_stdnosync(struct mount *mp, int waitfor)
1413 {
1414         return (EOPNOTSUPP);
1415 }
1416
1417 int     
1418 vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
1419 {
1420         return (EOPNOTSUPP);
1421 }
1422
1423 int     
1424 vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
1425               struct fid *fhp, struct vnode **vpp)
1426 {
1427         return (EOPNOTSUPP);
1428 }
1429
1430 int 
1431 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1432         struct ucred **credanonp)
1433 {
1434         return (EOPNOTSUPP);
1435 }
1436
1437 int
1438 vfs_stdinit(struct vfsconf *vfsp)
1439 {
1440         return (0);
1441 }
1442
1443 int
1444 vfs_stduninit(struct vfsconf *vfsp)
1445 {
1446         return(0);
1447 }
1448
1449 int
1450 vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
1451                  int attrnamespace, const char *attrname,
1452                  struct ucred *cred)
1453 {
1454         return(EOPNOTSUPP);
1455 }
1456
1457 #define ACCOUNTING_NB_FSTYPES 8
1458
1459 static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
1460         "ext2fs", "hammer", "hpfs", "mfs", "ntfs", "null", "tmpfs", "ufs" };
1461
1462 int
1463 vfs_stdac_init(struct mount *mp)
1464 {
1465         const char* fs_type;
1466         int i, fstype_ok = 0;
1467
1468         /* is mounted fs type one we want to do some accounting for ? */
1469         for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1470                 fs_type = accounting_fstypes[i];
1471                 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1472                                         sizeof(mp->mnt_stat)) == 0) {
1473                         fstype_ok = 1;
1474                         break;
1475                 }
1476         }
1477         if (fstype_ok == 0)
1478                 return (0);
1479
1480         vq_init(mp);
1481         return (0);
1482 }
1483
1484 void
1485 vfs_stdac_done(struct mount *mp)
1486 {
1487         vq_done(mp);
1488 }
1489
1490 void
1491 vfs_stdncpgen_set(struct mount *mp, struct namecache *ncp)
1492 {
1493 }
1494
1495 int
1496 vfs_stdncpgen_test(struct mount *mp, struct namecache *ncp)
1497 {
1498         return 0;
1499 }
1500 /* end of vfs default ops */