Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support time_gran and max_pages fuse options #239

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions fuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,17 @@ func initMount(c *Conn, conf *mountConfig) error {
}
c.proto = proto

timeGran := uint32(1)
if conf.timeGran > 0 {
timeGran = conf.timeGran
}

s := &InitResponse{
Library: proto,
MaxReadahead: conf.maxReadahead,
MaxWrite: maxWrite,
TimeGran: timeGran,
MaxPages: maxPages,
Flags: InitBigWrites | conf.initFlags,
}
r.Respond(s)
Expand Down Expand Up @@ -1249,10 +1256,14 @@ type InitResponse struct {
// Maximum size of a single write operation.
// Linux enforces a minimum of 4 KiB.
MaxWrite uint32
// Filesystem timestamp granularity in nanoseconds.
TimeGran uint32
// Max pages of a single FUSE message.
MaxPages uint16
}

func (r *InitResponse) String() string {
return fmt.Sprintf("Init %v ra=%d fl=%v w=%d", r.Library, r.MaxReadahead, r.Flags, r.MaxWrite)
return fmt.Sprintf("Init %v ra=%d fl=%v w=%d tg=%d pg=%d", r.Library, r.MaxReadahead, r.Flags, r.MaxWrite, r.TimeGran, r.MaxPages)
}

// Respond replies to the request with the given response.
Expand All @@ -1264,13 +1275,24 @@ func (r *InitRequest) Respond(resp *InitResponse) {
out.MaxReadahead = resp.MaxReadahead
out.Flags = uint32(resp.Flags)
out.MaxWrite = resp.MaxWrite
out.TimeGran = resp.TimeGran

if r.Kernel.GE(Protocol{7, 28}) {
out.Flags |= uint32(InitMaxPages)
felixbuenemann marked this conversation as resolved.
Show resolved Hide resolved
out.MaxPages = resp.MaxPages
}

// MaxWrite larger than our receive buffer would just lead to
// errors on large writes.
if out.MaxWrite > maxWrite {
out.MaxWrite = maxWrite
}
r.respond(buf)
if r.Kernel.GE(Protocol{7, 23}) {
r.respond(buf)
} else {
// Trucate header struct for older protocol versions.
r.respond(buf[:24])
}
}

// A StatfsRequest requests information about the mounted file system.
Expand Down
3 changes: 3 additions & 0 deletions fuse_darwin.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package fuse

// Max pages per fuse message.
const maxPages = 32

// Maximum file write size we are prepared to receive from the kernel.
//
// This value has to be >=16MB or OSXFUSE (3.4.0 observed) will
Expand Down
5 changes: 4 additions & 1 deletion fuse_freebsd.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package fuse

// Max pages per fuse message.
const maxPages = 32

// Maximum file write size we are prepared to receive from the kernel.
//
// This number is just a guess.
const maxWrite = 128 * 1024
const maxWrite = maxPages * 4096
21 changes: 19 additions & 2 deletions fuse_kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const (
protoVersionMinMajor = 7
protoVersionMinMinor = 8
protoVersionMaxMajor = 7
protoVersionMaxMinor = 12
protoVersionMaxMinor = 28
)

const (
Expand Down Expand Up @@ -273,6 +273,12 @@ const (
InitAsyncDIO InitFlags = 1 << 15
InitWritebackCache InitFlags = 1 << 16
InitNoOpenSupport InitFlags = 1 << 17
InitParallelDirops InitFlags = 1 << 18
InitHandleKillpriv InitFlags = 1 << 19
InitPosixACL InitFlags = 1 << 20
InitAbortError InitFlags = 1 << 21
InitMaxPages InitFlags = 1 << 22
InitCacheSymlinks InitFlags = 1 << 23

InitCaseSensitive InitFlags = 1 << 29 // OS X only
InitVolRename InitFlags = 1 << 30 // OS X only
Expand Down Expand Up @@ -303,6 +309,12 @@ var initFlagNames = []flagName{
{uint32(InitAsyncDIO), "InitAsyncDIO"},
{uint32(InitWritebackCache), "InitWritebackCache"},
{uint32(InitNoOpenSupport), "InitNoOpenSupport"},
{uint32(InitParallelDirops), "InitParallelDirops"},
{uint32(InitHandleKillpriv), "InitHandleKillpriv"},
{uint32(InitPosixACL), "InitPosixACL"},
{uint32(InitAbortError), "InitAbortError"},
{uint32(InitMaxPages), "InitMaxPages"},
{uint32(InitCacheSymlinks), "InitCacheSymlinks"},

{uint32(InitCaseSensitive), "InitCaseSensitive"},
{uint32(InitVolRename), "InitVolRename"},
Expand Down Expand Up @@ -706,8 +718,13 @@ type initOut struct {
Minor uint32
MaxReadahead uint32
Flags uint32
Unused uint32
_ uint16
_ uint16
MaxWrite uint32
TimeGran uint32
MaxPages uint16
_ uint16
_ [8]uint32
}

type interruptIn struct {
Expand Down
8 changes: 7 additions & 1 deletion fuse_linux.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package fuse

// Max pages per fuse message (FUSE_MAX_MAX_PAGES).
const maxPages = 256

// Maximum file write size we are prepared to receive from the kernel.
//
// Linux 4.2.0 has been observed to cap this value at 128kB
// (FUSE_MAX_PAGES_PER_REQ=32, 4kB pages).
const maxWrite = 128 * 1024
//
// Linux >= 4.20 allows up to FUSE_MAX_MAX_PAGES=256, but defaults to
// FUSE_DEFAULT_MAX_PAGES_PER_REQ=32.
const maxWrite = maxPages * 4096
11 changes: 11 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func dummyOption(conf *mountConfig) error {
type mountConfig struct {
options map[string]string
maxReadahead uint32
timeGran uint32
initFlags InitFlags
osxfuseLocations []OSXFUSEPaths
}
Expand Down Expand Up @@ -231,6 +232,16 @@ func WritebackCache() MountOption {
}
}

// TimeGran sets the granularity of timestamps in nanoseconds.
//
// Default is 1 nanosecond, must be power of 10.
func TimeGran(n uint32) MountOption {
return func(conf *mountConfig) error {
conf.timeGran = n
return nil
}
}

// OSXFUSEPaths describes the paths used by an installed OSXFUSE
// version. See OSXFUSELocationV3 for typical values.
type OSXFUSEPaths struct {
Expand Down