xref: /dragonfly/sys/kern/vfs_default.c (revision 655933d6)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed
6  * to Berkeley by John Heidemann of the UCLA Ficus project.
7  *
8  * The statvfs->statfs conversion code was contributed to the DragonFly
9  * Project by Joerg Sonnenberger <joerg@bec.de>.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
36  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/buf.h>
42 #include <sys/conf.h>
43 #include <sys/fcntl.h>
44 #include <sys/file.h>
45 #include <sys/kernel.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/unistd.h>
50 #include <sys/vnode.h>
51 #include <sys/namei.h>
52 #include <sys/mountctl.h>
53 #include <sys/vfs_quota.h>
54 #include <sys/uio.h>
55 
56 #include <machine/limits.h>
57 
58 #include <vm/vm.h>
59 #include <vm/vm_object.h>
60 #include <vm/vm_page.h>
61 #include <vm/vm_pager.h>
62 #include <vm/vnode_pager.h>
63 
64 static int	vop_nolookup (struct vop_old_lookup_args *);
65 static int	vop_nostrategy (struct vop_strategy_args *);
66 
67 /*
68  * This vnode table stores what we want to do if the filesystem doesn't
69  * implement a particular VOP.
70  *
71  * If there is no specific entry here, we will return EOPNOTSUPP.
72  */
73 struct vop_ops default_vnode_vops = {
74 	.vop_default		= vop_eopnotsupp,
75 	.vop_advlock		= (void *)vop_einval,
76 	.vop_fsync		= (void *)vop_null,
77 	.vop_fdatasync		= vop_stdfdatasync,
78 	.vop_ioctl		= (void *)vop_enotty,
79 	.vop_mmap		= (void *)vop_einval,
80 	.vop_old_lookup		= vop_nolookup,
81 	.vop_open		= vop_stdopen,
82 	.vop_close		= vop_stdclose,
83 	.vop_getattr_lite	= vop_stdgetattr_lite,
84 	.vop_pathconf		= vop_stdpathconf,
85 	.vop_readlink		= (void *)vop_einval,
86 	.vop_reallocblks	= (void *)vop_eopnotsupp,
87 	.vop_strategy		= vop_nostrategy,
88 	.vop_getacl		= (void *)vop_eopnotsupp,
89 	.vop_setacl		= (void *)vop_eopnotsupp,
90 	.vop_aclcheck		= (void *)vop_eopnotsupp,
91 	.vop_getextattr		= (void *)vop_eopnotsupp,
92 	.vop_setextattr		= (void *)vop_eopnotsupp,
93 	.vop_markatime		= vop_stdmarkatime,
94 	.vop_allocate		= vop_stdallocate,
95 	.vop_nresolve		= vop_compat_nresolve,
96 	.vop_nlookupdotdot	= vop_compat_nlookupdotdot,
97 	.vop_ncreate		= vop_compat_ncreate,
98 	.vop_nmkdir		= vop_compat_nmkdir,
99 	.vop_nmknod		= vop_compat_nmknod,
100 	.vop_nlink		= vop_compat_nlink,
101 	.vop_nsymlink		= vop_compat_nsymlink,
102 	.vop_nwhiteout		= vop_compat_nwhiteout,
103 	.vop_nremove		= vop_compat_nremove,
104 	.vop_nrmdir		= vop_compat_nrmdir,
105 	.vop_nrename		= vop_compat_nrename,
106 	.vop_mountctl		= vop_stdmountctl
107 };
108 
109 VNODEOP_SET(default_vnode_vops);
110 
111 int
112 vop_eopnotsupp(struct vop_generic_args *ap)
113 {
114 	return (EOPNOTSUPP);
115 }
116 
117 int
118 vop_ebadf(struct vop_generic_args *ap)
119 {
120 	return (EBADF);
121 }
122 
123 int
124 vop_enotty(struct vop_generic_args *ap)
125 {
126 	return (ENOTTY);
127 }
128 
129 int
130 vop_einval(struct vop_generic_args *ap)
131 {
132 	return (EINVAL);
133 }
134 
135 int
136 vop_stdmarkatime(struct vop_markatime_args *ap)
137 {
138 	return (EOPNOTSUPP);
139 }
140 
141 int
142 vop_null(struct vop_generic_args *ap)
143 {
144 	return (0);
145 }
146 
147 int
148 vop_defaultop(struct vop_generic_args *ap)
149 {
150 	return (VOCALL(&default_vnode_vops, ap));
151 }
152 
153 /*
154  * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
155  * XXX STOPGAP FUNCTION
156  *
157  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
158  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
159  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a
160  * vop_old_lookup() and does appropriate translations.
161  *
162  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
163  * VFSs will support this VOP and this routine can be removed, since
164  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
165  * API.
166  *
167  * A locked ncp is passed in to be resolved.  The NCP is resolved by
168  * figuring out the vnode (if any) and calling cache_setvp() to attach the
169  * vnode to the entry.  If the entry represents a non-existant node then
170  * cache_setvp() is called with a NULL vnode to resolve the entry into a
171  * negative cache entry.  No vnode locks are retained and the
172  * ncp is left locked on return.
173  *
174  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
175  *
176  * There is a potential directory and vnode interlock.   The lock order
177  * requirement is: namecache, governing directory, resolved vnode.
178  */
179 int
180 vop_compat_nresolve(struct vop_nresolve_args *ap)
181 {
182 	int error;
183 	struct vnode *dvp;
184 	struct vnode *vp;
185 	struct nchandle *nch;
186 	struct namecache *ncp;
187 	struct componentname cnp;
188 
189 	nch = ap->a_nch;	/* locked namecache node */
190 	ncp = nch->ncp;
191 	dvp = ap->a_dvp;
192 
193 	/*
194 	 * UFS currently stores all sorts of side effects, including a loop
195 	 * variable, in the directory inode.  That needs to be fixed and the
196 	 * other VFS's audited before we can switch to LK_SHARED.
197 	 */
198 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
199 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
200 			ncp, ncp->nc_name);
201 		return(EAGAIN);
202 	}
203 
204 	bzero(&cnp, sizeof(cnp));
205 	cnp.cn_nameiop = NAMEI_LOOKUP;
206 	cnp.cn_flags = 0;
207 	cnp.cn_nameptr = ncp->nc_name;
208 	cnp.cn_namelen = ncp->nc_nlen;
209 	cnp.cn_cred = ap->a_cred;
210 	cnp.cn_td = curthread; /* XXX */
211 
212 	/*
213 	 * vop_old_lookup() always returns vp locked.  dvp may or may not be
214 	 * left locked depending on CNP_PDIRUNLOCK.
215 	 */
216 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
217 	if (error == 0)
218 		vn_unlock(vp);
219 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
220 		vn_unlock(dvp);
221 	if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
222 		/* was resolved by another process while we were unlocked */
223 		if (error == 0)
224 			vrele(vp);
225 	} else if (error == 0) {
226 		KKASSERT(vp != NULL);
227 		cache_setvp(nch, vp);
228 		vrele(vp);
229 	} else if (error == ENOENT) {
230 		KKASSERT(vp == NULL);
231 		if (cnp.cn_flags & CNP_ISWHITEOUT)
232 			ncp->nc_flag |= NCF_WHITEOUT;
233 		cache_setvp(nch, NULL);
234 	}
235 	vrele(dvp);
236 	return (error);
237 }
238 
239 /*
240  * vop_compat_nlookupdotdot { struct vnode *a_dvp,
241  *			struct vnode **a_vpp,
242  *			struct ucred *a_cred }
243  *
244  * Lookup the vnode representing the parent directory of the specified
245  * directory vnode.  a_dvp should not be locked.  If no error occurs *a_vpp
246  * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
247  *
248  * This function is designed to aid NFS server-side operations and is
249  * used by cache_fromdvp() to create a consistent, connected namecache
250  * topology.
251  *
252  * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
253  * code out from their *_lookup() and create *_nlookupdotdot().  Then as time
254  * permits VFSs will implement the remaining *_n*() calls and finally get
255  * rid of their *_lookup() call.
256  */
257 int
258 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
259 {
260 	struct componentname cnp;
261 	int error;
262 
263 	/*
264 	 * UFS currently stores all sorts of side effects, including a loop
265 	 * variable, in the directory inode.  That needs to be fixed and the
266 	 * other VFS's audited before we can switch to LK_SHARED.
267 	 */
268 	*ap->a_vpp = NULL;
269 	if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
270 		return (error);
271 	if (ap->a_dvp->v_type != VDIR) {
272 		vput(ap->a_dvp);
273 		return (ENOTDIR);
274 	}
275 
276 	bzero(&cnp, sizeof(cnp));
277 	cnp.cn_nameiop = NAMEI_LOOKUP;
278 	cnp.cn_flags = CNP_ISDOTDOT;
279 	cnp.cn_nameptr = "..";
280 	cnp.cn_namelen = 2;
281 	cnp.cn_cred = ap->a_cred;
282 	cnp.cn_td = curthread; /* XXX */
283 
284 	/*
285 	 * vop_old_lookup() always returns vp locked.  dvp may or may not be
286 	 * left locked depending on CNP_PDIRUNLOCK.
287 	 *
288 	 * (*vpp) will be returned locked if no error occured, which is the
289 	 * state we want.
290 	 */
291 	error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
292 	if (cnp.cn_flags & CNP_PDIRUNLOCK)
293 		vrele(ap->a_dvp);
294 	else
295 		vput(ap->a_dvp);
296 	return (error);
297 }
298 
299 /*
300  * vop_compat_ncreate { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
301  *			struct vnode *a_dvp,
302  *			struct vnode **a_vpp,
303  *			struct ucred *a_cred,
304  *			struct vattr *a_vap }
305  *
306  * Create a file as specified by a_vap.  Compatibility requires us to issue
307  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
308  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
309  */
310 int
311 vop_compat_ncreate(struct vop_ncreate_args *ap)
312 {
313 	struct thread *td = curthread;
314 	struct componentname cnp;
315 	struct nchandle *nch;
316 	struct namecache *ncp;
317 	struct vnode *dvp;
318 	int error;
319 
320 	/*
321 	 * Sanity checks, get a locked directory vnode.
322 	 */
323 	nch = ap->a_nch;		/* locked namecache node */
324 	dvp = ap->a_dvp;
325 	ncp = nch->ncp;
326 
327 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
328 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
329 			ncp, ncp->nc_name);
330 		return(EAGAIN);
331 	}
332 
333 	/*
334 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
335 	 * caches all information required to create the entry in the
336 	 * directory inode.  We expect a return code of EJUSTRETURN for
337 	 * the CREATE case.  The cnp must simulated a saved-name situation.
338 	 */
339 	bzero(&cnp, sizeof(cnp));
340 	cnp.cn_nameiop = NAMEI_CREATE;
341 	cnp.cn_flags = CNP_LOCKPARENT;
342 	cnp.cn_nameptr = ncp->nc_name;
343 	cnp.cn_namelen = ncp->nc_nlen;
344 	cnp.cn_cred = ap->a_cred;
345 	cnp.cn_td = td;
346 	*ap->a_vpp = NULL;
347 
348 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
349 
350 	/*
351 	 * EJUSTRETURN should be returned for this case, which means that
352 	 * the VFS has setup the directory inode for the create.  The dvp we
353 	 * passed in is expected to remain in a locked state.
354 	 *
355 	 * If the VOP_OLD_CREATE is successful we are responsible for updating
356 	 * the cache state of the locked ncp that was passed to us.
357 	 */
358 	if (error == EJUSTRETURN) {
359 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
360 		error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
361 		if (error == 0) {
362 			cache_setunresolved(nch);
363 			cache_setvp(nch, *ap->a_vpp);
364 		}
365 	} else {
366 		if (error == 0) {
367 			vput(*ap->a_vpp);
368 			*ap->a_vpp = NULL;
369 			error = EEXIST;
370 		}
371 		KKASSERT(*ap->a_vpp == NULL);
372 	}
373 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
374 		vn_unlock(dvp);
375 	vrele(dvp);
376 	return (error);
377 }
378 
379 /*
380  * vop_compat_nmkdir { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
381  *			struct vnode *a_dvp,
382  *			struct vnode **a_vpp,
383  *			struct ucred *a_cred,
384  *			struct vattr *a_vap }
385  *
386  * Create a directory as specified by a_vap.  Compatibility requires us to
387  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
388  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
389  */
390 int
391 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
392 {
393 	struct thread *td = curthread;
394 	struct componentname cnp;
395 	struct nchandle *nch;
396 	struct namecache *ncp;
397 	struct vnode *dvp;
398 	int error;
399 
400 	/*
401 	 * Sanity checks, get a locked directory vnode.
402 	 */
403 	nch = ap->a_nch;		/* locked namecache node */
404 	ncp = nch->ncp;
405 	dvp = ap->a_dvp;
406 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
407 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
408 			ncp, ncp->nc_name);
409 		return(EAGAIN);
410 	}
411 
412 	/*
413 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
414 	 * caches all information required to create the entry in the
415 	 * directory inode.  We expect a return code of EJUSTRETURN for
416 	 * the CREATE case.  The cnp must simulated a saved-name situation.
417 	 */
418 	bzero(&cnp, sizeof(cnp));
419 	cnp.cn_nameiop = NAMEI_CREATE;
420 	cnp.cn_flags = CNP_LOCKPARENT;
421 	cnp.cn_nameptr = ncp->nc_name;
422 	cnp.cn_namelen = ncp->nc_nlen;
423 	cnp.cn_cred = ap->a_cred;
424 	cnp.cn_td = td;
425 	*ap->a_vpp = NULL;
426 
427 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
428 
429 	/*
430 	 * EJUSTRETURN should be returned for this case, which means that
431 	 * the VFS has setup the directory inode for the create.  The dvp we
432 	 * passed in is expected to remain in a locked state.
433 	 *
434 	 * If the VOP_OLD_MKDIR is successful we are responsible for updating
435 	 * the cache state of the locked ncp that was passed to us.
436 	 */
437 	if (error == EJUSTRETURN) {
438 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
439 		error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
440 		if (error == 0) {
441 			cache_setunresolved(nch);
442 			cache_setvp(nch, *ap->a_vpp);
443 		}
444 	} else {
445 		if (error == 0) {
446 			vput(*ap->a_vpp);
447 			*ap->a_vpp = NULL;
448 			error = EEXIST;
449 		}
450 		KKASSERT(*ap->a_vpp == NULL);
451 	}
452 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
453 		vn_unlock(dvp);
454 	vrele(dvp);
455 	return (error);
456 }
457 
458 /*
459  * vop_compat_nmknod { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
460  *			struct vnode *a_dvp,
461  *			struct vnode **a_vpp,
462  *			struct ucred *a_cred,
463  *			struct vattr *a_vap }
464  *
465  * Create a device or fifo node as specified by a_vap.  Compatibility requires
466  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
467  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
468  */
469 int
470 vop_compat_nmknod(struct vop_nmknod_args *ap)
471 {
472 	struct thread *td = curthread;
473 	struct componentname cnp;
474 	struct nchandle *nch;
475 	struct namecache *ncp;
476 	struct vnode *dvp;
477 	int error;
478 
479 	/*
480 	 * Sanity checks, get a locked directory vnode.
481 	 */
482 	nch = ap->a_nch;		/* locked namecache node */
483 	ncp = nch->ncp;
484 	dvp = ap->a_dvp;
485 
486 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
487 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
488 			ncp, ncp->nc_name);
489 		return(EAGAIN);
490 	}
491 
492 	/*
493 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
494 	 * caches all information required to create the entry in the
495 	 * directory inode.  We expect a return code of EJUSTRETURN for
496 	 * the CREATE case.  The cnp must simulated a saved-name situation.
497 	 */
498 	bzero(&cnp, sizeof(cnp));
499 	cnp.cn_nameiop = NAMEI_CREATE;
500 	cnp.cn_flags = CNP_LOCKPARENT;
501 	cnp.cn_nameptr = ncp->nc_name;
502 	cnp.cn_namelen = ncp->nc_nlen;
503 	cnp.cn_cred = ap->a_cred;
504 	cnp.cn_td = td;
505 	*ap->a_vpp = NULL;
506 
507 	error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
508 
509 	/*
510 	 * EJUSTRETURN should be returned for this case, which means that
511 	 * the VFS has setup the directory inode for the create.  The dvp we
512 	 * passed in is expected to remain in a locked state.
513 	 *
514 	 * If the VOP_OLD_MKNOD is successful we are responsible for updating
515 	 * the cache state of the locked ncp that was passed to us.
516 	 */
517 	if (error == EJUSTRETURN) {
518 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
519 		error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
520 		if (error == 0) {
521 			cache_setunresolved(nch);
522 			cache_setvp(nch, *ap->a_vpp);
523 		}
524 	} else {
525 		if (error == 0) {
526 			vput(*ap->a_vpp);
527 			*ap->a_vpp = NULL;
528 			error = EEXIST;
529 		}
530 		KKASSERT(*ap->a_vpp == NULL);
531 	}
532 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
533 		vn_unlock(dvp);
534 	vrele(dvp);
535 	return (error);
536 }
537 
538 /*
539  * vop_compat_nlink { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
540  *			struct vnode *a_dvp,
541  *			struct vnode *a_vp,
542  *			struct ucred *a_cred }
543  *
544  * The passed vp is locked and represents the source.  The passed ncp is
545  * locked and represents the target to create.
546  */
547 int
548 vop_compat_nlink(struct vop_nlink_args *ap)
549 {
550 	struct thread *td = curthread;
551 	struct componentname cnp;
552 	struct nchandle *nch;
553 	struct namecache *ncp;
554 	struct vnode *dvp;
555 	struct vnode *tvp;
556 	int error;
557 
558 	/*
559 	 * Sanity checks, get a locked directory vnode.
560 	 */
561 	nch = ap->a_nch;		/* locked namecache node */
562 	ncp = nch->ncp;
563 	dvp = ap->a_dvp;
564 
565 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
566 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
567 			ncp, ncp->nc_name);
568 		return(EAGAIN);
569 	}
570 
571 	/*
572 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
573 	 * caches all information required to create the entry in the
574 	 * directory inode.  We expect a return code of EJUSTRETURN for
575 	 * the CREATE case.  The cnp must simulated a saved-name situation.
576 	 *
577 	 * It should not be possible for there to be a vnode collision
578 	 * between the source vp and target (name lookup).  However NFS
579 	 * clients racing each other can cause NFS to alias the same vnode
580 	 * across several names without the rest of the system knowing it.
581 	 * Use CNP_NOTVP to avoid a panic in this situation.
582 	 */
583 	bzero(&cnp, sizeof(cnp));
584 	cnp.cn_nameiop = NAMEI_CREATE;
585 	cnp.cn_flags = CNP_LOCKPARENT | CNP_NOTVP;
586 	cnp.cn_nameptr = ncp->nc_name;
587 	cnp.cn_namelen = ncp->nc_nlen;
588 	cnp.cn_cred = ap->a_cred;
589 	cnp.cn_td = td;
590 	cnp.cn_notvp = ap->a_vp;
591 
592 	tvp = NULL;
593 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
594 
595 	/*
596 	 * EJUSTRETURN should be returned for this case, which means that
597 	 * the VFS has setup the directory inode for the create.  The dvp we
598 	 * passed in is expected to remain in a locked state.
599 	 *
600 	 * If the VOP_OLD_LINK is successful we are responsible for updating
601 	 * the cache state of the locked ncp that was passed to us.
602 	 */
603 	if (error == EJUSTRETURN) {
604 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
605 		error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
606 		if (error == 0) {
607 			cache_setunresolved(nch);
608 			cache_setvp(nch, ap->a_vp);
609 		}
610 	} else {
611 		if (error == 0) {
612 			vput(tvp);
613 			error = EEXIST;
614 		}
615 	}
616 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
617 		vn_unlock(dvp);
618 	vrele(dvp);
619 	return (error);
620 }
621 
622 int
623 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
624 {
625 	struct thread *td = curthread;
626 	struct componentname cnp;
627 	struct nchandle *nch;
628 	struct namecache *ncp;
629 	struct vnode *dvp;
630 	struct vnode *vp;
631 	int error;
632 
633 	/*
634 	 * Sanity checks, get a locked directory vnode.
635 	 */
636 	*ap->a_vpp = NULL;
637 	nch = ap->a_nch;		/* locked namecache node */
638 	ncp = nch->ncp;
639 	dvp = ap->a_dvp;
640 
641 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
642 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
643 			ncp, ncp->nc_name);
644 		return(EAGAIN);
645 	}
646 
647 	/*
648 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
649 	 * caches all information required to create the entry in the
650 	 * directory inode.  We expect a return code of EJUSTRETURN for
651 	 * the CREATE case.  The cnp must simulated a saved-name situation.
652 	 */
653 	bzero(&cnp, sizeof(cnp));
654 	cnp.cn_nameiop = NAMEI_CREATE;
655 	cnp.cn_flags = CNP_LOCKPARENT;
656 	cnp.cn_nameptr = ncp->nc_name;
657 	cnp.cn_namelen = ncp->nc_nlen;
658 	cnp.cn_cred = ap->a_cred;
659 	cnp.cn_td = td;
660 
661 	vp = NULL;
662 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
663 
664 	/*
665 	 * EJUSTRETURN should be returned for this case, which means that
666 	 * the VFS has setup the directory inode for the create.  The dvp we
667 	 * passed in is expected to remain in a locked state.
668 	 *
669 	 * If the VOP_OLD_SYMLINK is successful we are responsible for updating
670 	 * the cache state of the locked ncp that was passed to us.
671 	 */
672 	if (error == EJUSTRETURN) {
673 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
674 		error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
675 		if (error == 0) {
676 			cache_setunresolved(nch);
677 			cache_setvp(nch, vp);
678 			*ap->a_vpp = vp;
679 		}
680 	} else {
681 		if (error == 0) {
682 			vput(vp);
683 			vp = NULL;
684 			error = EEXIST;
685 		}
686 		KKASSERT(vp == NULL);
687 	}
688 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
689 		vn_unlock(dvp);
690 	vrele(dvp);
691 	return (error);
692 }
693 
694 /*
695  * vop_compat_nwhiteout { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
696  *			  struct vnode *a_dvp,
697  *			  struct ucred *a_cred,
698  *			  int a_flags }
699  *
700  * Issie a whiteout operation (create, lookup, or delete).  Compatibility
701  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue
702  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
703  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
704  * no lookup is necessary.
705  */
706 int
707 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
708 {
709 	struct thread *td = curthread;
710 	struct componentname cnp;
711 	struct nchandle *nch;
712 	struct namecache *ncp;
713 	struct vnode *dvp;
714 	struct vnode *vp;
715 	int error;
716 
717 	/*
718 	 * Sanity checks, get a locked directory vnode.
719 	 */
720 	nch = ap->a_nch;		/* locked namecache node */
721 	ncp = nch->ncp;
722 	dvp = ap->a_dvp;
723 
724 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
725 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
726 			ncp, ncp->nc_name);
727 		return(EAGAIN);
728 	}
729 
730 	/*
731 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
732 	 * caches all information required to create the entry in the
733 	 * directory inode.  We expect a return code of EJUSTRETURN for
734 	 * the CREATE case.  The cnp must simulated a saved-name situation.
735 	 */
736 	bzero(&cnp, sizeof(cnp));
737 	cnp.cn_nameiop = ap->a_flags;
738 	cnp.cn_flags = CNP_LOCKPARENT;
739 	cnp.cn_nameptr = ncp->nc_name;
740 	cnp.cn_namelen = ncp->nc_nlen;
741 	cnp.cn_cred = ap->a_cred;
742 	cnp.cn_td = td;
743 
744 	vp = NULL;
745 
746 	/*
747 	 * EJUSTRETURN should be returned for the CREATE or DELETE cases.
748 	 * The VFS has setup the directory inode for the create.  The dvp we
749 	 * passed in is expected to remain in a locked state.
750 	 *
751 	 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
752 	 * the cache state of the locked ncp that was passed to us.
753 	 */
754 	switch(ap->a_flags) {
755 	case NAMEI_DELETE:
756 		cnp.cn_flags |= CNP_DOWHITEOUT;
757 		/* fall through */
758 	case NAMEI_CREATE:
759 		error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
760 		if (error == EJUSTRETURN) {
761 			KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
762 			error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
763 			if (error == 0)
764 				cache_setunresolved(nch);
765 		} else {
766 			if (error == 0) {
767 				vput(vp);
768 				vp = NULL;
769 				error = EEXIST;
770 			}
771 			KKASSERT(vp == NULL);
772 		}
773 		break;
774 	case NAMEI_LOOKUP:
775 		error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
776 		break;
777 	default:
778 		error = EINVAL;
779 		break;
780 	}
781 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
782 		vn_unlock(dvp);
783 	vrele(dvp);
784 	return (error);
785 }
786 
787 
788 /*
789  * vop_compat_nremove { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
790  *			struct vnode *a_dvp,
791  *			struct ucred *a_cred }
792  */
793 int
794 vop_compat_nremove(struct vop_nremove_args *ap)
795 {
796 	struct thread *td = curthread;
797 	struct componentname cnp;
798 	struct nchandle *nch;
799 	struct namecache *ncp;
800 	struct vnode *dvp;
801 	struct vnode *vp;
802 	int error;
803 
804 	/*
805 	 * Sanity checks, get a locked directory vnode.
806 	 */
807 	nch = ap->a_nch;		/* locked namecache node */
808 	ncp = nch->ncp;
809 	dvp = ap->a_dvp;
810 
811 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
812 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
813 			ncp, ncp->nc_name);
814 		return(EAGAIN);
815 	}
816 
817 	/*
818 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
819 	 * caches all information required to delete the entry in the
820 	 * directory inode.  We expect a return code of 0 for the DELETE
821 	 * case (meaning that a vp has been found).  The cnp must simulated
822 	 * a saved-name situation.
823 	 */
824 	bzero(&cnp, sizeof(cnp));
825 	cnp.cn_nameiop = NAMEI_DELETE;
826 	cnp.cn_flags = CNP_LOCKPARENT;
827 	cnp.cn_nameptr = ncp->nc_name;
828 	cnp.cn_namelen = ncp->nc_nlen;
829 	cnp.cn_cred = ap->a_cred;
830 	cnp.cn_td = td;
831 
832 	/*
833 	 * The vnode must be a directory and must not represent the
834 	 * current directory.
835 	 */
836 	vp = NULL;
837 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
838 	if (error == 0 && vp->v_type == VDIR)
839 		error = EPERM;
840 	if (error == 0) {
841 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
842 		error = VOP_OLD_REMOVE(dvp, vp, &cnp);
843 		if (error == 0)
844 			cache_unlink(nch);
845 	}
846 	if (vp) {
847 		if (dvp == vp)
848 			vrele(vp);
849 		else
850 			vput(vp);
851 	}
852 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
853 		vn_unlock(dvp);
854 	vrele(dvp);
855 	return (error);
856 }
857 
858 /*
859  * vop_compat_nrmdir { struct nchandle *a_nch, 	XXX STOPGAP FUNCTION
860  *		       struct vnode *dvp,
861  *		       struct ucred *a_cred }
862  */
863 int
864 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
865 {
866 	struct thread *td = curthread;
867 	struct componentname cnp;
868 	struct nchandle *nch;
869 	struct namecache *ncp;
870 	struct vnode *dvp;
871 	struct vnode *vp;
872 	int error;
873 
874 	/*
875 	 * Sanity checks, get a locked directory vnode.
876 	 */
877 	nch = ap->a_nch;		/* locked namecache node */
878 	ncp = nch->ncp;
879 	dvp = ap->a_dvp;
880 
881 	if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
882 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
883 			ncp, ncp->nc_name);
884 		return(EAGAIN);
885 	}
886 
887 	/*
888 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
889 	 * caches all information required to delete the entry in the
890 	 * directory inode.  We expect a return code of 0 for the DELETE
891 	 * case (meaning that a vp has been found).  The cnp must simulated
892 	 * a saved-name situation.
893 	 */
894 	bzero(&cnp, sizeof(cnp));
895 	cnp.cn_nameiop = NAMEI_DELETE;
896 	cnp.cn_flags = CNP_LOCKPARENT;
897 	cnp.cn_nameptr = ncp->nc_name;
898 	cnp.cn_namelen = ncp->nc_nlen;
899 	cnp.cn_cred = ap->a_cred;
900 	cnp.cn_td = td;
901 
902 	/*
903 	 * The vnode must be a directory and must not represent the
904 	 * current directory.
905 	 */
906 	vp = NULL;
907 	error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
908 	if (error == 0 && vp->v_type != VDIR)
909 		error = ENOTDIR;
910 	if (error == 0 && vp == dvp)
911 		error = EINVAL;
912 	if (error == 0 && (vp->v_flag & VROOT))
913 		error = EBUSY;
914 	if (error == 0) {
915 		KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
916 		error = VOP_OLD_RMDIR(dvp, vp, &cnp);
917 
918 		/*
919 		 * Note that this invalidation will cause any process
920 		 * currently CD'd into the directory being removed to be
921 		 * disconnected from the topology and not be able to ".."
922 		 * back out.
923 		 */
924 		if (error == 0) {
925 			cache_inval(nch, CINV_DESTROY);
926 			cache_inval_vp(vp, CINV_DESTROY);
927 		}
928 	}
929 	if (vp) {
930 		if (dvp == vp)
931 			vrele(vp);
932 		else
933 			vput(vp);
934 	}
935 	if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
936 		vn_unlock(dvp);
937 	vrele(dvp);
938 	return (error);
939 }
940 
941 /*
942  * vop_compat_nrename { struct nchandle *a_fnch, 	XXX STOPGAP FUNCTION
943  *			struct nchandle *a_tnch,
944  *			struct ucred *a_cred }
945  *
946  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
947  * the source directory and vnode be unlocked and the target directory and
948  * vnode (if it exists) be locked.  All arguments will be vrele'd and
949  * the targets will also be unlocked regardless of the return code.
950  */
951 int
952 vop_compat_nrename(struct vop_nrename_args *ap)
953 {
954 	struct thread *td = curthread;
955 	struct componentname fcnp;
956 	struct componentname tcnp;
957 	struct nchandle *fnch;
958 	struct nchandle *tnch;
959 	struct namecache *fncp;
960 	struct namecache *tncp;
961 	struct vnode *fdvp, *fvp;
962 	struct vnode *tdvp, *tvp;
963 	int error;
964 
965 	/*
966 	 * Sanity checks, get referenced vnodes representing the source.
967 	 */
968 	fnch = ap->a_fnch;		/* locked namecache node */
969 	fncp = fnch->ncp;
970 	fdvp = ap->a_fdvp;
971 
972 	/*
973 	 * Temporarily lock the source directory and lookup in DELETE mode to
974 	 * check permissions.  XXX delete permissions should have been
975 	 * checked by nlookup(), we need to add NLC_DELETE for delete
976 	 * checking.  It is unclear whether VFS's require the directory setup
977 	 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
978 	 * since it isn't locked and since UFS always does a relookup of
979 	 * the source, it is believed that the only side effect that matters
980 	 * is the permissions check.
981 	 */
982 	if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
983 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
984 			fncp, fncp->nc_name);
985 		return(EAGAIN);
986 	}
987 
988 	bzero(&fcnp, sizeof(fcnp));
989 	fcnp.cn_nameiop = NAMEI_DELETE;
990 	fcnp.cn_flags = CNP_LOCKPARENT;
991 	fcnp.cn_nameptr = fncp->nc_name;
992 	fcnp.cn_namelen = fncp->nc_nlen;
993 	fcnp.cn_cred = ap->a_cred;
994 	fcnp.cn_td = td;
995 
996 	/*
997 	 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
998 	 * fvp.
999 	 */
1000 	fvp = NULL;
1001 	error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
1002 	if (error == 0 && (fvp->v_flag & VROOT)) {
1003 		vput(fvp);	/* as if vop_old_lookup had failed */
1004 		error = EBUSY;
1005 	}
1006 	if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1007 		fcnp.cn_flags |= CNP_PDIRUNLOCK;
1008 		vn_unlock(fdvp);
1009 	}
1010 	if (error) {
1011 		vrele(fdvp);
1012 		return (error);
1013 	}
1014 	vn_unlock(fvp);
1015 
1016 	/*
1017 	 * fdvp and fvp are now referenced and unlocked.
1018 	 *
1019 	 * Get a locked directory vnode for the target and lookup the target
1020 	 * in CREATE mode so it places the required information in the
1021 	 * directory inode.
1022 	 */
1023 	tnch = ap->a_tnch;		/* locked namecache node */
1024 	tncp = tnch->ncp;
1025 	tdvp = ap->a_tdvp;
1026 	if (error) {
1027 		vrele(fdvp);
1028 		vrele(fvp);
1029 		return (error);
1030 	}
1031 	if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
1032 		kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1033 			tncp, tncp->nc_name);
1034 		vrele(fdvp);
1035 		vrele(fvp);
1036 		return(EAGAIN);
1037 	}
1038 
1039 	/*
1040 	 * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
1041 	 * caches all information required to create the entry in the
1042 	 * target directory inode.
1043 	 */
1044 	bzero(&tcnp, sizeof(tcnp));
1045 	tcnp.cn_nameiop = NAMEI_RENAME;
1046 	tcnp.cn_flags = CNP_LOCKPARENT;
1047 	tcnp.cn_nameptr = tncp->nc_name;
1048 	tcnp.cn_namelen = tncp->nc_nlen;
1049 	tcnp.cn_cred = ap->a_cred;
1050 	tcnp.cn_td = td;
1051 
1052 	tvp = NULL;
1053 	error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1054 
1055 	if (error == EJUSTRETURN) {
1056 		/*
1057 		 * Target does not exist.  tvp should be NULL.
1058 		 */
1059 		KKASSERT(tvp == NULL);
1060 		KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1061 		error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1062 		if (error == 0)
1063 			cache_rename(fnch, tnch);
1064 	} else if (error == 0) {
1065 		/*
1066 		 * Target exists.  VOP_OLD_RENAME should correctly delete the
1067 		 * target.
1068 		 */
1069 		KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1070 		error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1071 		if (error == 0)
1072 			cache_rename(fnch, tnch);
1073 	} else {
1074 		vrele(fdvp);
1075 		vrele(fvp);
1076 		if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1077 			vrele(tdvp);
1078 		else
1079 			vput(tdvp);
1080 	}
1081 	return (error);
1082 }
1083 
1084 static int
1085 vop_nolookup(struct vop_old_lookup_args *ap)
1086 {
1087 
1088 	*ap->a_vpp = NULL;
1089 	return (ENOTDIR);
1090 }
1091 
1092 /*
1093  *	vop_nostrategy:
1094  *
1095  *	Strategy routine for VFS devices that have none.
1096  *
1097  *	B_ERROR and B_INVAL must be cleared prior to calling any strategy
1098  *	routine.  Typically this is done for a BUF_CMD_READ strategy call.
1099  *	Typically B_INVAL is assumed to already be clear prior to a write
1100  *	and should not be cleared manually unless you just made the buffer
1101  *	invalid.  B_ERROR should be cleared either way.
1102  */
1103 
1104 static int
1105 vop_nostrategy (struct vop_strategy_args *ap)
1106 {
1107 	kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1108 	vprint("", ap->a_vp);
1109 	ap->a_bio->bio_buf->b_flags |= B_ERROR;
1110 	ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1111 	biodone(ap->a_bio);
1112 	return (EOPNOTSUPP);
1113 }
1114 
1115 int
1116 vop_stdpathconf(struct vop_pathconf_args *ap)
1117 {
1118 	int error = 0;
1119 
1120 	switch (ap->a_name) {
1121 	case _PC_CHOWN_RESTRICTED:
1122 		*ap->a_retval = _POSIX_CHOWN_RESTRICTED;
1123 		break;
1124 	case _PC_LINK_MAX:
1125 		*ap->a_retval = LINK_MAX;
1126 		break;
1127 	case _PC_MAX_CANON:
1128 		*ap->a_retval = MAX_CANON;
1129 		break;
1130 	case _PC_MAX_INPUT:
1131 		*ap->a_retval = MAX_INPUT;
1132 		break;
1133 	case _PC_NAME_MAX:
1134 		*ap->a_retval = NAME_MAX;
1135 		break;
1136 	case _PC_NO_TRUNC:
1137 		*ap->a_retval = _POSIX_NO_TRUNC;
1138 		break;
1139 	case _PC_PATH_MAX:
1140 		*ap->a_retval = PATH_MAX;
1141 		break;
1142 	case _PC_PIPE_BUF:
1143 		*ap->a_retval = PIPE_BUF;
1144 		break;
1145 	case _PC_VDISABLE:
1146 		*ap->a_retval = _POSIX_VDISABLE;
1147 		break;
1148 	default:
1149 		error = EINVAL;
1150 		break;
1151 	}
1152 	return (error);
1153 }
1154 
1155 /*
1156  * Standard open.
1157  *
1158  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
1159  *
1160  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1161  */
1162 int
1163 vop_stdopen(struct vop_open_args *ap)
1164 {
1165 	struct vnode *vp = ap->a_vp;
1166 	struct file *fp;
1167 
1168 	if (ap->a_fpp) {
1169 		fp = *ap->a_fpp;
1170 
1171 		switch(vp->v_type) {
1172 		case VFIFO:
1173 			fp->f_type = DTYPE_FIFO;
1174 			break;
1175 		default:
1176 			fp->f_type = DTYPE_VNODE;
1177 			break;
1178 		}
1179 		/* retain flags not to be copied */
1180 		fp->f_flag = (fp->f_flag & ~FMASK) | (ap->a_mode & FMASK);
1181 		fp->f_ops = &vnode_fileops;
1182 		fp->f_data = vp;
1183 		vref(vp);
1184 	}
1185 	if (ap->a_mode & FWRITE)
1186 		atomic_add_int(&vp->v_writecount, 1);
1187 	KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1188 	atomic_add_int(&vp->v_opencount, 1);
1189 	return (0);
1190 }
1191 
1192 /*
1193  * Standard close.
1194  *
1195  * (struct vnode *a_vp, int a_fflag)
1196  *
1197  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
1198  *
1199  * v_lastwrite_ts is used to record the timestamp that should be used to
1200  * set the file mtime for any asynchronously flushed pages modified via
1201  * mmap(), which can occur after the last close().
1202  */
1203 int
1204 vop_stdclose(struct vop_close_args *ap)
1205 {
1206 	struct vnode *vp = ap->a_vp;
1207 
1208 	KASSERT(vp->v_opencount > 0,
1209 		("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x",
1210 		vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
1211 	if (ap->a_fflag & FWRITE) {
1212 		KASSERT(vp->v_writecount > 0,
1213 			("VOP_STDCLOSE: BAD WRITECOUNT %p %d",
1214 			vp, vp->v_writecount));
1215 		atomic_add_int(&vp->v_writecount, -1);
1216 	}
1217 	atomic_add_int(&vp->v_opencount, -1);
1218 	return (0);
1219 }
1220 
1221 /*
1222  * Standard getattr_lite
1223  *
1224  * Just calls getattr
1225  */
1226 int
1227 vop_stdgetattr_lite(struct vop_getattr_lite_args *ap)
1228 {
1229 	struct vattr va;
1230 	struct vattr_lite *lvap;
1231 	int error;
1232 
1233 	error = VOP_GETATTR(ap->a_vp, &va);
1234 	if (__predict_true(error == 0)) {
1235 		lvap = ap->a_lvap;
1236 		lvap->va_type = va.va_type;
1237 		lvap->va_nlink = va.va_nlink;
1238 		lvap->va_mode = va.va_mode;
1239 		lvap->va_uid = va.va_uid;
1240 		lvap->va_gid = va.va_gid;
1241 		lvap->va_size = va.va_size;
1242 		lvap->va_flags = va.va_flags;
1243 	}
1244 	return error;
1245 }
1246 
1247 /*
1248  * Implement standard getpages and putpages.  All filesystems must use
1249  * the buffer cache to back regular files.
1250  */
1251 int
1252 vop_stdgetpages(struct vop_getpages_args *ap)
1253 {
1254 	struct mount *mp;
1255 	int error;
1256 
1257 	if ((mp = ap->a_vp->v_mount) != NULL) {
1258 		error = vnode_pager_generic_getpages(
1259 				ap->a_vp, ap->a_m, ap->a_count,
1260 				ap->a_reqpage, ap->a_seqaccess);
1261 	} else {
1262 		error = VM_PAGER_BAD;
1263 	}
1264 	return (error);
1265 }
1266 
1267 int
1268 vop_stdputpages(struct vop_putpages_args *ap)
1269 {
1270 	struct mount *mp;
1271 	int error;
1272 
1273 	if ((mp = ap->a_vp->v_mount) != NULL) {
1274 		error = vnode_pager_generic_putpages(
1275 				ap->a_vp, ap->a_m, ap->a_count,
1276 				ap->a_flags, ap->a_rtvals);
1277 	} else {
1278 		error = VM_PAGER_BAD;
1279 	}
1280 	return (error);
1281 }
1282 
1283 int
1284 vop_stdnoread(struct vop_read_args *ap)
1285 {
1286 	return (EINVAL);
1287 }
1288 
1289 int
1290 vop_stdnowrite(struct vop_write_args *ap)
1291 {
1292 	return (EINVAL);
1293 }
1294 
1295 /*
1296  * vfs default ops
1297  * used to fill the vfs fucntion table to get reasonable default return values.
1298  */
1299 int
1300 vop_stdmountctl(struct vop_mountctl_args *ap)
1301 {
1302 
1303 	struct mount *mp;
1304 	int error = 0;
1305 
1306 	mp = ap->a_head.a_ops->head.vv_mount;
1307 
1308 	switch(ap->a_op) {
1309 	case MOUNTCTL_MOUNTFLAGS:
1310 		/*
1311 		 * Get a string buffer with all the mount flags
1312 		 * names comman separated.
1313 		 * mount(2) will use this information.
1314 		 */
1315 		*ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
1316 					    ap->a_buf, ap->a_buflen, &error);
1317 		break;
1318 	case MOUNTCTL_INSTALL_VFS_JOURNAL:
1319 	case MOUNTCTL_RESTART_VFS_JOURNAL:
1320 	case MOUNTCTL_REMOVE_VFS_JOURNAL:
1321 	case MOUNTCTL_RESYNC_VFS_JOURNAL:
1322 	case MOUNTCTL_STATUS_VFS_JOURNAL:
1323 		error = journal_mountctl(ap);
1324 		break;
1325 	default:
1326 		error = EOPNOTSUPP;
1327 		break;
1328 	}
1329 	return (error);
1330 }
1331 
1332 int
1333 vop_stdallocate(struct vop_allocate_args *ap)
1334 {
1335 	struct thread *td;
1336 	struct vnode *vp;
1337 	struct vattr vattr, *vap;
1338 	struct uio auio;
1339 	struct iovec aiov;
1340 	uint8_t *buf;
1341 	off_t offset, len, fsize;
1342 	size_t iosize;
1343 	int error;
1344 
1345 	td = curthread;
1346 	vap = &vattr;
1347 	buf = NULL;
1348 
1349 	vp = ap->a_vp;
1350 	offset = ap->a_offset;
1351 	len = ap->a_len;
1352 
1353 	error = VOP_GETATTR(vp, vap);
1354 	if (error != 0)
1355 		goto out;
1356 	fsize = vap->va_size;
1357 	iosize = vap->va_blocksize;
1358 	if (iosize == 0)
1359 		iosize = BLKDEV_IOSIZE;
1360 	if (iosize > vmaxiosize(vp))
1361 		iosize = vmaxiosize(vp);
1362 	buf = kmalloc(iosize, M_TEMP, M_WAITOK);
1363 
1364 	if (offset + len > vap->va_size) {
1365 		/*
1366 		 * Test offset + len against the filesystem's maxfilesize.
1367 		 */
1368 		VATTR_NULL(&vattr);
1369 		vap->va_size = offset + len;
1370 		error = VOP_SETATTR(vp, vap, td->td_ucred);
1371 		if (error != 0)
1372 			goto out;
1373 		VATTR_NULL(&vattr);
1374 		vap->va_size = fsize;
1375 		error = VOP_SETATTR(vp, vap, td->td_ucred);
1376 		if (error != 0)
1377 			goto out;
1378 	}
1379 
1380 	for (;;) {
1381 		/*
1382 		 * Read and write back anything below the nominal file
1383 		 * size.  There's currently no way outside the filesystem
1384 		 * to know whether this area is sparse or not.
1385 		 */
1386 		off_t cur = iosize;
1387 		if ((offset % iosize) != 0)
1388 			cur -= (offset % iosize);
1389 		if (cur > len)
1390 			cur = len;
1391 		if (offset < fsize) {
1392 			aiov.iov_base = buf;
1393 			aiov.iov_len = cur;
1394 			auio.uio_iov = &aiov;
1395 			auio.uio_iovcnt = 1;
1396 			auio.uio_offset = offset;
1397 			auio.uio_resid = cur;
1398 			auio.uio_segflg = UIO_SYSSPACE;
1399 			auio.uio_rw = UIO_READ;
1400 			auio.uio_td = td;
1401 			error = VOP_READ(vp, &auio, 0, td->td_ucred);
1402 			if (error != 0)
1403 				break;
1404 			if (auio.uio_resid > 0) {
1405 				bzero(buf + cur - auio.uio_resid,
1406 				    auio.uio_resid);
1407 			}
1408 		} else {
1409 			bzero(buf, cur);
1410 		}
1411 
1412 		aiov.iov_base = buf;
1413 		aiov.iov_len = cur;
1414 		auio.uio_iov = &aiov;
1415 		auio.uio_iovcnt = 1;
1416 		auio.uio_offset = offset;
1417 		auio.uio_resid = cur;
1418 		auio.uio_segflg = UIO_SYSSPACE;
1419 		auio.uio_rw = UIO_WRITE;
1420 		auio.uio_td = td;
1421 
1422 		error = VOP_WRITE(vp, &auio, 0, td->td_ucred);
1423 		if (error != 0)
1424 			break;
1425 
1426 		len -= cur;
1427 		offset += cur;
1428 		if (len == 0)
1429 			break;
1430 		/*
1431 		if (should_yield())
1432 			break;
1433 		*/
1434 	}
1435 out:
1436 	ap->a_offset = offset;
1437 	ap->a_len = len;
1438 	kfree(buf, M_TEMP);
1439 
1440 	return (error);
1441 }
1442 
1443 int
1444 vop_stdfdatasync(struct vop_fdatasync_args *ap)
1445 {
1446 	return (VOP_FSYNC_FP(ap->a_vp, ap->a_waitfor, ap->a_flags, ap->a_fp));
1447 }
1448 
1449 int
1450 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1451 {
1452 	return (EOPNOTSUPP);
1453 }
1454 
1455 int
1456 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
1457 {
1458 	return (EOPNOTSUPP);
1459 }
1460 
1461 /*
1462  * If the VFS does not implement statvfs, then call statfs and convert
1463  * the values.  This code was taken from libc's __cvtstatvfs() function,
1464  * contributed by Joerg Sonnenberger.
1465  */
1466 int
1467 vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
1468 {
1469 	struct statfs *in;
1470 	int error;
1471 
1472 	in = &mp->mnt_stat;
1473 	error = VFS_STATFS(mp, in, cred);
1474 	if (error == 0) {
1475 		bzero(sbp, sizeof(*sbp));
1476 
1477 		sbp->f_bsize = in->f_bsize;
1478 		sbp->f_frsize = in->f_bsize;
1479 		sbp->f_blocks = in->f_blocks;
1480 		sbp->f_bfree = in->f_bfree;
1481 		sbp->f_bavail = in->f_bavail;
1482 		sbp->f_files = in->f_files;
1483 		sbp->f_ffree = in->f_ffree;
1484 
1485 		/*
1486 		 * XXX
1487 		 * This field counts the number of available inodes to non-root
1488 		 * users, but this information is not available via statfs.
1489 		 * Just ignore this issue by returning the total number
1490 		 * instead.
1491 		 */
1492 		sbp->f_favail = in->f_ffree;
1493 
1494 		/*
1495 		 * XXX
1496 		 * This field has a different meaning for statfs and statvfs.
1497 		 * For the former it is the cookie exported for NFS and not
1498 		 * intended for normal userland use.
1499 		 */
1500 		sbp->f_fsid = 0;
1501 
1502 		sbp->f_flag = 0;
1503 		if (in->f_flags & MNT_RDONLY)
1504 			sbp->f_flag |= ST_RDONLY;
1505 		if (in->f_flags & MNT_NOSUID)
1506 			sbp->f_flag |= ST_NOSUID;
1507 		sbp->f_namemax = 0;
1508 		sbp->f_owner = in->f_owner;
1509 		/*
1510 		 * XXX
1511 		 * statfs contains the type as string, statvfs expects it as
1512 		 * enumeration.
1513 		 */
1514 		sbp->f_type = 0;
1515 
1516 		sbp->f_syncreads = in->f_syncreads;
1517 		sbp->f_syncwrites = in->f_syncwrites;
1518 		sbp->f_asyncreads = in->f_asyncreads;
1519 		sbp->f_asyncwrites = in->f_asyncwrites;
1520 	}
1521 	return (error);
1522 }
1523 
1524 int
1525 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1526 {
1527 	return (EOPNOTSUPP);
1528 }
1529 
1530 int
1531 vfs_stdstart(struct mount *mp, int flags)
1532 {
1533 	return (0);
1534 }
1535 
1536 int
1537 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1538 	caddr_t arg, struct ucred *cred)
1539 {
1540 	return (EOPNOTSUPP);
1541 }
1542 
1543 int
1544 vfs_stdsync(struct mount *mp, int waitfor)
1545 {
1546 	return (0);
1547 }
1548 
1549 int
1550 vfs_stdnosync(struct mount *mp, int waitfor)
1551 {
1552 	return (EOPNOTSUPP);
1553 }
1554 
1555 int
1556 vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
1557 {
1558 	return (EOPNOTSUPP);
1559 }
1560 
1561 int
1562 vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
1563 	      struct fid *fhp, struct vnode **vpp)
1564 {
1565 	return (EOPNOTSUPP);
1566 }
1567 
1568 int
1569 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1570 	struct ucred **credanonp)
1571 {
1572 	return (EOPNOTSUPP);
1573 }
1574 
1575 int
1576 vfs_stdinit(struct vfsconf *vfsp)
1577 {
1578 	return (0);
1579 }
1580 
1581 int
1582 vfs_stduninit(struct vfsconf *vfsp)
1583 {
1584 	return(0);
1585 }
1586 
1587 int
1588 vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
1589 		 int attrnamespace, const char *attrname,
1590 		 struct ucred *cred)
1591 {
1592 	return(EOPNOTSUPP);
1593 }
1594 
1595 #define ACCOUNTING_NB_FSTYPES 7
1596 
1597 static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
1598 	"ext2fs", "hammer", "mfs", "ntfs", "null", "tmpfs", "ufs" };
1599 
1600 int
1601 vfs_stdac_init(struct mount *mp)
1602 {
1603 	const char* fs_type;
1604 	int i, fstype_ok = 0;
1605 
1606 	/* is mounted fs type one we want to do some accounting for ? */
1607 	for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1608 		fs_type = accounting_fstypes[i];
1609 		if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1610 					sizeof(mp->mnt_stat)) == 0) {
1611 			fstype_ok = 1;
1612 			break;
1613 		}
1614 	}
1615 	if (fstype_ok == 0)
1616 		return (0);
1617 
1618 	vq_init(mp);
1619 	return (0);
1620 }
1621 
1622 void
1623 vfs_stdac_done(struct mount *mp)
1624 {
1625 	vq_done(mp);
1626 }
1627 
1628 void
1629 vfs_stdncpgen_set(struct mount *mp, struct namecache *ncp)
1630 {
1631 }
1632 
1633 int
1634 vfs_stdncpgen_test(struct mount *mp, struct namecache *ncp)
1635 {
1636 	return 0;
1637 }
1638 
1639 int
1640 vfs_stdmodifying(struct mount *mp)
1641 {
1642 	if (mp->mnt_flag & MNT_RDONLY)
1643 		return EROFS;
1644 	return 0;
1645 }
1646 /* end of vfs default ops */
1647