cmd/mountlib: convert time.Duration option to fs.Duration

This commit is contained in:
Nick Craig-Wood 2024-07-02 10:26:15 +01:00
parent 7c51b10d15
commit 2c57fe9826
8 changed files with 34 additions and 25 deletions

View File

@ -30,7 +30,7 @@ var _ fusefs.Node = (*Dir)(nil)
// Attr updates the attributes of a directory // Attr updates the attributes of a directory
func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) (err error) { func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) (err error) {
defer log.Trace(d, "")("attr=%+v, err=%v", a, &err) defer log.Trace(d, "")("attr=%+v, err=%v", a, &err)
a.Valid = d.fsys.opt.AttrTimeout a.Valid = time.Duration(d.fsys.opt.AttrTimeout)
a.Gid = d.VFS().Opt.GID a.Gid = d.VFS().Opt.GID
a.Uid = d.VFS().Opt.UID a.Uid = d.VFS().Opt.UID
a.Mode = os.ModeDir | d.VFS().Opt.DirPerms a.Mode = os.ModeDir | d.VFS().Opt.DirPerms
@ -77,7 +77,7 @@ func (d *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.Lo
if err != nil { if err != nil {
return nil, translateError(err) return nil, translateError(err)
} }
resp.EntryValid = d.fsys.opt.AttrTimeout resp.EntryValid = time.Duration(d.fsys.opt.AttrTimeout)
// Check the mnode to see if it has a fuse Node cached // Check the mnode to see if it has a fuse Node cached
// We must return the same fuse nodes for vfs Nodes // We must return the same fuse nodes for vfs Nodes
node, ok := mnode.Sys().(fusefs.Node) node, ok := mnode.Sys().(fusefs.Node)

View File

@ -25,7 +25,7 @@ var _ fusefs.Node = (*File)(nil)
// Attr fills out the attributes for the file // Attr fills out the attributes for the file
func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) { func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) {
defer log.Trace(f, "")("a=%+v, err=%v", a, &err) defer log.Trace(f, "")("a=%+v, err=%v", a, &err)
a.Valid = f.fsys.opt.AttrTimeout a.Valid = time.Duration(f.fsys.opt.AttrTimeout)
modTime := f.File.ModTime() modTime := f.File.ModTime()
Size := uint64(f.File.Size()) Size := uint64(f.File.Size())
Blocks := (Size + 511) / 512 Blocks := (Size + 511) / 512

View File

@ -6,6 +6,7 @@ package mount
import ( import (
"fmt" "fmt"
"runtime" "runtime"
"time"
"bazil.org/fuse" "bazil.org/fuse"
fusefs "bazil.org/fuse/fs" fusefs "bazil.org/fuse/fs"
@ -50,7 +51,7 @@ func mountOptions(VFS *vfs.VFS, device string, opt *mountlib.Options) (options [
options = append(options, fuse.WritebackCache()) options = append(options, fuse.WritebackCache())
} }
if opt.DaemonTimeout != 0 { if opt.DaemonTimeout != 0 {
options = append(options, fuse.DaemonTimeout(fmt.Sprint(int(opt.DaemonTimeout.Seconds())))) options = append(options, fuse.DaemonTimeout(fmt.Sprint(int(time.Duration(opt.DaemonTimeout).Seconds()))))
} }
if len(opt.ExtraOptions) > 0 { if len(opt.ExtraOptions) > 0 {
fs.Errorf(nil, "-o/--option not supported with this FUSE backend") fs.Errorf(nil, "-o/--option not supported with this FUSE backend")

View File

@ -7,6 +7,7 @@ package mount2
import ( import (
"os" "os"
"syscall" "syscall"
"time"
"github.com/hanwen/go-fuse/v2/fuse" "github.com/hanwen/go-fuse/v2/fuse"
"github.com/rclone/rclone/cmd/mountlib" "github.com/rclone/rclone/cmd/mountlib"
@ -88,14 +89,14 @@ func setAttr(node vfs.Node, attr *fuse.Attr) {
// fill in AttrOut from node // fill in AttrOut from node
func (f *FS) setAttrOut(node vfs.Node, out *fuse.AttrOut) { func (f *FS) setAttrOut(node vfs.Node, out *fuse.AttrOut) {
setAttr(node, &out.Attr) setAttr(node, &out.Attr)
out.SetTimeout(f.opt.AttrTimeout) out.SetTimeout(time.Duration(f.opt.AttrTimeout))
} }
// fill in EntryOut from node // fill in EntryOut from node
func (f *FS) setEntryOut(node vfs.Node, out *fuse.EntryOut) { func (f *FS) setEntryOut(node vfs.Node, out *fuse.EntryOut) {
setAttr(node, &out.Attr) setAttr(node, &out.Attr)
out.SetEntryTimeout(f.opt.AttrTimeout) out.SetEntryTimeout(time.Duration(f.opt.AttrTimeout))
out.SetAttrTimeout(f.opt.AttrTimeout) out.SetAttrTimeout(time.Duration(f.opt.AttrTimeout))
} }
// Translate errors from mountlib into Syscall error numbers // Translate errors from mountlib into Syscall error numbers

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"log" "log"
"runtime" "runtime"
"time"
fusefs "github.com/hanwen/go-fuse/v2/fs" fusefs "github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse" "github.com/hanwen/go-fuse/v2/fuse"
@ -215,8 +216,8 @@ func mount(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (<-chan error
// FIXME fill out // FIXME fill out
opts := fusefs.Options{ opts := fusefs.Options{
MountOptions: *mountOpts, MountOptions: *mountOpts,
EntryTimeout: &opt.AttrTimeout, EntryTimeout: (*time.Duration)(&opt.AttrTimeout),
AttrTimeout: &opt.AttrTimeout, AttrTimeout: (*time.Duration)(&opt.AttrTimeout),
GID: VFS.Opt.GID, GID: VFS.Opt.GID,
UID: VFS.Opt.UID, UID: VFS.Opt.UID,
} }

View File

@ -45,16 +45,16 @@ type Options struct {
DefaultPermissions bool DefaultPermissions bool
WritebackCache bool WritebackCache bool
Daemon bool Daemon bool
DaemonWait time.Duration // time to wait for ready mount from daemon, maximum on Linux or constant on macOS/BSD DaemonWait fs.Duration // time to wait for ready mount from daemon, maximum on Linux or constant on macOS/BSD
MaxReadAhead fs.SizeSuffix MaxReadAhead fs.SizeSuffix
ExtraOptions []string ExtraOptions []string
ExtraFlags []string ExtraFlags []string
AttrTimeout time.Duration // how long the kernel caches attribute for AttrTimeout fs.Duration // how long the kernel caches attribute for
DeviceName string DeviceName string
VolumeName string VolumeName string
NoAppleDouble bool NoAppleDouble bool
NoAppleXattr bool NoAppleXattr bool
DaemonTimeout time.Duration // OSXFUSE only DaemonTimeout fs.Duration // OSXFUSE only
AsyncRead bool AsyncRead bool
NetworkMode bool // Windows only NetworkMode bool // Windows only
DirectIO bool // use Direct IO for file access DirectIO bool // use Direct IO for file access
@ -64,10 +64,10 @@ type Options struct {
// DefaultOpt is the default values for creating the mount // DefaultOpt is the default values for creating the mount
var DefaultOpt = Options{ var DefaultOpt = Options{
MaxReadAhead: 128 * 1024, MaxReadAhead: 128 * 1024,
AttrTimeout: 1 * time.Second, // how long the kernel caches attribute for AttrTimeout: fs.Duration(1 * time.Second), // how long the kernel caches attribute for
NoAppleDouble: true, // use noappledouble by default NoAppleDouble: true, // use noappledouble by default
NoAppleXattr: false, // do not use noapplexattr by default NoAppleXattr: false, // do not use noapplexattr by default
AsyncRead: true, // do async reads by default AsyncRead: true, // do async reads by default
} }
type ( type (
@ -111,18 +111,18 @@ func init() {
case "darwin": case "darwin":
// DaemonTimeout defaults to non-zero for macOS // DaemonTimeout defaults to non-zero for macOS
// (this is a macOS specific kernel option unrelated to DaemonWait) // (this is a macOS specific kernel option unrelated to DaemonWait)
DefaultOpt.DaemonTimeout = 10 * time.Minute DefaultOpt.DaemonTimeout = fs.Duration(10 * time.Minute)
} }
switch runtime.GOOS { switch runtime.GOOS {
case "linux": case "linux":
// Linux provides /proc/mounts to check mount status // Linux provides /proc/mounts to check mount status
// so --daemon-wait means *maximum* time to wait // so --daemon-wait means *maximum* time to wait
DefaultOpt.DaemonWait = 60 * time.Second DefaultOpt.DaemonWait = fs.Duration(60 * time.Second)
case "darwin", "openbsd", "freebsd", "netbsd": case "darwin", "openbsd", "freebsd", "netbsd":
// On BSD we can't check mount status yet // On BSD we can't check mount status yet
// so --daemon-wait is just a *constant* delay // so --daemon-wait is just a *constant* delay
DefaultOpt.DaemonWait = 5 * time.Second DefaultOpt.DaemonWait = fs.Duration(5 * time.Second)
} }
// Opt must be assigned in the init block to ensure changes really get in // Opt must be assigned in the init block to ensure changes really get in
@ -136,12 +136,12 @@ var Opt Options
func AddFlags(flagSet *pflag.FlagSet) { func AddFlags(flagSet *pflag.FlagSet) {
rc.AddOption("mount", &Opt) rc.AddOption("mount", &Opt)
flags.BoolVarP(flagSet, &Opt.DebugFUSE, "debug-fuse", "", Opt.DebugFUSE, "Debug the FUSE internals - needs -v", "Mount") flags.BoolVarP(flagSet, &Opt.DebugFUSE, "debug-fuse", "", Opt.DebugFUSE, "Debug the FUSE internals - needs -v", "Mount")
flags.DurationVarP(flagSet, &Opt.AttrTimeout, "attr-timeout", "", Opt.AttrTimeout, "Time for which file/directory attributes are cached", "Mount") flags.FVarP(flagSet, &Opt.AttrTimeout, "attr-timeout", "", "Time for which file/directory attributes are cached", "Mount")
flags.StringArrayVarP(flagSet, &Opt.ExtraOptions, "option", "o", []string{}, "Option for libfuse/WinFsp (repeat if required)", "Mount") flags.StringArrayVarP(flagSet, &Opt.ExtraOptions, "option", "o", []string{}, "Option for libfuse/WinFsp (repeat if required)", "Mount")
flags.StringArrayVarP(flagSet, &Opt.ExtraFlags, "fuse-flag", "", []string{}, "Flags or arguments to be passed direct to libfuse/WinFsp (repeat if required)", "Mount") flags.StringArrayVarP(flagSet, &Opt.ExtraFlags, "fuse-flag", "", []string{}, "Flags or arguments to be passed direct to libfuse/WinFsp (repeat if required)", "Mount")
// Non-Windows only // Non-Windows only
flags.BoolVarP(flagSet, &Opt.Daemon, "daemon", "", Opt.Daemon, "Run mount in background and exit parent process (as background output is suppressed, use --log-file with --log-format=pid,... to monitor) (not supported on Windows)", "Mount") flags.BoolVarP(flagSet, &Opt.Daemon, "daemon", "", Opt.Daemon, "Run mount in background and exit parent process (as background output is suppressed, use --log-file with --log-format=pid,... to monitor) (not supported on Windows)", "Mount")
flags.DurationVarP(flagSet, &Opt.DaemonTimeout, "daemon-timeout", "", Opt.DaemonTimeout, "Time limit for rclone to respond to kernel (not supported on Windows)", "Mount") flags.FVarP(flagSet, &Opt.DaemonTimeout, "daemon-timeout", "", "Time limit for rclone to respond to kernel (not supported on Windows)", "Mount")
flags.BoolVarP(flagSet, &Opt.DefaultPermissions, "default-permissions", "", Opt.DefaultPermissions, "Makes kernel enforce access control based on the file mode (not supported on Windows)", "Mount") flags.BoolVarP(flagSet, &Opt.DefaultPermissions, "default-permissions", "", Opt.DefaultPermissions, "Makes kernel enforce access control based on the file mode (not supported on Windows)", "Mount")
flags.BoolVarP(flagSet, &Opt.AllowNonEmpty, "allow-non-empty", "", Opt.AllowNonEmpty, "Allow mounting over a non-empty directory (not supported on Windows)", "Mount") flags.BoolVarP(flagSet, &Opt.AllowNonEmpty, "allow-non-empty", "", Opt.AllowNonEmpty, "Allow mounting over a non-empty directory (not supported on Windows)", "Mount")
flags.BoolVarP(flagSet, &Opt.AllowRoot, "allow-root", "", Opt.AllowRoot, "Allow access to root user (not supported on Windows)", "Mount") flags.BoolVarP(flagSet, &Opt.AllowRoot, "allow-root", "", Opt.AllowRoot, "Allow access to root user (not supported on Windows)", "Mount")
@ -160,7 +160,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
// Windows only // Windows only
flags.BoolVarP(flagSet, &Opt.NetworkMode, "network-mode", "", Opt.NetworkMode, "Mount as remote network drive, instead of fixed disk drive (supported on Windows only)", "Mount") flags.BoolVarP(flagSet, &Opt.NetworkMode, "network-mode", "", Opt.NetworkMode, "Mount as remote network drive, instead of fixed disk drive (supported on Windows only)", "Mount")
// Unix only // Unix only
flags.DurationVarP(flagSet, &Opt.DaemonWait, "daemon-wait", "", Opt.DaemonWait, "Time to wait for ready mount from daemon (maximum time on Linux, constant sleep time on OSX/BSD) (not supported on Windows)", "Mount") flags.FVarP(flagSet, &Opt.DaemonWait, "daemon-wait", "", "Time to wait for ready mount from daemon (maximum time on Linux, constant sleep time on OSX/BSD) (not supported on Windows)", "Mount")
} }
const ( const (
@ -258,7 +258,7 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm
handle := atexit.Register(func() { handle := atexit.Register(func() {
killDaemon("Got interrupt") killDaemon("Got interrupt")
}) })
err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait, mountDaemon) err = WaitMountReady(mnt.MountPoint, time.Duration(Opt.DaemonWait), mountDaemon)
if err != nil { if err != nil {
killDaemon("Daemon timed out") killDaemon("Daemon timed out")
} }

View File

@ -185,7 +185,7 @@ func getMountOption(mntOpt *mountlib.Options, opt rc.Params, key string) (ok boo
case "debug-fuse": case "debug-fuse":
mntOpt.DebugFUSE, err = opt.GetBool(key) mntOpt.DebugFUSE, err = opt.GetBool(key)
case "attr-timeout": case "attr-timeout":
mntOpt.AttrTimeout, err = opt.GetDuration(key) mntOpt.AttrTimeout, err = opt.GetFsDuration(key)
case "option": case "option":
mntOpt.ExtraOptions, err = getStringArray(opt, key) mntOpt.ExtraOptions, err = getStringArray(opt, key)
case "fuse-flag": case "fuse-flag":
@ -193,7 +193,7 @@ func getMountOption(mntOpt *mountlib.Options, opt rc.Params, key string) (ok boo
case "daemon": case "daemon":
mntOpt.Daemon, err = opt.GetBool(key) mntOpt.Daemon, err = opt.GetBool(key)
case "daemon-timeout": case "daemon-timeout":
mntOpt.DaemonTimeout, err = opt.GetDuration(key) mntOpt.DaemonTimeout, err = opt.GetFsDuration(key)
case "default-permissions": case "default-permissions":
mntOpt.DefaultPermissions, err = opt.GetBool(key) mntOpt.DefaultPermissions, err = opt.GetBool(key)
case "allow-non-empty": case "allow-non-empty":

View File

@ -283,6 +283,12 @@ func (p Params) GetDuration(key string) (time.Duration, error) {
return duration, nil return duration, nil
} }
// GetFsDuration get the duration parameters from in
func (p Params) GetFsDuration(key string) (fs.Duration, error) {
d, err := p.GetDuration(key)
return fs.Duration(d), err
}
// Error creates the standard response for an errored rc call using an // Error creates the standard response for an errored rc call using an
// rc.Param from a path, input Params, error and a suggested HTTP // rc.Param from a path, input Params, error and a suggested HTTP
// response code. // response code.