Skip to content

Commit 15a8bb0

Browse files
rfjakobhanwen
authored andcommitted
fuse: add SyncRead flag to MountOptions to ensure in-order reads
We enable FUSE_CAP_ASYNC_READ per default, which means that the kernel can (and does) submit multiple concurrent out-of-order read requests to service userspace reads and kernel readahead. For some backing storages, like Amazon Cloud Drive, out-of-order reads are expensive. gocryptfs has implemented a delay-based workaround with its `-serialize_reads` flag for this case (see rfjakob/gocryptfs#92 for details). Not enabling FUSE_CAP_ASYNC_READ makes the kernel do this for us, as verified by adding debug output to gocryptfs, so expose it as a mount flag in MountOptions. Fixes: #140 Graphs-at: #395 Related: rfjakob/gocryptfs#92 Change-Id: I10f947d71e1453989c4a9b66fbb0407f7163994f
1 parent 0aaef6d commit 15a8bb0

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

fuse/api.go

+17
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ type MountOptions struct {
165165
// The filesystem is fully responsible for invalidating data cache.
166166
ExplicitDataCacheControl bool
167167

168+
// SyncRead is off by default, which means that go-fuse enable the
169+
// FUSE_CAP_ASYNC_READ capability.
170+
// The kernel then submits multiple concurrent reads to service
171+
// userspace requests and kernel readahead.
172+
//
173+
// Setting SyncRead disables the FUSE_CAP_ASYNC_READ capability.
174+
// The kernel then only sends one read request per file handle at a time,
175+
// and orders the requests by offset.
176+
//
177+
// This is useful if reading out of order or concurrently is expensive for
178+
// (example: Amazon Cloud Drive).
179+
//
180+
// See the comment to FUSE_CAP_ASYNC_READ in
181+
// https://github.com/libfuse/libfuse/blob/master/include/fuse_common.h
182+
// for more details.
183+
SyncRead bool
184+
168185
// If set, fuse will first attempt to use syscall.Mount instead of
169186
// fusermount to mount the filesystem. This will not update /etc/mtab
170187
// but might be needed if fusermount is not available.

fuse/opcode.go

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ func doInit(server *Server, req *request) {
9898
if server.opts.EnableAcl {
9999
server.kernelSettings.Flags |= CAP_POSIX_ACL
100100
}
101+
if server.opts.SyncRead {
102+
// Clear CAP_ASYNC_READ
103+
server.kernelSettings.Flags &= ^uint32(CAP_ASYNC_READ)
104+
}
101105

102106
dataCacheMode := input.Flags & CAP_AUTO_INVAL_DATA
103107
if server.opts.ExplicitDataCacheControl {

0 commit comments

Comments
 (0)