You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package mount
  2. import (
  3. "context"
  4. "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
  5. "github.com/chrislusf/seaweedfs/weed/pb"
  6. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  7. "github.com/chrislusf/seaweedfs/weed/storage/types"
  8. "github.com/chrislusf/seaweedfs/weed/util"
  9. "github.com/chrislusf/seaweedfs/weed/util/grace"
  10. "github.com/hanwen/go-fuse/v2/fuse"
  11. "google.golang.org/grpc"
  12. "os"
  13. "path"
  14. "path/filepath"
  15. "time"
  16. "github.com/hanwen/go-fuse/v2/fs"
  17. )
  18. type Option struct {
  19. MountDirectory string
  20. FilerAddresses []pb.ServerAddress
  21. filerIndex int
  22. GrpcDialOption grpc.DialOption
  23. FilerMountRootPath string
  24. Collection string
  25. Replication string
  26. TtlSec int32
  27. DiskType types.DiskType
  28. ChunkSizeLimit int64
  29. ConcurrentWriters int
  30. CacheDir string
  31. CacheSizeMB int64
  32. DataCenter string
  33. Umask os.FileMode
  34. MountUid uint32
  35. MountGid uint32
  36. MountMode os.FileMode
  37. MountCtime time.Time
  38. MountMtime time.Time
  39. MountParentInode uint64
  40. VolumeServerAccess string // how to access volume servers
  41. Cipher bool // whether encrypt data on volume server
  42. UidGidMapper *meta_cache.UidGidMapper
  43. uniqueCacheDir string
  44. uniqueCacheTempPageDir string
  45. }
  46. type WFS struct {
  47. // follow https://github.com/hanwen/go-fuse/blob/master/fuse/api.go
  48. fuse.RawFileSystem
  49. fs.Inode
  50. option *Option
  51. metaCache *meta_cache.MetaCache
  52. stats statsCache
  53. root Directory
  54. signature int32
  55. inodeToPath *InodeToPath
  56. fhmap *FileHandleToInode
  57. }
  58. func NewSeaweedFileSystem(option *Option) *WFS {
  59. wfs := &WFS{
  60. RawFileSystem: fuse.NewDefaultRawFileSystem(),
  61. option: option,
  62. signature: util.RandomInt32(),
  63. inodeToPath: NewInodeToPath(),
  64. fhmap: NewFileHandleToInode(),
  65. }
  66. wfs.root = Directory{
  67. name: "/",
  68. wfs: wfs,
  69. entry: nil,
  70. parent: nil,
  71. }
  72. wfs.metaCache = meta_cache.NewMetaCache(path.Join(option.getUniqueCacheDir(), "meta"), util.FullPath(option.FilerMountRootPath), option.UidGidMapper, func(filePath util.FullPath, entry *filer_pb.Entry) {
  73. })
  74. grace.OnInterrupt(func() {
  75. wfs.metaCache.Shutdown()
  76. })
  77. return wfs
  78. }
  79. func (wfs *WFS) Root() *Directory {
  80. return &wfs.root
  81. }
  82. func (wfs *WFS) String() string {
  83. return "seaweedfs"
  84. }
  85. func (wfs *WFS) maybeReadEntry(inode uint64) (path util.FullPath, entry *filer_pb.Entry, status fuse.Status) {
  86. path = wfs.inodeToPath.GetPath(inode)
  87. entry, status = wfs.maybeLoadEntry(path)
  88. return
  89. }
  90. func (wfs *WFS) maybeLoadEntry(fullpath util.FullPath) (*filer_pb.Entry, fuse.Status) {
  91. // glog.V(3).Infof("read entry cache miss %s", fullpath)
  92. dir, name := fullpath.DirAndName()
  93. // return a valid entry for the mount root
  94. if string(fullpath) == wfs.option.FilerMountRootPath {
  95. return &filer_pb.Entry{
  96. Name: name,
  97. IsDirectory: true,
  98. Attributes: &filer_pb.FuseAttributes{
  99. Mtime: wfs.option.MountMtime.Unix(),
  100. FileMode: uint32(wfs.option.MountMode),
  101. Uid: wfs.option.MountUid,
  102. Gid: wfs.option.MountGid,
  103. Crtime: wfs.option.MountCtime.Unix(),
  104. },
  105. }, fuse.OK
  106. }
  107. // TODO Use inode to selectively filetering metadata updates
  108. // read from async meta cache
  109. meta_cache.EnsureVisited(wfs.metaCache, wfs, util.FullPath(dir))
  110. cachedEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullpath)
  111. if cacheErr == filer_pb.ErrNotFound {
  112. return nil, fuse.ENOENT
  113. }
  114. return cachedEntry.ToProtoEntry(), fuse.OK
  115. }
  116. func (option *Option) setupUniqueCacheDirectory() {
  117. cacheUniqueId := util.Md5String([]byte(option.MountDirectory + string(option.FilerAddresses[0]) + option.FilerMountRootPath + util.Version()))[0:8]
  118. option.uniqueCacheDir = path.Join(option.CacheDir, cacheUniqueId)
  119. option.uniqueCacheTempPageDir = filepath.Join(option.uniqueCacheDir, "sw")
  120. os.MkdirAll(option.uniqueCacheTempPageDir, os.FileMode(0777)&^option.Umask)
  121. }
  122. func (option *Option) getTempFilePageDir() string {
  123. return option.uniqueCacheTempPageDir
  124. }
  125. func (option *Option) getUniqueCacheDir() string {
  126. return option.uniqueCacheDir
  127. }