From 2f438a99cd9f7a7bba329185d1e258c249df3762 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 20 Aug 2014 13:46:51 +0000 Subject: [PATCH] Rework ".." lookup; previous one failed to properly busy the mountpoint. Reviewed by: kib@ MFC after: 2 weeks Sponsored by: The FreeBSD Foundation --- sys/fs/autofs/autofs_vnops.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c index 7623145e63c..72e8b810bc9 100644 --- a/sys/fs/autofs/autofs_vnops.c +++ b/sys/fs/autofs/autofs_vnops.c @@ -197,6 +197,15 @@ mounted: return (0); } +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) { @@ -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); }