xref: /dragonfly/sys/kern/vfs_default.c (revision 5dfd06ac)
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  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *
39  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
40  * $DragonFly: src/sys/kern/vfs_default.c,v 1.47 2006/12/23 23:47:54 swildner 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/poll.h>
58 #include <sys/mountctl.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		= (void *)vop_einval,
87 	.vop_poll		= vop_nopoll,
88 	.vop_readlink		= (void *)vop_einval,
89 	.vop_reallocblks	= (void *)vop_eopnotsupp,
90 	.vop_revoke		= vop_stdrevoke,
91 	.vop_strategy		= vop_nostrategy,
92 	.vop_getacl		= (void *)vop_eopnotsupp,
93 	.vop_setacl		= (void *)vop_eopnotsupp,
94 	.vop_aclcheck		= (void *)vop_eopnotsupp,
95 	.vop_getextattr		= (void *)vop_eopnotsupp,
96 	.vop_setextattr		= (void *)vop_eopnotsupp,
97 	.vop_nresolve		= vop_compat_nresolve,
98 	.vop_nlookupdotdot	= vop_compat_nlookupdotdot,
99 	.vop_ncreate		= vop_compat_ncreate,
100 	.vop_nmkdir		= vop_compat_nmkdir,
101 	.vop_nmknod		= vop_compat_nmknod,
102 	.vop_nlink		= vop_compat_nlink,
103 	.vop_nsymlink		= vop_compat_nsymlink,
104 	.vop_nwhiteout		= vop_compat_nwhiteout,
105 	.vop_nremove		= vop_compat_nremove,
106 	.vop_nrmdir		= vop_compat_nrmdir,
107 	.vop_nrename		= vop_compat_nrename,
108 	.vop_mountctl		= journal_mountctl
109 };
110 
111 VNODEOP_SET(default_vnode_vops);
112 
113 int
114 vop_eopnotsupp(struct vop_generic_args *ap)
115 {
116 	return (EOPNOTSUPP);
117 }
118 
119 int
120 vop_ebadf(struct vop_generic_args *ap)
121 {
122 	return (EBADF);
123 }
124 
125 int
126 vop_enotty(struct vop_generic_args *ap)
127 {
128 	return (ENOTTY);
129 }
130 
131 int
132 vop_einval(struct vop_generic_args *ap)
133 {
134 	return (EINVAL);
135 }
136 
137 int
138 vop_null(struct vop_generic_args *ap)
139 {
140 	return (0);
141 }
142 
143 int
144 vop_defaultop(struct vop_generic_args *ap)
145 {
146 	return (VOCALL(&default_vnode_vops, ap));
147 }
148 
149 int
150 vop_panic(struct vop_generic_args *ap)
151 {
152 	panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
153 }
154 
155 /*
156  * vop_compat_resolve { struct nchandle *a_nch }	XXX STOPGAP FUNCTION
157  *
158  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
159  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
160  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a
161  * vop_old_lookup() and does appropriate translations.
162  *
163  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
164  * VFSs will support this VOP and this routine can be removed, since
165  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
166  * API.
167  *
168  * A locked ncp is passed in to be resolved.  The NCP is resolved by
169  * figuring out the vnode (if any) and calling cache_setvp() to attach the
170  * vnode to the entry.  If the entry represents a non-existant node then
171  * cache_setvp() is called with a NULL vnode to resolve the entry into a
172  * negative cache entry.  No vnode locks are retained and the
173  * ncp is left locked on return.
174  *
175  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
176  *
177  * There is a potential directory and vnode interlock.   The lock order
178  * requirement is: namecache, governing directory, resolved vnode.
179  */
180 int
181 vop_compat_nresolve(struct vop_nresolve_args *ap)
182 {
183 	int error;
184 	struct vnode *dvp;
185 	struct vnode *vp;
186 	struct nchandle *nch;
187 	struct namecache *ncp;
188 	struct componentname cnp;
189 
190 	nch = ap->a_nch;	/* locked namecache node */
191 	ncp = nch->ncp;
192 	if (ncp->nc_parent == NULL)
193 		return(EPERM);
194 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
195 		return(EPERM);
196 
197 	/*
198 	 * UFS currently stores all sorts of side effects, including a loop
199 	 * variable, in the directory inode.  That needs to be fixed and the
200 	 * other VFS's audited before we can switch to LK_SHARED.
201 	 */
202 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
203 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
204 			ncp, ncp->nc_name);
205 		return(EAGAIN);
206 	}
207 
208 	bzero(&cnp, sizeof(cnp));
209 	cnp.cn_nameiop = NAMEI_LOOKUP;
210 	cnp.cn_flags = 0;
211 	cnp.cn_nameptr = ncp->nc_name;
212 	cnp.cn_namelen = ncp->nc_nlen;
213 	cnp.cn_cred = ap->a_cred;
214 	cnp.cn_td = curthread; /* XXX */
215 
216 	/*
217 	 * vop_old_lookup() always returns vp locked.  dvp may or may not be
218 	 * left locked depending on CNP_PDIRUNLOCK.
219 	 */
220 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
221 	if (error == 0)
222 		vn_unlock(vp);
223 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
224 		vn_unlock(dvp);
225 	if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
226 		/* was resolved by another process while we were unlocked */
227 		if (error == 0)
228 			vrele(vp);
229 	} else if (error == 0) {
230 		KKASSERT(vp != NULL);
231 		cache_setvp(nch, vp);
232 		vrele(vp);
233 	} else if (error == ENOENT) {
234 		KKASSERT(vp == NULL);
235 		if (cnp.cn_flags & CNP_ISWHITEOUT)
236 			ncp->nc_flag |= NCF_WHITEOUT;
237 		cache_setvp(nch, NULL);
238 	}
239 	vrele(dvp);
240 	return (error);
241 }
242 
243 /*
244  * vop_compat_nlookupdotdot { struct vnode *a_dvp,
245  *			struct vnode **a_vpp,
246  *			struct ucred *a_cred }
247  *
248  * Lookup the vnode representing the parent directory of the specified
249  * directory vnode.  a_dvp should not be locked.  If no error occurs *a_vpp
250  * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
251  *
252  * This function is designed to aid NFS server-side operations and is
253  * used by cache_fromdvp() to create a consistent, connected namecache
254  * topology.
255  *
256  * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
257  * code out from their *_lookup() and create *_nlookupdotdot().  Then as time
258  * permits VFSs will implement the remaining *_n*() calls and finally get
259  * rid of their *_lookup() call.
260  */
261 int
262 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
263 {
264 	struct componentname cnp;
265 	int error;
266 
267 	/*
268 	 * UFS currently stores all sorts of side effects, including a loop
269 	 * variable, in the directory inode.  That needs to be fixed and the
270 	 * other VFS's audited before we can switch to LK_SHARED.
271 	 */
272 	*ap->a_vpp = NULL;
273 	if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
274 		return (error);
275 	if (ap->a_dvp->v_type != VDIR) {
276 		vput(ap->a_dvp);
277 		return (ENOTDIR);
278 	}
279 
280 	bzero(&cnp, sizeof(cnp));
281 	cnp.cn_nameiop = NAMEI_LOOKUP;
282 	cnp.cn_flags = CNP_ISDOTDOT;
283 	cnp.cn_nameptr = "..";
284 	cnp.cn_namelen = 2;
285 	cnp.cn_cred = ap->a_cred;
286 	cnp.cn_td = curthread; /* XXX */
287 
288 	/*
289 	 * vop_old_lookup() always returns vp locked.  dvp may or may not be
290 	 * left locked depending on CNP_PDIRUNLOCK.
291 	 */
292 	error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
293 	if (error == 0)
294 		vn_unlock(*ap->a_vpp);
295 	if (cnp.cn_flags & CNP_PDIRUNLOCK)
296 		vrele(ap->a_dvp);
297 	else
298 		vput(ap->a_dvp);
299 	return (error);
300 }
301 
302 /*
303  * vop_compat_ncreate { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
304  *			struct vnode *a_vpp,
305  *			struct ucred *a_cred,
306  *			struct vattr *a_vap }
307  *
308  * Create a file as specified by a_vap.  Compatibility requires us to issue
309  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
310  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
311  */
312 int
313 vop_compat_ncreate(struct vop_ncreate_args *ap)
314 {
315 	struct thread *td = curthread;
316 	struct componentname cnp;
317 	struct nchandle *nch;
318 	struct namecache *ncp;
319 	struct vnode *dvp;
320 	int error;
321 
322 	/*
323 	 * Sanity checks, get a locked directory vnode.
324 	 */
325 	nch = ap->a_nch;		/* locked namecache node */
326 	ncp = nch->ncp;
327 	if (ncp->nc_parent == NULL)
328 		return(EPERM);
329 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
330 		return(EPERM);
331 
332 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
333 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
334 			ncp, ncp->nc_name);
335 		return(EAGAIN);
336 	}
337 
338 	/*
339 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
340 	 * caches all information required to create the entry in the
341 	 * directory inode.  We expect a return code of EJUSTRETURN for
342 	 * the CREATE case.  The cnp must simulated a saved-name situation.
343 	 */
344 	bzero(&cnp, sizeof(cnp));
345 	cnp.cn_nameiop = NAMEI_CREATE;
346 	cnp.cn_flags = CNP_LOCKPARENT;
347 	cnp.cn_nameptr = ncp->nc_name;
348 	cnp.cn_namelen = ncp->nc_nlen;
349 	cnp.cn_cred = ap->a_cred;
350 	cnp.cn_td = td;
351 	*ap->a_vpp = NULL;
352 
353 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
354 
355 	/*
356 	 * EJUSTRETURN should be returned for this case, which means that
357 	 * the VFS has setup the directory inode for the create.  The dvp we
358 	 * passed in is expected to remain in a locked state.
359 	 *
360 	 * If the VOP_OLD_CREATE is successful we are responsible for updating
361 	 * the cache state of the locked ncp that was passed to us.
362 	 */
363 	if (error == EJUSTRETURN) {
364 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
365 		error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
366 		if (error == 0) {
367 			cache_setunresolved(nch);
368 			cache_setvp(nch, *ap->a_vpp);
369 		}
370 	} else {
371 		if (error == 0) {
372 			vput(*ap->a_vpp);
373 			*ap->a_vpp = NULL;
374 			error = EEXIST;
375 		}
376 		KKASSERT(*ap->a_vpp == NULL);
377 	}
378 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
379 		vn_unlock(dvp);
380 	vrele(dvp);
381 	return (error);
382 }
383 
384 /*
385  * vop_compat_nmkdir { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
386  *			struct vnode *a_vpp,
387  *			struct ucred *a_cred,
388  *			struct vattr *a_vap }
389  *
390  * Create a directory as specified by a_vap.  Compatibility requires us to
391  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
392  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
393  */
394 int
395 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
396 {
397 	struct thread *td = curthread;
398 	struct componentname cnp;
399 	struct nchandle *nch;
400 	struct namecache *ncp;
401 	struct vnode *dvp;
402 	int error;
403 
404 	/*
405 	 * Sanity checks, get a locked directory vnode.
406 	 */
407 	nch = ap->a_nch;		/* locked namecache node */
408 	ncp = nch->ncp;
409 	if (ncp->nc_parent == NULL)
410 		return(EPERM);
411 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
412 		return(EPERM);
413 
414 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
415 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
416 			ncp, ncp->nc_name);
417 		return(EAGAIN);
418 	}
419 
420 	/*
421 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
422 	 * caches all information required to create the entry in the
423 	 * directory inode.  We expect a return code of EJUSTRETURN for
424 	 * the CREATE case.  The cnp must simulated a saved-name situation.
425 	 */
426 	bzero(&cnp, sizeof(cnp));
427 	cnp.cn_nameiop = NAMEI_CREATE;
428 	cnp.cn_flags = CNP_LOCKPARENT;
429 	cnp.cn_nameptr = ncp->nc_name;
430 	cnp.cn_namelen = ncp->nc_nlen;
431 	cnp.cn_cred = ap->a_cred;
432 	cnp.cn_td = td;
433 	*ap->a_vpp = NULL;
434 
435 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
436 
437 	/*
438 	 * EJUSTRETURN should be returned for this case, which means that
439 	 * the VFS has setup the directory inode for the create.  The dvp we
440 	 * passed in is expected to remain in a locked state.
441 	 *
442 	 * If the VOP_OLD_MKDIR is successful we are responsible for updating
443 	 * the cache state of the locked ncp that was passed to us.
444 	 */
445 	if (error == EJUSTRETURN) {
446 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
447 		error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
448 		if (error == 0) {
449 			cache_setunresolved(nch);
450 			cache_setvp(nch, *ap->a_vpp);
451 		}
452 	} else {
453 		if (error == 0) {
454 			vput(*ap->a_vpp);
455 			*ap->a_vpp = NULL;
456 			error = EEXIST;
457 		}
458 		KKASSERT(*ap->a_vpp == NULL);
459 	}
460 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
461 		vn_unlock(dvp);
462 	vrele(dvp);
463 	return (error);
464 }
465 
466 /*
467  * vop_compat_nmknod { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
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 	if (ncp->nc_parent == NULL)
492 		return(EPERM);
493 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
494 		return(EPERM);
495 
496 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
497 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
498 			ncp, ncp->nc_name);
499 		return(EAGAIN);
500 	}
501 
502 	/*
503 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
504 	 * caches all information required to create the entry in the
505 	 * directory inode.  We expect a return code of EJUSTRETURN for
506 	 * the CREATE case.  The cnp must simulated a saved-name situation.
507 	 */
508 	bzero(&cnp, sizeof(cnp));
509 	cnp.cn_nameiop = NAMEI_CREATE;
510 	cnp.cn_flags = CNP_LOCKPARENT;
511 	cnp.cn_nameptr = ncp->nc_name;
512 	cnp.cn_namelen = ncp->nc_nlen;
513 	cnp.cn_cred = ap->a_cred;
514 	cnp.cn_td = td;
515 	*ap->a_vpp = NULL;
516 
517 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
518 
519 	/*
520 	 * EJUSTRETURN should be returned for this case, which means that
521 	 * the VFS has setup the directory inode for the create.  The dvp we
522 	 * passed in is expected to remain in a locked state.
523 	 *
524 	 * If the VOP_OLD_MKNOD is successful we are responsible for updating
525 	 * the cache state of the locked ncp that was passed to us.
526 	 */
527 	if (error == EJUSTRETURN) {
528 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
529 		error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
530 		if (error == 0) {
531 			cache_setunresolved(nch);
532 			cache_setvp(nch, *ap->a_vpp);
533 		}
534 	} else {
535 		if (error == 0) {
536 			vput(*ap->a_vpp);
537 			*ap->a_vpp = NULL;
538 			error = EEXIST;
539 		}
540 		KKASSERT(*ap->a_vpp == NULL);
541 	}
542 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
543 		vn_unlock(dvp);
544 	vrele(dvp);
545 	return (error);
546 }
547 
548 /*
549  * vop_compat_nlink { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
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 	if (ncp->nc_parent == NULL)
573 		return(EPERM);
574 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
575 		return(EPERM);
576 
577 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
578 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
579 			ncp, ncp->nc_name);
580 		return(EAGAIN);
581 	}
582 
583 	/*
584 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
585 	 * caches all information required to create the entry in the
586 	 * directory inode.  We expect a return code of EJUSTRETURN for
587 	 * the CREATE case.  The cnp must simulated a saved-name situation.
588 	 */
589 	bzero(&cnp, sizeof(cnp));
590 	cnp.cn_nameiop = NAMEI_CREATE;
591 	cnp.cn_flags = CNP_LOCKPARENT;
592 	cnp.cn_nameptr = ncp->nc_name;
593 	cnp.cn_namelen = ncp->nc_nlen;
594 	cnp.cn_cred = ap->a_cred;
595 	cnp.cn_td = td;
596 
597 	tvp = NULL;
598 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
599 
600 	/*
601 	 * EJUSTRETURN should be returned for this case, which means that
602 	 * the VFS has setup the directory inode for the create.  The dvp we
603 	 * passed in is expected to remain in a locked state.
604 	 *
605 	 * If the VOP_OLD_LINK is successful we are responsible for updating
606 	 * the cache state of the locked ncp that was passed to us.
607 	 */
608 	if (error == EJUSTRETURN) {
609 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
610 		error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
611 		if (error == 0) {
612 			cache_setunresolved(nch);
613 			cache_setvp(nch, ap->a_vp);
614 		}
615 	} else {
616 		if (error == 0) {
617 			vput(tvp);
618 			error = EEXIST;
619 		}
620 	}
621 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
622 		vn_unlock(dvp);
623 	vrele(dvp);
624 	return (error);
625 }
626 
627 int
628 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
629 {
630 	struct thread *td = curthread;
631 	struct componentname cnp;
632 	struct nchandle *nch;
633 	struct namecache *ncp;
634 	struct vnode *dvp;
635 	struct vnode *vp;
636 	int error;
637 
638 	/*
639 	 * Sanity checks, get a locked directory vnode.
640 	 */
641 	*ap->a_vpp = NULL;
642 	nch = ap->a_nch;		/* locked namecache node */
643 	ncp = nch->ncp;
644 	if (ncp->nc_parent == NULL)
645 		return(EPERM);
646 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
647 		return(EPERM);
648 
649 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
650 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
651 			ncp, ncp->nc_name);
652 		return(EAGAIN);
653 	}
654 
655 	/*
656 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
657 	 * caches all information required to create the entry in the
658 	 * directory inode.  We expect a return code of EJUSTRETURN for
659 	 * the CREATE case.  The cnp must simulated a saved-name situation.
660 	 */
661 	bzero(&cnp, sizeof(cnp));
662 	cnp.cn_nameiop = NAMEI_CREATE;
663 	cnp.cn_flags = CNP_LOCKPARENT;
664 	cnp.cn_nameptr = ncp->nc_name;
665 	cnp.cn_namelen = ncp->nc_nlen;
666 	cnp.cn_cred = ap->a_cred;
667 	cnp.cn_td = td;
668 
669 	vp = NULL;
670 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
671 
672 	/*
673 	 * EJUSTRETURN should be returned for this case, which means that
674 	 * the VFS has setup the directory inode for the create.  The dvp we
675 	 * passed in is expected to remain in a locked state.
676 	 *
677 	 * If the VOP_OLD_SYMLINK is successful we are responsible for updating
678 	 * the cache state of the locked ncp that was passed to us.
679 	 */
680 	if (error == EJUSTRETURN) {
681 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
682 		error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
683 		if (error == 0) {
684 			cache_setunresolved(nch);
685 			cache_setvp(nch, vp);
686 			*ap->a_vpp = vp;
687 		}
688 	} else {
689 		if (error == 0) {
690 			vput(vp);
691 			vp = NULL;
692 			error = EEXIST;
693 		}
694 		KKASSERT(vp == NULL);
695 	}
696 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
697 		vn_unlock(dvp);
698 	vrele(dvp);
699 	return (error);
700 }
701 
702 /*
703  * vop_compat_nwhiteout { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
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 	if (ncp->nc_parent == NULL)
730 		return(EPERM);
731 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
732 		return(EPERM);
733 
734 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
735 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
736 			ncp, ncp->nc_name);
737 		return(EAGAIN);
738 	}
739 
740 	/*
741 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
742 	 * caches all information required to create the entry in the
743 	 * directory inode.  We expect a return code of EJUSTRETURN for
744 	 * the CREATE case.  The cnp must simulated a saved-name situation.
745 	 */
746 	bzero(&cnp, sizeof(cnp));
747 	cnp.cn_nameiop = ap->a_flags;
748 	cnp.cn_flags = CNP_LOCKPARENT;
749 	cnp.cn_nameptr = ncp->nc_name;
750 	cnp.cn_namelen = ncp->nc_nlen;
751 	cnp.cn_cred = ap->a_cred;
752 	cnp.cn_td = td;
753 
754 	vp = NULL;
755 
756 	/*
757 	 * EJUSTRETURN should be returned for the CREATE or DELETE cases.
758 	 * The VFS has setup the directory inode for the create.  The dvp we
759 	 * passed in is expected to remain in a locked state.
760 	 *
761 	 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
762 	 * the cache state of the locked ncp that was passed to us.
763 	 */
764 	switch(ap->a_flags) {
765 	case NAMEI_DELETE:
766 		cnp.cn_flags |= CNP_DOWHITEOUT;
767 		/* fall through */
768 	case NAMEI_CREATE:
769 		error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
770 		if (error == EJUSTRETURN) {
771 			KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
772 			error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
773 			if (error == 0)
774 				cache_setunresolved(nch);
775 		} else {
776 			if (error == 0) {
777 				vput(vp);
778 				vp = NULL;
779 				error = EEXIST;
780 			}
781 			KKASSERT(vp == NULL);
782 		}
783 		break;
784 	case NAMEI_LOOKUP:
785 		error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
786 		break;
787 	default:
788 		error = EINVAL;
789 		break;
790 	}
791 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
792 		vn_unlock(dvp);
793 	vrele(dvp);
794 	return (error);
795 }
796 
797 
798 /*
799  * vop_compat_nremove { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
800  *			  struct ucred *a_cred }
801  */
802 int
803 vop_compat_nremove(struct vop_nremove_args *ap)
804 {
805 	struct thread *td = curthread;
806 	struct componentname cnp;
807 	struct nchandle *nch;
808 	struct namecache *ncp;
809 	struct vnode *dvp;
810 	struct vnode *vp;
811 	int error;
812 
813 	/*
814 	 * Sanity checks, get a locked directory vnode.
815 	 */
816 	nch = ap->a_nch;		/* locked namecache node */
817 	ncp = nch->ncp;
818 	if (ncp->nc_parent == NULL)
819 		return(EPERM);
820 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
821 		return(EPERM);
822 
823 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
824 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
825 			ncp, ncp->nc_name);
826 		return(EAGAIN);
827 	}
828 
829 	/*
830 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
831 	 * caches all information required to delete the entry in the
832 	 * directory inode.  We expect a return code of 0 for the DELETE
833 	 * case (meaning that a vp has been found).  The cnp must simulated
834 	 * a saved-name situation.
835 	 */
836 	bzero(&cnp, sizeof(cnp));
837 	cnp.cn_nameiop = NAMEI_DELETE;
838 	cnp.cn_flags = CNP_LOCKPARENT;
839 	cnp.cn_nameptr = ncp->nc_name;
840 	cnp.cn_namelen = ncp->nc_nlen;
841 	cnp.cn_cred = ap->a_cred;
842 	cnp.cn_td = td;
843 
844 	/*
845 	 * The vnode must be a directory and must not represent the
846 	 * current directory.
847 	 */
848 	vp = NULL;
849 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
850 	if (error == 0 && vp->v_type == VDIR)
851 		error = EPERM;
852 	if (error == 0) {
853 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
854 		error = VOP_OLD_REMOVE(dvp, vp, &cnp);
855 		if (error == 0) {
856 			cache_setunresolved(nch);
857 			cache_setvp(nch, NULL);
858 			cache_inval_vp(vp, CINV_DESTROY);
859 		}
860 	}
861 	if (vp) {
862 		if (dvp == vp)
863 			vrele(vp);
864 		else
865 			vput(vp);
866 	}
867 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
868 		vn_unlock(dvp);
869 	vrele(dvp);
870 	return (error);
871 }
872 
873 /*
874  * vop_compat_nrmdir { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
875  *			  struct ucred *a_cred }
876  */
877 int
878 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
879 {
880 	struct thread *td = curthread;
881 	struct componentname cnp;
882 	struct nchandle *nch;
883 	struct namecache *ncp;
884 	struct vnode *dvp;
885 	struct vnode *vp;
886 	int error;
887 
888 	/*
889 	 * Sanity checks, get a locked directory vnode.
890 	 */
891 	nch = ap->a_nch;		/* locked namecache node */
892 	ncp = nch->ncp;
893 	if (ncp->nc_parent == NULL)
894 		return(EPERM);
895 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
896 		return(EPERM);
897 
898 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
899 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
900 			ncp, ncp->nc_name);
901 		return(EAGAIN);
902 	}
903 
904 	/*
905 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
906 	 * caches all information required to delete the entry in the
907 	 * directory inode.  We expect a return code of 0 for the DELETE
908 	 * case (meaning that a vp has been found).  The cnp must simulated
909 	 * a saved-name situation.
910 	 */
911 	bzero(&cnp, sizeof(cnp));
912 	cnp.cn_nameiop = NAMEI_DELETE;
913 	cnp.cn_flags = CNP_LOCKPARENT;
914 	cnp.cn_nameptr = ncp->nc_name;
915 	cnp.cn_namelen = ncp->nc_nlen;
916 	cnp.cn_cred = ap->a_cred;
917 	cnp.cn_td = td;
918 
919 	/*
920 	 * The vnode must be a directory and must not represent the
921 	 * current directory.
922 	 */
923 	vp = NULL;
924 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
925 	if (error == 0 && vp->v_type != VDIR)
926 		error = ENOTDIR;
927 	if (error == 0 && vp == dvp)
928 		error = EINVAL;
929 	if (error == 0 && (vp->v_flag & VROOT))
930 		error = EBUSY;
931 	if (error == 0) {
932 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
933 		error = VOP_OLD_RMDIR(dvp, vp, &cnp);
934 
935 		/*
936 		 * Note that this invalidation will cause any process
937 		 * currently CD'd into the directory being removed to be
938 		 * disconnected from the topology and not be able to ".."
939 		 * back out.
940 		 */
941 		if (error == 0) {
942 			cache_inval(nch, CINV_DESTROY);
943 			cache_inval_vp(vp, CINV_DESTROY);
944 		}
945 	}
946 	if (vp) {
947 		if (dvp == vp)
948 			vrele(vp);
949 		else
950 			vput(vp);
951 	}
952 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
953 		vn_unlock(dvp);
954 	vrele(dvp);
955 	return (error);
956 }
957 
958 /*
959  * vop_compat_nrename { struct nchandle *a_fnch, 	XXX STOPGAP FUNCTION
960  *			struct nchandle *a_tnch,
961  *			struct ucred *a_cred }
962  *
963  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
964  * the source directory and vnode be unlocked and the target directory and
965  * vnode (if it exists) be locked.  All arguments will be vrele'd and
966  * the targets will also be unlocked regardless of the return code.
967  */
968 int
969 vop_compat_nrename(struct vop_nrename_args *ap)
970 {
971 	struct thread *td = curthread;
972 	struct componentname fcnp;
973 	struct componentname tcnp;
974 	struct nchandle *fnch;
975 	struct nchandle *tnch;
976 	struct namecache *fncp;
977 	struct namecache *tncp;
978 	struct vnode *fdvp, *fvp;
979 	struct vnode *tdvp, *tvp;
980 	int error;
981 
982 	/*
983 	 * Sanity checks, get referenced vnodes representing the source.
984 	 */
985 	fnch = ap->a_fnch;		/* locked namecache node */
986 	fncp = fnch->ncp;
987 	if (fncp->nc_parent == NULL)
988 		return(EPERM);
989 	if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
990 		return(EPERM);
991 
992 	/*
993 	 * Temporarily lock the source directory and lookup in DELETE mode to
994 	 * check permissions.  XXX delete permissions should have been
995 	 * checked by nlookup(), we need to add NLC_DELETE for delete
996 	 * checking.  It is unclear whether VFS's require the directory setup
997 	 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
998 	 * since it isn't locked and since UFS always does a relookup of
999 	 * the source, it is believed that the only side effect that matters
1000 	 * is the permissions check.
1001 	 */
1002 	if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
1003 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1004 			fncp, fncp->nc_name);
1005 		return(EAGAIN);
1006 	}
1007 
1008 	bzero(&fcnp, sizeof(fcnp));
1009 	fcnp.cn_nameiop = NAMEI_DELETE;
1010 	fcnp.cn_flags = CNP_LOCKPARENT;
1011 	fcnp.cn_nameptr = fncp->nc_name;
1012 	fcnp.cn_namelen = fncp->nc_nlen;
1013 	fcnp.cn_cred = ap->a_cred;
1014 	fcnp.cn_td = td;
1015 
1016 	/*
1017 	 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
1018 	 * fvp.
1019 	 */
1020 	fvp = NULL;
1021 	error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
1022 	if (error == 0 && (fvp->v_flag & VROOT)) {
1023 		vput(fvp);	/* as if vop_old_lookup had failed */
1024 		error = EBUSY;
1025 	}
1026 	if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1027 		fcnp.cn_flags |= CNP_PDIRUNLOCK;
1028 		vn_unlock(fdvp);
1029 	}
1030 	if (error) {
1031 		vrele(fdvp);
1032 		return (error);
1033 	}
1034 	vn_unlock(fvp);
1035 
1036 	/*
1037 	 * fdvp and fvp are now referenced and unlocked.
1038 	 *
1039 	 * Get a locked directory vnode for the target and lookup the target
1040 	 * in CREATE mode so it places the required information in the
1041 	 * directory inode.
1042 	 */
1043 	tnch = ap->a_tnch;		/* locked namecache node */
1044 	tncp = tnch->ncp;
1045 	if (tncp->nc_parent == NULL)
1046 		error = EPERM;
1047 	if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
1048 		error = EPERM;
1049 	if (error) {
1050 		vrele(fdvp);
1051 		vrele(fvp);
1052 		return (error);
1053 	}
1054 	if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
1055 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1056 			tncp, tncp->nc_name);
1057 		vrele(fdvp);
1058 		vrele(fvp);
1059 		return(EAGAIN);
1060 	}
1061 
1062 	/*
1063 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
1064 	 * caches all information required to create the entry in the
1065 	 * target directory inode.
1066 	 */
1067 	bzero(&tcnp, sizeof(tcnp));
1068 	tcnp.cn_nameiop = NAMEI_RENAME;
1069 	tcnp.cn_flags = CNP_LOCKPARENT;
1070 	tcnp.cn_nameptr = tncp->nc_name;
1071 	tcnp.cn_namelen = tncp->nc_nlen;
1072 	tcnp.cn_cred = ap->a_cred;
1073 	tcnp.cn_td = td;
1074 
1075 	tvp = NULL;
1076 	error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1077 
1078 	if (error == EJUSTRETURN) {
1079 		/*
1080 		 * Target does not exist.  tvp should be NULL.
1081 		 */
1082 		KKASSERT(tvp == NULL);
1083 		KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1084 		error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1085 		if (error == 0) {
1086 			cache_rename(fnch, tnch);
1087 			cache_setvp(tnch, fvp);
1088 		}
1089 	} else if (error == 0) {
1090 		/*
1091 		 * Target exists.  VOP_OLD_RENAME should correctly delete the
1092 		 * target.
1093 		 */
1094 		KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1095 		error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1096 		if (error == 0) {
1097 			cache_rename(fnch, tnch);
1098 			cache_setvp(tnch, fvp);
1099 		}
1100 	} else {
1101 		vrele(fdvp);
1102 		vrele(fvp);
1103 		if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1104 			vrele(tdvp);
1105 		else
1106 			vput(tdvp);
1107 	}
1108 	return (error);
1109 }
1110 
1111 static int
1112 vop_nolookup(struct vop_old_lookup_args *ap)
1113 {
1114 
1115 	*ap->a_vpp = NULL;
1116 	return (ENOTDIR);
1117 }
1118 
1119 /*
1120  *	vop_nostrategy:
1121  *
1122  *	Strategy routine for VFS devices that have none.
1123  *
1124  *	B_ERROR and B_INVAL must be cleared prior to calling any strategy
1125  *	routine.  Typically this is done for a BUF_CMD_READ strategy call.
1126  *	Typically B_INVAL is assumed to already be clear prior to a write
1127  *	and should not be cleared manually unless you just made the buffer
1128  *	invalid.  B_ERROR should be cleared either way.
1129  */
1130 
1131 static int
1132 vop_nostrategy (struct vop_strategy_args *ap)
1133 {
1134 	kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1135 	vprint("", ap->a_vp);
1136 	ap->a_bio->bio_buf->b_flags |= B_ERROR;
1137 	ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1138 	biodone(ap->a_bio);
1139 	return (EOPNOTSUPP);
1140 }
1141 
1142 int
1143 vop_stdpathconf(struct vop_pathconf_args *ap)
1144 {
1145 
1146 	switch (ap->a_name) {
1147 		case _PC_LINK_MAX:
1148 			*ap->a_retval = LINK_MAX;
1149 			return (0);
1150 		case _PC_MAX_CANON:
1151 			*ap->a_retval = MAX_CANON;
1152 			return (0);
1153 		case _PC_MAX_INPUT:
1154 			*ap->a_retval = MAX_INPUT;
1155 			return (0);
1156 		case _PC_PIPE_BUF:
1157 			*ap->a_retval = PIPE_BUF;
1158 			return (0);
1159 		case _PC_CHOWN_RESTRICTED:
1160 			*ap->a_retval = 1;
1161 			return (0);
1162 		case _PC_VDISABLE:
1163 			*ap->a_retval = _POSIX_VDISABLE;
1164 			return (0);
1165 		default:
1166 			return (EINVAL);
1167 	}
1168 	/* NOTREACHED */
1169 }
1170 
1171 /*
1172  * Standard open.
1173  *
1174  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp,
1175  *  struct thread *a_td)
1176  *
1177  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1178  */
1179 int
1180 vop_stdopen(struct vop_open_args *ap)
1181 {
1182 	struct vnode *vp = ap->a_vp;
1183 	struct file *fp;
1184 
1185 	if ((fp = ap->a_fp) != NULL) {
1186 		switch(vp->v_type) {
1187 		case VFIFO:
1188 			fp->f_type = DTYPE_FIFO;
1189 			break;
1190 		default:
1191 			fp->f_type = DTYPE_VNODE;
1192 			break;
1193 		}
1194 		fp->f_flag = ap->a_mode & FMASK;
1195 		fp->f_ops = &vnode_fileops;
1196 		fp->f_data = vp;
1197 		vref(vp);
1198 	}
1199 	if (ap->a_mode & FWRITE)
1200 		++vp->v_writecount;
1201 	KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1202 	++vp->v_opencount;
1203 	return (0);
1204 }
1205 
1206 /*
1207  * Standard close.
1208  *
1209  * (struct vnode *a_vp, int a_fflag, struct thread *a_td)
1210  *
1211  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
1212  */
1213 int
1214 vop_stdclose(struct vop_close_args *ap)
1215 {
1216 	struct vnode *vp = ap->a_vp;
1217 
1218 	KASSERT(vp->v_opencount > 0,
1219 		("VOP_STDCLOSE: BAD OPENCOUNT %p %d\n", vp, vp->v_opencount));
1220 	if (ap->a_fflag & FWRITE) {
1221 		KASSERT(vp->v_writecount > 0,
1222 			("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n",
1223 			vp, vp->v_writecount));
1224 		--vp->v_writecount;
1225 	}
1226 	--vp->v_opencount;
1227 	return (0);
1228 }
1229 
1230 /*
1231  * Return true for select/poll.
1232  */
1233 int
1234 vop_nopoll(struct vop_poll_args *ap)
1235 {
1236 	/*
1237 	 * Return true for read/write.  If the user asked for something
1238 	 * special, return POLLNVAL, so that clients have a way of
1239 	 * determining reliably whether or not the extended
1240 	 * functionality is present without hard-coding knowledge
1241 	 * of specific filesystem implementations.
1242 	 */
1243 	if (ap->a_events & ~POLLSTANDARD)
1244 		return (POLLNVAL);
1245 
1246 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1247 }
1248 
1249 /*
1250  * Implement poll for local filesystems that support it.
1251  */
1252 int
1253 vop_stdpoll(struct vop_poll_args *ap)
1254 {
1255 	if (ap->a_events & ~POLLSTANDARD)
1256 		return (vn_pollrecord(ap->a_vp, ap->a_events));
1257 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1258 }
1259 
1260 /*
1261  * vfs default ops
1262  * used to fill the vfs fucntion table to get reasonable default return values.
1263  */
1264 int
1265 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
1266 {
1267 	return (0);
1268 }
1269 
1270 int
1271 vfs_stdunmount(struct mount *mp, int mntflags)
1272 {
1273 	return (0);
1274 }
1275 
1276 int
1277 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1278 {
1279 	return (EOPNOTSUPP);
1280 }
1281 
1282 int
1283 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1284 {
1285 	return (EOPNOTSUPP);
1286 }
1287 
1288 int
1289 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1290 {
1291 	return (EOPNOTSUPP);
1292 }
1293 
1294 int
1295 vfs_stdstart(struct mount *mp, int flags)
1296 {
1297 	return (0);
1298 }
1299 
1300 int
1301 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1302 	caddr_t arg, struct ucred *cred)
1303 {
1304 	return (EOPNOTSUPP);
1305 }
1306 
1307 int
1308 vfs_stdsync(struct mount *mp, int waitfor)
1309 {
1310 	return (0);
1311 }
1312 
1313 int
1314 vfs_stdnosync(struct mount *mp, int waitfor)
1315 {
1316 	return (EOPNOTSUPP);
1317 }
1318 
1319 int
1320 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
1321 {
1322 	return (EOPNOTSUPP);
1323 }
1324 
1325 int
1326 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1327 {
1328 	return (EOPNOTSUPP);
1329 }
1330 
1331 int
1332 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1333 	struct ucred **credanonp)
1334 {
1335 	return (EOPNOTSUPP);
1336 }
1337 
1338 int
1339 vfs_stdinit(struct vfsconf *vfsp)
1340 {
1341 	return (0);
1342 }
1343 
1344 int
1345 vfs_stduninit(struct vfsconf *vfsp)
1346 {
1347 	return(0);
1348 }
1349 
1350 int
1351 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1352 	caddr_t arg, struct ucred *cred)
1353 {
1354 	return(EOPNOTSUPP);
1355 }
1356 
1357 /* end of vfs default ops */
1358