Commit 33fc3c76 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Synchronize nodeId access in notify functions.

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