Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 May 2019 17:27:05 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r346998 - projects/fuse2/sys/fs/fuse
Message-ID:  <201905011727.x41HR53t033667@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Wed May  1 17:27:04 2019
New Revision: 346998
URL: https://svnweb.freebsd.org/changeset/base/346998

Log:
  fusefs: fix "returning with lock held" panics in fuse_vnode_alloc
  
  These panics all lie in the error path.  The only one I've hit is caused by
  a buggy FUSE server unexpectedly changing the type of a vnode.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_node.c

Modified: projects/fuse2/sys/fs/fuse/fuse_node.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_node.c	Wed May  1 17:24:53 2019	(r346997)
+++ projects/fuse2/sys/fs/fuse/fuse_node.c	Wed May  1 17:27:04 2019	(r346998)
@@ -212,6 +212,7 @@ fuse_vnode_hash(uint64_t id)
 	return (fnv_32_buf(&id, sizeof(id), FNV1_32_INIT));
 }
 
+SDT_PROBE_DEFINE2(fusefs, , node, stale_vnode, "struct vnode*", "enum vtype");
 static int
 fuse_vnode_alloc(struct mount *mp,
     struct thread *td,
@@ -240,7 +241,10 @@ fuse_vnode_alloc(struct mount *mp,
 			 * between FUSE_LOOKUP and another client's
 			 * FUSE_UNLINK/FUSE_CREATE
 			 */
+			SDT_PROBE2(fusefs, , node, stale_vnode, *vpp, vtyp);
 			fuse_internal_vnode_disappear(*vpp);
+			lockmgr((*vpp)->v_vnlock, LK_RELEASE, NULL);
+			*vpp = NULL;
 			return (EAGAIN);
 		}
 		MPASS((*vpp)->v_data != NULL);
@@ -265,14 +269,19 @@ fuse_vnode_alloc(struct mount *mp,
 	err = insmntque(*vpp, mp);
 	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnode_alloc");
 	if (err) {
+		lockmgr((*vpp)->v_vnlock, LK_RELEASE, NULL);
 		free(fvdat, M_FUSEVN);
 		*vpp = NULL;
 		return (err);
 	}
 	err = vfs_hash_insert(*vpp, fuse_vnode_hash(nodeid), LK_EXCLUSIVE,
 	    td, &vp2, fuse_vnode_cmp, &nodeid);
-	if (err)
+	if (err) {
+		lockmgr((*vpp)->v_vnlock, LK_RELEASE, NULL);
+		free(fvdat, M_FUSEVN);
+		*vpp = NULL;
 		return (err);
+	}
 	if (vp2 != NULL) {
 		*vpp = vp2;
 		return (0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905011727.x41HR53t033667>