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.

168 lines
3.6 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package mount
  2. import (
  3. "github.com/chrislusf/seaweedfs/weed/glog"
  4. "github.com/chrislusf/seaweedfs/weed/util"
  5. "github.com/hanwen/go-fuse/v2/fuse"
  6. "sync"
  7. )
  8. type InodeToPath struct {
  9. sync.RWMutex
  10. nextInodeId uint64
  11. inode2path map[uint64]*InodeEntry
  12. path2inode map[util.FullPath]uint64
  13. }
  14. type InodeEntry struct {
  15. util.FullPath
  16. nlookup uint64
  17. isDirectory bool
  18. isChildrenCached bool
  19. }
  20. func NewInodeToPath() *InodeToPath {
  21. t := &InodeToPath{
  22. inode2path: make(map[uint64]*InodeEntry),
  23. path2inode: make(map[util.FullPath]uint64),
  24. nextInodeId: 2, // the root inode id is 1
  25. }
  26. t.inode2path[1] = &InodeEntry{"/", 1, true, false}
  27. t.path2inode["/"] = 1
  28. return t
  29. }
  30. func (i *InodeToPath) Lookup(path util.FullPath, isDirectory bool, isLookup bool) uint64 {
  31. i.Lock()
  32. defer i.Unlock()
  33. inode, found := i.path2inode[path]
  34. if !found {
  35. inode = i.nextInodeId
  36. i.nextInodeId++
  37. i.path2inode[path] = inode
  38. if !isLookup {
  39. i.inode2path[inode] = &InodeEntry{path, 0, isDirectory, false}
  40. } else {
  41. i.inode2path[inode] = &InodeEntry{path, 1, isDirectory, false}
  42. }
  43. } else {
  44. if isLookup {
  45. i.inode2path[inode].nlookup++
  46. }
  47. }
  48. return inode
  49. }
  50. func (i *InodeToPath) GetInode(path util.FullPath) uint64 {
  51. if path == "/" {
  52. return 1
  53. }
  54. i.Lock()
  55. defer i.Unlock()
  56. inode, found := i.path2inode[path]
  57. if !found {
  58. // glog.Fatalf("GetInode unknown inode for %s", path)
  59. // this could be the parent for mount point
  60. }
  61. return inode
  62. }
  63. func (i *InodeToPath) GetPath(inode uint64) (util.FullPath, fuse.Status) {
  64. i.RLock()
  65. defer i.RUnlock()
  66. path, found := i.inode2path[inode]
  67. if !found {
  68. return "", fuse.ENOENT
  69. }
  70. return path.FullPath, fuse.OK
  71. }
  72. func (i *InodeToPath) HasPath(path util.FullPath) bool {
  73. i.RLock()
  74. defer i.RUnlock()
  75. _, found := i.path2inode[path]
  76. return found
  77. }
  78. func (i *InodeToPath) MarkChildrenCached(fullpath util.FullPath) {
  79. i.RLock()
  80. defer i.RUnlock()
  81. inode, found := i.path2inode[fullpath]
  82. if !found {
  83. glog.Fatalf("MarkChildrenCached not found inode %v", fullpath)
  84. }
  85. path, found := i.inode2path[inode]
  86. path.isChildrenCached = true
  87. }
  88. func (i *InodeToPath) IsChildrenCached(fullpath util.FullPath) bool {
  89. i.RLock()
  90. defer i.RUnlock()
  91. inode, found := i.path2inode[fullpath]
  92. if !found {
  93. return false
  94. }
  95. path, found := i.inode2path[inode]
  96. if found {
  97. return path.isChildrenCached
  98. }
  99. return false
  100. }
  101. func (i *InodeToPath) HasInode(inode uint64) bool {
  102. if inode == 1 {
  103. return true
  104. }
  105. i.RLock()
  106. defer i.RUnlock()
  107. _, found := i.inode2path[inode]
  108. return found
  109. }
  110. func (i *InodeToPath) RemovePath(path util.FullPath) {
  111. i.Lock()
  112. defer i.Unlock()
  113. inode, found := i.path2inode[path]
  114. if found {
  115. delete(i.path2inode, path)
  116. delete(i.inode2path, inode)
  117. }
  118. }
  119. func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) {
  120. i.Lock()
  121. defer i.Unlock()
  122. sourceInode, sourceFound := i.path2inode[sourcePath]
  123. targetInode, targetFound := i.path2inode[targetPath]
  124. if sourceFound {
  125. delete(i.path2inode, sourcePath)
  126. i.path2inode[targetPath] = sourceInode
  127. } else {
  128. // it is possible some source folder items has not been visited before
  129. // so no need to worry about their source inodes
  130. return
  131. }
  132. i.inode2path[sourceInode].FullPath = targetPath
  133. if targetFound {
  134. delete(i.inode2path, targetInode)
  135. } else {
  136. i.inode2path[sourceInode].nlookup++
  137. }
  138. }
  139. func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
  140. i.Lock()
  141. path, found := i.inode2path[inode]
  142. if found {
  143. path.nlookup -= nlookup
  144. if path.nlookup <= 0 {
  145. delete(i.path2inode, path.FullPath)
  146. delete(i.inode2path, inode)
  147. }
  148. }
  149. i.Unlock()
  150. if found {
  151. if path.isDirectory && onForgetDir != nil {
  152. onForgetDir(path.FullPath)
  153. }
  154. }
  155. }