mount,cmount,mount2: add --direct-io flag to force uncached access

This change adds the --direct-io flag to the mount. This means the
page cache is completely bypassed for reads and writes. No read-ahead
takes place. Shared mmap is disabled.

This is useful to accurately read files which may change length
frequently on the source.
This commit is contained in:
Nick Craig-Wood 2024-03-04 11:37:18 +00:00
parent f3f743c3f9
commit a67688dcc7
5 changed files with 15 additions and 2 deletions

View File

@ -27,6 +27,7 @@ const fhUnset = ^uint64(0)
type FS struct { type FS struct {
VFS *vfs.VFS VFS *vfs.VFS
f fs.Fs f fs.Fs
opt *mountlib.Options
ready chan (struct{}) ready chan (struct{})
mu sync.Mutex // to protect the below mu sync.Mutex // to protect the below
handles []vfs.Handle handles []vfs.Handle
@ -34,10 +35,11 @@ type FS struct {
} }
// NewFS makes a new FS // NewFS makes a new FS
func NewFS(VFS *vfs.VFS) *FS { func NewFS(VFS *vfs.VFS, opt *mountlib.Options) *FS {
fsys := &FS{ fsys := &FS{
VFS: VFS, VFS: VFS,
f: VFS.Fs(), f: VFS.Fs(),
opt: opt,
ready: make(chan (struct{})), ready: make(chan (struct{})),
} }
return fsys return fsys
@ -309,6 +311,9 @@ func (fsys *FS) OpenEx(path string, fi *fuse.FileInfo_t) (errc int) {
if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 { if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 {
fi.DirectIo = true fi.DirectIo = true
} }
if fsys.opt.DirectIO {
fi.DirectIo = true
}
fi.Fh = fsys.openHandle(handle) fi.Fh = fsys.openHandle(handle)
return 0 return 0

View File

@ -149,7 +149,7 @@ func mount(VFS *vfs.VFS, mountPath string, opt *mountlib.Options) (<-chan error,
fs.Debugf(nil, "Mounting on %q (%q)", mountpoint, opt.VolumeName) fs.Debugf(nil, "Mounting on %q (%q)", mountpoint, opt.VolumeName)
// Create underlying FS // Create underlying FS
fsys := NewFS(VFS) fsys := NewFS(VFS, opt)
host := fuse.NewFileSystemHost(fsys) host := fuse.NewFileSystemHost(fsys)
host.SetCapReaddirPlus(true) // only works on Windows host.SetCapReaddirPlus(true) // only works on Windows
if opt.CaseInsensitive.Valid { if opt.CaseInsensitive.Valid {

View File

@ -78,6 +78,9 @@ func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenR
if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 { if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 {
resp.Flags |= fuse.OpenDirectIO resp.Flags |= fuse.OpenDirectIO
} }
if f.fsys.opt.DirectIO {
resp.Flags |= fuse.OpenDirectIO
}
return &FileHandle{handle}, nil return &FileHandle{handle}, nil
} }

View File

@ -158,6 +158,9 @@ func (n *Node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fu
if entry := n.node.DirEntry(); entry != nil && entry.Size() < 0 { if entry := n.node.DirEntry(); entry != nil && entry.Size() < 0 {
fuseFlags |= fuse.FOPEN_DIRECT_IO fuseFlags |= fuse.FOPEN_DIRECT_IO
} }
if n.fsys.opt.DirectIO {
fuseFlags |= fuse.FOPEN_DIRECT_IO
}
return newFileHandle(handle, n.fsys), fuseFlags, 0 return newFileHandle(handle, n.fsys), fuseFlags, 0
} }

View File

@ -52,6 +52,7 @@ type Options struct {
DaemonTimeout time.Duration // OSXFUSE only DaemonTimeout time.Duration // OSXFUSE only
AsyncRead bool AsyncRead bool
NetworkMode bool // Windows only NetworkMode bool // Windows only
DirectIO bool // use Direct IO for file access
CaseInsensitive fs.Tristate CaseInsensitive fs.Tristate
} }
@ -145,6 +146,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
flags.BoolVarP(flagSet, &Opt.WritebackCache, "write-back-cache", "", Opt.WritebackCache, "Makes kernel buffer writes before sending them to rclone (without this, writethrough caching is used) (not supported on Windows)", "Mount") flags.BoolVarP(flagSet, &Opt.WritebackCache, "write-back-cache", "", Opt.WritebackCache, "Makes kernel buffer writes before sending them to rclone (without this, writethrough caching is used) (not supported on Windows)", "Mount")
flags.StringVarP(flagSet, &Opt.DeviceName, "devname", "", Opt.DeviceName, "Set the device name - default is remote:path", "Mount") flags.StringVarP(flagSet, &Opt.DeviceName, "devname", "", Opt.DeviceName, "Set the device name - default is remote:path", "Mount")
flags.FVarP(flagSet, &Opt.CaseInsensitive, "mount-case-insensitive", "", "Tell the OS the mount is case insensitive (true) or sensitive (false) regardless of the backend (auto)", "Mount") flags.FVarP(flagSet, &Opt.CaseInsensitive, "mount-case-insensitive", "", "Tell the OS the mount is case insensitive (true) or sensitive (false) regardless of the backend (auto)", "Mount")
flags.BoolVarP(flagSet, &Opt.DirectIO, "direct-io", "", Opt.DirectIO, "Use Direct IO, disables caching of data", "Mount")
// Windows and OSX // Windows and OSX
flags.StringVarP(flagSet, &Opt.VolumeName, "volname", "", Opt.VolumeName, "Set the volume name (supported on Windows and OSX only)", "Mount") flags.StringVarP(flagSet, &Opt.VolumeName, "volname", "", Opt.VolumeName, "Set the volume name (supported on Windows and OSX only)", "Mount")
// OSX only // OSX only