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