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.

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