Commit 84301c8f authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

fuse: fix race condition in unmount.

parent 44a49fb5
...@@ -296,6 +296,8 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -296,6 +296,8 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
return EINVAL return EINVAL
} }
nodeId := c.inodeMap.Handle(&node.handled)
// Must lock parent to update tree structure. // Must lock parent to update tree structure.
parentNode := node.mountPoint.parentInode parentNode := node.mountPoint.parentInode
parentNode.mount.treeLock.Lock() parentNode.mount.treeLock.Lock()
...@@ -320,10 +322,6 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -320,10 +322,6 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
return EBUSY return EBUSY
} }
mount.mountInode = nil
// TODO - racy.
node.mountPoint = nil
delete(parentNode.children, name) delete(parentNode.children, name)
mount.fs.OnUnmount() mount.fs.OnUnmount()
...@@ -333,7 +331,30 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status { ...@@ -333,7 +331,30 @@ func (c *FileSystemConnector) Unmount(node *Inode) Status {
parentId = raw.FUSE_ROOT_ID parentId = raw.FUSE_ROOT_ID
} }
c.fsInit.DeleteNotify(parentId, c.inodeMap.Handle(&node.handled), name) // We have to wait until the kernel has forgotten the
// mountpoint, so the write to node.mountPoint is no longer
// racy.
code := c.fsInit.DeleteNotify(parentId, c.inodeMap.Handle(&node.handled), name)
if code.Ok() {
mount.treeLock.Unlock()
parentNode.mount.treeLock.Unlock()
delay := 100 * time.Microsecond
for {
// This operation is rare, so we kludge it to avoid
// contention.
time.Sleep(delay)
delay = delay * 2 + 1
if !c.inodeMap.Has(nodeId) {
break
}
}
parentNode.mount.treeLock.Lock()
mount.treeLock.Lock()
}
mount.mountInode = nil
node.mountPoint = nil
return OK return OK
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment