vfs: fix deadlock on concurrent operations on a directory - fixes #2811

Before this fix there were two paths where concurrent use of a
directory could take the file lock then directory lock and the other
would take the locks in the reverse order.

Fix this by narrowing the locking windows so the file lock and
directory lock don't overlap.
This commit is contained in:
Nick Craig-Wood 2018-12-03 21:51:39 +00:00
parent 5babf2dc5c
commit 13387c0838

View File

@ -331,9 +331,10 @@ func (f *File) setSize(n int64) {
// Update the object when written and add it to the directory // Update the object when written and add it to the directory
func (f *File) setObject(o fs.Object) { func (f *File) setObject(o fs.Object) {
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock()
f.o = o f.o = o
_ = f.applyPendingModTime() _ = f.applyPendingModTime()
f.mu.Unlock()
f.d.addObject(f) f.d.addObject(f)
} }
@ -440,20 +441,23 @@ func (f *File) Sync() error {
// Remove the file // Remove the file
func (f *File) Remove() error { func (f *File) Remove() error {
f.mu.Lock()
defer f.mu.Unlock()
f.muRW.Lock()
defer f.muRW.Unlock()
if f.d.vfs.Opt.ReadOnly { if f.d.vfs.Opt.ReadOnly {
return EROFS return EROFS
} }
f.mu.Lock()
f.muRW.Lock()
if f.o != nil { if f.o != nil {
err := f.o.Remove() err := f.o.Remove()
if err != nil { if err != nil {
fs.Errorf(f, "File.Remove file error: %v", err) fs.Errorf(f, "File.Remove file error: %v", err)
f.muRW.Unlock()
f.mu.Unlock()
return err return err
} }
} }
f.muRW.Unlock()
f.mu.Unlock()
// Remove the item from the directory listing // Remove the item from the directory listing
f.d.delObject(f.Name()) f.d.delObject(f.Name())
// Remove the object from the cache // Remove the object from the cache