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