diff --git a/weed/mount/weedfs_attr.go b/weed/mount/weedfs_attr.go index 311d5331a..788badb77 100644 --- a/weed/mount/weedfs_attr.go +++ b/weed/mount/weedfs_attr.go @@ -78,19 +78,27 @@ func (wfs *WFS) setAttrByPbEntry(out *fuse.Attr, inode uint64, entry *filer_pb.E func (wfs *WFS) setAttrByFilerEntry(out *fuse.Attr, inode uint64, entry *filer.Entry) { out.Ino = inode - out.Uid = entry.Attr.Uid - out.Gid = entry.Attr.Gid - out.Mode = toSystemMode(entry.Attr.Mode) - out.Mtime = uint64(entry.Attr.Mtime.Unix()) - out.Ctime = uint64(entry.Attr.Mtime.Unix()) - out.Atime = uint64(entry.Attr.Mtime.Unix()) - if entry.HardLinkCounter > 0 { - out.Nlink = uint32(entry.HardLinkCounter) - } out.Size = entry.FileSize out.Blocks = out.Size/blockSize + 1 setBlksize(out, blockSize) + out.Atime = uint64(entry.Attr.Mtime.Unix()) + out.Mtime = uint64(entry.Attr.Mtime.Unix()) + out.Ctime = uint64(entry.Attr.Mtime.Unix()) + out.Crtime_ = uint64(entry.Attr.Crtime.Unix()) + out.Mode = toSystemMode(entry.Attr.Mode) + if entry.HardLinkCounter > 0 { + out.Nlink = uint32(entry.HardLinkCounter) + } out.Nlink = 1 + out.Uid = entry.Attr.Uid + out.Gid = entry.Attr.Gid +} + +func (wfs *WFS) outputEntry(out *fuse.EntryOut, inode uint64, entry *filer.Entry) { + // out.Generation = 1 + out.EntryValid = 1 + out.AttrValid = 1 + wfs.setAttrByFilerEntry(&out.Attr, inode, entry) } func toSystemMode(mode os.FileMode) uint32 { diff --git a/weed/mount/weedfs_dir_lookup.go b/weed/mount/weedfs_dir_lookup.go new file mode 100644 index 000000000..672ba9711 --- /dev/null +++ b/weed/mount/weedfs_dir_lookup.go @@ -0,0 +1,59 @@ +package mount + +import ( + "context" + "github.com/chrislusf/seaweedfs/weed/filer" + "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache" + "github.com/chrislusf/seaweedfs/weed/glog" + "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" + "github.com/hanwen/go-fuse/v2/fuse" +) + +// Lookup is called by the kernel when the VFS wants to know +// about a file inside a directory. Many lookup calls can +// occur in parallel, but only one call happens for each (dir, +// name) pair. + +func (wfs *WFS) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name string, out *fuse.EntryOut) (code fuse.Status) { + + dirPath := wfs.inodeToPath.GetPath(header.NodeId) + + println("lookup", name, "dir inode", header.NodeId) + + fullFilePath := dirPath.Child(name) + + visitErr := meta_cache.EnsureVisited(wfs.metaCache, wfs, dirPath) + if visitErr != nil { + glog.Errorf("dir Lookup %s: %v", dirPath, visitErr) + return fuse.EIO + } + localEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullFilePath) + if cacheErr == filer_pb.ErrNotFound { + return fuse.ENOENT + } + + if localEntry == nil { + // glog.V(3).Infof("dir Lookup cache miss %s", fullFilePath) + entry, err := filer_pb.GetEntry(wfs, fullFilePath) + if err != nil { + glog.V(1).Infof("dir GetEntry %s: %v", fullFilePath, err) + return fuse.ENOENT + } + localEntry = filer.FromPbEntry(string(dirPath), entry) + } else { + glog.V(4).Infof("dir Lookup cache hit %s", fullFilePath) + } + + if localEntry == nil { + return fuse.ENOENT + } + + inode := wfs.inodeToPath.GetInode(fullFilePath) + + println("found", name, "inode", inode) + + wfs.outputEntry(out, inode, localEntry) + + return fuse.OK + +} diff --git a/weed/mount/weedfs_dir_read.go b/weed/mount/weedfs_dir_read.go index 43eb17bf2..a696953a1 100644 --- a/weed/mount/weedfs_dir_read.go +++ b/weed/mount/weedfs_dir_read.go @@ -5,8 +5,10 @@ import ( "github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache" "github.com/chrislusf/seaweedfs/weed/glog" + "github.com/chrislusf/seaweedfs/weed/util" "github.com/hanwen/go-fuse/v2/fuse" "math" + "os" ) // Directory handling @@ -31,26 +33,45 @@ func (wfs *WFS) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out *fus func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out *fuse.DirEntryList, isPlusMode bool) fuse.Status { dirPath := wfs.inodeToPath.GetPath(input.NodeId) + println("input size", input.Size, "offset", input.Offset, "pid", input.Caller.Pid) + var dirEntry fuse.DirEntry + if input.Offset == 0 { + dirEntry.Ino = input.NodeId + dirEntry.Name = "." + dirEntry.Mode = toSystemMode(os.ModeDir) + out.AddDirEntry(dirEntry) + + parentDir, _ := dirPath.DirAndName() + parentInode := wfs.inodeToPath.GetInode(util.FullPath(parentDir)) + dirEntry.Ino = parentInode + dirEntry.Name = ".." + dirEntry.Mode = toSystemMode(os.ModeDir) + out.AddDirEntry(dirEntry) + + } + + var counter uint64 processEachEntryFn := func(entry *filer.Entry, isLast bool) bool { + counter++ + if counter <= input.Offset { + return true + } dirEntry.Name = entry.Name() inode := wfs.inodeToPath.GetInode(dirPath.Child(dirEntry.Name)) + println("entry", dirEntry.Name, "inode", inode) dirEntry.Ino = inode dirEntry.Mode = toSystemMode(entry.Mode) if !isPlusMode { if !out.AddDirEntry(dirEntry) { return false } - } else { entryOut := out.AddDirLookupEntry(dirEntry) if entryOut == nil { return false } - entryOut.Generation = 1 - entryOut.EntryValid = 1 - entryOut.AttrValid = 1 - wfs.setAttrByFilerEntry(&entryOut.Attr, inode, entry) + wfs.outputEntry(entryOut, inode, entry) } return true } @@ -67,5 +88,6 @@ func (wfs *WFS) doReadDirectory(input *fuse.ReadIn, out *fuse.DirEntryList, isPl glog.Errorf("list meta cache: %v", listErr) return fuse.EIO } + return fuse.OK }