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.

201 lines
4.5 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 targetFound {
  146. delete(i.inode2path, targetInode)
  147. delete(i.path2inode, targetPath)
  148. }
  149. if sourceFound {
  150. delete(i.path2inode, sourcePath)
  151. i.path2inode[targetPath] = sourceInode
  152. } else {
  153. // it is possible some source folder items has not been visited before
  154. // so no need to worry about their source inodes
  155. return
  156. }
  157. if entry, entryFound := i.inode2path[sourceInode]; entryFound {
  158. entry.FullPath = targetPath
  159. entry.isChildrenCached = false
  160. if !targetFound {
  161. entry.nlookup++
  162. }
  163. } else {
  164. glog.Errorf("MovePath %s to %s: sourceInode %s not found", sourcePath, targetPath, sourceInode)
  165. }
  166. return targetInode
  167. }
  168. func (i *InodeToPath) Forget(inode, nlookup uint64, onForgetDir func(dir util.FullPath)) {
  169. i.Lock()
  170. path, found := i.inode2path[inode]
  171. if found {
  172. path.nlookup -= nlookup
  173. if path.nlookup <= 0 {
  174. delete(i.path2inode, path.FullPath)
  175. delete(i.inode2path, inode)
  176. }
  177. }
  178. i.Unlock()
  179. if found {
  180. if path.isDirectory && path.nlookup <= 0 && onForgetDir != nil {
  181. path.isChildrenCached = false
  182. onForgetDir(path.FullPath)
  183. }
  184. }
  185. }