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.

195 lines
4.2 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. "os"
  7. "sync"
  8. )
  9. type InodeToPath struct {
  10. sync.RWMutex
  11. nextInodeId uint64
  12. inode2path map[uint64]*InodeEntry
  13. path2inode map[util.FullPath]uint64
  14. }
  15. type InodeEntry struct {
  16. util.FullPath
  17. nlookup uint64
  18. isDirectory bool
  19. isChildrenCached bool
  20. }
  21. func NewInodeToPath() *InodeToPath {
  22. t := &InodeToPath{
  23. inode2path: make(map[uint64]*InodeEntry),
  24. path2inode: make(map[util.FullPath]uint64),
  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, mode os.FileMode, isHardlink bool, possibleInode uint64, isLookup bool) uint64 {
  31. i.Lock()
  32. defer i.Unlock()
  33. inode, found := i.path2inode[path]
  34. if !found {
  35. if possibleInode == 0 {
  36. inode = path.AsInode(mode)
  37. } else {
  38. inode = possibleInode
  39. }
  40. if !isHardlink {
  41. for _, found := i.inode2path[inode]; found; inode++ {
  42. _, found = i.inode2path[inode]
  43. }
  44. }
  45. }
  46. i.path2inode[path] = inode
  47. if _, found := i.inode2path[inode]; found {
  48. if isLookup {
  49. i.inode2path[inode].nlookup++
  50. }
  51. } else {
  52. if !isLookup {
  53. i.inode2path[inode] = &InodeEntry{path, 0, mode&os.ModeDir > 0, false}
  54. } else {
  55. i.inode2path[inode] = &InodeEntry{path, 1, mode&os.ModeDir > 0, false}
  56. }
  57. }
  58. return inode
  59. }
  60. func (i *InodeToPath) AllocateInode(path util.FullPath, mode os.FileMode) uint64 {
  61. if path == "/" {
  62. return 1
  63. }
  64. i.Lock()
  65. defer i.Unlock()
  66. inode := path.AsInode(mode)
  67. for _, found := i.inode2path[inode]; found; inode++ {
  68. _, found = i.inode2path[inode]
  69. }
  70. return inode
  71. }
  72. func (i *InodeToPath) GetInode(path util.FullPath) uint64 {
  73. if path == "/" {
  74. return 1
  75. }
  76. i.Lock()
  77. defer i.Unlock()
  78. inode, found := i.path2inode[path]
  79. if !found {
  80. // glog.Fatalf("GetInode unknown inode for %s", path)
  81. // this could be the parent for mount point
  82. }
  83. return inode
  84. }
  85. func (i *InodeToPath) GetPath(inode uint64) (util.FullPath, fuse.Status) {
  86. i.RLock()
  87. defer i.RUnlock()
  88. path, found := i.inode2path[inode]
  89. if !found {
  90. return "", fuse.ENOENT
  91. }
  92. return path.FullPath, fuse.OK
  93. }
  94. func (i *InodeToPath) HasPath(path util.FullPath) bool {
  95. i.RLock()
  96. defer i.RUnlock()
  97. _, found := i.path2inode[path]
  98. return found
  99. }
  100. func (i *InodeToPath) MarkChildrenCached(fullpath util.FullPath) {
  101. i.RLock()
  102. defer i.RUnlock()
  103. inode, found := i.path2inode[fullpath]
  104. if !found {
  105. glog.Fatalf("MarkChildrenCached not found inode %v", fullpath)
  106. }
  107. path, found := i.inode2path[inode]
  108. path.isChildrenCached = true
  109. }
  110. func (i *InodeToPath) IsChildrenCached(fullpath util.FullPath) bool {
  111. i.RLock()
  112. defer i.RUnlock()
  113. inode, found := i.path2inode[fullpath]
  114. if !found {
  115. return false
  116. }
  117. path, found := i.inode2path[inode]
  118. if found {
  119. return path.isChildrenCached
  120. }
  121. return false
  122. }
  123. func (i *InodeToPath) HasInode(inode uint64) bool {
  124. if inode == 1 {
  125. return true
  126. }
  127. i.RLock()
  128. defer i.RUnlock()
  129. _, found := i.inode2path[inode]
  130. return found
  131. }
  132. func (i *InodeToPath) RemovePath(path util.FullPath) {
  133. i.Lock()
  134. defer i.Unlock()
  135. inode, found := i.path2inode[path]
  136. if found {
  137. delete(i.path2inode, path)
  138. delete(i.inode2path, inode)
  139. }
  140. }
  141. func (i *InodeToPath) MovePath(sourcePath, targetPath util.FullPath) (replacedInode uint64) {
  142. i.Lock()
  143. defer i.Unlock()
  144. sourceInode, sourceFound := i.path2inode[sourcePath]
  145. targetInode, targetFound := i.path2inode[targetPath]
  146. if sourceFound {
  147. delete(i.path2inode, sourcePath)
  148. i.path2inode[targetPath] = sourceInode
  149. } else {
  150. // it is possible some source folder items has not been visited before
  151. // so no need to worry about their source inodes
  152. return
  153. }
  154. i.inode2path[sourceInode].FullPath = targetPath
  155. if targetFound {
  156. delete(i.inode2path, targetInode)
  157. } else {
  158. i.inode2path[sourceInode].nlookup++
  159. }
  160. return targetInode
  161. }
  162. func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
  163. i.Lock()
  164. path, found := i.inode2path[inode]
  165. if found {
  166. path.nlookup -= nlookup
  167. if path.nlookup <= 0 {
  168. delete(i.path2inode, path.FullPath)
  169. delete(i.inode2path, inode)
  170. }
  171. }
  172. i.Unlock()
  173. if found {
  174. if path.isDirectory && path.nlookup <= 0 && onForgetDir != nil {
  175. path.isChildrenCached = false
  176. onForgetDir(path.FullPath)
  177. }
  178. }
  179. }