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.

216 lines
5.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
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/filer"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  6. "github.com/hanwen/go-fuse/v2/fuse"
  7. "os"
  8. "syscall"
  9. "time"
  10. )
  11. func (wfs *WFS) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
  12. if input.NodeId == 1 {
  13. wfs.setRootAttr(out)
  14. return fuse.OK
  15. }
  16. _, _, entry, status := wfs.maybeReadEntry(input.NodeId)
  17. if status != fuse.OK {
  18. return status
  19. }
  20. out.AttrValid = 1
  21. wfs.setAttrByPbEntry(&out.Attr, input.NodeId, entry)
  22. return fuse.OK
  23. }
  24. func (wfs *WFS) SetAttr(cancel <-chan struct{}, input *fuse.SetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
  25. path, fh, entry, status := wfs.maybeReadEntry(input.NodeId)
  26. if status != fuse.OK {
  27. return status
  28. }
  29. if size, ok := input.GetSize(); ok {
  30. glog.V(4).Infof("%v setattr set size=%v chunks=%d", path, size, len(entry.Chunks))
  31. if size < filer.FileSize(entry) {
  32. // fmt.Printf("truncate %v \n", fullPath)
  33. var chunks []*filer_pb.FileChunk
  34. var truncatedChunks []*filer_pb.FileChunk
  35. for _, chunk := range entry.Chunks {
  36. int64Size := int64(chunk.Size)
  37. if chunk.Offset+int64Size > int64(size) {
  38. // this chunk is truncated
  39. int64Size = int64(size) - chunk.Offset
  40. if int64Size > 0 {
  41. chunks = append(chunks, chunk)
  42. glog.V(4).Infof("truncated chunk %+v from %d to %d\n", chunk.GetFileIdString(), chunk.Size, int64Size)
  43. chunk.Size = uint64(int64Size)
  44. } else {
  45. glog.V(4).Infof("truncated whole chunk %+v\n", chunk.GetFileIdString())
  46. truncatedChunks = append(truncatedChunks, chunk)
  47. }
  48. }
  49. }
  50. // set the new chunks and reset entry cache
  51. entry.Chunks = chunks
  52. if fh != nil {
  53. fh.entryViewCache = nil
  54. }
  55. }
  56. entry.Attributes.Mtime = time.Now().Unix()
  57. entry.Attributes.FileSize = size
  58. }
  59. if mode, ok := input.GetMode(); ok {
  60. glog.V(4).Infof("setAttr mode %o", mode)
  61. entry.Attributes.FileMode = chmod(entry.Attributes.FileMode, mode)
  62. }
  63. if uid, ok := input.GetUID(); ok {
  64. entry.Attributes.Uid = uid
  65. }
  66. if gid, ok := input.GetGID(); ok {
  67. entry.Attributes.Gid = gid
  68. }
  69. if mtime, ok := input.GetMTime(); ok {
  70. entry.Attributes.Mtime = mtime.Unix()
  71. }
  72. if atime, ok := input.GetATime(); ok {
  73. entry.Attributes.Mtime = atime.Unix()
  74. }
  75. entry.Attributes.Mtime = time.Now().Unix()
  76. out.AttrValid = 1
  77. wfs.setAttrByPbEntry(&out.Attr, input.NodeId, entry)
  78. if fh != nil {
  79. fh.dirtyMetadata = true
  80. return fuse.OK
  81. }
  82. return wfs.saveEntry(path, entry)
  83. }
  84. func (wfs *WFS) setRootAttr(out *fuse.AttrOut) {
  85. now := uint64(time.Now().Unix())
  86. out.AttrValid = 119
  87. out.Ino = 1
  88. setBlksize(&out.Attr, blockSize)
  89. out.Uid = wfs.option.MountUid
  90. out.Gid = wfs.option.MountGid
  91. out.Mtime = now
  92. out.Ctime = now
  93. out.Atime = now
  94. out.Mode = toSyscallType(os.ModeDir) | uint32(wfs.option.MountMode)
  95. out.Nlink = 1
  96. }
  97. func (wfs *WFS) setAttrByPbEntry(out *fuse.Attr, inode uint64, entry *filer_pb.Entry) {
  98. out.Ino = inode
  99. out.Size = filer.FileSize(entry)
  100. out.Blocks = (out.Size + blockSize - 1) / blockSize
  101. setBlksize(out, blockSize)
  102. out.Mtime = uint64(entry.Attributes.Mtime)
  103. out.Ctime = uint64(entry.Attributes.Mtime)
  104. out.Atime = uint64(entry.Attributes.Mtime)
  105. out.Mode = toSyscallMode(os.FileMode(entry.Attributes.FileMode))
  106. if entry.HardLinkCounter > 0 {
  107. out.Nlink = uint32(entry.HardLinkCounter)
  108. } else {
  109. out.Nlink = 1
  110. }
  111. out.Uid = entry.Attributes.Uid
  112. out.Gid = entry.Attributes.Gid
  113. }
  114. func (wfs *WFS) setAttrByFilerEntry(out *fuse.Attr, inode uint64, entry *filer.Entry) {
  115. out.Ino = inode
  116. out.Size = entry.FileSize
  117. out.Blocks = (out.Size + blockSize - 1) / blockSize
  118. setBlksize(out, blockSize)
  119. out.Atime = uint64(entry.Attr.Mtime.Unix())
  120. out.Mtime = uint64(entry.Attr.Mtime.Unix())
  121. out.Ctime = uint64(entry.Attr.Mtime.Unix())
  122. out.Mode = toSyscallMode(entry.Attr.Mode)
  123. if entry.HardLinkCounter > 0 {
  124. out.Nlink = uint32(entry.HardLinkCounter)
  125. } else {
  126. out.Nlink = 1
  127. }
  128. out.Uid = entry.Attr.Uid
  129. out.Gid = entry.Attr.Gid
  130. }
  131. func (wfs *WFS) outputPbEntry(out *fuse.EntryOut, inode uint64, entry *filer_pb.Entry) {
  132. out.NodeId = inode
  133. out.Generation = 1
  134. out.EntryValid = 1
  135. out.AttrValid = 1
  136. wfs.setAttrByPbEntry(&out.Attr, inode, entry)
  137. }
  138. func (wfs *WFS) outputFilerEntry(out *fuse.EntryOut, inode uint64, entry *filer.Entry) {
  139. out.NodeId = inode
  140. out.Generation = 1
  141. out.EntryValid = 1
  142. out.AttrValid = 1
  143. wfs.setAttrByFilerEntry(&out.Attr, inode, entry)
  144. }
  145. func chmod(existing uint32, mode uint32) uint32 {
  146. return existing&^07777 | mode&07777
  147. }
  148. func toSyscallMode(mode os.FileMode) uint32 {
  149. return toSyscallType(mode) | uint32(mode)
  150. }
  151. func toSyscallType(mode os.FileMode) uint32 {
  152. switch mode & os.ModeType {
  153. case os.ModeDir:
  154. return syscall.S_IFDIR
  155. case os.ModeSymlink:
  156. return syscall.S_IFLNK
  157. case os.ModeNamedPipe:
  158. return syscall.S_IFIFO
  159. case os.ModeSocket:
  160. return syscall.S_IFSOCK
  161. case os.ModeDevice:
  162. return syscall.S_IFBLK
  163. case os.ModeCharDevice:
  164. return syscall.S_IFCHR
  165. default:
  166. return syscall.S_IFREG
  167. }
  168. }
  169. func toOsFileType(mode uint32) os.FileMode {
  170. switch mode & (syscall.S_IFMT & 0xffff) {
  171. case syscall.S_IFDIR:
  172. return os.ModeDir
  173. case syscall.S_IFLNK:
  174. return os.ModeSymlink
  175. case syscall.S_IFIFO:
  176. return os.ModeNamedPipe
  177. case syscall.S_IFSOCK:
  178. return os.ModeSocket
  179. case syscall.S_IFBLK:
  180. return os.ModeDevice
  181. case syscall.S_IFCHR:
  182. return os.ModeCharDevice
  183. default:
  184. return 0
  185. }
  186. }
  187. func toOsFileMode(mode uint32) os.FileMode {
  188. return toOsFileType(mode) | os.FileMode(mode&07777)
  189. }