From fec8428fd80feb1ac7bfa34f5775a442f4627433 Mon Sep 17 00:00:00 2001 From: chrislu Date: Wed, 12 Jan 2022 11:51:13 -0800 Subject: [PATCH] POSIX: different inode for same named different file types --- weed/filesys/dir.go | 22 ++++++++--------- weed/filesys/dir_link.go | 4 ++-- weed/filesys/dir_rename.go | 19 ++++++++------- weed/filesys/file.go | 3 ++- weed/filesys/meta_cache/meta_cache.go | 9 +++---- .../meta_cache/meta_cache_subscribe.go | 6 ++--- weed/filesys/wfs.go | 6 ++--- weed/pb/filer_pb/filer_pb_helper.go | 8 +++++++ weed/util/fullpath.go | 24 +++++++++++++++---- 9 files changed, 63 insertions(+), 38 deletions(-) diff --git a/weed/filesys/dir.go b/weed/filesys/dir.go index eac4ecf25..7701e7de9 100644 --- a/weed/filesys/dir.go +++ b/weed/filesys/dir.go @@ -100,10 +100,10 @@ func (dir *Dir) Fsync(ctx context.Context, req *fuse.FsyncRequest) error { return nil } -func (dir *Dir) newFile(name string) fs.Node { +func (dir *Dir) newFile(name string, fileMode os.FileMode) fs.Node { fileFullPath := util.NewFullPath(dir.FullPath(), name) - fileId := fileFullPath.AsInode(false) + fileId := fileFullPath.AsInode(fileMode) dir.wfs.handlesLock.Lock() existingHandle, found := dir.wfs.handles[fileId] dir.wfs.handlesLock.Unlock() @@ -122,7 +122,7 @@ func (dir *Dir) newFile(name string) fs.Node { func (dir *Dir) newDirectory(fullpath util.FullPath) fs.Node { - return &Dir{name: fullpath.Name(), wfs: dir.wfs, parent: dir, id: fullpath.AsInode(true)} + return &Dir{name: fullpath.Name(), wfs: dir.wfs, parent: dir, id: fullpath.AsInode(os.ModeDir)} } @@ -148,7 +148,7 @@ func (dir *Dir) Create(ctx context.Context, req *fuse.CreateRequest, return node, node, nil } - node = dir.newFile(req.Name) + node = dir.newFile(req.Name, req.Mode) file := node.(*File) file.entry = &filer_pb.Entry{ Name: req.Name, @@ -184,7 +184,7 @@ func (dir *Dir) Mknod(ctx context.Context, req *fuse.MknodRequest) (fs.Node, err return nil, err } var node fs.Node - node = dir.newFile(req.Name) + node = dir.newFile(req.Name, req.Mode) return node, nil } @@ -328,7 +328,7 @@ func (dir *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse. if localEntry.IsDirectory() { node = dir.newDirectory(fullFilePath) } else { - node = dir.newFile(req.Name) + node = dir.newFile(req.Name, localEntry.Attr.Mode) } // resp.EntryValid = time.Second @@ -357,10 +357,10 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) { processEachEntryFn := func(entry *filer.Entry, isLast bool) { if entry.IsDirectory() { - dirent := fuse.Dirent{Name: entry.Name(), Type: fuse.DT_Dir, Inode: dirPath.Child(entry.Name()).AsInode(true)} + dirent := fuse.Dirent{Name: entry.Name(), Type: fuse.DT_Dir, Inode: dirPath.Child(entry.Name()).AsInode(os.ModeDir)} ret = append(ret, dirent) } else { - dirent := fuse.Dirent{Name: entry.Name(), Type: findFileType(uint16(entry.Attr.Mode)), Inode: dirPath.Child(entry.Name()).AsInode(false)} + dirent := fuse.Dirent{Name: entry.Name(), Type: findFileType(uint16(entry.Attr.Mode)), Inode: dirPath.Child(entry.Name()).AsInode(entry.Attr.Mode)} ret = append(ret, dirent) } } @@ -380,7 +380,7 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) { // create proper . and .. directories ret = append(ret, fuse.Dirent{ - Inode: dirPath.AsInode(true), + Inode: dirPath.AsInode(os.ModeDir), Name: ".", Type: fuse.DT_Dir, }) @@ -390,7 +390,7 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) { if string(dirPath) == dir.wfs.option.FilerMountRootPath { inode = dir.wfs.option.MountParentInode } else { - inode = util.FullPath(dir.parent.FullPath()).AsInode(true) + inode = util.FullPath(dir.parent.FullPath()).AsInode(os.ModeDir) } ret = append(ret, fuse.Dirent{ @@ -459,7 +459,7 @@ func (dir *Dir) removeOneFile(req *fuse.RemoveRequest) error { // remove current file handle if any dir.wfs.handlesLock.Lock() defer dir.wfs.handlesLock.Unlock() - inodeId := filePath.AsInode(false) + inodeId := filePath.AsInode(0) if fh, ok := dir.wfs.handles[inodeId]; ok { delete(dir.wfs.handles, inodeId) fh.isDeleted = true diff --git a/weed/filesys/dir_link.go b/weed/filesys/dir_link.go index cc339b2ed..423fffb71 100644 --- a/weed/filesys/dir_link.go +++ b/weed/filesys/dir_link.go @@ -97,7 +97,7 @@ func (dir *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fs.Node) (f } // create new file node - newNode := dir.newFile(req.NewName) + newNode := dir.newFile(req.NewName, 0) newFile := newNode.(*File) return newFile, err @@ -144,7 +144,7 @@ func (dir *Dir) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node, return nil }) - symlink := dir.newFile(req.NewName) + symlink := dir.newFile(req.NewName, os.ModeSymlink) return symlink, err diff --git a/weed/filesys/dir_rename.go b/weed/filesys/dir_rename.go index 22fe74fef..4cc9959f6 100644 --- a/weed/filesys/dir_rename.go +++ b/weed/filesys/dir_rename.go @@ -9,6 +9,7 @@ import ( "github.com/seaweedfs/fuse" "github.com/seaweedfs/fuse/fs" "io" + "os" "strings" ) @@ -91,13 +92,13 @@ func (dir *Dir) handleRenameResponse(ctx context.Context, resp *filer_pb.StreamR oldParent, newParent := util.FullPath(resp.Directory), util.FullPath(resp.EventNotification.NewParentPath) oldName, newName := resp.EventNotification.OldEntry.Name, resp.EventNotification.NewEntry.Name - isDirectory := newEntry.IsDirectory() + entryFileMode := newEntry.Attr.Mode oldPath := oldParent.Child(oldName) newPath := newParent.Child(newName) - oldFsNode := NodeWithId(oldPath.AsInode(isDirectory)) - newFsNode := NodeWithId(newPath.AsInode(isDirectory)) - newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode(true))) + oldFsNode := NodeWithId(oldPath.AsInode(entryFileMode)) + newFsNode := NodeWithId(newPath.AsInode(entryFileMode)) + newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode(os.ModeDir))) var newDir *Dir if found { newDir = newDirNode.(*Dir) @@ -122,16 +123,16 @@ func (dir *Dir) handleRenameResponse(ctx context.Context, resp *filer_pb.StreamR }) // change file handle - if !isDirectory { - inodeId := oldPath.AsInode(isDirectory) + if !newEntry.IsDirectory() { + inodeId := oldPath.AsInode(entryFileMode) dir.wfs.handlesLock.Lock() if existingHandle, found := dir.wfs.handles[inodeId]; found && existingHandle != nil { glog.V(4).Infof("opened file handle %s => %s", oldPath, newPath) delete(dir.wfs.handles, inodeId) - existingHandle.handle = newPath.AsInode(isDirectory) + existingHandle.handle = newPath.AsInode(entryFileMode) existingHandle.f.entry.Name = newName - existingHandle.f.id = newPath.AsInode(isDirectory) - dir.wfs.handles[newPath.AsInode(isDirectory)] = existingHandle + existingHandle.f.id = newPath.AsInode(entryFileMode) + dir.wfs.handles[newPath.AsInode(entryFileMode)] = existingHandle } dir.wfs.handlesLock.Unlock() } diff --git a/weed/filesys/file.go b/weed/filesys/file.go index 063c431b0..7b5b5a424 100644 --- a/weed/filesys/file.go +++ b/weed/filesys/file.go @@ -261,7 +261,8 @@ func (file *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) error { func (file *File) Forget() { t := util.NewFullPath(file.dir.FullPath(), file.Name) glog.V(4).Infof("Forget file %s", t) - file.wfs.ReleaseHandle(t, fuse.HandleID(t.AsInode(false))) + file.wfs.ReleaseHandle(t, fuse.HandleID(t.AsInode(file.entry.FileMode()))) + } func (file *File) maybeLoadEntry(ctx context.Context) (entry *filer_pb.Entry, err error) { diff --git a/weed/filesys/meta_cache/meta_cache.go b/weed/filesys/meta_cache/meta_cache.go index adb3f144f..dc8e6838f 100644 --- a/weed/filesys/meta_cache/meta_cache.go +++ b/weed/filesys/meta_cache/meta_cache.go @@ -5,6 +5,7 @@ import ( "github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/filer/leveldb" "github.com/chrislusf/seaweedfs/weed/glog" + "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" "github.com/chrislusf/seaweedfs/weed/util" "github.com/chrislusf/seaweedfs/weed/util/bounded_tree" "os" @@ -18,16 +19,16 @@ type MetaCache struct { // sync.RWMutex visitedBoundary *bounded_tree.BoundedTree uidGidMapper *UidGidMapper - invalidateFunc func(fullpath util.FullPath, isDirectory bool) + invalidateFunc func(fullpath util.FullPath, entry *filer_pb.Entry) } -func NewMetaCache(dbFolder string, baseDir util.FullPath, uidGidMapper *UidGidMapper, invalidateFunc func(util.FullPath, bool)) *MetaCache { +func NewMetaCache(dbFolder string, baseDir util.FullPath, uidGidMapper *UidGidMapper, invalidateFunc func(util.FullPath, *filer_pb.Entry)) *MetaCache { return &MetaCache{ localStore: openMetaStore(dbFolder), visitedBoundary: bounded_tree.NewBoundedTree(baseDir), uidGidMapper: uidGidMapper, - invalidateFunc: func(fullpath util.FullPath, isDirectory bool) { - invalidateFunc(fullpath, isDirectory) + invalidateFunc: func(fullpath util.FullPath, entry *filer_pb.Entry) { + invalidateFunc(fullpath, entry) }, } } diff --git a/weed/filesys/meta_cache/meta_cache_subscribe.go b/weed/filesys/meta_cache/meta_cache_subscribe.go index f33461dd4..881fee08f 100644 --- a/weed/filesys/meta_cache/meta_cache_subscribe.go +++ b/weed/filesys/meta_cache/meta_cache_subscribe.go @@ -40,16 +40,16 @@ func SubscribeMetaEvents(mc *MetaCache, selfSignature int32, client filer_pb.Fil if err == nil { if message.OldEntry != nil && message.NewEntry != nil { oldKey := util.NewFullPath(resp.Directory, message.OldEntry.Name) - mc.invalidateFunc(oldKey, message.OldEntry.IsDirectory) + mc.invalidateFunc(oldKey, message.OldEntry) if message.OldEntry.Name != message.NewEntry.Name { newKey := util.NewFullPath(dir, message.NewEntry.Name) - mc.invalidateFunc(newKey, message.NewEntry.IsDirectory) + mc.invalidateFunc(newKey, message.NewEntry) } } else if message.OldEntry == nil && message.NewEntry != nil { // no need to invaalidate } else if message.OldEntry != nil && message.NewEntry == nil { oldKey := util.NewFullPath(resp.Directory, message.OldEntry.Name) - mc.invalidateFunc(oldKey, message.OldEntry.IsDirectory) + mc.invalidateFunc(oldKey, message.OldEntry) } } diff --git a/weed/filesys/wfs.go b/weed/filesys/wfs.go index 63b83f7ef..f6a6031d2 100644 --- a/weed/filesys/wfs.go +++ b/weed/filesys/wfs.go @@ -109,15 +109,15 @@ func NewSeaweedFileSystem(option *Option) *WFS { wfs.chunkCache = chunk_cache.NewTieredChunkCache(256, option.getUniqueCacheDir(), option.CacheSizeMB, 1024*1024) } - wfs.metaCache = meta_cache.NewMetaCache(path.Join(option.getUniqueCacheDir(), "meta"), util.FullPath(option.FilerMountRootPath), option.UidGidMapper, func(filePath util.FullPath, isDirectory bool) { + wfs.metaCache = meta_cache.NewMetaCache(path.Join(option.getUniqueCacheDir(), "meta"), util.FullPath(option.FilerMountRootPath), option.UidGidMapper, func(filePath util.FullPath, entry *filer_pb.Entry) { - fsNode := NodeWithId(filePath.AsInode(isDirectory)) + fsNode := NodeWithId(filePath.AsInode(entry.FileMode())) if err := wfs.Server.InvalidateNodeData(fsNode); err != nil { glog.V(4).Infof("InvalidateNodeData %s : %v", filePath, err) } dir, name := filePath.DirAndName() - parent := NodeWithId(util.FullPath(dir).AsInode(true)) + parent := NodeWithId(util.FullPath(dir).AsInode(os.ModeDir)) if dir == option.FilerMountRootPath { parent = NodeWithId(1) } diff --git a/weed/pb/filer_pb/filer_pb_helper.go b/weed/pb/filer_pb/filer_pb_helper.go index 186a5e20a..b00d412e1 100644 --- a/weed/pb/filer_pb/filer_pb_helper.go +++ b/weed/pb/filer_pb/filer_pb_helper.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "strings" "github.com/chrislusf/seaweedfs/weed/glog" @@ -16,6 +17,13 @@ func (entry *Entry) IsInRemoteOnly() bool { return len(entry.Chunks) == 0 && entry.RemoteEntry != nil && entry.RemoteEntry.RemoteSize > 0 } +func (entry *Entry) FileMode() (fileMode os.FileMode) { + if entry != nil && entry.Attributes != nil { + fileMode = os.FileMode(entry.Attributes.FileMode) + } + return +} + func ToFileIdObject(fileIdStr string) (*FileId, error) { t, err := needle.ParseFileIdFromString(fileIdStr) if err != nil { diff --git a/weed/util/fullpath.go b/weed/util/fullpath.go index 404187e8b..d2fb017a1 100644 --- a/weed/util/fullpath.go +++ b/weed/util/fullpath.go @@ -1,6 +1,7 @@ package util import ( + "os" "path/filepath" "strings" ) @@ -41,12 +42,25 @@ func (fp FullPath) Child(name string) FullPath { return FullPath(dir + "/" + noPrefix) } -func (fp FullPath) AsInode(isDirectory bool) uint64 { +// AsInode an in-memory only inode representation +func (fp FullPath) AsInode(fileMode os.FileMode) uint64 { inode := uint64(HashStringToLong(string(fp))) - if isDirectory { - inode = inode - inode%2 // even - } else { - inode = inode - inode%2 + 1 // odd + inode = inode - inode%16 + if fileMode == 0 { + } else if fileMode&os.ModeDir > 0 { + inode += 1 + } else if fileMode&os.ModeSymlink > 0 { + inode += 2 + } else if fileMode&os.ModeDevice > 0 { + inode += 3 + } else if fileMode&os.ModeNamedPipe > 0 { + inode += 4 + } else if fileMode&os.ModeSocket > 0 { + inode += 5 + } else if fileMode&os.ModeCharDevice > 0 { + inode += 6 + } else if fileMode&os.ModeIrregular > 0 { + inode += 7 } return inode }