mount2: use consistent inode

This commit is contained in:
chrislu
2022-02-25 00:53:27 -08:00
parent ceaf993a27
commit be3fc77391
14 changed files with 513 additions and 467 deletions

View File

@@ -4,6 +4,7 @@ import (
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/hanwen/go-fuse/v2/fuse"
"os"
"sync"
)
@@ -22,33 +23,42 @@ type InodeEntry struct {
func NewInodeToPath() *InodeToPath {
t := &InodeToPath{
inode2path: make(map[uint64]*InodeEntry),
path2inode: make(map[util.FullPath]uint64),
nextInodeId: 2, // the root inode id is 1
inode2path: make(map[uint64]*InodeEntry),
path2inode: make(map[util.FullPath]uint64),
}
t.inode2path[1] = &InodeEntry{"/", 1, true, false}
t.path2inode["/"] = 1
return t
}
func (i *InodeToPath) Lookup(path util.FullPath, isDirectory bool, isLookup bool) uint64 {
func (i *InodeToPath) Lookup(path util.FullPath, mode os.FileMode, isCreate bool, possibleInode uint64, isLookup bool) uint64 {
i.Lock()
defer i.Unlock()
inode, found := i.path2inode[path]
if !found {
inode = i.nextInodeId
i.nextInodeId++
i.path2inode[path] = inode
if !isLookup {
i.inode2path[inode] = &InodeEntry{path, 0, isDirectory, false}
if possibleInode == 0 {
inode = path.AsInode(mode)
for _, found := i.inode2path[inode]; found; inode++ {
_, found = i.inode2path[inode]
}
} else {
i.inode2path[inode] = &InodeEntry{path, 1, isDirectory, false}
inode = possibleInode
}
} else {
}
i.path2inode[path] = inode
if _, found := i.inode2path[inode]; found {
if isLookup {
i.inode2path[inode].nlookup++
}
} else {
if !isLookup {
i.inode2path[inode] = &InodeEntry{path, 0, mode&os.ModeDir > 0, false}
} else {
i.inode2path[inode] = &InodeEntry{path, 1, mode&os.ModeDir > 0, false}
}
}
return inode
}

View File

@@ -53,7 +53,7 @@ func (wfs *WFS) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name strin
return fuse.ENOENT
}
inode := wfs.inodeToPath.Lookup(fullFilePath, localEntry.IsDirectory(), true)
inode := wfs.inodeToPath.Lookup(fullFilePath, localEntry.Mode, false, localEntry.Inode, true)
if fh, found := wfs.fhmap.FindFileHandle(inode); found {
glog.V(4).Infof("lookup opened file %s size %d", dirPath.Child(localEntry.Name()), filer.FileSize(fh.entry))

View File

@@ -74,7 +74,7 @@ func (wfs *WFS) Mkdir(cancel <-chan struct{}, in *fuse.MkdirIn, name string, out
return fuse.EIO
}
inode := wfs.inodeToPath.Lookup(entryFullPath, true, true)
inode := wfs.inodeToPath.Lookup(entryFullPath, os.ModeDir, true, 0, true)
wfs.outputPbEntry(out, inode, newEntry)

View File

@@ -162,14 +162,14 @@ func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out *fuse.DirEntryList, isPl
dirEntry.Name = entry.Name()
dirEntry.Mode = toSyscallMode(entry.Mode)
if !isPlusMode {
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.IsDirectory(), false)
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.Mode, false, entry.Inode, false)
dirEntry.Ino = inode
if !out.AddDirEntry(dirEntry) {
isEarlyTerminated = true
return false
}
} else {
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.IsDirectory(), true)
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.Mode, false, entry.Inode, true)
dirEntry.Ino = inode
entryOut := out.AddDirLookupEntry(dirEntry)
if entryOut == nil {

View File

@@ -39,28 +39,30 @@ func (wfs *WFS) Mknod(cancel <-chan struct{}, in *fuse.MknodIn, name string, out
return s
}
newEntry := &filer_pb.Entry{
Name: name,
IsDirectory: false,
Attributes: &filer_pb.FuseAttributes{
Mtime: time.Now().Unix(),
Crtime: time.Now().Unix(),
FileMode: uint32(toOsFileMode(in.Mode)),
Uid: in.Uid,
Gid: in.Gid,
Collection: wfs.option.Collection,
Replication: wfs.option.Replication,
TtlSec: wfs.option.TtlSec,
Rdev: in.Rdev,
},
}
dirFullPath, code := wfs.inodeToPath.GetPath(in.NodeId)
if code != fuse.OK {
return
}
entryFullPath := dirFullPath.Child(name)
fileMode := toOsFileMode(in.Mode)
newEntry := &filer_pb.Entry{
Name: name,
IsDirectory: false,
Attributes: &filer_pb.FuseAttributes{
Mtime: time.Now().Unix(),
Crtime: time.Now().Unix(),
FileMode: uint32(fileMode),
Uid: in.Uid,
Gid: in.Gid,
Collection: wfs.option.Collection,
Replication: wfs.option.Replication,
TtlSec: wfs.option.TtlSec,
Rdev: in.Rdev,
Inode: entryFullPath.AsInode(fileMode),
},
}
err := wfs.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
@@ -92,7 +94,7 @@ func (wfs *WFS) Mknod(cancel <-chan struct{}, in *fuse.MknodIn, name string, out
return fuse.EIO
}
inode := wfs.inodeToPath.Lookup(entryFullPath, false, true)
inode := wfs.inodeToPath.Lookup(entryFullPath, newEntry.FileMode(), true, 0, true)
wfs.outputPbEntry(out, inode, newEntry)

View File

@@ -5,14 +5,20 @@ import (
"github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/hanwen/go-fuse/v2/fuse"
"time"
)
const (
HARD_LINK_MARKER = '\x01'
)
/*
What is an inode?
If the file is an hardlinked file:
use the hardlink id as inode
Otherwise:
use the file path as inode
When creating a link:
use the original file inode
*/
/** Create a hard link to a file */
func (wfs *WFS) Link(cancel <-chan struct{}, in *fuse.LinkIn, name string, out *fuse.EntryOut) (code fuse.Status) {
@@ -38,7 +44,7 @@ func (wfs *WFS) Link(cancel <-chan struct{}, in *fuse.LinkIn, name string, out *
// update old file to hardlink mode
if len(oldEntry.HardLinkId) == 0 {
oldEntry.HardLinkId = append(util.RandomBytes(16), HARD_LINK_MARKER)
oldEntry.HardLinkId = filer.NewHardLinkId()
oldEntry.HardLinkCounter = 1
}
oldEntry.HardLinkCounter++
@@ -91,7 +97,7 @@ func (wfs *WFS) Link(cancel <-chan struct{}, in *fuse.LinkIn, name string, out *
return fuse.EIO
}
inode := wfs.inodeToPath.Lookup(newEntryPath, false, true)
inode := wfs.inodeToPath.Lookup(newEntryPath, oldEntry.FileMode(), false, oldEntry.Attributes.Inode, true)
wfs.outputPbEntry(out, inode, request.Entry)

View File

@@ -59,7 +59,7 @@ func (wfs *WFS) Symlink(cancel <-chan struct{}, header *fuse.InHeader, target st
return fuse.EIO
}
inode := wfs.inodeToPath.Lookup(entryFullPath, false, true)
inode := wfs.inodeToPath.Lookup(entryFullPath, os.ModeSymlink, false, 0, true)
wfs.outputPbEntry(out, inode, request.Entry)