diff --git a/fuse/fsconnector.go b/fuse/fsconnector.go
index a92bc063ff551549d40b49ca85a045ca2f18e303..6b77fb74526c9459891c40718b80e0495802b929 100644
--- a/fuse/fsconnector.go
+++ b/fuse/fsconnector.go
@@ -121,9 +121,10 @@ func (c *FileSystemConnector) lookupUpdate(node *Inode) uint64 {
 		node.nodeId = c.inodeMap.Register(&node.handled, node)
 	}
 	node.lookupCount += 1
+	id := node.nodeId
 	node.treeLock.Unlock()
 
-	return node.nodeId
+	return id
 }
 
 // Must run outside treeLock.
@@ -294,6 +295,7 @@ func (c *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFileS
 //
 // EBUSY: there are open files, or submounts below this node.
 func (c *FileSystemConnector) Unmount(node *Inode) Status {
+	// TODO - racy.
 	if node.mountPoint == nil {
 		log.Println("not a mountpoint:", node.nodeId)
 		return EINVAL
@@ -324,13 +326,14 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
 	delete(parentNode.children, name)
 	mount.fs.OnUnmount()
 
-	c.DeleteNotify(parentNode, mountInode, name)
-
+	c.fsInit.DeleteNotify(parentNode.nodeId, mountInode.nodeId, name)
 	return OK
 }
 
 func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) Status {
+	node.treeLock.RLock()
 	n := node.nodeId
+	node.treeLock.RUnlock()
 	if node == c.rootNode {
 		n = raw.FUSE_ROOT_ID
 	}
@@ -346,7 +349,9 @@ func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) S
 }
 
 func (c *FileSystemConnector) EntryNotify(dir *Inode, name string) Status {
+	dir.treeLock.RLock()
 	n := dir.nodeId
+	dir.treeLock.RUnlock()
 	if dir == c.rootNode {
 		n = raw.FUSE_ROOT_ID
 	}
@@ -357,12 +362,22 @@ func (c *FileSystemConnector) EntryNotify(dir *Inode, name string) Status {
 }
 
 func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string) Status {
+	dir.treeLock.RLock()
 	n := dir.nodeId
+	var chId uint64
+	if child.treeLock != dir.treeLock {
+		child.treeLock.RLock()
+		chId = child.nodeId
+		child.treeLock.RUnlock()
+	}
+	
+	dir.treeLock.RUnlock()
+	
 	if dir == c.rootNode {
 		n = raw.FUSE_ROOT_ID
 	}
 	if n == 0 {
 		return OK
 	}
-	return c.fsInit.DeleteNotify(n, child.nodeId, name)
+	return c.fsInit.DeleteNotify(n, chId, name)
 }
diff --git a/fuse/inode.go b/fuse/inode.go
index 925ee42efb27a8806a861f526f4bedaee2fcbc36..b595c22b7e6af2822d8d082da7ddd5fe144fb728 100644
--- a/fuse/inode.go
+++ b/fuse/inode.go
@@ -41,8 +41,8 @@ type Inode struct {
 
 	// The nodeId is only used to communicate to the kernel.  If
 	// it is zero, it means the kernel does not know about this
-	// Inode.  You should probably never read nodeId, but always
-	// do lookupUpdate() on the node instead.
+	// Inode.  Only forget/lookup/notify methods should nodeId
+	// directly.
 	nodeId uint64
 
 	// lookupCount registers how often the kernel got this inode
diff --git a/fuse/mount_test.go b/fuse/mount_test.go
index 0f54e04eda3811f2a9f8f38e448807240b337c3b..c5df3a6334b38bd0c6337e69168ec366c41b0fa4 100644
--- a/fuse/mount_test.go
+++ b/fuse/mount_test.go
@@ -27,7 +27,10 @@ func TestMountOnExisting(t *testing.T) {
 		t.Fatal("expect OK:", code)
 	}
 
-	ts.pathFs.Unmount("mnt")
+	code = ts.pathFs.Unmount("mnt")
+	if !code.Ok() {
+		t.Errorf("Unmount failed: %v", code)
+	}
 }
 
 func TestMountRename(t *testing.T) {
diff --git a/fuse/mountstate.go b/fuse/mountstate.go
index 1a5b6ad93547f0819cf33c8641c515f3e22961c8..951e6d18b7e2dbaeb730c3d269e7ae974875e557 100644
--- a/fuse/mountstate.go
+++ b/fuse/mountstate.go
@@ -153,7 +153,8 @@ func (ms *MountState) Unmount() (err error) {
 		if err == nil {
 			break
 		}
-
+		
+		fmt.Fprintf(os.Stderr, "umount failed; retrying\n")
 		// Sleep for a bit. This is not pretty, but there is
 		// no way we can be certain that the kernel thinks all
 		// open files have already been closed.