mount: fix weed inode nlookup do not equel kernel inode nlookup (#7682)
* mount: fix weed inode nlookup do not equel kernel inode nlookup * mount: add underflow protection for nlookup decrement in Forget * mount: use consistent == 0 check for uint64 nlookup * Update weed/mount/inode_to_path.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * mount: snapshot data before unlock in Forget to avoid using deleted InodeEntry --------- Co-authored-by: chrislu <chris.lu@gmail.com> Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
package mount
|
package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hanwen/go-fuse/v2/fuse"
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/util"
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type InodeToPath struct {
|
type InodeToPath struct {
|
||||||
@@ -41,7 +42,6 @@ func (ie *InodeEntry) removeOnePath(p util.FullPath) bool {
|
|||||||
ie.paths[x] = ie.paths[x+1]
|
ie.paths[x] = ie.paths[x+1]
|
||||||
}
|
}
|
||||||
ie.paths = ie.paths[0 : len(ie.paths)-1]
|
ie.paths = ie.paths[0 : len(ie.paths)-1]
|
||||||
ie.nlookup--
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,9 +230,6 @@ func (i *InodeToPath) removePathFromInode2Path(inode uint64, path util.FullPath)
|
|||||||
if !ie.removeOnePath(path) {
|
if !ie.removeOnePath(path) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(ie.paths) == 0 {
|
|
||||||
delete(i.inode2path, inode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) (sourceInode, targetInode uint64) {
|
func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) (sourceInode, targetInode uint64) {
|
||||||
@@ -259,9 +256,6 @@ func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) (sourceInod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry.isChildrenCached = false
|
entry.isChildrenCached = false
|
||||||
if !targetFound {
|
|
||||||
entry.nlookup++
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
glog.Errorf("MovePath %s to %s: sourceInode %d not found", sourcePath, targetPath, sourceInode)
|
glog.Errorf("MovePath %s to %s: sourceInode %d not found", sourcePath, targetPath, sourceInode)
|
||||||
}
|
}
|
||||||
@@ -269,24 +263,39 @@ func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) (sourceInod
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
|
func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
|
||||||
|
var dirPaths []util.FullPath
|
||||||
|
callOnForgetDir := false
|
||||||
|
|
||||||
i.Lock()
|
i.Lock()
|
||||||
path, found := i.inode2path[inode]
|
path, found := i.inode2path[inode]
|
||||||
if found {
|
if found {
|
||||||
|
if nlookup > path.nlookup {
|
||||||
|
glog.Errorf("kernel forget over-decrement: inode %d paths %v current %d forget %d", inode, path.paths, path.nlookup, nlookup)
|
||||||
|
path.nlookup = 0
|
||||||
|
} else {
|
||||||
path.nlookup -= nlookup
|
path.nlookup -= nlookup
|
||||||
if path.nlookup <= 0 {
|
}
|
||||||
|
glog.V(4).Infof("kernel forget: inode %d paths %v nlookup %d", inode, path.paths, path.nlookup)
|
||||||
|
if path.nlookup == 0 {
|
||||||
|
if path.isDirectory && onForgetDir != nil {
|
||||||
|
dirPaths = append([]util.FullPath(nil), path.paths...)
|
||||||
|
callOnForgetDir = true
|
||||||
|
}
|
||||||
for _, p := range path.paths {
|
for _, p := range path.paths {
|
||||||
delete(i.path2inode, p)
|
delete(i.path2inode, p)
|
||||||
}
|
}
|
||||||
delete(i.inode2path, inode)
|
delete(i.inode2path, inode)
|
||||||
|
} else {
|
||||||
|
glog.V(4).Infof("kernel forget but nlookup not zero: inode %d paths %v nlookup %d", inode, path.paths, path.nlookup)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
glog.Warningf("kernel forget but inode not found: inode %d", inode)
|
||||||
}
|
}
|
||||||
i.Unlock()
|
i.Unlock()
|
||||||
if found {
|
|
||||||
if path.isDirectory && path.nlookup <= 0 && onForgetDir != nil {
|
if callOnForgetDir {
|
||||||
path.isChildrenCached = false
|
for _, p := range dirPaths {
|
||||||
for _, p := range path.paths {
|
|
||||||
onForgetDir(p)
|
onForgetDir(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out *fuse.DirEntryList, isPl
|
|||||||
processEachEntryFn := func(entry *filer.Entry) bool {
|
processEachEntryFn := func(entry *filer.Entry) bool {
|
||||||
dirEntry.Name = entry.Name()
|
dirEntry.Name = entry.Name()
|
||||||
dirEntry.Mode = toSyscallMode(entry.Mode)
|
dirEntry.Mode = toSyscallMode(entry.Mode)
|
||||||
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.Crtime.Unix(), entry.IsDirectory(), len(entry.HardLinkId) > 0, entry.Inode, isPlusMode)
|
inode := wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.Crtime.Unix(), entry.IsDirectory(), len(entry.HardLinkId) > 0, entry.Inode, false)
|
||||||
dirEntry.Ino = inode
|
dirEntry.Ino = inode
|
||||||
if !isPlusMode {
|
if !isPlusMode {
|
||||||
if !out.AddDirEntry(dirEntry) {
|
if !out.AddDirEntry(dirEntry) {
|
||||||
@@ -187,6 +187,7 @@ func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out *fuse.DirEntryList, isPl
|
|||||||
entry = filer.FromPbEntry(string(dirPath), fh.GetEntry().GetEntry())
|
entry = filer.FromPbEntry(string(dirPath), fh.GetEntry().GetEntry())
|
||||||
}
|
}
|
||||||
wfs.outputFilerEntry(entryOut, inode, entry)
|
wfs.outputFilerEntry(entryOut, inode, entry)
|
||||||
|
wfs.inodeToPath.Lookup(dirPath.Child(dirEntry.Name), entry.Crtime.Unix(), entry.IsDirectory(), len(entry.HardLinkId) > 0, entry.Inode, true)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user