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