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.

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