From 4ffe9dcfef5557e536f9fc094370a408c11f6359 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 17 Oct 2022 16:46:59 +0100 Subject: [PATCH] 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/ --- vfs/vfscache/item.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/vfs/vfscache/item.go b/vfs/vfscache/item.go index b7f40252d..ed05c6710 100644 --- a/vfs/vfscache/item.go +++ b/vfs/vfscache/item.go @@ -590,20 +590,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 }