From f87da798a4e9f9d5e4e60966630c5ea1ff291d37 Mon Sep 17 00:00:00 2001 From: chrislu Date: Fri, 11 Feb 2022 03:09:30 -0800 Subject: [PATCH] to be re-written following fuse virtual file system --- go.mod | 1 - weed/Makefile | 4 ++ weed/command/mount2_std.go | 2 +- weed/mount/directory.go | 42 ++++++++++++++++++ weed/mount/directory_read.go | 84 ++++++++++++++++++++++++++++++++++++ weed/mount/weedfs.go | 34 ++++++--------- weed/mount/weedfs_stats.go | 6 ++- 7 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 weed/mount/directory.go create mode 100644 weed/mount/directory_read.go diff --git a/go.mod b/go.mod index 31c7666a2..ffdc48dcc 100644 --- a/go.mod +++ b/go.mod @@ -164,7 +164,6 @@ require ( require ( github.com/fluent/fluent-logger-golang v1.8.0 - github.com/hanwen/go-fuse v1.0.0 github.com/hanwen/go-fuse/v2 v2.1.0 ) diff --git a/weed/Makefile b/weed/Makefile index 4e871a71e..1d1a8476c 100644 --- a/weed/Makefile +++ b/weed/Makefile @@ -21,6 +21,10 @@ debug_mount: go build -gcflags="all=-N -l" dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- -v=4 mount -dir=~/tmp/mm -cacheCapacityMB=0 -filer.path=/ -umask=000 +debug_mount2: + go build -gcflags="all=-N -l" + dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- -v=4 mount2 -dir=~/tmp/mm -cacheCapacityMB=0 -filer.path=/ -umask=000 + debug_server: go build -gcflags="all=-N -l" dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- server -dir=~/tmp/99 -filer -volume.port=8343 -s3 -volume.max=0 -master.volumeSizeLimitMB=1024 -volume.preStopSeconds=1 diff --git a/weed/command/mount2_std.go b/weed/command/mount2_std.go index 2d3c0dfb4..0cb288c3b 100644 --- a/weed/command/mount2_std.go +++ b/weed/command/mount2_std.go @@ -207,7 +207,7 @@ func RunMount2(option *Mount2Options, umask os.FileMode) bool { UidGidMapper: uidGidMapper, }) - server, err := fs.Mount(dir, seaweedFileSystem, opts) + server, err := fs.Mount(dir, seaweedFileSystem.Root(), opts) if err != nil { glog.Fatalf("Mount fail: %v", err) } diff --git a/weed/mount/directory.go b/weed/mount/directory.go new file mode 100644 index 000000000..60fbafc37 --- /dev/null +++ b/weed/mount/directory.go @@ -0,0 +1,42 @@ +package mount + +import ( + "bytes" + "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" + "github.com/hanwen/go-fuse/v2/fs" + "strings" +) + +type Directory struct { + fs.Inode + + name string + wfs *WFS + entry *filer_pb.Entry + parent *Directory + id uint64 +} + +func (dir *Directory) FullPath() string { + var parts []string + for p := dir; p != nil; p = p.parent { + if strings.HasPrefix(p.name, "/") { + if len(p.name) > 1 { + parts = append(parts, p.name[1:]) + } + } else { + parts = append(parts, p.name) + } + } + + if len(parts) == 0 { + return "/" + } + + var buf bytes.Buffer + for i := len(parts) - 1; i >= 0; i-- { + buf.WriteString("/") + buf.WriteString(parts[i]) + } + return buf.String() +} diff --git a/weed/mount/directory_read.go b/weed/mount/directory_read.go new file mode 100644 index 000000000..51c51ae16 --- /dev/null +++ b/weed/mount/directory_read.go @@ -0,0 +1,84 @@ +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/util" + "github.com/hanwen/go-fuse/v2/fs" + "github.com/hanwen/go-fuse/v2/fuse" + "math" + "os" + "syscall" +) + +var _ = fs.NodeReaddirer(&Directory{}) +var _ = fs.NodeGetattrer(&Directory{}) + +func (dir *Directory) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno { + out.Mode = 0755 + return 0 +} + +func (dir *Directory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) { + + dirPath := util.FullPath(dir.FullPath()) + glog.V(4).Infof("Readdir %s", dirPath) + + sourceChan := make(chan fuse.DirEntry, 64) + + stream := newDirectoryListStream(sourceChan) + + processEachEntryFn := func(entry *filer.Entry, isLast bool) { + sourceChan <- fuse.DirEntry{ + Mode: uint32(entry.Mode), + Name: entry.Name(), + Ino: dirPath.Child(entry.Name()).AsInode(os.ModeDir), + } + } + + if err := meta_cache.EnsureVisited(dir.wfs.metaCache, dir.wfs, dirPath); err != nil { + glog.Errorf("dir ReadDirAll %s: %v", dirPath, err) + return nil, fs.ToErrno(os.ErrInvalid) + } + go func() { + dir.wfs.metaCache.ListDirectoryEntries(context.Background(), dirPath, "", false, int64(math.MaxInt32), func(entry *filer.Entry) bool { + processEachEntryFn(entry, false) + return true + }) + close(sourceChan) + }() + + return stream, fs.OK +} + +var _ = fs.DirStream(&DirectoryListStream{}) + +type DirectoryListStream struct { + next fuse.DirEntry + sourceChan chan fuse.DirEntry + isStarted bool + hasNext bool +} + +func newDirectoryListStream(ch chan fuse.DirEntry) *DirectoryListStream { + return &DirectoryListStream{ + sourceChan: ch, + } +} + +func (i *DirectoryListStream) HasNext() bool { + if !i.isStarted { + i.next, i.hasNext = <-i.sourceChan + i.isStarted = true + } + return i.hasNext +} +func (i *DirectoryListStream) Next() (fuse.DirEntry, syscall.Errno) { + t := i.next + i.next, i.hasNext = <-i.sourceChan + return t, fs.OK +} +func (i *DirectoryListStream) Close() { +} diff --git a/weed/mount/weedfs.go b/weed/mount/weedfs.go index 75a509b5c..b2a64acb7 100644 --- a/weed/mount/weedfs.go +++ b/weed/mount/weedfs.go @@ -1,7 +1,6 @@ package mount import ( - "context" "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache" "github.com/chrislusf/seaweedfs/weed/pb" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" @@ -12,11 +11,9 @@ import ( "os" "path" "path/filepath" - "syscall" "time" "github.com/hanwen/go-fuse/v2/fs" - "github.com/hanwen/go-fuse/v2/fuse" ) type Option struct { @@ -56,6 +53,7 @@ type WFS struct { option *Option metaCache *meta_cache.MetaCache stats statsCache + root Directory signature int32 } @@ -65,6 +63,13 @@ func NewSeaweedFileSystem(option *Option) *WFS { signature: util.RandomInt32(), } + wfs.root = Directory{ + name: "/", + wfs: wfs, + entry: nil, + parent: nil, + } + wfs.metaCache = meta_cache.NewMetaCache(path.Join(option.getUniqueCacheDir(), "meta"), util.FullPath(option.FilerMountRootPath), option.UidGidMapper, func(filePath util.FullPath, entry *filer_pb.Entry) { }) grace.OnInterrupt(func() { @@ -74,6 +79,10 @@ func NewSeaweedFileSystem(option *Option) *WFS { return wfs } +func (wfs *WFS) Root() *Directory { + return &wfs.root +} + func (option *Option) setupUniqueCacheDirectory() { cacheUniqueId := util.Md5String([]byte(option.MountDirectory + string(option.FilerAddresses[0]) + option.FilerMountRootPath + util.Version()))[0:8] option.uniqueCacheDir = path.Join(option.CacheDir, cacheUniqueId) @@ -87,22 +96,3 @@ func (option *Option) getTempFilePageDir() string { func (option *Option) getUniqueCacheDir() string { return option.uniqueCacheDir } - -func (r *WFS) OnAdd(ctx context.Context) { - ch := r.NewPersistentInode( - ctx, &fs.MemRegularFile{ - Data: []byte("file.txt"), - Attr: fuse.Attr{ - Mode: 0644, - }, - }, fs.StableAttr{Ino: 2}) - r.AddChild("file.txt", ch, false) -} - -func (r *WFS) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno { - out.Mode = 0755 - return 0 -} - -var _ = (fs.NodeGetattrer)((*WFS)(nil)) -var _ = (fs.NodeOnAdder)((*WFS)(nil)) diff --git a/weed/mount/weedfs_stats.go b/weed/mount/weedfs_stats.go index fc24db0e2..f3ef268df 100644 --- a/weed/mount/weedfs_stats.go +++ b/weed/mount/weedfs_stats.go @@ -15,14 +15,16 @@ import ( const blockSize = 512 -var _ = fs.NodeStatfser(&WFS{}) +var _ = fs.NodeStatfser(&Directory{}) type statsCache struct { filer_pb.StatisticsResponse lastChecked int64 // unix time in seconds } -func (wfs *WFS) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { +func (dir *Directory) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { + + wfs := dir.wfs glog.V(4).Infof("reading fs stats")