mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
POSIX: ensure file and directory inodes are different
this is just an in memory representation. POSIX wants different inode numbers for the same named file or directory.
This commit is contained in:
parent
5bb37d5905
commit
2dcb8cb93b
|
@ -103,7 +103,7 @@ func (dir *Dir) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
|||
func (dir *Dir) newFile(name string) fs.Node {
|
||||
|
||||
fileFullPath := util.NewFullPath(dir.FullPath(), name)
|
||||
fileId := fileFullPath.AsInode()
|
||||
fileId := fileFullPath.AsInode(false)
|
||||
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()}
|
||||
return &Dir{name: fullpath.Name(), wfs: dir.wfs, parent: dir, id: fullpath.AsInode(true)}
|
||||
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,6 @@ func (dir *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.
|
|||
}
|
||||
|
||||
// resp.EntryValid = time.Second
|
||||
resp.Attr.Inode = fullFilePath.AsInode()
|
||||
resp.Attr.Valid = time.Second
|
||||
resp.Attr.Size = localEntry.FileSize
|
||||
resp.Attr.Mtime = localEntry.Attr.Mtime
|
||||
|
@ -342,10 +341,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()}
|
||||
dirent := fuse.Dirent{Name: entry.Name(), Type: fuse.DT_Dir, Inode: dirPath.Child(entry.Name()).AsInode(true)}
|
||||
ret = append(ret, dirent)
|
||||
} else {
|
||||
dirent := fuse.Dirent{Name: entry.Name(), Type: findFileType(uint16(entry.Attr.Mode)), Inode: dirPath.Child(entry.Name()).AsInode()}
|
||||
dirent := fuse.Dirent{Name: entry.Name(), Type: findFileType(uint16(entry.Attr.Mode)), Inode: dirPath.Child(entry.Name()).AsInode(false)}
|
||||
ret = append(ret, dirent)
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +364,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(),
|
||||
Inode: dirPath.AsInode(true),
|
||||
Name: ".",
|
||||
Type: fuse.DT_Dir,
|
||||
})
|
||||
|
@ -375,7 +374,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()
|
||||
inode = util.FullPath(dir.parent.FullPath()).AsInode(true)
|
||||
}
|
||||
|
||||
ret = append(ret, fuse.Dirent{
|
||||
|
@ -444,7 +443,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()
|
||||
inodeId := filePath.AsInode(false)
|
||||
if fh, ok := dir.wfs.handles[inodeId]; ok {
|
||||
delete(dir.wfs.handles, inodeId)
|
||||
fh.isDeleted = true
|
||||
|
|
|
@ -84,11 +84,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()
|
||||
|
||||
oldPath := oldParent.Child(oldName)
|
||||
newPath := newParent.Child(newName)
|
||||
oldFsNode := NodeWithId(oldPath.AsInode())
|
||||
newFsNode := NodeWithId(newPath.AsInode())
|
||||
newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode()))
|
||||
oldFsNode := NodeWithId(oldPath.AsInode(isDirectory))
|
||||
newFsNode := NodeWithId(newPath.AsInode(isDirectory))
|
||||
newDirNode, found := dir.wfs.Server.FindInternalNode(NodeWithId(newParent.AsInode(true)))
|
||||
var newDir *Dir
|
||||
if found {
|
||||
newDir = newDirNode.(*Dir)
|
||||
|
@ -113,17 +115,19 @@ func (dir *Dir) handleRenameResponse(ctx context.Context, resp *filer_pb.StreamR
|
|||
})
|
||||
|
||||
// change file handle
|
||||
inodeId := oldPath.AsInode()
|
||||
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()
|
||||
existingHandle.f.entry.Name = newName
|
||||
existingHandle.f.id = newPath.AsInode()
|
||||
dir.wfs.handles[newPath.AsInode()] = existingHandle
|
||||
if !isDirectory {
|
||||
inodeId := oldPath.AsInode(isDirectory)
|
||||
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.f.entry.Name = newName
|
||||
existingHandle.f.id = newPath.AsInode(isDirectory)
|
||||
dir.wfs.handles[newPath.AsInode(isDirectory)] = existingHandle
|
||||
}
|
||||
dir.wfs.handlesLock.Unlock()
|
||||
}
|
||||
dir.wfs.handlesLock.Unlock()
|
||||
|
||||
} else if resp.EventNotification.OldEntry != nil {
|
||||
// without new entry, only old entry name exists. This is the second step to delete old entry
|
||||
|
|
|
@ -259,7 +259,7 @@ 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()))
|
||||
file.wfs.ReleaseHandle(t, fuse.HandleID(t.AsInode(false)))
|
||||
}
|
||||
|
||||
func (file *File) maybeLoadEntry(ctx context.Context) (entry *filer_pb.Entry, err error) {
|
||||
|
|
|
@ -18,16 +18,16 @@ type MetaCache struct {
|
|||
// sync.RWMutex
|
||||
visitedBoundary *bounded_tree.BoundedTree
|
||||
uidGidMapper *UidGidMapper
|
||||
invalidateFunc func(util.FullPath)
|
||||
invalidateFunc func(fullpath util.FullPath, isDirectory bool)
|
||||
}
|
||||
|
||||
func NewMetaCache(dbFolder string, baseDir util.FullPath, uidGidMapper *UidGidMapper, invalidateFunc func(util.FullPath)) *MetaCache {
|
||||
func NewMetaCache(dbFolder string, baseDir util.FullPath, uidGidMapper *UidGidMapper, invalidateFunc func(util.FullPath, bool)) *MetaCache {
|
||||
return &MetaCache{
|
||||
localStore: openMetaStore(dbFolder),
|
||||
visitedBoundary: bounded_tree.NewBoundedTree(baseDir),
|
||||
uidGidMapper: uidGidMapper,
|
||||
invalidateFunc: func(fullpath util.FullPath) {
|
||||
invalidateFunc(fullpath)
|
||||
invalidateFunc: func(fullpath util.FullPath, isDirectory bool) {
|
||||
invalidateFunc(fullpath, isDirectory)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
mc.invalidateFunc(oldKey, message.OldEntry.IsDirectory)
|
||||
if message.OldEntry.Name != message.NewEntry.Name {
|
||||
newKey := util.NewFullPath(dir, message.NewEntry.Name)
|
||||
mc.invalidateFunc(newKey)
|
||||
mc.invalidateFunc(newKey, message.NewEntry.IsDirectory)
|
||||
}
|
||||
} 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)
|
||||
mc.invalidateFunc(oldKey, message.OldEntry.IsDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
wfs.metaCache = meta_cache.NewMetaCache(path.Join(option.getUniqueCacheDir(), "meta"), util.FullPath(option.FilerMountRootPath), option.UidGidMapper, func(filePath util.FullPath, isDirectory bool) {
|
||||
|
||||
fsNode := NodeWithId(filePath.AsInode())
|
||||
fsNode := NodeWithId(filePath.AsInode(isDirectory))
|
||||
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())
|
||||
parent := NodeWithId(util.FullPath(dir).AsInode(true))
|
||||
if dir == option.FilerMountRootPath {
|
||||
parent = NodeWithId(1)
|
||||
}
|
||||
|
|
|
@ -41,8 +41,14 @@ func (fp FullPath) Child(name string) FullPath {
|
|||
return FullPath(dir + "/" + noPrefix)
|
||||
}
|
||||
|
||||
func (fp FullPath) AsInode() uint64 {
|
||||
return uint64(HashStringToLong(string(fp)))
|
||||
func (fp FullPath) AsInode(isDirectory bool) uint64 {
|
||||
inode := uint64(HashStringToLong(string(fp)))
|
||||
if isDirectory {
|
||||
inode = inode - inode%2 // even
|
||||
} else {
|
||||
inode = inode - inode%2 + 1 // odd
|
||||
}
|
||||
return inode
|
||||
}
|
||||
|
||||
// split, but skipping the root
|
||||
|
|
Loading…
Reference in a new issue