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