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

unionfs: don't hold lock while unmounting union FS.

parent 0eb229fd
...@@ -31,6 +31,7 @@ type autoUnionFs struct { ...@@ -31,6 +31,7 @@ type autoUnionFs struct {
debug bool debug bool
lock sync.RWMutex lock sync.RWMutex
zombies map[string]bool
knownFileSystems map[string]knownFs knownFileSystems map[string]knownFs
nameRootMap map[string]string nameRootMap map[string]string
root string root string
...@@ -73,6 +74,7 @@ func NewAutoUnionFs(directory string, options AutoUnionFsOptions) pathfs.FileSys ...@@ -73,6 +74,7 @@ func NewAutoUnionFs(directory string, options AutoUnionFsOptions) pathfs.FileSys
a := &autoUnionFs{ a := &autoUnionFs{
knownFileSystems: make(map[string]knownFs), knownFileSystems: make(map[string]knownFs),
nameRootMap: make(map[string]string), nameRootMap: make(map[string]string),
zombies: make(map[string]bool),
options: &options, options: &options,
FileSystem: pathfs.NewDefaultFileSystem(), FileSystem: pathfs.NewDefaultFileSystem(),
} }
...@@ -109,6 +111,11 @@ func (fs *autoUnionFs) createFs(name string, roots []string) fuse.Status { ...@@ -109,6 +111,11 @@ func (fs *autoUnionFs) createFs(name string, roots []string) fuse.Status {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
if fs.zombies[name] {
log.Printf("filesystem named %q is being removed", name)
return fuse.EBUSY
}
for workspace, root := range fs.nameRootMap { for workspace, root := range fs.nameRootMap {
if root == roots[0] && workspace != name { if root == roots[0] && workspace != name {
log.Printf("Already have a union FS for directory %s in workspace %s", log.Printf("Already have a union FS for directory %s in workspace %s",
...@@ -146,19 +153,30 @@ func (fs *autoUnionFs) rmFs(name string) (code fuse.Status) { ...@@ -146,19 +153,30 @@ func (fs *autoUnionFs) rmFs(name string) (code fuse.Status) {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
if fs.zombies[name] {
return fuse.ENOENT
}
known := fs.knownFileSystems[name] known := fs.knownFileSystems[name]
if known.unionFS == nil { if known.unionFS == nil {
return fuse.ENOENT return fuse.ENOENT
} }
root := fs.nameRootMap[name]
delete(fs.knownFileSystems, name)
delete(fs.nameRootMap, name)
fs.zombies[name] = true
fs.lock.Unlock()
code = fs.nodeFs.Unmount(name) code = fs.nodeFs.Unmount(name)
if code.Ok() {
delete(fs.knownFileSystems, name) fs.lock.Lock()
delete(fs.nameRootMap, name) delete(fs.zombies, name)
} else { if !code.Ok() {
// Reinstate.
log.Printf("Unmount failed for %s. Code %v", name, code) log.Printf("Unmount failed for %s. Code %v", name, code)
fs.knownFileSystems[name] = known
fs.nameRootMap[name] = root
} }
return code return code
} }
......
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