diff options
author | pjd <pjd@FreeBSD.org> | 2007-06-04 11:31:46 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2007-06-04 11:31:46 +0000 |
commit | f28297d01f737f3ca830b4161abd767edf0db5a3 (patch) | |
tree | 85e5e71c843675bef6135727cc87842e0b0eaa9e /sys/cddl/compat/opensolaris/kern | |
parent | e40209916cb59e0b7779db19d3699c409aa9f780 (diff) | |
download | FreeBSD-src-f28297d01f737f3ca830b4161abd767edf0db5a3.zip FreeBSD-src-f28297d01f737f3ca830b4161abd767edf0db5a3.tar.gz |
Reimplement traverse() helper function:
1. Pass locking flags to VFS_ROOT().
2. Check v_mountedhere while the vnode is locked.
3. Always return locked vnode on success.
Change 1 fixes problem reported by Stephen M. Rumble - after
zfs_vfsops.c,1.9 change, zfs_root() no longer locks the vnode
unconditionally and traverse() didn't pass right lock type to
VFS_ROOT(). The result was that kernel paniced when .zfs/ directory
was accessed via NFS.
Diffstat (limited to 'sys/cddl/compat/opensolaris/kern')
-rw-r--r-- | sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c index e3325ae..79a4c5b 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c @@ -110,7 +110,7 @@ vfs_optionisset(const vfs_t *vfsp, const char *opt, char **argp) } int -traverse(vnode_t **cvpp) +traverse(vnode_t **cvpp, int lktype) { kthread_t *td = curthread; vnode_t *cvp; @@ -119,7 +119,7 @@ traverse(vnode_t **cvpp) int error; cvp = *cvpp; - error = 0; + tvp = NULL; /* * If this vnode is mounted on, then we transparently indirect @@ -135,22 +135,26 @@ traverse(vnode_t **cvpp) vfsp = vn_mountedvfs(cvp); if (vfsp == NULL) break; - VN_RELE(cvp); + /* + * tvp is NULL for *cvpp vnode, which we can't unlock. + */ + if (tvp != NULL) + vput(cvp); + else + vrele(cvp); /* * The read lock must be held across the call to VFS_ROOT() to * prevent a concurrent unmount from destroying the vfs. */ - error = VFS_ROOT(vfsp, 0, &tvp, td); - if (error) - break; - VOP_UNLOCK(tvp, 0, td); - + error = VFS_ROOT(vfsp, lktype, &tvp, td); + if (error != 0) + return (error); cvp = tvp; } *cvpp = cvp; - return (error); + return (0); } int |