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