inode_to_path.go 3.9 KB

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