weedfs_attr.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. entry.Attributes.FileMode = uint32(mode)
  61. }
  62. if uid, ok := input.GetUID(); ok {
  63. entry.Attributes.Uid = uid
  64. }
  65. if gid, ok := input.GetGID(); ok {
  66. entry.Attributes.Gid = gid
  67. }
  68. if mtime, ok := input.GetMTime(); ok {
  69. entry.Attributes.Mtime = mtime.Unix()
  70. }
  71. entry.Attributes.Mtime = time.Now().Unix()
  72. out.AttrValid = 1
  73. wfs.setAttrByPbEntry(&out.Attr, input.NodeId, entry)
  74. if fh != nil {
  75. fh.dirtyMetadata = true
  76. return fuse.OK
  77. }
  78. return wfs.saveEntry(path, entry)
  79. }
  80. func (wfs *WFS) setRootAttr(out *fuse.AttrOut) {
  81. now := uint64(time.Now().Unix())
  82. out.AttrValid = 119
  83. out.Ino = 1
  84. setBlksize(&out.Attr, blockSize)
  85. out.Uid = wfs.option.MountUid
  86. out.Gid = wfs.option.MountGid
  87. out.Mtime = now
  88. out.Ctime = now
  89. out.Atime = now
  90. out.Mode = toSystemType(os.ModeDir) | uint32(wfs.option.MountMode)
  91. out.Nlink = 1
  92. }
  93. func (wfs *WFS) setAttrByPbEntry(out *fuse.Attr, inode uint64, entry *filer_pb.Entry) {
  94. out.Ino = inode
  95. out.Size = filer.FileSize(entry)
  96. out.Blocks = (out.Size + blockSize - 1) / blockSize
  97. setBlksize(out, blockSize)
  98. out.Mtime = uint64(entry.Attributes.Mtime)
  99. out.Ctime = uint64(entry.Attributes.Mtime)
  100. out.Atime = uint64(entry.Attributes.Mtime)
  101. out.Mode = toSystemMode(os.FileMode(entry.Attributes.FileMode))
  102. if entry.HardLinkCounter > 0 {
  103. out.Nlink = uint32(entry.HardLinkCounter)
  104. } else {
  105. out.Nlink = 1
  106. }
  107. out.Uid = entry.Attributes.Uid
  108. out.Gid = entry.Attributes.Gid
  109. }
  110. func (wfs *WFS) setAttrByFilerEntry(out *fuse.Attr, inode uint64, entry *filer.Entry) {
  111. out.Ino = inode
  112. out.Size = entry.FileSize
  113. out.Blocks = (out.Size + blockSize - 1) / blockSize
  114. setBlksize(out, blockSize)
  115. out.Atime = uint64(entry.Attr.Mtime.Unix())
  116. out.Mtime = uint64(entry.Attr.Mtime.Unix())
  117. out.Ctime = uint64(entry.Attr.Mtime.Unix())
  118. out.Crtime_ = uint64(entry.Attr.Crtime.Unix())
  119. out.Mode = toSystemMode(entry.Attr.Mode)
  120. if entry.HardLinkCounter > 0 {
  121. out.Nlink = uint32(entry.HardLinkCounter)
  122. } else {
  123. out.Nlink = 1
  124. }
  125. out.Uid = entry.Attr.Uid
  126. out.Gid = entry.Attr.Gid
  127. }
  128. func (wfs *WFS) outputPbEntry(out *fuse.EntryOut, inode uint64, entry *filer_pb.Entry) {
  129. out.NodeId = inode
  130. out.Generation = 1
  131. out.EntryValid = 1
  132. out.AttrValid = 1
  133. wfs.setAttrByPbEntry(&out.Attr, inode, entry)
  134. }
  135. func (wfs *WFS) outputFilerEntry(out *fuse.EntryOut, inode uint64, entry *filer.Entry) {
  136. out.NodeId = inode
  137. out.Generation = 1
  138. out.EntryValid = 1
  139. out.AttrValid = 1
  140. wfs.setAttrByFilerEntry(&out.Attr, inode, entry)
  141. }
  142. func toSystemMode(mode os.FileMode) uint32 {
  143. return toSystemType(mode) | uint32(mode)
  144. }
  145. func toSystemType(mode os.FileMode) uint32 {
  146. switch mode & os.ModeType {
  147. case os.ModeDir:
  148. return syscall.S_IFDIR
  149. case os.ModeSymlink:
  150. return syscall.S_IFLNK
  151. case os.ModeNamedPipe:
  152. return syscall.S_IFIFO
  153. case os.ModeSocket:
  154. return syscall.S_IFSOCK
  155. case os.ModeDevice:
  156. return syscall.S_IFBLK
  157. case os.ModeCharDevice:
  158. return syscall.S_IFCHR
  159. default:
  160. return syscall.S_IFREG
  161. }
  162. }
  163. func toFileType(mode uint32) os.FileMode {
  164. switch mode & (syscall.S_IFMT & 0xffff) {
  165. case syscall.S_IFDIR:
  166. return os.ModeDir
  167. case syscall.S_IFLNK:
  168. return os.ModeSymlink
  169. case syscall.S_IFIFO:
  170. return os.ModeNamedPipe
  171. case syscall.S_IFSOCK:
  172. return os.ModeSocket
  173. case syscall.S_IFBLK:
  174. return os.ModeDevice
  175. case syscall.S_IFCHR:
  176. return os.ModeCharDevice
  177. default:
  178. return 0
  179. }
  180. }
  181. func toFileMode(mode uint32) os.FileMode {
  182. return toFileType(mode) | os.FileMode(mode&07777)
  183. }