diff options
author | trasz <trasz@FreeBSD.org> | 2014-08-31 21:43:28 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2014-08-31 21:43:28 +0000 |
commit | 35b129889128246a6ef814aea59a301fa5d4ac8d (patch) | |
tree | aa007e8771db2819814614d858c428dd14dd8c93 /sys/fs | |
parent | e8d76f86d25e64bdb4a9ab0b15c509c07491724a (diff) | |
download | FreeBSD-src-35b129889128246a6ef814aea59a301fa5d4ac8d.zip FreeBSD-src-35b129889128246a6ef814aea59a301fa5d4ac8d.tar.gz |
MFC r270207:
Rework ".." lookup; previous one failed to properly busy the mountpoint.
Reviewed by: kib@
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/autofs/autofs_vnops.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c index 7623145..72e8b81 100644 --- a/sys/fs/autofs/autofs_vnops.c +++ b/sys/fs/autofs/autofs_vnops.c @@ -198,6 +198,15 @@ mounted: } static int +autofs_vget_callback(struct mount *mp, void *arg, int lkflags __unused, + struct vnode **vpp) +{ + + + return (autofs_node_vn(arg, mp, vpp)); +} + +static int autofs_lookup(struct vop_lookup_args *ap) { struct vnode *dvp, *newvp, **vpp; @@ -217,24 +226,19 @@ autofs_lookup(struct vop_lookup_args *ap) if (cnp->cn_flags & ISDOTDOT) { KASSERT(anp->an_parent != NULL, ("NULL parent")); /* - * Note that in this case, dvp is the child vnode, and we are - * looking up the parent vnode - exactly reverse from normal - * operation. To preserve lock order, we unlock the child - * (dvp), obtain the lock on parent (*vpp) in autofs_node_vn(), - * then relock the child. We use vhold()/vdrop() to prevent - * dvp from being freed in the meantime. + * Note that in this case, dvp is the child vnode, and we + * are looking up the parent vnode - exactly reverse from + * normal operation. Unlocking dvp requires some rather + * tricky unlock/relock dance to prevent mp from being freed; + * use vn_vget_ino_gen() which takes care of all that. */ - lock_flags = VOP_ISLOCKED(dvp); - vhold(dvp); - VOP_UNLOCK(dvp, 0); - error = autofs_node_vn(anp->an_parent, mp, vpp); + error = vn_vget_ino_gen(dvp, autofs_vget_callback, + anp->an_parent, 0, vpp); if (error != 0) { - AUTOFS_WARN("autofs_node_vn() failed with error %d", + AUTOFS_WARN("vn_vget_ino_gen() failed with error %d", error); + return (error); } - vn_lock(dvp, lock_flags | LK_RETRY); - vdrop(dvp); - return (error); } |