mount2: use consistent inode
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user