POSIX: different inode for same named different file types

This commit is contained in:
chrislu 2022-01-12 11:51:13 -08:00
parent e82ad60122
commit fec8428fd8
9 changed files with 63 additions and 38 deletions

View file

@ -100,10 +100,10 @@ func (dir *Dir) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
return nil 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) fileFullPath := util.NewFullPath(dir.FullPath(), name)
fileId := fileFullPath.AsInode(false) fileId := fileFullPath.AsInode(fileMode)
dir.wfs.handlesLock.Lock() dir.wfs.handlesLock.Lock()
existingHandle, found := dir.wfs.handles[fileId] existingHandle, found := dir.wfs.handles[fileId]
dir.wfs.handlesLock.Unlock() 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 { 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 return node, node, nil
} }
node = dir.newFile(req.Name) node = dir.newFile(req.Name, req.Mode)
file := node.(*File) file := node.(*File)
file.entry = &filer_pb.Entry{ file.entry = &filer_pb.Entry{
Name: req.Name, Name: req.Name,
@ -184,7 +184,7 @@ func (dir *Dir) Mknod(ctx context.Context, req *fuse.MknodRequest) (fs.Node, err
return nil, err return nil, err
} }
var node fs.Node var node fs.Node
node = dir.newFile(req.Name) node = dir.newFile(req.Name, req.Mode)
return node, nil return node, nil
} }
@ -328,7 +328,7 @@ func (dir *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.
if localEntry.IsDirectory() { if localEntry.IsDirectory() {
node = dir.newDirectory(fullFilePath) node = dir.newDirectory(fullFilePath)
} else { } else {
node = dir.newFile(req.Name) node = dir.newFile(req.Name, localEntry.Attr.Mode)
} }
// resp.EntryValid = time.Second // 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) { processEachEntryFn := func(entry *filer.Entry, isLast bool) {
if entry.IsDirectory() { 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) ret = append(ret, dirent)
} else { } 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) ret = append(ret, dirent)
} }
} }
@ -380,7 +380,7 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) {
// create proper . and .. directories // create proper . and .. directories
ret = append(ret, fuse.Dirent{ ret = append(ret, fuse.Dirent{
Inode: dirPath.AsInode(true), Inode: dirPath.AsInode(os.ModeDir),
Name: ".", Name: ".",
Type: fuse.DT_Dir, 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 { if string(dirPath) == dir.wfs.option.FilerMountRootPath {
inode = dir.wfs.option.MountParentInode inode = dir.wfs.option.MountParentInode
} else { } else {
inode = util.FullPath(dir.parent.FullPath()).AsInode(true) inode = util.FullPath(dir.parent.FullPath()).AsInode(os.ModeDir)
} }
ret = append(ret, fuse.Dirent{ ret = append(ret, fuse.Dirent{
@ -459,7 +459,7 @@ func (dir *Dir) removeOneFile(req *fuse.RemoveRequest) error {
// remove current file handle if any // remove current file handle if any
dir.wfs.handlesLock.Lock() dir.wfs.handlesLock.Lock()
defer dir.wfs.handlesLock.Unlock() defer dir.wfs.handlesLock.Unlock()
inodeId := filePath.AsInode(false) inodeId := filePath.AsInode(0)
if fh, ok := dir.wfs.handles[inodeId]; ok { if fh, ok := dir.wfs.handles[inodeId]; ok {
delete(dir.wfs.handles, inodeId) delete(dir.wfs.handles, inodeId)
fh.isDeleted = true fh.isDeleted = true

View file

@ -97,7 +97,7 @@ func (dir *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fs.Node) (f
} }
// create new file node // create new file node
newNode := dir.newFile(req.NewName) newNode := dir.newFile(req.NewName, 0)
newFile := newNode.(*File) newFile := newNode.(*File)
return newFile, err return newFile, err
@ -144,7 +144,7 @@ func (dir *Dir) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node,
return nil return nil
}) })
symlink := dir.newFile(req.NewName) symlink := dir.newFile(req.NewName, os.ModeSymlink)
return symlink, err return symlink, err

View file

@ -9,6 +9,7 @@ import (
"github.com/seaweedfs/fuse" "github.com/seaweedfs/fuse"
"github.com/seaweedfs/fuse/fs" "github.com/seaweedfs/fuse/fs"
"io" "io"
"os"
"strings" "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) oldParent, newParent := util.FullPath(resp.Directory), util.FullPath(resp.EventNotification.NewParentPath)
oldName, newName := resp.EventNotification.OldEntry.Name, resp.EventNotification.NewEntry.Name oldName, newName := resp.EventNotification.OldEntry.Name, resp.EventNotification.NewEntry.Name
isDirectory := newEntry.IsDirectory() entryFileMode := newEntry.Attr.Mode
oldPath := oldParent.Child(oldName) oldPath := oldParent.Child(oldName)
newPath := newParent.Child(newName) newPath := newParent.Child(newName)
oldFsNode := NodeWithId(oldPath.AsInode(isDirectory)) oldFsNode := NodeWithId(oldPath.AsInode(entryFileMode))
newFsNode := NodeWithId(newPath.AsInode(isDirectory)) newFsNode := NodeWithId(newPath.AsInode(entryFileMode))
newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode(true))) newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode(os.ModeDir)))
var newDir *Dir var newDir *Dir
if found { if found {
newDir = newDirNode.(*Dir) newDir = newDirNode.(*Dir)
@ -122,16 +123,16 @@ func (dir *Dir) handleRenameResponse(ctx context.Context, resp *filer_pb.StreamR
}) })
// change file handle // change file handle
if !isDirectory { if !newEntry.IsDirectory() {
inodeId := oldPath.AsInode(isDirectory) inodeId := oldPath.AsInode(entryFileMode)
dir.wfs.handlesLock.Lock() dir.wfs.handlesLock.Lock()
if existingHandle, found := dir.wfs.handles[inodeId]; found && existingHandle != nil { if existingHandle, found := dir.wfs.handles[inodeId]; found && existingHandle != nil {
glog.V(4).Infof("opened file handle %s => %s", oldPath, newPath) glog.V(4).Infof("opened file handle %s => %s", oldPath, newPath)
delete(dir.wfs.handles, inodeId) delete(dir.wfs.handles, inodeId)
existingHandle.handle = newPath.AsInode(isDirectory) existingHandle.handle = newPath.AsInode(entryFileMode)
existingHandle.f.entry.Name = newName existingHandle.f.entry.Name = newName
existingHandle.f.id = newPath.AsInode(isDirectory) existingHandle.f.id = newPath.AsInode(entryFileMode)
dir.wfs.handles[newPath.AsInode(isDirectory)] = existingHandle dir.wfs.handles[newPath.AsInode(entryFileMode)] = existingHandle
} }
dir.wfs.handlesLock.Unlock() dir.wfs.handlesLock.Unlock()
} }

View file

@ -261,7 +261,8 @@ func (file *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
func (file *File) Forget() { func (file *File) Forget() {
t := util.NewFullPath(file.dir.FullPath(), file.Name) t := util.NewFullPath(file.dir.FullPath(), file.Name)
glog.V(4).Infof("Forget file %s", t) 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) { func (file *File) maybeLoadEntry(ctx context.Context) (entry *filer_pb.Entry, err error) {

View file

@ -5,6 +5,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/filer/leveldb" "github.com/chrislusf/seaweedfs/weed/filer/leveldb"
"github.com/chrislusf/seaweedfs/weed/glog" "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"
"github.com/chrislusf/seaweedfs/weed/util/bounded_tree" "github.com/chrislusf/seaweedfs/weed/util/bounded_tree"
"os" "os"
@ -18,16 +19,16 @@ type MetaCache struct {
// sync.RWMutex // sync.RWMutex
visitedBoundary *bounded_tree.BoundedTree visitedBoundary *bounded_tree.BoundedTree
uidGidMapper *UidGidMapper 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{ return &MetaCache{
localStore: openMetaStore(dbFolder), localStore: openMetaStore(dbFolder),
visitedBoundary: bounded_tree.NewBoundedTree(baseDir), visitedBoundary: bounded_tree.NewBoundedTree(baseDir),
uidGidMapper: uidGidMapper, uidGidMapper: uidGidMapper,
invalidateFunc: func(fullpath util.FullPath, isDirectory bool) { invalidateFunc: func(fullpath util.FullPath, entry *filer_pb.Entry) {
invalidateFunc(fullpath, isDirectory) invalidateFunc(fullpath, entry)
}, },
} }
} }

View file

@ -40,16 +40,16 @@ func SubscribeMetaEvents(mc *MetaCache, selfSignature int32, client filer_pb.Fil
if err == nil { if err == nil {
if message.OldEntry != nil && message.NewEntry != nil { if message.OldEntry != nil && message.NewEntry != nil {
oldKey := util.NewFullPath(resp.Directory, message.OldEntry.Name) 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 { if message.OldEntry.Name != message.NewEntry.Name {
newKey := util.NewFullPath(dir, 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 { } else if message.OldEntry == nil && message.NewEntry != nil {
// no need to invaalidate // no need to invaalidate
} else if message.OldEntry != nil && message.NewEntry == nil { } else if message.OldEntry != nil && message.NewEntry == nil {
oldKey := util.NewFullPath(resp.Directory, message.OldEntry.Name) oldKey := util.NewFullPath(resp.Directory, message.OldEntry.Name)
mc.invalidateFunc(oldKey, message.OldEntry.IsDirectory) mc.invalidateFunc(oldKey, message.OldEntry)
} }
} }

View file

@ -109,15 +109,15 @@ func NewSeaweedFileSystem(option *Option) *WFS {
wfs.chunkCache = chunk_cache.NewTieredChunkCache(256, option.getUniqueCacheDir(), option.CacheSizeMB, 1024*1024) 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 { if err := wfs.Server.InvalidateNodeData(fsNode); err != nil {
glog.V(4).Infof("InvalidateNodeData %s : %v", filePath, err) glog.V(4).Infof("InvalidateNodeData %s : %v", filePath, err)
} }
dir, name := filePath.DirAndName() dir, name := filePath.DirAndName()
parent := NodeWithId(util.FullPath(dir).AsInode(true)) parent := NodeWithId(util.FullPath(dir).AsInode(os.ModeDir))
if dir == option.FilerMountRootPath { if dir == option.FilerMountRootPath {
parent = NodeWithId(1) parent = NodeWithId(1)
} }

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"os"
"strings" "strings"
"github.com/chrislusf/seaweedfs/weed/glog" "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 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) { func ToFileIdObject(fileIdStr string) (*FileId, error) {
t, err := needle.ParseFileIdFromString(fileIdStr) t, err := needle.ParseFileIdFromString(fileIdStr)
if err != nil { if err != nil {

View file

@ -1,6 +1,7 @@
package util package util
import ( import (
"os"
"path/filepath" "path/filepath"
"strings" "strings"
) )
@ -41,12 +42,25 @@ func (fp FullPath) Child(name string) FullPath {
return FullPath(dir + "/" + noPrefix) 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))) inode := uint64(HashStringToLong(string(fp)))
if isDirectory { inode = inode - inode%16
inode = inode - inode%2 // even if fileMode == 0 {
} else { } else if fileMode&os.ModeDir > 0 {
inode = inode - inode%2 + 1 // odd 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 return inode
} }