2022-02-14 11:14:34 +08:00
|
|
|
package mount
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/hanwen/go-fuse/v2/fuse"
|
2023-09-22 02:08:26 +08:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
2022-02-14 15:27:11 +08:00
|
|
|
"net/http"
|
2022-03-07 09:04:21 +08:00
|
|
|
"syscall"
|
2023-01-03 15:20:45 +08:00
|
|
|
"time"
|
2022-02-14 11:14:34 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Write data
|
|
|
|
*
|
|
|
|
* Write should return exactly the number of bytes requested
|
|
|
|
* except on error. An exception to this is when the file has
|
|
|
|
* been opened in 'direct_io' mode, in which case the return value
|
|
|
|
* of the write system call will reflect the return value of this
|
|
|
|
* operation.
|
|
|
|
*
|
|
|
|
* Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
|
|
|
|
* expected to reset the setuid and setgid bits.
|
|
|
|
*
|
|
|
|
* fi->fh will contain the value set by the open method, or will
|
|
|
|
* be undefined if the open method didn't set any value.
|
|
|
|
*
|
|
|
|
* Valid replies:
|
|
|
|
* fuse_reply_write
|
|
|
|
* fuse_reply_err
|
|
|
|
*
|
|
|
|
* @param req request handle
|
|
|
|
* @param ino the inode number
|
|
|
|
* @param buf data to write
|
|
|
|
* @param size number of bytes to write
|
|
|
|
* @param off offset to write to
|
|
|
|
* @param fi file information
|
|
|
|
*/
|
|
|
|
func (wfs *WFS) Write(cancel <-chan struct{}, in *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
|
2022-02-14 15:27:11 +08:00
|
|
|
|
2022-03-06 14:10:43 +08:00
|
|
|
if wfs.IsOverQuota {
|
2022-03-07 09:04:21 +08:00
|
|
|
return 0, fuse.Status(syscall.ENOSPC)
|
2022-03-06 14:10:43 +08:00
|
|
|
}
|
|
|
|
|
2022-02-14 15:27:11 +08:00
|
|
|
fh := wfs.GetHandle(FileHandleId(in.Fh))
|
|
|
|
if fh == nil {
|
|
|
|
return 0, fuse.ENOENT
|
|
|
|
}
|
|
|
|
|
2022-03-14 09:17:35 +08:00
|
|
|
fh.dirtyPages.writerPattern.MonitorWriteAt(int64(in.Offset), int(in.Size))
|
|
|
|
|
2023-01-03 15:20:45 +08:00
|
|
|
tsNs := time.Now().UnixNano()
|
|
|
|
|
2023-09-22 02:08:26 +08:00
|
|
|
fhActiveLock := fh.wfs.fhLockTable.AcquireLock("Write", fh.fh, util.ExclusiveLock)
|
|
|
|
defer fh.wfs.fhLockTable.ReleaseLock(fh.fh, fhActiveLock)
|
2022-02-14 15:27:11 +08:00
|
|
|
|
2022-12-05 15:33:05 +08:00
|
|
|
entry := fh.GetEntry()
|
2022-02-14 15:27:11 +08:00
|
|
|
if entry == nil {
|
|
|
|
return 0, fuse.OK
|
|
|
|
}
|
|
|
|
|
|
|
|
entry.Content = nil
|
|
|
|
offset := int64(in.Offset)
|
|
|
|
entry.Attributes.FileSize = uint64(max(offset+int64(len(data)), int64(entry.Attributes.FileSize)))
|
|
|
|
// glog.V(4).Infof("%v write [%d,%d) %d", fh.f.fullpath(), req.Offset, req.Offset+int64(len(req.Data)), len(req.Data))
|
|
|
|
|
2023-01-03 15:20:45 +08:00
|
|
|
fh.dirtyPages.AddPage(offset, data, fh.dirtyPages.writerPattern.IsSequentialMode(), tsNs)
|
2022-02-14 15:27:11 +08:00
|
|
|
|
|
|
|
written = uint32(len(data))
|
|
|
|
|
|
|
|
if offset == 0 {
|
|
|
|
// detect mime type
|
|
|
|
fh.contentType = http.DetectContentType(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fh.dirtyMetadata = true
|
|
|
|
|
2023-01-03 15:20:45 +08:00
|
|
|
if IsDebugFileReadWrite {
|
|
|
|
// print("+")
|
|
|
|
fh.mirrorFile.WriteAt(data, offset)
|
|
|
|
}
|
|
|
|
|
2022-02-14 15:27:11 +08:00
|
|
|
return written, fuse.OK
|
2022-02-14 11:14:34 +08:00
|
|
|
}
|