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