summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-11-24 22:36:04 +0100
committerJakob Unterwurzacher2016-11-25 09:19:14 +0100
commit0f8d3318a321bf19f92e0872d741266cd0431463 (patch)
tree996edf075751eaa011db27472fd9dd3de2367cd7 /internal
parent024511d9c71558be4b1169d6bb43bd18d65539e0 (diff)
main, fusefrontend: add "-noprealloc" option
Preallocation is very slow on hdds that run btrfs. Give the user the option to disable it. This greatly speeds up small file operations but reduces the robustness against out-of-space errors. Also add the option to the man page. More info: https://github.com/rfjakob/gocryptfs/issues/63
Diffstat (limited to 'internal')
-rw-r--r--internal/fusefrontend/args.go2
-rw-r--r--internal/fusefrontend/file.go30
-rw-r--r--internal/fusefrontend/fs.go4
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.