mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
POSIX: different inode for same named different file types
This commit is contained in:
parent
e82ad60122
commit
fec8428fd8
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue