2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed
6 * to Berkeley by John Heidemann of the UCLA Ficus project.
8 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
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.35 2006/04/30 17:22:17 dillon Exp $
43 #include <sys/param.h>
44 #include <sys/systm.h>
47 #include <sys/fcntl.h>
49 #include <sys/kernel.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>
58 #include <sys/mountctl.h>
60 #include <machine/limits.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>
68 static int vop_nolookup (struct vop_old_lookup_args *);
69 static int vop_nostrategy (struct vop_strategy_args *);
72 * This vnode table stores what we want to do if the filesystem doesn't
73 * implement a particular VOP.
75 * If there is no specific entry here, we will return EOPNOTSUPP.
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 },
117 static struct vnodeopv_desc default_vnodeop_opv_desc =
118 { &default_vnode_vops, default_vnodeop_entries, 0 };
120 VNODEOP_SET(default_vnodeop_opv_desc);
123 vop_eopnotsupp(struct vop_generic_args *ap)
129 vop_ebadf(struct vop_generic_args *ap)
135 vop_enotty(struct vop_generic_args *ap)
141 vop_einval(struct vop_generic_args *ap)
147 vop_null(struct vop_generic_args *ap)
153 vop_defaultop(struct vop_generic_args *ap)
155 return (VOCALL(default_vnode_vops, ap));
159 vop_panic(struct vop_generic_args *ap)
162 panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
166 * vop_compat_resolve { struct namecache *a_ncp } XXX STOPGAP FUNCTION
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.
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
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.
185 * The ncp will NEVER represent "", "." or "..", or contain any slashes.
187 * There is a potential directory and vnode interlock. The lock order
188 * requirement is: namecache, governing directory, resolved vnode.
191 vop_compat_nresolve(struct vop_nresolve_args *ap)
196 struct namecache *ncp;
197 struct componentname cnp;
199 ncp = ap->a_ncp; /* locked namecache node */
200 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
202 if (ncp->nc_parent == NULL)
204 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
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.
212 if ((error = vget(dvp, LK_EXCLUSIVE, curthread)) != 0) {
213 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
218 bzero(&cnp, sizeof(cnp));
219 cnp.cn_nameiop = NAMEI_LOOKUP;
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 */
227 * vop_old_lookup() always returns vp locked. dvp may or may not be
228 * left locked depending on CNP_PDIRUNLOCK.
230 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
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 */
239 } else if (error == 0) {
240 KKASSERT(vp != NULL);
241 cache_setvp(ncp, 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);
254 * vop_compat_nlookupdotdot { struct vnode *a_dvp,
255 * struct vnode **a_vpp,
256 * struct ucred *a_cred }
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.
262 * This function is designed to aid NFS server-side operations and is
263 * used by cache_fromdvp() to create a consistent, connected namecache
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.
272 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
274 struct componentname cnp;
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.
283 if ((error = vget(ap->a_dvp, LK_EXCLUSIVE, curthread)) != 0)
285 if (ap->a_dvp->v_type != VDIR) {
290 bzero(&cnp, sizeof(cnp));
291 cnp.cn_nameiop = NAMEI_LOOKUP;
292 cnp.cn_flags = CNP_ISDOTDOT;
293 cnp.cn_nameptr = "..";
295 cnp.cn_cred = ap->a_cred;
296 cnp.cn_td = curthread; /* XXX */
299 * vop_old_lookup() always returns vp locked. dvp may or may not be
300 * left locked depending on CNP_PDIRUNLOCK.
302 error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
304 VOP_UNLOCK(*ap->a_vpp, 0, curthread);
305 if (cnp.cn_flags & CNP_PDIRUNLOCK)
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 }
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).
323 vop_compat_ncreate(struct vop_ncreate_args *ap)
325 struct thread *td = curthread;
326 struct componentname cnp;
327 struct namecache *ncp;
332 * Sanity checks, get a locked directory vnode.
334 ncp = ap->a_ncp; /* locked namecache node */
335 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
337 if (ncp->nc_parent == NULL)
339 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
342 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
343 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
363 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
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.
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.
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);
377 cache_setunresolved(ncp);
378 cache_setvp(ncp, *ap->a_vpp);
386 KKASSERT(*ap->a_vpp == NULL);
388 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
389 VOP_UNLOCK(dvp, 0, td);
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 }
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).
405 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
407 struct thread *td = curthread;
408 struct componentname cnp;
409 struct namecache *ncp;
414 * Sanity checks, get a locked directory vnode.
416 ncp = ap->a_ncp; /* locked namecache node */
417 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
419 if (ncp->nc_parent == NULL)
421 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
424 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
425 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
445 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
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.
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.
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);
459 cache_setunresolved(ncp);
460 cache_setvp(ncp, *ap->a_vpp);
468 KKASSERT(*ap->a_vpp == NULL);
470 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
471 VOP_UNLOCK(dvp, 0, td);
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 }
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).
487 vop_compat_nmknod(struct vop_nmknod_args *ap)
489 struct thread *td = curthread;
490 struct componentname cnp;
491 struct namecache *ncp;
496 * Sanity checks, get a locked directory vnode.
498 ncp = ap->a_ncp; /* locked namecache node */
499 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
501 if (ncp->nc_parent == NULL)
503 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
506 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
507 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
527 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
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.
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.
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);
541 cache_setunresolved(ncp);
542 cache_setvp(ncp, *ap->a_vpp);
550 KKASSERT(*ap->a_vpp == NULL);
552 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
553 VOP_UNLOCK(dvp, 0, td);
559 * vop_compat_nlink { struct namecache *a_ncp, XXX STOPGAP FUNCTION
560 * struct vnode *a_vp,
561 * struct ucred *a_cred }
563 * The passed vp is locked and represents the source. The passed ncp is
564 * locked and represents the target to create.
567 vop_compat_nlink(struct vop_nlink_args *ap)
569 struct thread *td = curthread;
570 struct componentname cnp;
571 struct namecache *ncp;
577 * Sanity checks, get a locked directory vnode.
579 ncp = ap->a_ncp; /* locked namecache node */
580 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
582 if (ncp->nc_parent == NULL)
584 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
587 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
588 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
608 error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
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.
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.
618 if (error == EJUSTRETURN) {
619 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
620 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
622 cache_setunresolved(ncp);
623 cache_setvp(ncp, ap->a_vp);
631 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
632 VOP_UNLOCK(dvp, 0, td);
638 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
640 struct thread *td = curthread;
641 struct componentname cnp;
642 struct namecache *ncp;
648 * Sanity checks, get a locked directory vnode.
651 ncp = ap->a_ncp; /* locked namecache node */
652 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
654 if (ncp->nc_parent == NULL)
656 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
659 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
660 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
680 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
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.
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.
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);
694 cache_setunresolved(ncp);
695 cache_setvp(ncp, vp);
704 KKASSERT(vp == NULL);
706 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
707 VOP_UNLOCK(dvp, 0, td);
713 * vop_compat_nwhiteout { struct namecache *a_ncp, XXX STOPGAP FUNCTION
714 * struct ucred *a_cred,
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.
724 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
726 struct thread *td = curthread;
727 struct componentname cnp;
728 struct namecache *ncp;
734 * Sanity checks, get a locked directory vnode.
736 ncp = ap->a_ncp; /* locked namecache node */
737 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
739 if (ncp->nc_parent == NULL)
741 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
744 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
745 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
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.
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.
774 switch(ap->a_flags) {
776 cnp.cn_flags |= CNP_DOWHITEOUT;
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);
784 cache_setunresolved(ncp);
791 KKASSERT(vp == NULL);
795 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
801 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
802 VOP_UNLOCK(dvp, 0, td);
809 * vop_compat_nremove { struct namecache *a_ncp, XXX STOPGAP FUNCTION
810 * struct ucred *a_cred }
813 vop_compat_nremove(struct vop_nremove_args *ap)
815 struct thread *td = curthread;
816 struct componentname cnp;
817 struct namecache *ncp;
823 * Sanity checks, get a locked directory vnode.
825 ncp = ap->a_ncp; /* locked namecache node */
826 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
828 if (ncp->nc_parent == NULL)
830 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
833 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
834 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
855 * The vnode must be a directory and must not represent the
859 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
860 if (error == 0 && vp->v_type == VDIR)
863 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
864 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
866 cache_setunresolved(ncp);
867 cache_setvp(ncp, NULL);
876 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
877 VOP_UNLOCK(dvp, 0, td);
883 * vop_compat_nrmdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION
884 * struct ucred *a_cred }
887 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
889 struct thread *td = curthread;
890 struct componentname cnp;
891 struct namecache *ncp;
897 * Sanity checks, get a locked directory vnode.
899 ncp = ap->a_ncp; /* locked namecache node */
900 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
902 if (ncp->nc_parent == NULL)
904 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
907 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
908 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
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.
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;
929 * The vnode must be a directory and must not represent the
933 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
934 if (error == 0 && vp->v_type != VDIR)
936 if (error == 0 && vp == dvp)
938 if (error == 0 && (vp->v_flag & VROOT))
941 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
942 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
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 ".."
951 cache_inval(ncp, CINV_DESTROY);
959 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
960 VOP_UNLOCK(dvp, 0, td);
966 * vop_compat_nrename { struct namecache *a_fncp, XXX STOPGAP FUNCTION
967 * struct namecache *a_tncp,
968 * struct ucred *a_cred }
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.
976 vop_compat_nrename(struct vop_nrename_args *ap)
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;
988 * Sanity checks, get referenced vnodes representing the source.
990 fncp = ap->a_fncp; /* locked namecache node */
991 if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
993 if (fncp->nc_parent == NULL)
995 if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
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.
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);
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;
1023 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
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 */
1032 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1033 fcnp.cn_flags |= CNP_PDIRUNLOCK;
1034 VOP_UNLOCK(fdvp, 0, td);
1040 VOP_UNLOCK(fvp, 0, td);
1043 * fdvp and fvp are now referenced and unlocked.
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
1049 tncp = ap->a_tncp; /* locked namecache node */
1050 if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
1052 if (tncp->nc_parent == NULL)
1054 if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
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);
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.
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;
1083 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
1085 if (error == EJUSTRETURN) {
1087 * Target does not exist. tvp should be NULL.
1089 KKASSERT(tvp == NULL);
1090 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1091 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1093 cache_rename(fncp, tncp);
1094 cache_setvp(tncp, fvp);
1096 } else if (error == 0) {
1098 * Target exists. VOP_OLD_RENAME should correctly delete the
1101 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1102 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1104 cache_rename(fncp, tncp);
1105 cache_setvp(tncp, fvp);
1110 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1120 struct vop_old_lookup_args /* {
1121 struct vnode *a_dvp;
1122 struct vnode **a_vpp;
1123 struct componentname *a_cnp;
1134 * Strategy routine for VFS devices that have none.
1136 * B_ERROR and B_INVAL must be cleared prior to calling any strategy
1137 * routine. Typically this is done for a BUF_CMD_READ strategy call.
1138 * Typically B_INVAL is assumed to already be clear prior to a write
1139 * and should not be cleared manually unless you just made the buffer
1140 * invalid. B_ERROR should be cleared either way.
1144 vop_nostrategy (struct vop_strategy_args *ap)
1146 printf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
1147 vprint("", ap->a_vp);
1148 ap->a_bio->bio_buf->b_flags |= B_ERROR;
1149 ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1151 return (EOPNOTSUPP);
1156 struct vop_pathconf_args /* {
1163 switch (ap->a_name) {
1165 *ap->a_retval = LINK_MAX;
1168 *ap->a_retval = MAX_CANON;
1171 *ap->a_retval = MAX_INPUT;
1174 *ap->a_retval = PIPE_BUF;
1176 case _PC_CHOWN_RESTRICTED:
1180 *ap->a_retval = _POSIX_VDISABLE;
1191 * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp,
1192 * struct thread *a_td)
1194 * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1197 vop_stdopen(struct vop_open_args *ap)
1199 struct vnode *vp = ap->a_vp;
1202 if ((fp = ap->a_fp) != NULL) {
1203 switch(vp->v_type) {
1205 fp->f_type = DTYPE_FIFO;
1208 fp->f_type = DTYPE_VNODE;
1211 fp->f_flag = ap->a_mode & FMASK;
1212 fp->f_ops = &vnode_fileops;
1216 if (ap->a_mode & FWRITE)
1218 KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1226 * (struct vnode *a_vp, int a_fflag, struct thread *a_td)
1228 * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE. same as a_mode in stdopen?
1231 vop_stdclose(struct vop_close_args *ap)
1233 struct vnode *vp = ap->a_vp;
1235 KASSERT(vp->v_opencount > 0,
1236 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d\n", vp, vp->v_opencount));
1237 if (ap->a_fflag & FWRITE) {
1238 KASSERT(vp->v_writecount > 0,
1239 ("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n",
1240 vp, vp->v_writecount));
1248 * Standard lock. The lock is recursive-capable only if the lock was
1249 * initialized with LK_CANRECURSE or that flag is passed in a_flags.
1253 struct vop_lock_args /* {
1262 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags, ap->a_td);
1264 error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags, ap->a_td,
1265 "vop_stdlock", ap->a_vp->filename, ap->a_vp->line);
1272 struct vop_unlock_args /* {
1275 struct thread *a_td;
1280 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE, ap->a_td);
1286 struct vop_islocked_args /* {
1288 struct thread *a_td;
1291 return (lockstatus(&ap->a_vp->v_lock, ap->a_td));
1295 * Return true for select/poll.
1299 struct vop_poll_args /* {
1302 struct ucred *a_cred;
1307 * Return true for read/write. If the user asked for something
1308 * special, return POLLNVAL, so that clients have a way of
1309 * determining reliably whether or not the extended
1310 * functionality is present without hard-coding knowledge
1311 * of specific filesystem implementations.
1313 if (ap->a_events & ~POLLSTANDARD)
1316 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1320 * Implement poll for local filesystems that support it.
1324 struct vop_poll_args /* {
1327 struct ucred *a_cred;
1328 struct thread *a_td;
1331 if (ap->a_events & ~POLLSTANDARD)
1332 return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
1333 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1338 struct vop_bwrite_args *ap;
1340 return (bwrite(ap->a_bp));
1345 * used to fill the vfs fucntion table to get reasonable default return values.
1348 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct thread *td)
1354 vfs_stdunmount(struct mount *mp, int mntflags, struct thread *td)
1360 vfs_stdroot(struct mount *mp, struct vnode **vpp)
1362 return (EOPNOTSUPP);
1366 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct thread *td)
1368 return (EOPNOTSUPP);
1372 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
1374 return (EOPNOTSUPP);
1378 vfs_stdstart(struct mount *mp, int flags, struct thread *td)
1384 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1385 caddr_t arg, struct thread *td)
1387 return (EOPNOTSUPP);
1391 vfs_stdsync(struct mount *mp, int waitfor, struct thread *td)
1397 vfs_stdnosync(struct mount *mp, int waitfor, struct thread *td)
1399 return (EOPNOTSUPP);
1403 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
1405 return (EOPNOTSUPP);
1409 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1411 return (EOPNOTSUPP);
1415 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1416 struct ucred **credanonp)
1418 return (EOPNOTSUPP);
1422 vfs_stdinit(struct vfsconf *vfsp)
1428 vfs_stduninit(struct vfsconf *vfsp)
1434 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1435 caddr_t arg, struct thread *td)
1440 /* end of vfs default ops */