From e77e50886e937cd63175878ece20e0e0dbfc81ff Mon Sep 17 00:00:00 2001 From: zemul Date: Tue, 17 Dec 2024 12:19:32 +0800 Subject: [PATCH] mount metacache add ttl (#6360) * fix:mount deadlock * fix * feat: metaCache ttl * Update weed/command/mount.go Co-authored-by: Chris Lu * fix InodeEntry --------- Co-authored-by: zemul Co-authored-by: Chris Lu --- weed/command/mount.go | 2 ++ weed/command/mount_std.go | 1 + weed/mount/inode_to_path.go | 40 +++++++++++++++++++++++-------------- weed/mount/weedfs.go | 3 ++- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/weed/command/mount.go b/weed/command/mount.go index 3201fbb13..4fbcc0505 100644 --- a/weed/command/mount.go +++ b/weed/command/mount.go @@ -17,6 +17,7 @@ type MountOptions struct { ttlSec *int chunkSizeLimitMB *int concurrentWriters *int + cacheMetaTtlSec *int cacheDirForRead *string cacheDirForWrite *string cacheSizeMBForRead *int64 @@ -58,6 +59,7 @@ func init() { mountOptions.cacheDirForRead = cmdMount.Flag.String("cacheDir", os.TempDir(), "local cache directory for file chunks and meta data") mountOptions.cacheSizeMBForRead = cmdMount.Flag.Int64("cacheCapacityMB", 128, "file chunk read cache capacity in MB") mountOptions.cacheDirForWrite = cmdMount.Flag.String("cacheDirWrite", "", "buffer writes mostly for large files") + mountOptions.cacheMetaTtlSec = cmdMount.Flag.Int("cacheMetaTtlSec", 60, "metadata cache validity seconds") mountOptions.dataCenter = cmdMount.Flag.String("dataCenter", "", "prefer to write to the data center") mountOptions.allowOthers = cmdMount.Flag.Bool("allowOthers", true, "allows other users to access the file system") mountOptions.umaskString = cmdMount.Flag.String("umask", "022", "octal umask, e.g., 022, 0111") diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index 365a65c6d..110b0a2cf 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -236,6 +236,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { CacheDirForRead: *option.cacheDirForRead, CacheSizeMBForRead: *option.cacheSizeMBForRead, CacheDirForWrite: cacheDirForWrite, + CacheMetaTTlSec: *option.cacheMetaTtlSec, DataCenter: *option.dataCenter, Quota: int64(*option.collectionQuota) * 1024 * 1024, MountUid: uid, diff --git a/weed/mount/inode_to_path.go b/weed/mount/inode_to_path.go index 9992f1c22..da38750d1 100644 --- a/weed/mount/inode_to_path.go +++ b/weed/mount/inode_to_path.go @@ -10,15 +10,17 @@ import ( type InodeToPath struct { sync.RWMutex - nextInodeId uint64 - inode2path map[uint64]*InodeEntry - path2inode map[util.FullPath]uint64 + nextInodeId uint64 + cacheMetaTtlSec time.Duration + inode2path map[uint64]*InodeEntry + path2inode map[util.FullPath]uint64 } type InodeEntry struct { - paths []util.FullPath - nlookup uint64 - isDirectory bool - isChildrenCached bool + paths []util.FullPath + nlookup uint64 + isDirectory bool + isChildrenCached bool + cachedExpiresTime time.Time } func (ie *InodeEntry) removeOnePath(p util.FullPath) bool { @@ -43,13 +45,15 @@ func (ie *InodeEntry) removeOnePath(p util.FullPath) bool { return true } -func NewInodeToPath(root util.FullPath) *InodeToPath { +func NewInodeToPath(root util.FullPath, ttlSec int) *InodeToPath { t := &InodeToPath{ - inode2path: make(map[uint64]*InodeEntry), - path2inode: make(map[util.FullPath]uint64), + inode2path: make(map[uint64]*InodeEntry), + path2inode: make(map[util.FullPath]uint64), + cacheMetaTtlSec: time.Second * time.Duration(ttlSec), } - t.inode2path[1] = &InodeEntry{[]util.FullPath{root}, 1, true, false} + t.inode2path[1] = &InodeEntry{[]util.FullPath{root}, 1, true, false, time.Time{}} t.path2inode[root] = 1 + return t } @@ -92,9 +96,9 @@ func (i *InodeToPath) Lookup(path util.FullPath, unixTime int64, isDirectory boo } } else { if !isLookup { - i.inode2path[inode] = &InodeEntry{[]util.FullPath{path}, 0, isDirectory, false} + i.inode2path[inode] = &InodeEntry{[]util.FullPath{path}, 0, isDirectory, false, time.Time{}} } else { - i.inode2path[inode] = &InodeEntry{[]util.FullPath{path}, 1, isDirectory, false} + i.inode2path[inode] = &InodeEntry{[]util.FullPath{path}, 1, isDirectory, false, time.Time{}} } } @@ -157,6 +161,9 @@ func (i *InodeToPath) MarkChildrenCached(fullpath util.FullPath) { } path, found := i.inode2path[inode] path.isChildrenCached = true + if i.cacheMetaTtlSec > 0 { + path.cachedExpiresTime = time.Now().Add(i.cacheMetaTtlSec) + } } func (i *InodeToPath) IsChildrenCached(fullpath util.FullPath) bool { @@ -167,8 +174,11 @@ func (i *InodeToPath) IsChildrenCached(fullpath util.FullPath) bool { return false } path, found := i.inode2path[inode] - if found { - return path.isChildrenCached + if !found { + return false + } + if path.isChildrenCached { + return path.cachedExpiresTime.IsZero() || time.Now().Before(path.cachedExpiresTime) } return false } diff --git a/weed/mount/weedfs.go b/weed/mount/weedfs.go index 728777e32..7b67a8f32 100644 --- a/weed/mount/weedfs.go +++ b/weed/mount/weedfs.go @@ -42,6 +42,7 @@ type Option struct { CacheDirForRead string CacheSizeMBForRead int64 CacheDirForWrite string + CacheMetaTTlSec int DataCenter string Umask os.FileMode Quota int64 @@ -89,7 +90,7 @@ func NewSeaweedFileSystem(option *Option) *WFS { RawFileSystem: fuse.NewDefaultRawFileSystem(), option: option, signature: util.RandomInt32(), - inodeToPath: NewInodeToPath(util.FullPath(option.FilerMountRootPath)), + inodeToPath: NewInodeToPath(util.FullPath(option.FilerMountRootPath), option.CacheMetaTTlSec), fhMap: NewFileHandleToInode(), dhMap: NewDirectoryHandleToInode(), fhLockTable: util.NewLockTable[FileHandleId](),