xref: /dragonfly/sys/kern/vfs_default.c (revision 685c703c)
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.42 2006/07/19 06:08:06 dillon 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_islocked		= vop_stdislocked,
83 	.vop_lock		= vop_stdlock,
84 	.vop_mmap		= (void *)vop_einval,
85 	.vop_old_lookup		= vop_nolookup,
86 	.vop_open		= vop_stdopen,
87 	.vop_close		= vop_stdclose,
88 	.vop_pathconf		= (void *)vop_einval,
89 	.vop_poll		= vop_nopoll,
90 	.vop_readlink		= (void *)vop_einval,
91 	.vop_reallocblks	= (void *)vop_eopnotsupp,
92 	.vop_revoke		= vop_stdrevoke,
93 	.vop_strategy		= vop_nostrategy,
94 	.vop_unlock		= vop_stdunlock,
95 	.vop_getacl		= (void *)vop_eopnotsupp,
96 	.vop_setacl		= (void *)vop_eopnotsupp,
97 	.vop_aclcheck		= (void *)vop_eopnotsupp,
98 	.vop_getextattr		= (void *)vop_eopnotsupp,
99 	.vop_setextattr		= (void *)vop_eopnotsupp,
100 	.vop_nresolve		= vop_compat_nresolve,
101 	.vop_nlookupdotdot	= vop_compat_nlookupdotdot,
102 	.vop_ncreate		= vop_compat_ncreate,
103 	.vop_nmkdir		= vop_compat_nmkdir,
104 	.vop_nmknod		= vop_compat_nmknod,
105 	.vop_nlink		= vop_compat_nlink,
106 	.vop_nsymlink		= vop_compat_nsymlink,
107 	.vop_nwhiteout		= vop_compat_nwhiteout,
108 	.vop_nremove		= vop_compat_nremove,
109 	.vop_nrmdir		= vop_compat_nrmdir,
110 	.vop_nrename		= vop_compat_nrename,
111 	.vop_mountctl		= journal_mountctl
112 };
113 
114 VNODEOP_SET(default_vnode_vops);
115 
116 int
117 vop_eopnotsupp(struct vop_generic_args *ap)
118 {
119 	return (EOPNOTSUPP);
120 }
121 
122 int
123 vop_ebadf(struct vop_generic_args *ap)
124 {
125 	return (EBADF);
126 }
127 
128 int
129 vop_enotty(struct vop_generic_args *ap)
130 {
131 	return (ENOTTY);
132 }
133 
134 int
135 vop_einval(struct vop_generic_args *ap)
136 {
137 	return (EINVAL);
138 }
139 
140 int
141 vop_null(struct vop_generic_args *ap)
142 {
143 	return (0);
144 }
145 
146 int
147 vop_defaultop(struct vop_generic_args *ap)
148 {
149 	return (VOCALL(&default_vnode_vops, ap));
150 }
151 
152 int
153 vop_panic(struct vop_generic_args *ap)
154 {
155 	panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
156 }
157 
158 /*
159  * vop_compat_resolve { struct namecache *a_ncp }	XXX STOPGAP FUNCTION
160  *
161  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
162  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
163  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a
164  * vop_old_lookup() and does appropriate translations.
165  *
166  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
167  * VFSs will support this VOP and this routine can be removed, since
168  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
169  * API.
170  *
171  * A locked ncp is passed in to be resolved.  The NCP is resolved by
172  * figuring out the vnode (if any) and calling cache_setvp() to attach the
173  * vnode to the entry.  If the entry represents a non-existant node then
174  * cache_setvp() is called with a NULL vnode to resolve the entry into a
175  * negative cache entry.  No vnode locks are retained and the
176  * ncp is left locked on return.
177  *
178  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
179  *
180  * There is a potential directory and vnode interlock.   The lock order
181  * requirement is: namecache, governing directory, resolved vnode.
182  */
183 int
184 vop_compat_nresolve(struct vop_nresolve_args *ap)
185 {
186 	int error;
187 	struct vnode *dvp;
188 	struct vnode *vp;
189 	struct namecache *ncp;
190 	struct componentname cnp;
191 
192 	ncp = ap->a_ncp;	/* locked namecache node */
193 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
194 		return(EPERM);
195 	if (ncp->nc_parent == NULL)
196 		return(EPERM);
197 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
198 		return(EPERM);
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 		printf("[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 		VOP_UNLOCK(vp, 0);
226 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
227 		VOP_UNLOCK(dvp, 0);
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(ncp, 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(ncp, 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 	error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
296 	if (error == 0)
297 		VOP_UNLOCK(*ap->a_vpp, 0);
298 	if (cnp.cn_flags & CNP_PDIRUNLOCK)
299 		vrele(ap->a_dvp);
300 	else
301 		vput(ap->a_dvp);
302 	return (error);
303 }
304 
305 /*
306  * vop_compat_ncreate { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
307  *			struct vnode *a_vpp,
308  *			struct ucred *a_cred,
309  *			struct vattr *a_vap }
310  *
311  * Create a file as specified by a_vap.  Compatibility requires us to issue
312  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
313  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
314  */
315 int
316 vop_compat_ncreate(struct vop_ncreate_args *ap)
317 {
318 	struct thread *td = curthread;
319 	struct componentname cnp;
320 	struct namecache *ncp;
321 	struct vnode *dvp;
322 	int error;
323 
324 	/*
325 	 * Sanity checks, get a locked directory vnode.
326 	 */
327 	ncp = ap->a_ncp;		/* locked namecache node */
328 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
329 		return(EPERM);
330 	if (ncp->nc_parent == NULL)
331 		return(EPERM);
332 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
333 		return(EPERM);
334 
335 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
336 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
337 			ncp, ncp->nc_name);
338 		return(EAGAIN);
339 	}
340 
341 	/*
342 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
343 	 * caches all information required to create the entry in the
344 	 * directory inode.  We expect a return code of EJUSTRETURN for
345 	 * the CREATE case.  The cnp must simulated a saved-name situation.
346 	 */
347 	bzero(&cnp, sizeof(cnp));
348 	cnp.cn_nameiop = NAMEI_CREATE;
349 	cnp.cn_flags = CNP_LOCKPARENT;
350 	cnp.cn_nameptr = ncp->nc_name;
351 	cnp.cn_namelen = ncp->nc_nlen;
352 	cnp.cn_cred = ap->a_cred;
353 	cnp.cn_td = td;
354 	*ap->a_vpp = NULL;
355 
356 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
357 
358 	/*
359 	 * EJUSTRETURN should be returned for this case, which means that
360 	 * the VFS has setup the directory inode for the create.  The dvp we
361 	 * passed in is expected to remain in a locked state.
362 	 *
363 	 * If the VOP_OLD_CREATE is successful we are responsible for updating
364 	 * the cache state of the locked ncp that was passed to us.
365 	 */
366 	if (error == EJUSTRETURN) {
367 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
368 		error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
369 		if (error == 0) {
370 			cache_setunresolved(ncp);
371 			cache_setvp(ncp, *ap->a_vpp);
372 		}
373 	} else {
374 		if (error == 0) {
375 			vput(*ap->a_vpp);
376 			*ap->a_vpp = NULL;
377 			error = EEXIST;
378 		}
379 		KKASSERT(*ap->a_vpp == NULL);
380 	}
381 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
382 		VOP_UNLOCK(dvp, 0);
383 	vrele(dvp);
384 	return (error);
385 }
386 
387 /*
388  * vop_compat_nmkdir { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
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 namecache *ncp;
403 	struct vnode *dvp;
404 	int error;
405 
406 	/*
407 	 * Sanity checks, get a locked directory vnode.
408 	 */
409 	ncp = ap->a_ncp;		/* locked namecache node */
410 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
411 		return(EPERM);
412 	if (ncp->nc_parent == NULL)
413 		return(EPERM);
414 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
415 		return(EPERM);
416 
417 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
418 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
419 			ncp, ncp->nc_name);
420 		return(EAGAIN);
421 	}
422 
423 	/*
424 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
425 	 * caches all information required to create the entry in the
426 	 * directory inode.  We expect a return code of EJUSTRETURN for
427 	 * the CREATE case.  The cnp must simulated a saved-name situation.
428 	 */
429 	bzero(&cnp, sizeof(cnp));
430 	cnp.cn_nameiop = NAMEI_CREATE;
431 	cnp.cn_flags = CNP_LOCKPARENT;
432 	cnp.cn_nameptr = ncp->nc_name;
433 	cnp.cn_namelen = ncp->nc_nlen;
434 	cnp.cn_cred = ap->a_cred;
435 	cnp.cn_td = td;
436 	*ap->a_vpp = NULL;
437 
438 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
439 
440 	/*
441 	 * EJUSTRETURN should be returned for this case, which means that
442 	 * the VFS has setup the directory inode for the create.  The dvp we
443 	 * passed in is expected to remain in a locked state.
444 	 *
445 	 * If the VOP_OLD_MKDIR is successful we are responsible for updating
446 	 * the cache state of the locked ncp that was passed to us.
447 	 */
448 	if (error == EJUSTRETURN) {
449 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
450 		error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
451 		if (error == 0) {
452 			cache_setunresolved(ncp);
453 			cache_setvp(ncp, *ap->a_vpp);
454 		}
455 	} else {
456 		if (error == 0) {
457 			vput(*ap->a_vpp);
458 			*ap->a_vpp = NULL;
459 			error = EEXIST;
460 		}
461 		KKASSERT(*ap->a_vpp == NULL);
462 	}
463 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
464 		VOP_UNLOCK(dvp, 0);
465 	vrele(dvp);
466 	return (error);
467 }
468 
469 /*
470  * vop_compat_nmknod { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
471  *			struct vnode *a_vpp,
472  *			struct ucred *a_cred,
473  *			struct vattr *a_vap }
474  *
475  * Create a device or fifo node as specified by a_vap.  Compatibility requires
476  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
477  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
478  */
479 int
480 vop_compat_nmknod(struct vop_nmknod_args *ap)
481 {
482 	struct thread *td = curthread;
483 	struct componentname cnp;
484 	struct namecache *ncp;
485 	struct vnode *dvp;
486 	int error;
487 
488 	/*
489 	 * Sanity checks, get a locked directory vnode.
490 	 */
491 	ncp = ap->a_ncp;		/* locked namecache node */
492 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
493 		return(EPERM);
494 	if (ncp->nc_parent == NULL)
495 		return(EPERM);
496 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
497 		return(EPERM);
498 
499 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
500 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
501 			ncp, ncp->nc_name);
502 		return(EAGAIN);
503 	}
504 
505 	/*
506 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
507 	 * caches all information required to create the entry in the
508 	 * directory inode.  We expect a return code of EJUSTRETURN for
509 	 * the CREATE case.  The cnp must simulated a saved-name situation.
510 	 */
511 	bzero(&cnp, sizeof(cnp));
512 	cnp.cn_nameiop = NAMEI_CREATE;
513 	cnp.cn_flags = CNP_LOCKPARENT;
514 	cnp.cn_nameptr = ncp->nc_name;
515 	cnp.cn_namelen = ncp->nc_nlen;
516 	cnp.cn_cred = ap->a_cred;
517 	cnp.cn_td = td;
518 	*ap->a_vpp = NULL;
519 
520 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
521 
522 	/*
523 	 * EJUSTRETURN should be returned for this case, which means that
524 	 * the VFS has setup the directory inode for the create.  The dvp we
525 	 * passed in is expected to remain in a locked state.
526 	 *
527 	 * If the VOP_OLD_MKNOD is successful we are responsible for updating
528 	 * the cache state of the locked ncp that was passed to us.
529 	 */
530 	if (error == EJUSTRETURN) {
531 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
532 		error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
533 		if (error == 0) {
534 			cache_setunresolved(ncp);
535 			cache_setvp(ncp, *ap->a_vpp);
536 		}
537 	} else {
538 		if (error == 0) {
539 			vput(*ap->a_vpp);
540 			*ap->a_vpp = NULL;
541 			error = EEXIST;
542 		}
543 		KKASSERT(*ap->a_vpp == NULL);
544 	}
545 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
546 		VOP_UNLOCK(dvp, 0);
547 	vrele(dvp);
548 	return (error);
549 }
550 
551 /*
552  * vop_compat_nlink { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
553  *			struct vnode *a_vp,
554  *			struct ucred *a_cred }
555  *
556  * The passed vp is locked and represents the source.  The passed ncp is
557  * locked and represents the target to create.
558  */
559 int
560 vop_compat_nlink(struct vop_nlink_args *ap)
561 {
562 	struct thread *td = curthread;
563 	struct componentname cnp;
564 	struct namecache *ncp;
565 	struct vnode *dvp;
566 	struct vnode *tvp;
567 	int error;
568 
569 	/*
570 	 * Sanity checks, get a locked directory vnode.
571 	 */
572 	ncp = ap->a_ncp;		/* locked namecache node */
573 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
574 		return(EPERM);
575 	if (ncp->nc_parent == NULL)
576 		return(EPERM);
577 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
578 		return(EPERM);
579 
580 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
581 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
582 			ncp, ncp->nc_name);
583 		return(EAGAIN);
584 	}
585 
586 	/*
587 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
588 	 * caches all information required to create the entry in the
589 	 * directory inode.  We expect a return code of EJUSTRETURN for
590 	 * the CREATE case.  The cnp must simulated a saved-name situation.
591 	 */
592 	bzero(&cnp, sizeof(cnp));
593 	cnp.cn_nameiop = NAMEI_CREATE;
594 	cnp.cn_flags = CNP_LOCKPARENT;
595 	cnp.cn_nameptr = ncp->nc_name;
596 	cnp.cn_namelen = ncp->nc_nlen;
597 	cnp.cn_cred = ap->a_cred;
598 	cnp.cn_td = td;
599 
600 	tvp = NULL;
601 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
602 
603 	/*
604 	 * EJUSTRETURN should be returned for this case, which means that
605 	 * the VFS has setup the directory inode for the create.  The dvp we
606 	 * passed in is expected to remain in a locked state.
607 	 *
608 	 * If the VOP_OLD_LINK is successful we are responsible for updating
609 	 * the cache state of the locked ncp that was passed to us.
610 	 */
611 	if (error == EJUSTRETURN) {
612 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
613 		error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
614 		if (error == 0) {
615 			cache_setunresolved(ncp);
616 			cache_setvp(ncp, ap->a_vp);
617 		}
618 	} else {
619 		if (error == 0) {
620 			vput(tvp);
621 			error = EEXIST;
622 		}
623 	}
624 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
625 		VOP_UNLOCK(dvp, 0);
626 	vrele(dvp);
627 	return (error);
628 }
629 
630 int
631 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
632 {
633 	struct thread *td = curthread;
634 	struct componentname cnp;
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 	ncp = ap->a_ncp;		/* locked namecache node */
645 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
646 		return(EPERM);
647 	if (ncp->nc_parent == NULL)
648 		return(EPERM);
649 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
650 		return(EPERM);
651 
652 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
653 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
654 			ncp, ncp->nc_name);
655 		return(EAGAIN);
656 	}
657 
658 	/*
659 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
660 	 * caches all information required to create the entry in the
661 	 * directory inode.  We expect a return code of EJUSTRETURN for
662 	 * the CREATE case.  The cnp must simulated a saved-name situation.
663 	 */
664 	bzero(&cnp, sizeof(cnp));
665 	cnp.cn_nameiop = NAMEI_CREATE;
666 	cnp.cn_flags = CNP_LOCKPARENT;
667 	cnp.cn_nameptr = ncp->nc_name;
668 	cnp.cn_namelen = ncp->nc_nlen;
669 	cnp.cn_cred = ap->a_cred;
670 	cnp.cn_td = td;
671 
672 	vp = NULL;
673 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
674 
675 	/*
676 	 * EJUSTRETURN should be returned for this case, which means that
677 	 * the VFS has setup the directory inode for the create.  The dvp we
678 	 * passed in is expected to remain in a locked state.
679 	 *
680 	 * If the VOP_OLD_SYMLINK is successful we are responsible for updating
681 	 * the cache state of the locked ncp that was passed to us.
682 	 */
683 	if (error == EJUSTRETURN) {
684 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
685 		error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
686 		if (error == 0) {
687 			cache_setunresolved(ncp);
688 			cache_setvp(ncp, vp);
689 			*ap->a_vpp = vp;
690 		}
691 	} else {
692 		if (error == 0) {
693 			vput(vp);
694 			vp = NULL;
695 			error = EEXIST;
696 		}
697 		KKASSERT(vp == NULL);
698 	}
699 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
700 		VOP_UNLOCK(dvp, 0);
701 	vrele(dvp);
702 	return (error);
703 }
704 
705 /*
706  * vop_compat_nwhiteout { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
707  *			  struct ucred *a_cred,
708  *			  int a_flags }
709  *
710  * Issie a whiteout operation (create, lookup, or delete).  Compatibility
711  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue
712  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
713  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
714  * no lookup is necessary.
715  */
716 int
717 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
718 {
719 	struct thread *td = curthread;
720 	struct componentname cnp;
721 	struct namecache *ncp;
722 	struct vnode *dvp;
723 	struct vnode *vp;
724 	int error;
725 
726 	/*
727 	 * Sanity checks, get a locked directory vnode.
728 	 */
729 	ncp = ap->a_ncp;		/* locked namecache node */
730 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
731 		return(EPERM);
732 	if (ncp->nc_parent == NULL)
733 		return(EPERM);
734 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
735 		return(EPERM);
736 
737 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
738 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
739 			ncp, ncp->nc_name);
740 		return(EAGAIN);
741 	}
742 
743 	/*
744 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
745 	 * caches all information required to create the entry in the
746 	 * directory inode.  We expect a return code of EJUSTRETURN for
747 	 * the CREATE case.  The cnp must simulated a saved-name situation.
748 	 */
749 	bzero(&cnp, sizeof(cnp));
750 	cnp.cn_nameiop = ap->a_flags;
751 	cnp.cn_flags = CNP_LOCKPARENT;
752 	cnp.cn_nameptr = ncp->nc_name;
753 	cnp.cn_namelen = ncp->nc_nlen;
754 	cnp.cn_cred = ap->a_cred;
755 	cnp.cn_td = td;
756 
757 	vp = NULL;
758 
759 	/*
760 	 * EJUSTRETURN should be returned for the CREATE or DELETE cases.
761 	 * The VFS has setup the directory inode for the create.  The dvp we
762 	 * passed in is expected to remain in a locked state.
763 	 *
764 	 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
765 	 * the cache state of the locked ncp that was passed to us.
766 	 */
767 	switch(ap->a_flags) {
768 	case NAMEI_DELETE:
769 		cnp.cn_flags |= CNP_DOWHITEOUT;
770 		/* fall through */
771 	case NAMEI_CREATE:
772 		error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
773 		if (error == EJUSTRETURN) {
774 			KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
775 			error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
776 			if (error == 0)
777 				cache_setunresolved(ncp);
778 		} else {
779 			if (error == 0) {
780 				vput(vp);
781 				vp = NULL;
782 				error = EEXIST;
783 			}
784 			KKASSERT(vp == NULL);
785 		}
786 		break;
787 	case NAMEI_LOOKUP:
788 		error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
789 		break;
790 	default:
791 		error = EINVAL;
792 		break;
793 	}
794 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
795 		VOP_UNLOCK(dvp, 0);
796 	vrele(dvp);
797 	return (error);
798 }
799 
800 
801 /*
802  * vop_compat_nremove { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
803  *			  struct ucred *a_cred }
804  */
805 int
806 vop_compat_nremove(struct vop_nremove_args *ap)
807 {
808 	struct thread *td = curthread;
809 	struct componentname cnp;
810 	struct namecache *ncp;
811 	struct vnode *dvp;
812 	struct vnode *vp;
813 	int error;
814 
815 	/*
816 	 * Sanity checks, get a locked directory vnode.
817 	 */
818 	ncp = ap->a_ncp;		/* locked namecache node */
819 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
820 		return(EPERM);
821 	if (ncp->nc_parent == NULL)
822 		return(EPERM);
823 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
824 		return(EPERM);
825 
826 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
827 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
828 			ncp, ncp->nc_name);
829 		return(EAGAIN);
830 	}
831 
832 	/*
833 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
834 	 * caches all information required to delete the entry in the
835 	 * directory inode.  We expect a return code of 0 for the DELETE
836 	 * case (meaning that a vp has been found).  The cnp must simulated
837 	 * a saved-name situation.
838 	 */
839 	bzero(&cnp, sizeof(cnp));
840 	cnp.cn_nameiop = NAMEI_DELETE;
841 	cnp.cn_flags = CNP_LOCKPARENT;
842 	cnp.cn_nameptr = ncp->nc_name;
843 	cnp.cn_namelen = ncp->nc_nlen;
844 	cnp.cn_cred = ap->a_cred;
845 	cnp.cn_td = td;
846 
847 	/*
848 	 * The vnode must be a directory and must not represent the
849 	 * current directory.
850 	 */
851 	vp = NULL;
852 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
853 	if (error == 0 && vp->v_type == VDIR)
854 		error = EPERM;
855 	if (error == 0) {
856 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
857 		error = VOP_OLD_REMOVE(dvp, vp, &cnp);
858 		if (error == 0) {
859 			cache_setunresolved(ncp);
860 			cache_setvp(ncp, NULL);
861 		}
862 	}
863 	if (vp) {
864 		if (dvp == vp)
865 			vrele(vp);
866 		else
867 			vput(vp);
868 	}
869 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
870 		VOP_UNLOCK(dvp, 0);
871 	vrele(dvp);
872 	return (error);
873 }
874 
875 /*
876  * vop_compat_nrmdir { struct namecache *a_ncp, 	XXX STOPGAP FUNCTION
877  *			  struct ucred *a_cred }
878  */
879 int
880 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
881 {
882 	struct thread *td = curthread;
883 	struct componentname cnp;
884 	struct namecache *ncp;
885 	struct vnode *dvp;
886 	struct vnode *vp;
887 	int error;
888 
889 	/*
890 	 * Sanity checks, get a locked directory vnode.
891 	 */
892 	ncp = ap->a_ncp;		/* locked namecache node */
893 	if (ncp->nc_flag & NCF_MOUNTPT)	/* can't cross a mount point! */
894 		return(EPERM);
895 	if (ncp->nc_parent == NULL)
896 		return(EPERM);
897 	if ((dvp = ncp->nc_parent->nc_vp) == NULL)
898 		return(EPERM);
899 
900 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
901 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
902 			ncp, ncp->nc_name);
903 		return(EAGAIN);
904 	}
905 
906 	/*
907 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
908 	 * caches all information required to delete the entry in the
909 	 * directory inode.  We expect a return code of 0 for the DELETE
910 	 * case (meaning that a vp has been found).  The cnp must simulated
911 	 * a saved-name situation.
912 	 */
913 	bzero(&cnp, sizeof(cnp));
914 	cnp.cn_nameiop = NAMEI_DELETE;
915 	cnp.cn_flags = CNP_LOCKPARENT;
916 	cnp.cn_nameptr = ncp->nc_name;
917 	cnp.cn_namelen = ncp->nc_nlen;
918 	cnp.cn_cred = ap->a_cred;
919 	cnp.cn_td = td;
920 
921 	/*
922 	 * The vnode must be a directory and must not represent the
923 	 * current directory.
924 	 */
925 	vp = NULL;
926 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
927 	if (error == 0 && vp->v_type != VDIR)
928 		error = ENOTDIR;
929 	if (error == 0 && vp == dvp)
930 		error = EINVAL;
931 	if (error == 0 && (vp->v_flag & VROOT))
932 		error = EBUSY;
933 	if (error == 0) {
934 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
935 		error = VOP_OLD_RMDIR(dvp, vp, &cnp);
936 
937 		/*
938 		 * Note that this invalidation will cause any process
939 		 * currently CD'd into the directory being removed to be
940 		 * disconnected from the topology and not be able to ".."
941 		 * back out.
942 		 */
943 		if (error == 0)
944 			cache_inval(ncp, CINV_DESTROY);
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 		VOP_UNLOCK(dvp, 0);
954 	vrele(dvp);
955 	return (error);
956 }
957 
958 /*
959  * vop_compat_nrename { struct namecache *a_fncp, 	XXX STOPGAP FUNCTION
960  *			struct namecache *a_tncp,
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 namecache *fncp;
975 	struct namecache *tncp;
976 	struct vnode *fdvp, *fvp;
977 	struct vnode *tdvp, *tvp;
978 	int error;
979 
980 	/*
981 	 * Sanity checks, get referenced vnodes representing the source.
982 	 */
983 	fncp = ap->a_fncp;		/* locked namecache node */
984 	if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
985 		return(EPERM);
986 	if (fncp->nc_parent == NULL)
987 		return(EPERM);
988 	if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
989 		return(EPERM);
990 
991 	/*
992 	 * Temporarily lock the source directory and lookup in DELETE mode to
993 	 * check permissions.  XXX delete permissions should have been
994 	 * checked by nlookup(), we need to add NLC_DELETE for delete
995 	 * checking.  It is unclear whether VFS's require the directory setup
996 	 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
997 	 * since it isn't locked and since UFS always does a relookup of
998 	 * the source, it is believed that the only side effect that matters
999 	 * is the permissions check.
1000 	 */
1001 	if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
1002 		printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1003 			fncp, fncp->nc_name);
1004 		return(EAGAIN);
1005 	}
1006 
1007 	bzero(&fcnp, sizeof(fcnp));
1008 	fcnp.cn_nameiop = NAMEI_DELETE;
1009 	fcnp.cn_flags = CNP_LOCKPARENT;
1010 	fcnp.cn_nameptr = fncp->nc_name;
1011 	fcnp.cn_namelen = fncp->nc_nlen;
1012 	fcnp.cn_cred = ap->a_cred;
1013 	fcnp.cn_td = td;
1014 
1015 	/*
1016 	 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
1017 	 * fvp.
1018 	 */
1019 	fvp = NULL;
1020 	error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
1021 	if (error == 0 && (fvp->v_flag & VROOT)) {
1022 		vput(fvp);	/* as if vop_old_lookup had failed */
1023 		error = EBUSY;
1024 	}
1025 	if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1026 		fcnp.cn_flags |= CNP_PDIRUNLOCK;
1027 		VOP_UNLOCK(fdvp, 0);
1028 	}
1029 	if (error) {
1030 		vrele(fdvp);
1031 		return (error);
1032 	}
1033 	VOP_UNLOCK(fvp, 0);
1034 
1035 	/*
1036 	 * fdvp and fvp are now referenced and unlocked.
1037 	 *
1038 	 * Get a locked directory vnode for the target and lookup the target
1039 	 * in CREATE mode so it places the required information in the
1040 	 * directory inode.
1041 	 */
1042 	tncp = ap->a_tncp;		/* locked namecache node */
1043 	if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
1044 		error = EPERM;
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 		printf("[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(fncp, tncp);
1087 			cache_setvp(tncp, 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(fncp, tncp);
1098 			cache_setvp(tncp, 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(ap)
1113 	struct vop_old_lookup_args /* {
1114 		struct vnode *a_dvp;
1115 		struct vnode **a_vpp;
1116 		struct componentname *a_cnp;
1117 	} */ *ap;
1118 {
1119 
1120 	*ap->a_vpp = NULL;
1121 	return (ENOTDIR);
1122 }
1123 
1124 /*
1125  *	vop_nostrategy:
1126  *
1127  *	Strategy routine for VFS devices that have none.
1128  *
1129  *	B_ERROR and B_INVAL must be cleared prior to calling any strategy
1130  *	routine.  Typically this is done for a BUF_CMD_READ strategy call.
1131  *	Typically B_INVAL is assumed to already be clear prior to a write
1132  *	and should not be cleared manually unless you just made the buffer
1133  *	invalid.  B_ERROR should be cleared either way.
1134  */
1135 
1136 static int
1137 vop_nostrategy (struct vop_strategy_args *ap)
1138 {
1139 	printf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1140 	vprint("", ap->a_vp);
1141 	ap->a_bio->bio_buf->b_flags |= B_ERROR;
1142 	ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1143 	biodone(ap->a_bio);
1144 	return (EOPNOTSUPP);
1145 }
1146 
1147 int
1148 vop_stdpathconf(ap)
1149 	struct vop_pathconf_args /* {
1150 	struct vnode *a_vp;
1151 	int a_name;
1152 	int *a_retval;
1153 	} */ *ap;
1154 {
1155 
1156 	switch (ap->a_name) {
1157 		case _PC_LINK_MAX:
1158 			*ap->a_retval = LINK_MAX;
1159 			return (0);
1160 		case _PC_MAX_CANON:
1161 			*ap->a_retval = MAX_CANON;
1162 			return (0);
1163 		case _PC_MAX_INPUT:
1164 			*ap->a_retval = MAX_INPUT;
1165 			return (0);
1166 		case _PC_PIPE_BUF:
1167 			*ap->a_retval = PIPE_BUF;
1168 			return (0);
1169 		case _PC_CHOWN_RESTRICTED:
1170 			*ap->a_retval = 1;
1171 			return (0);
1172 		case _PC_VDISABLE:
1173 			*ap->a_retval = _POSIX_VDISABLE;
1174 			return (0);
1175 		default:
1176 			return (EINVAL);
1177 	}
1178 	/* NOTREACHED */
1179 }
1180 
1181 /*
1182  * Standard open.
1183  *
1184  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp,
1185  *  struct thread *a_td)
1186  *
1187  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1188  */
1189 int
1190 vop_stdopen(struct vop_open_args *ap)
1191 {
1192 	struct vnode *vp = ap->a_vp;
1193 	struct file *fp;
1194 
1195 	if ((fp = ap->a_fp) != NULL) {
1196 		switch(vp->v_type) {
1197 		case VFIFO:
1198 			fp->f_type = DTYPE_FIFO;
1199 			break;
1200 		default:
1201 			fp->f_type = DTYPE_VNODE;
1202 			break;
1203 		}
1204 		fp->f_flag = ap->a_mode & FMASK;
1205 		fp->f_ops = &vnode_fileops;
1206 		fp->f_data = vp;
1207 		vref(vp);
1208 	}
1209 	if (ap->a_mode & FWRITE)
1210 		++vp->v_writecount;
1211 	KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1212 	++vp->v_opencount;
1213 	return (0);
1214 }
1215 
1216 /*
1217  * Standard close.
1218  *
1219  * (struct vnode *a_vp, int a_fflag, struct thread *a_td)
1220  *
1221  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
1222  */
1223 int
1224 vop_stdclose(struct vop_close_args *ap)
1225 {
1226 	struct vnode *vp = ap->a_vp;
1227 
1228 	KASSERT(vp->v_opencount > 0,
1229 		("VOP_STDCLOSE: BAD OPENCOUNT %p %d\n", vp, vp->v_opencount));
1230 	if (ap->a_fflag & FWRITE) {
1231 		KASSERT(vp->v_writecount > 0,
1232 			("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n",
1233 			vp, vp->v_writecount));
1234 		--vp->v_writecount;
1235 	}
1236 	--vp->v_opencount;
1237 	return (0);
1238 }
1239 
1240 /*
1241  * Standard lock.  The lock is recursive-capable only if the lock was
1242  * initialized with LK_CANRECURSE or that flag is passed in a_flags.
1243  */
1244 int
1245 vop_stdlock(ap)
1246 	struct vop_lock_args /* {
1247 		struct vnode *a_vp;
1248 		int a_flags;
1249 	} */ *ap;
1250 {
1251 	int error;
1252 
1253 #ifndef	DEBUG_LOCKS
1254 	error = lockmgr(&ap->a_vp->v_lock, ap->a_flags);
1255 #else
1256 	error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags,
1257 			"vop_stdlock", ap->a_vp->filename, ap->a_vp->line);
1258 #endif
1259 	return(error);
1260 }
1261 
1262 int
1263 vop_stdunlock(ap)
1264 	struct vop_unlock_args /* {
1265 		struct vnode *a_vp;
1266 		int a_flags;
1267 	} */ *ap;
1268 {
1269 	int error;
1270 
1271 	error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE);
1272 	return(error);
1273 }
1274 
1275 int
1276 vop_stdislocked(ap)
1277 	struct vop_islocked_args /* {
1278 		struct vnode *a_vp;
1279 		struct thread *a_td;
1280 	} */ *ap;
1281 {
1282 	return (lockstatus(&ap->a_vp->v_lock, ap->a_td));
1283 }
1284 
1285 /*
1286  * Return true for select/poll.
1287  */
1288 int
1289 vop_nopoll(ap)
1290 	struct vop_poll_args /* {
1291 		struct vnode *a_vp;
1292 		int  a_events;
1293 		struct ucred *a_cred;
1294 		struct proc *a_p;
1295 	} */ *ap;
1296 {
1297 	/*
1298 	 * Return true for read/write.  If the user asked for something
1299 	 * special, return POLLNVAL, so that clients have a way of
1300 	 * determining reliably whether or not the extended
1301 	 * functionality is present without hard-coding knowledge
1302 	 * of specific filesystem implementations.
1303 	 */
1304 	if (ap->a_events & ~POLLSTANDARD)
1305 		return (POLLNVAL);
1306 
1307 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1308 }
1309 
1310 /*
1311  * Implement poll for local filesystems that support it.
1312  */
1313 int
1314 vop_stdpoll(ap)
1315 	struct vop_poll_args /* {
1316 		struct vnode *a_vp;
1317 		int  a_events;
1318 		struct ucred *a_cred;
1319 	} */ *ap;
1320 {
1321 	if (ap->a_events & ~POLLSTANDARD)
1322 		return (vn_pollrecord(ap->a_vp, ap->a_events));
1323 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1324 }
1325 
1326 /*
1327  * vfs default ops
1328  * used to fill the vfs fucntion table to get reasonable default return values.
1329  */
1330 int
1331 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
1332 {
1333 	return (0);
1334 }
1335 
1336 int
1337 vfs_stdunmount(struct mount *mp, int mntflags)
1338 {
1339 	return (0);
1340 }
1341 
1342 int
1343 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1344 {
1345 	return (EOPNOTSUPP);
1346 }
1347 
1348 int
1349 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1350 {
1351 	return (EOPNOTSUPP);
1352 }
1353 
1354 int
1355 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1356 {
1357 	return (EOPNOTSUPP);
1358 }
1359 
1360 int
1361 vfs_stdstart(struct mount *mp, int flags)
1362 {
1363 	return (0);
1364 }
1365 
1366 int
1367 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1368 	caddr_t arg, struct ucred *cred)
1369 {
1370 	return (EOPNOTSUPP);
1371 }
1372 
1373 int
1374 vfs_stdsync(struct mount *mp, int waitfor)
1375 {
1376 	return (0);
1377 }
1378 
1379 int
1380 vfs_stdnosync(struct mount *mp, int waitfor)
1381 {
1382 	return (EOPNOTSUPP);
1383 }
1384 
1385 int
1386 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
1387 {
1388 	return (EOPNOTSUPP);
1389 }
1390 
1391 int
1392 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1393 {
1394 	return (EOPNOTSUPP);
1395 }
1396 
1397 int
1398 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1399 	struct ucred **credanonp)
1400 {
1401 	return (EOPNOTSUPP);
1402 }
1403 
1404 int
1405 vfs_stdinit(struct vfsconf *vfsp)
1406 {
1407 	return (0);
1408 }
1409 
1410 int
1411 vfs_stduninit(struct vfsconf *vfsp)
1412 {
1413 	return(0);
1414 }
1415 
1416 int
1417 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1418 	caddr_t arg, struct ucred *cred)
1419 {
1420 	return(EOPNOTSUPP);
1421 }
1422 
1423 /* end of vfs default ops */
1424