Skip to content

Commit

Permalink
Added support for Max Pages, which was introduced from Linux Kernel 4.20
Browse files Browse the repository at this point in the history
Signed-off-by: Anagh Kumar Baranwal <[email protected]>
  • Loading branch information
darthShadow committed Feb 13, 2020
1 parent 7b5117f commit 3017a89
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 2 deletions.
18 changes: 17 additions & 1 deletion fuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ func (e *MountpointDoesNotExistError) Error() string {
// progress.
func Mount(dir string, options ...MountOption) (*Conn, error) {
conf := mountConfig{
options: make(map[string]string),
options: make(map[string]string),
maxPages: 32,
}
for _, option := range options {
if err := option(&conf); err != nil {
Expand Down Expand Up @@ -238,10 +239,20 @@ func initMount(c *Conn, conf *mountConfig) error {
MaxWrite: maxWrite,
Flags: InitBigWrites | conf.initFlags,
}

setMaxPages(r, s, conf)

r.Respond(s)
return nil
}

func setMaxPages(request *InitRequest, response *InitResponse, conf *mountConfig) {
if (request.Flags & InitMaxPages) == InitMaxPages {
response.Flags |= InitMaxPages
response.MaxPages = conf.maxPages
}
}

// A Request represents a single FUSE request received from the kernel.
// Use a type switch to determine the specific kind.
// A request of unrecognized type will have concrete type *Header.
Expand Down Expand Up @@ -1249,6 +1260,9 @@ type InitResponse struct {
// Maximum size of a single write operation.
// Linux enforces a minimum of 4 KiB.
MaxWrite uint32
// Maximum number of pages in a single write operation.
// Linux enforces a minimum of 32.
MaxPages uint16
}

func (r *InitResponse) String() string {
Expand All @@ -1264,12 +1278,14 @@ func (r *InitRequest) Respond(resp *InitResponse) {
out.MaxReadahead = resp.MaxReadahead
out.Flags = uint32(resp.Flags)
out.MaxWrite = resp.MaxWrite
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)
}

Expand Down
4 changes: 4 additions & 0 deletions fuse_kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ const (
InitWritebackCache InitFlags = 1 << 16
InitNoOpenSupport InitFlags = 1 << 17

InitMaxPages InitFlags = 1 << 22 // Linux only

InitCaseSensitive InitFlags = 1 << 29 // OS X only
InitVolRename InitFlags = 1 << 30 // OS X only
InitXtimes InitFlags = 1 << 31 // OS X only
Expand Down Expand Up @@ -708,6 +710,8 @@ type initOut struct {
Flags uint32
Unused uint32
MaxWrite uint32
_ uint32 // Unused, refers to TimeGran
MaxPages uint16
}

type interruptIn struct {
Expand Down
4 changes: 3 additions & 1 deletion fuse_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ package fuse
//
// 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
// From Linux 4.20, the cap has been increased to 1MiB
// (FUSE_MAX_PAGES_PER_REQ=256, 4kB pages).
const maxWrite = 1 * 1024 * 1024 // 1 MiB
9 changes: 9 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type mountConfig struct {
maxReadahead uint32
initFlags InitFlags
osxfuseLocations []OSXFUSEPaths
maxPages uint16
}

func escapeComma(s string) string {
Expand Down Expand Up @@ -294,3 +295,11 @@ func AllowNonEmptyMount() MountOption {
return nil
}
}

// EnableMaxPages enables the configuration of the maximum number of pages
// in the request & response from the kernel.
//
// Linux only. Others ignore this option.
func MaxPages(count uint16) MountOption {
return maxPages(count)
}
4 changes: 4 additions & 0 deletions options_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ func noBrowse(conf *mountConfig) error {
conf.options["nobrowse"] = ""
return nil
}

func maxPages(count uint16) MountOption {
return dummyOption
}
4 changes: 4 additions & 0 deletions options_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ func exclCreate(conf *mountConfig) error {
func noBrowse(conf *mountConfig) error {
return nil
}

func maxPages(count uint16) MountOption {
return dummyOption
}
12 changes: 12 additions & 0 deletions options_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,15 @@ func exclCreate(conf *mountConfig) error {
func noBrowse(conf *mountConfig) error {
return nil
}

func maxPages(count uint16) MountOption {
return func(conf *mountConfig) error {
if count < 32 {
count = 32 // The minimum allowed by the kernel
} else if count > 256 {
count = 256 // The maximum allowed by the kernel
}
conf.maxPages = count
return nil
}
}

0 comments on commit 3017a89

Please sign in to comment.