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