summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2014-08-31 21:43:28 +0000
committertrasz <trasz@FreeBSD.org>2014-08-31 21:43:28 +0000
commit35b129889128246a6ef814aea59a301fa5d4ac8d (patch)
treeaa007e8771db2819814614d858c428dd14dd8c93 /sys/fs
parente8d76f86d25e64bdb4a9ab0b15c509c07491724a (diff)
downloadFreeBSD-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.c32
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);
}
OpenPOWER on IntegriCloud