weedfs_file_write.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package mount
  2. import (
  3. "github.com/hanwen/go-fuse/v2/fuse"
  4. "github.com/seaweedfs/seaweedfs/weed/util"
  5. "net/http"
  6. "syscall"
  7. "time"
  8. )
  9. /**
  10. * Write data
  11. *
  12. * Write should return exactly the number of bytes requested
  13. * except on error. An exception to this is when the file has
  14. * been opened in 'direct_io' mode, in which case the return value
  15. * of the write system call will reflect the return value of this
  16. * operation.
  17. *
  18. * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
  19. * expected to reset the setuid and setgid bits.
  20. *
  21. * fi->fh will contain the value set by the open method, or will
  22. * be undefined if the open method didn't set any value.
  23. *
  24. * Valid replies:
  25. * fuse_reply_write
  26. * fuse_reply_err
  27. *
  28. * @param req request handle
  29. * @param ino the inode number
  30. * @param buf data to write
  31. * @param size number of bytes to write
  32. * @param off offset to write to
  33. * @param fi file information
  34. */
  35. func (wfs *WFS) Write(cancel <-chan struct{}, in *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
  36. if wfs.IsOverQuota {
  37. return 0, fuse.Status(syscall.ENOSPC)
  38. }
  39. fh := wfs.GetHandle(FileHandleId(in.Fh))
  40. if fh == nil {
  41. return 0, fuse.ENOENT
  42. }
  43. fh.dirtyPages.writerPattern.MonitorWriteAt(int64(in.Offset), int(in.Size))
  44. tsNs := time.Now().UnixNano()
  45. fhActiveLock := fh.wfs.fhLockTable.AcquireLock("Write", fh.fh, util.ExclusiveLock)
  46. defer fh.wfs.fhLockTable.ReleaseLock(fh.fh, fhActiveLock)
  47. entry := fh.GetEntry()
  48. if entry == nil {
  49. return 0, fuse.OK
  50. }
  51. entry.Content = nil
  52. offset := int64(in.Offset)
  53. entry.Attributes.FileSize = uint64(max(offset+int64(len(data)), int64(entry.Attributes.FileSize)))
  54. // glog.V(4).Infof("%v write [%d,%d) %d", fh.f.fullpath(), req.Offset, req.Offset+int64(len(req.Data)), len(req.Data))
  55. fh.dirtyPages.AddPage(offset, data, fh.dirtyPages.writerPattern.IsSequentialMode(), tsNs)
  56. written = uint32(len(data))
  57. if offset == 0 {
  58. // detect mime type
  59. fh.contentType = http.DetectContentType(data)
  60. }
  61. fh.dirtyMetadata = true
  62. if IsDebugFileReadWrite {
  63. // print("+")
  64. fh.mirrorFile.WriteAt(data, offset)
  65. }
  66. return written, fuse.OK
  67. }