vfs: fix deadlock caused by cache cleaner and upload finishing

Before this patch a deadlock could occur if the cache cleaner was
running when an object upload finished.

This fixes the problem by delaying marking the object as clean until
we have notified the VFS layer. This means that the cache cleaner
won't consider the object until **after** the VFS layer has been
notified, thus avoiding the deadlock.

See: https://forum.rclone.org/t/rclone-mount-deadlock-when-dir-cache-time-strikes/33486/
This commit is contained in:
Nick Craig-Wood 2022-10-17 16:46:59 +01:00
parent b4a3d1b9ed
commit 591fc3609a

View File

@ -606,20 +606,25 @@ func (item *Item) _store(ctx context.Context, storeFn StoreFn) (err error) {
item._updateFingerprint()
}
item.info.Dirty = false
err = item._save()
if err != nil {
fs.Errorf(item.name, "vfs cache: failed to write metadata file: %v", err)
}
// Write the object back to the VFS layer before we mark it as
// clean, otherwise it will become eligible for removal which
// can cause a deadlock
if storeFn != nil && item.o != nil {
fs.Debugf(item.name, "vfs cache: writeback object to VFS layer")
// Write the object back to the VFS layer as last
// thing we do with mutex unlocked
// Write the object back to the VFS layer last with mutex unlocked
o := item.o
item.mu.Unlock()
storeFn(o)
item.mu.Lock()
}
// Show item is clean and is elegible for cache removal
item.info.Dirty = false
err = item._save()
if err != nil {
fs.Errorf(item.name, "vfs cache: failed to write metadata file: %v", err)
}
return nil
}