Commit d2f8777d authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Handle umount busy check using per-node open counts.

parent 0ffb4617
...@@ -18,16 +18,8 @@ type mountData struct { ...@@ -18,16 +18,8 @@ type mountData struct {
// If yes, we are looking to unmount the mounted fs. // If yes, we are looking to unmount the mounted fs.
unmountPending bool unmountPending bool
// Count files, dirs and mounts.
openCount int
} }
func (me *mountData) incOpenCount(delta int) {
me.mutex.Lock()
defer me.mutex.Unlock()
me.openCount += delta
}
func newMount(fs PathFilesystem) *mountData { func newMount(fs PathFilesystem) *mountData {
return &mountData{fs: fs} return &mountData{fs: fs}
...@@ -49,6 +41,16 @@ type inode struct { ...@@ -49,6 +41,16 @@ type inode struct {
mount *mountData mount *mountData
} }
// Should be called with lock held.
func (me *inode) totalOpenCount() int {
o := me.OpenCount
for _, v := range me.Children {
o += v.totalOpenCount()
}
return o
}
const initDirSize = 20 const initDirSize = 20
func (me *inode) verify() { func (me *inode) verify() {
...@@ -359,15 +361,20 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S ...@@ -359,15 +361,20 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S
} }
node = me.findInode(mountPoint) node = me.findInode(mountPoint)
// TODO - check that fs was not mounted elsewhere.
if len(node.Children) > 0 {
return EBUSY
}
if node.Type&ModeToType(S_IFDIR) == 0 { if node.Type&ModeToType(S_IFDIR) == 0 {
return EINVAL return EINVAL
} }
me.lock.Lock()
hasChildren := len(node.Children) > 0
// don't use defer, as we dont want to hold the lock during
// fs.Mount().
me.lock.Unlock()
if hasChildren {
return EBUSY
}
code := fs.Mount(me) code := fs.Mount(me)
if code != OK { if code != OK {
if me.Debug { if me.Debug {
...@@ -381,9 +388,11 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S ...@@ -381,9 +388,11 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S
} }
node.mount = newMount(fs) node.mount = newMount(fs)
me.fileLock.Lock()
defer me.fileLock.Unlock()
if node.Parent != nil { if node.Parent != nil {
_, parentMount := node.Parent.GetPath() node.Parent.OpenCount++
parentMount.incOpenCount(1)
} }
return OK return OK
...@@ -400,9 +409,14 @@ func (me *PathFileSystemConnector) Unmount(path string) Status { ...@@ -400,9 +409,14 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
panic(path) panic(path)
} }
mount.mutex.Lock() // Need to lock to look at node.Children
defer mount.mutex.Unlock() me.lock.RLock()
if mount.openCount > 0 { defer me.lock.RUnlock()
me.fileLock.Lock()
defer me.fileLock.Unlock()
if node.totalOpenCount() > 0 {
log.Println("Umount - busy: ", mount) log.Println("Umount - busy: ", mount)
return EBUSY return EBUSY
} }
...@@ -411,6 +425,8 @@ func (me *PathFileSystemConnector) Unmount(path string) Status { ...@@ -411,6 +425,8 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
log.Println("Unmount: ", mount) log.Println("Unmount: ", mount)
} }
mount.mutex.Lock()
defer mount.mutex.Unlock()
if len(node.Children) > 0 { if len(node.Children) > 0 {
mount.fs.Unmount() mount.fs.Unmount()
mount.unmountPending = true mount.unmountPending = true
...@@ -419,8 +435,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status { ...@@ -419,8 +435,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
} }
if node.Parent != nil { if node.Parent != nil {
_, parentMount := node.Parent.GetPath() node.Parent.OpenCount--
parentMount.incOpenCount(-1)
} }
return OK return OK
} }
...@@ -519,8 +534,6 @@ func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (fla ...@@ -519,8 +534,6 @@ func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (fla
return 0, 0, err return 0, 0, err
} }
mount.incOpenCount(1)
de := new(FuseDir) de := new(FuseDir)
de.stream = stream de.stream = stream
...@@ -551,7 +564,6 @@ func (me *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flags ...@@ -551,7 +564,6 @@ func (me *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flags
} }
h := me.registerFile(node, f) h := me.registerFile(node, f)
mount.incOpenCount(1)
return 0, h, OK return 0, h, OK
} }
...@@ -731,24 +743,17 @@ func (me *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, nam ...@@ -731,24 +743,17 @@ func (me *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, nam
} }
out, code, inode := me.internalLookupWithNode(parent, name, 1) out, code, inode := me.internalLookupWithNode(parent, name, 1)
mount.incOpenCount(1)
return 0, me.registerFile(inode, f), out, code return 0, me.registerFile(inode, f), out, code
} }
func (me *PathFileSystemConnector) Release(header *InHeader, input *ReleaseIn) { func (me *PathFileSystemConnector) Release(header *InHeader, input *ReleaseIn) {
_, mount, node := me.GetPath(header.NodeId) _, _, node := me.GetPath(header.NodeId)
f := me.unregisterFile(node, input.Fh).(RawFuseFile) f := me.unregisterFile(node, input.Fh).(RawFuseFile)
f.Release() f.Release()
if mount != nil {
mount.incOpenCount(-1)
}
} }
func (me *PathFileSystemConnector) ReleaseDir(header *InHeader, input *ReleaseIn) { func (me *PathFileSystemConnector) ReleaseDir(header *InHeader, input *ReleaseIn) {
_, mount, node := me.GetPath(header.NodeId) _, _, node := me.GetPath(header.NodeId)
if mount != nil {
mount.incOpenCount(-1)
}
d := me.unregisterFile(node, input.Fh).(RawFuseDir) d := me.unregisterFile(node, input.Fh).(RawFuseDir)
d.Release() d.Release()
} }
......
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