Skip to content

Commit

Permalink
Replace FUSE's direct_mount option with mount_method
Browse files Browse the repository at this point in the history
When enabling direct_mount, go-fuse attempts to create a FUSE mount
directly, using the mount(2) system call. If that fails, it falls back
to using the fusermount utility. What's annoying is that this causes any
errors returned by mount(2) to be suppressed. go-fuse solved this by
adding a DirectMountStrict option, which disables the fallback
behaviour.

This change exposes go-fuse's DirectMountStrict feature. Instead of
adding a separate boolean flag for it, we promote the existing
direct_mount configuration option to an enumeration named mount_method.
This means that if your configuration previously contained:

    directMount: true,

You need to replace it with either one of the lines below, depending on
whether you want to still fall back to calling fusermount:

    mountMethod: 'DIRECT',
    mountMethod: 'DIRECT_AND_FUSERMOUNT',

Fixes: #156
  • Loading branch information
sfc-gh-guwang authored and EdSchouten committed Dec 15, 2024
1 parent b7b3bc4 commit d03d5e3
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 156 deletions.
53 changes: 35 additions & 18 deletions pkg/filesystem/virtual/configuration/fuse_mount_enabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import (

"github.com/buildbarn/bb-remote-execution/pkg/filesystem/virtual"
"github.com/buildbarn/bb-remote-execution/pkg/filesystem/virtual/fuse"
pb "github.com/buildbarn/bb-remote-execution/pkg/proto/configuration/filesystem/virtual"
"github.com/buildbarn/bb-storage/pkg/clock"
"github.com/buildbarn/bb-storage/pkg/filesystem"
"github.com/buildbarn/bb-storage/pkg/program"
"github.com/buildbarn/bb-storage/pkg/util"
go_fuse "github.com/hanwen/go-fuse/v2/fuse"
"github.com/jmespath/go-jmespath"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (m *fuseMount) Expose(terminationGroup program.Group, rootDirectory virtual.Directory) error {
Expand Down Expand Up @@ -45,6 +49,35 @@ func (m *fuseMount) Expose(terminationGroup program.Group, rootDirectory virtual
// Launch the FUSE server.
removeStaleMounts(m.mountPath)
deterministicTimestamp := uint64(filesystem.DeterministicFileModificationTimestamp.Unix())
mountOptions := &go_fuse.MountOptions{
// The name isn't strictly necessary, but is
// filled in to prevent runc from crashing with
// this error:
// https://github.com/opencontainers/runc/blob/v1.0.0-rc10/libcontainer/mount/mount_linux.go#L69
//
// Newer versions of runc use an improved parser
// that's more reliable:
// https://github.com/moby/sys/blob/master/mountinfo/mountinfo_linux.go
FsName: m.fsName,
AllowOther: m.configuration.AllowOther,
// Speed up workloads that perform many tiny
// writes. This means data is only guaranteed to
// make it into the virtual file system after
// calling close()/fsync()/munmap()/msync().
EnableWritebackCache: true,
}

switch m.configuration.MountMethod {
case pb.FUSEMountConfiguration_FUSERMOUNT:
// go-fuse uses fusermount by default.
case pb.FUSEMountConfiguration_DIRECT:
mountOptions.DirectMountStrict = true
case pb.FUSEMountConfiguration_DIRECT_AND_FUSERMOUNT:
mountOptions.DirectMount = true
default:
return status.Error(codes.InvalidArgument, "Invalid mount method")
}

server, err := go_fuse.NewServer(
fuse.NewMetricsRawFileSystem(
fuse.NewDefaultAttributesInjectingRawFileSystem(
Expand All @@ -61,24 +94,8 @@ func (m *fuseMount) Expose(terminationGroup program.Group, rootDirectory virtual
}),
clock.SystemClock),
m.mountPath,
&go_fuse.MountOptions{
// The name isn't strictly necessary, but is
// filled in to prevent runc from crashing with
// this error:
// https://github.com/opencontainers/runc/blob/v1.0.0-rc10/libcontainer/mount/mount_linux.go#L69
//
// Newer versions of runc use an improved parser
// that's more reliable:
// https://github.com/moby/sys/blob/master/mountinfo/mountinfo_linux.go
FsName: m.fsName,
AllowOther: m.configuration.AllowOther,
DirectMount: m.configuration.DirectMount,
// Speed up workloads that perform many tiny
// writes. This means data is only guaranteed to
// make it into the virtual file system after
// calling close()/fsync()/munmap()/msync().
EnableWritebackCache: true,
})
mountOptions,
)
if err != nil {
return util.StatusWrap(err, "Failed to create FUSE server")
}
Expand Down
Loading

0 comments on commit d03d5e3

Please sign in to comment.