mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 18:04:55 +01:00
vfs: fix deadlock in mount tests
This was caused by this sequence of calls 1> file.Release 1> file.close -> takes the file lock 2> vfs.waitforWriters 2> dir.walk -> takes the dir lock 1> file.setObject 1> dir.addObject -> attempts to take the dir lock - BLOCKS 2> file.activeWriters -> tries to take file lock - BLOCKS - DEADLOCK The fix is to make activeWriters not take the file lock and use atomic operations to read the number of writers instead.
This commit is contained in:
parent
7713acf23d
commit
a2336ad774
10
vfs/file.go
10
vfs/file.go
@ -23,6 +23,7 @@ type File struct {
|
|||||||
leaf string // leaf name of the object
|
leaf string // leaf name of the object
|
||||||
rwOpenCount int // number of open files on this handle
|
rwOpenCount int // number of open files on this handle
|
||||||
writers []Handle // writers for this file
|
writers []Handle // writers for this file
|
||||||
|
nwriters int32 // len(writers) which is read/updated with atomic
|
||||||
readWriters int // how many RWFileHandle are open for writing
|
readWriters int // how many RWFileHandle are open for writing
|
||||||
readWriterClosing bool // is a RWFileHandle currently cosing?
|
readWriterClosing bool // is a RWFileHandle currently cosing?
|
||||||
modified bool // has the cache file be modified by a RWFileHandle?
|
modified bool // has the cache file be modified by a RWFileHandle?
|
||||||
@ -103,6 +104,7 @@ func (f *File) rename(d *Dir, o fs.Object) {
|
|||||||
func (f *File) addWriter(h Handle) {
|
func (f *File) addWriter(h Handle) {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
f.writers = append(f.writers, h)
|
f.writers = append(f.writers, h)
|
||||||
|
atomic.AddInt32(&f.nwriters, 1)
|
||||||
if _, ok := h.(*RWFileHandle); ok {
|
if _, ok := h.(*RWFileHandle); ok {
|
||||||
f.readWriters++
|
f.readWriters++
|
||||||
}
|
}
|
||||||
@ -122,6 +124,7 @@ func (f *File) delWriter(h Handle, modifiedCacheFile bool) (lastWriterAndModifie
|
|||||||
}
|
}
|
||||||
if found >= 0 {
|
if found >= 0 {
|
||||||
f.writers = append(f.writers[:found], f.writers[found+1:]...)
|
f.writers = append(f.writers[:found], f.writers[found+1:]...)
|
||||||
|
atomic.AddInt32(&f.nwriters, -1)
|
||||||
} else {
|
} else {
|
||||||
fs.Debugf(f.o, "File.delWriter couldn't find handle")
|
fs.Debugf(f.o, "File.delWriter couldn't find handle")
|
||||||
}
|
}
|
||||||
@ -172,10 +175,11 @@ func (f *File) finishWriterClose() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// activeWriters returns the number of writers on the file
|
// activeWriters returns the number of writers on the file
|
||||||
|
//
|
||||||
|
// Note that we don't take the mutex here. If we do then we can get a
|
||||||
|
// deadlock.
|
||||||
func (f *File) activeWriters() int {
|
func (f *File) activeWriters() int {
|
||||||
f.mu.Lock()
|
return int(atomic.LoadInt32(&f.nwriters))
|
||||||
defer f.mu.Unlock()
|
|
||||||
return len(f.writers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModTime returns the modified time of the file
|
// ModTime returns the modified time of the file
|
||||||
|
Loading…
Reference in New Issue
Block a user