Skip to content

Commit

Permalink
fuse: add SyncRead flag to MountOptions to ensure in-order reads
Browse files Browse the repository at this point in the history
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
  • Loading branch information
rfjakob authored and hanwen committed Aug 2, 2021
1 parent 0aaef6d commit 15a8bb0
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
17 changes: 17 additions & 0 deletions fuse/api.go
Expand Up @@ -165,6 +165,23 @@ type MountOptions struct {
// The filesystem is fully responsible for invalidating data cache.
ExplicitDataCacheControl bool

// SyncRead is off by default, which means that go-fuse enable the
// FUSE_CAP_ASYNC_READ capability.
// The kernel then submits multiple concurrent reads to service
// userspace requests and kernel readahead.
//
// Setting SyncRead disables the FUSE_CAP_ASYNC_READ capability.
// The kernel then only sends one read request per file handle at a time,
// and orders the requests by offset.
//
// This is useful if reading out of order or concurrently is expensive for
// (example: Amazon Cloud Drive).
//
// See the comment to FUSE_CAP_ASYNC_READ in
// https://github.com/libfuse/libfuse/blob/master/include/fuse_common.h
// for more details.
SyncRead bool

// If set, fuse will first attempt to use syscall.Mount instead of
// fusermount to mount the filesystem. This will not update /etc/mtab
// but might be needed if fusermount is not available.
Expand Down
4 changes: 4 additions & 0 deletions fuse/opcode.go
Expand Up @@ -98,6 +98,10 @@ func doInit(server *Server, req *request) {
if server.opts.EnableAcl {
server.kernelSettings.Flags |= CAP_POSIX_ACL
}
if server.opts.SyncRead {
// Clear CAP_ASYNC_READ
server.kernelSettings.Flags &= ^uint32(CAP_ASYNC_READ)
}

dataCacheMode := input.Flags & CAP_AUTO_INVAL_DATA
if server.opts.ExplicitDataCacheControl {
Expand Down

0 comments on commit 15a8bb0

Please sign in to comment.