From fbe02294e50c04095612f57bf4047713a939d030 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Mon, 16 Dec 2024 13:12:21 +0100 Subject: [PATCH] mfs: clean directory cache on flush Flushing represents a sort of "I'm done" with the folder. It is less likely that old references to the folder are used after it has been flushed. As such, we take the chance to clean up the cache then. --- CHANGELOG.md | 2 +- mfs/dir.go | 10 +++++++--- mfs/file.go | 3 +-- mfs/root.go | 11 +---------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa6a512cf..e0e1bcf95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ The following emojis are used to highlight certain changes: ### Fixed -* `mfs`: directory cache is now cleared every time the directory node is read, somewhat limiting unbounded growth and time to sync it to the underlying unixfs. +* `mfs`: directory cache is now cleared on Flush(), liberating the memory used by the otherwise ever-growing cache. References to directories and sub-directories should be renewed after flushing. ### Security diff --git a/mfs/dir.go b/mfs/dir.go index 690aa9f98..581f446a6 100644 --- a/mfs/dir.go +++ b/mfs/dir.go @@ -323,7 +323,7 @@ func (d *Directory) Unlink(name string) error { } func (d *Directory) Flush() error { - nd, err := d.GetNode() + nd, err := d.getNode(true) if err != nil { return err } @@ -349,7 +349,7 @@ func (d *Directory) AddChild(name string, nd ipld.Node) error { return d.unixfsDir.AddChild(d.ctx, name, nd) } -func (d *Directory) syncCache(clean bool) error { +func (d *Directory) cacheSync(clean bool) error { for name, entry := range d.entriesCache { nd, err := entry.GetNode() if err != nil { @@ -385,10 +385,14 @@ func (d *Directory) Path() string { } func (d *Directory) GetNode() (ipld.Node, error) { + return d.getNode(false) +} + +func (d *Directory) getNode(cacheClean bool) (ipld.Node, error) { d.lock.Lock() defer d.lock.Unlock() - err := d.syncCache(true) + err := d.cacheSync(cacheClean) if err != nil { return nil, err } diff --git a/mfs/file.go b/mfs/file.go index aff025db6..700244321 100644 --- a/mfs/file.go +++ b/mfs/file.go @@ -270,10 +270,9 @@ func (fi *File) setNodeData(data []byte) error { } fi.nodeLock.Lock() - defer fi.nodeLock.Unlock() fi.node = nd parent := fi.inode.parent name := fi.inode.name - + fi.nodeLock.Unlock() return parent.updateChildEntry(child{name, fi.node}) } diff --git a/mfs/root.go b/mfs/root.go index e584b6e06..e332f2da3 100644 --- a/mfs/root.go +++ b/mfs/root.go @@ -170,16 +170,7 @@ func (kr *Root) Flush() error { func (kr *Root) FlushMemFree(ctx context.Context) error { dir := kr.GetDirectory() - if err := dir.Flush(); err != nil { - return err - } - - dir.lock.Lock() - defer dir.lock.Unlock() - - clear(dir.entriesCache) - - return nil + return dir.Flush() } // updateChildEntry implements the `parent` interface, and signals