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.

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