diff options
Diffstat (limited to 'internal/fusefrontend')
-rw-r--r-- | internal/fusefrontend/args.go | 2 | ||||
-rw-r--r-- | internal/fusefrontend/file.go | 30 | ||||
-rw-r--r-- | internal/fusefrontend/fs.go | 4 |
3 files changed, 23 insertions, 13 deletions
diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index d8b0304..eb796cd 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -21,4 +21,6 @@ type Args struct { // Raw64 is true when RawURLEncoding (without padding) should be used for // file names Raw64 bool + // NoPrealloc disables automatic preallocation before writing + NoPrealloc bool } diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index d637528..5fe866b 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -49,10 +49,12 @@ type file struct { // The opCount is used to judge whether "lastWrittenOffset" is still // guaranteed to be correct. lastOpCount uint64 + // Parent filesystem + fs *FS } // NewFile returns a new go-fuse File instance. -func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (nodefs.File, fuse.Status) { +func NewFile(fd *os.File, writeOnly bool, fs *FS) (nodefs.File, fuse.Status) { var st syscall.Stat_t err := syscall.Fstat(int(fd.Fd()), &st) if err != nil { @@ -65,10 +67,11 @@ func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (no return &file{ fd: fd, writeOnly: writeOnly, - contentEnc: contentEnc, + contentEnc: fs.contentEnc, devIno: di, fileTableEntry: t, loopbackFile: nodefs.NewLoopbackFile(fd), + fs: fs, }, fuse.OK } @@ -107,10 +110,12 @@ func (f *file) createHeader() (fileID []byte, err error) { h := contentenc.RandomHeader() buf := h.Pack() // Prevent partially written (=corrupt) header by preallocating the space beforehand - err = syscallcompat.EnospcPrealloc(int(f.fd.Fd()), 0, contentenc.HeaderLen) - if err != nil { - tlog.Warn.Printf("ino%d: createHeader: prealloc failed: %s\n", f.devIno.ino, err.Error()) - return nil, err + if !f.fs.args.NoPrealloc { + err = syscallcompat.EnospcPrealloc(int(f.fd.Fd()), 0, contentenc.HeaderLen) + if err != nil { + tlog.Warn.Printf("ino%d: createHeader: prealloc failed: %s\n", f.devIno.ino, err.Error()) + return nil, err + } } // Actually write header _, err = f.fd.WriteAt(buf, 0) @@ -285,7 +290,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) { writeChain[i] = blockData numOutBytes += len(blockData) } - // Concatenenate all elements in the writeChain into one contigous buffer + // Concatenenate all elements in the writeChain into one contiguous buffer tmp := make([]byte, numOutBytes) writeBuf := bytes.NewBuffer(tmp[:0]) for _, w := range writeChain { @@ -293,11 +298,14 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) { } // Preallocate so we cannot run out of space in the middle of the write. // This prevents partially written (=corrupt) blocks. + var err error cOff := blocks[0].BlockCipherOff() - err := syscallcompat.EnospcPrealloc(int(f.fd.Fd()), int64(cOff), int64(writeBuf.Len())) - if err != nil { - tlog.Warn.Printf("ino%d fh%d: doWrite: prealloc failed: %s", f.devIno.ino, f.intFd(), err.Error()) - return 0, fuse.ToStatus(err) + if !f.fs.args.NoPrealloc { + err = syscallcompat.EnospcPrealloc(int(f.fd.Fd()), int64(cOff), int64(writeBuf.Len())) + if err != nil { + tlog.Warn.Printf("ino%d fh%d: doWrite: prealloc failed: %s", f.devIno.ino, f.intFd(), err.Error()) + return 0, fuse.ToStatus(err) + } } // Write _, err = f.fd.WriteAt(writeBuf.Bytes(), int64(cOff)) diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index e9e6113..f41e9a7 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -106,7 +106,7 @@ func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile n return nil, fuse.ToStatus(err) } - return NewFile(f, writeOnly, fs.contentEnc) + return NewFile(f, writeOnly, fs) } // Create implements pathfs.Filesystem. @@ -160,7 +160,7 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte tlog.Warn.Printf("Create: Chown failed: %v", err) } } - return NewFile(fd, writeOnly, fs.contentEnc) + return NewFile(fd, writeOnly, fs) } // Chmod implements pathfs.Filesystem. |